Arun Raghavan pushed to branch master at PulseAudio / pavucontrol
Commits:
f52656b1 by Arun Raghavan at 2026-01-23T12:55:27-08:00
Expose a setting for forcing mono audio
Requires libpulse with message support, and pipewire-pulse from 1.4.10
or 1.6.
- - - - -
4 changed files:
- src/mainwindow.cc
- src/mainwindow.h
- src/mainwindow.ui
- src/pavucontrol.cc
Changes:
=====================================
src/mainwindow.cc
=====================================
@@ -98,6 +98,8 @@ MainWindow::MainWindow(BaseObjectType* cobject, const
Glib::RefPtr<Gtk::Builder>
notebook = x->get_widget<Gtk::Notebook>("notebook");
showVolumeMetersCheckButton =
x->get_widget<Gtk::CheckButton>("showVolumeMetersCheckButton");
hideUnavailableCardProfilesCheckButton =
x->get_widget<Gtk::CheckButton>("hideUnavailableCardProfilesCheckButton");
+ monoAudioLabel = x->get_widget<Gtk::Label>("monoAudioLabel");
+ monoAudioSwitch = x->get_widget<Gtk::Switch>("monoAudioSwitch");
sinkInputTypeComboBox->set_active((int) showSinkInputType);
sourceOutputTypeComboBox->set_active((int) showSourceOutputType);
@@ -111,6 +113,10 @@ MainWindow::MainWindow(BaseObjectType* cobject, const
Glib::RefPtr<Gtk::Builder>
showVolumeMetersCheckButton->signal_toggled().connect(sigc::mem_fun(*this,
&MainWindow::onShowVolumeMetersCheckButtonToggled));
hideUnavailableCardProfilesCheckButton->signal_toggled().connect(sigc::mem_fun(*this,
&MainWindow::onHideUnavailableCardProfilesCheckButtonToggled));
+#if HAVE_PULSE_MESSAGING_API
+ monoAudioSwitch->signal_state_set().connect(sigc::mem_fun(*this,
&MainWindow::onMonoAudioStateSet), false);
+#endif
+
auto event_controller_key = Gtk::EventControllerKey::create();
event_controller_key->signal_key_pressed().connect(sigc::mem_fun(*this,
&MainWindow::on_key_press_event), false);
this->add_controller(event_controller_key);
@@ -1475,3 +1481,15 @@ void
MainWindow::onHideUnavailableCardProfilesCheckButtonToggled() {
cw->prepareMenu();
}
}
+
+bool MainWindow::onMonoAudioStateSet(bool state) {
+ pa_context *c = get_context();
+ pa_operation *o;
+ const char *value = state ? "true" : "false";
+
+ o = pa_context_send_message_to_object(c, "/core",
"pipewire-pulse:force-mono-output", value, NULL, NULL);
+ if (o)
+ pa_operation_unref(o);
+
+ return false;
+}
=====================================
src/mainwindow.h
=====================================
@@ -91,6 +91,8 @@ class MainWindow : public Gtk::Window {
*sinkTypeComboBox, *sourceTypeComboBox;
Gtk::CheckButton *showVolumeMetersCheckButton,
*hideUnavailableCardProfilesCheckButton;
+ Gtk::Label *monoAudioLabel;
+ Gtk::Switch *monoAudioSwitch;
std::map<uint32_t, CardWidget *> cardWidgets;
std::map<uint32_t, SinkWidget *> sinkWidgets;
@@ -110,6 +112,7 @@ class MainWindow : public Gtk::Window {
virtual void onSourceTypeComboBoxChanged();
virtual void onShowVolumeMetersCheckButtonToggled();
virtual void onHideUnavailableCardProfilesCheckButtonToggled();
+ virtual bool onMonoAudioStateSet(bool);
void setConnectionState(gboolean connected);
void updateDeviceVisibility();
=====================================
src/mainwindow.ui
=====================================
@@ -405,6 +405,37 @@
<property name="child">
<object class="GtkBox">
<property
name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="optionsBox">
+ <property
name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <property name="margin-top">18</property>
+ <property
name="margin-bottom">18</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <child>
+ <object class="GtkBox" id="monoAudioBox">
+ <property
name="orientation">horizontal</property>
+ <property name="spacing">12</property>
+ <property name="tooltip-text">Requires
PipeWire 1.4.10 or later</property>
+ <child>
+ <object class="GtkSwitch"
id="monoAudioSwitch">
+ <property
name="sensitive">false</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel"
id="monoAudioLabel">
+ <property name="label"
translatable="yes">Configure all output devices as mono</property>
+ <property
name="sensitive">false</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparator"/>
+ </child>
<child>
<object class="GtkBox" id="cardsVBox">
<property name="vexpand">1</property>
=====================================
src/pavucontrol.cc
=====================================
@@ -613,6 +613,19 @@ static void ext_device_manager_subscribe_cb(pa_context *c,
void *userdata) {
pa_operation_unref(o);
}
+static void probe_force_mono_output_cb(pa_context *c, int success, char
*response, void *userdata)
+{
+ MainWindow *w = static_cast<MainWindow*>(userdata);
+
+ if (success && response && strcmp(response, "null") != 0) {
+ /* We know the setting is supported */
+ w->monoAudioLabel->set_sensitive(true);
+ w->monoAudioSwitch->set_sensitive(true);
+ }
+
+ dec_outstanding(w);
+}
+
void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t
index, void *userdata) {
MainWindow *w = static_cast<MainWindow*>(userdata);
@@ -838,6 +851,12 @@ void context_state_callback(pa_context *c, void *userdata)
{
} else
g_debug(_("Failed to initialize device manager extension:
%s"), pa_strerror(pa_context_errno(context)));
+#if HAVE_PULSE_MESSAGING_API
+ if ((o = pa_context_send_message_to_object(c, "/core",
"pipewire-pulse:force-mono-output", NULL, probe_force_mono_output_cb, w))) {
+ n_outstanding++;
+ } else
+ g_debug(_("Failed to check if we can force mono audio: %s"),
pa_strerror(pa_context_errno(context)));
+#endif
break;
}
View it on GitLab:
https://gitlab.freedesktop.org/pulseaudio/pavucontrol/-/commit/f52656b10e713bd27e443e2d82547975c35df0ed
--
View it on GitLab:
https://gitlab.freedesktop.org/pulseaudio/pavucontrol/-/commit/f52656b10e713bd27e443e2d82547975c35df0ed
You're receiving this email because of your account on gitlab.freedesktop.org.