From da0525f54f0479f545bfe120f180ca14c256e28f Mon Sep 17 00:00:00 2001 From: Linus Nielsen Feltzing Date: Tue, 18 Jul 2006 13:54:12 +0000 Subject: Patch #5179 by Sebastian Henriksen and Hardeep Sidhu - Playlist catalog git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10232 a1c6a512-1295-4272-9138-f99709370657 --- apps/SOURCES | 1 + apps/lang/english.lang | 85 ++++++++ apps/onplay.c | 52 ++++- apps/playlist.c | 256 +++++++++++++----------- apps/playlist.h | 3 + apps/playlist_catalog.c | 504 ++++++++++++++++++++++++++++++++++++++++++++++++ apps/playlist_catalog.h | 39 ++++ apps/playlist_menu.c | 12 +- 8 files changed, 832 insertions(+), 120 deletions(-) create mode 100644 apps/playlist_catalog.c create mode 100644 apps/playlist_catalog.h diff --git a/apps/SOURCES b/apps/SOURCES index 4c479b7a60..7580c5e3f6 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -13,6 +13,7 @@ menu.c misc.c onplay.c playlist.c +playlist_catalog.c playlist_menu.c playlist_viewer.c plugin.c diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 0bf10055e6..78e4ab6147 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -8571,3 +8571,88 @@ *: "Export modifications" + + id: LANG_CATALOG + desc: in onplay menu + user: + + *: "Playlist catalog" + + + *: "Playlist catalog" + + + *: "Playlist catalog" + + + + id: LANG_CATALOG_ADD_TO + desc: in onplay playlist catalog submenu + user: + + *: "Add to playlist" + + + *: "Add to playlist" + + + *: "Add to playlist" + + + + id: LANG_CATALOG_ADD_TO_NEW + desc: in onplay playlist catalog submenu + user: + + *: "Add to new playlist" + + + *: "Add to new playlist" + + + *: "Add to new playlist" + + + + id: LANG_CATALOG_VIEW + desc: in onplay playlist catalog submenu + user: + + *: "View catalog" + + + *: "View catalog" + + + *: "View catalog" + + + + id: LANG_CATALOG_NO_DIRECTORY + desc: error message when playlist catalog directory doesn't exist + user: + + *: "%s doesn't exist" + + + *: "%s doesn't exist" + + + *: "" + + + + id: LANG_CATALOG_NO_PLAYLISTS + desc: error message when no playlists for playlist catalog + user: + + *: "No playlists" + + + *: "No playlists" + + + *: "" + + + diff --git a/apps/onplay.c b/apps/onplay.c index bc486d1a38..d552e41826 100644 --- a/apps/onplay.c +++ b/apps/onplay.c @@ -63,6 +63,7 @@ #include "eq_menu.h" #endif #include "playlist_menu.h" +#include "playlist_catalog.h" static int context; static char* selected_file = NULL; @@ -222,6 +223,50 @@ static bool view_playlist(void) return result; } +bool cat_add_to_a_playlist(void) +{ + return catalog_add_to_a_playlist(selected_file, selected_file_attr, + false); +} + +bool cat_add_to_a_new_playlist(void) +{ + return catalog_add_to_a_playlist(selected_file, selected_file_attr, true); +} + +static bool cat_playlist_options(void) +{ + struct menu_item items[3]; + int m, i=0, result; + bool ret = false; + + if ((audio_status() & AUDIO_STATUS_PLAY && context == CONTEXT_WPS) || + context == CONTEXT_TREE) + { + if (context == CONTEXT_WPS) + { + items[i].desc = ID2P(LANG_CATALOG_VIEW); + items[i].function = catalog_view_playlists; + i++; + } + + items[i].desc = ID2P(LANG_CATALOG_ADD_TO); + items[i].function = cat_add_to_a_playlist; + i++; + items[i].desc = ID2P(LANG_CATALOG_ADD_TO_NEW); + items[i].function = cat_add_to_a_new_playlist; + i++; + } + + m = menu_init( items, i, NULL, NULL, NULL, NULL ); + result = menu_show(m); + if(result >= 0) + ret = items[result].function(); + menu_exit(m); + + return ret; +} + /* Sub-menu for playlist options */ static bool playlist_options(void) { @@ -773,9 +818,9 @@ static int onplay_callback(int key, int menu) int onplay(char* file, int attr, int from) { #if CONFIG_CODEC == SWCODEC - struct menu_item items[13]; /* increase this if you add entries! */ + struct menu_item items[14]; /* increase this if you add entries! */ #else - struct menu_item items[11]; + struct menu_item items[12]; #endif int m, i=0, result; #ifdef HAVE_LCD_COLOR @@ -803,6 +848,9 @@ int onplay(char* file, int attr, int from) items[i].desc = ID2P(LANG_PLAYLIST); items[i].function = playlist_options; i++; + items[i].desc = ID2P(LANG_CATALOG); + items[i].function = cat_playlist_options; + i++; } if (context == CONTEXT_WPS) diff --git a/apps/playlist.c b/apps/playlist.c index 93293d75ed..a08ecdfe34 100644 --- a/apps/playlist.c +++ b/apps/playlist.c @@ -133,6 +133,13 @@ #define PLAYLIST_DISPLAY_COUNT 10 +struct directory_search_context { + struct playlist_info* playlist; + int position; + bool queue; + int count; +}; + static bool changing_dir = false; static struct playlist_info current_playlist; @@ -151,9 +158,7 @@ static int add_indices_to_playlist(struct playlist_info* playlist, static int add_track_to_playlist(struct playlist_info* playlist, const char *filename, int position, bool queue, int seek_pos); -static int add_directory_to_playlist(struct playlist_info* playlist, - const char *dirname, int *position, - bool queue, int *count, bool recurse); +static int directory_search_callback(char* filename, void* context); static int remove_track_from_playlist(struct playlist_info* playlist, int position, bool write); static int randomise_playlist(struct playlist_info* playlist, @@ -681,121 +686,46 @@ static int add_track_to_playlist(struct playlist_info* playlist, } /* - * Insert directory into playlist. May be called recursively. + * Callback for playlist_directory_tracksearch to insert track into + * playlist. */ -static int add_directory_to_playlist(struct playlist_info* playlist, - const char *dirname, int *position, - bool queue, int *count, bool recurse) +static int directory_search_callback(char* filename, void* context) { - char buf[MAX_PATH+1]; - unsigned char *count_str; - int result = 0; - int num_files = 0; - int i; - struct entry *files; - struct tree_context* tc = tree_get_context(); - int dirfilter = *(tc->dirfilter); + struct directory_search_context* c = + (struct directory_search_context*) context; + int insert_pos; - /* use the tree browser dircache to load files */ - *(tc->dirfilter) = SHOW_ALL; + insert_pos = add_track_to_playlist(c->playlist, filename, c->position, + c->queue, -1); - if (ft_load(tc, dirname) < 0) - { - gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); - *(tc->dirfilter) = dirfilter; + if (insert_pos < 0) return -1; - } - - 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 (queue) - count_str = str(LANG_PLAYLIST_QUEUE_COUNT); - else - count_str = str(LANG_PLAYLIST_INSERT_COUNT); - - for (i=0; icount)++; + + /* Make sure tracks are inserted in correct order if user requests + INSERT_FIRST */ + if (c->position == PLAYLIST_INSERT_FIRST || c->position >= 0) + c->position = insert_pos + 1; + + if (((c->count)%PLAYLIST_DISPLAY_COUNT) == 0) { - /* user abort */ - if (button_get(false) == SETTINGS_CANCEL) - { - result = -1; - break; - } + unsigned char* count_str; - if (files[i].attr & ATTR_DIRECTORY) - { - if (recurse) - { - /* recursively add directories */ - snprintf(buf, sizeof(buf), "%s/%s", dirname, files[i].name); - result = add_directory_to_playlist(playlist, buf, position, - queue, count, recurse); - if (result < 0) - break; - - /* we now need to reload our current directory */ - if(ft_load(tc, dirname) < 0) - { - result = -1; - break; - } - - files = (struct entry*) tc->dircache; - num_files = tc->filesindir; - if (!num_files) - { - result = -1; - break; - } - } - else - continue; - } - else if ((files[i].attr & TREE_ATTR_MASK) == TREE_ATTR_MPA) - { - int insert_pos; - - snprintf(buf, sizeof(buf), "%s/%s", dirname, files[i].name); - - insert_pos = add_track_to_playlist(playlist, buf, *position, - queue, -1); - if (insert_pos < 0) - { - result = -1; - break; - } - - (*count)++; - - /* Make sure tracks are inserted in correct order if user requests - INSERT_FIRST */ - if (*position == PLAYLIST_INSERT_FIRST || *position >= 0) - *position = insert_pos + 1; - - if ((*count%PLAYLIST_DISPLAY_COUNT) == 0) - { - display_playlist_count(*count, count_str); + if (c->queue) + count_str = str(LANG_PLAYLIST_QUEUE_COUNT); + else + count_str = str(LANG_PLAYLIST_INSERT_COUNT); - if (*count == PLAYLIST_DISPLAY_COUNT && - (audio_status() & AUDIO_STATUS_PLAY) && - playlist->started) - audio_flush_and_reload_tracks(); - } - - /* let the other threads work */ - yield(); - } + display_playlist_count(c->count, count_str); + + if ((c->count) == PLAYLIST_DISPLAY_COUNT && + (audio_status() & AUDIO_STATUS_PLAY) && + c->playlist->started) + audio_flush_and_reload_tracks(); } - /* restore dirfilter */ - *(tc->dirfilter) = dirfilter; - - return result; + return 0; } /* @@ -2811,9 +2741,9 @@ int playlist_insert_directory(struct playlist_info* playlist, const char *dirname, int position, bool queue, bool recurse) { - int count = 0; int result; unsigned char *count_str; + struct directory_search_context context; if (!playlist) playlist = ¤t_playlist; @@ -2829,18 +2759,23 @@ int playlist_insert_directory(struct playlist_info* playlist, else count_str = str(LANG_PLAYLIST_INSERT_COUNT); - display_playlist_count(count, count_str); + display_playlist_count(0, count_str); + + context.playlist = playlist; + context.position = position; + context.queue = queue; + context.count = 0; cpu_boost(true); - result = add_directory_to_playlist(playlist, dirname, &position, queue, - &count, recurse); + result = playlist_directory_tracksearch(dirname, recurse, + directory_search_callback, &context); sync_control(playlist, false); cpu_boost(false); - display_playlist_count(count, count_str); + display_playlist_count(context.count, count_str); if ((audio_status() & AUDIO_STATUS_PLAY) && playlist->started) audio_flush_and_reload_tracks(); @@ -3403,3 +3338,98 @@ int playlist_save(struct playlist_info* playlist, char *filename) return result; } + +/* + * Search specified directory for tracks and notify via callback. May be + * called recursively. + */ +int playlist_directory_tracksearch(const char* dirname, bool recurse, + int (*callback)(char*, void*), + void* context) +{ + char buf[MAX_PATH+1]; + int result = 0; + int num_files = 0; + int i; + struct entry *files; + struct tree_context* tc = tree_get_context(); + int old_dirfilter = *(tc->dirfilter); + + if (!callback) + return -1; + + /* use the tree browser dircache to load files */ + *(tc->dirfilter) = SHOW_ALL; + + if (ft_load(tc, dirname) < 0) + { + gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR)); + *(tc->dirfilter) = old_dirfilter; + return -1; + } + + files = (struct entry*) tc->dircache; + num_files = tc->filesindir; + + /* we've overwritten the dircache so tree browser will need to be + reloaded */ + reload_directory(); + + for (i=0; idircache; + num_files = tc->filesindir; + if (!num_files) + { + result = -1; + break; + } + } + else + continue; + } + else if ((files[i].attr & TREE_ATTR_MASK) == TREE_ATTR_MPA) + { + snprintf(buf, sizeof(buf), "%s/%s", dirname, files[i].name); + + if (callback(buf, context) != 0) + { + result = -1; + break; + } + + /* let the other threads work */ + yield(); + } + } + + /* restore dirfilter */ + *(tc->dirfilter) = old_dirfilter; + + return result; +} diff --git a/apps/playlist.h b/apps/playlist.h index 1a5bb3d33c..c5449a219e 100644 --- a/apps/playlist.h +++ b/apps/playlist.h @@ -158,5 +158,8 @@ 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); +int playlist_directory_tracksearch(const char* dirname, bool recurse, + int (*callback)(char*, void*), + void* context); #endif /* __PLAYLIST_H__ */ diff --git a/apps/playlist_catalog.c b/apps/playlist_catalog.c new file mode 100644 index 0000000000..a1a9bd8ea1 --- /dev/null +++ b/apps/playlist_catalog.c @@ -0,0 +1,504 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 Sebastian Henriksen, Hardeep Sidhu + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include +#include +#include +#include "action.h" +#include "dir.h" +#include "file.h" +#include "filetree.h" +#include "kernel.h" +#include "keyboard.h" +#include "lang.h" +#include "list.h" +#include "misc.h" +#include "onplay.h" +#include "playlist.h" +#include "settings.h" +#include "splash.h" +#include "sprintf.h" +#include "tree.h" +#include "yesno.h" + +#define PLAYLIST_CATALOG_CFG ROCKBOX_DIR "/playlist_catalog.config" +#define PLAYLIST_CATALOG_DEFAULT_DIR "/Playlists" +#define MAX_PLAYLISTS 400 +#define PLAYLIST_DISPLAY_COUNT 10 + +/* Use for recursive directory search */ +struct add_track_context { + int fd; + int count; +}; + +/* keep track of most recently used playlist */ +static char most_recent_playlist[MAX_PATH]; + +/* directory where our playlists our stored (configured in + PLAYLIST_CATALOG_CFG) */ +static char playlist_dir[MAX_PATH]; +static int playlist_dir_length; +static bool playlist_dir_exists = false; + +/* Retrieve playlist directory from config file and verify it exists */ +static int initialize_catalog(void) +{ + static bool initialized = false; + + if (!initialized) + { + int f; + DIR* dir; + bool default_dir = true; + + f = open(PLAYLIST_CATALOG_CFG, O_RDONLY); + if (f >= 0) + { + char buf[MAX_PATH+5]; + + while (read_line(f, buf, sizeof(buf))) + { + char* name; + char* value; + + /* directory config is of the format: "dir: /path/to/dir" */ + if (settings_parseline(buf, &name, &value) && + !strncasecmp(name, "dir:", strlen(name)) && + strlen(value) > 0) + { + strncpy(playlist_dir, value, strlen(value)); + default_dir = false; + } + } + + close(f); + } + + /* fall back to default directory if no or invalid config */ + if (default_dir) + strncpy(playlist_dir, PLAYLIST_CATALOG_DEFAULT_DIR, + sizeof(playlist_dir)); + + playlist_dir_length = strlen(playlist_dir); + + dir = opendir(playlist_dir); + if (dir) + { + playlist_dir_exists = true; + closedir(dir); + memset(most_recent_playlist, 0, sizeof(most_recent_playlist)); + initialized = true; + } + } + + if (!playlist_dir_exists) + { + gui_syncsplash(HZ*2, true, str(LANG_CATALOG_NO_DIRECTORY), + playlist_dir); + return -1; + } + + 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) + { + gui_syncsplash(HZ*2, true, str(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; idirfilter) = dirfilter; + return result; +} + +/* Callback for gui_synclist */ +static char* playlist_callback_name(int selected_item, void* data, + char* buffer) +{ + char** playlists = (char**) data; + + strncpy(buffer, playlists[selected_item], MAX_PATH); + + return buffer; +} + +/* 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; + int lastbutton = BUTTON_NONE; + bool exit = false; + char temp_buf[MAX_PATH]; + char* playlists[MAX_PLAYLISTS]; + struct gui_synclist playlist_lists; + + if (create_playlist_list(playlists, sizeof(playlists), + &num_playlists) != 0) + return -1; + + if (num_playlists <= 0) + { + gui_syncsplash(HZ*2, true, str(LANG_CATALOG_NO_PLAYLISTS)); + return -1; + } + + if (!playlist) + playlist = temp_buf; + + gui_synclist_init(&playlist_lists, playlist_callback_name, playlists, + false, 1); + gui_synclist_set_nb_items(&playlist_lists, num_playlists); + gui_synclist_draw(&playlist_lists); + + while (!exit) + { + int button = button_get_w_tmo(HZ/2); + char* sel_file; + + gui_synclist_do_button(&playlist_lists, button); + + sel_file = playlists[gui_synclist_get_sel_pos(&playlist_lists)]; + + switch (button) + { + case TREE_EXIT: +#ifdef TREE_RC_EXIT + case TREE_RC_EXIT: +#endif +#ifdef TREE_OFF + case TREE_OFF: +#endif + exit = true; + break; + +#ifdef TREE_ENTER + case TREE_ENTER: + case TREE_ENTER | BUTTON_REPEAT: +#endif +#ifdef TREE_RC_RUN + case TREE_RC_RUN: +#endif + case TREE_RUN: +#ifdef TREE_RUN_PRE + if (((button == TREE_RUN) +#ifdef TREE_RC_RUN_PRE + || (button == TREE_RC_RUN)) + && ((lastbutton != TREE_RC_RUN_PRE) +#endif + && (lastbutton != TREE_RUN_PRE))) + break; +#endif + + if (view) + { + /* In view mode, selecting a playlist starts playback */ + if (playlist_create(playlist_dir, sel_file) != -1) + { + if (global_settings.playlist_shuffle) + playlist_shuffle(current_tick, -1); + playlist_start(0, 0); + } + } + else + { + /* we found the playlist we want to add to */ + snprintf(playlist, MAX_PATH, "%s/%s", playlist_dir, + sel_file); + } + + result = 0; + exit = true; + break; + + case TREE_CONTEXT: +#ifdef TREE_CONTEXT2 + case TREE_CONTEXT2: +#endif +#ifdef TREE_RC_CONTEXT + case TREE_RC_CONTEXT: +#endif + /* context menu only available in view mode */ + if (view) + { + snprintf(playlist, MAX_PATH, "%s/%s", playlist_dir, + sel_file); + + if (onplay(playlist, TREE_ATTR_M3U, + CONTEXT_TREE) != ONPLAY_OK) + { + result = 0; + exit = true; + } + else + gui_synclist_draw(&playlist_lists); + } + break; + + case BUTTON_NONE: + gui_syncstatusbar_draw(&statusbars, false); + break; + + default: + if(default_event_handler(button) == SYS_USB_CONNECTED) + { + result = -1; + exit = true; + } + break; + } + + lastbutton = button; + } + + return result; +} + +/* display number of tracks inserted into playlists. Used for directory + insert */ +static void display_insert_count(int count) +{ + gui_syncsplash(0, true, str(LANG_PLAYLIST_INSERT_COUNT), count, +#if CONFIG_KEYPAD == PLAYER_PAD + str(LANG_STOP_ABORT) +#else + str(LANG_OFF_ABORT) +#endif + ); +} + +/* Add specified track into playlist. Callback from directory insert */ +static int add_track_to_playlist(char* filename, void* context) +{ + struct add_track_context* c = (struct add_track_context*) context; + + if (fdprintf(c->fd, "%s\n", filename) <= 0) + return -1; + + (c->count)++; + + if (((c->count)%PLAYLIST_DISPLAY_COUNT) == 0) + display_insert_count(c->count); + + return 0; +} + +/* Add "sel" file into specified "playlist". How to insert depends on type + of file */ +static int add_to_playlist(const char* playlist, char* sel, int sel_attr) +{ + int fd; + int result = -1; + + fd = open(playlist, O_CREAT|O_WRONLY|O_APPEND); + if(fd < 0) + return result; + + /* In case we're in the playlist directory */ + reload_directory(); + + if ((sel_attr & TREE_ATTR_MASK) == TREE_ATTR_MPA) + { + /* append the selected file */ + if (fdprintf(fd, "%s\n", sel) > 0) + result = 0; + } + else if ((sel_attr & TREE_ATTR_MASK) == TREE_ATTR_M3U) + { + /* append playlist */ + int f, fs, i; + char buf[1024]; + + if(strcasecmp(playlist, sel) == 0) + goto exit; + + f = open(sel, O_RDONLY); + if (f < 0) + goto exit; + + fs = filesize(f); + + for (i=0; i= fs) + result = 0; + + close(f); + } + else if (sel_attr & ATTR_DIRECTORY) + { + /* search directory for tracks and append to playlist */ + bool recurse = false; + char *lines[] = { + (char *)str(LANG_RECURSE_DIRECTORY_QUESTION), + sel + }; + struct text_message message={lines, 2}; + struct add_track_context context; + + if (global_settings.recursive_dir_insert != RECURSE_ASK) + recurse = (bool)global_settings.recursive_dir_insert; + else + { + /* Ask if user wants to recurse directory */ + recurse = (gui_syncyesno_run(&message, NULL, NULL)==YESNO_YES); + } + + context.fd = fd; + context.count = 0; + + display_insert_count(0); + + result = playlist_directory_tracksearch(sel, recurse, + add_track_to_playlist, &context); + + display_insert_count(context.count); + } + +exit: + close(fd); + return result; +} + +bool catalog_view_playlists(void) +{ + if (initialize_catalog() == -1) + return false; + + if (display_playlists(NULL, true) == -1) + return false; + + return true; +} + +bool catalog_add_to_a_playlist(char* sel, int sel_attr, bool new_playlist) +{ + char playlist[MAX_PATH]; + + if (initialize_catalog() == -1) + return false; + + if (new_playlist) + { + snprintf(playlist, MAX_PATH, "%s/", playlist_dir); + if (kbd_input(playlist, MAX_PATH)) + return false; + + if(strlen(playlist) <= 4 || + strcasecmp(&playlist[strlen(playlist)-4], ".m3u")) + strcat(playlist, ".m3u"); + } + else + { + if (display_playlists(playlist, false) == -1) + return false; + } + + if (add_to_playlist(playlist, sel, sel_attr) == 0) + { + strncpy(most_recent_playlist, playlist+playlist_dir_length+1, + sizeof(most_recent_playlist)); + return true; + } + else + return false; +} diff --git a/apps/playlist_catalog.h b/apps/playlist_catalog.h new file mode 100644 index 0000000000..591906e64f --- /dev/null +++ b/apps/playlist_catalog.h @@ -0,0 +1,39 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 Sebastian Henriksen, Hardeep Sidhu + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef _PLAYLIST_CATALOG_H_ +#define _PLAYLIST_CATALOG_H_ + +/* + * View list of playlists in catalog. + * ret : true if no error + */ +bool catalog_view_playlists(void); + +/* + * Add something to a playlist (new or select from list of playlists in + * catalog). + * sel : the path of the music file, playlist or directory to add + * sel_attr : the attributes that tell what type of file we're adding + * new_playlist : whether we want to create a new playlist or add to an + * existing one. + * ret : true if the file was successfully added + */ +bool catalog_add_to_a_playlist(char* sel, int sel_attr, bool new_playlist); + +#endif diff --git a/apps/playlist_menu.c b/apps/playlist_menu.c index ba4a4fe0d2..e23722160f 100644 --- a/apps/playlist_menu.c +++ b/apps/playlist_menu.c @@ -28,6 +28,7 @@ #include "playlist_viewer.h" #include "talk.h" #include "lang.h" +#include "playlist_catalog.h" #include "playlist_menu.h" static bool save_playlist(void) @@ -61,11 +62,12 @@ bool playlist_menu(void) bool result; static const struct menu_item items[] = { - { ID2P(LANG_CREATE_PLAYLIST), create_playlist }, - { ID2P(LANG_VIEW_DYNAMIC_PLAYLIST), playlist_viewer }, - { ID2P(LANG_SAVE_DYNAMIC_PLAYLIST), save_playlist }, - { ID2P(LANG_RECURSE_DIRECTORY), recurse_directory }, - { ID2P(LANG_WARN_ERASEDYNPLAYLIST_MENU), warnon_option}, + { ID2P(LANG_CREATE_PLAYLIST), create_playlist }, + { ID2P(LANG_VIEW_DYNAMIC_PLAYLIST), playlist_viewer }, + { ID2P(LANG_SAVE_DYNAMIC_PLAYLIST), save_playlist }, + { ID2P(LANG_CATALOG), catalog_view_playlists }, + { ID2P(LANG_RECURSE_DIRECTORY), recurse_directory }, + { ID2P(LANG_WARN_ERASEDYNPLAYLIST_MENU), warnon_option }, }; m = menu_init( items, sizeof items / sizeof(struct menu_item), NULL, -- cgit v1.2.3