Add a ptr-to-int map
[openal-soft.git] / router / router.c
blob7bbdfa8e652fe5212105a07aa80098649e4dc813
2 #include "config.h"
4 #include "router.h"
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
10 #include "AL/alc.h"
11 #include "AL/al.h"
14 DriverIface *DriverList = NULL;
15 int DriverListSize = 0;
16 static int DriverListSizeMax = 0;
18 static void LoadDriverList(void);
21 BOOL APIENTRY DllMain(HINSTANCE module, DWORD reason, void *reserved)
23 int i;
25 switch(reason)
27 case DLL_PROCESS_ATTACH:
28 LoadDriverList();
29 break;
31 case DLL_THREAD_ATTACH:
32 case DLL_THREAD_DETACH:
33 break;
35 case DLL_PROCESS_DETACH:
36 for(i = 0;i < DriverListSize;i++)
38 if(DriverList[i].Module)
39 FreeLibrary(DriverList[i].Module);
41 free(DriverList);
42 DriverList = NULL;
43 DriverListSize = 0;
44 DriverListSizeMax = 0;
45 break;
47 return TRUE;
51 #ifdef __GNUC__
52 #define CAST_FUNC(x) (__typeof(x))
53 #else
54 #define CAST_FUNC(x) (void*)
55 #endif
57 static void AddModule(HMODULE module, const WCHAR *name)
59 int err = 0;
60 int i;
62 for(i = 0;i < DriverListSize;i++)
64 if(DriverList[i].Module == module || wcscmp(DriverList[i].Name, name) == 0)
66 FreeLibrary(module);
67 return;
71 if(DriverListSize == DriverListSizeMax)
73 int newmax = DriverListSizeMax ? DriverListSizeMax<<1 : 4;
74 void *newlist = calloc(sizeof(DriverList[0]), newmax);
75 if(!newlist) return;
77 memcpy(newlist, DriverList, DriverListSize*sizeof(DriverList[0]));
78 free(DriverList);
79 DriverList = newlist;
80 DriverListSizeMax = newmax;
83 #define LOAD_PROC(x) do { \
84 DriverList[DriverListSize].x = CAST_FUNC(DriverList[DriverListSize].x) \
85 GetProcAddress(module, #x); \
86 if(!DriverList[DriverListSize].x) \
87 { \
88 fprintf(stderr, "Failed to find entry point for %s in %ls\n", \
89 #x, name); \
90 err = 1; \
91 } \
92 } while(0)
93 LOAD_PROC(alcCreateContext);
94 LOAD_PROC(alcMakeContextCurrent);
95 LOAD_PROC(alcProcessContext);
96 LOAD_PROC(alcSuspendContext);
97 LOAD_PROC(alcDestroyContext);
98 LOAD_PROC(alcGetCurrentContext);
99 LOAD_PROC(alcGetContextsDevice);
100 LOAD_PROC(alcOpenDevice);
101 LOAD_PROC(alcCloseDevice);
102 LOAD_PROC(alcGetError);
103 LOAD_PROC(alcIsExtensionPresent);
104 LOAD_PROC(alcGetProcAddress);
105 LOAD_PROC(alcGetEnumValue);
106 LOAD_PROC(alcGetString);
107 LOAD_PROC(alcGetIntegerv);
108 LOAD_PROC(alcCaptureOpenDevice);
109 LOAD_PROC(alcCaptureCloseDevice);
110 LOAD_PROC(alcCaptureStart);
111 LOAD_PROC(alcCaptureStop);
112 LOAD_PROC(alcCaptureSamples);
114 LOAD_PROC(alEnable);
115 LOAD_PROC(alDisable);
116 LOAD_PROC(alIsEnabled);
117 LOAD_PROC(alGetString);
118 LOAD_PROC(alGetBooleanv);
119 LOAD_PROC(alGetIntegerv);
120 LOAD_PROC(alGetFloatv);
121 LOAD_PROC(alGetDoublev);
122 LOAD_PROC(alGetBoolean);
123 LOAD_PROC(alGetInteger);
124 LOAD_PROC(alGetFloat);
125 LOAD_PROC(alGetDouble);
126 LOAD_PROC(alGetError);
127 LOAD_PROC(alIsExtensionPresent);
128 LOAD_PROC(alGetProcAddress);
129 LOAD_PROC(alGetEnumValue);
130 LOAD_PROC(alListenerf);
131 LOAD_PROC(alListener3f);
132 LOAD_PROC(alListenerfv);
133 LOAD_PROC(alListeneri);
134 LOAD_PROC(alListener3i);
135 LOAD_PROC(alListeneriv);
136 LOAD_PROC(alGetListenerf);
137 LOAD_PROC(alGetListener3f);
138 LOAD_PROC(alGetListenerfv);
139 LOAD_PROC(alGetListeneri);
140 LOAD_PROC(alGetListener3i);
141 LOAD_PROC(alGetListeneriv);
142 LOAD_PROC(alGenSources);
143 LOAD_PROC(alDeleteSources);
144 LOAD_PROC(alIsSource);
145 LOAD_PROC(alSourcef);
146 LOAD_PROC(alSource3f);
147 LOAD_PROC(alSourcefv);
148 LOAD_PROC(alSourcei);
149 LOAD_PROC(alSource3i);
150 LOAD_PROC(alSourceiv);
151 LOAD_PROC(alGetSourcef);
152 LOAD_PROC(alGetSource3f);
153 LOAD_PROC(alGetSourcefv);
154 LOAD_PROC(alGetSourcei);
155 LOAD_PROC(alGetSource3i);
156 LOAD_PROC(alGetSourceiv);
157 LOAD_PROC(alSourcePlayv);
158 LOAD_PROC(alSourceStopv);
159 LOAD_PROC(alSourceRewindv);
160 LOAD_PROC(alSourcePausev);
161 LOAD_PROC(alSourcePlay);
162 LOAD_PROC(alSourceStop);
163 LOAD_PROC(alSourceRewind);
164 LOAD_PROC(alSourcePause);
165 LOAD_PROC(alSourceQueueBuffers);
166 LOAD_PROC(alSourceUnqueueBuffers);
167 LOAD_PROC(alGenBuffers);
168 LOAD_PROC(alDeleteBuffers);
169 LOAD_PROC(alIsBuffer);
170 LOAD_PROC(alBufferf);
171 LOAD_PROC(alBuffer3f);
172 LOAD_PROC(alBufferfv);
173 LOAD_PROC(alBufferi);
174 LOAD_PROC(alBuffer3i);
175 LOAD_PROC(alBufferiv);
176 LOAD_PROC(alGetBufferf);
177 LOAD_PROC(alGetBuffer3f);
178 LOAD_PROC(alGetBufferfv);
179 LOAD_PROC(alGetBufferi);
180 LOAD_PROC(alGetBuffer3i);
181 LOAD_PROC(alGetBufferiv);
182 LOAD_PROC(alBufferData);
183 LOAD_PROC(alDopplerFactor);
184 LOAD_PROC(alDopplerVelocity);
185 LOAD_PROC(alSpeedOfSound);
186 LOAD_PROC(alDistanceModel);
187 if(!err)
189 wcsncpy(DriverList[DriverListSize].Name, name, 32);
190 DriverList[DriverListSize++].Module = module;
194 static void SearchDrivers(WCHAR *path)
196 WCHAR srchPath[MAX_PATH+1] = L"";
197 WIN32_FIND_DATAW fdata;
198 HANDLE srchHdl;
200 wcsncpy(srchPath, path, MAX_PATH);
201 wcsncat(srchPath, L"\\*oal.dll", MAX_PATH - lstrlenW(srchPath));
202 srchHdl = FindFirstFileW(srchPath, &fdata);
203 if(srchHdl != INVALID_HANDLE_VALUE)
205 do {
206 HMODULE mod;
208 wcsncpy(srchPath, path, MAX_PATH);
209 wcsncat(srchPath, L"\\", MAX_PATH - lstrlenW(srchPath));
210 wcsncat(srchPath, fdata.cFileName, MAX_PATH - lstrlenW(srchPath));
212 mod = LoadLibraryW(srchPath);
213 if(mod) AddModule(mod, fdata.cFileName);
214 } while(FindNextFileW(srchHdl, &fdata));
215 FindClose(srchHdl);
219 static WCHAR *strrchrW(WCHAR *str, WCHAR ch)
221 WCHAR *res = NULL;
222 while(str && *str != '\0')
224 if(*str == ch)
225 res = str;
226 ++str;
228 return res;
231 static int GetLoadedModuleDirectory(const WCHAR *name, WCHAR *moddir, DWORD length)
233 HMODULE module = NULL;
234 WCHAR *sep0, *sep1;
236 if(name)
238 module = GetModuleHandleW(name);
239 if(!module) return 0;
242 if(GetModuleFileNameW(module, moddir, length) == 0)
243 return 0;
245 sep0 = strrchrW(moddir, '/');
246 if(sep0) sep1 = strrchrW(sep0+1, '\\');
247 else sep1 = strrchrW(moddir, '\\');
249 if(sep1) *sep1 = '\0';
250 else if(sep0) *sep0 = '\0';
251 else *moddir = '\0';
253 return 1;
256 void LoadDriverList(void)
258 WCHAR path[MAX_PATH+1] = L"";
259 int len;
261 if(GetLoadedModuleDirectory(L"OpenAL32.dll", path, MAX_PATH))
262 SearchDrivers(path);
264 GetCurrentDirectoryW(MAX_PATH, path);
265 len = lstrlenW(path);
266 if(len > 0 && (path[len-1] == '\\' || path[len-1] == '/'))
267 path[len-1] = '\0';
268 SearchDrivers(path);
270 if(GetLoadedModuleDirectory(NULL, path, MAX_PATH))
271 SearchDrivers(path);
273 GetSystemDirectoryW(path, MAX_PATH);
274 len = lstrlenW(path);
275 if(len > 0 && (path[len-1] == '\\' || path[len-1] == '/'))
276 path[len-1] = '\0';
277 SearchDrivers(path);
281 void InitPtrIntMap(PtrIntMap *map)
283 map->keys = NULL;
284 map->values = NULL;
285 map->size = 0;
286 map->capacity = 0;
287 RWLockInit(&map->lock);
290 void ResetPtrIntMap(PtrIntMap *map)
292 WriteLock(&map->lock);
293 free(map->keys);
294 map->keys = NULL;
295 map->values = NULL;
296 map->size = 0;
297 map->capacity = 0;
298 WriteUnlock(&map->lock);
301 ALenum InsertPtrIntMapEntry(PtrIntMap *map, ALvoid *key, ALint value)
303 ALsizei pos = 0;
305 WriteLock(&map->lock);
306 if(map->size > 0)
308 ALsizei count = map->size;
309 do {
310 ALsizei step = count>>1;
311 ALsizei i = pos+step;
312 if(!(map->keys[i] < key))
313 count = step;
314 else
316 pos = i+1;
317 count -= step+1;
319 } while(count > 0);
322 if(pos == map->size || map->keys[pos] != key)
324 if(map->size == map->capacity)
326 ALvoid **keys = NULL;
327 ALint *values;
328 ALsizei newcap;
330 newcap = (map->capacity ? (map->capacity<<1) : 4);
331 if(newcap > map->capacity)
332 keys = calloc(sizeof(map->keys[0])+sizeof(map->values[0]), newcap);
333 if(!keys)
335 WriteUnlock(&map->lock);
336 return AL_OUT_OF_MEMORY;
338 values = (ALint*)&keys[newcap];
340 if(map->keys)
342 memcpy(keys, map->keys, map->size*sizeof(map->keys[0]));
343 memcpy(values, map->values, map->size*sizeof(map->values[0]));
345 free(map->keys);
346 map->keys = keys;
347 map->values = values;
348 map->capacity = newcap;
351 if(pos < map->size)
353 memmove(&map->keys[pos+1], &map->keys[pos],
354 (map->size-pos)*sizeof(map->keys[0]));
355 memmove(&map->values[pos+1], &map->values[pos],
356 (map->size-pos)*sizeof(map->values[0]));
358 map->size++;
360 map->keys[pos] = key;
361 map->values[pos] = value;
362 WriteUnlock(&map->lock);
364 return AL_NO_ERROR;
367 ALint RemovePtrIntMapKey(PtrIntMap *map, ALvoid *key)
369 ALint ret = -1;
370 WriteLock(&map->lock);
371 if(map->size > 0)
373 ALsizei pos = 0;
374 ALsizei count = map->size;
375 do {
376 ALsizei step = count>>1;
377 ALsizei i = pos+step;
378 if(!(map->keys[i] < key))
379 count = step;
380 else
382 pos = i+1;
383 count -= step+1;
385 } while(count > 0);
386 if(pos < map->size && map->keys[pos] == key)
388 ret = map->values[pos];
389 if(pos < map->size-1)
391 memmove(&map->keys[pos], &map->keys[pos+1],
392 (map->size-1-pos)*sizeof(map->keys[0]));
393 memmove(&map->values[pos], &map->values[pos+1],
394 (map->size-1-pos)*sizeof(map->values[0]));
396 map->size--;
399 WriteUnlock(&map->lock);
400 return ret;
403 ALint LookupPtrIntMapKey(PtrIntMap *map, ALvoid *key)
405 ALint ret = -1;
406 ReadLock(&map->lock);
407 if(map->size > 0)
409 ALsizei pos = 0;
410 ALsizei count = map->size;
411 do {
412 ALsizei step = count>>1;
413 ALsizei i = pos+step;
414 if(!(map->keys[i] < key))
415 count = step;
416 else
418 pos = i+1;
419 count -= step+1;
421 } while(count > 0);
422 if(pos < map->size && map->keys[pos] == key)
423 ret = map->values[pos];
425 ReadUnlock(&map->lock);
426 return ret;