gnome: add audio settings

Refs #71866

Change-Id: Ib71b99db9c5c415e49b5fba284cf82dc4a38b43d
diff --git a/src/models/gtkqsortfiltertreemodel.h b/src/models/gtkqsortfiltertreemodel.h
index baed911..3929e3d 100644
--- a/src/models/gtkqsortfiltertreemodel.h
+++ b/src/models/gtkqsortfiltertreemodel.h
@@ -47,11 +47,11 @@
 typedef struct _GtkQSortFilterTreeModel        GtkQSortFilterTreeModel;
 typedef struct _GtkQSortFilterTreeModelClass   GtkQSortFilterTreeModelClass;
 
-GType                  gtk_q_sort_filter_tree_model_get_type            (void) G_GNUC_CONST;
-GtkQSortFilterTreeModel         *gtk_q_sort_filter_tree_model_new                 (QSortFilterProxyModel *, size_t, ...);
-QSortFilterProxyModel *gtk_q_sort_filter_tree_model_get_qmodel          (GtkQSortFilterTreeModel *);
-QModelIndex            gtk_q_sort_filter_tree_model_get_source_idx      (GtkQSortFilterTreeModel *, GtkTreeIter *);
-gboolean               gtk_q_sort_filter_tree_model_source_index_to_iter(GtkQSortFilterTreeModel *, const QModelIndex &, GtkTreeIter *);
+GType                    gtk_q_sort_filter_tree_model_get_type            (void) G_GNUC_CONST;
+GtkQSortFilterTreeModel *gtk_q_sort_filter_tree_model_new                 (QSortFilterProxyModel *, size_t, ...);
+QSortFilterProxyModel   *gtk_q_sort_filter_tree_model_get_qmodel          (GtkQSortFilterTreeModel *);
+QModelIndex              gtk_q_sort_filter_tree_model_get_source_idx      (GtkQSortFilterTreeModel *, GtkTreeIter *);
+gboolean                 gtk_q_sort_filter_tree_model_source_index_to_iter(GtkQSortFilterTreeModel *, const QModelIndex &, GtkTreeIter *);
 
 G_END_DECLS
 
diff --git a/src/models/gtkqtreemodel.cpp b/src/models/gtkqtreemodel.cpp
index 60fd90d..4b86bcf 100644
--- a/src/models/gtkqtreemodel.cpp
+++ b/src/models/gtkqtreemodel.cpp
@@ -420,6 +420,46 @@
         }
     );
 
+//     QObject::connect(
+//         proxy_model,
+//         &QAbstractItemModel::layoutAboutToBeChanged,
+//         [=] () {
+//             // g_debug("layout about to be changed");
+//             /* nothing equvivalent eixists in GtkTreeModel, so simply delete all
+//              * rows, and add all rows when the model is reset;
+//              * we must delete the rows in ascending order */
+//             int row_count = proxy_model->rowCount();
+//             for (int row = row_count; row > 0; --row) {
+//                 // g_debug("deleting row %d", row -1);
+//                 QModelIndex idx = proxy_model->index(row - 1, 0);
+//                 GtkTreeIter iter;
+//                 iter.stamp = stamp;
+//                 qmodelindex_to_iter(idx, &iter);
+//                 GtkTreePath *path = gtk_q_tree_model_get_path(GTK_TREE_MODEL(retval), &iter);
+//                 gtk_tree_model_row_deleted(GTK_TREE_MODEL(retval), path);
+//             }
+//         }
+//     );
+//
+//     QObject::connect(
+//         proxy_model,
+//         &QAbstractItemModel::layoutChanged,
+//         [=] () {
+//             // g_debug("layout changed");
+//             /* now add all the (new) rows */
+//             int row_count = proxy_model->rowCount();
+//             for (int row = 0; row < row_count; row++) {
+//                 // g_debug("adding row %d", row);
+//                 GtkTreeIter *iter_new = g_new0(GtkTreeIter, 1);
+//                 QModelIndex idx = proxy_model->index(row, 0);
+//                 iter_new->stamp = stamp;
+//                 qmodelindex_to_iter(idx, iter_new);
+//                 GtkTreePath *path_new = gtk_q_tree_model_get_path(GTK_TREE_MODEL(retval), iter_new);
+//                 gtk_tree_model_row_inserted(GTK_TREE_MODEL(retval), path_new, iter_new);
+//             }
+//         }
+//     );
+
     return retval;
 }
 
diff --git a/src/ringmainwindow.cpp b/src/ringmainwindow.cpp
index 6375855..8e7bf5f 100644
--- a/src/ringmainwindow.cpp
+++ b/src/ringmainwindow.cpp
@@ -63,7 +63,7 @@
 #define CREATE_ACCOUNT_2_VIEW_NAME "create2"
 #define GENERAL_SETTINGS_VIEW_NAME "general"
 #define AUDIO_SETTINGS_VIEW_NAME "audio"
-#define VIDEO_SETTINGS_VIEW_NAME "video"
+#define MEDIA_SETTINGS_VIEW_NAME "media"
 #define ACCOUNT_SETTINGS_VIEW_NAME "accounts"
 #define DEFAULT_VIEW_NAME "placeholder"
 #define VIEW_CONTACTS "contacts"
@@ -103,9 +103,8 @@
     GtkWidget *account_settings_view;
     GtkWidget *video_settings_view;
     GtkWidget *last_settings_view;
-    GtkWidget *radiobutton_audio_settings;
     GtkWidget *radiobutton_general_settings;
-    GtkWidget *radiobutton_video_settings;
+    GtkWidget *radiobutton_media_settings;
     GtkWidget *radiobutton_account_settings;
     GtkWidget *label_ring_id;
 
@@ -443,7 +442,7 @@
 }
 
 static void
-show_video_settings(GtkToggleButton *navbutton, RingMainWindow *win)
+show_media_settings(GtkToggleButton *navbutton, RingMainWindow *win)
 {
     g_return_if_fail(IS_RING_MAIN_WINDOW(win));
     RingMainWindowPrivate *priv = RING_MAIN_WINDOW_GET_PRIVATE(win);
@@ -451,7 +450,7 @@
     if (gtk_toggle_button_get_active(navbutton)) {
         video_settings_show_preview(VIDEO_SETTINGS_VIEW(priv->video_settings_view), TRUE);
         gtk_stack_set_transition_type(GTK_STACK(priv->stack_main_view), GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT);
-        gtk_stack_set_visible_child_name(GTK_STACK(priv->stack_main_view), VIDEO_SETTINGS_VIEW_NAME);
+        gtk_stack_set_visible_child_name(GTK_STACK(priv->stack_main_view), MEDIA_SETTINGS_VIEW_NAME);
         priv->last_settings_view = priv->video_settings_view;
     } else {
         video_settings_show_preview(VIDEO_SETTINGS_VIEW(priv->video_settings_view), FALSE);
@@ -944,14 +943,14 @@
     gtk_stack_add_named(GTK_STACK(priv->stack_main_view), priv->account_settings_view, ACCOUNT_SETTINGS_VIEW_NAME);
 
     priv->video_settings_view = video_settings_view_new();
-    gtk_stack_add_named(GTK_STACK(priv->stack_main_view), priv->video_settings_view, VIDEO_SETTINGS_VIEW_NAME);
+    gtk_stack_add_named(GTK_STACK(priv->stack_main_view), priv->video_settings_view, MEDIA_SETTINGS_VIEW_NAME);
 
     /* make the setting we will show first the active one */
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->radiobutton_video_settings), TRUE);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->radiobutton_media_settings), TRUE);
     priv->last_settings_view = priv->video_settings_view;
 
     /* connect the settings button signals to switch settings views */
-    g_signal_connect(priv->radiobutton_video_settings, "toggled", G_CALLBACK(show_video_settings), win);
+    g_signal_connect(priv->radiobutton_media_settings, "toggled", G_CALLBACK(show_media_settings), win);
     g_signal_connect(priv->radiobutton_account_settings, "toggled", G_CALLBACK(show_account_settings), win);
 
     /* call model */
@@ -1211,9 +1210,8 @@
     gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), RingMainWindow, vbox_call_view);
     gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), RingMainWindow, stack_call_view);
     gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), RingMainWindow, button_placecall);
-    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), RingMainWindow, radiobutton_audio_settings);
     gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), RingMainWindow, radiobutton_general_settings);
-    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), RingMainWindow, radiobutton_video_settings);
+    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), RingMainWindow, radiobutton_media_settings);
     gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), RingMainWindow, radiobutton_account_settings);
     gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), RingMainWindow, label_ring_id);
 
diff --git a/src/videosettingsview.cpp b/src/videosettingsview.cpp
index 2048e62..336caf5 100644
--- a/src/videosettingsview.cpp
+++ b/src/videosettingsview.cpp
@@ -36,6 +36,12 @@
 #include <video/previewmanager.h>
 #include <video/configurationproxy.h>
 #include <QtCore/QItemSelectionModel>
+#include <audio/settings.h>
+#include <audio/managermodel.h>
+#include <audio/alsapluginmodel.h>
+#include <audio/outputdevicemodel.h>
+#include <audio/inputdevicemodel.h>
+#include <audio/ringtonedevicemodel.h>
 
 struct _VideoSettingsView
 {
@@ -51,12 +57,23 @@
 
 struct _VideoSettingsViewPrivate
 {
+    /* audio settings */
+    GtkWidget *combobox_manager;
+    GtkWidget *combobox_ringtone;
+    GtkWidget *combobox_output;
+    GtkWidget *combobox_input;
+
+    QMetaObject::Connection manager_selection;
+    QMetaObject::Connection ringtone_selection;
+    QMetaObject::Connection output_selection;
+    QMetaObject::Connection input_selection;
+
+    /* camera settings */
     GtkWidget *combobox_device;
     GtkWidget *combobox_channel;
     GtkWidget *combobox_resolution;
     GtkWidget *combobox_framerate;
-    GtkWidget *button_startstop;
-    GtkWidget *vbox_camera_preview;
+    GtkWidget *hbox_camera;
     GtkWidget *video_widget;
 
     /* this is used to keep track of the state of the preview when the settings
@@ -82,6 +99,17 @@
     VideoSettingsView *view = VIDEO_SETTINGS_VIEW(object);
     VideoSettingsViewPrivate *priv = VIDEO_SETTINGS_VIEW_GET_PRIVATE(view);
 
+    /* make sure to stop the preview if this view is getting destroyed */
+    if (priv->video_started_by_settings) {
+        Video::PreviewManager::instance()->stopPreview();
+        priv->video_started_by_settings = FALSE;
+    }
+
+    QObject::disconnect(priv->manager_selection);
+    QObject::disconnect(priv->ringtone_selection);
+    QObject::disconnect(priv->output_selection);
+    QObject::disconnect(priv->input_selection);
+
     QObject::disconnect(priv->local_renderer_connection);
     QObject::disconnect(priv->device_selection);
     QObject::disconnect(priv->channel_selection);
@@ -135,7 +163,7 @@
             if (current.isValid()) {
                 GtkTreeIter new_iter;
                 GtkTreeModel *model = gtk_combo_box_get_model(box);
-                g_return_if_fail(model != NULL);
+                g_return_if_fail(model);
                 if (gtk_q_tree_model_source_index_to_iter(GTK_Q_TREE_MODEL(model), current, &new_iter)) {
                     gtk_combo_box_set_active_iter(box, &new_iter);
                 } else {
@@ -179,6 +207,27 @@
     priv->rate_selection = connect_combo_box_qmodel(GTK_COMBO_BOX(priv->combobox_framerate),
                                                     Video::ConfigurationProxy::rateModel(),
                                                     Video::ConfigurationProxy::rateSelectionModel());
+
+    /* audio settings */
+    /* instantiate all the models before the manager model first */
+    Audio::Settings::instance()->alsaPluginModel();
+    Audio::Settings::instance()->ringtoneDeviceModel();
+    Audio::Settings::instance()->inputDeviceModel();
+    Audio::Settings::instance()->outputDeviceModel();
+    priv->manager_selection = connect_combo_box_qmodel(GTK_COMBO_BOX(priv->combobox_manager),
+                                                       Audio::Settings::instance()->managerModel(),
+                                                       Audio::Settings::instance()->managerModel()->selectionModel());
+    priv->ringtone_selection = connect_combo_box_qmodel(GTK_COMBO_BOX(priv->combobox_ringtone),
+                                                        Audio::Settings::instance()->ringtoneDeviceModel(),
+                                                        Audio::Settings::instance()->ringtoneDeviceModel()->selectionModel());
+    priv->input_selection = connect_combo_box_qmodel(GTK_COMBO_BOX(priv->combobox_input),
+                                                     Audio::Settings::instance()->inputDeviceModel(),
+                                                     Audio::Settings::instance()->inputDeviceModel()->selectionModel());
+    priv->output_selection = connect_combo_box_qmodel(GTK_COMBO_BOX(priv->combobox_output),
+                                                      Audio::Settings::instance()->outputDeviceModel(),
+                                                      Audio::Settings::instance()->outputDeviceModel()->selectionModel());
+
+
 }
 
 static void
@@ -189,11 +238,15 @@
     gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
                                                 "/cx/ring/RingGnome/videosettingsview.ui");
 
+    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), VideoSettingsView, combobox_manager);
+    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), VideoSettingsView, combobox_ringtone);
+    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), VideoSettingsView, combobox_output);
+    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), VideoSettingsView, combobox_input);
     gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), VideoSettingsView, combobox_device);
     gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), VideoSettingsView, combobox_channel);
     gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), VideoSettingsView, combobox_resolution);
     gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), VideoSettingsView, combobox_framerate);
-    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), VideoSettingsView, vbox_camera_preview);
+    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), VideoSettingsView, hbox_camera);
 }
 
 GtkWidget *
@@ -220,7 +273,7 @@
         /* put video widget in */
         priv->video_widget = video_widget_new();
         gtk_widget_show_all(priv->video_widget);
-        gtk_box_pack_start(GTK_BOX(priv->vbox_camera_preview), priv->video_widget, TRUE, TRUE, 0);
+        gtk_box_pack_start(GTK_BOX(priv->hbox_camera), priv->video_widget, TRUE, TRUE, 0);
 
         if (Video::PreviewManager::instance()->isPreviewing()) {
             priv->video_started_by_settings = FALSE;
@@ -250,7 +303,7 @@
         }
 
         if (priv->video_widget && IS_VIDEO_WIDGET(priv->video_widget))
-            gtk_container_remove(GTK_CONTAINER(priv->vbox_camera_preview), priv->video_widget);
+            gtk_container_remove(GTK_CONTAINER(priv->hbox_camera), priv->video_widget);
         priv->video_widget = NULL;
     }