summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2006-05-20 17:28:50 +0000
committerLennart Poettering <lennart@poettering.net>2006-05-20 17:28:50 +0000
commitd6deb8caf5e54dbd61dbb9a96c04d31c0fe7a379 (patch)
tree8342780a4b5efcd2d3cc1da7e038fc6aeba637ad
parent2e1bf7e600b4dfccf8ed443d28273ce06f4c7500 (diff)
Show client name for playback streams
git-svn-id: file:///home/lennart/svn/public/pavucontrol/trunk@14 c17c95f2-f111-0410-90bf-f30a9569010c
-rw-r--r--src/pavucontrol.cc120
-rw-r--r--src/pavucontrol.glade72
2 files changed, 154 insertions, 38 deletions
diff --git a/src/pavucontrol.cc b/src/pavucontrol.cc
index 0367e72..d6a7414 100644
--- a/src/pavucontrol.cc
+++ b/src/pavucontrol.cc
@@ -61,10 +61,10 @@ public:
StreamWidget(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& x);
void setChannelMap(const pa_channel_map &m);
- void setVolume(const pa_cvolume &volume);
+ void setVolume(const pa_cvolume &volume, bool force);
virtual void updateChannelVolume(int channel, pa_volume_t v);
- Gtk::Label *nameLabel;
+ Gtk::Label *nameLabel, *boldNameLabel;
Gtk::VBox *channelsVBox;
Gtk::ToggleButton *lockToggleButton, *muteToggleButton;
@@ -107,7 +107,7 @@ public:
SinkInputWidget(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& x);
static SinkInputWidget* create();
- uint32_t index;
+ uint32_t index, clientIndex;
virtual void executeVolumeUpdate();
};
@@ -115,14 +115,17 @@ class MainWindow : public Gtk::Window {
public:
MainWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& x);
static MainWindow* create();
+ virtual ~MainWindow();
void updateSink(const pa_sink_info &info);
void updateSource(const pa_source_info &info);
void updateSinkInput(const pa_sink_input_info &info);
+ void updateClient(const pa_client_info &info);
void removeSink(uint32_t index);
void removeSource(uint32_t index);
void removeSinkInput(uint32_t index);
+ void removeClient(uint32_t index);
Gtk::VBox *streamsVBox, *sinksVBox, *sourcesVBox, *monitorsVBox;
Gtk::EventBox *titleEventBox;
@@ -132,6 +135,7 @@ public:
std::map<int, SourceWidget*> sourceWidgets;
std::map<int, SourceWidget*> monitorWidgets;
std::map<int, SinkInputWidget*> streamWidgets;
+ std::map<int, char*> clientNames;
void updateLabels();
};
@@ -206,6 +210,7 @@ StreamWidget::StreamWidget(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Gl
x->get_widget("channelsVBox", channelsVBox);
x->get_widget("nameLabel", nameLabel);
+ x->get_widget("boldNameLabel", boldNameLabel);
x->get_widget("lockToggleButton", lockToggleButton);
x->get_widget("muteToggleButton", muteToggleButton);
@@ -231,25 +236,28 @@ void StreamWidget::setChannelMap(const pa_channel_map &m) {
lockToggleButton->set_sensitive(m.channels > 1);
}
-void StreamWidget::setVolume(const pa_cvolume &v) {
+void StreamWidget::setVolume(const pa_cvolume &v, bool force = false) {
g_assert(v.channels == channelMap.channels);
volume = v;
-
- for (int i = 0; i < volume.channels; i++)
- channelWidgets[i]->setVolume(volume.values[i]);
+
+ if (timeoutConnection.empty() || force) /* do not update the volume when a volume change is still in flux */
+ for (int i = 0; i < volume.channels; i++)
+ channelWidgets[i]->setVolume(volume.values[i]);
}
void StreamWidget::updateChannelVolume(int channel, pa_volume_t v) {
+ pa_cvolume n;
g_assert(channel < volume.channels);
+ n = volume;
if (lockToggleButton->get_active()) {
- for (int i = 0; i < volume.channels; i++)
- volume.values[i] = v;
+ for (int i = 0; i < n.channels; i++)
+ n.values[i] = v;
} else
- volume.values[channel] = v;
+ n.values[channel] = v;
- setVolume(volume);
+ setVolume(n, true);
if (timeoutConnection.empty())
timeoutConnection = Glib::signal_timeout().connect(sigc::mem_fun(*this, &StreamWidget::timeoutEvent), 50);
@@ -389,6 +397,11 @@ MainWindow* MainWindow::create() {
return w;
}
+MainWindow::~MainWindow() {
+ for (std::map<int, char*>::iterator i = clientNames.begin(); i != clientNames.end(); ++i)
+ g_free(i->second);
+}
+
void MainWindow::updateSink(const pa_sink_info &info) {
SinkWidget *w;
@@ -401,9 +414,12 @@ void MainWindow::updateSink(const pa_sink_info &info) {
w->index = info.index;
}
- char txt[256];
- snprintf(txt, sizeof(txt), "<b>%s</b> - %s", info.name, info.description);
- w->nameLabel->set_markup(txt);
+ gchar *txt;
+ w->boldNameLabel->set_markup(txt = g_markup_printf_escaped("<b>%s</b>", info.name));
+ g_free(txt);
+ w->nameLabel->set_markup(txt = g_markup_printf_escaped(": %s", info.description));
+ g_free(txt);
+
w->setVolume(info.volume);
w->muteToggleButton->set_active(info.mute);
w->onMuteToggleButton();
@@ -427,9 +443,12 @@ void MainWindow::updateSource(const pa_source_info &info) {
w->index = info.index;
}
- char txt[256];
- snprintf(txt, sizeof(txt), "<b>%s</b> - %s", info.name, info.description);
- w->nameLabel->set_markup(txt);
+ gchar *txt;
+ w->boldNameLabel->set_markup(txt = g_markup_printf_escaped("<b>%s</b>", info.name));
+ g_free(txt);
+ w->nameLabel->set_markup(txt = g_markup_printf_escaped(": %s", info.description));
+ g_free(txt);
+
w->setVolume(info.volume);
w->muteToggleButton->set_active(info.mute);
w->onMuteToggleButton();
@@ -449,17 +468,39 @@ void MainWindow::updateSinkInput(const pa_sink_input_info &info) {
streamsVBox->pack_start(*w, false, false, 0);
w->muteToggleButton->hide();
w->index = info.index;
+ w->clientIndex = info.client;
}
- char txt[256];
- snprintf(txt, sizeof(txt), "<b>%s</b>", info.name);
- w->nameLabel->set_markup(txt);
+ char *txt;
+ w->boldNameLabel->set_markup(txt = g_markup_printf_escaped("<b>%s</b>", clientNames[info.client]));
+ g_free(txt);
+ w->nameLabel->set_markup(txt = g_markup_printf_escaped(": %s", info.name));
+ g_free(txt);
w->setVolume(info.volume);
updateLabels();
w->check_resize();
}
+void MainWindow::updateClient(const pa_client_info &info) {
+
+ g_free(clientNames[info.index]);
+ clientNames[info.index] = g_strdup(info.name);
+
+ for (std::map<int, SinkInputWidget*>::iterator i = streamWidgets.begin(); i != streamWidgets.end(); ++i) {
+ SinkInputWidget *w = i->second;
+
+ if (!w)
+ continue;
+
+ if (w->clientIndex == info.index) {
+ gchar *txt;
+ w->boldNameLabel->set_markup(txt = g_markup_printf_escaped("<b>%s</b>", info.name));
+ g_free(txt);
+ }
+ }
+}
+
void MainWindow::updateLabels() {
if (streamWidgets.empty())
noStreamsLabel->show();
@@ -520,6 +561,11 @@ void MainWindow::removeSinkInput(uint32_t index) {
updateLabels();
}
+void MainWindow::removeClient(uint32_t index) {
+ g_free(clientNames[index]);
+ clientNames.erase(index);
+}
+
void sink_cb(pa_context *, const pa_sink_info *i, int eol, void *userdata) {
MainWindow *w = static_cast<MainWindow*>(userdata);
@@ -562,6 +608,20 @@ void sink_input_cb(pa_context *, const pa_sink_input_info *i, int eol, void *use
w->updateSinkInput(*i);
}
+void client_cb(pa_context *, const pa_client_info *i, int eol, void *userdata) {
+ MainWindow *w = static_cast<MainWindow*>(userdata);
+
+ if (eol)
+ return;
+
+ if (!i) {
+ show_error("Client callback failure");
+ return;
+ }
+
+ w->updateClient(*i);
+}
+
void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index, void *userdata) {
MainWindow *w = static_cast<MainWindow*>(userdata);
@@ -602,6 +662,18 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
pa_operation_unref(o);
}
break;
+ case PA_SUBSCRIPTION_EVENT_CLIENT:
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE)
+ w->removeClient(index);
+ else {
+ pa_operation *o;
+ if (!(o = pa_context_get_client_info(c, index, client_cb, w))) {
+ show_error("pa_context_get_client_info() failed");
+ return;
+ }
+ pa_operation_unref(o);
+ }
+ break;
}
}
@@ -622,12 +694,18 @@ void context_state_callback(pa_context *c, void *userdata) {
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), 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), NULL, NULL))) {
show_error("pa_context_subscribe() failed");
return;
}
pa_operation_unref(o);
+ if (!(o = pa_context_get_client_info_list(c, client_cb, w))) {
+ show_error("pa_context_client_info_list() failed");
+ return;
+ }
+ pa_operation_unref(o);
+
if (!(o = pa_context_get_sink_info_list(c, sink_cb, w))) {
show_error("pa_context_get_sink_info_list() failed");
return;
diff --git a/src/pavucontrol.glade b/src/pavucontrol.glade
index 5aa2676..f2ab807 100644
--- a/src/pavucontrol.glade
+++ b/src/pavucontrol.glade
@@ -497,22 +497,60 @@
<property name="spacing">6</property>
<child>
- <widget class="GtkLabel" id="nameLabel">
+ <widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
- <property name="label" translatable="yes">&lt;b&gt;MPlayer&lt;/b&gt; - A good movie</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">0</property>
- <property name="ypad">0</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_END</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="boldNameLabel">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></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.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>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="nameLabel">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Stream Title</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">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</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">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="padding">0</property>
@@ -547,7 +585,7 @@
<widget class="GtkImage" id="image18">
<property name="visible">True</property>
<property name="stock">gtk-dialog-authentication</property>
- <property name="icon_size">4</property>
+ <property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
@@ -576,7 +614,7 @@
<widget class="GtkImage" id="image17">
<property name="visible">True</property>
<property name="stock">gtk-dialog-error</property>
- <property name="icon_size">4</property>
+ <property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>