6 #include <condition_variable>
7 #include <unordered_map>
14 // TODO: Can use <variant> with a C++17-compliant compiler.
15 #include "mpark/variant.hpp"
25 #define F_PI (3.14159265358979323846f)
29 // TODO: Can use std::variant stuff with a C++17-compliant compiler.
31 using AddPointerT
= typename
std::add_pointer
<T
>::type
;
32 template<typename
...Ts
>
33 using Variant
= mpark::variant
<Ts
...>;
34 template<typename T
, typename
...Ts
>
35 inline constexpr T
& Get(Variant
<Ts
...> &v
) { return mpark::get
<T
>(v
); }
36 template<size_t I
, typename
...Ts
>
37 inline constexpr mpark::variant_alternative_t
<I
,Variant
<Ts
...>>& Get(Variant
<Ts
...> &v
) { return mpark::get
<I
>(v
); }
38 template<typename T
, typename
...Ts
>
39 inline constexpr AddPointerT
<T
> GetIf(Variant
<Ts
...> *v
) noexcept
{ return mpark::get_if
<T
>(v
); }
40 template<size_t I
, typename
...Ts
>
41 inline constexpr AddPointerT
<mpark::variant_alternative_t
<I
,Variant
<Ts
...>>> GetIf(Variant
<Ts
...> *v
) noexcept
{ return mpark::get_if
<I
>(v
); }
60 SOFT_source_resampler
,
61 SOFT_source_spatialize
,
71 // Batches OpenAL updates while the object is alive, if batching isn't already
77 Batcher(ALCcontext
*context
) : mContext(context
) { }
78 Batcher(Batcher
&& rhs
) : mContext(rhs
.mContext
) { rhs
.mContext
= nullptr; }
79 Batcher(const Batcher
&) = delete;
83 alcProcessContext(mContext
);
86 Batcher
& operator=(Batcher
&&) = delete;
87 Batcher
& operator=(const Batcher
&) = delete;
92 ALContext
*const mContext
;
95 ALListener(ALContext
*ctx
) : mContext(ctx
) { }
97 void setGain(ALfloat gain
);
99 void set3DParameters(const Vector3
&position
, const Vector3
&velocity
, std::pair
<Vector3
,Vector3
> orientation
);
101 void setPosition(ALfloat x
, ALfloat y
, ALfloat z
);
102 void setPosition(const ALfloat
*pos
);
104 void setVelocity(ALfloat x
, ALfloat y
, ALfloat z
);
105 void setVelocity(const ALfloat
*vel
);
107 void setOrientation(ALfloat x1
, ALfloat y1
, ALfloat z1
, ALfloat x2
, ALfloat y2
, ALfloat z2
);
108 void setOrientation(const ALfloat
*at
, const ALfloat
*up
);
109 void setOrientation(const ALfloat
*ori
);
111 void setMetersPerUnit(ALfloat m_u
);
115 using BufferOrExceptT
= Variant
<Buffer
,std::runtime_error
>;
118 static ALContext
*sCurrentCtx
;
119 static thread_local ALContext
*sThreadCurrentCtx
;
122 static void MakeCurrent(ALContext
*context
);
123 static ALContext
*GetCurrent() { return sThreadCurrentCtx
? sThreadCurrentCtx
: sCurrentCtx
; }
125 static void MakeThreadCurrent(ALContext
*context
);
126 static ALContext
*GetThreadCurrent() { return sThreadCurrentCtx
; }
129 ALListener mListener
;
130 ALCcontext
*mContext
;
131 std::stack
<ALuint
> mSourceIds
;
133 ALDevice
*const mDevice
;
134 std::deque
<ALSource
> mAllSources
;
135 std::queue
<ALSource
*> mFreeSources
;
136 Vector
<ALSource
*> mUsedSources
;
138 Vector
<UniquePtr
<ALBuffer
>> mBuffers
;
140 Vector
<UniquePtr
<ALSourceGroup
>> mSourceGroups
;
144 Vector
<String
> mResamplers
;
146 SharedPtr
<MessageHandler
> mMessage
;
148 bool mHasExt
[AL_EXTENSION_MAX
];
150 struct PendingBuffer
{
153 SharedPtr
<Decoder
> mDecoder
;
159 RingBuffer mPendingBuffers
;
161 Vector
<ALSource
*> mStreamingSources
;
162 std::mutex mSourceStreamMutex
;
164 std::atomic
<std::chrono::milliseconds
> mWakeInterval
;
165 std::mutex mWakeMutex
;
166 std::condition_variable mWakeThread
;
168 std::mutex mContextMutex
;
170 std::atomic
<bool> mQuitThread
;
172 void backgroundProc();
174 std::once_flag mSetExts
;
177 BufferOrExceptT
doCreateBuffer(const String
&name
, Vector
<UniquePtr
<ALBuffer
>>::iterator iter
, SharedPtr
<Decoder
> decoder
);
178 BufferOrExceptT
doCreateBufferAsync(const String
&name
, Vector
<UniquePtr
<ALBuffer
>>::iterator iter
, SharedPtr
<Decoder
> decoder
);
180 bool mIsConnected
: 1;
181 bool mIsBatching
: 1;
184 ALContext(ALCcontext
*context
, ALDevice
*device
);
187 ALCcontext
*getContext() const { return mContext
; }
188 long addRef() { return ++mRefs
; }
189 long decRef() { return --mRefs
; }
191 bool hasExtension(ALExtension ext
) const { return mHasExt
[ext
]; }
193 LPALGETSTRINGISOFT alGetStringiSOFT
;
194 LPALGETSOURCEI64VSOFT alGetSourcei64vSOFT
;
195 LPALGETSOURCEDVSOFT alGetSourcedvSOFT
;
197 LPALGENEFFECTS alGenEffects
;
198 LPALDELETEEFFECTS alDeleteEffects
;
199 LPALISEFFECT alIsEffect
;
200 LPALEFFECTI alEffecti
;
201 LPALEFFECTIV alEffectiv
;
202 LPALEFFECTF alEffectf
;
203 LPALEFFECTFV alEffectfv
;
204 LPALGETEFFECTI alGetEffecti
;
205 LPALGETEFFECTIV alGetEffectiv
;
206 LPALGETEFFECTF alGetEffectf
;
207 LPALGETEFFECTFV alGetEffectfv
;
209 LPALGENFILTERS alGenFilters
;
210 LPALDELETEFILTERS alDeleteFilters
;
211 LPALISFILTER alIsFilter
;
212 LPALFILTERI alFilteri
;
213 LPALFILTERIV alFilteriv
;
214 LPALFILTERF alFilterf
;
215 LPALFILTERFV alFilterfv
;
216 LPALGETFILTERI alGetFilteri
;
217 LPALGETFILTERIV alGetFilteriv
;
218 LPALGETFILTERF alGetFilterf
;
219 LPALGETFILTERFV alGetFilterfv
;
221 LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots
;
222 LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots
;
223 LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot
;
224 LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti
;
225 LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv
;
226 LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf
;
227 LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv
;
228 LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti
;
229 LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv
;
230 LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf
;
231 LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv
;
233 ALuint
getSourceId(ALuint maxprio
);
234 void insertSourceId(ALuint id
) { mSourceIds
.push(id
); }
236 void addStream(ALSource
*source
);
237 void removeStream(ALSource
*source
);
238 void removeStreamNoLock(ALSource
*source
);
240 void freeSource(ALSource
*source
);
241 void freeSourceGroup(ALSourceGroup
*group
);
246 return Batcher(nullptr);
247 alcSuspendContext(mContext
);
248 return Batcher(mContext
);
251 std::unique_lock
<std::mutex
> getSourceStreamLock()
252 { return std::unique_lock
<std::mutex
>(mSourceStreamMutex
); }
254 template<typename R
, typename
... Args
>
255 void send(R
MessageHandler::* func
, Args
&&... args
)
256 { if(mMessage
.get()) (mMessage
.get()->*func
)(std::forward
<Args
>(args
)...); }
258 Device
getDevice() { return Device(mDevice
); }
265 Listener
getListener() { return Listener(&mListener
); }
267 SharedPtr
<MessageHandler
> setMessageHandler(SharedPtr
<MessageHandler
> handler
);
268 SharedPtr
<MessageHandler
> getMessageHandler() const { return mMessage
; }
270 void setAsyncWakeInterval(std::chrono::milliseconds msec
);
271 std::chrono::milliseconds
getAsyncWakeInterval() const { return mWakeInterval
.load(); }
273 SharedPtr
<Decoder
> createDecoder(const String
&name
);
275 bool isSupported(ChannelConfig channels
, SampleType type
) const;
277 const Vector
<String
> &getAvailableResamplers();
278 ALsizei
getDefaultResamplerIndex() const;
280 Buffer
getBuffer(const String
&name
);
281 Buffer
getBufferAsync(const String
&name
);
282 void precacheBuffersAsync(ArrayView
<String
> names
);
283 Buffer
createBufferFrom(const String
&name
, SharedPtr
<Decoder
> decoder
);
284 Buffer
createBufferAsyncFrom(const String
&name
, SharedPtr
<Decoder
> decoder
);
285 void removeBuffer(const String
&name
);
286 void removeBuffer(Buffer buffer
) { removeBuffer(buffer
.getName()); }
288 Source
createSource();
290 AuxiliaryEffectSlot
createAuxiliaryEffectSlot();
292 Effect
createEffect();
294 SourceGroup
createSourceGroup(String name
);
295 SourceGroup
getSourceGroup(const String
&name
);
297 void setDopplerFactor(ALfloat factor
);
299 void setSpeedOfSound(ALfloat speed
);
301 void setDistanceModel(DistanceModel model
);
307 inline void CheckContext(const ALContext
*ctx
)
309 if(EXPECT(ctx
!= ALContext::GetCurrent(), false))
310 throw std::runtime_error("Called context is not current");
315 #endif /* CONTEXT_H */