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:
parent
7b3083df57
commit
159609135f
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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"><b>Port:</b></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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,9 @@ public:
|
|||
virtual void onMuteToggleButton();
|
||||
virtual void executeVolumeUpdate();
|
||||
virtual void onDefaultToggleButton();
|
||||
|
||||
protected:
|
||||
virtual void onPortChange();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -39,6 +39,9 @@ public:
|
|||
virtual void onMuteToggleButton();
|
||||
virtual void executeVolumeUpdate();
|
||||
virtual void onDefaultToggleButton();
|
||||
|
||||
protected:
|
||||
virtual void onPortChange();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue