Remove an unnecessary variable
[alure.git] / src / context.h
blob84ada801a2291432341e27b334c762a45e1ece6d
1 #ifndef CONTEXT_H
2 #define CONTEXT_H
4 #include "main.h"
6 #include <condition_variable>
7 #include <unordered_map>
8 #include <stdexcept>
9 #include <thread>
10 #include <mutex>
11 #include <stack>
12 #include <queue>
13 #include <set>
14 #if __cplusplus >= 201703L
15 #include <variant>
16 #else
17 #include "mpark/variant.hpp"
18 #endif
20 #include "alc.h"
21 #include "alext.h"
23 #include "refcount.h"
24 #include "ringbuf.h"
25 #include "device.h"
26 #include "source.h"
28 #define F_PI (3.14159265358979323846f)
30 #if !(__cplusplus >= 201703L)
31 namespace std {
32 using mpark::variant;
33 using mpark::get;
34 using mpark::get_if;
35 using mpark::holds_alternative;
36 } // namespace std
37 #endif
39 namespace alure {
41 enum ALExtension {
42 EXT_EFX,
44 EXT_FLOAT32,
45 EXT_MCFORMATS,
46 EXT_BFORMAT,
48 EXT_MULAW,
49 EXT_MULAW_MCFORMATS,
50 EXT_MULAW_BFORMAT,
52 SOFT_loop_points,
53 SOFT_source_latency,
54 SOFT_source_resampler,
55 SOFT_source_spatialize,
57 EXT_disconnect,
59 EXT_SOURCE_RADIUS,
60 EXT_STEREO_ANGLES,
62 AL_EXTENSION_MAX
65 // Batches OpenAL updates while the object is alive, if batching isn't already
66 // in progress.
67 class Batcher {
68 ALCcontext *mContext;
70 public:
71 Batcher(ALCcontext *context) : mContext(context) { }
72 Batcher(Batcher&& rhs) : mContext(rhs.mContext) { rhs.mContext = nullptr; }
73 Batcher(const Batcher&) = delete;
74 ~Batcher()
76 if(mContext)
77 alcProcessContext(mContext);
80 Batcher& operator=(Batcher&&) = delete;
81 Batcher& operator=(const Batcher&) = delete;
85 class ListenerImpl {
86 ContextImpl *const mContext;
88 public:
89 ListenerImpl(ContextImpl *ctx) : mContext(ctx) { }
91 void setGain(ALfloat gain);
93 void set3DParameters(const Vector3 &position, const Vector3 &velocity, std::pair<Vector3,Vector3> orientation);
95 void setPosition(ALfloat x, ALfloat y, ALfloat z);
96 void setPosition(const ALfloat *pos);
98 void setVelocity(ALfloat x, ALfloat y, ALfloat z);
99 void setVelocity(const ALfloat *vel);
101 void setOrientation(ALfloat x1, ALfloat y1, ALfloat z1, ALfloat x2, ALfloat y2, ALfloat z2);
102 void setOrientation(const ALfloat *at, const ALfloat *up);
103 void setOrientation(const ALfloat *ori);
105 void setMetersPerUnit(ALfloat m_u);
109 using DecoderOrExceptT = std::variant<SharedPtr<Decoder>,std::runtime_error>;
110 using BufferOrExceptT = std::variant<Buffer,std::runtime_error>;
112 class ContextImpl {
113 static ContextImpl *sCurrentCtx;
114 static thread_local ContextImpl *sThreadCurrentCtx;
116 public:
117 static void MakeCurrent(ContextImpl *context);
118 static ContextImpl *GetCurrent() { return sThreadCurrentCtx ? sThreadCurrentCtx : sCurrentCtx; }
120 static void MakeThreadCurrent(ContextImpl *context);
121 static ContextImpl *GetThreadCurrent() { return sThreadCurrentCtx; }
123 private:
124 ListenerImpl mListener;
125 ALCcontext *mContext;
126 std::stack<ALuint> mSourceIds;
128 struct PendingFuture { BufferImpl *mBuffer; SharedFuture<Buffer> mFuture; };
130 DeviceImpl *const mDevice;
131 Vector<PendingFuture> mFutureBuffers;
132 Vector<UniquePtr<BufferImpl>> mBuffers;
133 Vector<UniquePtr<SourceGroupImpl>> mSourceGroups;
134 std::deque<SourceImpl> mAllSources;
135 Vector<SourceImpl*> mFreeSources;
136 Vector<SourceBufferUpdateEntry> mPlaySources;
137 Vector<SourceStreamUpdateEntry> mStreamSources;
138 Vector<SourceImpl*> mFadingSources;
140 Vector<SourceImpl*> mStreamingSources;
141 std::mutex mSourceStreamMutex;
143 std::atomic<std::chrono::milliseconds> mWakeInterval;
144 std::mutex mWakeMutex;
145 std::condition_variable mWakeThread;
147 SharedPtr<MessageHandler> mMessage;
149 struct PendingBuffer {
150 BufferImpl *mBuffer;
151 SharedPtr<Decoder> mDecoder;
152 ALenum mFormat;
153 ALuint mFrames;
154 Promise<Buffer> mPromise;
156 ~PendingBuffer() { }
158 RingBuffer mPendingBuffers;
160 std::atomic<bool> mQuitThread;
161 std::thread mThread;
162 void backgroundProc();
164 RefCount mRefs;
166 Vector<String> mResamplers;
168 bool mHasExt[AL_EXTENSION_MAX];
170 std::once_flag mSetExts;
171 void setupExts();
173 DecoderOrExceptT findDecoder(StringView name);
174 BufferOrExceptT doCreateBuffer(StringView name, Vector<UniquePtr<BufferImpl>>::iterator iter, SharedPtr<Decoder> decoder);
175 BufferOrExceptT doCreateBufferAsync(StringView name, Vector<UniquePtr<BufferImpl>>::iterator iter, SharedPtr<Decoder> decoder, Promise<Buffer> promise);
177 bool mIsConnected : 1;
178 bool mIsBatching : 1;
180 public:
181 ContextImpl(ALCcontext *context, DeviceImpl *device);
182 ~ContextImpl();
184 ALCcontext *getContext() const { return mContext; }
185 long addRef() { return ++mRefs; }
186 long decRef() { return --mRefs; }
188 bool hasExtension(ALExtension ext) const { return mHasExt[ext]; }
190 LPALGETSTRINGISOFT alGetStringiSOFT;
191 LPALGETSOURCEI64VSOFT alGetSourcei64vSOFT;
192 LPALGETSOURCEDVSOFT alGetSourcedvSOFT;
194 LPALGENEFFECTS alGenEffects;
195 LPALDELETEEFFECTS alDeleteEffects;
196 LPALISEFFECT alIsEffect;
197 LPALEFFECTI alEffecti;
198 LPALEFFECTIV alEffectiv;
199 LPALEFFECTF alEffectf;
200 LPALEFFECTFV alEffectfv;
201 LPALGETEFFECTI alGetEffecti;
202 LPALGETEFFECTIV alGetEffectiv;
203 LPALGETEFFECTF alGetEffectf;
204 LPALGETEFFECTFV alGetEffectfv;
206 LPALGENFILTERS alGenFilters;
207 LPALDELETEFILTERS alDeleteFilters;
208 LPALISFILTER alIsFilter;
209 LPALFILTERI alFilteri;
210 LPALFILTERIV alFilteriv;
211 LPALFILTERF alFilterf;
212 LPALFILTERFV alFilterfv;
213 LPALGETFILTERI alGetFilteri;
214 LPALGETFILTERIV alGetFilteriv;
215 LPALGETFILTERF alGetFilterf;
216 LPALGETFILTERFV alGetFilterfv;
218 LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;
219 LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;
220 LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot;
221 LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;
222 LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv;
223 LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;
224 LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv;
225 LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti;
226 LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv;
227 LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf;
228 LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv;
230 ALuint getSourceId(ALuint maxprio);
231 void insertSourceId(ALuint id) { mSourceIds.push(id); }
233 void addFadingSource(SourceImpl *source);
234 void addPlayingSource(SourceImpl *source, ALuint id);
235 void addPlayingSource(SourceImpl *source);
236 void removePlayingSource(SourceImpl *source);
238 void addStream(SourceImpl *source);
239 void removeStream(SourceImpl *source);
240 void removeStreamNoLock(SourceImpl *source);
242 void freeSource(SourceImpl *source) { mFreeSources.push_back(source); }
243 void freeSourceGroup(SourceGroupImpl *group);
245 Batcher getBatcher()
247 if(mIsBatching)
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); }
262 void destroy();
264 void startBatch();
265 void endBatch();
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(StringView name);
277 bool isSupported(ChannelConfig channels, SampleType type) const;
279 ArrayView<String> getAvailableResamplers();
280 ALsizei getDefaultResamplerIndex() const;
282 Buffer getBuffer(StringView name);
283 SharedFuture<Buffer> getBufferAsync(StringView name);
284 void precacheBuffersAsync(ArrayView<StringView> names);
285 Buffer createBufferFrom(StringView name, SharedPtr<Decoder> decoder);
286 SharedFuture<Buffer> createBufferAsyncFrom(StringView name, SharedPtr<Decoder> decoder);
287 void removeBuffer(StringView name);
288 void removeBuffer(Buffer buffer) { removeBuffer(buffer.getName()); }
290 Source createSource();
292 AuxiliaryEffectSlot createAuxiliaryEffectSlot();
294 Effect createEffect();
296 SourceGroup createSourceGroup(StringView name);
297 SourceGroup getSourceGroup(StringView name);
299 void setDopplerFactor(ALfloat factor);
301 void setSpeedOfSound(ALfloat speed);
303 void setDistanceModel(DistanceModel model);
305 void update();
309 inline void CheckContext(const ContextImpl *ctx)
311 if(Expect<false>(ctx != ContextImpl::GetCurrent()))
312 throw std::runtime_error("Called context is not current");
315 } // namespace alure
317 #endif /* CONTEXT_H */