From e4601ac655a03103f548b089735b2c5f794f0733 Mon Sep 17 00:00:00 2001 From: Palana Date: Thu, 12 Jun 2014 02:30:06 +0200 Subject: [PATCH 1/4] Show unsupported selected presets for mac-avcapture Configured presets that are unsupported are now preserved in the user config, but listed as disabled --- plugins/mac-avcapture/av-capture.m | 112 ++++++++++++++++++++++++----- 1 file changed, 93 insertions(+), 19 deletions(-) diff --git a/plugins/mac-avcapture/av-capture.m b/plugins/mac-avcapture/av-capture.m index a86391583..89fedf969 100644 --- a/plugins/mac-avcapture/av-capture.m +++ b/plugins/mac-avcapture/av-capture.m @@ -509,7 +509,10 @@ static NSString *preset_names(NSString *preset) AVCaptureSessionPreset960x540:@"960x540", AVCaptureSessionPreset1280x720:@"1280x720", }; - return preset_names[preset]; + NSString *name = preset_names[preset]; + if (name) + return name; + return [NSString stringWithFormat:@"Unknown (%@)", preset]; } @@ -536,6 +539,66 @@ static void av_capture_defaults(obs_data_t settings) obs_data_set_default_string(settings, "preset", highest.UTF8String); } +static void fill_presets(AVCaptureDevice *dev, obs_property_t list, + NSString *current_preset) +{ + obs_property_list_clear(list); + + bool preset_found = false; + for (NSString *preset in presets()) { + bool supported = [dev supportsAVCaptureSessionPreset:preset]; + bool is_current = [preset isEqualToString:current_preset]; + + if (is_current) + preset_found = true; + + if (!supported && !is_current) + continue; + + size_t idx = obs_property_list_add_string(list, + preset_names(preset).UTF8String, + preset.UTF8String); + obs_property_list_item_disable(list, idx, !supported); + } + + if (preset_found) + return; + + size_t idx = obs_property_list_add_string(list, + preset_names(current_preset).UTF8String, + current_preset.UTF8String); + obs_property_list_item_disable(list, idx, true); +} + +static bool check_preset(AVCaptureDevice *dev, + obs_property_t list, obs_data_t settings) +{ + NSString *current_preset = get_string(settings, "preset"); + + size_t size = obs_property_list_item_count(list); + NSMutableSet *listed = [NSMutableSet setWithCapacity:size]; + + for (size_t i = 0; i < size; i++) + [listed addObject:@(obs_property_list_item_string(list, i))]; + + bool presets_changed = false; + for (NSString *preset in presets()) { + bool is_listed = [listed member:preset] != nil; + bool supported = [dev supportsAVCaptureSessionPreset:preset]; + + if (supported == is_listed) + continue; + + presets_changed = true; + } + + if (!presets_changed && [listed member:current_preset] != nil) + return false; + + fill_presets(dev, list, current_preset); + return true; +} + static bool properties_device_changed(obs_properties_t props, obs_property_t p, obs_data_t settings) { @@ -547,25 +610,21 @@ static bool properties_device_changed(obs_properties_t props, obs_property_t p, if (!dev) return false; - obs_property_t preset_list = obs_properties_get(props, "preset"); - obs_property_list_clear(preset_list); + return check_preset(dev, obs_properties_get(props, "preset"), settings); +} - for (NSString *preset in presets()) { - if (![dev supportsAVCaptureSessionPreset:preset]) - continue; +static bool properties_preset_changed(obs_properties_t props, obs_property_t p, + obs_data_t settings) +{ + UNUSED_PARAMETER(props); - obs_property_list_add_string(preset_list, - preset_names(preset).UTF8String, - preset.UTF8String); + NSString *uid = get_string(settings, "device"); + AVCaptureDevice *dev = [AVCaptureDevice deviceWithUniqueID:uid]; - } + if (!dev) + return false; - NSString *preset = get_string(settings, "preset"); - if (![dev supportsAVCaptureSessionPreset:preset]) - obs_data_setstring(settings, "preset", - select_preset(dev, preset).UTF8String); - - return true; + return check_preset(dev, p, settings); } static obs_properties_t av_capture_properties(void) @@ -591,8 +650,15 @@ static obs_properties_t av_capture_properties(void) // TODO: implement manual configuration obs_property_set_enabled(use_preset, false); - obs_properties_add_list(props, "preset", "Preset", OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_STRING); + obs_property_t preset_list = obs_properties_add_list(props, "preset", + "Preset", OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); + for (NSString *preset in presets()) + obs_property_list_add_string(preset_list, + preset_names(preset).UTF8String, + preset.UTF8String); + + obs_property_set_modified_callback(preset_list, + properties_preset_changed); return props; } @@ -628,7 +694,15 @@ static void av_capture_update(void *data, obs_data_t settings) if (!capture->device || ![capture->device.uniqueID isEqualToString:uid]) return switch_device(capture, uid, settings); - capture->session.sessionPreset = get_string(settings, "preset"); + NSString *preset = get_string(settings, "preset"); + NSLog(@"%@", preset); + if (![capture->device supportsAVCaptureSessionPreset:preset]) { + AVLOG(LOG_ERROR, "Preset %s not available", preset.UTF8String); + preset = select_preset(capture->device, preset); + } + + capture->session.sessionPreset = preset; + AVLOG(LOG_INFO, "Selected preset %s", preset.UTF8String); } struct obs_source_info av_capture_info = { From 77e97637475b4f22e30939ee3a1f890be36e1036 Mon Sep 17 00:00:00 2001 From: Palana Date: Thu, 12 Jun 2014 03:05:00 +0200 Subject: [PATCH 2/4] Add disconnected (selected) devices to device list for mac-avcapture This requires the (localized) device name to be stored --- plugins/mac-avcapture/av-capture.m | 70 ++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/plugins/mac-avcapture/av-capture.m b/plugins/mac-avcapture/av-capture.m index 89fedf969..7e68c5f8c 100644 --- a/plugins/mac-avcapture/av-capture.m +++ b/plugins/mac-avcapture/av-capture.m @@ -331,8 +331,12 @@ static void capture_device(struct av_capture *capture, AVCaptureDevice *dev, obs_data_t settings) { capture->device = dev; - AVLOG(LOG_INFO, "Selected device '%s' %p", - capture->device.localizedName.UTF8String, capture); + + const char *name = capture->device.localizedName.UTF8String; + obs_data_setstring(settings, "device_name", name); + obs_data_setstring(settings, "device", + capture->device.uniqueID.UTF8String); + AVLOG(LOG_INFO, "Selected device '%s'", name); if (obs_data_getbool(settings, "use_preset")) { NSString *preset = get_string(settings, "preset"); @@ -534,11 +538,53 @@ static void av_capture_defaults(obs_data_t settings) obs_data_set_default_string(settings, "device", dev.uniqueID.UTF8String); + obs_data_set_default_string(settings, "device_name", + dev.localizedName.UTF8String); obs_data_set_default_bool(settings, "use_preset", true); obs_data_set_default_string(settings, "preset", highest.UTF8String); } +static bool update_device_list(obs_property_t list, + NSString *uid, NSString *name, bool disconnected) +{ + bool dev_found = false; + bool list_modified = false; + + size_t size = obs_property_list_item_count(list); + for (size_t i = 0; i < size;) { + const char *uid_ = obs_property_list_item_string(list, i); + bool found = [uid isEqualToString:@(uid_)]; + bool disabled = obs_property_list_item_disabled(list, i); + if (!found && !disabled) { + i += 1; + continue; + } + + if (disabled && !found) { + list_modified = true; + obs_property_list_item_remove(list, i); + continue; + } + + if (disabled != disconnected) + list_modified = true; + + dev_found = true; + obs_property_list_item_disable(list, i, disconnected); + i += 1; + } + + if (dev_found) + return list_modified; + + size_t idx = obs_property_list_add_string(list, name.UTF8String, + uid.UTF8String); + obs_property_list_item_disable(list, idx, disconnected); + + return true; +} + static void fill_presets(AVCaptureDevice *dev, obs_property_t list, NSString *current_preset) { @@ -546,8 +592,9 @@ static void fill_presets(AVCaptureDevice *dev, obs_property_t list, bool preset_found = false; for (NSString *preset in presets()) { - bool supported = [dev supportsAVCaptureSessionPreset:preset]; bool is_current = [preset isEqualToString:current_preset]; + bool supported = !dev || + [dev supportsAVCaptureSessionPreset:preset]; if (is_current) preset_found = true; @@ -584,7 +631,8 @@ static bool check_preset(AVCaptureDevice *dev, bool presets_changed = false; for (NSString *preset in presets()) { bool is_listed = [listed member:preset] != nil; - bool supported = [dev supportsAVCaptureSessionPreset:preset]; + bool supported = !dev || + [dev supportsAVCaptureSessionPreset:preset]; if (supported == is_listed) continue; @@ -602,15 +650,14 @@ static bool check_preset(AVCaptureDevice *dev, static bool properties_device_changed(obs_properties_t props, obs_property_t p, obs_data_t settings) { - UNUSED_PARAMETER(p); - NSString *uid = get_string(settings, "device"); - AVCaptureDevice *dev = [AVCaptureDevice deviceWithUniqueID:uid]; - if (!dev) - return false; - return check_preset(dev, obs_properties_get(props, "preset"), settings); + NSString *name = get_string(settings, "device_name"); + bool dev_list_updated = update_device_list(p, uid, name, !dev); + + p = obs_properties_get(props, "preset"); + return check_preset(dev, p, settings) || dev_list_updated; } static bool properties_preset_changed(obs_properties_t props, obs_property_t p, @@ -621,9 +668,6 @@ static bool properties_preset_changed(obs_properties_t props, obs_property_t p, NSString *uid = get_string(settings, "device"); AVCaptureDevice *dev = [AVCaptureDevice deviceWithUniqueID:uid]; - if (!dev) - return false; - return check_preset(dev, p, settings); } From 2b5bd11671744f7eb1db06c9b8e2223030555173 Mon Sep 17 00:00:00 2001 From: Palana Date: Wed, 25 Jun 2014 18:17:02 +0200 Subject: [PATCH 3/4] Implement preset auto select notification for mac-avcapture --- plugins/mac-avcapture/av-capture.m | 33 ++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/plugins/mac-avcapture/av-capture.m b/plugins/mac-avcapture/av-capture.m index 7e68c5f8c..2c7a2bb52 100644 --- a/plugins/mac-avcapture/av-capture.m +++ b/plugins/mac-avcapture/av-capture.m @@ -647,6 +647,29 @@ static bool check_preset(AVCaptureDevice *dev, return true; } +static bool autoselect_preset(AVCaptureDevice *dev, obs_data_t settings) +{ + NSString *preset = get_string(settings, "preset"); + if (!dev || [dev supportsAVCaptureSessionPreset:preset]) { + if (obs_data_has_autoselect(settings, "preset")) { + obs_data_unset_autoselect_value(settings, "preset"); + return true; + } + + } else { + preset = select_preset(dev, preset); + const char *autoselect = + obs_data_get_autoselect_string(settings, "preset"); + if (![preset isEqualToString:@(autoselect)]) { + obs_data_set_autoselect_string(settings, "preset", + preset.UTF8String); + return true; + } + } + + return false; +} + static bool properties_device_changed(obs_properties_t props, obs_property_t p, obs_data_t settings) { @@ -657,7 +680,10 @@ static bool properties_device_changed(obs_properties_t props, obs_property_t p, bool dev_list_updated = update_device_list(p, uid, name, !dev); p = obs_properties_get(props, "preset"); - return check_preset(dev, p, settings) || dev_list_updated; + bool preset_list_changed = check_preset(dev, p, settings); + bool autoselect_changed = autoselect_preset(dev, settings); + + return preset_list_changed || autoselect_changed || dev_list_updated; } static bool properties_preset_changed(obs_properties_t props, obs_property_t p, @@ -668,7 +694,10 @@ static bool properties_preset_changed(obs_properties_t props, obs_property_t p, NSString *uid = get_string(settings, "device"); AVCaptureDevice *dev = [AVCaptureDevice deviceWithUniqueID:uid]; - return check_preset(dev, p, settings); + bool preset_list_changed = check_preset(dev, p, settings); + bool autoselect_changed = autoselect_preset(dev, settings); + + return preset_list_changed || autoselect_changed; } static obs_properties_t av_capture_properties(void) From f09f969bc01495b537e43dbd484b6dfed2907dc6 Mon Sep 17 00:00:00 2001 From: Palana Date: Wed, 25 Jun 2014 22:56:10 +0200 Subject: [PATCH 4/4] Disable default device selection for mac-avcapture Since adding a source now opens the config dialog for that source the convenience gain from having a device automatically start capturing is outweighed by the inconvenience from having captured images unintentionally recorded/streamed --- plugins/mac-avcapture/av-capture.m | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/plugins/mac-avcapture/av-capture.m b/plugins/mac-avcapture/av-capture.m index 2c7a2bb52..8f19f8fdc 100644 --- a/plugins/mac-avcapture/av-capture.m +++ b/plugins/mac-avcapture/av-capture.m @@ -522,27 +522,11 @@ static NSString *preset_names(NSString *preset) static void av_capture_defaults(obs_data_t settings) { - AVCaptureDevice *dev = [AVCaptureDevice - defaultDeviceWithMediaType:AVMediaTypeVideo]; - if (!dev) - return; - - NSString *highest = nil; - for (NSString *preset in presets()) { - if (![dev supportsAVCaptureSessionPreset:preset]) - continue; - highest = preset; - } - if (!highest) - return; - - obs_data_set_default_string(settings, "device", - dev.uniqueID.UTF8String); - obs_data_set_default_string(settings, "device_name", - dev.localizedName.UTF8String); + //TODO: localize + obs_data_set_default_string(settings, "device_name", "none"); obs_data_set_default_bool(settings, "use_preset", true); - - obs_data_set_default_string(settings, "preset", highest.UTF8String); + obs_data_set_default_string(settings, "preset", + AVCaptureSessionPreset1280x720.UTF8String); } static bool update_device_list(obs_property_t list,