diff options
Diffstat (limited to 'drivers/am/alsa_seqmidi.c')
-rw-r--r-- | drivers/am/alsa_seqmidi.c | 609 |
1 files changed, 326 insertions, 283 deletions
diff --git a/drivers/am/alsa_seqmidi.c b/drivers/am/alsa_seqmidi.c index 3351b36..58db4b2 100644 --- a/drivers/am/alsa_seqmidi.c +++ b/drivers/am/alsa_seqmidi.c @@ -21,21 +21,21 @@ /* * alsa_seqmidi_read: * add new ports - * reads queued snd_seq_event's - * if PORT_EXIT: mark port as dead - * if PORT_ADD, PORT_CHANGE: send addr to port_thread (it also may mark port as dead) - * else process input event - * remove dead ports and send them to port_thread + * reads queued snd_seq_event's + * if PORT_EXIT: mark port as dead + * if PORT_ADD, PORT_CHANGE: send addr to port_thread (it also may mark port as dead) + * else process input event + * remove dead ports and send them to port_thread * * alsa_seqmidi_write: - * remove dead ports and send them to port_thread - * add new ports - * queue output events + * remove dead ports and send them to port_thread + * add new ports + * queue output events * * port_thread: - * wait for port_sem - * free deleted ports - * create new ports or mark existing as dead + * wait for port_sem + * free deleted ports + * create new ports or mark existing as dead */ #include <alsa/asoundlib.h> #include <jack/jack.h> @@ -52,29 +52,29 @@ #include "alsa_midi.h" #ifndef SND_SEQ_PORT_TYPE_PORT -#define SND_SEQ_PORT_TYPE_PORT (1<<19) /* Appears in version 1.0.12rc1 */ +#define SND_SEQ_PORT_TYPE_PORT (1 << 19) /* Appears in version 1.0.12rc1 */ #endif #ifndef SND_SEQ_PORT_TYPE_HARDWARE -#define SND_SEQ_PORT_TYPE_HARDWARE (1<<16) /* Appears in version 1.0.12rc1 */ +#define SND_SEQ_PORT_TYPE_HARDWARE (1 << 16) /* Appears in version 1.0.12rc1 */ #endif #ifdef STANDALONE -#define MESSAGE(...) fprintf(stderr, __VA_ARGS__) +#define MESSAGE(...) fprintf (stderr, __VA_ARGS__) #else #include "messagebuffer.h" #endif -#define info_log(...) MESSAGE(__VA_ARGS__) -#define error_log(...) MESSAGE(__VA_ARGS__) +#define info_log(...) MESSAGE (__VA_ARGS__) +#define error_log(...) MESSAGE (__VA_ARGS__) #ifdef JACK_MIDI_DEBUG -#define debug_log(...) MESSAGE(__VA_ARGS__) +#define debug_log(...) MESSAGE (__VA_ARGS__) #else #define debug_log(...) #endif -#define NSEC_PER_SEC ((int64_t)1000*1000*1000) +#define NSEC_PER_SEC ((int64_t)1000 * 1000 * 1000) enum { MAX_PORTS = 64, @@ -124,8 +124,8 @@ typedef struct alsa_seqmidi { pthread_t port_thread; sem_t port_sem; - jack_ringbuffer_t *port_add; // snd_seq_addr_t - jack_ringbuffer_t *port_del; // port_t* + jack_ringbuffer_t *port_add; // snd_seq_addr_t + jack_ringbuffer_t *port_del; // port_t* stream_t stream[2]; @@ -150,7 +150,7 @@ struct process_info { enum PortType { PORT_INPUT = 0, PORT_OUTPUT = 1 }; -typedef void (*port_jack_func)(alsa_seqmidi_t *self, port_t *port,struct process_info* info); +typedef void (*port_jack_func)(alsa_seqmidi_t *self, port_t *port, struct process_info* info); static void do_jack_input(alsa_seqmidi_t *self, port_t *port, struct process_info* info); static void do_jack_output(alsa_seqmidi_t *self, port_t *port, struct process_info* info); @@ -186,36 +186,36 @@ static void alsa_seqmidi_read(alsa_midi_t *m, jack_nframes_t nframes); static void alsa_seqmidi_write(alsa_midi_t *m, jack_nframes_t nframes); static -void stream_init(alsa_seqmidi_t *self, int dir) +void stream_init (alsa_seqmidi_t *self, int dir) { stream_t *str = &self->stream[dir]; - str->new_ports = jack_ringbuffer_create(MAX_PORTS*sizeof(port_t*)); - snd_midi_event_new(MAX_EVENT_SIZE, &str->codec); + str->new_ports = jack_ringbuffer_create (MAX_PORTS * sizeof(port_t*)); + snd_midi_event_new (MAX_EVENT_SIZE, &str->codec); } static void port_free(alsa_seqmidi_t *self, port_t *port); static void free_ports(alsa_seqmidi_t *self, jack_ringbuffer_t *ports); static -void stream_attach(alsa_seqmidi_t *self, int dir) +void stream_attach (alsa_seqmidi_t *self, int dir) { } static -void stream_detach(alsa_seqmidi_t *self, int dir) +void stream_detach (alsa_seqmidi_t *self, int dir) { stream_t *str = &self->stream[dir]; int i; - free_ports(self, str->new_ports); + free_ports (self, str->new_ports); // delete all ports from hash - for (i=0; i<PORT_HASH_SIZE; ++i) { + for (i = 0; i < PORT_HASH_SIZE; ++i) { port_t *port = str->ports[i]; while (port) { port_t *next = port->next; - port_free(self, port); + port_free (self, port); port = next; } str->ports[i] = NULL; @@ -223,33 +223,38 @@ void stream_detach(alsa_seqmidi_t *self, int dir) } static -void stream_close(alsa_seqmidi_t *self, int dir) +void stream_close (alsa_seqmidi_t *self, int dir) { stream_t *str = &self->stream[dir]; - if (str->codec) - snd_midi_event_free(str->codec); - if (str->new_ports) - jack_ringbuffer_free(str->new_ports); + if (str->codec) { + snd_midi_event_free (str->codec); + } + if (str->new_ports) { + jack_ringbuffer_free (str->new_ports); + } } -alsa_midi_t* alsa_seqmidi_new(jack_client_t *client, const char* alsa_name) +alsa_midi_t* alsa_seqmidi_new (jack_client_t *client, const char* alsa_name) { - alsa_seqmidi_t *self = calloc(1, sizeof(alsa_seqmidi_t)); - debug_log("midi: new\n"); - if (!self) + alsa_seqmidi_t *self = calloc (1, sizeof(alsa_seqmidi_t)); + + debug_log ("midi: new\n"); + if (!self) { return NULL; + } self->jack = client; - if (!alsa_name) + if (!alsa_name) { alsa_name = "jack_midi"; - snprintf(self->alsa_name, sizeof(self->alsa_name), "%s", alsa_name); + } + snprintf (self->alsa_name, sizeof(self->alsa_name), "%s", alsa_name); - self->port_add = jack_ringbuffer_create(2*MAX_PORTS*sizeof(snd_seq_addr_t)); - self->port_del = jack_ringbuffer_create(2*MAX_PORTS*sizeof(port_t*)); - sem_init(&self->port_sem, 0, 0); + self->port_add = jack_ringbuffer_create (2 * MAX_PORTS * sizeof(snd_seq_addr_t)); + self->port_del = jack_ringbuffer_create (2 * MAX_PORTS * sizeof(port_t*)); + sem_init (&self->port_sem, 0, 0); - stream_init(self, PORT_INPUT); - stream_init(self, PORT_OUTPUT); + stream_init (self, PORT_INPUT); + stream_init (self, PORT_OUTPUT); self->ops.destroy = alsa_seqmidi_delete; self->ops.attach = alsa_seqmidi_attach; @@ -262,77 +267,79 @@ alsa_midi_t* alsa_seqmidi_new(jack_client_t *client, const char* alsa_name) } static -void alsa_seqmidi_delete(alsa_midi_t *m) +void alsa_seqmidi_delete (alsa_midi_t *m) { - alsa_seqmidi_t *self = (alsa_seqmidi_t*) m; + alsa_seqmidi_t *self = (alsa_seqmidi_t*)m; - debug_log("midi: delete\n"); - alsa_seqmidi_detach(m); + debug_log ("midi: delete\n"); + alsa_seqmidi_detach (m); - stream_close(self, PORT_OUTPUT); - stream_close(self, PORT_INPUT); + stream_close (self, PORT_OUTPUT); + stream_close (self, PORT_INPUT); - jack_ringbuffer_free(self->port_add); - jack_ringbuffer_free(self->port_del); - sem_close(&self->port_sem); + jack_ringbuffer_free (self->port_add); + jack_ringbuffer_free (self->port_del); + sem_close (&self->port_sem); - free(self); + free (self); } static -int alsa_seqmidi_attach(alsa_midi_t *m) +int alsa_seqmidi_attach (alsa_midi_t *m) { - alsa_seqmidi_t *self = (alsa_seqmidi_t*) m; + alsa_seqmidi_t *self = (alsa_seqmidi_t*)m; int err; - debug_log("midi: attach\n"); + debug_log ("midi: attach\n"); - if (self->seq) + if (self->seq) { return -EALREADY; + } - if ((err = snd_seq_open(&self->seq, "hw", SND_SEQ_OPEN_DUPLEX, 0)) < 0) { - error_log("failed to open alsa seq"); + if ((err = snd_seq_open (&self->seq, "hw", SND_SEQ_OPEN_DUPLEX, 0)) < 0) { + error_log ("failed to open alsa seq"); return err; } - snd_seq_set_client_name(self->seq, self->alsa_name); - self->port_id = snd_seq_create_simple_port(self->seq, "port", - SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_WRITE + snd_seq_set_client_name (self->seq, self->alsa_name); + self->port_id = snd_seq_create_simple_port (self->seq, "port", + SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_WRITE #ifndef JACK_MIDI_DEBUG - |SND_SEQ_PORT_CAP_NO_EXPORT + | SND_SEQ_PORT_CAP_NO_EXPORT #endif - ,SND_SEQ_PORT_TYPE_APPLICATION); - self->client_id = snd_seq_client_id(self->seq); + , SND_SEQ_PORT_TYPE_APPLICATION); + self->client_id = snd_seq_client_id (self->seq); - self->queue = snd_seq_alloc_queue(self->seq); - snd_seq_start_queue(self->seq, self->queue, 0); + self->queue = snd_seq_alloc_queue (self->seq); + snd_seq_start_queue (self->seq, self->queue, 0); - stream_attach(self, PORT_INPUT); - stream_attach(self, PORT_OUTPUT); + stream_attach (self, PORT_INPUT); + stream_attach (self, PORT_OUTPUT); - snd_seq_nonblock(self->seq, 1); + snd_seq_nonblock (self->seq, 1); return 0; } static -int alsa_seqmidi_detach(alsa_midi_t *m) +int alsa_seqmidi_detach (alsa_midi_t *m) { - alsa_seqmidi_t *self = (alsa_seqmidi_t*) m; + alsa_seqmidi_t *self = (alsa_seqmidi_t*)m; - debug_log("midi: detach\n"); + debug_log ("midi: detach\n"); - if (!self->seq) + if (!self->seq) { return -EALREADY; + } - alsa_seqmidi_stop(m); + alsa_seqmidi_stop (m); - jack_ringbuffer_reset(self->port_add); - free_ports(self, self->port_del); + jack_ringbuffer_reset (self->port_add); + free_ports (self, self->port_del); - stream_detach(self, PORT_INPUT); - stream_detach(self, PORT_OUTPUT); + stream_detach (self, PORT_INPUT); + stream_detach (self, PORT_OUTPUT); - snd_seq_close(self->seq); + snd_seq_close (self->seq); self->seq = NULL; return 0; @@ -345,30 +352,32 @@ static void update_ports(alsa_seqmidi_t *self); static void add_ports(stream_t *str); static -int alsa_seqmidi_start(alsa_midi_t *m) +int alsa_seqmidi_start (alsa_midi_t *m) { - alsa_seqmidi_t *self = (alsa_seqmidi_t*) m; + alsa_seqmidi_t *self = (alsa_seqmidi_t*)m; int err; - debug_log("midi: start\n"); + debug_log ("midi: start\n"); - if (!self->seq) + if (!self->seq) { return -EBADF; + } - if (self->keep_walking) + if (self->keep_walking) { return -EALREADY; + } - snd_seq_connect_from(self->seq, self->port_id, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE); - snd_seq_drop_input(self->seq); + snd_seq_connect_from (self->seq, self->port_id, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE); + snd_seq_drop_input (self->seq); - add_existing_ports(self); - update_ports(self); - add_ports(&self->stream[PORT_INPUT]); - add_ports(&self->stream[PORT_OUTPUT]); + add_existing_ports (self); + update_ports (self); + add_ports (&self->stream[PORT_INPUT]); + add_ports (&self->stream[PORT_OUTPUT]); self->keep_walking = 1; - if ((err = pthread_create(&self->port_thread, NULL, port_thread, self))) { + if ((err = pthread_create (&self->port_thread, NULL, port_thread, self))) { self->keep_walking = 0; return -errno; } @@ -377,47 +386,49 @@ int alsa_seqmidi_start(alsa_midi_t *m) } static -int alsa_seqmidi_stop(alsa_midi_t *m) +int alsa_seqmidi_stop (alsa_midi_t *m) { - alsa_seqmidi_t *self = (alsa_seqmidi_t*) m; + alsa_seqmidi_t *self = (alsa_seqmidi_t*)m; - debug_log("midi: stop\n"); + debug_log ("midi: stop\n"); - if (!self->keep_walking) + if (!self->keep_walking) { return -EALREADY; + } - snd_seq_disconnect_from(self->seq, self->port_id, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE); + snd_seq_disconnect_from (self->seq, self->port_id, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE); self->keep_walking = 0; - sem_post(&self->port_sem); - pthread_join(self->port_thread, NULL); + sem_post (&self->port_sem); + pthread_join (self->port_thread, NULL); self->port_thread = 0; return 0; } static -int alsa_connect_from(alsa_seqmidi_t *self, int client, int port) +int alsa_connect_from (alsa_seqmidi_t *self, int client, int port) { snd_seq_port_subscribe_t* sub; snd_seq_addr_t seq_addr; int err; - snd_seq_port_subscribe_alloca(&sub); + snd_seq_port_subscribe_alloca (&sub); seq_addr.client = client; seq_addr.port = port; - snd_seq_port_subscribe_set_sender(sub, &seq_addr); + snd_seq_port_subscribe_set_sender (sub, &seq_addr); seq_addr.client = self->client_id; seq_addr.port = self->port_id; - snd_seq_port_subscribe_set_dest(sub, &seq_addr); + snd_seq_port_subscribe_set_dest (sub, &seq_addr); - snd_seq_port_subscribe_set_time_update(sub, 1); - snd_seq_port_subscribe_set_queue(sub, self->queue); - snd_seq_port_subscribe_set_time_real(sub, 1); + snd_seq_port_subscribe_set_time_update (sub, 1); + snd_seq_port_subscribe_set_queue (sub, self->queue); + snd_seq_port_subscribe_set_time_real (sub, 1); - if ((err=snd_seq_subscribe_port(self->seq, sub))) - error_log("can't subscribe to %d:%d - %s\n", client, port, snd_strerror(err)); + if ((err = snd_seq_subscribe_port (self->seq, sub))) { + error_log ("can't subscribe to %d:%d - %s\n", client, port, snd_strerror (err)); + } return err; } @@ -425,58 +436,65 @@ int alsa_connect_from(alsa_seqmidi_t *self, int client, int port) * ==================== Port routines ============================= */ static inline -int port_hash(snd_seq_addr_t addr) +int port_hash (snd_seq_addr_t addr) { return (addr.client + addr.port) % PORT_HASH_SIZE; } static -port_t* port_get(port_hash_t hash, snd_seq_addr_t addr) +port_t* port_get (port_hash_t hash, snd_seq_addr_t addr) { - port_t **pport = &hash[port_hash(addr)]; + port_t **pport = &hash[port_hash (addr)]; + while (*pport) { port_t *port = *pport; - if (port->remote.client == addr.client && port->remote.port == addr.port) + if (port->remote.client == addr.client && port->remote.port == addr.port) { return port; + } pport = &port->next; } return NULL; } static -void port_insert(port_hash_t hash, port_t *port) +void port_insert (port_hash_t hash, port_t *port) { - port_t **pport = &hash[port_hash(port->remote)]; + port_t **pport = &hash[port_hash (port->remote)]; + port->next = *pport; *pport = port; } static -void port_setdead(port_hash_t hash, snd_seq_addr_t addr) +void port_setdead (port_hash_t hash, snd_seq_addr_t addr) { - port_t *port = port_get(hash, addr); - if (port) + port_t *port = port_get (hash, addr); + + if (port) { port->is_dead = 1; // see jack_process - else - debug_log("port_setdead: not found (%d:%d)\n", addr.client, addr.port); + } else { + debug_log ("port_setdead: not found (%d:%d)\n", addr.client, addr.port); + } } static -void port_free(alsa_seqmidi_t *self, port_t *port) +void port_free (alsa_seqmidi_t *self, port_t *port) { //snd_seq_disconnect_from(self->seq, self->port_id, port->remote.client, port->remote.port); //snd_seq_disconnect_to(self->seq, self->port_id, port->remote.client, port->remote.port); - if (port->early_events) - jack_ringbuffer_free(port->early_events); - if (port->jack_port) - jack_port_unregister(self->jack, port->jack_port); + if (port->early_events) { + jack_ringbuffer_free (port->early_events); + } + if (port->jack_port) { + jack_port_unregister (self->jack, port->jack_port); + } // info_log("port deleted: %s\n", port->name); - free(port); + free (port); } static -port_t* port_create(alsa_seqmidi_t *self, int type, snd_seq_addr_t addr, const snd_seq_port_info_t *info) +port_t* port_create (alsa_seqmidi_t *self, int type, snd_seq_addr_t addr, const snd_seq_port_info_t *info) { snd_seq_client_info_t* client_info; port_t *port; @@ -484,62 +502,68 @@ port_t* port_create(alsa_seqmidi_t *self, int type, snd_seq_addr_t addr, const s int err; int jack_caps; - port = calloc(1, sizeof(port_t)); - if (!port) + port = calloc (1, sizeof(port_t)); + if (!port) { return NULL; + } port->remote = addr; snd_seq_client_info_alloca (&client_info); snd_seq_get_any_client_info (self->seq, addr.client, client_info); - snprintf(port->name, sizeof(port->name), "%s/midi_%s_%d", - snd_seq_client_info_get_name(client_info), port_type[type].name, addr.port+1); + snprintf (port->name, sizeof(port->name), "%s/midi_%s_%d", + snd_seq_client_info_get_name (client_info), port_type[type].name, addr.port + 1); // replace all offending characters by - for (c = port->name; *c; ++c) - if (!isalnum(*c) && *c != '/' && *c != '_' && *c != ':' && *c != '(' && *c != ')') + if (!isalnum (*c) && *c != '/' && *c != '_' && *c != ':' && *c != '(' && *c != ')') { *c = '-'; + } jack_caps = port_type[type].jack_caps; /* mark anything that looks like a hardware port as physical&terminal */ - if (snd_seq_port_info_get_type (info) & (SND_SEQ_PORT_TYPE_HARDWARE|SND_SEQ_PORT_TYPE_PORT|SND_SEQ_PORT_TYPE_SPECIFIC)) { - jack_caps |= (JackPortIsPhysical|JackPortIsTerminal); + if (snd_seq_port_info_get_type (info) & (SND_SEQ_PORT_TYPE_HARDWARE | SND_SEQ_PORT_TYPE_PORT | SND_SEQ_PORT_TYPE_SPECIFIC)) { + jack_caps |= (JackPortIsPhysical | JackPortIsTerminal); } - - port->jack_port = jack_port_register(self->jack, - port->name, JACK_DEFAULT_MIDI_TYPE, jack_caps, 0); - if (!port->jack_port) + + port->jack_port = jack_port_register (self->jack, + port->name, JACK_DEFAULT_MIDI_TYPE, jack_caps, 0); + if (!port->jack_port) { goto failed; + } /* generate an alias */ - snprintf(port->name, sizeof(port->name), "%s:midi/%s_%d", - snd_seq_client_info_get_name (client_info), port_type[type].name, addr.port+1); + snprintf (port->name, sizeof(port->name), "%s:midi/%s_%d", + snd_seq_client_info_get_name (client_info), port_type[type].name, addr.port + 1); // replace all offending characters by - for (c = port->name; *c; ++c) - if (!isalnum(*c) && *c != '/' && *c != '_' && *c != ':' && *c != '(' && *c != ')') + if (!isalnum (*c) && *c != '/' && *c != '_' && *c != ':' && *c != '(' && *c != ')') { *c = '-'; + } jack_port_set_alias (port->jack_port, port->name); - if (type == PORT_INPUT) - err = alsa_connect_from(self, port->remote.client, port->remote.port); - else - err = snd_seq_connect_to(self->seq, self->port_id, port->remote.client, port->remote.port); - if (err) + if (type == PORT_INPUT) { + err = alsa_connect_from (self, port->remote.client, port->remote.port); + } else { + err = snd_seq_connect_to (self->seq, self->port_id, port->remote.client, port->remote.port); + } + if (err) { goto failed; + } - port->early_events = jack_ringbuffer_create(MAX_EVENT_SIZE*16); + port->early_events = jack_ringbuffer_create (MAX_EVENT_SIZE * 16); // info_log("port created: %s\n", port->name); return port; - failed: - port_free(self, port); +failed: + port_free (self, port); return NULL; } @@ -547,65 +571,69 @@ port_t* port_create(alsa_seqmidi_t *self, int type, snd_seq_addr_t addr, const s * ==================== Port add/del handling thread ============================== */ static -void update_port_type(alsa_seqmidi_t *self, int type, snd_seq_addr_t addr, int caps, const snd_seq_port_info_t *info) +void update_port_type (alsa_seqmidi_t *self, int type, snd_seq_addr_t addr, int caps, const snd_seq_port_info_t *info) { stream_t *str = &self->stream[type]; int alsa_mask = port_type[type].alsa_mask; - port_t *port = port_get(str->ports, addr); + port_t *port = port_get (str->ports, addr); - debug_log("update_port_type(%d:%d)\n", addr.client, addr.port); + debug_log ("update_port_type(%d:%d)\n", addr.client, addr.port); - if (port && (caps & alsa_mask)!=alsa_mask) { - debug_log("setdead: %s\n", port->name); + if (port && (caps & alsa_mask) != alsa_mask) { + debug_log ("setdead: %s\n", port->name); port->is_dead = 1; } - if (!port && (caps & alsa_mask)==alsa_mask) { - assert (jack_ringbuffer_write_space(str->new_ports) >= sizeof(port)); - port = port_create(self, type, addr, info); - if (port) - jack_ringbuffer_write(str->new_ports, (char*)&port, sizeof(port)); + if (!port && (caps & alsa_mask) == alsa_mask) { + assert (jack_ringbuffer_write_space (str->new_ports) >= sizeof(port)); + port = port_create (self, type, addr, info); + if (port) { + jack_ringbuffer_write (str->new_ports, (char*)&port, sizeof(port)); + } } } static -void update_port(alsa_seqmidi_t *self, snd_seq_addr_t addr, const snd_seq_port_info_t *info) +void update_port (alsa_seqmidi_t *self, snd_seq_addr_t addr, const snd_seq_port_info_t *info) { - unsigned int port_caps = snd_seq_port_info_get_capability(info); - if (port_caps & SND_SEQ_PORT_CAP_NO_EXPORT) + unsigned int port_caps = snd_seq_port_info_get_capability (info); + + if (port_caps & SND_SEQ_PORT_CAP_NO_EXPORT) { return; - update_port_type(self, PORT_INPUT, addr, port_caps, info); - update_port_type(self, PORT_OUTPUT,addr, port_caps, info); + } + update_port_type (self, PORT_INPUT, addr, port_caps, info); + update_port_type (self, PORT_OUTPUT, addr, port_caps, info); } static -void free_ports(alsa_seqmidi_t *self, jack_ringbuffer_t *ports) +void free_ports (alsa_seqmidi_t *self, jack_ringbuffer_t *ports) { port_t *port; int sz; - while ((sz = jack_ringbuffer_read(ports, (char*)&port, sizeof(port)))) { + + while ((sz = jack_ringbuffer_read (ports, (char*)&port, sizeof(port)))) { assert (sz == sizeof(port)); - port_free(self, port); + port_free (self, port); } } static -void update_ports(alsa_seqmidi_t *self) +void update_ports (alsa_seqmidi_t *self) { snd_seq_addr_t addr; snd_seq_port_info_t *info; int size; - snd_seq_port_info_alloca(&info); + snd_seq_port_info_alloca (&info); + + while ((size = jack_ringbuffer_read (self->port_add, (char*)&addr, sizeof(addr)))) { - while ((size = jack_ringbuffer_read(self->port_add, (char*)&addr, sizeof(addr)))) { - int err; assert (size == sizeof(addr)); assert (addr.client != self->client_id); - if ((err=snd_seq_get_any_port_info(self->seq, addr.client, addr.port, info))>=0) { - update_port(self, addr, info); + if ((err = snd_seq_get_any_port_info (self->seq, addr.client, addr.port, info)) >= 0) { + update_port (self, addr, info); } else { //port_setdead(self->stream[PORT_INPUT].ports, addr); //port_setdead(self->stream[PORT_OUTPUT].ports, addr); @@ -614,40 +642,39 @@ void update_ports(alsa_seqmidi_t *self) } static -void* port_thread(void *arg) +void* port_thread (void *arg) { alsa_seqmidi_t *self = arg; while (self->keep_walking) { - sem_wait(&self->port_sem); - free_ports(self, self->port_del); - update_ports(self); + sem_wait (&self->port_sem); + free_ports (self, self->port_del); + update_ports (self); } - debug_log("port_thread exited\n"); + debug_log ("port_thread exited\n"); return NULL; } static -void add_existing_ports(alsa_seqmidi_t *self) +void add_existing_ports (alsa_seqmidi_t *self) { snd_seq_addr_t addr; snd_seq_client_info_t *client_info; snd_seq_port_info_t *port_info; - snd_seq_client_info_alloca(&client_info); - snd_seq_port_info_alloca(&port_info); - snd_seq_client_info_set_client(client_info, -1); - while (snd_seq_query_next_client(self->seq, client_info) >= 0) - { - addr.client = snd_seq_client_info_get_client(client_info); - if (addr.client == SND_SEQ_CLIENT_SYSTEM || addr.client == self->client_id) + snd_seq_client_info_alloca (&client_info); + snd_seq_port_info_alloca (&port_info); + snd_seq_client_info_set_client (client_info, -1); + while (snd_seq_query_next_client (self->seq, client_info) >= 0) { + addr.client = snd_seq_client_info_get_client (client_info); + if (addr.client == SND_SEQ_CLIENT_SYSTEM || addr.client == self->client_id) { continue; - snd_seq_port_info_set_client(port_info, addr.client); - snd_seq_port_info_set_port(port_info, -1); - while (snd_seq_query_next_port(self->seq, port_info) >= 0) - { - addr.port = snd_seq_port_info_get_port(port_info); - update_port(self, addr, port_info); + } + snd_seq_port_info_set_client (port_info, addr.client); + snd_seq_port_info_set_port (port_info, -1); + while (snd_seq_query_next_port (self->seq, port_info) >= 0) { + addr.port = snd_seq_port_info_get_port (port_info); + update_port (self, addr, port_info); } } } @@ -656,67 +683,69 @@ void add_existing_ports(alsa_seqmidi_t *self) * =================== Input/output port handling ========================= */ static -void set_process_info(struct process_info *info, alsa_seqmidi_t *self, int dir, jack_nframes_t nframes) +void set_process_info (struct process_info *info, alsa_seqmidi_t *self, int dir, jack_nframes_t nframes) { const snd_seq_real_time_t* alsa_time; snd_seq_queue_status_t *status; - snd_seq_queue_status_alloca(&status); + snd_seq_queue_status_alloca (&status); info->dir = dir; - info->period_start = jack_last_frame_time(self->jack); + info->period_start = jack_last_frame_time (self->jack); info->nframes = nframes; - info->sample_rate = jack_get_sample_rate(self->jack); + info->sample_rate = jack_get_sample_rate (self->jack); - info->cur_frames = jack_frame_time(self->jack); + info->cur_frames = jack_frame_time (self->jack); // immediately get alsa'a real time (uhh, why everybody has their on 'real' time) - snd_seq_get_queue_status(self->seq, self->queue, status); - alsa_time = snd_seq_queue_status_get_real_time(status); + snd_seq_get_queue_status (self->seq, self->queue, status); + alsa_time = snd_seq_queue_status_get_real_time (status); info->alsa_time = alsa_time->tv_sec * NSEC_PER_SEC + alsa_time->tv_nsec; if (info->period_start + info->nframes < info->cur_frames) { - int periods_lost = (info->cur_frames - info->period_start) / info->nframes; + int periods_lost = (info->cur_frames - info->period_start) / info->nframes; info->period_start += periods_lost * info->nframes; - debug_log("xrun detected: %d periods lost\n", periods_lost); + debug_log ("xrun detected: %d periods lost\n", periods_lost); } } static -void add_ports(stream_t *str) +void add_ports (stream_t *str) { port_t *port; - while (jack_ringbuffer_read(str->new_ports, (char*)&port, sizeof(port))) { - debug_log("jack: inserted port %s\n", port->name); - port_insert(str->ports, port); + + while (jack_ringbuffer_read (str->new_ports, (char*)&port, sizeof(port))) { + debug_log ("jack: inserted port %s\n", port->name); + port_insert (str->ports, port); } } static -void jack_process(alsa_seqmidi_t *self, struct process_info *info) +void jack_process (alsa_seqmidi_t *self, struct process_info *info) { stream_t *str = &self->stream[info->dir]; port_jack_func process = port_type[info->dir].jack_func; - int i, del=0; + int i, del = 0; - add_ports(str); + add_ports (str); // process ports - for (i=0; i<PORT_HASH_SIZE; ++i) { + for (i = 0; i < PORT_HASH_SIZE; ++i) { port_t **pport = &str->ports[i]; while (*pport) { port_t *port = *pport; - port->jack_buf = jack_port_get_buffer(port->jack_port, info->nframes); - if (info->dir == PORT_INPUT) - jack_midi_clear_buffer(port->jack_buf); + port->jack_buf = jack_port_get_buffer (port->jack_port, info->nframes); + if (info->dir == PORT_INPUT) { + jack_midi_clear_buffer (port->jack_buf); + } - if (!port->is_dead) + if (!port->is_dead) { (*process)(self, port, info); - else if (jack_ringbuffer_write_space(self->port_del) >= sizeof(port)) { - debug_log("jack: removed port %s\n", port->name); + } else if (jack_ringbuffer_write_space (self->port_del) >= sizeof(port)) { + debug_log ("jack: removed port %s\n", port->name); *pport = port->next; - jack_ringbuffer_write(self->port_del, (char*)&port, sizeof(port)); + jack_ringbuffer_write (self->port_del, (char*)&port, sizeof(port)); del++; continue; } @@ -725,57 +754,62 @@ void jack_process(alsa_seqmidi_t *self, struct process_info *info) } } - if (del) - sem_post(&self->port_sem); + if (del) { + sem_post (&self->port_sem); + } } /* * ============================ Input ============================== */ static -void do_jack_input(alsa_seqmidi_t *self, port_t *port, struct process_info *info) +void do_jack_input (alsa_seqmidi_t *self, port_t *port, struct process_info *info) { // process port->early_events alsa_midi_event_t ev; - while (jack_ringbuffer_read(port->early_events, (char*)&ev, sizeof(ev))) { + + while (jack_ringbuffer_read (port->early_events, (char*)&ev, sizeof(ev))) { jack_midi_data_t* buf; jack_nframes_t time = ev.time - info->period_start; - if (time < 0) + if (time < 0) { time = 0; - else if (time >= info->nframes) + } else if (time >= info->nframes) { time = info->nframes - 1; - buf = jack_midi_event_reserve(port->jack_buf, time, ev.size); - if (buf) - jack_ringbuffer_read(port->early_events, (char*)buf, ev.size); - else - jack_ringbuffer_read_advance(port->early_events, ev.size); - debug_log("input: it's time for %d bytes at %d\n", ev.size, time); + } + buf = jack_midi_event_reserve (port->jack_buf, time, ev.size); + if (buf) { + jack_ringbuffer_read (port->early_events, (char*)buf, ev.size); + } else { + jack_ringbuffer_read_advance (port->early_events, ev.size); + } + debug_log ("input: it's time for %d bytes at %d\n", ev.size, time); } } static -void port_event(alsa_seqmidi_t *self, snd_seq_event_t *ev) +void port_event (alsa_seqmidi_t *self, snd_seq_event_t *ev) { const snd_seq_addr_t addr = ev->data.addr; - if (addr.client == self->client_id) + if (addr.client == self->client_id) { return; + } if (ev->type == SND_SEQ_EVENT_PORT_START || ev->type == SND_SEQ_EVENT_PORT_CHANGE) { - assert (jack_ringbuffer_write_space(self->port_add) >= sizeof(addr)); + assert (jack_ringbuffer_write_space (self->port_add) >= sizeof(addr)); - debug_log("port_event: add/change %d:%d\n", addr.client, addr.port); - jack_ringbuffer_write(self->port_add, (char*)&addr, sizeof(addr)); - sem_post(&self->port_sem); + debug_log ("port_event: add/change %d:%d\n", addr.client, addr.port); + jack_ringbuffer_write (self->port_add, (char*)&addr, sizeof(addr)); + sem_post (&self->port_sem); } else if (ev->type == SND_SEQ_EVENT_PORT_EXIT) { - debug_log("port_event: del %d:%d\n", addr.client, addr.port); - port_setdead(self->stream[PORT_INPUT].ports, addr); - port_setdead(self->stream[PORT_OUTPUT].ports, addr); + debug_log ("port_event: del %d:%d\n", addr.client, addr.port); + port_setdead (self->stream[PORT_INPUT].ports, addr); + port_setdead (self->stream[PORT_OUTPUT].ports, addr); } } static -void input_event(alsa_seqmidi_t *self, snd_seq_event_t *alsa_event, struct process_info* info) +void input_event (alsa_seqmidi_t *self, snd_seq_event_t *alsa_event, struct process_info* info) { jack_midi_data_t data[MAX_EVENT_SIZE]; stream_t *str = &self->stream[PORT_INPUT]; @@ -784,17 +818,19 @@ void input_event(alsa_seqmidi_t *self, snd_seq_event_t *alsa_event, struct proce int64_t frame_offset, event_frame; port_t *port; - port = port_get(str->ports, alsa_event->source); - if (!port) + port = port_get (str->ports, alsa_event->source); + if (!port) { return; + } /* * RPNs, NRPNs, Bank Change, etc. need special handling * but seems, ALSA does it for us already. */ - snd_midi_event_reset_decode(str->codec); - if ((size = snd_midi_event_decode(str->codec, data, sizeof(data), alsa_event))<0) + snd_midi_event_reset_decode (str->codec); + if ((size = snd_midi_event_decode (str->codec, data, sizeof(data), alsa_event)) < 0) { return; + } // fixup NoteOn with vel 0 if ((data[0] & 0xF0) == 0x90 && data[2] == 0x00) { @@ -807,46 +843,49 @@ void input_event(alsa_seqmidi_t *self, snd_seq_event_t *alsa_event, struct proce frame_offset = (info->sample_rate * time_offset) / NSEC_PER_SEC; event_frame = (int64_t)info->cur_frames - info->period_start - frame_offset + info->nframes; - debug_log("input: %d bytes at event_frame=%d\n", (int)size, (int)event_frame); + debug_log ("input: %d bytes at event_frame=%d\n", (int)size, (int)event_frame); if (event_frame >= info->nframes && - jack_ringbuffer_write_space(port->early_events) >= (sizeof(alsa_midi_event_t) + size)) { + jack_ringbuffer_write_space (port->early_events) >= (sizeof(alsa_midi_event_t) + size)) { alsa_midi_event_t ev; ev.time = event_frame + info->period_start; ev.size = size; - jack_ringbuffer_write(port->early_events, (char*)&ev, sizeof(ev)); - jack_ringbuffer_write(port->early_events, (char*)data, size); - debug_log("postponed to next frame +%d\n", (int) (event_frame - info->nframes)); + jack_ringbuffer_write (port->early_events, (char*)&ev, sizeof(ev)); + jack_ringbuffer_write (port->early_events, (char*)data, size); + debug_log ("postponed to next frame +%d\n", (int)(event_frame - info->nframes)); return; } - if (event_frame < 0) + if (event_frame < 0) { event_frame = 0; - else if (event_frame >= info->nframes) + } else if (event_frame >= info->nframes) { event_frame = info->nframes - 1; + } - jack_midi_event_write(port->jack_buf, event_frame, data, size); + jack_midi_event_write (port->jack_buf, event_frame, data, size); } static -void alsa_seqmidi_read(alsa_midi_t *m, jack_nframes_t nframes) +void alsa_seqmidi_read (alsa_midi_t *m, jack_nframes_t nframes) { - alsa_seqmidi_t *self = (alsa_seqmidi_t*) m; + alsa_seqmidi_t *self = (alsa_seqmidi_t*)m; int res; snd_seq_event_t *event; struct process_info info; - if (!self->keep_walking) + if (!self->keep_walking) { return; + } - set_process_info(&info, self, PORT_INPUT, nframes); - jack_process(self, &info); + set_process_info (&info, self, PORT_INPUT, nframes); + jack_process (self, &info); - while ((res = snd_seq_event_input(self->seq, &event))>0) { - if (event->source.client == SND_SEQ_CLIENT_SYSTEM) - port_event(self, event); - else - input_event(self, event, &info); + while ((res = snd_seq_event_input (self->seq, &event)) > 0) { + if (event->source.client == SND_SEQ_CLIENT_SYSTEM) { + port_event (self, event); + } else { + input_event (self, event, &info); + } } } @@ -855,12 +894,13 @@ void alsa_seqmidi_read(alsa_midi_t *m, jack_nframes_t nframes) */ static -void do_jack_output(alsa_seqmidi_t *self, port_t *port, struct process_info* info) +void do_jack_output (alsa_seqmidi_t *self, port_t *port, struct process_info* info) { stream_t *str = &self->stream[info->dir]; - int nevents = jack_midi_get_event_count(port->jack_buf); + int nevents = jack_midi_get_event_count (port->jack_buf); int i; - for (i=0; i<nevents; ++i) { + + for (i = 0; i < nevents; ++i) { jack_midi_event_t jack_event; snd_seq_event_t alsa_event; int64_t frame_offset; @@ -868,21 +908,22 @@ void do_jack_output(alsa_seqmidi_t *self, port_t *port, struct process_info* inf snd_seq_real_time_t out_rt; int err; - jack_midi_event_get(&jack_event, port->jack_buf, i); + jack_midi_event_get (&jack_event, port->jack_buf, i); - snd_seq_ev_clear(&alsa_event); - snd_midi_event_reset_encode(str->codec); - if (!snd_midi_event_encode(str->codec, jack_event.buffer, jack_event.size, &alsa_event)) + snd_seq_ev_clear (&alsa_event); + snd_midi_event_reset_encode (str->codec); + if (!snd_midi_event_encode (str->codec, jack_event.buffer, jack_event.size, &alsa_event)) { continue; // invalid event - snd_seq_ev_set_source(&alsa_event, self->port_id); - snd_seq_ev_set_dest(&alsa_event, port->remote.client, port->remote.port); + } + snd_seq_ev_set_source (&alsa_event, self->port_id); + snd_seq_ev_set_dest (&alsa_event, port->remote.client, port->remote.port); /* NOTE: in case of xrun it could become negative, so it is essential to use signed type! */ frame_offset = (int64_t)jack_event.time + info->period_start + info->nframes - info->cur_frames; if (frame_offset < 0) { frame_offset = info->nframes + jack_event.time; - error_log("internal xrun detected: frame_offset = %"PRId64"\n", frame_offset); + error_log ("internal xrun detected: frame_offset = %" PRId64 "\n", frame_offset); } /* Ken Ellinwood reported problems with this assert. * Seems, magic 2 should be replaced with nperiods. */ @@ -894,32 +935,34 @@ void do_jack_output(alsa_seqmidi_t *self, port_t *port, struct process_info* inf // we should use absolute time to prevent reordering caused by rounding errors if (out_time < port->last_out_time) { - debug_log("alsa_out: limiting out_time %lld at %lld\n", out_time, port->last_out_time); + debug_log ("alsa_out: limiting out_time %lld at %lld\n", out_time, port->last_out_time); out_time = port->last_out_time; - } else + } else { port->last_out_time = out_time; + } out_rt.tv_nsec = out_time % NSEC_PER_SEC; out_rt.tv_sec = out_time / NSEC_PER_SEC; - snd_seq_ev_schedule_real(&alsa_event, self->queue, 0, &out_rt); + snd_seq_ev_schedule_real (&alsa_event, self->queue, 0, &out_rt); - err = snd_seq_event_output(self->seq, &alsa_event); + err = snd_seq_event_output (self->seq, &alsa_event); - debug_log("alsa_out: written %d bytes to %s at %d (%lld): %d %s\n", - jack_event.size, port->name, (int)frame_offset, out_time - info->alsa_time, err, err < 0 ? snd_strerror(err) : "bytes queued"); + debug_log ("alsa_out: written %d bytes to %s at %d (%lld): %d %s\n", + jack_event.size, port->name, (int)frame_offset, out_time - info->alsa_time, err, err < 0 ? snd_strerror (err) : "bytes queued"); } } static -void alsa_seqmidi_write(alsa_midi_t *m, jack_nframes_t nframes) +void alsa_seqmidi_write (alsa_midi_t *m, jack_nframes_t nframes) { - alsa_seqmidi_t *self = (alsa_seqmidi_t*) m; + alsa_seqmidi_t *self = (alsa_seqmidi_t*)m; struct process_info info; - if (!self->keep_walking) + if (!self->keep_walking) { return; + } - set_process_info(&info, self, PORT_OUTPUT, nframes); - jack_process(self, &info); - snd_seq_drain_output(self->seq); + set_process_info (&info, self, PORT_OUTPUT, nframes); + jack_process (self, &info); + snd_seq_drain_output (self->seq); } |