[pulseaudio-commits] src/mainwindow.cc src/mainwindow.h src/pavucontrol.cc src/pavucontrol.glade src/pavucontrol.h src/sinkwidget.cc src/sinkwidget.h

Colin Guthrie colin at kemper.freedesktop.org
Wed Aug 10 05:23:23 PDT 2011


 src/mainwindow.cc     |   42 +++++++++++++++++++++-
 src/mainwindow.h      |    9 +++-
 src/pavucontrol.cc    |   63 +++++++++++++++++++++++++++++++++
 src/pavucontrol.glade |   93 ++++++++++++++++++++++++++++++++++++++++++++++++--
 src/pavucontrol.h     |    1 
 src/sinkwidget.cc     |   76 +++++++++++++++++++++++++++++++++++++++-
 src/sinkwidget.h      |   19 +++++++++-
 7 files changed, 293 insertions(+), 10 deletions(-)

New commits:
commit 479e7bcd6eb283750ee13d2270610d6d814add08
Author: Colin Guthrie <colin at mageia.org>
Date:   Tue Aug 9 02:02:39 2011 +0200

    Add UI to select the formats supported by the receiver attached to a digitial sink

diff --git a/src/mainwindow.cc b/src/mainwindow.cc
index 7e49e36..906a5d9 100644
--- a/src/mainwindow.cc
+++ b/src/mainwindow.cc
@@ -298,10 +298,10 @@ void MainWindow::updateCard(const pa_card_info &info) {
         updateDeviceVisibility();
 }
 
-void MainWindow::updateSink(const pa_sink_info &info) {
+bool MainWindow::updateSink(const pa_sink_info &info) {
     SinkWidget *w;
     bool is_new = false;
-    const char *icon;
+    const char *icon, *profile;
     std::set<pa_sink_port_info,sink_port_prio_compare> port_priorities;
 
     if (sinkWidgets.count(info.index))
@@ -348,12 +348,18 @@ void MainWindow::updateSink(const pa_sink_info &info) {
 
     w->activePort = info.active_port ? info.active_port->name : "";
 
+    /* Can we do digital? This is a hack just now... we should expose some nice properties to indicate we can do digitial*/
+    profile = pa_proplist_gets(info.proplist, "device.profile.name");
+    w->setDigital(profile && 0 == strncmp("iec958", profile, 6));
+
     w->updating = false;
 
     w->prepareMenu();
 
     if (is_new)
         updateDeviceVisibility();
+
+    return is_new;
 }
 
 static void suspended_callback(pa_stream *s, void *userdata) {
@@ -760,6 +766,38 @@ void MainWindow::updateRole(const pa_ext_stream_restore_info &info) {
         updateDeviceVisibility();
 }
 
+#if HAVE_EXT_DEVICE_RESTORE_API
+void MainWindow::updateDeviceInfo(const pa_ext_device_restore_info &info) {
+
+    if (sinkWidgets.count(info.index)) {
+        SinkWidget *w;
+        pa_format_info *format;
+
+        w = sinkWidgets[info.index];
+
+        w->updating = true;
+
+        /* Unselect everything */
+        for (int j = 1; j < PAVU_NUM_ENCODINGS; ++j)
+            w->encodings[j].widget->set_active(false);
+
+
+        for (uint8_t i = 0; i < info.n_formats; ++i) {
+            format = info.formats[i];
+            for (int j = 1; j < PAVU_NUM_ENCODINGS; ++j) {
+                if (format->encoding == w->encodings[j].encoding) {
+                    w->encodings[j].widget->set_active(true);
+                    break;
+                }
+            }
+        }
+
+        w->updating = false;
+    }
+}
+#endif
+
+
 void MainWindow::updateVolumeMeter(uint32_t source_index, uint32_t sink_input_idx, double v) {
 
     if (sink_input_idx != PA_INVALID_INDEX) {
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 559b639..dd8df6c 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -23,7 +23,9 @@
 
 #include "pavucontrol.h"
 #include <pulse/ext-stream-restore.h>
-
+#if HAVE_EXT_DEVICE_RESTORE_API
+#  include <pulse/ext-device-restore.h>
+#endif
 
 class CardWidget;
 class SinkWidget;
@@ -39,7 +41,7 @@ public:
     virtual ~MainWindow();
 
     void updateCard(const pa_card_info &info);
-    void updateSink(const pa_sink_info &info);
+    bool updateSink(const pa_sink_info &info);
     void updateSource(const pa_source_info &info);
     void updateSinkInput(const pa_sink_input_info &info);
     void updateSourceOutput(const pa_source_output_info &info);
@@ -47,6 +49,9 @@ public:
     void updateServer(const pa_server_info &info);
     void updateVolumeMeter(uint32_t source_index, uint32_t sink_input_index, double v);
     void updateRole(const pa_ext_stream_restore_info &info);
+#if HAVE_EXT_DEVICE_RESTORE_API
+    void updateDeviceInfo(const pa_ext_device_restore_info &info);
+#endif
 
     void removeCard(uint32_t index);
     void removeSink(uint32_t index);
diff --git a/src/pavucontrol.cc b/src/pavucontrol.cc
index 4270fa7..4f2f0e5 100644
--- a/src/pavucontrol.cc
+++ b/src/pavucontrol.cc
@@ -88,7 +88,11 @@ void card_cb(pa_context *, const pa_card_info *i, int eol, void *userdata) {
     w->updateCard(*i);
 }
 
-void sink_cb(pa_context *, const pa_sink_info *i, int eol, void *userdata) {
+#if HAVE_EXT_DEVICE_RESTORE_API
+static void ext_device_restore_subscribe_cb(pa_context *c, uint32_t idx, void *userdata);
+#endif
+
+void sink_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata) {
     MainWindow *w = static_cast<MainWindow*>(userdata);
 
     if (eol < 0) {
@@ -104,7 +108,12 @@ void sink_cb(pa_context *, const pa_sink_info *i, int eol, void *userdata) {
         return;
     }
 
+#if HAVE_EXT_DEVICE_RESTORE_API
+    if (w->updateSink(*i))
+        ext_device_restore_subscribe_cb(c, i->index, w);
+#else
     w->updateSink(*i);
+#endif
 }
 
 void source_cb(pa_context *, const pa_source_info *i, int eol, void *userdata) {
@@ -251,6 +260,43 @@ static void ext_stream_restore_subscribe_cb(pa_context *c, void *userdata) {
     pa_operation_unref(o);
 }
 
+#if HAVE_EXT_DEVICE_RESTORE_API
+void ext_device_restore_read_cb(
+        pa_context *,
+        const pa_ext_device_restore_info *i,
+        int eol,
+        void *userdata) {
+
+    MainWindow *w = static_cast<MainWindow*>(userdata);
+
+    if (eol < 0) {
+        dec_outstanding(w);
+        g_debug(_("Failed to initialize device restore extension: %s"), pa_strerror(pa_context_errno(context)));
+        return;
+    }
+
+    if (eol > 0) {
+        dec_outstanding(w);
+        return;
+    }
+
+    /* Do something with a widget when this part is written */
+    w->updateDeviceInfo(*i);
+}
+
+static void ext_device_restore_subscribe_cb(pa_context *c, uint32_t idx, void *userdata) {
+    MainWindow *w = static_cast<MainWindow*>(userdata);
+    pa_operation *o;
+
+    if (!(o = pa_ext_device_restore_read_sink_formats(c, idx, ext_device_restore_read_cb, w))) {
+        show_error(_("pa_ext_device_restore_read_sink_formats() failed"));
+        return;
+    }
+
+    pa_operation_unref(o);
+}
+#endif
+
 void ext_device_manager_read_cb(
         pa_context *,
         const pa_ext_device_manager_info *,
@@ -485,6 +531,21 @@ void context_state_callback(pa_context *c, void *userdata) {
             } else
                 g_debug(_("Failed to initialize stream_restore extension: %s"), pa_strerror(pa_context_errno(context)));
 
+#if HAVE_EXT_DEVICE_RESTORE_API
+            /* TODO Change this to just the test function */
+            if ((o = pa_ext_device_restore_read_sink_formats_all(c, ext_device_restore_read_cb, w))) {
+                pa_operation_unref(o);
+                n_outstanding++;
+
+                pa_ext_device_restore_set_subscribe_cb(c, ext_device_restore_subscribe_cb, w);
+
+                if ((o = pa_ext_device_restore_subscribe(c, 1, NULL, NULL)))
+                    pa_operation_unref(o);
+
+            } else
+                g_debug(_("Failed to initialize device restore extension: %s"), pa_strerror(pa_context_errno(context)));
+#endif
+
             if ((o = pa_ext_device_manager_read(c, ext_device_manager_read_cb, w))) {
                 pa_operation_unref(o);
                 n_outstanding++;
diff --git a/src/pavucontrol.glade b/src/pavucontrol.glade
index c8b5a02..1d14f81 100644
--- a/src/pavucontrol.glade
+++ b/src/pavucontrol.glade
@@ -393,6 +393,91 @@
                   </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>
+                      <object class="GtkCheckButton" id="encodingFormatPCM">
+                        <property name="label" translatable="yes">PCM</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>
+                    </child>
+                    <child>
+                      <object class="GtkCheckButton" id="encodingFormatAC3">
+                        <property name="label" translatable="yes">AC3</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>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkCheckButton" id="encodingFormatDTS">
+                        <property name="label" translatable="yes">DTS</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>
+                        <property name="top_attach">1</property>
+                        <property name="bottom_attach">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkCheckButton" id="encodingFormatEAC3">
+                        <property name="label" translatable="yes">EAC3</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>
+                        <property name="left_attach">2</property>
+                        <property name="right_attach">3</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkCheckButton" id="encodingFormatMPEG">
+                        <property name="label" translatable="yes">MPEG</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>
+                        <property name="left_attach">1</property>
+                        <property name="right_attach">2</property>
+                        <property name="top_attach">1</property>
+                        <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>
+                  </packing>
+                </child>
+                <child>
                   <object class="GtkVBox" id="channelsVBox">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
@@ -407,7 +492,7 @@
                   <packing>
                     <property name="expand">False</property>
                     <property name="fill">False</property>
-                    <property name="position">2</property>
+                    <property name="position">3</property>
                   </packing>
                 </child>
               </object>
@@ -1069,7 +1154,7 @@
         <child>
           <object class="GtkLabel" id="connectingLabel">
             <property name="can_focus">False</property>
-            <property name="label" translatable="no">...</property>
+            <property name="label">...</property>
             <property name="use_markup">True</property>
           </object>
           <packing>
@@ -1130,6 +1215,10 @@
             <property name="invisible_char">●</property>
             <property name="activates_default">True</property>
             <property name="width_chars">60</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>
diff --git a/src/pavucontrol.h b/src/pavucontrol.h
index e16c20e..65cb913 100644
--- a/src/pavucontrol.h
+++ b/src/pavucontrol.h
@@ -40,6 +40,7 @@
 #endif
 
 #define HAVE_SOURCE_OUTPUT_VOLUMES PA_CHECK_VERSION(0,99,0)
+#define HAVE_EXT_DEVICE_RESTORE_API PA_CHECK_VERSION(0,99,0)
 
 enum SinkInputType {
     SINK_INPUT_ALL,
diff --git a/src/sinkwidget.cc b/src/sinkwidget.cc
index c797e68..6b5e86f 100644
--- a/src/sinkwidget.cc
+++ b/src/sinkwidget.cc
@@ -22,14 +22,47 @@
 #include <config.h>
 #endif
 
-#include <canberra-gtk.h>
-
 #include "sinkwidget.h"
 
+#include <canberra-gtk.h>
+#if HAVE_EXT_DEVICE_RESTORE_API
+#  include <pulse/format.h>
+#  include <pulse/ext-device-restore.h>
+#endif
+
 #include "i18n.h"
 
 SinkWidget::SinkWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& x) :
     DeviceWidget(cobject, x) {
+#if HAVE_EXT_DEVICE_RESTORE_API
+    uint8_t i = 0;
+
+    x->get_widget("encodingSelect", encodingSelect);
+
+    encodings[i].encoding = PA_ENCODING_PCM;
+    x->get_widget("encodingFormatPCM", encodings[i].widget);
+    encodings[i].widget->signal_toggled().connect(sigc::mem_fun(*this, &SinkWidget::onEncodingsChange));
+
+    ++i;
+    encodings[i].encoding = PA_ENCODING_AC3_IEC61937;
+    x->get_widget("encodingFormatAC3", encodings[i].widget);
+    encodings[i].widget->signal_toggled().connect(sigc::mem_fun(*this, &SinkWidget::onEncodingsChange));
+
+    ++i;
+    encodings[i].encoding = PA_ENCODING_EAC3_IEC61937;
+    x->get_widget("encodingFormatEAC3", encodings[i].widget);
+    encodings[i].widget->signal_toggled().connect(sigc::mem_fun(*this, &SinkWidget::onEncodingsChange));
+
+    ++i;
+    encodings[i].encoding = PA_ENCODING_MPEG_IEC61937;
+    x->get_widget("encodingFormatMPEG", encodings[i].widget);
+    encodings[i].widget->signal_toggled().connect(sigc::mem_fun(*this, &SinkWidget::onEncodingsChange));
+
+    ++i;
+    encodings[i].encoding = PA_ENCODING_DTS_IEC61937;
+    x->get_widget("encodingFormatDTS", encodings[i].widget);
+    encodings[i].widget->signal_toggled().connect(sigc::mem_fun(*this, &SinkWidget::onEncodingsChange));
+#endif
 }
 
 SinkWidget* SinkWidget::create(MainWindow* mainWindow) {
@@ -120,3 +153,42 @@ void SinkWidget::onPortChange() {
         }
     }
 }
+
+void SinkWidget::setDigital(bool digital) {
+#if HAVE_EXT_DEVICE_RESTORE_API
+    if (digital)
+        encodingSelect->show();
+    else
+        encodingSelect->hide();
+#endif
+}
+
+void SinkWidget::onEncodingsChange() {
+#if HAVE_EXT_DEVICE_RESTORE_API
+    pa_operation* o;
+    uint8_t n_formats = 0;
+    pa_format_info **formats;
+
+    if (updating)
+        return;
+
+    formats = (pa_format_info**)malloc(sizeof(pa_format_info*) * PAVU_NUM_ENCODINGS);
+
+    for (int i = 0; i < PAVU_NUM_ENCODINGS; ++i) {
+        if (encodings[i].widget->get_active()) {
+            formats[n_formats] = pa_format_info_new();
+            formats[n_formats]->encoding = encodings[i].encoding;
+            ++n_formats;
+        }
+    }
+
+    if (!(o = pa_ext_device_restore_save_sink_formats(get_context(), index, n_formats, formats, NULL, NULL))) {
+        show_error(_("pa_ext_device_restore_save_sink_formats() failed"));
+        free(formats);
+        return;
+    }
+
+    free(formats);
+    pa_operation_unref(o);
+#endif
+}
\ No newline at end of file
diff --git a/src/sinkwidget.h b/src/sinkwidget.h
index 3fbd7aa..4b79879 100644
--- a/src/sinkwidget.h
+++ b/src/sinkwidget.h
@@ -22,9 +22,19 @@
 #define sinkwidget_h
 
 #include "pavucontrol.h"
-
 #include "devicewidget.h"
 
+#if HAVE_EXT_DEVICE_RESTORE_API
+#  include <pulse/format.h>
+
+#  define PAVU_NUM_ENCODINGS 5
+
+typedef struct {
+    pa_encoding encoding;
+    Gtk::CheckButton *widget;
+} encodingList;
+#endif
+
 class SinkWidget : public DeviceWidget {
 public:
     SinkWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& x);
@@ -34,12 +44,19 @@ public:
     uint32_t index, monitor_index, card_index;
     bool can_decibel;
 
+#if HAVE_EXT_DEVICE_RESTORE_API
+    encodingList encodings[PAVU_NUM_ENCODINGS];
+    Gtk::Table *encodingSelect;
+#endif
+
     virtual void onMuteToggleButton();
     virtual void executeVolumeUpdate();
     virtual void onDefaultToggleButton();
+    void setDigital(bool);
 
 protected:
     virtual void onPortChange();
+    virtual void onEncodingsChange();
 };
 
 #endif



More information about the pulseaudio-commits mailing list