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

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_InputDevice.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
21class InputDevice : public Selectable
22{
23public:
26 {
27 waveDevice,
28 trackWaveDevice,
29 physicalMidiDevice,
30 virtualMidiDevice,
31 trackMidiDevice
32 };
33
34 //==============================================================================
36 ~InputDevice() override;
37
38 //==============================================================================
39 const juce::String& getName() const { return name; }
40 const juce::String& getType() const { return type; }
41
42 juce::String getDeviceID() const { return deviceID; }
43
44 virtual DeviceType getDeviceType() const = 0;
45 bool isTrackDevice() const;
46
48 juce::String getAlias() const;
49 void setAlias (const juce::String& newAlias);
50
51 virtual bool isAvailableToEdit() const { return isEnabled(); }
52
53 bool isEnabled() const;
54 virtual void setEnabled (bool) = 0;
55
56 virtual bool isMidi() const { return false; }
57
59 enum class MonitorMode
60 {
61 off,
62 automatic,
63 on
64 };
65
66 MonitorMode getMonitorMode() const { return monitorMode; }
67 void setMonitorMode (MonitorMode);
68
71
73 virtual void masterTimeUpdate (double time) = 0;
74
75 static void setRetrospectiveLock (Engine&, const juce::Array<InputDeviceInstance*>&, bool lock);
76 virtual void updateRetrospectiveBufferLength (double length) = 0;
77
78 //==============================================================================
80
81 virtual void saveProps() = 0;
82
83 Engine& engine;
84 LevelMeasurer levelMeasurer;
85
86protected:
87 std::atomic<bool> enabled { false };
89 MonitorMode defaultMonitorMode = MonitorMode::automatic;
90 bool retrospectiveRecordLock = false;
91
92private:
93 const juce::String type, deviceID, name;
94 juce::String alias;
95
96 juce::String getAliasPropName() const;
97};
98
99
100//==============================================================================
101//==============================================================================
109{
110public:
111 struct Destination;
112
113 //==============================================================================
114 //==============================================================================
117
119 ~InputDeviceInstance() override;
120
122 InputDevice& getInputDevice() noexcept { return owner; }
123
126
128 [[ nodiscard ]] tl::expected<Destination*, juce::String> setTarget (EditItemID targetID, bool moveToTrack, juce::UndoManager*,
130
132 [[ nodiscard ]] juce::Result removeTarget (EditItemID targetID, juce::UndoManager*);
133
135 virtual bool isLivePlayEnabled (const Track&) const;
136
138 virtual bool isRecordingActive() const;
139
141 virtual bool isRecordingActive (EditItemID) const;
142
145
147 bool isRecordingEnabled (EditItemID) const;
148
152 void setRecordingEnabled (EditItemID, bool);
153
157 virtual bool shouldTrackContentsBeMuted (const Track&) { return false; }
158
159 //==============================================================================
160 //** The parameters used to configure a recording operation. */
166
173 {
174 public:
176 virtual ~RecordingContext() = default;
177
180 protected:
181 RecordingContext (EditItemID targetID_)
182 : targetID (targetID_)
183 {}
184 };
185
190
196
204
218
222 virtual tl::expected<Clip::Array, juce::String> stopRecording (StopRecordingParameters) = 0;
223
231 std::function<void (tl::expected<Clip::Array, juce::String>)>) = 0;
232
234 virtual bool isRecording (EditItemID) = 0;
235
237 virtual bool isRecording() = 0;
238
240 virtual juce::File getRecordingFile (EditItemID) const { return {}; }
241
244
247
251 virtual juce::Array<Clip*> applyRetrospectiveRecord (bool armedOnly) = 0;
252
253 //==============================================================================
254 juce::ValueTree state;
259 //==============================================================================
260 struct Destination : public Selectable
261 {
263 ~Destination() override
264 {
265 notifyListenersOfDeletion();
266 }
267
272 const EditItemID targetID = EditItemID::fromProperty (state, IDs::targetID);
273
275 const int targetIndex = state[IDs::targetIndex];
276
279
280 //==============================================================================
283 : input (i), state (v)
284 {
285 recordEnabled.referTo (state, IDs::armed, nullptr, false);
286 assert (targetID.isValid() && "Must have a valid ID!");
287 }
288
294 };
295
296 //==============================================================================
298 {
300 ~WaveInputDestination() override { notifyListenersOfDeletion(); }
301 };
302
304 {
306 ~MidiInputDestination() override { notifyListenersOfDeletion(); }
307 };
308
310 {
312 ~VirtualMidiInputDestination() override { notifyListenersOfDeletion(); }
313 };
314
315 //==============================================================================
316 struct DestinationList : public ValueTreeObjectList<Destination>
317 {
319 : ValueTreeObjectList<Destination> (v), input (i)
320 {
321 rebuildObjects();
322 }
323
324 ~DestinationList() override
325 {
326 freeObjects();
327 }
328
329 bool isSuitableType (const juce::ValueTree& v) const override
330 {
331 return v.hasType (IDs::INPUTDEVICEDESTINATION);
332 }
333
334 Destination* createNewObject (const juce::ValueTree& v) override
335 {
336 switch (input.getInputDevice().getDeviceType())
337 {
338 case InputDevice::waveDevice: [[ fallthrough ]];
339 case InputDevice::trackWaveDevice: return new WaveInputDestination (input, v);
340 case InputDevice::physicalMidiDevice: [[ fallthrough ]];
341 case InputDevice::trackMidiDevice: return new MidiInputDestination (input, v);
342 case InputDevice::virtualMidiDevice: return new VirtualMidiInputDestination (input, v);
343 default:
344 {
346 return new Destination (input, v);
347 }
348 }
349 }
350
351 void deleteObject (Destination* c) override
352 {
353 delete c;
354 }
355
356 void newObjectAdded (Destination*) override {}
357 void objectRemoved (Destination*) override {}
358 void objectOrderChanged() override {}
359
360 InputDeviceInstance& input;
361 };
362
365
366 //==============================================================================
370 struct Consumer
371 {
373 virtual ~Consumer() = default;
374
376 virtual void acceptInputBuffer (choc::buffer::ChannelArrayView<float>) {}
377
380
382 virtual void discardRecordings (EditItemID /*targetID*/) {}
383 };
384
386 virtual void addConsumer (Consumer*) = 0;
387
389 virtual void removeConsumer (Consumer*) = 0;
390
391protected:
392 void valueTreePropertyChanged (juce::ValueTree&, const juce::Identifier&) override;
393 void valueTreeChildAdded (juce::ValueTree&, juce::ValueTree&) override;
394 void valueTreeChildRemoved (juce::ValueTree&, juce::ValueTree&, int) override;
395
396 ClipSlot* getFreeSlot (AudioTrack&);
397
398private:
399 mutable AsyncCaller trackDeviceEnabler, recordStatusUpdater;
400 bool wasLivePlayActive = false;
401 std::vector<EditItemID> changedTargetTrackIDs;
402 void updateRecordingStatus();
403
406};
407
408
409//==============================================================================
410//==============================================================================
413
416
418[[ nodiscard ]] bool isOnTargetTrack (InputDeviceInstance&, const Track&, int idx);
419
421[[ nodiscard ]] bool isAttached (InputDeviceInstance&);
422
425
426//==============================================================================
428[[ nodiscard ]] InputDeviceInstance::Destination* getDestination (InputDeviceInstance&, const Track& track, int index);
429
432
435
436
437//==============================================================================
439[[ nodiscard ]] inline bool hasErrors (const InputDeviceInstance::PreparedContext& pc)
440{
441 for (auto& res : pc)
442 if (! res)
443 return true;
444
445 return false;
446}
447
450{
451 std::move (src.begin(), src.end(), std::back_inserter(dest));
452 return dest;
453}
454
457{
459 juce::StringArray errors;
460
461 for (auto& res : pc)
462 {
463 if (res)
464 recContexts.emplace_back (std::move (res.value()));
465 else
466 errors.add (res.error());
467 }
468
469 return { std::move (recContexts), std::move (errors) };
470}
471
472
473}} // namespace tracktion { inline namespace engine
assert
T back_inserter(T... args)
void referTo(ValueTree &tree, const Identifier &property, UndoManager *um)
void add(String stringToAdd)
Represents a slot on a track that a Clip can live in to be played as a launched clip.
The Tracktion Edit class!
The Engine is the central class for all tracktion sessions.
const EditItemID targetID
The ID of the recording target, track or clip.
An instance of an InputDevice that's available to an Edit.
virtual bool isLivePlayEnabled(const Track &) const
Whether the track should monitor the input or not.
virtual bool isRecordingActive() const
Returns true if recording is enabled and the input is connected to any target.
virtual juce::Array< Clip * > applyRetrospectiveRecord(bool armedOnly)=0
Takes the retrospective buffer and creates clips from it, as if recording had been triggered in the p...
std::vector< tl::expected< std::unique_ptr< RecordingContext >, juce::String > > PreparedContext
An array of either valid RecordingContexts or an error message if the recording couldn't be started.
bool discardRecordings
Whether to discard recordings or keep them.
virtual void stopRecording(StopRecordingParameters, std::function< void(tl::expected< Clip::Array, juce::String >)>)=0
Stops a recording asyncronously.
std::vector< EditItemID > targetsToStop
The targets to stop, others will continue allowing you to punch out only specific targets.
Edit & edit
The Edit this instance belongs to.
bool isRecordingEnabled(EditItemID) const
Returns true if recording is enabled for the given target.
virtual juce::File getRecordingFile(EditItemID) const
Returns the File that the given target is currently recording to.
virtual std::vector< std::unique_ptr< RecordingContext > > startRecording(std::vector< std::unique_ptr< RecordingContext > >)=0
Starts a recording.
juce::Array< EditItemID > getTargets() const
Returns the targets this instance is assigned to.
virtual std::shared_ptr< choc::fifo::SingleReaderSingleWriterFIFO< juce::MidiMessage > > getRecordingNotes(EditItemID) const
Returns a fifo of recorded MIDInotes that can be used for drawing UI components.
virtual bool shouldTrackContentsBeMuted(const Track &)
Should return true if this input is currently actively recording into a track and it wants the existi...
std::vector< EditItemID > targets
The targets to record to, if this is empty, all armed targets will be added.
virtual bool isRecording(EditItemID)=0
Returns true if there are any active recordings for this device.
virtual PreparedContext prepareToRecord(RecordingParameters)=0
Prepares a recording operation.
virtual bool isRecording()=0
Returns true if there are any active recordings for this device.
void setRecordingEnabled(EditItemID, bool)
Enabled/disables recording for a given target.
EditPlaybackContext & context
The EditPlaybackContext this instance belongs to.
InputDevice & owner
The state of this instance.
DestinationList destinations
The list of assigned destinations.
InputDevice & getInputDevice() noexcept
Returns the InputDevice this instance belongs to.
bool isLooping
Whether to treat the stopped recordings as looped or not.
virtual void addConsumer(Consumer *)=0
Base classes should override this to add any Consumers internally.
TimeRange punchRange
The transport time range at which the recording should happen.
juce::Result removeTarget(EditItemID targetID, juce::UndoManager *)
Removes the destination with the given targetID.
tl::expected< Destination *, juce::String > setTarget(EditItemID targetID, bool moveToTrack, juce::UndoManager *, std::optional< int > index=std::nullopt)
Assigns this input to either an AudioTrack or a ClipSlot.
virtual void removeConsumer(Consumer *)=0
Base classes should override this to remove the Consumer internally.
TimeRange markedRange
The marked range used for either loop or punch times.
TimePosition unloopedTimeToEndRecording
The TimePosition this recording should be stopped at.
virtual tl::expected< Clip::Array, juce::String > stopRecording(StopRecordingParameters)=0
Stops a recording.
virtual bool isRecordingQueuedToStop(EditItemID)=0
Returns true if the async stopRecording function has been used and this target is waiting to stop.
virtual TimePosition getPunchInTime(EditItemID)=0
Returns the time that a given target started recording.
Represents an input device.
MonitorMode
Enum to describe monitor modes.
@ automatic
Live input is audible when record is enabled.
@ off
Live input is never audible.
@ on
Live input is always audible.
juce::String getAlias() const
the alias is the name shown in the draggable input device components
virtual InputDeviceInstance * createInstance(EditPlaybackContext &)=0
Creates an instance to use for a given playback context.
DeviceType
enum to allow quick querying of the device type.
juce::String getSelectableDescription() override
Subclasses must return a description of what they are.
virtual void masterTimeUpdate(double time)=0
This is a bit of a hack but allows the time for MIDI devices to be set through the base class interfa...
Monitors the levels of buffers that are passed in, and keeps peak values, overloads,...
Base class for things that can be selected, and whose properties can appear in the properties panel.
Base class for tracks which contain clips and plugins and can be added to Edit[s].
T emplace_back(T... args)
T is_pointer_v
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
#define jassertfalse
#define JUCE_DECLARE_WEAK_REFERENCEABLE(Class)
bool isAttached(InputDeviceInstance &instance)
Returns true if this input is assigned to a target.
juce::Array< std::pair< AudioTrack *, int > > getTargetTracksAndIndexes(InputDeviceInstance &instance)
Returns the AudioTracks and their indexes this instance is assigned to.
juce::Result clearFromTargets(InputDeviceInstance &instance, juce::UndoManager *um)
Removes this instance from all assigned targets.
bool hasErrors(const InputDeviceInstance::PreparedContext &pc)
Returns true if all the targets were fully prepared.
bool isOnTargetTrack(InputDeviceInstance &instance, const Track &track, int index)
Returns true if this instance is assigned to the given Track at the given index .
InputDeviceInstance::PreparedContext & append(InputDeviceInstance::PreparedContext &dest, InputDeviceInstance::PreparedContext &&src)
Appends a PreparedContent to another.
std::pair< std::vector< std::unique_ptr< InputDeviceInstance::RecordingContext > >, juce::StringArray > extract(InputDeviceInstance::PreparedContext &&pc)
Splits the PreparedContext in to valid RecordingContexts and an array of error messages.
InputDeviceInstance::Destination * getDestination(InputDeviceInstance &instance, const Track &track, int index)
Returns the destination if one has been assigned for the given arguments.
juce::Array< AudioTrack * > getTargetTracks(InputDeviceInstance &instance)
Returns the AudioTracks this instance is assigned to.
Represents a position in real-life time.
ID for objects of type EditElement - e.g.
Base class for classes that want to listen to an InputDevice and get a callback for each block of inp...
virtual void discardRecordings(EditItemID)
This is called when a recording is aborted so listeners should trash their temp data.
virtual void handleIncomingMidiMessage(const juce::MidiMessage &)
Override this to receive MIDI input from the device if it has any.
virtual void acceptInputBuffer(choc::buffer::ChannelArrayView< float >)
Override this to receive audio input from the device if it has any.
juce::ValueTree state
The state of this destination.
juce::CachedValue< bool > recordEnabled
Property to control whether the destination is armed to record or not.
const EditItemID targetID
The target for this destination, either an AudioTrack or ClipSlot.
const int targetIndex
The target index for this destination, if it is an AudioTrack.
juce::String getSelectableDescription() override
Subclasses must return a description of what they are.
InputDeviceInstance & input
The instance this belongs to.