1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 Bj�n Stenberg
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
28 #include "mp3_playback.h"
30 #include "statusbar.h"
32 #ifdef HAVE_LCD_BITMAP
48 #if CONFIG_CODEC == MAS3587F
49 #include "peakmeter.h"
53 #if CONFIG_CODEC == SWCODEC
60 int selected_setting
; /* Used by the callback */
61 void dec_sound_formatter(char *buffer
, int buffer_size
, int val
, const char * unit
)
63 val
= sound_val2phys(selected_setting
, val
);
70 int integer
= val
/ 10;
72 snprintf(buffer
, buffer_size
, "%c%d.%d %s", sign
, integer
, dec
, unit
);
75 bool set_sound(const unsigned char * string
,
79 int talkunit
= UNIT_INT
;
80 const char* unit
= sound_unit(setting
);
81 int numdec
= sound_numdecimals(setting
);
82 int steps
= sound_steps(setting
);
83 int min
= sound_min(setting
);
84 int max
= sound_max(setting
);
85 sound_set_type
* sound_callback
= sound_get_fn(setting
);
86 if (*unit
== 'd') /* crude reconstruction */
88 else if (*unit
== '%')
89 talkunit
= UNIT_PERCENT
;
90 else if (*unit
== 'H')
91 talkunit
= UNIT_HERTZ
;
93 #if CONFIG_CODEC == SWCODEC
94 /* We need to hijack this one and send it off to apps/dsp.c instead of
96 if (setting
== SOUND_STEREO_WIDTH
)
97 return set_int(string
, unit
, talkunit
, variable
, &stereo_width_set
,
98 steps
, min
, max
, NULL
);
101 return set_int(string
, unit
, talkunit
, variable
, sound_callback
,
102 steps
, min
, max
, NULL
);
104 {/* Decimal number */
105 selected_setting
=setting
;
106 return set_int(string
, unit
, talkunit
, variable
, sound_callback
,
107 steps
, min
, max
, &dec_sound_formatter
);
111 static bool volume(void)
113 return set_sound(str(LANG_VOLUME
), &global_settings
.volume
, SOUND_VOLUME
);
116 static bool balance(void)
118 return set_sound(str(LANG_BALANCE
), &global_settings
.balance
,
123 static bool bass(void)
125 return set_sound(str(LANG_BASS
), &global_settings
.bass
, SOUND_BASS
);
128 static bool treble(void)
130 return set_sound(str(LANG_TREBLE
), &global_settings
.treble
, SOUND_TREBLE
);
134 #if CONFIG_CODEC == SWCODEC
135 static void crossfeed_format(char* buffer
, int buffer_size
, int value
,
138 snprintf(buffer
, buffer_size
, "%s%d.%d %s", value
== 0 ? " " : "-",
139 value
/ 10, value
% 10, unit
);
142 static bool crossfeed_enabled(void)
144 bool result
= set_bool_options(str(LANG_CROSSFEED
),
145 &global_settings
.crossfeed
,
150 dsp_set_crossfeed(global_settings
.crossfeed
);
155 static bool crossfeed_direct_gain(void)
157 return set_int(str(LANG_CROSSFEED_DIRECT_GAIN
), str(LANG_UNIT_DB
),
158 UNIT_DB
, &global_settings
.crossfeed_direct_gain
,
159 &dsp_set_crossfeed_direct_gain
, 5, 0, 60, crossfeed_format
);
162 static void crossfeed_cross_gain_helper(int val
)
164 dsp_set_crossfeed_cross_params(val
,
165 val
+ global_settings
.crossfeed_hf_attenuation
,
166 global_settings
.crossfeed_hf_cutoff
);
169 static bool crossfeed_cross_gain(void)
171 return set_int(str(LANG_CROSSFEED_CROSS_GAIN
), str(LANG_UNIT_DB
),
172 UNIT_DB
, &global_settings
.crossfeed_cross_gain
,
173 &crossfeed_cross_gain_helper
, 5, 30, 120, crossfeed_format
);
176 static void crossfeed_hf_att_helper(int val
)
178 dsp_set_crossfeed_cross_params(global_settings
.crossfeed_cross_gain
,
179 global_settings
.crossfeed_cross_gain
+ val
,
180 global_settings
.crossfeed_hf_cutoff
);
183 static bool crossfeed_hf_attenuation(void)
185 return set_int(str(LANG_CROSSFEED_HF_ATTENUATION
), str(LANG_UNIT_DB
),
186 UNIT_DB
, &global_settings
.crossfeed_hf_attenuation
,
187 &crossfeed_hf_att_helper
, 5, 60, 240, crossfeed_format
);
190 static void crossfeed_hf_cutoff_helper(int val
)
192 dsp_set_crossfeed_cross_params(global_settings
.crossfeed_cross_gain
,
193 global_settings
.crossfeed_cross_gain
+ global_settings
.crossfeed_hf_attenuation
, val
);
196 static bool crossfeed_hf_cutoff(void)
198 return set_int(str(LANG_CROSSFEED_HF_CUTOFF
), str(LANG_UNIT_HERTZ
),
199 UNIT_HERTZ
, &global_settings
.crossfeed_hf_cutoff
, &crossfeed_hf_cutoff_helper
, 100, 500, 2000,
203 static bool crossfeed_menu(void)
207 static const struct menu_item items
[] = {
208 { ID2P(LANG_CROSSFEED
), crossfeed_enabled
},
209 { ID2P(LANG_CROSSFEED_DIRECT_GAIN
), crossfeed_direct_gain
},
210 { ID2P(LANG_CROSSFEED_CROSS_GAIN
), crossfeed_cross_gain
},
211 { ID2P(LANG_CROSSFEED_HF_ATTENUATION
), crossfeed_hf_attenuation
},
212 { ID2P(LANG_CROSSFEED_HF_CUTOFF
), crossfeed_hf_cutoff
},
215 m
=menu_init(items
, sizeof(items
) / sizeof(*items
), NULL
,
217 result
= menu_run(m
);
223 static bool dithering_enable(void)
225 return set_bool_options(str(LANG_DITHERING
),
226 &global_settings
.dithering_enabled
,
227 STR(LANG_SET_BOOL_YES
),
228 STR(LANG_SET_BOOL_NO
),
233 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
234 static bool loudness(void)
236 return set_sound(str(LANG_LOUDNESS
), &global_settings
.loudness
,
240 static bool mdb_strength(void)
242 return set_sound(str(LANG_MDB_STRENGTH
), &global_settings
.mdb_strength
,
246 static bool mdb_harmonics(void)
248 return set_sound(str(LANG_MDB_HARMONICS
), &global_settings
.mdb_harmonics
,
249 SOUND_MDB_HARMONICS
);
252 static bool mdb_center(void)
254 return set_sound(str(LANG_MDB_CENTER
), &global_settings
.mdb_center
,
258 static bool mdb_shape(void)
260 return set_sound(str(LANG_MDB_SHAPE
), &global_settings
.mdb_shape
,
264 static void set_mdb_enable(bool value
)
266 sound_set_mdb_enable((int)value
);
269 static bool mdb_enable(void)
271 return set_bool_options(str(LANG_MDB_ENABLE
),
272 &global_settings
.mdb_enable
,
273 STR(LANG_SET_BOOL_YES
),
274 STR(LANG_SET_BOOL_NO
),
278 static void set_superbass(bool value
)
280 sound_set_superbass((int)value
);
283 static bool superbass(void)
285 return set_bool_options(str(LANG_SUPERBASS
),
286 &global_settings
.superbass
,
287 STR(LANG_SET_BOOL_YES
),
288 STR(LANG_SET_BOOL_NO
),
292 static bool avc(void)
294 static const struct opt_items names
[] = {
296 { "20ms", TALK_ID(20, UNIT_MS
) },
297 { "2s", TALK_ID(2, UNIT_SEC
) },
298 { "4s", TALK_ID(4, UNIT_SEC
) },
299 { "8s", TALK_ID(8, UNIT_SEC
) }
301 return set_option(str(LANG_DECAY
), &global_settings
.avc
, INT
,
302 names
, 5, sound_set_avc
);
306 #ifdef HAVE_RECORDING
307 static bool recsource(void)
309 int n_opts
= AUDIO_NUM_SOURCES
;
311 struct opt_items names
[AUDIO_NUM_SOURCES
] = {
312 { STR(LANG_RECORDING_SRC_MIC
) },
313 { STR(LANG_RECORDING_SRC_LINE
) },
315 { STR(LANG_RECORDING_SRC_DIGITAL
) },
319 /* caveat: assumes it's the last item! */
320 #ifdef HAVE_FMRADIO_IN
321 if (radio_hardware_present())
323 names
[AUDIO_SRC_FMRADIO
].string
= ID2P(LANG_FM_RADIO
);
324 names
[AUDIO_SRC_FMRADIO
].voice_id
= LANG_FM_RADIO
;
330 return set_option(str(LANG_RECORDING_SOURCE
),
331 &global_settings
.rec_source
, INT
, names
,
335 /* To be removed when we add support for sample rates and channel settings */
336 #if CONFIG_CODEC == SWCODEC
337 static bool recquality(void)
339 static const struct opt_items names
[] = {
340 { "MP3 64 kBit/s", TALK_ID( 64, UNIT_KBIT
) },
341 { "MP3 96 kBit/s", TALK_ID( 96, UNIT_KBIT
) },
342 { "MP3 128 kBit/s", TALK_ID( 128, UNIT_KBIT
) },
343 { "MP3 160 kBit/s", TALK_ID( 160, UNIT_KBIT
) },
344 { "MP3 192 kBit/s", TALK_ID( 192, UNIT_KBIT
) },
345 { "MP3 224 kBit/s", TALK_ID( 224, UNIT_KBIT
) },
346 { "MP3 320 kBit/s", TALK_ID( 320, UNIT_KBIT
) },
347 { "WV 900 kBit/s", TALK_ID( 900, UNIT_KBIT
) },
348 { "WAV 1411 kBit/s", TALK_ID(1411, UNIT_KBIT
) }
351 return set_option(str(LANG_RECORDING_QUALITY
),
352 &global_settings
.rec_quality
, INT
,
353 names
, sizeof (names
)/sizeof(struct opt_items
),
356 #elif CONFIG_CODEC == MAS3587F
357 static bool recquality(void)
359 return set_int(str(LANG_RECORDING_QUALITY
), "", UNIT_INT
,
360 &global_settings
.rec_quality
,
361 NULL
, 1, 0, 7, NULL
);
364 static bool receditable(void)
366 return set_bool(str(LANG_RECORDING_EDITABLE
),
367 &global_settings
.rec_editable
);
369 #endif /* CONFIG_CODEC == MAS3587F */
371 static bool recfrequency(void)
373 static const struct opt_items names
[] = {
374 { "44.1kHz", TALK_ID(44, UNIT_KHZ
) },
375 #if CONFIG_CODEC != SWCODEC /* This is temporary */
376 { "48kHz", TALK_ID(48, UNIT_KHZ
) },
377 { "32kHz", TALK_ID(32, UNIT_KHZ
) },
378 { "22.05kHz", TALK_ID(22, UNIT_KHZ
) },
379 { "24kHz", TALK_ID(24, UNIT_KHZ
) },
380 { "16kHz", TALK_ID(16, UNIT_KHZ
) }
383 return set_option(str(LANG_RECORDING_FREQUENCY
),
384 &global_settings
.rec_frequency
, INT
,
385 names
, sizeof(names
)/sizeof(*names
), NULL
);
388 static bool recchannels(void)
390 static const struct opt_items names
[] = {
391 { STR(LANG_CHANNEL_STEREO
) },
392 { STR(LANG_CHANNEL_MONO
) }
394 return set_option(str(LANG_RECORDING_CHANNELS
),
395 &global_settings
.rec_channels
, INT
,
399 static bool rectimesplit(void)
401 static const struct opt_items names
[] = {
403 { "00:05" , TALK_ID(5, UNIT_MIN
) },
404 { "00:10" , TALK_ID(10, UNIT_MIN
) },
405 { "00:15" , TALK_ID(15, UNIT_MIN
) },
406 { "00:30" , TALK_ID(30, UNIT_MIN
) },
407 { "01:00" , TALK_ID(1, UNIT_HOUR
) },
408 { "01:14" , TALK_ID(74, UNIT_MIN
) },
409 { "01:20" , TALK_ID(80, UNIT_MIN
) },
410 { "02:00" , TALK_ID(2, UNIT_HOUR
) },
411 { "04:00" , TALK_ID(4, UNIT_HOUR
) },
412 { "06:00" , TALK_ID(6, UNIT_HOUR
) },
413 { "08:00" , TALK_ID(8, UNIT_HOUR
) },
414 { "10:00" , TALK_ID(10, UNIT_HOUR
) },
415 { "12:00" , TALK_ID(12, UNIT_HOUR
) },
416 { "18:00" , TALK_ID(18, UNIT_HOUR
) },
417 { "24:00" , TALK_ID(24, UNIT_HOUR
) }
419 return set_option(str(LANG_SPLIT_TIME
),
420 &global_settings
.rec_timesplit
, INT
,
424 static bool recsizesplit(void)
426 static const struct opt_items names
[] = {
428 { "5MB" , TALK_ID(5, UNIT_MB
) },
429 { "10MB" , TALK_ID(10, UNIT_MB
) },
430 { "15MB" , TALK_ID(15, UNIT_MB
) },
431 { "32MB" , TALK_ID(32, UNIT_MB
) },
432 { "64MB" , TALK_ID(64, UNIT_MB
) },
433 { "75MB" , TALK_ID(75, UNIT_MB
) },
434 { "100MB" , TALK_ID(100, UNIT_MB
) },
435 { "128MB" , TALK_ID(128, UNIT_MB
) },
436 { "256MB" , TALK_ID(256, UNIT_MB
) },
437 { "512MB" , TALK_ID(512, UNIT_MB
) },
438 { "650MB" , TALK_ID(650, UNIT_MB
) },
439 { "700MB" , TALK_ID(700, UNIT_MB
) },
440 { "1GB" , TALK_ID(1024, UNIT_MB
) },
441 { "1.5GB" , TALK_ID(1536, UNIT_MB
) },
442 { "1.75GB" , TALK_ID(1792, UNIT_MB
) }
444 return set_option(str(LANG_SPLIT_SIZE
),
445 &global_settings
.rec_sizesplit
, INT
,
449 static bool splitmethod(void)
451 static const struct opt_items names
[] = {
452 { STR(LANG_REC_TIME
) },
453 { STR(LANG_REC_SIZE
) },
456 ret
=set_option( str(LANG_SPLIT_MEASURE
),
457 &global_settings
.rec_split_method
, INT
, names
, 2, NULL
);
461 static bool splittype(void)
463 static const struct opt_items names
[] = {
464 { STR(LANG_START_NEW_FILE
) },
465 { STR(LANG_STOP_RECORDING
) },
468 ret
=set_option( str(LANG_SPLIT_TYPE
),
469 &global_settings
.rec_split_type
, INT
, names
, 2, NULL
);
473 static bool filesplitoptionsmenu(void)
478 static const struct menu_item items
[] = {
479 { ID2P(LANG_SPLIT_MEASURE
), splitmethod
},
480 { ID2P(LANG_SPLIT_TYPE
), splittype
},
481 { ID2P(LANG_SPLIT_TIME
), rectimesplit
},
482 { ID2P(LANG_SPLIT_SIZE
), recsizesplit
}
484 m
=menu_init( items
, sizeof(items
) / sizeof(*items
), NULL
,
486 result
= menu_run(m
);
490 static bool recprerecord(void)
492 static const struct opt_items names
[] = {
494 { "1s", TALK_ID(1, UNIT_SEC
) },
495 { "2s", TALK_ID(2, UNIT_SEC
) },
496 { "3s", TALK_ID(3, UNIT_SEC
) },
497 { "4s", TALK_ID(4, UNIT_SEC
) },
498 { "5s", TALK_ID(5, UNIT_SEC
) },
499 { "6s", TALK_ID(6, UNIT_SEC
) },
500 { "7s", TALK_ID(7, UNIT_SEC
) },
501 { "8s", TALK_ID(8, UNIT_SEC
) },
502 { "9s", TALK_ID(9, UNIT_SEC
) },
503 { "10s", TALK_ID(10, UNIT_SEC
) },
504 { "11s", TALK_ID(11, UNIT_SEC
) },
505 { "12s", TALK_ID(12, UNIT_SEC
) },
506 { "13s", TALK_ID(13, UNIT_SEC
) },
507 { "14s", TALK_ID(14, UNIT_SEC
) },
508 { "15s", TALK_ID(15, UNIT_SEC
) },
509 { "16s", TALK_ID(16, UNIT_SEC
) },
510 { "17s", TALK_ID(17, UNIT_SEC
) },
511 { "18s", TALK_ID(18, UNIT_SEC
) },
512 { "19s", TALK_ID(19, UNIT_SEC
) },
513 { "20s", TALK_ID(20, UNIT_SEC
) },
514 { "21s", TALK_ID(21, UNIT_SEC
) },
515 { "22s", TALK_ID(22, UNIT_SEC
) },
516 { "23s", TALK_ID(23, UNIT_SEC
) },
517 { "24s", TALK_ID(24, UNIT_SEC
) },
518 { "25s", TALK_ID(25, UNIT_SEC
) },
519 { "26s", TALK_ID(26, UNIT_SEC
) },
520 { "27s", TALK_ID(27, UNIT_SEC
) },
521 { "28s", TALK_ID(28, UNIT_SEC
) },
522 { "29s", TALK_ID(29, UNIT_SEC
) },
523 { "30s", TALK_ID(30, UNIT_SEC
) }
525 return set_option(str(LANG_RECORD_PRERECORD_TIME
),
526 &global_settings
.rec_prerecord_time
, INT
,
530 static bool recdirectory(void)
532 static const struct opt_items names
[] = {
533 { rec_base_directory
, -1 },
534 { STR(LANG_RECORD_CURRENT_DIR
) }
536 return set_option(str(LANG_RECORD_DIRECTORY
),
537 &global_settings
.rec_directory
, INT
,
541 static bool reconstartup(void)
543 return set_bool(str(LANG_RECORD_STARTUP
),
544 &global_settings
.rec_startup
);
547 #ifdef CONFIG_BACKLIGHT
548 static bool cliplight(void)
550 static const struct opt_items names
[] = {
552 { STR(LANG_MAIN_UNIT
) }
553 #ifdef HAVE_REMOTE_LCD
554 , { STR(LANG_REMOTE_MAIN
) },
555 { STR(LANG_REMOTE_UNIT
) }
559 return set_option( str(LANG_CLIP_LIGHT
),
560 &global_settings
.cliplight
, INT
, names
,
561 #ifdef HAVE_REMOTE_LCD
567 #endif /*CONFIG_BACKLIGHT */
570 static bool agc_preset(void)
572 static const struct opt_items names
[] = {
574 { STR(LANG_AGC_SAFETY
) },
575 { STR(LANG_AGC_LIVE
) },
576 { STR(LANG_AGC_DJSET
) },
577 { STR(LANG_AGC_MEDIUM
) },
578 { STR(LANG_AGC_VOICE
) },
580 if (global_settings
.rec_source
)
581 return set_option(str(LANG_RECORD_AGC_PRESET
),
582 &global_settings
.rec_agc_preset_line
,
583 INT
, names
, 6, NULL
);
585 return set_option(str(LANG_RECORD_AGC_PRESET
),
586 &global_settings
.rec_agc_preset_mic
,
587 INT
, names
, 6, NULL
);
590 static bool agc_cliptime(void)
592 static const struct opt_items names
[] = {
593 { "200ms", TALK_ID(200, UNIT_MS
) },
594 { "400ms", TALK_ID(400, UNIT_MS
) },
595 { "600ms", TALK_ID(600, UNIT_MS
) },
596 { "800ms", TALK_ID(800, UNIT_MS
) },
597 { "1s", TALK_ID(1, UNIT_SEC
) }
599 return set_option(str(LANG_RECORD_AGC_CLIPTIME
),
600 &global_settings
.rec_agc_cliptime
,
601 INT
, names
, 5, NULL
);
603 #endif /* HAVE_AGC */
604 #endif /* HAVE_RECORDING */
606 static bool chanconf(void)
608 static const struct opt_items names
[] = {
609 { STR(LANG_CHANNEL_STEREO
) },
610 { STR(LANG_CHANNEL_MONO
) },
611 { STR(LANG_CHANNEL_CUSTOM
) },
612 { STR(LANG_CHANNEL_LEFT
) },
613 { STR(LANG_CHANNEL_RIGHT
) },
614 { STR(LANG_CHANNEL_KARAOKE
) }
616 #if CONFIG_CODEC == SWCODEC
617 return set_option(str(LANG_CHANNEL
), &global_settings
.channel_config
, INT
,
618 names
, 6, channels_set
);
620 return set_option(str(LANG_CHANNEL
), &global_settings
.channel_config
, INT
,
621 names
, 6, sound_set_channels
);
625 static bool stereo_width(void)
627 return set_sound(str(LANG_STEREO_WIDTH
), &global_settings
.stereo_width
,
631 bool sound_menu(void)
635 static const struct menu_item items
[] = {
636 { ID2P(LANG_VOLUME
), volume
},
638 { ID2P(LANG_BASS
), bass
},
639 { ID2P(LANG_TREBLE
), treble
},
641 { ID2P(LANG_BALANCE
), balance
},
642 { ID2P(LANG_CHANNEL_MENU
), chanconf
},
643 { ID2P(LANG_STEREO_WIDTH
), stereo_width
},
644 #if CONFIG_CODEC == SWCODEC
645 { ID2P(LANG_CROSSFEED
), crossfeed_menu
},
646 { ID2P(LANG_EQUALIZER
), eq_menu
},
647 { ID2P(LANG_DITHERING
), dithering_enable
},
650 { ID2P(LANG_EQUALIZER_HARDWARE
), eq_hw_menu
},
652 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
653 { ID2P(LANG_LOUDNESS
), loudness
},
654 { ID2P(LANG_AUTOVOL
), avc
},
655 { ID2P(LANG_SUPERBASS
), superbass
},
656 { ID2P(LANG_MDB_ENABLE
), mdb_enable
},
657 { ID2P(LANG_MDB_STRENGTH
), mdb_strength
},
658 { ID2P(LANG_MDB_HARMONICS
), mdb_harmonics
},
659 { ID2P(LANG_MDB_CENTER
), mdb_center
},
660 { ID2P(LANG_MDB_SHAPE
), mdb_shape
},
664 #if CONFIG_CODEC == SWCODEC
665 pcmbuf_set_low_latency(true);
668 m
=menu_init( items
, sizeof(items
) / sizeof(*items
), NULL
,
670 result
= menu_run(m
);
673 #if CONFIG_CODEC == SWCODEC
674 pcmbuf_set_low_latency(false);
680 #ifdef HAVE_RECORDING
681 enum trigger_menu_option
693 #if !defined(SIMULATOR) && CONFIG_CODEC == MAS3587F
694 static char* create_thres_str(int threshold
)
696 static char retval
[6];
698 if (threshold
< -88) {
699 snprintf (retval
, sizeof retval
, "%s", str(LANG_DB_INF
));
701 snprintf (retval
, sizeof retval
, "%ddb", threshold
+ 1);
704 snprintf (retval
, sizeof retval
, "%d%%", threshold
);
710 static void change_threshold(int *threshold
, int change
)
712 if (global_settings
.peak_meter_dbfs
) {
713 if (*threshold
>= 0) {
714 int db
= (calc_db(*threshold
* MAX_PEAK
/ 100) - 9000) / 100;
717 *threshold
+= change
;
718 if (*threshold
> -1) {
720 } else if (*threshold
< INF_DB
) {
724 if (*threshold
< 0) {
725 *threshold
= peak_meter_db2sample(*threshold
* 100) * 100 / MAX_PEAK
;
727 *threshold
+= change
;
728 if (*threshold
> 100) {
730 } else if (*threshold
< 0) {
736 /* Variable button definitions */
737 #if CONFIG_KEYPAD == RECORDER_PAD
738 #define TRIG_CANCEL BUTTON_OFF
739 #define TRIG_ACCEPT BUTTON_PLAY
740 #define TRIG_RESET_SIM BUTTON_F2
742 #elif CONFIG_KEYPAD == ONDIO_PAD
743 #define TRIG_CANCEL BUTTON_OFF
744 #define TRIG_ACCEPT BUTTON_MENU
748 * Displays a menu for editing the trigger settings.
750 bool rectrigger(void)
752 int exit_request
= false;
753 enum trigger_menu_option selected
= TRIGGER_MODE
;
755 int old_x_margin
, old_y_margin
;
757 #define TRIGGER_MODE_COUNT 3
758 static const unsigned char *trigger_modes
[] = {
760 ID2P(LANG_RECORD_TRIG_NOREARM
),
761 ID2P(LANG_RECORD_TRIG_REARM
)
764 #define PRERECORD_TIMES_COUNT 31
765 static const unsigned char *prerecord_times
[] = {
766 ID2P(LANG_OFF
),"1s","2s", "3s", "4s", "5s", "6s", "7s", "8s", "9s",
767 "10s", "11s", "12s", "13s", "14s", "15s", "16s", "17s", "18s", "19s",
768 "20s", "21s", "22s", "23s", "24s", "25s", "26s", "27s", "28s", "29s",
772 static const unsigned char *option_name
[] = {
773 [TRIGGER_MODE
] = ID2P(LANG_RECORD_TRIGGER_MODE
),
774 [PRERECORD_TIME
] = ID2P(LANG_RECORD_PRERECORD_TIME
),
775 [START_THRESHOLD
] = ID2P(LANG_RECORD_START_THRESHOLD
),
776 [START_DURATION
] = ID2P(LANG_RECORD_MIN_DURATION
),
777 [STOP_THRESHOLD
] = ID2P(LANG_RECORD_STOP_THRESHOLD
),
778 [STOP_POSTREC
] = ID2P(LANG_RECORD_STOP_POSTREC
),
779 [STOP_GAP
] = ID2P(LANG_RECORD_STOP_GAP
)
782 int old_start_thres
= global_settings
.rec_start_thres
;
783 int old_start_duration
= global_settings
.rec_start_duration
;
784 int old_prerecord_time
= global_settings
.rec_prerecord_time
;
785 int old_stop_thres
= global_settings
.rec_stop_thres
;
786 int old_stop_postrec
= global_settings
.rec_stop_postrec
;
787 int old_stop_gap
= global_settings
.rec_stop_gap
;
788 int old_trigger_mode
= global_settings
.rec_trigger_mode
;
793 int stat_height
= global_settings
.statusbar
? STATUSBAR_HEIGHT
: 0;
794 /* array for y ordinate of peak_meter_draw_get_button
795 function in peakmeter.c*/
796 int pm_y
[NB_SCREENS
];
798 /* restart trigger with new values */
799 settings_apply_trigger();
800 peak_meter_trigger (global_settings
.rec_trigger_mode
!= TRIG_MODE_OFF
);
804 old_x_margin
= lcd_getxmargin();
805 old_y_margin
= lcd_getymargin();
806 if(global_settings
.statusbar
)
807 lcd_setmargins(0, STATUSBAR_HEIGHT
);
809 lcd_setmargins(0, 0);
811 lcd_getstringsize("M", &w
, &h
);
813 /* 16 pixels are reserved for peak meter and trigger status */
814 option_lines
= (LCD_HEIGHT
- 16 - stat_height
) / h
;
816 while (!exit_request
) {
819 char option_value
[TRIG_OPTION_COUNT
][7];
822 option_value
[TRIGGER_MODE
],
823 sizeof option_value
[TRIGGER_MODE
],
825 P2STR(trigger_modes
[global_settings
.rec_trigger_mode
]));
828 option_value
[PRERECORD_TIME
],
829 sizeof option_value
[PRERECORD_TIME
],
831 P2STR(prerecord_times
[global_settings
.rec_prerecord_time
]));
833 /* due to value range shift (peak_meter_define_trigger) -1 is 0db */
834 if (global_settings
.rec_start_thres
== -1) {
837 str
= create_thres_str(global_settings
.rec_start_thres
);
840 option_value
[START_THRESHOLD
],
841 sizeof option_value
[START_THRESHOLD
],
846 option_value
[START_DURATION
],
847 sizeof option_value
[START_DURATION
],
849 trig_durations
[global_settings
.rec_start_duration
]);
852 if (global_settings
.rec_stop_thres
<= INF_DB
) {
855 str
= create_thres_str(global_settings
.rec_stop_thres
);
858 option_value
[STOP_THRESHOLD
],
859 sizeof option_value
[STOP_THRESHOLD
],
864 option_value
[STOP_POSTREC
],
865 sizeof option_value
[STOP_POSTREC
],
867 trig_durations
[global_settings
.rec_stop_postrec
]);
870 option_value
[STOP_GAP
],
871 sizeof option_value
[STOP_GAP
],
873 trig_durations
[global_settings
.rec_stop_gap
]);
875 gui_syncstatusbar_draw(&statusbars
, true);
877 /* reselect FONT_SYSFONT as status_draw has changed the font */
878 /*lcd_setfont(FONT_SYSFIXED);*/
880 for (i
= 0; i
< option_lines
; i
++) {
883 str
= P2STR(option_name
[i
+ offset
]);
884 lcd_putsxy(5, stat_height
+ i
* h
, str
);
886 str
= option_value
[i
+ offset
];
887 lcd_getstringsize(str
, &w
, NULL
);
888 y
= stat_height
+ i
* h
;
890 lcd_putsxy(x
, y
, str
);
891 if ((int)selected
== (i
+ offset
)) {
892 lcd_set_drawmode(DRMODE_COMPLEMENT
);
893 lcd_fillrect(x
, y
, w
, h
);
894 lcd_set_drawmode(DRMODE_SOLID
);
898 scrollbar(0, stat_height
,
900 TRIG_OPTION_COUNT
, offset
, offset
+ option_lines
,
903 peak_meter_draw_trig(0, LCD_HEIGHT
- 8 - TRIG_HEIGHT
);
906 pm_y
[i
] = screens
[i
].height
- 8;
907 button
= peak_meter_draw_get_btn(0, pm_y
, 8, NB_SCREENS
);
912 case ACTION_STD_CANCEL
:
913 gui_syncsplash(50, true, str(LANG_MENU_SETTING_CANCEL
));
914 global_settings
.rec_start_thres
= old_start_thres
;
915 global_settings
.rec_start_duration
= old_start_duration
;
916 global_settings
.rec_prerecord_time
= old_prerecord_time
;
917 global_settings
.rec_stop_thres
= old_stop_thres
;
918 global_settings
.rec_stop_postrec
= old_stop_postrec
;
919 global_settings
.rec_stop_gap
= old_stop_gap
;
920 global_settings
.rec_trigger_mode
= old_trigger_mode
;
924 case ACTION_REC_PAUSE
:
928 case ACTION_STD_PREV
:
929 selected
+= TRIG_OPTION_COUNT
- 1;
930 selected
%= TRIG_OPTION_COUNT
;
931 offset
= MIN(offset
, (int)selected
);
932 offset
= MAX(offset
, (int)selected
- option_lines
+ 1);
935 case ACTION_STD_NEXT
:
937 selected
%= TRIG_OPTION_COUNT
;
938 offset
= MIN(offset
, (int)selected
);
939 offset
= MAX(offset
, (int)selected
- option_lines
+ 1);
942 case ACTION_SETTINGS_INC
:
945 global_settings
.rec_trigger_mode
++;
946 global_settings
.rec_trigger_mode
%= TRIGGER_MODE_COUNT
;
950 global_settings
.rec_prerecord_time
++;
951 global_settings
.rec_prerecord_time
%= PRERECORD_TIMES_COUNT
;
954 case START_THRESHOLD
:
955 change_threshold(&global_settings
.rec_start_thres
, 1);
959 global_settings
.rec_start_duration
++;
960 global_settings
.rec_start_duration
%= TRIG_DURATION_COUNT
;
964 change_threshold(&global_settings
.rec_stop_thres
, 1);
968 global_settings
.rec_stop_postrec
++;
969 global_settings
.rec_stop_postrec
%= TRIG_DURATION_COUNT
;
973 global_settings
.rec_stop_gap
++;
974 global_settings
.rec_stop_gap
%= TRIG_DURATION_COUNT
;
977 case TRIG_OPTION_COUNT
:
978 // avoid compiler warnings
981 peak_meter_trigger(global_settings
.rec_trigger_mode
!=TRIG_OFF
);
982 settings_apply_trigger();
985 case ACTION_SETTINGS_DEC
:
988 global_settings
.rec_trigger_mode
+=TRIGGER_MODE_COUNT
-1;
989 global_settings
.rec_trigger_mode
%= TRIGGER_MODE_COUNT
;
993 global_settings
.rec_prerecord_time
+= PRERECORD_TIMES_COUNT
- 1;
994 global_settings
.rec_prerecord_time
%= PRERECORD_TIMES_COUNT
;
997 case START_THRESHOLD
:
998 change_threshold(&global_settings
.rec_start_thres
, -1);
1001 case START_DURATION
:
1002 global_settings
.rec_start_duration
+= TRIG_DURATION_COUNT
-1;
1003 global_settings
.rec_start_duration
%= TRIG_DURATION_COUNT
;
1006 case STOP_THRESHOLD
:
1007 change_threshold(&global_settings
.rec_stop_thres
, -1);
1011 global_settings
.rec_stop_postrec
+=
1012 TRIG_DURATION_COUNT
- 1;
1013 global_settings
.rec_stop_postrec
%=
1014 TRIG_DURATION_COUNT
;
1018 global_settings
.rec_stop_gap
+=
1019 TRIG_DURATION_COUNT
- 1;
1020 global_settings
.rec_stop_gap
%= TRIG_DURATION_COUNT
;
1023 case TRIG_OPTION_COUNT
:
1024 // avoid compiler warnings
1027 peak_meter_trigger(global_settings
.rec_trigger_mode
!=TRIG_OFF
);
1028 settings_apply_trigger();
1031 #ifdef TRIG_RESET_SIM
1033 peak_meter_trigger(true);
1037 case SYS_USB_CONNECTED
:
1038 if(default_event_handler(button
) == SYS_USB_CONNECTED
) {
1040 exit_request
= true;
1046 peak_meter_trigger(false);
1047 lcd_setfont(FONT_UI
);
1048 lcd_setmargins(old_x_margin
, old_y_margin
);
1049 action_signalscreenchange();
1054 bool recording_menu(bool no_source
)
1058 struct menu_item items
[13];
1061 #if CONFIG_CODEC == MAS3587F || CONFIG_CODEC == SWCODEC
1062 items
[i
].desc
= ID2P(LANG_RECORDING_QUALITY
);
1063 items
[i
++].function
= recquality
;
1065 items
[i
].desc
= ID2P(LANG_RECORDING_FREQUENCY
);
1066 items
[i
++].function
= recfrequency
;
1068 items
[i
].desc
= ID2P(LANG_RECORDING_SOURCE
);
1069 items
[i
++].function
= recsource
;
1071 items
[i
].desc
= ID2P(LANG_RECORDING_CHANNELS
);
1072 items
[i
++].function
= recchannels
;
1073 #if CONFIG_CODEC == MAS3587F
1074 items
[i
].desc
= ID2P(LANG_RECORDING_EDITABLE
);
1075 items
[i
++].function
= receditable
;
1077 items
[i
].desc
= ID2P(LANG_RECORD_TIMESPLIT
);
1078 items
[i
++].function
= filesplitoptionsmenu
;
1079 items
[i
].desc
= ID2P(LANG_RECORD_PRERECORD_TIME
);
1080 items
[i
++].function
= recprerecord
;
1081 items
[i
].desc
= ID2P(LANG_RECORD_DIRECTORY
);
1082 items
[i
++].function
= recdirectory
;
1083 items
[i
].desc
= ID2P(LANG_RECORD_STARTUP
);
1084 items
[i
++].function
= reconstartup
;
1085 #ifdef CONFIG_BACKLIGHT
1086 items
[i
].desc
= ID2P(LANG_CLIP_LIGHT
);
1087 items
[i
++].function
= cliplight
;
1089 #if !defined(SIMULATOR) && CONFIG_CODEC == MAS3587F
1090 items
[i
].desc
= ID2P(LANG_RECORD_TRIGGER
);
1091 items
[i
++].function
= rectrigger
;
1094 items
[i
].desc
= ID2P(LANG_RECORD_AGC_PRESET
);
1095 items
[i
++].function
= agc_preset
;
1096 items
[i
].desc
= ID2P(LANG_RECORD_AGC_CLIPTIME
);
1097 items
[i
++].function
= agc_cliptime
;
1100 m
=menu_init( items
, i
, NULL
, NULL
, NULL
, NULL
);
1101 result
= menu_run(m
);