improved handling of device off/inactive events
This commit is contained in:
parent
dbcecf60c4
commit
c4c97f2f2c
|
@ -52,6 +52,9 @@
|
|||
//audio listeners
|
||||
@property(nonatomic, retain)NSMutableDictionary* audioListeners;
|
||||
|
||||
//camera listeners
|
||||
@property(nonatomic, retain)NSMutableDictionary* cameraListeners;
|
||||
|
||||
//per device events
|
||||
@property(nonatomic, retain)NSMutableDictionary* deviceEvents;
|
||||
|
||||
|
|
|
@ -56,9 +56,12 @@ extern os_log_t logHandle;
|
|||
//init camera attributions
|
||||
self.cameraAttributions = [NSMutableArray array];
|
||||
|
||||
//init audio listener
|
||||
//init audio listeners
|
||||
self.audioListeners = [NSMutableDictionary dictionary];
|
||||
|
||||
//init video listeners
|
||||
self.cameraListeners = [NSMutableDictionary dictionary];
|
||||
|
||||
//set up delegate
|
||||
UNUserNotificationCenter.currentNotificationCenter.delegate = self;
|
||||
|
||||
|
@ -232,7 +235,7 @@ extern os_log_t logHandle;
|
|||
continue;
|
||||
}
|
||||
|
||||
//cameraAttributionsList list?
|
||||
//cameraAttributions list?
|
||||
if(YES == [line hasPrefix:@"cameraAttributions = "])
|
||||
{
|
||||
//set flag
|
||||
|
@ -628,6 +631,9 @@ extern os_log_t logHandle;
|
|||
goto bail;
|
||||
}
|
||||
|
||||
//save
|
||||
self.audioListeners[device.uniqueID] = listenerBlock;
|
||||
|
||||
//dbg msg
|
||||
os_log_debug(logHandle, "monitoring %{public}@ for audio changes", device.localizedName);
|
||||
|
||||
|
@ -648,6 +654,7 @@ bail:
|
|||
//status var
|
||||
OSStatus status = -1;
|
||||
|
||||
//device id
|
||||
CMIOObjectID deviceID = 0;
|
||||
|
||||
//property struct
|
||||
|
@ -697,13 +704,15 @@ bail:
|
|||
goto bail;
|
||||
}
|
||||
|
||||
//save
|
||||
self.cameraListeners[device.uniqueID] = listenerBlock;
|
||||
|
||||
//dbg msg
|
||||
os_log_debug(logHandle, "monitoring %{public}@ for video changes", device.localizedName);
|
||||
|
||||
//happy
|
||||
bRegistered = YES;
|
||||
|
||||
//bail
|
||||
bail:
|
||||
|
||||
return bRegistered;
|
||||
|
@ -995,7 +1004,7 @@ bail:
|
|||
//external device?
|
||||
// don't show notification
|
||||
if( (YES != [self.builtInMic.uniqueID isEqualToString:event.device.uniqueID]) &&
|
||||
(YES != [self.builtInCamera.uniqueID isEqualToString:event.device.uniqueID]) )
|
||||
(YES != [self.builtInCamera.uniqueID isEqualToString:event.device.uniqueID]) )
|
||||
{
|
||||
//set result
|
||||
result = NOTIFICATION_SKIPPED;
|
||||
|
@ -1012,13 +1021,10 @@ bail:
|
|||
// check last device that turned off
|
||||
else
|
||||
{
|
||||
//wait
|
||||
// since logging event might come thru first
|
||||
[NSThread sleepForTimeInterval:1.0f];
|
||||
|
||||
//mic
|
||||
// check last mic off device
|
||||
if( (event.deviceType = Device_Microphone) &&
|
||||
if( (Device_Microphone == event.deviceType) &&
|
||||
(nil != self.lastMicOff) &&
|
||||
(YES != [self.builtInMic.uniqueID isEqualToString:self.lastMicOff.uniqueID]) )
|
||||
{
|
||||
//set result
|
||||
|
@ -1033,8 +1039,9 @@ bail:
|
|||
|
||||
//camera
|
||||
// check last camera off device
|
||||
if( (event.deviceType = Device_Camera) &&
|
||||
(YES != [self.builtInMic.uniqueID isEqualToString:self.lastCameraOff.uniqueID]) )
|
||||
if( (Device_Camera == event.deviceType) &&
|
||||
(nil != self.lastCameraOff) &&
|
||||
(YES != [self.builtInCamera.uniqueID isEqualToString:self.lastCameraOff.uniqueID]) )
|
||||
{
|
||||
//set result
|
||||
result = NOTIFICATION_SKIPPED;
|
||||
|
@ -1288,12 +1295,125 @@ bail:
|
|||
//stop monitor
|
||||
-(void)stop
|
||||
{
|
||||
//dbg msg
|
||||
os_log_debug(logHandle, "stopping log monitor");
|
||||
|
||||
//stop log monitoring
|
||||
[self.logMonitor stop];
|
||||
|
||||
//dbg msg
|
||||
os_log_debug(logHandle, "stopping audio monitor(s)");
|
||||
|
||||
//watch all input audio (mic) devices
|
||||
for(AVCaptureDevice* audioDevice in [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio])
|
||||
{
|
||||
//stop (device) monitor
|
||||
[self unwatchAudioDevice:audioDevice];
|
||||
}
|
||||
|
||||
//dbg msg
|
||||
os_log_debug(logHandle, "stopping video monitor(s)");
|
||||
|
||||
//watch all input video (cam) devices
|
||||
for(AVCaptureDevice* videoDevice in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo])
|
||||
{
|
||||
//start (device) monitor
|
||||
[self unwatchVideoDevice:videoDevice];
|
||||
}
|
||||
|
||||
//dbg msg
|
||||
os_log_debug(logHandle, "all stopped...");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//stop audio monitor
|
||||
-(void)unwatchAudioDevice:(AVCaptureDevice*)device
|
||||
{
|
||||
//status
|
||||
OSStatus status = -1;
|
||||
|
||||
//device ID
|
||||
AudioObjectID deviceID = 0;
|
||||
|
||||
//property struct
|
||||
AudioObjectPropertyAddress propertyStruct = {0};
|
||||
|
||||
//get device ID
|
||||
deviceID = [self getAVObjectID:device];
|
||||
|
||||
//init property struct's selector
|
||||
propertyStruct.mSelector = kAudioDevicePropertyDeviceIsRunningSomewhere;
|
||||
|
||||
//init property struct's scope
|
||||
propertyStruct.mScope = kAudioObjectPropertyScopeGlobal;
|
||||
|
||||
//init property struct's element
|
||||
propertyStruct.mElement = kAudioObjectPropertyElementMaster;
|
||||
|
||||
//remove
|
||||
status = AudioObjectRemovePropertyListenerBlock(deviceID, &propertyStruct, dispatch_get_main_queue(), self.audioListeners[device.uniqueID]);
|
||||
if(noErr != status)
|
||||
{
|
||||
//err msg
|
||||
os_log_error(logHandle, "ERROR: 'AudioObjectRemovePropertyListenerBlock' failed with %d", status);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//unset listener block
|
||||
self.audioListeners[device.uniqueID] = nil;
|
||||
|
||||
bail:
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//stop video monitor
|
||||
-(void)unwatchVideoDevice:(AVCaptureDevice*)device
|
||||
{
|
||||
//status
|
||||
OSStatus status = -1;
|
||||
|
||||
//device id
|
||||
CMIOObjectID deviceID = 0;
|
||||
|
||||
//property struct
|
||||
CMIOObjectPropertyAddress propertyStruct = {0};
|
||||
|
||||
//get device ID
|
||||
deviceID = [self getAVObjectID:device];
|
||||
|
||||
//init property struct's selector
|
||||
propertyStruct.mSelector = kAudioDevicePropertyDeviceIsRunningSomewhere;
|
||||
|
||||
//init property struct's scope
|
||||
propertyStruct.mScope = kAudioObjectPropertyScopeGlobal;
|
||||
|
||||
//init property struct's element
|
||||
propertyStruct.mElement = kAudioObjectPropertyElementMaster;
|
||||
|
||||
//remove
|
||||
status = CMIOObjectRemovePropertyListenerBlock(deviceID, &propertyStruct, dispatch_get_main_queue(), self.cameraListeners[device.uniqueID]);
|
||||
if(noErr != status)
|
||||
{
|
||||
//err msg
|
||||
os_log_error(logHandle, "ERROR: 'AudioObjectRemovePropertyListenerBlock' failed with %d", status);
|
||||
|
||||
//bail
|
||||
goto bail;
|
||||
}
|
||||
|
||||
//unset listener block
|
||||
self.cameraListeners[device.uniqueID] = nil;
|
||||
|
||||
bail:
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
# pragma mark UNNotificationCenter Delegate Methods
|
||||
|
||||
//handle user response to notification
|
||||
|
|
|
@ -94,7 +94,7 @@
|
|||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="156" translatesAutoresizingMaskIntoConstraints="NO" id="xbe-1S-lpy">
|
||||
<rect key="frame" x="72" y="326" width="114" height="15"/>
|
||||
<rect key="frame" x="72" y="327" width="114" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Start at Login" id="JVI-Or-h0u">
|
||||
<font key="font" size="13" name="Menlo-Bold"/>
|
||||
|
@ -103,7 +103,7 @@
|
|||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" preferredMaxLayoutWidth="471" translatesAutoresizingMaskIntoConstraints="NO" id="tFB-E4-zbp">
|
||||
<rect key="frame" x="72" y="309" width="475" height="15"/>
|
||||
<rect key="frame" x="72" y="310" width="475" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Automatically (re)start each time you login." id="E0T-Ug-P8f">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
|
@ -123,7 +123,7 @@
|
|||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="156" translatesAutoresizingMaskIntoConstraints="NO" id="Kjh-jc-STu">
|
||||
<rect key="frame" x="72" y="264" width="98" height="15"/>
|
||||
<rect key="frame" x="72" y="265" width="98" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="No Icon Mode" id="4EN-j2-enV">
|
||||
<font key="font" size="13" name="Menlo-Bold"/>
|
||||
|
@ -143,7 +143,7 @@
|
|||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="262" translatesAutoresizingMaskIntoConstraints="NO" id="Enr-tn-mwG">
|
||||
<rect key="frame" x="72" y="201" width="177" height="15"/>
|
||||
<rect key="frame" x="72" y="202" width="177" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Ignore External Device" id="a5n-tt-65v">
|
||||
<font key="font" size="13" name="Menlo-Bold"/>
|
||||
|
@ -152,7 +152,7 @@
|
|||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" preferredMaxLayoutWidth="471" translatesAutoresizingMaskIntoConstraints="NO" id="AAL-QY-azK">
|
||||
<rect key="frame" x="72" y="184" width="522" height="15"/>
|
||||
<rect key="frame" x="72" y="185" width="522" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Do not show an alert when external devices trigger an event." id="SYJ-Qv-cRq">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
|
@ -172,7 +172,7 @@
|
|||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="262" translatesAutoresizingMaskIntoConstraints="NO" id="K3U-Od-Xdy">
|
||||
<rect key="frame" x="72" y="149" width="200" height="15"/>
|
||||
<rect key="frame" x="72" y="150" width="200" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Disable 'Inactive' Alerts" id="Gsa-fn-iag">
|
||||
<font key="font" size="13" name="Menlo-Bold"/>
|
||||
|
@ -181,7 +181,7 @@
|
|||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" preferredMaxLayoutWidth="471" translatesAutoresizingMaskIntoConstraints="NO" id="5xo-jp-5qA">
|
||||
<rect key="frame" x="72" y="132" width="522" height="15"/>
|
||||
<rect key="frame" x="72" y="133" width="522" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Do not show an alert when the camera/microphone is deactivated. " id="1A2-j2-kqG">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
|
@ -201,7 +201,7 @@
|
|||
</connections>
|
||||
</button>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" preferredMaxLayoutWidth="471" translatesAutoresizingMaskIntoConstraints="NO" id="xaO-g8-rdS">
|
||||
<rect key="frame" x="72" y="247" width="475" height="15"/>
|
||||
<rect key="frame" x="72" y="248" width="475" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Run without showing an icon in the status menu bar." id="SG5-YM-BoV">
|
||||
<font key="font" size="13" name="Menlo-Regular"/>
|
||||
|
|
Loading…
Reference in New Issue