aboutsummaryrefslogtreecommitdiffstats
path: root/al/eax/call.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'al/eax/call.cpp')
-rw-r--r--al/eax/call.cpp219
1 files changed, 219 insertions, 0 deletions
diff --git a/al/eax/call.cpp b/al/eax/call.cpp
new file mode 100644
index 00000000..689d5cf1
--- /dev/null
+++ b/al/eax/call.cpp
@@ -0,0 +1,219 @@
+#include "config.h"
+#include "call.h"
+#include "exception.h"
+
+namespace {
+
+constexpr auto deferred_flag = 0x80000000U;
+
+class EaxCallException : public EaxException {
+public:
+ explicit EaxCallException(const char* message)
+ : EaxException{"EAX_CALL", message}
+ {}
+}; // EaxCallException
+
+} // namespace
+
+EaxCall::EaxCall(
+ EaxCallType type,
+ const GUID& property_set_guid,
+ ALuint property_id,
+ ALuint property_source_id,
+ ALvoid* property_buffer,
+ ALuint property_size)
+ : mCallType{type}, mVersion{0}, mPropertySetId{EaxCallPropertySetId::none}
+ , mIsDeferred{(property_id & deferred_flag) != 0}
+ , mPropertyId{property_id & ~deferred_flag}, mPropertySourceId{property_source_id}
+ , mPropertyBuffer{property_buffer}, mPropertyBufferSize{property_size}
+{
+ switch(mCallType)
+ {
+ case EaxCallType::get:
+ case EaxCallType::set:
+ break;
+
+ default:
+ fail("Invalid type.");
+ }
+
+ if (false)
+ {
+ }
+ else if (property_set_guid == EAXPROPERTYID_EAX40_Context)
+ {
+ mVersion = 4;
+ mPropertySetId = EaxCallPropertySetId::context;
+ }
+ else if (property_set_guid == EAXPROPERTYID_EAX50_Context)
+ {
+ mVersion = 5;
+ mPropertySetId = EaxCallPropertySetId::context;
+ }
+ else if (property_set_guid == DSPROPSETID_EAX20_ListenerProperties)
+ {
+ mVersion = 2;
+ mFxSlotIndex = 0u;
+ mPropertySetId = EaxCallPropertySetId::fx_slot_effect;
+ }
+ else if (property_set_guid == DSPROPSETID_EAX30_ListenerProperties)
+ {
+ mVersion = 3;
+ mFxSlotIndex = 0u;
+ mPropertySetId = EaxCallPropertySetId::fx_slot_effect;
+ }
+ else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot0)
+ {
+ mVersion = 4;
+ mFxSlotIndex = 0u;
+ mPropertySetId = EaxCallPropertySetId::fx_slot;
+ }
+ else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot0)
+ {
+ mVersion = 5;
+ mFxSlotIndex = 0u;
+ mPropertySetId = EaxCallPropertySetId::fx_slot;
+ }
+ else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot1)
+ {
+ mVersion = 4;
+ mFxSlotIndex = 1u;
+ mPropertySetId = EaxCallPropertySetId::fx_slot;
+ }
+ else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot1)
+ {
+ mVersion = 5;
+ mFxSlotIndex = 1u;
+ mPropertySetId = EaxCallPropertySetId::fx_slot;
+ }
+ else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot2)
+ {
+ mVersion = 4;
+ mFxSlotIndex = 2u;
+ mPropertySetId = EaxCallPropertySetId::fx_slot;
+ }
+ else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot2)
+ {
+ mVersion = 5;
+ mFxSlotIndex = 2u;
+ mPropertySetId = EaxCallPropertySetId::fx_slot;
+ }
+ else if (property_set_guid == EAXPROPERTYID_EAX40_FXSlot3)
+ {
+ mVersion = 4;
+ mFxSlotIndex = 3u;
+ mPropertySetId = EaxCallPropertySetId::fx_slot;
+ }
+ else if (property_set_guid == EAXPROPERTYID_EAX50_FXSlot3)
+ {
+ mVersion = 5;
+ mFxSlotIndex = 3u;
+ mPropertySetId = EaxCallPropertySetId::fx_slot;
+ }
+ else if (property_set_guid == DSPROPSETID_EAX20_BufferProperties)
+ {
+ mVersion = 2;
+ mPropertySetId = EaxCallPropertySetId::source;
+ }
+ else if (property_set_guid == DSPROPSETID_EAX30_BufferProperties)
+ {
+ mVersion = 3;
+ mPropertySetId = EaxCallPropertySetId::source;
+ }
+ else if (property_set_guid == EAXPROPERTYID_EAX40_Source)
+ {
+ mVersion = 4;
+ mPropertySetId = EaxCallPropertySetId::source;
+ }
+ else if (property_set_guid == EAXPROPERTYID_EAX50_Source)
+ {
+ mVersion = 5;
+ mPropertySetId = EaxCallPropertySetId::source;
+ }
+ else if (property_set_guid == DSPROPSETID_EAX_ReverbProperties)
+ {
+ mVersion = 1;
+ mFxSlotIndex = 0u;
+ mPropertySetId = EaxCallPropertySetId::fx_slot_effect;
+ }
+ else if (property_set_guid == DSPROPSETID_EAXBUFFER_ReverbProperties)
+ {
+ mVersion = 1;
+ mPropertySetId = EaxCallPropertySetId::source;
+ }
+ else
+ {
+ fail("Unsupported property set id.");
+ }
+
+ switch(mPropertyId)
+ {
+ case EAXCONTEXT_LASTERROR:
+ case EAXCONTEXT_SPEAKERCONFIG:
+ case EAXCONTEXT_EAXSESSION:
+ case EAXFXSLOT_NONE:
+ case EAXFXSLOT_ALLPARAMETERS:
+ case EAXFXSLOT_LOADEFFECT:
+ case EAXFXSLOT_VOLUME:
+ case EAXFXSLOT_LOCK:
+ case EAXFXSLOT_FLAGS:
+ case EAXFXSLOT_OCCLUSION:
+ case EAXFXSLOT_OCCLUSIONLFRATIO:
+ // EAX allow to set "defer" flag on immediate-only properties.
+ // If we don't clear our flag then "applyAllUpdates" in EAX context won't be called.
+ mIsDeferred = false;
+ break;
+ }
+
+ if(!mIsDeferred)
+ {
+ if(mPropertySetId != EaxCallPropertySetId::fx_slot && mPropertyId != 0)
+ {
+ if(mPropertyBuffer == nullptr)
+ fail("Null property buffer.");
+
+ if(mPropertyBufferSize == 0)
+ fail("Empty property.");
+ }
+ }
+
+ if(mPropertySetId == EaxCallPropertySetId::source && mPropertySourceId == 0)
+ fail("Null AL source id.");
+
+ if(mPropertySetId == EaxCallPropertySetId::fx_slot)
+ {
+ if(mPropertyId < EAXFXSLOT_NONE)
+ mPropertySetId = EaxCallPropertySetId::fx_slot_effect;
+ }
+}
+
+[[noreturn]] void EaxCall::fail(const char* message)
+{
+ throw EaxCallException{message};
+}
+
+[[noreturn]] void EaxCall::fail_too_small()
+{
+ fail("Property buffer too small.");
+}
+
+EaxCall create_eax_call(
+ EaxCallType type,
+ const GUID* property_set_id,
+ ALuint property_id,
+ ALuint property_source_id,
+ ALvoid* property_buffer,
+ ALuint property_size)
+{
+ if(!property_set_id)
+ throw EaxCallException{"Null property set ID."};
+
+ return EaxCall{
+ type,
+ *property_set_id,
+ property_id,
+ property_source_id,
+ property_buffer,
+ property_size
+ };
+}