gnome: rename video settings to media settings
Audio and video settings are now in the same panel.
Refs #71866
Change-Id: I5e9906b42a1160f985578438d363706c7d399548
diff --git a/src/mediasettingsview.cpp b/src/mediasettingsview.cpp
new file mode 100644
index 0000000..c216462
--- /dev/null
+++ b/src/mediasettingsview.cpp
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2015 Savoir-Faire Linux Inc.
+ * Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Additional permission under GNU GPL version 3 section 7:
+ *
+ * If you modify this program, or any covered work, by linking or
+ * combining it with the OpenSSL project's OpenSSL library (or a
+ * modified version of that library), containing parts covered by the
+ * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ * grants you additional permission to convey the resulting work.
+ * Corresponding Source for a non-source form of such a combination
+ * shall include the source code for the parts of OpenSSL used as well
+ * as that of the covered work.
+ */
+
+#include "mediasettingsview.h"
+
+#include <gtk/gtk.h>
+#include "models/gtkqtreemodel.h"
+#include "video/video_widget.h"
+#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 _MediaSettingsView
+{
+ GtkBox parent;
+};
+
+struct _MediaSettingsViewClass
+{
+ GtkBoxClass parent_class;
+};
+
+typedef struct _MediaSettingsViewPrivate MediaSettingsViewPrivate;
+
+struct _MediaSettingsViewPrivate
+{
+ /* 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 *hbox_camera;
+ GtkWidget *video_widget;
+
+ /* this is used to keep track of the state of the preview when the settings
+ * are opened; if a call is in progress, then the preview should already be
+ * started and we don't want to stop it when the settings are closed, in this
+ * case */
+ gboolean video_started_by_settings;
+
+ QMetaObject::Connection local_renderer_connection;
+ QMetaObject::Connection device_selection;
+ QMetaObject::Connection channel_selection;
+ QMetaObject::Connection resolution_selection;
+ QMetaObject::Connection rate_selection;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE(MediaSettingsView, media_settings_view, GTK_TYPE_BOX);
+
+#define MEDIA_SETTINGS_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), MEDIA_SETTINGS_VIEW_TYPE, MediaSettingsViewPrivate))
+
+static void
+media_settings_view_dispose(GObject *object)
+{
+ MediaSettingsView *view = MEDIA_SETTINGS_VIEW(object);
+ MediaSettingsViewPrivate *priv = MEDIA_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);
+ QObject::disconnect(priv->resolution_selection);
+ QObject::disconnect(priv->rate_selection);
+
+ G_OBJECT_CLASS(media_settings_view_parent_class)->dispose(object);
+}
+
+static QModelIndex
+get_index_from_combobox(GtkComboBox *box)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model = gtk_combo_box_get_model(box);
+ if (gtk_combo_box_get_active_iter(box, &iter)) {
+ return gtk_q_tree_model_get_source_idx(GTK_Q_TREE_MODEL(model), &iter);
+ } else {
+ return QModelIndex();
+ }
+}
+
+static void
+update_selection(GtkComboBox *box, QItemSelectionModel *selection_model)
+{
+ QModelIndex idx = get_index_from_combobox(box);
+ if (idx.isValid())
+ selection_model->setCurrentIndex(idx, QItemSelectionModel::ClearAndSelect);
+}
+
+static QMetaObject::Connection
+connect_combo_box_qmodel(GtkComboBox *box, QAbstractItemModel *qmodel, QItemSelectionModel *selection_model)
+{
+ QMetaObject::Connection connection;
+ GtkCellRenderer *renderer;
+ GtkQTreeModel *model = gtk_q_tree_model_new(qmodel,
+ 1,
+ Qt::DisplayRole, G_TYPE_STRING);
+
+ gtk_combo_box_set_model(box, GTK_TREE_MODEL(model));
+ renderer = gtk_cell_renderer_text_new();
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(box), renderer, FALSE);
+ gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(box), renderer,
+ "text", 0, NULL);
+
+ /* connect signals to and from the selection model */
+ connection = QObject::connect(
+ selection_model,
+ &QItemSelectionModel::currentChanged,
+ [=](const QModelIndex & current, G_GNUC_UNUSED const QModelIndex & previous) {
+ /* select the current */
+ if (current.isValid()) {
+ GtkTreeIter new_iter;
+ GtkTreeModel *model = gtk_combo_box_get_model(box);
+ 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 {
+ g_warning("SelectionModel changed to invalid QModelIndex?");
+ }
+ }
+ }
+ );
+ g_signal_connect(box,
+ "changed",
+ G_CALLBACK(update_selection),
+ selection_model);
+
+ /* sync the initial selection */
+ QModelIndex idx = selection_model->currentIndex();
+ if (idx.isValid()) {
+ GtkTreeIter iter;
+ if (gtk_q_tree_model_source_index_to_iter(model, idx, &iter))
+ gtk_combo_box_set_active_iter(box, &iter);
+ }
+
+ return connection;
+}
+
+static void
+media_settings_view_init(MediaSettingsView *view)
+{
+ gtk_widget_init_template(GTK_WIDGET(view));
+
+ MediaSettingsViewPrivate *priv = MEDIA_SETTINGS_VIEW_GET_PRIVATE(view);
+
+ priv->device_selection = connect_combo_box_qmodel(GTK_COMBO_BOX(priv->combobox_device),
+ Video::ConfigurationProxy::deviceModel(),
+ Video::ConfigurationProxy::deviceSelectionModel());
+ priv->channel_selection = connect_combo_box_qmodel(GTK_COMBO_BOX(priv->combobox_channel),
+ Video::ConfigurationProxy::channelModel(),
+ Video::ConfigurationProxy::channelSelectionModel());
+ priv->resolution_selection = connect_combo_box_qmodel(GTK_COMBO_BOX(priv->combobox_resolution),
+ Video::ConfigurationProxy::resolutionModel(),
+ Video::ConfigurationProxy::resolutionSelectionModel());
+ 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
+media_settings_view_class_init(MediaSettingsViewClass *klass)
+{
+ G_OBJECT_CLASS(klass)->dispose = media_settings_view_dispose;
+
+ gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
+ "/cx/ring/RingGnome/mediasettingsview.ui");
+
+ gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), MediaSettingsView, combobox_manager);
+ gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), MediaSettingsView, combobox_ringtone);
+ gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), MediaSettingsView, combobox_output);
+ gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), MediaSettingsView, combobox_input);
+ gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), MediaSettingsView, combobox_device);
+ gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), MediaSettingsView, combobox_channel);
+ gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), MediaSettingsView, combobox_resolution);
+ gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), MediaSettingsView, combobox_framerate);
+ gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), MediaSettingsView, hbox_camera);
+}
+
+GtkWidget *
+media_settings_view_new()
+{
+ gpointer view = g_object_new(MEDIA_SETTINGS_VIEW_TYPE, NULL);
+
+ return (GtkWidget *)view;
+}
+
+void
+media_settings_view_show_preview(MediaSettingsView *self, gboolean show_preview)
+{
+ g_return_if_fail(IS_MEDIA_SETTINGS_VIEW(self));
+ MediaSettingsViewPrivate *priv = MEDIA_SETTINGS_VIEW_GET_PRIVATE(self);
+
+ /* if TRUE, create a VideoWidget, then check if the preview has already been
+ * started (because a call was in progress); if not, then start it.
+ * if FALSE, check if the preview was started by this function, if so
+ * then stop the preview; then destroy the VideoWidget to make sure we don't
+ * get useless frame updates */
+
+ if (show_preview) {
+ /* put video widget in */
+ priv->video_widget = video_widget_new();
+ gtk_widget_show_all(priv->video_widget);
+ 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;
+
+ /* local renderer, but set as "remote" so that it takes up the whole screen */
+ video_widget_push_new_renderer(VIDEO_WIDGET(priv->video_widget),
+ Video::PreviewManager::instance()->previewRenderer(),
+ VIDEO_RENDERER_REMOTE);
+ } else {
+ priv->video_started_by_settings = TRUE;
+ priv->local_renderer_connection = QObject::connect(
+ Video::PreviewManager::instance(),
+ &Video::PreviewManager::previewStarted,
+ [=](Video::Renderer *renderer) {
+ video_widget_push_new_renderer(VIDEO_WIDGET(priv->video_widget),
+ renderer,
+ VIDEO_RENDERER_REMOTE);
+ }
+ );
+ Video::PreviewManager::instance()->startPreview();
+ }
+ } else {
+ if (priv->video_started_by_settings) {
+ Video::PreviewManager::instance()->stopPreview();
+ QObject::disconnect(priv->local_renderer_connection);
+ priv->video_started_by_settings = FALSE;
+ }
+
+ if (priv->video_widget && IS_VIDEO_WIDGET(priv->video_widget))
+ gtk_container_remove(GTK_CONTAINER(priv->hbox_camera), priv->video_widget);
+ priv->video_widget = NULL;
+ }
+
+}