11namespace tracktion {
inline namespace engine
14Edit::GlobalMacros::GlobalMacros (Edit& e)
15 : MacroParameterElement (e, e.state),
32 ref->edit.getUndoManager().addChangeListener (ref.get());
38 edit.getUndoManager().removeChangeListener (
this);
41 void timerCallback()
override
43 if (edit.numUndoTransactionInhibitors > 0)
46 if (! juce::Component::isMouseButtonDownAnywhere())
49 edit.getUndoManager().beginNewTransaction();
73 void timerCallback()
override
76 edit.resetChangedStatus();
77 edit.changeResetterTimer.reset();
88 state.addListener (
this);
96 if (v.hasType (IDs::TRANSPORT))
98 if (i == IDs::recordPunchInOut)
102 if (ecm.isAttachedToEdit (edit))
103 ecm.updatePunchLights();
105 else if (i == IDs::endToEnd)
109 if (v[IDs::endToEnd])
116 if (ecm.isAttachedToEdit (edit))
117 ecm.updateAllDevices();
121 else if (TrackList::isTrack (v))
123 if (i == IDs::frozenIndividually || i == IDs::compGroup)
127 else if (i == IDs::frozen)
129 edit.needToUpdateFrozenTracks();
131 else if (i == IDs::process)
135 else if (i == IDs::mute || i == IDs::solo || i == IDs::soloIsolate)
141 else if (Clip::isClipState (v))
143 if (i == IDs::start || i == IDs::length || i == IDs::offset)
145 clipMovedOrAdded (v);
147 else if (i == IDs::linkID)
149 linkedClipsChanged();
151 else if (i == IDs::speed || i == IDs::source || i == IDs::mpeMode
152 || i == IDs::fadeInType || i == IDs::fadeOutType
153 || i == IDs::fadeInBehaviour || i == IDs::fadeOutBehaviour
154 || i == IDs::fadeIn || i == IDs::fadeOut
155 || i == IDs::loopStart || i == IDs::loopLength
156 || i == IDs::loopStartBeats || i == IDs::loopLengthBeats
157 || i == IDs::transpose || i == IDs::pitchChange
158 || i == IDs::elastiqueMode || i == IDs::elastiqueOptions
159 || i == IDs::autoPitch || i == IDs::autoTempo
160 || i == IDs::channels || i == IDs::isReversed
161 || i == IDs::currentTake || i == IDs::sequence || i == IDs::repeatSequence
162 || i == IDs::loopedSequenceType || i == IDs::grooveStrength
163 || i == IDs::proxyAllowed || i == IDs::resamplingQuality || i == IDs::warpTime
164 || i == IDs::disabled || i == IDs::followActionBeats || i == IDs::followActionNumLoops
165 || i == IDs::followActionDurationType)
170 else if (v.hasType (IDs::COMPSECTION))
174 else if (v.hasType (IDs::WARPMARKER))
176 if (i == IDs::sourceTime || i == IDs::warpTime)
179 else if (v.hasType (IDs::QUANTISATION))
181 if (i == IDs::type || i == IDs::amount)
184 else if (v.hasType (IDs::NOTE) || v.hasType (IDs::CONTROL) || v.hasType (IDs::SYSEX))
189 else if (MidiExpression::isExpression (v.getType()))
191 if (i == IDs::b || i == IDs::v)
194 else if (v.hasType (IDs::CHANNEL))
196 if (i == IDs::pattern || i == IDs::channel
197 || i == IDs::velocities || i == IDs::gates || i == IDs::probabilities
198 || i == IDs::note || i == IDs::velocity || i == IDs::groove
199 || i == IDs::grooveStrength)
202 else if (v.hasType (IDs::PATTERN))
204 if (i == IDs::noteLength || i == IDs::numNotes)
207 else if (v.hasType (IDs::SEQUENCE))
209 if (i == IDs::channelNumber)
212 else if (v.hasType (IDs::GROOVE))
214 if (i == IDs::current)
217 else if (v.hasType (IDs::TAKES))
219 if (i == IDs::currentTake)
222 else if (v.hasType (IDs::SIDECHAINCONNECTION))
226 else if (v.hasType (IDs::CLICKTRACK))
228 if (i == IDs::active)
232 if (ecm.isAttachedToEdit (edit))
236 else if (v.hasType (IDs::TEMPO) || v.hasType (IDs::TIMESIG))
241 else if (v.hasType (IDs::PLUGIN))
243 if (i == IDs::enabled
250 const auto type = v[IDs::type].
toString();
252 if (type == AuxSendPlugin::xmlTypeName || type == AuxReturnPlugin::xmlTypeName)
254 if (i == IDs::enabled || i == IDs::busNum)
257 else if (type == RackInstance::xmlTypeName)
259 if (i == IDs::enabled
260 || i == IDs::leftTo || i == IDs::rightTo || i == IDs::leftFrom || i == IDs::rightFrom)
263 else if (i == IDs::outputDevice || i == IDs::inputDevice
264 || i == IDs::manualAdjustMs || i == IDs::sidechainSourceID || i == IDs::ignoreVca || i == IDs::busNum)
270 else if (v.hasType (IDs::MASTERVOLUME))
272 if (i == IDs::fadeIn || i == IDs::fadeOut
273 || i == IDs::fadeInType || i == IDs::fadeOutType)
276 else if (v.hasType (IDs::LOOPINFO))
278 if (i == IDs::numBeats || i == IDs::rootNote
279 || i == IDs::numerator || i == IDs::denominator)
284 else if (v.hasType (IDs::ACTION) && v.getParent().hasType (IDs::FOLLOWACTIONS))
286 if (i == IDs::type || i == IDs::weight)
293 childAddedOrRemoved (p, c,
true);
298 childAddedOrRemoved (p, c,
false);
303 if (c.hasType (IDs::NOTE)
304 || c.hasType (IDs::CONTROL)
305 || c.hasType (IDs::SYSEX)
306 || c.hasType (IDs::PLUGININSTANCE)
307 || c.hasType (IDs::CONNECTION)
308 || p.hasType (IDs::CHANNELS)
309 || c.hasType (IDs::CHANNELS)
310 || c.hasType (IDs::SIDECHAINCONNECTION)
311 || c.hasType (IDs::MACROPARAMETERS)
312 || c.hasType (IDs::MACROPARAMETER)
313 || p.hasType (IDs::MAPPEDPARAMETER)
314 || c.hasType (IDs::LFO)
315 || c.hasType (IDs::BREAKPOINTOSCILLATOR)
316 || c.hasType (IDs::STEP)
317 || c.hasType (IDs::ENVELOPEFOLLOWER)
318 || c.hasType (IDs::RANDOM)
319 || c.hasType (IDs::MIDITRACKER)
320 || p.hasType (IDs::LOOPINFO)
321 || p.hasType (IDs::PATTERN))
325 else if (c.hasType (IDs::PLUGIN)
326 || c.hasType (IDs::RACK))
329 EditItemID::readOrCreateNewID (edit, c);
333 else if (Clip::isClipState (c))
336 EditItemID::readOrCreateNewID (edit, c);
338 clipMovedOrAdded (c);
339 linkedClipsChanged();
341 else if (TrackList::isTrack (c))
344 EditItemID::readOrCreateNewID (edit, c);
349 else if (c.hasType (IDs::WARPMARKER))
353 else if (p.hasType (IDs::TRACKCOMP))
357 else if (p.hasType (IDs::TEMPOSEQUENCE))
362 else if (p.hasType (IDs::NOTE))
366 else if (p.hasType (IDs::FOLLOWACTIONS) && c.hasType (IDs::ACTION))
372 void valueTreeChildOrderChanged (
juce::ValueTree&,
int,
int)
override {}
379 if (v.hasType (IDs::AUDIOCLIP)
380 || v.hasType (IDs::MIDICLIP)
381 || v.hasType (IDs::STEPCLIP)
382 || v.hasType (IDs::EDITCLIP)
383 || v.hasType (IDs::CHORDCLIP)
384 || v.hasType (IDs::CONTAINERCLIP))
386 if (! v[IDs::disabled])
396 void updateTrackStatusesAsync()
398 if (trackStatusUpdater ==
nullptr)
406 void handleAsyncUpdate()
override
408 if (! owner.edit.isLoading())
409 owner.edit.updateTrackStatuses();
411 owner.trackStatusUpdater =
nullptr;
420 void linkedClipsChanged()
422 linkedClipsMapDirty =
true;
429 if (linkedClipsMapDirty)
431 linkedClipsMap.clear();
435 if (
auto ct =
dynamic_cast<ClipTrack*
> (&t))
436 for (
auto c : ct->getClips())
437 if (c->getLinkGroupID().isNotEmpty())
438 linkedClipsMap[c->getLinkGroupID()].add (c);
443 linkedClipsMapDirty =
false;
446 return linkedClipsMap[linkGroupid];
449 void messageThreadAssertIfLoaded()
const
453 TRACKTION_ASSERT_MESSAGE_THREAD
457 bool linkedClipsMapDirty =
true;
471 changedPlugins.addIfNotAlreadyThere (&p);
476 changedPlugins.clear();
482 TRACKTION_ASSERT_MESSAGE_THREAD
484 if (
auto index = changedPlugins.indexOf (&p); index >= 0)
486 p.flushPluginStateToValueTree();
487 changedPlugins.remove (index);
494 for (
auto& plugin : changedPlugins)
495 if (
auto p = plugin.get())
496 p->flushPluginStateToValueTree();
509 void handleAsyncUpdate()
override { edit.updateFrozenTracks(); }
523 void timerCallback()
override
537 void pluginChanged (
Plugin& p)
539 changedPlugins.addIfNotAlreadyThere (&p);
543 void timerCallback()
override
549 for (
auto& changed : changedPlugins)
550 if (
auto p = changed.get())
553 changedPlugins.clear();
562static int getNextInstanceId() noexcept
570 : engine (options.engine),
571 tempoSequence (*this),
572 state (options.editState),
573 instanceId (getNextInstanceId()),
574 editProjectItemID (options.editProjectItemID),
575 loadContext (options.loadContext),
576 editRole (options.role)
582 jassert (editProjectItemID.load().isValid());
590 return item->getSourceFile();
627 initialise (options);
631 if (loadContext !=
nullptr && ! loadContext->
shouldExit)
634 loadContext =
nullptr;
639 TRACKTION_LOG (
"Loaded edit: " +
getName());
655 ProjectItemID::fromProperty (editState, IDs::projectID),
668 track->getOutput().setOutputToDefaultDevice (
false);
675 for (
auto af : pluginCache->getPlugins())
676 af->hideWindowForShutdown();
678 for (
auto at : getTracksOfType<AudioTrack> (*
this,
true))
679 for (
auto c : at->getClips())
681 acb->hideMelodyneWindow();
684 masterReference.clear();
685 changeResetterTimer.reset();
687 if (transportControl !=
nullptr)
688 transportControl->freePlaybackContext();
692 jassert (juce::MessageManager::getInstance()->currentThreadHasLockedMessageManager());
694 jassert (numUndoTransactionInhibitors == 0);
697 changedPluginsList.reset();
698 editInputDevices.reset();
701 notifyListenersOfDeletion();
705 pluginChangeTimer.reset();
709 for (
auto rt : rackTypes->getTypes())
710 rt->hideWindowForShutdown();
714 globalMacros.reset();
715 masterVolumePlugin.
reset();
716 masterPluginList->releaseObjects();
717 masterPluginList.reset();
719 mirroredPluginUpdateTimer.reset();
721 undoTransactionTimer.reset();
722 markerManager.reset();
723 araDocumentHolder.reset();
724 frozenTrackCallback.reset();
736 return item->getName();
743 editProjectItemID = newID;
744 state.
setProperty (IDs::projectID, editProjectItemID.load().toString(),
nullptr);
748 : edit (ed), reallocateOnDestruction (shouldReallocateOnDestruction)
750 TRACKTION_ASSERT_MESSAGE_THREAD
751 jassert (edit.performingRenderCount >= 0);
752 ++edit.performingRenderCount;
758 TRACKTION_ASSERT_MESSAGE_THREAD
759 jassert (edit.performingRenderCount > 0);
760 --edit.performingRenderCount;
762 if (edit.performingRenderCount == 0 && reallocateOnDestruction && edit.
shouldPlay())
768void Edit::initialise (
const Options& options)
773 if (loadContext !=
nullptr)
778 isLoadInProgress =
true;
782 addValueTreeProperties (
state,
790 initialiseTempoAndPitch();
791 initialiseTransport();
793 initialiseClickTrack();
794 initialiseMasterVolume();
796 initialiseMasterPlugins();
797 initialiseAudioDevices();
800 if (loadContext !=
nullptr)
803 initialiseTracks (options);
806 readFrozenTracksFiles();
813 initialiseControllerMappings();
817 TemporaryFileManager::purgeOrphanFreezeAndProxyFiles (*
this);
821 isLoadInProgress =
false;
824 for (auto mp : mpl->getMacroParameters())
831 effect->initialise();
839 #if TRACKTION_ENABLE_AUTOMAP && TRACKTION_ENABLE_CONTROL_SURFACES
849 DBG (
"Edit loaded in: " << loadTimer.getDescription());
852void Edit::initialiseTempoAndPitch()
860 if (needToLoadOldTempoData)
861 loadOldTimeSigInfo();
866 timecodeFormat.referTo (
state, IDs::timecodeFormat,
nullptr);
871 timecodeOffset.referTo (transportState, IDs::midiTimecodeOffset,
nullptr);
874 midiTimecodeSourceDevice.
referTo (transportState, IDs::midiTimecodeSourceDevice,
nullptr);
875 midiMachineControlSourceDevice.
referTo (transportState, IDs::midiMachineControlSourceDevice,
nullptr);
876 midiMachineControlDestDevice.
referTo (transportState, IDs::midiMachineControlDestDevice,
nullptr);
879void Edit::initialiseTransport()
882 initialiseTimecode (transportState);
885void Edit::initialiseMasterVolume()
887 auto* um = &undoManager;
893 if (oldMasterVolState.isValid())
896 copyValueTree (masterVolState, oldMasterVolState,
nullptr);
898 mvTree.addChild (masterVolState, -1,
nullptr);
901 if (! masterVolState.isValid())
903 masterVolState = VolumeAndPanPlugin::create();
904 masterVolState.setProperty (IDs::volume, decibelsToVolumeFaderPosition (-3.0f),
nullptr);
905 mvTree.addChild (masterVolState, -1,
nullptr);
908 masterVolumePlugin =
new VolumeAndPanPlugin (*
this, masterVolState,
true);
915 if (mvTree.hasProperty (IDs::left))
918 const float masterVolL = (
float) mvTree.getProperty (IDs::left, decibelsToVolumeFaderPosition (0.0f));
919 const float masterVolR = (
float) mvTree.getProperty (IDs::right, decibelsToVolumeFaderPosition (0.0f));
921 const float leftGain = volumeFaderPositionToGain (masterVolL);
922 const float rightGain = volumeFaderPositionToGain (masterVolR);
923 const float volGain = (leftGain + rightGain) * 0.5f;
925 const float masterVolumeFaderPos = gainToVolumeFaderPosition (volGain);
926 const float masterPan = (rightGain - volGain) / volGain;
936void Edit::initialiseClickTrack()
949 clickTrackDevice.
referTo (click, IDs::outputDevice,
nullptr);
952void Edit::loadTracks()
960 treeWatcher->linkedClipsChanged();
961 updateTrackStatuses();
964void Edit::removeZeroLengthClips()
966 Clip::Array clipsToRemove;
969 for (auto& c : t->getClips())
970 if (c->getPosition().
getLength().inSeconds() <= 0.0)
971 clipsToRemove.add (c);
973 for (
auto& c : clipsToRemove)
974 c->removeFromParent();
977void Edit::initialiseTracks (
const Options& options)
983 updateTrackStatuses();
991 removeZeroLengthClips();
999 t->getOutput().updateOutput();
1003 t->refreshCurrentAutoParam();
1006void Edit::initialiseAudioDevices()
1012void Edit::initialiseRacks()
1017void Edit::initialiseMasterPlugins()
1022void Edit::initialiseVideo()
1024 auto* um = &undoManager;
1027 videoOffset.referTo (videoState, IDs::videoOffset, um);
1029 videoSource.referTo (videoState, IDs::videoSource,
nullptr);
1032 loadOldVideoInfo (videoState);
1035void Edit::initialiseControllerMappings()
1037 parameterControlMappings->loadFromEdit();
1045 return automapState;
1050 if (araDocumentHolder ==
nullptr)
1053 return *araDocumentHolder;
1056void Edit::initialiseARA()
1058 auto areAnyClipsUsingMelodyne = [
this]()
1061 for (auto c : at->getClips())
1063 if (acb->isUsingMelodyne())
1069 if (areAnyClipsUsingMelodyne())
1075 #if TRACKTION_ENABLE_AUTOMAP && TRACKTION_ENABLE_CONTROL_SURFACES
1083 addValueTreeProperties (
state,
1086 IDs::projectID, editProjectItemID.load().toString());
1089 p->flushPluginStateToValueTree();
1092 m->flushPluginStateToValueTree();
1096 at->flushStateToValueTree();
1097 at->getOutput().flushStateToValueTree();
1100 changedPluginsList->clear();
1102 if (araDocumentHolder !=
nullptr)
1103 araDocumentHolder->flushStateToValueTree();
1108 changedPluginsList->flushPluginStateIfNeeded (p);
1136 shouldRestartPlayback =
true;
1144 return transportControl->getCurrentPlaybackContext();
1152 return *abletonLink;
1158 wastedMidiMessagesListeners.add (l);
1163 wastedMidiMessagesListeners.remove (l);
1177 if (sm->getEdit() == &ed)
1184void Edit::undoOrRedo (
bool isUndo)
1194 for (
auto sm : getSelectionManagers (*this))
1196 sm->keepSelectedObjectsOnScreen();
1197 sm->refreshPropertyPanel();
1213 auto existingIDs = EditItemID::findAllIDs (
state);
1215 existingIDs.insert (existingIDs.end(), idsToAvoid.
begin(), idsToAvoid.
end());
1217 trackCache.visitItems ([&] (
auto i) { existingIDs.push_back (i->itemID); });
1218 clipCache.visitItems ([&] (
auto i) { existingIDs.push_back (i->itemID); });
1220 std::sort (existingIDs.begin(), existingIDs.end());
1221 nextID = existingIDs.empty() ? 1001 : (existingIDs.back().getRawID() + 1);
1224 usedIDs.insert (existingIDs.begin(), existingIDs.end());
1228 auto newID = EditItemID::fromRawID (nextID++);
1231 jassert (usedIDs.find (newID) == usedIDs.end());
1232 usedIDs.insert (newID);
1245 if (trackList !=
nullptr)
1246 trackList->visitAllRecursive (f);
1251 if (trackList !=
nullptr)
1252 trackList->visitAllTopLevel (f);
1257 if (trackList !=
nullptr)
1258 trackList->visitAllTracks (f, recursive);
1261template <
typename Predicate>
1262static Track* findTrackForPredicate (
const Edit& edit, Predicate&& f)
1264 Track* result =
nullptr;
1289 auto d = ct->getNextTimeOfInterest (t);
1291 if (d < first && d > t)
1307 auto d = ct->getPreviousTimeOfInterest (t);
1319 bool needsSanityCheck =
false;
1324 needsSanityCheck =
true;
1327 if (
auto tr = createTrack (v))
1329 if (needsSanityCheck)
1330 tr->sanityCheckName();
1339template <
typename Type>
1340static Track::Ptr createAndInitialiseTrack (Edit& ed,
const juce::ValueTree& v)
1342 Track::Ptr t =
new Type (ed, v);
1351 if (v.hasType (IDs::TRACK))
return createAndInitialiseTrack<AudioTrack> (*
this, v);
1352 if (v.hasType (IDs::MARKERTRACK))
return createAndInitialiseTrack<MarkerTrack> (*
this, v);
1353 if (v.hasType (IDs::FOLDERTRACK))
return createAndInitialiseTrack<FolderTrack> (*
this, v);
1354 if (v.hasType (IDs::AUTOMATIONTRACK))
return createAndInitialiseTrack<AutomationTrack> (*
this, v);
1355 if (v.hasType (IDs::TEMPOTRACK))
return createAndInitialiseTrack<TempoTrack> (*
this, v);
1356 if (v.hasType (IDs::CHORDTRACK))
return createAndInitialiseTrack<ChordTrack> (*
this, v);
1357 if (v.hasType (IDs::ARRANGERTRACK))
return createAndInitialiseTrack<ArrangerTrack> (*
this, v);
1358 if (v.hasType (IDs::MASTERTRACK))
return createAndInitialiseTrack<MasterTrack> (*
this, v);
1367 return findTrackForPredicate (*
this, [] (
Track& t) {
return t.isMuted (
true); }) !=
nullptr;
1372 return findTrackForPredicate (*
this, [] (
Track& t) {
return t.isSolo (
true); }) !=
nullptr;
1377 return findTrackForPredicate (*
this, [] (
Track& t) {
return t.isSoloIsolate (
true); }) !=
nullptr;
1386 t.updateAudibility (anySolo);
1392 if (ecm.isAttachedToEdit (
this))
1393 ecm.updateMuteSoloLights (
false);
1407 if (! launchQuantisation)
1410 return *launchQuantisation;
1418 if (
auto min = dm.findMidiInputDeviceForID (midiTimecodeSourceDevice))
1421 return dm.getMidiInDevice (0);
1426 if (newDevice ==
nullptr)
1429 midiTimecodeSourceDevice = newDevice->getDeviceID();
1475 if (newDevice ==
nullptr)
1478 midiMachineControlSourceDevice = newDevice->getDeviceID();
1488 for (
int i = dm.getNumMidiOutDevices(); --i >= 0;)
1489 if (
auto mout = dm.getMidiOutDevice (i))
1490 if (mout->getName() == midiMachineControlDestDevice)
1498 if (newDevice ==
nullptr)
1501 midiMachineControlDestDevice = newDevice->getName();
1518 for (
auto d : dm.getMidiInDevices())
1523 && min->getName() == midiTimecodeSourceDevice);
1524 min->setAcceptingMMC (min->getName() == midiMachineControlSourceDevice);
1529 for (
int i = dm.getNumMidiOutDevices(); --i >= 0;)
1531 if (
auto mo = dm.getMidiOutDevice (i))
1533 mo->setSendingMMC (mo->getName() == midiMachineControlDestDevice);
1535 if (mo->isEnabled())
1536 mo->updateMidiTC (
this);
1542void Edit::loadOldTimeSigInfo()
1548 if (! oldInfoState.isValid())
1553 if (
auto oldInfo = oldInfoXml.get())
1555 if (
auto sequenceNode = oldInfo->getFirstChildElement())
1556 if (sequenceNode->hasTagName (
"SECTION"))
1557 oldInfo = sequenceNode;
1560 tempo->set (
BeatPosition(), oldInfo->getDoubleAttribute (
"bpm", 120.0), 0,
false);
1564 timeSig->setStringTimeSig (oldInfo->getStringAttribute (
"timeSignature",
"4/4"));
1565 timeSig->triplets = oldInfo->getBoolAttribute (
"triplets",
false);
1576 const juce::File videoFile (videoState[
"videoFile"].toString());
1578 if (videoFile.existsAsFile())
1580 if (
auto newItem = proj->createNewItem (videoFile, ProjectItem::videoItemType(),
1581 videoFile.getFileNameWithoutExtension(),
1582 {}, ProjectItem::Category::video,
false))
1588 return timecodeFormat;
1593 timecodeFormat = newFormat;
1595 for (
auto sm : getSelectionManagers (*
this))
1597 sm->refreshPropertyPanel();
1601 if (ecm.isAttachedToEdit (*
this))
1602 ecm.editPositionChanged (
this,
getTransport().position);
1625 TRACKTION_ASSERT_MESSAGE_THREAD
1629 for (
auto& c : t->getClips())
1630 c->pitchTempoTrackChanged();
1639 for (
auto& c : t->getClips())
1640 c->sourceMediaChanged();
1642 for (
auto cs : t->getClipSlotList().getClipSlots())
1643 if (
auto c = cs->getClip())
1644 c->sourceMediaChanged();
1648 p->sourceMediaChanged();
1691 b = createValueTree (IDs::NAME,
1693 auxBusses.
addChild (b, -1,
nullptr);
1696 b.setProperty (IDs::name, name,
nullptr);
1708void Edit::timerCallback()
1715 shouldRestartPlayback =
false;
1716 parameterControlMappings->checkForDeletedParams();
1727 if (! totalEditLength)
1732 totalEditLength =
juce::jmax (*totalEditLength, t->getLength());
1735 return *totalEditLength;
1740 auto t = TimePosition::fromSeconds (
getLength().inSeconds());
1741 bool gotOne =
false;
1745 if (
auto first = track->getClips().getFirst())
1748 t =
std::min (t, first->getPosition().getStart());
1757 if (treeWatcher !=
nullptr)
1758 return treeWatcher->getClipsInLinkGroup (linkGroupID);
1770 auto parent =
state;
1772 if (insertPoint.parentTrackID.isValid())
1776 auto preceeding = parent.getChildWithProperty (IDs::id, insertPoint.precedingTrackID);
1790 if (newTrack !=
nullptr)
1796 sm->addToSelection (newTrack);
1806 if (
auto newTrack =
insertNewTrack (insertPoint, IDs::TRACK, sm))
1808 newTrack->pluginList.addDefaultTrackPlugins (
false);
1809 return dynamic_cast<AudioTrack*
> (newTrack.get());
1817 if (
auto newTrack =
insertNewTrack (insertPoint, IDs::FOLDERTRACK, sm))
1819 newTrack->pluginList.addDefaultTrackPlugins (! asSubmix);
1820 return dynamic_cast<FolderTrack*
> (newTrack.get());
1828 if (
auto t =
insertNewTrack (insertPoint, IDs::AUTOMATIONTRACK, sm))
1849 if (destination.parentTrackID.isValid())
1850 if (
auto parentTrack =
findTrackForID (*
this, destination.parentTrackID))
1851 newParent = parentTrack->state;
1853 if (destination.precedingTrackID.isValid())
1854 if (
auto p =
findTrackForID (*
this, destination.precedingTrackID))
1855 preceedingTrack = p->state;
1857 auto oldParent = t->state.getParent();
1858 auto currentIndex = oldParent.indexOf (t->state);
1859 auto precedingIndex = preceedingTrack.
isValid() ? newParent.indexOf (preceedingTrack) : 0;
1861 if (newParent.isAChildOf (t->state) || newParent == t->state)
1864 if (oldParent != newParent)
1866 oldParent.removeChild (currentIndex, &undoManager);
1867 newParent.addChild (t->state, precedingIndex + 1, &undoManager);
1871 auto newIndex = precedingIndex < currentIndex ? precedingIndex + 1 : precedingIndex;
1873 if (currentIndex < 0 || newIndex < 0)
1876 newParent.moveChild (currentIndex, newIndex, &undoManager);
1879 for (
auto sm : getSelectionManagers (*
this))
1880 sm->keepSelectedObjectsOnScreen();
1892 if (destination.parentTrackID.isValid())
1893 if (
auto parentTrack =
findTrackForID (*
this, destination.parentTrackID))
1894 newParent = parentTrack->state;
1896 if (destination.precedingTrackID.isValid())
1897 if (
auto p =
findTrackForID (*
this, destination.precedingTrackID))
1898 preceedingTrack = p->state;
1900 auto oldParent = t->state.getParent();
1901 auto currentIndex = oldParent.indexOf (t->state);
1902 auto precedingIndex = preceedingTrack.
isValid() ? newParent.indexOf (preceedingTrack) : 0;
1904 if (newParent.isAChildOf (t->state) || newParent == t->state)
1907 auto newTrack = t->state.createCopy();
1910 EditItemID::remapIDs (newTrack,
nullptr, t->edit, &remappedIDs);
1912 if (oldParent != newParent)
1914 newParent.addChild (newTrack, precedingIndex + 1, &undoManager);
1918 auto newIndex = precedingIndex + 1;
1920 if (currentIndex < 0 || newIndex < 0)
1923 newParent.addChild (newTrack, newIndex, &undoManager);
1926 for (
auto sm : getSelectionManagers (*
this))
1929 sm->select (track,
true);
1931 sm->keepSelectedObjectsOnScreen();
1940 for (
auto param : track->getAllAutomatableParams())
1942 auto assignments = param->getAssignments();
1944 for (
int i = assignments.size(); --i >= 0;)
1946 auto ass = assignments.getUnchecked (i);
1953 const auto oldID = EditItemID::fromProperty (ass->state, IDs::source);
1954 const auto newID = remappedIDs[oldID];
1956 if (newID.isValid())
1958 ass->state.setProperty (IDs::source, newID,
nullptr);
1970 param->removeModifier (*ass);
1977void Edit::updateTrackStatuses()
1981 sanityCheckTrackNames();
1985 for (
auto sm : getSelectionManagers (*this))
1986 sm->refreshPropertyPanel();
1989void Edit::updateTrackStatusesAsync()
1991 if (treeWatcher !=
nullptr && !
isLoading())
1992 treeWatcher->updateTrackStatusesAsync();
2001 jassert (! (t->isMasterTrack() || t->isMarkerTrack() || t->isTempoTrack() || t->isChordTrack()));
2007 if (
auto modifierList = t->getModifierList())
2008 for (
auto mod : modifierList->getModifiers())
2012 for (
auto sm : getSelectionManagers (*
this))
2017 auto clearEnabledTrackDevices = [
this, &audioTracks] (
AudioTrack* trackBeingDeleted)
2020 for (
auto* idi : editInputDevices->getDevicesForTargetTrack (*trackBeingDeleted))
2021 if (idi->owner.isTrackDevice())
2022 idi->owner.setEnabled (
false);
2024 auto& wid = trackBeingDeleted->getWaveInputDevice();
2025 auto& mid = trackBeingDeleted->getMidiInputDevice();
2027 const bool clearWave = wid.isEnabled();
2028 const bool clearMidi = mid.isEnabled();
2030 if (clearWave || clearMidi)
2034 for (
auto at : audioTracks)
2036 if (clearWave) editInputDevices->clearInputsOfDevice (*at, wid, &
getUndoManager());
2037 if (clearMidi) editInputDevices->clearInputsOfDevice (*at, mid, &
getUndoManager());
2044 if (
auto trackAsAudio =
dynamic_cast<AudioTrack*
> (t))
2046 for (
auto at : audioTracks)
2047 at->setTrackToGhost (trackAsAudio,
false);
2049 clearEnabledTrackDevices (trackAsAudio);
2054 for (
auto at : ft->getAllAudioSubTracks (
true))
2056 for (
auto f : at->pluginList)
2058 ep->hideWindowForShutdown();
2060 clearEnabledTrackDevices (at);
2066 for (
auto f : t->pluginList)
2068 ep->hideWindowForShutdown();
2072 clearEnabledTrackDevices (at);
2077 t->state.getParent().removeChild (t->state, &undoManager);
2081void Edit::sanityCheckTrackNames()
2085 t.sanityCheckName();
2094 auto v = createValueTree (IDs::ARRANGERTRACK,
2095 IDs::name,
TRANS(
"Arranger"));
2105 auto v = createValueTree (IDs::TEMPOTRACK,
2106 IDs::name,
TRANS(
"Global"));
2116 t->setName (
TRANS(
"Marker"));
2120 auto v = createValueTree (IDs::MARKERTRACK,
2121 IDs::name,
TRANS(
"Marker"));
2131 t->setName (
TRANS(
"Chord"));
2135 auto v = createValueTree (IDs::CHORDTRACK,
2136 IDs::name,
TRANS(
"Chord"));
2146 t->setName (
TRANS(
"Master"));
2150 auto v = createValueTree (IDs::MASTERTRACK,
2151 IDs::name,
TRANS(
"Master"));
2170 return *pluginCache;
2179 t->sendMirrorUpdateToAllPlugins (plugin);
2182 for (
auto p : r->getPlugins())
2183 p->updateFromMirroredPluginIfNeeded (plugin);
2185 masterPluginList->sendMirrorUpdateToAllPlugins (plugin);
2190 if (mirroredPluginUpdateTimer !=
nullptr)
2191 mirroredPluginUpdateTimer->pluginChanged (p);
2199 p->playStartedOrStopped();
2204 jassert (! modifierTimers.contains (&mt));
2205 modifierTimers.add (&mt);
2210 modifierTimers.removeFirstMatchingValue (&mt);
2217 for (
auto mt : modifierTimers)
2218 mt->updateStreamTime (editTime, numSamples);
2224 lowLatencyMonitoring = enabled;
2230 if (lowLatencyMonitoring)
2232 if (deviceManager.getCurrentAudioDevice() !=
nullptr)
2239 normalLatencyBufferSizeSeconds = 0.0f;
2250 if (
auto dev = deviceManager.getCurrentAudioDevice())
2252 if (! enabled || (enabled && setup.
bufferSize < dev->getCurrentBufferSizeSamples()))
2256 for (
auto bufferSize : dev->getAvailableBufferSizes())
2268 deviceManager.setAudioDeviceSetup (setup,
false);
2281 if (newPlugins.
contains (p->itemID))
2282 p->setEnabled (
false);
2283 else if (lowLatencyDisabledPlugins.contains (p->itemID))
2284 p->setEnabled (
true);
2287 lowLatencyDisabledPlugins = newPlugins;
2296 p->initialiseFully();
2303 return context->getInputFor (d);
2311 return context->getAllInputs();
2318 return *editInputDevices;
2324 if (isLoadInProgress)
2327 changedPluginsList->pluginChanged (p);
2328 pluginChangeTimer->pluginChanged();
2334 clickMark1Time = newTimes.getStart();
2335 clickMark2Time = newTimes.getEnd();
2340 return TimeRange::between (clickMark1Time, clickMark2Time);
2345 if (clickTrackDevice == DeviceManager::getDefaultAudioOutDeviceName (
false)
2346 || clickTrackDevice == DeviceManager::getDefaultMidiOutDeviceName (
false))
2347 return clickTrackDevice;
2350 return out->getName();
2352 return DeviceManager::getDefaultAudioOutDeviceName (
false);
2359 if (
auto out = dm.findOutputDeviceWithName (clickTrackDevice))
2362 if (clickTrackDevice == DeviceManager::getDefaultMidiOutDeviceName (
false))
2363 return dm.getDefaultMidiOutDeviceID() == dev.getDeviceID();
2365 return dm.getDefaultWaveOutDeviceID() == dev.getDeviceID();
2370 clickTrackDevice = deviceName;
2408void Edit::readFrozenTracksFiles()
2412 auto freezeFiles = TemporaryFileManager::getFrozenTrackFiles (*
this);
2413 bool resetFrozenness = freezeFiles.isEmpty();
2415 for (
auto& freezeFile : freezeFiles)
2417 const auto outId = TemporaryFileManager::getDeviceIDFromFreezeFile (*
this, freezeFile);
2421 resetFrozenness =
true;
2427 bool anyFrozen =
false;
2430 anyFrozen = anyFrozen || t->isFrozen (Track::groupFreeze);
2432 if (resetFrozenness || ! anyFrozen)
2434 AudioFile::deleteFiles (
engine, freezeFiles);
2440 if (
auto at =
dynamic_cast<AudioTrack*
> (t))
2453void Edit::updateFrozenTracks()
2460 const ScopedRenderStatus srs (*
this,
true);
2462 AudioFile::deleteFiles (
engine, TemporaryFileManager::getFrozenTrackFiles (*
this));
2466 for (
int j = dm.getNumOutputDevices(); --j >= 0;)
2468 if (
auto outputDevice =
dynamic_cast<WaveOutputDevice*
> (dm.getOutputDeviceAt (j)))
2471 TimeDuration length;
2476 if (
auto at =
dynamic_cast<AudioTrack*
> (t))
2479 && at->getOutput().outputsToDevice (outputDevice->getName(),
true)
2480 && ! at->isMuted (
true))
2482 frozen.setBit (i,
true);
2483 length =
juce::jmax (length, at->getLengthIncludingInputTracks());
2490 if (frozen.countNumberOfSetBits() > 0 && length > TimeDuration())
2492 length = length + TimeDuration::fromSeconds (5.0);
2494 for (
auto sm : getSelectionManagers (*this))
2499 Renderer::Parameters r (*
this);
2500 r.tracksToDo = frozen;
2501 r.destFile = TemporaryFileManager::getFreezeFileForDevice (*
this, *outputDevice);
2503 r.blockSizeForAudio = dm.getBlockSize();
2504 r.sampleRateForAudio = dm.getSampleRate();
2505 r.time = { {}, length };
2506 r.canRenderInMono =
true;
2507 r.mustRenderInMono =
false;
2508 r.usePlugins =
true;
2509 r.useMasterPlugins =
false;
2510 r.category = ProjectItem::Category::frozen;
2511 r.addAntiDenormalisationNoise = EditPlaybackContext::shouldAddAntiDenormalisationNoise (
engine);
2514 .replace (
"XDVX", outputDevice->getName()) +
"...", r);
2516 if (! r.destFile.exists())
2519 readFrozenTracksFiles();
2532 if (
auto at =
dynamic_cast<AudioTrack*
> (t))
2534 at->setSolo (
false);
2535 at->state.sendPropertyChangeMessage (IDs::height);
2542 SelectionManager::refreshAllPropertyPanels();
2545void Edit::needToUpdateFrozenTracks()
2548 if (frozenTrackCallback !=
nullptr && ! isLoadInProgress)
2549 frozenTrackCallback->triggerAsyncUpdate();
2555 if (t->areAnyClipsUsingFile (af))
2567 for (
auto& c : t->getClips())
2571 auto af = acb->getPlaybackFile();
2573 if (apg.isProxyBeingGenerated (af))
2574 apg.deleteProxy (af);
2589 TRACKTION_LOG_ERROR (
"Failed to create edit temp folder: " + result.
getFullPathName());
2596 tempDirectory = dir;
2606 currentFile = item->getSourceFile();
2608 if (f != currentFile)
2614 auto item = proj->getProjectItemForFile (f);
2616 if (item ==
nullptr)
2618 importDesc, ProjectItem::Category::video,
false);
2620 if (item !=
nullptr)
2630 return item->getSourceFile();
2643 list.
addArray (globalMacros->getMacroParameters());
2645 for (
auto f : *masterPluginList)
2647 list.
addArray (f->getMacroParameters());
2649 for (
int j = 0; j < f->getNumAutomatableParameters(); ++j)
2650 list.
add (f->getAutomatableParameter (j).get());
2655 for (
auto mod : rft->getModifierList().getModifiers())
2656 list.
addArray (mod->getAutomatableParameters());
2658 list.
addArray (rft->getMacroParameters());
2660 for (
auto p : rft->getPlugins())
2662 if (
auto mpl = p->getMacroParameterList())
2663 list.
addArray (mpl->getMacroParameters());
2665 list.
addArray (p->getAutomatableParameters());
2669 if (includeTrackParams)
2676 if (masterTrack != &t)
2679 list.
addArray (m->getMacroParameters());
2681 list.
addArray (t.getAllAutomatableParams());
2693 visit (*masterVolumePlugin->volParam);
2694 visit (*masterVolumePlugin->panParam);
2696 if (
auto mpl = globalMacros->getMacroParameterList())
2697 mpl->visitMacroParameters (visit);
2699 for (
auto p : *masterPluginList)
2701 if (
auto mpl = p->getMacroParameterList())
2702 mpl->visitMacroParameters (visit);
2704 p->visitAllAutomatableParams (visit);
2709 for (
auto mod : rft->getModifierList().getModifiers())
2710 mod->visitAllAutomatableParams (visit);
2712 if (
auto mpl = rft->getMacroParameterList())
2713 mpl->visitMacroParameters (visit);
2715 for (
auto p : rft->getPlugins())
2717 if (
auto mpl = p->getMacroParameterList())
2718 mpl->visitMacroParameters (visit);
2720 p->visitAllAutomatableParams (visit);
2724 if (includeTrackParams)
2731 if (masterTrack != &t)
2734 if (
auto mpl = m->getMacroParameterList())
2735 mpl->visitMacroParameters (visit);
2737 t.visitAllAutomatableParams (visit);
2748 return dynamic_cast<ArrangerTrack*
> (findTrackForPredicate (*
this, [] (
Track& t) {
return t.isArrangerTrack(); }));
2753 return dynamic_cast<MarkerTrack*
> (findTrackForPredicate (*
this, [] (
Track& t) {
return t.isMarkerTrack(); }));
2758 return dynamic_cast<TempoTrack*
> (findTrackForPredicate (*
this, [] (
Track& t) {
return t.isTempoTrack(); }));
2763 return dynamic_cast<ChordTrack*
> (findTrackForPredicate (*
this, [] (
Track& t) {
return t.isChordTrack(); }));
2768 return dynamic_cast<MasterTrack*
> (findTrackForPredicate (*
this, [] (
Track& t) {
return t.isMasterTrack(); }));
2780 metadata.album = meta[IDs::album];
2781 metadata.artist = meta[IDs::artist];
2782 metadata.comment = meta[IDs::comment];
2783 metadata.date = meta.getProperty (IDs::date, metadata.date);
2784 metadata.genre = meta[IDs::genre];
2785 metadata.title = meta[IDs::title];
2786 metadata.trackNumber = meta.getProperty (IDs::trackNumber, 1);
2796 addValueTreeProperties (meta,
2797 IDs::album, metadata.album,
2798 IDs::artist, metadata.artist,
2799 IDs::comment, metadata.comment,
2800 IDs::date, metadata.date,
2801 IDs::genre, metadata.genre,
2802 IDs::title, metadata.title,
2803 IDs::trackNumber, metadata.trackNumber);
2813 bool tryToMatchTempo,
bool* couldMatchTempo,
juce::ValueTree midiPreviewPlugin,
2818 if (edit ==
nullptr)
2821 edit->ensureNumberOfAudioTracks (3);
2822 edit->isPreviewEdit =
true;
2823 edit->getTransport().setPosition (0s);
2825 if (couldMatchTempo !=
nullptr)
2826 *couldMatchTempo =
false;
2829 if (tracks.size() < 3)
2832 for (
auto t : tracks)
2834 auto& clips = t->getClips();
2835 for (
int i = clips.size(); --i >= 0;)
2836 clips[i]->removeFromParent();
2838 jassert (t->getClips().size() == 0);
2841 auto& master = edit->getMasterPluginList();
2843 while (master.size() > 0)
2844 master[0]->removeFromParent();
2846 bool isDrums =
false;
2848 auto midiTrack = tracks[1];
2849 auto drumTrack = tracks[2];
2851 bool resizeClip =
false;
2852 double clipTempo = 120.0;
2863 EditItemID::remapIDs (
state,
nullptr, *edit);
2864 midiTrack->insertClipWithState (
state);
2867 clipTempo =
state[IDs::bpm];
2869 if (clipTempo < 20.0)
2875 if (
auto firstClip = midiTrack->getClips().getFirst())
2877 if (
dynamic_cast<StepClip*
> (firstClip) !=
nullptr)
2879 else if (
auto mc =
dynamic_cast<MidiClip*
> (firstClip))
2880 isDrums = forceMidiToDrums || mc->isRhythm();
2883 auto track = midiTrack;
2889 if (
auto firstClip = midiTrack->getClips().getFirst())
2890 firstClip->moveTo (*track);
2893 if (track->pluginList.size() < 3)
2895 if (isDrums && midiDrumPreviewPlugin.
isValid())
2896 track->pluginList.insertPlugin (midiDrumPreviewPlugin, 0);
2897 if (! isDrums && midiPreviewPlugin.
isValid())
2898 track->pluginList.insertPlugin (midiPreviewPlugin, 0);
2901 double songTempo = 120.0;
2902 auto length = TimeDuration::fromSeconds (1.0);
2905 if (
auto firstClip = track->getClips().getFirst())
2906 length = firstClip->getPosition().getLength();
2909 if (tryToMatchTempo && editToMatch !=
nullptr)
2912 auto firstTempo = edit->tempoSequence.getTempo (0);
2913 firstTempo->setBpm (targetTempo.getBpm());
2915 songTempo = targetTempo.getBpm();
2917 if (couldMatchTempo !=
nullptr)
2918 *couldMatchTempo =
true;
2920 auto& targetPitch = editToMatch->
pitchSequence.getPitchAt (TimePosition::fromSeconds (0.01));
2922 if (
auto firstPitch = edit->pitchSequence.getPitch (0))
2924 firstPitch->setPitch (targetPitch.getPitch());
2925 firstPitch->setScaleID (targetPitch.getScale());
2935 if (
auto firstClip = track->getClips().getFirst())
2937 length = TimeDuration::fromSeconds (length.inSeconds() * clipTempo / songTempo);
2938 firstClip->setStart ({},
false,
true);
2939 firstClip->setLength (length,
true);
2941 edit->getTransport().setLoopRange ({
TimePosition(), length });
2945 if (v.hasType (IDs::PROGRESSION))
2947 auto clipLength = edit->tempoSequence.toTime (BeatPosition::fromBeats (32 * 4));
2948 edit->getTransport().setLoopRange ({
TimePosition(), clipLength });
2950 if (
auto mc = track->insertMIDIClip ({ TimePosition(), clipLength },
nullptr))
2952 if (
auto pg = mc->getPatternGenerator())
2954 pg->mode = PatternGenerator::Mode::chords;
2956 pg->setChordProgression (v.createCopy());
2957 pg->generatePattern();
2961 else if (v.hasType (IDs::BASSPATTERN))
2963 auto clipLength = edit->tempoSequence.toTime (BeatPosition::fromBeats (32 * 4));
2964 edit->getTransport().setLoopRange ({
TimePosition(), clipLength });
2966 if (
auto mc = track->insertMIDIClip ({ TimePosition(), clipLength },
nullptr))
2968 if (
auto pg = mc->getPatternGenerator())
2970 pg->mode = PatternGenerator::Mode::bass;
2972 pg->setChordProgressionFromChordNames ({
"i"});
2973 pg->setBassPattern (v.createCopy());
2974 pg->generatePattern();
2978 else if (v.hasType (IDs::CHORDPATTERN))
2980 auto clipLength = edit->tempoSequence.toTime (BeatPosition::fromBeats (32 * 4));
2981 edit->getTransport().setLoopRange ({
TimePosition(), clipLength });
2983 if (
auto mc = track->insertMIDIClip ({ TimePosition(), clipLength },
nullptr))
2985 if (
auto pg = mc->getPatternGenerator())
2987 pg->mode = PatternGenerator::Mode::chords;
2989 pg->setChordProgressionFromChordNames ({
"i"});
2990 pg->setChordPattern (v.createCopy());
2991 pg->generatePattern();
3000 bool tryToMatchTempo,
bool tryToMatchPitch,
bool* couldMatchTempo,
3003 bool forceMidiToDrums,
3008 if (edit ==
nullptr)
3011 edit->ensureNumberOfAudioTracks (3);
3012 edit->isPreviewEdit =
true;
3013 edit->getTransport().setPosition (0s);
3015 if (couldMatchTempo !=
nullptr)
3016 *couldMatchTempo =
false;
3019 if (tracks.size() < 3)
3022 for (
auto t : tracks)
3024 auto& clips = t->getClips();
3025 for (
int i = clips.size(); --i >= 0;)
3026 clips[i]->removeFromParent();
3028 jassert (t->getClips().size() == 0);
3031 auto& master = edit->getMasterPluginList();
3032 while (master.size() > 0)
3033 master[0]->removeFromParent();
3035 edit->setMasterVolumeSliderPos (decibelsToVolumeFaderPosition (0.0));
3037 auto audioTrack = tracks[0];
3038 auto midiTrack = tracks[1];
3039 auto drumTrack = tracks[2];
3041 bool isMidi = file.hasFileExtension (
juce::String (midiFileWildCard).removeCharacters (
"*"));
3045 if (
auto fin = file.createInputStream())
3054 sequence.addSequence (*mf.
getTrack (i), 0.0, 0.0, 1.0e6);
3056 sequence.updateMatchedPairs();
3058 int ch10Count = 0, allCount = 0;
3060 for (
auto m : sequence)
3062 auto msg = m->message;
3068 if (msg.getChannel() == 10)
3073 bool isDrums = forceMidiToDrums || (
float (ch10Count) / allCount > 90.0f);
3074 auto track = isDrums ? drumTrack : midiTrack;
3076 if (
auto mc = track->insertMIDIClip ({ TimePosition(), TimePosition::fromSeconds (1.0) },
nullptr))
3078 if (track->pluginList.size() < 3)
3080 if (isDrums && midiDrumPreviewPlugin.
isValid())
3081 track->pluginList.insertPlugin (midiDrumPreviewPlugin, 0);
3082 if (! isDrums && midiPreviewPlugin.
isValid())
3083 track->pluginList.insertPlugin (midiPreviewPlugin, 0);
3087 double srcBpm = 120.0;
3092 if (evt->message.isTempoMetaEvent())
3093 srcBpm = 4.0 * 60.0 / (4 * evt->message.getTempoSecondsPerQuarterNote());
3096 edit->tempoSequence.getTempo (0)->setBpm (srcBpm);
3100 auto length = sequence.getEndTime();
3103 if (tryToMatchTempo && editToMatch !=
nullptr)
3106 auto firstTempo = edit->tempoSequence.getTempo (0);
3107 firstTempo->setBpm (targetTempo.getBpm());
3109 if (couldMatchTempo !=
nullptr)
3110 *couldMatchTempo =
true;
3113 auto dstBpm = edit->tempoSequence.getTempo (0)->getBpm();
3115 length *= srcBpm / dstBpm;
3120 const TimeRange timeRange (
TimePosition(), TimeDuration::fromSeconds (length));
3122 edit->getTransport().setLoopRange (timeRange);
3129 auto length = af.getLength();
3133 wc->setUsesProxy (
false);
3134 wc->getSourceFileReference().setToDirectFileReference (file,
false);
3136 if (editToMatch !=
nullptr)
3139 if (tryToMatchTempo || tryToMatchPitch)
3141 wc->setLoopInfo (af.getInfo().loopInfo);
3149 if (tryToMatchTempo)
3151 auto firstTempo = edit->tempoSequence.getTempo (0);
3152 firstTempo->setBpm (targetTempo.getBpm());
3158 if (wi.sampleRate > 0.0)
3160 if (wc->getLoopInfo().getNumBeats() > 0)
3162 length *= wc->getLoopInfo().getBpm (wi) / targetTempo.getBpm();
3164 wc->setAutoTempo (
true);
3166 if (couldMatchTempo !=
nullptr)
3167 *couldMatchTempo =
true;
3172 if (tryToMatchPitch)
3174 auto firstPitch = edit->pitchSequence.getPitch (0);
3175 firstPitch->setPitch (targetPitch->getPitch());
3179 if (wc->getLoopInfo().getRootNote() != -1)
3182 wc->setAutoPitch (
true);
3186 wc->setAutoPitch (
false);
3191 const TimeRange timeRange (0_tp, TimeDuration::fromSeconds (length));
3192 wc->setPosition ({ timeRange, 0_td });
3193 edit->getTransport().setLoopRange (timeRange);
3204 edit->setTempDirectory (clip.edit.getTempDirectory (
false));
3205 edit->tempoSequence.copyFrom (clip.edit.tempoSequence);
3206 edit->pitchSequence.copyFrom (clip.edit.pitchSequence);
3207 edit->setTimecodeFormat (clip.edit.getTimecodeFormat());
3208 edit->isPreviewEdit =
true;
3212 if (
auto c = track->insertClipWithState (clip.state.createCopy()))
3215 jassert (c->getPosition() == clip.getPosition());
3216 jassert (c->getLoopStart() == clip.getLoopStart());
3217 jassert (c->getLoopLength() == clip.getLoopLength());
3218 jassert (c->itemID == clip.itemID);
3228 track->getOutput().setOutputToDefaultDevice (
true);
3250 ProjectItemID::fromProperty (editState, IDs::projectID),
3261EditDeleter::EditDeleter() =
default;
3262EditDeleter::~EditDeleter() { TRACKTION_ASSERT_MESSAGE_THREAD }
3267 editsToDelete.add (ed.
release());
3268 triggerAsyncUpdate();
3271void EditDeleter::handleAsyncUpdate()
3274 editsToDelete.clear();
3278ActiveEdits::ActiveEdits() =
default;
void addArray(const Type *elementsToAdd, int numElementsToAdd)
int size() const noexcept
void add(const ElementType &newElement)
bool contains(ParameterType elementToLookFor) const
ElementType getLast() const noexcept
AudioDeviceSetup getAudioDeviceSetup() const
bool isUsingDefault() const
void referTo(ValueTree &tree, const Identifier &property, UndoManager *um)
Type get() const noexcept
void dispatchPendingMessages()
const String & getFullPathName() const noexcept
File getChildFile(StringRef relativeOrAbsolutePath) const
static bool isAbsolutePath(StringRef path)
String getFileNameWithoutExtension() const
Result createDirectory() const
bool isValid() const noexcept
const String & toString() const noexcept
bool fromBase64Encoding(StringRef encodedString)
void * getData() noexcept
size_t getSize() const noexcept
void convertTimestampTicksToSeconds()
int getNumTracks() const noexcept
bool readFrom(InputStream &sourceStream, bool createMatchingNoteOffs=true, int *midiFileType=nullptr)
void findAllTempoEvents(MidiMessageSequence &tempoChangeEvents) const
const MidiMessageSequence * getTrack(int index) const noexcept
MidiEventHolder * getEventPointer(int index) const noexcept
static String toHexString(IntegerType number)
String substring(int startIndex, int endIndex) const
static Time JUCE_CALLTYPE getCurrentTime() noexcept
int64 toMilliseconds() const noexcept
void stopTimer() noexcept
bool isTimerRunning() const noexcept
void startTimer(int intervalInMilliseconds) noexcept
void setMaxNumberOfStoredUnits(int maxNumberOfUnitsToKeep, int minimumTransactionsToKeep)
bool hasType(const Identifier &typeName) const noexcept
void removeChild(const ValueTree &child, UndoManager *undoManager)
bool isValid() const noexcept
ValueTree & setProperty(const Identifier &name, const var &newValue, UndoManager *undoManager)
int indexOf(const ValueTree &child) const noexcept
void addChild(const ValueTree &child, int index, UndoManager *undoManager)
const var & getProperty(const Identifier &name) const noexcept
ValueTree getChildWithName(const Identifier &type) const
ValueTree getOrCreateChildWithName(const Identifier &type, UndoManager *undoManager)
ValueTree getChildWithProperty(const Identifier &propertyName, const var &propertyValue) const
bool hasProperty(const Identifier &name) const noexcept
Manages an Ableton Link session connecting an Edit with a number of networked peers,...
A track similar to the MarkerTrack but can be used to move sections of an Edit around.
Base class for Clips that produce some kind of audio e.g.
static bool isClipState(const juce::ValueTree &)
Checks whether a ValueTree is some kind of clip state.
The Tracktion Edit class!
juce::ValueTree inputDeviceState
The ValueTree of the input device states.
ChordTrack * getChordTrack() const
Returns the global ChordTrack.
static std::unique_ptr< Edit > createEditForPreviewingClip(Clip &)
Creates an Edit for previewing a Clip.
InputDeviceInstance * getCurrentInstanceForInputDevice(InputDevice *) const
Returns an InputDeviceInstance for a global InputDevice.
juce::CachedValue< float > clickTrackGain
The gain of the click track.
static std::unique_ptr< Edit > createEdit(Options)
Creates an Edit for the given options.
void restartPlayback()
Use this to tell the play engine to rebuild the audio graph if the toplogy has changed.
juce::ValueTree state
The ValueTree of the Edit state.
juce::ValueTree getAutomapState()
Returns the ValueTree used as the Auotmap state.
void ensureMasterTrack()
Creates a MasterTrack if there isn't currently one.
juce::String getClickTrackDevice() const
Returns the name of the device being used as the click track output.
void setTimecodeOffset(TimeDuration newOffset)
Sets the offset to apply to MIDI timecode.
EditPlaybackContext * getCurrentPlaybackContext() const
Returns the active EditPlaybackContext which is what is attached to the DeviceManager.
ARADocumentHolder & getARADocument()
Returns the ARA document handler.
ArrangerTrack * getArrangerTrack() const
Returns the global ArrangerTrack.
void sendMirrorUpdateToAllPlugins(Plugin &) const
Syncronously updates all Plugins[s] mirroring this one.
juce::CachedValue< TimeDuration > videoOffset
The duration in seconds of the video offset.
TimeRange getClickTrackRange() const noexcept
Returns the range the click track will be audible within.
PitchSequence pitchSequence
The global PitchSequence of this Edit.
std::function< juce::File()> editFileRetriever
This callback can be set to return the file for this Edit.
static std::unique_ptr< Edit > createEditForPreviewingFile(Engine &, const juce::File &, const Edit *editToMatch, bool tryToMatchTempo, bool tryToMatchPitch, bool *couldMatchTempo, juce::ValueTree midiPreviewPlugin, juce::ValueTree midiDrumPreviewPlugin={}, bool forceMidiToDrums=false, std::unique_ptr< Edit > editToUpdate={})
Creates an Edit for previewing a file.
void enableTimecodeSync(bool)
Toggles syncing to MIDI timecode.
juce::CachedValue< TimeDuration > masterFadeIn
The duration in seconds of the fade in.
void setLowLatencyDisabledPlugins(const juce::Array< EditItemID > &plugins)
First enables all currently disabled latency plugins and then disables the new set.
Track::Ptr insertTrack(TrackInsertPoint, juce::ValueTree, SelectionManager *)
Inserts a new Track with the given state in the Edit.
TransportControl & getTransport() const noexcept
Returns the TransportControl which is used to stop/stop/position playback and recording.
SceneList & getSceneList()
Returns a list of Scenes in the Edit.
void warnOfWastedMidiMessages(InputDevice *, Track *)
Triggers a callback to any registered WastedMidiMessagesListener[s].
EditInputDevices & getEditInputDevices() noexcept
Returns the EditInputDevices for the Edit.
juce::CachedValue< juce::String > lastSignificantChange
The last time a change was made to the Edit.
void sendStartStopMessageToPlugins()
Calls Plugin::playStartedOrStopped to handle automation reacording.
void sendSourceFileUpdate()
Sends a 'sourceMediaChanged' call to all the clips.
CountIn getCountInMode() const
Returns the duration of the count in.
std::atomic< float > progress
Progress will be updated as the Edit loads.
void setEditMetadata(Metadata)
Sets the Metadata for the Edit.
juce::File getVideoFile() const
Returns the currently set video file.
EditRole
Enum used to determine what an Edit is being used for.
@ forEditing
Creates an Edit for normal use.
void visitAllAutomatableParams(bool includeTrackParams, const std::function< void(AutomatableParameter &)> &) const
Returns all automatable parameters in an Edit.
void ensureTempoTrack()
Creates a TempoTrack if there isn't currently one.
void setMidiTimecodeIgnoringHours(bool shouldIgnore)
Sets whether hours are ignored when syncing to MIDI timecode.
void deleteTrack(Track *)
Deletes a Track.
LaunchQuantisation & getLaunchQuantisation()
Returns the global launch quantisation.
Edit(Options)
Creates an Edit from a set of Options.
Metadata getEditMetadata()
Returns the current Metadata for the Edit.
void setTimecodeFormat(TimecodeDisplayFormat)
Sets the TimecodeDisplayFormat to use.
juce::CachedValue< bool > clickTrackRecordingOnly
Whether the click track should be audible only when recording.
void setClickTrackOutput(const juce::String &deviceName)
Sets the device to use as the click track output.
TimecodeDisplayFormat getTimecodeFormat() const
Returns the current TimecodeDisplayFormat.
void removeWastedMidiMessagesListener(WastedMidiMessagesListener *)
Removes a previously added WastedMidiMessagesListener.
void setClickTrackRange(TimeRange) noexcept
Sets a range for the click track to be audible within.
void sendTempoOrPitchSequenceChangedUpdates()
Sends a message to all the clips to let them know the tempo or pitch sequence has changed.
TimeDuration getLength() const
Returns the end time of last clip.
bool areAnyClipsUsingFile(const AudioFile &)
Returns true if any clips are using this file.
CountIn
An enum to determine the duration of the count in.
@ twoBeat
Two beats count in.
@ oneBeat
One beat count in.
@ none
No count in, play starts immidiately.
@ oneBar
One bar count in.
@ twoBar
Two bars count in.
void ensureMarkerTrack()
Creates a MarkerTrack if there isn't currently one.
void setCurrentMidiMachineControlSource(std::shared_ptr< MidiInputDevice >)
Sets the MidiInputDevice to be used as an MMC source.
void moveTrack(Track::Ptr, TrackInsertPoint)
Moves a track to a new position.
bool areAnyTracksSolo() const
Returns true if any tracks are soloed.
juce::CachedValue< bool > playInStopEnabled
Whether the audio engine should run when playback is stopped.
juce::Time getTimeOfLastChange() const
Returns the time the last change occurred.
juce::Array< AutomatableParameter * > getAllAutomatableParams(bool includeTrackParams) const
Returns all automatable parameters in an Edit.
juce::Array< Clip * > findClipsInLinkGroup(juce::String linkGroupID) const
Returns and Clip[s] with the given linkGroupID.
bool shouldPlay() const noexcept
Returns true if this Edit should be played back (or false if it was just opened for inspection).
void removeModifierTimer(ModifierTimer &)
Removes a ModifierTimer previously added.
void setLowLatencyMonitoring(bool enabled, const juce::Array< EditItemID > &plugins)
Toggles low latency monitoring for a set of plugins.
PluginCache & getPluginCache() noexcept
Returns the PluginCache which manages all active Plugin[s] for this Edit.
void ensureNumberOfAudioTracks(int minimumNumTracks)
Creates new tracks to ensure the minimum number.
AbletonLink & getAbletonLink() const noexcept
Returns the AbletonLink object.
void setMasterVolumeSliderPos(float)
Sets the master volume level.
juce::String getName()
Returns the name of the Edit if a ProjectItem can be found for it.
juce::ReferenceCountedObjectPtr< FolderTrack > insertNewFolderTrack(TrackInsertPoint, SelectionManager *, bool asSubmix)
Inserts a new FolderTrack in the Edit, optionally as a submix.
void redo()
Redoes the changes undone by the last undo.
juce::CachedValue< ProjectItemID > videoSource
The ProjectItemID of the video source.
juce::CachedValue< bool > videoMuted
Whether the video source is muted.
void visitAllTopLevelTracks(std::function< bool(Track &)>) const
Visits all top-level tracks (i.e.
std::atomic< bool > shouldExit
Can be set to true to cancel loading the Edit.
juce::ReferenceCountedObjectPtr< AutomationTrack > insertNewAutomationTrack(TrackInsertPoint, SelectionManager *)
Inserts a new AutomationTrack in the Edit.
bool areAnyTracksSoloIsolate() const
Returns true if any tracks are solo isolated.
juce::CachedValue< bool > clickTrackEmphasiseBars
Whether the click track should emphasise bars.
void updateMuteSoloStatuses()
Updates all the tracks and external controller mute/solo statuses.
std::shared_ptr< MidiInputDevice > getCurrentMidiMachineControlSource() const
Returns the MidiInputDevice being used as an MMC source.
void cancelAllProxyGeneratorJobs() const
Stops all proxy generator jobs clips may be performing.
juce::CachedValue< TimeDuration > masterFadeOut
The duration in seconds of the fade out.
void setCurrentMidiMachineControlDest(MidiOutputDevice *)
Sets the MidiInputDevice to be used as an MMC destination.
MasterTrack * getMasterTrack() const
Returns the global MasterTrack.
MarkerTrack * getMarkerTrack() const
Returns the global MarkerTrack.
void dispatchPendingUpdatesSynchronously()
If there's a change to send out to the listeners, do it now rather than waiting for the next timer me...
void setProjectItemID(ProjectItemID)
Sets the ProjectItemID of the Edit, this is also stored in the state.
static std::unique_ptr< Edit > createSingleTrackEdit(Engine &, EditRole role=EditRole::forEditing)
Creates an Edit with a single AudioTrack.
juce::CachedValue< bool > midiTimecodeIgnoringHours
Whether the MIDI timecode source ignores hours.
void flushState()
Saves the plugin, automap and ARA states to the state ValueTree.
std::shared_ptr< MidiInputDevice > getCurrentMidiTimecodeSource() const
Returns the MidiInputDevice being used as the MIDI timecode source.
juce::CachedValue< bool > clickTrackEnabled
Whether the click track is enabled.
void setCountInMode(CountIn)
Sets the duration of the count in.
void resetChangedStatus()
Resets the changed status so hasChangedSinceSaved returns false.
int numUndoLevelsToStore
The number of undo levels to use.
void setMasterPanPos(float)
Returns the master pan position.
void pluginChanged(Plugin &) noexcept
Plugins should call this when one of their parameters or state changes to mark the edit as unsaved.
void addWastedMidiMessagesListener(WastedMidiMessagesListener *)
Add a WastedMidiMessagesListener to be notified of wasted MIDI messages.
juce::Array< InputDeviceInstance * > getAllInputDevices() const
Returns all the active InputDeviceInstance[s] in the Edit.
bool isRendering() const noexcept
Returns true if the Edit is currently being rendered.
std::atomic< bool > completed
Set to true once the Edit has loaded.
TempoSequence tempoSequence
The global TempoSequence of this Edit.
juce::ReferenceCountedObjectPtr< AudioTrack > insertNewAudioTrack(TrackInsertPoint, SelectionManager *)
Inserts a new AudioTrack in the Edit.
void setVideoFile(const juce::File &, juce::String importDesc)
Sets a video file to display.
bool isLoading() const
Returns true if the Edit's not yet fully loaded.
juce::CachedValue< TimeDuration > timecodeOffset
The duration in seconds of the timecode offset.
void updateMirroredPlugin(Plugin &)
Adds this plugin to a list so mirrored Plugin[s] are updated asyncronously.
void setCurrentMidiTimecodeSource(std::shared_ptr< MidiInputDevice >)
Sets the MidiInputDevice being to be used as the MIDI timecode source.
void setClickTrackVolume(float gain)
Sets the volume of the click track.
std::function< juce::File(const juce::String &)> filePathResolver
An optional filePathResolver to use.
void ensureArrangerTrack()
Creates an ArrangerTrack if there isn't currently one.
TempoTrack * getTempoTrack() const
Returns the global TempoTrack.
void ensureChordTrack()
Creates a ChordTrack if there isn't currently one.
juce::CachedValue< AudioFadeCurve::Type > masterFadeInType
The curve type of the fade in.
void toggleTimecodeMode()
Toggles the TimecodeDisplayFormat through the available TimecodeType[s].
void invalidateStoredLength() noexcept
Invalidates the stored length so the next call to getLength will update form the Edit contents.
AutomatableParameter::Ptr getMasterSliderPosParameter() const
Returns the master volume AutomatableParameter.
static std::unique_ptr< Edit > createEditForExamining(Engine &, juce::ValueTree, EditRole role=EditRole::forExamining)
Creates an Edit that loads a state, using the role Edit::forExamining.
TimePosition getPreviousTimeOfInterest(TimePosition beforeThisTime)
Finds the previous marker or start/end of a clip after a certain time.
void copyTrack(Track::Ptr, TrackInsertPoint)
Copies a track to a new position.
int getNumCountInBeats() const
Returns the number of beats of the count in.
void visitAllTracksRecursive(std::function< bool(Track &)>) const
Visits all tracks in the Edit with the given function.
void flushPluginStateIfNeeded(Plugin &)
Saves the specified plugin state to the state ValueTree.
void updateMidiTimecodeDevices()
Updates the MIDI timecode/MMC devices.
juce::CachedValue< bool > recordingPunchInOut
Whether recoridng only happens within the in/out markers.
~Edit() override
Destructor.
AutomatableParameter::Ptr getMasterPanParameter() const
Returns the master pan AutomatableParameter.
TimePosition getFirstClipTime() const
Returns the time of first clip.
EditItemCache< Track > trackCache
Quick way to find and iterate all Track[s] in the Edit.
juce::UndoManager & getUndoManager() noexcept
Returns the juce::UndoManager used for this Edit.
bool hasChangedSinceSaved() const
Returns true if the Edit has changed since it was last saved.
void setTempDirectory(const juce::File &)
Sets the temp directory for the Edit to use.
static std::unique_ptr< Edit > createEditForPreviewingPreset(Engine &engine, juce::ValueTree, const Edit *editToMatch, bool tryToMatchTempo, bool *couldMatchTempo, juce::ValueTree midiPreviewPlugin, juce::ValueTree midiDrumPreviewPlugin={}, bool forceMidiToDrums=false, std::unique_ptr< Edit > editToUpdate={})
Creates an Edit for previewing a preset.
MidiOutputDevice * getCurrentMidiMachineControlDest() const
Returns the MidiInputDevice being used as an MMC destination.
juce::CachedValue< bool > midiTimecodeSourceDeviceEnabled
Whether a MIDI timecode source is enabled.
EditItemID createNewItemID() const
Returns a new EditItemID to use for a new EditItem.
void undo()
Undoes the most recent changes made.
ProjectItemID getProjectItemID() const noexcept
Returns the ProjectItemID of the Edit.
static int getDefaultNumUndoLevels() noexcept
Returns the default number of undo levels that should be used.
bool areAnyTracksMuted() const
Returns true if any tracks are muted.
std::function< juce::File(const juce::String &)> filePathResolver
This callback can be set to resolve file paths.
TimePosition getNextTimeOfInterest(TimePosition afterThisTime)
Finds the next marker or start/end of a clip after a certain time.
void addModifierTimer(ModifierTimer &)
Adds a ModifierTimer to be updated each block.
juce::File getTempDirectory(bool createIfNonExistent) const
Returns the temp directory the Edit it using.
void visitAllTracks(std::function< bool(Track &)>, bool recursive) const
Visits all tracks in the Edit with the given function.
EditItemCache< Clip > clipCache
Quick way to find and iterate all Clip[s] in the Edit.
void initialiseAllPlugins()
Initialises all the plugins.
bool isClickTrackDevice(OutputDevice &) const
Returns true if the given OutputDevice is being used as the click track output.
juce::CachedValue< AudioFadeCurve::Type > masterFadeOutType
The curve type of the fade out.
RackTypeList & getRackList() const noexcept
Returns the RackTypeList which contains all the RackTypes for the Edit.
juce::String getAuxBusName(int bus) const
Returns the name of an aux bus.
void setAuxBusName(int bus, const juce::String &name)
Sets the name of an aux bus.
Track::Ptr insertNewTrack(TrackInsertPoint, const juce::Identifier &xmlType, SelectionManager *)
Inserts a new Track with the given type in the Edit.
void updateModifierTimers(TimePosition editTime, int numSamples) const
Updates all the ModifierTimers with a given edit time and number of samples.
Engine & engine
A reference to the Engine.
std::function< juce::File()> editFileRetriever
An optional editFileRetriever to use.
void markAsChanged()
Marks the edit as being significantly changed and should therefore be saved.
Determines how the Edit will be created.
virtual EditLimits getEditLimits()
Should return the maximum number of elements that can be added to an Edit.
virtual void newClipAdded(Clip &, bool fromRecording)
Returns the defaults to be applied to new clips.
virtual bool shouldBypassedPluginsBeRemovedFromPlaybackGraph()
Should return if plugins which have been bypassed should be included in the playback graph.
The Engine is the central class for all tracktion sessions.
PropertyStorage & getPropertyStorage() const
Returns the PropertyStorage user settings customisable XML file.
AudioFileFormatManager & getAudioFileFormatManager() const
Returns the AudioFileFormatManager that maintains a list of available audio file formats.
UIBehaviour & getUIBehaviour() const
Returns the UIBehaviour class.
ExternalControllerManager & getExternalControllerManager() const
Returns the ExternalControllerManager instance.
DeviceManager & getDeviceManager() const
Returns the DeviceManager instance for handling audio / MIDI devices.
AudioFileManager & getAudioFileManager() const
Returns the AudioFileManager instance.
EngineBehaviour & getEngineBehaviour() const
Returns the EngineBehaviour instance.
ProjectManager & getProjectManager() const
Returns the ProjectManager instance.
ActiveEdits & getActiveEdits() const noexcept
Returns the ActiveEdits instance.
TemporaryFileManager & getTemporaryFileManager() const
Returns the TemporaryFileManager allowing to handle the default app and user temporary folders.
Represents a launch quantisation.
Base class for elements which can contain macro parameters.
A track to represent the master plugins.
@ none
No automation, add the sequence as plain MIDI with the channel of the clip.
Base class for audio or midi output devices, to which a track's output can be sent.
An ID representing one of the items in a Project.
ProjectItem::Ptr getProjectItem(ProjectItemID)
tries to find the project that contains an id, and open it as a ProjectItem.
static ProjectItem::Ptr renderToProjectItem(const juce::String &taskDescription, const Parameters ¶ms)
Renders an Edit to a file and creates a new ProjectItem for it.
Represents the Scenes in an Edit.
void cancelAnyPendingUpdates()
If changed() has been called, this will cancel any pending async change notificaions.
Manages a list of items that are currently selected.
void keepSelectedObjectsOnScreen()
Scrolls whatever is necessary to keep the selected stuff visible.
TimeSigSetting * getTimeSig(int index) const
Returns the TimeSigSetting at a given index.
TempoSetting * getTempo(int index) const
Returns the TempoSetting at the given index.
TempoSetting & getTempoAt(TimePosition) const
Returns the TempoSetting at the given position.
void setState(const juce::ValueTree &, bool remapEdit)
Sets the state this TempoSequence should refer to.
A track to represent the "global" items such as tempo, key changes etc.
@ defaultMode
Default mode.
@ disabled
No algorithm enabled.
Base class for tracks which contain clips and plugins and can be added to Edit[s].
@ groupFreeze
Freezes multiple tracks together in to a single file.
void ensureContextAllocated(bool alwaysReallocate=false)
Ensures an active EditPlaybackContext has been created so this Edit can be played back.
void freePlaybackContext()
Detaches the current EditPlaybackContext, removing it from the DeviceManager.
void play(bool justSendMMCIfEnabled)
Starts playback of an Edit.
static void stopAllTransports(Engine &, bool discardRecordings, bool clearDevices)
Stops all TransportControl[s] in the Engine playing.
void editHasChanged()
Triggers a playback graph rebuild.
void stop(bool discardRecordings, bool clearDevices, bool canSendMMCStop=true)
Stops recording, creating clips of newyly recorded files/MIDI data.
bool isPlaying() const
Returns true if the transport is playing.
void stopIfRecording()
Stops playback only if recording is currently in progress.
virtual void newTrackCreated(Track &)
Called when a new track is created from some kind of user action i.e.
virtual void showWarningMessage(const juce::String &message)
Should display a temporary warning message.
An audio clip that uses an audio file as its source.
#define TRANS(stringLiteral)
#define JUCE_DECLARE_WEAK_REFERENCEABLE(Class)
constexpr Type jmax(Type a, Type b)
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
int roundToInt(const FloatType value) noexcept
AudioTrack * getFirstAudioTrack(const Edit &edit)
Returns the first audio track in an Edit.
juce::Array< TrackType * > getTracksOfType(const Edit &, bool recursive)
Returns the tracks of a given type in an Edit.
Track * findTrackForState(const Edit &edit, const juce::ValueTree &v)
Returns the Track with a given state if contained in the Edit.
juce::Array< Track * > getTopLevelTracks(const Edit &edit)
Returns all of the non-foldered tracks in an Edit.
juce::Array< MacroParameterList * > getAllMacroParameterLists(const Edit &edit)
Returns all the MacroParameterLists in an Edit.
juce::Array< Track * > getAllTracks(const Edit &edit)
Returns all the tracks in an Edit.
bool containsTrack(const Edit &edit, const Track &track)
Returns true if the Edit contains this Track.
juce::Array< AudioTrack * > getAudioTracks(const Edit &edit)
Returns all the AudioTracks in an Edit.
ProjectItem::Ptr getProjectItemForEdit(const Edit &e)
Tries to find the project item that refers to this edit (but may return nullptr!)
juce::Array< ClipTrack * > getClipTracks(const Edit &edit)
Returns all the ClipTracks in an Edit.
juce::ReferenceCountedArray< Modifier > getAllModifiers(const Edit &edit)
Returns all the Modifiers in an Edit.
Modifier::Ptr findModifierForID(ModifierList &ml, EditItemID modifierID)
Returns a Modifier if it can be found in the list.
Track * getTrackContainingModifier(const Edit &edit, const Modifier::Ptr &m)
Returns the Track containing a Modifier.
Track * findTrackForID(const Edit &edit, EditItemID id)
Returns the Track with a given ID if contained in the Edit.
Project::Ptr getProjectForEdit(const Edit &e)
Tries to find the project that contains this edit (but may return nullptr!)
juce::ValueTree createEmptyEdit(Engine &e)
Legacy, will be deprecated soon.
juce::ValueTree updateLegacyEdit(const juce::ValueTree &)
Converts old edit formats to the latest structure.
bool isRecording(EditPlaybackContext &epc)
Returns true if any inputs are currently recording.
int maxNumTracks
The maximum number of Track[s] an Edit can contain.
Plugin::Array getAllPlugins(const Edit &edit, bool includeMasterVolume)
Returns all the plugins in a given Edit.
juce::Array< ClipEffect * > getAllClipEffects(Edit &edit)
Returns all clip effects.
Represents a position in beats.
Represents a duration in real-life time.
Represents a position in real-life time.
ID for objects of type EditElement - e.g.
void flushPluginStateIfNeeded(Plugin &p)
Flushes the plugin state to the Edit if it has changed.
void pluginChanged(Plugin &p)
Call to indicate a plugin's state has changed and needs saving.
void flushAll()
Flushes all changed plugins to the Edit.
ScopedRenderStatus(Edit &, bool shouldReallocateOnDestruction)
Constructs a ScopedRenderStatus, removing an Edit from the device manager.
~ScopedRenderStatus()
Destructor.
Disables the creation of a new transaction.
~UndoTransactionInhibitor()
Destructor.
UndoTransactionInhibitor(Edit &)
Creates an UndoTransactionInhibitor for an Edit.
Interface for classes that need to know about unused MIDI messages.
virtual void warnOfWastedMidiMessages(InputDevice *, Track *)=0
Callback to be notified when a MIDI message isn't used by a track because it doesn't have a plugin wh...
An Assignment between a MacroParameter and an AutomatableParameter.
Base class for objects which need to know about the global Edit time every block.
Defines the place to insert Track[s].
static void sortTracksByType(juce::ValueTree &editState, juce::UndoManager *)
Sorts a list of tracks by their type, placing global tracks at the top.
static bool isFixedTrack(const juce::ValueTree &) noexcept
Returns true if the track is fixed.
#define CRASH_TRACER
This macro adds the current location to a stack which gets logged if a crash happens.