//----------------------------------------------------------------------------- // Project : VST SDK // // Category : Helpers // Filename : public.sdk/source/vst/vstpresetfile.h // Created by : Steinberg, 03/2006 // Description : VST 3 Preset File Format // //----------------------------------------------------------------------------- // This file is part of a Steinberg SDK. It is subject to the license terms // in the LICENSE file found in the top-level directory of this distribution // and at www.steinberg.net/sdklicenses. // No part of the SDK, including this file, may be copied, modified, propagated, // or distributed except according to the terms contained in the LICENSE file. //----------------------------------------------------------------------------- #pragma once #include "pluginterfaces/vst/ivstcomponent.h" #include "pluginterfaces/vst/ivsteditcontroller.h" #include "pluginterfaces/vst/ivstunits.h" #include "pluginterfaces/base/ibstream.h" #include "base/source/fbuffer.h" #include #include //------------------------------------------------------------------------ /* VST 3 Preset File Format Definition =================================== 0 +---------------------------+ | HEADER | | header id ('VST3') | 4 Bytes | version | 4 Bytes (int32) | ASCII-encoded class id | 32 Bytes +--| offset to chunk list | 8 Bytes (int64) | +---------------------------+ | | DATA AREA |<-+ | | data of chunks 1..n | | | ... ... | | | | | +->+---------------------------+ | | CHUNK LIST | | | list id ('List') | | 4 Bytes | entry count | | 4 Bytes (int32) +---------------------------+ | | 1..n | | | +----------------------+ | | | | chunk id | | | 4 Bytes | | offset to chunk data |----+ 8 Bytes (int64) | | size of chunk data | | 8 Bytes (int64) | +----------------------+ | EOF +---------------------------+ */ //------------------------------------------------------------------------ namespace Steinberg { namespace Vst { //------------------------------------------------------------------------ using ChunkID = char[4]; //------------------------------------------------------------------------ enum ChunkType { kHeader, kComponentState, kControllerState, kProgramData, kMetaInfo, kChunkList, kNumPresetChunks }; //------------------------------------------------------------------------ extern const ChunkID& getChunkID (ChunkType type); //------------------------------------------------------------------------ inline bool isEqualID (const ChunkID id1, const ChunkID id2) { return memcmp (id1, id2, sizeof (ChunkID)) == 0; } //------------------------------------------------------------------------ /** Handler for a VST 3 Preset File. \ingroup vstClasses \see \ref presetformat */ class PresetFile { public: //------------------------------------------------------------------------ PresetFile (IBStream* stream); ///< Constructor of Preset file based on a stream virtual ~PresetFile (); /** Internal structure used for chunk handling */ struct Entry { ChunkID id; TSize offset; TSize size; }; IBStream* getStream () const { return stream; } ///< Returns the associated stream. const FUID& getClassID () const { return classID; } ///< Returns the associated classID (component ID: Processor part (not the controller!)). void setClassID (const FUID& uid) { classID = uid; }///< Sets the associated classID (component ID: Processor part (not the controller!)). const Entry* getEntry (ChunkType which) const; ///< Returns an entry for a given chunk type. const Entry* getLastEntry () const; ///< Returns the last available entry. int32 getEntryCount () const { return entryCount; } ///< Returns the number of total entries in the current stream. const Entry& at (int32 index) const { return entries[index]; } ///< Returns the entry at a given position. bool contains (ChunkType which) const { return getEntry (which) != nullptr; } ///< Checks if a given chunk type exist in the stream. bool readChunkList (); ///< Reads and build the chunk list (including the header chunk). bool writeHeader (); ///< Writes into the stream the main header. bool writeChunkList (); ///< Writes into the stream the chunk list (should be at the end). /** Reads the meta XML info and its size, the size could be retrieved by passing zero as xmlBuffer. */ bool readMetaInfo (char* xmlBuffer, int32& size); /** Writes the meta XML info, -1 means null-terminated, forceWriting to true will force to rewrite the XML Info when the chunk already exists. */ bool writeMetaInfo (const char* xmlBuffer, int32 size = -1, bool forceWriting = false); bool prepareMetaInfoUpdate (); ///< checks if meta info chunk is the last one and jump to correct position. /** Writes a given data of a given size as "which" chunk type. */ bool writeChunk (const void* data, int32 size, ChunkType which = kComponentState); //------------------------------------------------------------- // for storing and restoring the whole plug-in state (component and controller states) bool seekToComponentState (); ///< Seeks to the begin of the Component State. bool storeComponentState (IComponent* component); ///< Stores the component state (only one time). bool storeComponentState (IBStream* componentStream); ///< Stores the component state from stream (only one time). bool restoreComponentState (IComponent* component); ///< Restores the component state. bool seekToControllerState (); ///< Seeks to the begin of the Controller State. bool storeControllerState (IEditController* editController);///< Stores the controller state (only one time). bool storeControllerState (IBStream* editStream); ///< Stores the controller state from stream (only one time). bool restoreControllerState (IEditController* editController);///< Restores the controller state. bool restoreComponentState (IEditController* editController);///< Restores the component state and apply it to the controller. //--- ---------------------------------------------------------- /** Store program data or unit data from stream (including the header chunk). \param inStream \param listID could be ProgramListID or UnitID. */ bool storeProgramData (IBStream* inStream, ProgramListID listID); //---when plug-in uses IProgramListData----------------------- /** Stores a IProgramListData with a given identifier and index (including the header chunk). */ bool storeProgramData (IProgramListData* programListData, ProgramListID programListID, int32 programIndex); /** Restores a IProgramListData with a given identifier and index. */ bool restoreProgramData (IProgramListData* programListData, ProgramListID* programListID = nullptr, int32 programIndex = 0); //---when plug-in uses IUnitData------------------------------ /** Stores a IUnitData with a given unitID (including the header chunk). */ bool storeProgramData (IUnitData* unitData, UnitID unitID); /** Restores a IUnitData with a given unitID (optional). */ bool restoreProgramData (IUnitData* unitData, UnitID* unitID = nullptr); //--- ---------------------------------------------------------- /** for keeping the controller part in sync concerning preset data stream, unitProgramListID * could be ProgramListID or UnitID. */ bool restoreProgramData (IUnitInfo* unitInfo, int32 unitProgramListID, int32 programIndex = -1); /** Gets the unitProgramListID saved in the kProgramData chunk (if available). */ bool getUnitProgramListID (int32& unitProgramListID); //--- --------------------------------------------------------------------- /** Shortcut helper to create preset from component/controller state. classID is the FUID of the * component (processor) part. */ static bool savePreset (IBStream* stream, const FUID& classID, IComponent* component, IEditController* editController = nullptr, const char* xmlBuffer = nullptr, int32 xmlSize = -1); static bool savePreset (IBStream* stream, const FUID& classID, IBStream* componentStream, IBStream* editStream = nullptr, const char* xmlBuffer = nullptr, int32 xmlSize = -1); /** Shortcut helper to load preset with component/controller state. classID is the FUID of the * component (processor) part. */ static bool loadPreset (IBStream* stream, const FUID& classID, IComponent* component, IEditController* editController = nullptr, std::vector* otherClassIDArray = nullptr); //------------------------------------------------------------------------ protected: bool readID (ChunkID id); bool writeID (const ChunkID id); bool readEqualID (const ChunkID id); bool readSize (TSize& size); bool writeSize (TSize size); bool readInt32 (int32& value); bool writeInt32 (int32 value); bool seekTo (TSize offset); bool beginChunk (Entry& e, ChunkType which); bool endChunk (Entry& e); IBStream* stream; FUID classID; ///< classID is the FUID of the component (processor) part enum { kMaxEntries = 128 }; Entry entries[kMaxEntries]; int32 entryCount {0}; }; //------------------------------------------------------------------------ /** Stream implementation for a file using stdio. */ class FileStream: public IBStream { public: //------------------------------------------------------------------------ static IBStream* open (const char* filename, const char* mode); ///< open a stream using stdio function //---from FUnknown------------------ DECLARE_FUNKNOWN_METHODS //---from IBStream------------------ tresult PLUGIN_API read (void* buffer, int32 numBytes, int32* numBytesRead = nullptr) SMTG_OVERRIDE; tresult PLUGIN_API write (void* buffer, int32 numBytes, int32* numBytesWritten = nullptr) SMTG_OVERRIDE; tresult PLUGIN_API seek (int64 pos, int32 mode, int64* result = nullptr) SMTG_OVERRIDE; tresult PLUGIN_API tell (int64* pos) SMTG_OVERRIDE; //------------------------------------------------------------------------ protected: FileStream (FILE* file); virtual ~FileStream (); FILE* file; }; //------------------------------------------------------------------------ /** Stream representing a Read-Only subsection of its source stream. */ class ReadOnlyBStream: public IBStream { public: //------------------------------------------------------------------------ ReadOnlyBStream (IBStream* sourceStream, TSize sourceOffset, TSize sectionSize); virtual ~ReadOnlyBStream (); //---from FUnknown------------------ DECLARE_FUNKNOWN_METHODS //---from IBStream------------------ tresult PLUGIN_API read (void* buffer, int32 numBytes, int32* numBytesRead = nullptr) SMTG_OVERRIDE; tresult PLUGIN_API write (void* buffer, int32 numBytes, int32* numBytesWritten = nullptr) SMTG_OVERRIDE; tresult PLUGIN_API seek (int64 pos, int32 mode, int64* result = nullptr) SMTG_OVERRIDE; tresult PLUGIN_API tell (int64* pos) SMTG_OVERRIDE; //------------------------------------------------------------------------ protected: IBStream* sourceStream; TSize sourceOffset; TSize sectionSize; TSize seekPosition; }; //------------------------------------------------------------------------ /** Stream implementation for a memory buffer. */ class BufferStream : public IBStream { public: BufferStream (); virtual ~BufferStream (); //---from FUnknown------------------ DECLARE_FUNKNOWN_METHODS //---from IBStream------------------ tresult PLUGIN_API read (void* buffer, int32 numBytes, int32* numBytesRead = nullptr) SMTG_OVERRIDE; tresult PLUGIN_API write (void* buffer, int32 numBytes, int32* numBytesWritten = nullptr) SMTG_OVERRIDE; tresult PLUGIN_API seek (int64 pos, int32 mode, int64* result = nullptr) SMTG_OVERRIDE; tresult PLUGIN_API tell (int64* pos) SMTG_OVERRIDE; protected: Buffer mBuffer; }; //------------------------------------------------------------------------ } // namespace Vst } // namespace Steinberg