summaryrefslogtreecommitdiff
path: root/apps/sound_menu.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2006-11-06 18:07:30 +0000
committerMichael Sevakis <jethead71@rockbox.org>2006-11-06 18:07:30 +0000
commit0f5cb94aa4a334366a746fcbb22f3335ca413265 (patch)
tree8f89a96628c1810d51ee9816daf78edb8c76fcd4 /apps/sound_menu.c
parent0b22795e26ee09de14f6ac23219adeda12f2fd5b (diff)
downloadrockbox-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.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 */