diff --git a/Application/Application/AVMonitor.h b/Application/Application/AVMonitor.h index 14877ef..85cb5a7 100644 --- a/Application/Application/AVMonitor.h +++ b/Application/Application/AVMonitor.h @@ -10,6 +10,11 @@ @import Foundation; @import UserNotifications; +#import +#import +#import +#import + #import "LogMonitor.h" @interface AVMonitor : NSObject @@ -26,6 +31,9 @@ //audio clients @property(nonatomic, retain)NSMutableArray* audioClients; +//audio (mic) callback +@property(nonatomic, copy)AudioObjectPropertyListenerBlock listenerBlock; + //camera state @property NSControlStateValue cameraState; diff --git a/Application/Application/AVMonitor.m b/Application/Application/AVMonitor.m index 5f5ae9d..308890b 100644 --- a/Application/Application/AVMonitor.m +++ b/Application/Application/AVMonitor.m @@ -14,11 +14,6 @@ #import "AVMonitor.h" #import "utilities.h" -#import -#import -#import -#import - /* GLOBALS */ @@ -812,9 +807,12 @@ bail: //init property struct's element propertyStruct.mElement = kAudioObjectPropertyElementMaster; + //weak self + __unsafe_unretained typeof(self)weakSelf = self; + //block // invoked when audio changes - AudioObjectPropertyListenerBlock listenerBlock = ^(UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses) + self.listenerBlock = ^(UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses) { //state NSInteger state = -1; @@ -834,13 +832,13 @@ bail: os_log_debug(logHandle, "ignoring mic event, as it happened <0.5s "); //update - self.lastMicEvent = [NSDate date]; + weakSelf.lastMicEvent = [NSDate date]; return; } //update - self.lastMicEvent = [NSDate date]; + weakSelf.lastMicEvent = [NSDate date]; //mic off? if(NSControlStateValueOff == state) @@ -849,15 +847,15 @@ bail: os_log_debug(logHandle, "built in mic turned to off"); //show notification - [self generateNotification:Device_Microphone state:NSControlStateValueOff client:nil]; + [weakSelf generateNotification:Device_Microphone state:NSControlStateValueOff client:nil]; //execute action - [self executeUserAction:Device_Microphone state:NSControlStateValueOn client:nil]; + [weakSelf executeUserAction:Device_Microphone state:NSControlStateValueOn client:nil]; } }; //add property listener for audio changes - status = AudioObjectAddPropertyListenerBlock(builtInMic, &propertyStruct, dispatch_get_main_queue(), listenerBlock); + status = AudioObjectAddPropertyListenerBlock(builtInMic, &propertyStruct, dispatch_get_main_queue(), self.listenerBlock); if(noErr != status) { //err msg @@ -875,6 +873,49 @@ bail: return bRegistered; } +//stop audio monitor +-(void)stopAudioMonitor +{ + //status + OSStatus status = -1; + + //built in mic + AudioObjectID builtInMic = 0; + + //property struct + AudioObjectPropertyAddress propertyStruct = {0}; + + //dbg msg + os_log_debug(logHandle, "stopping audio (device) monitor"); + + //init property struct's selector + propertyStruct.mSelector = kAudioDevicePropertyDeviceIsRunningSomewhere; + + //init property struct's scope + propertyStruct.mScope = kAudioObjectPropertyScopeGlobal; + + //init property struct's element + propertyStruct.mElement = kAudioObjectPropertyElementMaster; + + //find built-in mic + builtInMic = [self findBuiltInMic]; + if(0 != builtInMic) + { + //remove + status = AudioObjectRemovePropertyListenerBlock(builtInMic, &propertyStruct, dispatch_get_main_queue(), self.listenerBlock); + if(noErr != status) + { + //err msg + os_log_error(logHandle, "ERROR: 'AudioObjectRemovePropertyListenerBlock' failed with %d", status); + } + } + +bail: + + return; + +} + //determine if audio device is active -(UInt32)getMicState:(AudioObjectID)deviceID { @@ -1116,6 +1157,9 @@ bail: //stop audio log monitoring [self.audioLogMonitor stop]; + //stop audio (device) monitor + [self stopAudioMonitor]; + return; } diff --git a/Application/Application/AppDelegate.m b/Application/Application/AppDelegate.m index 143d59f..da50690 100644 --- a/Application/Application/AppDelegate.m +++ b/Application/Application/AppDelegate.m @@ -39,6 +39,9 @@ extern os_log_t logHandle; //flag BOOL autoLaunched = NO; + //init + self.avMonitor = [[AVMonitor alloc] init]; + //get real parent parent = getRealParent(getpid()); @@ -68,9 +71,6 @@ extern os_log_t logHandle; // kick off device monitoring if(YES != [NSUserDefaults.standardUserDefaults boolForKey:PREF_IS_DISABLED]) { - //init - self.avMonitor = [[AVMonitor alloc] init]; - //start [self.avMonitor start]; } diff --git a/Application/Application/StatusBarItem.m b/Application/Application/StatusBarItem.m index 80c9f8a..787bdec 100644 --- a/Application/Application/StatusBarItem.m +++ b/Application/Application/StatusBarItem.m @@ -204,9 +204,21 @@ enum menuItems //stop monitor if(YES == self.isDisabled) { + //dbg msg + os_log_debug(logHandle, "will stop monitor"); + //stop [((AppDelegate*)[[NSApplication sharedApplication] delegate]).avMonitor stop]; } + //(re)start monitor + else + { + //dbg msg + os_log_debug(logHandle, "will (re)start monitor"); + + //start + [((AppDelegate*)[[NSApplication sharedApplication] delegate]).avMonitor start]; + } break;