1 /* Handle uade.conf file
2 
3    Copyright (C) 2005 Heikki Orsila <heikki.orsila@iki.fi>
4 
5    This source code module is dual licensed under GPL and Public Domain.
6    Hence you may use _this_ module (not another code module) in any way you
7    want in your projects.
8 */
9 
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <ctype.h>
13 #include <string.h>
14 #include <assert.h>
15 #include <limits.h>
16 #include <unistd.h>
17 #include <sys/stat.h>
18 #include <sys/types.h>
19 #include <unistd.h>
20 
21 #include "ossupport.h"
22 #include "uadeconf.h"
23 #include "uadeconfig.h"
24 #include "amigafilter.h"
25 #include "uadeconstants.h"
26 #include "songdb.h"
27 #include "uadeutils.h"
28 #include "support.h"
29 
30 static int uade_set_silence_timeout(struct uade_config *uc, const char *value);
31 static int uade_set_subsong_timeout(struct uade_config *uc, const char *value);
32 static int uade_set_timeout(struct uade_config *uc, const char *value);
33 
34 
35 struct uade_conf_opts {
36 	char *str;
37 	int l;
38 	enum uade_option e;
39 };
40 
41 /* List of uade.conf options. The list includes option name, minimum
42    string match length for the option name and its enum code. */
43 static const struct uade_conf_opts uadeconfopts[] = {
44 	{.str = "action_keys",           .l = 2,  .e = UC_ACTION_KEYS},
45 	{.str = "ao_option",             .l = 2,  .e = UC_AO_OPTION},
46 	{.str = "buffer_time",           .l = 1,  .e = UC_BUFFER_TIME},
47 	{.str = "cygwin",                .l = 1,  .e = UC_CYGWIN_DRIVE_WORKAROUND},
48 	{.str = "detect_format_by_detection", .l = 18, .e = UC_CONTENT_DETECTION},
49 	{.str = "disable_timeout",       .l = 1,  .e = UC_DISABLE_TIMEOUTS},
50 	{.str = "enable_timeout",        .l = 2,  .e = UC_ENABLE_TIMEOUTS},
51 	{.str = "ep_option",             .l = 2,  .e = UC_EAGLEPLAYER_OPTION},
52 	{.str = "filter_type",           .l = 2,  .e = UC_FILTER_TYPE},
53 	{.str = "force_led_off",         .l = 12, .e = UC_FORCE_LED_OFF},
54 	{.str = "force_led_on",          .l = 12, .e = UC_FORCE_LED_ON},
55 	{.str = "force_led",             .l = 9,  .e = UC_FORCE_LED},
56 	{.str = "frequency",             .l = 2,  .e = UC_FREQUENCY},
57 	{.str = "gain",                  .l = 1,  .e = UC_GAIN},
58 	{.str = "headphones",            .l = 11, .e = UC_HEADPHONES},
59 	{.str = "headphones2",           .l = 11, .e = UC_HEADPHONES2},
60 	{.str = "headphone",             .l = 11, .e = UC_HEADPHONES},
61 	{.str = "ignore_player_check",   .l = 2,  .e = UC_IGNORE_PLAYER_CHECK},
62 	{.str = "interpolator",          .l = 2,  .e = UC_RESAMPLER},
63 	{.str = "magic_detection",       .l = 1,  .e = UC_CONTENT_DETECTION},
64 	{.str = "no_ep_end_detect",      .l = 4,  .e = UC_NO_EP_END},
65 	{.str = "no_filter",             .l = 4,  .e = UC_NO_FILTER},
66 	{.str = "no_song_end",           .l = 4,  .e = UC_NO_EP_END},
67 	{.str = "normalise",             .l = 1,  .e = UC_NORMALISE},
68 	{.str = "ntsc",                  .l = 2,  .e = UC_NTSC},
69 	{.str = "one_subsong",           .l = 1,  .e = UC_ONE_SUBSONG},
70 	{.str = "pal",                   .l = 3,  .e = UC_PAL},
71 	{.str = "panning_value",         .l = 3,  .e = UC_PANNING_VALUE},
72 	{.str = "random_play",           .l = 3,  .e = UC_RANDOM_PLAY},
73 	{.str = "recursive_mode",        .l = 3,  .e = UC_RECURSIVE_MODE},
74 	{.str = "resampler",             .l = 3,  .e = UC_RESAMPLER},
75 	{.str = "silence_timeout_value", .l = 2,  .e = UC_SILENCE_TIMEOUT_VALUE},
76 	{.str = "song_title",            .l = 2,  .e = UC_SONG_TITLE},
77 	{.str = "speed_hack",            .l = 2,  .e = UC_SPEED_HACK},
78 	{.str = "subsong_timeout_value", .l = 2,  .e = UC_SUBSONG_TIMEOUT_VALUE},
79 	{.str = "timeout_value",         .l = 1,  .e = UC_TIMEOUT_VALUE},
80 	{.str = "verbose",               .l = 1,  .e = UC_VERBOSE},
81 	{.str = NULL} /* END OF LIST */
82 };
83 
84 
85 /* Map an uade.conf option to an enum */
map_str_to_option(const char * key)86 static enum uade_option map_str_to_option(const char *key)
87 {
88 	size_t i;
89 
90 	for (i = 0; uadeconfopts[i].str != NULL; i++) {
91 		if (strncmp(key, uadeconfopts[i].str, uadeconfopts[i].l) == 0)
92 			return uadeconfopts[i].e;
93 	}
94 
95 	return 0;
96 }
97 
98 /* The function sets the default options. No *_set variables are set because
99    we don't want any option to become mergeable by default. See
100    uade_merge_configs(). */
uade_config_set_defaults(struct uade_config * uc)101 void uade_config_set_defaults(struct uade_config *uc)
102 {
103 	memset(uc, 0, sizeof(*uc));
104 	uc->action_keys = 1;
105 	strlcpy(uc->basedir.name, UADE_CONFIG_BASE_DIR,	sizeof uc->basedir.name);
106 	uade_set_filter_type(uc, NULL);
107 	uc->frequency = UADE_DEFAULT_FREQUENCY;
108 	uc->gain = 1.0;
109 	uc->panning = 0.7;
110 	uc->silence_timeout = 20;
111 	uc->subsong_timeout = 512;
112 	uc->timeout = -1;
113 	uc->use_timeouts = 1;
114 }
115 
uade_convert_to_double(const char * value,double def,double low,double high,const char * type)116 double uade_convert_to_double(const char *value, double def, double low,
117 			      double high, const char *type)
118 {
119 	char *endptr, *newvalue;
120 	char newseparator;
121 	double v;
122 
123 	if (value == NULL)
124 		return def;
125 
126 	v = strtod(value, &endptr);
127 
128 	/* Decimal separator conversion, if needed */
129 	if (*endptr == ',' || *endptr == '.') {
130 		newvalue = strdup(value);
131 		if (newvalue == NULL)
132 			uade_error("Out of memory\n");
133 
134 		newseparator = (*endptr == ',') ? '.' : ',';
135 
136 		newvalue[(intptr_t) endptr - (intptr_t) value] = newseparator;
137 
138 		v = strtod(newvalue, &endptr);
139 		free(newvalue);
140 	}
141 
142 	if (*endptr != 0 || v < low || v > high) {
143 		fprintf(stderr, "Invalid %s value: %s\n", type, value);
144 		v = def;
145 	}
146 
147 	return v;
148 }
149 
uade_add_ep_option(struct uade_ep_options * opts,const char * s)150 static void uade_add_ep_option(struct uade_ep_options *opts, const char *s)
151 {
152 	size_t freespace = sizeof(opts->o) - opts->s;
153 
154 	if (strlcpy(&opts->o[opts->s], s, freespace) >= freespace) {
155 		fprintf(stderr, "Warning: uade eagleplayer option overflow: %s\n", s);
156 		return;
157 	}
158 
159 	opts->s += strlen(s) + 1;
160 }
161 
handle_attributes(struct uade_config * uc,struct uade_song * us,char * playername,size_t playernamelen,int flags,struct uade_attribute * attributelist)162 static int handle_attributes(struct uade_config *uc, struct uade_song *us,
163 			     char *playername, size_t playernamelen,
164 			     int flags, struct uade_attribute *attributelist)
165 {
166 	struct uade_attribute *a;
167 	size_t i;
168 
169 	for (i = 0; epconf[i].s != NULL; i++) {
170 
171 		if (epconf[i].o == 0)
172 			continue;
173 
174 		if ((flags & epconf[i].e) == 0)
175 			continue;
176 
177 		uade_set_config_option(uc, epconf[i].o, epconf[i].c);
178 	}
179 
180 	if (flags & ES_NEVER_ENDS)
181 		fprintf(stderr, "uade: ES_NEVER_ENDS is not implemented. What should it do?\n");
182 
183 	if (flags & ES_REJECT)
184 		return -1;
185 
186 	a = attributelist;
187 
188 	while (a != NULL) {
189 
190 		switch (a->type) {
191 		case ES_EP_OPTION:
192 			if (uc->verbose)
193 				fprintf(stderr, "Using eagleplayer option %s\n", a->s);
194 			uade_add_ep_option(&us->ep_options, a->s);
195 			break;
196 
197 		case ES_GAIN:
198 			uade_set_config_option(uc, UC_GAIN, a->s);
199 			break;
200 
201 		case ES_RESAMPLER:
202 			uade_set_config_option(uc, UC_RESAMPLER, a->s);
203 			break;
204 
205 		case ES_PANNING:
206 			uade_set_config_option(uc, UC_PANNING_VALUE, a->s);
207 			break;
208 
209 		case ES_PLAYER:
210 			if (playername) {
211 				snprintf(playername, playernamelen, "%s/players/%s", uc->basedir.name, a->s);
212 			} else {
213 				fprintf(stderr, "Error: attribute handling was given playername == NULL.\n");
214 			}
215 			break;
216 
217 		case ES_SILENCE_TIMEOUT:
218 			uade_set_config_option(uc, UC_SILENCE_TIMEOUT_VALUE, a->s);
219 			break;
220 
221 		case ES_SUBSONGS:
222 			fprintf(stderr, "Subsongs not implemented.\n");
223 			break;
224 
225 		case ES_SUBSONG_TIMEOUT:
226 			uade_set_config_option(uc, UC_SUBSONG_TIMEOUT_VALUE, a->s);
227 			break;
228 
229 		case ES_TIMEOUT:
230 			uade_set_config_option(uc, UC_TIMEOUT_VALUE, a->s);
231 			break;
232 
233 		default:
234 			fprintf(stderr,	"Unknown song attribute integer: 0x%x\n", a->type);
235 			break;
236 		}
237 
238 		a = a->next;
239 	}
240 
241 	return 0;
242 }
243 
uade_set_song_attributes(struct uade_state * state,char * playername,size_t playernamelen)244 int uade_set_song_attributes(struct uade_state *state,
245 			     char *playername, size_t playernamelen)
246 {
247 	struct uade_song *us = state->song;
248 	struct uade_config *uc = &state->config;
249 
250 	if (us->normalisation)
251 		uade_set_config_option(uc, UC_NORMALISE, us->normalisation);
252 
253 	return handle_attributes(uc, us, playername, playernamelen,
254 				 us->flags, us->songattributes);
255 }
256 
uade_load_config(struct uade_config * uc,const char * filename)257 int uade_load_config(struct uade_config *uc, const char *filename)
258 {
259 	char line[256];
260 	FILE *f;
261 	char *key, *value;
262 	int linenumber = 0;
263 	enum uade_option opt;
264 
265 	if ((f = fopen(filename, "r")) == NULL)
266 		return 0;
267 
268 	uade_config_set_defaults(uc);
269 
270 	while (xfgets(line, sizeof(line), f) != NULL) {
271 		linenumber++;
272 
273 		/* Skip comment lines */
274 		if (line[0] == '#')
275 			continue;
276 
277 		if (!get_two_ws_separated_fields(&key, &value, line))
278 			continue; /* Skip an empty line */
279 
280 		opt = map_str_to_option(key);
281 
282 		if (opt) {
283 			uade_set_config_option(uc, opt, value);
284 		} else {
285 			fprintf(stderr,	"Unknown config key in %s on line %d: %s\n", filename, linenumber, key);
286 		}
287 	}
288 
289 	fclose(f);
290 	return 1;
291 }
292 
uade_load_initial_config(char * uadeconfname,size_t maxlen,struct uade_config * uc,struct uade_config * ucbase)293 int uade_load_initial_config(char *uadeconfname, size_t maxlen,
294 			     struct uade_config *uc, struct uade_config *ucbase)
295 {
296 	int loaded;
297 	char *home;
298 
299 	assert(maxlen > 0);
300 	uadeconfname[0] = 0;
301 
302 	uade_config_set_defaults(uc);
303 
304 	loaded = 0;
305 
306 	/* First try to load from forced base dir (testing mode) */
307 	if (ucbase != NULL && ucbase->basedir_set) {
308 		snprintf(uadeconfname, maxlen, "%s/uade.conf",
309 			 ucbase->basedir.name);
310 		loaded = uade_load_config(uc, uadeconfname);
311 	}
312 
313 	home = uade_open_create_home();
314 
315 	/* Second, try to load config from ~/.uade2/uade.conf */
316 	if (loaded == 0 && home != NULL) {
317 		snprintf(uadeconfname, maxlen, "%s/.uade2/uade.conf", home);
318 		loaded = uade_load_config(uc, uadeconfname);
319 	}
320 
321 	/* Third, try to load from install path */
322 	if (loaded == 0) {
323 		snprintf(uadeconfname, maxlen, "%s/uade.conf",
324 			 uc->basedir.name);
325 		loaded = uade_load_config(uc, uadeconfname);
326 	}
327 
328 	return loaded;
329 }
330 
uade_load_initial_song_conf(char * songconfname,size_t maxlen,struct uade_config * uc,struct uade_config * ucbase)331 int uade_load_initial_song_conf(char *songconfname, size_t maxlen,
332 				struct uade_config *uc,
333 				struct uade_config *ucbase)
334 {
335 	int loaded = 0;
336 	char *home;
337 
338 	assert(maxlen > 0);
339 	songconfname[0] = 0;
340 
341 	/* Used for testing */
342 	if (ucbase != NULL && ucbase->basedir_set) {
343 		snprintf(songconfname, maxlen, "%s/song.conf",
344 			 ucbase->basedir.name);
345 		loaded = uade_read_song_conf(songconfname);
346 	}
347 
348 	/* Avoid unwanted home directory creation for test mode */
349 	if (loaded)
350 		return loaded;
351 
352 	home = uade_open_create_home();
353 
354 	/* Try to load from home dir */
355 	if (loaded == 0 && home != NULL) {
356 		snprintf(songconfname, maxlen, "%s/.uade2/song.conf", home);
357 		loaded = uade_read_song_conf(songconfname);
358 	}
359 
360 	/* No? Try install path */
361 	if (loaded == 0) {
362 		snprintf(songconfname, maxlen, "%s/song.conf",
363 			 uc->basedir.name);
364 		loaded = uade_read_song_conf(songconfname);
365 	}
366 
367 	return loaded;
368 }
369 
uade_merge_configs(struct uade_config * ucd,const struct uade_config * ucs)370 void uade_merge_configs(struct uade_config *ucd, const struct uade_config *ucs)
371 {
372 #define MERGE_OPTION(y) do { if (ucs->y##_set) ucd->y = ucs->y; } while (0)
373 
374 	MERGE_OPTION(action_keys);
375 	MERGE_OPTION(ao_options);
376 	MERGE_OPTION(basedir);
377 	MERGE_OPTION(buffer_time);
378 	MERGE_OPTION(content_detection);
379 	MERGE_OPTION(cygwin_drive_workaround);
380 	MERGE_OPTION(ep_options);
381 	MERGE_OPTION(filter_type);
382 	MERGE_OPTION(frequency);
383 	MERGE_OPTION(gain);
384 	MERGE_OPTION(gain_enable);
385 	MERGE_OPTION(headphones);
386 	MERGE_OPTION(headphones2);
387 	MERGE_OPTION(ignore_player_check);
388 	MERGE_OPTION(led_forced);
389 	MERGE_OPTION(led_state);
390 	MERGE_OPTION(no_ep_end);
391 	MERGE_OPTION(no_filter);
392 	MERGE_OPTION(no_postprocessing);
393 
394 	/* Special merge -> don't use MERGE_OPTION macro */
395 	if (ucs->normalise_set && ucs->normalise) {
396 		ucd->normalise = 1;
397 		if (ucs->normalise_parameter != NULL)
398 			ucd->normalise_parameter = ucs->normalise_parameter;
399 	}
400 
401 	MERGE_OPTION(one_subsong);
402 	MERGE_OPTION(panning);
403 	MERGE_OPTION(panning_enable);
404 	MERGE_OPTION(random_play);
405 	MERGE_OPTION(recursive_mode);
406 	MERGE_OPTION(resampler);
407 	MERGE_OPTION(silence_timeout);
408 	MERGE_OPTION(song_title);
409 	MERGE_OPTION(speed_hack);
410 	MERGE_OPTION(subsong_timeout);
411 
412 	MERGE_OPTION(timeout);
413 	MERGE_OPTION(use_timeouts);
414 	if (ucs->timeout_set) {
415 		ucd->use_timeouts = 1;
416 		ucd->use_timeouts_set = 1;
417 	}
418 
419 	MERGE_OPTION(use_text_scope);
420 	MERGE_OPTION(use_ntsc);
421 	MERGE_OPTION(verbose);
422 }
423 
uade_open_create_home(void)424 char *uade_open_create_home(void)
425 {
426 	/* Create ~/.uade2 directory if it does not exist */
427 	char *home = getenv("HOME");
428 	if (home) {
429 		char name[PATH_MAX];
430 		struct stat st;
431 		snprintf(name, sizeof name, "%s/.uade2", home);
432 		if (stat(name, &st) != 0)
433 			mkdir(name, S_IRUSR | S_IWUSR | S_IXUSR);
434 	}
435 
436 	return home;
437 }
438 
uade_parse_subsongs(int ** subsongs,char * option)439 int uade_parse_subsongs(int **subsongs, char *option)
440 {
441 	char substr[256];
442 	char *sp, *str;
443 	size_t pos;
444 	int nsubsongs;
445 
446 	nsubsongs = 0;
447 	*subsongs = NULL;
448 
449 	if (strlcpy(substr, option, sizeof subsongs) >= sizeof subsongs) {
450 		fprintf(stderr, "Too long a subsong option: %s\n", option);
451 		return -1;
452 	}
453 
454 	sp = substr;
455 	while ((str = strsep(&sp, ",")) != NULL) {
456 		if (*str == 0)
457 			continue;
458 		nsubsongs++;
459 	}
460 
461 	*subsongs = malloc((nsubsongs + 1) * sizeof((*subsongs)[0]));
462 	if (*subsongs == NULL) {
463 		fprintf(stderr, "No memory for subsongs.\n");
464 		return -1;
465 	}
466 
467 	strlcpy(substr, option, sizeof subsongs);
468 
469 	pos = 0;
470 	sp = substr;
471 	while ((str = strsep(&sp, ",")) != NULL) {
472 		if (*str == 0)
473 			continue;
474 		(*subsongs)[pos] = atoi(str);
475 		pos++;
476 	}
477 
478 	(*subsongs)[pos] = -1;
479 	assert(pos == nsubsongs);
480 
481 	return nsubsongs;
482 }
483 
uade_set_effects(struct uade_state * state)484 void uade_set_effects(struct uade_state *state)
485 {
486 	struct uade_effect *effects = &state->effects;
487 	struct uade_config *uc = &state->config;
488 
489 	uade_effect_set_defaults(effects);
490 
491 	if (uc->no_postprocessing)
492 		uade_effect_disable(effects, UADE_EFFECT_ALLOW);
493 
494 	if (uc->gain_enable) {
495 		uade_effect_gain_set_amount(effects, uc->gain);
496 		uade_effect_enable(effects, UADE_EFFECT_GAIN);
497 	}
498 
499 	if (uc->headphones)
500 		uade_effect_enable(effects, UADE_EFFECT_HEADPHONES);
501 
502 	if (uc->headphones2)
503 		uade_effect_enable(effects, UADE_EFFECT_HEADPHONES2);
504 
505 	if (uc->normalise) {
506 		uade_effect_normalise_unserialise(uc->normalise_parameter);
507 		uade_effect_enable(effects, UADE_EFFECT_NORMALISE);
508 	}
509 
510 	if (uc->panning_enable) {
511 		uade_effect_pan_set_amount(effects, uc->panning);
512 		uade_effect_enable(effects, UADE_EFFECT_PAN);
513 	}
514 
515 	uade_effect_set_sample_rate(effects, uc->frequency);
516 }
517 
uade_set_config_option(struct uade_config * uc,enum uade_option opt,const char * value)518 void uade_set_config_option(struct uade_config *uc, enum uade_option opt,
519 			    const char *value)
520 {
521 	char *endptr;
522 	long x;
523 
524 #define SET_OPTION(opt, value) do { uc->opt = (value); uc->opt##_set = 1; } while (0)
525 
526 	switch (opt) {
527 	case UC_ACTION_KEYS:
528 		if (value != NULL) {
529 			uc->action_keys_set = 1;
530 			if (!strcasecmp(value, "on") || !strcmp(value, "1")) {
531 				uc->action_keys = 1;
532 			} else if (!strcasecmp(value, "off") ||
533 				   !strcmp(value, "0")) {
534 				uc->action_keys = 0;
535 			} else {
536 				fprintf(stderr,
537 					"uade.conf: Unknown setting for action keys: %s\n",
538 					value);
539 			}
540 		}
541 		break;
542 
543 	case UC_AO_OPTION:
544 		strlcat(uc->ao_options.o, value, sizeof uc->ao_options.o);
545 		strlcat(uc->ao_options.o, "\n", sizeof uc->ao_options.o);
546 		uc->ao_options_set = 1;
547 		break;
548 
549 	case UC_BASE_DIR:
550 		if (value != NULL) {
551 			strlcpy(uc->basedir.name, value,
552 				sizeof uc->basedir.name);
553 			uc->basedir_set = 1;
554 		} else {
555 			fprintf(stderr, "uade: Passed NULL to UC_BASE_DIR.\n");
556 		}
557 		break;
558 
559 	case UC_BUFFER_TIME:
560 		if (value != NULL) {
561 			uc->buffer_time_set = 1;
562 			uc->buffer_time = strtol(value, &endptr, 10);
563 			if (uc->buffer_time <= 0 || *endptr != 0) {
564 				fprintf(stderr, "Invalid buffer_time: %s\n",
565 					value);
566 				uc->buffer_time = 0;
567 			}
568 		} else {
569 			fprintf(stderr,
570 				"uade: Passed NULL to UC_BUFFER_TIME.\n");
571 		}
572 		break;
573 
574 	case UC_CONTENT_DETECTION:
575 		SET_OPTION(content_detection, 1);
576 		break;
577 
578 	case UC_CYGWIN_DRIVE_WORKAROUND:
579 		SET_OPTION(cygwin_drive_workaround, 1);
580 		break;
581 
582 	case UC_DISABLE_TIMEOUTS:
583 		SET_OPTION(use_timeouts, 0);
584 		break;
585 
586 	case UC_ENABLE_TIMEOUTS:
587 		SET_OPTION(use_timeouts, 1);
588 		break;
589 
590 	case UC_EAGLEPLAYER_OPTION:
591 		if (value != NULL) {
592 			uade_add_ep_option(&uc->ep_options, value);
593 			uc->ep_options_set = 1;
594 		} else {
595 			fprintf(stderr,
596 				"uade: Passed NULL to UC_EAGLEPLAYER_OPTION.\n");
597 		}
598 		break;
599 
600 	case UC_FILTER_TYPE:
601 		SET_OPTION(no_filter, 0);
602 
603 		if (value != NULL) {
604 			if (strcasecmp(value, "none") != 0) {
605 				/* Filter != NONE */
606 				uade_set_filter_type(uc, value);
607 				uc->filter_type_set = 1;
608 			} else {
609 				/* Filter == NONE */
610 				uc->no_filter = 1;
611 			}
612 		}
613 		break;
614 
615 	case UC_FORCE_LED:
616 		if (value == NULL) {
617 			fprintf(stderr, "uade: UC_FORCE_LED value is NULL\n");
618 			break;
619 		}
620 		if (strcasecmp(value, "off") == 0 || strcmp(value, "0") == 0) {
621 			uc->led_state = 0;
622 		} else if (strcasecmp(value, "on") == 0
623 			   || strcmp(value, "1") == 0) {
624 			uc->led_state = 1;
625 		} else {
626 			fprintf(stderr, "Unknown force led argument: %s\n",
627 				value);
628 			break;
629 		}
630 		uc->led_state_set = 1;
631 
632 		SET_OPTION(led_forced, 1);
633 		break;
634 
635 	case UC_FORCE_LED_OFF:
636 		SET_OPTION(led_forced, 1);
637 		SET_OPTION(led_state, 0);
638 		break;
639 
640 	case UC_FORCE_LED_ON:
641 		SET_OPTION(led_forced, 1);
642 		SET_OPTION(led_state, 1);
643 		break;
644 
645 	case UC_FREQUENCY:
646 		if (value == NULL) {
647 			fprintf(stderr, "uade: UC_FREQUENCY value is NULL\n");
648 			break;
649 		}
650 		x = strtol(value, &endptr, 10);
651 		if (*endptr != 0) {
652 			fprintf(stderr, "Invalid frequency number: %s\n",
653 				value);
654 			break;
655 		}
656 		/* The upper bound is NTSC Amigas bus freq */
657 		if (x < 1 || x > 3579545) {
658 			fprintf(stderr, "Frequency out of bounds: %ld\n", x);
659 			x = UADE_DEFAULT_FREQUENCY;
660 		}
661 		SET_OPTION(frequency, x);
662 		break;
663 
664 	case UC_GAIN:
665 		if (value == NULL) {
666 			fprintf(stderr, "uade: UC_GAIN value is NULL\n");
667 			break;
668 		}
669 		SET_OPTION(gain_enable, 1);
670 		SET_OPTION(gain, uade_convert_to_double(value, 1.0, 0.0, 128.0, "gain"));
671 		break;
672 
673 	case UC_HEADPHONES:
674 		SET_OPTION(headphones, 1);
675 		break;
676 
677 	case UC_HEADPHONES2:
678 		SET_OPTION(headphones2, 1);
679 		break;
680 
681 	case UC_IGNORE_PLAYER_CHECK:
682 		SET_OPTION(ignore_player_check, 1);
683 		break;
684 
685 	case UC_RESAMPLER:
686 		if (value == NULL) {
687 			fprintf(stderr, "uade.conf: No resampler given.\n");
688 			break;
689 		}
690 		uc->resampler = strdup(value);
691 		if (uc->resampler != NULL) {
692 			uc->resampler_set = 1;
693 		} else {
694 			fprintf(stderr,	"uade.conf: no memory for resampler.\n");
695 		}
696 		break;
697 
698 	case UC_NO_EP_END:
699 		SET_OPTION(no_ep_end, 1);
700 		break;
701 
702 	case UC_NO_FILTER:
703 		SET_OPTION(no_filter, 1);
704 		break;
705 
706 	case UC_NO_HEADPHONES:
707 		SET_OPTION(headphones, 0);
708 		SET_OPTION(headphones2, 0);
709 		break;
710 
711 	case UC_NO_PANNING:
712 		SET_OPTION(panning_enable, 0);
713 		break;
714 
715 	case UC_NO_POSTPROCESSING:
716 		SET_OPTION(no_postprocessing, 1);
717 		break;
718 
719 	case UC_NORMALISE:
720 		if (value == NULL) {
721 			fprintf(stderr, "uade: UC_NORMALISE is NULL\n");
722 			break;
723 		}
724 		SET_OPTION(normalise, 1);
725 		uc->normalise_parameter = (char *) value;
726 		break;
727 
728 	case UC_NTSC:
729 		SET_OPTION(use_ntsc, 1);
730 		break;
731 
732 	case UC_ONE_SUBSONG:
733 		SET_OPTION(one_subsong, 1);
734 		break;
735 
736 	case UC_PAL:
737 		SET_OPTION(use_ntsc, 0);
738 		break;
739 
740 	case UC_PANNING_VALUE:
741 		if (value == NULL) {
742 			fprintf(stderr, "uade: UC_PANNING_VALUE is NULL\n");
743 			break;
744 		}
745 		SET_OPTION(panning_enable, 1);
746 		SET_OPTION(panning, uade_convert_to_double(value, 0.0, 0.0, 2.0, "panning"));
747 		break;
748 
749 	case UC_RANDOM_PLAY:
750 		SET_OPTION(random_play, 1);
751 		break;
752 
753 	case UC_RECURSIVE_MODE:
754 		SET_OPTION(recursive_mode, 1);
755 		break;
756 
757 	case UC_SILENCE_TIMEOUT_VALUE:
758 		if (value == NULL) {
759 			fprintf(stderr,
760 				"uade: UC_SILENCE_TIMEOUT_VALUE is NULL\n");
761 			break;
762 		}
763 		uade_set_silence_timeout(uc, value);
764 		break;
765 
766 	case UC_SONG_TITLE:
767 		if (value == NULL) {
768 			fprintf(stderr, "uade: No song_title format given.\n");
769 			break;
770 		}
771 		if ((uc->song_title = strdup(value)) == NULL) {
772 			fprintf(stderr, "No memory for song title format\n");
773 		} else {
774 			uc->song_title_set = 1;
775 		}
776 		break;
777 
778 	case UC_SPEED_HACK:
779 		SET_OPTION(speed_hack, 1);
780 		break;
781 
782 	case UC_SUBSONG_TIMEOUT_VALUE:
783 		if (value == NULL) {
784 			fprintf(stderr,
785 				"uade: UC_SUBSONG_TIMEOUT_VALUE is NULL\n");
786 			break;
787 		}
788 		uade_set_subsong_timeout(uc, value);
789 		break;
790 
791 	case UC_TIMEOUT_VALUE:
792 		if (value == NULL) {
793 			fprintf(stderr, "uade: UC_TIMEOUT_VALUE is NULL\n");
794 			break;
795 		}
796 		uade_set_timeout(uc, value);
797 		break;
798 
799 	case UC_USE_TEXT_SCOPE:
800 		SET_OPTION(use_text_scope, 1);
801 		break;
802 
803 	case UC_VERBOSE:
804 		SET_OPTION(verbose, 1);
805 		break;
806 
807 	default:
808 		fprintf(stderr, "uade_set_config_option(): unknown enum: %d\n",
809 			opt);
810 		exit(1);
811 	}
812 }
813 
uade_set_ep_attributes(struct uade_state * state)814 void uade_set_ep_attributes(struct uade_state *state)
815 {
816 	handle_attributes(&state->config, state->song, NULL, 0, state->ep->flags, state->ep->attributelist);
817 }
818 
uade_set_filter_type(struct uade_config * uc,const char * model)819 void uade_set_filter_type(struct uade_config *uc, const char *model)
820 {
821 	uc->filter_type = FILTER_MODEL_A500;
822 
823 	if (model == NULL)
824 		return;
825 
826 	/* a500 and a500e are the same */
827 	if (strncasecmp(model, "a500", 4) == 0) {
828 		uc->filter_type = FILTER_MODEL_A500;
829 
830 		/* a1200 and a1200e are the same */
831 	} else if (strncasecmp(model, "a1200", 5) == 0) {
832 		uc->filter_type = FILTER_MODEL_A1200;
833 
834 	} else {
835 		fprintf(stderr, "Unknown filter model: %s\n", model);
836 	}
837 }
838 
uade_set_silence_timeout(struct uade_config * uc,const char * value)839 static int uade_set_silence_timeout(struct uade_config *uc, const char *value)
840 {
841 	char *endptr;
842 	int t;
843 	if (value == NULL) {
844 		return -1;
845 	}
846 	t = strtol(value, &endptr, 10);
847 	if (*endptr != 0 || t < -1) {
848 		fprintf(stderr, "Invalid silence timeout value: %s\n", value);
849 		return -1;
850 	}
851 	uc->silence_timeout = t;
852 	uc->silence_timeout_set = 1;
853 	return 0;
854 }
855 
uade_set_subsong_timeout(struct uade_config * uc,const char * value)856 static int uade_set_subsong_timeout(struct uade_config *uc, const char *value)
857 {
858 	char *endptr;
859 	int t;
860 	if (value == NULL) {
861 		return -1;
862 	}
863 	t = strtol(value, &endptr, 10);
864 	if (*endptr != 0 || t < -1) {
865 		fprintf(stderr, "Invalid subsong timeout value: %s\n", value);
866 		return -1;
867 	}
868 	uc->subsong_timeout = t;
869 	uc->subsong_timeout_set = 1;
870 	return 0;
871 }
872 
uade_set_timeout(struct uade_config * uc,const char * value)873 static int uade_set_timeout(struct uade_config *uc, const char *value)
874 {
875 	char *endptr;
876 	int t;
877 	if (value == NULL) {
878 		return -1;
879 	}
880 	t = strtol(value, &endptr, 10);
881 	if (*endptr != 0 || t < -1) {
882 		fprintf(stderr, "Invalid timeout value: %s\n", value);
883 		return -1;
884 	}
885 	uc->timeout = t;
886 	uc->timeout_set = 1;
887 	return 0;
888 }
889