A clip whose playback file can't be read, and that isn't going to generate one, no longer gets a node in the playback graph.
createNodeForAudioClip already returned no node for a null playback file; it now also returns none when the playback file is invalid and AudioClipBase::isGeneratingPlaybackFile() is false, i.e. the source has been deleted, moved or is unreadable and no proxy or source render is going to produce it. Such a clip is silent, as before, but it no longer appears in the graph at all, so code walking the graph won't find a node for it. A subclass that produces its playback file through a mechanism the engine doesn't know about should override needsRender()/requiresRenderingSource() so isGeneratingPlaybackFile() reports it, otherwise its clips will be dropped from the graph instead of waited for.
WaveNode::isReadyToProcess returns false until its file can be read, which is how a render waits for proxies. For a source that will never appear that wait never ended, so Renderer::renderToFile retried forever with no error. Not building the node keeps the wait for files that really are coming and removes it for files that aren't.
EngineBehaviour::newClipAdded is deprecated and replaced by EngineBehaviour::newClipCreated. It's now only called when a clip is created, and it's called later than before.
newClipAdded used to be called from ClipOwner::ClipList::newObjectAdded, i.e. whenever a clip object was added outside undo/redo. That included moves through Clip::moveTo and ClipSlot::setClip, duplicateClip, clipboard paste and split. Both callbacks are now made from insertClipWithState only, so those cases no longer call either of them. They're also called after the engine's own clip defaults have been applied rather than during addChild, so an override that checks Clip::getColour() == Clip::getDefaultColour() now sees the colour the engine has already set. Overriding a deprecated virtual doesn't warn, so an app that overrides newClipAdded compiles unchanged and silently stops being called for moves, paste and split.
Override newClipCreated instead. If you relied on being told about moves or copies, listen for the clip being added to its new owner instead, e.g. via ClipOwner::clipAddedOrRemoved or a ValueTree::Listener on the owner's state.
Applying the defaults for a new clip to clips that were only moved or copied reset settings the user had chosen, e.g. a launcher clip's loop and tempo-remap settings when it was duplicated. Creating a clip and moving or copying one are now separate operations, and the callback follows the same split.
duplicateClip now goes through the same insert path as everything else, so it respects EditLimits::maxClipsInTrack.
It used to append the copy to the track's state unconditionally. It can now return nullptr when the track is full, and shows a warning message through UIBehaviour::showWarningMessage. Code that dereferences the result without checking, or that duplicates in a loop, can hit both.
Check the returned pointer. If you need to duplicate without the limit or the message, copy the state yourself with EditItemID::remapIDs and add it to the owner's state.
duplicateClip bypassed the clip-limit check that every other insert applies.
core::hash_combine (and therefore core::hash and core::hash_range) uses a new mixing function, so every value it produces has changed.
The old function was close to affine, so combining values that differed by small amounts (e.g. sequential EditItemIDs) could produce identical results. This caused duplicate playback graph node IDs, which made nodes adopt state from the wrong node when the graph was rebuilt. Any hash values you have persisted or cached across runs (e.g. as cache keys or change-detection stamps) will no longer match the values produced by the new function. Within the engine, cached audio thumbnails will be regenerated and PatternGenerator note hashes stored in Edits are upgraded automatically on load.
Treat previously stored hash values as stale and regenerate them. If you need to recognise values produced by the old function, its formula was seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed * 65537u) + (seed / 3u).
Node IDs and state hashes need a mixer where every input bit affects the output, otherwise structurally similar subgraphs collide.
toBitSet (const juce::Array<Track*>&) now returns a bitset of only the tracks passed in.
Previously it ignored its argument and set a bit for every track in the Edit, so anything built from it addressed the whole Edit. Code that passed a subset of tracks - most visibly Renderer::Parameters::tracksToDo and Renderer::measureStatistics() - will now render or measure just that subset instead of everything.
Pass getAllTracks (edit) where the whole Edit really is wanted, or leave Renderer::Parameters::tracksToDo empty, which already means "all tracks".
The function used its argument only to reach the Edit and then looped over every track, which contradicted its documented behaviour and silently broke subset rendering. See issue #399.
Plugin has a new pure virtual method getBusses() which every subclass must implement.
Custom Plugin subclasses will no longer compile until they implement getBusses(). The default implementation of takesAudioInput() has also changed from ! isSynth() to ! isSynth() && ! getBusses().inputs.empty().
Implement getBusses() returning a Plugin::BusLayout describing the plugin's inputs and outputs. Helpers cover the common cases: BusLayout::singleStereoInOut() for a typical stereo effect, BusLayout::singleInOut (in, out) for other fixed layouts, BusLayout::singlePassThrough() for plugins that pass through whatever they're given, and {} for MIDI-only plugins.
Multichannel support requires every plugin to explicitly declare its channel requirements rather than the engine assuming stereo.
ExternalPlugin::getNumInputs() and getNumOutputs() have been removed.
Code calling these methods will no longer compile.
Use getBusses() for main-bus channel counts, or getAudioPluginInstance()->getTotalNumInputChannels() / getTotalNumOutputChannels() for totals. A deprecated getTotalNumInputChannels() shim exists on ExternalPlugin for the input side.
Part of the multichannel work: single input/output counts can't describe multi-bus plugins.
The DeviceManager per-channel stereo-pair API has been removed. This includes setWaveOutChannelsEnabled, setWaveInChannelsEnabled, setDeviceOutChannelStereo, setDeviceInChannelStereo, isDeviceOutChannelStereo, isDeviceInChannelStereo, isDeviceOutEnabled, isDeviceInEnabled, enableAllWaveInputs, enableAllWaveOutputs, setAllWaveInputsToStereoPair and setAllWaveOutputsToStereoPair.
Code managing device channels through these methods will no longer compile.
Use the new device-centric API: setDeviceEnabled (WaveInputDevice&/WaveOutputDevice&, bool), setDeviceNumChannels (device, numChannels), setAllWaveInputsToNumChannels(), setAllWaveOutputsToNumChannels() and getPossibleChannelGroupsForDevice(). Whole configurations can be saved/restored with the new wave device layout preset API (getCurrentWaveDeviceLayout(), applyWaveDeviceLayout() etc.).
Channel groupings are no longer limited to mono or stereo pairs; devices can now use groups of any size up to maxNumChannelsPerDevice.
WaveDeviceDescription has been restructured around the new ChannelConfiguration class. Its std::vector<ChannelIndex> channels member is now a ChannelConfiguration, and the constructors taking left/right channel indices or a ChannelIndex* array have been removed. ChannelIndex has moved to utilities/tracktion_ChannelConfiguration.h, and the free functions createDescriptionOfChannels() and createChannelSet() have been removed.
Custom EngineBehaviour::describeWaveDevices() implementations will no longer compile (the virtual's signature is unchanged, so the failure is in the body, not the override). Code using the removed free functions will also fail to compile.
Construct descriptions with WaveDeviceDescription (name, ChannelConfiguration, enabled) or WaveDeviceDescription::withNumChannels (name, firstChannelIndexInDevice, numChannels, enabled). Replace createDescriptionOfChannels() with ChannelConfiguration::getDescription() and createChannelSet() with ChannelConfiguration::toChannelSet().
Wave devices can now describe arbitrary channel layouts, not just mono/stereo.
InputDevice and OutputDevice now share a common IODevice base class. Their constructors no longer take a type string, getType() has been removed in favour of a new pure virtual getDeviceTypeDescription(), getAlias() has been replaced by getAliasOrName() / getAliasIfSet(), and OutputDevice::getName() is no longer virtual.
Custom device subclasses will no longer compile (constructor and getDeviceTypeDescription() requirements). Code overriding OutputDevice::getName() will silently stop being called.
Update constructors to the new (Engine&, name, deviceID) signatures and implement getDeviceTypeDescription(). Replace getAlias() calls with getAliasOrName() (falls back to the name) or getAliasIfSet() (may be empty).
The two device hierarchies duplicated a lot of state and behaviour; a common base simplifies the multichannel refactor.
WaveInputDevice::getChannels() and WaveOutputDevice::getChannels() now return const ChannelConfiguration& instead of const std::vector<ChannelIndex>&. isStereoPair(), setStereoPair(), WaveOutputDevice::getLeftChannel() and getRightChannel() are deprecated.
Code binding the old return type or using the deprecated methods will fail to compile or emit warnings.
Use getChannels().getNumChannels(), getChannels()[i].indexInDevice and setChannelConfiguration() instead.
Wave devices are no longer restricted to one or two channels.
RackInstance's two-channel API has been removed: the enum Channel { left, right }, the Channel-taking name/level setters and getters, and the leftInputGoesTo / rightInputGoesTo / leftOutputComesFrom / rightOutputComesFrom cached values and their associated parameters.
Code using the left/right rack routing API will no longer compile.
Use the new dynamic channel-mapping API: get/setNumInputChannels, get/setNumOutputChannels, getNumChannelMappings(), get/setInputMapping, get/setOutputMapping, getInput/OutputGainParam (int) etc. Existing saved edits are migrated automatically on load, so only code needs updating.
Racks now support arbitrary channel counts rather than fixed stereo routing.
AudioClipBase's left/right channel API has been removed: setLeftChannelActive, isLeftChannelActive, setRightChannelActive, isRightChannelActive and the protected activeChannels member. getActiveChannels() remains but is deprecated.
Code using these methods will no longer compile.
Use getSourceChannelConfiguration(), getActiveChannelConfiguration(), setActiveChannelConfiguration() and getOutputChannelConfiguration().
Clips can now enable/disable any subset of an arbitrary number of source channels.
LevelMeasurer::Client::maxNumChannels has been removed (channel storage is now dynamic), along with setLevelCache() and getLevelCache().
Code referencing the constant or the cache methods will no longer compile.
Use the per-channel access APIs, which are unchanged; storage grows to fit however many channels are fed to the meter.
Meters previously crashed when given more than the fixed number of channels; they now handle any channel count.
PluginWindowState::windowLocked has been removed, along with its saved property.
Code reading or writing windowLocked will no longer compile.
None - window locking has been removed as a concept. Implement it at the application level if needed.
The flag didn't belong in the engine and was barely used in practice.
RenderOptions::getStereo() and the stereo cached value have been removed.
Code querying or setting stereo/mono rendering through these will no longer compile.
Use getChannelConfiguration() / setChannelConfiguration().
Renders can now target any channel layout, not just mono or stereo.
UIBehaviour::showOkCancelAlertBox() and showYesNoCancelAlertBox() have been replaced by showOkCancelAlertBoxAsync() and showYesNoCancelAlertBoxAsync(), which take a completion callback instead of returning a result. showMenuAndCreatePlugin() is deprecated in favour of showMenuAndCreatePluginAsync().
Overrides of the old methods will no longer compile, and callers can no longer get a synchronous answer.
Override the Async versions and restructure calling code into continuation callbacks. The result semantics are unchanged (true = OK; 1 = yes, 2 = no, 0 = cancel).
The engine no longer runs modal loops, which block the message thread and can re-enter the engine in unexpected ways.
Several save/load and project APIs have become asynchronous or lost their built-in UI as part of removing modal loops from the engine:
EditFileOperations::save()andsaveAs()now returnvoidand take a completion callback (as doAppFunctions::saveEdit()/saveEditAs())Renderer::checkTargetFile()now takes a completion callback instead of returningboolProjectManager::createNewProjectInteractively()now returnsvoidand takes a callbackProjectManager::unpackArchiveAndAddToList()now requires the caller to supply the destination directory (the engine no longer shows a file chooser)Project::askAboutTempoDetect()has been removed
Code using the old synchronous signatures will no longer compile.
Pass completion callbacks and move any dependent logic into them. For tests, test_utilities::saveEditSync() provides a synchronous save. UI questions such as tempo detection are now the application's responsibility.
Modal loops inside the engine blocked the message thread and made embedding the engine in other applications fragile.
The free function yieldGUIThread() has been removed.
Code calling it will no longer compile.
None - delete the call. It was a Windows-only juce::Thread::yield() used from within modal loops, which no longer exist in the engine.
Antiquated API that made no sense once the modal loops were removed.
FallbackReader has been renamed to AudioFormatReaderWithTimeout, and AudioFileCache::createFallbackReader() to createAudioFormatReaderWithTimeout(). AudioFileCache::Reader::readSamples() now takes ChannelConfiguration arguments instead of juce::AudioChannelSet.
Code using the old names or signature will no longer compile. No compatibility alias is provided.
Rename the symbols and update readSamples() call sites to pass ChannelConfiguration (see ChannelConfiguration::fromChannelSet()).
The old name didn't describe what the class did, and the cache is now channel-layout aware.
SourceFileReference::setToDirectFileReference() and the file-taking setToProjectFileReference() overload have been replaced by a single setToFile (const juce::File&, PathStyle, bool allowProjectItems) method. getSourceProjectItemID() is now getSourceProjectItemRef(), returning a ProjectItemRef.
Code using the removed setters or the old getter will no longer compile.
Use setToFile() with PathStyle::chooseBest, alwaysRelative or alwaysAbsolute. Direct-file callers should pass allowProjectItems = false; project-item callers chooseBest, true.
A single entry point with an explicit path policy replaces several overlapping setters, and supports the smarter relative/absolute path selection needed for folder-based projects.
Exportable::ReferencedItem::itemID (a ProjectItemID) is now itemRef (a ProjectItemRef), and the pure virtual reassignReferencedItem() now takes a ProjectItemRef instead of a ProjectItemID. The EngineBehaviour::reassignReferencedItem() overloads changed the same way.
Implementations of these virtuals in custom Clip or Plugin subclasses will no longer compile (or, if not marked override, will silently stop being called).
Update the signatures to take ProjectItemRef. ProjectItemRef converts implicitly from ProjectItemID, and getProjectItemID() returns a std::optional<ProjectItemID> when the underlying ID is needed.
Referenced items must support path-based references for folder-based projects.
The engine's unit tests have been converted from juce::UnitTest to doctest.
Clients that ran the engine's self-tests through a juce::UnitTestRunner (with TRACKTION_UNIT_TESTS=1) will find them gone.
Run the tests with a doctest runner instead - see examples/TestRunner. The helpers in tracktion_TestUtilities.h retain their juce::UnitTest-taking overloads.
doctest allows test filtering, better reporting and running the engine tests without a JUCE test harness.
TracktionArchiveFile and ExportJob moved to legacy:: namespace.
Code using TracktionArchiveFile or ExportJob directly will no longer compile.
Qualify with legacy:: (e.g. legacy::TracktionArchiveFile). For new code, use ArchiveJob instead, which produces standard zip files. Use isArchive() and isLegacyArchive() to detect archive formats.
The legacy .trkarch format is replaced by standard zip archives. The old classes are preserved in a legacy:: namespace for reading existing archives.
ProjectSearchIndex, SearchOperation, and related APIs have been removed.
Code using ProjectSearchIndex, SearchOperation, createSearchForKeywords(), or Project::searchFor() will no longer compile. The header tracktion_ProjectSearchIndex.h has been deleted.
Use plain string matching or Levenshtein distance on project item names/descriptions.
The search infrastructure was tightly coupled to file-based project internals and not applicable to folder-based projects. Simpler alternatives are sufficient.
Edit::createEditForExamining(Engine&, ValueTree, EditRole, LoadContext*) overload is now [[deprecated]].
Deprecation warnings when calling this overload.
Use loadEditForExamining(ProjectManager&, ProjectItemRef) instead.
The new function works with both file-based and folder-based projects and handles source resolution correctly.
Project::getAllItemIDs() has been removed.
Code that calls getAllItemIDs() will no longer compile.
Use getAllProjectItemRefs() instead to iterate over project items.
The method was unused and redundant with getAllProjectItemRefs().
ProjectItemRef::getProjectItemID() now returns std::optional<ProjectItemID> instead of a bare ProjectItemID.
Code that chains method calls on the return value (e.g. .isValid(), .getProjectID(), .getRawID()) will no longer compile.
Use has_value() or bool conversion instead of .isValid(). Use -> to access members when the optional is known to contain a value (e.g. pid->getProjectID()). Use * to extract the value when passing to functions that expect ProjectItemID.
Returning std::optional makes the fallibility explicit at the type level, preventing accidental use of an invalid ProjectItemID.
Project::getProjectID() now returns ProjectID instead of int. ProjectItemID constructors and createNewID take ProjectID instead of int. ProjectManager::getProject() takes ProjectID instead of int.
Code that stores or passes project IDs as raw int values will no longer compile.
Wrap raw ints with ProjectID(myInt) and extract with .toInt(). For example: ProjectID pid = project.getProjectID(); instead of int pid = project.getProjectID();.
A strong type prevents accidental misuse of raw integers as project identifiers and makes the API self-documenting.
ProjectItemRef replaces raw ProjectItemID in many APIs. Project::getProjectItemRef(), getProjectItemFor(), removeProjectItem(), and getIndexOf() now use ProjectItemRef. ProjectItem::getProjectItemRef() returns const ProjectItemRef&. ProjectManager::getProjectItem() and findSourceFile() have new ProjectItemRef overloads.
Code that explicitly types return values as ProjectItemID from these methods will no longer compile.
ProjectItemRef has an implicit constructor from ProjectItemID, so most call sites compile unchanged. For return values, use auto or ProjectItemRef. If you need the old type, call .getProjectItemID() on the ref after checking isProjectItemID().
ProjectItemRef supports both ID-based references (file-based projects) and path-based references (folder-based projects) in a single type.
ProjectManager::createNewProject, createNewProjectInteractively, createNewProjectFromTemplate, and the TempProject constructor now accept a ProjectType parameter (ProjectType::fileBased or ProjectType::folderBased).
None for existing code — the parameter defaults to ProjectType::fileBased.
No changes required. Pass ProjectType::folderBased to create folder-based projects.
Enables creation of folder-based projects through the existing project creation APIs.
Project::findOrphanItems() has been deprecated in favour of findOrphanItemRefs().
Deprecation warnings when calling findOrphanItems().
Replace findOrphanItems() with findOrphanItemRefs(), which returns juce::Array<ProjectItemRef> instead of juce::Array<ProjectItem::Ptr>.
The new method returns ProjectItemRef values that work with both file-based and folder-based project backends.
AudioClipBase::melodyneProxy public member has been removed. Use the new getARAProxy() accessor instead.
Code directly accessing clip.melodyneProxy will no longer compile.
Replace clip.melodyneProxy with clip.getARAProxy(). The deprecated getMelodyneProxy() accessor is also available temporarily.
The direct public member has been replaced with an accessor to support generic ARA plugins beyond Melodyne.
AudioClipBase::showMelodyneWindow(), hideMelodyneWindow(), and melodyneConvertToMIDI() have been moved from member functions to free functions: showARAWindow(AudioClipBase&), hideARAWindow(AudioClipBase&), and araConvertToMIDI(AudioClipBase&).
Code calling clip.showMelodyneWindow() etc. as member functions will no longer compile.
Replace member calls with free function calls:
clip.showMelodyneWindow()→showARAWindow(clip)clip.hideMelodyneWindow()→hideARAWindow(clip)clip.melodyneConvertToMIDI()→araConvertToMIDI(clip)
Deprecated free-function wrappers showMelodyneWindow(clip), hideMelodyneWindow(clip), and melodyneConvertToMIDI(clip) are also available temporarily.
Moving these to free functions supports the generalised ARA plugin architecture.
MelodyneFileReader has been renamed to ARAFileReader. The header file has been renamed from tracktion_MelodyneFileReader.h to tracktion_ARAFileReader.h.
Direct #include of the old header path will fail. Code using the class name directly will get deprecation warnings.
A using MelodyneFileReader = ARAFileReader alias is provided for source compatibility. Update includes and type names when convenient.
The reader now supports any ARA-compatible plugin, not just Melodyne.
MelodyneNode has been renamed to ARANode. The header file has been renamed from tracktion_MelodyneNode.h to tracktion_ARANode.h.
Direct #include of the old header path will fail. Code referencing the class name directly will get deprecation warnings.
A using MelodyneNode = ARANode alias is provided for source compatibility. Update includes and type names when convenient.
The node now handles any ARA plugin playback, not just Melodyne.
AudioClipBase::isUsingMelodyne() has been renamed to isUsingARA().
Deprecation warnings. Code will still compile via the deprecated wrapper.
Replace isUsingMelodyne() with isUsingARA().
The method now reflects generic ARA plugin support.
TimeStretcher::Mode::melodyne has been renamed to TimeStretcher::Mode::ara. TimeStretcher::isMelodyne() has been renamed to isARA(). The getPossibleModes() parameter has been renamed from excludeMelodyne to excludeARA.
Code using TimeStretcher::Mode::melodyne will get deprecation warnings but will still compile. Code passing a named parameter excludeMelodyne will need updating.
Replace TimeStretcher::Mode::melodyne with TimeStretcher::Mode::ara, isMelodyne() with isARA(), and excludeMelodyne with excludeARA.
The timestretcher mode now supports any ARA plugin, not just Melodyne.
New TRACKTION_ENABLE_ARA config flag replaces the implicit Melodyne-only behaviour. ARA now requires explicit JUCE and SDK configuration.
ARA support is now opt-in via the TRACKTION_ENABLE_ARA preprocessor flag (defaults to 0/disabled). Projects that previously relied on implicit Melodyne support will need to update their build configuration.
To enable ARA support:
- Define
TRACKTION_ENABLE_ARA=1in your build - Enable
JUCE_PLUGINHOST_ARA=1in your JUCE project settings - Call
juce_set_ara_sdk_path()in your CMake configuration, pointing to ARA SDK version 2.3 or later
ARA support is now a generic, configurable feature rather than being tied to a single plugin. The explicit SDK dependency ensures correct versioning and compatibility.
AutomationCurve has been restructured. It now only stores the parameter as a string and not a reference.
Many functions now need a AutomatableParameter&, TempoSequence& or juce::UndoManager* as additional arguments.
These extra parameters are usually within easy reach at the call site. You can use the new getTempoSequence (Type&) and getUndoManager_p (Type&) to easily get these from a bunch of objects.
This decoupling enables AutomationCurve to be used in more places and supports clip automation and AutomationClips.
The Edit constructor can now throw exceptions in rare cases. E.g. if it's being constructed on the message thread which is blocked.
You may need to catch this exception.
It's generally safer to use Edit::createEdit as this will catch the exception and just return a nullptr.
Previously if the above scenario happened, the Edit would just be left in an invalid (likely to crash) state. Ths stops that happening.
The APIs around InputDevice and InputDeviceInstance have been simplified to work more with EditItemIDs.
Some existing code might not compile.
Update to new APIs in InputDeviceInstance: prepareToRecord, startRecording and stopRecording along with other property setters/getters.
There are also some non-member functions at the bottom of tracktion_InputDevice.h which may replicate the old APIs (but with non-member arguments).
This change was required to implement ClipSlot recording and async-record-stopping.
InputDevice::setEndToEnd has been replaced by MonitorMode.
Code won't compile.
Use the more explicit an clear get/setMonitorMode.
MonitorMode provides a way to only enable audible input whilst record is enabled.
An Edit constructor has been removed.
Code using that constructor will fail to compile.
Use the new constructor that takes an Edit::Options or an EditRole.
The behaviour old constructor was ambiguous and this cleans up the API.
Removed the float newValue parameter to AutomatableParameter::currentValueChanged (AutomatableParameter&).
Existing code overriding the function will no longer compile.
Remove the float newValue argument and use AutomatoableParameter::getCurrentValue() instead.
This simplifies the API a bit as with Modifiers, the current value gets remapped a lot. Always getting the value via getCurrentValue, getCurrentExplicitValue, getCurrentBaseValue, getCurrentModifierValue avoids ambiguity about what newValue means.
Removed DeviceManager::CPUUsageListener
Existing code using it will no longer compile.
Use getCPUStatistics()/restCPUStatistics() instead.
The old listener code wasn't thread safe. The new funtion returns more information and is wait-free from the audio side.
CurveEditor::getCurrentLineColour() is no longer const
Code implementing CurveEditor::getCurrentLineColour() will fail to compile.
Remove const qualifier in sub classes.
Better API design.
Removed the TRACKTION_ENABLE_REALTIME_TIMESTRETCHING option.
Most code should be unaffected as it was enabled by default anyway. Along with this are the setUsesTimestretchedPreview/usesTimestretchedPreview AudioClipBase functions. Use setUsesProxy instead now for the same effect.
None.
This was always a temporary flag used to transition to this new feature.
Added a new ContainerClip type. To facilitate this, a new ClipOwner class has been created.
You may need to fix code which passes Tracks to functions, passing in a ClipOwner subclass like a ClipTrack instead.
None.
The changes required should be small but enable this new feature.
Removed the fixed buffer size requirement in HostedAudioDeviceInterface for using the Engine inside a plugin.
You may need to fix code which set the value of this member.
None.
With the audio playback rewite it's no longer required to have a fixed block size so we don't need to add a block of latency when using the Engine inside a plugin.
Removed the TracktionThumbnail class.
If you were using the default thumbnails of Tracktion Engine, these will now be juce::AudioThumbnails and so won't be anti-aliased and appear more jagged.
Take a copy of the TracktionThumbnail class from the history and add it to your own project.
Override the new UIBehaviour::createAudioThumbnail function to return instances of it to get back the old behaviour.
TracktionThumbnail never really should have been included in the Engine. We needed a way to support multiple thumbnail types in Waveform and in doing so broke all the dependancies on TracktionThumbnail so it seemed cleaner to remove it completely. It's simple to get back the old behaviour but also means it's now a lot easier to use your own thumbnail classes if desired.
Changed the minimum version of JUCE supported to 7 on commit of October 22.
If your project uses an eariler version of JUCE it may fail to compile.
Use the commit of JUCE pointed at in the modules/juce Git submodule. This is guaranteed to work.
There have been many breaking changes in JUCE recently and it is no longer feasible to support multiple versions. We aim to always be compatible with the tip of juce/develop in order to take advantage of the latest fixes and features.
Removed EngineBehaviour::getMaxNumMasterPlugins and static Edit constants.
Code relying on the Edit members or implementing the EngineBehaviour method will no longer compile.
Update to implement EngineBehaviour::getEditLimits() and call this instead of the static methods.
This enables a single customisation point for these properties and avoids them having static values.
The old AudioNode based engine has been replaced by a new tracktion_graph based engine.
Some classes will no longer be publicly available such as PlayHead, AudioNode nodes etc.
You'll have to update your code to use the new APIs. In most cases this shouldn't be a problem as this is a move to remove the public nature of the engine, the higher level APIs that you are using should stay the same. Some arguments to classes such as Plugin have changed to remove dependancy on playback specific classed. If you really need to use the old engine, see the archive/old_engine branch.
The move to the new engine greatly improves CPU performance, especially with multiple threads and fixes PDC in a lot of obscure cases such as track to track routing and bussing.
The PluginWindowConnection class has been removed to simplify the process of creating plugin windows and connecting them to a PluginWindowState.
PluginWindowState now takes an Edit in its constructor rather than an Engine. The UIBehaviour method createPluginWindowConnection has been changed to createPluginWindow which now simply needs to create and return a Component which will be used to show your plugin UI.
You'll have to update your code to use the new APIs.
The old PluginWindowConnection class was an attempt at communicating via IPC for sandboxed plugins. However, this is no longer necessary as it's possible to encapsulate a sandboxed plugin completely within the juice::AudioProcessor classes. The new API is much simpler for the standard use cases.