# HG changeset patch # User giacomo # Date 1142721098 28800 # Node ID bcff46a2558d1018e34b18c133d30c8f9b79e20e # Parent c9d70a699f804b56fc2cf61d08ae00f3a7ce2b8e [svn] added multiple 'remove duplicates' (by title, by filename, by path+filename) diff -r c9d70a699f80 -r bcff46a2558d audacious/playlist.c --- a/audacious/playlist.c Sat Mar 18 13:35:16 2006 -0800 +++ b/audacious/playlist.c Sat Mar 18 14:31:38 2006 -0800 @@ -106,6 +106,10 @@ static gint playlist_compare_title(const PlaylistEntry * a, const PlaylistEntry * b); static gint playlist_compare_date(const PlaylistEntry * a, const PlaylistEntry * b); +static gint playlist_dupscmp_path( const PlaylistEntry * a, const PlaylistEntry * b); +static gint playlist_dupscmp_filename( const PlaylistEntry * a, const PlaylistEntry * b); +static gint playlist_dupscmp_title( const PlaylistEntry * a, const PlaylistEntry * b); + static PlaylistCompareFunc playlist_compare_func_table[] = { playlist_compare_path, playlist_compare_filename, @@ -2206,11 +2210,103 @@ playlist_recalc_total_time(); } + +static gint +playlist_dupscmp_title( const PlaylistEntry * a , const PlaylistEntry * b ) +{ + const gchar *a_title, *b_title; + + g_return_val_if_fail(a != NULL, 0); + g_return_val_if_fail(b != NULL, 0); + + if (a->title) + a_title = a->title; + else { + if (strrchr(a->filename, '/')) + a_title = strrchr(a->filename, '/') + 1; + else + a_title = a->filename; + } + + if (b->title) + b_title = b->title; + else { + if (strrchr(a->filename, '/')) + b_title = strrchr(b->filename, '/') + 1; + else + b_title = b->filename; + } + + return strcmp(a_title, b_title); +} + +static gint +playlist_dupscmp_filename( const PlaylistEntry * a , const PlaylistEntry * b ) +{ + gchar *a_filename, *b_filename; + + g_return_val_if_fail(a != NULL, 0); + g_return_val_if_fail(b != NULL, 0); + + if (strrchr(a->filename, '/')) + a_filename = strrchr(a->filename, '/') + 1; + else + a_filename = a->filename; + + if (strrchr(b->filename, '/')) + b_filename = strrchr(b->filename, '/') + 1; + else + b_filename = b->filename; + + return strcmp(a_filename, b_filename); +} + +static gint +playlist_dupscmp_path( const PlaylistEntry * a , const PlaylistEntry * b ) +{ + gchar *a_filename = a->filename, *b_filename = b->filename; + gchar *posa, *posb; + gint len, ret; + + posa = strrchr(a_filename, '/'); + posb = strrchr(b_filename, '/'); + + /* sort directories before files */ + if (posa && posb && (posa - a_filename != posb - b_filename)) { + if (posa -a_filename > posb - b_filename) { + len = posb - b_filename; + ret = -1; + } + else { + len = posa - a_filename; + ret = 1; + } + if (!strncmp(a_filename, b_filename, len)) + return ret; + } + return strcmp(a_filename, b_filename); +} + void -playlist_remove_duplicates(void) +playlist_remove_duplicates( PlaylistDupsType type ) { GList *node, *next_node; GList *node_cmp, *next_node_cmp; + gint (*dups_compare_func)( const PlaylistEntry * , const PlaylistEntry * ); + + switch ( type ) + { + case PLAYLIST_DUPS_TITLE: + dups_compare_func = playlist_dupscmp_title; + break; + case PLAYLIST_DUPS_PATH: + dups_compare_func = playlist_dupscmp_path; + break; + case PLAYLIST_DUPS_FILENAME: + default: + dups_compare_func = playlist_dupscmp_filename; + break; + } PLAYLIST_LOCK(); @@ -2232,8 +2328,8 @@ continue; } - /* compare path+filenames, this can/should be optimized */ - if ( !strcmp( entry->filename , entry_cmp->filename ) ) { + /* compare using the chosen dups_compare_func */ + if ( !dups_compare_func( entry , entry_cmp ) ) { if (entry_cmp == playlist_position) { /* Don't remove the currently playing song */ diff -r c9d70a699f80 -r bcff46a2558d audacious/playlist.h --- a/audacious/playlist.h Sat Mar 18 13:35:16 2006 -0800 +++ b/audacious/playlist.h Sat Mar 18 14:31:38 2006 -0800 @@ -31,6 +31,12 @@ } PlaylistSortType; typedef enum { + PLAYLIST_DUPS_PATH, + PLAYLIST_DUPS_FILENAME, + PLAYLIST_DUPS_TITLE +} PlaylistDupsType; + +typedef enum { PLAYLIST_FORMAT_UNKNOWN = -1, PLAYLIST_FORMAT_M3U, PLAYLIST_FORMAT_PLS, @@ -100,7 +106,7 @@ void playlist_reverse(void); void playlist_random(void); -void playlist_remove_duplicates(void); +void playlist_remove_duplicates(PlaylistDupsType); void playlist_remove_dead_files(void); void playlist_fileinfo_current(void); diff -r c9d70a699f80 -r bcff46a2558d audacious/ui_playlist.c --- a/audacious/ui_playlist.c Sat Mar 18 13:35:16 2006 -0800 +++ b/audacious/ui_playlist.c Sat Mar 18 14:31:38 2006 -0800 @@ -63,7 +63,8 @@ enum { ADD_URL, ADD_DIR, ADD_FILES, - SUB_MISC, SUB_ALL, SUB_CROP, SUB_SELECTED, SUB_DUPLICATE, + SUB_MISC, SUB_ALL, SUB_CROP, SUB_SELECTED, + SUB_DUPLICATE_BYTITLE, SUB_DUPLICATE_BYFILENAME, SUB_DUPLICATE_BYPATH, SEL_INV, SEL_ZERO, SEL_ALL, MISC_SORT, MISC_FILEINFO, MISC_MISCOPTS, PLIST_NEW, PLIST_SAVE_AS, PLIST_LOAD, @@ -169,9 +170,16 @@ playlistwin_sub_menu_callback, PLAYLISTWIN_REMOVE_DEAD_FILES, "", removeunavail_pixbuf}, - {N_("/Remove Duplicates"), NULL, + {N_("/Remove Duplicates"), NULL, NULL, 0, "", NULL}, + {N_("/Remove Duplicates/By Title"), NULL, playlistwin_sub_menu_callback, - SUB_DUPLICATE, "", removedups_pixbuf}, + SUB_DUPLICATE_BYTITLE, "", removedups_pixbuf}, + {N_("/Remove Duplicates/By Filename"), NULL, + playlistwin_sub_menu_callback, + SUB_DUPLICATE_BYFILENAME, "", removedups_pixbuf}, + {N_("/Remove Duplicates/By Path + Filename"), NULL, + playlistwin_sub_menu_callback, + SUB_DUPLICATE_BYPATH, "", removedups_pixbuf}, ITEM_SEPARATOR, @@ -1883,8 +1891,14 @@ case SUB_SELECTED: playlist_delete(FALSE); break; - case SUB_DUPLICATE: - playlist_remove_duplicates(); + case SUB_DUPLICATE_BYTITLE: + playlist_remove_duplicates(PLAYLIST_DUPS_TITLE); + break; + case SUB_DUPLICATE_BYFILENAME: + playlist_remove_duplicates(PLAYLIST_DUPS_FILENAME); + break; + case SUB_DUPLICATE_BYPATH: + playlist_remove_duplicates(PLAYLIST_DUPS_PATH); break; case PLAYLISTWIN_REMOVE_DEAD_FILES: playlist_remove_dead_files();