Here's an updated version of the D-Bus enhancements patch. This patch adds some extra functionality to Rhythmbox's D-Bus interface that make it much more useful for programs such as Rhythmbox Applet [0]. This patch replaces the one I sent earlier [1]. Changes from the previous version of the patch include: * The duration_changed and elapsed_changed signals of RBShellPlayer have been merged into a single signal: elapsed_changed, which has the elapsed time of the current song as a parameter. * The code in RBShell that had listened for duration_changed now listens for elapsed_changed, and obtains the formatted "$ELAPSED of $DURATION" string from the new method rb_shell_player_get_playing_time_string (which simply wraps rb_header_get_elapsed_string). * Functions added or modified for use in the D-Bus interface now properly check whether the output argument is NULL or not before attempting to store the result in it. * The have_url and url fields of RBShellPlayerPrivate, and the code that manipulates them, is left intact. A look at RBHeader suggests that they might be used for Internet radio, so taking them out is probably a bad idea without knowing more about what RBHeader does with them. And since this patch is about enhancing the D-Bus interface, this really isn't the place to be messing with that anyway. If this revised patch looks OK, please commit it to CVS so that programs that want to manipulate Rhythmbox can do so over D-Bus instead of Bonobo. [0] http://web.ics.purdue.edu/~kuliniew/rhythmbox-applet/ [1] http://mail.gnome.org/archives/rhythmbox-devel/2005-October/msg00015.html
Index: shell/rb-shell-player.c =================================================================== RCS file: /cvs/gnome/rhythmbox/shell/rb-shell-player.c,v retrieving revision 1.173 diff -u -r1.173 rb-shell-player.c --- shell/rb-shell-player.c 5 Oct 2005 17:13:24 -0000 1.173 +++ shell/rb-shell-player.c 16 Oct 2005 05:24:55 -0000 @@ -250,7 +250,7 @@ enum { WINDOW_TITLE_CHANGED, - DURATION_CHANGED, + ELAPSED_CHANGED, PLAYING_SOURCE_CHANGED, PLAYING_CHANGED, PLAYING_SONG_CHANGED, @@ -425,16 +425,16 @@ 1, G_TYPE_STRING); - rb_shell_player_signals[DURATION_CHANGED] = - g_signal_new ("duration_changed", + rb_shell_player_signals[ELAPSED_CHANGED] = + g_signal_new ("elapsed_changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (RBShellPlayerClass, duration_changed), + G_STRUCT_OFFSET (RBShellPlayerClass, elapsed_changed), NULL, NULL, - g_cclosure_marshal_VOID__STRING, + g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, - G_TYPE_STRING); + G_TYPE_UINT); rb_shell_player_signals[PLAYING_SOURCE_CHANGED] = g_signal_new ("playing-source-changed", @@ -544,8 +544,10 @@ gchar *volume_mount_point; RhythmDBEntry *entry; const char *uri; + gboolean playing; - if (rb_shell_player_get_playing (player)) { + rb_shell_player_get_playing (player, &playing, NULL); + if (playing) { return; } @@ -1751,7 +1753,7 @@ const char *artist = NULL; char *title; RhythmDBEntry *entry; - char *duration; + glong elapsed; entry = rb_shell_player_get_playing_entry (player); rb_debug ("playing source: %p, active entry: %p", player->priv->source, entry); @@ -1779,13 +1781,12 @@ else title = NULL; - duration = rb_header_get_elapsed_string (player->priv->header_widget); + elapsed = rb_player_get_time (player->priv->mmplayer); g_signal_emit (G_OBJECT (player), rb_shell_player_signals[WINDOW_TITLE_CHANGED], 0, title); - g_signal_emit (G_OBJECT (player), rb_shell_player_signals[DURATION_CHANGED], 0, - duration); - g_free (duration); + g_signal_emit (G_OBJECT (player), rb_shell_player_signals[ELAPSED_CHANGED], 0, + (guint) elapsed); /* Sync the player */ if (player->priv->song) @@ -1975,11 +1976,14 @@ } gboolean -rb_shell_player_get_playing (RBShellPlayer *player) +rb_shell_player_get_playing (RBShellPlayer *player, + gboolean *playing, + GError **error) { - g_return_val_if_fail (RB_IS_SHELL_PLAYER (player), -1); + if (playing != NULL) + *playing = rb_player_playing (player->priv->mmplayer); - return rb_player_playing (player->priv->mmplayer); + return TRUE; } RBPlayer * @@ -1990,21 +1994,38 @@ return player->priv->mmplayer; } -long -rb_shell_player_get_playing_time (RBShellPlayer *player) +char * +rb_shell_player_get_playing_time_string (RBShellPlayer *player) { - g_return_val_if_fail (RB_IS_SHELL_PLAYER (player), 0); - - return rb_player_get_time (player->priv->mmplayer); + return rb_header_get_elapsed_string (player->priv->header_widget); } -void -rb_shell_player_set_playing_time (RBShellPlayer *player, long time) +gboolean +rb_shell_player_get_playing_time (RBShellPlayer *player, + guint *time, + GError **error) { - g_return_if_fail (RB_IS_SHELL_PLAYER (player)); - - if (rb_player_seekable (player->priv->mmplayer)) - rb_player_set_time (player->priv->mmplayer, time); + if (time != NULL) + *time = (guint) rb_player_get_time (player->priv->mmplayer); + + return TRUE; +} + +gboolean +rb_shell_player_set_playing_time (RBShellPlayer *player, + guint time, + GError **error) +{ + if (rb_player_seekable (player->priv->mmplayer)) { + rb_player_set_time (player->priv->mmplayer, (long) time); + return TRUE; + } else { + g_set_error (error, + RB_SHELL_PLAYER_ERROR, + RB_SHELL_PLAYER_ERROR_NOT_SEEKABLE, + _("Current song is not seekable")); + return FALSE; + } } void @@ -2171,16 +2192,11 @@ rb_header_sync_time (player->priv->header_widget); if (rb_player_playing (mmplayer)) { - static int callback_runs = 0; - callback_runs++; - if (callback_runs >= RB_PLAYER_TICK_HZ) { - gchar *duration; - - duration = rb_header_get_elapsed_string (player->priv->header_widget); - g_signal_emit (G_OBJECT (player), rb_shell_player_signals[DURATION_CHANGED], - 0, duration); - g_free (duration); - callback_runs = 0; + static long last_elapsed = -1; + if (last_elapsed != elapsed) { + g_signal_emit (G_OBJECT (player), rb_shell_player_signals[ELAPSED_CHANGED], + 0, (guint) elapsed); + last_elapsed = elapsed; } } @@ -2321,10 +2337,21 @@ } -const char * -rb_shell_player_get_playing_path (RBShellPlayer *shell_player) +gboolean +rb_shell_player_get_playing_path (RBShellPlayer *shell_player, + const gchar **path, + GError **error) { - return shell_player->priv->url; + RhythmDBEntry *entry; + + entry = rb_play_order_get_playing_entry (shell_player->priv->play_order); + if (entry != NULL) { + *path = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION); + } else { + *path = NULL; + } + + return TRUE; } #ifdef HAVE_MMKEYS @@ -2391,7 +2418,9 @@ rb_shell_player_playpause (player, TRUE, NULL); return GDK_FILTER_REMOVE; } else if (XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioPause) == key->keycode) { - if (rb_shell_player_get_playing (player)) { + gboolean playing; + rb_shell_player_get_playing (player, &playing, NULL); + if (playing) { rb_shell_player_playpause (player, TRUE, NULL); } return GDK_FILTER_REMOVE; Index: shell/rb-shell-player.h =================================================================== RCS file: /cvs/gnome/rhythmbox/shell/rb-shell-player.h,v retrieving revision 1.32 diff -u -r1.32 rb-shell-player.h --- shell/rb-shell-player.h 28 Aug 2005 11:56:54 -0000 1.32 +++ shell/rb-shell-player.h 16 Oct 2005 05:24:55 -0000 @@ -44,7 +44,8 @@ { RB_SHELL_PLAYER_ERROR_PLAYLIST_PARSE_ERROR, RB_SHELL_PLAYER_ERROR_END_OF_PLAYLIST, - RB_SHELL_PLAYER_ERROR_NOT_PLAYING + RB_SHELL_PLAYER_ERROR_NOT_PLAYING, + RB_SHELL_PLAYER_ERROR_NOT_SEEKABLE, } RBShellPlayerError; #define RB_SHELL_PLAYER_ERROR rb_shell_player_error_quark () @@ -65,7 +66,7 @@ GtkHBoxClass parent_class; void (*window_title_changed) (RBShellPlayer *player, const char *window_title); - void (*duration_changed) (RBShellPlayer *player, const char *duration); + void (*elapsed_changed) (RBShellPlayer *player, guint elapsed); void (*playing_changed) (RBShellPlayer *player, gboolean playing); void (*playing_source_changed) (RBShellPlayer *player, RBSource *source); void (*playing_uri_changed) (RBShellPlayer *player, const char *uri); @@ -94,16 +95,25 @@ gboolean rb_shell_player_do_previous (RBShellPlayer *player, GError **error); gboolean rb_shell_player_do_next (RBShellPlayer *player, GError **error); -long rb_shell_player_get_playing_time(RBShellPlayer *player); -void rb_shell_player_set_playing_time(RBShellPlayer *player, long time); +char * rb_shell_player_get_playing_time_string (RBShellPlayer *player); +gboolean rb_shell_player_get_playing_time(RBShellPlayer *player, + guint *time, + GError **error); +gboolean rb_shell_player_set_playing_time(RBShellPlayer *player, + guint time, + GError **error); void rb_shell_player_seek (RBShellPlayer *player, long offset); long rb_shell_player_get_playing_song_duration (RBShellPlayer *player); RBPlayer * rb_shell_player_get_mm_player (RBShellPlayer *shell_player); -gboolean rb_shell_player_get_playing (RBShellPlayer *shell_player); - -const char * rb_shell_player_get_playing_path(RBShellPlayer *shell_player); +gboolean rb_shell_player_get_playing (RBShellPlayer *shell_player, + gboolean *playing, + GError **error); + +gboolean rb_shell_player_get_playing_path(RBShellPlayer *shell_player, + const gchar **path, + GError **error); void rb_shell_player_sync_buttons (RBShellPlayer *player); Index: shell/rb-shell-player.xml =================================================================== RCS file: /cvs/gnome/rhythmbox/shell/rb-shell-player.xml,v retrieving revision 1.2 diff -u -r1.2 rb-shell-player.xml --- shell/rb-shell-player.xml 28 Aug 2005 11:56:54 -0000 1.2 +++ shell/rb-shell-player.xml 16 Oct 2005 05:24:55 -0000 @@ -16,9 +16,33 @@ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="rb_shell_player_do_next"/> </method> + <method name="getPlaying"> + <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="rb_shell_player_get_playing"/> + <arg type="b" name="playing" direction="out"/> + </method> + + <method name="getPlayingUri"> + <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="rb_shell_player_get_playing_path"/> + <arg type="s" name="uri" direction="out"> + <annotation name="org.freedesktop.DBus.GLib.Const" value=""/> + </arg> + </method> + + <method name="getElapsed"> + <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="rb_shell_player_get_playing_time"/> + <arg type="u" name="elapsed" direction="out"/> + </method> + + <method name="setElapsed"> + <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="rb_shell_player_set_playing_time"/> + <arg type="u" name="elapsed" direction="in"/> + </method> + + <!-- <property name="playing" access="readwrite"/> --> <signal name="playingChanged"/> <signal name="playingUriChanged"/> + <signal name="elapsedChanged"/> </interface> </node> Index: shell/rb-shell.c =================================================================== RCS file: /cvs/gnome/rhythmbox/shell/rb-shell.c,v retrieving revision 1.340 diff -u -r1.340 rb-shell.c --- shell/rb-shell.c 16 Oct 2005 03:07:52 -0000 1.340 +++ shell/rb-shell.c 16 Oct 2005 05:24:56 -0000 @@ -135,13 +135,13 @@ static void rb_shell_medium_added_cb (RBRemovableMediaManager *mgr, RBSource *source, RBShell *shell); static void rb_shell_source_deleted_cb (RBSource *source, RBShell *shell); static void rb_shell_set_window_title (RBShell *shell, const char *window_title); -static void rb_shell_set_duration (RBShell *shell, const char *duration); +static void rb_shell_set_elapsed (RBShell *shell, guint elapsed); static void rb_shell_player_window_title_changed_cb (RBShellPlayer *player, const char *window_title, RBShell *shell); -static void rb_shell_player_duration_changed_cb (RBShellPlayer *player, - const char *duration, - RBShell *shell); +static void rb_shell_player_elapsed_changed_cb (RBShellPlayer *player, + guint elapsed, + RBShell *shell); static void rb_shell_cmd_about (GtkAction *action, RBShell *shell); static void rb_shell_cmd_contents (GtkAction *action, @@ -896,8 +896,8 @@ G_CALLBACK (rb_shell_player_window_title_changed_cb), shell, 0); g_signal_connect_object (G_OBJECT (shell->priv->player_shell), - "duration_changed", - G_CALLBACK (rb_shell_player_duration_changed_cb), + "elapsed_changed", + G_CALLBACK (rb_shell_player_elapsed_changed_cb), shell, 0); shell->priv->clipboard_shell = rb_shell_clipboard_new (shell->priv->actiongroup, shell->priv->db); @@ -1538,32 +1538,37 @@ } static void -rb_shell_player_duration_changed_cb (RBShellPlayer *player, - const char *duration, - RBShell *shell) +rb_shell_player_elapsed_changed_cb (RBShellPlayer *player, + guint elapsed, + RBShell *shell) { - rb_shell_set_duration (shell, duration); + rb_shell_set_elapsed (shell, elapsed); } static void -rb_shell_set_duration (RBShell *shell, const char *duration) +rb_shell_set_elapsed (RBShell *shell, guint elapsed) { - gboolean playing = rb_shell_player_get_playing (shell->priv->player_shell); + gboolean playing; + char *elapsed_string; char *tooltip; - if (shell->priv->cached_title == NULL) + rb_shell_player_get_playing (shell->priv->player_shell, &playing, NULL); + elapsed_string = rb_shell_player_get_playing_time_string (shell->priv->player_shell); + + if (shell->priv->cached_title == NULL) tooltip = g_strdup (_("Not playing")); else if (!playing) { /* Translators: the first %s is substituted by the song name, the second one is the elapsed and total time */ tooltip = g_strdup_printf (_("%s\nPaused, %s"), - shell->priv->cached_title, duration); + shell->priv->cached_title, elapsed_string); } else { /* Translators: the first %s is substituted by the song name, the second one is the elapsed and total time */ tooltip = g_strdup_printf (_("%s\n%s"), - shell->priv->cached_title, duration); + shell->priv->cached_title, elapsed_string); } rb_tray_icon_set_tooltip (shell->priv->tray_icon, tooltip); + g_free (elapsed_string); g_free (tooltip); } @@ -1580,9 +1585,11 @@ _("Music Player")); } else { - gboolean playing = rb_shell_player_get_playing (shell->priv->player_shell); + gboolean playing; char *title; + rb_shell_player_get_playing (shell->priv->player_shell, &playing, NULL); + if (shell->priv->cached_title && !strcmp (shell->priv->cached_title, window_title)) { return; @@ -2474,21 +2481,25 @@ rb_shell_playing_impl (RBRemoteProxy *proxy) { RBShellPlayer *player = RB_SHELL (proxy)->priv->player_shell; - return rb_shell_player_get_playing (player); + gboolean playing; + rb_shell_player_get_playing (player, &playing, NULL); + return playing; } static long rb_shell_get_playing_time_impl (RBRemoteProxy *proxy) { RBShellPlayer *player = RB_SHELL (proxy)->priv->player_shell; - return rb_shell_player_get_playing_time (player); + guint time; + rb_shell_player_get_playing_time (player, &time, NULL); + return (long) time; } static void rb_shell_set_playing_time_impl (RBRemoteProxy *proxy, long time) { RBShellPlayer *player = RB_SHELL (proxy)->priv->player_shell; - rb_shell_player_set_playing_time (player, time); + rb_shell_player_set_playing_time (player, (guint) time, NULL); } static gchar*
Attachment:
signature.asc
Description: Digital signature