11namespace tracktion {
inline namespace engine
15 : edit (e), state (v), editState (e.state)
17 editState.addListener (
this);
18 callBlocking ([
this] { edit.engine.getDeviceManager().addChangeListener (
this); });
21EditInputDevices::~EditInputDevices()
23 cancelPendingUpdate();
24 edit.engine.getDeviceManager().removeChangeListener (
this);
25 removeNonExistantInputDeviceStates();
28int EditInputDevices::getMaxNumInputs()
const
33static bool isForDevice (
const juce::ValueTree& v,
const InputDevice& d,
bool fallbackToNameCheck)
35 auto typeProp = v.getPropertyPointer (IDs::type);
37 if (d.getDeviceType() == InputDevice::DeviceType::trackWaveDevice)
38 return typeProp !=
nullptr && *typeProp ==
"audio" && v[IDs::sourceTrack] == d.getName();
40 if (d.getDeviceType() == InputDevice::DeviceType::trackMidiDevice)
41 return typeProp !=
nullptr && *typeProp ==
"MIDI" && v[IDs::sourceTrack] == d.getName();
43 if (v[IDs::deviceID] == d.getDeviceID())
46 return fallbackToNameCheck && v[IDs::name] == d.getName();
51 for (
const auto& v : parent)
52 if (isForDevice (v, d, false))
55 for (
const auto& v : parent)
56 if (isForDevice (v, d, true))
67bool EditInputDevices::isInputDeviceAssigned (
const InputDevice& d)
69 return findDeviceState (state, d).
isValid();
74 for (
auto idi : getDevicesForTargetTrack (at))
75 [[ maybe_unused]] auto res = idi->removeTarget (at.itemID, um);
78static bool isInstanceRecording (InputDeviceInstance* idi)
80 if (idi->isRecording())
82 idi->edit.engine.getUIBehaviour().showWarningMessage (
TRANS(
"Can't change tracks whilst recording is active"));
89void EditInputDevices::clearInputsOfDevice (AudioTrack& at,
const InputDevice& d,
juce::UndoManager* um)
91 for (
auto idi : getDevicesForTargetTrack (at))
92 if (&idi->owner == &d)
93 if (! isInstanceRecording (idi))
94 [[ maybe_unused ]] auto res = idi->removeTarget (at.itemID, um);
97InputDeviceInstance* EditInputDevices::getInputInstance (
const AudioTrack& at,
int index)
const
99 for (
auto idi : getDevicesForTargetTrack (at))
110 for (
auto idi : edit.getAllInputDevices())
111 if (idi->getTargets().contains (at.itemID))
117juce::ValueTree EditInputDevices::getInstanceStateForInputDevice (
const InputDevice& d)
119 if (
auto v = findDeviceState (state, d); v.
isValid())
122 v.setProperty (IDs::deviceID, d.getDeviceID(),
nullptr);
123 v.setProperty (IDs::name, d.getName(),
nullptr);
129 if (d.getDeviceType() == InputDevice::DeviceType::trackWaveDevice)
131 v.setProperty (IDs::sourceTrack, EditItemID::fromString (d.getName()),
nullptr);
132 v.setProperty (IDs::type,
"audio",
nullptr);
134 else if (d.getDeviceType() == InputDevice::DeviceType::trackMidiDevice)
136 v.setProperty (IDs::sourceTrack, EditItemID::fromString (d.getName()),
nullptr);
137 v.setProperty (IDs::type,
"MIDI",
nullptr);
141 v.setProperty (IDs::deviceID, d.getDeviceID(),
nullptr);
142 v.setProperty (IDs::name, d.getName(),
nullptr);
145 state.addChild (v, -1,
nullptr);
150void EditInputDevices::removeNonExistantInputDeviceStates()
152 auto& dm = edit.engine.getDeviceManager();
155 for (
auto& d : dm.midiInputs)
156 devices.add (d.get());
160 if (! edit.isLoading())
164 if (
auto* wid = &at->getWaveInputDevice())
165 if (wid->isEnabled())
168 if (
auto* mid = &at->getMidiInputDevice())
169 if (mid->isEnabled())
176 for (
auto* d : devices)
177 if (isForDevice (v, *d, true))
183 for (
int i = state.getNumChildren(); --i >= 0;)
184 if (! isDevicePresent (state.getChild(i)))
185 state.removeChild (i,
nullptr);
188void EditInputDevices::addTrackDeviceInstanceToContext (
const juce::ValueTree& v)
const
190 if (
auto*
id = getTrackDeviceForState (v))
192 if (
auto* epc = edit.getCurrentPlaybackContext())
194 if (isTrackInputDeviceMIDI (v))
195 epc->addMidiInputDeviceInstance (*
id);
197 epc->addWaveInputDeviceInstance (*
id);
202void EditInputDevices::removeTrackDeviceInstanceToContext (
const juce::ValueTree& v)
const
204 if (
auto*
id = getTrackDeviceForState (v))
205 if (
auto* epc = edit.getCurrentPlaybackContext())
206 epc->removeInstanceForDevice (*
id);
209InputDevice* EditInputDevices::getTrackDeviceForState (
const juce::ValueTree& v)
const
211 auto trackID = EditItemID::fromProperty (v, IDs::sourceTrack);
213 if (trackID.isValid())
215 if (
auto at = findAudioTrackForID (edit, trackID))
217 if (isTrackInputDeviceMIDI (v))
218 return &at->getMidiInputDevice();
220 return &at->getWaveInputDevice();
229 removeNonExistantInputDeviceStates();
232void EditInputDevices::handleAsyncUpdate()
234 removeNonExistantInputDeviceStates();
239 jassert (v.hasType (IDs::INPUTDEVICE));
240 return v.hasProperty (IDs::sourceTrack);
246 if (c.hasType (IDs::INPUTDEVICE) && isTrackDevice (c))
247 addTrackDeviceInstanceToContext (c);
253 if (c.hasType (IDs::INPUTDEVICE) && isTrackDevice (c))
254 removeTrackDeviceInstanceToContext (c);
256 if (TrackList::isTrack (c))
257 triggerAsyncUpdate();
void addArray(const Type *elementsToAdd, int numElementsToAdd)
void add(const ElementType &newElement)
bool isValid() const noexcept
const String & toString() const noexcept
bool isValid() const noexcept
#define TRANS(stringLiteral)
juce::Array< AudioTrack * > getAudioTracks(const Edit &edit)
Returns all the AudioTracks in an Edit.
bool isOnTargetTrack(InputDeviceInstance &instance, const Track &track, int index)
Returns true if this instance is assigned to the given Track at the given index .