1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
24 #include "string-extra.h"
29 #include "settings_list.h"
30 #include "rbunicode.h"
31 #include "timefuncs.h"
34 #include "powermgmt.h"
38 #include "replaygain.h"
39 #include "core_alloc.h"
40 #ifdef HAVE_LCD_CHARCELLS
47 #ifdef HAVE_LCD_BITMAP
48 #include "peakmeter.h"
54 #if CONFIG_CODEC == SWCODEC
61 #include "wps_internals.h"
62 #include "skin_engine.h"
63 #include "statusbar-skinned.h"
64 #include "root_menu.h"
66 #include "recording.h"
67 #include "pcm_record.h"
77 #define NOINLINE __attribute__ ((noinline))
79 extern struct wps_state wps_state
;
81 static const char* get_codectype(const struct mp3entry
* id3
)
83 if (id3
&& id3
->codectype
< AFMT_NUM_CODECS
) {
84 return audio_formats
[id3
->codectype
].label
;
90 /* Extract a part from a path.
92 * buf - buffer extract part to.
93 * buf_size - size of buffer.
94 * path - path to extract from.
95 * level - what to extract. 0 is file name, 1 is parent of file, 2 is
96 * parent of parent, etc.
98 * Returns buf if the desired level was found, NULL otherwise.
100 char* get_dir(char* buf
, int buf_size
, const char* path
, int level
)
103 const char* last_sep
;
106 sep
= path
+ strlen(path
);
121 if (level
|| (last_sep
<= sep
))
124 len
= MIN(last_sep
- sep
, buf_size
- 1);
125 strlcpy(buf
, sep
+ 1, len
+ 1);
129 #if (CONFIG_CODEC != MAS3507D) && defined (HAVE_PITCHSCREEN)
130 /* A helper to determine the enum value for pitch/speed.
132 When there are two choices (i.e. boolean), return 1 if the value is
133 different from normal value and 2 if the value is the same as the
134 normal value. E.g. "%?Sp<%Sp>" would show the pitch only when
135 playing at a modified pitch.
137 When there are more than two choices (i.e. enum), the left half of
138 the choices are to show 0..normal range, and the right half of the
139 choices are to show values over that. The last entry is used when
140 it is set to the normal setting, following the rockbox convention
141 to use the last entry for special values.
145 2 items: %?Sp<0..99 or 101..infinity|100>
146 3 items: %?Sp<0..99|101..infinity|100>
147 4 items: %?Sp<0..49|50..99|101..infinity|100>
148 5 items: %?Sp<0..49|50..99|101..149|150..infinity|100>
149 6 items: %?Sp<0..33|34..66|67..99|101..133|134..infinity|100>
150 7 items: %?Sp<0..33|34..66|67..99|101..133|134..167|167..infinity|100>
152 static int pitch_speed_enum(int range
, int32_t val
, int32_t normval
)
158 return (val
== normval
) + 1;
162 n
= (center
* val
) / normval
+ 1;
163 return (range
<= n
) ? (range
- 1) : n
;
167 const char *get_cuesheetid3_token(struct wps_token
*token
, struct mp3entry
*id3
,
168 int offset_tracks
, char *buf
, int buf_size
)
170 struct cuesheet
*cue
= id3
?id3
->cuesheet
:NULL
;
171 if (!cue
|| !cue
->curr_track
)
174 struct cue_track_info
*track
= cue
->curr_track
;
177 if (cue
->curr_track_idx
+offset_tracks
< cue
->track_count
)
178 track
+=offset_tracks
;
184 case SKIN_TOKEN_METADATA_ARTIST
:
185 return *track
->performer
? track
->performer
: NULL
;
186 case SKIN_TOKEN_METADATA_COMPOSER
:
187 return *track
->songwriter
? track
->songwriter
: NULL
;
188 case SKIN_TOKEN_METADATA_ALBUM
:
189 return *cue
->title
? cue
->title
: NULL
;
190 case SKIN_TOKEN_METADATA_ALBUM_ARTIST
:
191 return *cue
->performer
? cue
->performer
: NULL
;
192 case SKIN_TOKEN_METADATA_TRACK_TITLE
:
193 return *track
->title
? track
->title
: NULL
;
194 case SKIN_TOKEN_METADATA_TRACK_NUMBER
:
195 snprintf(buf
, buf_size
, "%d/%d",
196 cue
->curr_track_idx
+offset_tracks
+1, cue
->track_count
);
204 static const char* get_filename_token(struct wps_token
*token
, char* filename
,
205 char *buf
, int buf_size
)
211 case SKIN_TOKEN_FILE_PATH
:
213 case SKIN_TOKEN_FILE_NAME
:
214 if (get_dir(buf
, buf_size
, filename
, 0)) {
215 /* Remove extension */
216 char* sep
= strrchr(buf
, '.');
223 case SKIN_TOKEN_FILE_NAME_WITH_EXTENSION
:
224 return get_dir(buf
, buf_size
, filename
, 0);
225 case SKIN_TOKEN_FILE_DIRECTORY
:
226 return get_dir(buf
, buf_size
, filename
, token
->value
.i
);
234 /* All tokens which only need the info to return a value go in here */
235 const char *get_id3_token(struct wps_token
*token
, struct mp3entry
*id3
,
236 char *filename
, char *buf
, int buf_size
, int limit
, int *intval
)
238 struct wps_state
*state
= &wps_state
;
241 unsigned long length
= id3
->length
;
242 unsigned long elapsed
= id3
->elapsed
+ state
->ff_rewind_count
;
245 case SKIN_TOKEN_METADATA_ARTIST
:
247 case SKIN_TOKEN_METADATA_COMPOSER
:
248 return id3
->composer
;
249 case SKIN_TOKEN_METADATA_ALBUM
:
251 case SKIN_TOKEN_METADATA_ALBUM_ARTIST
:
252 return id3
->albumartist
;
253 case SKIN_TOKEN_METADATA_GROUPING
:
254 return id3
->grouping
;
255 case SKIN_TOKEN_METADATA_GENRE
:
256 return id3
->genre_string
;
257 case SKIN_TOKEN_METADATA_DISC_NUMBER
:
258 if (id3
->disc_string
)
259 return id3
->disc_string
;
261 snprintf(buf
, buf_size
, "%d", id3
->discnum
);
265 case SKIN_TOKEN_METADATA_TRACK_NUMBER
:
266 if (id3
->track_string
)
267 return id3
->track_string
;
269 snprintf(buf
, buf_size
, "%d", id3
->tracknum
);
273 case SKIN_TOKEN_METADATA_TRACK_TITLE
:
275 case SKIN_TOKEN_METADATA_VERSION
:
276 switch (id3
->id3version
)
292 case SKIN_TOKEN_METADATA_YEAR
:
293 if( id3
->year_string
)
294 return id3
->year_string
;
296 snprintf(buf
, buf_size
, "%d", id3
->year
);
300 case SKIN_TOKEN_METADATA_COMMENT
:
302 case SKIN_TOKEN_FILE_BITRATE
:
304 snprintf(buf
, buf_size
, "%d", id3
->bitrate
);
308 case SKIN_TOKEN_TRACK_TIME_ELAPSED
:
309 format_time(buf
, buf_size
, elapsed
);
312 case SKIN_TOKEN_TRACK_TIME_REMAINING
:
313 format_time(buf
, buf_size
, length
- elapsed
);
316 case SKIN_TOKEN_TRACK_LENGTH
:
317 format_time(buf
, buf_size
, length
);
320 case SKIN_TOKEN_TRACK_ELAPSED_PERCENT
:
326 if (limit
== TOKEN_VALUE_ONLY
)
327 limit
= 100; /* make it a percentage */
328 *intval
= limit
* elapsed
/ length
+ 1;
330 snprintf(buf
, buf_size
, "%lu", 100 * elapsed
/ length
);
333 case SKIN_TOKEN_TRACK_STARTING
:
335 unsigned long time
= token
->value
.i
* (HZ
/TIMEOUT_UNIT
);
340 case SKIN_TOKEN_TRACK_ENDING
:
342 unsigned long time
= token
->value
.i
* (HZ
/TIMEOUT_UNIT
);
343 if (length
- elapsed
< time
)
348 case SKIN_TOKEN_FILE_CODEC
:
351 if(id3
->codectype
== AFMT_UNKNOWN
)
352 *intval
= AFMT_NUM_CODECS
;
354 *intval
= id3
->codectype
;
356 return get_codectype(id3
);
358 case SKIN_TOKEN_FILE_FREQUENCY
:
359 snprintf(buf
, buf_size
, "%ld", id3
->frequency
);
361 case SKIN_TOKEN_FILE_FREQUENCY_KHZ
:
362 /* ignore remainders < 100, so 22050 Hz becomes just 22k */
363 if ((id3
->frequency
% 1000) < 100)
364 snprintf(buf
, buf_size
, "%ld", id3
->frequency
/ 1000);
366 snprintf(buf
, buf_size
, "%ld.%lu",
367 id3
->frequency
/ 1000,
368 (id3
->frequency
% 1000) / 100);
370 case SKIN_TOKEN_FILE_VBR
:
371 return (id3
->vbr
) ? "(avg)" : NULL
;
372 case SKIN_TOKEN_FILE_SIZE
:
373 snprintf(buf
, buf_size
, "%ld", id3
->filesize
/ 1024);
377 case SKIN_TOKEN_DATABASE_PLAYCOUNT
:
379 *intval
= id3
->playcount
+ 1;
380 snprintf(buf
, buf_size
, "%ld", id3
->playcount
);
382 case SKIN_TOKEN_DATABASE_RATING
:
384 *intval
= id3
->rating
+ 1;
385 snprintf(buf
, buf_size
, "%d", id3
->rating
);
387 case SKIN_TOKEN_DATABASE_AUTOSCORE
:
389 *intval
= id3
->score
+ 1;
390 snprintf(buf
, buf_size
, "%d", id3
->score
);
395 return get_filename_token(token
, id3
->path
, buf
, buf_size
);
398 else /* id3 == NULL, handle the error based on the expected return type */
402 /* Most tokens expect NULL on error so leave that for the default case,
403 * The ones that expect "0" need to be handled */
404 case SKIN_TOKEN_FILE_FREQUENCY
:
405 case SKIN_TOKEN_FILE_FREQUENCY_KHZ
:
406 case SKIN_TOKEN_FILE_SIZE
:
408 case SKIN_TOKEN_DATABASE_PLAYCOUNT
:
409 case SKIN_TOKEN_DATABASE_RATING
:
410 case SKIN_TOKEN_DATABASE_AUTOSCORE
:
416 return get_filename_token(token
, filename
, buf
, buf_size
);
424 /* Formats the frequency (specified in Hz) in MHz, */
425 /* with one or two digits after the decimal point -- */
426 /* depending on the frequency changing step. */
428 static char *format_freq_MHz(int freq
, int freq_step
, char *buf
, int buf_size
)
432 if (freq_step
< 100000)
434 /* Format with two digits after decimal point */
440 /* Format with one digit after decimal point */
444 div
= 1000000 / scale
;
446 snprintf(buf
, buf_size
, fmt
, freq
/div
, freq
%div
);
451 /* Tokens which are really only used by the radio screen go in here */
452 const char *get_radio_token(struct wps_token
*token
, int preset_offset
,
453 char *buf
, int buf_size
, int limit
, int *intval
)
455 const struct fm_region_data
*region_data
=
456 &(fm_region_data
[global_settings
.fm_region
]);
460 /* Radio/tuner tokens */
461 case SKIN_TOKEN_TUNER_TUNED
:
462 if (tuner_get(RADIO_TUNED
))
465 case SKIN_TOKEN_TUNER_SCANMODE
:
466 if (radio_scan_mode())
469 case SKIN_TOKEN_TUNER_STEREO
:
470 if (radio_is_stereo())
473 case SKIN_TOKEN_TUNER_MINFREQ
: /* changes based on "region" */
474 return format_freq_MHz(region_data
->freq_min
,
475 region_data
->freq_step
, buf
, buf_size
);
476 case SKIN_TOKEN_TUNER_MAXFREQ
: /* changes based on "region" */
477 return format_freq_MHz(region_data
->freq_max
,
478 region_data
->freq_step
, buf
, buf_size
);
479 case SKIN_TOKEN_TUNER_CURFREQ
:
480 return format_freq_MHz(radio_current_frequency(),
481 region_data
->freq_step
, buf
, buf_size
);
482 #ifdef HAVE_RADIO_RSSI
483 case SKIN_TOKEN_TUNER_RSSI
:
484 snprintf(buf
, buf_size
, "%d",tuner_get(RADIO_RSSI
));
487 int val
= tuner_get(RADIO_RSSI
);
488 int min
= tuner_get(RADIO_RSSI_MIN
);
489 int max
= tuner_get(RADIO_RSSI_MAX
);
490 if (limit
== TOKEN_VALUE_ONLY
)
496 *intval
= 1+(limit
-1)*(val
-min
)/(max
-1-min
);
500 case SKIN_TOKEN_TUNER_RSSI_MIN
:
501 snprintf(buf
, buf_size
, "%d",tuner_get(RADIO_RSSI_MIN
));
503 case SKIN_TOKEN_TUNER_RSSI_MAX
:
504 snprintf(buf
, buf_size
, "%d",tuner_get(RADIO_RSSI_MAX
));
507 case SKIN_TOKEN_PRESET_NAME
:
508 case SKIN_TOKEN_PRESET_FREQ
:
509 case SKIN_TOKEN_PRESET_ID
:
511 int preset_count
= radio_preset_count();
512 int cur_preset
= radio_current_preset();
513 if (preset_count
== 0 || cur_preset
< 0)
515 int preset
= cur_preset
+ preset_offset
;
516 /* make sure it's in the valid range */
517 preset
%= preset_count
;
519 preset
+= preset_count
;
520 if (token
->type
== SKIN_TOKEN_PRESET_NAME
)
521 snprintf(buf
, buf_size
, "%s", radio_get_preset(preset
)->name
);
522 else if (token
->type
== SKIN_TOKEN_PRESET_FREQ
)
523 format_freq_MHz(radio_get_preset(preset
)->frequency
,
524 region_data
->freq_step
, buf
, buf_size
);
526 snprintf(buf
, buf_size
, "%d", preset
+ 1);
529 case SKIN_TOKEN_PRESET_COUNT
:
530 snprintf(buf
, buf_size
, "%d", radio_preset_count());
532 *intval
= radio_preset_count();
534 case SKIN_TOKEN_HAVE_RDS
:
537 case SKIN_TOKEN_RDS_NAME
:
538 return tuner_get_rds_info(RADIO_RDS_NAME
);
539 case SKIN_TOKEN_RDS_TEXT
:
540 return tuner_get_rds_info(RADIO_RDS_TEXT
);
542 return NULL
; /* end of the SKIN_TOKEN_HAVE_RDS case */
543 #endif /* HAVE_RDS_CAP */
551 static struct mp3entry
* get_mp3entry_from_offset(int offset
, char **filename
)
553 struct mp3entry
* pid3
= NULL
;
554 struct wps_state
*state
= skin_get_global_state();
555 struct cuesheet
*cue
= state
->id3
? state
->id3
->cuesheet
: NULL
;
556 const char *fname
= NULL
;
557 if (cue
&& cue
->curr_track_idx
+ offset
< cue
->track_count
)
559 else if (offset
== 0)
561 else if (offset
== 1)
565 static char filename_buf
[MAX_PATH
+ 1];
566 fname
= playlist_peek(offset
, filename_buf
, sizeof(filename_buf
));
567 *filename
= (char*)fname
;
568 #if CONFIG_CODEC == SWCODEC
569 static struct mp3entry tempid3
;
571 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
572 tagcache_fill_tags(&tempid3
, fname
) ||
574 audio_peek_track(&tempid3
, offset
)
584 #ifdef HAVE_LCD_CHARCELLS
585 static void format_player_progress(struct gui_wps
*gwps
)
587 struct wps_state
*state
= skin_get_global_state();
588 struct screen
*display
= gwps
->display
;
589 unsigned char progress_pattern
[7];
594 if (LIKELY(state
->id3
))
596 elapsed
= state
->id3
->elapsed
;
597 length
= state
->id3
->length
;
606 pos
= 36 * (elapsed
+ state
->ff_rewind_count
) / length
;
608 for (i
= 0; i
< 7; i
++, pos
-= 5)
611 progress_pattern
[i
] = 0x1fu
;
613 progress_pattern
[i
] = 0x00u
;
615 progress_pattern
[i
] = 0x1fu
>> pos
;
618 display
->define_pattern(gwps
->data
->wps_progress_pat
[0], progress_pattern
);
621 static void format_player_fullbar(struct gui_wps
*gwps
, char* buf
, int buf_size
)
623 static const unsigned char numbers
[10][4] = {
624 {0x0e, 0x0a, 0x0a, 0x0e}, /* 0 */
625 {0x04, 0x0c, 0x04, 0x04}, /* 1 */
626 {0x0e, 0x02, 0x04, 0x0e}, /* 2 */
627 {0x0e, 0x02, 0x06, 0x0e}, /* 3 */
628 {0x08, 0x0c, 0x0e, 0x04}, /* 4 */
629 {0x0e, 0x0c, 0x02, 0x0c}, /* 5 */
630 {0x0e, 0x08, 0x0e, 0x0e}, /* 6 */
631 {0x0e, 0x02, 0x04, 0x08}, /* 7 */
632 {0x0e, 0x0e, 0x0a, 0x0e}, /* 8 */
633 {0x0e, 0x0e, 0x02, 0x0e} /* 9 */
636 struct wps_state
*state
= skin_get_global_state();
637 struct screen
*display
= gwps
->display
;
638 struct wps_data
*data
= gwps
->data
;
639 unsigned char progress_pattern
[7];
649 if (LIKELY(state
->id3
))
651 elapsed
= state
->id3
->elapsed
;
652 length
= state
->id3
->length
;
660 if (buf_size
< 34) /* worst case: 11x UTF-8 char + \0 */
663 time
= elapsed
+ state
->ff_rewind_count
;
665 pos
= 55 * time
/ length
;
667 memset(timestr
, 0, sizeof(timestr
));
668 format_time(timestr
, sizeof(timestr
)-2, time
);
669 timestr
[strlen(timestr
)] = ':'; /* always safe */
671 for (i
= 0; i
< 11; i
++, pos
-= 5)
674 memset(progress_pattern
, 0, sizeof(progress_pattern
));
676 if ((digit
= timestr
[time_idx
]))
681 if (timestr
[time_idx
+ 1] == ':') /* ones, left aligned */
683 memcpy(progress_pattern
, numbers
[digit
], 4);
686 else /* tens, shifted right */
688 for (j
= 0; j
< 4; j
++)
689 progress_pattern
[j
] = numbers
[digit
][j
] >> 1;
691 if (time_idx
> 0) /* not the first group, add colon in front */
693 progress_pattern
[1] |= 0x10u
;
694 progress_pattern
[3] |= 0x10u
;
700 progress_pattern
[5] = progress_pattern
[6] = 0x1fu
;
703 if (pos
> 0 && pos
< 5)
706 progress_pattern
[5] = progress_pattern
[6] = (~0x1fu
>> pos
) & 0x1fu
;
709 if (softchar
&& pat_idx
< 8)
711 display
->define_pattern(data
->wps_progress_pat
[pat_idx
],
713 buf
= utf8encode(data
->wps_progress_pat
[pat_idx
], buf
);
717 buf
= utf8encode(' ', buf
);
719 buf
= utf8encode(0xe115, buf
); /* 2/7 _ */
724 #endif /* HAVE_LCD_CHARCELLS */
726 /* Don't inline this; it was broken out of get_token_value to reduce stack
729 static const char* NOINLINE
get_lif_token_value(struct gui_wps
*gwps
,
730 struct logical_if
*lif
,
731 int offset
, char *buf
,
734 int a
= lif
->num_options
;
736 struct wps_token
*liftoken
= SKINOFFSETTOPTR(get_skin_buffer(gwps
->data
), lif
->token
);
737 const char* out_text
= get_token_value(gwps
, liftoken
, offset
, buf
, buf_size
, &a
);
738 if (a
== -1 && liftoken
->type
!= SKIN_TOKEN_VOLUME
)
739 a
= (out_text
&& *out_text
) ? 1 : 0;
740 switch (lif
->operand
.type
)
744 char *cmp
= SKINOFFSETTOPTR(get_skin_buffer(gwps
->data
), lif
->operand
.data
.text
);
745 if (out_text
== NULL
)
747 a
= strcmp(out_text
, cmp
);
753 b
= lif
->operand
.data
.number
;
757 char temp_buf
[MAX_PATH
];
759 struct skin_element
*element
= SKINOFFSETTOPTR(get_skin_buffer(gwps
->data
), lif
->operand
.data
.code
);
760 struct wps_token
*token
= SKINOFFSETTOPTR(get_skin_buffer(gwps
->data
), element
->data
);
761 b
= lif
->num_options
;
762 outb
= get_token_value(gwps
, token
, offset
, temp_buf
,
763 sizeof(temp_buf
), &b
);
764 if (b
== -1 && liftoken
->type
!= SKIN_TOKEN_VOLUME
)
766 if (!out_text
|| !outb
)
767 return (lif
->op
== IF_EQUALS
) ? NULL
: "neq";
768 bool equal
= strcmp(out_text
, outb
) == 0;
769 if (lif
->op
== IF_EQUALS
)
770 return equal
? "eq" : NULL
;
771 else if (lif
->op
== IF_NOTEQUALS
)
772 return !equal
? "neq" : NULL
;
774 b
= (outb
&& *outb
) ? 1 : 0;
785 return a
== b
? "eq" : NULL
;
787 return a
!= b
? "neq" : NULL
;
789 return a
< b
? "lt" : NULL
;
791 return a
<= b
? "lte" : NULL
;
793 return a
> b
? "gt" : NULL
;
794 case IF_GREATERTHAN_EQ
:
795 return a
>= b
? "gte" : NULL
;
800 /* Return the tags value as text. buf should be used as temp storage if needed.
802 intval is used with conditionals/enums: when this function is called,
803 intval should contain the number of options in the conditional/enum.
804 When this function returns, intval is -1 if the tag is non numeric or,
805 if the tag is numeric, *intval is the enum case we want to go to (between 1
806 and the original value of *intval, inclusive).
807 When not treating a conditional/enum, intval should be NULL.
809 const char *get_token_value(struct gui_wps
*gwps
,
810 struct wps_token
*token
, int offset
,
811 char *buf
, int buf_size
,
817 struct wps_data
*data
= gwps
->data
;
818 struct wps_state
*state
= skin_get_global_state();
819 struct mp3entry
*id3
; /* Think very carefully about using this.
820 maybe get_id3_token() is the better place? */
821 const char *out_text
= NULL
;
822 char *filename
= NULL
;
827 id3
= get_mp3entry_from_offset(token
->next
? 1: offset
, &filename
);
829 filename
= id3
->path
;
832 struct tm
* tm
= NULL
;
834 /* if the token is an RTC one, update the time
835 and do the necessary checks */
836 if (token
->type
>= SKIN_TOKENS_RTC_BEGIN
837 && token
->type
<= SKIN_TOKENS_RTC_END
)
853 if (id3
&& id3
== state
->id3
&& id3
->cuesheet
)
855 out_text
= get_cuesheetid3_token(token
, id3
,
856 token
->next
?1:offset
, buf
, buf_size
);
860 out_text
= get_id3_token(token
, id3
, filename
, buf
, buf_size
, limit
, intval
);
864 out_text
= get_radio_token(token
, offset
, buf
, buf_size
, limit
, intval
);
871 case SKIN_TOKEN_LOGICAL_IF
:
873 struct logical_if
*lif
= SKINOFFSETTOPTR(get_skin_buffer(data
), token
->value
.data
);
874 return get_lif_token_value(gwps
, lif
, offset
, buf
, buf_size
);
877 case SKIN_TOKEN_SUBSTRING
:
879 struct substring
*ss
= SKINOFFSETTOPTR(get_skin_buffer(data
), token
->value
.data
);
880 const char *token_val
= get_token_value(gwps
,
881 SKINOFFSETTOPTR(get_skin_buffer(data
), ss
->token
), offset
,
882 buf
, buf_size
, intval
);
885 int start_byte
, end_byte
, byte_len
;
886 int utf8_len
= utf8length(token_val
);
888 if (utf8_len
< ss
->start
)
891 start_byte
= utf8seek(token_val
, ss
->start
);
893 if (ss
->length
< 0 || (ss
->start
+ ss
->length
) > utf8_len
)
894 end_byte
= strlen(token_val
);
896 end_byte
= utf8seek(token_val
, ss
->start
+ ss
->length
);
898 byte_len
= end_byte
- start_byte
;
900 if (token_val
!= buf
)
901 memcpy(buf
, &token_val
[start_byte
], byte_len
);
903 buf
= &buf
[start_byte
];
905 buf
[byte_len
] = '\0';
912 case SKIN_TOKEN_CHARACTER
:
913 if (token
->value
.c
== '\n')
915 return &(token
->value
.c
);
917 case SKIN_TOKEN_STRING
:
918 return (char*)SKINOFFSETTOPTR(get_skin_buffer(data
), token
->value
.data
);
920 case SKIN_TOKEN_TRANSLATEDSTRING
:
921 return (char*)P2STR(ID2P(token
->value
.i
));
923 case SKIN_TOKEN_PLAYLIST_ENTRIES
:
924 snprintf(buf
, buf_size
, "%d", playlist_amount());
926 *intval
= playlist_amount();
928 #ifdef HAVE_LCD_BITMAP
929 case SKIN_TOKEN_LIST_TITLE_TEXT
:
930 return sb_get_title(gwps
->display
->screen_type
);
931 case SKIN_TOKEN_LIST_TITLE_ICON
:
933 *intval
= sb_get_icon(gwps
->display
->screen_type
);
934 snprintf(buf
, buf_size
, "%d",sb_get_icon(gwps
->display
->screen_type
));
936 case SKIN_TOKEN_LIST_ITEM_TEXT
:
938 struct listitem
*li
= (struct listitem
*)SKINOFFSETTOPTR(get_skin_buffer(data
), token
->value
.data
);
939 return skinlist_get_item_text(li
->offset
, li
->wrap
, buf
, buf_size
);
941 case SKIN_TOKEN_LIST_ITEM_NUMBER
:
943 *intval
= skinlist_get_item_number() + 1;
944 snprintf(buf
, buf_size
, "%d",skinlist_get_item_number() + 1);
946 case SKIN_TOKEN_LIST_ITEM_IS_SELECTED
:
947 return skinlist_is_selected_item()?"s":"";
948 case SKIN_TOKEN_LIST_ITEM_ICON
:
950 struct listitem
*li
= (struct listitem
*)SKINOFFSETTOPTR(get_skin_buffer(data
), token
->value
.data
);
951 int icon
= skinlist_get_item_icon(li
->offset
, li
->wrap
);
954 snprintf(buf
, buf_size
, "%d", icon
);
957 case SKIN_TOKEN_LIST_NEEDS_SCROLLBAR
:
958 return skinlist_needs_scrollbar(gwps
->display
->screen_type
) ? "s" : "";
960 case SKIN_TOKEN_PLAYLIST_NAME
:
961 return playlist_name(NULL
, buf
, buf_size
);
963 case SKIN_TOKEN_PLAYLIST_POSITION
:
964 snprintf(buf
, buf_size
, "%d", playlist_get_display_index()+offset
);
966 *intval
= playlist_get_display_index()+offset
;
969 case SKIN_TOKEN_PLAYLIST_SHUFFLE
:
970 if ( global_settings
.playlist_shuffle
)
976 case SKIN_TOKEN_VOLUME
:
977 snprintf(buf
, buf_size
, "%d", global_settings
.volume
);
980 int minvol
= sound_min(SOUND_VOLUME
);
981 if (limit
== TOKEN_VALUE_ONLY
)
983 *intval
= global_settings
.volume
;
985 else if (global_settings
.volume
== minvol
)
989 else if (global_settings
.volume
== 0)
993 else if (global_settings
.volume
> 0)
999 *intval
= (limit
-3) * (global_settings
.volume
- minvol
- 1)
1000 / (-1 - minvol
) + 2;
1004 #ifdef HAVE_ALBUMART
1005 case SKIN_TOKEN_ALBUMART_FOUND
:
1006 if (SKINOFFSETTOPTR(get_skin_buffer(data
), data
->albumart
))
1009 handle
= playback_current_aa_hid(data
->playback_aa_slot
);
1011 if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF
))
1013 struct skin_albumart
*aa
= SKINOFFSETTOPTR(get_skin_buffer(data
), data
->albumart
);
1014 struct dim dim
= {aa
->width
, aa
->height
};
1015 handle
= radio_get_art_hid(&dim
);
1024 case SKIN_TOKEN_BATTERY_PERCENT
:
1026 int l
= battery_level();
1030 if (limit
== TOKEN_VALUE_ONLY
)
1036 limit
= MAX(limit
, 3);
1038 /* First enum is used for "unknown level",
1039 * last enum is used for 100%.
1041 *intval
= (limit
- 2) * l
/ 100 + 2;
1049 snprintf(buf
, buf_size
, "%d", l
);
1056 case SKIN_TOKEN_BATTERY_VOLTS
:
1058 unsigned int v
= battery_voltage();
1059 snprintf(buf
, buf_size
, "%d.%02d", v
/ 1000, (v
% 1000) / 10);
1063 case SKIN_TOKEN_BATTERY_TIME
:
1065 int t
= battery_time();
1067 snprintf(buf
, buf_size
, "%dh %dm", t
/ 60, t
% 60);
1074 case SKIN_TOKEN_BATTERY_CHARGER_CONNECTED
:
1076 if(charger_input_state
==CHARGER
)
1082 #if CONFIG_CHARGING >= CHARGING_MONITOR
1083 case SKIN_TOKEN_BATTERY_CHARGING
:
1085 if (charge_state
== CHARGING
|| charge_state
== TOPOFF
) {
1092 #ifdef HAVE_USB_POWER
1093 case SKIN_TOKEN_USB_POWERED
:
1098 case SKIN_TOKEN_BATTERY_SLEEPTIME
:
1100 if (get_sleep_timer() == 0)
1104 format_time(buf
, buf_size
, get_sleep_timer() * 1000);
1109 case SKIN_TOKEN_PLAYBACK_STATUS
:
1111 int status
= current_playmode();
1113 int mode
= 1; /* stop */
1114 if (status
== STATUS_PLAY
)
1115 mode
= 2; /* play */
1116 if (state
->is_fading
||
1117 (status
== STATUS_PAUSE
&& !status_get_ffmode()))
1118 mode
= 3; /* pause */
1121 if (status_get_ffmode() == STATUS_FASTFORWARD
)
1123 if (status_get_ffmode() == STATUS_FASTBACKWARD
)
1126 #ifdef HAVE_RECORDING
1128 if (status
== STATUS_RECORD
)
1130 else if (status
== STATUS_RECORD_PAUSE
)
1135 if (status
== STATUS_RADIO
)
1137 else if (status
== STATUS_RADIO_PAUSE
)
1145 snprintf(buf
, buf_size
, "%d", mode
-1);
1149 case SKIN_TOKEN_REPEAT_MODE
:
1151 *intval
= global_settings
.repeat_mode
+ 1;
1152 snprintf(buf
, buf_size
, "%d", global_settings
.repeat_mode
);
1155 case SKIN_TOKEN_RTC_PRESENT
:
1163 case SKIN_TOKEN_RTC_12HOUR_CFG
:
1165 *intval
= global_settings
.timeformat
+ 1;
1166 snprintf(buf
, buf_size
, "%d", global_settings
.timeformat
);
1169 case SKIN_TOKEN_RTC_DAY_OF_MONTH
:
1170 /* d: day of month (01..31) */
1171 snprintf(buf
, buf_size
, "%02d", tm
->tm_mday
);
1173 *intval
= tm
->tm_mday
- 1;
1176 case SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED
:
1177 /* e: day of month, blank padded ( 1..31) */
1178 snprintf(buf
, buf_size
, "%2d", tm
->tm_mday
);
1180 *intval
= tm
->tm_mday
- 1;
1183 case SKIN_TOKEN_RTC_HOUR_24_ZERO_PADDED
:
1184 /* H: hour (00..23) */
1185 snprintf(buf
, buf_size
, "%02d", tm
->tm_hour
);
1187 *intval
= tm
->tm_hour
;
1190 case SKIN_TOKEN_RTC_HOUR_24
:
1191 /* k: hour ( 0..23) */
1192 snprintf(buf
, buf_size
, "%2d", tm
->tm_hour
);
1194 *intval
= tm
->tm_hour
;
1197 case SKIN_TOKEN_RTC_HOUR_12_ZERO_PADDED
:
1198 /* I: hour (01..12) */
1199 snprintf(buf
, buf_size
, "%02d",
1200 (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12);
1202 *intval
= (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12;
1205 case SKIN_TOKEN_RTC_HOUR_12
:
1206 /* l: hour ( 1..12) */
1207 snprintf(buf
, buf_size
, "%2d",
1208 (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12);
1210 *intval
= (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12;
1213 case SKIN_TOKEN_RTC_MONTH
:
1214 /* m: month (01..12) */
1216 *intval
= tm
->tm_mon
+ 1;
1217 snprintf(buf
, buf_size
, "%02d", tm
->tm_mon
+ 1);
1220 case SKIN_TOKEN_RTC_MINUTE
:
1221 /* M: minute (00..59) */
1222 snprintf(buf
, buf_size
, "%02d", tm
->tm_min
);
1224 *intval
= tm
->tm_min
;
1227 case SKIN_TOKEN_RTC_SECOND
:
1228 /* S: second (00..59) */
1229 snprintf(buf
, buf_size
, "%02d", tm
->tm_sec
);
1231 *intval
= tm
->tm_sec
;
1234 case SKIN_TOKEN_RTC_YEAR_2_DIGITS
:
1235 /* y: last two digits of year (00..99) */
1236 snprintf(buf
, buf_size
, "%02d", tm
->tm_year
% 100);
1238 *intval
= tm
->tm_year
% 100;
1241 case SKIN_TOKEN_RTC_YEAR_4_DIGITS
:
1242 /* Y: year (1970...) */
1243 snprintf(buf
, buf_size
, "%04d", tm
->tm_year
+ 1900);
1245 *intval
= tm
->tm_year
+ 1900;
1248 case SKIN_TOKEN_RTC_AM_PM_UPPER
:
1249 /* p: upper case AM or PM indicator */
1251 *intval
= tm
->tm_hour
/12 == 0 ? 0 : 1;
1252 return tm
->tm_hour
/12 == 0 ? "AM" : "PM";
1254 case SKIN_TOKEN_RTC_AM_PM_LOWER
:
1255 /* P: lower case am or pm indicator */
1257 *intval
= tm
->tm_hour
/12 == 0 ? 0 : 1;
1258 return tm
->tm_hour
/12 == 0 ? "am" : "pm";
1260 case SKIN_TOKEN_RTC_WEEKDAY_NAME
:
1261 /* a: abbreviated weekday name (Sun..Sat) */
1262 return str(LANG_WEEKDAY_SUNDAY
+ tm
->tm_wday
);
1264 case SKIN_TOKEN_RTC_MONTH_NAME
:
1265 /* b: abbreviated month name (Jan..Dec) */
1266 return str(LANG_MONTH_JANUARY
+ tm
->tm_mon
);
1268 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_MON
:
1269 /* u: day of week (1..7); 1 is Monday */
1271 *intval
= (tm
->tm_wday
== 0) ? 7 : tm
->tm_wday
;
1272 snprintf(buf
, buf_size
, "%1d", tm
->tm_wday
+ 1);
1275 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_SUN
:
1276 /* w: day of week (0..6); 0 is Sunday */
1278 *intval
= tm
->tm_wday
+ 1;
1279 snprintf(buf
, buf_size
, "%1d", tm
->tm_wday
);
1282 case SKIN_TOKEN_RTC_DAY_OF_MONTH
:
1283 case SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED
:
1284 case SKIN_TOKEN_RTC_HOUR_24_ZERO_PADDED
:
1285 case SKIN_TOKEN_RTC_HOUR_24
:
1286 case SKIN_TOKEN_RTC_HOUR_12_ZERO_PADDED
:
1287 case SKIN_TOKEN_RTC_HOUR_12
:
1288 case SKIN_TOKEN_RTC_MONTH
:
1289 case SKIN_TOKEN_RTC_MINUTE
:
1290 case SKIN_TOKEN_RTC_SECOND
:
1291 case SKIN_TOKEN_RTC_AM_PM_UPPER
:
1292 case SKIN_TOKEN_RTC_AM_PM_LOWER
:
1293 case SKIN_TOKEN_RTC_YEAR_2_DIGITS
:
1295 case SKIN_TOKEN_RTC_YEAR_4_DIGITS
:
1297 case SKIN_TOKEN_RTC_WEEKDAY_NAME
:
1298 case SKIN_TOKEN_RTC_MONTH_NAME
:
1300 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_MON
:
1301 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_SUN
:
1305 #ifdef HAVE_LCD_CHARCELLS
1306 case SKIN_TOKEN_PROGRESSBAR
:
1309 format_player_progress(gwps
);
1310 end
= utf8encode(data
->wps_progress_pat
[0], buf
);
1315 case SKIN_TOKEN_PLAYER_PROGRESSBAR
:
1318 /* we need 11 characters (full line) for
1320 strlcpy(buf
, " ", buf_size
);
1321 format_player_fullbar(gwps
,buf
,buf_size
);
1322 DEBUGF("bar='%s'\n",buf
);
1326 /* Tell the user if we have an OldPlayer */
1327 strlcpy(buf
, " <Old LCD> ", buf_size
);
1333 #ifdef HAVE_LCD_BITMAP
1335 case SKIN_TOKEN_PEAKMETER_LEFT
:
1336 case SKIN_TOKEN_PEAKMETER_RIGHT
:
1338 int left
, right
, val
;
1339 peak_meter_current_vals(&left
, &right
);
1340 val
= token
->type
== SKIN_TOKEN_PEAKMETER_LEFT
?
1342 val
= peak_meter_scale_value(val
, limit
==1 ? MAX_PEAK
: limit
);
1345 snprintf(buf
, buf_size
, "%d", val
);
1346 data
->peak_meter_enabled
= true;
1351 #if (CONFIG_CODEC == SWCODEC)
1352 case SKIN_TOKEN_CROSSFADE
:
1353 #ifdef HAVE_CROSSFADE
1355 *intval
= global_settings
.crossfade
+ 1;
1356 snprintf(buf
, buf_size
, "%d", global_settings
.crossfade
);
1358 snprintf(buf
, buf_size
, "%d", 0);
1362 case SKIN_TOKEN_REPLAYGAIN
:
1366 if (global_settings
.replaygain_type
== REPLAYGAIN_OFF
)
1372 type
= get_replaygain_mode(id3
->track_gain
!= 0,
1373 id3
->album_gain
!= 0);
1378 val
= 6; /* no tag */
1382 if (global_settings
.replaygain_type
== REPLAYGAIN_SHUFFLE
)
1395 /* due to above, coming here with !id3 shouldn't be possible */
1398 replaygain_itoa(buf
, buf_size
, id3
->track_level
);
1402 replaygain_itoa(buf
, buf_size
, id3
->album_level
);
1407 #endif /* (CONFIG_CODEC == SWCODEC) */
1409 #if (CONFIG_CODEC != MAS3507D) && defined (HAVE_PITCHSCREEN)
1410 case SKIN_TOKEN_SOUND_PITCH
:
1412 int32_t pitch
= sound_get_pitch();
1413 snprintf(buf
, buf_size
, "%ld.%ld",
1414 pitch
/ PITCH_SPEED_PRECISION
,
1415 (pitch
% PITCH_SPEED_PRECISION
) / (PITCH_SPEED_PRECISION
/ 10));
1418 *intval
= pitch_speed_enum(limit
, pitch
,
1419 PITCH_SPEED_PRECISION
* 100);
1424 #if (CONFIG_CODEC == SWCODEC) && defined (HAVE_PITCHSCREEN)
1425 case SKIN_TOKEN_SOUND_SPEED
:
1427 int32_t pitch
= sound_get_pitch();
1429 if (dsp_timestretch_available())
1430 speed
= GET_SPEED(pitch
, dsp_get_timestretch());
1433 snprintf(buf
, buf_size
, "%ld.%ld",
1434 speed
/ PITCH_SPEED_PRECISION
,
1435 (speed
% PITCH_SPEED_PRECISION
) / (PITCH_SPEED_PRECISION
/ 10));
1437 *intval
= pitch_speed_enum(limit
, speed
,
1438 PITCH_SPEED_PRECISION
* 100);
1443 case SKIN_TOKEN_MAIN_HOLD
:
1444 #ifdef HAVE_TOUCHSCREEN
1445 if (data
->touchscreen_locked
)
1448 #ifdef HAS_BUTTON_HOLD
1451 if (is_keys_locked())
1452 #endif /*hold switch or softlock*/
1457 #ifdef HAS_REMOTE_BUTTON_HOLD
1458 case SKIN_TOKEN_REMOTE_HOLD
:
1459 if (remote_button_hold())
1465 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
1466 case SKIN_TOKEN_VLED_HDD
:
1472 case SKIN_TOKEN_BUTTON_VOLUME
:
1473 if (global_status
.last_volume_change
&&
1474 TIME_BEFORE(current_tick
, global_status
.last_volume_change
+
1479 case SKIN_TOKEN_LASTTOUCH
:
1481 #ifdef HAVE_TOUCHSCREEN
1482 unsigned int last_touch
= touchscreen_last_touch();
1483 char *skin_base
= get_skin_buffer(data
);
1484 struct touchregion_lastpress
*data
= SKINOFFSETTOPTR(skin_base
, token
->value
.data
);
1485 struct touchregion
*region
= SKINOFFSETTOPTR(skin_base
, data
->region
);
1487 last_touch
= region
->last_press
;
1489 if (last_touch
!= 0xffff &&
1490 TIME_BEFORE(current_tick
, data
->timeout
+ last_touch
))
1495 case SKIN_TOKEN_HAVE_TOUCH
:
1496 #ifdef HAVE_TOUCHSCREEN
1502 case SKIN_TOKEN_SETTING
:
1504 const struct settings_list
*s
= settings
+token
->value
.i
;
1507 /* Handle contionals */
1508 switch (s
->flags
&F_T_MASK
)
1512 if (s
->flags
&F_T_SOUND
)
1514 /* %?St|name|<min|min+1|...|max-1|max> */
1515 int sound_setting
= s
->sound_setting
->setting
;
1516 /* settings with decimals can't be used in conditionals */
1517 if (sound_numdecimals(sound_setting
) == 0)
1519 *intval
= (*(int*)s
->setting
-sound_min(sound_setting
))
1520 /sound_steps(sound_setting
) + 1;
1525 else if (s
->flags
&F_RGB
)
1526 /* %?St|name|<#000000|#000001|...|#FFFFFF> */
1527 /* shouldn't overflow since colors are stored
1529 * but this is pretty useless anyway */
1530 *intval
= *(int*)s
->setting
+ 1;
1531 else if (s
->cfg_vals
== NULL
)
1532 /* %?St|name|<1st choice|2nd choice|...> */
1533 *intval
= (*(int*)s
->setting
-s
->int_setting
->min
)
1534 /s
->int_setting
->step
+ 1;
1536 /* %?St|name|<1st choice|2nd choice|...> */
1537 /* Not sure about this one. cfg_name/vals are
1538 * indexed from 0 right? */
1539 *intval
= *(int*)s
->setting
+ 1;
1542 /* %?St|name|<if true|if false> */
1543 *intval
= *(bool*)s
->setting
?1:2;
1547 /* %?St|name|<if non empty string|if empty>
1548 * The string's emptyness discards the setting's
1549 * prefix and suffix */
1550 *intval
= ((char*)s
->setting
)[0]?1:2;
1551 /* if there is a prefix we should ignore it here */
1552 if (s
->filename_setting
->prefix
)
1553 return (char*)s
->setting
;
1556 /* This shouldn't happen ... but you never know */
1561 /* Special handlng for filenames because we dont want to show the prefix */
1562 if ((s
->flags
&F_T_MASK
) == F_T_CHARPTR
||
1563 (s
->flags
&F_T_MASK
) == F_T_UCHARPTR
)
1565 if (s
->filename_setting
->prefix
)
1566 return (char*)s
->setting
;
1568 cfg_to_string(token
->value
.i
,buf
,buf_size
);
1571 case SKIN_TOKEN_HAVE_TUNER
:
1573 if (radio_hardware_present())
1577 /* Recording tokens */
1578 case SKIN_TOKEN_HAVE_RECORDING
:
1579 #ifdef HAVE_RECORDING
1585 #ifdef HAVE_RECORDING
1586 case SKIN_TOKEN_IS_RECORDING
:
1587 if (audio_status() == AUDIO_STATUS_RECORD
)
1590 case SKIN_TOKEN_REC_FREQ
: /* order from REC_FREQ_CFG_VAL_LIST */
1592 #if CONFIG_CODEC == SWCODEC
1593 unsigned long samprk
;
1594 int rec_freq
= global_settings
.rec_frequency
;
1599 #if defined(HAVE_SPDIF_REC)
1600 if (global_settings
.rec_source
== AUDIO_SRC_SPDIF
)
1602 /* Use rate in use, not current measured rate if it changed */
1603 samprk
= pcm_rec_sample_rate();
1605 while (rec_freq
< SAMPR_NUM_FREQ
&&
1606 audio_master_sampr_list
[rec_freq
] != samprk
)
1613 samprk
= rec_freq_sampr
[rec_freq
];
1614 #endif /* SIMULATOR */
1619 REC_HAVE_96_(case REC_FREQ_96
:
1622 REC_HAVE_88_(case REC_FREQ_88
:
1625 REC_HAVE_64_(case REC_FREQ_64
:
1628 REC_HAVE_48_(case REC_FREQ_48
:
1631 REC_HAVE_44_(case REC_FREQ_44
:
1634 REC_HAVE_32_(case REC_FREQ_32
:
1637 REC_HAVE_24_(case REC_FREQ_24
:
1640 REC_HAVE_22_(case REC_FREQ_22
:
1643 REC_HAVE_16_(case REC_FREQ_16
:
1646 REC_HAVE_12_(case REC_FREQ_12
:
1649 REC_HAVE_11_(case REC_FREQ_11
:
1652 REC_HAVE_8_(case REC_FREQ_8
:
1657 snprintf(buf
, buf_size
, "%lu.%1lu", samprk
/1000,samprk
%1000);
1660 static const char * const freq_strings
[] =
1661 {"--", "44", "48", "32", "22", "24", "16"};
1662 int freq
= 1 + global_settings
.rec_frequency
;
1663 #ifdef HAVE_SPDIF_REC
1664 if (global_settings
.rec_source
== AUDIO_SRC_SPDIF
)
1666 /* Can't measure S/PDIF sample rate on Archos/Sim yet */
1669 #endif /* HAVE_SPDIF_IN */
1671 *intval
= freq
+1; /* so the token gets a value 1<=x<=7 */
1672 snprintf(buf
, buf_size
, "%s\n",
1673 freq_strings
[global_settings
.rec_frequency
]);
1677 #if CONFIG_CODEC == SWCODEC
1678 case SKIN_TOKEN_REC_ENCODER
:
1680 int rec_format
= global_settings
.rec_format
+1; /* WAV, AIFF, WV, MPEG */
1682 *intval
= rec_format
;
1685 case REC_FORMAT_PCM_WAV
:
1687 case REC_FORMAT_AIFF
:
1689 case REC_FORMAT_WAVPACK
:
1691 case REC_FORMAT_MPA_L3
:
1699 case SKIN_TOKEN_REC_BITRATE
:
1700 #if CONFIG_CODEC == SWCODEC
1701 if (global_settings
.rec_format
== REC_FORMAT_MPA_L3
)
1705 #if 0 /* FIXME: I dont know if this is needed? */
1706 switch (1<<global_settings
.mp3_enc_config
.bitrate
)
1708 case MP3_BITR_CAP_8
:
1711 case MP3_BITR_CAP_16
:
1714 case MP3_BITR_CAP_24
:
1717 case MP3_BITR_CAP_32
:
1720 case MP3_BITR_CAP_40
:
1723 case MP3_BITR_CAP_48
:
1726 case MP3_BITR_CAP_56
:
1729 case MP3_BITR_CAP_64
:
1732 case MP3_BITR_CAP_80
:
1735 case MP3_BITR_CAP_96
:
1738 case MP3_BITR_CAP_112
:
1741 case MP3_BITR_CAP_128
:
1744 case MP3_BITR_CAP_144
:
1747 case MP3_BITR_CAP_160
:
1750 case MP3_BITR_CAP_192
:
1755 *intval
= global_settings
.mp3_enc_config
.bitrate
+1;
1757 snprintf(buf
, buf_size
, "%lu", global_settings
.mp3_enc_config
.bitrate
+1);
1761 return NULL
; /* Fixme later */
1762 #else /* CONFIG_CODEC == HWCODEC */
1764 *intval
= global_settings
.rec_quality
+1;
1765 snprintf(buf
, buf_size
, "%d", global_settings
.rec_quality
);
1768 case SKIN_TOKEN_REC_MONO
:
1769 if (!global_settings
.rec_channels
)
1773 case SKIN_TOKEN_REC_SECONDS
:
1775 int time
= (audio_recorded_time() / HZ
) % 60;
1778 snprintf(buf
, buf_size
, "%02d", time
);
1781 case SKIN_TOKEN_REC_MINUTES
:
1783 int time
= (audio_recorded_time() / HZ
) / 60;
1786 snprintf(buf
, buf_size
, "%02d", time
);
1789 case SKIN_TOKEN_REC_HOURS
:
1791 int time
= (audio_recorded_time() / HZ
) / 3600;
1794 snprintf(buf
, buf_size
, "%02d", time
);
1798 #endif /* HAVE_RECORDING */
1800 case SKIN_TOKEN_CURRENT_SCREEN
:
1802 int curr_screen
= get_current_activity();
1805 *intval
= curr_screen
;
1807 snprintf(buf
, buf_size
, "%d", curr_screen
);
1811 case SKIN_TOKEN_LANG_IS_RTL
:
1812 return lang_is_rtl() ? "r" : NULL
;
1814 #ifdef HAVE_SKIN_VARIABLES
1815 case SKIN_TOKEN_VAR_GETVAL
:
1817 char *skin_base
= get_skin_buffer(data
);
1818 struct skin_var
* var
= SKINOFFSETTOPTR(skin_base
, token
->value
.data
);
1820 *intval
= var
->value
;
1821 snprintf(buf
, buf_size
, "%d", var
->value
);
1825 case SKIN_TOKEN_VAR_TIMEOUT
:
1827 char *skin_base
= get_skin_buffer(data
);
1828 struct skin_var_lastchange
*data
= SKINOFFSETTOPTR(skin_base
, token
->value
.data
);
1829 struct skin_var
* var
= SKINOFFSETTOPTR(skin_base
, data
->var
);
1830 unsigned int last_change
= var
->last_changed
;
1832 if (last_change
!= 0xffff &&
1833 TIME_BEFORE(current_tick
, data
->timeout
+ last_change
))