/*************************************************************************** * * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2002 Gilles Roux * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include "plugin.h" #define BUFFER_SIZE 1024 #define OUTSIDE_BUFFER -10 #define OUTSIDE_FILE -11 static int fd; static int file_size; static char buffer[BUFFER_SIZE+1]; static int buffer_pos; /* Position of the buffer in the file */ static char display_lines; /* number of lines on the display */ static char display_columns; /* number of columns on the display */ static int begin_line; /* Index of the first line displayed on the lcd */ static int end_line; /* Index of the last line displayed on the lcd */ static int begin_line_pos; /* Position of the first_line in the bufffer */ static int end_line_pos; /* Position of the last_line in the buffer */ static struct plugin_api* rb; /* * Known issue: The caching algorithm will fail (display incoherent data) if * the total space of the lines that are displayed on the screen exceeds the * buffer size (only happens with very long lines). */ static void display_line_count(void) { #ifdef HAVE_LCD_BITMAP int w,h; rb->lcd_getstringsize("M", &w, &h); display_lines = LCD_HEIGHT / h; display_columns = LCD_WIDTH / w; #else display_lines = 2; display_columns = 11; #endif } static int find_next_line(int pos) { int i; if (pos==OUTSIDE_BUFFER || pos==OUTSIDE_FILE) return pos; i = pos; if (buffer_pos+i>=file_size) { return OUTSIDE_FILE; } while (1) { i++; if (buffer_pos+i==file_size) { return i; } if (i>=BUFFER_SIZE) { return OUTSIDE_BUFFER; } if (buffer[i]==0) { return i; } } } static int find_prev_line(int pos) { int i; if (pos==OUTSIDE_BUFFER || pos==OUTSIDE_FILE) return pos; i = pos; if (buffer_pos+i<0) { return OUTSIDE_FILE; } while (1) { i--; if (buffer_pos+i<0) { return i; } if (i<0) { return OUTSIDE_BUFFER; } if (buffer[i]==0) { return i; } } } static void viewer_draw(int col) { int i, j; char* str; int line_pos; rb->lcd_clear_display(); line_pos = begin_line_pos; for (i=0; i <= end_line - begin_line; i++) { if (line_pos == OUTSIDE_BUFFER || line_pos == OUTSIDE_FILE) break; str = buffer + line_pos + 1; for (j=0; jlcd_puts(0, i, str); line_pos = find_next_line(line_pos); } #ifdef HAVE_LCD_BITMAP rb->lcd_update(); #endif } static void fill_buffer(int pos) { int i; int numread; if (pos>=file_size-BUFFER_SIZE) pos = file_size-BUFFER_SIZE; if (pos<0) pos = 0; rb->lseek(fd, pos, SEEK_SET); numread = rb->read(fd, buffer, BUFFER_SIZE); begin_line_pos -= pos - buffer_pos; end_line_pos -= pos - buffer_pos; buffer_pos = pos; buffer[numread] = 0; for(i=0;iopen(file, O_RDONLY); if (fd==-1) return false; file_size = rb->lseek(fd, 0, SEEK_END); buffer_pos = 0; begin_line = 0; begin_line_pos = -1; end_line = -1; end_line_pos = -1; fill_buffer(0); display_line_count(); for (i=0; iclose(fd); } static void viewer_scroll_down(void) { int ret; ret = find_next_line(end_line_pos); switch ( ret ) { case OUTSIDE_BUFFER: begin_line_pos = find_next_line(begin_line_pos); fill_buffer(begin_line_pos+buffer_pos); end_line_pos = find_next_line(end_line_pos); break; case OUTSIDE_FILE: return; default: begin_line_pos = find_next_line(begin_line_pos); end_line_pos = ret; break; } begin_line++; end_line++; } static void viewer_scroll_up(void) { int ret; ret = find_prev_line(begin_line_pos); switch ( ret ) { case OUTSIDE_BUFFER: end_line_pos = find_prev_line(end_line_pos); fill_buffer(buffer_pos+end_line_pos-BUFFER_SIZE); begin_line_pos = find_prev_line(begin_line_pos); break; case OUTSIDE_FILE: return; default: end_line_pos = find_prev_line(end_line_pos); begin_line_pos = ret; break; } begin_line--; end_line--; } static int pagescroll(int col) { bool exit = false; int i; while (!exit) { switch (rb->button_get(true)) { #ifdef HAVE_RECORDER_KEYPAD case BUTTON_ON | BUTTON_UP: case BUTTON_ON | BUTTON_UP | BUTTON_REPEAT: #else case BUTTON_ON | BUTTON_LEFT: case BUTTON_ON | BUTTON_LEFT | BUTTON_REPEAT: #endif for (i=0; isplash(HZ, 0, false, "Error"); viewer_exit(); return PLUGIN_OK; } viewer_draw(col); while (!exit) { button = rb->button_get(true); switch ( button ) { #ifdef HAVE_RECORDER_KEYPAD case BUTTON_F1: case BUTTON_OFF: #else case BUTTON_STOP: #endif viewer_exit(); exit = true; break; #ifdef HAVE_RECORDER_KEYPAD case BUTTON_UP: case BUTTON_UP | BUTTON_REPEAT: #else case BUTTON_LEFT: case BUTTON_LEFT | BUTTON_REPEAT: #endif viewer_scroll_up(); viewer_draw(col); break; #ifdef HAVE_RECORDER_KEYPAD case BUTTON_DOWN: case BUTTON_DOWN | BUTTON_REPEAT: #else case BUTTON_RIGHT: case BUTTON_RIGHT | BUTTON_REPEAT: #endif viewer_scroll_down(); viewer_draw(col); break; #ifdef HAVE_RECORDER_KEYPAD case BUTTON_LEFT: case BUTTON_LEFT | BUTTON_REPEAT: #else case BUTTON_MENU | BUTTON_LEFT: case BUTTON_MENU | BUTTON_LEFT | BUTTON_REPEAT: #endif col--; if (col < 0) col = 0; viewer_draw(col); break; #ifdef HAVE_RECORDER_KEYPAD case BUTTON_RIGHT: case BUTTON_RIGHT | BUTTON_REPEAT: #else case BUTTON_MENU | BUTTON_RIGHT: case BUTTON_MENU | BUTTON_RIGHT | BUTTON_REPEAT: #endif col++; viewer_draw(col); break; case BUTTON_ON: #ifdef HAVE_PLAYER_KEYPAD case BUTTON_ON | BUTTON_MENU: #endif col = pagescroll(col); break; case SYS_USB_CONNECTED: rb->usb_screen(); viewer_exit(); return PLUGIN_USB_CONNECTED; } } return PLUGIN_OK; }