mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-04 13:29:59 -05:00
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 <pierre-louis.bossart@linux.intel.com>
This commit is contained in:
parent
f0ec495938
commit
b232fbd8f8
4 changed files with 48 additions and 50 deletions
|
|
@ -1121,56 +1121,6 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
|
||||||
|
|
||||||
switch (code) {
|
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: {
|
case PA_SINK_MESSAGE_GET_LATENCY: {
|
||||||
pa_usec_t r = 0;
|
pa_usec_t r = 0;
|
||||||
|
|
||||||
|
|
@ -1595,6 +1545,19 @@ static pa_bool_t sink_set_formats(pa_sink *s, pa_idxset *formats) {
|
||||||
return TRUE;
|
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) {
|
static int process_rewind(struct userdata *u) {
|
||||||
snd_pcm_sframes_t unused;
|
snd_pcm_sframes_t unused;
|
||||||
size_t rewind_nbytes, unused_nbytes, limit_nbytes;
|
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;
|
struct userdata *u = NULL;
|
||||||
const char *dev_id = NULL;
|
const char *dev_id = NULL;
|
||||||
pa_sample_spec ss;
|
pa_sample_spec ss;
|
||||||
|
uint32_t alternate_sample_rate;
|
||||||
pa_channel_map map;
|
pa_channel_map map;
|
||||||
uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark, rewind_safeguard;
|
uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark, rewind_safeguard;
|
||||||
snd_pcm_uframes_t period_frames, buffer_frames, tsched_frames;
|
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;
|
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);
|
frame_size = pa_frame_size(&ss);
|
||||||
|
|
||||||
nfrags = m->core->default_n_fragments;
|
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_sample_spec(&data, &ss);
|
||||||
pa_sink_new_data_set_channel_map(&data, &map);
|
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_alsa_init_proplist_pcm(m->core, data.proplist, u->pcm_handle);
|
||||||
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
|
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->update_requested_latency = sink_update_requested_latency_cb;
|
||||||
u->sink->set_state = sink_set_state_cb;
|
u->sink->set_state = sink_set_state_cb;
|
||||||
u->sink->set_port = sink_set_port_cb;
|
u->sink->set_port = sink_set_port_cb;
|
||||||
|
u->sink->update_rate = sink_update_rate_cb;
|
||||||
u->sink->userdata = u;
|
u->sink->userdata = u;
|
||||||
|
|
||||||
pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
|
pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
|
||||||
|
|
|
||||||
|
|
@ -1382,6 +1382,19 @@ static void source_update_requested_latency_cb(pa_source *s) {
|
||||||
update_sw_params(u);
|
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) {
|
static void thread_func(void *userdata) {
|
||||||
struct userdata *u = userdata;
|
struct userdata *u = userdata;
|
||||||
unsigned short revents = 0;
|
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;
|
struct userdata *u = NULL;
|
||||||
const char *dev_id = NULL;
|
const char *dev_id = NULL;
|
||||||
pa_sample_spec ss;
|
pa_sample_spec ss;
|
||||||
|
uint32_t alternate_sample_rate;
|
||||||
pa_channel_map map;
|
pa_channel_map map;
|
||||||
uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark;
|
uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark;
|
||||||
snd_pcm_uframes_t period_frames, buffer_frames, tsched_frames;
|
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;
|
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);
|
frame_size = pa_frame_size(&ss);
|
||||||
|
|
||||||
nfrags = m->core->default_n_fragments;
|
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_sample_spec(&data, &ss);
|
||||||
pa_source_new_data_set_channel_map(&data, &map);
|
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_alsa_init_proplist_pcm(m->core, data.proplist, u->pcm_handle);
|
||||||
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
|
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->update_requested_latency = source_update_requested_latency_cb;
|
||||||
u->source->set_state = source_set_state_cb;
|
u->source->set_state = source_set_state_cb;
|
||||||
u->source->set_port = source_set_port_cb;
|
u->source->set_port = source_set_port_cb;
|
||||||
|
u->source->update_rate = source_update_rate_cb;
|
||||||
u->source->userdata = u;
|
u->source->userdata = u;
|
||||||
|
|
||||||
pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
|
pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ PA_MODULE_USAGE(
|
||||||
"device_id=<ALSA card index> "
|
"device_id=<ALSA card index> "
|
||||||
"format=<sample format> "
|
"format=<sample format> "
|
||||||
"rate=<sample rate> "
|
"rate=<sample rate> "
|
||||||
|
"alternate_rate=<alternate sample rate> "
|
||||||
"channels=<number of channels> "
|
"channels=<number of channels> "
|
||||||
"channel_map=<channel map> "
|
"channel_map=<channel map> "
|
||||||
"fragments=<number of fragments> "
|
"fragments=<number of fragments> "
|
||||||
|
|
@ -69,6 +70,7 @@ static const char* const valid_modargs[] = {
|
||||||
"device_id",
|
"device_id",
|
||||||
"format",
|
"format",
|
||||||
"rate",
|
"rate",
|
||||||
|
"alternate_rate",
|
||||||
"channels",
|
"channels",
|
||||||
"channel_map",
|
"channel_map",
|
||||||
"fragments",
|
"fragments",
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ PA_MODULE_USAGE(
|
||||||
"device_id=<ALSA card index> "
|
"device_id=<ALSA card index> "
|
||||||
"format=<sample format> "
|
"format=<sample format> "
|
||||||
"rate=<sample rate> "
|
"rate=<sample rate> "
|
||||||
|
"alternate_rate=<alternate sample rate> "
|
||||||
"channels=<number of channels> "
|
"channels=<number of channels> "
|
||||||
"channel_map=<channel map> "
|
"channel_map=<channel map> "
|
||||||
"fragments=<number of fragments> "
|
"fragments=<number of fragments> "
|
||||||
|
|
@ -77,6 +78,7 @@ static const char* const valid_modargs[] = {
|
||||||
"device_id",
|
"device_id",
|
||||||
"format",
|
"format",
|
||||||
"rate",
|
"rate",
|
||||||
|
"alternate_rate",
|
||||||
"channels",
|
"channels",
|
||||||
"channel_map",
|
"channel_map",
|
||||||
"fragments",
|
"fragments",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue