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("lockToggleButton", lockToggleButton);
|
||||||
x->get_widget("muteToggleButton", muteToggleButton);
|
x->get_widget("muteToggleButton", muteToggleButton);
|
||||||
x->get_widget("defaultToggleButton", defaultToggleButton);
|
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));
|
muteToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &DeviceWidget::onMuteToggleButton));
|
||||||
defaultToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &DeviceWidget::onDefaultToggleButton));
|
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++)
|
for (unsigned i = 0; i < PA_CHANNELS_MAX; i++)
|
||||||
channelWidgets[i] = NULL;
|
channelWidgets[i] = NULL;
|
||||||
}
|
}
|
||||||
|
@ -121,3 +129,27 @@ void DeviceWidget::setSteps(unsigned n) {
|
||||||
for (int i = 0; i < channelMap.channels; i++)
|
for (int i = 0; i < channelMap.channels; i++)
|
||||||
channelWidgets[channelMap.channels-1]->setSteps(n);
|
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 executeVolumeUpdate();
|
||||||
virtual void setBaseVolume(pa_volume_t v);
|
virtual void setBaseVolume(pa_volume_t v);
|
||||||
virtual void setSteps(unsigned n);
|
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
|
#endif
|
||||||
|
|
|
@ -37,13 +37,31 @@
|
||||||
|
|
||||||
/* Used for profile sorting */
|
/* Used for profile sorting */
|
||||||
struct profile_prio_compare {
|
struct profile_prio_compare {
|
||||||
bool operator() (const pa_card_profile_info& lhs, const pa_card_profile_info& rhs) const {
|
bool operator() (const pa_card_profile_info& lhs, const pa_card_profile_info& rhs) const {
|
||||||
|
|
||||||
if (lhs.priority == rhs.priority)
|
if (lhs.priority == rhs.priority)
|
||||||
return strcmp(lhs.name, rhs.name) > 0;
|
return strcmp(lhs.name, rhs.name) > 0;
|
||||||
|
|
||||||
return lhs.priority > rhs.priority;
|
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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -162,11 +180,10 @@ void MainWindow::updateCard(const pa_card_info &info) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w->profiles.clear();
|
w->profiles.clear();
|
||||||
|
|
||||||
for (std::set<pa_card_profile_info>::iterator i = profile_priorities.begin(); i != profile_priorities.end(); ++i)
|
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->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;
|
w->updating = false;
|
||||||
|
|
||||||
|
@ -180,6 +197,7 @@ void MainWindow::updateSink(const pa_sink_info &info) {
|
||||||
SinkWidget *w;
|
SinkWidget *w;
|
||||||
bool is_new = false;
|
bool is_new = false;
|
||||||
const char *icon;
|
const char *icon;
|
||||||
|
std::set<pa_sink_port_info,sink_port_prio_compare> port_priorities;
|
||||||
|
|
||||||
if (sinkWidgets.count(info.index))
|
if (sinkWidgets.count(info.index))
|
||||||
w = sinkWidgets[info.index];
|
w = sinkWidgets[info.index];
|
||||||
|
@ -216,8 +234,21 @@ void MainWindow::updateSink(const pa_sink_info &info) {
|
||||||
|
|
||||||
w->setDefault(w->name == defaultSinkName);
|
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->updating = false;
|
||||||
|
|
||||||
|
w->prepareMenu();
|
||||||
|
|
||||||
if (is_new)
|
if (is_new)
|
||||||
updateDeviceVisibility();
|
updateDeviceVisibility();
|
||||||
}
|
}
|
||||||
|
@ -327,6 +358,7 @@ void MainWindow::updateSource(const pa_source_info &info) {
|
||||||
SourceWidget *w;
|
SourceWidget *w;
|
||||||
bool is_new = false;
|
bool is_new = false;
|
||||||
const char *icon;
|
const char *icon;
|
||||||
|
std::set<pa_source_port_info,source_port_prio_compare> port_priorities;
|
||||||
|
|
||||||
if (sourceWidgets.count(info.index))
|
if (sourceWidgets.count(info.index))
|
||||||
w = sourceWidgets[info.index];
|
w = sourceWidgets[info.index];
|
||||||
|
@ -364,8 +396,21 @@ void MainWindow::updateSource(const pa_source_info &info) {
|
||||||
|
|
||||||
w->setDefault(w->name == defaultSourceName);
|
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->updating = false;
|
||||||
|
|
||||||
|
w->prepareMenu();
|
||||||
|
|
||||||
if (is_new)
|
if (is_new)
|
||||||
updateDeviceVisibility();
|
updateDeviceVisibility();
|
||||||
}
|
}
|
||||||
|
|
|
@ -797,6 +797,35 @@ Monitors</property>
|
||||||
<property name="position">0</property>
|
<property name="position">0</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</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>
|
<child>
|
||||||
<widget class="GtkVBox" id="channelsVBox">
|
<widget class="GtkVBox" id="channelsVBox">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
@ -811,7 +840,7 @@ Monitors</property>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">False</property>
|
<property name="fill">False</property>
|
||||||
<property name="position">1</property>
|
<property name="position">2</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
|
|
|
@ -75,3 +75,28 @@ void SinkWidget::onDefaultToggleButton() {
|
||||||
}
|
}
|
||||||
pa_operation_unref(o);
|
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 onMuteToggleButton();
|
||||||
virtual void executeVolumeUpdate();
|
virtual void executeVolumeUpdate();
|
||||||
virtual void onDefaultToggleButton();
|
virtual void onDefaultToggleButton();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void onPortChange();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -75,3 +75,28 @@ void SourceWidget::onDefaultToggleButton() {
|
||||||
}
|
}
|
||||||
pa_operation_unref(o);
|
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 onMuteToggleButton();
|
||||||
virtual void executeVolumeUpdate();
|
virtual void executeVolumeUpdate();
|
||||||
virtual void onDefaultToggleButton();
|
virtual void onDefaultToggleButton();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void onPortChange();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue