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 #ifdef HAVE_LCD_CHARCELLS
45 #ifdef HAVE_LCD_BITMAP
51 #if CONFIG_CODEC == SWCODEC
57 #include "wps_internals.h"
58 #include "root_menu.h"
60 #include "recording.h"
61 #include "pcm_record.h"
70 extern struct wps_state wps_state
;
72 static const char* get_codectype(const struct mp3entry
* id3
)
74 if (id3
&& id3
->codectype
< AFMT_NUM_CODECS
) {
75 return audio_formats
[id3
->codectype
].label
;
81 /* Extract a part from a path.
83 * buf - buffer extract part to.
84 * buf_size - size of buffer.
85 * path - path to extract from.
86 * level - what to extract. 0 is file name, 1 is parent of file, 2 is
87 * parent of parent, etc.
89 * Returns buf if the desired level was found, NULL otherwise.
91 char* get_dir(char* buf
, int buf_size
, const char* path
, int level
)
97 sep
= path
+ strlen(path
);
112 if (level
|| (last_sep
<= sep
))
115 len
= MIN(last_sep
- sep
, buf_size
- 1);
116 strlcpy(buf
, sep
+ 1, len
+ 1);
120 #if (CONFIG_CODEC != MAS3507D)
121 /* A helper to determine the enum value for pitch/speed.
123 When there are two choices (i.e. boolean), return 1 if the value is
124 different from normal value and 2 if the value is the same as the
125 normal value. E.g. "%?Sp<%Sp>" would show the pitch only when
126 playing at a modified pitch.
128 When there are more than two choices (i.e. enum), the left half of
129 the choices are to show 0..normal range, and the right half of the
130 choices are to show values over that. The last entry is used when
131 it is set to the normal setting, following the rockbox convention
132 to use the last entry for special values.
136 2 items: %?Sp<0..99 or 101..infinity|100>
137 3 items: %?Sp<0..99|101..infinity|100>
138 4 items: %?Sp<0..49|50..99|101..infinity|100>
139 5 items: %?Sp<0..49|50..99|101..149|150..infinity|100>
140 6 items: %?Sp<0..33|34..66|67..99|101..133|134..infinity|100>
141 7 items: %?Sp<0..33|34..66|67..99|101..133|134..167|167..infinity|100>
143 static int pitch_speed_enum(int range
, int32_t val
, int32_t normval
)
149 return (val
== normval
) + 1;
153 n
= (center
* val
) / normval
+ 1;
154 return (range
<= n
) ? (range
- 1) : n
;
159 /* All tokens which only need the info to return a value go in here */
160 const char *get_id3_token(struct wps_token
*token
, struct mp3entry
*id3
,
161 char *buf
, int buf_size
, int limit
, int *intval
)
163 struct wps_state
*state
= &wps_state
;
166 unsigned long length
= id3
->length
;
167 unsigned long elapsed
= id3
->elapsed
+ state
->ff_rewind_count
;
170 case WPS_TOKEN_METADATA_ARTIST
:
172 case WPS_TOKEN_METADATA_COMPOSER
:
173 return id3
->composer
;
174 case WPS_TOKEN_METADATA_ALBUM
:
176 case WPS_TOKEN_METADATA_ALBUM_ARTIST
:
177 return id3
->albumartist
;
178 case WPS_TOKEN_METADATA_GROUPING
:
179 return id3
->grouping
;
180 case WPS_TOKEN_METADATA_GENRE
:
181 return id3
->genre_string
;
182 case WPS_TOKEN_METADATA_DISC_NUMBER
:
183 if (id3
->disc_string
)
184 return id3
->disc_string
;
186 snprintf(buf
, buf_size
, "%d", id3
->discnum
);
190 case WPS_TOKEN_METADATA_TRACK_NUMBER
:
191 if (id3
->track_string
)
192 return id3
->track_string
;
194 snprintf(buf
, buf_size
, "%d", id3
->tracknum
);
198 case WPS_TOKEN_METADATA_TRACK_TITLE
:
200 case WPS_TOKEN_METADATA_VERSION
:
201 switch (id3
->id3version
)
217 case WPS_TOKEN_METADATA_YEAR
:
218 if( id3
->year_string
)
219 return id3
->year_string
;
221 snprintf(buf
, buf_size
, "%d", id3
->year
);
225 case WPS_TOKEN_METADATA_COMMENT
:
227 case WPS_TOKEN_FILE_PATH
:
229 case WPS_TOKEN_FILE_BITRATE
:
231 snprintf(buf
, buf_size
, "%d", id3
->bitrate
);
235 case WPS_TOKEN_TRACK_TIME_ELAPSED
:
236 format_time(buf
, buf_size
, elapsed
);
239 case WPS_TOKEN_TRACK_TIME_REMAINING
:
240 format_time(buf
, buf_size
, length
- elapsed
);
243 case WPS_TOKEN_TRACK_LENGTH
:
244 format_time(buf
, buf_size
, length
);
247 case WPS_TOKEN_TRACK_ELAPSED_PERCENT
:
253 *intval
= limit
* elapsed
/ length
+ 1;
255 snprintf(buf
, buf_size
, "%lu", 100 * elapsed
/ length
);
258 case WPS_TOKEN_TRACK_STARTING
:
260 unsigned long time
= token
->value
.i
* 1000;
265 case WPS_TOKEN_TRACK_ENDING
:
267 unsigned long time
= token
->value
.i
* 1000;
268 if (length
- elapsed
< time
)
273 case WPS_TOKEN_FILE_CODEC
:
276 if(id3
->codectype
== AFMT_UNKNOWN
)
277 *intval
= AFMT_NUM_CODECS
;
279 *intval
= id3
->codectype
;
281 return get_codectype(id3
);
283 case WPS_TOKEN_FILE_FREQUENCY
:
284 snprintf(buf
, buf_size
, "%ld", id3
->frequency
);
286 case WPS_TOKEN_FILE_FREQUENCY_KHZ
:
287 /* ignore remainders < 100, so 22050 Hz becomes just 22k */
288 if ((id3
->frequency
% 1000) < 100)
289 snprintf(buf
, buf_size
, "%ld", id3
->frequency
/ 1000);
291 snprintf(buf
, buf_size
, "%ld.%lu",
292 id3
->frequency
/ 1000,
293 (id3
->frequency
% 1000) / 100);
295 case WPS_TOKEN_FILE_NAME
:
296 if (get_dir(buf
, buf_size
, id3
->path
, 0)) {
297 /* Remove extension */
298 char* sep
= strrchr(buf
, '.');
305 case WPS_TOKEN_FILE_NAME_WITH_EXTENSION
:
306 return get_dir(buf
, buf_size
, id3
->path
, 0);
307 case WPS_TOKEN_FILE_SIZE
:
308 snprintf(buf
, buf_size
, "%ld", id3
->filesize
/ 1024);
310 case WPS_TOKEN_FILE_VBR
:
311 return (id3
->vbr
) ? "(avg)" : NULL
;
312 case WPS_TOKEN_FILE_DIRECTORY
:
313 return get_dir(buf
, buf_size
, id3
->path
, token
->value
.i
);
316 case WPS_TOKEN_DATABASE_PLAYCOUNT
:
318 *intval
= id3
->playcount
+ 1;
319 snprintf(buf
, buf_size
, "%ld", id3
->playcount
);
321 case WPS_TOKEN_DATABASE_RATING
:
323 *intval
= id3
->rating
+ 1;
324 snprintf(buf
, buf_size
, "%d", id3
->rating
);
326 case WPS_TOKEN_DATABASE_AUTOSCORE
:
328 *intval
= id3
->score
+ 1;
329 snprintf(buf
, buf_size
, "%d", id3
->score
);
337 else /* id3 == NULL, handle the error based on the expected return type */
341 /* Most tokens expect NULL on error so leave that for the default case,
342 * The ones that expect "0" need to be handled */
343 case WPS_TOKEN_FILE_FREQUENCY
:
344 case WPS_TOKEN_FILE_FREQUENCY_KHZ
:
345 case WPS_TOKEN_FILE_SIZE
:
347 case WPS_TOKEN_DATABASE_PLAYCOUNT
:
348 case WPS_TOKEN_DATABASE_RATING
:
349 case WPS_TOKEN_DATABASE_AUTOSCORE
:
363 /* Formats the frequency (specified in Hz) in MHz, */
364 /* with one or two digits after the decimal point -- */
365 /* depending on the frequency changing step. */
367 static char *format_freq_MHz(int freq
, int freq_step
, char *buf
, int buf_size
)
371 if (freq_step
< 100000)
373 /* Format with two digits after decimal point */
379 /* Format with one digit after decimal point */
383 div
= 1000000 / scale
;
385 snprintf(buf
, buf_size
, fmt
, freq
/div
, freq
%div
);
390 /* Tokens which are really only used by the radio screen go in here */
391 const char *get_radio_token(struct wps_token
*token
, int preset_offset
,
392 char *buf
, int buf_size
, int limit
, int *intval
)
394 const struct fm_region_data
*region_data
=
395 &(fm_region_data
[global_settings
.fm_region
]);
399 /* Radio/tuner tokens */
400 case WPS_TOKEN_TUNER_TUNED
:
401 if (tuner_get(RADIO_TUNED
))
404 case WPS_TOKEN_TUNER_SCANMODE
:
405 if (radio_scan_mode())
408 case WPS_TOKEN_TUNER_STEREO
:
409 if (radio_is_stereo())
412 case WPS_TOKEN_TUNER_MINFREQ
: /* changes based on "region" */
413 return format_freq_MHz(region_data
->freq_min
,
414 region_data
->freq_step
, buf
, buf_size
);
415 case WPS_TOKEN_TUNER_MAXFREQ
: /* changes based on "region" */
416 return format_freq_MHz(region_data
->freq_max
,
417 region_data
->freq_step
, buf
, buf_size
);
418 case WPS_TOKEN_TUNER_CURFREQ
:
419 return format_freq_MHz(radio_current_frequency(),
420 region_data
->freq_step
, buf
, buf_size
);
421 case WPS_TOKEN_PRESET_NAME
:
422 case WPS_TOKEN_PRESET_FREQ
:
423 case WPS_TOKEN_PRESET_ID
:
425 int preset_count
= radio_preset_count();
426 int cur_preset
= radio_current_preset();
427 if (preset_count
== 0 || cur_preset
< 0)
429 int preset
= cur_preset
+ preset_offset
;
430 /* make sure it's in the valid range */
431 preset
%= preset_count
;
433 preset
+= preset_count
;
434 if (token
->type
== WPS_TOKEN_PRESET_NAME
)
435 snprintf(buf
, buf_size
, "%s", radio_get_preset(preset
)->name
);
436 else if (token
->type
== WPS_TOKEN_PRESET_FREQ
)
437 format_freq_MHz(radio_get_preset(preset
)->frequency
,
438 region_data
->freq_step
, buf
, buf_size
);
440 snprintf(buf
, buf_size
, "%d", preset
+ 1);
443 case WPS_TOKEN_PRESET_COUNT
:
444 snprintf(buf
, buf_size
, "%d", radio_preset_count());
446 *intval
= radio_preset_count();
448 case WPS_TOKEN_HAVE_RDS
:
451 case WPS_TOKEN_RDS_NAME
:
452 return tuner_get_rds_info(RADIO_RDS_NAME
);
453 case WPS_TOKEN_RDS_TEXT
:
454 return tuner_get_rds_info(RADIO_RDS_TEXT
);
456 return NULL
; /* end of the WPS_TOKEN_HAVE_RDS case */
457 #endif /* HAVE_RDS_CAP */
463 /* Return the tags value as text. buf should be used as temp storage if needed.
465 intval is used with conditionals/enums: when this function is called,
466 intval should contain the number of options in the conditional/enum.
467 When this function returns, intval is -1 if the tag is non numeric or,
468 if the tag is numeric, *intval is the enum case we want to go to (between 1
469 and the original value of *intval, inclusive).
470 When not treating a conditional/enum, intval should be NULL.
472 const char *get_token_value(struct gui_wps
*gwps
,
473 struct wps_token
*token
,
474 char *buf
, int buf_size
,
480 struct wps_data
*data
= gwps
->data
;
481 struct wps_state
*state
= gwps
->state
;
482 struct mp3entry
*id3
; /* Think very carefully about using this.
483 maybe get_id3_token() is the better place? */
484 const char *out_text
= NULL
;
496 struct tm
* tm
= NULL
;
498 /* if the token is an RTC one, update the time
499 and do the necessary checks */
500 if (token
->type
>= WPS_TOKENS_RTC_BEGIN
501 && token
->type
<= WPS_TOKENS_RTC_END
)
517 if (state
->id3
&& state
->id3
->cuesheet
)
519 out_text
= get_cuesheetid3_token(token
, state
->id3
, token
->next
?1:0, buf
, buf_size
);
523 out_text
= get_id3_token(token
, id3
, buf
, buf_size
, limit
, intval
);
527 out_text
= get_radio_token(token
, 0, buf
, buf_size
, limit
, intval
);
534 case WPS_TOKEN_CHARACTER
:
535 if (token
->value
.c
== '\n')
537 return &(token
->value
.c
);
539 case WPS_TOKEN_STRING
:
540 return (char*)token
->value
.data
;
542 case WPS_TOKEN_TRANSLATEDSTRING
:
543 return (char*)P2STR(ID2P(token
->value
.i
));
545 case WPS_TOKEN_PLAYLIST_ENTRIES
:
546 snprintf(buf
, buf_size
, "%d", playlist_amount());
549 case WPS_TOKEN_LIST_TITLE_TEXT
:
550 return (char*)token
->value
.data
;
551 case WPS_TOKEN_LIST_TITLE_ICON
:
553 *intval
= token
->value
.i
;
554 snprintf(buf
, buf_size
, "%d", token
->value
.i
);
557 case WPS_TOKEN_PLAYLIST_NAME
:
558 return playlist_name(NULL
, buf
, buf_size
);
560 case WPS_TOKEN_PLAYLIST_POSITION
:
561 snprintf(buf
, buf_size
, "%d", playlist_get_display_index());
564 case WPS_TOKEN_PLAYLIST_SHUFFLE
:
565 if ( global_settings
.playlist_shuffle
)
571 case WPS_TOKEN_VOLUME
:
572 snprintf(buf
, buf_size
, "%d", global_settings
.volume
);
575 int minvol
= sound_min(SOUND_VOLUME
);
576 if (global_settings
.volume
== minvol
)
580 else if (global_settings
.volume
== 0)
584 else if (global_settings
.volume
> 0)
590 *intval
= (limit
-3) * (global_settings
.volume
- minvol
- 1)
596 case WPS_TOKEN_ALBUMART_FOUND
:
600 handle
= playback_current_aa_hid(data
->playback_aa_slot
);
602 if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF
))
604 struct dim dim
= {data
->albumart
->width
, data
->albumart
->height
};
605 handle
= radio_get_art_hid(&dim
);
613 case WPS_TOKEN_ALBUMART_DISPLAY
:
616 if (!data
->albumart
->draw
)
617 data
->albumart
->draw
= true;
621 case WPS_TOKEN_BATTERY_PERCENT
:
623 int l
= battery_level();
627 limit
= MAX(limit
, 2);
629 /* First enum is used for "unknown level". */
630 *intval
= (limit
- 1) * l
/ 100 + 2;
637 snprintf(buf
, buf_size
, "%d", l
);
644 case WPS_TOKEN_BATTERY_VOLTS
:
646 unsigned int v
= battery_voltage();
647 snprintf(buf
, buf_size
, "%d.%02d", v
/ 1000, (v
% 1000) / 10);
651 case WPS_TOKEN_BATTERY_TIME
:
653 int t
= battery_time();
655 snprintf(buf
, buf_size
, "%dh %dm", t
/ 60, t
% 60);
662 case WPS_TOKEN_BATTERY_CHARGER_CONNECTED
:
664 if(charger_input_state
==CHARGER
)
670 #if CONFIG_CHARGING >= CHARGING_MONITOR
671 case WPS_TOKEN_BATTERY_CHARGING
:
673 if (charge_state
== CHARGING
|| charge_state
== TOPOFF
) {
680 #ifdef HAVE_USB_POWER
681 case WPS_TOKEN_USB_POWERED
:
686 case WPS_TOKEN_BATTERY_SLEEPTIME
:
688 if (get_sleep_timer() == 0)
692 format_time(buf
, buf_size
, get_sleep_timer() * 1000);
697 case WPS_TOKEN_PLAYBACK_STATUS
:
699 int status
= current_playmode();
701 int mode
= 1; /* stop */
702 if (status
== STATUS_PLAY
)
704 if (state
->is_fading
||
705 (status
== STATUS_PAUSE
&& !status_get_ffmode()))
706 mode
= 3; /* pause */
709 if (status_get_ffmode() == STATUS_FASTFORWARD
)
711 if (status_get_ffmode() == STATUS_FASTBACKWARD
)
714 #ifdef HAVE_RECORDING
716 if (status
== STATUS_RECORD
)
718 else if (status
== STATUS_RECORD_PAUSE
)
723 if (status
== STATUS_RADIO
)
725 else if (status
== STATUS_RADIO_PAUSE
)
733 snprintf(buf
, buf_size
, "%d", mode
-1);
737 case WPS_TOKEN_REPEAT_MODE
:
739 *intval
= global_settings
.repeat_mode
+ 1;
740 snprintf(buf
, buf_size
, "%d", global_settings
.repeat_mode
);
743 case WPS_TOKEN_RTC_PRESENT
:
751 case WPS_TOKEN_RTC_12HOUR_CFG
:
753 *intval
= global_settings
.timeformat
+ 1;
754 snprintf(buf
, buf_size
, "%d", global_settings
.timeformat
);
757 case WPS_TOKEN_RTC_DAY_OF_MONTH
:
758 /* d: day of month (01..31) */
759 snprintf(buf
, buf_size
, "%02d", tm
->tm_mday
);
761 *intval
= tm
->tm_mday
- 1;
764 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED
:
765 /* e: day of month, blank padded ( 1..31) */
766 snprintf(buf
, buf_size
, "%2d", tm
->tm_mday
);
768 *intval
= tm
->tm_mday
- 1;
771 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED
:
772 /* H: hour (00..23) */
773 snprintf(buf
, buf_size
, "%02d", tm
->tm_hour
);
775 *intval
= tm
->tm_hour
;
778 case WPS_TOKEN_RTC_HOUR_24
:
779 /* k: hour ( 0..23) */
780 snprintf(buf
, buf_size
, "%2d", tm
->tm_hour
);
782 *intval
= tm
->tm_hour
;
785 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED
:
786 /* I: hour (01..12) */
787 snprintf(buf
, buf_size
, "%02d",
788 (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12);
790 *intval
= (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12;
793 case WPS_TOKEN_RTC_HOUR_12
:
794 /* l: hour ( 1..12) */
795 snprintf(buf
, buf_size
, "%2d",
796 (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12);
798 *intval
= (tm
->tm_hour
% 12 == 0) ? 12 : tm
->tm_hour
% 12;
801 case WPS_TOKEN_RTC_MONTH
:
802 /* m: month (01..12) */
804 *intval
= tm
->tm_mon
+ 1;
805 snprintf(buf
, buf_size
, "%02d", tm
->tm_mon
+ 1);
808 case WPS_TOKEN_RTC_MINUTE
:
809 /* M: minute (00..59) */
810 snprintf(buf
, buf_size
, "%02d", tm
->tm_min
);
812 *intval
= tm
->tm_min
;
815 case WPS_TOKEN_RTC_SECOND
:
816 /* S: second (00..59) */
817 snprintf(buf
, buf_size
, "%02d", tm
->tm_sec
);
819 *intval
= tm
->tm_sec
;
822 case WPS_TOKEN_RTC_YEAR_2_DIGITS
:
823 /* y: last two digits of year (00..99) */
824 snprintf(buf
, buf_size
, "%02d", tm
->tm_year
% 100);
826 *intval
= tm
->tm_year
% 100;
829 case WPS_TOKEN_RTC_YEAR_4_DIGITS
:
830 /* Y: year (1970...) */
831 snprintf(buf
, buf_size
, "%04d", tm
->tm_year
+ 1900);
833 *intval
= tm
->tm_year
+ 1900;
836 case WPS_TOKEN_RTC_AM_PM_UPPER
:
837 /* p: upper case AM or PM indicator */
839 *intval
= tm
->tm_hour
/12 == 0 ? 0 : 1;
840 return tm
->tm_hour
/12 == 0 ? "AM" : "PM";
842 case WPS_TOKEN_RTC_AM_PM_LOWER
:
843 /* P: lower case am or pm indicator */
845 *intval
= tm
->tm_hour
/12 == 0 ? 0 : 1;
846 return tm
->tm_hour
/12 == 0 ? "am" : "pm";
848 case WPS_TOKEN_RTC_WEEKDAY_NAME
:
849 /* a: abbreviated weekday name (Sun..Sat) */
850 return str(LANG_WEEKDAY_SUNDAY
+ tm
->tm_wday
);
852 case WPS_TOKEN_RTC_MONTH_NAME
:
853 /* b: abbreviated month name (Jan..Dec) */
854 return str(LANG_MONTH_JANUARY
+ tm
->tm_mon
);
856 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON
:
857 /* u: day of week (1..7); 1 is Monday */
859 *intval
= (tm
->tm_wday
== 0) ? 7 : tm
->tm_wday
;
860 snprintf(buf
, buf_size
, "%1d", tm
->tm_wday
+ 1);
863 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN
:
864 /* w: day of week (0..6); 0 is Sunday */
866 *intval
= tm
->tm_wday
+ 1;
867 snprintf(buf
, buf_size
, "%1d", tm
->tm_wday
);
870 case WPS_TOKEN_RTC_DAY_OF_MONTH
:
871 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED
:
872 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED
:
873 case WPS_TOKEN_RTC_HOUR_24
:
874 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED
:
875 case WPS_TOKEN_RTC_HOUR_12
:
876 case WPS_TOKEN_RTC_MONTH
:
877 case WPS_TOKEN_RTC_MINUTE
:
878 case WPS_TOKEN_RTC_SECOND
:
879 case WPS_TOKEN_RTC_AM_PM_UPPER
:
880 case WPS_TOKEN_RTC_AM_PM_LOWER
:
881 case WPS_TOKEN_RTC_YEAR_2_DIGITS
:
883 case WPS_TOKEN_RTC_YEAR_4_DIGITS
:
885 case WPS_TOKEN_RTC_WEEKDAY_NAME
:
886 case WPS_TOKEN_RTC_MONTH_NAME
:
888 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON
:
889 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN
:
893 #ifdef HAVE_LCD_CHARCELLS
894 case WPS_TOKEN_PROGRESSBAR
:
896 char *end
= utf8encode(data
->wps_progress_pat
[0], buf
);
901 case WPS_TOKEN_PLAYER_PROGRESSBAR
:
904 /* we need 11 characters (full line) for
906 strlcpy(buf
, " ", buf_size
);
910 /* Tell the user if we have an OldPlayer */
911 strlcpy(buf
, " <Old LCD> ", buf_size
);
918 #if (CONFIG_CODEC == SWCODEC)
919 case WPS_TOKEN_CROSSFADE
:
920 #ifdef HAVE_CROSSFADE
922 *intval
= global_settings
.crossfade
+ 1;
923 snprintf(buf
, buf_size
, "%d", global_settings
.crossfade
);
925 snprintf(buf
, buf_size
, "%d", 0);
929 case WPS_TOKEN_REPLAYGAIN
:
933 if (global_settings
.replaygain_type
== REPLAYGAIN_OFF
)
939 type
= get_replaygain_mode(id3
->track_gain_string
!= NULL
,
940 id3
->album_gain_string
!= NULL
);
945 val
= 6; /* no tag */
949 if (global_settings
.replaygain_type
== REPLAYGAIN_SHUFFLE
)
962 /* due to above, coming here with !id3 shouldn't be possible */
965 strlcpy(buf
, id3
->track_gain_string
, buf_size
);
969 strlcpy(buf
, id3
->album_gain_string
, buf_size
);
974 #endif /* (CONFIG_CODEC == SWCODEC) */
976 #if (CONFIG_CODEC != MAS3507D)
977 case WPS_TOKEN_SOUND_PITCH
:
979 int32_t pitch
= sound_get_pitch();
980 snprintf(buf
, buf_size
, "%ld.%ld",
981 pitch
/ PITCH_SPEED_PRECISION
,
982 (pitch
% PITCH_SPEED_PRECISION
) / (PITCH_SPEED_PRECISION
/ 10));
985 *intval
= pitch_speed_enum(limit
, pitch
,
986 PITCH_SPEED_PRECISION
* 100);
991 #if CONFIG_CODEC == SWCODEC
992 case WPS_TOKEN_SOUND_SPEED
:
994 int32_t pitch
= sound_get_pitch();
996 if (dsp_timestretch_available())
997 speed
= GET_SPEED(pitch
, dsp_get_timestretch());
1000 snprintf(buf
, buf_size
, "%ld.%ld",
1001 speed
/ PITCH_SPEED_PRECISION
,
1002 (speed
% PITCH_SPEED_PRECISION
) / (PITCH_SPEED_PRECISION
/ 10));
1004 *intval
= pitch_speed_enum(limit
, speed
,
1005 PITCH_SPEED_PRECISION
* 100);
1010 case WPS_TOKEN_MAIN_HOLD
:
1011 #ifdef HAS_BUTTON_HOLD
1014 if (is_keys_locked())
1015 #endif /*hold switch or softlock*/
1020 #ifdef HAS_REMOTE_BUTTON_HOLD
1021 case WPS_TOKEN_REMOTE_HOLD
:
1022 if (remote_button_hold())
1028 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
1029 case WPS_TOKEN_VLED_HDD
:
1035 case WPS_TOKEN_BUTTON_VOLUME
:
1036 if (global_status
.last_volume_change
&&
1037 TIME_BEFORE(current_tick
, global_status
.last_volume_change
+
1038 token
->value
.i
* TIMEOUT_UNIT
))
1042 case WPS_TOKEN_LASTTOUCH
:
1043 #ifdef HAVE_TOUCHSCREEN
1044 if (TIME_BEFORE(current_tick
, token
->value
.i
* TIMEOUT_UNIT
+
1045 touchscreen_last_touch()))
1050 case WPS_TOKEN_SETTING
:
1052 const struct settings_list
*s
= settings
+token
->value
.i
;
1055 /* Handle contionals */
1056 switch (s
->flags
&F_T_MASK
)
1060 if (s
->flags
&F_T_SOUND
)
1062 /* %?St|name|<min|min+1|...|max-1|max> */
1063 int sound_setting
= s
->sound_setting
->setting
;
1064 /* settings with decimals can't be used in conditionals */
1065 if (sound_numdecimals(sound_setting
) == 0)
1067 *intval
= (*(int*)s
->setting
-sound_min(sound_setting
))
1068 /sound_steps(sound_setting
) + 1;
1073 else if (s
->flags
&F_RGB
)
1074 /* %?St|name|<#000000|#000001|...|#FFFFFF> */
1075 /* shouldn't overflow since colors are stored
1077 * but this is pretty useless anyway */
1078 *intval
= *(int*)s
->setting
+ 1;
1079 else if (s
->cfg_vals
== NULL
)
1080 /* %?St|name|<1st choice|2nd choice|...> */
1081 *intval
= (*(int*)s
->setting
-s
->int_setting
->min
)
1082 /s
->int_setting
->step
+ 1;
1084 /* %?St|name|<1st choice|2nd choice|...> */
1085 /* Not sure about this one. cfg_name/vals are
1086 * indexed from 0 right? */
1087 *intval
= *(int*)s
->setting
+ 1;
1090 /* %?St|name|<if true|if false> */
1091 *intval
= *(bool*)s
->setting
?1:2;
1095 /* %?St|name|<if non empty string|if empty>
1096 * The string's emptyness discards the setting's
1097 * prefix and suffix */
1098 *intval
= ((char*)s
->setting
)[0]?1:2;
1099 /* if there is a prefix we should ignore it here */
1100 if (s
->filename_setting
->prefix
)
1101 return (char*)s
->setting
;
1104 /* This shouldn't happen ... but you never know */
1109 /* Special handlng for filenames because we dont want to show the prefix */
1110 if ((s
->flags
&F_T_MASK
) == F_T_UCHARPTR
||
1111 (s
->flags
&F_T_MASK
) == F_T_UCHARPTR
)
1113 if (s
->filename_setting
->prefix
)
1114 return (char*)s
->setting
;
1116 cfg_to_string(token
->value
.i
,buf
,buf_size
);
1119 case WPS_TOKEN_HAVE_TUNER
:
1121 if (radio_hardware_present())
1125 /* Recording tokens */
1126 case WPS_TOKEN_HAVE_RECORDING
:
1127 #ifdef HAVE_RECORDING
1133 #ifdef HAVE_RECORDING
1134 case WPS_TOKEN_IS_RECORDING
:
1135 if (audio_status() == AUDIO_STATUS_RECORD
)
1138 case WPS_TOKEN_REC_FREQ
: /* order from REC_FREQ_CFG_VAL_LIST */
1140 #if CONFIG_CODEC == SWCODEC
1141 unsigned long samprk
;
1142 int rec_freq
= global_settings
.rec_frequency
;
1147 #if defined(HAVE_SPDIF_REC)
1148 if (global_settings
.rec_source
== AUDIO_SRC_SPDIF
)
1150 /* Use rate in use, not current measured rate if it changed */
1151 samprk
= pcm_rec_sample_rate();
1153 while (rec_freq
< SAMPR_NUM_FREQ
&&
1154 audio_master_sampr_list
[rec_freq
] != samprk
)
1161 samprk
= rec_freq_sampr
[rec_freq
];
1162 #endif /* SIMULATOR */
1167 REC_HAVE_96_(case REC_FREQ_96
:
1170 REC_HAVE_88_(case REC_FREQ_88
:
1173 REC_HAVE_64_(case REC_FREQ_64
:
1176 REC_HAVE_48_(case REC_FREQ_48
:
1179 REC_HAVE_44_(case REC_FREQ_44
:
1182 REC_HAVE_32_(case REC_FREQ_32
:
1185 REC_HAVE_24_(case REC_FREQ_24
:
1188 REC_HAVE_22_(case REC_FREQ_22
:
1191 REC_HAVE_16_(case REC_FREQ_16
:
1194 REC_HAVE_12_(case REC_FREQ_12
:
1197 REC_HAVE_11_(case REC_FREQ_11
:
1200 REC_HAVE_8_(case REC_FREQ_8
:
1205 snprintf(buf
, buf_size
, "%lu.%1lu", samprk
/1000,samprk
%1000);
1208 static const char * const freq_strings
[] =
1209 {"--", "44", "48", "32", "22", "24", "16"};
1210 int freq
= 1 + global_settings
.rec_frequency
;
1211 #ifdef HAVE_SPDIF_REC
1212 if (global_settings
.rec_source
== AUDIO_SRC_SPDIF
)
1214 /* Can't measure S/PDIF sample rate on Archos/Sim yet */
1217 #endif /* HAVE_SPDIF_IN */
1219 *intval
= freq
+1; /* so the token gets a value 1<=x<=7 */
1220 snprintf(buf
, buf_size
, "%s\n",
1221 freq_strings
[global_settings
.rec_frequency
]);
1225 #if CONFIG_CODEC == SWCODEC
1226 case WPS_TOKEN_REC_ENCODER
:
1228 int rec_format
= global_settings
.rec_format
+1; /* WAV, AIFF, WV, MPEG */
1230 *intval
= rec_format
;
1233 case REC_FORMAT_PCM_WAV
:
1235 case REC_FORMAT_AIFF
:
1237 case REC_FORMAT_WAVPACK
:
1239 case REC_FORMAT_MPA_L3
:
1247 case WPS_TOKEN_REC_BITRATE
:
1248 #if CONFIG_CODEC == SWCODEC
1249 if (global_settings
.rec_format
== REC_FORMAT_MPA_L3
)
1253 #if 0 /* FIXME: I dont know if this is needed? */
1254 switch (1<<global_settings
.mp3_enc_config
.bitrate
)
1256 case MP3_BITR_CAP_8
:
1259 case MP3_BITR_CAP_16
:
1262 case MP3_BITR_CAP_24
:
1265 case MP3_BITR_CAP_32
:
1268 case MP3_BITR_CAP_40
:
1271 case MP3_BITR_CAP_48
:
1274 case MP3_BITR_CAP_56
:
1277 case MP3_BITR_CAP_64
:
1280 case MP3_BITR_CAP_80
:
1283 case MP3_BITR_CAP_96
:
1286 case MP3_BITR_CAP_112
:
1289 case MP3_BITR_CAP_128
:
1292 case MP3_BITR_CAP_144
:
1295 case MP3_BITR_CAP_160
:
1298 case MP3_BITR_CAP_192
:
1303 *intval
= global_settings
.mp3_enc_config
.bitrate
+1;
1305 snprintf(buf
, buf_size
, "%lu", global_settings
.mp3_enc_config
.bitrate
+1);
1309 return NULL
; /* Fixme later */
1310 #else /* CONFIG_CODEC == HWCODEC */
1312 *intval
= global_settings
.rec_quality
+1;
1313 snprintf(buf
, buf_size
, "%d", global_settings
.rec_quality
);
1316 case WPS_TOKEN_REC_MONO
:
1317 if (!global_settings
.rec_channels
)
1321 case WPS_TOKEN_REC_SECONDS
:
1323 int time
= (audio_recorded_time() / HZ
) % 60;
1326 snprintf(buf
, buf_size
, "%02d", time
);
1329 case WPS_TOKEN_REC_MINUTES
:
1331 int time
= (audio_recorded_time() / HZ
) / 60;
1334 snprintf(buf
, buf_size
, "%02d", time
);
1337 case WPS_TOKEN_REC_HOURS
:
1339 int time
= (audio_recorded_time() / HZ
) / 3600;
1342 snprintf(buf
, buf_size
, "%02d", time
);
1346 #endif /* HAVE_RECORDING */
1348 case WPS_TOKEN_CURRENT_SCREEN
:
1350 int curr_screen
= current_screen();
1352 #ifdef HAVE_RECORDING
1353 /* override current_screen() for recording screen since it may
1354 * be entered from the radio screen */
1355 if (in_recording_screen())
1356 curr_screen
= GO_TO_RECSCREEN
;
1359 switch (curr_screen
)
1364 #ifdef HAVE_RECORDING
1365 case GO_TO_RECSCREEN
:
1374 case GO_TO_PLAYLIST_VIEWER
:
1377 default: /* lists */
1383 *intval
= curr_screen
;
1385 snprintf(buf
, buf_size
, "%d", curr_screen
);
1389 case WPS_TOKEN_LANG_IS_RTL
:
1390 return lang_is_rtl() ? "r" : NULL
;