Allow %?Sp<...> to be used as a conditional
[kugel-rb.git] / apps / gui / skin_engine / skin_tokens.c
blob6eb1759b91308e67cd65f9b52a1d34a4c44cf85e
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.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 #ifdef HAVE_LCD_CHARCELLS
38 #include "hwcompat.h"
39 #endif
40 #include "abrepeat.h"
41 #include "lang.h"
42 #include "misc.h"
43 #include "led.h"
44 #ifdef HAVE_LCD_BITMAP
45 /* Image stuff */
46 #include "albumart.h"
47 #endif
48 #include "dsp.h"
49 #include "playlist.h"
50 #if CONFIG_CODEC == SWCODEC
51 #include "playback.h"
52 #endif
53 #include "viewport.h"
55 #include "wps_internals.h"
56 #include "root_menu.h"
57 #ifdef HAVE_RECORDING
58 #include "recording.h"
59 #include "pcm_record.h"
60 #endif
62 static char* get_codectype(const struct mp3entry* id3)
64 if (id3 && id3->codectype < AFMT_NUM_CODECS) {
65 return (char*)audio_formats[id3->codectype].label;
66 } else {
67 return NULL;
71 /* Extract a part from a path.
73 * buf - buffer extract part to.
74 * buf_size - size of buffer.
75 * path - path to extract from.
76 * level - what to extract. 0 is file name, 1 is parent of file, 2 is
77 * parent of parent, etc.
79 * Returns buf if the desired level was found, NULL otherwise.
81 static char* get_dir(char* buf, int buf_size, const char* path, int level)
83 const char* sep;
84 const char* last_sep;
85 int len;
87 sep = path + strlen(path);
88 last_sep = sep;
90 while (sep > path)
92 if ('/' == *(--sep))
94 if (!level)
95 break;
97 level--;
98 last_sep = sep - 1;
102 if (level || (last_sep <= sep))
103 return NULL;
105 len = MIN(last_sep - sep, buf_size - 1);
106 strlcpy(buf, sep + 1, len + 1);
107 return buf;
110 /* A helper to determine the enum value for pitch/speed.
112 When there are two choices (i.e. boolean), return 1 if the value is
113 different from normal value and 2 if the value is the same as the
114 normal value. E.g. "%?Sp<%Sp>" would show the pitch only when
115 playing at a modified pitch.
117 When there are more than two choices (i.e. enum), the left half of
118 the choices are to show 0..normal range, and the right half of the
119 choices are to show values over that. The last entry is used when
120 it is set to the normal setting, following the rockbox convention
121 to use the last entry for special values.
123 E.g.
125 2 items: %?Sp<0..99 or 101..infinity|100>
126 3 items: %?Sp<0..99|101..infinity|100>
127 4 items: %?Sp<0..49|50..99|101..infinity|100>
128 5 items: %?Sp<0..49|50..99|101..149|150..infinity|100>
129 6 items: %?Sp<0..33|34..66|67..99|101..133|134..infinity|100>
130 7 items: %?Sp<0..33|34..66|67..99|101..133|134..167|167..infinity|100>
132 static int pitch_speed_enum(int range, int32_t val, int32_t normval)
134 int center;
135 int n;
137 if (range < 3)
138 return (val == normval) + 1;
139 if (val == normval)
140 return range;
141 center = range / 2;
142 n = (center * val) / normval + 1;
143 return (range <= n) ? (range - 1) : n;
146 /* Return the tag found at index i and write its value in buf.
147 The return value is buf if the tag had a value, or NULL if not.
149 intval is used with conditionals/enums: when this function is called,
150 intval should contain the number of options in the conditional/enum.
151 When this function returns, intval is -1 if the tag is non numeric or,
152 if the tag is numeric, *intval is the enum case we want to go to (between 1
153 and the original value of *intval, inclusive).
154 When not treating a conditional/enum, intval should be NULL.
157 /* a few convinience macros for the id3 == NULL case
158 * depends on a few variable names in get_token_value() */
160 #define HANDLE_NULL_ID3(id3field) (LIKELY(id3) ? (id3field) : NULL)
162 #define HANDLE_NULL_ID3_NUM_ZERO { if (UNLIKELY(!id3)) return zero_str; }
164 #define HANDLE_NULL_ID3_NUM_INTVAL(id3field) \
165 do { \
166 if (intval) { \
167 *intval = (LIKELY(id3) ? (id3field) + 1 : 0); \
169 if (LIKELY(id3)) \
171 snprintf(buf, buf_size, "%ld", (id3field)); \
172 return buf; \
174 return zero_str; \
175 } while (0)
177 const char *get_token_value(struct gui_wps *gwps,
178 struct wps_token *token,
179 char *buf, int buf_size,
180 int *intval)
182 if (!gwps)
183 return NULL;
185 struct wps_data *data = gwps->data;
186 struct wps_state *state = gwps->state;
187 int elapsed, length;
188 static const char * const zero_str = "0";
190 if (!data || !state)
191 return NULL;
193 struct mp3entry *id3;
195 if (token->next)
196 id3 = state->nid3;
197 else
198 id3 = state->id3;
200 if (id3)
202 elapsed = id3->elapsed;
203 length = id3->length;
205 else
207 elapsed = 0;
208 length = 0;
211 #if CONFIG_RTC
212 struct tm* tm = NULL;
214 /* if the token is an RTC one, update the time
215 and do the necessary checks */
216 if (token->type >= WPS_TOKENS_RTC_BEGIN
217 && token->type <= WPS_TOKENS_RTC_END)
219 tm = get_time();
221 if (!valid_time(tm))
222 return NULL;
224 #endif
226 int limit = 1;
227 if (intval)
229 limit = *intval;
230 *intval = -1;
233 switch (token->type)
235 case WPS_TOKEN_CHARACTER:
236 if (token->value.c == '\n')
237 return NULL;
238 return &(token->value.c);
240 case WPS_TOKEN_STRING:
241 return (char*)token->value.data;
243 case WPS_TOKEN_TRANSLATEDSTRING:
244 return (char*)P2STR(ID2P(token->value.i));
246 case WPS_TOKEN_TRACK_TIME_ELAPSED:
247 format_time(buf, buf_size,
248 elapsed + state->ff_rewind_count);
249 return buf;
251 case WPS_TOKEN_TRACK_TIME_REMAINING:
252 format_time(buf, buf_size,
253 length - elapsed -
254 state->ff_rewind_count);
255 return buf;
257 case WPS_TOKEN_TRACK_LENGTH:
258 format_time(buf, buf_size, length);
259 return buf;
261 case WPS_TOKEN_PLAYLIST_ENTRIES:
262 snprintf(buf, buf_size, "%d", playlist_amount());
263 return buf;
265 case WPS_TOKEN_PLAYLIST_NAME:
266 return playlist_name(NULL, buf, buf_size);
268 case WPS_TOKEN_PLAYLIST_POSITION:
269 snprintf(buf, buf_size, "%d", playlist_get_display_index());
270 return buf;
272 case WPS_TOKEN_PLAYLIST_SHUFFLE:
273 if ( global_settings.playlist_shuffle )
274 return "s";
275 else
276 return NULL;
277 break;
279 case WPS_TOKEN_VOLUME:
280 snprintf(buf, buf_size, "%d", global_settings.volume);
281 if (intval)
283 if (global_settings.volume == sound_min(SOUND_VOLUME))
285 *intval = 1;
287 else if (global_settings.volume == 0)
289 *intval = limit - 1;
291 else if (global_settings.volume > 0)
293 *intval = limit;
295 else
297 *intval = (limit - 3) * (global_settings.volume
298 - sound_min(SOUND_VOLUME) - 1)
299 / (-1 - sound_min(SOUND_VOLUME)) + 2;
302 return buf;
304 case WPS_TOKEN_TRACK_ELAPSED_PERCENT:
305 if (length <= 0)
306 return NULL;
308 if (intval)
310 *intval = limit * (elapsed + state->ff_rewind_count)
311 / length + 1;
313 snprintf(buf, buf_size, "%d",
314 100*(elapsed + state->ff_rewind_count) / length);
315 return buf;
317 case WPS_TOKEN_METADATA_ARTIST:
318 return HANDLE_NULL_ID3(id3->artist);
320 case WPS_TOKEN_METADATA_COMPOSER:
321 return HANDLE_NULL_ID3(id3->composer);
323 case WPS_TOKEN_METADATA_ALBUM:
324 return HANDLE_NULL_ID3(id3->album);
326 case WPS_TOKEN_METADATA_ALBUM_ARTIST:
327 return HANDLE_NULL_ID3(id3->albumartist);
329 case WPS_TOKEN_METADATA_GROUPING:
330 return HANDLE_NULL_ID3(id3->grouping);
332 case WPS_TOKEN_METADATA_GENRE:
333 return HANDLE_NULL_ID3(id3->genre_string);
335 case WPS_TOKEN_METADATA_DISC_NUMBER:
336 if (LIKELY(id3)) {
337 if (id3->disc_string)
338 return id3->disc_string;
339 if (id3->discnum) {
340 snprintf(buf, buf_size, "%d", id3->discnum);
341 return buf;
344 return NULL;
346 case WPS_TOKEN_METADATA_TRACK_NUMBER:
347 if (LIKELY(id3)) {
348 if (id3->track_string)
349 return id3->track_string;
351 if (id3->tracknum) {
352 snprintf(buf, buf_size, "%d", id3->tracknum);
353 return buf;
356 return NULL;
358 case WPS_TOKEN_METADATA_TRACK_TITLE:
359 return HANDLE_NULL_ID3(id3->title);
361 case WPS_TOKEN_METADATA_VERSION:
362 if (LIKELY(id3))
364 switch (id3->id3version)
366 case ID3_VER_1_0:
367 return "1";
369 case ID3_VER_1_1:
370 return "1.1";
372 case ID3_VER_2_2:
373 return "2.2";
375 case ID3_VER_2_3:
376 return "2.3";
378 case ID3_VER_2_4:
379 return "2.4";
381 default:
382 break;
385 return NULL;
387 case WPS_TOKEN_METADATA_YEAR:
388 if (LIKELY(id3)) {
389 if( id3->year_string )
390 return id3->year_string;
392 if (id3->year) {
393 snprintf(buf, buf_size, "%d", id3->year);
394 return buf;
397 return NULL;
399 case WPS_TOKEN_METADATA_COMMENT:
400 return HANDLE_NULL_ID3(id3->comment);
402 #ifdef HAVE_ALBUMART
403 case WPS_TOKEN_ALBUMART_FOUND:
404 if (data->albumart) {
405 if (playback_current_aa_hid(data->playback_aa_slot) >= 0)
406 return "C";
408 return NULL;
410 case WPS_TOKEN_ALBUMART_DISPLAY:
411 if (!data->albumart)
412 return NULL;
413 if (!data->albumart->draw)
414 data->albumart->draw = true;
415 return NULL;
416 #endif
418 case WPS_TOKEN_FILE_BITRATE:
419 if(id3 && id3->bitrate)
420 snprintf(buf, buf_size, "%d", id3->bitrate);
421 else
422 return "?";
423 return buf;
425 case WPS_TOKEN_FILE_CODEC:
426 if (intval)
428 if (UNLIKELY(!id3))
429 *intval = 0;
430 else if(id3->codectype == AFMT_UNKNOWN)
431 *intval = AFMT_NUM_CODECS;
432 else
433 *intval = id3->codectype;
435 return get_codectype(id3);
437 case WPS_TOKEN_FILE_FREQUENCY:
438 HANDLE_NULL_ID3_NUM_ZERO;
439 snprintf(buf, buf_size, "%ld", id3->frequency);
440 return buf;
442 case WPS_TOKEN_FILE_FREQUENCY_KHZ:
443 HANDLE_NULL_ID3_NUM_ZERO;
444 /* ignore remainders < 100, so 22050 Hz becomes just 22k */
445 if ((id3->frequency % 1000) < 100)
446 snprintf(buf, buf_size, "%ld", id3->frequency / 1000);
447 else
448 snprintf(buf, buf_size, "%ld.%d",
449 id3->frequency / 1000,
450 (id3->frequency % 1000) / 100);
451 return buf;
453 case WPS_TOKEN_FILE_NAME:
454 if (LIKELY(id3) && get_dir(buf, buf_size, id3->path, 0)) {
455 /* Remove extension */
456 char* sep = strrchr(buf, '.');
457 if (NULL != sep) {
458 *sep = 0;
460 return buf;
462 else {
463 return NULL;
466 case WPS_TOKEN_FILE_NAME_WITH_EXTENSION:
467 if (LIKELY(id3))
468 return get_dir(buf, buf_size, id3->path, 0);
469 return NULL;
471 case WPS_TOKEN_FILE_PATH:
472 return HANDLE_NULL_ID3(id3->path);
474 case WPS_TOKEN_FILE_SIZE:
475 HANDLE_NULL_ID3_NUM_ZERO;
476 snprintf(buf, buf_size, "%ld", id3->filesize / 1024);
477 return buf;
479 case WPS_TOKEN_FILE_VBR:
480 return (LIKELY(id3) && id3->vbr) ? "(avg)" : NULL;
482 case WPS_TOKEN_FILE_DIRECTORY:
483 if (LIKELY(id3))
484 return get_dir(buf, buf_size, id3->path, token->value.i);
485 return NULL;
487 case WPS_TOKEN_BATTERY_PERCENT:
489 int l = battery_level();
491 if (intval)
493 limit = MAX(limit, 2);
494 if (l > -1) {
495 /* First enum is used for "unknown level". */
496 *intval = (limit - 1) * l / 100 + 2;
497 } else {
498 *intval = 1;
502 if (l > -1) {
503 snprintf(buf, buf_size, "%d", l);
504 return buf;
505 } else {
506 return "?";
510 case WPS_TOKEN_BATTERY_VOLTS:
512 unsigned int v = battery_voltage();
513 snprintf(buf, buf_size, "%d.%02d", v / 1000, (v % 1000) / 10);
514 return buf;
517 case WPS_TOKEN_BATTERY_TIME:
519 int t = battery_time();
520 if (t >= 0)
521 snprintf(buf, buf_size, "%dh %dm", t / 60, t % 60);
522 else
523 return "?h ?m";
524 return buf;
527 #if CONFIG_CHARGING
528 case WPS_TOKEN_BATTERY_CHARGER_CONNECTED:
530 if(charger_input_state==CHARGER)
531 return "p";
532 else
533 return NULL;
535 #endif
536 #if CONFIG_CHARGING >= CHARGING_MONITOR
537 case WPS_TOKEN_BATTERY_CHARGING:
539 if (charge_state == CHARGING || charge_state == TOPOFF) {
540 return "c";
541 } else {
542 return NULL;
545 #endif
546 case WPS_TOKEN_BATTERY_SLEEPTIME:
548 if (get_sleep_timer() == 0)
549 return NULL;
550 else
552 format_time(buf, buf_size, get_sleep_timer() * 1000);
553 return buf;
557 case WPS_TOKEN_PLAYBACK_STATUS:
559 int status = current_playmode();
560 /* music */
561 int mode = 1; /* stop */
562 if (status == STATUS_PLAY)
563 mode = 2; /* play */
564 if (state->is_fading ||
565 (status == STATUS_PAUSE && !status_get_ffmode()))
566 mode = 3; /* pause */
567 else
568 { /* ff / rwd */
569 if (status_get_ffmode() == STATUS_FASTFORWARD)
570 mode = 4;
571 if (status_get_ffmode() == STATUS_FASTBACKWARD)
572 mode = 5;
574 #ifdef HAVE_RECORDING
575 /* recording */
576 if (status == STATUS_RECORD)
577 mode = 6;
578 else if (status == STATUS_RECORD_PAUSE)
579 mode = 7;
580 #endif
581 #if CONFIG_TUNER
582 /* radio */
583 if (status == STATUS_RADIO)
584 mode = 8;
585 else if (status == STATUS_RADIO_PAUSE)
586 mode = 9;
587 #endif
589 if (intval) {
590 *intval = mode;
593 snprintf(buf, buf_size, "%d", mode-1);
594 return buf;
597 case WPS_TOKEN_REPEAT_MODE:
598 if (intval)
599 *intval = global_settings.repeat_mode + 1;
600 snprintf(buf, buf_size, "%d", global_settings.repeat_mode);
601 return buf;
603 case WPS_TOKEN_RTC_PRESENT:
604 #if CONFIG_RTC
605 return "c";
606 #else
607 return NULL;
608 #endif
610 #if CONFIG_RTC
611 case WPS_TOKEN_RTC_12HOUR_CFG:
612 if (intval)
613 *intval = global_settings.timeformat + 1;
614 snprintf(buf, buf_size, "%d", global_settings.timeformat);
615 return buf;
617 case WPS_TOKEN_RTC_DAY_OF_MONTH:
618 /* d: day of month (01..31) */
619 snprintf(buf, buf_size, "%02d", tm->tm_mday);
620 return buf;
622 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
623 /* e: day of month, blank padded ( 1..31) */
624 snprintf(buf, buf_size, "%2d", tm->tm_mday);
625 return buf;
627 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED:
628 /* H: hour (00..23) */
629 snprintf(buf, buf_size, "%02d", tm->tm_hour);
630 return buf;
632 case WPS_TOKEN_RTC_HOUR_24:
633 /* k: hour ( 0..23) */
634 snprintf(buf, buf_size, "%2d", tm->tm_hour);
635 return buf;
637 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED:
638 /* I: hour (01..12) */
639 snprintf(buf, buf_size, "%02d",
640 (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
641 return buf;
643 case WPS_TOKEN_RTC_HOUR_12:
644 /* l: hour ( 1..12) */
645 snprintf(buf, buf_size, "%2d",
646 (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
647 return buf;
649 case WPS_TOKEN_RTC_MONTH:
650 /* m: month (01..12) */
651 if (intval)
652 *intval = tm->tm_mon + 1;
653 snprintf(buf, buf_size, "%02d", tm->tm_mon + 1);
654 return buf;
656 case WPS_TOKEN_RTC_MINUTE:
657 /* M: minute (00..59) */
658 snprintf(buf, buf_size, "%02d", tm->tm_min);
659 return buf;
661 case WPS_TOKEN_RTC_SECOND:
662 /* S: second (00..59) */
663 snprintf(buf, buf_size, "%02d", tm->tm_sec);
664 return buf;
666 case WPS_TOKEN_RTC_YEAR_2_DIGITS:
667 /* y: last two digits of year (00..99) */
668 snprintf(buf, buf_size, "%02d", tm->tm_year % 100);
669 return buf;
671 case WPS_TOKEN_RTC_YEAR_4_DIGITS:
672 /* Y: year (1970...) */
673 snprintf(buf, buf_size, "%04d", tm->tm_year + 1900);
674 return buf;
676 case WPS_TOKEN_RTC_AM_PM_UPPER:
677 /* p: upper case AM or PM indicator */
678 return tm->tm_hour/12 == 0 ? "AM" : "PM";
680 case WPS_TOKEN_RTC_AM_PM_LOWER:
681 /* P: lower case am or pm indicator */
682 return tm->tm_hour/12 == 0 ? "am" : "pm";
684 case WPS_TOKEN_RTC_WEEKDAY_NAME:
685 /* a: abbreviated weekday name (Sun..Sat) */
686 return str(LANG_WEEKDAY_SUNDAY + tm->tm_wday);
688 case WPS_TOKEN_RTC_MONTH_NAME:
689 /* b: abbreviated month name (Jan..Dec) */
690 return str(LANG_MONTH_JANUARY + tm->tm_mon);
692 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
693 /* u: day of week (1..7); 1 is Monday */
694 if (intval)
695 *intval = (tm->tm_wday == 0) ? 7 : tm->tm_wday;
696 snprintf(buf, buf_size, "%1d", tm->tm_wday + 1);
697 return buf;
699 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
700 /* w: day of week (0..6); 0 is Sunday */
701 if (intval)
702 *intval = tm->tm_wday + 1;
703 snprintf(buf, buf_size, "%1d", tm->tm_wday);
704 return buf;
705 #else
706 case WPS_TOKEN_RTC_DAY_OF_MONTH:
707 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
708 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED:
709 case WPS_TOKEN_RTC_HOUR_24:
710 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED:
711 case WPS_TOKEN_RTC_HOUR_12:
712 case WPS_TOKEN_RTC_MONTH:
713 case WPS_TOKEN_RTC_MINUTE:
714 case WPS_TOKEN_RTC_SECOND:
715 case WPS_TOKEN_RTC_AM_PM_UPPER:
716 case WPS_TOKEN_RTC_AM_PM_LOWER:
717 case WPS_TOKEN_RTC_YEAR_2_DIGITS:
718 return "--";
719 case WPS_TOKEN_RTC_YEAR_4_DIGITS:
720 return "----";
721 case WPS_TOKEN_RTC_WEEKDAY_NAME:
722 case WPS_TOKEN_RTC_MONTH_NAME:
723 return "---";
724 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
725 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
726 return "-";
727 #endif
729 #ifdef HAVE_LCD_CHARCELLS
730 case WPS_TOKEN_PROGRESSBAR:
732 char *end = utf8encode(data->wps_progress_pat[0], buf);
733 *end = '\0';
734 return buf;
737 case WPS_TOKEN_PLAYER_PROGRESSBAR:
738 if(is_new_player())
740 /* we need 11 characters (full line) for
741 progress-bar */
742 strlcpy(buf, " ", buf_size);
744 else
746 /* Tell the user if we have an OldPlayer */
747 strlcpy(buf, " <Old LCD> ", buf_size);
749 return buf;
750 #endif
753 #ifdef HAVE_TAGCACHE
754 case WPS_TOKEN_DATABASE_PLAYCOUNT:
755 HANDLE_NULL_ID3_NUM_INTVAL(id3->playcount);
757 case WPS_TOKEN_DATABASE_RATING:
758 HANDLE_NULL_ID3_NUM_INTVAL(id3->rating);
760 case WPS_TOKEN_DATABASE_AUTOSCORE:
761 HANDLE_NULL_ID3_NUM_INTVAL(id3->score);
762 #endif
764 #if (CONFIG_CODEC == SWCODEC)
765 case WPS_TOKEN_CROSSFADE:
766 if (intval)
767 *intval = global_settings.crossfade + 1;
768 snprintf(buf, buf_size, "%d", global_settings.crossfade);
769 return buf;
771 case WPS_TOKEN_REPLAYGAIN:
773 int val;
775 if (global_settings.replaygain_type == REPLAYGAIN_OFF)
776 val = 1; /* off */
777 else
779 int type;
780 if (LIKELY(id3))
781 type = get_replaygain_mode(id3->track_gain_string != NULL,
782 id3->album_gain_string != NULL);
783 else
784 type = -1;
786 if (type < 0)
787 val = 6; /* no tag */
788 else
789 val = type + 2;
791 if (global_settings.replaygain_type == REPLAYGAIN_SHUFFLE)
792 val += 2;
795 if (intval)
796 *intval = val;
798 switch (val)
800 case 1:
801 case 6:
802 return "+0.00 dB";
803 break;
804 /* due to above, coming here with !id3 shouldn't be possible */
805 case 2:
806 case 4:
807 strlcpy(buf, id3->track_gain_string, buf_size);
808 break;
809 case 3:
810 case 5:
811 strlcpy(buf, id3->album_gain_string, buf_size);
812 break;
814 return buf;
816 #endif /* (CONFIG_CODEC == SWCODEC) */
818 #if (CONFIG_CODEC != MAS3507D)
819 case WPS_TOKEN_SOUND_PITCH:
821 int32_t pitch = sound_get_pitch();
822 snprintf(buf, buf_size, "%ld.%ld",
823 pitch / PITCH_SPEED_PRECISION,
824 (pitch % PITCH_SPEED_PRECISION) / (PITCH_SPEED_PRECISION / 10));
826 if (intval)
827 *intval = pitch_speed_enum(limit, pitch,
828 PITCH_SPEED_PRECISION * 100);
829 return buf;
831 #endif
833 case WPS_TOKEN_MAIN_HOLD:
834 #ifdef HAS_BUTTON_HOLD
835 if (button_hold())
836 #else
837 if (is_keys_locked())
838 #endif /*hold switch or softlock*/
839 return "h";
840 else
841 return NULL;
843 #ifdef HAS_REMOTE_BUTTON_HOLD
844 case WPS_TOKEN_REMOTE_HOLD:
845 if (remote_button_hold())
846 return "r";
847 else
848 return NULL;
849 #endif
851 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
852 case WPS_TOKEN_VLED_HDD:
853 if(led_read(HZ/2))
854 return "h";
855 else
856 return NULL;
857 #endif
858 case WPS_TOKEN_BUTTON_VOLUME:
859 if (global_status.last_volume_change &&
860 TIME_BEFORE(current_tick, global_status.last_volume_change +
861 token->value.i * TIMEOUT_UNIT))
862 return "v";
863 return NULL;
864 case WPS_TOKEN_LASTTOUCH:
865 #ifdef HAVE_TOUCHSCREEN
866 if (TIME_BEFORE(current_tick, token->value.i * TIMEOUT_UNIT +
867 touchscreen_last_touch()))
868 return "t";
869 #endif
870 return NULL;
872 case WPS_TOKEN_SETTING:
874 if (intval)
876 /* Handle contionals */
877 const struct settings_list *s = settings+token->value.i;
878 switch (s->flags&F_T_MASK)
880 case F_T_INT:
881 case F_T_UINT:
882 if (s->flags&F_RGB)
883 /* %?St|name|<#000000|#000001|...|#FFFFFF> */
884 /* shouldn't overflow since colors are stored
885 * on 16 bits ...
886 * but this is pretty useless anyway */
887 *intval = *(int*)s->setting + 1;
888 else if (s->cfg_vals == NULL)
889 /* %?St|name|<1st choice|2nd choice|...> */
890 *intval = (*(int*)s->setting-s->int_setting->min)
891 /s->int_setting->step + 1;
892 else
893 /* %?St|name|<1st choice|2nd choice|...> */
894 /* Not sure about this one. cfg_name/vals are
895 * indexed from 0 right? */
896 *intval = *(int*)s->setting + 1;
897 break;
898 case F_T_BOOL:
899 /* %?St|name|<if true|if false> */
900 *intval = *(bool*)s->setting?1:2;
901 break;
902 case F_T_CHARPTR:
903 /* %?St|name|<if non empty string|if empty>
904 * The string's emptyness discards the setting's
905 * prefix and suffix */
906 *intval = ((char*)s->setting)[0]?1:2;
907 break;
908 default:
909 /* This shouldn't happen ... but you never know */
910 *intval = -1;
911 break;
914 cfg_to_string(token->value.i,buf,buf_size);
915 return buf;
917 /* Recording tokens */
918 case WPS_TOKEN_HAVE_RECORDING:
919 #ifdef HAVE_RECORDING
920 return "r";
921 #else
922 return NULL;
923 #endif
925 #ifdef HAVE_RECORDING
926 case WPS_TOKEN_REC_FREQ: /* order from REC_FREQ_CFG_VAL_LIST */
928 #if CONFIG_CODEC == SWCODEC
929 unsigned long samprk;
930 int rec_freq = global_settings.rec_frequency;
932 #ifdef SIMULATOR
933 samprk = 44100;
934 #else
935 #if defined(HAVE_SPDIF_REC)
936 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
938 /* Use rate in use, not current measured rate if it changed */
939 samprk = pcm_rec_sample_rate();
940 rec_freq = 0;
941 while (rec_freq < SAMPR_NUM_FREQ &&
942 audio_master_sampr_list[rec_freq] != samprk)
944 rec_freq++;
947 else
948 #endif
949 samprk = rec_freq_sampr[rec_freq];
950 #endif /* SIMULATOR */
951 if (intval)
953 switch (rec_freq)
955 REC_HAVE_96_(case REC_FREQ_96:
956 *intval = 1;
957 break;)
958 REC_HAVE_88_(case REC_FREQ_88:
959 *intval = 2;
960 break;)
961 REC_HAVE_64_(case REC_FREQ_64:
962 *intval = 3;
963 break;)
964 REC_HAVE_48_(case REC_FREQ_48:
965 *intval = 4;
966 break;)
967 REC_HAVE_44_(case REC_FREQ_44:
968 *intval = 5;
969 break;)
970 REC_HAVE_32_(case REC_FREQ_32:
971 *intval = 6;
972 break;)
973 REC_HAVE_24_(case REC_FREQ_24:
974 *intval = 7;
975 break;)
976 REC_HAVE_22_(case REC_FREQ_22:
977 *intval = 8;
978 break;)
979 REC_HAVE_16_(case REC_FREQ_16:
980 *intval = 9;
981 break;)
982 REC_HAVE_12_(case REC_FREQ_12:
983 *intval = 10;
984 break;)
985 REC_HAVE_11_(case REC_FREQ_11:
986 *intval = 11;
987 break;)
988 REC_HAVE_8_(case REC_FREQ_8:
989 *intval = 12;
990 break;)
992 *intval = rec_freq+1;
994 snprintf(buf, buf_size, "%d.%1d", samprk/1000,samprk%1000);
995 #else /* HWCODEC */
997 static const char * const freq_strings[] =
998 {"--", "44", "48", "32", "22", "24", "16"};
999 int freq = 1 + global_settings.rec_frequency;
1000 #ifdef HAVE_SPDIF_REC
1001 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
1003 /* Can't measure S/PDIF sample rate on Archos/Sim yet */
1004 freq = 0;
1006 #endif /* HAVE_SPDIF_IN */
1007 if (intval)
1008 *intval = freq+1; /* so the token gets a value 1<=x<=7 */
1009 snprintf(buf, buf_size, "%d\n",
1010 freq_strings[global_settings.rec_frequency]);
1011 #endif
1012 return buf;
1014 #if CONFIG_CODEC == SWCODEC
1015 case WPS_TOKEN_REC_ENCODER:
1017 int rec_format = global_settings.rec_format+1; /* WAV, AIFF, WV, MPEG */
1018 if (intval)
1019 *intval = rec_format;
1020 switch (rec_format)
1022 case REC_FORMAT_PCM_WAV:
1023 return "wav";
1024 case REC_FORMAT_AIFF:
1025 return "aiff";
1026 case REC_FORMAT_WAVPACK:
1027 return "wv";
1028 case REC_FORMAT_MPA_L3:
1029 return "MP3";
1030 default:
1031 return NULL;
1033 break;
1035 #endif
1036 case WPS_TOKEN_REC_BITRATE:
1037 #if CONFIG_CODEC == SWCODEC
1038 if (global_settings.rec_format == REC_FORMAT_MPA_L3)
1040 if (intval)
1042 #if 0 /* FIXME: I dont know if this is needed? */
1043 switch (1<<global_settings.mp3_enc_config.bitrate)
1045 case MP3_BITR_CAP_8:
1046 *intval = 1;
1047 break;
1048 case MP3_BITR_CAP_16:
1049 *intval = 2;
1050 break;
1051 case MP3_BITR_CAP_24:
1052 *intval = 3;
1053 break;
1054 case MP3_BITR_CAP_32:
1055 *intval = 4;
1056 break;
1057 case MP3_BITR_CAP_40:
1058 *intval = 5;
1059 break;
1060 case MP3_BITR_CAP_48:
1061 *intval = 6;
1062 break;
1063 case MP3_BITR_CAP_56:
1064 *intval = 7;
1065 break;
1066 case MP3_BITR_CAP_64:
1067 *intval = 8;
1068 break;
1069 case MP3_BITR_CAP_80:
1070 *intval = 9;
1071 break;
1072 case MP3_BITR_CAP_96:
1073 *intval = 10;
1074 break;
1075 case MP3_BITR_CAP_112:
1076 *intval = 11;
1077 break;
1078 case MP3_BITR_CAP_128:
1079 *intval = 12;
1080 break;
1081 case MP3_BITR_CAP_144:
1082 *intval = 13;
1083 break;
1084 case MP3_BITR_CAP_160:
1085 *intval = 14;
1086 break;
1087 case MP3_BITR_CAP_192:
1088 *intval = 15;
1089 break;
1091 #endif
1093 *intval = global_settings.mp3_enc_config.bitrate+1;
1094 snprintf(buf, buf_size, "%d", global_settings.mp3_enc_config.bitrate+1);
1095 return buf;
1097 else
1098 return NULL; /* Fixme later */
1099 #else /* CONFIG_CODEC == HWCODEC */
1100 if (intval)
1101 *intval = global_settings.rec_quality+1;
1102 snprintf(buf, buf_size, "%d", global_settings.rec_quality);
1103 return buf;
1104 #endif
1105 case WPS_TOKEN_REC_MONO:
1106 if (intval)
1107 *intval = global_settings.rec_channels?2:1;
1108 snprintf(buf, buf_size, "%s", !global_settings.rec_channels?"m":'\0');
1109 return buf;
1111 #endif /* HAVE_RECORDING */
1112 case WPS_TOKEN_CURRENT_SCREEN:
1114 int curr_screen = current_screen();
1116 #ifdef HAVE_RECORDING
1117 /* override current_screen() for recording screen since it may
1118 * be entered from the radio screen */
1119 if (in_recording_screen())
1120 curr_screen = GO_TO_RECSCREEN;
1121 #endif
1123 switch (curr_screen)
1125 case GO_TO_WPS:
1126 curr_screen = 2;
1127 break;
1128 #ifdef HAVE_RECORDING
1129 case GO_TO_RECSCREEN:
1130 curr_screen = 3;
1131 break;
1132 #endif
1133 #if CONFIG_TUNER
1134 case GO_TO_FM:
1135 curr_screen = 4;
1136 break;
1137 #endif
1138 default: /* lists */
1139 curr_screen = 1;
1140 break;
1142 if (intval)
1145 *intval = curr_screen;
1147 snprintf(buf, buf_size, "%d", curr_screen);
1148 return buf;
1151 default:
1152 return NULL;