1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * Copyright (C)2003 by Benjamin Metzler
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
17 ****************************************************************************/
25 #include "applimits.h"
58 #define MAX_BOOKMARKS 10
59 #define MAX_BOOKMARK_SIZE 350
60 #define RECENT_BOOKMARK_FILE ROCKBOX_DIR "/most-recent.bmark"
62 static bool add_bookmark(const char* bookmark_file_name
, const char* bookmark
);
63 static bool check_bookmark(const char* bookmark
);
64 static char* create_bookmark(void);
65 static bool delete_bookmark(const char* bookmark_file_name
, int bookmark_id
);
66 static void display_bookmark(const char* bookmark
,
69 static void say_bookmark(const char* bookmark
,
71 static bool generate_bookmark_file_name(const char *in
);
72 static char* get_bookmark(const char* bookmark_file
, int bookmark_count
);
73 static bool parse_bookmark(const char *bookmark
,
77 int *resume_first_index
,
79 unsigned int resume_file_size
,
84 static char* select_bookmark(const char* bookmark_file_name
);
85 static bool system_check(void);
86 static bool write_bookmark(bool create_bookmark_file
);
87 static int get_bookmark_count(const char* bookmark_file_name
);
89 static char global_temp_buffer
[MAX_PATH
+1];
90 static char global_bookmark_file_name
[MAX_PATH
];
91 static char global_read_buffer
[MAX_BOOKMARK_SIZE
];
92 static char global_bookmark
[MAX_BOOKMARK_SIZE
];
93 static char global_filename
[MAX_PATH
];
95 /* ----------------------------------------------------------------------- */
96 /* This is the interface function from the main menu. */
97 /* ----------------------------------------------------------------------- */
98 bool bookmark_create_menu(void)
100 write_bookmark(true);
104 /* ----------------------------------------------------------------------- */
105 /* This function acts as the load interface from the main menu */
106 /* This function determines the bookmark file name and then loads that file*/
107 /* for the user. The user can then select a bookmark to load. */
108 /* If no file/directory is currently playing, the menu item does not work. */
109 /* ----------------------------------------------------------------------- */
110 bool bookmark_load_menu(void)
122 char* name
= playlist_get_name(NULL
, global_temp_buffer
,
123 sizeof(global_temp_buffer
));
124 if (generate_bookmark_file_name(name
))
126 bookmark
= select_bookmark(global_bookmark_file_name
);
128 return false; /* User exited without selecting a bookmark */
130 success
= parse_bookmark(bookmark
,
136 sizeof(global_temp_buffer
),
138 &global_settings
.repeat_mode
,
139 &global_settings
.playlist_shuffle
,
144 /* something bad happened while creating bookmark name*/
149 bookmark_play(global_temp_buffer
, index
, offset
, seed
,
156 /* ----------------------------------------------------------------------- */
157 /* Gives the user a list of the Most Recent Bookmarks. This is an */
158 /* interface function */
159 /* ----------------------------------------------------------------------- */
160 bool bookmark_mrb_load()
168 bookmark
= select_bookmark(RECENT_BOOKMARK_FILE
);
170 return false; /* User exited without selecting a bookmark */
172 success
= parse_bookmark(bookmark
,
178 sizeof(global_temp_buffer
),
180 &global_settings
.repeat_mode
,
181 &global_settings
.playlist_shuffle
,
185 bookmark_play(global_temp_buffer
, index
, offset
, seed
,
192 /* ----------------------------------------------------------------------- */
193 /* This function handles an autobookmark creation. This is an interface */
195 /* ----------------------------------------------------------------------- */
196 bool bookmark_autobookmark(void)
201 audio_pause(); /* first pause playback */
202 switch (global_settings
.autocreatebookmark
)
205 return write_bookmark(true);
210 case BOOKMARK_RECENT_ONLY_YES
:
211 return write_bookmark(false);
213 #ifdef HAVE_LCD_BITMAP
214 unsigned char *lines
[]={str(LANG_AUTO_BOOKMARK_QUERY
)};
215 struct text_message message
={(char **)lines
, 1};
217 unsigned char *lines
[]={str(LANG_AUTO_BOOKMARK_QUERY
),
218 str(LANG_RESUME_CONFIRM_PLAYER
)};
219 struct text_message message
={(char **)lines
, 2};
221 #ifdef HAVE_LCD_COLOR
222 show_main_backdrop(); /* switch to main backdrop as we may come from wps */
224 gui_syncstatusbar_draw(&statusbars
, false);
225 if(gui_syncyesno_run(&message
, NULL
, NULL
)==YESNO_YES
)
227 if (global_settings
.autocreatebookmark
== BOOKMARK_RECENT_ONLY_ASK
)
228 return write_bookmark(false);
230 return write_bookmark(true);
235 /* ----------------------------------------------------------------------- */
236 /* This function takes the current current resume information and writes */
237 /* that to the beginning of the bookmark file. */
238 /* This file will contain N number of bookmarks in the following format: */
239 /* resume_index*resume_offset*resume_seed*resume_first_index* */
240 /* resume_file*milliseconds*MP3 Title* */
241 /* ------------------------------------------------------------------------*/
242 static bool write_bookmark(bool create_bookmark_file
)
248 return false; /* something didn't happen correctly, do nothing */
250 bookmark
= create_bookmark();
252 return false; /* something didn't happen correctly, do nothing */
254 if (global_settings
.usemrb
)
255 success
= add_bookmark(RECENT_BOOKMARK_FILE
, bookmark
);
258 /* writing the bookmark */
259 if (create_bookmark_file
)
261 char* name
= playlist_get_name(NULL
, global_temp_buffer
,
262 sizeof(global_temp_buffer
));
263 if (generate_bookmark_file_name(name
))
265 success
= add_bookmark(global_bookmark_file_name
, bookmark
);
270 gui_syncsplash(HZ
, true, str(LANG_BOOKMARK_CREATE_SUCCESS
));
272 gui_syncsplash(HZ
, true, str(LANG_BOOKMARK_CREATE_FAILURE
));
277 /* ----------------------------------------------------------------------- */
278 /* This function adds a bookmark to a file. */
279 /* ------------------------------------------------------------------------*/
280 static bool add_bookmark(const char* bookmark_file_name
, const char* bookmark
)
282 int temp_bookmark_file
= 0;
283 int bookmark_file
= 0;
284 int bookmark_count
= 0;
285 char* playlist
= NULL
;
291 /* Opening up a temp bookmark file */
292 snprintf(global_temp_buffer
, sizeof(global_temp_buffer
),
293 "%s.tmp", bookmark_file_name
);
294 temp_bookmark_file
= open(global_temp_buffer
,
295 O_WRONLY
| O_CREAT
| O_TRUNC
);
296 if (temp_bookmark_file
< 0)
297 return false; /* can't open the temp file */
299 if (!strcmp(bookmark_file_name
,RECENT_BOOKMARK_FILE
) &&
300 (global_settings
.usemrb
== BOOKMARK_UNIQUE_ONLY
))
302 playlist
= strchr(bookmark
,'/');
303 cp
= strrchr(bookmark
,';');
308 /* Writing the new bookmark to the begining of the temp file */
309 write(temp_bookmark_file
, bookmark
, strlen(bookmark
));
310 write(temp_bookmark_file
, "\n", 1);
313 /* Reading in the previous bookmarks and writing them to the temp file */
314 bookmark_file
= open(bookmark_file_name
, O_RDONLY
);
315 if (bookmark_file
>= 0)
317 while (read_line(bookmark_file
, global_read_buffer
,
318 sizeof(global_read_buffer
)))
320 /* The MRB has a max of MAX_BOOKMARKS in it */
321 /* This keeps it from getting too large */
322 if ((strcmp(bookmark_file_name
,RECENT_BOOKMARK_FILE
)==0))
324 if(bookmark_count
>= MAX_BOOKMARKS
)
328 cp
= strchr(global_read_buffer
,'/');
329 tmp
= strrchr(global_read_buffer
,';');
330 if (check_bookmark(global_read_buffer
) &&
331 (!unique
|| len
!= tmp
-cp
|| strncmp(playlist
,cp
,len
)))
334 write(temp_bookmark_file
, global_read_buffer
,
335 strlen(global_read_buffer
));
336 write(temp_bookmark_file
, "\n", 1);
339 close(bookmark_file
);
341 close(temp_bookmark_file
);
343 remove(bookmark_file_name
);
344 rename(global_temp_buffer
, bookmark_file_name
);
350 /* ----------------------------------------------------------------------- */
351 /* This function takes the system resume data and formats it into a valid */
353 /* ----------------------------------------------------------------------- */
354 static char* create_bookmark()
356 int resume_index
= 0;
359 /* grab the currently playing track */
360 struct mp3entry
*id3
= audio_current_track();
364 /* Get some basic resume information */
365 /* queue_resume and queue_resume_index are not used and can be ignored.*/
366 playlist_get_resume_info(&resume_index
);
368 /* Get the currently playing file minus the path */
369 /* This is used when displaying the available bookmarks */
370 file
= strrchr(id3
->path
,'/');
374 /* create the bookmark */
375 snprintf(global_bookmark
, sizeof(global_bookmark
),
376 "%d;%ld;%d;%d;%ld;%d;%d;%s;%s",
379 playlist_get_seed(NULL
),
382 global_settings
.repeat_mode
,
383 global_settings
.playlist_shuffle
,
384 playlist_get_name(NULL
, global_temp_buffer
,
385 sizeof(global_temp_buffer
)),
388 /* checking to see if the bookmark is valid */
389 if (check_bookmark(global_bookmark
))
390 return global_bookmark
;
395 static bool check_bookmark(const char* bookmark
)
397 return parse_bookmark(bookmark
,
398 NULL
,NULL
,NULL
, NULL
,
403 /* ----------------------------------------------------------------------- */
404 /* This function will determine if an autoload is necessary. This is an */
405 /* interface function. */
406 /* ------------------------------------------------------------------------*/
407 bool bookmark_autoload(const char* file
)
414 if(global_settings
.autoloadbookmark
== BOOKMARK_NO
)
417 /*Checking to see if a bookmark file exists.*/
418 if(!generate_bookmark_file_name(file
))
422 fd
= open(global_bookmark_file_name
, O_RDONLY
);
425 if(-1 == lseek(fd
, 0, SEEK_END
))
431 if(global_settings
.autoloadbookmark
== BOOKMARK_YES
)
433 return bookmark_load(global_bookmark_file_name
, true);
437 /* Prompting user to confirm bookmark load */
439 screens
[i
].clear_display();
441 gui_syncstatusbar_draw(&statusbars
, false);
445 #ifdef HAVE_LCD_BITMAP
446 screens
[i
].setmargins(0, STATUSBAR_HEIGHT
);
447 screens
[i
].puts_scroll(0,0, str(LANG_BOOKMARK_AUTOLOAD_QUERY
));
448 screens
[i
].puts(0,1, str(LANG_CONFIRM_WITH_PLAY_RECORDER
));
449 screens
[i
].puts(0,2, str(LANG_BOOKMARK_SELECT_LIST_BOOKMARKS
));
450 screens
[i
].puts(0,3, str(LANG_CANCEL_WITH_ANY_RECORDER
));
453 screens
[i
].puts_scroll(0,0, str(LANG_BOOKMARK_AUTOLOAD_QUERY
));
454 screens
[i
].puts(0,1,str(LANG_RESUME_CONFIRM_PLAYER
));
460 /* Wait for a key to be pushed */
461 key
= button_get(true);
464 #ifdef HAVE_LCD_BITMAP
465 #ifdef BOOKMARK_RC_DOWN
466 case BOOKMARK_RC_DOWN
:
469 return bookmark_load(global_bookmark_file_name
, false);
471 #ifdef SETTINGS_RC_OK
475 return bookmark_load(global_bookmark_file_name
, true);
478 /* Handle sys events, ignore button releases & repeats */
479 if (default_event_handler(key
) ||
480 !(key
& (BUTTON_REPEAT
|BUTTON_REL
)))
489 /* ----------------------------------------------------------------------- */
490 /* This function loads the bookmark information into the resume memory. */
491 /* This is an interface function. */
492 /* ------------------------------------------------------------------------*/
493 bool bookmark_load(const char* file
, bool autoload
)
500 char* bookmark
= NULL
;;
504 fd
= open(file
, O_RDONLY
);
507 if(read_line(fd
, global_read_buffer
, sizeof(global_read_buffer
)))
508 bookmark
=global_read_buffer
;
514 /* This is not an auto-load, so list the bookmarks */
515 bookmark
=select_bookmark(file
);
517 return true; /* User exited without selecting a bookmark */
522 success
= parse_bookmark(bookmark
,
528 sizeof(global_temp_buffer
),
530 &global_settings
.repeat_mode
,
531 &global_settings
.playlist_shuffle
,
537 bookmark_play(global_temp_buffer
, index
, offset
, seed
,
544 static int get_bookmark_count(const char* bookmark_file_name
)
547 int file
= open(bookmark_file_name
, O_RDONLY
);
552 /* Get the requested bookmark */
553 while(read_line(file
, global_read_buffer
, sizeof(global_read_buffer
)))
555 if(check_bookmark(global_read_buffer
))
565 /* ----------------------------------------------------------------------- */
566 /* This displays a the bookmarks in a file and allows the user to */
567 /* select one to play. */
568 /* ------------------------------------------------------------------------*/
569 static char* select_bookmark(const char* bookmark_file_name
)
572 int bookmark_id_prev
= -1;
574 int lastkey
= BUTTON_NONE
;
575 char* bookmark
= NULL
;
576 int bookmark_count
= 0;
578 #ifdef HAVE_LCD_BITMAP
580 int x
= lcd_getxmargin();
581 int y
= lcd_getymargin();
583 screens
[i
].setmargins(0, 0);
586 bookmark_count
= get_bookmark_count(bookmark_file_name
);
591 bookmark_id
= bookmark_count
-1;
592 if(bookmark_id
>= bookmark_count
)
595 if (bookmark_id
!= bookmark_id_prev
)
597 bookmark
= get_bookmark(bookmark_file_name
, bookmark_id
);
598 bookmark_id_prev
= bookmark_id
;
603 /* if there were no bookmarks in the file, delete the file and exit. */
606 gui_syncsplash(HZ
, true, str(LANG_BOOKMARK_LOAD_EMPTY
));
607 remove(bookmark_file_name
);
612 bookmark_id_prev
= bookmark_id
;
618 display_bookmark(bookmark
, bookmark_id
, bookmark_count
);
619 if (global_settings
.talk_menu
) /* for voice UI */
620 say_bookmark(bookmark
, bookmark_id
);
623 /* waiting for the user to click a button */
624 key
= button_get(true);
627 #ifdef BOOKMARK_RC_SELECT
628 case BOOKMARK_RC_SELECT
:
630 case BOOKMARK_SELECT
:
631 #ifdef BOOKMARK_SELECT_PRE
632 if (lastkey
!= BOOKMARK_SELECT_PRE
)
635 /* User wants to use this bookmark */
636 #ifdef HAVE_LCD_BITMAP
637 if (global_settings
.statusbar
)
640 screens
[i
].setmargins(0, STATUSBAR_HEIGHT
);
645 screens
[i
].setmargins(0, 0);
649 #ifdef BOOKMARK_RC_DELETE
650 case BOOKMARK_RC_DELETE
:
652 case BOOKMARK_DELETE
:
653 /* User wants to delete this bookmark */
654 delete_bookmark(bookmark_file_name
, bookmark_id
);
657 if(bookmark_id
>= bookmark_count
)
658 bookmark_id
= bookmark_count
-1;
661 #ifdef SETTINGS_RC_DEC
662 case SETTINGS_RC_DEC
:
663 case SETTINGS_RC_DEC
| BUTTON_REPEAT
:
666 case SETTINGS_DEC
| BUTTON_REPEAT
:
670 #ifdef SETTINGS_RC_DEC
671 case SETTINGS_RC_INC
:
672 case SETTINGS_RC_INC
| BUTTON_REPEAT
:
675 case SETTINGS_INC
| BUTTON_REPEAT
:
679 #ifdef SETTINGS_RC_CANCEL
680 case SETTINGS_RC_CANCEL
:
682 #ifdef SETTINGS_RC_CANCEL2
683 case SETTINGS_RC_CANCEL2
:
685 case SETTINGS_CANCEL
:
686 #ifdef SETTINGS_CANCEL2
687 case SETTINGS_CANCEL2
:
689 #ifdef SETTINGS_RC_OK2
690 case SETTINGS_RC_OK2
:
695 #ifdef HAVE_LCD_BITMAP
697 screens
[i
].setmargins(x
, y
);
702 if(default_event_handler(key
) == SYS_USB_CONNECTED
)
713 /* ----------------------------------------------------------------------- */
714 /* This function takes a location in a bookmark file and deletes that */
716 /* ------------------------------------------------------------------------*/
717 static bool delete_bookmark(const char* bookmark_file_name
, int bookmark_id
)
719 int temp_bookmark_file
= 0;
720 int bookmark_file
= 0;
721 int bookmark_count
= 0;
723 /* Opening up a temp bookmark file */
724 snprintf(global_temp_buffer
, sizeof(global_temp_buffer
),
725 "%s.tmp", bookmark_file_name
);
726 temp_bookmark_file
= open(global_temp_buffer
,
727 O_WRONLY
| O_CREAT
| O_TRUNC
);
728 bookmark_file
= open(bookmark_file_name
, O_RDONLY
);
730 if (temp_bookmark_file
< 0 || bookmark_file
< 0)
731 return false; /* can't open one of the files */
733 /* Reading in the previous bookmarks and writing them to the temp file */
734 while (read_line(bookmark_file
, global_read_buffer
,
735 sizeof(global_read_buffer
)))
737 /* The MRB has a max of MAX_BOOKMARKS in it */
738 /* This keeps it from getting too large */
739 if ((strcmp(bookmark_file_name
,RECENT_BOOKMARK_FILE
)==0))
741 if(bookmark_count
>= MAX_BOOKMARKS
)
745 if (check_bookmark(global_read_buffer
))
747 if (bookmark_id
!= bookmark_count
)
749 write(temp_bookmark_file
, global_read_buffer
,
750 strlen(global_read_buffer
));
751 write(temp_bookmark_file
, "\n", 1);
757 close(bookmark_file
);
758 close(temp_bookmark_file
);
760 remove(bookmark_file_name
);
761 rename(global_temp_buffer
, bookmark_file_name
);
766 /* ----------------------------------------------------------------------- */
767 /* This function parses a bookmark and displays it for the user. */
768 /* ------------------------------------------------------------------------*/
769 static void display_bookmark(const char* bookmark
,
773 int resume_index
= 0;
776 bool playlist_shuffle
= false;
781 /* getting the index and the time into the file */
782 parse_bookmark(bookmark
,
783 &resume_index
, NULL
, NULL
, NULL
, NULL
, 0,
784 &ms
, &repeat_mode
, &playlist_shuffle
,
789 screens
[i
].clear_display();
790 screens
[i
].stop_scroll();
793 #ifdef HAVE_LCD_BITMAP
794 /* bookmark shuffle and repeat states*/
797 #if (AB_REPEAT_ENABLE == 1)
799 statusbar_icon_play_mode(Icon_RepeatAB
);
804 statusbar_icon_play_mode(Icon_RepeatOne
);
808 statusbar_icon_play_mode(Icon_Repeat
);
812 statusbar_icon_shuffle();
815 len
=strlen(global_filename
);
817 dot
=strrchr(global_filename
+ len
- 4, '.');
823 screens
[i
].puts_scroll(0, 0, (unsigned char *)global_filename
);
827 /* bookmark number */
828 snprintf(global_temp_buffer
, sizeof(global_temp_buffer
), "%s: %2d/%2d",
829 str(LANG_BOOKMARK_SELECT_BOOKMARK_TEXT
),
830 bookmark_id
+ 1, bookmark_count
);
832 screens
[i
].puts_scroll(0, 1, (unsigned char *)global_temp_buffer
);
834 /* bookmark resume index */
835 snprintf(global_temp_buffer
, sizeof(global_temp_buffer
), "%s: %2d",
836 str(LANG_BOOKMARK_SELECT_INDEX_TEXT
), resume_index
+1);
838 screens
[i
].puts_scroll(0, 2, (unsigned char *)global_temp_buffer
);
843 snprintf(global_temp_buffer
, sizeof(global_temp_buffer
), "%s: %ld:%02d",
844 str(LANG_BOOKMARK_SELECT_TIME_TEXT
),
846 (unsigned int)(ms
% 60000) / 1000);
847 /* unsigned int: hinting for 16bits archs */
851 snprintf(global_temp_buffer
, sizeof(global_temp_buffer
),
852 "%s: %ld:%02ld:%02d",
853 str(LANG_BOOKMARK_SELECT_TIME_TEXT
),
855 ms
% 3600000 / 60000,
856 (unsigned int)(ms
% 60000) / 1000);
859 screens
[i
].puts_scroll(0, 3, (unsigned char *)global_temp_buffer
);
864 screens
[i
].puts_scroll(0, 4, str(LANG_BOOKMARK_SELECT_PLAY
));
865 screens
[i
].puts_scroll(0, 5, str(LANG_BOOKMARK_SELECT_EXIT
));
866 screens
[i
].puts_scroll(0, 6, str(LANG_BOOKMARK_SELECT_DELETE
));
870 len
=strlen(global_filename
);
872 dot
=strrchr(global_filename
+len
-4,'.');
879 snprintf(global_temp_buffer
, sizeof(global_temp_buffer
),
880 "%2d, %ld:%02ld, %s,",
888 snprintf(global_temp_buffer
, sizeof(global_temp_buffer
),
889 "%2d, %ld:%02ld:%02ld, %s,",
892 ms
% 3600000 / 60000,
897 gui_syncstatusbar_draw(&statusbars
, false);
901 screens
[i
].puts_scroll(0,0,global_temp_buffer
);
902 screens
[i
].puts(0,1,str(LANG_RESUME_CONFIRM_PLAYER
));
908 #ifdef HAVE_LCD_BITMAP
915 /* ----------------------------------------------------------------------- */
916 /* This function parses a bookmark, says the voice UI part of it. */
917 /* ------------------------------------------------------------------------*/
918 static void say_bookmark(const char* bookmark
,
924 bool enqueue
= false; /* only the first voice is not queued */
926 parse_bookmark(bookmark
,
932 /* disabled, because transition between talkbox and voice UI clip is not nice */
934 if (global_settings
.talk_dir
>= 3)
935 { /* "talkbox" enabled */
936 char* last
= strrchr(dir
, '/');
938 { /* compose filename for talkbox */
939 strncpy(last
+ 1, dir_thumbnail_name
, sizeof(dir
)-(last
-dir
)-1);
940 talk_file(dir
, enqueue
);
945 talk_id(VOICE_EXT_BMARK
, enqueue
);
946 talk_number(bookmark_id
+ 1, true);
947 talk_id(LANG_BOOKMARK_SELECT_INDEX_TEXT
, true);
948 talk_number(resume_index
+ 1, true);
949 talk_id(LANG_BOOKMARK_SELECT_TIME_TEXT
, true);
951 talk_value(ms
/ 60000, UNIT_MIN
, true);
952 talk_value((ms
% 60000) / 1000, UNIT_SEC
, true);
956 /* ----------------------------------------------------------------------- */
957 /* This function retrieves a given bookmark from a file. */
958 /* If the bookmark requested is beyond the number of bookmarks available */
959 /* in the file, it will return the last one. */
960 /* It also returns the index number of the bookmark in the file */
961 /* ------------------------------------------------------------------------*/
962 static char* get_bookmark(const char* bookmark_file
, int bookmark_count
)
966 int file
= open(bookmark_file
, O_RDONLY
);
971 if (bookmark_count
< 0)
974 /* Get the requested bookmark */
975 while (read_count
< bookmark_count
)
977 /*Reading in a single bookmark */
978 result
= read_line(file
,
980 sizeof(global_read_buffer
));
982 /* Reading past the last bookmark in the file
983 causes the loop to stop */
991 if (read_count
== bookmark_count
)
992 return global_read_buffer
;
997 /* ----------------------------------------------------------------------- */
998 /* This function takes a bookmark and parses it. This function also */
999 /* validates the bookmark. Passing in NULL for an output variable */
1000 /* indicates that value is not requested. */
1001 /* ----------------------------------------------------------------------- */
1002 static bool parse_bookmark(const char *bookmark
,
1006 int *resume_first_index
,
1008 unsigned int resume_file_size
,
1010 int * repeat_mode
, bool *shuffle
,
1013 /* First check to see if a valid line was passed in. */
1014 int bookmark_len
= strlen(bookmark
);
1015 int local_resume_index
= 0;
1016 int local_resume_offset
= 0;
1017 int local_resume_seed
= 0;
1018 int local_resume_first_index
= 0;
1020 int local_shuffle
= 0;
1021 int local_repeat_mode
= 0;
1022 char* local_resume_file
= NULL
;
1023 char* local_file_name
= NULL
;
1026 static char bookmarkcopy
[MAX_BOOKMARK_SIZE
];
1028 /* Don't do anything if the bookmark length is 0 */
1029 if (bookmark_len
<= 0)
1032 /* Making a dup of the bookmark to use with strtok_r */
1033 strncpy(bookmarkcopy
, bookmark
, sizeof(bookmarkcopy
));
1034 bookmarkcopy
[sizeof(bookmarkcopy
) - 1] = 0;
1037 if ((field
= strtok_r(bookmarkcopy
, ";", &end
)))
1038 local_resume_index
= atoi(field
);
1043 if ((field
= strtok_r(NULL
, ";", &end
)))
1044 local_resume_offset
= atoi(field
);
1049 if ((field
= strtok_r(NULL
, ";", &end
)))
1050 local_resume_seed
= atoi(field
);
1054 /* resume_first_index */
1055 if ((field
= strtok_r(NULL
, ";", &end
)))
1056 local_resume_first_index
= atoi(field
);
1060 /* Milliseconds into MP3. Used for the bookmark select menu */
1061 if ((field
= strtok_r(NULL
, ";", &end
)))
1062 local_mS
= atoi(field
);
1067 if ((field
= strtok_r(NULL
, ";", &end
)))
1068 local_repeat_mode
= atoi(field
);
1073 if ((field
= strtok_r(NULL
, ";", &end
)))
1074 local_shuffle
= atoi(field
);
1078 /* resume_file & file_name (for the bookmark select menu)*/
1081 local_resume_file
= strtok_r(NULL
, ";", &end
);
1084 local_file_name
= strtok_r(NULL
, ";", &end
);
1089 /* Only return the values the calling function wants */
1091 *resume_index
= local_resume_index
;
1094 *resume_offset
= local_resume_offset
;
1097 *resume_seed
= local_resume_seed
;
1099 if (resume_first_index
)
1100 *resume_first_index
= local_resume_first_index
;
1102 if (resume_file
&& local_resume_file
)
1104 strncpy(resume_file
, local_resume_file
,
1105 MIN(strlen(local_resume_file
), resume_file_size
-1));
1106 resume_file
[MIN(strlen(local_resume_file
), resume_file_size
-1)]=0;
1113 *shuffle
= local_shuffle
;
1116 *repeat_mode
= local_repeat_mode
;
1118 if (file_name
&& local_file_name
)
1120 strncpy(file_name
, local_file_name
,MAX_PATH
-1);
1121 file_name
[MAX_PATH
-1] = 0;
1127 /* ----------------------------------------------------------------------- */
1128 /* This function is used by multiple functions and is used to generate a */
1129 /* bookmark named based off of the input. */
1130 /* Changing this function could result in how the bookmarks are stored. */
1131 /* it would be here that the centralized/decentralized bookmark code */
1132 /* could be placed. */
1133 /* ----------------------------------------------------------------------- */
1134 static bool generate_bookmark_file_name(const char *in
)
1136 int len
= strlen(in
);
1138 /* if this is a root dir MP3, rename the bookmark file root_dir.bmark */
1139 /* otherwise, name it based on the in variable */
1140 if (!strcmp("/", in
))
1141 strcpy(global_bookmark_file_name
, "/root_dir.bmark");
1144 strcpy(global_bookmark_file_name
, in
);
1145 if(global_bookmark_file_name
[len
-1] == '/')
1147 strcpy(&global_bookmark_file_name
[len
], ".bmark");
1153 /* ----------------------------------------------------------------------- */
1154 /* Returns the bookmark name for the current playlist */
1155 /* ----------------------------------------------------------------------- */
1156 bool bookmark_exist(void)
1162 char* name
= playlist_get_name(NULL
, global_temp_buffer
,
1163 sizeof(global_temp_buffer
));
1164 if (generate_bookmark_file_name(name
))
1166 int fd
=open(global_bookmark_file_name
, O_RDONLY
);
1178 /* ----------------------------------------------------------------------- */
1179 /* Checks the current state of the system and returns if it is in a */
1180 /* bookmarkable state. */
1181 /* ----------------------------------------------------------------------- */
1183 /* ----------------------------------------------------------------------- */
1185 /* return bool: Indicates if the system was in a bookmarkable state */
1186 /* ----------------------------------------------------------------------- */
1187 static bool system_check(void)
1189 int resume_index
= 0;
1190 struct mp3entry
*id3
= audio_current_track();
1194 /* no track playing */
1198 /* Checking to see if playing a queued track */
1199 if (playlist_get_resume_info(&resume_index
) == -1)
1201 /* something bad happened while getting the queue information */
1204 else if (playlist_modified(NULL
))
1206 /* can't bookmark while in the queue */