2 #include "sourcegroup.h"
11 void SourceGroupImpl::insertSubGroup(SourceGroupImpl
*group
)
13 auto iter
= std::lower_bound(mSubGroups
.begin(), mSubGroups
.end(), group
);
14 if(iter
== mSubGroups
.end() || *iter
!= group
)
15 mSubGroups
.insert(iter
, group
);
18 void SourceGroupImpl::eraseSubGroup(SourceGroupImpl
*group
)
20 auto iter
= std::lower_bound(mSubGroups
.begin(), mSubGroups
.end(), group
);
21 if(iter
!= mSubGroups
.end() && *iter
== group
) mSubGroups
.erase(iter
);
25 void SourceGroupImpl::unsetParent()
31 void SourceGroupImpl::update(ALfloat gain
, ALfloat pitch
)
33 mParentProps
.mGain
= gain
;
34 mParentProps
.mPitch
= pitch
;
38 for(SourceImpl
*alsrc
: mSources
)
39 alsrc
->groupPropUpdate(gain
, pitch
);
40 for(SourceGroupImpl
*group
: mSubGroups
)
41 group
->update(gain
, pitch
);
45 bool SourceGroupImpl::findInSubGroups(SourceGroupImpl
*group
) const
47 auto iter
= std::lower_bound(mSubGroups
.begin(), mSubGroups
.end(), group
);
48 if(iter
!= mSubGroups
.end() && *iter
== group
) return true;
50 for(SourceGroupImpl
*grp
: mSubGroups
)
52 if(grp
->findInSubGroups(group
))
59 void SourceGroupImpl::insertSource(SourceImpl
*source
)
61 auto iter
= std::lower_bound(mSources
.begin(), mSources
.end(), source
);
62 if(iter
== mSources
.end() || *iter
!= source
)
63 mSources
.insert(iter
, source
);
66 void SourceGroupImpl::eraseSource(SourceImpl
*source
)
68 auto iter
= std::lower_bound(mSources
.begin(), mSources
.end(), source
);
69 if(iter
!= mSources
.end() && *iter
== source
)
74 DECL_THUNK1(void, SourceGroup
, setParentGroup
,, SourceGroup
)
75 void SourceGroupImpl::setParentGroup(SourceGroup group
)
77 CheckContext(mContext
);
79 SourceGroupImpl
*parent
= group
.getHandle();
83 mParent
->eraseSubGroup(this);
89 if(this == parent
|| findInSubGroups(parent
))
90 throw std::runtime_error("Attempted circular group chain");
92 parent
->insertSubGroup(this);
94 Batcher batcher
= mContext
.getBatcher();
96 mParent
->eraseSubGroup(this);
98 update(mParent
->getAppliedGain(), mParent
->getAppliedPitch());
103 DECL_THUNK0(Vector
<Source
>, SourceGroup
, getSources
, const)
104 Vector
<Source
> SourceGroupImpl::getSources() const
107 ret
.reserve(mSources
.size());
108 for(SourceImpl
*src
: mSources
)
109 ret
.emplace_back(src
);
113 DECL_THUNK0(Vector
<SourceGroup
>, SourceGroup
, getSubGroups
, const)
114 Vector
<SourceGroup
> SourceGroupImpl::getSubGroups() const
116 Vector
<SourceGroup
> ret
;
117 ret
.reserve(mSubGroups
.size());
118 for(SourceGroupImpl
*grp
: mSubGroups
)
119 ret
.emplace_back(grp
);
124 DECL_THUNK1(void, SourceGroup
, setGain
,, ALfloat
)
125 void SourceGroupImpl::setGain(ALfloat gain
)
128 throw std::out_of_range("Gain out of range");
129 CheckContext(mContext
);
131 gain
*= mParentProps
.mGain
;
132 ALfloat pitch
= mPitch
* mParentProps
.mPitch
;
133 Batcher batcher
= mContext
.getBatcher();
134 for(SourceImpl
*alsrc
: mSources
)
135 alsrc
->groupPropUpdate(gain
, pitch
);
136 for(SourceGroupImpl
*group
: mSubGroups
)
137 group
->update(gain
, pitch
);
140 DECL_THUNK1(void, SourceGroup
, setPitch
,, ALfloat
)
141 void SourceGroupImpl::setPitch(ALfloat pitch
)
144 throw std::out_of_range("Pitch out of range");
145 CheckContext(mContext
);
147 ALfloat gain
= mGain
* mParentProps
.mGain
;
148 pitch
*= mParentProps
.mPitch
;
149 Batcher batcher
= mContext
.getBatcher();
150 for(SourceImpl
*alsrc
: mSources
)
151 alsrc
->groupPropUpdate(gain
, pitch
);
152 for(SourceGroupImpl
*group
: mSubGroups
)
153 group
->update(gain
, pitch
);
157 void SourceGroupImpl::collectPlayingSourceIds(Vector
<ALuint
> &sourceids
) const
159 for(SourceImpl
*alsrc
: mSources
)
161 if(ALuint id
= alsrc
->getId())
162 sourceids
.push_back(id
);
164 for(SourceGroupImpl
*group
: mSubGroups
)
165 group
->collectPlayingSourceIds(sourceids
);
168 void SourceGroupImpl::updatePausedStatus() const
170 for(SourceImpl
*alsrc
: mSources
)
171 alsrc
->checkPaused();
172 for(SourceGroupImpl
*group
: mSubGroups
)
173 group
->updatePausedStatus();
176 DECL_THUNK0(void, SourceGroup
, pauseAll
, const)
177 void SourceGroupImpl::pauseAll() const
179 CheckContext(mContext
);
180 auto lock
= mContext
.getSourceStreamLock();
182 Vector
<ALuint
> sourceids
;
183 sourceids
.reserve(16);
184 collectPlayingSourceIds(sourceids
);
185 if(!sourceids
.empty())
187 alSourcePausev(static_cast<ALsizei
>(sourceids
.size()), sourceids
.data());
188 updatePausedStatus();
194 void SourceGroupImpl::collectPausedSourceIds(Vector
<ALuint
> &sourceids
) const
196 for(SourceImpl
*alsrc
: mSources
)
198 if(alsrc
->isPaused())
199 sourceids
.push_back(alsrc
->getId());
201 for(SourceGroupImpl
*group
: mSubGroups
)
202 group
->collectPausedSourceIds(sourceids
);
205 void SourceGroupImpl::updatePlayingStatus() const
207 for(SourceImpl
*alsrc
: mSources
)
208 alsrc
->unsetPaused();
209 for(SourceGroupImpl
*group
: mSubGroups
)
210 group
->updatePlayingStatus();
213 DECL_THUNK0(void, SourceGroup
, resumeAll
, const)
214 void SourceGroupImpl::resumeAll() const
216 CheckContext(mContext
);
217 auto lock
= mContext
.getSourceStreamLock();
219 Vector
<ALuint
> sourceids
;
220 sourceids
.reserve(16);
221 collectPausedSourceIds(sourceids
);
222 if(!sourceids
.empty())
224 alSourcePlayv(static_cast<ALsizei
>(sourceids
.size()), sourceids
.data());
225 updatePlayingStatus();
231 void SourceGroupImpl::collectSourceIds(Vector
<ALuint
> &sourceids
) const
233 for(SourceImpl
*alsrc
: mSources
)
235 if(ALuint id
= alsrc
->getId())
236 sourceids
.push_back(id
);
238 for(SourceGroupImpl
*group
: mSubGroups
)
239 group
->collectSourceIds(sourceids
);
242 void SourceGroupImpl::updateStoppedStatus() const
244 for(SourceImpl
*alsrc
: mSources
)
246 mContext
.removePendingSource(alsrc
);
247 mContext
.removeFadingSource(alsrc
);
248 mContext
.removePlayingSource(alsrc
);
249 alsrc
->makeStopped(false);
250 mContext
.send(&MessageHandler::sourceForceStopped
, alsrc
);
252 for(SourceGroupImpl
*group
: mSubGroups
)
253 group
->updateStoppedStatus();
256 DECL_THUNK0(void, SourceGroup
, stopAll
, const)
257 void SourceGroupImpl::stopAll() const
259 CheckContext(mContext
);
261 Vector
<ALuint
> sourceids
;
262 sourceids
.reserve(16);
263 collectSourceIds(sourceids
);
264 if(!sourceids
.empty())
266 auto lock
= mContext
.getSourceStreamLock();
267 alSourceRewindv(static_cast<ALsizei
>(sourceids
.size()), sourceids
.data());
268 updateStoppedStatus();
273 void SourceGroup::destroy()
275 SourceGroupImpl
*i
= pImpl
;
279 void SourceGroupImpl::destroy()
281 CheckContext(mContext
);
282 Batcher batcher
= mContext
.getBatcher();
283 for(SourceImpl
*source
: mSources
)
284 source
->unsetGroup();
286 for(SourceGroupImpl
*group
: mSubGroups
)
287 group
->unsetParent();
290 mParent
->eraseSubGroup(this);
293 mContext
.freeSourceGroup(this);
297 DECL_THUNK0(SourceGroup
, SourceGroup
, getParentGroup
, const)
298 DECL_THUNK0(ALfloat
, SourceGroup
, getGain
, const)
299 DECL_THUNK0(ALfloat
, SourceGroup
, getPitch
, const)