Rename AL* implementation classes to *Impl
[alure.git] / src / context.h
blob988ae29c2d884eadfdb23d153f6aead6c8083f48
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 } // namespace std
36 #endif
38 namespace alure {
40 class DeviceImpl;
41 class BufferImpl;
42 class SourceGroupImpl;
44 enum ALExtension {
45 EXT_EFX,
47 EXT_FLOAT32,
48 EXT_MCFORMATS,
49 EXT_BFORMAT,
51 EXT_MULAW,
52 EXT_MULAW_MCFORMATS,
53 EXT_MULAW_BFORMAT,
55 SOFT_loop_points,
56 SOFT_source_latency,
57 SOFT_source_resampler,
58 SOFT_source_spatialize,
60 EXT_disconnect,
62 EXT_SOURCE_RADIUS,
63 EXT_STEREO_ANGLES,
65 AL_EXTENSION_MAX
68 // Batches OpenAL updates while the object is alive, if batching isn't already
69 // in progress.
70 class Batcher {
71 ALCcontext *mContext;
73 public:
74 Batcher(ALCcontext *context) : mContext(context) { }
75 Batcher(Batcher&& rhs) : mContext(rhs.mContext) { rhs.mContext = nullptr; }
76 Batcher(const Batcher&) = delete;
77 ~Batcher()
79 if(mContext)
80 alcProcessContext(mContext);
83 Batcher& operator=(Batcher&&) = delete;
84 Batcher& operator=(const Batcher&) = delete;
88 class ListenerImpl {
89 ContextImpl *const mContext;
91 public:
92 ListenerImpl(ContextImpl *ctx) : mContext(ctx) { }
94 void setGain(ALfloat gain);
96 void set3DParameters(const Vector3 &position, const Vector3 &velocity, std::pair<Vector3,Vector3> orientation);
98 void setPosition(ALfloat x, ALfloat y, ALfloat z);
99 void setPosition(const ALfloat *pos);
101 void setVelocity(ALfloat x, ALfloat y, ALfloat z);
102 void setVelocity(const ALfloat *vel);
104 void setOrientation(ALfloat x1, ALfloat y1, ALfloat z1, ALfloat x2, ALfloat y2, ALfloat z2);
105 void setOrientation(const ALfloat *at, const ALfloat *up);
106 void setOrientation(const ALfloat *ori);
108 void setMetersPerUnit(ALfloat m_u);
112 using BufferOrExceptT = std::variant<Buffer,std::runtime_error>;
114 class ContextImpl {
115 static ContextImpl *sCurrentCtx;
116 static thread_local ContextImpl *sThreadCurrentCtx;
118 public:
119 static void MakeCurrent(ContextImpl *context);
120 static ContextImpl *GetCurrent() { return sThreadCurrentCtx ? sThreadCurrentCtx : sCurrentCtx; }
122 static void MakeThreadCurrent(ContextImpl *context);
123 static ContextImpl *GetThreadCurrent() { return sThreadCurrentCtx; }
125 private:
126 ListenerImpl mListener;
127 ALCcontext *mContext;
128 std::stack<ALuint> mSourceIds;
130 DeviceImpl *const mDevice;
131 std::deque<SourceImpl> mAllSources;
132 std::queue<SourceImpl*> mFreeSources;
133 Vector<SourceImpl*> mUsedSources;
135 Vector<UniquePtr<BufferImpl>> mBuffers;
137 Vector<UniquePtr<SourceGroupImpl>> mSourceGroups;
139 RefCount mRefs;
141 Vector<String> mResamplers;
143 SharedPtr<MessageHandler> mMessage;
145 bool mHasExt[AL_EXTENSION_MAX];
147 struct PendingBuffer {
148 String mName;
149 BufferImpl *mBuffer;
150 SharedPtr<Decoder> mDecoder;
151 ALenum mFormat;
152 ALuint mFrames;
154 ~PendingBuffer() { }
156 RingBuffer mPendingBuffers;
158 Vector<SourceImpl*> mStreamingSources;
159 std::mutex mSourceStreamMutex;
161 std::atomic<std::chrono::milliseconds> mWakeInterval;
162 std::mutex mWakeMutex;
163 std::condition_variable mWakeThread;
165 std::mutex mContextMutex;
167 std::atomic<bool> mQuitThread;
168 std::thread mThread;
169 void backgroundProc();
171 std::once_flag mSetExts;
172 void setupExts();
174 BufferOrExceptT doCreateBuffer(const String &name, Vector<UniquePtr<BufferImpl>>::iterator iter, SharedPtr<Decoder> decoder);
175 BufferOrExceptT doCreateBufferAsync(const String &name, Vector<UniquePtr<BufferImpl>>::iterator iter, SharedPtr<Decoder> decoder);
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 addStream(SourceImpl *source);
234 void removeStream(SourceImpl *source);
235 void removeStreamNoLock(SourceImpl *source);
237 void freeSource(SourceImpl *source);
238 void freeSourceGroup(SourceGroupImpl *group);
240 Batcher getBatcher()
242 if(mIsBatching)
243 return Batcher(nullptr);
244 alcSuspendContext(mContext);
245 return Batcher(mContext);
248 std::unique_lock<std::mutex> getSourceStreamLock()
249 { return std::unique_lock<std::mutex>(mSourceStreamMutex); }
251 template<typename R, typename... Args>
252 void send(R MessageHandler::* func, Args&&... args)
253 { if(mMessage.get()) (mMessage.get()->*func)(std::forward<Args>(args)...); }
255 Device getDevice() { return Device(mDevice); }
257 void destroy();
259 void startBatch();
260 void endBatch();
262 Listener getListener() { return Listener(&mListener); }
264 SharedPtr<MessageHandler> setMessageHandler(SharedPtr<MessageHandler> handler);
265 SharedPtr<MessageHandler> getMessageHandler() const { return mMessage; }
267 void setAsyncWakeInterval(std::chrono::milliseconds msec);
268 std::chrono::milliseconds getAsyncWakeInterval() const { return mWakeInterval.load(); }
270 SharedPtr<Decoder> createDecoder(const String &name);
272 bool isSupported(ChannelConfig channels, SampleType type) const;
274 ArrayView<String> getAvailableResamplers();
275 ALsizei getDefaultResamplerIndex() const;
277 Buffer getBuffer(const String &name);
278 Buffer getBufferAsync(const String &name);
279 void precacheBuffersAsync(ArrayView<String> names);
280 Buffer createBufferFrom(const String &name, SharedPtr<Decoder> decoder);
281 Buffer createBufferAsyncFrom(const String &name, SharedPtr<Decoder> decoder);
282 void removeBuffer(const String &name);
283 void removeBuffer(Buffer buffer) { removeBuffer(buffer.getName()); }
285 Source createSource();
287 AuxiliaryEffectSlot createAuxiliaryEffectSlot();
289 Effect createEffect();
291 SourceGroup createSourceGroup(String name);
292 SourceGroup getSourceGroup(const String &name);
294 void setDopplerFactor(ALfloat factor);
296 void setSpeedOfSound(ALfloat speed);
298 void setDistanceModel(DistanceModel model);
300 void update();
304 inline void CheckContext(const ContextImpl *ctx)
306 if(EXPECT(ctx != ContextImpl::GetCurrent(), false))
307 throw std::runtime_error("Called context is not current");
310 } // namespace alure
312 #endif /* CONTEXT_H */