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 if (intval
&& limit
== TOKEN_VALUE_ONLY
)
310 *intval
= elapsed
/1000;
311 format_time(buf
, buf_size
, elapsed
);
314 case SKIN_TOKEN_TRACK_TIME_REMAINING
:
315 if (intval
&& limit
== TOKEN_VALUE_ONLY
)
316 *intval
= (length
- elapsed
)/1000;
317 format_time(buf
, buf_size
, length
- elapsed
);
320 case SKIN_TOKEN_TRACK_LENGTH
:
321 if (intval
&& limit
== TOKEN_VALUE_ONLY
)
322 *intval
= length
/1000;
323 format_time(buf
, buf_size
, length
);
326 case SKIN_TOKEN_TRACK_ELAPSED_PERCENT
:
332 if (limit
== TOKEN_VALUE_ONLY
)
333 limit
= 100; /* make it a percentage */
334 *intval
= limit
* elapsed
/ length
+ 1;
336 snprintf(buf
, buf_size
, "%lu", 100 * elapsed
/ length
);
339 case SKIN_TOKEN_TRACK_STARTING
:
341 unsigned long time
= token
->value
.i
* (HZ
/TIMEOUT_UNIT
);
346 case SKIN_TOKEN_TRACK_ENDING
:
348 unsigned long time
= token
->value
.i
* (HZ
/TIMEOUT_UNIT
);
349 if (length
- elapsed
< time
)
354 case SKIN_TOKEN_FILE_CODEC
:
357 if(id3
->codectype
== AFMT_UNKNOWN
)
358 *intval
= AFMT_NUM_CODECS
;
360 *intval
= id3
->codectype
;
362 return get_codectype(id3
);
364 case SKIN_TOKEN_FILE_FREQUENCY
:
365 snprintf(buf
, buf_size
, "%ld", id3
->frequency
);
367 case SKIN_TOKEN_FILE_FREQUENCY_KHZ
:
368 /* ignore remainders < 100, so 22050 Hz becomes just 22k */
369 if ((id3
->frequency
% 1000) < 100)
370 snprintf(buf
, buf_size
, "%ld", id3
->frequency
/ 1000);
372 snprintf(buf
, buf_size
, "%ld.%lu",
373 id3
->frequency
/ 1000,
374 (id3
->frequency
% 1000) / 100);
376 case SKIN_TOKEN_FILE_VBR
:
377 return (id3
->vbr
) ? "(avg)" : NULL
;
378 case SKIN_TOKEN_FILE_SIZE
:
379 snprintf(buf
, buf_size
, "%ld", id3
->filesize
/ 1024);
383 case SKIN_TOKEN_DATABASE_PLAYCOUNT
:
385 *intval
= id3
->playcount
+ 1;
386 snprintf(buf
, buf_size
, "%ld", id3
->playcount
);
388 case SKIN_TOKEN_DATABASE_RATING
:
390 *intval
= id3
->rating
+ 1;
391 snprintf(buf
, buf_size
, "%d", id3
->rating
);
393 case SKIN_TOKEN_DATABASE_AUTOSCORE
:
395 *intval
= id3
->score
+ 1;
396 snprintf(buf
, buf_size
, "%d", id3
->score
);
401 return get_filename_token(token
, id3
->path
, buf
, buf_size
);
404 else /* id3 == NULL, handle the error based on the expected return type */
408 /* Most tokens expect NULL on error so leave that for the default case,
409 * The ones that expect "0" need to be handled */
410 case SKIN_TOKEN_FILE_FREQUENCY
:
411 case SKIN_TOKEN_FILE_FREQUENCY_KHZ
:
412 case SKIN_TOKEN_FILE_SIZE
:
414 case SKIN_TOKEN_DATABASE_PLAYCOUNT
:
415 case SKIN_TOKEN_DATABASE_RATING
:
416 case SKIN_TOKEN_DATABASE_AUTOSCORE
:
422 return get_filename_token(token
, filename
, buf
, buf_size
);
430 /* Formats the frequency (specified in Hz) in MHz, */
431 /* with one or two digits after the decimal point -- */
432 /* depending on the frequency changing step. */
434 static char *format_freq_MHz(int freq
, int freq_step
, char *buf
, int buf_size
)
438 if (freq_step
< 100000)
440 /* Format with two digits after decimal point */
446 /* Format with one digit after decimal point */
450 div
= 1000000 / scale
;
452 snprintf(buf
, buf_size
, fmt
, freq
/div
, freq
%div
);
457 /* Tokens which are really only used by the radio screen go in here */
458 const char *get_radio_token(struct wps_token
*token
, int preset_offset
,
459 char *buf
, int buf_size
, int limit
, int *intval
)
461 const struct fm_region_data
*region_data
=
462 &(fm_region_data
[global_settings
.fm_region
]);
466 /* Radio/tuner tokens */
467 case SKIN_TOKEN_TUNER_TUNED
:
468 if (tuner_get(RADIO_TUNED
))
471 case SKIN_TOKEN_TUNER_SCANMODE
:
472 if (radio_scan_mode())
475 case SKIN_TOKEN_TUNER_STEREO
:
476 if (radio_is_stereo())
479 case SKIN_TOKEN_TUNER_MINFREQ
: /* changes based on "region" */
480 return format_freq_MHz(region_data
->freq_min
,
481 region_data
->freq_step
, buf
, buf_size
);
482 case SKIN_TOKEN_TUNER_MAXFREQ
: /* changes based on "region" */
483 return format_freq_MHz(region_data
->freq_max
,
484 region_data
->freq_step
, buf
, buf_size
);
485 case SKIN_TOKEN_TUNER_CURFREQ
:
486 return format_freq_MHz(radio_current_frequency(),
487 region_data
->freq_step
, buf
, buf_size
);
488 #ifdef HAVE_RADIO_RSSI
489 case SKIN_TOKEN_TUNER_RSSI
:
490 snprintf(buf
, buf_size
, "%d",tuner_get(RADIO_RSSI
));
493 int val
= tuner_get(RADIO_RSSI
);
494 int min
= tuner_get(RADIO_RSSI_MIN
);
495 int max
= tuner_get(RADIO_RSSI_MAX
);
496 if (limit
== TOKEN_VALUE_ONLY
)
502 *intval
= 1+(limit
-1)*(val
-min
)/(max
-1-min
);
506 case SKIN_TOKEN_TUNER_RSSI_MIN
:
507 snprintf(buf
, buf_size
, "%d",tuner_get(RADIO_RSSI_MIN
));
509 case SKIN_TOKEN_TUNER_RSSI_MAX
:
510 snprintf(buf
, buf_size
, "%d",tuner_get(RADIO_RSSI_MAX
));
513 case SKIN_TOKEN_PRESET_NAME
:
514 case SKIN_TOKEN_PRESET_FREQ
:
515 case SKIN_TOKEN_PRESET_ID
:
517 int preset_count
= radio_preset_count();
518 int cur_preset
= radio_current_preset();
519 if (preset_count
== 0 || cur_preset
< 0)
521 int preset
= cur_preset
+ preset_offset
;
522 /* make sure it's in the valid range */
523 preset
%= preset_count
;
525 preset
+= preset_count
;
526 if (token
->type
== SKIN_TOKEN_PRESET_NAME
)
527 snprintf(buf
, buf_size
, "%s", radio_get_preset(preset
)->name
);
528 else if (token
->type
== SKIN_TOKEN_PRESET_FREQ
)
529 format_freq_MHz(radio_get_preset(preset
)->frequency
,
530 region_data
->freq_step
, buf
, buf_size
);
532 snprintf(buf
, buf_size
, "%d", preset
+ 1);
535 case SKIN_TOKEN_PRESET_COUNT
:
536 snprintf(buf
, buf_size
, "%d", radio_preset_count());
538 *intval
= radio_preset_count();
540 case SKIN_TOKEN_HAVE_RDS
:
543 case SKIN_TOKEN_RDS_NAME
:
544 return tuner_get_rds_info(RADIO_RDS_NAME
);
545 case SKIN_TOKEN_RDS_TEXT
:
546 return tuner_get_rds_info(RADIO_RDS_TEXT
);
548 return NULL
; /* end of the SKIN_TOKEN_HAVE_RDS case */
549 #endif /* HAVE_RDS_CAP */
557 static struct mp3entry
* get_mp3entry_from_offset(int offset
, char **filename
)
559 struct mp3entry
* pid3
= NULL
;
560 struct wps_state
*state
= skin_get_global_state();
561 struct cuesheet
*cue
= state
->id3
? state
->id3
->cuesheet
: NULL
;
562 const char *fname
= NULL
;
563 if (cue
&& cue
->curr_track_idx
+ offset
< cue
->track_count
)
565 else if (offset
== 0)
567 else if (offset
== 1)
571 static char filename_buf
[MAX_PATH
+ 1];
572 fname
= playlist_peek(offset
, filename_buf
, sizeof(filename_buf
));
573 *filename
= (char*)fname
;
574 #if CONFIG_CODEC == SWCODEC
575 static struct mp3entry tempid3
;
577 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
578 tagcache_fill_tags(&tempid3
, fname
) ||
580 audio_peek_track(&tempid3
, offset
)
590 #ifdef HAVE_LCD_CHARCELLS
591 static void format_player_progress(struct gui_wps
*gwps
)
593 struct wps_state
*state
= skin_get_global_state();
594 struct screen
*display
= gwps
->display
;
595 unsigned char progress_pattern
[7];
600 if (LIKELY(state
->id3
))
602 elapsed
= state
->id3
->elapsed
;
603 length
= state
->id3
->length
;
612 pos
= 36 * (elapsed
+ state
->ff_rewind_count
) / length
;
614 for (i
= 0; i
< 7; i
++, pos
-= 5)
617 progress_pattern
[i
] = 0x1fu
;
619 progress_pattern
[i
] = 0x00u
;
621 progress_pattern
[i
] = 0x1fu
>> pos
;
624 display
->define_pattern(gwps
->data
->wps_progress_pat
[0], progress_pattern
);
627 static void format_player_fullbar(struct gui_wps
*gwps
, char* buf
, int buf_size
)
629 static const unsigned char numbers
[10][4] = {
630 {0x0e, 0x0a, 0x0a, 0x0e}, /* 0 */
631 {0x04, 0x0c, 0x04, 0x04}, /* 1 */
632 {0x0e, 0x02, 0x04, 0x0e}, /* 2 */
633 {0x0e, 0x02, 0x06, 0x0e}, /* 3 */
634 {0x08, 0x0c, 0x0e, 0x04}, /* 4 */
635 {0x0e, 0x0c, 0x02, 0x0c}, /* 5 */
636 {0x0e, 0x08, 0x0e, 0x0e}, /* 6 */
637 {0x0e, 0x02, 0x04, 0x08}, /* 7 */
638 {0x0e, 0x0e, 0x0a, 0x0e}, /* 8 */
639 {0x0e, 0x0e, 0x02, 0x0e} /* 9 */
642 struct wps_state
*state
= skin_get_global_state();
643 struct screen
*display
= gwps
->display
;
644 struct wps_data
*data
= gwps
->data
;
645 unsigned char progress_pattern
[7];
655 if (LIKELY(state
->id3
))
657 elapsed
= state
->id3
->elapsed
;
658 length
= state
->id3
->length
;
666 if (buf_size
< 34) /* worst case: 11x UTF-8 char + \0 */
669 time
= elapsed
+ state
->ff_rewind_count
;
671 pos
= 55 * time
/ length
;
673 memset(timestr
, 0, sizeof(timestr
));
674 format_time(timestr
, sizeof(timestr
)-2, time
);
675 timestr
[strlen(timestr
)] = ':'; /* always safe */
677 for (i
= 0; i
< 11; i
++, pos
-= 5)
680 memset(progress_pattern
, 0, sizeof(progress_pattern
));
682 if ((digit
= timestr
[time_idx
]))
687 if (timestr
[time_idx
+ 1] == ':') /* ones, left aligned */
689 memcpy(progress_pattern
, numbers
[digit
], 4);
692 else /* tens, shifted right */
694 for (j
= 0; j
< 4; j
++)
695 progress_pattern
[j
] = numbers
[digit
][j
] >> 1;
697 if (time_idx
> 0) /* not the first group, add colon in front */
699 progress_pattern
[1] |= 0x10u
;
700 progress_pattern
[3] |= 0x10u
;
706 progress_pattern
[5] = progress_pattern
[6] = 0x1fu
;
709 if (pos
> 0 && pos
< 5)
712 progress_pattern
[5] = progress_pattern
[6] = (~0x1fu
>> pos
) & 0x1fu
;
715 if (softchar
&& pat_idx
< 8)
717 display
->define_pattern(data
->wps_progress_pat
[pat_idx
],
719 buf
= utf8encode(data
->wps_progress_pat
[pat_idx
], buf
);
723 buf
= utf8encode(' ', buf
);
725 buf
= utf8encode(0xe115, buf
); /* 2/7 _ */
730 #endif /* HAVE_LCD_CHARCELLS */
732 /* Don't inline this; it was broken out of get_token_value to reduce stack
735 static const char* NOINLINE
get_lif_token_value(struct gui_wps
*gwps
,
736 struct logical_if
*lif
,
737 int offset
, char *buf
,
740 int a
= lif
->num_options
;
742 bool number_set
= true;
743 struct wps_token
*liftoken
= SKINOFFSETTOPTR(get_skin_buffer(gwps
->data
), lif
->token
);
744 const char* out_text
= get_token_value(gwps
, liftoken
, offset
, buf
, buf_size
, &a
);
745 if (a
== -1 && liftoken
->type
!= SKIN_TOKEN_VOLUME
)
747 a
= (out_text
&& *out_text
) ? 1 : 0;
750 switch (lif
->operand
.type
)
754 char *cmp
= SKINOFFSETTOPTR(get_skin_buffer(gwps
->data
), lif
->operand
.data
.text
);
755 if (out_text
== NULL
)
757 a
= strcmp(out_text
, cmp
);
762 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
)
930 start_byte
= utf8seek(token_val
, ss
->start
);
932 if (ss
->length
< 0 || (ss
->start
+ ss
->length
) > utf8_len
)
933 end_byte
= strlen(token_val
);
935 end_byte
= utf8seek(token_val
, ss
->start
+ ss
->length
);
937 byte_len
= end_byte
- start_byte
;
939 if (token_val
!= buf
)
940 memcpy(buf
, &token_val
[start_byte
], byte_len
);
942 buf
= &buf
[start_byte
];
944 buf
[byte_len
] = '\0';
951 case SKIN_TOKEN_CHARACTER
:
952 if (token
->value
.c
== '\n')
954 return &(token
->value
.c
);
956 case SKIN_TOKEN_STRING
:
957 return (char*)SKINOFFSETTOPTR(get_skin_buffer(data
), token
->value
.data
);
959 case SKIN_TOKEN_TRANSLATEDSTRING
:
960 return (char*)P2STR(ID2P(token
->value
.i
));
962 case SKIN_TOKEN_PLAYLIST_ENTRIES
:
963 snprintf(buf
, buf_size
, "%d", playlist_amount());
965 *intval
= playlist_amount();
967 #ifdef HAVE_LCD_BITMAP
968 case SKIN_TOKEN_LIST_TITLE_TEXT
:
969 return sb_get_title(gwps
->display
->screen_type
);
970 case SKIN_TOKEN_LIST_TITLE_ICON
:
972 *intval
= sb_get_icon(gwps
->display
->screen_type
);
973 snprintf(buf
, buf_size
, "%d",sb_get_icon(gwps
->display
->screen_type
));
975 case SKIN_TOKEN_LIST_ITEM_TEXT
:
977 struct listitem
*li
= (struct listitem
*)SKINOFFSETTOPTR(get_skin_buffer(data
), token
->value
.data
);
978 return skinlist_get_item_text(li
->offset
, li
->wrap
, buf
, buf_size
);
980 case SKIN_TOKEN_LIST_ITEM_NUMBER
:
982 *intval
= skinlist_get_item_number() + 1;
983 snprintf(buf
, buf_size
, "%d",skinlist_get_item_number() + 1);
985 case SKIN_TOKEN_LIST_ITEM_IS_SELECTED
:
986 return skinlist_is_selected_item()?"s":"";
987 case SKIN_TOKEN_LIST_ITEM_ICON
:
989 struct listitem
*li
= (struct listitem
*)SKINOFFSETTOPTR(get_skin_buffer(data
), token
->value
.data
);
990 int icon
= skinlist_get_item_icon(li
->offset
, li
->wrap
);
993 snprintf(buf
, buf_size
, "%d", icon
);
996 case SKIN_TOKEN_LIST_NEEDS_SCROLLBAR
:
997 return skinlist_needs_scrollbar(gwps
->display
->screen_type
) ? "s" : "";
999 case SKIN_TOKEN_PLAYLIST_NAME
:
1000 return playlist_name(NULL
, buf
, buf_size
);
1002 case SKIN_TOKEN_PLAYLIST_POSITION
:
1003 snprintf(buf
, buf_size
, "%d", playlist_get_display_index()+offset
);
1005 *intval
= playlist_get_display_index()+offset
;
1008 case SKIN_TOKEN_PLAYLIST_SHUFFLE
:
1009 if ( global_settings
.playlist_shuffle
)
1015 case SKIN_TOKEN_VOLUME
:
1016 snprintf(buf
, buf_size
, "%d", global_settings
.volume
);
1019 int minvol
= sound_min(SOUND_VOLUME
);
1020 if (limit
== TOKEN_VALUE_ONLY
)
1022 *intval
= global_settings
.volume
;
1024 else if (global_settings
.volume
== minvol
)
1028 else if (global_settings
.volume
== 0)
1030 *intval
= limit
- 1;
1032 else if (global_settings
.volume
> 0)
1038 *intval
= (limit
-3) * (global_settings
.volume
- minvol
- 1)
1039 / (-1 - minvol
) + 2;
1043 #ifdef HAVE_ALBUMART
1044 case SKIN_TOKEN_ALBUMART_FOUND
:
1045 if (SKINOFFSETTOPTR(get_skin_buffer(data
), data
->albumart
))
1048 handle
= playback_current_aa_hid(data
->playback_aa_slot
);
1050 if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF
))
1052 struct skin_albumart
*aa
= SKINOFFSETTOPTR(get_skin_buffer(data
), data
->albumart
);
1053 struct dim dim
= {aa
->width
, aa
->height
};
1054 handle
= radio_get_art_hid(&dim
);
1063 case SKIN_TOKEN_BATTERY_PERCENT
:
1065 int l
= battery_level();
1069 if (limit
== TOKEN_VALUE_ONLY
)
1075 limit
= MAX(limit
, 3);
1077 /* First enum is used for "unknown level",
1078 * last enum is used for 100%.
1080 *intval
= (limit
- 2) * l
/ 100 + 2;
1088 snprintf(buf
, buf_size
, "%d", l
);
1095 case SKIN_TOKEN_BATTERY_VOLTS
:
1097 int v
= battery_voltage();
1099 snprintf(buf
, buf_size
, "%d.%02d", v
/ 1000, (v
% 1000) / 10);
1106 case SKIN_TOKEN_BATTERY_TIME
:
1108 int t
= battery_time();
1110 snprintf(buf
, buf_size
, "%dh %dm", t
/ 60, t
% 60);
1117 case SKIN_TOKEN_BATTERY_CHARGER_CONNECTED
:
1119 if(charger_input_state
==CHARGER
)
1125 #if CONFIG_CHARGING >= CHARGING_MONITOR
1126 case SKIN_TOKEN_BATTERY_CHARGING
:
1128 if (charge_state
== CHARGING
|| charge_state
== TOPOFF
) {
1135 #ifdef HAVE_USB_POWER
1136 case SKIN_TOKEN_USB_POWERED
:
1141 case SKIN_TOKEN_BATTERY_SLEEPTIME
:
1143 if (get_sleep_timer() == 0)
1147 format_time(buf
, buf_size
, get_sleep_timer() * 1000);
1152 case SKIN_TOKEN_PLAYBACK_STATUS
:
1154 int status
= current_playmode();
1156 int mode
= 1; /* stop */
1157 if (status
== STATUS_PLAY
)
1158 mode
= 2; /* play */
1159 if (state
->is_fading
||
1160 (status
== STATUS_PAUSE
&& !status_get_ffmode()))
1161 mode
= 3; /* pause */
1164 if (status_get_ffmode() == STATUS_FASTFORWARD
)
1166 if (status_get_ffmode() == STATUS_FASTBACKWARD
)
1169 #ifdef HAVE_RECORDING
1171 if (status
== STATUS_RECORD
)
1173 else if (status
== STATUS_RECORD_PAUSE
)
1178 if (status
== STATUS_RADIO
)
1180 else if (status
== STATUS_RADIO_PAUSE
)
1188 snprintf(buf
, buf_size
, "%d", mode
-1);
1192 case SKIN_TOKEN_REPEAT_MODE
:
1194 *intval
= global_settings
.repeat_mode
+ 1;
1195 snprintf(buf
, buf_size
, "%d", global_settings
.repeat_mode
);
1198 case SKIN_TOKEN_RTC_PRESENT
:
1206 case SKIN_TOKEN_RTC_12HOUR_CFG
:
1208 *intval
= global_settings
.timeformat
+ 1;
1209 snprintf(buf
, buf_size
, "%d", global_settings
.timeformat
);
1212 case SKIN_TOKEN_RTC_DAY_OF_MONTH
:
1213 /* d: day of month (01..31) */
1214 snprintf(buf
, buf_size
, "%02d", tm
->tm_mday
);
1216 *intval
= tm
->tm_mday
- 1;
1219 case SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED
:
1220 /* e: day of month, blank padded ( 1..31) */
1221 snprintf(buf
, buf_size
, "%2d", tm
->tm_mday
);
1223 *intval
= tm
->tm_mday
- 1;
1226 case SKIN_TOKEN_RTC_HOUR_24_ZERO_PADDED
:
1227 /* H: hour (00..23) */
1228 snprintf(buf
, buf_size
, "%02d", tm
->tm_hour
);
1230 *intval
= tm
->tm_hour
;
1233 case SKIN_TOKEN_RTC_HOUR_24
:
1234 /* k: hour ( 0..23) */
1235 snprintf(buf
, buf_size
, "%2d", tm
->tm_hour
);
1237 *intval
= tm
->tm_hour
;
1240 case SKIN_TOKEN_RTC_HOUR_12_ZERO_PADDED
:
1241 /* I: hour (01..12) */
1242 snprintf(buf
, buf_size
, "%02d",
1243 (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12);
1245 *intval
= (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12;
1248 case SKIN_TOKEN_RTC_HOUR_12
:
1249 /* l: hour ( 1..12) */
1250 snprintf(buf
, buf_size
, "%2d",
1251 (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12);
1253 *intval
= (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12;
1256 case SKIN_TOKEN_RTC_MONTH
:
1257 /* m: month (01..12) */
1259 *intval
= tm
->tm_mon
+ 1;
1260 snprintf(buf
, buf_size
, "%02d", tm
->tm_mon
+ 1);
1263 case SKIN_TOKEN_RTC_MINUTE
:
1264 /* M: minute (00..59) */
1265 snprintf(buf
, buf_size
, "%02d", tm
->tm_min
);
1267 *intval
= tm
->tm_min
;
1270 case SKIN_TOKEN_RTC_SECOND
:
1271 /* S: second (00..59) */
1272 snprintf(buf
, buf_size
, "%02d", tm
->tm_sec
);
1274 *intval
= tm
->tm_sec
;
1277 case SKIN_TOKEN_RTC_YEAR_2_DIGITS
:
1278 /* y: last two digits of year (00..99) */
1279 snprintf(buf
, buf_size
, "%02d", tm
->tm_year
% 100);
1281 *intval
= tm
->tm_year
% 100;
1284 case SKIN_TOKEN_RTC_YEAR_4_DIGITS
:
1285 /* Y: year (1970...) */
1286 snprintf(buf
, buf_size
, "%04d", tm
->tm_year
+ 1900);
1288 *intval
= tm
->tm_year
+ 1900;
1291 case SKIN_TOKEN_RTC_AM_PM_UPPER
:
1292 /* p: upper case AM or PM indicator */
1294 *intval
= tm
->tm_hour
/12 == 0 ? 0 : 1;
1295 return tm
->tm_hour
/12 == 0 ? "AM" : "PM";
1297 case SKIN_TOKEN_RTC_AM_PM_LOWER
:
1298 /* P: lower case am or pm indicator */
1300 *intval
= tm
->tm_hour
/12 == 0 ? 0 : 1;
1301 return tm
->tm_hour
/12 == 0 ? "am" : "pm";
1303 case SKIN_TOKEN_RTC_WEEKDAY_NAME
:
1304 /* a: abbreviated weekday name (Sun..Sat) */
1305 return str(LANG_WEEKDAY_SUNDAY
+ tm
->tm_wday
);
1307 case SKIN_TOKEN_RTC_MONTH_NAME
:
1308 /* b: abbreviated month name (Jan..Dec) */
1309 return str(LANG_MONTH_JANUARY
+ tm
->tm_mon
);
1311 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_MON
:
1312 /* u: day of week (1..7); 1 is Monday */
1314 *intval
= (tm
->tm_wday
== 0) ? 7 : tm
->tm_wday
;
1315 snprintf(buf
, buf_size
, "%1d", tm
->tm_wday
+ 1);
1318 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_SUN
:
1319 /* w: day of week (0..6); 0 is Sunday */
1321 *intval
= tm
->tm_wday
+ 1;
1322 snprintf(buf
, buf_size
, "%1d", tm
->tm_wday
);
1325 case SKIN_TOKEN_RTC_DAY_OF_MONTH
:
1326 case SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED
:
1327 case SKIN_TOKEN_RTC_HOUR_24_ZERO_PADDED
:
1328 case SKIN_TOKEN_RTC_HOUR_24
:
1329 case SKIN_TOKEN_RTC_HOUR_12_ZERO_PADDED
:
1330 case SKIN_TOKEN_RTC_HOUR_12
:
1331 case SKIN_TOKEN_RTC_MONTH
:
1332 case SKIN_TOKEN_RTC_MINUTE
:
1333 case SKIN_TOKEN_RTC_SECOND
:
1334 case SKIN_TOKEN_RTC_AM_PM_UPPER
:
1335 case SKIN_TOKEN_RTC_AM_PM_LOWER
:
1336 case SKIN_TOKEN_RTC_YEAR_2_DIGITS
:
1338 case SKIN_TOKEN_RTC_YEAR_4_DIGITS
:
1340 case SKIN_TOKEN_RTC_WEEKDAY_NAME
:
1341 case SKIN_TOKEN_RTC_MONTH_NAME
:
1343 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_MON
:
1344 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_SUN
:
1348 #ifdef HAVE_LCD_CHARCELLS
1349 case SKIN_TOKEN_PROGRESSBAR
:
1352 format_player_progress(gwps
);
1353 end
= utf8encode(data
->wps_progress_pat
[0], buf
);
1358 case SKIN_TOKEN_PLAYER_PROGRESSBAR
:
1361 /* we need 11 characters (full line) for
1363 strlcpy(buf
, " ", buf_size
);
1364 format_player_fullbar(gwps
,buf
,buf_size
);
1365 DEBUGF("bar='%s'\n",buf
);
1369 /* Tell the user if we have an OldPlayer */
1370 strlcpy(buf
, " <Old LCD> ", buf_size
);
1376 #ifdef HAVE_LCD_BITMAP
1378 case SKIN_TOKEN_PEAKMETER_LEFT
:
1379 case SKIN_TOKEN_PEAKMETER_RIGHT
:
1381 int left
, right
, val
;
1382 peak_meter_current_vals(&left
, &right
);
1383 val
= token
->type
== SKIN_TOKEN_PEAKMETER_LEFT
?
1385 val
= peak_meter_scale_value(val
, limit
==1 ? MAX_PEAK
: limit
);
1388 snprintf(buf
, buf_size
, "%d", val
);
1389 data
->peak_meter_enabled
= true;
1394 #if (CONFIG_CODEC == SWCODEC)
1395 case SKIN_TOKEN_CROSSFADE
:
1396 #ifdef HAVE_CROSSFADE
1398 *intval
= global_settings
.crossfade
+ 1;
1399 snprintf(buf
, buf_size
, "%d", global_settings
.crossfade
);
1401 snprintf(buf
, buf_size
, "%d", 0);
1405 case SKIN_TOKEN_REPLAYGAIN
:
1409 if (global_settings
.replaygain_type
== REPLAYGAIN_OFF
)
1415 type
= get_replaygain_mode(id3
->track_gain
!= 0,
1416 id3
->album_gain
!= 0);
1421 val
= 6; /* no tag */
1425 if (global_settings
.replaygain_type
== REPLAYGAIN_SHUFFLE
)
1438 /* due to above, coming here with !id3 shouldn't be possible */
1441 replaygain_itoa(buf
, buf_size
, id3
->track_level
);
1445 replaygain_itoa(buf
, buf_size
, id3
->album_level
);
1450 #endif /* (CONFIG_CODEC == SWCODEC) */
1452 #if (CONFIG_CODEC != MAS3507D) && defined (HAVE_PITCHSCREEN)
1453 case SKIN_TOKEN_SOUND_PITCH
:
1455 int32_t pitch
= sound_get_pitch();
1456 snprintf(buf
, buf_size
, "%ld.%ld",
1457 pitch
/ PITCH_SPEED_PRECISION
,
1458 (pitch
% PITCH_SPEED_PRECISION
) / (PITCH_SPEED_PRECISION
/ 10));
1461 *intval
= pitch_speed_enum(limit
, pitch
,
1462 PITCH_SPEED_PRECISION
* 100);
1467 #if (CONFIG_CODEC == SWCODEC) && defined (HAVE_PITCHSCREEN)
1468 case SKIN_TOKEN_SOUND_SPEED
:
1470 int32_t pitch
= sound_get_pitch();
1472 if (dsp_timestretch_available())
1473 speed
= GET_SPEED(pitch
, dsp_get_timestretch());
1476 snprintf(buf
, buf_size
, "%ld.%ld",
1477 speed
/ PITCH_SPEED_PRECISION
,
1478 (speed
% PITCH_SPEED_PRECISION
) / (PITCH_SPEED_PRECISION
/ 10));
1480 *intval
= pitch_speed_enum(limit
, speed
,
1481 PITCH_SPEED_PRECISION
* 100);
1486 case SKIN_TOKEN_MAIN_HOLD
:
1487 #ifdef HAVE_TOUCHSCREEN
1488 if (data
->touchscreen_locked
)
1491 #ifdef HAS_BUTTON_HOLD
1494 if (is_keys_locked())
1495 #endif /*hold switch or softlock*/
1500 #ifdef HAS_REMOTE_BUTTON_HOLD
1501 case SKIN_TOKEN_REMOTE_HOLD
:
1502 if (remote_button_hold())
1508 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
1509 case SKIN_TOKEN_VLED_HDD
:
1515 case SKIN_TOKEN_BUTTON_VOLUME
:
1516 if (global_status
.last_volume_change
&&
1517 TIME_BEFORE(current_tick
, global_status
.last_volume_change
+
1522 case SKIN_TOKEN_LASTTOUCH
:
1524 #ifdef HAVE_TOUCHSCREEN
1525 unsigned int last_touch
= touchscreen_last_touch();
1526 char *skin_base
= get_skin_buffer(data
);
1527 struct touchregion_lastpress
*data
= SKINOFFSETTOPTR(skin_base
, token
->value
.data
);
1528 struct touchregion
*region
= SKINOFFSETTOPTR(skin_base
, data
->region
);
1530 last_touch
= region
->last_press
;
1532 if (last_touch
!= 0xffff &&
1533 TIME_BEFORE(current_tick
, data
->timeout
+ last_touch
))
1538 case SKIN_TOKEN_HAVE_TOUCH
:
1539 #ifdef HAVE_TOUCHSCREEN
1545 case SKIN_TOKEN_SETTING
:
1547 const struct settings_list
*s
= settings
+token
->value
.i
;
1550 /* Handle contionals */
1551 switch (s
->flags
&F_T_MASK
)
1555 if (s
->flags
&F_T_SOUND
)
1557 /* %?St|name|<min|min+1|...|max-1|max> */
1558 int sound_setting
= s
->sound_setting
->setting
;
1559 /* settings with decimals can't be used in conditionals */
1560 if (sound_numdecimals(sound_setting
) == 0)
1562 *intval
= (*(int*)s
->setting
-sound_min(sound_setting
))
1563 /sound_steps(sound_setting
) + 1;
1568 else if (s
->flags
&F_RGB
)
1569 /* %?St|name|<#000000|#000001|...|#FFFFFF> */
1570 /* shouldn't overflow since colors are stored
1572 * but this is pretty useless anyway */
1573 *intval
= *(int*)s
->setting
+ 1;
1574 else if (s
->cfg_vals
== NULL
)
1575 /* %?St|name|<1st choice|2nd choice|...> */
1576 *intval
= (*(int*)s
->setting
-s
->int_setting
->min
)
1577 /s
->int_setting
->step
+ 1;
1579 /* %?St|name|<1st choice|2nd choice|...> */
1580 /* Not sure about this one. cfg_name/vals are
1581 * indexed from 0 right? */
1582 *intval
= *(int*)s
->setting
+ 1;
1585 /* %?St|name|<if true|if false> */
1586 *intval
= *(bool*)s
->setting
?1:2;
1590 /* %?St|name|<if non empty string|if empty>
1591 * The string's emptyness discards the setting's
1592 * prefix and suffix */
1593 *intval
= ((char*)s
->setting
)[0]?1:2;
1594 /* if there is a prefix we should ignore it here */
1595 if (s
->filename_setting
->prefix
)
1596 return (char*)s
->setting
;
1599 /* This shouldn't happen ... but you never know */
1604 /* Special handlng for filenames because we dont want to show the prefix */
1605 if ((s
->flags
&F_T_MASK
) == F_T_CHARPTR
||
1606 (s
->flags
&F_T_MASK
) == F_T_UCHARPTR
)
1608 if (s
->filename_setting
->prefix
)
1609 return (char*)s
->setting
;
1611 cfg_to_string(token
->value
.i
,buf
,buf_size
);
1614 case SKIN_TOKEN_HAVE_TUNER
:
1616 if (radio_hardware_present())
1620 /* Recording tokens */
1621 case SKIN_TOKEN_HAVE_RECORDING
:
1622 #ifdef HAVE_RECORDING
1628 #ifdef HAVE_RECORDING
1629 case SKIN_TOKEN_IS_RECORDING
:
1630 if (audio_status() == AUDIO_STATUS_RECORD
)
1633 case SKIN_TOKEN_REC_FREQ
: /* order from REC_FREQ_CFG_VAL_LIST */
1635 #if CONFIG_CODEC == SWCODEC
1636 unsigned long samprk
;
1637 int rec_freq
= global_settings
.rec_frequency
;
1642 #if defined(HAVE_SPDIF_REC)
1643 if (global_settings
.rec_source
== AUDIO_SRC_SPDIF
)
1645 /* Use rate in use, not current measured rate if it changed */
1646 samprk
= pcm_rec_sample_rate();
1648 while (rec_freq
< SAMPR_NUM_FREQ
&&
1649 audio_master_sampr_list
[rec_freq
] != samprk
)
1656 samprk
= rec_freq_sampr
[rec_freq
];
1657 #endif /* SIMULATOR */
1662 REC_HAVE_96_(case REC_FREQ_96
:
1665 REC_HAVE_88_(case REC_FREQ_88
:
1668 REC_HAVE_64_(case REC_FREQ_64
:
1671 REC_HAVE_48_(case REC_FREQ_48
:
1674 REC_HAVE_44_(case REC_FREQ_44
:
1677 REC_HAVE_32_(case REC_FREQ_32
:
1680 REC_HAVE_24_(case REC_FREQ_24
:
1683 REC_HAVE_22_(case REC_FREQ_22
:
1686 REC_HAVE_16_(case REC_FREQ_16
:
1689 REC_HAVE_12_(case REC_FREQ_12
:
1692 REC_HAVE_11_(case REC_FREQ_11
:
1695 REC_HAVE_8_(case REC_FREQ_8
:
1700 snprintf(buf
, buf_size
, "%lu.%1lu", samprk
/1000,samprk
%1000);
1703 static const char * const freq_strings
[] =
1704 {"--", "44", "48", "32", "22", "24", "16"};
1705 int freq
= 1 + global_settings
.rec_frequency
;
1706 #ifdef HAVE_SPDIF_REC
1707 if (global_settings
.rec_source
== AUDIO_SRC_SPDIF
)
1709 /* Can't measure S/PDIF sample rate on Archos/Sim yet */
1712 #endif /* HAVE_SPDIF_IN */
1714 *intval
= freq
+1; /* so the token gets a value 1<=x<=7 */
1715 snprintf(buf
, buf_size
, "%s\n",
1716 freq_strings
[global_settings
.rec_frequency
]);
1720 #if CONFIG_CODEC == SWCODEC
1721 case SKIN_TOKEN_REC_ENCODER
:
1723 int rec_format
= global_settings
.rec_format
+1; /* WAV, AIFF, WV, MPEG */
1725 *intval
= rec_format
;
1728 case REC_FORMAT_PCM_WAV
:
1730 case REC_FORMAT_AIFF
:
1732 case REC_FORMAT_WAVPACK
:
1734 case REC_FORMAT_MPA_L3
:
1742 case SKIN_TOKEN_REC_BITRATE
:
1743 #if CONFIG_CODEC == SWCODEC
1744 if (global_settings
.rec_format
== REC_FORMAT_MPA_L3
)
1748 #if 0 /* FIXME: I dont know if this is needed? */
1749 switch (1<<global_settings
.mp3_enc_config
.bitrate
)
1751 case MP3_BITR_CAP_8
:
1754 case MP3_BITR_CAP_16
:
1757 case MP3_BITR_CAP_24
:
1760 case MP3_BITR_CAP_32
:
1763 case MP3_BITR_CAP_40
:
1766 case MP3_BITR_CAP_48
:
1769 case MP3_BITR_CAP_56
:
1772 case MP3_BITR_CAP_64
:
1775 case MP3_BITR_CAP_80
:
1778 case MP3_BITR_CAP_96
:
1781 case MP3_BITR_CAP_112
:
1784 case MP3_BITR_CAP_128
:
1787 case MP3_BITR_CAP_144
:
1790 case MP3_BITR_CAP_160
:
1793 case MP3_BITR_CAP_192
:
1798 *intval
= global_settings
.mp3_enc_config
.bitrate
+1;
1800 snprintf(buf
, buf_size
, "%lu", global_settings
.mp3_enc_config
.bitrate
+1);
1804 return NULL
; /* Fixme later */
1805 #else /* CONFIG_CODEC == HWCODEC */
1807 *intval
= global_settings
.rec_quality
+1;
1808 snprintf(buf
, buf_size
, "%d", global_settings
.rec_quality
);
1811 case SKIN_TOKEN_REC_MONO
:
1812 if (!global_settings
.rec_channels
)
1816 case SKIN_TOKEN_REC_SECONDS
:
1818 int time
= (audio_recorded_time() / HZ
) % 60;
1821 snprintf(buf
, buf_size
, "%02d", time
);
1824 case SKIN_TOKEN_REC_MINUTES
:
1826 int time
= (audio_recorded_time() / HZ
) / 60;
1829 snprintf(buf
, buf_size
, "%02d", time
);
1832 case SKIN_TOKEN_REC_HOURS
:
1834 int time
= (audio_recorded_time() / HZ
) / 3600;
1837 snprintf(buf
, buf_size
, "%02d", time
);
1841 #endif /* HAVE_RECORDING */
1843 case SKIN_TOKEN_CURRENT_SCREEN
:
1845 int curr_screen
= get_current_activity();
1848 *intval
= curr_screen
;
1850 snprintf(buf
, buf_size
, "%d", curr_screen
);
1854 case SKIN_TOKEN_LANG_IS_RTL
:
1855 return lang_is_rtl() ? "r" : NULL
;
1857 #ifdef HAVE_SKIN_VARIABLES
1858 case SKIN_TOKEN_VAR_GETVAL
:
1860 char *skin_base
= get_skin_buffer(data
);
1861 struct skin_var
* var
= SKINOFFSETTOPTR(skin_base
, token
->value
.data
);
1863 *intval
= var
->value
;
1864 snprintf(buf
, buf_size
, "%d", var
->value
);
1868 case SKIN_TOKEN_VAR_TIMEOUT
:
1870 char *skin_base
= get_skin_buffer(data
);
1871 struct skin_var_lastchange
*data
= SKINOFFSETTOPTR(skin_base
, token
->value
.data
);
1872 struct skin_var
* var
= SKINOFFSETTOPTR(skin_base
, data
->var
);
1873 unsigned int last_change
= var
->last_changed
;
1875 if (last_change
!= 0xffff &&
1876 TIME_BEFORE(current_tick
, data
->timeout
+ last_change
))