2 new tags:
[kugel-rb.git] / apps / gui / skin_engine / skin_tokens.c
blobdf2c42e727fb29c2e3b204985e5acaed721a4704
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 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, "%d", 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.%d",
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, "%ld", id3->rating);
306 return buf;
307 case WPS_TOKEN_DATABASE_AUTOSCORE:
308 if (intval)
309 *intval = id3->score + 1;
310 snprintf(buf, buf_size, "%ld", 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 * HZ)
905 return "starting";
907 return NULL;
908 case WPS_TOKEN_TRACK_ENDING:
909 if (id3)
911 int elapsed = id3->elapsed + + state->ff_rewind_count;
912 if (id3->length - elapsed < token->value.i * HZ)
913 return "ending";
915 return NULL;
916 case WPS_TOKEN_LASTTOUCH:
917 #ifdef HAVE_TOUCHSCREEN
918 if (TIME_BEFORE(current_tick, token->value.i * TIMEOUT_UNIT +
919 touchscreen_last_touch()))
920 return "t";
921 #endif
922 return NULL;
924 case WPS_TOKEN_SETTING:
926 const struct settings_list *s = settings+token->value.i;
927 if (intval)
929 /* Handle contionals */
930 switch (s->flags&F_T_MASK)
932 case F_T_INT:
933 case F_T_UINT:
934 if (s->flags&F_T_SOUND)
936 /* %?St|name|<min|min+1|...|max-1|max> */
937 int sound_setting = s->sound_setting->setting;
938 /* settings with decimals can't be used in conditionals */
939 if (sound_numdecimals(sound_setting) == 0)
941 *intval = (*(int*)s->setting-sound_min(sound_setting))
942 /sound_steps(sound_setting) + 1;
944 else
945 *intval = -1;
947 else if (s->flags&F_RGB)
948 /* %?St|name|<#000000|#000001|...|#FFFFFF> */
949 /* shouldn't overflow since colors are stored
950 * on 16 bits ...
951 * but this is pretty useless anyway */
952 *intval = *(int*)s->setting + 1;
953 else if (s->cfg_vals == NULL)
954 /* %?St|name|<1st choice|2nd choice|...> */
955 *intval = (*(int*)s->setting-s->int_setting->min)
956 /s->int_setting->step + 1;
957 else
958 /* %?St|name|<1st choice|2nd choice|...> */
959 /* Not sure about this one. cfg_name/vals are
960 * indexed from 0 right? */
961 *intval = *(int*)s->setting + 1;
962 break;
963 case F_T_BOOL:
964 /* %?St|name|<if true|if false> */
965 *intval = *(bool*)s->setting?1:2;
966 break;
967 case F_T_CHARPTR:
968 case F_T_UCHARPTR:
969 /* %?St|name|<if non empty string|if empty>
970 * The string's emptyness discards the setting's
971 * prefix and suffix */
972 *intval = ((char*)s->setting)[0]?1:2;
973 break;
974 default:
975 /* This shouldn't happen ... but you never know */
976 *intval = -1;
977 break;
980 /* Special handlng for filenames because we dont want to show the prefix */
981 if ((s->flags&F_T_MASK) == F_T_UCHARPTR ||
982 (s->flags&F_T_MASK) == F_T_UCHARPTR)
984 if (s->filename_setting->prefix)
985 return (char*)s->setting;
987 cfg_to_string(token->value.i,buf,buf_size);
988 return buf;
990 /* Recording tokens */
991 case WPS_TOKEN_HAVE_RECORDING:
992 #ifdef HAVE_RECORDING
993 return "r";
994 #else
995 return NULL;
996 #endif
998 #ifdef HAVE_RECORDING
999 case WPS_TOKEN_REC_FREQ: /* order from REC_FREQ_CFG_VAL_LIST */
1001 #if CONFIG_CODEC == SWCODEC
1002 unsigned long samprk;
1003 int rec_freq = global_settings.rec_frequency;
1005 #ifdef SIMULATOR
1006 samprk = 44100;
1007 #else
1008 #if defined(HAVE_SPDIF_REC)
1009 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
1011 /* Use rate in use, not current measured rate if it changed */
1012 samprk = pcm_rec_sample_rate();
1013 rec_freq = 0;
1014 while (rec_freq < SAMPR_NUM_FREQ &&
1015 audio_master_sampr_list[rec_freq] != samprk)
1017 rec_freq++;
1020 else
1021 #endif
1022 samprk = rec_freq_sampr[rec_freq];
1023 #endif /* SIMULATOR */
1024 if (intval)
1026 switch (rec_freq)
1028 REC_HAVE_96_(case REC_FREQ_96:
1029 *intval = 1;
1030 break;)
1031 REC_HAVE_88_(case REC_FREQ_88:
1032 *intval = 2;
1033 break;)
1034 REC_HAVE_64_(case REC_FREQ_64:
1035 *intval = 3;
1036 break;)
1037 REC_HAVE_48_(case REC_FREQ_48:
1038 *intval = 4;
1039 break;)
1040 REC_HAVE_44_(case REC_FREQ_44:
1041 *intval = 5;
1042 break;)
1043 REC_HAVE_32_(case REC_FREQ_32:
1044 *intval = 6;
1045 break;)
1046 REC_HAVE_24_(case REC_FREQ_24:
1047 *intval = 7;
1048 break;)
1049 REC_HAVE_22_(case REC_FREQ_22:
1050 *intval = 8;
1051 break;)
1052 REC_HAVE_16_(case REC_FREQ_16:
1053 *intval = 9;
1054 break;)
1055 REC_HAVE_12_(case REC_FREQ_12:
1056 *intval = 10;
1057 break;)
1058 REC_HAVE_11_(case REC_FREQ_11:
1059 *intval = 11;
1060 break;)
1061 REC_HAVE_8_(case REC_FREQ_8:
1062 *intval = 12;
1063 break;)
1066 snprintf(buf, buf_size, "%d.%1d", samprk/1000,samprk%1000);
1067 #else /* HWCODEC */
1069 static const char * const freq_strings[] =
1070 {"--", "44", "48", "32", "22", "24", "16"};
1071 int freq = 1 + global_settings.rec_frequency;
1072 #ifdef HAVE_SPDIF_REC
1073 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
1075 /* Can't measure S/PDIF sample rate on Archos/Sim yet */
1076 freq = 0;
1078 #endif /* HAVE_SPDIF_IN */
1079 if (intval)
1080 *intval = freq+1; /* so the token gets a value 1<=x<=7 */
1081 snprintf(buf, buf_size, "%d\n",
1082 freq_strings[global_settings.rec_frequency]);
1083 #endif
1084 return buf;
1086 #if CONFIG_CODEC == SWCODEC
1087 case WPS_TOKEN_REC_ENCODER:
1089 int rec_format = global_settings.rec_format+1; /* WAV, AIFF, WV, MPEG */
1090 if (intval)
1091 *intval = rec_format;
1092 switch (rec_format)
1094 case REC_FORMAT_PCM_WAV:
1095 return "wav";
1096 case REC_FORMAT_AIFF:
1097 return "aiff";
1098 case REC_FORMAT_WAVPACK:
1099 return "wv";
1100 case REC_FORMAT_MPA_L3:
1101 return "MP3";
1102 default:
1103 return NULL;
1105 break;
1107 #endif
1108 case WPS_TOKEN_REC_BITRATE:
1109 #if CONFIG_CODEC == SWCODEC
1110 if (global_settings.rec_format == REC_FORMAT_MPA_L3)
1112 if (intval)
1114 #if 0 /* FIXME: I dont know if this is needed? */
1115 switch (1<<global_settings.mp3_enc_config.bitrate)
1117 case MP3_BITR_CAP_8:
1118 *intval = 1;
1119 break;
1120 case MP3_BITR_CAP_16:
1121 *intval = 2;
1122 break;
1123 case MP3_BITR_CAP_24:
1124 *intval = 3;
1125 break;
1126 case MP3_BITR_CAP_32:
1127 *intval = 4;
1128 break;
1129 case MP3_BITR_CAP_40:
1130 *intval = 5;
1131 break;
1132 case MP3_BITR_CAP_48:
1133 *intval = 6;
1134 break;
1135 case MP3_BITR_CAP_56:
1136 *intval = 7;
1137 break;
1138 case MP3_BITR_CAP_64:
1139 *intval = 8;
1140 break;
1141 case MP3_BITR_CAP_80:
1142 *intval = 9;
1143 break;
1144 case MP3_BITR_CAP_96:
1145 *intval = 10;
1146 break;
1147 case MP3_BITR_CAP_112:
1148 *intval = 11;
1149 break;
1150 case MP3_BITR_CAP_128:
1151 *intval = 12;
1152 break;
1153 case MP3_BITR_CAP_144:
1154 *intval = 13;
1155 break;
1156 case MP3_BITR_CAP_160:
1157 *intval = 14;
1158 break;
1159 case MP3_BITR_CAP_192:
1160 *intval = 15;
1161 break;
1163 #endif
1164 *intval = global_settings.mp3_enc_config.bitrate+1;
1166 snprintf(buf, buf_size, "%d", global_settings.mp3_enc_config.bitrate+1);
1167 return buf;
1169 else
1170 return NULL; /* Fixme later */
1171 #else /* CONFIG_CODEC == HWCODEC */
1172 if (intval)
1173 *intval = global_settings.rec_quality+1;
1174 snprintf(buf, buf_size, "%d", global_settings.rec_quality);
1175 return buf;
1176 #endif
1177 case WPS_TOKEN_REC_MONO:
1178 if (!global_settings.rec_channels)
1179 return "m";
1180 return NULL;
1182 #endif /* HAVE_RECORDING */
1183 case WPS_TOKEN_CURRENT_SCREEN:
1185 int curr_screen = current_screen();
1187 #ifdef HAVE_RECORDING
1188 /* override current_screen() for recording screen since it may
1189 * be entered from the radio screen */
1190 if (in_recording_screen())
1191 curr_screen = GO_TO_RECSCREEN;
1192 #endif
1194 switch (curr_screen)
1196 case GO_TO_WPS:
1197 curr_screen = 2;
1198 break;
1199 #ifdef HAVE_RECORDING
1200 case GO_TO_RECSCREEN:
1201 curr_screen = 3;
1202 break;
1203 #endif
1204 #if CONFIG_TUNER
1205 case GO_TO_FM:
1206 curr_screen = 4;
1207 break;
1208 #endif
1209 case GO_TO_PLAYLIST_VIEWER:
1210 curr_screen = 5;
1211 break;
1212 default: /* lists */
1213 curr_screen = 1;
1214 break;
1216 if (intval)
1218 *intval = curr_screen;
1220 snprintf(buf, buf_size, "%d", curr_screen);
1221 return buf;
1224 case WPS_TOKEN_LANG_IS_RTL:
1225 return lang_is_rtl() ? "r" : NULL;
1227 default:
1228 return NULL;