Add "elfzip" target to make which creates a zip of all elf files, as mapzip does...
[maemo-rb.git] / apps / gui / skin_engine / skin_tokens.c
blobf455999b2ab58106e4f334ffa7c1797af581c98f
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002-2007 Björn Stenberg
11 * Copyright (C) 2007-2008 Nicolas Pennequin
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
22 #include "font.h"
23 #include <stdio.h>
24 #include "string-extra.h"
25 #include <stdlib.h>
26 #include "action.h"
27 #include "system.h"
28 #include "settings.h"
29 #include "settings_list.h"
30 #include "rbunicode.h"
31 #include "timefuncs.h"
32 #include "status.h"
33 #include "power.h"
34 #include "powermgmt.h"
35 #include "sound.h"
36 #include "debug.h"
37 #include "cuesheet.h"
38 #ifdef HAVE_LCD_CHARCELLS
39 #include "hwcompat.h"
40 #endif
41 #include "abrepeat.h"
42 #include "lang.h"
43 #include "misc.h"
44 #include "led.h"
45 #ifdef HAVE_LCD_BITMAP
46 #include "peakmeter.h"
47 /* Image stuff */
48 #include "albumart.h"
49 #endif
50 #include "dsp.h"
51 #include "playlist.h"
52 #if CONFIG_CODEC == SWCODEC
53 #include "playback.h"
54 #include "tdspeed.h"
55 #endif
56 #include "viewport.h"
57 #include "tagcache.h"
59 #include "wps_internals.h"
60 #include "skin_engine.h"
61 #include "statusbar-skinned.h"
62 #include "root_menu.h"
63 #ifdef HAVE_RECORDING
64 #include "recording.h"
65 #include "pcm_record.h"
66 #endif
67 #include "language.h"
68 #include "usb.h"
69 #if CONFIG_TUNER
70 #include "radio.h"
71 #include "tuner.h"
72 #endif
74 #define NOINLINE __attribute__ ((noinline))
76 extern struct wps_state wps_state;
78 static const char* get_codectype(const struct mp3entry* id3)
80 if (id3 && id3->codectype < AFMT_NUM_CODECS) {
81 return audio_formats[id3->codectype].label;
82 } else {
83 return NULL;
87 /* Extract a part from a path.
89 * buf - buffer extract part to.
90 * buf_size - size of buffer.
91 * path - path to extract from.
92 * level - what to extract. 0 is file name, 1 is parent of file, 2 is
93 * parent of parent, etc.
95 * Returns buf if the desired level was found, NULL otherwise.
97 char* get_dir(char* buf, int buf_size, const char* path, int level)
99 const char* sep;
100 const char* last_sep;
101 int len;
103 sep = path + strlen(path);
104 last_sep = sep;
106 while (sep > path)
108 if ('/' == *(--sep))
110 if (!level)
111 break;
113 level--;
114 last_sep = sep - 1;
118 if (level || (last_sep <= sep))
119 return NULL;
121 len = MIN(last_sep - sep, buf_size - 1);
122 strlcpy(buf, sep + 1, len + 1);
123 return buf;
126 #if (CONFIG_CODEC != MAS3507D) && defined (HAVE_PITCHSCREEN)
127 /* A helper to determine the enum value for pitch/speed.
129 When there are two choices (i.e. boolean), return 1 if the value is
130 different from normal value and 2 if the value is the same as the
131 normal value. E.g. "%?Sp<%Sp>" would show the pitch only when
132 playing at a modified pitch.
134 When there are more than two choices (i.e. enum), the left half of
135 the choices are to show 0..normal range, and the right half of the
136 choices are to show values over that. The last entry is used when
137 it is set to the normal setting, following the rockbox convention
138 to use the last entry for special values.
140 E.g.
142 2 items: %?Sp<0..99 or 101..infinity|100>
143 3 items: %?Sp<0..99|101..infinity|100>
144 4 items: %?Sp<0..49|50..99|101..infinity|100>
145 5 items: %?Sp<0..49|50..99|101..149|150..infinity|100>
146 6 items: %?Sp<0..33|34..66|67..99|101..133|134..infinity|100>
147 7 items: %?Sp<0..33|34..66|67..99|101..133|134..167|167..infinity|100>
149 static int pitch_speed_enum(int range, int32_t val, int32_t normval)
151 int center;
152 int n;
154 if (range < 3)
155 return (val == normval) + 1;
156 if (val == normval)
157 return range;
158 center = range / 2;
159 n = (center * val) / normval + 1;
160 return (range <= n) ? (range - 1) : n;
162 #endif
164 const char *get_cuesheetid3_token(struct wps_token *token, struct mp3entry *id3,
165 int offset_tracks, char *buf, int buf_size)
167 struct cuesheet *cue = id3?id3->cuesheet:NULL;
168 if (!cue || !cue->curr_track)
169 return NULL;
171 struct cue_track_info *track = cue->curr_track;
172 if (offset_tracks)
174 if (cue->curr_track_idx+offset_tracks < cue->track_count)
175 track+=offset_tracks;
176 else
177 return NULL;
179 switch (token->type)
181 case SKIN_TOKEN_METADATA_ARTIST:
182 return *track->performer ? track->performer : NULL;
183 case SKIN_TOKEN_METADATA_COMPOSER:
184 return *track->songwriter ? track->songwriter : NULL;
185 case SKIN_TOKEN_METADATA_ALBUM:
186 return *cue->title ? cue->title : NULL;
187 case SKIN_TOKEN_METADATA_ALBUM_ARTIST:
188 return *cue->performer ? cue->performer : NULL;
189 case SKIN_TOKEN_METADATA_TRACK_TITLE:
190 return *track->title ? track->title : NULL;
191 case SKIN_TOKEN_METADATA_TRACK_NUMBER:
192 snprintf(buf, buf_size, "%d/%d",
193 cue->curr_track_idx+offset_tracks+1, cue->track_count);
194 return buf;
195 default:
196 return NULL;
198 return NULL;
201 static const char* get_filename_token(struct wps_token *token, char* filename,
202 char *buf, int buf_size)
204 if (filename)
206 switch (token->type)
208 case SKIN_TOKEN_FILE_PATH:
209 return filename;
210 case SKIN_TOKEN_FILE_NAME:
211 if (get_dir(buf, buf_size, filename, 0)) {
212 /* Remove extension */
213 char* sep = strrchr(buf, '.');
214 if (NULL != sep) {
215 *sep = 0;
217 return buf;
219 return NULL;
220 case SKIN_TOKEN_FILE_NAME_WITH_EXTENSION:
221 return get_dir(buf, buf_size, filename, 0);
222 case SKIN_TOKEN_FILE_DIRECTORY:
223 return get_dir(buf, buf_size, filename, token->value.i);
224 default:
225 return NULL;
228 return NULL;
231 /* All tokens which only need the info to return a value go in here */
232 const char *get_id3_token(struct wps_token *token, struct mp3entry *id3,
233 char *filename, char *buf, int buf_size, int limit, int *intval)
235 struct wps_state *state = &wps_state;
236 if (id3)
238 unsigned long length = id3->length;
239 unsigned long elapsed = id3->elapsed + state->ff_rewind_count;
240 switch (token->type)
242 case SKIN_TOKEN_METADATA_ARTIST:
243 return id3->artist;
244 case SKIN_TOKEN_METADATA_COMPOSER:
245 return id3->composer;
246 case SKIN_TOKEN_METADATA_ALBUM:
247 return id3->album;
248 case SKIN_TOKEN_METADATA_ALBUM_ARTIST:
249 return id3->albumartist;
250 case SKIN_TOKEN_METADATA_GROUPING:
251 return id3->grouping;
252 case SKIN_TOKEN_METADATA_GENRE:
253 return id3->genre_string;
254 case SKIN_TOKEN_METADATA_DISC_NUMBER:
255 if (id3->disc_string)
256 return id3->disc_string;
257 if (id3->discnum) {
258 snprintf(buf, buf_size, "%d", id3->discnum);
259 return buf;
261 return NULL;
262 case SKIN_TOKEN_METADATA_TRACK_NUMBER:
263 if (id3->track_string)
264 return id3->track_string;
265 if (id3->tracknum) {
266 snprintf(buf, buf_size, "%d", id3->tracknum);
267 return buf;
269 return NULL;
270 case SKIN_TOKEN_METADATA_TRACK_TITLE:
271 return id3->title;
272 case SKIN_TOKEN_METADATA_VERSION:
273 switch (id3->id3version)
275 case ID3_VER_1_0:
276 return "1";
277 case ID3_VER_1_1:
278 return "1.1";
279 case ID3_VER_2_2:
280 return "2.2";
281 case ID3_VER_2_3:
282 return "2.3";
283 case ID3_VER_2_4:
284 return "2.4";
285 default:
286 break;
288 return NULL;
289 case SKIN_TOKEN_METADATA_YEAR:
290 if( id3->year_string )
291 return id3->year_string;
292 if (id3->year) {
293 snprintf(buf, buf_size, "%d", id3->year);
294 return buf;
296 return NULL;
297 case SKIN_TOKEN_METADATA_COMMENT:
298 return id3->comment;
299 case SKIN_TOKEN_FILE_BITRATE:
300 if(id3->bitrate)
301 snprintf(buf, buf_size, "%d", id3->bitrate);
302 else
303 return "?";
304 return buf;
305 case SKIN_TOKEN_TRACK_TIME_ELAPSED:
306 format_time(buf, buf_size, elapsed);
307 return buf;
309 case SKIN_TOKEN_TRACK_TIME_REMAINING:
310 format_time(buf, buf_size, length - elapsed);
311 return buf;
313 case SKIN_TOKEN_TRACK_LENGTH:
314 format_time(buf, buf_size, length);
315 return buf;
317 case SKIN_TOKEN_TRACK_ELAPSED_PERCENT:
318 if (length <= 0)
319 return NULL;
321 if (intval)
323 if (limit == TOKEN_VALUE_ONLY)
324 limit = 100; /* make it a percentage */
325 *intval = limit * elapsed / length + 1;
327 snprintf(buf, buf_size, "%lu", 100 * elapsed / length);
328 return buf;
330 case SKIN_TOKEN_TRACK_STARTING:
332 unsigned long time = token->value.i * (HZ/TIMEOUT_UNIT);
333 if (elapsed < time)
334 return "starting";
336 return NULL;
337 case SKIN_TOKEN_TRACK_ENDING:
339 unsigned long time = token->value.i * (HZ/TIMEOUT_UNIT);
340 if (length - elapsed < time)
341 return "ending";
343 return NULL;
345 case SKIN_TOKEN_FILE_CODEC:
346 if (intval)
348 if(id3->codectype == AFMT_UNKNOWN)
349 *intval = AFMT_NUM_CODECS;
350 else
351 *intval = id3->codectype;
353 return get_codectype(id3);
355 case SKIN_TOKEN_FILE_FREQUENCY:
356 snprintf(buf, buf_size, "%ld", id3->frequency);
357 return buf;
358 case SKIN_TOKEN_FILE_FREQUENCY_KHZ:
359 /* ignore remainders < 100, so 22050 Hz becomes just 22k */
360 if ((id3->frequency % 1000) < 100)
361 snprintf(buf, buf_size, "%ld", id3->frequency / 1000);
362 else
363 snprintf(buf, buf_size, "%ld.%lu",
364 id3->frequency / 1000,
365 (id3->frequency % 1000) / 100);
366 return buf;
367 case SKIN_TOKEN_FILE_VBR:
368 return (id3->vbr) ? "(avg)" : NULL;
369 case SKIN_TOKEN_FILE_SIZE:
370 snprintf(buf, buf_size, "%ld", id3->filesize / 1024);
371 return buf;
373 #ifdef HAVE_TAGCACHE
374 case SKIN_TOKEN_DATABASE_PLAYCOUNT:
375 if (intval)
376 *intval = id3->playcount + 1;
377 snprintf(buf, buf_size, "%ld", id3->playcount);
378 return buf;
379 case SKIN_TOKEN_DATABASE_RATING:
380 if (intval)
381 *intval = id3->rating + 1;
382 snprintf(buf, buf_size, "%d", id3->rating);
383 return buf;
384 case SKIN_TOKEN_DATABASE_AUTOSCORE:
385 if (intval)
386 *intval = id3->score + 1;
387 snprintf(buf, buf_size, "%d", id3->score);
388 return buf;
389 #endif
391 default:
392 return get_filename_token(token, id3->path, buf, buf_size);
395 else /* id3 == NULL, handle the error based on the expected return type */
397 switch (token->type)
399 /* Most tokens expect NULL on error so leave that for the default case,
400 * The ones that expect "0" need to be handled */
401 case SKIN_TOKEN_FILE_FREQUENCY:
402 case SKIN_TOKEN_FILE_FREQUENCY_KHZ:
403 case SKIN_TOKEN_FILE_SIZE:
404 #ifdef HAVE_TAGCACHE
405 case SKIN_TOKEN_DATABASE_PLAYCOUNT:
406 case SKIN_TOKEN_DATABASE_RATING:
407 case SKIN_TOKEN_DATABASE_AUTOSCORE:
408 #endif
409 if (intval)
410 *intval = 0;
411 return "0";
412 default:
413 return get_filename_token(token, filename, buf, buf_size);
416 return buf;
419 #if CONFIG_TUNER
421 /* Formats the frequency (specified in Hz) in MHz, */
422 /* with one or two digits after the decimal point -- */
423 /* depending on the frequency changing step. */
424 /* Returns buf */
425 static char *format_freq_MHz(int freq, int freq_step, char *buf, int buf_size)
427 int scale, div;
428 char *fmt;
429 if (freq_step < 100000)
431 /* Format with two digits after decimal point */
432 scale = 10000;
433 fmt = "%d.%02d";
435 else
437 /* Format with one digit after decimal point */
438 scale = 100000;
439 fmt = "%d.%d";
441 div = 1000000 / scale;
442 freq = freq / scale;
443 snprintf(buf, buf_size, fmt, freq/div, freq%div);
444 return buf;
448 /* Tokens which are really only used by the radio screen go in here */
449 const char *get_radio_token(struct wps_token *token, int preset_offset,
450 char *buf, int buf_size, int limit, int *intval)
452 const struct fm_region_data *region_data =
453 &(fm_region_data[global_settings.fm_region]);
454 (void)limit;
455 switch (token->type)
457 /* Radio/tuner tokens */
458 case SKIN_TOKEN_TUNER_TUNED:
459 if (tuner_get(RADIO_TUNED))
460 return "t";
461 return NULL;
462 case SKIN_TOKEN_TUNER_SCANMODE:
463 if (radio_scan_mode())
464 return "s";
465 return NULL;
466 case SKIN_TOKEN_TUNER_STEREO:
467 if (radio_is_stereo())
468 return "s";
469 return NULL;
470 case SKIN_TOKEN_TUNER_MINFREQ: /* changes based on "region" */
471 return format_freq_MHz(region_data->freq_min,
472 region_data->freq_step, buf, buf_size);
473 case SKIN_TOKEN_TUNER_MAXFREQ: /* changes based on "region" */
474 return format_freq_MHz(region_data->freq_max,
475 region_data->freq_step, buf, buf_size);
476 case SKIN_TOKEN_TUNER_CURFREQ:
477 return format_freq_MHz(radio_current_frequency(),
478 region_data->freq_step, buf, buf_size);
479 #ifdef HAVE_RADIO_RSSI
480 case SKIN_TOKEN_TUNER_RSSI:
481 snprintf(buf, buf_size, "%d",tuner_get(RADIO_RSSI));
482 if (intval)
484 int val = tuner_get(RADIO_RSSI);
485 int min = tuner_get(RADIO_RSSI_MIN);
486 int max = tuner_get(RADIO_RSSI_MAX);
487 if (limit == TOKEN_VALUE_ONLY)
489 *intval = val;
491 else
493 *intval = 1+(limit-1)*(val-min)/(max-1-min);
496 return buf;
497 case SKIN_TOKEN_TUNER_RSSI_MIN:
498 snprintf(buf, buf_size, "%d",tuner_get(RADIO_RSSI_MIN));
499 return buf;
500 case SKIN_TOKEN_TUNER_RSSI_MAX:
501 snprintf(buf, buf_size, "%d",tuner_get(RADIO_RSSI_MAX));
502 return buf;
503 #endif
504 case SKIN_TOKEN_PRESET_NAME:
505 case SKIN_TOKEN_PRESET_FREQ:
506 case SKIN_TOKEN_PRESET_ID:
508 int preset_count = radio_preset_count();
509 int cur_preset = radio_current_preset();
510 if (preset_count == 0 || cur_preset < 0)
511 return NULL;
512 int preset = cur_preset + preset_offset;
513 /* make sure it's in the valid range */
514 preset %= preset_count;
515 if (preset < 0)
516 preset += preset_count;
517 if (token->type == SKIN_TOKEN_PRESET_NAME)
518 snprintf(buf, buf_size, "%s", radio_get_preset(preset)->name);
519 else if (token->type == SKIN_TOKEN_PRESET_FREQ)
520 format_freq_MHz(radio_get_preset(preset)->frequency,
521 region_data->freq_step, buf, buf_size);
522 else
523 snprintf(buf, buf_size, "%d", preset + 1);
524 return buf;
526 case SKIN_TOKEN_PRESET_COUNT:
527 snprintf(buf, buf_size, "%d", radio_preset_count());
528 if (intval)
529 *intval = radio_preset_count();
530 return buf;
531 case SKIN_TOKEN_HAVE_RDS:
532 #ifdef HAVE_RDS_CAP
533 return "rds";
534 case SKIN_TOKEN_RDS_NAME:
535 return tuner_get_rds_info(RADIO_RDS_NAME);
536 case SKIN_TOKEN_RDS_TEXT:
537 return tuner_get_rds_info(RADIO_RDS_TEXT);
538 #else
539 return NULL; /* end of the SKIN_TOKEN_HAVE_RDS case */
540 #endif /* HAVE_RDS_CAP */
541 default:
542 return NULL;
544 return NULL;
546 #endif
548 static struct mp3entry* get_mp3entry_from_offset(int offset, char **filename)
550 struct mp3entry* pid3 = NULL;
551 struct wps_state *state = skin_get_global_state();
552 struct cuesheet *cue = state->id3 ? state->id3->cuesheet : NULL;
553 const char *fname = NULL;
554 if (cue && cue->curr_track_idx + offset < cue->track_count)
555 pid3 = state->id3;
556 else if (offset == 0)
557 pid3 = state->id3;
558 else if (offset == 1)
559 pid3 = state->nid3;
560 else
562 static char filename_buf[MAX_PATH + 1];
563 fname = playlist_peek(offset, filename_buf, sizeof(filename_buf));
564 *filename = (char*)fname;
565 #if CONFIG_CODEC == SWCODEC
566 static struct mp3entry tempid3;
567 if (
568 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
569 tagcache_fill_tags(&tempid3, fname) ||
570 #endif
571 audio_peek_track(&tempid3, offset)
574 pid3 = &tempid3;
576 #endif
578 return pid3;
581 #ifdef HAVE_LCD_CHARCELLS
582 static void format_player_progress(struct gui_wps *gwps)
584 struct wps_state *state = skin_get_global_state();
585 struct screen *display = gwps->display;
586 unsigned char progress_pattern[7];
587 int pos = 0;
588 int i;
590 int elapsed, length;
591 if (LIKELY(state->id3))
593 elapsed = state->id3->elapsed;
594 length = state->id3->length;
596 else
598 elapsed = 0;
599 length = 0;
602 if (length)
603 pos = 36 * (elapsed + state->ff_rewind_count) / length;
605 for (i = 0; i < 7; i++, pos -= 5)
607 if (pos <= 0)
608 progress_pattern[i] = 0x1fu;
609 else if (pos >= 5)
610 progress_pattern[i] = 0x00u;
611 else
612 progress_pattern[i] = 0x1fu >> pos;
615 display->define_pattern(gwps->data->wps_progress_pat[0], progress_pattern);
618 static void format_player_fullbar(struct gui_wps *gwps, char* buf, int buf_size)
620 static const unsigned char numbers[10][4] = {
621 {0x0e, 0x0a, 0x0a, 0x0e}, /* 0 */
622 {0x04, 0x0c, 0x04, 0x04}, /* 1 */
623 {0x0e, 0x02, 0x04, 0x0e}, /* 2 */
624 {0x0e, 0x02, 0x06, 0x0e}, /* 3 */
625 {0x08, 0x0c, 0x0e, 0x04}, /* 4 */
626 {0x0e, 0x0c, 0x02, 0x0c}, /* 5 */
627 {0x0e, 0x08, 0x0e, 0x0e}, /* 6 */
628 {0x0e, 0x02, 0x04, 0x08}, /* 7 */
629 {0x0e, 0x0e, 0x0a, 0x0e}, /* 8 */
630 {0x0e, 0x0e, 0x02, 0x0e} /* 9 */
633 struct wps_state *state = skin_get_global_state();
634 struct screen *display = gwps->display;
635 struct wps_data *data = gwps->data;
636 unsigned char progress_pattern[7];
637 char timestr[10];
638 int time;
639 int time_idx = 0;
640 int pos = 0;
641 int pat_idx = 1;
642 int digit, i, j;
643 bool softchar;
645 int elapsed, length;
646 if (LIKELY(state->id3))
648 elapsed = state->id3->elapsed;
649 length = state->id3->length;
651 else
653 elapsed = 0;
654 length = 0;
657 if (buf_size < 34) /* worst case: 11x UTF-8 char + \0 */
658 return;
660 time = elapsed + state->ff_rewind_count;
661 if (length)
662 pos = 55 * time / length;
664 memset(timestr, 0, sizeof(timestr));
665 format_time(timestr, sizeof(timestr)-2, time);
666 timestr[strlen(timestr)] = ':'; /* always safe */
668 for (i = 0; i < 11; i++, pos -= 5)
670 softchar = false;
671 memset(progress_pattern, 0, sizeof(progress_pattern));
673 if ((digit = timestr[time_idx]))
675 softchar = true;
676 digit -= '0';
678 if (timestr[time_idx + 1] == ':') /* ones, left aligned */
680 memcpy(progress_pattern, numbers[digit], 4);
681 time_idx += 2;
683 else /* tens, shifted right */
685 for (j = 0; j < 4; j++)
686 progress_pattern[j] = numbers[digit][j] >> 1;
688 if (time_idx > 0) /* not the first group, add colon in front */
690 progress_pattern[1] |= 0x10u;
691 progress_pattern[3] |= 0x10u;
693 time_idx++;
696 if (pos >= 5)
697 progress_pattern[5] = progress_pattern[6] = 0x1fu;
700 if (pos > 0 && pos < 5)
702 softchar = true;
703 progress_pattern[5] = progress_pattern[6] = (~0x1fu >> pos) & 0x1fu;
706 if (softchar && pat_idx < 8)
708 display->define_pattern(data->wps_progress_pat[pat_idx],
709 progress_pattern);
710 buf = utf8encode(data->wps_progress_pat[pat_idx], buf);
711 pat_idx++;
713 else if (pos <= 0)
714 buf = utf8encode(' ', buf);
715 else
716 buf = utf8encode(0xe115, buf); /* 2/7 _ */
718 *buf = '\0';
721 #endif /* HAVE_LCD_CHARCELLS */
723 /* Don't inline this; it was broken out of get_token_value to reduce stack
724 * usage.
726 static const char* NOINLINE get_lif_token_value(struct gui_wps *gwps,
727 struct logical_if *lif,
728 int offset, char *buf,
729 int buf_size)
731 int a = lif->num_options;
732 int b;
733 const char* out_text = get_token_value(gwps, lif->token, offset,
734 buf, buf_size, &a);
735 if (a == -1 && lif->token->type != SKIN_TOKEN_VOLUME)
736 a = (out_text && *out_text) ? 1 : 0;
737 switch (lif->operand.type)
739 case STRING:
740 if (lif->op == IF_EQUALS)
741 return (out_text && strcmp(out_text, lif->operand.data.text) == 0)
742 ? "eq" : NULL;
743 else
744 return NULL;
745 break;
746 case INTEGER:
747 case DECIMAL:
748 b = lif->operand.data.number;
749 break;
750 case CODE:
752 char temp_buf[MAX_PATH];
753 const char *outb;
754 struct wps_token *token = lif->operand.data.code->data;
755 b = lif->num_options;
756 outb = get_token_value(gwps, token, offset, temp_buf,
757 sizeof(temp_buf), &b);
758 if (b == -1 && lif->token->type != SKIN_TOKEN_VOLUME)
760 if (!out_text || !outb)
761 return (lif->op == IF_EQUALS) ? NULL : "neq";
762 bool equal = strcmp(out_text, outb) == 0;
763 if (lif->op == IF_EQUALS)
764 return equal ? "eq" : NULL;
765 else if (lif->op == IF_NOTEQUALS)
766 return !equal ? "neq" : NULL;
767 else
768 b = (outb && *outb) ? 1 : 0;
771 break;
772 case DEFAULT:
773 break;
776 switch (lif->op)
778 case IF_EQUALS:
779 return a == b ? "eq" : NULL;
780 case IF_NOTEQUALS:
781 return a != b ? "neq" : NULL;
782 case IF_LESSTHAN:
783 return a < b ? "lt" : NULL;
784 case IF_LESSTHAN_EQ:
785 return a <= b ? "lte" : NULL;
786 case IF_GREATERTHAN:
787 return a > b ? "gt" : NULL;
788 case IF_GREATERTHAN_EQ:
789 return a >= b ? "gte" : NULL;
791 return NULL;
794 /* Return the tags value as text. buf should be used as temp storage if needed.
796 intval is used with conditionals/enums: when this function is called,
797 intval should contain the number of options in the conditional/enum.
798 When this function returns, intval is -1 if the tag is non numeric or,
799 if the tag is numeric, *intval is the enum case we want to go to (between 1
800 and the original value of *intval, inclusive).
801 When not treating a conditional/enum, intval should be NULL.
803 const char *get_token_value(struct gui_wps *gwps,
804 struct wps_token *token, int offset,
805 char *buf, int buf_size,
806 int *intval)
808 if (!gwps)
809 return NULL;
811 struct wps_data *data = gwps->data;
812 struct wps_state *state = skin_get_global_state();
813 struct mp3entry *id3; /* Think very carefully about using this.
814 maybe get_id3_token() is the better place? */
815 const char *out_text = NULL;
816 char *filename = NULL;
818 if (!data || !state)
819 return NULL;
821 id3 = get_mp3entry_from_offset(token->next? 1: offset, &filename);
822 if (id3)
823 filename = id3->path;
825 #if CONFIG_RTC
826 struct tm* tm = NULL;
828 /* if the token is an RTC one, update the time
829 and do the necessary checks */
830 if (token->type >= SKIN_TOKENS_RTC_BEGIN
831 && token->type <= SKIN_TOKENS_RTC_END)
833 tm = get_time();
835 if (!valid_time(tm))
836 return NULL;
838 #endif
840 int limit = 1;
841 if (intval)
843 limit = *intval;
844 *intval = -1;
847 if (id3 && id3 == state->id3 && id3->cuesheet )
849 out_text = get_cuesheetid3_token(token, id3,
850 token->next?1:offset, buf, buf_size);
851 if (out_text)
852 return out_text;
854 out_text = get_id3_token(token, id3, filename, buf, buf_size, limit, intval);
855 if (out_text)
856 return out_text;
857 #if CONFIG_TUNER
858 out_text = get_radio_token(token, offset, buf, buf_size, limit, intval);
859 if (out_text)
860 return out_text;
861 #endif
863 switch (token->type)
865 case SKIN_TOKEN_LOGICAL_IF:
867 struct logical_if *lif = token->value.data;
868 return get_lif_token_value(gwps, lif, offset, buf, buf_size);
870 break;
872 case SKIN_TOKEN_CHARACTER:
873 if (token->value.c == '\n')
874 return NULL;
875 return &(token->value.c);
877 case SKIN_TOKEN_STRING:
878 return (char*)token->value.data;
880 case SKIN_TOKEN_TRANSLATEDSTRING:
881 return (char*)P2STR(ID2P(token->value.i));
883 case SKIN_TOKEN_PLAYLIST_ENTRIES:
884 snprintf(buf, buf_size, "%d", playlist_amount());
885 if (intval)
886 *intval = playlist_amount();
887 return buf;
888 #ifdef HAVE_LCD_BITMAP
889 case SKIN_TOKEN_LIST_TITLE_TEXT:
890 return sb_get_title(gwps->display->screen_type);
891 case SKIN_TOKEN_LIST_TITLE_ICON:
892 if (intval)
893 *intval = sb_get_icon(gwps->display->screen_type);
894 snprintf(buf, buf_size, "%d",sb_get_icon(gwps->display->screen_type));
895 return buf;
896 #endif
897 case SKIN_TOKEN_PLAYLIST_NAME:
898 return playlist_name(NULL, buf, buf_size);
900 case SKIN_TOKEN_PLAYLIST_POSITION:
901 snprintf(buf, buf_size, "%d", playlist_get_display_index()+offset);
902 if (intval)
903 *intval = playlist_get_display_index()+offset;
904 return buf;
906 case SKIN_TOKEN_PLAYLIST_SHUFFLE:
907 if ( global_settings.playlist_shuffle )
908 return "s";
909 else
910 return NULL;
911 break;
913 case SKIN_TOKEN_VOLUME:
914 snprintf(buf, buf_size, "%d", global_settings.volume);
915 if (intval)
917 int minvol = sound_min(SOUND_VOLUME);
918 if (limit == TOKEN_VALUE_ONLY)
920 *intval = global_settings.volume;
922 else if (global_settings.volume == minvol)
924 *intval = 1;
926 else if (global_settings.volume == 0)
928 *intval = limit - 1;
930 else if (global_settings.volume > 0)
932 *intval = limit;
934 else
936 *intval = (limit-3) * (global_settings.volume - minvol - 1)
937 / (-1 - minvol) + 2;
940 return buf;
941 #ifdef HAVE_ALBUMART
942 case SKIN_TOKEN_ALBUMART_FOUND:
943 if (data->albumart)
945 int handle = -1;
946 handle = playback_current_aa_hid(data->playback_aa_slot);
947 #if CONFIG_TUNER
948 if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF))
950 struct dim dim = {data->albumart->width, data->albumart->height};
951 handle = radio_get_art_hid(&dim);
953 #endif
954 if (handle >= 0)
955 return "C";
957 return NULL;
958 #endif
960 case SKIN_TOKEN_BATTERY_PERCENT:
962 int l = battery_level();
964 if (intval)
966 if (limit == TOKEN_VALUE_ONLY)
968 *intval = l;
970 else
972 limit = MAX(limit, 3);
973 if (l > -1) {
974 /* First enum is used for "unknown level",
975 * last enum is used for 100%.
977 *intval = (limit - 2) * l / 100 + 2;
978 } else {
979 *intval = 1;
984 if (l > -1) {
985 snprintf(buf, buf_size, "%d", l);
986 return buf;
987 } else {
988 return "?";
992 case SKIN_TOKEN_BATTERY_VOLTS:
994 unsigned int v = battery_voltage();
995 snprintf(buf, buf_size, "%d.%02d", v / 1000, (v % 1000) / 10);
996 return buf;
999 case SKIN_TOKEN_BATTERY_TIME:
1001 int t = battery_time();
1002 if (t >= 0)
1003 snprintf(buf, buf_size, "%dh %dm", t / 60, t % 60);
1004 else
1005 return "?h ?m";
1006 return buf;
1009 #if CONFIG_CHARGING
1010 case SKIN_TOKEN_BATTERY_CHARGER_CONNECTED:
1012 if(charger_input_state==CHARGER)
1013 return "p";
1014 else
1015 return NULL;
1017 #endif
1018 #if CONFIG_CHARGING >= CHARGING_MONITOR
1019 case SKIN_TOKEN_BATTERY_CHARGING:
1021 if (charge_state == CHARGING || charge_state == TOPOFF) {
1022 return "c";
1023 } else {
1024 return NULL;
1027 #endif
1028 #ifdef HAVE_USB_POWER
1029 case SKIN_TOKEN_USB_POWERED:
1030 if (usb_powered())
1031 return "u";
1032 return NULL;
1033 #endif
1034 case SKIN_TOKEN_BATTERY_SLEEPTIME:
1036 if (get_sleep_timer() == 0)
1037 return NULL;
1038 else
1040 format_time(buf, buf_size, get_sleep_timer() * 1000);
1041 return buf;
1045 case SKIN_TOKEN_PLAYBACK_STATUS:
1047 int status = current_playmode();
1048 /* music */
1049 int mode = 1; /* stop */
1050 if (status == STATUS_PLAY)
1051 mode = 2; /* play */
1052 if (state->is_fading ||
1053 (status == STATUS_PAUSE && !status_get_ffmode()))
1054 mode = 3; /* pause */
1055 else
1056 { /* ff / rwd */
1057 if (status_get_ffmode() == STATUS_FASTFORWARD)
1058 mode = 4;
1059 if (status_get_ffmode() == STATUS_FASTBACKWARD)
1060 mode = 5;
1062 #ifdef HAVE_RECORDING
1063 /* recording */
1064 if (status == STATUS_RECORD)
1065 mode = 6;
1066 else if (status == STATUS_RECORD_PAUSE)
1067 mode = 7;
1068 #endif
1069 #if CONFIG_TUNER
1070 /* radio */
1071 if (status == STATUS_RADIO)
1072 mode = 8;
1073 else if (status == STATUS_RADIO_PAUSE)
1074 mode = 9;
1075 #endif
1077 if (intval) {
1078 *intval = mode;
1081 snprintf(buf, buf_size, "%d", mode-1);
1082 return buf;
1085 case SKIN_TOKEN_REPEAT_MODE:
1086 if (intval)
1087 *intval = global_settings.repeat_mode + 1;
1088 snprintf(buf, buf_size, "%d", global_settings.repeat_mode);
1089 return buf;
1091 case SKIN_TOKEN_RTC_PRESENT:
1092 #if CONFIG_RTC
1093 return "c";
1094 #else
1095 return NULL;
1096 #endif
1098 #if CONFIG_RTC
1099 case SKIN_TOKEN_RTC_12HOUR_CFG:
1100 if (intval)
1101 *intval = global_settings.timeformat + 1;
1102 snprintf(buf, buf_size, "%d", global_settings.timeformat);
1103 return buf;
1105 case SKIN_TOKEN_RTC_DAY_OF_MONTH:
1106 /* d: day of month (01..31) */
1107 snprintf(buf, buf_size, "%02d", tm->tm_mday);
1108 if (intval)
1109 *intval = tm->tm_mday - 1;
1110 return buf;
1112 case SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
1113 /* e: day of month, blank padded ( 1..31) */
1114 snprintf(buf, buf_size, "%2d", tm->tm_mday);
1115 if (intval)
1116 *intval = tm->tm_mday - 1;
1117 return buf;
1119 case SKIN_TOKEN_RTC_HOUR_24_ZERO_PADDED:
1120 /* H: hour (00..23) */
1121 snprintf(buf, buf_size, "%02d", tm->tm_hour);
1122 if (intval)
1123 *intval = tm->tm_hour;
1124 return buf;
1126 case SKIN_TOKEN_RTC_HOUR_24:
1127 /* k: hour ( 0..23) */
1128 snprintf(buf, buf_size, "%2d", tm->tm_hour);
1129 if (intval)
1130 *intval = tm->tm_hour;
1131 return buf;
1133 case SKIN_TOKEN_RTC_HOUR_12_ZERO_PADDED:
1134 /* I: hour (01..12) */
1135 snprintf(buf, buf_size, "%02d",
1136 (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
1137 if (intval)
1138 *intval = (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12;
1139 return buf;
1141 case SKIN_TOKEN_RTC_HOUR_12:
1142 /* l: hour ( 1..12) */
1143 snprintf(buf, buf_size, "%2d",
1144 (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
1145 if (intval)
1146 *intval = (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12;
1147 return buf;
1149 case SKIN_TOKEN_RTC_MONTH:
1150 /* m: month (01..12) */
1151 if (intval)
1152 *intval = tm->tm_mon + 1;
1153 snprintf(buf, buf_size, "%02d", tm->tm_mon + 1);
1154 return buf;
1156 case SKIN_TOKEN_RTC_MINUTE:
1157 /* M: minute (00..59) */
1158 snprintf(buf, buf_size, "%02d", tm->tm_min);
1159 if (intval)
1160 *intval = tm->tm_min;
1161 return buf;
1163 case SKIN_TOKEN_RTC_SECOND:
1164 /* S: second (00..59) */
1165 snprintf(buf, buf_size, "%02d", tm->tm_sec);
1166 if (intval)
1167 *intval = tm->tm_sec;
1168 return buf;
1170 case SKIN_TOKEN_RTC_YEAR_2_DIGITS:
1171 /* y: last two digits of year (00..99) */
1172 snprintf(buf, buf_size, "%02d", tm->tm_year % 100);
1173 if (intval)
1174 *intval = tm->tm_year % 100;
1175 return buf;
1177 case SKIN_TOKEN_RTC_YEAR_4_DIGITS:
1178 /* Y: year (1970...) */
1179 snprintf(buf, buf_size, "%04d", tm->tm_year + 1900);
1180 if (intval)
1181 *intval = tm->tm_year + 1900;
1182 return buf;
1184 case SKIN_TOKEN_RTC_AM_PM_UPPER:
1185 /* p: upper case AM or PM indicator */
1186 if (intval)
1187 *intval = tm->tm_hour/12 == 0 ? 0 : 1;
1188 return tm->tm_hour/12 == 0 ? "AM" : "PM";
1190 case SKIN_TOKEN_RTC_AM_PM_LOWER:
1191 /* P: lower case am or pm indicator */
1192 if (intval)
1193 *intval = tm->tm_hour/12 == 0 ? 0 : 1;
1194 return tm->tm_hour/12 == 0 ? "am" : "pm";
1196 case SKIN_TOKEN_RTC_WEEKDAY_NAME:
1197 /* a: abbreviated weekday name (Sun..Sat) */
1198 return str(LANG_WEEKDAY_SUNDAY + tm->tm_wday);
1200 case SKIN_TOKEN_RTC_MONTH_NAME:
1201 /* b: abbreviated month name (Jan..Dec) */
1202 return str(LANG_MONTH_JANUARY + tm->tm_mon);
1204 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_MON:
1205 /* u: day of week (1..7); 1 is Monday */
1206 if (intval)
1207 *intval = (tm->tm_wday == 0) ? 7 : tm->tm_wday;
1208 snprintf(buf, buf_size, "%1d", tm->tm_wday + 1);
1209 return buf;
1211 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
1212 /* w: day of week (0..6); 0 is Sunday */
1213 if (intval)
1214 *intval = tm->tm_wday + 1;
1215 snprintf(buf, buf_size, "%1d", tm->tm_wday);
1216 return buf;
1217 #else
1218 case SKIN_TOKEN_RTC_DAY_OF_MONTH:
1219 case SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
1220 case SKIN_TOKEN_RTC_HOUR_24_ZERO_PADDED:
1221 case SKIN_TOKEN_RTC_HOUR_24:
1222 case SKIN_TOKEN_RTC_HOUR_12_ZERO_PADDED:
1223 case SKIN_TOKEN_RTC_HOUR_12:
1224 case SKIN_TOKEN_RTC_MONTH:
1225 case SKIN_TOKEN_RTC_MINUTE:
1226 case SKIN_TOKEN_RTC_SECOND:
1227 case SKIN_TOKEN_RTC_AM_PM_UPPER:
1228 case SKIN_TOKEN_RTC_AM_PM_LOWER:
1229 case SKIN_TOKEN_RTC_YEAR_2_DIGITS:
1230 return "--";
1231 case SKIN_TOKEN_RTC_YEAR_4_DIGITS:
1232 return "----";
1233 case SKIN_TOKEN_RTC_WEEKDAY_NAME:
1234 case SKIN_TOKEN_RTC_MONTH_NAME:
1235 return "---";
1236 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_MON:
1237 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
1238 return "-";
1239 #endif
1241 #ifdef HAVE_LCD_CHARCELLS
1242 case SKIN_TOKEN_PROGRESSBAR:
1244 char *end;
1245 format_player_progress(gwps);
1246 end = utf8encode(data->wps_progress_pat[0], buf);
1247 *end = '\0';
1248 return buf;
1251 case SKIN_TOKEN_PLAYER_PROGRESSBAR:
1252 if(is_new_player())
1254 /* we need 11 characters (full line) for
1255 progress-bar */
1256 strlcpy(buf, " ", buf_size);
1257 format_player_fullbar(gwps,buf,buf_size);
1258 DEBUGF("bar='%s'\n",buf);
1260 else
1262 /* Tell the user if we have an OldPlayer */
1263 strlcpy(buf, " <Old LCD> ", buf_size);
1265 return buf;
1266 #endif
1269 #ifdef HAVE_LCD_BITMAP
1270 /* peakmeter */
1271 case SKIN_TOKEN_PEAKMETER_LEFT:
1272 case SKIN_TOKEN_PEAKMETER_RIGHT:
1274 int left, right, val;
1275 peak_meter_current_vals(&left, &right);
1276 val = token->type == SKIN_TOKEN_PEAKMETER_LEFT ?
1277 left : right;
1278 val = peak_meter_scale_value(val, limit==1 ? MAX_PEAK : limit);
1279 if (intval)
1280 *intval = val;
1281 snprintf(buf, buf_size, "%d", val);
1282 data->peak_meter_enabled = true;
1283 return buf;
1285 #endif
1287 #if (CONFIG_CODEC == SWCODEC)
1288 case SKIN_TOKEN_CROSSFADE:
1289 #ifdef HAVE_CROSSFADE
1290 if (intval)
1291 *intval = global_settings.crossfade + 1;
1292 snprintf(buf, buf_size, "%d", global_settings.crossfade);
1293 #else
1294 snprintf(buf, buf_size, "%d", 0);
1295 #endif
1296 return buf;
1298 case SKIN_TOKEN_REPLAYGAIN:
1300 int val;
1302 if (global_settings.replaygain_type == REPLAYGAIN_OFF)
1303 val = 1; /* off */
1304 else
1306 int type;
1307 if (LIKELY(id3))
1308 type = get_replaygain_mode(id3->track_gain_string != NULL,
1309 id3->album_gain_string != NULL);
1310 else
1311 type = -1;
1313 if (type < 0)
1314 val = 6; /* no tag */
1315 else
1316 val = type + 2;
1318 if (global_settings.replaygain_type == REPLAYGAIN_SHUFFLE)
1319 val += 2;
1322 if (intval)
1323 *intval = val;
1325 switch (val)
1327 case 1:
1328 case 6:
1329 return "+0.00 dB";
1330 break;
1331 /* due to above, coming here with !id3 shouldn't be possible */
1332 case 2:
1333 case 4:
1334 strlcpy(buf, id3->track_gain_string, buf_size);
1335 break;
1336 case 3:
1337 case 5:
1338 strlcpy(buf, id3->album_gain_string, buf_size);
1339 break;
1341 return buf;
1343 #endif /* (CONFIG_CODEC == SWCODEC) */
1345 #if (CONFIG_CODEC != MAS3507D) && defined (HAVE_PITCHSCREEN)
1346 case SKIN_TOKEN_SOUND_PITCH:
1348 int32_t pitch = sound_get_pitch();
1349 snprintf(buf, buf_size, "%ld.%ld",
1350 pitch / PITCH_SPEED_PRECISION,
1351 (pitch % PITCH_SPEED_PRECISION) / (PITCH_SPEED_PRECISION / 10));
1353 if (intval)
1354 *intval = pitch_speed_enum(limit, pitch,
1355 PITCH_SPEED_PRECISION * 100);
1356 return buf;
1358 #endif
1360 #if (CONFIG_CODEC == SWCODEC) && defined (HAVE_PITCHSCREEN)
1361 case SKIN_TOKEN_SOUND_SPEED:
1363 int32_t pitch = sound_get_pitch();
1364 int32_t speed;
1365 if (dsp_timestretch_available())
1366 speed = GET_SPEED(pitch, dsp_get_timestretch());
1367 else
1368 speed = pitch;
1369 snprintf(buf, buf_size, "%ld.%ld",
1370 speed / PITCH_SPEED_PRECISION,
1371 (speed % PITCH_SPEED_PRECISION) / (PITCH_SPEED_PRECISION / 10));
1372 if (intval)
1373 *intval = pitch_speed_enum(limit, speed,
1374 PITCH_SPEED_PRECISION * 100);
1375 return buf;
1377 #endif
1379 case SKIN_TOKEN_MAIN_HOLD:
1380 #ifdef HAS_BUTTON_HOLD
1381 if (button_hold())
1382 #else
1383 if (is_keys_locked())
1384 #endif /*hold switch or softlock*/
1385 return "h";
1386 else
1387 return NULL;
1389 #ifdef HAS_REMOTE_BUTTON_HOLD
1390 case SKIN_TOKEN_REMOTE_HOLD:
1391 if (remote_button_hold())
1392 return "r";
1393 else
1394 return NULL;
1395 #endif
1397 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
1398 case SKIN_TOKEN_VLED_HDD:
1399 if(led_read(HZ/2))
1400 return "h";
1401 else
1402 return NULL;
1403 #endif
1404 case SKIN_TOKEN_BUTTON_VOLUME:
1405 if (global_status.last_volume_change &&
1406 TIME_BEFORE(current_tick, global_status.last_volume_change +
1407 token->value.i))
1408 return "v";
1409 return NULL;
1411 case SKIN_TOKEN_LASTTOUCH:
1413 #ifdef HAVE_TOUCHSCREEN
1414 unsigned int last_touch = touchscreen_last_touch();
1415 if (last_touch != 0xffff &&
1416 TIME_BEFORE(current_tick, token->value.i + last_touch))
1417 return "t";
1418 #endif
1420 return NULL;
1421 case SKIN_TOKEN_HAVE_TOUCH:
1422 #ifdef HAVE_TOUCHSCREEN
1423 return "t";
1424 #else
1425 return NULL;
1426 #endif
1428 case SKIN_TOKEN_SETTING:
1430 const struct settings_list *s = settings+token->value.i;
1431 if (intval)
1433 /* Handle contionals */
1434 switch (s->flags&F_T_MASK)
1436 case F_T_INT:
1437 case F_T_UINT:
1438 if (s->flags&F_T_SOUND)
1440 /* %?St|name|<min|min+1|...|max-1|max> */
1441 int sound_setting = s->sound_setting->setting;
1442 /* settings with decimals can't be used in conditionals */
1443 if (sound_numdecimals(sound_setting) == 0)
1445 *intval = (*(int*)s->setting-sound_min(sound_setting))
1446 /sound_steps(sound_setting) + 1;
1448 else
1449 *intval = -1;
1451 else if (s->flags&F_RGB)
1452 /* %?St|name|<#000000|#000001|...|#FFFFFF> */
1453 /* shouldn't overflow since colors are stored
1454 * on 16 bits ...
1455 * but this is pretty useless anyway */
1456 *intval = *(int*)s->setting + 1;
1457 else if (s->cfg_vals == NULL)
1458 /* %?St|name|<1st choice|2nd choice|...> */
1459 *intval = (*(int*)s->setting-s->int_setting->min)
1460 /s->int_setting->step + 1;
1461 else
1462 /* %?St|name|<1st choice|2nd choice|...> */
1463 /* Not sure about this one. cfg_name/vals are
1464 * indexed from 0 right? */
1465 *intval = *(int*)s->setting + 1;
1466 break;
1467 case F_T_BOOL:
1468 /* %?St|name|<if true|if false> */
1469 *intval = *(bool*)s->setting?1:2;
1470 break;
1471 case F_T_CHARPTR:
1472 case F_T_UCHARPTR:
1473 /* %?St|name|<if non empty string|if empty>
1474 * The string's emptyness discards the setting's
1475 * prefix and suffix */
1476 *intval = ((char*)s->setting)[0]?1:2;
1477 /* if there is a prefix we should ignore it here */
1478 if (s->filename_setting->prefix)
1479 return (char*)s->setting;
1480 break;
1481 default:
1482 /* This shouldn't happen ... but you never know */
1483 *intval = -1;
1484 break;
1487 /* Special handlng for filenames because we dont want to show the prefix */
1488 if ((s->flags&F_T_MASK) == F_T_UCHARPTR ||
1489 (s->flags&F_T_MASK) == F_T_UCHARPTR)
1491 if (s->filename_setting->prefix)
1492 return (char*)s->setting;
1494 cfg_to_string(token->value.i,buf,buf_size);
1495 return buf;
1497 case SKIN_TOKEN_HAVE_TUNER:
1498 #if CONFIG_TUNER
1499 if (radio_hardware_present())
1500 return "r";
1501 #endif
1502 return NULL;
1503 /* Recording tokens */
1504 case SKIN_TOKEN_HAVE_RECORDING:
1505 #ifdef HAVE_RECORDING
1506 return "r";
1507 #else
1508 return NULL;
1509 #endif
1511 #ifdef HAVE_RECORDING
1512 case SKIN_TOKEN_IS_RECORDING:
1513 if (audio_status() == AUDIO_STATUS_RECORD)
1514 return "r";
1515 return NULL;
1516 case SKIN_TOKEN_REC_FREQ: /* order from REC_FREQ_CFG_VAL_LIST */
1518 #if CONFIG_CODEC == SWCODEC
1519 unsigned long samprk;
1520 int rec_freq = global_settings.rec_frequency;
1522 #ifdef SIMULATOR
1523 samprk = 44100;
1524 #else
1525 #if defined(HAVE_SPDIF_REC)
1526 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
1528 /* Use rate in use, not current measured rate if it changed */
1529 samprk = pcm_rec_sample_rate();
1530 rec_freq = 0;
1531 while (rec_freq < SAMPR_NUM_FREQ &&
1532 audio_master_sampr_list[rec_freq] != samprk)
1534 rec_freq++;
1537 else
1538 #endif
1539 samprk = rec_freq_sampr[rec_freq];
1540 #endif /* SIMULATOR */
1541 if (intval)
1543 switch (rec_freq)
1545 REC_HAVE_96_(case REC_FREQ_96:
1546 *intval = 1;
1547 break;)
1548 REC_HAVE_88_(case REC_FREQ_88:
1549 *intval = 2;
1550 break;)
1551 REC_HAVE_64_(case REC_FREQ_64:
1552 *intval = 3;
1553 break;)
1554 REC_HAVE_48_(case REC_FREQ_48:
1555 *intval = 4;
1556 break;)
1557 REC_HAVE_44_(case REC_FREQ_44:
1558 *intval = 5;
1559 break;)
1560 REC_HAVE_32_(case REC_FREQ_32:
1561 *intval = 6;
1562 break;)
1563 REC_HAVE_24_(case REC_FREQ_24:
1564 *intval = 7;
1565 break;)
1566 REC_HAVE_22_(case REC_FREQ_22:
1567 *intval = 8;
1568 break;)
1569 REC_HAVE_16_(case REC_FREQ_16:
1570 *intval = 9;
1571 break;)
1572 REC_HAVE_12_(case REC_FREQ_12:
1573 *intval = 10;
1574 break;)
1575 REC_HAVE_11_(case REC_FREQ_11:
1576 *intval = 11;
1577 break;)
1578 REC_HAVE_8_(case REC_FREQ_8:
1579 *intval = 12;
1580 break;)
1583 snprintf(buf, buf_size, "%lu.%1lu", samprk/1000,samprk%1000);
1584 #else /* HWCODEC */
1586 static const char * const freq_strings[] =
1587 {"--", "44", "48", "32", "22", "24", "16"};
1588 int freq = 1 + global_settings.rec_frequency;
1589 #ifdef HAVE_SPDIF_REC
1590 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
1592 /* Can't measure S/PDIF sample rate on Archos/Sim yet */
1593 freq = 0;
1595 #endif /* HAVE_SPDIF_IN */
1596 if (intval)
1597 *intval = freq+1; /* so the token gets a value 1<=x<=7 */
1598 snprintf(buf, buf_size, "%s\n",
1599 freq_strings[global_settings.rec_frequency]);
1600 #endif
1601 return buf;
1603 #if CONFIG_CODEC == SWCODEC
1604 case SKIN_TOKEN_REC_ENCODER:
1606 int rec_format = global_settings.rec_format+1; /* WAV, AIFF, WV, MPEG */
1607 if (intval)
1608 *intval = rec_format;
1609 switch (rec_format)
1611 case REC_FORMAT_PCM_WAV:
1612 return "wav";
1613 case REC_FORMAT_AIFF:
1614 return "aiff";
1615 case REC_FORMAT_WAVPACK:
1616 return "wv";
1617 case REC_FORMAT_MPA_L3:
1618 return "MP3";
1619 default:
1620 return NULL;
1622 break;
1624 #endif
1625 case SKIN_TOKEN_REC_BITRATE:
1626 #if CONFIG_CODEC == SWCODEC
1627 if (global_settings.rec_format == REC_FORMAT_MPA_L3)
1629 if (intval)
1631 #if 0 /* FIXME: I dont know if this is needed? */
1632 switch (1<<global_settings.mp3_enc_config.bitrate)
1634 case MP3_BITR_CAP_8:
1635 *intval = 1;
1636 break;
1637 case MP3_BITR_CAP_16:
1638 *intval = 2;
1639 break;
1640 case MP3_BITR_CAP_24:
1641 *intval = 3;
1642 break;
1643 case MP3_BITR_CAP_32:
1644 *intval = 4;
1645 break;
1646 case MP3_BITR_CAP_40:
1647 *intval = 5;
1648 break;
1649 case MP3_BITR_CAP_48:
1650 *intval = 6;
1651 break;
1652 case MP3_BITR_CAP_56:
1653 *intval = 7;
1654 break;
1655 case MP3_BITR_CAP_64:
1656 *intval = 8;
1657 break;
1658 case MP3_BITR_CAP_80:
1659 *intval = 9;
1660 break;
1661 case MP3_BITR_CAP_96:
1662 *intval = 10;
1663 break;
1664 case MP3_BITR_CAP_112:
1665 *intval = 11;
1666 break;
1667 case MP3_BITR_CAP_128:
1668 *intval = 12;
1669 break;
1670 case MP3_BITR_CAP_144:
1671 *intval = 13;
1672 break;
1673 case MP3_BITR_CAP_160:
1674 *intval = 14;
1675 break;
1676 case MP3_BITR_CAP_192:
1677 *intval = 15;
1678 break;
1680 #endif
1681 *intval = global_settings.mp3_enc_config.bitrate+1;
1683 snprintf(buf, buf_size, "%lu", global_settings.mp3_enc_config.bitrate+1);
1684 return buf;
1686 else
1687 return NULL; /* Fixme later */
1688 #else /* CONFIG_CODEC == HWCODEC */
1689 if (intval)
1690 *intval = global_settings.rec_quality+1;
1691 snprintf(buf, buf_size, "%d", global_settings.rec_quality);
1692 return buf;
1693 #endif
1694 case SKIN_TOKEN_REC_MONO:
1695 if (!global_settings.rec_channels)
1696 return "m";
1697 return NULL;
1699 case SKIN_TOKEN_REC_SECONDS:
1701 int time = (audio_recorded_time() / HZ) % 60;
1702 if (intval)
1703 *intval = time;
1704 snprintf(buf, buf_size, "%02d", time);
1705 return buf;
1707 case SKIN_TOKEN_REC_MINUTES:
1709 int time = (audio_recorded_time() / HZ) / 60;
1710 if (intval)
1711 *intval = time;
1712 snprintf(buf, buf_size, "%02d", time);
1713 return buf;
1715 case SKIN_TOKEN_REC_HOURS:
1717 int time = (audio_recorded_time() / HZ) / 3600;
1718 if (intval)
1719 *intval = time;
1720 snprintf(buf, buf_size, "%02d", time);
1721 return buf;
1724 #endif /* HAVE_RECORDING */
1726 case SKIN_TOKEN_CURRENT_SCREEN:
1728 int curr_screen = current_screen();
1730 #ifdef HAVE_RECORDING
1731 /* override current_screen() for recording screen since it may
1732 * be entered from the radio screen */
1733 if (in_recording_screen())
1734 curr_screen = GO_TO_RECSCREEN;
1735 #endif
1737 switch (curr_screen)
1739 case GO_TO_WPS:
1740 curr_screen = 2;
1741 break;
1742 #ifdef HAVE_RECORDING
1743 case GO_TO_RECSCREEN:
1744 curr_screen = 3;
1745 break;
1746 #endif
1747 #if CONFIG_TUNER
1748 case GO_TO_FM:
1749 curr_screen = 4;
1750 break;
1751 #endif
1752 case GO_TO_PLAYLIST_VIEWER:
1753 curr_screen = 5;
1754 break;
1755 default: /* lists */
1756 curr_screen = 1;
1757 break;
1759 if (intval)
1761 *intval = curr_screen;
1763 snprintf(buf, buf_size, "%d", curr_screen);
1764 return buf;
1767 case SKIN_TOKEN_LANG_IS_RTL:
1768 return lang_is_rtl() ? "r" : NULL;
1770 default:
1771 return NULL;