Add a C++17-compliant variant class for C++11/14
[alure.git] / src / context.h
blobb5230486decae8e36cc05d77f29af2fd5bf0f0ca
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>
15 #include "alc.h"
16 #include "alext.h"
18 #include "refcount.h"
19 #include "ringbuf.h"
20 #include "device.h"
21 #include "source.h"
23 #define F_PI (3.14159265358979323846f)
25 namespace alure {
27 class ALDevice;
28 class ALBuffer;
29 class ALSourceGroup;
31 enum ALExtension {
32 EXT_EFX,
34 EXT_FLOAT32,
35 EXT_MCFORMATS,
36 EXT_BFORMAT,
38 EXT_MULAW,
39 EXT_MULAW_MCFORMATS,
40 EXT_MULAW_BFORMAT,
42 SOFT_loop_points,
43 SOFT_source_latency,
44 SOFT_source_resampler,
45 SOFT_source_spatialize,
47 EXT_disconnect,
49 EXT_SOURCE_RADIUS,
50 EXT_STEREO_ANGLES,
52 AL_EXTENSION_MAX
55 // Batches OpenAL updates while the object is alive, if batching isn't already
56 // in progress.
57 class Batcher {
58 ALCcontext *mContext;
60 public:
61 Batcher(ALCcontext *context) : mContext(context) { }
62 Batcher(Batcher&& rhs) : mContext(rhs.mContext) { rhs.mContext = nullptr; }
63 Batcher(const Batcher&) = delete;
64 ~Batcher()
66 if(mContext)
67 alcProcessContext(mContext);
70 Batcher& operator=(Batcher&&) = delete;
71 Batcher& operator=(const Batcher&) = delete;
75 class ALListener {
76 ALContext *const mContext;
78 public:
79 ALListener(ALContext *ctx) : mContext(ctx) { }
81 void setGain(ALfloat gain);
83 void set3DParameters(const Vector3 &position, const Vector3 &velocity, std::pair<Vector3,Vector3> orientation);
85 void setPosition(ALfloat x, ALfloat y, ALfloat z);
86 void setPosition(const ALfloat *pos);
88 void setVelocity(ALfloat x, ALfloat y, ALfloat z);
89 void setVelocity(const ALfloat *vel);
91 void setOrientation(ALfloat x1, ALfloat y1, ALfloat z1, ALfloat x2, ALfloat y2, ALfloat z2);
92 void setOrientation(const ALfloat *at, const ALfloat *up);
93 void setOrientation(const ALfloat *ori);
95 void setMetersPerUnit(ALfloat m_u);
98 class ALContext {
99 static ALContext *sCurrentCtx;
100 static thread_local ALContext *sThreadCurrentCtx;
102 public:
103 static void MakeCurrent(ALContext *context);
104 static ALContext *GetCurrent() { return sThreadCurrentCtx ? sThreadCurrentCtx : sCurrentCtx; }
106 static void MakeThreadCurrent(ALContext *context);
107 static ALContext *GetThreadCurrent() { return sThreadCurrentCtx; }
109 private:
110 ALListener mListener;
111 ALCcontext *mContext;
112 std::stack<ALuint> mSourceIds;
114 ALDevice *const mDevice;
115 std::deque<ALSource> mAllSources;
116 std::queue<ALSource*> mFreeSources;
117 Vector<ALSource*> mUsedSources;
119 Vector<UniquePtr<ALBuffer>> mBuffers;
121 Vector<UniquePtr<ALSourceGroup>> mSourceGroups;
123 RefCount mRefs;
125 Vector<String> mResamplers;
127 SharedPtr<MessageHandler> mMessage;
129 bool mHasExt[AL_EXTENSION_MAX];
131 struct PendingBuffer {
132 String mName;
133 ALBuffer *mBuffer;
134 SharedPtr<Decoder> mDecoder;
135 ALenum mFormat;
136 ALuint mFrames;
138 ~PendingBuffer() { }
140 RingBuffer mPendingBuffers;
142 Vector<ALSource*> mStreamingSources;
143 std::mutex mSourceStreamMutex;
145 std::atomic<std::chrono::milliseconds> mWakeInterval;
146 std::mutex mWakeMutex;
147 std::condition_variable mWakeThread;
149 std::mutex mContextMutex;
151 std::atomic<bool> mQuitThread;
152 std::thread mThread;
153 void backgroundProc();
155 std::once_flag mSetExts;
156 void setupExts();
158 Buffer doCreateBuffer(const String &name, Vector<UniquePtr<ALBuffer>>::iterator iter, SharedPtr<Decoder> decoder);
159 Buffer doCreateBufferAsync(const String &name, Vector<UniquePtr<ALBuffer>>::iterator iter, SharedPtr<Decoder> decoder);
161 bool mIsConnected : 1;
162 bool mIsBatching : 1;
164 public:
165 ALContext(ALCcontext *context, ALDevice *device);
166 ~ALContext();
168 ALCcontext *getContext() const { return mContext; }
169 long addRef() { return ++mRefs; }
170 long decRef() { return --mRefs; }
172 bool hasExtension(ALExtension ext) const { return mHasExt[ext]; }
174 LPALGETSTRINGISOFT alGetStringiSOFT;
175 LPALGETSOURCEI64VSOFT alGetSourcei64vSOFT;
176 LPALGETSOURCEDVSOFT alGetSourcedvSOFT;
178 LPALGENEFFECTS alGenEffects;
179 LPALDELETEEFFECTS alDeleteEffects;
180 LPALISEFFECT alIsEffect;
181 LPALEFFECTI alEffecti;
182 LPALEFFECTIV alEffectiv;
183 LPALEFFECTF alEffectf;
184 LPALEFFECTFV alEffectfv;
185 LPALGETEFFECTI alGetEffecti;
186 LPALGETEFFECTIV alGetEffectiv;
187 LPALGETEFFECTF alGetEffectf;
188 LPALGETEFFECTFV alGetEffectfv;
190 LPALGENFILTERS alGenFilters;
191 LPALDELETEFILTERS alDeleteFilters;
192 LPALISFILTER alIsFilter;
193 LPALFILTERI alFilteri;
194 LPALFILTERIV alFilteriv;
195 LPALFILTERF alFilterf;
196 LPALFILTERFV alFilterfv;
197 LPALGETFILTERI alGetFilteri;
198 LPALGETFILTERIV alGetFilteriv;
199 LPALGETFILTERF alGetFilterf;
200 LPALGETFILTERFV alGetFilterfv;
202 LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;
203 LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;
204 LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot;
205 LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;
206 LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv;
207 LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;
208 LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv;
209 LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti;
210 LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv;
211 LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf;
212 LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv;
214 ALuint getSourceId(ALuint maxprio);
215 void insertSourceId(ALuint id) { mSourceIds.push(id); }
217 void addStream(ALSource *source);
218 void removeStream(ALSource *source);
219 void removeStreamNoLock(ALSource *source);
221 void freeSource(ALSource *source);
222 void freeSourceGroup(ALSourceGroup *group);
224 Batcher getBatcher()
226 if(mIsBatching)
227 return Batcher(nullptr);
228 alcSuspendContext(mContext);
229 return Batcher(mContext);
232 std::unique_lock<std::mutex> getSourceStreamLock()
233 { return std::unique_lock<std::mutex>(mSourceStreamMutex); }
235 template<typename R, typename... Args>
236 void send(R MessageHandler::* func, Args&&... args)
237 { if(mMessage.get()) (mMessage.get()->*func)(std::forward<Args>(args)...); }
239 Device getDevice() { return Device(mDevice); }
241 void destroy();
243 void startBatch();
244 void endBatch();
246 Listener getListener() { return Listener(&mListener); }
248 SharedPtr<MessageHandler> setMessageHandler(SharedPtr<MessageHandler> handler);
249 SharedPtr<MessageHandler> getMessageHandler() const { return mMessage; }
251 void setAsyncWakeInterval(std::chrono::milliseconds msec);
252 std::chrono::milliseconds getAsyncWakeInterval() const { return mWakeInterval.load(); }
254 SharedPtr<Decoder> createDecoder(const String &name);
256 bool isSupported(ChannelConfig channels, SampleType type) const;
258 const Vector<String> &getAvailableResamplers();
259 ALsizei getDefaultResamplerIndex() const;
261 Buffer getBuffer(const String &name);
262 Buffer getBufferAsync(const String &name);
263 Buffer createBufferFrom(const String &name, SharedPtr<Decoder> decoder);
264 Buffer createBufferAsyncFrom(const String &name, SharedPtr<Decoder> decoder);
265 void removeBuffer(const String &name);
266 void removeBuffer(Buffer buffer) { removeBuffer(buffer.getName()); }
268 Source createSource();
270 AuxiliaryEffectSlot createAuxiliaryEffectSlot();
272 Effect createEffect();
274 SourceGroup createSourceGroup(String name);
275 SourceGroup getSourceGroup(const String &name);
277 void setDopplerFactor(ALfloat factor);
279 void setSpeedOfSound(ALfloat speed);
281 void setDistanceModel(DistanceModel model);
283 void update();
287 inline void CheckContext(const ALContext *ctx)
289 if(EXPECT(ctx != ALContext::GetCurrent(), false))
290 throw std::runtime_error("Called context is not current");
293 } // namespace alure
295 #endif /* CONTEXT_H */