Fix FS#10745 - %mv not working in sbs...
[kugel-rb.git] / apps / gui / skin_engine / skin_tokens.c
blob5156dd7ce72fc1f972a0e102d720926681df4220
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 "audio.h"
33 #include "status.h"
34 #include "power.h"
35 #include "powermgmt.h"
36 #include "sound.h"
37 #include "debug.h"
38 #ifdef HAVE_LCD_CHARCELLS
39 #include "hwcompat.h"
40 #endif
41 #include "abrepeat.h"
42 #include "mp3_playback.h"
43 #include "lang.h"
44 #include "misc.h"
45 #include "led.h"
46 #ifdef HAVE_LCD_BITMAP
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 #endif
55 #include "viewport.h"
57 #include "wps_internals.h"
58 #include "wps.h"
59 #include "root_menu.h"
60 #ifdef HAVE_RECORDING
61 #include "recording.h"
62 #endif
64 static char* get_codectype(const struct mp3entry* id3)
66 if (id3 && id3->codectype < AFMT_NUM_CODECS) {
67 return (char*)audio_formats[id3->codectype].label;
68 } else {
69 return NULL;
73 /* Extract a part from a path.
75 * buf - buffer extract part to.
76 * buf_size - size of buffer.
77 * path - path to extract from.
78 * level - what to extract. 0 is file name, 1 is parent of file, 2 is
79 * parent of parent, etc.
81 * Returns buf if the desired level was found, NULL otherwise.
83 static char* get_dir(char* buf, int buf_size, const char* path, int level)
85 const char* sep;
86 const char* last_sep;
87 int len;
89 sep = path + strlen(path);
90 last_sep = sep;
92 while (sep > path)
94 if ('/' == *(--sep))
96 if (!level)
97 break;
99 level--;
100 last_sep = sep - 1;
104 if (level || (last_sep <= sep))
105 return NULL;
107 len = MIN(last_sep - sep, buf_size - 1);
108 strlcpy(buf, sep + 1, len + 1);
109 return buf;
112 /* Return the tag found at index i and write its value in buf.
113 The return value is buf if the tag had a value, or NULL if not.
115 intval is used with conditionals/enums: when this function is called,
116 intval should contain the number of options in the conditional/enum.
117 When this function returns, intval is -1 if the tag is non numeric or,
118 if the tag is numeric, *intval is the enum case we want to go to (between 1
119 and the original value of *intval, inclusive).
120 When not treating a conditional/enum, intval should be NULL.
123 /* a few convinience macros for the id3 == NULL case
124 * depends on a few variable names in get_token_value() */
126 #define HANDLE_NULL_ID3(id3field) (LIKELY(id3) ? (id3field) : NULL)
128 #define HANDLE_NULL_ID3_NUM_ZERO { if (UNLIKELY(!id3)) return zero_str; }
130 #define HANDLE_NULL_ID3_NUM_INTVAL(id3field) \
131 do { \
132 if (intval) { \
133 *intval = (LIKELY(id3) ? (id3field) + 1 : 0); \
135 if (LIKELY(id3)) \
137 snprintf(buf, buf_size, "%ld", (id3field)); \
138 return buf; \
140 return zero_str; \
141 } while (0)
143 const char *get_token_value(struct gui_wps *gwps,
144 struct wps_token *token,
145 char *buf, int buf_size,
146 int *intval)
148 if (!gwps)
149 return NULL;
151 struct wps_data *data = gwps->data;
152 struct wps_state *state = gwps->state;
153 int elapsed, length;
154 static const char * const zero_str = "0";
156 if (!data || !state)
157 return NULL;
159 struct mp3entry *id3;
161 if (token->next)
162 id3 = state->nid3;
163 else
164 id3 = state->id3;
166 if (id3)
168 elapsed = id3->elapsed;
169 length = id3->length;
171 else
173 elapsed = 0;
174 length = 0;
177 #if CONFIG_RTC
178 struct tm* tm = NULL;
180 /* if the token is an RTC one, update the time
181 and do the necessary checks */
182 if (token->type >= WPS_TOKENS_RTC_BEGIN
183 && token->type <= WPS_TOKENS_RTC_END)
185 tm = get_time();
187 if (!valid_time(tm))
188 return NULL;
190 #endif
192 int limit = 1;
193 if (intval)
195 limit = *intval;
196 *intval = -1;
199 switch (token->type)
201 case WPS_TOKEN_CHARACTER:
202 if (token->value.c == '\n')
203 return NULL;
204 return &(token->value.c);
206 case WPS_TOKEN_STRING:
207 return (char*)token->value.data;
209 case WPS_TOKEN_TRANSLATEDSTRING:
210 return (char*)P2STR(ID2P(token->value.i));
212 case WPS_TOKEN_TRACK_TIME_ELAPSED:
213 format_time(buf, buf_size,
214 elapsed + state->ff_rewind_count);
215 return buf;
217 case WPS_TOKEN_TRACK_TIME_REMAINING:
218 format_time(buf, buf_size,
219 length - elapsed -
220 state->ff_rewind_count);
221 return buf;
223 case WPS_TOKEN_TRACK_LENGTH:
224 format_time(buf, buf_size, length);
225 return buf;
227 case WPS_TOKEN_PLAYLIST_ENTRIES:
228 snprintf(buf, buf_size, "%d", playlist_amount());
229 return buf;
231 case WPS_TOKEN_PLAYLIST_NAME:
232 return playlist_name(NULL, buf, buf_size);
234 case WPS_TOKEN_PLAYLIST_POSITION:
235 snprintf(buf, buf_size, "%d", playlist_get_display_index());
236 return buf;
238 case WPS_TOKEN_PLAYLIST_SHUFFLE:
239 if ( global_settings.playlist_shuffle )
240 return "s";
241 else
242 return NULL;
243 break;
245 case WPS_TOKEN_VOLUME:
246 snprintf(buf, buf_size, "%d", global_settings.volume);
247 if (intval)
249 if (global_settings.volume == sound_min(SOUND_VOLUME))
251 *intval = 1;
253 else if (global_settings.volume == 0)
255 *intval = limit - 1;
257 else if (global_settings.volume > 0)
259 *intval = limit;
261 else
263 *intval = (limit - 3) * (global_settings.volume
264 - sound_min(SOUND_VOLUME) - 1)
265 / (-1 - sound_min(SOUND_VOLUME)) + 2;
268 return buf;
270 case WPS_TOKEN_TRACK_ELAPSED_PERCENT:
271 if (length <= 0)
272 return NULL;
274 if (intval)
276 *intval = limit * (elapsed + state->ff_rewind_count)
277 / length + 1;
279 snprintf(buf, buf_size, "%d",
280 100*(elapsed + state->ff_rewind_count) / length);
281 return buf;
283 case WPS_TOKEN_METADATA_ARTIST:
284 return HANDLE_NULL_ID3(id3->artist);
286 case WPS_TOKEN_METADATA_COMPOSER:
287 return HANDLE_NULL_ID3(id3->composer);
289 case WPS_TOKEN_METADATA_ALBUM:
290 return HANDLE_NULL_ID3(id3->album);
292 case WPS_TOKEN_METADATA_ALBUM_ARTIST:
293 return HANDLE_NULL_ID3(id3->albumartist);
295 case WPS_TOKEN_METADATA_GROUPING:
296 return HANDLE_NULL_ID3(id3->grouping);
298 case WPS_TOKEN_METADATA_GENRE:
299 return HANDLE_NULL_ID3(id3->genre_string);
301 case WPS_TOKEN_METADATA_DISC_NUMBER:
302 if (LIKELY(id3)) {
303 if (id3->disc_string)
304 return id3->disc_string;
305 if (id3->discnum) {
306 snprintf(buf, buf_size, "%d", id3->discnum);
307 return buf;
310 return NULL;
312 case WPS_TOKEN_METADATA_TRACK_NUMBER:
313 if (LIKELY(id3)) {
314 if (id3->track_string)
315 return id3->track_string;
317 if (id3->tracknum) {
318 snprintf(buf, buf_size, "%d", id3->tracknum);
319 return buf;
322 return NULL;
324 case WPS_TOKEN_METADATA_TRACK_TITLE:
325 return HANDLE_NULL_ID3(id3->title);
327 case WPS_TOKEN_METADATA_VERSION:
328 if (LIKELY(id3))
330 switch (id3->id3version)
332 case ID3_VER_1_0:
333 return "1";
335 case ID3_VER_1_1:
336 return "1.1";
338 case ID3_VER_2_2:
339 return "2.2";
341 case ID3_VER_2_3:
342 return "2.3";
344 case ID3_VER_2_4:
345 return "2.4";
347 default:
348 break;
351 return NULL;
353 case WPS_TOKEN_METADATA_YEAR:
354 if (LIKELY(id3)) {
355 if( id3->year_string )
356 return id3->year_string;
358 if (id3->year) {
359 snprintf(buf, buf_size, "%d", id3->year);
360 return buf;
363 return NULL;
365 case WPS_TOKEN_METADATA_COMMENT:
366 return HANDLE_NULL_ID3(id3->comment);
368 #ifdef HAVE_ALBUMART
369 case WPS_TOKEN_ALBUMART_FOUND:
370 if (data->albumart) {
371 if (playback_current_aa_hid(data->playback_aa_slot) >= 0)
372 return "C";
374 return NULL;
376 case WPS_TOKEN_ALBUMART_DISPLAY:
377 if (!data->albumart)
378 return NULL;
379 if (!data->albumart->draw)
380 data->albumart->draw = true;
381 return NULL;
382 #endif
384 case WPS_TOKEN_FILE_BITRATE:
385 if(id3 && id3->bitrate)
386 snprintf(buf, buf_size, "%d", id3->bitrate);
387 else
388 return "?";
389 return buf;
391 case WPS_TOKEN_FILE_CODEC:
392 if (intval)
394 if (UNLIKELY(!id3))
395 *intval = 0;
396 else if(id3->codectype == AFMT_UNKNOWN)
397 *intval = AFMT_NUM_CODECS;
398 else
399 *intval = id3->codectype;
401 return get_codectype(id3);
403 case WPS_TOKEN_FILE_FREQUENCY:
404 HANDLE_NULL_ID3_NUM_ZERO;
405 snprintf(buf, buf_size, "%ld", id3->frequency);
406 return buf;
408 case WPS_TOKEN_FILE_FREQUENCY_KHZ:
409 HANDLE_NULL_ID3_NUM_ZERO;
410 /* ignore remainders < 100, so 22050 Hz becomes just 22k */
411 if ((id3->frequency % 1000) < 100)
412 snprintf(buf, buf_size, "%ld", id3->frequency / 1000);
413 else
414 snprintf(buf, buf_size, "%ld.%d",
415 id3->frequency / 1000,
416 (id3->frequency % 1000) / 100);
417 return buf;
419 case WPS_TOKEN_FILE_NAME:
420 if (LIKELY(id3) && get_dir(buf, buf_size, id3->path, 0)) {
421 /* Remove extension */
422 char* sep = strrchr(buf, '.');
423 if (NULL != sep) {
424 *sep = 0;
426 return buf;
428 else {
429 return NULL;
432 case WPS_TOKEN_FILE_NAME_WITH_EXTENSION:
433 if (LIKELY(id3))
434 return get_dir(buf, buf_size, id3->path, 0);
435 return NULL;
437 case WPS_TOKEN_FILE_PATH:
438 return HANDLE_NULL_ID3(id3->path);
440 case WPS_TOKEN_FILE_SIZE:
441 HANDLE_NULL_ID3_NUM_ZERO;
442 snprintf(buf, buf_size, "%ld", id3->filesize / 1024);
443 return buf;
445 case WPS_TOKEN_FILE_VBR:
446 return (LIKELY(id3) && id3->vbr) ? "(avg)" : NULL;
448 case WPS_TOKEN_FILE_DIRECTORY:
449 if (LIKELY(id3))
450 return get_dir(buf, buf_size, id3->path, token->value.i);
451 return NULL;
453 case WPS_TOKEN_BATTERY_PERCENT:
455 int l = battery_level();
457 if (intval)
459 limit = MAX(limit, 2);
460 if (l > -1) {
461 /* First enum is used for "unknown level". */
462 *intval = (limit - 1) * l / 100 + 2;
463 } else {
464 *intval = 1;
468 if (l > -1) {
469 snprintf(buf, buf_size, "%d", l);
470 return buf;
471 } else {
472 return "?";
476 case WPS_TOKEN_BATTERY_VOLTS:
478 unsigned int v = battery_voltage();
479 snprintf(buf, buf_size, "%d.%02d", v / 1000, (v % 1000) / 10);
480 return buf;
483 case WPS_TOKEN_BATTERY_TIME:
485 int t = battery_time();
486 if (t >= 0)
487 snprintf(buf, buf_size, "%dh %dm", t / 60, t % 60);
488 else
489 return "?h ?m";
490 return buf;
493 #if CONFIG_CHARGING
494 case WPS_TOKEN_BATTERY_CHARGER_CONNECTED:
496 if(charger_input_state==CHARGER)
497 return "p";
498 else
499 return NULL;
501 #endif
502 #if CONFIG_CHARGING >= CHARGING_MONITOR
503 case WPS_TOKEN_BATTERY_CHARGING:
505 if (charge_state == CHARGING || charge_state == TOPOFF) {
506 return "c";
507 } else {
508 return NULL;
511 #endif
512 case WPS_TOKEN_BATTERY_SLEEPTIME:
514 if (get_sleep_timer() == 0)
515 return NULL;
516 else
518 format_time(buf, buf_size, get_sleep_timer() * 1000);
519 return buf;
523 case WPS_TOKEN_PLAYBACK_STATUS:
525 int status = current_playmode();
526 /* music */
527 int mode = 1; /* stop */
528 if (status == STATUS_PLAY)
529 mode = 2; /* play */
530 if (is_wps_fading() ||
531 (status == STATUS_PAUSE && !status_get_ffmode()))
532 mode = 3; /* pause */
533 else
534 { /* ff / rwd */
535 if (status_get_ffmode() == STATUS_FASTFORWARD)
536 mode = 4;
537 if (status_get_ffmode() == STATUS_FASTBACKWARD)
538 mode = 5;
540 #ifdef HAVE_RECORDING
541 /* recording */
542 if (status == STATUS_RECORD)
543 mode = 6;
544 else if (status == STATUS_RECORD_PAUSE)
545 mode = 7;
546 #endif
547 #if CONFIG_TUNER
548 /* radio */
549 if (status == STATUS_RADIO)
550 mode = 8;
551 else if (status == STATUS_RADIO_PAUSE)
552 mode = 9;
553 #endif
555 if (intval) {
556 *intval = mode;
559 snprintf(buf, buf_size, "%d", mode-1);
560 return buf;
563 case WPS_TOKEN_REPEAT_MODE:
564 if (intval)
565 *intval = global_settings.repeat_mode + 1;
566 snprintf(buf, buf_size, "%d", global_settings.repeat_mode);
567 return buf;
569 case WPS_TOKEN_RTC_PRESENT:
570 #if CONFIG_RTC
571 return "c";
572 #else
573 return NULL;
574 #endif
576 #if CONFIG_RTC
577 case WPS_TOKEN_RTC_12HOUR_CFG:
578 if (intval)
579 *intval = global_settings.timeformat + 1;
580 snprintf(buf, buf_size, "%d", global_settings.timeformat);
581 return buf;
583 case WPS_TOKEN_RTC_DAY_OF_MONTH:
584 /* d: day of month (01..31) */
585 snprintf(buf, buf_size, "%02d", tm->tm_mday);
586 return buf;
588 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
589 /* e: day of month, blank padded ( 1..31) */
590 snprintf(buf, buf_size, "%2d", tm->tm_mday);
591 return buf;
593 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED:
594 /* H: hour (00..23) */
595 snprintf(buf, buf_size, "%02d", tm->tm_hour);
596 return buf;
598 case WPS_TOKEN_RTC_HOUR_24:
599 /* k: hour ( 0..23) */
600 snprintf(buf, buf_size, "%2d", tm->tm_hour);
601 return buf;
603 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED:
604 /* I: hour (01..12) */
605 snprintf(buf, buf_size, "%02d",
606 (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
607 return buf;
609 case WPS_TOKEN_RTC_HOUR_12:
610 /* l: hour ( 1..12) */
611 snprintf(buf, buf_size, "%2d",
612 (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
613 return buf;
615 case WPS_TOKEN_RTC_MONTH:
616 /* m: month (01..12) */
617 if (intval)
618 *intval = tm->tm_mon + 1;
619 snprintf(buf, buf_size, "%02d", tm->tm_mon + 1);
620 return buf;
622 case WPS_TOKEN_RTC_MINUTE:
623 /* M: minute (00..59) */
624 snprintf(buf, buf_size, "%02d", tm->tm_min);
625 return buf;
627 case WPS_TOKEN_RTC_SECOND:
628 /* S: second (00..59) */
629 snprintf(buf, buf_size, "%02d", tm->tm_sec);
630 return buf;
632 case WPS_TOKEN_RTC_YEAR_2_DIGITS:
633 /* y: last two digits of year (00..99) */
634 snprintf(buf, buf_size, "%02d", tm->tm_year % 100);
635 return buf;
637 case WPS_TOKEN_RTC_YEAR_4_DIGITS:
638 /* Y: year (1970...) */
639 snprintf(buf, buf_size, "%04d", tm->tm_year + 1900);
640 return buf;
642 case WPS_TOKEN_RTC_AM_PM_UPPER:
643 /* p: upper case AM or PM indicator */
644 return tm->tm_hour/12 == 0 ? "AM" : "PM";
646 case WPS_TOKEN_RTC_AM_PM_LOWER:
647 /* P: lower case am or pm indicator */
648 return tm->tm_hour/12 == 0 ? "am" : "pm";
650 case WPS_TOKEN_RTC_WEEKDAY_NAME:
651 /* a: abbreviated weekday name (Sun..Sat) */
652 return str(LANG_WEEKDAY_SUNDAY + tm->tm_wday);
654 case WPS_TOKEN_RTC_MONTH_NAME:
655 /* b: abbreviated month name (Jan..Dec) */
656 return str(LANG_MONTH_JANUARY + tm->tm_mon);
658 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
659 /* u: day of week (1..7); 1 is Monday */
660 if (intval)
661 *intval = (tm->tm_wday == 0) ? 7 : tm->tm_wday;
662 snprintf(buf, buf_size, "%1d", tm->tm_wday + 1);
663 return buf;
665 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
666 /* w: day of week (0..6); 0 is Sunday */
667 if (intval)
668 *intval = tm->tm_wday + 1;
669 snprintf(buf, buf_size, "%1d", tm->tm_wday);
670 return buf;
671 #else
672 case WPS_TOKEN_RTC_DAY_OF_MONTH:
673 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
674 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED:
675 case WPS_TOKEN_RTC_HOUR_24:
676 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED:
677 case WPS_TOKEN_RTC_HOUR_12:
678 case WPS_TOKEN_RTC_MONTH:
679 case WPS_TOKEN_RTC_MINUTE:
680 case WPS_TOKEN_RTC_SECOND:
681 case WPS_TOKEN_RTC_AM_PM_UPPER:
682 case WPS_TOKEN_RTC_AM_PM_LOWER:
683 case WPS_TOKEN_RTC_YEAR_2_DIGITS:
684 return "--";
685 case WPS_TOKEN_RTC_YEAR_4_DIGITS:
686 return "----";
687 case WPS_TOKEN_RTC_WEEKDAY_NAME:
688 case WPS_TOKEN_RTC_MONTH_NAME:
689 return "---";
690 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
691 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
692 return "-";
693 #endif
695 #ifdef HAVE_LCD_CHARCELLS
696 case WPS_TOKEN_PROGRESSBAR:
698 char *end = utf8encode(data->wps_progress_pat[0], buf);
699 *end = '\0';
700 return buf;
703 case WPS_TOKEN_PLAYER_PROGRESSBAR:
704 if(is_new_player())
706 /* we need 11 characters (full line) for
707 progress-bar */
708 strlcpy(buf, " ", buf_size);
710 else
712 /* Tell the user if we have an OldPlayer */
713 strlcpy(buf, " <Old LCD> ", buf_size);
715 return buf;
716 #endif
719 #ifdef HAVE_TAGCACHE
720 case WPS_TOKEN_DATABASE_PLAYCOUNT:
721 HANDLE_NULL_ID3_NUM_INTVAL(id3->playcount);
723 case WPS_TOKEN_DATABASE_RATING:
724 HANDLE_NULL_ID3_NUM_INTVAL(id3->rating);
726 case WPS_TOKEN_DATABASE_AUTOSCORE:
727 HANDLE_NULL_ID3_NUM_INTVAL(id3->score);
728 #endif
730 #if (CONFIG_CODEC == SWCODEC)
731 case WPS_TOKEN_CROSSFADE:
732 if (intval)
733 *intval = global_settings.crossfade + 1;
734 snprintf(buf, buf_size, "%d", global_settings.crossfade);
735 return buf;
737 case WPS_TOKEN_REPLAYGAIN:
739 int val;
741 if (global_settings.replaygain_type == REPLAYGAIN_OFF)
742 val = 1; /* off */
743 else
745 int type;
746 if (LIKELY(id3))
747 type = get_replaygain_mode(id3->track_gain_string != NULL,
748 id3->album_gain_string != NULL);
749 else
750 type = -1;
752 if (type < 0)
753 val = 6; /* no tag */
754 else
755 val = type + 2;
757 if (global_settings.replaygain_type == REPLAYGAIN_SHUFFLE)
758 val += 2;
761 if (intval)
762 *intval = val;
764 switch (val)
766 case 1:
767 case 6:
768 return "+0.00 dB";
769 break;
770 /* due to above, coming here with !id3 shouldn't be possible */
771 case 2:
772 case 4:
773 strlcpy(buf, id3->track_gain_string, buf_size);
774 break;
775 case 3:
776 case 5:
777 strlcpy(buf, id3->album_gain_string, buf_size);
778 break;
780 return buf;
782 #endif /* (CONFIG_CODEC == SWCODEC) */
784 #if (CONFIG_CODEC != MAS3507D)
785 case WPS_TOKEN_SOUND_PITCH:
787 int32_t pitch = sound_get_pitch();
788 snprintf(buf, buf_size, "%ld.%ld",
789 pitch / PITCH_SPEED_PRECISION,
790 (pitch % PITCH_SPEED_PRECISION) / (PITCH_SPEED_PRECISION / 10));
791 return buf;
793 #endif
795 case WPS_TOKEN_MAIN_HOLD:
796 #ifdef HAS_BUTTON_HOLD
797 if (button_hold())
798 #else
799 if (is_keys_locked())
800 #endif /*hold switch or softlock*/
801 return "h";
802 else
803 return NULL;
805 #ifdef HAS_REMOTE_BUTTON_HOLD
806 case WPS_TOKEN_REMOTE_HOLD:
807 if (remote_button_hold())
808 return "r";
809 else
810 return NULL;
811 #endif
813 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
814 case WPS_TOKEN_VLED_HDD:
815 if(led_read(HZ/2))
816 return "h";
817 else
818 return NULL;
819 #endif
820 case WPS_TOKEN_BUTTON_VOLUME:
821 if (global_status.last_volume_change &&
822 TIME_BEFORE(current_tick, global_status.last_volume_change +
823 token->value.i * TIMEOUT_UNIT))
824 return "v";
825 return NULL;
826 case WPS_TOKEN_LASTTOUCH:
827 #ifdef HAVE_TOUCHSCREEN
828 if (TIME_BEFORE(current_tick, token->value.i * TIMEOUT_UNIT +
829 touchscreen_last_touch()))
830 return "t";
831 #endif
832 return NULL;
834 case WPS_TOKEN_SETTING:
836 if (intval)
838 /* Handle contionals */
839 const struct settings_list *s = settings+token->value.i;
840 switch (s->flags&F_T_MASK)
842 case F_T_INT:
843 case F_T_UINT:
844 if (s->flags&F_RGB)
845 /* %?St|name|<#000000|#000001|...|#FFFFFF> */
846 /* shouldn't overflow since colors are stored
847 * on 16 bits ...
848 * but this is pretty useless anyway */
849 *intval = *(int*)s->setting + 1;
850 else if (s->cfg_vals == NULL)
851 /* %?St|name|<1st choice|2nd choice|...> */
852 *intval = (*(int*)s->setting-s->int_setting->min)
853 /s->int_setting->step + 1;
854 else
855 /* %?St|name|<1st choice|2nd choice|...> */
856 /* Not sure about this one. cfg_name/vals are
857 * indexed from 0 right? */
858 *intval = *(int*)s->setting + 1;
859 break;
860 case F_T_BOOL:
861 /* %?St|name|<if true|if false> */
862 *intval = *(bool*)s->setting?1:2;
863 break;
864 case F_T_CHARPTR:
865 /* %?St|name|<if non empty string|if empty>
866 * The string's emptyness discards the setting's
867 * prefix and suffix */
868 *intval = ((char*)s->setting)[0]?1:2;
869 break;
870 default:
871 /* This shouldn't happen ... but you never know */
872 *intval = -1;
873 break;
876 cfg_to_string(token->value.i,buf,buf_size);
877 return buf;
879 case WPS_TOKEN_CURRENT_SCREEN:
881 int curr_screen = current_screen();
883 #ifdef HAVE_RECORDING
884 /* override current_screen() for recording screen since it may
885 * be entered from the radio screen */
886 if (in_recording_screen())
887 curr_screen = GO_TO_RECSCREEN;
888 #endif
890 switch (curr_screen)
892 case GO_TO_WPS:
893 curr_screen = 2;
894 break;
895 #ifdef HAVE_RECORDING
896 case GO_TO_RECSCREEN:
897 curr_screen = 3;
898 break;
899 #endif
900 #if CONFIG_TUNER
901 case GO_TO_FM:
902 curr_screen = 4;
903 break;
904 #endif
905 default: /* lists */
906 curr_screen = 1;
907 break;
909 if (intval)
912 *intval = curr_screen;
914 snprintf(buf, buf_size, "%d", curr_screen);
915 return buf;
918 default:
919 return NULL;