diff options
Diffstat (limited to 'ext/jack')
-rw-r--r-- | ext/jack/gstjack.c | 656 | ||||
-rw-r--r-- | ext/jack/gstjack.h | 72 | ||||
-rw-r--r-- | ext/jack/gstjackbin.c | 476 |
3 files changed, 621 insertions, 583 deletions
diff --git a/ext/jack/gstjack.c b/ext/jack/gstjack.c index a43c6707..41f078bc 100644 --- a/ext/jack/gstjack.c +++ b/ext/jack/gstjack.c @@ -38,118 +38,122 @@ /* elementfactory information */ static GstElementDetails gst_jack_bin_details = { - "Jack Bin", - "Generic/Bin", - "Jack processing bin", - "Andy Wingo <wingo@pobox.com>", + "Jack Bin", + "Generic/Bin", + "Jack processing bin", + "Andy Wingo <wingo@pobox.com>", }; -static GstElementDetails gst_jack_sink_details = { - "Jack Sink", - "Sink/Audio", - "Output to a Jack processing network", - "Andy Wingo <wingo@pobox.com>", +static GstElementDetails gst_jack_sink_details = { + "Jack Sink", + "Sink/Audio", + "Output to a Jack processing network", + "Andy Wingo <wingo@pobox.com>", }; -static GstElementDetails gst_jack_src_details = { - "Jack Src", - "Source/Audio", - "Input from a Jack processing network", - "Andy Wingo <wingo@pobox.com>", +static GstElementDetails gst_jack_src_details = { + "Jack Src", + "Source/Audio", + "Input from a Jack processing network", + "Andy Wingo <wingo@pobox.com>", }; static GHashTable *port_name_counts = NULL; static GstElementClass *parent_class = NULL; -static void gst_jack_base_init (gpointer g_class); -static void gst_jack_src_base_init (gpointer g_class); -static void gst_jack_sink_base_init (gpointer g_class); -static void gst_jack_init(GstJack *this); -static void gst_jack_class_init(GstJackClass *klass); -static void gst_jack_set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec); -static void gst_jack_get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec); - -static GstPadTemplate* gst_jack_src_request_pad_factory(); -static GstPadTemplate* gst_jack_sink_request_pad_factory(); -static GstPad* gst_jack_request_new_pad (GstElement *element, GstPadTemplate *templ, - const gchar *name); -static GstElementStateReturn gst_jack_change_state (GstElement *element); -static GstPadLinkReturn gst_jack_link (GstPad *pad, const GstCaps *caps); - -static void gst_jack_loop (GstElement *element); - - -enum { - ARG_0, - ARG_PORT_NAME_PREFIX, +static void gst_jack_base_init (gpointer g_class); +static void gst_jack_src_base_init (gpointer g_class); +static void gst_jack_sink_base_init (gpointer g_class); +static void gst_jack_init (GstJack * this); +static void gst_jack_class_init (GstJackClass * klass); +static void gst_jack_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_jack_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstPadTemplate *gst_jack_src_request_pad_factory (); +static GstPadTemplate *gst_jack_sink_request_pad_factory (); +static GstPad *gst_jack_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name); +static GstElementStateReturn gst_jack_change_state (GstElement * element); +static GstPadLinkReturn gst_jack_link (GstPad * pad, const GstCaps * caps); + +static void gst_jack_loop (GstElement * element); + + +enum +{ + ARG_0, + ARG_PORT_NAME_PREFIX, }; GType -gst_jack_get_type (void) +gst_jack_get_type (void) { static GType jack_type = 0; if (!jack_type) { static const GTypeInfo jack_info = { - sizeof(GstJackClass), + sizeof (GstJackClass), gst_jack_base_init, NULL, NULL, NULL, NULL, - sizeof(GstJack), + sizeof (GstJack), 0, NULL, }; - jack_type = g_type_register_static (GST_TYPE_ELEMENT, "GstJack", &jack_info, 0); + jack_type = + g_type_register_static (GST_TYPE_ELEMENT, "GstJack", &jack_info, 0); } return jack_type; } GType -gst_jack_sink_get_type (void) +gst_jack_sink_get_type (void) { static GType jack_type = 0; - + if (!jack_type) { static const GTypeInfo jack_info = { - sizeof(GstJackClass), + sizeof (GstJackClass), gst_jack_sink_base_init, NULL, - (GClassInitFunc)gst_jack_class_init, + (GClassInitFunc) gst_jack_class_init, NULL, NULL, - sizeof(GstJack), + sizeof (GstJack), 0, - (GInstanceInitFunc)gst_jack_init, + (GInstanceInitFunc) gst_jack_init, }; - jack_type = g_type_register_static (GST_TYPE_JACK, "GstJackSink", &jack_info, 0); + jack_type = + g_type_register_static (GST_TYPE_JACK, "GstJackSink", &jack_info, 0); } return jack_type; } GType -gst_jack_src_get_type (void) +gst_jack_src_get_type (void) { static GType jack_type = 0; - + if (!jack_type) { static const GTypeInfo jack_info = { - sizeof(GstJackClass), + sizeof (GstJackClass), gst_jack_src_base_init, NULL, - (GClassInitFunc)gst_jack_class_init, + (GClassInitFunc) gst_jack_class_init, NULL, NULL, - sizeof(GstJack), + sizeof (GstJack), 0, - (GInstanceInitFunc)gst_jack_init, + (GInstanceInitFunc) gst_jack_init, }; - jack_type = g_type_register_static (GST_TYPE_JACK, "GstJackSrc", &jack_info, 0); + jack_type = + g_type_register_static (GST_TYPE_JACK, "GstJackSrc", &jack_info, 0); } return jack_type; } @@ -167,7 +171,8 @@ gst_jack_src_base_init (gpointer g_class) { GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - gst_element_class_add_pad_template (element_class, gst_jack_src_request_pad_factory ()); + gst_element_class_add_pad_template (element_class, + gst_jack_src_request_pad_factory ()); gst_element_class_set_details (element_class, &gst_jack_src_details); } @@ -176,342 +181,349 @@ gst_jack_sink_base_init (gpointer g_class) { GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - gst_element_class_add_pad_template (element_class, gst_jack_sink_request_pad_factory ()); + gst_element_class_add_pad_template (element_class, + gst_jack_sink_request_pad_factory ()); gst_element_class_set_details (element_class, &gst_jack_sink_details); } static void -gst_jack_class_init(GstJackClass *klass) +gst_jack_class_init (GstJackClass * klass) { - GObjectClass *object_class; - GstElementClass *element_class; - GParamSpec *pspec; - gchar *prefix; - - object_class = (GObjectClass *)klass; - element_class = (GstElementClass *)klass; - - if (parent_class == NULL) - parent_class = g_type_class_ref(GST_TYPE_ELEMENT); - - object_class->get_property = gst_jack_get_property; - object_class->set_property = gst_jack_set_property; - - if (GST_IS_JACK_SINK_CLASS (klass)) - prefix = "gst-out-"; - else - prefix = "gst-in-"; - - pspec = g_param_spec_string ("port-name-prefix", "Port name prefix", - "String to prepend to jack port names", - prefix, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); - g_object_class_install_property (object_class, ARG_PORT_NAME_PREFIX, pspec); - - element_class->change_state = gst_jack_change_state; - - element_class->request_new_pad = gst_jack_request_new_pad; + GObjectClass *object_class; + GstElementClass *element_class; + GParamSpec *pspec; + gchar *prefix; + + object_class = (GObjectClass *) klass; + element_class = (GstElementClass *) klass; + + if (parent_class == NULL) + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + + object_class->get_property = gst_jack_get_property; + object_class->set_property = gst_jack_set_property; + + if (GST_IS_JACK_SINK_CLASS (klass)) + prefix = "gst-out-"; + else + prefix = "gst-in-"; + + pspec = g_param_spec_string ("port-name-prefix", "Port name prefix", + "String to prepend to jack port names", + prefix, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_object_class_install_property (object_class, ARG_PORT_NAME_PREFIX, pspec); + + element_class->change_state = gst_jack_change_state; + + element_class->request_new_pad = gst_jack_request_new_pad; } static void -gst_jack_init(GstJack *this) +gst_jack_init (GstJack * this) { - if (G_OBJECT_TYPE (this) == GST_TYPE_JACK_SRC) - this->direction = GST_PAD_SRC; - else if (G_OBJECT_TYPE (this) == GST_TYPE_JACK_SINK) - this->direction = GST_PAD_SINK; - else - g_assert_not_reached (); - - gst_element_set_loop_function (GST_ELEMENT (this), gst_jack_loop); + if (G_OBJECT_TYPE (this) == GST_TYPE_JACK_SRC) + this->direction = GST_PAD_SRC; + else if (G_OBJECT_TYPE (this) == GST_TYPE_JACK_SINK) + this->direction = GST_PAD_SINK; + else + g_assert_not_reached (); + + gst_element_set_loop_function (GST_ELEMENT (this), gst_jack_loop); } static void -gst_jack_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +gst_jack_set_property (GObject * object, guint prop_id, const GValue * value, + GParamSpec * pspec) { - GstJack *this = (GstJack*)object; + GstJack *this = (GstJack *) object; - switch (prop_id) { + switch (prop_id) { case ARG_PORT_NAME_PREFIX: - if (this->port_name_prefix) - g_free (this->port_name_prefix); - this->port_name_prefix = g_strdup (g_value_get_string (value)); - break; + if (this->port_name_prefix) + g_free (this->port_name_prefix); + this->port_name_prefix = g_strdup (g_value_get_string (value)); + break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - return; - } + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + return; + } } static void -gst_jack_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +gst_jack_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) { - GstJack *this = (GstJack*)object; + GstJack *this = (GstJack *) object; - switch (prop_id) { + switch (prop_id) { case ARG_PORT_NAME_PREFIX: - g_value_set_string (value, this->port_name_prefix); - break; + g_value_set_string (value, this->port_name_prefix); + break; default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } -static GstPadTemplate* +static GstPadTemplate * gst_jack_src_request_pad_factory (void) { - static GstPadTemplate *template = NULL; - - if (!template) { - GstCaps *caps; - caps = gst_caps_from_string (GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_CAPS); - template = gst_pad_template_new ("%s", GST_PAD_SRC, - GST_PAD_REQUEST, caps); - } - - return template; + static GstPadTemplate *template = NULL; + + if (!template) { + GstCaps *caps; + + caps = gst_caps_from_string (GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_CAPS); + template = gst_pad_template_new ("%s", GST_PAD_SRC, GST_PAD_REQUEST, caps); + } + + return template; } -static GstPadTemplate* +static GstPadTemplate * gst_jack_sink_request_pad_factory (void) { - static GstPadTemplate *template = NULL; - - if (!template) { - GstCaps *caps; - caps = gst_caps_from_string (GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_CAPS); - template = gst_pad_template_new ("%s", GST_PAD_SINK, - GST_PAD_REQUEST, caps); - } - - return template; + static GstPadTemplate *template = NULL; + + if (!template) { + GstCaps *caps; + + caps = gst_caps_from_string (GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_CAPS); + template = gst_pad_template_new ("%s", GST_PAD_SINK, GST_PAD_REQUEST, caps); + } + + return template; } -static GstPad* -gst_jack_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *name) +static GstPad * +gst_jack_request_new_pad (GstElement * element, GstPadTemplate * templ, + const gchar * name) { - GstJack *this; - gchar *newname; - GList *l, **pad_list; - GstJackPad *pad; - gint count; - - g_return_val_if_fail ((this = GST_JACK (element)), NULL); - - if (!this->bin) - pad_list = &this->pads; - else if (this->direction == GST_PAD_SRC) - pad_list = &this->bin->src_pads; - else - pad_list = &this->bin->sink_pads; - - if (name) { - l = *pad_list; - while (l) { - if (strcmp (GST_JACK_PAD(l)->name, name) == 0) { - g_warning("requested port name %s already in use.", name); - return NULL; - } - l = l->next; - } - newname = g_strdup (name); - } else { - if (this->direction == GST_PAD_SINK) - newname = g_strdup ("alsa_pcm:playback_1"); - else - newname = g_strdup ("alsa_pcm:capture_1"); + GstJack *this; + gchar *newname; + GList *l, **pad_list; + GstJackPad *pad; + gint count; + + g_return_val_if_fail ((this = GST_JACK (element)), NULL); + + if (!this->bin) + pad_list = &this->pads; + else if (this->direction == GST_PAD_SRC) + pad_list = &this->bin->src_pads; + else + pad_list = &this->bin->sink_pads; + + if (name) { + l = *pad_list; + while (l) { + if (strcmp (GST_JACK_PAD (l)->name, name) == 0) { + g_warning ("requested port name %s already in use.", name); + return NULL; + } + l = l->next; } - - pad = g_new0 (GstJackPad, 1); - - if (!port_name_counts) - port_name_counts = g_hash_table_new (g_str_hash, g_str_equal); - - count = GPOINTER_TO_INT (g_hash_table_lookup (port_name_counts, this->port_name_prefix)); - g_hash_table_insert (port_name_counts, g_strdup (this->port_name_prefix), GINT_TO_POINTER (count+1)); - - pad->name = g_strdup_printf ("%s%d", this->port_name_prefix, count); - - pad->peer_name = newname; - pad->pad = gst_pad_new_from_template (templ, newname); - gst_element_add_pad (GST_ELEMENT (this), pad->pad); - gst_pad_set_link_function (pad->pad, gst_jack_link); - - this->pads = g_list_append (this->pads, pad); - - g_print ("returning from request_new_pad, pad %s created, to connect to %s\n", pad->name, pad->peer_name); - return pad->pad; + newname = g_strdup (name); + } else { + if (this->direction == GST_PAD_SINK) + newname = g_strdup ("alsa_pcm:playback_1"); + else + newname = g_strdup ("alsa_pcm:capture_1"); + } + + pad = g_new0 (GstJackPad, 1); + + if (!port_name_counts) + port_name_counts = g_hash_table_new (g_str_hash, g_str_equal); + + count = + GPOINTER_TO_INT (g_hash_table_lookup (port_name_counts, + this->port_name_prefix)); + g_hash_table_insert (port_name_counts, g_strdup (this->port_name_prefix), + GINT_TO_POINTER (count + 1)); + + pad->name = g_strdup_printf ("%s%d", this->port_name_prefix, count); + + pad->peer_name = newname; + pad->pad = gst_pad_new_from_template (templ, newname); + gst_element_add_pad (GST_ELEMENT (this), pad->pad); + gst_pad_set_link_function (pad->pad, gst_jack_link); + + this->pads = g_list_append (this->pads, pad); + + g_print ("returning from request_new_pad, pad %s created, to connect to %s\n", + pad->name, pad->peer_name); + return pad->pad; } static GstElementStateReturn -gst_jack_change_state (GstElement *element) +gst_jack_change_state (GstElement * element) { - GstJack *this; - GList *l = NULL, **pads; - GstJackPad *pad; - GstCaps *caps; - - g_return_val_if_fail (element != NULL, FALSE); - this = GST_JACK (element); - - switch (GST_STATE_PENDING (element)) { + GstJack *this; + GList *l = NULL, **pads; + GstJackPad *pad; + GstCaps *caps; + + g_return_val_if_fail (element != NULL, FALSE); + this = GST_JACK (element); + + switch (GST_STATE_PENDING (element)) { case GST_STATE_NULL: - JACK_DEBUG ("%s: NULL", GST_OBJECT_NAME (GST_OBJECT (this))); + JACK_DEBUG ("%s: NULL", GST_OBJECT_NAME (GST_OBJECT (this))); + + break; - break; - case GST_STATE_READY: - JACK_DEBUG ("%s: READY", GST_OBJECT_NAME (GST_OBJECT (this))); - - if (!this->bin) { - if (!(this->bin = (GstJackBin*)gst_element_get_managing_bin (element)) - || !GST_IS_JACK_BIN (this->bin)) { - this->bin = NULL; - g_warning ("jack element %s needs to be contained in a jack bin.", - GST_OBJECT_NAME (element)); - return GST_STATE_FAILURE; - } - - /* fixme: verify that all names are unique */ - l = this->pads; - pads = (this->direction == GST_PAD_SRC) ? &this->bin->src_pads : &this->bin->sink_pads; - while (l) { - pad = GST_JACK_PAD (l); - JACK_DEBUG ("%s: appending pad %s:%s to list", GST_OBJECT_NAME (this), pad->name, pad->peer_name); - *pads = g_list_append (*pads, pad); - l = g_list_next (l); - } - } - break; - + JACK_DEBUG ("%s: READY", GST_OBJECT_NAME (GST_OBJECT (this))); + + if (!this->bin) { + if (!(this->bin = (GstJackBin *) gst_element_get_managing_bin (element)) + || !GST_IS_JACK_BIN (this->bin)) { + this->bin = NULL; + g_warning ("jack element %s needs to be contained in a jack bin.", + GST_OBJECT_NAME (element)); + return GST_STATE_FAILURE; + } + + /* fixme: verify that all names are unique */ + l = this->pads; + pads = + (this->direction == + GST_PAD_SRC) ? &this->bin->src_pads : &this->bin->sink_pads; + while (l) { + pad = GST_JACK_PAD (l); + JACK_DEBUG ("%s: appending pad %s:%s to list", GST_OBJECT_NAME (this), + pad->name, pad->peer_name); + *pads = g_list_append (*pads, pad); + l = g_list_next (l); + } + } + break; + case GST_STATE_PAUSED: - JACK_DEBUG ("%s: PAUSED", GST_OBJECT_NAME (GST_OBJECT (this))); - - if (GST_STATE (element) == GST_STATE_READY) { - /* we're in READY->PAUSED */ - l = this->pads; - while (l) { - pad = GST_JACK_PAD (l); - caps = gst_caps_copy (gst_pad_get_negotiated_caps (pad->pad)); - gst_caps_set_simple (caps, - "rate", G_TYPE_INT, (int)this->bin->rate, - "buffer-frames", G_TYPE_INT, (gint)this->bin->nframes, - NULL); - if (gst_pad_try_set_caps (pad->pad, caps) <= 0) - return GST_STATE_FAILURE; - l = g_list_next (l); - } - } - break; + JACK_DEBUG ("%s: PAUSED", GST_OBJECT_NAME (GST_OBJECT (this))); + + if (GST_STATE (element) == GST_STATE_READY) { + /* we're in READY->PAUSED */ + l = this->pads; + while (l) { + pad = GST_JACK_PAD (l); + caps = gst_caps_copy (gst_pad_get_negotiated_caps (pad->pad)); + gst_caps_set_simple (caps, + "rate", G_TYPE_INT, (int) this->bin->rate, + "buffer-frames", G_TYPE_INT, (gint) this->bin->nframes, NULL); + if (gst_pad_try_set_caps (pad->pad, caps) <= 0) + return GST_STATE_FAILURE; + l = g_list_next (l); + } + } + break; case GST_STATE_PLAYING: - JACK_DEBUG ("%s: PLAYING", GST_OBJECT_NAME (GST_OBJECT (this))); - break; - } - - JACK_DEBUG ("%s: state change finished", GST_OBJECT_NAME (this)); - - if (GST_ELEMENT_CLASS (parent_class)->change_state) - return GST_ELEMENT_CLASS (parent_class)->change_state (element); + JACK_DEBUG ("%s: PLAYING", GST_OBJECT_NAME (GST_OBJECT (this))); + break; + } + + JACK_DEBUG ("%s: state change finished", GST_OBJECT_NAME (this)); - return GST_STATE_SUCCESS; + if (GST_ELEMENT_CLASS (parent_class)->change_state) + return GST_ELEMENT_CLASS (parent_class)->change_state (element); + + return GST_STATE_SUCCESS; } static GstPadLinkReturn -gst_jack_link (GstPad *pad, const GstCaps *caps) +gst_jack_link (GstPad * pad, const GstCaps * caps) { GstJack *this; gint rate, buffer_frames; GstStructure *structure; - + this = GST_JACK (GST_OBJECT_PARENT (pad)); - + structure = gst_caps_get_structure (caps, 0); - gst_structure_get_int (structure, "rate", &rate); - gst_structure_get_int (structure, "buffer-frames", &buffer_frames); + gst_structure_get_int (structure, "rate", &rate); + gst_structure_get_int (structure, "buffer-frames", &buffer_frames); if (this->bin && (rate != this->bin->rate || - buffer_frames != this->bin->nframes)) - return GST_PAD_LINK_REFUSED; - + buffer_frames != this->bin->nframes)) + return GST_PAD_LINK_REFUSED; + return GST_PAD_LINK_OK; } static void -gst_jack_loop (GstElement *element) +gst_jack_loop (GstElement * element) { - GstJack *this; - GList *pads; - gint len; - GstJackPad *pad; - GstBuffer *buffer; - - this = GST_JACK (element); - - len = this->bin->nframes * sizeof (sample_t); - - pads = this->pads; - while (pads) { - pad = GST_JACK_PAD (pads); - - if (this->direction == GST_PAD_SINK) { - buffer = GST_BUFFER (gst_pad_pull (pad->pad)); - - if (GST_IS_EVENT (buffer)) { - GstEvent *event = GST_EVENT (buffer); - switch (GST_EVENT_TYPE (buffer)) { - case GST_EVENT_EOS: - gst_element_set_eos (element); - gst_event_unref (event); - return; - default: - gst_pad_event_default (pad->pad, event); - return; - } - } - - /* if the other plugins only give out buffer-frames or less (as - they should), if the length of the GstBuffer is different - from nframes then the buffer is short and we will get EOS - next */ - memcpy (pad->data, GST_BUFFER_DATA (buffer), - GST_BUFFER_SIZE (buffer)); - if (len != GST_BUFFER_SIZE (buffer)) - memset (pad->data + GST_BUFFER_SIZE (buffer), 0, - len - GST_BUFFER_SIZE (buffer)); - - gst_buffer_unref (buffer); - } else { - buffer = gst_buffer_new (); - gst_buffer_set_data (buffer, pad->data, len); - GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_DONTFREE); - - gst_pad_push (pad->pad, GST_DATA (buffer)); - } - pads = g_list_next (pads); + GstJack *this; + GList *pads; + gint len; + GstJackPad *pad; + GstBuffer *buffer; + + this = GST_JACK (element); + + len = this->bin->nframes * sizeof (sample_t); + + pads = this->pads; + while (pads) { + pad = GST_JACK_PAD (pads); + + if (this->direction == GST_PAD_SINK) { + buffer = GST_BUFFER (gst_pad_pull (pad->pad)); + + if (GST_IS_EVENT (buffer)) { + GstEvent *event = GST_EVENT (buffer); + + switch (GST_EVENT_TYPE (buffer)) { + case GST_EVENT_EOS: + gst_element_set_eos (element); + gst_event_unref (event); + return; + default: + gst_pad_event_default (pad->pad, event); + return; + } + } + + /* if the other plugins only give out buffer-frames or less (as + they should), if the length of the GstBuffer is different + from nframes then the buffer is short and we will get EOS + next */ + memcpy (pad->data, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer)); + if (len != GST_BUFFER_SIZE (buffer)) + memset (pad->data + GST_BUFFER_SIZE (buffer), 0, + len - GST_BUFFER_SIZE (buffer)); + + gst_buffer_unref (buffer); + } else { + buffer = gst_buffer_new (); + gst_buffer_set_data (buffer, pad->data, len); + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_DONTFREE); + + gst_pad_push (pad->pad, GST_DATA (buffer)); } + pads = g_list_next (pads); + } } static gboolean -plugin_init (GstPlugin *plugin) +plugin_init (GstPlugin * plugin) { - if (!gst_element_register (plugin, "jackbin", GST_RANK_NONE, GST_TYPE_JACK_BIN)) + if (!gst_element_register (plugin, "jackbin", GST_RANK_NONE, + GST_TYPE_JACK_BIN)) return FALSE; - if (!gst_element_register (plugin, "jacksrc", GST_RANK_NONE, GST_TYPE_JACK_SRC)) + if (!gst_element_register (plugin, "jacksrc", GST_RANK_NONE, + GST_TYPE_JACK_SRC)) return FALSE; - if (!gst_element_register (plugin, "jacksink", GST_RANK_NONE, GST_TYPE_JACK_SINK)) + if (!gst_element_register (plugin, "jacksink", GST_RANK_NONE, + GST_TYPE_JACK_SINK)) return FALSE; - + return TRUE; } -GST_PLUGIN_DEFINE ( - GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "jack", - "Jack Plugin Library", - plugin_init, - VERSION, - "GPL", - GST_PACKAGE, - GST_ORIGIN) +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "jack", + "Jack Plugin Library", plugin_init, VERSION, "GPL", GST_PACKAGE, GST_ORIGIN) diff --git a/ext/jack/gstjack.h b/ext/jack/gstjack.h index 87d7d611..f5a5416f 100644 --- a/ext/jack/gstjack.h +++ b/ext/jack/gstjack.h @@ -51,7 +51,7 @@ #define GST_IS_JACK_BIN_CLASS(klass) G_TYPE_CHECK_CLASS_TYPE(klass, GST_TYPE_JACK_BIN) #define GST_TYPE_JACK_BIN gst_jack_bin_get_type() -#define GST_JACK_PAD(l) ((GstJackPad*)l->data) /* l is a GList */ +#define GST_JACK_PAD(l) ((GstJackPad*)l->data) /* l is a GList */ typedef struct _GstJack GstJack; @@ -64,59 +64,65 @@ typedef GstJack GstJackSrc; typedef GstJackClass GstJackSrcClass; -enum { - GST_JACK_OPEN = GST_BIN_FLAG_LAST, - GST_JACK_ACTIVE, - GST_JACK_FLAG_LAST = GST_BIN_FLAG_LAST + 3, +enum +{ + GST_JACK_OPEN = GST_BIN_FLAG_LAST, + GST_JACK_ACTIVE, + GST_JACK_FLAG_LAST = GST_BIN_FLAG_LAST + 3, }; typedef jack_default_audio_sample_t sample_t; -typedef struct { - GstPad *pad; - void *data; - const gchar *name; - const gchar *peer_name; - jack_port_t *port; +typedef struct +{ + GstPad *pad; + void *data; + const gchar *name; + const gchar *peer_name; + jack_port_t *port; } GstJackPad; -struct _GstJack { - GstElement element; +struct _GstJack +{ + GstElement element; - /* list of GstJackPads */ - GList *pads; + /* list of GstJackPads */ + GList *pads; - /* for convenience */ - GstPadDirection direction; + /* for convenience */ + GstPadDirection direction; - gchar *port_name_prefix; + gchar *port_name_prefix; - GstJackBin *bin; + GstJackBin *bin; }; -struct _GstJackClass { - GstElementClass parent_class; +struct _GstJackClass +{ + GstElementClass parent_class; }; -struct _GstJackBin { - GstBin bin; +struct _GstJackBin +{ + GstBin bin; - jack_client_t *client; - gint default_new_port_number; + jack_client_t *client; + gint default_new_port_number; - /* lists of GstJackPads */ - GList *sink_pads; - GList *src_pads; + /* lists of GstJackPads */ + GList *sink_pads; + GList *src_pads; - gchar *client_name; + gchar *client_name; - guint rate; - jack_nframes_t nframes; + guint rate; + jack_nframes_t nframes; }; -struct _GstJackBinClass { - GstBinClass parent_class; +struct _GstJackBinClass +{ + GstBinClass parent_class; }; diff --git a/ext/jack/gstjackbin.c b/ext/jack/gstjackbin.c index b0cea9bc..9be6e915 100644 --- a/ext/jack/gstjackbin.c +++ b/ext/jack/gstjackbin.c @@ -29,10 +29,10 @@ static GstBinClass *parent_class = NULL; -static void gst_jack_bin_init(GstJackBin *this); -static void gst_jack_bin_class_init(GstJackBinClass *klass); +static void gst_jack_bin_init (GstJackBin * this); +static void gst_jack_bin_class_init (GstJackBinClass * klass); -static GstElementStateReturn gst_jack_bin_change_state(GstElement *element); +static GstElementStateReturn gst_jack_bin_change_state (GstElement * element); /* jack callbacks */ static int process (jack_nframes_t nframes, void *arg); @@ -48,196 +48,213 @@ static gboolean watchdog_please_set_the_jackbin_to_ready = FALSE; * so set the state of the bin to READY. */ GType -gst_jack_bin_get_type (void) +gst_jack_bin_get_type (void) { - static GType jack_bin_type = 0; -if (!jack_bin_type) { - static const GTypeInfo jack_bin_info = { - sizeof(GstJackBinClass), - NULL, - NULL, - (GClassInitFunc)gst_jack_bin_class_init, - NULL, - NULL, - sizeof(GstJackBin), - 0, - (GInstanceInitFunc)gst_jack_bin_init, - }; - jack_bin_type = g_type_register_static (GST_TYPE_BIN, "GstJackBin", &jack_bin_info, 0); - } - return jack_bin_type; + static GType jack_bin_type = 0; + + if (!jack_bin_type) { + static const GTypeInfo jack_bin_info = { + sizeof (GstJackBinClass), + NULL, + NULL, + (GClassInitFunc) gst_jack_bin_class_init, + NULL, + NULL, + sizeof (GstJackBin), + 0, + (GInstanceInitFunc) gst_jack_bin_init, + }; + jack_bin_type = + g_type_register_static (GST_TYPE_BIN, "GstJackBin", &jack_bin_info, 0); + } + return jack_bin_type; } static void -gst_jack_bin_class_init(GstJackBinClass *klass) +gst_jack_bin_class_init (GstJackBinClass * klass) { - GObjectClass *object_class; - GstElementClass *element_class; - - object_class = (GObjectClass *)klass; - element_class = (GstElementClass *)klass; - - parent_class = g_type_class_ref(GST_TYPE_BIN); - - element_class->change_state = gst_jack_bin_change_state; + GObjectClass *object_class; + GstElementClass *element_class; + + object_class = (GObjectClass *) klass; + element_class = (GstElementClass *) klass; + + parent_class = g_type_class_ref (GST_TYPE_BIN); + + element_class->change_state = gst_jack_bin_change_state; } static void -gst_jack_bin_init(GstJackBin *this) +gst_jack_bin_init (GstJackBin * this) { - GST_DEBUG ("initializing jack bin"); - - /* jack bins are managing bins and iterate themselves */ - GST_FLAG_SET (this, GST_BIN_FLAG_MANAGER); - GST_FLAG_SET (this, GST_BIN_SELF_SCHEDULABLE); - - /* make a new scheduler and associate it with the bin */ - gst_scheduler_factory_make (NULL, GST_ELEMENT (this)); + GST_DEBUG ("initializing jack bin"); + + /* jack bins are managing bins and iterate themselves */ + GST_FLAG_SET (this, GST_BIN_FLAG_MANAGER); + GST_FLAG_SET (this, GST_BIN_SELF_SCHEDULABLE); + + /* make a new scheduler and associate it with the bin */ + gst_scheduler_factory_make (NULL, GST_ELEMENT (this)); } static GstElementStateReturn -gst_jack_bin_change_state (GstElement *element) +gst_jack_bin_change_state (GstElement * element) { - GstJackBin *this; - GList *l = NULL; - GstJackPad *pad; - - g_return_val_if_fail (element != NULL, FALSE); - this = GST_JACK_BIN (element); - - switch (GST_STATE_PENDING (element)) { + GstJackBin *this; + GList *l = NULL; + GstJackPad *pad; + + g_return_val_if_fail (element != NULL, FALSE); + this = GST_JACK_BIN (element); + + switch (GST_STATE_PENDING (element)) { case GST_STATE_NULL: - JACK_DEBUG ("jackbin: NULL state"); - if (this->client) { - JACK_DEBUG ("jackbin: closing client"); - jack_client_close (this->client); - this->client = NULL; - } - - if (_jackbin) - signal (SIGHUP, SIG_DFL); - _jackbin = NULL; - - if (GST_ELEMENT_CLASS (parent_class)->change_state) - return GST_ELEMENT_CLASS (parent_class)->change_state (element); - break; - + JACK_DEBUG ("jackbin: NULL state"); + if (this->client) { + JACK_DEBUG ("jackbin: closing client"); + jack_client_close (this->client); + this->client = NULL; + } + + if (_jackbin) + signal (SIGHUP, SIG_DFL); + _jackbin = NULL; + + if (GST_ELEMENT_CLASS (parent_class)->change_state) + return GST_ELEMENT_CLASS (parent_class)->change_state (element); + break; + case GST_STATE_READY: - JACK_DEBUG ("jackbin: READY"); - - _jackbin = this; - signal (SIGHUP, sighup_handler); - - if (!this->client) { - if (!(this->client = jack_client_new ("gst-jack"))) { - g_warning ("jack server not running?"); - return GST_STATE_FAILURE; - } - - gst_scheduler_setup (GST_ELEMENT_SCHED (this)); - - jack_set_process_callback (this->client, process, this); - jack_set_sample_rate_callback (this->client, sample_rate, this); - jack_set_buffer_size_callback (this->client, buffer_size, this); - this->nframes = jack_get_buffer_size (this->client); - jack_on_shutdown (this->client, shutdown, this); - } - - if (GST_FLAG_IS_SET (GST_OBJECT (this), GST_JACK_OPEN)) { - l = this->src_pads; - while (l) { - JACK_DEBUG ("jackbin: unregistering pad %s:%s", GST_JACK_PAD (l)->name, GST_JACK_PAD (l)->peer_name); - jack_port_unregister (this->client, GST_JACK_PAD (l)->port); - l = g_list_next (l); - } - l = this->sink_pads; - while (l) { - JACK_DEBUG ("jackbin: unregistering pad %s:%s", GST_JACK_PAD (l)->name, GST_JACK_PAD (l)->peer_name); - jack_port_unregister (this->client, GST_JACK_PAD (l)->port); - l = g_list_next (l); - } - GST_FLAG_UNSET (GST_OBJECT (this), GST_JACK_OPEN); - - if (GST_FLAG_IS_SET (GST_OBJECT (this), GST_JACK_ACTIVE)) { - JACK_DEBUG ("jackbin: deactivating client"); - jack_deactivate (this->client); - GST_FLAG_UNSET (GST_OBJECT (this), GST_JACK_ACTIVE); - } - } - - if (GST_ELEMENT_CLASS (parent_class)->change_state) - return GST_ELEMENT_CLASS (parent_class)->change_state (element); - break; - + JACK_DEBUG ("jackbin: READY"); + + _jackbin = this; + signal (SIGHUP, sighup_handler); + + if (!this->client) { + if (!(this->client = jack_client_new ("gst-jack"))) { + g_warning ("jack server not running?"); + return GST_STATE_FAILURE; + } + + gst_scheduler_setup (GST_ELEMENT_SCHED (this)); + + jack_set_process_callback (this->client, process, this); + jack_set_sample_rate_callback (this->client, sample_rate, this); + jack_set_buffer_size_callback (this->client, buffer_size, this); + this->nframes = jack_get_buffer_size (this->client); + jack_on_shutdown (this->client, shutdown, this); + } + + if (GST_FLAG_IS_SET (GST_OBJECT (this), GST_JACK_OPEN)) { + l = this->src_pads; + while (l) { + JACK_DEBUG ("jackbin: unregistering pad %s:%s", + GST_JACK_PAD (l)->name, GST_JACK_PAD (l)->peer_name); + jack_port_unregister (this->client, GST_JACK_PAD (l)->port); + l = g_list_next (l); + } + l = this->sink_pads; + while (l) { + JACK_DEBUG ("jackbin: unregistering pad %s:%s", + GST_JACK_PAD (l)->name, GST_JACK_PAD (l)->peer_name); + jack_port_unregister (this->client, GST_JACK_PAD (l)->port); + l = g_list_next (l); + } + GST_FLAG_UNSET (GST_OBJECT (this), GST_JACK_OPEN); + + if (GST_FLAG_IS_SET (GST_OBJECT (this), GST_JACK_ACTIVE)) { + JACK_DEBUG ("jackbin: deactivating client"); + jack_deactivate (this->client); + GST_FLAG_UNSET (GST_OBJECT (this), GST_JACK_ACTIVE); + } + } + + if (GST_ELEMENT_CLASS (parent_class)->change_state) + return GST_ELEMENT_CLASS (parent_class)->change_state (element); + break; + case GST_STATE_PAUSED: - JACK_DEBUG ("jackbin: PAUSED"); - - if (!GST_FLAG_IS_SET (GST_OBJECT (this), GST_JACK_OPEN)) { - l = this->src_pads; - while (l) { - pad = GST_JACK_PAD (l); - JACK_DEBUG ("jackbin: registering input port %s (peer %s)", pad->name, pad->peer_name); - pad->port = jack_port_register (this->client, pad->name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput|JackPortIsTerminal, 0); - l = g_list_next (l); - } - l = this->sink_pads; - while (l) { - pad = GST_JACK_PAD (l); - JACK_DEBUG ("jackbin: registering output port %s (peer %s)", pad->name, pad->peer_name); - pad->port = jack_port_register (this->client, pad->name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput|JackPortIsTerminal, 0); - l = g_list_next (l); - } - - /* must activate before connecting */ - if (!GST_FLAG_IS_SET (GST_OBJECT (this), GST_JACK_ACTIVE)) { - JACK_DEBUG ("jackbin: activating client"); - jack_activate (this->client); - GST_FLAG_SET (GST_OBJECT (this), GST_JACK_ACTIVE); - } - - l = this->src_pads; - while (l) { - pad = GST_JACK_PAD (l); - JACK_DEBUG ("connecting jack port %s to gst jack port %s", pad->peer_name, jack_port_name (pad->port)); - if (jack_connect (this->client, pad->peer_name, jack_port_name (pad->port))) { - g_warning ("jackbin: could not connect %s and %s", pad->peer_name, jack_port_name (pad->port)); - return GST_STATE_FAILURE; - } - l = g_list_next (l); - } - l = this->sink_pads; - while (l) { - pad = GST_JACK_PAD (l); - JACK_DEBUG ("connecting gst jack port %s to jack port %s", jack_port_name (pad->port), pad->peer_name); - if (jack_connect (this->client, jack_port_name (pad->port), pad->peer_name)) { - g_warning ("jackbin: could not connect %s and %s", pad->peer_name, jack_port_name (pad->port)); - return GST_STATE_FAILURE; - } - l = g_list_next (l); - } - - JACK_DEBUG ("jackbin: setting OPEN flag"); - GST_FLAG_SET (GST_OBJECT (this), GST_JACK_OPEN); - - if (GST_ELEMENT_CLASS (parent_class)->change_state) - return GST_ELEMENT_CLASS (parent_class)->change_state (element); - } else { - if (GST_ELEMENT_CLASS (parent_class)->change_state) - return GST_ELEMENT_CLASS (parent_class)->change_state (element); - } - - break; + JACK_DEBUG ("jackbin: PAUSED"); + + if (!GST_FLAG_IS_SET (GST_OBJECT (this), GST_JACK_OPEN)) { + l = this->src_pads; + while (l) { + pad = GST_JACK_PAD (l); + JACK_DEBUG ("jackbin: registering input port %s (peer %s)", pad->name, + pad->peer_name); + pad->port = + jack_port_register (this->client, pad->name, + JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0); + l = g_list_next (l); + } + l = this->sink_pads; + while (l) { + pad = GST_JACK_PAD (l); + JACK_DEBUG ("jackbin: registering output port %s (peer %s)", + pad->name, pad->peer_name); + pad->port = + jack_port_register (this->client, pad->name, + JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, + 0); + l = g_list_next (l); + } + + /* must activate before connecting */ + if (!GST_FLAG_IS_SET (GST_OBJECT (this), GST_JACK_ACTIVE)) { + JACK_DEBUG ("jackbin: activating client"); + jack_activate (this->client); + GST_FLAG_SET (GST_OBJECT (this), GST_JACK_ACTIVE); + } + + l = this->src_pads; + while (l) { + pad = GST_JACK_PAD (l); + JACK_DEBUG ("connecting jack port %s to gst jack port %s", + pad->peer_name, jack_port_name (pad->port)); + if (jack_connect (this->client, pad->peer_name, + jack_port_name (pad->port))) { + g_warning ("jackbin: could not connect %s and %s", pad->peer_name, + jack_port_name (pad->port)); + return GST_STATE_FAILURE; + } + l = g_list_next (l); + } + l = this->sink_pads; + while (l) { + pad = GST_JACK_PAD (l); + JACK_DEBUG ("connecting gst jack port %s to jack port %s", + jack_port_name (pad->port), pad->peer_name); + if (jack_connect (this->client, jack_port_name (pad->port), + pad->peer_name)) { + g_warning ("jackbin: could not connect %s and %s", pad->peer_name, + jack_port_name (pad->port)); + return GST_STATE_FAILURE; + } + l = g_list_next (l); + } + + JACK_DEBUG ("jackbin: setting OPEN flag"); + GST_FLAG_SET (GST_OBJECT (this), GST_JACK_OPEN); + + if (GST_ELEMENT_CLASS (parent_class)->change_state) + return GST_ELEMENT_CLASS (parent_class)->change_state (element); + } else { + if (GST_ELEMENT_CLASS (parent_class)->change_state) + return GST_ELEMENT_CLASS (parent_class)->change_state (element); + } + + break; case GST_STATE_PLAYING: - JACK_DEBUG ("jackbin: PLAYING"); - - if (GST_ELEMENT_CLASS (parent_class)->change_state) - return GST_ELEMENT_CLASS (parent_class)->change_state (element); - break; - } - - JACK_DEBUG ("jackbin: state change finished"); - - return GST_STATE_SUCCESS; + JACK_DEBUG ("jackbin: PLAYING"); + + if (GST_ELEMENT_CLASS (parent_class)->change_state) + return GST_ELEMENT_CLASS (parent_class)->change_state (element); + break; + } + + JACK_DEBUG ("jackbin: state change finished"); + + return GST_STATE_SUCCESS; } /* jack callbacks */ @@ -247,76 +264,79 @@ gst_jack_bin_change_state (GstElement *element) static int process (jack_nframes_t nframes, void *arg) { - GstJackBin *bin = (GstJackBin*) arg; - GstJackPad *pad; - GList *l; - - g_assert (bin); - - JACK_DEBUG ("jackbin: process()"); - - if (GST_STATE (bin) != GST_STATE_PLAYING) { - JACK_DEBUG ("jackbin: bin is not PLAYING yet, returning"); - return 0; - } else { - JACK_DEBUG ("jackbin: we are PLAYING, let's process()"); - } - - l = bin->src_pads; - while (l) { - pad = GST_JACK_PAD (l); - pad->data = jack_port_get_buffer (pad->port, nframes); - l = g_list_next (l); - } - - l = bin->sink_pads; - while (l) { - pad = GST_JACK_PAD (l); - pad->data = jack_port_get_buffer (pad->port, nframes); - l = g_list_next (l); - } - - bin->nframes = nframes; - - JACK_DEBUG ("jackbin: iterating to process %ld frames of audio...", nframes); - if (!gst_bin_iterate (GST_BIN (bin))) { - g_warning ("bin failed to iterate"); - return -1; - } - - /* that's all folks */ - - return 0; + GstJackBin *bin = (GstJackBin *) arg; + GstJackPad *pad; + GList *l; + + g_assert (bin); + + JACK_DEBUG ("jackbin: process()"); + + if (GST_STATE (bin) != GST_STATE_PLAYING) { + JACK_DEBUG ("jackbin: bin is not PLAYING yet, returning"); + return 0; + } else { + JACK_DEBUG ("jackbin: we are PLAYING, let's process()"); + } + + l = bin->src_pads; + while (l) { + pad = GST_JACK_PAD (l); + pad->data = jack_port_get_buffer (pad->port, nframes); + l = g_list_next (l); + } + + l = bin->sink_pads; + while (l) { + pad = GST_JACK_PAD (l); + pad->data = jack_port_get_buffer (pad->port, nframes); + l = g_list_next (l); + } + + bin->nframes = nframes; + + JACK_DEBUG ("jackbin: iterating to process %ld frames of audio...", nframes); + if (!gst_bin_iterate (GST_BIN (bin))) { + g_warning ("bin failed to iterate"); + return -1; + } + + /* that's all folks */ + + return 0; } static int sample_rate (jack_nframes_t nframes, void *arg) { - GstJackBin *bin = (GstJackBin*) arg; - JACK_DEBUG ("the sample rate is now %lu/sec\n", nframes); - bin->rate = nframes; - return 0; + GstJackBin *bin = (GstJackBin *) arg; + + JACK_DEBUG ("the sample rate is now %lu/sec\n", nframes); + bin->rate = nframes; + return 0; } static int buffer_size (jack_nframes_t nframes, void *arg) { - GstJackBin *bin = (GstJackBin*) arg; - JACK_DEBUG ("the buffer size is now %lu\n", nframes); - bin->nframes = nframes; - return 0; + GstJackBin *bin = (GstJackBin *) arg; + + JACK_DEBUG ("the buffer size is now %lu\n", nframes); + bin->nframes = nframes; + return 0; } static void shutdown (void *arg) { /* GstJackClient *client = (GstJackClient*) arg; */ - printf ("shutdown %p\n", arg); + printf ("shutdown %p\n", arg); /* gst_element_set_state (GST_ELEMENT (client->manager), GST_STATE_READY); */ } -static void sighup_handler (int sig) +static void +sighup_handler (int sig) { - g_message ("got sighup, setting state to READY"); - watchdog_please_set_the_jackbin_to_ready = TRUE; + g_message ("got sighup, setting state to READY"); + watchdog_please_set_the_jackbin_to_ready = TRUE; } |