From 98c7b3b525fc2acf562b60607426f6c9e493f55f Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Thu, 23 Jul 2020 22:16:27 +0900 Subject: [PATCH] darwin: Pause the audio when sleeping Updates hajimehoshi/ebiten#1259 --- driver_darwin.go | 16 ++++++++++++ driver_ios.go | 16 ------------ driver_macos.go | 6 ++--- driver_macos.m | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 20 deletions(-) create mode 100644 driver_macos.m diff --git a/driver_darwin.go b/driver_darwin.go index 6fc2d2b..d0fb603 100644 --- a/driver_darwin.go +++ b/driver_darwin.go @@ -21,6 +21,8 @@ package oto // #import // // void oto_render(void* inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer); +// +// void oto_setNotificationHandler(AudioQueueRef audioQueue); import "C" import ( @@ -242,3 +244,17 @@ func (d *driver) Close() error { setDriver(nil) return nil } + +func setNotificationHandler(driver *driver) { + C.oto_setNotificationHandler(driver.audioQueue) +} + +//export oto_setErrorByNotification +func oto_setErrorByNotification(s C.OSStatus, from *C.char) { + if theDriver.err != nil { + return + } + + gofrom := C.GoString(from) + theDriver.err = fmt.Errorf("oto: %s at notification failed: %d", gofrom, s) +} diff --git a/driver_ios.go b/driver_ios.go index 2edefee..2538fec 100644 --- a/driver_ios.go +++ b/driver_ios.go @@ -20,28 +20,12 @@ package oto // #cgo LDFLAGS: -framework Foundation -framework AVFoundation // // #import -// -// void oto_setNotificationHandler(AudioQueueRef audioQueue); import "C" import ( "fmt" ) -func setNotificationHandler(driver *driver) { - C.oto_setNotificationHandler(driver.audioQueue) -} - func componentSubType() C.OSType { return C.kAudioUnitSubType_RemoteIO } - -//export oto_setErrorByNotification -func oto_setErrorByNotification(s C.OSStatus, from *C.char) { - if theDriver.err != nil { - return - } - - gofrom := C.GoString(from) - theDriver.err = fmt.Errorf("oto: %s at notification failed: %d", gofrom, s) -} diff --git a/driver_macos.go b/driver_macos.go index 454c961..ad96e09 100644 --- a/driver_macos.go +++ b/driver_macos.go @@ -17,13 +17,11 @@ package oto +// #cgo LDFLAGS: -framework AppKit +// // #import import "C" -func setNotificationHandler(driver *driver) { - // Do nothing -} - func componentSubType() C.OSType { return C.kAudioUnitSubType_DefaultOutput } diff --git a/driver_macos.m b/driver_macos.m new file mode 100644 index 0000000..3af887c --- /dev/null +++ b/driver_macos.m @@ -0,0 +1,63 @@ +// Copyright 2020 The Oto Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build darwin,!ios,!js + +#import + +#include "_cgo_export.h" + +@interface OtoInterruptObserver : NSObject { +} + +@property(nonatomic) AudioQueueRef audioQueue; + +@end + +@implementation OtoInterruptObserver { + AudioQueueRef _audioQueue; +} + +- (void)receiveSleepNote:(NSNotification *)note { + OSStatus status = AudioQueuePause([self audioQueue]); + if (status != noErr) { + oto_setErrorByNotification(status, "AudioQueuePause"); + } +} + +- (void)receiveWakeNote:(NSNotification *)note { + OSStatus status = AudioQueueStart([self audioQueue], nil); + if (status != noErr) { + oto_setErrorByNotification(status, "AudioQueueStart"); + } +} + +@end + +// oto_setNotificationHandler sets a handler for interruption events. +void oto_setNotificationHandler(AudioQueueRef audioQueue) { + OtoInterruptObserver *observer = [[OtoInterruptObserver alloc] init]; + observer.audioQueue = audioQueue; + + [[[NSWorkspace sharedWorkspace] notificationCenter] + addObserver:observer + selector:@selector(receiveSleepNote:) + name:NSWorkspaceWillSleepNotification + object:NULL]; + [[[NSWorkspace sharedWorkspace] notificationCenter] + addObserver:observer + selector:@selector(receiveWakeNote:) + name:NSWorkspaceDidWakeNotification + object:NULL]; +}