diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2006-11-06 18:07:30 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2006-11-06 18:07:30 +0000 |
commit | 0f5cb94aa4a334366a746fcbb22f3335ca413265 (patch) | |
tree | 8f89a96628c1810d51ee9816daf78edb8c76fcd4 /apps/sound_menu.c | |
parent | 0b22795e26ee09de14f6ac23219adeda12f2fd5b (diff) | |
download | rockbox-0f5cb94aa4a334366a746fcbb22f3335ca413265.tar.gz rockbox-0f5cb94aa4a334366a746fcbb22f3335ca413265.zip |
Big Patch adds primarily: Samplerate and format selection to recording for SWCODEC. Supprort for samplerates changing in playback (just goes with the recording part inseparably). Samplerates to all encoders. Encoders can be configured individually on a menu specific to the encoder in the recording menu. File creation is delayed until flush time to reduce spinups when splitting. Misc: statusbar icons for numbers are individual digits to display any number. Audio buffer was rearranged to maximize memory available to recording and properly reinitialized when trashed. ColdFire PCM stuff moved to target tree to avoid a complicated mess when adding samplerate switching. Some needed API changes and to neaten up growing gap between hardware and software codecs.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11452 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/sound_menu.c')
-rw-r--r-- | apps/sound_menu.c | 288 |
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 | ||
337 | static 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 | ||
357 | static bool recquality(void) | 338 | static 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 */ | ||
354 | void 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 | |||
363 | static 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 | |||
371 | static bool recfrequency(void) | 386 | static 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 | ||
388 | static bool recchannels(void) | 485 | static 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 | ||
399 | static bool rectimesplit(void) | 530 | static 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 | ||
1054 | bool recording_menu(bool no_source) | 1185 | bool 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 */ | ||