plugins: random folder advance: misc improvements

fixes:
- traverse_dir was called recursively using two
  MAX_PATH local buffers => possible stack overflow
- The import function inserted additional, incorrect,
  entries when the whole line buffer was filled
- "Dirs not found" message overlapped number
  of folders when generating folder list
- Final number of scanned folders wasn't displayed
- Wouldn't stop inserting when maximum number
  of files in playlist was already reached
- Prevent buffer overflow when importing
- Don't write to fd after opening failed
- Use whole buffer with read_line, instead
  of subtracting 1. Remove hard coded sizes
- CRs don't need to be removed in import function
  (already handled by read_line)

features:
- Use insert context for *much* faster insertion
  of large # of folders, and nicer progress display
- Use UI viewport
- Add progress indicator when saving or loading
- Display number of folders in edit list title
- Go back to plugin's main menu from edit list
- Only ask to save changes if list is dirty
- Warn before erasing modified playlist
- Flag successfully created playlist as modified
- Make folder scan wait for dircache
- Shorten menu item names
- Put "Play Shuffled" menu item first
- Remember selection when returning from submenus
- Go to WPS after ACTION_TREE_WPS
- Exit menu when pressing Back
- Perform an initial scan, if no data file exists
  yet, when "Play Shuffled" or "Edit" is selected

Change-Id: I7df76f8fb8387888ce491d8b74b01b481e9997d3
This commit is contained in:
Christian Soffke 2026-01-01 19:26:06 +01:00
parent fcb2289274
commit f0d99391de
9 changed files with 582 additions and 428 deletions

View file

@ -296,7 +296,7 @@ static void op_playlist_insert_selected(int position, bool queue)
}
playlist_insert_directory(NULL, selected_file.path, position, queue,
recurse == RECURSE_ON);
recurse == RECURSE_ON, NULL);
}
}

View file

@ -2221,7 +2221,7 @@ int playlist_directory_tracksearch(const char* dirname, bool recurse,
/* user abort */
if (action_userabort(TIMEOUT_NOBLOCK))
{
result = -1;
result = -2;
break;
}
@ -2507,22 +2507,29 @@ void playlist_insert_context_release(struct playlist_insert_context *context)
*/
int playlist_insert_directory(struct playlist_info* playlist,
const char *dirname, int position, bool queue,
bool recurse)
bool recurse, struct playlist_insert_context* context)
{
int result = -1;
struct playlist_insert_context context;
result = playlist_insert_context_create(playlist, &context,
bool context_provided = context;
int result = 0;
struct playlist_insert_context c;
if (!context_provided)
{
context = &c;
result = playlist_insert_context_create(playlist, &c,
position, queue, true);
}
if (result >= 0)
{
cpu_boost(true);
result = playlist_directory_tracksearch(dirname, recurse,
directory_search_callback, &context);
directory_search_callback, context);
cpu_boost(false);
}
playlist_insert_context_release(&context);
if (!context_provided)
playlist_insert_context_release(&c);
return result;
}

View file

@ -157,7 +157,7 @@ int playlist_insert_context_add(struct playlist_insert_context *context,
void playlist_insert_context_release(struct playlist_insert_context *context);
int playlist_insert_directory(struct playlist_info* playlist,
const char *dirname, int position, bool queue,
bool recurse);
bool recurse, struct playlist_insert_context *context);
int playlist_insert_playlist(struct playlist_info* playlist, const char *filename,
int position, bool queue);
bool playlist_entries_iterate(const char *filename,

View file

@ -357,7 +357,10 @@ static const struct plugin_api rockbox_api = {
simplelist_show_list,
yesno_pop,
yesno_pop_confirm,
/* status bar */
sb_set_title_text,
sb_set_persistent_title,
/* action handling */
get_custom_action,
@ -738,6 +741,8 @@ static const struct plugin_api rockbox_api = {
playlist_insert_track,
playlist_insert_directory,
playlist_insert_playlist,
playlist_insert_context_create,
playlist_insert_context_release,
playlist_shuffle,
warn_on_pl_erase,
audio_play,
@ -874,7 +879,6 @@ static const struct plugin_api rockbox_api = {
/* new stuff at the end, sort into place next time
the API gets incompatible */
sb_set_persistent_title,
};
static int plugin_buffer_handle;

View file

@ -178,7 +178,7 @@ int plugin_open(const char *plugin, const char *parameter);
* when this happens please take the opportunity to sort in
* any new functions "waiting" at the end of the list.
*/
#define PLUGIN_API_VERSION 276
#define PLUGIN_API_VERSION 277
/* 239 Marks the removal of ARCHOS HWCODEC and CHARCELL */
@ -419,7 +419,11 @@ struct plugin_api {
bool (*simplelist_show_list)(struct simplelist_info *info);
bool (*yesno_pop)(const char* text);
bool (*yesno_pop_confirm)(const char* text);
/* status bar */
bool (*sb_set_title_text)(const char* title, enum themable_icons icon, enum screen_type screen);
bool (*sb_set_persistent_title)(const char* title, enum themable_icons icon,
enum screen_type screen);
/* action handling */
int (*get_custom_action)(int context,int timeout,
@ -863,9 +867,13 @@ struct plugin_api {
const char *filename, int position, bool queue, bool sync);
int (*playlist_insert_directory)(struct playlist_info* playlist,
const char *dirname, int position, bool queue,
bool recurse);
bool recurse, struct playlist_insert_context *context);
int (*playlist_insert_playlist)(struct playlist_info* playlist,
const char *filename, int position, bool queue);
int (*playlist_insert_context_create)(struct playlist_info* playlist,
struct playlist_insert_context *context,
int position, bool queue, bool progress);
void (*playlist_insert_context_release)(struct playlist_insert_context *context);
int (*playlist_shuffle)(int random_seed, int start_index);
bool (*warn_on_pl_erase)(void);
void (*audio_play)(unsigned long elapsed, unsigned long offset);
@ -1026,8 +1034,6 @@ struct plugin_api {
/* new stuff at the end, sort into place next time
the API gets incompatible */
bool (*sb_set_persistent_title)(const char* title, enum themable_icons icon,
enum screen_type screen);
};
/* plugin header */

View file

@ -392,7 +392,7 @@ RB_WRAP(playlist)
pos = luaL_optint(L, 3, PLAYLIST_INSERT);
queue = lua_toboolean(L, 4); /* default to false */
recurse = lua_toboolean(L, 5); /* default to false */
result = rb->playlist_insert_directory(NULL, dir, pos, queue, recurse);
result = rb->playlist_insert_directory(NULL, dir, pos, queue, recurse, NULL);
break;
case PLAYL_INSERTPLAYL:
filename = luaL_checkstring(L, 2); /* only required parameter */

File diff suppressed because it is too large Load diff

View file

@ -1874,13 +1874,14 @@ int playlist_get_track_info(struct playlist_info* playlist, int index, struct pl
\return
\description
int playlist_insert_directory(struct playlist_info* playlist, const char *dirname, int position, bool queue, bool recurse)
int playlist_insert_directory(struct playlist_info* playlist, const char *dirname, int position, bool queue, bool recurse, struct playlist_insert_context *context)
\group playback control
\param playlist
\param dirname
\param position
\param queue
\param recurse
\param context
\return
\description

View file

@ -5,7 +5,8 @@ when the Auto-Change Directory feature is set to \setting{Random}.
\subsubsection{Menu}
\begin{description}
\item[Generate Folder List] Generates a list of all folders found
\item[Play Shuffled] Starts playback with the selected directories in random order. Tracks within a directory will be played in normal order. The plugin will exit after starting playback.
\item[Scan Folders] Generates a list of all folders found
on the player. You can filter the directories which are scanned by
creating a file called \\*
\fname{/.rockbox/folder\_advance\_dir.txt}.
@ -16,12 +17,11 @@ Only the directories in this file and any contained directories
directory to be ignored.). If you just want \fname{/CDs}
to be ignored but want to include the folders within
it you need to have both \fname{-/CDs} and \fname{CDs} as entries.
\item[Edit Folder List] Enter the folder list editor
\item[Export List To Textfile] Exports the list to
\item[Edit] Enter the folder list editor
\item[Export to Text File] Exports the list to
\fname{/.rockbox/folder\_advance\_list.txt}
\item[Import List From Textfile] Imports the list from
\item[Import from Text File] Imports the list from
\fname{/.rockbox/folder\_advance\_list.txt}
\item[Play Shuffled] Starts playback with the selected directories in random order. Tracks within a directory will be played in normal order. The plugin will exit after starting playback.
\item[Quit]
\end{description}