alc.c 26 KB

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