aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2008-10-24 16:55:51 +0200
committerMax Kellermann <max@duempel.org>2008-10-24 16:55:51 +0200
commit0a6704420b7caace3f4eca81ca1862ea5803f6d2 (patch)
tree5b0fcd012b3278bebb1f26c787e37ed671ba2cde /src
parent4ecdaabbb095e2e0cb421308089a190c518b4b35 (diff)
downloadmpd-0a6704420b7caace3f4eca81ca1862ea5803f6d2.tar.gz
mpd-0a6704420b7caace3f4eca81ca1862ea5803f6d2.tar.xz
mpd-0a6704420b7caace3f4eca81ca1862ea5803f6d2.zip
jack: lockless data transfer to jack thread
The JACK documentation postulates that the process() callback must not block, therefore locking is forbidden. Anyway, the old code was racy. Remove all locks, and don't wait for more data to become available - just send to the port what is already in the buffer.
Diffstat (limited to 'src')
-rw-r--r--src/audioOutputs/audioOutput_jack.c62
1 files changed, 15 insertions, 47 deletions
diff --git a/src/audioOutputs/audioOutput_jack.c b/src/audioOutputs/audioOutput_jack.c
index e67554cc1..8c843549f 100644
--- a/src/audioOutputs/audioOutput_jack.c
+++ b/src/audioOutputs/audioOutput_jack.c
@@ -41,10 +41,6 @@ typedef struct _JackData {
/* for srate() only */
struct audio_format *audio_format;
- /* locks */
- pthread_mutex_t play_audio_lock;
- pthread_cond_t play_audio;
-
/* jack library stuff */
jack_port_t *ports[2];
jack_client_t *client;
@@ -64,9 +60,6 @@ static JackData *newJackData(void)
ret->name = "mpd";
ret->ringbuf_sz = 32768;
- pthread_mutex_init(&ret->play_audio_lock, NULL);
- pthread_cond_init(&ret->play_audio, NULL);
-
return ret;
}
@@ -89,9 +82,6 @@ static void freeJackClient(JackData *jd)
jack_ringbuffer_free(jd->ringbuffer[1]);
jd->ringbuffer[1] = NULL;
}
-
- pthread_mutex_destroy(&jd->play_audio_lock);
- pthread_cond_destroy(&jd->play_audio);
}
static void freeJackData(JackData *jd)
@@ -133,50 +123,29 @@ static int srate(mpd_unused jack_nframes_t rate, void *data)
static int process(jack_nframes_t nframes, void *arg)
{
- size_t i;
JackData *jd = (JackData *) arg;
- jack_default_audio_sample_t *out[2];
+ jack_default_audio_sample_t *out;
size_t avail_data, avail_frames;
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);
+ for (unsigned i = 0; i < 2; ++i) {
+ avail_data = jack_ringbuffer_read_space(jd->ringbuffer[i]);
+ if (avail_data > nframes * sample_size)
+ avail_data = nframes * sample_size;
- while (nframes) {
- avail_data = jack_ringbuffer_read_space(jd->ringbuffer[1]);
-
- if ( avail_data > 0 ) {
- avail_frames = avail_data / sample_size;
-
- if (avail_frames > nframes) {
- avail_frames = nframes;
- avail_data = nframes*sample_size;
- }
+ avail_frames = avail_data / sample_size;
- jack_ringbuffer_read(jd->ringbuffer[0], (char *)out[0],
- avail_data);
- jack_ringbuffer_read(jd->ringbuffer[1], (char *)out[1],
- avail_data);
+ out = jack_port_get_buffer(jd->ports[i], nframes);
+ jack_ringbuffer_read(jd->ringbuffer[i],
+ (char *)out, avail_data);
- nframes -= avail_frames;
- out[0] += avail_data;
- out[1] += avail_data;
- } else {
- for (i = 0; i < nframes; i++)
- out[0][i] = out[1][i] = 0.0;
- nframes = 0;
- }
-
- if (pthread_mutex_trylock (&jd->play_audio_lock) == 0) {
- pthread_cond_signal (&jd->play_audio);
- pthread_mutex_unlock (&jd->play_audio_lock);
- }
+ while (avail_frames < nframes)
+ /* ringbuffer underrun, fill with silence */
+ out[avail_frames++] = 0.0;
}
-
- /*DEBUG("process (pid=%d)\n", getpid());*/
return 0;
}
@@ -426,10 +395,9 @@ static int jack_playAudio(void *data,
sample_size);
}
} else {
- pthread_mutex_lock(&jd->play_audio_lock);
- pthread_cond_wait(&jd->play_audio,
- &jd->play_audio_lock);
- pthread_mutex_unlock(&jd->play_audio_lock);
+ /* XXX do something more intelligent to
+ synchronize */
+ my_usleep(10000);
}
}