From 5617f3ba5cab42d43710ff193ab8cdebd7cef812 Mon Sep 17 00:00:00 2001 From: Jörg Hohensohn Date: Thu, 18 Dec 2003 22:36:35 +0000 Subject: the vidoe player has some control now: backward, pause, step, FF/FR git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4163 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/video.c | 210 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 181 insertions(+), 29 deletions(-) (limited to 'apps') diff --git a/apps/plugins/video.c b/apps/plugins/video.c index 292b61a69c..c08708b19c 100644 --- a/apps/plugins/video.c +++ b/apps/plugins/video.c @@ -25,12 +25,120 @@ #ifndef SIMULATOR /* not for simulator by now */ #ifdef HAVE_LCD_BITMAP /* and definitely not for the Player, haha */ -#define DEFAULT_FILENAME "/default.rvf" +#define INT_MAX ((int)(~(unsigned)0 >> 1)) +#define INT_MIN (-INT_MAX-1) + #define SCREENSIZE (LCD_WIDTH*LCD_HEIGHT/8) /* in bytes */ #define FILEBUFSIZE SCREENSIZE*4 /* must result in a multiple of 512 */ +#define WIND_STEP 5 + + +/* globals */ static struct plugin_api* rb; /* here is a global api struct pointer */ +static enum +{ + playing, + paused, + stop, + exit +} state = playing; + +static int playstep = 1; /* forcurrent speed and direction */ +static long time; /* to calculate the playing time */ + + +/* test for button, returns relative frame and may change state */ +int check_button(void) +{ + int button; + int frame; + bool loop; + + frame = playstep; /* default */ + + do + { + loop = false; + if (state == playing) + button = rb->button_get(false); + else + { + long current = *rb->current_tick; + button = rb->button_get(true); /* block */ + time += *rb->current_tick - current; /* don't time while waiting */ + } + + switch(button) + { + case BUTTON_NONE: + break; /* quick exit */ + + case BUTTON_LEFT | BUTTON_REPEAT: + if (state == paused) + frame = -1; /* single step back */ + else if (state == playing) + playstep = -WIND_STEP; /* FR */ + break; + + case BUTTON_RIGHT | BUTTON_REPEAT: + if (state == paused) + frame = 1; /* single step */ + else if (state == playing) + playstep = WIND_STEP; /* FF */ + break; + + case BUTTON_PLAY: + if (state == playing && playstep == 1) + state = paused; + else if (state == paused) + state = playing; + playstep = 1; + break; + + case BUTTON_LEFT: + if (state == paused) + frame = -1; /* single step back */ + else if (state == playing) + playstep = -1; /* rewind */ + break; + + case BUTTON_RIGHT: + if (state == paused) + frame = 1; /* single step */ + else if (state == playing) + playstep = 1; /* forward */ + break; + + case BUTTON_UP: + if (state == paused) + frame = INT_MAX; /* end of clip */ + break; + + case BUTTON_DOWN: + frame = INT_MIN; /* start of clip */ + break; + + case BUTTON_OFF: + state = stop; + break; + + case SYS_USB_CONNECTED: + state = exit; + break; + + default: + if (state != playing) + loop = true; + } + } + while (loop); + + return frame; +} + + int WaitForButton(void) { int button; @@ -50,36 +158,44 @@ int show_buffer(unsigned char* p_start, int frames) unsigned char* p_current = p_start; unsigned char* p_end = p_start + SCREENSIZE * frames; int shown = 0; - int button; + int delta; /* next frame */ do { rb->lcd_blit(p_current, 0, 0, LCD_WIDTH, LCD_HEIGHT/8, LCD_WIDTH); - p_current += SCREENSIZE; - if (p_current >= p_end) - p_current = p_start; /* wrap */ rb->yield(); /* yield to the other treads */ shown++; - button = rb->button_get(false); - } while(button != BUTTON_OFF && button != SYS_USB_CONNECTED); + delta = check_button(); + if (delta == INT_MIN) + p_current = p_start; + else if (delta == INT_MAX) + p_current = p_end - SCREENSIZE; + else + { + p_current += delta * SCREENSIZE; + if (p_current >= p_end || p_current < p_start) + p_current = p_start; /* wrap */ + } + + } while(state != stop && state != exit); - return (button != SYS_USB_CONNECTED) ? shown : SYS_USB_CONNECTED; + return (state != exit) ? shown : -1; } /* play from file, exit if OFF is pressed */ int show_file(unsigned char* p_buffer, int fd) { - int got_now; /* how many gotten for this frame */ int shown = 0; - int button = BUTTON_NONE; + int delta; /* next frame */ /* tricky buffer handling to read only whole sectors, then no copying needed */ unsigned char* p_file = p_buffer; /* file read */ unsigned char* p_screen = p_buffer; /* display */ unsigned char* p_end = p_buffer + FILEBUFSIZE; /* for wraparound test */ int needed; /* read how much data to complete a frame */ + int got_now; /* how many gotten for this frame */ int read_now; /* size to read for this frame, 512 or 1024 */ do @@ -98,19 +214,54 @@ int show_file(unsigned char* p_buffer, int fd) if (p_file >= p_end) p_file = p_buffer; /* wrap */ + delta = check_button(); + if (read_now < SCREENSIZE) /* below average? time to do something else */ - { rb->yield(); /* yield to the other treads */ - button = rb->button_get(false); + + if (delta != 1) + { /* need to seek */ + long newpos; + + rb->yield(); /* yield in case we didn't do it above */ + + if (delta == INT_MIN) + newpos = 0; + else if (delta == INT_MAX) + newpos = rb->filesize(fd) - SCREENSIZE; + else + { + bool pause = false; + newpos = rb->lseek(fd, 0, SEEK_CUR) - (p_file - p_screen) + (delta-1) * SCREENSIZE; + + if (newpos < 0) + { + newpos = 0; + pause = true; /* go in paused mode */ + } + + if (newpos > rb->filesize(fd) - SCREENSIZE) + { + newpos = rb->filesize(fd) - SCREENSIZE; + pause = true; /* go in paused mode */ + } + + if (pause && state == playing) + state = paused; + } + + newpos -= newpos % SCREENSIZE; /* should be "even", just to make shure */ + + rb->lseek(fd, newpos & ~(SECTOR_SIZE-1), SEEK_SET); /* round down to sector */ + newpos %= FILEBUFSIZE; /* make it an offset within buffer */ + p_screen = p_buffer + newpos; + p_file = p_buffer + (newpos & ~(SECTOR_SIZE-1)); } shown++; + } while (got_now >= needed && state != stop && state != exit); - } while (got_now >= needed - && button != BUTTON_OFF - && button != SYS_USB_CONNECTED); - - return (button != SYS_USB_CONNECTED) ? shown : SYS_USB_CONNECTED; + return (state != exit) ? shown : -1; } @@ -122,19 +273,13 @@ int main(char* filename) int fd; /* file descriptor handle */ int got_now; /* how many bytes read from file */ int frames, shown; - long time; int button; + int fps; p_buffer = rb->plugin_get_buffer(&buffer_size); if (buffer_size < FILEBUFSIZE) return PLUGIN_ERROR; /* not enough memory */ - /* compose filename if none given */ - if (filename == NULL) - { - filename = DEFAULT_FILENAME; - } - fd = rb->open(filename, O_RDONLY); if (fd < 0) return PLUGIN_ERROR; @@ -157,17 +302,17 @@ int main(char* filename) rb->close(fd); } - rb->close(fd); - - if (shown == SYS_USB_CONNECTED) /* exception */ + if (shown == -1) /* exception */ return PLUGIN_USB_CONNECTED; + fps = (shown * HZ *100) / time; /* 100 times fps */ + rb->lcd_clear_display(); - rb->snprintf(buf, sizeof(buf), "%d frames", shown); + rb->snprintf(buf, sizeof(buf), "%d frames shown", shown); rb->lcd_puts(0, 0, buf); rb->snprintf(buf, sizeof(buf), "%d.%02d seconds", time/HZ, time%HZ); rb->lcd_puts(0, 1, buf); - rb->snprintf(buf, sizeof(buf), "%d fps", (shown * HZ + time/2) / time); + rb->snprintf(buf, sizeof(buf), "%d.%02d fps", fps/100, fps%100); rb->lcd_puts(0, 2, buf); rb->snprintf(buf, sizeof(buf), "file: %d bytes", file_size); rb->lcd_puts(0, 6, buf); @@ -177,6 +322,7 @@ int main(char* filename) button = WaitForButton(); return (button == SYS_USB_CONNECTED) ? PLUGIN_USB_CONNECTED : PLUGIN_OK; + } @@ -191,6 +337,12 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) rb = api; /* copy to global api pointer */ + if (parameter == NULL) + { + rb->splash(HZ*2, 0, true, "play .rfv file"); + return PLUGIN_ERROR; + } + /* now go ahead and have fun! */ return main((char*) parameter); } -- cgit v1.2.3