diff options
Diffstat (limited to 'plugins/media-keys/msd-media-keys-manager.c')
-rw-r--r-- | plugins/media-keys/msd-media-keys-manager.c | 377 |
1 files changed, 281 insertions, 96 deletions
diff --git a/plugins/media-keys/msd-media-keys-manager.c b/plugins/media-keys/msd-media-keys-manager.c index 14cb02d..5ab8946 100644 --- a/plugins/media-keys/msd-media-keys-manager.c +++ b/plugins/media-keys/msd-media-keys-manager.c @@ -3,6 +3,7 @@ * Copyright (C) 2001-2003 Bastien Nocera <[email protected]> * Copyright (C) 2006-2007 William Jon McCann <[email protected]> * Copyright (C) 2014 Michal Ratajsky <[email protected]> + * Copyright (C) 2012-2021 MATE Developers * * 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 @@ -29,9 +30,6 @@ #include <gtk/gtk.h> #include <gio/gio.h> -#include <dbus/dbus-glib.h> -#include <dbus/dbus-glib-lowlevel.h> - #ifdef HAVE_LIBMATEMIXER #include <libmatemixer/matemixer.h> #endif @@ -43,7 +41,6 @@ #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" @@ -58,9 +55,28 @@ #define TOUCHPAD_SCHEMA "org.mate.peripherals-touchpad" #define TOUCHPAD_ENABLED_KEY "touchpad-enabled" +#define SOUND_SCHEMA "org.mate.sound" +#define VOLUME_OVERAMPLIFIABLE_KEY "volume-overamplifiable" + +static const gchar introspection_xml[] = +"<node name='/org/mate/SettingsDaemon/MediaKeys'>" +" <interface name='org.mate.SettingsDaemon.MediaKeys'>" +" <method name='GrabMediaPlayerKeys'>" +" <arg name='application' direction='in' type='s'/>" +" <arg name='time' direction='in' type='u'/>" +" </method>" +" <method name='ReleaseMediaPlayerKeys'>" +" <arg name='application' direction='in' type='s'/>" +" </method>" +" <signal name='MediaPlayerKeyPressed'/>" +" </interface>" +"</node>"; + typedef struct { char *application; + char *dbus_name; guint32 time; + guint watch_id; } MediaPlayer; struct _MsdMediaKeysManagerPrivate @@ -75,6 +91,7 @@ struct _MsdMediaKeysManagerPrivate #endif GtkWidget *dialog; GSettings *settings; + GSettings *sound_settings; GVolumeMonitor *volume_monitor; /* Multihead stuff */ @@ -88,20 +105,20 @@ struct _MsdMediaKeysManagerPrivate GList *media_players; - DBusGConnection *connection; - guint notify[HANDLED_KEYS]; -}; + GDBusNodeInfo *introspection_data; + GDBusConnection *connection; + GCancellable *bus_cancellable; -enum { - MEDIA_PLAYER_KEY_PRESSED, - LAST_SIGNAL -}; + guint start_idle_id; -static guint signals[LAST_SIGNAL] = { 0 }; + guint owner_id; + guint notify[HANDLED_KEYS]; +}; G_DEFINE_TYPE_WITH_PRIVATE (MsdMediaKeysManager, msd_media_keys_manager, G_TYPE_OBJECT) static gpointer manager_object = NULL; +static void register_manager (MsdMediaKeysManager *manager); static void init_screens (MsdMediaKeysManager *manager) @@ -130,7 +147,7 @@ acme_error (char * msg) GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, - msg, NULL); + "%s", msg); gtk_dialog_set_default_response (GTK_DIALOG (error_dialog), GTK_RESPONSE_OK); gtk_widget_show (error_dialog); @@ -476,26 +493,31 @@ dialog_show (MsdMediaKeysManager *manager) } static void +launch_default_for_uri_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + gchar *uri = user_data; + + if (!g_app_info_launch_default_for_uri_finish (res, &error)) + { + g_warning ("Could not launch '%s': %s", uri, + error->message); + g_clear_error (&error); + } + g_free (uri); +} + +static void do_url_action (MsdMediaKeysManager *manager, const gchar *scheme) { - GError *error = NULL; - GAppInfo *app_info; - - app_info = g_app_info_get_default_for_uri_scheme (scheme); - - if (app_info != NULL) { - if (!g_app_info_launch (app_info, NULL, NULL, &error)) { - g_warning ("Could not launch '%s': %s", - g_app_info_get_commandline (app_info), - error->message); - g_object_unref (app_info); - g_error_free (error); - } - } - else { - g_warning ("Could not find default application for '%s' scheme", scheme); - } + g_app_info_launch_default_for_uri_async (scheme, + NULL, + NULL, + launch_default_for_uri_cb, + g_strdup (scheme)); } static void @@ -600,7 +622,6 @@ do_eject_action (MsdMediaKeysManager *manager) continue; if (score < SCORE_HAS_MEDIA) { fav_drive = drive; - score = SCORE_HAS_MEDIA; break; } } @@ -617,7 +638,7 @@ do_eject_action (MsdMediaKeysManager *manager) if (fav_drive != NULL) fav_drive = g_object_ref (fav_drive); - g_list_foreach (drives, (GFunc) g_object_unref, NULL); + g_list_free_full (drives, g_object_unref); if (fav_drive == NULL) return; @@ -666,7 +687,7 @@ update_dialog (MsdMediaKeysManager *manager, gboolean is_mic) { if (muted) - volume = 0.0; + volume = 0; dialog_init (manager); @@ -706,7 +727,8 @@ do_sound_action (MsdMediaKeysManager *manager, gboolean sound_changed = FALSE; guint volume; guint volume_min, volume_max; - guint volume_step; + gint volume_step; + guint volume_step_scaled; guint volume_last; MateMixerStreamControl *control; @@ -722,17 +744,21 @@ do_sound_action (MsdMediaKeysManager *manager, /* Theoretically the volume limits might be different for different * streams, also the minimum might not always start at 0 */ volume_min = mate_mixer_stream_control_get_min_volume (control); - volume_max = mate_mixer_stream_control_get_normal_volume (control); + if (g_settings_get_boolean (manager->priv->sound_settings, VOLUME_OVERAMPLIFIABLE_KEY)) + volume_max = mate_mixer_stream_control_get_max_volume (control); + else + volume_max = mate_mixer_stream_control_get_normal_volume (control); volume_step = g_settings_get_int (manager->priv->settings, "volume-step"); if (volume_step <= 0 || volume_step > 100) { GVariant *variant = g_settings_get_default_value (manager->priv->settings, "volume-step"); - volume_step = g_variant_get_int32 (variant); + gint32 volume_step_default = g_variant_get_int32 (variant); + volume_step = (gint) volume_step_default; g_variant_unref (variant); } /* Scale the volume step size accordingly to the range used by the control */ - volume_step = (volume_max - volume_min) * volume_step / 100; + volume_step_scaled = (volume_max - volume_min) * (guint) volume_step / 100; volume = volume_last = mate_mixer_stream_control_get_volume (control); @@ -745,11 +771,11 @@ do_sound_action (MsdMediaKeysManager *manager, muted = !muted; break; case VOLUME_DOWN_KEY: - if (volume <= (volume_min + volume_step)) { + if (volume <= (volume_min + volume_step_scaled)) { volume = volume_min; muted = TRUE; } else { - volume -= volume_step; + volume -= volume_step_scaled; muted = FALSE; } break; @@ -757,9 +783,9 @@ do_sound_action (MsdMediaKeysManager *manager, if (muted) { muted = FALSE; if (volume <= volume_min) - volume = volume_min + volume_step; + volume = volume_min + volume_step_scaled; } else - volume = CLAMP (volume + volume_step, + volume = CLAMP (volume + volume_step_scaled, volume_min, volume_max); break; @@ -1038,6 +1064,18 @@ do_display_osd_action (MsdMediaKeysManager *manager) dialog_show (manager); } +static void +free_media_player (MediaPlayer *player) +{ + if (player->watch_id > 0) { + g_bus_unwatch_name (player->watch_id); + player->watch_id = 0; + } + g_free (player->application); + g_free (player->dbus_name); + g_free (player); +} + static gint find_by_application (gconstpointer a, gconstpointer b) @@ -1046,12 +1084,40 @@ find_by_application (gconstpointer a, } static gint +find_by_name (gconstpointer a, + gconstpointer b) +{ + return strcmp (((MediaPlayer *)a)->dbus_name, b); +} + +static gint find_by_time (gconstpointer a, gconstpointer b) { return ((MediaPlayer *)a)->time < ((MediaPlayer *)b)->time; } +static void +name_vanished_handler (GDBusConnection *connection, + const gchar *name, + MsdMediaKeysManager *manager) +{ + GList *iter; + + iter = g_list_find_custom (manager->priv->media_players, + name, + find_by_name); + + if (iter != NULL) { + MediaPlayer *player; + + player = iter->data; + g_debug ("Deregistering vanished %s (dbus_name: %s)", player->application, player->dbus_name); + free_media_player (player); + manager->priv->media_players = g_list_delete_link (manager->priv->media_players, iter); + } +} + /* * Register a new media player. Most applications will want to call * this with time = GDK_CURRENT_TIME. This way, the last registered @@ -1059,14 +1125,15 @@ find_by_time (gconstpointer a, * may want to register with a lower priority (usually 1), to grab * events only nobody is interested. */ -gboolean +static void msd_media_keys_manager_grab_media_player_keys (MsdMediaKeysManager *manager, const char *application, - guint32 time, - GError **error) + const char *dbus_name, + guint32 time) { GList *iter; MediaPlayer *media_player; + guint watch_id; if (time == GDK_CURRENT_TIME) { time = (guint32)(g_get_monotonic_time () / 1000); @@ -1078,51 +1145,70 @@ msd_media_keys_manager_grab_media_player_keys (MsdMediaKeysManager *manager, if (iter != NULL) { if (((MediaPlayer *)iter->data)->time < time) { - g_free (((MediaPlayer *)iter->data)->application); - g_free (iter->data); + MediaPlayer *player = iter->data; + free_media_player (player); manager->priv->media_players = g_list_delete_link (manager->priv->media_players, iter); } else { - return TRUE; + return; } } + watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION, + dbus_name, + G_BUS_NAME_WATCHER_FLAGS_NONE, + NULL, + (GBusNameVanishedCallback) name_vanished_handler, + manager, + NULL); + g_debug ("Registering %s at %u", application, time); media_player = g_new0 (MediaPlayer, 1); media_player->application = g_strdup (application); + media_player->dbus_name = g_strdup (dbus_name); media_player->time = time; + media_player->watch_id = watch_id; manager->priv->media_players = g_list_insert_sorted (manager->priv->media_players, media_player, find_by_time); - - return TRUE; } -gboolean +static void msd_media_keys_manager_release_media_player_keys (MsdMediaKeysManager *manager, const char *application, - GError **error) + const char *name) { - GList *iter; + GList *iter = NULL; - iter = g_list_find_custom (manager->priv->media_players, - application, - find_by_application); + g_return_if_fail (application != NULL || name != NULL); + + if (application != NULL) { + iter = g_list_find_custom (manager->priv->media_players, + application, + find_by_application); + } + + if (iter == NULL && name != NULL) { + iter = g_list_find_custom (manager->priv->media_players, + name, + find_by_name); + } if (iter != NULL) { - g_debug ("Deregistering %s", application); - g_free (((MediaPlayer *)iter->data)->application); - g_free (iter->data); + MediaPlayer *player; + + player = iter->data; + g_debug ("Deregistering %s (dbus_name: %s)", application, player->dbus_name); + free_media_player (player); 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) { + GError *error = NULL; const char *application = NULL; gboolean have_listeners; @@ -1132,11 +1218,55 @@ msd_media_player_key_pressed (MsdMediaKeysManager *manager, application = ((MediaPlayer *)manager->priv->media_players->data)->application; } - g_signal_emit (manager, signals[MEDIA_PLAYER_KEY_PRESSED], 0, application, key); + if (g_dbus_connection_emit_signal (manager->priv->connection, + NULL, + MSD_MEDIA_KEYS_DBUS_PATH, + MSD_MEDIA_KEYS_DBUS_NAME, + "MediaPlayerKeyPressed", + g_variant_new ("(ss)", application, key), + &error) == FALSE) { + g_debug ("Error emitting signal: %s", error->message); + g_error_free (error); + } return !have_listeners; } +static void +handle_method_call (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + MsdMediaKeysManager *manager = (MsdMediaKeysManager *) user_data; + + g_debug ("Calling method '%s' for media-keys", method_name); + + if (g_strcmp0 (method_name, "ReleaseMediaPlayerKeys") == 0) { + const char *app_name; + + g_variant_get (parameters, "(&s)", &app_name); + msd_media_keys_manager_release_media_player_keys (manager, app_name, sender); + g_dbus_method_invocation_return_value (invocation, NULL); + } else if (g_strcmp0 (method_name, "GrabMediaPlayerKeys") == 0) { + const char *app_name; + guint32 time; + + g_variant_get (parameters, "(&su)", &app_name, &time); + msd_media_keys_manager_grab_media_player_keys (manager, app_name, sender, time); + g_dbus_method_invocation_return_value (invocation, NULL); + } +} + +static const GDBusInterfaceVTable interface_vtable = +{ + .method_call = handle_method_call, +}; + static gboolean do_multimedia_player_action (MsdMediaKeysManager *manager, const char *key) @@ -1400,7 +1530,7 @@ rfkill_appeared_cb (GDBusConnection *connection, g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, 0, NULL, - "org.mate.SettingsDaemon.Rfkill", + "org.mate.SettingsDaemon", "/org/mate/SettingsDaemon/Rfkill", "org.mate.SettingsDaemon.Rfkill", manager->priv->rfkill_cancellable, @@ -1422,6 +1552,7 @@ start_media_keys_idle_cb (MsdMediaKeysManager *manager) manager->priv->volume_monitor = g_volume_monitor_get (); manager->priv->settings = g_settings_new (BINDING_SCHEMA); + manager->priv->sound_settings = g_settings_new (SOUND_SCHEMA); ensure_cancellable (&manager->priv->rfkill_cancellable); @@ -1464,6 +1595,8 @@ start_media_keys_idle_cb (MsdMediaKeysManager *manager) mate_settings_profile_end (NULL); + manager->priv->start_idle_id = 0; + return FALSE; } @@ -1500,7 +1633,8 @@ msd_media_keys_manager_start (MsdMediaKeysManager *manager, GError **error) mate_settings_profile_end ("mate_mixer_context_new"); } #endif - g_idle_add ((GSourceFunc) start_media_keys_idle_cb, manager); + manager->priv->start_idle_id = g_idle_add ((GSourceFunc) start_media_keys_idle_cb, manager); + g_source_set_name_by_id (manager->priv->start_idle_id, "[mate-settings-daemon] start_media_keys_idle_cb"); mate_settings_profile_end (NULL); @@ -1535,16 +1669,39 @@ msd_media_keys_manager_stop (MsdMediaKeysManager *manager) priv->settings = NULL; } + if (priv->sound_settings != NULL) { + g_object_unref (priv->sound_settings); + priv->sound_settings = NULL; + } + if (priv->volume_monitor != NULL) { g_object_unref (priv->volume_monitor); priv->volume_monitor = NULL; } + if (priv->start_idle_id != 0) { + g_source_remove (priv->start_idle_id); + priv->start_idle_id = 0; + } + + if (priv->owner_id > 0) { + g_bus_unown_name (priv->owner_id); + priv->owner_id = 0; + } + if (priv->connection != NULL) { - dbus_g_connection_unref (priv->connection); + g_object_unref (priv->connection); priv->connection = NULL; } + if (priv->bus_cancellable != NULL) { + g_cancellable_cancel (priv->bus_cancellable); + g_object_unref (priv->bus_cancellable); + priv->bus_cancellable = NULL; + } + + g_clear_pointer (&priv->introspection_data, g_dbus_node_info_unref); + need_flush = FALSE; dpy = gdk_display_get_default (); gdk_x11_display_error_trap_push (dpy); @@ -1596,22 +1753,29 @@ msd_media_keys_manager_stop (MsdMediaKeysManager *manager) } static void +msd_media_keys_manager_finalize (GObject *object) +{ + MsdMediaKeysManager *manager; + + g_return_if_fail (object != NULL); + g_return_if_fail (MSD_IS_MEDIA_KEYS_MANAGER (object)); + + manager = MSD_MEDIA_KEYS_MANAGER (object); + + g_return_if_fail (manager->priv != NULL); + + msd_media_keys_manager_stop (manager); + + G_OBJECT_CLASS (msd_media_keys_manager_parent_class)->finalize (object); +} + + +static void msd_media_keys_manager_class_init (MsdMediaKeysManagerClass *klass) { - 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); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = msd_media_keys_manager_finalize; } static void @@ -1620,23 +1784,50 @@ msd_media_keys_manager_init (MsdMediaKeysManager *manager) manager->priv = msd_media_keys_manager_get_instance_private (manager); } -static gboolean -register_manager (MsdMediaKeysManager *manager) + +static void +on_bus_gotten (GObject *source_object, + GAsyncResult *res, + MsdMediaKeysManager *manager) { + GDBusConnection *connection; 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; + connection = g_bus_get_finish (res, &error); + if (connection == NULL) { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("Could not get session bus: %s", error->message); + g_error_free (error); + return; } + manager->priv->connection = connection; + + g_dbus_connection_register_object (connection, + MSD_MEDIA_KEYS_DBUS_PATH, + manager->priv->introspection_data->interfaces[0], + &interface_vtable, + manager, + NULL, + NULL); + + manager->priv->owner_id = g_bus_own_name_on_connection (manager->priv->connection, + "org.mate.SettingsDaemon", + G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT, + NULL, NULL, NULL, NULL); +} - dbus_g_connection_register_g_object (manager->priv->connection, MSD_MEDIA_KEYS_DBUS_PATH, G_OBJECT (manager)); +static void +register_manager (MsdMediaKeysManager *manager) +{ - return TRUE; + manager->priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); + manager->priv->bus_cancellable = g_cancellable_new (); + g_assert (manager->priv->introspection_data != NULL); + + g_bus_get (G_BUS_TYPE_SESSION, + manager->priv->bus_cancellable, + (GAsyncReadyCallback) on_bus_gotten, + manager); } MsdMediaKeysManager * @@ -1645,16 +1836,10 @@ 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; - } + register_manager (manager_object); } return MSD_MEDIA_KEYS_MANAGER (manager_object); |