diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/pavucontrol.cc | 172 | ||||
-rw-r--r-- | src/pavucontrol.glade | 277 |
2 files changed, 291 insertions, 158 deletions
diff --git a/src/pavucontrol.cc b/src/pavucontrol.cc index 4651db8..8397af5 100644 --- a/src/pavucontrol.cc +++ b/src/pavucontrol.cc @@ -35,7 +35,20 @@ #define GLADE_FILE "pavucontrol.glade" #endif -pa_context *context = NULL; +static pa_context *context = NULL; + +enum SinkType { + SINK_ALL, + SINK_HARDWARE, + SINK_VIRTUAL, +}; + +enum SourceType{ + SOURCE_ALL, + SOURCE_HARDWARE, + SOURCE_VIRTUAL, + SOURCE_MONITOR, +}; class StreamWidget; @@ -74,7 +87,7 @@ public: pa_channel_map channelMap; pa_cvolume volume; - + ChannelWidget *channelWidgets[PA_CHANNELS_MAX]; virtual void onMuteToggleButton(); @@ -91,6 +104,8 @@ public: SinkWidget(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& x); static SinkWidget* create(); + SinkType type; + virtual void onMuteToggleButton(); uint32_t index; virtual void executeVolumeUpdate(); @@ -101,6 +116,8 @@ public: SourceWidget(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& x); static SourceWidget* create(); + SourceType type; + virtual void onMuteToggleButton(); uint32_t index; virtual void executeVolumeUpdate(); @@ -131,17 +148,23 @@ public: void removeSinkInput(uint32_t index); void removeClient(uint32_t index); - Gtk::VBox *streamsVBox, *sinksVBox, *sourcesVBox, *monitorsVBox; + Gtk::VBox *streamsVBox, *sinksVBox, *sourcesVBox; Gtk::EventBox *titleEventBox; - Gtk::Label *noStreamsLabel, *noSinksLabel, *noSourcesLabel, *noMonitorsLabel; + Gtk::Label *noStreamsLabel, *noSinksLabel, *noSourcesLabel; + Gtk::ComboBox *sinkTypeComboBox, *sourceTypeComboBox; std::map<int, SinkWidget*> sinkWidgets; std::map<int, SourceWidget*> sourceWidgets; - std::map<int, SourceWidget*> monitorWidgets; std::map<int, SinkInputWidget*> streamWidgets; std::map<int, char*> clientNames; - void updateLabels(); + SinkType showSinkType; + SourceType showSourceType; + + virtual void onSinkTypeComboBoxChanged(); + virtual void onSourceTypeComboBoxChanged(); + + void updateDeviceVisibility(); }; void show_error(const char *txt) { @@ -375,22 +398,29 @@ void SinkInputWidget::executeVolumeUpdate() { /*** MainWindow ***/ MainWindow::MainWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& x) : - Gtk::Window(cobject) { + Gtk::Window(cobject), + showSinkType(SINK_HARDWARE), + showSourceType(SOURCE_HARDWARE) { x->get_widget("streamsVBox", streamsVBox); x->get_widget("sinksVBox", sinksVBox); x->get_widget("sourcesVBox", sourcesVBox); - x->get_widget("monitorsVBox", monitorsVBox); x->get_widget("titleEventBox", titleEventBox); x->get_widget("noStreamsLabel", noStreamsLabel); x->get_widget("noSinksLabel", noSinksLabel); x->get_widget("noSourcesLabel", noSourcesLabel); - x->get_widget("noMonitorsLabel", noMonitorsLabel); + x->get_widget("sinkTypeComboBox", sinkTypeComboBox); + x->get_widget("sourceTypeComboBox", sourceTypeComboBox); sourcesVBox->set_reallocate_redraws(true); - monitorsVBox->set_reallocate_redraws(true); streamsVBox->set_reallocate_redraws(true); sinksVBox->set_reallocate_redraws(true); + + sinkTypeComboBox->set_active((int) showSinkType); + sourceTypeComboBox->set_active((int) showSourceType); + + sinkTypeComboBox->signal_changed().connect(sigc::mem_fun(*this, &MainWindow::onSinkTypeComboBoxChanged)); + sourceTypeComboBox->signal_changed().connect(sigc::mem_fun(*this, &MainWindow::onSourceTypeComboBoxChanged)); Gdk::Color c("white"); titleEventBox->modify_bg(Gtk::STATE_NORMAL, c); @@ -420,6 +450,8 @@ void MainWindow::updateSink(const pa_sink_info &info) { w->index = info.index; } + w->type = info.flags & PA_SINK_HARDWARE ? SINK_HARDWARE : SINK_VIRTUAL; + gchar *txt; w->boldNameLabel->set_markup(txt = g_markup_printf_escaped("<b>%s</b>", info.name)); g_free(txt); @@ -428,27 +460,24 @@ void MainWindow::updateSink(const pa_sink_info &info) { w->setVolume(info.volume); w->muteToggleButton->set_active(info.mute); - w->onMuteToggleButton(); - updateLabels(); - w->queue_draw(); + updateDeviceVisibility(); } void MainWindow::updateSource(const pa_source_info &info) { SourceWidget *w; - std::map<int, SourceWidget*> &l = info.monitor_of_sink != PA_INVALID_INDEX ? monitorWidgets : sourceWidgets; - Gtk::VBox *vbox = info.monitor_of_sink != PA_INVALID_INDEX ? monitorsVBox : sourcesVBox; - - if (l.count(info.index)) - w = l[info.index]; + if (sourceWidgets.count(info.index)) + w = sourceWidgets[info.index]; else { - l[info.index] = w = SourceWidget::create(); + sourceWidgets[info.index] = w = SourceWidget::create(); w->setChannelMap(info.channel_map); - vbox->pack_start(*w, false, false, 0); + sourcesVBox->pack_start(*w, false, false, 0); w->index = info.index; } + w->type = info.monitor_of_sink != PA_INVALID_INDEX ? SOURCE_MONITOR : (info.flags & PA_SOURCE_HARDWARE ? SOURCE_HARDWARE : SOURCE_VIRTUAL); + gchar *txt; w->boldNameLabel->set_markup(txt = g_markup_printf_escaped("<b>%s</b>", info.name)); g_free(txt); @@ -457,10 +486,8 @@ void MainWindow::updateSource(const pa_source_info &info) { w->setVolume(info.volume); w->muteToggleButton->set_active(info.mute); - w->onMuteToggleButton(); - updateLabels(); - w->queue_draw(); + updateDeviceVisibility(); } void MainWindow::updateSinkInput(const pa_sink_input_info &info) { @@ -490,8 +517,8 @@ void MainWindow::updateSinkInput(const pa_sink_input_info &info) { w->setVolume(info.volume); - updateLabels(); - w->queue_draw(); + w->show(); + updateDeviceVisibility(); } void MainWindow::updateClient(const pa_client_info &info) { @@ -513,64 +540,73 @@ void MainWindow::updateClient(const pa_client_info &info) { } } -void MainWindow::updateLabels() { +void MainWindow::updateDeviceVisibility() { + if (streamWidgets.empty()) noStreamsLabel->show(); else noStreamsLabel->hide(); - - if (sinkWidgets.empty()) + + sourcesVBox->hide_all(); + sinksVBox->hide_all(); + + bool is_empty = true; + + for (std::map<int, SinkWidget*>::iterator i = sinkWidgets.begin(); i != sinkWidgets.end(); ++i) { + SinkWidget* w = i->second; + + if (showSinkType == SINK_ALL || w->type == showSinkType) { + w->show_all(); + is_empty = false; + } + } + + if (is_empty) noSinksLabel->show(); - else - noSinksLabel->hide(); + + is_empty = true; - if (sourceWidgets.empty()) + for (std::map<int, SourceWidget*>::iterator i = sourceWidgets.begin(); i != sourceWidgets.end(); ++i) { + SourceWidget* w = i->second; + + if (showSourceType == SOURCE_ALL || w->type == showSourceType) { + w->show_all(); + is_empty = false; + } + } + + if (is_empty) noSourcesLabel->show(); - else - noSourcesLabel->hide(); - if (monitorWidgets.empty()) - noMonitorsLabel->show(); - else - noMonitorsLabel->hide(); + sourcesVBox->show(); + sinksVBox->show(); } void MainWindow::removeSink(uint32_t index) { - StreamWidget *w; - - if (!(w = sinkWidgets[index])) + if (!sinkWidgets.count(index)) return; + delete sinkWidgets[index]; sinkWidgets.erase(index); - delete w; - updateLabels(); + updateDeviceVisibility(); } void MainWindow::removeSource(uint32_t index) { - StreamWidget *w; - - if (sourceWidgets.count(index)) { - w = sourceWidgets[index]; - sourceWidgets.erase(index); - } else if (monitorWidgets.count(index)) { - w = monitorWidgets[index]; - monitorWidgets.erase(index); - } else + if (!sourceWidgets.count(index)) return; - delete w; - updateLabels(); + delete sourceWidgets[index]; + sourceWidgets.erase(index); + updateDeviceVisibility(); } void MainWindow::removeSinkInput(uint32_t index) { - StreamWidget *w; - - if (!(w = streamWidgets[index])) + if (!streamWidgets.count(index)) return; - + + delete streamWidgets[index]; streamWidgets.erase(index); - delete w; - updateLabels(); + updateDeviceVisibility(); } void MainWindow::removeClient(uint32_t index) { @@ -578,6 +614,24 @@ void MainWindow::removeClient(uint32_t index) { clientNames.erase(index); } +void MainWindow::onSinkTypeComboBoxChanged() { + showSinkType = (SinkType) sinkTypeComboBox->get_active_row_number(); + + if (showSinkType == (SinkType) -1) + sinkTypeComboBox->set_active((int) SINK_HARDWARE); + + updateDeviceVisibility(); +} + +void MainWindow::onSourceTypeComboBoxChanged() { + showSourceType = (SourceType) sourceTypeComboBox->get_active_row_number(); + + if (showSourceType == (SourceType) -1) + sourceTypeComboBox->set_active((int) SOURCE_HARDWARE); + + updateDeviceVisibility(); +} + void sink_cb(pa_context *, const pa_sink_info *i, int eol, void *userdata) { MainWindow *w = static_cast<MainWindow*>(userdata); diff --git a/src/pavucontrol.glade b/src/pavucontrol.glade index 2ac6b8a..f45ab5d 100644 --- a/src/pavucontrol.glade +++ b/src/pavucontrol.glade @@ -148,12 +148,12 @@ <property name="spacing">12</property> <child> - <widget class="GtkNotebook" id="notebook1"> + <widget class="GtkNotebook" id="notebook"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="show_tabs">True</property> <property name="show_border">False</property> - <property name="tab_pos">GTK_POS_RIGHT</property> + <property name="tab_pos">GTK_POS_TOP</property> <property name="scrollable">False</property> <property name="enable_popup">False</property> @@ -217,7 +217,7 @@ <child> <widget class="GtkLabel" id="label34"> <property name="visible">True</property> - <property name="label" translatable="yes">_Streams</property> + <property name="label" translatable="yes">S_treams</property> <property name="use_underline">True</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> @@ -230,7 +230,7 @@ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> <property name="width_chars">-1</property> <property name="single_line_mode">False</property> - <property name="angle">270</property> + <property name="angle">0</property> </widget> <packing> <property name="type">tab</property> @@ -238,40 +238,100 @@ </child> <child> - <widget class="GtkScrolledWindow" id="scrolledwindow8"> - <property name="border_width">12</property> + <widget class="GtkVBox" id="vbox30"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="shadow_type">GTK_SHADOW_NONE</property> - <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> <child> - <widget class="GtkViewport" id="viewport4"> + <widget class="GtkScrolledWindow" id="scrolledwindow8"> + <property name="border_width">12</property> <property name="visible">True</property> - <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_NONE</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkViewport" id="viewport4"> + <property name="visible">True</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + + <child> + <widget class="GtkVBox" id="sinksVBox"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="noSinksLabel"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="label" translatable="yes"><i>No Sinks Available</i></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">16</property> + <property name="ypad">16</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + <property name="top_padding">0</property> + <property name="bottom_padding">12</property> + <property name="left_padding">12</property> + <property name="right_padding">12</property> <child> - <widget class="GtkVBox" id="sinksVBox"> + <widget class="GtkHBox" id="hbox3"> <property name="visible">True</property> <property name="homogeneous">False</property> - <property name="spacing">0</property> + <property name="spacing">6</property> <child> - <widget class="GtkLabel" id="noSinksLabel"> + <widget class="GtkLabel" id="label4826"> <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="label" translatable="yes"><i>No Sinks Available</i></property> - <property name="use_underline">False</property> + <property name="label" translatable="yes"><b>S_how:</b></property> + <property name="use_underline">True</property> <property name="use_markup">True</property> <property name="justify">GTK_JUSTIFY_LEFT</property> <property name="wrap">False</property> <property name="selectable">False</property> - <property name="xalign">0</property> + <property name="xalign">0.5</property> <property name="yalign">0.5</property> - <property name="xpad">16</property> - <property name="ypad">16</property> + <property name="xpad">0</property> + <property name="ypad">0</property> <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> <property name="width_chars">-1</property> <property name="single_line_mode">False</property> @@ -283,9 +343,30 @@ <property name="fill">False</property> </packing> </child> + + <child> + <widget class="GtkComboBox" id="sinkTypeComboBox"> + <property name="visible">True</property> + <property name="items" translatable="yes">All Sinks +Hardware Sinks +Virtual Sinks</property> + <property name="add_tearoffs">False</property> + <property name="focus_on_click">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> </widget> </child> </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> </child> </widget> <packing> @@ -297,7 +378,7 @@ <child> <widget class="GtkLabel" id="label4711"> <property name="visible">True</property> - <property name="label" translatable="yes">_Sinks</property> + <property name="label" translatable="yes">S_inks</property> <property name="use_underline">True</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> @@ -310,7 +391,7 @@ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> <property name="width_chars">-1</property> <property name="single_line_mode">False</property> - <property name="angle">270</property> + <property name="angle">0</property> </widget> <packing> <property name="type">tab</property> @@ -318,25 +399,25 @@ </child> <child> - <widget class="GtkScrolledWindow" id="scrolledwindow7"> - <property name="border_width">12</property> + <widget class="GtkVBox" id="vbox31"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="shadow_type">GTK_SHADOW_NONE</property> - <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> <child> - <widget class="GtkViewport" id="viewport3"> + <widget class="GtkScrolledWindow" id="scrolledwindow7"> + <property name="border_width">12</property> <property name="visible">True</property> - <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_NONE</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> <child> - <widget class="GtkVBox" id="vbox30"> + <widget class="GtkViewport" id="viewport3"> <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> + <property name="shadow_type">GTK_SHADOW_IN</property> <child> <widget class="GtkVBox" id="sourcesVBox"> @@ -370,6 +451,53 @@ </packing> </child> </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment2"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + <property name="top_padding">0</property> + <property name="bottom_padding">12</property> + <property name="left_padding">12</property> + <property name="right_padding">12</property> + + <child> + <widget class="GtkHBox" id="hbox4"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkLabel" id="label4827"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Sh_ow:</b></property> + <property name="use_underline">True</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> <packing> <property name="padding">0</property> <property name="expand">False</property> @@ -378,68 +506,14 @@ </child> <child> - <widget class="GtkExpander" id="monitorExpander"> + <widget class="GtkComboBox" id="sourceTypeComboBox"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="expanded">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkVBox" id="monitorsVBox"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkLabel" id="noMonitorsLabel"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="label" translatable="yes"><i>No Monitor Sources Available</i></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">16</property> - <property name="ypad">16</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - </child> - - <child> - <widget class="GtkLabel" id="label4826"> - <property name="visible">True</property> - <property name="label" translatable="yes">Monitor Sources</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">label_item</property> - </packing> - </child> + <property name="items" translatable="yes">All Sources +Hardware Sources +Virtual Sources +Monitor Sources</property> + <property name="add_tearoffs">False</property> + <property name="focus_on_click">True</property> </widget> <packing> <property name="padding">0</property> @@ -450,6 +524,11 @@ </widget> </child> </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> </child> </widget> <packing> @@ -461,7 +540,7 @@ <child> <widget class="GtkLabel" id="label4717"> <property name="visible">True</property> - <property name="label" translatable="yes">_Sources</property> + <property name="label" translatable="yes">S_ources</property> <property name="use_underline">True</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> @@ -474,7 +553,7 @@ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> <property name="width_chars">-1</property> <property name="single_line_mode">False</property> - <property name="angle">270</property> + <property name="angle">0</property> </widget> <packing> <property name="type">tab</property> |