iPlug2 - C++ Audio Plug-in Framework
Loading...
Searching...
No Matches
IPlugPluginBase.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the iPlug 2 library. Copyright (C) the iPlug 2 developers.
5
6 See LICENSE.txt for more info.
7
8 ==============================================================================
9*/
10
16#include "IPlugPluginBase.h"
17#include "wdlendian.h"
18#include "wdl_base64.h"
19
20using namespace iplug;
21
22IPluginBase::IPluginBase(int nParams, int nPresets)
23: EDITOR_DELEGATE_CLASS(nParams)
24{
25 for (int i = 0; i < nPresets; ++i)
26 mPresets.Add(new IPreset());
27}
28
29IPluginBase::~IPluginBase()
30{
31 mPresets.Empty(true);
32}
33
34int IPluginBase::GetPluginVersion(bool decimal) const
35{
36 if (decimal)
37 return GetDecimalVersion(mVersion);
38 else
39 return mVersion;
40}
41
42void IPluginBase::GetPluginVersionStr(WDL_String& str) const
43{
44 GetVersionStr(mVersion, str);
45#if defined TRACER_BUILD
46 str.Append("T");
47#endif
48#if defined _DEBUG
49 str.Append("D");
50#endif
51}
52
53int IPluginBase::GetHostVersion(bool decimal) const
54{
55 if (decimal)
56 return GetDecimalVersion(mHostVersion);
57
58 return mHostVersion;
59}
60
61void IPluginBase::GetHostVersionStr(WDL_String& str) const
62{
63 GetVersionStr(mHostVersion, str);
64}
65
66const char* IPluginBase::GetAPIStr() const
67{
68 switch (GetAPI())
69 {
70 case kAPIVST2: return "VST2";
71 case kAPIVST3: return "VST3";
72 case kAPIAU: return "AU";
73 case kAPIAUv3: return "AUv3";
74 case kAPIAAX: return "AAX";
75 case kAPIAPP: return "APP";
76 case kAPIWAM: return "WAM";
77 case kAPIWEB: return "WEB";
78 default: return "";
79 }
80}
81
82const char* IPluginBase::GetArchStr() const
83{
84#if defined OS_WEB
85 return "WASM";
86#elif defined __aarch64__
87 return "arm64";
88#elif defined ARCH_64BIT
89 return "x86-64";
90#else
91 return "x86-32";
92#endif
93}
94
95void IPluginBase::GetBuildInfoStr(WDL_String& str, const char* date, const char* time) const
96{
97 WDL_String version;
98 GetPluginVersionStr(version);
99 str.SetFormatted(MAX_BUILD_INFO_STR_LEN, "%s %s (%s), built on %s at %.5s ", version.Get(), GetAPIStr(), GetArchStr(), date, time);
100}
101
102#pragma mark -
103
105{
106 TRACE
107 bool savedOK = true;
108 int i, n = mParams.GetSize();
109 for (i = 0; i < n && savedOK; ++i)
110 {
111 IParam* pParam = mParams.Get(i);
112 Trace(TRACELOC, "%d %s %f", i, pParam->GetName(), pParam->Value());
113 double v = pParam->Value();
114 savedOK &= (chunk.Put(&v) > 0);
115 }
116 return savedOK;
117}
118
119int IPluginBase::UnserializeParams(const IByteChunk& chunk, int startPos)
120{
121 TRACE
122 int i, n = mParams.GetSize(), pos = startPos;
123 ENTER_PARAMS_MUTEX
124 for (i = 0; i < n && pos >= 0; ++i)
125 {
126 IParam* pParam = mParams.Get(i);
127 double v = 0.0;
128 pos = chunk.Get(&v, pos);
129 pParam->Set(v);
130 Trace(TRACELOC, "%d %s %f", i, pParam->GetName(), pParam->Value());
131 }
132
133 OnParamReset(kPresetRecall);
134 LEAVE_PARAMS_MUTEX
135
136 return pos;
137}
138
139void IPluginBase::InitParamRange(int startIdx, int endIdx, int countStart, const char* nameFmtStr, double defaultVal, double minVal, double maxVal, double step, const char *label, int flags, const char *group, const IParam::Shape& shape, IParam::EParamUnit unit, IParam::DisplayFunc displayFunc)
140{
141 WDL_String nameStr;
142 for (auto p = startIdx; p <= endIdx; p++)
143 {
144 nameStr.SetFormatted(MAX_PARAM_NAME_LEN, nameFmtStr, countStart + (p-startIdx));
145 GetParam(p)->InitDouble(nameStr.Get(), defaultVal, minVal, maxVal, step, label, flags, group, shape, unit, displayFunc);
146 }
147}
148
149void IPluginBase::CloneParamRange(int cloneStartIdx, int cloneEndIdx, int startIdx, const char* searchStr, const char* replaceStr, const char* newGroup)
150{
151 for (auto p = cloneStartIdx; p <= cloneEndIdx; p++)
152 {
153 IParam* pParam = GetParam(p);
154 int outIdx = startIdx + (p - cloneStartIdx);
155 GetParam(outIdx)->Init(*pParam, searchStr, replaceStr, newGroup);
156 GetParam(outIdx)->Set(pParam->Value());
157 }
158}
159
160void IPluginBase::CopyParamValues(int startIdx, int destIdx, int nParams)
161{
162 assert((startIdx + nParams) < NParams());
163 assert((destIdx + nParams) < NParams());
164 assert((startIdx + nParams) < destIdx);
165
166 for (auto p = startIdx; p < startIdx + nParams; p++)
167 {
168 GetParam(destIdx++)->Set(GetParam(p)->Value());
169 }
170}
171
172void IPluginBase::CopyParamValues(const char* inGroup, const char *outGroup)
173{
174 WDL_PtrList<IParam> inParams, outParams;
175
176 for (auto p = 0; p < NParams(); p++)
177 {
178 IParam* pParam = GetParam(p);
179 if(strcmp(pParam->GetGroup(), inGroup) == 0)
180 {
181 inParams.Add(pParam);
182 }
183 else if(strcmp(pParam->GetGroup(), outGroup) == 0)
184 {
185 outParams.Add(pParam);
186 }
187 }
188
189 assert(inParams.GetSize() == outParams.GetSize());
190
191 for (auto p = 0; p < inParams.GetSize(); p++)
192 {
193 outParams.Get(p)->Set(inParams.Get(p)->Value());
194 }
195}
196
197void IPluginBase::ForParamInRange(int startIdx, int endIdx, std::function<void(int paramIdx, IParam&)>func)
198{
199 for (auto p = startIdx; p <= endIdx; p++)
200 {
201 func(p, * GetParam(p));
202 }
203}
204
205void IPluginBase::ForParamInGroup(const char* paramGroup, std::function<void (int paramIdx, IParam&)> func)
206{
207 for (auto p = 0; p < NParams(); p++)
208 {
209 IParam* pParam = GetParam(p);
210 if(strcmp(pParam->GetGroup(), paramGroup) == 0)
211 {
212 func(p, *pParam);
213 }
214 }
215}
216
218{
219 DefaultParamValues(0, NParams()-1);
220}
221
222void IPluginBase::DefaultParamValues(int startIdx, int endIdx)
223{
224 ForParamInRange(startIdx, endIdx, [](int paramIdx, IParam& param) {
225 param.SetToDefault();
226 });
227}
228
229void IPluginBase::DefaultParamValues(const char* paramGroup)
230{
231 ForParamInGroup(paramGroup, [](int paramIdx, IParam& param) {
232 param.SetToDefault();
233 });
234}
235
237{
238 RandomiseParamValues(0, NParams()-1);
239}
240
241void IPluginBase::RandomiseParamValues(int startIdx, int endIdx)
242{
243 ForParamInRange(startIdx, endIdx, [&](int paramIdx, IParam& param) { param.SetNormalized( static_cast<float>(std::rand()/(static_cast<float>(RAND_MAX)+1.f)) ); });
244}
245
246void IPluginBase::RandomiseParamValues(const char *paramGroup)
247{
248 ForParamInGroup(paramGroup, [&](int paramIdx, IParam& param) { param.SetNormalized( static_cast<float>(std::rand()/(static_cast<float>(RAND_MAX)+1.f)) ); });
249}
250
252{
253 ForParamInRange(0, NParams()-1, [](int paramIdx, IParam& param) {
254 param.PrintDetails();
255 DBGMSG("\n");
256 });
257}
258
259static IPreset* GetNextUninitializedPreset(WDL_PtrList<IPreset>* pPresets)
260{
261 int n = pPresets->GetSize();
262 for (int i = 0; i < n; ++i)
263 {
264 IPreset* pPreset = pPresets->Get(i);
265 if (!(pPreset->mInitialized))
266 {
267 return pPreset;
268 }
269 }
270 return 0;
271}
272
273void IPluginBase::MakeDefaultPreset(const char* name, int nPresets)
274{
275 for (int i = 0; i < nPresets; ++i)
276 {
277 IPreset* pPreset = GetNextUninitializedPreset(&mPresets);
278 if (pPreset)
279 {
280 pPreset->mInitialized = true;
281 strcpy(pPreset->mName, (name ? name : "Empty"));
282 SerializeState(pPreset->mChunk);
283 }
284 }
285}
286
287void IPluginBase::MakePreset(const char* name, ...)
288{
289 IPreset* pPreset = GetNextUninitializedPreset(&mPresets);
290 if (pPreset)
291 {
292 pPreset->mInitialized = true;
293 strcpy(pPreset->mName, name);
294
295 int i, n = NParams();
296
297 double v = 0.0;
298 va_list vp;
299 va_start(vp, name);
300 for (i = 0; i < n; ++i)
301 {
302 GET_PARAM_FROM_VARARG(GetParam(i)->Type(), vp, v);
303 pPreset->mChunk.Put(&v);
304 }
305 }
306}
307
308void IPluginBase::MakePresetFromNamedParams(const char* name, int nParamsNamed, ...)
309{
310 TRACE
311 IPreset* pPreset = GetNextUninitializedPreset(&mPresets);
312 if (pPreset)
313 {
314 pPreset->mInitialized = true;
315 strcpy(pPreset->mName, name);
316
317 int i = 0, n = NParams();
318
319 WDL_TypedBuf<double> vals;
320 vals.Resize(n);
321 double* pV = vals.Get();
322 for (i = 0; i < n; ++i, ++pV)
323 {
324 *pV = PARAM_UNINIT;
325 }
326
327 va_list vp;
328 va_start(vp, nParamsNamed);
329 for (int i = 0; i < nParamsNamed; ++i)
330 {
331 int paramIdx = (int) va_arg(vp, int);
332 // This assert will fire if any of the passed-in param values do not match
333 // the type that the param was initialized with (int for bool, int, enum; double for double).
334 assert(paramIdx > kNoParameter && paramIdx < n);
335 GET_PARAM_FROM_VARARG(GetParam(paramIdx)->Type(), vp, *(vals.Get() + paramIdx));
336 }
337 va_end(vp);
338
339 pV = vals.Get();
340 for (int i = 0; i < n; ++i, ++pV)
341 {
342 if (*pV == PARAM_UNINIT) // Any that weren't explicitly set, use the defaults.
343 {
344 *pV = GetParam(i)->Value();
345 }
346 pPreset->mChunk.Put(pV);
347 }
348 }
349}
350
351void IPluginBase::MakePresetFromChunk(const char* name, IByteChunk& chunk)
352{
353 IPreset* pPreset = GetNextUninitializedPreset(&mPresets);
354 if (pPreset)
355 {
356 pPreset->mInitialized = true;
357 strcpy(pPreset->mName, name);
358
359 pPreset->mChunk.PutChunk(&chunk);
360 }
361}
362
363void IPluginBase::MakePresetFromBlob(const char* name, const char* blob, int sizeOfChunk)
364{
365 IByteChunk presetChunk;
366 presetChunk.Resize(sizeOfChunk);
367 wdl_base64decode(blob, presetChunk.GetData(), sizeOfChunk);
368
369 MakePresetFromChunk(name, presetChunk);
370}
371
372static void MakeDefaultUserPresetName(WDL_PtrList<IPreset>* pPresets, char* str)
373{
374 int nDefaultNames = 0;
375 int n = pPresets->GetSize();
376 for (int i = 0; i < n; ++i)
377 {
378 IPreset* pPreset = pPresets->Get(i);
379 if (strstr(pPreset->mName, DEFAULT_USER_PRESET_NAME))
380 {
381 ++nDefaultNames;
382 }
383 }
384 snprintf(str, MAX_PRESET_NAME_LEN, "%s %d", DEFAULT_USER_PRESET_NAME, nDefaultNames + 1);
385}
386
388{
389 TRACE
390 MakeDefaultPreset("Empty", mPresets.GetSize());
391}
392
394{
395 TRACE
396 int i = 0;
397 while (i < mPresets.GetSize())
398 {
399 IPreset* pPreset = mPresets.Get(i);
400 if (pPreset->mInitialized)
401 {
402 ++i;
403 }
404 else
405 {
406 mPresets.Delete(i, true);
407 }
408 }
409}
410
412{
413 TRACE
414 bool restoredOK = false;
415 if (idx >= 0 && idx < mPresets.GetSize())
416 {
417 IPreset* pPreset = mPresets.Get(idx);
418
419 if (!(pPreset->mInitialized))
420 {
421 pPreset->mInitialized = true;
422 MakeDefaultUserPresetName(&mPresets, pPreset->mName);
423 restoredOK = SerializeState(pPreset->mChunk);
424 }
425 else
426 {
427 restoredOK = (UnserializeState(pPreset->mChunk, 0) > 0);
428 }
429
430 if (restoredOK)
431 {
432 mCurrentPresetIdx = idx;
434 OnRestoreState();
435 }
436 }
437 return restoredOK;
438}
439
440bool IPluginBase::RestorePreset(const char* name)
441{
442 if (CStringHasContents(name))
443 {
444 int n = mPresets.GetSize();
445 for (int i = 0; i < n; ++i)
446 {
447 IPreset* pPreset = mPresets.Get(i);
448 if (!strcmp(pPreset->mName, name))
449 {
450 return RestorePreset(i);
451 }
452 }
453 }
454 return false;
455}
456
457const char* IPluginBase::GetPresetName(int idx) const
458{
459 if (idx >= 0 && idx < mPresets.GetSize())
460 {
461 return mPresets.Get(idx)->mName;
462 }
463 return "";
464}
465
467{
468 if (mCurrentPresetIdx >= 0 && mCurrentPresetIdx < mPresets.GetSize())
469 {
470 IPreset* pPreset = mPresets.Get(mCurrentPresetIdx);
471 pPreset->mChunk.Clear();
472
473 Trace(TRACELOC, "%d %s", mCurrentPresetIdx, pPreset->mName);
474
475 SerializeState(pPreset->mChunk);
476
477 if (CStringHasContents(name))
478 {
479 strcpy(pPreset->mName, name);
480 }
481 }
482}
483
485{
486 TRACE
487 bool savedOK = true;
488 int n = mPresets.GetSize();
489 for (int i = 0; i < n && savedOK; ++i)
490 {
491 IPreset* pPreset = mPresets.Get(i);
492 chunk.PutStr(pPreset->mName);
493
494 Trace(TRACELOC, "%d %s", i, pPreset->mName);
495
496 chunk.Put(&pPreset->mInitialized);
497 if (pPreset->mInitialized)
498 {
499 savedOK &= (chunk.PutChunk(&(pPreset->mChunk)) > 0);
500 }
501 }
502 return savedOK;
503}
504
505int IPluginBase::UnserializePresets(const IByteChunk& chunk, int startPos)
506{
507 TRACE
508 WDL_String name;
509 int n = mPresets.GetSize(), pos = startPos;
510 for (int i = 0; i < n && pos >= 0; ++i)
511 {
512 IPreset* pPreset = mPresets.Get(i);
513 pos = chunk.GetStr(name, pos);
514 strcpy(pPreset->mName, name.Get());
515
516 Trace(TRACELOC, "%d %s", i, pPreset->mName);
517
518 pos = chunk.Get<bool>(&(pPreset->mInitialized), pos);
519 if (pPreset->mInitialized)
520 {
521 pos = UnserializeState(chunk, pos);
522 if (pos > 0)
523 {
524 pPreset->mChunk.Clear();
525 SerializeState(pPreset->mChunk);
526 }
527 }
528 }
529 RestorePreset(mCurrentPresetIdx);
530 return pos;
531}
532
533void IPluginBase::DumpMakePresetSrc(const char* filename) const
534{
535 bool sDumped = false;
536 if (!sDumped)
537 {
538 sDumped = true;
539 int i, n = NParams();
540 FILE* fp = fopenUTF8(filename, "a");
541
542 if (!fp)
543 return;
544
545 int idx = GetCurrentPresetIdx();
546 fprintf(fp, "MakePreset(\"%s\"", GetPresetName(idx));
547 for (i = 0; i < n; ++i)
548 {
549 const IParam* pParam = GetParam(i);
550 constexpr int maxLen = 32;
551 char paramVal[maxLen];
552
553 switch (pParam->Type())
554 {
555 case IParam::kTypeBool:
556 snprintf(paramVal, maxLen, "%s", (pParam->Bool() ? "true" : "false"));
557 break;
558 case IParam::kTypeInt:
559 snprintf(paramVal, maxLen, "%d", pParam->Int());
560 break;
561 case IParam::kTypeEnum:
562 snprintf(paramVal, maxLen, "%d", pParam->Int());
563 break;
564 case IParam::kTypeDouble:
565 default:
566 snprintf(paramVal, maxLen, "%.6f", pParam->Value());
567 break;
568 }
569 fprintf(fp, ", %s", paramVal);
570 }
571 fprintf(fp, ");\n");
572 fclose(fp);
573 }
574}
575
576void IPluginBase::DumpMakePresetFromNamedParamsSrc(const char* filename, const char* paramEnumNames[]) const
577{
578 bool sDumped = false;
579
580 if (!sDumped)
581 {
582 sDumped = true;
583 int i, n = NParams();
584 FILE* fp = fopenUTF8(filename, "a");
585
586 if (!fp)
587 return;
588
589 int idx = GetCurrentPresetIdx();
590 fprintf(fp, " MakePresetFromNamedParams(\"%s\", %d", GetPresetName(idx), n);
591 for (i = 0; i < n; ++i)
592 {
593 const IParam* pParam = GetParam(i);
594 constexpr int maxLen = 32;
595 char paramVal[maxLen];
596 switch (pParam->Type())
597 {
598 case IParam::kTypeBool:
599 snprintf(paramVal, maxLen, "%s", (pParam->Bool() ? "true" : "false"));
600 break;
601 case IParam::kTypeInt:
602 snprintf(paramVal, maxLen, "%d", pParam->Int());
603 break;
604 case IParam::kTypeEnum:
605 snprintf(paramVal, maxLen, "%d", pParam->Int());
606 break;
607 case IParam::kTypeDouble:
608 default:
609 snprintf(paramVal, maxLen, "%.6f", pParam->Value());
610 break;
611 }
612 fprintf(fp, ",\n %s, %s", paramEnumNames[i], paramVal);
613 }
614 fprintf(fp, ");\n");
615 fclose(fp);
616 }
617}
618
619void IPluginBase::DumpPresetBlob(const char* filename) const
620{
621 FILE* fp = fopenUTF8(filename, "a");
622
623 if (!fp)
624 return;
625
626 int idx = GetCurrentPresetIdx();
627 fprintf(fp, "MakePresetFromBlob(\"%s\", \"", GetPresetName(idx));
628
629 char buf[MAX_BLOB_LENGTH];
630
631 IByteChunk* pPresetChunk = &mPresets.Get(mCurrentPresetIdx)->mChunk;
632 uint8_t* byteStart = pPresetChunk->GetData();
633
634 wdl_base64encode(byteStart, buf, pPresetChunk->Size());
635
636 fprintf(fp, "%s\", %i);\n", buf, pPresetChunk->Size());
637 fclose(fp);
638}
639
640// confusing... IByteChunk will force storage as little endian on big endian platforms,
641// so when we use it here, since vst fxp/fxb files are big endian, we need to swap the endianess
642// regardless of the endianness of the host, and on big endian hosts it will get swapped back to
643// big endian
644bool IPluginBase::SavePresetAsFXP(const char* file) const
645{
646 if (CStringHasContents(file))
647 {
648 FILE* fp = fopenUTF8(file, "wb");
649
650 IByteChunk pgm;
651
652 int32_t chunkMagic = WDL_bswap32('CcnK');
653 int32_t byteSize = 0;
654 int32_t fxpMagic;
655 int32_t fxpVersion = WDL_bswap32(kFXPVersionNum);
656 int32_t pluginID = WDL_bswap32(GetUniqueID());
657 int32_t pluginVersion = WDL_bswap32(GetPluginVersion(true));
658 int32_t numParams = WDL_bswap32(NParams());
659 char prgName[28];
660 memset(prgName, 0, 28);
661 strcpy(prgName, GetPresetName(GetCurrentPresetIdx()));
662
663 pgm.Put(&chunkMagic);
664
665 if (DoesStateChunks())
666 {
667 IByteChunk state;
668 int32_t chunkSize;
669
670 fxpMagic = WDL_bswap32('FPCh');
671
673 SerializeState(state);
674
675 chunkSize = WDL_bswap32(state.Size());
676 byteSize = WDL_bswap32(state.Size() + 60);
677
678 pgm.Put(&byteSize);
679 pgm.Put(&fxpMagic);
680 pgm.Put(&fxpVersion);
681 pgm.Put(&pluginID);
682 pgm.Put(&pluginVersion);
683 pgm.Put(&numParams);
684 pgm.PutBytes(prgName, 28); // not PutStr (we want all 28 bytes)
685 pgm.Put(&chunkSize);
686 pgm.PutBytes(state.GetData(), state.Size());
687 }
688 else
689 {
690 fxpMagic = WDL_bswap32('FxCk');
691 //byteSize = WDL_bswap32(20 + 28 + (NParams() * 4) );
692 pgm.Put(&byteSize);
693 pgm.Put(&fxpMagic);
694 pgm.Put(&fxpVersion);
695 pgm.Put(&pluginID);
696 pgm.Put(&pluginVersion);
697 pgm.Put(&numParams);
698 pgm.PutBytes(prgName, 28); // not PutStr (we want all 28 bytes)
699
700 for (int i = 0; i< NParams(); i++)
701 {
702 WDL_EndianFloat v32;
703 v32.f = (float) GetParam(i)->GetNormalized();
704 unsigned int swapped = WDL_bswap32(v32.int32);
705 pgm.Put(&swapped);
706 }
707 }
708
709 fwrite(pgm.GetData(), pgm.Size(), 1, fp);
710 fclose(fp);
711
712 return true;
713 }
714 return false;
715}
716
717bool IPluginBase::SaveBankAsFXB(const char* file) const
718{
719 if (CStringHasContents(file))
720 {
721 FILE* fp = fopenUTF8(file, "wb");
722
723 IByteChunk bnk;
724
725 int32_t chunkMagic = WDL_bswap32('CcnK');
726 int32_t byteSize = 0;
727 int32_t fxbMagic;
728 int32_t fxbVersion = WDL_bswap32(kFXBVersionNum);
729 int32_t pluginID = WDL_bswap32(GetUniqueID());
730 int32_t pluginVersion = WDL_bswap32(GetPluginVersion(true));
731 int32_t numPgms = WDL_bswap32(NPresets());
732 int32_t currentPgm = WDL_bswap32(GetCurrentPresetIdx());
733 char future[124];
734 memset(future, 0, 124);
735
736 bnk.Put(&chunkMagic);
737
738 if (DoesStateChunks())
739 {
740 IByteChunk state;
741 int32_t chunkSize;
742
743 fxbMagic = WDL_bswap32('FBCh');
744
746 SerializePresets(state);
747
748 chunkSize = WDL_bswap32(state.Size());
749 byteSize = WDL_bswap32(160 + state.Size() );
750
751 bnk.Put(&byteSize);
752 bnk.Put(&fxbMagic);
753 bnk.Put(&fxbVersion);
754 bnk.Put(&pluginID);
755 bnk.Put(&pluginVersion);
756 bnk.Put(&numPgms);
757 bnk.Put(&currentPgm);
758 bnk.PutBytes(&future, 124);
759
760 bnk.Put(&chunkSize);
761 bnk.PutBytes(state.GetData(), state.Size());
762 }
763 else
764 {
765 fxbMagic = WDL_bswap32('FxBk');
766
767 bnk.Put(&byteSize);
768 bnk.Put(&fxbMagic);
769 bnk.Put(&fxbVersion);
770 bnk.Put(&pluginID);
771 bnk.Put(&pluginVersion);
772 bnk.Put(&numPgms);
773 bnk.Put(&currentPgm);
774 bnk.PutBytes(&future, 124);
775
776 int32_t fxpMagic = WDL_bswap32('FxCk');
777 int32_t fxpVersion = WDL_bswap32(kFXPVersionNum);
778 int32_t numParams = WDL_bswap32(NParams());
779
780 for (int p = 0; p < NPresets(); p++)
781 {
782 IPreset* pPreset = mPresets.Get(p);
783
784 char prgName[28];
785 memset(prgName, 0, 28);
786 strcpy(prgName, pPreset->mName);
787
788 bnk.Put(&chunkMagic);
789 //byteSize = WDL_bswap32(20 + 28 + (NParams() * 4) );
790 bnk.Put(&byteSize);
791 bnk.Put(&fxpMagic);
792 bnk.Put(&fxpVersion);
793 bnk.Put(&pluginID);
794 bnk.Put(&pluginVersion);
795 bnk.Put(&numParams);
796 bnk.PutBytes(prgName, 28);
797
798 int pos = 0;
799
800 for (int i = 0; i< NParams(); i++)
801 {
802 double v = 0.0;
803 pos = pPreset->mChunk.Get(&v, pos);
804
805 WDL_EndianFloat v32;
806 v32.f = (float) GetParam(i)->ToNormalized(v);
807 uint32_t swapped = WDL_bswap32(v32.int32);
808 bnk.Put(&swapped);
809 }
810 }
811 }
812
813 fwrite(bnk.GetData(), bnk.Size(), 1, fp);
814 fclose(fp);
815
816 return true;
817 }
818 else
819 return false;
820}
821
822bool IPluginBase::LoadPresetFromFXP(const char* file)
823{
824 if (CStringHasContents(file))
825 {
826 FILE* fp = fopenUTF8(file, "rb");
827
828 if (fp)
829 {
830 IByteChunk pgm;
831 long fileSize;
832
833 fseek(fp , 0 , SEEK_END);
834 fileSize = ftell(fp);
835 rewind(fp);
836
837 pgm.Resize((int) fileSize);
838 fread(pgm.GetData(), fileSize, 1, fp);
839
840 fclose(fp);
841
842 int pos = 0;
843
844 int32_t chunkMagic;
845 int32_t byteSize = 0;
846 int32_t fxpMagic;
847 int32_t fxpVersion;
848 int32_t pluginID;
849 int32_t pluginVersion;
850 int32_t numParams;
851 char prgName[28];
852
853 pos = pgm.Get(&chunkMagic, pos);
854 chunkMagic = WDL_bswap_if_le(chunkMagic);
855 pos = pgm.Get(&byteSize, pos);
856 byteSize = WDL_bswap_if_le(byteSize);
857 pos = pgm.Get(&fxpMagic, pos);
858 fxpMagic = WDL_bswap_if_le(fxpMagic);
859 pos = pgm.Get(&fxpVersion, pos);
860 fxpVersion = WDL_bswap_if_le(fxpVersion);
861 pos = pgm.Get(&pluginID, pos);
862 pluginID = WDL_bswap_if_le(pluginID);
863 pos = pgm.Get(&pluginVersion, pos);
864 pluginVersion = WDL_bswap_if_le(pluginVersion);
865 pos = pgm.Get(&numParams, pos);
866 numParams = WDL_bswap_if_le(numParams);
867 pos = pgm.GetBytes(prgName, 28, pos);
868
869 if (chunkMagic != 'CcnK') return false;
870 if (fxpVersion != kFXPVersionNum) return false; // TODO: what if a host saves as a different version?
871 if (pluginID != GetUniqueID()) return false;
872 //if (pluginVersion != GetPluginVersion(true)) return false; // TODO: provide mechanism for loading earlier versions
873 //if (numParams != NParams()) return false; // TODO: provide mechanism for loading earlier versions with less params
874
875 if (DoesStateChunks() && fxpMagic == 'FPCh')
876 {
877 int32_t chunkSize;
878 pos = pgm.Get(&chunkSize, pos);
879 chunkSize = WDL_bswap_if_le(chunkSize);
880
882 UnserializeState(pgm, pos);
883 ModifyCurrentPreset(prgName);
886
887 return true;
888 }
889 else if (fxpMagic == 'FxCk') // Due to the big Endian-ness of FXP/FXB format we cannot call SerializeParams()
890 {
891 ENTER_PARAMS_MUTEX
892 for (int i = 0; i< NParams(); i++)
893 {
894 WDL_EndianFloat v32;
895 pos = pgm.Get(&v32.int32, pos);
896 v32.int32 = WDL_bswap_if_le(v32.int32);
897 GetParam(i)->SetNormalized((double) v32.f);
898 }
899 LEAVE_PARAMS_MUTEX
900
901 ModifyCurrentPreset(prgName);
904
905 return true;
906 }
907 }
908 }
909
910 return false;
911}
912
913bool IPluginBase::LoadBankFromFXB(const char* file)
914{
915 if (CStringHasContents(file))
916 {
917 FILE* fp = fopenUTF8(file, "rb");
918
919 if (fp)
920 {
921 IByteChunk bnk;
922 long fileSize;
923
924 fseek(fp , 0 , SEEK_END);
925 fileSize = ftell(fp);
926 rewind(fp);
927
928 bnk.Resize((int) fileSize);
929 fread(bnk.GetData(), fileSize, 1, fp);
930
931 fclose(fp);
932
933 int pos = 0;
934
935 int32_t chunkMagic;
936 int32_t byteSize = 0;
937 int32_t fxbMagic;
938 int32_t fxbVersion;
939 int32_t pluginID;
940 int32_t pluginVersion;
941 int32_t numPgms;
942 int32_t currentPgm;
943 char future[124];
944 memset(future, 0, 124);
945
946 pos = bnk.Get(&chunkMagic, pos);
947 chunkMagic = WDL_bswap_if_le(chunkMagic);
948 pos = bnk.Get(&byteSize, pos);
949 byteSize = WDL_bswap_if_le(byteSize);
950 pos = bnk.Get(&fxbMagic, pos);
951 fxbMagic = WDL_bswap_if_le(fxbMagic);
952 pos = bnk.Get(&fxbVersion, pos);
953 fxbVersion = WDL_bswap_if_le(fxbVersion);
954 pos = bnk.Get(&pluginID, pos);
955 pluginID = WDL_bswap_if_le(pluginID);
956 pos = bnk.Get(&pluginVersion, pos);
957 pluginVersion = WDL_bswap_if_le(pluginVersion);
958 pos = bnk.Get(&numPgms, pos);
959 numPgms = WDL_bswap_if_le(numPgms);
960 pos = bnk.Get(&currentPgm, pos);
961 currentPgm = WDL_bswap_if_le(currentPgm);
962 pos = bnk.GetBytes(future, 124, pos);
963
964 if (chunkMagic != 'CcnK') return false;
965 //if (fxbVersion != kFXBVersionNum) return false; // TODO: what if a host saves as a different version?
966 if (pluginID != GetUniqueID()) return false;
967 //if (pluginVersion != GetPluginVersion(true)) return false; // TODO: provide mechanism for loading earlier versions
968 //if (numPgms != NPresets()) return false; // TODO: provide mechanism for loading earlier versions with less params
969
970 if (DoesStateChunks() && fxbMagic == 'FBCh')
971 {
972 int32_t chunkSize;
973 pos = bnk.Get(&chunkSize, pos);
974 chunkSize = WDL_bswap_if_le(chunkSize);
975
977 UnserializePresets(bnk, pos);
978 //RestorePreset(currentPgm);
980 return true;
981 }
982 else if (fxbMagic == 'FxBk') // Due to the big Endian-ness of FXP/FXB format we cannot call SerializeParams()
983 {
984 int32_t chunkMagic;
985 int32_t byteSize;
986 int32_t fxpMagic;
987 int32_t fxpVersion;
988 int32_t pluginID;
989 int32_t pluginVersion;
990 int32_t numParams;
991 char prgName[28];
992
993 for(int i = 0; i<numPgms; i++)
994 {
995 pos = bnk.Get(&chunkMagic, pos);
996 chunkMagic = WDL_bswap_if_le(chunkMagic);
997
998 pos = bnk.Get(&byteSize, pos);
999 byteSize = WDL_bswap_if_le(byteSize);
1000
1001 pos = bnk.Get(&fxpMagic, pos);
1002 fxpMagic = WDL_bswap_if_le(fxpMagic);
1003
1004 pos = bnk.Get(&fxpVersion, pos);
1005 fxpVersion = WDL_bswap_if_le(fxpVersion);
1006
1007 pos = bnk.Get(&pluginID, pos);
1008 pluginID = WDL_bswap_if_le(pluginID);
1009
1010 pos = bnk.Get(&pluginVersion, pos);
1011 pluginVersion = WDL_bswap_if_le(pluginVersion);
1012
1013 pos = bnk.Get(&numParams, pos);
1014 numParams = WDL_bswap_if_le(numParams);
1015
1016 if (chunkMagic != 'CcnK') return false;
1017 if (fxpMagic != 'FxCk') return false;
1018 if (fxpVersion != kFXPVersionNum) return false;
1019 if (numParams != NParams()) return false;
1020
1021 pos = bnk.GetBytes(prgName, 28, pos);
1022
1023 RestorePreset(i);
1024
1025 ENTER_PARAMS_MUTEX
1026 for (int j = 0; j< NParams(); j++)
1027 {
1028 WDL_EndianFloat v32;
1029 pos = bnk.Get(&v32.int32, pos);
1030 v32.int32 = WDL_bswap_if_le(v32.int32);
1031 GetParam(j)->SetNormalized((double) v32.f);
1032 }
1033 LEAVE_PARAMS_MUTEX
1034
1035 ModifyCurrentPreset(prgName);
1036 }
1037
1038 RestorePreset(currentPgm);
1040
1041 return true;
1042 }
1043 }
1044 }
1045
1046 return false;
1047}
Manages a block of memory, for plug-in settings store/recall.
Definition: IPlugStructs.h:112
static int GetIPlugVerFromChunk(const IByteChunk &chunk, int &position)
Helper method to retrieve the IPlug version number from the beginning of the byte chunk.
Definition: IPlugStructs.h:132
int Put(const T *pVal)
Copies arbitary typed data into the IByteChunk.
Definition: IPlugStructs.h:170
int GetBytes(void *pDst, int nBytesToCopy, int startPos) const
Copy raw bytes from the IByteChunk, returning the new position for subsequent calls.
Definition: IPlugStructs.h:160
int PutStr(const char *str)
Put a string into the IByteChunk.
Definition: IPlugStructs.h:189
int Get(T *pDst, int startPos) const
Get arbitary typed data from the IByteChunk.
Definition: IPlugStructs.h:181
int PutBytes(const void *pSrc, int nBytesToCopy)
Copies data into the chunk, placing it at the end, resizing if necessary.
Definition: IPlugStructs.h:147
void Clear()
Clears the chunk (resizes to 0)
Definition: IPlugStructs.h:214
uint8_t * GetData()
Gets a ptr to the chunk data.
Definition: IPlugStructs.h:242
static void InitChunkWithIPlugVer(IByteChunk &chunk)
This method is used in order to place the IPlug version number in the chunk when serialising data.
Definition: IPlugStructs.h:119
int Size() const
Returns the current size of the chunk.
Definition: IPlugStructs.h:221
int Resize(int newSize)
Resizes the chunk.
Definition: IPlugStructs.h:229
int GetStr(WDL_String &str, int startPos) const
Get a string from the IByteChunk.
Definition: IPlugStructs.h:200
int PutChunk(const IByteChunk *pRHS)
Put another IByteChunk into this one.
Definition: IPlugStructs.h:208
IPlug's parameter class.
void SetToDefault()
Replaces the parameter's current value with the default one
EParamType Type() const
Get the parameter's type.
void Set(double value)
Sets the parameter value.
std::function< void(double, WDL_String &)> DisplayFunc
DisplayFunc allows custom parameter display functions, defined by a lambda matching this signature.
void SetNormalized(double normalizedValue)
Sets the parameter value from a normalized range (usually coming from the linked IControl)
EParamUnit
Used by AudioUnit plugins to determine the appearance of parameters, based on the kind of data they r...
const char * GetName() const
Returns the parameter's name.
bool Bool() const
Returns the parameter's value as a boolean.
void PrintDetails() const
Helper to print the parameter details to debug console in debug builds.
int Int() const
Returns the parameter's value as an integer.
const char * GetGroup() const
Returns the parameter's group.
double Value() const
Gets a readable value of the parameter.
void ForParamInRange(int startIdx, int endIdx, std::function< void(int paramIdx, IParam &param)> func)
Modify a range of parameters with a lamda function.
void InitParamRange(int startIdx, int endIdx, int countStart, const char *nameFmtStr, double defaultVal, double minVal, double maxVal, double step, const char *label="", int flags=0, const char *group="", const IParam::Shape &shape=IParam::ShapeLinear(), IParam::EParamUnit unit=IParam::kUnitCustom, IParam::DisplayFunc displayFunc=nullptr)
Initialise a range of parameters simultaneously.
virtual int UnserializeState(const IByteChunk &chunk, int startPos)
Override this method to unserialize custom state data, if your plugin does state chunks.
void DefaultParamValues()
Set all parameters to their default values.
void DumpMakePresetFromNamedParamsSrc(const char *file, const char *paramEnumNames[]) const
Writes a call to MakePresetFromNamedParams() for the current preset to a new text file.
bool SerializeParams(IByteChunk &chunk) const
Serializes the current double precision floating point, non-normalised values (IParam::mValue) of all...
int GetPluginVersion(bool decimal) const
Get the plug-in version number.
const char * GetArchStr() const
void RandomiseParamValues()
Randomise all parameters.
void MakePresetFromBlob(const char *name, const char *blob, int sizeOfChunk)
Creates a preset from a base64 encoded CString.
int GetUniqueID() const
int UnserializePresets(const IByteChunk &chunk, int startPos)
[VST2 only] Called when the VST2 host calls effSetChunk for a bank *
bool LoadPresetFromFXP(const char *file)
Load VST2 format preset.
virtual bool SerializeState(IByteChunk &chunk) const
Override this method to serialize custom state data, if your plugin does state chunks.
bool DoesStateChunks() const
void ModifyCurrentPreset(const char *name=0)
This method should update the current preset with current values NOTE: This is only relevant for VST2...
int GetCurrentPresetIdx() const
Get the index of the current, active preset.
int UnserializeParams(const IByteChunk &chunk, int startPos)
Unserializes double precision floating point, non-normalised values from a byte chunk into mParams.
void EnsureDefaultPreset()
[VST2 only] Called to fill uninitialzed presets
int GetHostVersion(bool decimal) const
Get the host version number as an integer.
void CopyParamValues(int startIdx, int destIdx, int nParams)
Copy a range of parameter values.
virtual void InformHostOfPresetChange()
Implemented by the API class, called by the UI (etc) when the plug-in initiates a program/preset chan...
void GetPluginVersionStr(WDL_String &str) const
Gets the plug-in version as a string.
void MakePresetFromNamedParams(const char *name, int nParamsNamed,...)
Create a baked-in factory preset, specifiying parameter values with a list of parameter index and val...
void DumpPresetBlob(const char *file) const
Writes a call to MakePresetFromBlob() for the current preset to a new text file.
bool RestorePreset(int idx)
Restore a preset by index.
void GetBuildInfoStr(WDL_String &str, const char *date, const char *time) const
Get the build date of the plug-in and architecture/api details in one string.
void GetHostVersionStr(WDL_String &str) const
Get the host version number as a string.
void MakeDefaultPreset(const char *name=0, int nPresets=1)
This method can be used to initialize baked-in factory presets with the default parameter values.
const char * GetAPIStr() const
bool SerializePresets(IByteChunk &chunk) const
[VST2 only] Called when the VST2 host calls effGetChunk for a bank *
void ForParamInGroup(const char *paramGroup, std::function< void(int paramIdx, IParam &param)> func)
Modify a parameter group simulataneously.
const char * GetPresetName(int idx) const
Get the name a preset.
bool LoadBankFromFXB(const char *file)
Load VST2 format bank [VST2 only].
void CloneParamRange(int cloneStartIdx, int cloneEndIdx, int startIdx, const char *searchStr="", const char *replaceStr="", const char *newGroup="")
Clone a range of parameters, optionally doing a string substitution on the parameter name.
void DumpMakePresetSrc(const char *file) const
Writes a call to MakePreset() for the current preset to a new text file.
bool SavePresetAsFXP(const char *file) const
Save current state as a VST2 format preset.
void PruneUninitializedPresets()
[AUV2 only] Removes any presets that weren't initialized
EAPI GetAPI() const
void PrintParamValues()
Default parameter values for a parameter group
virtual void OnPresetsModified()
[VST2 only] Called when the preset name is changed by the host
void MakePresetFromChunk(const char *name, IByteChunk &chunk)
Creates a preset from an IByteChunk containging serialized data.
int NPresets() const
Gets the number of factory presets.
bool SaveBankAsFXB(const char *file) const
Save current bank as a VST2 format bank [VST2 only].
void MakePreset(const char *name,...)
Create a baked-in factory preset, specifiying parameter values sequentially usage: MakePreset(name,...
static int GetDecimalVersion(int versionInteger)
Helper function to get the version number as a decimal integer.
static void GetVersionStr(int versionInteger, WDL_String &str)
Helper function to get the semantic version number as a string from an integer.
Base struct for parameter shaping.
A struct used for specifying baked-in factory presets.
Definition: IPlugStructs.h:602