/* MATE Volume Control * Copyright (C) 2003-2004 Ronald Bultje * * window.c: main window * * 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., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #if GTK_CHECK_VERSION (3, 0, 0) #include #endif #include "schemas.h" #include "preferences.h" #include "window.h" G_DEFINE_TYPE (MateVolumeControlWindow, mate_volume_control_window, GTK_TYPE_WINDOW) void mate_volume_control_window_set_page(GtkWidget *widget, const gchar *page) { MateVolumeControlWindow *win = MATE_VOLUME_CONTROL_WINDOW (widget); if (g_ascii_strncasecmp(page, "playback",8) == 0) gtk_notebook_set_current_page (GTK_NOTEBOOK (win->el), 0); else if (g_ascii_strncasecmp(page, "recording",9) == 0) gtk_notebook_set_current_page (GTK_NOTEBOOK (win->el), 1); else if (g_ascii_strncasecmp(page, "switches",9) == 0) gtk_notebook_set_current_page (GTK_NOTEBOOK (win->el), 2); else if (g_ascii_strncasecmp(page, "options",9) == 0) gtk_notebook_set_current_page (GTK_NOTEBOOK (win->el), 3); else /* default is "playback" */ gtk_notebook_set_current_page (GTK_NOTEBOOK (win->el), 0); } /* * Menu actions. */ static void cb_change (GtkComboBox *widget, MateVolumeControlWindow *win) { gchar *device_name; device_name = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (widget)); g_return_if_fail (device_name != NULL); g_settings_set_string (win->settings, MATE_VOLUME_CONTROL_KEY_ACTIVE_ELEMENT, device_name); g_free (device_name); } static void cb_exit (GtkAction *action, MateVolumeControlWindow *win) { gtk_widget_destroy (GTK_WIDGET (win)); } static void cb_preferences_destroy (GtkWidget *widget, MateVolumeControlWindow *win) { win->prefs = NULL; } static void cb_preferences (GtkAction *action, MateVolumeControlWindow *win) { if (!win->prefs) { win->prefs = mate_volume_control_preferences_new (GST_ELEMENT (win->el->mixer)); g_signal_connect (win->prefs, "destroy", G_CALLBACK (cb_preferences_destroy), win); gtk_widget_show (win->prefs); } else { gtk_window_present (GTK_WINDOW (win->prefs)); } } static void cb_help (GtkAction *action, MateVolumeControlWindow *win) { GdkScreen *screen; GtkWidget *dialog; GError *error = NULL; screen = gtk_window_get_screen (GTK_WINDOW (win)); if (gtk_show_uri (screen, "help:mate-volume-control", GDK_CURRENT_TIME, &error) == FALSE) { dialog = gtk_message_dialog_new (GTK_WINDOW (win), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", error->message); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); g_error_free (error); } } static void cb_show_about (MateVolumeControlWindow *win) { const gchar *authors[] = { "Ronald Bultje ", "Leif Johnson ", NULL }; const gchar *documenters[] = { "Sun Microsystems", NULL}; gtk_show_about_dialog (GTK_WINDOW (win), "version", VERSION, "copyright", "Copyright \xc2\xa9 2003-2004 Ronald Bultje", "comments", _("A MATE/GStreamer-based volume control application"), "authors", authors, "documenters", documenters, "translator-credits", _("translator-credits"), "logo-icon-name", "multimedia-volume-control", NULL); } static void window_change_mixer_element (MateVolumeControlWindow *win, const gchar *el) { const char *cur_el_str; GList *item; g_return_if_fail (win != NULL); g_return_if_fail (el != NULL); for (item = win->elements; item != NULL; item = item->next) { cur_el_str = g_object_get_data (item->data, "mate-volume-control-name"); if (cur_el_str == NULL) continue; if (g_str_equal (cur_el_str, el)) { GstElement *old_element = GST_ELEMENT (win->el->mixer); gchar *title; /* change element */ gst_element_set_state (item->data, GST_STATE_READY); mate_volume_control_element_change (win->el, item->data); if (win->prefs != NULL) mate_volume_control_preferences_change (MATE_VOLUME_CONTROL_PREFERENCES (win->prefs), item->data); if (old_element != NULL) gst_element_set_state (old_element, GST_STATE_NULL); /* change window title */ title = g_strdup_printf (_("Volume Control: %s"), cur_el_str); gtk_window_set_title (GTK_WINDOW (win), title); g_free (title); break; } } } static void cb_gsettings_active_element (GSettings *settings, gchar *key, gpointer data) { window_change_mixer_element (MATE_VOLUME_CONTROL_WINDOW (data), g_settings_get_string (settings, key)); } /* * Signal handlers. */ #if 0 static void cb_error (GstElement *element, GstElement *source, GError *error, gchar *debug, gpointer data) { MateVolumeControlWindow *win = MATE_VOLUME_CONTROL_WINDOW (data); GtkWidget *dialog; dialog = gtk_message_dialog_new (GTK_WINDOW (win), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, error->message); gtk_widget_show (dialog); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); } #endif static void mate_volume_control_window_dispose (GObject *object) { MateVolumeControlWindow *win = MATE_VOLUME_CONTROL_WINDOW (object); if (win->prefs) { gtk_widget_destroy (win->prefs); win->prefs = NULL; } /* clean up */ if (win->elements) { g_list_foreach (win->elements, (GFunc) g_object_unref, NULL); g_list_free (win->elements); win->elements = NULL; } if (win->settings) { g_object_unref (win->settings); win->settings = NULL; } G_OBJECT_CLASS (mate_volume_control_window_parent_class)->dispose (object); } static void mate_volume_control_window_class_init (MateVolumeControlWindowClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->dispose = mate_volume_control_window_dispose; } static void mate_volume_control_window_init (MateVolumeControlWindow *win) { int width, height; win->elements = NULL; win->el = NULL; win->settings = g_settings_new (MATE_VOLUME_CONTROL_SCHEMA); win->prefs = NULL; win->use_default_mixer = FALSE; g_set_application_name (_("Volume Control")); gtk_window_set_title (GTK_WINDOW (win), _("Volume Control")); /* gsettings */ g_signal_connect (win->settings, "changed::" MATE_VOLUME_CONTROL_KEY_ACTIVE_ELEMENT, G_CALLBACK (cb_gsettings_active_element), win); /* To set the window according to previous geometry */ width = g_settings_get_int (win->settings, MATE_VOLUME_CONTROL_KEY_WINDOW_WIDTH); if (width < 250) width = 250; height = g_settings_get_int (win->settings, MATE_VOLUME_CONTROL_KEY_WINDOW_HEIGHT); if (height < 100) height = -1; gtk_window_set_default_size (GTK_WINDOW (win), width, height); } GtkWidget * mate_volume_control_window_new (GList *elements) { gchar *active_el_str, *cur_el_str; GstElement *active_element; GList *item; MateVolumeControlWindow *win; GtkAccelGroup *accel_group; GtkWidget *combo_box; GtkWidget *label; GtkWidget *hbox; GtkWidget *buttons; GtkWidget *el; GtkWidget *prefsbtn; GtkWidget *closebtn; GtkWidget *helpbtn; gint count = 0; GtkWidget *vbox; GtkCellRenderer *renderer; gint active_element_num; g_return_val_if_fail (elements != NULL, NULL); active_element = NULL; /* window */ win = g_object_new (MATE_VOLUME_CONTROL_TYPE_WINDOW, NULL); win->elements = elements; accel_group = gtk_accel_group_new (); gtk_window_add_accel_group (GTK_WINDOW (win), accel_group); gtk_accel_group_connect (accel_group, GDK_A, GDK_CONTROL_MASK, 0, g_cclosure_new_swap (G_CALLBACK (cb_show_about), win, NULL)); /* get active element, if any (otherwise we use the default) */ active_el_str = g_settings_get_string (win->settings, MATE_VOLUME_CONTROL_KEY_ACTIVE_ELEMENT); if (active_el_str != NULL && *active_el_str != '\0') { for (count = 0, item = elements; item != NULL; item = item->next, count++) { cur_el_str = g_object_get_data (item->data, "mate-volume-control-name"); if (cur_el_str == NULL) continue; if (g_str_equal (active_el_str, cur_el_str)) { active_element = item->data; break; } } g_free (active_el_str); if (!item) { count = 0; active_element = elements->data; /* If there's a default but it doesn't match what we have available, * reset the default */ g_settings_set_string (win->settings, MATE_VOLUME_CONTROL_KEY_ACTIVE_ELEMENT, g_object_get_data (G_OBJECT (active_element), "mate-volume-control-name")); } /* default element to first */ if (!active_element) active_element = elements->data; } else { count = 0; active_element = elements->data; } active_element_num = count; combo_box = gtk_combo_box_text_new (); renderer = gtk_cell_renderer_text_new (); g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL); gtk_cell_layout_clear (GTK_CELL_LAYOUT (combo_box)); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, TRUE); gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo_box), renderer, "text", 0); for (count = 0, item = elements; item != NULL; item = item->next, count++) { const gchar *name; name = g_object_get_data (item->data, "mate-volume-control-name"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT (combo_box), name); } gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), active_element_num); g_signal_connect (combo_box, "changed", G_CALLBACK (cb_change), win); win->use_default_mixer = (active_el_str == NULL); /* add the combo box to choose the device */ label = gtk_label_new (NULL); gtk_label_set_text_with_mnemonic (GTK_LABEL (label), _("_Device: ")); gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo_box); hbox = gtk_hbox_new (FALSE, 6); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), combo_box, TRUE, TRUE, 0); /* add content for this element */ el = mate_volume_control_element_new (); win->el = MATE_VOLUME_CONTROL_ELEMENT (el); /* create the buttons box */ helpbtn = gtk_button_new_from_stock (GTK_STOCK_HELP); prefsbtn = gtk_button_new_from_stock (GTK_STOCK_PREFERENCES); closebtn = gtk_button_new_from_stock (GTK_STOCK_CLOSE); g_signal_connect (helpbtn, "clicked", G_CALLBACK (cb_help), win); g_signal_connect (prefsbtn, "clicked", G_CALLBACK (cb_preferences), win); g_signal_connect (closebtn, "clicked", G_CALLBACK (cb_exit), win); gtk_widget_add_accelerator (closebtn, "clicked", accel_group, GDK_Escape, 0, 0); gtk_widget_add_accelerator (helpbtn, "clicked", accel_group, GDK_F1, 0, 0); buttons = gtk_hbutton_box_new (); gtk_box_pack_start (GTK_BOX (buttons), helpbtn, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (buttons), prefsbtn, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (buttons), closebtn, FALSE, FALSE, 0); gtk_box_set_spacing (GTK_BOX (buttons), 6); gtk_button_box_set_layout (GTK_BUTTON_BOX (buttons), GTK_BUTTONBOX_END); gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (buttons), helpbtn, TRUE); /* Put the the elements in a vbox */ vbox = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER(win), vbox); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 6); gtk_box_pack_start (GTK_BOX (vbox), el, TRUE, TRUE, 6); gtk_box_pack_start (GTK_BOX (vbox), buttons, FALSE, FALSE, 0); gtk_container_set_border_width (GTK_CONTAINER (vbox), 6); /* set tooltips */ gtk_widget_set_tooltip_text (combo_box, _("Control volume on a different device")); gtk_widget_show_all (GTK_WIDGET (win)); /* refresh the control and window title with the default mixer */ window_change_mixer_element (win, g_object_get_data (G_OBJECT (active_element), "mate-volume-control-name")); /* FIXME: * - set error handler (cb_error) after device activation: * g_signal_connect (element, "error", G_CALLBACK (cb_error), win);. * - on device change: reset error handler, change menu (in case this * was done outside the UI). */ return GTK_WIDGET (win); }