summaryrefslogtreecommitdiffstats
path: root/ext/jack/gstjackaudiosink.c
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2007-03-08 15:24:52 +0000
committerWim Taymans <wim.taymans@gmail.com>2007-03-08 15:24:52 +0000
commitf1b91e369d111f10996074c14c6a4843c36d5d41 (patch)
treea31fe3a3f7123b5201ade0a405d2f170b2d39737 /ext/jack/gstjackaudiosink.c
parent49e29a2716904ce50c1db8b561801f2b87378821 (diff)
downloadgst-plugins-bad-f1b91e369d111f10996074c14c6a4843c36d5d41.tar.gz
gst-plugins-bad-f1b91e369d111f10996074c14c6a4843c36d5d41.tar.bz2
gst-plugins-bad-f1b91e369d111f10996074c14c6a4843c36d5d41.zip
ext/jack/: Make an object to manage client connections to the jack server which we will use in the future to run sele...
Original commit message from CVS: Includes patch by: Paul Davis <paul at linuxaudiosystems dot com> * ext/jack/Makefile.am: * ext/jack/gstjackaudioclient.c: (gst_jack_audio_client_init), (jack_process_cb), (jack_sample_rate_cb), (jack_buffer_size_cb), (jack_shutdown_cb), (connection_find), (gst_jack_audio_make_connection), (gst_jack_audio_get_connection), (gst_jack_audio_unref_connection), (gst_jack_audio_connection_add_client), (gst_jack_audio_connection_remove_client), (gst_jack_audio_client_new), (gst_jack_audio_client_free), (gst_jack_audio_client_get_client), (gst_jack_audio_client_set_active): * ext/jack/gstjackaudioclient.h: Make an object to manage client connections to the jack server which we will use in the future to run selected jack elements with the same jack connection. Make some stuff a bit more threadsafe. Activate the jack client ASAP. * ext/jack/gstjackaudiosink.c: (gst_jack_audio_sink_allocate_channels), (gst_jack_audio_sink_free_channels), (jack_process_cb), (gst_jack_ring_buffer_open_device), (gst_jack_ring_buffer_close_device), (gst_jack_ring_buffer_acquire), (gst_jack_ring_buffer_release), (gst_jack_audio_sink_class_init), (gst_jack_audio_sink_init), (gst_jack_audio_sink_getcaps): * ext/jack/gstjackaudiosink.h: Use new client object to manage connections. Don't remove and recreate all ports, try to reuse them.
Diffstat (limited to 'ext/jack/gstjackaudiosink.c')
-rw-r--r--ext/jack/gstjackaudiosink.c143
1 files changed, 83 insertions, 60 deletions
diff --git a/ext/jack/gstjackaudiosink.c b/ext/jack/gstjackaudiosink.c
index b57e51cf..6f0ea571 100644
--- a/ext/jack/gstjackaudiosink.c
+++ b/ext/jack/gstjackaudiosink.c
@@ -96,8 +96,6 @@ struct _GstJackRingBuffer
gint sample_rate;
gint buffer_size;
gint channels;
-
- jack_port_t **outport;
};
struct _GstJackRingBufferClass
@@ -123,6 +121,60 @@ static gboolean gst_jack_ring_buffer_pause (GstRingBuffer * buf);
static gboolean gst_jack_ring_buffer_stop (GstRingBuffer * buf);
static guint gst_jack_ring_buffer_delay (GstRingBuffer * buf);
+static gboolean
+gst_jack_audio_sink_allocate_channels (GstJackAudioSink * sink, gint channels)
+{
+ jack_client_t *client;
+
+ client = gst_jack_audio_client_get_client (sink->client);
+
+ /* remove ports we don't need */
+ while (sink->port_count > channels) {
+ jack_port_unregister (client, sink->ports[--sink->port_count]);
+ }
+
+ /* alloc enough output ports */
+ sink->ports = g_realloc (sink->ports, sizeof (jack_port_t *) * channels);
+
+ /* create an output port for each channel */
+ while (sink->port_count < channels) {
+ gchar *name;
+
+ /* port names start from 1 */
+ name = g_strdup_printf ("out_%d", sink->port_count + 1);
+ sink->ports[sink->port_count] =
+ jack_port_register (client, name,
+ JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+ if (sink->ports[sink->port_count] == NULL)
+ return FALSE;
+
+ sink->port_count++;
+
+ g_free (name);
+ }
+ return TRUE;
+}
+
+static void
+gst_jack_audio_sink_free_channels (GstJackAudioSink * sink)
+{
+ gint res, i = 0;
+ jack_client_t *client;
+
+ client = gst_jack_audio_client_get_client (sink->client);
+
+ /* get rid of all ports */
+ while (sink->port_count) {
+ GST_LOG_OBJECT (sink, "unregister port %d", i);
+ if ((res = jack_port_unregister (client, sink->ports[i++]))) {
+ GST_DEBUG_OBJECT (sink, "unregister of port failed (%d)", res);
+ }
+ sink->port_count--;
+ }
+ g_free (sink->ports);
+ sink->ports = NULL;
+}
+
/* ringbuffer abstract base class */
static GType
gst_jack_ring_buffer_get_type (void)
@@ -206,7 +258,7 @@ jack_process_cb (jack_nframes_t nframes, void *arg)
/* get target buffers */
for (i = 0; i < channels; i++) {
- buffers[i] = (sample_t *) jack_port_get_buffer (abuf->outport[i], nframes);
+ buffers[i] = (sample_t *) jack_port_get_buffer (sink->ports[i], nframes);
}
if (gst_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
@@ -343,30 +395,19 @@ static gboolean
gst_jack_ring_buffer_open_device (GstRingBuffer * buf)
{
GstJackAudioSink *sink;
- jack_options_t options;
jack_status_t status = 0;
sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf));
GST_DEBUG_OBJECT (sink, "open");
- /* never start a server */
- options = JackNoStartServer;
- /* if we have a servername, use it */
- if (sink->server != NULL)
- options |= JackServerName;
- /* open the client */
- sink->client = jack_client_open ("GStreamer", options, &status, sink->server);
+ sink->client = gst_jack_audio_client_new ("GStreamer", sink->server,
+ GST_JACK_CLIENT_SINK,
+ jack_shutdown_cb,
+ jack_process_cb, jack_buffer_size_cb, jack_sample_rate_cb, buf, &status);
if (sink->client == NULL)
goto could_not_open;
- /* set our callbacks */
- jack_set_process_callback (sink->client, jack_process_cb, buf);
- /* these callbacks cause us to error */
- jack_set_buffer_size_callback (sink->client, jack_buffer_size_cb, buf);
- jack_set_sample_rate_callback (sink->client, jack_sample_rate_cb, buf);
- jack_on_shutdown (sink->client, jack_shutdown_cb, buf);
-
GST_DEBUG_OBJECT (sink, "opened");
return TRUE;
@@ -391,17 +432,13 @@ static gboolean
gst_jack_ring_buffer_close_device (GstRingBuffer * buf)
{
GstJackAudioSink *sink;
- gint res;
sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf));
GST_DEBUG_OBJECT (sink, "close");
- if ((res = jack_client_close (sink->client))) {
- /* just a warning, we assume the client is gone. */
- GST_ELEMENT_WARNING (sink, RESOURCE, CLOSE,
- (NULL), ("Jack client close error (%d)", res));
- }
+ gst_jack_audio_sink_free_channels (sink);
+ gst_jack_audio_client_free (sink->client);
sink->client = NULL;
return TRUE;
@@ -426,37 +463,26 @@ gst_jack_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
const char **ports;
gint sample_rate, buffer_size;
gint i, channels, res;
+ jack_client_t *client;
sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf));
abuf = GST_JACK_RING_BUFFER_CAST (buf);
GST_DEBUG_OBJECT (sink, "acquire");
+ client = gst_jack_audio_client_get_client (sink->client);
+
/* sample rate must be that of the server */
- sample_rate = jack_get_sample_rate (sink->client);
+ sample_rate = jack_get_sample_rate (client);
if (sample_rate != spec->rate)
goto wrong_samplerate;
channels = spec->channels;
- /* alloc enough output ports */
- abuf->outport = g_new (jack_port_t *, channels);
-
- /* create an output port for each channel */
- for (i = 0; i < channels; i++) {
- gchar *name;
-
- /* port names start from 1 */
- name = g_strdup_printf ("out_%d", i + 1);
- abuf->outport[i] = jack_port_register (sink->client, name,
- JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
- if (abuf->outport[i] == NULL)
- goto out_of_ports;
+ if (!gst_jack_audio_sink_allocate_channels (sink, channels))
+ goto out_of_ports;
- g_free (name);
- }
-
- buffer_size = jack_get_buffer_size (sink->client);
+ buffer_size = jack_get_buffer_size (client);
/* the segment size in bytes, this is large enough to hold a buffer of 32bit floats
* for all channels */
@@ -473,7 +499,7 @@ gst_jack_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize);
memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data));
- if ((res = jack_activate (sink->client)))
+ if ((res = gst_jack_audio_client_set_active (sink->client, TRUE)))
goto could_not_activate;
/* if we need to automatically connect the ports, do so now. We must do this
@@ -482,7 +508,7 @@ gst_jack_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
/* find all the physical input ports. A physical input port is a port
* associated with a hardware device. Someone needs connect to a physical
* port in order to hear something. */
- ports = jack_get_ports (sink->client, NULL, NULL,
+ ports = jack_get_ports (client, NULL, NULL,
JackPortIsPhysical | JackPortIsInput);
if (ports == NULL) {
/* no ports? fine then we don't do anything except for posting a warning
@@ -501,7 +527,7 @@ gst_jack_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
break;
}
/* connect the port to a physical port */
- if ((res = jack_connect (sink->client, jack_port_name (abuf->outport[i]),
+ if ((res = jack_connect (client, jack_port_name (sink->ports[i]),
ports[i])))
goto cannot_connect;
}
@@ -550,30 +576,20 @@ gst_jack_ring_buffer_release (GstRingBuffer * buf)
{
GstJackAudioSink *sink;
GstJackRingBuffer *abuf;
- gint i, res;
+ gint res;
abuf = GST_JACK_RING_BUFFER_CAST (buf);
sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf));
GST_DEBUG_OBJECT (sink, "release");
- if ((res = jack_deactivate (sink->client))) {
+ if ((res = gst_jack_audio_client_set_active (sink->client, FALSE))) {
/* we only warn, this means the server is probably shut down and the client
* is gone anyway. */
GST_ELEMENT_WARNING (sink, RESOURCE, CLOSE, (NULL),
("Could not deactivate Jack client (%d)", res));
}
- /* remove all ports */
- for (i = 0; i < abuf->channels; i++) {
- GST_LOG_OBJECT (sink, "unregister port %d", i);
- if ((res = jack_port_unregister (sink->client, abuf->outport[i]))) {
- GST_DEBUG_OBJECT (sink, "unregister of port failed (%d)", res);
- }
- abuf->outport[i] = NULL;
- }
- g_free (abuf->outport);
- abuf->outport = NULL;
abuf->channels = -1;
abuf->buffer_size = -1;
abuf->sample_rate = -1;
@@ -746,6 +762,8 @@ gst_jack_audio_sink_class_init (GstJackAudioSinkClass * klass)
gstbaseaudiosink_class->create_ringbuffer =
GST_DEBUG_FUNCPTR (gst_jack_audio_sink_create_ringbuffer);
+
+ gst_jack_audio_client_init ();
}
static void
@@ -754,6 +772,8 @@ gst_jack_audio_sink_init (GstJackAudioSink * sink,
{
sink->connect = DEFAULT_PROP_CONNECT;
sink->server = g_strdup (DEFAULT_PROP_SERVER);
+ sink->ports = NULL;
+ sink->port_count = 0;
}
static void
@@ -806,14 +826,17 @@ gst_jack_audio_sink_getcaps (GstBaseSink * bsink)
const char **ports;
gint min, max;
gint rate;
+ jack_client_t *client;
if (sink->client == NULL)
goto no_client;
+ client = gst_jack_audio_client_get_client (sink->client);
+
if (sink->connect == GST_JACK_CONNECT_AUTO) {
/* get a port count, this is the number of channels we can automatically
* connect. */
- ports = jack_get_ports (sink->client, NULL, NULL,
+ ports = jack_get_ports (client, NULL, NULL,
JackPortIsPhysical | JackPortIsInput);
max = 0;
if (ports != NULL) {
@@ -822,13 +845,13 @@ gst_jack_audio_sink_getcaps (GstBaseSink * bsink)
} else
max = 0;
} else {
- /* we allow any number of pads, somoething else is going to connect the
+ /* we allow any number of pads, something else is going to connect the
* pads. */
max = G_MAXINT;
}
min = MIN (1, max);
- rate = jack_get_sample_rate (sink->client);
+ rate = jack_get_sample_rate (client);
GST_DEBUG_OBJECT (sink, "got %d-%d ports, samplerate: %d", min, max, rate);