Don't define pitch_speed_enum() on MAS3507D. Fixes yellow
[kugel-rb.git] / apps / gui / skin_engine / skin_tokens.c
blob9cd8dfcdb0d300677d6c42c2e69e9941a6a0f41c
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 #if (CONFIG_CODEC != MAS3507D)
111 /* A helper to determine the enum value for pitch/speed.
113 When there are two choices (i.e. boolean), return 1 if the value is
114 different from normal value and 2 if the value is the same as the
115 normal value. E.g. "%?Sp<%Sp>" would show the pitch only when
116 playing at a modified pitch.
118 When there are more than two choices (i.e. enum), the left half of
119 the choices are to show 0..normal range, and the right half of the
120 choices are to show values over that. The last entry is used when
121 it is set to the normal setting, following the rockbox convention
122 to use the last entry for special values.
124 E.g.
126 2 items: %?Sp<0..99 or 101..infinity|100>
127 3 items: %?Sp<0..99|101..infinity|100>
128 4 items: %?Sp<0..49|50..99|101..infinity|100>
129 5 items: %?Sp<0..49|50..99|101..149|150..infinity|100>
130 6 items: %?Sp<0..33|34..66|67..99|101..133|134..infinity|100>
131 7 items: %?Sp<0..33|34..66|67..99|101..133|134..167|167..infinity|100>
133 static int pitch_speed_enum(int range, int32_t val, int32_t normval)
135 int center;
136 int n;
138 if (range < 3)
139 return (val == normval) + 1;
140 if (val == normval)
141 return range;
142 center = range / 2;
143 n = (center * val) / normval + 1;
144 return (range <= n) ? (range - 1) : n;
146 #endif
148 /* Return the tag found at index i and write its value in buf.
149 The return value is buf if the tag had a value, or NULL if not.
151 intval is used with conditionals/enums: when this function is called,
152 intval should contain the number of options in the conditional/enum.
153 When this function returns, intval is -1 if the tag is non numeric or,
154 if the tag is numeric, *intval is the enum case we want to go to (between 1
155 and the original value of *intval, inclusive).
156 When not treating a conditional/enum, intval should be NULL.
159 /* a few convinience macros for the id3 == NULL case
160 * depends on a few variable names in get_token_value() */
162 #define HANDLE_NULL_ID3(id3field) (LIKELY(id3) ? (id3field) : NULL)
164 #define HANDLE_NULL_ID3_NUM_ZERO { if (UNLIKELY(!id3)) return zero_str; }
166 #define HANDLE_NULL_ID3_NUM_INTVAL(id3field) \
167 do { \
168 if (intval) { \
169 *intval = (LIKELY(id3) ? (id3field) + 1 : 0); \
171 if (LIKELY(id3)) \
173 snprintf(buf, buf_size, "%ld", (id3field)); \
174 return buf; \
176 return zero_str; \
177 } while (0)
179 const char *get_token_value(struct gui_wps *gwps,
180 struct wps_token *token,
181 char *buf, int buf_size,
182 int *intval)
184 if (!gwps)
185 return NULL;
187 struct wps_data *data = gwps->data;
188 struct wps_state *state = gwps->state;
189 int elapsed, length;
190 static const char * const zero_str = "0";
192 if (!data || !state)
193 return NULL;
195 struct mp3entry *id3;
197 if (token->next)
198 id3 = state->nid3;
199 else
200 id3 = state->id3;
202 if (id3)
204 elapsed = id3->elapsed;
205 length = id3->length;
207 else
209 elapsed = 0;
210 length = 0;
213 #if CONFIG_RTC
214 struct tm* tm = NULL;
216 /* if the token is an RTC one, update the time
217 and do the necessary checks */
218 if (token->type >= WPS_TOKENS_RTC_BEGIN
219 && token->type <= WPS_TOKENS_RTC_END)
221 tm = get_time();
223 if (!valid_time(tm))
224 return NULL;
226 #endif
228 int limit = 1;
229 if (intval)
231 limit = *intval;
232 *intval = -1;
235 switch (token->type)
237 case WPS_TOKEN_CHARACTER:
238 if (token->value.c == '\n')
239 return NULL;
240 return &(token->value.c);
242 case WPS_TOKEN_STRING:
243 return (char*)token->value.data;
245 case WPS_TOKEN_TRANSLATEDSTRING:
246 return (char*)P2STR(ID2P(token->value.i));
248 case WPS_TOKEN_TRACK_TIME_ELAPSED:
249 format_time(buf, buf_size,
250 elapsed + state->ff_rewind_count);
251 return buf;
253 case WPS_TOKEN_TRACK_TIME_REMAINING:
254 format_time(buf, buf_size,
255 length - elapsed -
256 state->ff_rewind_count);
257 return buf;
259 case WPS_TOKEN_TRACK_LENGTH:
260 format_time(buf, buf_size, length);
261 return buf;
263 case WPS_TOKEN_PLAYLIST_ENTRIES:
264 snprintf(buf, buf_size, "%d", playlist_amount());
265 return buf;
267 case WPS_TOKEN_PLAYLIST_NAME:
268 return playlist_name(NULL, buf, buf_size);
270 case WPS_TOKEN_PLAYLIST_POSITION:
271 snprintf(buf, buf_size, "%d", playlist_get_display_index());
272 return buf;
274 case WPS_TOKEN_PLAYLIST_SHUFFLE:
275 if ( global_settings.playlist_shuffle )
276 return "s";
277 else
278 return NULL;
279 break;
281 case WPS_TOKEN_VOLUME:
282 snprintf(buf, buf_size, "%d", global_settings.volume);
283 if (intval)
285 if (global_settings.volume == sound_min(SOUND_VOLUME))
287 *intval = 1;
289 else if (global_settings.volume == 0)
291 *intval = limit - 1;
293 else if (global_settings.volume > 0)
295 *intval = limit;
297 else
299 *intval = (limit - 3) * (global_settings.volume
300 - sound_min(SOUND_VOLUME) - 1)
301 / (-1 - sound_min(SOUND_VOLUME)) + 2;
304 return buf;
306 case WPS_TOKEN_TRACK_ELAPSED_PERCENT:
307 if (length <= 0)
308 return NULL;
310 if (intval)
312 *intval = limit * (elapsed + state->ff_rewind_count)
313 / length + 1;
315 snprintf(buf, buf_size, "%d",
316 100*(elapsed + state->ff_rewind_count) / length);
317 return buf;
319 case WPS_TOKEN_METADATA_ARTIST:
320 return HANDLE_NULL_ID3(id3->artist);
322 case WPS_TOKEN_METADATA_COMPOSER:
323 return HANDLE_NULL_ID3(id3->composer);
325 case WPS_TOKEN_METADATA_ALBUM:
326 return HANDLE_NULL_ID3(id3->album);
328 case WPS_TOKEN_METADATA_ALBUM_ARTIST:
329 return HANDLE_NULL_ID3(id3->albumartist);
331 case WPS_TOKEN_METADATA_GROUPING:
332 return HANDLE_NULL_ID3(id3->grouping);
334 case WPS_TOKEN_METADATA_GENRE:
335 return HANDLE_NULL_ID3(id3->genre_string);
337 case WPS_TOKEN_METADATA_DISC_NUMBER:
338 if (LIKELY(id3)) {
339 if (id3->disc_string)
340 return id3->disc_string;
341 if (id3->discnum) {
342 snprintf(buf, buf_size, "%d", id3->discnum);
343 return buf;
346 return NULL;
348 case WPS_TOKEN_METADATA_TRACK_NUMBER:
349 if (LIKELY(id3)) {
350 if (id3->track_string)
351 return id3->track_string;
353 if (id3->tracknum) {
354 snprintf(buf, buf_size, "%d", id3->tracknum);
355 return buf;
358 return NULL;
360 case WPS_TOKEN_METADATA_TRACK_TITLE:
361 return HANDLE_NULL_ID3(id3->title);
363 case WPS_TOKEN_METADATA_VERSION:
364 if (LIKELY(id3))
366 switch (id3->id3version)
368 case ID3_VER_1_0:
369 return "1";
371 case ID3_VER_1_1:
372 return "1.1";
374 case ID3_VER_2_2:
375 return "2.2";
377 case ID3_VER_2_3:
378 return "2.3";
380 case ID3_VER_2_4:
381 return "2.4";
383 default:
384 break;
387 return NULL;
389 case WPS_TOKEN_METADATA_YEAR:
390 if (LIKELY(id3)) {
391 if( id3->year_string )
392 return id3->year_string;
394 if (id3->year) {
395 snprintf(buf, buf_size, "%d", id3->year);
396 return buf;
399 return NULL;
401 case WPS_TOKEN_METADATA_COMMENT:
402 return HANDLE_NULL_ID3(id3->comment);
404 #ifdef HAVE_ALBUMART
405 case WPS_TOKEN_ALBUMART_FOUND:
406 if (data->albumart) {
407 if (playback_current_aa_hid(data->playback_aa_slot) >= 0)
408 return "C";
410 return NULL;
412 case WPS_TOKEN_ALBUMART_DISPLAY:
413 if (!data->albumart)
414 return NULL;
415 if (!data->albumart->draw)
416 data->albumart->draw = true;
417 return NULL;
418 #endif
420 case WPS_TOKEN_FILE_BITRATE:
421 if(id3 && id3->bitrate)
422 snprintf(buf, buf_size, "%d", id3->bitrate);
423 else
424 return "?";
425 return buf;
427 case WPS_TOKEN_FILE_CODEC:
428 if (intval)
430 if (UNLIKELY(!id3))
431 *intval = 0;
432 else if(id3->codectype == AFMT_UNKNOWN)
433 *intval = AFMT_NUM_CODECS;
434 else
435 *intval = id3->codectype;
437 return get_codectype(id3);
439 case WPS_TOKEN_FILE_FREQUENCY:
440 HANDLE_NULL_ID3_NUM_ZERO;
441 snprintf(buf, buf_size, "%ld", id3->frequency);
442 return buf;
444 case WPS_TOKEN_FILE_FREQUENCY_KHZ:
445 HANDLE_NULL_ID3_NUM_ZERO;
446 /* ignore remainders < 100, so 22050 Hz becomes just 22k */
447 if ((id3->frequency % 1000) < 100)
448 snprintf(buf, buf_size, "%ld", id3->frequency / 1000);
449 else
450 snprintf(buf, buf_size, "%ld.%d",
451 id3->frequency / 1000,
452 (id3->frequency % 1000) / 100);
453 return buf;
455 case WPS_TOKEN_FILE_NAME:
456 if (LIKELY(id3) && get_dir(buf, buf_size, id3->path, 0)) {
457 /* Remove extension */
458 char* sep = strrchr(buf, '.');
459 if (NULL != sep) {
460 *sep = 0;
462 return buf;
464 else {
465 return NULL;
468 case WPS_TOKEN_FILE_NAME_WITH_EXTENSION:
469 if (LIKELY(id3))
470 return get_dir(buf, buf_size, id3->path, 0);
471 return NULL;
473 case WPS_TOKEN_FILE_PATH:
474 return HANDLE_NULL_ID3(id3->path);
476 case WPS_TOKEN_FILE_SIZE:
477 HANDLE_NULL_ID3_NUM_ZERO;
478 snprintf(buf, buf_size, "%ld", id3->filesize / 1024);
479 return buf;
481 case WPS_TOKEN_FILE_VBR:
482 return (LIKELY(id3) && id3->vbr) ? "(avg)" : NULL;
484 case WPS_TOKEN_FILE_DIRECTORY:
485 if (LIKELY(id3))
486 return get_dir(buf, buf_size, id3->path, token->value.i);
487 return NULL;
489 case WPS_TOKEN_BATTERY_PERCENT:
491 int l = battery_level();
493 if (intval)
495 limit = MAX(limit, 2);
496 if (l > -1) {
497 /* First enum is used for "unknown level". */
498 *intval = (limit - 1) * l / 100 + 2;
499 } else {
500 *intval = 1;
504 if (l > -1) {
505 snprintf(buf, buf_size, "%d", l);
506 return buf;
507 } else {
508 return "?";
512 case WPS_TOKEN_BATTERY_VOLTS:
514 unsigned int v = battery_voltage();
515 snprintf(buf, buf_size, "%d.%02d", v / 1000, (v % 1000) / 10);
516 return buf;
519 case WPS_TOKEN_BATTERY_TIME:
521 int t = battery_time();
522 if (t >= 0)
523 snprintf(buf, buf_size, "%dh %dm", t / 60, t % 60);
524 else
525 return "?h ?m";
526 return buf;
529 #if CONFIG_CHARGING
530 case WPS_TOKEN_BATTERY_CHARGER_CONNECTED:
532 if(charger_input_state==CHARGER)
533 return "p";
534 else
535 return NULL;
537 #endif
538 #if CONFIG_CHARGING >= CHARGING_MONITOR
539 case WPS_TOKEN_BATTERY_CHARGING:
541 if (charge_state == CHARGING || charge_state == TOPOFF) {
542 return "c";
543 } else {
544 return NULL;
547 #endif
548 case WPS_TOKEN_BATTERY_SLEEPTIME:
550 if (get_sleep_timer() == 0)
551 return NULL;
552 else
554 format_time(buf, buf_size, get_sleep_timer() * 1000);
555 return buf;
559 case WPS_TOKEN_PLAYBACK_STATUS:
561 int status = current_playmode();
562 /* music */
563 int mode = 1; /* stop */
564 if (status == STATUS_PLAY)
565 mode = 2; /* play */
566 if (state->is_fading ||
567 (status == STATUS_PAUSE && !status_get_ffmode()))
568 mode = 3; /* pause */
569 else
570 { /* ff / rwd */
571 if (status_get_ffmode() == STATUS_FASTFORWARD)
572 mode = 4;
573 if (status_get_ffmode() == STATUS_FASTBACKWARD)
574 mode = 5;
576 #ifdef HAVE_RECORDING
577 /* recording */
578 if (status == STATUS_RECORD)
579 mode = 6;
580 else if (status == STATUS_RECORD_PAUSE)
581 mode = 7;
582 #endif
583 #if CONFIG_TUNER
584 /* radio */
585 if (status == STATUS_RADIO)
586 mode = 8;
587 else if (status == STATUS_RADIO_PAUSE)
588 mode = 9;
589 #endif
591 if (intval) {
592 *intval = mode;
595 snprintf(buf, buf_size, "%d", mode-1);
596 return buf;
599 case WPS_TOKEN_REPEAT_MODE:
600 if (intval)
601 *intval = global_settings.repeat_mode + 1;
602 snprintf(buf, buf_size, "%d", global_settings.repeat_mode);
603 return buf;
605 case WPS_TOKEN_RTC_PRESENT:
606 #if CONFIG_RTC
607 return "c";
608 #else
609 return NULL;
610 #endif
612 #if CONFIG_RTC
613 case WPS_TOKEN_RTC_12HOUR_CFG:
614 if (intval)
615 *intval = global_settings.timeformat + 1;
616 snprintf(buf, buf_size, "%d", global_settings.timeformat);
617 return buf;
619 case WPS_TOKEN_RTC_DAY_OF_MONTH:
620 /* d: day of month (01..31) */
621 snprintf(buf, buf_size, "%02d", tm->tm_mday);
622 return buf;
624 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
625 /* e: day of month, blank padded ( 1..31) */
626 snprintf(buf, buf_size, "%2d", tm->tm_mday);
627 return buf;
629 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED:
630 /* H: hour (00..23) */
631 snprintf(buf, buf_size, "%02d", tm->tm_hour);
632 return buf;
634 case WPS_TOKEN_RTC_HOUR_24:
635 /* k: hour ( 0..23) */
636 snprintf(buf, buf_size, "%2d", tm->tm_hour);
637 return buf;
639 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED:
640 /* I: hour (01..12) */
641 snprintf(buf, buf_size, "%02d",
642 (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
643 return buf;
645 case WPS_TOKEN_RTC_HOUR_12:
646 /* l: hour ( 1..12) */
647 snprintf(buf, buf_size, "%2d",
648 (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
649 return buf;
651 case WPS_TOKEN_RTC_MONTH:
652 /* m: month (01..12) */
653 if (intval)
654 *intval = tm->tm_mon + 1;
655 snprintf(buf, buf_size, "%02d", tm->tm_mon + 1);
656 return buf;
658 case WPS_TOKEN_RTC_MINUTE:
659 /* M: minute (00..59) */
660 snprintf(buf, buf_size, "%02d", tm->tm_min);
661 return buf;
663 case WPS_TOKEN_RTC_SECOND:
664 /* S: second (00..59) */
665 snprintf(buf, buf_size, "%02d", tm->tm_sec);
666 return buf;
668 case WPS_TOKEN_RTC_YEAR_2_DIGITS:
669 /* y: last two digits of year (00..99) */
670 snprintf(buf, buf_size, "%02d", tm->tm_year % 100);
671 return buf;
673 case WPS_TOKEN_RTC_YEAR_4_DIGITS:
674 /* Y: year (1970...) */
675 snprintf(buf, buf_size, "%04d", tm->tm_year + 1900);
676 return buf;
678 case WPS_TOKEN_RTC_AM_PM_UPPER:
679 /* p: upper case AM or PM indicator */
680 return tm->tm_hour/12 == 0 ? "AM" : "PM";
682 case WPS_TOKEN_RTC_AM_PM_LOWER:
683 /* P: lower case am or pm indicator */
684 return tm->tm_hour/12 == 0 ? "am" : "pm";
686 case WPS_TOKEN_RTC_WEEKDAY_NAME:
687 /* a: abbreviated weekday name (Sun..Sat) */
688 return str(LANG_WEEKDAY_SUNDAY + tm->tm_wday);
690 case WPS_TOKEN_RTC_MONTH_NAME:
691 /* b: abbreviated month name (Jan..Dec) */
692 return str(LANG_MONTH_JANUARY + tm->tm_mon);
694 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
695 /* u: day of week (1..7); 1 is Monday */
696 if (intval)
697 *intval = (tm->tm_wday == 0) ? 7 : tm->tm_wday;
698 snprintf(buf, buf_size, "%1d", tm->tm_wday + 1);
699 return buf;
701 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
702 /* w: day of week (0..6); 0 is Sunday */
703 if (intval)
704 *intval = tm->tm_wday + 1;
705 snprintf(buf, buf_size, "%1d", tm->tm_wday);
706 return buf;
707 #else
708 case WPS_TOKEN_RTC_DAY_OF_MONTH:
709 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
710 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED:
711 case WPS_TOKEN_RTC_HOUR_24:
712 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED:
713 case WPS_TOKEN_RTC_HOUR_12:
714 case WPS_TOKEN_RTC_MONTH:
715 case WPS_TOKEN_RTC_MINUTE:
716 case WPS_TOKEN_RTC_SECOND:
717 case WPS_TOKEN_RTC_AM_PM_UPPER:
718 case WPS_TOKEN_RTC_AM_PM_LOWER:
719 case WPS_TOKEN_RTC_YEAR_2_DIGITS:
720 return "--";
721 case WPS_TOKEN_RTC_YEAR_4_DIGITS:
722 return "----";
723 case WPS_TOKEN_RTC_WEEKDAY_NAME:
724 case WPS_TOKEN_RTC_MONTH_NAME:
725 return "---";
726 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
727 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
728 return "-";
729 #endif
731 #ifdef HAVE_LCD_CHARCELLS
732 case WPS_TOKEN_PROGRESSBAR:
734 char *end = utf8encode(data->wps_progress_pat[0], buf);
735 *end = '\0';
736 return buf;
739 case WPS_TOKEN_PLAYER_PROGRESSBAR:
740 if(is_new_player())
742 /* we need 11 characters (full line) for
743 progress-bar */
744 strlcpy(buf, " ", buf_size);
746 else
748 /* Tell the user if we have an OldPlayer */
749 strlcpy(buf, " <Old LCD> ", buf_size);
751 return buf;
752 #endif
755 #ifdef HAVE_TAGCACHE
756 case WPS_TOKEN_DATABASE_PLAYCOUNT:
757 HANDLE_NULL_ID3_NUM_INTVAL(id3->playcount);
759 case WPS_TOKEN_DATABASE_RATING:
760 HANDLE_NULL_ID3_NUM_INTVAL(id3->rating);
762 case WPS_TOKEN_DATABASE_AUTOSCORE:
763 HANDLE_NULL_ID3_NUM_INTVAL(id3->score);
764 #endif
766 #if (CONFIG_CODEC == SWCODEC)
767 case WPS_TOKEN_CROSSFADE:
768 if (intval)
769 *intval = global_settings.crossfade + 1;
770 snprintf(buf, buf_size, "%d", global_settings.crossfade);
771 return buf;
773 case WPS_TOKEN_REPLAYGAIN:
775 int val;
777 if (global_settings.replaygain_type == REPLAYGAIN_OFF)
778 val = 1; /* off */
779 else
781 int type;
782 if (LIKELY(id3))
783 type = get_replaygain_mode(id3->track_gain_string != NULL,
784 id3->album_gain_string != NULL);
785 else
786 type = -1;
788 if (type < 0)
789 val = 6; /* no tag */
790 else
791 val = type + 2;
793 if (global_settings.replaygain_type == REPLAYGAIN_SHUFFLE)
794 val += 2;
797 if (intval)
798 *intval = val;
800 switch (val)
802 case 1:
803 case 6:
804 return "+0.00 dB";
805 break;
806 /* due to above, coming here with !id3 shouldn't be possible */
807 case 2:
808 case 4:
809 strlcpy(buf, id3->track_gain_string, buf_size);
810 break;
811 case 3:
812 case 5:
813 strlcpy(buf, id3->album_gain_string, buf_size);
814 break;
816 return buf;
818 #endif /* (CONFIG_CODEC == SWCODEC) */
820 #if (CONFIG_CODEC != MAS3507D)
821 case WPS_TOKEN_SOUND_PITCH:
823 int32_t pitch = sound_get_pitch();
824 snprintf(buf, buf_size, "%ld.%ld",
825 pitch / PITCH_SPEED_PRECISION,
826 (pitch % PITCH_SPEED_PRECISION) / (PITCH_SPEED_PRECISION / 10));
828 if (intval)
829 *intval = pitch_speed_enum(limit, pitch,
830 PITCH_SPEED_PRECISION * 100);
831 return buf;
833 #endif
835 case WPS_TOKEN_MAIN_HOLD:
836 #ifdef HAS_BUTTON_HOLD
837 if (button_hold())
838 #else
839 if (is_keys_locked())
840 #endif /*hold switch or softlock*/
841 return "h";
842 else
843 return NULL;
845 #ifdef HAS_REMOTE_BUTTON_HOLD
846 case WPS_TOKEN_REMOTE_HOLD:
847 if (remote_button_hold())
848 return "r";
849 else
850 return NULL;
851 #endif
853 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
854 case WPS_TOKEN_VLED_HDD:
855 if(led_read(HZ/2))
856 return "h";
857 else
858 return NULL;
859 #endif
860 case WPS_TOKEN_BUTTON_VOLUME:
861 if (global_status.last_volume_change &&
862 TIME_BEFORE(current_tick, global_status.last_volume_change +
863 token->value.i * TIMEOUT_UNIT))
864 return "v";
865 return NULL;
866 case WPS_TOKEN_LASTTOUCH:
867 #ifdef HAVE_TOUCHSCREEN
868 if (TIME_BEFORE(current_tick, token->value.i * TIMEOUT_UNIT +
869 touchscreen_last_touch()))
870 return "t";
871 #endif
872 return NULL;
874 case WPS_TOKEN_SETTING:
876 if (intval)
878 /* Handle contionals */
879 const struct settings_list *s = settings+token->value.i;
880 switch (s->flags&F_T_MASK)
882 case F_T_INT:
883 case F_T_UINT:
884 if (s->flags&F_RGB)
885 /* %?St|name|<#000000|#000001|...|#FFFFFF> */
886 /* shouldn't overflow since colors are stored
887 * on 16 bits ...
888 * but this is pretty useless anyway */
889 *intval = *(int*)s->setting + 1;
890 else if (s->cfg_vals == NULL)
891 /* %?St|name|<1st choice|2nd choice|...> */
892 *intval = (*(int*)s->setting-s->int_setting->min)
893 /s->int_setting->step + 1;
894 else
895 /* %?St|name|<1st choice|2nd choice|...> */
896 /* Not sure about this one. cfg_name/vals are
897 * indexed from 0 right? */
898 *intval = *(int*)s->setting + 1;
899 break;
900 case F_T_BOOL:
901 /* %?St|name|<if true|if false> */
902 *intval = *(bool*)s->setting?1:2;
903 break;
904 case F_T_CHARPTR:
905 /* %?St|name|<if non empty string|if empty>
906 * The string's emptyness discards the setting's
907 * prefix and suffix */
908 *intval = ((char*)s->setting)[0]?1:2;
909 break;
910 default:
911 /* This shouldn't happen ... but you never know */
912 *intval = -1;
913 break;
916 cfg_to_string(token->value.i,buf,buf_size);
917 return buf;
919 /* Recording tokens */
920 case WPS_TOKEN_HAVE_RECORDING:
921 #ifdef HAVE_RECORDING
922 return "r";
923 #else
924 return NULL;
925 #endif
927 #ifdef HAVE_RECORDING
928 case WPS_TOKEN_REC_FREQ: /* order from REC_FREQ_CFG_VAL_LIST */
930 #if CONFIG_CODEC == SWCODEC
931 unsigned long samprk;
932 int rec_freq = global_settings.rec_frequency;
934 #ifdef SIMULATOR
935 samprk = 44100;
936 #else
937 #if defined(HAVE_SPDIF_REC)
938 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
940 /* Use rate in use, not current measured rate if it changed */
941 samprk = pcm_rec_sample_rate();
942 rec_freq = 0;
943 while (rec_freq < SAMPR_NUM_FREQ &&
944 audio_master_sampr_list[rec_freq] != samprk)
946 rec_freq++;
949 else
950 #endif
951 samprk = rec_freq_sampr[rec_freq];
952 #endif /* SIMULATOR */
953 if (intval)
955 switch (rec_freq)
957 REC_HAVE_96_(case REC_FREQ_96:
958 *intval = 1;
959 break;)
960 REC_HAVE_88_(case REC_FREQ_88:
961 *intval = 2;
962 break;)
963 REC_HAVE_64_(case REC_FREQ_64:
964 *intval = 3;
965 break;)
966 REC_HAVE_48_(case REC_FREQ_48:
967 *intval = 4;
968 break;)
969 REC_HAVE_44_(case REC_FREQ_44:
970 *intval = 5;
971 break;)
972 REC_HAVE_32_(case REC_FREQ_32:
973 *intval = 6;
974 break;)
975 REC_HAVE_24_(case REC_FREQ_24:
976 *intval = 7;
977 break;)
978 REC_HAVE_22_(case REC_FREQ_22:
979 *intval = 8;
980 break;)
981 REC_HAVE_16_(case REC_FREQ_16:
982 *intval = 9;
983 break;)
984 REC_HAVE_12_(case REC_FREQ_12:
985 *intval = 10;
986 break;)
987 REC_HAVE_11_(case REC_FREQ_11:
988 *intval = 11;
989 break;)
990 REC_HAVE_8_(case REC_FREQ_8:
991 *intval = 12;
992 break;)
994 *intval = rec_freq+1;
996 snprintf(buf, buf_size, "%d.%1d", samprk/1000,samprk%1000);
997 #else /* HWCODEC */
999 static const char * const freq_strings[] =
1000 {"--", "44", "48", "32", "22", "24", "16"};
1001 int freq = 1 + global_settings.rec_frequency;
1002 #ifdef HAVE_SPDIF_REC
1003 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
1005 /* Can't measure S/PDIF sample rate on Archos/Sim yet */
1006 freq = 0;
1008 #endif /* HAVE_SPDIF_IN */
1009 if (intval)
1010 *intval = freq+1; /* so the token gets a value 1<=x<=7 */
1011 snprintf(buf, buf_size, "%d\n",
1012 freq_strings[global_settings.rec_frequency]);
1013 #endif
1014 return buf;
1016 #if CONFIG_CODEC == SWCODEC
1017 case WPS_TOKEN_REC_ENCODER:
1019 int rec_format = global_settings.rec_format+1; /* WAV, AIFF, WV, MPEG */
1020 if (intval)
1021 *intval = rec_format;
1022 switch (rec_format)
1024 case REC_FORMAT_PCM_WAV:
1025 return "wav";
1026 case REC_FORMAT_AIFF:
1027 return "aiff";
1028 case REC_FORMAT_WAVPACK:
1029 return "wv";
1030 case REC_FORMAT_MPA_L3:
1031 return "MP3";
1032 default:
1033 return NULL;
1035 break;
1037 #endif
1038 case WPS_TOKEN_REC_BITRATE:
1039 #if CONFIG_CODEC == SWCODEC
1040 if (global_settings.rec_format == REC_FORMAT_MPA_L3)
1042 if (intval)
1044 #if 0 /* FIXME: I dont know if this is needed? */
1045 switch (1<<global_settings.mp3_enc_config.bitrate)
1047 case MP3_BITR_CAP_8:
1048 *intval = 1;
1049 break;
1050 case MP3_BITR_CAP_16:
1051 *intval = 2;
1052 break;
1053 case MP3_BITR_CAP_24:
1054 *intval = 3;
1055 break;
1056 case MP3_BITR_CAP_32:
1057 *intval = 4;
1058 break;
1059 case MP3_BITR_CAP_40:
1060 *intval = 5;
1061 break;
1062 case MP3_BITR_CAP_48:
1063 *intval = 6;
1064 break;
1065 case MP3_BITR_CAP_56:
1066 *intval = 7;
1067 break;
1068 case MP3_BITR_CAP_64:
1069 *intval = 8;
1070 break;
1071 case MP3_BITR_CAP_80:
1072 *intval = 9;
1073 break;
1074 case MP3_BITR_CAP_96:
1075 *intval = 10;
1076 break;
1077 case MP3_BITR_CAP_112:
1078 *intval = 11;
1079 break;
1080 case MP3_BITR_CAP_128:
1081 *intval = 12;
1082 break;
1083 case MP3_BITR_CAP_144:
1084 *intval = 13;
1085 break;
1086 case MP3_BITR_CAP_160:
1087 *intval = 14;
1088 break;
1089 case MP3_BITR_CAP_192:
1090 *intval = 15;
1091 break;
1093 #endif
1095 *intval = global_settings.mp3_enc_config.bitrate+1;
1096 snprintf(buf, buf_size, "%d", global_settings.mp3_enc_config.bitrate+1);
1097 return buf;
1099 else
1100 return NULL; /* Fixme later */
1101 #else /* CONFIG_CODEC == HWCODEC */
1102 if (intval)
1103 *intval = global_settings.rec_quality+1;
1104 snprintf(buf, buf_size, "%d", global_settings.rec_quality);
1105 return buf;
1106 #endif
1107 case WPS_TOKEN_REC_MONO:
1108 if (intval)
1109 *intval = global_settings.rec_channels?2:1;
1110 snprintf(buf, buf_size, "%s", !global_settings.rec_channels?"m":'\0');
1111 return buf;
1113 #endif /* HAVE_RECORDING */
1114 case WPS_TOKEN_CURRENT_SCREEN:
1116 int curr_screen = current_screen();
1118 #ifdef HAVE_RECORDING
1119 /* override current_screen() for recording screen since it may
1120 * be entered from the radio screen */
1121 if (in_recording_screen())
1122 curr_screen = GO_TO_RECSCREEN;
1123 #endif
1125 switch (curr_screen)
1127 case GO_TO_WPS:
1128 curr_screen = 2;
1129 break;
1130 #ifdef HAVE_RECORDING
1131 case GO_TO_RECSCREEN:
1132 curr_screen = 3;
1133 break;
1134 #endif
1135 #if CONFIG_TUNER
1136 case GO_TO_FM:
1137 curr_screen = 4;
1138 break;
1139 #endif
1140 default: /* lists */
1141 curr_screen = 1;
1142 break;
1144 if (intval)
1147 *intval = curr_screen;
1149 snprintf(buf, buf_size, "%d", curr_screen);
1150 return buf;
1153 default:
1154 return NULL;