🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

441 lines
13 KiB

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