add popup menu to sink/source view to choose default device
git-svn-id: file:///home/lennart/svn/public/pavucontrol/trunk@61 c17c95f2-f111-0410-90bf-f30a9569010c
This commit is contained in:
parent
e7ecb63249
commit
e41c9bed6c
|
@ -117,10 +117,18 @@ public:
|
||||||
|
|
||||||
SinkType type;
|
SinkType type;
|
||||||
Glib::ustring description;
|
Glib::ustring description;
|
||||||
|
Glib::ustring name;
|
||||||
|
uint32_t index;
|
||||||
|
|
||||||
|
Gtk::Menu menu;
|
||||||
|
Gtk::CheckMenuItem defaultMenuItem;
|
||||||
|
|
||||||
virtual void onMuteToggleButton();
|
virtual void onMuteToggleButton();
|
||||||
uint32_t index;
|
|
||||||
virtual void executeVolumeUpdate();
|
virtual void executeVolumeUpdate();
|
||||||
|
virtual void onDefaultToggle();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool on_button_press_event(GdkEventButton* event);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SourceWidget : public StreamWidget {
|
class SourceWidget : public StreamWidget {
|
||||||
|
@ -129,10 +137,18 @@ public:
|
||||||
static SourceWidget* create();
|
static SourceWidget* create();
|
||||||
|
|
||||||
SourceType type;
|
SourceType type;
|
||||||
|
Glib::ustring name;
|
||||||
|
uint32_t index;
|
||||||
|
|
||||||
|
Gtk::Menu menu;
|
||||||
|
Gtk::CheckMenuItem defaultMenuItem;
|
||||||
|
|
||||||
virtual void onMuteToggleButton();
|
virtual void onMuteToggleButton();
|
||||||
uint32_t index;
|
|
||||||
virtual void executeVolumeUpdate();
|
virtual void executeVolumeUpdate();
|
||||||
|
virtual void onDefaultToggle();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool on_button_press_event(GdkEventButton* event);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SinkInputWidget : public StreamWidget {
|
class SinkInputWidget : public StreamWidget {
|
||||||
|
@ -185,6 +201,7 @@ public:
|
||||||
void updateSource(const pa_source_info &info);
|
void updateSource(const pa_source_info &info);
|
||||||
void updateSinkInput(const pa_sink_input_info &info);
|
void updateSinkInput(const pa_sink_input_info &info);
|
||||||
void updateClient(const pa_client_info &info);
|
void updateClient(const pa_client_info &info);
|
||||||
|
void updateServer(const pa_server_info &info);
|
||||||
|
|
||||||
void removeSink(uint32_t index);
|
void removeSink(uint32_t index);
|
||||||
void removeSource(uint32_t index);
|
void removeSource(uint32_t index);
|
||||||
|
@ -211,6 +228,8 @@ public:
|
||||||
|
|
||||||
void updateDeviceVisibility();
|
void updateDeviceVisibility();
|
||||||
|
|
||||||
|
Glib::ustring defaultSinkName, defaultSourceName;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void on_realize();
|
virtual void on_realize();
|
||||||
};
|
};
|
||||||
|
@ -360,7 +379,15 @@ void StreamWidget::executeVolumeUpdate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
SinkWidget::SinkWidget(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& x) :
|
SinkWidget::SinkWidget(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& x) :
|
||||||
StreamWidget(cobject, x) {
|
StreamWidget(cobject, x),
|
||||||
|
defaultMenuItem("Default"){
|
||||||
|
|
||||||
|
add_events(Gdk::BUTTON_PRESS_MASK);
|
||||||
|
|
||||||
|
defaultMenuItem.set_active(false);
|
||||||
|
defaultMenuItem.signal_toggled().connect(sigc::mem_fun(*this, &SinkWidget::onDefaultToggle));
|
||||||
|
menu.append(defaultMenuItem);
|
||||||
|
menu.show_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
SinkWidget* SinkWidget::create() {
|
SinkWidget* SinkWidget::create() {
|
||||||
|
@ -396,8 +423,42 @@ void SinkWidget::onMuteToggleButton() {
|
||||||
pa_operation_unref(o);
|
pa_operation_unref(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SinkWidget::on_button_press_event(GdkEventButton* event) {
|
||||||
|
if (StreamWidget::on_button_press_event(event))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
|
||||||
|
|
||||||
|
menu.popup(0, event->time);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SinkWidget::onDefaultToggle() {
|
||||||
|
pa_operation* o;
|
||||||
|
|
||||||
|
if (updating)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(o = pa_context_set_default_sink(context, name.c_str(), NULL, NULL))) {
|
||||||
|
show_error("pa_context_set_default_sink() failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pa_operation_unref(o);
|
||||||
|
}
|
||||||
|
|
||||||
SourceWidget::SourceWidget(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& x) :
|
SourceWidget::SourceWidget(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& x) :
|
||||||
StreamWidget(cobject, x) {
|
StreamWidget(cobject, x),
|
||||||
|
defaultMenuItem("Default"){
|
||||||
|
|
||||||
|
add_events(Gdk::BUTTON_PRESS_MASK);
|
||||||
|
|
||||||
|
defaultMenuItem.set_active(false);
|
||||||
|
defaultMenuItem.signal_toggled().connect(sigc::mem_fun(*this, &SourceWidget::onDefaultToggle));
|
||||||
|
menu.append(defaultMenuItem);
|
||||||
|
menu.show_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceWidget* SourceWidget::create() {
|
SourceWidget* SourceWidget::create() {
|
||||||
|
@ -433,6 +494,32 @@ void SourceWidget::onMuteToggleButton() {
|
||||||
pa_operation_unref(o);
|
pa_operation_unref(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SourceWidget::on_button_press_event(GdkEventButton* event) {
|
||||||
|
if (StreamWidget::on_button_press_event(event))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
|
||||||
|
|
||||||
|
menu.popup(0, event->time);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourceWidget::onDefaultToggle() {
|
||||||
|
pa_operation* o;
|
||||||
|
|
||||||
|
if (updating)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(o = pa_context_set_default_source(context, name.c_str(), NULL, NULL))) {
|
||||||
|
show_error("pa_context_set_default_source() failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pa_operation_unref(o);
|
||||||
|
}
|
||||||
|
|
||||||
SinkInputWidget::SinkInputWidget(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& x) :
|
SinkInputWidget::SinkInputWidget(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& x) :
|
||||||
StreamWidget(cobject, x),
|
StreamWidget(cobject, x),
|
||||||
mainWindow(NULL),
|
mainWindow(NULL),
|
||||||
|
@ -516,6 +603,9 @@ void SinkInputWidget::buildMenu() {
|
||||||
|
|
||||||
void SinkInputWidget::SinkMenuItem::onToggle() {
|
void SinkInputWidget::SinkMenuItem::onToggle() {
|
||||||
|
|
||||||
|
if (widget->updating)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!menuItem.get_active())
|
if (!menuItem.get_active())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -600,8 +690,9 @@ void MainWindow::updateSink(const pa_sink_info &info) {
|
||||||
|
|
||||||
w->updating = true;
|
w->updating = true;
|
||||||
|
|
||||||
w->type = info.flags & PA_SINK_HARDWARE ? SINK_HARDWARE : SINK_VIRTUAL;
|
w->name = info.name;
|
||||||
w->description = info.description;
|
w->description = info.description;
|
||||||
|
w->type = info.flags & PA_SINK_HARDWARE ? SINK_HARDWARE : SINK_VIRTUAL;
|
||||||
|
|
||||||
w->boldNameLabel->set_text("");
|
w->boldNameLabel->set_text("");
|
||||||
gchar *txt;
|
gchar *txt;
|
||||||
|
@ -611,6 +702,8 @@ void MainWindow::updateSink(const pa_sink_info &info) {
|
||||||
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 == defaultSinkName);
|
||||||
|
|
||||||
if (is_new)
|
if (is_new)
|
||||||
updateDeviceVisibility();
|
updateDeviceVisibility();
|
||||||
|
|
||||||
|
@ -633,6 +726,7 @@ void MainWindow::updateSource(const pa_source_info &info) {
|
||||||
|
|
||||||
w->updating = true;
|
w->updating = true;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
w->boldNameLabel->set_text("");
|
w->boldNameLabel->set_text("");
|
||||||
|
@ -643,6 +737,8 @@ void MainWindow::updateSource(const pa_source_info &info) {
|
||||||
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);
|
||||||
|
|
||||||
if (is_new)
|
if (is_new)
|
||||||
updateDeviceVisibility();
|
updateDeviceVisibility();
|
||||||
|
|
||||||
|
@ -710,6 +806,34 @@ void MainWindow::updateClient(const pa_client_info &info) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::updateServer(const pa_server_info &info) {
|
||||||
|
|
||||||
|
for (std::map<uint32_t, SinkWidget*>::iterator i = sinkWidgets.begin(); i != sinkWidgets.end(); ++i) {
|
||||||
|
SinkWidget *w = i->second;
|
||||||
|
|
||||||
|
if (!w)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
w->updating = true;
|
||||||
|
w->defaultMenuItem.set_active(w->name == info.default_sink_name);
|
||||||
|
w->updating = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::map<uint32_t, SourceWidget*>::iterator i = sourceWidgets.begin(); i != sourceWidgets.end(); ++i) {
|
||||||
|
SourceWidget *w = i->second;
|
||||||
|
|
||||||
|
if (!w)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
w->updating = true;
|
||||||
|
w->defaultMenuItem.set_active(w->name == info.default_source_name);
|
||||||
|
w->updating = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultSourceName = info.default_source_name;
|
||||||
|
defaultSinkName = info.default_sink_name;
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::updateDeviceVisibility() {
|
void MainWindow::updateDeviceVisibility() {
|
||||||
|
|
||||||
streamsVBox->hide_all();
|
streamsVBox->hide_all();
|
||||||
|
@ -896,6 +1020,18 @@ void client_cb(pa_context *, const pa_client_info *i, int eol, void *userdata) {
|
||||||
w->updateClient(*i);
|
w->updateClient(*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void server_info_cb(pa_context *, const pa_server_info *i, void *userdata) {
|
||||||
|
MainWindow *w = static_cast<MainWindow*>(userdata);
|
||||||
|
|
||||||
|
if (!i) {
|
||||||
|
show_error("Server info callback failure");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
w->updateServer(*i);
|
||||||
|
dec_outstanding(w);
|
||||||
|
}
|
||||||
|
|
||||||
void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index, void *userdata) {
|
void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index, void *userdata) {
|
||||||
MainWindow *w = static_cast<MainWindow*>(userdata);
|
MainWindow *w = static_cast<MainWindow*>(userdata);
|
||||||
|
|
||||||
|
@ -912,6 +1048,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);
|
||||||
|
@ -924,6 +1061,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);
|
||||||
|
@ -936,6 +1074,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);
|
||||||
|
@ -948,6 +1087,15 @@ 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_SERVER: {
|
||||||
|
pa_operation *o;
|
||||||
|
if (!(o = pa_context_get_server_info(c, server_info_cb, w))) {
|
||||||
|
show_error("pa_context_get_server_info() failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pa_operation_unref(o);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -968,12 +1116,23 @@ void context_state_callback(pa_context *c, void *userdata) {
|
||||||
|
|
||||||
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) (PA_SUBSCRIPTION_MASK_SINK|PA_SUBSCRIPTION_MASK_SOURCE|PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_CLIENT), NULL, NULL))) {
|
if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t)
|
||||||
|
(PA_SUBSCRIPTION_MASK_SINK|
|
||||||
|
PA_SUBSCRIPTION_MASK_SOURCE|
|
||||||
|
PA_SUBSCRIPTION_MASK_SINK_INPUT|
|
||||||
|
PA_SUBSCRIPTION_MASK_CLIENT|
|
||||||
|
PA_SUBSCRIPTION_MASK_SERVER), NULL, NULL))) {
|
||||||
show_error("pa_context_subscribe() failed");
|
show_error("pa_context_subscribe() failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pa_operation_unref(o);
|
pa_operation_unref(o);
|
||||||
|
|
||||||
|
if (!(o = pa_context_get_server_info(c, server_info_cb, w))) {
|
||||||
|
show_error("pa_context_get_server_info() failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
@ -998,7 +1157,7 @@ void context_state_callback(pa_context *c, void *userdata) {
|
||||||
}
|
}
|
||||||
pa_operation_unref(o);
|
pa_operation_unref(o);
|
||||||
|
|
||||||
n_outstanding = 4;
|
n_outstanding = 5;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue