make all the RTC tokens in the skins be useable in conditionals (I dare anyone to...
[kugel-rb.git] / apps / gui / skin_engine / skin_tokens.c
blobfa80e86ab61eee4f42cf43aee783e05d6ea1ef3f
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 #include "tdspeed.h"
53 #endif
54 #include "viewport.h"
56 #include "wps_internals.h"
57 #include "root_menu.h"
58 #ifdef HAVE_RECORDING
59 #include "recording.h"
60 #include "pcm_record.h"
61 #endif
62 #include "language.h"
63 #include "usb.h"
65 extern struct wps_state wps_state;
67 static char* get_codectype(const struct mp3entry* id3)
69 if (id3 && id3->codectype < AFMT_NUM_CODECS) {
70 return (char*)audio_formats[id3->codectype].label;
71 } else {
72 return NULL;
76 /* Extract a part from a path.
78 * buf - buffer extract part to.
79 * buf_size - size of buffer.
80 * path - path to extract from.
81 * level - what to extract. 0 is file name, 1 is parent of file, 2 is
82 * parent of parent, etc.
84 * Returns buf if the desired level was found, NULL otherwise.
86 char* get_dir(char* buf, int buf_size, const char* path, int level)
88 const char* sep;
89 const char* last_sep;
90 int len;
92 sep = path + strlen(path);
93 last_sep = sep;
95 while (sep > path)
97 if ('/' == *(--sep))
99 if (!level)
100 break;
102 level--;
103 last_sep = sep - 1;
107 if (level || (last_sep <= sep))
108 return NULL;
110 len = MIN(last_sep - sep, buf_size - 1);
111 strlcpy(buf, sep + 1, len + 1);
112 return buf;
115 #if (CONFIG_CODEC != MAS3507D)
116 /* A helper to determine the enum value for pitch/speed.
118 When there are two choices (i.e. boolean), return 1 if the value is
119 different from normal value and 2 if the value is the same as the
120 normal value. E.g. "%?Sp<%Sp>" would show the pitch only when
121 playing at a modified pitch.
123 When there are more than two choices (i.e. enum), the left half of
124 the choices are to show 0..normal range, and the right half of the
125 choices are to show values over that. The last entry is used when
126 it is set to the normal setting, following the rockbox convention
127 to use the last entry for special values.
129 E.g.
131 2 items: %?Sp<0..99 or 101..infinity|100>
132 3 items: %?Sp<0..99|101..infinity|100>
133 4 items: %?Sp<0..49|50..99|101..infinity|100>
134 5 items: %?Sp<0..49|50..99|101..149|150..infinity|100>
135 6 items: %?Sp<0..33|34..66|67..99|101..133|134..infinity|100>
136 7 items: %?Sp<0..33|34..66|67..99|101..133|134..167|167..infinity|100>
138 static int pitch_speed_enum(int range, int32_t val, int32_t normval)
140 int center;
141 int n;
143 if (range < 3)
144 return (val == normval) + 1;
145 if (val == normval)
146 return range;
147 center = range / 2;
148 n = (center * val) / normval + 1;
149 return (range <= n) ? (range - 1) : n;
151 #endif
154 /* All tokens which only need the info to return a value go in here */
155 const char *get_id3_token(struct wps_token *token, struct mp3entry *id3,
156 char *buf, int buf_size, int limit, int *intval)
158 struct wps_state *state = &wps_state;
159 if (id3)
161 switch (token->type)
163 case WPS_TOKEN_METADATA_ARTIST:
164 return id3->artist;
165 case WPS_TOKEN_METADATA_COMPOSER:
166 return id3->composer;
167 case WPS_TOKEN_METADATA_ALBUM:
168 return id3->album;
169 case WPS_TOKEN_METADATA_ALBUM_ARTIST:
170 return id3->albumartist;
171 case WPS_TOKEN_METADATA_GROUPING:
172 return id3->grouping;
173 case WPS_TOKEN_METADATA_GENRE:
174 return id3->genre_string;
175 case WPS_TOKEN_METADATA_DISC_NUMBER:
176 if (id3->disc_string)
177 return id3->disc_string;
178 if (id3->discnum) {
179 snprintf(buf, buf_size, "%d", id3->discnum);
180 return buf;
182 return NULL;
183 case WPS_TOKEN_METADATA_TRACK_NUMBER:
184 if (id3->track_string)
185 return id3->track_string;
186 if (id3->tracknum) {
187 snprintf(buf, buf_size, "%d", id3->tracknum);
188 return buf;
190 return NULL;
191 case WPS_TOKEN_METADATA_TRACK_TITLE:
192 return id3->title;
193 case WPS_TOKEN_METADATA_VERSION:
194 switch (id3->id3version)
196 case ID3_VER_1_0:
197 return "1";
198 case ID3_VER_1_1:
199 return "1.1";
200 case ID3_VER_2_2:
201 return "2.2";
202 case ID3_VER_2_3:
203 return "2.3";
204 case ID3_VER_2_4:
205 return "2.4";
206 default:
207 break;
209 return NULL;
210 case WPS_TOKEN_METADATA_YEAR:
211 if( id3->year_string )
212 return id3->year_string;
213 if (id3->year) {
214 snprintf(buf, buf_size, "%d", id3->year);
215 return buf;
217 return NULL;
218 case WPS_TOKEN_METADATA_COMMENT:
219 return id3->comment;
220 case WPS_TOKEN_FILE_PATH:
221 return id3->path;
222 case WPS_TOKEN_FILE_BITRATE:
223 if(id3->bitrate)
224 snprintf(buf, buf_size, "%d", id3->bitrate);
225 else
226 return "?";
227 return buf;
228 case WPS_TOKEN_TRACK_TIME_ELAPSED:
229 format_time(buf, buf_size,
230 id3->elapsed + state->ff_rewind_count);
231 return buf;
233 case WPS_TOKEN_TRACK_TIME_REMAINING:
234 format_time(buf, buf_size,
235 id3->length - id3->elapsed -
236 state->ff_rewind_count);
237 return buf;
239 case WPS_TOKEN_TRACK_LENGTH:
240 format_time(buf, buf_size, id3->length);
241 return buf;
243 case WPS_TOKEN_TRACK_ELAPSED_PERCENT:
244 if (id3->length <= 0)
245 return NULL;
247 if (intval)
249 *intval = limit * (id3->elapsed + state->ff_rewind_count)
250 / id3->length + 1;
252 snprintf(buf, buf_size, "%d",
253 100*(id3->elapsed + state->ff_rewind_count) / id3->length);
254 return buf;
257 case WPS_TOKEN_FILE_CODEC:
258 if (intval)
260 if(id3->codectype == AFMT_UNKNOWN)
261 *intval = AFMT_NUM_CODECS;
262 else
263 *intval = id3->codectype;
265 return get_codectype(id3);
267 case WPS_TOKEN_FILE_FREQUENCY:
268 snprintf(buf, buf_size, "%ld", id3->frequency);
269 return buf;
270 case WPS_TOKEN_FILE_FREQUENCY_KHZ:
271 /* ignore remainders < 100, so 22050 Hz becomes just 22k */
272 if ((id3->frequency % 1000) < 100)
273 snprintf(buf, buf_size, "%ld", id3->frequency / 1000);
274 else
275 snprintf(buf, buf_size, "%ld.%d",
276 id3->frequency / 1000,
277 (id3->frequency % 1000) / 100);
278 return buf;
279 case WPS_TOKEN_FILE_NAME:
280 if (get_dir(buf, buf_size, id3->path, 0)) {
281 /* Remove extension */
282 char* sep = strrchr(buf, '.');
283 if (NULL != sep) {
284 *sep = 0;
286 return buf;
288 return NULL;
289 case WPS_TOKEN_FILE_NAME_WITH_EXTENSION:
290 return get_dir(buf, buf_size, id3->path, 0);
291 case WPS_TOKEN_FILE_SIZE:
292 snprintf(buf, buf_size, "%ld", id3->filesize / 1024);
293 return buf;
294 case WPS_TOKEN_FILE_VBR:
295 return (id3->vbr) ? "(avg)" : NULL;
296 case WPS_TOKEN_FILE_DIRECTORY:
297 return get_dir(buf, buf_size, id3->path, token->value.i);
299 #ifdef HAVE_TAGCACHE
300 case WPS_TOKEN_DATABASE_PLAYCOUNT:
301 if (intval)
302 *intval = id3->playcount + 1;
303 snprintf(buf, buf_size, "%ld", id3->playcount);
304 return buf;
305 case WPS_TOKEN_DATABASE_RATING:
306 if (intval)
307 *intval = id3->rating + 1;
308 snprintf(buf, buf_size, "%ld", id3->rating);
309 return buf;
310 case WPS_TOKEN_DATABASE_AUTOSCORE:
311 if (intval)
312 *intval = id3->score + 1;
313 snprintf(buf, buf_size, "%ld", id3->score);
314 return buf;
315 #endif
317 default:
318 return NULL;
321 else /* id3 == NULL, handle the error based on the expected return type */
323 switch (token->type)
325 /* Most tokens expect NULL on error so leave that for the default case,
326 * The ones that expect "0" need to be handled */
327 case WPS_TOKEN_FILE_FREQUENCY:
328 case WPS_TOKEN_FILE_FREQUENCY_KHZ:
329 case WPS_TOKEN_FILE_SIZE:
330 #ifdef HAVE_TAGCACHE
331 case WPS_TOKEN_DATABASE_PLAYCOUNT:
332 case WPS_TOKEN_DATABASE_RATING:
333 case WPS_TOKEN_DATABASE_AUTOSCORE:
334 #endif
335 if (intval)
336 *intval = 0;
337 return "0";
338 default:
339 return NULL;
342 return buf;
345 /* Return the tags value as text. buf should be used as temp storage if needed.
347 intval is used with conditionals/enums: when this function is called,
348 intval should contain the number of options in the conditional/enum.
349 When this function returns, intval is -1 if the tag is non numeric or,
350 if the tag is numeric, *intval is the enum case we want to go to (between 1
351 and the original value of *intval, inclusive).
352 When not treating a conditional/enum, intval should be NULL.
354 const char *get_token_value(struct gui_wps *gwps,
355 struct wps_token *token,
356 char *buf, int buf_size,
357 int *intval)
359 if (!gwps)
360 return NULL;
362 struct wps_data *data = gwps->data;
363 struct wps_state *state = gwps->state;
364 struct mp3entry *id3; /* Think very carefully about using this.
365 maybe get_id3_token() is the better place? */
366 const char *out_text = NULL;
368 if (!data || !state)
369 return NULL;
372 if (token->next)
373 id3 = state->nid3;
374 else
375 id3 = state->id3;
377 #if CONFIG_RTC
378 struct tm* tm = NULL;
380 /* if the token is an RTC one, update the time
381 and do the necessary checks */
382 if (token->type >= WPS_TOKENS_RTC_BEGIN
383 && token->type <= WPS_TOKENS_RTC_END)
385 tm = get_time();
387 if (!valid_time(tm))
388 return NULL;
390 #endif
392 int limit = 1;
393 if (intval)
395 limit = *intval;
396 *intval = -1;
399 out_text = get_id3_token(token, id3, buf, buf_size, limit, intval);
400 if (out_text)
401 return out_text;
403 switch (token->type)
405 case WPS_TOKEN_CHARACTER:
406 if (token->value.c == '\n')
407 return NULL;
408 return &(token->value.c);
410 case WPS_TOKEN_STRING:
411 return (char*)token->value.data;
413 case WPS_TOKEN_TRANSLATEDSTRING:
414 return (char*)P2STR(ID2P(token->value.i));
416 case WPS_TOKEN_PLAYLIST_ENTRIES:
417 snprintf(buf, buf_size, "%d", playlist_amount());
418 return buf;
420 case WPS_TOKEN_PLAYLIST_NAME:
421 return playlist_name(NULL, buf, buf_size);
423 case WPS_TOKEN_PLAYLIST_POSITION:
424 snprintf(buf, buf_size, "%d", playlist_get_display_index());
425 return buf;
427 case WPS_TOKEN_PLAYLIST_SHUFFLE:
428 if ( global_settings.playlist_shuffle )
429 return "s";
430 else
431 return NULL;
432 break;
434 case WPS_TOKEN_VOLUME:
435 snprintf(buf, buf_size, "%d", global_settings.volume);
436 if (intval)
438 if (global_settings.volume == sound_min(SOUND_VOLUME))
440 *intval = 1;
442 else if (global_settings.volume == 0)
444 *intval = limit - 1;
446 else if (global_settings.volume > 0)
448 *intval = limit;
450 else
452 *intval = (limit - 3) * (global_settings.volume
453 - sound_min(SOUND_VOLUME) - 1)
454 / (-1 - sound_min(SOUND_VOLUME)) + 2;
457 return buf;
458 #ifdef HAVE_ALBUMART
459 case WPS_TOKEN_ALBUMART_FOUND:
460 if (data->albumart) {
461 if (playback_current_aa_hid(data->playback_aa_slot) >= 0)
462 return "C";
464 return NULL;
466 case WPS_TOKEN_ALBUMART_DISPLAY:
467 if (!data->albumart)
468 return NULL;
469 if (!data->albumart->draw)
470 data->albumart->draw = true;
471 return NULL;
472 #endif
474 case WPS_TOKEN_BATTERY_PERCENT:
476 int l = battery_level();
478 if (intval)
480 limit = MAX(limit, 2);
481 if (l > -1) {
482 /* First enum is used for "unknown level". */
483 *intval = (limit - 1) * l / 100 + 2;
484 } else {
485 *intval = 1;
489 if (l > -1) {
490 snprintf(buf, buf_size, "%d", l);
491 return buf;
492 } else {
493 return "?";
497 case WPS_TOKEN_BATTERY_VOLTS:
499 unsigned int v = battery_voltage();
500 snprintf(buf, buf_size, "%d.%02d", v / 1000, (v % 1000) / 10);
501 return buf;
504 case WPS_TOKEN_BATTERY_TIME:
506 int t = battery_time();
507 if (t >= 0)
508 snprintf(buf, buf_size, "%dh %dm", t / 60, t % 60);
509 else
510 return "?h ?m";
511 return buf;
514 #if CONFIG_CHARGING
515 case WPS_TOKEN_BATTERY_CHARGER_CONNECTED:
517 if(charger_input_state==CHARGER)
518 return "p";
519 else
520 return NULL;
522 #endif
523 #if CONFIG_CHARGING >= CHARGING_MONITOR
524 case WPS_TOKEN_BATTERY_CHARGING:
526 if (charge_state == CHARGING || charge_state == TOPOFF) {
527 return "c";
528 } else {
529 return NULL;
532 #endif
533 #ifdef HAVE_USB_POWER
534 case WPS_TOKEN_USB_POWERED:
535 if (usb_powered())
536 return "u";
537 return NULL;
538 #endif
539 case WPS_TOKEN_BATTERY_SLEEPTIME:
541 if (get_sleep_timer() == 0)
542 return NULL;
543 else
545 format_time(buf, buf_size, get_sleep_timer() * 1000);
546 return buf;
550 case WPS_TOKEN_PLAYBACK_STATUS:
552 int status = current_playmode();
553 /* music */
554 int mode = 1; /* stop */
555 if (status == STATUS_PLAY)
556 mode = 2; /* play */
557 if (state->is_fading ||
558 (status == STATUS_PAUSE && !status_get_ffmode()))
559 mode = 3; /* pause */
560 else
561 { /* ff / rwd */
562 if (status_get_ffmode() == STATUS_FASTFORWARD)
563 mode = 4;
564 if (status_get_ffmode() == STATUS_FASTBACKWARD)
565 mode = 5;
567 #ifdef HAVE_RECORDING
568 /* recording */
569 if (status == STATUS_RECORD)
570 mode = 6;
571 else if (status == STATUS_RECORD_PAUSE)
572 mode = 7;
573 #endif
574 #if CONFIG_TUNER
575 /* radio */
576 if (status == STATUS_RADIO)
577 mode = 8;
578 else if (status == STATUS_RADIO_PAUSE)
579 mode = 9;
580 #endif
582 if (intval) {
583 *intval = mode;
586 snprintf(buf, buf_size, "%d", mode-1);
587 return buf;
590 case WPS_TOKEN_REPEAT_MODE:
591 if (intval)
592 *intval = global_settings.repeat_mode + 1;
593 snprintf(buf, buf_size, "%d", global_settings.repeat_mode);
594 return buf;
596 case WPS_TOKEN_RTC_PRESENT:
597 #if CONFIG_RTC
598 return "c";
599 #else
600 return NULL;
601 #endif
603 #if CONFIG_RTC
604 case WPS_TOKEN_RTC_12HOUR_CFG:
605 if (intval)
606 *intval = global_settings.timeformat + 1;
607 snprintf(buf, buf_size, "%d", global_settings.timeformat);
608 return buf;
610 case WPS_TOKEN_RTC_DAY_OF_MONTH:
611 /* d: day of month (01..31) */
612 snprintf(buf, buf_size, "%02d", tm->tm_mday);
613 if (intval)
614 *intval = tm->tm_mday - 1;
615 return buf;
617 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
618 /* e: day of month, blank padded ( 1..31) */
619 snprintf(buf, buf_size, "%2d", tm->tm_mday);
620 if (intval)
621 *intval = tm->tm_mday - 1;
622 return buf;
624 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED:
625 /* H: hour (00..23) */
626 snprintf(buf, buf_size, "%02d", tm->tm_hour);
627 if (intval)
628 *intval = tm->tm_hour;
629 return buf;
631 case WPS_TOKEN_RTC_HOUR_24:
632 /* k: hour ( 0..23) */
633 snprintf(buf, buf_size, "%2d", tm->tm_hour);
634 if (intval)
635 *intval = tm->tm_hour;
636 return buf;
638 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED:
639 /* I: hour (01..12) */
640 snprintf(buf, buf_size, "%02d",
641 (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
642 if (intval)
643 *intval = (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12;
644 return buf;
646 case WPS_TOKEN_RTC_HOUR_12:
647 /* l: hour ( 1..12) */
648 snprintf(buf, buf_size, "%2d",
649 (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
650 if (intval)
651 *intval = (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12;
652 return buf;
654 case WPS_TOKEN_RTC_MONTH:
655 /* m: month (01..12) */
656 if (intval)
657 *intval = tm->tm_mon + 1;
658 snprintf(buf, buf_size, "%02d", tm->tm_mon + 1);
659 return buf;
661 case WPS_TOKEN_RTC_MINUTE:
662 /* M: minute (00..59) */
663 snprintf(buf, buf_size, "%02d", tm->tm_min);
664 if (intval)
665 *intval = tm->tm_min;
666 return buf;
668 case WPS_TOKEN_RTC_SECOND:
669 /* S: second (00..59) */
670 snprintf(buf, buf_size, "%02d", tm->tm_sec);
671 if (intval)
672 *intval = tm->tm_sec;
673 return buf;
675 case WPS_TOKEN_RTC_YEAR_2_DIGITS:
676 /* y: last two digits of year (00..99) */
677 snprintf(buf, buf_size, "%02d", tm->tm_year % 100);
678 if (intval)
679 *intval = tm->tm_year % 100;
680 return buf;
682 case WPS_TOKEN_RTC_YEAR_4_DIGITS:
683 /* Y: year (1970...) */
684 snprintf(buf, buf_size, "%04d", tm->tm_year + 1900);
685 if (intval)
686 *intval = tm->tm_year + 1900;
687 return buf;
689 case WPS_TOKEN_RTC_AM_PM_UPPER:
690 /* p: upper case AM or PM indicator */
691 if (intval)
692 *intval = tm->tm_hour/12 == 0 ? 0 : 1;
693 return tm->tm_hour/12 == 0 ? "AM" : "PM";
695 case WPS_TOKEN_RTC_AM_PM_LOWER:
696 /* P: lower case am or pm indicator */
697 if (intval)
698 *intval = tm->tm_hour/12 == 0 ? 0 : 1;
699 return tm->tm_hour/12 == 0 ? "am" : "pm";
701 case WPS_TOKEN_RTC_WEEKDAY_NAME:
702 /* a: abbreviated weekday name (Sun..Sat) */
703 return str(LANG_WEEKDAY_SUNDAY + tm->tm_wday);
705 case WPS_TOKEN_RTC_MONTH_NAME:
706 /* b: abbreviated month name (Jan..Dec) */
707 return str(LANG_MONTH_JANUARY + tm->tm_mon);
709 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
710 /* u: day of week (1..7); 1 is Monday */
711 if (intval)
712 *intval = (tm->tm_wday == 0) ? 7 : tm->tm_wday;
713 snprintf(buf, buf_size, "%1d", tm->tm_wday + 1);
714 return buf;
716 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
717 /* w: day of week (0..6); 0 is Sunday */
718 if (intval)
719 *intval = tm->tm_wday + 1;
720 snprintf(buf, buf_size, "%1d", tm->tm_wday);
721 return buf;
722 #else
723 case WPS_TOKEN_RTC_DAY_OF_MONTH:
724 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
725 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED:
726 case WPS_TOKEN_RTC_HOUR_24:
727 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED:
728 case WPS_TOKEN_RTC_HOUR_12:
729 case WPS_TOKEN_RTC_MONTH:
730 case WPS_TOKEN_RTC_MINUTE:
731 case WPS_TOKEN_RTC_SECOND:
732 case WPS_TOKEN_RTC_AM_PM_UPPER:
733 case WPS_TOKEN_RTC_AM_PM_LOWER:
734 case WPS_TOKEN_RTC_YEAR_2_DIGITS:
735 return "--";
736 case WPS_TOKEN_RTC_YEAR_4_DIGITS:
737 return "----";
738 case WPS_TOKEN_RTC_WEEKDAY_NAME:
739 case WPS_TOKEN_RTC_MONTH_NAME:
740 return "---";
741 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
742 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
743 return "-";
744 #endif
746 #ifdef HAVE_LCD_CHARCELLS
747 case WPS_TOKEN_PROGRESSBAR:
749 char *end = utf8encode(data->wps_progress_pat[0], buf);
750 *end = '\0';
751 return buf;
754 case WPS_TOKEN_PLAYER_PROGRESSBAR:
755 if(is_new_player())
757 /* we need 11 characters (full line) for
758 progress-bar */
759 strlcpy(buf, " ", buf_size);
761 else
763 /* Tell the user if we have an OldPlayer */
764 strlcpy(buf, " <Old LCD> ", buf_size);
766 return buf;
767 #endif
771 #if (CONFIG_CODEC == SWCODEC)
772 case WPS_TOKEN_CROSSFADE:
773 #ifdef HAVE_CROSSFADE
774 if (intval)
775 *intval = global_settings.crossfade + 1;
776 snprintf(buf, buf_size, "%d", global_settings.crossfade);
777 #else
778 snprintf(buf, buf_size, "%d", 0);
779 #endif
780 return buf;
782 case WPS_TOKEN_REPLAYGAIN:
784 int val;
786 if (global_settings.replaygain_type == REPLAYGAIN_OFF)
787 val = 1; /* off */
788 else
790 int type;
791 if (LIKELY(id3))
792 type = get_replaygain_mode(id3->track_gain_string != NULL,
793 id3->album_gain_string != NULL);
794 else
795 type = -1;
797 if (type < 0)
798 val = 6; /* no tag */
799 else
800 val = type + 2;
802 if (global_settings.replaygain_type == REPLAYGAIN_SHUFFLE)
803 val += 2;
806 if (intval)
807 *intval = val;
809 switch (val)
811 case 1:
812 case 6:
813 return "+0.00 dB";
814 break;
815 /* due to above, coming here with !id3 shouldn't be possible */
816 case 2:
817 case 4:
818 strlcpy(buf, id3->track_gain_string, buf_size);
819 break;
820 case 3:
821 case 5:
822 strlcpy(buf, id3->album_gain_string, buf_size);
823 break;
825 return buf;
827 #endif /* (CONFIG_CODEC == SWCODEC) */
829 #if (CONFIG_CODEC != MAS3507D)
830 case WPS_TOKEN_SOUND_PITCH:
832 int32_t pitch = sound_get_pitch();
833 snprintf(buf, buf_size, "%ld.%ld",
834 pitch / PITCH_SPEED_PRECISION,
835 (pitch % PITCH_SPEED_PRECISION) / (PITCH_SPEED_PRECISION / 10));
837 if (intval)
838 *intval = pitch_speed_enum(limit, pitch,
839 PITCH_SPEED_PRECISION * 100);
840 return buf;
842 #endif
844 #if CONFIG_CODEC == SWCODEC
845 case WPS_TOKEN_SOUND_SPEED:
847 int32_t pitch = sound_get_pitch();
848 int32_t speed;
849 if (dsp_timestretch_available())
850 speed = GET_SPEED(pitch, dsp_get_timestretch());
851 else
852 speed = pitch;
853 snprintf(buf, buf_size, "%ld.%ld",
854 speed / PITCH_SPEED_PRECISION,
855 (speed % PITCH_SPEED_PRECISION) / (PITCH_SPEED_PRECISION / 10));
856 if (intval)
857 *intval = pitch_speed_enum(limit, speed,
858 PITCH_SPEED_PRECISION * 100);
859 return buf;
861 #endif
863 case WPS_TOKEN_MAIN_HOLD:
864 #ifdef HAS_BUTTON_HOLD
865 if (button_hold())
866 #else
867 if (is_keys_locked())
868 #endif /*hold switch or softlock*/
869 return "h";
870 else
871 return NULL;
873 #ifdef HAS_REMOTE_BUTTON_HOLD
874 case WPS_TOKEN_REMOTE_HOLD:
875 if (remote_button_hold())
876 return "r";
877 else
878 return NULL;
879 #endif
881 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
882 case WPS_TOKEN_VLED_HDD:
883 if(led_read(HZ/2))
884 return "h";
885 else
886 return NULL;
887 #endif
888 case WPS_TOKEN_BUTTON_VOLUME:
889 if (global_status.last_volume_change &&
890 TIME_BEFORE(current_tick, global_status.last_volume_change +
891 token->value.i * TIMEOUT_UNIT))
892 return "v";
893 return NULL;
894 case WPS_TOKEN_LASTTOUCH:
895 #ifdef HAVE_TOUCHSCREEN
896 if (TIME_BEFORE(current_tick, token->value.i * TIMEOUT_UNIT +
897 touchscreen_last_touch()))
898 return "t";
899 #endif
900 return NULL;
902 case WPS_TOKEN_SETTING:
904 if (intval)
906 /* Handle contionals */
907 const struct settings_list *s = settings+token->value.i;
908 switch (s->flags&F_T_MASK)
910 case F_T_INT:
911 case F_T_UINT:
912 if (s->flags&F_RGB)
913 /* %?St|name|<#000000|#000001|...|#FFFFFF> */
914 /* shouldn't overflow since colors are stored
915 * on 16 bits ...
916 * but this is pretty useless anyway */
917 *intval = *(int*)s->setting + 1;
918 else if (s->cfg_vals == NULL)
919 /* %?St|name|<1st choice|2nd choice|...> */
920 *intval = (*(int*)s->setting-s->int_setting->min)
921 /s->int_setting->step + 1;
922 else
923 /* %?St|name|<1st choice|2nd choice|...> */
924 /* Not sure about this one. cfg_name/vals are
925 * indexed from 0 right? */
926 *intval = *(int*)s->setting + 1;
927 break;
928 case F_T_BOOL:
929 /* %?St|name|<if true|if false> */
930 *intval = *(bool*)s->setting?1:2;
931 break;
932 case F_T_CHARPTR:
933 /* %?St|name|<if non empty string|if empty>
934 * The string's emptyness discards the setting's
935 * prefix and suffix */
936 *intval = ((char*)s->setting)[0]?1:2;
937 break;
938 default:
939 /* This shouldn't happen ... but you never know */
940 *intval = -1;
941 break;
944 cfg_to_string(token->value.i,buf,buf_size);
945 return buf;
947 /* Recording tokens */
948 case WPS_TOKEN_HAVE_RECORDING:
949 #ifdef HAVE_RECORDING
950 return "r";
951 #else
952 return NULL;
953 #endif
955 #ifdef HAVE_RECORDING
956 case WPS_TOKEN_REC_FREQ: /* order from REC_FREQ_CFG_VAL_LIST */
958 #if CONFIG_CODEC == SWCODEC
959 unsigned long samprk;
960 int rec_freq = global_settings.rec_frequency;
962 #ifdef SIMULATOR
963 samprk = 44100;
964 #else
965 #if defined(HAVE_SPDIF_REC)
966 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
968 /* Use rate in use, not current measured rate if it changed */
969 samprk = pcm_rec_sample_rate();
970 rec_freq = 0;
971 while (rec_freq < SAMPR_NUM_FREQ &&
972 audio_master_sampr_list[rec_freq] != samprk)
974 rec_freq++;
977 else
978 #endif
979 samprk = rec_freq_sampr[rec_freq];
980 #endif /* SIMULATOR */
981 if (intval)
983 switch (rec_freq)
985 REC_HAVE_96_(case REC_FREQ_96:
986 *intval = 1;
987 break;)
988 REC_HAVE_88_(case REC_FREQ_88:
989 *intval = 2;
990 break;)
991 REC_HAVE_64_(case REC_FREQ_64:
992 *intval = 3;
993 break;)
994 REC_HAVE_48_(case REC_FREQ_48:
995 *intval = 4;
996 break;)
997 REC_HAVE_44_(case REC_FREQ_44:
998 *intval = 5;
999 break;)
1000 REC_HAVE_32_(case REC_FREQ_32:
1001 *intval = 6;
1002 break;)
1003 REC_HAVE_24_(case REC_FREQ_24:
1004 *intval = 7;
1005 break;)
1006 REC_HAVE_22_(case REC_FREQ_22:
1007 *intval = 8;
1008 break;)
1009 REC_HAVE_16_(case REC_FREQ_16:
1010 *intval = 9;
1011 break;)
1012 REC_HAVE_12_(case REC_FREQ_12:
1013 *intval = 10;
1014 break;)
1015 REC_HAVE_11_(case REC_FREQ_11:
1016 *intval = 11;
1017 break;)
1018 REC_HAVE_8_(case REC_FREQ_8:
1019 *intval = 12;
1020 break;)
1023 snprintf(buf, buf_size, "%d.%1d", samprk/1000,samprk%1000);
1024 #else /* HWCODEC */
1026 static const char * const freq_strings[] =
1027 {"--", "44", "48", "32", "22", "24", "16"};
1028 int freq = 1 + global_settings.rec_frequency;
1029 #ifdef HAVE_SPDIF_REC
1030 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
1032 /* Can't measure S/PDIF sample rate on Archos/Sim yet */
1033 freq = 0;
1035 #endif /* HAVE_SPDIF_IN */
1036 if (intval)
1037 *intval = freq+1; /* so the token gets a value 1<=x<=7 */
1038 snprintf(buf, buf_size, "%d\n",
1039 freq_strings[global_settings.rec_frequency]);
1040 #endif
1041 return buf;
1043 #if CONFIG_CODEC == SWCODEC
1044 case WPS_TOKEN_REC_ENCODER:
1046 int rec_format = global_settings.rec_format+1; /* WAV, AIFF, WV, MPEG */
1047 if (intval)
1048 *intval = rec_format;
1049 switch (rec_format)
1051 case REC_FORMAT_PCM_WAV:
1052 return "wav";
1053 case REC_FORMAT_AIFF:
1054 return "aiff";
1055 case REC_FORMAT_WAVPACK:
1056 return "wv";
1057 case REC_FORMAT_MPA_L3:
1058 return "MP3";
1059 default:
1060 return NULL;
1062 break;
1064 #endif
1065 case WPS_TOKEN_REC_BITRATE:
1066 #if CONFIG_CODEC == SWCODEC
1067 if (global_settings.rec_format == REC_FORMAT_MPA_L3)
1069 if (intval)
1071 #if 0 /* FIXME: I dont know if this is needed? */
1072 switch (1<<global_settings.mp3_enc_config.bitrate)
1074 case MP3_BITR_CAP_8:
1075 *intval = 1;
1076 break;
1077 case MP3_BITR_CAP_16:
1078 *intval = 2;
1079 break;
1080 case MP3_BITR_CAP_24:
1081 *intval = 3;
1082 break;
1083 case MP3_BITR_CAP_32:
1084 *intval = 4;
1085 break;
1086 case MP3_BITR_CAP_40:
1087 *intval = 5;
1088 break;
1089 case MP3_BITR_CAP_48:
1090 *intval = 6;
1091 break;
1092 case MP3_BITR_CAP_56:
1093 *intval = 7;
1094 break;
1095 case MP3_BITR_CAP_64:
1096 *intval = 8;
1097 break;
1098 case MP3_BITR_CAP_80:
1099 *intval = 9;
1100 break;
1101 case MP3_BITR_CAP_96:
1102 *intval = 10;
1103 break;
1104 case MP3_BITR_CAP_112:
1105 *intval = 11;
1106 break;
1107 case MP3_BITR_CAP_128:
1108 *intval = 12;
1109 break;
1110 case MP3_BITR_CAP_144:
1111 *intval = 13;
1112 break;
1113 case MP3_BITR_CAP_160:
1114 *intval = 14;
1115 break;
1116 case MP3_BITR_CAP_192:
1117 *intval = 15;
1118 break;
1120 #endif
1121 *intval = global_settings.mp3_enc_config.bitrate+1;
1123 snprintf(buf, buf_size, "%d", global_settings.mp3_enc_config.bitrate+1);
1124 return buf;
1126 else
1127 return NULL; /* Fixme later */
1128 #else /* CONFIG_CODEC == HWCODEC */
1129 if (intval)
1130 *intval = global_settings.rec_quality+1;
1131 snprintf(buf, buf_size, "%d", global_settings.rec_quality);
1132 return buf;
1133 #endif
1134 case WPS_TOKEN_REC_MONO:
1135 if (!global_settings.rec_channels)
1136 return "m";
1137 return NULL;
1139 #endif /* HAVE_RECORDING */
1140 case WPS_TOKEN_CURRENT_SCREEN:
1142 int curr_screen = current_screen();
1144 #ifdef HAVE_RECORDING
1145 /* override current_screen() for recording screen since it may
1146 * be entered from the radio screen */
1147 if (in_recording_screen())
1148 curr_screen = GO_TO_RECSCREEN;
1149 #endif
1151 switch (curr_screen)
1153 case GO_TO_WPS:
1154 curr_screen = 2;
1155 break;
1156 #ifdef HAVE_RECORDING
1157 case GO_TO_RECSCREEN:
1158 curr_screen = 3;
1159 break;
1160 #endif
1161 #if CONFIG_TUNER
1162 case GO_TO_FM:
1163 curr_screen = 4;
1164 break;
1165 #endif
1166 default: /* lists */
1167 curr_screen = 1;
1168 break;
1170 if (intval)
1173 *intval = curr_screen;
1175 snprintf(buf, buf_size, "%d", curr_screen);
1176 return buf;
1179 case WPS_TOKEN_LANG_IS_RTL:
1180 return lang_is_rtl() ? "r" : NULL;
1182 default:
1183 return NULL;