mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-09 23:34:20 +00:00
VSTPluginFormat: Extract headless plugin format type
This commit is contained in:
parent
edcc699aa8
commit
dd5ced96c1
11 changed files with 3330 additions and 3136 deletions
|
|
@ -1,315 +0,0 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/** Structure for VST speaker mappings
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
struct SpeakerMappings : private AudioChannelSet // (inheritance only to give easier access to items in the namespace)
|
||||
{
|
||||
/** Structure describing a mapping */
|
||||
struct Mapping
|
||||
{
|
||||
int32 vst2;
|
||||
ChannelType channels[13];
|
||||
|
||||
bool matches (const Array<ChannelType>& chans) const noexcept
|
||||
{
|
||||
auto n = static_cast<int> (sizeof (channels) / sizeof (ChannelType));
|
||||
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
if (channels[i] == unknown) return (i == chans.size());
|
||||
if (i == chans.size()) return (channels[i] == unknown);
|
||||
|
||||
if (channels[i] != chans.getUnchecked (i))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
static AudioChannelSet vstArrangementTypeToChannelSet (int32 arr, int fallbackNumChannels)
|
||||
{
|
||||
if (arr == Vst2::kSpeakerArrEmpty) return AudioChannelSet::disabled();
|
||||
else if (arr == Vst2::kSpeakerArrMono) return AudioChannelSet::mono();
|
||||
else if (arr == Vst2::kSpeakerArrStereo) return AudioChannelSet::stereo();
|
||||
else if (arr == Vst2::kSpeakerArr30Cine) return AudioChannelSet::createLCR();
|
||||
else if (arr == Vst2::kSpeakerArr30Music) return AudioChannelSet::createLRS();
|
||||
else if (arr == Vst2::kSpeakerArr40Cine) return AudioChannelSet::createLCRS();
|
||||
else if (arr == Vst2::kSpeakerArr50) return AudioChannelSet::create5point0();
|
||||
else if (arr == Vst2::kSpeakerArr51) return AudioChannelSet::create5point1();
|
||||
else if (arr == Vst2::kSpeakerArr60Cine) return AudioChannelSet::create6point0();
|
||||
else if (arr == Vst2::kSpeakerArr61Cine) return AudioChannelSet::create6point1();
|
||||
else if (arr == Vst2::kSpeakerArr60Music) return AudioChannelSet::create6point0Music();
|
||||
else if (arr == Vst2::kSpeakerArr61Music) return AudioChannelSet::create6point1Music();
|
||||
else if (arr == Vst2::kSpeakerArr70Music) return AudioChannelSet::create7point0();
|
||||
else if (arr == Vst2::kSpeakerArr70Cine) return AudioChannelSet::create7point0SDDS();
|
||||
else if (arr == Vst2::kSpeakerArr71Music) return AudioChannelSet::create7point1();
|
||||
else if (arr == Vst2::kSpeakerArr71Cine) return AudioChannelSet::create7point1SDDS();
|
||||
else if (arr == Vst2::kSpeakerArr40Music) return AudioChannelSet::quadraphonic();
|
||||
|
||||
for (const Mapping* m = getMappings(); m->vst2 != Vst2::kSpeakerArrEmpty; ++m)
|
||||
{
|
||||
if (m->vst2 == arr)
|
||||
{
|
||||
AudioChannelSet s;
|
||||
|
||||
for (int i = 0; m->channels[i] != 0; ++i)
|
||||
s.addChannel (m->channels[i]);
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
return AudioChannelSet::discreteChannels (fallbackNumChannels);
|
||||
}
|
||||
|
||||
static AudioChannelSet vstArrangementTypeToChannelSet (const Vst2::VstSpeakerArrangement& arr)
|
||||
{
|
||||
return vstArrangementTypeToChannelSet (arr.type, arr.numChannels);
|
||||
}
|
||||
|
||||
static int32 channelSetToVstArrangementType (AudioChannelSet channels)
|
||||
{
|
||||
if (channels == AudioChannelSet::disabled()) return Vst2::kSpeakerArrEmpty;
|
||||
else if (channels == AudioChannelSet::mono()) return Vst2::kSpeakerArrMono;
|
||||
else if (channels == AudioChannelSet::stereo()) return Vst2::kSpeakerArrStereo;
|
||||
else if (channels == AudioChannelSet::createLCR()) return Vst2::kSpeakerArr30Cine;
|
||||
else if (channels == AudioChannelSet::createLRS()) return Vst2::kSpeakerArr30Music;
|
||||
else if (channels == AudioChannelSet::createLCRS()) return Vst2::kSpeakerArr40Cine;
|
||||
else if (channels == AudioChannelSet::create5point0()) return Vst2::kSpeakerArr50;
|
||||
else if (channels == AudioChannelSet::create5point1()) return Vst2::kSpeakerArr51;
|
||||
else if (channels == AudioChannelSet::create6point0()) return Vst2::kSpeakerArr60Cine;
|
||||
else if (channels == AudioChannelSet::create6point1()) return Vst2::kSpeakerArr61Cine;
|
||||
else if (channels == AudioChannelSet::create6point0Music()) return Vst2::kSpeakerArr60Music;
|
||||
else if (channels == AudioChannelSet::create6point1Music()) return Vst2::kSpeakerArr61Music;
|
||||
else if (channels == AudioChannelSet::create7point0()) return Vst2::kSpeakerArr70Music;
|
||||
else if (channels == AudioChannelSet::create7point0SDDS()) return Vst2::kSpeakerArr70Cine;
|
||||
else if (channels == AudioChannelSet::create7point1()) return Vst2::kSpeakerArr71Music;
|
||||
else if (channels == AudioChannelSet::create7point1SDDS()) return Vst2::kSpeakerArr71Cine;
|
||||
else if (channels == AudioChannelSet::quadraphonic()) return Vst2::kSpeakerArr40Music;
|
||||
|
||||
if (channels == AudioChannelSet::disabled())
|
||||
return Vst2::kSpeakerArrEmpty;
|
||||
|
||||
auto chans = channels.getChannelTypes();
|
||||
|
||||
for (auto* m = getMappings(); m->vst2 != Vst2::kSpeakerArrEmpty; ++m)
|
||||
if (m->matches (chans))
|
||||
return m->vst2;
|
||||
|
||||
return Vst2::kSpeakerArrUserDefined;
|
||||
}
|
||||
|
||||
static void channelSetToVstArrangement (const AudioChannelSet& channels, Vst2::VstSpeakerArrangement& result)
|
||||
{
|
||||
result.type = channelSetToVstArrangementType (channels);
|
||||
result.numChannels = channels.size();
|
||||
|
||||
for (int i = 0; i < result.numChannels; ++i)
|
||||
{
|
||||
auto& speaker = result.speakers[i];
|
||||
|
||||
zeromem (&speaker, sizeof (Vst2::VstSpeakerProperties));
|
||||
speaker.type = getSpeakerType (channels.getTypeOfChannel (i));
|
||||
}
|
||||
}
|
||||
|
||||
/** Class to hold a speaker configuration */
|
||||
class VstSpeakerConfigurationHolder
|
||||
{
|
||||
public:
|
||||
VstSpeakerConfigurationHolder()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
VstSpeakerConfigurationHolder (const Vst2::VstSpeakerArrangement& vstConfig)
|
||||
{
|
||||
operator= (vstConfig);
|
||||
}
|
||||
|
||||
VstSpeakerConfigurationHolder (const VstSpeakerConfigurationHolder& other)
|
||||
{
|
||||
operator= (other.get());
|
||||
}
|
||||
|
||||
VstSpeakerConfigurationHolder (VstSpeakerConfigurationHolder&& other)
|
||||
: storage (std::move (other.storage))
|
||||
{
|
||||
other.clear();
|
||||
}
|
||||
|
||||
VstSpeakerConfigurationHolder (const AudioChannelSet& channels)
|
||||
{
|
||||
auto numberOfChannels = channels.size();
|
||||
Vst2::VstSpeakerArrangement& dst = *allocate (numberOfChannels);
|
||||
|
||||
dst.type = channelSetToVstArrangementType (channels);
|
||||
dst.numChannels = numberOfChannels;
|
||||
|
||||
for (int i = 0; i < dst.numChannels; ++i)
|
||||
{
|
||||
Vst2::VstSpeakerProperties& speaker = dst.speakers[i];
|
||||
|
||||
zeromem (&speaker, sizeof (Vst2::VstSpeakerProperties));
|
||||
speaker.type = getSpeakerType (channels.getTypeOfChannel (i));
|
||||
}
|
||||
}
|
||||
|
||||
VstSpeakerConfigurationHolder& operator= (const VstSpeakerConfigurationHolder& vstConfig) { return operator= (vstConfig.get()); }
|
||||
VstSpeakerConfigurationHolder& operator= (const Vst2::VstSpeakerArrangement& vstConfig)
|
||||
{
|
||||
Vst2::VstSpeakerArrangement& dst = *allocate (vstConfig.numChannels);
|
||||
|
||||
dst.type = vstConfig.type;
|
||||
dst.numChannels = vstConfig.numChannels;
|
||||
|
||||
for (int i = 0; i < dst.numChannels; ++i)
|
||||
dst.speakers[i] = vstConfig.speakers[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
VstSpeakerConfigurationHolder& operator= (VstSpeakerConfigurationHolder && vstConfig)
|
||||
{
|
||||
storage = std::move (vstConfig.storage);
|
||||
vstConfig.clear();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Vst2::VstSpeakerArrangement& get() const { return *storage.get(); }
|
||||
|
||||
private:
|
||||
JUCE_LEAK_DETECTOR (VstSpeakerConfigurationHolder)
|
||||
|
||||
HeapBlock<Vst2::VstSpeakerArrangement> storage;
|
||||
|
||||
Vst2::VstSpeakerArrangement* allocate (int numChannels)
|
||||
{
|
||||
auto arrangementSize = (size_t) (jmax (8, numChannels) - 8) * sizeof (Vst2::VstSpeakerProperties)
|
||||
+ sizeof (Vst2::VstSpeakerArrangement);
|
||||
|
||||
storage.malloc (1, arrangementSize);
|
||||
return storage.get();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
Vst2::VstSpeakerArrangement& dst = *allocate (0);
|
||||
|
||||
dst.type = Vst2::kSpeakerArrEmpty;
|
||||
dst.numChannels = 0;
|
||||
}
|
||||
};
|
||||
|
||||
static const Mapping* getMappings() noexcept
|
||||
{
|
||||
static const Mapping mappings[] =
|
||||
{
|
||||
{ Vst2::kSpeakerArrMono, { centre, unknown } },
|
||||
{ Vst2::kSpeakerArrStereo, { left, right, unknown } },
|
||||
{ Vst2::kSpeakerArrStereoSurround, { leftSurround, rightSurround, unknown } },
|
||||
{ Vst2::kSpeakerArrStereoCenter, { leftCentre, rightCentre, unknown } },
|
||||
{ Vst2::kSpeakerArrStereoSide, { leftSurroundRear, rightSurroundRear, unknown } },
|
||||
{ Vst2::kSpeakerArrStereoCLfe, { centre, LFE, unknown } },
|
||||
{ Vst2::kSpeakerArr30Cine, { left, right, centre, unknown } },
|
||||
{ Vst2::kSpeakerArr30Music, { left, right, surround, unknown } },
|
||||
{ Vst2::kSpeakerArr31Cine, { left, right, centre, LFE, unknown } },
|
||||
{ Vst2::kSpeakerArr31Music, { left, right, LFE, surround, unknown } },
|
||||
{ Vst2::kSpeakerArr40Cine, { left, right, centre, surround, unknown } },
|
||||
{ Vst2::kSpeakerArr40Music, { left, right, leftSurround, rightSurround, unknown } },
|
||||
{ Vst2::kSpeakerArr41Cine, { left, right, centre, LFE, surround, unknown } },
|
||||
{ Vst2::kSpeakerArr41Music, { left, right, LFE, leftSurround, rightSurround, unknown } },
|
||||
{ Vst2::kSpeakerArr50, { left, right, centre, leftSurround, rightSurround, unknown } },
|
||||
{ Vst2::kSpeakerArr51, { left, right, centre, LFE, leftSurround, rightSurround, unknown } },
|
||||
{ Vst2::kSpeakerArr60Cine, { left, right, centre, leftSurround, rightSurround, surround, unknown } },
|
||||
{ Vst2::kSpeakerArr60Music, { left, right, leftSurround, rightSurround, leftSurroundRear, rightSurroundRear, unknown } },
|
||||
{ Vst2::kSpeakerArr61Cine, { left, right, centre, LFE, leftSurround, rightSurround, surround, unknown } },
|
||||
{ Vst2::kSpeakerArr61Music, { left, right, LFE, leftSurround, rightSurround, leftSurroundRear, rightSurroundRear, unknown } },
|
||||
{ Vst2::kSpeakerArr70Cine, { left, right, centre, leftSurround, rightSurround, topFrontLeft, topFrontRight, unknown } },
|
||||
{ Vst2::kSpeakerArr70Music, { left, right, centre, leftSurround, rightSurround, leftSurroundRear, rightSurroundRear, unknown } },
|
||||
{ Vst2::kSpeakerArr71Cine, { left, right, centre, LFE, leftSurround, rightSurround, topFrontLeft, topFrontRight, unknown } },
|
||||
{ Vst2::kSpeakerArr71Music, { left, right, centre, LFE, leftSurround, rightSurround, leftSurroundRear, rightSurroundRear, unknown } },
|
||||
{ Vst2::kSpeakerArr80Cine, { left, right, centre, leftSurround, rightSurround, topFrontLeft, topFrontRight, surround, unknown } },
|
||||
{ Vst2::kSpeakerArr80Music, { left, right, centre, leftSurround, rightSurround, surround, leftSurroundRear, rightSurroundRear, unknown } },
|
||||
{ Vst2::kSpeakerArr81Cine, { left, right, centre, LFE, leftSurround, rightSurround, topFrontLeft, topFrontRight, surround, unknown } },
|
||||
{ Vst2::kSpeakerArr81Music, { left, right, centre, LFE, leftSurround, rightSurround, surround, leftSurroundRear, rightSurroundRear, unknown } },
|
||||
{ Vst2::kSpeakerArr102, { left, right, centre, LFE, leftSurround, rightSurround, topFrontLeft, topFrontCentre, topFrontRight, topRearLeft, topRearRight, LFE2, unknown } },
|
||||
{ Vst2::kSpeakerArrEmpty, { unknown } }
|
||||
};
|
||||
|
||||
return mappings;
|
||||
}
|
||||
|
||||
static int32 getSpeakerType (AudioChannelSet::ChannelType type) noexcept
|
||||
{
|
||||
static const std::map<AudioChannelSet::ChannelType, int32> speakerTypeMap =
|
||||
{
|
||||
{ AudioChannelSet::left, Vst2::kSpeakerL },
|
||||
{ AudioChannelSet::right, Vst2::kSpeakerR },
|
||||
{ AudioChannelSet::centre, Vst2::kSpeakerC },
|
||||
{ AudioChannelSet::LFE, Vst2::kSpeakerLfe },
|
||||
{ AudioChannelSet::leftSurround, Vst2::kSpeakerLs },
|
||||
{ AudioChannelSet::rightSurround, Vst2::kSpeakerRs },
|
||||
{ AudioChannelSet::leftCentre, Vst2::kSpeakerLc },
|
||||
{ AudioChannelSet::rightCentre, Vst2::kSpeakerRc },
|
||||
{ AudioChannelSet::surround, Vst2::kSpeakerS },
|
||||
{ AudioChannelSet::leftSurroundRear, Vst2::kSpeakerSl },
|
||||
{ AudioChannelSet::rightSurroundRear, Vst2::kSpeakerSr },
|
||||
{ AudioChannelSet::topMiddle, Vst2::kSpeakerTm },
|
||||
{ AudioChannelSet::topFrontLeft, Vst2::kSpeakerTfl },
|
||||
{ AudioChannelSet::topFrontCentre, Vst2::kSpeakerTfc },
|
||||
{ AudioChannelSet::topFrontRight, Vst2::kSpeakerTfr },
|
||||
{ AudioChannelSet::topRearLeft, Vst2::kSpeakerTrl },
|
||||
{ AudioChannelSet::topRearCentre, Vst2::kSpeakerTrc },
|
||||
{ AudioChannelSet::topRearRight, Vst2::kSpeakerTrr },
|
||||
{ AudioChannelSet::LFE2, Vst2::kSpeakerLfe2 }
|
||||
};
|
||||
|
||||
if (speakerTypeMap.find (type) == speakerTypeMap.end())
|
||||
return 0;
|
||||
|
||||
return speakerTypeMap.at (type);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace juce
|
||||
|
|
@ -1,231 +0,0 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// NB: this must come first, *before* the header-guard.
|
||||
#ifdef JUCE_VSTINTERFACE_H_INCLUDED
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/** Holds a set of VSTMidiEvent objects and makes it easy to add
|
||||
events to the list.
|
||||
|
||||
This is used by both the VST hosting code and the plugin wrapper.
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class VSTMidiEventList
|
||||
{
|
||||
// "events" is expected to be a const- or non-const-ref to Vst2::VstEvents.
|
||||
template <typename Events>
|
||||
static auto& getEvent (Events& events, int index)
|
||||
{
|
||||
using EventType = decltype (&*events.events);
|
||||
static constexpr auto offset = offsetof (Vst2::VstEvents, events);
|
||||
|
||||
auto* bytes = reinterpret_cast<std::conditional_t<std::is_const_v<std::remove_pointer_t<EventType>>,
|
||||
const std::byte*,
|
||||
std::byte*>> (&events);
|
||||
auto* array = reinterpret_cast<EventType> (bytes + offset);
|
||||
|
||||
return array[index];
|
||||
}
|
||||
|
||||
Vst2::VstEvent* const& getEvent (int index) const { return getEvent (*events, index); }
|
||||
Vst2::VstEvent* & getEvent (int index) { return getEvent (*events, index); }
|
||||
|
||||
public:
|
||||
//==============================================================================
|
||||
VSTMidiEventList()
|
||||
: numEventsUsed (0), numEventsAllocated (0)
|
||||
{
|
||||
}
|
||||
|
||||
~VSTMidiEventList()
|
||||
{
|
||||
freeEvents();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void clear()
|
||||
{
|
||||
numEventsUsed = 0;
|
||||
|
||||
if (events != nullptr)
|
||||
events->numEvents = 0;
|
||||
}
|
||||
|
||||
void addEvent (const void* const midiData, int numBytes, int frameOffset)
|
||||
{
|
||||
ensureSize (numEventsUsed + 1);
|
||||
|
||||
void* const ptr = getEvent (numEventsUsed);
|
||||
events->numEvents = ++numEventsUsed;
|
||||
|
||||
if (numBytes <= 4)
|
||||
{
|
||||
auto* const e = static_cast<Vst2::VstMidiEvent*> (ptr);
|
||||
|
||||
if (e->type == Vst2::kVstSysExType)
|
||||
{
|
||||
delete[] reinterpret_cast<Vst2::VstMidiSysexEvent*> (e)->sysexDump;
|
||||
e->type = Vst2::kVstMidiType;
|
||||
e->byteSize = sizeof (Vst2::VstMidiEvent);
|
||||
e->noteLength = 0;
|
||||
e->noteOffset = 0;
|
||||
e->detune = 0;
|
||||
e->noteOffVelocity = 0;
|
||||
}
|
||||
|
||||
e->deltaFrames = frameOffset;
|
||||
memcpy (e->midiData, midiData, (size_t) numBytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto* const se = static_cast<Vst2::VstMidiSysexEvent*> (ptr);
|
||||
|
||||
if (se->type == Vst2::kVstSysExType)
|
||||
delete[] se->sysexDump;
|
||||
|
||||
se->sysexDump = new char [(size_t) numBytes];
|
||||
memcpy (se->sysexDump, midiData, (size_t) numBytes);
|
||||
|
||||
se->type = Vst2::kVstSysExType;
|
||||
se->byteSize = sizeof (Vst2::VstMidiSysexEvent);
|
||||
se->deltaFrames = frameOffset;
|
||||
se->flags = 0;
|
||||
se->dumpBytes = numBytes;
|
||||
se->resvd1 = 0;
|
||||
se->resvd2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Handy method to pull the events out of an event buffer supplied by the host
|
||||
// or plugin.
|
||||
static void addEventsToMidiBuffer (const Vst2::VstEvents* events, MidiBuffer& dest)
|
||||
{
|
||||
for (int i = 0; i < events->numEvents; ++i)
|
||||
{
|
||||
const auto* const e = getEvent (*events, i);
|
||||
|
||||
if (e != nullptr)
|
||||
{
|
||||
const void* const ptr = e;
|
||||
|
||||
if (e->type == Vst2::kVstMidiType)
|
||||
{
|
||||
dest.addEvent ((const juce::uint8*) static_cast<const Vst2::VstMidiEvent*> (ptr)->midiData,
|
||||
4, e->deltaFrames);
|
||||
}
|
||||
else if (e->type == Vst2::kVstSysExType)
|
||||
{
|
||||
const auto* se = static_cast<const Vst2::VstMidiSysexEvent*> (ptr);
|
||||
dest.addEvent ((const juce::uint8*) se->sysexDump,
|
||||
(int) se->dumpBytes,
|
||||
e->deltaFrames);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void ensureSize (int numEventsNeeded)
|
||||
{
|
||||
if (numEventsNeeded > numEventsAllocated)
|
||||
{
|
||||
numEventsNeeded = (numEventsNeeded + 32) & ~31;
|
||||
|
||||
const size_t size = 20 + (size_t) numEventsNeeded * sizeof (Vst2::VstEvent*);
|
||||
|
||||
if (events == nullptr)
|
||||
events.calloc (size, 1);
|
||||
else
|
||||
events.realloc (size, 1);
|
||||
|
||||
for (int i = numEventsAllocated; i < numEventsNeeded; ++i)
|
||||
getEvent (i) = allocateVSTEvent();
|
||||
|
||||
numEventsAllocated = numEventsNeeded;
|
||||
}
|
||||
}
|
||||
|
||||
void freeEvents()
|
||||
{
|
||||
if (events != nullptr)
|
||||
{
|
||||
for (int i = numEventsAllocated; --i >= 0;)
|
||||
freeVSTEvent (getEvent (i));
|
||||
|
||||
events.free();
|
||||
numEventsUsed = 0;
|
||||
numEventsAllocated = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
HeapBlock<Vst2::VstEvents> events;
|
||||
|
||||
private:
|
||||
int numEventsUsed, numEventsAllocated;
|
||||
|
||||
static Vst2::VstEvent* allocateVSTEvent()
|
||||
{
|
||||
constexpr auto size = jmax (sizeof (Vst2::VstMidiEvent), sizeof (Vst2::VstMidiSysexEvent));
|
||||
|
||||
if (auto* e = static_cast<Vst2::VstEvent*> (std::calloc (1, size)))
|
||||
{
|
||||
e->type = Vst2::kVstMidiType;
|
||||
e->byteSize = sizeof (Vst2::VstMidiEvent);
|
||||
return e;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void freeVSTEvent (Vst2::VstEvent* e)
|
||||
{
|
||||
if (e->type == Vst2::kVstSysExType)
|
||||
{
|
||||
delete[] (reinterpret_cast<Vst2::VstMidiSysexEvent*> (e)->sysexDump);
|
||||
}
|
||||
|
||||
std::free (e);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace juce
|
||||
|
||||
#endif // JUCE_VSTINTERFACE_H_INCLUDED
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -37,103 +37,20 @@
|
|||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Implements a plugin format manager for VSTs.
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API VSTPluginFormat : public AudioPluginFormat
|
||||
class JUCE_API VSTPluginFormat : public VSTPluginFormatHeadless
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
VSTPluginFormat();
|
||||
~VSTPluginFormat() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Attempts to retrieve the VSTXML data from a plugin.
|
||||
Will return nullptr if the plugin isn't a VST, or if it doesn't have any VSTXML.
|
||||
*/
|
||||
static const XmlElement* getVSTXML (AudioPluginInstance* plugin);
|
||||
|
||||
/** Attempts to reload a VST plugin's state from some FXB or FXP data. */
|
||||
static bool loadFromFXBFile (AudioPluginInstance* plugin, const void* data, size_t dataSize);
|
||||
|
||||
/** Attempts to save a VST's state to some FXP or FXB data. */
|
||||
static bool saveToFXBFile (AudioPluginInstance* plugin, MemoryBlock& result, bool asFXB);
|
||||
|
||||
/** Attempts to get a VST's state as a chunk of memory. */
|
||||
static bool getChunkData (AudioPluginInstance* plugin, MemoryBlock& result, bool isPreset);
|
||||
|
||||
/** Attempts to set a VST's state from a chunk of memory. */
|
||||
static bool setChunkData (AudioPluginInstance* plugin, const void* data, int size, bool isPreset);
|
||||
|
||||
/** Given a suitable function pointer to a VSTPluginMain function, this will attempt to
|
||||
instantiate and return a plugin for it.
|
||||
*/
|
||||
static AudioPluginInstance* createCustomVSTFromMainCall (void* entryPointFunction,
|
||||
double initialSampleRate,
|
||||
int initialBufferSize);
|
||||
|
||||
//==============================================================================
|
||||
/** Base class for some extra functions that can be attached to a VST plugin instance. */
|
||||
class ExtraFunctions
|
||||
{
|
||||
public:
|
||||
virtual ~ExtraFunctions() {}
|
||||
|
||||
/** This should return 10000 * the BPM at this position in the current edit. */
|
||||
virtual int64 getTempoAt (int64 samplePos) = 0;
|
||||
|
||||
/** This should return the host's automation state.
|
||||
@returns 0 = not supported, 1 = off, 2 = read, 3 = write, 4 = read/write
|
||||
*/
|
||||
virtual int getAutomationState() = 0;
|
||||
};
|
||||
|
||||
/** Provides an ExtraFunctions callback object for a plugin to use.
|
||||
The plugin will take ownership of the object and will delete it automatically.
|
||||
*/
|
||||
static void setExtraFunctions (AudioPluginInstance* plugin, ExtraFunctions* functions);
|
||||
|
||||
//==============================================================================
|
||||
/** This simply calls directly to the VST's AEffect::dispatcher() function. */
|
||||
static pointer_sized_int JUCE_CALLTYPE dispatcher (AudioPluginInstance*, int32, int32, pointer_sized_int, void*, float);
|
||||
|
||||
/** Given a VstEffectInterface* (aka vst::AEffect*), this will return the juce AudioPluginInstance
|
||||
that is being used to wrap it
|
||||
*/
|
||||
static AudioPluginInstance* getPluginInstanceFromVstEffectInterface (void* aEffect);
|
||||
|
||||
//==============================================================================
|
||||
static String getFormatName() { return "VST"; }
|
||||
String getName() const override { return getFormatName(); }
|
||||
bool canScanForPlugins() const override { return true; }
|
||||
bool isTrivialToScan() const override { return false; }
|
||||
|
||||
void findAllTypesForFile (OwnedArray<PluginDescription>&, const String& fileOrIdentifier) override;
|
||||
bool fileMightContainThisPluginType (const String& fileOrIdentifier) override;
|
||||
String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) override;
|
||||
bool pluginNeedsRescanning (const PluginDescription&) override;
|
||||
StringArray searchPathsForPlugins (const FileSearchPath&, bool recursive, bool) override;
|
||||
bool doesPluginStillExist (const PluginDescription&) override;
|
||||
FileSearchPath getDefaultLocationsToSearch() override;
|
||||
|
||||
/** Can be overridden to receive a callback when each member of a shell plugin is about to be
|
||||
tested during a call to findAllTypesForFile().
|
||||
Only the name and uid members of the PluginDescription are guaranteed to be valid when
|
||||
this is called.
|
||||
*/
|
||||
virtual void aboutToScanVSTShellPlugin (const PluginDescription&);
|
||||
static std::unique_ptr<AudioPluginInstance> createCustomVSTFromMainCall (void* entryPointFunction,
|
||||
double initialSampleRate,
|
||||
int initialBufferSize);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
void createPluginInstance (const PluginDescription&, double initialSampleRate,
|
||||
int initialBufferSize, PluginCreationCallback) override;
|
||||
bool requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const override;
|
||||
void recursiveFileSearch (StringArray&, const File&, bool recursive);
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VSTPluginFormat)
|
||||
void createPluginInstance (const PluginDescription&, double, int, PluginCreationCallback) override;
|
||||
};
|
||||
|
||||
} // namespace juce
|
||||
|
|
|
|||
|
|
@ -146,7 +146,6 @@
|
|||
#include "format_types/juce_LADSPAPluginFormat.h"
|
||||
#include "format_types/juce_LV2PluginFormat.h"
|
||||
#include "format_types/juce_VST3PluginFormat.h"
|
||||
#include "format_types/juce_VSTMidiEventList.h"
|
||||
#include "format_types/juce_VSTPluginFormat.h"
|
||||
#include "scanning/juce_PluginDirectoryScanner.h"
|
||||
#include "scanning/juce_PluginListComponent.h"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue