6 #include <condition_variable>
7 #include <unordered_map>
14 #if __cplusplus >= 201703L
17 #include "mpark/variant.hpp"
24 #define F_PI (3.14159265358979323846f)
26 #if !(__cplusplus >= 201703L)
31 using mpark::holds_alternative
;
50 SOFT_source_resampler
,
51 SOFT_source_spatialize
,
61 // Batches OpenAL updates while the object is alive, if batching isn't already
67 Batcher(ALCcontext
*context
) : mContext(context
) { }
68 Batcher(Batcher
&& rhs
) : mContext(rhs
.mContext
) { rhs
.mContext
= nullptr; }
69 Batcher(const Batcher
&) = delete;
73 alcProcessContext(mContext
);
76 Batcher
& operator=(Batcher
&&) = delete;
77 Batcher
& operator=(const Batcher
&) = delete;
82 ContextImpl
*const mContext
;
85 ListenerImpl(ContextImpl
*ctx
) : mContext(ctx
) { }
87 void setGain(ALfloat gain
);
89 void set3DParameters(const Vector3
&position
, const Vector3
&velocity
, const std::pair
<Vector3
,Vector3
> &orientation
);
91 void setPosition(ALfloat x
, ALfloat y
, ALfloat z
);
92 void setPosition(const ALfloat
*pos
);
94 void setVelocity(ALfloat x
, ALfloat y
, ALfloat z
);
95 void setVelocity(const ALfloat
*vel
);
97 void setOrientation(ALfloat x1
, ALfloat y1
, ALfloat z1
, ALfloat x2
, ALfloat y2
, ALfloat z2
);
98 void setOrientation(const ALfloat
*at
, const ALfloat
*up
);
99 void setOrientation(const ALfloat
*ori
);
101 void setMetersPerUnit(ALfloat m_u
);
105 using DecoderOrExceptT
= std::variant
<SharedPtr
<Decoder
>,std::runtime_error
>;
106 using BufferOrExceptT
= std::variant
<Buffer
,std::runtime_error
>;
109 static ContextImpl
*sCurrentCtx
;
110 static thread_local ContextImpl
*sThreadCurrentCtx
;
113 static void MakeCurrent(ContextImpl
*context
);
114 static ContextImpl
*GetCurrent()
116 auto thrd_ctx
= sThreadCurrentCtx
;
117 return thrd_ctx
? thrd_ctx
: sCurrentCtx
;
120 static void MakeThreadCurrent(ContextImpl
*context
);
121 static ContextImpl
*GetThreadCurrent() { return sThreadCurrentCtx
; }
123 static std::atomic
<uint64_t> sContextSetCount
;
124 mutable uint64_t mContextSetCounter
;
127 ListenerImpl mListener
;
128 ALCcontext
*mContext
;
129 std::stack
<ALuint
> mSourceIds
;
131 struct PendingFuture
{ BufferImpl
*mBuffer
; SharedFuture
<Buffer
> mFuture
; };
132 struct PendingSource
{ SourceImpl
*mSource
; SharedFuture
<Buffer
> mFuture
; };
134 DeviceImpl
*const mDevice
;
135 Vector
<PendingFuture
> mFutureBuffers
;
136 Vector
<UniquePtr
<BufferImpl
>> mBuffers
;
137 Vector
<UniquePtr
<SourceGroupImpl
>> mSourceGroups
;
138 std::deque
<SourceImpl
> mAllSources
;
139 Vector
<SourceImpl
*> mFreeSources
;
141 Vector
<PendingSource
> mPendingSources
;
142 Vector
<SourceImpl
*> mFadingSources
;
143 Vector
<SourceBufferUpdateEntry
> mPlaySources
;
144 Vector
<SourceStreamUpdateEntry
> mStreamSources
;
146 Vector
<SourceImpl
*> mStreamingSources
;
147 std::mutex mSourceStreamMutex
;
149 std::atomic
<std::chrono::milliseconds
> mWakeInterval
;
150 std::mutex mWakeMutex
;
151 std::condition_variable mWakeThread
;
153 SharedPtr
<MessageHandler
> mMessage
;
155 struct PendingBuffer
{
156 BufferImpl
*mBuffer
{nullptr};
157 SharedPtr
<Decoder
> mDecoder
;
160 Promise
<Buffer
> mPromise
;
162 std::atomic
<PendingBuffer
*> mNext
{nullptr};
164 PendingBuffer() = default;
165 PendingBuffer(BufferImpl
*buffer
, SharedPtr
<Decoder
> decoder
, ALenum format
, ALuint frames
,
166 Promise
<Buffer
> promise
)
167 : mBuffer(buffer
), mDecoder(std::move(decoder
)), mFormat(format
), mFrames(frames
)
168 , mPromise(std::move(promise
)), mNext(nullptr)
171 std::atomic
<PendingBuffer
*> mPendingCurrent
;
172 PendingBuffer
*mPendingTail
;
173 PendingBuffer
*mPendingHead
;
175 std::atomic
<bool> mQuitThread
;
177 void backgroundProc();
181 Vector
<String
> mResamplers
;
183 Bitfield
<static_cast<size_t>(AL::EXTENSION_MAX
)> mHasExt
;
185 std::once_flag mSetExts
;
188 DecoderOrExceptT
findDecoder(StringView name
);
189 BufferOrExceptT
doCreateBuffer(StringView name
, Vector
<UniquePtr
<BufferImpl
>>::iterator iter
, SharedPtr
<Decoder
> decoder
);
190 BufferOrExceptT
doCreateBufferAsync(StringView name
, Vector
<UniquePtr
<BufferImpl
>>::iterator iter
, SharedPtr
<Decoder
> decoder
, Promise
<Buffer
> promise
);
192 bool mIsConnected
: 1;
193 bool mIsBatching
: 1;
196 ContextImpl(ALCcontext
*context
, DeviceImpl
*device
);
199 ALCcontext
*getALCcontext() const { return mContext
; }
200 long addRef() { return ++mRefs
; }
201 long decRef() { return --mRefs
; }
203 bool hasExtension(AL ext
) const { return mHasExt
[static_cast<size_t>(ext
)]; }
205 LPALGETSTRINGISOFT alGetStringiSOFT
;
206 LPALGETSOURCEI64VSOFT alGetSourcei64vSOFT
;
207 LPALGETSOURCEDVSOFT alGetSourcedvSOFT
;
209 LPALGENEFFECTS alGenEffects
;
210 LPALDELETEEFFECTS alDeleteEffects
;
211 LPALISEFFECT alIsEffect
;
212 LPALEFFECTI alEffecti
;
213 LPALEFFECTIV alEffectiv
;
214 LPALEFFECTF alEffectf
;
215 LPALEFFECTFV alEffectfv
;
216 LPALGETEFFECTI alGetEffecti
;
217 LPALGETEFFECTIV alGetEffectiv
;
218 LPALGETEFFECTF alGetEffectf
;
219 LPALGETEFFECTFV alGetEffectfv
;
221 LPALGENFILTERS alGenFilters
;
222 LPALDELETEFILTERS alDeleteFilters
;
223 LPALISFILTER alIsFilter
;
224 LPALFILTERI alFilteri
;
225 LPALFILTERIV alFilteriv
;
226 LPALFILTERF alFilterf
;
227 LPALFILTERFV alFilterfv
;
228 LPALGETFILTERI alGetFilteri
;
229 LPALGETFILTERIV alGetFilteriv
;
230 LPALGETFILTERF alGetFilterf
;
231 LPALGETFILTERFV alGetFilterfv
;
233 LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots
;
234 LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots
;
235 LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot
;
236 LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti
;
237 LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv
;
238 LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf
;
239 LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv
;
240 LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti
;
241 LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv
;
242 LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf
;
243 LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv
;
245 ALuint
getSourceId(ALuint maxprio
);
246 void insertSourceId(ALuint id
) { mSourceIds
.push(id
); }
248 void addPendingSource(SourceImpl
*source
, SharedFuture
<Buffer
> future
);
249 void removePendingSource(SourceImpl
*source
);
250 bool isPendingSource(const SourceImpl
*source
) const;
251 void addFadingSource(SourceImpl
*source
);
252 void removeFadingSource(SourceImpl
*source
);
253 void addPlayingSource(SourceImpl
*source
, ALuint id
);
254 void addPlayingSource(SourceImpl
*source
);
255 void removePlayingSource(SourceImpl
*source
);
257 void addStream(SourceImpl
*source
);
258 void removeStream(SourceImpl
*source
);
259 void removeStreamNoLock(SourceImpl
*source
);
261 void freeSource(SourceImpl
*source
) { mFreeSources
.push_back(source
); }
262 void freeSourceGroup(SourceGroupImpl
*group
);
267 return Batcher(nullptr);
268 alcSuspendContext(mContext
);
269 return Batcher(mContext
);
272 std::unique_lock
<std::mutex
> getSourceStreamLock()
273 { return std::unique_lock
<std::mutex
>(mSourceStreamMutex
); }
275 template<typename R
, typename
... Args
>
276 void send(R
MessageHandler::* func
, Args
&&... args
)
277 { if(mMessage
.get()) (mMessage
.get()->*func
)(std::forward
<Args
>(args
)...); }
279 Device
getDevice() { return Device(mDevice
); }
286 Listener
getListener() { return Listener(&mListener
); }
288 SharedPtr
<MessageHandler
> setMessageHandler(SharedPtr
<MessageHandler
>&& handler
);
289 SharedPtr
<MessageHandler
> getMessageHandler() const { return mMessage
; }
291 void setAsyncWakeInterval(std::chrono::milliseconds interval
);
292 std::chrono::milliseconds
getAsyncWakeInterval() const { return mWakeInterval
.load(); }
294 SharedPtr
<Decoder
> createDecoder(StringView name
);
296 bool isSupported(ChannelConfig channels
, SampleType type
) const;
298 ArrayView
<String
> getAvailableResamplers();
299 ALsizei
getDefaultResamplerIndex() const;
301 Buffer
getBuffer(StringView name
);
302 SharedFuture
<Buffer
> getBufferAsync(StringView name
);
303 void precacheBuffersAsync(ArrayView
<StringView
> names
);
304 Buffer
createBufferFrom(StringView name
, SharedPtr
<Decoder
>&& decoder
);
305 SharedFuture
<Buffer
> createBufferAsyncFrom(StringView name
, SharedPtr
<Decoder
>&& decoder
);
306 Buffer
findBuffer(StringView name
);
307 SharedFuture
<Buffer
> findBufferAsync(StringView name
);
308 void removeBuffer(StringView name
);
309 void removeBuffer(Buffer buffer
) { removeBuffer(buffer
.getName()); }
311 Source
createSource();
313 AuxiliaryEffectSlot
createAuxiliaryEffectSlot();
315 Effect
createEffect();
317 SourceGroup
createSourceGroup(StringView name
);
318 SourceGroup
getSourceGroup(StringView name
);
320 void setDopplerFactor(ALfloat factor
);
322 void setSpeedOfSound(ALfloat speed
);
324 void setDistanceModel(DistanceModel model
);
330 inline void CheckContext(const ContextImpl
*ctx
)
332 auto count
= ContextImpl::sContextSetCount
.load(std::memory_order_acquire
);
333 if(UNLIKELY(count
!= ctx
->mContextSetCounter
))
335 if(UNLIKELY(ctx
!= ContextImpl::GetCurrent()))
336 throw std::runtime_error("Called context is not current");
337 ctx
->mContextSetCounter
= count
;
341 inline void CheckContexts(const ContextImpl
*ctx0
, const ContextImpl
*ctx1
)
343 if(UNLIKELY(ctx0
!= ctx1
))
344 throw std::runtime_error("Mismatched object contexts");
350 #endif /* CONTEXT_H */