diff options
Diffstat (limited to 'java/openjfx8-devel/files/sndiosink.c')
-rw-r--r-- | java/openjfx8-devel/files/sndiosink.c | 502 |
1 files changed, 102 insertions, 400 deletions
diff --git a/java/openjfx8-devel/files/sndiosink.c b/java/openjfx8-devel/files/sndiosink.c index eda86ee726f2..cc68bd29d807 100644 --- a/java/openjfx8-devel/files/sndiosink.c +++ b/java/openjfx8-devel/files/sndiosink.c @@ -1,5 +1,6 @@ /* - * Copyright (C) <2008> Jacob Meuser <jakemsr@sdf.lonestar.org> + * Copyright (C) 2008 Jacob Meuser <jakemsr@sdf.lonestar.org> + * Copyright (C) 2012 Alexandre Ratchov <alex@caoua.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -34,491 +35,192 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif - #include "sndiosink.h" -#include <unistd.h> -#include <errno.h> - -#define _(x) x GST_DEBUG_CATEGORY_EXTERN (gst_sndio_debug); #define GST_CAT_DEFAULT gst_sndio_debug -enum -{ - PROP_0, - PROP_HOST -}; +#define gst_sndiosink_parent_class parent_class -static GstStaticPadTemplate sndio_sink_factory = +static GstStaticPadTemplate sndiosink_factory = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw-int, " - "endianness = (int) { 1234, 4321 }, " - "signed = (boolean) { TRUE, FALSE }, " - "width = (int) { 8, 16, 24, 32 }, " - "depth = (int) { 8, 16, 24, 32 }, " - "rate = (int) [ 8000, 192000 ], " - "channels = (int) [ 1, 16 ] ") + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_SNDIO_CAPS_STRING) ); -static void gst_sndiosink_finalize (GObject * object); - -static GstCaps *gst_sndiosink_getcaps (GstBaseSink * bsink); +G_DEFINE_TYPE_WITH_CODE (GstSndioSink, gst_sndiosink, GST_TYPE_AUDIO_SINK, + G_IMPLEMENT_INTERFACE (GST_TYPE_STREAM_VOLUME, NULL)); +static void gst_sndiosink_finalize (GObject * object); +static GstCaps *gst_sndiosink_getcaps (GstBaseSink * bsink, + GstCaps * filter); static gboolean gst_sndiosink_open (GstAudioSink * asink); static gboolean gst_sndiosink_close (GstAudioSink * asink); static gboolean gst_sndiosink_prepare (GstAudioSink * asink, - GstRingBufferSpec * spec); + GstAudioRingBufferSpec * spec); static gboolean gst_sndiosink_unprepare (GstAudioSink * asink); -static guint gst_sndiosink_write (GstAudioSink * asink, gpointer data, +static gint gst_sndiosink_write (GstAudioSink * asink, gpointer data, guint length); static guint gst_sndiosink_delay (GstAudioSink * asink); static void gst_sndiosink_reset (GstAudioSink * asink); - static void gst_sndiosink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_sndiosink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static void gst_sndiosink_cb(void * addr, int delta); - -GST_BOILERPLATE (GstSndioSink, gst_sndiosink, GstAudioSink, GST_TYPE_AUDIO_SINK); - -static void -gst_sndiosink_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_set_details_simple (element_class, - "Sndio audio sink", "Sink/Audio", "Plays audio through sndio", - "Jacob Meuser <jakemsr@sdf.lonestar.org>"); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sndio_sink_factory)); -} - -static void -gst_sndiosink_class_init (GstSndioSinkClass * klass) -{ - GObjectClass *gobject_class; - GstBaseSinkClass *gstbasesink_class; - GstBaseAudioSinkClass *gstbaseaudiosink_class; - GstAudioSinkClass *gstaudiosink_class; - - gobject_class = (GObjectClass *) klass; - gstbasesink_class = (GstBaseSinkClass *) klass; - gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass; - gstaudiosink_class = (GstAudioSinkClass *) klass; - - parent_class = g_type_class_peek_parent (klass); - - gobject_class->finalize = gst_sndiosink_finalize; - - gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_sndiosink_getcaps); - - gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_sndiosink_open); - gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_sndiosink_close); - gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_sndiosink_prepare); - gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_sndiosink_unprepare); - gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_sndiosink_write); - gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_sndiosink_delay); - gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_sndiosink_reset); - - gobject_class->set_property = gst_sndiosink_set_property; - gobject_class->get_property = gst_sndiosink_get_property; - - /* default value is filled in the _init method */ - g_object_class_install_property (gobject_class, PROP_HOST, - g_param_spec_string ("host", "Host", - "Device or socket sndio will access", NULL, G_PARAM_READWRITE)); -} static void -gst_sndiosink_init (GstSndioSink * sndiosink, GstSndioSinkClass * klass) +gst_sndiosink_init (GstSndioSink * sink) { - sndiosink->hdl = NULL; - sndiosink->host = g_strdup (g_getenv ("AUDIODEVICE")); + gst_sndio_init (&sink->sndio, G_OBJECT(sink)); } static void gst_sndiosink_finalize (GObject * object) { - GstSndioSink *sndiosink = GST_SNDIOSINK (object); - - gst_caps_replace (&sndiosink->cur_caps, NULL); - g_free (sndiosink->host); + GstSndioSink *sink = GST_SNDIOSINK (object); + gst_sndio_finalize (&sink->sndio); G_OBJECT_CLASS (parent_class)->finalize (object); } static GstCaps * -gst_sndiosink_getcaps (GstBaseSink * bsink) +gst_sndiosink_getcaps (GstBaseSink * bsink, GstCaps * filter) { - GstSndioSink *sndiosink; - - sndiosink = GST_SNDIOSINK (bsink); - - /* no hdl, we're done with the template caps */ - if (sndiosink->cur_caps == NULL) { - GST_LOG_OBJECT (sndiosink, "getcaps called, returning template caps"); - return NULL; - } - - GST_LOG_OBJECT (sndiosink, "returning %" GST_PTR_FORMAT, sndiosink->cur_caps); + GstSndioSink *sink = GST_SNDIOSINK (bsink); - return gst_caps_ref (sndiosink->cur_caps); + return gst_sndio_getcaps (&sink->sndio, filter); } static gboolean gst_sndiosink_open (GstAudioSink * asink) { - GstPadTemplate *pad_template; - GstSndioSink *sndiosink; - struct sio_par par; - struct sio_cap cap; - GArray *rates, *chans; - GValue rates_v = { 0 }; - GValue chans_v = { 0 }; - GValue value = { 0 }; - struct sio_enc enc; - struct sio_conf conf; - int confs[SIO_NCONF]; - int rate, chan; - int i, j, k; - int nconfs; - - sndiosink = GST_SNDIOSINK (asink); - - GST_DEBUG_OBJECT (sndiosink, "open"); - - /* conect */ - sndiosink->hdl = sio_open (sndiosink->host, SIO_PLAY, 0); - - if (sndiosink->hdl == NULL) - goto couldnt_connect; - - /* Use sndio defaults as the only encodings, but get the supported - * sample rates and number of channels. - */ - - if (!sio_getpar(sndiosink->hdl, &par)) - goto no_server_info; - - if (!sio_getcap(sndiosink->hdl, &cap)) - goto no_server_info; - - rates = g_array_new(FALSE, FALSE, sizeof(int)); - chans = g_array_new(FALSE, FALSE, sizeof(int)); - - /* find confs that have the default encoding */ - nconfs = 0; - for (i = 0; i < cap.nconf; i++) { - for (j = 0; j < SIO_NENC; j++) { - if (cap.confs[i].enc & (1 << j)) { - enc = cap.enc[j]; - if (enc.bits == par.bits && enc.sig == par.sig && enc.le == par.le) { - confs[nconfs] = i; - nconfs++; - break; - } - } - } - } - - /* find the rates and channels of the confs that have the default encoding */ - for (i = 0; i < nconfs; i++) { - conf = cap.confs[confs[i]]; - /* rates */ - for (j = 0; j < SIO_NRATE; j++) { - if (conf.rate & (1 << j)) { - rate = cap.rate[j]; - for (k = 0; k < rates->len && rate; k++) { - if (rate == g_array_index(rates, int, k)) - rate = 0; - } - /* add in ascending order */ - if (rate) { - for (k = 0; k < rates->len; k++) { - if (rate < g_array_index(rates, int, k)) { - g_array_insert_val(rates, k, rate); - break; - } - } - if (k == rates->len) - g_array_append_val(rates, rate); - } - } - } - /* channels */ - for (j = 0; j < SIO_NCHAN; j++) { - if (conf.pchan & (1 << j)) { - chan = cap.pchan[j]; - for (k = 0; k < chans->len && chan; k++) { - if (chan == g_array_index(chans, int, k)) - chan = 0; - } - /* add in ascending order */ - if (chan) { - for (k = 0; k < chans->len; k++) { - if (chan < g_array_index(chans, int, k)) { - g_array_insert_val(chans, k, chan); - break; - } - } - if (k == chans->len) - g_array_append_val(chans, chan); - } - } - } - } - /* not sure how this can happen, but it might */ - if (cap.nconf == 0) { - g_array_append_val(rates, par.rate); - g_array_append_val(chans, par.pchan); - } + GstSndioSink *sink = GST_SNDIOSINK (asink); - g_value_init(&rates_v, GST_TYPE_LIST); - g_value_init(&chans_v, GST_TYPE_LIST); - g_value_init(&value, G_TYPE_INT); - - for (i = 0; i < rates->len; i++) { - g_value_set_int(&value, g_array_index(rates, int, i)); - gst_value_list_append_value(&rates_v, &value); - } - for (i = 0; i < chans->len; i++) { - g_value_set_int(&value, g_array_index(chans, int, i)); - gst_value_list_append_value(&chans_v, &value); - } - - g_array_free(rates, TRUE); - g_array_free(chans, TRUE); - - pad_template = gst_static_pad_template_get (&sndio_sink_factory); - sndiosink->cur_caps = gst_caps_copy (gst_pad_template_get_caps (pad_template)); - gst_object_unref (pad_template); - - for (i = 0; i < sndiosink->cur_caps->structs->len; i++) { - GstStructure *s; - - s = gst_caps_get_structure (sndiosink->cur_caps, i); - gst_structure_set (s, "endianness", G_TYPE_INT, par.le ? 1234 : 4321, NULL); - gst_structure_set (s, "signed", G_TYPE_BOOLEAN, par.sig ? TRUE : FALSE, NULL); - gst_structure_set (s, "width", G_TYPE_INT, par.bits, NULL); - // gst_structure_set (s, "depth", G_TYPE_INT, par.bps * 8, NULL); /* XXX */ - gst_structure_set_value (s, "rate", &rates_v); - gst_structure_set_value (s, "channels", &chans_v); - } - - return TRUE; - - /* ERRORS */ -couldnt_connect: - { - GST_ELEMENT_ERROR (sndiosink, RESOURCE, OPEN_WRITE, - (_("Could not establish connection to sndio")), - ("can't open connection to sndio")); - return FALSE; - } -no_server_info: - { - GST_ELEMENT_ERROR (sndiosink, RESOURCE, OPEN_WRITE, - (_("Failed to query sndio capabilities")), - ("couldn't get sndio info!")); - return FALSE; - } + return gst_sndio_open (&sink->sndio, SIO_PLAY); } static gboolean gst_sndiosink_close (GstAudioSink * asink) { - GstSndioSink *sndiosink = GST_SNDIOSINK (asink); - - GST_DEBUG_OBJECT (sndiosink, "close"); - - gst_caps_replace (&sndiosink->cur_caps, NULL); - sio_close (sndiosink->hdl); - sndiosink->hdl = NULL; - - return TRUE; -} - -static void -gst_sndiosink_cb(void *addr, int delta) -{ - GstSndioSink *sndiosink = GST_SNDIOSINK ((GstAudioSink *)addr); - - sndiosink->realpos += delta; + GstSndioSink *sink = GST_SNDIOSINK (asink); - if (sndiosink->realpos >= sndiosink->playpos) - sndiosink->latency = 0; - else - sndiosink->latency = sndiosink->playpos - sndiosink->realpos; + return gst_sndio_close (&sink->sndio); } static gboolean -gst_sndiosink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec) +gst_sndiosink_prepare (GstAudioSink * asink, GstAudioRingBufferSpec * spec) { - GstSndioSink *sndiosink = GST_SNDIOSINK (asink); - struct sio_par par; - int spec_bpf; - - GST_DEBUG_OBJECT (sndiosink, "prepare"); - - sndiosink->playpos = sndiosink->realpos = sndiosink->latency = 0; - - sio_initpar(&par); - par.sig = spec->sign; - par.le = !spec->bigend; - par.bits = spec->width; - // par.bps = spec->depth / 8; /* XXX */ - par.rate = spec->rate; - par.pchan = spec->channels; - - spec_bpf = ((spec->width / 8) * spec->channels); - - par.appbufsz = (spec->segsize * spec->segtotal) / spec_bpf; - - if (!sio_setpar(sndiosink->hdl, &par)) - goto cannot_configure; - - sio_getpar(sndiosink->hdl, &par); - - spec->sign = par.sig; - spec->bigend = !par.le; - spec->width = par.bits; - // spec->depth = par.bps * 8; /* XXX */ - spec->rate = par.rate; - spec->channels = par.pchan; - - sndiosink->bpf = par.bps * par.pchan; - - spec->segsize = par.round * par.pchan * par.bps; - spec->segtotal = par.bufsz / par.round; - - /* FIXME: this is wrong for signed ints (and the - * audioringbuffers should do it for us anyway) */ - spec->silence_sample[0] = 0; - spec->silence_sample[1] = 0; - spec->silence_sample[2] = 0; - spec->silence_sample[3] = 0; - - sio_onmove(sndiosink->hdl, gst_sndiosink_cb, sndiosink); - - if (!sio_start(sndiosink->hdl)) - goto cannot_start; - - GST_INFO_OBJECT (sndiosink, "successfully opened connection to sndio"); - - return TRUE; + GstSndioSink *sink = GST_SNDIOSINK (asink); - /* ERRORS */ -cannot_configure: - { - GST_ELEMENT_ERROR (sndiosink, RESOURCE, OPEN_WRITE, - (_("Could not configure sndio")), - ("can't configure sndio")); - return FALSE; - } -cannot_start: - { - GST_ELEMENT_ERROR (sndiosink, RESOURCE, OPEN_WRITE, - (_("Could not start sndio")), - ("can't start sndio")); - return FALSE; - } + return gst_sndio_prepare (&sink->sndio, spec); } static gboolean gst_sndiosink_unprepare (GstAudioSink * asink) { - GstSndioSink *sndiosink = GST_SNDIOSINK (asink); - - if (sndiosink->hdl == NULL) - return TRUE; + GstSndioSink *sink = GST_SNDIOSINK (asink); - sio_stop(sndiosink->hdl); - - return TRUE; + return gst_sndio_unprepare (&sink->sndio); } -static guint +static gint gst_sndiosink_write (GstAudioSink * asink, gpointer data, guint length) { - GstSndioSink *sndiosink = GST_SNDIOSINK (asink); + GstSndioSink *sink = GST_SNDIOSINK (asink); guint done; - done = sio_write (sndiosink->hdl, data, length); - - if (done == 0) - goto write_error; - - sndiosink->playpos += (done / sndiosink->bpf); - - data = (char *) data + done; - - return done; - - /* ERRORS */ -write_error: - { - GST_ELEMENT_ERROR (sndiosink, RESOURCE, WRITE, - ("Failed to write data to sndio"), GST_ERROR_SYSTEM); + if (length == 0) return 0; + done = sio_write (sink->sndio.hdl, data, length); + if (done == 0) { + GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, + ("Failed to write data to sndio"), (NULL)); + return 0; } + sink->sndio.delay += done; + return done; } static guint gst_sndiosink_delay (GstAudioSink * asink) { - GstSndioSink *sndiosink = GST_SNDIOSINK (asink); - - if (sndiosink->latency == (guint) - 1) { - GST_WARNING_OBJECT (asink, "couldn't get latency"); - return 0; - } + GstSndioSink *sink = GST_SNDIOSINK (asink); - GST_DEBUG_OBJECT (asink, "got latency: %u", sndiosink->latency); - - return sndiosink->latency; + return GST_SNDIO_DELAY(&sink->sndio); } static void gst_sndiosink_reset (GstAudioSink * asink) { - /* no way to flush the buffers with sndio ? */ - - GST_DEBUG_OBJECT (asink, "reset called"); } static void -gst_sndiosink_set_property (GObject * object, guint prop_id, const GValue * value, - GParamSpec * pspec) +gst_sndiosink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) { - GstSndioSink *sndiosink = GST_SNDIOSINK (object); - - switch (prop_id) { - case PROP_HOST: - g_free (sndiosink->host); - sndiosink->host = g_value_dup_string (value); - break; - default: - break; - } + GstSndioSink *sink = GST_SNDIOSINK (object); + + gst_sndio_set_property (&sink->sndio, prop_id, value, pspec); } static void gst_sndiosink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstSndioSink *sndiosink = GST_SNDIOSINK (object); - - switch (prop_id) { - case PROP_HOST: - g_value_set_string (value, sndiosink->host); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + GstSndioSink *sink = GST_SNDIOSINK (object); + + gst_sndio_get_property (&sink->sndio, prop_id, value, pspec); +} + +static void +gst_sndiosink_class_init (GstSndioSinkClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseSinkClass *gstbasesink_class; + GstAudioBaseSinkClass *gstbaseaudiosink_class; + GstAudioSinkClass *gstaudiosink_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + gstbasesink_class = (GstBaseSinkClass *) klass; + gstbaseaudiosink_class = (GstAudioBaseSinkClass *) klass; + gstaudiosink_class = (GstAudioSinkClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->finalize = gst_sndiosink_finalize; + gobject_class->get_property = gst_sndiosink_get_property; + gobject_class->set_property = gst_sndiosink_set_property; + + gst_element_class_set_static_metadata (gstelement_class, + "Audio sink (sndio)", "Sink/Audio", + "Output to a sound card via sndio", + "Jacob Meuser <jakemsr@sdf.lonestar.org>"); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sndiosink_factory)); + + gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_sndiosink_getcaps); + gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_sndiosink_open); + gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_sndiosink_prepare); + gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_sndiosink_unprepare); + gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_sndiosink_close); + gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_sndiosink_write); + gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_sndiosink_delay); + gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_sndiosink_reset); + + g_object_class_install_property (gobject_class, PROP_DEVICE, + g_param_spec_string ("device", "Device", + "sndio device as defined in sndio(7)", + SIO_DEVANY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_VOLUME, + g_param_spec_double ("volume", "Volume", + "Linear volume of this stream, 1.0=100%", 0.0, 1.0, + 1.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MUTE, + g_param_spec_boolean ("mute", "Mute", + "Mute state of this stream", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } |