[pulseaudio-commits] src/mainwindow.cc src/pavucontrol.glade src/rolewidget.cc src/sinkinputwidget.cc src/sinkinputwidget.h src/sourceoutputwidget.cc src/sourceoutputwidget.h src/streamwidget.cc src/streamwidget.h

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Nov 27 19:55:08 UTC 2019


 src/mainwindow.cc         |   18 ++++++++---
 src/pavucontrol.glade     |    6 ---
 src/rolewidget.cc         |    2 -
 src/sinkinputwidget.cc    |   75 +++++++++++++++++-----------------------------
 src/sinkinputwidget.h     |   26 +--------------
 src/sourceoutputwidget.cc |   75 +++++++++++++++++-----------------------------
 src/sourceoutputwidget.h  |   26 +--------------
 src/streamwidget.cc       |    9 ++---
 src/streamwidget.h        |    7 +++-
 9 files changed, 86 insertions(+), 158 deletions(-)

New commits:
commit ae278b8643cf1089f66df18713c8154208d9a505
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Fri Sep 6 11:32:12 2019 +0300

    streamwidget: Use a drop-down list instead of a button and a popup for selecting the device
    
    This looks better, requires less code and probably fixes
    https://gitlab.freedesktop.org/pulseaudio/pavucontrol/issues/63

diff --git a/src/mainwindow.cc b/src/mainwindow.cc
index 459ebbb..a402945 100644
--- a/src/mainwindow.cc
+++ b/src/mainwindow.cc
@@ -1084,12 +1084,15 @@ void MainWindow::reallyUpdateDeviceVisibility() {
     for (std::map<uint32_t, SinkInputWidget*>::iterator i = sinkInputWidgets.begin(); i != sinkInputWidgets.end(); ++i) {
         SinkInputWidget* w = i->second;
 
+        w->updating = true;
+        w->updateDeviceComboBox();
+
         if (sinkWidgets.size() > 1) {
             w->directionLabel->show();
-            w->deviceButton->show();
+            w->deviceComboBox->show();
         } else {
             w->directionLabel->hide();
-            w->deviceButton->hide();
+            w->deviceComboBox->hide();
         }
 
         if (showSinkInputType == SINK_INPUT_ALL || w->type == showSinkInputType) {
@@ -1097,6 +1100,8 @@ void MainWindow::reallyUpdateDeviceVisibility() {
             is_empty = false;
         } else
             w->hide();
+
+        w->updating = false;
     }
 
     if (eventRoleWidget)
@@ -1112,12 +1117,15 @@ void MainWindow::reallyUpdateDeviceVisibility() {
     for (std::map<uint32_t, SourceOutputWidget*>::iterator i = sourceOutputWidgets.begin(); i != sourceOutputWidgets.end(); ++i) {
         SourceOutputWidget* w = i->second;
 
+        w->updating = true;
+        w->updateDeviceComboBox();
+
         if (sourceWidgets.size() > 1) {
             w->directionLabel->show();
-            w->deviceButton->show();
+            w->deviceComboBox->show();
         } else {
             w->directionLabel->hide();
-            w->deviceButton->hide();
+            w->deviceComboBox->hide();
         }
 
         if (showSourceOutputType == SOURCE_OUTPUT_ALL || w->type == showSourceOutputType) {
@@ -1125,6 +1133,8 @@ void MainWindow::reallyUpdateDeviceVisibility() {
             is_empty = false;
         } else
             w->hide();
+
+        w->updating = false;
     }
 
     if (is_empty)
diff --git a/src/pavucontrol.glade b/src/pavucontrol.glade
index a66e193..fe6c635 100644
--- a/src/pavucontrol.glade
+++ b/src/pavucontrol.glade
@@ -1496,13 +1496,9 @@
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkButton" id="deviceButton">
-                            <property name="label" translatable="yes">Device</property>
+                          <object class="GtkComboBoxText" id="deviceComboBox">
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
-                            <property name="receives_default">True</property>
-                            <property name="relief">half</property>
-                            <property name="xalign">0</property>
                           </object>
                           <packing>
                             <property name="expand">False</property>
diff --git a/src/rolewidget.cc b/src/rolewidget.cc
index db07f92..7f755aa 100644
--- a/src/rolewidget.cc
+++ b/src/rolewidget.cc
@@ -33,7 +33,7 @@ RoleWidget::RoleWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
 
     lockToggleButton->hide();
     directionLabel->hide();
-    deviceButton->hide();
+    deviceComboBox->hide();
 }
 
 RoleWidget* RoleWidget::create() {
diff --git a/src/sinkinputwidget.cc b/src/sinkinputwidget.cc
index 5a0ba39..ff086d6 100644
--- a/src/sinkinputwidget.cc
+++ b/src/sinkinputwidget.cc
@@ -44,28 +44,42 @@ SinkInputWidget* SinkInputWidget::create(MainWindow* mainWindow) {
     x->get_widget_derived("streamWidget", w);
     w->init(mainWindow);
     w->reference();
+
     return w;
 }
 
 SinkInputWidget::~SinkInputWidget(void) {
-    clearMenu();
 }
 
 void SinkInputWidget::setSinkIndex(uint32_t idx) {
     mSinkIndex = idx;
-
-    if (mpMainWindow->sinkWidgets.count(idx)) {
-        SinkWidget *w = mpMainWindow->sinkWidgets[idx];
-        deviceButton->set_label(w->description.c_str());
-    }
-    else
-        deviceButton->set_label(_("Unknown output"));
+    updateDeviceComboBox();
 }
 
 uint32_t SinkInputWidget::sinkIndex() {
     return mSinkIndex;
 }
 
+void SinkInputWidget::updateDeviceComboBox() {
+    Glib::ustring currentSinkName = UNKNOWN_DEVICE_NAME;
+
+    deviceComboBox->remove_all();
+
+    for (auto i = mpMainWindow->sinkWidgets.begin(); i != mpMainWindow->sinkWidgets.end(); i++) {
+        SinkWidget *sink = i->second;
+
+        deviceComboBox->append(sink->name, sink->description);
+
+        if (sink->index == mSinkIndex)
+            currentSinkName = sink->name;
+    }
+
+    if (currentSinkName == UNKNOWN_DEVICE_NAME)
+        deviceComboBox->append(UNKNOWN_DEVICE_NAME, _("Unknown output"));
+
+    deviceComboBox->set_active_id(currentSinkName);
+}
+
 void SinkInputWidget::executeVolumeUpdate() {
     pa_operation* o;
 
@@ -102,44 +116,13 @@ void SinkInputWidget::onKill() {
     pa_operation_unref(o);
 }
 
-void SinkInputWidget::clearMenu() {
-  while (!sinkMenuItems.empty()) {
-    std::map<uint32_t, SinkMenuItem*>::iterator i = sinkMenuItems.begin();
-    delete i->second;
-    sinkMenuItems.erase(i);
-  }
-}
-
-void SinkInputWidget::buildMenu() {
-  for (std::map<uint32_t, SinkWidget*>::iterator i = mpMainWindow->sinkWidgets.begin(); i != mpMainWindow->sinkWidgets.end(); ++i) {
-    SinkMenuItem *m;
-    sinkMenuItems[i->second->index] = m = new SinkMenuItem(this, i->second->description.c_str(), i->second->index, i->second->index == mSinkIndex);
-    menu.append(m->menuItem);
-  }
-  menu.show_all();
-}
-
-void SinkInputWidget::SinkMenuItem::onToggle() {
-  if (widget->updating)
-    return;
-
-  if (!menuItem.get_active())
-    return;
-
-  /*if (!mpMainWindow->sinkWidgets.count(widget->index))
-    return;*/
-
-  pa_operation* o;
-  if (!(o = pa_context_move_sink_input_by_index(get_context(), widget->index, index, NULL, NULL))) {
-    show_error(_("pa_context_move_sink_input_by_index() failed"));
-    return;
-  }
+void SinkInputWidget::onDeviceComboBoxChanged() {
+    if (updating)
+        return;
 
-  pa_operation_unref(o);
-}
+    Glib::ustring sinkName = deviceComboBox->get_active_id();
 
-void SinkInputWidget::onDeviceChangePopup() {
-    clearMenu();
-    buildMenu();
-    menu.popup(1, 0);
+    pa_operation *o = pa_context_move_sink_input_by_name(get_context(), index, sinkName.c_str(), NULL, NULL);
+    if (o)
+        pa_operation_unref(o);
 }
diff --git a/src/sinkinputwidget.h b/src/sinkinputwidget.h
index 368dde0..af40d03 100644
--- a/src/sinkinputwidget.h
+++ b/src/sinkinputwidget.h
@@ -38,36 +38,14 @@ public:
     uint32_t index, clientIndex;
     void setSinkIndex(uint32_t idx);
     uint32_t sinkIndex();
+    void updateDeviceComboBox();
     virtual void executeVolumeUpdate();
     virtual void onMuteToggleButton();
-    virtual void onDeviceChangePopup();
     virtual void onKill();
+    virtual void onDeviceComboBoxChanged();
 
 private:
     uint32_t mSinkIndex;
-
-    void clearMenu();
-    void buildMenu();
-
-    Gtk::Menu menu;
-
-    struct SinkMenuItem {
-      SinkMenuItem(SinkInputWidget *w, const char *label, uint32_t i, bool active) :
-      widget(w),
-      menuItem(label),
-      index(i) {
-        menuItem.set_active(active);
-        menuItem.set_draw_as_radio(true);
-        menuItem.signal_toggled().connect(sigc::mem_fun(*this, &SinkMenuItem::onToggle));
-      }
-
-      SinkInputWidget *widget;
-      Gtk::CheckMenuItem menuItem;
-      uint32_t index;
-      void onToggle();
-    };
-
-    std::map<uint32_t, SinkMenuItem*> sinkMenuItems;
 };
 
 #endif
diff --git a/src/sourceoutputwidget.cc b/src/sourceoutputwidget.cc
index 4d915b0..1c2e762 100644
--- a/src/sourceoutputwidget.cc
+++ b/src/sourceoutputwidget.cc
@@ -54,24 +54,37 @@ SourceOutputWidget* SourceOutputWidget::create(MainWindow* mainWindow) {
 }
 
 SourceOutputWidget::~SourceOutputWidget(void) {
-  clearMenu();
 }
 
 void SourceOutputWidget::setSourceIndex(uint32_t idx) {
     mSourceIndex = idx;
-
-    if (mpMainWindow->sourceWidgets.count(idx)) {
-      SourceWidget *w = mpMainWindow->sourceWidgets[idx];
-      deviceButton->set_label(w->description.c_str());
-    }
-    else
-      deviceButton->set_label(_("Unknown input"));
+    updateDeviceComboBox();
 }
 
 uint32_t SourceOutputWidget::sourceIndex() {
     return mSourceIndex;
 }
 
+void SourceOutputWidget::updateDeviceComboBox() {
+    Glib::ustring currentSourceName = UNKNOWN_DEVICE_NAME;
+
+    deviceComboBox->remove_all();
+
+    for (auto i = mpMainWindow->sourceWidgets.begin(); i != mpMainWindow->sourceWidgets.end(); i++) {
+        SourceWidget *source = i->second;
+
+        deviceComboBox->append(source->name, source->description);
+
+        if (source->index == mSourceIndex)
+            currentSourceName = source->name;
+    }
+
+    if (currentSourceName == UNKNOWN_DEVICE_NAME)
+        deviceComboBox->append(UNKNOWN_DEVICE_NAME, _("Unknown input"));
+
+    deviceComboBox->set_active_id(currentSourceName);
+}
+
 #if HAVE_SOURCE_OUTPUT_VOLUMES
 void SourceOutputWidget::executeVolumeUpdate() {
     pa_operation* o;
@@ -110,45 +123,13 @@ void SourceOutputWidget::onKill() {
     pa_operation_unref(o);
 }
 
+void SourceOutputWidget::onDeviceComboBoxChanged() {
+    if (updating)
+        return;
 
-void SourceOutputWidget::clearMenu() {
-  while (!sourceMenuItems.empty()) {
-    std::map<uint32_t, SourceMenuItem*>::iterator i = sourceMenuItems.begin();
-    delete i->second;
-    sourceMenuItems.erase(i);
-  }
-}
-
-void SourceOutputWidget::buildMenu() {
-  for (std::map<uint32_t, SourceWidget*>::iterator i = mpMainWindow->sourceWidgets.begin(); i != mpMainWindow->sourceWidgets.end(); ++i) {
-    SourceMenuItem *m;
-    sourceMenuItems[i->second->index] = m = new SourceMenuItem(this, i->second->description.c_str(), i->second->index, i->second->index == mSourceIndex);
-    menu.append(m->menuItem);
-  }
-  menu.show_all();
-}
-
-void SourceOutputWidget::SourceMenuItem::onToggle() {
-  if (widget->updating)
-    return;
-
-  if (!menuItem.get_active())
-    return;
-
-  /*if (!mpMainWindow->sourceWidgets.count(widget->index))
-    return;*/
-
-  pa_operation* o;
-  if (!(o = pa_context_move_source_output_by_index(get_context(), widget->index, index, NULL, NULL))) {
-    show_error(_("pa_context_move_source_output_by_index() failed"));
-    return;
-  }
-
-  pa_operation_unref(o);
-}
+    Glib::ustring sourceName = deviceComboBox->get_active_id();
 
-void SourceOutputWidget::onDeviceChangePopup() {
-    clearMenu();
-    buildMenu();
-    menu.popup(1, 0);
+    pa_operation *o = pa_context_move_source_output_by_name(get_context(), index, sourceName.c_str(), NULL, NULL);
+    if (o)
+        pa_operation_unref(o);
 }
diff --git a/src/sourceoutputwidget.h b/src/sourceoutputwidget.h
index 1b9ab0f..5edd438 100644
--- a/src/sourceoutputwidget.h
+++ b/src/sourceoutputwidget.h
@@ -38,38 +38,16 @@ public:
     uint32_t index, clientIndex;
     void setSourceIndex(uint32_t idx);
     uint32_t sourceIndex();
+    void updateDeviceComboBox();
 #if HAVE_SOURCE_OUTPUT_VOLUMES
     virtual void executeVolumeUpdate();
     virtual void onMuteToggleButton();
 #endif
-    virtual void onDeviceChangePopup();
     virtual void onKill();
+    virtual void onDeviceComboBoxChanged();
 
 private:
     uint32_t mSourceIndex;
-
-    void clearMenu();
-    void buildMenu();
-
-    Gtk::Menu menu;
-
-    struct SourceMenuItem {
-      SourceMenuItem(SourceOutputWidget *w, const char *label, uint32_t i, bool active) :
-      widget(w),
-      menuItem(label),
-      index(i) {
-        menuItem.set_active(active);
-        menuItem.set_draw_as_radio(true);
-        menuItem.signal_toggled().connect(sigc::mem_fun(*this, &SourceMenuItem::onToggle));
-      }
-
-      SourceOutputWidget *widget;
-      Gtk::CheckMenuItem menuItem;
-      uint32_t index;
-      void onToggle();
-    };
-
-    std::map<uint32_t, SourceMenuItem*> sourceMenuItems;
 };
 
 #endif
diff --git a/src/streamwidget.cc b/src/streamwidget.cc
index 00b7796..00df09f 100644
--- a/src/streamwidget.cc
+++ b/src/streamwidget.cc
@@ -42,12 +42,12 @@ StreamWidget::StreamWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Buil
     x->get_widget("streamLockToggleButton", lockToggleButton);
     x->get_widget("streamMuteToggleButton", muteToggleButton);
     x->get_widget("directionLabel", directionLabel);
-    x->get_widget("deviceButton", deviceButton);
+    x->get_widget("deviceComboBox", deviceComboBox);
 
     this->signal_button_press_event().connect(sigc::mem_fun(*this, &StreamWidget::onContextTriggerEvent));
     muteToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &StreamWidget::onMuteToggleButton));
     lockToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &StreamWidget::onLockToggleButton));
-    deviceButton->signal_clicked().connect(sigc::mem_fun(*this, &StreamWidget::onDeviceChangePopup));
+    deviceComboBox->signal_changed().connect(sigc::mem_fun(*this, &StreamWidget::onDeviceComboBoxChanged));
 
     terminate.set_label(_("Terminate"));
     terminate.signal_activate().connect(sigc::mem_fun(*this, &StreamWidget::onKill));
@@ -58,7 +58,6 @@ StreamWidget::StreamWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Buil
         channelWidgets[i] = NULL;
 }
 
-
 void StreamWidget::init(MainWindow* mainWindow) {
     mpMainWindow = mainWindow;
 
@@ -145,8 +144,8 @@ bool StreamWidget::timeoutEvent() {
 void StreamWidget::executeVolumeUpdate() {
 }
 
-void StreamWidget::onDeviceChangePopup() {
+void StreamWidget::onKill() {
 }
 
-void StreamWidget::onKill() {
+void StreamWidget::onDeviceComboBoxChanged() {
 }
diff --git a/src/streamwidget.h b/src/streamwidget.h
index 23bdf7b..c1a79da 100644
--- a/src/streamwidget.h
+++ b/src/streamwidget.h
@@ -28,6 +28,9 @@
 class MainWindow;
 class ChannelWidget;
 
+/* Used as the ID for the unknown device item in deviceComboBox. */
+#define UNKNOWN_DEVICE_NAME "#unknown#"
+
 class StreamWidget : public MinimalStreamWidget {
 public:
     StreamWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& x);
@@ -41,7 +44,7 @@ public:
 
     Gtk::ToggleButton *lockToggleButton, *muteToggleButton;
     Gtk::Label *directionLabel;
-    Gtk::Button *deviceButton;
+    Gtk::ComboBoxText *deviceComboBox;
 
     pa_channel_map channelMap;
     pa_cvolume volume;
@@ -50,7 +53,6 @@ public:
 
     virtual void onMuteToggleButton();
     virtual void onLockToggleButton();
-    virtual void onDeviceChangePopup();
     virtual bool onContextTriggerEvent(GdkEventButton*);
 
     sigc::connection timeoutConnection;
@@ -59,6 +61,7 @@ public:
 
     virtual void executeVolumeUpdate();
     virtual void onKill();
+    virtual void onDeviceComboBoxChanged();
 
 protected:
     MainWindow* mpMainWindow;



More information about the pulseaudio-commits mailing list