diff options
author | Björn Stenberg <bjorn@haxx.se> | 2003-06-29 16:33:04 +0000 |
---|---|---|
committer | Björn Stenberg <bjorn@haxx.se> | 2003-06-29 16:33:04 +0000 |
commit | ba371fb595affd68c823926b85718d1d613dc7d3 (patch) | |
tree | cfda303d0603d623cdb12f3928905d3ae02f1d87 /apps/plugins/viewer.c | |
parent | 9bcbe3fd723d23a709873a0855f27b86bc5c96f1 (diff) | |
download | rockbox-ba371fb595affd68c823926b85718d1d613dc7d3.tar.gz rockbox-ba371fb595affd68c823926b85718d1d613dc7d3.zip |
Added plugin loader. Moved games, demos and the text viewer to loadable plugins. Copy your *.rock files to /.rockbox/rocks/
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3769 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/viewer.c')
-rw-r--r-- | apps/plugins/viewer.c | 415 |
1 files changed, 415 insertions, 0 deletions
diff --git a/apps/plugins/viewer.c b/apps/plugins/viewer.c new file mode 100644 index 0000000000..f8dc309a6e --- /dev/null +++ b/apps/plugins/viewer.c | |||
@@ -0,0 +1,415 @@ | |||
1 | /*************************************************************************** | ||
2 | * | ||
3 | * __________ __ ___. | ||
4 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
5 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
6 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
7 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
8 | * \/ \/ \/ \/ \/ | ||
9 | * $Id$ | ||
10 | * | ||
11 | * Copyright (C) 2002 Gilles Roux | ||
12 | * | ||
13 | * All files in this archive are subject to the GNU General Public License. | ||
14 | * See the file COPYING in the source tree root for full license agreement. | ||
15 | * | ||
16 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
17 | * KIND, either express or implied. | ||
18 | * | ||
19 | ****************************************************************************/ | ||
20 | #include "plugin.h" | ||
21 | |||
22 | #define BUFFER_SIZE 1024 | ||
23 | #define OUTSIDE_BUFFER -10 | ||
24 | #define OUTSIDE_FILE -11 | ||
25 | |||
26 | static int fd; | ||
27 | static int file_size; | ||
28 | |||
29 | static char buffer[BUFFER_SIZE+1]; | ||
30 | static int buffer_pos; /* Position of the buffer in the file */ | ||
31 | |||
32 | static char display_lines; /* number of lines on the display */ | ||
33 | static char display_columns; /* number of columns on the display */ | ||
34 | static int begin_line; /* Index of the first line displayed on the lcd */ | ||
35 | static int end_line; /* Index of the last line displayed on the lcd */ | ||
36 | static int begin_line_pos; /* Position of the first_line in the bufffer */ | ||
37 | static int end_line_pos; /* Position of the last_line in the buffer */ | ||
38 | static struct plugin_api* rb; | ||
39 | |||
40 | /* | ||
41 | * Known issue: The caching algorithm will fail (display incoherent data) if | ||
42 | * the total space of the lines that are displayed on the screen exceeds the | ||
43 | * buffer size (only happens with very long lines). | ||
44 | */ | ||
45 | |||
46 | static void display_line_count(void) | ||
47 | { | ||
48 | #ifdef HAVE_LCD_BITMAP | ||
49 | int w,h; | ||
50 | rb->lcd_getstringsize("M", &w, &h); | ||
51 | display_lines = LCD_HEIGHT / h; | ||
52 | display_columns = LCD_WIDTH / w; | ||
53 | #else | ||
54 | display_lines = 2; | ||
55 | display_columns = 11; | ||
56 | #endif | ||
57 | } | ||
58 | |||
59 | static int find_next_line(int pos) | ||
60 | { | ||
61 | int i; | ||
62 | |||
63 | if (pos==OUTSIDE_BUFFER || pos==OUTSIDE_FILE) | ||
64 | return pos; | ||
65 | |||
66 | i = pos; | ||
67 | if (buffer_pos+i>=file_size) { | ||
68 | return OUTSIDE_FILE; | ||
69 | } | ||
70 | while (1) { | ||
71 | i++; | ||
72 | if (buffer_pos+i==file_size) { | ||
73 | return i; | ||
74 | } | ||
75 | if (i>=BUFFER_SIZE) { | ||
76 | return OUTSIDE_BUFFER; | ||
77 | } | ||
78 | if (buffer[i]==0) { | ||
79 | return i; | ||
80 | } | ||
81 | } | ||
82 | } | ||
83 | |||
84 | static int find_prev_line(int pos) | ||
85 | { | ||
86 | int i; | ||
87 | |||
88 | if (pos==OUTSIDE_BUFFER || pos==OUTSIDE_FILE) | ||
89 | return pos; | ||
90 | |||
91 | i = pos; | ||
92 | if (buffer_pos+i<0) { | ||
93 | return OUTSIDE_FILE; | ||
94 | } | ||
95 | while (1) { | ||
96 | i--; | ||
97 | if (buffer_pos+i<0) { | ||
98 | return i; | ||
99 | } | ||
100 | if (i<0) { | ||
101 | return OUTSIDE_BUFFER; | ||
102 | } | ||
103 | if (buffer[i]==0) { | ||
104 | return i; | ||
105 | } | ||
106 | } | ||
107 | } | ||
108 | |||
109 | static void viewer_draw(int col) | ||
110 | { | ||
111 | int i, j; | ||
112 | char* str; | ||
113 | int line_pos; | ||
114 | |||
115 | rb->lcd_clear_display(); | ||
116 | |||
117 | line_pos = begin_line_pos; | ||
118 | |||
119 | for (i=0; i <= end_line - begin_line; i++) { | ||
120 | if (line_pos == OUTSIDE_BUFFER || | ||
121 | line_pos == OUTSIDE_FILE) | ||
122 | break; | ||
123 | str = buffer + line_pos + 1; | ||
124 | for (j=0; j<col && *str!=0; ++j) | ||
125 | str++; | ||
126 | rb->lcd_puts(0, i, str); | ||
127 | line_pos = find_next_line(line_pos); | ||
128 | } | ||
129 | #ifdef HAVE_LCD_BITMAP | ||
130 | rb->lcd_update(); | ||
131 | #endif | ||
132 | } | ||
133 | |||
134 | static void fill_buffer(int pos) | ||
135 | { | ||
136 | int i; | ||
137 | int numread; | ||
138 | |||
139 | if (pos>=file_size-BUFFER_SIZE) | ||
140 | pos = file_size-BUFFER_SIZE; | ||
141 | if (pos<0) | ||
142 | pos = 0; | ||
143 | |||
144 | rb->lseek(fd, pos, SEEK_SET); | ||
145 | numread = rb->read(fd, buffer, BUFFER_SIZE); | ||
146 | |||
147 | begin_line_pos -= pos - buffer_pos; | ||
148 | end_line_pos -= pos - buffer_pos; | ||
149 | buffer_pos = pos; | ||
150 | |||
151 | buffer[numread] = 0; | ||
152 | for(i=0;i<numread;i++) { | ||
153 | switch(buffer[i]) { | ||
154 | case '\r': | ||
155 | buffer[i] = ' '; | ||
156 | break; | ||
157 | case '\n': | ||
158 | buffer[i] = 0; | ||
159 | break; | ||
160 | default: | ||
161 | break; | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | |||
166 | static bool viewer_init(char* file) | ||
167 | { | ||
168 | int i; | ||
169 | int ret; | ||
170 | |||
171 | fd = rb->open(file, O_RDONLY); | ||
172 | if (fd==-1) | ||
173 | return false; | ||
174 | |||
175 | file_size = rb->lseek(fd, 0, SEEK_END); | ||
176 | |||
177 | buffer_pos = 0; | ||
178 | begin_line = 0; | ||
179 | begin_line_pos = -1; | ||
180 | end_line = -1; | ||
181 | end_line_pos = -1; | ||
182 | fill_buffer(0); | ||
183 | display_line_count(); | ||
184 | for (i=0; i<display_lines; ++i) { | ||
185 | ret = find_next_line(end_line_pos); | ||
186 | if (ret!=OUTSIDE_FILE && ret!=OUTSIDE_BUFFER) { | ||
187 | end_line_pos = ret; | ||
188 | end_line++; | ||
189 | } | ||
190 | } | ||
191 | |||
192 | return true; | ||
193 | } | ||
194 | |||
195 | static void viewer_exit(void) | ||
196 | { | ||
197 | rb->close(fd); | ||
198 | } | ||
199 | |||
200 | static void viewer_scroll_down(void) | ||
201 | { | ||
202 | int ret; | ||
203 | |||
204 | ret = find_next_line(end_line_pos); | ||
205 | switch ( ret ) { | ||
206 | case OUTSIDE_BUFFER: | ||
207 | begin_line_pos = find_next_line(begin_line_pos); | ||
208 | fill_buffer(begin_line_pos+buffer_pos); | ||
209 | end_line_pos = find_next_line(end_line_pos); | ||
210 | break; | ||
211 | |||
212 | case OUTSIDE_FILE: | ||
213 | return; | ||
214 | |||
215 | default: | ||
216 | begin_line_pos = find_next_line(begin_line_pos); | ||
217 | end_line_pos = ret; | ||
218 | break; | ||
219 | } | ||
220 | begin_line++; | ||
221 | end_line++; | ||
222 | } | ||
223 | |||
224 | static void viewer_scroll_up(void) | ||
225 | { | ||
226 | int ret; | ||
227 | |||
228 | ret = find_prev_line(begin_line_pos); | ||
229 | switch ( ret ) { | ||
230 | case OUTSIDE_BUFFER: | ||
231 | end_line_pos = find_prev_line(end_line_pos); | ||
232 | fill_buffer(buffer_pos+end_line_pos-BUFFER_SIZE); | ||
233 | begin_line_pos = find_prev_line(begin_line_pos); | ||
234 | break; | ||
235 | |||
236 | case OUTSIDE_FILE: | ||
237 | return; | ||
238 | |||
239 | default: | ||
240 | end_line_pos = find_prev_line(end_line_pos); | ||
241 | begin_line_pos = ret; | ||
242 | break; | ||
243 | } | ||
244 | begin_line--; | ||
245 | end_line--; | ||
246 | } | ||
247 | |||
248 | static int pagescroll(int col) | ||
249 | { | ||
250 | bool exit = false; | ||
251 | int i; | ||
252 | |||
253 | while (!exit) { | ||
254 | switch (rb->button_get(true)) { | ||
255 | #ifdef HAVE_RECORDER_KEYPAD | ||
256 | case BUTTON_ON | BUTTON_UP: | ||
257 | case BUTTON_ON | BUTTON_UP | BUTTON_REPEAT: | ||
258 | #else | ||
259 | case BUTTON_ON | BUTTON_LEFT: | ||
260 | case BUTTON_ON | BUTTON_LEFT | BUTTON_REPEAT: | ||
261 | #endif | ||
262 | for (i=0; i<display_lines; i++) | ||
263 | viewer_scroll_up(); | ||
264 | break; | ||
265 | |||
266 | #ifdef HAVE_RECORDER_KEYPAD | ||
267 | case BUTTON_ON | BUTTON_DOWN: | ||
268 | case BUTTON_ON | BUTTON_DOWN | BUTTON_REPEAT: | ||
269 | #else | ||
270 | case BUTTON_ON | BUTTON_RIGHT: | ||
271 | case BUTTON_ON | BUTTON_RIGHT | BUTTON_REPEAT: | ||
272 | #endif | ||
273 | for (i=0; i<display_lines; i++) | ||
274 | viewer_scroll_down(); | ||
275 | break; | ||
276 | |||
277 | #ifdef HAVE_RECORDER_KEYPAD | ||
278 | case BUTTON_ON | BUTTON_LEFT: | ||
279 | case BUTTON_ON | BUTTON_LEFT | BUTTON_REPEAT: | ||
280 | #else | ||
281 | case BUTTON_ON | BUTTON_MENU | BUTTON_LEFT: | ||
282 | case BUTTON_ON | BUTTON_MENU | BUTTON_LEFT | BUTTON_REPEAT: | ||
283 | #endif | ||
284 | col -= display_columns; | ||
285 | if (col < 0) | ||
286 | col = 0; | ||
287 | break; | ||
288 | |||
289 | #ifdef HAVE_RECORDER_KEYPAD | ||
290 | case BUTTON_ON | BUTTON_RIGHT: | ||
291 | case BUTTON_ON | BUTTON_RIGHT | BUTTON_REPEAT: | ||
292 | #else | ||
293 | case BUTTON_ON | BUTTON_MENU | BUTTON_RIGHT: | ||
294 | case BUTTON_ON | BUTTON_MENU | BUTTON_RIGHT | BUTTON_REPEAT: | ||
295 | #endif | ||
296 | col += display_columns; | ||
297 | break; | ||
298 | |||
299 | case BUTTON_ON | BUTTON_REL: | ||
300 | #ifdef HAVE_RECORDER_KEYPAD | ||
301 | case BUTTON_ON | BUTTON_DOWN | BUTTON_REL: | ||
302 | case BUTTON_ON | BUTTON_UP | BUTTON_REL: | ||
303 | #else | ||
304 | case BUTTON_ON | BUTTON_RIGHT | BUTTON_REL: | ||
305 | case BUTTON_ON | BUTTON_LEFT | BUTTON_REL: | ||
306 | case BUTTON_ON | BUTTON_MENU | BUTTON_RIGHT | BUTTON_REL: | ||
307 | case BUTTON_ON | BUTTON_MENU | BUTTON_LEFT | BUTTON_REL: | ||
308 | #endif | ||
309 | exit = true; | ||
310 | break; | ||
311 | } | ||
312 | if ( !exit ) | ||
313 | viewer_draw(col); | ||
314 | } | ||
315 | |||
316 | return col; | ||
317 | } | ||
318 | |||
319 | enum plugin_status plugin_start(struct plugin_api* api, void* file) | ||
320 | { | ||
321 | bool exit=false; | ||
322 | int button; | ||
323 | int col = 0; | ||
324 | int ok; | ||
325 | |||
326 | TEST_PLUGIN_API(api); | ||
327 | rb = api; | ||
328 | |||
329 | if (!file) | ||
330 | return PLUGIN_ERROR; | ||
331 | |||
332 | ok = viewer_init(file); | ||
333 | if (!ok) { | ||
334 | rb->splash(HZ, 0, false, "Error"); | ||
335 | viewer_exit(); | ||
336 | return PLUGIN_OK; | ||
337 | } | ||
338 | |||
339 | viewer_draw(col); | ||
340 | while (!exit) { | ||
341 | button = rb->button_get(true); | ||
342 | |||
343 | switch ( button ) { | ||
344 | |||
345 | #ifdef HAVE_RECORDER_KEYPAD | ||
346 | case BUTTON_F1: | ||
347 | case BUTTON_OFF: | ||
348 | #else | ||
349 | case BUTTON_STOP: | ||
350 | #endif | ||
351 | viewer_exit(); | ||
352 | exit = true; | ||
353 | break; | ||
354 | |||
355 | #ifdef HAVE_RECORDER_KEYPAD | ||
356 | case BUTTON_UP: | ||
357 | case BUTTON_UP | BUTTON_REPEAT: | ||
358 | #else | ||
359 | case BUTTON_LEFT: | ||
360 | case BUTTON_LEFT | BUTTON_REPEAT: | ||
361 | #endif | ||
362 | viewer_scroll_up(); | ||
363 | viewer_draw(col); | ||
364 | break; | ||
365 | |||
366 | #ifdef HAVE_RECORDER_KEYPAD | ||
367 | case BUTTON_DOWN: | ||
368 | case BUTTON_DOWN | BUTTON_REPEAT: | ||
369 | #else | ||
370 | case BUTTON_RIGHT: | ||
371 | case BUTTON_RIGHT | BUTTON_REPEAT: | ||
372 | #endif | ||
373 | viewer_scroll_down(); | ||
374 | viewer_draw(col); | ||
375 | break; | ||
376 | |||
377 | #ifdef HAVE_RECORDER_KEYPAD | ||
378 | case BUTTON_LEFT: | ||
379 | case BUTTON_LEFT | BUTTON_REPEAT: | ||
380 | #else | ||
381 | case BUTTON_MENU | BUTTON_LEFT: | ||
382 | case BUTTON_MENU | BUTTON_LEFT | BUTTON_REPEAT: | ||
383 | #endif | ||
384 | col--; | ||
385 | if (col < 0) | ||
386 | col = 0; | ||
387 | viewer_draw(col); | ||
388 | break; | ||
389 | |||
390 | #ifdef HAVE_RECORDER_KEYPAD | ||
391 | case BUTTON_RIGHT: | ||
392 | case BUTTON_RIGHT | BUTTON_REPEAT: | ||
393 | #else | ||
394 | case BUTTON_MENU | BUTTON_RIGHT: | ||
395 | case BUTTON_MENU | BUTTON_RIGHT | BUTTON_REPEAT: | ||
396 | #endif | ||
397 | col++; | ||
398 | viewer_draw(col); | ||
399 | break; | ||
400 | |||
401 | case BUTTON_ON: | ||
402 | #ifdef HAVE_PLAYER_KEYPAD | ||
403 | case BUTTON_ON | BUTTON_MENU: | ||
404 | #endif | ||
405 | col = pagescroll(col); | ||
406 | break; | ||
407 | |||
408 | case SYS_USB_CONNECTED: | ||
409 | rb->usb_screen(); | ||
410 | viewer_exit(); | ||
411 | return PLUGIN_USB_CONNECTED; | ||
412 | } | ||
413 | } | ||
414 | return PLUGIN_OK; | ||
415 | } | ||