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

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_ControlSurface.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
15{
16 ParameterSetting() noexcept;
17 void clear() noexcept;
18
19 char label[32] = "";
20 char valueDescription[32] = "";
21 float value = 0.0f;
22};
23
25{
26 MarkerSetting() noexcept;
27 void clear() noexcept;
28
29 char label[32] = "";
30 int number = 0;
31 bool absolute = false;
32};
33
34struct MidiID
35{
36 uint16_t manufacturer = 0;
37 uint16_t family = 0;
38 uint16_t model = 0;
39 uint32_t version = 0;
40};
41
42//==============================================================================
47{
48public:
50 ~ControlSurface() override;
51
52 //==============================================================================
53 /*
54 The following methods need to be implemented by the controller class, and will be
55 called by tracktion to tell it when stuff happens, such as midi messages arriving,
56 or the user doing things on the interface that should be reflected on the device.
57
58 Inside these callbacks, the device can call the methods specified further
59 down to tell tracktion about what it needs to do in response.
60 */
61
62 virtual void initialiseDevice ([[maybe_unused]] bool connect) {}
63 virtual void shutDownDevice() {}
64
65 // Given the MidiID from MIDI Identity Request SysEx message, return
66 // true if the ID is for a device the control surface understands
67 virtual bool wantsDevice (const MidiID&) { return false; }
68
69 // If the device communicates via OSC, then this tells the device the new settings
70 virtual void updateOSCSettings (int /*oscInputPort*/, int /*oscOutputPort*/, juce::String /*oscOutputAddr*/) {}
71
72 // most settings will be updated by the ExternalControllerManager, but this allows a device
73 // a chance to do some extra stuff when it needs to refresh itself
74 virtual void updateMiscFeatures() {}
75
76 // Called when the use changes the number of extenders
77 virtual void numExtendersChanged ([[maybe_unused]] int num, [[maybe_unused]] int main) {}
78
79 // called by tracktion when a midi message comes in from the controller. The
80 // subclass must translate this and call methods in this class accordingly to
81 // trigger whatever action the user is trying to do.
82 virtual void acceptMidiMessage ([[maybe_unused]] int idx, const juce::MidiMessage&) {}
83
84 // tells the device to move one of its faders.
85 // the channel number is the physical channel on the device, regardless of bank selection
86 // slider pos is 0 to 1.0
87 //
88 // If you override this, you must call parent class if you use pick mode
89 virtual void moveFader (int channelNum, float newSliderPos);
90
91 // tells the device to move the master faders, if it has them.
92 // slider pos is 0 to 1.0
93 virtual void moveMasterLevelFader (float newPos);
94
95 // tells the device to move a pan pot.
96 // the channel number is the physical channel on the device, regardless of bank selection
97 // pan is -1.0 to 1.0
98 virtual void movePanPot ([[maybe_unused]] int channelNum, [[maybe_unused]] float newPan);
99
100 // tells the device to move the master pan pot.
101 // pan is -1.0 to 1.0
102 virtual void moveMasterPanPot (float newPan);
103
104 virtual void moveAux ([[maybe_unused]] int channel, [[maybe_unused]] int auxNum, [[maybe_unused]] const char* bus, [[maybe_unused]] float newPos);
105
106 virtual void clearAux ([[maybe_unused]] int channel, [[maybe_unused]] int auxNum) {}
107
108 // the channel number is the physical channel on the device, regardless of bank selection
109 virtual void updateSoloAndMute ([[maybe_unused]] int channelNum, Track::MuteAndSoloLightState, [[maybe_unused]] bool isBright) {}
110
111 // count of number of tracks soloed
112 virtual void soloCountChanged ([[maybe_unused]] bool anySoloTracks) {}
113
114 // tells the device that playback has stopped or started, and it should turn its lights on
115 // accordingly.
116 virtual void playStateChanged ([[maybe_unused]] bool isPlaying) {}
117 virtual void recordStateChanged ([[maybe_unused]] bool isRecording) {}
118
119 // tells the device about automation read/write status changing.
120 virtual void automationReadModeChanged ([[maybe_unused]] bool isReading) {}
121 virtual void automationWriteModeChanged ([[maybe_unused]] bool isWriting) {}
122
123 // tells the device that the user has changed fader banks, so if the device has a bank number
124 // indicator, this tells it to update its contents.
125 //
126 // the newStartChannelNumber is the number of the first virtual channel now being mapped to the
127 // first physical fader channel on the device, starting from zero.
128 //
129 // the trackname array is the set of names for the tracks that now map onto the device's physical
130 // fader channels, so if it has a display that can show track names, it should update this.
131 virtual void faderBankChanged ([[maybe_unused]] int newStartChannelNumber, [[maybe_unused]] const juce::StringArray& trackNames) {}
132
133 // tells the device that a pad has changed colour
134 // colour 0: off
135 // colour 1 - 18: hue = (colour - 1) / 18
136 // state 0: solid
137 // state 1: blink
138 // state 2: pulse
139 virtual void padStateChanged ([[maybe_unused]] int channelNumber, [[maybe_unused]] int sceneNumber, [[maybe_unused]] int colourIdx, [[maybe_unused]] int state) {}
140
141 // Are any clips on the track playing.
142 virtual void clipsPlayingStateChanged ([[maybe_unused]] int channel, [[maybe_unused]] bool isPlaying) {}
143
144 // if the device has per-channel level meters, this should update one of them.
145 // the channel number is the physical channel on the device, regardless of bank selection
146 // if the channel is mono then l == r
147 // level is 0 to 1.0
148 virtual void channelLevelChanged ([[maybe_unused]] int channel, [[maybe_unused]] float l, [[maybe_unused]] float r) {}
149
150 // when a track is selected or deselected
151 virtual void trackSelectionChanged ([[maybe_unused]] int channel, [[maybe_unused]] bool isSelected) {}
152
153 virtual void trackRecordEnabled ([[maybe_unused]] int channel, [[maybe_unused]] bool isEnabled) {}
154
155 // if the device has a master level readout, this should update it.
156 virtual void masterLevelsChanged ([[maybe_unused]] float leftLevel,
157 [[maybe_unused]] float rightLevel) {}
158
159 // tells the device that the playback position has changed, so if it has a timecode
160 // display, it should update it.
161 //
162 // If isBarsBeats is true, barsOrHours is the bar number (starting from 1), beatsOrMinutes is
163 // the beat number (also from 1), ticksOrSeconds is the number of ticks (0 to 959) and millisecs is
164 // unused.
165 //
166 // If isBarsBeats is false, barsOrHours = hours, beatsOrMinutes = minutes, ticksOrSeconds = seconds, and
167 // millisecs is (surprise surprise) the milliseconds.
168 virtual void timecodeChanged ([[maybe_unused]] int barsOrHours,
169 [[maybe_unused]] int beatsOrMinutes,
170 [[maybe_unused]] int ticksOrSeconds,
171 [[maybe_unused]] int millisecs,
172 [[maybe_unused]] bool isBarsBeats,
173 [[maybe_unused]] bool isFrames) {}
174
175 // tells the device that the click has been turned on or off.
176 virtual void clickOnOffChanged ([[maybe_unused]] bool isClickOn) {}
177 // tells the device that snapping has been turned on or off.
178 virtual void snapOnOffChanged ([[maybe_unused]] bool isSnapOn) {}
179 // tells the device that looping has been turned on or off.
180 virtual void loopOnOffChanged ([[maybe_unused]] bool isLoopOn) {}
181
182 virtual void slaveOnOffChanged ([[maybe_unused]] bool isSlaving) {}
183 virtual void punchOnOffChanged ([[maybe_unused]] bool isPunching) {}
184 virtual void scrollOnOffChanged ([[maybe_unused]] bool isScroll) {}
185 virtual void undoStatusChanged ([[maybe_unused]] bool canUundo,
186 [[maybe_unused]] bool canReo) {}
187
188 // tells the device that one of the parameters has been changed.
189 //
190 // parameterNumber is the physical parameter number on the device, not the
191 // virtual one.
192 virtual void parameterChanged ([[maybe_unused]] int parameterNumber, [[maybe_unused]] const ParameterSetting& newValue);
193 virtual void clearParameter ([[maybe_unused]] int parameterNumber) {}
194
195 virtual void markerChanged ([[maybe_unused]] int parameterNumber, [[maybe_unused]] const MarkerSetting& newValue) {}
196 virtual void clearMarker ([[maybe_unused]] int parameterNumber) {}
197
198 virtual void auxBankChanged (int) {}
199
200 virtual bool wantsMessage (int, const juce::MidiMessage&) { return true; }
201 virtual bool eatsAllMessages() { return true; }
202 virtual bool canSetEatsAllMessages() { return false; }
203 virtual void setEatsAllMessages(bool) {}
204 virtual bool canChangeSelectedPlugin() { return true; }
205 virtual void currentSelectionChanged (juce::String) {}
206
208
209 virtual bool showingPluginParams() { return false; }
210 virtual bool showingMarkers() { return false; }
211 virtual bool showingTracks() { return true; }
212 virtual bool showingClipSlots() { return true; }
213
214 virtual void deleteController() {}
215 virtual void pluginBypass (bool) {}
216 virtual bool isPluginSelected (Plugin*) { return false; }
217
218 virtual void currentEditChanged (Edit* e) { edit = e; }
219
220 Edit* getEdit() const noexcept { return edit; }
221 TransportControl* getTransport() const noexcept { return edit != nullptr ? &edit->getTransport() : nullptr; }
222
223 virtual void currentSelectionManagerChanged (SelectionManager* sm) { selectionManager = sm; }
224 SelectionManager* getSelectionManager() { return selectionManager; }
225
226 //==============================================================================
227 /*
228 The following functions are called by the driver class to send commands
229 to tracktion..
230 */
231
232 // Don't send commands when safe recording. All callbacks check this,
233 // but your custom app code may not
234 bool isSafeRecording() const;
235
236 // Get the current bank offset. You shouldn't need to know this,
237 // just work with physical channel numbers. But it may come in useful
238 // rarely if you need to interact with the edit directly
239 int getMarkerBankOffset() const;
240 int getFaderBankOffset() const;
241 int getAuxBankOffset() const;
242 int getParamBankOffset() const;
243 int getClipSlotOffset() const;
244
245 // sends a MIDI message to the device's back-channel
246 void sendMidiCommandToController (int idx, const void* midiData, int numBytes);
247 void sendMidiCommandToController (int idx, const juce::MidiMessage&);
248
249 template <size_t size>
250 void sendMidiArray (int idx, const uint8_t (&rawData)[size]) { sendMidiCommandToController (idx, rawData, (int) size); }
251
252 // tells tracktion that the user has moved a fader.
253 // the channel number is the physical channel on the device, regardless of bank selection
254 // range 0 to 1.0 or -1.0 to 1.0
255 // delta false means absolute position, otherwise adjust by delta
256 void userMovedFader (int channelNum, float newFaderPosition, bool delta = false);
257
258 // tells tracktion that the user has moved a pan pot
259 // the channel number is the physical channel on the device, regardless of bank selection
260 // range -1.0 to 1.0
261 // delta false means absolute position, otherwise adjust by delta
262 void userMovedPanPot (int channelNum, float newPanPosition, bool delta = false);
263
264 // tells tracktion that the master fader has moved.
265 void userMovedMasterLevelFader (float newLevel, bool delta = false);
266 void userMovedMasterPanPot (float newLevel, bool delta = false);
267
268 void userMovedAux (int channelNum, int auxNum, float newPosition, bool delta = false);
269 void userPressedAux (int channelNum, int auxNum);
270 void userMovedQuickParam (float newLevel);
271
272 // these tell tracktion about buttons being pressed
273 void userPressedSolo (int channelNum);
274 void userPressedSoloIsolate (int channelNum);
275 void userPressedMute (int channelNum, bool muteVolumeControl);
276 void userSelectedTrack (int channelNum);
277 void userSelectedOneTrack (int channelNum);
278 void userSelectedClipInTrack (int channelNum);
279 void userSelectedPluginInTrack (int channelNum);
280 void userPressedRecEnable (int channelNum, bool enableEtoE);
281 void userLaunchedClip (int channelNum, int sceneNum);
282 void userStoppedClip (int channelNum);
283 void userLaunchedScene (int sceneNum);
284 void userPressedPlay();
285 void userPressedRecord();
286 void userPressedStop();
287 void userPressedHome(); // return to zero
288 void userPressedEnd();
289 void userPressedMarkIn();
290 void userPressedMarkOut();
291 void userPressedAutomationReading();
292 void userPressedAutomationWriting();
293 void userToggledBeatsSecondsMode();
294 void userPressedSave();
295 void userPressedSaveAs();
296 void userPressedArmAll();
297 void userPressedJumpToMarkIn();
298 void userPressedJumpToMarkOut();
299 void userPressedZoomIn();
300 void userPressedZoomOut();
301 void userPressedZoomToFit();
302 void userPressedCreateMarker();
303 void userPressedNextMarker();
304 void userPressedPreviousMarker();
305 void userPressedRedo();
306 void userPressedUndo();
307 void userPressedAbort();
308 void userPressedAbortRestart();
309 void userPressedCut();
310 void userPressedCopy();
311 void userPressedPaste (bool insert);
312 void userPressedDelete (bool marked);
313 void userPressedZoomFitToTracks();
314 void userPressedInsertTempoChange();
315 void userPressedInsertPitchChange();
316 void userPressedInsertTimeSigChange();
317 void userToggledVideoWindow();
318 void userToggledMixerWindow (bool fullscreen);
319 void userToggledMidiEditorWindow (bool fullscreen);
320 void userToggledTrackEditorWindow (bool zoomed);
321 void userToggledBrowserWindow();
322 void userToggledActionsWindow();
323 void userPressedUserAction (int);
324 void userPressedFreeze();
325
326 void userPressedClearAllSolo();
327 void userPressedClearAllMute();
328
329 void userToggledLoopOnOff();
330 void userToggledPunchOnOff();
331 void userToggledClickOnOff();
332 void userToggledSnapOnOff();
333 void userToggledSlaveOnOff();
334 void userToggledEtoE();
335 void userToggledScroll();
336
337 void userSkippedToNextMarkerLeft();
338 void userSkippedToNextMarkerRight();
339 void userNudgedLeft();
340 void userNudgedRight();
341 void userZoomedIn();
342 void userZoomedOut();
343 void userScrolledTracksUp();
344 void userScrolledTracksDown();
345 void userScrolledTracksLeft();
346 void userScrolledTracksRight();
347 void userZoomedTracksIn();
348 void userZoomedTracksOut();
349 void selectOtherObject (SelectableClass::Relationship, bool moveFromCurrentPlugin);
350 void muteOrUnmutePluginsInTrack();
351
352 // tells tracktion to move the fader bank up or down by the specified number of channels.
353 // After calling this, tracktion will call back the faderBankChanged() method to tell the
354 // device what its new state is.
355 void userChangedFaderBanks (int channelNumDelta);
356
357 // tells tracktion to move the pad bank up or down by the specified number of channels.
358 // After calling this, tracktion will call back the onPadStateChanged() method for each pad
359 // to tell the device what its new state is.
360 void userChangedPadBanks (int padDelta);
361
362 // tells tracktion to move the cursor.
363 //
364 // amount < 0 means moving backwards, amount > 0 forwards
365 // magnitude of about 1.0 is a 'normal' speed
366 void userMovedJogWheel (float amount);
367
368 // to allow it to auto-repeat, these tell tracktion when the left/right buttons are pressed and
369 // released.
370 // (try not to make sure the buttons aren't left stuck down!)
371 void userChangedRewindButton (bool isButtonDown);
372 void userChangedFastForwardButton (bool isButtonDown);
373
374 void userMovedParameterControl (int parameter, float newValue, bool delta = false);
375 void userPressedParameterControl (int paramNumber);
376
377 void userChangedParameterBank (int deltaParams);
378 void userChangedMarkerBank (int deltaMarkers);
379 void userPressedGoToMarker (int marker);
380
381 void userChangedAuxBank (int delta);
382 void userSetAuxBank (int num);
383
384 void updateDeviceState();
385
386 void redrawSelectedPlugin();
387 void redrawSelectedTracks();
388
389 Edit* getEditIfOnEditScreen() const;
390
391 //==============================================================================
394
395 // The number of multiple similar devices can be connected to add additional tracks
396 int supportedExtenders = 0;
397
398 // does this driver need to be able to send MIDI messages
399 bool needsMidiChannel = true;
400
401 // If the midi device always has the same name, set it and device will auto configure
402 juce::String midiChannelName;
403
404 // does this driver need to be able to send MIDI messages back to the
405 // controller as well as receive them?
406 bool needsMidiBackChannel = false;
407
408 // If the midi device always has the same name, set it and device will auto configure
409 juce::String midiBackChannelName;
410
411 // does this driver need to be able to communicate via OSC
412 bool needsOSCSocket = false;
413
414 // device wants MIDI clock
415 bool wantsClock = false;
416
417 // can be deleted
418 bool deletable = false;
419
420 // number of physical faders
421 int numberOfFaderChannels = 0;
422 int numCharactersForTrackNames = 0;
423
424 // number of physical pads per channel
425 int numberOfTrackPads = 0;
426
427 // is banking to the right allowed to show empty tracks
428 bool allowBankingOffEnd = false;
429
430 // number of labelled rotary dials that can control things like plugin parameters
431 bool wantsDummyParams = true;
432 int numParameterControls = 0;
433 int numCharactersForParameterLabels = 0;
434
435 // number of markers that can be displayed
436 int numMarkers = 0;
437 int numCharactersForMarkerLabels = 0;
438
439 // pick up mode. input value must cross current value before input is accepted
440 // useful for non motorized faders, so the don't jump when adjusted
441 bool pickUpMode = false;
442
443 // pad colors are limited to < 8
444 bool limitedPadColours = false;
445
446 int numAuxes = 0;
447 int numCharactersForAuxLabels = 0;
448 bool wantsAuxBanks = false;
449 bool followsTrackSelection = false;
450 AuxPosition auxMode = AuxPosition::byBus;
451
452 void setFollowsTrackSelection (bool f);
453
454 Engine& engine;
455 ExternalControllerManager& externalControllerManager;
456 ExternalController* owner = nullptr;
457
458 std::set<std::pair<int, int>> recentlyPressedPads;
459
460private:
461 enum ControlType
462 {
463 ctrlFader,
464 ctrlMasterFader,
465 ctrlMasterPanPot,
466 ctrlPan,
467 ctrlParam,
468 ctrlAux, // aux must be last because there can be several of them
469 };
470
471 struct PickUpInfo
472 {
473 bool pickedUp = false;
475 float lastOut = 0.0f;
476 };
477
478 Edit* edit = nullptr;
479 SelectionManager* selectionManager = nullptr;
480
481 void performIfNotSafeRecording (const std::function<void()>&);
482
483 bool pickedUp (ControlType, int index, float value);
484 bool pickedUp (ControlType, float value);
485
486 std::map<std::pair<ControlType, int>, PickUpInfo> pickUpMap;
487
489};
490
491}} // namespace tracktion { inline namespace engine
Base class for types of control surface.
juce::String deviceDescription
These values need to be set by the subclass.
juce::String getSelectableDescription() override
Subclasses must return a description of what they are.
The Tracktion Edit class!
TransportControl & getTransport() const noexcept
Returns the TransportControl which is used to stop/stop/position playback and recording.
The Engine is the central class for all tracktion sessions.
Keeps a list of external controllers and keeps them connected to the right MIDI in/out devices.
Acts as a holder for a ControlSurface object.
Base class for things that can be selected, and whose properties can appear in the properties panel.
Manages a list of items that are currently selected.
MuteAndSoloLightState
Determines the status of the mute and solo indicators.
Controls the transport of an Edit's playback.
connect
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
bool isRecording(EditPlaybackContext &epc)
Returns true if any inputs are currently recording.
typedef uint16_t