Inline some simple functions
[alure.git] / src / context.h
bloba514103415333de9c7d3bd0d0ed223aa1b908da8
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 setPosition(ALfloat x, ALfloat y, ALfloat z);
84 void setPosition(const ALfloat *pos);
86 void setVelocity(ALfloat x, ALfloat y, ALfloat z);
87 void setVelocity(const ALfloat *vel);
89 void setOrientation(ALfloat x1, ALfloat y1, ALfloat z1, ALfloat x2, ALfloat y2, ALfloat z2);
90 void setOrientation(const ALfloat *at, const ALfloat *up);
91 void setOrientation(const ALfloat *ori);
93 void setMetersPerUnit(ALfloat m_u);
96 class ALContext {
97 static ALContext *sCurrentCtx;
98 static thread_local ALContext *sThreadCurrentCtx;
100 public:
101 static void MakeCurrent(ALContext *context);
102 static ALContext *GetCurrent() { return sThreadCurrentCtx ? sThreadCurrentCtx : sCurrentCtx; }
104 static void MakeThreadCurrent(ALContext *context);
105 static ALContext *GetThreadCurrent() { return sThreadCurrentCtx; }
107 private:
108 ALListener mListener;
109 ALCcontext *mContext;
110 std::stack<ALuint> mSourceIds;
112 ALDevice *const mDevice;
113 std::deque<ALSource> mAllSources;
114 std::queue<ALSource*> mFreeSources;
115 Vector<ALSource*> mUsedSources;
117 Vector<UniquePtr<ALBuffer>> mBuffers;
119 Vector<UniquePtr<ALSourceGroup>> mSourceGroups;
121 RefCount mRefs;
123 Vector<String> mResamplers;
125 SharedPtr<MessageHandler> mMessage;
127 bool mHasExt[AL_EXTENSION_MAX];
129 struct PendingBuffer {
130 String mName;
131 ALBuffer *mBuffer;
132 SharedPtr<Decoder> mDecoder;
133 ALenum mFormat;
134 ALuint mFrames;
136 ~PendingBuffer() { }
138 RingBuffer mPendingBuffers;
140 Vector<ALSource*> mStreamingSources;
141 std::mutex mSourceStreamMutex;
143 std::atomic<ALuint> mWakeInterval;
144 std::mutex mWakeMutex;
145 std::condition_variable mWakeThread;
147 std::mutex mContextMutex;
149 std::atomic<bool> mQuitThread;
150 std::thread mThread;
151 void backgroundProc();
153 std::once_flag mSetExts;
154 void setupExts();
156 bool mIsConnected : 1;
157 bool mIsBatching : 1;
159 public:
160 ALContext(ALCcontext *context, ALDevice *device);
161 ~ALContext();
163 ALCcontext *getContext() const { return mContext; }
164 long addRef() { return ++mRefs; }
165 long decRef() { return --mRefs; }
167 bool hasExtension(ALExtension ext) const { return mHasExt[ext]; }
169 LPALGETSTRINGISOFT alGetStringiSOFT;
170 LPALGETSOURCEI64VSOFT alGetSourcei64vSOFT;
172 LPALGENEFFECTS alGenEffects;
173 LPALDELETEEFFECTS alDeleteEffects;
174 LPALISEFFECT alIsEffect;
175 LPALEFFECTI alEffecti;
176 LPALEFFECTIV alEffectiv;
177 LPALEFFECTF alEffectf;
178 LPALEFFECTFV alEffectfv;
179 LPALGETEFFECTI alGetEffecti;
180 LPALGETEFFECTIV alGetEffectiv;
181 LPALGETEFFECTF alGetEffectf;
182 LPALGETEFFECTFV alGetEffectfv;
184 LPALGENFILTERS alGenFilters;
185 LPALDELETEFILTERS alDeleteFilters;
186 LPALISFILTER alIsFilter;
187 LPALFILTERI alFilteri;
188 LPALFILTERIV alFilteriv;
189 LPALFILTERF alFilterf;
190 LPALFILTERFV alFilterfv;
191 LPALGETFILTERI alGetFilteri;
192 LPALGETFILTERIV alGetFilteriv;
193 LPALGETFILTERF alGetFilterf;
194 LPALGETFILTERFV alGetFilterfv;
196 LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;
197 LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;
198 LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot;
199 LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;
200 LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv;
201 LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;
202 LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv;
203 LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti;
204 LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv;
205 LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf;
206 LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv;
208 ALuint getSourceId(ALuint maxprio);
209 void insertSourceId(ALuint id) { mSourceIds.push(id); }
211 void addStream(ALSource *source);
212 void removeStream(ALSource *source);
213 void removeStreamNoLock(ALSource *source);
215 void freeSource(ALSource *source);
216 void freeSourceGroup(ALSourceGroup *group);
218 Batcher getBatcher()
220 if(mIsBatching)
221 return Batcher(nullptr);
222 alcSuspendContext(mContext);
223 return Batcher(mContext);
226 std::unique_lock<std::mutex> getSourceStreamLock()
227 { return std::unique_lock<std::mutex>(mSourceStreamMutex); }
229 template<typename R, typename... Args>
230 void send(R MessageHandler::* func, Args&&... args)
231 { if(mMessage.get()) (mMessage.get()->*func)(std::forward<Args>(args)...); }
233 Device getDevice() { return Device(mDevice); }
235 void destroy();
237 void startBatch();
238 void endBatch();
240 Listener getListener() { return Listener(&mListener); }
242 SharedPtr<MessageHandler> setMessageHandler(SharedPtr<MessageHandler> handler);
243 SharedPtr<MessageHandler> getMessageHandler() const { return mMessage; }
245 void setAsyncWakeInterval(ALuint msec);
246 ALuint getAsyncWakeInterval() const { return mWakeInterval.load(); }
248 SharedPtr<Decoder> createDecoder(const String &name);
250 bool isSupported(ChannelConfig channels, SampleType type) const;
252 const Vector<String> &getAvailableResamplers();
253 ALsizei getDefaultResamplerIndex() const;
255 Buffer getBuffer(const String &name);
256 Buffer getBufferAsync(const String &name);
257 void removeBuffer(const String &name);
258 void removeBuffer(Buffer buffer) { removeBuffer(buffer.getName()); }
260 Source createSource();
262 AuxiliaryEffectSlot createAuxiliaryEffectSlot();
264 Effect createEffect();
266 SourceGroup createSourceGroup(String name);
267 SourceGroup getSourceGroup(const String &name);
269 void setDopplerFactor(ALfloat factor);
271 void setSpeedOfSound(ALfloat speed);
273 void setDistanceModel(DistanceModel model);
275 void update();
279 inline void CheckContext(const ALContext *ctx)
281 if(ctx != ALContext::GetCurrent())
282 throw std::runtime_error("Called context is not current");
285 } // namespace alure
287 #endif /* CONTEXT_H */