alc.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994
  1. #include "config.h"
  2. #include <algorithm>
  3. #include <array>
  4. #include <cstddef>
  5. #include <cstdlib>
  6. #include <cstring>
  7. #include <cstdio>
  8. #include <mutex>
  9. #include <optional>
  10. #include <string_view>
  11. #include <tuple>
  12. #include <unordered_map>
  13. #include "AL/alc.h"
  14. #include "almalloc.h"
  15. #include "router.h"
  16. namespace {
  17. using namespace std::string_view_literals;
  18. struct FuncExportEntry {
  19. const char *funcName;
  20. void *address;
  21. };
  22. #define DECL(x) FuncExportEntry{ #x, reinterpret_cast<void*>(x) }
  23. const std::array alcFunctions{
  24. DECL(alcCreateContext),
  25. DECL(alcMakeContextCurrent),
  26. DECL(alcProcessContext),
  27. DECL(alcSuspendContext),
  28. DECL(alcDestroyContext),
  29. DECL(alcGetCurrentContext),
  30. DECL(alcGetContextsDevice),
  31. DECL(alcOpenDevice),
  32. DECL(alcCloseDevice),
  33. DECL(alcGetError),
  34. DECL(alcIsExtensionPresent),
  35. DECL(alcGetProcAddress),
  36. DECL(alcGetEnumValue),
  37. DECL(alcGetString),
  38. DECL(alcGetIntegerv),
  39. DECL(alcCaptureOpenDevice),
  40. DECL(alcCaptureCloseDevice),
  41. DECL(alcCaptureStart),
  42. DECL(alcCaptureStop),
  43. DECL(alcCaptureSamples),
  44. DECL(alcSetThreadContext),
  45. DECL(alcGetThreadContext),
  46. DECL(alEnable),
  47. DECL(alDisable),
  48. DECL(alIsEnabled),
  49. DECL(alGetString),
  50. DECL(alGetBooleanv),
  51. DECL(alGetIntegerv),
  52. DECL(alGetFloatv),
  53. DECL(alGetDoublev),
  54. DECL(alGetBoolean),
  55. DECL(alGetInteger),
  56. DECL(alGetFloat),
  57. DECL(alGetDouble),
  58. DECL(alGetError),
  59. DECL(alIsExtensionPresent),
  60. DECL(alGetProcAddress),
  61. DECL(alGetEnumValue),
  62. DECL(alListenerf),
  63. DECL(alListener3f),
  64. DECL(alListenerfv),
  65. DECL(alListeneri),
  66. DECL(alListener3i),
  67. DECL(alListeneriv),
  68. DECL(alGetListenerf),
  69. DECL(alGetListener3f),
  70. DECL(alGetListenerfv),
  71. DECL(alGetListeneri),
  72. DECL(alGetListener3i),
  73. DECL(alGetListeneriv),
  74. DECL(alGenSources),
  75. DECL(alDeleteSources),
  76. DECL(alIsSource),
  77. DECL(alSourcef),
  78. DECL(alSource3f),
  79. DECL(alSourcefv),
  80. DECL(alSourcei),
  81. DECL(alSource3i),
  82. DECL(alSourceiv),
  83. DECL(alGetSourcef),
  84. DECL(alGetSource3f),
  85. DECL(alGetSourcefv),
  86. DECL(alGetSourcei),
  87. DECL(alGetSource3i),
  88. DECL(alGetSourceiv),
  89. DECL(alSourcePlayv),
  90. DECL(alSourceStopv),
  91. DECL(alSourceRewindv),
  92. DECL(alSourcePausev),
  93. DECL(alSourcePlay),
  94. DECL(alSourceStop),
  95. DECL(alSourceRewind),
  96. DECL(alSourcePause),
  97. DECL(alSourceQueueBuffers),
  98. DECL(alSourceUnqueueBuffers),
  99. DECL(alGenBuffers),
  100. DECL(alDeleteBuffers),
  101. DECL(alIsBuffer),
  102. DECL(alBufferData),
  103. DECL(alBufferf),
  104. DECL(alBuffer3f),
  105. DECL(alBufferfv),
  106. DECL(alBufferi),
  107. DECL(alBuffer3i),
  108. DECL(alBufferiv),
  109. DECL(alGetBufferf),
  110. DECL(alGetBuffer3f),
  111. DECL(alGetBufferfv),
  112. DECL(alGetBufferi),
  113. DECL(alGetBuffer3i),
  114. DECL(alGetBufferiv),
  115. DECL(alDopplerFactor),
  116. DECL(alDopplerVelocity),
  117. DECL(alSpeedOfSound),
  118. DECL(alDistanceModel),
  119. /* EFX 1.0 */
  120. DECL(alGenFilters),
  121. DECL(alDeleteFilters),
  122. DECL(alIsFilter),
  123. DECL(alFilterf),
  124. DECL(alFilterfv),
  125. DECL(alFilteri),
  126. DECL(alFilteriv),
  127. DECL(alGetFilterf),
  128. DECL(alGetFilterfv),
  129. DECL(alGetFilteri),
  130. DECL(alGetFilteriv),
  131. DECL(alGenEffects),
  132. DECL(alDeleteEffects),
  133. DECL(alIsEffect),
  134. DECL(alEffectf),
  135. DECL(alEffectfv),
  136. DECL(alEffecti),
  137. DECL(alEffectiv),
  138. DECL(alGetEffectf),
  139. DECL(alGetEffectfv),
  140. DECL(alGetEffecti),
  141. DECL(alGetEffectiv),
  142. DECL(alGenAuxiliaryEffectSlots),
  143. DECL(alDeleteAuxiliaryEffectSlots),
  144. DECL(alIsAuxiliaryEffectSlot),
  145. DECL(alAuxiliaryEffectSlotf),
  146. DECL(alAuxiliaryEffectSlotfv),
  147. DECL(alAuxiliaryEffectSloti),
  148. DECL(alAuxiliaryEffectSlotiv),
  149. DECL(alGetAuxiliaryEffectSlotf),
  150. DECL(alGetAuxiliaryEffectSlotfv),
  151. DECL(alGetAuxiliaryEffectSloti),
  152. DECL(alGetAuxiliaryEffectSlotiv),
  153. };
  154. #undef DECL
  155. struct EnumExportEntry {
  156. const ALCchar *enumName;
  157. ALCenum value;
  158. };
  159. #define DECL(x) EnumExportEntry{ #x, (x) }
  160. const std::array alcEnumerations{
  161. DECL(ALC_INVALID),
  162. DECL(ALC_FALSE),
  163. DECL(ALC_TRUE),
  164. DECL(ALC_MAJOR_VERSION),
  165. DECL(ALC_MINOR_VERSION),
  166. DECL(ALC_ATTRIBUTES_SIZE),
  167. DECL(ALC_ALL_ATTRIBUTES),
  168. DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
  169. DECL(ALC_DEVICE_SPECIFIER),
  170. DECL(ALC_ALL_DEVICES_SPECIFIER),
  171. DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
  172. DECL(ALC_EXTENSIONS),
  173. DECL(ALC_FREQUENCY),
  174. DECL(ALC_REFRESH),
  175. DECL(ALC_SYNC),
  176. DECL(ALC_MONO_SOURCES),
  177. DECL(ALC_STEREO_SOURCES),
  178. DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
  179. DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
  180. DECL(ALC_CAPTURE_SAMPLES),
  181. DECL(ALC_NO_ERROR),
  182. DECL(ALC_INVALID_DEVICE),
  183. DECL(ALC_INVALID_CONTEXT),
  184. DECL(ALC_INVALID_ENUM),
  185. DECL(ALC_INVALID_VALUE),
  186. DECL(ALC_OUT_OF_MEMORY),
  187. DECL(AL_INVALID),
  188. DECL(AL_NONE),
  189. DECL(AL_FALSE),
  190. DECL(AL_TRUE),
  191. DECL(AL_SOURCE_RELATIVE),
  192. DECL(AL_CONE_INNER_ANGLE),
  193. DECL(AL_CONE_OUTER_ANGLE),
  194. DECL(AL_PITCH),
  195. DECL(AL_POSITION),
  196. DECL(AL_DIRECTION),
  197. DECL(AL_VELOCITY),
  198. DECL(AL_LOOPING),
  199. DECL(AL_BUFFER),
  200. DECL(AL_GAIN),
  201. DECL(AL_MIN_GAIN),
  202. DECL(AL_MAX_GAIN),
  203. DECL(AL_ORIENTATION),
  204. DECL(AL_REFERENCE_DISTANCE),
  205. DECL(AL_ROLLOFF_FACTOR),
  206. DECL(AL_CONE_OUTER_GAIN),
  207. DECL(AL_MAX_DISTANCE),
  208. DECL(AL_SEC_OFFSET),
  209. DECL(AL_SAMPLE_OFFSET),
  210. DECL(AL_BYTE_OFFSET),
  211. DECL(AL_SOURCE_TYPE),
  212. DECL(AL_STATIC),
  213. DECL(AL_STREAMING),
  214. DECL(AL_UNDETERMINED),
  215. DECL(AL_SOURCE_STATE),
  216. DECL(AL_INITIAL),
  217. DECL(AL_PLAYING),
  218. DECL(AL_PAUSED),
  219. DECL(AL_STOPPED),
  220. DECL(AL_BUFFERS_QUEUED),
  221. DECL(AL_BUFFERS_PROCESSED),
  222. DECL(AL_FORMAT_MONO8),
  223. DECL(AL_FORMAT_MONO16),
  224. DECL(AL_FORMAT_STEREO8),
  225. DECL(AL_FORMAT_STEREO16),
  226. DECL(AL_FREQUENCY),
  227. DECL(AL_BITS),
  228. DECL(AL_CHANNELS),
  229. DECL(AL_SIZE),
  230. DECL(AL_UNUSED),
  231. DECL(AL_PENDING),
  232. DECL(AL_PROCESSED),
  233. DECL(AL_NO_ERROR),
  234. DECL(AL_INVALID_NAME),
  235. DECL(AL_INVALID_ENUM),
  236. DECL(AL_INVALID_VALUE),
  237. DECL(AL_INVALID_OPERATION),
  238. DECL(AL_OUT_OF_MEMORY),
  239. DECL(AL_VENDOR),
  240. DECL(AL_VERSION),
  241. DECL(AL_RENDERER),
  242. DECL(AL_EXTENSIONS),
  243. DECL(AL_DOPPLER_FACTOR),
  244. DECL(AL_DOPPLER_VELOCITY),
  245. DECL(AL_DISTANCE_MODEL),
  246. DECL(AL_SPEED_OF_SOUND),
  247. DECL(AL_INVERSE_DISTANCE),
  248. DECL(AL_INVERSE_DISTANCE_CLAMPED),
  249. DECL(AL_LINEAR_DISTANCE),
  250. DECL(AL_LINEAR_DISTANCE_CLAMPED),
  251. DECL(AL_EXPONENT_DISTANCE),
  252. DECL(AL_EXPONENT_DISTANCE_CLAMPED),
  253. };
  254. #undef DECL
  255. [[nodiscard]] constexpr auto GetNoErrorString() noexcept { return "No Error"; }
  256. [[nodiscard]] constexpr auto GetInvalidDeviceString() noexcept { return "Invalid Device"; }
  257. [[nodiscard]] constexpr auto GetInvalidContextString() noexcept { return "Invalid Context"; }
  258. [[nodiscard]] constexpr auto GetInvalidEnumString() noexcept { return "Invalid Enum"; }
  259. [[nodiscard]] constexpr auto GetInvalidValueString() noexcept { return "Invalid Value"; }
  260. [[nodiscard]] constexpr auto GetOutOfMemoryString() noexcept { return "Out of Memory"; }
  261. [[nodiscard]] constexpr auto GetExtensionList() noexcept -> std::string_view
  262. {
  263. return "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
  264. "ALC_EXT_thread_local_context"sv;
  265. }
  266. constexpr ALCint alcMajorVersion = 1;
  267. constexpr ALCint alcMinorVersion = 1;
  268. std::recursive_mutex EnumerationLock;
  269. std::mutex ContextSwitchLock;
  270. std::atomic<ALCenum> LastError{ALC_NO_ERROR};
  271. std::unordered_map<ALCdevice*,ALCuint> DeviceIfaceMap;
  272. std::unordered_map<ALCcontext*,ALCuint> ContextIfaceMap;
  273. template<typename T, typename U, typename V>
  274. auto maybe_get(std::unordered_map<T,U> &list, V&& key) -> std::optional<U>
  275. {
  276. auto iter = list.find(std::forward<V>(key));
  277. if(iter != list.end()) return iter->second;
  278. return std::nullopt;
  279. }
  280. struct EnumeratedList {
  281. std::vector<ALCchar> Names;
  282. std::vector<ALCuint> Indicies;
  283. void clear()
  284. {
  285. Names.clear();
  286. Indicies.clear();
  287. }
  288. void AppendDeviceList(const ALCchar *names, ALCuint idx);
  289. [[nodiscard]]
  290. auto GetDriverIndexForName(const std::string_view name) const -> std::optional<ALCuint>;
  291. };
  292. EnumeratedList DevicesList;
  293. EnumeratedList AllDevicesList;
  294. EnumeratedList CaptureDevicesList;
  295. void EnumeratedList::AppendDeviceList(const ALCchar* names, ALCuint idx)
  296. {
  297. const ALCchar *name_end = names;
  298. if(!name_end) return;
  299. size_t count{0};
  300. while(*name_end)
  301. {
  302. TRACE("Enumerated \"%s\", driver %u\n", name_end, idx);
  303. ++count;
  304. name_end += strlen(name_end)+1; /* NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) */
  305. }
  306. if(names == name_end)
  307. return;
  308. Names.reserve(Names.size() + static_cast<size_t>(name_end - names) + 1);
  309. Names.insert(Names.cend(), names, name_end);
  310. Indicies.reserve(Indicies.size() + count);
  311. Indicies.insert(Indicies.cend(), count, idx);
  312. }
  313. auto EnumeratedList::GetDriverIndexForName(const std::string_view name) const -> std::optional<ALCuint>
  314. {
  315. auto devnames = Names.cbegin();
  316. auto index = Indicies.cbegin();
  317. while(devnames != Names.cend() && *devnames)
  318. {
  319. const auto devname = std::string_view{al::to_address(devnames)};
  320. if(name == devname) return *index;
  321. devnames += ptrdiff_t(devname.size()+1);
  322. ++index;
  323. }
  324. return std::nullopt;
  325. }
  326. void InitCtxFuncs(DriverIface &iface)
  327. {
  328. ALCdevice *device{iface.alcGetContextsDevice(iface.alcGetCurrentContext())};
  329. #define LOAD_PROC(x) do { \
  330. iface.x = reinterpret_cast<decltype(iface.x)>(iface.alGetProcAddress(#x));\
  331. if(!iface.x) \
  332. ERR("Failed to find entry point for %s in %ls\n", #x, \
  333. iface.Name.c_str()); \
  334. } while(0)
  335. if(iface.alcIsExtensionPresent(device, "ALC_EXT_EFX"))
  336. {
  337. LOAD_PROC(alGenFilters);
  338. LOAD_PROC(alDeleteFilters);
  339. LOAD_PROC(alIsFilter);
  340. LOAD_PROC(alFilterf);
  341. LOAD_PROC(alFilterfv);
  342. LOAD_PROC(alFilteri);
  343. LOAD_PROC(alFilteriv);
  344. LOAD_PROC(alGetFilterf);
  345. LOAD_PROC(alGetFilterfv);
  346. LOAD_PROC(alGetFilteri);
  347. LOAD_PROC(alGetFilteriv);
  348. LOAD_PROC(alGenEffects);
  349. LOAD_PROC(alDeleteEffects);
  350. LOAD_PROC(alIsEffect);
  351. LOAD_PROC(alEffectf);
  352. LOAD_PROC(alEffectfv);
  353. LOAD_PROC(alEffecti);
  354. LOAD_PROC(alEffectiv);
  355. LOAD_PROC(alGetEffectf);
  356. LOAD_PROC(alGetEffectfv);
  357. LOAD_PROC(alGetEffecti);
  358. LOAD_PROC(alGetEffectiv);
  359. LOAD_PROC(alGenAuxiliaryEffectSlots);
  360. LOAD_PROC(alDeleteAuxiliaryEffectSlots);
  361. LOAD_PROC(alIsAuxiliaryEffectSlot);
  362. LOAD_PROC(alAuxiliaryEffectSlotf);
  363. LOAD_PROC(alAuxiliaryEffectSlotfv);
  364. LOAD_PROC(alAuxiliaryEffectSloti);
  365. LOAD_PROC(alAuxiliaryEffectSlotiv);
  366. LOAD_PROC(alGetAuxiliaryEffectSlotf);
  367. LOAD_PROC(alGetAuxiliaryEffectSlotfv);
  368. LOAD_PROC(alGetAuxiliaryEffectSloti);
  369. LOAD_PROC(alGetAuxiliaryEffectSlotiv);
  370. }
  371. #undef LOAD_PROC
  372. }
  373. } /* namespace */
  374. ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename) noexcept
  375. {
  376. ALCdevice *device{nullptr};
  377. std::optional<ALCuint> idx;
  378. /* Prior to the enumeration extension, apps would hardcode these names as a
  379. * quality hint for the wrapper driver. Ignore them since there's no sane
  380. * way to map them.
  381. */
  382. if(devicename && *devicename != '\0' && devicename != "DirectSound3D"sv
  383. && devicename != "DirectSound"sv && devicename != "MMSYSTEM"sv)
  384. {
  385. {
  386. std::lock_guard<std::recursive_mutex> enumlock{EnumerationLock};
  387. if(DevicesList.Names.empty())
  388. std::ignore = alcGetString(nullptr, ALC_DEVICE_SPECIFIER);
  389. idx = DevicesList.GetDriverIndexForName(devicename);
  390. if(!idx)
  391. {
  392. if(AllDevicesList.Names.empty())
  393. std::ignore = alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER);
  394. idx = AllDevicesList.GetDriverIndexForName(devicename);
  395. }
  396. }
  397. if(!idx)
  398. {
  399. LastError.store(ALC_INVALID_VALUE);
  400. TRACE("Failed to find driver for name \"%s\"\n", devicename);
  401. return nullptr;
  402. }
  403. TRACE("Found driver %u for name \"%s\"\n", *idx, devicename);
  404. device = DriverList[*idx]->alcOpenDevice(devicename);
  405. }
  406. else
  407. {
  408. ALCuint drvidx{0};
  409. for(const auto &drv : DriverList)
  410. {
  411. if(drv->ALCVer >= MAKE_ALC_VER(1, 1)
  412. || drv->alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT"))
  413. {
  414. TRACE("Using default device from driver %u\n", drvidx);
  415. device = drv->alcOpenDevice(nullptr);
  416. idx = drvidx;
  417. break;
  418. }
  419. ++drvidx;
  420. }
  421. }
  422. if(device)
  423. {
  424. try {
  425. DeviceIfaceMap.emplace(device, idx.value());
  426. }
  427. catch(...) {
  428. DriverList[idx.value()]->alcCloseDevice(device);
  429. device = nullptr;
  430. }
  431. }
  432. return device;
  433. }
  434. ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device) noexcept
  435. {
  436. if(const auto idx = maybe_get(DeviceIfaceMap, device))
  437. {
  438. if(!DriverList[*idx]->alcCloseDevice(device))
  439. return ALC_FALSE;
  440. DeviceIfaceMap.erase(device);
  441. return ALC_TRUE;
  442. }
  443. LastError.store(ALC_INVALID_DEVICE);
  444. return ALC_FALSE;
  445. }
  446. ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrlist) noexcept
  447. {
  448. const auto idx = maybe_get(DeviceIfaceMap, device);
  449. if(!idx)
  450. {
  451. LastError.store(ALC_INVALID_DEVICE);
  452. return nullptr;
  453. }
  454. ALCcontext *context{DriverList[*idx]->alcCreateContext(device, attrlist)};
  455. if(context)
  456. {
  457. try {
  458. ContextIfaceMap.emplace(context, *idx);
  459. }
  460. catch(...) {
  461. DriverList[*idx]->alcDestroyContext(context);
  462. context = nullptr;
  463. }
  464. }
  465. return context;
  466. }
  467. ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context) noexcept
  468. {
  469. std::lock_guard<std::mutex> ctxlock{ContextSwitchLock};
  470. std::optional<ALCuint> idx;
  471. if(context)
  472. {
  473. idx = maybe_get(ContextIfaceMap, context);
  474. if(!idx)
  475. {
  476. LastError.store(ALC_INVALID_CONTEXT);
  477. return ALC_FALSE;
  478. }
  479. if(!DriverList[*idx]->alcMakeContextCurrent(context))
  480. return ALC_FALSE;
  481. std::call_once(DriverList[*idx]->InitOnceCtx, [idx]{ InitCtxFuncs(*DriverList[*idx]); });
  482. }
  483. /* Unset the context from the old driver if it's different from the new
  484. * current one.
  485. */
  486. if(!idx)
  487. {
  488. DriverIface *oldiface{GetThreadDriver()};
  489. if(oldiface) oldiface->alcSetThreadContext(nullptr);
  490. oldiface = CurrentCtxDriver.exchange(nullptr);
  491. if(oldiface) oldiface->alcMakeContextCurrent(nullptr);
  492. }
  493. else
  494. {
  495. DriverIface *oldiface{GetThreadDriver()};
  496. if(oldiface && oldiface != DriverList[*idx].get())
  497. oldiface->alcSetThreadContext(nullptr);
  498. oldiface = CurrentCtxDriver.exchange(DriverList[*idx].get());
  499. if(oldiface && oldiface != DriverList[*idx].get())
  500. oldiface->alcMakeContextCurrent(nullptr);
  501. }
  502. SetThreadDriver(nullptr);
  503. return ALC_TRUE;
  504. }
  505. ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context) noexcept
  506. {
  507. if(const auto idx = maybe_get(ContextIfaceMap, context))
  508. return DriverList[*idx]->alcProcessContext(context);
  509. LastError.store(ALC_INVALID_CONTEXT);
  510. }
  511. ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context) noexcept
  512. {
  513. if(const auto idx = maybe_get(ContextIfaceMap, context))
  514. return DriverList[*idx]->alcSuspendContext(context);
  515. LastError.store(ALC_INVALID_CONTEXT);
  516. }
  517. ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context) noexcept
  518. {
  519. if(const auto idx = maybe_get(ContextIfaceMap, context))
  520. {
  521. DriverList[*idx]->alcDestroyContext(context);
  522. ContextIfaceMap.erase(context);
  523. return;
  524. }
  525. LastError.store(ALC_INVALID_CONTEXT);
  526. }
  527. ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext() noexcept
  528. {
  529. DriverIface *iface{GetThreadDriver()};
  530. if(!iface) iface = CurrentCtxDriver.load();
  531. return iface ? iface->alcGetCurrentContext() : nullptr;
  532. }
  533. ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *context) noexcept
  534. {
  535. if(const auto idx = maybe_get(ContextIfaceMap, context))
  536. return DriverList[*idx]->alcGetContextsDevice(context);
  537. LastError.store(ALC_INVALID_CONTEXT);
  538. return nullptr;
  539. }
  540. ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device) noexcept
  541. {
  542. if(device)
  543. {
  544. if(const auto idx = maybe_get(DeviceIfaceMap, device))
  545. return DriverList[*idx]->alcGetError(device);
  546. return ALC_INVALID_DEVICE;
  547. }
  548. return LastError.exchange(ALC_NO_ERROR);
  549. }
  550. ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname) noexcept
  551. {
  552. if(device)
  553. {
  554. if(const auto idx = maybe_get(DeviceIfaceMap, device))
  555. return DriverList[*idx]->alcIsExtensionPresent(device, extname);
  556. LastError.store(ALC_INVALID_DEVICE);
  557. return ALC_FALSE;
  558. }
  559. const auto tofind = std::string_view{extname};
  560. const auto extlist = GetExtensionList();
  561. auto matchpos = extlist.find(tofind);
  562. while(matchpos != std::string_view::npos)
  563. {
  564. const auto endpos = matchpos + tofind.size();
  565. if((matchpos == 0 || std::isspace(extlist[matchpos-1]))
  566. && (endpos == extlist.size() || std::isspace(extlist[endpos])))
  567. return ALC_TRUE;
  568. matchpos = extlist.find(tofind, matchpos+1);
  569. }
  570. return ALC_FALSE;
  571. }
  572. ALC_API void* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname) noexcept
  573. {
  574. if(device)
  575. {
  576. if(const auto idx = maybe_get(DeviceIfaceMap, device))
  577. return DriverList[*idx]->alcGetProcAddress(device, funcname);
  578. LastError.store(ALC_INVALID_DEVICE);
  579. return nullptr;
  580. }
  581. auto iter = std::find_if(alcFunctions.cbegin(), alcFunctions.cend(),
  582. [funcname](const FuncExportEntry &entry) -> bool
  583. { return strcmp(funcname, entry.funcName) == 0; }
  584. );
  585. return (iter != alcFunctions.cend()) ? iter->address : nullptr;
  586. }
  587. ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumname) noexcept
  588. {
  589. if(device)
  590. {
  591. if(const auto idx = maybe_get(DeviceIfaceMap, device))
  592. return DriverList[*idx]->alcGetEnumValue(device, enumname);
  593. LastError.store(ALC_INVALID_DEVICE);
  594. return 0;
  595. }
  596. auto iter = std::find_if(alcEnumerations.cbegin(), alcEnumerations.cend(),
  597. [enumname](const EnumExportEntry &entry) -> bool
  598. { return strcmp(enumname, entry.enumName) == 0; }
  599. );
  600. return (iter != alcEnumerations.cend()) ? iter->value : 0;
  601. }
  602. ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum param) noexcept
  603. {
  604. if(device)
  605. {
  606. if(const auto idx = maybe_get(DeviceIfaceMap, device))
  607. return DriverList[*idx]->alcGetString(device, param);
  608. LastError.store(ALC_INVALID_DEVICE);
  609. return nullptr;
  610. }
  611. switch(param)
  612. {
  613. case ALC_NO_ERROR: return GetNoErrorString();
  614. case ALC_INVALID_ENUM: return GetInvalidEnumString();
  615. case ALC_INVALID_VALUE: return GetInvalidValueString();
  616. case ALC_INVALID_DEVICE: return GetInvalidDeviceString();
  617. case ALC_INVALID_CONTEXT: return GetInvalidContextString();
  618. case ALC_OUT_OF_MEMORY: return GetOutOfMemoryString();
  619. case ALC_EXTENSIONS: return GetExtensionList().data();
  620. case ALC_DEVICE_SPECIFIER:
  621. {
  622. std::lock_guard<std::recursive_mutex> enumlock{EnumerationLock};
  623. DevicesList.clear();
  624. ALCuint idx{0};
  625. for(const auto &drv : DriverList)
  626. {
  627. /* Only enumerate names from drivers that support it. */
  628. if(drv->ALCVer >= MAKE_ALC_VER(1, 1)
  629. || drv->alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT"))
  630. DevicesList.AppendDeviceList(drv->alcGetString(nullptr,ALC_DEVICE_SPECIFIER), idx);
  631. ++idx;
  632. }
  633. /* Ensure the list is double-null termianted. */
  634. if(DevicesList.Names.empty())
  635. DevicesList.Names.emplace_back('\0');
  636. DevicesList.Names.emplace_back('\0');
  637. return DevicesList.Names.data();
  638. }
  639. case ALC_ALL_DEVICES_SPECIFIER:
  640. {
  641. std::lock_guard<std::recursive_mutex> enumlock{EnumerationLock};
  642. AllDevicesList.clear();
  643. ALCuint idx{0};
  644. for(const auto &drv : DriverList)
  645. {
  646. /* If the driver doesn't support ALC_ENUMERATE_ALL_EXT, substitute
  647. * standard enumeration.
  648. */
  649. if(drv->alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT"))
  650. AllDevicesList.AppendDeviceList(
  651. drv->alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER), idx);
  652. else if(drv->ALCVer >= MAKE_ALC_VER(1, 1)
  653. || drv->alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT"))
  654. AllDevicesList.AppendDeviceList(
  655. drv->alcGetString(nullptr, ALC_DEVICE_SPECIFIER), idx);
  656. ++idx;
  657. }
  658. /* Ensure the list is double-null termianted. */
  659. if(AllDevicesList.Names.empty())
  660. AllDevicesList.Names.emplace_back('\0');
  661. AllDevicesList.Names.emplace_back('\0');
  662. return AllDevicesList.Names.data();
  663. }
  664. case ALC_CAPTURE_DEVICE_SPECIFIER:
  665. {
  666. std::lock_guard<std::recursive_mutex> enumlock{EnumerationLock};
  667. CaptureDevicesList.clear();
  668. ALCuint idx{0};
  669. for(const auto &drv : DriverList)
  670. {
  671. if(drv->ALCVer >= MAKE_ALC_VER(1, 1)
  672. || drv->alcIsExtensionPresent(nullptr, "ALC_EXT_CAPTURE"))
  673. CaptureDevicesList.AppendDeviceList(
  674. drv->alcGetString(nullptr, ALC_CAPTURE_DEVICE_SPECIFIER), idx);
  675. ++idx;
  676. }
  677. /* Ensure the list is double-null termianted. */
  678. if(CaptureDevicesList.Names.empty())
  679. CaptureDevicesList.Names.emplace_back('\0');
  680. CaptureDevicesList.Names.emplace_back('\0');
  681. return CaptureDevicesList.Names.data();
  682. }
  683. case ALC_DEFAULT_DEVICE_SPECIFIER:
  684. {
  685. for(const auto &drv : DriverList)
  686. {
  687. if(drv->ALCVer >= MAKE_ALC_VER(1, 1)
  688. || drv->alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT"))
  689. return drv->alcGetString(nullptr, ALC_DEFAULT_DEVICE_SPECIFIER);
  690. }
  691. return "";
  692. }
  693. case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
  694. {
  695. for(const auto &drv : DriverList)
  696. {
  697. if(drv->alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT") != ALC_FALSE)
  698. return drv->alcGetString(nullptr, ALC_DEFAULT_ALL_DEVICES_SPECIFIER);
  699. }
  700. return "";
  701. }
  702. case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
  703. {
  704. for(const auto &drv : DriverList)
  705. {
  706. if(drv->ALCVer >= MAKE_ALC_VER(1, 1)
  707. || drv->alcIsExtensionPresent(nullptr, "ALC_EXT_CAPTURE"))
  708. return drv->alcGetString(nullptr, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
  709. }
  710. return "";
  711. }
  712. default:
  713. LastError.store(ALC_INVALID_ENUM);
  714. break;
  715. }
  716. return nullptr;
  717. }
  718. ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values) noexcept
  719. {
  720. if(device)
  721. {
  722. if(const auto idx = maybe_get(DeviceIfaceMap, device))
  723. return DriverList[*idx]->alcGetIntegerv(device, param, size, values);
  724. LastError.store(ALC_INVALID_DEVICE);
  725. return;
  726. }
  727. if(size <= 0 || values == nullptr)
  728. {
  729. LastError.store(ALC_INVALID_VALUE);
  730. return;
  731. }
  732. switch(param)
  733. {
  734. case ALC_MAJOR_VERSION:
  735. if(size >= 1)
  736. {
  737. *values = alcMajorVersion;
  738. return;
  739. }
  740. LastError.store(ALC_INVALID_VALUE);
  741. return;
  742. case ALC_MINOR_VERSION:
  743. if(size >= 1)
  744. {
  745. *values = alcMinorVersion;
  746. return;
  747. }
  748. LastError.store(ALC_INVALID_VALUE);
  749. return;
  750. case ALC_ATTRIBUTES_SIZE:
  751. case ALC_ALL_ATTRIBUTES:
  752. case ALC_FREQUENCY:
  753. case ALC_REFRESH:
  754. case ALC_SYNC:
  755. case ALC_MONO_SOURCES:
  756. case ALC_STEREO_SOURCES:
  757. case ALC_CAPTURE_SAMPLES:
  758. LastError.store(ALC_INVALID_DEVICE);
  759. return;
  760. default:
  761. LastError.store(ALC_INVALID_ENUM);
  762. return;
  763. }
  764. }
  765. ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency,
  766. ALCenum format, ALCsizei buffersize) noexcept
  767. {
  768. ALCdevice *device{nullptr};
  769. std::optional<ALCuint> idx;
  770. if(devicename && *devicename != '\0')
  771. {
  772. {
  773. std::lock_guard<std::recursive_mutex> enumlock{EnumerationLock};
  774. if(CaptureDevicesList.Names.empty())
  775. std::ignore = alcGetString(nullptr, ALC_CAPTURE_DEVICE_SPECIFIER);
  776. idx = CaptureDevicesList.GetDriverIndexForName(devicename);
  777. }
  778. if(!idx)
  779. {
  780. LastError.store(ALC_INVALID_VALUE);
  781. TRACE("Failed to find driver for name \"%s\"\n", devicename);
  782. return nullptr;
  783. }
  784. TRACE("Found driver %u for name \"%s\"\n", *idx, devicename);
  785. device = DriverList[*idx]->alcCaptureOpenDevice(devicename, frequency, format, buffersize);
  786. }
  787. else
  788. {
  789. ALCuint drvidx{0};
  790. for(const auto &drv : DriverList)
  791. {
  792. if(drv->ALCVer >= MAKE_ALC_VER(1, 1)
  793. || drv->alcIsExtensionPresent(nullptr, "ALC_EXT_CAPTURE"))
  794. {
  795. TRACE("Using default capture device from driver %u\n", drvidx);
  796. device = drv->alcCaptureOpenDevice(nullptr, frequency, format, buffersize);
  797. idx = drvidx;
  798. break;
  799. }
  800. ++drvidx;
  801. }
  802. }
  803. if(device)
  804. {
  805. try {
  806. DeviceIfaceMap.emplace(device, idx.value());
  807. }
  808. catch(...) {
  809. DriverList[idx.value()]->alcCaptureCloseDevice(device);
  810. device = nullptr;
  811. }
  812. }
  813. return device;
  814. }
  815. ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device) noexcept
  816. {
  817. if(const auto idx = maybe_get(DeviceIfaceMap, device))
  818. {
  819. if(!DriverList[*idx]->alcCaptureCloseDevice(device))
  820. return ALC_FALSE;
  821. DeviceIfaceMap.erase(device);
  822. return ALC_TRUE;
  823. }
  824. LastError.store(ALC_INVALID_DEVICE);
  825. return ALC_FALSE;
  826. }
  827. ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device) noexcept
  828. {
  829. if(const auto idx = maybe_get(DeviceIfaceMap, device))
  830. return DriverList[*idx]->alcCaptureStart(device);
  831. LastError.store(ALC_INVALID_DEVICE);
  832. }
  833. ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device) noexcept
  834. {
  835. if(const auto idx = maybe_get(DeviceIfaceMap, device))
  836. return DriverList[*idx]->alcCaptureStop(device);
  837. LastError.store(ALC_INVALID_DEVICE);
  838. }
  839. ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) noexcept
  840. {
  841. if(const auto idx = maybe_get(DeviceIfaceMap, device))
  842. return DriverList[*idx]->alcCaptureSamples(device, buffer, samples);
  843. LastError.store(ALC_INVALID_DEVICE);
  844. }
  845. ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context) noexcept
  846. {
  847. if(!context)
  848. {
  849. DriverIface *oldiface{GetThreadDriver()};
  850. if(oldiface && !oldiface->alcSetThreadContext(nullptr))
  851. return ALC_FALSE;
  852. SetThreadDriver(nullptr);
  853. return ALC_TRUE;
  854. }
  855. ALCenum err{ALC_INVALID_CONTEXT};
  856. if(const auto idx = maybe_get(ContextIfaceMap, context))
  857. {
  858. if(DriverList[*idx]->alcSetThreadContext(context))
  859. {
  860. std::call_once(DriverList[*idx]->InitOnceCtx, [idx]{InitCtxFuncs(*DriverList[*idx]);});
  861. DriverIface *oldiface{GetThreadDriver()};
  862. if(oldiface != DriverList[*idx].get())
  863. {
  864. SetThreadDriver(DriverList[*idx].get());
  865. if(oldiface) oldiface->alcSetThreadContext(nullptr);
  866. }
  867. return ALC_TRUE;
  868. }
  869. err = DriverList[*idx]->alcGetError(nullptr);
  870. }
  871. LastError.store(err);
  872. return ALC_FALSE;
  873. }
  874. ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext() noexcept
  875. {
  876. if(DriverIface *iface{GetThreadDriver()})
  877. return iface->alcGetThreadContext();
  878. return nullptr;
  879. }