Move c/h files implementing/defining standard library stuff into a new libc directory...
[kugel-rb.git] / apps / gui / skin_engine / skin_tokens.c
blob6e5a2eae857da2eb488c2a8a43b607d88ceccd84
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002-2007 Björn Stenberg
11 * Copyright (C) 2007-2008 Nicolas Pennequin
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
22 #include "font.h"
23 #include <stdio.h>
24 #include "string-extra.h"
25 #include <stdlib.h>
26 #include "action.h"
27 #include "system.h"
28 #include "settings.h"
29 #include "settings_list.h"
30 #include "rbunicode.h"
31 #include "timefuncs.h"
32 #include "status.h"
33 #include "power.h"
34 #include "powermgmt.h"
35 #include "sound.h"
36 #include "debug.h"
37 #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 const char* get_codectype(const struct mp3entry* id3)
69 if (id3 && id3->codectype < AFMT_NUM_CODECS) {
70 return 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 unsigned long length = id3->length;
162 unsigned long elapsed = id3->elapsed + state->ff_rewind_count;
163 switch (token->type)
165 case WPS_TOKEN_METADATA_ARTIST:
166 return id3->artist;
167 case WPS_TOKEN_METADATA_COMPOSER:
168 return id3->composer;
169 case WPS_TOKEN_METADATA_ALBUM:
170 return id3->album;
171 case WPS_TOKEN_METADATA_ALBUM_ARTIST:
172 return id3->albumartist;
173 case WPS_TOKEN_METADATA_GROUPING:
174 return id3->grouping;
175 case WPS_TOKEN_METADATA_GENRE:
176 return id3->genre_string;
177 case WPS_TOKEN_METADATA_DISC_NUMBER:
178 if (id3->disc_string)
179 return id3->disc_string;
180 if (id3->discnum) {
181 snprintf(buf, buf_size, "%d", id3->discnum);
182 return buf;
184 return NULL;
185 case WPS_TOKEN_METADATA_TRACK_NUMBER:
186 if (id3->track_string)
187 return id3->track_string;
188 if (id3->tracknum) {
189 snprintf(buf, buf_size, "%d", id3->tracknum);
190 return buf;
192 return NULL;
193 case WPS_TOKEN_METADATA_TRACK_TITLE:
194 return id3->title;
195 case WPS_TOKEN_METADATA_VERSION:
196 switch (id3->id3version)
198 case ID3_VER_1_0:
199 return "1";
200 case ID3_VER_1_1:
201 return "1.1";
202 case ID3_VER_2_2:
203 return "2.2";
204 case ID3_VER_2_3:
205 return "2.3";
206 case ID3_VER_2_4:
207 return "2.4";
208 default:
209 break;
211 return NULL;
212 case WPS_TOKEN_METADATA_YEAR:
213 if( id3->year_string )
214 return id3->year_string;
215 if (id3->year) {
216 snprintf(buf, buf_size, "%d", id3->year);
217 return buf;
219 return NULL;
220 case WPS_TOKEN_METADATA_COMMENT:
221 return id3->comment;
222 case WPS_TOKEN_FILE_PATH:
223 return id3->path;
224 case WPS_TOKEN_FILE_BITRATE:
225 if(id3->bitrate)
226 snprintf(buf, buf_size, "%d", id3->bitrate);
227 else
228 return "?";
229 return buf;
230 case WPS_TOKEN_TRACK_TIME_ELAPSED:
231 format_time(buf, buf_size, elapsed);
232 return buf;
234 case WPS_TOKEN_TRACK_TIME_REMAINING:
235 format_time(buf, buf_size, length - elapsed);
236 return buf;
238 case WPS_TOKEN_TRACK_LENGTH:
239 format_time(buf, buf_size, length);
240 return buf;
242 case WPS_TOKEN_TRACK_ELAPSED_PERCENT:
243 if (length <= 0)
244 return NULL;
246 if (intval)
248 *intval = limit * elapsed / length + 1;
250 snprintf(buf, buf_size, "%lu", 100 * elapsed / length);
251 return buf;
254 case WPS_TOKEN_FILE_CODEC:
255 if (intval)
257 if(id3->codectype == AFMT_UNKNOWN)
258 *intval = AFMT_NUM_CODECS;
259 else
260 *intval = id3->codectype;
262 return get_codectype(id3);
264 case WPS_TOKEN_FILE_FREQUENCY:
265 snprintf(buf, buf_size, "%ld", id3->frequency);
266 return buf;
267 case WPS_TOKEN_FILE_FREQUENCY_KHZ:
268 /* ignore remainders < 100, so 22050 Hz becomes just 22k */
269 if ((id3->frequency % 1000) < 100)
270 snprintf(buf, buf_size, "%ld", id3->frequency / 1000);
271 else
272 snprintf(buf, buf_size, "%ld.%lu",
273 id3->frequency / 1000,
274 (id3->frequency % 1000) / 100);
275 return buf;
276 case WPS_TOKEN_FILE_NAME:
277 if (get_dir(buf, buf_size, id3->path, 0)) {
278 /* Remove extension */
279 char* sep = strrchr(buf, '.');
280 if (NULL != sep) {
281 *sep = 0;
283 return buf;
285 return NULL;
286 case WPS_TOKEN_FILE_NAME_WITH_EXTENSION:
287 return get_dir(buf, buf_size, id3->path, 0);
288 case WPS_TOKEN_FILE_SIZE:
289 snprintf(buf, buf_size, "%ld", id3->filesize / 1024);
290 return buf;
291 case WPS_TOKEN_FILE_VBR:
292 return (id3->vbr) ? "(avg)" : NULL;
293 case WPS_TOKEN_FILE_DIRECTORY:
294 return get_dir(buf, buf_size, id3->path, token->value.i);
296 #ifdef HAVE_TAGCACHE
297 case WPS_TOKEN_DATABASE_PLAYCOUNT:
298 if (intval)
299 *intval = id3->playcount + 1;
300 snprintf(buf, buf_size, "%ld", id3->playcount);
301 return buf;
302 case WPS_TOKEN_DATABASE_RATING:
303 if (intval)
304 *intval = id3->rating + 1;
305 snprintf(buf, buf_size, "%d", id3->rating);
306 return buf;
307 case WPS_TOKEN_DATABASE_AUTOSCORE:
308 if (intval)
309 *intval = id3->score + 1;
310 snprintf(buf, buf_size, "%d", id3->score);
311 return buf;
312 #endif
314 default:
315 return NULL;
318 else /* id3 == NULL, handle the error based on the expected return type */
320 switch (token->type)
322 /* Most tokens expect NULL on error so leave that for the default case,
323 * The ones that expect "0" need to be handled */
324 case WPS_TOKEN_FILE_FREQUENCY:
325 case WPS_TOKEN_FILE_FREQUENCY_KHZ:
326 case WPS_TOKEN_FILE_SIZE:
327 #ifdef HAVE_TAGCACHE
328 case WPS_TOKEN_DATABASE_PLAYCOUNT:
329 case WPS_TOKEN_DATABASE_RATING:
330 case WPS_TOKEN_DATABASE_AUTOSCORE:
331 #endif
332 if (intval)
333 *intval = 0;
334 return "0";
335 default:
336 return NULL;
339 return buf;
342 /* Return the tags value as text. buf should be used as temp storage if needed.
344 intval is used with conditionals/enums: when this function is called,
345 intval should contain the number of options in the conditional/enum.
346 When this function returns, intval is -1 if the tag is non numeric or,
347 if the tag is numeric, *intval is the enum case we want to go to (between 1
348 and the original value of *intval, inclusive).
349 When not treating a conditional/enum, intval should be NULL.
351 const char *get_token_value(struct gui_wps *gwps,
352 struct wps_token *token,
353 char *buf, int buf_size,
354 int *intval)
356 if (!gwps)
357 return NULL;
359 struct wps_data *data = gwps->data;
360 struct wps_state *state = gwps->state;
361 struct mp3entry *id3; /* Think very carefully about using this.
362 maybe get_id3_token() is the better place? */
363 const char *out_text = NULL;
365 if (!data || !state)
366 return NULL;
369 if (token->next)
370 id3 = state->nid3;
371 else
372 id3 = state->id3;
374 #if CONFIG_RTC
375 struct tm* tm = NULL;
377 /* if the token is an RTC one, update the time
378 and do the necessary checks */
379 if (token->type >= WPS_TOKENS_RTC_BEGIN
380 && token->type <= WPS_TOKENS_RTC_END)
382 tm = get_time();
384 if (!valid_time(tm))
385 return NULL;
387 #endif
389 int limit = 1;
390 if (intval)
392 limit = *intval;
393 *intval = -1;
396 out_text = get_id3_token(token, id3, buf, buf_size, limit, intval);
397 if (out_text)
398 return out_text;
400 switch (token->type)
402 case WPS_TOKEN_CHARACTER:
403 if (token->value.c == '\n')
404 return NULL;
405 return &(token->value.c);
407 case WPS_TOKEN_STRING:
408 return (char*)token->value.data;
410 case WPS_TOKEN_TRANSLATEDSTRING:
411 return (char*)P2STR(ID2P(token->value.i));
413 case WPS_TOKEN_PLAYLIST_ENTRIES:
414 snprintf(buf, buf_size, "%d", playlist_amount());
415 return buf;
417 case WPS_TOKEN_LIST_TITLE_TEXT:
418 return (char*)token->value.data;
419 case WPS_TOKEN_LIST_TITLE_ICON:
420 if (intval)
421 *intval = token->value.i;
422 snprintf(buf, buf_size, "%d", token->value.i);
423 return buf;
425 case WPS_TOKEN_PLAYLIST_NAME:
426 return playlist_name(NULL, buf, buf_size);
428 case WPS_TOKEN_PLAYLIST_POSITION:
429 snprintf(buf, buf_size, "%d", playlist_get_display_index());
430 return buf;
432 case WPS_TOKEN_PLAYLIST_SHUFFLE:
433 if ( global_settings.playlist_shuffle )
434 return "s";
435 else
436 return NULL;
437 break;
439 case WPS_TOKEN_VOLUME:
440 snprintf(buf, buf_size, "%d", global_settings.volume);
441 if (intval)
443 int minvol = sound_min(SOUND_VOLUME);
444 if (global_settings.volume == minvol)
446 *intval = 1;
448 else if (global_settings.volume == 0)
450 *intval = limit - 1;
452 else if (global_settings.volume > 0)
454 *intval = limit;
456 else
458 *intval = (limit-3) * (global_settings.volume - minvol - 1)
459 / (-1 - minvol) + 2;
462 return buf;
463 #ifdef HAVE_ALBUMART
464 case WPS_TOKEN_ALBUMART_FOUND:
465 if (data->albumart) {
466 if (playback_current_aa_hid(data->playback_aa_slot) >= 0)
467 return "C";
469 return NULL;
471 case WPS_TOKEN_ALBUMART_DISPLAY:
472 if (!data->albumart)
473 return NULL;
474 if (!data->albumart->draw)
475 data->albumart->draw = true;
476 return NULL;
477 #endif
479 case WPS_TOKEN_BATTERY_PERCENT:
481 int l = battery_level();
483 if (intval)
485 limit = MAX(limit, 2);
486 if (l > -1) {
487 /* First enum is used for "unknown level". */
488 *intval = (limit - 1) * l / 100 + 2;
489 } else {
490 *intval = 1;
494 if (l > -1) {
495 snprintf(buf, buf_size, "%d", l);
496 return buf;
497 } else {
498 return "?";
502 case WPS_TOKEN_BATTERY_VOLTS:
504 unsigned int v = battery_voltage();
505 snprintf(buf, buf_size, "%d.%02d", v / 1000, (v % 1000) / 10);
506 return buf;
509 case WPS_TOKEN_BATTERY_TIME:
511 int t = battery_time();
512 if (t >= 0)
513 snprintf(buf, buf_size, "%dh %dm", t / 60, t % 60);
514 else
515 return "?h ?m";
516 return buf;
519 #if CONFIG_CHARGING
520 case WPS_TOKEN_BATTERY_CHARGER_CONNECTED:
522 if(charger_input_state==CHARGER)
523 return "p";
524 else
525 return NULL;
527 #endif
528 #if CONFIG_CHARGING >= CHARGING_MONITOR
529 case WPS_TOKEN_BATTERY_CHARGING:
531 if (charge_state == CHARGING || charge_state == TOPOFF) {
532 return "c";
533 } else {
534 return NULL;
537 #endif
538 #ifdef HAVE_USB_POWER
539 case WPS_TOKEN_USB_POWERED:
540 if (usb_powered())
541 return "u";
542 return NULL;
543 #endif
544 case WPS_TOKEN_BATTERY_SLEEPTIME:
546 if (get_sleep_timer() == 0)
547 return NULL;
548 else
550 format_time(buf, buf_size, get_sleep_timer() * 1000);
551 return buf;
555 case WPS_TOKEN_PLAYBACK_STATUS:
557 int status = current_playmode();
558 /* music */
559 int mode = 1; /* stop */
560 if (status == STATUS_PLAY)
561 mode = 2; /* play */
562 if (state->is_fading ||
563 (status == STATUS_PAUSE && !status_get_ffmode()))
564 mode = 3; /* pause */
565 else
566 { /* ff / rwd */
567 if (status_get_ffmode() == STATUS_FASTFORWARD)
568 mode = 4;
569 if (status_get_ffmode() == STATUS_FASTBACKWARD)
570 mode = 5;
572 #ifdef HAVE_RECORDING
573 /* recording */
574 if (status == STATUS_RECORD)
575 mode = 6;
576 else if (status == STATUS_RECORD_PAUSE)
577 mode = 7;
578 #endif
579 #if CONFIG_TUNER
580 /* radio */
581 if (status == STATUS_RADIO)
582 mode = 8;
583 else if (status == STATUS_RADIO_PAUSE)
584 mode = 9;
585 #endif
587 if (intval) {
588 *intval = mode;
591 snprintf(buf, buf_size, "%d", mode-1);
592 return buf;
595 case WPS_TOKEN_REPEAT_MODE:
596 if (intval)
597 *intval = global_settings.repeat_mode + 1;
598 snprintf(buf, buf_size, "%d", global_settings.repeat_mode);
599 return buf;
601 case WPS_TOKEN_RTC_PRESENT:
602 #if CONFIG_RTC
603 return "c";
604 #else
605 return NULL;
606 #endif
608 #if CONFIG_RTC
609 case WPS_TOKEN_RTC_12HOUR_CFG:
610 if (intval)
611 *intval = global_settings.timeformat + 1;
612 snprintf(buf, buf_size, "%d", global_settings.timeformat);
613 return buf;
615 case WPS_TOKEN_RTC_DAY_OF_MONTH:
616 /* d: day of month (01..31) */
617 snprintf(buf, buf_size, "%02d", tm->tm_mday);
618 if (intval)
619 *intval = tm->tm_mday - 1;
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 if (intval)
626 *intval = tm->tm_mday - 1;
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 if (intval)
633 *intval = tm->tm_hour;
634 return buf;
636 case WPS_TOKEN_RTC_HOUR_24:
637 /* k: hour ( 0..23) */
638 snprintf(buf, buf_size, "%2d", tm->tm_hour);
639 if (intval)
640 *intval = tm->tm_hour;
641 return buf;
643 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED:
644 /* I: hour (01..12) */
645 snprintf(buf, buf_size, "%02d",
646 (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
647 if (intval)
648 *intval = (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12;
649 return buf;
651 case WPS_TOKEN_RTC_HOUR_12:
652 /* l: hour ( 1..12) */
653 snprintf(buf, buf_size, "%2d",
654 (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
655 if (intval)
656 *intval = (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12;
657 return buf;
659 case WPS_TOKEN_RTC_MONTH:
660 /* m: month (01..12) */
661 if (intval)
662 *intval = tm->tm_mon + 1;
663 snprintf(buf, buf_size, "%02d", tm->tm_mon + 1);
664 return buf;
666 case WPS_TOKEN_RTC_MINUTE:
667 /* M: minute (00..59) */
668 snprintf(buf, buf_size, "%02d", tm->tm_min);
669 if (intval)
670 *intval = tm->tm_min;
671 return buf;
673 case WPS_TOKEN_RTC_SECOND:
674 /* S: second (00..59) */
675 snprintf(buf, buf_size, "%02d", tm->tm_sec);
676 if (intval)
677 *intval = tm->tm_sec;
678 return buf;
680 case WPS_TOKEN_RTC_YEAR_2_DIGITS:
681 /* y: last two digits of year (00..99) */
682 snprintf(buf, buf_size, "%02d", tm->tm_year % 100);
683 if (intval)
684 *intval = tm->tm_year % 100;
685 return buf;
687 case WPS_TOKEN_RTC_YEAR_4_DIGITS:
688 /* Y: year (1970...) */
689 snprintf(buf, buf_size, "%04d", tm->tm_year + 1900);
690 if (intval)
691 *intval = tm->tm_year + 1900;
692 return buf;
694 case WPS_TOKEN_RTC_AM_PM_UPPER:
695 /* p: upper case AM or PM indicator */
696 if (intval)
697 *intval = tm->tm_hour/12 == 0 ? 0 : 1;
698 return tm->tm_hour/12 == 0 ? "AM" : "PM";
700 case WPS_TOKEN_RTC_AM_PM_LOWER:
701 /* P: lower case am or pm indicator */
702 if (intval)
703 *intval = tm->tm_hour/12 == 0 ? 0 : 1;
704 return tm->tm_hour/12 == 0 ? "am" : "pm";
706 case WPS_TOKEN_RTC_WEEKDAY_NAME:
707 /* a: abbreviated weekday name (Sun..Sat) */
708 return str(LANG_WEEKDAY_SUNDAY + tm->tm_wday);
710 case WPS_TOKEN_RTC_MONTH_NAME:
711 /* b: abbreviated month name (Jan..Dec) */
712 return str(LANG_MONTH_JANUARY + tm->tm_mon);
714 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
715 /* u: day of week (1..7); 1 is Monday */
716 if (intval)
717 *intval = (tm->tm_wday == 0) ? 7 : tm->tm_wday;
718 snprintf(buf, buf_size, "%1d", tm->tm_wday + 1);
719 return buf;
721 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
722 /* w: day of week (0..6); 0 is Sunday */
723 if (intval)
724 *intval = tm->tm_wday + 1;
725 snprintf(buf, buf_size, "%1d", tm->tm_wday);
726 return buf;
727 #else
728 case WPS_TOKEN_RTC_DAY_OF_MONTH:
729 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
730 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED:
731 case WPS_TOKEN_RTC_HOUR_24:
732 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED:
733 case WPS_TOKEN_RTC_HOUR_12:
734 case WPS_TOKEN_RTC_MONTH:
735 case WPS_TOKEN_RTC_MINUTE:
736 case WPS_TOKEN_RTC_SECOND:
737 case WPS_TOKEN_RTC_AM_PM_UPPER:
738 case WPS_TOKEN_RTC_AM_PM_LOWER:
739 case WPS_TOKEN_RTC_YEAR_2_DIGITS:
740 return "--";
741 case WPS_TOKEN_RTC_YEAR_4_DIGITS:
742 return "----";
743 case WPS_TOKEN_RTC_WEEKDAY_NAME:
744 case WPS_TOKEN_RTC_MONTH_NAME:
745 return "---";
746 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
747 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
748 return "-";
749 #endif
751 #ifdef HAVE_LCD_CHARCELLS
752 case WPS_TOKEN_PROGRESSBAR:
754 char *end = utf8encode(data->wps_progress_pat[0], buf);
755 *end = '\0';
756 return buf;
759 case WPS_TOKEN_PLAYER_PROGRESSBAR:
760 if(is_new_player())
762 /* we need 11 characters (full line) for
763 progress-bar */
764 strlcpy(buf, " ", buf_size);
766 else
768 /* Tell the user if we have an OldPlayer */
769 strlcpy(buf, " <Old LCD> ", buf_size);
771 return buf;
772 #endif
776 #if (CONFIG_CODEC == SWCODEC)
777 case WPS_TOKEN_CROSSFADE:
778 #ifdef HAVE_CROSSFADE
779 if (intval)
780 *intval = global_settings.crossfade + 1;
781 snprintf(buf, buf_size, "%d", global_settings.crossfade);
782 #else
783 snprintf(buf, buf_size, "%d", 0);
784 #endif
785 return buf;
787 case WPS_TOKEN_REPLAYGAIN:
789 int val;
791 if (global_settings.replaygain_type == REPLAYGAIN_OFF)
792 val = 1; /* off */
793 else
795 int type;
796 if (LIKELY(id3))
797 type = get_replaygain_mode(id3->track_gain_string != NULL,
798 id3->album_gain_string != NULL);
799 else
800 type = -1;
802 if (type < 0)
803 val = 6; /* no tag */
804 else
805 val = type + 2;
807 if (global_settings.replaygain_type == REPLAYGAIN_SHUFFLE)
808 val += 2;
811 if (intval)
812 *intval = val;
814 switch (val)
816 case 1:
817 case 6:
818 return "+0.00 dB";
819 break;
820 /* due to above, coming here with !id3 shouldn't be possible */
821 case 2:
822 case 4:
823 strlcpy(buf, id3->track_gain_string, buf_size);
824 break;
825 case 3:
826 case 5:
827 strlcpy(buf, id3->album_gain_string, buf_size);
828 break;
830 return buf;
832 #endif /* (CONFIG_CODEC == SWCODEC) */
834 #if (CONFIG_CODEC != MAS3507D)
835 case WPS_TOKEN_SOUND_PITCH:
837 int32_t pitch = sound_get_pitch();
838 snprintf(buf, buf_size, "%ld.%ld",
839 pitch / PITCH_SPEED_PRECISION,
840 (pitch % PITCH_SPEED_PRECISION) / (PITCH_SPEED_PRECISION / 10));
842 if (intval)
843 *intval = pitch_speed_enum(limit, pitch,
844 PITCH_SPEED_PRECISION * 100);
845 return buf;
847 #endif
849 #if CONFIG_CODEC == SWCODEC
850 case WPS_TOKEN_SOUND_SPEED:
852 int32_t pitch = sound_get_pitch();
853 int32_t speed;
854 if (dsp_timestretch_available())
855 speed = GET_SPEED(pitch, dsp_get_timestretch());
856 else
857 speed = pitch;
858 snprintf(buf, buf_size, "%ld.%ld",
859 speed / PITCH_SPEED_PRECISION,
860 (speed % PITCH_SPEED_PRECISION) / (PITCH_SPEED_PRECISION / 10));
861 if (intval)
862 *intval = pitch_speed_enum(limit, speed,
863 PITCH_SPEED_PRECISION * 100);
864 return buf;
866 #endif
868 case WPS_TOKEN_MAIN_HOLD:
869 #ifdef HAS_BUTTON_HOLD
870 if (button_hold())
871 #else
872 if (is_keys_locked())
873 #endif /*hold switch or softlock*/
874 return "h";
875 else
876 return NULL;
878 #ifdef HAS_REMOTE_BUTTON_HOLD
879 case WPS_TOKEN_REMOTE_HOLD:
880 if (remote_button_hold())
881 return "r";
882 else
883 return NULL;
884 #endif
886 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
887 case WPS_TOKEN_VLED_HDD:
888 if(led_read(HZ/2))
889 return "h";
890 else
891 return NULL;
892 #endif
893 case WPS_TOKEN_BUTTON_VOLUME:
894 if (global_status.last_volume_change &&
895 TIME_BEFORE(current_tick, global_status.last_volume_change +
896 token->value.i * TIMEOUT_UNIT))
897 return "v";
898 return NULL;
900 case WPS_TOKEN_TRACK_STARTING:
901 if (id3)
903 int elapsed = id3->elapsed + state->ff_rewind_count;
904 if (elapsed < token->value.i * 1000)
905 return "starting";
907 return NULL;
908 case WPS_TOKEN_TRACK_ENDING:
909 if (id3)
911 unsigned long elapsed = id3->elapsed + state->ff_rewind_count;
912 unsigned time = token->value.i * 1000;
913 if (id3->length - elapsed < time)
914 return "ending";
916 return NULL;
917 case WPS_TOKEN_LASTTOUCH:
918 #ifdef HAVE_TOUCHSCREEN
919 if (TIME_BEFORE(current_tick, token->value.i * TIMEOUT_UNIT +
920 touchscreen_last_touch()))
921 return "t";
922 #endif
923 return NULL;
925 case WPS_TOKEN_SETTING:
927 const struct settings_list *s = settings+token->value.i;
928 if (intval)
930 /* Handle contionals */
931 switch (s->flags&F_T_MASK)
933 case F_T_INT:
934 case F_T_UINT:
935 if (s->flags&F_T_SOUND)
937 /* %?St|name|<min|min+1|...|max-1|max> */
938 int sound_setting = s->sound_setting->setting;
939 /* settings with decimals can't be used in conditionals */
940 if (sound_numdecimals(sound_setting) == 0)
942 *intval = (*(int*)s->setting-sound_min(sound_setting))
943 /sound_steps(sound_setting) + 1;
945 else
946 *intval = -1;
948 else if (s->flags&F_RGB)
949 /* %?St|name|<#000000|#000001|...|#FFFFFF> */
950 /* shouldn't overflow since colors are stored
951 * on 16 bits ...
952 * but this is pretty useless anyway */
953 *intval = *(int*)s->setting + 1;
954 else if (s->cfg_vals == NULL)
955 /* %?St|name|<1st choice|2nd choice|...> */
956 *intval = (*(int*)s->setting-s->int_setting->min)
957 /s->int_setting->step + 1;
958 else
959 /* %?St|name|<1st choice|2nd choice|...> */
960 /* Not sure about this one. cfg_name/vals are
961 * indexed from 0 right? */
962 *intval = *(int*)s->setting + 1;
963 break;
964 case F_T_BOOL:
965 /* %?St|name|<if true|if false> */
966 *intval = *(bool*)s->setting?1:2;
967 break;
968 case F_T_CHARPTR:
969 case F_T_UCHARPTR:
970 /* %?St|name|<if non empty string|if empty>
971 * The string's emptyness discards the setting's
972 * prefix and suffix */
973 *intval = ((char*)s->setting)[0]?1:2;
974 break;
975 default:
976 /* This shouldn't happen ... but you never know */
977 *intval = -1;
978 break;
981 /* Special handlng for filenames because we dont want to show the prefix */
982 if ((s->flags&F_T_MASK) == F_T_UCHARPTR ||
983 (s->flags&F_T_MASK) == F_T_UCHARPTR)
985 if (s->filename_setting->prefix)
986 return (char*)s->setting;
988 cfg_to_string(token->value.i,buf,buf_size);
989 return buf;
991 /* Recording tokens */
992 case WPS_TOKEN_HAVE_RECORDING:
993 #ifdef HAVE_RECORDING
994 return "r";
995 #else
996 return NULL;
997 #endif
999 #ifdef HAVE_RECORDING
1000 case WPS_TOKEN_REC_FREQ: /* order from REC_FREQ_CFG_VAL_LIST */
1002 #if CONFIG_CODEC == SWCODEC
1003 unsigned long samprk;
1004 int rec_freq = global_settings.rec_frequency;
1006 #ifdef SIMULATOR
1007 samprk = 44100;
1008 #else
1009 #if defined(HAVE_SPDIF_REC)
1010 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
1012 /* Use rate in use, not current measured rate if it changed */
1013 samprk = pcm_rec_sample_rate();
1014 rec_freq = 0;
1015 while (rec_freq < SAMPR_NUM_FREQ &&
1016 audio_master_sampr_list[rec_freq] != samprk)
1018 rec_freq++;
1021 else
1022 #endif
1023 samprk = rec_freq_sampr[rec_freq];
1024 #endif /* SIMULATOR */
1025 if (intval)
1027 switch (rec_freq)
1029 REC_HAVE_96_(case REC_FREQ_96:
1030 *intval = 1;
1031 break;)
1032 REC_HAVE_88_(case REC_FREQ_88:
1033 *intval = 2;
1034 break;)
1035 REC_HAVE_64_(case REC_FREQ_64:
1036 *intval = 3;
1037 break;)
1038 REC_HAVE_48_(case REC_FREQ_48:
1039 *intval = 4;
1040 break;)
1041 REC_HAVE_44_(case REC_FREQ_44:
1042 *intval = 5;
1043 break;)
1044 REC_HAVE_32_(case REC_FREQ_32:
1045 *intval = 6;
1046 break;)
1047 REC_HAVE_24_(case REC_FREQ_24:
1048 *intval = 7;
1049 break;)
1050 REC_HAVE_22_(case REC_FREQ_22:
1051 *intval = 8;
1052 break;)
1053 REC_HAVE_16_(case REC_FREQ_16:
1054 *intval = 9;
1055 break;)
1056 REC_HAVE_12_(case REC_FREQ_12:
1057 *intval = 10;
1058 break;)
1059 REC_HAVE_11_(case REC_FREQ_11:
1060 *intval = 11;
1061 break;)
1062 REC_HAVE_8_(case REC_FREQ_8:
1063 *intval = 12;
1064 break;)
1067 snprintf(buf, buf_size, "%lu.%1lu", samprk/1000,samprk%1000);
1068 #else /* HWCODEC */
1070 static const char * const freq_strings[] =
1071 {"--", "44", "48", "32", "22", "24", "16"};
1072 int freq = 1 + global_settings.rec_frequency;
1073 #ifdef HAVE_SPDIF_REC
1074 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
1076 /* Can't measure S/PDIF sample rate on Archos/Sim yet */
1077 freq = 0;
1079 #endif /* HAVE_SPDIF_IN */
1080 if (intval)
1081 *intval = freq+1; /* so the token gets a value 1<=x<=7 */
1082 snprintf(buf, buf_size, "%d\n",
1083 freq_strings[global_settings.rec_frequency]);
1084 #endif
1085 return buf;
1087 #if CONFIG_CODEC == SWCODEC
1088 case WPS_TOKEN_REC_ENCODER:
1090 int rec_format = global_settings.rec_format+1; /* WAV, AIFF, WV, MPEG */
1091 if (intval)
1092 *intval = rec_format;
1093 switch (rec_format)
1095 case REC_FORMAT_PCM_WAV:
1096 return "wav";
1097 case REC_FORMAT_AIFF:
1098 return "aiff";
1099 case REC_FORMAT_WAVPACK:
1100 return "wv";
1101 case REC_FORMAT_MPA_L3:
1102 return "MP3";
1103 default:
1104 return NULL;
1106 break;
1108 #endif
1109 case WPS_TOKEN_REC_BITRATE:
1110 #if CONFIG_CODEC == SWCODEC
1111 if (global_settings.rec_format == REC_FORMAT_MPA_L3)
1113 if (intval)
1115 #if 0 /* FIXME: I dont know if this is needed? */
1116 switch (1<<global_settings.mp3_enc_config.bitrate)
1118 case MP3_BITR_CAP_8:
1119 *intval = 1;
1120 break;
1121 case MP3_BITR_CAP_16:
1122 *intval = 2;
1123 break;
1124 case MP3_BITR_CAP_24:
1125 *intval = 3;
1126 break;
1127 case MP3_BITR_CAP_32:
1128 *intval = 4;
1129 break;
1130 case MP3_BITR_CAP_40:
1131 *intval = 5;
1132 break;
1133 case MP3_BITR_CAP_48:
1134 *intval = 6;
1135 break;
1136 case MP3_BITR_CAP_56:
1137 *intval = 7;
1138 break;
1139 case MP3_BITR_CAP_64:
1140 *intval = 8;
1141 break;
1142 case MP3_BITR_CAP_80:
1143 *intval = 9;
1144 break;
1145 case MP3_BITR_CAP_96:
1146 *intval = 10;
1147 break;
1148 case MP3_BITR_CAP_112:
1149 *intval = 11;
1150 break;
1151 case MP3_BITR_CAP_128:
1152 *intval = 12;
1153 break;
1154 case MP3_BITR_CAP_144:
1155 *intval = 13;
1156 break;
1157 case MP3_BITR_CAP_160:
1158 *intval = 14;
1159 break;
1160 case MP3_BITR_CAP_192:
1161 *intval = 15;
1162 break;
1164 #endif
1165 *intval = global_settings.mp3_enc_config.bitrate+1;
1167 snprintf(buf, buf_size, "%lu", global_settings.mp3_enc_config.bitrate+1);
1168 return buf;
1170 else
1171 return NULL; /* Fixme later */
1172 #else /* CONFIG_CODEC == HWCODEC */
1173 if (intval)
1174 *intval = global_settings.rec_quality+1;
1175 snprintf(buf, buf_size, "%d", global_settings.rec_quality);
1176 return buf;
1177 #endif
1178 case WPS_TOKEN_REC_MONO:
1179 if (!global_settings.rec_channels)
1180 return "m";
1181 return NULL;
1183 #endif /* HAVE_RECORDING */
1184 case WPS_TOKEN_CURRENT_SCREEN:
1186 int curr_screen = current_screen();
1188 #ifdef HAVE_RECORDING
1189 /* override current_screen() for recording screen since it may
1190 * be entered from the radio screen */
1191 if (in_recording_screen())
1192 curr_screen = GO_TO_RECSCREEN;
1193 #endif
1195 switch (curr_screen)
1197 case GO_TO_WPS:
1198 curr_screen = 2;
1199 break;
1200 #ifdef HAVE_RECORDING
1201 case GO_TO_RECSCREEN:
1202 curr_screen = 3;
1203 break;
1204 #endif
1205 #if CONFIG_TUNER
1206 case GO_TO_FM:
1207 curr_screen = 4;
1208 break;
1209 #endif
1210 case GO_TO_PLAYLIST_VIEWER:
1211 curr_screen = 5;
1212 break;
1213 default: /* lists */
1214 curr_screen = 1;
1215 break;
1217 if (intval)
1219 *intval = curr_screen;
1221 snprintf(buf, buf_size, "%d", curr_screen);
1222 return buf;
1225 case WPS_TOKEN_LANG_IS_RTL:
1226 return lang_is_rtl() ? "r" : NULL;
1228 default:
1229 return NULL;