Bug 1027713 - Part 2 - Add a cubeb API to query the name of the audio output device in use. r=kinetik
☠☠ backed out by 5dc0231d0153 ☠ ☠
authorPaul Adenot <paul@paul.cx>
Thu, 24 Jul 2014 17:05:23 +0200
changeset 196015 274b2b25d167f8fccfd0d4dc034e5392f09cec9f
parent 196014 e0bba6f4966fe87744e042273d404a67f3d8225e
child 196016 c0045bb1849ed7cbe7e06c92318a8e7b01314428
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewerskinetik
bugs1027713
milestone34.0a1
Bug 1027713 - Part 2 - Add a cubeb API to query the name of the audio output device in use. r=kinetik
layout/media/symbols.def.in
media/libcubeb/include/cubeb.h
media/libcubeb/src/cubeb-internal.h
media/libcubeb/src/cubeb.c
media/libcubeb/src/cubeb_alsa.c
media/libcubeb/src/cubeb_audiotrack.c
media/libcubeb/src/cubeb_audiounit.c
media/libcubeb/src/cubeb_opensl.c
media/libcubeb/src/cubeb_pulse.c
media/libcubeb/src/cubeb_sndio.c
media/libcubeb/src/cubeb_wasapi.cpp
media/libcubeb/src/cubeb_winmm.c
--- a/layout/media/symbols.def.in
+++ b/layout/media/symbols.def.in
@@ -132,16 +132,18 @@ cubeb_get_preferred_sample_rate
 cubeb_stream_destroy
 cubeb_stream_get_position
 cubeb_stream_init
 cubeb_stream_start
 cubeb_stream_stop
 cubeb_stream_get_latency
 cubeb_stream_set_volume
 cubeb_stream_set_panning
+cubeb_stream_get_current_output_device
+cubeb_stream_output_device_destroy
 th_comment_clear
 th_comment_init
 th_decode_alloc
 th_decode_free
 th_decode_headerin
 th_decode_packetin
 th_decode_ycbcr_out
 th_granule_frame
--- a/media/libcubeb/include/cubeb.h
+++ b/media/libcubeb/include/cubeb.h
@@ -124,16 +124,21 @@ typedef struct {
                                    #cubeb_sample_format. */
   unsigned int rate;          /**< Requested sample rate.  Valid range is [1, 192000]. */
   unsigned int channels;      /**< Requested channel count.  Valid range is [1, 32]. */
 #if defined(__ANDROID__)
   cubeb_stream_type stream_type; /**< Used to map Android audio stream types */
 #endif
 } cubeb_stream_params;
 
+/** Output device description */
+typedef struct {
+  char * name; /**< The name of the output device */
+} cubeb_output_device;
+
 /** Stream states signaled via state_callback. */
 typedef enum {
   CUBEB_STATE_STARTED, /**< Stream started. */
   CUBEB_STATE_STOPPED, /**< Stream stopped. */
   CUBEB_STATE_DRAINED, /**< Stream drained. */
   CUBEB_STATE_ERROR    /**< Stream disabled due to error. */
 } cubeb_state;
 
@@ -280,13 +285,34 @@ int cubeb_stream_set_volume(cubeb_stream
  * channel. 0.0 is equal power in the right and left channel (default).
  * @return CUBEB_ERROR_INVALID_PARAMETER if stream is null or if panning is outside
  * the [-1.0; 1.0] range.
  * @return CUBEB_ERROR if this stream is not mono nor stereo.
  * @return CUBEB_OK otherwise.
  */
 int cubeb_stream_set_panning(cubeb_stream * stream, float panning);
 
+/**
+ * Get the current output device for this stream.
+ * @param stm the stream for which to query the current output device
+ * @param device a pointer in which the current output device will be stored.
+ * @return CUBEB_OK in case of success
+ * @return CUBEB_ERROR_INVALID_PARAMETER if either stm, device or count are
+ *         invalid pointers
+ */
+int cubeb_stream_get_current_output_device(cubeb_stream * stm,
+                                           cubeb_output_device ** const device);
+
+/**
+ * Destroy a cubeb_output_device structure.
+ * @param stream the stream passed in cubeb_stream_get_current_output_device
+ * @param devices the devices to destroy
+ * @return CUBEB_OK in case of success
+ * @return CUBEB_ERROR_INVALID_PARAMETER if devices is an invalid pointer
+ */
+int cubeb_stream_output_device_destroy(cubeb_stream * stream,
+                                       cubeb_output_device * devices);
+
 #if defined(__cplusplus)
 }
 #endif
 
 #endif /* CUBEB_c2f983e9_c96f_e71c_72c3_bbf62992a382 */
--- a/media/libcubeb/src/cubeb-internal.h
+++ b/media/libcubeb/src/cubeb-internal.h
@@ -25,11 +25,16 @@ struct cubeb_ops {
                       void * user_ptr);
   void (* stream_destroy)(cubeb_stream * stream);
   int (* stream_start)(cubeb_stream * stream);
   int (* stream_stop)(cubeb_stream * stream);
   int (* stream_get_position)(cubeb_stream * stream, uint64_t * position);
   int (* stream_get_latency)(cubeb_stream * stream, uint32_t * latency);
   int (* stream_set_volume)(cubeb_stream * stream, float volumes);
   int (* stream_set_panning)(cubeb_stream * stream, float panning);
+  int (* stream_get_current_output_device)(cubeb_stream * stream,
+                                           cubeb_output_device ** const device);
+  int (* stream_output_device_destroy)(cubeb_stream * stream,
+                                       cubeb_output_device * device);
 };
 
 #endif /* CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5 */
+
--- a/media/libcubeb/src/cubeb.c
+++ b/media/libcubeb/src/cubeb.c
@@ -272,8 +272,41 @@ cubeb_stream_set_volume(cubeb_stream * s
 int cubeb_stream_set_panning(cubeb_stream * stream, float panning)
 {
   if (!stream || panning < -1.0 || panning > 1.0) {
     return CUBEB_ERROR_INVALID_PARAMETER;
   }
 
   return stream->context->ops->stream_set_panning(stream, panning);
 }
+
+int cubeb_stream_get_current_output_device(cubeb_stream * stream,
+                                           cubeb_output_device ** const device)
+{
+  if (!stream || !device) {
+    return CUBEB_ERROR_INVALID_PARAMETER;
+  }
+
+  // If we find an implementation, call the function, it might not be available
+  // on some platforms.
+  if (stream->context->ops->stream_get_current_output_device) {
+    return stream->context->ops->stream_get_current_output_device(stream,
+                                                                  device);
+  }
+
+  return CUBEB_ERROR;
+}
+
+int cubeb_stream_output_device_destroy(cubeb_stream * stream,
+                                       cubeb_output_device * device)
+{
+  if (!stream || !device) {
+    return CUBEB_ERROR_INVALID_PARAMETER;
+  }
+
+  // If we find an implementation, call the function, it might not be available
+  // on some platforms.
+  if (stream->context->ops->stream_output_device_destroy) {
+    return stream->context->ops->stream_output_device_destroy(stream, device);
+  }
+
+  return CUBEB_ERROR;
+}
--- a/media/libcubeb/src/cubeb_alsa.c
+++ b/media/libcubeb/src/cubeb_alsa.c
@@ -1125,10 +1125,12 @@ static struct cubeb_ops const alsa_ops =
   .destroy = alsa_destroy,
   .stream_init = alsa_stream_init,
   .stream_destroy = alsa_stream_destroy,
   .stream_start = alsa_stream_start,
   .stream_stop = alsa_stream_stop,
   .stream_get_position = alsa_stream_get_position,
   .stream_get_latency = alsa_stream_get_latency,
   .stream_set_volume = alsa_stream_set_volume,
-  .stream_set_panning = alsa_stream_set_panning
+  .stream_set_panning = alsa_stream_set_panning,
+  .stream_get_current_output_device = NULL,
+  .stream_output_device_destroy = NULL
 };
--- a/media/libcubeb/src/cubeb_audiotrack.c
+++ b/media/libcubeb/src/cubeb_audiotrack.c
@@ -499,10 +499,12 @@ static struct cubeb_ops const audiotrack
   .destroy = audiotrack_destroy,
   .stream_init = audiotrack_stream_init,
   .stream_destroy = audiotrack_stream_destroy,
   .stream_start = audiotrack_stream_start,
   .stream_stop = audiotrack_stream_stop,
   .stream_get_position = audiotrack_stream_get_position,
   .stream_get_latency = audiotrack_stream_get_latency,
   .stream_set_volume = audiotrack_stream_set_volume,
-  .stream_set_panning = audiotrack_stream_set_panning
+  .stream_set_panning = audiotrack_stream_set_panning,
+  .stream_get_current_output_device = NULL,
+  .stream_output_device_destroy = NULL
 };
--- a/media/libcubeb/src/cubeb_audiounit.c
+++ b/media/libcubeb/src/cubeb_audiounit.c
@@ -649,24 +649,85 @@ int audiounit_stream_set_panning(cubeb_s
 
   pthread_mutex_lock(&stm->mutex);
   stm->panning = panning;
   pthread_mutex_unlock(&stm->mutex);
 
   return CUBEB_OK;
 }
 
+int audiounit_stream_get_current_output_device(cubeb_stream * stm,
+                                               cubeb_output_device ** const  device)
+{
+  OSStatus r;
+  uint32_t size;
+  UInt32 data;
+  char strdata[4];
+  AudioDeviceID output_device_id;
+
+  AudioObjectPropertyAddress datasource_address = {
+    kAudioDevicePropertyDataSource,
+    kAudioDevicePropertyScopeOutput,
+    kAudioObjectPropertyElementMaster
+  };
+
+  *device = NULL;
+
+  if (audiounit_get_output_device_id(&output_device_id) != CUBEB_OK) {
+    return CUBEB_ERROR;
+  }
+
+  size = sizeof(UInt32);
+  /* This fails with some USB headset, so simply return an empty string. */
+  r = AudioObjectGetPropertyData(output_device_id, &datasource_address, 0, NULL, &size, &data);
+  if (r != noErr) {
+    size = 0;
+    data = 0;
+  }
+
+  *device = malloc(sizeof(cubeb_output_device));
+  if (!*device) {
+    return CUBEB_ERROR;
+  }
+
+  (*device)->name = malloc(size + 1);
+  if (!(*device)->name) {
+    return CUBEB_ERROR;
+  }
+
+  // Turn the four chars packed into a uint32 into a string
+  strdata[0] = (char)(data >> 24);
+  strdata[1] = (char)(data >> 16);
+  strdata[2] = (char)(data >> 8);
+  strdata[3] = (char)(data);
+
+  memcpy((*device)->name, strdata, size);
+  (*device)->name[size] = '\0';
+
+  return CUBEB_OK;
+}
+
+int audiounit_stream_output_device_destroy(cubeb_stream * stream,
+                                           cubeb_output_device * device)
+{
+  free(device->name);
+  free(device);
+  return CUBEB_OK;
+}
+
 static struct cubeb_ops const audiounit_ops = {
   .init = audiounit_init,
   .get_backend_id = audiounit_get_backend_id,
   .get_max_channel_count = audiounit_get_max_channel_count,
   .get_min_latency = audiounit_get_min_latency,
   .get_preferred_sample_rate = audiounit_get_preferred_sample_rate,
   .destroy = audiounit_destroy,
   .stream_init = audiounit_stream_init,
   .stream_destroy = audiounit_stream_destroy,
   .stream_start = audiounit_stream_start,
   .stream_stop = audiounit_stream_stop,
   .stream_get_position = audiounit_stream_get_position,
   .stream_get_latency = audiounit_stream_get_latency,
   .stream_set_volume = audiounit_stream_set_volume,
-  .stream_set_panning = audiounit_stream_set_panning
+  .stream_set_panning = audiounit_stream_set_panning,
+  .stream_get_current_output_device = audiounit_stream_get_current_output_device,
+  .stream_output_device_destroy = audiounit_stream_output_device_destroy
 };
--- a/media/libcubeb/src/cubeb_opensl.c
+++ b/media/libcubeb/src/cubeb_opensl.c
@@ -782,10 +782,12 @@ static struct cubeb_ops const opensl_ops
   .destroy = opensl_destroy,
   .stream_init = opensl_stream_init,
   .stream_destroy = opensl_stream_destroy,
   .stream_start = opensl_stream_start,
   .stream_stop = opensl_stream_stop,
   .stream_get_position = opensl_stream_get_position,
   .stream_get_latency = opensl_stream_get_latency,
   .stream_set_volume = opensl_stream_set_volume,
-  .stream_set_panning = opensl_stream_set_panning
+  .stream_set_panning = opensl_stream_set_panning,
+  .stream_get_current_output_device = NULL,
+  .stream_output_device_destroy = NULL
 };
--- a/media/libcubeb/src/cubeb_pulse.c
+++ b/media/libcubeb/src/cubeb_pulse.c
@@ -743,10 +743,12 @@ static struct cubeb_ops const pulse_ops 
   .destroy = pulse_destroy,
   .stream_init = pulse_stream_init,
   .stream_destroy = pulse_stream_destroy,
   .stream_start = pulse_stream_start,
   .stream_stop = pulse_stream_stop,
   .stream_get_position = pulse_stream_get_position,
   .stream_get_latency = pulse_stream_get_latency,
   .stream_set_volume = pulse_stream_set_volume,
-  .stream_set_panning = pulse_stream_set_panning
+  .stream_set_panning = pulse_stream_set_panning,
+  .stream_get_current_output_device = NULL,
+  .stream_output_device_destroy = NULL
 };
--- a/media/libcubeb/src/cubeb_sndio.c
+++ b/media/libcubeb/src/cubeb_sndio.c
@@ -356,10 +356,12 @@ static struct cubeb_ops const sndio_ops 
   .destroy = sndio_destroy,
   .stream_init = sndio_stream_init,
   .stream_destroy = sndio_stream_destroy,
   .stream_start = sndio_stream_start,
   .stream_stop = sndio_stream_stop,
   .stream_get_position = sndio_stream_get_position,
   .stream_get_latency = sndio_stream_get_latency,
   .stream_set_volume = sndio_stream_set_volume,
-  .stream_set_panning = sndio_stream_set_panning
+  .stream_set_panning = sndio_stream_set_panning,
+  .stream_get_current_output_device = NULL,
+  .stream_output_device_destroy = NULL
 };
--- a/media/libcubeb/src/cubeb_wasapi.cpp
+++ b/media/libcubeb/src/cubeb_wasapi.cpp
@@ -934,12 +934,14 @@ cubeb_ops const wasapi_ops = {
   /*.destroy =*/ wasapi_destroy,
   /*.stream_init =*/ wasapi_stream_init,
   /*.stream_destroy =*/ wasapi_stream_destroy,
   /*.stream_start =*/ wasapi_stream_start,
   /*.stream_stop =*/ wasapi_stream_stop,
   /*.stream_get_position =*/ wasapi_stream_get_position,
   /*.stream_get_latency =*/ wasapi_stream_get_latency,
   /*.stream_set_volume =*/ wasapi_stream_set_volume,
-  /*.stream_set_panning =*/ wasapi_stream_set_panning
+  /*.stream_set_panning =*/ wasapi_stream_set_panning,
+  /*.stream_get_current_output_device =*/ NULL,
+  /*.stream_output_device_destroy =*/ NULL
  };
 } // namespace anonymous
 
--- a/media/libcubeb/src/cubeb_winmm.c
+++ b/media/libcubeb/src/cubeb_winmm.c
@@ -709,10 +709,12 @@ static struct cubeb_ops const winmm_ops 
   /*.destroy =*/ winmm_destroy,
   /*.stream_init =*/ winmm_stream_init,
   /*.stream_destroy =*/ winmm_stream_destroy,
   /*.stream_start =*/ winmm_stream_start,
   /*.stream_stop =*/ winmm_stream_stop,
   /*.stream_get_position =*/ winmm_stream_get_position,
   /*.stream_get_latency = */ winmm_stream_get_latency,
   /*.stream_set_volume =*/ winmm_stream_set_volume,
-  /*.stream_set_panning =*/ winmm_stream_set_panning
+  /*.stream_set_panning =*/ winmm_stream_set_panning,
+  /*.stream_get_current_output_device =*/ NULL,
+  /*.stream_output_device_destroy =*/ NULL
 };