router.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. #include "config.h"
  2. #include "router.h"
  3. #include <algorithm>
  4. #include <cstdio>
  5. #include <cstdlib>
  6. #include <cstring>
  7. #include "AL/alc.h"
  8. #include "AL/al.h"
  9. #include "almalloc.h"
  10. #include "strutils.h"
  11. #include "version.h"
  12. std::vector<DriverIface> DriverList;
  13. thread_local DriverIface *ThreadCtxDriver;
  14. enum LogLevel LogLevel = LogLevel_Error;
  15. FILE *LogFile;
  16. static void LoadDriverList(void);
  17. BOOL APIENTRY DllMain(HINSTANCE, DWORD reason, void*)
  18. {
  19. switch(reason)
  20. {
  21. case DLL_PROCESS_ATTACH:
  22. LogFile = stderr;
  23. if(auto logfname = al::getenv("ALROUTER_LOGFILE"))
  24. {
  25. FILE *f = fopen(logfname->c_str(), "w");
  26. if(f == nullptr)
  27. ERR("Could not open log file: %s\n", logfname->c_str());
  28. else
  29. LogFile = f;
  30. }
  31. if(auto loglev = al::getenv("ALROUTER_LOGLEVEL"))
  32. {
  33. char *end = nullptr;
  34. long l = strtol(loglev->c_str(), &end, 0);
  35. if(!end || *end != '\0')
  36. ERR("Invalid log level value: %s\n", loglev->c_str());
  37. else if(l < LogLevel_None || l > LogLevel_Trace)
  38. ERR("Log level out of range: %s\n", loglev->c_str());
  39. else
  40. LogLevel = static_cast<enum LogLevel>(l);
  41. }
  42. TRACE("Initializing router v0.1-%s %s\n", ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
  43. LoadDriverList();
  44. break;
  45. case DLL_THREAD_ATTACH:
  46. break;
  47. case DLL_THREAD_DETACH:
  48. break;
  49. case DLL_PROCESS_DETACH:
  50. DriverList.clear();
  51. if(LogFile && LogFile != stderr)
  52. fclose(LogFile);
  53. LogFile = nullptr;
  54. break;
  55. }
  56. return TRUE;
  57. }
  58. static void AddModule(HMODULE module, const WCHAR *name)
  59. {
  60. for(auto &drv : DriverList)
  61. {
  62. if(drv.Module == module)
  63. {
  64. TRACE("Skipping already-loaded module %p\n", decltype(std::declval<void*>()){module});
  65. FreeLibrary(module);
  66. return;
  67. }
  68. if(drv.Name == name)
  69. {
  70. TRACE("Skipping similarly-named module %ls\n", name);
  71. FreeLibrary(module);
  72. return;
  73. }
  74. }
  75. DriverList.emplace_back(name, module);
  76. DriverIface &newdrv = DriverList.back();
  77. /* Load required functions. */
  78. int err = 0;
  79. #define LOAD_PROC(x) do { \
  80. newdrv.x = reinterpret_cast<decltype(newdrv.x)>(reinterpret_cast<void*>( \
  81. GetProcAddress(module, #x))); \
  82. if(!newdrv.x) \
  83. { \
  84. ERR("Failed to find entry point for %s in %ls\n", #x, name); \
  85. err = 1; \
  86. } \
  87. } while(0)
  88. LOAD_PROC(alcCreateContext);
  89. LOAD_PROC(alcMakeContextCurrent);
  90. LOAD_PROC(alcProcessContext);
  91. LOAD_PROC(alcSuspendContext);
  92. LOAD_PROC(alcDestroyContext);
  93. LOAD_PROC(alcGetCurrentContext);
  94. LOAD_PROC(alcGetContextsDevice);
  95. LOAD_PROC(alcOpenDevice);
  96. LOAD_PROC(alcCloseDevice);
  97. LOAD_PROC(alcGetError);
  98. LOAD_PROC(alcIsExtensionPresent);
  99. LOAD_PROC(alcGetProcAddress);
  100. LOAD_PROC(alcGetEnumValue);
  101. LOAD_PROC(alcGetString);
  102. LOAD_PROC(alcGetIntegerv);
  103. LOAD_PROC(alcCaptureOpenDevice);
  104. LOAD_PROC(alcCaptureCloseDevice);
  105. LOAD_PROC(alcCaptureStart);
  106. LOAD_PROC(alcCaptureStop);
  107. LOAD_PROC(alcCaptureSamples);
  108. LOAD_PROC(alEnable);
  109. LOAD_PROC(alDisable);
  110. LOAD_PROC(alIsEnabled);
  111. LOAD_PROC(alGetString);
  112. LOAD_PROC(alGetBooleanv);
  113. LOAD_PROC(alGetIntegerv);
  114. LOAD_PROC(alGetFloatv);
  115. LOAD_PROC(alGetDoublev);
  116. LOAD_PROC(alGetBoolean);
  117. LOAD_PROC(alGetInteger);
  118. LOAD_PROC(alGetFloat);
  119. LOAD_PROC(alGetDouble);
  120. LOAD_PROC(alGetError);
  121. LOAD_PROC(alIsExtensionPresent);
  122. LOAD_PROC(alGetProcAddress);
  123. LOAD_PROC(alGetEnumValue);
  124. LOAD_PROC(alListenerf);
  125. LOAD_PROC(alListener3f);
  126. LOAD_PROC(alListenerfv);
  127. LOAD_PROC(alListeneri);
  128. LOAD_PROC(alListener3i);
  129. LOAD_PROC(alListeneriv);
  130. LOAD_PROC(alGetListenerf);
  131. LOAD_PROC(alGetListener3f);
  132. LOAD_PROC(alGetListenerfv);
  133. LOAD_PROC(alGetListeneri);
  134. LOAD_PROC(alGetListener3i);
  135. LOAD_PROC(alGetListeneriv);
  136. LOAD_PROC(alGenSources);
  137. LOAD_PROC(alDeleteSources);
  138. LOAD_PROC(alIsSource);
  139. LOAD_PROC(alSourcef);
  140. LOAD_PROC(alSource3f);
  141. LOAD_PROC(alSourcefv);
  142. LOAD_PROC(alSourcei);
  143. LOAD_PROC(alSource3i);
  144. LOAD_PROC(alSourceiv);
  145. LOAD_PROC(alGetSourcef);
  146. LOAD_PROC(alGetSource3f);
  147. LOAD_PROC(alGetSourcefv);
  148. LOAD_PROC(alGetSourcei);
  149. LOAD_PROC(alGetSource3i);
  150. LOAD_PROC(alGetSourceiv);
  151. LOAD_PROC(alSourcePlayv);
  152. LOAD_PROC(alSourceStopv);
  153. LOAD_PROC(alSourceRewindv);
  154. LOAD_PROC(alSourcePausev);
  155. LOAD_PROC(alSourcePlay);
  156. LOAD_PROC(alSourceStop);
  157. LOAD_PROC(alSourceRewind);
  158. LOAD_PROC(alSourcePause);
  159. LOAD_PROC(alSourceQueueBuffers);
  160. LOAD_PROC(alSourceUnqueueBuffers);
  161. LOAD_PROC(alGenBuffers);
  162. LOAD_PROC(alDeleteBuffers);
  163. LOAD_PROC(alIsBuffer);
  164. LOAD_PROC(alBufferf);
  165. LOAD_PROC(alBuffer3f);
  166. LOAD_PROC(alBufferfv);
  167. LOAD_PROC(alBufferi);
  168. LOAD_PROC(alBuffer3i);
  169. LOAD_PROC(alBufferiv);
  170. LOAD_PROC(alGetBufferf);
  171. LOAD_PROC(alGetBuffer3f);
  172. LOAD_PROC(alGetBufferfv);
  173. LOAD_PROC(alGetBufferi);
  174. LOAD_PROC(alGetBuffer3i);
  175. LOAD_PROC(alGetBufferiv);
  176. LOAD_PROC(alBufferData);
  177. LOAD_PROC(alDopplerFactor);
  178. LOAD_PROC(alDopplerVelocity);
  179. LOAD_PROC(alSpeedOfSound);
  180. LOAD_PROC(alDistanceModel);
  181. if(!err)
  182. {
  183. ALCint alc_ver[2] = { 0, 0 };
  184. newdrv.alcGetIntegerv(nullptr, ALC_MAJOR_VERSION, 1, &alc_ver[0]);
  185. newdrv.alcGetIntegerv(nullptr, ALC_MINOR_VERSION, 1, &alc_ver[1]);
  186. if(newdrv.alcGetError(nullptr) == ALC_NO_ERROR)
  187. newdrv.ALCVer = MAKE_ALC_VER(alc_ver[0], alc_ver[1]);
  188. else
  189. newdrv.ALCVer = MAKE_ALC_VER(1, 0);
  190. #undef LOAD_PROC
  191. #define LOAD_PROC(x) do { \
  192. newdrv.x = reinterpret_cast<decltype(newdrv.x)>( \
  193. newdrv.alcGetProcAddress(nullptr, #x)); \
  194. if(!newdrv.x) \
  195. { \
  196. ERR("Failed to find entry point for %s in %ls\n", #x, name); \
  197. err = 1; \
  198. } \
  199. } while(0)
  200. if(newdrv.alcIsExtensionPresent(nullptr, "ALC_EXT_thread_local_context"))
  201. {
  202. LOAD_PROC(alcSetThreadContext);
  203. LOAD_PROC(alcGetThreadContext);
  204. }
  205. }
  206. if(err)
  207. {
  208. DriverList.pop_back();
  209. return;
  210. }
  211. TRACE("Loaded module %p, %ls, ALC %d.%d\n", decltype(std::declval<void*>()){module}, name,
  212. newdrv.ALCVer>>8, newdrv.ALCVer&255);
  213. #undef LOAD_PROC
  214. }
  215. static void SearchDrivers(WCHAR *path)
  216. {
  217. WIN32_FIND_DATAW fdata;
  218. TRACE("Searching for drivers in %ls...\n", path);
  219. std::wstring srchPath = path;
  220. srchPath += L"\\*oal.dll";
  221. HANDLE srchHdl = FindFirstFileW(srchPath.c_str(), &fdata);
  222. if(srchHdl != INVALID_HANDLE_VALUE)
  223. {
  224. do {
  225. HMODULE mod;
  226. srchPath = path;
  227. srchPath += L"\\";
  228. srchPath += fdata.cFileName;
  229. TRACE("Found %ls\n", srchPath.c_str());
  230. mod = LoadLibraryW(srchPath.c_str());
  231. if(!mod)
  232. WARN("Could not load %ls\n", srchPath.c_str());
  233. else
  234. AddModule(mod, fdata.cFileName);
  235. } while(FindNextFileW(srchHdl, &fdata));
  236. FindClose(srchHdl);
  237. }
  238. }
  239. static WCHAR *strrchrW(WCHAR *str, WCHAR ch)
  240. {
  241. WCHAR *res = nullptr;
  242. while(str && *str != '\0')
  243. {
  244. if(*str == ch)
  245. res = str;
  246. ++str;
  247. }
  248. return res;
  249. }
  250. static int GetLoadedModuleDirectory(const WCHAR *name, WCHAR *moddir, DWORD length)
  251. {
  252. HMODULE module = nullptr;
  253. WCHAR *sep0, *sep1;
  254. if(name)
  255. {
  256. module = GetModuleHandleW(name);
  257. if(!module) return 0;
  258. }
  259. if(GetModuleFileNameW(module, moddir, length) == 0)
  260. return 0;
  261. sep0 = strrchrW(moddir, '/');
  262. if(sep0) sep1 = strrchrW(sep0+1, '\\');
  263. else sep1 = strrchrW(moddir, '\\');
  264. if(sep1) *sep1 = '\0';
  265. else if(sep0) *sep0 = '\0';
  266. else *moddir = '\0';
  267. return 1;
  268. }
  269. void LoadDriverList(void)
  270. {
  271. WCHAR dll_path[MAX_PATH+1] = L"";
  272. WCHAR cwd_path[MAX_PATH+1] = L"";
  273. WCHAR proc_path[MAX_PATH+1] = L"";
  274. WCHAR sys_path[MAX_PATH+1] = L"";
  275. int len;
  276. if(GetLoadedModuleDirectory(L"OpenAL32.dll", dll_path, MAX_PATH))
  277. TRACE("Got DLL path %ls\n", dll_path);
  278. GetCurrentDirectoryW(MAX_PATH, cwd_path);
  279. len = lstrlenW(cwd_path);
  280. if(len > 0 && (cwd_path[len-1] == '\\' || cwd_path[len-1] == '/'))
  281. cwd_path[len-1] = '\0';
  282. TRACE("Got current working directory %ls\n", cwd_path);
  283. if(GetLoadedModuleDirectory(nullptr, proc_path, MAX_PATH))
  284. TRACE("Got proc path %ls\n", proc_path);
  285. GetSystemDirectoryW(sys_path, MAX_PATH);
  286. len = lstrlenW(sys_path);
  287. if(len > 0 && (sys_path[len-1] == '\\' || sys_path[len-1] == '/'))
  288. sys_path[len-1] = '\0';
  289. TRACE("Got system path %ls\n", sys_path);
  290. /* Don't search the DLL's path if it is the same as the current working
  291. * directory, app's path, or system path (don't want to do duplicate
  292. * searches, or increase the priority of the app or system path).
  293. */
  294. if(dll_path[0] &&
  295. (!cwd_path[0] || wcscmp(dll_path, cwd_path) != 0) &&
  296. (!proc_path[0] || wcscmp(dll_path, proc_path) != 0) &&
  297. (!sys_path[0] || wcscmp(dll_path, sys_path) != 0))
  298. SearchDrivers(dll_path);
  299. if(cwd_path[0] &&
  300. (!proc_path[0] || wcscmp(cwd_path, proc_path) != 0) &&
  301. (!sys_path[0] || wcscmp(cwd_path, sys_path) != 0))
  302. SearchDrivers(cwd_path);
  303. if(proc_path[0] && (!sys_path[0] || wcscmp(proc_path, sys_path) != 0))
  304. SearchDrivers(proc_path);
  305. if(sys_path[0])
  306. SearchDrivers(sys_path);
  307. }
  308. PtrIntMap::~PtrIntMap()
  309. {
  310. std::lock_guard<std::mutex> maplock{mLock};
  311. al_free(mKeys);
  312. mKeys = nullptr;
  313. mValues = nullptr;
  314. mSize = 0;
  315. mCapacity = 0;
  316. }
  317. ALenum PtrIntMap::insert(void *key, int value)
  318. {
  319. std::lock_guard<std::mutex> maplock{mLock};
  320. auto iter = std::lower_bound(mKeys, mKeys+mSize, key);
  321. auto pos = static_cast<ALsizei>(std::distance(mKeys, iter));
  322. if(pos == mSize || mKeys[pos] != key)
  323. {
  324. if(mSize == mCapacity)
  325. {
  326. void **newkeys{nullptr};
  327. ALsizei newcap{mCapacity ? (mCapacity<<1) : 4};
  328. if(newcap > mCapacity)
  329. newkeys = static_cast<void**>(
  330. al_calloc(16, (sizeof(mKeys[0])+sizeof(mValues[0]))*newcap)
  331. );
  332. if(!newkeys)
  333. return AL_OUT_OF_MEMORY;
  334. auto newvalues = reinterpret_cast<int*>(&newkeys[newcap]);
  335. if(mKeys)
  336. {
  337. std::copy_n(mKeys, mSize, newkeys);
  338. std::copy_n(mValues, mSize, newvalues);
  339. }
  340. al_free(mKeys);
  341. mKeys = newkeys;
  342. mValues = newvalues;
  343. mCapacity = newcap;
  344. }
  345. if(pos < mSize)
  346. {
  347. std::copy_backward(mKeys+pos, mKeys+mSize, mKeys+mSize+1);
  348. std::copy_backward(mValues+pos, mValues+mSize, mValues+mSize+1);
  349. }
  350. mSize++;
  351. }
  352. mKeys[pos] = key;
  353. mValues[pos] = value;
  354. return AL_NO_ERROR;
  355. }
  356. int PtrIntMap::removeByKey(void *key)
  357. {
  358. int ret = -1;
  359. std::lock_guard<std::mutex> maplock{mLock};
  360. auto iter = std::lower_bound(mKeys, mKeys+mSize, key);
  361. auto pos = static_cast<ALsizei>(std::distance(mKeys, iter));
  362. if(pos < mSize && mKeys[pos] == key)
  363. {
  364. ret = mValues[pos];
  365. if(pos+1 < mSize)
  366. {
  367. std::copy(mKeys+pos+1, mKeys+mSize, mKeys+pos);
  368. std::copy(mValues+pos+1, mValues+mSize, mValues+pos);
  369. }
  370. mSize--;
  371. }
  372. return ret;
  373. }
  374. int PtrIntMap::lookupByKey(void *key)
  375. {
  376. int ret = -1;
  377. std::lock_guard<std::mutex> maplock{mLock};
  378. auto iter = std::lower_bound(mKeys, mKeys+mSize, key);
  379. auto pos = static_cast<ALsizei>(std::distance(mKeys, iter));
  380. if(pos < mSize && mKeys[pos] == key)
  381. ret = mValues[pos];
  382. return ret;
  383. }