sys/osxaudio/: Rewrite caps setting and ring buffer initialisation.
authorMichael Smith <msmith@xiph.org>
Tue, 26 Aug 2008 21:13:08 +0000 (21:13 +0000)
committerMichael Smith <msmith@xiph.org>
Tue, 26 Aug 2008 21:13:08 +0000 (21:13 +0000)
Original commit message from CVS:
* sys/osxaudio/Makefile.am:
* sys/osxaudio/gstosxaudio.c:
* sys/osxaudio/gstosxaudiosink.c:
* sys/osxaudio/gstosxaudiosink.h:
* sys/osxaudio/gstosxaudiosrc.c:
* sys/osxaudio/gstosxaudiosrc.h:
* sys/osxaudio/gstosxringbuffer.c:
* sys/osxaudio/gstosxringbuffer.h:
Rewrite caps setting and ring buffer initialisation.
Previously we never told CoreAudio what format we were going to send it,
so it only worked due to luck, and not at all on some hardware.
Now we explicitly advertise what formats the hardware supports, and then
configure the selected one correctly.

ChangeLog
sys/osxaudio/Makefile.am
sys/osxaudio/gstosxaudio.c
sys/osxaudio/gstosxaudiosink.c
sys/osxaudio/gstosxaudiosink.h
sys/osxaudio/gstosxaudiosrc.c
sys/osxaudio/gstosxaudiosrc.h
sys/osxaudio/gstosxringbuffer.c
sys/osxaudio/gstosxringbuffer.h

index 75c7634d4701257b41f16f371102517a6ef83bc1..faaa4f1ecc2ae029cbc206df5d55fc3f764da328 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2008-08-26  Michael Smith <msmith@songbirdnest.com>
+
+       * sys/osxaudio/Makefile.am:
+       * sys/osxaudio/gstosxaudio.c:
+       * sys/osxaudio/gstosxaudiosink.c:
+       * sys/osxaudio/gstosxaudiosink.h:
+       * sys/osxaudio/gstosxaudiosrc.c:
+       * sys/osxaudio/gstosxaudiosrc.h:
+       * sys/osxaudio/gstosxringbuffer.c:
+       * sys/osxaudio/gstosxringbuffer.h:
+         Rewrite caps setting and ring buffer initialisation.
+         Previously we never told CoreAudio what format we were going to send it,
+         so it only worked due to luck, and not at all on some hardware.
+         Now we explicitly advertise what formats the hardware supports, and then
+         configure the selected one correctly.
+
 2008-08-26  Stefan Kost  <ensonic@users.sf.net>
 
        * sys/v4l2/gstv4l2object.c:
index 1b0e4875737590c7a26c89b1fab564f47c425a20..8882dea2b82b4653cb85ada37f4160dc497ee165 100644 (file)
@@ -3,7 +3,8 @@ plugin_LTLIBRARIES = libgstosxaudio.la
 libgstosxaudio_la_SOURCES = gstosxringbuffer.c         \
                            gstosxaudioelement.c        \
                            gstosxaudiosink.c \
-                           gstosxaudiosrc.c
+                           gstosxaudiosrc.c \
+                           gstosxaudio.c
 
 libgstosxaudio_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \
        -Wno-deprecated-declarations
index 8a79bed27812dff6ddcf269340f3329450542459..8923284263c8d73df415168460969617f0586783 100644 (file)
@@ -1,6 +1,7 @@
 /* GStreamer
  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) 2007 Pioneers of the Inevitable <songbird@songbirdnest.com>
+ * Copyright (C) 2007,2008 Pioneers of the Inevitable <songbird@songbirdnest.com>
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  * License as published by the Free Software Foundation; either
@@ -16,7 +17,8 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  * 
- * The development of this code was made possible due to the involvement of Pioneers of the * Inevitable, the creators of the Songbird Music player
+ * The development of this code was made possible due to the involvement of 
+ * Pioneers of the Inevitable, the creators of the Songbird Music player
  * 
  */
 
 #include "gstosxaudioelement.h"
 #include "gstosxaudiosink.h"
 #include "gstosxaudiosrc.h"
-extern gchar *__gst_osxaudio_plugin_dir;
-
-GST_DEBUG_CATEGORY (osxaudio_debug);
 
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
-  if (!gst_library_load ("gstaudio"))
-    return FALSE;
 
-
-  if (!gst_element_register (plugin, "osxaudiosink", GST_RANK_PRIMARY,
-          GST_TYPE_OSXAUDIOSINK)) {
+  if (!gst_element_register (plugin, "fixedosxaudiosink", GST_RANK_PRIMARY + 1,
+          GST_TYPE_OSX_AUDIO_SINK)) {
     return FALSE;
   }
-  if (!gst_element_register (plugin, "osxaudiosrc", GST_RANK_PRIMARY,
-          GST_TYPE_OSXAUDIOSRC)) {
+  if (!gst_element_register (plugin, "fixedosxaudiosrc", GST_RANK_PRIMARY + 1,
+          GST_TYPE_OSX_AUDIO_SRC)) {
     return FALSE;
   }
 
-  GST_DEBUG_CATEGORY_INIT (osxaudio_debug, "osx", 0, "OSX audio elements");
-
-
   return TRUE;
 }
 
index 222056c8a372ee07f310b248ad98aeb7d0cc1136..5f67bb7b026fdcfa582ed3b051725c31d1701135 100644 (file)
@@ -41,8 +41,8 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  *
- *  The development of this code was made possible due to the involvement of Pioneers of i
- *  the Inevitable, the creators of the Songbird Music player
+ *  The development of this code was made possible due to the involvement of 
+ *  Pioneers of the Inevitable, the creators of the Songbird Music player.
  *
  */
 
@@ -65,6 +65,7 @@
 
 #include <gst/gst.h>
 #include <CoreAudio/CoreAudio.h>
+#include <CoreAudio/AudioHardware.h>
 #include "gstosxaudiosink.h"
 #include "gstosxaudiosrc.h"
 
@@ -99,7 +100,8 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
         "endianness = (int) {" G_STRINGIFY (G_BYTE_ORDER) " }, "
         "signed = (boolean) { TRUE }, "
         "width = (int) 32, "
-        "depth = (int) 32, " "rate = (int) 44100, " "channels = (int) 2")
+        "depth = (int) 32, "
+        "rate = (int) [1, MAX], " "channels = (int) [1, 2]")
     );
 
 static void gst_osx_audio_sink_set_property (GObject * object, guint prop_id,
@@ -108,16 +110,16 @@ static void gst_osx_audio_sink_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 static GstCaps *gst_osx_audio_sink_getcaps (GstBaseSink * sink);
 
-
 static GstRingBuffer *gst_osx_audio_sink_create_ringbuffer (GstBaseAudioSink *
     sink);
-/*static GstCaps* gst_osx_audio_sink_getcaps (GstBaseSink * bsink);*/
 static void gst_osx_audio_sink_osxelement_init (gpointer g_iface,
     gpointer iface_data);
 OSStatus gst_osx_audio_sink_io_proc (AudioDeviceID inDevice,
     const AudioTimeStamp * inNow, const AudioBufferList * inInputData,
     const AudioTimeStamp * inInputTime, AudioBufferList * outOutputData,
     const AudioTimeStamp * inOutputTime, void *inClientData);
+static void gst_osx_audio_sink_select_device (GstOsxAudioSink * osxsink);
+
 static void
 gst_osx_audio_sink_osxelement_do_init (GType type)
 {
@@ -189,10 +191,10 @@ static void
 gst_osx_audio_sink_init (GstOsxAudioSink * sink, GstOsxAudioSinkClass * gclass)
 {
 /*  GstElementClass *klass = GST_ELEMENT_GET_CLASS (sink); */
-  sink->ringbuffer = NULL;
   GST_DEBUG ("Initialising object");
 
-  gst_osx_audio_sink_create_ringbuffer (GST_BASE_AUDIO_SINK (sink));
+  sink->device_id = kAudioDeviceUnknown;
+  sink->stream_id = kAudioStreamUnknown;
 }
 
 static void
@@ -203,8 +205,7 @@ gst_osx_audio_sink_set_property (GObject * object, guint prop_id,
 
   switch (prop_id) {
     case ARG_DEVICE:
-      if (sink->ringbuffer)
-        sink->ringbuffer->device_id = g_value_get_int (value);
+      sink->device_id = g_value_get_int (value);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -217,14 +218,9 @@ gst_osx_audio_sink_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec)
 {
   GstOsxAudioSink *sink = GST_OSX_AUDIO_SINK (object);
-  int val = 0;
-
   switch (prop_id) {
     case ARG_DEVICE:
-      if (sink->ringbuffer)
-        val = sink->ringbuffer->device_id;
-
-      g_value_set_int (value, val);
+      g_value_set_int (value, sink->device_id);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -238,32 +234,93 @@ gst_osx_audio_sink_get_property (GObject * object, guint prop_id,
 static GstCaps *
 gst_osx_audio_sink_getcaps (GstBaseSink * sink)
 {
-  GstCaps *caps;
+  GstCaps *caps = NULL;
   GstOsxAudioSink *osxsink;
   OSStatus status;
-  AudioValueRange rates[10];
+  AudioValueRange *rates = NULL;
   UInt32 propertySize;
   int i;
+  gboolean foundFixedRate = FALSE;
+  GstStructure *structure;
+  GValue rate_v = { 0 };
+  GValue rates_v = { 0 };
 
-  propertySize = sizeof (AudioValueRange) * 9;
   osxsink = GST_OSX_AUDIO_SINK (sink);
 
-  caps = gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD
-          (sink)));
+  gst_osx_audio_sink_select_device (osxsink);
+
+  GST_DEBUG_OBJECT (osxsink, "Using device_id %d", (int) osxsink->device_id);
+
+  status = AudioDeviceGetPropertyInfo (osxsink->device_id, 0,   /* Master channel */
+      FALSE,                    /* isInput */
+      kAudioDevicePropertyAvailableNominalSampleRates, &propertySize, NULL);
+
+  if (status) {
+    GST_WARNING_OBJECT (osxsink, "Failed to get sample rates size: %ld",
+        status);
+    goto done;
+  }
 
+  GST_DEBUG_OBJECT (osxsink, "Allocating %d bytes for sizes",
+      (int) propertySize);
+  rates = g_malloc (propertySize);
 
-  status = AudioDeviceGetProperty (osxsink->ringbuffer->device_id, 0, FALSE,
-      kAudioDevicePropertyAvailableNominalSampleRates, &propertySize, &rates);
+  status = AudioDeviceGetProperty (osxsink->device_id, 0,       /* Master channel */
+      FALSE,                    /* isInput */
+      kAudioDevicePropertyAvailableNominalSampleRates, &propertySize, rates);
+
+  if (status) {
+    GST_WARNING_OBJECT (osxsink, "Failed to get sample rates: %ld", status);
+    goto done;
+  }
+
+  GST_DEBUG_OBJECT (osxsink, "Used %d bytes for sizes", (int) propertySize);
+
+  if (propertySize < sizeof (AudioValueRange)) {
+    GST_WARNING_OBJECT (osxsink, "Zero sample rates available");
+    goto done;
+  }
+
+  /* Create base caps object, then modify to suit. */
+  caps = gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD
+          (sink)));
+  structure = gst_caps_get_structure (caps, 0);
 
   GST_DEBUG
       ("Getting available sample rates: Status: %ld number of ranges: %lu",
       status, propertySize / sizeof (AudioValueRange));
 
+  g_value_init (&rates_v, GST_TYPE_LIST);
+  g_value_init (&rate_v, G_TYPE_INT);
+
   for (i = 0; i < propertySize / sizeof (AudioValueRange); i++) {
     GST_LOG_OBJECT (osxsink, "Range from %f to %f", rates[i].mMinimum,
         rates[i].mMaximum);
+    if (rates[i].mMinimum == rates[i].mMaximum) {
+      /* For now, we only support these in this form. If there are none
+       * in this form, we use the first (only) as a range. */
+      foundFixedRate = TRUE;
+
+      g_value_set_int (&rate_v, rates[i].mMinimum);
+      gst_value_list_append_value (&rates_v, &rate_v);
+    }
   }
 
+  g_value_unset (&rate_v);
+
+  if (foundFixedRate) {
+    gst_structure_set_value (structure, "rate", &rates_v);
+  } else {
+    gst_structure_set (structure, "rate", GST_TYPE_INT_RANGE,
+        rates[0].mMinimum, rates[0].mMaximum, NULL);
+  }
+
+  g_value_unset (&rates_v);
+
+done:
+  if (rates)
+    g_free (rates);
+
   return caps;
 }
 
@@ -272,19 +329,22 @@ static GstRingBuffer *
 gst_osx_audio_sink_create_ringbuffer (GstBaseAudioSink * sink)
 {
   GstOsxAudioSink *osxsink;
+  GstOsxRingBuffer *ringbuffer;
 
   osxsink = GST_OSX_AUDIO_SINK (sink);
-  if (!osxsink->ringbuffer) {
-    GST_DEBUG ("Creating ringbuffer");
-    osxsink->ringbuffer = g_object_new (GST_TYPE_OSX_RING_BUFFER, NULL);
-    GST_DEBUG ("osx sink 0x%p element 0x%p  ioproc 0x%p", osxsink,
-        GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsink),
-        (void *) gst_osx_audio_sink_io_proc);
-    osxsink->ringbuffer->element =
-        GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsink);
-  }
 
-  return GST_RING_BUFFER (osxsink->ringbuffer);
+  gst_osx_audio_sink_select_device (osxsink);
+
+  GST_DEBUG ("Creating ringbuffer");
+  ringbuffer = g_object_new (GST_TYPE_OSX_RING_BUFFER, NULL);
+  GST_DEBUG ("osx sink 0x%p element 0x%p  ioproc 0x%p", osxsink,
+      GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsink),
+      (void *) gst_osx_audio_sink_io_proc);
+  ringbuffer->element = GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsink);
+  ringbuffer->device_id = osxsink->device_id;
+  ringbuffer->stream_id = osxsink->stream_id;
+
+  return GST_RING_BUFFER (ringbuffer);
 }
 
 OSStatus
@@ -321,31 +381,73 @@ gst_osx_audio_sink_osxelement_init (gpointer g_iface, gpointer iface_data)
   iface->io_proc = gst_osx_audio_sink_io_proc;
 }
 
-/* entry point to initialize the plug-in
- * initialize the plug-in itself
- * register the element factories and pad templates
- * register the features
- *
- * exchange the string 'plugin' with your elemnt name
- */
-static gboolean
-plugin_init (GstPlugin * plugin)
+
+static void
+gst_osx_audio_sink_select_device (GstOsxAudioSink * osxsink)
 {
-  gboolean ret;
+  OSStatus status;
+  UInt32 propertySize;
 
-  ret = gst_element_register (plugin, "osxaudiosink",
-      GST_RANK_PRIMARY, GST_TYPE_OSX_AUDIO_SINK);
-  return ret && gst_element_register (plugin, "osxaudiosrc",
-      GST_RANK_PRIMARY, GST_TYPE_OSX_AUDIO_SRC);
-}
+  if (osxsink->device_id == kAudioDeviceUnknown) {
+    GST_DEBUG_OBJECT (osxsink, "Selecting device for OSXAudioSink");
+    propertySize = sizeof (osxsink->device_id);
+    status =
+        AudioHardwareGetProperty (kAudioHardwarePropertyDefaultOutputDevice,
+        &propertySize, &osxsink->device_id);
+
+    if (status)
+      GST_WARNING_OBJECT (osxsink,
+          "AudioHardwareGetProperty returned %d", (int) status);
+    else
+      GST_DEBUG_OBJECT (osxsink, "AudioHardwareGetProperty returned 0");
+
+    if (osxsink->device_id == kAudioDeviceUnknown)
+      GST_WARNING_OBJECT (osxsink,
+          "AudioHardwareGetProperty: device_id is kAudioDeviceUnknown");
+
+    GST_DEBUG_OBJECT (osxsink, "AudioHardwareGetProperty: device_id is %lu",
+        (long) osxsink->device_id);
+  }
 
-/* this is the structure that gstreamer looks for to register plugins
- *
- * exchange the strings 'plugin' and 'Template plugin' with you plugin name and
- * description
- */
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    "osxaudio",
-    "OSX Audio plugin",
-    plugin_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/")
+  if (osxsink->stream_id == kAudioStreamUnknown) {
+    AudioStreamID *streams;
+
+    GST_DEBUG_OBJECT (osxsink, "Getting streamid");
+    status = AudioDeviceGetPropertyInfo (osxsink->device_id, 0, /* Master channel */
+        FALSE,                  /* isInput */
+        kAudioDevicePropertyStreams, &propertySize, NULL);
+
+    if (status) {
+      GST_WARNING_OBJECT (osxsink,
+          "AudioDeviceGetProperty returned %d", (int) status);
+      return;
+    }
+
+    GST_DEBUG_OBJECT (osxsink,
+        "Getting available streamids from %d (%d bytes)",
+        (int) (propertySize / sizeof (AudioStreamID)), propertySize);
+    streams = g_malloc (propertySize);
+    status = AudioDeviceGetProperty (osxsink->device_id, 0,     /* Master channel */
+        FALSE,                  /* isInput */
+        kAudioDevicePropertyStreams, &propertySize, streams);
+
+    if (status) {
+      GST_WARNING_OBJECT (osxsink,
+          "AudioDeviceGetProperty returned %d", (int) status);
+      g_free (streams);
+      return;
+    }
+
+    GST_DEBUG_OBJECT (osxsink, "Getting streamid from %d (%d bytes)",
+        (int) (propertySize / sizeof (AudioStreamID)), propertySize);
+
+    if (propertySize >= sizeof (AudioStreamID)) {
+      osxsink->stream_id = streams[0];
+      GST_DEBUG_OBJECT (osxsink, "Selected stream %d of %d: %d", 0,
+          (int) (propertySize / sizeof (AudioStreamID)),
+          (int) osxsink->stream_id);
+    }
+
+    g_free (streams);
+  }
+}
index ba71c11d6a2d833b9c5583e051150b6facfbbb9d..a46d24489559f232fd9470bec7da576122298bc5 100644 (file)
@@ -71,7 +71,8 @@ struct _GstOsxAudioSink
 {
   GstBaseAudioSink sink;
 
-  GstOsxRingBuffer *ringbuffer;
+  AudioDeviceID device_id;
+  AudioStreamID stream_id;
 };
 
 struct _GstOsxAudioSinkClass 
index 0a543ae5aea49e46e0f37b7d35c3300c6af1fbb5..359eb7a7458f4c3e2db1ee0dba4be03259f15b14 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * GStreamer
  * Copyright 2005,2006 Zaheer Abbas Merali  <zaheerabbas at merali dot org>
+ *                2008 Pioneers of the Inevitable <songbird@songbirdnest.com>
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -92,7 +93,8 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
         "endianness = (int) {" G_STRINGIFY (G_BYTE_ORDER) " }, "
         "signed = (boolean) { TRUE }, "
         "width = (int) 32, "
-        "depth = (int) 32, " "rate = (int) 44100, " "channels = (int) 2")
+        "depth = (int) 32, "
+        "rate = (int) [1, MAX], " "channels = (int) [1, 2]")
     );
 
 static void gst_osx_audio_src_set_property (GObject * object, guint prop_id,
@@ -103,13 +105,13 @@ static void gst_osx_audio_src_get_property (GObject * object, guint prop_id,
 
 static GstRingBuffer *gst_osx_audio_src_create_ringbuffer (GstBaseAudioSrc *
     src);
-/*static GstCaps* gst_osx_audio_sink_getcaps (GstBaseSink * bsrc);*/
 static void gst_osx_audio_src_osxelement_init (gpointer g_iface,
     gpointer iface_data);
 OSStatus gst_osx_audio_src_io_proc (AudioDeviceID inDevice,
     const AudioTimeStamp * inNow, const AudioBufferList * inInputData,
     const AudioTimeStamp * inInputTime, AudioBufferList * outOutputData,
     const AudioTimeStamp * inOutputTime, void *inClientData);
+static void gst_osx_audio_src_select_device (GstOsxAudioSrc * osxsrc);
 
 static void
 gst_osx_audio_src_osxelement_do_init (GType type)
@@ -178,11 +180,11 @@ gst_osx_audio_src_class_init (GstOsxAudioSrcClass * klass)
 static void
 gst_osx_audio_src_init (GstOsxAudioSrc * src, GstOsxAudioSrcClass * gclass)
 {
-/*  GstElementClass *klass = GST_ELEMENT_GET_CLASS (sink); */
+/*  GstElementClass *klass = GST_ELEMENT_GET_CLASS (src); */
   gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
-  src->ringbuffer = NULL;
-  GST_DEBUG ("Initialising object");
-  gst_osx_audio_src_create_ringbuffer (GST_BASE_AUDIO_SRC (src));
+
+  src->device_id = kAudioDeviceUnknown;
+  src->stream_id = kAudioStreamUnknown;
 }
 
 static void
@@ -193,8 +195,7 @@ gst_osx_audio_src_set_property (GObject * object, guint prop_id,
 
   switch (prop_id) {
     case ARG_DEVICE:
-      if (src->ringbuffer)
-        src->ringbuffer->device_id = g_value_get_int (value);
+      src->device_id = g_value_get_int (value);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -207,14 +208,10 @@ gst_osx_audio_src_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec)
 {
   GstOsxAudioSrc *src = GST_OSX_AUDIO_SRC (object);
-  int val = 0;
 
   switch (prop_id) {
     case ARG_DEVICE:
-      if (src->ringbuffer)
-        val = src->ringbuffer->device_id;
-
-      g_value_set_int (value, val);
+      g_value_set_int (value, src->device_id);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -225,29 +222,32 @@ gst_osx_audio_src_get_property (GObject * object, guint prop_id,
 /* GstElement vmethod implementations */
 
 
-/* GstBaseAudioSink vmethod implementations */
+/* GstBaseAudioSrc vmethod implementations */
 static GstRingBuffer *
 gst_osx_audio_src_create_ringbuffer (GstBaseAudioSrc * src)
 {
   GstOsxAudioSrc *osxsrc;
   OSStatus status;
   UInt32 propertySize;
+  GstOsxRingBuffer *ringbuffer;
 
   osxsrc = GST_OSX_AUDIO_SRC (src);
-  if (!osxsrc->ringbuffer) {
-    GST_DEBUG ("Creating ringbuffer");
-    osxsrc->ringbuffer = g_object_new (GST_TYPE_OSX_RING_BUFFER, NULL);
-    /* change the device to the Default Input Device */
-    propertySize = sizeof (osxsrc->ringbuffer->device_id);
-    status = AudioHardwareGetProperty (kAudioHardwarePropertyDefaultInputDevice,
-        &propertySize, &osxsrc->ringbuffer->device_id);
-    GST_DEBUG ("osx src 0x%p element 0x%p  ioproc 0x%p", osxsrc,
-        GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsrc),
-        (void *) gst_osx_audio_src_io_proc);
-    osxsrc->ringbuffer->element = GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsrc);
-  }
 
-  return GST_RING_BUFFER (osxsrc->ringbuffer);
+  gst_osx_audio_src_select_device (osxsrc);
+
+  GST_DEBUG ("Creating ringbuffer");
+  ringbuffer = g_object_new (GST_TYPE_OSX_RING_BUFFER, NULL);
+
+  /* change the device to the Default Input Device */
+  GST_DEBUG ("osx src 0x%p element 0x%p  ioproc 0x%p", osxsrc,
+      GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsrc),
+      (void *) gst_osx_audio_src_io_proc);
+
+  ringbuffer->element = GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsrc);
+  ringbuffer->device_id = osxsrc->device_id;
+  ringbuffer->stream_id = osxsrc->stream_id;
+
+  return GST_RING_BUFFER (ringbuffer);
 }
 
 OSStatus
@@ -284,3 +284,72 @@ gst_osx_audio_src_osxelement_init (gpointer g_iface, gpointer iface_data)
 
   iface->io_proc = gst_osx_audio_src_io_proc;
 }
+
+static void
+gst_osx_audio_src_select_device (GstOsxAudioSrc * osxsrc)
+{
+  OSStatus status;
+  UInt32 propertySize;
+
+  if (osxsrc->device_id == kAudioDeviceUnknown) {
+    GST_DEBUG_OBJECT (osxsrc, "Selecting device for OSXAudioSrc");
+    propertySize = sizeof (osxsrc->device_id);
+    status = AudioHardwareGetProperty (kAudioHardwarePropertyDefaultInputDevice,
+        &propertySize, &osxsrc->device_id);
+
+    if (status)
+      GST_WARNING_OBJECT (osxsrc,
+          "AudioHardwareGetProperty returned %d", (int) status);
+    else
+      GST_DEBUG_OBJECT (osxsrc, "AudioHardwareGetProperty returned 0");
+
+    if (osxsrc->device_id == kAudioDeviceUnknown)
+      GST_WARNING_OBJECT (osxsrc,
+          "AudioHardwareGetProperty: device_id is kAudioDeviceUnknown");
+
+    GST_DEBUG_OBJECT (osxsrc, "AudioHardwareGetProperty: device_id is %lu",
+        (long) osxsrc->device_id);
+  }
+
+  if (osxsrc->stream_id == kAudioStreamUnknown) {
+    AudioStreamID *streams;
+
+    GST_DEBUG_OBJECT (osxsrc, "Getting streamid");
+    status = AudioDeviceGetPropertyInfo (osxsrc->device_id, 0,  /* Master channel */
+        FALSE,                  /* isInput */
+        kAudioDevicePropertyStreams, &propertySize, NULL);
+
+    if (status) {
+      GST_WARNING_OBJECT (osxsrc,
+          "AudioDeviceGetProperty returned %d", (int) status);
+      return;
+    }
+
+    GST_DEBUG_OBJECT (osxsrc,
+        "Getting available streamids from %d (%d bytes)",
+        (int) (propertySize / sizeof (AudioStreamID)), propertySize);
+    streams = g_malloc (propertySize);
+    status = AudioDeviceGetProperty (osxsrc->device_id, 0,      /* Master channel */
+        FALSE,                  /* isInput */
+        kAudioDevicePropertyStreams, &propertySize, streams);
+
+    if (status) {
+      GST_WARNING_OBJECT (osxsrc,
+          "AudioDeviceGetProperty returned %d", (int) status);
+      g_free (streams);
+      return;
+    }
+
+    GST_DEBUG_OBJECT (osxsrc, "Getting streamid from %d (%d bytes)",
+        (int) (propertySize / sizeof (AudioStreamID)), propertySize);
+
+    if (propertySize >= sizeof (AudioStreamID)) {
+      osxsrc->stream_id = streams[0];
+      GST_DEBUG_OBJECT (osxsrc, "Selected stream %d of %d: %d", 0,
+          (int) (propertySize / sizeof (AudioStreamID)),
+          (int) osxsrc->stream_id);
+    }
+
+    g_free (streams);
+  }
+}
index 93fc659f47934fa07530aa584ea1e8a41294247b..7336c82f19c044f3c61c52edb3c60cbafa4d788d 100644 (file)
@@ -65,7 +65,8 @@ struct _GstOsxAudioSrc
 {
   GstBaseAudioSrc src;
 
-  GstOsxRingBuffer *ringbuffer;
+  AudioDeviceID device_id;
+  AudioStreamID stream_id;
 };
 
 struct _GstOsxAudioSrcClass 
index 428c3806b3d42a643709e744e514797874bea12a..116893810da4095d0cab33c1093e9f1e3715f95e 100644 (file)
@@ -137,37 +137,7 @@ static void
 gst_osx_ring_buffer_init (GstOsxRingBuffer * ringbuffer,
     GstOsxRingBufferClass * g_class)
 {
-  OSStatus status;
-  UInt32 propertySize;
-
-  /* currently do bugger all */
-  GST_DEBUG ("osx ring buffer init");
-  propertySize = sizeof (ringbuffer->device_id);
-  status =
-      AudioHardwareGetProperty (kAudioHardwarePropertyDefaultOutputDevice,
-      &propertySize, &(ringbuffer->device_id));
-  GST_DEBUG ("osx ring buffer called AudioHardwareGetProperty");
-  if (status) {
-    GST_WARNING ("AudioHardwareGetProperty returned %d", (int) status);
-  } else {
-    GST_DEBUG ("AudioHardwareGetProperty returned 0");
-  }
-  if (ringbuffer->device_id == kAudioDeviceUnknown) {
-    GST_DEBUG ("AudioHardwareGetProperty: device_id is kAudioDeviceUnknown");
-  }
-  GST_DEBUG ("AudioHardwareGetProperty: device_id is %lu",
-      ringbuffer->device_id);
-  /* get requested buffer length */
-  propertySize = sizeof (ringbuffer->buffer_len);
-  status =
-      AudioDeviceGetProperty (ringbuffer->device_id, 0, false,
-      kAudioDevicePropertyBufferSize, &propertySize, &ringbuffer->buffer_len);
-  if (status) {
-    GST_WARNING
-        ("AudioDeviceGetProperty returned %d when getting kAudioDevicePropertyBufferSize",
-        (int) status);
-  }
-  GST_DEBUG ("%5d ringbuffer->buffer_len", (int) ringbuffer->buffer_len);
+  /* Nothing to do right now */
 }
 
 static void
@@ -199,15 +169,65 @@ gst_osx_ring_buffer_close_device (GstRingBuffer * buf)
 static gboolean
 gst_osx_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
 {
-  /* stub, we need to allocate ringbuffer memory */
+  /* Configure the output stream and allocate ringbuffer memory */
   GstOsxRingBuffer *osxbuf;
+  AudioStreamBasicDescription asbd;
+  AudioStreamBasicDescription asbd2;
+  OSStatus status;
+  UInt32 buffer_len;
+  UInt32 propertySize;
 
   osxbuf = GST_OSX_RING_BUFFER (buf);
 
-  spec->segsize = osxbuf->buffer_len;
+  /* Fill out the audio description we're going to be using */
+  asbd.mFormatID = kAudioFormatLinearPCM;
+  asbd.mSampleRate = (double) spec->rate;
+  asbd.mChannelsPerFrame = spec->channels;
+  asbd.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
+  asbd.mBytesPerFrame = spec->channels * sizeof (float);
+  asbd.mBitsPerChannel = sizeof (float) * 8;
+  asbd.mBytesPerPacket = spec->channels * sizeof (float);
+  asbd.mFramesPerPacket = 1;
+  asbd.mReserved = 0;
+
+  GST_LOG_OBJECT (osxbuf, "Format: %x, %f, %d, %x, %d, %d, %d, %d, %d",
+      asbd.mFormatID,
+      asbd.mSampleRate,
+      asbd.mChannelsPerFrame,
+      asbd.mFormatFlags,
+      asbd.mBytesPerFrame,
+      asbd.mBitsPerChannel,
+      asbd.mBytesPerPacket, asbd.mFramesPerPacket, asbd.mReserved);
+
+  GST_DEBUG_OBJECT (osxbuf, "Using stream_id %d, setting output format",
+      (int) osxbuf->stream_id);
+
+  propertySize = sizeof (asbd);
+  status = AudioStreamSetProperty (osxbuf->stream_id, NULL,     /* Change immediately */
+      0,                        /* Master channel */
+      kAudioStreamPropertyVirtualFormat, propertySize, &asbd);
+
+  if (status) {
+    GST_WARNING_OBJECT (osxbuf, "Failed to set output description: %lx",
+        status);
+    return FALSE;
+  }
+
+  /* get requested buffer length to use */
+  propertySize = sizeof (buffer_len);
+  status = AudioDeviceGetProperty (osxbuf->device_id, 0, false, /* TODO, this should be true for the source element */
+      kAudioDevicePropertyBufferSize, &propertySize, &buffer_len);
+
+  if (status) {
+    GST_WARNING_OBJECT (osxbuf,
+        "AudioDeviceGetProperty returned %d when getting "
+        "kAudioDevicePropertyBufferSize", (int) status);
+  }
+  GST_DEBUG_OBJECT (osxbuf, "%5d osxbuf->buffer_len", (int) buffer_len);
+  spec->segsize = buffer_len;
   spec->segtotal = 16;
 
-  GST_DEBUG ("osx ring buffer acquire");
+  GST_DEBUG_OBJECT (osxbuf, "osx ring buffer acquired");
 
   buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize);
   memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data));
index bc8d5524502ca215a61380cfb31c4c14ea2c2557..40a299ff4a4cf61d909b41ec3f159706e9dbba37 100644 (file)
@@ -67,6 +67,7 @@ struct _GstOsxRingBuffer {
        GstRingBuffer         object;
        
        AudioDeviceID  device_id;
+    AudioStreamID  stream_id;
        gboolean io_proc_active;
        guint buffer_len;
        GstOsxAudioElementInterface* element;