diff options
author | Nicolas Pennequin <nicolas.pennequin@free.fr> | 2007-11-11 12:29:37 +0000 |
---|---|---|
committer | Nicolas Pennequin <nicolas.pennequin@free.fr> | 2007-11-11 12:29:37 +0000 |
commit | 9d4bed7ff06818b098926932db824a8d6532bfee (patch) | |
tree | 0a1cfa6a98a75a2badc1a8d2a2d7839454522beb /apps/gui/wps_parser.c | |
parent | f34720b163aff1d167ae031f23f3250356aa2c1b (diff) | |
download | rockbox-9d4bed7ff06818b098926932db824a8d6532bfee.tar.gz rockbox-9d4bed7ff06818b098926932db824a8d6532bfee.zip |
Album art support. Based on FS#3045, but heavily modified to adapt to MoB and for cleanness.
The cover pictures are loaded from external bitmaps. JPEG and embedded art are not supported. The pictures will only be drawn on the main display. There is no resizing but it is possible to specify the WPS bitmap size in the bitmap names (e.g. cover.100x100.bmp).
The bitmaps are stored in the main buffer and read directly from there. Currently, duplicate bitmaps will simply be present several times in the buffer, but this will be improved.
To enable for a target, #define HAVE_ALBUMART in its config file.
For more information, see the wiki page: http://www.rockbox.org/wiki/AlbumArt.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15572 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/gui/wps_parser.c')
-rw-r--r-- | apps/gui/wps_parser.c | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/apps/gui/wps_parser.c b/apps/gui/wps_parser.c index 8471bff7d8..097a60c90f 100644 --- a/apps/gui/wps_parser.c +++ b/apps/gui/wps_parser.c | |||
@@ -113,6 +113,7 @@ static int parse_progressbar(const char *wps_bufptr, | |||
113 | struct wps_token *token, struct wps_data *wps_data); | 113 | struct wps_token *token, struct wps_data *wps_data); |
114 | static int parse_dir_level(const char *wps_bufptr, | 114 | static int parse_dir_level(const char *wps_bufptr, |
115 | struct wps_token *token, struct wps_data *wps_data); | 115 | struct wps_token *token, struct wps_data *wps_data); |
116 | |||
116 | #ifdef HAVE_LCD_BITMAP | 117 | #ifdef HAVE_LCD_BITMAP |
117 | static int parse_image_special(const char *wps_bufptr, | 118 | static int parse_image_special(const char *wps_bufptr, |
118 | struct wps_token *token, struct wps_data *wps_data); | 119 | struct wps_token *token, struct wps_data *wps_data); |
@@ -126,6 +127,13 @@ static int parse_image_load(const char *wps_bufptr, | |||
126 | struct wps_token *token, struct wps_data *wps_data); | 127 | struct wps_token *token, struct wps_data *wps_data); |
127 | #endif /*HAVE_LCD_BITMAP */ | 128 | #endif /*HAVE_LCD_BITMAP */ |
128 | 129 | ||
130 | #ifdef HAVE_ALBUMART | ||
131 | static int parse_albumart_load(const char *wps_bufptr, | ||
132 | struct wps_token *token, struct wps_data *wps_data); | ||
133 | static int parse_albumart_conditional(const char *wps_bufptr, | ||
134 | struct wps_token *token, struct wps_data *wps_data); | ||
135 | #endif /* HAVE_ALBUMART */ | ||
136 | |||
129 | #ifdef CONFIG_RTC | 137 | #ifdef CONFIG_RTC |
130 | #define WPS_RTC_REFRESH WPS_REFRESH_DYNAMIC | 138 | #define WPS_RTC_REFRESH WPS_REFRESH_DYNAMIC |
131 | #else | 139 | #else |
@@ -283,6 +291,11 @@ static const struct wps_tag all_tags[] = { | |||
283 | 291 | ||
284 | { WPS_TOKEN_IMAGE_DISPLAY, "x", 0, parse_image_load }, | 292 | { WPS_TOKEN_IMAGE_DISPLAY, "x", 0, parse_image_load }, |
285 | { WPS_TOKEN_IMAGE_PROGRESS_BAR, "P", 0, parse_image_special }, | 293 | { WPS_TOKEN_IMAGE_PROGRESS_BAR, "P", 0, parse_image_special }, |
294 | #ifdef HAVE_ALBUMART | ||
295 | { WPS_NO_TOKEN, "Cl", 0, parse_albumart_load }, | ||
296 | { WPS_TOKEN_ALBUMART_DISPLAY, "C", WPS_REFRESH_DYNAMIC, | ||
297 | parse_albumart_conditional }, | ||
298 | #endif | ||
286 | #if (LCD_DEPTH > 1) || (defined(HAVE_LCD_REMOTE) && (LCD_REMOTE_DEPTH > 1)) | 299 | #if (LCD_DEPTH > 1) || (defined(HAVE_LCD_REMOTE) && (LCD_REMOTE_DEPTH > 1)) |
287 | { WPS_TOKEN_IMAGE_BACKDROP, "X", 0, parse_image_special }, | 300 | { WPS_TOKEN_IMAGE_BACKDROP, "X", 0, parse_image_special }, |
288 | #endif | 301 | #endif |
@@ -606,6 +619,215 @@ static int parse_progressbar(const char *wps_bufptr, | |||
606 | #endif | 619 | #endif |
607 | } | 620 | } |
608 | 621 | ||
622 | #ifdef HAVE_ALBUMART | ||
623 | static int parse_albumart_load(const char *wps_bufptr, | ||
624 | struct wps_token *token, | ||
625 | struct wps_data *wps_data) | ||
626 | { | ||
627 | const char* _pos; | ||
628 | bool parsing; | ||
629 | const short xalign_mask = WPS_ALBUMART_ALIGN_LEFT | | ||
630 | WPS_ALBUMART_ALIGN_CENTER | | ||
631 | WPS_ALBUMART_ALIGN_RIGHT; | ||
632 | const short yalign_mask = WPS_ALBUMART_ALIGN_TOP | | ||
633 | WPS_ALBUMART_ALIGN_CENTER | | ||
634 | WPS_ALBUMART_ALIGN_BOTTOM; | ||
635 | |||
636 | (void)token; /* silence warning */ | ||
637 | |||
638 | /* reset albumart info in wps */ | ||
639 | wps_data->wps_uses_albumart = WPS_ALBUMART_NONE; | ||
640 | wps_data->albumart_max_width = -1; | ||
641 | wps_data->albumart_max_height = -1; | ||
642 | wps_data->albumart_xalign = WPS_ALBUMART_ALIGN_CENTER; /* default */ | ||
643 | wps_data->albumart_yalign = WPS_ALBUMART_ALIGN_CENTER; /* default */ | ||
644 | |||
645 | /* format: %Cl|x|y|[[l|c|r][d|i|s]mwidth]|[[t|c|b][d|i|s]mheight]| */ | ||
646 | |||
647 | /* initial validation and parsing of x and y components */ | ||
648 | if (*wps_bufptr != '|') | ||
649 | return 0; /* malformed token: e.g. %Cl7 */ | ||
650 | |||
651 | _pos = wps_bufptr + 1; | ||
652 | if (!isdigit(*_pos)) | ||
653 | return 0; /* malformed token: e.g. %Cl|@ */ | ||
654 | wps_data->albumart_x = atoi(_pos); | ||
655 | |||
656 | _pos = strchr(_pos, '|'); | ||
657 | if (!_pos || !isdigit(*(++_pos))) | ||
658 | return 0; /* malformed token: e.g. %Cl|7\n or %Cl|7|@ */ | ||
659 | |||
660 | wps_data->albumart_y = atoi(_pos); | ||
661 | |||
662 | _pos = strchr(_pos, '|'); | ||
663 | if (!_pos) | ||
664 | return 0; /* malformed token: no | after y coordinate | ||
665 | e.g. %Cl|7|59\n */ | ||
666 | |||
667 | /* parsing width field */ | ||
668 | parsing = true; | ||
669 | while (parsing) | ||
670 | { | ||
671 | /* apply each modifier in turn */ | ||
672 | ++_pos; | ||
673 | switch (*_pos) | ||
674 | { | ||
675 | case 'l': | ||
676 | case 'L': | ||
677 | case '+': | ||
678 | wps_data->albumart_xalign = | ||
679 | (wps_data->albumart_xalign & xalign_mask) | | ||
680 | WPS_ALBUMART_ALIGN_LEFT; | ||
681 | break; | ||
682 | case 'c': | ||
683 | case 'C': | ||
684 | wps_data->albumart_xalign = | ||
685 | (wps_data->albumart_xalign & xalign_mask) | | ||
686 | WPS_ALBUMART_ALIGN_CENTER; | ||
687 | break; | ||
688 | case 'r': | ||
689 | case 'R': | ||
690 | case '-': | ||
691 | wps_data->albumart_xalign = | ||
692 | (wps_data->albumart_xalign & xalign_mask) | | ||
693 | WPS_ALBUMART_ALIGN_RIGHT; | ||
694 | break; | ||
695 | case 'd': | ||
696 | case 'D': | ||
697 | wps_data->albumart_xalign |= WPS_ALBUMART_DECREASE; | ||
698 | break; | ||
699 | case 'i': | ||
700 | case 'I': | ||
701 | wps_data->albumart_xalign |= WPS_ALBUMART_INCREASE; | ||
702 | break; | ||
703 | case 's': | ||
704 | case 'S': | ||
705 | wps_data->albumart_xalign |= | ||
706 | (WPS_ALBUMART_DECREASE | WPS_ALBUMART_INCREASE); | ||
707 | break; | ||
708 | default: | ||
709 | parsing = false; | ||
710 | break; | ||
711 | } | ||
712 | } | ||
713 | /* extract max width data */ | ||
714 | if (*_pos != '|') | ||
715 | { | ||
716 | if (!isdigit(*_pos)) | ||
717 | return 0; /* malformed token: e.g. %Cl|7|59|# */ | ||
718 | wps_data->albumart_max_width = atoi(_pos); | ||
719 | _pos = strchr(_pos, '|'); | ||
720 | if (!_pos) | ||
721 | return 0; /* malformed token: no | after width field | ||
722 | e.g. %Cl|7|59|200\n */ | ||
723 | } | ||
724 | |||
725 | /* parsing height field */ | ||
726 | parsing = true; | ||
727 | while (parsing) | ||
728 | { | ||
729 | /* apply each modifier in turn */ | ||
730 | ++_pos; | ||
731 | switch (*_pos) | ||
732 | { | ||
733 | case 't': | ||
734 | case 'T': | ||
735 | case '-': | ||
736 | wps_data->albumart_yalign = | ||
737 | (wps_data->albumart_yalign & yalign_mask) | | ||
738 | WPS_ALBUMART_ALIGN_TOP; | ||
739 | break; | ||
740 | case 'c': | ||
741 | case 'C': | ||
742 | wps_data->albumart_yalign = | ||
743 | (wps_data->albumart_yalign & yalign_mask) | | ||
744 | WPS_ALBUMART_ALIGN_CENTER; | ||
745 | break; | ||
746 | case 'b': | ||
747 | case 'B': | ||
748 | case '+': | ||
749 | wps_data->albumart_yalign = | ||
750 | (wps_data->albumart_yalign & yalign_mask) | | ||
751 | WPS_ALBUMART_ALIGN_BOTTOM; | ||
752 | break; | ||
753 | case 'd': | ||
754 | case 'D': | ||
755 | wps_data->albumart_yalign |= WPS_ALBUMART_DECREASE; | ||
756 | break; | ||
757 | case 'i': | ||
758 | case 'I': | ||
759 | wps_data->albumart_yalign |= WPS_ALBUMART_INCREASE; | ||
760 | break; | ||
761 | case 's': | ||
762 | case 'S': | ||
763 | wps_data->albumart_yalign |= | ||
764 | (WPS_ALBUMART_DECREASE | WPS_ALBUMART_INCREASE); | ||
765 | break; | ||
766 | default: | ||
767 | parsing = false; | ||
768 | break; | ||
769 | } | ||
770 | } | ||
771 | /* extract max height data */ | ||
772 | if (*_pos != '|') | ||
773 | { | ||
774 | if (!isdigit(*_pos)) | ||
775 | return 0; /* malformed token e.g. %Cl|7|59|200|@ */ | ||
776 | wps_data->albumart_max_height = atoi(_pos); | ||
777 | _pos = strchr(_pos, '|'); | ||
778 | if (!_pos) | ||
779 | return 0; /* malformed token: no closing | | ||
780 | e.g. %Cl|7|59|200|200\n */ | ||
781 | } | ||
782 | |||
783 | /* if we got here, we parsed everything ok .. ! */ | ||
784 | if (wps_data->albumart_max_width < 0) | ||
785 | wps_data->albumart_max_width = 0; | ||
786 | else if (wps_data->albumart_max_width > LCD_WIDTH) | ||
787 | wps_data->albumart_max_width = LCD_WIDTH; | ||
788 | |||
789 | if (wps_data->albumart_max_height < 0) | ||
790 | wps_data->albumart_max_height = 0; | ||
791 | else if (wps_data->albumart_max_height > LCD_HEIGHT) | ||
792 | wps_data->albumart_max_height = LCD_HEIGHT; | ||
793 | |||
794 | wps_data->wps_uses_albumart = WPS_ALBUMART_LOAD; | ||
795 | |||
796 | /* Skip the rest of the line */ | ||
797 | return skip_end_of_line(wps_bufptr); | ||
798 | } | ||
799 | |||
800 | static int parse_albumart_conditional(const char *wps_bufptr, | ||
801 | struct wps_token *token, | ||
802 | struct wps_data *wps_data) | ||
803 | { | ||
804 | struct wps_token *prevtoken = token; | ||
805 | --prevtoken; | ||
806 | if (wps_data->num_tokens >= 1 && prevtoken->type == WPS_TOKEN_CONDITIONAL) | ||
807 | { | ||
808 | /* This %C is part of a %?C construct. | ||
809 | It's either %?C<blah> or %?Cn<blah> */ | ||
810 | token->type = WPS_TOKEN_ALBUMART_FOUND; | ||
811 | if (*wps_bufptr == 'n' && *(wps_bufptr + 1) == '<') | ||
812 | { | ||
813 | token->next = true; | ||
814 | return 1; | ||
815 | } | ||
816 | else if (*wps_bufptr == '<') | ||
817 | { | ||
818 | return 0; | ||
819 | } | ||
820 | else | ||
821 | { | ||
822 | token->type = WPS_NO_TOKEN; | ||
823 | return 0; | ||
824 | } | ||
825 | } | ||
826 | else | ||
827 | return 0; | ||
828 | }; | ||
829 | #endif /* HAVE_ALBUMART */ | ||
830 | |||
609 | /* Parse a generic token from the given string. Return the length read */ | 831 | /* Parse a generic token from the given string. Return the length read */ |
610 | static int parse_token(const char *wps_bufptr, struct wps_data *wps_data) | 832 | static int parse_token(const char *wps_bufptr, struct wps_data *wps_data) |
611 | { | 833 | { |
@@ -915,6 +1137,9 @@ static void wps_reset(struct wps_data *data) | |||
915 | bool rwps = data->remote_wps; /* remember whether the data is for a RWPS */ | 1137 | bool rwps = data->remote_wps; /* remember whether the data is for a RWPS */ |
916 | #endif | 1138 | #endif |
917 | memset(data, 0, sizeof(*data)); | 1139 | memset(data, 0, sizeof(*data)); |
1140 | #ifdef HAVE_ALBUMART | ||
1141 | data->wps_uses_albumart = WPS_ALBUMART_NONE; | ||
1142 | #endif | ||
918 | wps_data_init(data); | 1143 | wps_data_init(data); |
919 | #ifdef HAVE_REMOTE_LCD | 1144 | #ifdef HAVE_REMOTE_LCD |
920 | data->remote_wps = rwps; | 1145 | data->remote_wps = rwps; |