32#include "../../widgets/ProgressDialog.h"
35#if defined(BUILDING_AUDACITY)
36#include "../../PlatformCompatibility.h"
54#include <wx/busyinfo.h>
56#include <wx/combobox.h>
58#include <wx/filename.h>
59#include <wx/imaglist.h>
60#include <wx/listctrl.h>
63#include <wx/process.h>
64#include <wx/recguard.h>
67#include <wx/scrolwin.h>
68#include <wx/sstream.h>
69#include <wx/statbox.h>
70#include <wx/stattext.h>
72#include <wx/tokenzr.h>
77#pragma comment(lib, "shlwapi")
87#include "../../SelectFile.h"
88#include "../../ShuttleGui.h"
89#include "../../widgets/valnum.h"
90#include "../../widgets/AudacityMessageBox.h"
91#include "../../widgets/NumericTextCtrl.h"
95#if wxUSE_ACCESSIBILITY
96#include "../../widgets/WindowAccessible.h"
105#if defined(__WXOSX__)
107#elif defined(__WXMSW__)
109#elif defined(__WXGTK__)
115 static_assert(
sizeof(float) ==
sizeof(uint32_t),
"Cannot reinterpret uint32_t to float since sizes are different.");
117 std::memcpy(&f, &x,
sizeof(
float));
123 static_assert(
sizeof(float) ==
sizeof(uint32_t),
"Cannot reinterpret float to uint32_t since sizes are different.");
126 std::memcpy(&x, &f,
sizeof(uint32_t));
188 return XO(
"VST Effects");
193 return XO(
"The Audacity Team");
199 return AUDACITY_VERSION_STRING;
204 return XO(
"Adds the ability to use VST effects in Audacity.");
256 wxString vstpath = wxString::FromUTF8(getenv(
"VST_PATH"));
257 if (!vstpath.empty())
259 wxStringTokenizer tok(vstpath, wxPATH_SEP);
260 while (tok.HasMoreTokens())
262 pathList.push_back(tok.GetNextToken());
266#if defined(__WXMAC__)
267#define VSTPATH wxT("/Library/Audio/Plug-Ins/VST")
270 pathList.push_back(wxGetHomeDir() + wxFILE_SEP_PATH +
VSTPATH);
278 for (
size_t i = 0; i < files.size(); i++)
280 files[i] = wxPathOnly(wxPathOnly(files[i]));
281 if (!files[i].EndsWith(wxT(
".vst")))
283 files.erase( files.begin() + i-- );
287#elif defined(__WXMSW__)
289 TCHAR dpath[MAX_PATH];
290 TCHAR tpath[MAX_PATH];
294 len = WXSIZEOF(tpath);
295 if (SHRegGetUSValue(wxT(
"Software\\VST"),
296 wxT(
"VSTPluginsPath"),
306 ExpandEnvironmentStrings(tpath, dpath, WXSIZEOF(dpath));
307 pathList.push_back(dpath);
311 len = WXSIZEOF(tpath);
312 if (SHRegGetUSValue(wxT(
"Software\\VST"),
313 wxT(
"VSTPluginsPath"),
323 ExpandEnvironmentStrings(tpath, dpath, WXSIZEOF(dpath));
324 pathList.push_back(dpath);
329 ExpandEnvironmentStrings(wxT(
"%ProgramFiles%\\Steinberg\\VSTPlugins"),
332 pathList.push_back(dpath);
343 pathList.push_back(wxT(LIBDIR) wxT(
"/vst"));
346 pathList.push_back(wxT(
"/usr/lib/vst"));
347 pathList.push_back(wxT(
"/usr/local/lib/vst"));
348 pathList.push_back(wxGetHomeDir() + wxFILE_SEP_PATH + wxT(
".vst"));
356 return { files.begin(), files.end() };
368 if(effectIDs.empty())
370 effectIDs.push_back(0);
372 for(
auto id : effectIDs)
377 VSTEffect subeffect(wxString::Format(
"%s;%d", path,
id), &effect);
379 callback(
this, &subeffect);
381 return effectIDs.size();
383 errMsg =
XO(
"Could not load the library");
391 wxString realPath = path.BeforeFirst(wxT(
';'));
392 return wxFileName::FileExists(realPath) || wxFileName::DirExists(realPath);
395std::unique_ptr<ComponentInterface>
400 auto result = std::make_unique<VSTEffect>(path);
401 result->InitializePlugin();
427 void OnOk(wxCommandEvent & evt);
435 DECLARE_EVENT_TABLE()
448 wxT(
"BufferSize"), mBufferSize, 8192);
450 wxT(
"UseLatency"), mUseLatency,
true);
452 wxT(
"UseGUI"), mUseGUI,
true);
455 PopulateOrExchange(
S);
465 S.StartHorizontalLay(wxEXPAND, 1);
467 S.StartVerticalLay(
false);
469 S.StartStatic(
XO(
"Buffer Size"));
471 S.AddVariableText(
XO(
472"The buffer size controls the number of samples sent to the effect "
473"on each iteration. Smaller values will cause slower processing and "
474"some effects require 8192 samples or less to work properly. However "
475"most effects can accept large buffers and using them will greatly "
476"reduce processing time."),
479 S.StartHorizontalLay(wxALIGN_LEFT);
482 t =
S.Validator<IntegerValidator<int>>(
483 &
mBufferSize, NumValidatorStyle::DEFAULT, 8, 1048576 * 1)
484 .MinSize( { 100, -1 } )
485 .TieNumericTextBox(
XXO(
"&Buffer Size (8 to 1048576 samples):"),
489 S.EndHorizontalLay();
493 S.StartStatic(
XO(
"Latency Compensation"));
495 S.AddVariableText(
XO(
496"As part of their processing, some VST effects must delay returning "
497"audio to Audacity. When not compensating for this delay, you will "
498"notice that small silences have been inserted into the audio. "
499"Enabling this option will provide that compensation, but it may "
500"not work for all VST effects."),
503 S.StartHorizontalLay(wxALIGN_LEFT);
505 S.TieCheckBox(
XXO(
"Enable &compensation"),
508 S.EndHorizontalLay();
512 S.StartStatic(
XO(
"Graphical Mode"));
514 S.AddVariableText(
XO(
515"Most VST effects have a graphical interface for setting parameter values."
516" A basic text-only method is also available. "
517" Reopen the effect for this to take effect."),
519 S.TieCheckBox(
XXO(
"Enable &graphical interface"),
526 S.EndHorizontalLay();
528 S.AddStandardButtons();
598BEGIN_EVENT_TABLE(
VSTEffect, wxEvtHandler)
624 return (intptr_t) 2400;
627 return mCurrentEffectID;
630 strcpy((
char *) ptr,
"Audacity Team");
634 strcpy((
char *) ptr,
"Audacity");
638 return (intptr_t) (AUDACITY_VERSION << 24 |
639 AUDACITY_RELEASE << 16 |
640 AUDACITY_REVISION << 8 |
718 char *s = (
char *) ptr;
719 if (strcmp(s,
"acceptIOChanges") == 0 ||
720 strcmp(s,
"sendVstTimeInfo") == 0 ||
721 strcmp(s,
"startStopProcess") == 0 ||
722 strcmp(s,
"shellCategory") == 0 ||
723 strcmp(s,
"sizeWindow") == 0)
728#if defined(VST_DEBUG)
729#if defined(__WXMSW__)
730 wxLogDebug(wxT(
"VST canDo: %s"), wxString::FromAscii((
char *)ptr));
732 wxPrintf(wxT(
"VST canDo: %s\n"), wxString::FromAscii((
char *)ptr));
761#if defined(VST_DEBUG)
762#if defined(__WXMSW__)
763 wxLogDebug(wxT(
"vst: %p opcode: %d index: %d value: %p ptr: %p opt: %f user: %p"),
764 effect, (
int) opcode, (
int) index, (
void *) value, ptr, opt, vst);
766 wxPrintf(wxT(
"vst: %p opcode: %d index: %d value: %p ptr: %p opt: %f user: %p\n"),
767 effect, (
int) opcode, (
int) index, (
void *) value, ptr, opt, vst);
774#if !defined(__WXMSW__)
775void VSTEffect::ModuleDeleter::operator() (
void* p)
const
782#if defined(__WXMAC__)
799 mTimer = std::make_unique<VSTEffectTimer>(
this);
866 bool skipping =
true;
867 for (
int i = 0, s = 0; i < 4; i++, s += 8)
870 if (dig != 0 || !skipping)
872 version += !skipping ? wxT(
".") : wxT(
"");
873 version += wxString::Format(wxT(
"%d"), dig);
972 wxT(
"BufferSize"), userBlockSize, 8192);
977 return std::make_shared<Instance>(*
this);
1076 const float *
const *inBlock,
float *
const *outBlock,
size_t blockLen)
1109 mSlaves.push_back(std::make_unique<VSTEffect>(
mPath,
this));
1145return GuardedCall<bool>([&]{
1146 for (
const auto &slave : mSlaves)
1147 slave->ProcessFinalize();
1150 return ProcessFinalize();
1158 for (
const auto &slave :
mSlaves)
1166return GuardedCall<bool>([&]{
1169 for (
const auto &slave :
mSlaves)
1182 const float *
const *inbuf,
float *
const *outbuf,
size_t numSamples)
1185 return mSlaves[group]->ProcessBlock(
settings, inbuf, outbuf, numSamples);
1220 wxWindow &parent, wxDialog &dialog,
bool forceModal)
1257 name.Printf(wxT(
"parm_%d"), i);
1261 if (!parms.Write(
name, value))
1279 name.Printf(wxT(
"parm_%d"), i);
1283 if (!parms.Read(
name, &d))
1288 if (d >= -1.0 && d <= 1.0)
1291 for (
const auto &slave :
mSlaves)
1292 slave->callSetParameter(i, d);
1366 auto parent =
S.GetParent();
1367 mDialog =
static_cast<wxDialog *
>(wxGetTopLevelParent(parent));
1370 mParent->PushEventHandler(
this);
1395 return std::make_unique<DefaultEffectUIValidator>(*
this, access);
1414#ifdef __WX_EVTLOOP_BUSY_WAITING__
1415 wxEventLoop::SetBusyWaiting(
false);
1420 mParent->RemoveEventHandler(
this);
1453 path =
SelectFile(FileNames::Operation::Presets,
1454 XO(
"Save VST Preset As:"),
1459 {
XO(
"Standard VST bank file"), { wxT(
"fxb") },
true },
1460 {
XO(
"Standard VST program file"), { wxT(
"fxp") },
true },
1461 {
XO(
"Audacity VST preset file"), { wxT(
"xml") },
true },
1463 wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER,
1472 wxFileName
fn(path);
1473 wxString ext =
fn.GetExt();
1474 if (ext.CmpNoCase(wxT(
"fxb")) == 0)
1478 else if (ext.CmpNoCase(wxT(
"fxp")) == 0)
1482 else if (ext.CmpNoCase(wxT(
"xml")) == 0)
1491 XO(
"Unrecognized file extension."),
1492 XO(
"Error Saving VST Presets"),
1510 path =
SelectFile(FileNames::Operation::Presets,
1511 XO(
"Load VST Preset:"),
1516 XO(
"VST preset files"),
1517 { wxT(
"fxb"), wxT(
"fxp"), wxT(
"xml") },
1520 wxFD_OPEN | wxRESIZE_BORDER,
1529 wxFileName
fn(path);
1530 wxString ext =
fn.GetExt();
1531 bool success =
false;
1532 if (ext.CmpNoCase(wxT(
"fxb")) == 0)
1536 else if (ext.CmpNoCase(wxT(
"fxp")) == 0)
1540 else if (ext.CmpNoCase(wxT(
"xml")) == 0)
1548 XO(
"Unrecognized file extension."),
1549 XO(
"Error Loading VST Presets"),
1559 XO(
"Unable to load presets file."),
1560 XO(
"Error Loading VST Presets"),
1580 if (dlg.ShowModal())
1585 wxT(
"BufferSize"), userBlockSize, 8192);
1599 bool success =
false;
1602 wxString realPath =
mPath.BeforeFirst(wxT(
';'));
1603 mPath.AfterFirst(wxT(
';')).ToLong(&effectID);
1609#if defined(__WXMAC__)
1616 wxCFStringRef path(realPath);
1619 BundleHandle bundleRef{ CFBundleCreate(kCFAllocatorDefault,
1622 CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
1623 path, kCFURLPOSIXPathStyle,
true)
1634 Boolean good = CFURLGetFileSystemRepresentation(
1636 CF_ptr<CFURLRef>{ CFBundleCopyExecutableURL(bundleRef.get()) }.get(),
1637 true, exePath,
sizeof(exePath)
1645 mModule.reset((
char*)dlopen((
char *) exePath, RTLD_NOW | RTLD_LOCAL));
1653 if (pluginMain == NULL)
1659 if (pluginMain == NULL)
1674#elif defined(__WXMSW__)
1680 auto lib = std::make_unique<wxDynamicLibrary>(realPath);
1685 if (!lib->IsLoaded())
1689 pluginMain = (
vstPluginMain) lib->GetSymbol(wxT(
"VSTPluginMain"));
1690 if (pluginMain == NULL)
1693 if (pluginMain == NULL)
1719#ifndef RTLD_DEEPBIND
1720#define RTLD_DEEPBIND 0
1723 (
char*) dlopen((
const char *)wxString(realPath).ToUTF8(),
1724 RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND)
1732 pluginMain = (
vstPluginMain) dlsym(lib.get(),
"VSTPluginMain");
1733 if (pluginMain == NULL)
1736 if (pluginMain == NULL)
1752 wxLogMessage(wxT(
"VST plugin initialization failed\n"));
1792 if (
mName.length() == 0)
1797 if (
mName.length() == 0)
1799 mName = wxFileName{realPath}.GetName();
1873#if defined(__WXMAC__)
1885 std::vector<int> effectIDs;
1896 effectIDs.push_back(effectID);
1991 group, wxT(
"Parameters"), parms);
1999 if (guard.IsInside())
2088 wxCommandEvent sw(EVT_SIZEWINDOW);
2091 mParent->GetEventHandler()->AddPendingEvent(sw);
2103 wxCommandEvent ud(EVT_UPDATEDISPLAY);
2104 mParent->GetEventHandler()->AddPendingEvent(ud);
2118 for (
const auto &slave :
mSlaves)
2119 slave->callSetParameter(index, value);
2139 memset(buf, 0,
sizeof(buf));
2144 outstr = wxString::FromUTF8(buf);
2161 strcpy(buf,
str.Left(255).ToUTF8());
2167 int index, intptr_t value,
void *ptr,
float opt)
2170 wxCRIT_SECT_LOCKER(locker, mDispatcherLock);
2175 int index, intptr_t value,
void *ptr,
float opt)
const
2183 float *
const *outputs,
int sampleframes)
2186 const_cast<float**
>(inputs),
2187 const_cast<float**
>(outputs), sampleframes);
2201 for (
const auto &slave :
mSlaves)
2202 slave->callSetParameter(index, value);
2211 for (
const auto &slave :
mSlaves)
2212 slave->callSetProgram(index);
2221 memset(&info, 0,
sizeof(info));
2253 for (
const auto &slave :
mSlaves)
2254 slave->callSetChunk(isPgm, len, buf, info);
2270 wxWindow *w = (wxWindow *) evt.GetEventObject();
2271 wxSize sz = w->GetMinSize();
2273 if (sz != wxDefaultSize)
2290 if (!control->Create(
mParent,
this))
2296 auto mainSizer = std::make_unique<wxBoxSizer>(wxVERTICAL);
2298 mainSizer->Add((
mControl = control.release()), 0, wxALIGN_CENTER);
2300 mParent->SetMinSize(wxDefaultSize);
2301 mParent->SetSizer(mainSizer.release());
2309#ifdef __WX_EVTLOOP_BUSY_WAITING__
2310 wxEventLoop::SetBusyWaiting(
true);
2320 wxScrolledWindow *
const scroller =
safenew wxScrolledWindow(
mParent,
2324 wxVSCROLL | wxTAB_TRAVERSAL);
2327 auto mainSizer = std::make_unique<wxBoxSizer>(wxVERTICAL);
2330 scroller->SetMinSize(wxSize(wxMax(600,
mParent->GetSize().GetWidth() * 2 / 3),
2331 mParent->GetSize().GetHeight() / 2));
2332 scroller->SetScrollRate(0, 20);
2335 scroller->SetName(wxT(
"\a"));
2336 scroller->SetLabel(wxT(
"\a"));
2338 mainSizer->Add(scroller, 1, wxEXPAND | wxALL, 5);
2339 mParent->SetSizer(mainSizer.release());
2348 auto paramSizer = std::make_unique<wxStaticBoxSizer>(wxVERTICAL, scroller,
_(
"Effect Settings"));
2351 auto gridSizer = std::make_unique<wxFlexGridSizer>(4, 0, 0);
2352 gridSizer->AddGrowableCol(1);
2357 wxControl *item =
safenew wxStaticText(scroller, 0,
_(
"Duration:"));
2358 gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
2363 extra.GetDurationFormat(),
2364 extra.GetDuration(),
2369 gridSizer->Add(
mDuration, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2370 gridSizer->Add(1, 1, 0);
2371 gridSizer->Add(1, 1, 0);
2382 if (text.Right(1) != wxT(
':'))
2387 scroller->GetTextExtent(text, &w, &h);
2394 scroller->GetTextExtent(wxT(
"HHHHHHHH"), &w, &h);
2403 wxALIGN_RIGHT | wxST_NO_AUTORESIZE);
2404 gridSizer->Add(
mNames[i], 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
2413 gridSizer->Add(
mSliders[i], 0, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxALL, 5);
2414#if wxUSE_ACCESSIBILITY
2424 wxALIGN_RIGHT | wxST_NO_AUTORESIZE);
2425 gridSizer->Add(
mDisplays[i], 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
2432 wxALIGN_LEFT | wxST_NO_AUTORESIZE);
2433 gridSizer->Add(
mLabels[i], 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, 5);
2436 paramSizer->Add(gridSizer.release(), 1, wxEXPAND | wxALL, 5);
2438 scroller->SetSizer(paramSizer.release());
2457 text = text.Trim(
true).Trim(
false);
2459 wxString
name = text;
2461 if (text.Right(1) != wxT(
':'))
2465 mNames[i]->SetLabel(text);
2482 mDisplays[i]->SetLabel(wxString::Format(wxT(
"%8s"), text));
2483 name += wxT(
' ') + text;
2489 mLabels[i]->SetLabel(wxString::Format(wxT(
"%8s"), text));
2490 name += wxT(
' ') + text;
2504 mControl->SetMinSize(wxSize(evt.GetInt(), (
int) evt.GetExtraLong()));
2505 mControl->SetSize(wxSize(evt.GetInt(), (
int) evt.GetExtraLong()));
2511 mDialog->SetMinSize(wxDefaultSize);
2512 mDialog->SetMaxSize(wxDefaultSize);
2521 wxSlider *s = (wxSlider *) evt.GetEventObject();
2534 wxFFile f(
fn.GetFullPath(), wxT(
"rb"));
2545 XO(
"Unable to allocate memory when loading presets file."),
2546 XO(
"Error Loading VST Presets"),
2551 unsigned char *bptr = data.get();
2556 ssize_t len = f.Read((
void *) bptr, f.Length());
2560 XO(
"Unable to read presets file."),
2561 XO(
"Error Loading VST Presets"),
2568 int32_t *iptr = (int32_t *) bptr;
2577 if (wxINT32_SWAP_ON_LE(iptr[0]) !=
CCONST(
'C',
'c',
'n',
'K'))
2585 int version = wxINT32_SWAP_ON_LE(iptr[3]);
2586 if (version != 1 && version != 2)
2594 wxINT32_SWAP_ON_LE(iptr[4]),
2595 wxINT32_SWAP_ON_LE(iptr[5]),
2596 wxINT32_SWAP_ON_LE(iptr[6]),
2615 curProg = wxINT32_SWAP_ON_LE(iptr[7]);
2616 if (curProg < 0 || curProg >= numProgs)
2623 if (wxINT32_SWAP_ON_LE(iptr[2]) ==
CCONST(
'F',
'x',
'B',
'k'))
2629 unsigned char *tempPtr = bptr;
2630 ssize_t tempLen = len;
2633 for (
int i = 0; i < numProgs; i++)
2648 for (
int i = 0; i < numProgs; i++)
2654 else if (wxINT32_SWAP_ON_LE(iptr[2]) ==
CCONST(
'F',
'B',
'C',
'h'))
2669 int size = wxINT32_SWAP_ON_LE(iptr[39]);
2672 int proglen = 160 +
size;
2693 if (ret && version >= 2)
2707 wxFFile f(
fn.GetFullPath(), wxT(
"rb"));
2718 XO(
"Unable to allocate memory when loading presets file."),
2719 XO(
"Error Loading VST Presets"),
2724 unsigned char *bptr = data.get();
2729 ssize_t len = f.Read((
void *) bptr, f.Length());
2733 XO(
"Unable to read presets file."),
2734 XO(
"Error Loading VST Presets"),
2757 int32_t *iptr = (int32_t *) *bptr;
2766 if (wxINT32_SWAP_ON_LE(iptr[0]) !=
CCONST(
'C',
'c',
'n',
'K'))
2774#if defined(IS_THIS_AN_FXP_ARTIFICAL_LIMITATION)
2775 int version = wxINT32_SWAP_ON_LE(iptr[3]);
2785 wxINT32_SWAP_ON_LE(iptr[4]),
2786 wxINT32_SWAP_ON_LE(iptr[5]),
2787 wxINT32_SWAP_ON_LE(iptr[6]),
2809 wxString progName(wxString::From8BitData((
char *)&iptr[7]));
2812 if (wxINT32_SWAP_ON_LE(iptr[2]) ==
CCONST(
'F',
'x',
'C',
'k'))
2815 int proglen = 56 + (numParams *
sizeof(float));
2824 for (
int i = 0; i < numParams; i++)
2826 uint32_t ival = wxUINT32_SWAP_ON_LE(iptr[14 + i]);
2828 if (val < 0.0 || val > 1.0)
2845 for (
int i = 0; i < numParams; i++)
2847 wxUint32 val = wxUINT32_SWAP_ON_LE(iptr[14 + i]);
2858 else if (wxINT32_SWAP_ON_LE(iptr[2]) ==
CCONST(
'F',
'P',
'C',
'h'))
2873 int size = wxINT32_SWAP_ON_LE(iptr[14]);
2876 int proglen = 60 +
size;
2916 bool ok = reader.
Parse(
this,
fn.GetFullPath());
2931 XO(
"Error Loading VST Presets"),
2943 const wxString fullPath{
fn.GetFullPath()};
2944 wxFFile f(fullPath, wxT(
"wb"));
2948 XO(
"Could not open file: \"%s\"").
Format( fullPath ),
2949 XO(
"Error Saving VST Presets"),
2957 void *chunkPtr =
nullptr;
2965 subType =
CCONST(
'F',
'B',
'C',
'h');
2969 dataSize += 4 + chunkSize;
2973 subType =
CCONST(
'F',
'x',
'B',
'k');
2980 dataSize += buf.GetDataLen();
2983 tab[0] = wxINT32_SWAP_ON_LE(
CCONST(
'C',
'c',
'n',
'K'));
2984 tab[1] = wxINT32_SWAP_ON_LE(dataSize);
2985 tab[2] = wxINT32_SWAP_ON_LE(subType);
2986 tab[3] = wxINT32_SWAP_ON_LE(curProg >= 0 ? 2 : 1);
2990 tab[7] = wxINT32_SWAP_ON_LE(curProg >= 0 ? curProg : 0);
2992 f.Write(tab,
sizeof(tab));
2996 memset(padding, 0,
sizeof(padding));
2997 f.Write(padding,
sizeof(padding));
3003 wxInt32
size = wxINT32_SWAP_ON_LE(chunkSize);
3005 f.Write(chunkPtr, chunkSize);
3009 f.Write(buf.GetData(), buf.GetDataLen());
3017 XO(
"Error writing to file: \"%s\"").
Format( fullPath ),
3018 XO(
"Error Saving VST Presets"),
3031 const wxString fullPath{
fn.GetFullPath() };
3032 wxFFile f(fullPath, wxT(
"wb"));
3036 XO(
"Could not open file: \"%s\"").
Format( fullPath ),
3037 XO(
"Error Saving VST Presets"),
3049 f.Write(buf.GetData(), buf.GetDataLen());
3053 XO(
"Error writing to file: \"%s\"").
Format( fullPath ),
3054 XO(
"Error Saving VST Presets"),
3075 progName[27] =
'\0';
3076 chunkSize = strlen(progName);
3077 memset(&progName[chunkSize], 0,
sizeof(progName) - chunkSize);
3081 subType =
CCONST(
'F',
'P',
'C',
'h');
3085 dataSize += 4 + chunkSize;
3089 subType =
CCONST(
'F',
'x',
'C',
'k');
3094 tab[0] = wxINT32_SWAP_ON_LE(
CCONST(
'C',
'c',
'n',
'K'));
3095 tab[1] = wxINT32_SWAP_ON_LE(dataSize);
3096 tab[2] = wxINT32_SWAP_ON_LE(subType);
3097 tab[3] = wxINT32_SWAP_ON_LE(1);
3102 buf.AppendData(tab,
sizeof(tab));
3103 buf.AppendData(progName,
sizeof(progName));
3107 wxInt32
size = wxINT32_SWAP_ON_LE(chunkSize);
3108 buf.AppendData(&
size,
sizeof(
size));
3109 buf.AppendData(chunkPtr, chunkSize);
3117 buf.AppendData(&ival,
sizeof(ival));
3130 xmlFile.StartTag(wxT(
"vstprogrampersistence"));
3131 xmlFile.WriteAttr(wxT(
"version"), wxT(
"2"));
3133 xmlFile.StartTag(wxT(
"effect"));
3135 xmlFile.WriteAttr(wxT(
"name"), GetSymbol().
Internal());
3136 xmlFile.WriteAttr(wxT(
"uniqueID"), mAEffect->uniqueID);
3137 xmlFile.WriteAttr(wxT(
"version"), mAEffect->version);
3138 xmlFile.WriteAttr(wxT(
"numParams"), mAEffect->numParams);
3140 xmlFile.StartTag(wxT(
"program"));
3141 xmlFile.WriteAttr(wxT(
"name"), wxEmptyString);
3149 clen = (int) constCallDispatcher(
effGetChunk, 1, 0, &chunk, 0.0);
3152 xmlFile.StartTag(wxT(
"chunk"));
3154 xmlFile.EndTag(wxT(
"chunk"));
3160 for (
int i = 0; i < mAEffect->numParams; i++)
3162 xmlFile.StartTag(wxT(
"param"));
3164 xmlFile.WriteAttr(wxT(
"index"), i);
3165 xmlFile.WriteAttr(wxT(
"name"),
3167 xmlFile.WriteAttr(wxT(
"value"),
3168 wxString::Format(wxT(
"%f"),
3169 callGetParameter(i)));
3171 xmlFile.EndTag(wxT(
"param"));
3175 xmlFile.EndTag(wxT(
"program"));
3177 xmlFile.EndTag(wxT(
"effect"));
3179 xmlFile.EndTag(wxT(
"vstprogrampersistence"));
3186 if (tag ==
"vstprogrampersistence")
3188 for (
auto pair : attrs)
3190 auto attr = pair.first;
3191 auto value = pair.second;
3193 if (attr ==
"version")
3200 if (mXMLVersion < 1 || mXMLVersion > 2)
3214 if (tag ==
"effect")
3222 for (
auto pair : attrs)
3224 auto attr = pair.first;
3225 auto value = pair.second;
3229 wxString strValue = value.ToWString();
3233 auto msg =
XO(
"This parameter file was saved from %s. Continue?")
3234 .Format( strValue );
3246 else if (attr ==
"version")
3249 if (!value.TryGet(version))
3259 if (!value.TryGet(uniqueID))
3269 if (!value.TryGet(numParams))
3285 if (tag ==
"program")
3287 for (
auto pair : attrs)
3289 auto attr = pair.first;
3290 auto value = pair.second;
3294 const wxString strValue = value.ToWString();
3296 if (strValue.length() > 24)
3302 if (ndx == wxNOT_FOUND)
3334 for (
auto pair : attrs)
3336 auto attr = pair.first;
3337 auto value = pair.second;
3339 if (attr ==
"index")
3341 if (!value.TryGet(ndx))
3359 else if (attr ==
"value")
3361 if (!value.TryGet(val))
3366 if (val < 0.0 || val > 1.0)
3373 if (ndx == -1 || val == -1.0)
3411 if (tag ==
"program")
3426 mChunk += wxString(std::string(content)).Trim(
true).Trim(
false);
3432 if (tag ==
"vstprogrampersistence")
3437 if (tag ==
"effect")
3442 if (tag ==
"program")
@ Internal
Indicates internal failure from Audacity.
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
const TranslatableString name
enum ChannelName * ChannelNames
EVT_COMMAND_RANGE(ID_Slider, ID_Slider+NUMBER_OF_BANDS - 1, wxEVT_COMMAND_SLIDER_UPDATED, EffectEqualization::OnSlider) EffectEqualization
#define PLATFORM_MAX_PATH
std::vector< PluginPath > PluginPaths
wxString PluginPath
type alias for identifying a Plugin supplied by a module, each module defining its own interpretation...
std::vector< RegistryPath > RegistryPaths
EVT_COMMAND(wxID_ANY, EVT_FREQUENCYTEXTCTRL_UPDATED, LabelDialog::OnFreqUpdate) LabelDialog
std::unique_ptr< T, Destroyer< T > > Destroy_ptr
a convenience for using Destroyer
FilePath SelectFile(FileNames::Operation op, const TranslatableString &message, const FilePath &default_path, const FilePath &default_filename, const FileExtension &default_extension, const FileTypes &fileTypes, int flags, wxWindow *parent)
static Settings & settings()
static uint32_t reinterpretAsUint32(float f)
DECLARE_PROVIDER_ENTRY(AudacityModule)
AEffect *(* vstPluginMain)(audioMasterCallback audioMaster)
DEFINE_LOCAL_EVENT_TYPE(EVT_SIZEWINDOW)
static float reinterpretAsFloat(uint32_t x)
static void OnSize(wxSizeEvent &evt)
DECLARE_BUILTIN_PROVIDER(VSTBuiltin)
std::vector< Attribute > AttributesList
const int effGetParamDisplay
const int effGetVendorVersion
const int effGetVstVersion
const int kVstLangEnglish
const int effMainsChanged
const int effGetParamLabel
const int audioMasterGetVendorVersion
const int effCanBeAutomated
const int audioMasterGetCurrentProcessLevel
const int effGetProductString
intptr_t(* audioMasterCallback)(AEffect *, int32_t, int32_t, intptr_t, void *, float)
const int effStartProcess
const int effShellGetNextPlugin
const int effFlagsProgramChunks
const int effGetParamName
const int effGetProgramNameIndexed
const int audioMasterNeedIdle
const int audioMasterGetProductString
const int effSetBlockSize
const int effSetProgramName
const int effGetVendorString
const int kVstTransportPlaying
const int audioMasterWantMidi
const int audioMasterPinConnected
const int effFlagsIsSynth
const int audioMasterWillReplaceOrAccumulate
const int audioMasterUpdateDisplay
const int audioMasterGetTime
const int effGetEffectName
const int effGetPlugCategory
const int audioMasterEndEdit
const int audioMasterIdle
const int audioMasterIOChanged
const int effFlagsCanReplacing
const int effBeginSetProgram
const int effBeginLoadBank
#define CCONST(a, b, c, d)
const int audioMasterProcessEvents
const int effSetSampleRate
const int audioMasterCurrentId
const int audioMasterAutomate
const int effBeginLoadProgram
const int audioMasterVersion
const int audioMasterBeginEdit
const int audioMasterGetVendorString
const int audioMasterGetSampleRate
const int effFlagsHasEditor
const int effEndSetProgram
const int audioMasterGetLanguage
const int audioMasterSizeWindow
const int audioMasterCanDo
VST Effects class, conforming to VST layout.
void(* setParameter)(AEffect *, int, float)
void(* processReplacing)(AEffect *, float **, float **, int)
intptr_t(* dispatcher)(AEffect *, int, int, intptr_t, void *, float)
float(* getParameter)(AEffect *, int)
void reinit(Integral count, bool initialize=false)
CommandParameters, derived from wxFileConfig, is essentially doing the same things as the SettingsVis...
bool GetParameters(wxString &parms)
bool SetParameters(const wxString &parms)
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
EffectDefinitionInterface is a ComponentInterface that adds some basic read-only information about ef...
Base class for many of the effects in Audacity.
Performs effect computation.
virtual const EffectSettings & Get()=0
void SetName(const TranslatableString &name)
virtual void FindFilesInPathList(const wxString &pattern, const FilePaths &pathList, FilePaths &files, bool directories=false)=0
std::function< const PluginID &(PluginProvider *, ComponentInterface *) > RegistrationCallback
Further expand a path reported by FindModulePaths.
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Holds a msgid for the translation catalog; may also bind format arguments.
bool SaveParameters(const RegistryPath &group, const EffectSettings &settings) const
void SaveXML(const wxFileName &fn) const
bool LoadUserPreset(const RegistryPath &name, EffectSettings &settings) const override
Change settings to a user-named preset.
bool HasOptions() override
bool RealtimeResume() noexcept override
intptr_t callDispatcher(int opcode, int index, intptr_t value, void *ptr, float opt) override
void OnSizeWindow(wxCommandEvent &evt)
intptr_t constCallDispatcher(int opcode, int index, intptr_t value, void *ptr, float opt) const
RegistryPaths GetFactoryPresets() const override
Report names of factory presets.
std::unique_ptr< VSTEffectTimer > mTimer
void SetString(int opcode, const wxString &str, int index=0)
size_t SetBlockSize(size_t maxBlockSize) override
EffectType GetType() const override
Type determines how it behaves.
int GetString(wxString &outstr, int opcode, int index=0) const
bool DoLoadFactoryPreset(int id)
void SaveFXP(const wxFileName &fn) const
void callSetChunk(bool isPgm, int len, void *buf)
void NeedEditIdle(bool state)
bool RealtimeSuspend() override
ArrayOf< wxSlider * > mSliders
ArrayOf< wxStaticText * > mLabels
std::unique_ptr< EffectUIValidator > PopulateUI(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access) override
Adds controls to a panel that is given as the parent window of S
EffectFamilySymbol GetFamily() const override
Report identifier and user-visible name of the effect protocol.
std::unique_ptr< wxDynamicLibrary > ModuleHandle
CF_ptr< CFBundleRef > BundleHandle
bool LoadXML(const wxFileName &fn)
bool SupportsRealtime() const override
Whether the effect supports realtime previewing (while audio is playing).
bool RealtimeFinalize(EffectSettings &settings) noexcept override
PluginPath GetPath() const override
size_t GetBlockSize() const override
bool LoadFXB(const wxFileName &fn)
TranslatableString GetDescription() const override
ArrayOf< wxStaticText * > mDisplays
std::shared_ptr< EffectInstance > MakeInstance() const override
Make an object maintaining short-term state of an Effect.
void HandleXMLEndTag(const std::string_view &tag) override
void callSetParameter(int index, float value)
wxWeakRef< wxDialog > mDialog
wxString GetVersion() const override
void SetChannelCount(unsigned numChannels)
bool IsInteractive() const override
Whether the effect needs a dialog for entry of settings.
bool LoadFactoryPreset(int id, EffectSettings &settings) const override
Change settings to the preset whose name is GetFactoryPresets()[id]
bool LoadFXProgram(unsigned char **bptr, ssize_t &len, int index, bool dryrun)
VendorSymbol GetVendor() const override
bool LoadSettings(const CommandParameters &parms, EffectSettings &settings) const override
Restore settings from keys and values.
bool SupportsAutomation() const override
Whether the effect has any automatable controls.
void SetSampleRate(double rate) override
sampleCount GetLatency() override
bool RealtimeProcessEnd(EffectSettings &settings) noexcept override
static intptr_t AudioMaster(AEffect *effect, int32_t opcode, int32_t index, intptr_t value, void *ptr, float opt)
bool LoadFXP(const wxFileName &fn)
void OnSlider(wxCommandEvent &evt)
unsigned GetAudioInCount() const override
How many input buffers to allocate at once.
bool RealtimeProcessStart(EffectSettings &settings) override
void callProcessReplacing(const float *const *inputs, float *const *outputs, int sampleframes)
static intptr_t mCurrentEffectID
int GetMidiInCount() const override
Function that has not yet found a use.
VstPatchChunkInfo mXMLInfo
VSTEffect(const PluginPath &path, VSTEffect *master=NULL)
bool SaveUserPreset(const RegistryPath &name, const EffectSettings &settings) const override
Save settings in the configuration file as a user-named preset.
int ShowClientInterface(wxWindow &parent, wxDialog &dialog, bool forceModal) override
void HandleXMLContent(const std::string_view &content) override
unsigned GetAudioOutCount() const override
How many output buffers to allocate at once.
bool DoProcessInitialize(sampleCount totalLen, ChannelNames chanMap)
void SetBufferDelay(int samples)
bool ProcessInitialize(EffectSettings &settings, sampleCount totalLen, ChannelNames chanMap) override
bool IsDefault() const override
Whether the effect sorts "above the line" in the menus.
ComponentInterfaceSymbol GetSymbol() const override
void ExportPresets(const EffectSettings &settings) const override
VstTimeInfo * GetTimeInfo()
std::shared_ptr< EffectInstance > DoMakeInstance()
void RefreshParameters(int skip=-1)
std::vector< int > GetEffectIDs()
bool DoLoadUserPreset(const RegistryPath &name, EffectSettings &settings)
size_t ProcessBlock(EffectSettings &settings, const float *const *inBlock, float *const *outBlock, size_t blockLen) override
Called for destructive effect computation.
void BuildPlain(EffectSettingsAccess &access)
size_t RealtimeProcess(int group, EffectSettings &settings, const float *const *inbuf, float *const *outbuf, size_t numSamples) override
bool IsGraphicalUI() override
bool ValidateUI(EffectSettings &) override
float callGetParameter(int index) const
void SaveFXB(const wxFileName &fn) const
unsigned GetChannelCount()
bool ProcessFinalize() override
bool RealtimeInitialize(EffectSettings &settings) override
XMLTagHandler * HandleXMLChild(const std::string_view &tag) override
bool LoadParameters(const RegistryPath &group, EffectSettings &settings)
void ImportPresets(EffectSettings &settings) override
bool RealtimeAddProcessor(EffectSettings &settings, unsigned numChannels, float sampleRate) override
void Automate(int index, float value)
void callSetProgram(int index)
bool HandleXMLTag(const std::string_view &tag, const AttributesList &attrs) override
bool CanExportPresets() override
bool SaveSettings(const EffectSettings &settings, CommandParameters &parms) const override
Store settings as keys and values.
int GetMidiOutCount() const override
Function that has not yet found a use.
void SaveFXProgram(wxMemoryBuffer &buf, int index) const
NumericTextCtrl * mDuration
void SizeWindow(int w, int h)
void ShowOptions() override
ArrayOf< wxStaticText * > mNames
void OnOk(wxCommandEvent &evt)
EffectDefinitionInterface & mEffect
void PopulateOrExchange(ShuttleGui &S)
VSTEffectOptionsDialog(wxWindow *parent, EffectDefinitionInterface &effect)
virtual ~VSTEffectOptionsDialog()
VSTEffectTimer(VSTEffect *effect)
const FileExtensions & GetFileExtensions() override
File types associated with this protocol.
bool Initialize() override
Called immediately after creation. Let provider initialize.
EffectFamilySymbol GetOptionalFamilySymbol() override
A symbol identifying the family of plug-ins provided by this.
bool IsPluginValid(const PluginPath &path, bool bFast) override
FilePath InstallPath() override
Where plug-in files should be copied to install them.
PluginPaths FindModulePaths(PluginManagerInterface &pm) override
TranslatableString GetDescription() const override
void AutoRegisterPlugins(PluginManagerInterface &pm) override
Called so that a provider of a static set of plug-ins can register them.
virtual ~VSTEffectsModule()
VendorSymbol GetVendor() const override
PluginPath GetPath() const override
wxString GetVersion() const override
std::unique_ptr< ComponentInterface > LoadPlugin(const PluginPath &path) override
Load the plug-in at a path reported by DiscoverPluginsAtPath.
unsigned DiscoverPluginsAtPath(const PluginPath &path, TranslatableString &errMsg, const RegistrationCallback &callback) override
ComponentInterfaceSymbol GetSymbol() const override
void Terminate() override
Called just prior to deletion to allow releasing any resources.
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
Reads a file and passes the results through an XMLTagHandler.
const TranslatableString & GetErrorStr() const
bool Parse(XMLTagHandler *baseHandler, const FilePath &fname)
Wrapper to output XML data to files.
This class is an interface which should be implemented by classes which wish to be able to load and s...
Positions or offsets within audio files need a wide type.
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
STRINGS_API wxString Encode(const void *in, int len)
STRINGS_API int Decode(const wxString &in, void *out)
bool SetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, const Value &value)
bool GetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, Value &var, const Value &defval)
Externalized state of a plug-in.
EffectSettingsExtra extra
Options & AutoPos(bool enable)