1
Fork 0

improved error handling in a2j_new; light coding style changes

This commit is contained in:
Nedko Arnaudov 2009-12-29 06:15:32 +02:00
parent dbf35b77c8
commit dc65fa3dd5
4 changed files with 145 additions and 77 deletions

View File

@ -101,16 +101,23 @@ a2j_sigint_handler(
}
static
void
bool
a2j_stream_init(
struct a2j * self,
int dir)
{
struct a2j_stream *str = &self->stream[dir];
str->new_ports = jack_ringbuffer_create(MAX_PORTS*sizeof(struct a2j_port*));
str->new_ports = jack_ringbuffer_create(MAX_PORTS * sizeof(struct a2j_port *));
if (str->new_ports == NULL)
{
return false;
}
snd_midi_event_new(MAX_EVENT_SIZE, &str->codec);
INIT_LIST_HEAD(&str->list);
return true;
}
static
@ -152,35 +159,61 @@ a2j_stream_close(
jack_ringbuffer_free(str->new_ports);
}
struct a2j *
a2j_new()
struct a2j * a2j_new(void)
{
int error;
extern void* a2j_alsa_input_thread (void*);
extern void* a2j_alsa_output_thread (void*);
void * thread_status;
struct a2j *self = calloc(1, sizeof(struct a2j));
a2j_debug("midi: new");
if (!self)
return NULL;
{
a2j_error("calloc() failed to allocate a2j struct");
goto fail;
}
self->port_add = jack_ringbuffer_create(2*MAX_PORTS*sizeof(snd_seq_addr_t));
self->port_del = jack_ringbuffer_create(2*MAX_PORTS*sizeof(struct a2j_port*));
self->port_add = jack_ringbuffer_create(2 * MAX_PORTS * sizeof(snd_seq_addr_t));
if (self->port_add == NULL)
{
goto free_self;
}
self->outbound_events = jack_ringbuffer_create(MAX_EVENT_SIZE*16*sizeof(struct a2j_delivery_event));
self->port_del = jack_ringbuffer_create(2 * MAX_PORTS * sizeof(struct a2j_port *));
if (self->port_del == NULL)
{
goto free_ringbuffer_add;
}
a2j_stream_init(self, A2J_PORT_CAPTURE);
a2j_stream_init(self, A2J_PORT_PLAYBACK);
self->outbound_events = jack_ringbuffer_create(MAX_EVENT_SIZE * 16 * sizeof(struct a2j_delivery_event));
if (self->outbound_events == NULL)
{
goto free_ringbuffer_del;
}
if (!a2j_stream_init(self, A2J_PORT_CAPTURE))
{
goto free_ringbuffer_outbound;
}
if (!a2j_stream_init(self, A2J_PORT_PLAYBACK))
{
goto close_capture_stream;
}
error = snd_seq_open(&self->seq, "hw", SND_SEQ_OPEN_DUPLEX, 0);
if (error < 0)
{
a2j_error("failed to open alsa seq");
free(self);
return NULL;
goto close_playback_stream;
}
error = snd_seq_set_client_name(self->seq, "a2jmidid");
if (error < 0)
{
a2j_error("snd_seq_set_client_name() failed");
goto close_seq_client;
}
snd_seq_set_client_name(self->seq, "a2jmidid");
self->port_id = snd_seq_create_simple_port(
self->seq,
"port",
@ -189,17 +222,45 @@ a2j_new()
|SND_SEQ_PORT_CAP_NO_EXPORT
#endif
,SND_SEQ_PORT_TYPE_APPLICATION);
if (self->port_id < 0)
{
a2j_error("snd_seq_create_simple_port() failed");
goto close_seq_client;
}
self->client_id = snd_seq_client_id(self->seq);
if (self->client_id < 0)
{
a2j_error("snd_seq_client_id() failed");
goto close_seq_client;
}
self->queue = snd_seq_alloc_queue(self->seq);
if (self->queue < 0)
{
a2j_error("snd_seq_alloc_queue() failed");
goto close_seq_client;
}
snd_seq_start_queue(self->seq, self->queue, 0);
a2j_stream_attach(self->stream + A2J_PORT_CAPTURE);
a2j_stream_attach(self->stream + A2J_PORT_PLAYBACK);
snd_seq_nonblock(self->seq, 1);
error = snd_seq_nonblock(self->seq, 1);
if (error < 0)
{
a2j_error("snd_seq_nonblock() failed");
goto close_seq_client;
}
error = snd_seq_connect_from(self->seq, self->port_id, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE);
if (error < 0)
{
a2j_error("snd_seq_connect_from() failed");
goto close_seq_client;
}
snd_seq_connect_from(self->seq, self->port_id, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE);
snd_seq_drop_input(self->seq);
a2j_add_ports(&self->stream[A2J_PORT_CAPTURE]);
@ -208,71 +269,86 @@ a2j_new()
self->jack_client = a2j_jack_client_create(self, A2J_JACK_CLIENT_NAME, g_a2j_jack_server_name);
if (self->jack_client == NULL)
{
free(self);
return NULL;
goto free_self;
}
if (sem_init (&self->io_semaphore, 0, 0) < 0) {
a2j_error ("can't create IO semaphore");
free (self);
return NULL;
if (sem_init(&self->io_semaphore, 0, 0) < 0)
{
a2j_error("can't create IO semaphore");
goto close_jack_client;
}
if (jack_activate(self->jack_client))
{
a2j_error("can't activate jack client");
error = jack_client_close(self->jack_client);
if (error != 0)
{
a2j_error("Cannot close jack client");
}
free(self);
return NULL;
goto sem_destroy;
}
a2j_add_existing_ports(self);
g_keep_alsa_walking = true;
if (pthread_create (&self->alsa_input_thread, NULL, a2j_alsa_input_thread, self) < 0) {
fprintf (stderr, "cannot start ALSA input thread\n");
free (self);
return NULL;
if (pthread_create(&self->alsa_input_thread, NULL, a2j_alsa_input_thread, self) < 0)
{
a2j_error("cannot start ALSA input thread");
goto sem_destroy;
}
if (pthread_create (&self->alsa_output_thread, NULL, a2j_alsa_output_thread, self) < 0) {
fprintf (stderr, "cannot start ALSA output thread\n");
free (self);
return NULL;
if (pthread_create(&self->alsa_output_thread, NULL, a2j_alsa_output_thread, self) < 0)
{
a2j_error("cannot start ALSA output thread");
goto join_input_thread;
}
return self;
join_input_thread:
g_keep_alsa_walking = false; /* tell alsa threads to stop */
snd_seq_disconnect_from(self->seq, self->port_id, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE);
pthread_join(self->alsa_input_thread, &thread_status);
sem_destroy:
sem_destroy(&self->io_semaphore);
close_jack_client:
error = jack_client_close(self->jack_client);
if (error != 0)
{
a2j_error("Cannot close jack client");
}
close_seq_client:
snd_seq_close(self->seq);
close_playback_stream:
a2j_stream_close(self, A2J_PORT_PLAYBACK);
close_capture_stream:
a2j_stream_close(self, A2J_PORT_CAPTURE);
free_ringbuffer_outbound:
jack_ringbuffer_free(self->outbound_events);
free_ringbuffer_del:
jack_ringbuffer_free(self->port_del);
free_ringbuffer_add:
jack_ringbuffer_free(self->port_add);
free_self:
free(self);
fail:
return NULL;
}
static
void
a2j_destroy(
struct a2j * self)
static void a2j_destroy(struct a2j * self)
{
int error;
void* alsa_status;
void * thread_status;
a2j_debug("midi: delete");
g_keep_alsa_walking = false; /* tell alsa threads to stop */
/* do something that we need to do anyway and will wake the input thread, then join */
snd_seq_disconnect_from(self->seq, self->port_id, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE);
pthread_join (self->alsa_input_thread, &alsa_status);
pthread_join(self->alsa_input_thread, &thread_status);
/* wake output thread and join, then destroy the semaphore */
sem_post (&self->io_semaphore);
pthread_join (self->alsa_output_thread, &alsa_status);
sem_destroy (&self->io_semaphore);
sem_post(&self->io_semaphore);
pthread_join(self->alsa_output_thread, &thread_status);
sem_destroy(&self->io_semaphore);
jack_ringbuffer_reset(self->port_add);
@ -293,14 +369,14 @@ a2j_destroy(
a2j_stream_close(self, A2J_PORT_PLAYBACK);
a2j_stream_close(self, A2J_PORT_CAPTURE);
jack_ringbuffer_free(self->outbound_events);
jack_ringbuffer_free(self->port_add);
jack_ringbuffer_free(self->port_del);
free(self);
}
bool
a2j_start()
bool a2j_start(void)
{
if (g_started)
{
@ -333,8 +409,7 @@ a2j_start()
return true;
}
bool
a2j_stop()
bool a2j_stop(void)
{
if (!g_started)
{

View File

@ -21,14 +21,12 @@
#ifndef A2JMIDID_H__A9B1D7AF_8702_48D4_899B_86B25FA4F54C__INCLUDED
#define A2JMIDID_H__A9B1D7AF_8702_48D4_899B_86B25FA4F54C__INCLUDED
bool
a2j_start();
bool a2j_start(void);
bool a2j_stop(void);
bool a2j_is_started(void);
bool
a2j_stop();
bool
a2j_is_started();
void * a2j_alsa_input_thread(void * arg);
void * a2j_alsa_output_thread(void * arg);
extern bool g_keep_walking;
extern bool g_keep_alsa_walking;

21
jack.c
View File

@ -40,14 +40,13 @@ static bool g_freewheeling = false;
* =================== Input/output port handling =========================
*/
void
a2j_add_ports(
struct a2j_stream * str)
void a2j_add_ports(struct a2j_stream * str)
{
struct a2j_port *port;
while (jack_ringbuffer_read(str->new_ports, (char*)&port, sizeof(port))) {
a2j_debug("jack: inserted port %s", port->name);
a2j_port_insert(str->port_hash, port);
struct a2j_port * port_ptr;
while (jack_ringbuffer_read(str->new_ports, (char *)&port_ptr, sizeof(port_ptr)))
{
a2j_debug("jack: inserted port %s", port_ptr->name);
a2j_port_insert(str->port_hash, port_ptr);
}
}
@ -301,8 +300,7 @@ time_sorter (struct a2j_delivery_event * a, struct a2j_delivery_event * b)
return 0;
}
void*
a2j_alsa_output_thread (void *arg)
void * a2j_alsa_output_thread(void * arg)
{
struct a2j * self = (struct a2j*) arg;
struct a2j_stream *str = &self->stream[A2J_PORT_PLAYBACK];
@ -422,8 +420,7 @@ a2j_alsa_output_thread (void *arg)
/* ALSA */
void*
a2j_alsa_input_thread (void* arg)
void * a2j_alsa_input_thread(void * arg)
{
struct a2j* self = (struct a2j* ) arg;
int npfd;
@ -471,7 +468,7 @@ a2j_jack_process_internal(
int nevents = 0;
stream_ptr = &self->stream[dir];
a2j_add_ports (stream_ptr);
a2j_add_ports(stream_ptr);
// process ports
for (i = 0 ; i < PORT_HASH_SIZE ; i++)

4
jack.h
View File

@ -22,9 +22,7 @@
#ifndef JACK_H__A455F430_D6DE_4978_AAE6_517E713FC305__INCLUDED
#define JACK_H__A455F430_D6DE_4978_AAE6_517E713FC305__INCLUDED
void
a2j_add_ports(
struct a2j_stream * str);
void a2j_add_ports(struct a2j_stream * str);
jack_client_t *
a2j_jack_client_create(