Show client name for playback streams

git-svn-id: file:///home/lennart/svn/public/pavucontrol/trunk@14 c17c95f2-f111-0410-90bf-f30a9569010c
This commit is contained in:
Lennart Poettering 2006-05-20 17:28:50 +00:00
parent 2e1bf7e600
commit d6deb8caf5
2 changed files with 154 additions and 38 deletions

View File

@ -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;

View File

@ -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>