🛠️🐜 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.

447 lines
13 KiB

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