Jamba C++ API  6.1.0
ParamDef.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2023 pongasoft
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  *
16  * @author Yan Pujante
17  */
18 #pragma once
19 
20 #include "ParamConverters.h"
21 #include "ParamSerializers.h"
22 #include "Messaging.h"
23 #include "NormalizedState.h"
24 
25 #include <base/source/fstreamer.h>
26 #include <pluginterfaces/vst/vsttypes.h>
27 #include <pluginterfaces/vst/ivsteditcontroller.h>
28 #include <pluginterfaces/vst/ivstunits.h>
29 
30 #include <string>
31 #include <memory>
32 
33 namespace pongasoft::VST {
34 
35 using namespace Steinberg;
36 using namespace Steinberg::Vst;
37 
38 // forward declaration required for API
39 namespace GUI::Params {
40 class IGUIJmbParameter;
41 }
42 
46 class IParamDef : public std::enable_shared_from_this<IParamDef>
47 {
48 public:
51  enum class Owner
52  {
53  kRT,
54  kGUI
55  };
56 
58  static constexpr int16 kVersionNotDeprecated = -1;
59 
60 public:
61  IParamDef(ParamID const iParamID,
62  VstString16 iTitle,
63  Owner const iOwner,
64  bool const iTransient,
65  int16 const iDeprecatedSince) :
66  fParamID{iParamID},
67  fTitle{std::move(iTitle)},
68  fOwner{iOwner},
69  fTransient{iTransient},
70  fDeprecatedSince{iDeprecatedSince}
71  {}
72 
73  virtual ~IParamDef() = default;
74 
76  bool isDeprecated() const { return fDeprecatedSince > kVersionNotDeprecated; }
77 
78 public:
79  const ParamID fParamID;
81  const Owner fOwner; // who owns the parameter (and which stream will it be saved if non transient)
82  const bool fTransient; // not saved in the stream
83  const int16 fDeprecatedSince; // at which version the parameter got deprecated
84 };
85 
86 
90 class RawVstParamDef : public IParamDef
91 {
92 public:
93  RawVstParamDef(ParamID const iParamID,
94  VstString16 iTitle,
95  VstString16 iUnits,
96  ParamValue const iDefaultNormalizedValue,
97  int32 const iStepCount,
98  int32 const iFlags,
99  UnitID const iUnitID,
100  VstString16 iShortTitle,
101  int32 const iPrecision,
102  Owner const iOwner,
103  bool const iTransient,
104  int16 const iDeprecatedSince) :
105  IParamDef(iParamID, std::move(iTitle), iOwner, iTransient, iDeprecatedSince),
106  fUnits{std::move(iUnits)},
107  fDefaultValue{Utils::clampE(iDefaultNormalizedValue, 0.0, 1.0)},
108  fStepCount{iStepCount},
109  fFlags{iFlags},
110  fUnitID{iUnitID},
111  fShortTitle{std::move(iShortTitle)},
112  fPrecision{iPrecision}
113  {}
114 
115 public:
116  // readFromStream
117  ParamValue readFromStream(IBStreamer &iStreamer) const
118  {
119  ParamValue res = fDefaultValue;
120 
121  ParamValue value;
122  if(IBStreamHelper::readDouble(iStreamer, value) == kResultOk)
123  res = value;
124 
125  return res;
126  }
127 
129  ParamValue readFromState(NormalizedState const &iState) const
130  {
131  ParamValue res = fDefaultValue;
132  iState.getNormalizedValue(fParamID, res);
133  return res;
134  }
135 
137  tresult writeToState(ParamValue iValue, NormalizedState &oState) const
138  {
139  return oState.setNormalizedValue(fParamID, iValue);
140  }
141 
142  // toString
143  virtual void toString(ParamValue iNormalizedValue, String128 iString) const
144  {
145  RawParamConverter::staticToString(iNormalizedValue, iString, fPrecision);
146  }
147 
154  virtual std::string toUTF8String(ParamValue iNormalizedValue, int32 iPrecision) const
155  {
156  String128 s;
157  s[0] = 0;
158  RawParamConverter::staticToString(iNormalizedValue, s, iPrecision >= 0 ? iPrecision : fPrecision);
159  return VstUtils::toUT8String(s);
160  }
161 
162 public:
164  const ParamValue fDefaultValue;
165  const int32 fStepCount;
166  const int32 fFlags;
167  const UnitID fUnitID;
169  const int32 fPrecision;
170 };
171 
175 template<typename T>
177 {
178 public:
179  using ParamType = T;
180 
181  VstParamDef(ParamID const iParamID,
182  VstString16 iTitle,
183  VstString16 iUnits,
184  ParamType const iDefaultValue,
185  int32 const iFlags,
186  UnitID const iUnitID,
187  VstString16 iShortTitle,
188  int32 const iPrecision,
189  Owner const iOwner,
190  bool const iTransient,
191  int16 const iDeprecatedSince,
192  std::shared_ptr<IParamConverter<ParamType>> iConverter) :
193  RawVstParamDef(iParamID,
194  std::move(iTitle),
195  std::move(iUnits),
196  iConverter ? iConverter->normalize(iDefaultValue) : 0,
197  iConverter ? iConverter->getStepCount() : 0,
198  iFlags,
199  iUnitID,
200  std::move(iShortTitle),
201  iPrecision,
202  iOwner,
203  iTransient,
204  iDeprecatedSince),
205  fDefaultValue{iDefaultValue},
206  fConverter{std::move(iConverter)}
207  {
208  }
209 
212  {
213  return denormalize(RawVstParamDef::readFromState(iState));
214  }
215 
217  tresult writeToState(ParamType const &iValue, NormalizedState &oState) const
218  {
219  return RawVstParamDef::writeToState(normalize(iValue), oState);
220  }
221 
222  // getDefaultValue
223  ParamType getDefaultValue() const { return fDefaultValue; }
224 
225  // shortcut to normalize
226  inline ParamValue normalize(ParamType const &iValue) const
227  {
228  if(fConverter)
229  return fConverter->normalize(iValue);
230  return 0;
231  }
232 
233  // shortcut to denormalize
234  inline ParamType denormalize(ParamValue iNormalizedValue) const
235  {
236  if(fConverter)
237  return fConverter->denormalize(iNormalizedValue);
238  return fDefaultValue;
239  }
240 
244  void toString(ParamValue iNormalizedValue, String128 iString) const override
245  {
246  if(fConverter)
247  fConverter->toString(fConverter->denormalize(iNormalizedValue), iString, fPrecision);
248  else
249  RawVstParamDef::toString(iNormalizedValue, iString);
250  }
251 
258  std::string toUTF8String(ParamValue iNormalizedValue, int32 iPrecision) const override
259  {
260  if(fConverter)
261  {
262  String128 s;
263  s[0] = 0;
264  fConverter->toString(fConverter->denormalize(iNormalizedValue), s, iPrecision >= 0 ? iPrecision : fPrecision);
265  return VstUtils::toUT8String(s);
266  }
267  else
268  return RawVstParamDef::toUTF8String(iNormalizedValue, iPrecision);
269  }
270 
271 public:
273  const std::shared_ptr<IParamConverter<ParamType>> fConverter;
274 };
275 
279 class IJmbParamDef : public IParamDef
280 {
281 public:
282  IJmbParamDef(const ParamID iParamID,
283  VstString16 iTitle,
284  Owner const iOwner,
285  bool const iTransient,
286  int16 const iDeprecatedSince,
287  bool const iShared)
288  : IParamDef(iParamID, std::move(iTitle), iOwner, iTransient, iDeprecatedSince),
289  fShared{iShared}
290  {}
291 
292  ~IJmbParamDef() override = default;
293 
294  // writeDefaultValue
295  virtual void writeDefaultValue(std::ostream &oStreamer) const = 0;
296 
300  virtual std::shared_ptr<GUI::Params::IGUIJmbParameter> newGUIParam() = 0;
301 
305  virtual bool isSerializable() const = 0;
306 
307 public:
308  bool const fShared;
309 };
310 
315 template<typename T>
317 {
318 public:
319  using ParamType = T;
320 
321  JmbParamDef(ParamID const iParamID,
322  VstString16 iTitle,
323  Owner const iOwner,
324  bool const iTransient,
325  int16 const iDeprecatedSince,
326  bool const iShared,
327  ParamType const &iDefaultValue,
328  std::shared_ptr<IParamSerializer<ParamType>> iSerializer) :
329  IJmbParamDef(iParamID, std::move(iTitle), iOwner, iTransient, iDeprecatedSince, iShared),
330  fDefaultValue{iDefaultValue},
331  fSerializer{std::move(iSerializer)}
332  {}
333 
334  // readFromStream
335  tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const override;
336  ParamType readFromStream(IBStreamer &iStreamer) const;
337 
338  // writeToStream
339  tresult writeToStream(ParamType const &iValue, IBStreamer &oStreamer) const override;
340 
341  // writeToStream
342  void writeToStream(ParamType const &iValue, std::ostream &oStreamer) const override;
343 
344  // writeDefaultValue
345  void writeDefaultValue(std::ostream &oStreamer) const override;
346 
347  // readFromMessage
348  tresult readFromMessage(Message const &iMessage, ParamType &oValue) const;
349 
350  // writeToMessage
351  tresult writeToMessage(ParamType const &iValue, Message &oMessage) const;
352 
359  std::string toUTF8String(ParamType const &iValue, int32 iPrecision) const
360  {
361  if(fSerializer)
362  return fSerializer->toString(iValue, iPrecision);
363  else
364  {
365  if constexpr(Utils::is_operator_write_to_ostream_defined<ParamType>)
366  {
367  std::ostringstream s;
368  if(iPrecision >= 0)
369  {
370  s.precision(iPrecision);
371  s.setf(std::ios::fixed);
372  }
373  s << iValue;
374  return s.str();
375  }
376  else
377  return "";
378  }
379  }
380 
384  std::shared_ptr<IDiscreteConverter<T>> getDiscreteConverter() const
385  {
386  // Implementation note: at this moment, only checks if the serializer also implements the API.
387  // But possible to add an additional separate field to set it explicitly if there is a need
388  return std::dynamic_pointer_cast<IDiscreteConverter<T>>(fSerializer);
389  }
390 
391  // computeMessageAttrID
392  std::string computeMessageAttrID() const
393  {
394  return "__param__" + std::to_string(fParamID);
395  }
396 
403  std::shared_ptr<GUI::Params::IGUIJmbParameter> newGUIParam() override;
404 
408  bool isSerializable() const override { return fSerializer != nullptr; }
409 
410 public:
412  const std::shared_ptr<IParamSerializer<ParamType>> fSerializer;
413 };
414 
415 //------------------------------------------------------------------------
416 // JmbParamDef::readFromStream
417 //------------------------------------------------------------------------
418 template<typename T>
419 tresult JmbParamDef<T>::readFromStream(IBStreamer &iStreamer, T &oValue) const
420 {
421  if(fSerializer)
422  {
423  return fSerializer->readFromStream(iStreamer, oValue);
424  }
425  else
426  return kResultFalse;
427 }
428 
429 //------------------------------------------------------------------------
430 // JmbParamDef::readFromStream
431 //------------------------------------------------------------------------
432 template<typename T>
433 T JmbParamDef<T>::readFromStream(IBStreamer &iStreamer) const
434 {
435  T value;
436  if(readFromStream(iStreamer, value) != kResultOk)
437  value = fDefaultValue;
438  return value;
439 }
440 
441 
442 //------------------------------------------------------------------------
443 // JmbParamDef::writeToStream
444 //------------------------------------------------------------------------
445 template<typename T>
446 tresult JmbParamDef<T>::writeToStream(const T &iValue, IBStreamer &oStreamer) const
447 {
448  if(fSerializer)
449  return fSerializer->writeToStream(iValue, oStreamer);
450  else
451  return kResultFalse;
452 }
453 
454 //------------------------------------------------------------------------
455 // JmbParamDef::writeToStream
456 //------------------------------------------------------------------------
457 template<typename T>
458 void JmbParamDef<T>::writeToStream(const ParamType &iValue, std::ostream &oStream) const
459 {
460  if(fSerializer)
461  fSerializer->writeToStream(iValue, oStream);
462  else
463  {
464  if constexpr(Utils::is_operator_write_to_ostream_defined<ParamType>)
465  {
466  oStream << iValue;
467  }
468  }
469 }
470 
471 //------------------------------------------------------------------------
472 // JmbParamDef::writeDefaultValue
473 //------------------------------------------------------------------------
474 template<typename T>
475 void JmbParamDef<T>::writeDefaultValue(std::ostream &oStreamer) const
476 {
477  writeToStream(fDefaultValue, oStreamer);
478 }
479 
480 //------------------------------------------------------------------------
481 // JmbParamDef::readFromMessage
482 //------------------------------------------------------------------------
483 template<typename T>
484 tresult JmbParamDef<T>::readFromMessage(Message const &iMessage, ParamType &oValue) const
485 {
486  if(fSerializer)
487  return iMessage.getSerializableValue(computeMessageAttrID().c_str(), *this, oValue);
488  else
489  return kResultFalse;
490 }
491 
492 //------------------------------------------------------------------------
493 // JmbParamDef::writeToMessage
494 //------------------------------------------------------------------------
495 template<typename T>
496 tresult JmbParamDef<T>::writeToMessage(const ParamType &iValue, Message &oMessage) const
497 {
498  if(fSerializer)
499  return oMessage.setSerializableValue(computeMessageAttrID().c_str(), *this, iValue);
500  else
501  return kResultFalse;
502 }
503 
504 //------------------------------------------------------------------------
505 // VstParam - define shortcut notation
506 //------------------------------------------------------------------------
507 template<typename T>
508 using VstParam = std::shared_ptr<VstParamDef<T>>;
509 using RawVstParam = std::shared_ptr<RawVstParamDef>;
510 
511 template<typename T, size_t N>
512 using VstParams = std::array<VstParam<T>, N>;
513 
514 template<size_t N>
515 using RawVstParams = std::array<RawVstParam, N>;
516 
517 //------------------------------------------------------------------------
518 // JmbParam - define shortcut notation
519 //------------------------------------------------------------------------
520 template<typename T>
521 using JmbParam = std::shared_ptr<JmbParamDef<T>>;
522 
523 template<typename T, size_t N>
524 using JmbParams = std::array<JmbParam<T>, N>;
525 
526 }
tresult readDouble(IBStreamer &iStreamer, double &oValue)
Definition: ParamSerializers.h:156
const std::shared_ptr< IParamConverter< ParamType > > fConverter
Definition: ParamDef.h:273
ParamType readFromState(NormalizedState const &iState) const
Read the value from the (normalized) state.
Definition: ParamDef.h:211
tresult writeToState(ParamValue iValue, NormalizedState &oState) const
Writes the provided value to the (normalized) state.
Definition: ParamDef.h:137
const ParamType fDefaultValue
Definition: ParamDef.h:411
virtual std::string toUTF8String(ParamValue iNormalizedValue, int32 iPrecision) const
Return the value as a utf-8 string.
Definition: ParamDef.h:154
void toString(ParamValue iNormalizedValue, String128 iString) const override
Using fConverter::toString
Definition: ParamDef.h:244
const std::shared_ptr< IParamSerializer< ParamType > > fSerializer
Definition: ParamDef.h:412
tresult writeToStream(ParamType const &iValue, IBStreamer &oStreamer) const override
This method should write iValue to the stream (aka serialization)
Definition: ParamDef.h:446
Base class for a raw vst parameter definition.
Definition: ParamDef.h:90
const Owner fOwner
Definition: ParamDef.h:81
Simple wrapper class with better api.
Definition: Messaging.h:44
static T clampE(const U &value, const T &lower, const T &upper)
Same as clamp except it will actually fail/assert in debug mode.
Definition: Misc.h:58
const ParamID fParamID
Definition: ParamDef.h:79
ParamType denormalize(ParamValue iNormalizedValue) const
Definition: ParamDef.h:234
tresult setSerializableValue(IAttributeList::AttrID id, IParamSerializer< T > const &iSerializer, T const &iValue)
Serializes the parameter value as an entry in the message.
Definition: Messaging.h:151
std::array< VstParam< T >, N > VstParams
Definition: ParamDef.h:512
const int32 fFlags
Definition: ParamDef.h:166
std::shared_ptr< RawVstParamDef > RawVstParam
Definition: ParamDef.h:509
tresult setNormalizedValue(ParamID iParamID, ParamValue iValue)
Sets the normalized value for the given param id if it exists.
Definition: NormalizedState.cpp:146
const int16 fDeprecatedSince
Definition: ParamDef.h:83
std::string toUTF8String(T const &iValue, Steinberg::int32 iPrecision)
This generic function will determine (at compilation time) whether T can be written to an ostream and...
Definition: Utils.h:50
std::string toUTF8String(ParamValue iNormalizedValue, int32 iPrecision) const override
Return the value as a utf-8 string.
Definition: ParamDef.h:258
ParamValue readFromStream(IBStreamer &iStreamer) const
Definition: ParamDef.h:117
ParamValue readFromState(NormalizedState const &iState) const
Read the value from the (normalized) state.
Definition: ParamDef.h:129
const VstString16 fUnits
Definition: ParamDef.h:163
Used to communicate the state between the UI and the RT and read/write to stream.
Definition: NormalizedState.h:37
const ParamType fDefaultValue
Definition: ParamDef.h:272
T ParamType
Definition: ParamDef.h:179
const int32 fStepCount
Definition: ParamDef.h:165
T ParamType
Definition: ParamDef.h:319
static void staticToString(ParamValue const &iValue, String128 oString, int32 iPrecision)
Definition: ParamConverters.h:94
const ParamValue fDefaultValue
Definition: ParamDef.h:164
const bool fTransient
Definition: ParamDef.h:82
std::basic_string< Steinberg::char16 > VstString16
Strings made of char16 characters are represented by the native C++11 type std::basic_string<Steinber...
Definition: Types.h:43
const VstString16 fTitle
Definition: ParamDef.h:80
IParamDef(ParamID const iParamID, VstString16 iTitle, Owner const iOwner, bool const iTransient, int16 const iDeprecatedSince)
Definition: ParamDef.h:61
bool isDeprecated() const
Returns true if the parameter is deprecated (meaning it can only be used to upgrade to latest version...
Definition: ParamDef.h:76
VstParamDef(ParamID const iParamID, VstString16 iTitle, VstString16 iUnits, ParamType const iDefaultValue, int32 const iFlags, UnitID const iUnitID, VstString16 iShortTitle, int32 const iPrecision, Owner const iOwner, bool const iTransient, int16 const iDeprecatedSince, std::shared_ptr< IParamConverter< ParamType >> iConverter)
Definition: ParamDef.h:181
std::array< JmbParam< T >, N > JmbParams
Definition: ParamDef.h:524
tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const override
This method should read from the stream and populate oValue accordingly (aka deserialization)
Definition: ParamDef.h:419
Interface that defines a converter from a type T to an int32 given a number of steps (provided by get...
Definition: ParamSerializers.h:45
const VstString16 fShortTitle
Definition: ParamDef.h:168
tresult getNormalizedValue(ParamID iParamID, ParamValue &oValue) const
Returns the normalized value for the given param id if it exists.
Definition: NormalizedState.cpp:131
bool const fShared
Definition: ParamDef.h:308
A vst parameter is represented by a ParamValue type which is a double in the range [0,...
Definition: ParamSerializers.h:107
std::string computeMessageAttrID() const
Definition: ParamDef.h:392
IJmbParamDef(const ParamID iParamID, VstString16 iTitle, Owner const iOwner, bool const iTransient, int16 const iDeprecatedSince, bool const iShared)
Definition: ParamDef.h:282
std::array< RawVstParam, N > RawVstParams
Definition: ParamDef.h:515
Base class for all ParamDef.
Definition: ParamDef.h:46
ParamType getDefaultValue() const
Definition: ParamDef.h:223
std::shared_ptr< VstParamDef< T > > VstParam
Definition: ParamDef.h:508
ParamValue normalize(ParamType const &iValue) const
Definition: ParamDef.h:226
virtual void toString(ParamValue iNormalizedValue, String128 iString) const
Definition: ParamDef.h:143
Owner
Who owns the parameter (mostly for state saving purposes)
Definition: ParamDef.h:51
Typed parameter definition.
Definition: ParamDef.h:176
const int32 fPrecision
Definition: ParamDef.h:169
bool isSerializable() const override
Definition: ParamDef.h:408
RawVstParamDef(ParamID const iParamID, VstString16 iTitle, VstString16 iUnits, ParamValue const iDefaultNormalizedValue, int32 const iStepCount, int32 const iFlags, UnitID const iUnitID, VstString16 iShortTitle, int32 const iPrecision, Owner const iOwner, bool const iTransient, int16 const iDeprecatedSince)
Definition: ParamDef.h:93
const UnitID fUnitID
Definition: ParamDef.h:167
std::string toUTF8String(ParamType const &iValue, int32 iPrecision) const
Return the value as a utf-8 string.
Definition: ParamDef.h:359
Definition: Clock.h:23
Base class for all non vst parameters (need to provide serialization/deserialization)
Definition: ParamDef.h:316
JmbParamDef(ParamID const iParamID, VstString16 iTitle, Owner const iOwner, bool const iTransient, int16 const iDeprecatedSince, bool const iShared, ParamType const &iDefaultValue, std::shared_ptr< IParamSerializer< ParamType >> iSerializer)
Definition: ParamDef.h:321
tresult getSerializableValue(IAttributeList::AttrID id, IParamSerializer< T > const &iSerializer, T &oValue) const
Deserializes the parameter value from an entry in the message.
Definition: Messaging.h:169
std::shared_ptr< JmbParamDef< T > > JmbParam
Definition: ParamDef.h:521
std::shared_ptr< IDiscreteConverter< T > > getDiscreteConverter() const
Definition: ParamDef.h:384
Base class for jamba parameters (non templated)
Definition: ParamDef.h:279
constexpr char const * to_string(bool iValue)
Convenient call to convert a boolean into a string.
Definition: StringUtils.h:28
std::string toUT8String(VstString16 const &iString)
Converts a VstString16 to a regular std::string that is properly utf-8 encoded.
Definition: Utils.h:35
A vst parameter is represented by a ParamValue type which is a double in the range [0,...
Definition: ParamConverters.h:53
tresult writeToState(ParamType const &iValue, NormalizedState &oState) const
Writes the provided value to the (normalized) state.
Definition: ParamDef.h:217