1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006 Michael Sevakis
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 ****************************************************************************/
30 #include "statusbar.h"
33 #include "pcm_record.h"
34 #include "enc_config.h"
36 #define MENU_ITEM_FN(fn) \
39 #define ENC_MENU_ITEM_FN(fn) \
40 ((bool (*)(struct encoder_config *))fn)
42 #define CALL_FN_(fn, ...) \
43 if (fn) fn(__VA_ARGS__)
45 static bool enc_run_menu(int m
, const struct menu_item items
[],
46 struct encoder_config
*cfg
, bool global
);
47 static bool enc_no_config_menu(struct encoder_config
*cfg
, bool global
);
48 static void enc_rec_settings_changed(struct encoder_config
*cfg
);
50 /** Function definitions for each codec - add these to enc_data
51 list following the definitions **/
53 /** aiff_enc.codec **/
56 /* mp3_enc: return encoder capabilities */
57 static void mp3_enc_get_caps(const struct encoder_config
*cfg
,
58 struct encoder_caps
*caps
,
66 /* Overall encoder capabilities */
67 caps
->samplerate_caps
= MPEG1_SAMPR_CAPS
| MPEG2_SAMPR_CAPS
;
68 caps
->channel_caps
= CHN_CAP_ALL
;
72 /* Restrict caps based on config */
73 i
= round_value_to_list32(cfg
->mp3_enc
.bitrate
, mp3_enc_bitr
,
74 MP3_ENC_NUM_BITR
, false);
75 bitr
= mp3_enc_bitr
[i
];
77 /* sample rate caps */
79 /* check if MPEG1 sample rates are available */
80 if ((bitr
>= 32 && bitr
<= 128) || bitr
>= 160)
81 caps
->samplerate_caps
|= MPEG1_SAMPR_CAPS
;
83 /* check if MPEG2 sample rates and mono are available */
86 caps
->samplerate_caps
|= MPEG2_SAMPR_CAPS
;
87 caps
->channel_caps
|= CHN_CAP_MONO
;
90 /* check if stereo is available */
92 caps
->channel_caps
|= CHN_CAP_STEREO
;
93 } /* mp3_enc_get_caps */
95 /* mp3_enc: return the default configuration */
96 static void mp3_enc_default_config(struct encoder_config
*cfg
)
98 cfg
->mp3_enc
.bitrate
= 128; /* default that works for all types */
99 } /* mp3_enc_default_config */
101 static void mp3_enc_convert_config(struct encoder_config
*cfg
,
106 global_settings
.mp3_enc_config
.bitrate
=
107 round_value_to_list32(cfg
->mp3_enc
.bitrate
, mp3_enc_bitr
,
108 MP3_ENC_NUM_BITR
, false);
112 if ((unsigned)global_settings
.mp3_enc_config
.bitrate
> MP3_ENC_NUM_BITR
)
113 global_settings
.mp3_enc_config
.bitrate
= MP3_ENC_BITRATE_CFG_DEFAULT
;
114 cfg
->mp3_enc
.bitrate
= mp3_enc_bitr
[global_settings
.mp3_enc_config
.bitrate
];
116 } /* mp3_enc_convert_config */
118 /* mp3_enc: show the bitrate setting options */
119 static bool mp3_enc_bitrate(struct encoder_config
*cfg
)
121 static const struct opt_items items
[] =
123 /* Available in MPEG Version: */
124 #ifdef HAVE_MPEG2_SAMPR
126 /* this sounds awful no matter what */
127 { "8 kBit/s", TALK_ID(8, UNIT_KBIT
) }, /* 2 */
130 { "16 kBit/s", TALK_ID(16, UNIT_KBIT
) }, /* 2 */
131 { "24 kBit/s", TALK_ID(24, UNIT_KBIT
) }, /* 2 */
134 { "32 kBit/s", TALK_ID(32, UNIT_KBIT
) }, /* 1,2 */
135 { "40 kBit/s", TALK_ID(40, UNIT_KBIT
) }, /* 1,2 */
136 { "48 kBit/s", TALK_ID(48, UNIT_KBIT
) }, /* 1,2 */
137 { "56 kBit/s", TALK_ID(56, UNIT_KBIT
) }, /* 1,2 */
138 { "64 kBit/s", TALK_ID(64, UNIT_KBIT
) }, /* 1,2 */
139 { "80 kBit/s", TALK_ID(80, UNIT_KBIT
) }, /* 1,2 */
140 { "96 kBit/s", TALK_ID(96, UNIT_KBIT
) }, /* 1,2 */
141 { "112 kBit/s", TALK_ID(112, UNIT_KBIT
) }, /* 1,2 */
142 { "128 kBit/s", TALK_ID(128, UNIT_KBIT
) }, /* 1,2 */
144 /* oddball MPEG2-only rate stuck in the middle */
145 { "144 kBit/s", TALK_ID(144, UNIT_KBIT
) }, /* 2 */
147 { "160 kBit/s", TALK_ID(160, UNIT_KBIT
) }, /* 1,2 */
149 { "192 kBit/s", TALK_ID(192, UNIT_KBIT
) }, /* 1 */
150 { "224 kBit/s", TALK_ID(224, UNIT_KBIT
) }, /* 1 */
151 { "256 kBit/s", TALK_ID(256, UNIT_KBIT
) }, /* 1 */
152 { "320 kBit/s", TALK_ID(320, UNIT_KBIT
) }, /* 1 */
155 unsigned long rate_list
[ARRAYLEN(items
)];
157 /* This is rather constant based upon the build but better than
158 storing and maintaining yet another list of numbers */
159 int n_rates
= make_list_from_caps32(
160 MPEG1_BITR_CAPS
| MPEG2_BITR_CAPS
, mp3_enc_bitr
,
162 #ifdef HAVE_MPEG2_SAMPR
163 | (MPEG2_BITR_CAPS
& ~(MP3_BITR_CAP_144
| MP3_BITR_CAP_8
))
167 int index
= round_value_to_list32(cfg
->mp3_enc
.bitrate
, rate_list
,
169 bool res
= set_option(str(LANG_BITRATE
), &index
, INT
,
170 items
, n_rates
, NULL
);
171 index
= round_value_to_list32(rate_list
[index
], mp3_enc_bitr
,
172 MP3_ENC_NUM_BITR
, false);
173 cfg
->mp3_enc
.bitrate
= mp3_enc_bitr
[index
];
176 } /* mp3_enc_bitrate */
178 /* mp3_enc: show the configuration menu */
179 static bool mp3_enc_menu(struct encoder_config
*cfg
, bool global
)
181 static const struct menu_item items
[] =
183 { ID2P(LANG_BITRATE
), MENU_ITEM_FN(mp3_enc_bitrate
) }
187 int m
= menu_init(items
, ARRAYLEN(items
), NULL
, NULL
, NULL
, NULL
);
188 result
= enc_run_menu(m
, items
, cfg
, global
);
193 /** wav_enc.codec **/
194 /* wav_enc: show the configuration menu */
196 static bool wav_enc_menu(struct encoder_config
*cfg
, bool global
);
199 /** wavpack_enc.codec **/
200 /* wavpack_enc: show the configuration menu */
202 static bool wavpack_enc_menu(struct encoder_config
*cfg
, bool global
);
205 /** config function pointers and/or data for each codec **/
206 static const struct encoder_data
208 void (*get_caps
)(const struct encoder_config
*cfg
,
209 struct encoder_caps
*caps
, bool for_config
);
210 void (*default_cfg
)(struct encoder_config
*cfg
);
211 void (*convert_cfg
)(struct encoder_config
*cfg
, bool global
);
212 bool (*menu
)(struct encoder_config
*cfg
, bool global
);
213 } enc_data
[REC_NUM_FORMATS
] =
216 [REC_FORMAT_AIFF
] = {
223 [REC_FORMAT_MPA_L3
] = {
225 mp3_enc_default_config
,
226 mp3_enc_convert_config
,
230 [REC_FORMAT_PCM_WAV
] = {
236 /* wavpack_enc.codec */
237 [REC_FORMAT_WAVPACK
] = {
245 static inline bool rec_format_ok(int rec_format
)
247 return (unsigned)rec_format
< REC_NUM_FORMATS
;
250 static bool enc_run_menu(int m
, const struct menu_item items
[],
251 struct encoder_config
*cfg
, bool global
)
255 int selected
= menu_show(m
);
259 case MENU_SELECTED_EXIT
:
262 case MENU_ATTACHED_USB
:
266 if (items
[selected
].function
== NULL
)
269 /* If the setting being configured is global, it must be placed
270 in global_settings before updating the status bar for the
271 change to show upon exiting the item. */
273 global_to_encoder_config(cfg
);
275 if (ENC_MENU_ITEM_FN(items
[selected
].function
)(cfg
))
280 enc_rec_settings_changed(cfg
);
281 encoder_config_to_global(cfg
);
284 gui_syncstatusbar_draw(&statusbars
, true);
289 /* menu created when encoder has no configuration options */
290 static bool enc_no_config_menu(struct encoder_config
*cfg
, bool global
)
292 static const struct menu_item items
[] =
294 { ID2P(LANG_NO_SETTINGS
), NULL
}
299 m
= menu_init(items
, ARRAYLEN(items
), NULL
, NULL
, NULL
, NULL
);
300 result
= enc_run_menu(m
, items
, NULL
, false);
306 } /* enc_no_config_menu */
308 /* update settings dependent upon encoder settings */
309 static void enc_rec_settings_changed(struct encoder_config
*cfg
)
311 struct encoder_config enc_config
;
312 struct encoder_caps caps
;
313 long table
[MAX(CHN_NUM_MODES
, REC_NUM_FREQ
)];
319 cfg
->rec_format
= global_settings
.rec_format
;
320 global_to_encoder_config(cfg
);
323 /* have to sync other settings when encoder settings change */
324 if (!enc_get_caps(cfg
, &caps
, true))
328 n
= make_list_from_caps32(CHN_CAP_ALL
, NULL
,
329 caps
.channel_caps
, table
);
331 /* no zero check needed: encoder must support at least one
332 sample rate that recording supports or it shouldn't be in
333 available in the recording options */
334 n
= round_value_to_list32(global_settings
.rec_channels
,
336 global_settings
.rec_channels
= table
[n
];
339 n
= make_list_from_caps32(REC_SAMPR_CAPS
, rec_freq_sampr
,
340 caps
.samplerate_caps
, table
);
342 n
= round_value_to_list32(
343 rec_freq_sampr
[global_settings
.rec_frequency
],
346 global_settings
.rec_frequency
= round_value_to_list32(
347 table
[n
], rec_freq_sampr
, REC_NUM_FREQ
, false);
348 } /* enc_rec_settings_changed */
351 void global_to_encoder_config(struct encoder_config
*cfg
)
353 const struct encoder_data
*data
= &enc_data
[cfg
->rec_format
];
354 CALL_FN_(data
->convert_cfg
, cfg
, false);
355 } /* global_to_encoder_config */
357 void encoder_config_to_global(const struct encoder_config
*cfg
)
359 const struct encoder_data
*data
= &enc_data
[cfg
->rec_format
];
360 CALL_FN_(data
->convert_cfg
, (struct encoder_config
*)cfg
, true);
361 } /* encoder_config_to_global */
363 bool enc_get_caps(const struct encoder_config
*cfg
,
364 struct encoder_caps
*caps
,
367 /* get_caps expects caps to be zeroed first */
368 memset(caps
, 0, sizeof (*caps
));
370 if (!rec_format_ok(cfg
->rec_format
))
373 if (enc_data
[cfg
->rec_format
].get_caps
)
375 enc_data
[cfg
->rec_format
].get_caps(cfg
, caps
, for_config
);
379 /* If no function provided...defaults to all */
380 caps
->samplerate_caps
= SAMPR_CAP_ALL
;
381 caps
->channel_caps
= CHN_CAP_ALL
;
387 /* Initializes the config struct with default values */
388 bool enc_init_config(struct encoder_config
*cfg
)
390 if (!rec_format_ok(cfg
->rec_format
))
392 CALL_FN_(enc_data
[cfg
->rec_format
].default_cfg
, cfg
);
394 } /* enc_init_config */
396 /** Encoder Menus **/
398 bool enc_config_menu(struct encoder_config
*cfg
)
400 if (!rec_format_ok(cfg
->rec_format
))
402 return enc_data
[cfg
->rec_format
].menu(cfg
, false);
403 } /* enc_config_menu */
406 /** Global Settings **/
408 /* Reset all codecs to defaults */
409 void enc_global_settings_reset(void)
411 struct encoder_config cfg
;
416 global_to_encoder_config(&cfg
);
417 enc_init_config(&cfg
);
418 encoder_config_to_global(&cfg
);
419 if (cfg
.rec_format
== global_settings
.rec_format
)
420 enc_rec_settings_changed(&cfg
);
422 while (++cfg
.rec_format
< REC_NUM_FORMATS
);
423 } /* enc_global_settings_reset */
425 /* Apply new settings */
426 void enc_global_settings_apply(void)
428 struct encoder_config cfg
;
429 if (!rec_format_ok(global_settings
.rec_format
))
430 global_settings
.rec_format
= REC_FORMAT_DEFAULT
;
432 cfg
.rec_format
= global_settings
.rec_format
;
433 global_to_encoder_config(&cfg
);
434 enc_rec_settings_changed(&cfg
);
435 encoder_config_to_global(&cfg
);
436 } /* enc_global_settings_apply */
438 /* Show an encoder's config menu based on the global_settings.
439 Modified settings are placed in global_settings.enc_config. */
440 bool enc_global_config_menu(void)
442 struct encoder_config cfg
;
444 if (!rec_format_ok(global_settings
.rec_format
))
445 global_settings
.rec_format
= REC_FORMAT_DEFAULT
;
447 cfg
.rec_format
= global_settings
.rec_format
;
449 return enc_data
[cfg
.rec_format
].menu(&cfg
, true);
450 } /* enc_global_config_menu */