Allow recording source to be set from recording context menu. Not a very nice solutio...
[Rockbox.git] / apps / menus / recording_menu.c
blobe2be128d2dfda70cf88a768f353328ebaf5ae8fc
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 Jonathan Gordon
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 ****************************************************************************/
20 #include "config.h"
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdbool.h>
24 #include "string.h"
25 #include "system.h"
26 #include "kernel.h"
27 #include "lcd.h"
28 #include "menu.h"
29 #include "button.h"
30 #include "mp3_playback.h"
31 #include "settings.h"
32 #include "statusbar.h"
33 #include "screens.h"
34 #include "icons.h"
35 #ifdef HAVE_LCD_BITMAP
36 #include "font.h"
37 #include "scrollbar.h"
38 #endif
39 #include "lang.h"
40 #include "sprintf.h"
41 #include "talk.h"
42 #include "misc.h"
43 #include "sound.h"
44 #ifdef HAVE_RECORDING
45 #include "audio.h"
46 #if CONFIG_TUNER
47 #include "radio.h"
48 #endif
49 #endif
50 #ifdef HAVE_RECORDING
51 #include "peakmeter.h"
52 #include "mas.h"
53 #endif
54 #include "splash.h"
55 #if CONFIG_CODEC == SWCODEC
56 #include "dsp.h"
57 #include "menus/eq_menu.h"
58 #include "pcmbuf.h"
59 #ifdef HAVE_RECORDING
60 #include "enc_config.h"
61 #endif
62 #include "general.h"
63 #endif
64 #include "action.h"
65 #include "recording.h"
68 static bool no_source_in_menu = false;
69 int recmenu_callback(int action,const struct menu_item_ex *this_item);
71 static int recsource_func(void)
73 int n_opts = REC_NUM_SOURCES;
75 static const struct opt_items names[AUDIO_NUM_SOURCES] = {
76 HAVE_MIC_REC_([AUDIO_SRC_MIC]
77 = { STR(LANG_RECORDING_SRC_MIC) },)
78 HAVE_LINE_REC_([AUDIO_SRC_LINEIN]
79 = { STR(LANG_LINE_IN) },)
80 HAVE_SPDIF_REC_([AUDIO_SRC_SPDIF]
81 = { STR(LANG_RECORDING_SRC_DIGITAL) },)
82 HAVE_FMRADIO_REC_([AUDIO_SRC_FMRADIO]
83 = { STR(LANG_FM_RADIO) },)
86 /* caveat: assumes it's the last item! */
87 #ifdef HAVE_FMRADIO_REC
88 if (!radio_hardware_present())
89 n_opts--;
90 #endif
92 return set_option(str(LANG_RECORDING_SOURCE),
93 &global_settings.rec_source, INT, names,
94 n_opts, NULL );
96 MENUITEM_FUNCTION(recsource, 0, ID2P(LANG_RECORDING_SOURCE),
97 recsource_func, NULL, recmenu_callback, Icon_Menu_setting);
99 #if CONFIG_CODEC == SWCODEC
100 /* Makes an options list from a source list of options and indexes */
101 static void make_options_from_indexes(const struct opt_items *src_names,
102 const long *src_indexes,
103 int n_indexes,
104 struct opt_items *dst_names)
106 while (--n_indexes >= 0)
107 dst_names[n_indexes] = src_names[src_indexes[n_indexes]];
108 } /* make_options_from_indexes */
111 #endif /* CONFIG_CODEC == SWCODEC */
113 static int recfrequency_func(void)
115 #if CONFIG_CODEC == MAS3587F
116 static const struct opt_items names[6] = {
117 { "44.1kHz", TALK_ID(44, UNIT_KHZ) },
118 { "48kHz", TALK_ID(48, UNIT_KHZ) },
119 { "32kHz", TALK_ID(32, UNIT_KHZ) },
120 { "22.05kHz", TALK_ID(22, UNIT_KHZ) },
121 { "24kHz", TALK_ID(24, UNIT_KHZ) },
122 { "16kHz", TALK_ID(16, UNIT_KHZ) }
124 return set_option(str(LANG_RECORDING_FREQUENCY),
125 &global_settings.rec_frequency, INT,
126 names, 6, NULL );
127 #endif /* CONFIG_CODEC == MAS3587F */
129 #if CONFIG_CODEC == SWCODEC
130 static const struct opt_items names[REC_NUM_FREQ] = {
131 REC_HAVE_96_([REC_FREQ_96] = { "96kHz", TALK_ID(96, UNIT_KHZ) },)
132 REC_HAVE_88_([REC_FREQ_88] = { "88.2kHz", TALK_ID(88, UNIT_KHZ) },)
133 REC_HAVE_64_([REC_FREQ_64] = { "64kHz", TALK_ID(64, UNIT_KHZ) },)
134 REC_HAVE_48_([REC_FREQ_48] = { "48kHz", TALK_ID(48, UNIT_KHZ) },)
135 REC_HAVE_44_([REC_FREQ_44] = { "44.1kHz", TALK_ID(44, UNIT_KHZ) },)
136 REC_HAVE_32_([REC_FREQ_32] = { "32kHz", TALK_ID(32, UNIT_KHZ) },)
137 REC_HAVE_24_([REC_FREQ_24] = { "24kHz", TALK_ID(24, UNIT_KHZ) },)
138 REC_HAVE_22_([REC_FREQ_22] = { "22.05kHz", TALK_ID(22, UNIT_KHZ) },)
139 REC_HAVE_16_([REC_FREQ_16] = { "16kHz", TALK_ID(16, UNIT_KHZ) },)
140 REC_HAVE_12_([REC_FREQ_12] = { "12kHz", TALK_ID(12, UNIT_KHZ) },)
141 REC_HAVE_11_([REC_FREQ_11] = { "11.025kHz", TALK_ID(11, UNIT_KHZ) },)
142 REC_HAVE_8_( [REC_FREQ_8 ] = { "8kHz", TALK_ID( 8, UNIT_KHZ) },)
145 struct opt_items opts[REC_NUM_FREQ];
146 unsigned long table[REC_NUM_FREQ];
147 int n_opts;
148 int rec_frequency;
149 bool ret;
151 #ifdef HAVE_SPDIF_REC
152 if (global_settings.rec_source == REC_SRC_SPDIF)
154 /* Inform user that frequency follows the source's frequency */
155 opts[0].string = ID2P(LANG_SOURCE_FREQUENCY);
156 opts[0].voice_id = LANG_SOURCE_FREQUENCY;
157 n_opts = 1;
158 rec_frequency = 0;
160 else
161 #endif
163 struct encoder_caps caps;
164 struct encoder_config cfg;
166 cfg.rec_format = global_settings.rec_format;
167 global_to_encoder_config(&cfg);
169 if (!enc_get_caps(&cfg, &caps, true))
170 return false;
172 /* Construct samplerate menu based upon encoder settings */
173 n_opts = make_list_from_caps32(REC_SAMPR_CAPS, NULL,
174 caps.samplerate_caps, table);
176 if (n_opts == 0)
177 return false; /* No common flags...?? */
179 make_options_from_indexes(names, table, n_opts, opts);
181 /* Find closest rate that the potentially restricted list
182 comes to */
183 make_list_from_caps32(REC_SAMPR_CAPS, rec_freq_sampr,
184 caps.samplerate_caps, table);
186 rec_frequency = round_value_to_list32(
187 rec_freq_sampr[global_settings.rec_frequency],
188 table, n_opts, false);
191 ret = set_option(str(LANG_RECORDING_FREQUENCY),
192 &rec_frequency, INT, opts, n_opts, NULL );
194 if (!ret
195 HAVE_SPDIF_REC_( && global_settings.rec_source != REC_SRC_SPDIF)
198 /* Translate back to full index */
199 global_settings.rec_frequency =
200 round_value_to_list32(table[rec_frequency],
201 rec_freq_sampr,
202 REC_NUM_FREQ,
203 false);
206 return ret;
207 #endif /* CONFIG_CODEC == SWCODEC */
208 } /* recfrequency */
209 MENUITEM_FUNCTION(recfrequency, 0, ID2P(LANG_RECORDING_FREQUENCY),
210 recfrequency_func, NULL, NULL, Icon_Menu_setting);
213 static int recchannels_func(void)
215 static const struct opt_items names[CHN_NUM_MODES] = {
216 [CHN_MODE_STEREO] = { STR(LANG_CHANNEL_STEREO) },
217 [CHN_MODE_MONO] = { STR(LANG_CHANNEL_MONO) }
219 #if CONFIG_CODEC == MAS3587F
220 return set_option(str(LANG_CHANNELS),
221 &global_settings.rec_channels, INT,
222 names, CHN_NUM_MODES, NULL );
223 #endif /* CONFIG_CODEC == MAS3587F */
225 #if CONFIG_CODEC == SWCODEC
226 struct opt_items opts[CHN_NUM_MODES];
227 long table[CHN_NUM_MODES];
228 struct encoder_caps caps;
229 struct encoder_config cfg;
230 int n_opts;
231 int rec_channels;
232 bool ret;
234 cfg.rec_format = global_settings.rec_format;
235 global_to_encoder_config(&cfg);
237 if (!enc_get_caps(&cfg, &caps, true))
238 return false;
240 n_opts = make_list_from_caps32(CHN_CAP_ALL, NULL,
241 caps.channel_caps, table);
243 rec_channels = round_value_to_list32(global_settings.rec_channels,
244 table, n_opts, false);
246 make_options_from_indexes(names, table, n_opts, opts);
248 ret = set_option(str(LANG_CHANNELS), &rec_channels,
249 INT, opts, n_opts, NULL );
251 if (!ret)
252 global_settings.rec_channels = table[rec_channels];
254 return ret;
255 #endif /* CONFIG_CODEC == SWCODEC */
257 MENUITEM_FUNCTION(recchannels, 0, ID2P(LANG_CHANNELS),
258 recchannels_func, NULL, NULL, Icon_Menu_setting);
260 #if CONFIG_CODEC == SWCODEC
262 static int recformat_func(void)
264 static const struct opt_items names[REC_NUM_FORMATS] = {
265 [REC_FORMAT_AIFF] = { STR(LANG_AFMT_AIFF) },
266 [REC_FORMAT_MPA_L3] = { STR(LANG_AFMT_MPA_L3) },
267 [REC_FORMAT_WAVPACK] = { STR(LANG_AFMT_WAVPACK) },
268 [REC_FORMAT_PCM_WAV] = { STR(LANG_AFMT_PCM_WAV) },
271 int rec_format = global_settings.rec_format;
272 bool res = set_option(str(LANG_RECORDING_FORMAT), &rec_format, INT,
273 names, REC_NUM_FORMATS, NULL );
275 if (rec_format != global_settings.rec_format)
277 global_settings.rec_format = rec_format;
278 enc_global_settings_apply();
281 return res;
282 } /* recformat */
283 MENUITEM_FUNCTION(recformat, 0, ID2P(LANG_RECORDING_FORMAT),
284 recformat_func, NULL, NULL, Icon_Menu_setting);
286 MENUITEM_FUNCTION(enc_global_config_menu_item, 0, ID2P(LANG_ENCODER_SETTINGS),
287 (int(*)(void))enc_global_config_menu,
288 NULL, NULL, Icon_Submenu);
290 #endif /* CONFIG_CODEC == SWCODEC */
293 int recmenu_callback(int action,const struct menu_item_ex *this_item)
295 switch (action)
297 case ACTION_REQUEST_MENUITEM:
298 if (this_item == &recsource && no_source_in_menu)
299 return ACTION_EXIT_MENUITEM;
300 break;
302 return action;
304 #if CONFIG_CODEC == MAS3587F
305 MENUITEM_SETTING(rec_quality, &global_settings.rec_quality, NULL);
306 MENUITEM_SETTING(rec_editable, &global_settings.rec_editable, NULL);
307 #endif
309 MENUITEM_SETTING(rec_split_type, &global_settings.rec_split_type, NULL);
310 MENUITEM_SETTING(rec_split_method, &global_settings.rec_split_method, NULL);
311 MENUITEM_SETTING(rec_timesplit, &global_settings.rec_timesplit, NULL);
312 MENUITEM_SETTING(rec_sizesplit, &global_settings.rec_sizesplit, NULL);
313 MAKE_MENU(filesplitoptionsmenu, ID2P(LANG_RECORD_TIMESPLIT), NULL, Icon_NOICON,
314 &rec_split_method, &rec_split_type, &rec_timesplit, &rec_sizesplit);
317 MENUITEM_SETTING(rec_prerecord_time, &global_settings.rec_prerecord_time, NULL);
319 static int clear_rec_directory(void)
321 strcpy(global_settings.rec_directory, REC_BASE_DIR);
322 gui_syncsplash(HZ, str(LANG_RESET_DONE_CLEAR));
323 return false;
325 MENUITEM_FUNCTION(clear_rec_directory_item, 0, ID2P(LANG_CLEAR_REC_DIR),
326 clear_rec_directory, NULL, NULL, Icon_Folder);
328 MENUITEM_SETTING(cliplight, &global_settings.cliplight, NULL);
330 #ifdef HAVE_AGC
331 static int agc_preset_func(void)
333 static const struct opt_items names[] = {
334 { STR(LANG_OFF) },
335 { STR(LANG_AGC_SAFETY) },
336 { STR(LANG_AGC_LIVE) },
337 { STR(LANG_AGC_DJSET) },
338 { STR(LANG_AGC_MEDIUM) },
339 { STR(LANG_AGC_VOICE) },
341 if (global_settings.rec_source)
342 return set_option(str(LANG_RECORD_AGC_PRESET),
343 &global_settings.rec_agc_preset_line,
344 INT, names, 6, NULL );
345 else
346 return set_option(str(LANG_RECORD_AGC_PRESET),
347 &global_settings.rec_agc_preset_mic,
348 INT, names, 6, NULL );
351 static int agc_cliptime_func(void)
353 static const struct opt_items names[] = {
354 { "200ms", TALK_ID(200, UNIT_MS) },
355 { "400ms", TALK_ID(400, UNIT_MS) },
356 { "600ms", TALK_ID(600, UNIT_MS) },
357 { "800ms", TALK_ID(800, UNIT_MS) },
358 { "1s", TALK_ID(1, UNIT_SEC) }
360 return set_option(str(LANG_RECORD_AGC_CLIPTIME),
361 &global_settings.rec_agc_cliptime,
362 INT, names, 5, NULL );
364 MENUITEM_FUNCTION(agc_preset, 0, ID2P(LANG_RECORD_AGC_PRESET),
365 agc_preset_func, NULL, NULL, Icon_Menu_setting);
366 MENUITEM_FUNCTION(agc_cliptime, 0, ID2P(LANG_RECORD_AGC_CLIPTIME),
367 agc_cliptime_func, NULL, NULL, Icon_Menu_setting);
368 #endif /* HAVE_AGC */
370 /** Rec trigger **/
371 enum trigger_menu_option
373 TRIGGER_MODE,
374 TRIGGER_TYPE,
375 PRERECORD_TIME,
376 START_THRESHOLD,
377 START_DURATION,
378 STOP_THRESHOLD,
379 STOP_POSTREC,
380 STOP_GAP,
381 TRIG_OPTION_COUNT,
384 static char* create_thres_str(int threshold)
386 static char retval[6];
387 if (threshold < 0) {
388 if (threshold < -88) {
389 snprintf (retval, sizeof retval, "%s", str(LANG_DB_INF));
390 } else {
391 snprintf (retval, sizeof retval, "%ddb", threshold + 1);
393 } else {
394 snprintf (retval, sizeof retval, "%d%%", threshold);
396 return retval;
399 #define INF_DB (-89)
400 static void change_threshold(int *threshold, int change)
402 if (global_settings.peak_meter_dbfs) {
403 if (*threshold >= 0) {
404 int db = (calc_db(*threshold * MAX_PEAK / 100) - 9000) / 100;
405 *threshold = db;
407 *threshold += change;
408 if (*threshold > -1) {
409 *threshold = INF_DB;
410 } else if (*threshold < INF_DB) {
411 *threshold = -1;
413 } else {
414 if (*threshold < 0) {
415 *threshold = peak_meter_db2sample(*threshold * 100) * 100 / MAX_PEAK;
417 *threshold += change;
418 if (*threshold > 100) {
419 *threshold = 0;
420 } else if (*threshold < 0) {
421 *threshold = 100;
427 * Displays a menu for editing the trigger settings.
429 bool rectrigger(void)
431 int exit_request = false;
432 enum trigger_menu_option selected = TRIGGER_MODE;
433 bool retval = false;
434 int old_x_margin[NB_SCREENS];
435 int old_y_margin[NB_SCREENS];
437 #define TRIGGER_MODE_COUNT 3
438 static const unsigned char *trigger_modes[] = {
439 ID2P(LANG_OFF),
440 ID2P(LANG_RECORD_TRIG_NOREARM),
441 ID2P(LANG_REPEAT)
444 #define PRERECORD_TIMES_COUNT 31
445 static const unsigned char *prerecord_times[] = {
446 ID2P(LANG_OFF),"1s","2s", "3s", "4s", "5s", "6s", "7s", "8s", "9s",
447 "10s", "11s", "12s", "13s", "14s", "15s", "16s", "17s", "18s", "19s",
448 "20s", "21s", "22s", "23s", "24s", "25s", "26s", "27s", "28s", "29s",
449 "30s"
452 #define TRIGGER_TYPE_COUNT 3
453 static const unsigned char *trigger_types[] = {
454 ID2P(LANG_RECORD_TRIGGER_STOP),
455 ID2P(LANG_PAUSE),
456 ID2P(LANG_RECORD_TRIGGER_NEWFILESTP),
459 static const unsigned char *option_name[] = {
460 [TRIGGER_MODE] = ID2P(LANG_RECORD_TRIGGER),
461 [TRIGGER_TYPE] = ID2P(LANG_RECORD_TRIGGER_TYPE),
462 [PRERECORD_TIME] = ID2P(LANG_RECORD_PRERECORD_TIME),
463 [START_THRESHOLD] = ID2P(LANG_RECORD_START_THRESHOLD),
464 [START_DURATION] = ID2P(LANG_MIN_DURATION),
465 [STOP_THRESHOLD] = ID2P(LANG_RECORD_STOP_THRESHOLD),
466 [STOP_POSTREC] = ID2P(LANG_MIN_DURATION),
467 [STOP_GAP] = ID2P(LANG_RECORD_STOP_GAP)
470 int old_start_thres = global_settings.rec_start_thres;
471 int old_start_duration = global_settings.rec_start_duration;
472 int old_prerecord_time = global_settings.rec_prerecord_time;
473 int old_stop_thres = global_settings.rec_stop_thres;
474 int old_stop_postrec = global_settings.rec_stop_postrec;
475 int old_stop_gap = global_settings.rec_stop_gap;
476 int old_trigger_mode = global_settings.rec_trigger_mode;
477 int old_trigger_type = global_settings.rec_trigger_type;
479 int offset[NB_SCREENS];
480 int option_lines[NB_SCREENS];
481 int w, h, i;
482 int stat_height = global_settings.statusbar ? STATUSBAR_HEIGHT : 0;
483 int pm_y[NB_SCREENS];
485 int trig_xpos[NB_SCREENS];
486 int trig_ypos[NB_SCREENS];
487 int trig_width[NB_SCREENS];
489 FOR_NB_SCREENS(i)
491 offset[i] = 0;
492 trig_xpos[i] = 0;
493 trig_ypos[i] = screens[i].height - stat_height - TRIG_HEIGHT;
494 pm_y[i] = screens[i].height - stat_height;
495 trig_width[i] = screens[i].width;
498 /* restart trigger with new values */
499 settings_apply_trigger();
500 peak_meter_trigger (global_settings.rec_trigger_mode != TRIG_MODE_OFF);
502 FOR_NB_SCREENS(i)
504 screens[i].clear_display();
506 old_x_margin[i] = screens[i].getxmargin();
507 old_y_margin[i] = screens[i].getymargin();
508 if(global_settings.statusbar)
509 screens[i].setmargins(0, STATUSBAR_HEIGHT);
510 else
511 screens[i].setmargins(0, 0);
513 screens[i].getstringsize("M", &w, &h);
515 // 16 pixels are reserved for peak meter and trigger status
516 option_lines[i] = MIN(((screens[i].height) -
517 stat_height - 16)/h,
518 TRIG_OPTION_COUNT);
521 while (!exit_request) {
522 int button, k;
523 const char *str;
524 char option_value[TRIG_OPTION_COUNT][16];
526 snprintf(
527 option_value[TRIGGER_MODE],
528 sizeof option_value[TRIGGER_MODE],
529 "%s",
530 P2STR(trigger_modes[global_settings.rec_trigger_mode]));
532 snprintf(
533 option_value[TRIGGER_TYPE],
534 sizeof option_value[TRIGGER_TYPE],
535 "%s",
536 P2STR(trigger_types[global_settings.rec_trigger_type]));
538 snprintf(
539 option_value[TRIGGER_TYPE],
540 sizeof option_value[TRIGGER_TYPE],
541 "%s",
542 P2STR(trigger_types[global_settings.rec_trigger_type]));
544 snprintf (
545 option_value[PRERECORD_TIME],
546 sizeof option_value[PRERECORD_TIME],
547 "%s",
548 P2STR(prerecord_times[global_settings.rec_prerecord_time]));
550 /* due to value range shift (peak_meter_define_trigger) -1 is 0db */
551 if (global_settings.rec_start_thres == -1) {
552 str = str(LANG_OFF);
553 } else {
554 str = create_thres_str(global_settings.rec_start_thres);
556 snprintf(
557 option_value[START_THRESHOLD],
558 sizeof option_value[START_THRESHOLD],
559 "%s",
560 str);
562 snprintf(
563 option_value[START_DURATION],
564 sizeof option_value[START_DURATION],
565 "%s",
566 trig_durations[global_settings.rec_start_duration]);
569 if (global_settings.rec_stop_thres <= INF_DB) {
570 str = str(LANG_OFF);
571 } else {
572 str = create_thres_str(global_settings.rec_stop_thres);
574 snprintf(
575 option_value[STOP_THRESHOLD],
576 sizeof option_value[STOP_THRESHOLD],
577 "%s",
578 str);
580 snprintf(
581 option_value[STOP_POSTREC],
582 sizeof option_value[STOP_POSTREC],
583 "%s",
584 trig_durations[global_settings.rec_stop_postrec]);
586 snprintf(
587 option_value[STOP_GAP],
588 sizeof option_value[STOP_GAP],
589 "%s",
590 trig_durations[global_settings.rec_stop_gap]);
592 FOR_NB_SCREENS(i)
594 screens[i].set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
595 screens[i].fillrect(0, stat_height, screens[i].width,
596 screens[i].height - stat_height);
597 screens[i].set_drawmode(DRMODE_SOLID);
600 gui_syncstatusbar_draw(&statusbars, true);
602 /* reselect FONT_SYSFONT as status_draw has changed the font */
603 /*lcd_setfont(FONT_SYSFIXED);*/
605 FOR_NB_SCREENS(i)
607 for (k = 0; k < option_lines[i]; k++) {
608 int x, y;
610 str = P2STR(option_name[k + offset[i]]);
611 screens[i].putsxy((option_lines[i] < TRIG_OPTION_COUNT) ? 5 : 0,
612 stat_height + k * h, str);
614 str = option_value[k + offset[i]];
615 screens[i].getstringsize(str, &w, &h);
616 y = stat_height + k * h;
617 x = screens[i].width - w;
618 screens[i].putsxy(x, y, str);
619 if ((int)selected == (k + offset[i])) {
620 screens[i].set_drawmode(DRMODE_COMPLEMENT);
621 screens[i].fillrect(x, y, w, h);
622 screens[i].set_drawmode(DRMODE_SOLID);
625 if (option_lines[i] < TRIG_OPTION_COUNT)
626 gui_scrollbar_draw(&screens[i], 0, stat_height,
627 4, screens[i].height - 16 - stat_height,
628 TRIG_OPTION_COUNT, offset[i], offset[i] + option_lines[i],
629 VERTICAL);
632 peak_meter_draw_trig(trig_xpos, trig_ypos, trig_width, NB_SCREENS);
633 button = peak_meter_draw_get_btn(0, pm_y, 8, NB_SCREENS);
635 FOR_NB_SCREENS(i)
636 screens[i].update();
638 switch (button) {
639 case ACTION_STD_CANCEL:
640 gui_syncsplash(50, str(LANG_CANCEL));
641 global_settings.rec_start_thres = old_start_thres;
642 global_settings.rec_start_duration = old_start_duration;
643 global_settings.rec_prerecord_time = old_prerecord_time;
644 global_settings.rec_stop_thres = old_stop_thres;
645 global_settings.rec_stop_postrec = old_stop_postrec;
646 global_settings.rec_stop_gap = old_stop_gap;
647 global_settings.rec_trigger_mode = old_trigger_mode;
648 global_settings.rec_trigger_type = old_trigger_type;
649 exit_request = true;
650 break;
652 case ACTION_REC_PAUSE:
653 exit_request = true;
654 break;
656 case ACTION_STD_PREV:
657 selected += TRIG_OPTION_COUNT - 1;
658 selected %= TRIG_OPTION_COUNT;
659 FOR_NB_SCREENS(i)
661 offset[i] = MIN(offset[i], (int)selected);
662 offset[i] = MAX(offset[i], (int)selected - option_lines[i] + 1);
664 break;
666 case ACTION_STD_NEXT:
667 selected ++;
668 selected %= TRIG_OPTION_COUNT;
669 FOR_NB_SCREENS(i)
671 offset[i] = MIN(offset[i], (int)selected);
672 offset[i] = MAX(offset[i], (int)selected - option_lines[i] + 1);
674 break;
676 case ACTION_SETTINGS_INC:
677 switch (selected) {
678 case TRIGGER_MODE:
679 global_settings.rec_trigger_mode ++;
680 global_settings.rec_trigger_mode %= TRIGGER_MODE_COUNT;
681 break;
683 case TRIGGER_TYPE:
684 global_settings.rec_trigger_type ++;
685 global_settings.rec_trigger_type %= TRIGGER_TYPE_COUNT;
686 break;
688 case PRERECORD_TIME:
689 global_settings.rec_prerecord_time ++;
690 global_settings.rec_prerecord_time %= PRERECORD_TIMES_COUNT;
691 break;
693 case START_THRESHOLD:
694 change_threshold(&global_settings.rec_start_thres, 1);
695 break;
697 case START_DURATION:
698 global_settings.rec_start_duration ++;
699 global_settings.rec_start_duration %= TRIG_DURATION_COUNT;
700 break;
702 case STOP_THRESHOLD:
703 change_threshold(&global_settings.rec_stop_thres, 1);
704 break;
706 case STOP_POSTREC:
707 global_settings.rec_stop_postrec ++;
708 global_settings.rec_stop_postrec %= TRIG_DURATION_COUNT;
709 break;
711 case STOP_GAP:
712 global_settings.rec_stop_gap ++;
713 global_settings.rec_stop_gap %= TRIG_DURATION_COUNT;
714 break;
716 case TRIG_OPTION_COUNT:
717 // avoid compiler warnings
718 break;
720 peak_meter_trigger(global_settings.rec_trigger_mode!=TRIG_OFF);
721 settings_apply_trigger();
722 break;
724 case ACTION_SETTINGS_DEC:
725 switch (selected) {
726 case TRIGGER_MODE:
727 global_settings.rec_trigger_mode+=TRIGGER_MODE_COUNT-1;
728 global_settings.rec_trigger_mode %= TRIGGER_MODE_COUNT;
729 break;
731 case TRIGGER_TYPE:
732 global_settings.rec_trigger_type+=TRIGGER_TYPE_COUNT-1;
733 global_settings.rec_trigger_type %= TRIGGER_TYPE_COUNT;
734 break;
736 case PRERECORD_TIME:
737 global_settings.rec_prerecord_time += PRERECORD_TIMES_COUNT - 1;
738 global_settings.rec_prerecord_time %= PRERECORD_TIMES_COUNT;
739 break;
741 case START_THRESHOLD:
742 change_threshold(&global_settings.rec_start_thres, -1);
743 break;
745 case START_DURATION:
746 global_settings.rec_start_duration += TRIG_DURATION_COUNT-1;
747 global_settings.rec_start_duration %= TRIG_DURATION_COUNT;
748 break;
750 case STOP_THRESHOLD:
751 change_threshold(&global_settings.rec_stop_thres, -1);
752 break;
754 case STOP_POSTREC:
755 global_settings.rec_stop_postrec +=
756 TRIG_DURATION_COUNT - 1;
757 global_settings.rec_stop_postrec %=
758 TRIG_DURATION_COUNT;
759 break;
761 case STOP_GAP:
762 global_settings.rec_stop_gap +=
763 TRIG_DURATION_COUNT - 1;
764 global_settings.rec_stop_gap %= TRIG_DURATION_COUNT;
765 break;
767 case TRIG_OPTION_COUNT:
768 // avoid compiler warnings
769 break;
771 peak_meter_trigger(global_settings.rec_trigger_mode!=TRIG_OFF);
772 settings_apply_trigger();
773 break;
775 case ACTION_REC_F2:
776 peak_meter_trigger(true);
777 break;
779 case SYS_USB_CONNECTED:
780 if(default_event_handler(button) == SYS_USB_CONNECTED) {
781 retval = true;
782 exit_request = true;
784 break;
788 peak_meter_trigger(false);
789 FOR_NB_SCREENS(i)
791 screens[i].setfont(FONT_UI);
792 screens[i].setmargins(old_x_margin[i], old_y_margin[i]);
794 return retval;
797 MENUITEM_FUNCTION(rectrigger_item, 0, ID2P(LANG_RECORD_TRIGGER),
798 (int(*)(void))rectrigger, NULL, NULL, Icon_Menu_setting);
805 /* from main_menu.c */
806 struct browse_folder_info {
807 const char* dir;
808 int show_options;
810 static struct browse_folder_info rec_config_browse = {RECPRESETS_DIR, SHOW_CFG};
811 int browse_folder(void *param);
812 MENUITEM_FUNCTION(browse_recconfigs, MENU_FUNC_USEPARAM, ID2P(LANG_CUSTOM_CFG),
813 browse_folder, (void*)&rec_config_browse, NULL, Icon_Config);
814 static int write_settings_file(void)
816 return settings_save_config(SETTINGS_SAVE_RECPRESETS);
818 MENUITEM_FUNCTION(save_recpresets_item, 0, ID2P(LANG_SAVE_SETTINGS),
819 write_settings_file, NULL, NULL, Icon_Config);
821 MAKE_MENU(recording_settings_menu, ID2P(LANG_RECORDING_SETTINGS),
822 NULL, Icon_Recording,
823 #if CONFIG_CODEC == MAS3587F
824 &rec_quality,
825 #endif
826 #if CONFIG_CODEC == SWCODEC
827 &recformat, &enc_global_config_menu_item,
828 #endif
829 &recfrequency, &recsource, /* recsource not shown if no_source */
830 &recchannels,
831 #if CONFIG_CODEC == MAS3587F
832 &rec_editable,
833 #endif
834 &filesplitoptionsmenu,
835 &rec_prerecord_time,
836 &clear_rec_directory_item,
837 #ifdef HAVE_BACKLIGHT
838 &cliplight,
839 #endif
840 &rectrigger_item,
841 #ifdef HAVE_AGC
842 &agc_preset, &agc_cliptime,
843 #endif
844 &browse_recconfigs, &save_recpresets_item
847 bool recording_menu(bool no_source)
849 bool retval;
850 no_source_in_menu = no_source;
851 retval = do_menu(&recording_settings_menu, NULL) == MENU_ATTACHED_USB;
852 no_source_in_menu = false; /* always fall back to the default */
853 return retval;
856 MENUITEM_FUNCTION(recording_settings, MENU_FUNC_USEPARAM, ID2P(LANG_RECORDING_SETTINGS),
857 (int (*)(void*))recording_menu, 0, NULL, Icon_Recording);