Bug 1266753 - Update cubeb to revision dbdfb to pick up OSX device notification changes. r=padenot
authorAlex Chronopoulos <achronop@gmail.com>
Fri, 22 Apr 2016 16:36:39 +0200
changeset 332429 333ca1faed5a9d1672c26b10d41f5593996325dc
parent 332428 099d4414bd63296d586699b6e2b9bae068a4c4eb
child 332430 8045e15106d71d8267ca52b75d51b70851143136
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1266753
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1266753 - Update cubeb to revision dbdfb to pick up OSX device notification changes. r=padenot MozReview-Commit-ID: 7N66FmG9P5u
media/libcubeb/README_MOZILLA
media/libcubeb/src/cubeb.c
media/libcubeb/src/cubeb_audiounit.c
--- a/media/libcubeb/README_MOZILLA
+++ b/media/libcubeb/README_MOZILLA
@@ -1,8 +1,8 @@
 The source from this directory was copied from the cubeb 
 git repository using the update.sh script.  The only changes
 made were those applied by update.sh and the addition of
 Makefile.in build files for the Mozilla build system.
 
 The cubeb git repository is: git://github.com/kinetiknz/cubeb.git
 
-The git commit ID used was 0bc02f9f34dc8c39175157daf770d522ec160a64.
+The git commit ID used was dbdfb3904deb7a0381588209cdd7388217d96e61.
--- a/media/libcubeb/src/cubeb.c
+++ b/media/libcubeb/src/cubeb.c
@@ -379,17 +379,17 @@ int cubeb_stream_device_destroy(cubeb_st
   }
 
   return stream->context->ops->stream_device_destroy(stream, device);
 }
 
 int cubeb_stream_register_device_changed_callback(cubeb_stream * stream,
                                                   cubeb_device_changed_callback device_changed_callback)
 {
-  if (!stream || !device_changed_callback) {
+  if (!stream) {
     return CUBEB_ERROR_INVALID_PARAMETER;
   }
 
   if (!stream->context->ops->stream_register_device_changed_callback) {
     return CUBEB_ERROR_NOT_SUPPORTED;
   }
 
   return stream->context->ops->stream_register_device_changed_callback(stream, device_changed_callback);
--- a/media/libcubeb/src/cubeb_audiounit.c
+++ b/media/libcubeb/src/cubeb_audiounit.c
@@ -435,127 +435,170 @@ audiounit_get_input_device_id(AudioDevic
                                  device_id);
   if (r != noErr) {
     return CUBEB_ERROR;
   }
 
   return CUBEB_OK;
 }
 
-static int audiounit_install_device_changed_callback(cubeb_stream * stm);
-static int audiounit_uninstall_device_changed_callback();
-
 static OSStatus
 audiounit_property_listener_callback(AudioObjectID id, UInt32 address_count,
                                      const AudioObjectPropertyAddress * addresses,
                                      void * user)
 {
   cubeb_stream * stm = (cubeb_stream*) user;
 
   for (UInt32 i = 0; i < address_count; i++) {
     switch(addresses[i].mSelector) {
     case kAudioHardwarePropertyDefaultOutputDevice:
+    case kAudioHardwarePropertyDefaultInputDevice:
       /* fall through */
     case kAudioDevicePropertyDataSource:
       pthread_mutex_lock(&stm->mutex);
       if (stm->device_changed_callback) {
         stm->device_changed_callback(stm->user_ptr);
       }
       pthread_mutex_unlock(&stm->mutex);
       break;
     }
   }
 
   return noErr;
 }
 
+OSStatus
+audiounit_add_listener(cubeb_stream * stm, AudioDeviceID id, AudioObjectPropertySelector selector,
+    AudioObjectPropertyScope scope, AudioObjectPropertyListenerProc listener)
+{
+  AudioObjectPropertyAddress address = {
+      selector,
+      scope,
+      kAudioObjectPropertyElementMaster
+  };
+
+  return AudioObjectAddPropertyListener(id, &address, listener, stm);
+}
+
+OSStatus
+audiounit_remove_listener(cubeb_stream * stm, AudioDeviceID id,
+                          AudioObjectPropertySelector selector,
+                          AudioObjectPropertyScope scope,
+                          AudioObjectPropertyListenerProc listener)
+{
+  AudioObjectPropertyAddress address = {
+      selector,
+      scope,
+      kAudioObjectPropertyElementMaster
+  };
+
+  return AudioObjectRemovePropertyListener(id, &address, listener, stm);
+}
+
 static int
 audiounit_install_device_changed_callback(cubeb_stream * stm)
 {
   OSStatus r;
-  AudioDeviceID id;
+
+  if (stm->output_unit) {
+    /* This event will notify us when the data source on the same device changes,
+     * for example when the user plugs in a normal (non-usb) headset in the
+     * headphone jack. */
+    AudioDeviceID output_dev_id;
+    r = audiounit_get_output_device_id(&output_dev_id);
+    if (r != noErr) {
+      return CUBEB_ERROR;
+    }
 
-  /* This event will notify us when the data source on the same device changes,
-   * for example when the user plugs in a normal (non-usb) headset in the
-   * headphone jack. */
-  AudioObjectPropertyAddress alive_address = {
-    kAudioDevicePropertyDataSource,
-    kAudioObjectPropertyScopeGlobal,
-    kAudioObjectPropertyElementMaster
-  };
+    r = audiounit_add_listener(stm, output_dev_id, kAudioDevicePropertyDataSource,
+        kAudioObjectPropertyScopeOutput, &audiounit_property_listener_callback);
+    if (r != noErr) {
+      return CUBEB_ERROR;
+    }
 
-  if (audiounit_get_output_device_id(&id) != noErr) {
-    return CUBEB_ERROR;
+    /* This event will notify us when the default audio device changes,
+     * for example when the user plugs in a USB headset and the system chooses it
+     * automatically as the default, or when another device is chosen in the
+     * dropdown list. */
+    r = audiounit_add_listener(stm, kAudioObjectSystemObject, kAudioHardwarePropertyDefaultOutputDevice,
+        kAudioObjectPropertyScopeGlobal, &audiounit_property_listener_callback);
+    if (r != noErr) {
+      return CUBEB_ERROR;
+    }
   }
 
-  r = AudioObjectAddPropertyListener(id, &alive_address,
-                                     &audiounit_property_listener_callback,
-                                     stm);
-  if (r != noErr) {
-    return CUBEB_ERROR;
-  }
+  if (stm->input_unit) {
+    /* This event will notify us when the data source on the input device changes. */
+    AudioDeviceID input_dev_id;
+    r = audiounit_get_input_device_id(&input_dev_id);
+    if (r != noErr) {
+      return CUBEB_ERROR;
+    }
 
-  /* This event will notify us when the default audio device changes,
-   * for example when the user plugs in a USB headset and the system chooses it
-   * automatically as the default, or when another device is chosen in the
-   * dropdown list. */
-  AudioObjectPropertyAddress default_device_address = {
-    kAudioHardwarePropertyDefaultOutputDevice,
-    kAudioObjectPropertyScopeGlobal,
-    kAudioObjectPropertyElementMaster
-  };
+    r = audiounit_add_listener(stm, input_dev_id, kAudioDevicePropertyDataSource,
+        kAudioObjectPropertyScopeInput, &audiounit_property_listener_callback);
+    if (r != noErr) {
+      return CUBEB_ERROR;
+    }
 
-  r = AudioObjectAddPropertyListener(kAudioObjectSystemObject,
-                                     &default_device_address,
-                                     &audiounit_property_listener_callback,
-                                     stm);
-  if (r != noErr) {
-    return CUBEB_ERROR;
+    /* This event will notify us when the default input device changes. */
+    r = audiounit_add_listener(stm, kAudioObjectSystemObject, kAudioHardwarePropertyDefaultInputDevice,
+        kAudioObjectPropertyScopeGlobal, &audiounit_property_listener_callback);
+    if (r != noErr) {
+      return CUBEB_ERROR;
+    }
   }
 
   return CUBEB_OK;
 }
 
 static int
 audiounit_uninstall_device_changed_callback(cubeb_stream * stm)
 {
   OSStatus r;
-  AudioDeviceID id;
+
+  if (stm->output_unit) {
+    AudioDeviceID output_dev_id;
+    r = audiounit_get_output_device_id(&output_dev_id);
+    if (r != noErr) {
+      return CUBEB_ERROR;
+    }
 
-  AudioObjectPropertyAddress datasource_address = {
-    kAudioDevicePropertyDataSource,
-    kAudioObjectPropertyScopeGlobal,
-    kAudioObjectPropertyElementMaster
-  };
+    r = audiounit_remove_listener(stm, output_dev_id, kAudioDevicePropertyDataSource,
+        kAudioObjectPropertyScopeOutput, &audiounit_property_listener_callback);
+    if (r != noErr) {
+      return CUBEB_ERROR;
+    }
 
-  if (audiounit_get_output_device_id(&id) != noErr) {
-    return CUBEB_ERROR;
+    r = audiounit_remove_listener(stm, kAudioObjectSystemObject, kAudioHardwarePropertyDefaultOutputDevice,
+        kAudioObjectPropertyScopeGlobal, &audiounit_property_listener_callback);
+    if (r != noErr) {
+      return CUBEB_ERROR;
+    }
   }
 
-  r = AudioObjectRemovePropertyListener(id, &datasource_address,
-                                        &audiounit_property_listener_callback,
-                                        stm);
-  if (r != noErr) {
-    return CUBEB_ERROR;
-  }
+  if (stm->input_unit) {
+    AudioDeviceID input_dev_id;
+    r = audiounit_get_input_device_id(&input_dev_id);
+    if (r != noErr) {
+      return CUBEB_ERROR;
+    }
 
-  AudioObjectPropertyAddress default_device_address = {
-    kAudioHardwarePropertyDefaultOutputDevice,
-    kAudioObjectPropertyScopeGlobal,
-    kAudioObjectPropertyElementMaster
-  };
+    r = audiounit_remove_listener(stm, input_dev_id, kAudioDevicePropertyDataSource,
+        kAudioObjectPropertyScopeInput, &audiounit_property_listener_callback);
+    if (r != noErr) {
+      return CUBEB_ERROR;
+    }
 
-  r = AudioObjectRemovePropertyListener(kAudioObjectSystemObject,
-                                        &default_device_address,
-                                        &audiounit_property_listener_callback,
-                                        stm);
-  if (r != noErr) {
-    return CUBEB_ERROR;
+    r = audiounit_remove_listener(stm, kAudioObjectSystemObject, kAudioHardwarePropertyDefaultInputDevice,
+        kAudioObjectPropertyScopeGlobal, &audiounit_property_listener_callback);
+    if (r != noErr) {
+      return CUBEB_ERROR;
+    }
   }
-
   return CUBEB_OK;
 }
 
 /* Get the acceptable buffer size (in frames) that this device can work with. */
 static int
 audiounit_get_acceptable_latency_range(AudioValueRange * latency_range)
 {
   UInt32 size;
@@ -1135,22 +1178,16 @@ audiounit_stream_init(cubeb * context,
   }
   if (stm->output_unit != NULL &&
       AudioUnitInitialize(stm->output_unit) != 0) {
     audiounit_stream_destroy(stm);
     return CUBEB_ERROR;
   }
 
   *stream = stm;
-
-#if !TARGET_OS_IPHONE
-  /* we dont' check the return value here, because we want to be able to play
-   * even if we can't detect device changes. */
-  audiounit_install_device_changed_callback(stm);
-#endif
   LOG("Cubeb stream init successfully.\n");
   return CUBEB_OK;
 }
 
 static void
 audiounit_stream_destroy(cubeb_stream * stm)
 {
   stm->shutdown = 1;
@@ -1441,21 +1478,33 @@ int audiounit_stream_device_destroy(cube
   free(device->input_name);
   free(device);
   return CUBEB_OK;
 }
 
 int audiounit_stream_register_device_changed_callback(cubeb_stream * stream,
                                                       cubeb_device_changed_callback  device_changed_callback)
 {
+  /* Note: second register without unregister first causes 'nope' error.
+   * Current implementation requires unregister before register a new cb. */
+  assert(!stream->device_changed_callback);
+
   pthread_mutex_lock(&stream->mutex);
   stream->device_changed_callback = device_changed_callback;
+  int r = CUBEB_OK;
+#if !TARGET_OS_IPHONE
+  if (device_changed_callback) {
+    r = audiounit_install_device_changed_callback(stream);
+  } else {
+    r = audiounit_uninstall_device_changed_callback(stream);
+  }
+#endif
   pthread_mutex_unlock(&stream->mutex);
 
-  return CUBEB_OK;
+  return r;
 }
 
 static OSStatus
 audiounit_get_devices(AudioObjectID ** devices, uint32_t * count)
 {
   OSStatus ret;
   UInt32 size = 0;
   AudioObjectPropertyAddress adr = { kAudioHardwarePropertyDevices,