diff options
Diffstat (limited to 'src/audioOutputs/audioOutput_jack.c')
-rw-r--r-- | src/audioOutputs/audioOutput_jack.c | 359 |
1 files changed, 189 insertions, 170 deletions
diff --git a/src/audioOutputs/audioOutput_jack.c b/src/audioOutputs/audioOutput_jack.c index 1c9fee46c..c5b401b6c 100644 --- a/src/audioOutputs/audioOutput_jack.c +++ b/src/audioOutputs/audioOutput_jack.c @@ -32,64 +32,65 @@ #include <jack/types.h> #include <jack/ringbuffer.h> +/*#include "dmalloc.h"*/ + #define MIN(a, b) ((a) < (b) ? (a) : (b)) + +char *name = "mpd"; +char *output_ports[2] = {NULL, NULL}; int ringbuf_sz = 32768; -char *ports[2] = {NULL, NULL}; typedef struct _JackData { - jack_options_t options; jack_port_t *ports[2]; jack_client_t *client; - jack_default_audio_sample_t **in; jack_ringbuffer_t *ringbuffer[2]; + jack_default_audio_sample_t *samples1; + jack_default_audio_sample_t *samples2; int bps; int shutdown; - int nports; int our_xrun; } JackData; -JackData *jd = NULL; +/*JackData *jd = NULL;*/ -static JackData *newJackData (void) +static JackData *newJackData(void) { JackData *ret; - - ret = calloc (sizeof (JackData), 1); - ret->options = JackNullOption; + ret = xcalloc(sizeof(JackData), 1); return ret; } -static void disconnect_jack (JackData *jd) -{ - jack_deactivate (jd->client); - jack_client_close (jd->client); - - ERROR ("disconnect_jack (pid=%d)\n", getpid ()); -} - -static void jack_finishDriver (AudioOutput * audioOutput) +static void jack_finishDriver(AudioOutput * audioOutput) { JackData *jd = audioOutput->data; - disconnect_jack (jd); + jack_deactivate(jd->client); + jack_client_close(jd->client); + ERROR("disconnect_jack (pid=%d)\n", getpid ()); - free (jd); - free (ports[0]); - free (ports[1]); + if ( strcmp(name, "mpd") ) free(name); + if ( output_ports[0] ) free(output_ports[0]); + if ( output_ports[1] ) free(output_ports[1]); + + jack_ringbuffer_free(jd->ringbuffer[0]); + jack_ringbuffer_free(jd->ringbuffer[1]); + free(jd->samples1); + free(jd->samples2); + free(jd); } -static int srate (jack_nframes_t rate, void *data) +static int srate(jack_nframes_t rate, void *data) { JackData *jd = (JackData *) ((AudioOutput*) data)->data; AudioFormat *audioFormat = &(((AudioOutput*) data)->outAudioFormat); - audioFormat->sampleRate = (int) jack_get_sample_rate (jd->client); + audioFormat->sampleRate = (int)jack_get_sample_rate(jd->client); return 0; } -static int process (jack_nframes_t nframes, void *arg) +static int process(jack_nframes_t nframes, void *arg) { size_t i; JackData *jd = (JackData *) arg; @@ -99,19 +100,19 @@ static int process (jack_nframes_t nframes, void *arg) if ( nframes <= 0 ) return 0; - out[0] = jack_port_get_buffer (jd->ports[0], nframes); - out[1] = jack_port_get_buffer (jd->ports[1], nframes); + out[0] = jack_port_get_buffer(jd->ports[0], nframes); + out[1] = jack_port_get_buffer(jd->ports[1], nframes); - avail_data = jack_ringbuffer_read_space (jd->ringbuffer[1]); + avail_data = jack_ringbuffer_read_space(jd->ringbuffer[1]); if ( avail_data > 0 ) { - avail_frames = avail_data / sizeof (jack_default_audio_sample_t); + avail_frames = avail_data / sizeof(jack_default_audio_sample_t); if (avail_frames > nframes) { avail_frames = nframes; - avail_data = nframes * sizeof (jack_default_audio_sample_t); + avail_data = nframes * sizeof(jack_default_audio_sample_t); } - jack_ringbuffer_read (jd->ringbuffer[0], (char *)out[0], avail_data); - jack_ringbuffer_read (jd->ringbuffer[1], (char *)out[1], avail_data); + jack_ringbuffer_read(jd->ringbuffer[0], (char *)out[0], avail_data); + jack_ringbuffer_read(jd->ringbuffer[1], (char *)out[1], avail_data); if (avail_frames < nframes) { jd->our_xrun = 1; @@ -121,171 +122,182 @@ static int process (jack_nframes_t nframes, void *arg) } } else { //ERROR ("avail_data=%d, no play (pid=%d)!\n", avail_data, getpid ()); - - for (i = 0; i < nframes; i++) { - out[0][i] = 0.0; - out[1][i] = 0.0; - } + for (i = 0; i < nframes; i++) + out[0][i] = out[1][i] = 0.0; } + /*ERROR("process (pid=%d)\n", getpid());*/ return 0; } -static void shutdown_callback (void *arg) +static void shutdown_callback(void *arg) { JackData *jd = (JackData *) arg; jd->shutdown = 1; } -static void set_audioformat (AudioOutput *audioOutput) +static void set_audioformat(AudioOutput *audioOutput) { JackData *jd = audioOutput->data; AudioFormat *audioFormat = &audioOutput->outAudioFormat; - audioFormat->sampleRate = (int) jack_get_sample_rate (jd->client); + audioFormat->sampleRate = (int) jack_get_sample_rate(jd->client); ERROR ("samplerate = %d\n", audioFormat->sampleRate); - jd->nports = audioFormat->channels = 2; + audioFormat->channels = 2; audioFormat->bits = 16; jd->bps = audioFormat->channels * audioFormat->channels * audioFormat->sampleRate; } -static int connect_jack (AudioOutput *audioOutput) +static void error_callback(const char *msg) +{ + ERROR("jack: %s\n", msg); +} + +static int jack_initDriver(AudioOutput *audioOutput, ConfigParam *param) +{ + BlockParam *bp; + char *endptr; + int val; + char *cp = NULL; + + ERROR("jack_initDriver (pid=%d)\n", getpid()); + if ( ! param ) return 0; + + if ( (bp = getBlockParam(param, "ports")) ) { + cp = strdup(bp->value); + ERROR("output_ports=%s\n", cp); + output_ports[0] = strdup(strtok (cp, ",")); + output_ports[1] = strdup(strtok (NULL, ",")); + free(cp); + } + + if ( (bp = getBlockParam(param, "ringbuffer_size")) ) { + errno = 0; + val = strtol(bp->value, &endptr, 10); + + if ( errno == 0 && endptr != bp->value) { + ringbuf_sz = val < 32768 ? 32768 : val; + ERROR("ringbuffer_size=%d\n", ringbuf_sz); + } else { + ERROR("%s is not a number; ringbuf_size=%d\n", + bp->value, ringbuf_sz); + } + } + + if ( (bp = getBlockParam(param, "name")) + && (strcmp(bp->value, "mpd") != 0) ) { + name = strdup(bp->value); + ERROR("name=%s\n", name); + } + + return 0; +} + +static int jack_testDefault(void) +{ + return 0; +} + +static int connect_jack(AudioOutput *audioOutput) { JackData *jd = audioOutput->data; const char **jports; + char *port_name; - if ( (jd->client = jack_client_new ("mpd")) == NULL ) { - ERROR ("jack server not running?\n"); + if ( (jd->client = jack_client_new(name)) == NULL ) { + ERROR("jack server not running?\n"); return -1; } - jd->ringbuffer[0] = jack_ringbuffer_create (ringbuf_sz); - jd->ringbuffer[1] = jack_ringbuffer_create (ringbuf_sz); + jack_set_error_function(error_callback); + jack_set_process_callback(jd->client, process, (void *)jd); + jack_set_sample_rate_callback(jd->client, (JackProcessCallback)srate, + (void *)audioOutput); + jack_on_shutdown(jd->client, shutdown_callback, (void *)jd); - jack_set_process_callback (jd->client, process, (void *)jd); - jack_set_sample_rate_callback (jd->client, (JackProcessCallback)srate, - (void *)audioOutput); - jack_on_shutdown (jd->client, shutdown_callback, (void *)jd); - - if ( jack_activate (jd->client) ) { - ERROR ("cannot activate client"); - jack_ringbuffer_free (jd->ringbuffer[0]); - jack_ringbuffer_free (jd->ringbuffer[1]); + if ( jack_activate(jd->client) ) { + ERROR("cannot activate client"); return -1; } - jd->ports[0] = jack_port_register (jd->client, "left", - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsOutput, 0); + jd->ports[0] = jack_port_register(jd->client, "left", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsOutput, 0); if ( !jd->ports[0] ) { - ERROR ("Cannot register output port.\n"); - jack_ringbuffer_free (jd->ringbuffer[0]); - jack_ringbuffer_free (jd->ringbuffer[1]); + ERROR("Cannot register left output port.\n"); return -1; } - jd->ports[1] = jack_port_register (jd->client, "right", - JACK_DEFAULT_AUDIO_TYPE, - JackPortIsOutput, 0); + jd->ports[1] = jack_port_register(jd->client, "right", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsOutput, 0); if ( !jd->ports[1] ) { - ERROR ("Cannot register output port.\n"); - jack_ringbuffer_free (jd->ringbuffer[0]); - jack_ringbuffer_free (jd->ringbuffer[1]); + ERROR("Cannot register right output port.\n"); return -1; } - memset (jd->ringbuffer[0]->buf, 0, jd->ringbuffer[0]->size); - memset (jd->ringbuffer[1]->buf, 0, jd->ringbuffer[1]->size); - /* hay que buscar que hay */ - if ( !ports[1] && (jports = jack_get_ports (jd->client, NULL, NULL, - JackPortIsPhysical| - JackPortIsInput)) ) { - ports[0] = (char *) jports[0]; - ports[1] = (char *) ( jports[1] ? jports[1] : jports[0] ); - ERROR ("jports: %s %s\n", ports[0], ports[1]); - free (jports); + if ( !output_ports[1] && (jports = jack_get_ports(jd->client, NULL, NULL, + JackPortIsPhysical| + JackPortIsInput)) ) { + output_ports[0] = jports[0]; + output_ports[1] = jports[1] ? jports[1] : jports[0]; + ERROR("output_ports: %s %s\n", output_ports[0], output_ports[1]); + free(jports); } - if ( ports[1] ) { - if ( (jack_connect (jd->client, "mpd:left", ports[0])) != 0 ) { - ERROR ("%s is not a valid Jack Client / Port ", ports[0]); - jack_ringbuffer_free (jd->ringbuffer[0]); - jack_ringbuffer_free (jd->ringbuffer[1]); + if ( output_ports[1] ) { + jd->ringbuffer[0] = jack_ringbuffer_create(ringbuf_sz); + jd->ringbuffer[1] = jack_ringbuffer_create(ringbuf_sz); + memset(jd->ringbuffer[0]->buf, 0, jd->ringbuffer[0]->size); + memset(jd->ringbuffer[1]->buf, 0, jd->ringbuffer[1]->size); + + port_name = xmalloc(sizeof(char)*(7+strlen(name))); + + sprintf(port_name, "%s:left", name); + if ( (jack_connect(jd->client, port_name, output_ports[0])) != 0 ) { + ERROR("%s is not a valid Jack Client / Port ", output_ports[0]); + jack_ringbuffer_free(jd->ringbuffer[0]); + jack_ringbuffer_free(jd->ringbuffer[1]); + free(port_name); return -1; } - if ( (jack_connect (jd->client, "mpd:right", ports[1])) != 0 ) { - ERROR ("%s is not a valid Jack Client / Port ", ports[1]); - jack_ringbuffer_free (jd->ringbuffer[0]); - jack_ringbuffer_free (jd->ringbuffer[1]); + sprintf(port_name, "%s:right", name); + if ( (jack_connect(jd->client, port_name, output_ports[1])) != 0 ) { + ERROR("%s is not a valid Jack Client / Port ", output_ports[1]); + jack_ringbuffer_free(jd->ringbuffer[0]); + jack_ringbuffer_free(jd->ringbuffer[1]); + free(port_name); return -1; } + free(port_name); } - ERROR ("connect_jack (pid=%d)\n", getpid ()); + ERROR("connect_jack (pid=%d)\n", getpid()); return 1; } -static int jack_initDriver (AudioOutput *audioOutput, ConfigParam *param) +static int jack_openDevice(AudioOutput *audioOutput) { - BlockParam *bp; - char *endptr; - int val; - char *cp = NULL; - - if ( param ) { - bp = getBlockParam (param, "ports"); - if ( bp ) { - cp = strdup (bp->value); - ports[0] = strdup (strtok (cp, " ,")); - ports[1] = strdup (strtok (NULL, " ,")); - free (cp); - } - - bp = getBlockParam (param, "ringbuffer_size"); - if ( bp ) { - errno = 0; - val = strtol (bp->value, &endptr, 10); - - if ( errno == 0 && endptr != bp->value) { - ringbuf_sz = val; - ERROR ("ringbuffer_size=%d\n", ringbuf_sz); - } else { - ERROR ("%s is not a number; ringbuf_size=%d\n", - bp->value, ringbuf_sz); - } - } - } - - ERROR ("jack_initDriver (pid=%d)\n", getpid ()); - - return 0; - -} - -static int jack_testDefault(void) -{ - return 0; -} + JackData *jd = audioOutput->data; -static int jack_openDevice (AudioOutput *audioOutput) -{ if ( !jd ) { - jd = newJackData (); + ERROR("connect!\n"); + jd = newJackData(); audioOutput->data = jd; - if ( !connect_jack (audioOutput) ) { - free (jd); + if ( !connect_jack(audioOutput) ) { + jack_finishDriver(audioOutput); return -1; - } + } } - set_audioformat (audioOutput); + set_audioformat(audioOutput); audioOutput->open = 1; - ERROR ("jack_openDevice (pid=%d)!\n", getpid ()); + ERROR("jack_openDevice (pid=%d)!\n", getpid ()); return 0; } @@ -293,7 +305,7 @@ static int jack_openDevice (AudioOutput *audioOutput) static void jack_closeDevice(AudioOutput * audioOutput) { audioOutput->open = 0; - ERROR ("jack_closeDevice (pid=%d)!\n", getpid ()); + ERROR("jack_closeDevice (pid=%d)!\n", getpid()); } static void jack_dropBufferedAudio (AudioOutput * audioOutput) @@ -304,53 +316,60 @@ static void jack_dropBufferedAudio (AudioOutput * audioOutput) static int jack_playAudio(AudioOutput * audioOutput, char *buff, int size) { JackData *jd = audioOutput->data; - size_t remain = size; - size_t pos = 0; + size_t space; + char *samples1; + char *samples2; + int i; + short *buffer = (short *) buff; if ( jd->shutdown ) { - ERROR ("Refusing to play, because there is no client thread.\n"); + ERROR("Refusing to play, because there is no client thread.\n"); return 0; } if ( jd->our_xrun ) { - ERROR ("xrun\n"); + ERROR("xrun\n"); jd->our_xrun = 0; } - while (remain && !jd->shutdown) { - size_t space; - - if ( (space = jack_ringbuffer_write_space (jd->ringbuffer[0])) - > sizeof (jack_default_audio_sample_t) ) { - size_t to_write; - - to_write = MIN (space, remain); - remain -= to_write; - to_write /= 4; - //ERROR ("\t\tto_write=%d remain=%d (%d)\n", to_write, remain, to_write * 2 * 2); - while (to_write--) { - jack_default_audio_sample_t sample; - - sample = *(short *)(buff + pos); - sample /= 32768; - pos += 2; - jack_ringbuffer_write (jd->ringbuffer[0], - (char *)&sample, - sizeof (sample)); - - - sample = *(short *)(buff + pos); - sample /= 32768; - pos += 2; - jack_ringbuffer_write (jd->ringbuffer[1], - (char *)&sample, - sizeof (sample)); - } + /*ERROR("jack_playAudio: size=%d\n", size/4);*/ + /*ERROR("jack_playAudio - INICIO\n");*/ + + if ( ! jd->samples1 ) { + ERROR("jd->samples1=xmalloc\n"); + jd->samples1 = (jack_default_audio_sample_t *)xmalloc(size); + } + if ( ! jd->samples2 ) { + ERROR("jd->samples2=xmalloc\n"); + jd->samples2 = (jack_default_audio_sample_t *)xmalloc(size); + } + + /* primero convierto todo el buffer al formato que usa jack */ + for (i=0; i<size/4; i++) { + *(jd->samples1 + i) = (jack_default_audio_sample_t) *(buffer++) / 32768; + *(jd->samples2 + i) = (jack_default_audio_sample_t) *(buffer++) / 32768; + } + + samples1=(char *)jd->samples1; + samples2=(char *)jd->samples2; + while ( size && !jd->shutdown ) { + if ( (space = jack_ringbuffer_write_space(jd->ringbuffer[0])) > + sizeof(jack_default_audio_sample_t) ) { + /*ERROR("\t size=%d space=%d\n", size, space);*/ + space = MIN(space, size); + jack_ringbuffer_write(jd->ringbuffer[0],samples1,space); + jack_ringbuffer_write(jd->ringbuffer[1],samples2,space); + size -= space; + samples1 += space; + samples2 += space; } else { - usleep (ringbuf_sz / (float)(jd->bps) * 100000.0); + /*ERROR("\t space=%d\n", space);*/ + usleep(ringbuf_sz/(float)(jd->bps) * 100000.0); } } + /*ERROR("jack_playAudio - FIN\n");*/ + return 0; } |