state.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 1999-2000 by authors.
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Library General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Library General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Library General Public
  15. * License along with this library; if not, write to the
  16. * Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. * Or go to http://www.gnu.org/copyleft/lgpl.html
  19. */
  20. #include "config.h"
  21. #include "version.h"
  22. #include <atomic>
  23. #include <cmath>
  24. #include <cstdlib>
  25. #include <cstring>
  26. #include <mutex>
  27. #include "AL/al.h"
  28. #include "AL/alc.h"
  29. #include "AL/alext.h"
  30. #include "alcontext.h"
  31. #include "alexcpt.h"
  32. #include "almalloc.h"
  33. #include "alnumeric.h"
  34. #include "alspan.h"
  35. #include "alu.h"
  36. #include "atomic.h"
  37. #include "event.h"
  38. #include "inprogext.h"
  39. #include "opthelpers.h"
  40. #include "strutils.h"
  41. namespace {
  42. constexpr ALchar alVendor[] = "OpenAL Community";
  43. constexpr ALchar alVersion[] = "1.1 ALSOFT " ALSOFT_VERSION;
  44. constexpr ALchar alRenderer[] = "OpenAL Soft";
  45. // Error Messages
  46. constexpr ALchar alNoError[] = "No Error";
  47. constexpr ALchar alErrInvalidName[] = "Invalid Name";
  48. constexpr ALchar alErrInvalidEnum[] = "Invalid Enum";
  49. constexpr ALchar alErrInvalidValue[] = "Invalid Value";
  50. constexpr ALchar alErrInvalidOp[] = "Invalid Operation";
  51. constexpr ALchar alErrOutOfMemory[] = "Out of Memory";
  52. /* Resampler strings */
  53. template<Resampler rtype> struct ResamplerName { };
  54. template<> struct ResamplerName<Resampler::Point>
  55. { static constexpr const ALchar *Get() noexcept { return "Nearest"; } };
  56. template<> struct ResamplerName<Resampler::Linear>
  57. { static constexpr const ALchar *Get() noexcept { return "Linear"; } };
  58. template<> struct ResamplerName<Resampler::Cubic>
  59. { static constexpr const ALchar *Get() noexcept { return "Cubic"; } };
  60. template<> struct ResamplerName<Resampler::FastBSinc12>
  61. { static constexpr const ALchar *Get() noexcept { return "11th order Sinc (fast)"; } };
  62. template<> struct ResamplerName<Resampler::BSinc12>
  63. { static constexpr const ALchar *Get() noexcept { return "11th order Sinc"; } };
  64. template<> struct ResamplerName<Resampler::FastBSinc24>
  65. { static constexpr const ALchar *Get() noexcept { return "23rd order Sinc (fast)"; } };
  66. template<> struct ResamplerName<Resampler::BSinc24>
  67. { static constexpr const ALchar *Get() noexcept { return "23rd order Sinc"; } };
  68. const ALchar *GetResamplerName(const Resampler rtype)
  69. {
  70. #define HANDLE_RESAMPLER(r) case r: return ResamplerName<r>::Get()
  71. switch(rtype)
  72. {
  73. HANDLE_RESAMPLER(Resampler::Point);
  74. HANDLE_RESAMPLER(Resampler::Linear);
  75. HANDLE_RESAMPLER(Resampler::Cubic);
  76. HANDLE_RESAMPLER(Resampler::FastBSinc12);
  77. HANDLE_RESAMPLER(Resampler::BSinc12);
  78. HANDLE_RESAMPLER(Resampler::FastBSinc24);
  79. HANDLE_RESAMPLER(Resampler::BSinc24);
  80. }
  81. #undef HANDLE_RESAMPLER
  82. /* Should never get here. */
  83. throw std::runtime_error{"Unexpected resampler index"};
  84. }
  85. } // namespace
  86. /* WARNING: Non-standard export! Not part of any extension, or exposed in the
  87. * alcFunctions list.
  88. */
  89. extern "C" AL_API const ALchar* AL_APIENTRY alsoft_get_version(void)
  90. START_API_FUNC
  91. {
  92. static const auto spoof = al::getenv("ALSOFT_SPOOF_VERSION");
  93. if(spoof) return spoof->c_str();
  94. return ALSOFT_VERSION;
  95. }
  96. END_API_FUNC
  97. #define DO_UPDATEPROPS() do { \
  98. if(!context->mDeferUpdates.load(std::memory_order_acquire)) \
  99. UpdateContextProps(context.get()); \
  100. else \
  101. context->mPropsClean.clear(std::memory_order_release); \
  102. } while(0)
  103. AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
  104. START_API_FUNC
  105. {
  106. ContextRef context{GetContextRef()};
  107. if UNLIKELY(!context) return;
  108. std::lock_guard<std::mutex> _{context->mPropLock};
  109. switch(capability)
  110. {
  111. case AL_SOURCE_DISTANCE_MODEL:
  112. context->mSourceDistanceModel = AL_TRUE;
  113. DO_UPDATEPROPS();
  114. break;
  115. default:
  116. context->setError(AL_INVALID_VALUE, "Invalid enable property 0x%04x", capability);
  117. }
  118. }
  119. END_API_FUNC
  120. AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
  121. START_API_FUNC
  122. {
  123. ContextRef context{GetContextRef()};
  124. if UNLIKELY(!context) return;
  125. std::lock_guard<std::mutex> _{context->mPropLock};
  126. switch(capability)
  127. {
  128. case AL_SOURCE_DISTANCE_MODEL:
  129. context->mSourceDistanceModel = AL_FALSE;
  130. DO_UPDATEPROPS();
  131. break;
  132. default:
  133. context->setError(AL_INVALID_VALUE, "Invalid disable property 0x%04x", capability);
  134. }
  135. }
  136. END_API_FUNC
  137. AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
  138. START_API_FUNC
  139. {
  140. ContextRef context{GetContextRef()};
  141. if UNLIKELY(!context) return AL_FALSE;
  142. std::lock_guard<std::mutex> _{context->mPropLock};
  143. ALboolean value{AL_FALSE};
  144. switch(capability)
  145. {
  146. case AL_SOURCE_DISTANCE_MODEL:
  147. value = context->mSourceDistanceModel;
  148. break;
  149. default:
  150. context->setError(AL_INVALID_VALUE, "Invalid is enabled property 0x%04x", capability);
  151. }
  152. return value;
  153. }
  154. END_API_FUNC
  155. AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
  156. START_API_FUNC
  157. {
  158. ContextRef context{GetContextRef()};
  159. if UNLIKELY(!context) return AL_FALSE;
  160. std::lock_guard<std::mutex> _{context->mPropLock};
  161. ALboolean value{AL_FALSE};
  162. switch(pname)
  163. {
  164. case AL_DOPPLER_FACTOR:
  165. if(context->mDopplerFactor != 0.0f)
  166. value = AL_TRUE;
  167. break;
  168. case AL_DOPPLER_VELOCITY:
  169. if(context->mDopplerVelocity != 0.0f)
  170. value = AL_TRUE;
  171. break;
  172. case AL_DISTANCE_MODEL:
  173. if(context->mDistanceModel == DistanceModel::Default)
  174. value = AL_TRUE;
  175. break;
  176. case AL_SPEED_OF_SOUND:
  177. if(context->mSpeedOfSound != 0.0f)
  178. value = AL_TRUE;
  179. break;
  180. case AL_DEFERRED_UPDATES_SOFT:
  181. if(context->mDeferUpdates.load(std::memory_order_acquire))
  182. value = AL_TRUE;
  183. break;
  184. case AL_GAIN_LIMIT_SOFT:
  185. if(GAIN_MIX_MAX/context->mGainBoost != 0.0f)
  186. value = AL_TRUE;
  187. break;
  188. case AL_NUM_RESAMPLERS_SOFT:
  189. /* Always non-0. */
  190. value = AL_TRUE;
  191. break;
  192. case AL_DEFAULT_RESAMPLER_SOFT:
  193. value = static_cast<int>(ResamplerDefault) ? AL_TRUE : AL_FALSE;
  194. break;
  195. default:
  196. context->setError(AL_INVALID_VALUE, "Invalid boolean property 0x%04x", pname);
  197. }
  198. return value;
  199. }
  200. END_API_FUNC
  201. AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
  202. START_API_FUNC
  203. {
  204. ContextRef context{GetContextRef()};
  205. if UNLIKELY(!context) return 0.0;
  206. std::lock_guard<std::mutex> _{context->mPropLock};
  207. ALdouble value{0.0};
  208. switch(pname)
  209. {
  210. case AL_DOPPLER_FACTOR:
  211. value = context->mDopplerFactor;
  212. break;
  213. case AL_DOPPLER_VELOCITY:
  214. value = context->mDopplerVelocity;
  215. break;
  216. case AL_DISTANCE_MODEL:
  217. value = static_cast<ALdouble>(context->mDistanceModel);
  218. break;
  219. case AL_SPEED_OF_SOUND:
  220. value = context->mSpeedOfSound;
  221. break;
  222. case AL_DEFERRED_UPDATES_SOFT:
  223. if(context->mDeferUpdates.load(std::memory_order_acquire))
  224. value = static_cast<ALdouble>(AL_TRUE);
  225. break;
  226. case AL_GAIN_LIMIT_SOFT:
  227. value = ALdouble{GAIN_MIX_MAX}/context->mGainBoost;
  228. break;
  229. case AL_NUM_RESAMPLERS_SOFT:
  230. value = static_cast<ALdouble>(Resampler::Max) + 1.0;
  231. break;
  232. case AL_DEFAULT_RESAMPLER_SOFT:
  233. value = static_cast<ALdouble>(ResamplerDefault);
  234. break;
  235. default:
  236. context->setError(AL_INVALID_VALUE, "Invalid double property 0x%04x", pname);
  237. }
  238. return value;
  239. }
  240. END_API_FUNC
  241. AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
  242. START_API_FUNC
  243. {
  244. ContextRef context{GetContextRef()};
  245. if UNLIKELY(!context) return 0.0f;
  246. std::lock_guard<std::mutex> _{context->mPropLock};
  247. ALfloat value{0.0f};
  248. switch(pname)
  249. {
  250. case AL_DOPPLER_FACTOR:
  251. value = context->mDopplerFactor;
  252. break;
  253. case AL_DOPPLER_VELOCITY:
  254. value = context->mDopplerVelocity;
  255. break;
  256. case AL_DISTANCE_MODEL:
  257. value = static_cast<ALfloat>(context->mDistanceModel);
  258. break;
  259. case AL_SPEED_OF_SOUND:
  260. value = context->mSpeedOfSound;
  261. break;
  262. case AL_DEFERRED_UPDATES_SOFT:
  263. if(context->mDeferUpdates.load(std::memory_order_acquire))
  264. value = static_cast<ALfloat>(AL_TRUE);
  265. break;
  266. case AL_GAIN_LIMIT_SOFT:
  267. value = GAIN_MIX_MAX/context->mGainBoost;
  268. break;
  269. case AL_NUM_RESAMPLERS_SOFT:
  270. value = static_cast<ALfloat>(Resampler::Max) + 1.0f;
  271. break;
  272. case AL_DEFAULT_RESAMPLER_SOFT:
  273. value = static_cast<ALfloat>(ResamplerDefault);
  274. break;
  275. default:
  276. context->setError(AL_INVALID_VALUE, "Invalid float property 0x%04x", pname);
  277. }
  278. return value;
  279. }
  280. END_API_FUNC
  281. AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
  282. START_API_FUNC
  283. {
  284. ContextRef context{GetContextRef()};
  285. if UNLIKELY(!context) return 0;
  286. std::lock_guard<std::mutex> _{context->mPropLock};
  287. ALint value{0};
  288. switch(pname)
  289. {
  290. case AL_DOPPLER_FACTOR:
  291. value = static_cast<ALint>(context->mDopplerFactor);
  292. break;
  293. case AL_DOPPLER_VELOCITY:
  294. value = static_cast<ALint>(context->mDopplerVelocity);
  295. break;
  296. case AL_DISTANCE_MODEL:
  297. value = static_cast<ALint>(context->mDistanceModel);
  298. break;
  299. case AL_SPEED_OF_SOUND:
  300. value = static_cast<ALint>(context->mSpeedOfSound);
  301. break;
  302. case AL_DEFERRED_UPDATES_SOFT:
  303. if(context->mDeferUpdates.load(std::memory_order_acquire))
  304. value = AL_TRUE;
  305. break;
  306. case AL_GAIN_LIMIT_SOFT:
  307. value = static_cast<ALint>(GAIN_MIX_MAX/context->mGainBoost);
  308. break;
  309. case AL_NUM_RESAMPLERS_SOFT:
  310. value = static_cast<int>(Resampler::Max) + 1;
  311. break;
  312. case AL_DEFAULT_RESAMPLER_SOFT:
  313. value = static_cast<int>(ResamplerDefault);
  314. break;
  315. default:
  316. context->setError(AL_INVALID_VALUE, "Invalid integer property 0x%04x", pname);
  317. }
  318. return value;
  319. }
  320. END_API_FUNC
  321. extern "C" AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
  322. START_API_FUNC
  323. {
  324. ContextRef context{GetContextRef()};
  325. if UNLIKELY(!context) return 0_i64;
  326. std::lock_guard<std::mutex> _{context->mPropLock};
  327. ALint64SOFT value{0};
  328. switch(pname)
  329. {
  330. case AL_DOPPLER_FACTOR:
  331. value = static_cast<ALint64SOFT>(context->mDopplerFactor);
  332. break;
  333. case AL_DOPPLER_VELOCITY:
  334. value = static_cast<ALint64SOFT>(context->mDopplerVelocity);
  335. break;
  336. case AL_DISTANCE_MODEL:
  337. value = static_cast<ALint64SOFT>(context->mDistanceModel);
  338. break;
  339. case AL_SPEED_OF_SOUND:
  340. value = static_cast<ALint64SOFT>(context->mSpeedOfSound);
  341. break;
  342. case AL_DEFERRED_UPDATES_SOFT:
  343. if(context->mDeferUpdates.load(std::memory_order_acquire))
  344. value = AL_TRUE;
  345. break;
  346. case AL_GAIN_LIMIT_SOFT:
  347. value = static_cast<ALint64SOFT>(GAIN_MIX_MAX/context->mGainBoost);
  348. break;
  349. case AL_NUM_RESAMPLERS_SOFT:
  350. value = static_cast<ALint64SOFT>(Resampler::Max) + 1;
  351. break;
  352. case AL_DEFAULT_RESAMPLER_SOFT:
  353. value = static_cast<ALint64SOFT>(ResamplerDefault);
  354. break;
  355. default:
  356. context->setError(AL_INVALID_VALUE, "Invalid integer64 property 0x%04x", pname);
  357. }
  358. return value;
  359. }
  360. END_API_FUNC
  361. AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname)
  362. START_API_FUNC
  363. {
  364. ContextRef context{GetContextRef()};
  365. if UNLIKELY(!context) return nullptr;
  366. std::lock_guard<std::mutex> _{context->mPropLock};
  367. void *value{nullptr};
  368. switch(pname)
  369. {
  370. case AL_EVENT_CALLBACK_FUNCTION_SOFT:
  371. value = reinterpret_cast<void*>(context->mEventCb);
  372. break;
  373. case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
  374. value = context->mEventParam;
  375. break;
  376. default:
  377. context->setError(AL_INVALID_VALUE, "Invalid pointer property 0x%04x", pname);
  378. }
  379. return value;
  380. }
  381. END_API_FUNC
  382. AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
  383. START_API_FUNC
  384. {
  385. if(values)
  386. {
  387. switch(pname)
  388. {
  389. case AL_DOPPLER_FACTOR:
  390. case AL_DOPPLER_VELOCITY:
  391. case AL_DISTANCE_MODEL:
  392. case AL_SPEED_OF_SOUND:
  393. case AL_DEFERRED_UPDATES_SOFT:
  394. case AL_GAIN_LIMIT_SOFT:
  395. case AL_NUM_RESAMPLERS_SOFT:
  396. case AL_DEFAULT_RESAMPLER_SOFT:
  397. values[0] = alGetBoolean(pname);
  398. return;
  399. }
  400. }
  401. ContextRef context{GetContextRef()};
  402. if UNLIKELY(!context) return;
  403. if(!values)
  404. context->setError(AL_INVALID_VALUE, "NULL pointer");
  405. else switch(pname)
  406. {
  407. default:
  408. context->setError(AL_INVALID_VALUE, "Invalid boolean-vector property 0x%04x", pname);
  409. }
  410. }
  411. END_API_FUNC
  412. AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
  413. START_API_FUNC
  414. {
  415. if(values)
  416. {
  417. switch(pname)
  418. {
  419. case AL_DOPPLER_FACTOR:
  420. case AL_DOPPLER_VELOCITY:
  421. case AL_DISTANCE_MODEL:
  422. case AL_SPEED_OF_SOUND:
  423. case AL_DEFERRED_UPDATES_SOFT:
  424. case AL_GAIN_LIMIT_SOFT:
  425. case AL_NUM_RESAMPLERS_SOFT:
  426. case AL_DEFAULT_RESAMPLER_SOFT:
  427. values[0] = alGetDouble(pname);
  428. return;
  429. }
  430. }
  431. ContextRef context{GetContextRef()};
  432. if UNLIKELY(!context) return;
  433. if(!values)
  434. context->setError(AL_INVALID_VALUE, "NULL pointer");
  435. else switch(pname)
  436. {
  437. default:
  438. context->setError(AL_INVALID_VALUE, "Invalid double-vector property 0x%04x", pname);
  439. }
  440. }
  441. END_API_FUNC
  442. AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
  443. START_API_FUNC
  444. {
  445. if(values)
  446. {
  447. switch(pname)
  448. {
  449. case AL_DOPPLER_FACTOR:
  450. case AL_DOPPLER_VELOCITY:
  451. case AL_DISTANCE_MODEL:
  452. case AL_SPEED_OF_SOUND:
  453. case AL_DEFERRED_UPDATES_SOFT:
  454. case AL_GAIN_LIMIT_SOFT:
  455. case AL_NUM_RESAMPLERS_SOFT:
  456. case AL_DEFAULT_RESAMPLER_SOFT:
  457. values[0] = alGetFloat(pname);
  458. return;
  459. }
  460. }
  461. ContextRef context{GetContextRef()};
  462. if UNLIKELY(!context) return;
  463. if(!values)
  464. context->setError(AL_INVALID_VALUE, "NULL pointer");
  465. else switch(pname)
  466. {
  467. default:
  468. context->setError(AL_INVALID_VALUE, "Invalid float-vector property 0x%04x", pname);
  469. }
  470. }
  471. END_API_FUNC
  472. AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
  473. START_API_FUNC
  474. {
  475. if(values)
  476. {
  477. switch(pname)
  478. {
  479. case AL_DOPPLER_FACTOR:
  480. case AL_DOPPLER_VELOCITY:
  481. case AL_DISTANCE_MODEL:
  482. case AL_SPEED_OF_SOUND:
  483. case AL_DEFERRED_UPDATES_SOFT:
  484. case AL_GAIN_LIMIT_SOFT:
  485. case AL_NUM_RESAMPLERS_SOFT:
  486. case AL_DEFAULT_RESAMPLER_SOFT:
  487. values[0] = alGetInteger(pname);
  488. return;
  489. }
  490. }
  491. ContextRef context{GetContextRef()};
  492. if UNLIKELY(!context) return;
  493. if(!values)
  494. context->setError(AL_INVALID_VALUE, "NULL pointer");
  495. else switch(pname)
  496. {
  497. default:
  498. context->setError(AL_INVALID_VALUE, "Invalid integer-vector property 0x%04x", pname);
  499. }
  500. }
  501. END_API_FUNC
  502. extern "C" AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
  503. START_API_FUNC
  504. {
  505. if(values)
  506. {
  507. switch(pname)
  508. {
  509. case AL_DOPPLER_FACTOR:
  510. case AL_DOPPLER_VELOCITY:
  511. case AL_DISTANCE_MODEL:
  512. case AL_SPEED_OF_SOUND:
  513. case AL_DEFERRED_UPDATES_SOFT:
  514. case AL_GAIN_LIMIT_SOFT:
  515. case AL_NUM_RESAMPLERS_SOFT:
  516. case AL_DEFAULT_RESAMPLER_SOFT:
  517. values[0] = alGetInteger64SOFT(pname);
  518. return;
  519. }
  520. }
  521. ContextRef context{GetContextRef()};
  522. if UNLIKELY(!context) return;
  523. if(!values)
  524. context->setError(AL_INVALID_VALUE, "NULL pointer");
  525. else switch(pname)
  526. {
  527. default:
  528. context->setError(AL_INVALID_VALUE, "Invalid integer64-vector property 0x%04x", pname);
  529. }
  530. }
  531. END_API_FUNC
  532. AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values)
  533. START_API_FUNC
  534. {
  535. if(values)
  536. {
  537. switch(pname)
  538. {
  539. case AL_EVENT_CALLBACK_FUNCTION_SOFT:
  540. case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
  541. values[0] = alGetPointerSOFT(pname);
  542. return;
  543. }
  544. }
  545. ContextRef context{GetContextRef()};
  546. if UNLIKELY(!context) return;
  547. if(!values)
  548. context->setError(AL_INVALID_VALUE, "NULL pointer");
  549. else switch(pname)
  550. {
  551. default:
  552. context->setError(AL_INVALID_VALUE, "Invalid pointer-vector property 0x%04x", pname);
  553. }
  554. }
  555. END_API_FUNC
  556. AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
  557. START_API_FUNC
  558. {
  559. ContextRef context{GetContextRef()};
  560. if UNLIKELY(!context) return nullptr;
  561. const ALchar *value{nullptr};
  562. switch(pname)
  563. {
  564. case AL_VENDOR:
  565. value = alVendor;
  566. break;
  567. case AL_VERSION:
  568. value = alVersion;
  569. break;
  570. case AL_RENDERER:
  571. value = alRenderer;
  572. break;
  573. case AL_EXTENSIONS:
  574. value = context->mExtensionList;
  575. break;
  576. case AL_NO_ERROR:
  577. value = alNoError;
  578. break;
  579. case AL_INVALID_NAME:
  580. value = alErrInvalidName;
  581. break;
  582. case AL_INVALID_ENUM:
  583. value = alErrInvalidEnum;
  584. break;
  585. case AL_INVALID_VALUE:
  586. value = alErrInvalidValue;
  587. break;
  588. case AL_INVALID_OPERATION:
  589. value = alErrInvalidOp;
  590. break;
  591. case AL_OUT_OF_MEMORY:
  592. value = alErrOutOfMemory;
  593. break;
  594. default:
  595. context->setError(AL_INVALID_VALUE, "Invalid string property 0x%04x", pname);
  596. }
  597. return value;
  598. }
  599. END_API_FUNC
  600. AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
  601. START_API_FUNC
  602. {
  603. ContextRef context{GetContextRef()};
  604. if UNLIKELY(!context) return;
  605. if(!(value >= 0.0f && std::isfinite(value)))
  606. context->setError(AL_INVALID_VALUE, "Doppler factor %f out of range", value);
  607. else
  608. {
  609. std::lock_guard<std::mutex> _{context->mPropLock};
  610. context->mDopplerFactor = value;
  611. DO_UPDATEPROPS();
  612. }
  613. }
  614. END_API_FUNC
  615. AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
  616. START_API_FUNC
  617. {
  618. ContextRef context{GetContextRef()};
  619. if UNLIKELY(!context) return;
  620. if((context->mEnabledEvts.load(std::memory_order_relaxed)&EventType_Deprecated))
  621. {
  622. std::lock_guard<std::mutex> _{context->mEventCbLock};
  623. ALbitfieldSOFT enabledevts{context->mEnabledEvts.load(std::memory_order_relaxed)};
  624. if((enabledevts&EventType_Deprecated) && context->mEventCb)
  625. {
  626. static const char msg[] =
  627. "alDopplerVelocity is deprecated in AL1.1, use alSpeedOfSound";
  628. const ALsizei msglen{sizeof(msg)-1};
  629. (*context->mEventCb)(AL_EVENT_TYPE_DEPRECATED_SOFT, 0, 0, msglen, msg,
  630. context->mEventParam);
  631. }
  632. }
  633. if(!(value >= 0.0f && std::isfinite(value)))
  634. context->setError(AL_INVALID_VALUE, "Doppler velocity %f out of range", value);
  635. else
  636. {
  637. std::lock_guard<std::mutex> _{context->mPropLock};
  638. context->mDopplerVelocity = value;
  639. DO_UPDATEPROPS();
  640. }
  641. }
  642. END_API_FUNC
  643. AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value)
  644. START_API_FUNC
  645. {
  646. ContextRef context{GetContextRef()};
  647. if UNLIKELY(!context) return;
  648. if(!(value > 0.0f && std::isfinite(value)))
  649. context->setError(AL_INVALID_VALUE, "Speed of sound %f out of range", value);
  650. else
  651. {
  652. std::lock_guard<std::mutex> _{context->mPropLock};
  653. context->mSpeedOfSound = value;
  654. DO_UPDATEPROPS();
  655. }
  656. }
  657. END_API_FUNC
  658. AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
  659. START_API_FUNC
  660. {
  661. ContextRef context{GetContextRef()};
  662. if UNLIKELY(!context) return;
  663. if(!(value == AL_INVERSE_DISTANCE || value == AL_INVERSE_DISTANCE_CLAMPED ||
  664. value == AL_LINEAR_DISTANCE || value == AL_LINEAR_DISTANCE_CLAMPED ||
  665. value == AL_EXPONENT_DISTANCE || value == AL_EXPONENT_DISTANCE_CLAMPED ||
  666. value == AL_NONE))
  667. context->setError(AL_INVALID_VALUE, "Distance model 0x%04x out of range", value);
  668. else
  669. {
  670. std::lock_guard<std::mutex> _{context->mPropLock};
  671. context->mDistanceModel = static_cast<DistanceModel>(value);
  672. if(!context->mSourceDistanceModel)
  673. DO_UPDATEPROPS();
  674. }
  675. }
  676. END_API_FUNC
  677. AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void)
  678. START_API_FUNC
  679. {
  680. ContextRef context{GetContextRef()};
  681. if UNLIKELY(!context) return;
  682. context->deferUpdates();
  683. }
  684. END_API_FUNC
  685. AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void)
  686. START_API_FUNC
  687. {
  688. ContextRef context{GetContextRef()};
  689. if UNLIKELY(!context) return;
  690. context->processUpdates();
  691. }
  692. END_API_FUNC
  693. AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index)
  694. START_API_FUNC
  695. {
  696. ContextRef context{GetContextRef()};
  697. if UNLIKELY(!context) return nullptr;
  698. const ALchar *value{nullptr};
  699. switch(pname)
  700. {
  701. case AL_RESAMPLER_NAME_SOFT:
  702. if(index < 0 || index > static_cast<ALint>(Resampler::Max))
  703. context->setError(AL_INVALID_VALUE, "Resampler name index %d out of range", index);
  704. else
  705. value = GetResamplerName(static_cast<Resampler>(index));
  706. break;
  707. default:
  708. context->setError(AL_INVALID_VALUE, "Invalid string indexed property");
  709. }
  710. return value;
  711. }
  712. END_API_FUNC
  713. void UpdateContextProps(ALCcontext *context)
  714. {
  715. /* Get an unused proprty container, or allocate a new one as needed. */
  716. ALcontextProps *props{context->mFreeContextProps.load(std::memory_order_acquire)};
  717. if(!props)
  718. props = new ALcontextProps{};
  719. else
  720. {
  721. ALcontextProps *next;
  722. do {
  723. next = props->next.load(std::memory_order_relaxed);
  724. } while(context->mFreeContextProps.compare_exchange_weak(props, next,
  725. std::memory_order_seq_cst, std::memory_order_acquire) == 0);
  726. }
  727. /* Copy in current property values. */
  728. props->DopplerFactor = context->mDopplerFactor;
  729. props->DopplerVelocity = context->mDopplerVelocity;
  730. props->SpeedOfSound = context->mSpeedOfSound;
  731. props->SourceDistanceModel = context->mSourceDistanceModel;
  732. props->mDistanceModel = context->mDistanceModel;
  733. /* Set the new container for updating internal parameters. */
  734. props = context->mUpdate.exchange(props, std::memory_order_acq_rel);
  735. if(props)
  736. {
  737. /* If there was an unused update container, put it back in the
  738. * freelist.
  739. */
  740. AtomicReplaceHead(context->mFreeContextProps, props);
  741. }
  742. }