diff options
-rw-r--r-- | apps/plugins/video.c | 213 |
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 | ||
48 | static int playstep = 1; /* forcurrent speed and direction */ | 45 | static int playstep = 1; /* for current speed and direction */ |
46 | static int acceleration = 0; | ||
49 | static long time; /* to calculate the playing time */ | 47 | static long time; /* to calculate the playing time */ |
50 | 48 | ||
51 | 49 | ||
@@ -53,7 +51,7 @@ static long time; /* to calculate the playing time */ | |||
53 | int check_button(void) | 51 | int 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 */ |
189 | int show_file(unsigned char* p_buffer, int fd) | 187 | int 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 | |||