summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
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 292b61a69c..c08708b19c 100644
--- a/apps/plugins/video.c
+++ b/apps/plugins/video.c
@@ -25,12 +25,120 @@
25#ifndef SIMULATOR /* not for simulator by now */ 25#ifndef SIMULATOR /* not for simulator by now */
26#ifdef HAVE_LCD_BITMAP /* and definitely not for the Player, haha */ 26#ifdef HAVE_LCD_BITMAP /* and definitely not for the Player, haha */
27 27
28#define DEFAULT_FILENAME "/default.rvf" 28#define INT_MAX ((int)(~(unsigned)0 >> 1))
29#define INT_MIN (-INT_MAX-1)
30
29#define SCREENSIZE (LCD_WIDTH*LCD_HEIGHT/8) /* in bytes */ 31#define SCREENSIZE (LCD_WIDTH*LCD_HEIGHT/8) /* in bytes */
30#define FILEBUFSIZE SCREENSIZE*4 /* must result in a multiple of 512 */ 32#define FILEBUFSIZE SCREENSIZE*4 /* must result in a multiple of 512 */
31 33
34#define WIND_STEP 5
35
36
37/* globals */
32static struct plugin_api* rb; /* here is a global api struct pointer */ 38static struct plugin_api* rb; /* here is a global api struct pointer */
33 39
40static enum
41{
42 playing,
43 paused,
44 stop,
45 exit
46} state = playing;
47
48static int playstep = 1; /* forcurrent speed and direction */
49static long time; /* to calculate the playing time */
50
51
52/* test for button, returns relative frame and may change state */
53int check_button(void)
54{
55 int button;
56 int frame;
57 bool loop;
58
59 frame = playstep; /* default */
60
61 do
62 {
63 loop = false;
64 if (state == playing)
65 button = rb->button_get(false);
66 else
67 {
68 long current = *rb->current_tick;
69 button = rb->button_get(true); /* block */
70 time += *rb->current_tick - current; /* don't time while waiting */
71 }
72
73 switch(button)
74 {
75 case BUTTON_NONE:
76 break; /* quick exit */
77
78 case BUTTON_LEFT | BUTTON_REPEAT:
79 if (state == paused)
80 frame = -1; /* single step back */
81 else if (state == playing)
82 playstep = -WIND_STEP; /* FR */
83 break;
84
85 case BUTTON_RIGHT | BUTTON_REPEAT:
86 if (state == paused)
87 frame = 1; /* single step */
88 else if (state == playing)
89 playstep = WIND_STEP; /* FF */
90 break;
91
92 case BUTTON_PLAY:
93 if (state == playing && playstep == 1)
94 state = paused;
95 else if (state == paused)
96 state = playing;
97 playstep = 1;
98 break;
99
100 case BUTTON_LEFT:
101 if (state == paused)
102 frame = -1; /* single step back */
103 else if (state == playing)
104 playstep = -1; /* rewind */
105 break;
106
107 case BUTTON_RIGHT:
108 if (state == paused)
109 frame = 1; /* single step */
110 else if (state == playing)
111 playstep = 1; /* forward */
112 break;
113
114 case BUTTON_UP:
115 if (state == paused)
116 frame = INT_MAX; /* end of clip */
117 break;
118
119 case BUTTON_DOWN:
120 frame = INT_MIN; /* start of clip */
121 break;
122
123 case BUTTON_OFF:
124 state = stop;
125 break;
126
127 case SYS_USB_CONNECTED:
128 state = exit;
129 break;
130
131 default:
132 if (state != playing)
133 loop = true;
134 }
135 }
136 while (loop);
137
138 return frame;
139}
140
141
34int WaitForButton(void) 142int WaitForButton(void)
35{ 143{
36 int button; 144 int button;
@@ -50,36 +158,44 @@ int show_buffer(unsigned char* p_start, int frames)
50 unsigned char* p_current = p_start; 158 unsigned char* p_current = p_start;
51 unsigned char* p_end = p_start + SCREENSIZE * frames; 159 unsigned char* p_end = p_start + SCREENSIZE * frames;
52 int shown = 0; 160 int shown = 0;
53 int button; 161 int delta; /* next frame */
54 162
55 do 163 do
56 { 164 {
57 rb->lcd_blit(p_current, 0, 0, LCD_WIDTH, LCD_HEIGHT/8, LCD_WIDTH); 165 rb->lcd_blit(p_current, 0, 0, LCD_WIDTH, LCD_HEIGHT/8, LCD_WIDTH);
58 p_current += SCREENSIZE;
59 if (p_current >= p_end)
60 p_current = p_start; /* wrap */
61 166
62 rb->yield(); /* yield to the other treads */ 167 rb->yield(); /* yield to the other treads */
63 shown++; 168 shown++;
64 169
65 button = rb->button_get(false); 170 delta = check_button();
66 } while(button != BUTTON_OFF && button != SYS_USB_CONNECTED); 171 if (delta == INT_MIN)
172 p_current = p_start;
173 else if (delta == INT_MAX)
174 p_current = p_end - SCREENSIZE;
175 else
176 {
177 p_current += delta * SCREENSIZE;
178 if (p_current >= p_end || p_current < p_start)
179 p_current = p_start; /* wrap */
180 }
181
182 } while(state != stop && state != exit);
67 183
68 return (button != SYS_USB_CONNECTED) ? shown : SYS_USB_CONNECTED; 184 return (state != exit) ? shown : -1;
69} 185}
70 186
71 187
72/* play from file, exit if OFF is pressed */ 188/* play from file, exit if OFF is pressed */
73int show_file(unsigned char* p_buffer, int fd) 189int show_file(unsigned char* p_buffer, int fd)
74{ 190{
75 int got_now; /* how many gotten for this frame */
76 int shown = 0; 191 int shown = 0;
77 int button = BUTTON_NONE; 192 int delta; /* next frame */
78 /* tricky buffer handling to read only whole sectors, then no copying needed */ 193 /* tricky buffer handling to read only whole sectors, then no copying needed */
79 unsigned char* p_file = p_buffer; /* file read */ 194 unsigned char* p_file = p_buffer; /* file read */
80 unsigned char* p_screen = p_buffer; /* display */ 195 unsigned char* p_screen = p_buffer; /* display */
81 unsigned char* p_end = p_buffer + FILEBUFSIZE; /* for wraparound test */ 196 unsigned char* p_end = p_buffer + FILEBUFSIZE; /* for wraparound test */
82 int needed; /* read how much data to complete a frame */ 197 int needed; /* read how much data to complete a frame */
198 int got_now; /* how many gotten for this frame */
83 int read_now; /* size to read for this frame, 512 or 1024 */ 199 int read_now; /* size to read for this frame, 512 or 1024 */
84 200
85 do 201 do
@@ -98,19 +214,54 @@ int show_file(unsigned char* p_buffer, int fd)
98 if (p_file >= p_end) 214 if (p_file >= p_end)
99 p_file = p_buffer; /* wrap */ 215 p_file = p_buffer; /* wrap */
100 216
217 delta = check_button();
218
101 if (read_now < SCREENSIZE) /* below average? time to do something else */ 219 if (read_now < SCREENSIZE) /* below average? time to do something else */
102 {
103 rb->yield(); /* yield to the other treads */ 220 rb->yield(); /* yield to the other treads */
104 button = rb->button_get(false); 221
222 if (delta != 1)
223 { /* need to seek */
224 long newpos;
225
226 rb->yield(); /* yield in case we didn't do it above */
227
228 if (delta == INT_MIN)
229 newpos = 0;
230 else if (delta == INT_MAX)
231 newpos = rb->filesize(fd) - SCREENSIZE;
232 else
233 {
234 bool pause = false;
235 newpos = rb->lseek(fd, 0, SEEK_CUR) - (p_file - p_screen) + (delta-1) * SCREENSIZE;
236
237 if (newpos < 0)
238 {
239 newpos = 0;
240 pause = true; /* go in paused mode */
241 }
242
243 if (newpos > rb->filesize(fd) - SCREENSIZE)
244 {
245 newpos = rb->filesize(fd) - SCREENSIZE;
246 pause = true; /* go in paused mode */
247 }
248
249 if (pause && state == playing)
250 state = paused;
251 }
252
253 newpos -= newpos % SCREENSIZE; /* should be "even", just to make shure */
254
255 rb->lseek(fd, newpos & ~(SECTOR_SIZE-1), SEEK_SET); /* round down to sector */
256 newpos %= FILEBUFSIZE; /* make it an offset within buffer */
257 p_screen = p_buffer + newpos;
258 p_file = p_buffer + (newpos & ~(SECTOR_SIZE-1));
105 } 259 }
106 260
107 shown++; 261 shown++;
262 } while (got_now >= needed && state != stop && state != exit);
108 263
109 } while (got_now >= needed 264 return (state != exit) ? shown : -1;
110 && button != BUTTON_OFF
111 && button != SYS_USB_CONNECTED);
112
113 return (button != SYS_USB_CONNECTED) ? shown : SYS_USB_CONNECTED;
114} 265}
115 266
116 267
@@ -122,19 +273,13 @@ int main(char* filename)
122 int fd; /* file descriptor handle */ 273 int fd; /* file descriptor handle */
123 int got_now; /* how many bytes read from file */ 274 int got_now; /* how many bytes read from file */
124 int frames, shown; 275 int frames, shown;
125 long time;
126 int button; 276 int button;
277 int fps;
127 278
128 p_buffer = rb->plugin_get_buffer(&buffer_size); 279 p_buffer = rb->plugin_get_buffer(&buffer_size);
129 if (buffer_size < FILEBUFSIZE) 280 if (buffer_size < FILEBUFSIZE)
130 return PLUGIN_ERROR; /* not enough memory */ 281 return PLUGIN_ERROR; /* not enough memory */
131 282
132 /* compose filename if none given */
133 if (filename == NULL)
134 {
135 filename = DEFAULT_FILENAME;
136 }
137
138 fd = rb->open(filename, O_RDONLY); 283 fd = rb->open(filename, O_RDONLY);
139 if (fd < 0) 284 if (fd < 0)
140 return PLUGIN_ERROR; 285 return PLUGIN_ERROR;
@@ -157,17 +302,17 @@ int main(char* filename)
157 rb->close(fd); 302 rb->close(fd);
158 } 303 }
159 304
160 rb->close(fd); 305 if (shown == -1) /* exception */
161
162 if (shown == SYS_USB_CONNECTED) /* exception */
163 return PLUGIN_USB_CONNECTED; 306 return PLUGIN_USB_CONNECTED;
164 307
308 fps = (shown * HZ *100) / time; /* 100 times fps */
309
165 rb->lcd_clear_display(); 310 rb->lcd_clear_display();
166 rb->snprintf(buf, sizeof(buf), "%d frames", shown); 311 rb->snprintf(buf, sizeof(buf), "%d frames shown", shown);
167 rb->lcd_puts(0, 0, buf); 312 rb->lcd_puts(0, 0, buf);
168 rb->snprintf(buf, sizeof(buf), "%d.%02d seconds", time/HZ, time%HZ); 313 rb->snprintf(buf, sizeof(buf), "%d.%02d seconds", time/HZ, time%HZ);
169 rb->lcd_puts(0, 1, buf); 314 rb->lcd_puts(0, 1, buf);
170 rb->snprintf(buf, sizeof(buf), "%d fps", (shown * HZ + time/2) / time); 315 rb->snprintf(buf, sizeof(buf), "%d.%02d fps", fps/100, fps%100);
171 rb->lcd_puts(0, 2, buf); 316 rb->lcd_puts(0, 2, buf);
172 rb->snprintf(buf, sizeof(buf), "file: %d bytes", file_size); 317 rb->snprintf(buf, sizeof(buf), "file: %d bytes", file_size);
173 rb->lcd_puts(0, 6, buf); 318 rb->lcd_puts(0, 6, buf);
@@ -177,6 +322,7 @@ int main(char* filename)
177 button = WaitForButton(); 322 button = WaitForButton();
178 return (button == SYS_USB_CONNECTED) ? PLUGIN_USB_CONNECTED : PLUGIN_OK; 323 return (button == SYS_USB_CONNECTED) ? PLUGIN_USB_CONNECTED : PLUGIN_OK;
179 324
325
180} 326}
181 327
182 328
@@ -191,6 +337,12 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
191 337
192 rb = api; /* copy to global api pointer */ 338 rb = api; /* copy to global api pointer */
193 339
340 if (parameter == NULL)
341 {
342 rb->splash(HZ*2, 0, true, "play .rfv file");
343 return PLUGIN_ERROR;
344 }
345
194 /* now go ahead and have fun! */ 346 /* now go ahead and have fun! */
195 return main((char*) parameter); 347 return main((char*) parameter);
196} 348}