changeset 852:bcff46a2558d trunk

[svn] added multiple 'remove duplicates' (by title, by filename, by path+filename)
author giacomo
date Sat, 18 Mar 2006 14:31:38 -0800
parents c9d70a699f80
children 74576869a506
files audacious/playlist.c audacious/playlist.h audacious/ui_playlist.c
diffstat 3 files changed, 125 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- 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 */
--- 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);
--- 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, "<ImageItem>", removeunavail_pixbuf},
 
-    {N_("/Remove Duplicates"), NULL,
+    {N_("/Remove Duplicates"), NULL, NULL, 0, "<Branch>", NULL},
+    {N_("/Remove Duplicates/By Title"), NULL,
      playlistwin_sub_menu_callback,
-     SUB_DUPLICATE, "<ImageItem>", removedups_pixbuf},
+     SUB_DUPLICATE_BYTITLE, "<ImageItem>", removedups_pixbuf},
+    {N_("/Remove Duplicates/By Filename"), NULL,
+     playlistwin_sub_menu_callback,
+     SUB_DUPLICATE_BYFILENAME, "<ImageItem>", removedups_pixbuf},
+    {N_("/Remove Duplicates/By Path + Filename"), NULL,
+     playlistwin_sub_menu_callback,
+     SUB_DUPLICATE_BYPATH, "<ImageItem>", 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();