summaryrefslogtreecommitdiff
path: root/apps/misc.c
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2009-02-10 23:43:37 +0000
committerJens Arnold <amiconn@rockbox.org>2009-02-10 23:43:37 +0000
commit11ad7b4bc8bcb049040c02fae04074faf5dfaf27 (patch)
treece92c57120cb9b019743a863083f654e8d80f95f /apps/misc.c
parenteddb5680f9aefecdaccf24279cff2d3cf4fd5d86 (diff)
downloadrockbox-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.c330
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. */
146char *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. */
215char *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 */
243bool warn_on_pl_erase(void) 140bool 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
381static 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
424static void (*screen_dump_hook)(int fh) = NULL;
425
426void 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
562void 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