1 /* -*- Mode: C ; c-basic-offset: 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
24 #include <alsa/asoundlib.h>
25 #include <jack/jack.h>
26 #include <jack/midiport.h>
27 #include <jack/ringbuffer.h>
33 #include "port_hash.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 ==============================
58 a2j_process_incoming (
60 struct a2j_port
* port
,
61 jack_nframes_t nframes
)
63 struct a2j_alsa_midi_event ev
;
65 jack_nframes_t one_period
;
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
) {
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
)
98 offset
= self
->cycle_start
- ev
.time
;
99 if (offset
> one_period
) {
100 /* from a previous cycle, somehow. cram it in at the front */
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
);
115 memcpy( buf
, ev_buf
+ sizeof(ev
), ev
.size
);
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
);
130 snd_seq_event_t
* ev
)
132 const snd_seq_addr_t addr
= ev
->data
.addr
;
134 if (addr
.client
== self
->client_id
)
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
));
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
);
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
];
160 struct a2j_port
*port
;
163 now
= jack_frame_time (self
->jack_client
);
165 if ((port
= a2j_port_get(str
->port_hash
, alsa_event
->source
)) == NULL
) {
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) {
178 // fixup NoteOn with vel 0
179 if ((data
[0] & 0xF0) == 0x90 && data
[2] == 0x00) {
180 data
[0] = 0x80 + (data
[0] & 0x0F);
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
;
190 size_t to_write
= sizeof(ev
);
192 jack_ringbuffer_data_t vec
[2];
193 jack_ringbuffer_get_write_vector( port
->inbound_events
, vec
);
198 limit
= (to_write
> vec
[0].len
? vec
[0].len
: to_write
);
200 memcpy( vec
[0].buf
, ev_charp
, limit
);
207 memcpy( vec
[1].buf
, ev_charp
, to_write
);
208 vec
[1].buf
+= to_write
;
209 vec
[1].len
-= to_write
;
213 ev_charp
= (char *)data
;
214 limit
= (to_write
> vec
[0].len
? vec
[0].len
: to_write
);
216 memcpy( vec
[0].buf
, ev_charp
, limit
);
220 memcpy( vec
[1].buf
, ev_charp
, to_write
);
222 jack_ringbuffer_write_advance( port
->inbound_events
, sizeof(ev
) + size
);
224 a2j_error ("MIDI data lost (incoming event buffer full): %ld bytes lost", size
);
230 * ============================ Output ==============================
234 a2j_process_outgoing (
236 struct a2j_port
* port
)
238 /* collect data from JACK port buffer and queue it for later delivery by ALSA output thread */
241 jack_ringbuffer_data_t vec
[2];
245 struct a2j_delivery_event
* dev
;
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
;
261 memcpy( dev
->midistring
, dev
->jack_event
.buffer
, dev
->jack_event
.size
);
267 /* anything left? use the second part of the vector, as much as possible */
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
;
287 memcpy(dev
->midistring
, dev
->jack_event
.buffer
, dev
->jack_event
.size
);
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
);
304 time_sorter (struct a2j_delivery_event
* a
, struct a2j_delivery_event
* b
)
306 if (a
->time
< b
->time
) {
308 } else if (a
->time
> b
->time
) {
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
];
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
;
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
);
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
);
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");
362 /* now sort this list by time */
364 list_sort(&evlist
, struct a2j_delivery_event
, siblings
, time_sorter
);
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");
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 */
431 #define a2j_ptr ((struct a2j *)arg)
435 void * a2j_alsa_input_thread(void * arg
)
437 struct a2j
* self
= arg
;
441 snd_seq_client_info_t
* client_info
;
442 snd_seq_port_info_t
* port_info
;
444 snd_seq_event_t
* event
;
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
);
452 while (g_keep_alsa_walking
)
454 if ((ret
= poll(pfd
, npfd
, 1000)) > 0)
457 while (snd_seq_event_input (self
->seq
, &event
) > 0)
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
)
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
);
481 if (event
->source
.client
== SND_SEQ_CLIENT_SYSTEM
)
483 a2j_port_event(a2j_ptr
, event
);
487 a2j_input_event(a2j_ptr
, event
);
490 snd_seq_free_event (event
);
503 a2j_jack_process_internal(
506 jack_nframes_t nframes
)
508 struct a2j_stream
* stream_ptr
;
510 struct a2j_port
** port_ptr_ptr
;
511 struct a2j_port
* port_ptr
;
514 stream_ptr
= &self
->stream
[dir
];
515 a2j_add_ports(stream_ptr
);
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
);
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
));
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.
554 sem_getvalue (&self
->io_semaphore
, &sv
);
555 sem_post (&self
->io_semaphore
);
562 jack_nframes_t nframes
,
565 struct a2j
* self
= (struct a2j
*) arg
;
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
);
584 g_freewheeling
= starting
;
592 a2j_warning("JACK server shutdown notification received.");
593 g_stop_request
= true;
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
);
613 jack_client
= jack_client_open(client_name
, JackNoStartServer
|JackUseExactName
, &status
);
618 a2j_error("Cannot create jack client");
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
);