6 #include <condition_variable>
7 #include <unordered_map>
14 #if __cplusplus >= 201703L
17 #include "mpark/variant.hpp"
27 #define F_PI (3.14159265358979323846f)
29 #if !(__cplusplus >= 201703L)
34 using mpark::holds_alternative
;
53 SOFT_source_resampler
,
54 SOFT_source_spatialize
,
64 // Batches OpenAL updates while the object is alive, if batching isn't already
70 Batcher(ALCcontext
*context
) : mContext(context
) { }
71 Batcher(Batcher
&& rhs
) : mContext(rhs
.mContext
) { rhs
.mContext
= nullptr; }
72 Batcher(const Batcher
&) = delete;
76 alcProcessContext(mContext
);
79 Batcher
& operator=(Batcher
&&) = delete;
80 Batcher
& operator=(const Batcher
&) = delete;
85 ContextImpl
*const mContext
;
88 ListenerImpl(ContextImpl
*ctx
) : mContext(ctx
) { }
90 void setGain(ALfloat gain
);
92 void set3DParameters(const Vector3
&position
, const Vector3
&velocity
, std::pair
<Vector3
,Vector3
> orientation
);
94 void setPosition(ALfloat x
, ALfloat y
, ALfloat z
);
95 void setPosition(const ALfloat
*pos
);
97 void setVelocity(ALfloat x
, ALfloat y
, ALfloat z
);
98 void setVelocity(const ALfloat
*vel
);
100 void setOrientation(ALfloat x1
, ALfloat y1
, ALfloat z1
, ALfloat x2
, ALfloat y2
, ALfloat z2
);
101 void setOrientation(const ALfloat
*at
, const ALfloat
*up
);
102 void setOrientation(const ALfloat
*ori
);
104 void setMetersPerUnit(ALfloat m_u
);
108 using DecoderOrExceptT
= std::variant
<SharedPtr
<Decoder
>,std::runtime_error
>;
109 using BufferOrExceptT
= std::variant
<Buffer
,std::runtime_error
>;
112 static ContextImpl
*sCurrentCtx
;
113 static thread_local ContextImpl
*sThreadCurrentCtx
;
116 static void MakeCurrent(ContextImpl
*context
);
117 static ContextImpl
*GetCurrent() { return sThreadCurrentCtx
? sThreadCurrentCtx
: sCurrentCtx
; }
119 static void MakeThreadCurrent(ContextImpl
*context
);
120 static ContextImpl
*GetThreadCurrent() { return sThreadCurrentCtx
; }
123 ListenerImpl mListener
;
124 ALCcontext
*mContext
;
125 std::stack
<ALuint
> mSourceIds
;
127 struct PendingFuture
{ BufferImpl
*mBuffer
; SharedFuture
<Buffer
> mFuture
; };
129 DeviceImpl
*const mDevice
;
130 Vector
<PendingFuture
> mFutureBuffers
;
131 Vector
<UniquePtr
<BufferImpl
>> mBuffers
;
132 Vector
<UniquePtr
<SourceGroupImpl
>> mSourceGroups
;
133 std::deque
<SourceImpl
> mAllSources
;
134 Vector
<SourceImpl
*> mFreeSources
;
135 Vector
<SourceBufferUpdateEntry
> mPlaySources
;
136 Vector
<SourceStreamUpdateEntry
> mStreamSources
;
137 Vector
<SourceImpl
*> mFadingSources
;
139 Vector
<SourceImpl
*> mStreamingSources
;
140 std::mutex mSourceStreamMutex
;
142 std::atomic
<std::chrono::milliseconds
> mWakeInterval
;
143 std::mutex mWakeMutex
;
144 std::condition_variable mWakeThread
;
146 SharedPtr
<MessageHandler
> mMessage
;
148 struct PendingBuffer
{
149 BufferImpl
*mBuffer
{nullptr};
150 SharedPtr
<Decoder
> mDecoder
;
153 Promise
<Buffer
> mPromise
;
155 std::atomic
<PendingBuffer
*> mNext
{nullptr};
157 PendingBuffer() = default;
158 PendingBuffer(BufferImpl
*buffer
, SharedPtr
<Decoder
> decoder
, ALenum format
, ALuint frames
,
159 Promise
<Buffer
> promise
)
160 : mBuffer(buffer
), mDecoder(std::move(decoder
)), mFormat(format
), mFrames(frames
)
161 , mPromise(std::move(promise
)), mNext(nullptr)
164 std::atomic
<PendingBuffer
*> mPendingCurrent
;
165 PendingBuffer
*mPendingTail
;
166 PendingBuffer
*mPendingHead
;
168 std::atomic
<bool> mQuitThread
;
170 void backgroundProc();
174 Vector
<String
> mResamplers
;
176 bool mHasExt
[AL_EXTENSION_MAX
];
178 std::once_flag mSetExts
;
181 DecoderOrExceptT
findDecoder(StringView name
);
182 BufferOrExceptT
doCreateBuffer(StringView name
, Vector
<UniquePtr
<BufferImpl
>>::iterator iter
, SharedPtr
<Decoder
> decoder
);
183 BufferOrExceptT
doCreateBufferAsync(StringView name
, Vector
<UniquePtr
<BufferImpl
>>::iterator iter
, SharedPtr
<Decoder
> decoder
, Promise
<Buffer
> promise
);
185 bool mIsConnected
: 1;
186 bool mIsBatching
: 1;
189 ContextImpl(ALCcontext
*context
, DeviceImpl
*device
);
192 ALCcontext
*getContext() const { return mContext
; }
193 long addRef() { return ++mRefs
; }
194 long decRef() { return --mRefs
; }
196 bool hasExtension(ALExtension ext
) const { return mHasExt
[ext
]; }
198 LPALGETSTRINGISOFT alGetStringiSOFT
;
199 LPALGETSOURCEI64VSOFT alGetSourcei64vSOFT
;
200 LPALGETSOURCEDVSOFT alGetSourcedvSOFT
;
202 LPALGENEFFECTS alGenEffects
;
203 LPALDELETEEFFECTS alDeleteEffects
;
204 LPALISEFFECT alIsEffect
;
205 LPALEFFECTI alEffecti
;
206 LPALEFFECTIV alEffectiv
;
207 LPALEFFECTF alEffectf
;
208 LPALEFFECTFV alEffectfv
;
209 LPALGETEFFECTI alGetEffecti
;
210 LPALGETEFFECTIV alGetEffectiv
;
211 LPALGETEFFECTF alGetEffectf
;
212 LPALGETEFFECTFV alGetEffectfv
;
214 LPALGENFILTERS alGenFilters
;
215 LPALDELETEFILTERS alDeleteFilters
;
216 LPALISFILTER alIsFilter
;
217 LPALFILTERI alFilteri
;
218 LPALFILTERIV alFilteriv
;
219 LPALFILTERF alFilterf
;
220 LPALFILTERFV alFilterfv
;
221 LPALGETFILTERI alGetFilteri
;
222 LPALGETFILTERIV alGetFilteriv
;
223 LPALGETFILTERF alGetFilterf
;
224 LPALGETFILTERFV alGetFilterfv
;
226 LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots
;
227 LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots
;
228 LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot
;
229 LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti
;
230 LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv
;
231 LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf
;
232 LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv
;
233 LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti
;
234 LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv
;
235 LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf
;
236 LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv
;
238 ALuint
getSourceId(ALuint maxprio
);
239 void insertSourceId(ALuint id
) { mSourceIds
.push(id
); }
241 void addFadingSource(SourceImpl
*source
);
242 void removeFadingSource(SourceImpl
*source
);
243 void addPlayingSource(SourceImpl
*source
, ALuint id
);
244 void addPlayingSource(SourceImpl
*source
);
245 void removePlayingSource(SourceImpl
*source
);
247 void addStream(SourceImpl
*source
);
248 void removeStream(SourceImpl
*source
);
249 void removeStreamNoLock(SourceImpl
*source
);
251 void freeSource(SourceImpl
*source
) { mFreeSources
.push_back(source
); }
252 void freeSourceGroup(SourceGroupImpl
*group
);
257 return Batcher(nullptr);
258 alcSuspendContext(mContext
);
259 return Batcher(mContext
);
262 std::unique_lock
<std::mutex
> getSourceStreamLock()
263 { return std::unique_lock
<std::mutex
>(mSourceStreamMutex
); }
265 template<typename R
, typename
... Args
>
266 void send(R
MessageHandler::* func
, Args
&&... args
)
267 { if(mMessage
.get()) (mMessage
.get()->*func
)(std::forward
<Args
>(args
)...); }
269 Device
getDevice() { return Device(mDevice
); }
276 Listener
getListener() { return Listener(&mListener
); }
278 SharedPtr
<MessageHandler
> setMessageHandler(SharedPtr
<MessageHandler
> handler
);
279 SharedPtr
<MessageHandler
> getMessageHandler() const { return mMessage
; }
281 void setAsyncWakeInterval(std::chrono::milliseconds interval
);
282 std::chrono::milliseconds
getAsyncWakeInterval() const { return mWakeInterval
.load(); }
284 SharedPtr
<Decoder
> createDecoder(StringView name
);
286 bool isSupported(ChannelConfig channels
, SampleType type
) const;
288 ArrayView
<String
> getAvailableResamplers();
289 ALsizei
getDefaultResamplerIndex() const;
291 Buffer
getBuffer(StringView name
);
292 SharedFuture
<Buffer
> getBufferAsync(StringView name
);
293 void precacheBuffersAsync(ArrayView
<StringView
> names
);
294 Buffer
createBufferFrom(StringView name
, SharedPtr
<Decoder
> decoder
);
295 SharedFuture
<Buffer
> createBufferAsyncFrom(StringView name
, SharedPtr
<Decoder
> decoder
);
296 void removeBuffer(StringView name
);
297 void removeBuffer(Buffer buffer
) { removeBuffer(buffer
.getName()); }
299 Source
createSource();
301 AuxiliaryEffectSlot
createAuxiliaryEffectSlot();
303 Effect
createEffect();
305 SourceGroup
createSourceGroup(StringView name
);
306 SourceGroup
getSourceGroup(StringView name
);
308 void setDopplerFactor(ALfloat factor
);
310 void setSpeedOfSound(ALfloat speed
);
312 void setDistanceModel(DistanceModel model
);
318 inline void CheckContext(const ContextImpl
*ctx
)
320 if(Expect
<false>(ctx
!= ContextImpl::GetCurrent()))
321 throw std::runtime_error("Called context is not current");
326 #endif /* CONTEXT_H */