From d03f9ffac22a867c746015cf84d3e87fef3ec5ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?poljar=20=28Damir=20Jeli=C4=87=29?= Date: Thu, 26 Jul 2012 15:42:11 +0200 Subject: [PATCH] devicewidget: Add a latency offset spinbutton This change adds the ability to change the latency offset of a port with pavucontrol. --- src/devicewidget.cc | 48 ++++++++++++++++++++++-- src/devicewidget.h | 9 ++++- src/mainwindow.cc | 54 +++++++++++++++++++++++++++ src/pavucontrol.glade | 87 +++++++++++++++++++++++++++++++++++-------- 4 files changed, 177 insertions(+), 21 deletions(-) diff --git a/src/devicewidget.cc b/src/devicewidget.cc index dda1763..ba08cc8 100644 --- a/src/devicewidget.cc +++ b/src/devicewidget.cc @@ -32,13 +32,16 @@ /*** DeviceWidget ***/ DeviceWidget::DeviceWidget(BaseObjectType* cobject, const Glib::RefPtr& x) : - MinimalStreamWidget(cobject, x) { + MinimalStreamWidget(cobject, x), + offsetButtonEnabled(false) { 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); + x->get_widget("offsetSelect", offsetSelect); + x->get_widget("offsetButton", offsetButton); this->signal_button_press_event().connect(sigc::mem_fun(*this, &DeviceWidget::onContextTriggerEvent)); muteToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &DeviceWidget::onMuteToggleButton)); @@ -54,9 +57,13 @@ DeviceWidget::DeviceWidget(BaseObjectType* cobject, const Glib::RefPtrpack_start(portModel.desc); portList->signal_changed().connect(sigc::mem_fun(*this, &DeviceWidget::onPortChange)); + offsetButton->signal_value_changed().connect(sigc::mem_fun(*this, &DeviceWidget::onOffsetChange)); for (unsigned i = 0; i < PA_CHANNELS_MAX; i++) channelWidgets[i] = NULL; + + offsetAdjustment = Gtk::Adjustment::create(0.0, -2000.0, 2000.0, 10.0, 50.0, 0.0); + offsetButton->configure(offsetAdjustment, 0, 2); } void DeviceWidget::init(MainWindow* mainWindow, Glib::ustring deviceType) { @@ -120,6 +127,27 @@ void DeviceWidget::onMuteToggleButton() { void DeviceWidget::onDefaultToggleButton() { } +void DeviceWidget::onOffsetChange() { + pa_operation *o; + int64_t offset; + std::ostringstream card_stream; + Glib::ustring card_name; + + if (!offsetButtonEnabled) + return; + + offset = offsetButton->get_value() * 1000.0; + card_stream << card_index; + card_name = card_stream.str(); + + if (!(o = pa_context_set_port_latency_offset(get_context(), + card_name.c_str(), activePort.c_str(), offset, NULL, NULL))) { + show_error(_("pa_context_set_port_latency_offset() failed")); + return; + } + pa_operation_unref(o); +} + void DeviceWidget::setDefault(bool isDefault) { defaultToggleButton->set_active(isDefault); /*defaultToggleButton->set_sensitive(!isDefault);*/ @@ -133,6 +161,12 @@ bool DeviceWidget::timeoutEvent() { void DeviceWidget::executeVolumeUpdate() { } +void DeviceWidget::setLatencyOffset(int64_t offset) { + offsetButtonEnabled = false; + offsetButton->set_value(offset / 1000.0); + offsetButtonEnabled = true; +} + void DeviceWidget::setBaseVolume(pa_volume_t v) { for (int i = 0; i < channelMap.channels; i++) @@ -157,10 +191,18 @@ void DeviceWidget::prepareMenu() { if (active_idx >= 0) portList->set_active(active_idx); - if (ports.size() > 0) + if (ports.size() > 0) { portSelect->show(); - else + + if (pa_context_get_server_protocol_version(get_context()) >= 27) + offsetSelect->show(); + else + offsetSelect->hide(); + + } else { portSelect->hide(); + offsetSelect->hide(); + } } bool DeviceWidget::onContextTriggerEvent(GdkEventButton* event) { diff --git a/src/devicewidget.h b/src/devicewidget.h index 94f14e6..f099e6e 100644 --- a/src/devicewidget.h +++ b/src/devicewidget.h @@ -42,6 +42,9 @@ public: uint32_t index, card_index; Gtk::ToggleButton *lockToggleButton, *muteToggleButton, *defaultToggleButton; + Gtk::SpinButton *offsetButton; + + bool offsetButtonEnabled; pa_channel_map channelMap; pa_cvolume volume; @@ -52,6 +55,8 @@ public: virtual void onDefaultToggleButton(); virtual void setDefault(bool isDefault); virtual bool onContextTriggerEvent(GdkEventButton*); + virtual void setLatencyOffset(int64_t offset); + void onOffsetChange(); sigc::connection timeoutConnection; @@ -75,7 +80,6 @@ protected: Gtk::Menu contextMenu; Gtk::MenuItem rename; - /* Tree model columns */ class ModelColumns : public Gtk::TreeModel::ColumnRecord { @@ -90,9 +94,10 @@ protected: ModelColumns portModel; - Gtk::HBox *portSelect; + Gtk::HBox *portSelect, *offsetSelect; Gtk::ComboBox *portList; Glib::RefPtr treeModel; + Glib::RefPtr offsetAdjustment; private: Glib::ustring mDeviceType; diff --git a/src/mainwindow.cc b/src/mainwindow.cc index fe085ef..ac5f916 100644 --- a/src/mainwindow.cc +++ b/src/mainwindow.cc @@ -252,6 +252,17 @@ static void set_icon_name_fallback(Gtk::Image *i, const char *name, Gtk::IconSiz } } +static void updatePorts(DeviceWidget *w, std::map &ports) { + std::map::iterator it; + + it = ports.find(w->activePort); + + if (it != ports.end()) { + PortInfo &activePort = it->second; + w->setLatencyOffset(activePort.latency_offset); + } +} + void MainWindow::updateCard(const pa_card_info &info) { CardWidget *w; bool is_new = false; @@ -304,6 +315,37 @@ void MainWindow::updateCard(const pa_card_info &info) { w->ports[p.name] = p; } + /* Because the port info for sinks and sources is discontinued we need + * to update the port info for them here. */ + + if (w->hasSinks) { + std::map::iterator it; + + for (it = sinkWidgets.begin() ; it != sinkWidgets.end(); it++) { + SinkWidget *sw = (*it).second; + + if (sw->card_index == w->index) { + sw->updating = true; + updatePorts(sw, w->ports); + sw->updating = false; + } + } + } + + if (w->hasSources) { + std::map::iterator it; + + for (it = sourceWidgets.begin() ; it != sourceWidgets.end(); it++) { + SourceWidget *sw = (*it).second; + + if (sw->card_index == w->index) { + sw->updating = true; + updatePorts(sw, w->ports); + sw->updating = false; + } + } + } + w->updating = false; w->prepareMenu(); @@ -316,6 +358,7 @@ bool MainWindow::updateSink(const pa_sink_info &info) { SinkWidget *w; bool is_new = false; const char *icon; + std::map::iterator cw; std::set port_priorities; if (sinkWidgets.count(info.index)) @@ -362,6 +405,11 @@ bool MainWindow::updateSink(const pa_sink_info &info) { w->activePort = info.active_port ? info.active_port->name : ""; + cw = cardWidgets.find(info.card); + + if (cw != cardWidgets.end()) + updatePorts(w, cw->second->ports); + #ifdef PA_SINK_SET_FORMATS w->setDigital(info.flags & PA_SINK_SET_FORMATS); #endif @@ -463,6 +511,7 @@ void MainWindow::updateSource(const pa_source_info &info) { SourceWidget *w; bool is_new = false; const char *icon; + std::map::iterator cw; std::set port_priorities; if (sourceWidgets.count(info.index)) @@ -511,6 +560,11 @@ void MainWindow::updateSource(const pa_source_info &info) { w->activePort = info.active_port ? info.active_port->name : ""; + cw = cardWidgets.find(info.card); + + if (cw != cardWidgets.end()) + updatePorts(w, cw->second->ports); + w->updating = false; w->prepareMenu(); diff --git a/src/pavucontrol.glade b/src/pavucontrol.glade index e569ba6..befdee0 100644 --- a/src/pavucontrol.glade +++ b/src/pavucontrol.glade @@ -277,11 +277,11 @@ 3 + False True True False Mute audio - False none @@ -300,11 +300,11 @@ + False True True False Lock channels together - False none True @@ -324,11 +324,11 @@ + False True True False Set as fallback - False True @@ -394,19 +394,77 @@ 1 + + + True + False + 6 + + + True + False + 0 + <b>Latency offset:</b> + True + + + False + True + 0 + + + + + True + True + + False + False + True + True + + + True + True + 1 + + + + + True + False + ms + True + + + False + True + 2 + + + + + False + False + 2 + + False 2 3 + + + PCM + False True False True False - False True True @@ -414,10 +472,10 @@ AC3 + False True True False - False True @@ -428,10 +486,10 @@ DTS + False True True False - False True @@ -442,10 +500,10 @@ EAC3 + False True True False - False True @@ -456,10 +514,10 @@ MPEG + False True True False - False True @@ -469,14 +527,11 @@ 2 - - - False False - 2 + 3 @@ -494,7 +549,7 @@ False False - 3 + 4 @@ -1316,10 +1371,10 @@ Device + False True True True - False half 0 @@ -1344,11 +1399,11 @@ 3 + False True True False Mute audio - False none @@ -1367,11 +1422,11 @@ + False True True False Lock channels together - False none True