Create and get SourceGroups by StringView
[alure.git] / src / context.h
blob6e15372152a5569a41ffd3051ad3a6ee991189f9
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 std::queue<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 freeSourceGroup(SourceGroupImpl *group);
246 Batcher getBatcher()
248 if(mIsBatching)
249 return Batcher(nullptr);
250 alcSuspendContext(mContext);
251 return Batcher(mContext);
254 std::unique_lock<std::mutex> getSourceStreamLock()
255 { return std::unique_lock<std::mutex>(mSourceStreamMutex); }
257 template<typename R, typename... Args>
258 void send(R MessageHandler::* func, Args&&... args)
259 { if(mMessage.get()) (mMessage.get()->*func)(std::forward<Args>(args)...); }
261 Device getDevice() { return Device(mDevice); }
263 void destroy();
265 void startBatch();
266 void endBatch();
268 Listener getListener() { return Listener(&mListener); }
270 SharedPtr<MessageHandler> setMessageHandler(SharedPtr<MessageHandler> handler);
271 SharedPtr<MessageHandler> getMessageHandler() const { return mMessage; }
273 void setAsyncWakeInterval(std::chrono::milliseconds interval);
274 std::chrono::milliseconds getAsyncWakeInterval() const { return mWakeInterval.load(); }
276 SharedPtr<Decoder> createDecoder(StringView name);
278 bool isSupported(ChannelConfig channels, SampleType type) const;
280 ArrayView<String> getAvailableResamplers();
281 ALsizei getDefaultResamplerIndex() const;
283 Buffer getBuffer(StringView name);
284 SharedFuture<Buffer> getBufferAsync(StringView name);
285 void precacheBuffersAsync(ArrayView<StringView> names);
286 Buffer createBufferFrom(StringView name, SharedPtr<Decoder> decoder);
287 SharedFuture<Buffer> createBufferAsyncFrom(StringView name, SharedPtr<Decoder> decoder);
288 void removeBuffer(StringView name);
289 void removeBuffer(Buffer buffer) { removeBuffer(buffer.getName()); }
291 Source createSource();
293 AuxiliaryEffectSlot createAuxiliaryEffectSlot();
295 Effect createEffect();
297 SourceGroup createSourceGroup(StringView name);
298 SourceGroup getSourceGroup(StringView name);
300 void setDopplerFactor(ALfloat factor);
302 void setSpeedOfSound(ALfloat speed);
304 void setDistanceModel(DistanceModel model);
306 void update();
310 inline void CheckContext(const ContextImpl *ctx)
312 if(EXPECT(ctx != ContextImpl::GetCurrent(), false))
313 throw std::runtime_error("Called context is not current");
316 } // namespace alure
318 #endif /* CONTEXT_H */