1 /* -*- Mode: C; c-basic-offset: 4 -*- */
3 Copyright (C) 2002 Andy Wingo <wingo@pobox.com>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public
16 License along with this library; if not, write to the Free
17 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 static GstBinClass *parent_class = NULL;
28 static void gst_jack_bin_init(GstJackBin *this);
29 static void gst_jack_bin_class_init(GstJackBinClass *klass);
31 static GstElementStateReturn gst_jack_bin_change_state(GstElement *element);
34 static int process (jack_nframes_t nframes, void *arg);
35 static int sample_rate (jack_nframes_t nframes, void *arg);
36 static void shutdown (void *arg);
38 static void sighup_handler (int sig);
39 static GstJackBin *_jackbin = NULL;
40 static gboolean watchdog_please_set_the_jackbin_to_ready = FALSE;
42 /* fixme: we need a watchdog thread to see if we have received a SIGHUP, and if
43 * so set the state of the bin to READY. */
46 gst_jack_bin_get_type (void)
48 static GType jack_bin_type = 0;
50 static const GTypeInfo jack_bin_info = {
51 sizeof(GstJackBinClass),
54 (GClassInitFunc)gst_jack_bin_class_init,
59 (GInstanceInitFunc)gst_jack_bin_init,
61 jack_bin_type = g_type_register_static (GST_TYPE_BIN, "GstJackBin", &jack_bin_info, 0);
67 gst_jack_bin_class_init(GstJackBinClass *klass)
69 GObjectClass *object_class;
70 GstElementClass *element_class;
72 object_class = (GObjectClass *)klass;
73 element_class = (GstElementClass *)klass;
75 parent_class = g_type_class_ref(GST_TYPE_BIN);
77 element_class->change_state = gst_jack_bin_change_state;
81 gst_jack_bin_init(GstJackBin *this)
83 GST_DEBUG ("initializing jack bin");
85 /* jack bins are managing bins and iterate themselves */
86 GST_FLAG_SET (this, GST_BIN_FLAG_MANAGER);
87 GST_FLAG_SET (this, GST_BIN_SELF_SCHEDULABLE);
89 /* make a new scheduler and associate it with the bin */
90 gst_scheduler_factory_make (NULL, GST_ELEMENT (this));
93 static GstElementStateReturn
94 gst_jack_bin_change_state (GstElement *element)
100 g_return_val_if_fail (element != NULL, FALSE);
101 this = GST_JACK_BIN (element);
103 switch (GST_STATE_PENDING (element)) {
105 JACK_DEBUG ("jackbin: NULL state");
107 JACK_DEBUG ("jackbin: closing client");
108 jack_client_close (this->client);
113 signal (SIGHUP, SIG_DFL);
116 if (GST_ELEMENT_CLASS (parent_class)->change_state)
117 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
120 case GST_STATE_READY:
121 JACK_DEBUG ("jackbin: READY");
124 signal (SIGHUP, sighup_handler);
127 if (!(this->client = jack_client_new ("gst-jack"))) {
128 g_warning ("jack server not running?");
129 return GST_STATE_FAILURE;
132 gst_scheduler_setup (GST_ELEMENT_SCHED (this));
134 jack_set_process_callback (this->client, process, this);
135 jack_set_sample_rate_callback (this->client, sample_rate, this);
136 jack_on_shutdown (this->client, shutdown, this);
139 if (GST_FLAG_IS_SET (GST_OBJECT (this), GST_JACK_OPEN)) {
142 JACK_DEBUG ("jackbin: unregistering pad %s:%s", GST_JACK_PAD (l)->name, GST_JACK_PAD (l)->peer_name);
143 jack_port_unregister (this->client, GST_JACK_PAD (l)->port);
148 JACK_DEBUG ("jackbin: unregistering pad %s:%s", GST_JACK_PAD (l)->name, GST_JACK_PAD (l)->peer_name);
149 jack_port_unregister (this->client, GST_JACK_PAD (l)->port);
152 GST_FLAG_UNSET (GST_OBJECT (this), GST_JACK_OPEN);
154 if (GST_FLAG_IS_SET (GST_OBJECT (this), GST_JACK_ACTIVE)) {
155 JACK_DEBUG ("jackbin: deactivating client");
156 jack_deactivate (this->client);
157 GST_FLAG_UNSET (GST_OBJECT (this), GST_JACK_ACTIVE);
161 if (GST_ELEMENT_CLASS (parent_class)->change_state)
162 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
165 case GST_STATE_PAUSED:
166 JACK_DEBUG ("jackbin: PAUSED");
168 if (!GST_FLAG_IS_SET (GST_OBJECT (this), GST_JACK_OPEN)) {
171 pad = GST_JACK_PAD (l);
172 JACK_DEBUG ("jackbin: registering input port %s (peer %s)", pad->name, pad->peer_name);
173 pad->port = jack_port_register (this->client, pad->name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput|JackPortIsTerminal, 0);
178 pad = GST_JACK_PAD (l);
179 JACK_DEBUG ("jackbin: registering output port %s (peer %s)", pad->name, pad->peer_name);
180 pad->port = jack_port_register (this->client, pad->name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput|JackPortIsTerminal, 0);
184 /* must activate before connecting */
185 if (!GST_FLAG_IS_SET (GST_OBJECT (this), GST_JACK_ACTIVE)) {
186 JACK_DEBUG ("jackbin: activating client");
187 jack_activate (this->client);
188 GST_FLAG_SET (GST_OBJECT (this), GST_JACK_ACTIVE);
193 pad = GST_JACK_PAD (l);
194 JACK_DEBUG ("connecting jack port %s to gst jack port %s", pad->peer_name, jack_port_name (pad->port));
195 if (jack_connect (this->client, pad->peer_name, jack_port_name (pad->port))) {
196 g_warning ("jackbin: could not connect %s and %s", pad->peer_name, jack_port_name (pad->port));
197 return GST_STATE_FAILURE;
203 pad = GST_JACK_PAD (l);
204 JACK_DEBUG ("connecting gst jack port %s to jack port %s", jack_port_name (pad->port), pad->peer_name);
205 if (jack_connect (this->client, jack_port_name (pad->port), pad->peer_name)) {
206 g_warning ("jackbin: could not connect %s and %s", pad->peer_name, jack_port_name (pad->port));
207 return GST_STATE_FAILURE;
212 JACK_DEBUG ("jackbin: setting OPEN flag");
213 GST_FLAG_SET (GST_OBJECT (this), GST_JACK_OPEN);
215 if (GST_ELEMENT_CLASS (parent_class)->change_state)
216 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
218 if (GST_ELEMENT_CLASS (parent_class)->change_state)
219 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
223 case GST_STATE_PLAYING:
224 JACK_DEBUG ("jackbin: PLAYING");
226 if (GST_ELEMENT_CLASS (parent_class)->change_state)
227 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
231 JACK_DEBUG ("jackbin: state change finished");
233 return GST_STATE_SUCCESS;
238 /* keep in mind that these run in another thread, mm-kay? */
241 process (jack_nframes_t nframes, void *arg)
243 GstJackBin *bin = (GstJackBin*) arg;
249 JACK_DEBUG ("jackbin: process()");
251 if (GST_STATE (bin) != GST_STATE_PLAYING) {
252 JACK_DEBUG ("jackbin: bin is not PLAYING yet, returning");
255 JACK_DEBUG ("jackbin: we are PLAYING, let's process()");
260 pad = GST_JACK_PAD (l);
261 pad->data = jack_port_get_buffer (pad->port, nframes);
267 pad = GST_JACK_PAD (l);
268 pad->data = jack_port_get_buffer (pad->port, nframes);
272 bin->nframes = nframes;
274 JACK_DEBUG ("jackbin: iterating to process %ld frames of audio...", nframes);
275 if (!gst_bin_iterate (GST_BIN_CAST (bin))) {
276 g_warning ("bin failed to iterate");
280 /* that's all folks */
286 sample_rate (jack_nframes_t nframes, void *arg)
288 GstJackBin *bin = (GstJackBin*) arg;
289 JACK_DEBUG ("the sample rate is now %lu/sec\n", nframes);
297 /* GstJackClient *client = (GstJackClient*) arg; */
298 printf ("shutdown %p\n", arg);
299 /* gst_element_set_state (GST_ELEMENT (client->manager), GST_STATE_READY); */
302 static void sighup_handler (int sig)
304 g_message ("got sighup, setting state to READY");
305 watchdog_please_set_the_jackbin_to_ready = TRUE;