Mercurial > audlegacy
changeset 3344:c03055ef8822 trunk
-Implemented /Player GetStatus, GetMetadata, GetCaps, PositionGet, PositionSet, VolumeGet, and VolumeSet
-Implemented /TrackList Loop and GetMetadata
-Fixed /TrackList Random so that it toggles shuffle mode based on the passed argument instead of the current state
-Modified /TrackList AddTrack so that it will not start playing if the add failed (pending mods to playlist.c by yaz)
author | Ben Tucker <ben.tucker@gmail.com> |
---|---|
date | Sun, 12 Aug 2007 13:26:02 -0700 |
parents | 904c58081f0a |
children | 67951f8f9d83 |
files | src/audacious/dbus-service.h src/audacious/dbus.c |
diffstat | 2 files changed, 217 insertions(+), 48 deletions(-) [+] |
line wrap: on
line diff
--- a/src/audacious/dbus-service.h Sat Aug 11 22:17:13 2007 -0700 +++ b/src/audacious/dbus-service.h Sun Aug 12 13:26:02 2007 -0700 @@ -28,7 +28,7 @@ typedef struct { GObject parent; - DBusGProxy *proxy; + DBusGProxy *proxy; } RemoteObject, MprisRoot, MprisPlayer, MprisTrackList; typedef struct { @@ -39,9 +39,19 @@ void free_dbus(); DBusGProxy *audacious_get_dbus_proxy(); -/////////////////////////// -// MPRIS defined methods // -/////////////////////////// +/* MPRIS API */ +// Capabilities +enum { + MPRIS_CAPS_NONE = 0, + MPRIS_CAPS_CAN_GO_NEXT = 1 << 0, + MPRIS_CAPS_CAN_GO_PREV = 1 << 1, + MPRIS_CAPS_CAN_PAUSE = 1 << 2, + MPRIS_CAPS_CAN_PLAY = 1 << 3, + MPRIS_CAPS_CAN_SEEK = 1 << 4, + MPRIS_CAPS_CAN_PROVIDE_METADATA = 1 << 5, + MPRIS_CAPS_PROVIDES_TIMING = 1 << 6, +}; + // MPRIS / gboolean mpris_root_identity(MprisRoot *obj, gchar **identity, GError **error); @@ -55,8 +65,8 @@ gboolean mpris_player_quit(MprisPlayer *obj, GError **error); gboolean mpris_player_get_status(MprisPlayer *obj, gint *status, GError **error); -gboolean mpris_player_get_metadata(MprisTrackList *obj, gint pos, - GHashTable *metadata, GError **error); +gboolean mpris_player_get_metadata(MprisPlayer *obj, GHashTable **metadata, + GError **error); gboolean mpris_player_get_caps(MprisPlayer *obj, gint *capabilities, GError **error); gboolean mpris_player_volume_set(MprisPlayer *obj, gint vol, GError **error); @@ -77,7 +87,7 @@ // MPRIS /TrackList gboolean mpris_tracklist_get_metadata(MprisTrackList *obj, gint pos, - GHashTable *metadata, GError **error); + GHashTable **metadata, GError **error); gboolean mpris_tracklist_get_current_track(MprisTrackList *obj, gint *pos, GError **error); gboolean mpris_tracklist_get_length(MprisTrackList *obj, gint *length, @@ -91,7 +101,7 @@ gboolean mpris_tracklist_random(MprisTrackList *obj, gboolean random, GError **error); - +/* Legacy API */ // Audacious General Information gboolean audacious_rc_version(RemoteObject *obj, gchar **version, GError **error);
--- a/src/audacious/dbus.c Sat Aug 11 22:17:13 2007 -0700 +++ b/src/audacious/dbus.c Sun Aug 12 13:26:02 2007 -0700 @@ -28,6 +28,7 @@ #include "dbus-service.h" #include "dbus-server-bindings.h" +#include <math.h> #include "main.h" #include "ui_equalizer.h" #include "ui_main.h" @@ -49,6 +50,8 @@ G_DEFINE_TYPE(MprisPlayer, mpris_player, G_TYPE_OBJECT); G_DEFINE_TYPE(MprisTrackList, mpris_tracklist, G_TYPE_OBJECT); +#define DBUS_TYPE_G_STRING_VALUE_HASHTABLE (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)) + void audacious_rc_class_init(RemoteObjectClass *klass) {} void mpris_root_class_init(MprisRootClass *klass) {} @@ -59,24 +62,24 @@ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); signals[TRACK_CHANGE_SIG] = g_signal_new("track_change", G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, 1, DBUS_TYPE_G_STRING_VALUE_HASHTABLE); signals[STATUS_CHANGE_SIG] = g_signal_new("status_change", G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); } void mpris_tracklist_class_init(MprisTrackListClass *klass) {} @@ -84,7 +87,7 @@ void audacious_rc_init(RemoteObject *object) { GError *error = NULL; DBusGProxy *driver_proxy; - unsigned int request_ret; + guint request_ret; dbus_g_object_type_install_info(audacious_rc_get_type(), @@ -163,9 +166,62 @@ g_message("D-Bus support has been activated"); } -/////////////////////////// -// MPRIS defined methods // -/////////////////////////// +GValue *tuple_value_to_gvalue(Tuple *tuple, const gchar *key) { + GValue *val; + TupleValueType type; + type = tuple_get_value_type(tuple, key); + if (type == TUPLE_STRING) { + val = g_new0(GValue, 1); + g_value_init(val, G_TYPE_STRING); + g_value_set_string(val, tuple_get_string(tuple, key)); + return val; + } else if (type == TUPLE_INT) { + val = g_new0(GValue, 1); + g_value_init(val, G_TYPE_INT); + g_value_set_int(val, tuple_get_int(tuple, key)); + return val; + } + return NULL; +} + +GHashTable *mpris_metadata_from_tuple(Tuple *tuple) { + GHashTable *md = NULL; + GValue *value; + + if (tuple == NULL) + return NULL; + + md = g_hash_table_new(g_str_hash, g_str_equal); + + value = tuple_value_to_gvalue(tuple, "length"); + if (value != NULL) { + g_hash_table_insert(md, "length", value); + } + + value = tuple_value_to_gvalue(tuple, "title"); + if (value != NULL) { + g_hash_table_insert(md, "name", value); + } + + value = tuple_value_to_gvalue(tuple, "artist"); + if (value != NULL) { + g_hash_table_insert(md, "artist", value); + } + + value = tuple_value_to_gvalue(tuple, "album"); + if (value != NULL) { + g_hash_table_insert(md, "album", value); + } + + value = tuple_value_to_gvalue(tuple, "genre"); + if (value != NULL) { + g_hash_table_insert(md, "genre", value); + } + + return md; +} + +/* MPRIS API */ // MPRIS / gboolean mpris_root_identity(MprisRoot *obj, gchar **identity, GError **error) { @@ -175,26 +231,26 @@ // MPRIS /Player gboolean mpris_player_next(MprisPlayer *obj, GError **error) { - playlist_next(playlist_get_active()); + playlist_next(playlist_get_active()); return TRUE; } gboolean mpris_player_prev(MprisPlayer *obj, GError **error) { - playlist_prev(playlist_get_active()); + playlist_prev(playlist_get_active()); return TRUE; } gboolean mpris_player_pause(MprisPlayer *obj, GError **error) { - playback_pause(); + playback_pause(); return TRUE; } gboolean mpris_player_stop(MprisPlayer *obj, GError **error) { - ip_data.stop = TRUE; + ip_data.stop = TRUE; playback_stop(); ip_data.stop = FALSE; mainwin_clear_song_info(); return TRUE; } gboolean mpris_player_play(MprisPlayer *obj, GError **error) { - if (playback_get_paused()) + if (playback_get_paused()) playback_pause(); else if (playlist_get_length(playlist_get_active())) playback_initiate(); @@ -208,39 +264,111 @@ return TRUE; } gboolean mpris_player_quit(MprisPlayer *obj, GError **error) { - mainwin_quit_cb(); + mainwin_quit_cb(); return TRUE; } gboolean mpris_player_get_status(MprisPlayer *obj, gint *status, GError **error) { - return FALSE; + // check paused before playing because playback_get_playing() is true when + // paused as well as when playing + if (playback_get_paused()) + *status = 1; + else if (playback_get_playing()) + *status = 0; + else + *status = 2; + return TRUE; } -gboolean mpris_player_get_metadata(MprisTrackList *obj, gint pos, - GHashTable *metadata, GError **error) { - return FALSE; +gboolean mpris_player_get_metadata(MprisPlayer *obj, GHashTable **metadata, + GError **error) { + GHashTable *md = NULL; + Tuple *tuple = NULL; + GValue *value; + Playlist *active; + + active = playlist_get_active(); + gint pos = playlist_get_position(active); + tuple = playlist_get_tuple(active, pos); + + md = mpris_metadata_from_tuple(tuple); + + if (md == NULL) { + // there's no metadata for this track + return TRUE; + } + + // Song URI + value = g_new0(GValue, 1); + g_value_init(value, G_TYPE_STRING); + g_value_set_string(value, playlist_get_filename(active, pos)); + + g_hash_table_insert(md, "URI", value); + + *metadata = md; + + return TRUE; } gboolean mpris_player_get_caps(MprisPlayer *obj, gint *capabilities, GError **error) { - return FALSE; + *capabilities = MPRIS_CAPS_CAN_GO_NEXT | + MPRIS_CAPS_CAN_GO_PREV | + MPRIS_CAPS_CAN_PAUSE | + MPRIS_CAPS_CAN_PLAY | + MPRIS_CAPS_CAN_SEEK | + MPRIS_CAPS_CAN_PROVIDE_METADATA | + MPRIS_CAPS_PROVIDES_TIMING; + return TRUE; } gboolean mpris_player_volume_set(MprisPlayer *obj, gint vol, GError **error) { - return FALSE; + gint vl, vr, v; + + // get the current volume so we can maintain the balance + input_get_volume(&vl, &vr); + + // sanity check + vl = CLAMP(vl, 0, 100); + vr = CLAMP(vr, 0, 100); + v = CLAMP(vol, 0, 100); + + if (vl > vr) { + input_set_volume(v, (gint) rint(((gdouble) vr / vl) * v)); + } else if (vl < vr) { + input_set_volume((gint) rint(((gdouble) vl / vr) * v), v); + } else { + input_set_volume(v, v); + } + return TRUE; } gboolean mpris_player_volume_get(MprisPlayer *obj, gint *vol, GError **error) { - return FALSE; + gint vl, vr; + input_get_volume(&vl, &vr); + // vl and vr may be different depending on the balance; the true volume is + // the maximum of vl or vr. + *vol = MAX(vl, vr); + return TRUE; } gboolean mpris_player_position_set(MprisPlayer *obj, gint pos, GError **error) { - return FALSE; + gint time = CLAMP(pos / 1000, 0, + playlist_get_current_length(playlist_get_active()) / 1000 - 1); + playback_seek(time); + return TRUE; } gboolean mpris_player_position_get(MprisPlayer *obj, gint *pos, GError **error) { - return FALSE; + if (playback_get_playing()) + *pos = playback_get_time(); + else + *pos = 0; + return TRUE; } // MPRIS /Player signals gboolean mpris_player_emit_caps_change(MprisPlayer *obj, GError **error) { - g_signal_emit(obj, signals[CAPS_CHANGE_SIG], 0, "capabilities changed"); + static GQuark quark; + if (!quark) + quark = g_quark_from_static_string("CapsChange"); + g_signal_emit(obj, signals[CAPS_CHANGE_SIG], quark, "capabilities changed"); return TRUE; } @@ -256,41 +384,72 @@ // MPRIS /TrackList gboolean mpris_tracklist_get_metadata(MprisTrackList *obj, gint pos, - GHashTable *metadata, GError **error) { - return FALSE; + GHashTable **metadata, GError **error) { + GHashTable *md = NULL; + Tuple *tuple = NULL; + GValue *value; + Playlist *active; + + active = playlist_get_active(); + tuple = playlist_get_tuple(active, pos); + + md = mpris_metadata_from_tuple(tuple); + + if (md == NULL) { + // there's no metadata for this track + return TRUE; + } + + // Song URI + value = g_new0(GValue, 1); + g_value_init(value, G_TYPE_STRING); + g_value_set_string(value, playlist_get_filename(active, pos)); + + g_hash_table_insert(md, "URI", value); + + *metadata = md; + + return TRUE; } gboolean mpris_tracklist_get_current_track(MprisTrackList *obj, gint *pos, GError **error) { - *pos = playlist_get_position(playlist_get_active()); + *pos = playlist_get_position(playlist_get_active()); return TRUE; } gboolean mpris_tracklist_get_length(MprisTrackList *obj, gint *length, GError **error) { - *length = playlist_get_length(playlist_get_active()); + *length = playlist_get_length(playlist_get_active()); return TRUE; } gboolean mpris_tracklist_add_track(MprisTrackList *obj, gchar *uri, gboolean play, GError **error) { - playlist_add_url(playlist_get_active(), uri); - if (play) { - int pos = playlist_get_length(playlist_get_active()) - 1; + guint num_added; + num_added = playlist_add_url(playlist_get_active(), uri); + if (play && num_added > 0) { + gint pos = playlist_get_length(playlist_get_active()) - 1; playlist_set_position(playlist_get_active(), pos); playback_initiate(); } + // TODO: set an error if num_added == 0 return TRUE; } gboolean mpris_tracklist_del_track(MprisTrackList *obj, gint pos, GError **error) { - playlist_delete_index(playlist_get_active(), pos); + playlist_delete_index(playlist_get_active(), pos); return TRUE; } gboolean mpris_tracklist_loop(MprisTrackList *obj, gboolean loop, GError **error) { - return FALSE; + mainwin_repeat_pushed(loop); + if (loop) { + mainwin_set_noplaylistadvance(FALSE); + mainwin_set_stopaftersong(FALSE); + } + return TRUE; } gboolean mpris_tracklist_random(MprisTrackList *obj, gboolean random, GError **error) { - mainwin_shuffle_pushed(!cfg.shuffle); + mainwin_shuffle_pushed(random); return TRUE; } @@ -464,7 +623,7 @@ } // Playlist Information/Manipulation -gboolean audacious_rc_position(RemoteObject *obj, int *pos, GError **error) { +gboolean audacious_rc_position(RemoteObject *obj, gint *pos, GError **error) { *pos = playlist_get_position(playlist_get_active()); return TRUE; } @@ -479,7 +638,7 @@ return TRUE; } -gboolean audacious_rc_length(RemoteObject *obj, int *length, +gboolean audacious_rc_length(RemoteObject *obj, gint *length, GError **error) { *length = playlist_get_length(playlist_get_active()); return TRUE; @@ -505,13 +664,13 @@ return TRUE; } -gboolean audacious_rc_song_length(RemoteObject *obj, guint pos, int *length, +gboolean audacious_rc_song_length(RemoteObject *obj, guint pos, gint *length, GError **error) { *length = playlist_get_songtime(playlist_get_active(), pos) / 1000; return TRUE; } -gboolean audacious_rc_song_frames(RemoteObject *obj, guint pos, int *length, +gboolean audacious_rc_song_frames(RemoteObject *obj, guint pos, gint *length, GError **error) { *length = playlist_get_songtime(playlist_get_active(), pos); return TRUE;