From ba322a49e1754eba11495da9a10e3e0dbbe89244 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 24 Sep 2007 16:10:43 +0000 Subject: [PATCH] drop the PA_SOURCE_CAN_SUSPEND and PA_SINK_CAN_SUSPEND flags, since they were a bad idea in the first place. All sinks/sources are now *required* to handle suspending in one way or another. Luckily all current sink/source implementations handle it fine anyway. git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1894 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-alsa-sink.c | 159 +++++++++++++-------------- src/modules/module-alsa-source.c | 145 ++++++++++++------------ src/modules/module-combine.c | 2 +- src/modules/module-ladspa-sink.c | 2 +- src/modules/module-oss.c | 4 +- src/modules/module-remap-sink.c | 2 +- src/modules/module-suspend-on-idle.c | 64 +++++------ src/pulse/def.h | 6 +- src/pulse/stream.c | 12 +- src/pulsecore/cli-text.c | 8 +- src/pulsecore/sink.c | 3 - src/pulsecore/source.c | 3 - 12 files changed, 196 insertions(+), 214 deletions(-) diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 4f2e570a..0489fa87 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -70,11 +70,11 @@ struct userdata { pa_core *core; pa_module *module; pa_sink *sink; - + pa_thread *thread; pa_thread_mq thread_mq; pa_rtpoll *rtpoll; - + snd_pcm_t *pcm_handle; pa_alsa_fdlist *mixer_fdl; @@ -110,7 +110,7 @@ static const char* const valid_modargs[] = { static int mmap_write(struct userdata *u) { int work_done = 0; - + pa_assert(u); pa_sink_assert_ref(u->sink); @@ -121,33 +121,33 @@ static int mmap_write(struct userdata *u) { int err; const snd_pcm_channel_area_t *areas; snd_pcm_uframes_t offset, frames; - + if ((n = snd_pcm_avail_update(u->pcm_handle)) < 0) { if (n == -EPIPE) { pa_log_debug("snd_pcm_avail_update: Buffer underrun!"); u->first = 1; } - + if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0) continue; if (err == -EAGAIN) return work_done; - + pa_log("snd_pcm_avail_update: %s", snd_strerror(err)); return -1; } /* pa_log("Got request for %i samples", (int) n); */ - + if (n <= 0) return work_done; frames = n; - + if ((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0) { - + if (err == -EPIPE) { pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!"); u->first = 1; @@ -172,7 +172,7 @@ static int mmap_write(struct userdata *u) { pa_assert((areas[0].step >> 3) == u->frame_size); p = (uint8_t*) areas[0].addr + (offset * u->frame_size); - + chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames * u->frame_size, 1); chunk.length = pa_memblock_get_length(chunk.memblock); chunk.index = 0; @@ -189,13 +189,13 @@ static int mmap_write(struct userdata *u) { pa_log_debug("snd_pcm_mmap_commit: Buffer underrun!"); u->first = 1; } - + if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) continue; - + if (err == -EAGAIN) return work_done; - + pa_log("Failed to write data to DSP: %s", snd_strerror(err)); return -1; } @@ -204,7 +204,7 @@ static int mmap_write(struct userdata *u) { if (frames >= (snd_pcm_uframes_t) n) return work_done; - + /* pa_log("wrote %i samples", (int) frames); */ } } @@ -214,7 +214,7 @@ static int unix_write(struct userdata *u) { int work_done = 0; snd_pcm_status_alloca(&status); - + pa_assert(u); pa_sink_assert_ref(u->sink); @@ -223,7 +223,7 @@ static int unix_write(struct userdata *u) { snd_pcm_sframes_t t; ssize_t l; int err; - + if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) { pa_log("Failed to query DSP status data: %s", snd_strerror(err)); return -1; @@ -231,32 +231,32 @@ static int unix_write(struct userdata *u) { if (snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size) pa_log_debug("Buffer underrun!"); - + l = snd_pcm_status_get_avail(status) * u->frame_size; /* pa_log("%u bytes to write", l); */ - + if (l <= 0) return work_done; - + if (u->memchunk.length <= 0) pa_sink_render(u->sink, l, &u->memchunk); - + pa_assert(u->memchunk.length > 0); - + p = pa_memblock_acquire(u->memchunk.memblock); t = snd_pcm_writei(u->pcm_handle, (const uint8_t*) p + u->memchunk.index, u->memchunk.length / u->frame_size); pa_memblock_release(u->memchunk.memblock); - + /* pa_log("wrote %i bytes of %u (%u)", t*u->frame_size, u->memchunk.length, l); */ - + pa_assert(t != 0); - + if (t < 0) { if ((t = snd_pcm_recover(u->pcm_handle, t, 1)) == 0) continue; - + if (t == -EAGAIN) { pa_log_debug("EAGAIN"); return work_done; @@ -265,10 +265,10 @@ static int unix_write(struct userdata *u) { return -1; } } - + u->memchunk.index += t * u->frame_size; u->memchunk.length -= t * u->frame_size; - + if (u->memchunk.length <= 0) { pa_memblock_unref(u->memchunk.memblock); pa_memchunk_reset(&u->memchunk); @@ -278,7 +278,7 @@ static int unix_write(struct userdata *u) { if (t * u->frame_size >= (unsigned) l) return work_done; - } + } } static pa_usec_t sink_get_latency(struct userdata *u) { @@ -288,18 +288,18 @@ static pa_usec_t sink_get_latency(struct userdata *u) { int err; snd_pcm_status_alloca(&status); - + pa_assert(u); pa_assert(u->pcm_handle); - if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) + if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) pa_log("Failed to get delay: %s", snd_strerror(err)); else frames = snd_pcm_status_get_delay(status); if (frames > 0) r = pa_bytes_to_usec(frames * u->frame_size, &u->sink->sample_spec); - + if (u->memchunk.memblock) r += pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec); @@ -310,7 +310,7 @@ static int build_pollfd(struct userdata *u) { int err; struct pollfd *pollfd; int n; - + pa_assert(u); pa_assert(u->pcm_handle); @@ -329,7 +329,7 @@ static int build_pollfd(struct userdata *u) { pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err)); return -1; } - + return 0; } @@ -338,7 +338,7 @@ static int suspend(struct userdata *u) { pa_assert(u->pcm_handle); /* Let's suspend */ - snd_pcm_drain(u->pcm_handle); + snd_pcm_drain(u->pcm_handle); snd_pcm_close(u->pcm_handle); u->pcm_handle = NULL; @@ -346,9 +346,9 @@ static int suspend(struct userdata *u) { pa_rtpoll_item_free(u->alsa_rtpoll_item); u->alsa_rtpoll_item = NULL; } - + pa_log_info("Device suspended..."); - + return 0; } @@ -373,7 +373,7 @@ static int unsuspend(struct userdata *u) { nfrags = u->nfragments; period_size = u->fragment_size / u->frame_size; b = u->use_mmap; - + if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) { pa_log("Failed to set hardware parameters: %s", snd_strerror(err)); goto fail; @@ -401,11 +401,11 @@ static int unsuspend(struct userdata *u) { if (build_pollfd(u) < 0) goto fail; - + /* FIXME: We need to reload the volume somehow */ - + u->first = 1; - + pa_log_info("Resumed successfully..."); return 0; @@ -438,13 +438,13 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse case PA_SINK_MESSAGE_SET_STATE: switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) { - + case PA_SINK_SUSPENDED: pa_assert(PA_SINK_OPENED(u->sink->thread_info.state)); if (suspend(u) < 0) return -1; - + break; case PA_SINK_IDLE: @@ -454,14 +454,14 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse if (unsuspend(u) < 0) return -1; } - + break; case PA_SINK_UNLINKED: case PA_SINK_INIT: ; } - + break; } @@ -512,7 +512,7 @@ static int sink_get_volume_cb(pa_sink *s) { fail: pa_log_error("Unable to read volume: %s", snd_strerror(err)); - + s->get_volume = NULL; s->set_volume = NULL; return -1; @@ -547,7 +547,7 @@ static int sink_set_volume_cb(pa_sink *s) { fail: pa_log_error("Unable to set volume: %s", snd_strerror(err)); - + s->get_volume = NULL; s->set_volume = NULL; return -1; @@ -582,7 +582,7 @@ static int sink_set_mute_cb(pa_sink *s) { if ((err = snd_mixer_selem_set_playback_switch_all(u->mixer_elem, !s->muted)) < 0) { pa_log_error("Unable to set switch: %s", snd_strerror(err)); - + s->get_mute = NULL; s->set_mute = NULL; return -1; @@ -593,7 +593,7 @@ static int sink_set_mute_cb(pa_sink *s) { static void thread_func(void *userdata) { struct userdata *u = userdata; - + pa_assert(u); pa_log_debug("Thread starting up"); @@ -603,17 +603,17 @@ static void thread_func(void *userdata) { pa_thread_mq_install(&u->thread_mq); pa_rtpoll_install(u->rtpoll); - + if (build_pollfd(u) < 0) goto fail; for (;;) { int ret; - + /* Render some data and write it to the dsp */ if (PA_SINK_OPENED(u->sink->thread_info.state)) { int work_done = 0; - + if (u->use_mmap) { if ((work_done = mmap_write(u)) < 0) goto fail; @@ -636,7 +636,7 @@ static void thread_func(void *userdata) { if (ret == 0) goto finish; - + /* Tell ALSA about this and process its response */ if (PA_SINK_OPENED(u->sink->thread_info.state)) { struct pollfd *pollfd; @@ -655,7 +655,7 @@ static void thread_func(void *userdata) { if (revents & POLLERR) pa_log_warn("Got POLLERR from ALSA"); if (revents & POLLNVAL) - pa_log_warn("Got POLLNVAL from ALSA"); + pa_log_warn("Got POLLNVAL from ALSA"); if (revents & POLLHUP) pa_log_warn("Got POLLHUP from ALSA"); @@ -675,7 +675,7 @@ finish: } int pa__init(pa_module*m) { - + pa_modargs *ma = NULL; struct userdata *u = NULL; char *dev; @@ -693,7 +693,7 @@ int pa__init(pa_module*m) { int use_mmap = 1, b; snd_pcm_info_alloca(&pcm_info); - + pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { @@ -724,7 +724,7 @@ int pa__init(pa_module*m) { pa_log("Failed to parse mmap argument."); goto fail; } - + u = pa_xnew0(struct userdata, 1); u->core = m->core; u->module = m; @@ -741,19 +741,19 @@ int pa__init(pa_module*m) { dev = pa_xstrdup(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE)); for (;;) { - + if ((err = snd_pcm_open(&u->pcm_handle, dev, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) { pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err)); pa_xfree(dev); goto fail; } - + b = use_mmap; if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) { if (err == -EPERM) { /* Hmm, some hw is very exotic, so we retry with plughw, if hw didn't work */ - + if (pa_startswith(dev, "hw:")) { char *d = pa_sprintf_malloc("plughw:%s", dev+3); pa_log_debug("Opening the device as '%s' didn't work, retrying with '%s'.", dev, d); @@ -765,7 +765,7 @@ int pa__init(pa_module*m) { continue; } } - + pa_log("Failed to set hardware parameters: %s", snd_strerror(err)); pa_xfree(dev); goto fail; @@ -773,9 +773,9 @@ int pa__init(pa_module*m) { break; } - + u->device_name = dev; - + if (use_mmap && !b) { pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode."); u->use_mmap = use_mmap = b; @@ -807,7 +807,7 @@ int pa__init(pa_module*m) { if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) || !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Master", "PCM"))) { - + snd_mixer_close(u->mixer_handle); u->mixer_handle = NULL; } @@ -822,7 +822,7 @@ int pa__init(pa_module*m) { u->sink = pa_sink_new(m->core, __FILE__, name, namereg_fail, &ss, &map); pa_xfree(name_buf); - + if (!u->sink) { pa_log("Failed to create sink object"); goto fail; @@ -840,8 +840,8 @@ int pa__init(pa_module*m) { snd_pcm_info_get_name(pcm_info), use_mmap ? " via DMA" : "")); pa_xfree(t); - - u->sink->flags = PA_SINK_HARDWARE|PA_SINK_CAN_SUSPEND|PA_SINK_HW_VOLUME_CTRL|PA_SINK_LATENCY; + + u->sink->flags = PA_SINK_HARDWARE|PA_SINK_HW_VOLUME_CTRL|PA_SINK_LATENCY; u->frame_size = frame_size; u->fragment_size = frag_size = period_size * frame_size; @@ -854,9 +854,9 @@ int pa__init(pa_module*m) { if (u->mixer_handle) { /* Initialize mixer code */ - + pa_assert(u->mixer_elem); - + if (snd_mixer_selem_has_playback_volume(u->mixer_elem)) { int i; @@ -872,7 +872,7 @@ int pa__init(pa_module*m) { } else pa_log_info("ALSA device lacks separate volumes controls for all %u channels (%u available), falling back to software volume control.", ss.channels, i+1); } - + if (snd_mixer_selem_has_playback_switch(u->mixer_elem)) { u->sink->get_mute = sink_get_mute_cb; u->sink->set_mute = sink_set_mute_cb; @@ -894,7 +894,7 @@ int pa__init(pa_module*m) { pa_log("Failed to create thread."); goto fail; } - + /* Get initial mixer settings */ if (u->sink->get_volume) u->sink->get_volume(u->sink); @@ -902,11 +902,11 @@ int pa__init(pa_module*m) { u->sink->get_mute(u->sink); pa_sink_put(u->sink); - + pa_modargs_free(ma); - + return 0; - + fail: if (ma) @@ -919,7 +919,7 @@ fail: void pa__done(pa_module*m) { struct userdata *u; - + pa_assert(m); if (!(u = m->userdata)) @@ -937,19 +937,19 @@ void pa__done(pa_module*m) { if (u->sink) pa_sink_unref(u->sink); - + if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); if (u->alsa_rtpoll_item) pa_rtpoll_item_free(u->alsa_rtpoll_item); - + if (u->rtpoll) pa_rtpoll_free(u->rtpoll); - + if (u->mixer_fdl) pa_alsa_fdlist_free(u->mixer_fdl); - + if (u->mixer_handle) snd_mixer_close(u->mixer_handle); @@ -960,7 +960,6 @@ void pa__done(pa_module*m) { pa_xfree(u->device_name); pa_xfree(u); - + snd_config_update_free_global(); } - diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c index 82f66bb9..de019ffb 100644 --- a/src/modules/module-alsa-source.c +++ b/src/modules/module-alsa-source.c @@ -71,7 +71,7 @@ struct userdata { pa_core *core; pa_module *module; pa_source *source; - + pa_thread *thread; pa_thread_mq thread_mq; pa_rtpoll *rtpoll; @@ -108,7 +108,7 @@ static const char* const valid_modargs[] = { static int mmap_read(struct userdata *u) { int work_done = 0; - + pa_assert(u); pa_source_assert_ref(u->source); @@ -119,31 +119,31 @@ static int mmap_read(struct userdata *u) { snd_pcm_uframes_t offset, frames; pa_memchunk chunk; void *p; - + if ((n = snd_pcm_avail_update(u->pcm_handle)) < 0) { if (n == -EPIPE) pa_log_debug("snd_pcm_avail_update: Buffer underrun!"); - + if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0) continue; if (err == -EAGAIN) return work_done; - + pa_log("snd_pcm_avail_update: %s", snd_strerror(err)); return -1; } /* pa_log("Got request for %i samples", (int) n); */ - + if (n <= 0) return work_done; frames = n; - + if ((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0) { - + if (err == -EPIPE) pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!"); @@ -166,7 +166,7 @@ static int mmap_read(struct userdata *u) { pa_assert((areas[0].step >> 3) == u->frame_size); p = (uint8_t*) areas[0].addr + (offset * u->frame_size); - + chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames * u->frame_size, 1); chunk.length = pa_memblock_get_length(chunk.memblock); chunk.index = 0; @@ -181,13 +181,13 @@ static int mmap_read(struct userdata *u) { if (err == -EPIPE) pa_log_debug("snd_pcm_mmap_commit: Buffer underrun!"); - + if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) continue; - + if (err == -EAGAIN) return work_done; - + pa_log("Failed to write data to DSP: %s", snd_strerror(err)); return -1; } @@ -213,7 +213,7 @@ static int unix_read(struct userdata *u) { ssize_t l; int err; pa_memchunk chunk; - + if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) { pa_log("Failed to query DSP status data: %s", snd_strerror(err)); return -1; @@ -221,12 +221,12 @@ static int unix_read(struct userdata *u) { if (snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size) pa_log_debug("Buffer overrun!"); - + l = snd_pcm_status_get_avail(status) * u->frame_size; if (l <= 0) return work_done; - + chunk.memblock = pa_memblock_new(u->core->mempool, (size_t) -1); k = pa_memblock_get_length(chunk.memblock); @@ -239,17 +239,17 @@ static int unix_read(struct userdata *u) { p = pa_memblock_acquire(chunk.memblock); t = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, k / u->frame_size); pa_memblock_release(chunk.memblock); - + /* pa_log("wrote %i bytes of %u (%u)", t*u->frame_size, u->memchunk.length, l); */ - + pa_assert(t != 0); - + if (t < 0) { pa_memblock_unref(chunk.memblock); - + if ((t = snd_pcm_recover(u->pcm_handle, t, 1)) == 0) continue; - + if (t == -EAGAIN) { pa_log_debug("EAGAIN"); return work_done; @@ -257,14 +257,14 @@ static int unix_read(struct userdata *u) { pa_log("Failed to read data from DSP: %s", snd_strerror(t)); return -1; } - } - + } + chunk.index = 0; chunk.length = t * u->frame_size; pa_source_post(u->source, &chunk); pa_memblock_unref(chunk.memblock); - + work_done = 1; if (t * u->frame_size >= (unsigned) l) @@ -279,11 +279,11 @@ static pa_usec_t source_get_latency(struct userdata *u) { int err; snd_pcm_status_alloca(&status); - + pa_assert(u); pa_assert(u->pcm_handle); - if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) + if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) pa_log("Failed to get delay: %s", snd_strerror(err)); else frames = snd_pcm_status_get_delay(status); @@ -298,7 +298,7 @@ static int build_pollfd(struct userdata *u) { int err; struct pollfd *pollfd; int n; - + pa_assert(u); pa_assert(u->pcm_handle); @@ -312,12 +312,12 @@ static int build_pollfd(struct userdata *u) { u->alsa_rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, n); pollfd = pa_rtpoll_item_get_pollfd(u->alsa_rtpoll_item, NULL); - + if ((err = snd_pcm_poll_descriptors(u->pcm_handle, pollfd, n)) < 0) { pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err)); return -1; } - + return 0; } @@ -333,9 +333,9 @@ static int suspend(struct userdata *u) { pa_rtpoll_item_free(u->alsa_rtpoll_item); u->alsa_rtpoll_item = NULL; } - + pa_log_info("Device suspended..."); - + return 0; } @@ -360,7 +360,7 @@ static int unsuspend(struct userdata *u) { nfrags = u->nfragments; period_size = u->fragment_size / u->frame_size; b = u->use_mmap; - + if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) { pa_log("Failed to set hardware parameters: %s", snd_strerror(err)); goto fail; @@ -370,7 +370,7 @@ static int unsuspend(struct userdata *u) { pa_log_warn("Resume failed, couldn't get original access mode."); goto fail; } - + if (!pa_sample_spec_equal(&ss, &u->source->sample_spec)) { pa_log_warn("Resume failed, couldn't restore original sample settings."); goto fail; @@ -388,11 +388,11 @@ static int unsuspend(struct userdata *u) { if (build_pollfd(u) < 0) goto fail; - + snd_pcm_start(u->pcm_handle); - + /* FIXME: We need to reload the volume somehow */ - + pa_log_info("Resumed successfully..."); return 0; @@ -425,13 +425,13 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off case PA_SOURCE_MESSAGE_SET_STATE: switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) { - + case PA_SOURCE_SUSPENDED: pa_assert(PA_SOURCE_OPENED(u->source->thread_info.state)); if (suspend(u) < 0) return -1; - + break; case PA_SOURCE_IDLE: @@ -441,14 +441,14 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off if (unsuspend(u) < 0) return -1; } - + break; case PA_SOURCE_UNLINKED: case PA_SOURCE_INIT: ; } - + break; } @@ -499,7 +499,7 @@ static int source_get_volume_cb(pa_source *s) { fail: pa_log_error("Unable to read volume: %s", snd_strerror(err)); - + s->get_volume = NULL; s->set_volume = NULL; return -1; @@ -534,7 +534,7 @@ static int source_set_volume_cb(pa_source *s) { fail: pa_log_error("Unable to set volume: %s", snd_strerror(err)); - + s->get_volume = NULL; s->set_volume = NULL; return -1; @@ -569,7 +569,7 @@ static int source_set_mute_cb(pa_source *s) { if ((err = snd_mixer_selem_set_capture_switch_all(u->mixer_elem, !s->muted)) < 0) { pa_log_error("Unable to set switch: %s", snd_strerror(err)); - + s->get_mute = NULL; s->set_mute = NULL; return -1; @@ -590,18 +590,18 @@ static void thread_func(void *userdata) { pa_thread_mq_install(&u->thread_mq); pa_rtpoll_install(u->rtpoll); - + if (build_pollfd(u) < 0) goto fail; snd_pcm_start(u->pcm_handle); - + for (;;) { int ret; /* Read some data and pass it to the sources */ if (PA_SOURCE_OPENED(u->source->thread_info.state)) { - + if (u->use_mmap) { if (mmap_read(u) < 0) goto fail; @@ -618,7 +618,7 @@ static void thread_func(void *userdata) { if (ret == 0) goto finish; - + /* Tell ALSA about this and process its response */ if (PA_SOURCE_OPENED(u->source->thread_info.state)) { struct pollfd *pollfd; @@ -627,7 +627,7 @@ static void thread_func(void *userdata) { unsigned n; pollfd = pa_rtpoll_item_get_pollfd(u->alsa_rtpoll_item, &n); - + if ((err = snd_pcm_poll_descriptors_revents(u->pcm_handle, pollfd, n, &revents)) < 0) { pa_log("snd_pcm_poll_descriptors_revents() failed: %s", snd_strerror(err)); goto fail; @@ -637,7 +637,7 @@ static void thread_func(void *userdata) { if (revents & POLLERR) pa_log_warn("Got POLLERR from ALSA"); if (revents & POLLNVAL) - pa_log_warn("Got POLLNVAL from ALSA"); + pa_log_warn("Got POLLNVAL from ALSA"); if (revents & POLLHUP) pa_log_warn("Got POLLHUP from ALSA"); @@ -657,7 +657,7 @@ finish: } int pa__init(pa_module*m) { - + pa_modargs *ma = NULL; struct userdata *u = NULL; char *dev; @@ -677,7 +677,7 @@ int pa__init(pa_module*m) { snd_pcm_info_alloca(&pcm_info); pa_assert(m); - + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); goto fail; @@ -706,7 +706,7 @@ int pa__init(pa_module*m) { pa_log("Failed to parse mmap argument."); goto fail; } - + u = pa_xnew0(struct userdata, 1); u->core = m->core; u->module = m; @@ -720,9 +720,9 @@ int pa__init(pa_module*m) { snd_config_update_free_global(); dev = pa_xstrdup(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE)); - + for (;;) { - + if ((err = snd_pcm_open(&u->pcm_handle, dev, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) { pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err)); pa_xfree(dev); @@ -734,7 +734,7 @@ int pa__init(pa_module*m) { if (err == -EPERM) { /* Hmm, some hw is very exotic, so we retry with plughw, if hw didn't work */ - + if (pa_startswith(dev, "hw:")) { char *d = pa_sprintf_malloc("plughw:%s", dev+3); pa_log_debug("Opening the device as '%s' didn't work, retrying with '%s'.", dev, d); @@ -746,7 +746,7 @@ int pa__init(pa_module*m) { continue; } } - + pa_log("Failed to set hardware parameters: %s", snd_strerror(err)); pa_xfree(dev); goto fail; @@ -756,7 +756,7 @@ int pa__init(pa_module*m) { } u->device_name = dev; - + if (use_mmap && !b) { pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode."); u->use_mmap = use_mmap = b; @@ -774,7 +774,7 @@ int pa__init(pa_module*m) { pa_log("Failed to set software parameters: %s", snd_strerror(err)); goto fail; } - + /* ALSA might tweak the sample spec, so recalculate the frame size */ frame_size = pa_frame_size(&ss); @@ -785,7 +785,7 @@ int pa__init(pa_module*m) { if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0) pa_log("Error opening mixer: %s", snd_strerror(err)); else { - + if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) || !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Capture", NULL))) { snd_mixer_close(u->mixer_handle); @@ -802,7 +802,7 @@ int pa__init(pa_module*m) { u->source = pa_source_new(m->core, __FILE__, name, namereg_fail, &ss, &map); pa_xfree(name_buf); - + if (!u->source) { pa_log("Failed to create source object"); goto fail; @@ -821,7 +821,7 @@ int pa__init(pa_module*m) { use_mmap ? " via DMA" : "")); pa_xfree(t); - u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_CAN_SUSPEND|PA_SOURCE_LATENCY|PA_SOURCE_HW_VOLUME_CTRL; + u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY|PA_SOURCE_HW_VOLUME_CTRL; u->frame_size = frame_size; u->fragment_size = frag_size = period_size * frame_size; @@ -832,7 +832,7 @@ int pa__init(pa_module*m) { if (u->mixer_handle) { pa_assert(u->mixer_elem); - + if (snd_mixer_selem_has_capture_volume(u->mixer_elem)) { int i; @@ -847,19 +847,19 @@ int pa__init(pa_module*m) { snd_mixer_selem_get_capture_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max); } } - + if (snd_mixer_selem_has_capture_switch(u->mixer_elem)) { u->source->get_mute = source_get_mute_cb; u->source->set_mute = source_set_mute_cb; } u->mixer_fdl = pa_alsa_fdlist_new(); - + if (pa_alsa_fdlist_set_mixer(u->mixer_fdl, u->mixer_handle, m->core->mainloop) < 0) { pa_log("failed to initialise file descriptor monitoring"); goto fail; } - + snd_mixer_elem_set_callback(u->mixer_elem, mixer_callback); snd_mixer_elem_set_callback_private(u->mixer_elem, u); } else @@ -875,25 +875,25 @@ int pa__init(pa_module*m) { if (u->source->get_mute) u->source->get_mute(u->source); - pa_source_put(u->source); - + pa_source_put(u->source); + pa_modargs_free(ma); - + return 0; - + fail: if (ma) pa_modargs_free(ma); pa__done(m); - + return -1; } void pa__done(pa_module*m) { struct userdata *u; - + pa_assert(m); if (!(u = m->userdata)) @@ -914,10 +914,10 @@ void pa__done(pa_module*m) { if (u->alsa_rtpoll_item) pa_rtpoll_item_free(u->alsa_rtpoll_item); - + if (u->rtpoll) pa_rtpoll_free(u->rtpoll); - + if (u->mixer_fdl) pa_alsa_fdlist_free(u->mixer_fdl); @@ -934,4 +934,3 @@ void pa__done(pa_module*m) { snd_config_update_free_global(); } - diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index af5ddb1c..656cef92 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -1134,7 +1134,7 @@ int pa__init(pa_module*m) { u->sink->set_state = sink_set_state; u->sink->userdata = u; - u->sink->flags = PA_SINK_CAN_SUSPEND|PA_SINK_LATENCY; + u->sink->flags = PA_SINK_LATENCY; pa_sink_set_module(u->sink, m); pa_sink_set_description(u->sink, "Simultaneous output"); diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c index 38b7e011..9f771c6b 100644 --- a/src/modules/module-ladspa-sink.c +++ b/src/modules/module-ladspa-sink.c @@ -568,7 +568,7 @@ int pa__init(pa_module*m) { u->sink->parent.process_msg = sink_process_msg; u->sink->set_state = sink_set_state; u->sink->userdata = u; - u->sink->flags = PA_SINK_LATENCY|PA_SINK_CAN_SUSPEND; + u->sink->flags = PA_SINK_LATENCY; pa_sink_set_module(u->sink, m); pa_sink_set_description(u->sink, t = pa_sprintf_malloc("LADSPA plugin '%s' on '%s'", label, master->description)); diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 358154ac..8d088997 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -1243,7 +1243,7 @@ int pa__init(pa_module*m) { hwdesc[0] ? ")" : "", use_mmap ? " via DMA" : "")); pa_xfree(t); - u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_CAN_SUSPEND|PA_SOURCE_LATENCY; + u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY; u->source->refresh_volume = 1; if (use_mmap) @@ -1298,7 +1298,7 @@ int pa__init(pa_module*m) { hwdesc[0] ? ")" : "", use_mmap ? " via DMA" : "")); pa_xfree(t); - u->sink->flags = PA_SINK_HARDWARE|PA_SINK_CAN_SUSPEND|PA_SINK_LATENCY; + u->sink->flags = PA_SINK_HARDWARE|PA_SINK_LATENCY; u->sink->refresh_volume = 1; if (use_mmap) diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c index bff787bc..d712a045 100644 --- a/src/modules/module-remap-sink.c +++ b/src/modules/module-remap-sink.c @@ -262,7 +262,7 @@ int pa__init(pa_module*m) { u->sink->parent.process_msg = sink_process_msg; u->sink->set_state = sink_set_state; u->sink->userdata = u; - u->sink->flags = PA_SINK_LATENCY|PA_SINK_CAN_SUSPEND; + u->sink->flags = PA_SINK_LATENCY; pa_sink_set_module(u->sink, m); pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Remapped %s", master->description)); diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c index 79850e71..4fcb404c 100644 --- a/src/modules/module-suspend-on-idle.c +++ b/src/modules/module-suspend-on-idle.c @@ -57,7 +57,7 @@ struct userdata { *source_unlink_slot, *sink_state_changed_slot, *source_state_changed_slot; - + pa_hook_slot *sink_input_new_slot, *source_output_new_slot, @@ -83,7 +83,7 @@ static void timeout_cb(pa_mainloop_api*a, pa_time_event* e, const struct timeval pa_assert(d); d->userdata->core->mainloop->time_restart(d->time_event, NULL); - + if (d->sink && pa_sink_used_by(d->sink) <= 0 && pa_sink_get_state(d->sink) != PA_SINK_SUSPENDED) { pa_log_info("Sink %s idle for too long, suspending ...", d->sink->name); pa_sink_suspend(d->sink, 1); @@ -119,7 +119,7 @@ static void resume(struct device_info *d) { if (d->sink) { pa_sink_suspend(d->sink, 0); pa_source_suspend(d->sink->monitor_source, 0); - + pa_log_debug("Sink %s becomes busy.", d->sink->name); } @@ -134,14 +134,14 @@ static void resume(struct device_info *d) { static pa_hook_result_t sink_input_new_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) { struct device_info *d; - + pa_assert(c); pa_sink_input_assert_ref(s); pa_assert(u); - + if ((d = pa_hashmap_get(u->device_infos, s->sink))) resume(d); - + return PA_HOOK_OK; } @@ -151,10 +151,10 @@ static pa_hook_result_t source_output_new_hook_cb(pa_core *c, pa_source_output * pa_assert(c); pa_source_output_assert_ref(s); pa_assert(u); - + if ((d = pa_hashmap_get(u->device_infos, s->source))) resume(d); - + return PA_HOOK_OK; } @@ -168,7 +168,7 @@ static pa_hook_result_t sink_input_unlink_hook_cb(pa_core *c, pa_sink_input *s, if ((d = pa_hashmap_get(u->device_infos, s->sink))) restart(d); } - + return PA_HOOK_OK; } @@ -182,7 +182,7 @@ static pa_hook_result_t source_output_unlink_hook_cb(pa_core *c, pa_source_outpu if ((d = pa_hashmap_get(u->device_infos, s->source))) restart(d); } - + return PA_HOOK_OK; } @@ -196,7 +196,7 @@ static pa_hook_result_t sink_input_move_hook_cb(pa_core *c, pa_sink_input *s, st if ((d = pa_hashmap_get(u->device_infos, s->sink))) restart(d); } - + return PA_HOOK_OK; } @@ -208,7 +208,7 @@ static pa_hook_result_t sink_input_move_post_hook_cb(pa_core *c, pa_sink_input * if ((d = pa_hashmap_get(u->device_infos, s->sink))) resume(d); - + return PA_HOOK_OK; } @@ -223,7 +223,7 @@ static pa_hook_result_t source_output_move_hook_cb(pa_core *c, pa_source_output if ((d = pa_hashmap_get(u->device_infos, s->source))) restart(d); } - + return PA_HOOK_OK; } @@ -235,7 +235,7 @@ static pa_hook_result_t source_output_move_post_hook_cb(pa_core *c, pa_source_ou if ((d = pa_hashmap_get(u->device_infos, s->source))) resume(d); - + return PA_HOOK_OK; } @@ -243,7 +243,7 @@ static pa_hook_result_t device_new_hook_cb(pa_core *c, pa_object *o, struct user struct device_info *d; pa_source *source; pa_sink *sink; - + pa_assert(c); pa_object_assert_ref(o); pa_assert(u); @@ -252,12 +252,6 @@ static pa_hook_result_t device_new_hook_cb(pa_core *c, pa_object *o, struct user sink = pa_sink_isinstance(o) ? PA_SINK(o) : NULL; pa_assert(source || sink); - - if (source && !(source->flags & PA_SOURCE_CAN_SUSPEND)) - return PA_HOOK_OK; - - if (sink && !(sink->flags & PA_SINK_CAN_SUSPEND)) - return PA_HOOK_OK; d = pa_xnew(struct device_info, 1); d->userdata = u; @@ -275,20 +269,20 @@ static pa_hook_result_t device_new_hook_cb(pa_core *c, pa_object *o, struct user static void device_info_free(struct device_info *d) { pa_assert(d); - + if (d->source) pa_source_unref(d->source); if (d->sink) pa_sink_unref(d->sink); - + d->userdata->core->mainloop->time_free(d->time_event); - + pa_xfree(d); } static pa_hook_result_t device_unlink_hook_cb(pa_core *c, pa_object *o, struct userdata *u) { struct device_info *d; - + pa_assert(c); pa_object_assert_ref(o); pa_assert(u); @@ -311,14 +305,14 @@ static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, s if (pa_sink_isinstance(o)) { pa_sink *s = PA_SINK(o); - + if (pa_sink_used_by(s) <= 0) { pa_sink_state_t state = pa_sink_get_state(s); if (state == PA_SINK_RUNNING || state == PA_SINK_IDLE) restart(d); } - + } else if (pa_source_isinstance(o)) { pa_source *s = PA_SOURCE(o); @@ -329,7 +323,7 @@ static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, s restart(d); } } - + return PA_HOOK_OK; } @@ -352,7 +346,7 @@ int pa__init(pa_module*m) { pa_log("Failed to parse timeout value."); goto fail; } - + m->userdata = u = pa_xnew(struct userdata, 1); u->core = m->core; u->timeout = timeout; @@ -380,29 +374,29 @@ int pa__init(pa_module*m) { u->sink_input_move_post_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_POST], (pa_hook_cb_t) sink_input_move_post_hook_cb, u); u->source_output_move_post_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_POST], (pa_hook_cb_t) source_output_move_post_hook_cb, u); - + pa_modargs_free(ma); return 0; fail: - + if (ma) pa_modargs_free(ma); - + return -1; } void pa__done(pa_module*m) { struct userdata *u; struct device_info *d; - + pa_assert(m); if (!m->userdata) return; u = m->userdata; - + if (u->sink_new_slot) pa_hook_slot_free(u->sink_new_slot); if (u->sink_unlink_slot) @@ -439,6 +433,6 @@ void pa__done(pa_module*m) { device_info_free(d); pa_hashmap_free(u->device_infos, NULL, NULL); - + pa_xfree(u); } diff --git a/src/pulse/def.h b/src/pulse/def.h index 4102ba6e..c2816234 100644 --- a/src/pulse/def.h +++ b/src/pulse/def.h @@ -300,16 +300,14 @@ typedef enum pa_seek_mode { typedef enum pa_sink_flags { PA_SINK_HW_VOLUME_CTRL = 1, /**< Supports hardware volume control */ PA_SINK_LATENCY = 2, /**< Supports latency querying */ - PA_SINK_HARDWARE = 4, /**< Is a hardware sink of some kind, in contrast to "virtual"/software sinks \since 0.9.3 */ - PA_SINK_CAN_SUSPEND = 8 /**< Can suspend \since 0.9.7 */ + PA_SINK_HARDWARE = 4 /**< Is a hardware sink of some kind, in contrast to "virtual"/software sinks \since 0.9.3 */ } pa_sink_flags_t; /** Special source flags. \since 0.8 */ typedef enum pa_source_flags { PA_SOURCE_HW_VOLUME_CTRL = 1, /**< Supports hardware volume control */ PA_SOURCE_LATENCY = 2, /**< Supports latency querying */ - PA_SOURCE_HARDWARE = 4, /**< Is a hardware source of some kind, in contrast to "virtual"/software source \since 0.9.3 */ - PA_SOURCE_CAN_SUSPEND = 8 /**< Can suspend \since 0.9.7 */ + PA_SOURCE_HARDWARE = 4 /**< Is a hardware source of some kind, in contrast to "virtual"/software source \since 0.9.3 */ } pa_source_flags_t; /** A generic free() like callback prototype */ diff --git a/src/pulse/stream.c b/src/pulse/stream.c index 6d14a70a..47906a5c 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -423,7 +423,7 @@ static void create_stream_complete(pa_stream *s) { tv.tv_usec += LATENCY_IPOL_INTERVAL_USEC; /* every 100 ms */ pa_assert(!s->auto_timing_update_event); s->auto_timing_update_event = s->mainloop->time_new(s->mainloop, &tv, &auto_timing_update_callback, s); - } + } } void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { @@ -497,7 +497,7 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED s->state = PA_STREAM_READY; request_auto_timing_update(s, 1); s->state = PA_STREAM_CREATING; - + } else create_stream_complete(s); @@ -540,12 +540,12 @@ static int create_stream( if (attr) s->buffer_attr = *attr; else { - /* half a second */ + /* half a second, with minimum request of 10 ms */ s->buffer_attr.tlength = pa_bytes_per_second(&s->sample_spec)/2; s->buffer_attr.maxlength = (s->buffer_attr.tlength*3)/2; - s->buffer_attr.minreq = s->buffer_attr.tlength/100; + s->buffer_attr.minreq = s->buffer_attr.tlength/50; s->buffer_attr.prebuf = s->buffer_attr.tlength - s->buffer_attr.minreq; - s->buffer_attr.fragsize = s->buffer_attr.tlength/100; + s->buffer_attr.fragsize = s->buffer_attr.tlength/50; } if (!dev) @@ -921,7 +921,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, } /* First, let's complete the initialization, if necessary. */ - if (o->stream->state == PA_STREAM_CREATING) + if (o->stream->state == PA_STREAM_CREATING) create_stream_complete(o->stream); if (o->stream->latency_update_callback) diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c index bac61dc9..ec220198 100644 --- a/src/pulsecore/cli-text.c +++ b/src/pulsecore/cli-text.c @@ -111,7 +111,7 @@ char *pa_sink_list_to_string(pa_core *c) { " %c index: %u\n" "\tname: <%s>\n" "\tdriver: <%s>\n" - "\tflags: %s%s%s%s\n" + "\tflags: %s%s%s\n" "\tstate: %s\n" "\tvolume: <%s>\n" "\tmute: <%i>\n" @@ -119,7 +119,7 @@ char *pa_sink_list_to_string(pa_core *c) { "\tmonitor source: <%u>\n" "\tsample spec: <%s>\n" "\tchannel map: <%s>\n" - "\tused by: <%u>\n", + "\tused by: <%u>\n", c->default_sink_name && !strcmp(sink->name, c->default_sink_name) ? '*' : ' ', sink->index, sink->name, @@ -127,7 +127,6 @@ char *pa_sink_list_to_string(pa_core *c) { sink->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", sink->flags & PA_SINK_LATENCY ? "LATENCY " : "", sink->flags & PA_SINK_HARDWARE ? "HARDWARE " : "", - sink->flags & PA_SINK_CAN_SUSPEND ? "CAN_SUSPEND " : "", state_table[pa_sink_get_state(sink)], pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink)), !!pa_sink_get_mute(sink), @@ -171,7 +170,7 @@ char *pa_source_list_to_string(pa_core *c) { " %c index: %u\n" "\tname: <%s>\n" "\tdriver: <%s>\n" - "\tflags: %s%s%s%s\n" + "\tflags: %s%s%s\n" "\tstate: %s\n" "\tvolume: <%s>\n" "\tmute: <%u>\n" @@ -186,7 +185,6 @@ char *pa_source_list_to_string(pa_core *c) { source->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "", source->flags & PA_SOURCE_HARDWARE ? "HARDWARE " : "", - source->flags & PA_SOURCE_CAN_SUSPEND ? "CAN_SUSPEND " : "", state_table[pa_source_get_state(source)], pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source)), !!pa_source_get_mute(source), diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index b814f837..830960a5 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -170,9 +170,6 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) { if (s->state == state) return 0; - if (state == PA_SINK_SUSPENDED && !(s->flags & PA_SINK_CAN_SUSPEND)) - return -1; - if ((s->state == PA_SINK_SUSPENDED && PA_SINK_OPENED(state)) || (PA_SINK_OPENED(s->state) && state == PA_SINK_SUSPENDED)) { pa_sink_input *i; diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 9745a13e..20088c74 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -145,9 +145,6 @@ static int source_set_state(pa_source *s, pa_source_state_t state) { if (s->state == state) return 0; - if (state == PA_SOURCE_SUSPENDED && !(s->flags & PA_SOURCE_CAN_SUSPEND)) - return -1; - if ((s->state == PA_SOURCE_SUSPENDED && PA_SOURCE_OPENED(state)) || (PA_SOURCE_OPENED(s->state) && state == PA_SOURCE_SUSPENDED)) { pa_source_output *o; -- 2.39.2