Well, its working... sort of...
Attached is the first demo version.. yes there are compiler warnings
and waste code, this one is obviously not ready to commit... but if
your interested have a look...
I've only been testing this on the sim so far so if someone tries and
its unbareable (too slow) on targets please let me know.
atm, only loading a .bmark in the browser, and creating a .bmark from
the wps conext menu work (and it will always create the file
/dummy.bmark) so remember to rename it...
things to test: (some of these may be broken....)
you should be able to :-
* load a bmark file, then add new points to it without it creating any new files
* press cancel in the resume selection screen (only shown if there is
more than one resume point) and your previous playlist should resume
* modifying a playlist and adding new bookmarks should create new files
also, just a thing to note.. each bmark can have up to 10 resume
points (actually it can have infinite, but only the first 10 will be
selectable).
have a bit of a play, let me know how it goes (and if its workable)...
and PLEASE.. someone put your foot down and tell me how to name the
files...
Jonathan
Index: apps/misc.h
===================================================================
--- apps/misc.h (revision 18241)
+++ apps/misc.h (working copy)
@@ -111,6 +111,7 @@
#endif
int open_utf8(const char* pathname, int flags);
+bool file_copy(const char* src, const char* target);
#ifdef BOOTFILE
#if !defined(USB_NONE) && !defined(USB_IPODSTYLE)
Index: apps/playlist.c
===================================================================
--- apps/playlist.c (revision 18242)
+++ apps/playlist.c (working copy)
@@ -1854,6 +1854,11 @@
mutex_lock(&playlist->control_mutex);
+ if (playlist->bmark_fd >= 0)
+ {
+ close(playlist->bmark_fd);
+ playlist->bmark_fd = -1;
+ }
cache = &(playlist->control_cache[playlist->num_cached++]);
cache->command = command;
@@ -1936,6 +1941,7 @@
"%s", PLAYLIST_CONTROL_FILE);
playlist->fd = -1;
playlist->control_fd = -1;
+ playlist->bmark_fd = -1;
playlist->max_playlist_size = global_settings.max_files_in_playlist;
playlist->indices = buffer_alloc(
playlist->max_playlist_size * sizeof(int));
@@ -2291,6 +2297,9 @@
case '#':
current_command = PLAYLIST_COMMAND_COMMENT;
break;
+ case 'B':
+ current_command = PLAYLIST_COMMAND_RESUMEPOINT;
+ break;
default:
result = -1;
exit_loop = true;
@@ -3608,3 +3617,73 @@
return result;
}
+
+
+bool playlist_add_bookmark(char *bmark_filename, bool createnew)
+{
+ struct playlist_info *pl = ¤t_playlist;
+ struct playlist_resume_point resume_pt;
+ /* grab the currently playing track */
+ struct mp3entry *id3 = audio_current_track();
+ if(!id3)
+ return false;
+ resume_pt.track_position = id3->offset;
+ playlist_get_resume_info(&resume_pt.playlist_index);
+ sync_control(pl, true);
+ if (createnew || pl->bmark_fd < 0)
+ {
+ if (pl->bmark_fd >= 0)
+ close(pl->bmark_fd);
+ if (file_copy(PLAYLIST_CONTROL_FILE, bmark_filename) == false)
+ return false;
+ pl->bmark_fd = open(bmark_filename, O_RDWR|O_APPEND);
+ if (pl->bmark_fd < 0)
+ return false;
+ }
+ fdprintf(pl->bmark_fd, "B:%d:%ld\n", resume_pt.playlist_index, resume_pt.track_position);
+ return true;
+}
+
+/* setup the playlist from a bmark file and find any resume points in the bmark
+ if successful *resumes_count will be set to the number of available resumes
+ current_playlist.bmark_fd will also be set the to correct file and at the end
+ and ready to add new points if the playlist isnt changed */
+bool playlist_resume_bookmark(char *bmark_filename, struct playlist_resume_point *resumes, int *resumes_count)
+{
+ int maxresumes = *resumes_count;
+ struct playlist_info *pl = ¤t_playlist;
+ char buf[MAX_PATH];
+ *resumes_count = 0;
+ playlist_close(pl); /* may not be the best way to do this */
+ if (file_copy(bmark_filename, PLAYLIST_CONTROL_FILE) == false)
+ return false;
+ if (playlist_resume() >= 0)
+ {
+ /* playlist is loaded, open the origional bmark file and find any resume points */
+ pl->bmark_fd = open(bmark_filename, O_RDWR);
+ if (pl->bmark_fd < 0)
+ return false;
+ while (read_line(pl->bmark_fd, buf, MAX_PATH) > 0 &&
+ *resumes_count < maxresumes)
+ {
+ if (buf[0] == 'B')
+ {
+ struct playlist_resume_point *r = &resumes[*resumes_count];
+ if (sscanf(buf, "B:%d:%ld", &r->playlist_index, &r->track_position) == 2)
+ (*resumes_count)++;
+ }
+ }
+ lseek(pl->bmark_fd, SEEK_END, 0);
+ return true;
+ }
+ return false;
+}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
Index: apps/playlist.h
===================================================================
--- apps/playlist.h (revision 18241)
+++ apps/playlist.h (working copy)
@@ -42,7 +42,8 @@
PLAYLIST_COMMAND_SHUFFLE,
PLAYLIST_COMMAND_UNSHUFFLE,
PLAYLIST_COMMAND_RESET,
- PLAYLIST_COMMAND_COMMENT
+ PLAYLIST_COMMAND_COMMENT,
+ PLAYLIST_COMMAND_RESUMEPOINT
};
enum {
@@ -76,6 +77,8 @@
int fd; /* descriptor of the open playlist file */
int control_fd; /* descriptor of the open control file */
bool control_created; /* has control file been created? */
+ int bmark_fd; /* fd of the bmark file if it exists. set to -1 if
+ the control changes and it exists */
int dirlen; /* Length of the path to the playlist file */
unsigned long *indices; /* array of indices */
const struct dircache_entry **filenames; /* Entries from dircache */
@@ -113,6 +116,12 @@
int display_index; /* index of track for display */
};
+struct playlist_resume_point
+{
+ int playlist_index; /* index into the playlist for the current track */
+ long track_position; /* position in the current song to resume from */
+};
+
/* Exported functions only for current playlist. */
void playlist_init(void);
void playlist_shutdown(void);
Index: apps/onplay.c
===================================================================
--- apps/onplay.c (revision 18241)
+++ apps/onplay.c (working copy)
@@ -684,77 +684,10 @@
/* Paste a file to a new directory. Will overwrite always. */
static bool clipboard_pastefile(const char *src, const char *target, bool copy)
{
- int src_fd, target_fd;
- size_t buffersize;
- ssize_t size, bytesread, byteswritten;
- char *buffer;
bool result = false;
if (copy) {
- /* See if we can get the plugin buffer for the file copy buffer */
- buffer = (char *) plugin_get_buffer(&buffersize);
- if (buffer == NULL || buffersize < 512) {
- /* Not large enough, try for a disk sector worth of stack
- instead */
- buffersize = 512;
- buffer = (char *) __builtin_alloca(buffersize);
- }
-
- if (buffer == NULL) {
- return false;
- }
-
- buffersize &= ~0x1ff; /* Round buffer size to multiple of sector
- size */
-
- src_fd = open(src, O_RDONLY);
-
- if (src_fd >= 0) {
- target_fd = creat(target);
-
- if (target_fd >= 0) {
- result = true;
-
- size = filesize(src_fd);
-
- if (size == -1) {
- result = false;
- }
-
- while(size > 0) {
- bytesread = read(src_fd, buffer, buffersize);
-
- if (bytesread == -1) {
- result = false;
- break;
- }
-
- size -= bytesread;
-
- while(bytesread > 0) {
- byteswritten = write(target_fd, buffer, bytesread);
-
- if (byteswritten == -1) {
- result = false;
- size = 0;
- break;
- }
-
- bytesread -= byteswritten;
- draw_slider();
- }
- }
-
- close(target_fd);
-
- /* Copy failed. Cleanup. */
- if (!result) {
- remove(target);
- }
- }
-
- close(src_fd);
- }
+ result = file_copy(src, target);
} else {
result = rename(src, target) == 0;
#ifdef HAVE_MULTIVOLUME
Index: apps/filetree.c
===================================================================
--- apps/filetree.c (revision 18241)
+++ apps/filetree.c (working copy)
@@ -381,6 +381,7 @@
int seed = current_tick;
bool play = false;
int start_index=0;
+ long track_offset = 0;
switch ( file->attr & FILE_ATTR_MASK ) {
case FILE_ATTR_M3U:
@@ -491,7 +492,10 @@
case FILE_ATTR_BMARK:
gui_syncsplash(0, ID2P(LANG_WAIT));
- bookmark_load(buf, false);
+ if (bookmark_load(buf, false) == true)
+ {
+ start_wps = true;
+ }
reload_dir = true;
break;
Index: apps/bookmark.c
===================================================================
--- apps/bookmark.c (revision 18241)
+++ apps/bookmark.c (working copy)
@@ -110,7 +110,10 @@
/* ----------------------------------------------------------------------- */
bool bookmark_create_menu(void)
{
- write_bookmark(true, create_bookmark());
+// write_bookmark(true, create_bookmark());
+ char buffer[MAX_PATH];
+ if (!playlist_add_bookmark("/dummy.bmark", false))
+ gui_syncsplash(HZ, "FAiled!");
return false;
}
@@ -415,10 +418,85 @@
/* ----------------------------------------------------------------------- */
/* This function loads the bookmark information into the resume memory. */
-/* This is an interface function. */
/* ------------------------------------------------------------------------*/
+#define PREVIOUS_BMARK_FILE ROCKBOX_DIR "/previous.bmark"
+static char bookmark_resume_points[MAX_BOOKMARKS][MAX_BOOKMARK_SIZE];
+static int selection = -1;
+char * bmark_get_name(int selected_item, void * data,
+ char * buffer, size_t buffer_len)
+{
+ return bookmark_resume_points[selected_item];
+}
+int bmark_action_callback(int action, struct gui_synclist *lists)
+{
+ if (action == ACTION_STD_OK)
+ {
+ selection = lists->selected_item;
+ return ACTION_STD_CANCEL;
+ }
+ if (action == ACTION_STD_CANCEL)
+ selection = -1;
+ return action;
+}
bool bookmark_load(const char* file, bool autoload)
{
+ struct playlist_resume_point resumes[MAX_BOOKMARKS];
+ int resume_count = MAX_BOOKMARKS;
+ int i;
+ bool load_previous = !strcmp(file, PREVIOUS_BMARK_FILE);
+ struct playlist_track_info info;
+ int audio_playing = audio_status();
+ /* dump the current playlist and position incase the user wants to cancel */
+ if (load_previous)
+ {
+ if (playlist_resume_bookmark(PREVIOUS_BMARK_FILE, resumes, &resume_count)
+ && resume_count > 0)
+ {
+ remove(PREVIOUS_BMARK_FILE);
+ playlist_start(resumes[0].playlist_index,resumes[0].track_position);
+ }
+ return false;
+ }
+
+ playlist_add_bookmark(PREVIOUS_BMARK_FILE, true);
+ if (playlist_resume_bookmark(file, resumes, &resume_count) && resume_count > 0)
+ {
+ if (resume_count > 1)
+ {
+ for (i=0;i<resume_count;i++)
+ {
+ if (playlist_get_track_info(NULL, resumes[i].playlist_index, &info) > -1)
+ {
+ snprintf(bookmark_resume_points[i], MAX_BOOKMARK_SIZE, "%s: %d",
+ info.filename, resumes[i].track_position);
+ }
+ }
+ struct simplelist_info list;
+ simplelist_info_init(&list, "Bookmark", resume_count, NULL);
+ list.action_callback = bmark_action_callback;
+ list.get_name = bmark_get_name;
+ selection = -1;
+ simplelist_show_list(&list);
+ if (selection == -1)
+ {
+ if (audio_playing)
+ return bookmark_load(PREVIOUS_BMARK_FILE, true);
+ return false;
+ }
+ }
+ else
+ selection = 0;
+
+ playlist_start(resumes[selection].playlist_index,
+ resumes[selection].track_position);
+ return true;
+ }
+ else
+ return bookmark_load(PREVIOUS_BMARK_FILE, true);
+
+ return false;
+
+#if 0
int fd;
char* bookmark = NULL;
@@ -451,8 +529,7 @@
return false;
}
}
-
- return true;
+#endif
}
Index: apps/misc.c
===================================================================
--- apps/misc.c (revision 18241)
+++ apps/misc.c (working copy)
@@ -1208,7 +1208,79 @@
return fd;
}
+/** Copy a file from src to dst **/
+bool file_copy(const char* src, const char* target)
+{
+ int src_fd, target_fd;
+ size_t buffersize;
+ ssize_t size, bytesread, byteswritten;
+ char *buffer;
+ bool result = false;
+ /* See if we can get the plugin buffer for the file copy buffer */
+ buffer = (char *) plugin_get_buffer(&buffersize);
+ if (buffer == NULL || buffersize < 512) {
+ /* Not large enough, try for a disk sector worth of stack
+ instead */
+ buffersize = 512;
+ buffer = (char *) __builtin_alloca(buffersize);
+ }
+ if (buffer == NULL) {
+ return false;
+ }
+
+ buffersize &= ~0x1ff; /* Round buffer size to multiple of sector
+ size */
+
+ src_fd = open(src, O_RDONLY);
+
+ if (src_fd >= 0) {
+ target_fd = creat(target);
+
+ if (target_fd >= 0) {
+ result = true;
+
+ size = filesize(src_fd);
+
+ if (size == -1) {
+ result = false;
+ }
+
+ while(size > 0) {
+ bytesread = read(src_fd, buffer, buffersize);
+
+ if (bytesread == -1) {
+ result = false;
+ break;
+ }
+
+ size -= bytesread;
+
+ while(bytesread > 0) {
+ byteswritten = write(target_fd, buffer, bytesread);
+
+ if (byteswritten == -1) {
+ result = false;
+ size = 0;
+ break;
+ }
+
+ bytesread -= byteswritten;
+ // draw_slider();
+ }
+ }
+
+ close(target_fd);
+
+ /* Copy failed. Cleanup. */
+ if (!result) {
+ remove(target);
+ }
+ }
+ close(src_fd);
+ }
+ return result;
+}
#ifdef HAVE_LCD_COLOR
/*
* Helper function to convert a string of 6 hex digits to a native colour