Bug 1278612 - Use DefaultOutputUnit as the default output device. r=jesup, a=lizzard
authorMatthew Gregan <kinetik@flim.org>
Mon, 15 Aug 2016 13:21:29 +1200
changeset 340363 6b44534d8e744473c3a8a762ebe454f7b749e35e
parent 340362 36cdcd06bf6f2fa49e5f097ad0fbef0f9630ae84
child 340364 ffe315faba1726473b709697314c13e2da071a62
push id6313
push userryanvm@gmail.com
push dateThu, 18 Aug 2016 01:58:39 +0000
treeherdermozilla-beta@6b44534d8e74 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup, lizzard
bugs1278612
milestone49.0
Bug 1278612 - Use DefaultOutputUnit as the default output device. r=jesup, a=lizzard https://github.com/kinetiknz/cubeb/commit/6b2c610 changed the output unit from kAudioUnitSubType_DefaultOutput to kAudioUnitSubType_HALOutput because capture is never available on the DefaultOutputUnit. For the case where we're doing output only to the default device, this regressed the automatic device switching when the output device was changed in the Sound system preferences. Reverting to the DefaultOutputUnit for this case restores the previous behaviour. This addresses BMO #1278612.
media/libcubeb/bug1278612.patch
media/libcubeb/src/cubeb_audiounit.c
media/libcubeb/update.sh
new file mode 100644
--- /dev/null
+++ b/media/libcubeb/bug1278612.patch
@@ -0,0 +1,125 @@
+diff --git a/media/libcubeb/src/cubeb_audiounit.c b/media/libcubeb/src/cubeb_audiounit.c
+--- a/media/libcubeb/src/cubeb_audiounit.c
++++ b/media/libcubeb/src/cubeb_audiounit.c
+@@ -45,22 +45,16 @@
+ typedef UInt32  AudioFormatFlags;
+ #endif
+ 
+ #define CUBEB_STREAM_MAX 8
+ 
+ #define AU_OUT_BUS    0
+ #define AU_IN_BUS     1
+ 
+-#if TARGET_OS_IPHONE
+-#define CUBEB_AUDIOUNIT_SUBTYPE kAudioUnitSubType_RemoteIO
+-#else
+-#define CUBEB_AUDIOUNIT_SUBTYPE kAudioUnitSubType_HALOutput
+-#endif
+-
+ //#define LOGGING_ENABLED
+ #ifdef LOGGING_ENABLED
+ #define LOG(...) do {                           \
+     fprintf(stderr, __VA_ARGS__);               \
+   } while(0)
+ #else
+ #define LOG(...)
+ #endif
+@@ -824,57 +818,73 @@ audiounit_create_unit(AudioUnit * unit,
+                       bool is_input,
+                       const cubeb_stream_params * stream_params,
+                       cubeb_devid device)
+ {
+   AudioComponentDescription desc;
+   AudioComponent comp;
+   UInt32 enable;
+   AudioDeviceID devid;
++  bool use_default_output = false;
+ 
+   desc.componentType = kAudioUnitType_Output;
+-  desc.componentSubType = CUBEB_AUDIOUNIT_SUBTYPE;
++#if TARGET_OS_IPHONE
++  desc.componentSubType = kAudioUnitSubType_RemoteIO;
++#else
++  // Use the DefaultOutputUnit for output when no device is specified
++  // so we retain automatic output device switching when the default
++  // changes.  Once we have complete support for device notifications
++  // and switching, we can use the AUHAL for everything.
++  use_default_output = device == NULL && !is_input;
++  if (use_default_output) {
++    desc.componentSubType = kAudioUnitSubType_DefaultOutput;
++  } else {
++    desc.componentSubType = kAudioUnitSubType_HALOutput;
++  }
++#endif
+   desc.componentManufacturer = kAudioUnitManufacturer_Apple;
+   desc.componentFlags = 0;
+   desc.componentFlagsMask = 0;
+   comp = AudioComponentFindNext(NULL, &desc);
+   if (comp == NULL) {
+     return CUBEB_ERROR;
+   }
+ 
+   if (AudioComponentInstanceNew(comp, unit) != 0) {
+     return CUBEB_ERROR;
+   }
+ 
+-  enable = 1;
+-  if (AudioUnitSetProperty(*unit, kAudioOutputUnitProperty_EnableIO,
+-        is_input ? kAudioUnitScope_Input : kAudioUnitScope_Output,
+-        is_input ? AU_IN_BUS : AU_OUT_BUS, &enable, sizeof(UInt32)) != noErr) {
+-    return CUBEB_ERROR;
+-  }
++  if (!use_default_output) {
++    enable = 1;
++    if (AudioUnitSetProperty(*unit, kAudioOutputUnitProperty_EnableIO,
++                             is_input ? kAudioUnitScope_Input : kAudioUnitScope_Output,
++                             is_input ? AU_IN_BUS : AU_OUT_BUS, &enable, sizeof(UInt32)) != noErr) {
++      return CUBEB_ERROR;
++    }
+ 
+-  enable = 0;
+-  if (AudioUnitSetProperty(*unit, kAudioOutputUnitProperty_EnableIO,
+-        is_input ? kAudioUnitScope_Output : kAudioUnitScope_Input,
+-        is_input ? AU_OUT_BUS : AU_IN_BUS, &enable, sizeof(UInt32)) != noErr) {
+-    return CUBEB_ERROR;
+-  }
++    enable = 0;
++    if (AudioUnitSetProperty(*unit, kAudioOutputUnitProperty_EnableIO,
++                             is_input ? kAudioUnitScope_Output : kAudioUnitScope_Input,
++                             is_input ? AU_OUT_BUS : AU_IN_BUS, &enable, sizeof(UInt32)) != noErr) {
++      return CUBEB_ERROR;
++    }
+ 
+-  if (device == NULL) {
+-    devid = audiounit_get_default_device_id(is_input ? CUBEB_DEVICE_TYPE_INPUT
+-                                                     : CUBEB_DEVICE_TYPE_OUTPUT);
+-  } else {
+-    devid = (AudioDeviceID)device;
+-  }
+-  int err = AudioUnitSetProperty(*unit, kAudioOutputUnitProperty_CurrentDevice,
+-                                 kAudioUnitScope_Global,
+-                                 is_input ? AU_IN_BUS : AU_OUT_BUS,
+-                                 &devid, sizeof(AudioDeviceID));
+-  if (err != noErr) {
+-    return CUBEB_ERROR;
++    if (device == NULL) {
++      assert(is_input);
++      devid = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_INPUT);
++    } else {
++      devid = (AudioDeviceID)device;
++    }
++    int err = AudioUnitSetProperty(*unit, kAudioOutputUnitProperty_CurrentDevice,
++                                   kAudioUnitScope_Global,
++                                   is_input ? AU_IN_BUS : AU_OUT_BUS,
++                                   &devid, sizeof(AudioDeviceID));
++    if (err != noErr) {
++      return CUBEB_ERROR;
++    }
+   }
+ 
+   return CUBEB_OK;
+ }
+ 
+ static int
+ audiounit_init_input_buffer_array(cubeb_stream * stream, uint32_t capacity)
+ {
--- a/media/libcubeb/src/cubeb_audiounit.c
+++ b/media/libcubeb/src/cubeb_audiounit.c
@@ -45,22 +45,16 @@
 typedef UInt32  AudioFormatFlags;
 #endif
 
 #define CUBEB_STREAM_MAX 8
 
 #define AU_OUT_BUS    0
 #define AU_IN_BUS     1
 
-#if TARGET_OS_IPHONE
-#define CUBEB_AUDIOUNIT_SUBTYPE kAudioUnitSubType_RemoteIO
-#else
-#define CUBEB_AUDIOUNIT_SUBTYPE kAudioUnitSubType_HALOutput
-#endif
-
 //#define LOGGING_ENABLED
 #ifdef LOGGING_ENABLED
 #define LOG(...) do {                           \
     fprintf(stderr, __VA_ARGS__);               \
   } while(0)
 #else
 #define LOG(...)
 #endif
@@ -824,57 +818,73 @@ audiounit_create_unit(AudioUnit * unit,
                       bool is_input,
                       const cubeb_stream_params * stream_params,
                       cubeb_devid device)
 {
   AudioComponentDescription desc;
   AudioComponent comp;
   UInt32 enable;
   AudioDeviceID devid;
+  bool use_default_output = false;
 
   desc.componentType = kAudioUnitType_Output;
-  desc.componentSubType = CUBEB_AUDIOUNIT_SUBTYPE;
+#if TARGET_OS_IPHONE
+  desc.componentSubType = kAudioUnitSubType_RemoteIO;
+#else
+  // Use the DefaultOutputUnit for output when no device is specified
+  // so we retain automatic output device switching when the default
+  // changes.  Once we have complete support for device notifications
+  // and switching, we can use the AUHAL for everything.
+  use_default_output = device == NULL && !is_input;
+  if (use_default_output) {
+    desc.componentSubType = kAudioUnitSubType_DefaultOutput;
+  } else {
+    desc.componentSubType = kAudioUnitSubType_HALOutput;
+  }
+#endif
   desc.componentManufacturer = kAudioUnitManufacturer_Apple;
   desc.componentFlags = 0;
   desc.componentFlagsMask = 0;
   comp = AudioComponentFindNext(NULL, &desc);
   if (comp == NULL) {
     return CUBEB_ERROR;
   }
 
   if (AudioComponentInstanceNew(comp, unit) != 0) {
     return CUBEB_ERROR;
   }
 
-  enable = 1;
-  if (AudioUnitSetProperty(*unit, kAudioOutputUnitProperty_EnableIO,
-        is_input ? kAudioUnitScope_Input : kAudioUnitScope_Output,
-        is_input ? AU_IN_BUS : AU_OUT_BUS, &enable, sizeof(UInt32)) != noErr) {
-    return CUBEB_ERROR;
-  }
+  if (!use_default_output) {
+    enable = 1;
+    if (AudioUnitSetProperty(*unit, kAudioOutputUnitProperty_EnableIO,
+                             is_input ? kAudioUnitScope_Input : kAudioUnitScope_Output,
+                             is_input ? AU_IN_BUS : AU_OUT_BUS, &enable, sizeof(UInt32)) != noErr) {
+      return CUBEB_ERROR;
+    }
 
-  enable = 0;
-  if (AudioUnitSetProperty(*unit, kAudioOutputUnitProperty_EnableIO,
-        is_input ? kAudioUnitScope_Output : kAudioUnitScope_Input,
-        is_input ? AU_OUT_BUS : AU_IN_BUS, &enable, sizeof(UInt32)) != noErr) {
-    return CUBEB_ERROR;
-  }
+    enable = 0;
+    if (AudioUnitSetProperty(*unit, kAudioOutputUnitProperty_EnableIO,
+                             is_input ? kAudioUnitScope_Output : kAudioUnitScope_Input,
+                             is_input ? AU_OUT_BUS : AU_IN_BUS, &enable, sizeof(UInt32)) != noErr) {
+      return CUBEB_ERROR;
+    }
 
-  if (device == NULL) {
-    devid = audiounit_get_default_device_id(is_input ? CUBEB_DEVICE_TYPE_INPUT
-                                                     : CUBEB_DEVICE_TYPE_OUTPUT);
-  } else {
-    devid = (AudioDeviceID)device;
-  }
-  int err = AudioUnitSetProperty(*unit, kAudioOutputUnitProperty_CurrentDevice,
-                                 kAudioUnitScope_Global,
-                                 is_input ? AU_IN_BUS : AU_OUT_BUS,
-                                 &devid, sizeof(AudioDeviceID));
-  if (err != noErr) {
-    return CUBEB_ERROR;
+    if (device == NULL) {
+      assert(is_input);
+      devid = audiounit_get_default_device_id(CUBEB_DEVICE_TYPE_INPUT);
+    } else {
+      devid = (AudioDeviceID)device;
+    }
+    int err = AudioUnitSetProperty(*unit, kAudioOutputUnitProperty_CurrentDevice,
+                                   kAudioUnitScope_Global,
+                                   is_input ? AU_IN_BUS : AU_OUT_BUS,
+                                   &devid, sizeof(AudioDeviceID));
+    if (err != noErr) {
+      return CUBEB_ERROR;
+    }
   }
 
   return CUBEB_OK;
 }
 
 static int
 audiounit_init_input_buffer_array(cubeb_stream * stream, uint32_t capacity)
 {
--- a/media/libcubeb/update.sh
+++ b/media/libcubeb/update.sh
@@ -48,8 +48,10 @@ if [ -n "$rev" ]; then
     echo "WARNING: updating from a dirty git repository."
   fi
   sed -i.bak -e "/The git commit ID used was/ s/[0-9a-f]\{40\}\(-dirty\)\{0,1\}\./$version./" README_MOZILLA
   rm README_MOZILLA.bak
 else
   echo "Remember to update README_MOZILLA with the version details."
 fi
 
+patch -p3 < bug1278612.patch
+