Jamba C++ API  4.1.0
ParamDef.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2019 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 
24 #include <base/source/fstreamer.h>
25 #include <pluginterfaces/vst/vsttypes.h>
26 #include <pluginterfaces/vst/ivsteditcontroller.h>
27 #include <pluginterfaces/vst/ivstunits.h>
28 
29 #include <string>
30 #include <memory>
31 
32 namespace pongasoft::VST {
33 
34 using namespace Steinberg;
35 using namespace Steinberg::Vst;
36 
37 // forward declaration required for API
38 namespace GUI::Params {
39 class IGUIJmbParameter;
40 }
41 
45 class IParamDef : public std::enable_shared_from_this<IParamDef>
46 {
47 public:
48  enum class Owner
49  {
50  kRT,
51  kGUI
52  };
53 public:
54  IParamDef(ParamID const iParamID,
55  VstString16 iTitle,
56  Owner const iOwner,
57  bool const iTransient) :
58  fParamID{iParamID},
59  fTitle{std::move(iTitle)},
60  fOwner{iOwner},
61  fTransient{iTransient}
62  {}
63 
64  virtual ~IParamDef() = default;
65 
66 public:
67  const ParamID fParamID;
69  const Owner fOwner; // who owns the parameter (and which stream will it be saved if non transient)
70  const bool fTransient; // not saved in the stream
71 };
72 
73 
77 class RawVstParamDef : public IParamDef
78 {
79 public:
80  RawVstParamDef(ParamID const iParamID,
81  VstString16 iTitle,
82  VstString16 iUnits,
83  ParamValue const iDefaultNormalizedValue,
84  int32 const iStepCount,
85  int32 const iFlags,
86  UnitID const iUnitID,
87  VstString16 iShortTitle,
88  int32 const iPrecision,
89  Owner const iOwner,
90  bool const iTransient) :
91  IParamDef(iParamID, std::move(iTitle), iOwner, iTransient),
92  fUnits{std::move(iUnits)},
93  fDefaultValue{Utils::clampE(iDefaultNormalizedValue, 0.0, 1.0)},
94  fStepCount{iStepCount},
95  fFlags{iFlags},
96  fUnitID{iUnitID},
97  fShortTitle{std::move(iShortTitle)},
98  fPrecision{iPrecision}
99  {}
100 
101 public:
102  // readFromStream
103  ParamValue readFromStream(IBStreamer &iStreamer) const
104  {
105  ParamValue res = fDefaultValue;
106 
107  ParamValue value;
108  if(IBStreamHelper::readDouble(iStreamer, value) == kResultOk)
109  res = value;
110 
111  return res;
112  }
113 
114  // toString
115  virtual void toString(ParamValue iNormalizedValue, String128 iString) const
116  {
117  RawParamConverter::staticToString(iNormalizedValue, iString, fPrecision);
118  }
119 
126  virtual std::string toUTF8String(ParamValue iNormalizedValue, int32 iPrecision) const
127  {
128  String128 s;
129  s[0] = 0;
130  RawParamConverter::staticToString(iNormalizedValue, s, iPrecision >= 0 ? iPrecision : fPrecision);
131  return VstUtils::toUT8String(s);
132  }
133 
134 public:
136  const ParamValue fDefaultValue;
137  const int32 fStepCount;
138  const int32 fFlags;
139  const UnitID fUnitID;
141  const int32 fPrecision;
142 };
143 
147 template<typename T>
149 {
150 public:
151  using ParamType = T;
152 
153  VstParamDef(ParamID const iParamID,
154  VstString16 iTitle,
155  VstString16 iUnits,
156  ParamType const iDefaultValue,
157  int32 const iFlags,
158  UnitID const iUnitID,
159  VstString16 iShortTitle,
160  int32 const iPrecision,
161  Owner const iOwner,
162  bool const iTransient,
163  std::shared_ptr<IParamConverter<ParamType>> iConverter) :
164  RawVstParamDef(iParamID,
165  std::move(iTitle),
166  std::move(iUnits),
167  iConverter ? iConverter->normalize(iDefaultValue) : 0,
168  iConverter ? iConverter->getStepCount() : 0,
169  iFlags,
170  iUnitID,
171  std::move(iShortTitle),
172  iPrecision,
173  iOwner,
174  iTransient),
175  fDefaultValue{iDefaultValue},
176  fConverter{std::move(iConverter)}
177  {
178  }
179 
180  // getDefaultValue
181  ParamType getDefaultValue() const { return fDefaultValue; }
182 
183  // shortcut to normalize
184  inline ParamValue normalize(ParamType const &iValue) const
185  {
186  if(fConverter)
187  return fConverter->normalize(iValue);
188  return 0;
189  }
190 
191  // shortcut to denormalize
192  inline ParamType denormalize(ParamValue iNormalizedValue) const
193  {
194  if(fConverter)
195  return fConverter->denormalize(iNormalizedValue);
196  return fDefaultValue;
197  }
198 
202  void toString(ParamValue iNormalizedValue, String128 iString) const override
203  {
204  if(fConverter)
205  fConverter->toString(fConverter->denormalize(iNormalizedValue), iString, fPrecision);
206  else
207  RawVstParamDef::toString(iNormalizedValue, iString);
208  }
209 
216  std::string toUTF8String(ParamValue iNormalizedValue, int32 iPrecision) const override
217  {
218  if(fConverter)
219  {
220  String128 s;
221  s[0] = 0;
222  fConverter->toString(fConverter->denormalize(iNormalizedValue), s, iPrecision >= 0 ? iPrecision : fPrecision);
223  return VstUtils::toUT8String(s);
224  }
225  else
226  return RawVstParamDef::toUTF8String(iNormalizedValue, iPrecision);
227  }
228 
229 public:
231  const std::shared_ptr<IParamConverter<ParamType>> fConverter;
232 };
233 
237 class IJmbParamDef : public IParamDef
238 {
239 public:
240  IJmbParamDef(const ParamID iParamID,
241  VstString16 iTitle,
242  Owner const iOwner,
243  bool const iTransient,
244  bool const iShared)
245  : IParamDef(iParamID, std::move(iTitle), iOwner, iTransient),
246  fShared{iShared}
247  {}
248 
249  ~IJmbParamDef() override = default;
250 
251  // writeDefaultValue
252  virtual void writeDefaultValue(std::ostream &oStreamer) const = 0;
253 
257  virtual std::shared_ptr<GUI::Params::IGUIJmbParameter> newGUIParam() = 0;
258 
262  virtual bool isSerializable() const = 0;
263 
264 public:
265  bool const fShared;
266 };
267 
272 template<typename T>
274 {
275 public:
276  using ParamType = T;
277 
278  JmbParamDef(ParamID const iParamID,
279  VstString16 iTitle,
280  Owner const iOwner,
281  bool const iTransient,
282  bool const iShared,
283  ParamType const &iDefaultValue,
284  std::shared_ptr<IParamSerializer<ParamType>> iSerializer) :
285  IJmbParamDef(iParamID, std::move(iTitle), iOwner, iTransient, iShared),
286  fDefaultValue{iDefaultValue},
287  fSerializer{std::move(iSerializer)}
288  {}
289 
290  // readFromStream
291  tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const override;
292  ParamType readFromStream(IBStreamer &iStreamer) const;
293 
294  // writeToStream
295  tresult writeToStream(ParamType const &iValue, IBStreamer &oStreamer) const override;
296 
297  // writeToStream
298  void writeToStream(ParamType const &iValue, std::ostream &oStreamer) const override;
299 
300  // writeDefaultValue
301  void writeDefaultValue(std::ostream &oStreamer) const override;
302 
303  // readFromMessage
304  tresult readFromMessage(Message const &iMessage, ParamType &oValue) const;
305 
306  // writeToMessage
307  tresult writeToMessage(ParamType const &iValue, Message &oMessage) const;
308 
315  std::string toUTF8String(ParamType const &iValue, int32 iPrecision) const
316  {
317  if(fSerializer)
318  return fSerializer->toString(iValue, iPrecision);
319  else
320  {
321  if constexpr(Utils::is_operator_write_to_ostream_defined<ParamType>)
322  {
323  std::ostringstream s;
324  if(iPrecision >= 0)
325  {
326  s.precision(iPrecision);
327  s.setf(std::ios::fixed);
328  }
329  s << iValue;
330  return s.str();
331  }
332  }
333  return "";
334  }
335 
339  std::shared_ptr<IDiscreteConverter<T>> getDiscreteConverter() const
340  {
341  // Implementation note: at this moment, only checks if the serializer also implements the API.
342  // But possible to add an additional separate field to set it explicitly if there is a need
343  return std::dynamic_pointer_cast<IDiscreteConverter<T>>(fSerializer);
344  }
345 
346  // computeMessageAttrID
347  std::string computeMessageAttrID() const
348  {
349  return "__param__" + std::to_string(fParamID);
350  }
351 
358  std::shared_ptr<GUI::Params::IGUIJmbParameter> newGUIParam() override;
359 
363  bool isSerializable() const override { return fSerializer != nullptr; }
364 
365 public:
367  const std::shared_ptr<IParamSerializer<ParamType>> fSerializer;
368 };
369 
370 //------------------------------------------------------------------------
371 // JmbParamDef::readFromStream
372 //------------------------------------------------------------------------
373 template<typename T>
374 tresult JmbParamDef<T>::readFromStream(IBStreamer &iStreamer, T &oValue) const
375 {
376  if(fSerializer)
377  {
378  return fSerializer->readFromStream(iStreamer, oValue);
379  }
380  else
381  return kResultFalse;
382 }
383 
384 //------------------------------------------------------------------------
385 // JmbParamDef::readFromStream
386 //------------------------------------------------------------------------
387 template<typename T>
388 T JmbParamDef<T>::readFromStream(IBStreamer &iStreamer) const
389 {
390  T value;
391  if(readFromStream(iStreamer, value) != kResultOk)
392  value = fDefaultValue;
393  return value;
394 }
395 
396 
397 //------------------------------------------------------------------------
398 // JmbParamDef::writeToStream
399 //------------------------------------------------------------------------
400 template<typename T>
401 tresult JmbParamDef<T>::writeToStream(const T &iValue, IBStreamer &oStreamer) const
402 {
403  if(fSerializer)
404  return fSerializer->writeToStream(iValue, oStreamer);
405  else
406  return kResultFalse;
407 }
408 
409 //------------------------------------------------------------------------
410 // JmbParamDef::writeToStream
411 //------------------------------------------------------------------------
412 template<typename T>
413 void JmbParamDef<T>::writeToStream(const ParamType &iValue, std::ostream &oStreamer) const
414 {
415  if(fSerializer)
416  fSerializer->writeToStream(iValue, oStreamer);
417 }
418 
419 //------------------------------------------------------------------------
420 // JmbParamDef::writeDefaultValue
421 //------------------------------------------------------------------------
422 template<typename T>
423 void JmbParamDef<T>::writeDefaultValue(std::ostream &oStreamer) const
424 {
425  writeToStream(fDefaultValue, oStreamer);
426 }
427 
428 //------------------------------------------------------------------------
429 // JmbParamDef::readFromMessage
430 //------------------------------------------------------------------------
431 template<typename T>
432 tresult JmbParamDef<T>::readFromMessage(Message const &iMessage, ParamType &oValue) const
433 {
434  if(fSerializer)
435  return iMessage.getSerializableValue(computeMessageAttrID().c_str(), *this, oValue);
436  else
437  return kResultFalse;
438 }
439 
440 //------------------------------------------------------------------------
441 // JmbParamDef::writeToMessage
442 //------------------------------------------------------------------------
443 template<typename T>
444 tresult JmbParamDef<T>::writeToMessage(const ParamType &iValue, Message &oMessage) const
445 {
446  if(fSerializer)
447  return oMessage.setSerializableValue(computeMessageAttrID().c_str(), *this, iValue);
448  else
449  return kResultFalse;
450 }
451 
452 //------------------------------------------------------------------------
453 // VstParam - define shortcut notation
454 //------------------------------------------------------------------------
455 template<typename T>
456 using VstParam = std::shared_ptr<VstParamDef<T>>;
457 using RawVstParam = std::shared_ptr<RawVstParamDef>;
458 
459 //------------------------------------------------------------------------
460 // JmbParam - define shortcut notation
461 //------------------------------------------------------------------------
462 template<typename T>
463 using JmbParam = std::shared_ptr<JmbParamDef<T>>;
464 
465 }
tresult readDouble(IBStreamer &iStreamer, double &oValue)
Definition: ParamSerializers.h:144
const std::shared_ptr< IParamConverter< ParamType > > fConverter
Definition: ParamDef.h:231
const ParamType fDefaultValue
Definition: ParamDef.h:366
virtual std::string toUTF8String(ParamValue iNormalizedValue, int32 iPrecision) const
Return the value as a utf-8 string.
Definition: ParamDef.h:126
void toString(ParamValue iNormalizedValue, String128 iString) const override
Using fConverter::toString
Definition: ParamDef.h:202
const std::shared_ptr< IParamSerializer< ParamType > > fSerializer
Definition: ParamDef.h:367
tresult writeToStream(ParamType const &iValue, IBStreamer &oStreamer) const override
Definition: ParamDef.h:401
Base class for a raw vst parameter definition.
Definition: ParamDef.h:77
const Owner fOwner
Definition: ParamDef.h:69
Simple wrapper class with better api.
Definition: Messaging.h:42
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:67
ParamType denormalize(ParamValue iNormalizedValue) const
Definition: ParamDef.h:192
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:163
const int32 fFlags
Definition: ParamDef.h:138
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)
Definition: ParamDef.h:80
std::shared_ptr< RawVstParamDef > RawVstParam
Definition: ParamDef.h:457
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:49
std::string toUTF8String(ParamValue iNormalizedValue, int32 iPrecision) const override
Return the value as a utf-8 string.
Definition: ParamDef.h:216
ParamValue readFromStream(IBStreamer &iStreamer) const
Definition: ParamDef.h:103
const VstString16 fUnits
Definition: ParamDef.h:135
const ParamType fDefaultValue
Definition: ParamDef.h:230
T ParamType
Definition: ParamDef.h:151
const int32 fStepCount
Definition: ParamDef.h:137
T ParamType
Definition: ParamDef.h:276
static void staticToString(ParamValue const &iValue, String128 oString, int32 iPrecision)
Definition: ParamConverters.h:94
const ParamValue fDefaultValue
Definition: ParamDef.h:136
IJmbParamDef(const ParamID iParamID, VstString16 iTitle, Owner const iOwner, bool const iTransient, bool const iShared)
Definition: ParamDef.h:240
const bool fTransient
Definition: ParamDef.h:70
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
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, std::shared_ptr< IParamConverter< ParamType >> iConverter)
Definition: ParamDef.h:153
const VstString16 fTitle
Definition: ParamDef.h:68
tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const override
Definition: ParamDef.h:374
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:140
bool const fShared
Definition: ParamDef.h:265
A vst parameter is represented by a ParamValue type which is a double in the range [0,...
Definition: ParamSerializers.h:105
JmbParamDef(ParamID const iParamID, VstString16 iTitle, Owner const iOwner, bool const iTransient, bool const iShared, ParamType const &iDefaultValue, std::shared_ptr< IParamSerializer< ParamType >> iSerializer)
Definition: ParamDef.h:278
std::string computeMessageAttrID() const
Definition: ParamDef.h:347
Base class for all ParamDef.
Definition: ParamDef.h:45
ParamType getDefaultValue() const
Definition: ParamDef.h:181
std::shared_ptr< VstParamDef< T > > VstParam
Definition: ParamDef.h:456
ParamValue normalize(ParamType const &iValue) const
Definition: ParamDef.h:184
virtual void toString(ParamValue iNormalizedValue, String128 iString) const
Definition: ParamDef.h:115
Owner
Definition: ParamDef.h:48
Typed parameter definition.
Definition: ParamDef.h:148
const int32 fPrecision
Definition: ParamDef.h:141
IParamDef(ParamID const iParamID, VstString16 iTitle, Owner const iOwner, bool const iTransient)
Definition: ParamDef.h:54
bool isSerializable() const override
Definition: ParamDef.h:363
const UnitID fUnitID
Definition: ParamDef.h:139
std::string toUTF8String(ParamType const &iValue, int32 iPrecision) const
Return the value as a utf-8 string.
Definition: ParamDef.h:315
Definition: Clock.h:23
Base class for all non vst parameters (need to provide serialization/deserialization)
Definition: ParamDef.h:273
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:182
std::shared_ptr< JmbParamDef< T > > JmbParam
Definition: ParamDef.h:463
std::shared_ptr< IDiscreteConverter< T > > getDiscreteConverter() const
Definition: ParamDef.h:339
Base class for jamba parameters (non templated)
Definition: ParamDef.h:237
std::string toUT8String(VstString16 const &iString)
Converts a VstString16 to a regular std::string that is properly utf-8 encoded.
Definition: Utils.h:34
A vst parameter is represented by a ParamValue type which is a double in the range [0,...
Definition: ParamConverters.h:53