here too
[maemo-rb.git] / apps / gui / skin_engine / skin_tokens.c
blobddc2221ce6abcd91ebe33f348715ff8386b0c945
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 #include "cuesheet.h"
38 #ifdef HAVE_LCD_CHARCELLS
39 #include "hwcompat.h"
40 #endif
41 #include "abrepeat.h"
42 #include "lang.h"
43 #include "misc.h"
44 #include "led.h"
45 #ifdef HAVE_LCD_BITMAP
46 #include "peakmeter.h"
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 #include "tdspeed.h"
55 #endif
56 #include "viewport.h"
57 #include "tagcache.h"
59 #include "wps_internals.h"
60 #include "skin_engine.h"
61 #include "statusbar-skinned.h"
62 #include "root_menu.h"
63 #ifdef HAVE_RECORDING
64 #include "recording.h"
65 #include "pcm_record.h"
66 #endif
67 #include "language.h"
68 #include "usb.h"
69 #if CONFIG_TUNER
70 #include "radio.h"
71 #include "tuner.h"
72 #endif
74 #define NOINLINE __attribute__ ((noinline))
76 extern struct wps_state wps_state;
78 static const char* get_codectype(const struct mp3entry* id3)
80 if (id3 && id3->codectype < AFMT_NUM_CODECS) {
81 return audio_formats[id3->codectype].label;
82 } else {
83 return NULL;
87 /* Extract a part from a path.
89 * buf - buffer extract part to.
90 * buf_size - size of buffer.
91 * path - path to extract from.
92 * level - what to extract. 0 is file name, 1 is parent of file, 2 is
93 * parent of parent, etc.
95 * Returns buf if the desired level was found, NULL otherwise.
97 char* get_dir(char* buf, int buf_size, const char* path, int level)
99 const char* sep;
100 const char* last_sep;
101 int len;
103 sep = path + strlen(path);
104 last_sep = sep;
106 while (sep > path)
108 if ('/' == *(--sep))
110 if (!level)
111 break;
113 level--;
114 last_sep = sep - 1;
118 if (level || (last_sep <= sep))
119 return NULL;
121 len = MIN(last_sep - sep, buf_size - 1);
122 strlcpy(buf, sep + 1, len + 1);
123 return buf;
126 #if (CONFIG_CODEC != MAS3507D) && defined (HAVE_PITCHSCREEN)
127 /* A helper to determine the enum value for pitch/speed.
129 When there are two choices (i.e. boolean), return 1 if the value is
130 different from normal value and 2 if the value is the same as the
131 normal value. E.g. "%?Sp<%Sp>" would show the pitch only when
132 playing at a modified pitch.
134 When there are more than two choices (i.e. enum), the left half of
135 the choices are to show 0..normal range, and the right half of the
136 choices are to show values over that. The last entry is used when
137 it is set to the normal setting, following the rockbox convention
138 to use the last entry for special values.
140 E.g.
142 2 items: %?Sp<0..99 or 101..infinity|100>
143 3 items: %?Sp<0..99|101..infinity|100>
144 4 items: %?Sp<0..49|50..99|101..infinity|100>
145 5 items: %?Sp<0..49|50..99|101..149|150..infinity|100>
146 6 items: %?Sp<0..33|34..66|67..99|101..133|134..infinity|100>
147 7 items: %?Sp<0..33|34..66|67..99|101..133|134..167|167..infinity|100>
149 static int pitch_speed_enum(int range, int32_t val, int32_t normval)
151 int center;
152 int n;
154 if (range < 3)
155 return (val == normval) + 1;
156 if (val == normval)
157 return range;
158 center = range / 2;
159 n = (center * val) / normval + 1;
160 return (range <= n) ? (range - 1) : n;
162 #endif
164 const char *get_cuesheetid3_token(struct wps_token *token, struct mp3entry *id3,
165 int offset_tracks, char *buf, int buf_size)
167 struct cuesheet *cue = id3?id3->cuesheet:NULL;
168 if (!cue || !cue->curr_track)
169 return NULL;
171 struct cue_track_info *track = cue->curr_track;
172 if (offset_tracks)
174 if (cue->curr_track_idx+offset_tracks < cue->track_count)
175 track+=offset_tracks;
176 else
177 return NULL;
179 switch (token->type)
181 case SKIN_TOKEN_METADATA_ARTIST:
182 return *track->performer ? track->performer : NULL;
183 case SKIN_TOKEN_METADATA_COMPOSER:
184 return *track->songwriter ? track->songwriter : NULL;
185 case SKIN_TOKEN_METADATA_ALBUM:
186 return *cue->title ? cue->title : NULL;
187 case SKIN_TOKEN_METADATA_ALBUM_ARTIST:
188 return *cue->performer ? cue->performer : NULL;
189 case SKIN_TOKEN_METADATA_TRACK_TITLE:
190 return *track->title ? track->title : NULL;
191 case SKIN_TOKEN_METADATA_TRACK_NUMBER:
192 snprintf(buf, buf_size, "%d/%d",
193 cue->curr_track_idx+offset_tracks+1, cue->track_count);
194 return buf;
195 default:
196 return NULL;
198 return NULL;
201 static const char* get_filename_token(struct wps_token *token, char* filename,
202 char *buf, int buf_size)
204 if (filename)
206 switch (token->type)
208 case SKIN_TOKEN_FILE_PATH:
209 return filename;
210 case SKIN_TOKEN_FILE_NAME:
211 if (get_dir(buf, buf_size, filename, 0)) {
212 /* Remove extension */
213 char* sep = strrchr(buf, '.');
214 if (NULL != sep) {
215 *sep = 0;
217 return buf;
219 return NULL;
220 case SKIN_TOKEN_FILE_NAME_WITH_EXTENSION:
221 return get_dir(buf, buf_size, filename, 0);
222 case SKIN_TOKEN_FILE_DIRECTORY:
223 return get_dir(buf, buf_size, filename, token->value.i);
224 default:
225 return NULL;
228 return NULL;
231 /* All tokens which only need the info to return a value go in here */
232 const char *get_id3_token(struct wps_token *token, struct mp3entry *id3,
233 char *filename, char *buf, int buf_size, int limit, int *intval)
235 struct wps_state *state = &wps_state;
236 if (id3)
238 unsigned long length = id3->length;
239 unsigned long elapsed = id3->elapsed + state->ff_rewind_count;
240 switch (token->type)
242 case SKIN_TOKEN_METADATA_ARTIST:
243 return id3->artist;
244 case SKIN_TOKEN_METADATA_COMPOSER:
245 return id3->composer;
246 case SKIN_TOKEN_METADATA_ALBUM:
247 return id3->album;
248 case SKIN_TOKEN_METADATA_ALBUM_ARTIST:
249 return id3->albumartist;
250 case SKIN_TOKEN_METADATA_GROUPING:
251 return id3->grouping;
252 case SKIN_TOKEN_METADATA_GENRE:
253 return id3->genre_string;
254 case SKIN_TOKEN_METADATA_DISC_NUMBER:
255 if (id3->disc_string)
256 return id3->disc_string;
257 if (id3->discnum) {
258 snprintf(buf, buf_size, "%d", id3->discnum);
259 return buf;
261 return NULL;
262 case SKIN_TOKEN_METADATA_TRACK_NUMBER:
263 if (id3->track_string)
264 return id3->track_string;
265 if (id3->tracknum) {
266 snprintf(buf, buf_size, "%d", id3->tracknum);
267 return buf;
269 return NULL;
270 case SKIN_TOKEN_METADATA_TRACK_TITLE:
271 return id3->title;
272 case SKIN_TOKEN_METADATA_VERSION:
273 switch (id3->id3version)
275 case ID3_VER_1_0:
276 return "1";
277 case ID3_VER_1_1:
278 return "1.1";
279 case ID3_VER_2_2:
280 return "2.2";
281 case ID3_VER_2_3:
282 return "2.3";
283 case ID3_VER_2_4:
284 return "2.4";
285 default:
286 break;
288 return NULL;
289 case SKIN_TOKEN_METADATA_YEAR:
290 if( id3->year_string )
291 return id3->year_string;
292 if (id3->year) {
293 snprintf(buf, buf_size, "%d", id3->year);
294 return buf;
296 return NULL;
297 case SKIN_TOKEN_METADATA_COMMENT:
298 return id3->comment;
299 case SKIN_TOKEN_FILE_BITRATE:
300 if(id3->bitrate)
301 snprintf(buf, buf_size, "%d", id3->bitrate);
302 else
303 return "?";
304 return buf;
305 case SKIN_TOKEN_TRACK_TIME_ELAPSED:
306 format_time(buf, buf_size, elapsed);
307 return buf;
309 case SKIN_TOKEN_TRACK_TIME_REMAINING:
310 format_time(buf, buf_size, length - elapsed);
311 return buf;
313 case SKIN_TOKEN_TRACK_LENGTH:
314 format_time(buf, buf_size, length);
315 return buf;
317 case SKIN_TOKEN_TRACK_ELAPSED_PERCENT:
318 if (length <= 0)
319 return NULL;
321 if (intval)
323 if (limit == TOKEN_VALUE_ONLY)
324 limit = 100; /* make it a percentage */
325 *intval = limit * elapsed / length + 1;
327 snprintf(buf, buf_size, "%lu", 100 * elapsed / length);
328 return buf;
330 case SKIN_TOKEN_TRACK_STARTING:
332 unsigned long time = token->value.i * (HZ/TIMEOUT_UNIT);
333 if (elapsed < time)
334 return "starting";
336 return NULL;
337 case SKIN_TOKEN_TRACK_ENDING:
339 unsigned long time = token->value.i * (HZ/TIMEOUT_UNIT);
340 if (length - elapsed < time)
341 return "ending";
343 return NULL;
345 case SKIN_TOKEN_FILE_CODEC:
346 if (intval)
348 if(id3->codectype == AFMT_UNKNOWN)
349 *intval = AFMT_NUM_CODECS;
350 else
351 *intval = id3->codectype;
353 return get_codectype(id3);
355 case SKIN_TOKEN_FILE_FREQUENCY:
356 snprintf(buf, buf_size, "%ld", id3->frequency);
357 return buf;
358 case SKIN_TOKEN_FILE_FREQUENCY_KHZ:
359 /* ignore remainders < 100, so 22050 Hz becomes just 22k */
360 if ((id3->frequency % 1000) < 100)
361 snprintf(buf, buf_size, "%ld", id3->frequency / 1000);
362 else
363 snprintf(buf, buf_size, "%ld.%lu",
364 id3->frequency / 1000,
365 (id3->frequency % 1000) / 100);
366 return buf;
367 case SKIN_TOKEN_FILE_VBR:
368 return (id3->vbr) ? "(avg)" : NULL;
369 case SKIN_TOKEN_FILE_SIZE:
370 snprintf(buf, buf_size, "%ld", id3->filesize / 1024);
371 return buf;
373 #ifdef HAVE_TAGCACHE
374 case SKIN_TOKEN_DATABASE_PLAYCOUNT:
375 if (intval)
376 *intval = id3->playcount + 1;
377 snprintf(buf, buf_size, "%ld", id3->playcount);
378 return buf;
379 case SKIN_TOKEN_DATABASE_RATING:
380 if (intval)
381 *intval = id3->rating + 1;
382 snprintf(buf, buf_size, "%d", id3->rating);
383 return buf;
384 case SKIN_TOKEN_DATABASE_AUTOSCORE:
385 if (intval)
386 *intval = id3->score + 1;
387 snprintf(buf, buf_size, "%d", id3->score);
388 return buf;
389 #endif
391 default:
392 return get_filename_token(token, id3->path, buf, buf_size);
395 else /* id3 == NULL, handle the error based on the expected return type */
397 switch (token->type)
399 /* Most tokens expect NULL on error so leave that for the default case,
400 * The ones that expect "0" need to be handled */
401 case SKIN_TOKEN_FILE_FREQUENCY:
402 case SKIN_TOKEN_FILE_FREQUENCY_KHZ:
403 case SKIN_TOKEN_FILE_SIZE:
404 #ifdef HAVE_TAGCACHE
405 case SKIN_TOKEN_DATABASE_PLAYCOUNT:
406 case SKIN_TOKEN_DATABASE_RATING:
407 case SKIN_TOKEN_DATABASE_AUTOSCORE:
408 #endif
409 if (intval)
410 *intval = 0;
411 return "0";
412 default:
413 return get_filename_token(token, filename, buf, buf_size);
416 return buf;
419 #if CONFIG_TUNER
421 /* Formats the frequency (specified in Hz) in MHz, */
422 /* with one or two digits after the decimal point -- */
423 /* depending on the frequency changing step. */
424 /* Returns buf */
425 static char *format_freq_MHz(int freq, int freq_step, char *buf, int buf_size)
427 int scale, div;
428 char *fmt;
429 if (freq_step < 100000)
431 /* Format with two digits after decimal point */
432 scale = 10000;
433 fmt = "%d.%02d";
435 else
437 /* Format with one digit after decimal point */
438 scale = 100000;
439 fmt = "%d.%d";
441 div = 1000000 / scale;
442 freq = freq / scale;
443 snprintf(buf, buf_size, fmt, freq/div, freq%div);
444 return buf;
448 /* Tokens which are really only used by the radio screen go in here */
449 const char *get_radio_token(struct wps_token *token, int preset_offset,
450 char *buf, int buf_size, int limit, int *intval)
452 const struct fm_region_data *region_data =
453 &(fm_region_data[global_settings.fm_region]);
454 (void)limit;
455 switch (token->type)
457 /* Radio/tuner tokens */
458 case SKIN_TOKEN_TUNER_TUNED:
459 if (tuner_get(RADIO_TUNED))
460 return "t";
461 return NULL;
462 case SKIN_TOKEN_TUNER_SCANMODE:
463 if (radio_scan_mode())
464 return "s";
465 return NULL;
466 case SKIN_TOKEN_TUNER_STEREO:
467 if (radio_is_stereo())
468 return "s";
469 return NULL;
470 case SKIN_TOKEN_TUNER_MINFREQ: /* changes based on "region" */
471 return format_freq_MHz(region_data->freq_min,
472 region_data->freq_step, buf, buf_size);
473 case SKIN_TOKEN_TUNER_MAXFREQ: /* changes based on "region" */
474 return format_freq_MHz(region_data->freq_max,
475 region_data->freq_step, buf, buf_size);
476 case SKIN_TOKEN_TUNER_CURFREQ:
477 return format_freq_MHz(radio_current_frequency(),
478 region_data->freq_step, buf, buf_size);
479 #ifdef HAVE_RADIO_RSSI
480 case SKIN_TOKEN_TUNER_RSSI:
481 snprintf(buf, buf_size, "%d",tuner_get(RADIO_RSSI));
482 if (intval)
484 int val = tuner_get(RADIO_RSSI);
485 int min = tuner_get(RADIO_RSSI_MIN);
486 int max = tuner_get(RADIO_RSSI_MAX);
487 if (limit == TOKEN_VALUE_ONLY)
489 *intval = val;
491 else
493 *intval = 1+(limit-1)*(val-min)/(max-1-min);
496 return buf;
497 case SKIN_TOKEN_TUNER_RSSI_MIN:
498 snprintf(buf, buf_size, "%d",tuner_get(RADIO_RSSI_MIN));
499 return buf;
500 case SKIN_TOKEN_TUNER_RSSI_MAX:
501 snprintf(buf, buf_size, "%d",tuner_get(RADIO_RSSI_MAX));
502 return buf;
503 #endif
504 case SKIN_TOKEN_PRESET_NAME:
505 case SKIN_TOKEN_PRESET_FREQ:
506 case SKIN_TOKEN_PRESET_ID:
508 int preset_count = radio_preset_count();
509 int cur_preset = radio_current_preset();
510 if (preset_count == 0 || cur_preset < 0)
511 return NULL;
512 int preset = cur_preset + preset_offset;
513 /* make sure it's in the valid range */
514 preset %= preset_count;
515 if (preset < 0)
516 preset += preset_count;
517 if (token->type == SKIN_TOKEN_PRESET_NAME)
518 snprintf(buf, buf_size, "%s", radio_get_preset(preset)->name);
519 else if (token->type == SKIN_TOKEN_PRESET_FREQ)
520 format_freq_MHz(radio_get_preset(preset)->frequency,
521 region_data->freq_step, buf, buf_size);
522 else
523 snprintf(buf, buf_size, "%d", preset + 1);
524 return buf;
526 case SKIN_TOKEN_PRESET_COUNT:
527 snprintf(buf, buf_size, "%d", radio_preset_count());
528 if (intval)
529 *intval = radio_preset_count();
530 return buf;
531 case SKIN_TOKEN_HAVE_RDS:
532 #ifdef HAVE_RDS_CAP
533 return "rds";
534 case SKIN_TOKEN_RDS_NAME:
535 return tuner_get_rds_info(RADIO_RDS_NAME);
536 case SKIN_TOKEN_RDS_TEXT:
537 return tuner_get_rds_info(RADIO_RDS_TEXT);
538 #else
539 return NULL; /* end of the SKIN_TOKEN_HAVE_RDS case */
540 #endif /* HAVE_RDS_CAP */
541 default:
542 return NULL;
544 return NULL;
546 #endif
548 static struct mp3entry* get_mp3entry_from_offset(int offset, char **filename)
550 struct mp3entry* pid3 = NULL;
551 struct wps_state *state = skin_get_global_state();
552 struct cuesheet *cue = state->id3 ? state->id3->cuesheet : NULL;
553 const char *fname = NULL;
554 if (cue && cue->curr_track_idx + offset < cue->track_count)
555 pid3 = state->id3;
556 else if (offset == 0)
557 pid3 = state->id3;
558 else if (offset == 1)
559 pid3 = state->nid3;
560 else
562 static char filename_buf[MAX_PATH + 1];
563 fname = playlist_peek(offset, filename_buf, sizeof(filename_buf));
564 *filename = (char*)fname;
565 #if CONFIG_CODEC == SWCODEC
566 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
567 static struct mp3entry tempid3;
568 if (tagcache_fill_tags(&tempid3, fname))
570 pid3 = &tempid3;
572 else
573 #endif
575 if (!audio_peek_track(&pid3, offset))
576 pid3 = NULL;
578 #endif
580 return pid3;
583 #ifdef HAVE_LCD_CHARCELLS
584 static void format_player_progress(struct gui_wps *gwps)
586 struct wps_state *state = skin_get_global_state();
587 struct screen *display = gwps->display;
588 unsigned char progress_pattern[7];
589 int pos = 0;
590 int i;
592 int elapsed, length;
593 if (LIKELY(state->id3))
595 elapsed = state->id3->elapsed;
596 length = state->id3->length;
598 else
600 elapsed = 0;
601 length = 0;
604 if (length)
605 pos = 36 * (elapsed + state->ff_rewind_count) / length;
607 for (i = 0; i < 7; i++, pos -= 5)
609 if (pos <= 0)
610 progress_pattern[i] = 0x1fu;
611 else if (pos >= 5)
612 progress_pattern[i] = 0x00u;
613 else
614 progress_pattern[i] = 0x1fu >> pos;
617 display->define_pattern(gwps->data->wps_progress_pat[0], progress_pattern);
620 static void format_player_fullbar(struct gui_wps *gwps, char* buf, int buf_size)
622 static const unsigned char numbers[10][4] = {
623 {0x0e, 0x0a, 0x0a, 0x0e}, /* 0 */
624 {0x04, 0x0c, 0x04, 0x04}, /* 1 */
625 {0x0e, 0x02, 0x04, 0x0e}, /* 2 */
626 {0x0e, 0x02, 0x06, 0x0e}, /* 3 */
627 {0x08, 0x0c, 0x0e, 0x04}, /* 4 */
628 {0x0e, 0x0c, 0x02, 0x0c}, /* 5 */
629 {0x0e, 0x08, 0x0e, 0x0e}, /* 6 */
630 {0x0e, 0x02, 0x04, 0x08}, /* 7 */
631 {0x0e, 0x0e, 0x0a, 0x0e}, /* 8 */
632 {0x0e, 0x0e, 0x02, 0x0e} /* 9 */
635 struct wps_state *state = skin_get_global_state();
636 struct screen *display = gwps->display;
637 struct wps_data *data = gwps->data;
638 unsigned char progress_pattern[7];
639 char timestr[10];
640 int time;
641 int time_idx = 0;
642 int pos = 0;
643 int pat_idx = 1;
644 int digit, i, j;
645 bool softchar;
647 int elapsed, length;
648 if (LIKELY(state->id3))
650 elapsed = state->id3->elapsed;
651 length = state->id3->length;
653 else
655 elapsed = 0;
656 length = 0;
659 if (buf_size < 34) /* worst case: 11x UTF-8 char + \0 */
660 return;
662 time = elapsed + state->ff_rewind_count;
663 if (length)
664 pos = 55 * time / length;
666 memset(timestr, 0, sizeof(timestr));
667 format_time(timestr, sizeof(timestr)-2, time);
668 timestr[strlen(timestr)] = ':'; /* always safe */
670 for (i = 0; i < 11; i++, pos -= 5)
672 softchar = false;
673 memset(progress_pattern, 0, sizeof(progress_pattern));
675 if ((digit = timestr[time_idx]))
677 softchar = true;
678 digit -= '0';
680 if (timestr[time_idx + 1] == ':') /* ones, left aligned */
682 memcpy(progress_pattern, numbers[digit], 4);
683 time_idx += 2;
685 else /* tens, shifted right */
687 for (j = 0; j < 4; j++)
688 progress_pattern[j] = numbers[digit][j] >> 1;
690 if (time_idx > 0) /* not the first group, add colon in front */
692 progress_pattern[1] |= 0x10u;
693 progress_pattern[3] |= 0x10u;
695 time_idx++;
698 if (pos >= 5)
699 progress_pattern[5] = progress_pattern[6] = 0x1fu;
702 if (pos > 0 && pos < 5)
704 softchar = true;
705 progress_pattern[5] = progress_pattern[6] = (~0x1fu >> pos) & 0x1fu;
708 if (softchar && pat_idx < 8)
710 display->define_pattern(data->wps_progress_pat[pat_idx],
711 progress_pattern);
712 buf = utf8encode(data->wps_progress_pat[pat_idx], buf);
713 pat_idx++;
715 else if (pos <= 0)
716 buf = utf8encode(' ', buf);
717 else
718 buf = utf8encode(0xe115, buf); /* 2/7 _ */
720 *buf = '\0';
723 #endif /* HAVE_LCD_CHARCELLS */
725 /* Don't inline this; it was broken out of get_token_value to reduce stack
726 * usage.
728 static const char* NOINLINE get_lif_token_value(struct gui_wps *gwps,
729 struct logical_if *lif,
730 int offset, char *buf,
731 int buf_size)
733 int a = lif->num_options;
734 int b;
735 const char* out_text = get_token_value(gwps, lif->token, offset,
736 buf, buf_size, &a);
737 if (a == -1 && lif->token->type != SKIN_TOKEN_VOLUME)
738 a = (out_text && *out_text) ? 1 : 0;
739 switch (lif->operand.type)
741 case STRING:
742 if (lif->op == IF_EQUALS)
743 return (out_text && strcmp(out_text, lif->operand.data.text) == 0)
744 ? "eq" : NULL;
745 else
746 return NULL;
747 break;
748 case INTEGER:
749 case DECIMAL:
750 b = lif->operand.data.number;
751 break;
752 case CODE:
754 char temp_buf[MAX_PATH];
755 const char *outb;
756 struct wps_token *token = lif->operand.data.code->data;
757 b = lif->num_options;
758 outb = get_token_value(gwps, token, offset, temp_buf,
759 sizeof(temp_buf), &b);
760 if (b == -1 && lif->token->type != SKIN_TOKEN_VOLUME)
762 if (!out_text || !outb)
763 return (lif->op == IF_EQUALS) ? NULL : "neq";
764 bool equal = strcmp(out_text, outb) == 0;
765 if (lif->op == IF_EQUALS)
766 return equal ? "eq" : NULL;
767 else if (lif->op == IF_NOTEQUALS)
768 return !equal ? "neq" : NULL;
769 else
770 b = (outb && *outb) ? 1 : 0;
773 break;
774 case DEFAULT:
775 break;
778 switch (lif->op)
780 case IF_EQUALS:
781 return a == b ? "eq" : NULL;
782 case IF_NOTEQUALS:
783 return a != b ? "neq" : NULL;
784 case IF_LESSTHAN:
785 return a < b ? "lt" : NULL;
786 case IF_LESSTHAN_EQ:
787 return a <= b ? "lte" : NULL;
788 case IF_GREATERTHAN:
789 return a > b ? "gt" : NULL;
790 case IF_GREATERTHAN_EQ:
791 return a >= b ? "gte" : NULL;
793 return NULL;
796 /* Return the tags value as text. buf should be used as temp storage if needed.
798 intval is used with conditionals/enums: when this function is called,
799 intval should contain the number of options in the conditional/enum.
800 When this function returns, intval is -1 if the tag is non numeric or,
801 if the tag is numeric, *intval is the enum case we want to go to (between 1
802 and the original value of *intval, inclusive).
803 When not treating a conditional/enum, intval should be NULL.
805 const char *get_token_value(struct gui_wps *gwps,
806 struct wps_token *token, int offset,
807 char *buf, int buf_size,
808 int *intval)
810 if (!gwps)
811 return NULL;
813 struct wps_data *data = gwps->data;
814 struct wps_state *state = skin_get_global_state();
815 struct mp3entry *id3; /* Think very carefully about using this.
816 maybe get_id3_token() is the better place? */
817 const char *out_text = NULL;
818 char *filename = NULL;
820 if (!data || !state)
821 return NULL;
823 id3 = get_mp3entry_from_offset(token->next? 1: offset, &filename);
824 if (id3)
825 filename = id3->path;
827 #if CONFIG_RTC
828 struct tm* tm = NULL;
830 /* if the token is an RTC one, update the time
831 and do the necessary checks */
832 if (token->type >= SKIN_TOKENS_RTC_BEGIN
833 && token->type <= SKIN_TOKENS_RTC_END)
835 tm = get_time();
837 if (!valid_time(tm))
838 return NULL;
840 #endif
842 int limit = 1;
843 if (intval)
845 limit = *intval;
846 *intval = -1;
849 if (id3 && id3 == state->id3 && id3->cuesheet )
851 out_text = get_cuesheetid3_token(token, id3,
852 token->next?1:offset, buf, buf_size);
853 if (out_text)
854 return out_text;
856 out_text = get_id3_token(token, id3, filename, buf, buf_size, limit, intval);
857 if (out_text)
858 return out_text;
859 #if CONFIG_TUNER
860 out_text = get_radio_token(token, offset, buf, buf_size, limit, intval);
861 if (out_text)
862 return out_text;
863 #endif
865 switch (token->type)
867 case SKIN_TOKEN_LOGICAL_IF:
869 struct logical_if *lif = token->value.data;
870 return get_lif_token_value(gwps, lif, offset, buf, buf_size);
872 break;
874 case SKIN_TOKEN_CHARACTER:
875 if (token->value.c == '\n')
876 return NULL;
877 return &(token->value.c);
879 case SKIN_TOKEN_STRING:
880 return (char*)token->value.data;
882 case SKIN_TOKEN_TRANSLATEDSTRING:
883 return (char*)P2STR(ID2P(token->value.i));
885 case SKIN_TOKEN_PLAYLIST_ENTRIES:
886 snprintf(buf, buf_size, "%d", playlist_amount());
887 if (intval)
888 *intval = playlist_amount();
889 return buf;
890 #ifdef HAVE_LCD_BITMAP
891 case SKIN_TOKEN_LIST_TITLE_TEXT:
892 return sb_get_title(gwps->display->screen_type);
893 case SKIN_TOKEN_LIST_TITLE_ICON:
894 if (intval)
895 *intval = sb_get_icon(gwps->display->screen_type);
896 snprintf(buf, buf_size, "%d",sb_get_icon(gwps->display->screen_type));
897 return buf;
898 #endif
899 case SKIN_TOKEN_PLAYLIST_NAME:
900 return playlist_name(NULL, buf, buf_size);
902 case SKIN_TOKEN_PLAYLIST_POSITION:
903 snprintf(buf, buf_size, "%d", playlist_get_display_index()+offset);
904 if (intval)
905 *intval = playlist_get_display_index()+offset;
906 return buf;
908 case SKIN_TOKEN_PLAYLIST_SHUFFLE:
909 if ( global_settings.playlist_shuffle )
910 return "s";
911 else
912 return NULL;
913 break;
915 case SKIN_TOKEN_VOLUME:
916 snprintf(buf, buf_size, "%d", global_settings.volume);
917 if (intval)
919 int minvol = sound_min(SOUND_VOLUME);
920 if (limit == TOKEN_VALUE_ONLY)
922 *intval = global_settings.volume;
924 else if (global_settings.volume == minvol)
926 *intval = 1;
928 else if (global_settings.volume == 0)
930 *intval = limit - 1;
932 else if (global_settings.volume > 0)
934 *intval = limit;
936 else
938 *intval = (limit-3) * (global_settings.volume - minvol - 1)
939 / (-1 - minvol) + 2;
942 return buf;
943 #ifdef HAVE_ALBUMART
944 case SKIN_TOKEN_ALBUMART_FOUND:
945 if (data->albumart)
947 int handle = -1;
948 handle = playback_current_aa_hid(data->playback_aa_slot);
949 #if CONFIG_TUNER
950 if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF))
952 struct dim dim = {data->albumart->width, data->albumart->height};
953 handle = radio_get_art_hid(&dim);
955 #endif
956 if (handle >= 0)
957 return "C";
959 return NULL;
960 #endif
962 case SKIN_TOKEN_BATTERY_PERCENT:
964 int l = battery_level();
966 if (intval)
968 if (limit == TOKEN_VALUE_ONLY)
970 *intval = l;
972 else
974 limit = MAX(limit, 3);
975 if (l > -1) {
976 /* First enum is used for "unknown level",
977 * last enum is used for 100%.
979 *intval = (limit - 2) * l / 100 + 2;
980 } else {
981 *intval = 1;
986 if (l > -1) {
987 snprintf(buf, buf_size, "%d", l);
988 return buf;
989 } else {
990 return "?";
994 case SKIN_TOKEN_BATTERY_VOLTS:
996 unsigned int v = battery_voltage();
997 snprintf(buf, buf_size, "%d.%02d", v / 1000, (v % 1000) / 10);
998 return buf;
1001 case SKIN_TOKEN_BATTERY_TIME:
1003 int t = battery_time();
1004 if (t >= 0)
1005 snprintf(buf, buf_size, "%dh %dm", t / 60, t % 60);
1006 else
1007 return "?h ?m";
1008 return buf;
1011 #if CONFIG_CHARGING
1012 case SKIN_TOKEN_BATTERY_CHARGER_CONNECTED:
1014 if(charger_input_state==CHARGER)
1015 return "p";
1016 else
1017 return NULL;
1019 #endif
1020 #if CONFIG_CHARGING >= CHARGING_MONITOR
1021 case SKIN_TOKEN_BATTERY_CHARGING:
1023 if (charge_state == CHARGING || charge_state == TOPOFF) {
1024 return "c";
1025 } else {
1026 return NULL;
1029 #endif
1030 #ifdef HAVE_USB_POWER
1031 case SKIN_TOKEN_USB_POWERED:
1032 if (usb_powered())
1033 return "u";
1034 return NULL;
1035 #endif
1036 case SKIN_TOKEN_BATTERY_SLEEPTIME:
1038 if (get_sleep_timer() == 0)
1039 return NULL;
1040 else
1042 format_time(buf, buf_size, get_sleep_timer() * 1000);
1043 return buf;
1047 case SKIN_TOKEN_PLAYBACK_STATUS:
1049 int status = current_playmode();
1050 /* music */
1051 int mode = 1; /* stop */
1052 if (status == STATUS_PLAY)
1053 mode = 2; /* play */
1054 if (state->is_fading ||
1055 (status == STATUS_PAUSE && !status_get_ffmode()))
1056 mode = 3; /* pause */
1057 else
1058 { /* ff / rwd */
1059 if (status_get_ffmode() == STATUS_FASTFORWARD)
1060 mode = 4;
1061 if (status_get_ffmode() == STATUS_FASTBACKWARD)
1062 mode = 5;
1064 #ifdef HAVE_RECORDING
1065 /* recording */
1066 if (status == STATUS_RECORD)
1067 mode = 6;
1068 else if (status == STATUS_RECORD_PAUSE)
1069 mode = 7;
1070 #endif
1071 #if CONFIG_TUNER
1072 /* radio */
1073 if (status == STATUS_RADIO)
1074 mode = 8;
1075 else if (status == STATUS_RADIO_PAUSE)
1076 mode = 9;
1077 #endif
1079 if (intval) {
1080 *intval = mode;
1083 snprintf(buf, buf_size, "%d", mode-1);
1084 return buf;
1087 case SKIN_TOKEN_REPEAT_MODE:
1088 if (intval)
1089 *intval = global_settings.repeat_mode + 1;
1090 snprintf(buf, buf_size, "%d", global_settings.repeat_mode);
1091 return buf;
1093 case SKIN_TOKEN_RTC_PRESENT:
1094 #if CONFIG_RTC
1095 return "c";
1096 #else
1097 return NULL;
1098 #endif
1100 #if CONFIG_RTC
1101 case SKIN_TOKEN_RTC_12HOUR_CFG:
1102 if (intval)
1103 *intval = global_settings.timeformat + 1;
1104 snprintf(buf, buf_size, "%d", global_settings.timeformat);
1105 return buf;
1107 case SKIN_TOKEN_RTC_DAY_OF_MONTH:
1108 /* d: day of month (01..31) */
1109 snprintf(buf, buf_size, "%02d", tm->tm_mday);
1110 if (intval)
1111 *intval = tm->tm_mday - 1;
1112 return buf;
1114 case SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
1115 /* e: day of month, blank padded ( 1..31) */
1116 snprintf(buf, buf_size, "%2d", tm->tm_mday);
1117 if (intval)
1118 *intval = tm->tm_mday - 1;
1119 return buf;
1121 case SKIN_TOKEN_RTC_HOUR_24_ZERO_PADDED:
1122 /* H: hour (00..23) */
1123 snprintf(buf, buf_size, "%02d", tm->tm_hour);
1124 if (intval)
1125 *intval = tm->tm_hour;
1126 return buf;
1128 case SKIN_TOKEN_RTC_HOUR_24:
1129 /* k: hour ( 0..23) */
1130 snprintf(buf, buf_size, "%2d", tm->tm_hour);
1131 if (intval)
1132 *intval = tm->tm_hour;
1133 return buf;
1135 case SKIN_TOKEN_RTC_HOUR_12_ZERO_PADDED:
1136 /* I: hour (01..12) */
1137 snprintf(buf, buf_size, "%02d",
1138 (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
1139 if (intval)
1140 *intval = (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12;
1141 return buf;
1143 case SKIN_TOKEN_RTC_HOUR_12:
1144 /* l: hour ( 1..12) */
1145 snprintf(buf, buf_size, "%2d",
1146 (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
1147 if (intval)
1148 *intval = (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12;
1149 return buf;
1151 case SKIN_TOKEN_RTC_MONTH:
1152 /* m: month (01..12) */
1153 if (intval)
1154 *intval = tm->tm_mon + 1;
1155 snprintf(buf, buf_size, "%02d", tm->tm_mon + 1);
1156 return buf;
1158 case SKIN_TOKEN_RTC_MINUTE:
1159 /* M: minute (00..59) */
1160 snprintf(buf, buf_size, "%02d", tm->tm_min);
1161 if (intval)
1162 *intval = tm->tm_min;
1163 return buf;
1165 case SKIN_TOKEN_RTC_SECOND:
1166 /* S: second (00..59) */
1167 snprintf(buf, buf_size, "%02d", tm->tm_sec);
1168 if (intval)
1169 *intval = tm->tm_sec;
1170 return buf;
1172 case SKIN_TOKEN_RTC_YEAR_2_DIGITS:
1173 /* y: last two digits of year (00..99) */
1174 snprintf(buf, buf_size, "%02d", tm->tm_year % 100);
1175 if (intval)
1176 *intval = tm->tm_year % 100;
1177 return buf;
1179 case SKIN_TOKEN_RTC_YEAR_4_DIGITS:
1180 /* Y: year (1970...) */
1181 snprintf(buf, buf_size, "%04d", tm->tm_year + 1900);
1182 if (intval)
1183 *intval = tm->tm_year + 1900;
1184 return buf;
1186 case SKIN_TOKEN_RTC_AM_PM_UPPER:
1187 /* p: upper case AM or PM indicator */
1188 if (intval)
1189 *intval = tm->tm_hour/12 == 0 ? 0 : 1;
1190 return tm->tm_hour/12 == 0 ? "AM" : "PM";
1192 case SKIN_TOKEN_RTC_AM_PM_LOWER:
1193 /* P: lower case am or pm indicator */
1194 if (intval)
1195 *intval = tm->tm_hour/12 == 0 ? 0 : 1;
1196 return tm->tm_hour/12 == 0 ? "am" : "pm";
1198 case SKIN_TOKEN_RTC_WEEKDAY_NAME:
1199 /* a: abbreviated weekday name (Sun..Sat) */
1200 return str(LANG_WEEKDAY_SUNDAY + tm->tm_wday);
1202 case SKIN_TOKEN_RTC_MONTH_NAME:
1203 /* b: abbreviated month name (Jan..Dec) */
1204 return str(LANG_MONTH_JANUARY + tm->tm_mon);
1206 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_MON:
1207 /* u: day of week (1..7); 1 is Monday */
1208 if (intval)
1209 *intval = (tm->tm_wday == 0) ? 7 : tm->tm_wday;
1210 snprintf(buf, buf_size, "%1d", tm->tm_wday + 1);
1211 return buf;
1213 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
1214 /* w: day of week (0..6); 0 is Sunday */
1215 if (intval)
1216 *intval = tm->tm_wday + 1;
1217 snprintf(buf, buf_size, "%1d", tm->tm_wday);
1218 return buf;
1219 #else
1220 case SKIN_TOKEN_RTC_DAY_OF_MONTH:
1221 case SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
1222 case SKIN_TOKEN_RTC_HOUR_24_ZERO_PADDED:
1223 case SKIN_TOKEN_RTC_HOUR_24:
1224 case SKIN_TOKEN_RTC_HOUR_12_ZERO_PADDED:
1225 case SKIN_TOKEN_RTC_HOUR_12:
1226 case SKIN_TOKEN_RTC_MONTH:
1227 case SKIN_TOKEN_RTC_MINUTE:
1228 case SKIN_TOKEN_RTC_SECOND:
1229 case SKIN_TOKEN_RTC_AM_PM_UPPER:
1230 case SKIN_TOKEN_RTC_AM_PM_LOWER:
1231 case SKIN_TOKEN_RTC_YEAR_2_DIGITS:
1232 return "--";
1233 case SKIN_TOKEN_RTC_YEAR_4_DIGITS:
1234 return "----";
1235 case SKIN_TOKEN_RTC_WEEKDAY_NAME:
1236 case SKIN_TOKEN_RTC_MONTH_NAME:
1237 return "---";
1238 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_MON:
1239 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
1240 return "-";
1241 #endif
1243 #ifdef HAVE_LCD_CHARCELLS
1244 case SKIN_TOKEN_PROGRESSBAR:
1246 char *end;
1247 format_player_progress(gwps);
1248 end = utf8encode(data->wps_progress_pat[0], buf);
1249 *end = '\0';
1250 return buf;
1253 case SKIN_TOKEN_PLAYER_PROGRESSBAR:
1254 if(is_new_player())
1256 /* we need 11 characters (full line) for
1257 progress-bar */
1258 strlcpy(buf, " ", buf_size);
1259 format_player_fullbar(gwps,buf,buf_size);
1260 DEBUGF("bar='%s'\n",buf);
1262 else
1264 /* Tell the user if we have an OldPlayer */
1265 strlcpy(buf, " <Old LCD> ", buf_size);
1267 return buf;
1268 #endif
1271 #ifdef HAVE_LCD_BITMAP
1272 /* peakmeter */
1273 case SKIN_TOKEN_PEAKMETER_LEFT:
1274 case SKIN_TOKEN_PEAKMETER_RIGHT:
1276 int left, right, val;
1277 peak_meter_current_vals(&left, &right);
1278 val = token->type == SKIN_TOKEN_PEAKMETER_LEFT ?
1279 left : right;
1280 val = peak_meter_scale_value(val, limit==1 ? MAX_PEAK : limit);
1281 if (intval)
1282 *intval = val;
1283 snprintf(buf, buf_size, "%d", val);
1284 data->peak_meter_enabled = true;
1285 return buf;
1287 #endif
1289 #if (CONFIG_CODEC == SWCODEC)
1290 case SKIN_TOKEN_CROSSFADE:
1291 #ifdef HAVE_CROSSFADE
1292 if (intval)
1293 *intval = global_settings.crossfade + 1;
1294 snprintf(buf, buf_size, "%d", global_settings.crossfade);
1295 #else
1296 snprintf(buf, buf_size, "%d", 0);
1297 #endif
1298 return buf;
1300 case SKIN_TOKEN_REPLAYGAIN:
1302 int val;
1304 if (global_settings.replaygain_type == REPLAYGAIN_OFF)
1305 val = 1; /* off */
1306 else
1308 int type;
1309 if (LIKELY(id3))
1310 type = get_replaygain_mode(id3->track_gain_string != NULL,
1311 id3->album_gain_string != NULL);
1312 else
1313 type = -1;
1315 if (type < 0)
1316 val = 6; /* no tag */
1317 else
1318 val = type + 2;
1320 if (global_settings.replaygain_type == REPLAYGAIN_SHUFFLE)
1321 val += 2;
1324 if (intval)
1325 *intval = val;
1327 switch (val)
1329 case 1:
1330 case 6:
1331 return "+0.00 dB";
1332 break;
1333 /* due to above, coming here with !id3 shouldn't be possible */
1334 case 2:
1335 case 4:
1336 strlcpy(buf, id3->track_gain_string, buf_size);
1337 break;
1338 case 3:
1339 case 5:
1340 strlcpy(buf, id3->album_gain_string, buf_size);
1341 break;
1343 return buf;
1345 #endif /* (CONFIG_CODEC == SWCODEC) */
1347 #if (CONFIG_CODEC != MAS3507D) && defined (HAVE_PITCHSCREEN)
1348 case SKIN_TOKEN_SOUND_PITCH:
1350 int32_t pitch = sound_get_pitch();
1351 snprintf(buf, buf_size, "%ld.%ld",
1352 pitch / PITCH_SPEED_PRECISION,
1353 (pitch % PITCH_SPEED_PRECISION) / (PITCH_SPEED_PRECISION / 10));
1355 if (intval)
1356 *intval = pitch_speed_enum(limit, pitch,
1357 PITCH_SPEED_PRECISION * 100);
1358 return buf;
1360 #endif
1362 #if (CONFIG_CODEC == SWCODEC) && defined (HAVE_PITCHSCREEN)
1363 case SKIN_TOKEN_SOUND_SPEED:
1365 int32_t pitch = sound_get_pitch();
1366 int32_t speed;
1367 if (dsp_timestretch_available())
1368 speed = GET_SPEED(pitch, dsp_get_timestretch());
1369 else
1370 speed = pitch;
1371 snprintf(buf, buf_size, "%ld.%ld",
1372 speed / PITCH_SPEED_PRECISION,
1373 (speed % PITCH_SPEED_PRECISION) / (PITCH_SPEED_PRECISION / 10));
1374 if (intval)
1375 *intval = pitch_speed_enum(limit, speed,
1376 PITCH_SPEED_PRECISION * 100);
1377 return buf;
1379 #endif
1381 case SKIN_TOKEN_MAIN_HOLD:
1382 #ifdef HAS_BUTTON_HOLD
1383 if (button_hold())
1384 #else
1385 if (is_keys_locked())
1386 #endif /*hold switch or softlock*/
1387 return "h";
1388 else
1389 return NULL;
1391 #ifdef HAS_REMOTE_BUTTON_HOLD
1392 case SKIN_TOKEN_REMOTE_HOLD:
1393 if (remote_button_hold())
1394 return "r";
1395 else
1396 return NULL;
1397 #endif
1399 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
1400 case SKIN_TOKEN_VLED_HDD:
1401 if(led_read(HZ/2))
1402 return "h";
1403 else
1404 return NULL;
1405 #endif
1406 case SKIN_TOKEN_BUTTON_VOLUME:
1407 if (global_status.last_volume_change &&
1408 TIME_BEFORE(current_tick, global_status.last_volume_change +
1409 token->value.i))
1410 return "v";
1411 return NULL;
1413 case SKIN_TOKEN_LASTTOUCH:
1415 #ifdef HAVE_TOUCHSCREEN
1416 unsigned int last_touch = touchscreen_last_touch();
1417 if (last_touch != 0xffff &&
1418 TIME_BEFORE(current_tick, token->value.i + last_touch))
1419 return "t";
1420 #endif
1422 return NULL;
1423 case SKIN_TOKEN_HAVE_TOUCH:
1424 #ifdef HAVE_TOUCHSCREEN
1425 return "t";
1426 #else
1427 return NULL;
1428 #endif
1430 case SKIN_TOKEN_SETTING:
1432 const struct settings_list *s = settings+token->value.i;
1433 if (intval)
1435 /* Handle contionals */
1436 switch (s->flags&F_T_MASK)
1438 case F_T_INT:
1439 case F_T_UINT:
1440 if (s->flags&F_T_SOUND)
1442 /* %?St|name|<min|min+1|...|max-1|max> */
1443 int sound_setting = s->sound_setting->setting;
1444 /* settings with decimals can't be used in conditionals */
1445 if (sound_numdecimals(sound_setting) == 0)
1447 *intval = (*(int*)s->setting-sound_min(sound_setting))
1448 /sound_steps(sound_setting) + 1;
1450 else
1451 *intval = -1;
1453 else if (s->flags&F_RGB)
1454 /* %?St|name|<#000000|#000001|...|#FFFFFF> */
1455 /* shouldn't overflow since colors are stored
1456 * on 16 bits ...
1457 * but this is pretty useless anyway */
1458 *intval = *(int*)s->setting + 1;
1459 else if (s->cfg_vals == NULL)
1460 /* %?St|name|<1st choice|2nd choice|...> */
1461 *intval = (*(int*)s->setting-s->int_setting->min)
1462 /s->int_setting->step + 1;
1463 else
1464 /* %?St|name|<1st choice|2nd choice|...> */
1465 /* Not sure about this one. cfg_name/vals are
1466 * indexed from 0 right? */
1467 *intval = *(int*)s->setting + 1;
1468 break;
1469 case F_T_BOOL:
1470 /* %?St|name|<if true|if false> */
1471 *intval = *(bool*)s->setting?1:2;
1472 break;
1473 case F_T_CHARPTR:
1474 case F_T_UCHARPTR:
1475 /* %?St|name|<if non empty string|if empty>
1476 * The string's emptyness discards the setting's
1477 * prefix and suffix */
1478 *intval = ((char*)s->setting)[0]?1:2;
1479 /* if there is a prefix we should ignore it here */
1480 if (s->filename_setting->prefix)
1481 return (char*)s->setting;
1482 break;
1483 default:
1484 /* This shouldn't happen ... but you never know */
1485 *intval = -1;
1486 break;
1489 /* Special handlng for filenames because we dont want to show the prefix */
1490 if ((s->flags&F_T_MASK) == F_T_UCHARPTR ||
1491 (s->flags&F_T_MASK) == F_T_UCHARPTR)
1493 if (s->filename_setting->prefix)
1494 return (char*)s->setting;
1496 cfg_to_string(token->value.i,buf,buf_size);
1497 return buf;
1499 case SKIN_TOKEN_HAVE_TUNER:
1500 #if CONFIG_TUNER
1501 if (radio_hardware_present())
1502 return "r";
1503 #endif
1504 return NULL;
1505 /* Recording tokens */
1506 case SKIN_TOKEN_HAVE_RECORDING:
1507 #ifdef HAVE_RECORDING
1508 return "r";
1509 #else
1510 return NULL;
1511 #endif
1513 #ifdef HAVE_RECORDING
1514 case SKIN_TOKEN_IS_RECORDING:
1515 if (audio_status() == AUDIO_STATUS_RECORD)
1516 return "r";
1517 return NULL;
1518 case SKIN_TOKEN_REC_FREQ: /* order from REC_FREQ_CFG_VAL_LIST */
1520 #if CONFIG_CODEC == SWCODEC
1521 unsigned long samprk;
1522 int rec_freq = global_settings.rec_frequency;
1524 #ifdef SIMULATOR
1525 samprk = 44100;
1526 #else
1527 #if defined(HAVE_SPDIF_REC)
1528 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
1530 /* Use rate in use, not current measured rate if it changed */
1531 samprk = pcm_rec_sample_rate();
1532 rec_freq = 0;
1533 while (rec_freq < SAMPR_NUM_FREQ &&
1534 audio_master_sampr_list[rec_freq] != samprk)
1536 rec_freq++;
1539 else
1540 #endif
1541 samprk = rec_freq_sampr[rec_freq];
1542 #endif /* SIMULATOR */
1543 if (intval)
1545 switch (rec_freq)
1547 REC_HAVE_96_(case REC_FREQ_96:
1548 *intval = 1;
1549 break;)
1550 REC_HAVE_88_(case REC_FREQ_88:
1551 *intval = 2;
1552 break;)
1553 REC_HAVE_64_(case REC_FREQ_64:
1554 *intval = 3;
1555 break;)
1556 REC_HAVE_48_(case REC_FREQ_48:
1557 *intval = 4;
1558 break;)
1559 REC_HAVE_44_(case REC_FREQ_44:
1560 *intval = 5;
1561 break;)
1562 REC_HAVE_32_(case REC_FREQ_32:
1563 *intval = 6;
1564 break;)
1565 REC_HAVE_24_(case REC_FREQ_24:
1566 *intval = 7;
1567 break;)
1568 REC_HAVE_22_(case REC_FREQ_22:
1569 *intval = 8;
1570 break;)
1571 REC_HAVE_16_(case REC_FREQ_16:
1572 *intval = 9;
1573 break;)
1574 REC_HAVE_12_(case REC_FREQ_12:
1575 *intval = 10;
1576 break;)
1577 REC_HAVE_11_(case REC_FREQ_11:
1578 *intval = 11;
1579 break;)
1580 REC_HAVE_8_(case REC_FREQ_8:
1581 *intval = 12;
1582 break;)
1585 snprintf(buf, buf_size, "%lu.%1lu", samprk/1000,samprk%1000);
1586 #else /* HWCODEC */
1588 static const char * const freq_strings[] =
1589 {"--", "44", "48", "32", "22", "24", "16"};
1590 int freq = 1 + global_settings.rec_frequency;
1591 #ifdef HAVE_SPDIF_REC
1592 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
1594 /* Can't measure S/PDIF sample rate on Archos/Sim yet */
1595 freq = 0;
1597 #endif /* HAVE_SPDIF_IN */
1598 if (intval)
1599 *intval = freq+1; /* so the token gets a value 1<=x<=7 */
1600 snprintf(buf, buf_size, "%s\n",
1601 freq_strings[global_settings.rec_frequency]);
1602 #endif
1603 return buf;
1605 #if CONFIG_CODEC == SWCODEC
1606 case SKIN_TOKEN_REC_ENCODER:
1608 int rec_format = global_settings.rec_format+1; /* WAV, AIFF, WV, MPEG */
1609 if (intval)
1610 *intval = rec_format;
1611 switch (rec_format)
1613 case REC_FORMAT_PCM_WAV:
1614 return "wav";
1615 case REC_FORMAT_AIFF:
1616 return "aiff";
1617 case REC_FORMAT_WAVPACK:
1618 return "wv";
1619 case REC_FORMAT_MPA_L3:
1620 return "MP3";
1621 default:
1622 return NULL;
1624 break;
1626 #endif
1627 case SKIN_TOKEN_REC_BITRATE:
1628 #if CONFIG_CODEC == SWCODEC
1629 if (global_settings.rec_format == REC_FORMAT_MPA_L3)
1631 if (intval)
1633 #if 0 /* FIXME: I dont know if this is needed? */
1634 switch (1<<global_settings.mp3_enc_config.bitrate)
1636 case MP3_BITR_CAP_8:
1637 *intval = 1;
1638 break;
1639 case MP3_BITR_CAP_16:
1640 *intval = 2;
1641 break;
1642 case MP3_BITR_CAP_24:
1643 *intval = 3;
1644 break;
1645 case MP3_BITR_CAP_32:
1646 *intval = 4;
1647 break;
1648 case MP3_BITR_CAP_40:
1649 *intval = 5;
1650 break;
1651 case MP3_BITR_CAP_48:
1652 *intval = 6;
1653 break;
1654 case MP3_BITR_CAP_56:
1655 *intval = 7;
1656 break;
1657 case MP3_BITR_CAP_64:
1658 *intval = 8;
1659 break;
1660 case MP3_BITR_CAP_80:
1661 *intval = 9;
1662 break;
1663 case MP3_BITR_CAP_96:
1664 *intval = 10;
1665 break;
1666 case MP3_BITR_CAP_112:
1667 *intval = 11;
1668 break;
1669 case MP3_BITR_CAP_128:
1670 *intval = 12;
1671 break;
1672 case MP3_BITR_CAP_144:
1673 *intval = 13;
1674 break;
1675 case MP3_BITR_CAP_160:
1676 *intval = 14;
1677 break;
1678 case MP3_BITR_CAP_192:
1679 *intval = 15;
1680 break;
1682 #endif
1683 *intval = global_settings.mp3_enc_config.bitrate+1;
1685 snprintf(buf, buf_size, "%lu", global_settings.mp3_enc_config.bitrate+1);
1686 return buf;
1688 else
1689 return NULL; /* Fixme later */
1690 #else /* CONFIG_CODEC == HWCODEC */
1691 if (intval)
1692 *intval = global_settings.rec_quality+1;
1693 snprintf(buf, buf_size, "%d", global_settings.rec_quality);
1694 return buf;
1695 #endif
1696 case SKIN_TOKEN_REC_MONO:
1697 if (!global_settings.rec_channels)
1698 return "m";
1699 return NULL;
1701 case SKIN_TOKEN_REC_SECONDS:
1703 int time = (audio_recorded_time() / HZ) % 60;
1704 if (intval)
1705 *intval = time;
1706 snprintf(buf, buf_size, "%02d", time);
1707 return buf;
1709 case SKIN_TOKEN_REC_MINUTES:
1711 int time = (audio_recorded_time() / HZ) / 60;
1712 if (intval)
1713 *intval = time;
1714 snprintf(buf, buf_size, "%02d", time);
1715 return buf;
1717 case SKIN_TOKEN_REC_HOURS:
1719 int time = (audio_recorded_time() / HZ) / 3600;
1720 if (intval)
1721 *intval = time;
1722 snprintf(buf, buf_size, "%02d", time);
1723 return buf;
1726 #endif /* HAVE_RECORDING */
1728 case SKIN_TOKEN_CURRENT_SCREEN:
1730 int curr_screen = current_screen();
1732 #ifdef HAVE_RECORDING
1733 /* override current_screen() for recording screen since it may
1734 * be entered from the radio screen */
1735 if (in_recording_screen())
1736 curr_screen = GO_TO_RECSCREEN;
1737 #endif
1739 switch (curr_screen)
1741 case GO_TO_WPS:
1742 curr_screen = 2;
1743 break;
1744 #ifdef HAVE_RECORDING
1745 case GO_TO_RECSCREEN:
1746 curr_screen = 3;
1747 break;
1748 #endif
1749 #if CONFIG_TUNER
1750 case GO_TO_FM:
1751 curr_screen = 4;
1752 break;
1753 #endif
1754 case GO_TO_PLAYLIST_VIEWER:
1755 curr_screen = 5;
1756 break;
1757 default: /* lists */
1758 curr_screen = 1;
1759 break;
1761 if (intval)
1763 *intval = curr_screen;
1765 snprintf(buf, buf_size, "%d", curr_screen);
1766 return buf;
1769 case SKIN_TOKEN_LANG_IS_RTL:
1770 return lang_is_rtl() ? "r" : NULL;
1772 default:
1773 return NULL;