add dbus command to allow checking of wether hardware is currently exported
[a2jmidid.git] / jack.c
blobae1a160663e0d13a29a5760d027949057a832e79
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * ALSA SEQ < - > JACK MIDI bridge
5 * Copyright (c) 2006,2007 Dmitry S. Baikov <c0ff@konstruktiv.org>
6 * Copyright (c) 2007,2008,2009 Nedko Arnaudov <nedko@arnaudov.name>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <stdbool.h>
23 #include <time.h>
24 #include <alsa/asoundlib.h>
25 #include <jack/jack.h>
26 #include <jack/midiport.h>
27 #include <jack/ringbuffer.h>
29 #include "list.h"
30 #include "structs.h"
31 #include "jack.h"
32 #include "log.h"
33 #include "port_hash.h"
34 #include "port.h"
35 #include "a2jmidid.h"
36 #include "port_thread.h"
38 static bool g_freewheeling = false;
41 * =================== Input/output port handling =========================
44 void a2j_add_ports(struct a2j_stream * str)
46 struct a2j_port * port_ptr;
47 while (jack_ringbuffer_read(str->new_ports, (char *)&port_ptr, sizeof(port_ptr)))
49 a2j_debug("jack: inserted port %s", port_ptr->name);
50 a2j_port_insert(str->port_hash, port_ptr);
55 * ============================ Input ==============================
57 void
58 a2j_process_incoming (
59 struct a2j * self,
60 struct a2j_port * port,
61 jack_nframes_t nframes)
63 struct a2j_alsa_midi_event ev;
64 jack_nframes_t now;
65 jack_nframes_t one_period;
66 char *ev_buf;
68 /* grab data queued by the ALSA input thread and write it into the JACK
69 port buffer. it will delivered during the JACK period that this
70 function is called from.
73 /* first clear the JACK port buffer in preparation for new data
76 // a2j_debug ("PORT: %s process input", jack_port_name (port->jack_port));
78 jack_midi_clear_buffer (port->jack_buf);
80 now = jack_frame_time (self->jack_client);
81 one_period = jack_get_buffer_size (self->jack_client);
83 while (jack_ringbuffer_peek (port->inbound_events, (char*)&ev, sizeof(ev) ) == sizeof(ev) ) {
85 jack_midi_data_t* buf;
86 jack_nframes_t offset;
88 if (ev.time >= self->cycle_start) {
89 break;
92 //jack_ringbuffer_read_advance (port->inbound_events, sizeof (ev));
93 ev_buf = (char *) alloca( sizeof(ev) + ev.size );
95 if (jack_ringbuffer_peek (port->inbound_events, ev_buf, sizeof(ev) + ev.size ) != sizeof(ev) + ev.size)
96 break;
98 offset = self->cycle_start - ev.time;
99 if (offset > one_period) {
100 /* from a previous cycle, somehow. cram it in at the front */
101 offset = 0;
102 } else {
103 /* offset from start of the current cycle */
104 offset = one_period - offset;
107 a2j_debug ("event at %d offset %d", ev.time, offset);
109 /* make sure there is space for it */
111 buf = jack_midi_event_reserve (port->jack_buf, offset, ev.size);
113 if (buf) {
114 /* grab the event */
115 memcpy( buf, ev_buf + sizeof(ev), ev.size );
116 } else {
117 /* throw it away (no space) */
118 a2j_error ("threw away MIDI event - not reserved at time %d", ev.time);
120 jack_ringbuffer_read_advance (port->inbound_events, sizeof(ev) + ev.size);
122 a2j_debug("input on %s: sucked %d bytes from inbound at %d", jack_port_name (port->jack_port), ev.size, ev.time);
126 static
127 void
128 a2j_port_event(
129 struct a2j * self,
130 snd_seq_event_t * ev)
132 const snd_seq_addr_t addr = ev->data.addr;
134 if (addr.client == self->client_id)
135 return;
137 if (ev->type == SND_SEQ_EVENT_PORT_START || ev->type == SND_SEQ_EVENT_PORT_CHANGE) {
138 if (jack_ringbuffer_write_space(self->port_add) >= sizeof(addr)) {
139 a2j_debug("port_event: add/change %d:%d", addr.client, addr.port);
140 jack_ringbuffer_write(self->port_add, (char*)&addr, sizeof(addr));
141 } else {
142 a2j_error("dropping port_event: add/change %d:%d", addr.client, addr.port);
144 } else if (ev->type == SND_SEQ_EVENT_PORT_EXIT) {
145 a2j_debug("port_event: del %d:%d", addr.client, addr.port);
146 a2j_port_setdead(self->stream[A2J_PORT_CAPTURE].port_hash, addr);
147 a2j_port_setdead(self->stream[A2J_PORT_PLAYBACK].port_hash, addr);
151 static
152 void
153 a2j_input_event(
154 struct a2j * self,
155 snd_seq_event_t * alsa_event)
157 jack_midi_data_t data[MAX_EVENT_SIZE];
158 struct a2j_stream *str = &self->stream[A2J_PORT_CAPTURE];
159 long size;
160 struct a2j_port *port;
161 jack_nframes_t now;
163 now = jack_frame_time (self->jack_client);
165 if ((port = a2j_port_get(str->port_hash, alsa_event->source)) == NULL) {
166 return;
170 * RPNs, NRPNs, Bank Change, etc. need special handling
171 * but seems, ALSA does it for us already.
173 snd_midi_event_reset_decode(str->codec);
174 if ((size = snd_midi_event_decode(str->codec, data, sizeof(data), alsa_event))<0) {
175 return;
178 // fixup NoteOn with vel 0
179 if ((data[0] & 0xF0) == 0x90 && data[2] == 0x00) {
180 data[0] = 0x80 + (data[0] & 0x0F);
181 data[2] = 0x40;
184 a2j_debug("input: %d bytes at event_frame=%u", (int)size, now);
186 if (jack_ringbuffer_write_space(port->inbound_events) >= (sizeof(struct a2j_alsa_midi_event) + size)) {
187 struct a2j_alsa_midi_event ev;
188 char *ev_charp = (char*) &ev;
189 size_t limit;
190 size_t to_write = sizeof(ev);
192 jack_ringbuffer_data_t vec[2];
193 jack_ringbuffer_get_write_vector( port->inbound_events, vec );
194 ev.time = now;
195 ev.size = size;
198 limit = (to_write > vec[0].len ? vec[0].len : to_write);
199 if( limit ) {
200 memcpy( vec[0].buf, ev_charp, limit );
201 to_write -= limit;
202 ev_charp += limit;
203 vec[0].buf += limit;
204 vec[0].len -= limit;
206 if( to_write ) {
207 memcpy( vec[1].buf, ev_charp, to_write );
208 vec[1].buf += to_write;
209 vec[1].len -= to_write;
212 to_write = size;
213 ev_charp = (char *)data;
214 limit = (to_write > vec[0].len ? vec[0].len : to_write);
215 if( limit )
216 memcpy( vec[0].buf, ev_charp, limit );
217 to_write -= limit;
218 ev_charp += limit;
219 if( to_write )
220 memcpy( vec[1].buf, ev_charp, to_write );
222 jack_ringbuffer_write_advance( port->inbound_events, sizeof(ev) + size );
223 } else {
224 a2j_error ("MIDI data lost (incoming event buffer full): %ld bytes lost", size);
230 * ============================ Output ==============================
234 a2j_process_outgoing (
235 struct a2j * self,
236 struct a2j_port * port)
238 /* collect data from JACK port buffer and queue it for later delivery by ALSA output thread */
240 int nevents;
241 jack_ringbuffer_data_t vec[2];
242 int i;
243 int written = 0;
244 size_t limit;
245 struct a2j_delivery_event* dev;
246 size_t gap = 0;
248 jack_ringbuffer_get_write_vector (self->outbound_events, vec);
250 dev = (struct a2j_delivery_event*) vec[0].buf;
251 limit = vec[0].len / sizeof (struct a2j_delivery_event);
252 nevents = jack_midi_get_event_count (port->jack_buf);
254 for (i = 0; (i < nevents) && (written < limit); ++i) {
256 jack_midi_event_get (&dev->jack_event, port->jack_buf, i);
257 if (dev->jack_event.size <= MAX_JACKMIDI_EV_SIZE)
259 dev->time = dev->jack_event.time;
260 dev->port = port;
261 memcpy( dev->midistring, dev->jack_event.buffer, dev->jack_event.size );
262 written++;
263 ++dev;
267 /* anything left? use the second part of the vector, as much as possible */
269 if (i < nevents)
271 if (vec[0].len)
273 gap = vec[0].len - written * sizeof(struct a2j_delivery_event);
276 dev = (struct a2j_delivery_event*) vec[1].buf;
278 limit += (vec[1].len / sizeof (struct a2j_delivery_event));
280 while ((i < nevents) && (written < limit))
282 jack_midi_event_get(&dev->jack_event, port->jack_buf, i);
283 if (dev->jack_event.size <= MAX_JACKMIDI_EV_SIZE)
285 dev->time = dev->jack_event.time;
286 dev->port = port;
287 memcpy(dev->midistring, dev->jack_event.buffer, dev->jack_event.size);
288 written++;
289 ++dev;
291 ++i;
295 a2j_debug( "done pushing events: %d ... gap: %d ", (int)written, (int)gap );
296 /* clear JACK port buffer; advance ring buffer ptr */
298 jack_ringbuffer_write_advance (self->outbound_events, written * sizeof (struct a2j_delivery_event) + gap);
300 return nevents;
303 static int
304 time_sorter (struct a2j_delivery_event * a, struct a2j_delivery_event * b)
306 if (a->time < b->time) {
307 return -1;
308 } else if (a->time > b->time) {
309 return 1;
311 return 0;
314 void * a2j_alsa_output_thread(void * arg)
316 struct a2j * self = (struct a2j*) arg;
317 struct a2j_stream *str = &self->stream[A2J_PORT_PLAYBACK];
318 int i;
319 struct list_head evlist;
320 struct list_head * node_ptr;
321 jack_ringbuffer_data_t vec[2];
322 snd_seq_event_t alsa_event;
323 struct a2j_delivery_event* ev;
324 float sr;
325 jack_nframes_t now;
326 int err;
327 int limit;
329 while (g_keep_alsa_walking) {
330 /* first, make a list of all events in the outbound_events FIFO */
332 INIT_LIST_HEAD(&evlist);
334 jack_ringbuffer_get_read_vector (self->outbound_events, vec);
336 a2j_debug ("output thread: got %d+%d events",
337 (vec[0].len / sizeof (struct a2j_delivery_event)),
338 (vec[1].len / sizeof (struct a2j_delivery_event)));
340 ev = (struct a2j_delivery_event*) vec[0].buf;
341 limit = vec[0].len / sizeof (struct a2j_delivery_event);
342 for (i = 0; i < limit; ++i) {
343 list_add_tail(&ev->siblings, &evlist);
344 ev++;
347 ev = (struct a2j_delivery_event*) vec[1].buf;
348 limit = vec[1].len / sizeof (struct a2j_delivery_event);
349 for (i = 0; i < limit; ++i) {
350 list_add_tail(&ev->siblings, &evlist);
351 ev++;
354 if (vec[0].len < sizeof(struct a2j_delivery_event) && (vec[1].len == 0)) {
355 /* no events: wait for some */
356 a2j_debug ("output thread: wait for events");
357 sem_wait (&self->io_semaphore);
358 a2j_debug ("output thread: AWAKE ... loop back for events");
359 continue;
362 /* now sort this list by time */
364 list_sort(&evlist, struct a2j_delivery_event, siblings, time_sorter);
366 /* now deliver */
368 sr = jack_get_sample_rate (self->jack_client);
370 list_for_each(node_ptr, &evlist)
372 ev = list_entry(node_ptr, struct a2j_delivery_event, siblings);
374 snd_seq_ev_clear(&alsa_event);
375 snd_midi_event_reset_encode(str->codec);
376 if (!snd_midi_event_encode(str->codec, (const unsigned char *)ev->midistring, ev->jack_event.size, &alsa_event))
378 continue; // invalid event
381 snd_seq_ev_set_source(&alsa_event, self->port_id);
382 snd_seq_ev_set_dest(&alsa_event, ev->port->remote.client, ev->port->remote.port);
383 snd_seq_ev_set_direct (&alsa_event);
385 now = jack_frame_time (self->jack_client);
387 ev->time += self->cycle_start;
389 a2j_debug ("@ %d, next event @ %d", now, ev->time);
391 /* do we need to wait a while before delivering? */
393 if (ev->time > now) {
394 struct timespec nanoseconds;
395 jack_nframes_t sleep_frames = ev->time - now;
396 float seconds = sleep_frames / sr;
398 /* if the gap is long enough, sleep */
400 if (seconds > 0.001) {
401 nanoseconds.tv_sec = (time_t) seconds;
402 nanoseconds.tv_nsec = (long) NSEC_PER_SEC * (seconds - nanoseconds.tv_sec);
404 a2j_debug ("output thread sleeps for %.2f msec", ((double) nanoseconds.tv_nsec / NSEC_PER_SEC) * 1000.0);
406 if (nanosleep (&nanoseconds, NULL) < 0) {
407 fprintf (stderr, "BAD SLEEP\n");
408 /* do something ? */
413 /* its time to deliver */
414 err = snd_seq_event_output(self->seq, &alsa_event);
415 snd_seq_drain_output (self->seq);
416 now = jack_frame_time (self->jack_client);
417 a2j_debug("alsa_out: written %d bytes to %s at %d, DELTA = %d", ev->jack_event.size, ev->port->name, now,
418 (int32_t) (now - ev->time));
421 /* free up space in the FIFO */
423 jack_ringbuffer_read_advance (self->outbound_events, vec[0].len + vec[1].len);
425 /* and head back for more */
428 return (void*) 0;
431 #define a2j_ptr ((struct a2j *)arg)
433 /* ALSA */
435 void * a2j_alsa_input_thread(void * arg)
437 struct a2j * self = arg;
438 int npfd;
439 struct pollfd * pfd;
440 snd_seq_addr_t addr;
441 snd_seq_client_info_t * client_info;
442 snd_seq_port_info_t * port_info;
443 bool initial;
444 snd_seq_event_t * event;
445 int ret;
447 npfd = snd_seq_poll_descriptors_count(self->seq, POLLIN);
448 pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd));
449 snd_seq_poll_descriptors(self->seq, pfd, npfd, POLLIN);
451 initial = true;
452 while (g_keep_alsa_walking)
454 if ((ret = poll(pfd, npfd, 1000)) > 0)
457 while (snd_seq_event_input (self->seq, &event) > 0)
459 if (initial)
461 snd_seq_client_info_alloca(&client_info);
462 snd_seq_port_info_alloca(&port_info);
463 snd_seq_client_info_set_client(client_info, -1);
464 while (snd_seq_query_next_client(self->seq, client_info) >= 0)
466 addr.client = snd_seq_client_info_get_client(client_info);
467 if (addr.client == SND_SEQ_CLIENT_SYSTEM || addr.client == self->client_id)
468 continue;
469 snd_seq_port_info_set_client(port_info, addr.client);
470 snd_seq_port_info_set_port(port_info, -1);
471 while (snd_seq_query_next_port(self->seq, port_info) >= 0)
473 addr.port = snd_seq_port_info_get_port(port_info);
474 a2j_update_port(self, addr, port_info);
478 initial = false;
481 if (event->source.client == SND_SEQ_CLIENT_SYSTEM)
483 a2j_port_event(a2j_ptr, event);
485 else
487 a2j_input_event(a2j_ptr, event);
490 snd_seq_free_event (event);
495 return (void*) 0;
499 /* JACK */
501 static
502 void
503 a2j_jack_process_internal(
504 struct a2j * self,
505 int dir,
506 jack_nframes_t nframes)
508 struct a2j_stream * stream_ptr;
509 int i;
510 struct a2j_port ** port_ptr_ptr;
511 struct a2j_port * port_ptr;
512 int nevents = 0;
514 stream_ptr = &self->stream[dir];
515 a2j_add_ports(stream_ptr);
517 // process ports
518 for (i = 0 ; i < PORT_HASH_SIZE ; i++)
520 port_ptr_ptr = &stream_ptr->port_hash[i];
521 while (*port_ptr_ptr != NULL)
523 port_ptr = *port_ptr_ptr;
525 if (!port_ptr->is_dead)
527 port_ptr->jack_buf = jack_port_get_buffer(port_ptr->jack_port, nframes);
529 if (dir == A2J_PORT_CAPTURE) {
530 a2j_process_incoming (self, port_ptr, nframes);
531 } else {
532 nevents += a2j_process_outgoing (self, port_ptr);
535 } else if (jack_ringbuffer_write_space (self->port_del) >= sizeof(port_ptr)) {
537 a2j_debug("jack: removed port %s", port_ptr->name);
538 *port_ptr_ptr = port_ptr->next;
539 jack_ringbuffer_write(self->port_del, (char*)&port_ptr, sizeof(port_ptr));
540 continue;
544 port_ptr_ptr = &port_ptr->next;
548 /* if we queued up anything for output, tell the output thread in
549 case its waiting for us.
552 if (nevents > 0) {
553 int sv;
554 sem_getvalue (&self->io_semaphore, &sv);
555 sem_post (&self->io_semaphore);
559 static
561 a2j_jack_process(
562 jack_nframes_t nframes,
563 void * arg)
565 struct a2j* self = (struct a2j *) arg;
567 if (g_freewheeling)
568 return 0;
570 self->cycle_start = jack_last_frame_time (self->jack_client);
572 a2j_jack_process_internal (self, A2J_PORT_CAPTURE, nframes);
573 a2j_jack_process_internal (self, A2J_PORT_PLAYBACK, nframes);
575 return 0;
578 static
579 void
580 a2j_jack_freewheel(
581 int starting,
582 void * arg)
584 g_freewheeling = starting;
587 static
588 void
589 a2j_jack_shutdown(
590 void * arg)
592 a2j_warning("JACK server shutdown notification received.");
593 g_stop_request = true;
596 #undef a2j_ptr
598 jack_client_t *
599 a2j_jack_client_create(
600 struct a2j * a2j_ptr,
601 const char * client_name,
602 const char * server_name)
604 jack_status_t status;
605 jack_client_t * jack_client;
607 if (server_name != NULL)
609 jack_client = jack_client_open(client_name, JackServerName|JackNoStartServer|JackUseExactName, &status, server_name);
611 else
613 jack_client = jack_client_open(client_name, JackNoStartServer|JackUseExactName, &status);
616 if (!jack_client)
618 a2j_error("Cannot create jack client");
619 return NULL;
622 jack_set_process_callback(jack_client, a2j_jack_process, a2j_ptr);
623 jack_set_freewheel_callback(jack_client, a2j_jack_freewheel, NULL);
624 jack_on_shutdown(jack_client, a2j_jack_shutdown, NULL);
626 return jack_client;