Use hidden visibility by default
[alure.git] / src / context.h
blob72550ca432b80ecacae95a17d9a39fad39eaa7ac
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 DeviceImpl *const mDevice;
133 std::unordered_map<String,SharedFuture<Buffer>> mFutureBuffers;
134 Vector<UniquePtr<BufferImpl>> mBuffers;
135 Vector<UniquePtr<SourceGroupImpl>> mSourceGroups;
136 std::deque<SourceImpl> mAllSources;
137 std::queue<SourceImpl*> mFreeSources;
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 String mName;
152 BufferImpl *mBuffer;
153 SharedPtr<Decoder> mDecoder;
154 ALenum mFormat;
155 ALuint mFrames;
156 Promise<Buffer> mPromise;
158 ~PendingBuffer() { }
160 RingBuffer mPendingBuffers;
162 std::atomic<bool> mQuitThread;
163 std::thread mThread;
164 void backgroundProc();
166 RefCount mRefs;
168 Vector<String> mResamplers;
170 bool mHasExt[AL_EXTENSION_MAX];
172 std::once_flag mSetExts;
173 void setupExts();
175 DecoderOrExceptT findDecoder(const String &name);
176 BufferOrExceptT doCreateBuffer(const String &name, Vector<UniquePtr<BufferImpl>>::iterator iter, SharedPtr<Decoder> decoder);
177 BufferOrExceptT doCreateBufferAsync(const String &name, Vector<UniquePtr<BufferImpl>>::iterator iter, SharedPtr<Decoder> decoder, Promise<Buffer> promise);
179 bool mIsConnected : 1;
180 bool mIsBatching : 1;
182 public:
183 ContextImpl(ALCcontext *context, DeviceImpl *device);
184 ~ContextImpl();
186 ALCcontext *getContext() const { return mContext; }
187 long addRef() { return ++mRefs; }
188 long decRef() { return --mRefs; }
190 bool hasExtension(ALExtension ext) const { return mHasExt[ext]; }
192 LPALGETSTRINGISOFT alGetStringiSOFT;
193 LPALGETSOURCEI64VSOFT alGetSourcei64vSOFT;
194 LPALGETSOURCEDVSOFT alGetSourcedvSOFT;
196 LPALGENEFFECTS alGenEffects;
197 LPALDELETEEFFECTS alDeleteEffects;
198 LPALISEFFECT alIsEffect;
199 LPALEFFECTI alEffecti;
200 LPALEFFECTIV alEffectiv;
201 LPALEFFECTF alEffectf;
202 LPALEFFECTFV alEffectfv;
203 LPALGETEFFECTI alGetEffecti;
204 LPALGETEFFECTIV alGetEffectiv;
205 LPALGETEFFECTF alGetEffectf;
206 LPALGETEFFECTFV alGetEffectfv;
208 LPALGENFILTERS alGenFilters;
209 LPALDELETEFILTERS alDeleteFilters;
210 LPALISFILTER alIsFilter;
211 LPALFILTERI alFilteri;
212 LPALFILTERIV alFilteriv;
213 LPALFILTERF alFilterf;
214 LPALFILTERFV alFilterfv;
215 LPALGETFILTERI alGetFilteri;
216 LPALGETFILTERIV alGetFilteriv;
217 LPALGETFILTERF alGetFilterf;
218 LPALGETFILTERFV alGetFilterfv;
220 LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;
221 LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;
222 LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot;
223 LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;
224 LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv;
225 LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;
226 LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv;
227 LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti;
228 LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv;
229 LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf;
230 LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv;
232 ALuint getSourceId(ALuint maxprio);
233 void insertSourceId(ALuint id) { mSourceIds.push(id); }
235 void addPlayingSource(SourceImpl *source, ALuint id);
236 void addPlayingSource(SourceImpl *source);
237 void removePlayingSource(SourceImpl *source);
239 void addStream(SourceImpl *source);
240 void removeStream(SourceImpl *source);
241 void removeStreamNoLock(SourceImpl *source);
243 void freeSourceGroup(SourceGroupImpl *group);
245 Batcher getBatcher()
247 if(mIsBatching)
248 return Batcher(nullptr);
249 alcSuspendContext(mContext);
250 return Batcher(mContext);
253 std::unique_lock<std::mutex> getSourceStreamLock()
254 { return std::unique_lock<std::mutex>(mSourceStreamMutex); }
256 template<typename R, typename... Args>
257 void send(R MessageHandler::* func, Args&&... args)
258 { if(mMessage.get()) (mMessage.get()->*func)(std::forward<Args>(args)...); }
260 Device getDevice() { return Device(mDevice); }
262 void destroy();
264 void startBatch();
265 void endBatch();
267 Listener getListener() { return Listener(&mListener); }
269 SharedPtr<MessageHandler> setMessageHandler(SharedPtr<MessageHandler> handler);
270 SharedPtr<MessageHandler> getMessageHandler() const { return mMessage; }
272 void setAsyncWakeInterval(std::chrono::milliseconds interval);
273 std::chrono::milliseconds getAsyncWakeInterval() const { return mWakeInterval.load(); }
275 SharedPtr<Decoder> createDecoder(const String &name);
277 bool isSupported(ChannelConfig channels, SampleType type) const;
279 ArrayView<String> getAvailableResamplers();
280 ALsizei getDefaultResamplerIndex() const;
282 Buffer getBuffer(const String &name);
283 SharedFuture<Buffer> getBufferAsync(const String &name);
284 void precacheBuffersAsync(ArrayView<String> names);
285 Buffer createBufferFrom(const String &name, SharedPtr<Decoder> decoder);
286 SharedFuture<Buffer> createBufferAsyncFrom(const String &name, SharedPtr<Decoder> decoder);
287 void removeBuffer(const String &name);
288 void removeBuffer(Buffer buffer) { removeBuffer(buffer.getName()); }
290 Source createSource();
292 AuxiliaryEffectSlot createAuxiliaryEffectSlot();
294 Effect createEffect();
296 SourceGroup createSourceGroup(String name);
297 SourceGroup getSourceGroup(const String &name);
299 void setDopplerFactor(ALfloat factor);
301 void setSpeedOfSound(ALfloat speed);
303 void setDistanceModel(DistanceModel model);
305 void update();
309 inline void CheckContext(const ContextImpl *ctx)
311 if(EXPECT(ctx != ContextImpl::GetCurrent(), false))
312 throw std::runtime_error("Called context is not current");
315 } // namespace alure
317 #endif /* CONTEXT_H */