diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugins/bitmaps/native/SOURCES | 2 | ||||
-rw-r--r-- | apps/plugins/lib/bmp.c | 33 | ||||
-rw-r--r-- | apps/plugins/lib/bmp.h | 6 | ||||
-rw-r--r-- | apps/plugins/pictureflow.c | 220 | ||||
-rw-r--r-- | apps/plugins/resize_test.c | 127 |
5 files changed, 322 insertions, 66 deletions
diff --git a/apps/plugins/bitmaps/native/SOURCES b/apps/plugins/bitmaps/native/SOURCES index 1acc903387..35bd6ad69e 100644 --- a/apps/plugins/bitmaps/native/SOURCES +++ b/apps/plugins/bitmaps/native/SOURCES | |||
@@ -517,7 +517,7 @@ matrix_normal.bmp | |||
517 | #else | 517 | #else |
518 | pictureflow_logo.193x34x16.bmp | 518 | pictureflow_logo.193x34x16.bmp |
519 | #endif | 519 | #endif |
520 | #if (LCD_HEIGHT < 200 ) | 520 | #if (LCD_HEIGHT < 100 ) |
521 | pictureflow_emptyslide.50x50x16.bmp | 521 | pictureflow_emptyslide.50x50x16.bmp |
522 | #else | 522 | #else |
523 | pictureflow_emptyslide.100x100x16.bmp | 523 | pictureflow_emptyslide.100x100x16.bmp |
diff --git a/apps/plugins/lib/bmp.c b/apps/plugins/lib/bmp.c index dc8432f76a..03bdc73783 100644 --- a/apps/plugins/lib/bmp.c +++ b/apps/plugins/lib/bmp.c | |||
@@ -82,3 +82,36 @@ int save_bmp_file( char* filename, struct bitmap *bm, struct plugin_api* rb ) | |||
82 | rb->close( fh ); | 82 | rb->close( fh ); |
83 | return 1; | 83 | return 1; |
84 | } | 84 | } |
85 | |||
86 | /** | ||
87 | Very simple image scale from src to dst (nearest neighbour). | ||
88 | Source and destination dimensions are read from the struct bitmap. | ||
89 | */ | ||
90 | void simple_resize_bitmap(struct bitmap *src, struct bitmap *dst) | ||
91 | { | ||
92 | const int srcw = src->width; | ||
93 | const int srch = src->height; | ||
94 | const int dstw = dst->width; | ||
95 | const int dsth = dst->height; | ||
96 | const fb_data *srcd = (fb_data*)(src->data); | ||
97 | const fb_data *dstd = (fb_data*)(dst->data); | ||
98 | |||
99 | const long xrstep = ((srcw-1) << 8) / (dstw-1); | ||
100 | const long yrstep = ((srch-1) << 8) / (dsth-1); | ||
101 | fb_data *src_row, *dst_row; | ||
102 | long xr, yr = 0; | ||
103 | int src_x, src_y, dst_x, dst_y; | ||
104 | for (dst_y=0; dst_y < dsth; dst_y++) | ||
105 | { | ||
106 | src_y = (yr >> 8); | ||
107 | src_row = (fb_data*)&srcd[src_y * srcw]; | ||
108 | dst_row = (fb_data*)&dstd[dst_y * dstw]; | ||
109 | for (xr=0,dst_x=0; dst_x < dstw; dst_x++) | ||
110 | { | ||
111 | src_x = (xr >> 8); | ||
112 | dst_row[dst_x] = src_row[src_x]; | ||
113 | xr += xrstep; | ||
114 | } | ||
115 | yr += yrstep; | ||
116 | } | ||
117 | } | ||
diff --git a/apps/plugins/lib/bmp.h b/apps/plugins/lib/bmp.h index dc26e80114..e35c1ecb0a 100644 --- a/apps/plugins/lib/bmp.h +++ b/apps/plugins/lib/bmp.h | |||
@@ -27,4 +27,10 @@ | |||
27 | */ | 27 | */ |
28 | int save_bmp_file( char* filename, struct bitmap *bm, struct plugin_api* rb ); | 28 | int save_bmp_file( char* filename, struct bitmap *bm, struct plugin_api* rb ); |
29 | 29 | ||
30 | /** | ||
31 | Very simple image scale from src to dst (nearest neighbour). | ||
32 | Source and destination dimensions are read from the struct bitmap. | ||
33 | */ | ||
34 | void simple_resize_bitmap(struct bitmap *src, struct bitmap *dst); | ||
35 | |||
30 | #endif | 36 | #endif |
diff --git a/apps/plugins/pictureflow.c b/apps/plugins/pictureflow.c index c52fba4970..272a691306 100644 --- a/apps/plugins/pictureflow.c +++ b/apps/plugins/pictureflow.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include "plugin.h" | 24 | #include "plugin.h" |
25 | #include "pluginlib_actions.h" | 25 | #include "pluginlib_actions.h" |
26 | #include "helper.h" | 26 | #include "helper.h" |
27 | #include "lib/bmp.h" | 27 | #include "bmp.h" |
28 | #include "picture.h" | 28 | #include "picture.h" |
29 | #include "pictureflow_logo.h" | 29 | #include "pictureflow_logo.h" |
30 | #include "pictureflow_emptyslide.h" | 30 | #include "pictureflow_emptyslide.h" |
@@ -77,7 +77,7 @@ const struct button_mapping *plugin_contexts[] | |||
77 | #define MAX_IMG_WIDTH LCD_WIDTH | 77 | #define MAX_IMG_WIDTH LCD_WIDTH |
78 | #define MAX_IMG_HEIGHT LCD_HEIGHT | 78 | #define MAX_IMG_HEIGHT LCD_HEIGHT |
79 | 79 | ||
80 | #if (LCD_WIDTH < 200) | 80 | #if (LCD_HEIGHT < 100) |
81 | #define PREFERRED_IMG_WIDTH 50 | 81 | #define PREFERRED_IMG_WIDTH 50 |
82 | #define PREFERRED_IMG_HEIGHT 50 | 82 | #define PREFERRED_IMG_HEIGHT 50 |
83 | #else | 83 | #else |
@@ -90,8 +90,10 @@ const struct button_mapping *plugin_contexts[] | |||
90 | 90 | ||
91 | #define SLIDE_CACHE_SIZE 100 | 91 | #define SLIDE_CACHE_SIZE 100 |
92 | 92 | ||
93 | #define LEFT_SLIDES_COUNT 3 | 93 | #define MAX_SLIDES_COUNT 10 |
94 | #define RIGHT_SLIDES_COUNT 3 | 94 | |
95 | #define SPACING_BETWEEN_SLIDE 40 | ||
96 | #define EXTRA_SPACING_FOR_CENTER_SLIDE 0 | ||
95 | 97 | ||
96 | #define THREAD_STACK_SIZE DEFAULT_STACK_SIZE + 0x200 | 98 | #define THREAD_STACK_SIZE DEFAULT_STACK_SIZE + 0x200 |
97 | #define CACHE_PREFIX PLUGIN_DEMOS_DIR "/pictureflow" | 99 | #define CACHE_PREFIX PLUGIN_DEMOS_DIR "/pictureflow" |
@@ -106,6 +108,7 @@ const struct button_mapping *plugin_contexts[] | |||
106 | #define UNIQBUF_SIZE (64*1024) | 108 | #define UNIQBUF_SIZE (64*1024) |
107 | 109 | ||
108 | #define EMPTY_SLIDE CACHE_PREFIX "/emptyslide.pfraw" | 110 | #define EMPTY_SLIDE CACHE_PREFIX "/emptyslide.pfraw" |
111 | #define CONFIG_FILE CACHE_PREFIX "/pictureflow.config" | ||
109 | 112 | ||
110 | /* Error return values */ | 113 | /* Error return values */ |
111 | #define ERROR_NO_ALBUMS -1 | 114 | #define ERROR_NO_ALBUMS -1 |
@@ -154,7 +157,12 @@ const struct picture logos[]={ | |||
154 | {pictureflow_logo, BMPWIDTH_pictureflow_logo, BMPHEIGHT_pictureflow_logo}, | 157 | {pictureflow_logo, BMPWIDTH_pictureflow_logo, BMPHEIGHT_pictureflow_logo}, |
155 | }; | 158 | }; |
156 | 159 | ||
157 | 160 | struct config_data { | |
161 | long avg_album_width; | ||
162 | int spacing_between_slides; | ||
163 | int extra_spacing_for_center_slide; | ||
164 | int show_slides; | ||
165 | }; | ||
158 | 166 | ||
159 | /** below we allocate the memory we want to use **/ | 167 | /** below we allocate the memory we want to use **/ |
160 | 168 | ||
@@ -162,15 +170,14 @@ static fb_data *buffer; /* for now it always points to the lcd framebuffer */ | |||
162 | static PFreal rays[BUFFER_WIDTH]; | 170 | static PFreal rays[BUFFER_WIDTH]; |
163 | static bool animation_is_active; /* an animation is currently running */ | 171 | static bool animation_is_active; /* an animation is currently running */ |
164 | static struct slide_data center_slide; | 172 | static struct slide_data center_slide; |
165 | static struct slide_data left_slides[LEFT_SLIDES_COUNT]; | 173 | static struct slide_data left_slides[MAX_SLIDES_COUNT]; |
166 | static struct slide_data right_slides[RIGHT_SLIDES_COUNT]; | 174 | static struct slide_data right_slides[MAX_SLIDES_COUNT]; |
167 | static int slide_frame; | 175 | static int slide_frame; |
168 | static int step; | 176 | static int step; |
169 | static int target; | 177 | static int target; |
170 | static int fade; | 178 | static int fade; |
171 | static int center_index; /* index of the slide that is in the center */ | 179 | static int center_index; /* index of the slide that is in the center */ |
172 | static int itilt; | 180 | static int itilt; |
173 | static int spacing; /* spacing between slides */ | ||
174 | static int zoom; | 181 | static int zoom; |
175 | static PFreal offsetX; | 182 | static PFreal offsetX; |
176 | static PFreal offsetY; | 183 | static PFreal offsetY; |
@@ -204,6 +211,7 @@ static fb_data *input_bmp_buffer; | |||
204 | static fb_data *output_bmp_buffer; | 211 | static fb_data *output_bmp_buffer; |
205 | static int input_hid; | 212 | static int input_hid; |
206 | static int output_hid; | 213 | static int output_hid; |
214 | static struct config_data config; | ||
207 | 215 | ||
208 | static bool thread_is_running; | 216 | static bool thread_is_running; |
209 | 217 | ||
@@ -343,7 +351,7 @@ PFreal sinTable[] = { /* 10 */ | |||
343 | /** code */ | 351 | /** code */ |
344 | 352 | ||
345 | 353 | ||
346 | bool create_bmp(struct bitmap* input_bmp, char *target_path); | 354 | bool create_bmp(struct bitmap* input_bmp, char *target_path, bool resize); |
347 | int load_surface(int); | 355 | int load_surface(int); |
348 | 356 | ||
349 | /* There are some precision issues when not using (long long) which in turn | 357 | /* There are some precision issues when not using (long long) which in turn |
@@ -386,6 +394,7 @@ static inline PFreal fdiv(PFreal n, PFreal m) | |||
386 | } | 394 | } |
387 | #endif | 395 | #endif |
388 | 396 | ||
397 | |||
389 | inline PFreal fsin(int iangle) | 398 | inline PFreal fsin(int iangle) |
390 | { | 399 | { |
391 | while (iangle < 0) | 400 | while (iangle < 0) |
@@ -569,15 +578,12 @@ bool free_buffers(void) | |||
569 | */ | 578 | */ |
570 | bool create_albumart_cache(bool force) | 579 | bool create_albumart_cache(bool force) |
571 | { | 580 | { |
572 | /* FIXME: currently we check for the file CACHE_PREFIX/ready | ||
573 | We need a real menu etc. to recreate cache. For now, delete | ||
574 | the file to recreate the cache. */ | ||
575 | |||
576 | number_of_slides = album_count; | 581 | number_of_slides = album_count; |
582 | int fh,ret; | ||
577 | 583 | ||
578 | if ( ! force && rb->file_exists( CACHE_PREFIX "/ready" ) ) return true; | 584 | if ( ! force && rb->file_exists( CACHE_PREFIX "/ready" ) ) return true; |
579 | 585 | ||
580 | int i; | 586 | int i, slides = 0; |
581 | struct bitmap input_bmp; | 587 | struct bitmap input_bmp; |
582 | 588 | ||
583 | for (i=0; i < album_count; i++) | 589 | for (i=0; i < album_count; i++) |
@@ -586,7 +592,6 @@ bool create_albumart_cache(bool force) | |||
586 | if (!get_albumart_for_index_from_db(i, tmp_path_name, MAX_PATH)) | 592 | if (!get_albumart_for_index_from_db(i, tmp_path_name, MAX_PATH)) |
587 | continue; | 593 | continue; |
588 | 594 | ||
589 | int ret; | ||
590 | input_bmp.data = (char *)input_bmp_buffer; | 595 | input_bmp.data = (char *)input_bmp_buffer; |
591 | ret = rb->read_bmp_file(tmp_path_name, &input_bmp, | 596 | ret = rb->read_bmp_file(tmp_path_name, &input_bmp, |
592 | sizeof(fb_data)*MAX_IMG_WIDTH*MAX_IMG_HEIGHT, | 597 | sizeof(fb_data)*MAX_IMG_WIDTH*MAX_IMG_HEIGHT, |
@@ -596,13 +601,21 @@ bool create_albumart_cache(bool force) | |||
596 | continue; /* skip missing/broken files */ | 601 | continue; /* skip missing/broken files */ |
597 | } | 602 | } |
598 | 603 | ||
604 | |||
599 | rb->snprintf(tmp_path_name, sizeof(tmp_path_name), CACHE_PREFIX "/%d.pfraw", i); | 605 | rb->snprintf(tmp_path_name, sizeof(tmp_path_name), CACHE_PREFIX "/%d.pfraw", i); |
600 | if (!create_bmp(&input_bmp, tmp_path_name)) { | 606 | if (!create_bmp(&input_bmp, tmp_path_name, false)) { |
601 | rb->splash(HZ, "couldn't write bmp"); | 607 | rb->splash(HZ, "couldn't write bmp"); |
602 | } | 608 | } |
609 | config.avg_album_width += input_bmp.width; | ||
610 | slides++; | ||
603 | if ( rb->button_get(false) == PICTUREFLOW_MENU ) return false; | 611 | if ( rb->button_get(false) == PICTUREFLOW_MENU ) return false; |
604 | } | 612 | } |
605 | int fh = rb->creat( CACHE_PREFIX "/ready" ); | 613 | config.avg_album_width /= slides; |
614 | if ( config.avg_album_width == 0 ) { | ||
615 | rb->splash(HZ, "album size is 0"); | ||
616 | return false; | ||
617 | } | ||
618 | fh = rb->creat( CACHE_PREFIX "/ready" ); | ||
606 | rb->close(fh); | 619 | rb->close(fh); |
607 | return true; | 620 | return true; |
608 | } | 621 | } |
@@ -847,25 +860,38 @@ int read_pfraw(char* filename) | |||
847 | Create the slide with it's reflection for the given slide_index and filename | 860 | Create the slide with it's reflection for the given slide_index and filename |
848 | and store it as pfraw in CACHE_PREFIX/[slide_index].pfraw | 861 | and store it as pfraw in CACHE_PREFIX/[slide_index].pfraw |
849 | */ | 862 | */ |
850 | bool create_bmp(struct bitmap *input_bmp, char *target_path) | 863 | bool create_bmp(struct bitmap *input_bmp, char *target_path, bool resize) |
851 | { | 864 | { |
852 | fb_data *src = (fb_data *)input_bmp->data; | ||
853 | struct bitmap output_bmp; | 865 | struct bitmap output_bmp; |
854 | 866 | ||
855 | output_bmp.width = input_bmp->width * 2; | ||
856 | output_bmp.height = input_bmp->height; | ||
857 | output_bmp.format = input_bmp->format; | 867 | output_bmp.format = input_bmp->format; |
858 | output_bmp.data = (char *)output_bmp_buffer; | 868 | output_bmp.data = (char *)output_bmp_buffer; |
869 | if ( resize ) { /* resize image and swap buffers */ | ||
870 | output_bmp.width = config.avg_album_width; | ||
871 | output_bmp.height = config.avg_album_width; | ||
872 | simple_resize_bitmap(input_bmp, &output_bmp); | ||
873 | input_bmp->data = output_bmp.data; | ||
874 | input_bmp->width = output_bmp.width; | ||
875 | input_bmp->height = output_bmp.height; | ||
876 | output_bmp.data = (char *)input_bmp_buffer; | ||
877 | output_bmp.width = input_bmp->width * 2; | ||
878 | output_bmp.height = input_bmp->height; | ||
879 | } | ||
880 | output_bmp.width = input_bmp->width * 2; | ||
881 | output_bmp.height = input_bmp->height; | ||
882 | |||
883 | fb_data *src = (fb_data *)input_bmp->data; | ||
884 | fb_data *dst = (fb_data *)output_bmp.data; | ||
859 | 885 | ||
860 | /* transpose the image, this is to speed-up the rendering | 886 | /* transpose the image, this is to speed-up the rendering |
861 | because we process one column at a time | 887 | because we process one column at a time |
862 | (and much better and faster to work row-wise, i.e in one scanline) */ | 888 | (and much better and faster to work row-wise, i.e in one scanline) */ |
863 | int hofs = input_bmp->width / 3; | 889 | int hofs = input_bmp->width / 3; |
864 | rb->memset(output_bmp_buffer, 0, sizeof(fb_data) * output_bmp.width * output_bmp.height); | 890 | rb->memset(dst, 0, sizeof(fb_data) * output_bmp.width * output_bmp.height); |
865 | int x, y; | 891 | int x, y; |
866 | for (x = 0; x < input_bmp->width; x++) | 892 | for (x = 0; x < input_bmp->width; x++) |
867 | for (y = 0; y < input_bmp->height; y++) | 893 | for (y = 0; y < input_bmp->height; y++) |
868 | output_bmp_buffer[output_bmp.width * x + (hofs + y)] = | 894 | dst[output_bmp.width * x + (hofs + y)] = |
869 | src[y * input_bmp->width + x]; | 895 | src[y * input_bmp->width + x]; |
870 | 896 | ||
871 | /* create the reflection */ | 897 | /* create the reflection */ |
@@ -877,7 +903,7 @@ bool create_bmp(struct bitmap *input_bmp, char *target_path) | |||
877 | int r = RGB_UNPACK_RED(color) * (hte - y) / hte * 3 / 5; | 903 | int r = RGB_UNPACK_RED(color) * (hte - y) / hte * 3 / 5; |
878 | int g = RGB_UNPACK_GREEN(color) * (hte - y) / hte * 3 / 5; | 904 | int g = RGB_UNPACK_GREEN(color) * (hte - y) / hte * 3 / 5; |
879 | int b = RGB_UNPACK_BLUE(color) * (hte - y) / hte * 3 / 5; | 905 | int b = RGB_UNPACK_BLUE(color) * (hte - y) / hte * 3 / 5; |
880 | output_bmp_buffer[output_bmp.height + hofs + y + output_bmp.width * x] = | 906 | dst[output_bmp.height + hofs + y + output_bmp.width * x] = |
881 | LCD_RGBPACK(r, g, b); | 907 | LCD_RGBPACK(r, g, b); |
882 | } | 908 | } |
883 | } | 909 | } |
@@ -988,18 +1014,18 @@ void reset_slides(void) | |||
988 | center_slide.slide_index = center_index; | 1014 | center_slide.slide_index = center_index; |
989 | 1015 | ||
990 | int i; | 1016 | int i; |
991 | for (i = 0; i < LEFT_SLIDES_COUNT; i++) { | 1017 | for (i = 0; i < config.show_slides; i++) { |
992 | struct slide_data *si = &left_slides[i]; | 1018 | struct slide_data *si = &left_slides[i]; |
993 | si->angle = itilt; | 1019 | si->angle = itilt; |
994 | si->cx = -(offsetX + spacing * i * PFREAL_ONE); | 1020 | si->cx = -(offsetX + config.spacing_between_slides * i * PFREAL_ONE); |
995 | si->cy = offsetY; | 1021 | si->cy = offsetY; |
996 | si->slide_index = center_index - 1 - i; | 1022 | si->slide_index = center_index - 1 - i; |
997 | } | 1023 | } |
998 | 1024 | ||
999 | for (i = 0; i < RIGHT_SLIDES_COUNT; i++) { | 1025 | for (i = 0; i < config.show_slides; i++) { |
1000 | struct slide_data *si = &right_slides[i]; | 1026 | struct slide_data *si = &right_slides[i]; |
1001 | si->angle = -itilt; | 1027 | si->angle = -itilt; |
1002 | si->cx = offsetX + spacing * i * PFREAL_ONE; | 1028 | si->cx = offsetX + config.spacing_between_slides * i * PFREAL_ONE; |
1003 | si->cy = offsetY; | 1029 | si->cy = offsetY; |
1004 | si->slide_index = center_index + 1 + i; | 1030 | si->slide_index = center_index + 1 + i; |
1005 | } | 1031 | } |
@@ -1023,11 +1049,11 @@ void recalc_table(void) | |||
1023 | 1049 | ||
1024 | itilt = 70 * IANGLE_MAX / 360; /* approx. 70 degrees tilted */ | 1050 | itilt = 70 * IANGLE_MAX / 360; /* approx. 70 degrees tilted */ |
1025 | 1051 | ||
1026 | offsetX = PREFERRED_IMG_WIDTH / 2 * (PFREAL_ONE - fcos(itilt)); | 1052 | offsetX = config.avg_album_width / 2 * (PFREAL_ONE - fcos(itilt)); |
1027 | offsetY = PREFERRED_IMG_HEIGHT / 2 * fsin(itilt); | 1053 | offsetY = config.avg_album_width / 2 * fsin(itilt); |
1028 | offsetX += PREFERRED_IMG_WIDTH * PFREAL_ONE; | 1054 | offsetX += config.avg_album_width * PFREAL_ONE; |
1029 | offsetY += PREFERRED_IMG_HEIGHT * PFREAL_ONE / 4; | 1055 | offsetY += config.avg_album_width * PFREAL_ONE / 4; |
1030 | spacing = 40; | 1056 | offsetX += config.extra_spacing_for_center_slide << PFREAL_SHIFT; |
1031 | } | 1057 | } |
1032 | 1058 | ||
1033 | 1059 | ||
@@ -1236,8 +1262,8 @@ void render(void) | |||
1236 | rb->lcd_set_background(LCD_RGBPACK(0,0,0)); | 1262 | rb->lcd_set_background(LCD_RGBPACK(0,0,0)); |
1237 | rb->lcd_clear_display(); /* TODO: Optimizes this by e.g. invalidating rects */ | 1263 | rb->lcd_clear_display(); /* TODO: Optimizes this by e.g. invalidating rects */ |
1238 | 1264 | ||
1239 | int nleft = LEFT_SLIDES_COUNT; | 1265 | int nleft = config.show_slides; |
1240 | int nright = RIGHT_SLIDES_COUNT; | 1266 | int nright = config.show_slides; |
1241 | 1267 | ||
1242 | struct rect r; | 1268 | struct rect r; |
1243 | render_slide(¢er_slide, &r, 256, -1, -1); | 1269 | render_slide(¢er_slide, &r, 256, -1, -1); |
@@ -1271,6 +1297,7 @@ void render(void) | |||
1271 | } | 1297 | } |
1272 | } | 1298 | } |
1273 | } else { | 1299 | } else { |
1300 | if ( step < 0 ) c1 = BUFFER_WIDTH; | ||
1274 | /* the first and last slide must fade in/fade out */ | 1301 | /* the first and last slide must fade in/fade out */ |
1275 | for (index = 0; index < nleft; index++) { | 1302 | for (index = 0; index < nleft; index++) { |
1276 | int alpha = 256; | 1303 | int alpha = 256; |
@@ -1289,6 +1316,7 @@ void render(void) | |||
1289 | c1 = r.left; | 1316 | c1 = r.left; |
1290 | } | 1317 | } |
1291 | } | 1318 | } |
1319 | if ( step > 0 ) c2 = 0; | ||
1292 | for (index = 0; index < nright; index++) { | 1320 | for (index = 0; index < nright; index++) { |
1293 | int alpha = (index < nright - 2) ? 256 : 128; | 1321 | int alpha = (index < nright - 2) ? 256 : 128; |
1294 | if (index == nright - 1) | 1322 | if (index == nright - 1) |
@@ -1354,9 +1382,9 @@ void update_animation(void) | |||
1354 | center_index = index; | 1382 | center_index = index; |
1355 | slide_frame = index << 16; | 1383 | slide_frame = index << 16; |
1356 | center_slide.slide_index = center_index; | 1384 | center_slide.slide_index = center_index; |
1357 | for (i = 0; i < LEFT_SLIDES_COUNT; i++) | 1385 | for (i = 0; i < config.show_slides; i++) |
1358 | left_slides[i].slide_index = center_index - 1 - i; | 1386 | left_slides[i].slide_index = center_index - 1 - i; |
1359 | for (i = 0; i < RIGHT_SLIDES_COUNT; i++) | 1387 | for (i = 0; i < config.show_slides; i++) |
1360 | right_slides[i].slide_index = center_index + 1 + i; | 1388 | right_slides[i].slide_index = center_index + 1 + i; |
1361 | } | 1389 | } |
1362 | 1390 | ||
@@ -1372,19 +1400,19 @@ void update_animation(void) | |||
1372 | return; | 1400 | return; |
1373 | } | 1401 | } |
1374 | 1402 | ||
1375 | for (i = 0; i < LEFT_SLIDES_COUNT; i++) { | 1403 | for (i = 0; i < config.show_slides; i++) { |
1376 | struct slide_data *si = &left_slides[i]; | 1404 | struct slide_data *si = &left_slides[i]; |
1377 | si->angle = itilt; | 1405 | si->angle = itilt; |
1378 | si->cx = | 1406 | si->cx = |
1379 | -(offsetX + spacing * i * PFREAL_ONE + step * spacing * ftick); | 1407 | -(offsetX + config.spacing_between_slides * i * PFREAL_ONE + step * config.spacing_between_slides * ftick); |
1380 | si->cy = offsetY; | 1408 | si->cy = offsetY; |
1381 | } | 1409 | } |
1382 | 1410 | ||
1383 | for (i = 0; i < RIGHT_SLIDES_COUNT; i++) { | 1411 | for (i = 0; i < config.show_slides; i++) { |
1384 | struct slide_data *si = &right_slides[i]; | 1412 | struct slide_data *si = &right_slides[i]; |
1385 | si->angle = -itilt; | 1413 | si->angle = -itilt; |
1386 | si->cx = | 1414 | si->cx = |
1387 | offsetX + spacing * i * PFREAL_ONE - step * spacing * ftick; | 1415 | offsetX + config.spacing_between_slides * i * PFREAL_ONE - step * config.spacing_between_slides * ftick; |
1388 | si->cy = offsetY; | 1416 | si->cy = offsetY; |
1389 | } | 1417 | } |
1390 | 1418 | ||
@@ -1438,9 +1466,8 @@ int create_empty_slide(bool force) | |||
1438 | input_bmp.width = BMPWIDTH_pictureflow_emptyslide; | 1466 | input_bmp.width = BMPWIDTH_pictureflow_emptyslide; |
1439 | input_bmp.height = BMPHEIGHT_pictureflow_emptyslide; | 1467 | input_bmp.height = BMPHEIGHT_pictureflow_emptyslide; |
1440 | input_bmp.format = FORMAT_NATIVE; | 1468 | input_bmp.format = FORMAT_NATIVE; |
1441 | DEBUGF("The empty slide is %d x %d\n", input_bmp.width, input_bmp.height); | ||
1442 | input_bmp.data = (char*) &pictureflow_emptyslide; | 1469 | input_bmp.data = (char*) &pictureflow_emptyslide; |
1443 | if ( ! create_bmp(&input_bmp, EMPTY_SLIDE) ) return false; | 1470 | if ( ! create_bmp(&input_bmp, EMPTY_SLIDE, true) ) return false; |
1444 | } | 1471 | } |
1445 | 1472 | ||
1446 | empty_slide_hid = read_pfraw( EMPTY_SLIDE ); | 1473 | empty_slide_hid = read_pfraw( EMPTY_SLIDE ); |
@@ -1456,30 +1483,54 @@ int create_empty_slide(bool force) | |||
1456 | int settings_menu(void) { | 1483 | int settings_menu(void) { |
1457 | int selection = 0; | 1484 | int selection = 0; |
1458 | 1485 | ||
1459 | MENUITEM_STRINGLIST(settings_menu,"PictureFlow Settings",NULL,"Show FPS", "Rebuild cache"); | 1486 | MENUITEM_STRINGLIST(settings_menu,"PictureFlow Settings",NULL,"Show FPS", "Spacing", "Center margin", "Number of slides", "Rebuild cache"); |
1460 | 1487 | ||
1461 | selection=rb->do_menu(&settings_menu,&selection); | 1488 | do { |
1462 | switch(selection) { | 1489 | selection=rb->do_menu(&settings_menu,&selection); |
1463 | case 0: | 1490 | switch(selection) { |
1464 | rb->set_bool("Show FPS", &show_fps); | 1491 | case 0: |
1465 | break; | 1492 | rb->set_bool("Show FPS", &show_fps); |
1493 | break; | ||
1466 | 1494 | ||
1467 | case 1: | 1495 | case 1: |
1468 | rb->remove(CACHE_PREFIX "/ready"); | 1496 | rb->set_int("Spacing between slides", "", 1, &(config.spacing_between_slides), |
1469 | rb->remove(EMPTY_SLIDE); | 1497 | NULL, 1, 0, 100, NULL ); |
1470 | rb->splash(HZ, "Cache will be rebuilt on next restart"); | 1498 | recalc_table(); |
1471 | break; | 1499 | reset_slides(); |
1500 | break; | ||
1472 | 1501 | ||
1473 | case MENU_ATTACHED_USB: | 1502 | case 2: |
1474 | return PLUGIN_USB_CONNECTED; | 1503 | rb->set_int("Center margin", "", 1, &(config.extra_spacing_for_center_slide), |
1475 | } | 1504 | NULL, 1, -50, 50, NULL ); |
1505 | recalc_table(); | ||
1506 | reset_slides(); | ||
1507 | break; | ||
1508 | |||
1509 | case 3: | ||
1510 | rb->set_int("Number of slides", "", 1, &(config.show_slides), | ||
1511 | NULL, 1, 1, MAX_SLIDES_COUNT, NULL ); | ||
1512 | recalc_table(); | ||
1513 | reset_slides(); | ||
1514 | break; | ||
1515 | |||
1516 | case 4: | ||
1517 | rb->remove(CACHE_PREFIX "/ready"); | ||
1518 | rb->remove(EMPTY_SLIDE); | ||
1519 | rb->splash(HZ, "Cache will be rebuilt on next restart"); | ||
1520 | break; | ||
1521 | |||
1522 | case MENU_ATTACHED_USB: | ||
1523 | return PLUGIN_USB_CONNECTED; | ||
1524 | } | ||
1525 | } while ( selection >= 0 ); | ||
1476 | return 0; | 1526 | return 0; |
1477 | } | 1527 | } |
1478 | 1528 | ||
1479 | /** | 1529 | /** |
1480 | Show the main menu | 1530 | Show the main menu |
1481 | */ | 1531 | */ |
1482 | int main_menu(void) { | 1532 | int main_menu(void) |
1533 | { | ||
1483 | int selection = 0; | 1534 | int selection = 0; |
1484 | int result; | 1535 | int result; |
1485 | 1536 | ||
@@ -1510,6 +1561,30 @@ int main_menu(void) { | |||
1510 | } | 1561 | } |
1511 | } | 1562 | } |
1512 | 1563 | ||
1564 | bool read_pfconfig(void) | ||
1565 | { | ||
1566 | /* defaults */ | ||
1567 | config.spacing_between_slides = 40; | ||
1568 | config.extra_spacing_for_center_slide = 0; | ||
1569 | config.show_slides = 3; | ||
1570 | int fh = rb->open( CONFIG_FILE, O_RDONLY ); | ||
1571 | if ( fh < 0 ) { /* no config yet */ | ||
1572 | return true; | ||
1573 | } | ||
1574 | int ret = rb->read(fh, &config, sizeof(struct config_data)); | ||
1575 | rb->close(fh); | ||
1576 | return ( ret == sizeof(struct config_data) ); | ||
1577 | } | ||
1578 | |||
1579 | bool write_pfconfig(void) | ||
1580 | { | ||
1581 | int fh = rb->creat( CONFIG_FILE ); | ||
1582 | if( fh < 0 ) return false; | ||
1583 | rb->write( fh, &config, sizeof( struct config_data ) ); | ||
1584 | rb->close( fh ); | ||
1585 | return true; | ||
1586 | } | ||
1587 | |||
1513 | /** | 1588 | /** |
1514 | Main function that also contain the main plasma | 1589 | Main function that also contain the main plasma |
1515 | algorithm. | 1590 | algorithm. |
@@ -1526,13 +1601,13 @@ int main(void) | |||
1526 | } | 1601 | } |
1527 | } | 1602 | } |
1528 | 1603 | ||
1529 | if (!allocate_buffers()) { | 1604 | if (!read_pfconfig()) { |
1530 | rb->splash(HZ, "Could not allocate temporary buffers"); | 1605 | rb->splash(HZ, "Error in config. Please delete " CONFIG_FILE); |
1531 | return PLUGIN_ERROR; | 1606 | return PLUGIN_ERROR; |
1532 | } | 1607 | } |
1533 | 1608 | ||
1534 | if (!create_empty_slide(false)) { | 1609 | if (!allocate_buffers()) { |
1535 | rb->splash(HZ, "Could not load the empty slide"); | 1610 | rb->splash(HZ, "Could not allocate temporary buffers"); |
1536 | return PLUGIN_ERROR; | 1611 | return PLUGIN_ERROR; |
1537 | } | 1612 | } |
1538 | 1613 | ||
@@ -1545,11 +1620,16 @@ int main(void) | |||
1545 | return PLUGIN_ERROR; | 1620 | return PLUGIN_ERROR; |
1546 | } | 1621 | } |
1547 | 1622 | ||
1548 | if (!create_albumart_cache(false)) { | 1623 | if (!create_albumart_cache(config.avg_album_width == 0)) { |
1549 | rb->splash(HZ, "Could not create album art cache"); | 1624 | rb->splash(HZ, "Could not create album art cache"); |
1550 | return PLUGIN_ERROR; | 1625 | return PLUGIN_ERROR; |
1551 | } | 1626 | } |
1552 | 1627 | ||
1628 | if (!create_empty_slide(false)) { | ||
1629 | rb->splash(HZ, "Could not load the empty slide"); | ||
1630 | return PLUGIN_ERROR; | ||
1631 | } | ||
1632 | |||
1553 | if (!free_buffers()) { | 1633 | if (!free_buffers()) { |
1554 | rb->splash(HZ, "Could not free temporary buffers"); | 1634 | rb->splash(HZ, "Could not free temporary buffers"); |
1555 | return PLUGIN_ERROR; | 1635 | return PLUGIN_ERROR; |
@@ -1563,12 +1643,13 @@ int main(void) | |||
1563 | int i; | 1643 | int i; |
1564 | 1644 | ||
1565 | /* initialize */ | 1645 | /* initialize */ |
1566 | for (i = 0; i < SLIDE_CACHE_SIZE; i++) { | 1646 | int min_slide_cache = fmin(number_of_slides, SLIDE_CACHE_SIZE); |
1647 | for (i = 0; i < min_slide_cache; i++) { | ||
1567 | cache[i].hid = -1; | 1648 | cache[i].hid = -1; |
1568 | cache[i].touched = 0; | 1649 | cache[i].touched = 0; |
1569 | slide_cache_stack[i] = SLIDE_CACHE_SIZE-i-1; | 1650 | slide_cache_stack[i] = SLIDE_CACHE_SIZE-i-1; |
1570 | } | 1651 | } |
1571 | slide_cache_stack_index = SLIDE_CACHE_SIZE-2; | 1652 | slide_cache_stack_index = min_slide_cache-1; |
1572 | slide_cache_in_use = 0; | 1653 | slide_cache_in_use = 0; |
1573 | buffer = rb->lcd_framebuffer; | 1654 | buffer = rb->lcd_framebuffer; |
1574 | animation_is_active = false; | 1655 | animation_is_active = false; |
@@ -1676,6 +1757,8 @@ int main(void) | |||
1676 | break; | 1757 | break; |
1677 | } | 1758 | } |
1678 | } | 1759 | } |
1760 | |||
1761 | |||
1679 | } | 1762 | } |
1680 | 1763 | ||
1681 | /*************************** Plugin entry point ****************************/ | 1764 | /*************************** Plugin entry point ****************************/ |
@@ -1692,6 +1775,13 @@ enum plugin_status plugin_start(struct plugin_api *api, void *parameter) | |||
1692 | /* Turn off backlight timeout */ | 1775 | /* Turn off backlight timeout */ |
1693 | backlight_force_on(rb); /* backlight control in lib/helper.c */ | 1776 | backlight_force_on(rb); /* backlight control in lib/helper.c */ |
1694 | ret = main(); | 1777 | ret = main(); |
1778 | if ( ret == PLUGIN_OK ) { | ||
1779 | if (!write_pfconfig()) { | ||
1780 | rb->splash(HZ, "Error writing config."); | ||
1781 | return PLUGIN_ERROR; | ||
1782 | } | ||
1783 | } | ||
1784 | |||
1695 | end_pf_thread(); | 1785 | end_pf_thread(); |
1696 | cleanup(NULL); | 1786 | cleanup(NULL); |
1697 | return ret; | 1787 | return ret; |
diff --git a/apps/plugins/resize_test.c b/apps/plugins/resize_test.c new file mode 100644 index 0000000000..8583613d99 --- /dev/null +++ b/apps/plugins/resize_test.c | |||
@@ -0,0 +1,127 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2007 Jonas Hurrelmann | ||
11 | * | ||
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. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | /* Resizing test plugin. Loads /test.bmp (max 100x100) and displays a resized | ||
21 | * version. Use the scrollwheel or the left/right keys to change the size of | ||
22 | * the resizded version. | ||
23 | */ | ||
24 | |||
25 | #include "plugin.h" | ||
26 | #include "pluginlib_actions.h" | ||
27 | #include "bmp.h" | ||
28 | |||
29 | PLUGIN_HEADER | ||
30 | |||
31 | static struct plugin_api* rb; | ||
32 | |||
33 | const struct button_mapping *plugin_contexts[] | ||
34 | = {generic_actions, generic_directions}; | ||
35 | |||
36 | #define NB_ACTION_CONTEXTS sizeof(plugin_contexts)/sizeof(plugin_contexts[0]) | ||
37 | |||
38 | /* Key assignement */ | ||
39 | #if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \ | ||
40 | || (CONFIG_KEYPAD == IPOD_3G_PAD) \ | ||
41 | || (CONFIG_KEYPAD == IPOD_4G_PAD) \ | ||
42 | || (CONFIG_KEYPAD == SANSA_E200_PAD) | ||
43 | #define SIZE_INCREASE PLA_UP | ||
44 | #define SIZE_INCREASE_REPEAT PLA_UP_REPEAT | ||
45 | #define SIZE_DECREASE PLA_DOWN | ||
46 | #define SIZE_DECREASE_REPEAT PLA_DOWN_REPEAT | ||
47 | #else | ||
48 | #define SIZE_INCREASE PLA_RIGHT | ||
49 | #define SIZE_INCREASE_REPEAT PLA_RIGHT_REPEAT | ||
50 | #define SIZE_DECREASE PLA_LEFT | ||
51 | #define SIZE_DECREASE_REPEAT PLA_LEFT_REPEAT | ||
52 | #endif | ||
53 | #define BUTTON_QUIT PLA_QUIT | ||
54 | |||
55 | #define MAX_OUTPUT_WIDTH 200 | ||
56 | #define MAX_OUTPUT_HEIGHT 200 | ||
57 | |||
58 | static fb_data *b; | ||
59 | |||
60 | static struct bitmap input_bmp; | ||
61 | static struct bitmap output_bmp; | ||
62 | |||
63 | static fb_data input_bmp_data[100*100]; | ||
64 | static fb_data output_bmp_data[MAX_OUTPUT_WIDTH*MAX_OUTPUT_HEIGHT]; | ||
65 | |||
66 | |||
67 | /* this is the plugin entry point */ | ||
68 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | ||
69 | { | ||
70 | (void)parameter; | ||
71 | |||
72 | rb = api; | ||
73 | b = rb->lcd_framebuffer; | ||
74 | |||
75 | rb->lcd_set_background(LCD_RGBPACK(0,0,0)); | ||
76 | rb->lcd_clear_display(); // TODO: Optimizes this by e.g. invalidating rects | ||
77 | |||
78 | input_bmp.data = (char*)input_bmp_data; | ||
79 | output_bmp.data = (char*)output_bmp_data; | ||
80 | |||
81 | int ret = rb->read_bmp_file("/test.bmp", &input_bmp, sizeof(input_bmp_data), | ||
82 | FORMAT_NATIVE); | ||
83 | |||
84 | if (ret < 0) { | ||
85 | rb->splash(HZ, "Could not load /test.bmp"); | ||
86 | return PLUGIN_ERROR; | ||
87 | } | ||
88 | |||
89 | int button; | ||
90 | output_bmp.width = 50; | ||
91 | output_bmp.height = 50; | ||
92 | |||
93 | DEBUGF("input_bmp_data starts at %p\n", input_bmp_data); | ||
94 | DEBUGF("output_bmp_data starts at %p\n", output_bmp_data); | ||
95 | |||
96 | while(1) { | ||
97 | rb->lcd_clear_display(); | ||
98 | rb->lcd_bitmap(input_bmp_data, 0, 0, input_bmp.width, input_bmp.height); | ||
99 | |||
100 | simple_resize_bitmap(&input_bmp, &output_bmp); | ||
101 | |||
102 | rb->lcd_bitmap(output_bmp_data, 0, 100, output_bmp.width, | ||
103 | output_bmp.height); | ||
104 | |||
105 | rb->lcd_update(); | ||
106 | button = pluginlib_getaction(rb, HZ, | ||
107 | plugin_contexts, NB_ACTION_CONTEXTS); | ||
108 | switch (button) { | ||
109 | case BUTTON_QUIT: | ||
110 | return PLUGIN_OK; | ||
111 | case SIZE_INCREASE: | ||
112 | case SIZE_INCREASE_REPEAT: | ||
113 | if (output_bmp.width < MAX_OUTPUT_WIDTH - 2) | ||
114 | output_bmp.width += 2; | ||
115 | if (output_bmp.height < MAX_OUTPUT_HEIGHT - 2) | ||
116 | output_bmp.height += 2; | ||
117 | break; | ||
118 | |||
119 | case SIZE_DECREASE: | ||
120 | case SIZE_DECREASE_REPEAT: | ||
121 | if (output_bmp.width >= 2) output_bmp.width -= 2; | ||
122 | if (output_bmp.height >= 2) output_bmp.height -= 2; | ||
123 | break; | ||
124 | } | ||
125 | } | ||
126 | return PLUGIN_OK; | ||
127 | } | ||