summaryrefslogtreecommitdiffstats
path: root/polyp/pcm_polyp.c
diff options
context:
space:
mode:
Diffstat (limited to 'polyp/pcm_polyp.c')
-rw-r--r--polyp/pcm_polyp.c235
1 files changed, 128 insertions, 107 deletions
diff --git a/polyp/pcm_polyp.c b/polyp/pcm_polyp.c
index 032ccbb..44ae35e 100644
--- a/polyp/pcm_polyp.c
+++ b/polyp/pcm_polyp.c
@@ -21,8 +21,6 @@
#include <stdio.h>
#include <sys/poll.h>
-#include <pthread.h>
-
#include <alsa/asoundlib.h>
#include <alsa/pcm_external.h>
@@ -46,8 +44,6 @@ typedef struct snd_pcm_polyp {
pa_sample_spec ss;
unsigned int frame_size;
pa_buffer_attr buffer_attr;
-
- pthread_mutex_t mutex;
} snd_pcm_polyp_t;
static void update_ptr(snd_pcm_polyp_t *pcm)
@@ -74,20 +70,17 @@ static int polyp_start(snd_pcm_ioplug_t *io)
int err = 0;
assert(pcm);
+ assert(pcm->p);
- pthread_mutex_lock(&pcm->mutex);
-
- assert(pcm->p && pcm->stream);
+ pa_threaded_mainloop_lock(pcm->p->mainloop);
- err = polyp_finish_poll(pcm->p);
- if (err < 0)
- goto finish;
+ assert(pcm->stream);
err = polyp_check_connection(pcm->p);
if (err < 0)
goto finish;
- o = pa_stream_cork(pcm->stream, 0, NULL, NULL);
+ o = pa_stream_cork(pcm->stream, 0, polyp_stream_success_cb, pcm->p);
assert(o);
err = polyp_wait_operation(pcm->p, o);
@@ -100,7 +93,7 @@ static int polyp_start(snd_pcm_ioplug_t *io)
}
finish:
- pthread_mutex_unlock(&pcm->mutex);
+ pa_threaded_mainloop_unlock(pcm->p->mainloop);
return err;
}
@@ -112,20 +105,17 @@ static int polyp_stop(snd_pcm_ioplug_t *io)
int err = 0;
assert(pcm);
+ assert(pcm->p);
- pthread_mutex_lock(&pcm->mutex);
-
- assert(pcm->p && pcm->stream);
+ pa_threaded_mainloop_lock(pcm->p->mainloop);
- err = polyp_finish_poll(pcm->p);
- if (err < 0)
- goto finish;
+ assert(pcm->stream);
err = polyp_check_connection(pcm->p);
if (err < 0)
goto finish;
- o = pa_stream_flush(pcm->stream, NULL, NULL);
+ o = pa_stream_flush(pcm->stream, polyp_stream_success_cb, pcm->p);
assert(o);
err = polyp_wait_operation(pcm->p, o);
@@ -137,7 +127,7 @@ static int polyp_stop(snd_pcm_ioplug_t *io)
goto finish;
}
- o = pa_stream_cork(pcm->stream, 1, NULL, NULL);
+ o = pa_stream_cork(pcm->stream, 1, polyp_stream_success_cb, pcm->p);
assert(o);
err = polyp_wait_operation(pcm->p, o);
@@ -150,7 +140,7 @@ static int polyp_stop(snd_pcm_ioplug_t *io)
}
finish:
- pthread_mutex_unlock(&pcm->mutex);
+ pa_threaded_mainloop_unlock(pcm->p->mainloop);
return err;
}
@@ -162,20 +152,17 @@ int polyp_drain(snd_pcm_ioplug_t *io)
int err = 0;
assert(pcm);
+ assert(pcm->p);
- pthread_mutex_lock(&pcm->mutex);
-
- assert(pcm->p && pcm->stream);
+ pa_threaded_mainloop_lock(pcm->p->mainloop);
- err = polyp_finish_poll(pcm->p);
- if (err < 0)
- goto finish;
+ assert(pcm->stream);
err = polyp_check_connection(pcm->p);
if (err < 0)
goto finish;
- o = pa_stream_drain(pcm->stream, NULL, NULL);
+ o = pa_stream_drain(pcm->stream, polyp_stream_success_cb, pcm->p);
assert(o);
err = polyp_wait_operation(pcm->p, o);
@@ -188,7 +175,7 @@ int polyp_drain(snd_pcm_ioplug_t *io)
}
finish:
- pthread_mutex_unlock(&pcm->mutex);
+ pa_threaded_mainloop_unlock(pcm->p->mainloop);
return err;
}
@@ -199,14 +186,11 @@ static snd_pcm_sframes_t polyp_pointer(snd_pcm_ioplug_t *io)
int err = 0;
assert(pcm);
+ assert(pcm->p);
- pthread_mutex_lock(&pcm->mutex);
-
- assert(pcm->p && pcm->stream);
+ pa_threaded_mainloop_lock(pcm->p->mainloop);
- err = polyp_finish_poll(pcm->p);
- if (err < 0)
- goto finish;
+ assert(pcm->stream);
err = polyp_check_connection(pcm->p);
if (err < 0)
@@ -214,14 +198,41 @@ static snd_pcm_sframes_t polyp_pointer(snd_pcm_ioplug_t *io)
update_ptr(pcm);
- err = polyp_start_poll(pcm->p);
+ err = snd_pcm_bytes_to_frames(io->pcm, pcm->ptr);
+
+finish:
+ pa_threaded_mainloop_unlock(pcm->p->mainloop);
+
+ return err;
+}
+
+static int polyp_delay(snd_pcm_ioplug_t *io,
+ snd_pcm_sframes_t *delayp)
+{
+ snd_pcm_polyp_t *pcm = io->private_data;
+ int err = 0;
+ pa_usec_t lat;
+
+ assert(pcm);
+ assert(pcm->p);
+
+ pa_threaded_mainloop_lock(pcm->p->mainloop);
+
+ assert(pcm->stream);
+
+ err = polyp_check_connection(pcm->p);
if (err < 0)
goto finish;
- err = snd_pcm_bytes_to_frames(io->pcm, pcm->ptr);
+ if (pa_stream_get_latency(pcm->stream, &lat, NULL)) {
+ err = -EIO;
+ goto finish;
+ }
+
+ *delayp = snd_pcm_bytes_to_frames(io->pcm, pa_usec_to_bytes(lat, &pcm->ss));
finish:
- pthread_mutex_unlock(&pcm->mutex);
+ pa_threaded_mainloop_unlock(pcm->p->mainloop);
return err;
}
@@ -236,14 +247,11 @@ static snd_pcm_sframes_t polyp_write(snd_pcm_ioplug_t *io,
int err = 0;
assert(pcm);
+ assert(pcm->p);
- pthread_mutex_lock(&pcm->mutex);
-
- assert(pcm->p && pcm->stream);
+ pa_threaded_mainloop_lock(pcm->p->mainloop);
- err = polyp_finish_poll(pcm->p);
- if (err < 0)
- goto finish;
+ assert(pcm->stream);
err = polyp_check_connection(pcm->p);
if (err < 0)
@@ -261,10 +269,13 @@ static snd_pcm_sframes_t polyp_write(snd_pcm_ioplug_t *io,
/* Make sure the buffer pointer is in sync */
update_ptr(pcm);
+ if (pcm->last_size < pcm->buffer_attr.minreq)
+ polyp_poll_deactivate(pcm->p);
+
err = size;
finish:
- pthread_mutex_unlock(&pcm->mutex);
+ pa_threaded_mainloop_unlock(pcm->p->mainloop);
return err;
}
@@ -280,14 +291,11 @@ static snd_pcm_sframes_t polyp_read(snd_pcm_ioplug_t *io,
int err = 0;
assert(pcm);
+ assert(pcm->p);
- pthread_mutex_lock(&pcm->mutex);
-
- assert(pcm->p && pcm->stream);
+ pa_threaded_mainloop_lock(pcm->p->mainloop);
- err = polyp_finish_poll(pcm->p);
- if (err < 0)
- goto finish;
+ assert(pcm->stream);
err = polyp_check_connection(pcm->p);
if (err < 0)
@@ -325,28 +333,40 @@ static snd_pcm_sframes_t polyp_read(snd_pcm_ioplug_t *io,
/* Make sure the buffer pointer is in sync */
update_ptr(pcm);
+ if (pcm->last_size < pcm->buffer_attr.minreq)
+ polyp_poll_deactivate(pcm->p);
+
err = size - (remain_size / pcm->frame_size);
finish:
- pthread_mutex_unlock(&pcm->mutex);
+ pa_threaded_mainloop_unlock(pcm->p->mainloop);
return err;
}
+static void stream_request_cb(pa_stream *p, size_t length, void *userdata)
+{
+ snd_pcm_polyp_t *pcm = userdata;
+
+ assert(pcm);
+ assert(pcm->p);
+
+ polyp_poll_activate(pcm->p);
+}
+
static int polyp_pcm_poll_descriptors_count(snd_pcm_ioplug_t *io)
{
snd_pcm_polyp_t *pcm = io->private_data;
int count;
assert(pcm);
-
- pthread_mutex_lock(&pcm->mutex);
-
assert(pcm->p);
+ pa_threaded_mainloop_lock(pcm->p->mainloop);
+
count = polyp_poll_descriptors_count(pcm->p);
- pthread_mutex_unlock(&pcm->mutex);
+ pa_threaded_mainloop_unlock(pcm->p->mainloop);
return count;
}
@@ -357,14 +377,13 @@ static int polyp_pcm_poll_descriptors(snd_pcm_ioplug_t *io, struct pollfd *pfd,
int err;
assert(pcm);
-
- pthread_mutex_lock(&pcm->mutex);
-
assert(pcm->p);
+ pa_threaded_mainloop_lock(pcm->p->mainloop);
+
err = polyp_poll_descriptors(pcm->p, pfd, space);
- pthread_mutex_unlock(&pcm->mutex);
+ pa_threaded_mainloop_unlock(pcm->p->mainloop);
return err;
}
@@ -375,11 +394,10 @@ static int polyp_pcm_poll_revents(snd_pcm_ioplug_t *io, struct pollfd *pfd, unsi
int err = 0;
assert(pcm);
-
- pthread_mutex_lock(&pcm->mutex);
-
assert(pcm->p);
+ pa_threaded_mainloop_lock(pcm->p->mainloop);
+
err = polyp_poll_revents(pcm->p, pfd, nfds, revents);
if (err < 0)
goto finish;
@@ -402,25 +420,21 @@ static int polyp_pcm_poll_revents(snd_pcm_ioplug_t *io, struct pollfd *pfd, unsi
}
finish:
- pthread_mutex_unlock(&pcm->mutex);
+ pa_threaded_mainloop_unlock(pcm->p->mainloop);
return err;
}
static int polyp_prepare(snd_pcm_ioplug_t *io)
{
+ pa_channel_map map;
snd_pcm_polyp_t *pcm = io->private_data;
int err = 0;
assert(pcm);
-
- pthread_mutex_lock(&pcm->mutex);
-
assert(pcm->p);
- err = polyp_finish_poll(pcm->p);
- if (err < 0)
- goto finish;
+ pa_threaded_mainloop_lock(pcm->p->mainloop);
if (pcm->stream) {
pa_stream_disconnect(pcm->stream);
@@ -436,15 +450,24 @@ static int polyp_prepare(snd_pcm_ioplug_t *io)
assert(pcm->stream == NULL);
if (io->stream == SND_PCM_STREAM_PLAYBACK)
- pcm->stream = pa_stream_new(pcm->p->context, "ALSA Playback", &pcm->ss, NULL);
+ pcm->stream = pa_stream_new(pcm->p->context, "ALSA Playback", &pcm->ss,
+ pa_channel_map_init_auto(&map, pcm->ss.channels, PA_CHANNEL_MAP_ALSA));
else
- pcm->stream = pa_stream_new(pcm->p->context, "ALSA Capture", &pcm->ss, NULL);
+ pcm->stream = pa_stream_new(pcm->p->context, "ALSA Capture", &pcm->ss,
+ pa_channel_map_init_auto(&map, pcm->ss.channels, PA_CHANNEL_MAP_ALSA));
assert(pcm->stream);
- if (io->stream == SND_PCM_STREAM_PLAYBACK)
- pa_stream_connect_playback(pcm->stream, pcm->device, &pcm->buffer_attr, 0, NULL, NULL);
- else
- pa_stream_connect_record(pcm->stream, pcm->device, &pcm->buffer_attr, 0);
+ pa_stream_set_state_callback(pcm->stream, polyp_stream_state_cb, pcm->p);
+
+ if (io->stream == SND_PCM_STREAM_PLAYBACK) {
+ pa_stream_set_write_callback(pcm->stream, stream_request_cb, pcm);
+ pa_stream_connect_playback(pcm->stream, pcm->device, &pcm->buffer_attr,
+ PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING, NULL, NULL);
+ } else {
+ pa_stream_set_read_callback(pcm->stream, stream_request_cb, pcm);
+ pa_stream_connect_record(pcm->stream, pcm->device, &pcm->buffer_attr,
+ PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING);
+ }
err = polyp_wait_stream_state(pcm->p, pcm->stream, PA_STREAM_READY);
if (err < 0) {
@@ -459,7 +482,7 @@ static int polyp_prepare(snd_pcm_ioplug_t *io)
pcm->offset = 0;
finish:
- pthread_mutex_unlock(&pcm->mutex);
+ pa_threaded_mainloop_unlock(pcm->p->mainloop);
return err;
}
@@ -470,10 +493,11 @@ static int polyp_hw_params(snd_pcm_ioplug_t *io, snd_pcm_hw_params_t *params)
int err = 0;
assert(pcm);
+ assert(pcm->p);
- pthread_mutex_lock(&pcm->mutex);
+ pa_threaded_mainloop_lock(pcm->p->mainloop);
- assert(pcm->p && !pcm->stream);
+ assert(!pcm->stream);
pcm->frame_size = (snd_pcm_format_physical_width(io->format) * io->channels) / 8;
@@ -516,7 +540,7 @@ static int polyp_hw_params(snd_pcm_ioplug_t *io, snd_pcm_hw_params_t *params)
pcm->buffer_attr.fragsize = io->period_size * pcm->frame_size;
finish:
- pthread_mutex_unlock(&pcm->mutex);
+ pa_threaded_mainloop_unlock(pcm->p->mainloop);
return err;
}
@@ -527,51 +551,55 @@ static int polyp_close(snd_pcm_ioplug_t *io)
assert(pcm);
+ pa_threaded_mainloop_lock(pcm->p->mainloop);
+
if (pcm->stream) {
pa_stream_disconnect(pcm->stream);
polyp_wait_stream_state(pcm->p, pcm->stream, PA_STREAM_TERMINATED);
pa_stream_unref(pcm->stream);
}
+ pa_threaded_mainloop_unlock(pcm->p->mainloop);
+
if (pcm->p)
polyp_free(pcm->p);
if (pcm->device)
free(pcm->device);
- pthread_mutex_destroy(&pcm->mutex);
-
free(pcm);
return 0;
}
static snd_pcm_ioplug_callback_t polyp_playback_callback = {
- .start = polyp_start,
- .stop = polyp_stop,
+ .start = polyp_start,
+ .stop = polyp_stop,
.drain = polyp_drain,
- .pointer = polyp_pointer,
- .transfer = polyp_write,
+ .pointer = polyp_pointer,
+ .transfer = polyp_write,
+ .delay = polyp_delay,
.poll_descriptors_count = polyp_pcm_poll_descriptors_count,
.poll_descriptors = polyp_pcm_poll_descriptors,
.poll_revents = polyp_pcm_poll_revents,
- .prepare = polyp_prepare,
- .hw_params = polyp_hw_params,
- .close = polyp_close,
+ .prepare = polyp_prepare,
+ .hw_params = polyp_hw_params,
+ .close = polyp_close,
};
static snd_pcm_ioplug_callback_t polyp_capture_callback = {
- .start = polyp_start,
- .stop = polyp_stop,
- .pointer = polyp_pointer,
- .transfer = polyp_read,
+ .start = polyp_start,
+ .stop = polyp_stop,
+ .pointer = polyp_pointer,
+ .transfer = polyp_read,
+ .delay = polyp_delay,
.poll_descriptors_count = polyp_pcm_poll_descriptors_count,
.poll_descriptors = polyp_pcm_poll_descriptors,
.poll_revents = polyp_pcm_poll_revents,
- .prepare = polyp_prepare,
- .hw_params = polyp_hw_params,
- .close = polyp_close,
+ .prepare = polyp_prepare,
+ .hw_params = polyp_hw_params,
+ .close = polyp_close,
};
@@ -645,7 +673,6 @@ SND_PCM_PLUGIN_DEFINE_FUNC(polyp)
const char *device = NULL;
int err;
snd_pcm_polyp_t *pcm;
- pthread_mutexattr_t mutexattr;
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
@@ -678,21 +705,15 @@ SND_PCM_PLUGIN_DEFINE_FUNC(polyp)
pcm->device = strdup(device);
pcm->p = polyp_new();
- assert(pcm->p);
-
- err = polyp_connect(pcm->p, server);
- if (err < 0)
+ if (!pcm->p) {
+ err = -EIO;
goto error;
+ }
- err = polyp_start_thread(pcm->p);
+ err = polyp_connect(pcm->p, server);
if (err < 0)
goto error;
- pthread_mutexattr_init(&mutexattr);
- pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init(&pcm->mutex, &mutexattr);
- pthread_mutexattr_destroy(&mutexattr);
-
pcm->io.version = SND_PCM_IOPLUG_VERSION;
pcm->io.name = "ALSA <-> Polypaudio PCM I/O Plugin";
pcm->io.poll_fd = -1;