Merge pull request #1 from atsampson/master
[calfbox.git] / jackio.c
blobdbdfdd01d6715701959e2a2c98bbf9d15c135d3f
1 /*
2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010-2012 Krzysztof Foltman
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program 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
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "config.h"
21 #if USE_JACK
23 #include "config-api.h"
24 #include "errors.h"
25 #include "hwcfg.h"
26 #include "io.h"
27 #include "meter.h"
28 #include "midi.h"
29 #include "mididest.h"
30 #include "recsrc.h"
32 #include <errno.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <glib.h>
36 #include <jack/ringbuffer.h>
37 #include <jack/types.h>
38 #include <jack/midiport.h>
39 #include <jack/transport.h>
41 struct cbox_jack_io_impl
43 struct cbox_io_impl ioi;
45 jack_client_t *client;
46 jack_port_t **inputs;
47 jack_port_t **outputs;
48 jack_port_t *midi;
49 char *error_str; // set to non-NULL if client has been booted out by JACK
50 char *client_name;
51 gboolean enable_common_midi_input;
52 jack_transport_state_t last_transport_state;
53 gboolean debug_transport;
55 jack_ringbuffer_t *rb_autoconnect;
58 ///////////////////////////////////////////////////////////////////////////////
60 struct cbox_jack_midi_input
62 struct cbox_midi_input hdr;
63 gchar *autoconnect_spec;
64 jack_port_t *port;
65 struct cbox_jack_io_impl *jii;
68 struct cbox_jack_midi_output
70 struct cbox_midi_output hdr;
71 gchar *autoconnect_spec;
72 jack_port_t *port;
73 struct cbox_jack_io_impl *jii;
76 static struct cbox_midi_input *cbox_jackio_create_midi_in(struct cbox_io_impl *impl, const char *name, GError **error);
77 static struct cbox_midi_output *cbox_jackio_create_midi_out(struct cbox_io_impl *impl, const char *name, GError **error);
78 static void cbox_jackio_destroy_midi_in(struct cbox_io_impl *ioi, struct cbox_midi_input *midiin);
79 static void cbox_jackio_destroy_midi_out(struct cbox_io_impl *ioi, struct cbox_midi_output *midiout);
80 static void cbox_jack_midi_output_set_autoconnect(struct cbox_jack_midi_output *jmo, const gchar *autoconnect_spec);
82 static const char *transport_state_names[] = {"Stopped", "Rolling", "Looping?", "Starting", "Unknown/invalid#4", "Unknown/invalid#5", "Unknown/invalid#6" };
84 void cbox_jack_midi_input_destroy(struct cbox_jack_midi_input *jmi)
86 if (jmi->port)
88 jack_port_unregister(jmi->jii->client, jmi->port);
89 jmi->port = NULL;
91 g_free(jmi->hdr.name);
92 g_free(jmi->autoconnect_spec);
93 free(jmi);
96 void cbox_jack_midi_output_destroy(struct cbox_jack_midi_output *jmo)
98 if (jmo->port)
100 jack_port_unregister(jmo->jii->client, jmo->port);
101 jmo->port = NULL;
103 g_free(jmo->hdr.name);
104 g_free(jmo->autoconnect_spec);
105 free(jmo);
108 ///////////////////////////////////////////////////////////////////////////////
110 static int copy_midi_data_to_buffer(jack_port_t *port, int buffer_size, struct cbox_midi_buffer *destination)
112 void *midi = jack_port_get_buffer(port, buffer_size);
113 if (!midi)
114 return 0;
115 uint32_t event_count = jack_midi_get_event_count(midi);
117 cbox_midi_buffer_clear(destination);
118 for (uint32_t i = 0; i < event_count; i++)
120 jack_midi_event_t event;
122 if (!jack_midi_event_get(&event, midi, i))
124 if (!cbox_midi_buffer_write_event(destination, event.time, event.buffer, event.size))
125 return -i;
127 else
128 return -i;
131 return event_count;
134 ///////////////////////////////////////////////////////////////////////////////
136 static int process_cb(jack_nframes_t nframes, void *arg)
138 struct cbox_jack_io_impl *jii = arg;
139 struct cbox_io *io = jii->ioi.pio;
140 struct cbox_io_callbacks *cb = io->cb;
142 io->io_env.buffer_size = nframes;
143 for (int i = 0; i < io->io_env.input_count; i++)
144 io->input_buffers[i] = jack_port_get_buffer(jii->inputs[i], nframes);
145 for (int i = 0; i < io->io_env.output_count; i++)
147 io->output_buffers[i] = jack_port_get_buffer(jii->outputs[i], nframes);
148 if (!io->output_buffers[i])
149 continue;
150 for (int j = 0; j < nframes; j ++)
151 io->output_buffers[i][j] = 0.f;
153 for (GSList *p = io->midi_inputs; p; p = p->next)
155 struct cbox_jack_midi_input *input = p->data;
156 if (input->hdr.output_set || input->hdr.enable_appsink)
158 copy_midi_data_to_buffer(input->port, io->io_env.buffer_size, &input->hdr.buffer);
159 if (input->hdr.enable_appsink)
160 cbox_midi_appsink_supply(&input->hdr.appsink, &input->hdr.buffer);
162 else
163 cbox_midi_buffer_clear(&input->hdr.buffer);
165 if (cb->on_transport_sync)
167 jack_transport_state_t state = jack_transport_query(jii->client, NULL);
168 if (state != jii->last_transport_state)
170 jack_position_t pos;
171 jack_transport_query(jii->client, &pos);
172 if (jii->debug_transport)
173 g_message("JACK transport: incoming state change, state = %s, last state = %s, pos = %d\n", transport_state_names[state], transport_state_names[(int)jii->last_transport_state], (int)pos.frame);
174 if (state == JackTransportStopped)
176 if (cb->on_transport_sync(cb->user_data, ts_stopping, pos.frame))
177 jii->last_transport_state = state;
179 else
180 if (state == JackTransportRolling && jii->last_transport_state == JackTransportStarting)
182 if (cb->on_transport_sync(cb->user_data, ts_rolling, pos.frame))
183 jii->last_transport_state = state;
185 else
186 jii->last_transport_state = state;
189 cb->process(cb->user_data, io, nframes);
190 for (int i = 0; i < io->io_env.input_count; i++)
191 io->input_buffers[i] = NULL;
192 for (int i = 0; i < io->io_env.output_count; i++)
193 io->output_buffers[i] = NULL;
194 for (GSList *p = io->midi_outputs; p; p = g_slist_next(p))
196 struct cbox_jack_midi_output *midiout = p->data;
198 void *pbuf = jack_port_get_buffer(midiout->port, nframes);
199 jack_midi_clear_buffer(pbuf);
201 cbox_midi_merger_render(&midiout->hdr.merger);
202 if (midiout->hdr.buffer.count)
204 uint8_t tmp_data[4];
205 for (int i = 0; i < midiout->hdr.buffer.count; i++)
207 const struct cbox_midi_event *event = cbox_midi_buffer_get_event(&midiout->hdr.buffer, i);
208 const uint8_t *pdata = cbox_midi_event_get_data(event);
209 if ((pdata[0] & 0xF0) == 0x90 && !pdata[2] && event->size == 3)
211 tmp_data[0] = pdata[0] & ~0x10;
212 tmp_data[1] = pdata[1];
213 tmp_data[2] = pdata[2];
214 pdata = tmp_data;
216 if (jack_midi_event_write(pbuf, event->time, pdata, event->size))
218 g_warning("MIDI buffer overflow on JACK output port '%s'", midiout->hdr.name);
219 break;
224 return 0;
227 static void autoconnect_port(jack_client_t *client, const char *port, const char *use_name, int is_cbox_input, const jack_port_t *only_connect_port, struct cbox_command_target *fb)
229 int res;
230 if (only_connect_port)
232 jack_port_t *right;
233 right = jack_port_by_name(client, use_name);
234 if (only_connect_port != right)
235 return;
238 const char *pfrom = is_cbox_input ? use_name : port;
239 const char *pto = !is_cbox_input ? use_name : port;
241 res = jack_connect(client, pfrom, pto);
242 if (res == EEXIST)
243 res = 0;
244 gboolean suppressed = FALSE;
245 if (fb)
247 if (!res)
248 suppressed = cbox_execute_on(fb, NULL, "/io/jack/connected", "ss", NULL, pfrom, pto);
249 else
250 suppressed = cbox_execute_on(fb, NULL, "/io/jack/connect_failed", "sss", NULL, pfrom, pto, (res == EEXIST ? "already connected" : "failed"));
252 if (!suppressed)
253 g_message("Connect: %s %s %s (%s)", port, is_cbox_input ? "<-" : "->", use_name, res == 0 ? "success" : (res == EEXIST ? "already connected" : "failed"));
256 static void autoconnect_by_spec(jack_client_t *client, const char *port, const char *orig_spec, int is_cbox_input, int is_midi, const jack_port_t *only_connect_port, struct cbox_command_target *fb)
258 char *name, *copy_spec, *dpos;
259 const char *use_name;
261 copy_spec = g_strdup(orig_spec);
262 name = copy_spec;
263 do {
264 dpos = strchr(name, ';');
265 if (dpos)
266 *dpos = '\0';
268 use_name = name;
269 if (use_name[0] == '#')
271 char *endptr = NULL;
272 long portidx = strtol(use_name + 1, &endptr, 10) - 1;
273 if (endptr == use_name + strlen(use_name))
275 const char **names = jack_get_ports(client, ".*", is_midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE, is_cbox_input ? JackPortIsOutput : JackPortIsInput);
276 // Client killed by JACK
277 if (!names)
278 return;
279 int i;
280 for (i = 0; i < portidx && names[i]; i++)
283 if (names[i])
284 autoconnect_port(client, port, names[i], is_cbox_input, only_connect_port, fb);
285 else
286 g_message("Connect: unmatched port index %d", (int)portidx);
288 jack_free(names);
291 else if (use_name[0] == '~' || use_name[0] == '*')
293 const char **names = jack_get_ports(client, use_name + 1, is_midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE, is_cbox_input ? JackPortIsOutput : JackPortIsInput);
294 // Client killed by JACK
295 if (!names)
296 return;
298 if (names && names[0])
300 if (use_name[0] == '*')
302 int i;
303 for (i = 0; names[i]; i++)
304 autoconnect_port(client, port, names[i], is_cbox_input, only_connect_port, fb);
306 else
307 autoconnect_port(client, port, names[0], is_cbox_input, only_connect_port, fb);
309 else
310 g_message("Connect: unmatched port regexp %s", use_name);
311 jack_free(names);
313 else
314 autoconnect_port(client, port, use_name, is_cbox_input, only_connect_port, fb);
316 if (dpos)
317 name = dpos + 1;
318 } while(dpos);
319 g_free(copy_spec);
322 static void autoconnect_by_var(jack_client_t *client, const char *port, const char *config_var, int is_cbox_input, int is_midi, const jack_port_t *only_connect_port, struct cbox_command_target *fb)
324 const char *orig_spec = cbox_config_get_string(cbox_io_section, config_var);
325 if (orig_spec)
326 autoconnect_by_spec(client, port, orig_spec, is_cbox_input, is_midi, only_connect_port, fb);
329 static void port_connect_cb(jack_port_id_t port, int registered, void *arg)
331 struct cbox_jack_io_impl *jii = arg;
332 if (registered)
334 jack_port_t *portobj = jack_port_by_id(jii->client, port);
336 jack_ringbuffer_write(jii->rb_autoconnect, (char *)&portobj, sizeof(portobj));
340 static void port_autoconnect(struct cbox_jack_io_impl *jii, jack_port_t *portobj, struct cbox_command_target *fb)
342 struct cbox_io *io = jii->ioi.pio;
344 for (int i = 0; i < io->io_env.output_count; i++)
346 gchar *cbox_port = g_strdup_printf("%s:out_%d", jii->client_name, 1 + i);
347 gchar *config_key = g_strdup_printf("out_%d", 1 + i);
348 autoconnect_by_var(jii->client, cbox_port, config_key, 0, 0, portobj, fb);
349 g_free(cbox_port);
350 g_free(config_key);
352 for (int i = 0; i < io->io_env.input_count; i++)
354 gchar *cbox_port = g_strdup_printf("%s:in_%d", jii->client_name, 1 + i);
355 gchar *config_key = g_strdup_printf("in_%d", 1 + i);
356 autoconnect_by_var(jii->client, cbox_port, config_key, 1, 0, portobj, fb);
357 g_free(cbox_port);
358 g_free(config_key);
360 for (GSList *p = io->midi_outputs; p; p = g_slist_next(p))
362 struct cbox_jack_midi_output *midiout = p->data;
363 if (midiout->autoconnect_spec)
365 gchar *cbox_port = g_strdup_printf("%s:%s", jii->client_name, midiout->hdr.name);
366 autoconnect_by_spec(jii->client, cbox_port, midiout->autoconnect_spec, 0, 1, portobj, fb);
367 g_free(cbox_port);
370 for (GSList *p = io->midi_inputs; p; p = g_slist_next(p))
372 struct cbox_jack_midi_input *midiin = p->data;
373 if (midiin->autoconnect_spec)
375 gchar *cbox_port = g_strdup_printf("%s:%s", jii->client_name, midiin->hdr.name);
376 autoconnect_by_spec(jii->client, cbox_port, midiin->autoconnect_spec, 1, 1, portobj, fb);
377 g_free(cbox_port);
380 gchar *cbox_port = g_strdup_printf("%s:midi", jii->client_name);
381 autoconnect_by_var(jii->client, cbox_port, "midi", 1, 1, portobj, fb);
382 g_free(cbox_port);
385 int cbox_jackio_get_sample_rate(struct cbox_io_impl *impl)
387 struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)impl;
389 return jack_get_sample_rate(jii->client);
392 gboolean cbox_jackio_get_status(struct cbox_io_impl *impl, GError **error)
394 struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)impl;
395 if (!jii->error_str)
396 return TRUE;
397 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "%s", jii->error_str);
398 return FALSE;
401 static void client_shutdown_cb(jack_status_t code, const char *reason, void *arg)
403 struct cbox_jack_io_impl *jii = arg;
404 struct cbox_io *io = jii->ioi.pio;
405 jii->error_str = g_strdup(reason);
406 if (io->cb && io->cb->on_disconnected)
407 (io->cb->on_disconnected)(io->cb->user_data);
410 static int sync_cb(jack_transport_state_t state, jack_position_t *pos, void *arg)
412 struct cbox_jack_io_impl *jii = arg;
413 struct cbox_io *io = jii->ioi.pio;
414 gboolean result = TRUE;
415 int last_state = jii->last_transport_state;
416 switch(state)
418 case JackTransportStopped:
419 result = io->cb->on_transport_sync(io->cb->user_data, ts_stopped, pos->frame);
420 break;
421 case JackTransportStarting:
422 jii->last_transport_state = JackTransportStarting;
423 result = io->cb->on_transport_sync(io->cb->user_data, ts_starting, pos->frame);
424 break;
425 case JackTransportRolling:
426 result = io->cb->on_transport_sync(io->cb->user_data, ts_rolling, pos->frame);
427 break;
428 default:
429 // assume the client is ready
430 result = TRUE;
432 if (jii->debug_transport)
433 g_message("JACK transport: incoming sync callback, state = %s, last state = %s, pos = %d, result = %d\n", transport_state_names[state], transport_state_names[last_state], (int)pos->frame, result);
434 return result;
437 gboolean cbox_jackio_start(struct cbox_io_impl *impl, struct cbox_command_target *fb, GError **error)
439 struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)impl;
440 struct cbox_io *io = jii->ioi.pio;
442 if (io->cb->on_transport_sync)
443 jack_set_sync_callback(jii->client, sync_cb, jii);
444 jack_set_process_callback(jii->client, process_cb, jii);
445 jack_set_port_registration_callback(jii->client, port_connect_cb, jii);
446 jack_on_info_shutdown(jii->client, client_shutdown_cb, jii);
448 if (io->cb->on_started)
449 io->cb->on_started(io->cb->user_data);
451 jack_activate(jii->client);
453 if (cbox_config_has_section(cbox_io_section))
454 port_autoconnect(jii, NULL, fb);
456 return TRUE;
459 gboolean cbox_jackio_stop(struct cbox_io_impl *impl, GError **error)
461 struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)impl;
463 if (jii->error_str)
465 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "%s", jii->error_str);
466 return FALSE;
468 jack_deactivate(jii->client);
469 return TRUE;
472 void cbox_jackio_poll_ports(struct cbox_io_impl *impl, struct cbox_command_target *fb)
474 struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)impl;
476 while (jack_ringbuffer_read_space(jii->rb_autoconnect) >= sizeof(jack_port_t *))
478 jack_port_t *portobj;
479 jack_ringbuffer_read(jii->rb_autoconnect, (char *)&portobj, sizeof(portobj));
480 port_autoconnect(jii, portobj, fb);
484 int cbox_jackio_get_midi_data(struct cbox_io_impl *impl, struct cbox_midi_buffer *destination)
486 struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)impl;
487 if (!jii->enable_common_midi_input)
489 cbox_midi_buffer_clear(destination);
490 return 1;
493 return copy_midi_data_to_buffer(jii->midi, jii->ioi.pio->io_env.buffer_size, destination);
496 void cbox_jackio_destroy(struct cbox_io_impl *impl)
498 struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)impl;
499 struct cbox_io *io = impl->pio;
500 if (jii->client)
502 if (jii->error_str)
504 g_free(jii->error_str);
505 jii->error_str = NULL;
507 else
509 for (int i = 0; i < io->io_env.input_count; i++)
510 jack_port_unregister(jii->client, jii->inputs[i]);
511 free(jii->inputs);
512 for (int i = 0; i < io->io_env.output_count; i++)
513 jack_port_unregister(jii->client, jii->outputs[i]);
514 free(jii->outputs);
515 if (jii->midi)
516 jack_port_unregister(jii->client, jii->midi);
518 if (jii->client_name)
520 free(jii->client_name);
521 jii->client_name = NULL;
523 cbox_io_destroy_all_midi_ports(io);
525 jack_ringbuffer_free(jii->rb_autoconnect);
526 jack_client_close(jii->client);
528 free(jii);
531 gboolean cbox_jackio_cycle(struct cbox_io_impl *impl, struct cbox_command_target *fb, GError **error)
533 struct cbox_io *io = impl->pio;
534 struct cbox_io_callbacks *cb = io->cb;
535 cbox_io_close(io);
537 // XXXKF use params structure some day
538 if (!cbox_io_init_jack(io, NULL, fb, error))
539 return FALSE;
541 cbox_io_start(io, cb, fb);
542 if (cb->on_reconnected)
543 (cb->on_reconnected)(cb->user_data);
544 return TRUE;
549 ///////////////////////////////////////////////////////////////////////////////
551 struct cbox_midi_input *cbox_jackio_create_midi_in(struct cbox_io_impl *impl, const char *name, GError **error)
553 struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)impl;
554 jack_port_t *port = jack_port_register(jii->client, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
555 if (!port)
557 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot create input MIDI port '%s'", name);
558 return FALSE;
560 struct cbox_jack_midi_input *input = calloc(1, sizeof(struct cbox_jack_midi_input));
561 input->hdr.name = g_strdup(name);
562 input->hdr.removing = FALSE;
563 input->port = port;
564 input->jii = jii;
565 cbox_uuid_generate(&input->hdr.uuid);
566 cbox_midi_buffer_init(&input->hdr.buffer);
568 return (struct cbox_midi_input *)input;
571 struct cbox_midi_output *cbox_jackio_create_midi_out(struct cbox_io_impl *impl, const char *name, GError **error)
573 struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)impl;
574 jack_port_t *port = jack_port_register(jii->client, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
575 if (!port)
577 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot create output MIDI port '%s'", name);
578 return FALSE;
580 struct cbox_jack_midi_output *output = calloc(1, sizeof(struct cbox_jack_midi_output));
581 output->hdr.name = g_strdup(name);
582 output->hdr.removing = FALSE;
583 output->port = port;
584 output->jii = jii;
585 cbox_uuid_generate(&output->hdr.uuid);
586 cbox_midi_buffer_init(&output->hdr.buffer);
587 cbox_midi_merger_init(&output->hdr.merger, &output->hdr.buffer);
589 return (struct cbox_midi_output *)output;
592 void cbox_jack_midi_input_set_autoconnect(struct cbox_jack_midi_input *jmi, const gchar *autoconnect_spec)
594 if (jmi->autoconnect_spec)
595 g_free(jmi->autoconnect_spec);
596 jmi->autoconnect_spec = autoconnect_spec && *autoconnect_spec ? g_strdup(autoconnect_spec) : NULL;
597 if (jmi->autoconnect_spec)
599 gchar *cbox_port = g_strdup_printf("%s:%s", jmi->jii->client_name, jmi->hdr.name);
600 autoconnect_by_spec(jmi->jii->client, cbox_port, jmi->autoconnect_spec, 1, 1, NULL, NULL);
601 g_free(cbox_port);
605 void cbox_jack_midi_output_set_autoconnect(struct cbox_jack_midi_output *jmo, const gchar *autoconnect_spec)
607 if (jmo->autoconnect_spec)
608 g_free(jmo->autoconnect_spec);
609 jmo->autoconnect_spec = autoconnect_spec && *autoconnect_spec ? g_strdup(autoconnect_spec) : NULL;
610 if (jmo->autoconnect_spec)
612 gchar *cbox_port = g_strdup_printf("%s:%s", jmo->jii->client_name, jmo->hdr.name);
613 autoconnect_by_spec(jmo->jii->client, cbox_port, jmo->autoconnect_spec, 0, 1, NULL, NULL);
614 g_free(cbox_port);
618 void cbox_jackio_destroy_midi_in(struct cbox_io_impl *ioi, struct cbox_midi_input *midiin)
620 cbox_jack_midi_input_destroy((struct cbox_jack_midi_input *)midiin);
623 void cbox_jackio_destroy_midi_out(struct cbox_io_impl *ioi, struct cbox_midi_output *midiout)
625 cbox_jack_midi_output_destroy((struct cbox_jack_midi_output *)midiout);
628 static gboolean cbox_jack_io_process_cmd(struct cbox_command_target *ct, struct cbox_command_target *fb, struct cbox_osc_command *cmd, GError **error)
630 struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)ct->user_data;
631 struct cbox_io *io = jii->ioi.pio;
632 gboolean handled = FALSE;
633 if (!strcmp(cmd->command, "/status") && !strcmp(cmd->arg_types, ""))
635 if (!cbox_check_fb_channel(fb, cmd->command, error))
636 return FALSE;
637 return cbox_execute_on(fb, NULL, "/client_type", "s", error, "JACK") &&
638 cbox_execute_on(fb, NULL, "/client_name", "s", error, jii->client_name) &&
639 cbox_io_process_cmd(io, fb, cmd, error, &handled);
641 else if (!strcmp(cmd->command, "/rename_midi_port") && !strcmp(cmd->arg_types, "ss"))
643 const char *uuidstr = CBOX_ARG_S(cmd, 0);
644 const char *new_name = CBOX_ARG_S(cmd, 1);
645 struct cbox_uuid uuid;
646 if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
647 return FALSE;
648 struct cbox_midi_input *midiin = cbox_io_get_midi_input(io, NULL, &uuid);
649 struct cbox_midi_output *midiout = cbox_io_get_midi_output(io, NULL, &uuid);
650 if (!midiout && !midiin)
652 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
653 return FALSE;
655 jack_port_t *port = midiout ? ((struct cbox_jack_midi_output *)midiout)->port
656 : ((struct cbox_jack_midi_input *)midiin)->port;
657 char **pname = midiout ? &midiout->name : &midiin->name;
658 if (0 != jack_port_set_name(port, new_name))
660 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot set port name to '%s'", new_name);
661 return FALSE;
663 g_free(*pname);
664 *pname = g_strdup(new_name);
665 return TRUE;
667 else if (!strcmp(cmd->command, "/autoconnect") && !strcmp(cmd->arg_types, "ss"))
669 const char *uuidstr = CBOX_ARG_S(cmd, 0);
670 const char *spec = CBOX_ARG_S(cmd, 1);
671 struct cbox_uuid uuid;
672 if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
673 return FALSE;
674 struct cbox_midi_output *midiout = cbox_io_get_midi_output(io, NULL, &uuid);
675 if (midiout)
677 cbox_jack_midi_output_set_autoconnect((struct cbox_jack_midi_output *)midiout, spec);
678 return TRUE;
680 struct cbox_midi_input *midiin = cbox_io_get_midi_input(io, NULL, &uuid);
681 if (midiin)
683 cbox_jack_midi_input_set_autoconnect((struct cbox_jack_midi_input *)midiin, spec);
684 return TRUE;
686 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
687 return FALSE;
689 else if (!strcmp(cmd->command, "/disconnect_midi_port") && !strcmp(cmd->arg_types, "s"))
691 const char *uuidstr = CBOX_ARG_S(cmd, 0);
692 struct cbox_uuid uuid;
693 if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
694 return FALSE;
695 struct cbox_midi_input *midiin = cbox_io_get_midi_input(io, NULL, &uuid);
696 struct cbox_midi_output *midiout = cbox_io_get_midi_output(io, NULL, &uuid);
697 if (!midiout && !midiin)
699 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
700 return FALSE;
702 jack_port_t *port = midiout ? ((struct cbox_jack_midi_output *)midiout)->port
703 : ((struct cbox_jack_midi_input *)midiin)->port;
704 jack_port_disconnect(jii->client, port);
705 return TRUE;
707 else if (!strcmp(cmd->command, "/port_connect") && !strcmp(cmd->arg_types, "ss"))
709 const char *port_from = CBOX_ARG_S(cmd, 0);
710 const char *port_to = CBOX_ARG_S(cmd, 1);
711 int res = jack_connect(jii->client, port_from, port_to);
712 if (res == EEXIST)
713 res = 0;
714 if (res)
715 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot connect port '%s' to '%s'", port_from, port_to);
716 return res == 0;
718 else if (!strcmp(cmd->command, "/port_disconnect") && !strcmp(cmd->arg_types, "ss"))
720 const char *port_from = CBOX_ARG_S(cmd, 0);
721 const char *port_to = CBOX_ARG_S(cmd, 1);
722 int res = jack_disconnect(jii->client, port_from, port_to);
723 if (res)
724 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot disconnect port '%s' from '%s'", port_from, port_to);
725 return res == 0;
727 else if (!strcmp(cmd->command, "/get_connected_ports") && !strcmp(cmd->arg_types, "s"))
729 if (!cbox_check_fb_channel(fb, cmd->command, error))
730 return FALSE;
731 const char *name = CBOX_ARG_S(cmd, 0);
732 jack_port_t *port = jack_port_by_name(jii->client, name);
733 if (!port)
735 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", name);
736 return FALSE;
738 const char** ports = jack_port_get_all_connections(jii->client, port);
739 for (int i = 0; ports && ports[i]; i++)
741 if (!cbox_execute_on(fb, NULL, "/port", "s", error, ports[i]))
742 return FALSE;
744 jack_free(ports);
745 return TRUE;
747 else if (!strcmp(cmd->command, "/get_ports") && !strcmp(cmd->arg_types, "ssi"))
749 if (!cbox_check_fb_channel(fb, cmd->command, error))
750 return FALSE;
751 const char *mask = CBOX_ARG_S(cmd, 0);
752 const char *type = CBOX_ARG_S(cmd, 1);
753 uint32_t flags = CBOX_ARG_I(cmd, 2);
754 const char** ports = jack_get_ports(jii->client, mask, type, flags);
755 for (int i = 0; ports && ports[i]; i++)
757 if (!cbox_execute_on(fb, NULL, "/port", "s", error, ports[i]))
758 return FALSE;
760 jack_free(ports);
761 return TRUE;
763 else
765 gboolean result = cbox_io_process_cmd(io, fb, cmd, error, &handled);
766 if (!handled)
767 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Unknown combination of target path and argument: '%s', '%s'", cmd->command, cmd->arg_types);
768 return result;
772 ///////////////////////////////////////////////////////////////////////////////
774 static void cbox_jackio_control_transport(struct cbox_io_impl *impl, gboolean roll, uint32_t pos)
776 struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)impl;
778 if (jii->debug_transport)
779 g_message("JACK transport: control(op=%s, pos=%d)\n", roll ? "roll" : "stop", (int)pos);
781 jack_transport_state_t state = jack_transport_query(jii->client, NULL);
782 if (roll && state == JackTransportStopped)
783 jack_transport_start(jii->client);
784 if (!roll && state != JackTransportStopped)
785 jack_transport_stop(jii->client);
787 if (pos != (uint32_t)-1)
788 jack_transport_locate(jii->client, pos);
791 static gboolean cbox_jackio_get_sync_completed(struct cbox_io_impl *impl)
793 struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)impl;
794 return jack_transport_query(jii->client, NULL) != JackTransportStarting;
797 ///////////////////////////////////////////////////////////////////////////////
799 gboolean cbox_io_init_jack(struct cbox_io *io, struct cbox_open_params *const params, struct cbox_command_target *fb, GError **error)
801 const char *client_name = cbox_config_get_string_with_default("io", "client_name", "cbox");
803 jack_client_t *client = NULL;
804 jack_status_t status = 0;
805 client = jack_client_open(client_name, JackNoStartServer, &status);
806 if (client == NULL)
808 if (!cbox_hwcfg_setup_jack())
810 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot set up JACK server configuration based on current hardware");
811 return FALSE;
814 status = 0;
815 client = jack_client_open(client_name, 0, &status);
817 if (client == NULL)
819 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot create JACK instance");
820 return FALSE;
823 // XXXKF would use a callback instead
824 io->io_env.buffer_size = jack_get_buffer_size(client);
825 io->cb = NULL;
826 io->io_env.input_count = cbox_config_get_int("io", "inputs", 0);
827 io->input_buffers = malloc(sizeof(float *) * io->io_env.input_count);
828 io->io_env.output_count = cbox_config_get_int("io", "outputs", 2);
829 io->output_buffers = malloc(sizeof(float *) * io->io_env.output_count);
831 struct cbox_jack_io_impl *jii = malloc(sizeof(struct cbox_jack_io_impl));
832 io->impl = &jii->ioi;
833 jii->enable_common_midi_input = cbox_config_get_int("io", "enable_common_midi_input", 1);
834 jii->debug_transport = cbox_config_get_int("debug", "jack_transport", 0);
835 jii->last_transport_state = JackTransportStopped;
837 cbox_command_target_init(&io->cmd_target, cbox_jack_io_process_cmd, jii);
838 jii->ioi.pio = io;
839 jii->ioi.getsampleratefunc = cbox_jackio_get_sample_rate;
840 jii->ioi.startfunc = cbox_jackio_start;
841 jii->ioi.stopfunc = cbox_jackio_stop;
842 jii->ioi.getstatusfunc = cbox_jackio_get_status;
843 jii->ioi.pollfunc = cbox_jackio_poll_ports;
844 jii->ioi.cyclefunc = cbox_jackio_cycle;
845 jii->ioi.getmidifunc = cbox_jackio_get_midi_data;
846 jii->ioi.createmidiinfunc = cbox_jackio_create_midi_in;
847 jii->ioi.destroymidiinfunc = cbox_jackio_destroy_midi_in;
848 jii->ioi.createmidioutfunc = cbox_jackio_create_midi_out;
849 jii->ioi.destroymidioutfunc = cbox_jackio_destroy_midi_out;
850 jii->ioi.updatemidiinroutingfunc = NULL;
851 jii->ioi.controltransportfunc = cbox_jackio_control_transport;
852 jii->ioi.getsynccompletedfunc = cbox_jackio_get_sync_completed;
853 jii->ioi.destroyfunc = cbox_jackio_destroy;
855 jii->client_name = g_strdup(jack_get_client_name(client));
856 jii->client = client;
857 jii->rb_autoconnect = jack_ringbuffer_create(sizeof(jack_port_t *) * 128);
858 jii->error_str = NULL;
859 io->io_env.srate = jack_get_sample_rate(client);
861 jii->inputs = malloc(sizeof(jack_port_t *) * io->io_env.input_count);
862 jii->outputs = malloc(sizeof(jack_port_t *) * io->io_env.output_count);
863 for (int i = 0; i < io->io_env.input_count; i++)
864 jii->inputs[i] = NULL;
865 for (int i = 0; i < io->io_env.output_count; i++)
866 jii->outputs[i] = NULL;
867 for (int i = 0; i < io->io_env.input_count; i++)
869 gchar *name = g_strdup_printf("in_%d", 1 + i);
870 jii->inputs[i] = jack_port_register(jii->client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
871 if (!jii->inputs[i])
873 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot create input port %d (%s)", i, name);
874 g_free(name);
875 goto cleanup;
877 g_free(name);
879 for (int i = 0; i < io->io_env.output_count; i++)
881 gchar *name = g_strdup_printf("out_%d", 1 + i);
882 jii->outputs[i] = jack_port_register(jii->client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
883 if (!jii->outputs[i])
885 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot create output port %d (%s)", i, name);
886 g_free(name);
887 goto cleanup;
889 g_free(name);
891 if (jii->enable_common_midi_input)
893 jii->midi = jack_port_register(jii->client, "midi", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
894 if (!jii->midi)
896 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot create MIDI port");
897 return FALSE;
900 else
901 jii->midi = NULL;
903 if (fb)
904 cbox_execute_on(fb, NULL, "/io/jack_client_name", "s", NULL, jii->client_name);
906 cbox_io_poll_ports(io, fb);
908 return TRUE;
910 cleanup:
911 if (jii->inputs)
913 for (int i = 0; i < io->io_env.input_count; i++)
914 free(jii->inputs[i]);
915 free(jii->inputs);
917 if (jii->outputs)
919 for (int i = 0; i < io->io_env.output_count; i++)
920 free(jii->outputs[i]);
921 free(jii->outputs);
923 cbox_io_destroy_all_midi_ports(io);
924 if (jii->client_name)
925 free(jii->client_name);
926 jack_client_close(jii->client);
927 free(jii);
928 io->impl = NULL;
929 return FALSE;
932 #endif