Commit f1b91e36 authored by Paul Davis's avatar Paul Davis Committed by Wim Taymans

ext/jack/: Make an object to manage client connections to the jack server...

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.
parent 49e29a27
2007-03-08 Wim Taymans <wim@fluendo.com>
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.
2007-03-07 Sebastian Dröge <slomo@circular-chaos.org>
* ext/wavpack/gstwavpack.c: (plugin_init):
......
common @ 7c5a0ab6
Subproject commit c4f56a657d79aee0e3fc25ef2bcf876f9f3c1593
Subproject commit 7c5a0ab68de1fed4e5a1fd473160debc2c4c7b89
plugin_LTLIBRARIES = libgstjack.la
libgstjack_la_SOURCES = gstjack.c gstjackaudiosink.c
libgstjack_la_SOURCES = gstjack.c gstjackaudiosink.c gstjackaudioclient.c
libgstjack_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(JACK_CFLAGS)
libgstjack_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) $(JACK_LIBS)
libgstjack_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
noinst_HEADERS = gstjackaudiosink.h
noinst_HEADERS = gstjackaudiosink.h gstjackaudioclient.h
EXTRA_DIST = README
This diff is collapsed.
/* GStreamer
* Copyright (C) 2006 Wim Taymans <wim@fluendo.com>
*
* gstjackaudioclient.h:
*
* 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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_JACK_AUDIO_CLIENT_H__
#define __GST_JACK_AUDIO_CLIENT_H__
#include <jack/jack.h>
#include <gst/gst.h>
G_BEGIN_DECLS
typedef enum
{
GST_JACK_CLIENT_SOURCE,
GST_JACK_CLIENT_SINK
} GstJackClientType;
typedef struct _GstJackAudioClient GstJackAudioClient;
void gst_jack_audio_client_init (void);
GstJackAudioClient * gst_jack_audio_client_new (const gchar *id, const gchar *server,
GstJackClientType type,
void (*shutdown) (void *arg),
JackProcessCallback process,
JackBufferSizeCallback buffer_size,
JackSampleRateCallback sample_rate,
gpointer user_data,
jack_status_t *status);
void gst_jack_audio_client_free (GstJackAudioClient *client);
jack_client_t * gst_jack_audio_client_get_client (GstJackAudioClient *client);
gboolean gst_jack_audio_client_set_active (GstJackAudioClient *client, gboolean active);
G_END_DECLS
#endif /* __GST_JACK_AUDIO_CLIENT_H__ */
......@@ -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);
......
......@@ -27,6 +27,8 @@
#include <gst/gst.h>
#include <gst/audio/gstbaseaudiosink.h>
#include "gstjackaudioclient.h"
G_BEGIN_DECLS
#define GST_TYPE_JACK_AUDIO_SINK (gst_jack_audio_sink_get_type())
......@@ -63,6 +65,7 @@ typedef enum {
struct _GstJackAudioSink {
GstBaseAudioSink element;
/*< private >*/
/* cached caps */
GstCaps *caps;
......@@ -71,17 +74,15 @@ struct _GstJackAudioSink {
gchar *server;
/* our client */
jack_client_t *client;
GstJackAudioClient *client;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
/* our ports */
jack_port_t **ports;
int port_count;
};
struct _GstJackAudioSinkClass {
GstBaseAudioSinkClass parent_class;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
GType gst_jack_audio_sink_get_type (void);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment