mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-03 09:01:50 -05:00
alsa: Reinitialise the mixer on port change.
This allows us to flip from software to hardware volume control as the port's mixer path dictates.
This commit is contained in:
parent
a9cf320bc1
commit
6c6b50d6a8
11 changed files with 315 additions and 120 deletions
|
|
@ -130,7 +130,7 @@ struct userdata {
|
|||
char *device_name; /* name of the PCM device */
|
||||
char *control_device; /* name of the control device */
|
||||
|
||||
pa_bool_t use_mmap:1, use_tsched:1;
|
||||
pa_bool_t use_mmap:1, use_tsched:1, sync_volume:1;
|
||||
|
||||
pa_bool_t first, after_rewind;
|
||||
|
||||
|
|
@ -1372,6 +1372,55 @@ static void sink_set_mute_cb(pa_sink *s) {
|
|||
pa_alsa_path_set_mute(u->mixer_path, u->mixer_handle, s->muted);
|
||||
}
|
||||
|
||||
static void mixer_volume_init(struct userdata *u) {
|
||||
pa_assert(u);
|
||||
|
||||
if (!u->mixer_path->has_volume) {
|
||||
pa_sink_set_write_volume_callback(u->sink, NULL);
|
||||
pa_sink_set_get_volume_callback(u->sink, NULL);
|
||||
pa_sink_set_set_volume_callback(u->sink, NULL);
|
||||
|
||||
pa_log_info("Driver does not support hardware volume control, falling back to software volume control.");
|
||||
} else {
|
||||
pa_sink_set_get_volume_callback(u->sink, sink_get_volume_cb);
|
||||
pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb);
|
||||
|
||||
if (u->mixer_path->has_dB && u->sync_volume) {
|
||||
pa_sink_set_write_volume_callback(u->sink, sink_write_volume_cb);
|
||||
pa_log_info("Successfully enabled synchronous volume.");
|
||||
} else
|
||||
pa_sink_set_write_volume_callback(u->sink, NULL);
|
||||
|
||||
if (u->mixer_path->has_dB) {
|
||||
pa_sink_enable_decibel_volume(u->sink, TRUE);
|
||||
pa_log_info("Hardware volume ranges from %0.2f dB to %0.2f dB.", u->mixer_path->min_dB, u->mixer_path->max_dB);
|
||||
|
||||
u->sink->base_volume = pa_sw_volume_from_dB(-u->mixer_path->max_dB);
|
||||
u->sink->n_volume_steps = PA_VOLUME_NORM+1;
|
||||
|
||||
pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(u->sink->base_volume));
|
||||
} else {
|
||||
pa_sink_enable_decibel_volume(u->sink, FALSE);
|
||||
pa_log_info("Hardware volume ranges from %li to %li.", u->mixer_path->min_volume, u->mixer_path->max_volume);
|
||||
|
||||
u->sink->base_volume = PA_VOLUME_NORM;
|
||||
u->sink->n_volume_steps = u->mixer_path->max_volume - u->mixer_path->min_volume + 1;
|
||||
}
|
||||
|
||||
pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->mixer_path->has_dB ? "supported" : "not supported");
|
||||
}
|
||||
|
||||
if (!u->mixer_path->has_mute) {
|
||||
pa_sink_set_get_mute_callback(u->sink, NULL);
|
||||
pa_sink_set_set_mute_callback(u->sink, NULL);
|
||||
pa_log_info("Driver does not support hardware mute control, falling back to software mute control.");
|
||||
} else {
|
||||
pa_sink_set_get_mute_callback(u->sink, sink_get_mute_cb);
|
||||
pa_sink_set_set_mute_callback(u->sink, sink_set_mute_cb);
|
||||
pa_log_info("Using hardware mute control.");
|
||||
}
|
||||
}
|
||||
|
||||
static int sink_set_port_cb(pa_sink *s, pa_device_port *p) {
|
||||
struct userdata *u = s->userdata;
|
||||
pa_alsa_port_data *data;
|
||||
|
|
@ -1385,15 +1434,7 @@ static int sink_set_port_cb(pa_sink *s, pa_device_port *p) {
|
|||
pa_assert_se(u->mixer_path = data->path);
|
||||
pa_alsa_path_select(u->mixer_path, u->mixer_handle);
|
||||
|
||||
if (u->mixer_path->has_volume && u->mixer_path->has_dB) {
|
||||
s->base_volume = pa_sw_volume_from_dB(-u->mixer_path->max_dB);
|
||||
s->n_volume_steps = PA_VOLUME_NORM+1;
|
||||
|
||||
pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(s->base_volume));
|
||||
} else {
|
||||
s->base_volume = PA_VOLUME_NORM;
|
||||
s->n_volume_steps = u->mixer_path->max_volume - u->mixer_path->min_volume + 1;
|
||||
}
|
||||
mixer_volume_init(u);
|
||||
|
||||
if (data->setting)
|
||||
pa_alsa_setting_select(data->setting, u->mixer_handle);
|
||||
|
|
@ -1723,7 +1764,10 @@ fail:
|
|||
}
|
||||
}
|
||||
|
||||
static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB, pa_bool_t sync_volume) {
|
||||
|
||||
static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) {
|
||||
pa_bool_t need_mixer_callback = FALSE;
|
||||
|
||||
pa_assert(u);
|
||||
|
||||
if (!u->mixer_handle)
|
||||
|
|
@ -1759,47 +1803,21 @@ static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB, pa_bool_t sync_v
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!u->mixer_path->has_volume) {
|
||||
pa_log_info("Driver does not support hardware volume control, falling back to software volume control.");
|
||||
} else {
|
||||
mixer_volume_init(u);
|
||||
|
||||
if (u->mixer_path->has_dB) {
|
||||
pa_log_info("Hardware volume ranges from %0.2f dB to %0.2f dB.", u->mixer_path->min_dB, u->mixer_path->max_dB);
|
||||
/* Will we need to register callbacks? */
|
||||
if (u->mixer_path_set && u->mixer_path_set->paths) {
|
||||
pa_alsa_path *p;
|
||||
|
||||
u->sink->base_volume = pa_sw_volume_from_dB(-u->mixer_path->max_dB);
|
||||
u->sink->n_volume_steps = PA_VOLUME_NORM+1;
|
||||
|
||||
pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(u->sink->base_volume));
|
||||
|
||||
} else {
|
||||
pa_log_info("Hardware volume ranges from %li to %li.", u->mixer_path->min_volume, u->mixer_path->max_volume);
|
||||
u->sink->base_volume = PA_VOLUME_NORM;
|
||||
u->sink->n_volume_steps = u->mixer_path->max_volume - u->mixer_path->min_volume + 1;
|
||||
PA_LLIST_FOREACH(p, u->mixer_path_set->paths) {
|
||||
if (p->has_volume || p->has_mute)
|
||||
need_mixer_callback = TRUE;
|
||||
}
|
||||
|
||||
pa_sink_set_get_volume_callback(u->sink, sink_get_volume_cb);
|
||||
pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb);
|
||||
|
||||
if (u->mixer_path->has_dB) {
|
||||
u->sink->flags |= PA_SINK_DECIBEL_VOLUME;
|
||||
if (sync_volume) {
|
||||
pa_sink_set_write_volume_callback(u->sink, sink_write_volume_cb);
|
||||
pa_log_info("Successfully enabled synchronous volume.");
|
||||
}
|
||||
}
|
||||
|
||||
pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->mixer_path->has_dB ? "supported" : "not supported");
|
||||
}
|
||||
else if (u->mixer_path)
|
||||
need_mixer_callback = u->mixer_path->has_volume || u->mixer_path->has_mute;
|
||||
|
||||
if (!u->mixer_path->has_mute) {
|
||||
pa_log_info("Driver does not support hardware mute control, falling back to software mute control.");
|
||||
} else {
|
||||
pa_sink_set_get_mute_callback(u->sink, sink_get_mute_cb);
|
||||
pa_sink_set_set_mute_callback(u->sink, sink_set_mute_cb);
|
||||
pa_log_info("Using hardware mute control.");
|
||||
}
|
||||
|
||||
if (u->mixer_path->has_volume || u->mixer_path->has_mute) {
|
||||
if (need_mixer_callback) {
|
||||
int (*mixer_callback)(snd_mixer_elem_t *, unsigned int);
|
||||
if (u->sink->flags & PA_SINK_SYNC_VOLUME) {
|
||||
u->mixer_pd = pa_alsa_mixer_pdata_new();
|
||||
|
|
@ -1909,6 +1927,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
u->module = m;
|
||||
u->use_mmap = use_mmap;
|
||||
u->use_tsched = use_tsched;
|
||||
u->sync_volume = sync_volume;
|
||||
u->first = TRUE;
|
||||
u->rewind_safeguard = rewind_safeguard;
|
||||
u->rtpoll = pa_rtpoll_new();
|
||||
|
|
@ -2133,7 +2152,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
|
|||
if (update_sw_params(u) < 0)
|
||||
goto fail;
|
||||
|
||||
if (setup_mixer(u, ignore_dB, sync_volume) < 0)
|
||||
if (setup_mixer(u, ignore_dB) < 0)
|
||||
goto fail;
|
||||
|
||||
pa_alsa_dump(PA_LOG_DEBUG, u->pcm_handle);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue