11namespace tracktion {
inline namespace engine
17 soloed.referTo (state, IDs::solo,
nullptr);
18 muted.referTo (state, IDs::mute,
nullptr);
19 soloIsolated.referTo (state, IDs::soloIsolate,
nullptr);
21 pluginUpdater.setFunction ([
this] { updatePlugins(); });
24FolderTrack::~FolderTrack()
26 notifyListenersOfDeletion();
29void FolderTrack::initialise()
37 return (isSubmixFolder() ?
TRANS(
"Submix") :
TRANS(
"Folder")) +
" - \"" +
getName() +
"\"";
40bool FolderTrack::isFolderTrack()
const
45void FolderTrack::sanityCheckName()
47 auto n = Track::getName();
51 return ((n.startsWithIgnoreCase (
"Folder ")
52 || n.startsWithIgnoreCase (
TRANS(type) +
" "))
53 && n.substring (6).trim().containsOnly (
"0123456789"));
56 if (checkName (
"Folder") || checkName (
"Submix"))
65 auto n = Track::getName();
68 n << (isSubmixFolder() ?
TRANS(
"Submix")
69 :
TRANS(
"Folder")) <<
' ' << getFolderTrackNumber();
74int FolderTrack::getFolderTrackNumber() const noexcept
78 edit.visitAllTracksRecursive ([&] (
Track& t)
83 if (t.isFolderTrack())
92bool FolderTrack::isSubmixFolder()
const
94 for (
auto p : pluginList)
95 if (dynamic_cast<VCAPlugin*> (p) == nullptr && dynamic_cast<TextPlugin*> (p) == nullptr)
103 if (! isSubmixFolder())
106 for (
auto t : getAllAudioSubTracks (
true))
108 return &at->getOutput();
117 for (
auto track : getAllSubTracks (
false))
119 if (
dynamic_cast<AudioTrack*
> (track) !=
nullptr)
123 if (ft->isSubmixFolder())
130bool FolderTrack::isMuted (
bool includeMutingByDestination)
const
135 if (includeMutingByDestination)
136 if (
auto p = getParentFolderTrack())
137 return p->isMuted (
true);
142bool FolderTrack::isSolo (
bool includeIndirectSolo)
const
147 if (includeIndirectSolo)
150 for (
auto p = getParentFolderTrack(); p !=
nullptr; p = p->getParentFolderTrack())
151 if (p->isSolo (
false))
154 if (! isPartOfSubmix())
155 if (
auto output = getOutput())
156 if (
auto dest = output->getDestinationTrack())
157 return dest->isSolo (
true);
160 bool anySubTracksSolo =
false;
162 if (
auto tl = getSubTrackList())
163 tl->visitAllRecursive ([&anySubTracksSolo] (
Track& t)
165 if (t.isSolo (
false))
167 anySubTracksSolo = true;
174 return anySubTracksSolo;
180bool FolderTrack::isSoloIsolate (
bool includeIndirectSolo)
const
185 if (includeIndirectSolo)
188 for (
auto p = getParentFolderTrack(); p !=
nullptr; p = p->getParentFolderTrack())
189 if (p->isSoloIsolate (
false))
192 if (! isPartOfSubmix())
193 if (
auto output = getOutput())
194 if (
auto dest = output->getDestinationTrack())
195 return dest->isSoloIsolate (
true);
198 bool anySubTracksSolo =
false;
200 if (
auto tl = getSubTrackList())
201 tl->visitAllRecursive ([&anySubTracksSolo] (
Track& t)
203 if (t.isSoloIsolate (
false))
205 anySubTracksSolo = true;
212 return anySubTracksSolo;
222 if (
auto ptr = vcaPlugin)
223 if (ptr->isEnabled())
224 return ptr->updateAutomationStreamAndGetVolumeDb (time);
229TimeRange FolderTrack::getClipExtendedBounds (
Clip& c)
233 return cc->getEditTimeRange();
235 return c.getEditTimeRange();
238void FolderTrack::generateCollectionClips (SelectionManager& sm)
247 for (
int i = collectionClips.size(); --i >= 0;)
249 if (
auto cc = collectionClips[i])
252 if (sm.isSelected (*cc) && ! cc->isDragging())
254 sm.deselect (cc.get());
255 selectedClips.
addArray (cc->getClips());
259 if (! cc->isDragging())
260 collectionClips.remove (i);
265 for (
int i = 0; i < collectionClips.size(); ++i)
267 if (
auto cc = collectionClips[i])
269 if (cc->getNumClips() > 0)
274 for (
int j = cc->getNumClips(); --j >= 0;)
276 auto c = cc->getClip(j);
278 if (c ==
nullptr || c->getTrack() ==
nullptr)
280 cc->removeClip (c.get());
284 auto pos = c->getPosition();
286 if (pos.getLength() > TimeDuration::fromSeconds (0.000001))
289 totalRange = pos.time;
291 totalRange = totalRange.getUnionWith (pos.time);
298 cc->range = totalRange;
306 for (
auto at : getAllAudioSubTracks (true))
307 clips.addArray (at->getClips());
309 TrackItem::sortByTime (clips);
312 for (
int i = clips.
size(); --i >= 0;)
316 for (
auto cc : collectionClips)
318 if (cc->containsClip (c))
327 CollectionClip* colClip =
nullptr;
329 for (
auto clip : clips)
331 const auto tolerance = 0.000001s;
332 auto bounds = getClipExtendedBounds (*clip);
334 if (bounds.getLength() > tolerance)
336 if (colClip ==
nullptr || bounds.getStart() + tolerance >= colClip->getPosition().getEnd())
338 colClip =
new CollectionClip (*
this);
339 colClip->range = bounds;
340 colClip->addClip (clip);
342 collectionClips.add (colClip);
346 if (bounds.getEnd() > colClip->getPosition().getEnd())
347 colClip->range =
TimeRange (colClip->range.getStart(), bounds.getEnd());
349 colClip->addClip (clip);
355 for (
auto cc : collectionClips)
356 for (auto c : selectedClips)
358 sm.addToSelection (cc);
362 for (
auto cc : collectionClips)
364 jassert (Selectable::isSelectableValid (cc));
369 for (
auto c : cc->getClips())
371 auto bounds = getClipExtendedBounds (*c);
373 if (bounds.getLength() > 0.000001s)
378 totalRange = totalRange.getUnionWith (bounds);
384 cc->range = totalRange;
389CollectionClip* FolderTrack::getCollectionClip (
int index)
const noexcept
391 return collectionClips[index].get();
394int FolderTrack::getNumCollectionClips() const noexcept
396 return collectionClips.size();
399int FolderTrack::indexOfCollectionClip (CollectionClip* c)
const
401 return collectionClips.indexOf (c);
404int FolderTrack::getIndexOfNextCollectionClipAt (TimePosition time)
409CollectionClip* FolderTrack::getNextCollectionClipAt (TimePosition time)
411 return collectionClips[getIndexOfNextCollectionClipAt (time)].get();
414bool FolderTrack::contains (CollectionClip* clip)
const
416 return collectionClips.contains (clip);
421 return indexOfCollectionClip (
dynamic_cast<CollectionClip*
> (ti));
424int FolderTrack::getNumTrackItems()
const
426 return getNumCollectionClips();
431 return getIndexOfNextCollectionClipAt (
time);
436 return getCollectionClip (idx);
441 return getNextCollectionClipAt (
time);
444VCAPlugin* FolderTrack::getVCAPlugin() {
return pluginList.findFirstPluginOfType<
VCAPlugin>(); }
447void FolderTrack::setDirtyClips()
451 if (
auto p = getParentFolderTrack())
458 if (isSubmixFolder())
461 for (
auto at : getAllAudioSubTracks (
true))
462 if (at->isFrozen (t))
468bool FolderTrack::canContainPlugin (
Plugin* p)
const
473bool FolderTrack::willAcceptPlugin (
Plugin& p)
475 if (! canContainPlugin (&p))
478 if (
dynamic_cast<TextPlugin*
> (&p) !=
nullptr)
481 if (
dynamic_cast<VCAPlugin*
> (&p) !=
nullptr)
482 return getVCAPlugin() ==
nullptr;
484 if (! isSubmixFolder())
490void FolderTrack::setMute (
bool b) { muted = b; }
491void FolderTrack::setSolo (
bool b) { soloed = b; }
492void FolderTrack::setSoloIsolate (
bool b) { soloIsolated = b; }
494void FolderTrack::updatePlugins()
497 vcaPlugin = pluginList.findFirstPluginOfType<
VCAPlugin>();
503 if (c.hasType (IDs::PLUGIN))
504 pluginUpdater.triggerAsyncUpdate();
506 Track::valueTreeChildAdded (p, c);
511 if (c.hasType (IDs::PLUGIN))
512 pluginUpdater.triggerAsyncUpdate();
514 Track::valueTreeChildRemoved (p, c, index);
517void FolderTrack::valueTreeChildOrderChanged (
juce::ValueTree& p,
int oldIndex,
int newIndex)
519 if (p.getChild (oldIndex).hasType (IDs::PLUGIN) || p.getChild (newIndex).hasType (IDs::PLUGIN))
520 pluginUpdater.triggerAsyncUpdate();
522 Track::valueTreeChildOrderChanged (p, oldIndex, newIndex);
ElementType getUnchecked(int index) const
void addArray(const Type *elementsToAdd, int numElementsToAdd)
int size() const noexcept
void remove(int indexToRemove)
void add(const ElementType &newElement)
UIBehaviour & getUIBehaviour() const
Returns the UIBehaviour class.
Base class for EditItems that live in a Track, e.g.
Represents the destination output device(s) for a track.
Base class for tracks which contain clips and plugins and can be added to Edit[s].
FreezeType
Determines the type of freeze.
virtual void showWarningMessage(const juce::String &message)
Should display a temporary warning message.
The VCA plugin sits on a folder track to control the overall level of all the volume/pan plugins in i...
The built-in Tracktion volume/pan plugin.
#define TRANS(stringLiteral)
juce::String getName(LaunchQType t)
Retuns the name of a LaunchQType for display purposes.
int findIndexOfNextItemAt(const ArrayType &items, TimePosition time)
Returns the index of the next item after the given time.
bool containsClip(const Edit &edit, Clip *clip)
Returns true if an Edit contains a given clip.
RangeType< TimePosition > TimeRange
A RangeType based on real time (i.e.
Represents a position in real-life time.
#define CRASH_TRACER
This macro adds the current location to a stack which gets logged if a crash happens.