Modify some context checks
[openal-soft.git] / Alc / alcConfig.c
blobb6e4613964769e61b7f399c469c50e1616b14098
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #ifdef _WIN32
22 #define _WIN32_IE 0x400
23 #endif
25 #include "config.h"
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <ctype.h>
30 #include <string.h>
32 #include "alMain.h"
34 #ifdef _WIN32_IE
35 #include <shlobj.h>
36 #endif
38 typedef struct ConfigEntry {
39 char *key;
40 char *value;
41 } ConfigEntry;
43 typedef struct ConfigBlock {
44 char *name;
45 ConfigEntry *entries;
46 size_t entryCount;
47 } ConfigBlock;
49 static ConfigBlock *cfgBlocks;
50 static size_t cfgCount;
52 static char buffer[1024];
54 static void LoadConfigFromFile(FILE *f)
56 ConfigBlock *curBlock = cfgBlocks;
57 ConfigEntry *ent;
59 while(fgets(buffer, sizeof(buffer), f))
61 size_t i = 0;
63 while(isspace(buffer[i]))
64 i++;
65 if(!buffer[i] || buffer[i] == '#')
66 continue;
68 memmove(buffer, buffer+i, strlen(buffer+i)+1);
70 if(buffer[0] == '[')
72 ConfigBlock *nextBlock;
74 i = 1;
75 while(buffer[i] && buffer[i] != ']')
76 i++;
78 if(!buffer[i])
80 AL_PRINT("config parse error: bad line \"%s\"\n", buffer);
81 continue;
83 buffer[i] = 0;
85 do {
86 i++;
87 if(buffer[i] && !isspace(buffer[i]))
89 if(buffer[i] != '#')
90 AL_PRINT("config warning: extra data after block: \"%s\"\n", buffer+i);
91 break;
93 } while(buffer[i]);
95 nextBlock = NULL;
96 for(i = 0;i < cfgCount;i++)
98 if(strcasecmp(cfgBlocks[i].name, buffer+1) == 0)
100 nextBlock = cfgBlocks+i;
101 // AL_PRINT("found block '%s'\n", nextBlock->name);
102 break;
106 if(!nextBlock)
108 nextBlock = realloc(cfgBlocks, (cfgCount+1)*sizeof(ConfigBlock));
109 if(!nextBlock)
111 AL_PRINT("config parse error: error reallocating config blocks\n");
112 continue;
114 cfgBlocks = nextBlock;
115 nextBlock = cfgBlocks+cfgCount;
116 cfgCount++;
118 nextBlock->name = strdup(buffer+1);
119 nextBlock->entries = NULL;
120 nextBlock->entryCount = 0;
122 // AL_PRINT("found new block '%s'\n", nextBlock->name);
124 curBlock = nextBlock;
125 continue;
128 /* Look for the option name */
129 i = 0;
130 while(buffer[i] && buffer[i] != '#' && buffer[i] != '=' &&
131 !isspace(buffer[i]))
132 i++;
134 if(!buffer[i] || buffer[i] == '#' || i == 0)
136 AL_PRINT("config parse error: malformed option line: \"%s\"\n", buffer);
137 continue;
140 /* Seperate the option */
141 if(buffer[i] != '=')
143 buffer[i++] = 0;
145 while(isspace(buffer[i]))
146 i++;
147 if(buffer[i] != '=')
149 AL_PRINT("config parse error: option without a value: \"%s\"\n", buffer);
150 continue;
153 /* Find the start of the value */
154 buffer[i++] = 0;
155 while(isspace(buffer[i]))
156 i++;
158 /* Check if we already have this option set */
159 ent = curBlock->entries;
160 while((size_t)(ent-curBlock->entries) < curBlock->entryCount)
162 if(strcasecmp(ent->key, buffer) == 0)
163 break;
164 ent++;
167 if((size_t)(ent-curBlock->entries) >= curBlock->entryCount)
169 /* Allocate a new option entry */
170 ent = realloc(curBlock->entries, (curBlock->entryCount+1)*sizeof(ConfigEntry));
171 if(!ent)
173 AL_PRINT("config parse error: error reallocating config entries\n");
174 continue;
176 curBlock->entries = ent;
177 ent = curBlock->entries + curBlock->entryCount;
178 curBlock->entryCount++;
180 ent->key = strdup(buffer);
181 ent->value = NULL;
184 /* Look for the end of the line (Null term, new-line, or #-symbol) and
185 eat up the trailing whitespace */
186 memmove(buffer, buffer+i, strlen(buffer+i)+1);
188 i = 0;
189 while(buffer[i] && buffer[i] != '#' && buffer[i] != '\n')
190 i++;
191 do {
192 i--;
193 } while(isspace(buffer[i]));
194 buffer[++i] = 0;
196 free(ent->value);
197 ent->value = strdup(buffer);
199 // AL_PRINT("found '%s' = '%s'\n", ent->key, ent->value);
203 void ReadALConfig(void)
205 FILE *f;
207 cfgBlocks = calloc(1, sizeof(ConfigBlock));
208 cfgBlocks->name = strdup("general");
209 cfgCount = 1;
211 #ifdef _WIN32
212 if(SHGetSpecialFolderPathA(NULL, buffer, CSIDL_APPDATA, FALSE) != FALSE)
214 int p = strlen(buffer);
215 snprintf(buffer+p, sizeof(buffer)-p, "\\alsoft.ini");
216 f = fopen(buffer, "rt");
217 if(f)
219 LoadConfigFromFile(f);
220 fclose(f);
223 #else
224 f = fopen("/etc/openal/alsoft.conf", "r");
225 if(f)
227 LoadConfigFromFile(f);
228 fclose(f);
230 if(getenv("HOME") && *(getenv("HOME")))
232 snprintf(buffer, sizeof(buffer), "%s/.alsoftrc", getenv("HOME"));
233 f = fopen(buffer, "r");
234 if(f)
236 LoadConfigFromFile(f);
237 fclose(f);
240 #endif
241 if(getenv("ALSOFT_CONF"))
243 f = fopen(getenv("ALSOFT_CONF"), "r");
244 if(f)
246 LoadConfigFromFile(f);
247 fclose(f);
252 void FreeALConfig(void)
254 size_t i;
256 for(i = 0;i < cfgCount;i++)
258 size_t j;
259 for(j = 0;j < cfgBlocks[i].entryCount;j++)
261 free(cfgBlocks[i].entries[j].key);
262 free(cfgBlocks[i].entries[j].value);
264 free(cfgBlocks[i].entries);
265 free(cfgBlocks[i].name);
267 free(cfgBlocks);
268 cfgBlocks = NULL;
269 cfgCount = 0;
272 const char *GetConfigValue(const char *blockName, const char *keyName, const char *def)
274 size_t i, j;
276 if(keyName)
278 if(!blockName)
279 blockName = "general";
281 for(i = 0;i < cfgCount;i++)
283 if(strcasecmp(cfgBlocks[i].name, blockName) != 0)
284 continue;
286 for(j = 0;j < cfgBlocks[i].entryCount;j++)
288 if(strcasecmp(cfgBlocks[i].entries[j].key, keyName) == 0)
289 return cfgBlocks[i].entries[j].value;
294 return def;
297 int GetConfigValueInt(const char *blockName, const char *keyName, int def)
299 const char *val = GetConfigValue(blockName, keyName, "");
301 if(!val[0]) return def;
302 return strtol(val, NULL, 0);
305 float GetConfigValueFloat(const char *blockName, const char *keyName, float def)
307 const char *val = GetConfigValue(blockName, keyName, "");
309 if(!val[0]) return def;
310 #ifdef HAVE_STRTOF
311 return strtof(val, NULL);
312 #else
313 return (float)strtod(val, NULL);
314 #endif