6 #include <condition_variable>
7 #include <unordered_map>
14 #if __cplusplus >= 201703L
17 #include "mpark/variant.hpp"
28 #define F_PI (3.14159265358979323846f)
30 #if !(__cplusplus >= 201703L)
35 using mpark::holds_alternative
;
43 class SourceGroupImpl
;
58 SOFT_source_resampler
,
59 SOFT_source_spatialize
,
69 // Batches OpenAL updates while the object is alive, if batching isn't already
75 Batcher(ALCcontext
*context
) : mContext(context
) { }
76 Batcher(Batcher
&& rhs
) : mContext(rhs
.mContext
) { rhs
.mContext
= nullptr; }
77 Batcher(const Batcher
&) = delete;
81 alcProcessContext(mContext
);
84 Batcher
& operator=(Batcher
&&) = delete;
85 Batcher
& operator=(const Batcher
&) = delete;
90 ContextImpl
*const mContext
;
93 ListenerImpl(ContextImpl
*ctx
) : mContext(ctx
) { }
95 void setGain(ALfloat gain
);
97 void set3DParameters(const Vector3
&position
, const Vector3
&velocity
, std::pair
<Vector3
,Vector3
> orientation
);
99 void setPosition(ALfloat x
, ALfloat y
, ALfloat z
);
100 void setPosition(const ALfloat
*pos
);
102 void setVelocity(ALfloat x
, ALfloat y
, ALfloat z
);
103 void setVelocity(const ALfloat
*vel
);
105 void setOrientation(ALfloat x1
, ALfloat y1
, ALfloat z1
, ALfloat x2
, ALfloat y2
, ALfloat z2
);
106 void setOrientation(const ALfloat
*at
, const ALfloat
*up
);
107 void setOrientation(const ALfloat
*ori
);
109 void setMetersPerUnit(ALfloat m_u
);
113 using DecoderOrExceptT
= std::variant
<SharedPtr
<Decoder
>,std::runtime_error
>;
114 using BufferOrExceptT
= std::variant
<Buffer
,std::runtime_error
>;
117 static ContextImpl
*sCurrentCtx
;
118 static thread_local ContextImpl
*sThreadCurrentCtx
;
121 static void MakeCurrent(ContextImpl
*context
);
122 static ContextImpl
*GetCurrent() { return sThreadCurrentCtx
? sThreadCurrentCtx
: sCurrentCtx
; }
124 static void MakeThreadCurrent(ContextImpl
*context
);
125 static ContextImpl
*GetThreadCurrent() { return sThreadCurrentCtx
; }
128 ListenerImpl mListener
;
129 ALCcontext
*mContext
;
130 std::stack
<ALuint
> mSourceIds
;
132 DeviceImpl
*const mDevice
;
133 std::unordered_map
<String
,SharedFuture
<Buffer
>> mFutureBuffers
;
134 Vector
<UniquePtr
<BufferImpl
>> mBuffers
;
135 Vector
<UniquePtr
<SourceGroupImpl
>> mSourceGroups
;
136 std::deque
<SourceImpl
> mAllSources
;
137 std::queue
<SourceImpl
*> mFreeSources
;
138 Vector
<SourceBufferUpdateEntry
> mPlaySources
;
139 Vector
<SourceStreamUpdateEntry
> mStreamSources
;
141 Vector
<SourceImpl
*> mStreamingSources
;
142 std::mutex mSourceStreamMutex
;
144 std::atomic
<std::chrono::milliseconds
> mWakeInterval
;
145 std::mutex mWakeMutex
;
146 std::condition_variable mWakeThread
;
148 SharedPtr
<MessageHandler
> mMessage
;
150 struct PendingBuffer
{
153 SharedPtr
<Decoder
> mDecoder
;
156 Promise
<Buffer
> mPromise
;
160 RingBuffer mPendingBuffers
;
162 std::atomic
<bool> mQuitThread
;
164 void backgroundProc();
168 Vector
<String
> mResamplers
;
170 bool mHasExt
[AL_EXTENSION_MAX
];
172 std::once_flag mSetExts
;
175 DecoderOrExceptT
findDecoder(const String
&name
);
176 BufferOrExceptT
doCreateBuffer(const String
&name
, Vector
<UniquePtr
<BufferImpl
>>::iterator iter
, SharedPtr
<Decoder
> decoder
);
177 BufferOrExceptT
doCreateBufferAsync(const String
&name
, Vector
<UniquePtr
<BufferImpl
>>::iterator iter
, SharedPtr
<Decoder
> decoder
, Promise
<Buffer
> promise
);
179 bool mIsConnected
: 1;
180 bool mIsBatching
: 1;
183 ContextImpl(ALCcontext
*context
, DeviceImpl
*device
);
186 ALCcontext
*getContext() const { return mContext
; }
187 long addRef() { return ++mRefs
; }
188 long decRef() { return --mRefs
; }
190 bool hasExtension(ALExtension ext
) const { return mHasExt
[ext
]; }
192 LPALGETSTRINGISOFT alGetStringiSOFT
;
193 LPALGETSOURCEI64VSOFT alGetSourcei64vSOFT
;
194 LPALGETSOURCEDVSOFT alGetSourcedvSOFT
;
196 LPALGENEFFECTS alGenEffects
;
197 LPALDELETEEFFECTS alDeleteEffects
;
198 LPALISEFFECT alIsEffect
;
199 LPALEFFECTI alEffecti
;
200 LPALEFFECTIV alEffectiv
;
201 LPALEFFECTF alEffectf
;
202 LPALEFFECTFV alEffectfv
;
203 LPALGETEFFECTI alGetEffecti
;
204 LPALGETEFFECTIV alGetEffectiv
;
205 LPALGETEFFECTF alGetEffectf
;
206 LPALGETEFFECTFV alGetEffectfv
;
208 LPALGENFILTERS alGenFilters
;
209 LPALDELETEFILTERS alDeleteFilters
;
210 LPALISFILTER alIsFilter
;
211 LPALFILTERI alFilteri
;
212 LPALFILTERIV alFilteriv
;
213 LPALFILTERF alFilterf
;
214 LPALFILTERFV alFilterfv
;
215 LPALGETFILTERI alGetFilteri
;
216 LPALGETFILTERIV alGetFilteriv
;
217 LPALGETFILTERF alGetFilterf
;
218 LPALGETFILTERFV alGetFilterfv
;
220 LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots
;
221 LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots
;
222 LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot
;
223 LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti
;
224 LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv
;
225 LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf
;
226 LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv
;
227 LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti
;
228 LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv
;
229 LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf
;
230 LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv
;
232 ALuint
getSourceId(ALuint maxprio
);
233 void insertSourceId(ALuint id
) { mSourceIds
.push(id
); }
235 void addPlayingSource(SourceImpl
*source
, ALuint id
);
236 void addPlayingSource(SourceImpl
*source
);
237 void removePlayingSource(SourceImpl
*source
);
239 void addStream(SourceImpl
*source
);
240 void removeStream(SourceImpl
*source
);
241 void removeStreamNoLock(SourceImpl
*source
);
243 void freeSourceGroup(SourceGroupImpl
*group
);
248 return Batcher(nullptr);
249 alcSuspendContext(mContext
);
250 return Batcher(mContext
);
253 std::unique_lock
<std::mutex
> getSourceStreamLock()
254 { return std::unique_lock
<std::mutex
>(mSourceStreamMutex
); }
256 template<typename R
, typename
... Args
>
257 void send(R
MessageHandler::* func
, Args
&&... args
)
258 { if(mMessage
.get()) (mMessage
.get()->*func
)(std::forward
<Args
>(args
)...); }
260 Device
getDevice() { return Device(mDevice
); }
267 Listener
getListener() { return Listener(&mListener
); }
269 SharedPtr
<MessageHandler
> setMessageHandler(SharedPtr
<MessageHandler
> handler
);
270 SharedPtr
<MessageHandler
> getMessageHandler() const { return mMessage
; }
272 void setAsyncWakeInterval(std::chrono::milliseconds interval
);
273 std::chrono::milliseconds
getAsyncWakeInterval() const { return mWakeInterval
.load(); }
275 SharedPtr
<Decoder
> createDecoder(const String
&name
);
277 bool isSupported(ChannelConfig channels
, SampleType type
) const;
279 ArrayView
<String
> getAvailableResamplers();
280 ALsizei
getDefaultResamplerIndex() const;
282 Buffer
getBuffer(const String
&name
);
283 SharedFuture
<Buffer
> getBufferAsync(const String
&name
);
284 void precacheBuffersAsync(ArrayView
<String
> names
);
285 Buffer
createBufferFrom(const String
&name
, SharedPtr
<Decoder
> decoder
);
286 SharedFuture
<Buffer
> createBufferAsyncFrom(const String
&name
, SharedPtr
<Decoder
> decoder
);
287 void removeBuffer(const String
&name
);
288 void removeBuffer(Buffer buffer
) { removeBuffer(buffer
.getName()); }
290 Source
createSource();
292 AuxiliaryEffectSlot
createAuxiliaryEffectSlot();
294 Effect
createEffect();
296 SourceGroup
createSourceGroup(String name
);
297 SourceGroup
getSourceGroup(const String
&name
);
299 void setDopplerFactor(ALfloat factor
);
301 void setSpeedOfSound(ALfloat speed
);
303 void setDistanceModel(DistanceModel model
);
309 inline void CheckContext(const ContextImpl
*ctx
)
311 if(EXPECT(ctx
!= ContextImpl::GetCurrent(), false))
312 throw std::runtime_error("Called context is not current");
317 #endif /* CONTEXT_H */