Mercurial > audlegacy
changeset 3391:0afbafec6cd8
merge
author | Cristi Magherusan <majeru@atheme-project.org> |
---|---|
date | Mon, 13 Aug 2007 02:18:04 +0300 |
parents | 3a77e835874f (current diff) 71d8d93f1bad (diff) |
children | d538aabf6df5 |
files | |
diffstat | 7 files changed, 316 insertions(+), 68 deletions(-) [+] |
line wrap: on
line diff
--- a/src/audacious/dbus-service.h Sun Aug 12 20:03:43 2007 +0300 +++ b/src/audacious/dbus-service.h Mon Aug 13 02:18:04 2007 +0300 @@ -28,7 +28,7 @@ typedef struct { GObject parent; - DBusGProxy *proxy; + DBusGProxy *proxy; } RemoteObject, MprisRoot, MprisPlayer, MprisTrackList; typedef struct { @@ -39,9 +39,26 @@ 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, +}; + +// Status +typedef enum { + MPRIS_STATUS_PLAY = 0, + MPRIS_STATUS_PAUSE, + MPRIS_STATUS_STOP +} PlaybackStatus; + // MPRIS / gboolean mpris_root_identity(MprisRoot *obj, gchar **identity, GError **error); @@ -55,8 +72,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); @@ -71,13 +88,14 @@ CAPS_CHANGE_SIG, LAST_SIG }; -gboolean mpris_player_emit_track_change(MprisPlayer *obj, GError **error); -gboolean mpris_player_emit_status_change(MprisPlayer *obj, GError **error); -gboolean mpris_player_emit_caps_change(MprisPlayer *obj, GError **error); + +gboolean mpris_emit_track_change(MprisPlayer *obj); +gboolean mpris_emit_status_change(MprisPlayer *obj, PlaybackStatus status); +gboolean mpris_emit_caps_change(MprisPlayer *obj); // 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 +109,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 Sun Aug 12 20:03:43 2007 +0300 +++ b/src/audacious/dbus.c Mon Aug 13 02:18:04 2007 +0300 @@ -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(), @@ -133,6 +136,15 @@ dbus_g_connection_register_g_object(dbus_conn, AUDACIOUS_DBUS_PATH_MPRIS_PLAYER, G_OBJECT(object)); + + // Add signals + DBusGProxy *proxy = object->proxy; + dbus_g_proxy_add_signal(proxy, "StatusChange", + G_TYPE_INT, G_TYPE_INVALID); + dbus_g_proxy_add_signal(proxy, "CapsChange", + G_TYPE_INT, G_TYPE_INVALID); + dbus_g_proxy_add_signal(proxy, "TrackChange", + DBUS_TYPE_G_STRING_VALUE_HASHTABLE, G_TYPE_INVALID); } void mpris_tracklist_init(MprisTrackList *object) { @@ -158,14 +170,67 @@ g_type_init(); g_object_new(audacious_rc_get_type(), NULL); g_object_new(mpris_root_get_type(), NULL); - g_object_new(mpris_player_get_type(), NULL); + mpris = g_object_new(mpris_player_get_type(), NULL); g_object_new(mpris_tracklist_get_type(), NULL); 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 +240,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,89 +273,209 @@ 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 = MPRIS_STATUS_PAUSE; + else if (playback_get_playing()) + *status = MPRIS_STATUS_PLAY; + else + *status = MPRIS_STATUS_STOP; + 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"); +gboolean mpris_emit_caps_change(MprisPlayer *obj) { + g_signal_emit(obj, signals[CAPS_CHANGE_SIG], 0, 0); return TRUE; } -gboolean mpris_player_emit_track_change(MprisPlayer *obj, GError **error) { - g_signal_emit(obj, signals[TRACK_CHANGE_SIG], 0, "track changed"); +gboolean mpris_emit_track_change(MprisPlayer *obj) { + GHashTable *metadata; + Tuple *tuple = NULL; + GValue *value; + Playlist *active; + + active = playlist_get_active(); + gint pos = playlist_get_position(active); + tuple = playlist_get_tuple(active, pos); + + metadata = mpris_metadata_from_tuple(tuple); + + if (metadata != NULL) { + // 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(metadata, "URI", value); + } + + g_signal_emit(obj, signals[TRACK_CHANGE_SIG], 0, metadata); return TRUE; } -gboolean mpris_player_emit_status_change(MprisPlayer *obj, GError **error) { - g_signal_emit(obj, signals[STATUS_CHANGE_SIG], 0, "status changed"); +gboolean mpris_emit_status_change(MprisPlayer *obj, PlaybackStatus status) { + g_signal_emit(obj, signals[STATUS_CHANGE_SIG], 0, status); return TRUE; } // 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 +649,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 +664,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 +690,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;
--- a/src/audacious/input.c Sun Aug 12 20:03:43 2007 +0300 +++ b/src/audacious/input.c Mon Aug 13 02:18:04 2007 +0300 @@ -391,8 +391,8 @@ /* CD-Audio uses cdda:// dummy paths, no filedescriptor handling for it */ /* also cuesheet uses cue:// */ - if (!g_strncasecmp(filename, "cdda://", 7) || - !g_strncasecmp(filename, "cue://", 6)) { +/* + if (!g_strncasecmp(filename, "cue://", 6)) { for (node = get_input_list(); node != NULL; node = g_list_next(node)) { ip = INPUT_PLUGIN(node->data); @@ -413,7 +413,7 @@ g_free(filename_proxy); return NULL; } - +*/ fd = vfs_buffered_file_new_from_uri(tmp_uri); g_free(tmp_uri);
--- a/src/audacious/main.c Sun Aug 12 20:03:43 2007 +0300 +++ b/src/audacious/main.c Mon Aug 13 02:18:04 2007 +0300 @@ -414,6 +414,9 @@ GCond *cond_scan; GMutex *mutex_scan; +#ifdef USE_DBUS +MprisPlayer *mpris; +#endif static GSList * get_feature_list(void)
--- a/src/audacious/main.h Sun Aug 12 20:03:43 2007 +0300 +++ b/src/audacious/main.h Mon Aug 13 02:18:04 2007 +0300 @@ -30,6 +30,10 @@ # include "ui_main.h" #endif +#ifdef USE_DBUS +#include "dbus-service.h" +#endif + #include <sys/types.h> #include <sys/stat.h> @@ -174,6 +178,9 @@ extern GCond *cond_scan; extern GMutex *mutex_scan; +#ifdef USE_DBUS +extern MprisPlayer *mpris; +#endif G_END_DECLS
--- a/src/audacious/playback.c Sun Aug 12 20:03:43 2007 +0300 +++ b/src/audacious/playback.c Mon Aug 13 02:18:04 2007 +0300 @@ -108,7 +108,7 @@ if (playback->error) return -2; if (!playback->playing || - (playback->eof && !playback->output->buffer_playing())) + (playback->eof && !playback->output->buffer_playing())) return -1; return playback->output->output_time(); } @@ -191,10 +191,17 @@ g_return_if_fail(mainwin_playstatus != NULL); - if (ip_data.paused) + if (ip_data.paused) { ui_skinned_playstatus_set_status(mainwin_playstatus, STATUS_PAUSE); - else +#ifdef USE_DBUS + mpris_emit_status_change(mpris, MPRIS_STATUS_PAUSE); +#endif + } else { ui_skinned_playstatus_set_status(mainwin_playstatus, STATUS_PLAY); +#ifdef USE_DBUS + mpris_emit_status_change(mpris, MPRIS_STATUS_PLAY); +#endif + } } void @@ -240,6 +247,9 @@ g_free(playback->filename); g_free(playback); set_current_input_playback(NULL); +#ifdef USE_DBUS + mpris_emit_status_change(mpris, MPRIS_STATUS_STOP); +#endif } ip_data.buffering = FALSE; @@ -345,6 +355,9 @@ set_current_input_playback(playback); playback->thread = g_thread_create(playback_monitor_thread, playback, TRUE, NULL); +#ifdef USE_DBUS + mpris_emit_status_change(mpris, MPRIS_STATUS_PLAY); +#endif return TRUE; }
--- a/src/audacious/playlist.c Sun Aug 12 20:03:43 2007 +0300 +++ b/src/audacious/playlist.c Mon Aug 13 02:18:04 2007 +0300 @@ -521,6 +521,9 @@ playlistwin_update_list(playlist); if (restart_playing) { if (playlist->position) { +#ifdef USE_DBUS + mpris_emit_track_change(mpris); +#endif playback_initiate(); } else { @@ -560,6 +563,9 @@ if (restart_playing) { if (playlist->position) { +#ifdef USE_DBUS + mpris_emit_track_change(mpris); +#endif playback_initiate(); } else { @@ -601,6 +607,9 @@ if (restart_playing) { if (playlist->position) { +#ifdef USE_DBUS + mpris_emit_track_change(mpris); +#endif playback_initiate(); } else { @@ -1168,8 +1177,12 @@ PLAYLIST_UNLOCK(playlist->mutex); playlist_check_pos_current(playlist); - if (restart_playing) + if (restart_playing) { +#ifdef USE_DBUS + mpris_emit_track_change(mpris); +#endif playback_initiate(); + } playlistwin_update_list(playlist); } @@ -1228,9 +1241,12 @@ playlist_check_pos_current(playlist); - if (restart_playing) + if (restart_playing) { +#ifdef USE_DBUS + mpris_emit_track_change(mpris); +#endif playback_initiate(); - else { + } else { playlistwin_update_list(playlist); } } @@ -1410,9 +1426,12 @@ PLAYLIST_UNLOCK(playlist->mutex); playlist_check_pos_current(playlist); - if (restart_playing) + if (restart_playing) { +#ifdef USE_DBUS + mpris_emit_track_change(mpris); +#endif playback_initiate(); - else { + } else { playlistwin_update_list(playlist); } } @@ -1479,6 +1498,9 @@ PLAYLIST_UNLOCK(playlist->mutex); playlist_check_pos_current(playlist); +#ifdef USE_DBUS + mpris_emit_track_change(mpris); +#endif playback_initiate(); playlistwin_update_list(playlist); }