[Rhythmbox-devel] Added support for folders on mtp-devices



Hello,

I have added support for folders for the plugin mtpdevices.
1. It adds a folder for artist and album like this:
<music-folder>/<artist>/<album>.
2. If rhythmbox deletes files it checks if the folders are empty to
delete them as well.
-  
greetings

Karl-Heinz Schneider

-----------------------------------

Karl-Heinz Schneider
Teckstraße 30
73734 Esslingen - Berkheim
s karl-heinz web de

From da5f94c20cc8fb846238decb3049a9c88d0c7651 Mon Sep 17 00:00:00 2001
From: karl-heinz web de <s karl-heinz web de>
Date: Sun, 30 Aug 2009 21:54:54 +0200
Subject: [PATCH] Added support for folders in plugin mtpdevice
 Folders will appear like this: <music-folder>/<artist>/<album>.
 If folder is emty after file deletion, folder get deleted as well.

---
 plugins/mtpdevice/rb-mtp-source.c |  161 ++++++++++++++++++++++++++++++++++++-
 1 files changed, 157 insertions(+), 4 deletions(-)

diff --git a/plugins/mtpdevice/rb-mtp-source.c b/plugins/mtpdevice/rb-mtp-source.c
index 37952a2..58c45e9 100644
--- a/plugins/mtpdevice/rb-mtp-source.c
+++ b/plugins/mtpdevice/rb-mtp-source.c
@@ -106,6 +106,12 @@ static void prepare_encoder_source_cb (RBEncoderFactory *factory,
 				       GObject *src,
 				       RBMtpSource *source);
 
+static gboolean create_folder (LIBMTP_mtpdevice_t *device, LIBMTP_track_t *trackmeta);
+
+static guint32 find_folder_by_name (LIBMTP_folder_t * folderlist, char * name);
+
+static gboolean remove_folder_if_empty (LIBMTP_mtpdevice_t * device, guint32 folder_id);
+
 typedef struct
 {
 	LIBMTP_mtpdevice_t *device;
@@ -292,7 +298,7 @@ rb_mtp_source_constructor (GType type, guint n_construct_properties,
 
 	g_signal_connect (G_OBJECT (source), "notify::name",
 			  (GCallback)rb_mtp_source_name_changed_cb, NULL);
-	
+
 	/* figure out supported file types */
 	if (LIBMTP_Get_Supported_Filetypes(priv->device, &types, &num_types) == 0) {
 		int i;
@@ -304,7 +310,7 @@ rb_mtp_source_constructor (GType type, guint n_construct_properties,
 				priv->supported_types[types[i]] = 1;
 			}
 
-			/* this has to work with the remapping done in 
+			/* this has to work with the remapping done in
 			 * rb-removable-media-source.c:impl_paste.
 			 */
 			switch (types[i]) {
@@ -365,7 +371,7 @@ rb_mtp_source_constructor (GType type, guint n_construct_properties,
 	} else {
 		report_libmtp_errors (priv->device, FALSE);
 	}
-	
+
 	if (priv->album_art_supported) {
 		RhythmDB *db;
 
@@ -702,7 +708,7 @@ load_mtp_db_idle_cb (RBMtpSource* source)
 
 			album = value;
 			if (album->no_tracks == 0) {
-				rb_debug ("pruning empty album \"%s\"", album->name); 
+				rb_debug ("pruning empty album \"%s\"", album->name);
 				ret = LIBMTP_Delete_Object (priv->device, album->album_id);
 				if (ret != 0) {
 					report_libmtp_errors (priv->device, FALSE);
@@ -868,6 +874,74 @@ remove_track_from_album (RBMtpSource *source, const char *album_name, LIBMTP_tra
 	}
 }
 
+/**
+ * Deletes a folder on the device if the folder is empty.
+ * Returns TRUE if successful otherwise FALSE
+ */
+
+static gboolean
+remove_folder_if_empty (LIBMTP_mtpdevice_t * device, guint32 folder_id) {
+	gboolean ret = TRUE;
+	LIBMTP_folder_t * folders;
+	LIBMTP_folder_t * folder;
+	LIBMTP_file_t * file_list;
+
+	// Don't delete default folders
+	if ((folder_id == device->default_album_folder) ||
+		(folder_id == device->default_music_folder) ||
+		(folder_id == device->default_organizer_folder) ||
+		(folder_id == device->default_picture_folder) ||
+		(folder_id == device->default_playlist_folder) ||
+		(folder_id == device->default_text_folder) ||
+		(folder_id == device->default_video_folder) ||
+		(folder_id == device->default_zencast_folder)) {
+
+		rb_debug ("Didn'd delete default folder %i", folder_id);
+		ret = FALSE;
+	}
+
+	// get folder and filelist from device
+	folders = LIBMTP_Get_Folder_List (device);
+	file_list = LIBMTP_Get_Filelisting_With_Callback (device,NULL,NULL);
+
+	// check if folder has subfolders
+	folder = LIBMTP_Find_Folder (folders, folder_id);
+	if (folder && ret) {
+		if (folder->child) {
+			rb_debug ("Didn'd delete nonempty folder %i (containing folders)", folder_id);
+			ret = FALSE;
+		}
+	}
+
+	// check if folder contains files
+	while (file_list != NULL) {
+		LIBMTP_file_t * tmp = file_list;
+
+		if (file_list->parent_id == folder_id) {
+			ret = FALSE;
+		}
+		file_list = file_list->next;
+		LIBMTP_destroy_file_t (tmp);
+	}
+
+	if (!ret)
+		rb_debug ("Didn'd delete nonempty folder %i (containing files)", folder_id);
+	else {
+		if (LIBMTP_Delete_Object(device, folder_id) != 0) {
+			report_libmtp_errors (device, FALSE);
+			g_debug ("Didn't delete empty folder %i because of MTP error", folder_id);
+		}
+
+		// check if we deleted the album folder?
+		if (folder->parent_id != 0 && folder->parent_id != device->default_music_folder)
+			ret = remove_folder_if_empty (device, folder->parent_id);
+	}
+
+	LIBMTP_destroy_folder_t (folders);
+	return ret;
+}
+
+
 static void
 impl_delete (RBSource *source)
 {
@@ -908,6 +982,8 @@ impl_delete (RBSource *source)
 			remove_track_from_album (RB_MTP_SOURCE (source), album_name, track);
 		}
 
+		remove_folder_if_empty (priv->device, track->parent_id);
+
 		g_hash_table_remove (priv->entry_map, entry);
 		rhythmdb_entry_delete (db, entry);
 	}
@@ -984,6 +1060,8 @@ transfer_track (RBMtpSource *source,
 		  LIBMTP_Get_Filetype_Description (trackmeta->filetype),
 		  mimetype);
 
+	create_folder(device, trackmeta);
+
 	ret = LIBMTP_Send_Track_From_File (device, filename, trackmeta, NULL, NULL);
 	rb_debug ("LIBMTP_Send_Track_From_File (%s) returned %d", filename, ret);
 	if (ret != 0) {
@@ -999,6 +1077,81 @@ transfer_track (RBMtpSource *source,
 	return trackmeta;
 }
 
+static gboolean
+create_folder (LIBMTP_mtpdevice_t *device, LIBMTP_track_t *trackmeta) {
+	gboolean ret = FALSE;
+	guint32 folder_id;
+	LIBMTP_folder_t * folders;
+	LIBMTP_folder_t * music_folder;
+
+	// get folder list
+	folders = LIBMTP_Get_Folder_List (device);
+
+	// locate default music folder
+	if (device->default_music_folder > 0) {
+		music_folder = LIBMTP_Find_Folder(folders, device->default_music_folder);
+	}
+
+	// search artist folder
+	folder_id = find_folder_by_name (music_folder->child, trackmeta->artist);
+	if (folder_id == 0) {
+		folder_id = LIBMTP_Create_Folder(device, trackmeta->artist,
+										device->default_music_folder,
+										trackmeta->storage_id);
+
+		rb_debug ("Artist folder %s with id %i created", trackmeta->artist, folder_id);
+
+		folder_id = LIBMTP_Create_Folder(device,
+							trackmeta->album,
+							folder_id,
+							trackmeta->storage_id);
+
+		rb_debug ("Album folder %s with id %i created", trackmeta->album, folder_id);
+
+		trackmeta->parent_id = folder_id;
+		ret = TRUE;
+	} else {
+		LIBMTP_folder_t * artist_folder;
+		guint32 album_folder_id;
+		artist_folder = LIBMTP_Find_Folder (music_folder, folder_id);
+
+		album_folder_id = find_folder_by_name (artist_folder->child, trackmeta->album);
+
+		if (album_folder_id == 0) {
+			folder_id = LIBMTP_Create_Folder (device,
+											trackmeta->album,
+											folder_id,
+											trackmeta->storage_id);
+
+			rb_debug ("Album folder %s with id %i created", trackmeta->album, folder_id);
+
+			trackmeta->parent_id = folder_id;
+		} else {
+			trackmeta->parent_id = album_folder_id;
+		}
+
+		ret = TRUE;
+	}
+
+	LIBMTP_destroy_folder_t (folders);
+	return ret;
+}
+
+
+
+static guint32
+find_folder_by_name (LIBMTP_folder_t * folderlist, char * name) {
+	while (folderlist) {
+		if (strcmp(folderlist->name, name)==0)
+			return folderlist->folder_id;
+		if (folderlist->sibling)
+			folderlist = folderlist->sibling;
+		else
+			return 0;
+	}
+	return 0;
+}
+
 static GList *
 impl_get_mime_types (RBRemovableMediaSource *source)
 {
-- 
1.6.3.3

Attachment: signature.asc
Description: Dies ist ein digital signierter Nachrichtenteil



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