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

932 lines
25 KiB

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