iPlug2 - C++ Audio Plug-in Framework
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 
20 using namespace iplug;
21 
22 IPluginBase::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 
29 IPluginBase::~IPluginBase()
30 {
31  mPresets.Empty(true);
32 }
33 
34 int IPluginBase::GetPluginVersion(bool decimal) const
35 {
36  if (decimal)
37  return GetDecimalVersion(mVersion);
38  else
39  return mVersion;
40 }
41 
42 void 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 
53 int IPluginBase::GetHostVersion(bool decimal) const
54 {
55  if (decimal)
56  return GetDecimalVersion(mHostVersion);
57 
58  return mHostVersion;
59 }
60 
61 void IPluginBase::GetHostVersionStr(WDL_String& str) const
62 {
63  GetVersionStr(mHostVersion, str);
64 }
65 
66 const 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 
82 const 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 
95 void 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 
119 int 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 
139 void 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 
149 void 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 
160 void 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 
172 void 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 
197 void 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 
205 void 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 
222 void IPluginBase::DefaultParamValues(int startIdx, int endIdx)
223 {
224  ForParamInRange(startIdx, endIdx, [](int paramIdx, IParam& param) {
225  param.SetToDefault();
226  });
227 }
228 
229 void 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 
241 void 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 
246 void 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 
259 static 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 
273 void 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 
287 void 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 
308 void 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 
351 void 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 
363 void 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 
372 static 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  sprintf(str, "%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;
433  OnPresetsModified();
434  OnRestoreState();
435  }
436  }
437  return restoredOK;
438 }
439 
440 bool 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 
457 const 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 
466 void IPluginBase::ModifyCurrentPreset(const char* name)
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 
505 int 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 
533 void 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 = fopen(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  char paramVal[32];
551  switch (pParam->Type())
552  {
553  case IParam::kTypeBool:
554  sprintf(paramVal, "%s", (pParam->Bool() ? "true" : "false"));
555  break;
556  case IParam::kTypeInt:
557  sprintf(paramVal, "%d", pParam->Int());
558  break;
559  case IParam::kTypeEnum:
560  sprintf(paramVal, "%d", pParam->Int());
561  break;
562  case IParam::kTypeDouble:
563  default:
564  sprintf(paramVal, "%.6f", pParam->Value());
565  break;
566  }
567  fprintf(fp, ", %s", paramVal);
568  }
569  fprintf(fp, ");\n");
570  fclose(fp);
571  }
572 }
573 
574 void IPluginBase::DumpMakePresetFromNamedParamsSrc(const char* filename, const char* paramEnumNames[]) const
575 {
576  bool sDumped = false;
577 
578  if (!sDumped)
579  {
580  sDumped = true;
581  int i, n = NParams();
582  FILE* fp = fopen(filename, "a");
583 
584  if (!fp)
585  return;
586 
587  int idx = GetCurrentPresetIdx();
588  fprintf(fp, " MakePresetFromNamedParams(\"%s\", %d", GetPresetName(idx), n);
589  for (i = 0; i < n; ++i)
590  {
591  const IParam* pParam = GetParam(i);
592  char paramVal[32];
593  switch (pParam->Type())
594  {
595  case IParam::kTypeBool:
596  sprintf(paramVal, "%s", (pParam->Bool() ? "true" : "false"));
597  break;
598  case IParam::kTypeInt:
599  sprintf(paramVal, "%d", pParam->Int());
600  break;
601  case IParam::kTypeEnum:
602  sprintf(paramVal, "%d", pParam->Int());
603  break;
604  case IParam::kTypeDouble:
605  default:
606  sprintf(paramVal, "%.6f", pParam->Value());
607  break;
608  }
609  fprintf(fp, ",\n %s, %s", paramEnumNames[i], paramVal);
610  }
611  fprintf(fp, ");\n");
612  fclose(fp);
613  }
614 }
615 
616 void IPluginBase::DumpPresetBlob(const char* filename) const
617 {
618  FILE* fp = fopen(filename, "a");
619 
620  if (!fp)
621  return;
622 
623  int idx = GetCurrentPresetIdx();
624  fprintf(fp, "MakePresetFromBlob(\"%s\", \"", GetPresetName(idx));
625 
626  char buf[MAX_BLOB_LENGTH];
627 
628  IByteChunk* pPresetChunk = &mPresets.Get(mCurrentPresetIdx)->mChunk;
629  uint8_t* byteStart = pPresetChunk->GetData();
630 
631  wdl_base64encode(byteStart, buf, pPresetChunk->Size());
632 
633  fprintf(fp, "%s\", %i);\n", buf, pPresetChunk->Size());
634  fclose(fp);
635 }
636 
637 // confusing... IByteChunk will force storage as little endian on big endian platforms,
638 // so when we use it here, since vst fxp/fxb files are big endian, we need to swap the endianess
639 // regardless of the endianness of the host, and on big endian hosts it will get swapped back to
640 // big endian
641 bool IPluginBase::SavePresetAsFXP(const char* file) const
642 {
643  if (CStringHasContents(file))
644  {
645  FILE* fp = fopen(file, "wb");
646 
647  IByteChunk pgm;
648 
649  int32_t chunkMagic = WDL_bswap32('CcnK');
650  int32_t byteSize = 0;
651  int32_t fxpMagic;
652  int32_t fxpVersion = WDL_bswap32(kFXPVersionNum);
653  int32_t pluginID = WDL_bswap32(GetUniqueID());
654  int32_t pluginVersion = WDL_bswap32(GetPluginVersion(true));
655  int32_t numParams = WDL_bswap32(NParams());
656  char prgName[28];
657  memset(prgName, 0, 28);
658  strcpy(prgName, GetPresetName(GetCurrentPresetIdx()));
659 
660  pgm.Put(&chunkMagic);
661 
662  if (DoesStateChunks())
663  {
664  IByteChunk state;
665  int32_t chunkSize;
666 
667  fxpMagic = WDL_bswap32('FPCh');
668 
670  SerializeState(state);
671 
672  chunkSize = WDL_bswap32(state.Size());
673  byteSize = WDL_bswap32(state.Size() + 60);
674 
675  pgm.Put(&byteSize);
676  pgm.Put(&fxpMagic);
677  pgm.Put(&fxpVersion);
678  pgm.Put(&pluginID);
679  pgm.Put(&pluginVersion);
680  pgm.Put(&numParams);
681  pgm.PutBytes(prgName, 28); // not PutStr (we want all 28 bytes)
682  pgm.Put(&chunkSize);
683  pgm.PutBytes(state.GetData(), state.Size());
684  }
685  else
686  {
687  fxpMagic = WDL_bswap32('FxCk');
688  //byteSize = WDL_bswap32(20 + 28 + (NParams() * 4) );
689  pgm.Put(&byteSize);
690  pgm.Put(&fxpMagic);
691  pgm.Put(&fxpVersion);
692  pgm.Put(&pluginID);
693  pgm.Put(&pluginVersion);
694  pgm.Put(&numParams);
695  pgm.PutBytes(prgName, 28); // not PutStr (we want all 28 bytes)
696 
697  for (int i = 0; i< NParams(); i++)
698  {
699  WDL_EndianFloat v32;
700  v32.f = (float) GetParam(i)->GetNormalized();
701  unsigned int swapped = WDL_bswap32(v32.int32);
702  pgm.Put(&swapped);
703  }
704  }
705 
706  fwrite(pgm.GetData(), pgm.Size(), 1, fp);
707  fclose(fp);
708 
709  return true;
710  }
711  return false;
712 }
713 
714 bool IPluginBase::SaveBankAsFXB(const char* file) const
715 {
716  if (CStringHasContents(file))
717  {
718  FILE* fp = fopen(file, "wb");
719 
720  IByteChunk bnk;
721 
722  int32_t chunkMagic = WDL_bswap32('CcnK');
723  int32_t byteSize = 0;
724  int32_t fxbMagic;
725  int32_t fxbVersion = WDL_bswap32(kFXBVersionNum);
726  int32_t pluginID = WDL_bswap32(GetUniqueID());
727  int32_t pluginVersion = WDL_bswap32(GetPluginVersion(true));
728  int32_t numPgms = WDL_bswap32(NPresets());
729  int32_t currentPgm = WDL_bswap32(GetCurrentPresetIdx());
730  char future[124];
731  memset(future, 0, 124);
732 
733  bnk.Put(&chunkMagic);
734 
735  if (DoesStateChunks())
736  {
737  IByteChunk state;
738  int32_t chunkSize;
739 
740  fxbMagic = WDL_bswap32('FBCh');
741 
743  SerializePresets(state);
744 
745  chunkSize = WDL_bswap32(state.Size());
746  byteSize = WDL_bswap32(160 + state.Size() );
747 
748  bnk.Put(&byteSize);
749  bnk.Put(&fxbMagic);
750  bnk.Put(&fxbVersion);
751  bnk.Put(&pluginID);
752  bnk.Put(&pluginVersion);
753  bnk.Put(&numPgms);
754  bnk.Put(&currentPgm);
755  bnk.PutBytes(&future, 124);
756 
757  bnk.Put(&chunkSize);
758  bnk.PutBytes(state.GetData(), state.Size());
759  }
760  else
761  {
762  fxbMagic = WDL_bswap32('FxBk');
763 
764  bnk.Put(&byteSize);
765  bnk.Put(&fxbMagic);
766  bnk.Put(&fxbVersion);
767  bnk.Put(&pluginID);
768  bnk.Put(&pluginVersion);
769  bnk.Put(&numPgms);
770  bnk.Put(&currentPgm);
771  bnk.PutBytes(&future, 124);
772 
773  int32_t fxpMagic = WDL_bswap32('FxCk');
774  int32_t fxpVersion = WDL_bswap32(kFXPVersionNum);
775  int32_t numParams = WDL_bswap32(NParams());
776 
777  for (int p = 0; p < NPresets(); p++)
778  {
779  IPreset* pPreset = mPresets.Get(p);
780 
781  char prgName[28];
782  memset(prgName, 0, 28);
783  strcpy(prgName, pPreset->mName);
784 
785  bnk.Put(&chunkMagic);
786  //byteSize = WDL_bswap32(20 + 28 + (NParams() * 4) );
787  bnk.Put(&byteSize);
788  bnk.Put(&fxpMagic);
789  bnk.Put(&fxpVersion);
790  bnk.Put(&pluginID);
791  bnk.Put(&pluginVersion);
792  bnk.Put(&numParams);
793  bnk.PutBytes(prgName, 28);
794 
795  int pos = 0;
796 
797  for (int i = 0; i< NParams(); i++)
798  {
799  double v = 0.0;
800  pos = pPreset->mChunk.Get(&v, pos);
801 
802  WDL_EndianFloat v32;
803  v32.f = (float) GetParam(i)->ToNormalized(v);
804  uint32_t swapped = WDL_bswap32(v32.int32);
805  bnk.Put(&swapped);
806  }
807  }
808  }
809 
810  fwrite(bnk.GetData(), bnk.Size(), 1, fp);
811  fclose(fp);
812 
813  return true;
814  }
815  else
816  return false;
817 }
818 
819 bool IPluginBase::LoadPresetFromFXP(const char* file)
820 {
821  if (CStringHasContents(file))
822  {
823  FILE* fp = fopen(file, "rb");
824 
825  if (fp)
826  {
827  IByteChunk pgm;
828  long fileSize;
829 
830  fseek(fp , 0 , SEEK_END);
831  fileSize = ftell(fp);
832  rewind(fp);
833 
834  pgm.Resize((int) fileSize);
835  fread(pgm.GetData(), fileSize, 1, fp);
836 
837  fclose(fp);
838 
839  int pos = 0;
840 
841  int32_t chunkMagic;
842  int32_t byteSize = 0;
843  int32_t fxpMagic;
844  int32_t fxpVersion;
845  int32_t pluginID;
846  int32_t pluginVersion;
847  int32_t numParams;
848  char prgName[28];
849 
850  pos = pgm.Get(&chunkMagic, pos);
851  chunkMagic = WDL_bswap_if_le(chunkMagic);
852  pos = pgm.Get(&byteSize, pos);
853  byteSize = WDL_bswap_if_le(byteSize);
854  pos = pgm.Get(&fxpMagic, pos);
855  fxpMagic = WDL_bswap_if_le(fxpMagic);
856  pos = pgm.Get(&fxpVersion, pos);
857  fxpVersion = WDL_bswap_if_le(fxpVersion);
858  pos = pgm.Get(&pluginID, pos);
859  pluginID = WDL_bswap_if_le(pluginID);
860  pos = pgm.Get(&pluginVersion, pos);
861  pluginVersion = WDL_bswap_if_le(pluginVersion);
862  pos = pgm.Get(&numParams, pos);
863  numParams = WDL_bswap_if_le(numParams);
864  pos = pgm.GetBytes(prgName, 28, pos);
865 
866  if (chunkMagic != 'CcnK') return false;
867  if (fxpVersion != kFXPVersionNum) return false; // TODO: what if a host saves as a different version?
868  if (pluginID != GetUniqueID()) return false;
869  //if (pluginVersion != GetPluginVersion(true)) return false; // TODO: provide mechanism for loading earlier versions
870  //if (numParams != NParams()) return false; // TODO: provide mechanism for loading earlier versions with less params
871 
872  if (DoesStateChunks() && fxpMagic == 'FPCh')
873  {
874  int32_t chunkSize;
875  pos = pgm.Get(&chunkSize, pos);
876  chunkSize = WDL_bswap_if_le(chunkSize);
877 
879  UnserializeState(pgm, pos);
880  ModifyCurrentPreset(prgName);
881  RestorePreset(GetCurrentPresetIdx());
882  InformHostOfPresetChange();
883 
884  return true;
885  }
886  else if (fxpMagic == 'FxCk') // Due to the big Endian-ness of FXP/FXB format we cannot call SerializeParams()
887  {
888  ENTER_PARAMS_MUTEX
889  for (int i = 0; i< NParams(); i++)
890  {
891  WDL_EndianFloat v32;
892  pos = pgm.Get(&v32.int32, pos);
893  v32.int32 = WDL_bswap_if_le(v32.int32);
894  GetParam(i)->SetNormalized((double) v32.f);
895  }
896  LEAVE_PARAMS_MUTEX
897 
898  ModifyCurrentPreset(prgName);
899  RestorePreset(GetCurrentPresetIdx());
900  InformHostOfPresetChange();
901 
902  return true;
903  }
904  }
905  }
906 
907  return false;
908 }
909 
910 bool IPluginBase::LoadBankFromFXB(const char* file)
911 {
912  if (CStringHasContents(file))
913  {
914  FILE* fp = fopen(file, "rb");
915 
916  if (fp)
917  {
918  IByteChunk bnk;
919  long fileSize;
920 
921  fseek(fp , 0 , SEEK_END);
922  fileSize = ftell(fp);
923  rewind(fp);
924 
925  bnk.Resize((int) fileSize);
926  fread(bnk.GetData(), fileSize, 1, fp);
927 
928  fclose(fp);
929 
930  int pos = 0;
931 
932  int32_t chunkMagic;
933  int32_t byteSize = 0;
934  int32_t fxbMagic;
935  int32_t fxbVersion;
936  int32_t pluginID;
937  int32_t pluginVersion;
938  int32_t numPgms;
939  int32_t currentPgm;
940  char future[124];
941  memset(future, 0, 124);
942 
943  pos = bnk.Get(&chunkMagic, pos);
944  chunkMagic = WDL_bswap_if_le(chunkMagic);
945  pos = bnk.Get(&byteSize, pos);
946  byteSize = WDL_bswap_if_le(byteSize);
947  pos = bnk.Get(&fxbMagic, pos);
948  fxbMagic = WDL_bswap_if_le(fxbMagic);
949  pos = bnk.Get(&fxbVersion, pos);
950  fxbVersion = WDL_bswap_if_le(fxbVersion);
951  pos = bnk.Get(&pluginID, pos);
952  pluginID = WDL_bswap_if_le(pluginID);
953  pos = bnk.Get(&pluginVersion, pos);
954  pluginVersion = WDL_bswap_if_le(pluginVersion);
955  pos = bnk.Get(&numPgms, pos);
956  numPgms = WDL_bswap_if_le(numPgms);
957  pos = bnk.Get(&currentPgm, pos);
958  currentPgm = WDL_bswap_if_le(currentPgm);
959  pos = bnk.GetBytes(future, 124, pos);
960 
961  if (chunkMagic != 'CcnK') return false;
962  //if (fxbVersion != kFXBVersionNum) return false; // TODO: what if a host saves as a different version?
963  if (pluginID != GetUniqueID()) return false;
964  //if (pluginVersion != GetPluginVersion(true)) return false; // TODO: provide mechanism for loading earlier versions
965  //if (numPgms != NPresets()) return false; // TODO: provide mechanism for loading earlier versions with less params
966 
967  if (DoesStateChunks() && fxbMagic == 'FBCh')
968  {
969  int32_t chunkSize;
970  pos = bnk.Get(&chunkSize, pos);
971  chunkSize = WDL_bswap_if_le(chunkSize);
972 
974  UnserializePresets(bnk, pos);
975  //RestorePreset(currentPgm);
976  InformHostOfPresetChange();
977  return true;
978  }
979  else if (fxbMagic == 'FxBk') // Due to the big Endian-ness of FXP/FXB format we cannot call SerializeParams()
980  {
981  int32_t chunkMagic;
982  int32_t byteSize;
983  int32_t fxpMagic;
984  int32_t fxpVersion;
985  int32_t pluginID;
986  int32_t pluginVersion;
987  int32_t numParams;
988  char prgName[28];
989 
990  for(int i = 0; i<numPgms; i++)
991  {
992  pos = bnk.Get(&chunkMagic, pos);
993  chunkMagic = WDL_bswap_if_le(chunkMagic);
994 
995  pos = bnk.Get(&byteSize, pos);
996  byteSize = WDL_bswap_if_le(byteSize);
997 
998  pos = bnk.Get(&fxpMagic, pos);
999  fxpMagic = WDL_bswap_if_le(fxpMagic);
1000 
1001  pos = bnk.Get(&fxpVersion, pos);
1002  fxpVersion = WDL_bswap_if_le(fxpVersion);
1003 
1004  pos = bnk.Get(&pluginID, pos);
1005  pluginID = WDL_bswap_if_le(pluginID);
1006 
1007  pos = bnk.Get(&pluginVersion, pos);
1008  pluginVersion = WDL_bswap_if_le(pluginVersion);
1009 
1010  pos = bnk.Get(&numParams, pos);
1011  numParams = WDL_bswap_if_le(numParams);
1012 
1013  if (chunkMagic != 'CcnK') return false;
1014  if (fxpMagic != 'FxCk') return false;
1015  if (fxpVersion != kFXPVersionNum) return false;
1016  if (numParams != NParams()) return false;
1017 
1018  pos = bnk.GetBytes(prgName, 28, pos);
1019 
1020  RestorePreset(i);
1021 
1022  ENTER_PARAMS_MUTEX
1023  for (int j = 0; j< NParams(); j++)
1024  {
1025  WDL_EndianFloat v32;
1026  pos = bnk.Get(&v32.int32, pos);
1027  v32.int32 = WDL_bswap_if_le(v32.int32);
1028  GetParam(j)->SetNormalized((double) v32.f);
1029  }
1030  LEAVE_PARAMS_MUTEX
1031 
1032  ModifyCurrentPreset(prgName);
1033  }
1034 
1035  RestorePreset(currentPgm);
1036  InformHostOfPresetChange();
1037 
1038  return true;
1039  }
1040  }
1041  }
1042 
1043  return false;
1044 }
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...
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.
const char * GetPresetName(int idx) const
Get the name a preset.
const char * GetName() const
Returns the parameter&#39;s name.
void MakePreset(const char *name,...)
Create a baked-in factory preset, specifiying parameter values sequentially usage: MakePreset(name...
void PrintParamValues()
Default parameter values for a parameter group.
const char * GetArchStr() const
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...
const char * GetAPIStr() const
void Set(double value)
Sets the parameter value.
void Clear()
Clears the chunk (resizes to 0)
Definition: IPlugStructs.h:214
void DumpMakePresetSrc(const char *file) const
Writes a call to MakePreset() for the current preset to a new text file.
void ForParamInGroup(const char *paramGroup, std::function< void(int paramIdx, IParam &param)> func)
Modify a parameter group simulataneously.
void MakePresetFromNamedParams(const char *name, int nParamsNamed,...)
Create a baked-in factory preset, specifiying parameter values with a list of parameter index and val...
int PutStr(const char *str)
Put a string into the IByteChunk.
Definition: IPlugStructs.h:189
IPlug&#39;s parameter class.
void GetHostVersionStr(WDL_String &str) const
Get the host version number as a string.
int Get(T *pDst, int startPos) const
Get arbitary typed data from the IByteChunk.
Definition: IPlugStructs.h:181
void PruneUninitializedPresets()
[AUV2 only] Removes any presets that weren&#39;t initialized
void RandomiseParamValues()
Randomise all parameters.
void GetPluginVersionStr(WDL_String &str) const
Gets the plug-in version as a string.
bool Bool() const
Returns the parameter&#39;s value as a boolean.
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
Base struct for parameter shaping.
void EnsureDefaultPreset()
[VST2 only] Called to fill uninitialzed presets
void DumpPresetBlob(const char *file) const
Writes a call to MakePresetFromBlob() for the current preset to a new text file.
int Put(const T *pVal)
Copies arbitary typed data into the IByteChunk.
Definition: IPlugStructs.h:170
double Value() const
Gets a readable value of the parameter.
Manages a block of memory, for plug-in settings store/recall.
Definition: IPlugStructs.h:111
void DefaultParamValues()
Set all parameters to their default values.
int UnserializePresets(const IByteChunk &chunk, int startPos)
[VST2 only] Called when the VST2 host calls effSetChunk for a bank *
void MakePresetFromBlob(const char *name, const char *blob, int sizeOfChunk)
Creates a preset from a base64 encoded CString.
int UnserializeParams(const IByteChunk &chunk, int startPos)
Unserializes double precision floating point, non-normalised values from a byte chunk into mParams...
Base class that contains plug-in info and state manipulation methods.
A struct used for specifying baked-in factory presets.
Definition: IPlugStructs.h:598
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) ...
int GetHostVersion(bool decimal) const
Get the host version number as an integer.
int Size() const
Returns the current size of the chunk.
Definition: IPlugStructs.h:221
const char * GetGroup() const
Returns the parameter&#39;s group.
int Resize(int newSize)
Resizes the chunk.
Definition: IPlugStructs.h:229
static void GetVersionStr(int versionInteger, WDL_String &str)
Helper function to get the semantic version number as a string from an integer.
bool LoadPresetFromFXP(const char *file)
Load VST2 format preset.
int Int() const
Returns the parameter&#39;s value as an integer.
void ModifyCurrentPreset(const char *name=0)
This method should update the current preset with current values NOTE: This is only relevant for VST2...
bool LoadBankFromFXB(const char *file)
Load VST2 format bank [VST2 only].
void PrintDetails() const
Helper to print the parameter details to debug console in debug builds.
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
bool SerializeParams(IByteChunk &chunk) const
Serializes the current double precision floating point, non-normalised values (IParam::mValue) of all...
EParamUnit
Used by AudioUnit plugins to determine the appearance of parameters, based on the kind of data they r...
bool RestorePreset(int idx)
Restore a preset by index.
static int GetDecimalVersion(int versionInteger)
Helper function to get the version number as a decimal integer.
void ForParamInRange(int startIdx, int endIdx, std::function< void(int paramIdx, IParam &param)> func)
Modify a range of parameters with a lamda function.
void MakePresetFromChunk(const char *name, IByteChunk &chunk)
Creates a preset from an IByteChunk containging serialized data.
bool SavePresetAsFXP(const char *file) const
Save current state as a VST2 format preset.
EParamType Type() const
Get the parameter&#39;s type.
void DumpMakePresetFromNamedParamsSrc(const char *file, const char *paramEnumNames[]) const
Writes a call to MakePresetFromNamedParams() for the current preset to a new text file...
int GetStr(WDL_String &str, int startPos) const
Get a string from the IByteChunk.
Definition: IPlugStructs.h:200
uint8_t * GetData()
Gets a ptr to the chunk data.
Definition: IPlugStructs.h:242
int PutChunk(const IByteChunk *pRHS)
Put another IByteChunk into this one.
Definition: IPlugStructs.h:208
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.
int PutBytes(const void *pSrc, int nBytesToCopy)
Copies data into the chunk, placing it at the end, resizing if nessecary.
Definition: IPlugStructs.h:147
int GetPluginVersion(bool decimal) const
Get the plug-in version number.
void CopyParamValues(int startIdx, int destIdx, int nParams)
Copy a range of parameter values.
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
bool SerializePresets(IByteChunk &chunk) const
[VST2 only] Called when the VST2 host calls effGetChunk for a bank *
bool SaveBankAsFXB(const char *file) const
Save current bank as a VST2 format bank [VST2 only].
void SetToDefault()
Replaces the parameter&#39;s current value with the default one.