static void _check_if_seeked (ClutterMedia *media, GParamSpec *pspec, MexMprisPlugin *self) { MexMprisPluginPrivate *priv = MEX_MPRIS_PLUGIN (self)->priv; if (clutter_gst_player_get_in_seek (CLUTTER_GST_PLAYER (media))) { gdouble progress, duration; gint64 newposition; duration = clutter_media_get_duration (media); /* progress is in a range of 0.0 1.0 so convert to position in uS */ progress = clutter_media_get_progress (media); newposition = duration * progress * 1000000; g_dbus_connection_emit_signal (priv->connection, NULL, MPRIS_OBJECT_NAME, MPRIS_PLAYER_INTERFACE, "Seeked", g_variant_new ("(x)", newposition), NULL); } }
static gboolean _set_player_property_cb (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GVariant *value, GError **error, gpointer user_data) { MexMprisPluginPrivate *priv = MEX_MPRIS_PLUGIN (user_data)->priv; /* Currently unsupported properties */ if (g_strcmp0 (property_name, "LoopStatus") == 0 || g_strcmp0 (property_name, "Rate") == 0 || g_strcmp0 (property_name, "Shuffle") == 0) return FALSE; if (g_strcmp0 (property_name, "Volume") == 0) { clutter_media_set_audio_volume (priv->media, g_variant_get_double (value)); return TRUE; } g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "Property %s.%s not supported", interface_name, property_name); return FALSE; }
static void _player_method_cb (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, MexMprisPlugin *self) { MexMprisPluginPrivate *priv = MEX_MPRIS_PLUGIN (self)->priv; if (g_strcmp0 (method_name, "Next") == 0) mex_player_next (priv->player); else if (g_strcmp0 (method_name, "OpenUri") == 0) { const gchar *uri; g_variant_get (parameters, "(s)", &uri); mex_player_set_uri (priv->player, uri); } else if (g_strcmp0 (method_name, "Pause") == 0) mex_player_pause (priv->player); else if (g_strcmp0 (method_name, "Play") == 0) mex_player_play (priv->player); else if (g_strcmp0 (method_name, "PlayPause") == 0) mex_player_playpause (priv->player); else if (g_strcmp0 (method_name, "Previous") == 0) mex_player_previous (priv->player); else if (g_strcmp0 (method_name, "Seek") == 0) { gint64 seek_offset; g_variant_get (parameters, "(x)", &seek_offset); mex_player_seek_us (priv->player, seek_offset); } else if (g_strcmp0 (method_name, "Stop") == 0) mex_player_quit (priv->player); else g_message ("Unhandled MPRIS Player method %s", method_name); g_dbus_method_invocation_return_value (invocation, NULL); }
static void mex_mpris_plugin_finalize (GObject *object) { MexMprisPluginPrivate *priv = MEX_MPRIS_PLUGIN (object)->priv; if (priv->connection) g_object_unref (priv->connection); g_dbus_node_info_unref (priv->introspection_data); if (priv->mimes_supported) g_strfreev (priv->mimes_supported); G_OBJECT_CLASS (mex_mpris_plugin_parent_class)->finalize (object); }
static GVariant * _root_property_cb (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GError **error, MexMprisPlugin *self) { MexMprisPluginPrivate *priv = MEX_MPRIS_PLUGIN (self)->priv; if (g_strcmp0 (property_name, "SupportedUriSchemes") == 0) { const char *supported_schemes[] = { "file", "http", "cdda", "smb", "sftp", "ftp", NULL }; return g_variant_new_strv (supported_schemes, -1); } if (g_strcmp0 (property_name, "SupportedMimeTypes") == 0) return g_variant_new_strv ((const gchar**)priv->mimes_supported, -1); if (g_strcmp0 (property_name, "CanQuit") == 0 || g_strcmp0 (property_name, "CanRaise") == 0 || g_strcmp0 (property_name, "HasTrackList") == 0) return g_variant_new_boolean (FALSE); if (g_strcmp0 (property_name, "DesktopEntry") == 0) return g_variant_new_string ("media-explorer"); if (g_strcmp0 (property_name, "Identity") == 0) return g_variant_new_string ("Media Explorer"); g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "Property %s.%s not supported", interface_name, property_name); return NULL; }
static void on_bus_acquired (GObject *source_object, GAsyncResult *result, gpointer user_data) { MexMprisPlugin *self = user_data; MexMprisPluginPrivate *priv = MEX_MPRIS_PLUGIN (self)->priv; GError *error = NULL; priv->connection = g_bus_get_finish (result, &error); if (error) { g_warning ("Could not acquire bus connection: %s", error->message); g_error_free (error); return; } /* Note: Dbus object and name subject to change */ g_dbus_connection_register_object (priv->connection, MPRIS_OBJECT_NAME, priv->introspection_data->interfaces[0], &root_interface_table, self, NULL, &error); g_dbus_connection_register_object (priv->connection, MPRIS_OBJECT_NAME, priv->introspection_data->interfaces[1], &player_interface_table, self, NULL, &error); if (error) { g_warning ("Problem registering object: %s", error->message); g_error_free (error); } }
static void _player_method_cb (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, MexMprisPlugin *self) { MexMprisPluginPrivate *priv = MEX_MPRIS_PLUGIN (self)->priv; if (g_strcmp0 (method_name, "Next") == 0) { if (CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR (priv->music)) || mex_music_player_is_playing (priv->music)) mex_music_player_next (priv->music); else mex_player_next (priv->player); } else if (g_strcmp0 (method_name, "OpenUri") == 0) { const gchar *uri; char *pfx; g_variant_get (parameters, "(s)", &uri); if ((pfx = _content_mime_prefix (uri))) { if (!strcmp (pfx, "audio")) mex_music_player_set_uri (priv->music, uri); else if (!strcmp (pfx, "image")) g_warning ("Mpris image playback is not implemented"); else mex_player_set_uri (priv->player, uri); } else mex_player_set_uri (priv->player, uri); } else if (g_strcmp0 (method_name, "Pause") == 0) { if (CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR (priv->music)) || mex_music_player_is_playing (priv->music)) mex_music_player_stop (priv->music); else mex_player_pause (priv->player); } else if (g_strcmp0 (method_name, "Play") == 0) { if (CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR (priv->music)) || mex_music_player_is_playing (priv->music)) mex_music_player_play (priv->music); else mex_player_play (priv->player); } else if (g_strcmp0 (method_name, "PlayPause") == 0) { if (CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR (priv->music)) || mex_music_player_is_playing (priv->music)) mex_music_player_play_toggle (priv->music); else mex_player_playpause (priv->player); } else if (g_strcmp0 (method_name, "Previous") == 0) { if (CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR (priv->music)) || mex_music_player_is_playing (priv->music)) mex_music_player_previous (priv->music); else mex_player_previous (priv->player); } else if (g_strcmp0 (method_name, "Seek") == 0) { gint64 seek_offset; g_variant_get (parameters, "(x)", &seek_offset); if (CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR (priv->music)) || mex_music_player_is_playing (priv->music)) mex_music_player_seek_us (priv->music, seek_offset); else mex_player_seek_us (priv->player, seek_offset); } else if (g_strcmp0 (method_name, "Stop") == 0) { if (CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR (priv->music)) || mex_music_player_is_playing (priv->music)) mex_music_player_quit (priv->music); else mex_player_quit (priv->player); } else g_message ("Unhandled MPRIS Player method %s", method_name); g_dbus_method_invocation_return_value (invocation, NULL); }
static GVariant * _get_player_property_cb (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GError **error, gpointer user_data) { MexMprisPluginPrivate *priv = MEX_MPRIS_PLUGIN (user_data)->priv; ClutterMedia *media; GVariant *v = NULL; if (mex_music_player_is_playing (priv->music)) media = mex_music_player_get_clutter_media (priv->music); else media = mex_player_get_clutter_media (priv->player); if (g_strcmp0 ("PlaybackStatus", property_name) == 0) { /* Doesn't map to ClutterMedia straight away so try to emulate. * Playback could theoretically be paused at progress 0.0 but well ...*/ gdouble progress = clutter_media_get_progress (media); gboolean playing = clutter_media_get_playing (media); if (playing) v = g_variant_new_string ("Playing"); else if (progress != 0) v = g_variant_new_string ("Paused"); else v = g_variant_new_string ("Stopped"); } else if (g_strcmp0 ("LoopStatus", property_name) == 0) v = g_variant_new_string ("None"); else if (g_strcmp0 ("Rate", property_name) == 0 || g_strcmp0 ("MinimumRate", property_name) == 0 || g_strcmp0 ("MinimumRate", property_name) == 0 ) v = g_variant_new_double (1.0); else if (g_strcmp0 ("Shuffle", property_name) == 0) v = g_variant_new_boolean (FALSE); else if (g_strcmp0 ("Volume", property_name) == 0) v = g_variant_new_double (clutter_media_get_audio_volume (media)); else if (g_strcmp0 ("Position", property_name) == 0) { gdouble duration_s = clutter_media_get_duration (media); gdouble progress_rel = clutter_media_get_progress (media); gint64 position_ms = duration_s * 1000000 * progress_rel; v = g_variant_new_int64 (position_ms); } else if (g_strcmp0 ("CanGoNext", property_name) == 0 || g_strcmp0 ("CanGoPrevious", property_name) == 0 || g_strcmp0 ("CanPlay", property_name) == 0 || g_strcmp0 ("CanControl", property_name) == 0 || g_strcmp0 ("CanPause", property_name) == 0) v = g_variant_new_boolean (TRUE); else if (g_strcmp0 ("CanSeek", property_name) == 0) v = g_variant_new_boolean (clutter_media_get_can_seek (media)); if (v) return v; g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "Property %s.%s not supported", interface_name, property_name); return NULL; }