2 #include "sourcegroup.h"
12 void SourceGroupImpl::eraseSubGroup(SourceGroupImpl
*group
)
14 auto iter
= std::lower_bound(mSubGroups
.begin(), mSubGroups
.end(), group
);
15 if(iter
!= mSubGroups
.end() && *iter
== group
) mSubGroups
.erase(iter
);
19 void SourceGroupImpl::setParentGroup(SourceGroupImpl
*group
)
22 mParent
->eraseSubGroup(this);
24 SourceGroupProps props
;
25 mParent
->applyPropTree(props
);
26 update(props
.mGain
, props
.mPitch
);
29 void SourceGroupImpl::unsetParentGroup()
35 void SourceGroupImpl::update(ALfloat gain
, ALfloat pitch
)
37 mParentProps
.mGain
= gain
;
38 mParentProps
.mPitch
= pitch
;
42 for(SourceImpl
*alsrc
: mSources
)
43 alsrc
->groupPropUpdate(gain
, pitch
);
44 for(SourceGroupImpl
*group
: mSubGroups
)
45 group
->update(gain
, pitch
);
49 bool SourceGroupImpl::findInSubGroups(SourceGroupImpl
*group
) const
51 auto iter
= std::lower_bound(mSubGroups
.begin(), mSubGroups
.end(), group
);
52 if(iter
!= mSubGroups
.end() && *iter
== group
) return true;
54 for(SourceGroupImpl
*group
: mSubGroups
)
56 if(group
->findInSubGroups(group
))
63 void SourceGroupImpl::addSource(Source source
)
65 SourceImpl
*alsrc
= source
.getHandle();
66 if(!alsrc
) throw std::runtime_error("Source is not valid");
67 CheckContext(mContext
);
69 auto iter
= std::lower_bound(mSources
.begin(), mSources
.end(), alsrc
);
70 if(iter
!= mSources
.end() && *iter
== alsrc
) return;
72 mSources
.insert(iter
, alsrc
);
73 alsrc
->setGroup(this);
76 void SourceGroupImpl::removeSource(Source source
)
78 CheckContext(mContext
);
79 auto iter
= std::lower_bound(mSources
.begin(), mSources
.end(), source
.getHandle());
80 if(iter
!= mSources
.end() && *iter
== source
.getHandle())
82 (*iter
)->unsetGroup();
88 void SourceGroupImpl::addSources(ArrayView
<Source
> sources
)
90 CheckContext(mContext
);
94 Vector
<SourceImpl
*> alsrcs
;
95 alsrcs
.reserve(sources
.size());
97 for(Source source
: sources
)
99 alsrcs
.push_back(source
.getHandle());
100 if(!alsrcs
.back()) throw std::runtime_error("Source is not valid");
103 Batcher batcher
= mContext
->getBatcher();
104 for(SourceImpl
*alsrc
: alsrcs
)
106 auto iter
= std::lower_bound(mSources
.begin(), mSources
.end(), alsrc
);
107 if(iter
!= mSources
.end() && *iter
== alsrc
) continue;
109 mSources
.insert(iter
, alsrc
);
110 alsrc
->setGroup(this);
114 void SourceGroupImpl::removeSources(ArrayView
<Source
> sources
)
116 Batcher batcher
= mContext
->getBatcher();
117 for(Source source
: sources
)
119 auto iter
= std::lower_bound(mSources
.begin(), mSources
.end(), source
.getHandle());
120 if(iter
!= mSources
.end() && *iter
== source
.getHandle())
122 (*iter
)->unsetGroup();
123 mSources
.erase(iter
);
129 void SourceGroupImpl::addSubGroup(SourceGroup group
)
131 SourceGroupImpl
*algrp
= group
.getHandle();
132 if(!algrp
) throw std::runtime_error("SourceGroup is not valid");
133 CheckContext(mContext
);
135 auto iter
= std::lower_bound(mSubGroups
.begin(), mSubGroups
.end(), algrp
);
136 if(iter
!= mSubGroups
.end() && *iter
== algrp
) return;
138 if(this == algrp
|| algrp
->findInSubGroups(this))
139 throw std::runtime_error("Attempted circular group chain");
141 mSubGroups
.insert(iter
, algrp
);
142 Batcher batcher
= mContext
->getBatcher();
143 algrp
->setParentGroup(this);
146 void SourceGroupImpl::removeSubGroup(SourceGroup group
)
148 auto iter
= std::lower_bound(mSubGroups
.begin(), mSubGroups
.end(), group
.getHandle());
149 if(iter
!= mSubGroups
.end() && *iter
== group
.getHandle())
151 Batcher batcher
= mContext
->getBatcher();
152 (*iter
)->unsetParentGroup();
153 mSubGroups
.erase(iter
);
158 Vector
<Source
> SourceGroupImpl::getSources() const
161 ret
.reserve(mSources
.size());
162 for(SourceImpl
*src
: mSources
)
163 ret
.emplace_back(Source(src
));
167 Vector
<SourceGroup
> SourceGroupImpl::getSubGroups() const
169 Vector
<SourceGroup
> ret
;
170 ret
.reserve(mSubGroups
.size());
171 for(SourceGroupImpl
*grp
: mSubGroups
)
172 ret
.emplace_back(SourceGroup(grp
));
177 void SourceGroupImpl::setGain(ALfloat gain
)
180 throw std::runtime_error("Gain out of range");
181 CheckContext(mContext
);
183 gain
*= mParentProps
.mGain
;
184 ALfloat pitch
= mPitch
* mParentProps
.mPitch
;
185 Batcher batcher
= mContext
->getBatcher();
186 for(SourceImpl
*alsrc
: mSources
)
187 alsrc
->groupPropUpdate(gain
, pitch
);
188 for(SourceGroupImpl
*group
: mSubGroups
)
189 group
->update(gain
, pitch
);
192 void SourceGroupImpl::setPitch(ALfloat pitch
)
195 throw std::runtime_error("Pitch out of range");
196 CheckContext(mContext
);
198 ALfloat gain
= mGain
* mParentProps
.mGain
;
199 pitch
*= mParentProps
.mPitch
;
200 Batcher batcher
= mContext
->getBatcher();
201 for(SourceImpl
*alsrc
: mSources
)
202 alsrc
->groupPropUpdate(gain
, pitch
);
203 for(SourceGroupImpl
*group
: mSubGroups
)
204 group
->update(gain
, pitch
);
208 void SourceGroupImpl::collectPlayingSourceIds(Vector
<ALuint
> &sourceids
) const
210 for(SourceImpl
*alsrc
: mSources
)
212 if(ALuint id
= alsrc
->getId())
213 sourceids
.push_back(id
);
215 for(SourceGroupImpl
*group
: mSubGroups
)
216 group
->collectPlayingSourceIds(sourceids
);
219 void SourceGroupImpl::updatePausedStatus() const
221 for(SourceImpl
*alsrc
: mSources
)
222 alsrc
->checkPaused();
223 for(SourceGroupImpl
*group
: mSubGroups
)
224 group
->updatePausedStatus();
227 void SourceGroupImpl::pauseAll() const
229 CheckContext(mContext
);
230 auto lock
= mContext
->getSourceStreamLock();
232 Vector
<ALuint
> sourceids
;
233 sourceids
.reserve(16);
234 collectPlayingSourceIds(sourceids
);
235 if(!sourceids
.empty())
237 alSourcePausev(sourceids
.size(), sourceids
.data());
238 updatePausedStatus();
244 void SourceGroupImpl::collectPausedSourceIds(Vector
<ALuint
> &sourceids
) const
246 for(SourceImpl
*alsrc
: mSources
)
248 if(alsrc
->isPaused())
249 sourceids
.push_back(alsrc
->getId());
251 for(SourceGroupImpl
*group
: mSubGroups
)
252 group
->collectPausedSourceIds(sourceids
);
255 void SourceGroupImpl::updatePlayingStatus() const
257 for(SourceImpl
*alsrc
: mSources
)
258 alsrc
->unsetPaused();
259 for(SourceGroupImpl
*group
: mSubGroups
)
260 group
->updatePlayingStatus();
263 void SourceGroupImpl::resumeAll() const
265 CheckContext(mContext
);
266 auto lock
= mContext
->getSourceStreamLock();
268 Vector
<ALuint
> sourceids
;
269 sourceids
.reserve(16);
270 collectPausedSourceIds(sourceids
);
271 if(!sourceids
.empty())
273 alSourcePlayv(sourceids
.size(), sourceids
.data());
274 updatePlayingStatus();
280 void SourceGroupImpl::collectSourceIds(Vector
<ALuint
> &sourceids
) const
282 for(SourceImpl
*alsrc
: mSources
)
284 if(ALuint id
= alsrc
->getId())
285 sourceids
.push_back(id
);
287 for(SourceGroupImpl
*group
: mSubGroups
)
288 group
->collectSourceIds(sourceids
);
291 void SourceGroupImpl::updateStoppedStatus() const
293 for(SourceImpl
*alsrc
: mSources
)
295 mContext
->removePendingSource(alsrc
);
296 mContext
->removeFadingSource(alsrc
);
297 mContext
->removePlayingSource(alsrc
);
298 alsrc
->makeStopped(false);
299 mContext
->send(&MessageHandler::sourceForceStopped
, alsrc
);
301 for(SourceGroupImpl
*group
: mSubGroups
)
302 group
->updateStoppedStatus();
305 void SourceGroupImpl::stopAll() const
307 CheckContext(mContext
);
309 Vector
<ALuint
> sourceids
;
310 sourceids
.reserve(16);
311 collectSourceIds(sourceids
);
312 if(!sourceids
.empty())
314 auto lock
= mContext
->getSourceStreamLock();
315 alSourceRewindv(sourceids
.size(), sourceids
.data());
316 updateStoppedStatus();
321 void SourceGroupImpl::release()
323 CheckContext(mContext
);
324 Batcher batcher
= mContext
->getBatcher();
325 for(SourceImpl
*source
: mSources
)
326 source
->unsetGroup();
328 for(SourceGroupImpl
*group
: mSubGroups
)
329 group
->unsetParentGroup();
332 mParent
->eraseSubGroup(this);
335 mContext
->freeSourceGroup(this);
339 DECL_THUNK0(StringView
, SourceGroup
, getName
, const)
340 DECL_THUNK1(void, SourceGroup
, addSource
,, Source
)
341 DECL_THUNK1(void, SourceGroup
, removeSource
,, Source
)
342 DECL_THUNK1(void, SourceGroup
, addSources
,, ArrayView
<Source
>)
343 DECL_THUNK1(void, SourceGroup
, removeSources
,, ArrayView
<Source
>)
344 DECL_THUNK1(void, SourceGroup
, addSubGroup
,, SourceGroup
)
345 DECL_THUNK1(void, SourceGroup
, removeSubGroup
,, SourceGroup
)
346 DECL_THUNK0(Vector
<Source
>, SourceGroup
, getSources
, const)
347 DECL_THUNK0(Vector
<SourceGroup
>, SourceGroup
, getSubGroups
, const)
348 DECL_THUNK1(void, SourceGroup
, setGain
,, ALfloat
)
349 DECL_THUNK0(ALfloat
, SourceGroup
, getGain
, const)
350 DECL_THUNK1(void, SourceGroup
, setPitch
,, ALfloat
)
351 DECL_THUNK0(ALfloat
, SourceGroup
, getPitch
, const)
352 DECL_THUNK0(void, SourceGroup
, pauseAll
, const)
353 DECL_THUNK0(void, SourceGroup
, resumeAll
, const)
354 DECL_THUNK0(void, SourceGroup
, stopAll
, const)
355 void SourceGroup::release()