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"
37 #ifdef HAVE_LCD_CHARCELLS
44 #ifdef HAVE_LCD_BITMAP
50 #if CONFIG_CODEC == SWCODEC
56 #include "wps_internals.h"
57 #include "root_menu.h"
59 #include "recording.h"
60 #include "pcm_record.h"
69 extern struct wps_state wps_state
;
71 static const char* get_codectype(const struct mp3entry
* id3
)
73 if (id3
&& id3
->codectype
< AFMT_NUM_CODECS
) {
74 return audio_formats
[id3
->codectype
].label
;
80 /* Extract a part from a path.
82 * buf - buffer extract part to.
83 * buf_size - size of buffer.
84 * path - path to extract from.
85 * level - what to extract. 0 is file name, 1 is parent of file, 2 is
86 * parent of parent, etc.
88 * Returns buf if the desired level was found, NULL otherwise.
90 char* get_dir(char* buf
, int buf_size
, const char* path
, int level
)
96 sep
= path
+ strlen(path
);
111 if (level
|| (last_sep
<= sep
))
114 len
= MIN(last_sep
- sep
, buf_size
- 1);
115 strlcpy(buf
, sep
+ 1, len
+ 1);
119 #if (CONFIG_CODEC != MAS3507D)
120 /* A helper to determine the enum value for pitch/speed.
122 When there are two choices (i.e. boolean), return 1 if the value is
123 different from normal value and 2 if the value is the same as the
124 normal value. E.g. "%?Sp<%Sp>" would show the pitch only when
125 playing at a modified pitch.
127 When there are more than two choices (i.e. enum), the left half of
128 the choices are to show 0..normal range, and the right half of the
129 choices are to show values over that. The last entry is used when
130 it is set to the normal setting, following the rockbox convention
131 to use the last entry for special values.
135 2 items: %?Sp<0..99 or 101..infinity|100>
136 3 items: %?Sp<0..99|101..infinity|100>
137 4 items: %?Sp<0..49|50..99|101..infinity|100>
138 5 items: %?Sp<0..49|50..99|101..149|150..infinity|100>
139 6 items: %?Sp<0..33|34..66|67..99|101..133|134..infinity|100>
140 7 items: %?Sp<0..33|34..66|67..99|101..133|134..167|167..infinity|100>
142 static int pitch_speed_enum(int range
, int32_t val
, int32_t normval
)
148 return (val
== normval
) + 1;
152 n
= (center
* val
) / normval
+ 1;
153 return (range
<= n
) ? (range
- 1) : n
;
158 /* All tokens which only need the info to return a value go in here */
159 const char *get_id3_token(struct wps_token
*token
, struct mp3entry
*id3
,
160 char *buf
, int buf_size
, int limit
, int *intval
)
162 struct wps_state
*state
= &wps_state
;
165 unsigned long length
= id3
->length
;
166 unsigned long elapsed
= id3
->elapsed
+ state
->ff_rewind_count
;
169 case WPS_TOKEN_METADATA_ARTIST
:
171 case WPS_TOKEN_METADATA_COMPOSER
:
172 return id3
->composer
;
173 case WPS_TOKEN_METADATA_ALBUM
:
175 case WPS_TOKEN_METADATA_ALBUM_ARTIST
:
176 return id3
->albumartist
;
177 case WPS_TOKEN_METADATA_GROUPING
:
178 return id3
->grouping
;
179 case WPS_TOKEN_METADATA_GENRE
:
180 return id3
->genre_string
;
181 case WPS_TOKEN_METADATA_DISC_NUMBER
:
182 if (id3
->disc_string
)
183 return id3
->disc_string
;
185 snprintf(buf
, buf_size
, "%d", id3
->discnum
);
189 case WPS_TOKEN_METADATA_TRACK_NUMBER
:
190 if (id3
->track_string
)
191 return id3
->track_string
;
193 snprintf(buf
, buf_size
, "%d", id3
->tracknum
);
197 case WPS_TOKEN_METADATA_TRACK_TITLE
:
199 case WPS_TOKEN_METADATA_VERSION
:
200 switch (id3
->id3version
)
216 case WPS_TOKEN_METADATA_YEAR
:
217 if( id3
->year_string
)
218 return id3
->year_string
;
220 snprintf(buf
, buf_size
, "%d", id3
->year
);
224 case WPS_TOKEN_METADATA_COMMENT
:
226 case WPS_TOKEN_FILE_PATH
:
228 case WPS_TOKEN_FILE_BITRATE
:
230 snprintf(buf
, buf_size
, "%d", id3
->bitrate
);
234 case WPS_TOKEN_TRACK_TIME_ELAPSED
:
235 format_time(buf
, buf_size
, elapsed
);
238 case WPS_TOKEN_TRACK_TIME_REMAINING
:
239 format_time(buf
, buf_size
, length
- elapsed
);
242 case WPS_TOKEN_TRACK_LENGTH
:
243 format_time(buf
, buf_size
, length
);
246 case WPS_TOKEN_TRACK_ELAPSED_PERCENT
:
252 *intval
= limit
* elapsed
/ length
+ 1;
254 snprintf(buf
, buf_size
, "%lu", 100 * elapsed
/ length
);
258 case WPS_TOKEN_FILE_CODEC
:
261 if(id3
->codectype
== AFMT_UNKNOWN
)
262 *intval
= AFMT_NUM_CODECS
;
264 *intval
= id3
->codectype
;
266 return get_codectype(id3
);
268 case WPS_TOKEN_FILE_FREQUENCY
:
269 snprintf(buf
, buf_size
, "%ld", id3
->frequency
);
271 case WPS_TOKEN_FILE_FREQUENCY_KHZ
:
272 /* ignore remainders < 100, so 22050 Hz becomes just 22k */
273 if ((id3
->frequency
% 1000) < 100)
274 snprintf(buf
, buf_size
, "%ld", id3
->frequency
/ 1000);
276 snprintf(buf
, buf_size
, "%ld.%lu",
277 id3
->frequency
/ 1000,
278 (id3
->frequency
% 1000) / 100);
280 case WPS_TOKEN_FILE_NAME
:
281 if (get_dir(buf
, buf_size
, id3
->path
, 0)) {
282 /* Remove extension */
283 char* sep
= strrchr(buf
, '.');
290 case WPS_TOKEN_FILE_NAME_WITH_EXTENSION
:
291 return get_dir(buf
, buf_size
, id3
->path
, 0);
292 case WPS_TOKEN_FILE_SIZE
:
293 snprintf(buf
, buf_size
, "%ld", id3
->filesize
/ 1024);
295 case WPS_TOKEN_FILE_VBR
:
296 return (id3
->vbr
) ? "(avg)" : NULL
;
297 case WPS_TOKEN_FILE_DIRECTORY
:
298 return get_dir(buf
, buf_size
, id3
->path
, token
->value
.i
);
301 case WPS_TOKEN_DATABASE_PLAYCOUNT
:
303 *intval
= id3
->playcount
+ 1;
304 snprintf(buf
, buf_size
, "%ld", id3
->playcount
);
306 case WPS_TOKEN_DATABASE_RATING
:
308 *intval
= id3
->rating
+ 1;
309 snprintf(buf
, buf_size
, "%d", id3
->rating
);
311 case WPS_TOKEN_DATABASE_AUTOSCORE
:
313 *intval
= id3
->score
+ 1;
314 snprintf(buf
, buf_size
, "%d", id3
->score
);
322 else /* id3 == NULL, handle the error based on the expected return type */
326 /* Most tokens expect NULL on error so leave that for the default case,
327 * The ones that expect "0" need to be handled */
328 case WPS_TOKEN_FILE_FREQUENCY
:
329 case WPS_TOKEN_FILE_FREQUENCY_KHZ
:
330 case WPS_TOKEN_FILE_SIZE
:
332 case WPS_TOKEN_DATABASE_PLAYCOUNT
:
333 case WPS_TOKEN_DATABASE_RATING
:
334 case WPS_TOKEN_DATABASE_AUTOSCORE
:
348 /* Formats the frequency (specified in Hz) in MHz, */
349 /* with one or two digits after the decimal point -- */
350 /* depending on the frequency changing step. */
352 static char *format_freq_MHz(int freq
, int freq_step
, char *buf
, int buf_size
)
356 if (freq_step
< 100000)
358 /* Format with two digits after decimal point */
364 /* Format with one digit after decimal point */
368 div
= 1000000 / scale
;
370 snprintf(buf
, buf_size
, fmt
, freq
/div
, freq
%div
);
375 /* Tokens which are really only used by the radio screen go in here */
376 const char *get_radio_token(struct wps_token
*token
, int preset_offset
,
377 char *buf
, int buf_size
, int limit
, int *intval
)
379 const struct fm_region_data
*region_data
=
380 &(fm_region_data
[global_settings
.fm_region
]);
384 /* Radio/tuner tokens */
385 case WPS_TOKEN_TUNER_TUNED
:
386 if (tuner_get(RADIO_TUNED
))
389 case WPS_TOKEN_TUNER_SCANMODE
:
390 if (radio_scan_mode())
393 case WPS_TOKEN_TUNER_STEREO
:
394 if (radio_is_stereo())
397 case WPS_TOKEN_TUNER_MINFREQ
: /* changes based on "region" */
398 return format_freq_MHz(region_data
->freq_min
,
399 region_data
->freq_step
, buf
, buf_size
);
400 case WPS_TOKEN_TUNER_MAXFREQ
: /* changes based on "region" */
401 return format_freq_MHz(region_data
->freq_max
,
402 region_data
->freq_step
, buf
, buf_size
);
403 case WPS_TOKEN_TUNER_CURFREQ
:
404 return format_freq_MHz(radio_current_frequency(),
405 region_data
->freq_step
, buf
, buf_size
);
406 case WPS_TOKEN_PRESET_ID
:
407 snprintf(buf
, buf_size
, "%d", radio_current_preset() + 1 + preset_offset
);
409 case WPS_TOKEN_PRESET_NAME
:
410 case WPS_TOKEN_PRESET_FREQ
:
412 int preset_count
= radio_preset_count();
413 int cur_preset
= radio_current_preset();
414 if (preset_count
== 0 || cur_preset
< 0)
416 int preset
= cur_preset
+ preset_offset
;
417 /* make sure it's in the valid range */
418 preset
%= preset_count
;
420 preset
+= preset_count
;
421 if (token
->type
== WPS_TOKEN_PRESET_NAME
)
422 snprintf(buf
, buf_size
, "%s", radio_get_preset(preset
)->name
);
424 format_freq_MHz(radio_get_preset(preset
)->frequency
,
425 region_data
->freq_step
, buf
, buf_size
);
428 case WPS_TOKEN_PRESET_COUNT
:
429 snprintf(buf
, buf_size
, "%d", radio_preset_count());
431 *intval
= radio_preset_count();
433 case WPS_TOKEN_HAVE_RDS
:
436 case WPS_TOKEN_RDS_NAME
:
437 return tuner_get_rds_info(RADIO_RDS_NAME
);
438 case WPS_TOKEN_RDS_TEXT
:
439 return tuner_get_rds_info(RADIO_RDS_TEXT
);
441 return NULL
; /* end of the WPS_TOKEN_HAVE_RDS case */
442 #endif /* HAVE_RDS_CAP */
448 /* Return the tags value as text. buf should be used as temp storage if needed.
450 intval is used with conditionals/enums: when this function is called,
451 intval should contain the number of options in the conditional/enum.
452 When this function returns, intval is -1 if the tag is non numeric or,
453 if the tag is numeric, *intval is the enum case we want to go to (between 1
454 and the original value of *intval, inclusive).
455 When not treating a conditional/enum, intval should be NULL.
457 const char *get_token_value(struct gui_wps
*gwps
,
458 struct wps_token
*token
,
459 char *buf
, int buf_size
,
465 struct wps_data
*data
= gwps
->data
;
466 struct wps_state
*state
= gwps
->state
;
467 struct mp3entry
*id3
; /* Think very carefully about using this.
468 maybe get_id3_token() is the better place? */
469 const char *out_text
= NULL
;
481 struct tm
* tm
= NULL
;
483 /* if the token is an RTC one, update the time
484 and do the necessary checks */
485 if (token
->type
>= WPS_TOKENS_RTC_BEGIN
486 && token
->type
<= WPS_TOKENS_RTC_END
)
502 out_text
= get_id3_token(token
, id3
, buf
, buf_size
, limit
, intval
);
506 out_text
= get_radio_token(token
, 0, buf
, buf_size
, limit
, intval
);
513 case WPS_TOKEN_CHARACTER
:
514 if (token
->value
.c
== '\n')
516 return &(token
->value
.c
);
518 case WPS_TOKEN_STRING
:
519 return (char*)token
->value
.data
;
521 case WPS_TOKEN_TRANSLATEDSTRING
:
522 return (char*)P2STR(ID2P(token
->value
.i
));
524 case WPS_TOKEN_PLAYLIST_ENTRIES
:
525 snprintf(buf
, buf_size
, "%d", playlist_amount());
528 case WPS_TOKEN_LIST_TITLE_TEXT
:
529 return (char*)token
->value
.data
;
530 case WPS_TOKEN_LIST_TITLE_ICON
:
532 *intval
= token
->value
.i
;
533 snprintf(buf
, buf_size
, "%d", token
->value
.i
);
536 case WPS_TOKEN_PLAYLIST_NAME
:
537 return playlist_name(NULL
, buf
, buf_size
);
539 case WPS_TOKEN_PLAYLIST_POSITION
:
540 snprintf(buf
, buf_size
, "%d", playlist_get_display_index());
543 case WPS_TOKEN_PLAYLIST_SHUFFLE
:
544 if ( global_settings
.playlist_shuffle
)
550 case WPS_TOKEN_VOLUME
:
551 snprintf(buf
, buf_size
, "%d", global_settings
.volume
);
554 int minvol
= sound_min(SOUND_VOLUME
);
555 if (global_settings
.volume
== minvol
)
559 else if (global_settings
.volume
== 0)
563 else if (global_settings
.volume
> 0)
569 *intval
= (limit
-3) * (global_settings
.volume
- minvol
- 1)
575 case WPS_TOKEN_ALBUMART_FOUND
:
579 handle
= playback_current_aa_hid(data
->playback_aa_slot
);
581 if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF
))
583 struct dim dim
= {data
->albumart
->width
, data
->albumart
->height
};
584 handle
= radio_get_art_hid(&dim
);
592 case WPS_TOKEN_ALBUMART_DISPLAY
:
595 if (!data
->albumart
->draw
)
596 data
->albumart
->draw
= true;
600 case WPS_TOKEN_BATTERY_PERCENT
:
602 int l
= battery_level();
606 limit
= MAX(limit
, 2);
608 /* First enum is used for "unknown level". */
609 *intval
= (limit
- 1) * l
/ 100 + 2;
616 snprintf(buf
, buf_size
, "%d", l
);
623 case WPS_TOKEN_BATTERY_VOLTS
:
625 unsigned int v
= battery_voltage();
626 snprintf(buf
, buf_size
, "%d.%02d", v
/ 1000, (v
% 1000) / 10);
630 case WPS_TOKEN_BATTERY_TIME
:
632 int t
= battery_time();
634 snprintf(buf
, buf_size
, "%dh %dm", t
/ 60, t
% 60);
641 case WPS_TOKEN_BATTERY_CHARGER_CONNECTED
:
643 if(charger_input_state
==CHARGER
)
649 #if CONFIG_CHARGING >= CHARGING_MONITOR
650 case WPS_TOKEN_BATTERY_CHARGING
:
652 if (charge_state
== CHARGING
|| charge_state
== TOPOFF
) {
659 #ifdef HAVE_USB_POWER
660 case WPS_TOKEN_USB_POWERED
:
665 case WPS_TOKEN_BATTERY_SLEEPTIME
:
667 if (get_sleep_timer() == 0)
671 format_time(buf
, buf_size
, get_sleep_timer() * 1000);
676 case WPS_TOKEN_PLAYBACK_STATUS
:
678 int status
= current_playmode();
680 int mode
= 1; /* stop */
681 if (status
== STATUS_PLAY
)
683 if (state
->is_fading
||
684 (status
== STATUS_PAUSE
&& !status_get_ffmode()))
685 mode
= 3; /* pause */
688 if (status_get_ffmode() == STATUS_FASTFORWARD
)
690 if (status_get_ffmode() == STATUS_FASTBACKWARD
)
693 #ifdef HAVE_RECORDING
695 if (status
== STATUS_RECORD
)
697 else if (status
== STATUS_RECORD_PAUSE
)
702 if (status
== STATUS_RADIO
)
704 else if (status
== STATUS_RADIO_PAUSE
)
712 snprintf(buf
, buf_size
, "%d", mode
-1);
716 case WPS_TOKEN_REPEAT_MODE
:
718 *intval
= global_settings
.repeat_mode
+ 1;
719 snprintf(buf
, buf_size
, "%d", global_settings
.repeat_mode
);
722 case WPS_TOKEN_RTC_PRESENT
:
730 case WPS_TOKEN_RTC_12HOUR_CFG
:
732 *intval
= global_settings
.timeformat
+ 1;
733 snprintf(buf
, buf_size
, "%d", global_settings
.timeformat
);
736 case WPS_TOKEN_RTC_DAY_OF_MONTH
:
737 /* d: day of month (01..31) */
738 snprintf(buf
, buf_size
, "%02d", tm
->tm_mday
);
740 *intval
= tm
->tm_mday
- 1;
743 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED
:
744 /* e: day of month, blank padded ( 1..31) */
745 snprintf(buf
, buf_size
, "%2d", tm
->tm_mday
);
747 *intval
= tm
->tm_mday
- 1;
750 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED
:
751 /* H: hour (00..23) */
752 snprintf(buf
, buf_size
, "%02d", tm
->tm_hour
);
754 *intval
= tm
->tm_hour
;
757 case WPS_TOKEN_RTC_HOUR_24
:
758 /* k: hour ( 0..23) */
759 snprintf(buf
, buf_size
, "%2d", tm
->tm_hour
);
761 *intval
= tm
->tm_hour
;
764 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED
:
765 /* I: hour (01..12) */
766 snprintf(buf
, buf_size
, "%02d",
767 (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12);
769 *intval
= (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12;
772 case WPS_TOKEN_RTC_HOUR_12
:
773 /* l: hour ( 1..12) */
774 snprintf(buf
, buf_size
, "%2d",
775 (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12);
777 *intval
= (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12;
780 case WPS_TOKEN_RTC_MONTH
:
781 /* m: month (01..12) */
783 *intval
= tm
->tm_mon
+ 1;
784 snprintf(buf
, buf_size
, "%02d", tm
->tm_mon
+ 1);
787 case WPS_TOKEN_RTC_MINUTE
:
788 /* M: minute (00..59) */
789 snprintf(buf
, buf_size
, "%02d", tm
->tm_min
);
791 *intval
= tm
->tm_min
;
794 case WPS_TOKEN_RTC_SECOND
:
795 /* S: second (00..59) */
796 snprintf(buf
, buf_size
, "%02d", tm
->tm_sec
);
798 *intval
= tm
->tm_sec
;
801 case WPS_TOKEN_RTC_YEAR_2_DIGITS
:
802 /* y: last two digits of year (00..99) */
803 snprintf(buf
, buf_size
, "%02d", tm
->tm_year
% 100);
805 *intval
= tm
->tm_year
% 100;
808 case WPS_TOKEN_RTC_YEAR_4_DIGITS
:
809 /* Y: year (1970...) */
810 snprintf(buf
, buf_size
, "%04d", tm
->tm_year
+ 1900);
812 *intval
= tm
->tm_year
+ 1900;
815 case WPS_TOKEN_RTC_AM_PM_UPPER
:
816 /* p: upper case AM or PM indicator */
818 *intval
= tm
->tm_hour
/12 == 0 ? 0 : 1;
819 return tm
->tm_hour
/12 == 0 ? "AM" : "PM";
821 case WPS_TOKEN_RTC_AM_PM_LOWER
:
822 /* P: lower case am or pm indicator */
824 *intval
= tm
->tm_hour
/12 == 0 ? 0 : 1;
825 return tm
->tm_hour
/12 == 0 ? "am" : "pm";
827 case WPS_TOKEN_RTC_WEEKDAY_NAME
:
828 /* a: abbreviated weekday name (Sun..Sat) */
829 return str(LANG_WEEKDAY_SUNDAY
+ tm
->tm_wday
);
831 case WPS_TOKEN_RTC_MONTH_NAME
:
832 /* b: abbreviated month name (Jan..Dec) */
833 return str(LANG_MONTH_JANUARY
+ tm
->tm_mon
);
835 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON
:
836 /* u: day of week (1..7); 1 is Monday */
838 *intval
= (tm
->tm_wday
== 0) ? 7 : tm
->tm_wday
;
839 snprintf(buf
, buf_size
, "%1d", tm
->tm_wday
+ 1);
842 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN
:
843 /* w: day of week (0..6); 0 is Sunday */
845 *intval
= tm
->tm_wday
+ 1;
846 snprintf(buf
, buf_size
, "%1d", tm
->tm_wday
);
849 case WPS_TOKEN_RTC_DAY_OF_MONTH
:
850 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED
:
851 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED
:
852 case WPS_TOKEN_RTC_HOUR_24
:
853 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED
:
854 case WPS_TOKEN_RTC_HOUR_12
:
855 case WPS_TOKEN_RTC_MONTH
:
856 case WPS_TOKEN_RTC_MINUTE
:
857 case WPS_TOKEN_RTC_SECOND
:
858 case WPS_TOKEN_RTC_AM_PM_UPPER
:
859 case WPS_TOKEN_RTC_AM_PM_LOWER
:
860 case WPS_TOKEN_RTC_YEAR_2_DIGITS
:
862 case WPS_TOKEN_RTC_YEAR_4_DIGITS
:
864 case WPS_TOKEN_RTC_WEEKDAY_NAME
:
865 case WPS_TOKEN_RTC_MONTH_NAME
:
867 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON
:
868 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN
:
872 #ifdef HAVE_LCD_CHARCELLS
873 case WPS_TOKEN_PROGRESSBAR
:
875 char *end
= utf8encode(data
->wps_progress_pat
[0], buf
);
880 case WPS_TOKEN_PLAYER_PROGRESSBAR
:
883 /* we need 11 characters (full line) for
885 strlcpy(buf
, " ", buf_size
);
889 /* Tell the user if we have an OldPlayer */
890 strlcpy(buf
, " <Old LCD> ", buf_size
);
897 #if (CONFIG_CODEC == SWCODEC)
898 case WPS_TOKEN_CROSSFADE
:
899 #ifdef HAVE_CROSSFADE
901 *intval
= global_settings
.crossfade
+ 1;
902 snprintf(buf
, buf_size
, "%d", global_settings
.crossfade
);
904 snprintf(buf
, buf_size
, "%d", 0);
908 case WPS_TOKEN_REPLAYGAIN
:
912 if (global_settings
.replaygain_type
== REPLAYGAIN_OFF
)
918 type
= get_replaygain_mode(id3
->track_gain_string
!= NULL
,
919 id3
->album_gain_string
!= NULL
);
924 val
= 6; /* no tag */
928 if (global_settings
.replaygain_type
== REPLAYGAIN_SHUFFLE
)
941 /* due to above, coming here with !id3 shouldn't be possible */
944 strlcpy(buf
, id3
->track_gain_string
, buf_size
);
948 strlcpy(buf
, id3
->album_gain_string
, buf_size
);
953 #endif /* (CONFIG_CODEC == SWCODEC) */
955 #if (CONFIG_CODEC != MAS3507D)
956 case WPS_TOKEN_SOUND_PITCH
:
958 int32_t pitch
= sound_get_pitch();
959 snprintf(buf
, buf_size
, "%ld.%ld",
960 pitch
/ PITCH_SPEED_PRECISION
,
961 (pitch
% PITCH_SPEED_PRECISION
) / (PITCH_SPEED_PRECISION
/ 10));
964 *intval
= pitch_speed_enum(limit
, pitch
,
965 PITCH_SPEED_PRECISION
* 100);
970 #if CONFIG_CODEC == SWCODEC
971 case WPS_TOKEN_SOUND_SPEED
:
973 int32_t pitch
= sound_get_pitch();
975 if (dsp_timestretch_available())
976 speed
= GET_SPEED(pitch
, dsp_get_timestretch());
979 snprintf(buf
, buf_size
, "%ld.%ld",
980 speed
/ PITCH_SPEED_PRECISION
,
981 (speed
% PITCH_SPEED_PRECISION
) / (PITCH_SPEED_PRECISION
/ 10));
983 *intval
= pitch_speed_enum(limit
, speed
,
984 PITCH_SPEED_PRECISION
* 100);
989 case WPS_TOKEN_MAIN_HOLD
:
990 #ifdef HAS_BUTTON_HOLD
993 if (is_keys_locked())
994 #endif /*hold switch or softlock*/
999 #ifdef HAS_REMOTE_BUTTON_HOLD
1000 case WPS_TOKEN_REMOTE_HOLD
:
1001 if (remote_button_hold())
1007 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
1008 case WPS_TOKEN_VLED_HDD
:
1014 case WPS_TOKEN_BUTTON_VOLUME
:
1015 if (global_status
.last_volume_change
&&
1016 TIME_BEFORE(current_tick
, global_status
.last_volume_change
+
1017 token
->value
.i
* TIMEOUT_UNIT
))
1021 case WPS_TOKEN_TRACK_STARTING
:
1024 int elapsed
= id3
->elapsed
+ state
->ff_rewind_count
;
1025 if (elapsed
< token
->value
.i
* 1000)
1029 case WPS_TOKEN_TRACK_ENDING
:
1032 unsigned long elapsed
= id3
->elapsed
+ state
->ff_rewind_count
;
1033 unsigned time
= token
->value
.i
* 1000;
1034 if (id3
->length
- elapsed
< time
)
1038 case WPS_TOKEN_LASTTOUCH
:
1039 #ifdef HAVE_TOUCHSCREEN
1040 if (TIME_BEFORE(current_tick
, token
->value
.i
* TIMEOUT_UNIT
+
1041 touchscreen_last_touch()))
1046 case WPS_TOKEN_SETTING
:
1048 const struct settings_list
*s
= settings
+token
->value
.i
;
1051 /* Handle contionals */
1052 switch (s
->flags
&F_T_MASK
)
1056 if (s
->flags
&F_T_SOUND
)
1058 /* %?St|name|<min|min+1|...|max-1|max> */
1059 int sound_setting
= s
->sound_setting
->setting
;
1060 /* settings with decimals can't be used in conditionals */
1061 if (sound_numdecimals(sound_setting
) == 0)
1063 *intval
= (*(int*)s
->setting
-sound_min(sound_setting
))
1064 /sound_steps(sound_setting
) + 1;
1069 else if (s
->flags
&F_RGB
)
1070 /* %?St|name|<#000000|#000001|...|#FFFFFF> */
1071 /* shouldn't overflow since colors are stored
1073 * but this is pretty useless anyway */
1074 *intval
= *(int*)s
->setting
+ 1;
1075 else if (s
->cfg_vals
== NULL
)
1076 /* %?St|name|<1st choice|2nd choice|...> */
1077 *intval
= (*(int*)s
->setting
-s
->int_setting
->min
)
1078 /s
->int_setting
->step
+ 1;
1080 /* %?St|name|<1st choice|2nd choice|...> */
1081 /* Not sure about this one. cfg_name/vals are
1082 * indexed from 0 right? */
1083 *intval
= *(int*)s
->setting
+ 1;
1086 /* %?St|name|<if true|if false> */
1087 *intval
= *(bool*)s
->setting
?1:2;
1091 /* %?St|name|<if non empty string|if empty>
1092 * The string's emptyness discards the setting's
1093 * prefix and suffix */
1094 *intval
= ((char*)s
->setting
)[0]?1:2;
1095 /* if there is a prefix we should ignore it here */
1096 if (s
->filename_setting
->prefix
)
1097 return (char*)s
->setting
;
1100 /* This shouldn't happen ... but you never know */
1105 /* Special handlng for filenames because we dont want to show the prefix */
1106 if ((s
->flags
&F_T_MASK
) == F_T_UCHARPTR
||
1107 (s
->flags
&F_T_MASK
) == F_T_UCHARPTR
)
1109 if (s
->filename_setting
->prefix
)
1110 return (char*)s
->setting
;
1112 cfg_to_string(token
->value
.i
,buf
,buf_size
);
1115 case WPS_TOKEN_HAVE_TUNER
:
1117 if (radio_hardware_present())
1121 /* Recording tokens */
1122 case WPS_TOKEN_HAVE_RECORDING
:
1123 #ifdef HAVE_RECORDING
1129 #ifdef HAVE_RECORDING
1130 case WPS_TOKEN_IS_RECORDING
:
1131 if (audio_status() == AUDIO_STATUS_RECORD
)
1134 case WPS_TOKEN_REC_FREQ
: /* order from REC_FREQ_CFG_VAL_LIST */
1136 #if CONFIG_CODEC == SWCODEC
1137 unsigned long samprk
;
1138 int rec_freq
= global_settings
.rec_frequency
;
1143 #if defined(HAVE_SPDIF_REC)
1144 if (global_settings
.rec_source
== AUDIO_SRC_SPDIF
)
1146 /* Use rate in use, not current measured rate if it changed */
1147 samprk
= pcm_rec_sample_rate();
1149 while (rec_freq
< SAMPR_NUM_FREQ
&&
1150 audio_master_sampr_list
[rec_freq
] != samprk
)
1157 samprk
= rec_freq_sampr
[rec_freq
];
1158 #endif /* SIMULATOR */
1163 REC_HAVE_96_(case REC_FREQ_96
:
1166 REC_HAVE_88_(case REC_FREQ_88
:
1169 REC_HAVE_64_(case REC_FREQ_64
:
1172 REC_HAVE_48_(case REC_FREQ_48
:
1175 REC_HAVE_44_(case REC_FREQ_44
:
1178 REC_HAVE_32_(case REC_FREQ_32
:
1181 REC_HAVE_24_(case REC_FREQ_24
:
1184 REC_HAVE_22_(case REC_FREQ_22
:
1187 REC_HAVE_16_(case REC_FREQ_16
:
1190 REC_HAVE_12_(case REC_FREQ_12
:
1193 REC_HAVE_11_(case REC_FREQ_11
:
1196 REC_HAVE_8_(case REC_FREQ_8
:
1201 snprintf(buf
, buf_size
, "%lu.%1lu", samprk
/1000,samprk
%1000);
1204 static const char * const freq_strings
[] =
1205 {"--", "44", "48", "32", "22", "24", "16"};
1206 int freq
= 1 + global_settings
.rec_frequency
;
1207 #ifdef HAVE_SPDIF_REC
1208 if (global_settings
.rec_source
== AUDIO_SRC_SPDIF
)
1210 /* Can't measure S/PDIF sample rate on Archos/Sim yet */
1213 #endif /* HAVE_SPDIF_IN */
1215 *intval
= freq
+1; /* so the token gets a value 1<=x<=7 */
1216 snprintf(buf
, buf_size
, "%s\n",
1217 freq_strings
[global_settings
.rec_frequency
]);
1221 #if CONFIG_CODEC == SWCODEC
1222 case WPS_TOKEN_REC_ENCODER
:
1224 int rec_format
= global_settings
.rec_format
+1; /* WAV, AIFF, WV, MPEG */
1226 *intval
= rec_format
;
1229 case REC_FORMAT_PCM_WAV
:
1231 case REC_FORMAT_AIFF
:
1233 case REC_FORMAT_WAVPACK
:
1235 case REC_FORMAT_MPA_L3
:
1243 case WPS_TOKEN_REC_BITRATE
:
1244 #if CONFIG_CODEC == SWCODEC
1245 if (global_settings
.rec_format
== REC_FORMAT_MPA_L3
)
1249 #if 0 /* FIXME: I dont know if this is needed? */
1250 switch (1<<global_settings
.mp3_enc_config
.bitrate
)
1252 case MP3_BITR_CAP_8
:
1255 case MP3_BITR_CAP_16
:
1258 case MP3_BITR_CAP_24
:
1261 case MP3_BITR_CAP_32
:
1264 case MP3_BITR_CAP_40
:
1267 case MP3_BITR_CAP_48
:
1270 case MP3_BITR_CAP_56
:
1273 case MP3_BITR_CAP_64
:
1276 case MP3_BITR_CAP_80
:
1279 case MP3_BITR_CAP_96
:
1282 case MP3_BITR_CAP_112
:
1285 case MP3_BITR_CAP_128
:
1288 case MP3_BITR_CAP_144
:
1291 case MP3_BITR_CAP_160
:
1294 case MP3_BITR_CAP_192
:
1299 *intval
= global_settings
.mp3_enc_config
.bitrate
+1;
1301 snprintf(buf
, buf_size
, "%lu", global_settings
.mp3_enc_config
.bitrate
+1);
1305 return NULL
; /* Fixme later */
1306 #else /* CONFIG_CODEC == HWCODEC */
1308 *intval
= global_settings
.rec_quality
+1;
1309 snprintf(buf
, buf_size
, "%d", global_settings
.rec_quality
);
1312 case WPS_TOKEN_REC_MONO
:
1313 if (!global_settings
.rec_channels
)
1317 case WPS_TOKEN_REC_SECONDS
:
1319 int time
= (audio_recorded_time() / HZ
) % 60;
1322 snprintf(buf
, buf_size
, "%02d", time
);
1325 case WPS_TOKEN_REC_MINUTES
:
1327 int time
= (audio_recorded_time() / HZ
) / 60;
1330 snprintf(buf
, buf_size
, "%02d", time
);
1333 case WPS_TOKEN_REC_HOURS
:
1335 int time
= (audio_recorded_time() / HZ
) / 3600;
1338 snprintf(buf
, buf_size
, "%02d", time
);
1342 #endif /* HAVE_RECORDING */
1344 case WPS_TOKEN_CURRENT_SCREEN
:
1346 int curr_screen
= current_screen();
1348 #ifdef HAVE_RECORDING
1349 /* override current_screen() for recording screen since it may
1350 * be entered from the radio screen */
1351 if (in_recording_screen())
1352 curr_screen
= GO_TO_RECSCREEN
;
1355 switch (curr_screen
)
1360 #ifdef HAVE_RECORDING
1361 case GO_TO_RECSCREEN
:
1370 case GO_TO_PLAYLIST_VIEWER
:
1373 default: /* lists */
1379 *intval
= curr_screen
;
1381 snprintf(buf
, buf_size
, "%d", curr_screen
);
1385 case WPS_TOKEN_LANG_IS_RTL
:
1386 return lang_is_rtl() ? "r" : NULL
;