Add support for changing ports.

This commit adds a combo box for selecting ports.
Overall this implementation could have taken two paths:
 * Implement port selection as combo box.
 * Implement port selection as a button.

I went for the first option as is done in selecting card profiles over the
second method used for selecting devices for streams. This seems more like
how a config option should be presented as opposed to a runtime type thing.
This commit is contained in:
Colin Guthrie 2009-06-27 18:14:05 +01:00
parent 7b3083df57
commit 159609135f
8 changed files with 200 additions and 12 deletions

View File

@ -32,10 +32,18 @@ DeviceWidget::DeviceWidget(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Gl
x->get_widget("lockToggleButton", lockToggleButton);
x->get_widget("muteToggleButton", muteToggleButton);
x->get_widget("defaultToggleButton", defaultToggleButton);
x->get_widget("portSelect", portSelect);
x->get_widget("portList", portList);
muteToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &DeviceWidget::onMuteToggleButton));
defaultToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &DeviceWidget::onDefaultToggleButton));
treeModel = Gtk::ListStore::create(portModel);
portList->set_model(treeModel);
portList->pack_start(portModel.desc);
portList->signal_changed().connect( sigc::mem_fun(*this, &DeviceWidget::onPortChange));
for (unsigned i = 0; i < PA_CHANNELS_MAX; i++)
channelWidgets[i] = NULL;
}
@ -121,3 +129,27 @@ void DeviceWidget::setSteps(unsigned n) {
for (int i = 0; i < channelMap.channels; i++)
channelWidgets[channelMap.channels-1]->setSteps(n);
}
void DeviceWidget::prepareMenu() {
int idx = 0;
int active_idx = -1;
treeModel->clear();
/* Fill the ComboBox's Tree Model */
for (uint32_t i = 0; i < ports.size(); ++i) {
Gtk::TreeModel::Row row = *(treeModel->append());
row[portModel.name] = ports[i].first;
row[portModel.desc] = ports[i].second;
if (ports[i].first == activePort)
active_idx = idx;
idx++;
}
if (active_idx >= 0)
portList->set_active(active_idx);
if (ports.size() > 0)
portSelect->show();
else
portSelect->hide();
}

View File

@ -53,6 +53,32 @@ public:
virtual void executeVolumeUpdate();
virtual void setBaseVolume(pa_volume_t v);
virtual void setSteps(unsigned n);
std::vector< std::pair<Glib::ustring,Glib::ustring> > ports;
Glib::ustring activePort;
void prepareMenu();
protected:
virtual void onPortChange() = 0;
/* Tree model columns */
class ModelColumns : public Gtk::TreeModel::ColumnRecord
{
public:
ModelColumns()
{ add(name); add(desc); }
Gtk::TreeModelColumn<Glib::ustring> name;
Gtk::TreeModelColumn<Glib::ustring> desc;
};
ModelColumns portModel;
Gtk::HBox *portSelect;
Gtk::ComboBox *portList;
Glib::RefPtr<Gtk::ListStore> treeModel;
};
#endif

View File

@ -45,6 +45,24 @@ struct profile_prio_compare {
return lhs.priority > rhs.priority;
}
};
struct sink_port_prio_compare {
bool operator() (const pa_sink_port_info& lhs, const pa_sink_port_info& rhs) const {
if (lhs.priority == rhs.priority)
return strcmp(lhs.name, rhs.name) > 0;
return lhs.priority > rhs.priority;
}
};
struct source_port_prio_compare {
bool operator() (const pa_source_port_info& lhs, const pa_source_port_info& rhs) const {
if (lhs.priority == rhs.priority)
return strcmp(lhs.name, rhs.name) > 0;
return lhs.priority > rhs.priority;
}
};
MainWindow::MainWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& x) :
@ -162,11 +180,10 @@ void MainWindow::updateCard(const pa_card_info &info) {
}
w->profiles.clear();
for (std::set<pa_card_profile_info>::iterator i = profile_priorities.begin(); i != profile_priorities.end(); ++i)
w->profiles.push_back(std::pair<Glib::ustring,Glib::ustring>(i->name, i->description));
w->activeProfile = info.active_profile->name;
w->activeProfile = info.active_profile ? info.active_profile->name : "";
w->updating = false;
@ -180,6 +197,7 @@ void MainWindow::updateSink(const pa_sink_info &info) {
SinkWidget *w;
bool is_new = false;
const char *icon;
std::set<pa_sink_port_info,sink_port_prio_compare> port_priorities;
if (sinkWidgets.count(info.index))
w = sinkWidgets[info.index];
@ -216,8 +234,21 @@ void MainWindow::updateSink(const pa_sink_info &info) {
w->setDefault(w->name == defaultSinkName);
port_priorities.clear();
for (uint32_t i=0; i<info.n_ports; ++i) {
port_priorities.insert(*info.ports[i]);
}
w->ports.clear();
for (std::set<pa_sink_port_info>::iterator i = port_priorities.begin(); i != port_priorities.end(); ++i)
w->ports.push_back(std::pair<Glib::ustring,Glib::ustring>(i->name, i->description));
w->activePort = info.active_port ? info.active_port->name : "";
w->updating = false;
w->prepareMenu();
if (is_new)
updateDeviceVisibility();
}
@ -327,6 +358,7 @@ void MainWindow::updateSource(const pa_source_info &info) {
SourceWidget *w;
bool is_new = false;
const char *icon;
std::set<pa_source_port_info,source_port_prio_compare> port_priorities;
if (sourceWidgets.count(info.index))
w = sourceWidgets[info.index];
@ -364,8 +396,21 @@ void MainWindow::updateSource(const pa_source_info &info) {
w->setDefault(w->name == defaultSourceName);
port_priorities.clear();
for (uint32_t i=0; i<info.n_ports; ++i) {
port_priorities.insert(*info.ports[i]);
}
w->ports.clear();
for (std::set<pa_source_port_info>::iterator i = port_priorities.begin(); i != port_priorities.end(); ++i)
w->ports.push_back(std::pair<Glib::ustring,Glib::ustring>(i->name, i->description));
w->activePort = info.active_port ? info.active_port->name : "";
w->updating = false;
w->prepareMenu();
if (is_new)
updateDeviceVisibility();
}

View File

@ -797,6 +797,35 @@ Monitors</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="portSelect">
<property name="visible">True</property>
<property name="spacing">6</property>
<child>
<widget class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">&lt;b&gt;Port:&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkComboBox" id="portList">
<property name="visible">True</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="channelsVBox">
<property name="visible">True</property>
@ -811,7 +840,7 @@ Monitors</property>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
<property name="position">2</property>
</packing>
</child>
</widget>

View File

@ -75,3 +75,28 @@ void SinkWidget::onDefaultToggleButton() {
}
pa_operation_unref(o);
}
void SinkWidget::onPortChange() {
Gtk::TreeModel::iterator iter;
if (updating)
return;
iter = portList->get_active();
if (iter)
{
Gtk::TreeModel::Row row = *iter;
if (row)
{
pa_operation* o;
Glib::ustring port = row[portModel.name];
if (!(o = pa_context_set_sink_port_by_index(get_context(), index, port.c_str(), NULL, NULL))) {
show_error(_("pa_context_set_sink_port_by_index() failed"));
return;
}
pa_operation_unref(o);
}
}
}

View File

@ -39,6 +39,9 @@ public:
virtual void onMuteToggleButton();
virtual void executeVolumeUpdate();
virtual void onDefaultToggleButton();
protected:
virtual void onPortChange();
};
#endif

View File

@ -75,3 +75,28 @@ void SourceWidget::onDefaultToggleButton() {
}
pa_operation_unref(o);
}
void SourceWidget::onPortChange() {
Gtk::TreeModel::iterator iter;
if (updating)
return;
iter = portList->get_active();
if (iter)
{
Gtk::TreeModel::Row row = *iter;
if (row)
{
pa_operation* o;
Glib::ustring port = row[portModel.name];
if (!(o = pa_context_set_source_port_by_index(get_context(), index, port.c_str(), NULL, NULL))) {
show_error(_("pa_context_set_source_port_by_index() failed"));
return;
}
pa_operation_unref(o);
}
}
}

View File

@ -39,6 +39,9 @@ public:
virtual void onMuteToggleButton();
virtual void executeVolumeUpdate();
virtual void onDefaultToggleButton();
protected:
virtual void onPortChange();
};
#endif