pulsesink: Use the extended stream API if available
authorArun Raghavan <arun.raghavan@collabora.co.uk>
Tue, 1 Mar 2011 10:04:46 +0000 (15:34 +0530)
committerArun Raghavan <arun.raghavan@collabora.co.uk>
Thu, 28 Jul 2011 19:55:15 +0000 (01:25 +0530)
This uses the new extended API for creating streams. This will allow us
to support compressed formats natively in pulsesink as well.

configure.ac
ext/pulse/pulsesink.c
ext/pulse/pulseutil.c
ext/pulse/pulseutil.h

index d6f2b9ba2e5ed247333167ebd9562fb377e03e61..304feddc441daf494d82b047cc497b5bb8aa3a61 100644 (file)
@@ -839,6 +839,10 @@ AG_GST_CHECK_FEATURE(PULSE, [pulseaudio plug-in], pulseaudio, [
   if test x$HAVE_PULSE_0_9_20 = xyes; then
     AC_DEFINE(HAVE_PULSE_0_9_20, 1, [defined if pulseaudio >= 0.9.20 is available])
   fi
+  AG_GST_PKG_CHECK_MODULES(PULSE_1_0, libpulse >= 0.98)
+  if test x$HAVE_PULSE_1_0 = xyes; then
+    AC_DEFINE(HAVE_PULSE_1_0, 1, [defined if pulseaudio >= 1.0 is available])
+  fi
 ])
 
 dnl *** dv1394 ***
index 83ccdb29509f7b72fd9f2171f732a48a7b5fd0e7..ad8282cc709b216f132ba22804cfaabe5279b5ac 100644 (file)
@@ -138,7 +138,12 @@ struct _GstPulseRingBuffer
   pa_context *context;
   pa_stream *stream;
 
+#if HAVE_PULSE_1_0
+  pa_format_info *format;
+  guint channels;
+#else
   pa_sample_spec sample_spec;
+#endif
 
   void *m_data;
   size_t m_towrite;
@@ -222,7 +227,12 @@ gst_pulseringbuffer_init (GstPulseRingBuffer * pbuf)
   pbuf->context = NULL;
   pbuf->stream = NULL;
 
+#ifdef HAVE_PULSE_1_0
+  pbuf->format = NULL;
+  pbuf->channels = 0;
+#else
   pa_sample_spec_init (&pbuf->sample_spec);
+#endif
 
   pbuf->m_data = NULL;
   pbuf->m_towrite = 0;
@@ -251,6 +261,13 @@ gst_pulsering_destroy_stream (GstPulseRingBuffer * pbuf)
       pbuf->m_offset = 0;
       pbuf->m_lastoffset = 0;
     }
+#ifdef HAVE_PULSE_1_0
+    if (pbuf->format) {
+      pa_format_info_free (pbuf->format);
+      pbuf->format = NULL;
+      pbuf->channels = 0;
+    }
+#endif
 
     pa_stream_disconnect (pbuf->stream);
 
@@ -718,14 +735,22 @@ gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
   pa_stream_flags_t flags;
   const gchar *name;
   GstAudioClock *clock;
+#ifdef HAVE_PULSE_1_0
+  pa_format_info *formats[1];
+#endif
 
   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (buf));
   pbuf = GST_PULSERING_BUFFER_CAST (buf);
 
   GST_LOG_OBJECT (psink, "creating sample spec");
   /* convert the gstreamer sample spec to the pulseaudio format */
+#ifdef HAVE_PULSE_1_0
+  if (!gst_pulse_fill_format_info (spec, &pbuf->format, &pbuf->channels))
+    goto invalid_spec;
+#else
   if (!gst_pulse_fill_sample_spec (spec, &pbuf->sample_spec))
     goto invalid_spec;
+#endif
 
   pa_threaded_mainloop_lock (mainloop);
 
@@ -742,7 +767,13 @@ gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
   pa_operation_unref (o);
 
   /* initialize the channel map */
+#ifdef HAVE_PULSE_1_0
+  if (pa_format_info_is_pcm (pbuf->format) &&
+      gst_pulse_gst_to_channel_map (&channel_map, spec))
+    pa_format_info_set_channel_map (pbuf->format, &channel_map);
+#else
   gst_pulse_gst_to_channel_map (&channel_map, spec);
+#endif
 
   /* find a good name for the stream */
   if (psink->stream_name)
@@ -751,10 +782,17 @@ gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
     name = "Playback Stream";
 
   /* create a stream */
+#ifdef HAVE_PULSE_1_0
+  formats[0] = pbuf->format;
+  if (!(pbuf->stream = pa_stream_new_extended (pbuf->context, name, formats, 1,
+              psink->proplist)))
+    goto stream_failed;
+#else
   GST_LOG_OBJECT (psink, "creating stream with name %s", name);
   if (!(pbuf->stream = pa_stream_new_with_proplist (pbuf->context, name,
               &pbuf->sample_spec, &channel_map, psink->proplist)))
     goto stream_failed;
+#endif
 
   /* install essential callbacks */
   pa_stream_set_state_callback (pbuf->stream,
@@ -792,8 +830,13 @@ gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
   if (psink->volume_set) {
     GST_LOG_OBJECT (psink, "have volume of %f", psink->volume);
     pv = &v;
+#ifdef HAVE_PULSE_1_0
+    if (pa_format_info_is_pcm (pbuf->format))
+      gst_pulse_cvolume_from_linear (pv, pbuf->channels, psink->volume);
+#else
     gst_pulse_cvolume_from_linear (pv, pbuf->sample_spec.channels,
         psink->volume);
+#endif
   } else {
     pv = NULL;
   }
@@ -1923,7 +1966,12 @@ gst_pulsesink_set_volume (GstPulseSink * psink, gdouble volume)
   if ((idx = pa_stream_get_index (pbuf->stream)) == PA_INVALID_INDEX)
     goto no_index;
 
+#ifdef HAVE_PULSE_1_0
+  if (pa_format_info_is_pcm (pbuf->format))
+    gst_pulse_cvolume_from_linear (&v, pbuf->channels, volume);
+#else
   gst_pulse_cvolume_from_linear (&v, pbuf->sample_spec.channels, volume);
+#endif
 
   if (!(o = pa_context_set_sink_input_volume (pbuf->context, idx,
               &v, NULL, NULL)))
index 8fbb3caece58c46de3b23630ad820cec36f1a62e..a634b71f6407b01847bf874318203f383b4a11ba 100644 (file)
@@ -118,6 +118,81 @@ gst_pulse_fill_sample_spec (GstRingBufferSpec * spec, pa_sample_spec * ss)
   return TRUE;
 }
 
+#ifdef HAVE_PULSE_1_0
+gboolean
+gst_pulse_fill_format_info (GstRingBufferSpec * spec, pa_format_info ** f,
+    guint * channels)
+{
+  pa_format_info *format;
+  pa_sample_format_t sf = PA_SAMPLE_INVALID;
+
+  format = pa_format_info_new ();
+
+  if (spec->format == GST_MU_LAW && spec->width == 8) {
+    format->encoding = PA_ENCODING_PCM;
+    sf = PA_SAMPLE_ULAW;
+  } else if (spec->format == GST_A_LAW && spec->width == 8) {
+    format->encoding = PA_ENCODING_PCM;
+    sf = PA_SAMPLE_ALAW;
+  } else if (spec->format == GST_U8 && spec->width == 8) {
+    format->encoding = PA_ENCODING_PCM;
+    sf = PA_SAMPLE_U8;
+  } else if (spec->format == GST_S16_LE && spec->width == 16) {
+    format->encoding = PA_ENCODING_PCM;
+    sf = PA_SAMPLE_S16LE;
+  } else if (spec->format == GST_S16_BE && spec->width == 16) {
+    format->encoding = PA_ENCODING_PCM;
+    sf = PA_SAMPLE_S16BE;
+  } else if (spec->format == GST_FLOAT32_LE && spec->width == 32) {
+    format->encoding = PA_ENCODING_PCM;
+    sf = PA_SAMPLE_FLOAT32LE;
+  } else if (spec->format == GST_FLOAT32_BE && spec->width == 32) {
+    format->encoding = PA_ENCODING_PCM;
+    sf = PA_SAMPLE_FLOAT32BE;
+  } else if (spec->format == GST_S32_LE && spec->width == 32) {
+    format->encoding = PA_ENCODING_PCM;
+    sf = PA_SAMPLE_S32LE;
+  } else if (spec->format == GST_S32_BE && spec->width == 32) {
+    format->encoding = PA_ENCODING_PCM;
+    sf = PA_SAMPLE_S32BE;
+  } else if (spec->format == GST_S24_3LE && spec->width == 24) {
+    format->encoding = PA_ENCODING_PCM;
+    sf = PA_SAMPLE_S24LE;
+  } else if (spec->format == GST_S24_3BE && spec->width == 24) {
+    format->encoding = PA_ENCODING_PCM;
+    sf = PA_SAMPLE_S24BE;
+  } else if (spec->format == GST_S24_LE && spec->width == 32) {
+    format->encoding = PA_ENCODING_PCM;
+    sf = PA_SAMPLE_S24_32LE;
+  } else if (spec->format == GST_S24_BE && spec->width == 32) {
+    format->encoding = PA_ENCODING_PCM;
+    sf = PA_SAMPLE_S24_32BE;
+  } else {
+    goto fail;
+  }
+
+  if (format->encoding == PA_ENCODING_PCM) {
+    pa_format_info_set_sample_format (format, sf);
+    pa_format_info_set_channels (format, spec->channels);
+  }
+
+  pa_format_info_set_rate (format, spec->rate);
+
+  if (!pa_format_info_valid (format))
+    goto fail;
+
+  *f = format;
+  *channels = spec->channels;
+
+  return TRUE;
+
+fail:
+  if (format)
+    pa_format_info_free (format);
+  return FALSE;
+}
+#endif
+
 /* PATH_MAX is not defined everywhere, e.g. on GNU Hurd */
 #ifndef PATH_MAX
 #define PATH_MAX 4096
index ec04ffc0cbf0598886e1326e00636c5918b275c6..91c8502e39b84986d11326926826261275b4cb93 100644 (file)
 
 gboolean gst_pulse_fill_sample_spec (GstRingBufferSpec * spec,
     pa_sample_spec * ss);
+#ifdef HAVE_PULSE_1_0
+gboolean gst_pulse_fill_format_info (GstRingBufferSpec * spec,
+    pa_format_info ** f, guint * channels);
+#endif
 
 gchar *gst_pulse_client_name (void);