diff --git a/apps/applimits.h b/apps/applimits.h index a18544e87d..6372dac924 100644 --- a/apps/applimits.h +++ b/apps/applimits.h @@ -23,5 +23,6 @@ #define AVERAGE_FILENAME_LENGTH 40 #define MAX_DIR_LEVELS 10 #define MAX_PLAYLIST_SIZE 10000 +#define MAX_QUEUED_FILES 100 #endif diff --git a/apps/lang/english.lang b/apps/lang/english.lang index e358474477..97435bb36c 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -1221,3 +1221,18 @@ id: LANG_BATTERY_CAPACITY desc: in settings_menu eng: "Battery Capacity" new: + +id: LANG_QUEUE_QUEUED +desc: queued track name %s +eng: "Queued: %s" +new: + +id: LANG_QUEUE_TOTAL +desc: number of queued tracks %d +eng: "Total queued: %d" +new: + +id: LANG_QUEUE_FULL +desc: queue buffer full +eng: "Queue buffer full" +new: diff --git a/apps/playlist.c b/apps/playlist.c index 38eca09fc9..0a99cb91f4 100644 --- a/apps/playlist.c +++ b/apps/playlist.c @@ -21,7 +21,7 @@ #include #include #include "playlist.h" -#include +#include "file.h" #include "sprintf.h" #include "debug.h" #include "mpeg.h" @@ -39,6 +39,7 @@ static struct playlist_info playlist; +#define QUEUE_FILE ROCKBOX_DIR "/.queue_file" #define PLAYLIST_BUFFER_SIZE (AVERAGE_FILENAME_LENGTH*MAX_FILES_IN_DIR) static unsigned char playlist_buffer[PLAYLIST_BUFFER_SIZE]; @@ -46,6 +47,207 @@ static int playlist_end_pos = 0; static char now_playing[MAX_PATH+1]; +/* + * remove any files and indices associated with the playlist + */ +static void empty_playlist(bool queue_resume) +{ + int fd; + + playlist.filename[0] = '\0'; + playlist.index = 0; + playlist.queue_index = 0; + playlist.last_queue_index = 0; + playlist.amount = 0; + playlist.num_queued = 0; + playlist.start_queue = 0; + + if (!queue_resume) + { + /* start with fresh queue file when starting new playlist */ + remove(QUEUE_FILE); + fd = creat(QUEUE_FILE, 0); + if (fd > 0) + close(fd); + } +} + +/* update queue list after resume */ +static void add_indices_to_queuelist(int seek) +{ + int nread; + int fd = -1; + int i = seek; + int count = 0; + bool store_index; + char buf[MAX_PATH]; + + unsigned char *p = buf; + + fd = open(QUEUE_FILE, O_RDONLY); + if(fd < 0) + return; + + nread = lseek(fd, seek, SEEK_SET); + if (nread < 0) + return; + + store_index = true; + + while(1) + { + nread = read(fd, buf, MAX_PATH); + if(nread <= 0) + break; + + p = buf; + + for(count=0; count < nread; count++,p++) { + if(*p == '\n') + store_index = true; + else if(store_index) + { + store_index = false; + + playlist.queue_indices[playlist.last_queue_index] = i+count; + playlist.last_queue_index = + (playlist.last_queue_index + 1) % MAX_QUEUED_FILES; + playlist.num_queued++; + } + } + + i += count; + } +} + +static int get_next_index(int steps, bool *queue) +{ + int current_index = playlist.index; + int next_index = -1; + + if (global_settings.repeat_mode == REPEAT_ONE) + steps = 0; + else if (steps >= 0) + steps -= playlist.start_queue; + + if (steps >= 0 && playlist.num_queued > 0 && + playlist.num_queued - steps > 0) + *queue = true; + else + { + *queue = false; + if (playlist.num_queued) + { + if (steps >= 0) + steps -= (playlist.num_queued - 1); + else if (!playlist.start_queue) + steps += 1; + } + } + + switch (global_settings.repeat_mode) + { + case REPEAT_OFF: + if (*queue) + next_index = (playlist.queue_index+steps) % MAX_QUEUED_FILES; + else + { + if (current_index < playlist.first_index) + current_index += playlist.amount; + current_index -= playlist.first_index; + + next_index = current_index+steps; + if ((next_index < 0) || (next_index >= playlist.amount)) + next_index = -1; + else + next_index = (next_index+playlist.first_index) % + playlist.amount; + } + break; + + case REPEAT_ONE: + if (*queue && !playlist.start_queue) + next_index = playlist.queue_index; + else + { + next_index = current_index; + *queue = false; + } + break; + + case REPEAT_ALL: + default: + if (*queue) + next_index = (playlist.queue_index+steps) % MAX_QUEUED_FILES; + else + { + next_index = (current_index+steps) % playlist.amount; + while (next_index < 0) + next_index += playlist.amount; + } + break; + } + + return next_index; +} + +int playlist_amount(void) +{ + return playlist.amount + playlist.num_queued; +} + +int playlist_first_index(void) +{ + return playlist.first_index; +} + +int playlist_get_resume_info(int *resume_index, int *queue_resume, + int *queue_resume_index) +{ + int result = 0; + + *resume_index = playlist.index; + + if (playlist.num_queued > 0) + { + if (global_settings.save_queue_resume) + { + *queue_resume_index = + playlist.queue_indices[playlist.queue_index]; + if (playlist.start_queue) + *queue_resume = QUEUE_BEGIN_PLAYLIST; + else + *queue_resume = QUEUE_BEGIN_QUEUE; + } + else if (!playlist.start_queue) + { + *queue_resume = QUEUE_OFF; + result = -1; + } + } + else + *queue_resume = QUEUE_OFF; + + return result; +} + +char *playlist_name(char *buf, int buf_size) +{ + char *sep; + + snprintf(buf, buf_size, "%s", playlist.filename+playlist.dirlen); + + if (0 == buf[0]) + return NULL; + + /* Remove extension */ + sep = strrchr(buf, '.'); + if (NULL != sep) + *sep = 0; + + return buf; +} + void playlist_clear(void) { playlist_end_pos = 0; @@ -66,73 +268,81 @@ int playlist_add(char *filename) return 0; } -static int get_next_index(int steps) +/* Add track to queue file */ +int queue_add(char *filename) { - int current_index = playlist.index; - int next_index = -1; + int fd, seek, result; + int len = strlen(filename); - switch (global_settings.repeat_mode) + if(playlist.num_queued >= MAX_QUEUED_FILES) + return -1; + + fd = open(QUEUE_FILE, O_WRONLY); + if (fd < 0) + return -1; + + seek = lseek(fd, 0, SEEK_END); + if (seek < 0) { - case REPEAT_OFF: - if (current_index < playlist.first_index) - current_index += playlist.amount; - current_index -= playlist.first_index; - - next_index = current_index+steps; - if ((next_index < 0) || (next_index >= playlist.amount)) - next_index = -1; - else - next_index = (next_index+playlist.first_index)%playlist.amount; - break; - - case REPEAT_ONE: - next_index = current_index; - break; - - case REPEAT_ALL: - default: - next_index = (current_index+steps) % playlist.amount; - while (next_index < 0) - next_index += playlist.amount; - break; + close(fd); + return -1; } - return next_index; -} + filename[len] = '\n'; + result = write(fd, filename, len+1); + if (result < 0) + { + close(fd); + return -1; + } + filename[len] = '\0'; -/* the mpeg thread might ask us */ -int playlist_amount(void) -{ - return playlist.amount; -} + close(fd); -int playlist_first_index(void) -{ - return playlist.first_index; -} + if (playlist.num_queued <= 0) + playlist.start_queue = 1; -char *playlist_name(char *buf, int buf_size) -{ - char *sep; + playlist.queue_indices[playlist.last_queue_index] = seek; + playlist.last_queue_index = + (playlist.last_queue_index + 1) % MAX_QUEUED_FILES; + playlist.num_queued++; - snprintf(buf, buf_size, "%s", playlist.filename+playlist.dirlen); + mpeg_flush_and_reload_tracks(); - if (0 == buf[0]) - return NULL; - - /* Remove extension */ - sep = strrchr(buf, '.'); - if (NULL != sep) - *sep = 0; - - return buf; + return playlist.num_queued; } int playlist_next(int steps) { - playlist.index = get_next_index(steps); + bool queue; + int index = get_next_index(steps, &queue); - return playlist.index; + if (queue) + { + int queue_diff = index - playlist.queue_index; + if (queue_diff < 0) + queue_diff += MAX_QUEUED_FILES; + + playlist.num_queued -= queue_diff; + playlist.queue_index = index; + playlist.start_queue = 0; + } + else + { + playlist.index = index; + if (playlist.num_queued > 0 && !playlist.start_queue) + { + if (steps >= 0) + { + playlist.queue_index = playlist.last_queue_index; + playlist.num_queued = 0; + } + else + playlist.start_queue = true; + } + } + + return index; } char* playlist_peek(int steps) @@ -145,24 +355,19 @@ char* playlist_peek(int steps) char dir_buf[MAX_PATH+1]; char *dir_end; int index; + bool queue; - index = get_next_index(steps); - if (index >= 0) - seek = playlist.indices[index]; - else + index = get_next_index(steps, &queue); + if (index < 0) return NULL; - if(playlist.in_ram) + if (queue) { - buf = playlist_buffer + seek; - max = playlist_end_pos - seek; - } - else - { - fd = open(playlist.filename, O_RDONLY); + seek = playlist.queue_indices[index]; + fd = open(QUEUE_FILE, O_RDONLY); if(-1 != fd) { - buf = playlist_buffer; + buf = dir_buf; lseek(fd, seek, SEEK_SET); max = read(fd, buf, MAX_PATH); close(fd); @@ -170,6 +375,29 @@ char* playlist_peek(int steps) else return NULL; } + else + { + seek = playlist.indices[index]; + + if(playlist.in_ram) + { + buf = playlist_buffer + seek; + max = playlist_end_pos - seek; + } + else + { + fd = open(playlist.filename, O_RDONLY); + if(-1 != fd) + { + buf = playlist_buffer; + lseek(fd, seek, SEEK_SET); + max = read(fd, buf, MAX_PATH); + close(fd); + } + else + return NULL; + } + } /* Zero-terminate the file name */ seek=0; @@ -260,11 +488,13 @@ int play_list(char *dir, /* "current directory" */ playlist AFTER the shuffle */ int start_offset, /* offset in the file */ int random_seed, /* used for shuffling */ - int first_index ) /* first index of playlist */ + int first_index, /* first index of playlist */ + int queue_resume, /* resume queue list? */ + int queue_resume_index ) /* queue list seek pos */ { char *sep=""; int dirlen; - empty_playlist(); + empty_playlist(queue_resume); playlist.index = start_index; playlist.first_index = first_index; @@ -343,6 +573,18 @@ int play_list(char *dir, /* "current directory" */ } } + /* update the queue indices */ + if (queue_resume) + { + add_indices_to_queuelist(queue_resume_index); + + if (queue_resume == QUEUE_BEGIN_PLAYLIST) + { + playlist.start_queue = 1; + playlist.index++; /* so we begin at the correct track */ + } + } + if(!playlist.in_ram) { lcd_puts(0,0,str(LANG_PLAYLIST_PLAY)); status_draw(); @@ -354,16 +596,6 @@ int play_list(char *dir, /* "current directory" */ return playlist.index; } -/* - * remove any filename and indices associated with the playlist - */ -void empty_playlist(void) -{ - playlist.filename[0] = '\0'; - playlist.index = 0; - playlist.amount = 0; -} - /* * calculate track offsets within a playlist file */ diff --git a/apps/playlist.h b/apps/playlist.h index 47422a40a5..57a23f2a8f 100644 --- a/apps/playlist.h +++ b/apps/playlist.h @@ -36,6 +36,13 @@ struct playlist_info int seed; /* random seed */ int amount; /* number of tracks in the index */ bool in_ram; /* True if the playlist is RAM-based */ + + /* Queue function */ + int queue_indices[MAX_QUEUED_FILES]; /* array of queue indices */ + int last_queue_index; /* index of last queued track */ + int queue_index; /* index of current playing queued track */ + int num_queued; /* number of songs queued */ + int start_queue; /* the first song was queued */ }; extern struct playlist_info playlist; @@ -43,18 +50,23 @@ extern bool playlist_shuffle; int play_list(char *dir, char *file, int start_index, bool shuffled_index, int start_offset, - int random_seed, int first_index); + int random_seed, int first_index, int queue_resume, + int queue_resume_index); char* playlist_peek(int steps); char* playlist_name(char *name, int name_size); int playlist_next(int steps); void randomise_playlist( unsigned int seed ); void sort_playlist(bool start_current); -void empty_playlist(void); void add_indices_to_playlist(void); void playlist_clear(void); int playlist_add(char *filename); +int queue_add(char *filename); int playlist_amount(void); int playlist_first_index(void); +int playlist_get_resume_info(int *resume_index, int *queue_resume, + int *queue_resume_index); + +enum { QUEUE_OFF, QUEUE_BEGIN_QUEUE, QUEUE_BEGIN_PLAYLIST, NUM_QUEUE_MODES }; #endif /* __PLAYLIST_H__ */ diff --git a/apps/settings.c b/apps/settings.c index 5a532bf95e..717443f6cd 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -92,14 +92,10 @@ offset abs 0x12 0x26 <(int) Resume playlist index, or -1 if no playlist resume> 0x16 0x2a <(int) Byte offset into resume file> 0x1a 0x2e