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
,
64 static bool check_bookmark(const char* bookmark
);
65 static char* create_bookmark(void);
66 static bool delete_bookmark(const char* bookmark_file_name
, int bookmark_id
);
67 static void display_bookmark(const char* bookmark
,
70 static void say_bookmark(const char* bookmark
,
72 static bool play_bookmark(const char* bookmark
);
73 static bool generate_bookmark_file_name(const char *in
);
74 static char* get_bookmark(const char* bookmark_file
, int bookmark_count
);
75 static const char* skip_token(const char* s
);
76 static const char* int_token(const char* s
, int* dest
);
77 static const char* long_token(const char* s
, long* dest
);
78 static const char* bool_token(const char* s
, bool* dest
);
79 static bool parse_bookmark(const char *bookmark
,
83 int *resume_first_index
,
85 unsigned int resume_file_size
,
90 static char* select_bookmark(const char* bookmark_file_name
);
91 static bool system_check(void);
92 static bool write_bookmark(bool create_bookmark_file
);
93 static int get_bookmark_count(const char* bookmark_file_name
);
95 static char global_temp_buffer
[MAX_PATH
+1];
96 static char global_bookmark_file_name
[MAX_PATH
];
97 static char global_read_buffer
[MAX_BOOKMARK_SIZE
];
98 static char global_bookmark
[MAX_BOOKMARK_SIZE
];
99 static char global_filename
[MAX_PATH
];
101 /* ----------------------------------------------------------------------- */
102 /* This is the interface function from the main menu. */
103 /* ----------------------------------------------------------------------- */
104 bool bookmark_create_menu(void)
106 write_bookmark(true);
110 /* ----------------------------------------------------------------------- */
111 /* This function acts as the load interface from the main menu */
112 /* This function determines the bookmark file name and then loads that file*/
113 /* for the user. The user can then select a bookmark to load. */
114 /* If no file/directory is currently playing, the menu item does not work. */
115 /* ----------------------------------------------------------------------- */
116 bool bookmark_load_menu(void)
120 char* name
= playlist_get_name(NULL
, global_temp_buffer
,
121 sizeof(global_temp_buffer
));
122 if (generate_bookmark_file_name(name
))
124 char* bookmark
= select_bookmark(global_bookmark_file_name
);
126 if (bookmark
!= NULL
)
128 return play_bookmark(bookmark
);
136 /* ----------------------------------------------------------------------- */
137 /* Gives the user a list of the Most Recent Bookmarks. This is an */
138 /* interface function */
139 /* ----------------------------------------------------------------------- */
140 bool bookmark_mrb_load()
142 char* bookmark
= select_bookmark(RECENT_BOOKMARK_FILE
);
144 if (bookmark
!= NULL
)
146 return play_bookmark(bookmark
);
152 /* ----------------------------------------------------------------------- */
153 /* This function handles an autobookmark creation. This is an interface */
155 /* ----------------------------------------------------------------------- */
156 bool bookmark_autobookmark(void)
161 audio_pause(); /* first pause playback */
162 switch (global_settings
.autocreatebookmark
)
165 return write_bookmark(true);
170 case BOOKMARK_RECENT_ONLY_YES
:
171 return write_bookmark(false);
173 #ifdef HAVE_LCD_BITMAP
174 unsigned char *lines
[]={str(LANG_AUTO_BOOKMARK_QUERY
)};
175 struct text_message message
={(char **)lines
, 1};
177 unsigned char *lines
[]={str(LANG_AUTO_BOOKMARK_QUERY
),
178 str(LANG_RESUME_CONFIRM_PLAYER
)};
179 struct text_message message
={(char **)lines
, 2};
182 show_main_backdrop(); /* switch to main backdrop as we may come from wps */
184 gui_syncstatusbar_draw(&statusbars
, false);
185 if(gui_syncyesno_run(&message
, NULL
, NULL
)==YESNO_YES
)
187 if (global_settings
.autocreatebookmark
== BOOKMARK_RECENT_ONLY_ASK
)
188 return write_bookmark(false);
190 return write_bookmark(true);
195 /* ----------------------------------------------------------------------- */
196 /* This function takes the current current resume information and writes */
197 /* that to the beginning of the bookmark file. */
198 /* This file will contain N number of bookmarks in the following format: */
199 /* resume_index*resume_offset*resume_seed*resume_first_index* */
200 /* resume_file*milliseconds*MP3 Title* */
201 /* ------------------------------------------------------------------------*/
202 static bool write_bookmark(bool create_bookmark_file
)
208 return false; /* something didn't happen correctly, do nothing */
210 bookmark
= create_bookmark();
212 return false; /* something didn't happen correctly, do nothing */
214 if (global_settings
.usemrb
)
215 success
= add_bookmark(RECENT_BOOKMARK_FILE
, bookmark
, true);
218 /* writing the bookmark */
219 if (create_bookmark_file
)
221 char* name
= playlist_get_name(NULL
, global_temp_buffer
,
222 sizeof(global_temp_buffer
));
223 if (generate_bookmark_file_name(name
))
225 success
= add_bookmark(global_bookmark_file_name
, bookmark
, false);
229 gui_syncsplash(HZ
, str(success
? LANG_BOOKMARK_CREATE_SUCCESS
230 : LANG_BOOKMARK_CREATE_FAILURE
));
235 /* ----------------------------------------------------------------------- */
236 /* This function adds a bookmark to a file. */
237 /* ------------------------------------------------------------------------*/
238 static bool add_bookmark(const char* bookmark_file_name
, const char* bookmark
,
241 int temp_bookmark_file
= 0;
242 int bookmark_file
= 0;
243 int bookmark_count
= 0;
244 char* playlist
= NULL
;
250 /* Opening up a temp bookmark file */
251 snprintf(global_temp_buffer
, sizeof(global_temp_buffer
),
252 "%s.tmp", bookmark_file_name
);
253 temp_bookmark_file
= open(global_temp_buffer
,
254 O_WRONLY
| O_CREAT
| O_TRUNC
);
255 if (temp_bookmark_file
< 0)
256 return false; /* can't open the temp file */
258 if (most_recent
&& (global_settings
.usemrb
== BOOKMARK_UNIQUE_ONLY
))
260 playlist
= strchr(bookmark
,'/');
261 cp
= strrchr(bookmark
,';');
266 /* Writing the new bookmark to the begining of the temp file */
267 write(temp_bookmark_file
, bookmark
, strlen(bookmark
));
268 write(temp_bookmark_file
, "\n", 1);
271 /* Reading in the previous bookmarks and writing them to the temp file */
272 bookmark_file
= open(bookmark_file_name
, O_RDONLY
);
273 if (bookmark_file
>= 0)
275 while (read_line(bookmark_file
, global_read_buffer
,
276 sizeof(global_read_buffer
)) > 0)
278 /* The MRB has a max of MAX_BOOKMARKS in it */
279 /* This keeps it from getting too large */
280 if (most_recent
&& (bookmark_count
>= MAX_BOOKMARKS
))
283 cp
= strchr(global_read_buffer
,'/');
284 tmp
= strrchr(global_read_buffer
,';');
285 if (check_bookmark(global_read_buffer
) &&
286 (!unique
|| len
!= tmp
-cp
|| strncmp(playlist
,cp
,len
)))
289 write(temp_bookmark_file
, global_read_buffer
,
290 strlen(global_read_buffer
));
291 write(temp_bookmark_file
, "\n", 1);
294 close(bookmark_file
);
296 close(temp_bookmark_file
);
298 remove(bookmark_file_name
);
299 rename(global_temp_buffer
, bookmark_file_name
);
305 /* ----------------------------------------------------------------------- */
306 /* This function takes the system resume data and formats it into a valid */
308 /* ----------------------------------------------------------------------- */
309 static char* create_bookmark()
311 int resume_index
= 0;
314 /* grab the currently playing track */
315 struct mp3entry
*id3
= audio_current_track();
319 /* Get some basic resume information */
320 /* queue_resume and queue_resume_index are not used and can be ignored.*/
321 playlist_get_resume_info(&resume_index
);
323 /* Get the currently playing file minus the path */
324 /* This is used when displaying the available bookmarks */
325 file
= strrchr(id3
->path
,'/');
329 /* create the bookmark */
330 snprintf(global_bookmark
, sizeof(global_bookmark
),
331 "%d;%ld;%d;%d;%ld;%d;%d;%s;%s",
334 playlist_get_seed(NULL
),
337 global_settings
.repeat_mode
,
338 global_settings
.playlist_shuffle
,
339 playlist_get_name(NULL
, global_temp_buffer
,
340 sizeof(global_temp_buffer
)),
343 /* checking to see if the bookmark is valid */
344 if (check_bookmark(global_bookmark
))
345 return global_bookmark
;
350 static bool check_bookmark(const char* bookmark
)
352 return parse_bookmark(bookmark
,
353 NULL
,NULL
,NULL
, NULL
,
358 /* ----------------------------------------------------------------------- */
359 /* This function will determine if an autoload is necessary. This is an */
360 /* interface function. */
361 /* ------------------------------------------------------------------------*/
362 bool bookmark_autoload(const char* file
)
368 if(global_settings
.autoloadbookmark
== BOOKMARK_NO
)
371 /*Checking to see if a bookmark file exists.*/
372 if(!generate_bookmark_file_name(file
))
376 fd
= open(global_bookmark_file_name
, O_RDONLY
);
380 if(global_settings
.autoloadbookmark
== BOOKMARK_YES
)
382 return bookmark_load(global_bookmark_file_name
, true);
386 /* Prompting user to confirm bookmark load */
388 screens
[i
].clear_display();
390 gui_syncstatusbar_draw(&statusbars
, false);
394 #ifdef HAVE_LCD_BITMAP
395 screens
[i
].setmargins(0, STATUSBAR_HEIGHT
);
396 screens
[i
].puts_scroll(0,0, str(LANG_BOOKMARK_AUTOLOAD_QUERY
));
397 screens
[i
].puts(0,1, str(LANG_CONFIRM_WITH_PLAY_RECORDER
));
398 screens
[i
].puts(0,2, str(LANG_BOOKMARK_SELECT_LIST_BOOKMARKS
));
399 screens
[i
].puts(0,3, str(LANG_CANCEL_WITH_ANY_RECORDER
));
402 screens
[i
].puts_scroll(0,0, str(LANG_BOOKMARK_AUTOLOAD_QUERY
));
403 screens
[i
].puts(0,1,str(LANG_RESUME_CONFIRM_PLAYER
));
407 /* Wait for a key to be pushed */
408 key
= get_action(CONTEXT_BOOKMARKSCREEN
,TIMEOUT_BLOCK
);
411 #ifdef HAVE_LCD_BITMAP
412 case ACTION_STD_NEXT
:
413 action_signalscreenchange();
414 return bookmark_load(global_bookmark_file_name
, false);
416 case ACTION_BMS_SELECT
:
417 action_signalscreenchange();
418 return bookmark_load(global_bookmark_file_name
, true);
424 action_signalscreenchange();
429 /* ----------------------------------------------------------------------- */
430 /* This function loads the bookmark information into the resume memory. */
431 /* This is an interface function. */
432 /* ------------------------------------------------------------------------*/
433 bool bookmark_load(const char* file
, bool autoload
)
436 char* bookmark
= NULL
;;
440 fd
= open(file
, O_RDONLY
);
443 if(read_line(fd
, global_read_buffer
, sizeof(global_read_buffer
)) > 0)
444 bookmark
=global_read_buffer
;
450 /* This is not an auto-load, so list the bookmarks */
451 bookmark
= select_bookmark(file
);
454 if (bookmark
!= NULL
)
456 return play_bookmark(bookmark
);
463 static int get_bookmark_count(const char* bookmark_file_name
)
466 int file
= open(bookmark_file_name
, O_RDONLY
);
471 /* Get the requested bookmark */
472 while(read_line(file
, global_read_buffer
, sizeof(global_read_buffer
)) > 0)
483 /* ----------------------------------------------------------------------- */
484 /* This displays a the bookmarks in a file and allows the user to */
485 /* select one to play. */
486 /* ------------------------------------------------------------------------*/
487 static char* select_bookmark(const char* bookmark_file_name
)
490 int bookmark_id_prev
= -1;
492 char* bookmark
= NULL
;
493 int bookmark_count
= 0;
495 #ifdef HAVE_LCD_BITMAP
499 screens
[i
].setmargins(0, global_settings
.statusbar
500 ? STATUSBAR_HEIGHT
: 0);
503 bookmark_count
= get_bookmark_count(bookmark_file_name
);
504 if (bookmark_count
< 1) /* error opening file, or empty file */
506 gui_syncsplash(HZ
, str(LANG_BOOKMARK_LOAD_EMPTY
));
509 action_signalscreenchange();
513 bookmark_id
= bookmark_count
-1;
514 if(bookmark_id
>= bookmark_count
)
517 if (bookmark_id
!= bookmark_id_prev
)
519 bookmark
= get_bookmark(bookmark_file_name
, bookmark_id
);
520 bookmark_id_prev
= bookmark_id
;
525 /* if there were no bookmarks in the file, delete the file and exit. */
528 gui_syncsplash(HZ
, str(LANG_BOOKMARK_LOAD_EMPTY
));
529 remove(bookmark_file_name
);
530 action_signalscreenchange();
535 bookmark_id_prev
= bookmark_id
;
542 display_bookmark(bookmark
, bookmark_id
, bookmark_count
);
543 if (global_settings
.talk_menu
) /* for voice UI */
544 say_bookmark(bookmark
, bookmark_id
);
547 /* waiting for the user to click a button */
548 key
= get_action(CONTEXT_BOOKMARKSCREEN
,TIMEOUT_BLOCK
);
551 case ACTION_BMS_SELECT
:
552 /* User wants to use this bookmark */
553 action_signalscreenchange();
556 case ACTION_BMS_DELETE
:
557 /* User wants to delete this bookmark */
558 delete_bookmark(bookmark_file_name
, bookmark_id
);
561 if(bookmark_id
>= bookmark_count
)
562 bookmark_id
= bookmark_count
-1;
565 case ACTION_STD_PREV
:
566 case ACTION_STD_PREVREPEAT
:
570 case ACTION_STD_NEXT
:
571 case ACTION_STD_NEXTREPEAT
:
575 case ACTION_BMS_EXIT
:
576 action_signalscreenchange();
580 if(default_event_handler(key
) == SYS_USB_CONNECTED
)
582 action_signalscreenchange();
588 action_signalscreenchange();
593 /* ----------------------------------------------------------------------- */
594 /* This function takes a location in a bookmark file and deletes that */
596 /* ------------------------------------------------------------------------*/
597 static bool delete_bookmark(const char* bookmark_file_name
, int bookmark_id
)
599 int temp_bookmark_file
= 0;
600 int bookmark_file
= 0;
601 int bookmark_count
= 0;
603 /* Opening up a temp bookmark file */
604 snprintf(global_temp_buffer
, sizeof(global_temp_buffer
),
605 "%s.tmp", bookmark_file_name
);
606 temp_bookmark_file
= open(global_temp_buffer
,
607 O_WRONLY
| O_CREAT
| O_TRUNC
);
609 if (temp_bookmark_file
< 0)
610 return false; /* can't open the temp file */
612 /* Reading in the previous bookmarks and writing them to the temp file */
613 bookmark_file
= open(bookmark_file_name
, O_RDONLY
);
614 if (bookmark_file
>= 0)
616 while (read_line(bookmark_file
, global_read_buffer
,
617 sizeof(global_read_buffer
)) > 0)
619 if (bookmark_id
!= bookmark_count
)
621 write(temp_bookmark_file
, global_read_buffer
,
622 strlen(global_read_buffer
));
623 write(temp_bookmark_file
, "\n", 1);
627 close(bookmark_file
);
629 close(temp_bookmark_file
);
631 remove(bookmark_file_name
);
632 rename(global_temp_buffer
, bookmark_file_name
);
637 /* ----------------------------------------------------------------------- */
638 /* This function parses a bookmark and displays it for the user. */
639 /* ------------------------------------------------------------------------*/
640 static void display_bookmark(const char* bookmark
,
644 int resume_index
= 0;
647 bool playlist_shuffle
= false;
652 /* getting the index and the time into the file */
653 parse_bookmark(bookmark
,
654 &resume_index
, NULL
, NULL
, NULL
, NULL
, 0,
655 &ms
, &repeat_mode
, &playlist_shuffle
,
659 screens
[i
].clear_display();
661 #ifdef HAVE_LCD_BITMAP
662 /* bookmark shuffle and repeat states*/
665 #ifdef AB_REPEAT_ENABLE
667 statusbar_icon_play_mode(Icon_RepeatAB
);
672 statusbar_icon_play_mode(Icon_RepeatOne
);
676 statusbar_icon_play_mode(Icon_Repeat
);
680 statusbar_icon_shuffle();
683 dot
= strrchr(global_filename
, '.');
689 screens
[i
].puts_scroll(0, 0, (unsigned char *)global_filename
);
694 /* bookmark number */
695 snprintf(global_temp_buffer
, sizeof(global_temp_buffer
), "%s: %d/%d",
696 str(LANG_BOOKMARK_SELECT_BOOKMARK_TEXT
),
697 bookmark_id
+ 1, bookmark_count
);
699 screens
[i
].puts_scroll(0, 1, (unsigned char *)global_temp_buffer
);
701 /* bookmark resume index */
702 snprintf(global_temp_buffer
, sizeof(global_temp_buffer
), "%s: %d",
703 str(LANG_BOOKMARK_SELECT_INDEX_TEXT
), resume_index
+1);
705 screens
[i
].puts_scroll(0, 2, (unsigned char *)global_temp_buffer
);
708 format_time(time_buf
, sizeof(time_buf
), ms
);
709 snprintf(global_temp_buffer
, sizeof(global_temp_buffer
), "%s: %s",
710 str(LANG_BOOKMARK_SELECT_TIME_TEXT
), time_buf
);
712 screens
[i
].puts_scroll(0, 3, (unsigned char *)global_temp_buffer
);
717 screens
[i
].puts_scroll(0, 4, str(LANG_BOOKMARK_SELECT_PLAY
));
718 screens
[i
].puts_scroll(0, 5, str(LANG_BOOKMARK_SELECT_EXIT
));
719 screens
[i
].puts_scroll(0, 6, str(LANG_BOOKMARK_SELECT_DELETE
));
723 dot
= strrchr(global_filename
, '.');
728 format_time(time_buf
, sizeof(time_buf
), ms
);
729 snprintf(global_temp_buffer
, sizeof(global_temp_buffer
),
730 "%d/%d, %s, %s", (bookmark_id
+ 1), bookmark_count
,
731 time_buf
, global_filename
);
736 gui_syncstatusbar_draw(&statusbars
, false);
740 screens
[i
].puts_scroll(0,0,global_temp_buffer
);
741 screens
[i
].puts(0,1,str(LANG_RESUME_CONFIRM_PLAYER
));
747 /* ----------------------------------------------------------------------- */
748 /* This function parses a bookmark, says the voice UI part of it. */
749 /* ------------------------------------------------------------------------*/
750 static void say_bookmark(const char* bookmark
,
756 bool enqueue
= false; /* only the first voice is not queued */
758 parse_bookmark(bookmark
,
764 /* disabled, because transition between talkbox and voice UI clip is not nice */
766 if (global_settings
.talk_dir
>= 3)
767 { /* "talkbox" enabled */
768 char* last
= strrchr(dir
, '/');
770 { /* compose filename for talkbox */
771 strncpy(last
+ 1, dir_thumbnail_name
, sizeof(dir
)-(last
-dir
)-1);
772 talk_file(dir
, enqueue
);
777 talk_id(VOICE_EXT_BMARK
, enqueue
);
778 talk_number(bookmark_id
+ 1, true);
779 talk_id(LANG_BOOKMARK_SELECT_INDEX_TEXT
, true);
780 talk_number(resume_index
+ 1, true);
781 talk_id(LANG_BOOKMARK_SELECT_TIME_TEXT
, true);
783 talk_value(ms
/ 60000, UNIT_MIN
, true);
784 talk_value((ms
% 60000) / 1000, UNIT_SEC
, true);
787 /* ----------------------------------------------------------------------- */
788 /* This function parses a bookmark and then plays it. */
789 /* ------------------------------------------------------------------------*/
790 static bool play_bookmark(const char* bookmark
)
796 if (parse_bookmark(bookmark
,
802 sizeof(global_temp_buffer
),
804 &global_settings
.repeat_mode
,
805 &global_settings
.playlist_shuffle
,
808 bookmark_play(global_temp_buffer
, index
, offset
, seed
,
816 /* ----------------------------------------------------------------------- */
817 /* This function retrieves a given bookmark from a file. */
818 /* If the bookmark requested is beyond the number of bookmarks available */
819 /* in the file, it will return the last one. */
820 /* It also returns the index number of the bookmark in the file */
821 /* ------------------------------------------------------------------------*/
822 static char* get_bookmark(const char* bookmark_file
, int bookmark_count
)
826 int file
= open(bookmark_file
, O_RDONLY
);
831 /* Get the requested bookmark */
832 while (read_count
< bookmark_count
)
834 /*Reading in a single bookmark */
835 result
= read_line(file
,
837 sizeof(global_read_buffer
));
839 /* Reading past the last bookmark in the file
840 causes the loop to stop */
848 if ((read_count
>= 0) && (read_count
== bookmark_count
))
849 return global_read_buffer
;
854 static const char* skip_token(const char* s
)
856 while (*s
&& *s
!= ';')
869 static const char* int_token(const char* s
, int* dest
)
876 return skip_token(s
);
879 static const char* long_token(const char* s
, long* dest
)
883 *dest
= atoi(s
); /* Should be atol, but we don't have it. */
886 return skip_token(s
);
889 static const char* bool_token(const char* s
, bool* dest
)
893 *dest
= atoi(s
) != 0;
896 return skip_token(s
);
899 /* ----------------------------------------------------------------------- */
900 /* This function takes a bookmark and parses it. This function also */
901 /* validates the bookmark. Passing in NULL for an output variable */
902 /* indicates that value is not requested. */
903 /* ----------------------------------------------------------------------- */
904 static bool parse_bookmark(const char *bookmark
,
908 int *resume_first_index
,
910 unsigned int resume_file_size
,
912 int * repeat_mode
, bool *shuffle
,
915 const char* s
= bookmark
;
918 s
= int_token(s
, resume_index
);
919 s
= int_token(s
, resume_offset
);
920 s
= int_token(s
, resume_seed
);
921 s
= int_token(s
, resume_first_index
);
922 s
= long_token(s
, ms
);
923 s
= int_token(s
, repeat_mode
);
924 s
= bool_token(s
, shuffle
);
931 end
= strchr(s
, ';');
933 if (resume_file
!= NULL
)
935 size_t len
= (end
== NULL
) ? strlen(s
) : (size_t) (end
- s
);
937 len
= MIN(resume_file_size
- 1, len
);
938 strncpy(resume_file
, s
, len
);
939 resume_file
[len
] = 0;
942 if (end
!= NULL
&& file_name
!= NULL
)
945 strncpy(file_name
, end
, MAX_PATH
- 1);
946 file_name
[MAX_PATH
- 1] = 0;
952 /* ----------------------------------------------------------------------- */
953 /* This function is used by multiple functions and is used to generate a */
954 /* bookmark named based off of the input. */
955 /* Changing this function could result in how the bookmarks are stored. */
956 /* it would be here that the centralized/decentralized bookmark code */
957 /* could be placed. */
958 /* ----------------------------------------------------------------------- */
959 static bool generate_bookmark_file_name(const char *in
)
961 int len
= strlen(in
);
963 /* if this is a root dir MP3, rename the bookmark file root_dir.bmark */
964 /* otherwise, name it based on the in variable */
965 if (!strcmp("/", in
))
966 strcpy(global_bookmark_file_name
, "/root_dir.bmark");
969 strcpy(global_bookmark_file_name
, in
);
970 if(global_bookmark_file_name
[len
-1] == '/')
972 strcpy(&global_bookmark_file_name
[len
], ".bmark");
978 /* ----------------------------------------------------------------------- */
979 /* Returns true if a bookmark file exists for the current playlist */
980 /* ----------------------------------------------------------------------- */
981 bool bookmark_exist(void)
987 char* name
= playlist_get_name(NULL
, global_temp_buffer
,
988 sizeof(global_temp_buffer
));
989 if (generate_bookmark_file_name(name
))
991 int fd
=open(global_bookmark_file_name
, O_RDONLY
);
1003 /* ----------------------------------------------------------------------- */
1004 /* Checks the current state of the system and returns if it is in a */
1005 /* bookmarkable state. */
1006 /* ----------------------------------------------------------------------- */
1008 /* ----------------------------------------------------------------------- */
1010 /* return bool: Indicates if the system was in a bookmarkable state */
1011 /* ----------------------------------------------------------------------- */
1012 static bool system_check(void)
1014 int resume_index
= 0;
1015 struct mp3entry
*id3
= audio_current_track();
1019 /* no track playing */
1023 /* Checking to see if playing a queued track */
1024 if (playlist_get_resume_info(&resume_index
) == -1)
1026 /* something bad happened while getting the queue information */
1029 else if (playlist_modified(NULL
))
1031 /* can't bookmark while in the queue */