Initial release
This commit is contained in:
@@ -0,0 +1,281 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Project : VST SDK
|
||||
//
|
||||
// Category : Helpers
|
||||
// Filename : public.sdk/source/vst/interappaudio/PresetManager.mm
|
||||
// Created by : Steinberg, 10/2013
|
||||
// Description : VST 3 InterAppAudio
|
||||
// Flags : clang-format SMTGSequencer
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#import "PresetManager.h"
|
||||
#import "PresetBrowserViewController.h"
|
||||
#import "PresetSaveViewController.h"
|
||||
#import "public.sdk/source/vst/vstpresetfile.h"
|
||||
#import "pluginterfaces/vst/ivstattributes.h"
|
||||
|
||||
namespace Steinberg {
|
||||
namespace Vst {
|
||||
namespace InterAppAudio {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class PresetStream : public ReadOnlyBStream, public IStreamAttributes
|
||||
{
|
||||
public:
|
||||
PresetStream (IBStream* sourceStream, TSize sourceOffset, TSize sectionSize,
|
||||
const char* utf8Path)
|
||||
: ReadOnlyBStream (sourceStream, sourceOffset, sectionSize), fileName (utf8Path)
|
||||
{
|
||||
fileName.toWideString (kCP_Utf8);
|
||||
}
|
||||
|
||||
virtual tresult PLUGIN_API getFileName (String128 name) override
|
||||
{
|
||||
if (fileName.length () > 0)
|
||||
{
|
||||
fileName.copyTo (name, 0, 128);
|
||||
return kResultTrue;
|
||||
}
|
||||
return kResultFalse;
|
||||
}
|
||||
virtual IAttributeList* PLUGIN_API getAttributes () override { return nullptr; }
|
||||
|
||||
DEF_INTERFACES_1 (IStreamAttributes, ReadOnlyBStream)
|
||||
REFCOUNT_METHODS (ReadOnlyBStream)
|
||||
protected:
|
||||
String fileName;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
PresetManager::PresetManager (VST3Plugin* plugin, const TUID& cid)
|
||||
: plugin (plugin)
|
||||
, visiblePresetBrowserViewController (nil)
|
||||
, visibleSavePresetViewController (nil)
|
||||
, cid (cid)
|
||||
{
|
||||
id obj = [[NSUserDefaults standardUserDefaults] objectForKey:@"PresetManager|lastPreset"];
|
||||
if (obj && [obj isKindOfClass:[NSString class]])
|
||||
{
|
||||
lastPreset = [obj UTF8String];
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
NSArray* PresetManager::getPresetPaths (PresetPathType type)
|
||||
{
|
||||
if (type == kFactory)
|
||||
{
|
||||
return [[NSBundle mainBundle] URLsForResourcesWithExtension:@"vstpreset"
|
||||
subdirectory:@"Presets"];
|
||||
}
|
||||
NSFileManager* fs = [NSFileManager defaultManager];
|
||||
NSURL* documentsUrl = [fs URLForDirectory:NSDocumentDirectory
|
||||
inDomain:NSUserDomainMask
|
||||
appropriateForURL:Nil
|
||||
create:YES
|
||||
error:NULL];
|
||||
if (documentsUrl)
|
||||
{
|
||||
NSMutableArray* userUrls = [NSMutableArray new];
|
||||
NSDirectoryEnumerator* enumerator =
|
||||
[fs enumeratorAtURL:documentsUrl
|
||||
includingPropertiesForKeys:nil
|
||||
options:NSDirectoryEnumerationSkipsSubdirectoryDescendants
|
||||
errorHandler:nil];
|
||||
for (NSURL* url in enumerator.allObjects)
|
||||
{
|
||||
if ([[url pathExtension] isEqualToString:@"vstpreset"])
|
||||
{
|
||||
[userUrls addObject:url];
|
||||
}
|
||||
}
|
||||
return [userUrls sortedArrayUsingComparator:^NSComparisonResult (NSURL* obj1, NSURL* obj2) {
|
||||
return [[obj1 lastPathComponent] caseInsensitiveCompare:[obj2 lastPathComponent]];
|
||||
}];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
tresult PLUGIN_API PresetManager::runLoadPresetBrowser ()
|
||||
{
|
||||
if (visiblePresetBrowserViewController != nil)
|
||||
return kResultFalse;
|
||||
|
||||
addRef ();
|
||||
visiblePresetBrowserViewController =
|
||||
[[PresetBrowserViewController alloc] initWithCallback:[this] (const char* path) {
|
||||
loadPreset (path);
|
||||
visiblePresetBrowserViewController = nil;
|
||||
release ();
|
||||
}];
|
||||
addRef ();
|
||||
dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
if (visiblePresetBrowserViewController)
|
||||
{
|
||||
[visiblePresetBrowserViewController setFactoryPresets:getPresetPaths (kFactory)
|
||||
userPresets:getPresetPaths (kUser)];
|
||||
}
|
||||
release ();
|
||||
});
|
||||
return kResultTrue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
tresult PLUGIN_API PresetManager::runSavePresetBrowser ()
|
||||
{
|
||||
if (visibleSavePresetViewController != nil)
|
||||
return kResultFalse;
|
||||
|
||||
addRef ();
|
||||
visibleSavePresetViewController =
|
||||
[[PresetSaveViewController alloc] initWithCallback:[this] (const char* path) {
|
||||
savePreset (path);
|
||||
visibleSavePresetViewController = nil;
|
||||
release ();
|
||||
}];
|
||||
return kResultTrue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
tresult PLUGIN_API PresetManager::loadNextPreset ()
|
||||
{
|
||||
return loadPreset (true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
tresult PLUGIN_API PresetManager::loadPreviousPreset ()
|
||||
{
|
||||
return loadPreset (false);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
tresult PresetManager::loadPreset (bool next)
|
||||
{
|
||||
NSArray* presets =
|
||||
[[getPresetPaths (kFactory) arrayByAddingObjectsFromArray:getPresetPaths (kUser)]
|
||||
sortedArrayUsingComparator:^NSComparisonResult (NSURL* obj1, NSURL* obj2) {
|
||||
return [[obj1 lastPathComponent] caseInsensitiveCompare:[obj2 lastPathComponent]];
|
||||
}];
|
||||
|
||||
__block NSUInteger index = NSNotFound;
|
||||
if (lastPreset.isEmpty () == false)
|
||||
{
|
||||
NSURL* lastUrl =
|
||||
[[NSURL fileURLWithPath:[NSString stringWithUTF8String:lastPreset]] fileReferenceURL];
|
||||
if (lastUrl)
|
||||
{
|
||||
[presets enumerateObjectsUsingBlock:^(NSURL* obj, NSUInteger idx, BOOL* stop) {
|
||||
if ([[obj fileReferenceURL] isEqual:lastUrl])
|
||||
{
|
||||
index = idx;
|
||||
*stop = YES;
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
if (index == NSNotFound)
|
||||
{
|
||||
if (next)
|
||||
index = [presets count] - 1;
|
||||
else
|
||||
index = 1;
|
||||
}
|
||||
if (index != NSNotFound)
|
||||
{
|
||||
if (next)
|
||||
{
|
||||
if (index >= [presets count] - 1)
|
||||
index = 0;
|
||||
else
|
||||
index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (index == 0)
|
||||
index = [presets count] - 1;
|
||||
else
|
||||
index--;
|
||||
}
|
||||
return loadPreset ([[[presets objectAtIndex:index] path] UTF8String]);
|
||||
}
|
||||
return kResultFalse;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
tresult PresetManager::loadPreset (const char* path)
|
||||
{
|
||||
if (path)
|
||||
{
|
||||
IPtr<IBStream> stream = owned (FileStream::open (path, "r"));
|
||||
if (stream)
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithUTF8String:path]
|
||||
forKey:@"PresetManager|lastPreset"];
|
||||
lastPreset = path;
|
||||
auto component = U::cast<IComponent> (plugin->getAudioProcessor ());
|
||||
IEditController* controller = plugin->getEditController ();
|
||||
if (component)
|
||||
{
|
||||
PresetFile pf (stream);
|
||||
if (!pf.readChunkList ())
|
||||
return kResultFalse;
|
||||
if (pf.getClassID () != cid)
|
||||
return kResultFalse;
|
||||
const PresetFile::Entry* e = pf.getEntry (kComponentState);
|
||||
if (e == nullptr)
|
||||
return kResultFalse;
|
||||
auto filename = strrchr (path, '/');
|
||||
if (filename)
|
||||
filename++;
|
||||
IPtr<PresetStream> readOnlyBStream =
|
||||
owned (new PresetStream (stream, e->offset, e->size, filename));
|
||||
tresult result = component->setState (readOnlyBStream);
|
||||
if ((result == kResultTrue || result == kNotImplemented) && controller)
|
||||
{
|
||||
readOnlyBStream->seek (0, IBStream::kIBSeekSet);
|
||||
controller->setComponentState (readOnlyBStream);
|
||||
if (pf.contains (kControllerState))
|
||||
{
|
||||
e = pf.getEntry (kControllerState);
|
||||
if (e)
|
||||
{
|
||||
readOnlyBStream =
|
||||
owned (new PresetStream (stream, e->offset, e->size, filename));
|
||||
controller->setState (readOnlyBStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return kResultFalse;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PresetManager::savePreset (const char* path)
|
||||
{
|
||||
IBStream* stream = FileStream::open (path, "w");
|
||||
if (stream)
|
||||
{
|
||||
auto component = U::cast<IComponent> (plugin->getAudioProcessor ());
|
||||
IEditController* controller = plugin->getEditController ();
|
||||
if (component)
|
||||
{
|
||||
PresetFile::savePreset (stream, cid, component, controller);
|
||||
}
|
||||
stream->release ();
|
||||
loadPreset (path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespaces
|
||||
Reference in New Issue
Block a user