changeset 31649:e55ce930e6ae

Refactor device selection in ao_coreaudio: Add output device selection and correctly set the default device if it's selected.
author adrian
date Sun, 11 Jul 2010 21:08:57 +0000
parents a09f02987594
children 955cdbd3ac02
files DOCS/man/en/mplayer.1 libao2/ao_coreaudio.c
diffstat 2 files changed, 84 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/DOCS/man/en/mplayer.1	Sun Jul 11 21:02:53 2010 +0000
+++ b/DOCS/man/en/mplayer.1	Sun Jul 11 21:08:57 2010 +0000
@@ -2852,6 +2852,14 @@
 .TP
 .B coreaudio (Mac OS X only)
 native Mac OS X audio output driver
+.PD 0
+.RSs
+.IPs device_id=<id>
+ID of output device to use (0 = default device)
+.IPs help
+List all available output devices with their IDs.
+.RE
+.PD 1
 .
 .TP
 .B "openal\ "
--- a/libao2/ao_coreaudio.c	Sun Jul 11 21:02:53 2010 +0000
+++ b/libao2/ao_coreaudio.c	Sun Jul 11 21:08:57 2010 +0000
@@ -53,6 +53,7 @@
 #include "libaf/af_format.h"
 #include "osdep/timer.h"
 #include "libavutil/fifo.h"
+#include "subopt-helper.h"
 
 static const ao_info_t info =
   {
@@ -345,6 +346,51 @@
                                 const AudioObjectPropertyAddress inAddresses[],
                                 void *inClientData );
 
+static void print_help(void)
+{
+    OSStatus err;
+    UInt32 i_param_size;
+    int num_devices;
+    AudioDeviceID *devids;
+    AudioObjectPropertyAddress property_address;
+    char *device_name;
+
+    mp_msg(MSGT_AO, MSGL_FATAL,
+           "\n-ao coreaudio commandline help:\n"
+           "Example: mplayer -ao coreaudio:device_id=266\n"
+           "    open Core Audio with output device ID 266.\n"
+           "\nOptions:\n"
+           "    device_id\n"
+           "        ID of output device to use (0 = default device)\n"
+           "    help\n"
+           "        This help including list of available devices.\n"
+           "\n"
+           "Available output devices:\n");
+
+    i_param_size = GetGlobalAudioPropertyArray(kAudioObjectSystemObject, kAudioHardwarePropertyDevices, (void **)&devids);
+
+    if (!i_param_size) {
+        mp_msg(MSGT_AO, MSGL_FATAL, "Failed to get list of output devices.\n");
+        return;
+    }
+
+    num_devices = i_param_size / sizeof(AudioDeviceID);
+
+    for (int i = 0; i < num_devices; ++i) {
+        err = GetAudioPropertyString(devids[i], kAudioObjectPropertyName, &device_name);
+
+        if (err == noErr) {
+            mp_msg(MSGT_AO, MSGL_FATAL, "%s (id: %"PRIu32")\n", device_name, devids[i]);
+            free(device_name);
+        } else
+            mp_msg(MSGT_AO, MSGL_FATAL, "Unknown (id: %"PRIu32")\n", devids[i]);
+    }
+
+    mp_msg(MSGT_AO, MSGL_FATAL, "\n");
+
+    free(devids);
+}
+
 static int init(int rate,int channels,int format,int flags)
 {
 AudioStreamBasicDescription inDesc;
@@ -355,6 +401,20 @@
 UInt32 size, maxFrames, i_param_size, b_alive;
 char *psz_name;
 AudioDeviceID devid_def = 0;
+int device_id;
+
+    const opt_t subopts[] = {
+        {"device_id", OPT_ARG_INT, &device_id, NULL},
+        {NULL}
+    };
+
+    // set defaults
+    device_id = 0;
+
+    if (subopt_parse(ao_subdevice, subopts) != 0) {
+        print_help();
+        return 0;
+    }
 
     ao_msg(MSGT_AO,MSGL_V, "init([%dHz][%dch][%s][%d])\n", rate, channels, af_fmt2str_short(format), flags);
 
@@ -371,9 +431,7 @@
     ao->b_revert = 0;
     ao->b_changed_mixing = 0;
 
-    /* Probe whether device support S/PDIF stream output if input is AC3 stream. */
-    if (AF_FORMAT_IS_AC3(format))
-    {
+    if (device_id == 0) {
         /* Find the ID of the default Device. */
         err = GetAudioProperty(kAudioObjectSystemObject,
                                kAudioHardwarePropertyDefaultOutputDevice,
@@ -383,6 +441,9 @@
             ao_msg(MSGT_AO, MSGL_WARN, "could not get default audio device: [%4.4s]\n", (char *)&err);
             goto err_out;
         }
+    } else {
+        devid_def = device_id;
+    }
 
         /* Retrieve the name of the device. */
         err = GetAudioPropertyString(devid_def,
@@ -394,17 +455,21 @@
             goto err_out;
         }
 
-        ao_msg(MSGT_AO,MSGL_V, "got default audio output device ID: %"PRIu32" Name: %s\n", devid_def, psz_name );
+    ao_msg(MSGT_AO,MSGL_V, "got audio output device ID: %"PRIu32" Name: %s\n", devid_def, psz_name );
 
+    /* Probe whether device support S/PDIF stream output if input is AC3 stream. */
+    if (AF_FORMAT_IS_AC3(format)) {
         if (AudioDeviceSupportsDigital(devid_def))
         {
             ao->b_supports_digital = 1;
-            ao->i_selected_dev = devid_def;
         }
         ao_msg(MSGT_AO,MSGL_V, "probe default audio output device whether support digital s/pdif output:%d\n", ao->b_supports_digital );
+    }
 
-        free( psz_name);
-    }
+    free(psz_name);
+
+    // Save selected device id
+    ao->i_selected_dev = devid_def;
 
 	// Build Description for the input format
 	inDesc.mSampleRate=rate;
@@ -464,7 +529,7 @@
 
 	/* original analog output code */
 	desc.componentType = kAudioUnitType_Output;
-	desc.componentSubType = kAudioUnitSubType_DefaultOutput;
+	desc.componentSubType = (device_id == 0) ? kAudioUnitSubType_DefaultOutput : kAudioUnitSubType_HALOutput;
 	desc.componentManufacturer = kAudioUnitManufacturer_Apple;
 	desc.componentFlags = 0;
 	desc.componentFlagsMask = 0;
@@ -505,6 +570,9 @@
 		goto err_out2;
 	}
 
+	//Set the Current Device to the Default Output Unit.
+    err = AudioUnitSetProperty(ao->theOutputUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &ao->i_selected_dev, sizeof(ao->i_selected_dev));
+
 	ao->chunk_size = maxFrames;//*inDesc.mBytesPerFrame;
 
 	ao_data.samplerate = inDesc.mSampleRate;