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