# HG changeset patch # User Yoshiki Yazawa # Date 1223061586 -32400 # Node ID dc3aa0bf24c0066edf21b834fa50e2b700b25939 # Parent 14de631fa9295dd9ef05fd411ea039df17fd9788 moved to mpris access diff -r 14de631fa929 -r dc3aa0bf24c0 Makefile.in --- a/Makefile.in Thu Oct 02 18:36:39 2008 +0900 +++ b/Makefile.in Sat Oct 04 04:19:46 2008 +0900 @@ -1,3 +1,4 @@ +TARGET = pidgin-audacious3.so PIDGIN_CFLAGS = @PIDGIN_CFLAGS@ AUD_CFLAGS = @AUD_CFLAGS@ DBUS_GLIB_CFLAGS = @DBUS_GLIB_CFLAGS@ @@ -12,18 +13,18 @@ PIDGIN_LIB_DIR = @PIDGIN_LIB_DIR@ -default: pidgin-audacious.so +default: $(TARGET) -pidgin-audacious.so: pidgin-audacious.c +$(TARGET): pidgin-audacious.c gcc -o $@ $< $(CFLAGS) $(LDFLAGS) -g -Wl,-rpath=$(AUD_LIB_DIR) -install: pidgin-audacious.so - install -m 755 pidgin-audacious.so $(PIDGIN_LIB_DIR)/pidgin +install: $(TARGET) + install -m 755 $(TARGET) $(PIDGIN_LIB_DIR)/pidgin clean: - rm -f pidgin-audacious.so + rm -f $(TARGET) distclean: clean diff -r 14de631fa929 -r dc3aa0bf24c0 pidgin-audacious.c --- a/pidgin-audacious.c Thu Oct 02 18:36:39 2008 +0900 +++ b/pidgin-audacious.c Sat Oct 04 04:19:46 2008 +0900 @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include "gtkplugin.h" #include "util.h" @@ -28,58 +30,240 @@ #include "connection.h" #include "version.h" #include "cmds.h" -#include -#include - -extern gchar *botch_utf(const gchar *msg, gsize len, gsize *newlen) __attribute__ ((weak)); +#include "savedstatuses.h" #define PIDGINAUD_PLUGIN_ID "pidgin_audacious" #define OPT_PIDGINAUD "/plugins/pidgin_audacious" #define OPT_PROCESS_STATUS OPT_PIDGINAUD "/process_status" #define OPT_PROCESS_USERINFO OPT_PIDGINAUD "/process_userinfo" +#define OPT_SONG_TEMPLATE OPT_PIDGINAUD "/song_template" #define OPT_PASTE_TEMPLATE OPT_PIDGINAUD "/paste_template" +#define DEFAULT_SONG_TEMPLATE "%artist - %title" #define SONG_TOKEN "%song" #define NO_SONG_MESSAGE "No song being played." +#define DBUS_TYPE_G_STRING_VALUE_HASHTABLE (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)) + #define aud_debug(fmt, ...) purple_debug(PURPLE_DEBUG_INFO, \ "Pidgin-Audacious", \ fmt, ## __VA_ARGS__); #define aud_error(fmt, ...) purple_debug(PURPLE_DEBUG_ERROR, \ "Pidgin-Audacious", \ fmt, ## __VA_ARGS__); - -static gint timeout_tag = 0; - -GHashTable *seed_status; -GHashTable *seed_userinfo; +/* xxx move up */ +#define TITLE "%title" +#define ARTIST "%artist" +#define ALBUM "%album" +#define GENRE "%genre" -GHashTable *pushed_status; -GHashTable *pushed_userinfo; +typedef struct song_tuple { + gchar *title; + gchar *artist; + gchar *album; + gchar *genre; +} song_tuple; + -DBusGConnection *connection = NULL; -DBusGProxy *session = NULL; - +/* globals */ +static GHashTable *seed_status; +static GHashTable *seed_userinfo; +static GHashTable *pushed_status; +static GHashTable *pushed_userinfo; +static DBusGConnection *connection = NULL; +static DBusGProxy *session = NULL; static PurpleCmdId cmdid_paste_current_song; +/* prototypes */ +extern gchar *botch_utf(const gchar *msg, gsize len, gsize *newlen) __attribute__ ((weak)); static void aud_process(gchar *aud_info); +static void track_signal_cb(DBusGProxy *player_proxy, GHashTable *table, gpointer data); +static void status_signal_cb(DBusGProxy *player_proxy, gint status, gpointer data); +static gboolean is_app_running(void); +static GHashTable *get_song_table(void); +static song_tuple *get_song_tuple(GHashTable *table); + + +/* implementation */ static DBusGProxy * -get_dbus_proxy(void) +get_dbus_session(void) { GError *error = NULL; + DBusGProxy *proxy; connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error); g_clear_error(&error); - session = dbus_g_proxy_new_for_name(connection, AUDACIOUS_DBUS_SERVICE, - AUDACIOUS_DBUS_PATH, - AUDACIOUS_DBUS_INTERFACE); + proxy = dbus_g_proxy_new_for_name(connection, + "org.mpris.audacious", + "/Player", + "org.freedesktop.MediaPlayer"); g_clear_error(&error); - return session; + return proxy; +} + + +static void +connect_dbus_signals() +{ + dbus_g_proxy_add_signal(session, + "TrackChange", + DBUS_TYPE_G_STRING_VALUE_HASHTABLE, + G_TYPE_INVALID); + + dbus_g_proxy_connect_signal(session, + "TrackChange", + G_CALLBACK(track_signal_cb), + NULL, NULL); + + dbus_g_proxy_add_signal(session, + "StatusChange", + G_TYPE_INT, G_TYPE_INVALID); + + dbus_g_proxy_connect_signal(session, + "StatusChange", + G_CALLBACK(status_signal_cb), + NULL, NULL); +} + +static GHashTable * +get_song_table(void) +{ + GHashTable *table = NULL; + + status_signal_cb(NULL, -1, NULL); + + if(is_app_running()) { + dbus_g_proxy_call(session, + "GetMetadata", + NULL, + G_TYPE_INVALID, + DBUS_TYPE_G_STRING_VALUE_HASHTABLE, + &table, + G_TYPE_INVALID); + } + + return table; +} + +static song_tuple * +get_song_tuple(GHashTable *table) +{ + song_tuple *t = NULL; + GValue *value; + + if(!table) + return NULL; + + t = g_new0(song_tuple, 1); + + value = (GValue *) g_hash_table_lookup(table, "title"); + if (value && G_VALUE_HOLDS_STRING(value)) { + t->title = g_value_dup_string(value); + } + value = (GValue *) g_hash_table_lookup(table, "artist"); + if (value != NULL && G_VALUE_HOLDS_STRING(value)) { + t->artist = g_value_dup_string(value); + } + value = (GValue *) g_hash_table_lookup(table, "album"); + if (value != NULL && G_VALUE_HOLDS_STRING(value)) { + t->album = g_value_dup_string(value); + } + value = (GValue *) g_hash_table_lookup(table, "genre"); + if (value != NULL && G_VALUE_HOLDS_STRING(value)) { + t->genre = g_value_dup_string(value); + } + + return t; } +void +free_song_tuple(song_tuple *t) +{ + g_free(t->title); + g_free(t->artist); + g_free(t->album); + g_free(t->genre); + + g_free(t); +} + + +static gchar * +format_song_info(song_tuple *tuple) +{ + gchar *song_info = NULL, *tmp = NULL; + + if(!tuple) + return NULL; + + song_info = g_strdup(purple_prefs_get_string(OPT_SONG_TEMPLATE)); + if(!song_info) + return NULL; + + if(tuple->title && strstr(song_info, TITLE)) { + tmp = purple_strreplace(song_info, TITLE, tuple->title); + g_free(song_info); + song_info = tmp; + } + if(tuple->artist && strstr(song_info, ARTIST)) { + tmp = purple_strreplace(song_info, ARTIST, tuple->artist); + g_free(song_info); + song_info = tmp; + } + if(tuple->album && strstr(song_info, ALBUM)) { + tmp = purple_strreplace(song_info, ALBUM, tuple->album); + g_free(song_info); + song_info = tmp; + } + if(tuple->genre && strstr(song_info, GENRE)) { + tmp = purple_strreplace(song_info, GENRE, tuple->genre); + g_free(song_info); + song_info = tmp; + } + + return song_info; +} + + + +static void +track_signal_cb(DBusGProxy *player_proxy, GHashTable *table, gpointer data) +{ + gchar *song_info = NULL; + song_tuple *tuple = get_song_tuple(table); + + /* set current song */ + purple_util_set_current_song(tuple->title ? tuple->title : "", + tuple->artist ? tuple->artist : "", + tuple->album ? tuple->album : ""); + + song_info = format_song_info(tuple); + + aud_process(song_info); + free_song_tuple(tuple); + g_free(song_info); +} + + +static void +status_signal_cb(DBusGProxy *player_proxy, gint status, gpointer data) +{ + aud_debug("StatusChange %d\n", status); + + if (status != 0) { + aud_process(""); + + /* clear current song */ + purple_util_set_current_song(NULL, NULL, NULL); + + } +} + + +#if 0 static gboolean watchdog_func(void) { @@ -90,7 +274,7 @@ size_t dummy; if(!session) { - session = get_dbus_proxy(); + session = get_dbus_session(); } aud_debug("session = %p\n", session); @@ -134,6 +318,11 @@ return rv; } +#endif + + + + static void aud_process_status(PurpleConnection *gc, gchar *aud_info) @@ -322,9 +511,10 @@ if (purple_prefs_get_bool(OPT_PROCESS_STATUS)) { aud_process_status(gc, aud_info); } + } - } } + static void removekey(gpointer data) { @@ -337,23 +527,30 @@ g_free(data); } + + + + static PurpleCmdRet paste_current_song(PurpleConversation *conv, const gchar *cmd, gchar **args, gchar **error, void *data) { - gint playpos = 0; gchar *song = NULL, *tmp = NULL, *tmp2 = NULL; PurpleConversationType type = purple_conversation_get_type(conv); size_t dummy; const gchar *template = NULL; /* audacious isn't playing */ - if(!audacious_remote_is_playing(session)) { + if(!is_app_running()) { return PURPLE_CMD_RET_OK; } - playpos = audacious_remote_get_playlist_pos(session); - tmp = audacious_remote_get_playlist_title(session, playpos); + /* dbus lookup */ + GHashTable *table = get_song_table(); + song_tuple *tuple = get_song_tuple(table); + tmp = format_song_info(tuple); + free_song_tuple(tuple); + g_hash_table_destroy(table); template = purple_prefs_get_string(OPT_PASTE_TEMPLATE); @@ -391,6 +588,66 @@ return PURPLE_CMD_RET_OK; } + + + + +static gboolean +is_app_running(void) +{ + gchar *player_name = g_strconcat("org.mpris.", "audacious", NULL); + +#if 0 + if(g_strcasecmp(pidginmpris->player_name, player_name) != 0) { + pidginmpris->player_name = g_strdup(player_name); + g_object_unref(pidginmpris->player); + mpris_connect_dbus_signals(); + } +#endif + + DBusGProxy *player = + dbus_g_proxy_new_for_name_owner(connection, + player_name, + "/Player", + "org.freedesktop.MediaPlayer", + NULL); + + if(!player) + return FALSE; + + g_object_unref(player); + g_free(player_name); + return TRUE; +} + +static void +signed_on_cb(PurpleConnection *gc, void *data) +{ + gchar *song_info = NULL; + GHashTable *table = NULL; + song_tuple *tuple = NULL; + + table = get_song_table(); + tuple = get_song_tuple(table); + + song_info = format_song_info(tuple); + free_song_tuple(tuple); + g_hash_table_destroy(table); + + if(song_info) + aud_process(song_info); + + g_free(song_info); +} + + +static void prefs_cb(const char *name, PurplePrefType type, + gconstpointer value, gpointer data) +{ + aud_debug("settings change detected at %s\n", name); + signed_on_cb(NULL, NULL); +} + static gboolean load_plugin(PurplePlugin *plugin) { @@ -404,8 +661,34 @@ pushed_userinfo = g_hash_table_new_full(g_str_hash, g_str_equal, removekey, removeval); - timeout_tag = g_timeout_add(15*1000, (gpointer)watchdog_func, NULL); + + session = get_dbus_session(); + + /* connect to mpris signals */ + connect_dbus_signals(); + + /* connect to purple signals */ + purple_signal_connect(purple_connections_get_handle(), + "signed-on", + plugin, + PURPLE_CALLBACK(signed_on_cb), + NULL); + purple_signal_connect(purple_savedstatuses_get_handle(), + "savedstatus-changed", + plugin, + PURPLE_CALLBACK(signed_on_cb), + NULL); + + purple_prefs_connect_callback(purple_prefs_get_handle(), + OPT_PIDGINAUD, + prefs_cb, + NULL); + + status_signal_cb(NULL, -1, NULL); + + + /* register /song command */ cmdid_paste_current_song = purple_cmd_register("song", "", PURPLE_CMD_P_DEFAULT, PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT, @@ -420,8 +703,6 @@ { aud_debug("pidgin-audacious unload called\n"); - g_source_remove(timeout_tag); - g_hash_table_destroy(seed_status); g_hash_table_destroy(seed_userinfo); @@ -430,8 +711,10 @@ purple_cmd_unregister(cmdid_paste_current_song); - g_object_unref(session); - session = NULL; + if(session) { + g_object_unref(session); + session = NULL; + } if(connection) { dbus_g_connection_unref(connection); @@ -462,6 +745,12 @@ "Expand " SONG_TOKEN " to song info in the user info"); purple_plugin_pref_frame_add(frame, pref); + /* song template */ + pref = purple_plugin_pref_new_with_name_and_label( + OPT_SONG_TEMPLATE, + "Song template"); + purple_plugin_pref_frame_add(frame, pref); + /* paste template */ pref = purple_plugin_pref_new_with_name_and_label( OPT_PASTE_TEMPLATE, @@ -488,7 +777,7 @@ PURPLE_PRIORITY_DEFAULT, /**< priority */ PIDGINAUD_PLUGIN_ID, /**< id */ "Pidgin-Audacious", /**< name */ - "2.1.0d2", /**< version */ + "3.0.0d2", /**< version */ "Automatically updates your Pidgin status info with the currently " "playing music in Audacious.", /** summary */ "Automatically updates your Pidgin status info with the currently " @@ -513,6 +802,7 @@ purple_prefs_add_none(OPT_PIDGINAUD); purple_prefs_add_bool(OPT_PROCESS_STATUS, TRUE); purple_prefs_add_bool(OPT_PROCESS_USERINFO, TRUE); + purple_prefs_add_string(OPT_SONG_TEMPLATE, DEFAULT_SONG_TEMPLATE); purple_prefs_add_string(OPT_PASTE_TEMPLATE, SONG_TOKEN); }