diff options
Diffstat (limited to 'apps/plugins/pictureflow.c')
-rw-r--r-- | apps/plugins/pictureflow.c | 124 |
1 files changed, 95 insertions, 29 deletions
diff --git a/apps/plugins/pictureflow.c b/apps/plugins/pictureflow.c index a4b75b2ace..380070bdd0 100644 --- a/apps/plugins/pictureflow.c +++ b/apps/plugins/pictureflow.c | |||
@@ -37,7 +37,7 @@ PLUGIN_HEADER | |||
37 | static struct plugin_api *rb; /* global api struct pointer */ | 37 | static struct plugin_api *rb; /* global api struct pointer */ |
38 | 38 | ||
39 | const struct button_mapping *plugin_contexts[] | 39 | const struct button_mapping *plugin_contexts[] |
40 | = {generic_directions, generic_actions}; | 40 | = {generic_actions, generic_directions}; |
41 | 41 | ||
42 | #define NB_ACTION_CONTEXTS sizeof(plugin_contexts)/sizeof(plugin_contexts[0]) | 42 | #define NB_ACTION_CONTEXTS sizeof(plugin_contexts)/sizeof(plugin_contexts[0]) |
43 | 43 | ||
@@ -74,8 +74,11 @@ const struct button_mapping *plugin_contexts[] | |||
74 | #define IANGLE_MASK 1023 | 74 | #define IANGLE_MASK 1023 |
75 | 75 | ||
76 | /* maximum size of an slide */ | 76 | /* maximum size of an slide */ |
77 | #define MAX_IMG_WIDTH 100 | 77 | #define MAX_IMG_WIDTH LCD_WIDTH |
78 | #define MAX_IMG_HEIGHT 100 | 78 | #define MAX_IMG_HEIGHT LCD_HEIGHT |
79 | |||
80 | #define PREFERRED_IMG_WIDTH 100 | ||
81 | #define PREFERRED_IMG_HEIGHT 100 | ||
79 | 82 | ||
80 | #define BUFFER_WIDTH LCD_WIDTH | 83 | #define BUFFER_WIDTH LCD_WIDTH |
81 | #define BUFFER_HEIGHT LCD_HEIGHT | 84 | #define BUFFER_HEIGHT LCD_HEIGHT |
@@ -165,7 +168,7 @@ static PFreal offsetY; | |||
165 | static bool show_fps; /* show fps in the main screen */ | 168 | static bool show_fps; /* show fps in the main screen */ |
166 | static int number_of_slides; | 169 | static int number_of_slides; |
167 | 170 | ||
168 | static struct slide_cache cache[SLIDE_CACHE_SIZE+1]; | 171 | static struct slide_cache cache[SLIDE_CACHE_SIZE]; |
169 | static int slide_cache_in_use; | 172 | static int slide_cache_in_use; |
170 | 173 | ||
171 | /* use long for aligning */ | 174 | /* use long for aligning */ |
@@ -188,8 +191,10 @@ static struct album_data album[MAX_ALBUMS]; | |||
188 | static char album_names[MAX_ALBUMS*AVG_ALBUM_NAME_LENGTH]; | 191 | static char album_names[MAX_ALBUMS*AVG_ALBUM_NAME_LENGTH]; |
189 | static int album_count; | 192 | static int album_count; |
190 | 193 | ||
191 | static fb_data input_bmp_buffer[MAX_IMG_WIDTH * MAX_IMG_HEIGHT]; /* static buffer for reading the bitmaps */ | 194 | static fb_data *input_bmp_buffer; |
192 | static fb_data output_bmp_buffer[MAX_IMG_WIDTH * MAX_IMG_HEIGHT * 2]; /* static buffer for reading the bitmaps */ | 195 | static fb_data *output_bmp_buffer; |
196 | static int input_hid; | ||
197 | static int output_hid; | ||
193 | 198 | ||
194 | static bool thread_is_running; | 199 | static bool thread_is_running; |
195 | 200 | ||
@@ -449,7 +454,7 @@ bool get_albumart_for_index_from_db(int slide_index, char *buf, int buflen) | |||
449 | if ( rb->tagcache_get_next(&tcs) ) { | 454 | if ( rb->tagcache_get_next(&tcs) ) { |
450 | struct mp3entry id3; | 455 | struct mp3entry id3; |
451 | char size[9]; | 456 | char size[9]; |
452 | rb->snprintf(size, sizeof(size), ".%dx%d", MAX_IMG_WIDTH, MAX_IMG_HEIGHT); | 457 | rb->snprintf(size, sizeof(size), ".%dx%d", PREFERRED_IMG_WIDTH, PREFERRED_IMG_HEIGHT); |
453 | rb->strncpy( (char*)&id3.path, tcs.result, MAX_PATH ); | 458 | rb->strncpy( (char*)&id3.path, tcs.result, MAX_PATH ); |
454 | id3.album = get_album_name(slide_index); | 459 | id3.album = get_album_name(slide_index); |
455 | if ( rb->search_albumart_files(&id3, size, buf, buflen) ) | 460 | if ( rb->search_albumart_files(&id3, size, buf, buflen) ) |
@@ -504,15 +509,52 @@ void draw_progressbar(int step) | |||
504 | rb->lcd_set_foreground(LCD_RGBPACK(165, 231, 82)); | 509 | rb->lcd_set_foreground(LCD_RGBPACK(165, 231, 82)); |
505 | 510 | ||
506 | rb->lcd_fillrect(x+1, y+1, step * w / album_count, bar_height-2); | 511 | rb->lcd_fillrect(x+1, y+1, step * w / album_count, bar_height-2); |
512 | rb->lcd_set_foreground(LCD_RGBPACK(255,255,255)); | ||
507 | rb->lcd_update(); | 513 | rb->lcd_update(); |
508 | rb->yield(); | 514 | rb->yield(); |
509 | } | 515 | } |
510 | 516 | ||
517 | bool allocate_buffers(void) | ||
518 | { | ||
519 | int input_size = MAX_IMG_WIDTH * MAX_IMG_HEIGHT * sizeof( fb_data ); | ||
520 | int output_size = MAX_IMG_WIDTH * MAX_IMG_HEIGHT * sizeof( fb_data ) * 2; | ||
521 | |||
522 | input_hid = rb->bufalloc(NULL, input_size, TYPE_BITMAP); | ||
523 | |||
524 | if (input_hid < 0) | ||
525 | return false; | ||
526 | |||
527 | if (rb->bufgetdata(input_hid, 0, (void *)&input_bmp_buffer) < input_size) { | ||
528 | rb->bufclose(input_hid); | ||
529 | return false; | ||
530 | } | ||
531 | |||
532 | output_hid = rb->bufalloc(NULL, output_size, TYPE_BITMAP); | ||
533 | |||
534 | if (output_hid < 0) { | ||
535 | rb->bufclose(input_hid); | ||
536 | return false; | ||
537 | } | ||
538 | |||
539 | if (rb->bufgetdata(output_hid, 0, (void *)&output_bmp_buffer) < output_size) { | ||
540 | rb->bufclose(output_hid); | ||
541 | return false; | ||
542 | } | ||
543 | return true; | ||
544 | } | ||
545 | |||
546 | |||
547 | bool free_buffers(void) | ||
548 | { | ||
549 | rb->bufclose(input_hid); | ||
550 | rb->bufclose(output_hid); | ||
551 | return true; | ||
552 | } | ||
511 | 553 | ||
512 | /** | 554 | /** |
513 | Precomupte the album art images and store them in CACHE_PREFIX. | 555 | Precomupte the album art images and store them in CACHE_PREFIX. |
514 | */ | 556 | */ |
515 | bool create_albumart_cache(void) | 557 | bool create_albumart_cache(bool force) |
516 | { | 558 | { |
517 | /* FIXME: currently we check for the file CACHE_PREFIX/ready | 559 | /* FIXME: currently we check for the file CACHE_PREFIX/ready |
518 | We need a real menu etc. to recreate cache. For now, delete | 560 | We need a real menu etc. to recreate cache. For now, delete |
@@ -520,10 +562,11 @@ bool create_albumart_cache(void) | |||
520 | 562 | ||
521 | number_of_slides = album_count; | 563 | number_of_slides = album_count; |
522 | 564 | ||
523 | if ( rb->file_exists( CACHE_PREFIX "/ready" ) ) return true; | 565 | if ( ! force && rb->file_exists( CACHE_PREFIX "/ready" ) ) return true; |
524 | 566 | ||
525 | int i; | 567 | int i; |
526 | struct bitmap input_bmp; | 568 | struct bitmap input_bmp; |
569 | |||
527 | for (i=0; i < album_count; i++) | 570 | for (i=0; i < album_count; i++) |
528 | { | 571 | { |
529 | draw_progressbar(i); | 572 | draw_progressbar(i); |
@@ -531,17 +574,23 @@ bool create_albumart_cache(void) | |||
531 | continue; | 574 | continue; |
532 | 575 | ||
533 | int ret; | 576 | int ret; |
534 | input_bmp.data = (char *) &input_bmp_buffer; | 577 | input_bmp.data = (char *)input_bmp_buffer; |
535 | ret = rb->read_bmp_file(tmp_path_name, &input_bmp, sizeof(input_bmp_buffer), FORMAT_NATIVE); | 578 | ret = rb->read_bmp_file(tmp_path_name, &input_bmp, |
536 | if (ret <= 0) continue; /* skip missing/broken files */ | 579 | sizeof(fb_data)*MAX_IMG_WIDTH*MAX_IMG_HEIGHT, |
580 | FORMAT_NATIVE); | ||
581 | if (ret <= 0) { | ||
582 | rb->splash(HZ, "couldn't read bmp"); | ||
583 | continue; /* skip missing/broken files */ | ||
584 | } | ||
537 | 585 | ||
538 | rb->snprintf(tmp_path_name, sizeof(tmp_path_name), CACHE_PREFIX "/%d.pfraw", i); | 586 | rb->snprintf(tmp_path_name, sizeof(tmp_path_name), CACHE_PREFIX "/%d.pfraw", i); |
539 | create_bmp(&input_bmp, tmp_path_name); | 587 | if (!create_bmp(&input_bmp, tmp_path_name)) { |
588 | rb->splash(HZ, "couldn't write bmp"); | ||
589 | } | ||
540 | if ( rb->button_get(false) == PICTUREFLOW_MENU ) return false; | 590 | if ( rb->button_get(false) == PICTUREFLOW_MENU ) return false; |
541 | } | 591 | } |
542 | int fh = rb->creat( CACHE_PREFIX "/ready" ); | 592 | int fh = rb->creat( CACHE_PREFIX "/ready" ); |
543 | rb->close(fh); | 593 | rb->close(fh); |
544 | |||
545 | return true; | 594 | return true; |
546 | } | 595 | } |
547 | 596 | ||
@@ -720,13 +769,13 @@ bool create_pf_thread(void) | |||
720 | /** | 769 | /** |
721 | Safe the given bitmap as filename in the pfraw format | 770 | Safe the given bitmap as filename in the pfraw format |
722 | */ | 771 | */ |
723 | int save_pfraw(char* filename, struct bitmap *bm) | 772 | bool save_pfraw(char* filename, struct bitmap *bm) |
724 | { | 773 | { |
725 | struct pfraw_header bmph; | 774 | struct pfraw_header bmph; |
726 | bmph.width = bm->width; | 775 | bmph.width = bm->width; |
727 | bmph.height = bm->height; | 776 | bmph.height = bm->height; |
728 | int fh = rb->creat( filename ); | 777 | int fh = rb->creat( filename ); |
729 | if( fh < 0 ) return -1; | 778 | if( fh < 0 ) return false; |
730 | rb->write( fh, &bmph, sizeof( struct pfraw_header ) ); | 779 | rb->write( fh, &bmph, sizeof( struct pfraw_header ) ); |
731 | int y; | 780 | int y; |
732 | for( y = 0; y < bm->height; y++ ) | 781 | for( y = 0; y < bm->height; y++ ) |
@@ -735,7 +784,7 @@ int save_pfraw(char* filename, struct bitmap *bm) | |||
735 | rb->write( fh, d, sizeof( fb_data ) * bm->width ); | 784 | rb->write( fh, d, sizeof( fb_data ) * bm->width ); |
736 | } | 785 | } |
737 | rb->close( fh ); | 786 | rb->close( fh ); |
738 | return 0; | 787 | return true; |
739 | } | 788 | } |
740 | 789 | ||
741 | 790 | ||
@@ -789,7 +838,7 @@ bool create_bmp(struct bitmap *input_bmp, char *target_path) | |||
789 | output_bmp.width = input_bmp->width * 2; | 838 | output_bmp.width = input_bmp->width * 2; |
790 | output_bmp.height = input_bmp->height; | 839 | output_bmp.height = input_bmp->height; |
791 | output_bmp.format = input_bmp->format; | 840 | output_bmp.format = input_bmp->format; |
792 | output_bmp.data = (char*) &output_bmp_buffer; | 841 | output_bmp.data = (char *)output_bmp_buffer; |
793 | 842 | ||
794 | /* transpose the image, this is to speed-up the rendering | 843 | /* transpose the image, this is to speed-up the rendering |
795 | because we process one column at a time | 844 | because we process one column at a time |
@@ -815,8 +864,7 @@ bool create_bmp(struct bitmap *input_bmp, char *target_path) | |||
815 | LCD_RGBPACK(r, g, b); | 864 | LCD_RGBPACK(r, g, b); |
816 | } | 865 | } |
817 | } | 866 | } |
818 | save_pfraw(target_path, &output_bmp); | 867 | return save_pfraw(target_path, &output_bmp); |
819 | return true; | ||
820 | } | 868 | } |
821 | 869 | ||
822 | 870 | ||
@@ -826,6 +874,7 @@ bool create_bmp(struct bitmap *input_bmp, char *target_path) | |||
826 | static bool load_and_prepare_surface(int slide_index, int cache_index) | 874 | static bool load_and_prepare_surface(int slide_index, int cache_index) |
827 | { | 875 | { |
828 | rb->snprintf(tmp_path_name, sizeof(tmp_path_name), CACHE_PREFIX "/%d.pfraw", slide_index); | 876 | rb->snprintf(tmp_path_name, sizeof(tmp_path_name), CACHE_PREFIX "/%d.pfraw", slide_index); |
877 | |||
829 | int hid = read_pfraw(tmp_path_name); | 878 | int hid = read_pfraw(tmp_path_name); |
830 | if (hid < 0) | 879 | if (hid < 0) |
831 | return false; | 880 | return false; |
@@ -957,10 +1006,10 @@ void recalc_table(void) | |||
957 | 1006 | ||
958 | itilt = 70 * IANGLE_MAX / 360; /* approx. 70 degrees tilted */ | 1007 | itilt = 70 * IANGLE_MAX / 360; /* approx. 70 degrees tilted */ |
959 | 1008 | ||
960 | offsetX = MAX_IMG_WIDTH / 2 * (PFREAL_ONE - fcos(itilt)); | 1009 | offsetX = PREFERRED_IMG_WIDTH / 2 * (PFREAL_ONE - fcos(itilt)); |
961 | offsetY = MAX_IMG_WIDTH / 2 * fsin(itilt); | 1010 | offsetY = PREFERRED_IMG_HEIGHT / 2 * fsin(itilt); |
962 | offsetX += MAX_IMG_WIDTH * PFREAL_ONE; | 1011 | offsetX += PREFERRED_IMG_WIDTH * PFREAL_ONE; |
963 | offsetY += MAX_IMG_WIDTH * PFREAL_ONE / 4; | 1012 | offsetY += PREFERRED_IMG_HEIGHT * PFREAL_ONE / 4; |
964 | spacing = 40; | 1013 | spacing = 40; |
965 | } | 1014 | } |
966 | 1015 | ||
@@ -1365,9 +1414,9 @@ void cleanup(void *parameter) | |||
1365 | } | 1414 | } |
1366 | 1415 | ||
1367 | 1416 | ||
1368 | int create_empty_slide(void) | 1417 | int create_empty_slide(bool force) |
1369 | { | 1418 | { |
1370 | if ( ! rb->file_exists( EMPTY_SLIDE ) ) { | 1419 | if ( force || ! rb->file_exists( EMPTY_SLIDE ) ) { |
1371 | struct bitmap input_bmp; | 1420 | struct bitmap input_bmp; |
1372 | input_bmp.width = BMPWIDTH_pictureflow_emptyslide; | 1421 | input_bmp.width = BMPWIDTH_pictureflow_emptyslide; |
1373 | input_bmp.height = BMPHEIGHT_pictureflow_emptyslide; | 1422 | input_bmp.height = BMPHEIGHT_pictureflow_emptyslide; |
@@ -1383,13 +1432,14 @@ int create_empty_slide(void) | |||
1383 | return true; | 1432 | return true; |
1384 | } | 1433 | } |
1385 | 1434 | ||
1435 | |||
1386 | /** | 1436 | /** |
1387 | Shows the settings menu | 1437 | Shows the settings menu |
1388 | */ | 1438 | */ |
1389 | int settings_menu(void) { | 1439 | int settings_menu(void) { |
1390 | int selection = 0; | 1440 | int selection = 0; |
1391 | 1441 | ||
1392 | MENUITEM_STRINGLIST(settings_menu,"PictureFlow Settings",NULL,"Show FPS"); | 1442 | MENUITEM_STRINGLIST(settings_menu,"PictureFlow Settings",NULL,"Show FPS", "Rebuild cache"); |
1393 | 1443 | ||
1394 | selection=rb->do_menu(&settings_menu,&selection); | 1444 | selection=rb->do_menu(&settings_menu,&selection); |
1395 | switch(selection) { | 1445 | switch(selection) { |
@@ -1397,6 +1447,12 @@ int settings_menu(void) { | |||
1397 | rb->set_bool("Show FPS", &show_fps); | 1447 | rb->set_bool("Show FPS", &show_fps); |
1398 | break; | 1448 | break; |
1399 | 1449 | ||
1450 | case 1: | ||
1451 | rb->remove(CACHE_PREFIX "/ready"); | ||
1452 | rb->remove(EMPTY_SLIDE); | ||
1453 | rb->splash(HZ, "Cache will be rebuilt on next restart"); | ||
1454 | break; | ||
1455 | |||
1400 | case MENU_ATTACHED_USB: | 1456 | case MENU_ATTACHED_USB: |
1401 | return PLUGIN_USB_CONNECTED; | 1457 | return PLUGIN_USB_CONNECTED; |
1402 | } | 1458 | } |
@@ -1450,7 +1506,12 @@ int main(void) | |||
1450 | } | 1506 | } |
1451 | } | 1507 | } |
1452 | 1508 | ||
1453 | if (!create_empty_slide()) { | 1509 | if (!allocate_buffers()) { |
1510 | rb->splash(HZ, "Could allocate temporary buffers"); | ||
1511 | return PLUGIN_ERROR; | ||
1512 | } | ||
1513 | |||
1514 | if (!create_empty_slide(false)) { | ||
1454 | rb->splash(HZ, "Could not load the empty slide"); | 1515 | rb->splash(HZ, "Could not load the empty slide"); |
1455 | return PLUGIN_ERROR; | 1516 | return PLUGIN_ERROR; |
1456 | } | 1517 | } |
@@ -1460,11 +1521,16 @@ int main(void) | |||
1460 | return PLUGIN_ERROR; | 1521 | return PLUGIN_ERROR; |
1461 | } | 1522 | } |
1462 | 1523 | ||
1463 | if (!create_albumart_cache()) { | 1524 | if (!create_albumart_cache(false)) { |
1464 | rb->splash(HZ, "Could not create album art cache"); | 1525 | rb->splash(HZ, "Could not create album art cache"); |
1465 | return PLUGIN_ERROR; | 1526 | return PLUGIN_ERROR; |
1466 | } | 1527 | } |
1467 | 1528 | ||
1529 | if (!free_buffers()) { | ||
1530 | rb->splash(HZ, "Could note free temporary buffers"); | ||
1531 | return PLUGIN_ERROR; | ||
1532 | } | ||
1533 | |||
1468 | if (!create_pf_thread()) { | 1534 | if (!create_pf_thread()) { |
1469 | rb->splash(HZ, "Cannot create thread!"); | 1535 | rb->splash(HZ, "Cannot create thread!"); |
1470 | return PLUGIN_ERROR; | 1536 | return PLUGIN_ERROR; |