Use a sorted vector for the source send properties
[alure.git] / src / context.h
blob100d5e011a03a450a3d84efd8eec38699bb50c27
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 "device.h"
24 #include "source.h"
26 #define F_PI (3.14159265358979323846f)
28 #if !(__cplusplus >= 201703L)
29 namespace std {
30 using mpark::variant;
31 using mpark::get;
32 using mpark::get_if;
33 using mpark::holds_alternative;
34 } // namespace std
35 #endif
37 namespace alure {
39 enum class AL {
40 EXT_EFX,
42 EXT_FLOAT32,
43 EXT_MCFORMATS,
44 EXT_BFORMAT,
46 EXT_MULAW,
47 EXT_MULAW_MCFORMATS,
48 EXT_MULAW_BFORMAT,
50 SOFT_loop_points,
51 SOFT_source_latency,
52 SOFT_source_resampler,
53 SOFT_source_spatialize,
55 EXT_disconnect,
57 EXT_SOURCE_RADIUS,
58 EXT_STEREO_ANGLES,
60 EXTENSION_MAX
63 // Batches OpenAL updates while the object is alive, if batching isn't already
64 // in progress.
65 class Batcher {
66 ALCcontext *mContext;
68 public:
69 Batcher(ALCcontext *context) : mContext(context) { }
70 Batcher(Batcher&& rhs) : mContext(rhs.mContext) { rhs.mContext = nullptr; }
71 Batcher(const Batcher&) = delete;
72 ~Batcher()
74 if(mContext)
75 alcProcessContext(mContext);
78 Batcher& operator=(Batcher&&) = delete;
79 Batcher& operator=(const Batcher&) = delete;
83 class ListenerImpl {
84 ContextImpl *const mContext;
86 public:
87 ListenerImpl(ContextImpl *ctx) : mContext(ctx) { }
89 void setGain(ALfloat gain);
91 void set3DParameters(const Vector3 &position, const Vector3 &velocity, std::pair<Vector3,Vector3> orientation);
93 void setPosition(ALfloat x, ALfloat y, ALfloat z);
94 void setPosition(const ALfloat *pos);
96 void setVelocity(ALfloat x, ALfloat y, ALfloat z);
97 void setVelocity(const ALfloat *vel);
99 void setOrientation(ALfloat x1, ALfloat y1, ALfloat z1, ALfloat x2, ALfloat y2, ALfloat z2);
100 void setOrientation(const ALfloat *at, const ALfloat *up);
101 void setOrientation(const ALfloat *ori);
103 void setMetersPerUnit(ALfloat m_u);
107 using DecoderOrExceptT = std::variant<SharedPtr<Decoder>,std::runtime_error>;
108 using BufferOrExceptT = std::variant<Buffer,std::runtime_error>;
110 class ContextImpl {
111 static ContextImpl *sCurrentCtx;
112 static thread_local ContextImpl *sThreadCurrentCtx;
114 public:
115 static void MakeCurrent(ContextImpl *context);
116 static ContextImpl *GetCurrent() { return sThreadCurrentCtx ? sThreadCurrentCtx : sCurrentCtx; }
118 static void MakeThreadCurrent(ContextImpl *context);
119 static ContextImpl *GetThreadCurrent() { return sThreadCurrentCtx; }
121 private:
122 ListenerImpl mListener;
123 ALCcontext *mContext;
124 std::stack<ALuint> mSourceIds;
126 struct PendingFuture { BufferImpl *mBuffer; SharedFuture<Buffer> mFuture; };
127 struct PendingSource { SourceImpl *mSource; SharedFuture<Buffer> mFuture; };
129 DeviceImpl *const mDevice;
130 Vector<PendingFuture> mFutureBuffers;
131 Vector<UniquePtr<BufferImpl>> mBuffers;
132 Vector<UniquePtr<SourceGroupImpl>> mSourceGroups;
133 std::deque<SourceImpl> mAllSources;
134 Vector<SourceImpl*> mFreeSources;
136 Vector<PendingSource> mPendingSources;
137 Vector<SourceImpl*> mFadingSources;
138 Vector<SourceBufferUpdateEntry> mPlaySources;
139 Vector<SourceStreamUpdateEntry> mStreamSources;
141 Vector<SourceImpl*> mStreamingSources;
142 std::mutex mSourceStreamMutex;
144 std::atomic<std::chrono::milliseconds> mWakeInterval;
145 std::mutex mWakeMutex;
146 std::condition_variable mWakeThread;
148 SharedPtr<MessageHandler> mMessage;
150 struct PendingBuffer {
151 BufferImpl *mBuffer{nullptr};
152 SharedPtr<Decoder> mDecoder;
153 ALenum mFormat{0};
154 ALuint mFrames{0};
155 Promise<Buffer> mPromise;
157 std::atomic<PendingBuffer*> mNext{nullptr};
159 PendingBuffer() = default;
160 PendingBuffer(BufferImpl *buffer, SharedPtr<Decoder> decoder, ALenum format, ALuint frames,
161 Promise<Buffer> promise)
162 : mBuffer(buffer), mDecoder(std::move(decoder)), mFormat(format), mFrames(frames)
163 , mPromise(std::move(promise)), mNext(nullptr)
166 std::atomic<PendingBuffer*> mPendingCurrent;
167 PendingBuffer *mPendingTail;
168 PendingBuffer *mPendingHead;
170 std::atomic<bool> mQuitThread;
171 std::thread mThread;
172 void backgroundProc();
174 size_t mRefs;
176 Vector<String> mResamplers;
178 Bitfield<static_cast<size_t>(AL::EXTENSION_MAX)> mHasExt;
180 std::once_flag mSetExts;
181 void setupExts();
183 DecoderOrExceptT findDecoder(StringView name);
184 BufferOrExceptT doCreateBuffer(StringView name, Vector<UniquePtr<BufferImpl>>::iterator iter, SharedPtr<Decoder> decoder);
185 BufferOrExceptT doCreateBufferAsync(StringView name, Vector<UniquePtr<BufferImpl>>::iterator iter, SharedPtr<Decoder> decoder, Promise<Buffer> promise);
187 bool mIsConnected : 1;
188 bool mIsBatching : 1;
190 public:
191 ContextImpl(ALCcontext *context, DeviceImpl *device);
192 ~ContextImpl();
194 ALCcontext *getALCcontext() const { return mContext; }
195 long addRef() { return ++mRefs; }
196 long decRef() { return --mRefs; }
198 bool hasExtension(AL ext) const { return mHasExt[static_cast<size_t>(ext)]; }
200 LPALGETSTRINGISOFT alGetStringiSOFT;
201 LPALGETSOURCEI64VSOFT alGetSourcei64vSOFT;
202 LPALGETSOURCEDVSOFT alGetSourcedvSOFT;
204 LPALGENEFFECTS alGenEffects;
205 LPALDELETEEFFECTS alDeleteEffects;
206 LPALISEFFECT alIsEffect;
207 LPALEFFECTI alEffecti;
208 LPALEFFECTIV alEffectiv;
209 LPALEFFECTF alEffectf;
210 LPALEFFECTFV alEffectfv;
211 LPALGETEFFECTI alGetEffecti;
212 LPALGETEFFECTIV alGetEffectiv;
213 LPALGETEFFECTF alGetEffectf;
214 LPALGETEFFECTFV alGetEffectfv;
216 LPALGENFILTERS alGenFilters;
217 LPALDELETEFILTERS alDeleteFilters;
218 LPALISFILTER alIsFilter;
219 LPALFILTERI alFilteri;
220 LPALFILTERIV alFilteriv;
221 LPALFILTERF alFilterf;
222 LPALFILTERFV alFilterfv;
223 LPALGETFILTERI alGetFilteri;
224 LPALGETFILTERIV alGetFilteriv;
225 LPALGETFILTERF alGetFilterf;
226 LPALGETFILTERFV alGetFilterfv;
228 LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;
229 LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;
230 LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot;
231 LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;
232 LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv;
233 LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;
234 LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv;
235 LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti;
236 LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv;
237 LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf;
238 LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv;
240 ALuint getSourceId(ALuint maxprio);
241 void insertSourceId(ALuint id) { mSourceIds.push(id); }
243 void addPendingSource(SourceImpl *source, SharedFuture<Buffer> future);
244 void removePendingSource(SourceImpl *source);
245 bool isPendingSource(const SourceImpl *source) const;
246 void addFadingSource(SourceImpl *source);
247 void removeFadingSource(SourceImpl *source);
248 void addPlayingSource(SourceImpl *source, ALuint id);
249 void addPlayingSource(SourceImpl *source);
250 void removePlayingSource(SourceImpl *source);
252 void addStream(SourceImpl *source);
253 void removeStream(SourceImpl *source);
254 void removeStreamNoLock(SourceImpl *source);
256 void freeSource(SourceImpl *source) { mFreeSources.push_back(source); }
257 void freeSourceGroup(SourceGroupImpl *group);
259 Batcher getBatcher()
261 if(mIsBatching)
262 return Batcher(nullptr);
263 alcSuspendContext(mContext);
264 return Batcher(mContext);
267 std::unique_lock<std::mutex> getSourceStreamLock()
268 { return std::unique_lock<std::mutex>(mSourceStreamMutex); }
270 template<typename R, typename... Args>
271 void send(R MessageHandler::* func, Args&&... args)
272 { if(mMessage.get()) (mMessage.get()->*func)(std::forward<Args>(args)...); }
274 Device getDevice() { return Device(mDevice); }
276 void destroy();
278 void startBatch();
279 void endBatch();
281 Listener getListener() { return Listener(&mListener); }
283 SharedPtr<MessageHandler> setMessageHandler(SharedPtr<MessageHandler> handler);
284 SharedPtr<MessageHandler> getMessageHandler() const { return mMessage; }
286 void setAsyncWakeInterval(std::chrono::milliseconds interval);
287 std::chrono::milliseconds getAsyncWakeInterval() const { return mWakeInterval.load(); }
289 SharedPtr<Decoder> createDecoder(StringView name);
291 bool isSupported(ChannelConfig channels, SampleType type) const;
293 ArrayView<String> getAvailableResamplers();
294 ALsizei getDefaultResamplerIndex() const;
296 Buffer getBuffer(StringView name);
297 SharedFuture<Buffer> getBufferAsync(StringView name);
298 void precacheBuffersAsync(ArrayView<StringView> names);
299 Buffer createBufferFrom(StringView name, SharedPtr<Decoder> decoder);
300 SharedFuture<Buffer> createBufferAsyncFrom(StringView name, SharedPtr<Decoder> decoder);
301 void removeBuffer(StringView name);
302 void removeBuffer(Buffer buffer) { removeBuffer(buffer.getName()); }
304 Source createSource();
306 AuxiliaryEffectSlot createAuxiliaryEffectSlot();
308 Effect createEffect();
310 SourceGroup createSourceGroup(StringView name);
311 SourceGroup getSourceGroup(StringView name);
313 void setDopplerFactor(ALfloat factor);
315 void setSpeedOfSound(ALfloat speed);
317 void setDistanceModel(DistanceModel model);
319 void update();
323 inline void CheckContext(const ContextImpl *ctx)
325 if(Expect<false>(ctx != ContextImpl::GetCurrent()))
326 throw std::runtime_error("Called context is not current");
329 } // namespace alure
331 #endif /* CONTEXT_H */