router.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. #include "config.h"
  2. #include "router.h"
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "AL/alc.h"
  7. #include "AL/al.h"
  8. #include "almalloc.h"
  9. #include "version.h"
  10. DriverIface *DriverList = NULL;
  11. int DriverListSize = 0;
  12. static int DriverListSizeMax = 0;
  13. altss_t ThreadCtxDriver;
  14. enum LogLevel LogLevel = LogLevel_Error;
  15. FILE *LogFile;
  16. static void LoadDriverList(void);
  17. BOOL APIENTRY DllMain(HINSTANCE UNUSED(module), DWORD reason, void* UNUSED(reserved))
  18. {
  19. const char *str;
  20. int i;
  21. switch(reason)
  22. {
  23. case DLL_PROCESS_ATTACH:
  24. LogFile = stderr;
  25. str = getenv("ALROUTER_LOGFILE");
  26. if(str && *str != '\0')
  27. {
  28. FILE *f = fopen(str, "w");
  29. if(f == NULL)
  30. ERR("Could not open log file: %s\n", str);
  31. else
  32. LogFile = f;
  33. }
  34. str = getenv("ALROUTER_LOGLEVEL");
  35. if(str && *str != '\0')
  36. {
  37. char *end = NULL;
  38. long l = strtol(str, &end, 0);
  39. if(!end || *end != '\0')
  40. ERR("Invalid log level value: %s\n", str);
  41. else if(l < LogLevel_None || l > LogLevel_Trace)
  42. ERR("Log level out of range: %s\n", str);
  43. else
  44. LogLevel = l;
  45. }
  46. TRACE("Initializing router v0.1-%s %s\n", ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
  47. LoadDriverList();
  48. altss_create(&ThreadCtxDriver, NULL);
  49. InitALC();
  50. break;
  51. case DLL_THREAD_ATTACH:
  52. break;
  53. case DLL_THREAD_DETACH:
  54. althrd_thread_detach();
  55. break;
  56. case DLL_PROCESS_DETACH:
  57. ReleaseALC();
  58. altss_delete(ThreadCtxDriver);
  59. for(i = 0;i < DriverListSize;i++)
  60. {
  61. if(DriverList[i].Module)
  62. FreeLibrary(DriverList[i].Module);
  63. }
  64. al_free(DriverList);
  65. DriverList = NULL;
  66. DriverListSize = 0;
  67. DriverListSizeMax = 0;
  68. if(LogFile && LogFile != stderr)
  69. fclose(LogFile);
  70. LogFile = NULL;
  71. althrd_deinit();
  72. break;
  73. }
  74. return TRUE;
  75. }
  76. #ifdef __GNUC__
  77. #define CAST_FUNC(x) (__typeof(x))
  78. #else
  79. #define CAST_FUNC(x) (void*)
  80. #endif
  81. static void AddModule(HMODULE module, const WCHAR *name)
  82. {
  83. DriverIface newdrv;
  84. int err = 0;
  85. int i;
  86. for(i = 0;i < DriverListSize;i++)
  87. {
  88. if(DriverList[i].Module == module)
  89. {
  90. TRACE("Skipping already-loaded module %p\n", module);
  91. FreeLibrary(module);
  92. return;
  93. }
  94. if(wcscmp(DriverList[i].Name, name) == 0)
  95. {
  96. TRACE("Skipping similarly-named module %ls\n", name);
  97. FreeLibrary(module);
  98. return;
  99. }
  100. }
  101. if(DriverListSize == DriverListSizeMax)
  102. {
  103. int newmax = DriverListSizeMax ? DriverListSizeMax<<1 : 4;
  104. void *newlist = al_calloc(DEF_ALIGN, sizeof(DriverList[0])*newmax);
  105. if(!newlist) return;
  106. memcpy(newlist, DriverList, DriverListSize*sizeof(DriverList[0]));
  107. al_free(DriverList);
  108. DriverList = newlist;
  109. DriverListSizeMax = newmax;
  110. }
  111. memset(&newdrv, 0, sizeof(newdrv));
  112. /* Load required functions. */
  113. #define LOAD_PROC(x) do { \
  114. newdrv.x = CAST_FUNC(newdrv.x) GetProcAddress(module, #x); \
  115. if(!newdrv.x) \
  116. { \
  117. ERR("Failed to find entry point for %s in %ls\n", #x, name); \
  118. err = 1; \
  119. } \
  120. } while(0)
  121. LOAD_PROC(alcCreateContext);
  122. LOAD_PROC(alcMakeContextCurrent);
  123. LOAD_PROC(alcProcessContext);
  124. LOAD_PROC(alcSuspendContext);
  125. LOAD_PROC(alcDestroyContext);
  126. LOAD_PROC(alcGetCurrentContext);
  127. LOAD_PROC(alcGetContextsDevice);
  128. LOAD_PROC(alcOpenDevice);
  129. LOAD_PROC(alcCloseDevice);
  130. LOAD_PROC(alcGetError);
  131. LOAD_PROC(alcIsExtensionPresent);
  132. LOAD_PROC(alcGetProcAddress);
  133. LOAD_PROC(alcGetEnumValue);
  134. LOAD_PROC(alcGetString);
  135. LOAD_PROC(alcGetIntegerv);
  136. LOAD_PROC(alcCaptureOpenDevice);
  137. LOAD_PROC(alcCaptureCloseDevice);
  138. LOAD_PROC(alcCaptureStart);
  139. LOAD_PROC(alcCaptureStop);
  140. LOAD_PROC(alcCaptureSamples);
  141. LOAD_PROC(alEnable);
  142. LOAD_PROC(alDisable);
  143. LOAD_PROC(alIsEnabled);
  144. LOAD_PROC(alGetString);
  145. LOAD_PROC(alGetBooleanv);
  146. LOAD_PROC(alGetIntegerv);
  147. LOAD_PROC(alGetFloatv);
  148. LOAD_PROC(alGetDoublev);
  149. LOAD_PROC(alGetBoolean);
  150. LOAD_PROC(alGetInteger);
  151. LOAD_PROC(alGetFloat);
  152. LOAD_PROC(alGetDouble);
  153. LOAD_PROC(alGetError);
  154. LOAD_PROC(alIsExtensionPresent);
  155. LOAD_PROC(alGetProcAddress);
  156. LOAD_PROC(alGetEnumValue);
  157. LOAD_PROC(alListenerf);
  158. LOAD_PROC(alListener3f);
  159. LOAD_PROC(alListenerfv);
  160. LOAD_PROC(alListeneri);
  161. LOAD_PROC(alListener3i);
  162. LOAD_PROC(alListeneriv);
  163. LOAD_PROC(alGetListenerf);
  164. LOAD_PROC(alGetListener3f);
  165. LOAD_PROC(alGetListenerfv);
  166. LOAD_PROC(alGetListeneri);
  167. LOAD_PROC(alGetListener3i);
  168. LOAD_PROC(alGetListeneriv);
  169. LOAD_PROC(alGenSources);
  170. LOAD_PROC(alDeleteSources);
  171. LOAD_PROC(alIsSource);
  172. LOAD_PROC(alSourcef);
  173. LOAD_PROC(alSource3f);
  174. LOAD_PROC(alSourcefv);
  175. LOAD_PROC(alSourcei);
  176. LOAD_PROC(alSource3i);
  177. LOAD_PROC(alSourceiv);
  178. LOAD_PROC(alGetSourcef);
  179. LOAD_PROC(alGetSource3f);
  180. LOAD_PROC(alGetSourcefv);
  181. LOAD_PROC(alGetSourcei);
  182. LOAD_PROC(alGetSource3i);
  183. LOAD_PROC(alGetSourceiv);
  184. LOAD_PROC(alSourcePlayv);
  185. LOAD_PROC(alSourceStopv);
  186. LOAD_PROC(alSourceRewindv);
  187. LOAD_PROC(alSourcePausev);
  188. LOAD_PROC(alSourcePlay);
  189. LOAD_PROC(alSourceStop);
  190. LOAD_PROC(alSourceRewind);
  191. LOAD_PROC(alSourcePause);
  192. LOAD_PROC(alSourceQueueBuffers);
  193. LOAD_PROC(alSourceUnqueueBuffers);
  194. LOAD_PROC(alGenBuffers);
  195. LOAD_PROC(alDeleteBuffers);
  196. LOAD_PROC(alIsBuffer);
  197. LOAD_PROC(alBufferf);
  198. LOAD_PROC(alBuffer3f);
  199. LOAD_PROC(alBufferfv);
  200. LOAD_PROC(alBufferi);
  201. LOAD_PROC(alBuffer3i);
  202. LOAD_PROC(alBufferiv);
  203. LOAD_PROC(alGetBufferf);
  204. LOAD_PROC(alGetBuffer3f);
  205. LOAD_PROC(alGetBufferfv);
  206. LOAD_PROC(alGetBufferi);
  207. LOAD_PROC(alGetBuffer3i);
  208. LOAD_PROC(alGetBufferiv);
  209. LOAD_PROC(alBufferData);
  210. LOAD_PROC(alDopplerFactor);
  211. LOAD_PROC(alDopplerVelocity);
  212. LOAD_PROC(alSpeedOfSound);
  213. LOAD_PROC(alDistanceModel);
  214. if(!err)
  215. {
  216. ALCint alc_ver[2] = { 0, 0 };
  217. wcsncpy(newdrv.Name, name, 32);
  218. newdrv.Module = module;
  219. newdrv.alcGetIntegerv(NULL, ALC_MAJOR_VERSION, 1, &alc_ver[0]);
  220. newdrv.alcGetIntegerv(NULL, ALC_MINOR_VERSION, 1, &alc_ver[1]);
  221. if(newdrv.alcGetError(NULL) == ALC_NO_ERROR)
  222. newdrv.ALCVer = MAKE_ALC_VER(alc_ver[0], alc_ver[1]);
  223. else
  224. newdrv.ALCVer = MAKE_ALC_VER(1, 0);
  225. #undef LOAD_PROC
  226. #define LOAD_PROC(x) do { \
  227. newdrv.x = CAST_FUNC(newdrv.x) newdrv.alcGetProcAddress(NULL, #x); \
  228. if(!newdrv.x) \
  229. { \
  230. ERR("Failed to find entry point for %s in %ls\n", #x, name); \
  231. err = 1; \
  232. } \
  233. } while(0)
  234. if(newdrv.alcIsExtensionPresent(NULL, "ALC_EXT_thread_local_context"))
  235. {
  236. LOAD_PROC(alcSetThreadContext);
  237. LOAD_PROC(alcGetThreadContext);
  238. }
  239. }
  240. if(!err)
  241. {
  242. TRACE("Loaded module %p, %ls, ALC %d.%d\n", module, name,
  243. newdrv.ALCVer>>8, newdrv.ALCVer&255);
  244. DriverList[DriverListSize++] = newdrv;
  245. }
  246. #undef LOAD_PROC
  247. }
  248. static void SearchDrivers(WCHAR *path)
  249. {
  250. WCHAR srchPath[MAX_PATH+1] = L"";
  251. WIN32_FIND_DATAW fdata;
  252. HANDLE srchHdl;
  253. TRACE("Searching for drivers in %ls...\n", path);
  254. wcsncpy(srchPath, path, MAX_PATH);
  255. wcsncat(srchPath, L"\\*oal.dll", MAX_PATH - lstrlenW(srchPath));
  256. srchHdl = FindFirstFileW(srchPath, &fdata);
  257. if(srchHdl != INVALID_HANDLE_VALUE)
  258. {
  259. do {
  260. HMODULE mod;
  261. wcsncpy(srchPath, path, MAX_PATH);
  262. wcsncat(srchPath, L"\\", MAX_PATH - lstrlenW(srchPath));
  263. wcsncat(srchPath, fdata.cFileName, MAX_PATH - lstrlenW(srchPath));
  264. TRACE("Found %ls\n", srchPath);
  265. mod = LoadLibraryW(srchPath);
  266. if(!mod)
  267. WARN("Could not load %ls\n", srchPath);
  268. else
  269. AddModule(mod, fdata.cFileName);
  270. } while(FindNextFileW(srchHdl, &fdata));
  271. FindClose(srchHdl);
  272. }
  273. }
  274. static WCHAR *strrchrW(WCHAR *str, WCHAR ch)
  275. {
  276. WCHAR *res = NULL;
  277. while(str && *str != '\0')
  278. {
  279. if(*str == ch)
  280. res = str;
  281. ++str;
  282. }
  283. return res;
  284. }
  285. static int GetLoadedModuleDirectory(const WCHAR *name, WCHAR *moddir, DWORD length)
  286. {
  287. HMODULE module = NULL;
  288. WCHAR *sep0, *sep1;
  289. if(name)
  290. {
  291. module = GetModuleHandleW(name);
  292. if(!module) return 0;
  293. }
  294. if(GetModuleFileNameW(module, moddir, length) == 0)
  295. return 0;
  296. sep0 = strrchrW(moddir, '/');
  297. if(sep0) sep1 = strrchrW(sep0+1, '\\');
  298. else sep1 = strrchrW(moddir, '\\');
  299. if(sep1) *sep1 = '\0';
  300. else if(sep0) *sep0 = '\0';
  301. else *moddir = '\0';
  302. return 1;
  303. }
  304. void LoadDriverList(void)
  305. {
  306. WCHAR dll_path[MAX_PATH+1] = L"";
  307. WCHAR cwd_path[MAX_PATH+1] = L"";
  308. WCHAR proc_path[MAX_PATH+1] = L"";
  309. WCHAR sys_path[MAX_PATH+1] = L"";
  310. int len;
  311. if(GetLoadedModuleDirectory(L"OpenAL32.dll", dll_path, MAX_PATH))
  312. TRACE("Got DLL path %ls\n", dll_path);
  313. GetCurrentDirectoryW(MAX_PATH, cwd_path);
  314. len = lstrlenW(cwd_path);
  315. if(len > 0 && (cwd_path[len-1] == '\\' || cwd_path[len-1] == '/'))
  316. cwd_path[len-1] = '\0';
  317. TRACE("Got current working directory %ls\n", cwd_path);
  318. if(GetLoadedModuleDirectory(NULL, proc_path, MAX_PATH))
  319. TRACE("Got proc path %ls\n", proc_path);
  320. GetSystemDirectoryW(sys_path, MAX_PATH);
  321. len = lstrlenW(sys_path);
  322. if(len > 0 && (sys_path[len-1] == '\\' || sys_path[len-1] == '/'))
  323. sys_path[len-1] = '\0';
  324. TRACE("Got system path %ls\n", sys_path);
  325. /* Don't search the DLL's path if it is the same as the current working
  326. * directory, app's path, or system path (don't want to do duplicate
  327. * searches, or increase the priority of the app or system path).
  328. */
  329. if(dll_path[0] &&
  330. (!cwd_path[0] || wcscmp(dll_path, cwd_path) != 0) &&
  331. (!proc_path[0] || wcscmp(dll_path, proc_path) != 0) &&
  332. (!sys_path[0] || wcscmp(dll_path, sys_path) != 0))
  333. SearchDrivers(dll_path);
  334. if(cwd_path[0] &&
  335. (!proc_path[0] || wcscmp(cwd_path, proc_path) != 0) &&
  336. (!sys_path[0] || wcscmp(cwd_path, sys_path) != 0))
  337. SearchDrivers(cwd_path);
  338. if(proc_path[0] && (!sys_path[0] || wcscmp(proc_path, sys_path) != 0))
  339. SearchDrivers(proc_path);
  340. if(sys_path[0])
  341. SearchDrivers(sys_path);
  342. }
  343. void InitPtrIntMap(PtrIntMap *map)
  344. {
  345. map->keys = NULL;
  346. map->values = NULL;
  347. map->size = 0;
  348. map->capacity = 0;
  349. RWLockInit(&map->lock);
  350. }
  351. void ResetPtrIntMap(PtrIntMap *map)
  352. {
  353. WriteLock(&map->lock);
  354. al_free(map->keys);
  355. map->keys = NULL;
  356. map->values = NULL;
  357. map->size = 0;
  358. map->capacity = 0;
  359. WriteUnlock(&map->lock);
  360. }
  361. ALenum InsertPtrIntMapEntry(PtrIntMap *map, ALvoid *key, ALint value)
  362. {
  363. ALsizei pos = 0;
  364. WriteLock(&map->lock);
  365. if(map->size > 0)
  366. {
  367. ALsizei count = map->size;
  368. do {
  369. ALsizei step = count>>1;
  370. ALsizei i = pos+step;
  371. if(!(map->keys[i] < key))
  372. count = step;
  373. else
  374. {
  375. pos = i+1;
  376. count -= step+1;
  377. }
  378. } while(count > 0);
  379. }
  380. if(pos == map->size || map->keys[pos] != key)
  381. {
  382. if(map->size == map->capacity)
  383. {
  384. ALvoid **keys = NULL;
  385. ALint *values;
  386. ALsizei newcap;
  387. newcap = (map->capacity ? (map->capacity<<1) : 4);
  388. if(newcap > map->capacity)
  389. keys = al_calloc(16, (sizeof(map->keys[0])+sizeof(map->values[0]))*newcap);
  390. if(!keys)
  391. {
  392. WriteUnlock(&map->lock);
  393. return AL_OUT_OF_MEMORY;
  394. }
  395. values = (ALint*)&keys[newcap];
  396. if(map->keys)
  397. {
  398. memcpy(keys, map->keys, map->size*sizeof(map->keys[0]));
  399. memcpy(values, map->values, map->size*sizeof(map->values[0]));
  400. }
  401. al_free(map->keys);
  402. map->keys = keys;
  403. map->values = values;
  404. map->capacity = newcap;
  405. }
  406. if(pos < map->size)
  407. {
  408. memmove(&map->keys[pos+1], &map->keys[pos],
  409. (map->size-pos)*sizeof(map->keys[0]));
  410. memmove(&map->values[pos+1], &map->values[pos],
  411. (map->size-pos)*sizeof(map->values[0]));
  412. }
  413. map->size++;
  414. }
  415. map->keys[pos] = key;
  416. map->values[pos] = value;
  417. WriteUnlock(&map->lock);
  418. return AL_NO_ERROR;
  419. }
  420. ALint RemovePtrIntMapKey(PtrIntMap *map, ALvoid *key)
  421. {
  422. ALint ret = -1;
  423. WriteLock(&map->lock);
  424. if(map->size > 0)
  425. {
  426. ALsizei pos = 0;
  427. ALsizei count = map->size;
  428. do {
  429. ALsizei step = count>>1;
  430. ALsizei i = pos+step;
  431. if(!(map->keys[i] < key))
  432. count = step;
  433. else
  434. {
  435. pos = i+1;
  436. count -= step+1;
  437. }
  438. } while(count > 0);
  439. if(pos < map->size && map->keys[pos] == key)
  440. {
  441. ret = map->values[pos];
  442. if(pos < map->size-1)
  443. {
  444. memmove(&map->keys[pos], &map->keys[pos+1],
  445. (map->size-1-pos)*sizeof(map->keys[0]));
  446. memmove(&map->values[pos], &map->values[pos+1],
  447. (map->size-1-pos)*sizeof(map->values[0]));
  448. }
  449. map->size--;
  450. }
  451. }
  452. WriteUnlock(&map->lock);
  453. return ret;
  454. }
  455. ALint LookupPtrIntMapKey(PtrIntMap *map, ALvoid *key)
  456. {
  457. ALint ret = -1;
  458. ReadLock(&map->lock);
  459. if(map->size > 0)
  460. {
  461. ALsizei pos = 0;
  462. ALsizei count = map->size;
  463. do {
  464. ALsizei step = count>>1;
  465. ALsizei i = pos+step;
  466. if(!(map->keys[i] < key))
  467. count = step;
  468. else
  469. {
  470. pos = i+1;
  471. count -= step+1;
  472. }
  473. } while(count > 0);
  474. if(pos < map->size && map->keys[pos] == key)
  475. ret = map->values[pos];
  476. }
  477. ReadUnlock(&map->lock);
  478. return ret;
  479. }