diff options
-rw-r--r-- | configure.ac | 30 | ||||
-rw-r--r-- | ext/Makefile.am | 10 | ||||
-rw-r--r-- | ext/audiofile/gstafsink.c | 2 | ||||
-rw-r--r-- | ext/audiofile/gstafsrc.c | 2 | ||||
-rw-r--r-- | ext/jack/Makefile.am | 12 | ||||
-rw-r--r-- | ext/jack/README | 4 | ||||
-rw-r--r-- | ext/jack/gstjack.c | 593 | ||||
-rw-r--r-- | ext/jack/gstjack.h | 115 | ||||
-rw-r--r-- | gst/mpeg1sys/gstmpeg1systemencode.c | 4 |
9 files changed, 755 insertions, 17 deletions
diff --git a/configure.ac b/configure.ac index 5bca237d..67b17422 100644 --- a/configure.ac +++ b/configure.ac @@ -10,7 +10,7 @@ AM_DISABLE_STATIC dnl when going to/from release please set the nano (fourth number) right ! dnl We disable static building for development, for time savings AM_DISABLE_STATIC -AS_VERSION(gst-plugins, GST_PLUGINS, 0, 3, 2, 2) +AS_VERSION(gst-plugins, GST_PLUGINS, 0, 3, 3, 1) AM_INIT_AUTOMAKE($PACKAGE,$VERSION) AS_LIBTOOL(GST_PLUGINS, 0, 0, 0, yes) @@ -426,6 +426,23 @@ GST_CHECK_FEATURE(HTTP, [http plugins], gsthttpsrc, [ AC_SUBST(GST_HTTPSRC_GET_TYPE) ]) +dnl *** Jack *** +translit(dnm, m, l) AM_CONDITIONAL(USE_JACK, true) +GST_CHECK_FEATURE(JACK, Jack, jack, [ + PKG_CHECK_MODULES(JACK, jack, HAVE_JACK="yes", HAVE_JACK="no") + AC_SUBST(JACK_CFLAGS) + AC_SUBST(JACK_LIBS) +]) + +dnl *** jpeg *** +dnl FIXME: we could use header checks here as well IMO +translit(dnm, m, l) AM_CONDITIONAL(USE_JPEG, true) +GST_CHECK_FEATURE(JPEG, [jpeg], jpegenc jpegdec, [ + AC_CHECK_LIB(jpeg, jpeg_set_defaults, HAVE_JPEG="yes", HAVE_JPEG="no") + JPEG_LIBS="-ljpeg" + AC_SUBST(JPEG_LIBS) +]) + dnl *** lame *** translit(dnm, m, l) AM_CONDITIONAL(USE_LAME, true) GST_CHECK_FEATURE(LAME, [lame mp3 encoder library], lame, [ @@ -433,22 +450,12 @@ GST_CHECK_LIBHEADER(LAME, mp3lame, lame_init, -lm, lame/lame.h, HAVE_LAME="yes" ]) AC_SUBST(LAME_LIBS) - dnl FIXME : check if these CPP flags can be dealt with otherwise dnl libdvcheck_save_CPPFLAGS="$CPPFLAGS" dnl CPPFLAGS="$CPPFLAGS $GST_CFLAGS" dnl AC_CHECK_HEADER(libdv/dv.h, :, HAVE_LIBDV=no) dnl CPPFLAGS="$libdvcheck_save_CPPFLAGS" -dnl *** jpeg *** -dnl FIXME: we could use header checks here as well IMO -translit(dnm, m, l) AM_CONDITIONAL(USE_JPEG, true) -GST_CHECK_FEATURE(JPEG, [jpeg], jpegenc jpegdec, [ - AC_CHECK_LIB(jpeg, jpeg_set_defaults, HAVE_JPEG="yes", HAVE_JPEG="no") - JPEG_LIBS="-ljpeg" - AC_SUBST(JPEG_LIBS) -]) - dnl *** mad *** dnl FIXME: we could use header checks here as well IMO translit(dnm, m, l) AM_CONDITIONAL(USE_MAD, true) @@ -780,6 +787,7 @@ ext/gnomevfs/Makefile ext/gsm/Makefile ext/hermes/Makefile ext/http/Makefile +ext/jack/Makefile ext/jpeg/Makefile ext/ladspa/Makefile ext/lame/Makefile diff --git a/ext/Makefile.am b/ext/Makefile.am index e03242b7..39e6a986 100644 --- a/ext/Makefile.am +++ b/ext/Makefile.am @@ -100,6 +100,12 @@ else HTTP_DIR= endif +if USE_JACK +JACK_DIR=jack +else +JACK_DIR= +endif + if USE_JPEG JPEG_DIR=jpeg else @@ -203,7 +209,7 @@ SUBDIRS=$(A52DEC_DIR) $(AALIB_DIR) $(ALSA_DIR) \ $(AVIFILE_DIR) $(CDPARANOIA_DIR) $(DV_DIR) \ $(DVDREAD_DIR) $(ESD_DIR) $(FESTIVAL_DIR) \ $(FLAC_DIR) $(GNOMEVFS_DIR) $(GSM_DIR) \ - $(HERMES_DIR) $(HTTP_DIR) $(JPEG_DIR) \ + $(HERMES_DIR) $(HTTP_DIR) $(JACK_DIR) $(JPEG_DIR) \ $(LADSPA_DIR) $(LAME_DIR) \ $(MAD_DIR) $(MIKMOD_DIR) $(MJPEGTOOLS_DIR) $(MPEG2DEC_DIR) \ $(OPENQUICKTIME_DIR) $(RAW1394_DIR) $(RTP_DIR) \ @@ -216,7 +222,7 @@ DIST_SUBDIRS=\ audiofile cdparanoia dv \ dvdread esd festival \ flac gnomevfs gsm \ - hermes http jpeg \ + hermes http jack jpeg \ ladspa lame \ mad mikmod mjpegtools mpeg2dec \ openquicktime raw1394 rtp \ diff --git a/ext/audiofile/gstafsink.c b/ext/audiofile/gstafsink.c index d81c7498..24abae50 100644 --- a/ext/audiofile/gstafsink.c +++ b/ext/audiofile/gstafsink.c @@ -148,7 +148,7 @@ gst_afsink_class_init (GstAFSinkClass *klass) parent_class = g_type_class_ref (GST_TYPE_ELEMENT); - gst_element_install_std_props ( + gst_element_class_install_std_props ( GST_ELEMENT_CLASS (klass), "location", ARG_LOCATION, G_PARAM_READWRITE, NULL); diff --git a/ext/audiofile/gstafsrc.c b/ext/audiofile/gstafsrc.c index 4a4e64ef..657372e7 100644 --- a/ext/audiofile/gstafsrc.c +++ b/ext/audiofile/gstafsrc.c @@ -147,7 +147,7 @@ gst_afsrc_class_init (GstAFSrcClass *klass) parent_class = g_type_class_ref (GST_TYPE_ELEMENT); - gst_element_install_std_props ( + gst_element_class_install_std_props ( GST_ELEMENT_CLASS (klass), "location", ARG_LOCATION, G_PARAM_READWRITE, NULL); diff --git a/ext/jack/Makefile.am b/ext/jack/Makefile.am new file mode 100644 index 00000000..97f3f6f0 --- /dev/null +++ b/ext/jack/Makefile.am @@ -0,0 +1,12 @@ +plugindir = $(libdir)/gst + +plugin_LTLIBRARIES = libgstjack.la + +libgstjack_la_SOURCES = gstjack.c +libgstjack_la_CFLAGS = $(GST_CFLAGS) $(JACK_CFLAGS) +libgstjack_la_LIBADD = $(GST_LIBS) $(JACK_LIBS) +libgstjack_la_LDFLAGS = @GST_PLUGIN_LDFLAGS@ + +noinst_HEADERS = gstjack.h + +EXTRA_DIST = README diff --git a/ext/jack/README b/ext/jack/README new file mode 100644 index 00000000..2bb97beb --- /dev/null +++ b/ext/jack/README @@ -0,0 +1,4 @@ +to be written, la dee da + +jackit.sf.net + diff --git a/ext/jack/gstjack.c b/ext/jack/gstjack.c new file mode 100644 index 00000000..82da2aee --- /dev/null +++ b/ext/jack/gstjack.c @@ -0,0 +1,593 @@ +/* + Copyright (C) 2002 Andy Wingo <wingo@pobox.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <stdlib.h> +#include "gstjack.h" +#include <gst/audio/audio.h> + + +/* TODO: + + this element is still nonfunctional + + - work out the src side (caps setting, etc) + + future core TODO: + - make a jack clock provider + - add GST_ELEMENT_FIXED_DATA_RATE, GST_ELEMENT_QOS, + GST_ELEMENT_CHANGES_DATA_RATE element flags, and make the scheduler + sensitive to them +*/ + + +static GstElementDetails gst_jack_sink_details = { + "Jack Sink", + "Sink/Audio", + "Output to a Jack processing network: see README for more info", + VERSION, + "Andy Wingo <wingo@pobox.com>", + "(C) 2002 " +}; + +static GstElementDetails gst_jack_src_details = { + "Jack Src", + "Source/Audio", + "Input from a Jack processing network: see README for more info", + VERSION, + "Andy Wingo <wingo@pobox.com>", + "(C) 2002", +}; + + +static GstElement *parent_class = NULL; + +static void gst_jack_init(GstJack *this); +static void gst_jack_class_init(GstJackClass *klass); + +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 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 GstElementStateReturn gst_jack_change_state(GstElement *element); +static GstPadConnectReturn gst_jack_connect (GstPad *pad, GstCaps *caps); + +static void gst_jack_loop (GstElement *element); + +/* jack callbacks */ +static int process (nframes_t nframes, void *arg); +static int buffer_size (nframes_t nframes, void *arg); +static int sample_rate (nframes_t nframes, void *arg); +static void shutdown (void *arg); + + +enum { + ARG_0, + ARG_PORT_NAME_PREFIX, +}; + + +GType +gst_jack_get_type (void) +{ + static GType jack_type = 0; + + if (!jack_type) { + static const GTypeInfo jack_info = { + sizeof(GstJackClass), + NULL, + NULL, + NULL, + NULL, + NULL, + sizeof(GstJack), + 0, + NULL, + }; + jack_type = g_type_register_static (GST_TYPE_ELEMENT, "GstJack", &jack_info, 0); + } + return jack_type; +} + +GType +gst_jack_sink_get_type (void) +{ + static GType jack_type = 0; + + if (!jack_type) { + static const GTypeInfo jack_info = { + sizeof(GstJackClass), + NULL, + NULL, + (GClassInitFunc)gst_jack_class_init, + NULL, + NULL, + sizeof(GstJack), + 0, + (GInstanceInitFunc)gst_jack_init, + }; + jack_type = g_type_register_static (GST_TYPE_JACK, "GstJackSink", &jack_info, 0); + } + return jack_type; +} + +GType +gst_jack_src_get_type (void) +{ + static GType jack_type = 0; + + if (!jack_type) { + static const GTypeInfo jack_info = { + sizeof(GstJackClass), + NULL, + NULL, + (GClassInitFunc)gst_jack_class_init, + NULL, + NULL, + sizeof(GstJack), + 0, + (GInstanceInitFunc)gst_jack_init, + }; + jack_type = g_type_register_static (GST_TYPE_JACK, "GstJackSrc", &jack_info, 0); + } + return jack_type; +} + +static GstPadTemplate* +gst_jack_src_request_pad_factory(void) +{ + static GstPadTemplate *template = NULL; + + if (!template) + template = gst_padtemplate_new("%s", GST_PAD_SRC, GST_PAD_REQUEST, + gst_caps_new("src", "audio/raw", + GST_AUDIO_FLOAT_MONO_PAD_TEMPLATE_PROPS), + NULL); + + return template; +} + +static GstPadTemplate* +gst_jack_sink_request_pad_factory(void) +{ + static GstPadTemplate *template = NULL; + + if (!template) + template = gst_padtemplate_new("%s", GST_PAD_SINK, GST_PAD_REQUEST, + gst_caps_new("sink", "audio/raw", + GST_AUDIO_FLOAT_MONO_PAD_TEMPLATE_PROPS), + NULL); + + return template; +} + +static void +gst_jack_class_init(GstJackClass *klass) +{ + GObjectClass *object_class; + GstElementClass *element_class; + + 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; + + g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PORT_NAME_PREFIX, + g_param_spec_string("port-name-prefix","Port name prefix", + "String to prepend to jack port names", + "gst-", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + 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) +{ + 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 GstPad* +gst_jack_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *name) +{ + GstJack *this; + gchar *newname; + GList *l, **pad_list; + GstJackPad *pad; + + g_return_val_if_fail ((this = GST_JACK (element)), NULL); + + if (!this->client) + pad_list = &this->pads; + else if (this->direction == GST_PAD_SRC) + pad_list = &this->client->src_pads; + else + pad_list = &this->client->src_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 { + newname = g_strdup ("alsa_pcm:out_1"); + } + + pad = g_new0(GstJackPad, 1); + pad->name = g_strdup_printf ("%s%d", this->port_name_prefix, this->client->default_new_port_number++); + 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_connect_function (pad->pad, gst_jack_connect); + + if (this->client) + *pad_list = g_list_append (*pad_list, pad); +// this->pads = g_list_append (this->pads, pad); + + return pad->pad; +} + +static void +gst_jack_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + GstJack *this; + + this = (GstJack *)object; + 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; + default: + 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) +{ + GstJack *this; + + this = (GstJack *)object; + + switch (prop_id) { + case ARG_PORT_NAME_PREFIX: + g_value_set_string (value, this->port_name_prefix); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstElementStateReturn +gst_jack_change_state (GstElement *element) +{ + GstJack *this; + GstJackClient *client; + GstBin *bin; + GList *l = NULL, **pads; + enum JackPortFlags flags; + GstJackPad *pad; + + g_return_val_if_fail (element != NULL, FALSE); + this = GST_JACK (element); + client = this->client; + + switch (GST_STATE_PENDING (element)) { + case GST_STATE_NULL: + if (client) { + jack_client_close (client->client); + } + + break; + + case GST_STATE_READY: + if (!this->client) { + if (!(bin = gst_element_get_managing_bin (element))) { + g_warning ("jack element %s cannot be brought to READY state without a managing bin", + GST_OBJECT_NAME (GST_OBJECT (element))); + return GST_STATE_FAILURE; + } + + client = g_object_get_data (G_OBJECT (bin), "gst-jack-client"); + + if (!client) { + client = g_new0 (GstJackClient, 1); + if (!(client->client = jack_client_new ("gst-jack"))) { + g_warning ("jack server not running?"); + return GST_STATE_FAILURE; + } + + jack_set_process_callback (client->client, process, client); + jack_set_buffer_size_callback (client->client, buffer_size, client); + jack_set_sample_rate_callback (client->client, sample_rate, client); + jack_on_shutdown (client->client, shutdown, client); + + client->refcount = 1; + g_object_set_data (G_OBJECT (bin), "gst-jack-client", client); + client->manager = bin; + GST_FLAG_SET (GST_OBJECT (bin), GST_BIN_SELF_ITERATING); + } else { + client->refcount++; + } + this->client = client; + + /* fixme: verify that all names are unique */ + l = this->pads; + pads = (this->direction == GST_PAD_SRC) ? &client->src_pads : &client->sink_pads; + while (l) { + pad = GST_JACK_PAD (l); + *pads = g_list_append (*pads, pad); + l = g_list_next (l); + } + } + + /* fixme: there are a *lot* of problems here */ + if (GST_FLAG_IS_SET (GST_OBJECT (this), GST_JACK_OPEN)) { + l = this->pads; + while (l) { + jack_port_unregister (client->client, GST_JACK_PAD (l)->port); + l = g_list_next (l); + } + GST_FLAG_UNSET (GST_OBJECT (this), GST_JACK_OPEN); + } + break; + + case GST_STATE_PAUSED: + g_assert (client); + + if (!GST_FLAG_IS_SET (GST_OBJECT (this), GST_JACK_OPEN)) { + l = this->pads; + while (l) { + pad = GST_JACK_PAD (l); + + if (this->direction == GST_PAD_SINK) + flags = JackPortIsOutput; + else + flags = JackPortIsInput; + + pad->port = jack_port_register (client->client, pad->name, JACK_DEFAULT_AUDIO_TYPE, flags, 0); + if (jack_connect (client->client, pad->peer_name, jack_port_name (pad->port))) { + g_warning ("could not connect %s and %s", pad->peer_name, jack_port_name (pad->port)); + return GST_STATE_FAILURE; + } + + l = g_list_next (l); + } + GST_FLAG_SET (GST_OBJECT (this), GST_JACK_OPEN); + } + + if (GST_FLAG_IS_SET (GST_OBJECT (this), GST_JACK_ACTIVE)) { + jack_deactivate (client->client); + GST_FLAG_UNSET (GST_OBJECT (this), GST_JACK_ACTIVE); + } + break; + case GST_STATE_PLAYING: + if (!GST_FLAG_IS_SET (GST_OBJECT (this), GST_JACK_ACTIVE)) { + jack_activate (client->client); + GST_FLAG_SET (GST_OBJECT (this), GST_JACK_ACTIVE); + } + break; + } + + if (GST_ELEMENT_CLASS (parent_class)->change_state) + return GST_ELEMENT_CLASS (parent_class)->change_state (element); + + return GST_STATE_SUCCESS; +} + +static GstPadConnectReturn +gst_jack_connect (GstPad *pad, GstCaps *caps) +{ + GstJack *this; + + this = GST_JACK (gst_pad_get_parent (pad)); + g_return_val_if_fail (this != NULL, GST_PAD_CONNECT_REFUSED); + g_return_val_if_fail (GST_IS_JACK (this), GST_PAD_CONNECT_REFUSED); + + if (GST_CAPS_IS_FIXED (caps)) { + if (this->client && gst_caps_get_int (caps, "rate") != this->client->rate) + return GST_PAD_CONNECT_REFUSED; + + return GST_PAD_CONNECT_OK; + } + + return GST_PAD_CONNECT_DELAYED; +} + +static void +gst_jack_loop (GstElement *element) +{ + GstJack *this; + GList *pads; + gint len; + gchar *peeked; + gint avail; + GstEvent *event; + GstJackPad *pad; + GstBuffer *buffer; + + this = GST_JACK (element); + + g_return_if_fail(this != NULL); + len = this->client->nframes * sizeof (sample_t); + + do { + pads = this->pads; + while (pads) { + pad = GST_JACK_PAD (pads); + + if (this->direction == GST_PAD_SINK) { + if (pad->bs) + pad->bs = gst_bytestream_new (pad->pad); + + if (!(peeked = gst_bytestream_peek_bytes (pad->bs, len))) { + gst_bytestream_get_status(pad->bs, &avail, &event); + if (event) { + g_warning("got an event on jacksink"); + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { + /* really, we should just cut this pad out of the graph. let + * me know when this is needed ;) + * also, for sample accuracy etc, we should play avail + * bytes, but hey. */ + gst_element_set_eos(GST_ELEMENT(this)); + gst_event_free(event); + } + } else { + /* the element at the top of the chain did not emit an eos + * event. this is a Bug(tm) */ + g_assert_not_reached(); + } + } + + memcpy (pad->data, peeked, len); + gst_bytestream_flush (pad->bs, len); + } else { + buffer = gst_buffer_new (); + GST_BUFFER_DATA (buffer) = pad->data; + GST_BUFFER_SIZE (buffer) = len; + GST_BUFFER_MAXSIZE (buffer) = len; + + gst_pad_push (pad->pad, buffer); + } + pads = g_list_next (pads); + } + + gst_element_yield (element); + } while (TRUE); +} + +/* jack callbacks */ + +static int +process (nframes_t nframes, void *arg) +{ + GstJackClient *client = (GstJackClient*) arg; + GstJackPad *pad; + GList *l; + + g_assert (client); + + l = client->src_pads; + while (l) { + pad = GST_JACK_PAD (l); + pad->data = jack_port_get_buffer (pad->port, nframes); + l = g_list_next (l); + } + + l = client->sink_pads; + while (l) { + pad = GST_JACK_PAD (l); + pad->data = jack_port_get_buffer (pad->port, nframes); + l = g_list_next (l); + } + + client->nframes = nframes; + + if (!gst_bin_iterate (client->manager)) { + g_warning ("bin failed to iterate"); + return -1; + } + + /* that's all folks */ + + return 0; +} + +static int +buffer_size (nframes_t nframes, void *arg) +{ + printf ("the maximum buffer size is now %lu\n", nframes); + return 0; +} + +static int +sample_rate (nframes_t nframes, void *arg) +{ + GstJackClient *client = (GstJackClient*) arg; + printf ("the sample rate is now %lu/sec\n", nframes); + client->rate = nframes; + return 0; +} + +static void +shutdown (void *arg) +{ + GstJackClient *client = (GstJackClient*) arg; + printf ("shutdown\n"); +// gst_element_set_state (GST_ELEMENT (client->manager), GST_STATE_READY); +} + +static gboolean +plugin_init (GModule *module, GstPlugin *plugin) +{ + GstElementFactory *factory; + + if (!gst_library_load ("gstbytestream")) { + gst_info("jack: could not load support library: 'gstbytestream'\n"); + return FALSE; + } + + factory = gst_elementfactory_new ("jacksrc", GST_TYPE_JACK_SRC, &gst_jack_src_details); + g_return_val_if_fail (factory != NULL, FALSE); + gst_elementfactory_add_padtemplate (factory, gst_jack_src_request_pad_factory()); + gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); + + factory = gst_elementfactory_new ("jacksink", GST_TYPE_JACK_SINK, &gst_jack_sink_details); + g_return_val_if_fail (factory != NULL, FALSE); + gst_elementfactory_add_padtemplate (factory, gst_jack_sink_request_pad_factory()); + gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); + + gst_plugin_set_longname(plugin, "JACK plugin library"); + + return TRUE; +} + +GstPluginDesc plugin_desc = { + GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "jack", + plugin_init +}; + + diff --git a/ext/jack/gstjack.h b/ext/jack/gstjack.h new file mode 100644 index 00000000..da6940f2 --- /dev/null +++ b/ext/jack/gstjack.h @@ -0,0 +1,115 @@ +/* + Copyright (C) 2002 Andy Wingo <wingo@pobox.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 + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __GST_JACK_H__ +#define __GST_JACK_H__ + +#include <jack/jack.h> +#include <gst/gst.h> +#include <gst/bytestream/bytestream.h> + + +#define GST_JACK(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, GST_TYPE_JACK, GstJack) +#define GST_JACK_CLASS(klass) G_TYPE_CHECK_CLASS_CAST(klass, GST_TYPE_JACK, GstJackClass) +#define GST_IS_JACK(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, GST_TYPE_JACK) +#define GST_IS_JACK_CLASS(klass) G_TYPE_CHECK_CLASS_TYPE(klass, GST_TYPE_JACK) +#define GST_TYPE_JACK gst_jack_get_type() + +#define GST_JACK_SINK(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, GST_TYPE_JACK_SINK, GstJack) +#define GST_JACK_SINK_CLASS(klass) G_TYPE_CHECK_CLASS_CAST(klass, GST_TYPE_JACK_SINK, GstJackClass) +#define GST_IS_JACK_SINK(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, GST_TYPE_JACK_SINK) +#define GST_IS_JACK_SINK_CLASS(klass) G_TYPE_CHECK_CLASS_TYPE(klass, GST_TYPE_JACK_SINK) +#define GST_TYPE_JACK_SINK gst_jack_sink_get_type() + +#define GST_JACK_SRC(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, GST_TYPE_JACK_SRC, GstJack) +#define GST_JACK_SRC_CLASS(klass) G_TYPE_CHECK_CLASS_CAST(klass, GST_TYPE_JACK_SRC, GstJackClass) +#define GST_IS_JACK_SRC(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, GST_TYPE_JACK_SRC) +#define GST_IS_JACK_SRC_CLASS(klass) G_TYPE_CHECK_CLASS_TYPE(klass, GST_TYPE_JACK_SRC) +#define GST_TYPE_JACK_SRC gst_jack_src_get_type() + +#define GST_JACK_PAD(l) ((GstJackPad*)l->data) /* l is a GList */ + + +typedef struct _GstJack GstJack; +typedef struct _GstJackClass GstJackClass; +typedef GstJack GstJackSink; +typedef GstJackClass GstJackSinkClass; +typedef GstJack GstJackSrc; +typedef GstJackClass GstJackSrcClass; + + +enum { + GST_JACK_OPEN = GST_ELEMENT_FLAG_LAST, + GST_JACK_ACTIVE, + GST_JACK_FLAG_LAST = GST_ELEMENT_FLAG_LAST + 3, +}; + + +typedef struct { + GstPad *pad; + void *data; + const gchar *name; + const gchar *peer_name; + GstByteStream *bs; + jack_port_t *port; +} GstJackPad; + +typedef struct { + GstBin *manager; + + jack_client_t *client; + gint default_new_port_number; + + /* lists of GstJackPads */ + GList *sink_pads; + GList *src_pads; + + gchar *client_name; + + guint rate; + nframes_t nframes; + + guint refcount; +} GstJackClient; + +struct _GstJack { + GstElement element; + + /* list of GstJackPads */ + GList *pads; + + /* for convenience */ + GstPadDirection direction; + + gchar *port_name_prefix; + + /* there is exactly one client per managing bin */ + GstJackClient *client; +}; + +struct _GstJackClass { + GstElementClass parent_class; +}; + + +GType gst_jack_get_type (void); +GType gst_jack_sink_get_type (void); +GType gst_jack_src_get_type (void); + + +#endif /* __GST_JACK_H__ */ diff --git a/gst/mpeg1sys/gstmpeg1systemencode.c b/gst/mpeg1sys/gstmpeg1systemencode.c index d8927d0f..c863da9e 100644 --- a/gst/mpeg1sys/gstmpeg1systemencode.c +++ b/gst/mpeg1sys/gstmpeg1systemencode.c @@ -60,7 +60,7 @@ GST_PADTEMPLATE_FACTORY (src_factory, ) ) GST_PADTEMPLATE_FACTORY (video_sink_factory, - "video_%02d", + "video_%d", GST_PAD_SINK, GST_PAD_REQUEST, GST_CAPS_NEW ( @@ -72,7 +72,7 @@ GST_PADTEMPLATE_FACTORY (video_sink_factory, ) GST_PADTEMPLATE_FACTORY (audio_sink_factory, - "audio_%02d", + "audio_%d", GST_PAD_SINK, GST_PAD_REQUEST, GST_CAPS_NEW ( |