summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorJörg Hohensohn <hohensoh@rockbox.org>2003-12-18 22:36:35 +0000
committerJörg Hohensohn <hohensoh@rockbox.org>2003-12-18 22:36:35 +0000
commit5617f3ba5cab42d43710ff193ab8cdebd7cef812 (patch)
tree285eb1099ce0e6028a5b98053a2c274de4f466f4 /apps
parent5199e8c62551b8296ba938200ebe74215ff1e5fb (diff)
downloadrockbox-5617f3ba5cab42d43710ff193ab8cdebd7cef812.zip
rockbox-5617f3ba5cab42d43710ff193ab8cdebd7cef812.tar.gz
rockbox-5617f3ba5cab42d43710ff193ab8cdebd7cef812.tar.bz2
rockbox-5617f3ba5cab42d43710ff193ab8cdebd7cef812.tar.xz
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
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/video.c210
1 files changed, 181 insertions, 29 deletions
diff --git a/apps/plugins/video.c b/apps/plugins/video.c
index 292b61a..c08708b 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);
}