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"
53 #if CONFIG_CODEC == SWCODEC
60 #include "wps_internals.h"
61 #include "skin_engine.h"
62 #include "statusbar-skinned.h"
63 #include "root_menu.h"
65 #include "recording.h"
66 #include "pcm_record.h"
76 #define NOINLINE __attribute__ ((noinline))
78 extern struct wps_state wps_state
;
80 static const char* get_codectype(const struct mp3entry
* id3
)
82 if (id3
&& id3
->codectype
< AFMT_NUM_CODECS
) {
83 return audio_formats
[id3
->codectype
].label
;
89 /* Extract a part from a path.
91 * buf - buffer extract part to.
92 * buf_size - size of buffer.
93 * path - path to extract from.
94 * level - what to extract. 0 is file name, 1 is parent of file, 2 is
95 * parent of parent, etc.
97 * Returns buf if the desired level was found, NULL otherwise.
99 char* get_dir(char* buf
, int buf_size
, const char* path
, int level
)
102 const char* last_sep
;
105 sep
= path
+ strlen(path
);
120 if (level
|| (last_sep
<= sep
))
123 len
= MIN(last_sep
- sep
, buf_size
- 1);
124 strlcpy(buf
, sep
+ 1, len
+ 1);
128 #if (CONFIG_CODEC != MAS3507D) && defined (HAVE_PITCHCONTROL)
129 /* A helper to determine the enum value for pitch/speed.
131 When there are two choices (i.e. boolean), return 1 if the value is
132 different from normal value and 2 if the value is the same as the
133 normal value. E.g. "%?Sp<%Sp>" would show the pitch only when
134 playing at a modified pitch.
136 When there are more than two choices (i.e. enum), the left half of
137 the choices are to show 0..normal range, and the right half of the
138 choices are to show values over that. The last entry is used when
139 it is set to the normal setting, following the rockbox convention
140 to use the last entry for special values.
144 2 items: %?Sp<0..99 or 101..infinity|100>
145 3 items: %?Sp<0..99|101..infinity|100>
146 4 items: %?Sp<0..49|50..99|101..infinity|100>
147 5 items: %?Sp<0..49|50..99|101..149|150..infinity|100>
148 6 items: %?Sp<0..33|34..66|67..99|101..133|134..infinity|100>
149 7 items: %?Sp<0..33|34..66|67..99|101..133|134..167|167..infinity|100>
151 static int pitch_speed_enum(int range
, int32_t val
, int32_t normval
)
157 return (val
== normval
) + 1;
161 n
= (center
* val
) / normval
+ 1;
162 return (range
<= n
) ? (range
- 1) : n
;
166 const char *get_cuesheetid3_token(struct wps_token
*token
, struct mp3entry
*id3
,
167 int offset_tracks
, char *buf
, int buf_size
)
169 struct cuesheet
*cue
= id3
?id3
->cuesheet
:NULL
;
170 if (!cue
|| !cue
->curr_track
)
173 struct cue_track_info
*track
= cue
->curr_track
;
176 if (cue
->curr_track_idx
+offset_tracks
< cue
->track_count
)
177 track
+=offset_tracks
;
183 case SKIN_TOKEN_METADATA_ARTIST
:
184 return *track
->performer
? track
->performer
: NULL
;
185 case SKIN_TOKEN_METADATA_COMPOSER
:
186 return *track
->songwriter
? track
->songwriter
: NULL
;
187 case SKIN_TOKEN_METADATA_ALBUM
:
188 return *cue
->title
? cue
->title
: NULL
;
189 case SKIN_TOKEN_METADATA_ALBUM_ARTIST
:
190 return *cue
->performer
? cue
->performer
: NULL
;
191 case SKIN_TOKEN_METADATA_TRACK_TITLE
:
192 return *track
->title
? track
->title
: NULL
;
193 case SKIN_TOKEN_METADATA_TRACK_NUMBER
:
194 snprintf(buf
, buf_size
, "%d/%d",
195 cue
->curr_track_idx
+offset_tracks
+1, cue
->track_count
);
203 static const char* get_filename_token(struct wps_token
*token
, char* filename
,
204 char *buf
, int buf_size
)
210 case SKIN_TOKEN_FILE_PATH
:
212 case SKIN_TOKEN_FILE_NAME
:
213 if (get_dir(buf
, buf_size
, filename
, 0)) {
214 /* Remove extension */
215 char* sep
= strrchr(buf
, '.');
222 case SKIN_TOKEN_FILE_NAME_WITH_EXTENSION
:
223 return get_dir(buf
, buf_size
, filename
, 0);
224 case SKIN_TOKEN_FILE_DIRECTORY
:
225 return get_dir(buf
, buf_size
, filename
, token
->value
.i
);
233 /* All tokens which only need the info to return a value go in here */
234 const char *get_id3_token(struct wps_token
*token
, struct mp3entry
*id3
,
235 char *filename
, char *buf
, int buf_size
, int limit
, int *intval
)
237 struct wps_state
*state
= &wps_state
;
240 unsigned long length
= id3
->length
;
241 unsigned long elapsed
= id3
->elapsed
+ state
->ff_rewind_count
;
244 case SKIN_TOKEN_METADATA_ARTIST
:
246 case SKIN_TOKEN_METADATA_COMPOSER
:
247 return id3
->composer
;
248 case SKIN_TOKEN_METADATA_ALBUM
:
250 case SKIN_TOKEN_METADATA_ALBUM_ARTIST
:
251 return id3
->albumartist
;
252 case SKIN_TOKEN_METADATA_GROUPING
:
253 return id3
->grouping
;
254 case SKIN_TOKEN_METADATA_GENRE
:
255 return id3
->genre_string
;
256 case SKIN_TOKEN_METADATA_DISC_NUMBER
:
257 if (id3
->disc_string
)
258 return id3
->disc_string
;
260 snprintf(buf
, buf_size
, "%d", id3
->discnum
);
264 case SKIN_TOKEN_METADATA_TRACK_NUMBER
:
265 if (id3
->track_string
)
266 return id3
->track_string
;
268 snprintf(buf
, buf_size
, "%d", id3
->tracknum
);
272 case SKIN_TOKEN_METADATA_TRACK_TITLE
:
274 case SKIN_TOKEN_METADATA_VERSION
:
275 switch (id3
->id3version
)
291 case SKIN_TOKEN_METADATA_YEAR
:
292 if( id3
->year_string
)
293 return id3
->year_string
;
295 snprintf(buf
, buf_size
, "%d", id3
->year
);
299 case SKIN_TOKEN_METADATA_COMMENT
:
301 case SKIN_TOKEN_FILE_BITRATE
:
303 snprintf(buf
, buf_size
, "%d", id3
->bitrate
);
307 case SKIN_TOKEN_TRACK_TIME_ELAPSED
:
308 if (intval
&& limit
== TOKEN_VALUE_ONLY
)
309 *intval
= elapsed
/1000;
310 format_time(buf
, buf_size
, elapsed
);
313 case SKIN_TOKEN_TRACK_TIME_REMAINING
:
314 if (intval
&& limit
== TOKEN_VALUE_ONLY
)
315 *intval
= (length
- elapsed
)/1000;
316 format_time(buf
, buf_size
, length
- elapsed
);
319 case SKIN_TOKEN_TRACK_LENGTH
:
320 if (intval
&& limit
== TOKEN_VALUE_ONLY
)
321 *intval
= length
/1000;
322 format_time(buf
, buf_size
, length
);
325 case SKIN_TOKEN_TRACK_ELAPSED_PERCENT
:
331 if (limit
== TOKEN_VALUE_ONLY
)
332 limit
= 100; /* make it a percentage */
333 *intval
= limit
* elapsed
/ length
+ 1;
335 snprintf(buf
, buf_size
, "%lu", 100 * elapsed
/ length
);
338 case SKIN_TOKEN_TRACK_STARTING
:
340 unsigned long time
= token
->value
.i
* (HZ
/TIMEOUT_UNIT
);
345 case SKIN_TOKEN_TRACK_ENDING
:
347 unsigned long time
= token
->value
.i
* (HZ
/TIMEOUT_UNIT
);
348 if (length
- elapsed
< time
)
353 case SKIN_TOKEN_FILE_CODEC
:
356 if(id3
->codectype
== AFMT_UNKNOWN
)
357 *intval
= AFMT_NUM_CODECS
;
359 *intval
= id3
->codectype
;
361 return get_codectype(id3
);
363 case SKIN_TOKEN_FILE_FREQUENCY
:
364 snprintf(buf
, buf_size
, "%ld", id3
->frequency
);
366 case SKIN_TOKEN_FILE_FREQUENCY_KHZ
:
367 /* ignore remainders < 100, so 22050 Hz becomes just 22k */
368 if ((id3
->frequency
% 1000) < 100)
369 snprintf(buf
, buf_size
, "%ld", id3
->frequency
/ 1000);
371 snprintf(buf
, buf_size
, "%ld.%lu",
372 id3
->frequency
/ 1000,
373 (id3
->frequency
% 1000) / 100);
375 case SKIN_TOKEN_FILE_VBR
:
376 return (id3
->vbr
) ? "(avg)" : NULL
;
377 case SKIN_TOKEN_FILE_SIZE
:
378 snprintf(buf
, buf_size
, "%ld", id3
->filesize
/ 1024);
382 case SKIN_TOKEN_DATABASE_PLAYCOUNT
:
384 *intval
= id3
->playcount
+ 1;
385 snprintf(buf
, buf_size
, "%ld", id3
->playcount
);
387 case SKIN_TOKEN_DATABASE_RATING
:
389 *intval
= id3
->rating
+ 1;
390 snprintf(buf
, buf_size
, "%d", id3
->rating
);
392 case SKIN_TOKEN_DATABASE_AUTOSCORE
:
394 *intval
= id3
->score
+ 1;
395 snprintf(buf
, buf_size
, "%d", id3
->score
);
400 return get_filename_token(token
, id3
->path
, buf
, buf_size
);
403 else /* id3 == NULL, handle the error based on the expected return type */
407 /* Most tokens expect NULL on error so leave that for the default case,
408 * The ones that expect "0" need to be handled */
409 case SKIN_TOKEN_FILE_FREQUENCY
:
410 case SKIN_TOKEN_FILE_FREQUENCY_KHZ
:
411 case SKIN_TOKEN_FILE_SIZE
:
413 case SKIN_TOKEN_DATABASE_PLAYCOUNT
:
414 case SKIN_TOKEN_DATABASE_RATING
:
415 case SKIN_TOKEN_DATABASE_AUTOSCORE
:
421 return get_filename_token(token
, filename
, buf
, buf_size
);
429 /* Formats the frequency (specified in Hz) in MHz, */
430 /* with one or two digits after the decimal point -- */
431 /* depending on the frequency changing step. */
433 static char *format_freq_MHz(int freq
, int freq_step
, char *buf
, int buf_size
)
437 if (freq_step
< 100000)
439 /* Format with two digits after decimal point */
445 /* Format with one digit after decimal point */
449 div
= 1000000 / scale
;
451 snprintf(buf
, buf_size
, fmt
, freq
/div
, freq
%div
);
456 /* Tokens which are really only used by the radio screen go in here */
457 const char *get_radio_token(struct wps_token
*token
, int preset_offset
,
458 char *buf
, int buf_size
, int limit
, int *intval
)
460 const struct fm_region_data
*region_data
=
461 &(fm_region_data
[global_settings
.fm_region
]);
465 /* Radio/tuner tokens */
466 case SKIN_TOKEN_TUNER_TUNED
:
467 if (tuner_get(RADIO_TUNED
))
470 case SKIN_TOKEN_TUNER_SCANMODE
:
471 if (radio_scan_mode())
474 case SKIN_TOKEN_TUNER_STEREO
:
475 if (radio_is_stereo())
478 case SKIN_TOKEN_TUNER_MINFREQ
: /* changes based on "region" */
479 return format_freq_MHz(region_data
->freq_min
,
480 region_data
->freq_step
, buf
, buf_size
);
481 case SKIN_TOKEN_TUNER_MAXFREQ
: /* changes based on "region" */
482 return format_freq_MHz(region_data
->freq_max
,
483 region_data
->freq_step
, buf
, buf_size
);
484 case SKIN_TOKEN_TUNER_CURFREQ
:
485 return format_freq_MHz(radio_current_frequency(),
486 region_data
->freq_step
, buf
, buf_size
);
487 #ifdef HAVE_RADIO_RSSI
488 case SKIN_TOKEN_TUNER_RSSI
:
489 snprintf(buf
, buf_size
, "%d",tuner_get(RADIO_RSSI
));
492 int val
= tuner_get(RADIO_RSSI
);
493 int min
= tuner_get(RADIO_RSSI_MIN
);
494 int max
= tuner_get(RADIO_RSSI_MAX
);
495 if (limit
== TOKEN_VALUE_ONLY
)
501 *intval
= 1+(limit
-1)*(val
-min
)/(max
-1-min
);
505 case SKIN_TOKEN_TUNER_RSSI_MIN
:
506 snprintf(buf
, buf_size
, "%d",tuner_get(RADIO_RSSI_MIN
));
508 case SKIN_TOKEN_TUNER_RSSI_MAX
:
509 snprintf(buf
, buf_size
, "%d",tuner_get(RADIO_RSSI_MAX
));
512 case SKIN_TOKEN_PRESET_NAME
:
513 case SKIN_TOKEN_PRESET_FREQ
:
514 case SKIN_TOKEN_PRESET_ID
:
516 int preset_count
= radio_preset_count();
517 int cur_preset
= radio_current_preset();
518 if (preset_count
== 0 || cur_preset
< 0)
520 int preset
= cur_preset
+ preset_offset
;
521 /* make sure it's in the valid range */
522 preset
%= preset_count
;
524 preset
+= preset_count
;
525 if (token
->type
== SKIN_TOKEN_PRESET_NAME
)
526 snprintf(buf
, buf_size
, "%s", radio_get_preset(preset
)->name
);
527 else if (token
->type
== SKIN_TOKEN_PRESET_FREQ
)
528 format_freq_MHz(radio_get_preset(preset
)->frequency
,
529 region_data
->freq_step
, buf
, buf_size
);
531 snprintf(buf
, buf_size
, "%d", preset
+ 1);
534 case SKIN_TOKEN_PRESET_COUNT
:
535 snprintf(buf
, buf_size
, "%d", radio_preset_count());
537 *intval
= radio_preset_count();
539 case SKIN_TOKEN_HAVE_RDS
:
542 case SKIN_TOKEN_RDS_NAME
:
543 return tuner_get_rds_info(RADIO_RDS_NAME
);
544 case SKIN_TOKEN_RDS_TEXT
:
545 return tuner_get_rds_info(RADIO_RDS_TEXT
);
547 return NULL
; /* end of the SKIN_TOKEN_HAVE_RDS case */
548 #endif /* HAVE_RDS_CAP */
556 static struct mp3entry
* get_mp3entry_from_offset(int offset
, char **filename
)
558 struct mp3entry
* pid3
= NULL
;
559 struct wps_state
*state
= skin_get_global_state();
560 struct cuesheet
*cue
= state
->id3
? state
->id3
->cuesheet
: NULL
;
561 const char *fname
= NULL
;
562 if (cue
&& cue
->curr_track_idx
+ offset
< cue
->track_count
)
564 else if (offset
== 0)
566 else if (offset
== 1)
570 static char filename_buf
[MAX_PATH
+ 1];
571 fname
= playlist_peek(offset
, filename_buf
, sizeof(filename_buf
));
572 *filename
= (char*)fname
;
573 #if CONFIG_CODEC == SWCODEC
574 static struct mp3entry tempid3
;
576 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
577 tagcache_fill_tags(&tempid3
, fname
) ||
579 audio_peek_track(&tempid3
, offset
)
589 #ifdef HAVE_LCD_CHARCELLS
590 static void format_player_progress(struct gui_wps
*gwps
)
592 struct wps_state
*state
= skin_get_global_state();
593 struct screen
*display
= gwps
->display
;
594 unsigned char progress_pattern
[7];
599 if (LIKELY(state
->id3
))
601 elapsed
= state
->id3
->elapsed
;
602 length
= state
->id3
->length
;
611 pos
= 36 * (elapsed
+ state
->ff_rewind_count
) / length
;
613 for (i
= 0; i
< 7; i
++, pos
-= 5)
616 progress_pattern
[i
] = 0x1fu
;
618 progress_pattern
[i
] = 0x00u
;
620 progress_pattern
[i
] = 0x1fu
>> pos
;
623 display
->define_pattern(gwps
->data
->wps_progress_pat
[0], progress_pattern
);
626 static void format_player_fullbar(struct gui_wps
*gwps
, char* buf
, int buf_size
)
628 static const unsigned char numbers
[10][4] = {
629 {0x0e, 0x0a, 0x0a, 0x0e}, /* 0 */
630 {0x04, 0x0c, 0x04, 0x04}, /* 1 */
631 {0x0e, 0x02, 0x04, 0x0e}, /* 2 */
632 {0x0e, 0x02, 0x06, 0x0e}, /* 3 */
633 {0x08, 0x0c, 0x0e, 0x04}, /* 4 */
634 {0x0e, 0x0c, 0x02, 0x0c}, /* 5 */
635 {0x0e, 0x08, 0x0e, 0x0e}, /* 6 */
636 {0x0e, 0x02, 0x04, 0x08}, /* 7 */
637 {0x0e, 0x0e, 0x0a, 0x0e}, /* 8 */
638 {0x0e, 0x0e, 0x02, 0x0e} /* 9 */
641 struct wps_state
*state
= skin_get_global_state();
642 struct screen
*display
= gwps
->display
;
643 struct wps_data
*data
= gwps
->data
;
644 unsigned char progress_pattern
[7];
654 if (LIKELY(state
->id3
))
656 elapsed
= state
->id3
->elapsed
;
657 length
= state
->id3
->length
;
665 if (buf_size
< 34) /* worst case: 11x UTF-8 char + \0 */
668 time
= elapsed
+ state
->ff_rewind_count
;
670 pos
= 55 * time
/ length
;
672 memset(timestr
, 0, sizeof(timestr
));
673 format_time(timestr
, sizeof(timestr
)-2, time
);
674 timestr
[strlen(timestr
)] = ':'; /* always safe */
676 for (i
= 0; i
< 11; i
++, pos
-= 5)
679 memset(progress_pattern
, 0, sizeof(progress_pattern
));
681 if ((digit
= timestr
[time_idx
]))
686 if (timestr
[time_idx
+ 1] == ':') /* ones, left aligned */
688 memcpy(progress_pattern
, numbers
[digit
], 4);
691 else /* tens, shifted right */
693 for (j
= 0; j
< 4; j
++)
694 progress_pattern
[j
] = numbers
[digit
][j
] >> 1;
696 if (time_idx
> 0) /* not the first group, add colon in front */
698 progress_pattern
[1] |= 0x10u
;
699 progress_pattern
[3] |= 0x10u
;
705 progress_pattern
[5] = progress_pattern
[6] = 0x1fu
;
708 if (pos
> 0 && pos
< 5)
711 progress_pattern
[5] = progress_pattern
[6] = (~0x1fu
>> pos
) & 0x1fu
;
714 if (softchar
&& pat_idx
< 8)
716 display
->define_pattern(data
->wps_progress_pat
[pat_idx
],
718 buf
= utf8encode(data
->wps_progress_pat
[pat_idx
], buf
);
722 buf
= utf8encode(' ', buf
);
724 buf
= utf8encode(0xe115, buf
); /* 2/7 _ */
729 #endif /* HAVE_LCD_CHARCELLS */
731 /* Don't inline this; it was broken out of get_token_value to reduce stack
734 static const char* NOINLINE
get_lif_token_value(struct gui_wps
*gwps
,
735 struct logical_if
*lif
,
736 int offset
, char *buf
,
739 int a
= lif
->num_options
;
741 bool number_set
= true;
742 struct wps_token
*liftoken
= SKINOFFSETTOPTR(get_skin_buffer(gwps
->data
), lif
->token
);
743 const char* out_text
= get_token_value(gwps
, liftoken
, offset
, buf
, buf_size
, &a
);
744 if (a
== -1 && liftoken
->type
!= SKIN_TOKEN_VOLUME
)
746 a
= (out_text
&& *out_text
) ? 1 : 0;
749 switch (lif
->operand
.type
)
753 char *cmp
= SKINOFFSETTOPTR(get_skin_buffer(gwps
->data
), lif
->operand
.data
.text
);
754 if (out_text
== NULL
)
756 a
= strcmp(out_text
, cmp
);
761 if (!number_set
&& out_text
&& *out_text
>= '0' && *out_text
<= '9')
766 b
= lif
->operand
.data
.number
;
770 char temp_buf
[MAX_PATH
];
772 struct skin_element
*element
= SKINOFFSETTOPTR(get_skin_buffer(gwps
->data
), lif
->operand
.data
.code
);
773 struct wps_token
*token
= SKINOFFSETTOPTR(get_skin_buffer(gwps
->data
), element
->data
);
774 b
= lif
->num_options
;
775 outb
= get_token_value(gwps
, token
, offset
, temp_buf
,
776 sizeof(temp_buf
), &b
);
777 if (b
== -1 && liftoken
->type
!= SKIN_TOKEN_VOLUME
)
779 if (!out_text
|| !outb
)
780 return (lif
->op
== IF_EQUALS
) ? NULL
: "neq";
781 bool equal
= strcmp(out_text
, outb
) == 0;
782 if (lif
->op
== IF_EQUALS
)
783 return equal
? "eq" : NULL
;
784 else if (lif
->op
== IF_NOTEQUALS
)
785 return !equal
? "neq" : NULL
;
787 b
= (outb
&& *outb
) ? 1 : 0;
798 return a
== b
? "eq" : NULL
;
800 return a
!= b
? "neq" : NULL
;
802 return a
< b
? "lt" : NULL
;
804 return a
<= b
? "lte" : NULL
;
806 return a
> b
? "gt" : NULL
;
807 case IF_GREATERTHAN_EQ
:
808 return a
>= b
? "gte" : NULL
;
813 /* Return the tags value as text. buf should be used as temp storage if needed.
815 intval is used with conditionals/enums: when this function is called,
816 intval should contain the number of options in the conditional/enum.
817 When this function returns, intval is -1 if the tag is non numeric or,
818 if the tag is numeric, *intval is the enum case we want to go to (between 1
819 and the original value of *intval, inclusive).
820 When not treating a conditional/enum, intval should be NULL.
822 const char *get_token_value(struct gui_wps
*gwps
,
823 struct wps_token
*token
, int offset
,
824 char *buf
, int buf_size
,
830 struct wps_data
*data
= gwps
->data
;
831 struct wps_state
*state
= skin_get_global_state();
832 struct mp3entry
*id3
; /* Think very carefully about using this.
833 maybe get_id3_token() is the better place? */
834 const char *out_text
= NULL
;
835 char *filename
= NULL
;
840 id3
= get_mp3entry_from_offset(token
->next
? 1: offset
, &filename
);
842 filename
= id3
->path
;
845 struct tm
* tm
= NULL
;
847 /* if the token is an RTC one, update the time
848 and do the necessary checks */
849 if (token
->type
>= SKIN_TOKENS_RTC_BEGIN
850 && token
->type
<= SKIN_TOKENS_RTC_END
)
866 if (id3
&& id3
== state
->id3
&& id3
->cuesheet
)
868 out_text
= get_cuesheetid3_token(token
, id3
,
869 token
->next
?1:offset
, buf
, buf_size
);
873 out_text
= get_id3_token(token
, id3
, filename
, buf
, buf_size
, limit
, intval
);
877 out_text
= get_radio_token(token
, offset
, buf
, buf_size
, limit
, intval
);
884 case SKIN_TOKEN_LOGICAL_IF
:
886 struct logical_if
*lif
= SKINOFFSETTOPTR(get_skin_buffer(data
), token
->value
.data
);
887 return get_lif_token_value(gwps
, lif
, offset
, buf
, buf_size
);
890 case SKIN_TOKEN_LOGICAL_AND
:
891 case SKIN_TOKEN_LOGICAL_OR
:
893 int i
= 0, truecount
= 0;
894 char *skinbuffer
= get_skin_buffer(data
);
895 struct skin_element
*element
=
896 SKINOFFSETTOPTR(skinbuffer
, token
->value
.data
);
897 struct skin_tag_parameter
* params
=
898 SKINOFFSETTOPTR(skinbuffer
, element
->params
);
899 struct skin_tag_parameter
* thistag
;
900 for (i
=0; i
<element
->params_count
; i
++)
902 thistag
= ¶ms
[i
];
903 struct skin_element
*tokenelement
=
904 SKINOFFSETTOPTR(skinbuffer
, thistag
->data
.code
);
905 out_text
= get_token_value(gwps
,
906 SKINOFFSETTOPTR(skinbuffer
, tokenelement
->data
),
907 offset
, buf
, buf_size
, intval
);
908 if (out_text
&& *out_text
)
910 else if (token
->type
== SKIN_TOKEN_LOGICAL_AND
)
913 return truecount
? "true" : NULL
;
916 case SKIN_TOKEN_SUBSTRING
:
918 struct substring
*ss
= SKINOFFSETTOPTR(get_skin_buffer(data
), token
->value
.data
);
919 const char *token_val
= get_token_value(gwps
,
920 SKINOFFSETTOPTR(get_skin_buffer(data
), ss
->token
), offset
,
921 buf
, buf_size
, intval
);
924 int start_byte
, end_byte
, byte_len
;
925 int utf8_len
= utf8length(token_val
);
927 if (utf8_len
< ss
->start
)
931 start_byte
= utf8seek(token_val
, ss
->start
+ utf8_len
);
933 start_byte
= utf8seek(token_val
, ss
->start
);
935 if (ss
->length
< 0 || (ss
->start
+ ss
->length
) > utf8_len
)
936 end_byte
= strlen(token_val
);
938 end_byte
= utf8seek(token_val
, ss
->start
+ ss
->length
);
940 byte_len
= end_byte
- start_byte
;
942 if (token_val
!= buf
)
943 memcpy(buf
, &token_val
[start_byte
], byte_len
);
945 buf
= &buf
[start_byte
];
947 buf
[byte_len
] = '\0';
948 if (ss
->expect_number
&&
949 intval
&& (buf
[0] >= '0' && buf
[0] <= '9'))
950 *intval
= atoi(buf
) + 1; /* so 0 is the first item */
958 case SKIN_TOKEN_CHARACTER
:
959 if (token
->value
.c
== '\n')
961 return &(token
->value
.c
);
963 case SKIN_TOKEN_STRING
:
964 return (char*)SKINOFFSETTOPTR(get_skin_buffer(data
), token
->value
.data
);
966 case SKIN_TOKEN_TRANSLATEDSTRING
:
967 return (char*)P2STR(ID2P(token
->value
.i
));
969 case SKIN_TOKEN_PLAYLIST_ENTRIES
:
970 snprintf(buf
, buf_size
, "%d", playlist_amount());
972 *intval
= playlist_amount();
974 #ifdef HAVE_LCD_BITMAP
975 case SKIN_TOKEN_LIST_TITLE_TEXT
:
976 return sb_get_title(gwps
->display
->screen_type
);
977 case SKIN_TOKEN_LIST_TITLE_ICON
:
979 *intval
= sb_get_icon(gwps
->display
->screen_type
);
980 snprintf(buf
, buf_size
, "%d",sb_get_icon(gwps
->display
->screen_type
));
982 case SKIN_TOKEN_LIST_ITEM_TEXT
:
984 struct listitem
*li
= (struct listitem
*)SKINOFFSETTOPTR(get_skin_buffer(data
), token
->value
.data
);
985 return skinlist_get_item_text(li
->offset
, li
->wrap
, buf
, buf_size
);
987 case SKIN_TOKEN_LIST_ITEM_ROW
:
989 *intval
= skinlist_get_item_row() + 1;
990 snprintf(buf
, buf_size
, "%d",skinlist_get_item_row() + 1);
992 case SKIN_TOKEN_LIST_ITEM_COLUMN
:
994 *intval
= skinlist_get_item_column() + 1;
995 snprintf(buf
, buf_size
, "%d",skinlist_get_item_column() + 1);
997 case SKIN_TOKEN_LIST_ITEM_NUMBER
:
999 *intval
= skinlist_get_item_number() + 1;
1000 snprintf(buf
, buf_size
, "%d",skinlist_get_item_number() + 1);
1002 case SKIN_TOKEN_LIST_ITEM_IS_SELECTED
:
1003 return skinlist_is_selected_item()?"s":"";
1004 case SKIN_TOKEN_LIST_ITEM_ICON
:
1006 struct listitem
*li
= (struct listitem
*)SKINOFFSETTOPTR(get_skin_buffer(data
), token
->value
.data
);
1007 int icon
= skinlist_get_item_icon(li
->offset
, li
->wrap
);
1010 snprintf(buf
, buf_size
, "%d", icon
);
1013 case SKIN_TOKEN_LIST_NEEDS_SCROLLBAR
:
1014 return skinlist_needs_scrollbar(gwps
->display
->screen_type
) ? "s" : "";
1016 case SKIN_TOKEN_PLAYLIST_NAME
:
1017 return playlist_name(NULL
, buf
, buf_size
);
1019 case SKIN_TOKEN_PLAYLIST_POSITION
:
1020 snprintf(buf
, buf_size
, "%d", playlist_get_display_index()+offset
);
1022 *intval
= playlist_get_display_index()+offset
;
1025 case SKIN_TOKEN_PLAYLIST_SHUFFLE
:
1026 if ( global_settings
.playlist_shuffle
)
1032 case SKIN_TOKEN_VOLUME
:
1033 snprintf(buf
, buf_size
, "%d", global_settings
.volume
);
1036 int minvol
= sound_min(SOUND_VOLUME
);
1037 if (limit
== TOKEN_VALUE_ONLY
)
1039 *intval
= global_settings
.volume
;
1041 else if (global_settings
.volume
== minvol
)
1045 else if (global_settings
.volume
== 0)
1047 *intval
= limit
- 1;
1049 else if (global_settings
.volume
> 0)
1055 *intval
= (limit
-3) * (global_settings
.volume
- minvol
- 1)
1056 / (-1 - minvol
) + 2;
1060 #ifdef HAVE_ALBUMART
1061 case SKIN_TOKEN_ALBUMART_FOUND
:
1062 if (SKINOFFSETTOPTR(get_skin_buffer(data
), data
->albumart
))
1065 handle
= playback_current_aa_hid(data
->playback_aa_slot
);
1067 if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF
))
1069 struct skin_albumart
*aa
= SKINOFFSETTOPTR(get_skin_buffer(data
), data
->albumart
);
1070 struct dim dim
= {aa
->width
, aa
->height
};
1071 handle
= radio_get_art_hid(&dim
);
1080 case SKIN_TOKEN_BATTERY_PERCENT
:
1082 int l
= battery_level();
1086 if (limit
== TOKEN_VALUE_ONLY
)
1092 limit
= MAX(limit
, 3);
1094 /* First enum is used for "unknown level",
1095 * last enum is used for 100%.
1097 *intval
= (limit
- 2) * l
/ 100 + 2;
1105 snprintf(buf
, buf_size
, "%d", l
);
1112 case SKIN_TOKEN_BATTERY_VOLTS
:
1114 int v
= battery_voltage();
1116 snprintf(buf
, buf_size
, "%d.%02d", v
/ 1000, (v
% 1000) / 10);
1123 case SKIN_TOKEN_BATTERY_TIME
:
1125 int t
= battery_time();
1127 snprintf(buf
, buf_size
, "%dh %dm", t
/ 60, t
% 60);
1134 case SKIN_TOKEN_BATTERY_CHARGER_CONNECTED
:
1136 if(charger_input_state
==CHARGER
)
1142 #if CONFIG_CHARGING >= CHARGING_MONITOR
1143 case SKIN_TOKEN_BATTERY_CHARGING
:
1145 if (charge_state
== CHARGING
|| charge_state
== TOPOFF
) {
1152 #ifdef HAVE_USB_POWER
1153 case SKIN_TOKEN_USB_POWERED
:
1158 case SKIN_TOKEN_BATTERY_SLEEPTIME
:
1160 if (get_sleep_timer() == 0)
1164 format_time(buf
, buf_size
, get_sleep_timer() * 1000);
1169 case SKIN_TOKEN_PLAYBACK_STATUS
:
1171 int status
= current_playmode();
1173 int mode
= 1; /* stop */
1174 if (status
== STATUS_PLAY
)
1175 mode
= 2; /* play */
1176 if (state
->is_fading
||
1177 (status
== STATUS_PAUSE
&& !status_get_ffmode()))
1178 mode
= 3; /* pause */
1181 if (status_get_ffmode() == STATUS_FASTFORWARD
)
1183 if (status_get_ffmode() == STATUS_FASTBACKWARD
)
1186 #ifdef HAVE_RECORDING
1188 if (status
== STATUS_RECORD
)
1190 else if (status
== STATUS_RECORD_PAUSE
)
1195 if (status
== STATUS_RADIO
)
1197 else if (status
== STATUS_RADIO_PAUSE
)
1205 snprintf(buf
, buf_size
, "%d", mode
-1);
1209 case SKIN_TOKEN_REPEAT_MODE
:
1211 *intval
= global_settings
.repeat_mode
+ 1;
1212 snprintf(buf
, buf_size
, "%d", global_settings
.repeat_mode
);
1215 case SKIN_TOKEN_RTC_PRESENT
:
1223 case SKIN_TOKEN_RTC_12HOUR_CFG
:
1225 *intval
= global_settings
.timeformat
+ 1;
1226 snprintf(buf
, buf_size
, "%d", global_settings
.timeformat
);
1229 case SKIN_TOKEN_RTC_DAY_OF_MONTH
:
1230 /* d: day of month (01..31) */
1231 snprintf(buf
, buf_size
, "%02d", tm
->tm_mday
);
1233 *intval
= tm
->tm_mday
- 1;
1236 case SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED
:
1237 /* e: day of month, blank padded ( 1..31) */
1238 snprintf(buf
, buf_size
, "%2d", tm
->tm_mday
);
1240 *intval
= tm
->tm_mday
- 1;
1243 case SKIN_TOKEN_RTC_HOUR_24_ZERO_PADDED
:
1244 /* H: hour (00..23) */
1245 snprintf(buf
, buf_size
, "%02d", tm
->tm_hour
);
1247 *intval
= tm
->tm_hour
;
1250 case SKIN_TOKEN_RTC_HOUR_24
:
1251 /* k: hour ( 0..23) */
1252 snprintf(buf
, buf_size
, "%2d", tm
->tm_hour
);
1254 *intval
= tm
->tm_hour
;
1257 case SKIN_TOKEN_RTC_HOUR_12_ZERO_PADDED
:
1258 /* I: hour (01..12) */
1259 snprintf(buf
, buf_size
, "%02d",
1260 (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12);
1262 *intval
= (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12;
1265 case SKIN_TOKEN_RTC_HOUR_12
:
1266 /* l: hour ( 1..12) */
1267 snprintf(buf
, buf_size
, "%2d",
1268 (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12);
1270 *intval
= (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12;
1273 case SKIN_TOKEN_RTC_MONTH
:
1274 /* m: month (01..12) */
1276 *intval
= tm
->tm_mon
+ 1;
1277 snprintf(buf
, buf_size
, "%02d", tm
->tm_mon
+ 1);
1280 case SKIN_TOKEN_RTC_MINUTE
:
1281 /* M: minute (00..59) */
1282 snprintf(buf
, buf_size
, "%02d", tm
->tm_min
);
1284 *intval
= tm
->tm_min
;
1287 case SKIN_TOKEN_RTC_SECOND
:
1288 /* S: second (00..59) */
1289 snprintf(buf
, buf_size
, "%02d", tm
->tm_sec
);
1291 *intval
= tm
->tm_sec
;
1294 case SKIN_TOKEN_RTC_YEAR_2_DIGITS
:
1295 /* y: last two digits of year (00..99) */
1296 snprintf(buf
, buf_size
, "%02d", tm
->tm_year
% 100);
1298 *intval
= tm
->tm_year
% 100;
1301 case SKIN_TOKEN_RTC_YEAR_4_DIGITS
:
1302 /* Y: year (1970...) */
1303 snprintf(buf
, buf_size
, "%04d", tm
->tm_year
+ 1900);
1305 *intval
= tm
->tm_year
+ 1900;
1308 case SKIN_TOKEN_RTC_AM_PM_UPPER
:
1309 /* p: upper case AM or PM indicator */
1311 *intval
= tm
->tm_hour
/12 == 0 ? 0 : 1;
1312 return tm
->tm_hour
/12 == 0 ? "AM" : "PM";
1314 case SKIN_TOKEN_RTC_AM_PM_LOWER
:
1315 /* P: lower case am or pm indicator */
1317 *intval
= tm
->tm_hour
/12 == 0 ? 0 : 1;
1318 return tm
->tm_hour
/12 == 0 ? "am" : "pm";
1320 case SKIN_TOKEN_RTC_WEEKDAY_NAME
:
1321 /* a: abbreviated weekday name (Sun..Sat) */
1322 return str(LANG_WEEKDAY_SUNDAY
+ tm
->tm_wday
);
1324 case SKIN_TOKEN_RTC_MONTH_NAME
:
1325 /* b: abbreviated month name (Jan..Dec) */
1326 return str(LANG_MONTH_JANUARY
+ tm
->tm_mon
);
1328 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_MON
:
1329 /* u: day of week (1..7); 1 is Monday */
1331 *intval
= (tm
->tm_wday
== 0) ? 7 : tm
->tm_wday
;
1332 snprintf(buf
, buf_size
, "%1d", tm
->tm_wday
+ 1);
1335 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_SUN
:
1336 /* w: day of week (0..6); 0 is Sunday */
1338 *intval
= tm
->tm_wday
+ 1;
1339 snprintf(buf
, buf_size
, "%1d", tm
->tm_wday
);
1342 case SKIN_TOKEN_RTC_DAY_OF_MONTH
:
1343 case SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED
:
1344 case SKIN_TOKEN_RTC_HOUR_24_ZERO_PADDED
:
1345 case SKIN_TOKEN_RTC_HOUR_24
:
1346 case SKIN_TOKEN_RTC_HOUR_12_ZERO_PADDED
:
1347 case SKIN_TOKEN_RTC_HOUR_12
:
1348 case SKIN_TOKEN_RTC_MONTH
:
1349 case SKIN_TOKEN_RTC_MINUTE
:
1350 case SKIN_TOKEN_RTC_SECOND
:
1351 case SKIN_TOKEN_RTC_AM_PM_UPPER
:
1352 case SKIN_TOKEN_RTC_AM_PM_LOWER
:
1353 case SKIN_TOKEN_RTC_YEAR_2_DIGITS
:
1355 case SKIN_TOKEN_RTC_YEAR_4_DIGITS
:
1357 case SKIN_TOKEN_RTC_WEEKDAY_NAME
:
1358 case SKIN_TOKEN_RTC_MONTH_NAME
:
1360 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_MON
:
1361 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_SUN
:
1365 #ifdef HAVE_LCD_CHARCELLS
1366 case SKIN_TOKEN_PROGRESSBAR
:
1369 format_player_progress(gwps
);
1370 end
= utf8encode(data
->wps_progress_pat
[0], buf
);
1375 case SKIN_TOKEN_PLAYER_PROGRESSBAR
:
1378 /* we need 11 characters (full line) for
1380 strlcpy(buf
, " ", buf_size
);
1381 format_player_fullbar(gwps
,buf
,buf_size
);
1382 DEBUGF("bar='%s'\n",buf
);
1386 /* Tell the user if we have an OldPlayer */
1387 strlcpy(buf
, " <Old LCD> ", buf_size
);
1393 #ifdef HAVE_LCD_BITMAP
1395 case SKIN_TOKEN_PEAKMETER_LEFT
:
1396 case SKIN_TOKEN_PEAKMETER_RIGHT
:
1398 int left
, right
, val
;
1399 peak_meter_current_vals(&left
, &right
);
1400 val
= token
->type
== SKIN_TOKEN_PEAKMETER_LEFT
?
1402 val
= peak_meter_scale_value(val
, limit
==1 ? MAX_PEAK
: limit
);
1405 snprintf(buf
, buf_size
, "%d", val
);
1406 data
->peak_meter_enabled
= true;
1411 #if (CONFIG_CODEC == SWCODEC)
1412 case SKIN_TOKEN_CROSSFADE
:
1413 #ifdef HAVE_CROSSFADE
1415 *intval
= global_settings
.crossfade
+ 1;
1416 snprintf(buf
, buf_size
, "%d", global_settings
.crossfade
);
1418 snprintf(buf
, buf_size
, "%d", 0);
1422 case SKIN_TOKEN_REPLAYGAIN
:
1424 int globtype
= global_settings
.replaygain_settings
.type
;
1428 if (globtype
== REPLAYGAIN_OFF
)
1432 int type
= id3_get_replaygain_mode(id3
);
1435 val
= 6; /* no tag */
1439 if (globtype
== REPLAYGAIN_SHUFFLE
)
1452 /* due to above, coming here with !id3 shouldn't be possible */
1455 replaygain_itoa(buf
, buf_size
, id3
->track_level
);
1459 replaygain_itoa(buf
, buf_size
, id3
->album_level
);
1464 #endif /* (CONFIG_CODEC == SWCODEC) */
1466 #if (CONFIG_CODEC != MAS3507D) && defined (HAVE_PITCHCONTROL)
1467 case SKIN_TOKEN_SOUND_PITCH
:
1469 int32_t pitch
= sound_get_pitch();
1470 snprintf(buf
, buf_size
, "%ld.%ld",
1471 pitch
/ PITCH_SPEED_PRECISION
,
1472 (pitch
% PITCH_SPEED_PRECISION
) / (PITCH_SPEED_PRECISION
/ 10));
1475 *intval
= pitch_speed_enum(limit
, pitch
,
1476 PITCH_SPEED_PRECISION
* 100);
1481 #if (CONFIG_CODEC == SWCODEC) && defined (HAVE_PITCHCONTROL)
1482 case SKIN_TOKEN_SOUND_SPEED
:
1484 int32_t pitch
= sound_get_pitch();
1486 if (dsp_timestretch_available())
1487 speed
= GET_SPEED(pitch
, dsp_get_timestretch());
1490 snprintf(buf
, buf_size
, "%ld.%ld",
1491 speed
/ PITCH_SPEED_PRECISION
,
1492 (speed
% PITCH_SPEED_PRECISION
) / (PITCH_SPEED_PRECISION
/ 10));
1494 *intval
= pitch_speed_enum(limit
, speed
,
1495 PITCH_SPEED_PRECISION
* 100);
1500 case SKIN_TOKEN_MAIN_HOLD
:
1501 #ifdef HAVE_TOUCHSCREEN
1502 if (data
->touchscreen_locked
)
1505 #ifdef HAS_BUTTON_HOLD
1508 if (is_keys_locked())
1509 #endif /*hold switch or softlock*/
1514 #ifdef HAS_REMOTE_BUTTON_HOLD
1515 case SKIN_TOKEN_REMOTE_HOLD
:
1516 if (remote_button_hold())
1522 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
1523 case SKIN_TOKEN_VLED_HDD
:
1529 case SKIN_TOKEN_BUTTON_VOLUME
:
1530 if (global_status
.last_volume_change
&&
1531 TIME_BEFORE(current_tick
, global_status
.last_volume_change
+
1536 case SKIN_TOKEN_LASTTOUCH
:
1538 #ifdef HAVE_TOUCHSCREEN
1539 unsigned int last_touch
= touchscreen_last_touch();
1540 char *skin_base
= get_skin_buffer(data
);
1541 struct touchregion_lastpress
*data
= SKINOFFSETTOPTR(skin_base
, token
->value
.data
);
1542 struct touchregion
*region
= SKINOFFSETTOPTR(skin_base
, data
->region
);
1544 last_touch
= region
->last_press
;
1546 if (last_touch
!= 0xffff &&
1547 TIME_BEFORE(current_tick
, data
->timeout
+ last_touch
))
1552 case SKIN_TOKEN_HAVE_TOUCH
:
1553 #ifdef HAVE_TOUCHSCREEN
1559 case SKIN_TOKEN_SETTING
:
1561 const struct settings_list
*s
= settings
+token
->value
.i
;
1564 /* Handle contionals */
1565 switch (s
->flags
&F_T_MASK
)
1569 if (s
->flags
&F_T_SOUND
)
1571 /* %?St|name|<min|min+1|...|max-1|max> */
1572 int sound_setting
= s
->sound_setting
->setting
;
1573 /* settings with decimals can't be used in conditionals */
1574 if (sound_numdecimals(sound_setting
) == 0)
1576 *intval
= (*(int*)s
->setting
-sound_min(sound_setting
))
1577 /sound_steps(sound_setting
) + 1;
1582 else if (s
->flags
&F_RGB
)
1583 /* %?St|name|<#000000|#000001|...|#FFFFFF> */
1584 /* shouldn't overflow since colors are stored
1586 * but this is pretty useless anyway */
1587 *intval
= *(int*)s
->setting
+ 1;
1588 else if (s
->cfg_vals
== NULL
)
1589 /* %?St|name|<1st choice|2nd choice|...> */
1590 *intval
= (*(int*)s
->setting
-s
->int_setting
->min
)
1591 /s
->int_setting
->step
+ 1;
1593 /* %?St|name|<1st choice|2nd choice|...> */
1594 /* Not sure about this one. cfg_name/vals are
1595 * indexed from 0 right? */
1596 *intval
= *(int*)s
->setting
+ 1;
1599 /* %?St|name|<if true|if false> */
1600 *intval
= *(bool*)s
->setting
?1:2;
1604 /* %?St|name|<if non empty string|if empty>
1605 * The string's emptyness discards the setting's
1606 * prefix and suffix */
1607 *intval
= ((char*)s
->setting
)[0]?1:2;
1608 /* if there is a prefix we should ignore it here */
1609 if (s
->filename_setting
->prefix
)
1610 return (char*)s
->setting
;
1613 /* This shouldn't happen ... but you never know */
1618 /* Special handlng for filenames because we dont want to show the prefix */
1619 if ((s
->flags
&F_T_MASK
) == F_T_CHARPTR
||
1620 (s
->flags
&F_T_MASK
) == F_T_UCHARPTR
)
1622 if (s
->filename_setting
->prefix
)
1623 return (char*)s
->setting
;
1625 cfg_to_string(token
->value
.i
,buf
,buf_size
);
1628 case SKIN_TOKEN_HAVE_TUNER
:
1630 if (radio_hardware_present())
1634 /* Recording tokens */
1635 case SKIN_TOKEN_HAVE_RECORDING
:
1636 #ifdef HAVE_RECORDING
1642 #ifdef HAVE_RECORDING
1643 case SKIN_TOKEN_IS_RECORDING
:
1644 if (audio_status() == AUDIO_STATUS_RECORD
)
1647 case SKIN_TOKEN_REC_FREQ
: /* order from REC_FREQ_CFG_VAL_LIST */
1649 #if CONFIG_CODEC == SWCODEC
1650 unsigned long samprk
;
1651 int rec_freq
= global_settings
.rec_frequency
;
1656 #if defined(HAVE_SPDIF_REC)
1657 if (global_settings
.rec_source
== AUDIO_SRC_SPDIF
)
1659 /* Use rate in use, not current measured rate if it changed */
1660 samprk
= pcm_rec_sample_rate();
1662 while (rec_freq
< SAMPR_NUM_FREQ
&&
1663 audio_master_sampr_list
[rec_freq
] != samprk
)
1670 samprk
= rec_freq_sampr
[rec_freq
];
1671 #endif /* SIMULATOR */
1676 REC_HAVE_96_(case REC_FREQ_96
:
1679 REC_HAVE_88_(case REC_FREQ_88
:
1682 REC_HAVE_64_(case REC_FREQ_64
:
1685 REC_HAVE_48_(case REC_FREQ_48
:
1688 REC_HAVE_44_(case REC_FREQ_44
:
1691 REC_HAVE_32_(case REC_FREQ_32
:
1694 REC_HAVE_24_(case REC_FREQ_24
:
1697 REC_HAVE_22_(case REC_FREQ_22
:
1700 REC_HAVE_16_(case REC_FREQ_16
:
1703 REC_HAVE_12_(case REC_FREQ_12
:
1706 REC_HAVE_11_(case REC_FREQ_11
:
1709 REC_HAVE_8_(case REC_FREQ_8
:
1714 snprintf(buf
, buf_size
, "%lu.%1lu", samprk
/1000,samprk
%1000);
1717 static const char * const freq_strings
[] =
1718 {"--", "44", "48", "32", "22", "24", "16"};
1719 int freq
= 1 + global_settings
.rec_frequency
;
1720 #ifdef HAVE_SPDIF_REC
1721 if (global_settings
.rec_source
== AUDIO_SRC_SPDIF
)
1723 /* Can't measure S/PDIF sample rate on Archos/Sim yet */
1726 #endif /* HAVE_SPDIF_IN */
1728 *intval
= freq
+1; /* so the token gets a value 1<=x<=7 */
1729 snprintf(buf
, buf_size
, "%s\n",
1730 freq_strings
[global_settings
.rec_frequency
]);
1734 #if CONFIG_CODEC == SWCODEC
1735 case SKIN_TOKEN_REC_ENCODER
:
1737 int rec_format
= global_settings
.rec_format
+1; /* WAV, AIFF, WV, MPEG */
1739 *intval
= rec_format
;
1742 case REC_FORMAT_PCM_WAV
:
1744 case REC_FORMAT_AIFF
:
1746 case REC_FORMAT_WAVPACK
:
1748 case REC_FORMAT_MPA_L3
:
1756 case SKIN_TOKEN_REC_BITRATE
:
1757 #if CONFIG_CODEC == SWCODEC
1758 if (global_settings
.rec_format
== REC_FORMAT_MPA_L3
)
1762 #if 0 /* FIXME: I dont know if this is needed? */
1763 switch (1<<global_settings
.mp3_enc_config
.bitrate
)
1765 case MP3_BITR_CAP_8
:
1768 case MP3_BITR_CAP_16
:
1771 case MP3_BITR_CAP_24
:
1774 case MP3_BITR_CAP_32
:
1777 case MP3_BITR_CAP_40
:
1780 case MP3_BITR_CAP_48
:
1783 case MP3_BITR_CAP_56
:
1786 case MP3_BITR_CAP_64
:
1789 case MP3_BITR_CAP_80
:
1792 case MP3_BITR_CAP_96
:
1795 case MP3_BITR_CAP_112
:
1798 case MP3_BITR_CAP_128
:
1801 case MP3_BITR_CAP_144
:
1804 case MP3_BITR_CAP_160
:
1807 case MP3_BITR_CAP_192
:
1812 *intval
= global_settings
.mp3_enc_config
.bitrate
+1;
1814 snprintf(buf
, buf_size
, "%lu", global_settings
.mp3_enc_config
.bitrate
+1);
1818 return NULL
; /* Fixme later */
1819 #else /* CONFIG_CODEC == HWCODEC */
1821 *intval
= global_settings
.rec_quality
+1;
1822 snprintf(buf
, buf_size
, "%d", global_settings
.rec_quality
);
1825 case SKIN_TOKEN_REC_MONO
:
1826 if (!global_settings
.rec_channels
)
1830 case SKIN_TOKEN_REC_SECONDS
:
1832 int time
= (audio_recorded_time() / HZ
) % 60;
1835 snprintf(buf
, buf_size
, "%02d", time
);
1838 case SKIN_TOKEN_REC_MINUTES
:
1840 int time
= (audio_recorded_time() / HZ
) / 60;
1843 snprintf(buf
, buf_size
, "%02d", time
);
1846 case SKIN_TOKEN_REC_HOURS
:
1848 int time
= (audio_recorded_time() / HZ
) / 3600;
1851 snprintf(buf
, buf_size
, "%02d", time
);
1855 #endif /* HAVE_RECORDING */
1857 case SKIN_TOKEN_CURRENT_SCREEN
:
1859 int curr_screen
= get_current_activity();
1862 *intval
= curr_screen
;
1864 snprintf(buf
, buf_size
, "%d", curr_screen
);
1868 case SKIN_TOKEN_LANG_IS_RTL
:
1869 return lang_is_rtl() ? "r" : NULL
;
1871 #ifdef HAVE_SKIN_VARIABLES
1872 case SKIN_TOKEN_VAR_GETVAL
:
1874 char *skin_base
= get_skin_buffer(data
);
1875 struct skin_var
* var
= SKINOFFSETTOPTR(skin_base
, token
->value
.data
);
1877 *intval
= var
->value
;
1878 snprintf(buf
, buf_size
, "%d", var
->value
);
1882 case SKIN_TOKEN_VAR_TIMEOUT
:
1884 char *skin_base
= get_skin_buffer(data
);
1885 struct skin_var_lastchange
*data
= SKINOFFSETTOPTR(skin_base
, token
->value
.data
);
1886 struct skin_var
* var
= SKINOFFSETTOPTR(skin_base
, data
->var
);
1887 unsigned int last_change
= var
->last_changed
;
1889 if (last_change
!= 0xffff &&
1890 TIME_BEFORE(current_tick
, data
->timeout
+ last_change
))