aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2018-11-30 21:39:59 -0800
committerChris Robinson <[email protected]>2018-11-30 21:39:59 -0800
commit7b1548af3cdda7f0023510a9ec12813a137a1668 (patch)
tree22339a93ca37352cdaebc5eda29e76c065ba2762
parent1e6e84374b9928b614e7f36a26499d806f3c89cc (diff)
Handle source state changed events uniquely in the event loop
To avoid the need of constructing the string in the mixer thread, which is commonly formatted anyway.
-rw-r--r--Alc/alu.cpp27
-rw-r--r--OpenAL32/Include/alMain.h10
-rw-r--r--OpenAL32/alSource.cpp18
-rw-r--r--OpenAL32/event.cpp21
4 files changed, 36 insertions, 40 deletions
diff --git a/Alc/alu.cpp b/Alc/alu.cpp
index b9fe95f0..197d554d 100644
--- a/Alc/alu.cpp
+++ b/Alc/alu.cpp
@@ -287,31 +287,12 @@ aluVector aluMatrixfVector(const aluMatrixf *mtx, const aluVector *vec)
void SendSourceStoppedEvent(ALCcontext *context, ALuint id)
{
- AsyncEvent evt = ASYNC_EVENT(EventType_SourceStateChange);
- ALbitfieldSOFT enabledevt;
- size_t strpos;
- ALuint scale;
-
- enabledevt = context->EnabledEvts.load(std::memory_order_acquire);
+ ALbitfieldSOFT enabledevt{context->EnabledEvts.load(std::memory_order_acquire)};
if(!(enabledevt&EventType_SourceStateChange)) return;
- evt.u.user.type = AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT;
- evt.u.user.id = id;
- evt.u.user.param = AL_STOPPED;
-
- /* Normally snprintf would be used, but this is called from the mixer and
- * that function's not real-time safe, so we have to construct it manually.
- */
- strcpy(evt.u.user.msg, "Source ID "); strpos = 10;
- scale = 1000000000;
- while(scale > 0 && scale > id)
- scale /= 10;
- while(scale > 0)
- {
- evt.u.user.msg[strpos++] = '0' + ((id/scale)%10);
- scale /= 10;
- }
- strcpy(evt.u.user.msg+strpos, " state changed to AL_STOPPED");
+ AsyncEvent evt{ASYNC_EVENT(EventType_SourceStateChange)};
+ evt.u.srcstate.id = id;
+ evt.u.srcstate.state = AL_STOPPED;
if(ll_ringbuffer_write(context->AsyncEvents, &evt, 1) == 1)
context->EventSem.post();
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index 898c8a08..bff3d52e 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -841,11 +841,15 @@ enum {
EventType_ReleaseEffectState = 65536,
};
-typedef struct AsyncEvent {
+struct AsyncEvent {
unsigned int EnumType;
union {
char dummy;
struct {
+ ALuint id;
+ ALenum state;
+ } srcstate;
+ struct {
ALenum type;
ALuint id;
ALuint param;
@@ -853,8 +857,8 @@ typedef struct AsyncEvent {
} user;
EffectState *mEffectState;
} u;
-} AsyncEvent;
-#define ASYNC_EVENT(t) { t, { 0 } }
+};
+#define ASYNC_EVENT(t) AsyncEvent{ t, { 0 } }
void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends);
diff --git a/OpenAL32/alSource.cpp b/OpenAL32/alSource.cpp
index 87729c73..11cea945 100644
--- a/OpenAL32/alSource.cpp
+++ b/OpenAL32/alSource.cpp
@@ -684,21 +684,13 @@ inline bool SourceShouldUpdate(ALsource *source, ALCcontext *context)
/** Can only be called while the mixer is locked! */
void SendStateChangeEvent(ALCcontext *context, ALuint id, ALenum state)
{
- AsyncEvent evt = ASYNC_EVENT(EventType_SourceStateChange);
- ALbitfieldSOFT enabledevt;
-
- enabledevt = context->EnabledEvts.load(std::memory_order_acquire);
+ ALbitfieldSOFT enabledevt{context->EnabledEvts.load(std::memory_order_acquire)};
if(!(enabledevt&EventType_SourceStateChange)) return;
- evt.u.user.type = AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT;
- evt.u.user.id = id;
- evt.u.user.param = state;
- snprintf(evt.u.user.msg, sizeof(evt.u.user.msg), "Source ID %u state changed to %s", id,
- (state==AL_INITIAL) ? "AL_INITIAL" :
- (state==AL_PLAYING) ? "AL_PLAYING" :
- (state==AL_PAUSED) ? "AL_PAUSED" :
- (state==AL_STOPPED) ? "AL_STOPPED" : "<unknown>"
- );
+ AsyncEvent evt{ASYNC_EVENT(EventType_SourceStateChange)};
+ evt.u.srcstate.id = id;
+ evt.u.srcstate.state = state;
+
/* The mixer may have queued a state change that's not yet been processed,
* and we don't want state change messages to occur out of order, so send
* it through the async queue to ensure proper ordering.
diff --git a/OpenAL32/event.cpp b/OpenAL32/event.cpp
index b7599a02..4980abee 100644
--- a/OpenAL32/event.cpp
+++ b/OpenAL32/event.cpp
@@ -39,7 +39,26 @@ static int EventThread(ALCcontext *context)
}
ALbitfieldSOFT enabledevts{context->EnabledEvts.load(std::memory_order_acquire)};
- if(context->EventCb && (enabledevts&evt.EnumType) == evt.EnumType)
+ if(!context->EventCb) continue;
+
+ if(evt.EnumType == EventType_SourceStateChange)
+ {
+ if(!(enabledevts&EventType_SourceStateChange))
+ continue;
+ char msg[1024]{};
+ int msglen{snprintf(msg, sizeof(msg), "Source ID %u state changed to %s",
+ evt.u.srcstate.id,
+ (evt.u.srcstate.state==AL_INITIAL) ? "AL_INITIAL" :
+ (evt.u.srcstate.state==AL_PLAYING) ? "AL_PLAYING" :
+ (evt.u.srcstate.state==AL_PAUSED) ? "AL_PAUSED" :
+ (evt.u.srcstate.state==AL_STOPPED) ? "AL_STOPPED" : "<unknown>"
+ )};
+ if(msglen < 1) msglen = strlen(msg);
+ context->EventCb(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT, evt.u.srcstate.id,
+ evt.u.srcstate.state, msglen, msg, context->EventParam
+ );
+ }
+ else if((enabledevts&evt.EnumType) == evt.EnumType)
context->EventCb(evt.u.user.type, evt.u.user.id, evt.u.user.param,
(ALsizei)strlen(evt.u.user.msg), evt.u.user.msg, context->EventParam
);