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

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