show radio buttons for the the sink menu items

git-svn-id: file:///home/lennart/svn/public/pavucontrol/trunk@67 c17c95f2-f111-0410-90bf-f30a9569010c
This commit is contained in:
Lennart Poettering 2007-11-20 02:14:59 +00:00
parent 95dc5fc4e9
commit 98a7f6c5d1
1 changed files with 58 additions and 57 deletions

View File

@ -2,17 +2,17 @@
/*** /***
This file is part of pavucontrol. This file is part of pavucontrol.
pavucontrol is free software; you can redistribute it and/or modify pavucontrol is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published it under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 2 of the License, by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version. or (at your option) any later version.
pavucontrol is distributed in the hope that it will be useful, but pavucontrol is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details. General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with pavucontrol; if not, write to the Free Software along with pavucontrol; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
@ -95,10 +95,10 @@ public:
Gtk::ToggleButton *lockToggleButton, *muteToggleButton; Gtk::ToggleButton *lockToggleButton, *muteToggleButton;
bool updating; bool updating;
pa_channel_map channelMap; pa_channel_map channelMap;
pa_cvolume volume; pa_cvolume volume;
ChannelWidget *channelWidgets[PA_CHANNELS_MAX]; ChannelWidget *channelWidgets[PA_CHANNELS_MAX];
virtual void onMuteToggleButton(); virtual void onMuteToggleButton();
@ -106,7 +106,7 @@ public:
sigc::connection timeoutConnection; sigc::connection timeoutConnection;
bool timeoutEvent(); bool timeoutEvent();
virtual void executeVolumeUpdate(); virtual void executeVolumeUpdate();
}; };
@ -122,7 +122,7 @@ public:
Gtk::Menu menu; Gtk::Menu menu;
Gtk::CheckMenuItem defaultMenuItem; Gtk::CheckMenuItem defaultMenuItem;
virtual void onMuteToggleButton(); virtual void onMuteToggleButton();
virtual void executeVolumeUpdate(); virtual void executeVolumeUpdate();
virtual void onDefaultToggle(); virtual void onDefaultToggle();
@ -142,7 +142,7 @@ public:
Gtk::Menu menu; Gtk::Menu menu;
Gtk::CheckMenuItem defaultMenuItem; Gtk::CheckMenuItem defaultMenuItem;
virtual void onMuteToggleButton(); virtual void onMuteToggleButton();
virtual void executeVolumeUpdate(); virtual void executeVolumeUpdate();
virtual void onDefaultToggle(); virtual void onDefaultToggle();
@ -158,12 +158,12 @@ public:
virtual ~SinkInputWidget(); virtual ~SinkInputWidget();
SinkInputType type; SinkInputType type;
uint32_t index, clientIndex, sinkIndex; uint32_t index, clientIndex, sinkIndex;
virtual void executeVolumeUpdate(); virtual void executeVolumeUpdate();
virtual void onMuteToggleButton(); virtual void onMuteToggleButton();
virtual void onKill(); virtual void onKill();
MainWindow *mainWindow; MainWindow *mainWindow;
Gtk::Menu menu, submenu; Gtk::Menu menu, submenu;
Gtk::MenuItem titleMenuItem, killMenuItem; Gtk::MenuItem titleMenuItem, killMenuItem;
@ -174,6 +174,7 @@ public:
menuItem(label), menuItem(label),
index(i) { index(i) {
menuItem.set_active(active); menuItem.set_active(active);
menuItem.set_draw_as_radio(true);
menuItem.signal_toggled().connect(sigc::mem_fun(*this, &SinkMenuItem::onToggle)); menuItem.signal_toggled().connect(sigc::mem_fun(*this, &SinkMenuItem::onToggle));
} }
@ -182,12 +183,12 @@ public:
uint32_t index; uint32_t index;
void onToggle(); void onToggle();
}; };
std::map<uint32_t, SinkMenuItem*> sinkMenuItems; std::map<uint32_t, SinkMenuItem*> sinkMenuItems;
void clearMenu(); void clearMenu();
void buildMenu(); void buildMenu();
protected: protected:
virtual bool on_button_press_event(GdkEventButton* event); virtual bool on_button_press_event(GdkEventButton* event);
}; };
@ -208,7 +209,7 @@ public:
void removeSource(uint32_t index); void removeSource(uint32_t index);
void removeSinkInput(uint32_t index); void removeSinkInput(uint32_t index);
void removeClient(uint32_t index); void removeClient(uint32_t index);
Gtk::VBox *streamsVBox, *sinksVBox, *sourcesVBox; Gtk::VBox *streamsVBox, *sinksVBox, *sourcesVBox;
Gtk::EventBox *titleEventBox; Gtk::EventBox *titleEventBox;
Gtk::Label *noStreamsLabel, *noSinksLabel, *noSourcesLabel; Gtk::Label *noStreamsLabel, *noSinksLabel, *noSourcesLabel;
@ -222,7 +223,7 @@ public:
SinkInputType showSinkInputType; SinkInputType showSinkInputType;
SinkType showSinkType; SinkType showSinkType;
SourceType showSourceType; SourceType showSourceType;
virtual void onSinkInputTypeComboBoxChanged(); virtual void onSinkInputTypeComboBoxChanged();
virtual void onSinkTypeComboBoxChanged(); virtual void onSinkTypeComboBoxChanged();
virtual void onSourceTypeComboBoxChanged(); virtual void onSourceTypeComboBoxChanged();
@ -230,7 +231,7 @@ public:
void updateDeviceVisibility(); void updateDeviceVisibility();
Glib::ustring defaultSinkName, defaultSourceName; Glib::ustring defaultSinkName, defaultSourceName;
protected: protected:
virtual void on_realize(); virtual void on_realize();
}; };
@ -239,7 +240,7 @@ void show_error(const char *txt) {
char buf[256]; char buf[256];
snprintf(buf, sizeof(buf), "%s: %s", txt, pa_strerror(pa_context_errno(context))); snprintf(buf, sizeof(buf), "%s: %s", txt, pa_strerror(pa_context_errno(context)));
Gtk::MessageDialog dialog(buf, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true); Gtk::MessageDialog dialog(buf, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
dialog.run(); dialog.run();
@ -269,7 +270,7 @@ ChannelWidget* ChannelWidget::create() {
void ChannelWidget::setVolume(pa_volume_t volume) { void ChannelWidget::setVolume(pa_volume_t volume) {
double v = ((gdouble) volume * 100) / PA_VOLUME_NORM; double v = ((gdouble) volume * 100) / PA_VOLUME_NORM;
char txt[64]; char txt[64];
snprintf(txt, sizeof(txt), "%0.0f%%", v); snprintf(txt, sizeof(txt), "%0.0f%%", v);
volumeLabel->set_text(txt); volumeLabel->set_text(txt);
@ -314,14 +315,14 @@ StreamWidget::StreamWidget(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Gl
x->get_widget("muteToggleButton", muteToggleButton); x->get_widget("muteToggleButton", muteToggleButton);
muteToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &StreamWidget::onMuteToggleButton)); muteToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &StreamWidget::onMuteToggleButton));
for (int i = 0; i < PA_CHANNELS_MAX; i++) for (int i = 0; i < PA_CHANNELS_MAX; i++)
channelWidgets[i] = NULL; channelWidgets[i] = NULL;
} }
void StreamWidget::setChannelMap(const pa_channel_map &m) { void StreamWidget::setChannelMap(const pa_channel_map &m) {
channelMap = m; channelMap = m;
for (int i = 0; i < m.channels; i++) { for (int i = 0; i < m.channels; i++) {
ChannelWidget *cw = channelWidgets[i] = ChannelWidget::create(); ChannelWidget *cw = channelWidgets[i] = ChannelWidget::create();
cw->channel = i; cw->channel = i;
@ -354,7 +355,7 @@ void StreamWidget::updateChannelVolume(int channel, pa_volume_t v) {
if (lockToggleButton->get_active()) { if (lockToggleButton->get_active()) {
for (int i = 0; i < n.channels; i++) for (int i = 0; i < n.channels; i++)
n.values[i] = v; n.values[i] = v;
} else } else
n.values[channel] = v; n.values[channel] = v;
setVolume(n, true); setVolume(n, true);
@ -400,7 +401,7 @@ SinkWidget* SinkWidget::create() {
void SinkWidget::executeVolumeUpdate() { void SinkWidget::executeVolumeUpdate() {
pa_operation* o; pa_operation* o;
if (!(o = pa_context_set_sink_volume_by_index(context, index, &volume, NULL, NULL))) { if (!(o = pa_context_set_sink_volume_by_index(context, index, &volume, NULL, NULL))) {
show_error("pa_context_set_sink_volume_by_index() failed"); show_error("pa_context_set_sink_volume_by_index() failed");
return; return;
@ -414,7 +415,7 @@ void SinkWidget::onMuteToggleButton() {
if (updating) if (updating)
return; return;
pa_operation* o; pa_operation* o;
if (!(o = pa_context_set_sink_mute_by_index(context, index, muteToggleButton->get_active(), NULL, NULL))) { if (!(o = pa_context_set_sink_mute_by_index(context, index, muteToggleButton->get_active(), NULL, NULL))) {
show_error("pa_context_set_sink_mute_by_index() failed"); show_error("pa_context_set_sink_mute_by_index() failed");
@ -429,7 +430,7 @@ bool SinkWidget::on_button_press_event(GdkEventButton* event) {
return TRUE; return TRUE;
if (event->type == GDK_BUTTON_PRESS && event->button == 3) { if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
menu.popup(0, event->time); menu.popup(0, event->time);
return TRUE; return TRUE;
} }
@ -442,7 +443,7 @@ void SinkWidget::onDefaultToggle() {
if (updating) if (updating)
return; return;
if (!(o = pa_context_set_default_sink(context, name.c_str(), NULL, NULL))) { if (!(o = pa_context_set_default_sink(context, name.c_str(), NULL, NULL))) {
show_error("pa_context_set_default_sink() failed"); show_error("pa_context_set_default_sink() failed");
return; return;
@ -471,7 +472,7 @@ SourceWidget* SourceWidget::create() {
void SourceWidget::executeVolumeUpdate() { void SourceWidget::executeVolumeUpdate() {
pa_operation* o; pa_operation* o;
if (!(o = pa_context_set_source_volume_by_index(context, index, &volume, NULL, NULL))) { if (!(o = pa_context_set_source_volume_by_index(context, index, &volume, NULL, NULL))) {
show_error("pa_context_set_source_volume_by_index() failed"); show_error("pa_context_set_source_volume_by_index() failed");
return; return;
@ -485,13 +486,13 @@ void SourceWidget::onMuteToggleButton() {
if (updating) if (updating)
return; return;
pa_operation* o; pa_operation* o;
if (!(o = pa_context_set_source_mute_by_index(context, index, muteToggleButton->get_active(), NULL, NULL))) { if (!(o = pa_context_set_source_mute_by_index(context, index, muteToggleButton->get_active(), NULL, NULL))) {
show_error("pa_context_set_source_mute_by_index() failed"); show_error("pa_context_set_source_mute_by_index() failed");
return; return;
} }
pa_operation_unref(o); pa_operation_unref(o);
} }
@ -500,7 +501,7 @@ bool SourceWidget::on_button_press_event(GdkEventButton* event) {
return TRUE; return TRUE;
if (event->type == GDK_BUTTON_PRESS && event->button == 3) { if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
menu.popup(0, event->time); menu.popup(0, event->time);
return TRUE; return TRUE;
} }
@ -513,7 +514,7 @@ void SourceWidget::onDefaultToggle() {
if (updating) if (updating)
return; return;
if (!(o = pa_context_set_default_source(context, name.c_str(), NULL, NULL))) { if (!(o = pa_context_set_default_source(context, name.c_str(), NULL, NULL))) {
show_error("pa_context_set_default_source() failed"); show_error("pa_context_set_default_source() failed");
return; return;
@ -563,7 +564,7 @@ void SinkInputWidget::onMuteToggleButton() {
if (updating) if (updating)
return; return;
pa_operation* o; pa_operation* o;
if (!(o = pa_context_set_sink_input_mute(context, index, muteToggleButton->get_active(), NULL, NULL))) { if (!(o = pa_context_set_sink_input_mute(context, index, muteToggleButton->get_active(), NULL, NULL))) {
show_error("pa_context_set_sink_input_mute() failed"); show_error("pa_context_set_sink_input_mute() failed");
@ -588,7 +589,7 @@ bool SinkInputWidget::on_button_press_event(GdkEventButton* event) {
} }
void SinkInputWidget::clearMenu() { void SinkInputWidget::clearMenu() {
while (!sinkMenuItems.empty()) { while (!sinkMenuItems.empty()) {
std::map<uint32_t, SinkMenuItem*>::iterator i = sinkMenuItems.begin(); std::map<uint32_t, SinkMenuItem*>::iterator i = sinkMenuItems.begin();
delete i->second; delete i->second;
@ -620,7 +621,7 @@ void SinkInputWidget::SinkMenuItem::onToggle() {
if (widget->updating) if (widget->updating)
return; return;
if (!menuItem.get_active()) if (!menuItem.get_active())
return; return;
@ -704,7 +705,7 @@ void MainWindow::updateSink(const pa_sink_info &info) {
} }
w->updating = true; w->updating = true;
w->name = info.name; w->name = info.name;
w->description = info.description; w->description = info.description;
w->type = info.flags & PA_SINK_HARDWARE ? SINK_HARDWARE : SINK_VIRTUAL; w->type = info.flags & PA_SINK_HARDWARE ? SINK_HARDWARE : SINK_VIRTUAL;
@ -740,7 +741,7 @@ void MainWindow::updateSource(const pa_source_info &info) {
} }
w->updating = true; w->updating = true;
w->name = info.name; w->name = info.name;
w->type = info.monitor_of_sink != PA_INVALID_INDEX ? SOURCE_MONITOR : (info.flags & PA_SOURCE_HARDWARE ? SOURCE_HARDWARE : SOURCE_VIRTUAL); w->type = info.monitor_of_sink != PA_INVALID_INDEX ? SOURCE_MONITOR : (info.flags & PA_SOURCE_HARDWARE ? SOURCE_HARDWARE : SOURCE_VIRTUAL);
@ -748,12 +749,12 @@ void MainWindow::updateSource(const pa_source_info &info) {
gchar *txt; gchar *txt;
w->nameLabel->set_markup(txt = g_markup_printf_escaped("%s", info.description)); w->nameLabel->set_markup(txt = g_markup_printf_escaped("%s", info.description));
g_free(txt); g_free(txt);
w->setVolume(info.volume); w->setVolume(info.volume);
w->muteToggleButton->set_active(info.mute); w->muteToggleButton->set_active(info.mute);
w->defaultMenuItem.set_active(w->name == defaultSourceName); w->defaultMenuItem.set_active(w->name == defaultSourceName);
if (is_new) if (is_new)
updateDeviceVisibility(); updateDeviceVisibility();
@ -792,7 +793,7 @@ void MainWindow::updateSinkInput(const pa_sink_input_info &info) {
w->boldNameLabel->set_text(""); w->boldNameLabel->set_text("");
w->nameLabel->set_label(info.name); w->nameLabel->set_label(info.name);
} }
w->setVolume(info.volume); w->setVolume(info.volume);
w->muteToggleButton->set_active(info.mute); w->muteToggleButton->set_active(info.mute);
@ -812,7 +813,7 @@ void MainWindow::updateClient(const pa_client_info &info) {
if (!w) if (!w)
continue; continue;
if (w->clientIndex == info.index) { if (w->clientIndex == info.index) {
gchar *txt; gchar *txt;
w->boldNameLabel->set_markup(txt = g_markup_printf_escaped("<b>%s</b>", info.name)); w->boldNameLabel->set_markup(txt = g_markup_printf_escaped("<b>%s</b>", info.name));
@ -865,12 +866,12 @@ void MainWindow::updateDeviceVisibility() {
is_empty = false; is_empty = false;
} }
} }
if (is_empty) if (is_empty)
noStreamsLabel->show(); noStreamsLabel->show();
is_empty = true; is_empty = true;
for (std::map<uint32_t, SinkWidget*>::iterator i = sinkWidgets.begin(); i != sinkWidgets.end(); ++i) { for (std::map<uint32_t, SinkWidget*>::iterator i = sinkWidgets.begin(); i != sinkWidgets.end(); ++i) {
SinkWidget* w = i->second; SinkWidget* w = i->second;
@ -884,7 +885,7 @@ void MainWindow::updateDeviceVisibility() {
noSinksLabel->show(); noSinksLabel->show();
is_empty = true; is_empty = true;
for (std::map<uint32_t, SourceWidget*>::iterator i = sourceWidgets.begin(); i != sourceWidgets.end(); ++i) { for (std::map<uint32_t, SourceWidget*>::iterator i = sourceWidgets.begin(); i != sourceWidgets.end(); ++i) {
SourceWidget* w = i->second; SourceWidget* w = i->second;
@ -925,7 +926,7 @@ void MainWindow::removeSource(uint32_t index) {
void MainWindow::removeSinkInput(uint32_t index) { void MainWindow::removeSinkInput(uint32_t index) {
if (!sinkInputWidgets.count(index)) if (!sinkInputWidgets.count(index))
return; return;
delete sinkInputWidgets[index]; delete sinkInputWidgets[index];
sinkInputWidgets.erase(index); sinkInputWidgets.erase(index);
updateDeviceVisibility(); updateDeviceVisibility();
@ -966,7 +967,7 @@ void MainWindow::onSinkInputTypeComboBoxChanged() {
static void dec_outstanding(MainWindow *w) { static void dec_outstanding(MainWindow *w) {
if (n_outstanding <= 0) if (n_outstanding <= 0)
return; return;
if (--n_outstanding <= 0) if (--n_outstanding <= 0)
w->get_window()->set_cursor(); w->get_window()->set_cursor();
} }
@ -1063,7 +1064,7 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
pa_operation_unref(o); pa_operation_unref(o);
} }
break; break;
case PA_SUBSCRIPTION_EVENT_SOURCE: case PA_SUBSCRIPTION_EVENT_SOURCE:
if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE)
w->removeSource(index); w->removeSource(index);
@ -1076,7 +1077,7 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
pa_operation_unref(o); pa_operation_unref(o);
} }
break; break;
case PA_SUBSCRIPTION_EVENT_SINK_INPUT: case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE)
w->removeSinkInput(index); w->removeSinkInput(index);
@ -1089,7 +1090,7 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
pa_operation_unref(o); pa_operation_unref(o);
} }
break; break;
case PA_SUBSCRIPTION_EVENT_CLIENT: case PA_SUBSCRIPTION_EVENT_CLIENT:
if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE)
w->removeClient(index); w->removeClient(index);
@ -1116,7 +1117,7 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
void context_state_callback(pa_context *c, void *userdata) { void context_state_callback(pa_context *c, void *userdata) {
MainWindow *w = static_cast<MainWindow*>(userdata); MainWindow *w = static_cast<MainWindow*>(userdata);
g_assert(c); g_assert(c);
switch (pa_context_get_state(c)) { switch (pa_context_get_state(c)) {
@ -1128,9 +1129,9 @@ void context_state_callback(pa_context *c, void *userdata) {
case PA_CONTEXT_READY: { case PA_CONTEXT_READY: {
pa_operation *o; pa_operation *o;
pa_context_set_subscribe_callback(c, subscribe_cb, w); pa_context_set_subscribe_callback(c, subscribe_cb, w);
if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t) if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t)
(PA_SUBSCRIPTION_MASK_SINK| (PA_SUBSCRIPTION_MASK_SINK|
PA_SUBSCRIPTION_MASK_SOURCE| PA_SUBSCRIPTION_MASK_SOURCE|
@ -1147,7 +1148,7 @@ void context_state_callback(pa_context *c, void *userdata) {
return; return;
} }
pa_operation_unref(o); pa_operation_unref(o);
if (!(o = pa_context_get_client_info_list(c, client_cb, w))) { if (!(o = pa_context_get_client_info_list(c, client_cb, w))) {
show_error("pa_context_client_info_list() failed"); show_error("pa_context_client_info_list() failed");
return; return;
@ -1173,14 +1174,14 @@ void context_state_callback(pa_context *c, void *userdata) {
pa_operation_unref(o); pa_operation_unref(o);
n_outstanding = 5; n_outstanding = 5;
break; break;
} }
case PA_CONTEXT_FAILED: case PA_CONTEXT_FAILED:
show_error("Connection failed"); show_error("Connection failed");
return; return;
case PA_CONTEXT_TERMINATED: case PA_CONTEXT_TERMINATED:
default: default:
Gtk::Main::quit(); Gtk::Main::quit();
@ -1192,9 +1193,9 @@ int main(int argc, char *argv[]) {
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
Gtk::Main kit(argc, argv); Gtk::Main kit(argc, argv);
Gtk::Window* mainWindow = MainWindow::create(); Gtk::Window* mainWindow = MainWindow::create();
pa_glib_mainloop *m = pa_glib_mainloop_new(g_main_context_default()); pa_glib_mainloop *m = pa_glib_mainloop_new(g_main_context_default());
g_assert(m); g_assert(m);
pa_mainloop_api *api = pa_glib_mainloop_get_api(m); pa_mainloop_api *api = pa_glib_mainloop_get_api(m);
@ -1203,12 +1204,12 @@ int main(int argc, char *argv[]) {
g_assert(context); g_assert(context);
pa_context_set_state_callback(context, context_state_callback, mainWindow); pa_context_set_state_callback(context, context_state_callback, mainWindow);
if (pa_context_connect(context, NULL, (pa_context_flags_t) 0, NULL) < 0) { if (pa_context_connect(context, NULL, (pa_context_flags_t) 0, NULL) < 0) {
show_error("Connection failed"); show_error("Connection failed");
goto finish; goto finish;
} }
Gtk::Main::run(*mainWindow); Gtk::Main::run(*mainWindow);
delete mainWindow; delete mainWindow;