alc.cpp 29 KB

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