summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/plugins/video.c213
1 files changed, 126 insertions, 87 deletions
diff --git a/apps/plugins/video.c b/apps/plugins/video.c
index c07519ed3d..5a2c28ca2b 100644
--- a/apps/plugins/video.c
+++ b/apps/plugins/video.c
@@ -20,18 +20,15 @@
20* 20*
21****************************************************************************/ 21****************************************************************************/
22#include "plugin.h" 22#include "plugin.h"
23#include "system.h" 23#include "../apps/recorder/widgets.h" /* not in search path, booh */
24 24
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 INT_MAX ((int)(~(unsigned)0 >> 1))
29#define INT_MIN (-INT_MAX-1)
30
31#define SCREENSIZE (LCD_WIDTH*LCD_HEIGHT/8) /* in bytes */ 28#define SCREENSIZE (LCD_WIDTH*LCD_HEIGHT/8) /* in bytes */
32#define FILEBUFSIZE SCREENSIZE*4 /* must result in a multiple of 512 */ 29#define FILEBUFSIZE (SCREENSIZE*4) /* must result in a multiple of 512 */
33 30
34#define WIND_STEP 5 31#define WIND_MAX 9
35 32
36 33
37/* globals */ 34/* globals */
@@ -45,7 +42,8 @@ static enum
45 exit 42 exit
46} state = playing; 43} state = playing;
47 44
48static int playstep = 1; /* forcurrent speed and direction */ 45static int playstep = 1; /* for current speed and direction */
46static int acceleration = 0;
49static long time; /* to calculate the playing time */ 47static long time; /* to calculate the playing time */
50 48
51 49
@@ -53,7 +51,7 @@ static long time; /* to calculate the playing time */
53int check_button(void) 51int check_button(void)
54{ 52{
55 int button; 53 int button;
56 int frame; 54 int frame; /* result: relative frame */
57 bool loop; 55 bool loop;
58 56
59 frame = playstep; /* default */ 57 frame = playstep; /* default */
@@ -79,22 +77,37 @@ int check_button(void)
79 if (state == paused) 77 if (state == paused)
80 frame = -1; /* single step back */ 78 frame = -1; /* single step back */
81 else if (state == playing) 79 else if (state == playing)
82 playstep = -WIND_STEP; /* FR */ 80 {
81 acceleration--;
82 playstep = acceleration/4; /* FR */
83 if (playstep > -2)
84 playstep = -2;
85 if (playstep < -WIND_MAX)
86 playstep = -WIND_MAX;
87 }
83 break; 88 break;
84 89
85 case BUTTON_RIGHT | BUTTON_REPEAT: 90 case BUTTON_RIGHT | BUTTON_REPEAT:
86 if (state == paused) 91 if (state == paused)
87 frame = 1; /* single step */ 92 frame = 1; /* single step */
88 else if (state == playing) 93 else if (state == playing)
89 playstep = WIND_STEP; /* FF */ 94 {
95 acceleration++;
96 playstep = acceleration/4; /* FF */
97 if (playstep < 2)
98 playstep = 2;
99 if (playstep > WIND_MAX)
100 playstep = WIND_MAX;
101 }
90 break; 102 break;
91 103
92 case BUTTON_PLAY: 104 case BUTTON_PLAY:
93 if (state == playing && playstep == 1) 105 if (state == playing && (playstep == 1 || playstep == -1))
94 state = paused; 106 state = paused;
95 else if (state == paused) 107 else if (state == paused)
96 state = playing; 108 state = playing;
97 playstep = 1; 109 playstep = 1;
110 acceleration = 0;
98 break; 111 break;
99 112
100 case BUTTON_LEFT: 113 case BUTTON_LEFT:
@@ -102,6 +115,7 @@ int check_button(void)
102 frame = -1; /* single step back */ 115 frame = -1; /* single step back */
103 else if (state == playing) 116 else if (state == playing)
104 playstep = -1; /* rewind */ 117 playstep = -1; /* rewind */
118 acceleration = 0;
105 break; 119 break;
106 120
107 case BUTTON_RIGHT: 121 case BUTTON_RIGHT:
@@ -109,15 +123,7 @@ int check_button(void)
109 frame = 1; /* single step */ 123 frame = 1; /* single step */
110 else if (state == playing) 124 else if (state == playing)
111 playstep = 1; /* forward */ 125 playstep = 1; /* forward */
112 break; 126 acceleration = 0;
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; 127 break;
122 128
123 case BUTTON_OFF: 129 case BUTTON_OFF:
@@ -168,17 +174,9 @@ int show_buffer(unsigned char* p_start, int frames)
168 shown++; 174 shown++;
169 175
170 delta = check_button(); 176 delta = check_button();
171 if (delta == INT_MIN) 177 p_current += delta * SCREENSIZE;
172 p_current = p_start; 178 if (p_current >= p_end || p_current < p_start)
173 else if (delta == INT_MAX) 179 p_current = p_start; /* wrap */
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); 180 } while(state != stop && state != exit);
183 181
184 return (state != exit) ? shown : -1; 182 return (state != exit) ? shown : -1;
@@ -188,78 +186,118 @@ int show_buffer(unsigned char* p_start, int frames)
188/* play from file, exit if OFF is pressed */ 186/* play from file, exit if OFF is pressed */
189int show_file(unsigned char* p_buffer, int fd) 187int show_file(unsigned char* p_buffer, int fd)
190{ 188{
189 long tag[FILEBUFSIZE/512]; /* I treat the buffer as direct-mapped cache */
190 long framepos = 0; /* position of frame in file */
191 long filesize = rb->filesize(fd);
192 long filepos = 0; /* my own counting */
191 int shown = 0; 193 int shown = 0;
192 int delta; /* next frame */
193 /* tricky buffer handling to read only whole sectors, then no copying needed */
194 unsigned char* p_file = p_buffer; /* file read */
195 unsigned char* p_screen = p_buffer; /* display */
196 unsigned char* p_end = p_buffer + FILEBUFSIZE; /* for wraparound test */
197 int needed; /* read how much data to complete a frame */
198 int got_now; /* how many gotten for this frame */
199 int read_now; /* size to read for this frame, 512 or 1024 */
200 194
201 do 195 long readfrom;
202 { 196 long readto;
203 needed = SCREENSIZE - (p_file - p_screen); /* minus what we have */ 197 int read; /* amount read from disk */
204 read_now = (needed + (SECTOR_SIZE-1)) & ~(SECTOR_SIZE-1); /* round up to whole sectors */ 198 long frame_offset; /* pos of frame in buffer */
205 199 long writefrom; /* round down to sector */
206 got_now = rb->read(fd, p_file, read_now); /* read the sector(s) */ 200 long sector; /* sector in frame buffer */
207 rb->lcd_blit(p_screen, 0, 0, LCD_WIDTH, LCD_HEIGHT/8, LCD_WIDTH); 201 long pos_aligned, orig_aligned; /* round down to sector */
208 202 char buf[10];
209 p_screen += SCREENSIZE; 203
210 if (p_screen >= p_end) 204 rb->memset(&tag, 0xFF, sizeof(tag)); /* invalidate cache */
211 p_screen = p_buffer; /* wrap */ 205
206 do
207 {
208 /* load the frame into memory */
209 readfrom = readto = -1; /* invalidate */
210 frame_offset = framepos % FILEBUFSIZE; /* pos of frame in buffer */
211 writefrom = frame_offset & ~511; /* round down to sector */
212 sector = frame_offset / 512; /* sector in frame buffer */
213 orig_aligned = pos_aligned = framepos & ~511; /* down to sector */
214
215 do
216 {
217 if (tag[sector] != pos_aligned) /* in cache? */
218 { /* not cached */
219 tag[sector] = pos_aligned;
220 if (readfrom == -1) /* not used yet? */
221 {
222 readfrom = pos_aligned; /* set start */
223 writefrom += pos_aligned - orig_aligned;
224 }
225 readto = pos_aligned; /* set stop */
226 }
227 pos_aligned += 512;
228 sector++;
229 } while (pos_aligned < framepos + SCREENSIZE);
230
231 if (readfrom != -1)
232 { /* need to read from disk */
233 if (filepos != readfrom)
234 { /* need to seek */
235 filepos = rb->lseek(fd, readfrom, SEEK_SET);
236 }
237 read = readto - readfrom + 512;
238 /* read the sector(s) */
239 filepos += rb->read(fd, p_buffer + writefrom, read);
240 }
241 else
242 read = 0;
212 243
213 p_file += got_now; 244 if (read < SCREENSIZE) /* below average? */
214 if (p_file >= p_end) 245 rb->yield(); /* time to do something else */
215 p_file = p_buffer; /* wrap */
216 246
217 delta = check_button(); 247 /* display OSD if FF/FR */
248 if (playstep != 1 && playstep != -1)
249 {
250 int w,h;
218 251
219 if (read_now < SCREENSIZE) /* below average? time to do something else */ 252 if (playstep > 0)
220 rb->yield(); /* yield to the other treads */ 253 rb->snprintf(buf, sizeof(buf), "%d>>", playstep);
254 else
255 rb->snprintf(buf, sizeof(buf), "%d<<", -playstep);
221 256
222 if (delta != 1) 257 rb->lcd_getstringsize(buf, &w, &h);
223 { /* need to seek */ 258 rb->lcd_putsxy(0, LCD_HEIGHT-h, buf);
224 long newpos;
225 259
226 rb->yield(); /* yield in case we didn't do it above */ 260 w++;
261 rb->slidebar(w, LCD_HEIGHT-7, LCD_WIDTH-w, 7,
262 (100 * filepos)/filesize, Grow_Right);
263 rb->lcd_update_rect(0, LCD_HEIGHT-8, LCD_WIDTH, 8);
264 rb->lcd_blit(p_buffer + frame_offset, 0, 0,
265 LCD_WIDTH, LCD_HEIGHT/8 - 1, LCD_WIDTH);
266 }
267 else
268 { /* display the frame normally */
269 rb->lcd_blit(p_buffer + frame_offset, 0, 0, LCD_WIDTH,
270 LCD_HEIGHT/8, LCD_WIDTH);
271 }
227 272
228 if (delta == INT_MIN) 273 /* query keys to determine next frame */
229 newpos = 0; 274 framepos += check_button() * SCREENSIZE;
230 else if (delta == INT_MAX) 275 if (framepos <= 0)
231 newpos = rb->filesize(fd) - SCREENSIZE; 276 {
232 else 277 state = paused;
278 framepos = 0;
279 }
280 else if (framepos >= filesize)
281 {
282 if (state == playing)
233 { 283 {
234 bool pause = false; 284 if (playstep == 1)
235 newpos = rb->lseek(fd, 0, SEEK_CUR) - (p_file - p_screen) + (delta-1) * SCREENSIZE; 285 state = stop; /* reached the end while playing normally */
236 286 else
237 if (newpos < 0)
238 { 287 {
239 newpos = 0; 288 state = paused; /* it may have been FF */
240 pause = true; /* go in paused mode */ 289 playstep = 1;
241 } 290 }
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 } 291 }
252 292
253 newpos -= newpos % SCREENSIZE; /* should be "even", just to make shure */ 293 framepos = filesize - SCREENSIZE;
254 294 /* in case the file size is no integer multiple */
255 rb->lseek(fd, newpos & ~(SECTOR_SIZE-1), SEEK_SET); /* round down to sector */ 295 framepos -= framepos % SCREENSIZE;
256 newpos %= FILEBUFSIZE; /* make it an offset within buffer */
257 p_screen = p_buffer + newpos;
258 p_file = p_buffer + (newpos & ~(SECTOR_SIZE-1));
259 } 296 }
260 297
261 shown++; 298 shown++;
262 } while (got_now >= needed && state != stop && state != exit); 299
300 } while (state != stop && state != exit);
263 301
264 return (state != exit) ? shown : -1; 302 return (state != exit) ? shown : -1;
265} 303}
@@ -353,3 +391,4 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
353 391
354#endif /* #ifdef HAVE_LCD_BITMAP */ 392#endif /* #ifdef HAVE_LCD_BITMAP */
355#endif /* #ifndef SIMULATOR */ 393#endif /* #ifndef SIMULATOR */
394