[rhythmbox/media-player-sync: 2/3] mtp: add sync support



commit 3fd493fd1833d20d8699f5429413a8a1f241ee99
Author: Jonathan Matthew <jonathan d14n org>
Date:   Sun Dec 27 20:26:47 2009 +1000

    mtp: add sync support
    
    Since the MTP plugin doesn't support playlists yet, it only has to
    implement the methods that return the set of entries on the device
    and remove entries from the device.

 plugins/mtpdevice/mtp-ui.xml      |    1 +
 plugins/mtpdevice/rb-mtp-source.c |  175 +++++++++++++++++++++++++++++--------
 2 files changed, 141 insertions(+), 35 deletions(-)
---
diff --git a/plugins/mtpdevice/mtp-ui.xml b/plugins/mtpdevice/mtp-ui.xml
index 05986df..bdc7161 100644
--- a/plugins/mtpdevice/mtp-ui.xml
+++ b/plugins/mtpdevice/mtp-ui.xml
@@ -1,5 +1,6 @@
 <ui>
   <popup name="MTPSourcePopup">
+    <menuitem name="MTPSrcPopupSync" action="MediaPlayerSourceSync"/>
     <menuitem name="MTPSrcPopupRename" action="MTPSourceRename"/>
     <menuitem name="MTPSrcPopupEject" action="MTPSourceEject"/>
     <menuitem name="MTPSrcPopupProperties" action="MTPSourceProperties"/>
diff --git a/plugins/mtpdevice/rb-mtp-source.c b/plugins/mtpdevice/rb-mtp-source.c
index 672bd48..37e5a7f 100644
--- a/plugins/mtpdevice/rb-mtp-source.c
+++ b/plugins/mtpdevice/rb-mtp-source.c
@@ -47,6 +47,7 @@
 #include "rb-shell-player.h"
 #include "rb-player.h"
 #include "rb-encoder.h"
+#include "rb-media-player-sync-settings.h"
 
 #include "rb-mtp-source.h"
 #include "rb-mtp-thread.h"
@@ -97,8 +98,14 @@ static void artwork_notify_cb (RhythmDB *db,
 			       const GValue *metadata,
 			       RBMtpSource *source);
 
+static void		impl_get_entries	(RBMediaPlayerSource *source, const char *category, GHashTable *map);
 static guint64		impl_get_capacity	(RBMediaPlayerSource *source);
 static guint64		impl_get_free_space	(RBMediaPlayerSource *source);
+static void		impl_delete_entries	(RBMediaPlayerSource *source,
+						 GList *entries,
+						 RBMediaPlayerSourceDeleteCallback callback,
+						 gpointer callback_data,
+						 GDestroyNotify destroy_data);
 static void		impl_show_properties	(RBMediaPlayerSource *source, GtkWidget *info_box, GtkWidget *notebook);
 
 static void prepare_player_source_cb (RBPlayer *player,
@@ -189,8 +196,10 @@ rb_mtp_source_class_init (RBMtpSourceClass *klass)
 	rms_class->impl_get_mime_types = impl_get_mime_types;
 	rms_class->impl_should_paste = rb_removable_media_source_should_paste_no_duplicate;
 
+	mps_class->impl_get_entries = impl_get_entries;
 	mps_class->impl_get_capacity = impl_get_capacity;
 	mps_class->impl_get_free_space = impl_get_free_space;
+	mps_class->impl_delete_entries = impl_delete_entries;
 	mps_class->impl_show_properties = impl_show_properties;
 
 	g_object_class_install_property (object_class,
@@ -618,6 +627,8 @@ device_opened_idle (DeviceOpenedData *data)
 	g_signal_connect (G_OBJECT (data->source), "notify::name",
 			  (GCallback)rb_mtp_source_name_changed_cb, NULL);
 
+	rb_media_player_source_load (RB_MEDIA_PLAYER_SOURCE (data->source));
+
 	for (i = 0; i < data->num_types; i++) {
 		const char *mediatype;
 
@@ -817,43 +828,13 @@ mimetype_to_filetype (RBMtpSource *source, const char *mimetype)
 static void
 impl_delete (RBSource *source)
 {
-	RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source);
 	GList *sel;
-	GList *tem;
-	RBEntryView *tracks;
-	RhythmDB *db;
-
-	db = get_db_for_source (RB_MTP_SOURCE (source));
-
-	tracks = rb_source_get_entry_view (source);
-	sel = rb_entry_view_get_selected_entries (tracks);
-	for (tem = sel; tem != NULL; tem = tem->next) {
-		LIBMTP_track_t *track;
-		RhythmDBEntry *entry;
-		const char *uri;
-		const char *album_name;
-
-		entry = (RhythmDBEntry *)tem->data;
-		uri = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
-		track = g_hash_table_lookup (priv->entry_map, entry);
-		if (track == NULL) {
-			rb_debug ("Couldn't find track on mtp-device! (%s)", uri);
-			continue;
-		}
+	RBEntryView *songs;
 
-		album_name = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM);
-		if (strcmp (album_name, _("Unknown")) != 0) {
-			rb_mtp_thread_remove_from_album (priv->device_thread, track, album_name);
-		}
-		rb_mtp_thread_delete_track (priv->device_thread, track);
-
-		g_hash_table_remove (priv->entry_map, entry);
-		rhythmdb_entry_delete (db, entry);
-	}
-	rhythmdb_commit (db);
-
-	g_list_free (sel);
-	g_list_free (tem);
+	songs = rb_source_get_entry_view (source);
+	sel = rb_entry_view_get_selected_entries (songs);
+	impl_delete_entries (RB_MEDIA_PLAYER_SOURCE (source), sel, NULL, NULL, NULL);
+	rb_list_destroy_free (sel, (GDestroyNotify) rhythmdb_entry_unref);
 }
 
 static gboolean
@@ -869,6 +850,7 @@ impl_get_ui_actions (RBSource *source)
 	GList *actions = NULL;
 
 	actions = g_list_prepend (actions, g_strdup ("MTPSourceEject"));
+	actions = g_list_prepend (actions, g_strdup ("MediaPlayerSourceSync"));
 
 	return actions;
 }
@@ -966,6 +948,9 @@ impl_track_added (RBRemovableMediaSource *source,
 		g_idle_add ((GSourceFunc) request_album_art_idle, artdata);
 	}
 	queue_free_space_update (RB_MTP_SOURCE (source));
+
+	/* chain up to parent class for sync */
+	RB_REMOVABLE_MEDIA_SOURCE_CLASS (rb_mtp_source_parent_class)->impl_track_added (source, entry, dest, filesize, mimetype);
 	return FALSE;
 }
 
@@ -985,6 +970,8 @@ impl_track_add_error (RBRemovableMediaSource *source,
 		rb_debug ("track-add-error called, but can't find a track for dest URI %s", dest);
 	}
 
+	/* chain up to parent class for sync */
+	RB_REMOVABLE_MEDIA_SOURCE_CLASS (rb_mtp_source_parent_class)->impl_track_add_error (source, entry, dest, error);
 	return TRUE;
 }
 
@@ -1120,6 +1107,31 @@ artwork_notify_cb (RhythmDB *db,
 	g_object_unref (pixbuf);		/* ? */
 }
 
+
+static void
+impl_get_entries (RBMediaPlayerSource *source, const char *category, GHashTable *map)
+{
+	RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source);
+	GHashTableIter iter;
+	gpointer key, value;
+	gboolean podcast;
+
+	/* sync category mapping is a bit hackish here, as MTP doesn't categorise
+	 * tracks itself.  matching specific genres is about the best we can do.
+	 */
+	podcast = (g_str_equal (category, SYNC_CATEGORY_PODCAST));
+
+	g_hash_table_iter_init (&iter, priv->entry_map);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		LIBMTP_track_t *track = value;
+
+		if ((g_strcmp0 (track->genre, "Podcast") == 0) == podcast) {
+			RhythmDBEntry *entry = key;
+			_rb_media_player_source_add_to_map (map, entry);
+		}
+	}
+}
+
 static guint64
 impl_get_capacity	(RBMediaPlayerSource *source)
 {
@@ -1135,6 +1147,99 @@ impl_get_free_space	(RBMediaPlayerSource *source)
 	return priv->free_space;
 }
 
+typedef struct {
+	gboolean actually_free;
+	RBMediaPlayerSource *source;
+	RBMediaPlayerSourceDeleteCallback callback;
+	gpointer callback_data;
+	GDestroyNotify destroy_data;
+} TracksDeletedCallbackData;
+
+static void
+free_delete_data (TracksDeletedCallbackData *data)
+{
+	if (data->actually_free == FALSE) {
+		return;
+	}
+
+	g_object_unref (data->source);
+	if (data->destroy_data) {
+		data->destroy_data (data->callback_data);
+	}
+	g_free (data);
+}
+
+static gboolean
+delete_done_idle_cb (TracksDeletedCallbackData *data)
+{
+	if (data->callback) {
+		data->callback (data->source, data->callback_data);
+	}
+
+	data->actually_free = TRUE;
+	free_delete_data (data);
+	return FALSE;
+}
+
+static void
+delete_done_cb (LIBMTP_mtpdevice_t *device, TracksDeletedCallbackData *data)
+{
+	data->actually_free = FALSE;
+	update_free_space_cb (device, RB_MTP_SOURCE (data->source));
+	g_idle_add ((GSourceFunc) delete_done_idle_cb, data);
+}
+
+static void
+impl_delete_entries	(RBMediaPlayerSource *source,
+			 GList *entries,
+			 RBMediaPlayerSourceDeleteCallback callback,
+			 gpointer user_data,
+			 GDestroyNotify destroy_data)
+{
+	RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source);
+	RhythmDB *db;
+	GList *i;
+	TracksDeletedCallbackData *cb_data;
+
+	db = get_db_for_source (RB_MTP_SOURCE (source));
+	for (i = entries; i != NULL; i = i->next) {
+		LIBMTP_track_t *track;
+		const char *uri;
+		const char *album_name;
+		RhythmDBEntry *entry;
+
+		entry = i->data;
+		uri = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
+		track = g_hash_table_lookup (priv->entry_map, entry);
+		if (track == NULL) {
+			rb_debug ("Couldn't find track on mtp-device! (%s)", uri);
+			continue;
+		}
+
+		album_name = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM);
+		if (g_strcmp0 (album_name, _("Unknown")) != 0) {
+			rb_mtp_thread_remove_from_album (priv->device_thread, track, album_name);
+		}
+		rb_mtp_thread_delete_track (priv->device_thread, track);
+
+		g_hash_table_remove (priv->entry_map, entry);
+		rhythmdb_entry_delete (db, entry);
+	}
+
+	/* callback when all tracks have been deleted */
+	cb_data = g_new0 (TracksDeletedCallbackData, 1);
+	cb_data->source = g_object_ref (source);
+	cb_data->callback_data = user_data;
+	cb_data->callback = callback;
+	cb_data->destroy_data = destroy_data;
+	rb_mtp_thread_queue_callback (priv->device_thread,
+				      (RBMtpThreadCallback) delete_done_cb,
+				      cb_data,
+				      (GDestroyNotify) free_delete_data);
+
+	rhythmdb_commit (db);
+}
+
 static void
 impl_show_properties (RBMediaPlayerSource *source, GtkWidget *info_box, GtkWidget *notebook)
 {



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