summaryrefslogtreecommitdiff
path: root/apps/onplay.c
diff options
context:
space:
mode:
authorDan Everton <dan@iocaine.org>2006-03-20 11:46:06 +0000
committerDan Everton <dan@iocaine.org>2006-03-20 11:46:06 +0000
commit1429c9b86332bbc027aee1f2abb1c1de18c0f972 (patch)
tree353ce487570d4408ddf80c861d8c771acdf63d0e /apps/onplay.c
parenta836b27dfb93bde01d7cc4ab94393a4ac62c331d (diff)
downloadrockbox-1429c9b86332bbc027aee1f2abb1c1de18c0f972.tar.gz
rockbox-1429c9b86332bbc027aee1f2abb1c1de18c0f972.zip
Add 'clipboard' type functionality to onplay menu. You can cut/copy/paste directories and files. Works across volumes. No multiselect support though.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9132 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/onplay.c')
-rw-r--r--apps/onplay.c299
1 files changed, 293 insertions, 6 deletions
diff --git a/apps/onplay.c b/apps/onplay.c
index e057623c1c..62ba0a1005 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -16,6 +16,7 @@
16 * KIND, either express or implied. 16 * KIND, either express or implied.
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19#include <errno.h>
19#include <stdio.h> 20#include <stdio.h>
20#include <string.h> 21#include <string.h>
21#include <stdlib.h> 22#include <stdlib.h>
@@ -67,6 +68,9 @@ static int context;
67static char* selected_file = NULL; 68static char* selected_file = NULL;
68static int selected_file_attr = 0; 69static int selected_file_attr = 0;
69static int onplay_result = ONPLAY_OK; 70static int onplay_result = ONPLAY_OK;
71static char clipboard_selection[MAX_PATH];
72static int clipboard_selection_attr = 0;
73static bool clipboard_is_copy = false;
70 74
71/* For playlist options */ 75/* For playlist options */
72struct playlist_args { 76struct playlist_args {
@@ -516,6 +520,262 @@ bool create_dir(void)
516 return true; 520 return true;
517} 521}
518 522
523/* Store the current selection in the clipboard */
524static bool clipboard_clip(bool copy)
525{
526 clipboard_selection[0] = 0;
527 strncpy(clipboard_selection, selected_file, MAX_PATH);
528 clipboard_selection_attr = selected_file_attr;
529 clipboard_is_copy = copy;
530
531 return true;
532}
533
534static bool clipboard_cut(void)
535{
536 return clipboard_clip(false);
537}
538
539static bool clipboard_copy(void)
540{
541 return clipboard_clip(true);
542}
543
544/* Paste a file to a new directory. Will overwrite always. */
545static bool clipboard_pastefile(const char *src, const char *target, bool copy)
546{
547 int src_fd, target_fd, buffersize, size, bytesread, byteswritten;
548 char *buffer;
549 bool result = false;
550
551 if (copy) {
552 /* See if we can get the plugin buffer for the file copy buffer */
553 buffer = (char *) plugin_get_buffer(&buffersize);
554 if (buffer == NULL || buffersize < 512) {
555 /* Not large enough, try for a disk sector worth of stack instead */
556 buffersize = 512;
557 buffer = (char *) __builtin_alloca(buffersize);
558 }
559
560 if (buffer == NULL) {
561 return false;
562 }
563
564 buffersize &= ~0x1ff; /* Round buffer size to multiple of sector size */
565
566 src_fd = open(src, O_RDONLY);
567
568 if (src_fd >= 0) {
569 target_fd = creat(target, O_WRONLY);
570
571 if (target_fd >= 0) {
572 result = true;
573
574 size = filesize(src_fd);
575
576 if (size == -1) {
577 result = false;
578 }
579
580 while(size > 0) {
581 bytesread = read(src_fd, buffer, buffersize);
582
583 if (bytesread == -1) {
584 result = false;
585 break;
586 }
587
588 size -= bytesread;
589
590 while(bytesread > 0) {
591 byteswritten = write(target_fd, buffer, bytesread);
592
593 if (byteswritten == -1) {
594 result = false;
595 size = 0;
596 break;
597 }
598
599 bytesread -= byteswritten;
600 }
601 }
602
603 close(target_fd);
604
605 /* Copy failed. Cleanup. */
606 if (!result) {
607 remove(target);
608 }
609 }
610
611 close(src_fd);
612 }
613 } else {
614 result = rename(src, target) == 0;
615#ifdef HAVE_MULTIVOLUME
616 if (!result) {
617 if (errno == EXDEV) {
618 /* Failed because cross volume rename doesn't work. Copy instead */
619 result = clipboard_pastefile(src, target, true);
620
621 if (result) {
622 result = remove(src);
623 }
624 }
625 }
626#endif
627 }
628
629 return result;
630}
631
632/* Paste a directory to a new location. Designed to be called by clipboard_paste */
633static bool clipboard_pastedirectory(char *src, int srclen, char *target, int targetlen, bool copy)
634{
635 DIR *srcdir;
636 int srcdirlen = strlen(src);
637 int targetdirlen = strlen(target);
638 int fd;
639 bool result = true;
640
641 /* Check if the target exists */
642 fd = open(target, O_RDONLY);
643 close(fd);
644
645 if (fd < 0) {
646 if (!copy) {
647 /* Just move the directory */
648 result = rename(src, target) == 0;
649
650#ifdef HAVE_MULTIVOLUME
651 if (!result && errno == EXDEV) {
652 /* Try a copy as we're going across devices */
653 result = clipboard_pastedirectory(src, srclen, target, targetlen, true);
654
655 /* If it worked, remove the source directory */
656 if (result) {
657 remove_dir(src, srclen);
658 }
659 }
660#endif
661 return result;
662 } else {
663 /* Make a directory to copy things to */
664 result = mkdir(target, 0) == 0;
665 }
666 }
667
668 /* Check if something went wrong already */
669 if (!result) {
670 return result;
671 }
672
673 srcdir = opendir(src);
674 if (!srcdir) {
675 return false;
676 }
677
678 /* This loop will exit as soon as there's a problem */
679 while(result)
680 {
681 struct dirent* entry;
682 /* walk through the directory content */
683 entry = readdir(srcdir);
684 if (!entry)
685 break;
686
687 /* append name to current directory */
688 snprintf(src+srcdirlen, srclen-srcdirlen, "/%s", entry->d_name);
689 snprintf(target+targetdirlen, targetlen-targetdirlen, "/%s", entry->d_name);
690
691 DEBUGF("Copy %s to %s\n", src, target);
692
693 if (entry->attribute & ATTR_DIRECTORY)
694 { /* copy/move a subdirectory */
695 if (!strcmp((char *)entry->d_name, ".") ||
696 !strcmp((char *)entry->d_name, ".."))
697 continue; /* skip these */
698
699 result = clipboard_pastedirectory(src, srclen, target, targetlen, copy); /* recursion */
700 }
701 else
702 { /* copy/move a file */
703 result = clipboard_pastefile(src, target, copy);
704 }
705 }
706
707 closedir(srcdir);
708
709 if (result) {
710 src[srcdirlen] = '\0'; /* terminate to original length */
711 target[targetdirlen] = '\0'; /* terminate to original length */
712 }
713
714 return result;
715}
716
717/* Paste the clipboard to the current directory */
718static bool clipboard_paste(void)
719{
720 char target[MAX_PATH];
721 char *cwd, *nameptr;
722 bool success;
723 int target_fd;
724
725 unsigned char *lines[]={str(LANG_REALLY_OVERWRITE)};
726 struct text_message message={(char **)lines, 1};
727
728 /* Get the name of the current directory */
729 cwd = getcwd(NULL, 0);
730 snprintf(target, sizeof target, "%s", cwd[1] ? cwd : "");
731
732 /* Figure out the name of the selection */
733 nameptr = strrchr(clipboard_selection, '/');
734
735 /* Paste the name on to the current directory to give us our final target */
736 strcat(target, nameptr);
737
738 /* Check if we're going to overwrite */
739 target_fd = open(target, O_RDONLY);
740 close(target_fd);
741
742 /* If the target existed but they choose not to overwite, exit */
743 if (target_fd >= 0 &&
744 (gui_syncyesno_run(&message, NULL, NULL) == YESNO_NO)) {
745 return false;
746 }
747
748 /* Now figure out what we're doing */
749 if (clipboard_selection_attr & ATTR_DIRECTORY) {
750 /* Recursion. Set up external stack */
751 char srcpath[MAX_PATH];
752 char targetpath[MAX_PATH];
753
754 strncpy(srcpath, clipboard_selection, sizeof srcpath);
755 strncpy(targetpath, target, sizeof targetpath);
756
757 success = clipboard_pastedirectory(srcpath, sizeof(srcpath), target, sizeof(targetpath), clipboard_is_copy);
758 } else {
759 success = clipboard_pastefile(clipboard_selection, target, clipboard_is_copy);
760 }
761
762 /* Did it work? */
763 if (success) {
764 /* Reset everything */
765 clipboard_selection[0] = 0;
766 clipboard_selection_attr = 0;
767 clipboard_is_copy = false;
768
769 /* Force reload of the current directory */
770 onplay_result = ONPLAY_RELOAD_DIR;
771 } else {
772 gui_syncsplash(HZ, true, (unsigned char *)"%s %s",
773 str(LANG_PASTE), str(LANG_FAILED));
774 }
775
776 return true;
777}
778
519static bool exit_to_main; 779static bool exit_to_main;
520 780
521/* catch MENU_EXIT_MENU within context menu to call the main menu afterwards */ 781/* catch MENU_EXIT_MENU within context menu to call the main menu afterwards */
@@ -536,9 +796,9 @@ static int onplay_callback(int key, int menu)
536int onplay(char* file, int attr, int from) 796int onplay(char* file, int attr, int from)
537{ 797{
538#if CONFIG_CODEC == SWCODEC 798#if CONFIG_CODEC == SWCODEC
539 struct menu_item items[10]; /* increase this if you add entries! */ 799 struct menu_item items[13]; /* increase this if you add entries! */
540#else 800#else
541 struct menu_item items[8]; 801 struct menu_item items[11];
542#endif 802#endif
543 int m, i=0, result; 803 int m, i=0, result;
544#ifdef HAVE_LCD_COLOR 804#ifdef HAVE_LCD_COLOR
@@ -557,7 +817,7 @@ int onplay(char* file, int attr, int from)
557 items[i].function = sound_menu; 817 items[i].function = sound_menu;
558 i++; 818 i++;
559 } 819 }
560 820
561 if (context == CONTEXT_WPS || 821 if (context == CONTEXT_WPS ||
562 context == CONTEXT_TREE || 822 context == CONTEXT_TREE ||
563 ((context == CONTEXT_ID3DB) && 823 ((context == CONTEXT_ID3DB) &&
@@ -582,7 +842,8 @@ int onplay(char* file, int attr, int from)
582 items[i].desc = ID2P(LANG_MENU_SHOW_ID3_INFO); 842 items[i].desc = ID2P(LANG_MENU_SHOW_ID3_INFO);
583 items[i].function = browse_id3; 843 items[i].function = browse_id3;
584 i++; 844 i++;
585 if(rundb_initialized) { 845 if(rundb_initialized)
846 {
586 items[i].desc = ID2P(LANG_MENU_SET_RATING); 847 items[i].desc = ID2P(LANG_MENU_SET_RATING);
587 items[i].function = set_rating; 848 items[i].function = set_rating;
588 i++; 849 i++;
@@ -598,6 +859,21 @@ int onplay(char* file, int attr, int from)
598 items[i].desc = ID2P(LANG_RENAME); 859 items[i].desc = ID2P(LANG_RENAME);
599 items[i].function = rename_file; 860 items[i].function = rename_file;
600 i++; 861 i++;
862
863 items[i].desc = ID2P(LANG_CUT);
864 items[i].function = clipboard_cut;
865 i++;
866
867 items[i].desc = ID2P(LANG_COPY);
868 items[i].function = clipboard_copy;
869 i++;
870
871 if (clipboard_selection[0] != 0) /* Something in the clipboard? */
872 {
873 items[i].desc = ID2P(LANG_PASTE);
874 items[i].function = clipboard_paste;
875 i++;
876 }
601 } 877 }
602 878
603 if (!(attr & ATTR_DIRECTORY) && context == CONTEXT_TREE) 879 if (!(attr & ATTR_DIRECTORY) && context == CONTEXT_TREE)
@@ -608,8 +884,10 @@ int onplay(char* file, int attr, int from)
608 884
609#ifdef HAVE_LCD_COLOR 885#ifdef HAVE_LCD_COLOR
610 suffix = strrchr(file, '.'); 886 suffix = strrchr(file, '.');
611 if (suffix) { 887 if (suffix)
612 if (strcasecmp(suffix, ".bmp") == 0) { 888 {
889 if (strcasecmp(suffix, ".bmp") == 0)
890 {
613 items[i].desc = ID2P(LANG_SET_AS_BACKDROP); 891 items[i].desc = ID2P(LANG_SET_AS_BACKDROP);
614 items[i].function = set_backdrop; 892 items[i].function = set_backdrop;
615 i++; 893 i++;
@@ -635,6 +913,15 @@ int onplay(char* file, int attr, int from)
635 i++; 913 i++;
636 } 914 }
637 } 915 }
916 else
917 {
918 if (strlen(clipboard_selection) != 0)
919 {
920 items[i].desc = ID2P(LANG_PASTE);
921 items[i].function = clipboard_paste;
922 i++;
923 }
924 }
638 925
639 if (context == CONTEXT_TREE) 926 if (context == CONTEXT_TREE)
640 { 927 {