[rhythmbox] audioscrobbler: add love and ban actions



commit 28f0bc1af438070ef869051b838c2903a41e14f2
Author: Jamie Nicol <jamie thenicols net>
Date:   Wed Jul 7 22:15:43 2010 +0100

    audioscrobbler: add love and ban actions

 .../rb-audioscrobbler-profile-source.c             |  145 ++++++++++++++++++++
 .../rb-audioscrobbler-radio-source.c               |   10 ++
 plugins/audioscrobbler/rb-audioscrobbler-user.c    |  116 ++++++++++++++++
 plugins/audioscrobbler/rb-audioscrobbler-user.h    |    7 +
 4 files changed, 278 insertions(+), 0 deletions(-)
---
diff --git a/plugins/audioscrobbler/rb-audioscrobbler-profile-source.c b/plugins/audioscrobbler/rb-audioscrobbler-profile-source.c
index af3eb67..ccd5110 100644
--- a/plugins/audioscrobbler/rb-audioscrobbler-profile-source.c
+++ b/plugins/audioscrobbler/rb-audioscrobbler-profile-source.c
@@ -91,6 +91,8 @@ struct _RBAudioscrobblerProfileSourcePrivate {
 
 	GHashTable *button_to_popup_menu_map;
 	GHashTable *popup_menu_to_data_map;
+
+	GtkActionGroup *action_group;
 };
 
 #define RB_AUDIOSCROBBLER_PROFILE_SOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_AUDIOSCROBBLER_PROFILE_SOURCE, RBAudioscrobblerProfileSourcePrivate))
@@ -111,6 +113,7 @@ static void rb_audioscrobbler_profile_source_set_property (GObject *object,
 
 static void rb_audioscrobbler_profile_source_init_login_ui (RBAudioscrobblerProfileSource *source);
 static void rb_audioscrobbler_profile_source_init_profile_ui (RBAudioscrobblerProfileSource *source);
+static void rb_audioscrobbler_profile_source_init_actions (RBAudioscrobblerProfileSource *source);
 
 static void rb_audioscrobbler_profile_source_login_bar_response (GtkInfoBar *info_bar,
                                                                  gint response_id,
@@ -136,6 +139,9 @@ static void rb_audioscrobbler_profile_source_scrobbler_statistics_changed_cb (RB
                                                                               guint submit_count,
                                                                               const char *submit_time,
                                                                               gpointer user_data);
+static void rb_audioscrobbler_profile_source_playing_song_changed_cb (RBShellPlayer *player,
+                                                                     RhythmDBEntry *entry,
+                                                                     RBAudioscrobblerProfileSource *source);
 
 static void rb_audioscrobbler_profile_source_create_radio_sources (RBAudioscrobblerProfileSource *source);
 
@@ -173,6 +179,12 @@ void rb_audioscrobbler_profile_source_list_layout_size_allocate_cb (GtkWidget *l
                                                                     GtkAllocation *allocation,
                                                                     gpointer user_data);
 
+static void rb_audioscrobbler_profile_source_love_track_action_cb (GtkAction *action,
+                                                                   RBAudioscrobblerProfileSource *source);
+static void rb_audioscrobbler_profile_source_ban_track_action_cb (GtkAction *action,
+                                                                  RBAudioscrobblerProfileSource *source);
+
+static GList *impl_get_ui_actions (RBSource *asource);
 static void impl_delete_thyself (RBSource *asource);
 
 
@@ -233,6 +245,7 @@ rb_audioscrobbler_profile_source_class_init (RBAudioscrobblerProfileSourceClass
 	object_class->set_property = rb_audioscrobbler_profile_source_set_property;
 
 	source_class = RB_SOURCE_CLASS (klass);
+	source_class->impl_get_ui_actions = impl_get_ui_actions;
 	source_class->impl_delete_thyself = impl_delete_thyself;
 
 	g_object_class_install_property (object_class,
@@ -269,6 +282,11 @@ rb_audioscrobbler_profile_source_constructed (GObject *object)
 
 	rb_shell_append_source (shell, RB_SOURCE (source), NULL);
 
+	g_signal_connect_object (rb_shell_get_player (shell),
+				 "playing-song-changed",
+				 G_CALLBACK (rb_audioscrobbler_profile_source_playing_song_changed_cb),
+				 source, 0);
+
 	/* create the UI */
 	source->priv->main_vbox = gtk_vbox_new (FALSE, 4);
 	gtk_box_pack_start (GTK_BOX (source), source->priv->main_vbox, TRUE, TRUE, 0);
@@ -276,6 +294,7 @@ rb_audioscrobbler_profile_source_constructed (GObject *object)
 
 	rb_audioscrobbler_profile_source_init_login_ui (source);
 	rb_audioscrobbler_profile_source_init_profile_ui (source);
+	rb_audioscrobbler_profile_source_init_actions (source);
 
 	/* create the user */
 	source->priv->user = rb_audioscrobbler_user_new (source->priv->service);
@@ -518,6 +537,43 @@ rb_audioscrobbler_profile_source_init_profile_ui (RBAudioscrobblerProfileSource
 }
 
 static void
+rb_audioscrobbler_profile_source_init_actions (RBAudioscrobblerProfileSource *source)
+{
+	/* Unfortunately we can't use the usual trick of declaring a static array of GtkActionEntry,
+	 * and simply using _rb_source_register_action_group with that array.
+	 * This is because each instance of this source needs its own love and ban actions
+	 * so tracks can be loved/banned differently for different audioscrobbler services.
+	 */
+
+	char *group_name;
+	char *love_name;
+	char *ban_name;
+
+	group_name = g_strdup_printf ("%sActions", rb_audioscrobbler_service_get_name (source->priv->service));
+	love_name = g_strdup_printf ("%sLoveTrack", rb_audioscrobbler_service_get_name (source->priv->service));
+	ban_name = g_strdup_printf ("%sBanTrack", rb_audioscrobbler_service_get_name (source->priv->service));
+
+	GtkActionEntry actions [] =
+	{
+		{ love_name, "emblem-favorite", N_("Love"), NULL,
+		  N_("Mark this song as loved"),
+		  G_CALLBACK (rb_audioscrobbler_profile_source_love_track_action_cb) },
+		{ ban_name, GTK_STOCK_CANCEL, N_("Ban"), NULL,
+		  N_("Ban the current track from being played again"),
+		  G_CALLBACK (rb_audioscrobbler_profile_source_ban_track_action_cb) },
+	};
+
+	source->priv->action_group = _rb_source_register_action_group (RB_SOURCE (source),
+								       group_name,
+								       actions,
+								       G_N_ELEMENTS (actions),
+								       source);
+	g_free (group_name);
+	g_free (love_name);
+	g_free (ban_name);
+}
+
+static void
 rb_audioscrobbler_profile_source_login_bar_response (GtkInfoBar *info_bar,
                                                      gint response_id,
                                                      gpointer user_data)
@@ -728,6 +784,26 @@ rb_audioscrobbler_profile_source_scrobbler_statistics_changed_cb (RBAudioscrobbl
 }
 
 static void
+rb_audioscrobbler_profile_source_playing_song_changed_cb (RBShellPlayer *player,
+                                                         RhythmDBEntry *entry,
+                                                         RBAudioscrobblerProfileSource *source)
+{
+	char *action_name;
+	GtkAction *action;
+
+	/* re-enable love/ban */
+	action_name = g_strdup_printf ("%sLoveTrack", rb_audioscrobbler_service_get_name (source->priv->service));
+	action = gtk_action_group_get_action (source->priv->action_group, action_name);
+	gtk_action_set_sensitive (action, TRUE);
+	g_free (action_name);
+
+	action_name = g_strdup_printf ("%sBanTrack", rb_audioscrobbler_service_get_name (source->priv->service));
+	action = gtk_action_group_get_action (source->priv->action_group, action_name);
+	gtk_action_set_sensitive (action, TRUE);
+	g_free (action_name);
+}
+
+static void
 rb_audioscrobbler_profile_source_create_radio_sources (RBAudioscrobblerProfileSource *source)
 {
 	const char *username;
@@ -1141,7 +1217,76 @@ rb_audioscrobbler_profile_source_list_layout_size_allocate_cb (GtkWidget *layout
 	gtk_layout_set_size (GTK_LAYOUT (layout), table_requisition.width, table_requisition.height);
 }
 
+/* GtkAction callbacks */
+static void
+rb_audioscrobbler_profile_source_love_track_action_cb (GtkAction *action,
+                                                       RBAudioscrobblerProfileSource *source)
+{
+	RBShell *shell;
+	RhythmDBEntry *entry;
+	char *ban_action_name;
+	GtkAction *ban_action;
+
+	g_object_get (source, "shell", &shell, NULL);
+
+	entry = rb_shell_player_get_playing_entry (RB_SHELL_PLAYER (rb_shell_get_player (shell)));
+
+	if (entry != NULL) {
+		rb_audioscrobbler_user_love_track (source->priv->user,
+			                           rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE),
+			                           rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST));
+		rhythmdb_entry_unref (entry);
+	}
+
+	/* disable love/ban */
+	gtk_action_set_sensitive (action, FALSE);
+	ban_action_name = g_strdup_printf ("%sBanSong", rb_audioscrobbler_service_get_name (source->priv->service));
+	ban_action = gtk_action_group_get_action (source->priv->action_group, ban_action_name);
+	gtk_action_set_sensitive (ban_action, FALSE);
+
+	g_free (ban_action_name);
+	g_object_unref (shell);
+}
+
+static void
+rb_audioscrobbler_profile_source_ban_track_action_cb (GtkAction *action,
+                                                      RBAudioscrobblerProfileSource *source)
+{
+	RBShell *shell;
+	RhythmDBEntry *entry;
+
+	g_object_get (source, "shell", &shell, NULL);
+
+	entry = rb_shell_player_get_playing_entry (RB_SHELL_PLAYER (rb_shell_get_player (shell)));
+
+	if (entry != NULL) {
+		rb_audioscrobbler_user_ban_track (source->priv->user,
+			                          rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE),
+			                          rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST));
+		rhythmdb_entry_unref (entry);
+	}
+
+	/* skip to next track */
+	rb_shell_player_do_next (RB_SHELL_PLAYER (rb_shell_get_player (shell)), NULL);
+
+	g_object_unref (shell);
+}
+
 /* RBSource implementations */
+static GList *
+impl_get_ui_actions (RBSource *asource)
+{
+	RBAudioscrobblerProfileSource *source = RB_AUDIOSCROBBLER_PROFILE_SOURCE (asource);
+	GList *actions = NULL;
+
+	actions = g_list_append (actions,
+	                          g_strdup_printf ("%sLoveTrack", rb_audioscrobbler_service_get_name (source->priv->service)));
+	actions = g_list_append (actions,
+	                          g_strdup_printf ("%sBanTrack", rb_audioscrobbler_service_get_name (source->priv->service)));
+
+	return actions;
+}
+
 static void
 impl_delete_thyself (RBSource *asource)
 {
diff --git a/plugins/audioscrobbler/rb-audioscrobbler-radio-source.c b/plugins/audioscrobbler/rb-audioscrobbler-radio-source.c
index cd31243..4155e12 100644
--- a/plugins/audioscrobbler/rb-audioscrobbler-radio-source.c
+++ b/plugins/audioscrobbler/rb-audioscrobbler-radio-source.c
@@ -131,6 +131,7 @@ static void impl_activate (RBSource *source);
 static RBEntryView *impl_get_entry_view (RBSource *asource);
 static void impl_get_status (RBSource *asource, char **text, char **progress_text, float *progress);
 static RBSourceEOFType impl_handle_eos (RBSource *asource);
+static GList *impl_get_ui_actions (RBSource *asource);
 static void impl_delete_thyself (RBSource *asource);
 
 enum {
@@ -213,6 +214,7 @@ rb_audioscrobbler_radio_source_class_init (RBAudioscrobblerRadioSourceClass *kla
 	source_class->impl_get_entry_view = impl_get_entry_view;
 	source_class->impl_get_status = impl_get_status;
 	source_class->impl_handle_eos = impl_handle_eos;
+	source_class->impl_get_ui_actions = impl_get_ui_actions;
 	source_class->impl_delete_thyself = impl_delete_thyself;
 
 	g_object_class_install_property (object_class,
@@ -911,6 +913,14 @@ impl_handle_eos (RBSource *asource)
 	return RB_SOURCE_EOF_NEXT;
 }
 
+static GList *
+impl_get_ui_actions (RBSource *asource)
+{
+	RBAudioscrobblerRadioSource *source = RB_AUDIOSCROBBLER_RADIO_SOURCE (asource);
+
+	return rb_source_get_ui_actions (RB_SOURCE (source->priv->parent));
+}
+
 static void
 impl_delete_thyself (RBSource *asource)
 {
diff --git a/plugins/audioscrobbler/rb-audioscrobbler-user.c b/plugins/audioscrobbler/rb-audioscrobbler-user.c
index fd8ffc8..4ac3d85 100644
--- a/plugins/audioscrobbler/rb-audioscrobbler-user.c
+++ b/plugins/audioscrobbler/rb-audioscrobbler-user.c
@@ -26,6 +26,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
  */
 
+#include <string.h>
 #include <libsoup/soup.h>
 #include <libsoup/soup-gnome.h>
 #include <json-glib/json-glib.h>
@@ -204,6 +205,13 @@ static void rb_audioscrobbler_user_download_image (RBAudioscrobblerUser *user,
 static void rb_audioscrobbler_user_image_download_cb (GObject *source_object,
                                                       GAsyncResult *res,
                                                       gpointer user_data);
+
+static void rb_audioscrobbler_user_love_track_response_cb (SoupSession *session,
+                                                           SoupMessage *msg,
+                                                           gpointer user_data);
+static void rb_audioscrobbler_user_ban_track_response_cb (SoupSession *session,
+                                                          SoupMessage *msg,
+                                                          gpointer user_data);
 enum {
 	PROP_0,
 	PROP_SERVICE
@@ -1587,3 +1595,111 @@ rb_audioscrobbler_user_image_download_cb (GObject *source_object, GAsyncResult *
 		rb_debug ("error downloading image. possibly due to cancellation");
 	}
 }
+
+void
+rb_audioscrobbler_user_love_track (RBAudioscrobblerUser *user,
+                                   const char *title,
+                                   const char *artist)
+{
+	char *sig_arg;
+	char *sig;
+	char *request;
+	SoupMessage *msg;
+
+	rb_debug ("loving track %s - %s", artist, title);
+
+	sig_arg = g_strdup_printf ("api_key%sartist%smethodtrack.lovesk%strack%s%s",
+	                           rb_audioscrobbler_service_get_api_key (user->priv->service),
+	                           artist,
+	                           user->priv->session_key,
+	                           title,
+	                           rb_audioscrobbler_service_get_api_secret (user->priv->service));
+
+	sig = mkmd5 (sig_arg);
+
+	request = g_strdup_printf ("method=track.love&track=%s&artist=%s&api_key=%s&api_sig=%s&sk=%s",
+	                           title,
+	                           artist,
+	                           rb_audioscrobbler_service_get_api_key (user->priv->service),
+	                           sig,
+	                           user->priv->session_key);
+
+	msg = soup_message_new ("POST", rb_audioscrobbler_service_get_api_url (user->priv->service));
+	soup_message_set_request (msg,
+	                          "application/x-www-form-urlencoded",
+	                          SOUP_MEMORY_COPY,
+	                          request,
+	                          strlen (request));
+	soup_session_queue_message (user->priv->soup_session,
+	                            msg,
+	                            rb_audioscrobbler_user_love_track_response_cb,
+	                            user);
+
+	g_free (sig_arg);
+	g_free (sig);
+	g_free (request);
+}
+
+static void
+rb_audioscrobbler_user_love_track_response_cb (SoupSession *session,
+                                               SoupMessage *msg,
+                                               gpointer user_data)
+{
+	/* Don't know if there's anything to do here,
+	 * might want a debug message indicating success or failure?
+	 */
+}
+
+void
+rb_audioscrobbler_user_ban_track (RBAudioscrobblerUser *user,
+                                  const char *title,
+                                  const char *artist)
+{
+	char *sig_arg;
+	char *sig;
+	char *request;
+	SoupMessage *msg;
+
+	rb_debug ("banning track %s - %s", artist, title);
+
+	sig_arg = g_strdup_printf ("api_key%sartist%smethodtrack.bansk%strack%s%s",
+	                           rb_audioscrobbler_service_get_api_key (user->priv->service),
+	                           artist,
+	                           user->priv->session_key,
+	                           title,
+	                           rb_audioscrobbler_service_get_api_secret (user->priv->service));
+
+	sig = mkmd5 (sig_arg);
+
+	request = g_strdup_printf ("method=track.ban&track=%s&artist=%s&api_key=%s&api_sig=%s&sk=%s",
+	                           title,
+	                           artist,
+	                           rb_audioscrobbler_service_get_api_key (user->priv->service),
+	                           sig,
+	                           user->priv->session_key);
+
+	msg = soup_message_new ("POST", rb_audioscrobbler_service_get_api_url (user->priv->service));
+	soup_message_set_request (msg,
+	                          "application/x-www-form-urlencoded",
+	                          SOUP_MEMORY_COPY,
+	                          request,
+	                          strlen (request));
+	soup_session_queue_message (user->priv->soup_session,
+	                            msg,
+	                            rb_audioscrobbler_user_ban_track_response_cb,
+	                            user);
+
+	g_free (sig_arg);
+	g_free (sig);
+	g_free (request);
+}
+
+static void
+rb_audioscrobbler_user_ban_track_response_cb (SoupSession *session,
+                                              SoupMessage *msg,
+                                              gpointer user_data)
+{
+	/* Don't know if there's anything to do here,
+	 * might want a debug message indicating success or failure?
+	 */
+}
diff --git a/plugins/audioscrobbler/rb-audioscrobbler-user.h b/plugins/audioscrobbler/rb-audioscrobbler-user.h
index 8aaa591..fbd9120 100644
--- a/plugins/audioscrobbler/rb-audioscrobbler-user.h
+++ b/plugins/audioscrobbler/rb-audioscrobbler-user.h
@@ -96,6 +96,13 @@ void rb_audioscrobbler_user_set_authentication_details (RBAudioscrobblerUser *us
 
 void rb_audioscrobbler_user_update (RBAudioscrobblerUser *user);
 
+void rb_audioscrobbler_user_love_track (RBAudioscrobblerUser *user,
+                                        const char *title,
+                                        const char *artist);
+void rb_audioscrobbler_user_ban_track (RBAudioscrobblerUser *user,
+                                       const char *title,
+                                       const char *artist);
+
 G_END_DECLS
 
 #endif /* __RB_AUDIOSCROBBLER_USER_H */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]