X-Git-Url: https://code.delx.au/pulseaudio/blobdiff_plain/34fe8bd893ed9c7531bc4898b934ef9d4cdf3e68..c005bd466651d8720aef3198d73bc0a3d459f953:/polyp/module-alsa-sink.c diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index 0c9d77b8..e319f6c1 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -38,6 +38,13 @@ #include "sample-util.h" #include "alsa-util.h" #include "xmalloc.h" +#include "log.h" +#include "module-alsa-sink-symdef.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("ALSA Sink") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("sink_name= device= format= channels= rate= fragments= fragment_size=") struct userdata { snd_pcm_t *pcm_handle; @@ -73,10 +80,10 @@ static void update_usage(struct userdata *u) { static void xrun_recovery(struct userdata *u) { assert(u); - fprintf(stderr, "*** ALSA-XRUN (playback) ***\n"); + pa_log(__FILE__": *** ALSA-XRUN (playback) ***\n"); if (snd_pcm_prepare(u->pcm_handle) < 0) - fprintf(stderr, "snd_pcm_prepare() failed\n"); + pa_log(__FILE__": snd_pcm_prepare() failed\n"); } static void do_write(struct userdata *u) { @@ -108,7 +115,7 @@ static void do_write(struct userdata *u) { continue; } - fprintf(stderr, "snd_pcm_writei() failed\n"); + pa_log(__FILE__": snd_pcm_writei() failed\n"); return; } @@ -138,13 +145,14 @@ static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, do_write(u); } -static uint32_t sink_get_latency_cb(struct pa_sink *s) { +static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { + pa_usec_t r = 0; struct userdata *u = s->userdata; snd_pcm_sframes_t frames; assert(s && u && u->sink); if (snd_pcm_delay(u->pcm_handle, &frames) < 0) { - fprintf(stderr, __FILE__": failed to get delay\n"); + pa_log(__FILE__": failed to get delay\n"); s->get_latency = NULL; return 0; } @@ -152,10 +160,15 @@ static uint32_t sink_get_latency_cb(struct pa_sink *s) { if (frames < 0) frames = 0; - return pa_bytes_to_usec(frames * u->frame_size, &s->sample_spec); + r += pa_bytes_to_usec(frames * u->frame_size, &s->sample_spec); + + if (u->memchunk.memblock) + r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec); + + return r; } -int pa_module_init(struct pa_core *c, struct pa_module*m) { +int pa__init(struct pa_core *c, struct pa_module*m) { struct pa_modargs *ma = NULL; int ret = -1; struct userdata *u = NULL; @@ -166,13 +179,13 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { size_t frame_size; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - fprintf(stderr, __FILE__": failed to parse module arguments\n"); + pa_log(__FILE__": failed to parse module arguments\n"); goto fail; } ss = c->default_sample_spec; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { - fprintf(stderr, __FILE__": failed to parse sample specification\n"); + pa_log(__FILE__": failed to parse sample specification\n"); goto fail; } frame_size = pa_frame_size(&ss); @@ -180,7 +193,7 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { periods = 12; fragsize = 1024; if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) { - fprintf(stderr, __FILE__": failed to parse buffer metrics\n"); + pa_log(__FILE__": failed to parse buffer metrics\n"); goto fail; } buffer_size = fragsize/frame_size*periods; @@ -190,12 +203,12 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->module = m; if (snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) { - fprintf(stderr, __FILE__": Error opening PCM device %s\n", dev); + pa_log(__FILE__": Error opening PCM device %s\n", dev); goto fail; } if (pa_alsa_set_hw_params(u->pcm_handle, &ss, &periods, &buffer_size) < 0) { - fprintf(stderr, __FILE__": Failed to set hardware parameters\n"); + pa_log(__FILE__": Failed to set hardware parameters\n"); goto fail; } @@ -208,14 +221,14 @@ int pa_module_init(struct pa_core *c, struct pa_module*m) { u->sink->description = pa_sprintf_malloc("Advanced Linux Sound Architecture PCM on '%s'", dev); if (pa_create_io_events(u->pcm_handle, c->mainloop, &u->io_events, &u->n_io_events, io_callback, u) < 0) { - fprintf(stderr, __FILE__": failed to obtain file descriptors\n"); + pa_log(__FILE__": failed to obtain file descriptors\n"); goto fail; } u->frame_size = frame_size; u->fragment_size = buffer_size*u->frame_size/periods; - fprintf(stderr, __FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size); + pa_log(__FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size); u->silence.memblock = pa_memblock_new(u->silence.length = u->fragment_size, c->memblock_stat); assert(u->silence.memblock); @@ -236,20 +249,22 @@ finish: fail: if (u) - pa_module_done(c, m); + pa__done(c, m); goto finish; } -void pa_module_done(struct pa_core *c, struct pa_module*m) { +void pa__done(struct pa_core *c, struct pa_module*m) { struct userdata *u; assert(c && m); if (!(u = m->userdata)) return; - if (u->sink) - pa_sink_free(u->sink); + if (u->sink) { + pa_sink_disconnect(u->sink); + pa_sink_unref(u->sink); + } if (u->io_events) pa_free_io_events(c->mainloop, u->io_events, u->n_io_events);