From b232fbd8f8afa5881d483e2fa72e06206f1da861 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Aug 2011 18:37:29 -0500 Subject: [PATCH] alsa: support for alternate sampling rate This is where the actual changes happen. Some additional checks would be required to make sure the rate is actually supported Tested with both PCM and passthrough streams Signed-off-by: Pierre-Louis Bossart --- src/modules/alsa/alsa-sink.c | 72 +++++++++++------------------------ src/modules/alsa/alsa-source.c | 22 +++++++++++ src/modules/alsa/module-alsa-sink.c | 2 + src/modules/alsa/module-alsa-source.c | 2 + 4 files changed, 48 insertions(+), 50 deletions(-) diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index bcc6e51..0b7bbe0 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -1121,56 +1121,6 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse switch (code) { - case PA_SINK_MESSAGE_FINISH_MOVE: - case PA_SINK_MESSAGE_ADD_INPUT: { - pa_sink_input *i = PA_SINK_INPUT(data); - int r = 0; - - if (PA_LIKELY(!pa_sink_input_is_passthrough(i))) - break; - - u->old_rate = u->sink->sample_spec.rate; - - /* Passthrough format, see if we need to reset sink sample rate */ - if (u->sink->sample_spec.rate == i->thread_info.sample_spec.rate) - break; - - /* .. we do */ - if ((r = suspend(u)) < 0) - return r; - - u->sink->sample_spec.rate = i->thread_info.sample_spec.rate; - - if ((r = unsuspend(u)) < 0) - return r; - - break; - } - - case PA_SINK_MESSAGE_START_MOVE: - case PA_SINK_MESSAGE_REMOVE_INPUT: { - pa_sink_input *i = PA_SINK_INPUT(data); - int r = 0; - - if (PA_LIKELY(!pa_sink_input_is_passthrough(i))) - break; - - /* Passthrough format, see if we need to reset sink sample rate */ - if (u->sink->sample_spec.rate == u->old_rate) - break; - - /* .. we do */ - if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && ((r = suspend(u)) < 0)) - return r; - - u->sink->sample_spec.rate = u->old_rate; - - if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && ((r = unsuspend(u)) < 0)) - return r; - - break; - } - case PA_SINK_MESSAGE_GET_LATENCY: { pa_usec_t r = 0; @@ -1595,6 +1545,19 @@ static pa_bool_t sink_set_formats(pa_sink *s, pa_idxset *formats) { return TRUE; } +static pa_bool_t sink_update_rate_cb(pa_sink *s, uint32_t rate) +{ + struct userdata *u = s->userdata; + pa_assert(u); + + if (!PA_SINK_IS_OPENED(s->state)) { + pa_log_info("Updating rate for device %s, new rate is %d",u->device_name, rate); + u->sink->sample_spec.rate = rate; + return TRUE; + } + return FALSE; +} + static int process_rewind(struct userdata *u) { snd_pcm_sframes_t unused; size_t rewind_nbytes, unused_nbytes, limit_nbytes; @@ -1975,6 +1938,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca struct userdata *u = NULL; const char *dev_id = NULL; pa_sample_spec ss; + uint32_t alternate_sample_rate; pa_channel_map map; uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark, rewind_safeguard; snd_pcm_uframes_t period_frames, buffer_frames, tsched_frames; @@ -1993,6 +1957,12 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca goto fail; } + alternate_sample_rate = m->core->alternate_sample_rate; + if (pa_modargs_get_alternate_sample_rate(ma, &alternate_sample_rate) < 0) { + pa_log("Failed to parse alternate sample rate"); + goto fail; + } + frame_size = pa_frame_size(&ss); nfrags = m->core->default_n_fragments; @@ -2178,6 +2148,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca pa_sink_new_data_set_sample_spec(&data, &ss); pa_sink_new_data_set_channel_map(&data, &map); + pa_sink_new_data_set_alternate_sample_rate(&data, alternate_sample_rate); pa_alsa_init_proplist_pcm(m->core, data.proplist, u->pcm_handle); pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name); @@ -2230,6 +2201,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca u->sink->update_requested_latency = sink_update_requested_latency_cb; u->sink->set_state = sink_set_state_cb; u->sink->set_port = sink_set_port_cb; + u->sink->update_rate = sink_update_rate_cb; u->sink->userdata = u; pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c index 0766e11..c279429 100644 --- a/src/modules/alsa/alsa-source.c +++ b/src/modules/alsa/alsa-source.c @@ -1382,6 +1382,19 @@ static void source_update_requested_latency_cb(pa_source *s) { update_sw_params(u); } +static pa_bool_t source_update_rate_cb(pa_source *s, uint32_t rate) +{ + struct userdata *u = s->userdata; + pa_assert(u); + + if (!PA_SOURCE_IS_OPENED(s->state)) { + pa_log_info("Updating rate for device %s, new rate is %d", u->device_name, rate); + u->source->sample_spec.rate = rate; + return TRUE; + } + return FALSE; +} + static void thread_func(void *userdata) { struct userdata *u = userdata; unsigned short revents = 0; @@ -1674,6 +1687,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p struct userdata *u = NULL; const char *dev_id = NULL; pa_sample_spec ss; + uint32_t alternate_sample_rate; pa_channel_map map; uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark; snd_pcm_uframes_t period_frames, buffer_frames, tsched_frames; @@ -1692,6 +1706,12 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p goto fail; } + alternate_sample_rate = m->core->alternate_sample_rate; + if (pa_modargs_get_alternate_sample_rate(ma, &alternate_sample_rate) < 0) { + pa_log("Failed to parse alternate sample rate"); + goto fail; + } + frame_size = pa_frame_size(&ss); nfrags = m->core->default_n_fragments; @@ -1867,6 +1887,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p pa_source_new_data_set_sample_spec(&data, &ss); pa_source_new_data_set_channel_map(&data, &map); + pa_source_new_data_set_alternate_sample_rate(&data, alternate_sample_rate); pa_alsa_init_proplist_pcm(m->core, data.proplist, u->pcm_handle); pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name); @@ -1918,6 +1939,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p u->source->update_requested_latency = source_update_requested_latency_cb; u->source->set_state = source_set_state_cb; u->source->set_port = source_set_port_cb; + u->source->update_rate = source_update_rate_cb; u->source->userdata = u; pa_source_set_asyncmsgq(u->source, u->thread_mq.inq); diff --git a/src/modules/alsa/module-alsa-sink.c b/src/modules/alsa/module-alsa-sink.c index 2a558a1..019ccf0 100644 --- a/src/modules/alsa/module-alsa-sink.c +++ b/src/modules/alsa/module-alsa-sink.c @@ -45,6 +45,7 @@ PA_MODULE_USAGE( "device_id= " "format= " "rate= " + "alternate_rate= " "channels= " "channel_map= " "fragments= " @@ -69,6 +70,7 @@ static const char* const valid_modargs[] = { "device_id", "format", "rate", + "alternate_rate", "channels", "channel_map", "fragments", diff --git a/src/modules/alsa/module-alsa-source.c b/src/modules/alsa/module-alsa-source.c index 628e631..2d2c8b6 100644 --- a/src/modules/alsa/module-alsa-source.c +++ b/src/modules/alsa/module-alsa-source.c @@ -54,6 +54,7 @@ PA_MODULE_USAGE( "device_id= " "format= " "rate= " + "alternate_rate= " "channels= " "channel_map= " "fragments= " @@ -77,6 +78,7 @@ static const char* const valid_modargs[] = { "device_id", "format", "rate", + "alternate_rate", "channels", "channel_map", "fragments", -- 2.7.4