1 /* $Id: options.c,v 1.4 2006/09/15 13:34:06 toad32767 Exp $ */
2 /**
3  ** 2005, 2006 by Marco Trillo
4  ** This file is part of UModPlayer, and is released by
5  ** its autors to the Public Domain.
6  ** In case it's not legally possible, its autors grant
7  ** anyone the right to use, redistribute and modify
8  ** this software for any purpose, without any conditions,
9  ** unless such conditions are required by law.
10  **
11  ** THIS FILE COMES WITHOUT ANY WARRANTY. THE AUTHORS
12  ** SHALL NOT BE LIABLE FOR ANY DAMAGE RESULTING BY THE
13  ** USE OR MISUSE OF THIS SOFTWARE.
14  **/
15 
16 /*
17  * =====================
18  * OPTIONS-RELATED STUFF
19  * =====================
20  */
21 
22 #include <umodplayer.h>
23 #include <text.h>
24 #include <messages.h>
25 #include <file_read.h>
26 
27 /*
28  * Try to detect the local endianness
29  */
30 LOCAL Endian
DetectEndian()31 DetectEndian()
32 {
33 	union cio {
34 		uint16_t w;
35 		uint8_t b[2];
36 	} d;
37 
38 	d.w = 0xCAFE;
39 
40 	if (d.b[0] == 0xCA && d.b[1] == 0xFE) {
41 		return BIG_ENDIAN;
42 	} else if (d.b[0] == 0xFE && d.b[1] == 0xCA) {
43 		return LTE_ENDIAN;
44 	} else {
45 		fputs(">>> WARNING: CAN'T detect local endianness!\n", stderr);
46 		fputs(">>>  Please set it manually with the `setadvanced' command\n", stderr);
47 		return UNKNOWN_ENDIAN;
48 	}
49 
50 	/* NOTREACHED */
51 	return UNKNOWN_ENDIAN;
52 }
53 
54 EXPORT void
DefaultOptions(struct oFlags * ops)55 DefaultOptions(struct oFlags * ops)
56 {
57 	ops->samplerate = DEFAULT_SAMPLERATE;
58 	ops->flags = MODPLUG_ENABLE_OVERSAMPLING;
59 	ops->resampling = MODPLUG_RESAMPLE_SPLINE;
60 	ops->vol = 128;
61 	ops->channels = 2;
62 	ops->reverbDepth = 20;
63 	ops->reverbDelay = 60;
64 	ops->bassAmount = 40;
65 	ops->bassRange = 50;
66 	ops->surroundDepth = 50;
67 	ops->surroundDelay = 20;
68 	ops->appareance = TABLE_THEME_CLASSIC;
69 	ops->endianness = DetectEndian();
70 	ops->verbosity = 1;
71 	return;
72 }
73 
74 EXPORT void
InitOptions(struct oFlags * ops)75 InitOptions(struct oFlags * ops)
76 {
77 	char *path, *home;
78 	int fd, bytes_in, dodefaults = 1;
79 
80 	home = getenv("HOME");
81 	if (home != NULL) {
82 		path = (char *) malloc(strlen(home) + strlen(PREFS_FILE) + 2);
83 		if (path == NULL) {
84 			error("%s", MESSAGE_NO_MEMORY);
85 			UFreeFile();
86 			exit(UM_ERR_MEMORY);
87 		}
88 		strcpy(path, home);
89 		strcat(path, "/");
90 		strcat(path, PREFS_FILE);
91 
92 		fd = open(path, O_RDONLY);
93 		if (fd != -1) {
94 			bytes_in = read(fd, ops, sizeof(struct oFlags));
95 			if (bytes_in == sizeof(struct oFlags))
96 				dodefaults = 0;
97 			close(fd);
98 		}
99 		free(path);
100 	}
101 	if (dodefaults == 1) {
102 		DefaultOptions(ops);
103 	}
104 	return;
105 }
106 
107 EXPORT void
SaveOptions(struct oFlags * ops)108 SaveOptions(struct oFlags * ops)
109 {
110 	char *path, *home;
111 	int fd;
112 
113 	home = getenv("HOME");
114 	if (home != NULL) {
115 		path = (char *) malloc(strlen(home) + strlen(PREFS_FILE) + 2);
116 		if (path == NULL) {
117 			error("%s", MESSAGE_NO_MEMORY);
118 			UFreeFile();
119 			exit(UM_ERR_MEMORY);
120 		}
121 		strcpy(path, home);
122 		strcat(path, "/");
123 		strcat(path, PREFS_FILE);
124 
125 		fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0600);
126 		if (fd != -1) {
127 			(void) write(fd, ops, sizeof(struct oFlags));
128 			close(fd);
129 		}
130 		free(path);
131 	}
132 	return;
133 }
134 
135 EXPORT void
AdvancedConfig()136 AdvancedConfig()
137 {
138 	static char vbuf[4];
139 	WTable table;
140 	int i;
141 
142 	rr = (char **) malloc(9 * sizeof(char *));
143 	rr[0] = (char *) malloc(8);
144 	sprintf(rr[0], "%d", sets.reverbDepth);
145 	rr[1] = (char *) malloc(8);
146 	sprintf(rr[1], "%d ms", sets.reverbDelay);
147 	rr[2] = (char *) malloc(8);
148 	sprintf(rr[2], "%d", sets.bassAmount);
149 	rr[3] = (char *) malloc(8);
150 	sprintf(rr[3], "%d Hz", sets.bassRange);
151 	rr[4] = (char *) malloc(8);
152 	sprintf(rr[4], "%d", sets.surroundDepth);
153 	rr[5] = (char *) malloc(16);
154 	sprintf(rr[5], "%d ms", sets.surroundDelay);
155 
156 	if (sets.endianness == BIG_ENDIAN) {
157 		rr[6] = "big-endian";
158 	} else if (sets.endianness == LTE_ENDIAN) {
159 		rr[6] = "little-endian";
160 	} else {
161 		rr[6] = "unknown!";
162 	}
163 
164 	if (sets.appareance == TABLE_THEME_CLASSIC) {
165 		rr[7] = "classic";
166 	} else if (sets.appareance == TABLE_THEME_STRONG) {
167 		rr[7] = "strong";
168 	} else {
169 		rr[7] = "boxed";
170 	}
171 
172 	snprintf(vbuf, 4, "%d", sets.verbosity);
173 	rr[8] = vbuf;
174 
175 	TableSetOptions(&table, 2, 9, 2, 16, 0, TABLE_LEFT_ALIGN);
176 	TableInitCallback(&table, MyTextCallback);
177 	TableUseTheme(&table, sets.appareance);
178 	DrawTable(table);
179 
180 	for (i = 0; i < 6; ++i)
181 		free(rr[i]);
182 	free(rr);
183 
184 	return;
185 }
186 
187 LOCAL void
AskUserForData(const char * str,int minvalue,int maxvalue,int * putdata)188 AskUserForData(const char *str, int minvalue, int maxvalue, int *putdata)
189 {
190 	char *e;
191 	int k;
192 
193 	for (;;) {
194 		fputs(str, stdout);
195 		fflush(stdout);
196 		e = ReadString();
197 		if (e == NULL) {
198 			error("%s", MESSAGE_NO_MEMORY);
199 			return;
200 		}
201 		TrimString(e);
202 		if (*e == 0)
203 			return;
204 		k = atoi(e);
205 		free(e);
206 		if (k < minvalue || k > maxvalue) {
207 			continue;
208 		}
209 		*putdata = k;
210 		break;
211 	}
212 
213 	return;
214 }
215 
216 EXPORT void
SetAdvancedConfig()217 SetAdvancedConfig()
218 {
219 	char *response;
220 
221 	AskUserForData("Reverb Depth [0-100]? ", 0, 100, &(sets.reverbDepth));
222 	AskUserForData("Reverb Delay in ms. [40-200]? ", 40, 200, &(sets.reverbDelay));
223 	AskUserForData("Bass Amount [0-100]? ", 0, 100, &(sets.bassAmount));
224 	AskUserForData("Bass Range in Hz. [10-100]? ", 10, 100, &(sets.bassRange));
225 	AskUserForData("Surround Depth [0-100]? ", 0, 100, &(sets.surroundDepth));
226 	AskUserForData("Surround Delay in ms. [5-40]? ", 5, 40, &(sets.surroundDelay));
227 
228 endian1:
229 	fputs("local endianness [little-endian, big-endian]? ", stdout);
230 	fflush(stdout);
231 	response = ReadString();
232 	if (response == NULL) {
233 		error("%s", MESSAGE_NO_MEMORY);
234 	} else if (*response == '\0') {
235 		/*
236 		 * skip to the next question
237 		 */
238 		free(response);
239 		goto appareance1;
240 	} else {
241 		/*
242 		 * Use memcmp() instead of strcmp()
243 		 * to match only the beginning of the string.
244 		 *
245 		 * I.e., any string starting with "little" will match
246 		 * little-endian, no matter if its "little-endian", "littleendian",
247 		 * "little", or whatever.
248 		 */
249 		if (memcmp(response, "little", 6) == 0) {
250 			sets.endianness = LTE_ENDIAN;
251 		} else if (memcmp(response, "big", 3) == 0) {
252 			sets.endianness = BIG_ENDIAN;
253 		} else {
254 			free(response);
255 			goto endian1; /* ask again until a valid response is found! */
256 		}
257 
258 		free(response);
259 	}
260 
261 appareance1:
262 	fputs("appareance [classic, strong, boxed]? ", stdout);
263 	fflush(stdout);
264 	response = ReadString();
265 	if (response == NULL) {
266 		error("%s", MESSAGE_NO_MEMORY);
267 	} else if (*response == '\0') {
268 		/*
269 		 * skip to the next question
270 		 */
271 		free(response);
272 		goto end;
273 	} else {
274 		if (strcmp(response, "classic") == 0) {
275 			sets.appareance = TABLE_THEME_CLASSIC;
276 		} else if (strcmp(response, "strong") == 0) {
277 			sets.appareance = TABLE_THEME_STRONG;
278 		} else if (strcmp(response, "boxed") == 0) {
279 			sets.appareance = TABLE_THEME_BOXED;
280 		} else {
281 			free(response);
282 			goto appareance1;
283 		}
284 
285 		free(response);
286 	}
287 
288 end:
289 
290 	AskUserForData("verbosity level? ", 0, 3, &(sets.verbosity));
291 }
292