summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Pennequin <nicolas.pennequin@free.fr>2007-12-11 18:54:50 +0000
committerNicolas Pennequin <nicolas.pennequin@free.fr>2007-12-11 18:54:50 +0000
commita7d08774dccec1b078ff953be57ac7b5b19bf7e3 (patch)
tree2668af5668fc80d92eafcc8defe787ec496ba7c1
parent303cf259d99b66c9c2d21e476f6ca77b99ef0743 (diff)
downloadrockbox-a7d08774dccec1b078ff953be57ac7b5b19bf7e3.tar.gz
rockbox-a7d08774dccec1b078ff953be57ac7b5b19bf7e3.zip
PictureFlow fixes and improvements:
* Reduced popping effect (FS#8303) * Scale the empty slide to average album width * Introduced some visual settings * Fix FS#8298 but make the criteria a screen height of less than 100 px so that only the c200 gets 50x50 slides The scaling code is added as a lib function with a basic test plugin that's not compiled by default. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15913 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/bitmaps/native/SOURCES2
-rw-r--r--apps/plugins/lib/bmp.c33
-rw-r--r--apps/plugins/lib/bmp.h6
-rw-r--r--apps/plugins/pictureflow.c220
-rw-r--r--apps/plugins/resize_test.c127
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*/
90void 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 */
28int save_bmp_file( char* filename, struct bitmap *bm, struct plugin_api* rb ); 28int 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*/
34void 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 160struct 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 */
162static PFreal rays[BUFFER_WIDTH]; 170static PFreal rays[BUFFER_WIDTH];
163static bool animation_is_active; /* an animation is currently running */ 171static bool animation_is_active; /* an animation is currently running */
164static struct slide_data center_slide; 172static struct slide_data center_slide;
165static struct slide_data left_slides[LEFT_SLIDES_COUNT]; 173static struct slide_data left_slides[MAX_SLIDES_COUNT];
166static struct slide_data right_slides[RIGHT_SLIDES_COUNT]; 174static struct slide_data right_slides[MAX_SLIDES_COUNT];
167static int slide_frame; 175static int slide_frame;
168static int step; 176static int step;
169static int target; 177static int target;
170static int fade; 178static int fade;
171static int center_index; /* index of the slide that is in the center */ 179static int center_index; /* index of the slide that is in the center */
172static int itilt; 180static int itilt;
173static int spacing; /* spacing between slides */
174static int zoom; 181static int zoom;
175static PFreal offsetX; 182static PFreal offsetX;
176static PFreal offsetY; 183static PFreal offsetY;
@@ -204,6 +211,7 @@ static fb_data *input_bmp_buffer;
204static fb_data *output_bmp_buffer; 211static fb_data *output_bmp_buffer;
205static int input_hid; 212static int input_hid;
206static int output_hid; 213static int output_hid;
214static struct config_data config;
207 215
208static bool thread_is_running; 216static bool thread_is_running;
209 217
@@ -343,7 +351,7 @@ PFreal sinTable[] = { /* 10 */
343/** code */ 351/** code */
344 352
345 353
346bool create_bmp(struct bitmap* input_bmp, char *target_path); 354bool create_bmp(struct bitmap* input_bmp, char *target_path, bool resize);
347int load_surface(int); 355int 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
389inline PFreal fsin(int iangle) 398inline PFreal fsin(int iangle)
390{ 399{
391 while (iangle < 0) 400 while (iangle < 0)
@@ -569,15 +578,12 @@ bool free_buffers(void)
569 */ 578 */
570bool create_albumart_cache(bool force) 579bool 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 */
850bool create_bmp(struct bitmap *input_bmp, char *target_path) 863bool 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(&center_slide, &r, 256, -1, -1); 1269 render_slide(&center_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)
1456int settings_menu(void) { 1483int 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 */
1482int main_menu(void) { 1532int 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
1564bool 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
1579bool 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
29PLUGIN_HEADER
30
31static struct plugin_api* rb;
32
33const 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
58static fb_data *b;
59
60static struct bitmap input_bmp;
61static struct bitmap output_bmp;
62
63static fb_data input_bmp_data[100*100];
64static fb_data output_bmp_data[MAX_OUTPUT_WIDTH*MAX_OUTPUT_HEIGHT];
65
66
67/* this is the plugin entry point */
68enum 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}