Ver Fonte

Merge pull request #128 from palana/mac-avcapture-settings-changes

Update mac-avcapture to use recent property and data changes
Jim há 11 anos atrás
pai
commit
8e860576ea
1 ficheiros alterados com 168 adições e 37 exclusões
  1. 168 37
      plugins/mac-avcapture/av-capture.m

+ 168 - 37
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");
@@ -509,65 +513,177 @@ 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];
 }
 
 
 static void av_capture_defaults(obs_data_t settings)
 {
-	AVCaptureDevice *dev = [AVCaptureDevice
-		defaultDeviceWithMediaType:AVMediaTypeVideo];
-	if (!dev)
-		return;
+	//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",
+			AVCaptureSessionPreset1280x720.UTF8String);
+}
 
-	NSString *highest = nil;
-	for (NSString *preset in presets()) {
-		if (![dev supportsAVCaptureSessionPreset:preset])
+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;
-		highest = preset;
+		}
+		
+		if (disabled != disconnected)
+			list_modified = true;
+
+		dev_found = true;
+		obs_property_list_item_disable(list, i, disconnected);
+		i += 1;
 	}
-	if (!highest)
-		return;
 
-	obs_data_set_default_string(settings, "device",
-			dev.uniqueID.UTF8String);
-	obs_data_set_default_bool(settings, "use_preset", true);
+	if (dev_found)
+		return list_modified;
 
-	obs_data_set_default_string(settings, "preset", highest.UTF8String);
+	size_t idx = obs_property_list_add_string(list, name.UTF8String,
+			uid.UTF8String);
+	obs_property_list_item_disable(list, idx, disconnected);
+
+	return true;
 }
 
-static bool properties_device_changed(obs_properties_t props, obs_property_t p,
-		obs_data_t settings)
+static void fill_presets(AVCaptureDevice *dev, obs_property_t list,
+		NSString *current_preset)
 {
-	UNUSED_PARAMETER(p);
-
-	NSString *uid = get_string(settings, "device");
+	obs_property_list_clear(list);
 
-	AVCaptureDevice *dev = [AVCaptureDevice deviceWithUniqueID:uid];
-	if (!dev)
-		return false;
+	bool preset_found = false;
+	for (NSString *preset in presets()) {
+		bool is_current = [preset isEqualToString:current_preset];
+		bool supported  = !dev ||
+			[dev supportsAVCaptureSessionPreset:preset];
 
-	obs_property_t preset_list = obs_properties_get(props, "preset");
-	obs_property_list_clear(preset_list);
+		if (is_current)
+			preset_found = true;
 
-	for (NSString *preset in presets()) {
-		if (![dev supportsAVCaptureSessionPreset:preset])
+		if (!supported && !is_current)
 			continue;
 
-		obs_property_list_add_string(preset_list,
+		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 || 
+			[dev supportsAVCaptureSessionPreset:preset];
+
+		if (supported == is_listed)
+			continue;
 
+		presets_changed = true;
 	}
 
-	NSString *preset = get_string(settings, "preset");
-	if (![dev supportsAVCaptureSessionPreset:preset])
-		obs_data_setstring(settings, "preset",
-				select_preset(dev, preset).UTF8String);
+	if (!presets_changed && [listed member:current_preset] != nil)
+		return false;
 
+	fill_presets(dev, list, current_preset);
 	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)
+{
+	NSString *uid = get_string(settings, "device");
+	AVCaptureDevice *dev = [AVCaptureDevice deviceWithUniqueID:uid];
+
+	NSString *name = get_string(settings, "device_name");
+	bool dev_list_updated = update_device_list(p, uid, name, !dev);
+
+	p = obs_properties_get(props, "preset");
+	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,
+		obs_data_t settings)
+{
+	UNUSED_PARAMETER(props);
+
+	NSString *uid = get_string(settings, "device");
+	AVCaptureDevice *dev = [AVCaptureDevice deviceWithUniqueID:uid];
+
+	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)
 {
 	obs_properties_t props = obs_properties_create();
@@ -591,8 +707,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 +751,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 = {