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
) {
259 *intval
= atoi(id3
->disc_string
);
260 return id3
->disc_string
;
264 *intval
= id3
->discnum
;
265 snprintf(buf
, buf_size
, "%d", id3
->discnum
);
269 case SKIN_TOKEN_METADATA_TRACK_NUMBER
:
270 if (id3
->track_string
) {
272 *intval
= atoi(id3
->track_string
);
273 return id3
->track_string
;
277 *intval
= id3
->tracknum
;
278 snprintf(buf
, buf_size
, "%d", id3
->tracknum
);
282 case SKIN_TOKEN_METADATA_TRACK_TITLE
:
284 case SKIN_TOKEN_METADATA_VERSION
:
285 switch (id3
->id3version
)
301 case SKIN_TOKEN_METADATA_YEAR
:
302 if( id3
->year_string
)
303 return id3
->year_string
;
305 snprintf(buf
, buf_size
, "%d", id3
->year
);
309 case SKIN_TOKEN_METADATA_COMMENT
:
311 case SKIN_TOKEN_FILE_BITRATE
:
313 snprintf(buf
, buf_size
, "%d", id3
->bitrate
);
317 case SKIN_TOKEN_TRACK_TIME_ELAPSED
:
318 if (intval
&& limit
== TOKEN_VALUE_ONLY
)
319 *intval
= elapsed
/1000;
320 format_time(buf
, buf_size
, elapsed
);
323 case SKIN_TOKEN_TRACK_TIME_REMAINING
:
324 if (intval
&& limit
== TOKEN_VALUE_ONLY
)
325 *intval
= (length
- elapsed
)/1000;
326 format_time(buf
, buf_size
, length
- elapsed
);
329 case SKIN_TOKEN_TRACK_LENGTH
:
330 if (intval
&& limit
== TOKEN_VALUE_ONLY
)
331 *intval
= length
/1000;
332 format_time(buf
, buf_size
, length
);
335 case SKIN_TOKEN_TRACK_ELAPSED_PERCENT
:
341 if (limit
== TOKEN_VALUE_ONLY
)
342 limit
= 100; /* make it a percentage */
343 *intval
= limit
* elapsed
/ length
+ 1;
345 snprintf(buf
, buf_size
, "%lu", 100 * elapsed
/ length
);
348 case SKIN_TOKEN_TRACK_STARTING
:
350 unsigned long time
= token
->value
.i
* (HZ
/TIMEOUT_UNIT
);
355 case SKIN_TOKEN_TRACK_ENDING
:
357 unsigned long time
= token
->value
.i
* (HZ
/TIMEOUT_UNIT
);
358 if (length
- elapsed
< time
)
363 case SKIN_TOKEN_FILE_CODEC
:
366 if(id3
->codectype
== AFMT_UNKNOWN
)
367 *intval
= AFMT_NUM_CODECS
;
369 *intval
= id3
->codectype
;
371 return get_codectype(id3
);
373 case SKIN_TOKEN_FILE_FREQUENCY
:
374 snprintf(buf
, buf_size
, "%ld", id3
->frequency
);
376 case SKIN_TOKEN_FILE_FREQUENCY_KHZ
:
377 /* ignore remainders < 100, so 22050 Hz becomes just 22k */
378 if ((id3
->frequency
% 1000) < 100)
379 snprintf(buf
, buf_size
, "%ld", id3
->frequency
/ 1000);
381 snprintf(buf
, buf_size
, "%ld.%lu",
382 id3
->frequency
/ 1000,
383 (id3
->frequency
% 1000) / 100);
385 case SKIN_TOKEN_FILE_VBR
:
386 return (id3
->vbr
) ? "(avg)" : NULL
;
387 case SKIN_TOKEN_FILE_SIZE
:
388 snprintf(buf
, buf_size
, "%ld", id3
->filesize
/ 1024);
392 case SKIN_TOKEN_DATABASE_PLAYCOUNT
:
394 *intval
= id3
->playcount
+ 1;
395 snprintf(buf
, buf_size
, "%ld", id3
->playcount
);
397 case SKIN_TOKEN_DATABASE_RATING
:
399 *intval
= id3
->rating
+ 1;
400 snprintf(buf
, buf_size
, "%d", id3
->rating
);
402 case SKIN_TOKEN_DATABASE_AUTOSCORE
:
404 *intval
= id3
->score
+ 1;
405 snprintf(buf
, buf_size
, "%d", id3
->score
);
410 return get_filename_token(token
, id3
->path
, buf
, buf_size
);
413 else /* id3 == NULL, handle the error based on the expected return type */
417 /* Most tokens expect NULL on error so leave that for the default case,
418 * The ones that expect "0" need to be handled */
419 case SKIN_TOKEN_FILE_FREQUENCY
:
420 case SKIN_TOKEN_FILE_FREQUENCY_KHZ
:
421 case SKIN_TOKEN_FILE_SIZE
:
423 case SKIN_TOKEN_DATABASE_PLAYCOUNT
:
424 case SKIN_TOKEN_DATABASE_RATING
:
425 case SKIN_TOKEN_DATABASE_AUTOSCORE
:
431 return get_filename_token(token
, filename
, buf
, buf_size
);
439 /* Formats the frequency (specified in Hz) in MHz, */
440 /* with one or two digits after the decimal point -- */
441 /* depending on the frequency changing step. */
443 static char *format_freq_MHz(int freq
, int freq_step
, char *buf
, int buf_size
)
447 if (freq_step
< 100000)
449 /* Format with two digits after decimal point */
455 /* Format with one digit after decimal point */
459 div
= 1000000 / scale
;
461 snprintf(buf
, buf_size
, fmt
, freq
/div
, freq
%div
);
466 /* Tokens which are really only used by the radio screen go in here */
467 const char *get_radio_token(struct wps_token
*token
, int preset_offset
,
468 char *buf
, int buf_size
, int limit
, int *intval
)
470 const struct fm_region_data
*region_data
=
471 &(fm_region_data
[global_settings
.fm_region
]);
475 /* Radio/tuner tokens */
476 case SKIN_TOKEN_TUNER_TUNED
:
477 if (tuner_get(RADIO_TUNED
))
480 case SKIN_TOKEN_TUNER_SCANMODE
:
481 if (radio_scan_mode())
484 case SKIN_TOKEN_TUNER_STEREO
:
485 if (radio_is_stereo())
488 case SKIN_TOKEN_TUNER_MINFREQ
: /* changes based on "region" */
489 return format_freq_MHz(region_data
->freq_min
,
490 region_data
->freq_step
, buf
, buf_size
);
491 case SKIN_TOKEN_TUNER_MAXFREQ
: /* changes based on "region" */
492 return format_freq_MHz(region_data
->freq_max
,
493 region_data
->freq_step
, buf
, buf_size
);
494 case SKIN_TOKEN_TUNER_CURFREQ
:
495 return format_freq_MHz(radio_current_frequency(),
496 region_data
->freq_step
, buf
, buf_size
);
497 #ifdef HAVE_RADIO_RSSI
498 case SKIN_TOKEN_TUNER_RSSI
:
499 snprintf(buf
, buf_size
, "%d",tuner_get(RADIO_RSSI
));
502 int val
= tuner_get(RADIO_RSSI
);
503 int min
= tuner_get(RADIO_RSSI_MIN
);
504 int max
= tuner_get(RADIO_RSSI_MAX
);
505 if (limit
== TOKEN_VALUE_ONLY
)
511 *intval
= 1+(limit
-1)*(val
-min
)/(max
-1-min
);
515 case SKIN_TOKEN_TUNER_RSSI_MIN
:
516 snprintf(buf
, buf_size
, "%d",tuner_get(RADIO_RSSI_MIN
));
518 case SKIN_TOKEN_TUNER_RSSI_MAX
:
519 snprintf(buf
, buf_size
, "%d",tuner_get(RADIO_RSSI_MAX
));
522 case SKIN_TOKEN_PRESET_NAME
:
523 case SKIN_TOKEN_PRESET_FREQ
:
524 case SKIN_TOKEN_PRESET_ID
:
526 int preset_count
= radio_preset_count();
527 int cur_preset
= radio_current_preset();
528 if (preset_count
== 0 || cur_preset
< 0)
530 int preset
= cur_preset
+ preset_offset
;
531 /* make sure it's in the valid range */
532 preset
%= preset_count
;
534 preset
+= preset_count
;
535 if (token
->type
== SKIN_TOKEN_PRESET_NAME
)
536 snprintf(buf
, buf_size
, "%s", radio_get_preset(preset
)->name
);
537 else if (token
->type
== SKIN_TOKEN_PRESET_FREQ
)
538 format_freq_MHz(radio_get_preset(preset
)->frequency
,
539 region_data
->freq_step
, buf
, buf_size
);
541 snprintf(buf
, buf_size
, "%d", preset
+ 1);
544 case SKIN_TOKEN_PRESET_COUNT
:
545 snprintf(buf
, buf_size
, "%d", radio_preset_count());
547 *intval
= radio_preset_count();
549 case SKIN_TOKEN_HAVE_RDS
:
552 case SKIN_TOKEN_RDS_NAME
:
553 return tuner_get_rds_info(RADIO_RDS_NAME
);
554 case SKIN_TOKEN_RDS_TEXT
:
555 return tuner_get_rds_info(RADIO_RDS_TEXT
);
557 return NULL
; /* end of the SKIN_TOKEN_HAVE_RDS case */
558 #endif /* HAVE_RDS_CAP */
566 static struct mp3entry
* get_mp3entry_from_offset(int offset
, char **filename
)
568 struct mp3entry
* pid3
= NULL
;
569 struct wps_state
*state
= skin_get_global_state();
570 struct cuesheet
*cue
= state
->id3
? state
->id3
->cuesheet
: NULL
;
571 const char *fname
= NULL
;
572 if (cue
&& cue
->curr_track_idx
+ offset
< cue
->track_count
)
574 else if (offset
== 0)
576 else if (offset
== 1)
580 static char filename_buf
[MAX_PATH
+ 1];
581 fname
= playlist_peek(offset
, filename_buf
, sizeof(filename_buf
));
582 *filename
= (char*)fname
;
583 #if CONFIG_CODEC == SWCODEC
584 static struct mp3entry tempid3
;
586 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
587 tagcache_fill_tags(&tempid3
, fname
) ||
589 audio_peek_track(&tempid3
, offset
)
599 #ifdef HAVE_LCD_CHARCELLS
600 static void format_player_progress(struct gui_wps
*gwps
)
602 struct wps_state
*state
= skin_get_global_state();
603 struct screen
*display
= gwps
->display
;
604 unsigned char progress_pattern
[7];
609 if (LIKELY(state
->id3
))
611 elapsed
= state
->id3
->elapsed
;
612 length
= state
->id3
->length
;
621 pos
= 36 * (elapsed
+ state
->ff_rewind_count
) / length
;
623 for (i
= 0; i
< 7; i
++, pos
-= 5)
626 progress_pattern
[i
] = 0x1fu
;
628 progress_pattern
[i
] = 0x00u
;
630 progress_pattern
[i
] = 0x1fu
>> pos
;
633 display
->define_pattern(gwps
->data
->wps_progress_pat
[0], progress_pattern
);
636 static void format_player_fullbar(struct gui_wps
*gwps
, char* buf
, int buf_size
)
638 static const unsigned char numbers
[10][4] = {
639 {0x0e, 0x0a, 0x0a, 0x0e}, /* 0 */
640 {0x04, 0x0c, 0x04, 0x04}, /* 1 */
641 {0x0e, 0x02, 0x04, 0x0e}, /* 2 */
642 {0x0e, 0x02, 0x06, 0x0e}, /* 3 */
643 {0x08, 0x0c, 0x0e, 0x04}, /* 4 */
644 {0x0e, 0x0c, 0x02, 0x0c}, /* 5 */
645 {0x0e, 0x08, 0x0e, 0x0e}, /* 6 */
646 {0x0e, 0x02, 0x04, 0x08}, /* 7 */
647 {0x0e, 0x0e, 0x0a, 0x0e}, /* 8 */
648 {0x0e, 0x0e, 0x02, 0x0e} /* 9 */
651 struct wps_state
*state
= skin_get_global_state();
652 struct screen
*display
= gwps
->display
;
653 struct wps_data
*data
= gwps
->data
;
654 unsigned char progress_pattern
[7];
664 if (LIKELY(state
->id3
))
666 elapsed
= state
->id3
->elapsed
;
667 length
= state
->id3
->length
;
675 if (buf_size
< 34) /* worst case: 11x UTF-8 char + \0 */
678 time
= elapsed
+ state
->ff_rewind_count
;
680 pos
= 55 * time
/ length
;
682 memset(timestr
, 0, sizeof(timestr
));
683 format_time(timestr
, sizeof(timestr
)-2, time
);
684 timestr
[strlen(timestr
)] = ':'; /* always safe */
686 for (i
= 0; i
< 11; i
++, pos
-= 5)
689 memset(progress_pattern
, 0, sizeof(progress_pattern
));
691 if ((digit
= timestr
[time_idx
]))
696 if (timestr
[time_idx
+ 1] == ':') /* ones, left aligned */
698 memcpy(progress_pattern
, numbers
[digit
], 4);
701 else /* tens, shifted right */
703 for (j
= 0; j
< 4; j
++)
704 progress_pattern
[j
] = numbers
[digit
][j
] >> 1;
706 if (time_idx
> 0) /* not the first group, add colon in front */
708 progress_pattern
[1] |= 0x10u
;
709 progress_pattern
[3] |= 0x10u
;
715 progress_pattern
[5] = progress_pattern
[6] = 0x1fu
;
718 if (pos
> 0 && pos
< 5)
721 progress_pattern
[5] = progress_pattern
[6] = (~0x1fu
>> pos
) & 0x1fu
;
724 if (softchar
&& pat_idx
< 8)
726 display
->define_pattern(data
->wps_progress_pat
[pat_idx
],
728 buf
= utf8encode(data
->wps_progress_pat
[pat_idx
], buf
);
732 buf
= utf8encode(' ', buf
);
734 buf
= utf8encode(0xe115, buf
); /* 2/7 _ */
739 #endif /* HAVE_LCD_CHARCELLS */
741 /* Don't inline this; it was broken out of get_token_value to reduce stack
744 static const char* NOINLINE
get_lif_token_value(struct gui_wps
*gwps
,
745 struct logical_if
*lif
,
746 int offset
, char *buf
,
749 int a
= lif
->num_options
;
751 bool number_set
= true;
752 struct wps_token
*liftoken
= SKINOFFSETTOPTR(get_skin_buffer(gwps
->data
), lif
->token
);
753 const char* out_text
= get_token_value(gwps
, liftoken
, offset
, buf
, buf_size
, &a
);
754 if (a
== -1 && liftoken
->type
!= SKIN_TOKEN_VOLUME
)
756 a
= (out_text
&& *out_text
) ? 1 : 0;
759 switch (lif
->operand
.type
)
763 char *cmp
= SKINOFFSETTOPTR(get_skin_buffer(gwps
->data
), lif
->operand
.data
.text
);
764 if (out_text
== NULL
)
766 a
= strcmp(out_text
, cmp
);
771 if (!number_set
&& out_text
&& *out_text
>= '0' && *out_text
<= '9')
776 b
= lif
->operand
.data
.number
;
780 char temp_buf
[MAX_PATH
];
782 struct skin_element
*element
= SKINOFFSETTOPTR(get_skin_buffer(gwps
->data
), lif
->operand
.data
.code
);
783 struct wps_token
*token
= SKINOFFSETTOPTR(get_skin_buffer(gwps
->data
), element
->data
);
784 b
= lif
->num_options
;
785 outb
= get_token_value(gwps
, token
, offset
, temp_buf
,
786 sizeof(temp_buf
), &b
);
787 if (b
== -1 && liftoken
->type
!= SKIN_TOKEN_VOLUME
)
789 if (!out_text
|| !outb
)
790 return (lif
->op
== IF_EQUALS
) ? NULL
: "neq";
791 bool equal
= strcmp(out_text
, outb
) == 0;
792 if (lif
->op
== IF_EQUALS
)
793 return equal
? "eq" : NULL
;
794 else if (lif
->op
== IF_NOTEQUALS
)
795 return !equal
? "neq" : NULL
;
797 b
= (outb
&& *outb
) ? 1 : 0;
808 return a
== b
? "eq" : NULL
;
810 return a
!= b
? "neq" : NULL
;
812 return a
< b
? "lt" : NULL
;
814 return a
<= b
? "lte" : NULL
;
816 return a
> b
? "gt" : NULL
;
817 case IF_GREATERTHAN_EQ
:
818 return a
>= b
? "gte" : NULL
;
823 /* Return the tags value as text. buf should be used as temp storage if needed.
825 intval is used with conditionals/enums: when this function is called,
826 intval should contain the number of options in the conditional/enum.
827 When this function returns, intval is -1 if the tag is non numeric or,
828 if the tag is numeric, *intval is the enum case we want to go to (between 1
829 and the original value of *intval, inclusive).
830 When not treating a conditional/enum, intval should be NULL.
832 const char *get_token_value(struct gui_wps
*gwps
,
833 struct wps_token
*token
, int offset
,
834 char *buf
, int buf_size
,
840 struct wps_data
*data
= gwps
->data
;
841 struct wps_state
*state
= skin_get_global_state();
842 struct mp3entry
*id3
; /* Think very carefully about using this.
843 maybe get_id3_token() is the better place? */
844 const char *out_text
= NULL
;
845 char *filename
= NULL
;
850 id3
= get_mp3entry_from_offset(token
->next
? 1: offset
, &filename
);
852 filename
= id3
->path
;
855 struct tm
* tm
= NULL
;
857 /* if the token is an RTC one, update the time
858 and do the necessary checks */
859 if (token
->type
>= SKIN_TOKENS_RTC_BEGIN
860 && token
->type
<= SKIN_TOKENS_RTC_END
)
876 if (id3
&& id3
== state
->id3
&& id3
->cuesheet
)
878 out_text
= get_cuesheetid3_token(token
, id3
,
879 token
->next
?1:offset
, buf
, buf_size
);
883 out_text
= get_id3_token(token
, id3
, filename
, buf
, buf_size
, limit
, intval
);
887 out_text
= get_radio_token(token
, offset
, buf
, buf_size
, limit
, intval
);
894 case SKIN_TOKEN_LOGICAL_IF
:
896 struct logical_if
*lif
= SKINOFFSETTOPTR(get_skin_buffer(data
), token
->value
.data
);
897 return get_lif_token_value(gwps
, lif
, offset
, buf
, buf_size
);
900 case SKIN_TOKEN_LOGICAL_AND
:
901 case SKIN_TOKEN_LOGICAL_OR
:
903 int i
= 0, truecount
= 0;
904 char *skinbuffer
= get_skin_buffer(data
);
905 struct skin_element
*element
=
906 SKINOFFSETTOPTR(skinbuffer
, token
->value
.data
);
907 struct skin_tag_parameter
* params
=
908 SKINOFFSETTOPTR(skinbuffer
, element
->params
);
909 struct skin_tag_parameter
* thistag
;
910 for (i
=0; i
<element
->params_count
; i
++)
912 thistag
= ¶ms
[i
];
913 struct skin_element
*tokenelement
=
914 SKINOFFSETTOPTR(skinbuffer
, thistag
->data
.code
);
915 out_text
= get_token_value(gwps
,
916 SKINOFFSETTOPTR(skinbuffer
, tokenelement
->data
),
917 offset
, buf
, buf_size
, intval
);
918 if (out_text
&& *out_text
)
920 else if (token
->type
== SKIN_TOKEN_LOGICAL_AND
)
923 return truecount
? "true" : NULL
;
926 case SKIN_TOKEN_SUBSTRING
:
928 struct substring
*ss
= SKINOFFSETTOPTR(get_skin_buffer(data
), token
->value
.data
);
929 const char *token_val
= get_token_value(gwps
,
930 SKINOFFSETTOPTR(get_skin_buffer(data
), ss
->token
), offset
,
931 buf
, buf_size
, intval
);
934 int start_byte
, end_byte
, byte_len
;
935 int utf8_len
= utf8length(token_val
);
937 if (utf8_len
< ss
->start
)
941 start_byte
= utf8seek(token_val
, ss
->start
+ utf8_len
);
943 start_byte
= utf8seek(token_val
, ss
->start
);
945 if (ss
->length
< 0 || (ss
->start
+ ss
->length
) > utf8_len
)
946 end_byte
= strlen(token_val
);
948 end_byte
= utf8seek(token_val
, ss
->start
+ ss
->length
);
950 byte_len
= end_byte
- start_byte
;
952 if (token_val
!= buf
)
953 memcpy(buf
, &token_val
[start_byte
], byte_len
);
955 buf
= &buf
[start_byte
];
957 buf
[byte_len
] = '\0';
958 if (ss
->expect_number
&&
959 intval
&& (buf
[0] >= '0' && buf
[0] <= '9'))
960 *intval
= atoi(buf
) + 1; /* so 0 is the first item */
968 case SKIN_TOKEN_CHARACTER
:
969 if (token
->value
.c
== '\n')
971 return &(token
->value
.c
);
973 case SKIN_TOKEN_STRING
:
974 return (char*)SKINOFFSETTOPTR(get_skin_buffer(data
), token
->value
.data
);
976 case SKIN_TOKEN_TRANSLATEDSTRING
:
977 return (char*)P2STR(ID2P(token
->value
.i
));
979 case SKIN_TOKEN_PLAYLIST_ENTRIES
:
980 snprintf(buf
, buf_size
, "%d", playlist_amount());
982 *intval
= playlist_amount();
984 #ifdef HAVE_LCD_BITMAP
985 case SKIN_TOKEN_LIST_TITLE_TEXT
:
986 return sb_get_title(gwps
->display
->screen_type
);
987 case SKIN_TOKEN_LIST_TITLE_ICON
:
989 *intval
= sb_get_icon(gwps
->display
->screen_type
);
990 snprintf(buf
, buf_size
, "%d",sb_get_icon(gwps
->display
->screen_type
));
992 case SKIN_TOKEN_LIST_ITEM_TEXT
:
994 struct listitem
*li
= (struct listitem
*)SKINOFFSETTOPTR(get_skin_buffer(data
), token
->value
.data
);
995 return skinlist_get_item_text(li
->offset
, li
->wrap
, buf
, buf_size
);
997 case SKIN_TOKEN_LIST_ITEM_ROW
:
999 *intval
= skinlist_get_item_row() + 1;
1000 snprintf(buf
, buf_size
, "%d",skinlist_get_item_row() + 1);
1002 case SKIN_TOKEN_LIST_ITEM_COLUMN
:
1004 *intval
= skinlist_get_item_column() + 1;
1005 snprintf(buf
, buf_size
, "%d",skinlist_get_item_column() + 1);
1007 case SKIN_TOKEN_LIST_ITEM_NUMBER
:
1009 *intval
= skinlist_get_item_number() + 1;
1010 snprintf(buf
, buf_size
, "%d",skinlist_get_item_number() + 1);
1012 case SKIN_TOKEN_LIST_ITEM_IS_SELECTED
:
1013 return skinlist_is_selected_item()?"s":"";
1014 case SKIN_TOKEN_LIST_ITEM_ICON
:
1016 struct listitem
*li
= (struct listitem
*)SKINOFFSETTOPTR(get_skin_buffer(data
), token
->value
.data
);
1017 int icon
= skinlist_get_item_icon(li
->offset
, li
->wrap
);
1020 snprintf(buf
, buf_size
, "%d", icon
);
1023 case SKIN_TOKEN_LIST_NEEDS_SCROLLBAR
:
1024 return skinlist_needs_scrollbar(gwps
->display
->screen_type
) ? "s" : "";
1026 case SKIN_TOKEN_PLAYLIST_NAME
:
1027 return playlist_name(NULL
, buf
, buf_size
);
1029 case SKIN_TOKEN_PLAYLIST_POSITION
:
1030 snprintf(buf
, buf_size
, "%d", playlist_get_display_index()+offset
);
1032 *intval
= playlist_get_display_index()+offset
;
1035 case SKIN_TOKEN_PLAYLIST_SHUFFLE
:
1036 if ( global_settings
.playlist_shuffle
)
1042 case SKIN_TOKEN_VOLUME
:
1043 snprintf(buf
, buf_size
, "%d", global_settings
.volume
);
1046 int minvol
= sound_min(SOUND_VOLUME
);
1047 if (limit
== TOKEN_VALUE_ONLY
)
1049 *intval
= global_settings
.volume
;
1051 else if (global_settings
.volume
== minvol
)
1055 else if (global_settings
.volume
== 0)
1057 *intval
= limit
- 1;
1059 else if (global_settings
.volume
> 0)
1065 *intval
= (limit
-3) * (global_settings
.volume
- minvol
- 1)
1066 / (-1 - minvol
) + 2;
1070 #ifdef HAVE_ALBUMART
1071 case SKIN_TOKEN_ALBUMART_FOUND
:
1072 if (SKINOFFSETTOPTR(get_skin_buffer(data
), data
->albumart
))
1075 handle
= playback_current_aa_hid(data
->playback_aa_slot
);
1077 if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF
))
1079 struct skin_albumart
*aa
= SKINOFFSETTOPTR(get_skin_buffer(data
), data
->albumart
);
1080 struct dim dim
= {aa
->width
, aa
->height
};
1081 handle
= radio_get_art_hid(&dim
);
1090 case SKIN_TOKEN_BATTERY_PERCENT
:
1092 int l
= battery_level();
1096 if (limit
== TOKEN_VALUE_ONLY
)
1102 limit
= MAX(limit
, 3);
1104 /* First enum is used for "unknown level",
1105 * last enum is used for 100%.
1107 *intval
= (limit
- 2) * l
/ 100 + 2;
1115 snprintf(buf
, buf_size
, "%d", l
);
1122 case SKIN_TOKEN_BATTERY_VOLTS
:
1124 int v
= battery_voltage();
1126 snprintf(buf
, buf_size
, "%d.%02d", v
/ 1000, (v
% 1000) / 10);
1133 case SKIN_TOKEN_BATTERY_TIME
:
1135 int t
= battery_time();
1137 snprintf(buf
, buf_size
, "%dh %dm", t
/ 60, t
% 60);
1144 case SKIN_TOKEN_BATTERY_CHARGER_CONNECTED
:
1146 if(charger_input_state
==CHARGER
)
1152 #if CONFIG_CHARGING >= CHARGING_MONITOR
1153 case SKIN_TOKEN_BATTERY_CHARGING
:
1155 if (charge_state
== CHARGING
|| charge_state
== TOPOFF
) {
1162 #ifdef HAVE_USB_POWER
1163 case SKIN_TOKEN_USB_POWERED
:
1168 case SKIN_TOKEN_BATTERY_SLEEPTIME
:
1170 if (get_sleep_timer() == 0)
1174 format_time(buf
, buf_size
, get_sleep_timer() * 1000);
1179 case SKIN_TOKEN_PLAYBACK_STATUS
:
1181 int status
= current_playmode();
1183 int mode
= 1; /* stop */
1184 if (status
== STATUS_PLAY
)
1185 mode
= 2; /* play */
1186 if (state
->is_fading
||
1187 (status
== STATUS_PAUSE
&& !status_get_ffmode()))
1188 mode
= 3; /* pause */
1191 if (status_get_ffmode() == STATUS_FASTFORWARD
)
1193 if (status_get_ffmode() == STATUS_FASTBACKWARD
)
1196 #ifdef HAVE_RECORDING
1198 if (status
== STATUS_RECORD
)
1200 else if (status
== STATUS_RECORD_PAUSE
)
1205 if (status
== STATUS_RADIO
)
1207 else if (status
== STATUS_RADIO_PAUSE
)
1215 snprintf(buf
, buf_size
, "%d", mode
-1);
1219 case SKIN_TOKEN_REPEAT_MODE
:
1221 *intval
= global_settings
.repeat_mode
+ 1;
1222 snprintf(buf
, buf_size
, "%d", global_settings
.repeat_mode
);
1225 case SKIN_TOKEN_RTC_PRESENT
:
1233 case SKIN_TOKEN_RTC_12HOUR_CFG
:
1235 *intval
= global_settings
.timeformat
+ 1;
1236 snprintf(buf
, buf_size
, "%d", global_settings
.timeformat
);
1239 case SKIN_TOKEN_RTC_DAY_OF_MONTH
:
1240 /* d: day of month (01..31) */
1241 snprintf(buf
, buf_size
, "%02d", tm
->tm_mday
);
1243 *intval
= tm
->tm_mday
- 1;
1246 case SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED
:
1247 /* e: day of month, blank padded ( 1..31) */
1248 snprintf(buf
, buf_size
, "%2d", tm
->tm_mday
);
1250 *intval
= tm
->tm_mday
- 1;
1253 case SKIN_TOKEN_RTC_HOUR_24_ZERO_PADDED
:
1254 /* H: hour (00..23) */
1255 snprintf(buf
, buf_size
, "%02d", tm
->tm_hour
);
1257 *intval
= tm
->tm_hour
;
1260 case SKIN_TOKEN_RTC_HOUR_24
:
1261 /* k: hour ( 0..23) */
1262 snprintf(buf
, buf_size
, "%2d", tm
->tm_hour
);
1264 *intval
= tm
->tm_hour
;
1267 case SKIN_TOKEN_RTC_HOUR_12_ZERO_PADDED
:
1268 /* I: hour (01..12) */
1269 snprintf(buf
, buf_size
, "%02d",
1270 (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12);
1272 *intval
= (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12;
1275 case SKIN_TOKEN_RTC_HOUR_12
:
1276 /* l: hour ( 1..12) */
1277 snprintf(buf
, buf_size
, "%2d",
1278 (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12);
1280 *intval
= (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12;
1283 case SKIN_TOKEN_RTC_MONTH
:
1284 /* m: month (01..12) */
1286 *intval
= tm
->tm_mon
+ 1;
1287 snprintf(buf
, buf_size
, "%02d", tm
->tm_mon
+ 1);
1290 case SKIN_TOKEN_RTC_MINUTE
:
1291 /* M: minute (00..59) */
1292 snprintf(buf
, buf_size
, "%02d", tm
->tm_min
);
1294 *intval
= tm
->tm_min
;
1297 case SKIN_TOKEN_RTC_SECOND
:
1298 /* S: second (00..59) */
1299 snprintf(buf
, buf_size
, "%02d", tm
->tm_sec
);
1301 *intval
= tm
->tm_sec
;
1304 case SKIN_TOKEN_RTC_YEAR_2_DIGITS
:
1305 /* y: last two digits of year (00..99) */
1306 snprintf(buf
, buf_size
, "%02d", tm
->tm_year
% 100);
1308 *intval
= tm
->tm_year
% 100;
1311 case SKIN_TOKEN_RTC_YEAR_4_DIGITS
:
1312 /* Y: year (1970...) */
1313 snprintf(buf
, buf_size
, "%04d", tm
->tm_year
+ 1900);
1315 *intval
= tm
->tm_year
+ 1900;
1318 case SKIN_TOKEN_RTC_AM_PM_UPPER
:
1319 /* p: upper case AM or PM indicator */
1321 *intval
= tm
->tm_hour
/12 == 0 ? 0 : 1;
1322 return tm
->tm_hour
/12 == 0 ? "AM" : "PM";
1324 case SKIN_TOKEN_RTC_AM_PM_LOWER
:
1325 /* P: lower case am or pm indicator */
1327 *intval
= tm
->tm_hour
/12 == 0 ? 0 : 1;
1328 return tm
->tm_hour
/12 == 0 ? "am" : "pm";
1330 case SKIN_TOKEN_RTC_WEEKDAY_NAME
:
1331 /* a: abbreviated weekday name (Sun..Sat) */
1332 return str(LANG_WEEKDAY_SUNDAY
+ tm
->tm_wday
);
1334 case SKIN_TOKEN_RTC_MONTH_NAME
:
1335 /* b: abbreviated month name (Jan..Dec) */
1336 return str(LANG_MONTH_JANUARY
+ tm
->tm_mon
);
1338 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_MON
:
1339 /* u: day of week (1..7); 1 is Monday */
1341 *intval
= (tm
->tm_wday
== 0) ? 7 : tm
->tm_wday
;
1342 snprintf(buf
, buf_size
, "%1d", tm
->tm_wday
+ 1);
1345 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_SUN
:
1346 /* w: day of week (0..6); 0 is Sunday */
1348 *intval
= tm
->tm_wday
+ 1;
1349 snprintf(buf
, buf_size
, "%1d", tm
->tm_wday
);
1352 case SKIN_TOKEN_RTC_DAY_OF_MONTH
:
1353 case SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED
:
1354 case SKIN_TOKEN_RTC_HOUR_24_ZERO_PADDED
:
1355 case SKIN_TOKEN_RTC_HOUR_24
:
1356 case SKIN_TOKEN_RTC_HOUR_12_ZERO_PADDED
:
1357 case SKIN_TOKEN_RTC_HOUR_12
:
1358 case SKIN_TOKEN_RTC_MONTH
:
1359 case SKIN_TOKEN_RTC_MINUTE
:
1360 case SKIN_TOKEN_RTC_SECOND
:
1361 case SKIN_TOKEN_RTC_AM_PM_UPPER
:
1362 case SKIN_TOKEN_RTC_AM_PM_LOWER
:
1363 case SKIN_TOKEN_RTC_YEAR_2_DIGITS
:
1365 case SKIN_TOKEN_RTC_YEAR_4_DIGITS
:
1367 case SKIN_TOKEN_RTC_WEEKDAY_NAME
:
1368 case SKIN_TOKEN_RTC_MONTH_NAME
:
1370 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_MON
:
1371 case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_SUN
:
1375 #ifdef HAVE_LCD_CHARCELLS
1376 case SKIN_TOKEN_PROGRESSBAR
:
1379 format_player_progress(gwps
);
1380 end
= utf8encode(data
->wps_progress_pat
[0], buf
);
1385 case SKIN_TOKEN_PLAYER_PROGRESSBAR
:
1388 /* we need 11 characters (full line) for
1390 strlcpy(buf
, " ", buf_size
);
1391 format_player_fullbar(gwps
,buf
,buf_size
);
1392 DEBUGF("bar='%s'\n",buf
);
1396 /* Tell the user if we have an OldPlayer */
1397 strlcpy(buf
, " <Old LCD> ", buf_size
);
1403 #ifdef HAVE_LCD_BITMAP
1405 case SKIN_TOKEN_PEAKMETER_LEFT
:
1406 case SKIN_TOKEN_PEAKMETER_RIGHT
:
1408 int left
, right
, val
;
1409 peak_meter_current_vals(&left
, &right
);
1410 val
= token
->type
== SKIN_TOKEN_PEAKMETER_LEFT
?
1412 val
= peak_meter_scale_value(val
, limit
==1 ? MAX_PEAK
: limit
);
1415 snprintf(buf
, buf_size
, "%d", val
);
1416 data
->peak_meter_enabled
= true;
1421 #if (CONFIG_CODEC == SWCODEC)
1422 case SKIN_TOKEN_CROSSFADE
:
1423 #ifdef HAVE_CROSSFADE
1425 *intval
= global_settings
.crossfade
+ 1;
1426 snprintf(buf
, buf_size
, "%d", global_settings
.crossfade
);
1428 snprintf(buf
, buf_size
, "%d", 0);
1432 case SKIN_TOKEN_REPLAYGAIN
:
1434 int globtype
= global_settings
.replaygain_settings
.type
;
1438 if (globtype
== REPLAYGAIN_OFF
)
1442 int type
= id3_get_replaygain_mode(id3
);
1445 val
= 6; /* no tag */
1449 if (globtype
== REPLAYGAIN_SHUFFLE
)
1462 /* due to above, coming here with !id3 shouldn't be possible */
1465 replaygain_itoa(buf
, buf_size
, id3
->track_level
);
1469 replaygain_itoa(buf
, buf_size
, id3
->album_level
);
1474 #endif /* (CONFIG_CODEC == SWCODEC) */
1476 #if (CONFIG_CODEC != MAS3507D) && defined (HAVE_PITCHCONTROL)
1477 case SKIN_TOKEN_SOUND_PITCH
:
1479 int32_t pitch
= sound_get_pitch();
1480 snprintf(buf
, buf_size
, "%ld.%ld",
1481 pitch
/ PITCH_SPEED_PRECISION
,
1482 (pitch
% PITCH_SPEED_PRECISION
) / (PITCH_SPEED_PRECISION
/ 10));
1485 *intval
= pitch_speed_enum(limit
, pitch
,
1486 PITCH_SPEED_PRECISION
* 100);
1491 #if (CONFIG_CODEC == SWCODEC) && defined (HAVE_PITCHCONTROL)
1492 case SKIN_TOKEN_SOUND_SPEED
:
1494 int32_t pitch
= sound_get_pitch();
1496 if (dsp_timestretch_available())
1497 speed
= GET_SPEED(pitch
, dsp_get_timestretch());
1500 snprintf(buf
, buf_size
, "%ld.%ld",
1501 speed
/ PITCH_SPEED_PRECISION
,
1502 (speed
% PITCH_SPEED_PRECISION
) / (PITCH_SPEED_PRECISION
/ 10));
1504 *intval
= pitch_speed_enum(limit
, speed
,
1505 PITCH_SPEED_PRECISION
* 100);
1510 case SKIN_TOKEN_MAIN_HOLD
:
1511 #ifdef HAVE_TOUCHSCREEN
1512 if (data
->touchscreen_locked
)
1515 #ifdef HAS_BUTTON_HOLD
1518 if (is_keys_locked())
1519 #endif /*hold switch or softlock*/
1524 #ifdef HAS_REMOTE_BUTTON_HOLD
1525 case SKIN_TOKEN_REMOTE_HOLD
:
1526 if (remote_button_hold())
1532 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
1533 case SKIN_TOKEN_VLED_HDD
:
1539 case SKIN_TOKEN_BUTTON_VOLUME
:
1540 if (global_status
.last_volume_change
&&
1541 TIME_BEFORE(current_tick
, global_status
.last_volume_change
+
1546 case SKIN_TOKEN_LASTTOUCH
:
1548 #ifdef HAVE_TOUCHSCREEN
1549 unsigned int last_touch
= touchscreen_last_touch();
1550 char *skin_base
= get_skin_buffer(data
);
1551 struct touchregion_lastpress
*data
= SKINOFFSETTOPTR(skin_base
, token
->value
.data
);
1552 struct touchregion
*region
= SKINOFFSETTOPTR(skin_base
, data
->region
);
1554 last_touch
= region
->last_press
;
1556 if (last_touch
!= 0xffff &&
1557 TIME_BEFORE(current_tick
, data
->timeout
+ last_touch
))
1562 case SKIN_TOKEN_HAVE_TOUCH
:
1563 #ifdef HAVE_TOUCHSCREEN
1569 case SKIN_TOKEN_SETTING
:
1571 const struct settings_list
*s
= settings
+token
->value
.i
;
1574 /* Handle contionals */
1575 switch (s
->flags
&F_T_MASK
)
1579 if (s
->flags
&F_T_SOUND
)
1581 /* %?St|name|<min|min+1|...|max-1|max> */
1582 int sound_setting
= s
->sound_setting
->setting
;
1583 /* settings with decimals can't be used in conditionals */
1584 if (sound_numdecimals(sound_setting
) == 0)
1586 *intval
= (*(int*)s
->setting
-sound_min(sound_setting
))
1587 /sound_steps(sound_setting
) + 1;
1592 else if (s
->flags
&F_RGB
)
1593 /* %?St|name|<#000000|#000001|...|#FFFFFF> */
1594 /* shouldn't overflow since colors are stored
1596 * but this is pretty useless anyway */
1597 *intval
= *(int*)s
->setting
+ 1;
1598 else if (s
->cfg_vals
== NULL
)
1599 /* %?St|name|<1st choice|2nd choice|...> */
1600 *intval
= (*(int*)s
->setting
-s
->int_setting
->min
)
1601 /s
->int_setting
->step
+ 1;
1603 /* %?St|name|<1st choice|2nd choice|...> */
1604 /* Not sure about this one. cfg_name/vals are
1605 * indexed from 0 right? */
1606 *intval
= *(int*)s
->setting
+ 1;
1609 /* %?St|name|<if true|if false> */
1610 *intval
= *(bool*)s
->setting
?1:2;
1614 /* %?St|name|<if non empty string|if empty>
1615 * The string's emptyness discards the setting's
1616 * prefix and suffix */
1617 *intval
= ((char*)s
->setting
)[0]?1:2;
1618 /* if there is a prefix we should ignore it here */
1619 if (s
->filename_setting
->prefix
)
1620 return (char*)s
->setting
;
1623 /* This shouldn't happen ... but you never know */
1628 /* Special handlng for filenames because we dont want to show the prefix */
1629 if ((s
->flags
&F_T_MASK
) == F_T_CHARPTR
||
1630 (s
->flags
&F_T_MASK
) == F_T_UCHARPTR
)
1632 if (s
->filename_setting
->prefix
)
1633 return (char*)s
->setting
;
1635 cfg_to_string(token
->value
.i
,buf
,buf_size
);
1638 case SKIN_TOKEN_HAVE_TUNER
:
1640 if (radio_hardware_present())
1644 /* Recording tokens */
1645 case SKIN_TOKEN_HAVE_RECORDING
:
1646 #ifdef HAVE_RECORDING
1652 #ifdef HAVE_RECORDING
1653 case SKIN_TOKEN_IS_RECORDING
:
1654 if (audio_status() == AUDIO_STATUS_RECORD
)
1657 case SKIN_TOKEN_REC_FREQ
: /* order from REC_FREQ_CFG_VAL_LIST */
1659 #if CONFIG_CODEC == SWCODEC
1660 unsigned long samprk
;
1661 int rec_freq
= global_settings
.rec_frequency
;
1666 #if defined(HAVE_SPDIF_REC)
1667 if (global_settings
.rec_source
== AUDIO_SRC_SPDIF
)
1669 /* Use rate in use, not current measured rate if it changed */
1670 samprk
= pcm_rec_sample_rate();
1672 while (rec_freq
< SAMPR_NUM_FREQ
&&
1673 audio_master_sampr_list
[rec_freq
] != samprk
)
1680 samprk
= rec_freq_sampr
[rec_freq
];
1681 #endif /* SIMULATOR */
1686 REC_HAVE_96_(case REC_FREQ_96
:
1689 REC_HAVE_88_(case REC_FREQ_88
:
1692 REC_HAVE_64_(case REC_FREQ_64
:
1695 REC_HAVE_48_(case REC_FREQ_48
:
1698 REC_HAVE_44_(case REC_FREQ_44
:
1701 REC_HAVE_32_(case REC_FREQ_32
:
1704 REC_HAVE_24_(case REC_FREQ_24
:
1707 REC_HAVE_22_(case REC_FREQ_22
:
1710 REC_HAVE_16_(case REC_FREQ_16
:
1713 REC_HAVE_12_(case REC_FREQ_12
:
1716 REC_HAVE_11_(case REC_FREQ_11
:
1719 REC_HAVE_8_(case REC_FREQ_8
:
1724 snprintf(buf
, buf_size
, "%lu.%1lu", samprk
/1000,samprk
%1000);
1727 static const char * const freq_strings
[] =
1728 {"--", "44", "48", "32", "22", "24", "16"};
1729 int freq
= 1 + global_settings
.rec_frequency
;
1730 #ifdef HAVE_SPDIF_REC
1731 if (global_settings
.rec_source
== AUDIO_SRC_SPDIF
)
1733 /* Can't measure S/PDIF sample rate on Archos/Sim yet */
1736 #endif /* HAVE_SPDIF_IN */
1738 *intval
= freq
+1; /* so the token gets a value 1<=x<=7 */
1739 snprintf(buf
, buf_size
, "%s\n",
1740 freq_strings
[global_settings
.rec_frequency
]);
1744 #if CONFIG_CODEC == SWCODEC
1745 case SKIN_TOKEN_REC_ENCODER
:
1747 int rec_format
= global_settings
.rec_format
+1; /* WAV, AIFF, WV, MPEG */
1749 *intval
= rec_format
;
1752 case REC_FORMAT_PCM_WAV
:
1754 case REC_FORMAT_AIFF
:
1756 case REC_FORMAT_WAVPACK
:
1758 case REC_FORMAT_MPA_L3
:
1766 case SKIN_TOKEN_REC_BITRATE
:
1767 #if CONFIG_CODEC == SWCODEC
1768 if (global_settings
.rec_format
== REC_FORMAT_MPA_L3
)
1772 #if 0 /* FIXME: I dont know if this is needed? */
1773 switch (1<<global_settings
.mp3_enc_config
.bitrate
)
1775 case MP3_BITR_CAP_8
:
1778 case MP3_BITR_CAP_16
:
1781 case MP3_BITR_CAP_24
:
1784 case MP3_BITR_CAP_32
:
1787 case MP3_BITR_CAP_40
:
1790 case MP3_BITR_CAP_48
:
1793 case MP3_BITR_CAP_56
:
1796 case MP3_BITR_CAP_64
:
1799 case MP3_BITR_CAP_80
:
1802 case MP3_BITR_CAP_96
:
1805 case MP3_BITR_CAP_112
:
1808 case MP3_BITR_CAP_128
:
1811 case MP3_BITR_CAP_144
:
1814 case MP3_BITR_CAP_160
:
1817 case MP3_BITR_CAP_192
:
1822 *intval
= global_settings
.mp3_enc_config
.bitrate
+1;
1824 snprintf(buf
, buf_size
, "%lu", global_settings
.mp3_enc_config
.bitrate
+1);
1828 return NULL
; /* Fixme later */
1829 #else /* CONFIG_CODEC == HWCODEC */
1831 *intval
= global_settings
.rec_quality
+1;
1832 snprintf(buf
, buf_size
, "%d", global_settings
.rec_quality
);
1835 case SKIN_TOKEN_REC_MONO
:
1836 if (!global_settings
.rec_channels
)
1840 case SKIN_TOKEN_REC_SECONDS
:
1842 int time
= (audio_recorded_time() / HZ
) % 60;
1845 snprintf(buf
, buf_size
, "%02d", time
);
1848 case SKIN_TOKEN_REC_MINUTES
:
1850 int time
= (audio_recorded_time() / HZ
) / 60;
1853 snprintf(buf
, buf_size
, "%02d", time
);
1856 case SKIN_TOKEN_REC_HOURS
:
1858 int time
= (audio_recorded_time() / HZ
) / 3600;
1861 snprintf(buf
, buf_size
, "%02d", time
);
1865 #endif /* HAVE_RECORDING */
1867 case SKIN_TOKEN_CURRENT_SCREEN
:
1869 int curr_screen
= get_current_activity();
1872 *intval
= curr_screen
;
1874 snprintf(buf
, buf_size
, "%d", curr_screen
);
1878 case SKIN_TOKEN_LANG_IS_RTL
:
1879 return lang_is_rtl() ? "r" : NULL
;
1881 #ifdef HAVE_SKIN_VARIABLES
1882 case SKIN_TOKEN_VAR_GETVAL
:
1884 char *skin_base
= get_skin_buffer(data
);
1885 struct skin_var
* var
= SKINOFFSETTOPTR(skin_base
, token
->value
.data
);
1887 *intval
= var
->value
;
1888 snprintf(buf
, buf_size
, "%d", var
->value
);
1892 case SKIN_TOKEN_VAR_TIMEOUT
:
1894 char *skin_base
= get_skin_buffer(data
);
1895 struct skin_var_lastchange
*data
= SKINOFFSETTOPTR(skin_base
, token
->value
.data
);
1896 struct skin_var
* var
= SKINOFFSETTOPTR(skin_base
, data
->var
);
1897 unsigned int last_change
= var
->last_changed
;
1899 if (last_change
!= 0xffff &&
1900 TIME_BEFORE(current_tick
, data
->timeout
+ last_change
))