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