Update several codec Makefiles so that the codec libs build again on Coldfire targets...
[Rockbox.git] / apps / onplay.c
blob60a737938ff693ebfd34134e1dadfd8a8c1fbf26
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Björn Stenberg
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include <errno.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <stdbool.h>
25 #include "debug.h"
26 #include "sprintf.h"
27 #include "lcd.h"
28 #include "dir.h"
29 #include "file.h"
30 #include "audio.h"
31 #include "menu.h"
32 #include "lang.h"
33 #include "playlist.h"
34 #include "button.h"
35 #include "kernel.h"
36 #include "keyboard.h"
37 #include "mp3data.h"
38 #include "id3.h"
39 #include "screens.h"
40 #include "tree.h"
41 #include "buffer.h"
42 #include "settings.h"
43 #include "statusbar.h"
44 #include "playlist_viewer.h"
45 #include "talk.h"
46 #include "onplay.h"
47 #include "filetypes.h"
48 #include "plugin.h"
49 #include "bookmark.h"
50 #include "action.h"
51 #include "splash.h"
52 #include "yesno.h"
53 #ifdef HAVE_LCD_COLOR
54 #include "backdrop.h"
55 #endif
56 #ifdef HAVE_LCD_BITMAP
57 #include "icons.h"
58 #endif
59 #include "main_menu.h"
60 #include "sound_menu.h"
61 #include "database.h"
62 #if CONFIG_CODEC == SWCODEC
63 #include "eq_menu.h"
64 #endif
65 #include "playlist_menu.h"
66 #include "playlist_catalog.h"
67 #ifdef HAVE_TAGCACHE
68 #include "tagtree.h"
69 #endif
71 static int context;
72 static char* selected_file = NULL;
73 static int selected_file_attr = 0;
74 static int onplay_result = ONPLAY_OK;
75 static char clipboard_selection[MAX_PATH];
76 static int clipboard_selection_attr = 0;
77 static bool clipboard_is_copy = false;
79 /* For playlist options */
80 struct playlist_args {
81 int position;
82 bool queue;
85 /* ----------------------------------------------------------------------- */
86 /* Displays the bookmark menu options for the user to decide. This is an */
87 /* interface function. */
88 /* ----------------------------------------------------------------------- */
89 bool bookmark_menu(void)
91 int i,m;
92 bool result;
93 struct menu_item items[3];
95 i=0;
97 if ((audio_status() & AUDIO_STATUS_PLAY))
99 items[i].desc = ID2P(LANG_BOOKMARK_MENU_CREATE);
100 items[i].function = bookmark_create_menu;
101 i++;
103 if (bookmark_exist())
105 items[i].desc = ID2P(LANG_BOOKMARK_MENU_LIST);
106 items[i].function = bookmark_load_menu;
107 i++;
111 m=menu_init( items, i, NULL, NULL, NULL, NULL );
113 #ifdef HAVE_LCD_CHARCELLS
114 status_set_param(true);
115 #endif
116 result = menu_run(m);
117 #ifdef HAVE_LCD_CHARCELLS
118 status_set_param(false);
119 #endif
120 menu_exit(m);
122 settings_save();
124 return result;
127 static bool list_viewers(void)
129 struct menu_item menu[16];
130 int m, i, result;
131 int ret = 0;
133 i=filetype_load_menu(menu,sizeof(menu)/sizeof(*menu));
134 if (i)
136 m = menu_init( menu, i, NULL, NULL, NULL, NULL );
137 result = menu_show(m);
138 menu_exit(m);
139 if (result >= 0)
140 ret = filetype_load_plugin((char *)menu[result].desc,selected_file);
142 else
144 /* FIX: translation! */
145 gui_syncsplash(HZ*2, true, (unsigned char *)"No viewers found");
148 if (ret == PLUGIN_USB_CONNECTED)
149 onplay_result = ONPLAY_RELOAD_DIR;
151 return false;
154 static bool shuffle_playlist(void)
156 playlist_sort(NULL, true);
157 playlist_randomise(NULL, current_tick, true);
159 return false;
162 static bool save_playlist(void)
164 save_playlist_screen(NULL);
165 return false;
168 static bool add_to_playlist(int position, bool queue)
170 bool new_playlist = !(audio_status() & AUDIO_STATUS_PLAY);
171 char *lines[] = {
172 (char *)str(LANG_RECURSE_DIRECTORY_QUESTION),
173 selected_file
175 struct text_message message={lines, 2};
177 gui_syncsplash(0, true, str(LANG_WAIT));
179 if (new_playlist)
180 playlist_create(NULL, NULL);
182 /* always set seed before inserting shuffled */
183 if (position == PLAYLIST_INSERT_SHUFFLED)
184 srand(current_tick);
186 #ifdef HAVE_TAGCACHE
187 if (context == CONTEXT_ID3DB)
189 tagtree_insert_selection_playlist(position, queue);
191 else
192 #endif
194 if ((selected_file_attr & TREE_ATTR_MASK) == TREE_ATTR_MPA)
195 playlist_insert_track(NULL, selected_file, position, queue, true);
196 else if (selected_file_attr & ATTR_DIRECTORY)
198 bool recurse = false;
200 if (global_settings.recursive_dir_insert != RECURSE_ASK)
201 recurse = (bool)global_settings.recursive_dir_insert;
202 else
204 /* Ask if user wants to recurse directory */
205 recurse = (gui_syncyesno_run(&message, NULL, NULL)==YESNO_YES);
208 playlist_insert_directory(NULL, selected_file, position, queue,
209 recurse);
211 else if ((selected_file_attr & TREE_ATTR_MASK) == TREE_ATTR_M3U)
212 playlist_insert_playlist(NULL, selected_file, position, queue);
215 if (new_playlist && (playlist_amount() > 0))
217 /* nothing is currently playing so begin playing what we just
218 inserted */
219 if (global_settings.playlist_shuffle)
220 playlist_shuffle(current_tick, -1);
221 playlist_start(0,0);
222 gui_syncstatusbar_draw(&statusbars, false);
223 onplay_result = ONPLAY_START_PLAY;
226 return false;
229 static bool view_playlist(void)
231 bool was_playing = audio_status() & AUDIO_STATUS_PLAY;
232 bool result;
234 result = playlist_viewer_ex(selected_file);
236 if (!was_playing && (audio_status() & AUDIO_STATUS_PLAY) &&
237 onplay_result == ONPLAY_OK)
238 /* playlist was started from viewer */
239 onplay_result = ONPLAY_START_PLAY;
241 return result;
244 bool cat_add_to_a_playlist(void)
246 return catalog_add_to_a_playlist(selected_file, selected_file_attr,
247 false);
250 bool cat_add_to_a_new_playlist(void)
252 return catalog_add_to_a_playlist(selected_file, selected_file_attr, true);
255 static bool cat_playlist_options(void)
257 struct menu_item items[3];
258 int m, i=0, result;
259 bool ret = false;
261 if ((audio_status() & AUDIO_STATUS_PLAY && context == CONTEXT_WPS) ||
262 context == CONTEXT_TREE)
264 if (context == CONTEXT_WPS)
266 items[i].desc = ID2P(LANG_CATALOG_VIEW);
267 items[i].function = catalog_view_playlists;
268 i++;
271 items[i].desc = ID2P(LANG_CATALOG_ADD_TO);
272 items[i].function = cat_add_to_a_playlist;
273 i++;
274 items[i].desc = ID2P(LANG_CATALOG_ADD_TO_NEW);
275 items[i].function = cat_add_to_a_new_playlist;
276 i++;
279 m = menu_init( items, i, NULL, NULL, NULL, NULL );
280 result = menu_show(m);
281 if(result >= 0)
282 ret = items[result].function();
283 menu_exit(m);
285 return ret;
288 /* Sub-menu for playlist options */
289 static bool playlist_options(void)
291 struct menu_item items[13];
292 struct playlist_args args[13]; /* increase these 2 if you add entries! */
293 int m, i=0, pstart=0, result;
294 bool ret = false;
296 if ((selected_file_attr & TREE_ATTR_MASK) == TREE_ATTR_M3U &&
297 context == CONTEXT_TREE)
299 items[i].desc = ID2P(LANG_VIEW);
300 items[i].function = view_playlist;
301 i++;
302 pstart++;
305 if (audio_status() & AUDIO_STATUS_PLAY &&
306 context == CONTEXT_WPS)
308 items[i].desc = ID2P(LANG_VIEW_DYNAMIC_PLAYLIST);
309 items[i].function = playlist_viewer;
310 i++;
311 pstart++;
313 items[i].desc = ID2P(LANG_SEARCH_IN_PLAYLIST);
314 items[i].function = search_playlist;
315 i++;
316 pstart++;
318 items[i].desc = ID2P(LANG_SAVE_DYNAMIC_PLAYLIST);
319 items[i].function = save_playlist;
320 i++;
321 pstart++;
323 items[i].desc = ID2P(LANG_SHUFFLE_PLAYLIST);
324 items[i].function = shuffle_playlist;
325 i++;
326 pstart++;
329 if (context == CONTEXT_TREE || context == CONTEXT_ID3DB)
331 if (audio_status() & AUDIO_STATUS_PLAY)
333 items[i].desc = ID2P(LANG_INSERT);
334 args[i].position = PLAYLIST_INSERT;
335 args[i].queue = false;
336 i++;
338 items[i].desc = ID2P(LANG_INSERT_FIRST);
339 args[i].position = PLAYLIST_INSERT_FIRST;
340 args[i].queue = false;
341 i++;
343 items[i].desc = ID2P(LANG_INSERT_LAST);
344 args[i].position = PLAYLIST_INSERT_LAST;
345 args[i].queue = false;
346 i++;
348 items[i].desc = ID2P(LANG_INSERT_SHUFFLED);
349 args[i].position = PLAYLIST_INSERT_SHUFFLED;
350 args[i].queue = false;
351 i++;
353 items[i].desc = ID2P(LANG_QUEUE);
354 args[i].position = PLAYLIST_INSERT;
355 args[i].queue = true;
356 i++;
358 items[i].desc = ID2P(LANG_QUEUE_FIRST);
359 args[i].position = PLAYLIST_INSERT_FIRST;
360 args[i].queue = true;
361 i++;
363 items[i].desc = ID2P(LANG_QUEUE_LAST);
364 args[i].position = PLAYLIST_INSERT_LAST;
365 args[i].queue = true;
366 i++;
368 items[i].desc = ID2P(LANG_QUEUE_SHUFFLED);
369 args[i].position = PLAYLIST_INSERT_SHUFFLED;
370 args[i].queue = true;
371 i++;
373 else if (((selected_file_attr & TREE_ATTR_MASK) == TREE_ATTR_MPA) ||
374 (selected_file_attr & ATTR_DIRECTORY))
376 items[i].desc = ID2P(LANG_INSERT);
377 args[i].position = PLAYLIST_INSERT_LAST;
378 args[i].queue = false;
379 i++;
381 if (selected_file_attr & ATTR_DIRECTORY)
383 items[i].desc = ID2P(LANG_INSERT_SHUFFLED);
384 args[i].position = PLAYLIST_INSERT_SHUFFLED;
385 args[i].queue = false;
386 i++;
391 m = menu_init( items, i, NULL, NULL, NULL, NULL );
392 result = menu_show(m);
393 if (result >= 0 && result < pstart)
394 ret = items[result].function();
395 else if (result >= pstart)
396 ret = add_to_playlist(args[result].position, args[result].queue);
397 menu_exit(m);
399 return ret;
403 /* helper function to remove a non-empty directory */
404 static int remove_dir(char* dirname, int len)
406 int result = 0;
407 DIR* dir;
408 int dirlen = strlen(dirname);
410 dir = opendir(dirname);
411 if (!dir)
412 return -1; /* open error */
414 while(true)
416 struct dirent* entry;
417 /* walk through the directory content */
418 entry = readdir(dir);
419 if (!entry)
420 break;
422 /* append name to current directory */
423 snprintf(dirname+dirlen, len-dirlen, "/%s", entry->d_name);
425 if (entry->attribute & ATTR_DIRECTORY)
426 { /* remove a subdirectory */
427 if (!strcmp((char *)entry->d_name, ".") ||
428 !strcmp((char *)entry->d_name, ".."))
429 continue; /* skip these */
431 result = remove_dir(dirname, len); /* recursion */
432 if (result)
433 break; /* or better continue, delete what we can? */
435 else
436 { /* remove a file */
437 result = remove(dirname);
440 closedir(dir);
442 if (!result)
443 { /* remove the now empty directory */
444 dirname[dirlen] = '\0'; /* terminate to original length */
446 result = rmdir(dirname);
449 return result;
453 /* share code for file and directory deletion, saves space */
454 static bool delete_handler(bool is_dir)
456 char *lines[]={
457 (char *)str(LANG_REALLY_DELETE),
458 selected_file
460 char *yes_lines[]={
461 (char *)str(LANG_DELETED),
462 selected_file
465 struct text_message message={lines, 2};
466 struct text_message yes_message={yes_lines, 2};
467 if(gui_syncyesno_run(&message, &yes_message, NULL)!=YESNO_YES)
468 return false;
469 int res;
470 if (is_dir)
472 char pathname[MAX_PATH]; /* space to go deep */
473 strncpy(pathname, selected_file, sizeof pathname);
474 res = remove_dir(pathname, sizeof(pathname));
476 else
477 res = remove(selected_file);
479 if (!res) {
480 onplay_result = ONPLAY_RELOAD_DIR;
482 return false;
486 static bool delete_file(void)
488 return delete_handler(false);
491 static bool delete_dir(void)
493 return delete_handler(true);
496 #ifdef HAVE_LCD_COLOR
497 static bool set_backdrop(void)
499 /* load the image */
500 if(load_main_backdrop(selected_file)) {
501 gui_syncsplash(HZ, true, str(LANG_BACKDROP_LOADED));
502 set_file(selected_file, (char *)global_settings.backdrop_file, MAX_FILENAME);
503 show_main_backdrop();
504 return true;
505 } else {
506 gui_syncsplash(HZ, true, str(LANG_BACKDROP_FAILED));
507 return false;
510 #endif
512 static bool rename_file(void)
514 char newname[MAX_PATH];
515 char* ptr = strrchr(selected_file, '/') + 1;
516 int pathlen = (ptr - selected_file);
517 strncpy(newname, selected_file, sizeof newname);
518 if (!kbd_input(newname + pathlen, (sizeof newname)-pathlen)) {
519 if (!strlen(newname + pathlen) ||
520 (rename(selected_file, newname) < 0)) {
521 lcd_clear_display();
522 lcd_puts(0,0,str(LANG_RENAME));
523 lcd_puts(0,1,str(LANG_FAILED));
524 lcd_update();
525 sleep(HZ*2);
527 else
528 onplay_result = ONPLAY_RELOAD_DIR;
531 return false;
534 bool create_dir(void)
536 char dirname[MAX_PATH];
537 char *cwd;
538 int rc;
539 int pathlen;
541 cwd = getcwd(NULL, 0);
542 memset(dirname, 0, sizeof dirname);
544 snprintf(dirname, sizeof dirname, "%s/",
545 cwd[1] ? cwd : "");
547 pathlen = strlen(dirname);
548 rc = kbd_input(dirname + pathlen, (sizeof dirname)-pathlen);
549 if (rc < 0)
550 return false;
552 rc = mkdir(dirname, 0);
553 if (rc < 0) {
554 gui_syncsplash(HZ, true, (unsigned char *)"%s %s",
555 str(LANG_CREATE_DIR), str(LANG_FAILED));
556 } else {
557 onplay_result = ONPLAY_RELOAD_DIR;
560 return true;
563 /* Store the current selection in the clipboard */
564 static bool clipboard_clip(bool copy)
566 clipboard_selection[0] = 0;
567 strncpy(clipboard_selection, selected_file, MAX_PATH);
568 clipboard_selection_attr = selected_file_attr;
569 clipboard_is_copy = copy;
571 return true;
574 static bool clipboard_cut(void)
576 return clipboard_clip(false);
579 static bool clipboard_copy(void)
581 return clipboard_clip(true);
584 /* Paste a file to a new directory. Will overwrite always. */
585 static bool clipboard_pastefile(const char *src, const char *target, bool copy)
587 int src_fd, target_fd, buffersize, size, bytesread, byteswritten;
588 char *buffer;
589 bool result = false;
591 if (copy) {
592 /* See if we can get the plugin buffer for the file copy buffer */
593 buffer = (char *) plugin_get_buffer(&buffersize);
594 if (buffer == NULL || buffersize < 512) {
595 /* Not large enough, try for a disk sector worth of stack instead */
596 buffersize = 512;
597 buffer = (char *) __builtin_alloca(buffersize);
600 if (buffer == NULL) {
601 return false;
604 buffersize &= ~0x1ff; /* Round buffer size to multiple of sector size */
606 src_fd = open(src, O_RDONLY);
608 if (src_fd >= 0) {
609 target_fd = creat(target, O_WRONLY);
611 if (target_fd >= 0) {
612 result = true;
614 size = filesize(src_fd);
616 if (size == -1) {
617 result = false;
620 while(size > 0) {
621 bytesread = read(src_fd, buffer, buffersize);
623 if (bytesread == -1) {
624 result = false;
625 break;
628 size -= bytesread;
630 while(bytesread > 0) {
631 byteswritten = write(target_fd, buffer, bytesread);
633 if (byteswritten == -1) {
634 result = false;
635 size = 0;
636 break;
639 bytesread -= byteswritten;
643 close(target_fd);
645 /* Copy failed. Cleanup. */
646 if (!result) {
647 remove(target);
651 close(src_fd);
653 } else {
654 result = rename(src, target) == 0;
655 #ifdef HAVE_MULTIVOLUME
656 if (!result) {
657 if (errno == EXDEV) {
658 /* Failed because cross volume rename doesn't work. Copy instead */
659 result = clipboard_pastefile(src, target, true);
661 if (result) {
662 result = remove(src);
666 #endif
669 return result;
672 /* Paste a directory to a new location. Designed to be called by clipboard_paste */
673 static bool clipboard_pastedirectory(char *src, int srclen, char *target, int targetlen, bool copy)
675 DIR *srcdir;
676 int srcdirlen = strlen(src);
677 int targetdirlen = strlen(target);
678 int fd;
679 bool result = true;
681 /* Check if the target exists */
682 fd = open(target, O_RDONLY);
683 close(fd);
685 if (fd < 0) {
686 if (!copy) {
687 /* Just move the directory */
688 result = rename(src, target) == 0;
690 #ifdef HAVE_MULTIVOLUME
691 if (!result && errno == EXDEV) {
692 /* Try a copy as we're going across devices */
693 result = clipboard_pastedirectory(src, srclen, target, targetlen, true);
695 /* If it worked, remove the source directory */
696 if (result) {
697 remove_dir(src, srclen);
700 #endif
701 return result;
702 } else {
703 /* Make a directory to copy things to */
704 result = mkdir(target, 0) == 0;
708 /* Check if something went wrong already */
709 if (!result) {
710 return result;
713 srcdir = opendir(src);
714 if (!srcdir) {
715 return false;
718 /* This loop will exit as soon as there's a problem */
719 while(result)
721 struct dirent* entry;
722 /* walk through the directory content */
723 entry = readdir(srcdir);
724 if (!entry)
725 break;
727 /* append name to current directory */
728 snprintf(src+srcdirlen, srclen-srcdirlen, "/%s", entry->d_name);
729 snprintf(target+targetdirlen, targetlen-targetdirlen, "/%s", entry->d_name);
731 DEBUGF("Copy %s to %s\n", src, target);
733 if (entry->attribute & ATTR_DIRECTORY)
734 { /* copy/move a subdirectory */
735 if (!strcmp((char *)entry->d_name, ".") ||
736 !strcmp((char *)entry->d_name, ".."))
737 continue; /* skip these */
739 result = clipboard_pastedirectory(src, srclen, target, targetlen, copy); /* recursion */
741 else
742 { /* copy/move a file */
743 result = clipboard_pastefile(src, target, copy);
747 closedir(srcdir);
749 if (result) {
750 src[srcdirlen] = '\0'; /* terminate to original length */
751 target[targetdirlen] = '\0'; /* terminate to original length */
754 return result;
757 /* Paste the clipboard to the current directory */
758 static bool clipboard_paste(void)
760 char target[MAX_PATH];
761 char *cwd, *nameptr;
762 bool success;
763 int target_fd;
765 unsigned char *lines[]={str(LANG_REALLY_OVERWRITE)};
766 struct text_message message={(char **)lines, 1};
768 /* Get the name of the current directory */
769 cwd = getcwd(NULL, 0);
770 snprintf(target, sizeof target, "%s", cwd[1] ? cwd : "");
772 /* Figure out the name of the selection */
773 nameptr = strrchr(clipboard_selection, '/');
775 /* Paste the name on to the current directory to give us our final target */
776 strcat(target, nameptr);
778 /* Check if we're going to overwrite */
779 target_fd = open(target, O_RDONLY);
780 close(target_fd);
782 /* If the target existed but they choose not to overwite, exit */
783 if (target_fd >= 0 &&
784 (gui_syncyesno_run(&message, NULL, NULL) == YESNO_NO)) {
785 return false;
788 /* Now figure out what we're doing */
789 if (clipboard_selection_attr & ATTR_DIRECTORY) {
790 /* Recursion. Set up external stack */
791 char srcpath[MAX_PATH];
792 char targetpath[MAX_PATH];
794 strncpy(srcpath, clipboard_selection, sizeof srcpath);
795 strncpy(targetpath, target, sizeof targetpath);
797 success = clipboard_pastedirectory(srcpath, sizeof(srcpath), target, sizeof(targetpath), clipboard_is_copy);
798 } else {
799 success = clipboard_pastefile(clipboard_selection, target, clipboard_is_copy);
802 /* Did it work? */
803 if (success) {
804 /* Reset everything */
805 clipboard_selection[0] = 0;
806 clipboard_selection_attr = 0;
807 clipboard_is_copy = false;
809 /* Force reload of the current directory */
810 onplay_result = ONPLAY_RELOAD_DIR;
811 } else {
812 gui_syncsplash(HZ, true, (unsigned char *)"%s %s",
813 str(LANG_PASTE), str(LANG_FAILED));
816 return true;
819 static bool exit_to_main;
821 /* catch MENU_EXIT_MENU within context menu to call the main menu afterwards */
822 static int onplay_callback(int key, int menu)
824 (void)menu;
826 if (key == ACTION_STD_MENU)
827 exit_to_main = true;
829 return key;
832 int onplay(char* file, int attr, int from)
834 #if CONFIG_CODEC == SWCODEC
835 struct menu_item items[14]; /* increase this if you add entries! */
836 #else
837 struct menu_item items[12];
838 #endif
839 int m, i=0, result;
840 #ifdef HAVE_LCD_COLOR
841 char *suffix;
842 #endif
844 onplay_result = ONPLAY_OK;
845 context=from;
846 exit_to_main = false;
847 selected_file = file;
848 selected_file_attr = attr;
850 if (context == CONTEXT_WPS)
852 items[i].desc = ID2P(LANG_SOUND_SETTINGS);
853 items[i].function = sound_menu;
854 i++;
857 if (context == CONTEXT_WPS ||
858 context == CONTEXT_TREE ||
859 context == CONTEXT_ID3DB)
861 items[i].desc = ID2P(LANG_PLAYLIST);
862 items[i].function = playlist_options;
863 i++;
864 items[i].desc = ID2P(LANG_CATALOG);
865 items[i].function = cat_playlist_options;
866 i++;
869 if (context == CONTEXT_WPS)
871 items[i].desc = ID2P(LANG_BOOKMARK_MENU);
872 items[i].function = bookmark_menu;
873 i++;
876 if (file)
878 if (context == CONTEXT_WPS)
880 items[i].desc = ID2P(LANG_MENU_SHOW_ID3_INFO);
881 items[i].function = browse_id3;
882 i++;
883 /* if(rundb_initialized)
885 items[i].desc = ID2P(LANG_MENU_SET_RATING);
886 items[i].function = set_rating;
887 i++;
891 #ifdef HAVE_MULTIVOLUME
892 if (!(attr & ATTR_VOLUME)) /* no rename+delete for volumes */
893 #endif
895 if (context == CONTEXT_TREE)
897 items[i].desc = ID2P(LANG_RENAME);
898 items[i].function = rename_file;
899 i++;
901 items[i].desc = ID2P(LANG_CUT);
902 items[i].function = clipboard_cut;
903 i++;
905 items[i].desc = ID2P(LANG_COPY);
906 items[i].function = clipboard_copy;
907 i++;
909 if (clipboard_selection[0] != 0) /* Something in the clipboard? */
911 items[i].desc = ID2P(LANG_PASTE);
912 items[i].function = clipboard_paste;
913 i++;
917 if (!(attr & ATTR_DIRECTORY) && context == CONTEXT_TREE)
919 items[i].desc = ID2P(LANG_DELETE);
920 items[i].function = delete_file;
921 i++;
923 #ifdef HAVE_LCD_COLOR
924 suffix = strrchr(file, '.');
925 if (suffix)
927 if (strcasecmp(suffix, ".bmp") == 0)
929 items[i].desc = ID2P(LANG_SET_AS_BACKDROP);
930 items[i].function = set_backdrop;
931 i++;
934 #endif
936 else
938 if (context == CONTEXT_TREE)
940 items[i].desc = ID2P(LANG_DELETE_DIR);
941 items[i].function = delete_dir;
942 i++;
947 if (!(attr & ATTR_DIRECTORY))
949 items[i].desc = ID2P(LANG_ONPLAY_OPEN_WITH);
950 items[i].function = list_viewers;
951 i++;
954 else
956 if (strlen(clipboard_selection) != 0)
958 items[i].desc = ID2P(LANG_PASTE);
959 items[i].function = clipboard_paste;
960 i++;
964 if (context == CONTEXT_TREE)
966 items[i].desc = ID2P(LANG_CREATE_DIR);
967 items[i].function = create_dir;
968 i++;
970 if (context == CONTEXT_WPS)
972 #ifdef HAVE_PITCHSCREEN
973 /* Pitch screen access */
974 items[i].desc = ID2P(LANG_PITCH);
975 items[i].function = pitch_screen;
976 i++;
977 #endif
978 #if CONFIG_CODEC == SWCODEC
979 /* Equalizer menu items */
980 items[i].desc = ID2P(LANG_EQUALIZER_GRAPHICAL);
981 items[i].function = eq_menu_graphical;
982 i++;
983 items[i].desc = ID2P(LANG_EQUALIZER_BROWSE);
984 items[i].function = eq_browse_presets;
985 i++;
986 #endif
989 /* DIY menu handling, since we want to exit after selection */
990 if (i)
992 m = menu_init( items, i, onplay_callback, NULL, NULL, NULL );
993 result = menu_show(m);
994 if (result >= 0)
995 items[result].function();
996 menu_exit(m);
998 if (exit_to_main)
999 result = main_menu();
1001 #ifdef HAVE_LCD_BITMAP
1002 if (global_settings.statusbar)
1003 lcd_setmargins(0, STATUSBAR_HEIGHT);
1004 else
1005 lcd_setmargins(0, 0);
1006 #endif
1009 return onplay_result;