From e46b4adef5c6c6805b3ca6dbfbe99a4299252514 Mon Sep 17 00:00:00 2001 From: haxar Date: Tue, 21 Feb 2012 20:14:01 -0800 Subject: gsd to msd complete rename patch by NiceandGently; file rename commit --- plugins/media-keys/gsd-marshal.list | 1 - plugins/media-keys/gsd-media-keys-manager.c | 1447 ------------------------- plugins/media-keys/gsd-media-keys-manager.h | 72 -- plugins/media-keys/gsd-media-keys-manager.xml | 14 - plugins/media-keys/gsd-media-keys-plugin.c | 104 -- plugins/media-keys/gsd-media-keys-plugin.h | 63 -- plugins/media-keys/gsd-media-keys-window.c | 714 ------------ plugins/media-keys/gsd-media-keys-window.h | 78 -- plugins/media-keys/msd-marshal.list | 1 + plugins/media-keys/msd-media-keys-manager.c | 1447 +++++++++++++++++++++++++ plugins/media-keys/msd-media-keys-manager.h | 72 ++ plugins/media-keys/msd-media-keys-manager.xml | 14 + plugins/media-keys/msd-media-keys-plugin.c | 104 ++ plugins/media-keys/msd-media-keys-plugin.h | 63 ++ plugins/media-keys/msd-media-keys-window.c | 714 ++++++++++++ plugins/media-keys/msd-media-keys-window.h | 78 ++ 16 files changed, 2493 insertions(+), 2493 deletions(-) delete mode 100644 plugins/media-keys/gsd-marshal.list delete mode 100644 plugins/media-keys/gsd-media-keys-manager.c delete mode 100644 plugins/media-keys/gsd-media-keys-manager.h delete mode 100644 plugins/media-keys/gsd-media-keys-manager.xml delete mode 100644 plugins/media-keys/gsd-media-keys-plugin.c delete mode 100644 plugins/media-keys/gsd-media-keys-plugin.h delete mode 100644 plugins/media-keys/gsd-media-keys-window.c delete mode 100644 plugins/media-keys/gsd-media-keys-window.h create mode 100644 plugins/media-keys/msd-marshal.list create mode 100644 plugins/media-keys/msd-media-keys-manager.c create mode 100644 plugins/media-keys/msd-media-keys-manager.h create mode 100644 plugins/media-keys/msd-media-keys-manager.xml create mode 100644 plugins/media-keys/msd-media-keys-plugin.c create mode 100644 plugins/media-keys/msd-media-keys-plugin.h create mode 100644 plugins/media-keys/msd-media-keys-window.c create mode 100644 plugins/media-keys/msd-media-keys-window.h (limited to 'plugins/media-keys') diff --git a/plugins/media-keys/gsd-marshal.list b/plugins/media-keys/gsd-marshal.list deleted file mode 100644 index 72f9937..0000000 --- a/plugins/media-keys/gsd-marshal.list +++ /dev/null @@ -1 +0,0 @@ -VOID:STRING,STRING diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c deleted file mode 100644 index d7e1b04..0000000 --- a/plugins/media-keys/gsd-media-keys-manager.c +++ /dev/null @@ -1,1447 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2001-2003 Bastien Nocera - * Copyright (C) 2006-2007 William Jon McCann - * - * 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "mate-settings-profile.h" -#include "msd-marshal.h" -#include "msd-media-keys-manager.h" -#include "msd-media-keys-manager-glue.h" - -#include "eggaccelerators.h" -#include "acme.h" -#include "msd-media-keys-window.h" - -#ifdef HAVE_PULSE -#include -#include "gvc-mixer-control.h" -#elif defined(HAVE_GSTREAMER) -#include "gvc-gstreamer-acme-vol.h" -#endif /* HAVE_PULSE */ - -#define MSD_DBUS_PATH "/org/mate/SettingsDaemon" -#define MSD_DBUS_NAME "org.mate.SettingsDaemon" -#define MSD_MEDIA_KEYS_DBUS_PATH MSD_DBUS_PATH "/MediaKeys" -#define MSD_MEDIA_KEYS_DBUS_NAME MSD_DBUS_NAME ".MediaKeys" - -#define TOUCHPAD_ENABLED_KEY "/desktop/mate/peripherals/touchpad/touchpad_enabled" - -#define VOLUME_STEP 6 /* percents for one volume button press */ -#define MAX_VOLUME 65536.0 - -#define MSD_MEDIA_KEYS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MSD_TYPE_MEDIA_KEYS_MANAGER, MsdMediaKeysManagerPrivate)) - -typedef struct { - char *application; - guint32 time; -} MediaPlayer; - -struct MsdMediaKeysManagerPrivate -{ -#ifdef HAVE_PULSE - /* Volume bits */ - GvcMixerControl *volume; - GvcMixerStream *stream; -#elif defined(HAVE_GSTREAMER) - AcmeVolume *volume; -#endif /* HAVE_PULSE */ - GtkWidget *dialog; - MateConfClient *conf_client; - GVolumeMonitor *volume_monitor; - - /* Multihead stuff */ - GdkScreen *current_screen; - GSList *screens; - - GList *media_players; - - DBusGConnection *connection; - guint notify[HANDLED_KEYS]; -}; - -enum { - MEDIA_PLAYER_KEY_PRESSED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -static void msd_media_keys_manager_class_init (MsdMediaKeysManagerClass *klass); -static void msd_media_keys_manager_init (MsdMediaKeysManager *media_keys_manager); -static void msd_media_keys_manager_finalize (GObject *object); - -G_DEFINE_TYPE (MsdMediaKeysManager, msd_media_keys_manager, G_TYPE_OBJECT) - -static gpointer manager_object = NULL; - - -static void -init_screens (MsdMediaKeysManager *manager) -{ - GdkDisplay *display; - int i; - - display = gdk_display_get_default (); - for (i = 0; i < gdk_display_get_n_screens (display); i++) { - GdkScreen *screen; - - screen = gdk_display_get_screen (display, i); - if (screen == NULL) { - continue; - } - manager->priv->screens = g_slist_append (manager->priv->screens, screen); - } - - manager->priv->current_screen = manager->priv->screens->data; -} - - -static void -acme_error (char * msg) -{ - GtkWidget *error_dialog; - - error_dialog = gtk_message_dialog_new (NULL, - GTK_DIALOG_MODAL, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - msg, NULL); - gtk_dialog_set_default_response (GTK_DIALOG (error_dialog), - GTK_RESPONSE_OK); - gtk_widget_show (error_dialog); - g_signal_connect (error_dialog, - "response", - G_CALLBACK (gtk_widget_destroy), - NULL); -} - -static char * -get_term_command (MsdMediaKeysManager *manager) -{ - char *cmd_term; - char *cmd = NULL; - - cmd_term = mateconf_client_get_string (manager->priv->conf_client, - "/desktop/mate/applications/terminal/exec", NULL); - if ((cmd_term != NULL) && (strcmp (cmd_term, "") != 0)) { - char *cmd_args; - cmd_args = mateconf_client_get_string (manager->priv->conf_client, - "/desktop/mate/applications/terminal/exec_arg", NULL); - if ((cmd_args != NULL) && (strcmp (cmd_term, "") != 0)) { - cmd = g_strdup_printf ("%s %s -e", cmd_term, cmd_args); - } else { - cmd = g_strdup_printf ("%s -e", cmd_term); - } - - g_free (cmd_args); - } - - g_free (cmd_term); - - return cmd; -} - -static void -execute (MsdMediaKeysManager *manager, - char *cmd, - gboolean sync, - gboolean need_term) -{ - gboolean retval; - char **argv; - int argc; - char *exec; - char *term = NULL; - - retval = FALSE; - - if (need_term) { - term = get_term_command (manager); - if (term == NULL) { - acme_error (_("Could not get default terminal. Verify that your default " - "terminal command is set and points to a valid application.")); - return; - } - } - - if (term) { - exec = g_strdup_printf ("%s %s", term, cmd); - g_free (term); - } else { - exec = g_strdup (cmd); - } - - if (g_shell_parse_argv (exec, &argc, &argv, NULL)) { - if (sync != FALSE) { - retval = g_spawn_sync (g_get_home_dir (), - argv, - NULL, - G_SPAWN_SEARCH_PATH, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL); - } else { - retval = g_spawn_async (g_get_home_dir (), - argv, - NULL, - G_SPAWN_SEARCH_PATH, - NULL, - NULL, - NULL, - NULL); - } - g_strfreev (argv); - } - - if (retval == FALSE) { - char *msg; - msg = g_strdup_printf (_("Couldn't execute command: %s\n" - "Verify that this is a valid command."), - exec); - - acme_error (msg); - g_free (msg); - } - g_free (exec); -} - -static void -dialog_init (MsdMediaKeysManager *manager) -{ - if (manager->priv->dialog != NULL - && !msd_osd_window_is_valid (MSD_OSD_WINDOW (manager->priv->dialog))) { - gtk_widget_destroy (manager->priv->dialog); - manager->priv->dialog = NULL; - } - - if (manager->priv->dialog == NULL) { - manager->priv->dialog = msd_media_keys_window_new (); - } -} - -static gboolean -is_valid_shortcut (const char *string) -{ - if (string == NULL || string[0] == '\0') { - return FALSE; - } - if (strcmp (string, "disabled") == 0) { - return FALSE; - } - - return TRUE; -} - -static void -update_kbd_cb (MateConfClient *client, - guint id, - MateConfEntry *entry, - MsdMediaKeysManager *manager) -{ - int i; - gboolean need_flush = TRUE; - - g_return_if_fail (entry->key != NULL); - - gdk_error_trap_push (); - - /* Find the key that was modified */ - for (i = 0; i < HANDLED_KEYS; i++) { - if (strcmp (entry->key, keys[i].mateconf_key) == 0) { - char *tmp; - Key *key; - - if (keys[i].key != NULL) { - need_flush = TRUE; - grab_key_unsafe (keys[i].key, FALSE, manager->priv->screens); - } - - g_free (keys[i].key); - keys[i].key = NULL; - - tmp = mateconf_client_get_string (manager->priv->conf_client, - keys[i].mateconf_key, NULL); - - if (is_valid_shortcut (tmp) == FALSE) { - g_free (tmp); - break; - } - - key = g_new0 (Key, 1); - if (!egg_accelerator_parse_virtual (tmp, &key->keysym, &key->keycodes, &key->state)) { - g_free (tmp); - g_free (key); - break; - } - - need_flush = TRUE; - grab_key_unsafe (key, TRUE, manager->priv->screens); - keys[i].key = key; - - g_free (tmp); - - break; - } - } - - if (need_flush) - gdk_flush (); - if (gdk_error_trap_pop ()) - g_warning ("Grab failed for some keys, another application may already have access the them."); -} - -static void init_kbd(MsdMediaKeysManager* manager) -{ - int i; - gboolean need_flush = FALSE; - - mate_settings_profile_start(NULL); - - gdk_error_trap_push(); - - for (i = 0; i < HANDLED_KEYS; i++) - { - char* tmp; - Key* key; - - manager->priv->notify[i] = mateconf_client_notify_add(manager->priv->conf_client, - keys[i].mateconf_key, - (MateConfClientNotifyFunc) update_kbd_cb, - manager, - NULL, - NULL); - - tmp = mateconf_client_get_string(manager->priv->conf_client, - keys[i].mateconf_key, - NULL); - - if (!is_valid_shortcut(tmp)) - { - g_debug("Not a valid shortcut: '%s'", tmp); - g_free(tmp); - continue; - } - - key = g_new0(Key, 1); - - if (!egg_accelerator_parse_virtual(tmp, &key->keysym, &key->keycodes, &key->state)) - { - g_debug("Unable to parse: '%s'", tmp); - g_free(tmp); - g_free(key); - continue; - } - - g_free(tmp); - - keys[i].key = key; - - need_flush = TRUE; - grab_key_unsafe(key, TRUE, manager->priv->screens); - } - - if (need_flush) - { - gdk_flush(); - } - - if (gdk_error_trap_pop ()) - { - g_warning("Grab failed for some keys, another application may already have access the them."); - } - - mate_settings_profile_end(NULL); -} - -static void -dialog_show (MsdMediaKeysManager *manager) -{ - int orig_w; - int orig_h; - int screen_w; - int screen_h; - int x; - int y; - int pointer_x; - int pointer_y; - GtkRequisition win_req; - GdkScreen *pointer_screen; - GdkRectangle geometry; - int monitor; - - gtk_window_set_screen (GTK_WINDOW (manager->priv->dialog), - manager->priv->current_screen); - - /* - * get the window size - * if the window hasn't been mapped, it doesn't necessarily - * know its true size, yet, so we need to jump through hoops - */ - gtk_window_get_default_size (GTK_WINDOW (manager->priv->dialog), &orig_w, &orig_h); - gtk_widget_size_request (manager->priv->dialog, &win_req); - - if (win_req.width > orig_w) { - orig_w = win_req.width; - } - if (win_req.height > orig_h) { - orig_h = win_req.height; - } - - pointer_screen = NULL; - gdk_display_get_pointer (gdk_screen_get_display (manager->priv->current_screen), - &pointer_screen, - &pointer_x, - &pointer_y, - NULL); - if (pointer_screen != manager->priv->current_screen) { - /* The pointer isn't on the current screen, so just - * assume the default monitor - */ - monitor = 0; - } else { - monitor = gdk_screen_get_monitor_at_point (manager->priv->current_screen, - pointer_x, - pointer_y); - } - - gdk_screen_get_monitor_geometry (manager->priv->current_screen, - monitor, - &geometry); - - screen_w = geometry.width; - screen_h = geometry.height; - - x = ((screen_w - orig_w) / 2) + geometry.x; - y = geometry.y + (screen_h / 2) + (screen_h / 2 - orig_h) / 2; - - gtk_window_move (GTK_WINDOW (manager->priv->dialog), x, y); - - gtk_widget_show (manager->priv->dialog); - - gdk_display_sync (gdk_screen_get_display (manager->priv->current_screen)); -} - -static void -do_unknown_action (MsdMediaKeysManager *manager, - const char *url) -{ - char *string; - - g_return_if_fail (url != NULL); - - string = mateconf_client_get_string (manager->priv->conf_client, - "/desktop/mate/url-handlers/unknown/command", - NULL); - - if ((string != NULL) && (strcmp (string, "") != 0)) { - char *cmd; - cmd = g_strdup_printf (string, url); - execute (manager, cmd, FALSE, FALSE); - g_free (cmd); - } - g_free (string); -} - -static void -do_help_action (MsdMediaKeysManager *manager) -{ - char *string; - - string = mateconf_client_get_string (manager->priv->conf_client, - "/desktop/mate/url-handlers/ghelp/command", - NULL); - - if ((string != NULL) && (strcmp (string, "") != 0)) { - char *cmd; - cmd = g_strdup_printf (string, ""); - execute (manager, cmd, FALSE, FALSE); - g_free (cmd); - } else { - do_unknown_action (manager, "ghelp:"); - } - - g_free (string); -} - -static void -do_mail_action (MsdMediaKeysManager *manager) -{ - char *string; - - string = mateconf_client_get_string (manager->priv->conf_client, - "/desktop/mate/url-handlers/mailto/command", - NULL); - - if ((string != NULL) && (strcmp (string, "") != 0)) { - char *cmd; - cmd = g_strdup_printf (string, ""); - execute (manager, - cmd, - FALSE, - mateconf_client_get_bool (manager->priv->conf_client, - "/desktop/mate/url-handlers/mailto/needs_terminal", NULL)); - g_free (cmd); - } - g_free (string); -} - -static void -do_media_action (MsdMediaKeysManager *manager) -{ - char *command; - - command = mateconf_client_get_string (manager->priv->conf_client, - "/desktop/mate/applications/media/exec", NULL); - if ((command != NULL) && (strcmp (command, "") != 0)) { - execute (manager, - command, - FALSE, - mateconf_client_get_bool (manager->priv->conf_client, - "/desktop/mate/applications/media/needs_term", NULL)); - } - g_free (command); -} - -static void -do_www_action (MsdMediaKeysManager *manager, - const char *url) -{ - char *string; - - string = mateconf_client_get_string (manager->priv->conf_client, - "/desktop/mate/url-handlers/http/command", - NULL); - - if ((string != NULL) && (strcmp (string, "") != 0)) { - gchar *cmd; - - if (url == NULL) { - cmd = g_strdup_printf (string, ""); - } else { - cmd = g_strdup_printf (string, url); - } - - execute (manager, - cmd, - FALSE, - mateconf_client_get_bool (manager->priv->conf_client, - "/desktop/mate/url-handlers/http/needs_terminal", NULL)); - g_free (cmd); - } else { - do_unknown_action (manager, url ? url : ""); - } - g_free (string); -} - -static void -do_exit_action (MsdMediaKeysManager *manager) -{ - execute (manager, "mate-session-save --shutdown-dialog", FALSE, FALSE); -} - -static void -do_eject_action_cb (GDrive *drive, - GAsyncResult *res, - MsdMediaKeysManager *manager) -{ - g_drive_eject_with_operation_finish (drive, res, NULL); -} - -#define NO_SCORE 0 -#define SCORE_CAN_EJECT 50 -#define SCORE_HAS_MEDIA 100 -static void -do_eject_action (MsdMediaKeysManager *manager) -{ - GList *drives, *l; - GDrive *fav_drive; - guint score; - - /* Find the best drive to eject */ - fav_drive = NULL; - score = NO_SCORE; - drives = g_volume_monitor_get_connected_drives (manager->priv->volume_monitor); - for (l = drives; l != NULL; l = l->next) { - GDrive *drive = l->data; - - if (g_drive_can_eject (drive) == FALSE) - continue; - if (g_drive_is_media_removable (drive) == FALSE) - continue; - if (score < SCORE_CAN_EJECT) { - fav_drive = drive; - score = SCORE_CAN_EJECT; - } - if (g_drive_has_media (drive) == FALSE) - continue; - if (score < SCORE_HAS_MEDIA) { - fav_drive = drive; - score = SCORE_HAS_MEDIA; - break; - } - } - - /* Show the dialogue */ - dialog_init (manager); - msd_media_keys_window_set_action_custom (MSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), - "media-eject", - FALSE); - dialog_show (manager); - - /* Clean up the drive selection and exit if no suitable - * drives are found */ - if (fav_drive != NULL) - fav_drive = g_object_ref (fav_drive); - - g_list_foreach (drives, (GFunc) g_object_unref, NULL); - if (fav_drive == NULL) - return; - - /* Eject! */ - g_drive_eject_with_operation (fav_drive, G_MOUNT_UNMOUNT_FORCE, - NULL, NULL, - (GAsyncReadyCallback) do_eject_action_cb, - manager); - g_object_unref (fav_drive); -} - -static void -do_touchpad_action (MsdMediaKeysManager *manager) -{ - MateConfClient *client = manager->priv->conf_client; - gboolean state = mateconf_client_get_bool (client, TOUCHPAD_ENABLED_KEY, NULL); - - dialog_init (manager); - msd_media_keys_window_set_action_custom (MSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), - (!state) ? "touchpad-enabled" : "touchpad-disabled", - FALSE); - dialog_show (manager); - - mateconf_client_set_bool (client, TOUCHPAD_ENABLED_KEY, !state, NULL); -} - -#ifdef HAVE_PULSE -static void -update_dialog (MsdMediaKeysManager *manager, - guint vol, - gboolean muted, - gboolean sound_changed) -{ - vol = (int) (100 * (double) vol / PA_VOLUME_NORM); - vol = CLAMP (vol, 0, 100); - - dialog_init (manager); - msd_media_keys_window_set_volume_muted (MSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), - muted); - msd_media_keys_window_set_volume_level (MSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), vol); - msd_media_keys_window_set_action (MSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), - MSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME); - dialog_show (manager); - - if (sound_changed != FALSE && muted == FALSE) - ca_gtk_play_for_widget (manager->priv->dialog, 0, - CA_PROP_EVENT_ID, "audio-volume-change", - CA_PROP_EVENT_DESCRIPTION, "volume changed through key press", - CA_PROP_APPLICATION_ID, "org.mate.VolumeControl", - NULL); -} -#endif /* HAVE_PULSE */ - -#if defined(HAVE_PULSE) || defined(HAVE_GSTREAMER) -static void -do_sound_action (MsdMediaKeysManager *manager, - int type) -{ - gboolean muted; - guint vol, norm_vol_step; - int vol_step; - gboolean sound_changed; - -#ifdef HAVE_PULSE - if (manager->priv->stream == NULL) - return; -#elif defined(HAVE_GSTREAMER) - if (manager->priv->volume == NULL) - return; -#endif - - vol_step = mateconf_client_get_int (manager->priv->conf_client, - MATECONF_MISC_DIR "/volume_step", - NULL); - - if (vol_step <= 0 || vol_step > 100) - vol_step = VOLUME_STEP; - -#ifdef HAVE_PULSE - norm_vol_step = PA_VOLUME_NORM * vol_step / 100; - - /* FIXME: this is racy */ - vol = gvc_mixer_stream_get_volume (manager->priv->stream); - muted = gvc_mixer_stream_get_is_muted (manager->priv->stream); -#else - if (vol_step > 0) { - gint threshold = acme_volume_get_threshold (manager->priv->volume); - if (vol_step < threshold) - vol_step = threshold; - g_debug ("Using volume step of %d", vol_step); - } - vol = acme_volume_get_volume (manager->priv->volume); - muted = acme_volume_get_mute (manager->priv->volume); -#endif - sound_changed = FALSE; - - switch (type) { - case MUTE_KEY: -#ifdef HAVE_PULSE - muted = !muted; - gvc_mixer_stream_change_is_muted (manager->priv->stream, muted); - sound_changed = TRUE; -#else - acme_volume_mute_toggle (manager->priv->volume); -#endif - break; - case VOLUME_DOWN_KEY: -#ifdef HAVE_PULSE - if (!muted && (vol <= norm_vol_step)) { - muted = !muted; - vol = 0; - gvc_mixer_stream_change_is_muted (manager->priv->stream, muted); - if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE) { - gvc_mixer_stream_push_volume (manager->priv->stream); - sound_changed = TRUE; - } - } else if (!muted) { - vol = vol - norm_vol_step; - if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE) { - gvc_mixer_stream_push_volume (manager->priv->stream); - sound_changed = TRUE; - } - } -#else - if (!muted && (vol <= vol_step)) - acme_volume_mute_toggle (manager->priv->volume); - acme_volume_set_volume (manager->priv->volume, vol - vol_step); -#endif - break; - case VOLUME_UP_KEY: - if (muted) { - muted = !muted; - if (vol == 0) { -#ifdef HAVE_PULSE - vol = vol + norm_vol_step; - gvc_mixer_stream_change_is_muted (manager->priv->stream, muted); - if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE) { - gvc_mixer_stream_push_volume (manager->priv->stream); - sound_changed = TRUE; - } - } else { - gvc_mixer_stream_change_is_muted (manager->priv->stream, muted); - sound_changed = TRUE; - } -#else - /* We need to unmute otherwise vol is blocked (and muted) */ - acme_volume_set_mute (manager->priv->volume, FALSE); - } - acme_volume_set_volume (manager->priv->volume, vol + vol_step); -#endif - } else { -#ifdef HAVE_PULSE - if (vol < MAX_VOLUME) { - if (vol + norm_vol_step >= MAX_VOLUME) { - vol = MAX_VOLUME; - } else { - vol = vol + norm_vol_step; - } - if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE) { - gvc_mixer_stream_push_volume (manager->priv->stream); - sound_changed = TRUE; - } - } -#else - acme_volume_set_volume (manager->priv->volume, vol + vol_step); -#endif - } - break; - } - -#ifdef HAVE_PULSE - update_dialog (manager, vol, muted, sound_changed); -#else - muted = acme_volume_get_mute (manager->priv->volume); - vol = acme_volume_get_volume (manager->priv->volume); - - /* FIXME: AcmeVolume should probably emit signals - instead of doing it like this */ - dialog_init (manager); - msd_media_keys_window_set_volume_muted (MSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), - muted); - msd_media_keys_window_set_volume_level (MSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), - vol); - msd_media_keys_window_set_action (MSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), - MSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME); - dialog_show (manager); -#endif /* HAVE_PULSE */ -} -#endif /* defined(HAVE_PULSE) || defined(HAVE_GSTREAMER) */ - -#ifdef HAVE_PULSE -static void -update_default_sink (MsdMediaKeysManager *manager) -{ - GvcMixerStream *stream; - - stream = gvc_mixer_control_get_default_sink (manager->priv->volume); - if (stream == manager->priv->stream) - return; - - if (manager->priv->stream != NULL) { - g_object_unref (manager->priv->stream); - manager->priv->stream = NULL; - } - - if (stream != NULL) { - manager->priv->stream = g_object_ref (stream); - } else { - g_warning ("Unable to get default sink"); - } -} - -static void -on_control_ready (GvcMixerControl *control, - MsdMediaKeysManager *manager) -{ - update_default_sink (manager); -} - -static void -on_control_default_sink_changed (GvcMixerControl *control, - guint id, - MsdMediaKeysManager *manager) -{ - update_default_sink (manager); -} - -#endif /* HAVE_PULSE */ - -static gint -find_by_application (gconstpointer a, - gconstpointer b) -{ - return strcmp (((MediaPlayer *)a)->application, b); -} - -static gint -find_by_time (gconstpointer a, - gconstpointer b) -{ - return ((MediaPlayer *)a)->time < ((MediaPlayer *)b)->time; -} - -/* - * Register a new media player. Most applications will want to call - * this with time = GDK_CURRENT_TIME. This way, the last registered - * player will receive media events. In some cases, applications - * may want to register with a lower priority (usually 1), to grab - * events only nobody is interested. - */ -gboolean -msd_media_keys_manager_grab_media_player_keys (MsdMediaKeysManager *manager, - const char *application, - guint32 time, - GError **error) -{ - GList *iter; - MediaPlayer *media_player; - - if (time == GDK_CURRENT_TIME) { - GTimeVal tv; - - g_get_current_time (&tv); - time = tv.tv_sec * 1000 + tv.tv_usec / 1000; - } - - iter = g_list_find_custom (manager->priv->media_players, - application, - find_by_application); - - if (iter != NULL) { - if (((MediaPlayer *)iter->data)->time < time) { - g_free (((MediaPlayer *)iter->data)->application); - g_free (iter->data); - manager->priv->media_players = g_list_delete_link (manager->priv->media_players, iter); - } else { - return TRUE; - } - } - - g_debug ("Registering %s at %u", application, time); - media_player = g_new0 (MediaPlayer, 1); - media_player->application = g_strdup (application); - media_player->time = time; - - manager->priv->media_players = g_list_insert_sorted (manager->priv->media_players, - media_player, - find_by_time); - - return TRUE; -} - -gboolean -msd_media_keys_manager_release_media_player_keys (MsdMediaKeysManager *manager, - const char *application, - GError **error) -{ - GList *iter; - - iter = g_list_find_custom (manager->priv->media_players, - application, - find_by_application); - - if (iter != NULL) { - g_debug ("Deregistering %s", application); - g_free (((MediaPlayer *)iter->data)->application); - g_free (iter->data); - manager->priv->media_players = g_list_delete_link (manager->priv->media_players, iter); - } - - return TRUE; -} - -static gboolean -msd_media_player_key_pressed (MsdMediaKeysManager *manager, - const char *key) -{ - const char *application = NULL; - gboolean have_listeners; - - have_listeners = (manager->priv->media_players != NULL); - - if (have_listeners) { - application = ((MediaPlayer *)manager->priv->media_players->data)->application; - } - - g_signal_emit (manager, signals[MEDIA_PLAYER_KEY_PRESSED], 0, application, key); - - return !have_listeners; -} - -static gboolean -do_multimedia_player_action (MsdMediaKeysManager *manager, - const char *key) -{ - return msd_media_player_key_pressed (manager, key); -} - -static gboolean -do_action (MsdMediaKeysManager *manager, - int type) -{ - char *cmd; - char *path; - - switch (type) { - case TOUCHPAD_KEY: - do_touchpad_action (manager); - break; - case MUTE_KEY: - case VOLUME_DOWN_KEY: - case VOLUME_UP_KEY: -#if defined(HAVE_PULSE) || defined(HAVE_GSTREAMER) - do_sound_action (manager, type); -#endif /* HAVE_PULSE || HAVE_GSTREAMER */ - break; - case POWER_KEY: - do_exit_action (manager); - break; - case EJECT_KEY: - do_eject_action (manager); - break; - case HOME_KEY: - path = g_shell_quote (g_get_home_dir ()); - cmd = g_strconcat ("caja --no-desktop ", path, NULL); - g_free (path); - execute (manager, cmd, FALSE, FALSE); - g_free (cmd); - break; - case SEARCH_KEY: - cmd = NULL; - if ((cmd = g_find_program_in_path ("beagle-search"))) { - execute (manager, "beagle-search", FALSE, FALSE); - } else if ((cmd = g_find_program_in_path ("tracker-search-tool"))) { - execute (manager, "tracker-search-tool", FALSE, FALSE); - } else { - execute (manager, "mate-search-tool", FALSE, FALSE); - } - g_free (cmd); - break; - case EMAIL_KEY: - do_mail_action (manager); - break; - case SCREENSAVER_KEY: - if ((cmd = g_find_program_in_path ("mate-screensaver-command"))) { - execute (manager, "mate-screensaver-command --lock", FALSE, FALSE); - } else { - execute (manager, "xscreensaver-command -lock", FALSE, FALSE); - } - - g_free (cmd); - break; - case HELP_KEY: - do_help_action (manager); - break; - case WWW_KEY: - do_www_action (manager, NULL); - break; - case MEDIA_KEY: - do_media_action (manager); - break; - case CALCULATOR_KEY: - execute (manager, "gcalctool", FALSE, FALSE); - break; - case PLAY_KEY: - return do_multimedia_player_action (manager, "Play"); - break; - case PAUSE_KEY: - return do_multimedia_player_action (manager, "Pause"); - break; - case STOP_KEY: - return do_multimedia_player_action (manager, "Stop"); - break; - case PREVIOUS_KEY: - return do_multimedia_player_action (manager, "Previous"); - break; - case NEXT_KEY: - return do_multimedia_player_action (manager, "Next"); - break; - default: - g_assert_not_reached (); - } - - return FALSE; -} - -static GdkScreen * -acme_get_screen_from_event (MsdMediaKeysManager *manager, - XAnyEvent *xanyev) -{ - GdkWindow *window; - GdkScreen *screen; - GSList *l; - - /* Look for which screen we're receiving events */ - for (l = manager->priv->screens; l != NULL; l = l->next) { - screen = (GdkScreen *) l->data; - window = gdk_screen_get_root_window (screen); - - if (GDK_WINDOW_XID (window) == xanyev->window) { - return screen; - } - } - - return NULL; -} - -static GdkFilterReturn -acme_filter_events (GdkXEvent *xevent, - GdkEvent *event, - MsdMediaKeysManager *manager) -{ - XEvent *xev = (XEvent *) xevent; - XAnyEvent *xany = (XAnyEvent *) xevent; - int i; - - /* verify we have a key event */ - if (xev->type != KeyPress && xev->type != KeyRelease) { - return GDK_FILTER_CONTINUE; - } - - for (i = 0; i < HANDLED_KEYS; i++) { - if (match_key (keys[i].key, xev)) { - switch (keys[i].key_type) { - case VOLUME_DOWN_KEY: - case VOLUME_UP_KEY: - /* auto-repeatable keys */ - if (xev->type != KeyPress) { - return GDK_FILTER_CONTINUE; - } - break; - default: - if (xev->type != KeyRelease) { - return GDK_FILTER_CONTINUE; - } - } - - manager->priv->current_screen = acme_get_screen_from_event (manager, xany); - - if (do_action (manager, keys[i].key_type) == FALSE) { - return GDK_FILTER_REMOVE; - } else { - return GDK_FILTER_CONTINUE; - } - } - } - - return GDK_FILTER_CONTINUE; -} - -static gboolean -start_media_keys_idle_cb (MsdMediaKeysManager *manager) -{ - GSList *l; - - g_debug ("Starting media_keys manager"); - mate_settings_profile_start (NULL); - manager->priv->volume_monitor = g_volume_monitor_get (); - manager->priv->conf_client = mateconf_client_get_default (); - - mateconf_client_add_dir (manager->priv->conf_client, - MATECONF_BINDING_DIR, - MATECONF_CLIENT_PRELOAD_ONELEVEL, - NULL); - - init_screens (manager); - init_kbd (manager); - - /* Start filtering the events */ - for (l = manager->priv->screens; l != NULL; l = l->next) { - mate_settings_profile_start ("gdk_window_add_filter"); - - g_debug ("adding key filter for screen: %d", - gdk_screen_get_number (l->data)); - - gdk_window_add_filter (gdk_screen_get_root_window (l->data), - (GdkFilterFunc)acme_filter_events, - manager); - mate_settings_profile_end ("gdk_window_add_filter"); - } - - mate_settings_profile_end (NULL); - - return FALSE; -} - -gboolean -msd_media_keys_manager_start (MsdMediaKeysManager *manager, - GError **error) -{ - mate_settings_profile_start (NULL); - -#ifdef HAVE_PULSE - /* initialise Volume handler - * - * We do this one here to force checking gstreamer cache, etc. - * The rest (grabbing and setting the keys) can happen in an - * idle. - */ - mate_settings_profile_start ("gvc_mixer_control_new"); - - manager->priv->volume = gvc_mixer_control_new ("MATE Volume Control Media Keys"); - - g_signal_connect (manager->priv->volume, - "ready", - G_CALLBACK (on_control_ready), - manager); - g_signal_connect (manager->priv->volume, - "default-sink-changed", - G_CALLBACK (on_control_default_sink_changed), - manager); - - gvc_mixer_control_open (manager->priv->volume); - - mate_settings_profile_end ("gvc_mixer_control_new"); -#elif defined(HAVE_GSTREAMER) - mate_settings_profile_start ("acme_volume_new"); - manager->priv->volume = acme_volume_new (); - mate_settings_profile_end ("acme_volume_new"); -#endif /* HAVE_PULSE */ - g_idle_add ((GSourceFunc) start_media_keys_idle_cb, manager); - - mate_settings_profile_end (NULL); - - return TRUE; -} - -void -msd_media_keys_manager_stop (MsdMediaKeysManager *manager) -{ - MsdMediaKeysManagerPrivate *priv = manager->priv; - GSList *ls; - GList *l; - int i; - gboolean need_flush; - - g_debug ("Stopping media_keys manager"); - - for (ls = priv->screens; ls != NULL; ls = ls->next) { - gdk_window_remove_filter (gdk_screen_get_root_window (ls->data), - (GdkFilterFunc) acme_filter_events, - manager); - } - - if (priv->conf_client) { - mateconf_client_remove_dir (priv->conf_client, - MATECONF_BINDING_DIR, - NULL); - - for (i = 0; i < HANDLED_KEYS; ++i) { - if (priv->notify[i] != 0) { - mateconf_client_notify_remove (priv->conf_client, priv->notify[i]); - priv->notify[i] = 0; - } - } - - g_object_unref (priv->conf_client); - priv->conf_client = NULL; - } - - if (priv->volume_monitor != NULL) { - g_object_unref (priv->volume_monitor); - priv->volume_monitor = NULL; - } - - if (priv->connection != NULL) { - dbus_g_connection_unref (priv->connection); - priv->connection = NULL; - } - - need_flush = FALSE; - gdk_error_trap_push (); - - for (i = 0; i < HANDLED_KEYS; ++i) { - if (keys[i].key) { - need_flush = TRUE; - grab_key_unsafe (keys[i].key, FALSE, priv->screens); - - g_free (keys[i].key->keycodes); - g_free (keys[i].key); - keys[i].key = NULL; - } - } - - if (need_flush) - gdk_flush (); - gdk_error_trap_pop (); - - g_slist_free (priv->screens); - priv->screens = NULL; - -#ifdef HAVE_PULSE - if (priv->stream) { - g_object_unref (priv->stream); - priv->stream = NULL; - } -#endif /* HAVE_PULSE */ - -#if defined(HAVE_PULSE) || defined(HAVE_GSTREAMER) - if (priv->volume) { - g_object_unref (priv->volume); - priv->volume = NULL; - } -#endif /* defined(HAVE_PULSE) || defined(HAVE_GSTREAMER) */ - - if (priv->dialog != NULL) { - gtk_widget_destroy (priv->dialog); - priv->dialog = NULL; - } - - for (l = priv->media_players; l; l = l->next) { - MediaPlayer *mp = l->data; - g_free (mp->application); - g_free (mp); - } - g_list_free (priv->media_players); - priv->media_players = NULL; -} - -static void -msd_media_keys_manager_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MsdMediaKeysManager *self; - - self = MSD_MEDIA_KEYS_MANAGER (object); - - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -msd_media_keys_manager_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MsdMediaKeysManager *self; - - self = MSD_MEDIA_KEYS_MANAGER (object); - - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GObject * -msd_media_keys_manager_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_properties) -{ - MsdMediaKeysManager *media_keys_manager; - MsdMediaKeysManagerClass *klass; - - klass = MSD_MEDIA_KEYS_MANAGER_CLASS (g_type_class_peek (MSD_TYPE_MEDIA_KEYS_MANAGER)); - - media_keys_manager = MSD_MEDIA_KEYS_MANAGER (G_OBJECT_CLASS (msd_media_keys_manager_parent_class)->constructor (type, - n_construct_properties, - construct_properties)); - - return G_OBJECT (media_keys_manager); -} - -static void -msd_media_keys_manager_dispose (GObject *object) -{ - MsdMediaKeysManager *media_keys_manager; - - media_keys_manager = MSD_MEDIA_KEYS_MANAGER (object); - - G_OBJECT_CLASS (msd_media_keys_manager_parent_class)->dispose (object); -} - -static void -msd_media_keys_manager_class_init (MsdMediaKeysManagerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = msd_media_keys_manager_get_property; - object_class->set_property = msd_media_keys_manager_set_property; - object_class->constructor = msd_media_keys_manager_constructor; - object_class->dispose = msd_media_keys_manager_dispose; - object_class->finalize = msd_media_keys_manager_finalize; - - signals[MEDIA_PLAYER_KEY_PRESSED] = - g_signal_new ("media-player-key-pressed", - G_OBJECT_CLASS_TYPE (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (MsdMediaKeysManagerClass, media_player_key_pressed), - NULL, - NULL, - msd_marshal_VOID__STRING_STRING, - G_TYPE_NONE, - 2, - G_TYPE_STRING, - G_TYPE_STRING); - - dbus_g_object_type_install_info (MSD_TYPE_MEDIA_KEYS_MANAGER, &dbus_glib_msd_media_keys_manager_object_info); - - g_type_class_add_private (klass, sizeof (MsdMediaKeysManagerPrivate)); -} - -static void -msd_media_keys_manager_init (MsdMediaKeysManager *manager) -{ - manager->priv = MSD_MEDIA_KEYS_MANAGER_GET_PRIVATE (manager); - -} - -static void -msd_media_keys_manager_finalize (GObject *object) -{ - MsdMediaKeysManager *media_keys_manager; - - g_return_if_fail (object != NULL); - g_return_if_fail (MSD_IS_MEDIA_KEYS_MANAGER (object)); - - media_keys_manager = MSD_MEDIA_KEYS_MANAGER (object); - - g_return_if_fail (media_keys_manager->priv != NULL); - - G_OBJECT_CLASS (msd_media_keys_manager_parent_class)->finalize (object); -} - -static gboolean -register_manager (MsdMediaKeysManager *manager) -{ - GError *error = NULL; - - manager->priv->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); - if (manager->priv->connection == NULL) { - if (error != NULL) { - g_error ("Error getting session bus: %s", error->message); - g_error_free (error); - } - return FALSE; - } - - dbus_g_connection_register_g_object (manager->priv->connection, MSD_MEDIA_KEYS_DBUS_PATH, G_OBJECT (manager)); - - return TRUE; -} - -MsdMediaKeysManager * -msd_media_keys_manager_new (void) -{ - if (manager_object != NULL) { - g_object_ref (manager_object); - } else { - gboolean res; - - manager_object = g_object_new (MSD_TYPE_MEDIA_KEYS_MANAGER, NULL); - g_object_add_weak_pointer (manager_object, - (gpointer *) &manager_object); - res = register_manager (manager_object); - if (! res) { - g_object_unref (manager_object); - return NULL; - } - } - - return MSD_MEDIA_KEYS_MANAGER (manager_object); -} diff --git a/plugins/media-keys/gsd-media-keys-manager.h b/plugins/media-keys/gsd-media-keys-manager.h deleted file mode 100644 index 96c135f..0000000 --- a/plugins/media-keys/gsd-media-keys-manager.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2007 William Jon McCann - * - * 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef __MSD_MEDIA_KEYS_MANAGER_H -#define __MSD_MEDIA_KEYS_MANAGER_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define MSD_TYPE_MEDIA_KEYS_MANAGER (msd_media_keys_manager_get_type ()) -#define MSD_MEDIA_KEYS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MSD_TYPE_MEDIA_KEYS_MANAGER, MsdMediaKeysManager)) -#define MSD_MEDIA_KEYS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), MSD_TYPE_MEDIA_KEYS_MANAGER, MsdMediaKeysManagerClass)) -#define MSD_IS_MEDIA_KEYS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MSD_TYPE_MEDIA_KEYS_MANAGER)) -#define MSD_IS_MEDIA_KEYS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), MSD_TYPE_MEDIA_KEYS_MANAGER)) -#define MSD_MEDIA_KEYS_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), MSD_TYPE_MEDIA_KEYS_MANAGER, MsdMediaKeysManagerClass)) - -typedef struct MsdMediaKeysManagerPrivate MsdMediaKeysManagerPrivate; - -typedef struct -{ - GObject parent; - MsdMediaKeysManagerPrivate *priv; -} MsdMediaKeysManager; - -typedef struct -{ - GObjectClass parent_class; - void (* media_player_key_pressed) (MsdMediaKeysManager *manager, - const char *application, - const char *key); -} MsdMediaKeysManagerClass; - -GType msd_media_keys_manager_get_type (void); - -MsdMediaKeysManager * msd_media_keys_manager_new (void); -gboolean msd_media_keys_manager_start (MsdMediaKeysManager *manager, - GError **error); -void msd_media_keys_manager_stop (MsdMediaKeysManager *manager); - -gboolean msd_media_keys_manager_grab_media_player_keys (MsdMediaKeysManager *manager, - const char *application, - guint32 time, - GError **error); -gboolean msd_media_keys_manager_release_media_player_keys (MsdMediaKeysManager *manager, - const char *application, - GError **error); - -#ifdef __cplusplus -} -#endif - -#endif /* __MSD_MEDIA_KEYS_MANAGER_H */ diff --git a/plugins/media-keys/gsd-media-keys-manager.xml b/plugins/media-keys/gsd-media-keys-manager.xml deleted file mode 100644 index db0552e..0000000 --- a/plugins/media-keys/gsd-media-keys-manager.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/plugins/media-keys/gsd-media-keys-plugin.c b/plugins/media-keys/gsd-media-keys-plugin.c deleted file mode 100644 index d76e233..0000000 --- a/plugins/media-keys/gsd-media-keys-plugin.c +++ /dev/null @@ -1,104 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2007 William Jon McCann - * - * 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 2, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "config.h" - -#include -#include - -#include "mate-settings-plugin.h" -#include "msd-media-keys-plugin.h" -#include "msd-media-keys-manager.h" - -struct MsdMediaKeysPluginPrivate { - MsdMediaKeysManager *manager; -}; - -#define MSD_MEDIA_KEYS_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), MSD_TYPE_MEDIA_KEYS_PLUGIN, MsdMediaKeysPluginPrivate)) - -MATE_SETTINGS_PLUGIN_REGISTER (MsdMediaKeysPlugin, msd_media_keys_plugin) - -static void -msd_media_keys_plugin_init (MsdMediaKeysPlugin *plugin) -{ - plugin->priv = MSD_MEDIA_KEYS_PLUGIN_GET_PRIVATE (plugin); - - g_debug ("MsdMediaKeysPlugin initializing"); - - plugin->priv->manager = msd_media_keys_manager_new (); -} - -static void -msd_media_keys_plugin_finalize (GObject *object) -{ - MsdMediaKeysPlugin *plugin; - - g_return_if_fail (object != NULL); - g_return_if_fail (MSD_IS_MEDIA_KEYS_PLUGIN (object)); - - g_debug ("MsdMediaKeysPlugin finalizing"); - - plugin = MSD_MEDIA_KEYS_PLUGIN (object); - - g_return_if_fail (plugin->priv != NULL); - - if (plugin->priv->manager != NULL) { - g_object_unref (plugin->priv->manager); - } - - G_OBJECT_CLASS (msd_media_keys_plugin_parent_class)->finalize (object); -} - -static void -impl_activate (MateSettingsPlugin *plugin) -{ - gboolean res; - GError *error; - - g_debug ("Activating media_keys plugin"); - - error = NULL; - res = msd_media_keys_manager_start (MSD_MEDIA_KEYS_PLUGIN (plugin)->priv->manager, &error); - if (! res) { - g_warning ("Unable to start media_keys manager: %s", error->message); - g_error_free (error); - } -} - -static void -impl_deactivate (MateSettingsPlugin *plugin) -{ - g_debug ("Deactivating media_keys plugin"); - msd_media_keys_manager_stop (MSD_MEDIA_KEYS_PLUGIN (plugin)->priv->manager); -} - -static void -msd_media_keys_plugin_class_init (MsdMediaKeysPluginClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass); - - object_class->finalize = msd_media_keys_plugin_finalize; - - plugin_class->activate = impl_activate; - plugin_class->deactivate = impl_deactivate; - - g_type_class_add_private (klass, sizeof (MsdMediaKeysPluginPrivate)); -} diff --git a/plugins/media-keys/gsd-media-keys-plugin.h b/plugins/media-keys/gsd-media-keys-plugin.h deleted file mode 100644 index c869d62..0000000 --- a/plugins/media-keys/gsd-media-keys-plugin.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2007 William Jon McCann - * - * 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 2, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef __MSD_MEDIA_KEYS_PLUGIN_H__ -#define __MSD_MEDIA_KEYS_PLUGIN_H__ - -#include -#include -#include - -#include "mate-settings-plugin.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define MSD_TYPE_MEDIA_KEYS_PLUGIN (msd_media_keys_plugin_get_type ()) -#define MSD_MEDIA_KEYS_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MSD_TYPE_MEDIA_KEYS_PLUGIN, MsdMediaKeysPlugin)) -#define MSD_MEDIA_KEYS_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), MSD_TYPE_MEDIA_KEYS_PLUGIN, MsdMediaKeysPluginClass)) -#define MSD_IS_MEDIA_KEYS_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MSD_TYPE_MEDIA_KEYS_PLUGIN)) -#define MSD_IS_MEDIA_KEYS_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), MSD_TYPE_MEDIA_KEYS_PLUGIN)) -#define MSD_MEDIA_KEYS_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), MSD_TYPE_MEDIA_KEYS_PLUGIN, MsdMediaKeysPluginClass)) - -typedef struct MsdMediaKeysPluginPrivate MsdMediaKeysPluginPrivate; - -typedef struct -{ - MateSettingsPlugin parent; - MsdMediaKeysPluginPrivate *priv; -} MsdMediaKeysPlugin; - -typedef struct -{ - MateSettingsPluginClass parent_class; -} MsdMediaKeysPluginClass; - -GType msd_media_keys_plugin_get_type (void) G_GNUC_CONST; - -/* All the plugins must implement this function */ -G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module); - -#ifdef __cplusplus -} -#endif - -#endif /* __MSD_MEDIA_KEYS_PLUGIN_H__ */ diff --git a/plugins/media-keys/gsd-media-keys-window.c b/plugins/media-keys/gsd-media-keys-window.c deleted file mode 100644 index 8bd6c33..0000000 --- a/plugins/media-keys/gsd-media-keys-window.c +++ /dev/null @@ -1,714 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2006-2007 William Jon McCann - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2, 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 Lesser General Public License for more - * details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include - -#include "msd-media-keys-window.h" - -#define MSD_MEDIA_KEYS_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MSD_TYPE_MEDIA_KEYS_WINDOW, MsdMediaKeysWindowPrivate)) - -struct MsdMediaKeysWindowPrivate -{ - MsdMediaKeysWindowAction action; - char *icon_name; - gboolean show_level; - - guint volume_muted : 1; - int volume_level; - - GtkImage *image; - GtkWidget *progress; -}; - -G_DEFINE_TYPE (MsdMediaKeysWindow, msd_media_keys_window, MSD_TYPE_OSD_WINDOW) - -static void -volume_controls_set_visible (MsdMediaKeysWindow *window, - gboolean visible) -{ - if (window->priv->progress == NULL) - return; - - if (visible) { - gtk_widget_show (window->priv->progress); - } else { - gtk_widget_hide (window->priv->progress); - } -} - -static void -window_set_icon_name (MsdMediaKeysWindow *window, - const char *name) -{ - if (window->priv->image == NULL) - return; - - gtk_image_set_from_icon_name (window->priv->image, - name, GTK_ICON_SIZE_DIALOG); -} - -static void -action_changed (MsdMediaKeysWindow *window) -{ - if (!msd_osd_window_is_composited (MSD_OSD_WINDOW (window))) { - switch (window->priv->action) { - case MSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME: - volume_controls_set_visible (window, TRUE); - - if (window->priv->volume_muted) { - window_set_icon_name (window, "audio-volume-muted"); - } else { - window_set_icon_name (window, "audio-volume-high"); - } - - break; - case MSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM: - volume_controls_set_visible (window, window->priv->show_level); - window_set_icon_name (window, window->priv->icon_name); - break; - default: - g_assert_not_reached (); - break; - } - } - - msd_osd_window_update_and_hide (MSD_OSD_WINDOW (window)); -} - -static void -volume_level_changed (MsdMediaKeysWindow *window) -{ - msd_osd_window_update_and_hide (MSD_OSD_WINDOW (window)); - - if (!msd_osd_window_is_composited (MSD_OSD_WINDOW (window)) && window->priv->progress != NULL) { - double fraction; - - fraction = (double) window->priv->volume_level / 100.0; - - gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (window->priv->progress), - fraction); - } -} - -static void -volume_muted_changed (MsdMediaKeysWindow *window) -{ - msd_osd_window_update_and_hide (MSD_OSD_WINDOW (window)); - - if (!msd_osd_window_is_composited (MSD_OSD_WINDOW (window))) { - if (window->priv->volume_muted) { - window_set_icon_name (window, "audio-volume-muted"); - } else { - window_set_icon_name (window, "audio-volume-high"); - } - } -} - -void -msd_media_keys_window_set_action (MsdMediaKeysWindow *window, - MsdMediaKeysWindowAction action) -{ - g_return_if_fail (MSD_IS_MEDIA_KEYS_WINDOW (window)); - g_return_if_fail (action == MSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME); - - if (window->priv->action != action) { - window->priv->action = action; - action_changed (window); - } else { - msd_osd_window_update_and_hide (MSD_OSD_WINDOW (window)); - } -} - -void -msd_media_keys_window_set_action_custom (MsdMediaKeysWindow *window, - const char *icon_name, - gboolean show_level) -{ - g_return_if_fail (MSD_IS_MEDIA_KEYS_WINDOW (window)); - g_return_if_fail (icon_name != NULL); - - if (window->priv->action != MSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM || - g_strcmp0 (window->priv->icon_name, icon_name) != 0 || - window->priv->show_level != show_level) { - window->priv->action = MSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM; - g_free (window->priv->icon_name); - window->priv->icon_name = g_strdup (icon_name); - window->priv->show_level = show_level; - action_changed (window); - } else { - msd_osd_window_update_and_hide (MSD_OSD_WINDOW (window)); - } -} - -void -msd_media_keys_window_set_volume_muted (MsdMediaKeysWindow *window, - gboolean muted) -{ - g_return_if_fail (MSD_IS_MEDIA_KEYS_WINDOW (window)); - - if (window->priv->volume_muted != muted) { - window->priv->volume_muted = muted; - volume_muted_changed (window); - } -} - -void -msd_media_keys_window_set_volume_level (MsdMediaKeysWindow *window, - int level) -{ - g_return_if_fail (MSD_IS_MEDIA_KEYS_WINDOW (window)); - - if (window->priv->volume_level != level) { - window->priv->volume_level = level; - volume_level_changed (window); - } -} - -static GdkPixbuf * -load_pixbuf (MsdMediaKeysWindow *window, - const char *name, - int icon_size) -{ - GtkIconTheme *theme; - GdkPixbuf *pixbuf; - - if (window != NULL && gtk_widget_has_screen (GTK_WIDGET (window))) { - theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window))); - } else { - theme = gtk_icon_theme_get_default (); - } - - pixbuf = gtk_icon_theme_load_icon (theme, - name, - icon_size, - GTK_ICON_LOOKUP_FORCE_SIZE, - NULL); - - return pixbuf; -} - -static void -draw_eject (cairo_t *cr, - double _x0, - double _y0, - double width, - double height) -{ - int box_height; - int tri_height; - int separation; - - box_height = height * 0.2; - separation = box_height / 3; - tri_height = height - box_height - separation; - - cairo_rectangle (cr, _x0, _y0 + height - box_height, width, box_height); - - cairo_move_to (cr, _x0, _y0 + tri_height); - cairo_rel_line_to (cr, width, 0); - cairo_rel_line_to (cr, -width / 2, -tri_height); - cairo_rel_line_to (cr, -width / 2, tri_height); - cairo_close_path (cr); - cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, MSD_OSD_WINDOW_FG_ALPHA); - cairo_fill_preserve (cr); - - cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, MSD_OSD_WINDOW_FG_ALPHA / 2); - cairo_set_line_width (cr, 2); - cairo_stroke (cr); -} - -static void -draw_waves (cairo_t *cr, - double cx, - double cy, - double max_radius, - int volume_level) -{ - const int n_waves = 3; - int last_wave; - int i; - - last_wave = n_waves * volume_level / 100; - - for (i = 0; i < n_waves; i++) { - double angle1; - double angle2; - double radius; - double alpha; - - angle1 = -M_PI / 4; - angle2 = M_PI / 4; - - if (i < last_wave) - alpha = 1.0; - else if (i > last_wave) - alpha = 0.1; - else alpha = 0.1 + 0.9 * (n_waves * volume_level % 100) / 100.0; - - radius = (i + 1) * (max_radius / n_waves); - cairo_arc (cr, cx, cy, radius, angle1, angle2); - cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, alpha / 2); - cairo_set_line_width (cr, 14); - cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); - cairo_stroke_preserve (cr); - - cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, alpha); - cairo_set_line_width (cr, 10); - cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); - cairo_stroke (cr); - } -} - -static void -draw_cross (cairo_t *cr, - double cx, - double cy, - double size) -{ - cairo_move_to (cr, cx, cy - size/2.0); - cairo_rel_line_to (cr, size, size); - - cairo_move_to (cr, cx, cy + size/2.0); - cairo_rel_line_to (cr, size, -size); - - cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, MSD_OSD_WINDOW_FG_ALPHA / 2); - cairo_set_line_width (cr, 14); - cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); - cairo_stroke_preserve (cr); - - cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, MSD_OSD_WINDOW_FG_ALPHA); - cairo_set_line_width (cr, 10); - cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); - cairo_stroke (cr); -} - -static void -draw_speaker (cairo_t *cr, - double cx, - double cy, - double width, - double height) -{ - double box_width; - double box_height; - double _x0; - double _y0; - - box_width = width / 3; - box_height = height / 3; - - _x0 = cx - (width / 2) + box_width; - _y0 = cy - box_height / 2; - - cairo_move_to (cr, _x0, _y0); - cairo_rel_line_to (cr, - box_width, 0); - cairo_rel_line_to (cr, 0, box_height); - cairo_rel_line_to (cr, box_width, 0); - - cairo_line_to (cr, cx + box_width, cy + height / 2); - cairo_rel_line_to (cr, 0, -height); - cairo_line_to (cr, _x0, _y0); - cairo_close_path (cr); - - cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, MSD_OSD_WINDOW_FG_ALPHA); - cairo_fill_preserve (cr); - - cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, MSD_OSD_WINDOW_FG_ALPHA / 2); - cairo_set_line_width (cr, 2); - cairo_stroke (cr); -} - -static gboolean -render_speaker (MsdMediaKeysWindow *window, - cairo_t *cr, - double _x0, - double _y0, - double width, - double height) -{ - GdkPixbuf *pixbuf; - int icon_size; - int n; - static const char *icon_names[] = { - "audio-volume-muted", - "audio-volume-low", - "audio-volume-medium", - "audio-volume-high", - NULL - }; - - if (window->priv->volume_muted) { - n = 0; - } else { - /* select image */ - n = 3 * window->priv->volume_level / 100 + 1; - if (n < 1) { - n = 1; - } else if (n > 3) { - n = 3; - } - } - - icon_size = (int)width; - - pixbuf = load_pixbuf (window, icon_names[n], icon_size); - - if (pixbuf == NULL) { - return FALSE; - } - - gdk_cairo_set_source_pixbuf (cr, pixbuf, _x0, _y0); - cairo_paint_with_alpha (cr, MSD_OSD_WINDOW_FG_ALPHA); - - g_object_unref (pixbuf); - - return TRUE; -} - -static void -draw_volume_boxes (MsdMediaKeysWindow *window, - cairo_t *cr, - double percentage, - double _x0, - double _y0, - double width, - double height) -{ - gdouble x1; - GdkColor color; - double r, g, b; - GtkStyle *style; - - _x0 += 0.5; - _y0 += 0.5; - height = round (height) - 1; - width = round (width) - 1; - x1 = round ((width - 1) * percentage); - style = gtk_widget_get_style (GTK_WIDGET (window)); - - /* bar background */ - msd_osd_window_color_reverse (&style->dark[GTK_STATE_NORMAL], &color); - r = (float)color.red / 65535.0; - g = (float)color.green / 65535.0; - b = (float)color.blue / 65535.0; - msd_osd_window_draw_rounded_rectangle (cr, 1.0, _x0, _y0, height / 6, width, height); - cairo_set_source_rgba (cr, r, g, b, MSD_OSD_WINDOW_FG_ALPHA / 2); - cairo_fill_preserve (cr); - - /* bar border */ - msd_osd_window_color_reverse (&style->light[GTK_STATE_NORMAL], &color); - r = (float)color.red / 65535.0; - g = (float)color.green / 65535.0; - b = (float)color.blue / 65535.0; - cairo_set_source_rgba (cr, r, g, b, MSD_OSD_WINDOW_FG_ALPHA / 2); - cairo_set_line_width (cr, 1); - cairo_stroke (cr); - - /* bar progress */ - if (percentage < 0.01) - return; - color = style->bg[GTK_STATE_NORMAL]; - r = (float)color.red / 65535.0; - g = (float)color.green / 65535.0; - b = (float)color.blue / 65535.0; - msd_osd_window_draw_rounded_rectangle (cr, 1.0, _x0 + 0.5, _y0 + 0.5, height / 6 - 0.5, x1, height - 1); - cairo_set_source_rgba (cr, r, g, b, MSD_OSD_WINDOW_FG_ALPHA); - cairo_fill (cr); -} - -static void -draw_action_volume (MsdMediaKeysWindow *window, - cairo_t *cr) -{ - int window_width; - int window_height; - double icon_box_width; - double icon_box_height; - double icon_box_x0; - double icon_box_y0; - double volume_box_x0; - double volume_box_y0; - double volume_box_width; - double volume_box_height; - gboolean res; - - gtk_window_get_size (GTK_WINDOW (window), &window_width, &window_height); - - icon_box_width = round (window_width * 0.65); - icon_box_height = round (window_height * 0.65); - volume_box_width = icon_box_width; - volume_box_height = round (window_height * 0.05); - - icon_box_x0 = (window_width - icon_box_width) / 2; - icon_box_y0 = (window_height - icon_box_height - volume_box_height) / 2; - volume_box_x0 = round (icon_box_x0); - volume_box_y0 = round (icon_box_height + icon_box_y0); - -#if 0 - g_message ("icon box: w=%f h=%f _x0=%f _y0=%f", - icon_box_width, - icon_box_height, - icon_box_x0, - icon_box_y0); - g_message ("volume box: w=%f h=%f _x0=%f _y0=%f", - volume_box_width, - volume_box_height, - volume_box_x0, - volume_box_y0); -#endif - - res = render_speaker (window, - cr, - icon_box_x0, icon_box_y0, - icon_box_width, icon_box_height); - if (! res) { - double speaker_width; - double speaker_height; - double speaker_cx; - double speaker_cy; - - speaker_width = icon_box_width * 0.5; - speaker_height = icon_box_height * 0.75; - speaker_cx = icon_box_x0 + speaker_width / 2; - speaker_cy = icon_box_y0 + speaker_height / 2; - -#if 0 - g_message ("speaker box: w=%f h=%f cx=%f cy=%f", - speaker_width, - speaker_height, - speaker_cx, - speaker_cy); -#endif - - /* draw speaker symbol */ - draw_speaker (cr, speaker_cx, speaker_cy, speaker_width, speaker_height); - - if (! window->priv->volume_muted) { - /* draw sound waves */ - double wave_x0; - double wave_y0; - double wave_radius; - - wave_x0 = window_width / 2; - wave_y0 = speaker_cy; - wave_radius = icon_box_width / 2; - - draw_waves (cr, wave_x0, wave_y0, wave_radius, window->priv->volume_level); - } else { - /* draw 'mute' cross */ - double cross_x0; - double cross_y0; - double cross_size; - - cross_size = speaker_width * 3 / 4; - cross_x0 = icon_box_x0 + icon_box_width - cross_size; - cross_y0 = speaker_cy; - - draw_cross (cr, cross_x0, cross_y0, cross_size); - } - } - - /* draw volume meter */ - draw_volume_boxes (window, - cr, - (double)window->priv->volume_level / 100.0, - volume_box_x0, - volume_box_y0, - volume_box_width, - volume_box_height); -} - -static gboolean -render_custom (MsdMediaKeysWindow *window, - cairo_t *cr, - double _x0, - double _y0, - double width, - double height) -{ - GdkPixbuf *pixbuf; - int icon_size; - - icon_size = (int)width; - - pixbuf = load_pixbuf (window, window->priv->icon_name, icon_size); - - if (pixbuf == NULL) { - char *name; - if (gtk_widget_get_direction (GTK_WIDGET (window)) == GTK_TEXT_DIR_RTL) - name = g_strdup_printf ("%s-rtl", window->priv->icon_name); - else - name = g_strdup_printf ("%s-ltr", window->priv->icon_name); - pixbuf = load_pixbuf (window, name, icon_size); - g_free (name); - if (pixbuf == NULL) - return FALSE; - } - - gdk_cairo_set_source_pixbuf (cr, pixbuf, _x0, _y0); - cairo_paint_with_alpha (cr, MSD_OSD_WINDOW_FG_ALPHA); - - g_object_unref (pixbuf); - - return TRUE; -} - -static void -draw_action_custom (MsdMediaKeysWindow *window, - cairo_t *cr) -{ - int window_width; - int window_height; - double icon_box_width; - double icon_box_height; - double icon_box_x0; - double icon_box_y0; - double bright_box_x0; - double bright_box_y0; - double bright_box_width; - double bright_box_height; - gboolean res; - - gtk_window_get_size (GTK_WINDOW (window), &window_width, &window_height); - - icon_box_width = round (window_width * 0.65); - icon_box_height = round (window_height * 0.65); - bright_box_width = round (icon_box_width); - bright_box_height = round (window_height * 0.05); - - icon_box_x0 = (window_width - icon_box_width) / 2; - icon_box_y0 = (window_height - icon_box_height - bright_box_height) / 2; - bright_box_x0 = round (icon_box_x0); - bright_box_y0 = round (icon_box_height + icon_box_y0); - -#if 0 - g_message ("icon box: w=%f h=%f _x0=%f _y0=%f", - icon_box_width, - icon_box_height, - icon_box_x0, - icon_box_y0); - g_message ("brightness box: w=%f h=%f _x0=%f _y0=%f", - bright_box_width, - bright_box_height, - bright_box_x0, - bright_box_y0); -#endif - - res = render_custom (window, - cr, - icon_box_x0, icon_box_y0, - icon_box_width, icon_box_height); - if (! res && g_strcmp0 (window->priv->icon_name, "media-eject") == 0) { - /* draw eject symbol */ - draw_eject (cr, - icon_box_x0, icon_box_y0, - icon_box_width, icon_box_height); - } - - if (window->priv->show_level != FALSE) { - /* draw volume meter */ - draw_volume_boxes (window, - cr, - (double)window->priv->volume_level / 100.0, - bright_box_x0, - bright_box_y0, - bright_box_width, - bright_box_height); - } -} - -static void -msd_media_keys_window_expose_when_composited (MsdOsdWindow *osd_window, - cairo_t *cr) -{ - MsdMediaKeysWindow *window = MSD_MEDIA_KEYS_WINDOW (osd_window); - - switch (window->priv->action) { - case MSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME: - draw_action_volume (window, cr); - break; - case MSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM: - draw_action_custom (window, cr); - break; - default: - break; - } -} - -static void -msd_media_keys_window_class_init (MsdMediaKeysWindowClass *klass) -{ - MsdOsdWindowClass *osd_window_class = MSD_OSD_WINDOW_CLASS (klass); - - osd_window_class->expose_when_composited = msd_media_keys_window_expose_when_composited; - - g_type_class_add_private (klass, sizeof (MsdMediaKeysWindowPrivate)); -} - -static void -msd_media_keys_window_init (MsdMediaKeysWindow *window) -{ - GdkScreen *screen; - - window->priv = MSD_MEDIA_KEYS_WINDOW_GET_PRIVATE (window); - - screen = gtk_widget_get_screen (GTK_WIDGET (window)); - - if (!msd_osd_window_is_composited (MSD_OSD_WINDOW (window))) { - GtkBuilder *builder; - const gchar *objects[] = {"acme_box", NULL}; - GtkWidget *box; - - builder = gtk_builder_new (); - gtk_builder_add_objects_from_file (builder, - GTKBUILDERDIR "/acme.ui", - (char **) objects, - NULL); - - window->priv->image = GTK_IMAGE (gtk_builder_get_object (builder, "acme_image")); - window->priv->progress = GTK_WIDGET (gtk_builder_get_object (builder, "acme_volume_progressbar")); - box = GTK_WIDGET (gtk_builder_get_object (builder, "acme_box")); - - if (box != NULL) { - gtk_container_add (GTK_CONTAINER (window), box); - gtk_widget_show_all (box); - } - - /* The builder needs to stay alive until the window - takes ownership of the box (and its children) */ - g_object_unref (builder); - } -} - -GtkWidget * -msd_media_keys_window_new (void) -{ - return g_object_new (MSD_TYPE_MEDIA_KEYS_WINDOW, NULL); -} diff --git a/plugins/media-keys/gsd-media-keys-window.h b/plugins/media-keys/gsd-media-keys-window.h deleted file mode 100644 index c0e5739..0000000 --- a/plugins/media-keys/gsd-media-keys-window.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8; tab-width: 8 -*- - * - * Copyright (C) 2006 William Jon McCann - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2, 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 Lesser General Public License for more - * details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef MSD_MEDIA_KEYS_WINDOW_H -#define MSD_MEDIA_KEYS_WINDOW_H - -#include -#include - -#include "msd-osd-window.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define MSD_TYPE_MEDIA_KEYS_WINDOW (msd_media_keys_window_get_type ()) -#define MSD_MEDIA_KEYS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MSD_TYPE_MEDIA_KEYS_WINDOW, MsdMediaKeysWindow)) -#define MSD_MEDIA_KEYS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MSD_TYPE_MEDIA_KEYS_WINDOW, MsdMediaKeysWindowClass)) -#define MSD_IS_MEDIA_KEYS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MSD_TYPE_MEDIA_KEYS_WINDOW)) -#define MSD_IS_MEDIA_KEYS_WINDOW_CLASS(klass) (G_TYPE_INSTANCE_GET_CLASS ((klass), MSD_TYPE_MEDIA_KEYS_WINDOW)) - -typedef struct MsdMediaKeysWindow MsdMediaKeysWindow; -typedef struct MsdMediaKeysWindowClass MsdMediaKeysWindowClass; -typedef struct MsdMediaKeysWindowPrivate MsdMediaKeysWindowPrivate; - -struct MsdMediaKeysWindow { - MsdOsdWindow parent; - - MsdMediaKeysWindowPrivate *priv; -}; - -struct MsdMediaKeysWindowClass { - MsdOsdWindowClass parent_class; -}; - -typedef enum { - MSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME, - MSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM -} MsdMediaKeysWindowAction; - -GType msd_media_keys_window_get_type (void); - -GtkWidget * msd_media_keys_window_new (void); -void msd_media_keys_window_set_action (MsdMediaKeysWindow *window, - MsdMediaKeysWindowAction action); -void msd_media_keys_window_set_action_custom (MsdMediaKeysWindow *window, - const char *icon_name, - gboolean show_level); -void msd_media_keys_window_set_volume_muted (MsdMediaKeysWindow *window, - gboolean muted); -void msd_media_keys_window_set_volume_level (MsdMediaKeysWindow *window, - int level); -gboolean msd_media_keys_window_is_valid (MsdMediaKeysWindow *window); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/plugins/media-keys/msd-marshal.list b/plugins/media-keys/msd-marshal.list new file mode 100644 index 0000000..72f9937 --- /dev/null +++ b/plugins/media-keys/msd-marshal.list @@ -0,0 +1 @@ +VOID:STRING,STRING diff --git a/plugins/media-keys/msd-media-keys-manager.c b/plugins/media-keys/msd-media-keys-manager.c new file mode 100644 index 0000000..d7e1b04 --- /dev/null +++ b/plugins/media-keys/msd-media-keys-manager.c @@ -0,0 +1,1447 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2001-2003 Bastien Nocera + * Copyright (C) 2006-2007 William Jon McCann + * + * 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "mate-settings-profile.h" +#include "msd-marshal.h" +#include "msd-media-keys-manager.h" +#include "msd-media-keys-manager-glue.h" + +#include "eggaccelerators.h" +#include "acme.h" +#include "msd-media-keys-window.h" + +#ifdef HAVE_PULSE +#include +#include "gvc-mixer-control.h" +#elif defined(HAVE_GSTREAMER) +#include "gvc-gstreamer-acme-vol.h" +#endif /* HAVE_PULSE */ + +#define MSD_DBUS_PATH "/org/mate/SettingsDaemon" +#define MSD_DBUS_NAME "org.mate.SettingsDaemon" +#define MSD_MEDIA_KEYS_DBUS_PATH MSD_DBUS_PATH "/MediaKeys" +#define MSD_MEDIA_KEYS_DBUS_NAME MSD_DBUS_NAME ".MediaKeys" + +#define TOUCHPAD_ENABLED_KEY "/desktop/mate/peripherals/touchpad/touchpad_enabled" + +#define VOLUME_STEP 6 /* percents for one volume button press */ +#define MAX_VOLUME 65536.0 + +#define MSD_MEDIA_KEYS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MSD_TYPE_MEDIA_KEYS_MANAGER, MsdMediaKeysManagerPrivate)) + +typedef struct { + char *application; + guint32 time; +} MediaPlayer; + +struct MsdMediaKeysManagerPrivate +{ +#ifdef HAVE_PULSE + /* Volume bits */ + GvcMixerControl *volume; + GvcMixerStream *stream; +#elif defined(HAVE_GSTREAMER) + AcmeVolume *volume; +#endif /* HAVE_PULSE */ + GtkWidget *dialog; + MateConfClient *conf_client; + GVolumeMonitor *volume_monitor; + + /* Multihead stuff */ + GdkScreen *current_screen; + GSList *screens; + + GList *media_players; + + DBusGConnection *connection; + guint notify[HANDLED_KEYS]; +}; + +enum { + MEDIA_PLAYER_KEY_PRESSED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static void msd_media_keys_manager_class_init (MsdMediaKeysManagerClass *klass); +static void msd_media_keys_manager_init (MsdMediaKeysManager *media_keys_manager); +static void msd_media_keys_manager_finalize (GObject *object); + +G_DEFINE_TYPE (MsdMediaKeysManager, msd_media_keys_manager, G_TYPE_OBJECT) + +static gpointer manager_object = NULL; + + +static void +init_screens (MsdMediaKeysManager *manager) +{ + GdkDisplay *display; + int i; + + display = gdk_display_get_default (); + for (i = 0; i < gdk_display_get_n_screens (display); i++) { + GdkScreen *screen; + + screen = gdk_display_get_screen (display, i); + if (screen == NULL) { + continue; + } + manager->priv->screens = g_slist_append (manager->priv->screens, screen); + } + + manager->priv->current_screen = manager->priv->screens->data; +} + + +static void +acme_error (char * msg) +{ + GtkWidget *error_dialog; + + error_dialog = gtk_message_dialog_new (NULL, + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + msg, NULL); + gtk_dialog_set_default_response (GTK_DIALOG (error_dialog), + GTK_RESPONSE_OK); + gtk_widget_show (error_dialog); + g_signal_connect (error_dialog, + "response", + G_CALLBACK (gtk_widget_destroy), + NULL); +} + +static char * +get_term_command (MsdMediaKeysManager *manager) +{ + char *cmd_term; + char *cmd = NULL; + + cmd_term = mateconf_client_get_string (manager->priv->conf_client, + "/desktop/mate/applications/terminal/exec", NULL); + if ((cmd_term != NULL) && (strcmp (cmd_term, "") != 0)) { + char *cmd_args; + cmd_args = mateconf_client_get_string (manager->priv->conf_client, + "/desktop/mate/applications/terminal/exec_arg", NULL); + if ((cmd_args != NULL) && (strcmp (cmd_term, "") != 0)) { + cmd = g_strdup_printf ("%s %s -e", cmd_term, cmd_args); + } else { + cmd = g_strdup_printf ("%s -e", cmd_term); + } + + g_free (cmd_args); + } + + g_free (cmd_term); + + return cmd; +} + +static void +execute (MsdMediaKeysManager *manager, + char *cmd, + gboolean sync, + gboolean need_term) +{ + gboolean retval; + char **argv; + int argc; + char *exec; + char *term = NULL; + + retval = FALSE; + + if (need_term) { + term = get_term_command (manager); + if (term == NULL) { + acme_error (_("Could not get default terminal. Verify that your default " + "terminal command is set and points to a valid application.")); + return; + } + } + + if (term) { + exec = g_strdup_printf ("%s %s", term, cmd); + g_free (term); + } else { + exec = g_strdup (cmd); + } + + if (g_shell_parse_argv (exec, &argc, &argv, NULL)) { + if (sync != FALSE) { + retval = g_spawn_sync (g_get_home_dir (), + argv, + NULL, + G_SPAWN_SEARCH_PATH, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL); + } else { + retval = g_spawn_async (g_get_home_dir (), + argv, + NULL, + G_SPAWN_SEARCH_PATH, + NULL, + NULL, + NULL, + NULL); + } + g_strfreev (argv); + } + + if (retval == FALSE) { + char *msg; + msg = g_strdup_printf (_("Couldn't execute command: %s\n" + "Verify that this is a valid command."), + exec); + + acme_error (msg); + g_free (msg); + } + g_free (exec); +} + +static void +dialog_init (MsdMediaKeysManager *manager) +{ + if (manager->priv->dialog != NULL + && !msd_osd_window_is_valid (MSD_OSD_WINDOW (manager->priv->dialog))) { + gtk_widget_destroy (manager->priv->dialog); + manager->priv->dialog = NULL; + } + + if (manager->priv->dialog == NULL) { + manager->priv->dialog = msd_media_keys_window_new (); + } +} + +static gboolean +is_valid_shortcut (const char *string) +{ + if (string == NULL || string[0] == '\0') { + return FALSE; + } + if (strcmp (string, "disabled") == 0) { + return FALSE; + } + + return TRUE; +} + +static void +update_kbd_cb (MateConfClient *client, + guint id, + MateConfEntry *entry, + MsdMediaKeysManager *manager) +{ + int i; + gboolean need_flush = TRUE; + + g_return_if_fail (entry->key != NULL); + + gdk_error_trap_push (); + + /* Find the key that was modified */ + for (i = 0; i < HANDLED_KEYS; i++) { + if (strcmp (entry->key, keys[i].mateconf_key) == 0) { + char *tmp; + Key *key; + + if (keys[i].key != NULL) { + need_flush = TRUE; + grab_key_unsafe (keys[i].key, FALSE, manager->priv->screens); + } + + g_free (keys[i].key); + keys[i].key = NULL; + + tmp = mateconf_client_get_string (manager->priv->conf_client, + keys[i].mateconf_key, NULL); + + if (is_valid_shortcut (tmp) == FALSE) { + g_free (tmp); + break; + } + + key = g_new0 (Key, 1); + if (!egg_accelerator_parse_virtual (tmp, &key->keysym, &key->keycodes, &key->state)) { + g_free (tmp); + g_free (key); + break; + } + + need_flush = TRUE; + grab_key_unsafe (key, TRUE, manager->priv->screens); + keys[i].key = key; + + g_free (tmp); + + break; + } + } + + if (need_flush) + gdk_flush (); + if (gdk_error_trap_pop ()) + g_warning ("Grab failed for some keys, another application may already have access the them."); +} + +static void init_kbd(MsdMediaKeysManager* manager) +{ + int i; + gboolean need_flush = FALSE; + + mate_settings_profile_start(NULL); + + gdk_error_trap_push(); + + for (i = 0; i < HANDLED_KEYS; i++) + { + char* tmp; + Key* key; + + manager->priv->notify[i] = mateconf_client_notify_add(manager->priv->conf_client, + keys[i].mateconf_key, + (MateConfClientNotifyFunc) update_kbd_cb, + manager, + NULL, + NULL); + + tmp = mateconf_client_get_string(manager->priv->conf_client, + keys[i].mateconf_key, + NULL); + + if (!is_valid_shortcut(tmp)) + { + g_debug("Not a valid shortcut: '%s'", tmp); + g_free(tmp); + continue; + } + + key = g_new0(Key, 1); + + if (!egg_accelerator_parse_virtual(tmp, &key->keysym, &key->keycodes, &key->state)) + { + g_debug("Unable to parse: '%s'", tmp); + g_free(tmp); + g_free(key); + continue; + } + + g_free(tmp); + + keys[i].key = key; + + need_flush = TRUE; + grab_key_unsafe(key, TRUE, manager->priv->screens); + } + + if (need_flush) + { + gdk_flush(); + } + + if (gdk_error_trap_pop ()) + { + g_warning("Grab failed for some keys, another application may already have access the them."); + } + + mate_settings_profile_end(NULL); +} + +static void +dialog_show (MsdMediaKeysManager *manager) +{ + int orig_w; + int orig_h; + int screen_w; + int screen_h; + int x; + int y; + int pointer_x; + int pointer_y; + GtkRequisition win_req; + GdkScreen *pointer_screen; + GdkRectangle geometry; + int monitor; + + gtk_window_set_screen (GTK_WINDOW (manager->priv->dialog), + manager->priv->current_screen); + + /* + * get the window size + * if the window hasn't been mapped, it doesn't necessarily + * know its true size, yet, so we need to jump through hoops + */ + gtk_window_get_default_size (GTK_WINDOW (manager->priv->dialog), &orig_w, &orig_h); + gtk_widget_size_request (manager->priv->dialog, &win_req); + + if (win_req.width > orig_w) { + orig_w = win_req.width; + } + if (win_req.height > orig_h) { + orig_h = win_req.height; + } + + pointer_screen = NULL; + gdk_display_get_pointer (gdk_screen_get_display (manager->priv->current_screen), + &pointer_screen, + &pointer_x, + &pointer_y, + NULL); + if (pointer_screen != manager->priv->current_screen) { + /* The pointer isn't on the current screen, so just + * assume the default monitor + */ + monitor = 0; + } else { + monitor = gdk_screen_get_monitor_at_point (manager->priv->current_screen, + pointer_x, + pointer_y); + } + + gdk_screen_get_monitor_geometry (manager->priv->current_screen, + monitor, + &geometry); + + screen_w = geometry.width; + screen_h = geometry.height; + + x = ((screen_w - orig_w) / 2) + geometry.x; + y = geometry.y + (screen_h / 2) + (screen_h / 2 - orig_h) / 2; + + gtk_window_move (GTK_WINDOW (manager->priv->dialog), x, y); + + gtk_widget_show (manager->priv->dialog); + + gdk_display_sync (gdk_screen_get_display (manager->priv->current_screen)); +} + +static void +do_unknown_action (MsdMediaKeysManager *manager, + const char *url) +{ + char *string; + + g_return_if_fail (url != NULL); + + string = mateconf_client_get_string (manager->priv->conf_client, + "/desktop/mate/url-handlers/unknown/command", + NULL); + + if ((string != NULL) && (strcmp (string, "") != 0)) { + char *cmd; + cmd = g_strdup_printf (string, url); + execute (manager, cmd, FALSE, FALSE); + g_free (cmd); + } + g_free (string); +} + +static void +do_help_action (MsdMediaKeysManager *manager) +{ + char *string; + + string = mateconf_client_get_string (manager->priv->conf_client, + "/desktop/mate/url-handlers/ghelp/command", + NULL); + + if ((string != NULL) && (strcmp (string, "") != 0)) { + char *cmd; + cmd = g_strdup_printf (string, ""); + execute (manager, cmd, FALSE, FALSE); + g_free (cmd); + } else { + do_unknown_action (manager, "ghelp:"); + } + + g_free (string); +} + +static void +do_mail_action (MsdMediaKeysManager *manager) +{ + char *string; + + string = mateconf_client_get_string (manager->priv->conf_client, + "/desktop/mate/url-handlers/mailto/command", + NULL); + + if ((string != NULL) && (strcmp (string, "") != 0)) { + char *cmd; + cmd = g_strdup_printf (string, ""); + execute (manager, + cmd, + FALSE, + mateconf_client_get_bool (manager->priv->conf_client, + "/desktop/mate/url-handlers/mailto/needs_terminal", NULL)); + g_free (cmd); + } + g_free (string); +} + +static void +do_media_action (MsdMediaKeysManager *manager) +{ + char *command; + + command = mateconf_client_get_string (manager->priv->conf_client, + "/desktop/mate/applications/media/exec", NULL); + if ((command != NULL) && (strcmp (command, "") != 0)) { + execute (manager, + command, + FALSE, + mateconf_client_get_bool (manager->priv->conf_client, + "/desktop/mate/applications/media/needs_term", NULL)); + } + g_free (command); +} + +static void +do_www_action (MsdMediaKeysManager *manager, + const char *url) +{ + char *string; + + string = mateconf_client_get_string (manager->priv->conf_client, + "/desktop/mate/url-handlers/http/command", + NULL); + + if ((string != NULL) && (strcmp (string, "") != 0)) { + gchar *cmd; + + if (url == NULL) { + cmd = g_strdup_printf (string, ""); + } else { + cmd = g_strdup_printf (string, url); + } + + execute (manager, + cmd, + FALSE, + mateconf_client_get_bool (manager->priv->conf_client, + "/desktop/mate/url-handlers/http/needs_terminal", NULL)); + g_free (cmd); + } else { + do_unknown_action (manager, url ? url : ""); + } + g_free (string); +} + +static void +do_exit_action (MsdMediaKeysManager *manager) +{ + execute (manager, "mate-session-save --shutdown-dialog", FALSE, FALSE); +} + +static void +do_eject_action_cb (GDrive *drive, + GAsyncResult *res, + MsdMediaKeysManager *manager) +{ + g_drive_eject_with_operation_finish (drive, res, NULL); +} + +#define NO_SCORE 0 +#define SCORE_CAN_EJECT 50 +#define SCORE_HAS_MEDIA 100 +static void +do_eject_action (MsdMediaKeysManager *manager) +{ + GList *drives, *l; + GDrive *fav_drive; + guint score; + + /* Find the best drive to eject */ + fav_drive = NULL; + score = NO_SCORE; + drives = g_volume_monitor_get_connected_drives (manager->priv->volume_monitor); + for (l = drives; l != NULL; l = l->next) { + GDrive *drive = l->data; + + if (g_drive_can_eject (drive) == FALSE) + continue; + if (g_drive_is_media_removable (drive) == FALSE) + continue; + if (score < SCORE_CAN_EJECT) { + fav_drive = drive; + score = SCORE_CAN_EJECT; + } + if (g_drive_has_media (drive) == FALSE) + continue; + if (score < SCORE_HAS_MEDIA) { + fav_drive = drive; + score = SCORE_HAS_MEDIA; + break; + } + } + + /* Show the dialogue */ + dialog_init (manager); + msd_media_keys_window_set_action_custom (MSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), + "media-eject", + FALSE); + dialog_show (manager); + + /* Clean up the drive selection and exit if no suitable + * drives are found */ + if (fav_drive != NULL) + fav_drive = g_object_ref (fav_drive); + + g_list_foreach (drives, (GFunc) g_object_unref, NULL); + if (fav_drive == NULL) + return; + + /* Eject! */ + g_drive_eject_with_operation (fav_drive, G_MOUNT_UNMOUNT_FORCE, + NULL, NULL, + (GAsyncReadyCallback) do_eject_action_cb, + manager); + g_object_unref (fav_drive); +} + +static void +do_touchpad_action (MsdMediaKeysManager *manager) +{ + MateConfClient *client = manager->priv->conf_client; + gboolean state = mateconf_client_get_bool (client, TOUCHPAD_ENABLED_KEY, NULL); + + dialog_init (manager); + msd_media_keys_window_set_action_custom (MSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), + (!state) ? "touchpad-enabled" : "touchpad-disabled", + FALSE); + dialog_show (manager); + + mateconf_client_set_bool (client, TOUCHPAD_ENABLED_KEY, !state, NULL); +} + +#ifdef HAVE_PULSE +static void +update_dialog (MsdMediaKeysManager *manager, + guint vol, + gboolean muted, + gboolean sound_changed) +{ + vol = (int) (100 * (double) vol / PA_VOLUME_NORM); + vol = CLAMP (vol, 0, 100); + + dialog_init (manager); + msd_media_keys_window_set_volume_muted (MSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), + muted); + msd_media_keys_window_set_volume_level (MSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), vol); + msd_media_keys_window_set_action (MSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), + MSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME); + dialog_show (manager); + + if (sound_changed != FALSE && muted == FALSE) + ca_gtk_play_for_widget (manager->priv->dialog, 0, + CA_PROP_EVENT_ID, "audio-volume-change", + CA_PROP_EVENT_DESCRIPTION, "volume changed through key press", + CA_PROP_APPLICATION_ID, "org.mate.VolumeControl", + NULL); +} +#endif /* HAVE_PULSE */ + +#if defined(HAVE_PULSE) || defined(HAVE_GSTREAMER) +static void +do_sound_action (MsdMediaKeysManager *manager, + int type) +{ + gboolean muted; + guint vol, norm_vol_step; + int vol_step; + gboolean sound_changed; + +#ifdef HAVE_PULSE + if (manager->priv->stream == NULL) + return; +#elif defined(HAVE_GSTREAMER) + if (manager->priv->volume == NULL) + return; +#endif + + vol_step = mateconf_client_get_int (manager->priv->conf_client, + MATECONF_MISC_DIR "/volume_step", + NULL); + + if (vol_step <= 0 || vol_step > 100) + vol_step = VOLUME_STEP; + +#ifdef HAVE_PULSE + norm_vol_step = PA_VOLUME_NORM * vol_step / 100; + + /* FIXME: this is racy */ + vol = gvc_mixer_stream_get_volume (manager->priv->stream); + muted = gvc_mixer_stream_get_is_muted (manager->priv->stream); +#else + if (vol_step > 0) { + gint threshold = acme_volume_get_threshold (manager->priv->volume); + if (vol_step < threshold) + vol_step = threshold; + g_debug ("Using volume step of %d", vol_step); + } + vol = acme_volume_get_volume (manager->priv->volume); + muted = acme_volume_get_mute (manager->priv->volume); +#endif + sound_changed = FALSE; + + switch (type) { + case MUTE_KEY: +#ifdef HAVE_PULSE + muted = !muted; + gvc_mixer_stream_change_is_muted (manager->priv->stream, muted); + sound_changed = TRUE; +#else + acme_volume_mute_toggle (manager->priv->volume); +#endif + break; + case VOLUME_DOWN_KEY: +#ifdef HAVE_PULSE + if (!muted && (vol <= norm_vol_step)) { + muted = !muted; + vol = 0; + gvc_mixer_stream_change_is_muted (manager->priv->stream, muted); + if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE) { + gvc_mixer_stream_push_volume (manager->priv->stream); + sound_changed = TRUE; + } + } else if (!muted) { + vol = vol - norm_vol_step; + if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE) { + gvc_mixer_stream_push_volume (manager->priv->stream); + sound_changed = TRUE; + } + } +#else + if (!muted && (vol <= vol_step)) + acme_volume_mute_toggle (manager->priv->volume); + acme_volume_set_volume (manager->priv->volume, vol - vol_step); +#endif + break; + case VOLUME_UP_KEY: + if (muted) { + muted = !muted; + if (vol == 0) { +#ifdef HAVE_PULSE + vol = vol + norm_vol_step; + gvc_mixer_stream_change_is_muted (manager->priv->stream, muted); + if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE) { + gvc_mixer_stream_push_volume (manager->priv->stream); + sound_changed = TRUE; + } + } else { + gvc_mixer_stream_change_is_muted (manager->priv->stream, muted); + sound_changed = TRUE; + } +#else + /* We need to unmute otherwise vol is blocked (and muted) */ + acme_volume_set_mute (manager->priv->volume, FALSE); + } + acme_volume_set_volume (manager->priv->volume, vol + vol_step); +#endif + } else { +#ifdef HAVE_PULSE + if (vol < MAX_VOLUME) { + if (vol + norm_vol_step >= MAX_VOLUME) { + vol = MAX_VOLUME; + } else { + vol = vol + norm_vol_step; + } + if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE) { + gvc_mixer_stream_push_volume (manager->priv->stream); + sound_changed = TRUE; + } + } +#else + acme_volume_set_volume (manager->priv->volume, vol + vol_step); +#endif + } + break; + } + +#ifdef HAVE_PULSE + update_dialog (manager, vol, muted, sound_changed); +#else + muted = acme_volume_get_mute (manager->priv->volume); + vol = acme_volume_get_volume (manager->priv->volume); + + /* FIXME: AcmeVolume should probably emit signals + instead of doing it like this */ + dialog_init (manager); + msd_media_keys_window_set_volume_muted (MSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), + muted); + msd_media_keys_window_set_volume_level (MSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), + vol); + msd_media_keys_window_set_action (MSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), + MSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME); + dialog_show (manager); +#endif /* HAVE_PULSE */ +} +#endif /* defined(HAVE_PULSE) || defined(HAVE_GSTREAMER) */ + +#ifdef HAVE_PULSE +static void +update_default_sink (MsdMediaKeysManager *manager) +{ + GvcMixerStream *stream; + + stream = gvc_mixer_control_get_default_sink (manager->priv->volume); + if (stream == manager->priv->stream) + return; + + if (manager->priv->stream != NULL) { + g_object_unref (manager->priv->stream); + manager->priv->stream = NULL; + } + + if (stream != NULL) { + manager->priv->stream = g_object_ref (stream); + } else { + g_warning ("Unable to get default sink"); + } +} + +static void +on_control_ready (GvcMixerControl *control, + MsdMediaKeysManager *manager) +{ + update_default_sink (manager); +} + +static void +on_control_default_sink_changed (GvcMixerControl *control, + guint id, + MsdMediaKeysManager *manager) +{ + update_default_sink (manager); +} + +#endif /* HAVE_PULSE */ + +static gint +find_by_application (gconstpointer a, + gconstpointer b) +{ + return strcmp (((MediaPlayer *)a)->application, b); +} + +static gint +find_by_time (gconstpointer a, + gconstpointer b) +{ + return ((MediaPlayer *)a)->time < ((MediaPlayer *)b)->time; +} + +/* + * Register a new media player. Most applications will want to call + * this with time = GDK_CURRENT_TIME. This way, the last registered + * player will receive media events. In some cases, applications + * may want to register with a lower priority (usually 1), to grab + * events only nobody is interested. + */ +gboolean +msd_media_keys_manager_grab_media_player_keys (MsdMediaKeysManager *manager, + const char *application, + guint32 time, + GError **error) +{ + GList *iter; + MediaPlayer *media_player; + + if (time == GDK_CURRENT_TIME) { + GTimeVal tv; + + g_get_current_time (&tv); + time = tv.tv_sec * 1000 + tv.tv_usec / 1000; + } + + iter = g_list_find_custom (manager->priv->media_players, + application, + find_by_application); + + if (iter != NULL) { + if (((MediaPlayer *)iter->data)->time < time) { + g_free (((MediaPlayer *)iter->data)->application); + g_free (iter->data); + manager->priv->media_players = g_list_delete_link (manager->priv->media_players, iter); + } else { + return TRUE; + } + } + + g_debug ("Registering %s at %u", application, time); + media_player = g_new0 (MediaPlayer, 1); + media_player->application = g_strdup (application); + media_player->time = time; + + manager->priv->media_players = g_list_insert_sorted (manager->priv->media_players, + media_player, + find_by_time); + + return TRUE; +} + +gboolean +msd_media_keys_manager_release_media_player_keys (MsdMediaKeysManager *manager, + const char *application, + GError **error) +{ + GList *iter; + + iter = g_list_find_custom (manager->priv->media_players, + application, + find_by_application); + + if (iter != NULL) { + g_debug ("Deregistering %s", application); + g_free (((MediaPlayer *)iter->data)->application); + g_free (iter->data); + manager->priv->media_players = g_list_delete_link (manager->priv->media_players, iter); + } + + return TRUE; +} + +static gboolean +msd_media_player_key_pressed (MsdMediaKeysManager *manager, + const char *key) +{ + const char *application = NULL; + gboolean have_listeners; + + have_listeners = (manager->priv->media_players != NULL); + + if (have_listeners) { + application = ((MediaPlayer *)manager->priv->media_players->data)->application; + } + + g_signal_emit (manager, signals[MEDIA_PLAYER_KEY_PRESSED], 0, application, key); + + return !have_listeners; +} + +static gboolean +do_multimedia_player_action (MsdMediaKeysManager *manager, + const char *key) +{ + return msd_media_player_key_pressed (manager, key); +} + +static gboolean +do_action (MsdMediaKeysManager *manager, + int type) +{ + char *cmd; + char *path; + + switch (type) { + case TOUCHPAD_KEY: + do_touchpad_action (manager); + break; + case MUTE_KEY: + case VOLUME_DOWN_KEY: + case VOLUME_UP_KEY: +#if defined(HAVE_PULSE) || defined(HAVE_GSTREAMER) + do_sound_action (manager, type); +#endif /* HAVE_PULSE || HAVE_GSTREAMER */ + break; + case POWER_KEY: + do_exit_action (manager); + break; + case EJECT_KEY: + do_eject_action (manager); + break; + case HOME_KEY: + path = g_shell_quote (g_get_home_dir ()); + cmd = g_strconcat ("caja --no-desktop ", path, NULL); + g_free (path); + execute (manager, cmd, FALSE, FALSE); + g_free (cmd); + break; + case SEARCH_KEY: + cmd = NULL; + if ((cmd = g_find_program_in_path ("beagle-search"))) { + execute (manager, "beagle-search", FALSE, FALSE); + } else if ((cmd = g_find_program_in_path ("tracker-search-tool"))) { + execute (manager, "tracker-search-tool", FALSE, FALSE); + } else { + execute (manager, "mate-search-tool", FALSE, FALSE); + } + g_free (cmd); + break; + case EMAIL_KEY: + do_mail_action (manager); + break; + case SCREENSAVER_KEY: + if ((cmd = g_find_program_in_path ("mate-screensaver-command"))) { + execute (manager, "mate-screensaver-command --lock", FALSE, FALSE); + } else { + execute (manager, "xscreensaver-command -lock", FALSE, FALSE); + } + + g_free (cmd); + break; + case HELP_KEY: + do_help_action (manager); + break; + case WWW_KEY: + do_www_action (manager, NULL); + break; + case MEDIA_KEY: + do_media_action (manager); + break; + case CALCULATOR_KEY: + execute (manager, "gcalctool", FALSE, FALSE); + break; + case PLAY_KEY: + return do_multimedia_player_action (manager, "Play"); + break; + case PAUSE_KEY: + return do_multimedia_player_action (manager, "Pause"); + break; + case STOP_KEY: + return do_multimedia_player_action (manager, "Stop"); + break; + case PREVIOUS_KEY: + return do_multimedia_player_action (manager, "Previous"); + break; + case NEXT_KEY: + return do_multimedia_player_action (manager, "Next"); + break; + default: + g_assert_not_reached (); + } + + return FALSE; +} + +static GdkScreen * +acme_get_screen_from_event (MsdMediaKeysManager *manager, + XAnyEvent *xanyev) +{ + GdkWindow *window; + GdkScreen *screen; + GSList *l; + + /* Look for which screen we're receiving events */ + for (l = manager->priv->screens; l != NULL; l = l->next) { + screen = (GdkScreen *) l->data; + window = gdk_screen_get_root_window (screen); + + if (GDK_WINDOW_XID (window) == xanyev->window) { + return screen; + } + } + + return NULL; +} + +static GdkFilterReturn +acme_filter_events (GdkXEvent *xevent, + GdkEvent *event, + MsdMediaKeysManager *manager) +{ + XEvent *xev = (XEvent *) xevent; + XAnyEvent *xany = (XAnyEvent *) xevent; + int i; + + /* verify we have a key event */ + if (xev->type != KeyPress && xev->type != KeyRelease) { + return GDK_FILTER_CONTINUE; + } + + for (i = 0; i < HANDLED_KEYS; i++) { + if (match_key (keys[i].key, xev)) { + switch (keys[i].key_type) { + case VOLUME_DOWN_KEY: + case VOLUME_UP_KEY: + /* auto-repeatable keys */ + if (xev->type != KeyPress) { + return GDK_FILTER_CONTINUE; + } + break; + default: + if (xev->type != KeyRelease) { + return GDK_FILTER_CONTINUE; + } + } + + manager->priv->current_screen = acme_get_screen_from_event (manager, xany); + + if (do_action (manager, keys[i].key_type) == FALSE) { + return GDK_FILTER_REMOVE; + } else { + return GDK_FILTER_CONTINUE; + } + } + } + + return GDK_FILTER_CONTINUE; +} + +static gboolean +start_media_keys_idle_cb (MsdMediaKeysManager *manager) +{ + GSList *l; + + g_debug ("Starting media_keys manager"); + mate_settings_profile_start (NULL); + manager->priv->volume_monitor = g_volume_monitor_get (); + manager->priv->conf_client = mateconf_client_get_default (); + + mateconf_client_add_dir (manager->priv->conf_client, + MATECONF_BINDING_DIR, + MATECONF_CLIENT_PRELOAD_ONELEVEL, + NULL); + + init_screens (manager); + init_kbd (manager); + + /* Start filtering the events */ + for (l = manager->priv->screens; l != NULL; l = l->next) { + mate_settings_profile_start ("gdk_window_add_filter"); + + g_debug ("adding key filter for screen: %d", + gdk_screen_get_number (l->data)); + + gdk_window_add_filter (gdk_screen_get_root_window (l->data), + (GdkFilterFunc)acme_filter_events, + manager); + mate_settings_profile_end ("gdk_window_add_filter"); + } + + mate_settings_profile_end (NULL); + + return FALSE; +} + +gboolean +msd_media_keys_manager_start (MsdMediaKeysManager *manager, + GError **error) +{ + mate_settings_profile_start (NULL); + +#ifdef HAVE_PULSE + /* initialise Volume handler + * + * We do this one here to force checking gstreamer cache, etc. + * The rest (grabbing and setting the keys) can happen in an + * idle. + */ + mate_settings_profile_start ("gvc_mixer_control_new"); + + manager->priv->volume = gvc_mixer_control_new ("MATE Volume Control Media Keys"); + + g_signal_connect (manager->priv->volume, + "ready", + G_CALLBACK (on_control_ready), + manager); + g_signal_connect (manager->priv->volume, + "default-sink-changed", + G_CALLBACK (on_control_default_sink_changed), + manager); + + gvc_mixer_control_open (manager->priv->volume); + + mate_settings_profile_end ("gvc_mixer_control_new"); +#elif defined(HAVE_GSTREAMER) + mate_settings_profile_start ("acme_volume_new"); + manager->priv->volume = acme_volume_new (); + mate_settings_profile_end ("acme_volume_new"); +#endif /* HAVE_PULSE */ + g_idle_add ((GSourceFunc) start_media_keys_idle_cb, manager); + + mate_settings_profile_end (NULL); + + return TRUE; +} + +void +msd_media_keys_manager_stop (MsdMediaKeysManager *manager) +{ + MsdMediaKeysManagerPrivate *priv = manager->priv; + GSList *ls; + GList *l; + int i; + gboolean need_flush; + + g_debug ("Stopping media_keys manager"); + + for (ls = priv->screens; ls != NULL; ls = ls->next) { + gdk_window_remove_filter (gdk_screen_get_root_window (ls->data), + (GdkFilterFunc) acme_filter_events, + manager); + } + + if (priv->conf_client) { + mateconf_client_remove_dir (priv->conf_client, + MATECONF_BINDING_DIR, + NULL); + + for (i = 0; i < HANDLED_KEYS; ++i) { + if (priv->notify[i] != 0) { + mateconf_client_notify_remove (priv->conf_client, priv->notify[i]); + priv->notify[i] = 0; + } + } + + g_object_unref (priv->conf_client); + priv->conf_client = NULL; + } + + if (priv->volume_monitor != NULL) { + g_object_unref (priv->volume_monitor); + priv->volume_monitor = NULL; + } + + if (priv->connection != NULL) { + dbus_g_connection_unref (priv->connection); + priv->connection = NULL; + } + + need_flush = FALSE; + gdk_error_trap_push (); + + for (i = 0; i < HANDLED_KEYS; ++i) { + if (keys[i].key) { + need_flush = TRUE; + grab_key_unsafe (keys[i].key, FALSE, priv->screens); + + g_free (keys[i].key->keycodes); + g_free (keys[i].key); + keys[i].key = NULL; + } + } + + if (need_flush) + gdk_flush (); + gdk_error_trap_pop (); + + g_slist_free (priv->screens); + priv->screens = NULL; + +#ifdef HAVE_PULSE + if (priv->stream) { + g_object_unref (priv->stream); + priv->stream = NULL; + } +#endif /* HAVE_PULSE */ + +#if defined(HAVE_PULSE) || defined(HAVE_GSTREAMER) + if (priv->volume) { + g_object_unref (priv->volume); + priv->volume = NULL; + } +#endif /* defined(HAVE_PULSE) || defined(HAVE_GSTREAMER) */ + + if (priv->dialog != NULL) { + gtk_widget_destroy (priv->dialog); + priv->dialog = NULL; + } + + for (l = priv->media_players; l; l = l->next) { + MediaPlayer *mp = l->data; + g_free (mp->application); + g_free (mp); + } + g_list_free (priv->media_players); + priv->media_players = NULL; +} + +static void +msd_media_keys_manager_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MsdMediaKeysManager *self; + + self = MSD_MEDIA_KEYS_MANAGER (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +msd_media_keys_manager_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MsdMediaKeysManager *self; + + self = MSD_MEDIA_KEYS_MANAGER (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GObject * +msd_media_keys_manager_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties) +{ + MsdMediaKeysManager *media_keys_manager; + MsdMediaKeysManagerClass *klass; + + klass = MSD_MEDIA_KEYS_MANAGER_CLASS (g_type_class_peek (MSD_TYPE_MEDIA_KEYS_MANAGER)); + + media_keys_manager = MSD_MEDIA_KEYS_MANAGER (G_OBJECT_CLASS (msd_media_keys_manager_parent_class)->constructor (type, + n_construct_properties, + construct_properties)); + + return G_OBJECT (media_keys_manager); +} + +static void +msd_media_keys_manager_dispose (GObject *object) +{ + MsdMediaKeysManager *media_keys_manager; + + media_keys_manager = MSD_MEDIA_KEYS_MANAGER (object); + + G_OBJECT_CLASS (msd_media_keys_manager_parent_class)->dispose (object); +} + +static void +msd_media_keys_manager_class_init (MsdMediaKeysManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = msd_media_keys_manager_get_property; + object_class->set_property = msd_media_keys_manager_set_property; + object_class->constructor = msd_media_keys_manager_constructor; + object_class->dispose = msd_media_keys_manager_dispose; + object_class->finalize = msd_media_keys_manager_finalize; + + signals[MEDIA_PLAYER_KEY_PRESSED] = + g_signal_new ("media-player-key-pressed", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (MsdMediaKeysManagerClass, media_player_key_pressed), + NULL, + NULL, + msd_marshal_VOID__STRING_STRING, + G_TYPE_NONE, + 2, + G_TYPE_STRING, + G_TYPE_STRING); + + dbus_g_object_type_install_info (MSD_TYPE_MEDIA_KEYS_MANAGER, &dbus_glib_msd_media_keys_manager_object_info); + + g_type_class_add_private (klass, sizeof (MsdMediaKeysManagerPrivate)); +} + +static void +msd_media_keys_manager_init (MsdMediaKeysManager *manager) +{ + manager->priv = MSD_MEDIA_KEYS_MANAGER_GET_PRIVATE (manager); + +} + +static void +msd_media_keys_manager_finalize (GObject *object) +{ + MsdMediaKeysManager *media_keys_manager; + + g_return_if_fail (object != NULL); + g_return_if_fail (MSD_IS_MEDIA_KEYS_MANAGER (object)); + + media_keys_manager = MSD_MEDIA_KEYS_MANAGER (object); + + g_return_if_fail (media_keys_manager->priv != NULL); + + G_OBJECT_CLASS (msd_media_keys_manager_parent_class)->finalize (object); +} + +static gboolean +register_manager (MsdMediaKeysManager *manager) +{ + GError *error = NULL; + + manager->priv->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); + if (manager->priv->connection == NULL) { + if (error != NULL) { + g_error ("Error getting session bus: %s", error->message); + g_error_free (error); + } + return FALSE; + } + + dbus_g_connection_register_g_object (manager->priv->connection, MSD_MEDIA_KEYS_DBUS_PATH, G_OBJECT (manager)); + + return TRUE; +} + +MsdMediaKeysManager * +msd_media_keys_manager_new (void) +{ + if (manager_object != NULL) { + g_object_ref (manager_object); + } else { + gboolean res; + + manager_object = g_object_new (MSD_TYPE_MEDIA_KEYS_MANAGER, NULL); + g_object_add_weak_pointer (manager_object, + (gpointer *) &manager_object); + res = register_manager (manager_object); + if (! res) { + g_object_unref (manager_object); + return NULL; + } + } + + return MSD_MEDIA_KEYS_MANAGER (manager_object); +} diff --git a/plugins/media-keys/msd-media-keys-manager.h b/plugins/media-keys/msd-media-keys-manager.h new file mode 100644 index 0000000..96c135f --- /dev/null +++ b/plugins/media-keys/msd-media-keys-manager.h @@ -0,0 +1,72 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2007 William Jon McCann + * + * 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef __MSD_MEDIA_KEYS_MANAGER_H +#define __MSD_MEDIA_KEYS_MANAGER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MSD_TYPE_MEDIA_KEYS_MANAGER (msd_media_keys_manager_get_type ()) +#define MSD_MEDIA_KEYS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MSD_TYPE_MEDIA_KEYS_MANAGER, MsdMediaKeysManager)) +#define MSD_MEDIA_KEYS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), MSD_TYPE_MEDIA_KEYS_MANAGER, MsdMediaKeysManagerClass)) +#define MSD_IS_MEDIA_KEYS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MSD_TYPE_MEDIA_KEYS_MANAGER)) +#define MSD_IS_MEDIA_KEYS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), MSD_TYPE_MEDIA_KEYS_MANAGER)) +#define MSD_MEDIA_KEYS_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), MSD_TYPE_MEDIA_KEYS_MANAGER, MsdMediaKeysManagerClass)) + +typedef struct MsdMediaKeysManagerPrivate MsdMediaKeysManagerPrivate; + +typedef struct +{ + GObject parent; + MsdMediaKeysManagerPrivate *priv; +} MsdMediaKeysManager; + +typedef struct +{ + GObjectClass parent_class; + void (* media_player_key_pressed) (MsdMediaKeysManager *manager, + const char *application, + const char *key); +} MsdMediaKeysManagerClass; + +GType msd_media_keys_manager_get_type (void); + +MsdMediaKeysManager * msd_media_keys_manager_new (void); +gboolean msd_media_keys_manager_start (MsdMediaKeysManager *manager, + GError **error); +void msd_media_keys_manager_stop (MsdMediaKeysManager *manager); + +gboolean msd_media_keys_manager_grab_media_player_keys (MsdMediaKeysManager *manager, + const char *application, + guint32 time, + GError **error); +gboolean msd_media_keys_manager_release_media_player_keys (MsdMediaKeysManager *manager, + const char *application, + GError **error); + +#ifdef __cplusplus +} +#endif + +#endif /* __MSD_MEDIA_KEYS_MANAGER_H */ diff --git a/plugins/media-keys/msd-media-keys-manager.xml b/plugins/media-keys/msd-media-keys-manager.xml new file mode 100644 index 0000000..db0552e --- /dev/null +++ b/plugins/media-keys/msd-media-keys-manager.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/plugins/media-keys/msd-media-keys-plugin.c b/plugins/media-keys/msd-media-keys-plugin.c new file mode 100644 index 0000000..d76e233 --- /dev/null +++ b/plugins/media-keys/msd-media-keys-plugin.c @@ -0,0 +1,104 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2007 William Jon McCann + * + * 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 2, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "config.h" + +#include +#include + +#include "mate-settings-plugin.h" +#include "msd-media-keys-plugin.h" +#include "msd-media-keys-manager.h" + +struct MsdMediaKeysPluginPrivate { + MsdMediaKeysManager *manager; +}; + +#define MSD_MEDIA_KEYS_PLUGIN_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), MSD_TYPE_MEDIA_KEYS_PLUGIN, MsdMediaKeysPluginPrivate)) + +MATE_SETTINGS_PLUGIN_REGISTER (MsdMediaKeysPlugin, msd_media_keys_plugin) + +static void +msd_media_keys_plugin_init (MsdMediaKeysPlugin *plugin) +{ + plugin->priv = MSD_MEDIA_KEYS_PLUGIN_GET_PRIVATE (plugin); + + g_debug ("MsdMediaKeysPlugin initializing"); + + plugin->priv->manager = msd_media_keys_manager_new (); +} + +static void +msd_media_keys_plugin_finalize (GObject *object) +{ + MsdMediaKeysPlugin *plugin; + + g_return_if_fail (object != NULL); + g_return_if_fail (MSD_IS_MEDIA_KEYS_PLUGIN (object)); + + g_debug ("MsdMediaKeysPlugin finalizing"); + + plugin = MSD_MEDIA_KEYS_PLUGIN (object); + + g_return_if_fail (plugin->priv != NULL); + + if (plugin->priv->manager != NULL) { + g_object_unref (plugin->priv->manager); + } + + G_OBJECT_CLASS (msd_media_keys_plugin_parent_class)->finalize (object); +} + +static void +impl_activate (MateSettingsPlugin *plugin) +{ + gboolean res; + GError *error; + + g_debug ("Activating media_keys plugin"); + + error = NULL; + res = msd_media_keys_manager_start (MSD_MEDIA_KEYS_PLUGIN (plugin)->priv->manager, &error); + if (! res) { + g_warning ("Unable to start media_keys manager: %s", error->message); + g_error_free (error); + } +} + +static void +impl_deactivate (MateSettingsPlugin *plugin) +{ + g_debug ("Deactivating media_keys plugin"); + msd_media_keys_manager_stop (MSD_MEDIA_KEYS_PLUGIN (plugin)->priv->manager); +} + +static void +msd_media_keys_plugin_class_init (MsdMediaKeysPluginClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + MateSettingsPluginClass *plugin_class = MATE_SETTINGS_PLUGIN_CLASS (klass); + + object_class->finalize = msd_media_keys_plugin_finalize; + + plugin_class->activate = impl_activate; + plugin_class->deactivate = impl_deactivate; + + g_type_class_add_private (klass, sizeof (MsdMediaKeysPluginPrivate)); +} diff --git a/plugins/media-keys/msd-media-keys-plugin.h b/plugins/media-keys/msd-media-keys-plugin.h new file mode 100644 index 0000000..c869d62 --- /dev/null +++ b/plugins/media-keys/msd-media-keys-plugin.h @@ -0,0 +1,63 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2007 William Jon McCann + * + * 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 2, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef __MSD_MEDIA_KEYS_PLUGIN_H__ +#define __MSD_MEDIA_KEYS_PLUGIN_H__ + +#include +#include +#include + +#include "mate-settings-plugin.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MSD_TYPE_MEDIA_KEYS_PLUGIN (msd_media_keys_plugin_get_type ()) +#define MSD_MEDIA_KEYS_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MSD_TYPE_MEDIA_KEYS_PLUGIN, MsdMediaKeysPlugin)) +#define MSD_MEDIA_KEYS_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), MSD_TYPE_MEDIA_KEYS_PLUGIN, MsdMediaKeysPluginClass)) +#define MSD_IS_MEDIA_KEYS_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MSD_TYPE_MEDIA_KEYS_PLUGIN)) +#define MSD_IS_MEDIA_KEYS_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), MSD_TYPE_MEDIA_KEYS_PLUGIN)) +#define MSD_MEDIA_KEYS_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), MSD_TYPE_MEDIA_KEYS_PLUGIN, MsdMediaKeysPluginClass)) + +typedef struct MsdMediaKeysPluginPrivate MsdMediaKeysPluginPrivate; + +typedef struct +{ + MateSettingsPlugin parent; + MsdMediaKeysPluginPrivate *priv; +} MsdMediaKeysPlugin; + +typedef struct +{ + MateSettingsPluginClass parent_class; +} MsdMediaKeysPluginClass; + +GType msd_media_keys_plugin_get_type (void) G_GNUC_CONST; + +/* All the plugins must implement this function */ +G_MODULE_EXPORT GType register_mate_settings_plugin (GTypeModule *module); + +#ifdef __cplusplus +} +#endif + +#endif /* __MSD_MEDIA_KEYS_PLUGIN_H__ */ diff --git a/plugins/media-keys/msd-media-keys-window.c b/plugins/media-keys/msd-media-keys-window.c new file mode 100644 index 0000000..8bd6c33 --- /dev/null +++ b/plugins/media-keys/msd-media-keys-window.c @@ -0,0 +1,714 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2006-2007 William Jon McCann + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2, 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 Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include "msd-media-keys-window.h" + +#define MSD_MEDIA_KEYS_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MSD_TYPE_MEDIA_KEYS_WINDOW, MsdMediaKeysWindowPrivate)) + +struct MsdMediaKeysWindowPrivate +{ + MsdMediaKeysWindowAction action; + char *icon_name; + gboolean show_level; + + guint volume_muted : 1; + int volume_level; + + GtkImage *image; + GtkWidget *progress; +}; + +G_DEFINE_TYPE (MsdMediaKeysWindow, msd_media_keys_window, MSD_TYPE_OSD_WINDOW) + +static void +volume_controls_set_visible (MsdMediaKeysWindow *window, + gboolean visible) +{ + if (window->priv->progress == NULL) + return; + + if (visible) { + gtk_widget_show (window->priv->progress); + } else { + gtk_widget_hide (window->priv->progress); + } +} + +static void +window_set_icon_name (MsdMediaKeysWindow *window, + const char *name) +{ + if (window->priv->image == NULL) + return; + + gtk_image_set_from_icon_name (window->priv->image, + name, GTK_ICON_SIZE_DIALOG); +} + +static void +action_changed (MsdMediaKeysWindow *window) +{ + if (!msd_osd_window_is_composited (MSD_OSD_WINDOW (window))) { + switch (window->priv->action) { + case MSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME: + volume_controls_set_visible (window, TRUE); + + if (window->priv->volume_muted) { + window_set_icon_name (window, "audio-volume-muted"); + } else { + window_set_icon_name (window, "audio-volume-high"); + } + + break; + case MSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM: + volume_controls_set_visible (window, window->priv->show_level); + window_set_icon_name (window, window->priv->icon_name); + break; + default: + g_assert_not_reached (); + break; + } + } + + msd_osd_window_update_and_hide (MSD_OSD_WINDOW (window)); +} + +static void +volume_level_changed (MsdMediaKeysWindow *window) +{ + msd_osd_window_update_and_hide (MSD_OSD_WINDOW (window)); + + if (!msd_osd_window_is_composited (MSD_OSD_WINDOW (window)) && window->priv->progress != NULL) { + double fraction; + + fraction = (double) window->priv->volume_level / 100.0; + + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (window->priv->progress), + fraction); + } +} + +static void +volume_muted_changed (MsdMediaKeysWindow *window) +{ + msd_osd_window_update_and_hide (MSD_OSD_WINDOW (window)); + + if (!msd_osd_window_is_composited (MSD_OSD_WINDOW (window))) { + if (window->priv->volume_muted) { + window_set_icon_name (window, "audio-volume-muted"); + } else { + window_set_icon_name (window, "audio-volume-high"); + } + } +} + +void +msd_media_keys_window_set_action (MsdMediaKeysWindow *window, + MsdMediaKeysWindowAction action) +{ + g_return_if_fail (MSD_IS_MEDIA_KEYS_WINDOW (window)); + g_return_if_fail (action == MSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME); + + if (window->priv->action != action) { + window->priv->action = action; + action_changed (window); + } else { + msd_osd_window_update_and_hide (MSD_OSD_WINDOW (window)); + } +} + +void +msd_media_keys_window_set_action_custom (MsdMediaKeysWindow *window, + const char *icon_name, + gboolean show_level) +{ + g_return_if_fail (MSD_IS_MEDIA_KEYS_WINDOW (window)); + g_return_if_fail (icon_name != NULL); + + if (window->priv->action != MSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM || + g_strcmp0 (window->priv->icon_name, icon_name) != 0 || + window->priv->show_level != show_level) { + window->priv->action = MSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM; + g_free (window->priv->icon_name); + window->priv->icon_name = g_strdup (icon_name); + window->priv->show_level = show_level; + action_changed (window); + } else { + msd_osd_window_update_and_hide (MSD_OSD_WINDOW (window)); + } +} + +void +msd_media_keys_window_set_volume_muted (MsdMediaKeysWindow *window, + gboolean muted) +{ + g_return_if_fail (MSD_IS_MEDIA_KEYS_WINDOW (window)); + + if (window->priv->volume_muted != muted) { + window->priv->volume_muted = muted; + volume_muted_changed (window); + } +} + +void +msd_media_keys_window_set_volume_level (MsdMediaKeysWindow *window, + int level) +{ + g_return_if_fail (MSD_IS_MEDIA_KEYS_WINDOW (window)); + + if (window->priv->volume_level != level) { + window->priv->volume_level = level; + volume_level_changed (window); + } +} + +static GdkPixbuf * +load_pixbuf (MsdMediaKeysWindow *window, + const char *name, + int icon_size) +{ + GtkIconTheme *theme; + GdkPixbuf *pixbuf; + + if (window != NULL && gtk_widget_has_screen (GTK_WIDGET (window))) { + theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window))); + } else { + theme = gtk_icon_theme_get_default (); + } + + pixbuf = gtk_icon_theme_load_icon (theme, + name, + icon_size, + GTK_ICON_LOOKUP_FORCE_SIZE, + NULL); + + return pixbuf; +} + +static void +draw_eject (cairo_t *cr, + double _x0, + double _y0, + double width, + double height) +{ + int box_height; + int tri_height; + int separation; + + box_height = height * 0.2; + separation = box_height / 3; + tri_height = height - box_height - separation; + + cairo_rectangle (cr, _x0, _y0 + height - box_height, width, box_height); + + cairo_move_to (cr, _x0, _y0 + tri_height); + cairo_rel_line_to (cr, width, 0); + cairo_rel_line_to (cr, -width / 2, -tri_height); + cairo_rel_line_to (cr, -width / 2, tri_height); + cairo_close_path (cr); + cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, MSD_OSD_WINDOW_FG_ALPHA); + cairo_fill_preserve (cr); + + cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, MSD_OSD_WINDOW_FG_ALPHA / 2); + cairo_set_line_width (cr, 2); + cairo_stroke (cr); +} + +static void +draw_waves (cairo_t *cr, + double cx, + double cy, + double max_radius, + int volume_level) +{ + const int n_waves = 3; + int last_wave; + int i; + + last_wave = n_waves * volume_level / 100; + + for (i = 0; i < n_waves; i++) { + double angle1; + double angle2; + double radius; + double alpha; + + angle1 = -M_PI / 4; + angle2 = M_PI / 4; + + if (i < last_wave) + alpha = 1.0; + else if (i > last_wave) + alpha = 0.1; + else alpha = 0.1 + 0.9 * (n_waves * volume_level % 100) / 100.0; + + radius = (i + 1) * (max_radius / n_waves); + cairo_arc (cr, cx, cy, radius, angle1, angle2); + cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, alpha / 2); + cairo_set_line_width (cr, 14); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + cairo_stroke_preserve (cr); + + cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, alpha); + cairo_set_line_width (cr, 10); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + cairo_stroke (cr); + } +} + +static void +draw_cross (cairo_t *cr, + double cx, + double cy, + double size) +{ + cairo_move_to (cr, cx, cy - size/2.0); + cairo_rel_line_to (cr, size, size); + + cairo_move_to (cr, cx, cy + size/2.0); + cairo_rel_line_to (cr, size, -size); + + cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, MSD_OSD_WINDOW_FG_ALPHA / 2); + cairo_set_line_width (cr, 14); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + cairo_stroke_preserve (cr); + + cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, MSD_OSD_WINDOW_FG_ALPHA); + cairo_set_line_width (cr, 10); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + cairo_stroke (cr); +} + +static void +draw_speaker (cairo_t *cr, + double cx, + double cy, + double width, + double height) +{ + double box_width; + double box_height; + double _x0; + double _y0; + + box_width = width / 3; + box_height = height / 3; + + _x0 = cx - (width / 2) + box_width; + _y0 = cy - box_height / 2; + + cairo_move_to (cr, _x0, _y0); + cairo_rel_line_to (cr, - box_width, 0); + cairo_rel_line_to (cr, 0, box_height); + cairo_rel_line_to (cr, box_width, 0); + + cairo_line_to (cr, cx + box_width, cy + height / 2); + cairo_rel_line_to (cr, 0, -height); + cairo_line_to (cr, _x0, _y0); + cairo_close_path (cr); + + cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, MSD_OSD_WINDOW_FG_ALPHA); + cairo_fill_preserve (cr); + + cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, MSD_OSD_WINDOW_FG_ALPHA / 2); + cairo_set_line_width (cr, 2); + cairo_stroke (cr); +} + +static gboolean +render_speaker (MsdMediaKeysWindow *window, + cairo_t *cr, + double _x0, + double _y0, + double width, + double height) +{ + GdkPixbuf *pixbuf; + int icon_size; + int n; + static const char *icon_names[] = { + "audio-volume-muted", + "audio-volume-low", + "audio-volume-medium", + "audio-volume-high", + NULL + }; + + if (window->priv->volume_muted) { + n = 0; + } else { + /* select image */ + n = 3 * window->priv->volume_level / 100 + 1; + if (n < 1) { + n = 1; + } else if (n > 3) { + n = 3; + } + } + + icon_size = (int)width; + + pixbuf = load_pixbuf (window, icon_names[n], icon_size); + + if (pixbuf == NULL) { + return FALSE; + } + + gdk_cairo_set_source_pixbuf (cr, pixbuf, _x0, _y0); + cairo_paint_with_alpha (cr, MSD_OSD_WINDOW_FG_ALPHA); + + g_object_unref (pixbuf); + + return TRUE; +} + +static void +draw_volume_boxes (MsdMediaKeysWindow *window, + cairo_t *cr, + double percentage, + double _x0, + double _y0, + double width, + double height) +{ + gdouble x1; + GdkColor color; + double r, g, b; + GtkStyle *style; + + _x0 += 0.5; + _y0 += 0.5; + height = round (height) - 1; + width = round (width) - 1; + x1 = round ((width - 1) * percentage); + style = gtk_widget_get_style (GTK_WIDGET (window)); + + /* bar background */ + msd_osd_window_color_reverse (&style->dark[GTK_STATE_NORMAL], &color); + r = (float)color.red / 65535.0; + g = (float)color.green / 65535.0; + b = (float)color.blue / 65535.0; + msd_osd_window_draw_rounded_rectangle (cr, 1.0, _x0, _y0, height / 6, width, height); + cairo_set_source_rgba (cr, r, g, b, MSD_OSD_WINDOW_FG_ALPHA / 2); + cairo_fill_preserve (cr); + + /* bar border */ + msd_osd_window_color_reverse (&style->light[GTK_STATE_NORMAL], &color); + r = (float)color.red / 65535.0; + g = (float)color.green / 65535.0; + b = (float)color.blue / 65535.0; + cairo_set_source_rgba (cr, r, g, b, MSD_OSD_WINDOW_FG_ALPHA / 2); + cairo_set_line_width (cr, 1); + cairo_stroke (cr); + + /* bar progress */ + if (percentage < 0.01) + return; + color = style->bg[GTK_STATE_NORMAL]; + r = (float)color.red / 65535.0; + g = (float)color.green / 65535.0; + b = (float)color.blue / 65535.0; + msd_osd_window_draw_rounded_rectangle (cr, 1.0, _x0 + 0.5, _y0 + 0.5, height / 6 - 0.5, x1, height - 1); + cairo_set_source_rgba (cr, r, g, b, MSD_OSD_WINDOW_FG_ALPHA); + cairo_fill (cr); +} + +static void +draw_action_volume (MsdMediaKeysWindow *window, + cairo_t *cr) +{ + int window_width; + int window_height; + double icon_box_width; + double icon_box_height; + double icon_box_x0; + double icon_box_y0; + double volume_box_x0; + double volume_box_y0; + double volume_box_width; + double volume_box_height; + gboolean res; + + gtk_window_get_size (GTK_WINDOW (window), &window_width, &window_height); + + icon_box_width = round (window_width * 0.65); + icon_box_height = round (window_height * 0.65); + volume_box_width = icon_box_width; + volume_box_height = round (window_height * 0.05); + + icon_box_x0 = (window_width - icon_box_width) / 2; + icon_box_y0 = (window_height - icon_box_height - volume_box_height) / 2; + volume_box_x0 = round (icon_box_x0); + volume_box_y0 = round (icon_box_height + icon_box_y0); + +#if 0 + g_message ("icon box: w=%f h=%f _x0=%f _y0=%f", + icon_box_width, + icon_box_height, + icon_box_x0, + icon_box_y0); + g_message ("volume box: w=%f h=%f _x0=%f _y0=%f", + volume_box_width, + volume_box_height, + volume_box_x0, + volume_box_y0); +#endif + + res = render_speaker (window, + cr, + icon_box_x0, icon_box_y0, + icon_box_width, icon_box_height); + if (! res) { + double speaker_width; + double speaker_height; + double speaker_cx; + double speaker_cy; + + speaker_width = icon_box_width * 0.5; + speaker_height = icon_box_height * 0.75; + speaker_cx = icon_box_x0 + speaker_width / 2; + speaker_cy = icon_box_y0 + speaker_height / 2; + +#if 0 + g_message ("speaker box: w=%f h=%f cx=%f cy=%f", + speaker_width, + speaker_height, + speaker_cx, + speaker_cy); +#endif + + /* draw speaker symbol */ + draw_speaker (cr, speaker_cx, speaker_cy, speaker_width, speaker_height); + + if (! window->priv->volume_muted) { + /* draw sound waves */ + double wave_x0; + double wave_y0; + double wave_radius; + + wave_x0 = window_width / 2; + wave_y0 = speaker_cy; + wave_radius = icon_box_width / 2; + + draw_waves (cr, wave_x0, wave_y0, wave_radius, window->priv->volume_level); + } else { + /* draw 'mute' cross */ + double cross_x0; + double cross_y0; + double cross_size; + + cross_size = speaker_width * 3 / 4; + cross_x0 = icon_box_x0 + icon_box_width - cross_size; + cross_y0 = speaker_cy; + + draw_cross (cr, cross_x0, cross_y0, cross_size); + } + } + + /* draw volume meter */ + draw_volume_boxes (window, + cr, + (double)window->priv->volume_level / 100.0, + volume_box_x0, + volume_box_y0, + volume_box_width, + volume_box_height); +} + +static gboolean +render_custom (MsdMediaKeysWindow *window, + cairo_t *cr, + double _x0, + double _y0, + double width, + double height) +{ + GdkPixbuf *pixbuf; + int icon_size; + + icon_size = (int)width; + + pixbuf = load_pixbuf (window, window->priv->icon_name, icon_size); + + if (pixbuf == NULL) { + char *name; + if (gtk_widget_get_direction (GTK_WIDGET (window)) == GTK_TEXT_DIR_RTL) + name = g_strdup_printf ("%s-rtl", window->priv->icon_name); + else + name = g_strdup_printf ("%s-ltr", window->priv->icon_name); + pixbuf = load_pixbuf (window, name, icon_size); + g_free (name); + if (pixbuf == NULL) + return FALSE; + } + + gdk_cairo_set_source_pixbuf (cr, pixbuf, _x0, _y0); + cairo_paint_with_alpha (cr, MSD_OSD_WINDOW_FG_ALPHA); + + g_object_unref (pixbuf); + + return TRUE; +} + +static void +draw_action_custom (MsdMediaKeysWindow *window, + cairo_t *cr) +{ + int window_width; + int window_height; + double icon_box_width; + double icon_box_height; + double icon_box_x0; + double icon_box_y0; + double bright_box_x0; + double bright_box_y0; + double bright_box_width; + double bright_box_height; + gboolean res; + + gtk_window_get_size (GTK_WINDOW (window), &window_width, &window_height); + + icon_box_width = round (window_width * 0.65); + icon_box_height = round (window_height * 0.65); + bright_box_width = round (icon_box_width); + bright_box_height = round (window_height * 0.05); + + icon_box_x0 = (window_width - icon_box_width) / 2; + icon_box_y0 = (window_height - icon_box_height - bright_box_height) / 2; + bright_box_x0 = round (icon_box_x0); + bright_box_y0 = round (icon_box_height + icon_box_y0); + +#if 0 + g_message ("icon box: w=%f h=%f _x0=%f _y0=%f", + icon_box_width, + icon_box_height, + icon_box_x0, + icon_box_y0); + g_message ("brightness box: w=%f h=%f _x0=%f _y0=%f", + bright_box_width, + bright_box_height, + bright_box_x0, + bright_box_y0); +#endif + + res = render_custom (window, + cr, + icon_box_x0, icon_box_y0, + icon_box_width, icon_box_height); + if (! res && g_strcmp0 (window->priv->icon_name, "media-eject") == 0) { + /* draw eject symbol */ + draw_eject (cr, + icon_box_x0, icon_box_y0, + icon_box_width, icon_box_height); + } + + if (window->priv->show_level != FALSE) { + /* draw volume meter */ + draw_volume_boxes (window, + cr, + (double)window->priv->volume_level / 100.0, + bright_box_x0, + bright_box_y0, + bright_box_width, + bright_box_height); + } +} + +static void +msd_media_keys_window_expose_when_composited (MsdOsdWindow *osd_window, + cairo_t *cr) +{ + MsdMediaKeysWindow *window = MSD_MEDIA_KEYS_WINDOW (osd_window); + + switch (window->priv->action) { + case MSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME: + draw_action_volume (window, cr); + break; + case MSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM: + draw_action_custom (window, cr); + break; + default: + break; + } +} + +static void +msd_media_keys_window_class_init (MsdMediaKeysWindowClass *klass) +{ + MsdOsdWindowClass *osd_window_class = MSD_OSD_WINDOW_CLASS (klass); + + osd_window_class->expose_when_composited = msd_media_keys_window_expose_when_composited; + + g_type_class_add_private (klass, sizeof (MsdMediaKeysWindowPrivate)); +} + +static void +msd_media_keys_window_init (MsdMediaKeysWindow *window) +{ + GdkScreen *screen; + + window->priv = MSD_MEDIA_KEYS_WINDOW_GET_PRIVATE (window); + + screen = gtk_widget_get_screen (GTK_WIDGET (window)); + + if (!msd_osd_window_is_composited (MSD_OSD_WINDOW (window))) { + GtkBuilder *builder; + const gchar *objects[] = {"acme_box", NULL}; + GtkWidget *box; + + builder = gtk_builder_new (); + gtk_builder_add_objects_from_file (builder, + GTKBUILDERDIR "/acme.ui", + (char **) objects, + NULL); + + window->priv->image = GTK_IMAGE (gtk_builder_get_object (builder, "acme_image")); + window->priv->progress = GTK_WIDGET (gtk_builder_get_object (builder, "acme_volume_progressbar")); + box = GTK_WIDGET (gtk_builder_get_object (builder, "acme_box")); + + if (box != NULL) { + gtk_container_add (GTK_CONTAINER (window), box); + gtk_widget_show_all (box); + } + + /* The builder needs to stay alive until the window + takes ownership of the box (and its children) */ + g_object_unref (builder); + } +} + +GtkWidget * +msd_media_keys_window_new (void) +{ + return g_object_new (MSD_TYPE_MEDIA_KEYS_WINDOW, NULL); +} diff --git a/plugins/media-keys/msd-media-keys-window.h b/plugins/media-keys/msd-media-keys-window.h new file mode 100644 index 0000000..c0e5739 --- /dev/null +++ b/plugins/media-keys/msd-media-keys-window.h @@ -0,0 +1,78 @@ +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8; tab-width: 8 -*- + * + * Copyright (C) 2006 William Jon McCann + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2, 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 Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef MSD_MEDIA_KEYS_WINDOW_H +#define MSD_MEDIA_KEYS_WINDOW_H + +#include +#include + +#include "msd-osd-window.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MSD_TYPE_MEDIA_KEYS_WINDOW (msd_media_keys_window_get_type ()) +#define MSD_MEDIA_KEYS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MSD_TYPE_MEDIA_KEYS_WINDOW, MsdMediaKeysWindow)) +#define MSD_MEDIA_KEYS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MSD_TYPE_MEDIA_KEYS_WINDOW, MsdMediaKeysWindowClass)) +#define MSD_IS_MEDIA_KEYS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MSD_TYPE_MEDIA_KEYS_WINDOW)) +#define MSD_IS_MEDIA_KEYS_WINDOW_CLASS(klass) (G_TYPE_INSTANCE_GET_CLASS ((klass), MSD_TYPE_MEDIA_KEYS_WINDOW)) + +typedef struct MsdMediaKeysWindow MsdMediaKeysWindow; +typedef struct MsdMediaKeysWindowClass MsdMediaKeysWindowClass; +typedef struct MsdMediaKeysWindowPrivate MsdMediaKeysWindowPrivate; + +struct MsdMediaKeysWindow { + MsdOsdWindow parent; + + MsdMediaKeysWindowPrivate *priv; +}; + +struct MsdMediaKeysWindowClass { + MsdOsdWindowClass parent_class; +}; + +typedef enum { + MSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME, + MSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM +} MsdMediaKeysWindowAction; + +GType msd_media_keys_window_get_type (void); + +GtkWidget * msd_media_keys_window_new (void); +void msd_media_keys_window_set_action (MsdMediaKeysWindow *window, + MsdMediaKeysWindowAction action); +void msd_media_keys_window_set_action_custom (MsdMediaKeysWindow *window, + const char *icon_name, + gboolean show_level); +void msd_media_keys_window_set_volume_muted (MsdMediaKeysWindow *window, + gboolean muted); +void msd_media_keys_window_set_volume_level (MsdMediaKeysWindow *window, + int level); +gboolean msd_media_keys_window_is_valid (MsdMediaKeysWindow *window); + +#ifdef __cplusplus +} +#endif + +#endif -- cgit v1.2.1