mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-16 19:56:31 +01:00
VST3: Implement host classes
This commit is contained in:
parent
9bd8c43693
commit
84a86fa21a
3 changed files with 1199 additions and 1 deletions
414
libs/ardour/ardour/vst3_host.h
Normal file
414
libs/ardour/ardour/vst3_host.h
Normal file
|
|
@ -0,0 +1,414 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019-2020 Robin Gareus <robin@gareus.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ardour_vst3_host_h_
|
||||||
|
#define _ardour_vst3_host_h_
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
#include "ardour/libardour_visibility.h"
|
||||||
|
#include "vst3/vst3.h"
|
||||||
|
|
||||||
|
#define QUERY_INTERFACE_IMPL(Interface) \
|
||||||
|
tresult queryInterface (const TUID _iid, void** obj) \
|
||||||
|
{ \
|
||||||
|
QUERY_INTERFACE (_iid, obj, FUnknown::iid, Interface) \
|
||||||
|
QUERY_INTERFACE (_iid, obj, Interface::iid, Interface) \
|
||||||
|
*obj = nullptr; \
|
||||||
|
return kNoInterface; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
# pragma clang diagnostic push
|
||||||
|
# pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||||
|
#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||||
|
# pragma GCC diagnostic push
|
||||||
|
# pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Steinberg {
|
||||||
|
|
||||||
|
LIBARDOUR_API extern std::string tchar_to_utf8 (Vst::TChar const* s);
|
||||||
|
LIBARDOUR_API extern bool utf8_to_tchar (Vst::TChar* rv, const char* s, size_t l = 0);
|
||||||
|
LIBARDOUR_API extern bool utf8_to_tchar (Vst::TChar* rv, std::string const& s, size_t l = 0);
|
||||||
|
|
||||||
|
namespace Vst {
|
||||||
|
/* see public.sdk/source/vst/vstpresetfile.cpp */
|
||||||
|
typedef char ChunkID[4]; // using ChunkID = char[4];
|
||||||
|
static const int32 kClassIDSize = 32; // ASCII-encoded FUID
|
||||||
|
static const int32 kHeaderSize = sizeof (ChunkID) + sizeof (int32) + kClassIDSize + sizeof (TSize);
|
||||||
|
static const int32 kListOffsetPos = kHeaderSize - sizeof (TSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
class LIBARDOUR_API HostAttribute
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Type {
|
||||||
|
kInteger,
|
||||||
|
kFloat,
|
||||||
|
kString,
|
||||||
|
kBinary
|
||||||
|
};
|
||||||
|
|
||||||
|
HostAttribute (int64 value)
|
||||||
|
: _size (0)
|
||||||
|
, _type (kInteger)
|
||||||
|
{
|
||||||
|
v.intValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
HostAttribute (double value)
|
||||||
|
: _size (0)
|
||||||
|
, _type (kFloat)
|
||||||
|
{
|
||||||
|
v.floatValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
HostAttribute (const Vst::TChar* value, uint32 size)
|
||||||
|
: _size (size)
|
||||||
|
, _type (kString)
|
||||||
|
{
|
||||||
|
v.stringValue = new Vst::TChar[_size];
|
||||||
|
memcpy (v.stringValue, value, _size * sizeof (Vst::TChar));
|
||||||
|
}
|
||||||
|
|
||||||
|
HostAttribute (const void* value, uint32 size)
|
||||||
|
: _size (size)
|
||||||
|
, _type (kBinary)
|
||||||
|
{
|
||||||
|
v.binaryValue = new char[_size];
|
||||||
|
memcpy (v.binaryValue, value, _size);
|
||||||
|
}
|
||||||
|
|
||||||
|
~HostAttribute ()
|
||||||
|
{
|
||||||
|
if (_size) {
|
||||||
|
delete[] v.binaryValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Type getType () const { return _type; }
|
||||||
|
int64 intValue () const { return v.intValue; }
|
||||||
|
double floatValue () const { return v.floatValue; }
|
||||||
|
|
||||||
|
const Vst::TChar* stringValue (uint32& stringSize)
|
||||||
|
{
|
||||||
|
stringSize = _size;
|
||||||
|
return v.stringValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void* binaryValue (uint32& binarySize)
|
||||||
|
{
|
||||||
|
binarySize = _size;
|
||||||
|
return v.binaryValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
union v {
|
||||||
|
int64 intValue;
|
||||||
|
double floatValue;
|
||||||
|
Vst::TChar* stringValue;
|
||||||
|
char* binaryValue;
|
||||||
|
} v;
|
||||||
|
|
||||||
|
uint32 _size;
|
||||||
|
Type _type;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* prevent copy construction */
|
||||||
|
HostAttribute (HostAttribute const& other);
|
||||||
|
};
|
||||||
|
|
||||||
|
class LIBARDOUR_API RefObject : public FUnknown
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RefObject ();
|
||||||
|
virtual ~RefObject () {}
|
||||||
|
uint32 addRef ();
|
||||||
|
uint32 release ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
gint _cnt; // atomic
|
||||||
|
};
|
||||||
|
|
||||||
|
class LIBARDOUR_API HostAttributeList : public Vst::IAttributeList, public RefObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HostAttributeList ();
|
||||||
|
virtual ~HostAttributeList ();
|
||||||
|
|
||||||
|
QUERY_INTERFACE_IMPL (Vst::IAttributeList);
|
||||||
|
uint32 addRef () SMTG_OVERRIDE { return RefObject::addRef (); }
|
||||||
|
uint32 release () SMTG_OVERRIDE { return RefObject::release (); }
|
||||||
|
|
||||||
|
tresult setInt (AttrID aid, int64 value) SMTG_OVERRIDE;
|
||||||
|
tresult getInt (AttrID aid, int64& value) SMTG_OVERRIDE;
|
||||||
|
tresult setFloat (AttrID aid, double value) SMTG_OVERRIDE;
|
||||||
|
tresult getFloat (AttrID aid, double& value) SMTG_OVERRIDE;
|
||||||
|
tresult setString (AttrID aid, const Vst::TChar* string) SMTG_OVERRIDE;
|
||||||
|
tresult getString (AttrID aid, Vst::TChar* string, uint32 size) SMTG_OVERRIDE;
|
||||||
|
tresult setBinary (AttrID aid, const void* data, uint32 size) SMTG_OVERRIDE;
|
||||||
|
tresult getBinary (AttrID aid, const void*& data, uint32& size) SMTG_OVERRIDE;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void removeAttrID (AttrID aid);
|
||||||
|
|
||||||
|
std::map<std::string, HostAttribute*> list;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LIBARDOUR_API HostMessage : public Vst::IMessage, public RefObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HostMessage ();
|
||||||
|
virtual ~HostMessage ();
|
||||||
|
|
||||||
|
QUERY_INTERFACE_IMPL (Vst::IMessage);
|
||||||
|
uint32 addRef () SMTG_OVERRIDE { return RefObject::addRef (); }
|
||||||
|
uint32 release () SMTG_OVERRIDE { return RefObject::release (); }
|
||||||
|
|
||||||
|
const char* getMessageID () SMTG_OVERRIDE;
|
||||||
|
void setMessageID (const char* messageID) SMTG_OVERRIDE;
|
||||||
|
Vst::IAttributeList* getAttributes () SMTG_OVERRIDE;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
char* _messageId;
|
||||||
|
boost::shared_ptr<HostAttributeList> _attribute_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LIBARDOUR_API PlugInterfaceSupport : public Vst::IPlugInterfaceSupport
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PlugInterfaceSupport ();
|
||||||
|
QUERY_INTERFACE_IMPL (Vst::IPlugInterfaceSupport);
|
||||||
|
uint32 addRef () SMTG_OVERRIDE { return 1; }
|
||||||
|
uint32 release () SMTG_OVERRIDE { return 1; }
|
||||||
|
|
||||||
|
tresult isPlugInterfaceSupported (const TUID) SMTG_OVERRIDE;
|
||||||
|
void addPlugInterfaceSupported (const TUID);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<FUID> _interfaces;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LIBARDOUR_API HostApplication : public Vst::IHostApplication
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static Vst::IHostApplication* getHostContext ()
|
||||||
|
{
|
||||||
|
static HostApplication* app = new HostApplication;
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
HostApplication ();
|
||||||
|
virtual ~HostApplication () {}
|
||||||
|
tresult queryInterface (const TUID _iid, void** obj) SMTG_OVERRIDE;
|
||||||
|
|
||||||
|
uint32 addRef () SMTG_OVERRIDE { return 1; }
|
||||||
|
uint32 release () SMTG_OVERRIDE { return 1; }
|
||||||
|
|
||||||
|
tresult getName (Vst::String128 name) SMTG_OVERRIDE;
|
||||||
|
tresult createInstance (TUID cid, TUID _iid, void** obj) SMTG_OVERRIDE;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
boost::shared_ptr<PlugInterfaceSupport> _plug_interface_support;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LIBARDOUR_LOCAL Vst3ParamValueQueue : public Vst::IParamValueQueue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QUERY_INTERFACE_IMPL (Vst::IParamValueQueue);
|
||||||
|
uint32 addRef () SMTG_OVERRIDE { return 1; }
|
||||||
|
uint32 release () SMTG_OVERRIDE { return 1; }
|
||||||
|
|
||||||
|
static const int maxNumPoints = 64;
|
||||||
|
|
||||||
|
Vst3ParamValueQueue() {
|
||||||
|
_values.reserve (maxNumPoints);
|
||||||
|
_id = Vst::kNoParamId;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vst::ParamID getParameterId() SMTG_OVERRIDE { return _id; }
|
||||||
|
|
||||||
|
void setParameterId (Vst::ParamID id) {
|
||||||
|
_values.clear();
|
||||||
|
_id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 getPointCount() SMTG_OVERRIDE { return _values.size(); }
|
||||||
|
tresult getPoint (int32 index, int32&, Vst::ParamValue&) SMTG_OVERRIDE;
|
||||||
|
tresult addPoint (int32, Vst::ParamValue, int32&) SMTG_OVERRIDE;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct Value {
|
||||||
|
Value (Vst::ParamValue v, int32 offset)
|
||||||
|
: value(v)
|
||||||
|
, sampleOffset(offset)
|
||||||
|
{}
|
||||||
|
Vst::ParamValue value;
|
||||||
|
int32 sampleOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<Value> _values;
|
||||||
|
Vst::ParamID _id;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LIBARDOUR_LOCAL Vst3ParameterChanges : public Vst::IParameterChanges
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QUERY_INTERFACE_IMPL (Vst::IParameterChanges);
|
||||||
|
uint32 addRef () SMTG_OVERRIDE { return 1; }
|
||||||
|
uint32 release () SMTG_OVERRIDE { return 1; }
|
||||||
|
|
||||||
|
Vst3ParameterChanges () {
|
||||||
|
clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_n_params (int n) {
|
||||||
|
_queue.resize(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear () {
|
||||||
|
_used_queue_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 getParameterCount() SMTG_OVERRIDE {
|
||||||
|
return _used_queue_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vst::IParamValueQueue* getParameterData (int32 index) SMTG_OVERRIDE;
|
||||||
|
Vst::IParamValueQueue* addParameterData (Vst::ParamID const& id, int32& index) SMTG_OVERRIDE;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<Vst3ParamValueQueue> _queue;
|
||||||
|
int _used_queue_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LIBARDOUR_LOCAL Vst3EventList : public Vst::IEventList
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vst3EventList() {
|
||||||
|
_events.reserve (128);
|
||||||
|
}
|
||||||
|
|
||||||
|
QUERY_INTERFACE_IMPL (Vst::IEventList)
|
||||||
|
uint32 addRef () SMTG_OVERRIDE { return 1; }
|
||||||
|
uint32 release () SMTG_OVERRIDE { return 1; }
|
||||||
|
|
||||||
|
int32 PLUGIN_API getEventCount() {
|
||||||
|
return _events.size ();
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult PLUGIN_API getEvent (int32 index, Vst::Event& e) {
|
||||||
|
if (index >= 0 && index < (int32)_events.size ()) {
|
||||||
|
e = _events[index];
|
||||||
|
return kResultTrue;
|
||||||
|
} else {
|
||||||
|
return kResultFalse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult PLUGIN_API addEvent (Vst::Event& e) {
|
||||||
|
_events.push_back (e);
|
||||||
|
return kResultTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
_events.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<Vst::Event> _events;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LIBARDOUR_LOCAL RAMStream : public IBStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RAMStream ();
|
||||||
|
RAMStream (uint8_t* data, size_t size);
|
||||||
|
RAMStream (std::string const& fn);
|
||||||
|
|
||||||
|
virtual ~RAMStream ();
|
||||||
|
|
||||||
|
QUERY_INTERFACE_IMPL (IBStream)
|
||||||
|
uint32 addRef () SMTG_OVERRIDE { return 1; }
|
||||||
|
uint32 release () SMTG_OVERRIDE { return 1; }
|
||||||
|
|
||||||
|
/* IBStream API */
|
||||||
|
tresult PLUGIN_API read (void* buffer, int32 numBytes, int32* numBytesRead) SMTG_OVERRIDE;
|
||||||
|
tresult PLUGIN_API write (void* buffer, int32 numBytes, int32* numBytesWritten) SMTG_OVERRIDE;
|
||||||
|
tresult PLUGIN_API seek (int64 pos, int32 mode, int64* result) SMTG_OVERRIDE;
|
||||||
|
tresult PLUGIN_API tell (int64* pos) SMTG_OVERRIDE;
|
||||||
|
|
||||||
|
/* convenience API for state I/O */
|
||||||
|
void rewind () { _pos = 0; }
|
||||||
|
bool readonly () const { return _readonly; }
|
||||||
|
|
||||||
|
bool write_int32 (int32 i);
|
||||||
|
bool write_int64 (int64 i);
|
||||||
|
bool write_ChunkID (const Vst::ChunkID& id);
|
||||||
|
bool write_TUID (const TUID& tuid);
|
||||||
|
|
||||||
|
bool read_int32 (int32& i);
|
||||||
|
bool read_int64 (int64& i);
|
||||||
|
bool read_ChunkID (Vst::ChunkID& id);
|
||||||
|
bool read_TUID (TUID& tuid);
|
||||||
|
|
||||||
|
/* direct access */
|
||||||
|
uint8_t const* data () const { return _data; }
|
||||||
|
int64 size () const { return _size; }
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
void hexdump (int64 max_len = 64) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool reallocate_buffer (int64 size, bool exact);
|
||||||
|
|
||||||
|
template<typename T> bool read_pod (T& t) {
|
||||||
|
int32 n_read = 0;
|
||||||
|
read ((void *)&t, sizeof(T), &n_read);
|
||||||
|
return n_read == sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> bool write_pod (const T& t) {
|
||||||
|
int32 written = 0;
|
||||||
|
write (const_cast<void*>((const void *)&t), sizeof(T), &written);
|
||||||
|
return written == sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* _data;
|
||||||
|
int64 _size;
|
||||||
|
int64 _alloc;
|
||||||
|
int64 _pos;
|
||||||
|
bool _readonly;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
# pragma clang diagnostic pop
|
||||||
|
#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||||
|
# pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace Steinberg
|
||||||
|
#endif
|
||||||
784
libs/ardour/vst3_host.cc
Normal file
784
libs/ardour/vst3_host.cc
Normal file
|
|
@ -0,0 +1,784 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019-2020 Robin Gareus <robin@gareus.org>
|
||||||
|
* Copyright (C) 2019 Steinberg Media Technologies GmbH
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#if (__cplusplus >= 201103L)
|
||||||
|
#include <boost/make_unique.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "ardour/vst3_host.h"
|
||||||
|
|
||||||
|
using namespace Steinberg;
|
||||||
|
|
||||||
|
DEF_CLASS_IID (FUnknown)
|
||||||
|
DEF_CLASS_IID (IBStream)
|
||||||
|
DEF_CLASS_IID (IPluginBase)
|
||||||
|
DEF_CLASS_IID (IPluginFactory)
|
||||||
|
DEF_CLASS_IID (IPluginFactory2)
|
||||||
|
DEF_CLASS_IID (IPlugFrame)
|
||||||
|
DEF_CLASS_IID (IPlugView)
|
||||||
|
DEF_CLASS_IID (Vst::IAttributeList)
|
||||||
|
DEF_CLASS_IID (Vst::IAudioProcessor)
|
||||||
|
DEF_CLASS_IID (Vst::IAutomationState)
|
||||||
|
DEF_CLASS_IID (Vst::IComponent)
|
||||||
|
DEF_CLASS_IID (Vst::IComponentHandler)
|
||||||
|
DEF_CLASS_IID (Vst::IConnectionPoint)
|
||||||
|
DEF_CLASS_IID (Vst::IEditController)
|
||||||
|
DEF_CLASS_IID (Vst::IEventList)
|
||||||
|
DEF_CLASS_IID (Vst::IHostApplication)
|
||||||
|
DEF_CLASS_IID (Vst::IMessage)
|
||||||
|
DEF_CLASS_IID (Vst::IMidiMapping)
|
||||||
|
DEF_CLASS_IID (Vst::IParameterChanges)
|
||||||
|
DEF_CLASS_IID (Vst::IParamValueQueue)
|
||||||
|
DEF_CLASS_IID (Vst::IPlugInterfaceSupport)
|
||||||
|
DEF_CLASS_IID (Vst::IProgramListData)
|
||||||
|
DEF_CLASS_IID (Vst::IUnitData)
|
||||||
|
DEF_CLASS_IID (Vst::IUnitInfo)
|
||||||
|
|
||||||
|
#if SMTG_OS_LINUX
|
||||||
|
DEF_CLASS_IID (Linux::IRunLoop);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::string
|
||||||
|
Steinberg::tchar_to_utf8 (Vst::TChar const* s)
|
||||||
|
{
|
||||||
|
glong len;
|
||||||
|
gchar* utf8 = g_utf16_to_utf8 ((const gunichar2*)s, -1, NULL, &len, NULL);
|
||||||
|
if (!utf8 || len == 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
std::string rv (utf8, len);
|
||||||
|
g_free (utf8);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Steinberg::utf8_to_tchar (Vst::TChar* rv, const char* s, size_t l)
|
||||||
|
{
|
||||||
|
glong len;
|
||||||
|
gunichar2* s16 = g_utf8_to_utf16 (s, -1, NULL, &len, NULL);
|
||||||
|
if (!s16 || len == 0) {
|
||||||
|
memset (rv, 0, sizeof (Vst::TChar));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (l > 0 && l < len) {
|
||||||
|
len = l;
|
||||||
|
}
|
||||||
|
memcpy (rv, s16, len * sizeof (Vst::TChar));
|
||||||
|
g_free (s16);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Steinberg::utf8_to_tchar (Vst::TChar* rv, std::string const& s, size_t l)
|
||||||
|
{
|
||||||
|
return utf8_to_tchar (rv, s.c_str(), l);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ****************************************************************************/
|
||||||
|
|
||||||
|
RefObject::RefObject ()
|
||||||
|
{
|
||||||
|
g_atomic_int_set (&_cnt, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32
|
||||||
|
RefObject::addRef ()
|
||||||
|
{
|
||||||
|
g_atomic_int_inc (&_cnt);
|
||||||
|
return g_atomic_int_get (&_cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32
|
||||||
|
RefObject::release ()
|
||||||
|
{
|
||||||
|
if (g_atomic_int_dec_and_test (&_cnt)) {
|
||||||
|
delete this;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return g_atomic_int_get (&_cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ****************************************************************************/
|
||||||
|
/* copy/edit from public.sdk/source/vst/hosting/hostclasses.cpp */
|
||||||
|
/* ****************************************************************************/
|
||||||
|
|
||||||
|
#include "vst3/pluginterfaces/base/funknown.cpp"
|
||||||
|
|
||||||
|
HostAttributeList::HostAttributeList ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HostAttributeList::~HostAttributeList ()
|
||||||
|
{
|
||||||
|
std::map<std::string, HostAttribute*>::reverse_iterator it = list.rbegin ();
|
||||||
|
while (it != list.rend ()) {
|
||||||
|
delete it->second;
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HostAttributeList::removeAttrID (AttrID aid)
|
||||||
|
{
|
||||||
|
std::map<std::string, HostAttribute*>::iterator it = list.find (aid);
|
||||||
|
if (it != list.end ()) {
|
||||||
|
delete it->second;
|
||||||
|
list.erase (it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult
|
||||||
|
HostAttributeList::setInt (AttrID aid, int64 value)
|
||||||
|
{
|
||||||
|
removeAttrID (aid);
|
||||||
|
list[aid] = new HostAttribute (value);
|
||||||
|
return kResultTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult
|
||||||
|
HostAttributeList::getInt (AttrID aid, int64& value)
|
||||||
|
{
|
||||||
|
std::map<std::string, HostAttribute*>::iterator it = list.find (aid);
|
||||||
|
if (it != list.end () && it->second) {
|
||||||
|
value = it->second->intValue ();
|
||||||
|
return kResultTrue;
|
||||||
|
}
|
||||||
|
return kResultFalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult
|
||||||
|
HostAttributeList::setFloat (AttrID aid, double value)
|
||||||
|
{
|
||||||
|
removeAttrID (aid);
|
||||||
|
list[aid] = new HostAttribute (value);
|
||||||
|
return kResultTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult
|
||||||
|
HostAttributeList::getFloat (AttrID aid, double& value)
|
||||||
|
{
|
||||||
|
std::map<std::string, HostAttribute*>::iterator it = list.find (aid);
|
||||||
|
if (it != list.end () && it->second) {
|
||||||
|
value = it->second->floatValue ();
|
||||||
|
return kResultTrue;
|
||||||
|
}
|
||||||
|
return kResultFalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult
|
||||||
|
HostAttributeList::setString (AttrID aid, const Vst::TChar* string)
|
||||||
|
{
|
||||||
|
removeAttrID (aid);
|
||||||
|
list[aid] = new HostAttribute (string, wcslen ((const wchar_t*)string));
|
||||||
|
return kResultTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult
|
||||||
|
HostAttributeList::getString (AttrID aid, Vst::TChar* string, uint32 size)
|
||||||
|
{
|
||||||
|
std::map<std::string, HostAttribute*>::iterator it = list.find (aid);
|
||||||
|
if (it != list.end () && it->second) {
|
||||||
|
uint32 stringSize = 0;
|
||||||
|
const Vst::TChar* _string = it->second->stringValue (stringSize);
|
||||||
|
memcpy (string, _string, std::min<uint32> (stringSize, size) * sizeof (Vst::TChar));
|
||||||
|
return kResultTrue;
|
||||||
|
}
|
||||||
|
return kResultFalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult
|
||||||
|
HostAttributeList::setBinary (AttrID aid, const void* data, uint32 size)
|
||||||
|
{
|
||||||
|
removeAttrID (aid);
|
||||||
|
list[aid] = new HostAttribute (data, size);
|
||||||
|
return kResultTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult
|
||||||
|
HostAttributeList::getBinary (AttrID aid, const void*& data, uint32& size)
|
||||||
|
{
|
||||||
|
std::map<std::string, HostAttribute*>::iterator it = list.find (aid);
|
||||||
|
if (it != list.end () && it->second) {
|
||||||
|
data = it->second->binaryValue (size);
|
||||||
|
return kResultTrue;
|
||||||
|
}
|
||||||
|
size = 0;
|
||||||
|
return kResultFalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ****************************************************************************/
|
||||||
|
|
||||||
|
HostMessage::HostMessage ()
|
||||||
|
: _messageId (0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HostMessage::~HostMessage ()
|
||||||
|
{
|
||||||
|
setMessageID (0);
|
||||||
|
if (_attribute_list) {
|
||||||
|
//_attribute_list->release ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char*
|
||||||
|
HostMessage::getMessageID ()
|
||||||
|
{
|
||||||
|
return _messageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HostMessage::setMessageID (const char* mid)
|
||||||
|
{
|
||||||
|
if (_messageId) {
|
||||||
|
delete[] _messageId;
|
||||||
|
}
|
||||||
|
if (mid) {
|
||||||
|
size_t len = strlen (mid) + 1;
|
||||||
|
_messageId = new char[len];
|
||||||
|
strcpy (_messageId, mid);
|
||||||
|
} else {
|
||||||
|
_messageId = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vst::IAttributeList*
|
||||||
|
HostMessage::getAttributes ()
|
||||||
|
{
|
||||||
|
if (!_attribute_list) {
|
||||||
|
_attribute_list.reset (new HostAttributeList);
|
||||||
|
}
|
||||||
|
return _attribute_list.get ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ****************************************************************************/
|
||||||
|
|
||||||
|
PlugInterfaceSupport::PlugInterfaceSupport ()
|
||||||
|
{
|
||||||
|
using namespace Vst;
|
||||||
|
|
||||||
|
//---VST 3.0.0--------------------------------
|
||||||
|
addPlugInterfaceSupported (IComponent::iid);
|
||||||
|
addPlugInterfaceSupported (IAudioProcessor::iid);
|
||||||
|
addPlugInterfaceSupported (IEditController::iid);
|
||||||
|
addPlugInterfaceSupported (IConnectionPoint::iid);
|
||||||
|
|
||||||
|
addPlugInterfaceSupported (IUnitInfo::iid);
|
||||||
|
addPlugInterfaceSupported (IUnitData::iid);
|
||||||
|
addPlugInterfaceSupported (IProgramListData::iid);
|
||||||
|
|
||||||
|
//---VST 3.0.1--------------------------------
|
||||||
|
addPlugInterfaceSupported (IMidiMapping::iid);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
//---VST 3.1----------------------------------
|
||||||
|
addPlugInterfaceSupported (IEditController2::iid);
|
||||||
|
|
||||||
|
//---VST 3.0.2--------------------------------
|
||||||
|
addPlugInterfaceSupported (IParameterFinder::iid);
|
||||||
|
|
||||||
|
//---VST 3.1----------------------------------
|
||||||
|
addPlugInterfaceSupported (IAudioPresentationLatency::iid);
|
||||||
|
|
||||||
|
//---VST 3.5----------------------------------
|
||||||
|
addPlugInterfaceSupported (IKeyswitchController::iid);
|
||||||
|
addPlugInterfaceSupported (IContextMenuTarget::iid);
|
||||||
|
addPlugInterfaceSupported (IEditControllerHostEditing::iid);
|
||||||
|
addPlugInterfaceSupported (IXmlRepresentationController::iid);
|
||||||
|
addPlugInterfaceSupported (INoteExpressionController::iid);
|
||||||
|
|
||||||
|
//---VST 3.6.5--------------------------------
|
||||||
|
addPlugInterfaceSupported (ChannelContext::IInfoListener::iid);
|
||||||
|
addPlugInterfaceSupported (IPrefetchableSupport::iid);
|
||||||
|
addPlugInterfaceSupported (IAutomationState::iid);
|
||||||
|
|
||||||
|
//---VST 3.6.11--------------------------------
|
||||||
|
addPlugInterfaceSupported (INoteExpressionPhysicalUIMapping::iid);
|
||||||
|
|
||||||
|
//---VST 3.6.12--------------------------------
|
||||||
|
addPlugInterfaceSupported (IMidiLearn::iid);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult
|
||||||
|
PlugInterfaceSupport::isPlugInterfaceSupported (const TUID _iid)
|
||||||
|
{
|
||||||
|
const FUID uid = FUID::fromTUID (_iid);
|
||||||
|
if (std::find (_interfaces.begin (), _interfaces.end (), uid) != _interfaces.end ()) {
|
||||||
|
return kResultTrue;
|
||||||
|
}
|
||||||
|
return kResultFalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PlugInterfaceSupport::addPlugInterfaceSupported (const TUID id)
|
||||||
|
{
|
||||||
|
_interfaces.push_back (FUID::fromTUID (id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ****************************************************************************/
|
||||||
|
|
||||||
|
HostApplication::HostApplication ()
|
||||||
|
{
|
||||||
|
#if (__cplusplus >= 201103L)
|
||||||
|
_plug_interface_support = boost::make_unique<PlugInterfaceSupport> ();
|
||||||
|
#else
|
||||||
|
_plug_interface_support.reset (new PlugInterfaceSupport);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult
|
||||||
|
HostApplication::queryInterface (const char* _iid, void** obj)
|
||||||
|
{
|
||||||
|
QUERY_INTERFACE (_iid, obj, FUnknown::iid, IHostApplication)
|
||||||
|
QUERY_INTERFACE (_iid, obj, IHostApplication::iid, IHostApplication)
|
||||||
|
|
||||||
|
if (_plug_interface_support && _plug_interface_support->queryInterface (Vst::IHostApplication::iid, obj) == kResultTrue) {
|
||||||
|
return kResultOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
*obj = nullptr;
|
||||||
|
return kResultFalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult
|
||||||
|
HostApplication::getName (Vst::String128 name)
|
||||||
|
{
|
||||||
|
utf8_to_tchar (name, PROGRAM_NAME, 128);
|
||||||
|
return kResultTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult
|
||||||
|
HostApplication::createInstance (TUID cid, TUID _iid, void** obj)
|
||||||
|
{
|
||||||
|
FUID classID (FUID::fromTUID (cid));
|
||||||
|
FUID interfaceID (FUID::fromTUID (_iid));
|
||||||
|
if (classID == Vst::IMessage::iid && interfaceID == Vst::IMessage::iid) {
|
||||||
|
*obj = (Vst::IMessage*)new HostMessage;
|
||||||
|
return kResultTrue;
|
||||||
|
} else if (classID == Vst::IAttributeList::iid && interfaceID == Vst::IAttributeList::iid) {
|
||||||
|
*obj = (Vst::IAttributeList*)new HostAttributeList;
|
||||||
|
return kResultTrue;
|
||||||
|
}
|
||||||
|
*obj = nullptr;
|
||||||
|
return kResultFalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ****************************************************************************/
|
||||||
|
|
||||||
|
tresult
|
||||||
|
Vst3ParamValueQueue::getPoint (int32 index, int32& sampleOffset, Vst::ParamValue& value)
|
||||||
|
{
|
||||||
|
if (index >=0 && index < (int32)_values.size ()) {
|
||||||
|
const Value& v = _values[index];
|
||||||
|
sampleOffset = v.sampleOffset;
|
||||||
|
value = v.value;
|
||||||
|
return kResultTrue;
|
||||||
|
}
|
||||||
|
return kResultFalse;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult
|
||||||
|
Vst3ParamValueQueue::addPoint (int32 sampleOffset, Vst::ParamValue value, int32& index)
|
||||||
|
{
|
||||||
|
int32 dest_index = (int32)_values.size ();
|
||||||
|
for (uint32 i = 0; i < _values.size (); ++i) {
|
||||||
|
if (_values[i].sampleOffset == sampleOffset) {
|
||||||
|
_values[i].value = value;
|
||||||
|
index = i;
|
||||||
|
return kResultTrue;
|
||||||
|
} else if (_values[i].sampleOffset > sampleOffset) {
|
||||||
|
dest_index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Value v (value, sampleOffset);
|
||||||
|
if (dest_index == (int32)_values.size ()) {
|
||||||
|
_values.push_back (v);
|
||||||
|
} else {
|
||||||
|
_values.insert (_values.begin () + dest_index, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
index = dest_index;
|
||||||
|
return kResultTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ****************************************************************************/
|
||||||
|
|
||||||
|
Vst::IParamValueQueue*
|
||||||
|
Vst3ParameterChanges::getParameterData (int32 index)
|
||||||
|
{
|
||||||
|
if (index < _used_queue_count) {
|
||||||
|
return &_queue[index];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vst::IParamValueQueue*
|
||||||
|
Vst3ParameterChanges::addParameterData (Vst::ParamID const& pid, int32& index)
|
||||||
|
{
|
||||||
|
for (int32 i = 0; i < _used_queue_count; ++i) {
|
||||||
|
if (_queue[i].getParameterId () == pid) {
|
||||||
|
index = i;
|
||||||
|
return &_queue[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_used_queue_count < (int32)_queue.size ()) {
|
||||||
|
index = _used_queue_count++;
|
||||||
|
_queue[index].setParameterId (pid);
|
||||||
|
return &_queue[index];
|
||||||
|
}
|
||||||
|
index = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ****************************************************************************/
|
||||||
|
|
||||||
|
RAMStream::RAMStream ()
|
||||||
|
: _data (0)
|
||||||
|
, _size (0)
|
||||||
|
, _alloc (0)
|
||||||
|
, _pos (0)
|
||||||
|
, _readonly (false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RAMStream::RAMStream (uint8_t* data, size_t size)
|
||||||
|
: _data (0)
|
||||||
|
, _size (size)
|
||||||
|
, _alloc (0)
|
||||||
|
, _pos (0)
|
||||||
|
, _readonly (true)
|
||||||
|
{
|
||||||
|
if (reallocate_buffer (_size, true)) {
|
||||||
|
memcpy (_data, data, _size);
|
||||||
|
} else {
|
||||||
|
_size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RAMStream::RAMStream (std::string const& fn)
|
||||||
|
: _data (0)
|
||||||
|
, _size (0)
|
||||||
|
, _alloc (0)
|
||||||
|
, _pos (0)
|
||||||
|
, _readonly (true)
|
||||||
|
{
|
||||||
|
gchar* buf = NULL;
|
||||||
|
gsize length = 0;
|
||||||
|
|
||||||
|
if (!g_file_get_contents (fn.c_str (), &buf, &length, NULL)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (reallocate_buffer (length, true)) {
|
||||||
|
_size = length;
|
||||||
|
memcpy (_data, buf, _size);
|
||||||
|
}
|
||||||
|
g_free (buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
RAMStream::~RAMStream ()
|
||||||
|
{
|
||||||
|
free (_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RAMStream::reallocate_buffer (int64 size, bool exact)
|
||||||
|
{
|
||||||
|
if (size <= 0) {
|
||||||
|
free (_data);
|
||||||
|
_data = 0;
|
||||||
|
_alloc = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == _alloc) {
|
||||||
|
assert (_data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!exact) {
|
||||||
|
if (size <= _alloc) {
|
||||||
|
/* don't shrink */
|
||||||
|
assert (_data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (size > _alloc) {
|
||||||
|
size = (((size - 1) / 8192) + 1) * 8192;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_data = (uint8_t*) realloc (_data, size);
|
||||||
|
|
||||||
|
if (_data) {
|
||||||
|
_alloc = size;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
_alloc = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult
|
||||||
|
RAMStream::read (void* buffer, int32 n_bytes, int32* n_read)
|
||||||
|
{
|
||||||
|
assert (_pos >= 0 && _pos <= _size);
|
||||||
|
int64 available = _size - _pos;
|
||||||
|
|
||||||
|
if (n_bytes < 0 || available < 0) {
|
||||||
|
n_bytes = 0;
|
||||||
|
} else if (n_bytes > available) {
|
||||||
|
n_bytes = available;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n_bytes > 0) {
|
||||||
|
memcpy(buffer, &_data[_pos], n_bytes);
|
||||||
|
_pos += n_bytes;
|
||||||
|
}
|
||||||
|
if (n_read) {
|
||||||
|
*n_read = n_bytes;
|
||||||
|
}
|
||||||
|
return kResultTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult
|
||||||
|
RAMStream::write (void* buffer, int32 n_bytes, int32* n_written)
|
||||||
|
{
|
||||||
|
if (_readonly) {
|
||||||
|
return kResultFalse;
|
||||||
|
}
|
||||||
|
if (n_bytes < 0) {
|
||||||
|
return kInvalidArgument;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reallocate_buffer (_pos + n_bytes, false)) {
|
||||||
|
return kOutOfMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer && _data && _pos >= 0 && n_bytes > 0) {
|
||||||
|
memcpy (&_data[_pos], buffer, n_bytes);
|
||||||
|
_pos += n_bytes;
|
||||||
|
_size = _pos;
|
||||||
|
} else {
|
||||||
|
n_bytes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n_written) {
|
||||||
|
*n_written = n_bytes;
|
||||||
|
}
|
||||||
|
return kResultTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult
|
||||||
|
RAMStream::seek (int64 pos, int32 mode, int64* result)
|
||||||
|
{
|
||||||
|
switch (mode) {
|
||||||
|
case kIBSeekSet:
|
||||||
|
_pos = pos;
|
||||||
|
break;
|
||||||
|
case kIBSeekCur:
|
||||||
|
_pos += pos;
|
||||||
|
break;
|
||||||
|
case kIBSeekEnd:
|
||||||
|
_pos = _size + pos;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return kInvalidArgument;
|
||||||
|
}
|
||||||
|
if (_pos < 0) {
|
||||||
|
_pos = 0;
|
||||||
|
}
|
||||||
|
if (result) {
|
||||||
|
*result = _pos;
|
||||||
|
}
|
||||||
|
return kResultTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tresult
|
||||||
|
RAMStream::tell (int64* pos)
|
||||||
|
{
|
||||||
|
if (!pos) {
|
||||||
|
return kInvalidArgument;
|
||||||
|
}
|
||||||
|
*pos = _pos;
|
||||||
|
return kResultTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RAMStream::write_int32 (int32 i) {
|
||||||
|
/* pluginterfaces/base/ftypes.h */
|
||||||
|
#if BYTEORDER == kBigEndian
|
||||||
|
SWAP_32 (i)
|
||||||
|
#endif
|
||||||
|
return write_pod (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RAMStream::write_int64 (int64 i)
|
||||||
|
{
|
||||||
|
/* pluginterfaces/base/ftypes.h */
|
||||||
|
#if BYTEORDER == kBigEndian
|
||||||
|
SWAP_64 (i)
|
||||||
|
#endif
|
||||||
|
return write_pod (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RAMStream::write_ChunkID (const Vst::ChunkID& id)
|
||||||
|
{
|
||||||
|
return write_pod (id);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if COM_COMPATIBLE
|
||||||
|
/* pluginterfaces/base/funknown.cpp */
|
||||||
|
struct GUIDStruct {
|
||||||
|
uint32_t data1;
|
||||||
|
uint16_t data2;
|
||||||
|
uint16_t data3;
|
||||||
|
uint8_t data4[8];
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool
|
||||||
|
RAMStream::write_TUID (const TUID& tuid)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int32 n_bytes = 0;
|
||||||
|
char buf[Vst::kClassIDSize + 1];
|
||||||
|
|
||||||
|
#if COM_COMPATIBLE
|
||||||
|
GUIDStruct guid;
|
||||||
|
memcpy (&guid, tuid, sizeof(GUIDStruct));
|
||||||
|
sprintf(buf, "%08X%04X%04X", guid.data1, guid.data2, guid.data3);
|
||||||
|
i += 8;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (; i < (int)sizeof(TUID); ++i){
|
||||||
|
sprintf(buf + 2 * i, "%02X", (uint8_t)tuid[i]);
|
||||||
|
}
|
||||||
|
write (buf, Vst::kClassIDSize, &n_bytes);
|
||||||
|
return n_bytes == Vst::kClassIDSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RAMStream::read_int32 (int32& i) {
|
||||||
|
if (!read_pod (i)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#if BYTEORDER == kBigEndian
|
||||||
|
SWAP_32 (i)
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RAMStream::read_int64 (int64& i) {
|
||||||
|
if (!read_pod (i)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#if BYTEORDER == kBigEndian
|
||||||
|
SWAP_64 (i)
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RAMStream::read_ChunkID (Vst::ChunkID& id)
|
||||||
|
{
|
||||||
|
return read_pod (id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RAMStream::read_TUID (TUID& tuid)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int32 n_bytes = 0;
|
||||||
|
char buf[Vst::kClassIDSize+1];
|
||||||
|
|
||||||
|
read((void *)buf, Vst::kClassIDSize, &n_bytes);
|
||||||
|
if (n_bytes != Vst::kClassIDSize) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[Vst::kClassIDSize] = '\0';
|
||||||
|
|
||||||
|
#if COM_COMPATIBLE
|
||||||
|
GUIDStruct guid;
|
||||||
|
sscanf (buf, "%08x", &guid.data1);
|
||||||
|
sscanf (buf+8, "%04hx", &guid.data2);
|
||||||
|
sscanf (buf+12, "%04hx", &guid.data3);
|
||||||
|
memcpy (tuid, &guid, sizeof(TUID) >> 1);
|
||||||
|
i += 16;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (; i < Vst::kClassIDSize; i += 2){
|
||||||
|
uint32_t temp;
|
||||||
|
sscanf (buf + i, "%02X", &temp);
|
||||||
|
tuid[i >> 1] = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
void
|
||||||
|
RAMStream::hexdump (int64 max_len) const
|
||||||
|
{
|
||||||
|
std::ostringstream out;
|
||||||
|
|
||||||
|
size_t row_size = 16;
|
||||||
|
size_t length = max_len > 0 ? std::min (max_len, _size) : _size;
|
||||||
|
|
||||||
|
out << std::setfill('0');
|
||||||
|
for (size_t i = 0; i < length; i += row_size) {
|
||||||
|
out << "0x" << std::setw(6) << std::hex << i << ": ";
|
||||||
|
for (size_t j = 0; j < row_size; ++j) {
|
||||||
|
if (i + j < length) {
|
||||||
|
out << std::hex << std::setw(2) << static_cast<int>(_data[i + j]) << " ";
|
||||||
|
} else {
|
||||||
|
out << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << " ";
|
||||||
|
if (true) {
|
||||||
|
for (size_t j = 0; j < row_size; ++j) {
|
||||||
|
if (i + j < length) {
|
||||||
|
if (std::isprint(_data[i + j])) {
|
||||||
|
out << static_cast<char>(_data[i + j]);
|
||||||
|
} else {
|
||||||
|
out << ".";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << std::endl;
|
||||||
|
}
|
||||||
|
std::cout << out.str ();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -460,7 +460,7 @@ def build(bld):
|
||||||
obj.defines += [ 'MACVST_SUPPORT' ]
|
obj.defines += [ 'MACVST_SUPPORT' ]
|
||||||
|
|
||||||
if bld.is_defined('VST3_SUPPORT'):
|
if bld.is_defined('VST3_SUPPORT'):
|
||||||
obj.source += [ 'vst3_plugin.cc', 'vst3_module.cc' ]
|
obj.source += [ 'vst3_plugin.cc', 'vst3_module.cc', 'vst3_host.cc' ]
|
||||||
obj.defines += [ 'VST3_SUPPORT' ]
|
obj.defines += [ 'VST3_SUPPORT' ]
|
||||||
|
|
||||||
if bld.is_defined('HAVE_COREAUDIO'):
|
if bld.is_defined('HAVE_COREAUDIO'):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue