2 #include "sourcegroup.h"
12 void SourceGroupImpl::insertSubGroup(SourceGroupImpl
*group
)
14 auto iter
= std::lower_bound(mSubGroups
.begin(), mSubGroups
.end(), group
);
15 if(iter
== mSubGroups
.end() || *iter
!= group
)
16 mSubGroups
.insert(iter
, group
);
19 void SourceGroupImpl::eraseSubGroup(SourceGroupImpl
*group
)
21 auto iter
= std::lower_bound(mSubGroups
.begin(), mSubGroups
.end(), group
);
22 if(iter
!= mSubGroups
.end() && *iter
== group
) mSubGroups
.erase(iter
);
26 void SourceGroupImpl::unsetParent()
32 void SourceGroupImpl::update(ALfloat gain
, ALfloat pitch
)
34 mParentProps
.mGain
= gain
;
35 mParentProps
.mPitch
= pitch
;
39 for(SourceImpl
*alsrc
: mSources
)
40 alsrc
->groupPropUpdate(gain
, pitch
);
41 for(SourceGroupImpl
*group
: mSubGroups
)
42 group
->update(gain
, pitch
);
46 bool SourceGroupImpl::findInSubGroups(SourceGroupImpl
*group
) const
48 auto iter
= std::lower_bound(mSubGroups
.begin(), mSubGroups
.end(), group
);
49 if(iter
!= mSubGroups
.end() && *iter
== group
) return true;
51 for(SourceGroupImpl
*grp
: mSubGroups
)
53 if(grp
->findInSubGroups(group
))
60 void SourceGroupImpl::insertSource(SourceImpl
*source
)
62 auto iter
= std::lower_bound(mSources
.begin(), mSources
.end(), source
);
63 if(iter
== mSources
.end() || *iter
!= source
)
64 mSources
.insert(iter
, source
);
67 void SourceGroupImpl::eraseSource(SourceImpl
*source
)
69 auto iter
= std::lower_bound(mSources
.begin(), mSources
.end(), source
);
70 if(iter
!= mSources
.end() && *iter
== source
)
75 DECL_THUNK1(void, SourceGroup
, setParentGroup
,, SourceGroup
)
76 void SourceGroupImpl::setParentGroup(SourceGroup group
)
78 CheckContext(mContext
);
80 SourceGroupImpl
*parent
= group
.getHandle();
84 mParent
->eraseSubGroup(this);
90 if(this == parent
|| findInSubGroups(parent
))
91 throw std::runtime_error("Attempted circular group chain");
93 parent
->insertSubGroup(this);
95 Batcher batcher
= mContext
->getBatcher();
97 mParent
->eraseSubGroup(this);
99 update(mParent
->getAppliedGain(), mParent
->getAppliedPitch());
104 DECL_THUNK0(Vector
<Source
>, SourceGroup
, getSources
, const)
105 Vector
<Source
> SourceGroupImpl::getSources() const
108 ret
.reserve(mSources
.size());
109 for(SourceImpl
*src
: mSources
)
110 ret
.emplace_back(src
);
114 DECL_THUNK0(Vector
<SourceGroup
>, SourceGroup
, getSubGroups
, const)
115 Vector
<SourceGroup
> SourceGroupImpl::getSubGroups() const
117 Vector
<SourceGroup
> ret
;
118 ret
.reserve(mSubGroups
.size());
119 for(SourceGroupImpl
*grp
: mSubGroups
)
120 ret
.emplace_back(grp
);
125 DECL_THUNK1(void, SourceGroup
, setGain
,, ALfloat
)
126 void SourceGroupImpl::setGain(ALfloat gain
)
129 throw std::out_of_range("Gain out of range");
130 CheckContext(mContext
);
132 gain
*= mParentProps
.mGain
;
133 ALfloat pitch
= mPitch
* mParentProps
.mPitch
;
134 Batcher batcher
= mContext
->getBatcher();
135 for(SourceImpl
*alsrc
: mSources
)
136 alsrc
->groupPropUpdate(gain
, pitch
);
137 for(SourceGroupImpl
*group
: mSubGroups
)
138 group
->update(gain
, pitch
);
141 DECL_THUNK1(void, SourceGroup
, setPitch
,, ALfloat
)
142 void SourceGroupImpl::setPitch(ALfloat pitch
)
145 throw std::out_of_range("Pitch out of range");
146 CheckContext(mContext
);
148 ALfloat gain
= mGain
* mParentProps
.mGain
;
149 pitch
*= mParentProps
.mPitch
;
150 Batcher batcher
= mContext
->getBatcher();
151 for(SourceImpl
*alsrc
: mSources
)
152 alsrc
->groupPropUpdate(gain
, pitch
);
153 for(SourceGroupImpl
*group
: mSubGroups
)
154 group
->update(gain
, pitch
);
158 void SourceGroupImpl::collectPlayingSourceIds(Vector
<ALuint
> &sourceids
) const
160 for(SourceImpl
*alsrc
: mSources
)
162 if(ALuint id
= alsrc
->getId())
163 sourceids
.push_back(id
);
165 for(SourceGroupImpl
*group
: mSubGroups
)
166 group
->collectPlayingSourceIds(sourceids
);
169 void SourceGroupImpl::updatePausedStatus() const
171 for(SourceImpl
*alsrc
: mSources
)
172 alsrc
->checkPaused();
173 for(SourceGroupImpl
*group
: mSubGroups
)
174 group
->updatePausedStatus();
177 DECL_THUNK0(void, SourceGroup
, pauseAll
, const)
178 void SourceGroupImpl::pauseAll() const
180 CheckContext(mContext
);
181 auto lock
= mContext
->getSourceStreamLock();
183 Vector
<ALuint
> sourceids
;
184 sourceids
.reserve(16);
185 collectPlayingSourceIds(sourceids
);
186 if(!sourceids
.empty())
188 alSourcePausev(sourceids
.size(), sourceids
.data());
189 updatePausedStatus();
195 void SourceGroupImpl::collectPausedSourceIds(Vector
<ALuint
> &sourceids
) const
197 for(SourceImpl
*alsrc
: mSources
)
199 if(alsrc
->isPaused())
200 sourceids
.push_back(alsrc
->getId());
202 for(SourceGroupImpl
*group
: mSubGroups
)
203 group
->collectPausedSourceIds(sourceids
);
206 void SourceGroupImpl::updatePlayingStatus() const
208 for(SourceImpl
*alsrc
: mSources
)
209 alsrc
->unsetPaused();
210 for(SourceGroupImpl
*group
: mSubGroups
)
211 group
->updatePlayingStatus();
214 DECL_THUNK0(void, SourceGroup
, resumeAll
, const)
215 void SourceGroupImpl::resumeAll() const
217 CheckContext(mContext
);
218 auto lock
= mContext
->getSourceStreamLock();
220 Vector
<ALuint
> sourceids
;
221 sourceids
.reserve(16);
222 collectPausedSourceIds(sourceids
);
223 if(!sourceids
.empty())
225 alSourcePlayv(sourceids
.size(), sourceids
.data());
226 updatePlayingStatus();
232 void SourceGroupImpl::collectSourceIds(Vector
<ALuint
> &sourceids
) const
234 for(SourceImpl
*alsrc
: mSources
)
236 if(ALuint id
= alsrc
->getId())
237 sourceids
.push_back(id
);
239 for(SourceGroupImpl
*group
: mSubGroups
)
240 group
->collectSourceIds(sourceids
);
243 void SourceGroupImpl::updateStoppedStatus() const
245 for(SourceImpl
*alsrc
: mSources
)
247 mContext
->removePendingSource(alsrc
);
248 mContext
->removeFadingSource(alsrc
);
249 mContext
->removePlayingSource(alsrc
);
250 alsrc
->makeStopped(false);
251 mContext
->send(&MessageHandler::sourceForceStopped
, alsrc
);
253 for(SourceGroupImpl
*group
: mSubGroups
)
254 group
->updateStoppedStatus();
257 DECL_THUNK0(void, SourceGroup
, stopAll
, const)
258 void SourceGroupImpl::stopAll() const
260 CheckContext(mContext
);
262 Vector
<ALuint
> sourceids
;
263 sourceids
.reserve(16);
264 collectSourceIds(sourceids
);
265 if(!sourceids
.empty())
267 auto lock
= mContext
->getSourceStreamLock();
268 alSourceRewindv(sourceids
.size(), sourceids
.data());
269 updateStoppedStatus();
274 void SourceGroup::release()
276 SourceGroupImpl
*i
= pImpl
;
280 void SourceGroupImpl::release()
282 CheckContext(mContext
);
283 Batcher batcher
= mContext
->getBatcher();
284 for(SourceImpl
*source
: mSources
)
285 source
->unsetGroup();
287 for(SourceGroupImpl
*group
: mSubGroups
)
288 group
->unsetParent();
291 mParent
->eraseSubGroup(this);
294 mContext
->freeSourceGroup(this);
298 DECL_THUNK0(SourceGroup
, SourceGroup
, getParentGroup
, const)
299 DECL_THUNK0(ALfloat
, SourceGroup
, getGain
, const)
300 DECL_THUNK0(ALfloat
, SourceGroup
, getPitch
, const)