summaryrefslogtreecommitdiffstats
path: root/ext/esd
diff options
context:
space:
mode:
authorDavid Schleef <ds@schleef.org>2003-07-17 08:08:09 +0000
committerDavid Schleef <ds@schleef.org>2003-07-17 08:08:09 +0000
commit8da323b63d7e9b5fa14f45081c00b29a50a77adc (patch)
treed28f52f026a9273cf2468c94bf3839be3b1b1392 /ext/esd
parente0cf75ee7ace961c9e51341cb9869c787a3588b8 (diff)
Added clock to esdsink based on GstAudioClock
Original commit message from CVS: Added clock to esdsink based on GstAudioClock
Diffstat (limited to 'ext/esd')
-rw-r--r--ext/esd/esdsink.c128
-rw-r--r--ext/esd/esdsink.h7
-rw-r--r--ext/esd/gstesd.c2
3 files changed, 129 insertions, 8 deletions
diff --git a/ext/esd/esdsink.c b/ext/esd/esdsink.c
index 3d985b5b..f4557383 100644
--- a/ext/esd/esdsink.c
+++ b/ext/esd/esdsink.c
@@ -26,6 +26,7 @@
#include "esdsink.h"
#include <esd.h>
#include <unistd.h>
+#include <errno.h>
/* elementfactory information */
static GstElementDetails esdsink_details = {
@@ -48,6 +49,8 @@ enum {
ARG_0,
ARG_MUTE,
ARG_HOST,
+ ARG_SYNC,
+ ARG_FALLBACK,
};
GST_PAD_TEMPLATE_FACTORY (sink_factory,
@@ -87,6 +90,8 @@ static void gst_esdsink_close_audio (GstEsdsink *sink);
static GstElementStateReturn gst_esdsink_change_state (GstElement *element);
static GstPadLinkReturn gst_esdsink_sinkconnect (GstPad *pad, GstCaps *caps);
+static GstClockTime gst_esdsink_get_time (GstClock *clock, gpointer data);
+static GstClock * gst_esdsink_get_clock (GstElement *element);
static void gst_esdsink_set_clock (GstElement *element, GstClock *clock);
static void gst_esdsink_chain (GstPad *pad, GstBuffer *buf);
@@ -136,13 +141,19 @@ gst_esdsink_class_init (GstEsdsinkClass *klass)
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_HOST,
g_param_spec_string("host","host","host",
NULL, G_PARAM_READWRITE)); /* CHECKME */
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SYNC,
+ g_param_spec_boolean("sync","sync","Synchronize output to clock",
+ FALSE,G_PARAM_READWRITE));
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FALLBACK,
+ g_param_spec_boolean("fallback","fallback","Fall back to using OSS if Esound daemon is not present",
+ FALSE,G_PARAM_READWRITE));
gobject_class->set_property = gst_esdsink_set_property;
gobject_class->get_property = gst_esdsink_get_property;
gstelement_class->change_state = gst_esdsink_change_state;
gstelement_class->set_clock = gst_esdsink_set_clock;
- //gstelement_class->get_clock = gst_esdsink_get_clock;
+ gstelement_class->get_clock = gst_esdsink_get_clock;
}
static void
@@ -165,6 +176,10 @@ gst_esdsink_init(GstEsdsink *esdsink)
esdsink->channels = -1;
esdsink->frequency = -1;
esdsink->host = getenv ("ESPEAKER");
+ esdsink->provided_clock = gst_audio_clock_new("esdclock", gst_esdsink_get_time, esdsink);
+ gst_object_set_parent(GST_OBJECT(esdsink->provided_clock), GST_OBJECT(esdsink));
+ esdsink->sync = FALSE;
+ esdsink->fallback = FALSE;
}
static GstPadLinkReturn
@@ -183,6 +198,8 @@ gst_esdsink_sinkconnect (GstPad *pad, GstCaps *caps)
gst_caps_get_int (caps, "channels", &esdsink->channels);
gst_caps_get_int (caps, "rate", &esdsink->frequency);
+ esdsink->bytes_per_sample = esdsink->channels * (esdsink->depth/8);
+
/* only u8/s16 */
if ((sign == FALSE && esdsink->depth != 8) ||
(sign == TRUE && esdsink->depth != 16)) {
@@ -198,17 +215,38 @@ gst_esdsink_sinkconnect (GstPad *pad, GstCaps *caps)
return GST_PAD_LINK_REFUSED;
}
+static int
+gst_esdsink_get_latency (GstEsdsink *esdsink)
+{
+ /* esd_get_latency() doesn't actually work. So we return a
+ * fake value */
+ return 44100/2;
#if 0
+ return esd_get_latency (esdsink->fd);
+#endif
+}
+
+static GstClockTime
+gst_esdsink_get_time (GstClock *clock, gpointer data)
+{
+ GstEsdsink *esdsink = GST_ESDSINK(data);
+ GstClockTime res;
+
+ res = (esdsink->handled - gst_esdsink_get_latency(esdsink))
+ * GST_SECOND / esdsink->frequency;
+
+ return res;
+}
+
static GstClock *
gst_esdsink_get_clock (GstElement *element)
{
GstEsdsink *esdsink;
- esdsink = GET_ESDSINK (element);
+ esdsink = GST_ESDSINK (element);
return GST_CLOCK(esdsink->provided_clock);
}
-#endif
static void
gst_esdsink_set_clock (GstElement *element, GstClock *clock)
@@ -239,6 +277,9 @@ gst_esdsink_chain (GstPad *pad, GstBuffer *buf)
switch(GST_EVENT_TYPE(event)){
case GST_EVENT_EOS:
+ gst_audio_clock_set_active (GST_AUDIO_CLOCK (esdsink->provided_clock),
+ FALSE);
+ gst_pad_event_default (pad, event);
break;
case GST_EVENT_DISCONTINUOUS:
{
@@ -246,11 +287,12 @@ gst_esdsink_chain (GstPad *pad, GstBuffer *buf)
if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &value)) {
if (!gst_clock_handle_discont (esdsink->clock, value)){
- //gst_esdsink_clock_set_active (osssink->provided_clock, FALSE);
+ gst_audio_clock_set_active (GST_AUDIO_CLOCK (esdsink->provided_clock),
+ FALSE);
}
- //esdsink->handled = 0;
+ esdsink->handled = 0;
}
- //esdsink->resync = TRUE;
+ esdsink->resync = TRUE;
break;
}
default:
@@ -263,11 +305,62 @@ gst_esdsink_chain (GstPad *pad, GstBuffer *buf)
if (GST_BUFFER_DATA (buf) != NULL) {
if (!esdsink->mute && esdsink->fd >= 0) {
+ guchar *data = GST_BUFFER_DATA (buf);
+ gint size = GST_BUFFER_SIZE (buf);
+ gint to_write = 0;
+
+ if (esdsink->clock){
+ gint delay = 0;
+ gint64 queued;
+ GstClockTimeDiff jitter;
+
+ delay = gst_esdsink_get_latency (esdsink);
+ queued = delay * GST_SECOND / esdsink->frequency;
+
+ if (esdsink->resync && esdsink->sync) {
+ GstClockID id = gst_clock_new_single_shot_id (esdsink->clock,
+ GST_BUFFER_TIMESTAMP (buf) - queued);
+
+ gst_element_clock_wait (GST_ELEMENT (esdsink), id, &jitter);
+ gst_clock_id_free (id);
+
+ if (jitter >= 0){
+ gst_clock_handle_discont (esdsink->clock,
+ GST_BUFFER_TIMESTAMP (buf) - queued + jitter);
+ to_write = size;
+ gst_audio_clock_set_active ((GstAudioClock *)esdsink->provided_clock, TRUE);
+ esdsink->resync = FALSE;
+ }
+ }else{
+ to_write = size;
+ }
+ }
+
GST_DEBUG ("esdsink: fd=%d data=%p size=%d",
esdsink->fd, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
- write (esdsink->fd, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+ while (to_write > 0){
+ int done;
+
+ done = write (esdsink->fd, data, to_write);
+
+ if(done < 0){
+ if(errno==EINTR){
+ goto done;
+ }
+ g_assert_not_reached();
+ }
+
+ to_write -= done;
+ data += done;
+ esdsink->handled += done / esdsink->bytes_per_sample;
+ }
+
}
}
+
+ gst_audio_clock_update_time ((GstAudioClock *)esdsink->provided_clock,
+ GST_BUFFER_TIMESTAMP (buf));
+
done:
gst_buffer_unref (buf);
}
@@ -292,6 +385,12 @@ gst_esdsink_set_property (GObject *object, guint prop_id, const GValue *value, G
else
esdsink->host = g_strdup (g_value_get_string (value));
break;
+ case ARG_SYNC:
+ esdsink->sync = g_value_get_boolean (value);
+ break;
+ case ARG_FALLBACK:
+ esdsink->fallback = g_value_get_boolean (value);
+ break;
default:
break;
}
@@ -311,6 +410,12 @@ gst_esdsink_get_property (GObject *object, guint prop_id, GValue *value, GParamS
case ARG_HOST:
g_value_set_string (value, esdsink->host);
break;
+ case ARG_SYNC:
+ g_value_set_boolean (value, esdsink->sync);
+ break;
+ case ARG_FALLBACK:
+ g_value_set_boolean (value, esdsink->fallback);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -360,7 +465,11 @@ gst_esdsink_open_audio (GstEsdsink *sink)
}
GST_DEBUG ("esdsink: attempting to open connection to esound server");
- sink->fd = esd_play_stream_fallback(esdformat, sink->frequency, sink->host, connname);
+ if(sink->fallback){
+ sink->fd = esd_play_stream_fallback(esdformat, sink->frequency, sink->host, connname);
+ }else{
+ sink->fd = esd_play_stream(esdformat, sink->frequency, sink->host, connname);
+ }
if ( sink->fd < 0 ) {
GST_DEBUG ("esdsink: can't open connection to esound server");
return FALSE;
@@ -396,6 +505,9 @@ gst_esdsink_change_state (GstElement *element)
case GST_STATE_PAUSED_TO_PLAYING:
break;
case GST_STATE_PLAYING_TO_PAUSED:
+ gst_audio_clock_set_active (GST_AUDIO_CLOCK (esdsink->provided_clock),
+ FALSE);
+ esdsink->resync = TRUE;
break;
case GST_STATE_PAUSED_TO_READY:
gst_esdsink_close_audio (GST_ESDSINK (element));
diff --git a/ext/esd/esdsink.h b/ext/esd/esdsink.h
index c418386e..9bf81641 100644
--- a/ext/esd/esdsink.h
+++ b/ext/esd/esdsink.h
@@ -22,6 +22,7 @@
#define __GST_ESDSINK_H__
#include <gst/gst.h>
+#include <gst/audio/audioclock.h>
G_BEGIN_DECLS
@@ -44,6 +45,7 @@ struct _GstEsdsink {
GstPad *sinkpad;
+ GstClock *provided_clock;
GstClock *clock;
gboolean mute;
@@ -54,6 +56,11 @@ struct _GstEsdsink {
gint frequency;
gboolean negotiated;
gchar *host;
+ int handled;
+ int bytes_per_sample;
+ gboolean sync;
+ gboolean resync;
+ gboolean fallback;
};
struct _GstEsdsinkClass {
diff --git a/ext/esd/gstesd.c b/ext/esd/gstesd.c
index 3f016323..24a9842a 100644
--- a/ext/esd/gstesd.c
+++ b/ext/esd/gstesd.c
@@ -30,6 +30,8 @@ plugin_init (GModule *module, GstPlugin *plugin)
{
gboolean ret;
+ if (!gst_library_load ("gstaudio")) return FALSE;
+
ret = gst_esdsink_factory_init(plugin);
if(ret == FALSE) return FALSE;