6 commits - meson.build src/cardwidget.cc src/cardwidget.h src/channelwidget.cc src/channelwidget.h src/devicewidget.cc src/devicewidget.h src/mainwindow.cc src/mainwindow.h src/meson.build src/minimalstreamwidget.cc src/minimalstreamwidget.h src/org.pulseaudio.pavucontrol.desktop.in src/pavuapplication.cc src/pavuapplication.h src/pavucontrol.cc src/pavucontrol.desktop.in src/pavucontrol.glade src/pavucontrol.h src/rolewidget.cc src/rolewidget.h src/sinkinputwidget.cc src/sinkinputwidget.h src/sinkwidget.cc src/sourceoutputwidget.cc src/sourceoutputwidget.h src/sourcewidget.cc src/streamwidget.cc src/streamwidget.h

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Apr 16 15:45:45 UTC 2024


 meson.build                |    6 
 src/cardwidget.cc          |   18 
 src/cardwidget.h           |    3 
 src/channelwidget.cc       |   20 
 src/channelwidget.h        |    3 
 src/devicewidget.cc        |  139 +--
 src/devicewidget.h         |   19 
 src/mainwindow.cc          |  145 +--
 src/mainwindow.h           |    8 
 src/meson.build            |    4 
 src/minimalstreamwidget.cc |   19 
 src/minimalstreamwidget.h  |    9 
 src/pavuapplication.cc     |   26 
 src/pavuapplication.h      |    3 
 src/pavucontrol.cc         |   83 -
 src/pavucontrol.glade      | 1980 ++++++++++++++-------------------------------
 src/pavucontrol.h          |    6 
 src/rolewidget.cc          |    8 
 src/rolewidget.h           |    1 
 src/sinkinputwidget.cc     |   12 
 src/sinkinputwidget.h      |    2 
 src/sinkwidget.cc          |   55 -
 src/sourceoutputwidget.cc  |   12 
 src/sourceoutputwidget.h   |    2 
 src/sourcewidget.cc        |   10 
 src/streamwidget.cc        |   59 -
 src/streamwidget.h         |    8 
 27 files changed, 1014 insertions(+), 1646 deletions(-)

New commits:
commit 44f984883fc6d29f26cae333661d5a0f47322956
Author: Arun Raghavan <arun at asymptotic.io>
Date:   Mon Apr 15 17:38:36 2024 -0400

    Some minor whitespace fixups
    
    We should really just get a clang-format config that's close enough and
    set that up instead.

diff --git a/src/devicewidget.cc b/src/devicewidget.cc
index b9b3b3c..e149ceb 100644
--- a/src/devicewidget.cc
+++ b/src/devicewidget.cc
@@ -271,7 +271,7 @@ void DeviceWidget::openRenamePopup(const Glib::VariantBase& parameter) {
 
 RenameWindow::RenameWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& x, const gchar* name, const gchar* key) :
     Gtk::ApplicationWindow(cobject),
-    deviceKey(key){
+    deviceKey(key) {
 
     renameText = x->get_widget<Gtk::Entry>("renameText");
     renameText->set_text(name);
diff --git a/src/mainwindow.cc b/src/mainwindow.cc
index 7dba1a5..9579dad 100644
--- a/src/mainwindow.cc
+++ b/src/mainwindow.cc
@@ -76,7 +76,7 @@ MainWindow::MainWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
     canRenameDevices(false),
     m_connected(false),
     m_config_filename(NULL) {
-    ca_context_create (&canberraContext);
+    ca_context_create(&canberraContext);
     ca_context_set_driver(canberraContext, "pulse");
 
     cardsVBox = x->get_widget<Gtk::Box>("cardsVBox");
@@ -286,7 +286,7 @@ static void set_icon_name_default(Gtk::Image *i, const char *name) {
             iconName = "gtk-missing-image";
             break;
         }
-        iconName = iconName.substr(0,lastDashIndex);
+        iconName = iconName.substr(0, lastDashIndex);
     }
     i->set_from_icon_name(iconName.c_str());
 }
diff --git a/src/pavucontrol.cc b/src/pavucontrol.cc
index 3ecbf2d..86d7ddd 100644
--- a/src/pavucontrol.cc
+++ b/src/pavucontrol.cc
@@ -67,8 +67,7 @@ void show_error(Gtk::Widget* widget, const char *txt) {
         Gtk::Window* window = Glib::wrap(w);
         window->present();
         dialog->choose(*window, sigc::ptr_fun(show_error_finish));
-    }
-    else {
+    } else {
         dialog->choose(sigc::ptr_fun(show_error_finish));
     }
 }

commit a1ac8eb8d38de5a34f728156936b9c0a613a48b8
Author: Arun Raghavan <arun at asymptotic.io>
Date:   Mon Apr 15 17:06:45 2024 -0400

    pavuapplication: Drop references to unused on_hide_window

diff --git a/src/pavuapplication.cc b/src/pavuapplication.cc
index f4ad11a..915ab2d 100644
--- a/src/pavuapplication.cc
+++ b/src/pavuapplication.cc
@@ -47,7 +47,7 @@ PavuApplication::PavuApplication() :
 }
 
 /*
- * Create the main window and connect its "on_hide_window" signal to our cleanup
+ * Create the main window and connect its "on_close_window" signal to our cleanup
  * function
  */
 MainWindow* PavuApplication::create_window()
@@ -86,7 +86,7 @@ void PavuApplication::on_activate()
     mainWindow->present();
 }
 
-/* "on_hide_window" signal handler
+/* "on_close_window" signal handler
  * This is executed in the first-running process and performs cleanup before
  * exiting : when the last registered window of Gtk::Application is closed,
  * the application's run() function returns.
diff --git a/src/pavuapplication.h b/src/pavuapplication.h
index 70cf90b..902efdd 100644
--- a/src/pavuapplication.h
+++ b/src/pavuapplication.h
@@ -44,7 +44,6 @@ protected:
 
 private:
     MainWindow* create_window();
-    void on_hide_window();
     bool on_close_window();
 
     pa_glib_mainloop *m;

commit 19d19b9e4b88bae3f74f13520747bdd09e88080c
Author: Arun Raghavan <arun at asymptotic.io>
Date:   Mon Apr 15 17:06:18 2024 -0400

    mainwindow: Clean up canberra context on shutdown

diff --git a/src/mainwindow.cc b/src/mainwindow.cc
index 6c0964e..7dba1a5 100644
--- a/src/mainwindow.cc
+++ b/src/mainwindow.cc
@@ -271,6 +271,8 @@ finish:
         g_free(i->second);
         clientNames.erase(i);
     }
+
+    ca_context_destroy(canberraContext);
 }
 
 static void set_icon_name_default(Gtk::Image *i, const char *name) {

commit 1fa1b86ca78670d7a8639e117106e04e226dfde1
Author: Arun Raghavan <arun at asymptotic.io>
Date:   Mon Apr 15 17:05:57 2024 -0400

    devicewidget: Minor function rename for legibility

diff --git a/src/devicewidget.cc b/src/devicewidget.cc
index d03450f..b9b3b3c 100644
--- a/src/devicewidget.cc
+++ b/src/devicewidget.cc
@@ -281,14 +281,12 @@ RenameWindow::RenameWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Buil
 
     auto renameAction = Gio::SimpleAction::create("rename");
     renameAction->set_enabled(true);
-    renameAction->signal_activate().connect(sigc::mem_fun(*this, &RenameWindow::renamePopup));
+    renameAction->signal_activate().connect(sigc::mem_fun(*this, &RenameWindow::doRename));
 
     add_action(renameAction);
 }
 
-
-
-void RenameWindow::renamePopup(const Glib::VariantBase& parameter){
+void RenameWindow::doRename(const Glib::VariantBase& parameter) {
     pa_operation* o;
     auto name = renameText->get_text();
 
diff --git a/src/devicewidget.h b/src/devicewidget.h
index bd6f317..4fceda2 100644
--- a/src/devicewidget.h
+++ b/src/devicewidget.h
@@ -119,7 +119,7 @@ public:
     Gtk::Entry* renameText;
     const gchar* deviceKey;
 private:
-    void renamePopup(const Glib::VariantBase& parameter);
+    void doRename(const Glib::VariantBase& parameter);
 };
 
 #endif

commit a8927981778569e17e92f63544798e9ed02f173f
Author: Arun Raghavan <arun at asymptotic.io>
Date:   Fri Apr 12 13:33:10 2024 -0400

    Fix some minor lints and warnings

diff --git a/src/devicewidget.h b/src/devicewidget.h
index d229fe2..bd6f317 100644
--- a/src/devicewidget.h
+++ b/src/devicewidget.h
@@ -21,8 +21,6 @@
 #ifndef devicewidget_h
 #define devicewidget_h
 
-#include "pavucontrol.h"
-
 #include "minimalstreamwidget.h"
 
 class MainWindow;
diff --git a/src/minimalstreamwidget.h b/src/minimalstreamwidget.h
index 78671a5..0f7275f 100644
--- a/src/minimalstreamwidget.h
+++ b/src/minimalstreamwidget.h
@@ -21,7 +21,8 @@
 #ifndef minimalstreamwidget_h
 #define minimalstreamwidget_h
 
-#include "pavucontrol.h"
+#include <gtkmm.h>
+#include <pulse/pulseaudio.h>
 
 #define PEAKS_RATE 144
 
@@ -55,7 +56,7 @@ public:
 protected:
     /* Subclasses must call this after the constructor to finalize the initial
      * layout. */
-    virtual void init();
+    void init();
 
 private :
     bool volumeMeterVisible;
diff --git a/src/pavuapplication.h b/src/pavuapplication.h
index 53cc0e3..70cf90b 100644
--- a/src/pavuapplication.h
+++ b/src/pavuapplication.h
@@ -21,7 +21,6 @@
 #ifndef pavuapplication_h
 #define pavuapplication_h
 
-#include "pavucontrol.h"
 #include "mainwindow.h"
 
 class PavuApplication : public Gtk::Application {
diff --git a/src/pavucontrol.cc b/src/pavucontrol.cc
index 62a6499..3ecbf2d 100644
--- a/src/pavucontrol.cc
+++ b/src/pavucontrol.cc
@@ -31,15 +31,9 @@
 
 #include "pavucontrol.h"
 #include "i18n.h"
-#include "minimalstreamwidget.h"
-#include "channelwidget.h"
 #include "streamwidget.h"
-#include "cardwidget.h"
-#include "sinkwidget.h"
-#include "sourcewidget.h"
 #include "sinkinputwidget.h"
 #include "sourceoutputwidget.h"
-#include "rolewidget.h"
 #include "mainwindow.h"
 #include "pavuapplication.h"
 
diff --git a/src/pavucontrol.h b/src/pavucontrol.h
index e6282d7..d7e81a8 100644
--- a/src/pavucontrol.h
+++ b/src/pavucontrol.h
@@ -23,9 +23,6 @@
 
 #include <string>
 
-#include <signal.h>
-#include <string.h>
-
 #include <libintl.h>
 
 #include <gtkmm.h>

commit 52aef7e81d9c44601e78bac4930084b513a2936e
Author: JA <jagw40k at free.fr>
Date:   Thu Nov 30 16:44:52 2023 +0100

    Use Gtk4 instead of Gtk3

diff --git a/meson.build b/meson.build
index 0d72ca1..d6e410d 100644
--- a/meson.build
+++ b/meson.build
@@ -1,16 +1,16 @@
 project('pavucontrol', 'cpp',
         version : '5.0',
         meson_version : '>= 0.50.0',
-        default_options : [ 'c_std=gnu11', 'cpp_std=c++11' ]
+        default_options : [ 'c_std=gnu11', 'cpp_std=c++17' ]
         )
 
 with_lynx = get_option('lynx')
 
 cpp = meson.get_compiler('cpp')
 
-gtkmm_dep = dependency('gtkmm-3.0', version : '>= 3.0', required : true)
+gtkmm_dep = dependency('gtkmm-4.0', version : '>= 4.0', required : true)
 sigcpp_dep = dependency('sigc++-2.0', required : true)
-canberragtk_dep = dependency('libcanberra-gtk3', version : '>= 0.16', required : true)
+canberragtk_dep = dependency('libcanberra', version : '>= 0.16', required : true)
 
 libpulse_dep = dependency('libpulse', version : '>= 5.0', required : true)
 libpulsemlglib_dep = dependency('libpulse-mainloop-glib', version : '>= 0.9.16', required : true)
diff --git a/src/cardwidget.cc b/src/cardwidget.cc
index d751fd2..bdacdaa 100644
--- a/src/cardwidget.cc
+++ b/src/cardwidget.cc
@@ -28,14 +28,14 @@
 
 /*** CardWidget ***/
 CardWidget::CardWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& x) :
-    Gtk::VBox(cobject) {
+    Gtk::Box(cobject) {
 
-    x->get_widget("cardNameLabel", nameLabel);
-    x->get_widget("profileList", profileList);
-    x->get_widget("cardIconImage", iconImage);
-    x->get_widget("codecBox", codecBox);
-    x->get_widget("codecList", codecList);
-    x->get_widget("profileLockToggleButton", profileLockToggleButton);
+    nameLabel = x->get_widget<Gtk::Label>("cardNameLabel");
+    profileList = x->get_widget<Gtk::ComboBox>("profileList");
+    iconImage = x->get_widget<Gtk::Image>("cardIconImage");
+    codecBox = x->get_widget<Gtk::Box>("codecBox");
+    codecList = x->get_widget<Gtk::ComboBox>("codecList");
+    profileLockToggleButton = x->get_widget<Gtk::ToggleButton>("profileLockToggleButton");
 
     profileListStore = Gtk::ListStore::create(profileModel);
     profileList->set_model(profileListStore);
@@ -61,7 +61,7 @@ CardWidget::CardWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
 CardWidget* CardWidget::create() {
     CardWidget* w;
     Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create_from_file(GLADE_FILE, "cardWidget");
-    x->get_widget_derived("cardWidget", w);
+    w = Gtk::Builder::get_widget_derived<CardWidget>(x, "cardWidget");
     w->reference();
     return w;
 }
@@ -123,7 +123,7 @@ void CardWidget::onProfileChange() {
           Glib::ustring profile = row[profileModel.name];
 
           if (!(o = pa_context_set_card_profile_by_index(get_context(), index, profile.c_str(), NULL, NULL))) {
-              show_error(_("pa_context_set_card_profile_by_index() failed"));
+              show_error(this, _("pa_context_set_card_profile_by_index() failed"));
               return;
           }
 
diff --git a/src/cardwidget.h b/src/cardwidget.h
index 3c86659..fcaacdd 100644
--- a/src/cardwidget.h
+++ b/src/cardwidget.h
@@ -34,13 +34,12 @@ public:
       std::vector<Glib::ustring> profiles;
 };
 
-class CardWidget : public Gtk::VBox {
+class CardWidget : public Gtk::Box {
 public:
     CardWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& x);
     static CardWidget* create();
 
     Gtk::Label *nameLabel;
-    Gtk::Menu menu;
     Gtk::Image *iconImage;
     Glib::ustring name;
     std::string pulse_card_name;
diff --git a/src/channelwidget.cc b/src/channelwidget.cc
index f141009..87c494b 100644
--- a/src/channelwidget.cc
+++ b/src/channelwidget.cc
@@ -30,14 +30,14 @@
 /*** ChannelWidget ***/
 
 ChannelWidget::ChannelWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& x) :
-    Gtk::EventBox(cobject),
+    Gtk::Widget(cobject),
     can_decibel(false),
     volumeScaleEnabled(true),
     last(false) {
 
-    x->get_widget("channelLabel", channelLabel);
-    x->get_widget("volumeLabel", volumeLabel);
-    x->get_widget("volumeScale", volumeScale);
+    channelLabel = x->get_widget<Gtk::Label>("channelLabel");
+    volumeLabel = x->get_widget<Gtk::Label>("volumeLabel");
+    volumeScale = x->get_widget<Gtk::Scale>("volumeScale");
 
     volumeScale->set_range((double)PA_VOLUME_MUTED, (double)PA_VOLUME_UI_MAX);
     volumeScale->set_value((double)PA_VOLUME_NORM);
@@ -52,7 +52,7 @@ ChannelWidget* ChannelWidget::createOne(MinimalStreamWidget *owner, int channelI
     Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create();
     x->add_from_file(GLADE_FILE, "adjustment1");
     x->add_from_file(GLADE_FILE, "channelWidget");
-    x->get_widget_derived("channelWidget", w);
+    w = Gtk::Builder::get_widget_derived<ChannelWidget>(x, "channelWidget");
     w->reference();
 
     w->channel = channelIndex;
@@ -75,8 +75,8 @@ void ChannelWidget::create(MinimalStreamWidget *owner, const pa_channel_map &m,
         Gtk::Requisition minimumSize;
         Gtk::Requisition naturalSize;
         widgets[i]->channelLabel->get_preferred_size(minimumSize, naturalSize);
-        if (naturalSize.width > maxLabelWidth)
-            maxLabelWidth = naturalSize.width;
+        if (naturalSize.get_width() > maxLabelWidth)
+            maxLabelWidth = naturalSize.get_width();
     }
 
     widgets[m.channels - 1]->last = true;
@@ -108,6 +108,7 @@ void ChannelWidget::setVolume(pa_volume_t volume) {
 
     volumeScaleEnabled = false;
     volumeScale->set_value(volume > PA_VOLUME_UI_MAX ? PA_VOLUME_UI_MAX : volume);
+    currentVolume = volumeScale->get_value();
     volumeScaleEnabled = true;
 }
 
@@ -120,11 +121,12 @@ void ChannelWidget::onVolumeScaleValueChanged() {
         return;
 
     pa_volume_t volume = (pa_volume_t) volumeScale->get_value();
-    minimalStreamWidget->updateChannelVolume(channel, volume);
+    if (volume != currentVolume)
+        minimalStreamWidget->updateChannelVolume(channel, volume);
 }
 
 void ChannelWidget::set_sensitive(bool enabled) {
-    Gtk::EventBox::set_sensitive(enabled);
+    Gtk::Widget::set_sensitive(enabled);
 
     channelLabel->set_sensitive(enabled);
     volumeLabel->set_sensitive(enabled);
diff --git a/src/channelwidget.h b/src/channelwidget.h
index 6216b74..d09c6ec 100644
--- a/src/channelwidget.h
+++ b/src/channelwidget.h
@@ -25,7 +25,7 @@
 
 class MinimalStreamWidget;
 
-class ChannelWidget : public Gtk::EventBox {
+class ChannelWidget : public Gtk::Widget {
 public:
     ChannelWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& x);
 
@@ -53,6 +53,7 @@ public:
     virtual void setBaseVolume(pa_volume_t);
 
 private:
+    pa_volume_t currentVolume;
     static ChannelWidget *createOne(MinimalStreamWidget *owner, int channelIndex, pa_channel_position channelPosition,
                                     bool can_decibel);
 };
diff --git a/src/devicewidget.cc b/src/devicewidget.cc
index e86cd20..d03450f 100644
--- a/src/devicewidget.cc
+++ b/src/devicewidget.cc
@@ -37,29 +37,45 @@ DeviceWidget::DeviceWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Buil
     mDigital(false) {
 
     /* MinimalStreamWidget member variables. */
-    x->get_widget("deviceChannelsVBox", channelsVBox);
-    x->get_widget("deviceNameLabel", nameLabel);
-    x->get_widget("deviceBoldNameLabel", boldNameLabel);
-    x->get_widget("deviceIconImage", iconImage);
-
-    x->get_widget("deviceLockToggleButton", lockToggleButton);
-    x->get_widget("deviceMuteToggleButton", muteToggleButton);
-    x->get_widget("defaultToggleButton", defaultToggleButton);
-    x->get_widget("portSelect", portSelect);
-    x->get_widget("portList", portList);
-    x->get_widget("advancedOptions", advancedOptions);
-    x->get_widget("offsetSelect", offsetSelect);
-    x->get_widget("offsetButton", offsetButton);
-
-    this->signal_button_press_event().connect(sigc::mem_fun(*this, &DeviceWidget::onContextTriggerEvent));
+    channelsVBox = x->get_widget<Gtk::Box>("deviceChannelsVBox");
+    nameLabel = x->get_widget<Gtk::Label>("deviceNameLabel");
+    boldNameLabel = x->get_widget<Gtk::Label>("deviceBoldNameLabel");
+    iconImage= x->get_widget<Gtk::Image>("deviceIconImage");
+
+    lockToggleButton = x->get_widget<Gtk::ToggleButton>("deviceLockToggleButton");
+    muteToggleButton = x->get_widget<Gtk::ToggleButton>("deviceMuteToggleButton");
+    defaultToggleButton= x->get_widget<Gtk::ToggleButton>("defaultToggleButton");
+    portSelect = x->get_widget<Gtk::Box>("portSelect");
+    portList = x->get_widget<Gtk::ComboBox>("portList");
+    advancedOptions = x->get_widget<Gtk::Expander>("advancedOptions");
+    offsetSelect = x->get_widget<Gtk::Box>("offsetSelect");
+    offsetButton = x->get_widget<Gtk::SpinButton>("offsetButton");
+
     muteToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &DeviceWidget::onMuteToggleButton));
     lockToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &DeviceWidget::onLockToggleButton));
     defaultToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &DeviceWidget::onDefaultToggleButton));
 
-    rename.set_label(_("Rename Device..."));
-    rename.signal_activate().connect(sigc::mem_fun(*this, &DeviceWidget::renamePopup));
-    contextMenu.append(rename);
-    contextMenu.show_all();
+    auto gesture = Gtk::GestureClick::create();
+    gesture->set_button(3);
+    gesture->set_exclusive(true);
+    gesture->signal_pressed().connect(sigc::mem_fun(*this, &DeviceWidget::onContextTriggerEvent));
+    this->add_controller(gesture);
+
+    const std::string actionName = "rename", groupName="devicewidget";
+    auto action = Gio::SimpleAction::create(actionName);
+    action->set_enabled(true);
+    action->signal_activate().connect(sigc::mem_fun(*this, &DeviceWidget::openRenamePopup));
+
+    auto group = Gio::SimpleActionGroup::create();
+    group->add_action(action);
+
+    insert_action_group(groupName, group);
+
+    auto menuModel = Gio::Menu::create();
+    menuModel->append(_("Rename Device..."), groupName + "." + actionName);
+    contextMenu.set_menu_model(menuModel);
+    contextMenu.set_parent(*this);
+
 
     treeModel = Gtk::ListStore::create(portModel);
     portList->set_model(treeModel);
@@ -88,7 +104,7 @@ void DeviceWidget::setChannelMap(const pa_channel_map &m, bool can_decibel) {
 
     for (int i = 0; i < m.channels; i++) {
         ChannelWidget *cw = channelWidgets[i];
-        channelsVBox->pack_start(*cw, false, false, 0);
+        channelsVBox->prepend(*cw);
         cw->unreference();
     }
 
@@ -160,7 +176,7 @@ void DeviceWidget::onOffsetChange() {
 
     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"));
+        show_error(this, _("pa_context_set_port_latency_offset() failed"));
         return;
     }
     pa_operation_unref(o);
@@ -225,55 +241,64 @@ void DeviceWidget::prepareMenu() {
     updateAdvancedOptionsVisibility();
 }
 
-bool DeviceWidget::onContextTriggerEvent(GdkEventButton* event) {
-    if (GDK_BUTTON_PRESS == event->type && 3 == event->button) {
-        contextMenu.popup_at_pointer((GdkEvent*)event);
-        return true;
-    }
 
-    return false;
+void DeviceWidget::onContextTriggerEvent(gint n_press, gdouble x, gdouble y) {
+    if (n_press == 1) {
+        contextMenu.set_pointing_to(Gdk::Rectangle {(int) x, (int) y, 0 , 0});
+        contextMenu.popup();
+    }
 }
 
-void DeviceWidget::renamePopup() {
+void DeviceWidget::openRenamePopup(const Glib::VariantBase& parameter) {
     if (updating)
         return;
 
     if (!mpMainWindow->canRenameDevices) {
-        Gtk::MessageDialog dialog(
-            *mpMainWindow,
-            _("Sorry, but device renaming is not supported."),
-            false,
-            Gtk::MESSAGE_WARNING,
-            Gtk::BUTTONS_OK,
-            true);
-        dialog.set_secondary_text(_("You need to load module-device-manager in the PulseAudio server in order to rename devices"));
-        dialog.run();
+        auto dialog = Gtk::AlertDialog::create(_("Sorry, but device renaming is not supported."));
+        dialog->set_modal(true);
+        dialog->set_detail(_("You need to load module-device-manager in the PulseAudio server in order to rename devices"));
+        dialog->show(*mpMainWindow);
         return;
     }
 
-    Gtk::Dialog* dialog;
-    Gtk::Entry* renameText;
-
     Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create_from_file(GLADE_FILE, "renameDialog");
-    x->get_widget("renameDialog", dialog);
-    x->get_widget("renameText", renameText);
-
-    renameText->set_text(description);
-    dialog->add_button(_("_Cancel"), Gtk::RESPONSE_CANCEL);
-    dialog->add_button(_("_OK"), Gtk::RESPONSE_OK);
-    dialog->set_default_response(Gtk::RESPONSE_OK);
-    if (Gtk::RESPONSE_OK == dialog->run()) {
-        pa_operation* o;
-        gchar *key = g_markup_printf_escaped("%s:%s", mDeviceType.c_str(), name.c_str());
-
-        if (!(o = pa_ext_device_manager_set_device_description(get_context(), key, renameText->get_text().c_str(), NULL, NULL))) {
-            show_error(_("pa_ext_device_manager_write() failed"));
-            return;
-        }
-        pa_operation_unref(o);
-        g_free(key);
+    gchar *key = g_markup_printf_escaped("%s:%s", mDeviceType.c_str(), name.c_str());
+    RenameWindow* renameDialog = Gtk::Builder::get_widget_derived<RenameWindow>(x, "renameDialog", description.c_str(), key);
+    renameDialog->set_transient_for(*mpMainWindow);
+
+    renameDialog->present();
+}
+
+RenameWindow::RenameWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& x, const gchar* name, const gchar* key) :
+    Gtk::ApplicationWindow(cobject),
+    deviceKey(key){
+
+    renameText = x->get_widget<Gtk::Entry>("renameText");
+    renameText->set_text(name);
+
+    Gtk::Button* renameButton = x->get_widget<Gtk::Button>("renameButton");
+    set_default_widget(*renameButton);
+
+    auto renameAction = Gio::SimpleAction::create("rename");
+    renameAction->set_enabled(true);
+    renameAction->signal_activate().connect(sigc::mem_fun(*this, &RenameWindow::renamePopup));
+
+    add_action(renameAction);
+}
+
+
+
+void RenameWindow::renamePopup(const Glib::VariantBase& parameter){
+    pa_operation* o;
+    auto name = renameText->get_text();
+
+    if (!(o = pa_ext_device_manager_set_device_description(get_context(), deviceKey, name.c_str(), NULL, NULL))) {
+        show_error(this, _("pa_ext_device_manager_write() failed"));
+        return;
     }
-    delete dialog;
+    pa_operation_unref(o);
+    g_free((char*)deviceKey);
+    delete this;
 }
 
 void DeviceWidget::updateAdvancedOptionsVisibility() {
diff --git a/src/devicewidget.h b/src/devicewidget.h
index cb13b61..d229fe2 100644
--- a/src/devicewidget.h
+++ b/src/devicewidget.h
@@ -57,7 +57,7 @@ public:
     virtual void onLockToggleButton();
     virtual void onDefaultToggleButton();
     virtual void setDefault(bool isDefault);
-    virtual bool onContextTriggerEvent(GdkEventButton*);
+    virtual void onContextTriggerEvent(gint n_press, gdouble x, gdouble y);
     virtual void setLatencyOffset(int64_t offset);
     void onOffsetChange();
 
@@ -73,7 +73,7 @@ public:
 
     void prepareMenu();
 
-    void renamePopup();
+    void openRenamePopup(const Glib::VariantBase& parameter);
 
 protected:
     MainWindow *mpMainWindow;
@@ -85,8 +85,7 @@ protected:
 
     virtual void onPortChange() = 0;
 
-    Gtk::Menu contextMenu;
-    Gtk::MenuItem rename;
+    Gtk::PopoverMenu contextMenu;
 
     /* Tree model columns */
     class ModelColumns : public Gtk::TreeModel::ColumnRecord
@@ -103,7 +102,7 @@ protected:
     ModelColumns portModel;
 
     Gtk::Expander *advancedOptions;
-    Gtk::HBox *portSelect, *offsetSelect;
+    Gtk::Box *portSelect, *offsetSelect;
     Gtk::ComboBox *portList;
     Glib::RefPtr<Gtk::ListStore> treeModel;
     Glib::RefPtr<Gtk::Adjustment> offsetAdjustment;
@@ -114,7 +113,15 @@ protected:
 
 private:
     Glib::ustring mDeviceType;
+};
 
+class RenameWindow : public Gtk::ApplicationWindow {
+public:
+    RenameWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& x, const gchar* name, const gchar* key);
+    Gtk::Entry* renameText;
+    const gchar* deviceKey;
+private:
+    void renamePopup(const Glib::VariantBase& parameter);
 };
 
 #endif
diff --git a/src/mainwindow.cc b/src/mainwindow.cc
index 4199a37..6c0964e 100644
--- a/src/mainwindow.cc
+++ b/src/mainwindow.cc
@@ -76,30 +76,26 @@ MainWindow::MainWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
     canRenameDevices(false),
     m_connected(false),
     m_config_filename(NULL) {
-
-    x->get_widget("cardsVBox", cardsVBox);
-    x->get_widget("streamsVBox", streamsVBox);
-    x->get_widget("recsVBox", recsVBox);
-    x->get_widget("sinksVBox", sinksVBox);
-    x->get_widget("sourcesVBox", sourcesVBox);
-    x->get_widget("noCardsLabel", noCardsLabel);
-    x->get_widget("noStreamsLabel", noStreamsLabel);
-    x->get_widget("noRecsLabel", noRecsLabel);
-    x->get_widget("noSinksLabel", noSinksLabel);
-    x->get_widget("noSourcesLabel", noSourcesLabel);
-    x->get_widget("connectingLabel", connectingLabel);
-    x->get_widget("sinkInputTypeComboBox", sinkInputTypeComboBox);
-    x->get_widget("sourceOutputTypeComboBox", sourceOutputTypeComboBox);
-    x->get_widget("sinkTypeComboBox", sinkTypeComboBox);
-    x->get_widget("sourceTypeComboBox", sourceTypeComboBox);
-    x->get_widget("notebook", notebook);
-    x->get_widget("showVolumeMetersCheckButton", showVolumeMetersCheckButton);
-
-    sourcesVBox->signal_size_allocate().connect([this](Gdk::Rectangle _unused){ sourcesVBox->queue_draw(); });
-    cardsVBox->signal_size_allocate().connect([this](Gdk::Rectangle _unused){ cardsVBox->queue_draw(); });
-    streamsVBox->signal_size_allocate().connect([this](Gdk::Rectangle _unused){ streamsVBox->queue_draw(); });
-    recsVBox->signal_size_allocate().connect([this](Gdk::Rectangle _unused){ recsVBox->queue_draw(); });
-    sinksVBox->signal_size_allocate().connect([this](Gdk::Rectangle _unused){ sinksVBox->queue_draw(); });
+    ca_context_create (&canberraContext);
+    ca_context_set_driver(canberraContext, "pulse");
+
+    cardsVBox = x->get_widget<Gtk::Box>("cardsVBox");
+    streamsVBox = x->get_widget<Gtk::Box>("streamsVBox");
+    recsVBox = x->get_widget<Gtk::Box>("recsVBox");
+    sinksVBox = x->get_widget<Gtk::Box>("sinksVBox");
+    sourcesVBox = x->get_widget<Gtk::Box>("sourcesVBox");
+    noCardsLabel = x->get_widget<Gtk::Label>("noCardsLabel");
+    noStreamsLabel = x->get_widget<Gtk::Label>("noStreamsLabel");
+    noRecsLabel = x->get_widget<Gtk::Label>("noRecsLabel");
+    noSinksLabel = x->get_widget<Gtk::Label>("noSinksLabel");
+    noSourcesLabel = x->get_widget<Gtk::Label>("noSourcesLabel");
+    connectingLabel = x->get_widget<Gtk::Label>("connectingLabel");
+    sinkInputTypeComboBox = x->get_widget<Gtk::ComboBox>("sinkInputTypeComboBox");
+    sourceOutputTypeComboBox = x->get_widget<Gtk::ComboBox>("sourceOutputTypeComboBox");
+    sinkTypeComboBox = x->get_widget<Gtk::ComboBox>("sinkTypeComboBox");
+    sourceTypeComboBox = x->get_widget<Gtk::ComboBox>("sourceTypeComboBox");
+    notebook = x->get_widget<Gtk::Notebook>("notebook");
+    showVolumeMetersCheckButton = x->get_widget<Gtk::CheckButton>("showVolumeMetersCheckButton");
 
     sinkInputTypeComboBox->set_active((int) showSinkInputType);
     sourceOutputTypeComboBox->set_active((int) showSourceOutputType);
@@ -112,6 +108,9 @@ MainWindow::MainWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
     sourceTypeComboBox->signal_changed().connect(sigc::mem_fun(*this, &MainWindow::onSourceTypeComboBoxChanged));
     showVolumeMetersCheckButton->signal_toggled().connect(sigc::mem_fun(*this, &MainWindow::onShowVolumeMetersCheckButtonToggled));
 
+    auto event_controller_key = Gtk::EventControllerKey::create();
+    event_controller_key->signal_key_pressed().connect(sigc::mem_fun(*this, &MainWindow::on_key_press_event), false);
+    this->add_controller(event_controller_key);
 
     GKeyFile* config = g_key_file_new();
     g_assert(config);
@@ -134,7 +133,7 @@ MainWindow::MainWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
         int default_width, default_height;
         get_default_size(default_width, default_height);
         if (width >= default_width && height >= default_height)
-            resize(width, height);
+            set_default_size(width, height);
 
         int sinkInputTypeSelection = g_key_file_get_integer(config, "window", "sinkInputType", &err);
         if (err == NULL)
@@ -187,7 +186,7 @@ MainWindow* MainWindow::create(bool maximize) {
     x->add_from_file(GLADE_FILE, "liststore3");
     x->add_from_file(GLADE_FILE, "liststore4");
     x->add_from_file(GLADE_FILE, "mainWindow");
-    x->get_widget_derived("mainWindow", w);
+    w = Gtk::Builder::get_widget_derived<MainWindow>(x, "mainWindow");
     w->get_style_context()->add_class("pavucontrol-window");
     if (w && maximize)
         w->maximize();
@@ -197,26 +196,26 @@ MainWindow* MainWindow::create(bool maximize) {
 void MainWindow::on_realize() {
     Gtk::Window::on_realize();
 
-    get_window()->set_cursor(Gdk::Cursor::create(Gdk::WATCH));
+    set_cursor(Gdk::Cursor::create("wait"));
 }
 
-bool MainWindow::on_key_press_event(GdkEventKey* event) {
+bool MainWindow::on_key_press_event(guint keyval, guint keycode, Gdk::ModifierType state) {
 
-    if (event->state & GDK_CONTROL_MASK) {
-        switch (event->keyval) {
+    if ((state & Gdk::ModifierType::CONTROL_MASK) == Gdk::ModifierType::CONTROL_MASK) {
+        switch (keyval) {
             case GDK_KEY_KP_1:
             case GDK_KEY_KP_2:
             case GDK_KEY_KP_3:
             case GDK_KEY_KP_4:
             case GDK_KEY_KP_5:
-                notebook->set_current_page(event->keyval - GDK_KEY_KP_1);
+                notebook->set_current_page(keyval - GDK_KEY_KP_1);
                 return true;
             case GDK_KEY_1:
             case GDK_KEY_2:
             case GDK_KEY_3:
             case GDK_KEY_4:
             case GDK_KEY_5:
-                notebook->set_current_page(event->keyval - GDK_KEY_1);
+                notebook->set_current_page(keyval - GDK_KEY_1);
                 return true;
             case GDK_KEY_W:
             case GDK_KEY_Q:
@@ -226,7 +225,7 @@ bool MainWindow::on_key_press_event(GdkEventKey* event) {
                 return true;
         }
     }
-    return Gtk::Window::on_key_press_event(event);
+    return false;
 }
 
 MainWindow::~MainWindow() {
@@ -234,7 +233,7 @@ MainWindow::~MainWindow() {
     g_assert(config);
 
     int width, height;
-    get_size(width, height);
+    get_default_size(width, height);
     g_key_file_set_integer(config, "window", "width", width);
     g_key_file_set_integer(config, "window", "height", height);
     g_key_file_set_integer(config, "window", "sinkInputType", sinkInputTypeComboBox->get_active_row_number());
@@ -247,7 +246,7 @@ MainWindow::~MainWindow() {
     GError *err = NULL;
     gchar *filedata = g_key_file_to_data(config, &filelen, &err);
     if (err) {
-        show_error(_("Error saving preferences"));
+        show_error(this, _("Error saving preferences"));
         g_error_free(err);
         goto finish;
     }
@@ -256,7 +255,7 @@ MainWindow::~MainWindow() {
     g_free(filedata);
     if (err) {
         gchar* msg = g_strconcat(_("Error writing config file %s"), m_config_filename, NULL);
-        show_error(msg);
+        show_error(this, msg);
         g_free(msg);
         g_error_free(err);
         goto finish;
@@ -274,34 +273,20 @@ finish:
     }
 }
 
-static void set_icon_name_default(Gtk::Image *i, const char *name, Gtk::IconSize size) {
+static void set_icon_name_default(Gtk::Image *i, const char *name) {
+    /* We emulate the behavior of the GTK_ICON_LOOKUP_GENERIC_FALLBACK flag from Gtk3 */
     Glib::RefPtr<Gtk::IconTheme> theme;
-    Glib::RefPtr<Gdk::Pixbuf> pixbuf;
-    gint width = 24, height = 24;
-
-    Gtk::IconSize::lookup(size, width, height);
-    theme = Gtk::IconTheme::get_default();
-
-    try {
-        pixbuf = theme->load_icon(name, width, Gtk::ICON_LOOKUP_GENERIC_FALLBACK | Gtk::ICON_LOOKUP_FORCE_SIZE);
-    } catch (Glib::Error &e) {
-        /* Ignore errors. */
-    }
-
-    if (!pixbuf) {
-        try {
-            pixbuf = Gdk::Pixbuf::create_from_file(name);
-        } catch (Glib::FileError &e) {
-            /* Ignore errors. */
-        } catch (Gdk::PixbufError &e) {
-            /* Ignore errors. */
+    theme = Gtk::IconTheme::get_for_display(Gdk::Display::get_default());
+    std::string iconName(name);
+    while (!theme->has_icon(iconName.c_str())) {
+        size_t lastDashIndex = iconName.find_last_of("-");
+        if (lastDashIndex == std::string::npos) {
+            iconName = "gtk-missing-image";
+            break;
         }
+        iconName = iconName.substr(0,lastDashIndex);
     }
-
-    if (pixbuf) {
-        pixbuf = pixbuf->scale_simple(width, height, Gdk::INTERP_BILINEAR);
-        i->set(pixbuf);
-    }
+    i->set_from_icon_name(iconName.c_str());
 }
 
 static void updatePorts(DeviceWidget *w, std::map<Glib::ustring, PortInfo> &ports) {
@@ -365,7 +350,7 @@ void MainWindow::updateCard(const pa_card_info &info) {
         w = cardWidgets[info.index];
     else {
         cardWidgets[info.index] = w = CardWidget::create();
-        cardsVBox->pack_start(*w, false, false, 0);
+        cardsVBox->append(*w);
         w->unreference();
         w->index = info.index;
         is_new = true;
@@ -382,7 +367,7 @@ void MainWindow::updateCard(const pa_card_info &info) {
     g_free(txt);
 
     icon = pa_proplist_gets(info.proplist, PA_PROP_DEVICE_ICON_NAME);
-    set_icon_name_default(w->iconImage, icon ? icon : "audio-card", Gtk::ICON_SIZE_SMALL_TOOLBAR);
+    set_icon_name_default(w->iconImage, icon ? icon : "audio-card");
 
     w->hasSinks = w->hasSources = false;
     profile_priorities.clear();
@@ -556,7 +541,7 @@ bool MainWindow::updateSink(const pa_sink_info &info) {
     else {
         sinkWidgets[info.index] = w = SinkWidget::create(this);
         w->setChannelMap(info.channel_map, !!(info.flags & PA_SINK_DECIBEL_VOLUME));
-        sinksVBox->pack_start(*w, false, false, 0);
+        sinksVBox->append(*w);
         w->unreference();
         w->index = info.index;
         w->monitor_index = info.monitor_source;
@@ -580,7 +565,7 @@ bool MainWindow::updateSink(const pa_sink_info &info) {
     g_free(txt);
 
     icon = pa_proplist_gets(info.proplist, PA_PROP_DEVICE_ICON_NAME);
-    set_icon_name_default(w->iconImage, icon ? icon : "audio-card", Gtk::ICON_SIZE_SMALL_TOOLBAR);
+    set_icon_name_default(w->iconImage, icon ? icon : "audio-card");
 
     w->setVolume(info.volume);
     w->muteToggleButton->set_active(info.mute);
@@ -630,7 +615,7 @@ static void read_callback(pa_stream *s, size_t length, void *userdata) {
     double v;
 
     if (pa_stream_peek(s, &data, &length) < 0) {
-        show_error(_("Failed to read data from stream"));
+        show_error(w, _("Failed to read data from stream"));
         return;
     }
 
@@ -675,7 +660,7 @@ pa_stream* MainWindow::createMonitorStreamForSource(uint32_t source_idx, uint32_
     snprintf(t, sizeof(t), "%u", source_idx);
 
     if (!(s = pa_stream_new(get_context(), _("Peak detect"), &ss, NULL))) {
-        show_error(_("Failed to create monitoring stream"));
+        show_error(this, _("Failed to create monitoring stream"));
         return NULL;
     }
 
@@ -690,7 +675,7 @@ pa_stream* MainWindow::createMonitorStreamForSource(uint32_t source_idx, uint32_
                                  (!showVolumeMetersCheckButton->get_active() ? PA_STREAM_START_CORKED : PA_STREAM_NOFLAGS));
 
     if (pa_stream_connect_record(s, t, &attr, flags) < 0) {
-        show_error(_("Failed to connect monitoring stream"));
+        show_error(this, _("Failed to connect monitoring stream"));
         pa_stream_unref(s);
         return NULL;
     }
@@ -722,7 +707,7 @@ void MainWindow::updateSource(const pa_source_info &info) {
     else {
         sourceWidgets[info.index] = w = SourceWidget::create(this);
         w->setChannelMap(info.channel_map, !!(info.flags & PA_SOURCE_DECIBEL_VOLUME));
-        sourcesVBox->pack_start(*w, false, false, 0);
+        sourcesVBox->append(*w);
         w->unreference();
         w->index = info.index;
         is_new = true;
@@ -748,7 +733,7 @@ void MainWindow::updateSource(const pa_source_info &info) {
     g_free(txt);
 
     icon = pa_proplist_gets(info.proplist, PA_PROP_DEVICE_ICON_NAME);
-    set_icon_name_default(w->iconImage, icon ? icon : "audio-input-microphone", Gtk::ICON_SIZE_SMALL_TOOLBAR);
+    set_icon_name_default(w->iconImage, icon ? icon : "audio-input-microphone");
 
     w->setVolume(info.volume);
     w->muteToggleButton->set_active(info.mute);
@@ -817,7 +802,7 @@ void MainWindow::setIconFromProplist(Gtk::Image *icon, pa_proplist *l, const cha
 
 finish:
 
-    set_icon_name_default(icon, t, Gtk::ICON_SIZE_SMALL_TOOLBAR);
+    set_icon_name_default(icon, t);
 }
 
 void MainWindow::updateSinkInput(const pa_sink_input_info &info) {
@@ -840,7 +825,7 @@ void MainWindow::updateSinkInput(const pa_sink_input_info &info) {
     } else {
         sinkInputWidgets[info.index] = w = SinkInputWidget::create(this);
         w->setChannelMap(info.channel_map, true);
-        streamsVBox->pack_start(*w, false, false, 0);
+        streamsVBox->append(*w);
         w->unreference();
         w->index = info.index;
         w->clientIndex = info.client;
@@ -899,7 +884,7 @@ void MainWindow::updateSourceOutput(const pa_source_output_info &info) {
 #if HAVE_SOURCE_OUTPUT_VOLUMES
         w->setChannelMap(info.channel_map, true);
 #endif
-        recsVBox->pack_start(*w, false, false, 0);
+        recsVBox->append(*w);
         w->unreference();
         w->index = info.index;
         w->clientIndex = info.client;
@@ -996,7 +981,7 @@ bool MainWindow::createEventRoleWidget() {
     };
 
     eventRoleWidget = RoleWidget::create();
-    streamsVBox->pack_start(*eventRoleWidget, false, false, 0);
+    streamsVBox->append(*eventRoleWidget);
     eventRoleWidget->unreference();
     eventRoleWidget->role = "sink-input-by-media-role:event";
     eventRoleWidget->setChannelMap(cm, true);
@@ -1004,7 +989,7 @@ bool MainWindow::createEventRoleWidget() {
     eventRoleWidget->boldNameLabel->set_text("");
     eventRoleWidget->nameLabel->set_label(_("System Sounds"));
 
-    eventRoleWidget->iconImage->set_from_icon_name("multimedia-volume-control", Gtk::ICON_SIZE_SMALL_TOOLBAR);
+    eventRoleWidget->iconImage->set_from_icon_name("multimedia-volume-control");
 
     eventRoleWidget->device = "";
 
@@ -1292,7 +1277,7 @@ void MainWindow::removeSink(uint32_t index) {
     if (!sinkWidgets.count(index))
         return;
 
-    delete sinkWidgets[index];
+    sinksVBox->remove(*sinkWidgets[index]);
     sinkWidgets.erase(index);
     updateDeviceVisibility();
 }
@@ -1301,7 +1286,7 @@ void MainWindow::removeSource(uint32_t index) {
     if (!sourceWidgets.count(index))
         return;
 
-    delete sourceWidgets[index];
+    sourcesVBox->remove(*sourceWidgets[index]);
     sourceWidgets.erase(index);
     updateDeviceVisibility();
 }
@@ -1310,7 +1295,7 @@ void MainWindow::removeSinkInput(uint32_t index) {
     if (!sinkInputWidgets.count(index))
         return;
 
-    delete sinkInputWidgets[index];
+    streamsVBox->remove(*sinkInputWidgets[index]);
     sinkInputWidgets.erase(index);
     updateDeviceVisibility();
 }
@@ -1319,7 +1304,7 @@ void MainWindow::removeSourceOutput(uint32_t index) {
     if (!sourceOutputWidgets.count(index))
         return;
 
-    delete sourceOutputWidgets[index];
+    recsVBox->remove(*sourceOutputWidgets[index]);
     sourceOutputWidgets.erase(index);
     updateDeviceVisibility();
 }
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 5015144..ca40a7b 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -29,6 +29,8 @@ class MainWindow;
 #  include <pulse/ext-device-restore.h>
 #endif
 
+#include <canberra.h>
+
 #include <unordered_map>
 
 class CardWidget;
@@ -76,7 +78,7 @@ public:
     void setConnectingMessage(const char *string = NULL);
 
     Gtk::Notebook *notebook;
-    Gtk::VBox *streamsVBox, *recsVBox, *sinksVBox, *sourcesVBox, *cardsVBox;
+    Gtk::Box *streamsVBox, *recsVBox, *sinksVBox, *sourcesVBox, *cardsVBox;
     Gtk::Label *noStreamsLabel, *noRecsLabel, *noSinksLabel, *noSourcesLabel, *noCardsLabel, *connectingLabel;
     Gtk::ComboBox *sinkInputTypeComboBox, *sourceOutputTypeComboBox, *sinkTypeComboBox, *sourceTypeComboBox;
     Gtk::CheckButton *showVolumeMetersCheckButton;
@@ -116,9 +118,11 @@ public:
 
     bool canRenameDevices;
 
+    ca_context *canberraContext;
+
 protected:
     virtual void on_realize();
-    virtual bool on_key_press_event(GdkEventKey* event);
+    virtual bool on_key_press_event(guint keyval, guint keycode, Gdk::ModifierType state);
 
 private:
     gboolean m_connected;
diff --git a/src/meson.build b/src/meson.build
index f8a4b81..97eeb00 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -33,8 +33,8 @@ executable('pavucontrol',
 install_data('pavucontrol.glade')
 
 desktop_file = i18n.merge_file(
-  input : 'pavucontrol.desktop.in',
-  output : 'pavucontrol.desktop',
+  input : 'org.pulseaudio.pavucontrol.desktop.in',
+  output : 'org.pulseaudio.pavucontrol.desktop',
   po_dir : po_dir,
   type : 'desktop',
   install : true,
diff --git a/src/minimalstreamwidget.cc b/src/minimalstreamwidget.cc
index 09b34b8..92e5f08 100644
--- a/src/minimalstreamwidget.cc
+++ b/src/minimalstreamwidget.cc
@@ -26,7 +26,7 @@
 
 /*** MinimalStreamWidget ***/
 MinimalStreamWidget::MinimalStreamWidget(BaseObjectType* cobject) :
-    Gtk::VBox(cobject),
+    Gtk::Box(cobject),
     channelsVBox(NULL),
     nameLabel(NULL),
     boldNameLabel(NULL),
@@ -53,7 +53,7 @@ void MinimalStreamWidget::init() {
      * in the constructor. */
 
     peakProgressBar.set_size_request(-1, 10);
-    channelsVBox->pack_end(peakProgressBar, false, false);
+    channelsVBox->append(peakProgressBar);
 
     /* XXX: Why is the peak meter hidden by default? Maybe the idea is that if
      * setting up the monitoring stream fails for whatever reason, then we
@@ -64,20 +64,19 @@ void MinimalStreamWidget::init() {
 #define DECAY_STEP (1.0 / PEAKS_RATE)
 
 void MinimalStreamWidget::updatePeak(double v) {
-
     if (lastPeak >= DECAY_STEP)
         if (v < lastPeak - DECAY_STEP)
             v = lastPeak - DECAY_STEP;
 
     lastPeak = v;
 
-    if (v >= 0) {
-        peakProgressBar.set_sensitive(TRUE);
-        peakProgressBar.set_fraction(v);
-    } else {
-        peakProgressBar.set_sensitive(FALSE);
-        peakProgressBar.set_fraction(0);
-    }
+      if (v >= 0) {
+          peakProgressBar.set_sensitive(TRUE);
+          peakProgressBar.set_fraction(v);
+      } else {
+          peakProgressBar.set_sensitive(FALSE);
+          peakProgressBar.set_fraction(0);
+      }
 
     enableVolumeMeter();
 }
diff --git a/src/minimalstreamwidget.h b/src/minimalstreamwidget.h
index 24f2f6a..78671a5 100644
--- a/src/minimalstreamwidget.h
+++ b/src/minimalstreamwidget.h
@@ -25,7 +25,7 @@
 
 #define PEAKS_RATE 144
 
-class MinimalStreamWidget : public Gtk::VBox {
+class MinimalStreamWidget : public Gtk::Box {
 public:
     MinimalStreamWidget(BaseObjectType* cobject);
     virtual ~MinimalStreamWidget();
@@ -33,7 +33,7 @@ public:
     /* Subclass constructors are expected to initialize these variables.
      * MinimalStreamWidget can't initialize these, because the glade object
      * id's depend on the subclass type. */
-    Gtk::VBox *channelsVBox;
+    Gtk::Box *channelsVBox;
     Gtk::Label *nameLabel, *boldNameLabel;
     Gtk::Image *iconImage;
 
diff --git a/src/pavucontrol.desktop.in b/src/org.pulseaudio.pavucontrol.desktop.in
similarity index 100%
rename from src/pavucontrol.desktop.in
rename to src/org.pulseaudio.pavucontrol.desktop.in
diff --git a/src/pavuapplication.cc b/src/pavuapplication.cc
index 6773b53..f4ad11a 100644
--- a/src/pavuapplication.cc
+++ b/src/pavuapplication.cc
@@ -24,8 +24,6 @@
 
 #include "i18n.h"
 
-#include <canberra-gtk.h>
-
 #include "pavuapplication.h"
 #include "pavucontrol.h"
 #include "mainwindow.h"
@@ -39,7 +37,7 @@ PavuApplication::get_instance()
 }
 
 PavuApplication::PavuApplication() :
-    Gtk::Application("org.pulseaudio.pavucontrol", Gio::ApplicationFlags::APPLICATION_HANDLES_COMMAND_LINE),
+    Gtk::Application("org.pulseaudio.pavucontrol", Gio::Application::Flags::HANDLES_COMMAND_LINE),
     mainWindow(NULL),
     retry(false),
     maximize(false),
@@ -59,9 +57,8 @@ MainWindow* PavuApplication::create_window()
 
     MainWindow* pavucontrol_window = pavucontrol_get_window(m, maximize, retry, tab);
 
-    pavucontrol_window->signal_hide().connect(
-                     sigc::bind<Gtk::Window*>(sigc::mem_fun(*this,
-                     &PavuApplication::on_hide_window), pavucontrol_window));
+    pavucontrol_window->signal_close_request().connect(sigc::mem_fun(*this,
+                     &PavuApplication::on_close_window), true);
 
     return pavucontrol_window;
 }
@@ -94,9 +91,9 @@ void PavuApplication::on_activate()
  * exiting : when the last registered window of Gtk::Application is closed,
  * the application's run() function returns.
  */
-void PavuApplication::on_hide_window(Gtk::Window* window)
+bool PavuApplication::on_close_window()
 {
-    delete window;
+    delete mainWindow;
     mainWindow = NULL;
 
     if (get_context()) {
@@ -104,6 +101,7 @@ void PavuApplication::on_hide_window(Gtk::Window* window)
     }
     pa_glib_mainloop_free(m);
     m = NULL;
+    return true;
 }
 
 template <typename T_ArgType>
@@ -155,23 +153,23 @@ int main(int argc, char *argv[]) {
 
     /* Add command-line options */
     globalInstance.add_main_option_entry(
-        Gio::Application::OptionType::OPTION_TYPE_INT,
+        Gio::Application::OptionType::INT,
         "tab", 't',
         _("Select a specific tab on load."),
         _("number"));
 
     globalInstance.add_main_option_entry(
-        Gio::Application::OptionType::OPTION_TYPE_BOOL,
+        Gio::Application::OptionType::BOOL,
         "retry", 'r',
         _("Retry forever if pa quits (every 5 seconds)."));
 
     globalInstance.add_main_option_entry(
-        Gio::Application::OptionType::OPTION_TYPE_BOOL,
+        Gio::Application::OptionType::BOOL,
         "maximize", 'm',
         _("Maximize the window."));
 
     globalInstance.add_main_option_entry(
-        Gio::Application::OptionType::OPTION_TYPE_BOOL,
+        Gio::Application::OptionType::BOOL,
         "version", 'v',
         _("Show version."));
 
diff --git a/src/pavuapplication.h b/src/pavuapplication.h
index d2a1f5a..53cc0e3 100644
--- a/src/pavuapplication.h
+++ b/src/pavuapplication.h
@@ -45,7 +45,8 @@ protected:
 
 private:
     MainWindow* create_window();
-    void on_hide_window(Gtk::Window* window);
+    void on_hide_window();
+    bool on_close_window();
 
     pa_glib_mainloop *m;
 };
diff --git a/src/pavucontrol.cc b/src/pavucontrol.cc
index 18d5400..62a6499 100644
--- a/src/pavucontrol.cc
+++ b/src/pavucontrol.cc
@@ -29,8 +29,6 @@
 #include <json-glib/json-glib.h>
 #endif
 
-#include <canberra-gtk.h>
-
 #include "pavucontrol.h"
 #include "i18n.h"
 #include "minimalstreamwidget.h"
@@ -58,15 +56,27 @@ static int tab_number = 0;
 static bool retry = false;
 static int reconnect_timeout = 1;
 
-void show_error(const char *txt) {
+void show_error_finish (const Glib::RefPtr<Gio::AsyncResult>& result) {
+    PavuApplication::get_instance().quit();
+}
+
+void show_error(Gtk::Widget* widget, const char *txt) {
+    Gtk::Root *root = widget->get_root();
     char buf[256];
 
     snprintf(buf, sizeof(buf), "%s: %s", txt, pa_strerror(pa_context_errno(context)));
 
-    Gtk::MessageDialog dialog(buf, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
-    dialog.run();
-
-    PavuApplication::get_instance().quit();
+    auto dialog = Gtk::AlertDialog::create(buf);
+    dialog->set_modal(true);
+    if (GTK_IS_WINDOW(root->gobj())) {
+        GtkWindow* w = (GtkWindow*) root->gobj();
+        Gtk::Window* window = Glib::wrap(w);
+        window->present();
+        dialog->choose(*window, sigc::ptr_fun(show_error_finish));
+    }
+    else {
+        dialog->choose(sigc::ptr_fun(show_error_finish));
+    }
 }
 
 static void dec_outstanding(MainWindow *w) {
@@ -74,7 +84,7 @@ static void dec_outstanding(MainWindow *w) {
         return;
 
     if (--n_outstanding <= 0) {
-        w->get_window()->set_cursor();
+        w->set_cursor(Gdk::Cursor::create("default"));;
         w->setConnectionState(true);
     }
 }
@@ -355,7 +365,7 @@ void card_cb(pa_context *c, const pa_card_info *i, int eol, void *userdata) {
         if (pa_context_errno(context) == PA_ERR_NOENTITY)
             return;
 
-        show_error(_("Card callback failure"));
+        show_error(w, _("Card callback failure"));
         return;
     }
 
@@ -383,7 +393,7 @@ void sink_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata) {
         if (pa_context_errno(context) == PA_ERR_NOENTITY)
             return;
 
-        show_error(_("Sink callback failure"));
+        show_error(w, _("Sink callback failure"));
         return;
     }
 
@@ -407,7 +417,7 @@ void source_cb(pa_context *, const pa_source_info *i, int eol, void *userdata) {
         if (pa_context_errno(context) == PA_ERR_NOENTITY)
             return;
 
-        show_error(_("Source callback failure"));
+        show_error(w, _("Source callback failure"));
         return;
     }
 
@@ -426,7 +436,7 @@ void sink_input_cb(pa_context *, const pa_sink_input_info *i, int eol, void *use
         if (pa_context_errno(context) == PA_ERR_NOENTITY)
             return;
 
-        show_error(_("Sink input callback failure"));
+        show_error(w, _("Sink input callback failure"));
         return;
     }
 
@@ -445,7 +455,7 @@ void source_output_cb(pa_context *, const pa_source_output_info *i, int eol, voi
         if (pa_context_errno(context) == PA_ERR_NOENTITY)
             return;
 
-        show_error(_("Source output callback failure"));
+        show_error(w, _("Source output callback failure"));
         return;
     }
 
@@ -475,7 +485,7 @@ void client_cb(pa_context *, const pa_client_info *i, int eol, void *userdata) {
         if (pa_context_errno(context) == PA_ERR_NOENTITY)
             return;
 
-        show_error(_("Client callback failure"));
+        show_error(w, _("Client callback failure"));
         return;
     }
 
@@ -491,7 +501,7 @@ void server_info_cb(pa_context *, const pa_server_info *i, void *userdata) {
     MainWindow *w = static_cast<MainWindow*>(userdata);
 
     if (!i) {
-        show_error(_("Server info callback failure"));
+        show_error(w, _("Server info callback failure"));
         return;
     }
 
@@ -527,7 +537,7 @@ static void ext_stream_restore_subscribe_cb(pa_context *c, void *userdata) {
     pa_operation *o;
 
     if (!(o = pa_ext_stream_restore_read(c, ext_stream_restore_read_cb, w))) {
-        show_error(_("pa_ext_stream_restore_read() failed"));
+        show_error(w, _("pa_ext_stream_restore_read() failed"));
         return;
     }
 
@@ -566,7 +576,7 @@ static void ext_device_restore_subscribe_cb(pa_context *c, pa_device_type_t type
         return;
 
     if (!(o = pa_ext_device_restore_read_formats(c, type, idx, ext_device_restore_read_cb, w))) {
-        show_error(_("pa_ext_device_restore_read_sink_formats() failed"));
+        show_error(w, _("pa_ext_device_restore_read_sink_formats() failed"));
         return;
     }
 
@@ -603,7 +613,7 @@ static void ext_device_manager_subscribe_cb(pa_context *c, void *userdata) {
     pa_operation *o;
 
     if (!(o = pa_ext_device_manager_read(c, ext_device_manager_read_cb, w))) {
-        show_error(_("pa_ext_device_manager_read() failed"));
+        show_error(w, _("pa_ext_device_manager_read() failed"));
         return;
     }
 
@@ -620,7 +630,7 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
             else {
                 pa_operation *o;
                 if (!(o = pa_context_get_sink_info_by_index(c, index, sink_cb, w))) {
-                    show_error(_("pa_context_get_sink_info_by_index() failed"));
+                    show_error(w, _("pa_context_get_sink_info_by_index() failed"));
                     return;
                 }
                 pa_operation_unref(o);
@@ -633,7 +643,7 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
             else {
                 pa_operation *o;
                 if (!(o = pa_context_get_source_info_by_index(c, index, source_cb, w))) {
-                    show_error(_("pa_context_get_source_info_by_index() failed"));
+                    show_error(w, _("pa_context_get_source_info_by_index() failed"));
                     return;
                 }
                 pa_operation_unref(o);
@@ -646,7 +656,7 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
             else {
                 pa_operation *o;
                 if (!(o = pa_context_get_sink_input_info(c, index, sink_input_cb, w))) {
-                    show_error(_("pa_context_get_sink_input_info() failed"));
+                    show_error(w, _("pa_context_get_sink_input_info() failed"));
                     return;
                 }
                 pa_operation_unref(o);
@@ -659,7 +669,7 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
             else {
                 pa_operation *o;
                 if (!(o = pa_context_get_source_output_info(c, index, source_output_cb, w))) {
-                    show_error(_("pa_context_get_sink_input_info() failed"));
+                    show_error(w, _("pa_context_get_sink_input_info() failed"));
                     return;
                 }
                 pa_operation_unref(o);
@@ -672,7 +682,7 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
             else {
                 pa_operation *o;
                 if (!(o = pa_context_get_client_info(c, index, client_cb, w))) {
-                    show_error(_("pa_context_get_client_info() failed"));
+                    show_error(w, _("pa_context_get_client_info() failed"));
                     return;
                 }
                 pa_operation_unref(o);
@@ -682,7 +692,7 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
         case PA_SUBSCRIPTION_EVENT_SERVER: {
                 pa_operation *o;
                 if (!(o = pa_context_get_server_info(c, server_info_cb, w))) {
-                    show_error(_("pa_context_get_server_info() failed"));
+                    show_error(w, _("pa_context_get_server_info() failed"));
                     return;
                 }
                 pa_operation_unref(o);
@@ -695,7 +705,7 @@ void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index,
             else {
                 pa_operation *o;
                 if (!(o = pa_context_get_card_info_by_index(c, index, card_cb, w))) {
-                    show_error(_("pa_context_get_card_info_by_index() failed"));
+                    show_error(w, _("pa_context_get_card_info_by_index() failed"));
                     return;
                 }
                 pa_operation_unref(o);
@@ -738,7 +748,7 @@ void context_state_callback(pa_context *c, void *userdata) {
                                             PA_SUBSCRIPTION_MASK_CLIENT|
                                             PA_SUBSCRIPTION_MASK_SERVER|
                                             PA_SUBSCRIPTION_MASK_CARD), NULL, NULL))) {
-                show_error(_("pa_context_subscribe() failed"));
+                show_error(w, _("pa_context_subscribe() failed"));
                 return;
             }
             pa_operation_unref(o);
@@ -747,49 +757,49 @@ void context_state_callback(pa_context *c, void *userdata) {
             n_outstanding = 0;
 
             if (!(o = pa_context_get_server_info(c, server_info_cb, w))) {
-                show_error(_("pa_context_get_server_info() failed"));
+                show_error(w, _("pa_context_get_server_info() failed"));
                 return;
             }
             pa_operation_unref(o);
             n_outstanding++;
 
             if (!(o = pa_context_get_client_info_list(c, client_cb, w))) {
-                show_error(_("pa_context_client_info_list() failed"));
+                show_error(w, _("pa_context_client_info_list() failed"));
                 return;
             }
             pa_operation_unref(o);
             n_outstanding++;
 
             if (!(o = pa_context_get_card_info_list(c, card_cb, w))) {
-                show_error(_("pa_context_get_card_info_list() failed"));
+                show_error(w, _("pa_context_get_card_info_list() failed"));
                 return;
             }
             pa_operation_unref(o);
             n_outstanding++;
 
             if (!(o = pa_context_get_sink_info_list(c, sink_cb, w))) {
-                show_error(_("pa_context_get_sink_info_list() failed"));
+                show_error(w, _("pa_context_get_sink_info_list() failed"));
                 return;
             }
             pa_operation_unref(o);
             n_outstanding++;
 
             if (!(o = pa_context_get_source_info_list(c, source_cb, w))) {
-                show_error(_("pa_context_get_source_info_list() failed"));
+                show_error(w, _("pa_context_get_source_info_list() failed"));
                 return;
             }
             pa_operation_unref(o);
             n_outstanding++;
 
             if (!(o = pa_context_get_sink_input_info_list(c, sink_input_cb, w))) {
-                show_error(_("pa_context_get_sink_input_info_list() failed"));
+                show_error(w, _("pa_context_get_sink_input_info_list() failed"));
                 return;
             }
             pa_operation_unref(o);
             n_outstanding++;
 
             if (!(o = pa_context_get_source_output_info_list(c, source_output_cb, w))) {
-                show_error(_("pa_context_get_source_output_info_list() failed"));
+                show_error(w, _("pa_context_get_source_output_info_list() failed"));
                 return;
             }
             pa_operation_unref(o);
@@ -916,8 +926,6 @@ MainWindow* pavucontrol_get_window(pa_glib_mainloop *m, bool maximize, bool _ret
     tab_number = _tab_number;
     retry = _retry;
 
-    ca_context_set_driver(ca_gtk_context_get(), "pulse");
-
     mainWindow = MainWindow::create(maximize);
 
     api = pa_glib_mainloop_get_api(m);
diff --git a/src/pavucontrol.glade b/src/pavucontrol.glade
index b9155fb..25591fd 100644
--- a/src/pavucontrol.glade
+++ b/src/pavucontrol.glade
@@ -1,714 +1,430 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
-  <requires lib="gtk+" version="3.0"/>
+  <requires lib="gtk" version="4.0"/>
   <object class="GtkAdjustment" id="adjustment1">
     <property name="upper">100</property>
     <property name="value">44.2408370972</property>
     <property name="step_increment">5</property>
   </object>
   <object class="GtkWindow" id="channelWindow">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="title" translatable="yes">window2</property>
+    <property name="visible">1</property>
+    <property name="title" translatable="1">window2</property>
     <child>
       <placeholder/>
     </child>
-    <child>
-      <object class="GtkHBox" id="channelWidget">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
+    <property name="child">
+      <object class="GtkBox" id="channelWidget">
         <property name="spacing">6</property>
         <child>
           <object class="GtkLabel" id="channelLabel">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="label" translatable="yes"><b>left-front</b></property>
-            <property name="use_markup">True</property>
+            <property name="halign">center</property>
+            <property name="label" translatable="1"><b>left-front</b></property>
+            <property name="use_markup">1</property>
             <property name="xalign">1</property>
             <property name="yalign">0</property>
           </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
         </child>
         <child>
-          <object class="GtkHScale" id="volumeScale">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
+          <object class="GtkScale" id="volumeScale">
+            <property name="hexpand">1</property>
+            <property name="focusable">1</property>
             <property name="adjustment">adjustment1</property>
             <property name="digits">0</property>
-            <property name="draw_value">False</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="volumeLabel">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xpad">8</property>
-            <property name="label" translatable="yes"><small>50%</small></property>
-            <property name="use_markup">True</property>
+            <property name="halign">center</property>
+            <property name="margin_start">8</property>
+            <property name="margin_end">8</property>
+            <property name="label" translatable="1"><small>50%</small></property>
+            <property name="use_markup">1</property>
             <property name="justify">right</property>
             <property name="width_chars">12</property>
             <property name="xalign">1</property>
             <property name="yalign">0</property>
           </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">2</property>
-          </packing>
         </child>
       </object>
-    </child>
+    </property>
   </object>
   <object class="GtkWindow" id="cardWindow">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="title" translatable="yes">window1</property>
+    <property name="visible">1</property>
+    <property name="title" translatable="1">window1</property>
     <child>
       <placeholder/>
     </child>
-    <child>
-      <object class="GtkEventBox" id="cardWidgetBox">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="visible_window">False</property>
+    <property name="child">
+      <object class="GtkBox" id="cardWidget">
+        <property name="orientation">vertical</property>
         <child>
-          <object class="GtkVBox" id="cardWidget">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
+          <object class="GtkBox" id="vbox7">
+            <property name="valign">center</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">6</property>
+            <property name="margin-start">12</property>
+            <property name="margin-top">12</property>
+            <property name="margin-end">12</property>
+            <property name="margin-bottom">12</property>
             <child>
-              <object class="GtkVBox" id="vbox7">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="border_width">12</property>
+              <object class="GtkBox" id="hbox9">
+                <property name="valign">center</property>
                 <property name="spacing">6</property>
                 <child>
-                  <object class="GtkHBox" id="hbox9">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="spacing">6</property>
+                  <object class="GtkImage" id="cardIconImage">
+                    <property name="icon_name">gtk-missing-image</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkBox" id="hbox11">
+                    <property name="hexpand">1</property>
                     <child>
-                      <object class="GtkImage" id="cardIconImage">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
+                      <object class="GtkLabel" id="cardNameLabel">
+                        <property name="hexpand">1</property>
+                        <property name="label" translatable="1">Card Name</property>
+                        <property name="use_markup">1</property>
+                        <property name="ellipsize">middle</property>
                         <property name="xalign">0</property>
-                        <property name="stock">gtk-missing-image</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkHBox" id="hbox11">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <child>
-                          <object class="GtkLabel" id="cardNameLabel">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes">Card Name</property>
-                            <property name="use_markup">True</property>
-                            <property name="ellipsize">middle</property>
-                            <property name="xalign">0</property>
-                          </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
                       </object>
-                      <packing>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
-                        <property name="position">1</property>
-                      </packing>
                     </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkBox" id="hbox14">
+                    <property name="spacing">3</property>
                     <child>
-                      <object class="GtkHBox" id="hbox14">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="spacing">3</property>
+                      <object class="GtkToggleButton" id="profileLockToggleButton">
+                        <property name="halign">center</property>
+                        <property name="focusable">1</property>
+                        <property name="tooltip_text" translatable="1">Lock card to this profile</property>
+                        <property name="has-frame">0</property>
+                        <property name="active">1</property>
                         <child>
-                          <object class="GtkToggleButton" id="profileLockToggleButton">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="tooltip_text" translatable="yes">Lock card to this profile</property>
-                            <property name="relief">none</property>
-                            <property name="active">True</property>
-                            <child>
-                              <object class="GtkImage" id="image4">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="icon_name">changes-prevent</property>
-                                <property name="icon_size">1</property>
-                              </object>
-                            </child>
+                          <object class="GtkImage" id="image4">
+                            <property name="icon_name">changes-prevent</property>
+                            <property name="icon_size">normal</property>
                           </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">1</property>
-                          </packing>
                         </child>
                       </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">0</property>
-                  </packing>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkBox" id="hbox1">
+                <property name="valign">center</property>
+                <property name="spacing">6</property>
+                <child>
+                  <object class="GtkLabel" id="label1">
+                    <property name="label" translatable="1"><b>Profile:</b></property>
+                    <property name="use_markup">1</property>
+                    <property name="xalign">0</property>
+                  </object>
                 </child>
                 <child>
-                  <object class="GtkHBox" id="hbox1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                  <object class="GtkComboBox" id="profileList">
+                    <property name="hexpand">1</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkBox" id="codecBox">
+                    <property name="halign">center</property>
                     <property name="spacing">6</property>
                     <child>
-                      <object class="GtkLabel" id="label1">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes"><b>Profile:</b></property>
-                        <property name="use_markup">True</property>
+                      <object class="GtkLabel" id="label51">
+                        <property name="label" translatable="1"><b>Codec:</b></property>
+                        <property name="use_markup">1</property>
                         <property name="xalign">0</property>
                       </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkComboBox" id="profileList">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                      </object>
-                      <packing>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
-                        <property name="position">1</property>
-                      </packing>
                     </child>
                     <child>
-                      <object class="GtkHBox" id="codecBox">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="spacing">6</property>
-                        <child>
-                          <object class="GtkLabel" id="label51">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes"><b>Codec:</b></property>
-                            <property name="use_markup">True</property>
-                            <property name="xalign">0</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkComboBox" id="codecList">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                          </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
+                      <object class="GtkComboBox" id="codecList">
+                        <property name="hexpand">1</property>
                       </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">2</property>
-                      </packing>
                     </child>
                   </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">1</property>
-                  </packing>
                 </child>
               </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkHSeparator" id="hseparator5">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">1</property>
-              </packing>
             </child>
           </object>
         </child>
+        <child>
+          <object class="GtkSeparator" id="hseparator5">
+            <property name="valign">center</property>
+          </object>
+        </child>
       </object>
-    </child>
+    </property>
   </object>
   <object class="GtkWindow" id="deviceWindow">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="title" translatable="yes">window1</property>
+    <property name="visible">1</property>
+    <property name="title" translatable="1">window1</property>
     <child>
       <placeholder/>
     </child>
-    <child>
-      <object class="GtkEventBox" id="deviceWidgetBox">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="visible_window">False</property>
+    <property name="child">
+      <object class="GtkBox" id="deviceWidget">
+        <property name="orientation">vertical</property>
         <child>
-          <object class="GtkVBox" id="deviceWidget">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
+          <object class="GtkBox" id="vbox26">
+            <property name="valign">center</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">6</property>
+            <property name="margin-start">12</property>
+            <property name="margin-top">12</property>
+            <property name="margin-end">12</property>
+            <property name="margin-bottom">12</property>
             <child>
-              <object class="GtkVBox" id="vbox26">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="border_width">12</property>
+              <object class="GtkBox" id="hbox2">
+                <property name="valign">center</property>
                 <property name="spacing">6</property>
                 <child>
-                  <object class="GtkHBox" id="hbox2">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="spacing">6</property>
+                  <object class="GtkImage" id="deviceIconImage">
+                    <property name="icon_name">gtk-missing-image</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkBox" id="hbox12">
+                    <property name="hexpand">1</property>
                     <child>
-                      <object class="GtkImage" id="deviceIconImage">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="stock">gtk-missing-image</property>
+                      <object class="GtkLabel" id="deviceBoldNameLabel">
+                        <property name="use_markup">1</property>
                       </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
                     </child>
                     <child>
-                      <object class="GtkHBox" id="hbox12">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <child>
-                          <object class="GtkLabel" id="deviceBoldNameLabel">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</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="GtkLabel" id="deviceNameLabel">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes">Device Title</property>
-                            <property name="use_markup">True</property>
-                            <property name="ellipsize">end</property>
-                            <property name="xalign">0</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
+                      <object class="GtkLabel" id="deviceNameLabel">
+                        <property name="label" translatable="1">Device Title</property>
+                        <property name="use_markup">1</property>
+                        <property name="ellipsize">end</property>
+                        <property name="xalign">0</property>
                       </object>
-                      <packing>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
-                        <property name="position">1</property>
-                      </packing>
                     </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkBox" id="hbox10">
+                    <property name="spacing">3</property>
                     <child>
-                      <object class="GtkHBox" id="hbox10">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="spacing">3</property>
+                      <object class="GtkToggleButton" id="deviceMuteToggleButton">
+                        <property name="halign">center</property>
+                        <property name="focusable">1</property>
+                        <property name="tooltip_text" translatable="1">Mute audio</property>
+                        <property name="has-frame">0</property>
                         <child>
-                          <object class="GtkToggleButton" id="deviceMuteToggleButton">
-                            <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="relief">none</property>
-                            <child>
-                              <object class="GtkImage" id="image20">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="icon_name">audio-volume-muted</property>
-                                <property name="icon_size">1</property>
-                              </object>
-                            </child>
+                          <object class="GtkImage" id="image20">
+                            <property name="icon_name">audio-volume-muted</property>
+                            <property name="icon_size">normal</property>
                           </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">0</property>
-                          </packing>
                         </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkToggleButton" id="deviceLockToggleButton">
+                        <property name="halign">center</property>
+                        <property name="focusable">1</property>
+                        <property name="tooltip_text" translatable="1">Lock channels together</property>
+                        <property name="has-frame">0</property>
+                        <property name="active">1</property>
                         <child>
-                          <object class="GtkToggleButton" id="deviceLockToggleButton">
-                            <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="relief">none</property>
-                            <property name="active">True</property>
-                            <child>
-                              <object class="GtkImage" id="image18">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="icon_name">changes-prevent</property>
-                                <property name="icon_size">1</property>
-                              </object>
-                            </child>
+                          <object class="GtkImage" id="image18">
+                            <property name="icon_name">changes-prevent</property>
+                            <property name="icon_size">normal</property>
                           </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">1</property>
-                          </packing>
                         </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkToggleButton" id="defaultToggleButton">
+                        <property name="halign">center</property>
+                        <property name="focusable">1</property>
+                        <property name="tooltip_text" translatable="1">Set as default</property>
                         <child>
-                          <object class="GtkToggleButton" id="defaultToggleButton">
-                            <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 default</property>
-                            <child>
-                              <object class="GtkImage" id="image2">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="icon_name">emblem-default</property>
-                              </object>
-                            </child>
+                          <object class="GtkImage" id="image2">
+                            <property name="icon_name">emblem-default</property>
                           </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">2</property>
-                          </packing>
                         </child>
                       </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">0</property>
-                  </packing>
                 </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkBox" id="portSelect">
+                <property name="valign">center</property>
+                <property name="spacing">6</property>
                 <child>
-                  <object class="GtkHBox" id="portSelect">
-                    <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="label" translatable="yes"><b>Port:</b></property>
-                        <property name="use_markup">True</property>
-                        <property name="xalign">0</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkComboBox" id="portList">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                      </object>
-                      <packing>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
+                  <object class="GtkLabel" id="label2">
+                    <property name="label" translatable="1"><b>Port:</b></property>
+                    <property name="use_markup">1</property>
+                    <property name="xalign">0</property>
                   </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">1</property>
-                  </packing>
                 </child>
                 <child>
-                  <object class="GtkVBox" id="deviceChannelsVBox">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="spacing">6</property>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
+                  <object class="GtkComboBox" id="portList">
+                    <property name="hexpand">1</property>
                   </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">2</property>
-                  </packing>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkBox" id="deviceChannelsVBox">
+                <property name="valign">center</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">6</property>
+                <child>
+                  <placeholder/>
                 </child>
                 <child>
-                  <object class="GtkExpander" id="advancedOptions">
-                    <property name="can_focus">True</property>
+                  <placeholder/>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkExpander" id="advancedOptions">
+                <property name="valign">center</property>
+                <property name="visible">0</property>
+                <property name="focusable">1</property>
+                <child>
+                  <object class="GtkBox" id="vbox1">
+                    <property name="orientation">vertical</property>
                     <child>
-                      <object class="GtkVBox" id="vbox1">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
+                      <object class="GtkGrid" id="encodingSelect">
+                        <property name="valign">center</property>
+                        <property name="visible">0</property>
+                        <property name="row_homogeneous">1</property>
+                        <property name="column_homogeneous">1</property>
                         <child>
-                          <object class="GtkGrid" id="encodingSelect">
-                            <property name="can_focus">False</property>
-                            <property name="row_homogeneous">True</property>
-                            <property name="column_homogeneous">True</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="active">True</property>
-                                <property name="draw_indicator">True</property>
-                              </object>
-                              <packing>
-                                <property name="left_attach">0</property>
-                                <property name="top_attach">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkCheckButton" id="encodingFormatAC3">
-                                <property name="label" translatable="yes">AC-3</property>
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="receives_default">False</property>
-                                <property name="draw_indicator">True</property>
-                              </object>
-                              <packing>
-                                <property name="left_attach">1</property>
-                                <property name="top_attach">0</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="draw_indicator">True</property>
-                              </object>
-                              <packing>
-                                <property name="left_attach">2</property>
-                                <property name="top_attach">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkCheckButton" id="encodingFormatEAC3">
-                                <property name="label" translatable="yes">E-AC-3</property>
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="receives_default">False</property>
-                                <property name="draw_indicator">True</property>
-                              </object>
-                              <packing>
-                                <property name="left_attach">0</property>
-                                <property name="top_attach">1</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="draw_indicator">True</property>
-                              </object>
-                              <packing>
-                                <property name="left_attach">1</property>
-                                <property name="top_attach">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkCheckButton" id="encodingFormatAAC">
-                                <property name="label" translatable="yes">AAC</property>
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="receives_default">False</property>
-                                <property name="draw_indicator">True</property>
-                              </object>
-                              <packing>
-                                <property name="left_attach">2</property>
-                                <property name="top_attach">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkCheckButton" id="encodingFormatTRUEHD">
-                                <property name="label" translatable="yes">TrueHD</property>
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="receives_default">False</property>
-                                <property name="draw_indicator">True</property>
-                              </object>
-                              <packing>
-                                <property name="left_attach">0</property>
-                                <property name="top_attach">2</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkCheckButton" id="encodingFormatDTSHD">
-                                <property name="label" translatable="yes">DTS-HD</property>
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="receives_default">False</property>
-                                <property name="draw_indicator">True</property>
-                              </object>
-                              <packing>
-                                <property name="left_attach">1</property>
-                                <property name="top_attach">2</property>
-                              </packing>
-                            </child>
+                          <object class="GtkCheckButton" id="encodingFormatPCM">
+                            <property name="label" translatable="1">PCM</property>
+                            <property name="sensitive">0</property>
+                            <property name="focusable">1</property>
+                            <property name="active">1</property>
+                            <layout>
+                              <property name="column">0</property>
+                              <property name="row">0</property>
+                            </layout>
                           </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">0</property>
-                          </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="label3">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="label" translatable="yes"><b>Latency offset:</b></property>
-                                <property name="use_markup">True</property>
-                                <property name="xalign">0</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>
-                              </object>
-                              <packing>
-                                <property name="expand">True</property>
-                                <property name="fill">True</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="label4">
-                                <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 class="GtkCheckButton" id="encodingFormatAC3">
+                            <property name="label" translatable="1">AC-3</property>
+                            <property name="focusable">1</property>
+                            <layout>
+                              <property name="column">1</property>
+                              <property name="row">0</property>
+                            </layout>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" id="encodingFormatDTS">
+                            <property name="label" translatable="1">DTS</property>
+                            <property name="focusable">1</property>
+                            <layout>
+                              <property name="column">2</property>
+                              <property name="row">0</property>
+                            </layout>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" id="encodingFormatEAC3">
+                            <property name="label" translatable="1">E-AC-3</property>
+                            <property name="focusable">1</property>
+                            <layout>
+                              <property name="column">0</property>
+                              <property name="row">1</property>
+                            </layout>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" id="encodingFormatMPEG">
+                            <property name="label" translatable="1">MPEG</property>
+                            <property name="focusable">1</property>
+                            <layout>
+                              <property name="column">1</property>
+                              <property name="row">1</property>
+                            </layout>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" id="encodingFormatAAC">
+                            <property name="label" translatable="1">AAC</property>
+                            <property name="focusable">1</property>
+                            <layout>
+                              <property name="column">2</property>
+                              <property name="row">1</property>
+                            </layout>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" id="encodingFormatTRUEHD">
+                            <property name="label" translatable="1">TrueHD</property>
+                            <property name="focusable">1</property>
+                            <layout>
+                              <property name="column">0</property>
+                              <property name="row">2</property>
+                            </layout>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" id="encodingFormatDTSHD">
+                            <property name="label" translatable="1">DTS-HD</property>
+                            <property name="focusable">1</property>
+                            <layout>
+                              <property name="column">1</property>
+                              <property name="row">2</property>
+                            </layout>
                           </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">1</property>
-                          </packing>
                         </child>
                       </object>
                     </child>
-                    <child type="label">
-                      <object class="GtkLabel" id="advancedLabel">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes">Advanced</property>
+                    <child>
+                      <object class="GtkBox" id="offsetSelect">
+                        <property name="valign">center</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkLabel" id="label3">
+                            <property name="label" translatable="1"><b>Latency offset:</b></property>
+                            <property name="use_markup">1</property>
+                            <property name="xalign">0</property>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkSpinButton" id="offsetButton">
+                            <property name="hexpand">1</property>
+                            <property name="focusable">1</property>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="label4">
+                            <property name="label" translatable="1">ms</property>
+                            <property name="use_markup">1</property>
+                          </object>
+                        </child>
                       </object>
                     </child>
                   </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">3</property>
-                  </packing>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="advancedLabel">
+                    <property name="label" translatable="1">Advanced</property>
+                  </object>
                 </child>
               </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkHSeparator" id="hseparator2">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">1</property>
-              </packing>
             </child>
           </object>
         </child>
+        <child>
+          <object class="GtkSeparator" id="hseparator2">
+            <property name="valign">center</property>
+          </object>
+        </child>
       </object>
-    </child>
+    </property>
   </object>
   <object class="GtkListStore" id="liststore1">
     <columns>
-      <!-- column-name item -->
       <column type="gchararray"/>
     </columns>
     <data>
@@ -725,7 +441,6 @@
   </object>
   <object class="GtkListStore" id="liststore2">
     <columns>
-      <!-- column-name item -->
       <column type="gchararray"/>
     </columns>
     <data>
@@ -742,7 +457,6 @@
   </object>
   <object class="GtkListStore" id="liststore3">
     <columns>
-      <!-- column-name item -->
       <column type="gchararray"/>
     </columns>
     <data>
@@ -759,7 +473,6 @@
   </object>
   <object class="GtkListStore" id="liststore4">
     <columns>
-      <!-- column-name item -->
       <column type="gchararray"/>
     </columns>
     <data>
@@ -781,113 +494,76 @@
     </data>
   </object>
   <object class="GtkWindow" id="mainWindow">
-    <property name="can_focus">False</property>
-    <property name="title" translatable="yes">Volume Control</property>
+    <property name="title" translatable="1">Volume Control</property>
     <property name="default_width">500</property>
     <property name="default_height">400</property>
     <property name="icon_name">multimedia-volume-control</property>
     <child>
       <placeholder/>
     </child>
-    <child>
-      <object class="GtkVBox" id="vbox20">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
+    <property name="child">
+      <object class="GtkBox" id="vbox20">
+        <property name="orientation">vertical</property>
         <property name="spacing">12</property>
         <child>
           <object class="GtkNotebook" id="notebook">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="show_border">False</property>
-            <property name="scrollable">True</property>
+            <property name="vexpand">1</property>
+            <property name="focusable">1</property>
+            <property name="show_border">0</property>
+            <property name="scrollable">1</property>
             <child>
-              <object class="GtkVBox" id="vbox32">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <child>
-                  <object class="GtkScrolledWindow" id="scrolledwindow5">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="border_width">0</property>
+              <object class="GtkNotebookPage">
+                <property name="child">
+                  <object class="GtkBox" id="vbox32">
+                    <property name="orientation">vertical</property>
                     <child>
-                      <object class="GtkViewport" id="viewport1">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="shadow_type">none</property>
-                        <child>
-                          <object class="GtkVBox" id="streamsVBox">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <child>
-                              <object class="GtkLabel" id="noStreamsLabel">
-                                <property name="visible">True</property>
-                                <property name="sensitive">False</property>
-                                <property name="can_focus">False</property>
-                                <property name="xpad">16</property>
-                                <property name="ypad">16</property>
-                                <property name="label" translatable="yes"><i>No application is currently playing audio.</i></property>
-                                <property name="use_markup">True</property>
+                      <object class="GtkScrolledWindow" id="scrolledwindow5">
+                        <property name="vexpand">1</property>
+                        <property name="focusable">1</property>
+                        <property name="child">
+                          <object class="GtkViewport" id="viewport1">
+                            <property name="child">
+                              <object class="GtkBox" id="streamsVBox">
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel" id="noStreamsLabel">
+                                    <property name="vexpand">1</property>
+                                    <property name="sensitive">0</property>
+                                    <property name="label" translatable="1"><i>No application is currently playing audio.</i></property>
+                                    <property name="use_markup">1</property>
+                                  </object>
+                                </child>
                               </object>
-                              <packing>
-                                <property name="expand">True</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
+                            </property>
                           </object>
-                        </child>
+                        </property>
                       </object>
                     </child>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkHSeparator" id="hseparator1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkAlignment" id="alignment3">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="top_padding">12</property>
-                    <property name="bottom_padding">12</property>
-                    <property name="left_padding">12</property>
-                    <property name="right_padding">12</property>
                     <child>
-                      <object class="GtkHBox" id="hbox5">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
+                      <object class="GtkSeparator" id="hseparator1">
+                        <property name="valign">center</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkBox" id="hbox5">
                         <property name="spacing">6</property>
+                        <property name="margin-top">12</property>
+                        <property name="margin-bottom">12</property>
+                        <property name="margin-start">12</property>
+                        <property name="margin-end">12</property>
+                        <property name="valign">center</property>
                         <child>
                           <object class="GtkLabel" id="label5">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes"><b>_Show:</b></property>
-                            <property name="use_markup">True</property>
-                            <property name="use_underline">True</property>
+                            <property name="hexpand">1</property>
+                            <property name="label" translatable="1"><b>_Show:</b></property>
+                            <property name="use_markup">1</property>
+                            <property name="use_underline">1</property>
                             <property name="xalign">1</property>
                           </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
                         </child>
                         <child>
                           <object class="GtkComboBox" id="sinkInputTypeComboBox">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
+                            <property name="hexpand">1</property>
                             <property name="model">liststore1</property>
                             <child>
                               <object class="GtkCellRendererText" id="cellrenderertext1"/>
@@ -896,122 +572,72 @@
                               </attributes>
                             </child>
                           </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
                         </child>
                       </object>
                     </child>
                   </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
-              </object>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel" id="label34">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">_Playback</property>
-                <property name="use_underline">True</property>
+                </property>
+                <property name="tab">
+                  <object class="GtkLabel" id="label34">
+                    <property name="label" translatable="1">_Playback</property>
+                    <property name="use_underline">1</property>
+                  </object>
+                </property>
               </object>
-              <packing>
-                <property name="tab_fill">False</property>
-              </packing>
             </child>
             <child>
-              <object class="GtkVBox" id="vbox2">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <child>
-                  <object class="GtkScrolledWindow" id="scrolledwindow2">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="border_width">0</property>
+              <object class="GtkNotebookPage">
+                <property name="child">
+                  <object class="GtkBox" id="vbox2">
+                    <property name="orientation">vertical</property>
                     <child>
-                      <object class="GtkViewport" id="viewport5">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="shadow_type">none</property>
-                        <child>
-                          <object class="GtkVBox" id="recsVBox">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <child>
-                              <object class="GtkLabel" id="noRecsLabel">
-                                <property name="visible">True</property>
-                                <property name="sensitive">False</property>
-                                <property name="can_focus">False</property>
-                                <property name="xpad">16</property>
-                                <property name="ypad">16</property>
-                                <property name="label" translatable="yes"><i>No application is currently recording audio.</i></property>
-                                <property name="use_markup">True</property>
+                      <object class="GtkScrolledWindow" id="scrolledwindow2">
+                        <property name="vexpand">1</property>
+                        <property name="focusable">1</property>
+                        <property name="child">
+                          <object class="GtkViewport" id="viewport5">
+                            <property name="child">
+                              <object class="GtkBox" id="recsVBox">
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel" id="noRecsLabel">
+                                    <property name="vexpand">1</property>
+                                    <property name="sensitive">0</property>
+                                    <property name="label" translatable="1"><i>No application is currently recording audio.</i></property>
+                                    <property name="use_markup">1</property>
+                                  </object>
+                                </child>
                               </object>
-                              <packing>
-                                <property name="expand">True</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
+                            </property>
                           </object>
-                        </child>
+                        </property>
                       </object>
                     </child>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkHSeparator" id="hseparator3">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkAlignment" id="alignment9">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="top_padding">12</property>
-                    <property name="bottom_padding">12</property>
-                    <property name="left_padding">12</property>
-                    <property name="right_padding">12</property>
                     <child>
-                      <object class="GtkHBox" id="hbox7">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
+                      <object class="GtkSeparator" id="hseparator3">
+                        <property name="valign">center</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkBox" id="hbox7">
                         <property name="spacing">6</property>
+                        <property name="margin-top">12</property>
+                        <property name="margin-bottom">12</property>
+                        <property name="margin-start">12</property>
+                        <property name="margin-end">12</property>
+                        <property name="valign">center</property>
                         <child>
                           <object class="GtkLabel" id="label8">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes"><b>_Show:</b></property>
-                            <property name="use_markup">True</property>
-                            <property name="use_underline">True</property>
+                            <property name="hexpand">1</property>
+                            <property name="label" translatable="1"><b>_Show:</b></property>
+                            <property name="use_markup">1</property>
+                            <property name="use_underline">1</property>
                             <property name="xalign">1</property>
                           </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
                         </child>
                         <child>
                           <object class="GtkComboBox" id="sourceOutputTypeComboBox">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
+                            <property name="hexpand">1</property>
                             <property name="model">liststore2</property>
                             <child>
                               <object class="GtkCellRendererText" id="cellrenderertext2"/>
@@ -1020,127 +646,73 @@
                               </attributes>
                             </child>
                           </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
                         </child>
                       </object>
                     </child>
                   </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel" id="label6">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">_Recording</property>
-                <property name="use_underline">True</property>
+                </property>
+                <property name="tab">
+                  <object class="GtkLabel" id="label6">
+                    <property name="label" translatable="1">_Recording</property>
+                    <property name="use_underline">1</property>
+                  </object>
+                </property>
               </object>
-              <packing>
-                <property name="position">1</property>
-                <property name="tab_fill">False</property>
-              </packing>
             </child>
             <child>
-              <object class="GtkVBox" id="vbox30">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <child>
-                  <object class="GtkScrolledWindow" id="scrolledwindow8">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="border_width">0</property>
+              <object class="GtkNotebookPage">
+                <property name="child">
+                  <object class="GtkBox" id="vbox30">
+                    <property name="orientation">vertical</property>
                     <child>
-                      <object class="GtkViewport" id="viewport4">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="shadow_type">none</property>
-                        <child>
-                          <object class="GtkVBox" id="sinksVBox">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <child>
-                              <object class="GtkLabel" id="noSinksLabel">
-                                <property name="visible">True</property>
-                                <property name="sensitive">False</property>
-                                <property name="can_focus">False</property>
-                                <property name="xpad">16</property>
-                                <property name="ypad">16</property>
-                                <property name="label" translatable="yes"><i>No output devices available</i></property>
-                                <property name="use_markup">True</property>
+                      <object class="GtkScrolledWindow" id="scrolledwindow8">
+                        <property name="vexpand">1</property>
+                        <property name="focusable">1</property>
+                        <property name="child">
+                          <object class="GtkViewport" id="viewport4">
+                            <property name="child">
+                              <object class="GtkBox" id="sinksVBox">
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel" id="noSinksLabel">
+                                    <property name="vexpand">1</property>
+                                    <property name="sensitive">0</property>
+                                    <property name="label" translatable="1"><i>No output devices available</i></property>
+                                    <property name="use_markup">1</property>
+                                  </object>
+                                </child>
                               </object>
-                              <packing>
-                                <property name="expand">True</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
+                            </property>
                           </object>
-                        </child>
+                        </property>
                       </object>
                     </child>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkHSeparator" id="hseparator4">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkAlignment" id="alignment1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="top_padding">12</property>
-                    <property name="bottom_padding">12</property>
-                    <property name="left_padding">12</property>
-                    <property name="right_padding">12</property>
                     <child>
-                      <object class="GtkHBox" id="hbox3">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
+                      <object class="GtkSeparator" id="hseparator4">
+                        <property name="valign">center</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkBox" id="hbox3">
                         <property name="spacing">6</property>
+                        <property name="margin-top">12</property>
+                        <property name="margin-bottom">12</property>
+                        <property name="margin-start">12</property>
+                        <property name="margin-end">12</property>
+                        <property name="valign">center</property>
                         <child>
                           <object class="GtkLabel" id="label4826">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes"><b>S_how:</b></property>
-                            <property name="use_markup">True</property>
-                            <property name="use_underline">True</property>
+                            <property name="hexpand">1</property>
+                            <property name="label" translatable="1"><b>S_how:</b></property>
+                            <property name="use_markup">1</property>
+                            <property name="use_underline">1</property>
                             <property name="mnemonic_widget">sinkTypeComboBox</property>
                             <property name="xalign">1</property>
                           </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
                         </child>
                         <child>
                           <object class="GtkComboBox" id="sinkTypeComboBox">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
+                            <property name="hexpand">1</property>
                             <property name="model">liststore3</property>
                             <child>
                               <object class="GtkCellRendererText" id="cellrenderertext3"/>
@@ -1149,128 +721,73 @@
                               </attributes>
                             </child>
                           </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
                         </child>
                       </object>
                     </child>
                   </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="position">2</property>
-              </packing>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel" id="label4711">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">_Output Devices</property>
-                <property name="use_underline">True</property>
+                </property>
+                <property name="tab">
+                  <object class="GtkLabel" id="label4711">
+                    <property name="label" translatable="1">_Output Devices</property>
+                    <property name="use_underline">1</property>
+                  </object>
+                </property>
               </object>
-              <packing>
-                <property name="position">2</property>
-                <property name="tab_fill">False</property>
-              </packing>
             </child>
             <child>
-              <object class="GtkVBox" id="vbox31">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <child>
-                  <object class="GtkScrolledWindow" id="scrolledwindow7">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="border_width">0</property>
+              <object class="GtkNotebookPage">
+                <property name="child">
+                  <object class="GtkBox" id="vbox31">
+                    <property name="orientation">vertical</property>
                     <child>
-                      <object class="GtkViewport" id="viewport3">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="resize_mode">queue</property>
-                        <property name="shadow_type">none</property>
-                        <child>
-                          <object class="GtkVBox" id="sourcesVBox">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <child>
-                              <object class="GtkLabel" id="noSourcesLabel">
-                                <property name="visible">True</property>
-                                <property name="sensitive">False</property>
-                                <property name="can_focus">False</property>
-                                <property name="xpad">16</property>
-                                <property name="ypad">16</property>
-                                <property name="label" translatable="yes"><i>No input devices available</i></property>
-                                <property name="use_markup">True</property>
+                      <object class="GtkScrolledWindow" id="scrolledwindow7">
+                        <property name="vexpand">1</property>
+                        <property name="focusable">1</property>
+                        <property name="child">
+                          <object class="GtkViewport" id="viewport3">
+                            <property name="child">
+                              <object class="GtkBox" id="sourcesVBox">
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel" id="noSourcesLabel">
+                                    <property name="vexpand">1</property>
+                                    <property name="sensitive">0</property>
+                                    <property name="label" translatable="1"><i>No input devices available</i></property>
+                                    <property name="use_markup">1</property>
+                                  </object>
+                                </child>
                               </object>
-                              <packing>
-                                <property name="expand">True</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
+                            </property>
                           </object>
-                        </child>
+                        </property>
                       </object>
                     </child>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkHSeparator" id="hseparator6">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkAlignment" id="alignment2">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="top_padding">12</property>
-                    <property name="bottom_padding">12</property>
-                    <property name="left_padding">12</property>
-                    <property name="right_padding">12</property>
                     <child>
-                      <object class="GtkHBox" id="hbox4">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
+                      <object class="GtkSeparator" id="hseparator6">
+                        <property name="valign">center</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkBox" id="hbox4">
                         <property name="spacing">6</property>
+                        <property name="margin-top">12</property>
+                        <property name="margin-bottom">12</property>
+                        <property name="margin-start">12</property>
+                        <property name="margin-end">12</property>
+                        <property name="valign">center</property>
                         <child>
                           <object class="GtkLabel" id="label4827">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes"><b>Sho_w:</b></property>
-                            <property name="use_markup">True</property>
-                            <property name="use_underline">True</property>
+                            <property name="hexpand">1</property>
+                            <property name="label" translatable="1"><b>Sho_w:</b></property>
+                            <property name="use_markup">1</property>
+                            <property name="use_underline">1</property>
                             <property name="mnemonic_widget">sourceTypeComboBox</property>
                             <property name="xalign">1</property>
                           </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
                         </child>
                         <child>
                           <object class="GtkComboBox" id="sourceTypeComboBox">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
+                            <property name="hexpand">1</property>
                             <property name="model">liststore4</property>
                             <child>
                               <object class="GtkCellRendererText" id="cellrenderertext4"/>
@@ -1279,442 +796,263 @@
                               </attributes>
                             </child>
                           </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
                         </child>
                       </object>
                     </child>
                   </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="position">3</property>
-              </packing>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel" id="label4717">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">_Input Devices</property>
-                <property name="use_underline">True</property>
+                </property>
+                <property name="tab">
+                  <object class="GtkLabel" id="label4717">
+                    <property name="label" translatable="1">_Input Devices</property>
+                    <property name="use_underline">1</property>
+                  </object>
+                </property>
               </object>
-              <packing>
-                <property name="position">3</property>
-                <property name="tab_fill">False</property>
-              </packing>
             </child>
             <child>
-              <object class="GtkVBox" id="vbox3">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <child>
-                  <object class="GtkScrolledWindow" id="scrolledwindow1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="border_width">0</property>
+              <object class="GtkNotebookPage">
+                <property name="child">
+                  <object class="GtkBox" id="vbox3">
+                    <property name="orientation">vertical</property>
                     <child>
-                      <object class="GtkViewport" id="viewport2">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="shadow_type">none</property>
-                        <child>
-                          <object class="GtkVBox" id="vbox4">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <child>
-                              <object class="GtkVBox" id="cardsVBox">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
+                      <object class="GtkScrolledWindow" id="scrolledwindow1">
+                        <property name="vexpand">1</property>
+                        <property name="focusable">1</property>
+                        <property name="child">
+                          <object class="GtkViewport" id="viewport2">
+                            <property name="child">
+                              <object class="GtkBox" id="vbox4">
+                                <property name="orientation">vertical</property>
                                 <child>
-                                  <object class="GtkLabel" id="noCardsLabel">
-                                    <property name="visible">True</property>
-                                    <property name="sensitive">False</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="xpad">16</property>
-                                    <property name="ypad">16</property>
-                                    <property name="label" translatable="yes"><i>No cards available for configuration</i></property>
-                                    <property name="use_markup">True</property>
+                                  <object class="GtkBox" id="cardsVBox">
+                                    <property name="vexpand">1</property>
+                                    <property name="orientation">vertical</property>
+                                    <child>
+                                      <object class="GtkLabel" id="noCardsLabel">
+                                        <property name="vexpand">1</property>
+                                        <property name="sensitive">0</property>
+                                        <property name="label" translatable="1"><i>No cards available for configuration</i></property>
+                                        <property name="use_markup">1</property>
+                                      </object>
+                                    </child>
                                   </object>
-                                  <packing>
-                                    <property name="expand">True</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
                                 </child>
-                              </object>
-                              <packing>
-                                <property name="expand">True</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkVBox" id="vbox5">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
                                 <child>
-                                  <object class="GtkHSeparator" id="hseparator7">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
+                                  <object class="GtkBox" id="vbox5">
+                                    <property name="orientation">vertical</property>
+                                    <property name="vexpand-set">1</property>
+                                    <child>
+                                      <object class="GtkSeparator" id="hseparator7"/>
+                                    </child>
+                                    <child>
+                                      <object class="GtkCheckButton" id="showVolumeMetersCheckButton">
+                                        <property name="label" translatable="1">Show volume meters</property>
+                                        <property name="focusable">1</property>
+                                        <property name="active">1</property>
+                                      </object>
+                                    </child>
                                   </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkCheckButton" id="showVolumeMetersCheckButton">
-                                    <property name="label" translatable="yes">Show volume meters</property>
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">True</property>
-                                    <property name="receives_default">False</property>
-                                    <property name="active">True</property>
-                                    <property name="draw_indicator">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">True</property>
-                                    <property name="fill">True</property>
-                                    <property name="position">1</property>
-                                  </packing>
                                 </child>
                               </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
+                            </property>
                           </object>
-                        </child>
+                        </property>
                       </object>
                     </child>
                   </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="position">4</property>
-              </packing>
-            </child>
-            <child type="tab">
-              <object class="GtkLabel" id="label7">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">_Configuration</property>
-                <property name="use_underline">True</property>
+                </property>
+                <property name="tab">
+                  <object class="GtkLabel" id="label7">
+                    <property name="label" translatable="1">_Configuration</property>
+                    <property name="use_underline">1</property>
+                  </object>
+                </property>
               </object>
-              <packing>
-                <property name="position">4</property>
-                <property name="tab_fill">False</property>
-              </packing>
             </child>
           </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">0</property>
-          </packing>
         </child>
         <child>
           <object class="GtkLabel" id="connectingLabel">
-            <property name="can_focus">False</property>
+            <property name="vexpand">1</property>
+            <property name="visible">0</property>
             <property name="label">...</property>
-            <property name="use_markup">True</property>
+            <property name="use_markup">1</property>
           </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
         </child>
       </object>
-    </child>
+    </property>
   </object>
-  <object class="GtkDialog" id="renameDialog">
-    <property name="can_focus">False</property>
-    <property name="border_width">5</property>
-    <property name="type_hint">normal</property>
+  <object class="GtkApplicationWindow" id="renameDialog">
+    <property name="modal">1</property>
     <child>
-      <placeholder/>
-    </child>
-    <child internal-child="vbox">
       <object class="GtkBox" id="dialog-vbox1">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
         <property name="spacing">2</property>
-        <child internal-child="action_area">
-          <object class="GtkButtonBox" id="dialog-action_area1">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="layout_style">end</property>
-            <child>
-              <placeholder/>
-            </child>
-            <child>
-              <placeholder/>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="pack_type">end</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
+        <property name="margin-start">5</property>
+        <property name="margin-top">5</property>
+        <property name="margin-end">5</property>
+        <property name="margin-bottom">5</property>
         <child>
           <object class="GtkLabel" id="label9">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="label" translatable="yes"><b>Rename device to:</b></property>
-            <property name="use_markup">True</property>
+            <property name="vexpand">1</property>
+            <property name="label" translatable="1"><b>Rename device to:</b></property>
+            <property name="use_markup">1</property>
             <property name="xalign">0</property>
           </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
         </child>
         <child>
           <object class="GtkEntry" id="renameText">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
+            <property name="vexpand">1</property>
+            <property name="focusable">1</property>
             <property name="invisible_char">●</property>
-            <property name="activates_default">True</property>
+            <property name="activates_default">1</property>
             <property name="width_chars">60</property>
-            <property name="primary_icon_activatable">False</property>
-            <property name="secondary_icon_activatable">False</property>
           </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">2</property>
-          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="dialog-action_area1">
+            <property name="baseline_position">bottom</property>
+            <property name="halign">GTK_ALIGN_END</property>
+            <property name="homogeneous">1</property>
+            <child>
+              <object class="GtkButton">
+                <property name="label" translatable="1">_Cancel</property>
+                <property name="use_underline">1</property>
+                <property name="focusable">1</property>
+                <property name="action_name">window.close</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkButton" id="renameButton">
+                <property name="label" translatable="1">_Ok</property>
+                <property name="use_underline">1</property>
+                <property name="focusable">1</property>
+                <property name="action_name">win.rename</property>
+              </object>
+            </child>
+          </object>
         </child>
       </object>
     </child>
   </object>
   <object class="GtkWindow" id="streamWindow">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="title" translatable="yes">window1</property>
+    <property name="visible">1</property>
+    <property name="title" translatable="1">window1</property>
     <child>
       <placeholder/>
     </child>
-    <child>
-      <object class="GtkEventBox" id="streamWidgetBox">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="visible_window">False</property>
+    <property name="child">
+      <object class="GtkBox" id="streamWidget">
+        <property name="orientation">vertical</property>
         <child>
-          <object class="GtkVBox" id="streamWidget">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
+          <object class="GtkBox" id="vbox6">
+            <property name="valign">center</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">6</property>
+            <property name="margin-start">12</property>
+            <property name="margin-top">12</property>
+            <property name="margin-end">12</property>
+            <property name="margin-bottom">12</property>
             <child>
-              <object class="GtkVBox" id="vbox6">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="border_width">12</property>
+              <object class="GtkBox" id="hbox6">
+                <property name="valign">center</property>
                 <property name="spacing">6</property>
                 <child>
-                  <object class="GtkHBox" id="hbox6">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="spacing">6</property>
+                  <object class="GtkImage" id="streamIconImage">
+                    <property name="icon_name">gtk-missing-image</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkBox" id="hbox8">
+                    <property name="hexpand">1</property>
+                    <property name="spacing">2</property>
                     <child>
-                      <object class="GtkImage" id="streamIconImage">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="stock">gtk-missing-image</property>
+                      <object class="GtkLabel" id="streamBoldNameLabel">
+                        <property name="use_markup">1</property>
                       </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
                     </child>
                     <child>
-                      <object class="GtkHBox" id="hbox8">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="spacing">2</property>
-                        <child>
-                          <object class="GtkLabel" id="streamBoldNameLabel">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</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="GtkLabel" id="streamNameLabel">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes">Stream Title</property>
-                            <property name="use_markup">True</property>
-                            <property name="ellipsize">end</property>
-                            <property name="xalign">0</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="directionLabel">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="xpad">4</property>
-                            <property name="label" translatable="yes">direction</property>
-                            <property name="use_markup">True</property>
-                            <property name="xalign">0</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">2</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkComboBoxText" id="deviceComboBox">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="pack_type">end</property>
-                            <property name="position">3</property>
-                          </packing>
-                        </child>
+                      <object class="GtkLabel" id="streamNameLabel">
+                        <property name="label" translatable="1">Stream Title</property>
+                        <property name="use_markup">1</property>
+                        <property name="ellipsize">end</property>
+                        <property name="xalign">0</property>
                       </object>
-                      <packing>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
-                        <property name="position">1</property>
-                      </packing>
                     </child>
                     <child>
-                      <object class="GtkHBox" id="hbox13">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="spacing">3</property>
-                        <child>
-                          <object class="GtkToggleButton" id="streamMuteToggleButton">
-                            <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="relief">none</property>
-                            <child>
-                              <object class="GtkImage" id="image1">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="icon_name">audio-volume-muted</property>
-                                <property name="icon_size">1</property>
-                              </object>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkToggleButton" id="streamLockToggleButton">
-                            <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="relief">none</property>
-                            <property name="active">True</property>
-                            <child>
-                              <object class="GtkImage" id="image3">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="icon_name">changes-prevent</property>
-                                <property name="icon_size">1</property>
-                              </object>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
+                      <object class="GtkLabel" id="directionLabel">
+                        <property name="margin_start">4</property>
+                        <property name="margin_end">4</property>
+                        <property name="label" translatable="1">direction</property>
+                        <property name="use_markup">1</property>
+                        <property name="xalign">0</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkComboBoxText" id="deviceComboBox">
+                        <property name="halign">GTK_ALIGN_END</property>
+                        <property name="hexpand">1</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">0</property>
-                  </packing>
                 </child>
                 <child>
-                  <object class="GtkVBox" id="streamChannelsVBox">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="spacing">6</property>
+                  <object class="GtkBox" id="hbox13">
+                    <property name="spacing">3</property>
                     <child>
-                      <placeholder/>
+                      <object class="GtkToggleButton" id="streamMuteToggleButton">
+                        <property name="halign">center</property>
+                        <property name="focusable">1</property>
+                        <property name="tooltip_text" translatable="1">Mute audio</property>
+                        <property name="has-frame">0</property>
+                        <child>
+                          <object class="GtkImage" id="image1">
+                            <property name="icon_name">audio-volume-muted</property>
+                            <property name="icon_size">normal</property>
+                          </object>
+                        </child>
+                      </object>
                     </child>
                     <child>
-                      <placeholder/>
+                      <object class="GtkToggleButton" id="streamLockToggleButton">
+                        <property name="halign">center</property>
+                        <property name="focusable">1</property>
+                        <property name="tooltip_text" translatable="1">Lock channels together</property>
+                        <property name="has-frame">0</property>
+                        <property name="active">1</property>
+                        <child>
+                          <object class="GtkImage" id="image3">
+                            <property name="icon_name">changes-prevent</property>
+                            <property name="icon_size">normal</property>
+                          </object>
+                        </child>
+                      </object>
                     </child>
                   </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">1</property>
-                  </packing>
                 </child>
               </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
             </child>
             <child>
-              <object class="GtkHSeparator" id="hseparator8">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
+              <object class="GtkBox" id="streamChannelsVBox">
+                <property name="valign">center</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">6</property>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
               </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">1</property>
-              </packing>
             </child>
           </object>
         </child>
+        <child>
+          <object class="GtkSeparator" id="hseparator8">
+            <property name="valign">center</property>
+          </object>
+        </child>
       </object>
-    </child>
+    </property>
   </object>
 </interface>
diff --git a/src/pavucontrol.h b/src/pavucontrol.h
index c8696e6..e6282d7 100644
--- a/src/pavucontrol.h
+++ b/src/pavucontrol.h
@@ -29,6 +29,7 @@
 #include <libintl.h>
 
 #include <gtkmm.h>
+#include <gtkmm/buildable.h>
 
 #include <pulse/pulseaudio.h>
 #include <pulse/glib-mainloop.h>
@@ -74,7 +75,7 @@ enum SourceType {
 #include "mainwindow.h"
 
 pa_context* get_context(void);
-void show_error(const char *txt);
+void show_error(Gtk::Widget *w, const char *txt);
 
 MainWindow* pavucontrol_get_window(pa_glib_mainloop *m, bool maximize, bool retry, int tab_number);
 
diff --git a/src/rolewidget.cc b/src/rolewidget.cc
index 7f755aa..cff0880 100644
--- a/src/rolewidget.cc
+++ b/src/rolewidget.cc
@@ -39,15 +39,11 @@ RoleWidget::RoleWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
 RoleWidget* RoleWidget::create() {
     RoleWidget* w;
     Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create_from_file(GLADE_FILE, "streamWidget");
-    x->get_widget_derived("streamWidget", w);
+    w = Gtk::Builder::get_widget_derived<RoleWidget>(x, "streamWidget");
     w->reference();
     return w;
 }
 
-bool RoleWidget::onContextTriggerEvent(GdkEventButton*) {
-    return false;
-}
-
 void RoleWidget::onMuteToggleButton() {
     StreamWidget::onMuteToggleButton();
 
@@ -69,7 +65,7 @@ void RoleWidget::executeVolumeUpdate() {
 
     pa_operation* o;
     if (!(o = pa_ext_stream_restore_write(get_context(), PA_UPDATE_REPLACE, &info, 1, TRUE, NULL, NULL))) {
-        show_error(_("pa_ext_stream_restore_write() failed"));
+        show_error(this, _("pa_ext_stream_restore_write() failed"));
         return;
     }
 
diff --git a/src/rolewidget.h b/src/rolewidget.h
index 1d008f2..3dc2861 100644
--- a/src/rolewidget.h
+++ b/src/rolewidget.h
@@ -35,7 +35,6 @@ public:
 
     virtual void onMuteToggleButton();
     virtual void executeVolumeUpdate();
-    virtual bool onContextTriggerEvent(GdkEventButton*);
 };
 
 #endif
diff --git a/src/sinkinputwidget.cc b/src/sinkinputwidget.cc
index ff086d6..732205f 100644
--- a/src/sinkinputwidget.cc
+++ b/src/sinkinputwidget.cc
@@ -35,13 +35,13 @@ SinkInputWidget::SinkInputWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk
     directionLabel->set_label(txt = g_markup_printf_escaped("<i>%s</i>", _("on")));
     g_free(txt);
 
-    terminate.set_label(_("Terminate Playback"));
+    addKillMenu(_("Terminate Playback"));
 }
 
 SinkInputWidget* SinkInputWidget::create(MainWindow* mainWindow) {
     SinkInputWidget* w;
     Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create_from_file(GLADE_FILE, "streamWidget");
-    x->get_widget_derived("streamWidget", w);
+    w = Gtk::Builder::get_widget_derived<SinkInputWidget>(x, "streamWidget");
     w->init(mainWindow);
     w->reference();
 
@@ -84,7 +84,7 @@ void SinkInputWidget::executeVolumeUpdate() {
     pa_operation* o;
 
     if (!(o = pa_context_set_sink_input_volume(get_context(), index, &volume, NULL, NULL))) {
-        show_error(_("pa_context_set_sink_input_volume() failed"));
+        show_error(this, _("pa_context_set_sink_input_volume() failed"));
         return;
     }
 
@@ -99,17 +99,17 @@ void SinkInputWidget::onMuteToggleButton() {
 
     pa_operation* o;
     if (!(o = pa_context_set_sink_input_mute(get_context(), index, muteToggleButton->get_active(), NULL, NULL))) {
-        show_error(_("pa_context_set_sink_input_mute() failed"));
+        show_error(this, _("pa_context_set_sink_input_mute() failed"));
         return;
     }
 
     pa_operation_unref(o);
 }
 
-void SinkInputWidget::onKill() {
+void SinkInputWidget::onKill(const Glib::VariantBase& parameter) {
     pa_operation* o;
     if (!(o = pa_context_kill_sink_input(get_context(), index, NULL, NULL))) {
-        show_error(_("pa_context_kill_sink_input() failed"));
+        show_error(this, _("pa_context_kill_sink_input() failed"));
         return;
     }
 
diff --git a/src/sinkinputwidget.h b/src/sinkinputwidget.h
index af40d03..acd8cc1 100644
--- a/src/sinkinputwidget.h
+++ b/src/sinkinputwidget.h
@@ -41,7 +41,7 @@ public:
     void updateDeviceComboBox();
     virtual void executeVolumeUpdate();
     virtual void onMuteToggleButton();
-    virtual void onKill();
+    virtual void onKill(const Glib::VariantBase& parameter);
     virtual void onDeviceComboBoxChanged();
 
 private:
diff --git a/src/sinkwidget.cc b/src/sinkwidget.cc
index f30bd37..1cbc1c3 100644
--- a/src/sinkwidget.cc
+++ b/src/sinkwidget.cc
@@ -24,7 +24,7 @@
 
 #include "sinkwidget.h"
 
-#include <canberra-gtk.h>
+#include <canberra.h>
 #if HAVE_EXT_DEVICE_RESTORE_API
 #  include <pulse/format.h>
 #  include <pulse/ext-device-restore.h>
@@ -37,35 +37,35 @@ SinkWidget::SinkWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
 #if HAVE_EXT_DEVICE_RESTORE_API
     uint8_t i = 0;
 
-    x->get_widget("encodingSelect", encodingSelect);
+    encodingSelect = x->get_widget<Gtk::Grid>("encodingSelect");
 
     encodings[i].encoding = PA_ENCODING_PCM;
-    x->get_widget("encodingFormatPCM", encodings[i].widget);
+    encodings[i].widget = x->get_widget<Gtk::CheckButton>("encodingFormatPCM");
     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 = x->get_widget<Gtk::CheckButton>("encodingFormatAC3");
     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 = x->get_widget<Gtk::CheckButton>("encodingFormatEAC3");
     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 = x->get_widget<Gtk::CheckButton>("encodingFormatMPEG");
     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 = x->get_widget<Gtk::CheckButton>("encodingFormatDTS");
     encodings[i].widget->signal_toggled().connect(sigc::mem_fun(*this, &SinkWidget::onEncodingsChange));
 
     ++i;
     encodings[i].encoding = PA_ENCODING_INVALID;
-    x->get_widget("encodingFormatAAC", encodings[i].widget);
+    encodings[i].widget = x->get_widget<Gtk::CheckButton>("encodingFormatAAC");
     encodings[i].widget->set_sensitive(false);
 #ifdef PA_ENCODING_MPEG2_AAC_IEC61937
     if (pa_context_get_server_protocol_version(get_context()) >= 28) {
@@ -76,7 +76,7 @@ SinkWidget::SinkWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
 #endif
     ++i;
     encodings[i].encoding = PA_ENCODING_INVALID;
-    x->get_widget("encodingFormatTRUEHD", encodings[i].widget);
+    encodings[i].widget = x->get_widget<Gtk::CheckButton>("encodingFormatTRUEHD");
     encodings[i].widget->set_sensitive(false);
 #ifdef PA_ENCODING_TRUEHD_IEC61937
     if (pa_context_get_server_protocol_version(get_context()) >= 33) {
@@ -87,7 +87,7 @@ SinkWidget::SinkWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
 #endif
     ++i;
     encodings[i].encoding = PA_ENCODING_INVALID;
-    x->get_widget("encodingFormatDTSHD", encodings[i].widget);
+    encodings[i].widget = x->get_widget<Gtk::CheckButton>("encodingFormatDTSHD");
     encodings[i].widget->set_sensitive(false);
 #ifdef PA_ENCODING_DTSHD_IEC61937
     if (pa_context_get_server_protocol_version(get_context()) >= 33) {
@@ -102,7 +102,7 @@ SinkWidget::SinkWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
 SinkWidget* SinkWidget::create(MainWindow* mainWindow) {
     SinkWidget* w;
     Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create_from_file(GLADE_FILE, "deviceWidget");
-    x->get_widget_derived("deviceWidget", w);
+    w = Gtk::Builder::get_widget_derived<SinkWidget>(x, "deviceWidget");
     w->init(mainWindow, "sink");
     w->reference();
     return w;
@@ -114,28 +114,29 @@ void SinkWidget::executeVolumeUpdate() {
     int playing = 0;
 
     if (!(o = pa_context_set_sink_volume_by_index(get_context(), index, &volume, NULL, NULL))) {
-        show_error(_("pa_context_set_sink_volume_by_index() failed"));
+        show_error(this, _("pa_context_set_sink_volume_by_index() failed"));
         return;
     }
 
     pa_operation_unref(o);
 
-    ca_context_playing(ca_gtk_context_get(), 2, &playing);
+    snprintf(dev, sizeof(dev), "%lu", (unsigned long) index);
+
+    ca_context_playing(mpMainWindow->canberraContext, 2, &playing);
     if (playing)
         return;
 
-    snprintf(dev, sizeof(dev), "%lu", (unsigned long) index);
-    ca_context_change_device(ca_gtk_context_get(), dev);
+    ca_context_change_device(mpMainWindow->canberraContext, dev);
 
-    ca_gtk_play_for_widget(GTK_WIDGET(gobj()),
-                           2,
-                           CA_PROP_EVENT_DESCRIPTION, _("Volume Control Feedback Sound"),
-                           CA_PROP_EVENT_ID, "audio-volume-change",
-                           CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
-                           CA_PROP_CANBERRA_ENABLE, "1",
-                           NULL);
+    ca_context_play(mpMainWindow->canberraContext,
+                     2,
+                     CA_PROP_EVENT_DESCRIPTION, _("Volume Control Feedback Sound"),
+                     CA_PROP_EVENT_ID, "audio-volume-change",
+                     CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
+                     CA_PROP_CANBERRA_ENABLE, "1",
+                     NULL);
 
-    ca_context_change_device(ca_gtk_context_get(), NULL);
+    ca_context_change_device(mpMainWindow->canberraContext, NULL);
 }
 
 void SinkWidget::onMuteToggleButton() {
@@ -146,7 +147,7 @@ void SinkWidget::onMuteToggleButton() {
 
     pa_operation* o;
     if (!(o = pa_context_set_sink_mute_by_index(get_context(), index, muteToggleButton->get_active(), NULL, NULL))) {
-        show_error(_("pa_context_set_sink_mute_by_index() failed"));
+        show_error(this, _("pa_context_set_sink_mute_by_index() failed"));
         return;
     }
 
@@ -160,7 +161,7 @@ void SinkWidget::onDefaultToggleButton() {
         return;
 
     if (!(o = pa_context_set_default_sink(get_context(), name.c_str(), NULL, NULL))) {
-        show_error(_("pa_context_set_default_sink() failed"));
+        show_error(this, _("pa_context_set_default_sink() failed"));
         return;
     }
     pa_operation_unref(o);
@@ -180,7 +181,7 @@ void SinkWidget::onPortChange() {
             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"));
+                show_error(this, _("pa_context_set_sink_port_by_index() failed"));
                 return;
             }
 
@@ -222,7 +223,7 @@ void SinkWidget::onEncodingsChange() {
     }
 
     if (!(o = pa_ext_device_restore_save_formats(get_context(), PA_DEVICE_TYPE_SINK, index, n_formats, formats, NULL, NULL))) {
-        show_error(_("pa_ext_device_restore_save_sink_formats() failed"));
+        show_error(this, _("pa_ext_device_restore_save_sink_formats() failed"));
         free(formats);
         return;
     }
diff --git a/src/sourceoutputwidget.cc b/src/sourceoutputwidget.cc
index 1c2e762..d164552 100644
--- a/src/sourceoutputwidget.cc
+++ b/src/sourceoutputwidget.cc
@@ -35,7 +35,7 @@ SourceOutputWidget::SourceOutputWidget(BaseObjectType* cobject, const Glib::RefP
     directionLabel->set_label(txt = g_markup_printf_escaped("<i>%s</i>", _("from")));
     g_free(txt);
 
-    terminate.set_label(_("Terminate Recording"));
+    addKillMenu(_("Terminate Recording"));
 
 #if !HAVE_SOURCE_OUTPUT_VOLUMES
     /* Source Outputs do not have volume controls in versions of PA < 1.0 */
@@ -47,7 +47,7 @@ SourceOutputWidget::SourceOutputWidget(BaseObjectType* cobject, const Glib::RefP
 SourceOutputWidget* SourceOutputWidget::create(MainWindow* mainWindow) {
     SourceOutputWidget* w;
     Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create_from_file(GLADE_FILE, "streamWidget");
-    x->get_widget_derived("streamWidget", w);
+    w = Gtk::Builder::get_widget_derived<SourceOutputWidget>(x, "streamWidget");
     w->init(mainWindow);
     w->reference();
     return w;
@@ -90,7 +90,7 @@ void SourceOutputWidget::executeVolumeUpdate() {
     pa_operation* o;
 
     if (!(o = pa_context_set_source_output_volume(get_context(), index, &volume, NULL, NULL))) {
-        show_error(_("pa_context_set_source_output_volume() failed"));
+        show_error(this, _("pa_context_set_source_output_volume() failed"));
         return;
     }
 
@@ -105,7 +105,7 @@ void SourceOutputWidget::onMuteToggleButton() {
 
     pa_operation* o;
     if (!(o = pa_context_set_source_output_mute(get_context(), index, muteToggleButton->get_active(), NULL, NULL))) {
-        show_error(_("pa_context_set_source_output_mute() failed"));
+        show_error(this, _("pa_context_set_source_output_mute() failed"));
         return;
     }
 
@@ -113,10 +113,10 @@ void SourceOutputWidget::onMuteToggleButton() {
 }
 #endif
 
-void SourceOutputWidget::onKill() {
+void SourceOutputWidget::onKill(const Glib::VariantBase& parameter) {
     pa_operation* o;
     if (!(o = pa_context_kill_source_output(get_context(), index, NULL, NULL))) {
-        show_error(_("pa_context_kill_source_output() failed"));
+        show_error(this, _("pa_context_kill_source_output() failed"));
         return;
     }
 
diff --git a/src/sourceoutputwidget.h b/src/sourceoutputwidget.h
index 5edd438..a670c65 100644
--- a/src/sourceoutputwidget.h
+++ b/src/sourceoutputwidget.h
@@ -43,7 +43,7 @@ public:
     virtual void executeVolumeUpdate();
     virtual void onMuteToggleButton();
 #endif
-    virtual void onKill();
+    virtual void onKill(const Glib::VariantBase& parameter);
     virtual void onDeviceComboBoxChanged();
 
 private:
diff --git a/src/sourcewidget.cc b/src/sourcewidget.cc
index fde5333..ebcf7fb 100644
--- a/src/sourcewidget.cc
+++ b/src/sourcewidget.cc
@@ -33,7 +33,7 @@ SourceWidget::SourceWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Buil
 SourceWidget* SourceWidget::create(MainWindow* mainWindow) {
     SourceWidget* w;
     Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create_from_file(GLADE_FILE, "deviceWidget");
-    x->get_widget_derived("deviceWidget", w);
+    w = Gtk::Builder::get_widget_derived<SourceWidget>(x, "deviceWidget");
     w->init(mainWindow, "source");
     w->reference();
     return w;
@@ -43,7 +43,7 @@ void SourceWidget::executeVolumeUpdate() {
     pa_operation* o;
 
     if (!(o = pa_context_set_source_volume_by_index(get_context(), index, &volume, NULL, NULL))) {
-        show_error(_("pa_context_set_source_volume_by_index() failed"));
+        show_error(this, _("pa_context_set_source_volume_by_index() failed"));
         return;
     }
 
@@ -58,7 +58,7 @@ void SourceWidget::onMuteToggleButton() {
 
     pa_operation* o;
     if (!(o = pa_context_set_source_mute_by_index(get_context(), index, muteToggleButton->get_active(), NULL, NULL))) {
-        show_error(_("pa_context_set_source_mute_by_index() failed"));
+        show_error(this, _("pa_context_set_source_mute_by_index() failed"));
         return;
     }
 
@@ -72,7 +72,7 @@ void SourceWidget::onDefaultToggleButton() {
         return;
 
     if (!(o = pa_context_set_default_source(get_context(), name.c_str(), NULL, NULL))) {
-        show_error(_("pa_context_set_default_source() failed"));
+        show_error(this, _("pa_context_set_default_source() failed"));
         return;
     }
     pa_operation_unref(o);
@@ -94,7 +94,7 @@ void SourceWidget::onPortChange() {
       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"));
+        show_error(this, _("pa_context_set_source_port_by_index() failed"));
         return;
       }
 
diff --git a/src/streamwidget.cc b/src/streamwidget.cc
index d203b20..499fbb2 100644
--- a/src/streamwidget.cc
+++ b/src/streamwidget.cc
@@ -34,26 +34,20 @@ StreamWidget::StreamWidget(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Buil
     mpMainWindow(NULL) {
 
     /* MinimalStreamWidget member variables. */
-    x->get_widget("streamChannelsVBox", channelsVBox);
-    x->get_widget("streamNameLabel", nameLabel);
-    x->get_widget("streamBoldNameLabel", boldNameLabel);
-    x->get_widget("streamIconImage", iconImage);
+    channelsVBox = x->get_widget<Gtk::Box>("streamChannelsVBox");
+    nameLabel = x->get_widget<Gtk::Label>("streamNameLabel");
+    boldNameLabel = x->get_widget<Gtk::Label>("streamBoldNameLabel");
+    iconImage = x->get_widget<Gtk::Image>("streamIconImage");
 
-    x->get_widget("streamLockToggleButton", lockToggleButton);
-    x->get_widget("streamMuteToggleButton", muteToggleButton);
-    x->get_widget("directionLabel", directionLabel);
-    x->get_widget("deviceComboBox", deviceComboBox);
+    lockToggleButton = x->get_widget<Gtk::ToggleButton>("streamLockToggleButton");
+    muteToggleButton = x->get_widget<Gtk::ToggleButton>("streamMuteToggleButton");
+    directionLabel = x->get_widget<Gtk::Label>("directionLabel");
+    deviceComboBox = x->get_widget<Gtk::ComboBoxText>("deviceComboBox");
 
-    this->signal_button_press_event().connect(sigc::mem_fun(*this, &StreamWidget::onContextTriggerEvent));
     muteToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &StreamWidget::onMuteToggleButton));
     lockToggleButton->signal_clicked().connect(sigc::mem_fun(*this, &StreamWidget::onLockToggleButton));
     deviceComboBox->signal_changed().connect(sigc::mem_fun(*this, &StreamWidget::onDeviceComboBoxChanged));
 
-    terminate.set_label(_("Terminate"));
-    terminate.signal_activate().connect(sigc::mem_fun(*this, &StreamWidget::onKill));
-    contextMenu.append(terminate);
-    contextMenu.show_all();
-
     for (unsigned i = 0; i < PA_CHANNELS_MAX; i++)
         channelWidgets[i] = NULL;
 }
@@ -64,12 +58,35 @@ void StreamWidget::init(MainWindow* mainWindow) {
     MinimalStreamWidget::init();
 }
 
-bool StreamWidget::onContextTriggerEvent(GdkEventButton* event) {
-    if (GDK_BUTTON_PRESS == event->type && 3 == event->button) {
-        contextMenu.popup_at_pointer((GdkEvent*)event);
-        return true;
+void StreamWidget::addKillMenu(const char* killLabel) {
+    auto gesture = Gtk::GestureClick::create();
+    gesture->set_button(3);
+    gesture->set_exclusive(true);
+    gesture->signal_pressed().connect(sigc::mem_fun(*this, &StreamWidget::onContextTriggerEvent));
+    this->add_controller(gesture);
+
+    const std::string actionName = "kill", groupName="streamwidget";
+    auto action = Gio::SimpleAction::create(actionName);
+    action->set_enabled(true);
+    action->signal_activate().connect(sigc::mem_fun(*this, &StreamWidget::onKill));
+
+    auto group = Gio::SimpleActionGroup::create();
+    group->add_action(action);
+
+    insert_action_group(groupName, group);
+
+    auto menuModel = Gio::Menu::create();
+    menuModel->append(killLabel, groupName + "." + actionName);
+    contextMenu.set_menu_model(menuModel);
+    contextMenu.set_parent(*this);
+}
+
+
+void StreamWidget::onContextTriggerEvent(gint n_press, gdouble x, gdouble y) {
+    if (n_press == 1) {
+        contextMenu.set_pointing_to(Gdk::Rectangle {(int) x, (int) y, 0 , 0});
+        contextMenu.popup();
     }
-    return false;
 }
 
 void StreamWidget::setChannelMap(const pa_channel_map &m, bool can_decibel) {
@@ -79,7 +96,7 @@ void StreamWidget::setChannelMap(const pa_channel_map &m, bool can_decibel) {
 
     for (int i = 0; i < m.channels; i++) {
         ChannelWidget *cw = channelWidgets[i];
-        channelsVBox->pack_start(*cw, false, false, 0);
+        channelsVBox->prepend(*cw);
         cw->unreference();
     }
 
@@ -144,7 +161,7 @@ bool StreamWidget::timeoutEvent() {
 void StreamWidget::executeVolumeUpdate() {
 }
 
-void StreamWidget::onKill() {
+void StreamWidget::onKill(const Glib::VariantBase& parameter) {
 }
 
 void StreamWidget::onDeviceComboBoxChanged() {
diff --git a/src/streamwidget.h b/src/streamwidget.h
index c1a79da..048fbb9 100644
--- a/src/streamwidget.h
+++ b/src/streamwidget.h
@@ -53,21 +53,21 @@ public:
 
     virtual void onMuteToggleButton();
     virtual void onLockToggleButton();
-    virtual bool onContextTriggerEvent(GdkEventButton*);
+    virtual void onContextTriggerEvent(gint n_press, gdouble x, gdouble y);
 
     sigc::connection timeoutConnection;
 
     bool timeoutEvent();
 
     virtual void executeVolumeUpdate();
-    virtual void onKill();
+    virtual void onKill(const Glib::VariantBase& parameter);
     virtual void onDeviceComboBoxChanged();
 
 protected:
     MainWindow* mpMainWindow;
 
-    Gtk::Menu contextMenu;
-    Gtk::MenuItem terminate;
+    Gtk::PopoverMenu contextMenu;
+    void addKillMenu(const char* killLabel);
 };
 
 #endif



More information about the pulseaudio-commits mailing list