11namespace tracktion {
inline namespace engine
20 void handleAsyncUpdate()
override
22 for (
int i = 1; i <= 16; ++i)
24 MidiMessageArray::notMPE);
26 owner.trackMuter =
nullptr;
38 : owner (at), state (owner.state), triggerFreeze (
false), updateFreeze (
false)
51 markAndUpdate (triggerFreeze);
58 bool triggerFreeze, updateFreeze;
62 bool compareAndReset (
bool& flag)
71 void valueTreeChanged()
override
73 markAndUpdate (updateFreeze);
76 void handleAsyncUpdate()
override
78 if (compareAndReset (triggerFreeze))
84 if (compareAndReset (updateFreeze))
99 soloed.referTo (state, IDs::solo,
nullptr);
100 soloIsolated.referTo (state, IDs::soloIsolate,
nullptr);
101 muted.referTo (state, IDs::mute,
nullptr);
102 frozen.referTo (state, IDs::frozen,
nullptr);
103 frozenIndividually.referTo (state, IDs::frozenIndividually,
nullptr);
104 ghostTracks.referTo (state, IDs::ghostTracks,
nullptr);
105 maxInputs.referTo (state, IDs::maxInputs,
nullptr, 1);
106 compGroup.referTo (state, IDs::compGroup, &edit.getUndoManager(), -1);
107 midiNoteMap.referTo (state, IDs::midiNoteMap,
nullptr);
110 updateMidiNoteMapCache();
113 desc.name =
itemID.toString();
117 callBlocking ([
this, desc]
120 desc, InputDevice::trackWaveDevice);
123 InputDevice::trackMidiDevice,
124 "TrkMIDI_" +
itemID.toString(),
127 auto& eid = edit.getEditInputDevices();
128 waveInputDevice->setEnabled (eid.isInputDeviceAssigned (*waveInputDevice));
129 midiInputDevice->setEnabled (eid.isInputDeviceAssigned (*midiInputDevice));
135 if (getMidiVerticalOffset() < 0 || getMidiVerticalOffset() > 0.99
137 setVerticalScaleToDefault();
139 asyncCaller.addFunction (updateAutoCrossfadesFlag,
144 if (acb->getAutoCrossfade())
145 acb->updateAutoCrossfadesAsync (false);
149AudioTrack::~AudioTrack()
151 const bool clearWave = waveInputDevice !=
nullptr && waveInputDevice->isEnabled();
152 const bool clearMidi = midiInputDevice !=
nullptr && midiInputDevice->isEnabled();
154 if (clearWave || clearMidi)
165 notifyListenersOfDeletion();
177 if (frozenIndividually && ! getFreezeFile().existsAsFile())
180 output->initialise();
185 auto n = ClipTrack::getName();
187 if ((n.startsWithIgnoreCase (
"Track ")
188 || n.startsWithIgnoreCase (
TRANS(
"Track") +
" "))
189 && n.substring (6).trim().containsOnly (
"0123456789"))
198 auto devName = getName();
200 if (waveInputDevice !=
nullptr) waveInputDevice->setAlias (devName);
201 if (midiInputDevice !=
nullptr) midiInputDevice->setAlias (devName);
206 if (
auto n = ClipTrack::getName(); ! n.isEmpty())
212int AudioTrack::getAudioTrackNumber() const noexcept
221 if (t.isAudioTrack())
240 desc <<
" (" << n <<
")";
252EqualiserPlugin* AudioTrack::getEqualiserPlugin() {
return pluginList.getPluginsOfType<EqualiserPlugin>().getLast(); }
254AuxSendPlugin* AudioTrack::getAuxSendPlugin (
int bus, AuxPosition ap)
const
256 if (ap == AuxPosition::byBus)
259 if (auto f = dynamic_cast<AuxSendPlugin*> (p))
260 if (bus < 0 || bus == f->getBusNumber())
263 else if (ap == AuxPosition::byPosition)
270 if (
auto f =
dynamic_cast<AuxSendPlugin*
> (p))
288 if (midiNoteMapCache.
size() > 0)
290 auto itr = midiNoteMapCache.
find (note);
292 if (itr != midiNoteMapCache.
end())
301 if (af->hasNameForMidiNoteNumber (note, midiChannel, s))
304 if (
auto dest = output->getDestinationTrack())
305 return dest->getNameForMidiNoteNumber (note, midiChannel, preferSharp);
309 if (af->hasNameForMidiNoteNumber (note, midiChannel, s))
312 if (
auto mo =
dynamic_cast<MidiOutputDevice*
> (getOutput().getOutputDevice (
true)))
313 return mo->getNameForMidiNoteNumber (note, midiChannel, preferSharp);
320void AudioTrack::updateMidiNoteMapCache()
322 midiNoteMapCache.
clear();
324 auto m = midiNoteMap.
get();
329 if (l.startsWith (
"//"))
333 for (
int i = 0; i < l.length(); i++)
344 midiNoteMapCache[l.substring (0, digits).getIntValue()] = l.substring (digits).trim();
348bool AudioTrack::areMidiPatchesZeroBased()
const
351 if (
auto dest = output->getDestinationTrack())
352 return dest->areMidiPatchesZeroBased();
355 if (
auto midiDevice =
dynamic_cast<MidiOutputDevice*
> (output->getOutputDevice (
false)))
356 return midiDevice->areMidiPatchesZeroBased();
366 if (p->hasNameForMidiBank (bank, s))
369 if (
auto dest = output->getDestinationTrack())
370 return dest->getNameForBank (bank);
373 for (
auto p : edit.getMasterPluginList())
374 if (p->hasNameForMidiBank (bank, s))
377 if (
auto midiDevice =
dynamic_cast<MidiOutputDevice*
> (output->getOutputDevice (
false)))
378 return midiDevice->getBankName (bank);
383int AudioTrack::getIdForBank (
int bank)
const
385 if (
auto dest = output->getDestinationTrack())
386 return dest->getIdForBank (bank);
388 if (
auto midiDevice =
dynamic_cast<MidiOutputDevice*
> (output->getOutputDevice (
false)))
389 return midiDevice->getBankID (bank);
399 if (p->hasNameForMidiProgram (programNumber, bank, s))
402 if (
const AudioTrack*
const dest = output->getDestinationTrack())
403 return dest->getNameForProgramNumber (programNumber, bank);
407 if (p->hasNameForMidiProgram (programNumber, bank, s))
410 if (
auto midiDevice =
dynamic_cast<MidiOutputDevice*
> (output->getOutputDevice (
false)))
411 return midiDevice->getProgramName (programNumber, bank);
426 if (includeMutingByDestination)
429 return p->isMuted (
true);
431 if (
auto dest = output->getDestinationTrack())
432 return dest->isMuted (
true);
443 if (includeIndirectSolo)
447 if (p->isSolo (
false))
451 if (
auto dest = output->getDestinationTrack())
452 return dest->isSolo (
true);
463 if (includeIndirectSolo)
467 if (p->isSoloIsolate (
false))
471 if (
auto dest = output->getDestinationTrack())
472 return dest->isSoloIsolate (
true);
478static bool isInputTrackSolo (
const Track& track)
489 if (areAnyTracksSolo && isInputTrackSolo (*
this))
498 bool hasMidi =
false, hasWave =
false;
510 if (hasMidi && hasWave)
514 if (hasMidi && ! canPlayMidi())
515 return TRANS(
"This track contains MIDI-generating clips which may be inaudible as it doesn't output to a MIDI device or a plugin synthesiser.")
516 +
"\n\n" +
TRANS(
"To change a track's destination, select the track and use its destination list.");
521 return TRANS(
"This track contains wave clips which may be inaudible as it doesn't output to an audio device.")
522 +
"\n\n" +
TRANS(
"To change a track's destination, select the track and use its destination list.");
524 return TRANS(
"This track contains wave clips which may be inaudible as the audio will be blocked by some of the track's plugins.");
530juce::String AudioTrack::getLauncherPlayabilityWarning()
const
532 bool hasMidi =
false, hasWave =
false;
536 for (
auto slot : clipSlotList->getClipSlots())
540 if (
auto c = slot->getClip())
550 if (hasMidi && hasWave)
557 if (hasMidi && ! canPlayMidi())
558 return TRANS(
"This track contains MIDI-generating clips which may be inaudible as it doesn't output to a MIDI device or a plugin synthesiser.")
559 +
"\n\n" +
TRANS(
"To change a track's destination, select the track and use its destination list.");
564 return TRANS(
"This track contains wave clips which may be inaudible as it doesn't output to an audio device.")
565 +
"\n\n" +
TRANS(
"To change a track's destination, select the track and use its destination list.");
567 return TRANS(
"This track contains wave clips which may be inaudible as the audio will be blocked by some of the track's plugins.");
579 if (! p->takesAudioInput())
585bool AudioTrack::canPlayMidi()
const
587 if (getOutput().canPlayMidi())
591 if (p->takesMidiInput())
597 if (p->takesMidiInput())
609 return *clipSlotList;
613double AudioTrack::getMidiVerticalOffset()
const
623void AudioTrack::setMidiVerticalPos (
double visibleProp,
double offset)
626 auto vo =
juce::jlimit (0.0, 1.0 - visibleProp, offset);
633void AudioTrack::setVerticalScaleToDefault()
636 .getProperty (SettingID::midiEditorOctaves, 3)));
638 defaultMidiVisibleProportion = midiNotes / 128.0;
639 defaultMidiVerticalOffset = (1.0 - defaultMidiVisibleProportion) * 0.5;
645void AudioTrack::setTrackToGhost (AudioTrack* track,
bool shouldGhost)
647 if (track ==
nullptr)
650 auto list = EditItemID::parseStringList (ghostTracks.
get());
651 bool isGhosted = list.contains (track->itemID);
653 if (isGhosted != shouldGhost)
656 list.add (track->itemID);
658 list.removeAllInstancesOf (track->itemID);
660 ghostTracks = EditItemID::listToString (list);
666 if (ghostTracks.
get().isEmpty())
671 for (
auto& trackID : EditItemID::parseStringList (ghostTracks))
678void AudioTrack::playGuideNote (
int note, MidiChannel midiChannel,
int velocity,
bool stopOtherFirst,
bool forceNote,
bool autorelease)
680 jassert (midiChannel.isValid());
681 jassert (velocity >= 0 && velocity <= 127);
684 turnOffGuideNotes (midiChannel);
690 if (! currentlyPlayingGuideNotes.
contains (pitch))
692 currentlyPlayingGuideNotes.
add (pitch);
694 pitch, (uint8_t) velocity),
695 MidiMessageArray::notMPE);
703void AudioTrack::playGuideNotes (
const juce::Array<int>& notes, MidiChannel midiChannel,
706 jassert (midiChannel.isValid());
709 turnOffGuideNotes (midiChannel);
713 for (
int i = 0; i < notes.
size(); ++i)
717 if (! currentlyPlayingGuideNotes.
contains (pitch))
719 currentlyPlayingGuideNotes.
add (pitch);
722 MidiMessageArray::notMPE);
728void AudioTrack::turnOffGuideNotes()
732 for (
int ch = 1; ch <= 16; ch++)
733 turnOffGuideNotes (MidiChannel (ch));
736void AudioTrack::turnOffGuideNotes (MidiChannel midiChannel)
738 jassert (midiChannel.isValid());
739 auto channel = midiChannel.getChannelNumber();
741 for (
auto note : currentlyPlayingGuideNotes)
742 injectLiveMidiMessage (
juce::MidiMessage::noteOff (channel, note),
743 MidiMessageArray::notMPE);
745 currentlyPlayingGuideNotes.
clear();
751 if (listeners.isEmpty())
759 listeners.remove (l);
768 if (i == IDs::maxInputs)
773 else if (i == IDs::ghostTracks)
775 if (ghostTracks.
get().isEmpty())
780 else if (i == IDs::playSlotClips)
786 if (auto c = cs->getClip())
787 if (auto lh = c->getLaunchHandle(); lh->getPlayingStatus() == LaunchHandle::PlayState::playing)
790 else if (i == IDs::compGroup)
794 else if (i == IDs::frozen)
799 else if (i == IDs::frozenIndividually)
803 if (frozenIndividually)
808 else if (i == IDs::name)
810 auto devName = getName();
812 waveInputDevice->setAlias (devName);
813 midiInputDevice->setAlias (devName);
815 else if (i == IDs::midiNoteMap)
817 updateMidiNoteMapCache();
822 TRACKTION_ASSERT_MESSAGE_THREAD;
824 if (i == IDs::start || i == IDs::length)
825 asyncCaller.
updateAsync (updateAutoCrossfadesFlag);
827 if (i == IDs::mute &&
bool (v.getProperty (i)))
828 if (trackMuter ==
nullptr && !
bool (v.getProperty (IDs::processMidiWhenMuted,
false)))
829 if (v.hasType (IDs::MIDICLIP))
846bool AudioTrack::hasAnyLiveInputs()
848 for (
auto in : edit.getAllInputDevices())
849 if (in->isRecordingActive (
itemID) && in->getTargets().contains (
itemID))
855bool AudioTrack::hasAnyTracksFeedingIn()
858 if (t != this && t->getOutput().feedsInto (this))
865void AudioTrack::injectLiveMidiMessage (
const MidiMessageArray::MidiMessageWithSource& message)
867 TRACKTION_ASSERT_MESSAGE_THREAD
868 bool wasUsed =
false;
875void AudioTrack::injectLiveMidiMessage (
const juce::MidiMessage& m, MidiMessageArray::MPESourceID source)
877 injectLiveMidiMessage ({ m, source });
886 const auto start = TimePosition::fromSeconds (ms.
getStartTime()) + toDuration (startTime);
887 const auto end = TimePosition::fromSeconds (ms.
getEndTime()) + toDuration (startTime);
891 if (c->getPosition().time.overlaps ({ start, end }))
915 if (! track->isPartOfSubmix() && track !=
this && track->getOutput().feedsInto (
this))
916 inputTracks.
add (track);
918 for (
auto track : getTracksOfType<FolderTrack> (edit,
true))
919 if (! track->isPartOfSubmix() && track->getOutput() !=
nullptr && track->getOutput()->feedsInto (
this))
920 inputTracks.
add (track);
936void AudioTrack::setMaxNumOfInputs (
int n)
938 for (
auto* idi : edit.getEditInputDevices().getDevicesForTargetTrack (*this))
939 if (! canTrackBeChanged (idi))
948 return t ==
anyFreeze ? (frozen || frozenIndividually)
949 : (t ==
groupFreeze ? frozen : frozenIndividually);
956 if (frozenIndividually != b)
958 if (b && getOutput().getDestinationTrack() !=
nullptr)
961 "instead, you should freeze the track they input into."));
965 frozenIndividually = b;
975 const auto outputsToSubmixTrack = [
this]
978 return folder->isSubmixFolder();
983 if (b && (getOutput().getDestinationTrack() !=
nullptr || outputsToSubmixTrack()))
986 "instead, you should freeze the track they input into."));
1001 return dynamic_cast<VCAPlugin*
> (p) ==
nullptr
1007AudioTrack::FreezePointRemovalInhibitor::FreezePointRemovalInhibitor (
AudioTrack& at) : track (at) { ++track.freezePointRemovalInhibitor; }
1008AudioTrack::FreezePointRemovalInhibitor::~FreezePointRemovalInhibitor() { --track.freezePointRemovalInhibitor; }
1010void AudioTrack::freezeTrack()
1012 insertFreezePointIfRequired();
1013 const FreezePointPlugin::ScopedPluginDisabler spd (*
this,
juce::Range<int> (getIndexOfFreezePoint(),
1018 const bool shouldBeMuted =
isMuted (
true);
1020 const FreezePointPlugin::ScopedTrackUnsoloer stu (edit);
1024 auto freezeFile = getFreezeFile();
1025 freezeFile.deleteFile();
1032 trackIDs.addIfNotAlreadyThere (inputTrack->itemID);
1034 if (
auto ct =
dynamic_cast<ClipTrack*
> (inputTrack))
1035 clips.addArray (ct->getClips());
1038 Renderer::Parameters r (edit);
1039 r.tracksToDo = trackNum;
1040 r.destFile = freezeFile;
1042 r.blockSizeForAudio = dm.getBlockSize();
1043 r.sampleRateForAudio = dm.getSampleRate();
1044 r.time = { {}, getLengthIncludingInputTracks() };
1045 r.endAllowance = RenderOptions::findEndAllowance (edit, &trackIDs,
nullptr);
1046 r.canRenderInMono =
true;
1047 r.mustRenderInMono =
false;
1048 r.usePlugins =
true;
1049 r.useMasterPlugins =
false;
1050 r.addAntiDenormalisationNoise = EditPlaybackContext::shouldAddAntiDenormalisationNoise (edit.
engine);
1051 r.category = ProjectItem::Category::frozen;
1053 const Edit::ScopedRenderStatus srs (edit,
true);
1054 const auto desc =
TRANS(
"Creating track freeze for \"XDVX\"")
1055 .replace (
"XDVX", getName()) +
"...";
1065 if (! r.destFile.existsAsFile())
1075int AudioTrack::getIndexOfFreezePoint()
1081 if (
dynamic_cast<FreezePointPlugin*
> (p) !=
nullptr)
1090void AudioTrack::insertFreezePointAfterPlugin (
const Plugin::Ptr& p)
1094 if (! pl.getPlugins().contains (p.get()))
1097 removeFreezePoint();
1098 pl.insertPlugin (FreezePointPlugin::create(), pl.getPlugins().indexOf (p.get()) + 1);
1104void AudioTrack::removeFreezePoint()
1108 for (
int i = pl.size(); --i >= 0;)
1109 if (
auto f =
dynamic_cast<FreezePointPlugin*
> (pl[i]))
1110 f->deleteFromParent();
1113bool AudioTrack::insertFreezePointIfRequired()
1115 if (getIndexOfFreezePoint() != -1)
1118 if (
auto p =
pluginList.insertPlugin (FreezePointPlugin::create(), getIndexOfDefaultFreezePoint()))
1119 auto freezer = FreezePointPlugin::createTrackFreezer (p);
1127void AudioTrack::freezeTrackAsync()
const
1129 freezeUpdater->freeze();
1132int AudioTrack::getIndexOfDefaultFreezePoint()
1136 if (position == FreezePointPlugin::beforeAllPlugins)
1141 for (
int i = 0; i < pl.size(); ++i)
1143 if (
dynamic_cast<VolumeAndPanPlugin*
> (pl[i]) !=
nullptr)
1145 if (position == FreezePointPlugin::preFader)
1148 if (position == FreezePointPlugin::postFader)
1161 p->
setFrozen (pluginsToFreeze.contains (i++));
1164void AudioTrack::unFreezeTrack()
1168 auto defaultIndex = getIndexOfDefaultFreezePoint();
1169 auto freezePosition = (defaultPosition == FreezePointPlugin::postFader) ? defaultIndex
1170 :
std::
max (0, defaultIndex - 1);
1172 if (getIndexOfFreezePoint() == freezePosition)
1173 if (freezePointRemovalInhibitor == 0)
1174 if (
auto f =
dynamic_cast<FreezePointPlugin*
> (
pluginList[freezePosition]))
1175 f->deleteFromParent();
1185 return TemporaryFileManager::getFreezeFileForTrack (*
this);
1188bool AudioTrack::isSidechainSource()
const
1190 for (
auto p : edit.getPluginCache().getPlugins())
1191 if (p->getSidechainSourceID() ==
itemID)
1203 auto srcId = p->getSidechainSourceID();
1205 if (srcId.isValid())
ElementType getUnchecked(int index) const
int size() const noexcept
void add(const ElementType &newElement)
bool contains(ParameterType elementToLookFor) const
bool addIfNotAlreadyThere(ParameterType newElement)
void triggerAsyncUpdate()
void cancelPendingUpdate() noexcept
BigInteger & setBit(int bitNumber)
void forceUpdateOfCachedValue()
Type get() const noexcept
static bool isDigit(char character) noexcept
double getStartTime() const noexcept
double getEndTime() const noexcept
static MidiMessage noteOn(int channel, int noteNumber, float velocity) noexcept
static const char * getGMInstrumentName(int midiInstrumentNumber)
static MidiMessage allNotesOff(int channel) noexcept
static String getMidiNoteName(int noteNumber, bool useSharps, bool includeOctaveNumber, int octaveNumForMiddleC)
static const char * getRhythmInstrumentName(int midiNoteNumber)
static StringArray fromLines(StringRef stringToBreakUp)
bool startsWithIgnoreCase(StringRef text) const noexcept
void stopTimer() noexcept
void startTimer(int intervalInMilliseconds) noexcept
virtual void valueTreeParentChanged(ValueTree &treeWhoseParentHasChanged)
virtual void valueTreePropertyChanged(ValueTree &treeWhosePropertyHasChanged, const Identifier &property)
bool isValid() const noexcept
ValueTree & setProperty(const Identifier &name, const var &newValue, UndoManager *undoManager)
void addListener(Listener *listener)
ValueTree getParent() const noexcept
const var & getProperty(const Identifier &name) const noexcept
void removeListener(Listener *listener)
ValueTree getOrCreateChildWithName(const Identifier &type, UndoManager *undoManager)
void removeProperty(const Identifier &name, UndoManager *undoManager)
Base class for Clips that produce some kind of audio e.g.
ClipSlotList & getClipSlotList()
Returns the ClipSlotList for this track.
bool canContainPlugin(Plugin *) const override
Returns true if this track can contain a specific Plugin.
bool mergeInMidiSequence(juce::MidiMessageSequence, TimePosition startTime, MidiClip *, MidiList::NoteAutomationType)
try to add this MIDI sequence to any MIDI clips that are already in the track.
bool canPlayAudio() const
checks whether audio clips can be played - i.e.
juce::CachedValue< AtomicWrapper< bool > > playSlotClips
Determines if the track's arrange clips or clip slots should be audible.
juce::String getNameForMidiNoteNumber(int note, int midiChannel, bool preferSharp=true) const
looks for a name for a midi note by trying all the plugins, and returning a default on failure.
bool isSolo(bool includeIndirectSolo) const override
Returns true if this track is soloed.
void initialise() override
Initialises the Track.
void sanityCheckName() override
checks whether the name is 'track n' and if so, makes sure the number is right
bool isTrackAudible(bool areAnyTracksSolo) const override
Returns whether this Track should be audible.
juce::String getTrackPlayabilityWarning() const
returns a warning message about this track not being playable, or "" if it's ok
bool isFrozen(FreezeType) const override
Returns true if this track is frozen using the given type.
void setSolo(bool) override
Subclasses should implement this to solo themselves.
void removeListener(Listener *)
Removes a Listener.
void addListener(Listener *)
Adds a Listener.
bool isMuted(bool includeMutingByDestination) const override
Returns true if this track is muted.
void setFrozen(bool, FreezeType) override
Attempts to freeze or unfreeze the track using a given FreezeType.
void setSoloIsolate(bool) override
Subclasses should implement this to solo isolate themselves.
void setMute(bool) override
Subclasses should implement this to mute themselves.
bool isSoloIsolate(bool includeIndirectSolo) const override
Returns true if this track is solo isolated.
double getMidiVisibleProportion() const
vertical scales for displaying the midi note editor
juce::String getNameAsTrackNumberWithDescription() const
Returns a name in the form "Track [number] ([track name])" (This is smart enough to not add the paren...
juce::String getSelectableDescription() override
Subclasses must return a description of what they are.
juce::String getNameForProgramNumber(int programNumber, int bank) const
prog number is 0 based.
juce::Array< Track * > getInputTracks() const override
Should return any tracks which feed into this track.
juce::String getNameAsTrackNumber() const
Returns a name in the form "Track [number]".
const juce::Array< Clip * > & getClips() const
Returns the clips this owner contains.
A list of the ClipSlots on a Track.
void ensureNumberOfSlots(int numSlots)
Adds Slots to ensure at least numSlots exist.
void initialise() override
Initialises the Track.
Plugin::Array getAllPlugins() const override
Returns all pugins on this Track.
static bool isClipState(const juce::ValueTree &)
Checks whether a ValueTree is some kind of clip state.
const EditItemID itemID
Every EditItem has an ID which is unique within the edit.
The Tracktion Edit class!
void restartPlayback()
Use this to tell the play engine to rebuild the audio graph if the toplogy has changed.
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.
void dispatchPendingUpdatesSynchronously()
If there's a change to send out to the listeners, do it now rather than waiting for the next timer me...
bool isLoading() const
Returns true if the Edit's not yet fully loaded.
void visitAllTracksRecursive(std::function< bool(Track &)>) const
Visits all tracks in the Edit with the given function.
juce::UndoManager & getUndoManager() noexcept
Returns the juce::UndoManager used for this Edit.
PluginList & getMasterPluginList() const noexcept
Returns the master PluginList.
Engine & engine
A reference to the Engine.
MidiProgramManager & getMidiProgramManager() const
Returns the MidiProgramManager instance that handles MIDI banks, programs, sets or presets.
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.
DeviceManager & getDeviceManager() const
Returns the DeviceManager instance for handling audio / MIDI devices.
EngineBehaviour & getEngineBehaviour() const
Returns the EngineBehaviour instance.
Base class for elements which can contain macro parameters.
static ProjectItem::Ptr renderToProjectItem(const juce::String &taskDescription, const Parameters ¶ms)
Renders an Edit to a file and creates a new ProjectItem for it.
static juce::File renderToFile(const juce::String &taskDescription, const Parameters ¶ms)
Renders an Edit to a file given by the Parameters.
void ensureNumberOfScenes(int numScenes)
Adds Scenes to ensure numScenes are preset in the list.
int getNumScenes()
Returns the number of Scenes in the Edit.
virtual void changed()
This should be called to send a change notification to any SelectableListeners that are registered wi...
Base class for tracks which contain clips and plugins and can be added to Edit[s].
PluginList pluginList
The Track's PluginList.
FreezeType
Determines the type of freeze.
@ individualFreeze
Freezes a track in to a single audio file.
@ groupFreeze
Freezes multiple tracks together in to a single file.
@ anyFreeze
Either a group or individual freeze.
int getIndexInEditTrackList() const
Returns the index of this track in a flat list of tracks contained in an Edit.
bool isPartOfSubmix() const
Tests whether this nested within a submix FolderTrack.
juce::ValueTree state
The state of this Track.
bool hasFreezePointPlugin() const
Tests whether this Track contains a FreezePointPlugin.
void resetName()
Sets the name of the Track to an empty string.
FolderTrack * getParentFolderTrack() const
Returns the parent FolderTrack if this is nested in one.
virtual bool isTrackAudible(bool areAnyTracksSolo) const
Returns whether this Track should be audible.
void freePlaybackContext()
Detaches the current EditPlaybackContext, removing it from the DeviceManager.
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)
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
juce::Array< TrackType * > getTracksOfType(const Edit &, bool recursive)
Returns the tracks of a given type in an Edit.
juce::Array< AudioTrack * > getAudioTracks(const Edit &edit)
Returns all the AudioTracks in an Edit.
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!)
void mergeInMidiSequence(MidiClip &mc, juce::MidiMessageSequence ms, TimeDuration startTime, MidiList::NoteAutomationType automationType)
Copies a zero-time origin based MIDI sequence in to a MidiClip.
AudioTrack * findAudioTrackForID(const Edit &edit, EditItemID id)
Returns the AudioTrack with a given ID if contained in the Edit.
Represents a position in real-life time.
void updateAsync(int functionID)
Triggers an asyncronous call to one of the functions.
Listener interface to be notified of recorded MIDI being sent to the plugins.
virtual void injectLiveMidiMessage(AudioTrack &, const MidiMessageArray::MidiMessageWithSource &, bool &wasUsed)=0
Called when a MidiMessage (i.e.
Describes a channel of a WaveInputDevice or WaveOutputDevice by specifying the channel index in the g...
Describes a WaveDevice from which the WaveOutputDevice and WaveInputDevice lists will be built.
#define CRASH_TRACER
This macro adds the current location to a stack which gets logged if a crash happens.