/* gm_audio-profile-choose.c: combo box to choose a specific profile */ /* * Copyright (C) 2003 Thomas Vander Stichele * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include "gmp-util.h" #include "audio-profile-choose.h" /* Private structure */ struct _GMAudioProfileChoosePrivate { GtkTreeModel *model; GMAudioProfile *profile; }; enum { P_0, P_ACTIVE_PROFILE }; enum { S_PROFILE_CHANGED, LAST_SIGNAL }; enum { NAME_COLUMN, ID_COLUMN, PROFILE_COLUMN, N_COLUMNS }; static guint signals[LAST_SIGNAL] = { 0 }; /* GObject methods */ static void gm_audio_profile_choose_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void gm_audio_profile_choose_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void gm_audio_profile_choose_dispose (GObject *object); /* GtkComboBox methods */ static void gm_audio_profile_choose_changed (GtkComboBox *combo); /* Internal routines */ static void audio_profile_forgotten (GMAudioProfile *profile, GMAudioProfileChoose *choose); G_DEFINE_TYPE (GMAudioProfileChoose, gm_audio_profile_choose, GTK_TYPE_COMBO_BOX) /* Initialization */ static void gm_audio_profile_choose_init (GMAudioProfileChoose *choose) { GMAudioProfileChoosePrivate *priv; GtkListStore *store; GList *orig, *profiles; GtkCellRenderer *cell; priv = G_TYPE_INSTANCE_GET_PRIVATE (choose, GM_AUDIO_TYPE_PROFILE_CHOOSE, GMAudioProfileChoosePrivate); /* Create model */ store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, GM_AUDIO_TYPE_PROFILE); for (orig = profiles = gm_audio_profile_get_active_list (); profiles; profiles = g_list_next (profiles)) { GMAudioProfile *profile = profiles->data; gchar *profile_name, *temp_file_name, *mime_type_description; GtkTreeIter iter; temp_file_name = g_strdup_printf (".%s", gm_audio_profile_get_extension (profile)); mime_type_description = g_content_type_get_description (temp_file_name); g_free (temp_file_name); profile_name = g_strdup_printf (gettext ("%s (%s)"), gm_audio_profile_get_name (profile), mime_type_description); g_free (mime_type_description); gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, NAME_COLUMN, profile_name, ID_COLUMN, gm_audio_profile_get_id (profile), PROFILE_COLUMN, profile, -1); g_signal_connect (profile, "forgotten", G_CALLBACK (audio_profile_forgotten), choose); g_free (profile_name); } g_list_free (orig); /* Display name in the combo */ cell = gtk_cell_renderer_text_new (); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (choose), cell, TRUE ); gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (choose), cell, "text", NAME_COLUMN); gtk_combo_box_set_model (GTK_COMBO_BOX (choose), GTK_TREE_MODEL (store)); g_object_unref (store); /* Populate private struct */ priv->model = GTK_TREE_MODEL (store); priv->profile = NULL; /* cache access to private data */ choose->priv = priv; } static void gm_audio_profile_choose_class_init (GMAudioProfileChooseClass *klass) { GObjectClass *g_class = G_OBJECT_CLASS (klass); GtkComboBoxClass *c_class = GTK_COMBO_BOX_CLASS (klass); GParamSpec *pspec; g_class->get_property = gm_audio_profile_choose_get_property; g_class->set_property = gm_audio_profile_choose_set_property; g_class->dispose = gm_audio_profile_choose_dispose; c_class->changed = gm_audio_profile_choose_changed; /* Signals */ /** * GMAudioProfileChoose::profile-changed: * @choose: the object which received the signal * * The profile-changed signal is emitted when the active profile is changed. * * Since: 2.32/3.0 */ signals[S_PROFILE_CHANGED] = g_signal_new (g_intern_static_string ("profile-changed"), G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GMAudioProfileChooseClass, profile_changed), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GM_AUDIO_TYPE_PROFILE); /* Properties */ /** * GMAudioProfileChoose:active-profile: * * Currently shown #GMAudioProfile. * * Since: 2.32/3.0 */ pspec = g_param_spec_object ("active-profile", "Active profile", "Currently selected GMAudioProfile", GM_AUDIO_TYPE_PROFILE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (g_class, P_ACTIVE_PROFILE, pspec); /* Add private data */ g_type_class_add_private (g_class, sizeof (GMAudioProfileChoose)); } static void gm_audio_profile_choose_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { switch (prop_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gm_audio_profile_choose_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GMAudioProfileChoosePrivate *priv = GM_AUDIO_PROFILE_CHOOSE (object)->priv; switch (prop_id) { case P_ACTIVE_PROFILE: g_value_set_object (value, priv->profile); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void gm_audio_profile_choose_dispose (GObject *object) { GMAudioProfileChoosePrivate *priv = GM_AUDIO_PROFILE_CHOOSE (object)->priv; if (priv->profile) { g_object_unref (priv->profile); priv->profile = NULL; } G_OBJECT_CLASS (gm_audio_profile_choose_parent_class)->dispose (object); } static void gm_audio_profile_choose_changed (GtkComboBox *combo) { GMAudioProfileChoosePrivate *priv; GtkTreeIter iter; GMAudioProfile *new_profile = NULL; priv = GM_AUDIO_PROFILE_CHOOSE (combo)->priv; if (gtk_combo_box_get_active_iter (combo, &iter)) gtk_tree_model_get (priv->model, &iter, PROFILE_COLUMN, &new_profile, -1); if (priv->profile != new_profile) { if (priv->profile) g_object_unref (priv->profile); priv->profile = new_profile; g_signal_emit (combo, signals[S_PROFILE_CHANGED], 0, new_profile); g_object_notify (G_OBJECT (combo), "active-profile"); } else if (new_profile) g_object_unref (new_profile); } static void audio_profile_forgotten (GMAudioProfile *profile, GMAudioProfileChoose *choose) { GMAudioProfileChoosePrivate *priv; GtkTreeIter iter; GMAudioProfile *tmp; priv = choose->priv; if (!gtk_tree_model_get_iter_first (priv->model, &iter)) return; do { gtk_tree_model_get (priv->model, &iter, PROFILE_COLUMN, &tmp, -1); if (tmp == profile) { gtk_list_store_remove (GTK_LIST_STORE (priv->model), &iter); g_object_unref (tmp); return; } g_object_unref (tmp); } while (gtk_tree_model_iter_next (priv->model, &iter)); } /* Public API */ /** * gm_audio_profile_choose_new: * * Creates new #GMAudioProfileChoose, populated with currently active profiles. * * Return value: A new #GMAudioProfileChoose. */ GtkWidget* gm_audio_profile_choose_new (void) { return g_object_new (GM_AUDIO_TYPE_PROFILE_CHOOSE, NULL); } /** * gm_audio_profile_choose_get_active_profile: * @choose: #GMAudioProfileChoose widget * * This function retrieves currently selected #GMAudioProfile. Returned object is * owned by #GMAudioProfileChoose and should not be unreferenced. * * Return value: Currently selected #GMAudioProfile or %NULL if none is * selected. * * Since: 2.32/3.0 */ GMAudioProfile * gm_audio_profile_choose_get_active_profile (GMAudioProfileChoose *choose) { g_return_val_if_fail (GM_AUDIO_IS_PROFILE_CHOOSE (choose), NULL); return choose->priv->profile; } /** * gm_audio_profile_choose_set_active_profile: * @choose: #GMAudioProfileChoose widget * @id: A id of #GMAudioProfile that should be selected * * This function sets currently selected #GMAudioProfile. If no profile matches * the @id, first available profile is set as selected and function returns * %FALSE. * * Return value: %TRUE if profile has been successfully set, %FALSE otherwise. * * Since: 2.32/3.0 */ gboolean gm_audio_profile_choose_set_active_profile (GMAudioProfileChoose *choose, const gchar *id) { GMAudioProfileChoosePrivate *priv; GtkTreeIter iter; gchar *tmp; g_return_val_if_fail (GM_AUDIO_IS_PROFILE_CHOOSE (choose), FALSE); priv = choose->priv; if (!gtk_tree_model_get_iter_first (priv->model, &iter)) return FALSE; do { gtk_tree_model_get (priv->model, &iter, ID_COLUMN, &tmp, -1); if (!g_strcmp0 (tmp, id)) { gtk_combo_box_set_active_iter (GTK_COMBO_BOX (choose), &iter); g_free (tmp); return TRUE; } g_free (tmp); } while (gtk_tree_model_iter_next (priv->model, &iter)); /* Fallback to first entry */ gtk_combo_box_set_active (GTK_COMBO_BOX (choose), 0); return FALSE; } /* Deprecated functions */ /** * gm_audio_profile_choose_get_active: * @choose: A #GMAudioProfileChoose widget * * This function retrieves currently selected #GMAudioProfile. Returned object is * owned by #GMAudioProfileChoose and should not be unreferenced. * * Return value: Currently selected #GMAudioProfile or %NULL if none is * selected. * * Deprecated: 2.32/3.0: Use gm_audio_profile_choose_get_active_profile() * instead. */ GMAudioProfile* gm_audio_profile_choose_get_active (GtkWidget *choose) { /* We cannot simply wrap gm_audio_profile_choose_get_active_profile() here, * since this function can be (and in case of sound-juicer is) called from * GtkComboBox::changed signal handler. In this situation, code would return * invalid profile, since we haven't updated the current selection yet. */ GMAudioProfileChoosePrivate *priv; GtkTreeIter iter; GMAudioProfile *new_profile = NULL; g_return_val_if_fail (GM_AUDIO_IS_PROFILE_CHOOSE (choose), NULL); priv = GM_AUDIO_PROFILE_CHOOSE (choose)->priv; if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (choose), &iter)) { gtk_tree_model_get (priv->model, &iter, PROFILE_COLUMN, &new_profile, -1); g_object_unref (new_profile); } return new_profile; } /** * gm_audio_profile_choose_set_active: * @choose: #GMAudioProfileChoose widget * @id: A id of #GMAudioProfile that should be selected * * This function sets currently selected #GMAudioProfile. If no profile matches * the @id, first available profile is set as selected and function returns * %FALSE. * * Return value: %TRUE if profile has been successfully set, %FALSE otherwise. * * Deprecated: 2.32/3.0: Use gm_audio_profile_choose_set_active_profile() * instead. */ gboolean gm_audio_profile_choose_set_active (GtkWidget *choose, const char *id) { return gm_audio_profile_choose_set_active_profile (GM_AUDIO_PROFILE_CHOOSE (choose), id); }