summaryrefslogtreecommitdiff
path: root/apps/sound_menu.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/sound_menu.c')
-rw-r--r--apps/sound_menu.c288
1 files changed, 210 insertions, 78 deletions
diff --git a/apps/sound_menu.c b/apps/sound_menu.c
index c10ba9417e..fb766d604c 100644
--- a/apps/sound_menu.c
+++ b/apps/sound_menu.c
@@ -54,6 +54,10 @@
54#include "dsp.h" 54#include "dsp.h"
55#include "eq_menu.h" 55#include "eq_menu.h"
56#include "pcmbuf.h" 56#include "pcmbuf.h"
57#ifdef HAVE_RECORDING
58#include "enc_config.h"
59#endif
60#include "general.h"
57#endif 61#endif
58#include "action.h" 62#include "action.h"
59 63
@@ -308,22 +312,20 @@ static bool recsource(void)
308{ 312{
309 int n_opts = AUDIO_NUM_SOURCES; 313 int n_opts = AUDIO_NUM_SOURCES;
310 314
311 struct opt_items names[AUDIO_NUM_SOURCES] = { 315 static const struct opt_items names[AUDIO_NUM_SOURCES] = {
312 { STR(LANG_RECORDING_SRC_MIC) }, 316 [AUDIO_SRC_MIC] = { STR(LANG_RECORDING_SRC_MIC) },
313 { STR(LANG_RECORDING_SRC_LINE) }, 317 [AUDIO_SRC_LINEIN] = { STR(LANG_RECORDING_SRC_LINE) },
314#ifdef HAVE_SPDIF_IN 318#ifdef HAVE_SPDIF_IN
315 { STR(LANG_RECORDING_SRC_DIGITAL) }, 319 [AUDIO_SRC_SPDIF] = { STR(LANG_RECORDING_SRC_DIGITAL) },
320#endif
321#ifdef HAVE_FMRADIO_IN
322 [AUDIO_SRC_FMRADIO] = { STR(LANG_FM_RADIO) }
316#endif 323#endif
317 }; 324 };
318 325
319 /* caveat: assumes it's the last item! */ 326 /* caveat: assumes it's the last item! */
320#ifdef HAVE_FMRADIO_IN 327#ifdef HAVE_FMRADIO_IN
321 if (radio_hardware_present()) 328 if (!radio_hardware_present())
322 {
323 names[AUDIO_SRC_FMRADIO].string = ID2P(LANG_FM_RADIO);
324 names[AUDIO_SRC_FMRADIO].voice_id = LANG_FM_RADIO;
325 }
326 else
327 n_opts--; 329 n_opts--;
328#endif 330#endif
329 331
@@ -332,28 +334,7 @@ static bool recsource(void)
332 n_opts, NULL ); 334 n_opts, NULL );
333} 335}
334 336
335/* To be removed when we add support for sample rates and channel settings */ 337#if CONFIG_CODEC == MAS3587F
336#if CONFIG_CODEC == SWCODEC
337static bool recquality(void)
338{
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) }
349 };
350
351 return set_option(str(LANG_RECORDING_QUALITY),
352 &global_settings.rec_quality, INT,
353 names, sizeof (names)/sizeof(struct opt_items),
354 NULL );
355}
356#elif CONFIG_CODEC == MAS3587F
357static bool recquality(void) 338static bool recquality(void)
358{ 339{
359 return set_int(str(LANG_RECORDING_QUALITY), "", UNIT_INT, 340 return set_int(str(LANG_RECORDING_QUALITY), "", UNIT_INT,
@@ -368,32 +349,182 @@ static bool receditable(void)
368} 349}
369#endif /* CONFIG_CODEC == MAS3587F */ 350#endif /* CONFIG_CODEC == MAS3587F */
370 351
352#if CONFIG_CODEC == SWCODEC
353/* Makes an options list from a source list of options and indexes */
354void make_options_from_indexes(const struct opt_items *src_names,
355 const long *src_indexes,
356 int n_indexes,
357 struct opt_items *dst_names)
358{
359 while (--n_indexes >= 0)
360 dst_names[n_indexes] = src_names[src_indexes[n_indexes]];
361} /* make_options_from_indexes */
362
363static bool recformat(void)
364{
365 static const struct opt_items names[REC_NUM_FORMATS] = {
366 [REC_FORMAT_MPA_L3] = { STR(LANG_AFMT_MPA_L3) },
367 [REC_FORMAT_WAVPACK] = { STR(LANG_AFMT_WAVPACK) },
368 [REC_FORMAT_PCM_WAV] = { STR(LANG_AFMT_PCM_WAV) },
369 };
370
371 int rec_format = global_settings.rec_format;
372 bool res = set_option(str(LANG_RECORDING_FORMAT), &rec_format, INT,
373 names, REC_NUM_FORMATS, NULL );
374
375 if (rec_format != global_settings.rec_format)
376 {
377 global_settings.rec_format = rec_format;
378 enc_global_settings_apply();
379 }
380
381 return res;
382} /* recformat */
383
384#endif /* CONFIG_CODEC == SWCODEC */
385
371static bool recfrequency(void) 386static bool recfrequency(void)
372{ 387{
373 static const struct opt_items names[] = { 388#if CONFIG_CODEC == MAS3587F
389 static const struct opt_items names[6] = {
374 { "44.1kHz", TALK_ID(44, UNIT_KHZ) }, 390 { "44.1kHz", TALK_ID(44, UNIT_KHZ) },
375#if CONFIG_CODEC != SWCODEC /* This is temporary */
376 { "48kHz", TALK_ID(48, UNIT_KHZ) }, 391 { "48kHz", TALK_ID(48, UNIT_KHZ) },
377 { "32kHz", TALK_ID(32, UNIT_KHZ) }, 392 { "32kHz", TALK_ID(32, UNIT_KHZ) },
378 { "22.05kHz", TALK_ID(22, UNIT_KHZ) }, 393 { "22.05kHz", TALK_ID(22, UNIT_KHZ) },
379 { "24kHz", TALK_ID(24, UNIT_KHZ) }, 394 { "24kHz", TALK_ID(24, UNIT_KHZ) },
380 { "16kHz", TALK_ID(16, UNIT_KHZ) } 395 { "16kHz", TALK_ID(16, UNIT_KHZ) }
381#endif
382 }; 396 };
383 return set_option(str(LANG_RECORDING_FREQUENCY), 397 return set_option(str(LANG_RECORDING_FREQUENCY),
384 &global_settings.rec_frequency, INT, 398 &global_settings.rec_frequency, INT,
385 names, sizeof(names)/sizeof(*names), NULL ); 399 names, 6, NULL );
400#endif /* CONFIG_CODEC == MAS3587F */
401
402#if CONFIG_CODEC == SWCODEC
403 static const struct opt_items names[REC_NUM_FREQ] = {
404 REC_HAVE_96_([REC_FREQ_96] = { "96kHz", TALK_ID(96, UNIT_KHZ) },)
405 REC_HAVE_88_([REC_FREQ_88] = { "88.2kHz", TALK_ID(88, UNIT_KHZ) },)
406 REC_HAVE_64_([REC_FREQ_64] = { "64kHz", TALK_ID(64, UNIT_KHZ) },)
407 REC_HAVE_48_([REC_FREQ_48] = { "48kHz", TALK_ID(48, UNIT_KHZ) },)
408 REC_HAVE_44_([REC_FREQ_44] = { "44.1kHz", TALK_ID(44, UNIT_KHZ) },)
409 REC_HAVE_32_([REC_FREQ_32] = { "32kHz", TALK_ID(32, UNIT_KHZ) },)
410 REC_HAVE_24_([REC_FREQ_24] = { "24kHz", TALK_ID(24, UNIT_KHZ) },)
411 REC_HAVE_22_([REC_FREQ_22] = { "22.05kHz", TALK_ID(22, UNIT_KHZ) },)
412 REC_HAVE_16_([REC_FREQ_16] = { "16kHz", TALK_ID(16, UNIT_KHZ) },)
413 REC_HAVE_12_([REC_FREQ_12] = { "12kHz", TALK_ID(12, UNIT_KHZ) },)
414 REC_HAVE_11_([REC_FREQ_11] = { "11.025kHz", TALK_ID(11, UNIT_KHZ) },)
415 REC_HAVE_8_( [REC_FREQ_8 ] = { "8kHz", TALK_ID( 8, UNIT_KHZ) },)
416 };
417
418 struct opt_items opts[REC_NUM_FREQ];
419 unsigned long table[REC_NUM_FREQ];
420 int n_opts;
421 int rec_frequency;
422 bool ret;
423
424#ifdef HAVE_SPDIF_IN
425 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
426 {
427 /* Inform user that frequency follows the source's frequency */
428 opts[0].string = ID2P(LANG_SOURCE_FREQUENCY);
429 opts[0].voice_id = LANG_SOURCE_FREQUENCY;
430 n_opts = 1;
431 rec_frequency = 0;
386} 432}
433 else
434#endif
435 {
436 struct encoder_caps caps;
437 struct encoder_config cfg;
438
439 cfg.rec_format = global_settings.rec_format;
440 global_to_encoder_config(&cfg);
441
442 if (!enc_get_caps(&cfg, &caps, true))
443 return false;
444
445 /* Construct samplerate menu based upon encoder settings */
446 n_opts = make_list_from_caps32(REC_SAMPR_CAPS, NULL,
447 caps.samplerate_caps, table);
448
449 if (n_opts == 0)
450 return false; /* No common flags...?? */
451
452 make_options_from_indexes(names, table, n_opts, opts);
453
454 /* Find closest rate that the potentially restricted list
455 comes to */
456 make_list_from_caps32(REC_SAMPR_CAPS, rec_freq_sampr,
457 caps.samplerate_caps, table);
458
459 rec_frequency = round_value_to_list32(
460 rec_freq_sampr[global_settings.rec_frequency],
461 table, n_opts, false);
462 }
463
464 ret = set_option(str(LANG_RECORDING_FREQUENCY),
465 &rec_frequency, INT, opts, n_opts, NULL );
466
467 if (!ret
468#ifdef HAVE_SPDIF_IN
469 && global_settings.rec_source != AUDIO_SRC_SPDIF
470#endif
471 )
472 {
473 /* Translate back to full index */
474 global_settings.rec_frequency =
475 round_value_to_list32(table[rec_frequency],
476 rec_freq_sampr,
477 REC_NUM_FREQ,
478 false);
479 }
480
481 return ret;
482#endif /* CONFIG_CODEC == SWCODEC */
483} /* recfrequency */
387 484
388static bool recchannels(void) 485static bool recchannels(void)
389{ 486{
390 static const struct opt_items names[] = { 487 static const struct opt_items names[CHN_NUM_MODES] = {
391 { STR(LANG_CHANNEL_STEREO) }, 488 [CHN_MODE_STEREO] = { STR(LANG_CHANNEL_STEREO) },
392 { STR(LANG_CHANNEL_MONO) } 489 [CHN_MODE_MONO] = { STR(LANG_CHANNEL_MONO) }
393 }; 490 };
491#if CONFIG_CODEC == MAS3587F
394 return set_option(str(LANG_RECORDING_CHANNELS), 492 return set_option(str(LANG_RECORDING_CHANNELS),
395 &global_settings.rec_channels, INT, 493 &global_settings.rec_channels, INT,
396 names, 2, NULL ); 494 names, CHN_NUM_MODES, NULL );
495#endif /* CONFIG_CODEC == MAS3587F */
496
497#if CONFIG_CODEC == SWCODEC
498 struct opt_items opts[CHN_NUM_MODES];
499 long table[CHN_NUM_MODES];
500 struct encoder_caps caps;
501 struct encoder_config cfg;
502 int n_opts;
503 int rec_channels;
504 bool ret;
505
506 cfg.rec_format = global_settings.rec_format;
507 global_to_encoder_config(&cfg);
508
509 if (!enc_get_caps(&cfg, &caps, true))
510 return false;
511
512 n_opts = make_list_from_caps32(CHN_CAP_ALL, NULL,
513 caps.channel_caps, table);
514
515 rec_channels = round_value_to_list32(global_settings.rec_channels,
516 table, n_opts, false);
517
518 make_options_from_indexes(names, table, n_opts, opts);
519
520 ret = set_option(str(LANG_RECORDING_CHANNELS), &rec_channels,
521 INT, opts, n_opts, NULL );
522
523 if (!ret)
524 global_settings.rec_channels = table[rec_channels];
525
526 return ret;
527#endif /* CONFIG_CODEC == SWCODEC */
397} 528}
398 529
399static bool rectimesplit(void) 530static bool rectimesplit(void)
@@ -1049,58 +1180,59 @@ bool rectrigger(void)
1049 action_signalscreenchange(); 1180 action_signalscreenchange();
1050 return retval; 1181 return retval;
1051} 1182}
1052#endif 1183#endif /* !defined(SIMULATOR) && CONFIG_CODEC == MAS3587F */
1053 1184
1054bool recording_menu(bool no_source) 1185bool recording_menu(bool no_source)
1055{ 1186{
1056 int m; 1187 static const struct menu_item static_items[] = {
1057 int i = 0; 1188#if CONFIG_CODEC == MAS3587F
1058 struct menu_item items[13]; 1189 { ID2P(LANG_RECORDING_QUALITY), recquality },
1059 bool result;
1060
1061#if CONFIG_CODEC == MAS3587F || CONFIG_CODEC == SWCODEC
1062 items[i].desc = ID2P(LANG_RECORDING_QUALITY);
1063 items[i++].function = recquality;
1064#endif 1190#endif
1065 items[i].desc = ID2P(LANG_RECORDING_FREQUENCY); 1191#if CONFIG_CODEC == SWCODEC
1066 items[i++].function = recfrequency; 1192 { ID2P(LANG_RECORDING_FORMAT), recformat },
1067 if(!no_source) { 1193 { ID2P(LANG_ENCODER_SETTINGS), enc_global_config_menu },
1068 items[i].desc = ID2P(LANG_RECORDING_SOURCE); 1194#endif
1069 items[i++].function = recsource; 1195 { ID2P(LANG_RECORDING_FREQUENCY), recfrequency },
1070 } 1196 { ID2P(LANG_RECORDING_SOURCE), recsource }, /* not shown if no_source */
1071 items[i].desc = ID2P(LANG_RECORDING_CHANNELS); 1197 { ID2P(LANG_RECORDING_CHANNELS), recchannels },
1072 items[i++].function = recchannels;
1073#if CONFIG_CODEC == MAS3587F 1198#if CONFIG_CODEC == MAS3587F
1074 items[i].desc = ID2P(LANG_RECORDING_EDITABLE); 1199 { ID2P(LANG_RECORDING_EDITABLE), receditable },
1075 items[i++].function = receditable;
1076#endif 1200#endif
1077 items[i].desc = ID2P(LANG_RECORD_TIMESPLIT); 1201 { ID2P(LANG_RECORD_TIMESPLIT), filesplitoptionsmenu },
1078 items[i++].function = filesplitoptionsmenu; 1202 { ID2P(LANG_RECORD_PRERECORD_TIME), recprerecord },
1079 items[i].desc = ID2P(LANG_RECORD_PRERECORD_TIME); 1203 { ID2P(LANG_RECORD_DIRECTORY), recdirectory },
1080 items[i++].function = recprerecord; 1204 { ID2P(LANG_RECORD_STARTUP), reconstartup },
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 1205#ifdef CONFIG_BACKLIGHT
1086 items[i].desc = ID2P(LANG_CLIP_LIGHT); 1206 { ID2P(LANG_CLIP_LIGHT), cliplight },
1087 items[i++].function = cliplight;
1088#endif 1207#endif
1089#if !defined(SIMULATOR) && CONFIG_CODEC == MAS3587F 1208#if !defined(SIMULATOR) && CONFIG_CODEC == MAS3587F
1090 items[i].desc = ID2P(LANG_RECORD_TRIGGER); 1209 { ID2P(LANG_RECORD_TRIGGER), rectrigger },
1091 items[i++].function = rectrigger;
1092#endif 1210#endif
1093#ifdef HAVE_AGC 1211#ifdef HAVE_AGC
1094 items[i].desc = ID2P(LANG_RECORD_AGC_PRESET); 1212 { ID2P(LANG_RECORD_AGC_PRESET), agc_preset },
1095 items[i++].function = agc_preset; 1213 { ID2P(LANG_RECORD_AGC_CLIPTIME), agc_cliptime },
1096 items[i].desc = ID2P(LANG_RECORD_AGC_CLIPTIME);
1097 items[i++].function = agc_cliptime;
1098#endif 1214#endif
1215 };
1099 1216
1100 m=menu_init( items, i, NULL, NULL, NULL, NULL); 1217 struct menu_item items[ARRAYLEN(static_items)];
1218 int i, n_items;
1219 int m;
1220
1221 bool result;
1222
1223 for (i = 0, n_items = 0; i < (int)ARRAYLEN(items); i++)
1224 {
1225 const struct menu_item *mi = &static_items[i];
1226 if (no_source && mi->function == recsource)
1227 continue;
1228 items[n_items++] = *mi;
1229 }
1230
1231 m = menu_init(items, n_items, NULL, NULL, NULL, NULL);
1101 result = menu_run(m); 1232 result = menu_run(m);
1102 menu_exit(m); 1233 menu_exit(m);
1103 1234
1104 return result; 1235 return result;
1105} 1236} /* recording_menu */
1106#endif 1237
1238#endif /* HAVE_RECORDING */