Index: apps/playlist_catalog.h
===================================================================
--- apps/playlist_catalog.h	(リビジョン 28280)
+++ apps/playlist_catalog.h	(作業コピー)
@@ -27,6 +27,9 @@
  */
 bool catalog_view_playlists(void);
 
+const char* get_playlist_catalog_dir(void);
+const char* get_most_recent_playlist(void);
+
 /* 
  * Add something to a playlist (new or select from list of playlists in
  * catalog).
Index: apps/tree.c
===================================================================
--- apps/tree.c	(リビジョン 28280)
+++ apps/tree.c	(作業コピー)
@@ -102,7 +102,7 @@
 static bool start_wps = false;
 static int curr_context = false;/* id3db or tree*/
 
-static int dirbrowse(void);
+static int dirbrowse(bool select_only);
 static int ft_play_dirname(char* name);
 static void ft_play_filename(char *dir, char *file);
 static void say_filetype(int attr);
@@ -619,7 +619,7 @@
 
 
 /* main loop, handles key events */
-static int dirbrowse()
+static int dirbrowse(bool select_only)
 {
     int numentries=0;
     char buf[MAX_PATH];
@@ -686,6 +686,8 @@
                 if ( numentries == 0 )
                     break;
 
+                if (select_only)
+                    return GO_TO_PLAYLIST_VIEWER; /* HACK */
 #ifdef HAVE_TAGCACHE
                 switch (id3db?tagtree_enter(&tc):ft_enter(&tc))
 #else
@@ -927,7 +929,8 @@
     return true;
 }
 
-int rockbox_browse(const char *root, int dirfilter)
+
+int rockbox_choose_file(const char *root, int dirfilter, char* buf, size_t buflen)
 {
     int ret_val = 0;
     int *last_filter = tc.dirfilter;
@@ -938,6 +941,7 @@
     if (dirfilter >= NUM_FILTER_MODES)
     {
         static struct tree_context backup;
+        char current[MAX_PATH], _dir[MAX_PATH];
         int last_context;
         const char *dir, *ext, *setting = NULL;
         
@@ -1009,40 +1013,62 @@
                 setting = global_settings.fmr_file;
                 break;
 #endif
+            case SHOW_PLAYLISTCAT:
+                dir = get_playlist_catalog_dir();
+                ext = NULL;
+                setting = get_most_recent_playlist();
+                break;
             default:
                 dir = ext = setting = NULL;
                 break;
             }
 
         /* If we've found a file to center on, do it */
-        if (setting)
+        if (setting && ext)
         {
-            char current[MAX_PATH], _dir[MAX_PATH];
             /* if setting != NULL, ext and dir are not used uninitialized */
             snprintf(current, sizeof(current), "%s/%s.%s",
                      get_user_file_path(dir, 0, _dir, sizeof(_dir)), setting, ext);
             set_current_file(current);
             /* set_current_file changes dirlevel, change it back */
-            tc.dirlevel = 0; 
+            tc.dirlevel = 0;
         }
+        else if (setting)
+        {
+            snprintf(current, sizeof(current), "%s/%s", dir, setting);
+            set_current_file(current);
+            /* set_current_file changes dirlevel, change it back */
+            tc.dirlevel = 0;
+        }
 
-        ret_val = dirbrowse();
+        ret_val = dirbrowse(buf != NULL);
+        if (buf && ret_val != GO_TO_PREVIOUS)
+            get_current_file(buf, buflen);
         tc = backup;
         curr_context = last_context;
     }
     else
     {
-        static char buf[MAX_PATH];
+        static char temp[MAX_PATH];
         if (dirfilter != SHOW_ID3DB)
             tc.dirfilter = &global_settings.dirfilter;
-        strcpy(buf,root);
-        set_current_file(buf);
-        ret_val = dirbrowse();
+        strcpy(temp,root);
+        set_current_file(temp);
+        ret_val = dirbrowse(false);
+        if (buf)
+            get_current_file(buf, buflen);
     }
+    
     tc.dirfilter = last_filter;
     return ret_val;
 }
 
+
+int rockbox_browse(const char *root, int dirfilter)
+{
+    return rockbox_choose_file(root, dirfilter, NULL, 0);
+}
+
 void tree_mem_init(void)
 {
     /* We copy the settings value in case it is changed by the user. We can't
Index: apps/tree.h
===================================================================
--- apps/tree.h	(リビジョン 28280)
+++ apps/tree.h	(作業コピー)
@@ -77,6 +77,7 @@
 void set_dirfilter(int l_dirfilter);
 void set_current_file(char *path);
 int rockbox_browse(const char *root, int dirfilter);
+int rockbox_choose_file(const char *root, int dirfilter, char* buf, size_t buflen);
 bool create_playlist(void);
 void resume_directory(const char *dir);
 #ifdef WIN32
Index: apps/settings.h
===================================================================
--- apps/settings.h	(リビジョン 28280)
+++ apps/settings.h	(作業コピー)
@@ -105,7 +105,7 @@
 enum { SHOW_ALL, SHOW_SUPPORTED, SHOW_MUSIC, SHOW_PLAYLIST, SHOW_ID3DB,
        NUM_FILTER_MODES,
        SHOW_WPS, SHOW_RWPS, SHOW_FMS, SHOW_RFMS, SHOW_SBS, SHOW_RSBS, SHOW_FMR, SHOW_CFG,
-       SHOW_LNG, SHOW_MOD, SHOW_FONT, SHOW_PLUGINS};
+       SHOW_LNG, SHOW_MOD, SHOW_FONT, SHOW_PLUGINS, SHOW_PLAYLISTCAT};
 
 /* file and dir sort options */
 enum { SORT_ALPHA, SORT_DATE, SORT_DATE_REVERSED, SORT_TYPE, /* available as settings */
Index: apps/filetree.c
===================================================================
--- apps/filetree.c	(リビジョン 28280)
+++ apps/filetree.c	(作業コピー)
@@ -323,7 +323,7 @@
 
         /* filter out non-visible files */
         if ((!(dptr->attr & ATTR_DIRECTORY) && (
-            (*c->dirfilter == SHOW_PLAYLIST &&
+            ((*c->dirfilter == SHOW_PLAYLIST || *c->dirfilter == SHOW_PLAYLISTCAT) &&
              (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_M3U) ||
             ((*c->dirfilter == SHOW_MUSIC &&
              (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) &&
Index: apps/playlist_catalog.c
===================================================================
--- apps/playlist_catalog.c	(リビジョン 28280)
+++ apps/playlist_catalog.c	(作業コピー)
@@ -44,8 +44,6 @@
 #include "playlist_catalog.h"
 #include "talk.h"
 
-#define MAX_PLAYLISTS 400
-
 /* Use for recursive directory search */
 struct add_track_context {
     int fd;
@@ -60,6 +58,16 @@
 static int  playlist_dir_length;
 static bool playlist_dir_exists = false;
 
+const char* get_playlist_catalog_dir(void)
+{
+    return playlist_dir;
+}
+
+const char* get_most_recent_playlist(void)
+{
+    return most_recent_playlist[0]? most_recent_playlist: NULL;
+}
+
 /* Retrieve playlist directory from config file and verify it exists */
 static int initialize_catalog(void)
 {
@@ -70,7 +78,8 @@
         bool default_dir = true;
 
         /* directory config is of the format: "dir: /path/to/dir" */
-        if (global_settings.playlist_catalog_dir[0])
+        if (global_settings.playlist_catalog_dir[0] &&
+            strcmp(playlist_dir, PLAYLIST_CATALOG_DEFAULT_DIR))
         {
             strcpy(playlist_dir, global_settings.playlist_catalog_dir);
             default_dir = false;
@@ -111,206 +120,7 @@
 
     return 0;
 }
-/* Use the filetree functions to retrieve the list of playlists in the
-   directory */
-static int create_playlist_list(char** playlists, int num_items,
-                                int* num_playlists)
-{
-    int result = -1;
-    int num_files = 0;
-    int index = 0;
-    int i;
-    bool most_recent = false;
-    struct entry *files;
-    struct tree_context* tc = tree_get_context();
-    int dirfilter = *(tc->dirfilter);
 
-    *num_playlists = 0;
-
-    /* use the tree browser dircache to load only playlists */
-    *(tc->dirfilter) = SHOW_PLAYLIST;
-
-    if (ft_load(tc, playlist_dir) < 0)
-    {
-        splashf(HZ*2, ID2P(LANG_CATALOG_NO_DIRECTORY), playlist_dir);
-        goto exit;
-    }
-
-    files = (struct entry*) tc->dircache;
-    num_files = tc->filesindir;
-
-    /* we've overwritten the dircache so tree browser will need to be
-       reloaded */
-    reload_directory();
-
-    /* if it exists, most recent playlist will always be index 0 */
-    if (most_recent_playlist[0] != '\0')
-    {
-        index = 1;
-        most_recent = true;
-    }
-
-    for (i=0; i<num_files && index<num_items; i++)
-    {
-        if (files[i].attr & FILE_ATTR_M3U)
-        {
-            if (most_recent && !strncmp(files[i].name, most_recent_playlist,
-                sizeof(most_recent_playlist)))
-            {
-                playlists[0] = files[i].name;
-                most_recent = false;
-            }
-            else
-            {
-                playlists[index] = files[i].name;
-                index++;
-            }
-        }
-    }
-
-    *num_playlists = index;
-
-    /* we couldn't find the most recent playlist, shift all playlists up */
-    if (most_recent)
-    {
-        for (i=0; i<index-1; i++)
-            playlists[i] = playlists[i+1];
-
-        (*num_playlists)--;
-
-        most_recent_playlist[0] = '\0';
-    }
-
-    result = 0;
-
-exit:
-    *(tc->dirfilter) = dirfilter;
-    return result;
-}
-
-/* Callback for gui_synclist */
-static const char* playlist_callback_name(int selected_item, void* data,
-                                          char* buffer, size_t buffer_len)
-{
-    char** playlists = (char**) data;
-
-    strlcpy(buffer, playlists[selected_item], buffer_len);
-
-    if (buffer[0] != '.' && !(global_settings.show_filename_ext == 1
-        || (global_settings.show_filename_ext == 3
-            && global_settings.dirfilter == 0)))
-    {
-        char* dot = strrchr(buffer, '.');
-
-        if (dot != NULL)
-        {
-            *dot = '\0';
-        }
-    }
-
-    return buffer;
-}
-
-static int playlist_callback_voice(int selected_item, void* data)
-{
-    char** playlists = (char**) data;
-    talk_file_or_spell(playlist_dir, playlists[selected_item], NULL, false);
-    return 0;
-}
-
-/* Display all playlists in catalog.  Selected "playlist" is returned.
-   If "view" mode is set then we're not adding anything into playlist. */
-static int display_playlists(char* playlist, bool view)
-{
-    int result = -1;
-    int num_playlists = 0;
-    bool exit = false;
-    char temp_buf[MAX_PATH];
-    char* playlists[MAX_PLAYLISTS];
-    struct gui_synclist playlist_lists;
-
-    if (create_playlist_list(playlists, MAX_PLAYLISTS,
-            &num_playlists) != 0)
-        return -1;
-
-    if (num_playlists <= 0)
-    {
-        splash(HZ*2, ID2P(LANG_CATALOG_NO_PLAYLISTS));
-        return -1;
-    }
-
-    if (!playlist)
-        playlist = temp_buf;
-
-    gui_synclist_init(&playlist_lists, playlist_callback_name, playlists,
-                       false, 1, NULL);
-    if(global_settings.talk_menu)
-        gui_synclist_set_voice_callback(&playlist_lists,
-                                        playlist_callback_voice);
-    gui_synclist_set_nb_items(&playlist_lists, num_playlists);
-    gui_synclist_draw(&playlist_lists);
-    gui_synclist_speak_item(&playlist_lists);
-
-    while (!exit)
-    {
-        int button;
-        char* sel_file;
-        list_do_action(CONTEXT_LIST,HZ/2,
-                       &playlist_lists, &button,LIST_WRAP_UNLESS_HELD);
-        sel_file = playlists[gui_synclist_get_sel_pos(&playlist_lists)];
-
-        switch (button)
-        {
-            case ACTION_STD_CANCEL:
-                exit = true;
-                break;
-
-            case ACTION_STD_OK:
-                snprintf(playlist, MAX_PATH, "%s/%s", playlist_dir, sel_file);
-
-                if (view)
-                {
-                    /* In view mode, selecting a playlist starts playback */
-                    ft_play_playlist(playlist, playlist_dir, sel_file);
-                }
-
-                result = 0;
-                exit = true;
-                break;
-
-            case ACTION_STD_CONTEXT:
-                /* context menu only available in view mode */
-                if (view)
-                {
-                    snprintf(playlist, MAX_PATH, "%s/%s", playlist_dir,
-                        sel_file);
-
-                    if (onplay(playlist, FILE_ATTR_M3U,
-                            CONTEXT_TREE, false) != ONPLAY_OK)
-                    {
-                        result = 0;
-                        exit = true;
-                    }
-                    else
-                    {
-                        gui_synclist_draw(&playlist_lists);
-                        gui_synclist_speak_item(&playlist_lists);
-                    }
-                }
-                break;
-
-            default:
-                if(default_event_handler(button) == SYS_USB_CONNECTED)
-                {
-                    result = -1;
-                    exit = true;
-                }
-                break;
-        }
-    }
-    return result;
-}
-
 /* display number of tracks inserted into playlists.  Used for directory
    insert */
 static void display_insert_count(int count)
@@ -443,16 +253,20 @@
 
     if (initialize_catalog() == -1)
         return false;
+
     in_cat_viewer = true;
-    retval = (display_playlists(NULL, true) != -1);
+    rockbox_browse(playlist_dir, SHOW_PLAYLISTCAT);
     in_cat_viewer = false;
     return retval;
 }
 
+static bool in_add_to_playlist = false;
 bool catalog_add_to_a_playlist(const char* sel, int sel_attr,
                                bool new_playlist, char *m3u8name)
 {
     char playlist[MAX_PATH];
+    if (in_add_to_playlist)
+        return false;
 
     if (initialize_catalog() == -1)
         return false;
@@ -478,7 +292,11 @@
     }
     else
     {
-        if (display_playlists(playlist, false) == -1)
+        playlist[0] = '\0';
+        in_add_to_playlist = true;
+        rockbox_choose_file(playlist_dir, SHOW_PLAYLISTCAT, playlist, sizeof(playlist));
+        in_add_to_playlist = false;
+        if (playlist[0] == '\0')
             return false;
     }
 
