[pulseaudio-discuss] [PATCH 3/3] devicewidget: Add a latency offset spinbutton
poljar (Damir Jelić)
poljarinho at gmail.com
Sun Jul 22 06:23:26 PDT 2012
From: "poljar (Damir Jelić)" <poljarinho at gmail.com>
This change adds the ability to change the latency offset of a port with
pavucontrol.
---
src/devicewidget.cc | 47 ++++++++++++++++++++++++++--
src/devicewidget.h | 10 ++++--
src/mainwindow.cc | 35 +++++++++++++++++++++
src/pavucontrol.glade | 87 +++++++++++++++++++++++++++++++++++++++++----------
4 files changed, 159 insertions(+), 20 deletions(-)
diff --git a/src/devicewidget.cc b/src/devicewidget.cc
index dda1763..bb30c0d 100644
--- a/src/devicewidget.cc
+++ b/src/devicewidget.cc
@@ -39,6 +39,8 @@ DeviceWidget::DeviceWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Buil
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 +56,13 @@ DeviceWidget::DeviceWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Buil
portList->pack_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 +126,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 +160,14 @@ bool DeviceWidget::timeoutEvent() {
void DeviceWidget::executeVolumeUpdate() {
}
+void DeviceWidget::updatePorts(std::map<Glib::ustring, PortInfo> &ports) {
+ if (pa_context_get_server_protocol_version(get_context()) >= 27) {
+ offsetButtonEnabled = false;
+ offsetButton->set_value(ports.find(activePort)->second.latency_offset / 1000.0);
+ offsetButtonEnabled = true;
+ }
+}
+
void DeviceWidget::setBaseVolume(pa_volume_t v) {
for (int i = 0; i < channelMap.channels; i++)
@@ -157,10 +192,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..2d66204 100644
--- a/src/devicewidget.h
+++ b/src/devicewidget.h
@@ -24,6 +24,7 @@
#include "pavucontrol.h"
#include "minimalstreamwidget.h"
+#include "cardwidget.h"
class MainWindow;
class ChannelWidget;
@@ -42,6 +43,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 +56,8 @@ public:
virtual void onDefaultToggleButton();
virtual void setDefault(bool isDefault);
virtual bool onContextTriggerEvent(GdkEventButton*);
+ virtual void updatePorts(std::map<Glib::ustring, PortInfo> &ports);
+ void onOffsetChange();
sigc::connection timeoutConnection;
@@ -75,7 +81,6 @@ protected:
Gtk::Menu contextMenu;
Gtk::MenuItem rename;
-
/* Tree model columns */
class ModelColumns : public Gtk::TreeModel::ColumnRecord
{
@@ -90,9 +95,10 @@ protected:
ModelColumns portModel;
- Gtk::HBox *portSelect;
+ Gtk::HBox *portSelect, *offsetSelect;
Gtk::ComboBox *portList;
Glib::RefPtr<Gtk::ListStore> treeModel;
+ Glib::RefPtr<Gtk::Adjustment> offsetAdjustment;
private:
Glib::ustring mDeviceType;
diff --git a/src/mainwindow.cc b/src/mainwindow.cc
index b167943..add797e 100644
--- a/src/mainwindow.cc
+++ b/src/mainwindow.cc
@@ -309,6 +309,37 @@ void MainWindow::updateCard(const pa_card_info &info) {
}
}
+ /* 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<uint32_t, SinkWidget*>::iterator it;
+
+ for (it = sinkWidgets.begin() ; it != sinkWidgets.end(); it++) {
+ SinkWidget *sw = (*it).second;
+
+ if (sw->card_index == w->index) {
+ sw->updating = true;
+ sw->updatePorts(w->ports);
+ sw->updating = false;
+ }
+ }
+ }
+
+ if (w->hasSources) {
+ std::map<uint32_t, SourceWidget*>::iterator it;
+
+ for (it = sourceWidgets.begin() ; it != sourceWidgets.end(); it++) {
+ SourceWidget *sw = (*it).second;
+
+ if (sw->card_index == w->index) {
+ sw->updating = true;
+ sw->updatePorts(w->ports);
+ sw->updating = false;
+ }
+ }
+ }
+
w->updating = false;
w->prepareMenu();
@@ -367,6 +398,8 @@ bool MainWindow::updateSink(const pa_sink_info &info) {
w->activePort = info.active_port ? info.active_port->name : "";
+ w->updatePorts(cardWidgets[info.card]->ports);
+
#ifdef PA_SINK_SET_FORMATS
w->setDigital(info.flags & PA_SINK_SET_FORMATS);
#endif
@@ -516,6 +549,8 @@ void MainWindow::updateSource(const pa_source_info &info) {
w->activePort = info.active_port ? info.active_port->name : "";
+ w->updatePorts(cardWidgets[info.card]->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 @@
<property name="spacing">3</property>
<child>
<object class="GtkToggleButton" id="muteToggleButton">
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Mute audio</property>
- <property name="use_action_appearance">False</property>
<property name="relief">none</property>
<child>
<object class="GtkImage" id="image20">
@@ -300,11 +300,11 @@
</child>
<child>
<object class="GtkToggleButton" id="lockToggleButton">
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Lock channels together</property>
- <property name="use_action_appearance">False</property>
<property name="relief">none</property>
<property name="active">True</property>
<child>
@@ -324,11 +324,11 @@
</child>
<child>
<object class="GtkToggleButton" id="defaultToggleButton">
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Set as fallback</property>
- <property name="use_action_appearance">False</property>
<child>
<object class="GtkImage" id="image2">
<property name="visible">True</property>
@@ -395,18 +395,76 @@
</packing>
</child>
<child>
+ <object class="GtkHBox" id="offsetSelect">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes"><b>Latency offset:</b></property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="offsetButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">•</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">ms</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkTable" id="encodingSelect">
<property name="can_focus">False</property>
<property name="n_rows">2</property>
<property name="n_columns">3</property>
<child>
+ <placeholder/>
+ </child>
+ <child>
<object class="GtkCheckButton" id="encodingFormatPCM">
<property name="label" translatable="yes">PCM</property>
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
- <property name="use_action_appearance">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</object>
@@ -414,10 +472,10 @@
<child>
<object class="GtkCheckButton" id="encodingFormatAC3">
<property name="label" translatable="yes">AC3</property>
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
- <property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
@@ -428,10 +486,10 @@
<child>
<object class="GtkCheckButton" id="encodingFormatDTS">
<property name="label" translatable="yes">DTS</property>
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
- <property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
@@ -442,10 +500,10 @@
<child>
<object class="GtkCheckButton" id="encodingFormatEAC3">
<property name="label" translatable="yes">EAC3</property>
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
- <property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
@@ -456,10 +514,10 @@
<child>
<object class="GtkCheckButton" id="encodingFormatMPEG">
<property name="label" translatable="yes">MPEG</property>
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
- <property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
@@ -469,14 +527,11 @@
<property name="bottom_attach">2</property>
</packing>
</child>
- <child>
- <placeholder/>
- </child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
- <property name="position">2</property>
+ <property name="position">3</property>
</packing>
</child>
<child>
@@ -494,7 +549,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
- <property name="position">3</property>
+ <property name="position">4</property>
</packing>
</child>
</object>
@@ -1316,10 +1371,10 @@
<child>
<object class="GtkButton" id="deviceButton">
<property name="label" translatable="yes">Device</property>
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
- <property name="use_action_appearance">False</property>
<property name="relief">half</property>
<property name="xalign">0</property>
</object>
@@ -1344,11 +1399,11 @@
<property name="spacing">3</property>
<child>
<object class="GtkToggleButton" id="muteToggleButton">
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Mute audio</property>
- <property name="use_action_appearance">False</property>
<property name="relief">none</property>
<child>
<object class="GtkImage" id="image20">
@@ -1367,11 +1422,11 @@
</child>
<child>
<object class="GtkToggleButton" id="lockToggleButton">
+ <property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Lock channels together</property>
- <property name="use_action_appearance">False</property>
<property name="relief">none</property>
<property name="active">True</property>
<child>
--
1.7.11.2
More information about the pulseaudio-discuss
mailing list