tracktion-engine 3.0-10-g034fdde4aa5
Tracktion Engine — High level data model for audio applications

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_TransportControl.h
Go to the documentation of this file.
1 /*
2 ,--. ,--. ,--. ,--.
3 ,-' '-.,--.--.,--,--.,---.| |,-.,-' '-.`--' ,---. ,--,--, Copyright 2024
4 '-. .-'| .--' ,-. | .--'| /'-. .-',--.| .-. || \ Tracktion Software
5 | | | | \ '-' \ `--.| \ \ | | | |' '-' '| || | Corporation
6 `---' `--' `--`--'`---'`--'`--' `---' `--' `---' `--''--' www.tracktion.com
7
8 Tracktion Engine uses a GPL/commercial licence - see LICENCE.md for details.
9*/
10
11namespace tracktion { inline namespace engine
12{
13
15void toStart (TransportControl&, const SelectableList&);
16
18void toEnd (TransportControl&, const SelectableList&);
19
21void tabBack (TransportControl&);
22
24void tabForward (TransportControl&);
25
27void markIn (TransportControl&);
28
30void markOut (TransportControl&);
31
35void scrub (TransportControl&, double unitsForwards);
36
40void freePlaybackContextIfNotRecording (TransportControl&);
41
42
43//==============================================================================
57 private juce::Timer
58
59{
60public:
64 ~TransportControl() override;
65
66 //==============================================================================
72 void play (bool justSendMMCIfEnabled);
73
75 void playFromStart (bool justSendMMCIfEnabled);
76
78 void playSectionAndReset (TimeRange rangeToPlay);
79
91 void record (bool justSendMMCIfEnabled, bool allowRecordingIfNoInputsArmed = false);
92
98 void stop (bool discardRecordings,
99 bool clearDevices,
100 bool canSendMMCStop = true);
101
105 void stopIfRecording();
106
108 void stopRecording (bool discardRecordings = false);
109
110 //==============================================================================
114 juce::Result applyRetrospectiveRecord (bool armedOnly);
115
118
124 void syncToEdit (Edit* editToSyncTo, bool syncToTargetLoopLength);
125
126 //==============================================================================
128 bool isPlaying() const;
129
131 bool isRecording() const;
132
134 bool isSafeRecording() const;
135
140 bool isStopping() const;
141
145 bool isRecordingStopping() const;
146
149
150 //==============================================================================
157
160
162 void setPosition (TimePosition timeToMoveTo, TimePosition timeToPerformJump);
163
167 void setUserDragging (bool);
168
172 bool isUserDragging() const noexcept;
173
178
179 //==============================================================================
181 void setLoopIn (TimePosition);
182
185
188
191
193 void setLoopRange (TimeRange);
194
196 TimeRange getLoopRange() const noexcept;
197
200
202 TimecodeSnapType getSnapType() const noexcept { return currentSnapType; }
203
204 //==============================================================================
206 EditPlaybackContext* getCurrentPlaybackContext() const { return playbackContext.get(); }
207
209 bool isPlayContextActive() const { return playbackContext != nullptr; }
210
214 void ensureContextAllocated (bool alwaysReallocate = false);
215
219 void freePlaybackContext();
220
225
228
229 //==============================================================================
231 void setRewindButtonDown (bool isDown);
232
234 void setFastForwardButtonDown (bool isDown);
235
237 void nudgeLeft();
238
240 void nudgeRight();
241
242 //==============================================================================
246 void editHasChanged();
247
263
265 bool isAllowedToReallocate() const noexcept;
266
267 //==============================================================================
270 {
272 ScopedPlaybackRestarter (TransportControl& o) : tc (o), wasPlaying (tc.isPlaying()) {}
273
275 ~ScopedPlaybackRestarter() { if (wasPlaying) tc.play (false); }
276
278 bool wasPlaying = false;
279
281 };
282
283 //==============================================================================
286 {
289 : tc (o), wasAllocated (tc.isPlayContextActive())
290 {}
291
294 {
295 if (wasAllocated)
297 }
298
300 bool wasAllocated = false;
301 ScopedPlaybackRestarter playbackRestarter { tc };
302
303 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ScopedContextAllocator)
304 };
305
306 //==============================================================================
309
311 static int getNumPlayingTransports (Engine&);
312
314 static void stopAllTransports (Engine&, bool discardRecordings, bool clearDevices);
315
318
319 //==============================================================================
321 struct Listener
322 {
324 virtual ~Listener() {}
325
327 virtual void playbackContextChanged() {}
328
330 virtual void autoSaveNow() {}
331
333 virtual void setAllLevelMetersActive (bool /*metersBecameInactive*/) {}
334
336 virtual void setVideoPosition (TimePosition, bool /*forceJump*/) {}
337
339 virtual void startVideo() {}
340
342 virtual void stopVideo() {}
343
345 virtual void recordingStarted (SyncPoint /*start*/, std::optional<TimeRange> /*punchRange*/) {}
346
348 virtual void recordingStopped (SyncPoint, bool /*discardRecordings*/) {}
349
351 virtual void recordingAboutToStart (InputDeviceInstance&, EditItemID /*targetID*/) {}
352
356 virtual void recordingAboutToStop (InputDeviceInstance&, EditItemID /*targetID*/) {}
357
364 EditItemID /*targetID*/,
365 const juce::ReferenceCountedArray<Clip>& /*recordedClips*/)
366 {}
367 };
368
370 void addListener (Listener* l) { listeners.add (l); }
371
373 void removeListener (Listener* l) { listeners.remove (l); }
374
375 //==============================================================================
384 juce::CachedValue<TimePosition> loopPoint1, loopPoint2;
387 juce::CachedValue<bool> snapToTimecode, looping;
388
389 //==============================================================================
391 void callRecordingAboutToStartListeners (InputDeviceInstance&, EditItemID);
393 void callRecordingAboutToStopListeners (InputDeviceInstance&, EditItemID);
395 void callRecordingFinishedListeners (InputDeviceInstance&, EditItemID, juce::ReferenceCountedArray<Clip>);
396
397private:
398 //==============================================================================
399 struct TransportState;
400 std::unique_ptr<TransportState> transportState;
403
404 TimecodeSnapType currentSnapType;
405 bool isDelayedChangePending = false;
406 int loopUpdateCounter = 10;
407 bool isStopInProgress = false;
408 bool recordingIsStoppingFlag = false;
409
410 struct ScreenSaverDefeater;
411 std::unique_ptr<ScreenSaverDefeater> screenSaverDefeater;
412
413 struct PlayingFlag
414 {
415 PlayingFlag (Engine&) noexcept;
416 ~PlayingFlag() noexcept;
417
418 Engine& engine;
419 };
420
421 std::unique_ptr<PlayingFlag> playingFlag;
422 void clearPlayingFlags();
423
424 struct SectionPlayer;
425 std::unique_ptr<SectionPlayer> sectionPlayer;
426
427 struct PlayHeadWrapper;
428 std::unique_ptr<PlayHeadWrapper> playHeadWrapper;
429
430 bool lastPlayStatus = false, lastRecordStatus = false;
431 void startedOrStopped();
432 void releaseAudioNodes();
433
434 void performPlay();
435 std::optional<std::pair<SyncPoint, std::optional<TimeRange>>> performRecord();
436 void performStop();
437 std::optional<SyncPoint> performStopRecording();
438
439 void performPositionChange();
440 void performRewindButtonChanged();
441 void performFastForwardButtonChanged();
442 void performNudgeLeft();
443 void performNudgeRight();
444
445 void sendMMC (const juce::MidiMessage&);
446 void sendMMCCommand (juce::MidiMessage::MidiMachineControlCommand);
447 bool sendMMCStartPlay();
448 bool sendMMCStartRecord();
449
450 bool areAnyInputsRecording();
451
452 struct FileFlushTimer;
453 std::unique_ptr<FileFlushTimer> fileFlushTimer;
454
455 struct ButtonRepeater;
456 std::unique_ptr<ButtonRepeater> rwRepeater, ffRepeater;
457
458 void timerCallback() override;
459
460 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TransportControl)
461};
462
463}} // namespace tracktion { inline namespace engine
The Tracktion Edit class!
The Engine is the central class for all tracktion sessions.
An instance of an InputDevice that's available to an Edit.
Controls the transport of an Edit's playback.
void playSectionAndReset(TimeRange rangeToPlay)
Plays a section of an Edit then stops playback, useful for previewing clips.
void setLoopIn(TimePosition)
Sets the loop in position.
void setFastForwardButtonDown(bool isDown)
Starts/stops a fast-forward operation.
TimePosition getPosition() const
Returns the current transport position.
void removeListener(Listener *l)
Removes a Listener.
void setLoopPoint2(TimePosition)
Sets a loop point 2 position.
TimecodeSnapType getSnapType() const noexcept
Returns the current snap type.
void ensureContextAllocated(bool alwaysReallocate=false)
Ensures an active EditPlaybackContext has been created so this Edit can be played back.
bool isPlayContextActive() const
Returns true if this Edit is attached to the DeviceManager for playback.
void syncToEdit(Edit *editToSyncTo, bool syncToTargetLoopLength)
Syncs this Edit's playback to another Edit.
juce::ValueTree state
The state of this transport.
bool isAllowedToReallocate() const noexcept
Returns true if no ReallocationInhibitors currently exist.
void setLoopRange(TimeRange)
Sets the loop points from a given range.
juce::Result applyRetrospectiveRecord(bool armedOnly)
Applys a retrospective record to any assigned input devices, creating clips for any historical input.
juce::Array< juce::File > getRetrospectiveRecordAsAudioFiles()
Perfoms a retrospective record operation and returns any new files.
void nudgeRight()
Moves the transport forwards slightly.
EditPlaybackContext * getCurrentPlaybackContext() const
Returns the active EditPlaybackContext if this Edit is attached to the DeviceManager for playback.
void freePlaybackContext()
Detaches the current EditPlaybackContext, removing it from the DeviceManager.
bool isRecordingStopping() const
Returns true if a recording is currently being stopped.
bool isRecording() const
Returns true if recording is in progress.
void setLoopPoint1(TimePosition)
Sets a loop point 1 position.
void play(bool justSendMMCIfEnabled)
Starts playback of an Edit.
void stopRecording(bool discardRecordings=false)
Stops recording without stopping playback.
bool isUserDragging() const noexcept
Returns true if a drag/scrub operation has been enabled.
void setUserDragging(bool)
Signifies a scrub-drag operation has started/stopped.
static void stopAllTransports(Engine &, bool discardRecordings, bool clearDevices)
Stops all TransportControl[s] in the Engine playing.
void forceOrphanFreezeAndProxyFilesPurge()
Triggers a cleanup of any unused freeze and proxy files.
void playFromStart(bool justSendMMCIfEnabled)
Sets the position to the startPosition and begins playback from there.
void nudgeLeft()
Moves the transport back slightly.
static juce::Array< TransportControl * > getAllActiveTransports(Engine &)
Returns all the active TransportControl[s] in the Engine.
static int getNumPlayingTransports(Engine &)
Returns the number of Edits currently playing.
TimePosition getTimeWhenStarted() const
Returns the time when the transport was started.
bool isStopping() const
Returns true if the transport is currently being stopped.
bool isPositionUpdatingFromPlayhead() const
Returns true if the current position change was triggered from an update directly from the playhead (...
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.
void record(bool justSendMMCIfEnabled, bool allowRecordingIfNoInputsArmed=false)
Starts recording.
TimeRange getLoopRange() const noexcept
Returns the loop range.
void setPosition(TimePosition)
Sets a new transport position.
void setLoopOut(TimePosition)
Sets a loop out position.
bool isSafeRecording() const
Returns true if safe-recording is in progress.
void setRewindButtonDown(bool isDown)
Starts/stops a rewind operation.
void addListener(Listener *l)
Adds a Listener.
bool isPlaying() const
Returns true if the transport is playing.
Edit & edit
The Edit this transport belongs to.
void setSnapType(TimecodeSnapType)
Sets a snap type to use.
void stopIfRecording()
Stops playback only if recording is currently in progress.
Engine & engine
The Engine this Edit belongs to.
static std::vector< std::unique_ptr< ScopedContextAllocator > > restartAllTransports(Engine &, bool clearDevices)
Restarts all TransportControl[s] in the Edit.
juce::CachedValue< TimePosition > startPosition
The position to start playing from.
void triggerClearDevicesOnStop()
Triggers a graph rebuild when playback stops.
#define JUCE_DECLARE_NON_COPYABLE(className)
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
void markOut(TransportControl &tc)
Sets the mark out position to the current transport position.
void toStart(TransportControl &tc, const SelectableList &items)
Moves the transport to the start of the selected objects.
void freePlaybackContextIfNotRecording(TransportControl &tc)
Frees the playback context if no recording is in progress, useful for when an app is minimised.
void toEnd(TransportControl &tc, const SelectableList &items)
Moves the transport to the end of the selected objects.
void markIn(TransportControl &tc)
Sets the mark in position to the current transport position.
void tabBack(TransportControl &tc)
Moves the transport back to the previous point of interest.
void tabForward(TransportControl &tc)
Moves the transport forwards to the next point of interest.
void scrub(TransportControl &tc, double units)
Scrubs back and forth in 'units', where a unit is about 1/50th of the width of the strip window.
Holds a reference sample position and the Edit time and beat that it corresponds to.
Represents a position in real-life time.
ID for objects of type EditElement - e.g.
Listener interface to be notified of changes to the transport.
virtual void autoSaveNow()
Called periodically to indicate the Edit has changed in an audible way and should be auto-saved.
virtual void stopVideo()
Should stop video playback.
virtual void recordingAboutToStart(InputDeviceInstance &, EditItemID)
Called before recording start for a specific input instance.
virtual void recordingFinished(InputDeviceInstance &, EditItemID, const juce::ReferenceCountedArray< Clip > &)
Called when recording stops for a specific input instance.
virtual void recordingAboutToStop(InputDeviceInstance &, EditItemID)
Called before recording stops for a specific input instance.
virtual void playbackContextChanged()
Called when an EditPlaybackContext is created or deleted.
virtual void recordingStarted(SyncPoint, std::optional< TimeRange >)
Called when global recording starts.
virtual void recordingStopped(SyncPoint, bool)
Called when global recording stops.
virtual void setVideoPosition(TimePosition, bool)
Should set a new position for any playing video.
virtual void setAllLevelMetersActive(bool)
If false, levels should be cleared.
virtual void startVideo()
Should start video playback.
Prevents the nodes being regenerated while one of these exists, e.g.
Frees the playback context and then re-allocates it upon destruction.
~ScopedContextAllocator()
Allocated the Edit if it was allocated on construction.
ScopedContextAllocator(TransportControl &o)
Saves whether the Edit was allocated.
Is an Edit is playing back, this resumes playback when destroyed.
ScopedPlaybackRestarter(TransportControl &o)
Saves the playback state.
~ScopedPlaybackRestarter()
Starts playback if playing when constructed.