call.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. #include "config.h"
  2. #include "call.h"
  3. #include "exception.h"
  4. namespace {
  5. constexpr auto deferred_flag = 0x80000000U;
  6. class EaxCallException : public EaxException {
  7. public:
  8. explicit EaxCallException(const char* message)
  9. : EaxException{"EAX_CALL", message}
  10. {}
  11. }; // EaxCallException
  12. } // namespace
  13. EaxCall::EaxCall(EaxCallType type, const GUID &property_set_guid, ALuint property_id,
  14. ALuint property_source_id, ALvoid *property_buffer, ALuint property_size)
  15. : mCallType{type}, mIsDeferred{(property_id & deferred_flag) != 0}
  16. , mPropertyId{property_id & ~deferred_flag}, mPropertySourceId{property_source_id}
  17. , mPropertyBuffer{property_buffer}, mPropertyBufferSize{property_size}
  18. {
  19. switch(mCallType)
  20. {
  21. case EaxCallType::get:
  22. case EaxCallType::set:
  23. break;
  24. default:
  25. fail("Invalid type.");
  26. }
  27. if (false)
  28. {
  29. }
  30. else if (property_set_guid == EAXPROPERTYID_EAX40_Context)
  31. {
  32. mVersion = 4;
  33. mPropertySetId = EaxCallPropertySetId::context;
  34. }
  35. else if (property_set_guid == EAXPROPERTYID_EAX50_Context)
  36. {
  37. mVersion = 5;
  38. mPropertySetId = EaxCallPropertySetId::context;
  39. }
  40. else if (property_set_guid == DSPROPSETID_EAX20_ListenerProperties)
  41. {
  42. mVersion = 2;
  43. mFxSlotIndex = 0u;
  44. mPropertySetId = EaxCallPropertySetId::fx_slot_effect;
  45. }
  46. else if (property_set_guid == DSPROPSETID_EAX30_ListenerProperties)
  47. {
  48. mVersion = 3;
  49. mFxSlotIndex = 0u;
  50. mPropertySetId = EaxCallPropertySetId::fx_slot_effect;
  51. }
  52. else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot0)
  53. {
  54. mVersion = 4;
  55. mFxSlotIndex = 0u;
  56. mPropertySetId = EaxCallPropertySetId::fx_slot;
  57. }
  58. else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot0)
  59. {
  60. mVersion = 5;
  61. mFxSlotIndex = 0u;
  62. mPropertySetId = EaxCallPropertySetId::fx_slot;
  63. }
  64. else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot1)
  65. {
  66. mVersion = 4;
  67. mFxSlotIndex = 1u;
  68. mPropertySetId = EaxCallPropertySetId::fx_slot;
  69. }
  70. else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot1)
  71. {
  72. mVersion = 5;
  73. mFxSlotIndex = 1u;
  74. mPropertySetId = EaxCallPropertySetId::fx_slot;
  75. }
  76. else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot2)
  77. {
  78. mVersion = 4;
  79. mFxSlotIndex = 2u;
  80. mPropertySetId = EaxCallPropertySetId::fx_slot;
  81. }
  82. else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot2)
  83. {
  84. mVersion = 5;
  85. mFxSlotIndex = 2u;
  86. mPropertySetId = EaxCallPropertySetId::fx_slot;
  87. }
  88. else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot3)
  89. {
  90. mVersion = 4;
  91. mFxSlotIndex = 3u;
  92. mPropertySetId = EaxCallPropertySetId::fx_slot;
  93. }
  94. else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot3)
  95. {
  96. mVersion = 5;
  97. mFxSlotIndex = 3u;
  98. mPropertySetId = EaxCallPropertySetId::fx_slot;
  99. }
  100. else if (property_set_guid == DSPROPSETID_EAX20_BufferProperties)
  101. {
  102. mVersion = 2;
  103. mPropertySetId = EaxCallPropertySetId::source;
  104. }
  105. else if (property_set_guid == DSPROPSETID_EAX30_BufferProperties)
  106. {
  107. mVersion = 3;
  108. mPropertySetId = EaxCallPropertySetId::source;
  109. }
  110. else if (property_set_guid == EAXPROPERTYID_EAX40_Source)
  111. {
  112. mVersion = 4;
  113. mPropertySetId = EaxCallPropertySetId::source;
  114. }
  115. else if (property_set_guid == EAXPROPERTYID_EAX50_Source)
  116. {
  117. mVersion = 5;
  118. mPropertySetId = EaxCallPropertySetId::source;
  119. }
  120. else if (property_set_guid == DSPROPSETID_EAX_ReverbProperties)
  121. {
  122. mVersion = 1;
  123. mFxSlotIndex = 0u;
  124. mPropertySetId = EaxCallPropertySetId::fx_slot_effect;
  125. }
  126. else if (property_set_guid == DSPROPSETID_EAXBUFFER_ReverbProperties)
  127. {
  128. mVersion = 1;
  129. mPropertySetId = EaxCallPropertySetId::source;
  130. }
  131. else
  132. {
  133. fail("Unsupported property set id.");
  134. }
  135. if(mPropertySetId == EaxCallPropertySetId::context)
  136. {
  137. switch(mPropertyId)
  138. {
  139. case EAXCONTEXT_LASTERROR:
  140. case EAXCONTEXT_SPEAKERCONFIG:
  141. case EAXCONTEXT_EAXSESSION:
  142. // EAX allow to set "defer" flag on immediate-only properties.
  143. // If we don't clear our flag then "applyAllUpdates" in EAX context won't be called.
  144. mIsDeferred = false;
  145. break;
  146. }
  147. }
  148. else if(mPropertySetId == EaxCallPropertySetId::fx_slot)
  149. {
  150. switch(mPropertyId)
  151. {
  152. case EAXFXSLOT_NONE:
  153. case EAXFXSLOT_ALLPARAMETERS:
  154. case EAXFXSLOT_LOADEFFECT:
  155. case EAXFXSLOT_VOLUME:
  156. case EAXFXSLOT_LOCK:
  157. case EAXFXSLOT_FLAGS:
  158. case EAXFXSLOT_OCCLUSION:
  159. case EAXFXSLOT_OCCLUSIONLFRATIO:
  160. mIsDeferred = false;
  161. break;
  162. }
  163. }
  164. if(!mIsDeferred)
  165. {
  166. if(mPropertySetId != EaxCallPropertySetId::fx_slot && mPropertyId != 0)
  167. {
  168. if(mPropertyBuffer == nullptr)
  169. fail("Null property buffer.");
  170. if(mPropertyBufferSize == 0)
  171. fail("Empty property.");
  172. }
  173. }
  174. if(mPropertySetId == EaxCallPropertySetId::source && mPropertySourceId == 0)
  175. fail("Null AL source id.");
  176. if(mPropertySetId == EaxCallPropertySetId::fx_slot)
  177. {
  178. if(mPropertyId < EAXFXSLOT_NONE)
  179. mPropertySetId = EaxCallPropertySetId::fx_slot_effect;
  180. }
  181. }
  182. [[noreturn]] void EaxCall::fail(const char* message)
  183. {
  184. throw EaxCallException{message};
  185. }
  186. [[noreturn]] void EaxCall::fail_too_small()
  187. {
  188. fail("Property buffer too small.");
  189. }
  190. EaxCall create_eax_call(
  191. EaxCallType type,
  192. const GUID* property_set_id,
  193. ALuint property_id,
  194. ALuint property_source_id,
  195. ALvoid* property_buffer,
  196. ALuint property_size)
  197. {
  198. if(!property_set_id)
  199. throw EaxCallException{"Null property set ID."};
  200. return EaxCall{
  201. type,
  202. *property_set_id,
  203. property_id,
  204. property_source_id,
  205. property_buffer,
  206. property_size
  207. };
  208. }