3 * Copyright (C) 2011-2021 Filipe Coelho <falktx@falktx.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #include "CarlaEngine.hpp"
19 #include "CarlaMathUtils.hpp"
20 #include "CarlaMIDI.h"
22 CARLA_BACKEND_START_NAMESPACE
24 // -----------------------------------------------------------------------
27 uint8_t EngineControlEvent::convertToMidiData(const uint8_t channel
, uint8_t data
[3]) const noexcept
31 case kEngineControlEventTypeNull
:
34 case kEngineControlEventTypeParameter
:
35 CARLA_SAFE_ASSERT_RETURN(param
< MAX_MIDI_VALUE
, 0);
37 data
[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE
| (channel
& MIDI_CHANNEL_BIT
));
39 if (MIDI_IS_CONTROL_BANK_SELECT(param
))
41 data
[1] = MIDI_CONTROL_BANK_SELECT
;
43 data
[2] = uint8_t(midiValue
);
45 data
[2] = uint8_t(carla_fixedValue
<float>(0.0f
, static_cast<float>(MAX_MIDI_VALUE
-1), normalizedValue
));
49 data
[1] = static_cast<uint8_t>(param
);
51 data
[2] = uint8_t(midiValue
);
53 data
[2] = uint8_t(carla_fixedValue
<float>(0.0f
, 1.0f
, normalizedValue
) * static_cast<float>(MAX_MIDI_VALUE
-1) + 0.5f
);
57 case kEngineControlEventTypeMidiBank
:
58 data
[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE
| (channel
& MIDI_CHANNEL_BIT
));
59 data
[1] = MIDI_CONTROL_BANK_SELECT
;
60 data
[2] = uint8_t(carla_fixedValue
<uint16_t>(0, MAX_MIDI_VALUE
-1, param
));
63 case kEngineControlEventTypeMidiProgram
:
64 data
[0] = static_cast<uint8_t>(MIDI_STATUS_PROGRAM_CHANGE
| (channel
& MIDI_CHANNEL_BIT
));
65 data
[1] = uint8_t(carla_fixedValue
<uint16_t>(0, MAX_MIDI_VALUE
-1, param
));
68 case kEngineControlEventTypeAllSoundOff
:
69 data
[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE
| (channel
& MIDI_CHANNEL_BIT
));
70 data
[1] = MIDI_CONTROL_ALL_SOUND_OFF
;
73 case kEngineControlEventTypeAllNotesOff
:
74 data
[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE
| (channel
& MIDI_CHANNEL_BIT
));
75 data
[1] = MIDI_CONTROL_ALL_NOTES_OFF
;
82 // -----------------------------------------------------------------------
85 void EngineEvent::fillFromMidiData(const uint8_t size
, const uint8_t* const data
, const uint8_t midiPortOffset
) noexcept
87 if (size
== 0 || data
== nullptr || data
[0] < MIDI_STATUS_NOTE_OFF
)
89 type
= kEngineEventTypeNull
;
95 channel
= uint8_t(MIDI_GET_CHANNEL_FROM_DATA(data
));
98 const uint8_t midiStatus(uint8_t(MIDI_GET_STATUS_FROM_DATA(data
)));
100 if (midiStatus
== MIDI_STATUS_CONTROL_CHANGE
)
102 CARLA_SAFE_ASSERT_RETURN(size
>= 2,);
104 type
= kEngineEventTypeControl
;
106 const uint8_t midiControl(data
[1]);
108 if (MIDI_IS_CONTROL_BANK_SELECT(midiControl
))
110 CARLA_SAFE_ASSERT_RETURN(size
>= 3,);
112 const uint8_t midiBank(data
[2]);
114 ctrl
.type
= kEngineControlEventTypeMidiBank
;
115 ctrl
.param
= midiBank
;
117 ctrl
.normalizedValue
= 0.0f
;
120 else if (midiControl
== MIDI_CONTROL_ALL_SOUND_OFF
)
122 ctrl
.type
= kEngineControlEventTypeAllSoundOff
;
125 ctrl
.normalizedValue
= 0.0f
;
128 else if (midiControl
== MIDI_CONTROL_ALL_NOTES_OFF
)
130 ctrl
.type
= kEngineControlEventTypeAllNotesOff
;
133 ctrl
.normalizedValue
= 0.0f
;
138 CARLA_SAFE_ASSERT_RETURN(size
>= 3,);
140 // ensures 0.0<->1.0 value range
141 const int8_t midiValue
= static_cast<int8_t>(carla_fixedValue
<uint8_t>(0, 127, data
[2]));
143 ctrl
.type
= kEngineControlEventTypeParameter
;
144 ctrl
.param
= midiControl
;
145 ctrl
.midiValue
= midiValue
;
146 ctrl
.normalizedValue
= float(midiValue
)/127.0f
;
147 ctrl
.handled
= false;
150 else if (midiStatus
== MIDI_STATUS_PROGRAM_CHANGE
)
152 CARLA_SAFE_ASSERT_RETURN(size
>= 2,);
154 type
= kEngineEventTypeControl
;
156 const uint8_t midiProgram(data
[1]);
158 ctrl
.type
= kEngineControlEventTypeMidiProgram
;
159 ctrl
.param
= midiProgram
;
161 ctrl
.normalizedValue
= 0.0f
;
166 type
= kEngineEventTypeMidi
;
168 midi
.port
= midiPortOffset
;
171 if (size
> EngineMidiEvent::kDataSize
)
174 std::memset(midi
.data
, 0, sizeof(uint8_t)*EngineMidiEvent::kDataSize
);
178 midi
.data
[0] = midiStatus
;
181 for (; i
< size
; ++i
)
182 midi
.data
[i
] = data
[i
];
183 for (; i
< EngineMidiEvent::kDataSize
; ++i
)
186 midi
.dataExt
= nullptr;
191 // -----------------------------------------------------------------------
194 EngineOptions::EngineOptions() noexcept
195 #ifdef CARLA_OS_LINUX
196 : processMode(ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
),
197 transportMode(ENGINE_TRANSPORT_MODE_JACK
),
199 : processMode(ENGINE_PROCESS_MODE_PATCHBAY
),
200 transportMode(ENGINE_TRANSPORT_MODE_INTERNAL
),
202 transportExtra(nullptr),
205 preferPluginBridges(false),
206 #if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
207 preferUiBridges(false),
209 preferUiBridges(true),
211 uisAlwaysOnTop(true),
212 pluginsAreStandalone(false),
216 maxParameters(MAX_DEFAULT_PARAMETERS
),
217 uiBridgesTimeout(4000),
218 audioBufferSize(512),
219 audioSampleRate(44100),
220 audioTripleBuffer(false),
221 audioDriver(nullptr),
222 audioDevice(nullptr),
244 resourceDir(nullptr),
245 clientNamePrefix(nullptr),
246 preventBadBehaviour(false),
254 EngineOptions::~EngineOptions() noexcept
256 if (audioDriver
!= nullptr)
258 delete[] audioDriver
;
259 audioDriver
= nullptr;
261 if (audioDevice
!= nullptr)
263 delete[] audioDevice
;
264 audioDevice
= nullptr;
266 if (pathAudio
!= nullptr)
271 if (pathMIDI
!= nullptr)
276 if (pathLADSPA
!= nullptr)
279 pathLADSPA
= nullptr;
281 if (pathDSSI
!= nullptr)
286 if (pathLV2
!= nullptr)
291 if (pathVST2
!= nullptr)
296 if (pathVST3
!= nullptr)
301 if (pathSF2
!= nullptr)
306 if (pathSFZ
!= nullptr)
311 if (pathJSFX
!= nullptr)
316 if (pathCLAP
!= nullptr)
321 if (binaryDir
!= nullptr)
326 if (resourceDir
!= nullptr)
328 delete[] resourceDir
;
329 resourceDir
= nullptr;
331 if (clientNamePrefix
!= nullptr)
333 delete[] clientNamePrefix
;
334 clientNamePrefix
= nullptr;
339 EngineOptions::Wine::Wine() noexcept
340 : executable(nullptr),
342 fallbackPrefix(nullptr),
347 EngineOptions::Wine::~Wine() noexcept
349 if (executable
!= nullptr)
352 executable
= nullptr;
355 if (fallbackPrefix
!= nullptr)
357 delete[] fallbackPrefix
;
358 fallbackPrefix
= nullptr;
363 // -----------------------------------------------------------------------
366 EngineTimeInfoBBT::EngineTimeInfoBBT() noexcept
375 beatsPerMinute(0.0) {}
377 EngineTimeInfoBBT::EngineTimeInfoBBT(const EngineTimeInfoBBT
& bbt
) noexcept
382 barStartTick(bbt
.barStartTick
),
383 beatsPerBar(bbt
.beatsPerBar
),
384 beatType(bbt
.beatType
),
385 ticksPerBeat(bbt
.ticksPerBeat
),
386 beatsPerMinute(bbt
.beatsPerMinute
) {}
388 void EngineTimeInfoBBT::clear() noexcept
398 beatsPerMinute
= 0.0;
401 // -----------------------------------------------------------------------
404 EngineTimeInfo::EngineTimeInfo() noexcept
410 void EngineTimeInfo::clear() noexcept
418 EngineTimeInfo::EngineTimeInfo(const EngineTimeInfo
& info
) noexcept
419 : playing(info
.playing
),
424 EngineTimeInfo
& EngineTimeInfo::operator=(const EngineTimeInfo
& info
) noexcept
426 playing
= info
.playing
;
429 bbt
.valid
= info
.bbt
.valid
;
430 bbt
.bar
= info
.bbt
.bar
;
431 bbt
.beat
= info
.bbt
.beat
;
432 bbt
.tick
= info
.bbt
.tick
;
433 bbt
.barStartTick
= info
.bbt
.barStartTick
;
434 bbt
.beatsPerBar
= info
.bbt
.beatsPerBar
;
435 bbt
.beatType
= info
.bbt
.beatType
;
436 bbt
.ticksPerBeat
= info
.bbt
.ticksPerBeat
;
437 bbt
.beatsPerMinute
= info
.bbt
.beatsPerMinute
;
442 bool EngineTimeInfo::compareIgnoringRollingFrames(const EngineTimeInfo
& timeInfo
, const uint32_t maxFrames
) const noexcept
444 if (timeInfo
.playing
!= playing
|| timeInfo
.bbt
.valid
!= bbt
.valid
)
449 if (carla_isNotEqual(timeInfo
.bbt
.beatsPerBar
, bbt
.beatsPerBar
))
451 if (carla_isNotEqual(timeInfo
.bbt
.beatsPerMinute
, bbt
.beatsPerMinute
))
455 // frame matches, nothing else to compare
456 if (timeInfo
.frame
== frame
)
459 // if we went back in time, so a case of reposition
460 if (frame
> timeInfo
.frame
)
463 // not playing, so don't bother checking transport
464 // assume frame changed, likely playback has stopped
468 // if we are within expected bounds, assume we are rolling normally
469 if (frame
+ maxFrames
<= timeInfo
.frame
)
472 // out of bounds, another reposition
476 bool EngineTimeInfo::operator==(const EngineTimeInfo
& timeInfo
) const noexcept
478 if (timeInfo
.playing
!= playing
|| timeInfo
.frame
!= frame
|| timeInfo
.bbt
.valid
!= bbt
.valid
)
482 if (carla_isNotEqual(timeInfo
.bbt
.beatsPerBar
, bbt
.beatsPerBar
))
484 if (carla_isNotEqual(timeInfo
.bbt
.beatsPerMinute
, bbt
.beatsPerMinute
))
489 bool EngineTimeInfo::operator!=(const EngineTimeInfo
& timeInfo
) const noexcept
491 return !operator==(timeInfo
);
494 // -----------------------------------------------------------------------
496 CARLA_BACKEND_END_NAMESPACE