diff options
author | Jens Arnold <amiconn@rockbox.org> | 2009-02-10 23:43:37 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2009-02-10 23:43:37 +0000 |
commit | 11ad7b4bc8bcb049040c02fae04074faf5dfaf27 (patch) | |
tree | ce92c57120cb9b019743a863083f654e8d80f95f /apps/misc.c | |
parent | eddb5680f9aefecdaccf24279cff2d3cf4fd5d86 (diff) | |
download | rockbox-11ad7b4bc8bcb049040c02fae04074faf5dfaf27.tar.gz rockbox-11ad7b4bc8bcb049040c02fae04074faf5dfaf27.zip |
Move screendump from apps to firmware, solving two nasty firmware-to-apps calls. This required to move the filename creation functions as well. * Fix bug in the BMP header of Clip screendumps. * Add remote screendump for targets with an LCD remote. * Simplify some ifdefs and rename a macro in the sim.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19967 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/misc.c')
-rw-r--r-- | apps/misc.c | 330 |
1 files changed, 0 insertions, 330 deletions
diff --git a/apps/misc.c b/apps/misc.c index b1d795708c..872d91592d 100644 --- a/apps/misc.c +++ b/apps/misc.c | |||
@@ -135,109 +135,6 @@ char *output_dyn_value(char *buf, int buf_size, int value, | |||
135 | return buf; | 135 | return buf; |
136 | } | 136 | } |
137 | 137 | ||
138 | /* Create a filename with a number part in a way that the number is 1 | ||
139 | * higher than the highest numbered file matching the same pattern. | ||
140 | * It is allowed that buffer and path point to the same memory location, | ||
141 | * saving a strcpy(). Path must always be given without trailing slash. | ||
142 | * "num" can point to an int specifying the number to use or NULL or a value | ||
143 | * less than zero to number automatically. The final number used will also | ||
144 | * be returned in *num. If *num is >= 0 then *num will be incremented by | ||
145 | * one. */ | ||
146 | char *create_numbered_filename(char *buffer, const char *path, | ||
147 | const char *prefix, const char *suffix, | ||
148 | int numberlen IF_CNFN_NUM_(, int *num)) | ||
149 | { | ||
150 | DIR *dir; | ||
151 | struct dirent *entry; | ||
152 | int max_num; | ||
153 | int pathlen; | ||
154 | int prefixlen = strlen(prefix); | ||
155 | char fmtstring[12]; | ||
156 | |||
157 | if (buffer != path) | ||
158 | strncpy(buffer, path, MAX_PATH); | ||
159 | |||
160 | pathlen = strlen(buffer); | ||
161 | |||
162 | #ifdef IF_CNFN_NUM | ||
163 | if (num && *num >= 0) | ||
164 | { | ||
165 | /* number specified */ | ||
166 | max_num = *num; | ||
167 | } | ||
168 | else | ||
169 | #endif | ||
170 | { | ||
171 | /* automatic numbering */ | ||
172 | max_num = 0; | ||
173 | |||
174 | dir = opendir(pathlen ? buffer : "/"); | ||
175 | if (!dir) | ||
176 | return NULL; | ||
177 | |||
178 | while ((entry = readdir(dir))) | ||
179 | { | ||
180 | int curr_num; | ||
181 | |||
182 | if (strncasecmp((char *)entry->d_name, prefix, prefixlen) | ||
183 | || strcasecmp((char *)entry->d_name + prefixlen + numberlen, suffix)) | ||
184 | continue; | ||
185 | |||
186 | curr_num = atoi((char *)entry->d_name + prefixlen); | ||
187 | if (curr_num > max_num) | ||
188 | max_num = curr_num; | ||
189 | } | ||
190 | |||
191 | closedir(dir); | ||
192 | } | ||
193 | |||
194 | max_num++; | ||
195 | |||
196 | snprintf(fmtstring, sizeof(fmtstring), "/%%s%%0%dd%%s", numberlen); | ||
197 | snprintf(buffer + pathlen, MAX_PATH - pathlen, fmtstring, prefix, | ||
198 | max_num, suffix); | ||
199 | |||
200 | #ifdef IF_CNFN_NUM | ||
201 | if (num) | ||
202 | *num = max_num; | ||
203 | #endif | ||
204 | |||
205 | return buffer; | ||
206 | } | ||
207 | |||
208 | |||
209 | #if CONFIG_RTC | ||
210 | /* Create a filename with a date+time part. | ||
211 | It is allowed that buffer and path point to the same memory location, | ||
212 | saving a strcpy(). Path must always be given without trailing slash. | ||
213 | unique_time as true makes the function wait until the current time has | ||
214 | changed. */ | ||
215 | char *create_datetime_filename(char *buffer, const char *path, | ||
216 | const char *prefix, const char *suffix, | ||
217 | bool unique_time) | ||
218 | { | ||
219 | struct tm *tm = get_time(); | ||
220 | static struct tm last_tm; | ||
221 | int pathlen; | ||
222 | |||
223 | while (unique_time && !memcmp(get_time(), &last_tm, sizeof (struct tm))) | ||
224 | sleep(HZ/10); | ||
225 | |||
226 | last_tm = *tm; | ||
227 | |||
228 | if (buffer != path) | ||
229 | strncpy(buffer, path, MAX_PATH); | ||
230 | |||
231 | pathlen = strlen(buffer); | ||
232 | snprintf(buffer + pathlen, MAX_PATH - pathlen, | ||
233 | "/%s%02d%02d%02d-%02d%02d%02d%s", prefix, | ||
234 | tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, | ||
235 | tm->tm_hour, tm->tm_min, tm->tm_sec, suffix); | ||
236 | |||
237 | return buffer; | ||
238 | } | ||
239 | #endif /* CONFIG_RTC */ | ||
240 | |||
241 | /* Ask the user if they really want to erase the current dynamic playlist | 138 | /* Ask the user if they really want to erase the current dynamic playlist |
242 | * returns true if the playlist should be replaced */ | 139 | * returns true if the playlist should be replaced */ |
243 | bool warn_on_pl_erase(void) | 140 | bool warn_on_pl_erase(void) |
@@ -339,233 +236,6 @@ int fast_readline(int fd, char *buf, int buf_size, void *parameters, | |||
339 | return 0; | 236 | return 0; |
340 | } | 237 | } |
341 | 238 | ||
342 | #ifdef HAVE_LCD_BITMAP | ||
343 | |||
344 | #if LCD_DEPTH == 16 | ||
345 | #define BMP_COMPRESSION 3 /* BI_BITFIELDS */ | ||
346 | #define BMP_NUMCOLORS 3 | ||
347 | #else /* LCD_DEPTH != 16 */ | ||
348 | #define BMP_COMPRESSION 0 /* BI_RGB */ | ||
349 | #if LCD_DEPTH <= 8 | ||
350 | #ifdef HAVE_LCD_SPLIT | ||
351 | #define BMP_NUMCOLORS (2 << LCD_DEPTH) | ||
352 | #else | ||
353 | #define BMP_NUMCOLORS (1 << LCD_DEPTH) | ||
354 | #endif | ||
355 | #else /* LCD_DEPTH > 8 */ | ||
356 | #define BMP_NUMCOLORS 0 | ||
357 | #endif /* LCD_DEPTH > 8 */ | ||
358 | #endif /* LCD_DEPTH != 16 */ | ||
359 | |||
360 | #if LCD_DEPTH <= 4 | ||
361 | #define BMP_BPP 4 | ||
362 | #define BMP_LINESIZE ((LCD_WIDTH/2 + 3) & ~3) | ||
363 | #elif LCD_DEPTH <= 8 | ||
364 | #define BMP_BPP 8 | ||
365 | #define BMP_LINESIZE ((LCD_WIDTH + 3) & ~3) | ||
366 | #elif LCD_DEPTH <= 16 | ||
367 | #define BMP_BPP 16 | ||
368 | #define BMP_LINESIZE ((LCD_WIDTH*2 + 3) & ~3) | ||
369 | #else | ||
370 | #define BMP_BPP 24 | ||
371 | #define BMP_LINESIZE ((LCD_WIDTH*3 + 3) & ~3) | ||
372 | #endif | ||
373 | |||
374 | #define BMP_HEADERSIZE (54 + 4 * BMP_NUMCOLORS) | ||
375 | #define BMP_DATASIZE (BMP_LINESIZE * LCD_HEIGHT) | ||
376 | #define BMP_TOTALSIZE (BMP_HEADERSIZE + BMP_DATASIZE) | ||
377 | |||
378 | #define LE16_CONST(x) (x)&0xff, ((x)>>8)&0xff | ||
379 | #define LE32_CONST(x) (x)&0xff, ((x)>>8)&0xff, ((x)>>16)&0xff, ((x)>>24)&0xff | ||
380 | |||
381 | static const unsigned char bmpheader[] = | ||
382 | { | ||
383 | 0x42, 0x4d, /* 'BM' */ | ||
384 | LE32_CONST(BMP_TOTALSIZE), /* Total file size */ | ||
385 | 0x00, 0x00, 0x00, 0x00, /* Reserved */ | ||
386 | LE32_CONST(BMP_HEADERSIZE), /* Offset to start of pixel data */ | ||
387 | |||
388 | 0x28, 0x00, 0x00, 0x00, /* Size of (2nd) header */ | ||
389 | LE32_CONST(LCD_WIDTH), /* Width in pixels */ | ||
390 | LE32_CONST(LCD_HEIGHT+LCD_SPLIT_LINES), /* Height in pixels */ | ||
391 | 0x01, 0x00, /* Number of planes (always 1) */ | ||
392 | LE16_CONST(BMP_BPP), /* Bits per pixel 1/4/8/16/24 */ | ||
393 | LE32_CONST(BMP_COMPRESSION),/* Compression mode */ | ||
394 | LE32_CONST(BMP_DATASIZE), /* Size of bitmap data */ | ||
395 | 0xc4, 0x0e, 0x00, 0x00, /* Horizontal resolution (pixels/meter) */ | ||
396 | 0xc4, 0x0e, 0x00, 0x00, /* Vertical resolution (pixels/meter) */ | ||
397 | LE32_CONST(BMP_NUMCOLORS), /* Number of used colours */ | ||
398 | LE32_CONST(BMP_NUMCOLORS), /* Number of important colours */ | ||
399 | |||
400 | #if LCD_DEPTH == 1 | ||
401 | #ifdef HAVE_NEGATIVE_LCD | ||
402 | BMP_COLOR(LCD_BL_DARKCOLOR), | ||
403 | BMP_COLOR(LCD_BL_BRIGHTCOLOR), | ||
404 | #ifdef HAVE_LCD_SPLIT | ||
405 | BMP_COLOR(LCD_BL_DARKCOLOR_2), | ||
406 | BMP_COLOR(LCD_BL_BRIGHTCOLOR_2), | ||
407 | #endif | ||
408 | #else /* positive display */ | ||
409 | BMP_COLOR(LCD_BL_BRIGHTCOLOR), | ||
410 | BMP_COLOR(LCD_BL_DARKCOLOR), | ||
411 | #endif /* positive display */ | ||
412 | #elif LCD_DEPTH == 2 | ||
413 | BMP_COLOR(LCD_BL_BRIGHTCOLOR), | ||
414 | BMP_COLOR_MIX(LCD_BL_BRIGHTCOLOR, LCD_BL_DARKCOLOR, 1, 3), | ||
415 | BMP_COLOR_MIX(LCD_BL_BRIGHTCOLOR, LCD_BL_DARKCOLOR, 2, 3), | ||
416 | BMP_COLOR(LCD_BL_DARKCOLOR), | ||
417 | #elif LCD_DEPTH == 16 | ||
418 | 0x00, 0xf8, 0x00, 0x00, /* red bitfield mask */ | ||
419 | 0xe0, 0x07, 0x00, 0x00, /* green bitfield mask */ | ||
420 | 0x1f, 0x00, 0x00, 0x00, /* blue bitfield mask */ | ||
421 | #endif | ||
422 | }; | ||
423 | |||
424 | static void (*screen_dump_hook)(int fh) = NULL; | ||
425 | |||
426 | void screen_dump(void) | ||
427 | { | ||
428 | int fd, y; | ||
429 | char filename[MAX_PATH]; | ||
430 | |||
431 | fb_data *src; | ||
432 | #if LCD_DEPTH == 1 | ||
433 | unsigned mask; | ||
434 | unsigned val; | ||
435 | #elif (LCD_DEPTH == 2) && (LCD_PIXELFORMAT != HORIZONTAL_PACKING) | ||
436 | int shift; | ||
437 | unsigned val; | ||
438 | #endif | ||
439 | #if LCD_DEPTH <= 8 | ||
440 | unsigned char *dst, *dst_end; | ||
441 | unsigned char linebuf[BMP_LINESIZE]; | ||
442 | #elif LCD_DEPTH <= 16 | ||
443 | unsigned short *dst, *dst_end; | ||
444 | unsigned short linebuf[BMP_LINESIZE/2]; | ||
445 | #endif | ||
446 | |||
447 | #if CONFIG_RTC | ||
448 | create_datetime_filename(filename, "", "dump ", ".bmp", false); | ||
449 | #else | ||
450 | create_numbered_filename(filename, "", "dump_", ".bmp", 4 | ||
451 | IF_CNFN_NUM_(, NULL)); | ||
452 | #endif | ||
453 | |||
454 | fd = creat(filename); | ||
455 | if (fd < 0) | ||
456 | return; | ||
457 | |||
458 | if (screen_dump_hook) | ||
459 | { | ||
460 | screen_dump_hook(fd); | ||
461 | } | ||
462 | else | ||
463 | { | ||
464 | write(fd, bmpheader, sizeof(bmpheader)); | ||
465 | |||
466 | /* BMP image goes bottom up */ | ||
467 | for (y = LCD_HEIGHT - 1; y >= 0; y--) | ||
468 | { | ||
469 | memset(linebuf, 0, BMP_LINESIZE); | ||
470 | |||
471 | #if defined(HAVE_LCD_SPLIT) && (LCD_SPLIT_LINES == 2) | ||
472 | if (y == LCD_SPLIT_POS - 1) | ||
473 | { | ||
474 | write(fd, linebuf, BMP_LINESIZE); | ||
475 | write(fd, linebuf, BMP_LINESIZE); | ||
476 | } | ||
477 | #endif | ||
478 | dst = linebuf; | ||
479 | |||
480 | #if LCD_DEPTH == 1 | ||
481 | dst_end = dst + LCD_WIDTH/2; | ||
482 | src = lcd_framebuffer[y >> 3]; | ||
483 | mask = 1 << (y & 7); | ||
484 | |||
485 | do | ||
486 | { | ||
487 | val = (*src++ & mask) ? 0x10 : 0; | ||
488 | val |= (*src++ & mask) ? 0x01 : 0; | ||
489 | #ifdef HAVE_LCD_SPLIT | ||
490 | if (y < LCD_SPLIT_POS) | ||
491 | val |= 0x22; | ||
492 | #endif | ||
493 | *dst++ = val; | ||
494 | } | ||
495 | while (dst < dst_end); | ||
496 | |||
497 | #elif LCD_DEPTH == 2 | ||
498 | dst_end = dst + LCD_WIDTH/2; | ||
499 | |||
500 | #if LCD_PIXELFORMAT == HORIZONTAL_PACKING | ||
501 | src = lcd_framebuffer[y]; | ||
502 | |||
503 | do | ||
504 | { | ||
505 | unsigned data = *src++; | ||
506 | |||
507 | *dst++ = ((data >> 2) & 0x30) | ((data >> 4) & 0x03); | ||
508 | *dst++ = ((data << 2) & 0x30) | (data & 0x03); | ||
509 | } | ||
510 | while (dst < dst_end); | ||
511 | |||
512 | #elif LCD_PIXELFORMAT == VERTICAL_PACKING | ||
513 | src = lcd_framebuffer[y >> 2]; | ||
514 | shift = 2 * (y & 3); | ||
515 | |||
516 | do | ||
517 | { | ||
518 | val = ((*src++ >> shift) & 3) << 4; | ||
519 | val |= ((*src++ >> shift) & 3); | ||
520 | *dst++ = val; | ||
521 | } | ||
522 | while (dst < dst_end); | ||
523 | |||
524 | #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED | ||
525 | src = lcd_framebuffer[y >> 3]; | ||
526 | shift = y & 7; | ||
527 | |||
528 | do | ||
529 | { | ||
530 | unsigned data = (*src++ >> shift) & 0x0101; | ||
531 | |||
532 | val = (((data >> 7) | data) & 3) << 4; | ||
533 | data = (*src++ >> shift) & 0x0101; | ||
534 | val |= ((data >> 7) | data) & 3; | ||
535 | *dst++ = val; | ||
536 | } | ||
537 | while (dst < dst_end); | ||
538 | |||
539 | #endif | ||
540 | #elif LCD_DEPTH == 16 | ||
541 | dst_end = dst + LCD_WIDTH; | ||
542 | src = lcd_framebuffer[y]; | ||
543 | |||
544 | do | ||
545 | { | ||
546 | #if (LCD_PIXELFORMAT == RGB565SWAPPED) | ||
547 | /* iPod LCD data is big endian although the CPU is not */ | ||
548 | *dst++ = htobe16(*src++); | ||
549 | #else | ||
550 | *dst++ = htole16(*src++); | ||
551 | #endif | ||
552 | } | ||
553 | while (dst < dst_end); | ||
554 | |||
555 | #endif /* LCD_DEPTH */ | ||
556 | write(fd, linebuf, BMP_LINESIZE); | ||
557 | } | ||
558 | } | ||
559 | close(fd); | ||
560 | } | ||
561 | |||
562 | void screen_dump_set_hook(void (*hook)(int fh)) | ||
563 | { | ||
564 | screen_dump_hook = hook; | ||
565 | } | ||
566 | |||
567 | #endif /* HAVE_LCD_BITMAP */ | ||
568 | |||
569 | /* parse a line from a configuration file. the line format is: | 239 | /* parse a line from a configuration file. the line format is: |
570 | 240 | ||
571 | name: value | 241 | name: value |