From e2c7da201dfb22a0a95d704dd8d44cd68a83eb69 Mon Sep 17 00:00:00 2001 From: Alex Bennee Date: Mon, 12 Jan 2009 16:42:19 +0000 Subject: [PATCH] v7 of the Save Playlist on new playlist functionality. * Rebased to current code base. * Clean up comments, remove funge function and simplyfy the menu stuff * As using NULL to fetch the playlist is OK we shouldn't really pass in random ptrs * Prevent warning on unused params * Use strlcpy * Fix language IDs and add a cancel menu item --- apps/filetree.c | 23 +++-- apps/lang/english.lang | 104 ++++++++++++++++++++-- apps/menus/playlist_menu.c | 201 +++++++++++++++++++++++++++++++++++++++++--- apps/misc.c | 17 ---- apps/misc.h | 4 - apps/playlist.c | 3 +- apps/playlist.h | 1 + apps/settings_list.c | 4 +- apps/tagtree.c | 8 +- 9 files changed, 305 insertions(+), 60 deletions(-) diff --git a/apps/filetree.c b/apps/filetree.c index 6b56c80..3e21cd3 100644 --- a/apps/filetree.c +++ b/apps/filetree.c @@ -104,11 +104,12 @@ bool ft_play_playlist(char* pathname, char* dirname, char* filename) splash(0, ID2P(LANG_WAIT)); - /* about to create a new current playlist... - allow user to cancel the operation */ - if (!warn_on_pl_erase()) - return false; - + /* maybe save the current playlist */ + if (!playlist_maybe_save_current()) + { + return false; + } + if (playlist_create(dirname, filename) != -1) { if (global_settings.playlist_shuffle) @@ -425,11 +426,13 @@ int ft_enter(struct tree_context* c) splash(0, ID2P(LANG_WAIT)); - /* about to create a new current playlist... - allow user to cancel the operation */ - if (!warn_on_pl_erase()) - break; - + /* about to create a new current + * playlist... allow user to + * cancel the operation + */ + if (!playlist_maybe_save_current()) + break; + if (global_settings.party_mode && audio_status()) { playlist_insert_track(NULL, buf, diff --git a/apps/lang/english.lang b/apps/lang/english.lang index ce72a52..fa76f91 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -6830,6 +6830,76 @@ + id: LANG_SAVE_CURRENT_PLAYLIST_Q + desc: Ask user if they want to save the current playlist when creating a new one? + user: core + + *: "Save Current Playlist?" + + + *: "Save Current Playlist?" + + + *: "Save Current Playlist?" + + + + id: LANG_SAVE_CURRENT_PLAYLIST_AS + desc: Save the old playlist under it's existing name + user: core + + *: "as '%s'" + + + *: "as '%s'" + + + *: "Save Current Playlist as '%s'" + + + + id: LANG_SAVE_CURRENT_PLAYLIST_AS_PROMPT + desc: Prompt the user to select a filename to save the old playlist as + user: core + + *: "as ..." + + + *: "as ..." + + + *: "as ..." + + + + id: LANG_DONT_SAVE_CURRENT_PLAYLIST + desc: Accept any changes to the old playlist will be lost + user: core + + *: "No (Changes will be lost)" + + + *: "No (Changes will be lost)" + + + *: "No (Changes will be lost)" + + + + id: LANG_CANCEL_NEW_PLAYLIST + desc: Cancel the action that would create a new playlist + user: core + + *: "Cancel (Don't create new playlist)" + + + *: "Cancel (Don't create new playlist)" + + + *: "Cancel (Don't create new playlist)" + + + id: LANG_PLAYLIST_SAVE_COUNT desc: splash number of tracks saved user: core @@ -6886,31 +6956,45 @@ - id: LANG_WARN_ERASEDYNPLAYLIST_MENU - desc: in playlist options menu, option to warn when erasing dynamic playlist + id: LANG_WARN_ERASE_PLAYLIST_MENU + desc: in playlist options menu, option to warn when erasing modified playlists + user: core + + *: "Warn When Erasing Modified Playlist" + + + *: "Warn When Erasing Modified Playlist" + + + *: "Warn When Erasing Modified Playlist" + + + + id: LANG_WARN_SAVE_PLAYLIST_PROMPT + desc: prompt shown when about to erase a modified playlist user: core - *: "Warn When Erasing Dynamic Playlist" + *: "Erase modified playlist?" - *: "Warn When Erasing Dynamic Playlist" + *: "Erase modified playlist?" - *: "Warn When Erasing Dynamic Playlist" + *: "Erase modified playlist?" - id: LANG_WARN_ERASEDYNPLAYLIST_PROMPT - desc: prompt shown when about to erase a modified dynamic playlist + id: LANG_WARN_ERASE_PLAYLIST_CONTINUE + desc: option to select if we are happy to continue and erase current playlist user: core - *: "Erase dynamic playlist?" + *: "Continue" - *: "Erase dynamic playlist?" + *: "Continue" - *: "Erase dynamic playlist?" + *: "Continue" diff --git a/apps/menus/playlist_menu.c b/apps/menus/playlist_menu.c index 87a61a9..429a5f0 100644 --- a/apps/menus/playlist_menu.c +++ b/apps/menus/playlist_menu.c @@ -8,6 +8,7 @@ * $Id$ * * Copyright (C) 2007 Jonathan Gordon + * Copyright (C) 2009 Alex Bennee * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -35,31 +36,90 @@ #include "playlist_viewer.h" #include "talk.h" #include "playlist_catalog.h" +#include "sprintf.h" -int save_playlist_screen(struct playlist_info* playlist) +#include "debug.h" + +extern struct playlist_info current_playlist; + +/* + playlist_menu_getname + + Fetch the current playlist name and then ensure: + + a) Ends in m3u8 (as we encode as UTF8) + b) Contains a proper path + c) Failing that is the default path +*/ + +static void playlist_menu_getname(struct playlist_info* playlist, char *str, int maxlen) { - char temp[MAX_PATH+1]; int len; - playlist_get_name(playlist, temp, sizeof(temp)); - len = strlen(temp); + /* + Fetch the playlist name, if playlist is NULL it will + fetch the current playing playlist name + */ + playlist_get_name(playlist, str, maxlen); + len = strlen(str); - if (len > 4 && !strcasecmp(&temp[len-4], ".m3u")) - strcat(temp, "8"); + /* Make sure playlist always ends in m3u8 */ + if (len > 4 && !strcasecmp(&str[len-4], ".m3u")) + strcat(str, "8"); - if (len <= 5 || strcasecmp(&temp[len-5], ".m3u8")) - strcpy(temp, DEFAULT_DYNAMIC_PLAYLIST_NAME); + /* If the playlist is shorter than the extension then it's + * probably a dud filename so replace it with the default + * filename + */ + if (len<=5) + { + /* directory config is of the format: "dir: /path/to/dir" */ + if (global_settings.playlist_catalog_dir[0]) + { + snprintf(str, maxlen, "%s%s", global_settings.playlist_catalog_dir, DEFAULT_DYNAMIC_PLAYLIST_NAME); + } else { + strlcpy(str, DEFAULT_DYNAMIC_PLAYLIST_NAME, sizeof(DEFAULT_DYNAMIC_PLAYLIST_NAME)); + } + } +} + +/* + save_playlist_screen + + Called when we want to save the current playlist. If the current + playlist is already named then sets the starting string as that. + + Returns 0 if we didn't anything, 1 once the playlist is saved +*/ + +int save_playlist_screen(struct playlist_info* playlist) +{ + char temp[MAX_PATH+1]; - if (!kbd_input(temp, sizeof(temp))) + playlist_menu_getname(playlist, temp, MAX_PATH); + + if (!kbd_input(temp, MAX_PATH)) { playlist_save(playlist, temp); /* reload in case playlist was saved to cwd */ reload_directory(); + + /* can exit menu now */ + return 1; } return 0; } + +/* + Main Menu -> Playlists -> + + Create Playlist + + View Current Playlist + + Save Current Playlist + + View Catalog +*/ + MENUITEM_FUNCTION(create_playlist_item, 0, ID2P(LANG_CREATE_PLAYLIST), (int(*)(void))create_playlist, NULL, NULL, Icon_NOICON); MENUITEM_FUNCTION(view_playlist, 0, ID2P(LANG_VIEW_DYNAMIC_PLAYLIST), @@ -70,13 +130,130 @@ MENUITEM_FUNCTION(save_playlist, MENU_FUNC_USEPARAM, ID2P(LANG_SAVE_DYNAMIC_PLAY MENUITEM_FUNCTION(catalog, 0, ID2P(LANG_CATALOG_VIEW), (int(*)(void))catalog_view_playlists, NULL, NULL, Icon_NOICON); +MAKE_MENU(playlist_options, ID2P(LANG_PLAYLISTS), NULL, + Icon_Playlist, + &create_playlist_item, &view_playlist, &save_playlist, &catalog); + +/* + Settings -> General Settings -> Playlists -> + + Recursively Insert Directories + + Warn When Erasing Modified Playlist +*/ + MENUITEM_SETTING(recursive_dir_insert, &global_settings.recursive_dir_insert, NULL); MENUITEM_SETTING(warn_on_erase, &global_settings.warnon_erase_dynplaylist, NULL); MAKE_MENU(playlist_settings, ID2P(LANG_PLAYLISTS), NULL, Icon_Playlist, &recursive_dir_insert, &warn_on_erase); -MAKE_MENU(playlist_options, ID2P(LANG_PLAYLISTS), NULL, - Icon_Playlist, - &create_playlist_item, &view_playlist, &save_playlist, &catalog); +/* Returns "Save current as " */ +static char* save_playlist_as_string(int selected_item, void * data, char *buffer) +{ + /* Unused */ + (void) selected_item; + (void) data; + + char temp[MAX_PATH]; + + playlist_menu_getname(NULL, temp, MAX_PATH); + snprintf(buffer, MAX_PATH, str(LANG_SAVE_CURRENT_PLAYLIST_AS), temp); + return buffer; +} + +/* Just save the playlist and exit */ +int save_playlist_now(void) +{ + char temp[MAX_PATH]; + + playlist_menu_getname(NULL, temp, MAX_PATH); + playlist_save(NULL, temp); + /* reload in case playlist was saved to cwd */ + reload_directory(); + return 1; +} + +/* + Menu: + + (Potential playlist erasing action) -> + "Save current playlist? + + as "current name" + + as .... + + No (Changes will be lost) + + Cancel (Don't create new playlist) +*/ + +MENUITEM_FUNCTION_DYNTEXT(pmsc_save_playlist_as, + MENU_FUNC_CHECK_RETVAL, + (int(*)(void))save_playlist_now, /* func */ + NULL, + save_playlist_as_string, + NULL, /* voice callback */ + NULL, + NULL, Icon_NOICON); + +MENUITEM_FUNCTION(pmsc_save_playlist, + MENU_FUNC_USEPARAM|MENU_FUNC_CHECK_RETVAL, + ID2P(LANG_SAVE_CURRENT_PLAYLIST_AS_PROMPT), + (int(*)(void*))save_playlist_screen, + ¤t_playlist, + NULL, Icon_NOICON); + +MENUITEM_RETURNVALUE(pmsc_continue, + ID2P(LANG_DONT_SAVE_CURRENT_PLAYLIST), /* Continue */ + 0, /* Returns 0 */ + NULL, Icon_NOICON); + +MENUITEM_RETURNVALUE(pmsc_cancel, + ID2P(LANG_CANCEL_NEW_PLAYLIST), /* Cancel */ + GO_TO_PREVIOUS, /* Same as pressing back */ + NULL, Icon_NOICON); + +MAKE_MENU(maybe_save_menu, ID2P(LANG_SAVE_CURRENT_PLAYLIST_Q), NULL, + Icon_Playlist, + &pmsc_save_playlist_as, &pmsc_save_playlist, &pmsc_continue, &pmsc_cancel); + +/* + * Potentially save current dynamic playlist. + * + * Originally we used to warn if the dynamic playlist was going to get + * over-written. Now we offer multiple options for quick save as + * defined in the above menu. + * + * If the user aborts the menu (e.g. going "back") we return false up + * the chain and abort whatever action we were about to do. + * + */ +bool playlist_maybe_save_current(void) +{ + bool r=true; + + DEBUGF("playlist_maybe_save_current: c:%s pm:%s mod:%s\n", + global_settings.warnon_erase_dynplaylist?"true":"false", + global_settings.party_mode?"true":"false", + playlist_modified(NULL)?"true":"false"); + + /* We only care if the playlist has been modified */ + if (global_settings.warnon_erase_dynplaylist && + !global_settings.party_mode && + playlist_modified(NULL)) + { + int menu_selection = 0; + int menu_r; + menu_r = do_menu(&maybe_save_menu, &menu_selection, NULL, false); + + + DEBUGF("playlist_maybe_save_current: menu_selection=%d menu_r=%d\n", + menu_selection, menu_r); + + /* Did we abort? */ + if (menu_r == GO_TO_PREVIOUS) { + r = false; + } + } + + DEBUGF("playlist_maybe_save_current: %s\n", r?"true":"false"); + return r; +} + diff --git a/apps/misc.c b/apps/misc.c index 939de44..2c06fa1 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -140,23 +140,6 @@ char *output_dyn_value(char *buf, int buf_size, int value, return buf; } -/* Ask the user if they really want to erase the current dynamic playlist - * returns true if the playlist should be replaced */ -bool warn_on_pl_erase(void) -{ - if (global_settings.warnon_erase_dynplaylist && - !global_settings.party_mode && - playlist_modified(NULL)) - { - static const char *lines[] = - {ID2P(LANG_WARN_ERASEDYNPLAYLIST_PROMPT)}; - static const struct text_message message={lines, 1}; - - return (gui_syncyesno_run(&message, NULL, NULL) == YESNO_YES); - } - else - return true; -} /* Read (up to) a line of text from fd into buffer and return number of bytes * read (which may be larger than the number of bytes stored in buffer). If diff --git a/apps/misc.h b/apps/misc.h index 34f754b..1b12caa 100644 --- a/apps/misc.h +++ b/apps/misc.h @@ -45,10 +45,6 @@ char *output_dyn_value(char *buf, int buf_size, int value, */ void format_time(char* buf, int buf_size, long t); -/* Ask the user if they really want to erase the current dynamic playlist - * returns true if the playlist should be replaced */ -bool warn_on_pl_erase(void); - /* Read (up to) a line of text from fd into buffer and return number of bytes * read (which may be larger than the number of bytes stored in buffer). If * an error occurs, -1 is returned (and buffer contains whatever could be diff --git a/apps/playlist.c b/apps/playlist.c index fb0b105..81d33e4 100644 --- a/apps/playlist.c +++ b/apps/playlist.c @@ -144,7 +144,7 @@ struct directory_search_context { int count; }; -static struct playlist_info current_playlist; +struct playlist_info current_playlist; static char now_playing[MAX_PATH+1]; static void empty_playlist(struct playlist_info* playlist, bool resume); @@ -3478,6 +3478,7 @@ int playlist_save(struct playlist_info* playlist, char *filename) return result; } + /* * Search specified directory for tracks and notify via callback. May be * called recursively. diff --git a/apps/playlist.h b/apps/playlist.h index fa234f6..e6fdc32 100644 --- a/apps/playlist.h +++ b/apps/playlist.h @@ -169,6 +169,7 @@ char *playlist_get_name(const struct playlist_info* playlist, char *buf, int playlist_get_track_info(struct playlist_info* playlist, int index, struct playlist_track_info* info); int playlist_save(struct playlist_info* playlist, char *filename); +bool playlist_maybe_save_current(void); int playlist_directory_tracksearch(const char* dirname, bool recurse, int (*callback)(char*, void*), void* context); diff --git a/apps/settings_list.c b/apps/settings_list.c index a60ee3f..99ac9f0 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c @@ -1340,8 +1340,8 @@ const struct settings_list settings[] = { ID2P(LANG_CODEPAGE_CENTRAL_EUROPEAN), ID2P(LANG_CODEPAGE_UTF8)), #endif - OFFON_SETTING(0, warnon_erase_dynplaylist, LANG_WARN_ERASEDYNPLAYLIST_MENU, - true, "warn when erasing dynamic playlist",NULL), + OFFON_SETTING(0, warnon_erase_dynplaylist, LANG_WARN_ERASE_PLAYLIST_MENU, + true, "warn when erasing modified playlist",NULL), #ifdef HAVE_BACKLIGHT #ifdef HAS_BUTTON_HOLD diff --git a/apps/tagtree.c b/apps/tagtree.c index 4b67b73..3f8f050 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c @@ -1503,10 +1503,10 @@ int tagtree_enter(struct tree_context* c) break; } c->dirlevel--; - /* about to create a new current playlist... - allow user to cancel the operation */ - if (!warn_on_pl_erase()) - break; + + /* maybe save the current playlist */ + if (!playlist_maybe_save_current()) + break; if (tagtree_play_folder(c) >= 0) rc = 2; -- 1.6.4.4