Index: apps/plugins/png/SOURCES =================================================================== --- apps/plugins/png/SOURCES (revision 24098) +++ apps/plugins/png/SOURCES (working copy) @@ -1,3 +1,4 @@ +png_ui.c adler32.c crc32_png.c inffast.c Index: apps/plugins/png/png_ui.c =================================================================== --- apps/plugins/png/png_ui.c (revision 0) +++ apps/plugins/png/png_ui.c (revision 0) @@ -0,0 +1,28 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: png.c 24093 2009-12-21 15:20:33Z teru $id $ + * + * Copyright (C) 2009 by Christophe Gouiran + * + * Based on lodepng, a lightweight png decoder/encoder + * (c) 2005-2008 Lode Vandevenne + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#define PNG_VIEWER +#define MENU_TITLE "Png Menu" + +#include "../imageviewer_ui/imageviewer_ui.c" Index: apps/plugins/png/inflate.c =================================================================== --- apps/plugins/png/inflate.c (revision 24098) +++ apps/plugins/png/inflate.c (working copy) @@ -1132,7 +1132,7 @@ return Z_STREAM_ERROR; } //DEBUGF("%d / %d\n", strm->total_in, strm->avail_in); - if (rb->button_get(false) == PNG_MENU) + if (rb->button_get(false) == IMGVIEW_MENU) return PLUGIN_ABORT; else cb_progress(insize - strm->avail_in, insize); } Index: apps/plugins/png/png.c =================================================================== --- apps/plugins/png/png.c (revision 24098) +++ apps/plugins/png/png.c (working copy) @@ -54,16 +54,10 @@ #include "plugin.h" #include "lcd.h" -#include -#include -#include -#include #include #include "zlib.h" #include "png.h" -PLUGIN_HEADER - /* ////////////////////////////////////////////////////////////////////////// */ /* LodeFlate & LodeZlib Setting structs */ /* ////////////////////////////////////////////////////////////////////////// */ @@ -140,26 +134,10 @@ LodePNG_InfoPng infoPng; /*info of the PNG image obtained after decoding*/ long error; char error_msg[128]; - int x,y; - int width,height; } LodePNG_Decoder; #define VERSION_STRING "20080927" -/* Min memory allowing us to use the plugin buffer - * and thus not stopping the music - * *Very* rough estimation: - * Max 10 000 dir entries * 4bytes/entry (char **) = 40000 bytes - * + 30k code size = 70 000 - * + 50k min for png = 130 000 - */ -#define MIN_MEM 130000 - -/* Headings */ -#define DIR_PREV 1 -#define DIR_NEXT -1 -#define DIR_NONE 0 - /* decompressed image in the possible sizes (1,2,4,8), wasting the other */ static fb_data *disp[9]; /* up to here currently used by image(s) */ @@ -180,63 +158,8 @@ static unsigned char *decoded_image; /* the decoded image */ static size_t decoded_image_size; -static fb_data *resized_image; /* the decoded image */ +static LodePNG_Decoder _decoder; -static struct tree_context *tree; - -/* the current full file name */ -static char np_file[MAX_PATH]; -static int curfile = 0, direction = DIR_NONE, entries = 0; - -static LodePNG_Decoder decoder; - -/* list of the png files */ -static char **file_pt; -#if PLUGIN_BUFFER_SIZE >= MIN_MEM -/* are we using the plugin buffer or the audio buffer? */ -static bool plug_buf = true; -#endif - -/* Persistent configuration */ -#define PNG_CONFIGFILE "png.cfg" -#define PNG_SETTINGS_MINVERSION 1 -#define PNG_SETTINGS_VERSION 1 - -/* Slideshow times */ -#define SS_MIN_TIMEOUT 1 -#define SS_MAX_TIMEOUT 20 -#define SS_DEFAULT_TIMEOUT 5 - -struct png_settings -{ - int ss_timeout; -}; - -static struct png_settings png_settings = - { - SS_DEFAULT_TIMEOUT - }; -static struct png_settings old_settings; - -static struct configdata png_config[] = - { - { TYPE_INT, SS_MIN_TIMEOUT, SS_MAX_TIMEOUT, - { .int_p = &png_settings.ss_timeout }, "Slideshow Time", NULL - }, - }; - -#if LCD_DEPTH > 1 -static fb_data* old_backdrop; -#endif - -static int slideshow_enabled = false; /* run slideshow */ -static int running_slideshow = false; /* loading image because of slideshw */ -#ifndef SIMULATOR -static int immediate_ata_off = false; /* power down disk after loading */ -#endif - -static unsigned ds, ds_min, ds_max; /* downscaling and limits */ - /* The two functions below (LodePNG_decompress and LodePNG_compress) directly call the LodeZlib_decompress and LodeZlib_compress functions. The only purpose of the functions @@ -1263,7 +1186,7 @@ if (!decoder->error) { unsigned char *scanlines = idat + idat_size; - size_t scanlines_size = (size_t)memory_max - idat_size + 1; + size_t scanlines_size = (size_t)memory_max - idat_size; long time = *rb->current_tick; decoder->error = LodePNG_decompress(scanlines, &scanlines_size, idat, idat_size, decoder->error_msg); /*decompress with the Zlib decompressor*/ if (pf_progress) pf_progress(100, 100); @@ -1273,7 +1196,7 @@ { decoded_image_size = (decoder->infoPng.height * decoder->infoPng.width * LodePNG_InfoColor_getBpp(&decoder->infoPng.color) + 7) / 8; if (decoded_image_size > memory_size) { decoder->error = OUT_OF_MEMORY; return; } - decoded_image = memory_max - decoded_image_size + 1; + decoded_image = memory_max - decoded_image_size; if (scanlines + scanlines_size >= decoded_image) { decoder->error = OUT_OF_MEMORY; return; } memset(decoded_image, 0, decoded_image_size * sizeof(unsigned char)); if (!running_slideshow) @@ -1373,7 +1296,7 @@ "invalid pHYs chunk size", /*74*/ }; -bool png_ext(const char ext[]) +bool img_ext(const char ext[]) { if (!ext) return false; @@ -1383,437 +1306,37 @@ return false; } -/*Read directory contents for scrolling. */ -void get_pic_list(void) +void draw_image_rect(struct imageviewer_info *info, + int x, int y, int width, int height) { - int i; - struct entry *dircache; - char *pname; - tree = rb->tree_get_context(); - dircache = tree->dircache; - - file_pt = (char **) memory; - - /* Remove path and leave only the name.*/ - pname = rb->strrchr(np_file,'/'); - pname++; - - for (i = 0; i < tree->filesindir; i++) - { - if (!(dircache[i].attr & ATTR_DIRECTORY) - && png_ext(rb->strrchr(dircache[i].name, '.'))) - { - file_pt[entries] = dircache[i].name; - /* Set Selected File. */ - if (!rb->strcmp(file_pt[entries], pname)) - curfile = entries; - entries++; - } - } - - memory += (entries * sizeof(char**)); - memory_size -= (entries * sizeof(char**)); + rb->lcd_bitmap_part(*((fb_data**)info->data), info->x + x, info->y + y, info->width, + x + MAX(0, (LCD_WIDTH-info->width)/2), + y + MAX(0, (LCD_HEIGHT-info->height)/2), + width, height); } -int change_filename(int direct) +int img_mem(struct imageviewer_info *info, int ds) { - bool file_erased = (file_pt[curfile] == NULL); - direction = direct; - - curfile += (direct == DIR_PREV? entries - 1: 1); - if (curfile >= entries) - curfile -= entries; - - if (file_erased) - { - /* remove 'erased' file names from list. */ - int count, i; - for (count = i = 0; i < entries; i++) - { - if (curfile == i) - curfile = count; - if (file_pt[i] != NULL) - file_pt[count++] = file_pt[i]; - } - entries = count; - } - - if (entries == 0) - { - rb->splash(HZ, "No supported files"); - return PLUGIN_ERROR; - } - - if (rb->strlen(tree->currdir) > 1) - { - rb->strcpy(np_file, tree->currdir); - rb->strcat(np_file, "/"); - } - else - rb->strcpy(np_file, tree->currdir); - - rb->strcat(np_file, file_pt[curfile]); - - return PLUGIN_OTHER; -} - -/* switch off overlay, for handling SYS_ events */ -void cleanup(void *parameter) -{ - (void)parameter; -} - -#define VSCROLL (LCD_HEIGHT/8) -#define HSCROLL (LCD_WIDTH/10) - -#define ZOOM_IN 100 /* return codes for below function */ -#define ZOOM_OUT 101 - -int show_menu(void) /* return 1 to quit */ -{ -#if LCD_DEPTH > 1 - rb->lcd_set_backdrop(old_backdrop); -#ifdef HAVE_LCD_COLOR - rb->lcd_set_foreground(rb->global_settings->fg_color); - rb->lcd_set_background(rb->global_settings->bg_color); -#else - rb->lcd_set_foreground(LCD_BLACK); - rb->lcd_set_background(LCD_WHITE); -#endif -#endif - int result; - - enum menu_id - { - MIID_RETURN = 0, - MIID_TOGGLE_SS_MODE, - MIID_CHANGE_SS_MODE, -#if PLUGIN_BUFFER_SIZE >= MIN_MEM - MIID_SHOW_PLAYBACK_MENU, -#endif - MIID_QUIT, - }; - - MENUITEM_STRINGLIST(menu, "Png Menu", NULL, - "Return", "Toggle Slideshow Mode", - "Change Slideshow Time", -#if PLUGIN_BUFFER_SIZE >= MIN_MEM - "Show Playback Menu", -#endif - "Quit"); - - static const struct opt_items slideshow[2] = { - { "Disable", -1 }, - { "Enable", -1 }, - }; - - result=rb->do_menu(&menu, NULL, NULL, false); - - switch (result) - { - case MIID_RETURN: - break; - case MIID_TOGGLE_SS_MODE: - rb->set_option("Toggle Slideshow", &slideshow_enabled, INT, - slideshow , 2, NULL); - break; - case MIID_CHANGE_SS_MODE: - rb->set_int("Slideshow Time", "s", UNIT_SEC, - &png_settings.ss_timeout, NULL, 1, - SS_MIN_TIMEOUT, SS_MAX_TIMEOUT, NULL); - break; -#if PLUGIN_BUFFER_SIZE >= MIN_MEM - case MIID_SHOW_PLAYBACK_MENU: - if (plug_buf) - { - playback_control(NULL); - } - else - { - rb->splash(HZ, "Cannot restart playback"); - } - break; -#endif - case MIID_QUIT: - return 1; - break; - } - -#if !defined(SIMULATOR) && defined(HAVE_DISK_STORAGE) - /* change ata spindown time based on slideshow time setting */ - immediate_ata_off = false; - rb->storage_spindown(rb->global_settings->disk_spindown); - - if (slideshow_enabled) - { - if (png_settings.ss_timeout < 10) - { - /* slideshow times < 10s keep disk spinning */ - rb->storage_spindown(0); - } - else if (!rb->mp3_is_playing()) - { - /* slideshow times > 10s and not playing: ata_off after load */ - immediate_ata_off = true; - } - } -#endif -#if LCD_DEPTH > 1 - rb->lcd_set_backdrop(NULL); - rb->lcd_set_foreground(LCD_WHITE); - rb->lcd_set_background(LCD_BLACK); -#endif - rb->lcd_clear_display(); - return 0; -} - -void draw_image(struct LodePNG_Decoder* decoder) -{ - rb->lcd_bitmap_part(resized_image, decoder->x, decoder->y, decoder->width, - MAX(0, (LCD_WIDTH - decoder->width) / 2), - MAX(0, (LCD_HEIGHT - decoder->height) / 2), - decoder->width - decoder->x, - decoder->height - decoder->y); -} - -/* Pan the viewing window right - move image to the left and fill in - the right-hand side */ -static void pan_view_right(struct LodePNG_Decoder* decoder) -{ - int move; - - move = MIN(HSCROLL, decoder->width - decoder->x - LCD_WIDTH); - if (move > 0) - { - decoder->x += move; - draw_image(decoder); - rb->lcd_update(); - } -} - -/* Pan the viewing window left - move image to the right and fill in - the left-hand side */ -static void pan_view_left(struct LodePNG_Decoder* decoder) -{ - int move; - - move = MIN(HSCROLL, decoder->x); - if (move > 0) - { - decoder->x -= move; - draw_image(decoder); - rb->lcd_update(); - } -} - - -/* Pan the viewing window up - move image down and fill in - the top */ -static void pan_view_up(struct LodePNG_Decoder* decoder) -{ - int move; - - move = MIN(VSCROLL, decoder->y); - if (move > 0) - { - decoder->y -= move; - draw_image(decoder); - rb->lcd_update(); - } -} - -/* Pan the viewing window down - move image up and fill in - the bottom */ -static void pan_view_down(struct LodePNG_Decoder* decoder) -{ - int move; - - move = MIN(VSCROLL, decoder->height - decoder->y - LCD_HEIGHT); - if (move > 0) - { - decoder->y += move; - draw_image(decoder); - rb->lcd_update(); - } -} - -/* interactively scroll around the image */ -int scroll_bmp(struct LodePNG_Decoder* decoder) -{ - int button; - int lastbutton = 0; - - while (true) - { - if (slideshow_enabled) - button = rb->button_get_w_tmo(png_settings.ss_timeout * HZ); - else - button = rb->button_get(true); - - running_slideshow = false; - - switch (button) - { - case PNG_LEFT: - if (entries > 1 && decoder->width <= LCD_WIDTH - && decoder->height <= LCD_HEIGHT) - return change_filename(DIR_PREV); - case PNG_LEFT | BUTTON_REPEAT: - pan_view_left(decoder); - break; - - case PNG_RIGHT: - if (entries > 1 && decoder->width <= LCD_WIDTH - && decoder->height <= LCD_HEIGHT) - return change_filename(DIR_NEXT); - case PNG_RIGHT | BUTTON_REPEAT: - pan_view_right(decoder); - break; - - case PNG_UP: - case PNG_UP | BUTTON_REPEAT: - pan_view_up(decoder); - break; - - case PNG_DOWN: - case PNG_DOWN | BUTTON_REPEAT: - pan_view_down(decoder); - break; - - case BUTTON_NONE: - if (!slideshow_enabled) - break; - running_slideshow = true; - if (entries > 1) - return change_filename(DIR_NEXT); - break; - -#ifdef PNG_SLIDE_SHOW - case PNG_SLIDE_SHOW: - slideshow_enabled = !slideshow_enabled; - running_slideshow = slideshow_enabled; - break; -#endif - -#ifdef PNG_NEXT_REPEAT - case PNG_NEXT_REPEAT: -#endif - case PNG_NEXT: - if (entries > 1) - return change_filename(DIR_NEXT); - break; - -#ifdef PNG_PREVIOUS_REPEAT - case PNG_PREVIOUS_REPEAT: -#endif - case PNG_PREVIOUS: - if (entries > 1) - return change_filename(DIR_PREV); - break; - - case PNG_ZOOM_IN: -#ifdef PNG_ZOOM_PRE - if (lastbutton != PNG_ZOOM_PRE) - break; -#endif - return ZOOM_IN; - break; - - case PNG_ZOOM_OUT: -#ifdef PNG_ZOOM_PRE - if (lastbutton != PNG_ZOOM_PRE) - break; -#endif - return ZOOM_OUT; - break; - -#ifdef PNG_RC_MENU - case PNG_RC_MENU: -#endif - case PNG_MENU: - - if (show_menu() == 1) - return PLUGIN_OK; - - draw_image(decoder); - rb->lcd_update(); - - break; - default: - if (rb->default_event_handler_ex(button, cleanup, NULL) - == SYS_USB_CONNECTED) - return PLUGIN_USB_CONNECTED; - break; - - } /* switch */ - - if (button != BUTTON_NONE) - lastbutton = button; - } /* while (true) */ -} - -/* callback updating a progress meter while PNG decoding */ -void cb_progress(int current, int total) -{ - - if (current & 1) rb->yield(); /* be nice to the other threads */ - if (!running_slideshow) - { - rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN], - 0, LCD_HEIGHT-8, LCD_WIDTH, 8, - total, 0, current, HORIZONTAL); - rb->lcd_update_rect(0, LCD_HEIGHT-8, LCD_WIDTH, 8); - } - else - { - /* in slideshow mode, keep gui interference to a minimum */ - rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN], - 0, LCD_HEIGHT-4, LCD_WIDTH, 4, - total, 0, current, HORIZONTAL); - rb->lcd_update_rect(0, LCD_HEIGHT-4, LCD_WIDTH, 4); - } -} - -int pngmem(struct LodePNG_Decoder* decoder, int ds) -{ + LodePNG_Decoder *decoder = &_decoder; + if(info == NULL) return 0; return (decoder->infoPng.width/ds) * (decoder->infoPng.height/ds) * FB_DATA_SZ; } -/* how far can we zoom in without running out of memory */ -int min_downscale(struct LodePNG_Decoder* decoder, int bufsize) +int load_image(char *filename, struct imageviewer_info *info, + unsigned char *buf, ssize_t *buf_size) { - int downscale = 8; - - if (pngmem(decoder, 8) > bufsize) - return 0; /* error, too large, even 1:8 doesn't fit */ - - while (downscale > 1 && pngmem(decoder, downscale/2) <= bufsize) - downscale /= 2; - - return downscale; -} - -/* how far can we zoom out, to fit image into the LCD */ -unsigned max_downscale(struct LodePNG_Decoder* decoder) -{ - unsigned downscale = 1; - - while (downscale < 8 && (decoder->infoPng.width/downscale > LCD_WIDTH - || decoder->infoPng.height/downscale > LCD_HEIGHT)) - { - downscale *= 2; - } - - return downscale; -} - -/* load image from filename. */ -int load_image(char* filename, struct LodePNG_Decoder* decoder) -{ int fd; long time = 0; /* measured ticks */ int w, h; /* used to center output */ + LodePNG_Decoder *decoder = &_decoder; + memset(&disp, 0, sizeof(disp)); + LodePNG_Decoder_init(decoder); + + memory = buf; + memory_size = *buf_size; + memory_max = memory + memory_size; + fd = rb->open(filename, O_RDONLY); if (fd < 0) { @@ -1847,7 +1370,7 @@ rb->lcd_update(); } - image = memory_max - image_size + 1; + image = memory_max - image_size; rb->read(fd, image, image_size); rb->close(fd); @@ -1939,21 +1462,28 @@ else return PLUGIN_ERROR; } + + disp_buf = (fb_data *)((intptr_t)(converted_image + converted_image_size + 3) & ~3); + info->x_size = decoder->infoPng.width; + info->y_size = decoder->infoPng.height; + *buf_size = memory_max - (unsigned char*)disp_buf; return PLUGIN_OK; } -/* return decoded or cached image */ -fb_data *get_image(struct LodePNG_Decoder* decoder, int ds) +int get_image(struct imageviewer_info *info, int ds) { - fb_data * p_disp = disp[ds]; /* short cut */ + fb_data **p_disp = &disp[ds]; /* short cut */ + LodePNG_Decoder *decoder = &_decoder; - decoder->width = decoder->infoPng.width / ds; - decoder->height = decoder->infoPng.height / ds; + info->width = decoder->infoPng.width / ds; + info->height = decoder->infoPng.height / ds; + info->data = p_disp; - if (p_disp != NULL) + if (*p_disp != NULL) { + /* we still have it */ DEBUGF("Found an image in cache\n"); - return p_disp; /* we still have it */ + return PLUGIN_OK; } /* assign image buffer */ @@ -1961,13 +1491,13 @@ if (!running_slideshow) { rb->snprintf(print, sizeof(print), "resizing %d*%d", - decoder->width, decoder->height); + info->width, info->height); rb->lcd_puts(0, 3, print); rb->lcd_update(); } struct bitmap bmp_src, bmp_dst; - int size = decoder->width * decoder->height; + int size = info->width * info->height; if ((unsigned char *)(disp_buf + size) >= memory_max) { /* have to discard the current */ @@ -1978,16 +1508,16 @@ disp_buf = (fb_data *)((intptr_t)(converted_image + converted_image_size + 3) & ~3); } - disp[ds] = disp_buf; - disp_buf = (fb_data *)((intptr_t)(disp[ds] + size + 3) & ~3); + *p_disp = disp_buf; + disp_buf = (fb_data *)((intptr_t)(disp_buf + size + 3) & ~3); bmp_src.width = decoder->infoPng.width; bmp_src.height = decoder->infoPng.height; bmp_src.data = (unsigned char *)converted_image; - bmp_dst.width = decoder->width; - bmp_dst.height = decoder->height; - bmp_dst.data = (unsigned char *)disp[ds]; + bmp_dst.width = info->width; + bmp_dst.height = info->height; + bmp_dst.data = (unsigned char *)*p_disp; #ifdef HAVE_ADJUSTABLE_CPU_FREQ rb->cpu_boost(true); smooth_resize_bitmap(&bmp_src, &bmp_dst); @@ -1996,276 +1526,8 @@ smooth_resize_bitmap(&bmp_src, &bmp_dst); #endif /*HAVE_ADJUSTABLE_CPU_FREQ*/ } else { - disp[ds] = converted_image; - return converted_image; + *p_disp = converted_image; } - return disp[ds]; + return PLUGIN_OK; } - -/* set the view to the given center point, limit if necessary */ -void set_view (struct LodePNG_Decoder* decoder, int cx, int cy) -{ - int x, y; - - /* plain center to available width/height */ - x = cx - MIN(LCD_WIDTH, decoder->width) / 2; - y = cy - MIN(LCD_HEIGHT, decoder->height) / 2; - - /* limit against upper image size */ - x = MIN(decoder->width - LCD_WIDTH, x); - y = MIN(decoder->height - LCD_HEIGHT, y); - - /* limit against negative side */ - x = MAX(0, x); - y = MAX(0, y); - - decoder->x = x; /* set the values */ - decoder->y = y; -} - -/* calculate the view center based on the bitmap position */ -void get_view(struct LodePNG_Decoder* decoder, int* p_cx, int* p_cy) -{ - *p_cx = decoder->x + MIN(LCD_WIDTH, decoder->width) / 2; - *p_cy = decoder->y + MIN(LCD_HEIGHT, decoder->height) / 2; -} - -/* load, decode, display the image */ -int load_and_show(char* filename) -{ - int status; - int cx=0, cy=0; /* view center */ - -#if LCD_DEPTH > 1 - rb->lcd_set_foreground(LCD_WHITE); - rb->lcd_set_background(LCD_BLACK); - rb->lcd_set_backdrop(NULL); -#endif - rb->lcd_clear_display(); - - memset(&disp, 0, sizeof(disp)); - LodePNG_Decoder_init(&decoder); - - if (rb->button_get(false) == PNG_MENU) - status = PLUGIN_ABORT; - else - status = load_image(filename, &decoder); - - if (status == PLUGIN_OUTOFMEM) - { -#if PLUGIN_BUFFER_SIZE >= MIN_MEM - if (plug_buf) - { - rb->lcd_setfont(FONT_SYSFIXED); - rb->lcd_clear_display(); - rb->snprintf(print,sizeof(print),"%s:",rb->strrchr(filename,'/')+1); - rb->lcd_puts(0,0,print); - rb->lcd_puts(0,1,"Not enough plugin memory!"); - rb->lcd_puts(0,2,"Zoom In: Stop playback."); - if (entries>1) - rb->lcd_puts(0,3,"Left/Right: Skip File."); - rb->lcd_puts(0,4,"Show Menu: Quit."); - rb->lcd_update(); - rb->lcd_setfont(FONT_UI); - - rb->button_clear_queue(); - - while (1) - { - int button = rb->button_get(true); - switch (button) - { - case PNG_ZOOM_IN: - plug_buf = false; - memory = rb->plugin_get_audio_buffer((size_t *)&memory_size); - memory_max = memory + memory_size - 1; - /*try again this file, now using the audio buffer */ - return PLUGIN_OTHER; -#ifdef PNG_RC_MENU - case PNG_RC_MENU: -#endif - case PNG_MENU: - return PLUGIN_OK; - - case PNG_LEFT: - if (entries>1) - { - rb->lcd_clear_display(); - return change_filename(DIR_PREV); - } - break; - - case PNG_RIGHT: - if (entries>1) - { - rb->lcd_clear_display(); - return change_filename(DIR_NEXT); - } - break; - default: - if (rb->default_event_handler_ex(button, cleanup, NULL) - == SYS_USB_CONNECTED) - return PLUGIN_USB_CONNECTED; - - } - } - } - else -#endif - { - rb->splash(HZ, "Out of Memory"); - file_pt[curfile] = NULL; - return change_filename(direction); - } - } - else if (status == PLUGIN_ERROR) - { - file_pt[curfile] = NULL; - return change_filename(direction); - } - else if (status == PLUGIN_ABORT) { - rb->splash(HZ, "aborted"); - return PLUGIN_OK; - } - - disp_buf = (fb_data *)((intptr_t)(converted_image + converted_image_size + 3) & ~3); - ds_max = max_downscale(&decoder); /* check display constraint */ - ds_min = min_downscale(&decoder, memory_max - (unsigned char*)disp_buf); /* check memory constraint */ - if (ds_min == 0) { - /* Can not resize the image */ - ds_min = ds_max = 1; - } else if (ds_max < ds_min) { - ds_max = ds_min; - } - - ds = ds_max; /* initialize setting */ - cx = decoder.infoPng.width/ds/2; /* center the view */ - cy = decoder.infoPng.height/ds/2; - - do { - resized_image = get_image(&decoder, ds); /* decode or fetch from cache */ - - set_view(&decoder, cx, cy); - - if (!running_slideshow) - { - rb->snprintf(print, sizeof(print), "showing %dx%d", - decoder.width, decoder.height); - rb->lcd_puts(0, 3, print); - rb->lcd_update(); - } - - rb->lcd_clear_display(); - draw_image(&decoder); - rb->lcd_update(); - - /* drawing is now finished, play around with scrolling - * until you press OFF or connect USB - */ - while (1) - { - status = scroll_bmp(&decoder); - if (status == ZOOM_IN) - { - if (ds > 1) - { - /* as 1/1 is always available, jump ds to 1 if ds is ds_min. */ - int zoom = (ds == ds_min)? ds_min: 2; - ds /= zoom; /* reduce downscaling to zoom in */ - get_view(&decoder, &cx, &cy); - cx *= zoom; /* prepare the position in the new image */ - cy *= zoom; - } - else - continue; - } - - if (status == ZOOM_OUT) - { - if (ds < ds_max) - { - /* if ds is 1 and ds_min is greater than 1, jump ds to ds_min. */ - int zoom = (ds < ds_min)? ds_min: 2; - ds *= zoom; /* increase downscaling to zoom out */ - get_view(&decoder, &cx, &cy); - cx /= zoom; /* prepare the position in the new image */ - cy /= zoom; - } - else - continue; - } - break; - } - rb->lcd_clear_display(); - } - while (status != PLUGIN_OK && status != PLUGIN_USB_CONNECTED - && status != PLUGIN_OTHER); - - return status; -} - -/******************** Plugin entry point *********************/ - -enum plugin_status plugin_start(const void* parameter) -{ - int condition; -#if LCD_DEPTH > 1 - old_backdrop = rb->lcd_get_backdrop(); -#endif - - if (!parameter) return PLUGIN_ERROR; - -#if PLUGIN_BUFFER_SIZE >= MIN_MEM - memory = rb->plugin_get_buffer((size_t *)&memory_size); -#else - memory = rb->plugin_get_audio_buffer((size_t *)&memory_size); -#endif - - rb->strcpy(np_file, parameter); - get_pic_list(); - - if (!entries) return PLUGIN_ERROR; - -#if (PLUGIN_BUFFER_SIZE >= MIN_MEM) && !defined(SIMULATOR) - if (!rb->audio_status()) { - plug_buf = false; - memory = rb->plugin_get_audio_buffer((size_t *)&memory_size); - } -#endif - - memory_max = memory + memory_size - 1; - - /* should be ok to just load settings since the plugin itself has - just been loaded from disk and the drive should be spinning */ - configfile_load(PNG_CONFIGFILE, png_config, - ARRAYLEN(png_config), PNG_SETTINGS_MINVERSION); - old_settings = png_settings; - - /* Turn off backlight timeout */ - backlight_force_on(); /* backlight control in lib/helper.c */ - - do - { - condition = load_and_show(np_file); - } while (condition != PLUGIN_OK && condition != PLUGIN_USB_CONNECTED - && condition != PLUGIN_ERROR); - - if (rb->memcmp(&png_settings, &old_settings, sizeof (png_settings))) - { - /* Just in case drive has to spin, keep it from looking locked */ - rb->splash(0, "Saving Settings"); - configfile_save(PNG_CONFIGFILE, png_config, - ARRAYLEN(png_config), PNG_SETTINGS_VERSION); - } - -#if !defined(SIMULATOR) && defined(HAVE_DISK_STORAGE) - /* set back ata spindown time in case we changed it */ - rb->storage_spindown(rb->global_settings->disk_spindown); -#endif - - /* Turn on backlight timeout (revert to settings) */ - backlight_use_settings(); /* backlight control in lib/helper.c */ - - return condition; -} Index: apps/plugins/png/png.h =================================================================== --- apps/plugins/png/png.h (revision 24098) +++ apps/plugins/png/png.h (working copy) @@ -22,345 +22,8 @@ * ****************************************************************************/ -/* -LodePNG version 20080927 +#include "../imageviewer_ui/imageviewer_ui.h" -Copyright (c) 2005-2008 Lode Vandevenne - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*/ - -/* -The manual and changelog can be found in the header file "lodepng.h" -You are free to name this file lodepng.cpp or lodepng.c depending on your usage. -*/ - -/* variable button definitions */ -#if CONFIG_KEYPAD == RECORDER_PAD -#define PNG_ZOOM_IN BUTTON_PLAY -#define PNG_ZOOM_OUT BUTTON_ON -#define PNG_UP BUTTON_UP -#define PNG_DOWN BUTTON_DOWN -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#define PNG_NEXT BUTTON_F3 -#define PNG_PREVIOUS BUTTON_F2 -#define PNG_MENU BUTTON_OFF - -#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD -#define PNG_ZOOM_IN BUTTON_SELECT -#define PNG_ZOOM_OUT BUTTON_ON -#define PNG_UP BUTTON_UP -#define PNG_DOWN BUTTON_DOWN -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#define PNG_NEXT BUTTON_F3 -#define PNG_PREVIOUS BUTTON_F2 -#define PNG_MENU BUTTON_OFF - -#elif CONFIG_KEYPAD == ONDIO_PAD -#define PNG_ZOOM_PRE BUTTON_MENU -#define PNG_ZOOM_IN (BUTTON_MENU | BUTTON_REL) -#define PNG_ZOOM_OUT (BUTTON_MENU | BUTTON_DOWN) -#define PNG_UP BUTTON_UP -#define PNG_DOWN BUTTON_DOWN -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#define PNG_NEXT (BUTTON_MENU | BUTTON_RIGHT) -#define PNG_PREVIOUS (BUTTON_MENU | BUTTON_LEFT) -#define PNG_MENU BUTTON_OFF - -#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ - (CONFIG_KEYPAD == IRIVER_H300_PAD) -#define PNG_ZOOM_IN BUTTON_SELECT -#define PNG_ZOOM_OUT BUTTON_MODE -#define PNG_UP BUTTON_UP -#define PNG_DOWN BUTTON_DOWN -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#if (CONFIG_KEYPAD == IRIVER_H100_PAD) -#define PNG_NEXT BUTTON_ON -#define PNG_PREVIOUS BUTTON_REC -#else -#define PNG_NEXT BUTTON_REC -#define PNG_PREVIOUS BUTTON_ON -#endif -#define PNG_MENU BUTTON_OFF -#define PNG_RC_MENU BUTTON_RC_STOP - -#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \ - (CONFIG_KEYPAD == IPOD_1G2G_PAD) -#define PNG_ZOOM_IN BUTTON_SCROLL_FWD -#define PNG_ZOOM_OUT BUTTON_SCROLL_BACK -#define PNG_UP BUTTON_MENU -#define PNG_DOWN BUTTON_PLAY -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#define PNG_MENU (BUTTON_SELECT | BUTTON_MENU) -#define PNG_NEXT (BUTTON_SELECT | BUTTON_RIGHT) -#define PNG_PREVIOUS (BUTTON_SELECT | BUTTON_LEFT) - -#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD -#define PNG_ZOOM_PRE BUTTON_SELECT -#define PNG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) -#define PNG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) -#define PNG_UP BUTTON_UP -#define PNG_DOWN BUTTON_DOWN -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#define PNG_MENU BUTTON_POWER -#define PNG_NEXT BUTTON_PLAY -#define PNG_PREVIOUS BUTTON_REC - -#elif CONFIG_KEYPAD == GIGABEAT_PAD -#define PNG_ZOOM_IN BUTTON_VOL_UP -#define PNG_ZOOM_OUT BUTTON_VOL_DOWN -#define PNG_UP BUTTON_UP -#define PNG_DOWN BUTTON_DOWN -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#define PNG_MENU BUTTON_MENU -#define PNG_NEXT (BUTTON_A | BUTTON_RIGHT) -#define PNG_PREVIOUS (BUTTON_A | BUTTON_LEFT) - -#elif CONFIG_KEYPAD == SANSA_E200_PAD -#define PNG_ZOOM_PRE BUTTON_SELECT -#define PNG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) -#define PNG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) -#define PNG_UP BUTTON_UP -#define PNG_DOWN BUTTON_DOWN -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#define PNG_MENU BUTTON_POWER -#define PNG_SLIDE_SHOW BUTTON_REC -#define PNG_NEXT BUTTON_SCROLL_FWD -#define PNG_NEXT_REPEAT (BUTTON_SCROLL_FWD|BUTTON_REPEAT) -#define PNG_PREVIOUS BUTTON_SCROLL_BACK -#define PNG_PREVIOUS_REPEAT (BUTTON_SCROLL_BACK|BUTTON_REPEAT) - -#elif CONFIG_KEYPAD == SANSA_FUZE_PAD -#define PNG_ZOOM_PRE BUTTON_SELECT -#define PNG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) -#define PNG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) -#define PNG_UP BUTTON_UP -#define PNG_DOWN BUTTON_DOWN -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#define PNG_MENU (BUTTON_HOME|BUTTON_REPEAT) -#define PNG_NEXT BUTTON_SCROLL_FWD -#define PNG_NEXT_REPEAT (BUTTON_SCROLL_FWD|BUTTON_REPEAT) -#define PNG_PREVIOUS BUTTON_SCROLL_BACK -#define PNG_PREVIOUS_REPEAT (BUTTON_SCROLL_BACK|BUTTON_REPEAT) - -#elif CONFIG_KEYPAD == SANSA_C200_PAD -#define PNG_ZOOM_PRE BUTTON_SELECT -#define PNG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) -#define PNG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) -#define PNG_UP BUTTON_UP -#define PNG_DOWN BUTTON_DOWN -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#define PNG_MENU BUTTON_POWER -#define PNG_SLIDE_SHOW BUTTON_REC -#define PNG_NEXT BUTTON_VOL_UP -#define PNG_NEXT_REPEAT (BUTTON_VOL_UP|BUTTON_REPEAT) -#define PNG_PREVIOUS BUTTON_VOL_DOWN -#define PNG_PREVIOUS_REPEAT (BUTTON_VOL_DOWN|BUTTON_REPEAT) - -#elif CONFIG_KEYPAD == SANSA_CLIP_PAD -#define PNG_ZOOM_PRE BUTTON_SELECT -#define PNG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) -#define PNG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) -#define PNG_UP BUTTON_UP -#define PNG_DOWN BUTTON_DOWN -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#define PNG_MENU BUTTON_POWER -#define PNG_SLIDE_SHOW BUTTON_HOME -#define PNG_NEXT BUTTON_VOL_UP -#define PNG_NEXT_REPEAT (BUTTON_VOL_UP|BUTTON_REPEAT) -#define PNG_PREVIOUS BUTTON_VOL_DOWN -#define PNG_PREVIOUS_REPEAT (BUTTON_VOL_DOWN|BUTTON_REPEAT) - -#elif CONFIG_KEYPAD == SANSA_M200_PAD -#define PNG_ZOOM_PRE BUTTON_SELECT -#define PNG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) -#define PNG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) -#define PNG_UP BUTTON_UP -#define PNG_DOWN BUTTON_DOWN -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#define PNG_MENU BUTTON_POWER -#define PNG_SLIDE_SHOW (BUTTON_SELECT | BUTTON_UP) -#define PNG_NEXT BUTTON_VOL_UP -#define PNG_NEXT_REPEAT (BUTTON_VOL_UP|BUTTON_REPEAT) -#define PNG_PREVIOUS BUTTON_VOL_DOWN -#define PNG_PREVIOUS_REPEAT (BUTTON_VOL_DOWN|BUTTON_REPEAT) - -#elif CONFIG_KEYPAD == IRIVER_H10_PAD -#define PNG_ZOOM_PRE BUTTON_PLAY -#define PNG_ZOOM_IN (BUTTON_PLAY | BUTTON_REL) -#define PNG_ZOOM_OUT (BUTTON_PLAY | BUTTON_REPEAT) -#define PNG_UP BUTTON_SCROLL_UP -#define PNG_DOWN BUTTON_SCROLL_DOWN -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#define PNG_MENU BUTTON_POWER -#define PNG_NEXT BUTTON_FF -#define PNG_PREVIOUS BUTTON_REW - -#elif CONFIG_KEYPAD == MROBE500_PAD - -#elif CONFIG_KEYPAD == GIGABEAT_S_PAD -#define PNG_ZOOM_IN BUTTON_VOL_UP -#define PNG_ZOOM_OUT BUTTON_VOL_DOWN -#define PNG_UP BUTTON_UP -#define PNG_DOWN BUTTON_DOWN -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#define PNG_MENU BUTTON_MENU -#define PNG_NEXT BUTTON_NEXT -#define PNG_PREVIOUS BUTTON_PREV - -#elif CONFIG_KEYPAD == MROBE100_PAD -#define PNG_ZOOM_IN BUTTON_SELECT -#define PNG_ZOOM_OUT BUTTON_PLAY -#define PNG_UP BUTTON_UP -#define PNG_DOWN BUTTON_DOWN -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#define PNG_MENU BUTTON_MENU -#define PNG_NEXT (BUTTON_DISPLAY | BUTTON_RIGHT) -#define PNG_PREVIOUS (BUTTON_DISPLAY | BUTTON_LEFT) - -#elif CONFIG_KEYPAD == IAUDIO_M3_PAD -#define PNG_ZOOM_PRE BUTTON_RC_PLAY -#define PNG_ZOOM_IN (BUTTON_RC_PLAY|BUTTON_REL) -#define PNG_ZOOM_OUT (BUTTON_RC_PLAY|BUTTON_REPEAT) -#define PNG_UP BUTTON_RC_VOL_UP -#define PNG_DOWN BUTTON_RC_VOL_DOWN -#define PNG_LEFT BUTTON_RC_REW -#define PNG_RIGHT BUTTON_RC_FF -#define PNG_MENU BUTTON_RC_REC -#define PNG_NEXT BUTTON_RC_MODE -#define PNG_PREVIOUS BUTTON_RC_MENU - -#elif CONFIG_KEYPAD == COWON_D2_PAD - -#elif CONFIG_KEYPAD == IAUDIO67_PAD -#define PNG_ZOOM_IN BUTTON_VOLUP -#define PNG_ZOOM_OUT BUTTON_VOLDOWN -#define PNG_UP BUTTON_STOP -#define PNG_DOWN BUTTON_PLAY -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#define PNG_MENU BUTTON_MENU -#define PNG_NEXT (BUTTON_PLAY|BUTTON_VOLUP) -#define PNG_PREVIOUS (BUTTON_PLAY|BUTTON_VOLDOWN) - -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD - -#define PNG_ZOOM_IN BUTTON_PLAY -#define PNG_ZOOM_OUT BUTTON_CUSTOM -#define PNG_UP BUTTON_UP -#define PNG_DOWN BUTTON_DOWN -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#define PNG_MENU BUTTON_MENU -#define PNG_NEXT BUTTON_SELECT -#define PNG_PREVIOUS BUTTON_BACK - -#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD -#define PNG_ZOOM_IN BUTTON_VOL_UP -#define PNG_ZOOM_OUT BUTTON_VOL_DOWN -#define PNG_UP BUTTON_UP -#define PNG_DOWN BUTTON_DOWN -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#define PNG_MENU BUTTON_MENU -#define PNG_NEXT BUTTON_VIEW -#define PNG_PREVIOUS BUTTON_PLAYLIST - -#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD -#define PNG_ZOOM_IN BUTTON_VOL_UP -#define PNG_ZOOM_OUT BUTTON_VOL_DOWN -#define PNG_UP BUTTON_UP -#define PNG_DOWN BUTTON_DOWN -#define PNG_LEFT BUTTON_PREV -#define PNG_RIGHT BUTTON_NEXT -#define PNG_MENU BUTTON_MENU -#define PNG_NEXT BUTTON_RIGHT -#define PNG_PREVIOUS BUTTON_LEFT - -#elif CONFIG_KEYPAD == ONDAVX747_PAD -#define PNG_MENU BUTTON_POWER -#elif CONFIG_KEYPAD == ONDAVX777_PAD -#define PNG_MENU BUTTON_POWER - -#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD -#define PNG_ZOOM_IN (BUTTON_PLAY|BUTTON_UP) -#define PNG_ZOOM_OUT (BUTTON_PLAY|BUTTON_DOWN) -#define PNG_UP BUTTON_UP -#define PNG_DOWN BUTTON_DOWN -#define PNG_LEFT BUTTON_LEFT -#define PNG_RIGHT BUTTON_RIGHT -#define PNG_MENU BUTTON_PLAY -#define PNG_NEXT BUTTON_FFWD -#define PNG_PREVIOUS BUTTON_REW - -#else -#error No keymap defined! -#endif - -#ifdef HAVE_TOUCHSCREEN -#ifndef PNG_UP -#define PNG_UP BUTTON_TOPMIDDLE -#endif -#ifndef PNG_DOWN -#define PNG_DOWN BUTTON_BOTTOMMIDDLE -#endif -#ifndef PNG_LEFT -#define PNG_LEFT BUTTON_MIDLEFT -#endif -#ifndef PNG_RIGHT -#define PNG_RIGHT BUTTON_MIDRIGHT -#endif -#ifndef PNG_ZOOM_IN -#define PNG_ZOOM_IN BUTTON_TOPRIGHT -#endif -#ifndef PNG_ZOOM_OUT -#define PNG_ZOOM_OUT BUTTON_TOPLEFT -#endif -#ifndef PNG_MENU -#define PNG_MENU (BUTTON_CENTER|BUTTON_REL) -#endif -#ifndef PNG_NEXT -#define PNG_NEXT BUTTON_BOTTOMRIGHT -#endif -#ifndef PNG_PREVIOUS -#define PNG_PREVIOUS BUTTON_BOTTOMLEFT -#endif -#endif - -#define PLUGIN_OTHER 10 /* State code for output with return. */ -#define PLUGIN_ABORT 11 -#define PLUGIN_OUTOFMEM 12 #define OUT_OF_MEMORY 9900 #define FILE_TOO_LARGE 9910 + Index: apps/plugins/jpeg/SOURCES =================================================================== --- apps/plugins/jpeg/SOURCES (revision 24098) +++ apps/plugins/jpeg/SOURCES (working copy) @@ -1,3 +1,4 @@ +jpeg_ui.c jpeg.c jpeg_decoder.c #ifdef HAVE_LCD_COLOR Index: apps/plugins/jpeg/jpeg_ui.c =================================================================== --- apps/plugins/jpeg/jpeg_ui.c (revision 0) +++ apps/plugins/jpeg/jpeg_ui.c (revision 0) @@ -0,0 +1,28 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: png.c 24093 2009-12-21 15:20:33Z teru $id $ + * + * Copyright (C) 2009 by Christophe Gouiran + * + * Based on lodepng, a lightweight png decoder/encoder + * (c) 2005-2008 Lode Vandevenne + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#define JPEG_VIEWER +#define MENU_TITLE "Jpeg Menu" + +#include "../imageviewer_ui/imageviewer_ui.c" Index: apps/plugins/jpeg/jpeg.c =================================================================== --- apps/plugins/jpeg/jpeg.c (revision 24098) +++ apps/plugins/jpeg/jpeg.c (working copy) @@ -26,9 +26,6 @@ ****************************************************************************/ #include "plugin.h" -#include -#include -#include #include #include @@ -36,105 +33,12 @@ #include "jpeg.h" #include "jpeg_decoder.h" -PLUGIN_HEADER - #ifdef HAVE_LCD_COLOR #include "yuv2rgb.h" #endif -/* different graphics libraries */ -#if LCD_DEPTH < 8 -#define USEGSLIB -GREY_INFO_STRUCT -#define MYLCD(fn) grey_ub_ ## fn -#define MYLCD_UPDATE() -#define MYXLCD(fn) grey_ub_ ## fn -#else -#define MYLCD(fn) rb->lcd_ ## fn -#define MYLCD_UPDATE() rb->lcd_update(); -#define MYXLCD(fn) xlcd_ ## fn -#endif - -/* Min memory allowing us to use the plugin buffer - * and thus not stopping the music - * *Very* rough estimation: - * Max 10 000 dir entries * 4bytes/entry (char **) = 40000 bytes - * + 20k code size = 60 000 - * + 50k min for jpeg = 120 000 - */ -#define MIN_MEM 120000 - -/* Headings */ -#define DIR_PREV 1 -#define DIR_NEXT -1 -#define DIR_NONE 0 - -#define PLUGIN_OTHER 10 /* State code for output with return. */ -#define PLUGIN_ABORT 11 -#define PLUGIN_OUTOFMEM 12 - -/******************************* Globals ***********************************/ - -static int slideshow_enabled = false; /* run slideshow */ -static int running_slideshow = false; /* loading image because of slideshw */ -#ifndef SIMULATOR -static int immediate_ata_off = false; /* power down disk after loading */ -#endif - -#ifdef HAVE_LCD_COLOR -fb_data rgb_linebuf[LCD_WIDTH]; /* Line buffer for scrolling when - DITHER_DIFFUSION is set */ -#endif - - -/* Persistent configuration */ -#define JPEG_CONFIGFILE "jpeg.cfg" -#define JPEG_SETTINGS_MINVERSION 1 -#define JPEG_SETTINGS_VERSION 2 - -/* Slideshow times */ -#define SS_MIN_TIMEOUT 1 -#define SS_MAX_TIMEOUT 20 -#define SS_DEFAULT_TIMEOUT 5 - -struct jpeg_settings -{ -#ifdef HAVE_LCD_COLOR - int colour_mode; - int dither_mode; -#endif - int ss_timeout; -}; - -static struct jpeg_settings jpeg_settings = -{ -#ifdef HAVE_LCD_COLOR - COLOURMODE_COLOUR, - DITHER_NONE, -#endif - SS_DEFAULT_TIMEOUT -}; -static struct jpeg_settings old_settings; - -static struct configdata jpeg_config[] = -{ -#ifdef HAVE_LCD_COLOR - { TYPE_ENUM, 0, COLOUR_NUM_MODES, { .int_p = &jpeg_settings.colour_mode }, - "Colour Mode", (char *[]){ "Colour", "Grayscale" } }, - { TYPE_ENUM, 0, DITHER_NUM_MODES, { .int_p = &jpeg_settings.dither_mode }, - "Dither Mode", (char *[]){ "None", "Ordered", "Diffusion" } }, -#endif - { TYPE_INT, SS_MIN_TIMEOUT, SS_MAX_TIMEOUT, - { .int_p = &jpeg_settings.ss_timeout }, "Slideshow Time", NULL }, -}; - -#if LCD_DEPTH > 1 -static fb_data* old_backdrop; -#endif - /**************** begin Application ********************/ - /************************* Types ***************************/ struct t_disp @@ -145,10 +49,7 @@ #else unsigned char* bitmap[1]; /* Y only */ #endif - int width; - int height; int stride; - int x, y; }; /************************* Globals ***************************/ @@ -158,9 +59,6 @@ /* my memory pool (from the mp3 buffer) */ static char print[32]; /* use a common snprintf() buffer */ -/* the remaining free part of the buffer for compressed+uncompressed images */ -static unsigned char* buf; -static ssize_t buf_size; /* the root of the images, hereafter are decompresed ones */ static unsigned char* buf_root; @@ -170,26 +68,11 @@ static unsigned char* buf_images; static ssize_t buf_images_size; -static int ds, ds_min, ds_max; /* downscaling and limits */ static struct jpeg jpg; /* too large for stack */ -static struct tree_context *tree; - -/* the current full file name */ -static char np_file[MAX_PATH]; -static int curfile = 0, direction = DIR_NONE, entries = 0; - -/* list of the jpeg files */ -static char **file_pt; -#if PLUGIN_BUFFER_SIZE >= MIN_MEM -/* are we using the plugin buffer or the audio buffer? */ -static bool plug_buf = true; -#endif - - /************************* Implementation ***************************/ -bool jpg_ext(const char ext[]) +bool img_ext(const char ext[]) { if(!ext) return false; @@ -201,503 +84,32 @@ return false; } -/*Read directory contents for scrolling. */ -void get_pic_list(void) +void draw_image_rect(struct imageviewer_info *info, + int x, int y, int width, int height) { - int i; - struct entry *dircache; - char *pname; - tree = rb->tree_get_context(); - dircache = tree->dircache; - - file_pt = (char **) buf; - - /* Remove path and leave only the name.*/ - pname = rb->strrchr(np_file,'/'); - pname++; - - for (i = 0; i < tree->filesindir; i++) - { - if (!(dircache[i].attr & ATTR_DIRECTORY) - && jpg_ext(rb->strrchr(dircache[i].name,'.'))) - { - file_pt[entries] = dircache[i].name; - /* Set Selected File. */ - if (!rb->strcmp(file_pt[entries], pname)) - curfile = entries; - entries++; - } - } - - buf += (entries * sizeof(char**)); - buf_size -= (entries * sizeof(char**)); -} - -int change_filename(int direct) -{ - bool file_erased = (file_pt[curfile] == NULL); - direction = direct; - - curfile += (direct == DIR_PREV? entries - 1: 1); - if (curfile >= entries) - curfile -= entries; - - if (file_erased) - { - /* remove 'erased' file names from list. */ - int count, i; - for (count = i = 0; i < entries; i++) - { - if (curfile == i) - curfile = count; - if (file_pt[i] != NULL) - file_pt[count++] = file_pt[i]; - } - entries = count; - } - - if (entries == 0) - { - rb->splash(HZ, "No supported files"); - return PLUGIN_ERROR; - } - - if (rb->strlen(tree->currdir) > 1) - { - rb->strcpy(np_file, tree->currdir); - rb->strcat(np_file, "/"); - } - else - rb->strcpy(np_file, tree->currdir); - - rb->strcat(np_file, file_pt[curfile]); - - return PLUGIN_OTHER; -} - -/* switch off overlay, for handling SYS_ events */ -void cleanup(void *parameter) -{ - (void)parameter; -#ifdef USEGSLIB - grey_show(false); -#endif -} - -#define VSCROLL (LCD_HEIGHT/8) -#define HSCROLL (LCD_WIDTH/10) - -#define ZOOM_IN 100 /* return codes for below function */ -#define ZOOM_OUT 101 - + struct t_disp* pdisp = (struct t_disp*)info->data; #ifdef HAVE_LCD_COLOR -bool set_option_grayscale(void) -{ - bool gray = jpeg_settings.colour_mode == COLOURMODE_GRAY; - rb->set_bool("Grayscale", &gray); - jpeg_settings.colour_mode = gray ? COLOURMODE_GRAY : COLOURMODE_COLOUR; - return false; -} - -bool set_option_dithering(void) -{ - static const struct opt_items dithering[DITHER_NUM_MODES] = { - [DITHER_NONE] = { "Off", -1 }, - [DITHER_ORDERED] = { "Ordered", -1 }, - [DITHER_DIFFUSION] = { "Diffusion", -1 }, - }; - - rb->set_option("Dithering", &jpeg_settings.dither_mode, INT, - dithering, DITHER_NUM_MODES, NULL); - return false; -} - -MENUITEM_FUNCTION(grayscale_item, 0, "Greyscale", - set_option_grayscale, NULL, NULL, Icon_NOICON); -MENUITEM_FUNCTION(dithering_item, 0, "Dithering", - set_option_dithering, NULL, NULL, Icon_NOICON); -MAKE_MENU(display_menu, "Display Options", NULL, Icon_NOICON, - &grayscale_item, &dithering_item); - -static void display_options(void) -{ - rb->do_menu(&display_menu, NULL, NULL, false); -} -#endif /* HAVE_LCD_COLOR */ - -int show_menu(void) /* return 1 to quit */ -{ -#if LCD_DEPTH > 1 - rb->lcd_set_backdrop(old_backdrop); -#ifdef HAVE_LCD_COLOR - rb->lcd_set_foreground(rb->global_settings->fg_color); - rb->lcd_set_background(rb->global_settings->bg_color); -#else - rb->lcd_set_foreground(LCD_BLACK); - rb->lcd_set_background(LCD_WHITE); -#endif -#endif - int result; - - enum menu_id - { - MIID_RETURN = 0, - MIID_TOGGLE_SS_MODE, - MIID_CHANGE_SS_MODE, -#if PLUGIN_BUFFER_SIZE >= MIN_MEM - MIID_SHOW_PLAYBACK_MENU, -#endif -#ifdef HAVE_LCD_COLOR - MIID_DISPLAY_OPTIONS, -#endif - MIID_QUIT, - }; - - MENUITEM_STRINGLIST(menu, "Jpeg Menu", NULL, - "Return", "Toggle Slideshow Mode", - "Change Slideshow Time", -#if PLUGIN_BUFFER_SIZE >= MIN_MEM - "Show Playback Menu", -#endif -#ifdef HAVE_LCD_COLOR - "Display Options", -#endif - "Quit"); - - static const struct opt_items slideshow[2] = { - { "Disable", -1 }, - { "Enable", -1 }, - }; - - result=rb->do_menu(&menu, NULL, NULL, false); - - switch (result) - { - case MIID_RETURN: - break; - case MIID_TOGGLE_SS_MODE: - rb->set_option("Toggle Slideshow", &slideshow_enabled, INT, - slideshow , 2, NULL); - break; - case MIID_CHANGE_SS_MODE: - rb->set_int("Slideshow Time", "s", UNIT_SEC, - &jpeg_settings.ss_timeout, NULL, 1, - SS_MIN_TIMEOUT, SS_MAX_TIMEOUT, NULL); - break; - -#if PLUGIN_BUFFER_SIZE >= MIN_MEM - case MIID_SHOW_PLAYBACK_MENU: - if (plug_buf) - { - playback_control(NULL); - } - else - { - rb->splash(HZ, "Cannot restart playback"); - } - break; -#endif -#ifdef HAVE_LCD_COLOR - case MIID_DISPLAY_OPTIONS: - display_options(); - break; -#endif - case MIID_QUIT: - return 1; - break; - } - -#if !defined(SIMULATOR) && defined(HAVE_DISK_STORAGE) - /* change ata spindown time based on slideshow time setting */ - immediate_ata_off = false; - rb->storage_spindown(rb->global_settings->disk_spindown); - - if (slideshow_enabled) - { - if(jpeg_settings.ss_timeout < 10) - { - /* slideshow times < 10s keep disk spinning */ - rb->storage_spindown(0); - } - else if (!rb->mp3_is_playing()) - { - /* slideshow times > 10s and not playing: ata_off after load */ - immediate_ata_off = true; - } - } -#endif -#if LCD_DEPTH > 1 - rb->lcd_set_backdrop(NULL); - rb->lcd_set_foreground(LCD_WHITE); - rb->lcd_set_background(LCD_BLACK); -#endif - rb->lcd_clear_display(); - return 0; -} - -void draw_image_rect(struct t_disp* pdisp, int x, int y, int width, int height) -{ -#ifdef HAVE_LCD_COLOR yuv_bitmap_part( pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, - pdisp->x + x, pdisp->y + y, pdisp->stride, - x + MAX(0, (LCD_WIDTH - pdisp->width) / 2), - y + MAX(0, (LCD_HEIGHT - pdisp->height) / 2), + info->x + x, info->y + y, pdisp->stride, + x + MAX(0, (LCD_WIDTH - info->width) / 2), + y + MAX(0, (LCD_HEIGHT - info->height) / 2), width, height, - jpeg_settings.colour_mode, jpeg_settings.dither_mode); + info->settings->jpeg_colour_mode, info->settings->jpeg_dither_mode); #else MYXLCD(gray_bitmap_part)( - pdisp->bitmap[0], pdisp->x + x, pdisp->y + y, pdisp->stride, - x + MAX(0, (LCD_WIDTH-pdisp->width)/2), - y + MAX(0, (LCD_HEIGHT-pdisp->height)/2), + pdisp->bitmap[0], info->x + x, info->y + y, pdisp->stride, + x + MAX(0, (LCD_WIDTH-info->width)/2), + y + MAX(0, (LCD_HEIGHT-info->height)/2), width, height); #endif } -/* Pan the viewing window right - move image to the left and fill in - the right-hand side */ -static void pan_view_right(struct t_disp* pdisp) +int img_mem(struct imageviewer_info *info, int ds) { - int move; - - move = MIN(HSCROLL, pdisp->width - pdisp->x - LCD_WIDTH); - if (move > 0) - { - MYXLCD(scroll_left)(move); /* scroll left */ - pdisp->x += move; - draw_image_rect(pdisp, LCD_WIDTH - move, 0, move, pdisp->height-pdisp->y); - MYLCD_UPDATE(); - } -} - -/* Pan the viewing window left - move image to the right and fill in - the left-hand side */ -static void pan_view_left(struct t_disp* pdisp) -{ - int move; - - move = MIN(HSCROLL, pdisp->x); - if (move > 0) - { - MYXLCD(scroll_right)(move); /* scroll right */ - pdisp->x -= move; - draw_image_rect(pdisp, 0, 0, move, pdisp->height-pdisp->y); - MYLCD_UPDATE(); - } -} - -/* Pan the viewing window up - move image down and fill in - the top */ -static void pan_view_up(struct t_disp* pdisp) -{ - int move; - - move = MIN(VSCROLL, pdisp->y); - if (move > 0) - { - MYXLCD(scroll_down)(move); /* scroll down */ - pdisp->y -= move; -#ifdef HAVE_LCD_COLOR - if (jpeg_settings.dither_mode == DITHER_DIFFUSION) - { - /* Draw over the band at the top of the last update - caused by lack of error history on line zero. */ - move = MIN(move + 1, pdisp->y + pdisp->height); - } -#endif - draw_image_rect(pdisp, 0, 0, pdisp->width-pdisp->x, move); - MYLCD_UPDATE(); - } -} - -/* Pan the viewing window down - move image up and fill in - the bottom */ -static void pan_view_down(struct t_disp* pdisp) -{ - int move; - - move = MIN(VSCROLL, pdisp->height - pdisp->y - LCD_HEIGHT); - if (move > 0) - { - MYXLCD(scroll_up)(move); /* scroll up */ - pdisp->y += move; -#ifdef HAVE_LCD_COLOR - if (jpeg_settings.dither_mode == DITHER_DIFFUSION) - { - /* Save the line that was on the last line of the display - and draw one extra line above then recover the line with - image data that had an error history when it was drawn. - */ - move++, pdisp->y--; - rb->memcpy(rgb_linebuf, - rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH, - LCD_WIDTH*sizeof (fb_data)); - } -#endif - - draw_image_rect(pdisp, 0, LCD_HEIGHT - move, pdisp->width-pdisp->x, move); - -#ifdef HAVE_LCD_COLOR - if (jpeg_settings.dither_mode == DITHER_DIFFUSION) - { - /* Cover the first row drawn with previous image data. */ - rb->memcpy(rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH, - rgb_linebuf, LCD_WIDTH*sizeof (fb_data)); - pdisp->y++; - } -#endif - MYLCD_UPDATE(); - } -} - -/* interactively scroll around the image */ -int scroll_bmp(struct t_disp* pdisp) -{ - int button; - int lastbutton = 0; - - while (true) - { - if (slideshow_enabled) - button = rb->button_get_w_tmo(jpeg_settings.ss_timeout * HZ); - else - button = rb->button_get(true); - - running_slideshow = false; - - switch(button) - { - case JPEG_LEFT: - if (entries > 1 && pdisp->width <= LCD_WIDTH - && pdisp->height <= LCD_HEIGHT) - return change_filename(DIR_PREV); - case JPEG_LEFT | BUTTON_REPEAT: - pan_view_left(pdisp); - break; - - case JPEG_RIGHT: - if (entries > 1 && pdisp->width <= LCD_WIDTH - && pdisp->height <= LCD_HEIGHT) - return change_filename(DIR_NEXT); - case JPEG_RIGHT | BUTTON_REPEAT: - pan_view_right(pdisp); - break; - - case JPEG_UP: - case JPEG_UP | BUTTON_REPEAT: - pan_view_up(pdisp); - break; - - case JPEG_DOWN: - case JPEG_DOWN | BUTTON_REPEAT: - pan_view_down(pdisp); - break; - - case BUTTON_NONE: - if (!slideshow_enabled) - break; - running_slideshow = true; - if (entries > 1) - return change_filename(DIR_NEXT); - break; - -#ifdef JPEG_SLIDE_SHOW - case JPEG_SLIDE_SHOW: - slideshow_enabled = !slideshow_enabled; - running_slideshow = slideshow_enabled; - break; -#endif - -#ifdef JPEG_NEXT_REPEAT - case JPEG_NEXT_REPEAT: -#endif - case JPEG_NEXT: - if (entries > 1) - return change_filename(DIR_NEXT); - break; - -#ifdef JPEG_PREVIOUS_REPEAT - case JPEG_PREVIOUS_REPEAT: -#endif - case JPEG_PREVIOUS: - if (entries > 1) - return change_filename(DIR_PREV); - break; - - case JPEG_ZOOM_IN: -#ifdef JPEG_ZOOM_PRE - if (lastbutton != JPEG_ZOOM_PRE) - break; -#endif - return ZOOM_IN; - break; - - case JPEG_ZOOM_OUT: -#ifdef JPEG_ZOOM_PRE - if (lastbutton != JPEG_ZOOM_PRE) - break; -#endif - return ZOOM_OUT; - break; -#ifdef JPEG_RC_MENU - case JPEG_RC_MENU: -#endif - case JPEG_MENU: -#ifdef USEGSLIB - grey_show(false); /* switch off greyscale overlay */ -#endif - if (show_menu() == 1) - return PLUGIN_OK; - -#ifdef USEGSLIB - grey_show(true); /* switch on greyscale overlay */ -#else - draw_image_rect(pdisp, 0, 0, - pdisp->width-pdisp->x, pdisp->height-pdisp->y); - MYLCD_UPDATE(); -#endif - break; - default: - if (rb->default_event_handler_ex(button, cleanup, NULL) - == SYS_USB_CONNECTED) - return PLUGIN_USB_CONNECTED; - break; - - } /* switch */ - - if (button != BUTTON_NONE) - lastbutton = button; - } /* while (true) */ -} - -/********************* main function *************************/ - -/* callback updating a progress meter while JPEG decoding */ -void cb_progress(int current, int total) -{ - rb->yield(); /* be nice to the other threads */ - if(!running_slideshow) - { - rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN], - 0, LCD_HEIGHT-8, LCD_WIDTH, 8, - total, 0, current, HORIZONTAL); - rb->lcd_update_rect(0, LCD_HEIGHT-8, LCD_WIDTH, 8); - } -#ifndef USEGSLIB - else - { - /* in slideshow mode, keep gui interference to a minimum */ - rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN], - 0, LCD_HEIGHT-4, LCD_WIDTH, 4, - total, 0, current, HORIZONTAL); - rb->lcd_update_rect(0, LCD_HEIGHT-4, LCD_WIDTH, 4); - } -#endif -} - -int jpegmem(struct jpeg *p_jpg, int ds) -{ int size; + struct jpeg *p_jpg = &jpg; + if(info == NULL) return 1; size = (p_jpg->x_phys/ds/p_jpg->subsample_x[0]) * (p_jpg->y_phys/ds/p_jpg->subsample_y[0]); @@ -713,42 +125,18 @@ return size; } -/* how far can we zoom in without running out of memory */ -int min_downscale(struct jpeg *p_jpg, int bufsize) +int load_image(char *filename, struct imageviewer_info *info, + unsigned char *buf, ssize_t *buf_size) { - int downscale = 8; - - if (jpegmem(p_jpg, 8) > bufsize) - return 0; /* error, too large, even 1:8 doesn't fit */ - - while (downscale > 1 && jpegmem(p_jpg, downscale/2) <= bufsize) - downscale /= 2; - - return downscale; -} - -/* how far can we zoom out, to fit image into the LCD */ -int max_downscale(struct jpeg *p_jpg) -{ - int downscale = 1; - - while (downscale < 8 && (p_jpg->x_size/downscale > LCD_WIDTH - || p_jpg->y_size/downscale > LCD_HEIGHT)) - { - downscale *= 2; - } - - return downscale; -} - -/* load image from filename. */ -int load_image(char* filename, struct jpeg *p_jpg) -{ int fd; int filesize; unsigned char* buf_jpeg; /* compressed JPEG image */ int status; + struct jpeg *p_jpg = &jpg; + rb->memset(&disp, 0, sizeof(disp)); + rb->memset(&jpg, 0, sizeof(jpg)); + fd = rb->open(filename, O_RDONLY); if (fd < 0) { @@ -762,7 +150,7 @@ /* we can start the decompressed images behind it */ buf_images = buf_root = buf + filesize; - buf_images_size = root_size = buf_size - filesize; + buf_images_size = root_size = *buf_size - filesize; if (buf_images_size <= 0) { @@ -819,28 +207,35 @@ rb->lcd_update(); } + info->x_size = p_jpg->x_size; + info->y_size = p_jpg->y_size; + *buf_size = buf_images_size; return PLUGIN_OK; } -/* return decoded or cached image */ -struct t_disp* get_image(struct jpeg* p_jpg, int ds) +int get_image(struct imageviewer_info *info, int ds) { int w, h; /* used to center output */ int size; /* decompressed image size */ long time; /* measured ticks */ int status; - + struct jpeg* p_jpg = &jpg; struct t_disp* p_disp = &disp[ds]; /* short cut */ + info->width = p_jpg->x_size / ds; + info->height = p_jpg->y_size / ds; + info->data = p_disp; + if (p_disp->bitmap[0] != NULL) { - return p_disp; /* we still have it */ + /* we still have it */ + return PLUGIN_OK; } /* assign image buffer */ /* physical size needed for decoding */ - size = jpegmem(p_jpg, ds); + size = img_mem(info, ds); if (buf_images_size <= size) { /* have to discard the current */ int i; @@ -873,7 +268,7 @@ } #endif /* size may be less when decoded (if height is not block aligned) */ - size = (p_jpg->x_phys/ds) * (p_jpg->y_size / ds); + size = (p_jpg->x_phys/ds) * (p_jpg->y_size/ds); p_disp->bitmap[0] = buf_images; buf_images += size; buf_images_size -= size; @@ -887,9 +282,7 @@ } /* update image properties */ - p_disp->width = p_jpg->x_size / ds; p_disp->stride = p_jpg->x_phys / ds; /* use physical size for stride */ - p_disp->height = p_jpg->y_size / ds; /* the actual decoding */ time = *rb->current_tick; @@ -903,7 +296,7 @@ if (status) { rb->splashf(HZ, "decode error %d", status); - return NULL; + return PLUGIN_ERROR; } time = *rb->current_tick - time; @@ -915,304 +308,5 @@ rb->lcd_update(); } - return p_disp; + return PLUGIN_OK; } - - -/* set the view to the given center point, limit if necessary */ -void set_view (struct t_disp* p_disp, int cx, int cy) -{ - int x, y; - - /* plain center to available width/height */ - x = cx - MIN(LCD_WIDTH, p_disp->width) / 2; - y = cy - MIN(LCD_HEIGHT, p_disp->height) / 2; - - /* limit against upper image size */ - x = MIN(p_disp->width - LCD_WIDTH, x); - y = MIN(p_disp->height - LCD_HEIGHT, y); - - /* limit against negative side */ - x = MAX(0, x); - y = MAX(0, y); - - p_disp->x = x; /* set the values */ - p_disp->y = y; -} - -/* calculate the view center based on the bitmap position */ -void get_view(struct t_disp* p_disp, int* p_cx, int* p_cy) -{ - *p_cx = p_disp->x + MIN(LCD_WIDTH, p_disp->width) / 2; - *p_cy = p_disp->y + MIN(LCD_HEIGHT, p_disp->height) / 2; -} - -/* load, decode, display the image */ -int load_and_show(char* filename) -{ - int status; - struct t_disp* p_disp; /* currenly displayed image */ - int cx, cy; /* view center */ - -#if LCD_DEPTH > 1 - rb->lcd_set_foreground(LCD_WHITE); - rb->lcd_set_background(LCD_BLACK); - rb->lcd_set_backdrop(NULL); -#endif - rb->lcd_clear_display(); - - rb->memset(&disp, 0, sizeof(disp)); - rb->memset(&jpg, 0, sizeof(jpg)); /* clear info struct */ - - if (rb->button_get(false) == JPEG_MENU) - status = PLUGIN_ABORT; - else - status = load_image(filename, &jpg); - - if (status == PLUGIN_OUTOFMEM) - { -#if PLUGIN_BUFFER_SIZE >= MIN_MEM - if(plug_buf) - { - rb->lcd_setfont(FONT_SYSFIXED); - rb->lcd_clear_display(); - rb->snprintf(print,sizeof(print),"%s:",rb->strrchr(filename,'/')+1); - rb->lcd_puts(0,0,print); - rb->lcd_puts(0,1,"Not enough plugin memory!"); - rb->lcd_puts(0,2,"Zoom In: Stop playback."); - if(entries>1) - rb->lcd_puts(0,3,"Left/Right: Skip File."); - rb->lcd_puts(0,4,"Show Menu: Quit."); - rb->lcd_update(); - rb->lcd_setfont(FONT_UI); - - rb->button_clear_queue(); - - while (1) - { - int button = rb->button_get(true); - switch(button) - { - case JPEG_ZOOM_IN: - plug_buf = false; - buf = rb->plugin_get_audio_buffer((size_t *)&buf_size); - /*try again this file, now using the audio buffer */ - return PLUGIN_OTHER; -#ifdef JPEG_RC_MENU - case JPEG_RC_MENU: -#endif - case JPEG_MENU: - return PLUGIN_OK; - - case JPEG_LEFT: - if(entries>1) - { - rb->lcd_clear_display(); - return change_filename(DIR_PREV); - } - break; - - case JPEG_RIGHT: - if(entries>1) - { - rb->lcd_clear_display(); - return change_filename(DIR_NEXT); - } - break; - default: - if(rb->default_event_handler_ex(button, cleanup, NULL) - == SYS_USB_CONNECTED) - return PLUGIN_USB_CONNECTED; - - } - } - } - else -#endif - { - rb->splash(HZ, "Out of Memory"); - file_pt[curfile] = NULL; - return change_filename(direction); - } - } - else if (status == PLUGIN_ERROR) - { - file_pt[curfile] = NULL; - return change_filename(direction); - } - else if (status == PLUGIN_ABORT) { - rb->splash(HZ, "aborted"); - return PLUGIN_OK; - } - - ds_max = max_downscale(&jpg); /* check display constraint */ - ds_min = min_downscale(&jpg, buf_images_size); /* check memory constraint */ - if (ds_min == 0) - { - rb->splash(HZ, "too large"); - file_pt[curfile] = NULL; - return change_filename(direction); - } - else if (ds_max < ds_min) - ds_max = ds_min; - - ds = ds_max; /* initialize setting */ - cx = jpg.x_size/ds/2; /* center the view */ - cy = jpg.y_size/ds/2; - - do /* loop the image prepare and decoding when zoomed */ - { - p_disp = get_image(&jpg, ds); /* decode or fetch from cache */ - if (p_disp == NULL) - { - file_pt[curfile] = NULL; - return change_filename(direction); - } - - set_view(p_disp, cx, cy); - - if(!running_slideshow) - { - rb->snprintf(print, sizeof(print), "showing %dx%d", - p_disp->width, p_disp->height); - rb->lcd_puts(0, 3, print); - rb->lcd_update(); - } - - MYLCD(clear_display)(); - draw_image_rect(p_disp, 0, 0, - p_disp->width-p_disp->x, p_disp->height-p_disp->y); - MYLCD_UPDATE(); - -#ifdef USEGSLIB - grey_show(true); /* switch on greyscale overlay */ -#endif - - /* drawing is now finished, play around with scrolling - * until you press OFF or connect USB - */ - while (1) - { - status = scroll_bmp(p_disp); - if (status == ZOOM_IN) - { - if (ds > ds_min) - { - ds /= 2; /* reduce downscaling to zoom in */ - get_view(p_disp, &cx, &cy); - cx *= 2; /* prepare the position in the new image */ - cy *= 2; - } - else - continue; - } - - if (status == ZOOM_OUT) - { - if (ds < ds_max) - { - ds *= 2; /* increase downscaling to zoom out */ - get_view(p_disp, &cx, &cy); - cx /= 2; /* prepare the position in the new image */ - cy /= 2; - } - else - continue; - } - break; - } - -#ifdef USEGSLIB - grey_show(false); /* switch off overlay */ -#endif - rb->lcd_clear_display(); - } - while (status != PLUGIN_OK && status != PLUGIN_USB_CONNECTED - && status != PLUGIN_OTHER); -#ifdef USEGSLIB - rb->lcd_update(); -#endif - return status; -} - -/******************** Plugin entry point *********************/ - -enum plugin_status plugin_start(const void* parameter) -{ - int condition; -#ifdef USEGSLIB - long greysize; /* helper */ -#endif -#if LCD_DEPTH > 1 - old_backdrop = rb->lcd_get_backdrop(); -#endif - - if(!parameter) return PLUGIN_ERROR; - -#if PLUGIN_BUFFER_SIZE >= MIN_MEM - buf = rb->plugin_get_buffer((size_t *)&buf_size); -#else - buf = rb->plugin_get_audio_buffer((size_t *)&buf_size); -#endif - - rb->strcpy(np_file, parameter); - get_pic_list(); - - if(!entries) return PLUGIN_ERROR; - -#if (PLUGIN_BUFFER_SIZE >= MIN_MEM) && !defined(SIMULATOR) - if(!rb->audio_status()) - { - plug_buf = false; - buf = rb->plugin_get_audio_buffer((size_t *)&buf_size); - } -#endif - -#ifdef USEGSLIB - if (!grey_init(buf, buf_size, GREY_ON_COP, - LCD_WIDTH, LCD_HEIGHT, &greysize)) - { - rb->splash(HZ, "grey buf error"); - return PLUGIN_ERROR; - } - buf += greysize; - buf_size -= greysize; -#endif - - /* should be ok to just load settings since the plugin itself has - just been loaded from disk and the drive should be spinning */ - configfile_load(JPEG_CONFIGFILE, jpeg_config, - ARRAYLEN(jpeg_config), JPEG_SETTINGS_MINVERSION); - old_settings = jpeg_settings; - - /* Turn off backlight timeout */ - backlight_force_on(); /* backlight control in lib/helper.c */ - - do - { - condition = load_and_show(np_file); - } while (condition != PLUGIN_OK && condition != PLUGIN_USB_CONNECTED - && condition != PLUGIN_ERROR); - - if (rb->memcmp(&jpeg_settings, &old_settings, sizeof (jpeg_settings))) - { - /* Just in case drive has to spin, keep it from looking locked */ - rb->splash(0, "Saving Settings"); - configfile_save(JPEG_CONFIGFILE, jpeg_config, - ARRAYLEN(jpeg_config), JPEG_SETTINGS_VERSION); - } - -#if !defined(SIMULATOR) && defined(HAVE_DISK_STORAGE) - /* set back ata spindown time in case we changed it */ - rb->storage_spindown(rb->global_settings->disk_spindown); -#endif - - /* Turn on backlight timeout (revert to settings) */ - backlight_use_settings(); /* backlight control in lib/helper.c */ - -#ifdef USEGSLIB - grey_release(); /* deinitialize */ -#endif - - return condition; -} Index: apps/plugins/jpeg/jpeg.h =================================================================== --- apps/plugins/jpeg/jpeg.h (revision 24098) +++ apps/plugins/jpeg/jpeg.h (working copy) @@ -28,313 +28,6 @@ #ifndef _JPEG_JPEG_H #define _JPEG_JPEG_H -#include "plugin.h" +#include "../imageviewer_ui/imageviewer_ui.h" -/* variable button definitions */ -#if CONFIG_KEYPAD == RECORDER_PAD -#define JPEG_ZOOM_IN BUTTON_PLAY -#define JPEG_ZOOM_OUT BUTTON_ON -#define JPEG_UP BUTTON_UP -#define JPEG_DOWN BUTTON_DOWN -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#define JPEG_NEXT BUTTON_F3 -#define JPEG_PREVIOUS BUTTON_F2 -#define JPEG_MENU BUTTON_OFF - -#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD -#define JPEG_ZOOM_IN BUTTON_SELECT -#define JPEG_ZOOM_OUT BUTTON_ON -#define JPEG_UP BUTTON_UP -#define JPEG_DOWN BUTTON_DOWN -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#define JPEG_NEXT BUTTON_F3 -#define JPEG_PREVIOUS BUTTON_F2 -#define JPEG_MENU BUTTON_OFF - -#elif CONFIG_KEYPAD == ONDIO_PAD -#define JPEG_ZOOM_PRE BUTTON_MENU -#define JPEG_ZOOM_IN (BUTTON_MENU | BUTTON_REL) -#define JPEG_ZOOM_OUT (BUTTON_MENU | BUTTON_DOWN) -#define JPEG_UP BUTTON_UP -#define JPEG_DOWN BUTTON_DOWN -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#define JPEG_NEXT (BUTTON_MENU | BUTTON_RIGHT) -#define JPEG_PREVIOUS (BUTTON_MENU | BUTTON_LEFT) -#define JPEG_MENU BUTTON_OFF - -#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ - (CONFIG_KEYPAD == IRIVER_H300_PAD) -#define JPEG_ZOOM_IN BUTTON_SELECT -#define JPEG_ZOOM_OUT BUTTON_MODE -#define JPEG_UP BUTTON_UP -#define JPEG_DOWN BUTTON_DOWN -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#if (CONFIG_KEYPAD == IRIVER_H100_PAD) -#define JPEG_NEXT BUTTON_ON -#define JPEG_PREVIOUS BUTTON_REC -#else -#define JPEG_NEXT BUTTON_REC -#define JPEG_PREVIOUS BUTTON_ON -#endif -#define JPEG_MENU BUTTON_OFF -#define JPEG_RC_MENU BUTTON_RC_STOP - -#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \ - (CONFIG_KEYPAD == IPOD_1G2G_PAD) -#define JPEG_ZOOM_IN BUTTON_SCROLL_FWD -#define JPEG_ZOOM_OUT BUTTON_SCROLL_BACK -#define JPEG_UP BUTTON_MENU -#define JPEG_DOWN BUTTON_PLAY -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#define JPEG_MENU (BUTTON_SELECT | BUTTON_MENU) -#define JPEG_NEXT (BUTTON_SELECT | BUTTON_RIGHT) -#define JPEG_PREVIOUS (BUTTON_SELECT | BUTTON_LEFT) - -#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD -#define JPEG_ZOOM_PRE BUTTON_SELECT -#define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) -#define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) -#define JPEG_UP BUTTON_UP -#define JPEG_DOWN BUTTON_DOWN -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#define JPEG_MENU BUTTON_POWER -#define JPEG_NEXT BUTTON_PLAY -#define JPEG_PREVIOUS BUTTON_REC - -#elif CONFIG_KEYPAD == GIGABEAT_PAD -#define JPEG_ZOOM_IN BUTTON_VOL_UP -#define JPEG_ZOOM_OUT BUTTON_VOL_DOWN -#define JPEG_UP BUTTON_UP -#define JPEG_DOWN BUTTON_DOWN -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#define JPEG_MENU BUTTON_MENU -#define JPEG_NEXT (BUTTON_A | BUTTON_RIGHT) -#define JPEG_PREVIOUS (BUTTON_A | BUTTON_LEFT) - -#elif CONFIG_KEYPAD == SANSA_E200_PAD -#define JPEG_ZOOM_PRE BUTTON_SELECT -#define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) -#define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) -#define JPEG_UP BUTTON_UP -#define JPEG_DOWN BUTTON_DOWN -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#define JPEG_MENU BUTTON_POWER -#define JPEG_SLIDE_SHOW BUTTON_REC -#define JPEG_NEXT BUTTON_SCROLL_FWD -#define JPEG_NEXT_REPEAT (BUTTON_SCROLL_FWD|BUTTON_REPEAT) -#define JPEG_PREVIOUS BUTTON_SCROLL_BACK -#define JPEG_PREVIOUS_REPEAT (BUTTON_SCROLL_BACK|BUTTON_REPEAT) - -#elif CONFIG_KEYPAD == SANSA_FUZE_PAD -#define JPEG_ZOOM_PRE BUTTON_SELECT -#define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) -#define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) -#define JPEG_UP BUTTON_UP -#define JPEG_DOWN BUTTON_DOWN -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#define JPEG_MENU (BUTTON_HOME|BUTTON_REPEAT) -#define JPEG_NEXT BUTTON_SCROLL_FWD -#define JPEG_NEXT_REPEAT (BUTTON_SCROLL_FWD|BUTTON_REPEAT) -#define JPEG_PREVIOUS BUTTON_SCROLL_BACK -#define JPEG_PREVIOUS_REPEAT (BUTTON_SCROLL_BACK|BUTTON_REPEAT) - -#elif CONFIG_KEYPAD == SANSA_C200_PAD -#define JPEG_ZOOM_PRE BUTTON_SELECT -#define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) -#define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) -#define JPEG_UP BUTTON_UP -#define JPEG_DOWN BUTTON_DOWN -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#define JPEG_MENU BUTTON_POWER -#define JPEG_SLIDE_SHOW BUTTON_REC -#define JPEG_NEXT BUTTON_VOL_UP -#define JPEG_NEXT_REPEAT (BUTTON_VOL_UP|BUTTON_REPEAT) -#define JPEG_PREVIOUS BUTTON_VOL_DOWN -#define JPEG_PREVIOUS_REPEAT (BUTTON_VOL_DOWN|BUTTON_REPEAT) - -#elif CONFIG_KEYPAD == SANSA_CLIP_PAD -#define JPEG_ZOOM_PRE BUTTON_SELECT -#define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) -#define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) -#define JPEG_UP BUTTON_UP -#define JPEG_DOWN BUTTON_DOWN -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#define JPEG_MENU BUTTON_POWER -#define JPEG_SLIDE_SHOW BUTTON_HOME -#define JPEG_NEXT BUTTON_VOL_UP -#define JPEG_NEXT_REPEAT (BUTTON_VOL_UP|BUTTON_REPEAT) -#define JPEG_PREVIOUS BUTTON_VOL_DOWN -#define JPEG_PREVIOUS_REPEAT (BUTTON_VOL_DOWN|BUTTON_REPEAT) - -#elif CONFIG_KEYPAD == SANSA_M200_PAD -#define JPEG_ZOOM_PRE BUTTON_SELECT -#define JPEG_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) -#define JPEG_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) -#define JPEG_UP BUTTON_UP -#define JPEG_DOWN BUTTON_DOWN -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#define JPEG_MENU BUTTON_POWER -#define JPEG_SLIDE_SHOW (BUTTON_SELECT | BUTTON_UP) -#define JPEG_NEXT BUTTON_VOL_UP -#define JPEG_NEXT_REPEAT (BUTTON_VOL_UP|BUTTON_REPEAT) -#define JPEG_PREVIOUS BUTTON_VOL_DOWN -#define JPEG_PREVIOUS_REPEAT (BUTTON_VOL_DOWN|BUTTON_REPEAT) - -#elif CONFIG_KEYPAD == IRIVER_H10_PAD -#define JPEG_ZOOM_PRE BUTTON_PLAY -#define JPEG_ZOOM_IN (BUTTON_PLAY | BUTTON_REL) -#define JPEG_ZOOM_OUT (BUTTON_PLAY | BUTTON_REPEAT) -#define JPEG_UP BUTTON_SCROLL_UP -#define JPEG_DOWN BUTTON_SCROLL_DOWN -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#define JPEG_MENU BUTTON_POWER -#define JPEG_NEXT BUTTON_FF -#define JPEG_PREVIOUS BUTTON_REW - -#elif CONFIG_KEYPAD == MROBE500_PAD -#define JPEG_MENU BUTTON_POWER - -#elif CONFIG_KEYPAD == GIGABEAT_S_PAD -#define JPEG_ZOOM_IN BUTTON_VOL_UP -#define JPEG_ZOOM_OUT BUTTON_VOL_DOWN -#define JPEG_UP BUTTON_UP -#define JPEG_DOWN BUTTON_DOWN -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#define JPEG_MENU BUTTON_MENU -#define JPEG_NEXT BUTTON_NEXT -#define JPEG_PREVIOUS BUTTON_PREV - -#elif CONFIG_KEYPAD == MROBE100_PAD -#define JPEG_ZOOM_IN BUTTON_SELECT -#define JPEG_ZOOM_OUT BUTTON_PLAY -#define JPEG_UP BUTTON_UP -#define JPEG_DOWN BUTTON_DOWN -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#define JPEG_MENU BUTTON_MENU -#define JPEG_NEXT (BUTTON_DISPLAY | BUTTON_RIGHT) -#define JPEG_PREVIOUS (BUTTON_DISPLAY | BUTTON_LEFT) - -#elif CONFIG_KEYPAD == IAUDIO_M3_PAD -#define JPEG_ZOOM_PRE BUTTON_RC_PLAY -#define JPEG_ZOOM_IN (BUTTON_RC_PLAY|BUTTON_REL) -#define JPEG_ZOOM_OUT (BUTTON_RC_PLAY|BUTTON_REPEAT) -#define JPEG_UP BUTTON_RC_VOL_UP -#define JPEG_DOWN BUTTON_RC_VOL_DOWN -#define JPEG_LEFT BUTTON_RC_REW -#define JPEG_RIGHT BUTTON_RC_FF -#define JPEG_MENU BUTTON_RC_REC -#define JPEG_NEXT BUTTON_RC_MODE -#define JPEG_PREVIOUS BUTTON_RC_MENU - -#elif CONFIG_KEYPAD == COWON_D2_PAD - -#elif CONFIG_KEYPAD == IAUDIO67_PAD -#define JPEG_ZOOM_IN BUTTON_VOLUP -#define JPEG_ZOOM_OUT BUTTON_VOLDOWN -#define JPEG_UP BUTTON_STOP -#define JPEG_DOWN BUTTON_PLAY -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#define JPEG_MENU BUTTON_MENU -#define JPEG_NEXT (BUTTON_PLAY|BUTTON_VOLUP) -#define JPEG_PREVIOUS (BUTTON_PLAY|BUTTON_VOLDOWN) - -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD - -#define JPEG_ZOOM_IN BUTTON_PLAY -#define JPEG_ZOOM_OUT BUTTON_CUSTOM -#define JPEG_UP BUTTON_UP -#define JPEG_DOWN BUTTON_DOWN -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#define JPEG_MENU BUTTON_MENU -#define JPEG_NEXT BUTTON_SELECT -#define JPEG_PREVIOUS BUTTON_BACK - -#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD -#define JPEG_ZOOM_IN BUTTON_VOL_UP -#define JPEG_ZOOM_OUT BUTTON_VOL_DOWN -#define JPEG_UP BUTTON_UP -#define JPEG_DOWN BUTTON_DOWN -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#define JPEG_MENU BUTTON_MENU -#define JPEG_NEXT BUTTON_VIEW -#define JPEG_PREVIOUS BUTTON_PLAYLIST - -#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD -#define JPEG_ZOOM_IN BUTTON_VOL_UP -#define JPEG_ZOOM_OUT BUTTON_VOL_DOWN -#define JPEG_UP BUTTON_UP -#define JPEG_DOWN BUTTON_DOWN -#define JPEG_LEFT BUTTON_PREV -#define JPEG_RIGHT BUTTON_NEXT -#define JPEG_MENU BUTTON_MENU -#define JPEG_NEXT BUTTON_RIGHT -#define JPEG_PREVIOUS BUTTON_LEFT - -#elif CONFIG_KEYPAD == ONDAVX747_PAD -#elif CONFIG_KEYPAD == ONDAVX777_PAD - -#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD -#define JPEG_ZOOM_IN (BUTTON_PLAY|BUTTON_UP) -#define JPEG_ZOOM_OUT (BUTTON_PLAY|BUTTON_DOWN) -#define JPEG_UP BUTTON_UP -#define JPEG_DOWN BUTTON_DOWN -#define JPEG_LEFT BUTTON_LEFT -#define JPEG_RIGHT BUTTON_RIGHT -#define JPEG_MENU BUTTON_PLAY -#define JPEG_NEXT BUTTON_FFWD -#define JPEG_PREVIOUS BUTTON_REW - -#else -#error No keymap defined! -#endif - -#ifdef HAVE_TOUCHSCREEN -#ifndef JPEG_UP -#define JPEG_UP BUTTON_TOPMIDDLE -#endif -#ifndef JPEG_DOWN -#define JPEG_DOWN BUTTON_BOTTOMMIDDLE -#endif -#ifndef JPEG_LEFT -#define JPEG_LEFT BUTTON_MIDLEFT -#endif -#ifndef JPEG_RIGHT -#define JPEG_RIGHT BUTTON_MIDRIGHT -#endif -#ifndef JPEG_ZOOM_IN -#define JPEG_ZOOM_IN BUTTON_TOPRIGHT -#endif -#ifndef JPEG_ZOOM_OUT -#define JPEG_ZOOM_OUT BUTTON_TOPLEFT -#endif -#ifndef JPEG_MENU -#define JPEG_MENU (BUTTON_CENTER|BUTTON_REL) -#endif -#ifndef JPEG_NEXT -#define JPEG_NEXT BUTTON_BOTTOMRIGHT -#endif -#ifndef JPEG_PREVIOUS -#define JPEG_PREVIOUS BUTTON_BOTTOMLEFT -#endif -#endif - - #endif /* _JPEG_JPEG_H */ Index: apps/plugins/imageviewer_ui/imageviewer_ui.c =================================================================== --- apps/plugins/imageviewer_ui/imageviewer_ui.c (revision 0) +++ apps/plugins/imageviewer_ui/imageviewer_ui.c (revision 0) @@ -0,0 +1,936 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * user intereface of image viewers (jpeg, png, etc.) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "plugin.h" +#include +#include +#include +#include "imageviewer_ui.h" + +PLUGIN_HEADER + +#ifdef HAVE_LCD_COLOR +/* needed for settings values */ +#include "../jpeg/yuv2rgb.h" +#endif + +#ifdef USEGSLIB +GREY_INFO_STRUCT +#endif + +/* Headings */ +#define DIR_PREV 1 +#define DIR_NEXT -1 +#define DIR_NONE 0 + +/******************************* Globals ***********************************/ + +bool slideshow_enabled = false; /* run slideshow */ +bool running_slideshow = false; /* loading image because of slideshw */ +#ifndef SIMULATOR +bool immediate_ata_off = false; /* power down disk after loading */ +#endif +#if PLUGIN_BUFFER_SIZE >= MIN_MEM +/* are we using the plugin buffer or the audio buffer? */ +bool plug_buf = true; +#endif + +/* Persistent configuration */ +#define IMGVIEW_CONFIGFILE "imageviewer.cfg" +#define IMGVIEW_SETTINGS_MINVERSION 1 +#define IMGVIEW_SETTINGS_VERSION 2 + +/* Slideshow times */ +#define SS_MIN_TIMEOUT 1 +#define SS_MAX_TIMEOUT 20 +#define SS_DEFAULT_TIMEOUT 5 + +#ifdef HAVE_LCD_COLOR +/* hack. for value of settings */ +#include "../jpeg/yuv2rgb.h" +#endif + +static struct imgview_settings settings = +{ +#ifdef HAVE_LCD_COLOR + COLOURMODE_COLOUR, + DITHER_NONE, +#endif + SS_DEFAULT_TIMEOUT +}; +static struct imgview_settings old_settings; + +static struct configdata config[] = +{ +#ifdef HAVE_LCD_COLOR + { TYPE_ENUM, 0, COLOUR_NUM_MODES, { .int_p = &settings.jpeg_colour_mode }, + "Colour Mode", (char *[]){ "Colour", "Grayscale" } }, + { TYPE_ENUM, 0, DITHER_NUM_MODES, { .int_p = &settings.jpeg_dither_mode }, + "Dither Mode", (char *[]){ "None", "Ordered", "Diffusion" } }, +#endif + { TYPE_INT, SS_MIN_TIMEOUT, SS_MAX_TIMEOUT, + { .int_p = &settings.ss_timeout }, "Slideshow Time", NULL }, +}; + +#if LCD_DEPTH > 1 +static fb_data* old_backdrop; +#endif + +/**************** begin Application ********************/ + + +/************************* Globals ***************************/ + +#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER) +static fb_data rgb_linebuf[LCD_WIDTH]; /* Line buffer for scrolling when + DITHER_DIFFUSION is set */ +#endif + +/* my memory pool (from the mp3 buffer) */ +static char print[32]; /* use a common snprintf() buffer */ +/* the remaining free part of the buffer for loaded+resized images */ +static unsigned char* buf; +static ssize_t buf_size; + +static int ds, ds_min, ds_max; /* downscaling and limits */ +struct imageviewer_info imgview_info; + +static struct tree_context *tree; + +/* the current full file name */ +static char np_file[MAX_PATH]; +static int curfile = 0, direction = DIR_NONE, entries = 0; + +/* list of the supported image files */ +static char **file_pt; + +/* unscaled image can be always displayed when there isn't enough memory + * for resized image. e.g. when using native format to store image. */ +static bool unscaled_avail = false; + +/************************* Implementation ***************************/ + +/*Read directory contents for scrolling. */ +static void get_pic_list(void) +{ + int i; + struct entry *dircache; + char *pname; + tree = rb->tree_get_context(); + dircache = tree->dircache; + + file_pt = (char **) buf; + + /* Remove path and leave only the name.*/ + pname = rb->strrchr(np_file,'/'); + pname++; + + for (i = 0; i < tree->filesindir; i++) + { + if (!(dircache[i].attr & ATTR_DIRECTORY) + && img_ext(rb->strrchr(dircache[i].name,'.'))) + { + file_pt[entries] = dircache[i].name; + /* Set Selected File. */ + if (!rb->strcmp(file_pt[entries], pname)) + curfile = entries; + entries++; + } + } + + buf += (entries * sizeof(char**)); + buf_size -= (entries * sizeof(char**)); +} + +static int change_filename(int direct) +{ + bool file_erased = (file_pt[curfile] == NULL); + direction = direct; + + curfile += (direct == DIR_PREV? entries - 1: 1); + if (curfile >= entries) + curfile -= entries; + + if (file_erased) + { + /* remove 'erased' file names from list. */ + int count, i; + for (count = i = 0; i < entries; i++) + { + if (curfile == i) + curfile = count; + if (file_pt[i] != NULL) + file_pt[count++] = file_pt[i]; + } + entries = count; + } + + if (entries == 0) + { + rb->splash(HZ, "No supported files"); + return PLUGIN_ERROR; + } + + if (rb->strlen(tree->currdir) > 1) + { + rb->strcpy(np_file, tree->currdir); + rb->strcat(np_file, "/"); + } + else + rb->strcpy(np_file, tree->currdir); + + rb->strcat(np_file, file_pt[curfile]); + + return PLUGIN_OTHER; +} + +/* switch off overlay, for handling SYS_ events */ +void cleanup(void *parameter) +{ + (void)parameter; +#ifdef USEGSLIB + grey_show(false); +#endif +} + +#define VSCROLL (LCD_HEIGHT/8) +#define HSCROLL (LCD_WIDTH/10) + +#define ZOOM_IN 100 /* return codes for below function */ +#define ZOOM_OUT 101 + +#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER) +static bool set_option_grayscale(void) +{ + bool gray = settings.jpeg_colour_mode == COLOURMODE_GRAY; + rb->set_bool("Grayscale", &gray); + settings.jpeg_colour_mode = gray ? COLOURMODE_GRAY : COLOURMODE_COLOUR; + return false; +} + +static bool set_option_dithering(void) +{ + static const struct opt_items dithering[DITHER_NUM_MODES] = { + [DITHER_NONE] = { "Off", -1 }, + [DITHER_ORDERED] = { "Ordered", -1 }, + [DITHER_DIFFUSION] = { "Diffusion", -1 }, + }; + + rb->set_option("Dithering", &settings.jpeg_dither_mode, INT, + dithering, DITHER_NUM_MODES, NULL); + return false; +} + +MENUITEM_FUNCTION(grayscale_item, 0, "Greyscale", + set_option_grayscale, NULL, NULL, Icon_NOICON); +MENUITEM_FUNCTION(dithering_item, 0, "Dithering", + set_option_dithering, NULL, NULL, Icon_NOICON); +MAKE_MENU(display_menu, "Display Options", NULL, Icon_NOICON, + &grayscale_item, &dithering_item); + +static void display_options(void) +{ + rb->do_menu(&display_menu, NULL, NULL, false); +} +#endif /* defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER) */ + +static int show_menu(void) /* return 1 to quit */ +{ +#if LCD_DEPTH > 1 + rb->lcd_set_backdrop(old_backdrop); +#ifdef HAVE_LCD_COLOR + rb->lcd_set_foreground(rb->global_settings->fg_color); + rb->lcd_set_background(rb->global_settings->bg_color); +#else + rb->lcd_set_foreground(LCD_BLACK); + rb->lcd_set_background(LCD_WHITE); +#endif +#endif + int result; + + enum menu_id + { + MIID_RETURN = 0, + MIID_TOGGLE_SS_MODE, + MIID_CHANGE_SS_MODE, +#if PLUGIN_BUFFER_SIZE >= MIN_MEM + MIID_SHOW_PLAYBACK_MENU, +#endif +#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER) + MIID_DISPLAY_OPTIONS, +#endif + MIID_QUIT, + }; + + MENUITEM_STRINGLIST(menu, MENU_TITLE, NULL, + "Return", "Toggle Slideshow Mode", + "Change Slideshow Time", +#if PLUGIN_BUFFER_SIZE >= MIN_MEM + "Show Playback Menu", +#endif +#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER) + "Display Options", +#endif + "Quit"); + + result=rb->do_menu(&menu, NULL, NULL, false); + + switch (result) + { + case MIID_RETURN: + break; + case MIID_TOGGLE_SS_MODE: + rb->set_bool_options("Toggle Slideshow", &slideshow_enabled, + "Disable", -1, "Enable", -1, NULL); + break; + case MIID_CHANGE_SS_MODE: + rb->set_int("Slideshow Time", "s", UNIT_SEC, + &settings.ss_timeout, NULL, 1, + SS_MIN_TIMEOUT, SS_MAX_TIMEOUT, NULL); + break; + +#if PLUGIN_BUFFER_SIZE >= MIN_MEM + case MIID_SHOW_PLAYBACK_MENU: + if (plug_buf) + { + playback_control(NULL); + } + else + { + rb->splash(HZ, "Cannot restart playback"); + } + break; +#endif +#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER) + case MIID_DISPLAY_OPTIONS: + display_options(); + break; +#endif + case MIID_QUIT: + return 1; + break; + } + +#if !defined(SIMULATOR) && defined(HAVE_DISK_STORAGE) + /* change ata spindown time based on slideshow time setting */ + immediate_ata_off = false; + rb->storage_spindown(rb->global_settings->disk_spindown); + + if (slideshow_enabled) + { + if(settings.ss_timeout < 10) + { + /* slideshow times < 10s keep disk spinning */ + rb->storage_spindown(0); + } + else if (!rb->mp3_is_playing()) + { + /* slideshow times > 10s and not playing: ata_off after load */ + immediate_ata_off = true; + } + } +#endif +#if LCD_DEPTH > 1 + rb->lcd_set_backdrop(NULL); + rb->lcd_set_foreground(LCD_WHITE); + rb->lcd_set_background(LCD_BLACK); +#endif + rb->lcd_clear_display(); + return 0; +} + +/* Pan the viewing window right - move image to the left and fill in + the right-hand side */ +static void pan_view_right(struct imageviewer_info *info) +{ + int move; + + move = MIN(HSCROLL, info->width - info->x - LCD_WIDTH); + if (move > 0) + { + MYXLCD(scroll_left)(move); /* scroll left */ + info->x += move; + draw_image_rect(info, LCD_WIDTH - move, 0, move, info->height-info->y); + MYLCD_UPDATE(); + } +} + +/* Pan the viewing window left - move image to the right and fill in + the left-hand side */ +static void pan_view_left(struct imageviewer_info *info) +{ + int move; + + move = MIN(HSCROLL, info->x); + if (move > 0) + { + MYXLCD(scroll_right)(move); /* scroll right */ + info->x -= move; + draw_image_rect(info, 0, 0, move, info->height-info->y); + MYLCD_UPDATE(); + } +} + +/* Pan the viewing window up - move image down and fill in the top */ +static void pan_view_up(struct imageviewer_info *info) +{ + int move; + + move = MIN(VSCROLL, info->y); + if (move > 0) + { + MYXLCD(scroll_down)(move); /* scroll down */ + info->y -= move; +#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER) + if (settings.jpeg_dither_mode == DITHER_DIFFUSION) + { + /* Draw over the band at the top of the last update + caused by lack of error history on line zero. */ + move = MIN(move + 1, info->y + info->height); + } +#endif + draw_image_rect(info, 0, 0, info->width-info->x, move); + MYLCD_UPDATE(); + } +} + +/* Pan the viewing window down - move image up and fill in the bottom */ +static void pan_view_down(struct imageviewer_info *info) +{ + int move; + + move = MIN(VSCROLL, info->height - info->y - LCD_HEIGHT); + if (move > 0) + { + MYXLCD(scroll_up)(move); /* scroll up */ + info->y += move; +#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER) + if (settings.jpeg_dither_mode == DITHER_DIFFUSION) + { + /* Save the line that was on the last line of the display + and draw one extra line above then recover the line with + image data that had an error history when it was drawn. + */ + move++, info->y--; + rb->memcpy(rgb_linebuf, + rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH, + LCD_WIDTH*sizeof (fb_data)); + } +#endif + + draw_image_rect(info, 0, LCD_HEIGHT - move, info->width-info->x, move); + +#if defined(HAVE_LCD_COLOR) && defined(JPEG_VIEWER) + if (settings.jpeg_dither_mode == DITHER_DIFFUSION) + { + /* Cover the first row drawn with previous image data. */ + rb->memcpy(rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH, + rgb_linebuf, LCD_WIDTH*sizeof (fb_data)); + info->y++; + } +#endif + MYLCD_UPDATE(); + } +} + +/* interactively scroll around the image */ +static int scroll_bmp(struct imageviewer_info *info) +{ + int button; + int lastbutton = 0; + + while (true) + { + if (slideshow_enabled) + button = rb->button_get_w_tmo(settings.ss_timeout * HZ); + else + button = rb->button_get(true); + + running_slideshow = false; + + switch(button) + { + case IMGVIEW_LEFT: + if (entries > 1 && info->width <= LCD_WIDTH + && info->height <= LCD_HEIGHT) + return change_filename(DIR_PREV); + case IMGVIEW_LEFT | BUTTON_REPEAT: + pan_view_left(info); + break; + + case IMGVIEW_RIGHT: + if (entries > 1 && info->width <= LCD_WIDTH + && info->height <= LCD_HEIGHT) + return change_filename(DIR_NEXT); + case IMGVIEW_RIGHT | BUTTON_REPEAT: + pan_view_right(info); + break; + + case IMGVIEW_UP: + case IMGVIEW_UP | BUTTON_REPEAT: + pan_view_up(info); + break; + + case IMGVIEW_DOWN: + case IMGVIEW_DOWN | BUTTON_REPEAT: + pan_view_down(info); + break; + + case BUTTON_NONE: + if (!slideshow_enabled) + break; + running_slideshow = true; + if (entries > 1) + return change_filename(DIR_NEXT); + break; + +#ifdef IMGVIEW_SLIDE_SHOW + case IMGVIEW_SLIDE_SHOW: + slideshow_enabled = !slideshow_enabled; + running_slideshow = slideshow_enabled; + break; +#endif + +#ifdef IMGVIEW_NEXT_REPEAT + case IMGVIEW_NEXT_REPEAT: +#endif + case IMGVIEW_NEXT: + if (entries > 1) + return change_filename(DIR_NEXT); + break; + +#ifdef IMGVIEW_PREVIOUS_REPEAT + case IMGVIEW_PREVIOUS_REPEAT: +#endif + case IMGVIEW_PREVIOUS: + if (entries > 1) + return change_filename(DIR_PREV); + break; + + case IMGVIEW_ZOOM_IN: +#ifdef IMGVIEW_ZOOM_PRE + if (lastbutton != IMGVIEW_ZOOM_PRE) + break; +#endif + return ZOOM_IN; + break; + + case IMGVIEW_ZOOM_OUT: +#ifdef IMGVIEW_ZOOM_PRE + if (lastbutton != IMGVIEW_ZOOM_PRE) + break; +#endif + return ZOOM_OUT; + break; +#ifdef IMGVIEW_RC_MENU + case IMGVIEW_RC_MENU: +#endif + case IMGVIEW_MENU: +#ifdef USEGSLIB + grey_show(false); /* switch off greyscale overlay */ +#endif + if (show_menu() == 1) + return PLUGIN_OK; + +#ifdef USEGSLIB + grey_show(true); /* switch on greyscale overlay */ +#else + draw_image_rect(info, 0, 0, + info->width-info->x, info->height-info->y); + MYLCD_UPDATE(); +#endif + break; + default: + if (rb->default_event_handler_ex(button, cleanup, NULL) + == SYS_USB_CONNECTED) + return PLUGIN_USB_CONNECTED; + break; + + } /* switch */ + + if (button != BUTTON_NONE) + lastbutton = button; + } /* while (true) */ +} + +/********************* main function *************************/ + +/* callback updating a progress meter while decoding image */ +void cb_progress(int current, int total) +{ + rb->yield(); /* be nice to the other threads */ + if(!running_slideshow) + { + rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN], + 0, LCD_HEIGHT-8, LCD_WIDTH, 8, + total, 0, current, HORIZONTAL); + rb->lcd_update_rect(0, LCD_HEIGHT-8, LCD_WIDTH, 8); + } +#ifndef USEGSLIB + else + { + /* in slideshow mode, keep gui interference to a minimum */ + rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN], + 0, LCD_HEIGHT-4, LCD_WIDTH, 4, + total, 0, current, HORIZONTAL); + rb->lcd_update_rect(0, LCD_HEIGHT-4, LCD_WIDTH, 4); + } +#endif +} + +/* how far can we zoom in without running out of memory */ +static int min_downscale(struct imageviewer_info *info, int bufsize) +{ + int downscale = 8; + + if (img_mem(info, 8) > bufsize) + return 0; /* error, too large, even 1:8 doesn't fit */ + + while (downscale > 1 && img_mem(info, downscale/2) <= bufsize) + downscale /= 2; + + return downscale; +} + +/* how far can we zoom out, to fit image into the LCD */ +static int max_downscale(struct imageviewer_info *info) +{ + int downscale = 1; + + while (downscale < 8 && (info->x_size/downscale > LCD_WIDTH + || info->y_size/downscale > LCD_HEIGHT)) + { + downscale *= 2; + } + + return downscale; +} + +/* set the view to the given center point, limit if necessary */ +static void set_view(struct imageviewer_info *info, int cx, int cy) +{ + int x, y; + + /* plain center to available width/height */ + x = cx - MIN(LCD_WIDTH, info->width) / 2; + y = cy - MIN(LCD_HEIGHT, info->height) / 2; + + /* limit against upper image size */ + x = MIN(info->width - LCD_WIDTH, x); + y = MIN(info->height - LCD_HEIGHT, y); + + /* limit against negative side */ + x = MAX(0, x); + y = MAX(0, y); + + info->x = x; /* set the values */ + info->y = y; +} + +/* calculate the view center based on the bitmap position */ +static void get_view(struct imageviewer_info *info, int *p_cx, int *p_cy) +{ + *p_cx = info->x + MIN(LCD_WIDTH, info->width) / 2; + *p_cy = info->y + MIN(LCD_HEIGHT, info->height) / 2; +} + +/* load, decode, display the image */ +static int load_and_show(char* filename, struct imageviewer_info *info) +{ + int status; + int cx, cy; + ssize_t remaining = buf_size; + +#if LCD_DEPTH > 1 + rb->lcd_set_foreground(LCD_WHITE); + rb->lcd_set_background(LCD_BLACK); + rb->lcd_set_backdrop(NULL); +#endif + rb->lcd_clear_display(); + + if (rb->button_get(false) == IMGVIEW_MENU) + status = PLUGIN_ABORT; + else + status = load_image(filename, info, buf, &remaining); + + if (status == PLUGIN_OUTOFMEM) + { +#if PLUGIN_BUFFER_SIZE >= MIN_MEM + if(plug_buf) + { + rb->lcd_setfont(FONT_SYSFIXED); + rb->lcd_clear_display(); + rb->snprintf(print,sizeof(print),"%s:",rb->strrchr(filename,'/')+1); + rb->lcd_puts(0,0,print); + rb->lcd_puts(0,1,"Not enough plugin memory!"); + rb->lcd_puts(0,2,"Zoom In: Stop playback."); + if(entries>1) + rb->lcd_puts(0,3,"Left/Right: Skip File."); + rb->lcd_puts(0,4,"Show Menu: Quit."); + rb->lcd_update(); + rb->lcd_setfont(FONT_UI); + + rb->button_clear_queue(); + + while (1) + { + int button = rb->button_get(true); + switch(button) + { + case IMGVIEW_ZOOM_IN: + plug_buf = false; + buf = rb->plugin_get_audio_buffer((size_t *)&buf_size); + /*try again this file, now using the audio buffer */ + return PLUGIN_OTHER; +#ifdef IMGVIEW_RC_MENU + case IMGVIEW_RC_MENU: +#endif + case IMGVIEW_MENU: + return PLUGIN_OK; + + case IMGVIEW_LEFT: + if(entries>1) + { + rb->lcd_clear_display(); + return change_filename(DIR_PREV); + } + break; + + case IMGVIEW_RIGHT: + if(entries>1) + { + rb->lcd_clear_display(); + return change_filename(DIR_NEXT); + } + break; + default: + if(rb->default_event_handler_ex(button, cleanup, NULL) + == SYS_USB_CONNECTED) + return PLUGIN_USB_CONNECTED; + + } + } + } + else +#endif + { + rb->splash(HZ, "Out of Memory"); + file_pt[curfile] = NULL; + return change_filename(direction); + } + } + else if (status == PLUGIN_ERROR) + { + file_pt[curfile] = NULL; + return change_filename(direction); + } + else if (status == PLUGIN_ABORT) { + rb->splash(HZ, "aborted"); + return PLUGIN_OK; + } + + ds_max = max_downscale(info); /* check display constraint */ + ds_min = min_downscale(info, remaining); /* check memory constraint */ + if (ds_min == 0) + { + if (!unscaled_avail) + { + rb->splash(HZ, "too large"); + file_pt[curfile] = NULL; + return change_filename(direction); + } + else + { + /* Can not resize the image bat original one is available. */ + ds_min = ds_max = 1; + } + } + else if (ds_max < ds_min) + ds_max = ds_min; + + ds = ds_max; /* initialize setting */ + cx = info->x_size/ds/2; /* center the view */ + cy = info->y_size/ds/2; + + do /* loop the image prepare and decoding when zoomed */ + { + status = get_image(info, ds); /* decode or fetch from cache */ + if (status == PLUGIN_ERROR) + { + file_pt[curfile] = NULL; + return change_filename(direction); + } + + set_view(info, cx, cy); + + if(!running_slideshow) + { + rb->snprintf(print, sizeof(print), "showing %dx%d", + info->width, info->height); + rb->lcd_puts(0, 3, print); + rb->lcd_update(); + } + + MYLCD(clear_display)(); + draw_image_rect(info, 0, 0, + info->width-info->x, info->height-info->y); + MYLCD_UPDATE(); + +#ifdef USEGSLIB + grey_show(true); /* switch on greyscale overlay */ +#endif + + /* drawing is now finished, play around with scrolling + * until you press OFF or connect USB + */ + while(1) + { + status = scroll_bmp(info); + if (status == ZOOM_IN) + { + if (ds > ds_min || (unscaled_avail && ds > 1)) + { + /* if 1/1 is always available, jump ds from ds_min to 1. */ + int zoom = (ds == ds_min)? ds_min: 2; + ds /= zoom; /* reduce downscaling to zoom in */ + get_view(info, &cx, &cy); + cx *= zoom; /* prepare the position in the new image */ + cy *= zoom; + } + else + continue; + } + + if (status == ZOOM_OUT) + { + if (ds < ds_max) + { + /* if ds is 1 and ds_min is greater than 1, jump ds to ds_min. */ + int zoom = (ds < ds_min)? ds_min: 2; + ds *= zoom; /* increase downscaling to zoom out */ + get_view(info, &cx, &cy); + cx /= zoom; /* prepare the position in the new image */ + cy /= zoom; + } + else + continue; + } + break; + } + +#ifdef USEGSLIB + grey_show(false); /* switch off overlay */ +#endif + rb->lcd_clear_display(); + } + while (status != PLUGIN_OK && status != PLUGIN_USB_CONNECTED + && status != PLUGIN_OTHER); +#ifdef USEGSLIB + rb->lcd_update(); +#endif + return status; +} + +/******************** Plugin entry point *********************/ + +enum plugin_status plugin_start(const void* parameter) +{ + int condition; +#ifdef USEGSLIB + long greysize; /* helper */ +#endif +#if LCD_DEPTH > 1 + old_backdrop = rb->lcd_get_backdrop(); +#endif + + if(!parameter) return PLUGIN_ERROR; + +#if PLUGIN_BUFFER_SIZE >= MIN_MEM + buf = rb->plugin_get_buffer((size_t *)&buf_size); +#else + buf = rb->plugin_get_audio_buffer((size_t *)&buf_size); +#endif + + rb->strcpy(np_file, parameter); + get_pic_list(); + + if(!entries) return PLUGIN_ERROR; + +#if (PLUGIN_BUFFER_SIZE >= MIN_MEM) && !defined(SIMULATOR) + if(!rb->audio_status()) + { + plug_buf = false; + buf = rb->plugin_get_audio_buffer((size_t *)&buf_size); + } +#endif + +#ifdef USEGSLIB + if (!grey_init(buf, buf_size, GREY_ON_COP, + LCD_WIDTH, LCD_HEIGHT, &greysize)) + { + rb->splash(HZ, "grey buf error"); + return PLUGIN_ERROR; + } + buf += greysize; + buf_size -= greysize; +#endif + + /* should be ok to just load settings since the plugin itself has + just been loaded from disk and the drive should be spinning */ + configfile_load(IMGVIEW_CONFIGFILE, config, + ARRAYLEN(config), IMGVIEW_SETTINGS_MINVERSION); + rb->memcpy(&old_settings, &settings, sizeof (settings)); + + /* Turn off backlight timeout */ + backlight_force_on(); /* backlight control in lib/helper.c */ + + rb->memset(&imgview_info, 0, sizeof(imgview_info)); + imgview_info.settings = &settings; + unscaled_avail = (img_mem(NULL, 1) == 0); + + do + { + condition = load_and_show(np_file, &imgview_info); + } while (condition != PLUGIN_OK && condition != PLUGIN_USB_CONNECTED + && condition != PLUGIN_ERROR); + + if (rb->memcmp(&settings, &old_settings, sizeof (settings))) + { + /* Just in case drive has to spin, keep it from looking locked */ + rb->splash(0, "Saving Settings"); + configfile_save(IMGVIEW_CONFIGFILE, config, + ARRAYLEN(config), IMGVIEW_SETTINGS_VERSION); + } + +#if !defined(SIMULATOR) && defined(HAVE_DISK_STORAGE) + /* set back ata spindown time in case we changed it */ + rb->storage_spindown(rb->global_settings->disk_spindown); +#endif + + /* Turn on backlight timeout (revert to settings) */ + backlight_use_settings(); /* backlight control in lib/helper.c */ + +#ifdef USEGSLIB + grey_release(); /* deinitialize */ +#endif + + return condition; +} Index: apps/plugins/imageviewer_ui/imageviewer_ui.h =================================================================== --- apps/plugins/imageviewer_ui/imageviewer_ui.h (revision 0) +++ apps/plugins/imageviewer_ui/imageviewer_ui.h (revision 0) @@ -0,0 +1,411 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * user intereface of image viewers (jpeg, png, etc.) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef _IMGVIEW_IMGVIEW_H +#define _IMGVIEW_IMGVIEW_H + +#include "plugin.h" + +/* variable button definitions */ +#if CONFIG_KEYPAD == RECORDER_PAD +#define IMGVIEW_ZOOM_IN BUTTON_PLAY +#define IMGVIEW_ZOOM_OUT BUTTON_ON +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_NEXT BUTTON_F3 +#define IMGVIEW_PREVIOUS BUTTON_F2 +#define IMGVIEW_MENU BUTTON_OFF + +#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD +#define IMGVIEW_ZOOM_IN BUTTON_SELECT +#define IMGVIEW_ZOOM_OUT BUTTON_ON +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_NEXT BUTTON_F3 +#define IMGVIEW_PREVIOUS BUTTON_F2 +#define IMGVIEW_MENU BUTTON_OFF + +#elif CONFIG_KEYPAD == ONDIO_PAD +#define IMGVIEW_ZOOM_PRE BUTTON_MENU +#define IMGVIEW_ZOOM_IN (BUTTON_MENU | BUTTON_REL) +#define IMGVIEW_ZOOM_OUT (BUTTON_MENU | BUTTON_DOWN) +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_NEXT (BUTTON_MENU | BUTTON_RIGHT) +#define IMGVIEW_PREVIOUS (BUTTON_MENU | BUTTON_LEFT) +#define IMGVIEW_MENU BUTTON_OFF + +#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ + (CONFIG_KEYPAD == IRIVER_H300_PAD) +#define IMGVIEW_ZOOM_IN BUTTON_SELECT +#define IMGVIEW_ZOOM_OUT BUTTON_MODE +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#if (CONFIG_KEYPAD == IRIVER_H100_PAD) +#define IMGVIEW_NEXT BUTTON_ON +#define IMGVIEW_PREVIOUS BUTTON_REC +#else +#define IMGVIEW_NEXT BUTTON_REC +#define IMGVIEW_PREVIOUS BUTTON_ON +#endif +#define IMGVIEW_MENU BUTTON_OFF +#define IMGVIEW_RC_MENU BUTTON_RC_STOP + +#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \ + (CONFIG_KEYPAD == IPOD_1G2G_PAD) +#define IMGVIEW_ZOOM_IN BUTTON_SCROLL_FWD +#define IMGVIEW_ZOOM_OUT BUTTON_SCROLL_BACK +#define IMGVIEW_UP BUTTON_MENU +#define IMGVIEW_DOWN BUTTON_PLAY +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_MENU (BUTTON_SELECT | BUTTON_MENU) +#define IMGVIEW_NEXT (BUTTON_SELECT | BUTTON_RIGHT) +#define IMGVIEW_PREVIOUS (BUTTON_SELECT | BUTTON_LEFT) + +#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD +#define IMGVIEW_ZOOM_PRE BUTTON_SELECT +#define IMGVIEW_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) +#define IMGVIEW_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_MENU BUTTON_POWER +#define IMGVIEW_NEXT BUTTON_PLAY +#define IMGVIEW_PREVIOUS BUTTON_REC + +#elif CONFIG_KEYPAD == GIGABEAT_PAD +#define IMGVIEW_ZOOM_IN BUTTON_VOL_UP +#define IMGVIEW_ZOOM_OUT BUTTON_VOL_DOWN +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_MENU BUTTON_MENU +#define IMGVIEW_NEXT (BUTTON_A | BUTTON_RIGHT) +#define IMGVIEW_PREVIOUS (BUTTON_A | BUTTON_LEFT) + +#elif CONFIG_KEYPAD == SANSA_E200_PAD +#define IMGVIEW_ZOOM_PRE BUTTON_SELECT +#define IMGVIEW_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) +#define IMGVIEW_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_MENU BUTTON_POWER +#define IMGVIEW_SLIDE_SHOW BUTTON_REC +#define IMGVIEW_NEXT BUTTON_SCROLL_FWD +#define IMGVIEW_NEXT_REPEAT (BUTTON_SCROLL_FWD|BUTTON_REPEAT) +#define IMGVIEW_PREVIOUS BUTTON_SCROLL_BACK +#define IMGVIEW_PREVIOUS_REPEAT (BUTTON_SCROLL_BACK|BUTTON_REPEAT) + +#elif CONFIG_KEYPAD == SANSA_FUZE_PAD +#define IMGVIEW_ZOOM_PRE BUTTON_SELECT +#define IMGVIEW_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) +#define IMGVIEW_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_MENU (BUTTON_HOME|BUTTON_REPEAT) +#define IMGVIEW_NEXT BUTTON_SCROLL_FWD +#define IMGVIEW_NEXT_REPEAT (BUTTON_SCROLL_FWD|BUTTON_REPEAT) +#define IMGVIEW_PREVIOUS BUTTON_SCROLL_BACK +#define IMGVIEW_PREVIOUS_REPEAT (BUTTON_SCROLL_BACK|BUTTON_REPEAT) + +#elif CONFIG_KEYPAD == SANSA_C200_PAD +#define IMGVIEW_ZOOM_PRE BUTTON_SELECT +#define IMGVIEW_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) +#define IMGVIEW_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_MENU BUTTON_POWER +#define IMGVIEW_SLIDE_SHOW BUTTON_REC +#define IMGVIEW_NEXT BUTTON_VOL_UP +#define IMGVIEW_NEXT_REPEAT (BUTTON_VOL_UP|BUTTON_REPEAT) +#define IMGVIEW_PREVIOUS BUTTON_VOL_DOWN +#define IMGVIEW_PREVIOUS_REPEAT (BUTTON_VOL_DOWN|BUTTON_REPEAT) + +#elif CONFIG_KEYPAD == SANSA_CLIP_PAD +#define IMGVIEW_ZOOM_PRE BUTTON_SELECT +#define IMGVIEW_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) +#define IMGVIEW_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_MENU BUTTON_POWER +#define IMGVIEW_SLIDE_SHOW BUTTON_HOME +#define IMGVIEW_NEXT BUTTON_VOL_UP +#define IMGVIEW_NEXT_REPEAT (BUTTON_VOL_UP|BUTTON_REPEAT) +#define IMGVIEW_PREVIOUS BUTTON_VOL_DOWN +#define IMGVIEW_PREVIOUS_REPEAT (BUTTON_VOL_DOWN|BUTTON_REPEAT) + +#elif CONFIG_KEYPAD == SANSA_M200_PAD +#define IMGVIEW_ZOOM_PRE BUTTON_SELECT +#define IMGVIEW_ZOOM_IN (BUTTON_SELECT | BUTTON_REL) +#define IMGVIEW_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT) +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_MENU BUTTON_POWER +#define IMGVIEW_SLIDE_SHOW (BUTTON_SELECT | BUTTON_UP) +#define IMGVIEW_NEXT BUTTON_VOL_UP +#define IMGVIEW_NEXT_REPEAT (BUTTON_VOL_UP|BUTTON_REPEAT) +#define IMGVIEW_PREVIOUS BUTTON_VOL_DOWN +#define IMGVIEW_PREVIOUS_REPEAT (BUTTON_VOL_DOWN|BUTTON_REPEAT) + +#elif CONFIG_KEYPAD == IRIVER_H10_PAD +#define IMGVIEW_ZOOM_PRE BUTTON_PLAY +#define IMGVIEW_ZOOM_IN (BUTTON_PLAY | BUTTON_REL) +#define IMGVIEW_ZOOM_OUT (BUTTON_PLAY | BUTTON_REPEAT) +#define IMGVIEW_UP BUTTON_SCROLL_UP +#define IMGVIEW_DOWN BUTTON_SCROLL_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_MENU BUTTON_POWER +#define IMGVIEW_NEXT BUTTON_FF +#define IMGVIEW_PREVIOUS BUTTON_REW + +#elif CONFIG_KEYPAD == MROBE500_PAD +#define IMGVIEW_MENU BUTTON_POWER + +#elif CONFIG_KEYPAD == GIGABEAT_S_PAD +#define IMGVIEW_ZOOM_IN BUTTON_VOL_UP +#define IMGVIEW_ZOOM_OUT BUTTON_VOL_DOWN +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_MENU BUTTON_MENU +#define IMGVIEW_NEXT BUTTON_NEXT +#define IMGVIEW_PREVIOUS BUTTON_PREV + +#elif CONFIG_KEYPAD == MROBE100_PAD +#define IMGVIEW_ZOOM_IN BUTTON_SELECT +#define IMGVIEW_ZOOM_OUT BUTTON_PLAY +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_MENU BUTTON_MENU +#define IMGVIEW_NEXT (BUTTON_DISPLAY | BUTTON_RIGHT) +#define IMGVIEW_PREVIOUS (BUTTON_DISPLAY | BUTTON_LEFT) + +#elif CONFIG_KEYPAD == IAUDIO_M3_PAD +#define IMGVIEW_ZOOM_PRE BUTTON_RC_PLAY +#define IMGVIEW_ZOOM_IN (BUTTON_RC_PLAY|BUTTON_REL) +#define IMGVIEW_ZOOM_OUT (BUTTON_RC_PLAY|BUTTON_REPEAT) +#define IMGVIEW_UP BUTTON_RC_VOL_UP +#define IMGVIEW_DOWN BUTTON_RC_VOL_DOWN +#define IMGVIEW_LEFT BUTTON_RC_REW +#define IMGVIEW_RIGHT BUTTON_RC_FF +#define IMGVIEW_MENU BUTTON_RC_REC +#define IMGVIEW_NEXT BUTTON_RC_MODE +#define IMGVIEW_PREVIOUS BUTTON_RC_MENU + +#elif CONFIG_KEYPAD == COWON_D2_PAD + +#elif CONFIG_KEYPAD == IAUDIO67_PAD +#define IMGVIEW_ZOOM_IN BUTTON_VOLUP +#define IMGVIEW_ZOOM_OUT BUTTON_VOLDOWN +#define IMGVIEW_UP BUTTON_STOP +#define IMGVIEW_DOWN BUTTON_PLAY +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_MENU BUTTON_MENU +#define IMGVIEW_NEXT (BUTTON_PLAY|BUTTON_VOLUP) +#define IMGVIEW_PREVIOUS (BUTTON_PLAY|BUTTON_VOLDOWN) + +#elif CONFIG_KEYPAD == CREATIVEZVM_PAD + +#define IMGVIEW_ZOOM_IN BUTTON_PLAY +#define IMGVIEW_ZOOM_OUT BUTTON_CUSTOM +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_MENU BUTTON_MENU +#define IMGVIEW_NEXT BUTTON_SELECT +#define IMGVIEW_PREVIOUS BUTTON_BACK + +#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD +#define IMGVIEW_ZOOM_IN BUTTON_VOL_UP +#define IMGVIEW_ZOOM_OUT BUTTON_VOL_DOWN +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_MENU BUTTON_MENU +#define IMGVIEW_NEXT BUTTON_VIEW +#define IMGVIEW_PREVIOUS BUTTON_PLAYLIST + +#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD +#define IMGVIEW_ZOOM_IN BUTTON_VOL_UP +#define IMGVIEW_ZOOM_OUT BUTTON_VOL_DOWN +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_PREV +#define IMGVIEW_RIGHT BUTTON_NEXT +#define IMGVIEW_MENU BUTTON_MENU +#define IMGVIEW_NEXT BUTTON_RIGHT +#define IMGVIEW_PREVIOUS BUTTON_LEFT + +#elif CONFIG_KEYPAD == ONDAVX747_PAD +#elif CONFIG_KEYPAD == ONDAVX777_PAD + +#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD +#define IMGVIEW_ZOOM_IN (BUTTON_PLAY|BUTTON_UP) +#define IMGVIEW_ZOOM_OUT (BUTTON_PLAY|BUTTON_DOWN) +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_MENU BUTTON_PLAY +#define IMGVIEW_NEXT BUTTON_FFWD +#define IMGVIEW_PREVIOUS BUTTON_REW + +#else +#error No keymap defined! +#endif + +#ifdef HAVE_TOUCHSCREEN +#ifndef IMGVIEW_UP +#define IMGVIEW_UP BUTTON_TOPMIDDLE +#endif +#ifndef IMGVIEW_DOWN +#define IMGVIEW_DOWN BUTTON_BOTTOMMIDDLE +#endif +#ifndef IMGVIEW_LEFT +#define IMGVIEW_LEFT BUTTON_MIDLEFT +#endif +#ifndef IMGVIEW_RIGHT +#define IMGVIEW_RIGHT BUTTON_MIDRIGHT +#endif +#ifndef IMGVIEW_ZOOM_IN +#define IMGVIEW_ZOOM_IN BUTTON_TOPRIGHT +#endif +#ifndef IMGVIEW_ZOOM_OUT +#define IMGVIEW_ZOOM_OUT BUTTON_TOPLEFT +#endif +#ifndef IMGVIEW_MENU +#define IMGVIEW_MENU (BUTTON_CENTER|BUTTON_REL) +#endif +#ifndef IMGVIEW_NEXT +#define IMGVIEW_NEXT BUTTON_BOTTOMRIGHT +#endif +#ifndef IMGVIEW_PREVIOUS +#define IMGVIEW_PREVIOUS BUTTON_BOTTOMLEFT +#endif +#endif + +/* different graphics libraries */ +#if LCD_DEPTH < 8 +#define USEGSLIB +#include +#define MYLCD(fn) grey_ub_ ## fn +#define MYLCD_UPDATE() +#define MYXLCD(fn) grey_ub_ ## fn +#else +#include +#define MYLCD(fn) rb->lcd_ ## fn +#define MYLCD_UPDATE() rb->lcd_update(); +#define MYXLCD(fn) xlcd_ ## fn +#endif + +/* Min memory allowing us to use the plugin buffer + * and thus not stopping the music + * *Very* rough estimation: + * Max 10 000 dir entries * 4bytes/entry (char **) = 40000 bytes + * + 30k code size = 70 000 + * + 50k min for image = 120 000 + */ +#define MIN_MEM 120000 + +/* State code for output with return. */ +#define PLUGIN_OTHER 10 +#define PLUGIN_ABORT 11 +#define PLUGIN_OUTOFMEM 12 + +/* Settings. jpeg needs these */ +struct imgview_settings +{ + /* include all settings for varias decoders as using same setting file. */ +#ifdef HAVE_LCD_COLOR + int jpeg_colour_mode; + int jpeg_dither_mode; +#endif + int ss_timeout; +}; + +/* structure passed to decoder. */ +struct imageviewer_info { + const struct imgview_settings *settings; + int x_size, y_size; /* set size of loaded image in load_image(). */ + int width, height; /* set size of resized image in get_image(). */ + int x, y; /* display position */ + void *data; /* use freely in decoder. not touched in ui. */ +}; + +/* use this to show progress of loading file etc. */ +extern void cb_progress(int current, int total); + +extern bool slideshow_enabled; +extern bool running_slideshow; +#ifndef SIMULATOR +extern bool immediate_ata_off; +#endif +#if PLUGIN_BUFFER_SIZE >= MIN_MEM +extern bool plug_buf; +#endif + +/* + * functions needed to be implemented in each image decoders. + */ +/* return true if ext is supported by the decoder. */ +extern bool img_ext(const char ext[]); +/* draw part of image */ +extern void draw_image_rect(struct imageviewer_info *info, + int x, int y, int width, int height); +extern int img_mem(struct imageviewer_info *info, int ds); +/* load image from filename. set width and height of info properly. alos, set + * buf_size to remaining size of buf after load image. it is used to caluclate + * min downscale. */ +extern int load_image(char *filename, struct imageviewer_info *info, + unsigned char *buf, ssize_t *buf_size); +/* downscale image by ds. note that buf to store reszied image is not + * provided. return PLUGIN_ERROR for error. ui will skip to next image. */ +extern int get_image(struct imageviewer_info *info, int ds); + +#endif /* _IMGVIEW_IMGVIEW_H */