sound: update the volume-slider after getting a valid stream

In the ubuntu 20.04, we met an issue about the output volume-slider
on the machine with the legacy HDA audio driver, the output device
is the Speaker first (analog-stereo pa sink), then we connect a hdmi
monitor, the HDMI audio is in the output combo-box, we select the
hdmi audio (hdmi-stereo pa sink) from the combo-box, the hdmi audio
becomes the active output device now, we adjust the output volume from
the volume-slider, the slider UI is changed, but the output sound
is not changed with the UI.

The root cause is when the speaker is active, the pulseaudio only
keeps the analog-stereo sink, the sink hdmi-stereo is unlinked, when
users select the hdmi audio from UI, the pulseaudio will unlink
analo-stereo sink and create hdmi-stereo sink, but before hdmi-stereo
is created, the output_device_changed_cb() is called and
gvc_mixer_control_get_stream_from_device() returns a NULL since the
hdmi-stereo sink is not created yet in the pulseaudio. Because stream
is NULL, the output_volume_slider->stream is NULL, users can't change
the output volume via the volume-slider.

To fix it, we add a output_volume_slider->stream check in the
device_update_cb(), if it is NULL, get the stream and set it to
volume-slider. In this function, the sink hdmi-stereo is created
already, so the stream is not NULL. And this change also applies to
input as well.

Signed-off-by: Hui Wang <hui.wang@canonical.com>
This commit is contained in:
Hui Wang 2021-07-29 17:08:08 +08:00 committed by Robert Ancell
parent 28ae06207d
commit 0f18a662be
3 changed files with 47 additions and 10 deletions

View file

@ -91,18 +91,12 @@ allow_amplified_changed_cb (CcSoundPanel *self)
} }
static void static void
output_device_changed_cb (CcSoundPanel *self) set_output_stream (CcSoundPanel *self,
GvcMixerStream *stream)
{ {
GvcMixerUIDevice *device;
GvcMixerStream *stream = NULL;
GvcChannelMap *map = NULL; GvcChannelMap *map = NULL;
gboolean can_fade = FALSE, has_lfe = FALSE; gboolean can_fade = FALSE, has_lfe = FALSE;
device = cc_device_combo_box_get_device (self->output_device_combo_box);
if (device != NULL)
stream = gvc_mixer_control_get_stream_from_device (self->mixer_control, device);
cc_volume_slider_set_stream (self->output_volume_slider, stream, CC_STREAM_TYPE_OUTPUT); cc_volume_slider_set_stream (self->output_volume_slider, stream, CC_STREAM_TYPE_OUTPUT);
cc_level_bar_set_stream (self->output_level_bar, stream, CC_STREAM_TYPE_OUTPUT); cc_level_bar_set_stream (self->output_level_bar, stream, CC_STREAM_TYPE_OUTPUT);
@ -118,11 +112,33 @@ output_device_changed_cb (CcSoundPanel *self)
gtk_widget_set_visible (GTK_WIDGET (self->fade_row), can_fade); gtk_widget_set_visible (GTK_WIDGET (self->fade_row), can_fade);
gtk_widget_set_visible (GTK_WIDGET (self->subwoofer_row), has_lfe); gtk_widget_set_visible (GTK_WIDGET (self->subwoofer_row), has_lfe);
}
static void
output_device_changed_cb (CcSoundPanel *self)
{
GvcMixerUIDevice *device;
GvcMixerStream *stream = NULL;
device = cc_device_combo_box_get_device (self->output_device_combo_box);
if (device != NULL)
stream = gvc_mixer_control_get_stream_from_device (self->mixer_control, device);
set_output_stream (self, stream);
if (device != NULL) if (device != NULL)
gvc_mixer_control_change_output (self->mixer_control, device); gvc_mixer_control_change_output (self->mixer_control, device);
} }
static void
set_input_stream (CcSoundPanel *self,
GvcMixerStream *stream)
{
cc_volume_slider_set_stream (self->input_volume_slider, stream, CC_STREAM_TYPE_INPUT);
cc_level_bar_set_stream (self->input_level_bar, stream, CC_STREAM_TYPE_INPUT);
}
static void static void
input_device_changed_cb (CcSoundPanel *self) input_device_changed_cb (CcSoundPanel *self)
{ {
@ -134,8 +150,7 @@ input_device_changed_cb (CcSoundPanel *self)
if (device != NULL) if (device != NULL)
stream = gvc_mixer_control_get_stream_from_device (self->mixer_control, device); stream = gvc_mixer_control_get_stream_from_device (self->mixer_control, device);
cc_volume_slider_set_stream (self->input_volume_slider, stream, CC_STREAM_TYPE_INPUT); set_input_stream (self, stream);
cc_level_bar_set_stream (self->input_level_bar, stream, CC_STREAM_TYPE_INPUT);
if (device != NULL) if (device != NULL)
gvc_mixer_control_change_input (self->mixer_control, device); gvc_mixer_control_change_input (self->mixer_control, device);
@ -147,12 +162,18 @@ output_device_update_cb (CcSoundPanel *self,
{ {
GvcMixerUIDevice *device; GvcMixerUIDevice *device;
gboolean has_multi_profiles; gboolean has_multi_profiles;
GvcMixerStream *stream = NULL;
device = cc_device_combo_box_get_device (self->output_device_combo_box); device = cc_device_combo_box_get_device (self->output_device_combo_box);
cc_profile_combo_box_set_device (self->output_profile_combo_box, self->mixer_control, device); cc_profile_combo_box_set_device (self->output_profile_combo_box, self->mixer_control, device);
has_multi_profiles = (cc_profile_combo_box_get_profile_count (self->output_profile_combo_box) > 1); has_multi_profiles = (cc_profile_combo_box_get_profile_count (self->output_profile_combo_box) > 1);
gtk_widget_set_visible (GTK_WIDGET (self->output_profile_row), gtk_widget_set_visible (GTK_WIDGET (self->output_profile_row),
has_multi_profiles); has_multi_profiles);
if (cc_volume_slider_get_stream (self->output_volume_slider) == NULL)
stream = gvc_mixer_control_get_stream_from_device (self->mixer_control, device);
if (stream != NULL)
set_output_stream (self, stream);
} }
static void static void
@ -161,12 +182,18 @@ input_device_update_cb (CcSoundPanel *self,
{ {
GvcMixerUIDevice *device; GvcMixerUIDevice *device;
gboolean has_multi_profiles; gboolean has_multi_profiles;
GvcMixerStream *stream = NULL;
device = cc_device_combo_box_get_device (self->input_device_combo_box); device = cc_device_combo_box_get_device (self->input_device_combo_box);
cc_profile_combo_box_set_device (self->input_profile_combo_box, self->mixer_control, device); cc_profile_combo_box_set_device (self->input_profile_combo_box, self->mixer_control, device);
has_multi_profiles = (cc_profile_combo_box_get_profile_count (self->input_profile_combo_box) > 1); has_multi_profiles = (cc_profile_combo_box_get_profile_count (self->input_profile_combo_box) > 1);
gtk_widget_set_visible (GTK_WIDGET (self->input_profile_row), gtk_widget_set_visible (GTK_WIDGET (self->input_profile_row),
has_multi_profiles); has_multi_profiles);
if (cc_volume_slider_get_stream (self->input_volume_slider) == NULL)
stream = gvc_mixer_control_get_stream_from_device (self->mixer_control, device);
if (stream != NULL)
set_input_stream (self, stream);
} }
static void static void

View file

@ -247,6 +247,14 @@ cc_volume_slider_set_stream (CcVolumeSlider *self,
} }
} }
GvcMixerStream *
cc_volume_slider_get_stream (CcVolumeSlider *self)
{
g_return_val_if_fail (CC_IS_VOLUME_SLIDER (self), NULL);
return self->stream;
}
void void
cc_volume_slider_set_is_amplified (CcVolumeSlider *self, cc_volume_slider_set_is_amplified (CcVolumeSlider *self,
gboolean is_amplified) gboolean is_amplified)

View file

@ -40,4 +40,6 @@ void cc_volume_slider_set_stream (CcVolumeSlider *slider,
void cc_volume_slider_set_is_amplified (CcVolumeSlider *slider, void cc_volume_slider_set_is_amplified (CcVolumeSlider *slider,
gboolean is_amplified); gboolean is_amplified);
GvcMixerStream *cc_volume_slider_get_stream (CcVolumeSlider *slider);
G_END_DECLS G_END_DECLS