[rhythmbox] revive rhythmbox-client using new dbus interfaces + mpris
- From: Jonathan Matthew <jmatthew src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [rhythmbox] revive rhythmbox-client using new dbus interfaces + mpris
- Date: Wed, 28 Sep 2011 23:47:06 +0000 (UTC)
commit 5ec27a0dece6eb6d7e4d77da4f02f393bbe5c47f
Author: Jonathan Matthew <jonathan d14n org>
Date: Thu Sep 29 09:45:10 2011 +1000
revive rhythmbox-client using new dbus interfaces + mpris
remote/dbus/Makefile.am | 7 +-
remote/dbus/rb-client.c | 670 ++++++++++++++++++++++++++---------------------
2 files changed, 370 insertions(+), 307 deletions(-)
---
diff --git a/remote/dbus/Makefile.am b/remote/dbus/Makefile.am
index 7fede7c..12e80c4 100644
--- a/remote/dbus/Makefile.am
+++ b/remote/dbus/Makefile.am
@@ -1,5 +1,4 @@
-bin_PROGRAMS =
-# rhythmbox-client
+bin_PROGRAMS = rhythmbox-client
rhythmbox_client_SOURCES = rb-client.c
rhythmbox_client_LDADD = \
$(top_builddir)/lib/librb.la \
@@ -16,9 +15,9 @@ INCLUDES = \
-DPIXMAP_DIR=\""$(datadir)/pixmaps"\" \
-DSHARE_DIR=\"$(pkgdatadir)\" \
-DDATADIR=\""$(datadir)"\" \
- $(RB_CLIENT_CFLAGS) \
+ $(RHYTHMBOX_CFLAGS) \
$(DBUS_CFLAGS) \
- -D_XOPEN_SOURCE -D__EXTENSIONS__ -D_BSD_SOURCE
+ -D__EXTENSIONS__ -D_BSD_SOURCE
EXTRA_DIST = rb-client.c rb-print-playing.py rb-set-rating.py
diff --git a/remote/dbus/rb-client.c b/remote/dbus/rb-client.c
index d6ec452..b881cb8 100644
--- a/remote/dbus/rb-client.c
+++ b/remote/dbus/rb-client.c
@@ -33,12 +33,9 @@
#include <glib.h>
#include <glib/gi18n.h>
#include <glib-object.h>
-#include <dbus/dbus-glib.h>
#include <gio/gio.h>
#include "rb-debug.h"
-#include "rb-shell-binding.h"
-#include "rb-shell-player-binding.h"
static gboolean debug = FALSE;
@@ -47,14 +44,11 @@ static gboolean quit = FALSE;
static gboolean check_running = FALSE;
static gboolean no_present = FALSE;
-static gboolean hide = FALSE;
static gboolean next = FALSE;
static gboolean previous = FALSE;
static gint32 seek = 0;
-static gboolean notify = FALSE;
-
static gboolean play = FALSE;
static gboolean do_pause = FALSE;
static gboolean play_pause = FALSE;
@@ -75,8 +69,8 @@ static gdouble set_volume = -1.0;
static gboolean volume_up = FALSE;
static gboolean volume_down = FALSE;
static gboolean print_volume = FALSE;
-static gboolean mute = FALSE;
-static gboolean unmute = FALSE;
+/*static gboolean mute = FALSE;
+static gboolean unmute = FALSE; */
static gdouble set_rating = -1.0;
static gchar **other_stuff = NULL;
@@ -89,14 +83,11 @@ static GOptionEntry args[] = {
{ "check-running", 0, 0, G_OPTION_ARG_NONE, &check_running, N_("Check if Rhythmbox is already running"), NULL },
{ "no-present", 0, 0, G_OPTION_ARG_NONE, &no_present, N_("Don't present an existing Rhythmbox window"), NULL },
- { "hide", 0, 0, G_OPTION_ARG_NONE, &hide, N_("Hide the Rhythmbox window"), NULL },
{ "next", 0, 0, G_OPTION_ARG_NONE, &next, N_("Jump to next song"), NULL },
{ "previous", 0, 0, G_OPTION_ARG_NONE, &previous, N_("Jump to previous song"), NULL },
{ "seek", 0, 0, G_OPTION_ARG_INT64, &seek, N_("Seek in current track"), NULL },
- { "notify", 0, 0, G_OPTION_ARG_NONE, ¬ify, N_("Show notification of the playing song"), NULL },
-
{ "play", 0, 0, G_OPTION_ARG_NONE, &play, N_("Resume playback if currently paused"), NULL },
{ "pause", 0, 0, G_OPTION_ARG_NONE, &do_pause, N_("Pause playback if currently playing"), NULL },
{ "play-pause", 0, 0, G_OPTION_ARG_NONE, &play_pause, N_("Toggle play/pause mode"), NULL },
@@ -116,8 +107,8 @@ static GOptionEntry args[] = {
{ "volume-up", 0, 0, G_OPTION_ARG_NONE, &volume_up, N_("Increase the playback volume"), NULL },
{ "volume-down", 0, 0, G_OPTION_ARG_NONE, &volume_down, N_("Decrease the playback volume"), NULL },
{ "print-volume", 0, 0, G_OPTION_ARG_NONE, &print_volume, N_("Print the current playback volume"), NULL },
- { "mute", 0, 0, G_OPTION_ARG_NONE, &mute, N_("Mute playback"), NULL },
- { "unmute", 0, 0, G_OPTION_ARG_NONE, &unmute, N_("Unmute playback"), NULL },
+/* { "mute", 0, 0, G_OPTION_ARG_NONE, &mute, N_("Mute playback"), NULL },
+ { "unmute", 0, 0, G_OPTION_ARG_NONE, &unmute, N_("Unmute playback"), NULL }, */
{ "set-rating", 0, 0, G_OPTION_ARG_DOUBLE, &set_rating, N_("Set the rating of the current song"), NULL },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &other_stuff, NULL, NULL },
@@ -125,9 +116,6 @@ static GOptionEntry args[] = {
{ NULL }
};
-static gboolean db_load_complete = FALSE;
-static gboolean scan_finished = FALSE;
-
static gboolean
annoy (GError **error)
{
@@ -142,11 +130,12 @@ annoy (GError **error)
static char *
-rb_make_duration_string (guint duration)
+rb_make_duration_string (gint64 duration)
{
char *str;
int hours, minutes, seconds;
+ duration /= G_USEC_PER_SEC;
hours = duration / (60 * 60);
minutes = (duration - (hours * 60 * 60)) / 60;
seconds = duration % 60;
@@ -189,7 +178,7 @@ rb_make_duration_string (guint duration)
* %st -- stream title
*/
static char *
-parse_pattern (const char *pattern, GHashTable *properties, guint elapsed)
+parse_pattern (const char *pattern, GHashTable *properties, gint64 elapsed)
{
/* p is the pattern iterator, i is a general purpose iterator */
const char *p;
@@ -204,7 +193,8 @@ parse_pattern (const char *pattern, GHashTable *properties, guint elapsed)
p = pattern;
while (*p) {
char *string = NULL;
- const GValue *value = NULL;
+ const char **strv = NULL;
+ GVariant *value = NULL;
/* If not a % marker, copy and continue */
if (*p != '%') {
@@ -227,62 +217,80 @@ parse_pattern (const char *pattern, GHashTable *properties, guint elapsed)
*/
switch (*++p) {
case 't':
- value = g_hash_table_lookup (properties, "album");
+ value = g_hash_table_lookup (properties, "xesam:album");
if (value)
- string = g_value_dup_string (value);
+ string = g_variant_dup_string (value, NULL);
break;
case 'T':
- value = g_hash_table_lookup (properties, "album-folded");
+ value = g_hash_table_lookup (properties, "xesam:album");
if (value)
- string = g_value_dup_string (value);
+ string = g_utf8_strdown (g_variant_get_string (value, NULL), -1);
break;
case 'a':
- value = g_hash_table_lookup (properties, "artist");
- if (value)
- string = g_value_dup_string (value);
+ value = g_hash_table_lookup (properties, "xesam:artist");
+ if (value) {
+ strv = g_variant_get_strv (value, NULL);
+ string = g_strdup (strv[0]);
+ }
break;
case 'A':
- value = g_hash_table_lookup (properties, "artist-folded");
- if (value)
- string = g_value_dup_string (value);
+ value = g_hash_table_lookup (properties, "xesam:artist");
+ if (value) {
+ strv = g_variant_get_strv (value, NULL);
+ string = g_utf8_strdown (strv[0], -1);
+ }
break;
case 's':
- value = g_hash_table_lookup (properties, "mb-artistsortname");
+ value = g_hash_table_lookup (properties, "rhythmbox:albumArtistSortname");
if (value)
- string = g_value_dup_string (value);
+ string = g_variant_dup_string (value, NULL);
break;
case 'S':
- value = g_hash_table_lookup (properties, "mb-artistsortname");
+ value = g_hash_table_lookup (properties, "rhythmbox:albumArtistSortname");
if (value)
- string = g_utf8_strdown (g_value_get_string (value), -1);
+ string = g_utf8_strdown (g_variant_get_string (value, NULL), -1);
break;
case 'y':
/* Release year */
- value = g_hash_table_lookup (properties, "year");
- if (value)
- string = g_strdup_printf ("%u", g_value_get_uint (value));
+ value = g_hash_table_lookup (properties, "xesam:contentCreated");
+ if (value) {
+ const char *iso8601;
+ GTimeVal tv;
+
+ iso8601 = g_variant_get_string (value, NULL);
+ if (g_time_val_from_iso8601 (iso8601, &tv)) {
+ GDate d;
+ g_date_set_time_val (&d, &tv);
+
+ string = g_strdup_printf ("%u", g_date_get_year (&d));
+ }
+ }
break;
/* Disc number */
case 'n':
- value = g_hash_table_lookup (properties, "disc-number");
+ value = g_hash_table_lookup (properties, "xesam:discNumber");
if (value)
- string = g_strdup_printf ("%u", g_value_get_uint (value));
+ string = g_strdup_printf ("%u", g_variant_get_int32 (value));
break;
case 'N':
- value = g_hash_table_lookup (properties, "disc-number");
+ value = g_hash_table_lookup (properties, "xesam:discNumber");
if (value)
- string = g_strdup_printf ("%02u", g_value_get_uint (value));
+ string = g_strdup_printf ("%02u", g_variant_get_int32 (value));
break;
/* genre */
case 'g':
- value = g_hash_table_lookup (properties, "genre");
- if (value)
- string = g_value_dup_string (value);
+ value = g_hash_table_lookup (properties, "xesam:genre");
+ if (value) {
+ strv = g_variant_get_strv (value, NULL);
+ string = g_strdup (strv[0]);
+ }
break;
case 'G':
- value = g_hash_table_lookup (properties, "genre-folded");
- if (value)
- string = g_value_dup_string (value);
+ value = g_hash_table_lookup (properties, "xesam:genre");
+ if (value) {
+ strv = g_variant_get_strv (value, NULL);
+ string = g_utf8_strdown (strv[0], -1);
+ }
break;
default:
string = g_strdup_printf ("%%a%c", *p);
@@ -296,52 +304,60 @@ parse_pattern (const char *pattern, GHashTable *properties, guint elapsed)
*/
switch (*++p) {
case 't':
- value = g_hash_table_lookup (properties, "title");
+ value = g_hash_table_lookup (properties, "rhythmbox:streamTitle");
+ if (value == NULL)
+ value = g_hash_table_lookup (properties, "xesam:title");
if (value)
- string = g_value_dup_string (value);
+ string = g_variant_dup_string (value, NULL);
break;
case 'T':
- value = g_hash_table_lookup (properties, "title-folded");
+ value = g_hash_table_lookup (properties, "rhythmbox:streamTitle");
+ if (value == NULL)
+ value = g_hash_table_lookup (properties, "xesam:title");
if (value)
- string = g_value_dup_string (value);
+ string = g_utf8_strdown (g_variant_get_string (value, NULL), -1);
break;
case 'a':
- value = g_hash_table_lookup (properties, "artist");
- if (value)
- string = g_value_dup_string (value);
+ value = g_hash_table_lookup (properties, "xesam:artist");
+ if (value) {
+ strv = g_variant_get_strv (value, NULL);
+ string = g_strdup (strv[0]);
+ }
break;
case 'A':
- value = g_hash_table_lookup (properties, "artist-folded");
- if (value)
- string = g_value_dup_string (value);
+ value = g_hash_table_lookup (properties, "xesam:artist");
+ if (value) {
+ strv = g_variant_get_strv (value, NULL);
+ string = g_utf8_strdown (strv[0], -1);
+ }
break;
case 's':
- value = g_hash_table_lookup (properties, "mb-artistsortname");
+ value = g_hash_table_lookup (properties, "rhythmbox:artistSortname");
if (value)
- string = g_value_dup_string (value);
+ string = g_variant_dup_string (value, NULL);
break;
case 'S':
- value = g_hash_table_lookup (properties, "mb-artistsortname");
+ value = g_hash_table_lookup (properties, "rhythmbox:artistSortname");
if (value)
- string = g_utf8_strdown (g_value_get_string (value), -1);
+ string = g_utf8_strdown (g_variant_get_string (value, NULL), -1);
break;
case 'n':
/* Track number */
- value = g_hash_table_lookup (properties, "track-number");
+ value = g_hash_table_lookup (properties, "xesam:trackNumber");
if (value)
- string = g_strdup_printf ("%u", g_value_get_uint (value));
+ string = g_strdup_printf ("%u", g_variant_get_int32 (value));
break;
case 'N':
/* Track number, zero-padded */
- value = g_hash_table_lookup (properties, "track-number");
+ value = g_hash_table_lookup (properties, "xesam:trackNumber");
if (value)
- string = g_strdup_printf ("%02u", g_value_get_uint (value));
+ string = g_strdup_printf ("%02u", g_variant_get_int32 (value));
break;
case 'd':
/* Track duration */
- value = g_hash_table_lookup (properties, "duration");
+ value = g_hash_table_lookup (properties, "xesam:length");
if (value)
- string = rb_make_duration_string (g_value_get_uint (value));
+ string = rb_make_duration_string (g_variant_get_int64 (value));
break;
case 'e':
/* Track elapsed time */
@@ -349,9 +365,9 @@ parse_pattern (const char *pattern, GHashTable *properties, guint elapsed)
break;
case 'b':
/* Track bitrate */
- value = g_hash_table_lookup (properties, "bitrate");
+ value = g_hash_table_lookup (properties, "xesam:audioBitrate");
if (value)
- string = g_strdup_printf ("%u", g_value_get_uint (value));
+ string = g_strdup_printf ("%u", g_variant_get_int32 (value) / 1024);
break;
default:
@@ -366,17 +382,19 @@ parse_pattern (const char *pattern, GHashTable *properties, guint elapsed)
*/
switch (*++p) {
case 't':
- value = g_hash_table_lookup (properties, "rb:stream-song-title");
- if (value)
- string = g_value_dup_string (value);
+ value = g_hash_table_lookup (properties, "rhythmbox:streamTitle");
+ if (value) {
+ value = g_hash_table_lookup (properties, "xesam:title");
+ if (value) {
+ string = g_variant_dup_string (value, NULL);
+ }
+ }
break;
default:
string = g_strdup_printf ("%%s%c", *p);
}
-
break;
-
default:
string = g_strdup_printf ("%%%c", *p);
}
@@ -394,83 +412,59 @@ parse_pattern (const char *pattern, GHashTable *properties, guint elapsed)
}
-
-static gboolean
-create_rb_shell_proxies (DBusGConnection *bus, DBusGProxy **shell_proxy, DBusGProxy **player_proxy, GError **error)
-{
- DBusGProxy *sp;
-
- rb_debug ("creating shell proxy");
- sp = dbus_g_proxy_new_for_name_owner (bus,
- "org.gnome.Rhythmbox",
- "/org/gnome/Rhythmbox/Shell",
- "org.gnome.Rhythmbox.Shell",
- error);
- if (*error) {
- *shell_proxy = NULL;
- return ((*error)->code == DBUS_GERROR_NAME_HAS_NO_OWNER);
- }
- dbus_g_proxy_add_signal (sp, "removableMediaScanFinished", G_TYPE_INVALID);
- dbus_g_proxy_add_signal (sp, "databaseLoadComplete", G_TYPE_INVALID);
-
- rb_debug ("creating player proxy");
- *player_proxy = dbus_g_proxy_new_from_proxy (sp,
- "org.gnome.Rhythmbox.Player",
- "/org/gnome/Rhythmbox/Player");
- if (*player_proxy == NULL) {
- g_object_unref (G_OBJECT (sp));
- *shell_proxy = NULL;
- *player_proxy = NULL;
- return FALSE;
- }
-
- *shell_proxy = sp;
- return TRUE;
-}
-
static GHashTable *
-get_playing_song_info (DBusGProxy *shell_proxy, DBusGProxy *player_proxy, GError **error)
+get_playing_song_info (GDBusProxy *mpris)
{
- char *playing_uri;
GHashTable *properties;
+ GVariant *prop;
+ GVariant *metadata;
+ GVariantIter iter;
+ GVariant *value;
+ char *key;
+ GError *error = NULL;
- org_gnome_Rhythmbox_Player_get_playing_uri (player_proxy, &playing_uri, error);
- if (*error != NULL) {
+ prop = g_dbus_proxy_call_sync (mpris,
+ "org.freedesktop.DBus.Properties.Get",
+ g_variant_new ("(ss)", "org.mpris.MediaPlayer2.Player", "Metadata"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ if (annoy (&error)) {
return NULL;
}
- if (!playing_uri || playing_uri[0] == '\0') {
- return NULL;
- }
+ g_variant_get (prop, "(v)", &metadata);
- rb_debug ("playing song is %s", playing_uri);
- org_gnome_Rhythmbox_Shell_get_song_properties (shell_proxy, playing_uri, &properties, error);
- if (*error != NULL) {
- return NULL;
+ properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
+ g_variant_iter_init (&iter, metadata);
+ while (g_variant_iter_loop (&iter, "{sv}", &key, &value)) {
+ g_hash_table_insert (properties, g_strdup (key), g_variant_ref (value));
}
+ g_variant_unref (prop);
return properties;
}
static void
-print_playing_song (DBusGProxy *shell_proxy, DBusGProxy *player_proxy, const char *format)
+print_playing_song (GDBusProxy *mpris, const char *format)
{
GHashTable *properties;
- guint elapsed = 0;
- GError *error = NULL;
+ GVariant *v;
+ gint64 elapsed = 0;
char *string;
- properties = get_playing_song_info (shell_proxy, player_proxy, &error);
- if (annoy (&error)) {
- return;
- }
+ properties = get_playing_song_info (mpris);
if (properties == NULL) {
g_print ("%s\n", _("Not playing"));
return;
}
-
- org_gnome_Rhythmbox_Player_get_elapsed (player_proxy, &elapsed, &error);
- annoy (&error);
+
+ v = g_dbus_proxy_get_cached_property (mpris, "Position");
+ if (v != NULL) {
+ elapsed = g_variant_get_int64 (v);
+ g_variant_unref (v);
+ }
string = parse_pattern (format, properties, elapsed);
g_print ("%s\n", string);
@@ -479,22 +473,18 @@ print_playing_song (DBusGProxy *shell_proxy, DBusGProxy *player_proxy, const cha
}
static void
-print_playing_song_default (DBusGProxy *shell_proxy, DBusGProxy *player_proxy)
+print_playing_song_default (GDBusProxy *mpris)
{
GHashTable *properties;
char *string;
- GError *error = NULL;
- properties = get_playing_song_info (shell_proxy, player_proxy, &error);
- if (annoy (&error)) {
- return;
- }
+ properties = get_playing_song_info (mpris);
if (properties == NULL) {
g_print ("%s\n", _("Not playing"));
return;
}
- if (g_hash_table_lookup (properties, "rb:stream-song-title") != NULL) {
+ if (g_hash_table_lookup (properties, "rhythmbox:streamTitle") != NULL) {
string = parse_pattern ("%st (%tt)", properties, 0);
} else {
string = parse_pattern ("%ta - %tt", properties, 0);
@@ -506,73 +496,104 @@ print_playing_song_default (DBusGProxy *shell_proxy, DBusGProxy *player_proxy)
}
static void
-rate_song (DBusGProxy *shell_proxy, DBusGProxy *player_proxy, gdouble song_rating)
+rate_song (GDBusProxy *mpris, gdouble song_rating)
{
+ GHashTable *properties;
+ GVariantBuilder props;
+ GVariant *v;
GError *error = NULL;
- char *playing_uri;
- GValue *value = NULL;
- org_gnome_Rhythmbox_Player_get_playing_uri (player_proxy, &playing_uri, &error);
- if (annoy (&error)) {
+ properties = get_playing_song_info (mpris);
+ if (properties == NULL) {
+ rb_debug ("can't set rating when not playing");
return;
}
- if (!playing_uri || playing_uri[0] == '\0') {
+ v = g_hash_table_lookup (properties, "xesam:uri");
+ if (v == NULL) {
+ rb_debug ("can't set rating, no uri");
return;
}
- rb_debug ("rating song %s: %f", playing_uri, song_rating);
-
- value = g_new0 (GValue, 1);
- g_value_init (value, G_TYPE_DOUBLE);
- g_value_set_double (value, song_rating);
- org_gnome_Rhythmbox_Shell_set_song_property (shell_proxy, playing_uri, "rating", value, &error);
- annoy (&error);
-
- g_free (value);
- g_free (playing_uri);
+ g_variant_builder_init (&props, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&props, "{sv}", "rating", g_variant_new_double (song_rating));
+
+ g_dbus_connection_call_sync (g_dbus_proxy_get_connection (mpris),
+ "org.gnome.Rhythmbox3",
+ "/org/gnome/Rhythmbox3/RhythmDB",
+ "org.gnome.Rhythmbox3.RhythmDB",
+ "SetEntryProperties",
+ g_variant_new ("(sa{sv})", v, g_variant_builder_end (&props)),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ if (error != NULL) {
+ g_warning ("Error setting rating on %s: %s",
+ g_variant_get_string (v, NULL),
+ error->message);
+ g_clear_error (&error);
+ }
+ g_hash_table_destroy (properties);
}
static void
-maybe_unblock (GMainLoop *loop)
+state_changed_cb (GActionGroup *action, const char *action_name, GVariant *state, GMainLoop *loop)
{
- if (db_load_complete && scan_finished) {
- /* FIXME - we're not really ready to accept playback control just yet.
- * the library (at least) needs to populate itself with the database contents,
- * which takes some non-zero amount of time. this hack makes things work
- * somewhat reliably.
- */
- g_usleep (G_USEC_PER_SEC);
- g_main_loop_quit (loop);
+ if (g_strcmp0 (action_name, "LoadURI") == 0) {
+ gboolean loaded, scanned;
+
+ g_variant_get (state, "(bb)", &loaded, &scanned);
+ if (loaded && scanned) {
+ /* give it a tiny bit longer to populate sources etc. */
+ g_timeout_add (1500, (GSourceFunc) g_main_loop_quit, loop);
+ }
}
}
static void
-scan_finished_cb (DBusGProxy *proxy, GMainLoop *loop)
+state_changed_signal_cb (GDBusProxy *proxy, const char *sender_name, const char *signal_name, GVariant *parameters, GMainLoop *loop)
{
- rb_debug ("removable media scan finished");
- scan_finished = TRUE;
- maybe_unblock (loop);
+ const char *action;
+ GVariant *state;
+ if (g_strcmp0 (signal_name, "StateChanged") != 0) {
+ return;
+ }
+
+ g_variant_get (parameters, "(sv)", &action, &state);
+ if (g_strcmp0 (action, "LoadURI") == 0) {
+ GApplication *app;
+ app = g_object_get_data (G_OBJECT (proxy), "actual-app");
+ state_changed_cb (G_ACTION_GROUP (app), action, state, loop);
+ }
+ g_variant_unref (state);
}
-static void
-db_load_complete_cb (DBusGProxy *proxy, GMainLoop *loop)
+static gboolean
+proxy_has_name_owner (GDBusProxy *proxy)
{
- rb_debug ("database load complete");
- db_load_complete = TRUE;
- maybe_unblock (loop);
+ gboolean has_owner;
+ char *owner = g_dbus_proxy_get_name_owner (proxy);
+
+ has_owner = (owner != NULL);
+ g_free (owner);
+ return has_owner;
}
+
int
main (int argc, char **argv)
{
GOptionContext *context;
- gboolean ok;
GError *error = NULL;
- DBusGConnection *bus;
- DBusGProxy *shell_proxy = NULL;
- DBusGProxy *player_proxy = NULL;
- gboolean is_playing;
+ GDBusConnection *bus;
+ GDBusProxy *mpris;
+ GDBusProxy *queue;
+ GApplication *app;
+ gboolean loaded;
+ gboolean scanned;
+ GVariant *state;
#ifdef ENABLE_NLS
/* initialize i18n */
@@ -588,84 +609,104 @@ main (int argc, char **argv)
/* parse arguments */
context = g_option_context_new (NULL);
g_option_context_add_main_entries (context, args, NULL);
- ok = g_option_context_parse (context, &argc, &argv, &error);
+ g_option_context_parse (context, &argc, &argv, &error);
if (annoy (&error))
exit (1);
rb_debug_init (debug);
- /* get dbus connection and proxy for rhythmbox shell */
- bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
- if (annoy (&error))
- exit (1);
+ app = g_application_new ("org.gnome.Rhythmbox3", G_APPLICATION_IS_LAUNCHER);
+ if (g_application_register (app, NULL, &error) == FALSE) {
+ if (check_running) {
+ rb_debug ("no running instance found");
+ exit (2);
+ } else if (quit) {
+ rb_debug ("no existing instance to quit");
+ exit (0);
+ }
- if (!create_rb_shell_proxies (bus, &shell_proxy, &player_proxy, &error)) {
- annoy (&error);
- exit (1);
+ rb_debug ("uh.. what?");
+ exit (0);
}
- g_clear_error (&error);
+
/* are we just checking if it's running? */
if (check_running) {
- if (shell_proxy) {
- rb_debug ("running instance found");
- exit (0);
- } else {
- rb_debug ("no running instance found");
- exit (2);
- }
+ rb_debug ("running instance found");
+ exit (0);
}
- /* 1. activate or quit */
- if (quit) {
- if (shell_proxy) {
- rb_debug ("quitting existing instance");
- dbus_g_proxy_call_no_reply (shell_proxy, "quit", G_TYPE_INVALID);
- } else {
- rb_debug ("no existing instance to quit");
- }
-
+ /* wait until it's ready to accept control */
+ state = g_action_group_get_action_state (G_ACTION_GROUP (app), "LoadURI");
+ if (state == NULL) {
+ rb_debug ("couldn't get app startup state");
exit (0);
}
- if (shell_proxy == NULL) {
- DBusGProxy *bus_proxy;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+ g_variant_get (state, "(bb)", &loaded, &scanned);
+ if ((loaded && scanned) == FALSE) {
GMainLoop *loop;
- guint start_service_reply;
+ GDBusProxy *app_proxy;
- if (no_start) {
- rb_debug ("no existing instance, and can't start one");
- exit (0);
+ rb_debug ("waiting for app startup");
+ loop = g_main_loop_new (NULL, FALSE);
+ g_signal_connect (app, "action-state-changed", G_CALLBACK (state_changed_cb), loop);
+
+ /* dbus implementation of GApplication doesn't do action state updates yet */
+ app_proxy = g_dbus_proxy_new_sync (bus, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, NULL,
+ "org.gnome.Rhythmbox3",
+ "/org/gnome/Rhythmbox3",
+ "org.gtk.Actions",
+ NULL,
+ &error);
+ if (app_proxy == NULL || proxy_has_name_owner (app_proxy) == FALSE) {
+ g_warning ("unable to wait for app startup: %s", error->message);
+ g_clear_error (&error);
+ } else {
+ g_object_set_data (G_OBJECT (app_proxy), "actual-app", app);
+ g_signal_connect (app_proxy, "g-signal", G_CALLBACK (state_changed_signal_cb), loop);
+ g_main_loop_run (loop);
+ rb_debug ("app is now started enough");
}
+ }
- rb_debug ("starting new instance");
- bus_proxy = dbus_g_proxy_new_for_name (bus,
- "org.freedesktop.DBus",
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus");
-
- if (!dbus_g_proxy_call (bus_proxy, "StartServiceByName", &error,
- G_TYPE_STRING, "org.gnome.Rhythmbox",
- G_TYPE_UINT, 0,
- G_TYPE_INVALID,
- G_TYPE_UINT, &start_service_reply,
- G_TYPE_INVALID)) {
- g_warning ("%s", error->message);
+ /* create proxies */
+ mpris = g_dbus_proxy_new_sync (bus,
+ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+ NULL,
+ "org.mpris.MediaPlayer2.rhythmbox3",
+ "/org/mpris/MediaPlayer2",
+ "org.mpris.MediaPlayer2.Player",
+ NULL,
+ &error);
+ if (mpris == NULL || proxy_has_name_owner (mpris) == FALSE) {
+ g_warning ("MPRIS D-Bus interface not available, some things won't work");
+ if (next || previous || (seek != 0) || play || do_pause || play_pause || stop || volume_up || volume_down || (set_volume > -0.01)) {
exit (1);
}
+ }
- /* hopefully we can get a proxy for the rb shell now.. */
- if (!create_rb_shell_proxies (bus, &shell_proxy, &player_proxy, &error)) {
- annoy (&error);
+ queue = g_dbus_proxy_new_sync (bus,
+ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+ NULL,
+ "org.gnome.Rhythmbox3",
+ "/org/gnome/Rhythmbox3/PlayQueue",
+ "org.gnome.Rhythmbox3.PlayQueue",
+ NULL,
+ &error);
+ if (queue == NULL || proxy_has_name_owner (queue) == FALSE) {
+ g_warning ("Play queue interface not available, some things won't work");
+ if (enqueue || clear_queue) {
exit (1);
}
- g_clear_error (&error);
+ }
- /* wait for it to load enough state to be useful */
- rb_debug ("waiting for database load and removable media scan to finish");
- loop = g_main_loop_new (NULL, FALSE);
- dbus_g_proxy_connect_signal (shell_proxy, "removableMediaScanFinished", G_CALLBACK (scan_finished_cb), loop, NULL);
- dbus_g_proxy_connect_signal (shell_proxy, "databaseLoadComplete", G_CALLBACK (db_load_complete_cb), loop, NULL);
- g_main_loop_run (loop);
+ /* activate or quit */
+ if (quit) {
+ rb_debug ("quitting existing instance");
+ g_action_group_activate_action (G_ACTION_GROUP (app), "Quit", NULL);
+ exit (0);
}
/* don't present if we're doing something else */
@@ -673,50 +714,57 @@ main (int argc, char **argv)
clear_queue ||
play_uri || other_stuff ||
play || do_pause || play_pause || stop ||
- print_playing || print_playing_format || notify ||
- (set_volume > -0.01) || volume_up || volume_down || print_volume || mute || unmute || (set_rating > -0.01))
+ print_playing || print_playing_format ||
+ (set_volume > -0.01) || volume_up || volume_down || print_volume /*|| mute || unmute*/ || (set_rating > -0.01))
no_present = TRUE;
- /* 2. present or hide */
- if (hide || !no_present) {
- DBusGProxy *properties_proxy;
- GValue value = {0,};
-
- rb_debug ("setting visibility property");
- g_value_init (&value, G_TYPE_BOOLEAN);
- g_value_set_boolean (&value, !hide);
- properties_proxy = dbus_g_proxy_new_from_proxy (shell_proxy,
- "org.freedesktop.DBus.Properties",
- "/org/gnome/Rhythmbox/Shell");
- dbus_g_proxy_call_no_reply (properties_proxy, "Set",
- G_TYPE_STRING, "org.gnome.Rhythmbox.Shell",
- G_TYPE_STRING, "visibility",
- G_TYPE_VALUE, &value,
- G_TYPE_INVALID);
- g_object_unref (G_OBJECT (properties_proxy));
- }
-
- /* 3. skip to next or previous track */
+ /* present */
+ if (!no_present) {
+ g_application_activate (app);
+ }
+
+ /* set song rating */
+ if (set_rating >= 0.0 && set_rating <= 5.0) {
+ rb_debug ("rate song");
+
+ rate_song (mpris, set_rating);
+ }
+
+ /* skip to next or previous track */
if (next) {
rb_debug ("next track");
- org_gnome_Rhythmbox_Player_next (player_proxy, &error);
+ g_dbus_proxy_call_sync (mpris, "Next", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
annoy (&error);
} else if (previous) {
rb_debug ("previous track");
- org_gnome_Rhythmbox_Player_previous (player_proxy, &error);
+ g_dbus_proxy_call_sync (mpris, "Previous", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
annoy (&error);
}
/* seek in track */
if (seek != 0) {
+ GHashTable *properties;
rb_debug ("seek");
- org_gnome_Rhythmbox_Player_seek (player_proxy, seek, &error);
- annoy (&error);
+
+ properties = get_playing_song_info (mpris);
+ if (properties != NULL) {
+ GVariant *v = g_hash_table_lookup (properties, "mpris:trackid");
+ if (v != NULL) {
+ g_dbus_proxy_call_sync (mpris,
+ "SetPosition",
+ g_variant_new ("(ox)", g_variant_get_string (v, NULL), seek),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ annoy (&error);
+ }
+ }
}
- /* 4. add/enqueue */
+ /* add/enqueue */
if (clear_queue) {
- org_gnome_Rhythmbox_Shell_clear_queue (shell_proxy, &error);
+ g_dbus_proxy_call_sync (queue, "ClearQueue", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
annoy (&error);
}
if (other_stuff) {
@@ -734,12 +782,12 @@ main (int argc, char **argv)
if (enqueue) {
rb_debug ("enqueueing %s", fileuri);
- org_gnome_Rhythmbox_Shell_add_to_queue (shell_proxy, fileuri, &error);
+ g_dbus_proxy_call_sync (queue, "AddToQueue", g_variant_new ("(s)", fileuri), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+ annoy (&error);
} else {
rb_debug ("importing %s", fileuri);
- org_gnome_Rhythmbox_Shell_load_ur_i (shell_proxy, fileuri, FALSE, &error);
+ g_action_group_activate_action (G_ACTION_GROUP (app), "LoadURI", g_variant_new ("(sb)", fileuri, FALSE));
}
- annoy (&error);
g_free (fileuri);
g_object_unref (file);
}
@@ -747,14 +795,14 @@ main (int argc, char **argv)
/* select/activate/play source */
if (select_source) {
- org_gnome_Rhythmbox_Shell_activate_source (shell_proxy, select_source, 0, &error);
- annoy (&error);
+ rb_debug ("selecting source %s", select_source);
+ g_action_group_activate_action (G_ACTION_GROUP (app), "ActivateSource", g_variant_new ("(su)", select_source, 0));
} else if (activate_source) {
- org_gnome_Rhythmbox_Shell_activate_source (shell_proxy, activate_source, 1, &error);
- annoy (&error);
+ rb_debug ("activating source %s", activate_source);
+ g_action_group_activate_action (G_ACTION_GROUP (app), "ActivateSource", g_variant_new ("(su)", activate_source, 1));
} else if (play_source) {
- org_gnome_Rhythmbox_Shell_activate_source (shell_proxy, play_source, 2, &error);
- annoy (&error);
+ rb_debug ("playing source %s", play_source);
+ g_action_group_activate_action (G_ACTION_GROUP (app), "ActivateSource", g_variant_new ("(su)", play_source, 2));
}
/* play uri */
@@ -768,21 +816,28 @@ main (int argc, char **argv)
g_warning ("couldn't convert \"%s\" to a URI", play_uri);
} else {
rb_debug ("loading and playing %s", fileuri);
- org_gnome_Rhythmbox_Shell_load_ur_i (shell_proxy, fileuri, TRUE, &error);
+ g_action_group_activate_action (G_ACTION_GROUP (app), "LoadURI", g_variant_new ("(sb)", fileuri, TRUE));
annoy (&error);
}
g_free (fileuri);
g_object_unref (file);
}
- /* 5. play/pause/stop */
- org_gnome_Rhythmbox_Player_get_playing (player_proxy, &is_playing, &error);
- if (!annoy (&error)) {
- rb_debug ("playback state: %d", is_playing);
+ /* play/pause/stop */
+ if (mpris) {
+ GVariant *v;
+ gboolean is_playing = FALSE;
+
+ v = g_dbus_proxy_get_cached_property (mpris, "PlaybackStatus");
+ if (v != NULL) {
+ is_playing = (g_strcmp0 (g_variant_get_string (v, NULL), "Playing") == 0);
+ g_variant_unref (v);
+ }
+
if (play || do_pause || play_pause) {
if (is_playing != play || play_pause) {
- rb_debug ("calling playPause to change playback state");
- org_gnome_Rhythmbox_Player_play_pause (player_proxy, FALSE, &error);
+ rb_debug ("calling PlayPause to change playback state");
+ g_dbus_proxy_call_sync (mpris, "PlayPause", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
annoy (&error);
} else {
rb_debug ("no need to change playback state");
@@ -792,57 +847,66 @@ main (int argc, char **argv)
}
}
- /* 6. get/set volume, mute/unmute */
+ /* get/set volume, mute/unmute */
if (set_volume > -0.01) {
- org_gnome_Rhythmbox_Player_set_volume (player_proxy, set_volume, &error);
+ g_dbus_proxy_call_sync (mpris,
+ "org.freedesktop.DBus.Properties.Set",
+ g_variant_new ("(ssv)", "org.mpris.MediaPlayer2.Player", "Volume", g_variant_new_double (set_volume)),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
annoy (&error);
} else if (volume_up || volume_down) {
- org_gnome_Rhythmbox_Player_set_volume_relative (player_proxy, volume_up ? 0.1 : -0.1, &error);
- annoy (&error);
+ GVariant *v;
+
+ v = g_dbus_proxy_get_cached_property (mpris, "Volume");
+ if (v != NULL) {
+
+ set_volume = g_variant_get_double (v) + (volume_up ? 0.1 : -0.1);
+ g_dbus_proxy_call_sync (mpris,
+ "org.freedesktop.DBus.Properties.Set",
+ g_variant_new ("(ssv)", "org.mpris.MediaPlayer2.Player", "Volume", g_variant_new_double (set_volume)),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ annoy (&error);
+
+ g_variant_unref (v);
+ }
+ }
+ /* no mute for now? */
+ /*
} else if (unmute || mute) {
org_gnome_Rhythmbox_Player_set_mute (player_proxy, unmute ? FALSE : TRUE, &error);
annoy (&error);
}
+ */
if (print_volume) {
- gboolean mute = FALSE;
gdouble volume = 1.0;
-
- org_gnome_Rhythmbox_Player_get_mute (player_proxy, &mute, &error);
- annoy (&error);
- org_gnome_Rhythmbox_Player_get_volume (player_proxy, &volume, &error);
- annoy (&error);
-
- if (mute)
- g_print (_("Playback is muted.\n"));
+ GVariant *v = g_dbus_proxy_get_cached_property (mpris, "Volume");
+ if (v != NULL) {
+ volume = g_variant_get_double (v);
+ g_variant_unref (v);
+ }
g_print (_("Playback volume is %f.\n"), volume);
}
- /* 7. print playing song */
+ /* print playing song */
if (print_playing_format) {
- print_playing_song (shell_proxy, player_proxy, print_playing_format);
+ print_playing_song (mpris, print_playing_format);
} else if (print_playing) {
- print_playing_song_default (shell_proxy, player_proxy);
+ print_playing_song_default (mpris);
}
- /* 8. display notification about playing song */
- if (notify) {
- rb_debug ("show notification");
- org_gnome_Rhythmbox_Shell_notify (shell_proxy, TRUE, &error);
- annoy (&error);
+ if (mpris) {
+ g_object_unref (mpris);
}
- /* 9. set song rate */
- if (set_rating >= 0.0 && set_rating <= 5.0) {
- rb_debug ("rate song");
-
- rate_song (shell_proxy, player_proxy, set_rating);
- }
-
- g_object_unref (shell_proxy);
- g_object_unref (player_proxy);
+ g_dbus_connection_flush_sync (bus, NULL, NULL);
g_option_context_free (context);
return 0;
}
-
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]