فهرست منبع

CoreAudio: Enumerate AudioDeviceID manually

Apparently, despite the fact that Apple added
kAudioHardwarePropertyTranslateUIDToDevice in 10.8, it's not actually
usable in 10.8, only 10.9.  So, instead of being able to use it like a
normal, sane person, we have to enumerate all devices manually and find
the AudioDeviceID ourselves.  A slight annoyance and a mark against
apple's competence, but audio devices should now be working again on
10.8 at least, so whatever.
jp9000 11 سال پیش
والد
کامیت
5cd8304dc0
3فایلهای تغییر یافته به همراه86 افزوده شده و 30 حذف شده
  1. 81 23
      plugins/mac-capture/audio-device-enum.c
  2. 1 0
      plugins/mac-capture/audio-device-enum.h
  3. 4 7
      plugins/mac-capture/mac-audio.c

+ 81 - 23
plugins/mac-capture/audio-device-enum.c

@@ -23,14 +23,17 @@ static inline bool enum_success(OSStatus stat, const char *msg)
 	return true;
 }
 
-static void coreaudio_enum_add_device(struct device_list *list,
-		AudioDeviceID id, bool input)
+typedef bool (*enum_device_proc_t)(void *param, CFStringRef cf_name,
+		CFStringRef cf_uid, AudioDeviceID id);
+
+static bool coreaudio_enum_device(enum_device_proc_t proc, void *param,
+		AudioDeviceID id)
 {
-	OSStatus           stat;
-	UInt32             size     = 0;
-	CFStringRef        cf_name  = NULL;
-	CFStringRef        cf_value = NULL;
-	struct device_item item;
+	UInt32      size      = 0;
+	CFStringRef cf_name   = NULL;
+	CFStringRef cf_uid    = NULL;
+	bool        enum_next = true;
+	OSStatus    stat;
 
 	AudioObjectPropertyAddress addr = {
 		kAudioDevicePropertyStreams,
@@ -38,40 +41,32 @@ static void coreaudio_enum_add_device(struct device_list *list,
 		kAudioObjectPropertyElementMaster
 	};
 
-	memset(&item, 0, sizeof(item));
-
 	/* check to see if it's a mac input device */
 	AudioObjectGetPropertyDataSize(id, &addr, 0, NULL, &size);
 	if (!size)
-		return;
+		return true;
 
 	size = sizeof(CFStringRef);
 
 	addr.mSelector = kAudioDevicePropertyDeviceUID;
-	stat = AudioObjectGetPropertyData(id, &addr, 0, NULL, &size, &cf_value);
+	stat = AudioObjectGetPropertyData(id, &addr, 0, NULL, &size, &cf_uid);
 	if (!enum_success(stat, "get audio device UID"))
-		return;
+		return true;
 
 	addr.mSelector = kAudioDevicePropertyDeviceNameCFString;
 	stat = AudioObjectGetPropertyData(id, &addr, 0, NULL, &size, &cf_name);
 	if (!enum_success(stat, "get audio device name"))
 		goto fail;
 
-	if (!cf_to_dstr(cf_name,  &item.name))
-		goto fail;
-	if (!cf_to_dstr(cf_value, &item.value))
-		goto fail;
-
-	if (input || !device_is_input(item.value.array))
-		device_list_add(list, &item);
+	enum_next = proc(param, cf_name, cf_uid, id);
 
 fail:
-	device_item_free(&item);
 	CFRelease(cf_name);
-	CFRelease(cf_value);
+	CFRelease(cf_uid);
+	return enum_next;
 }
 
-void coreaudio_enum_devices(struct device_list *list, bool input)
+static void enum_devices(enum_device_proc_t proc, void *param)
 {
 	AudioObjectPropertyAddress addr = {
 		kAudioHardwarePropertyDevices,
@@ -97,7 +92,70 @@ void coreaudio_enum_devices(struct device_list *list, bool input)
 
 	if (enum_success(stat, "get kAudioObjectSystemObject data"))
 		for (UInt32 i = 0; i < count; i++)
-			coreaudio_enum_add_device(list, ids[i], input);
+			if (!coreaudio_enum_device(proc, param, ids[i]))
+				break;
 
 	bfree(ids);
 }
+
+struct add_data {
+	struct device_list *list;
+	bool               input;
+};
+
+static bool coreaudio_enum_add_device(void *param, CFStringRef cf_name,
+		CFStringRef cf_uid, AudioDeviceID id)
+{
+	struct add_data    *data = param;
+	struct device_item item;
+
+	memset(&item, 0, sizeof(item));
+
+	if (!cf_to_dstr(cf_name, &item.name))
+		goto fail;
+	if (!cf_to_dstr(cf_uid,  &item.value))
+		goto fail;
+
+	if (data->input || !device_is_input(item.value.array))
+		device_list_add(data->list, &item);
+
+fail:
+	device_item_free(&item);
+
+	UNUSED_PARAMETER(id);
+	return true;
+}
+
+void coreaudio_enum_devices(struct device_list *list, bool input)
+{
+	struct add_data data = {list, input};
+	enum_devices(coreaudio_enum_add_device, &data);
+}
+
+struct device_id_data {
+	CFStringRef   uid;
+	AudioDeviceID *id;
+	bool          found;
+};
+
+static bool get_device_id(void *param, CFStringRef cf_name, CFStringRef cf_uid,
+		AudioDeviceID id)
+{
+	struct device_id_data *data = param;
+
+	if (CFStringCompare(cf_uid, data->uid, 0) == 0) {
+		*data->id   = id;
+		data->found = true;
+		return false;
+	}
+
+	UNUSED_PARAMETER(cf_name);
+	return true;
+}
+
+bool coreaudio_get_device_id(CFStringRef uid, AudioDeviceID *id)
+{
+	struct device_id_data data = {uid, id, false};
+	enum_devices(get_device_id, &data);
+	return data.found;
+}

+ 1 - 0
plugins/mac-capture/audio-device-enum.h

@@ -33,3 +33,4 @@ static inline void device_list_add(struct device_list *list,
 }
 
 extern void coreaudio_enum_devices(struct device_list *list, bool input);
+extern bool coreaudio_get_device_id(CFStringRef uid, AudioDeviceID *id);

+ 4 - 7
plugins/mac-capture/mac-audio.c

@@ -101,16 +101,13 @@ static bool find_device_id_by_uid(struct coreaudio_data *ca)
 
 	if (ca->default_device) {
 		addr.mSelector = PROPERTY_DEFAULT_DEVICE;
+		stat = AudioObjectGetPropertyData(kAudioObjectSystemObject,
+				&addr, qual_size, &qual, &size, &ca->device_id);
+		success = (stat == noErr);
 	} else {
-		addr.mSelector = kAudioHardwarePropertyTranslateUIDToDevice;
-		qual      = cf_uid;
-		qual_size = sizeof(CFStringRef);
+		success = coreaudio_get_device_id(cf_uid, &ca->device_id);
 	}
 
-	stat = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr,
-			qual_size, &qual, &size, &ca->device_id);
-	success = (stat == noErr);
-
 	CFRelease(cf_uid);
 	return success;
 }