diff --git a/apps/filetree.c b/apps/filetree.c
index 1dc510f..233391f 100644
--- a/apps/filetree.c
+++ b/apps/filetree.c
@@ -347,6 +347,7 @@ int ft_load(struct tree_context* c, const char* tempdir)
 #if CONFIG_TUNER
             (*c->dirfilter == SHOW_FMR && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_FMR) ||
 #endif
+            (*c->dirfilter == SHOW_M3U && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_M3U) ||
             (*c->dirfilter == SHOW_CFG && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_CFG) ||
             (*c->dirfilter == SHOW_LNG && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_LNG) ||
             (*c->dirfilter == SHOW_MOD && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_MOD) ||
diff --git a/apps/menus/playlist_menu.c b/apps/menus/playlist_menu.c
index a47c3b1..780805a 100644
--- a/apps/menus/playlist_menu.c
+++ b/apps/menus/playlist_menu.c
@@ -74,16 +74,23 @@ MENUITEM_FUNCTION(view_cur_playlist, MENU_FUNC_CHECK_RETVAL,
 MENUITEM_FUNCTION(save_playlist, MENU_FUNC_USEPARAM, ID2P(LANG_SAVE_DYNAMIC_PLAYLIST), 
                          (int(*)(void*))save_playlist_screen, 
                         NULL, NULL, Icon_NOICON);
-MENUITEM_FUNCTION(catalog, 0, ID2P(LANG_CATALOG_VIEW), 
-                  (int(*)(void))catalog_view_playlists,
-                   NULL, NULL, Icon_NOICON);
 MENUITEM_SETTING(recursive_dir_insert, &global_settings.recursive_dir_insert, NULL);
 MENUITEM_SETTING(warn_on_erase, &global_settings.warnon_erase_dynplaylist, NULL);
 
+/* Playlist viewer settings submenu */
+MENUITEM_SETTING(show_icons, &global_settings.playlist_viewer_icons, NULL);
+MENUITEM_SETTING(show_indices, &global_settings.playlist_viewer_indices, NULL);
+MENUITEM_SETTING(track_display, 
+                 &global_settings.playlist_viewer_track_display, NULL);
+MAKE_MENU(viewer_settings_menu, ID2P(LANG_PLAYLISTVIEWER_SETTINGS), 
+          NULL, Icon_Playlist,
+          &show_icons, &show_indices, &track_display);
+          
+
 MAKE_MENU(playlist_settings, ID2P(LANG_PLAYLISTS), NULL,
           Icon_Playlist,
-          &recursive_dir_insert, &warn_on_erase);
+          &viewer_settings_menu, &recursive_dir_insert, &warn_on_erase);
 MAKE_MENU(playlist_options, ID2P(LANG_PLAYLISTS), NULL,
           Icon_Playlist,
-          &create_playlist_item, &view_cur_playlist, &save_playlist, &catalog);
+          &create_playlist_item, &view_cur_playlist, &save_playlist);
 
diff --git a/apps/menus/theme_menu.c b/apps/menus/theme_menu.c
index 983eca9..65cc06c 100644
--- a/apps/menus/theme_menu.c
+++ b/apps/menus/theme_menu.c
@@ -248,7 +248,7 @@ int browse_folder(void *param)
 {
     const struct browse_folder_info *info =
         (const struct browse_folder_info*)param;
-    return rockbox_browse(info->dir, info->show_options);
+    return rockbox_browse(info->dir, info->show_options, NULL);
 }
 
 #ifdef HAVE_LCD_BITMAP
diff --git a/apps/onplay.c b/apps/onplay.c
index eb0c168..89385c5 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -382,6 +382,10 @@ static int treeplaylist_callback(int action,
     return action;
 }
 
+void onplay_show_playlist_menu(void)
+{
+    do_menu(&tree_playlist_menu, NULL, NULL, false);
+}
 
 /* playlist catalog options */
 static bool cat_add_to_a_playlist(void)
@@ -398,20 +402,25 @@ static bool cat_add_to_a_new_playlist(void)
 
 static int cat_playlist_callback(int action,
                                  const struct menu_item_ex *this_item);
-MENUITEM_FUNCTION(cat_view_lists, 0, ID2P(LANG_CATALOG_VIEW),
-                  catalog_view_playlists, 0,
-                  cat_playlist_callback, Icon_Playlist);
 MENUITEM_FUNCTION(cat_add_to_list, 0, ID2P(LANG_CATALOG_ADD_TO),
                   cat_add_to_a_playlist, 0, NULL, Icon_Playlist);
 MENUITEM_FUNCTION(cat_add_to_new, 0, ID2P(LANG_CATALOG_ADD_TO_NEW),
                   cat_add_to_a_new_playlist, 0, NULL, Icon_Playlist);
 MAKE_ONPLAYMENU(cat_playlist_menu, ID2P(LANG_CATALOG),
                 cat_playlist_callback, Icon_Playlist,
-                &cat_view_lists, &cat_add_to_list, &cat_add_to_new);
+                &cat_add_to_list, &cat_add_to_new);
+
+void onlplay_show_playlist_cat_menu(char* track_name)
+{
+    selected_file = track_name;
+    selected_file_attr = FILE_ATTR_AUDIO;
+    do_menu(&cat_playlist_menu, NULL, NULL, false);
+}
 
 static int cat_playlist_callback(int action,
                                  const struct menu_item_ex *this_item)
 {
+    (void)this_item;
     if (!selected_file ||
         (((selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) &&
          ((selected_file_attr & FILE_ATTR_MASK) != FILE_ATTR_M3U) &&
@@ -430,12 +439,7 @@ static int cat_playlist_callback(int action,
     switch (action)
     {
         case ACTION_REQUEST_MENUITEM:
-            if (this_item == &cat_view_lists)
-            {
-                return action;
-            }
-            else if ((audio_status() & AUDIO_STATUS_PLAY) ||
-                     context != CONTEXT_WPS)
+            if ((audio_status() & AUDIO_STATUS_PLAY) || context != CONTEXT_WPS)
             {
                 return action;
             }
diff --git a/apps/onplay.h b/apps/onplay.h
index b129296..591eeb5 100644
--- a/apps/onplay.h
+++ b/apps/onplay.h
@@ -48,4 +48,8 @@ enum hotkey_action {
 };
 #endif
 
+/* needed for the playlist viewer.. eventually clean this up */
+void onlplay_show_playlist_cat_menu(char* track_name);
+void onplay_show_playlist_menu(void);
+
 #endif
diff --git a/apps/playlist_catalog.c b/apps/playlist_catalog.c
index ff69b28..ac53962 100644
--- a/apps/playlist_catalog.c
+++ b/apps/playlist_catalog.c
@@ -43,6 +43,7 @@
 #include "debug.h"
 #include "playlist_catalog.h"
 #include "talk.h"
+#include "playlist_viewer.h"
 
 #define MAX_PLAYLISTS 400
 
@@ -60,6 +61,8 @@ static char playlist_dir[MAX_PATH];
 static int  playlist_dir_length;
 static bool playlist_dir_exists = false;
 
+static bool doing_choose_playlist = false;
+
 /* Retrieve playlist directory from config file and verify it exists */
 static int initialize_catalog(void)
 {
@@ -108,207 +111,61 @@ static int initialize_catalog(void)
             initialized = true;
         }
     }
+    strcat(playlist_dir, "/");
 
     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;
+static char selected_playlist[MAX_PATH];
 
-    /* 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)
+static int treeaction_callback(int action, struct tree_context *tc)
 {
-    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)))
+    (void)tc;
+    char *c;
+    switch (action)
     {
-        char* dot = strrchr(buffer, '.');
-
-        if (dot != NULL)
-        {
-            *dot = '\0';
-        }
+        case ACTION_STD_OK:
+            c = get_current_file(selected_playlist, MAX_PATH);
+            strcpy(most_recent_playlist, selected_playlist);
+            return ACTION_STD_CANCEL; /* causes rockbox_browse() to exit */
+        case ACTION_STD_CANCEL:
+            selected_playlist[0] = '\0';
+            break;
+        case ACTION_STD_CONTEXT:
+            if (doing_choose_playlist)
+                return ACTION_NONE;
+            break;
     }
-
-    return buffer;
+    return action;
 }
 
-static int playlist_callback_voice(int selected_item, void* data)
+char* catalog_get_last_playlist(void)
 {
-    char** playlists = (char**) data;
-    talk_file_or_spell(playlist_dir, playlists[selected_item], NULL, false);
-    return 0;
+    return most_recent_playlist[0] ? most_recent_playlist : NULL;
 }
 
 /* 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 retval;
+    selected_playlist[0] = '\0';
+restart:
+    retval = rockbox_browse(playlist_dir, SHOW_M3U, treeaction_callback);
+    
+    if (selected_playlist[0])
     {
-        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)
+        if (view)
         {
-            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;
+            if (playlist_viewer_ex(selected_playlist) == PLAYLIST_VIEWER_CANCEL)
+                goto restart;
         }
+        else
+            strncpy(playlist, selected_playlist, MAX_PATH);
     }
-    return result;
+    
+    
+    return retval;
 }
 
 /* display number of tracks inserted into playlists.  Used for directory
@@ -462,7 +319,7 @@ bool catalog_add_to_a_playlist(const char* sel, int sel_attr,
         size_t len;
         if (m3u8name == NULL)
         {
-            snprintf(playlist, MAX_PATH, "%s/", playlist_dir);
+            snprintf(playlist, MAX_PATH, "%s", playlist_dir);
             if (kbd_input(playlist, MAX_PATH))
                 return false;
         }
@@ -478,8 +335,12 @@ bool catalog_add_to_a_playlist(const char* sel, int sel_attr,
     }
     else
     {
+        doing_choose_playlist = true;
         if (display_playlists(playlist, false) == -1)
+        {
+            doing_choose_playlist = false;
             return false;
+        }
     }
 
     if (add_to_playlist(playlist, new_playlist, sel, sel_attr) == 0)
diff --git a/apps/playlist_catalog.h b/apps/playlist_catalog.h
index 2c2a2d4..3685eee 100644
--- a/apps/playlist_catalog.h
+++ b/apps/playlist_catalog.h
@@ -39,5 +39,7 @@ bool catalog_view_playlists(void);
  */
 bool catalog_add_to_a_playlist(const char* sel, int sel_attr,
                                bool new_playlist, char* m3u8name);
+                               
+char* catalog_get_last_playlist(void);
 
 #endif
diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c
index 293577b..552efff 100644
--- a/apps/playlist_viewer.c
+++ b/apps/playlist_viewer.c
@@ -125,7 +125,6 @@ static void format_line(const struct playlist_entry* track, char* str,
 
 static bool update_playlist(bool force);
 static int  onplay_menu(int index);
-static bool viewer_menu(void);
 static int save_playlist_func(void);
 
 static void playlist_buffer_init(struct playlist_buffer *pb, char *names_buffer,
@@ -437,6 +436,9 @@ static bool update_playlist(bool force)
     return true;
 }
 
+MENUITEM_FUNCTION(save_playlist_item, 0, ID2P(LANG_SAVE_DYNAMIC_PLAYLIST),
+                  save_playlist_func, 0, NULL, Icon_NOICON);
+
 /* Menu of playlist commands.  Invoked via ON+PLAY on main viewer screen.
    Returns -1 if USB attached, 0 if no playlist change, and 1 if playlist
    changed. */
@@ -446,9 +448,8 @@ static int onplay_menu(int index)
     struct playlist_entry * current_track=
         playlist_buffer_get_track(&viewer.buffer, index);
     MENUITEM_STRINGLIST(menu_items, ID2P(LANG_PLAYLIST), NULL, 
-                        ID2P(LANG_REMOVE), ID2P(LANG_MOVE),
-                        ID2P(LANG_CATALOG_ADD_TO), ID2P(LANG_CATALOG_ADD_TO_NEW),
-                        ID2P(LANG_PLAYLISTVIEWER_SETTINGS));
+                        ID2P(LANG_PLAYLIST), ID2P(LANG_CATALOG),
+                        ID2P(LANG_REMOVE), ID2P(LANG_MOVE));
     bool current = (current_track->index == viewer.current_playing_track);
 
     result = do_menu(&menu_items, NULL, NULL, false);
@@ -464,7 +465,15 @@ static int onplay_menu(int index)
 
         switch (result)
         {
-            case 0:
+            case 0: /* playlist */
+                onplay_show_playlist_menu();
+                ret = 0;
+                break;
+            case 1: /* add to catalog */
+                onlplay_show_playlist_cat_menu(current_track->name);
+                ret = 0;
+                break;
+            case 2:
                 /* delete track */
                 playlist_delete(viewer.playlist, current_track->index);
                 if (current)
@@ -490,43 +499,17 @@ static int onplay_menu(int index)
                 }
                 ret = 1;
                 break;
-            case 1:
+            case 3:
                 /* move track */
                 viewer.moving_track = index;
                 viewer.moving_playlist_index = current_track->index;
                 ret = 0;
                 break;
-            case 2: /* add to catalog */
-            case 3: /* add to a new one */
-                catalog_add_to_a_playlist(current_track->name,
-                                          FILE_ATTR_AUDIO,
-                                          result==3, NULL);
-                ret = 0;
-                break;
-            case 4: /* playlist viewer settings */
-                /* true on usb connect */
-                ret = viewer_menu() ? -1 : 0;
-                break;
         }
     }
     return ret;
 }
 
-/* Menu of viewer options.  Invoked via F1(r) or Menu(p). */
-MENUITEM_SETTING(show_icons, &global_settings.playlist_viewer_icons, NULL);
-MENUITEM_SETTING(show_indices, &global_settings.playlist_viewer_indices, NULL);
-MENUITEM_SETTING(track_display, 
-                 &global_settings.playlist_viewer_track_display, NULL);
-MENUITEM_FUNCTION(save_playlist_item, 0, ID2P(LANG_SAVE_DYNAMIC_PLAYLIST),
-                  save_playlist_func, 0, NULL, Icon_NOICON);
-MAKE_MENU(viewer_settings_menu, ID2P(LANG_PLAYLISTVIEWER_SETTINGS), 
-          NULL, Icon_Playlist,
-          &show_icons, &show_indices, &track_display, &save_playlist_item);
-static bool viewer_menu(void)
-{
-    return do_menu(&viewer_settings_menu, NULL, NULL, false) == MENU_ATTACHED_USB;
-}
-
 /* Save playlist to disk */
 static int save_playlist_func(void)
 {
@@ -682,7 +665,10 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename)
                     gui_synclist_draw(&playlist_lists);
                 }
                 else
+                {
                     exit = true;
+                    ret = PLAYLIST_VIEWER_CANCEL;
+                }
                 break;
             }
             case ACTION_STD_OK:
diff --git a/apps/playlist_viewer.h b/apps/playlist_viewer.h
index 97f5b0b..0a54c1b 100644
--- a/apps/playlist_viewer.h
+++ b/apps/playlist_viewer.h
@@ -29,6 +29,7 @@ bool search_playlist(void);
 
 enum playlist_viewer_result {
     PLAYLIST_VIEWER_OK,
+    PLAYLIST_VIEWER_CANCEL,
     PLAYLIST_VIEWER_USB,
     PLAYLIST_VIEWER_MAINMENU,
 };
diff --git a/apps/radio/presets.c b/apps/radio/presets.c
index e900afe..0840f8e 100644
--- a/apps/radio/presets.c
+++ b/apps/radio/presets.c
@@ -353,7 +353,7 @@ static int radio_delete_preset(void)
 
 int preset_list_load(void)
 {
-    return !rockbox_browse(FMPRESET_PATH, SHOW_FMR);
+    return !rockbox_browse(FMPRESET_PATH, SHOW_FMR, NULL);
 }
 
 int preset_list_save(void)
diff --git a/apps/root_menu.c b/apps/root_menu.c
index a65ceb5..cf3364c 100644
--- a/apps/root_menu.c
+++ b/apps/root_menu.c
@@ -252,7 +252,7 @@ static int browser(void* param)
             strlcpy(folder, PLUGIN_DIR, MAX_PATH);
         break;
     }
-    ret_val = rockbox_browse(folder, filter);
+    ret_val = rockbox_browse(folder, filter, NULL);
     switch ((intptr_t)param)
     {
         case GO_TO_FILEBROWSER:
@@ -327,14 +327,7 @@ static int radio(void* param)
 static int playlist_view(void * param)
 {
     (void)param;
-    switch (playlist_viewer())
-    {
-        case PLAYLIST_VIEWER_MAINMENU:
-        case PLAYLIST_VIEWER_USB:
-            return GO_TO_ROOT;
-        case PLAYLIST_VIEWER_OK:
-            return GO_TO_PREVIOUS;
-    }
+    catalog_view_playlists();
     return GO_TO_PREVIOUS;
 }
 
@@ -371,7 +364,7 @@ static int plugins_menu(void* param)
             default:
                 return selection;
         }
-        retval = rockbox_browse(folder, SHOW_PLUGINS);
+        retval = rockbox_browse(folder, SHOW_PLUGINS, NULL);
     }
     return retval;
 }
@@ -407,7 +400,7 @@ static const struct root_items items[] = {
     
     [GO_TO_RECENTBMARKS] =  { load_bmarks, NULL, &bookmark_settings_menu }, 
     [GO_TO_BROWSEPLUGINS] = { plugins_menu, NULL, NULL },
-    [GO_TO_PLAYLIST_VIEWER] = { playlist_view, NULL, NULL },
+    [GO_TO_PLAYLIST_VIEWER] = { playlist_view, NULL, &playlist_options },
     
 };
 static const int nb_items = sizeof(items)/sizeof(*items);
@@ -422,6 +415,10 @@ MENUITEM_RETURNVALUE(db_browser, ID2P(LANG_TAGCACHE), GO_TO_DBBROWSER,
 #endif
 MENUITEM_RETURNVALUE(rocks_browser, ID2P(LANG_PLUGINS), GO_TO_BROWSEPLUGINS, 
                         NULL, Icon_Plugin);
+                        
+MENUITEM_RETURNVALUE(playlist_browser, ID2P(LANG_PLAYLISTS), GO_TO_PLAYLIST_VIEWER, 
+                        NULL, Icon_Playlist);
+                        
 static char *get_wps_item_name(int selected_item, void * data, char *buffer)
 {
     (void)selected_item; (void)data; (void)buffer;
@@ -471,7 +468,7 @@ MAKE_MENU(root_menu_, ID2P(LANG_ROCKBOX_TITLE),
 #if CONFIG_TUNER
             &fm,
 #endif
-            &playlist_options, &rocks_browser,  &info_menu
+            &playlist_browser, &rocks_browser,  &info_menu
 
 #ifdef HAVE_LCD_CHARCELLS
             ,&do_shutdown_item
diff --git a/apps/settings.h b/apps/settings.h
index cd06dae..fac2c96 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -106,7 +106,7 @@ enum
 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_M3U};
 
 /* file and dir sort options */
 enum { SORT_ALPHA, SORT_DATE, SORT_DATE_REVERSED, SORT_TYPE, /* available as settings */
diff --git a/apps/tree.c b/apps/tree.c
index 98880f0..3b76d07 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -418,17 +418,28 @@ static int update_dir(void)
     {
 #ifdef HAVE_LCD_BITMAP
         if (global_settings.show_path_in_browser && 
-            *(tc.dirfilter) == SHOW_PLUGINS)
+            (*(tc.dirfilter) == SHOW_PLUGINS ||
+            *(tc.dirfilter) == SHOW_M3U))
         {
             char *title;
-            if (!strcmp(tc.currdir, PLUGIN_GAMES_DIR))
-                title = str(LANG_PLUGIN_GAMES);
-            else if (!strcmp(tc.currdir, PLUGIN_APPS_DIR))
-                title = str(LANG_PLUGIN_APPS);
-            else if (!strcmp(tc.currdir, PLUGIN_DEMOS_DIR))
-                title = str(LANG_PLUGIN_DEMOS);
-            else title = str(LANG_PLUGINS);
-            gui_synclist_set_title(&tree_lists, title, Icon_Plugin);
+            enum themable_icons icon;
+            if (*(tc.dirfilter) == SHOW_PLUGINS)
+            {
+                if (!strcmp(tc.currdir, PLUGIN_GAMES_DIR))
+                    title = str(LANG_PLUGIN_GAMES);
+                else if (!strcmp(tc.currdir, PLUGIN_APPS_DIR))
+                    title = str(LANG_PLUGIN_APPS);
+                else if (!strcmp(tc.currdir, PLUGIN_DEMOS_DIR))
+                    title = str(LANG_PLUGIN_DEMOS);
+                else title = str(LANG_PLUGINS);
+                icon = Icon_Plugin;
+            }
+            else
+            {
+                title = str(LANG_PLAYLISTS);
+                icon = Icon_Playlist;
+            }
+            gui_synclist_set_title(&tree_lists, title, icon);
         }
         else if (global_settings.show_path_in_browser == SHOW_PATH_FULL)
         {
@@ -677,6 +688,8 @@ static int dirbrowse()
         oldbutton = button;
         gui_synclist_do_button(&tree_lists, &button,LIST_WRAP_UNLESS_HELD);
         tc.selected_item = gui_synclist_get_sel_pos(&tree_lists);
+        if (tc.action_callback != NULL)
+            button = tc.action_callback(button, &tc);
         switch ( button ) {
             case ACTION_STD_OK:
                 /* nothing to do if no files to display */
@@ -924,7 +937,8 @@ bool create_playlist(void)
     return true;
 }
 
-int rockbox_browse(const char *root, int dirfilter)
+int rockbox_browse(const char *root, int dirfilter,
+                   int (*action_callback)(int action, struct tree_context *tc))
 {
     static char current[MAX_PATH];
     int ret_val = 0;
@@ -943,6 +957,7 @@ int rockbox_browse(const char *root, int dirfilter)
         tc.selected_item = 0;
         tc.dirlevel = 0;
         memcpy(tc.currdir, root, sizeof(tc.currdir));
+        tc.action_callback = action_callback;
         start_wps = false;
         last_context = curr_context;
 
@@ -998,6 +1013,18 @@ int rockbox_browse(const char *root, int dirfilter)
                 setting = global_settings.fmr_file;
                 break;
 #endif
+            case SHOW_M3U: /* mild hack to set the last playlist in the catalog */
+            {
+                char* last = catalog_get_last_playlist();
+                if (last)
+                {
+                    set_current_file(last);
+                    /* set_current_file changes dirlevel, change it back */
+                    tc.dirlevel = 0; 
+                }
+                ext = setting = NULL;
+                break;
+            }
             default:
                 ext = setting = NULL;
                 break;
diff --git a/apps/tree.h b/apps/tree.h
index a74960f..2d3e74c 100644
--- a/apps/tree.h
+++ b/apps/tree.h
@@ -31,7 +31,6 @@ struct entry {
     char *name;
 };
 
-
 /* browser context for file or db */
 struct tree_context {
     /* The directory we are browsing */
@@ -68,6 +67,9 @@ struct tree_context {
     int dentry_size;
     bool dirfull;
     int sort_dir; /* directory sort order */
+    
+    /* optional callback to do custom action handling */
+    int (*action_callback)(int action, struct tree_context *tc);
 };
 
 void tree_drawlists(void);
@@ -76,7 +78,8 @@ void tree_gui_init(void) INIT_ATTR;
 char* get_current_file(char* buffer, size_t buffer_len);
 void set_dirfilter(int l_dirfilter);
 void set_current_file(const char *path);
-int rockbox_browse(const char *root, int dirfilter);
+int rockbox_browse(const char *root, int dirfilter,
+                   int (*action_callback)(int action, struct tree_context *tc));
 bool create_playlist(void);
 void resume_directory(const char *dir);
 #ifdef WIN32
