Change i2c config on e200. Seems to speed things up somewhat.
[kugel-rb.git] / apps / enc_config.c
blob3323c8dd94d5ef50c15a1300de4083d8f4c7d184
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
19 #include <stdio.h>
20 #include <sprintf.h>
21 #include <string.h>
22 #include "config.h"
23 #include "action.h"
24 #include "atoi.h"
25 #include "lang.h"
26 #include "misc.h"
27 #include "talk.h"
28 #include "general.h"
29 #include "codecs.h"
30 #include "menu.h"
31 #include "statusbar.h"
32 #include "settings.h"
33 #include "audio.h"
34 #include "pcm_record.h"
35 #include "enc_config.h"
36 #include "splash.h"
39 #define CALL_FN_(fn, ...) \
40 if (fn) fn(__VA_ARGS__)
42 static int enc_menuitem_callback(int action,
43 const struct menu_item_ex *this_item);
44 static int enc_menuitem_enteritem(int action,
45 const struct menu_item_ex *this_item);
46 static void enc_rec_settings_changed(struct encoder_config *cfg);
47 /* this is used by all encoder menu items,
48 MUST be initialised before the call to do_menu() */
49 struct menucallback_data {
50 struct encoder_config *cfg;
51 bool global;
52 } menu_callback_data;
54 /** Function definitions for each codec - add these to enc_data
55 list following the definitions **/
57 /** aiff_enc.codec **/
59 /** mp3_enc.codec **/
60 /* mp3_enc: return encoder capabilities */
61 static void mp3_enc_get_caps(const struct encoder_config *cfg,
62 struct encoder_caps *caps,
63 bool for_config)
65 int i;
66 unsigned long bitr;
68 if (!for_config)
70 /* Overall encoder capabilities */
71 caps->samplerate_caps = MPEG1_SAMPR_CAPS | MPEG2_SAMPR_CAPS;
72 caps->channel_caps = CHN_CAP_ALL;
73 return;
76 /* Restrict caps based on config */
77 i = round_value_to_list32(cfg->mp3_enc.bitrate, mp3_enc_bitr,
78 MP3_ENC_NUM_BITR, false);
79 bitr = mp3_enc_bitr[i];
81 /* sample rate caps */
83 /* check if MPEG1 sample rates are available */
84 if ((bitr >= 32 && bitr <= 128) || bitr >= 160)
85 caps->samplerate_caps |= MPEG1_SAMPR_CAPS;
87 /* check if MPEG2 sample rates and mono are available */
88 if (bitr <= 160)
90 caps->samplerate_caps |= MPEG2_SAMPR_CAPS;
91 caps->channel_caps |= CHN_CAP_MONO;
94 /* check if stereo is available */
95 if (bitr >= 32)
96 caps->channel_caps |= CHN_CAP_STEREO;
97 } /* mp3_enc_get_caps */
99 /* mp3_enc: return the default configuration */
100 static void mp3_enc_default_config(struct encoder_config *cfg)
102 cfg->mp3_enc.bitrate = 128; /* default that works for all types */
103 } /* mp3_enc_default_config */
105 static void mp3_enc_convert_config(struct encoder_config *cfg,
106 bool global)
108 if (global)
110 global_settings.mp3_enc_config.bitrate =
111 round_value_to_list32(cfg->mp3_enc.bitrate, mp3_enc_bitr,
112 MP3_ENC_NUM_BITR, false);
114 else
116 if ((unsigned)global_settings.mp3_enc_config.bitrate > MP3_ENC_NUM_BITR)
117 global_settings.mp3_enc_config.bitrate = MP3_ENC_BITRATE_CFG_DEFAULT;
118 cfg->mp3_enc.bitrate = mp3_enc_bitr[global_settings.mp3_enc_config.bitrate];
120 } /* mp3_enc_convert_config */
122 /* mp3_enc: show the bitrate setting options */
123 static bool mp3_enc_bitrate(struct menucallback_data *data)
125 struct encoder_config *cfg = data->cfg;
126 static const struct opt_items items[] =
128 /* Available in MPEG Version: */
129 #ifdef HAVE_MPEG2_SAMPR
130 #if 0
131 /* this sounds awful no matter what */
132 { "8 kBit/s", TALK_ID(8, UNIT_KBIT) }, /* 2 */
133 #endif
134 /* mono only */
135 { "16 kBit/s", TALK_ID(16, UNIT_KBIT) }, /* 2 */
136 { "24 kBit/s", TALK_ID(24, UNIT_KBIT) }, /* 2 */
137 #endif
138 /* stereo/mono */
139 { "32 kBit/s", TALK_ID(32, UNIT_KBIT) }, /* 1,2 */
140 { "40 kBit/s", TALK_ID(40, UNIT_KBIT) }, /* 1,2 */
141 { "48 kBit/s", TALK_ID(48, UNIT_KBIT) }, /* 1,2 */
142 { "56 kBit/s", TALK_ID(56, UNIT_KBIT) }, /* 1,2 */
143 { "64 kBit/s", TALK_ID(64, UNIT_KBIT) }, /* 1,2 */
144 { "80 kBit/s", TALK_ID(80, UNIT_KBIT) }, /* 1,2 */
145 { "96 kBit/s", TALK_ID(96, UNIT_KBIT) }, /* 1,2 */
146 { "112 kBit/s", TALK_ID(112, UNIT_KBIT) }, /* 1,2 */
147 { "128 kBit/s", TALK_ID(128, UNIT_KBIT) }, /* 1,2 */
148 #if 0
149 /* oddball MPEG2-only rate stuck in the middle */
150 { "144 kBit/s", TALK_ID(144, UNIT_KBIT) }, /* 2 */
151 #endif
152 { "160 kBit/s", TALK_ID(160, UNIT_KBIT) }, /* 1,2 */
153 /* stereo only */
154 { "192 kBit/s", TALK_ID(192, UNIT_KBIT) }, /* 1 */
155 { "224 kBit/s", TALK_ID(224, UNIT_KBIT) }, /* 1 */
156 { "256 kBit/s", TALK_ID(256, UNIT_KBIT) }, /* 1 */
157 { "320 kBit/s", TALK_ID(320, UNIT_KBIT) }, /* 1 */
160 unsigned long rate_list[ARRAYLEN(items)];
162 /* This is rather constant based upon the build but better than
163 storing and maintaining yet another list of numbers */
164 int n_rates = make_list_from_caps32(
165 MPEG1_BITR_CAPS | MPEG2_BITR_CAPS, mp3_enc_bitr,
166 MPEG1_BITR_CAPS
167 #ifdef HAVE_MPEG2_SAMPR
168 | (MPEG2_BITR_CAPS & ~(MP3_BITR_CAP_144 | MP3_BITR_CAP_8))
169 #endif
170 , rate_list);
172 int index = round_value_to_list32(cfg->mp3_enc.bitrate, rate_list,
173 n_rates, false);
174 bool res = set_option(str(LANG_BITRATE), &index, INT,
175 items, n_rates, NULL);
176 index = round_value_to_list32(rate_list[index], mp3_enc_bitr,
177 MP3_ENC_NUM_BITR, false);
178 cfg->mp3_enc.bitrate = mp3_enc_bitr[index];
180 return res;
181 } /* mp3_enc_bitrate */
183 /* mp3_enc configuration menu */
184 MENUITEM_FUNCTION(mp3_bitrate, MENU_FUNC_USEPARAM, ID2P(LANG_BITRATE),
185 mp3_enc_bitrate,
186 &menu_callback_data, enc_menuitem_callback, Icon_NOICON);
187 MAKE_MENU( mp3_enc_menu, ID2P(LANG_ENCODER_SETTINGS),
188 enc_menuitem_enteritem, Icon_NOICON,
189 &mp3_bitrate);
192 /** wav_enc.codec **/
193 /* wav_enc: show the configuration menu */
194 #if 0
195 MAKE_MENU( wav_enc_menu, ID2P(LANG_ENCODER_SETTINGS),
196 enc_menuitem_enteritem, Icon_NOICON,
198 #endif
200 /** wavpack_enc.codec **/
201 /* wavpack_enc: show the configuration menu */
202 #if 0
203 MAKE_MENU( wavpack_enc_menu, ID2P(LANG_ENCODER_SETTINGS),
204 enc_menuitem_enteritem, Icon_NOICON,
206 #endif
208 /** config function pointers and/or data for each codec **/
209 static const struct encoder_data
211 void (*get_caps)(const struct encoder_config *cfg,
212 struct encoder_caps *caps, bool for_config);
213 void (*default_cfg)(struct encoder_config *cfg);
214 void (*convert_cfg)(struct encoder_config *cfg , bool global);
215 const struct menu_item_ex *menu;
216 } enc_data[REC_NUM_FORMATS] =
218 /* aiff_enc.codec */
219 [REC_FORMAT_AIFF] = {
220 NULL,
221 NULL,
222 NULL,
223 NULL,
225 /* mp3_enc.codec */
226 [REC_FORMAT_MPA_L3] = {
227 mp3_enc_get_caps,
228 mp3_enc_default_config,
229 mp3_enc_convert_config,
230 &mp3_enc_menu,
232 /* wav_enc.codec */
233 [REC_FORMAT_PCM_WAV] = {
234 NULL,
235 NULL,
236 NULL,
237 NULL,
239 /* wavpack_enc.codec */
240 [REC_FORMAT_WAVPACK] = {
241 NULL,
242 NULL,
243 NULL,
244 NULL,
248 static inline bool rec_format_ok(int rec_format)
250 return (unsigned)rec_format < REC_NUM_FORMATS;
252 /* This is called before entering the menu with the encoder settings
253 Its needed to make sure the settings can take effect. */
254 static int enc_menuitem_enteritem(int action,
255 const struct menu_item_ex *this_item)
257 (void)this_item;
258 /* this struct must be init'ed before calling do_menu() so this is safe */
259 struct menucallback_data *data = &menu_callback_data;
260 if (action == ACTION_STD_OK) /* entering the item */
262 if (data->global)
263 global_to_encoder_config(data->cfg);
265 return action;
267 /* this is called when a encoder setting is exited
268 It is used to update the status bar and save the setting */
269 static int enc_menuitem_callback(int action,
270 const struct menu_item_ex *this_item)
272 struct menucallback_data *data =
273 (struct menucallback_data*)this_item->function->param;
275 if (action == ACTION_EXIT_MENUITEM)
277 /* If the setting being configured is global, it must be placed
278 in global_settings before updating the status bar for the
279 change to show upon exiting the item. */
280 if (data->global)
282 enc_rec_settings_changed(data->cfg);
283 encoder_config_to_global(data->cfg);
286 gui_syncstatusbar_draw(&statusbars, true);
288 return action;
291 /* update settings dependent upon encoder settings */
292 static void enc_rec_settings_changed(struct encoder_config *cfg)
294 struct encoder_config enc_config;
295 struct encoder_caps caps;
296 long table[MAX(CHN_NUM_MODES, REC_NUM_FREQ)];
297 int n;
299 if (cfg == NULL)
301 cfg = &enc_config;
302 cfg->rec_format = global_settings.rec_format;
303 global_to_encoder_config(cfg);
306 /* have to sync other settings when encoder settings change */
307 if (!enc_get_caps(cfg, &caps, true))
308 return;
310 /* rec_channels */
311 n = make_list_from_caps32(CHN_CAP_ALL, NULL,
312 caps.channel_caps, table);
314 /* no zero check needed: encoder must support at least one
315 sample rate that recording supports or it shouldn't be in
316 available in the recording options */
317 n = round_value_to_list32(global_settings.rec_channels,
318 table, n, true);
319 global_settings.rec_channels = table[n];
321 /* rec_frequency */
322 n = make_list_from_caps32(REC_SAMPR_CAPS, rec_freq_sampr,
323 caps.samplerate_caps, table);
325 n = round_value_to_list32(
326 rec_freq_sampr[global_settings.rec_frequency],
327 table, n, false);
329 global_settings.rec_frequency = round_value_to_list32(
330 table[n], rec_freq_sampr, REC_NUM_FREQ, false);
331 } /* enc_rec_settings_changed */
333 /** public stuff **/
334 void global_to_encoder_config(struct encoder_config *cfg)
336 const struct encoder_data *data = &enc_data[cfg->rec_format];
337 CALL_FN_(data->convert_cfg, cfg, false);
338 } /* global_to_encoder_config */
340 void encoder_config_to_global(const struct encoder_config *cfg)
342 const struct encoder_data *data = &enc_data[cfg->rec_format];
343 CALL_FN_(data->convert_cfg, (struct encoder_config *)cfg, true);
344 } /* encoder_config_to_global */
346 bool enc_get_caps(const struct encoder_config *cfg,
347 struct encoder_caps *caps,
348 bool for_config)
350 /* get_caps expects caps to be zeroed first */
351 memset(caps, 0, sizeof (*caps));
353 if (!rec_format_ok(cfg->rec_format))
354 return false;
356 if (enc_data[cfg->rec_format].get_caps)
358 enc_data[cfg->rec_format].get_caps(cfg, caps, for_config);
360 else
362 /* If no function provided...defaults to all */
363 caps->samplerate_caps = SAMPR_CAP_ALL;
364 caps->channel_caps = CHN_CAP_ALL;
367 return true;
368 } /* enc_get_caps */
370 /* Initializes the config struct with default values */
371 bool enc_init_config(struct encoder_config *cfg)
373 if (!rec_format_ok(cfg->rec_format))
374 return false;
375 CALL_FN_(enc_data[cfg->rec_format].default_cfg, cfg);
376 return true;
377 } /* enc_init_config */
379 /** Encoder Menus **/
380 #if 0
381 bool enc_config_menu(struct encoder_config *cfg)
383 if (!rec_format_ok(cfg->rec_format))
384 return false;
385 if (enc_data[cfg->rec_format].menu)
387 menu_callback_data.cfg = &cfg;
388 menu_callback_data.global = false;
389 return do_menu(enc_data[cfg->rec_format].menu, NULL)
390 == MENU_ATTACHED_USB;
392 else
394 gui_syncsplash(HZ, str(LANG_NO_SETTINGS));
395 return false;
397 } /* enc_config_menu */
398 #endif
400 /** Global Settings **/
402 /* Reset all codecs to defaults */
403 void enc_global_settings_reset(void)
405 struct encoder_config cfg;
406 cfg.rec_format = 0;
410 global_to_encoder_config(&cfg);
411 enc_init_config(&cfg);
412 encoder_config_to_global(&cfg);
413 if (cfg.rec_format == global_settings.rec_format)
414 enc_rec_settings_changed(&cfg);
416 while (++cfg.rec_format < REC_NUM_FORMATS);
417 } /* enc_global_settings_reset */
419 /* Apply new settings */
420 void enc_global_settings_apply(void)
422 struct encoder_config cfg;
423 if (!rec_format_ok(global_settings.rec_format))
424 global_settings.rec_format = REC_FORMAT_DEFAULT;
426 cfg.rec_format = global_settings.rec_format;
427 global_to_encoder_config(&cfg);
428 enc_rec_settings_changed(&cfg);
429 encoder_config_to_global(&cfg);
430 } /* enc_global_settings_apply */
432 /* Show an encoder's config menu based on the global_settings.
433 Modified settings are placed in global_settings.enc_config. */
434 bool enc_global_config_menu(void)
436 struct encoder_config cfg;
438 if (!rec_format_ok(global_settings.rec_format))
439 global_settings.rec_format = REC_FORMAT_DEFAULT;
441 cfg.rec_format = global_settings.rec_format;
443 if (enc_data[cfg.rec_format].menu)
445 menu_callback_data.cfg = &cfg;
446 menu_callback_data.global = true;
447 return do_menu(enc_data[cfg.rec_format].menu, NULL)
448 == MENU_ATTACHED_USB;
450 else
452 gui_syncsplash(HZ, str(LANG_NO_SETTINGS));
453 return false;
455 } /* enc_global_config_menu */