Fix reusing source objects
[alure.git] / src / context.h
blob4dbfddf5ab92d0c811c7c34c7ddad55fbbfa233d
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 class DeviceImpl;
42 class BufferImpl;
43 class SourceGroupImpl;
45 enum ALExtension {
46 EXT_EFX,
48 EXT_FLOAT32,
49 EXT_MCFORMATS,
50 EXT_BFORMAT,
52 EXT_MULAW,
53 EXT_MULAW_MCFORMATS,
54 EXT_MULAW_BFORMAT,
56 SOFT_loop_points,
57 SOFT_source_latency,
58 SOFT_source_resampler,
59 SOFT_source_spatialize,
61 EXT_disconnect,
63 EXT_SOURCE_RADIUS,
64 EXT_STEREO_ANGLES,
66 AL_EXTENSION_MAX
69 // Batches OpenAL updates while the object is alive, if batching isn't already
70 // in progress.
71 class Batcher {
72 ALCcontext *mContext;
74 public:
75 Batcher(ALCcontext *context) : mContext(context) { }
76 Batcher(Batcher&& rhs) : mContext(rhs.mContext) { rhs.mContext = nullptr; }
77 Batcher(const Batcher&) = delete;
78 ~Batcher()
80 if(mContext)
81 alcProcessContext(mContext);
84 Batcher& operator=(Batcher&&) = delete;
85 Batcher& operator=(const Batcher&) = delete;
89 class ListenerImpl {
90 ContextImpl *const mContext;
92 public:
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>;
116 class ContextImpl {
117 static ContextImpl *sCurrentCtx;
118 static thread_local ContextImpl *sThreadCurrentCtx;
120 public:
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; }
127 private:
128 ListenerImpl mListener;
129 ALCcontext *mContext;
130 std::stack<ALuint> mSourceIds;
132 struct PendingFuture { BufferImpl *mBuffer; SharedFuture<Buffer> mFuture; };
134 DeviceImpl *const mDevice;
135 Vector<PendingFuture> mFutureBuffers;
136 Vector<UniquePtr<BufferImpl>> mBuffers;
137 Vector<UniquePtr<SourceGroupImpl>> mSourceGroups;
138 std::deque<SourceImpl> mAllSources;
139 Vector<SourceImpl*> mFreeSources;
140 Vector<SourceBufferUpdateEntry> mPlaySources;
141 Vector<SourceStreamUpdateEntry> mStreamSources;
143 Vector<SourceImpl*> mStreamingSources;
144 std::mutex mSourceStreamMutex;
146 std::atomic<std::chrono::milliseconds> mWakeInterval;
147 std::mutex mWakeMutex;
148 std::condition_variable mWakeThread;
150 SharedPtr<MessageHandler> mMessage;
152 struct PendingBuffer {
153 BufferImpl *mBuffer;
154 SharedPtr<Decoder> mDecoder;
155 ALenum mFormat;
156 ALuint mFrames;
157 Promise<Buffer> mPromise;
159 ~PendingBuffer() { }
161 RingBuffer mPendingBuffers;
163 std::atomic<bool> mQuitThread;
164 std::thread mThread;
165 void backgroundProc();
167 RefCount mRefs;
169 Vector<String> mResamplers;
171 bool mHasExt[AL_EXTENSION_MAX];
173 std::once_flag mSetExts;
174 void setupExts();
176 DecoderOrExceptT findDecoder(StringView name);
177 BufferOrExceptT doCreateBuffer(StringView name, Vector<UniquePtr<BufferImpl>>::iterator iter, SharedPtr<Decoder> decoder);
178 BufferOrExceptT doCreateBufferAsync(StringView name, Vector<UniquePtr<BufferImpl>>::iterator iter, SharedPtr<Decoder> decoder, Promise<Buffer> promise);
180 bool mIsConnected : 1;
181 bool mIsBatching : 1;
183 public:
184 ContextImpl(ALCcontext *context, DeviceImpl *device);
185 ~ContextImpl();
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 addPlayingSource(SourceImpl *source, ALuint id);
237 void addPlayingSource(SourceImpl *source);
238 void removePlayingSource(SourceImpl *source);
240 void addStream(SourceImpl *source);
241 void removeStream(SourceImpl *source);
242 void removeStreamNoLock(SourceImpl *source);
244 void freeSource(SourceImpl *source) { mFreeSources.push_back(source); }
245 void freeSourceGroup(SourceGroupImpl *group);
247 Batcher getBatcher()
249 if(mIsBatching)
250 return Batcher(nullptr);
251 alcSuspendContext(mContext);
252 return Batcher(mContext);
255 std::unique_lock<std::mutex> getSourceStreamLock()
256 { return std::unique_lock<std::mutex>(mSourceStreamMutex); }
258 template<typename R, typename... Args>
259 void send(R MessageHandler::* func, Args&&... args)
260 { if(mMessage.get()) (mMessage.get()->*func)(std::forward<Args>(args)...); }
262 Device getDevice() { return Device(mDevice); }
264 void destroy();
266 void startBatch();
267 void endBatch();
269 Listener getListener() { return Listener(&mListener); }
271 SharedPtr<MessageHandler> setMessageHandler(SharedPtr<MessageHandler> handler);
272 SharedPtr<MessageHandler> getMessageHandler() const { return mMessage; }
274 void setAsyncWakeInterval(std::chrono::milliseconds interval);
275 std::chrono::milliseconds getAsyncWakeInterval() const { return mWakeInterval.load(); }
277 SharedPtr<Decoder> createDecoder(StringView name);
279 bool isSupported(ChannelConfig channels, SampleType type) const;
281 ArrayView<String> getAvailableResamplers();
282 ALsizei getDefaultResamplerIndex() const;
284 Buffer getBuffer(StringView name);
285 SharedFuture<Buffer> getBufferAsync(StringView name);
286 void precacheBuffersAsync(ArrayView<StringView> names);
287 Buffer createBufferFrom(StringView name, SharedPtr<Decoder> decoder);
288 SharedFuture<Buffer> createBufferAsyncFrom(StringView name, SharedPtr<Decoder> decoder);
289 void removeBuffer(StringView name);
290 void removeBuffer(Buffer buffer) { removeBuffer(buffer.getName()); }
292 Source createSource();
294 AuxiliaryEffectSlot createAuxiliaryEffectSlot();
296 Effect createEffect();
298 SourceGroup createSourceGroup(StringView name);
299 SourceGroup getSourceGroup(StringView name);
301 void setDopplerFactor(ALfloat factor);
303 void setSpeedOfSound(ALfloat speed);
305 void setDistanceModel(DistanceModel model);
307 void update();
311 inline void CheckContext(const ContextImpl *ctx)
313 if(EXPECT(ctx != ContextImpl::GetCurrent(), false))
314 throw std::runtime_error("Called context is not current");
317 } // namespace alure
319 #endif /* CONTEXT_H */