diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/misc.c | 47 | ||||
-rw-r--r-- | apps/misc.h | 2 | ||||
-rw-r--r-- | apps/tagcache.c | 55 | ||||
-rw-r--r-- | apps/tagtree.c | 258 |
4 files changed, 193 insertions, 169 deletions
diff --git a/apps/misc.c b/apps/misc.c index 4be9e43fd9..0936e85569 100644 --- a/apps/misc.c +++ b/apps/misc.c | |||
@@ -217,6 +217,53 @@ int read_line(int fd, char* buffer, int buffer_size) | |||
217 | return errno ? -1 : num_read; | 217 | return errno ? -1 : num_read; |
218 | } | 218 | } |
219 | 219 | ||
220 | /* Performance optimized version of the previous function. */ | ||
221 | int fast_readline(int fd, char *buf, int buf_size, void *parameters, | ||
222 | int (*callback)(int n, const char *buf, void *parameters)) | ||
223 | { | ||
224 | char *p, *next; | ||
225 | int rc, pos = 0; | ||
226 | int count = 0; | ||
227 | |||
228 | while ( 1 ) | ||
229 | { | ||
230 | next = NULL; | ||
231 | |||
232 | rc = read(fd, &buf[pos], buf_size - pos - 1); | ||
233 | if (rc >= 0) | ||
234 | buf[pos+rc] = '\0'; | ||
235 | |||
236 | if ( (p = strchr(buf, '\r')) != NULL) | ||
237 | { | ||
238 | *p = '\0'; | ||
239 | next = ++p; | ||
240 | } | ||
241 | else | ||
242 | p = buf; | ||
243 | |||
244 | if ( (p = strchr(p, '\n')) != NULL) | ||
245 | { | ||
246 | *p = '\0'; | ||
247 | next = ++p; | ||
248 | } | ||
249 | |||
250 | rc = callback(count, buf, parameters); | ||
251 | if (rc < 0) | ||
252 | return rc; | ||
253 | |||
254 | count++; | ||
255 | if (next) | ||
256 | { | ||
257 | pos = buf_size - ((long)next - (long)buf) - 1; | ||
258 | memmove(buf, next, pos); | ||
259 | } | ||
260 | else | ||
261 | break ; | ||
262 | } | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
220 | #ifdef HAVE_LCD_BITMAP | 267 | #ifdef HAVE_LCD_BITMAP |
221 | 268 | ||
222 | #if LCD_DEPTH == 16 | 269 | #if LCD_DEPTH == 16 |
diff --git a/apps/misc.h b/apps/misc.h index c5a89901ee..1bc9a23447 100644 --- a/apps/misc.h +++ b/apps/misc.h | |||
@@ -42,6 +42,8 @@ char *create_datetime_filename(char *buffer, const char *path, | |||
42 | * stored in buffer. | 42 | * stored in buffer. |
43 | */ | 43 | */ |
44 | int read_line(int fd, char* buffer, int buffer_size); | 44 | int read_line(int fd, char* buffer, int buffer_size); |
45 | int fast_readline(int fd, char *buf, int buf_size, void *parameters, | ||
46 | int (*callback)(int n, const char *buf, void *parameters)); | ||
45 | 47 | ||
46 | #ifdef HAVE_LCD_BITMAP | 48 | #ifdef HAVE_LCD_BITMAP |
47 | /* Save a .BMP file containing the current screen contents. */ | 49 | /* Save a .BMP file containing the current screen contents. */ |
diff --git a/apps/tagcache.c b/apps/tagcache.c index 38537b5ceb..bf20927d95 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c | |||
@@ -72,6 +72,7 @@ | |||
72 | #include "atoi.h" | 72 | #include "atoi.h" |
73 | #include "crc32.h" | 73 | #include "crc32.h" |
74 | #include "eeprom_settings.h" | 74 | #include "eeprom_settings.h" |
75 | #include "misc.h" | ||
75 | 76 | ||
76 | /* Tag Cache thread. */ | 77 | /* Tag Cache thread. */ |
77 | static struct event_queue tagcache_queue; | 78 | static struct event_queue tagcache_queue; |
@@ -2687,40 +2688,42 @@ static bool read_tag(char *dest, long size, | |||
2687 | return false; | 2688 | return false; |
2688 | } | 2689 | } |
2689 | 2690 | ||
2690 | static bool parse_changelog_line(int masterfd, const char *buf) | 2691 | static int parse_changelog_line(int line_n, const char *buf, void *parameters) |
2691 | { | 2692 | { |
2692 | struct index_entry idx; | 2693 | struct index_entry idx; |
2693 | char tag_data[MAX_PATH]; | 2694 | char tag_data[MAX_PATH]; |
2694 | int idx_id; | 2695 | int idx_id; |
2696 | int masterfd = (int)parameters; | ||
2695 | const int import_tags[] = { tag_playcount, tag_playtime, tag_lastplayed }; | 2697 | const int import_tags[] = { tag_playcount, tag_playtime, tag_lastplayed }; |
2696 | int i; | 2698 | int i; |
2699 | (void)line_n; | ||
2697 | 2700 | ||
2698 | if (*buf == '#') | 2701 | if (*buf == '#') |
2699 | return true; | 2702 | return 0; |
2700 | 2703 | ||
2701 | if (!read_tag(tag_data, sizeof tag_data, buf, "filename")) | 2704 | if (!read_tag(tag_data, sizeof tag_data, buf, "filename")) |
2702 | { | 2705 | { |
2703 | logf("filename missing"); | 2706 | logf("filename missing"); |
2704 | logf("-> %s", buf); | 2707 | logf("-> %s", buf); |
2705 | return false; | 2708 | return -1; |
2706 | } | 2709 | } |
2707 | 2710 | ||
2708 | idx_id = find_index(tag_data); | 2711 | idx_id = find_index(tag_data); |
2709 | if (idx_id < 0) | 2712 | if (idx_id < 0) |
2710 | { | 2713 | { |
2711 | logf("entry not found"); | 2714 | logf("entry not found"); |
2712 | return false; | 2715 | return -2; |
2713 | } | 2716 | } |
2714 | 2717 | ||
2715 | if (!get_index(masterfd, idx_id, &idx, false)) | 2718 | if (!get_index(masterfd, idx_id, &idx, false)) |
2716 | { | 2719 | { |
2717 | logf("failed to retrieve index entry"); | 2720 | logf("failed to retrieve index entry"); |
2718 | return false; | 2721 | return -3; |
2719 | } | 2722 | } |
2720 | 2723 | ||
2721 | /* Stop if tag has already been modified. */ | 2724 | /* Stop if tag has already been modified. */ |
2722 | if (idx.flag & FLAG_DIRTYNUM) | 2725 | if (idx.flag & FLAG_DIRTYNUM) |
2723 | return false; | 2726 | return -4; |
2724 | 2727 | ||
2725 | logf("import: %s", tag_data); | 2728 | logf("import: %s", tag_data); |
2726 | 2729 | ||
@@ -2745,7 +2748,7 @@ static bool parse_changelog_line(int masterfd, const char *buf) | |||
2745 | current_serial = data; | 2748 | current_serial = data; |
2746 | } | 2749 | } |
2747 | 2750 | ||
2748 | return write_index(masterfd, idx_id, &idx); | 2751 | return write_index(masterfd, idx_id, &idx) ? 0 : -5; |
2749 | } | 2752 | } |
2750 | 2753 | ||
2751 | bool tagcache_import_changelog(void) | 2754 | bool tagcache_import_changelog(void) |
@@ -2754,7 +2757,6 @@ bool tagcache_import_changelog(void) | |||
2754 | struct tagcache_header tch; | 2757 | struct tagcache_header tch; |
2755 | int clfd, masterfd; | 2758 | int clfd, masterfd; |
2756 | char buf[2048]; | 2759 | char buf[2048]; |
2757 | int pos = 0; | ||
2758 | 2760 | ||
2759 | if (!stat.ready) | 2761 | if (!stat.ready) |
2760 | return false; | 2762 | return false; |
@@ -2779,41 +2781,8 @@ bool tagcache_import_changelog(void) | |||
2779 | 2781 | ||
2780 | filenametag_fd = open_tag_fd(&tch, tag_filename, false); | 2782 | filenametag_fd = open_tag_fd(&tch, tag_filename, false); |
2781 | 2783 | ||
2782 | /* Fast readline */ | 2784 | fast_readline(filenametag_fd, buf, sizeof buf, (void *)masterfd, |
2783 | while ( 1 ) | 2785 | parse_changelog_line); |
2784 | { | ||
2785 | char *p; | ||
2786 | char *next = NULL; | ||
2787 | int rc; | ||
2788 | |||
2789 | rc = read(clfd, &buf[pos], sizeof(buf)-pos-1); | ||
2790 | if (rc >= 0) | ||
2791 | buf[pos+rc] = '\0'; | ||
2792 | |||
2793 | if ( (p = strchr(buf, '\r')) != NULL) | ||
2794 | { | ||
2795 | *p = '\0'; | ||
2796 | next = ++p; | ||
2797 | } | ||
2798 | else | ||
2799 | p = buf; | ||
2800 | |||
2801 | if ( (p = strchr(p, '\n')) != NULL) | ||
2802 | { | ||
2803 | *p = '\0'; | ||
2804 | next = ++p; | ||
2805 | } | ||
2806 | |||
2807 | parse_changelog_line(masterfd, buf); | ||
2808 | |||
2809 | if (next) | ||
2810 | { | ||
2811 | pos = sizeof(buf) - ((long)next - (long)buf) - 1; | ||
2812 | memmove(buf, next, pos); | ||
2813 | } | ||
2814 | else | ||
2815 | break ; | ||
2816 | } | ||
2817 | 2786 | ||
2818 | close(clfd); | 2787 | close(clfd); |
2819 | close(masterfd); | 2788 | close(masterfd); |
diff --git a/apps/tagtree.c b/apps/tagtree.c index 97339fa13a..082e10d7d9 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include "atoi.h" | 42 | #include "atoi.h" |
43 | #include "playback.h" | 43 | #include "playback.h" |
44 | #include "yesno.h" | 44 | #include "yesno.h" |
45 | #include "misc.h" | ||
45 | 46 | ||
46 | #define FILE_SEARCH_INSTRUCTIONS ROCKBOX_DIR "/tagnavi.config" | 47 | #define FILE_SEARCH_INSTRUCTIONS ROCKBOX_DIR "/tagnavi.config" |
47 | 48 | ||
@@ -678,157 +679,162 @@ bool tagtree_import(void) | |||
678 | return false; | 679 | return false; |
679 | } | 680 | } |
680 | 681 | ||
681 | static bool parse_menu(const char *filename) | 682 | static bool parse_menu(const char *filename); |
683 | |||
684 | int parse_line(int n, const char *buf, void *parameters) | ||
682 | { | 685 | { |
683 | int fd; | ||
684 | char buf[256]; | ||
685 | char data[256]; | 686 | char data[256]; |
686 | int variable; | 687 | int variable; |
687 | int rc; | 688 | static bool read_menu; |
688 | bool first = true; | ||
689 | bool read_menu = false; | ||
690 | int i; | 689 | int i; |
691 | |||
692 | if (menu_count >= TAGMENU_MAX_MENUS) | ||
693 | { | ||
694 | logf("max menucount reached"); | ||
695 | return false; | ||
696 | } | ||
697 | 690 | ||
698 | fd = open(filename, O_RDONLY); | 691 | (void)parameters; |
699 | if (fd < 0) | ||
700 | { | ||
701 | logf("Search instruction file not found."); | ||
702 | return false; | ||
703 | } | ||
704 | 692 | ||
705 | /* Now read file for real, parsing into si */ | 693 | /* First line, do initialisation. */ |
706 | while ( 1 ) | 694 | if (n == 0) |
707 | { | 695 | { |
708 | rc = read_line(fd, buf, sizeof(buf)-1); | 696 | if (strcasecmp(TAGNAVI_VERSION, buf)) |
709 | if (rc <= 0) | ||
710 | break; | ||
711 | |||
712 | if (first) | ||
713 | { | 697 | { |
714 | if (strcasecmp(TAGNAVI_VERSION, buf)) | 698 | logf("Version mismatch"); |
715 | { | 699 | return -1; |
716 | logf("Version mismatch"); | ||
717 | break; | ||
718 | } | ||
719 | first = false; | ||
720 | } | 700 | } |
721 | 701 | ||
722 | if (buf[0] == '#') | 702 | read_menu = false; |
723 | continue; | 703 | } |
724 | 704 | ||
725 | if (buf[0] == '\0') | 705 | if (buf[0] == '#') |
706 | return 0; | ||
707 | |||
708 | if (buf[0] == '\0') | ||
709 | { | ||
710 | if (read_menu) | ||
726 | { | 711 | { |
727 | if (read_menu) | 712 | /* End the menu */ |
728 | { | 713 | menu_count++; |
729 | /* End the menu */ | 714 | read_menu = false; |
730 | menu_count++; | ||
731 | read_menu = false; | ||
732 | } | ||
733 | continue; | ||
734 | } | 715 | } |
716 | return 0; | ||
717 | } | ||
718 | |||
719 | if (!read_menu) | ||
720 | { | ||
721 | strp = buf; | ||
722 | if (get_tag(&variable) <= 0) | ||
723 | return 0; | ||
735 | 724 | ||
736 | if (!read_menu) | 725 | switch (variable) |
737 | { | 726 | { |
738 | strp = buf; | 727 | case var_format: |
739 | if (get_tag(&variable) <= 0) | 728 | if (add_format(strp) < 0) |
740 | continue; | 729 | { |
730 | logf("Format add fail: %s", data); | ||
731 | } | ||
732 | break; | ||
733 | |||
734 | case var_include: | ||
735 | if (get_token_str(data, sizeof(data)) < 0) | ||
736 | { | ||
737 | logf("%include empty"); | ||
738 | return false; | ||
739 | } | ||
741 | 740 | ||
742 | switch (variable) | 741 | if (!parse_menu(data)) |
743 | { | 742 | { |
744 | case var_format: | 743 | logf("Load menu fail: %s", data); |
745 | if (add_format(strp) < 0) | 744 | } |
746 | { | 745 | break; |
747 | logf("Format add fail: %s", data); | ||
748 | } | ||
749 | break; | ||
750 | 746 | ||
751 | case var_include: | 747 | case var_menu_start: |
752 | if (get_token_str(data, sizeof(data)) < 0) | 748 | if (menu_count >= TAGMENU_MAX_MENUS) |
753 | { | 749 | { |
754 | logf("%include empty"); | 750 | logf("max menucount reached"); |
755 | return false; | 751 | return false; |
756 | } | 752 | } |
757 | 753 | ||
758 | if (!parse_menu(data)) | 754 | menus[menu_count] = buffer_alloc(sizeof(struct root_menu)); |
759 | { | 755 | menu = menus[menu_count]; |
760 | logf("Load menu fail: %s", data); | 756 | memset(menu, 0, sizeof(struct root_menu)); |
761 | } | 757 | if (get_token_str(menu->id, sizeof(menu->id)) < 0) |
762 | break; | 758 | { |
759 | logf("%menu_start id empty"); | ||
760 | return false; | ||
761 | } | ||
762 | if (get_token_str(menu->title, sizeof(menu->title)) < 0) | ||
763 | { | ||
764 | logf("%menu_start title empty"); | ||
765 | return false; | ||
766 | } | ||
767 | menu->itemcount = 0; | ||
768 | read_menu = true; | ||
769 | break; | ||
763 | 770 | ||
764 | case var_menu_start: | 771 | case var_rootmenu: |
765 | if (menu_count >= TAGMENU_MAX_MENUS) | 772 | /* Only set root menu once. */ |
766 | { | 773 | if (root_menu) |
767 | logf("max menucount reached"); | ||
768 | return false; | ||
769 | } | ||
770 | |||
771 | menus[menu_count] = buffer_alloc(sizeof(struct root_menu)); | ||
772 | menu = menus[menu_count]; | ||
773 | memset(menu, 0, sizeof(struct root_menu)); | ||
774 | if (get_token_str(menu->id, sizeof(menu->id)) < 0) | ||
775 | { | ||
776 | logf("%menu_start id empty"); | ||
777 | return false; | ||
778 | } | ||
779 | if (get_token_str(menu->title, sizeof(menu->title)) < 0) | ||
780 | { | ||
781 | logf("%menu_start title empty"); | ||
782 | return false; | ||
783 | } | ||
784 | menu->itemcount = 0; | ||
785 | read_menu = true; | ||
786 | break; | 774 | break; |
787 | 775 | ||
788 | case var_rootmenu: | 776 | if (get_token_str(data, sizeof(data)) < 0) |
789 | /* Only set root menu once. */ | 777 | { |
790 | if (root_menu) | 778 | logf("%root_menu empty"); |
791 | break; | 779 | return false; |
792 | 780 | } | |
793 | if (get_token_str(data, sizeof(data)) < 0) | ||
794 | { | ||
795 | logf("%root_menu empty"); | ||
796 | return false; | ||
797 | } | ||
798 | 781 | ||
799 | for (i = 0; i < menu_count; i++) | 782 | for (i = 0; i < menu_count; i++) |
783 | { | ||
784 | if (!strcasecmp(menus[i]->id, data)) | ||
800 | { | 785 | { |
801 | if (!strcasecmp(menus[i]->id, data)) | 786 | root_menu = i; |
802 | { | ||
803 | root_menu = i; | ||
804 | } | ||
805 | } | 787 | } |
806 | break; | 788 | } |
807 | } | 789 | break; |
808 | |||
809 | continue; | ||
810 | } | ||
811 | |||
812 | if (menu->itemcount >= TAGMENU_MAX_ITEMS) | ||
813 | { | ||
814 | logf("max itemcount reached"); | ||
815 | continue; | ||
816 | } | ||
817 | |||
818 | /* Allocate */ | ||
819 | if (menu->items[menu->itemcount] == NULL) | ||
820 | { | ||
821 | menu->items[menu->itemcount] = buffer_alloc(sizeof(struct menu_entry)); | ||
822 | memset(menu->items[menu->itemcount], 0, sizeof(struct menu_entry)); | ||
823 | menu->items[menu->itemcount]->si = buffer_alloc(sizeof(struct search_instruction)); | ||
824 | } | 790 | } |
825 | 791 | ||
826 | memset(menu->items[menu->itemcount]->si, 0, sizeof(struct search_instruction)); | 792 | return 0; |
827 | if (!parse_search(menu->items[menu->itemcount], buf)) | ||
828 | continue; | ||
829 | |||
830 | menu->itemcount++; | ||
831 | } | 793 | } |
794 | |||
795 | if (menu->itemcount >= TAGMENU_MAX_ITEMS) | ||
796 | { | ||
797 | logf("max itemcount reached"); | ||
798 | return 0; | ||
799 | } | ||
800 | |||
801 | /* Allocate */ | ||
802 | if (menu->items[menu->itemcount] == NULL) | ||
803 | { | ||
804 | menu->items[menu->itemcount] = buffer_alloc(sizeof(struct menu_entry)); | ||
805 | memset(menu->items[menu->itemcount], 0, sizeof(struct menu_entry)); | ||
806 | menu->items[menu->itemcount]->si = buffer_alloc(sizeof(struct search_instruction)); | ||
807 | } | ||
808 | |||
809 | memset(menu->items[menu->itemcount]->si, 0, sizeof(struct search_instruction)); | ||
810 | if (!parse_search(menu->items[menu->itemcount], buf)) | ||
811 | return 0; | ||
812 | |||
813 | menu->itemcount++; | ||
814 | |||
815 | return 0; | ||
816 | } | ||
817 | |||
818 | static bool parse_menu(const char *filename) | ||
819 | { | ||
820 | int fd; | ||
821 | char buf[256]; | ||
822 | |||
823 | if (menu_count >= TAGMENU_MAX_MENUS) | ||
824 | { | ||
825 | logf("max menucount reached"); | ||
826 | return false; | ||
827 | } | ||
828 | |||
829 | fd = open(filename, O_RDONLY); | ||
830 | if (fd < 0) | ||
831 | { | ||
832 | logf("Search instruction file not found."); | ||
833 | return false; | ||
834 | } | ||
835 | |||
836 | /* Now read file for real, parsing into si */ | ||
837 | fast_readline(fd, buf, sizeof buf, NULL, parse_line); | ||
832 | close(fd); | 838 | close(fd); |
833 | 839 | ||
834 | return true; | 840 | return true; |