Use a separate enum for the VoiceChange state
This commit is contained in:
+25
-6
@@ -27,6 +27,7 @@
|
||||
#include "opthelpers.h"
|
||||
#include "ringbuffer.h"
|
||||
#include "threads.h"
|
||||
#include "voice_change.h"
|
||||
|
||||
|
||||
static int EventThread(ALCcontext *context)
|
||||
@@ -68,15 +69,33 @@ static int EventThread(ALCcontext *context)
|
||||
{
|
||||
if(!(enabledevts&EventType_SourceStateChange))
|
||||
continue;
|
||||
ALuint state{};
|
||||
std::string msg{"Source ID " + std::to_string(evt.u.srcstate.id)};
|
||||
msg += " state has changed to ";
|
||||
msg += (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>";
|
||||
switch(evt.u.srcstate.state)
|
||||
{
|
||||
case VChangeState::Reset:
|
||||
msg += "AL_INITIAL";
|
||||
state = AL_INITIAL;
|
||||
break;
|
||||
case VChangeState::Stop:
|
||||
msg += "AL_STOPPED";
|
||||
state = AL_STOPPED;
|
||||
break;
|
||||
case VChangeState::Play:
|
||||
msg += "AL_PLAYING";
|
||||
state = AL_PLAYING;
|
||||
break;
|
||||
case VChangeState::Pause:
|
||||
msg += "AL_PAUSED";
|
||||
state = AL_PAUSED;
|
||||
break;
|
||||
/* Shouldn't happen */
|
||||
case VChangeState::Restart:
|
||||
break;
|
||||
}
|
||||
context->mEventCb(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT, evt.u.srcstate.id,
|
||||
static_cast<ALuint>(evt.u.srcstate.state), static_cast<ALsizei>(msg.length()),
|
||||
msg.c_str(), context->mEventParam);
|
||||
state, static_cast<ALsizei>(msg.length()), msg.c_str(), context->mEventParam);
|
||||
}
|
||||
else if(evt.EnumType == EventType_BufferCompleted)
|
||||
{
|
||||
|
||||
+11
-10
@@ -1,12 +1,13 @@
|
||||
#ifndef AL_EVENT_H
|
||||
#define AL_EVENT_H
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
|
||||
#include "almalloc.h"
|
||||
|
||||
struct ALCcontext;
|
||||
struct EffectState;
|
||||
enum class VChangeState;
|
||||
|
||||
using uint = unsigned int;
|
||||
|
||||
|
||||
enum {
|
||||
@@ -23,25 +24,25 @@ enum {
|
||||
};
|
||||
|
||||
struct AsyncEvent {
|
||||
unsigned int EnumType{0u};
|
||||
uint EnumType{0u};
|
||||
union {
|
||||
char dummy;
|
||||
struct {
|
||||
ALuint id;
|
||||
ALenum state;
|
||||
uint id;
|
||||
VChangeState state;
|
||||
} srcstate;
|
||||
struct {
|
||||
ALuint id;
|
||||
ALuint count;
|
||||
uint id;
|
||||
uint count;
|
||||
} bufcomp;
|
||||
struct {
|
||||
ALchar msg[244];
|
||||
char msg[244];
|
||||
} disconnect;
|
||||
EffectState *mEffectState;
|
||||
} u{};
|
||||
|
||||
AsyncEvent() noexcept = default;
|
||||
constexpr AsyncEvent(unsigned int type) noexcept : EnumType{type} { }
|
||||
constexpr AsyncEvent(uint type) noexcept : EnumType{type} { }
|
||||
|
||||
DISABLE_ALLOC()
|
||||
};
|
||||
|
||||
+7
-7
@@ -619,7 +619,7 @@ bool SetVoiceOffset(Voice *oldvoice, const VoicePos &vpos, ALsource *source, ALC
|
||||
vchg->mOldVoice = oldvoice;
|
||||
vchg->mVoice = newvoice;
|
||||
vchg->mSourceID = source->id;
|
||||
vchg->mState = AL_SAMPLE_OFFSET;
|
||||
vchg->mState = VChangeState::Restart;
|
||||
SendVoiceChanges(context, vchg);
|
||||
|
||||
/* If the old voice still has a sourceID, it's still active and the change-
|
||||
@@ -740,7 +740,7 @@ void FreeSource(ALCcontext *context, ALsource *source)
|
||||
voice->mPendingChange.store(true, std::memory_order_relaxed);
|
||||
vchg->mVoice = voice;
|
||||
vchg->mSourceID = source->id;
|
||||
vchg->mState = AL_STOPPED;
|
||||
vchg->mState = VChangeState::Stop;
|
||||
|
||||
SendVoiceChanges(context, vchg);
|
||||
}
|
||||
@@ -2935,7 +2935,7 @@ START_API_FUNC
|
||||
if(!voice) break;
|
||||
cur->mVoice = voice;
|
||||
cur->mSourceID = source->id;
|
||||
cur->mState = AL_PLAYING;
|
||||
cur->mState = VChangeState::Play;
|
||||
source->state = AL_PLAYING;
|
||||
continue;
|
||||
|
||||
@@ -2997,7 +2997,7 @@ START_API_FUNC
|
||||
|
||||
cur->mVoice = voice;
|
||||
cur->mSourceID = source->id;
|
||||
cur->mState = AL_PLAYING;
|
||||
cur->mState = VChangeState::Play;
|
||||
}
|
||||
if LIKELY(tail)
|
||||
SendVoiceChanges(context.get(), tail);
|
||||
@@ -3059,7 +3059,7 @@ START_API_FUNC
|
||||
}
|
||||
cur->mVoice = voice;
|
||||
cur->mSourceID = source->id;
|
||||
cur->mState = AL_PAUSED;
|
||||
cur->mState = VChangeState::Pause;
|
||||
}
|
||||
}
|
||||
if LIKELY(tail)
|
||||
@@ -3131,7 +3131,7 @@ START_API_FUNC
|
||||
voice->mPendingChange.store(true, std::memory_order_relaxed);
|
||||
cur->mVoice = voice;
|
||||
cur->mSourceID = source->id;
|
||||
cur->mState = AL_STOPPED;
|
||||
cur->mState = VChangeState::Stop;
|
||||
source->state = AL_STOPPED;
|
||||
}
|
||||
source->Offset = 0.0;
|
||||
@@ -3196,7 +3196,7 @@ START_API_FUNC
|
||||
voice->mPendingChange.store(true, std::memory_order_relaxed);
|
||||
cur->mVoice = voice;
|
||||
cur->mSourceID = source->id;
|
||||
cur->mState = AL_INITIAL;
|
||||
cur->mState = VChangeState::Reset;
|
||||
source->state = AL_INITIAL;
|
||||
}
|
||||
source->Offset = 0.0;
|
||||
|
||||
+6
-6
@@ -1564,7 +1564,7 @@ void CalcSourceParams(Voice *voice, ALCcontext *context, bool force)
|
||||
}
|
||||
|
||||
|
||||
void SendSourceStateEvent(ALCcontext *context, ALuint id, ALenum state)
|
||||
void SendSourceStateEvent(ALCcontext *context, uint id, VChangeState state)
|
||||
{
|
||||
RingBuffer *ring{context->mAsyncEvents.get()};
|
||||
auto evt_vec = ring->getWriteVector();
|
||||
@@ -1588,7 +1588,7 @@ void ProcessVoiceChanges(ALCcontext *ctx)
|
||||
cur = next;
|
||||
|
||||
bool sendevt{false};
|
||||
if(cur->mState == AL_INITIAL || cur->mState == AL_STOPPED)
|
||||
if(cur->mState == VChangeState::Reset || cur->mState == VChangeState::Stop)
|
||||
{
|
||||
if(Voice *voice{cur->mVoice})
|
||||
{
|
||||
@@ -1603,16 +1603,16 @@ void ProcessVoiceChanges(ALCcontext *ctx)
|
||||
/* AL_INITIAL state change events are always sent, even if the
|
||||
* voice is already stopped or even if there is no voice.
|
||||
*/
|
||||
sendevt |= (cur->mState == AL_INITIAL);
|
||||
sendevt |= (cur->mState == VChangeState::Reset);
|
||||
}
|
||||
else if(cur->mState == AL_PAUSED)
|
||||
else if(cur->mState == VChangeState::Pause)
|
||||
{
|
||||
Voice *voice{cur->mVoice};
|
||||
Voice::State oldvstate{Voice::Playing};
|
||||
sendevt = voice->mPlayState.compare_exchange_strong(oldvstate, Voice::Stopping,
|
||||
std::memory_order_release, std::memory_order_acquire);
|
||||
}
|
||||
else if(cur->mState == AL_PLAYING)
|
||||
else if(cur->mState == VChangeState::Play)
|
||||
{
|
||||
/* NOTE: When playing a voice, sending a source state change event
|
||||
* depends if there's an old voice to stop and if that stop is
|
||||
@@ -1636,7 +1636,7 @@ void ProcessVoiceChanges(ALCcontext *ctx)
|
||||
Voice *voice{cur->mVoice};
|
||||
voice->mPlayState.store(Voice::Playing, std::memory_order_release);
|
||||
}
|
||||
else if(cur->mState == AL_SAMPLE_OFFSET)
|
||||
else if(cur->mState == VChangeState::Restart)
|
||||
{
|
||||
/* Changing a voice offset never sends a source change event. */
|
||||
Voice *oldvoice{cur->mOldVoice};
|
||||
|
||||
+2
-1
@@ -60,6 +60,7 @@
|
||||
#include "ringbuffer.h"
|
||||
#include "threads.h"
|
||||
#include "vector.h"
|
||||
#include "voice_change.h"
|
||||
|
||||
struct CTag;
|
||||
#ifdef HAVE_SSE
|
||||
@@ -184,7 +185,7 @@ void SendSourceStoppedEvent(ALCcontext *context, uint id)
|
||||
|
||||
AsyncEvent *evt{::new(evt_vec.first.buf) AsyncEvent{EventType_SourceStateChange}};
|
||||
evt->u.srcstate.id = id;
|
||||
evt->u.srcstate.state = AL_STOPPED;
|
||||
evt->u.srcstate.state = VChangeState::Stop;
|
||||
|
||||
ring->writeAdvance(1);
|
||||
}
|
||||
|
||||
+8
-1
@@ -10,11 +10,18 @@ struct Voice;
|
||||
using uint = unsigned int;
|
||||
|
||||
|
||||
enum class VChangeState {
|
||||
Reset,
|
||||
Stop,
|
||||
Play,
|
||||
Pause,
|
||||
Restart
|
||||
};
|
||||
struct VoiceChange {
|
||||
Voice *mOldVoice{nullptr};
|
||||
Voice *mVoice{nullptr};
|
||||
uint mSourceID{0};
|
||||
int mState{0};
|
||||
VChangeState mState{};
|
||||
|
||||
std::atomic<VoiceChange*> mNext{nullptr};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user