Jamba C++ API  5.1.1
ParamSerializers.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 <pongasoft/logging/logging.h>
22 #include <pongasoft/Utils/Misc.h>
24 #include <pluginterfaces/vst/vsttypes.h>
25 #include <base/source/fstreamer.h>
26 #include <string>
27 #include <iostream>
28 #include <memory>
29 #include <sstream>
30 #include <map>
31 #include <vector>
32 
33 namespace pongasoft::VST {
34 
35 using namespace Steinberg;
36 using namespace Steinberg::Vst;
37 
44 template<typename T>
46 {
47 public:
48  virtual int32 getStepCount() const = 0;
49  virtual tresult convertFromDiscreteValue(int32 iDiscreteValue, T &oValue) const = 0;
50  virtual tresult convertToDiscreteValue(T const &iValue, int32 &oDiscreteValue) const = 0;
51 };
52 
62 template<typename T>
64 {
65 public:
66  // Constructor
67  explicit StaticCastDiscreteConverter(int32 iStepCount) : fStepCount(iStepCount)
68  {
69  DCHECK_F(fStepCount > 0);
70  }
71 
72  // getStepCount
73  int32 getStepCount() const override { return fStepCount; }
74 
75  // convertFromDiscreteValue
76  tresult convertFromDiscreteValue(int32 iDiscreteValue, T &oValue) const override
77  {
78  iDiscreteValue = Utils::clamp(iDiscreteValue, Utils::ZERO_INT32, fStepCount);
79  oValue = static_cast<T>(iDiscreteValue);
80  return kResultOk;
81  }
82 
83  // convertToDiscreteValue
84  tresult convertToDiscreteValue(T const &iValue, int32 &oDiscreteValue) const override
85  {
86  oDiscreteValue = static_cast<int32>(iValue);
87  oDiscreteValue = Utils::clamp(oDiscreteValue, Utils::ZERO_INT32, fStepCount);
88  return kResultOk;
89  }
90 
91 protected:
92  int32 fStepCount;
93 };
94 
95 
106 template<typename T>
108 {
109 public:
110  using ParamType = T;
111 
116  virtual tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const { return kNotImplemented; };
117 
122  virtual tresult writeToStream(const ParamType &iValue, IBStreamer &oStreamer) const { return kNotImplemented; };
123 
129  virtual void writeToStream(ParamType const &iValue, std::ostream &oStream) const
130  {
131  if constexpr(Utils::is_operator_write_to_ostream_defined<ParamType>)
132  {
133  oStream << iValue;
134  }
135  }
136 
137  virtual std::string toString(ParamType const &iValue, int32 iPrecision) const
138  {
139  std::ostringstream s;
140  if(iPrecision >= 0)
141  {
142  s.precision(iPrecision);
143  s.setf(std::ios::fixed);
144  }
145  writeToStream(iValue, s);
146  return s.str();
147  }
148 };
149 
153 namespace IBStreamHelper {
154 
155 // readDouble - contrary to IBStreamer.readDouble, this method does NOT modify oValue if cannot be read
156 inline tresult readDouble(IBStreamer &iStreamer, double &oValue)
157 {
158  double value;
159  if(!iStreamer.readDouble(value))
160  return kResultFalse;
161  oValue = value;
162  return kResultOk;
163 }
164 
165 // readFloat - contrary to IBStreamer.readFloat, this method does NOT modify oValue if cannot be read
166 inline tresult readFloat(IBStreamer &iStreamer, float &oValue)
167 {
168  float value;
169  if(!iStreamer.readFloat(value))
170  return kResultFalse;
171  oValue = value;
172  return kResultOk;
173 }
174 
175 // readFloatArray - contrary to IBStreamer.readFloatArray, this method returns tresult and can use any Int type
176 template<typename Int>
177 inline tresult readFloatArray(IBStreamer &iStreamer, float *oValue, Int iCount)
178 {
179  for(Int i = 0; i < iCount; i++)
180  {
181  if(!iStreamer.readFloat(oValue[i]))
182  return kResultFalse;
183  }
184  return kResultOk;
185 }
186 
187 
188 // readInt64 - contrary to IBStreamer.readInt64, this method does NOT modify oValue if cannot be read
189 inline tresult readInt64(IBStreamer &iStreamer, int64 &oValue)
190 {
191  int64 value;
192  if(!iStreamer.readInt64(value))
193  return kResultFalse;
194  oValue = value;
195  return kResultOk;
196 }
197 
198 // readInt64 - contrary to IBStreamer.readInt64, this method does NOT modify oValue if cannot be read
199 inline tresult readInt64u(IBStreamer &iStreamer, uint64 &oValue)
200 {
201  uint64 value;
202  if(!iStreamer.readInt64u(value))
203  return kResultFalse;
204  oValue = value;
205  return kResultOk;
206 }
207 
208 // readInt32 - contrary to IBStreamer.readInt32, this method does NOT modify oValue if cannot be read
209 inline tresult readInt32(IBStreamer &iStreamer, int32 &oValue)
210 {
211  int32 value;
212  if(!iStreamer.readInt32(value))
213  return kResultFalse;
214  oValue = value;
215  return kResultOk;
216 }
217 
218 // readBool - contrary to IBStreamer.readBool, this method does NOT modify oValue if cannot be read
219 inline tresult readBool(IBStreamer &iStreamer, bool &oValue)
220 {
221  bool value;
222  if(!iStreamer.readBool(value))
223  return kResultFalse;
224  oValue = value;
225  return kResultOk;
226 }
227 
228 }
229 
233 class RawParamSerializer : public IParamSerializer<ParamValue>
234 {
235 public:
236  tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const override
237  {
238  return IBStreamHelper::readDouble(iStreamer, oValue);
239  }
240 
241  tresult writeToStream(const ParamType &iValue, IBStreamer &oStreamer) const override
242  {
243  oStreamer.writeDouble(iValue);
244  return kResultOk;
245  }
246 };
247 
252 {
253 public:
254  tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const override
255  {
256  return IBStreamHelper::readDouble(iStreamer, oValue);
257  }
258 
259  tresult writeToStream(const ParamType &iValue, IBStreamer &oStreamer) const override
260  {
261  oStreamer.writeDouble(iValue);
262  return kResultOk;
263  }
264 };
265 
270 {
271 public:
272  tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const override
273  {
274  return IBStreamHelper::readInt32(iStreamer, oValue);
275  }
276 
277  tresult writeToStream(const ParamType &iValue, IBStreamer &oStreamer) const override
278  {
279  oStreamer.writeInt32(iValue);
280  return kResultOk;
281  }
282 };
283 
288 {
289 public:
290  tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const override
291  {
292  return IBStreamHelper::readInt64(iStreamer, oValue);
293  }
294 
295  tresult writeToStream(const ParamType &iValue, IBStreamer &oStreamer) const override
296  {
297  oStreamer.writeInt64(iValue);
298  return kResultOk;
299  }
300 };
301 
306 {
307 public:
308  explicit BooleanParamSerializer(std::string iFalseString = "Off",
309  std::string iTrueString = "On") :
310  fFalseString{std::move(iFalseString)},
311  fTrueString{std::move(iTrueString)}
312  {}
313 
314  tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const override
315  {
316  return IBStreamHelper::readBool(iStreamer, oValue);
317  }
318 
319  tresult writeToStream(const ParamType &iValue, IBStreamer &oStreamer) const override
320  {
321  oStreamer.writeBool(iValue);
322  return kResultOk;
323  }
324 
325  void writeToStream(ParamType const &iValue, std::ostream &oStream) const override
326  {
327  oStream << (iValue ? fTrueString : fFalseString);
328  }
329 
330 private:
331  inline int32 getStepCount() const override { return 1; }
332 
333  tresult convertFromDiscreteValue(int32 iDiscreteValue, bool &oValue) const override
334  {
335  oValue = iDiscreteValue != 0;
336  return kResultOk;
337  }
338 
339  tresult convertToDiscreteValue(const bool &iValue, int32 &oDiscreteValue) const override
340  {
341  oDiscreteValue = iValue ? 1 : 0;
342  return kResultOk;
343  }
344 
345 protected:
346  std::string fFalseString;
347  std::string fTrueString;
348 };
349 
350 
356 template<int size = 128>
357 class CStringParamSerializer : public IParamSerializer<char[size]>
358 {
359 public:
360  using ParamType = char[size];
361 
362  // readFromStream
363  inline tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const override
364  {
365  if(iStreamer.readRaw(static_cast<void*>(oValue), size) == size)
366  {
367  oValue[size - 1] = 0; // making sure it is null terminated
368  return kResultOk;
369  }
370  else
371  return kResultFalse;
372  }
373 
374  // writeToStream - IBStreamer
375  inline tresult writeToStream(const ParamType &iValue, IBStreamer &oStreamer) const override
376  {
377  if(oStreamer.writeRaw(static_cast<void const *>(iValue), size) == size)
378  return kResultOk;
379  else
380  return kResultFalse;
381  }
382 
383  // writeToStream - std::ostream
384  void writeToStream(ParamType const &iValue, std::ostream &oStream) const override
385  {
386  if(std::find(std::begin(iValue), std::end(iValue), 0) != std::end(iValue))
387  {
388  // this means that the string is null terminated... we are good
389  oStream << iValue;
390  }
391  else
392  {
393  char8 str[size];
394  std::copy(std::begin(iValue), std::end(iValue), std::begin(str));
395  str[size - 1] = 0; // make the copy null terminated
396  oStream << str;
397  DLOG_F(WARNING, "%s not properly null terminated!", str);
398  }
399  }
400 };
401 
429 template<typename T, class Compare = std::less<T>>
431 {
432 public:
435  using TMap = std::map<T, std::pair<std::string, int32>, Compare>;
436 
439  using TList = std::vector<T>;
440 
443  using ConstructorType = std::initializer_list<std::pair<const T, std::string>> const &;
444 
445  using ParamType = T;
446 
447  // DiscreteTypeParamSerializer
449  {
450 #ifndef NDEBUG
451  // by definition, a discrete parameter has a step count > 0
452  auto stepCount = static_cast<int32>(iInitList.size() - 1);
453  DCHECK_F(stepCount > 0);
454 #endif
455 
456  int32 i = 0;
457  for(auto &pair : iInitList)
458  {
459  fMap[pair.first] = std::make_pair(pair.second, i);
460  fList.emplace_back(pair.first);
461  i++;
462  }
463 
464  // sanity check... if not the same size it means that 2 entries in the list were the same!
465  DCHECK_F(fList.size() == fMap.size());
466  }
467 
468  // getStepCount
469  inline int32 getStepCount() const override { return static_cast<int32>(fMap.size() - 1); }
470 
471  // convertFromDiscreteValue
472  tresult convertFromDiscreteValue(int32 iDiscreteValue, ParamType &oValue) const override
473  {
474  if(iDiscreteValue < 0 || iDiscreteValue > getStepCount())
475  return kResultFalse;
476  oValue = fList[iDiscreteValue];
477  return kResultOk;
478  }
479 
480  // convertToDiscreteValue
481  tresult convertToDiscreteValue(ParamType const &iValue, int32 &oDiscreteValue) const override
482  {
483  auto iter = fMap.find(iValue);
484  if(iter != fMap.cend())
485  {
486  oDiscreteValue = std::get<1>(iter->second);
487  return kResultOk;
488  }
489  else
490  {
491  DLOG_F(WARNING, "could not convertToDiscreteValue...");
492  return kResultFalse;
493  }
494  }
495 
496  // readFromStream
497  tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const override
498  {
499  int32 discreteValue;
500  if(IBStreamHelper::readInt32(iStreamer, discreteValue) == kResultOk)
501  {
502  return convertFromDiscreteValue(discreteValue, oValue);
503  }
504  return kResultFalse;
505  }
506 
507  // writeToStream
508  tresult writeToStream(const ParamType &iValue, IBStreamer &oStreamer) const override
509  {
510  int32 discreteValue;
511  if(convertToDiscreteValue(iValue, discreteValue) == kResultOk)
512  {
513  if(oStreamer.writeInt32(discreteValue))
514  return kResultOk;
515  }
516 
517  return kResultFalse;
518  }
519 
520  // writeToStream
521  void writeToStream(ParamType const &iValue, std::ostream &oStream) const override
522  {
523  auto iter = fMap.find(iValue);
524  if(iter != fMap.cend())
525  {
526  oStream << std::get<0>(iter->second);
527  }
528  }
529 
530 private:
531  TMap fMap{};
532  TList fList{};
533 };
534 
535 }
This parameter handles serializing a double parameter.
Definition: ParamSerializers.h:251
tresult readDouble(IBStreamer &iStreamer, double &oValue)
Definition: ParamSerializers.h:156
tresult readFloat(IBStreamer &iStreamer, float &oValue)
Definition: ParamSerializers.h:166
static T clamp(const U &iValue, const T &iLower, const T &iUpper)
Make sure that the value remains within its bounds.
Definition: Misc.h:33
This parameter handles serializing a int64 parameter.
Definition: ParamSerializers.h:287
tresult convertToDiscreteValue(T const &iValue, int32 &oDiscreteValue) const override
Definition: ParamSerializers.h:84
tresult readInt64u(IBStreamer &iStreamer, uint64 &oValue)
Definition: ParamSerializers.h:199
tresult writeToStream(const ParamType &iValue, IBStreamer &oStreamer) const override
Definition: ParamSerializers.h:375
char[size] ParamType
Definition: ParamSerializers.h:360
std::initializer_list< std::pair< const T, std::string > > const & ConstructorType
Defines the type for the constructor argument.
Definition: ParamSerializers.h:443
This parameter handles serializing a bool parameter.
Definition: ParamSerializers.h:305
constexpr auto ZERO_INT32
Definition: Constants.h:24
This parameter handles serializing a raw parameter (ParamValue)
Definition: ParamSerializers.h:233
int32 getStepCount() const override
Definition: ParamSerializers.h:469
tresult writeToStream(const ParamType &iValue, IBStreamer &oStreamer) const override
This method should write iValue to the stream (aka serialization)
Definition: ParamSerializers.h:259
tresult convertFromDiscreteValue(int32 iDiscreteValue, T &oValue) const override
Definition: ParamSerializers.h:76
tresult convertFromDiscreteValue(int32 iDiscreteValue, bool &oValue) const override
Definition: ParamSerializers.h:333
std::vector< T > TList
Defines the mapping: discrete value [0, stepCount] to T.
Definition: ParamSerializers.h:439
tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const override
This method should read from the stream and populate oValue accordingly (aka deserialization)
Definition: ParamSerializers.h:272
tresult readInt32(IBStreamer &iStreamer, int32 &oValue)
Definition: ParamSerializers.h:209
virtual tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const
This method should read from the stream and populate oValue accordingly (aka deserialization)
Definition: ParamSerializers.h:116
DiscreteTypeParamSerializer(ConstructorType iInitList)
Definition: ParamSerializers.h:448
tresult convertToDiscreteValue(ParamType const &iValue, int32 &oDiscreteValue) const override
Definition: ParamSerializers.h:481
tresult writeToStream(const ParamType &iValue, IBStreamer &oStreamer) const override
This method should write iValue to the stream (aka serialization)
Definition: ParamSerializers.h:277
tresult readFloatArray(IBStreamer &iStreamer, float *oValue, Int iCount)
Definition: ParamSerializers.h:177
tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const override
This method should read from the stream and populate oValue accordingly (aka deserialization)
Definition: ParamSerializers.h:314
tresult convertFromDiscreteValue(int32 iDiscreteValue, ParamType &oValue) const override
Definition: ParamSerializers.h:472
tresult writeToStream(const ParamType &iValue, IBStreamer &oStreamer) const override
This method should write iValue to the stream (aka serialization)
Definition: ParamSerializers.h:295
tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const override
Definition: ParamSerializers.h:363
int32 fStepCount
Definition: ParamSerializers.h:92
virtual tresult writeToStream(const ParamType &iValue, IBStreamer &oStreamer) const
This method should write iValue to the stream (aka serialization)
Definition: ParamSerializers.h:122
A parameter backed by a C type string (char[size]).
Definition: ParamSerializers.h:357
void writeToStream(ParamType const &iValue, std::ostream &oStream) const override
By default, this implementation simply writes the value to the stream IF it is possible (determined a...
Definition: ParamSerializers.h:325
tresult readBool(IBStreamer &iStreamer, bool &oValue)
Definition: ParamSerializers.h:219
std::map< T, std::pair< std::string, int32 >, Compare > TMap
Maintains the map of possible values of T (defined in constructor)
Definition: ParamSerializers.h:435
tresult writeToStream(const ParamType &iValue, IBStreamer &oStreamer) const override
This method should write iValue to the stream (aka serialization)
Definition: ParamSerializers.h:241
tresult writeToStream(const ParamType &iValue, IBStreamer &oStreamer) const override
This method should write iValue to the stream (aka serialization)
Definition: ParamSerializers.h:319
Interface that defines a converter from a type T to an int32 given a number of steps (provided by get...
Definition: ParamSerializers.h:45
std::string fFalseString
Definition: ParamSerializers.h:346
BooleanParamSerializer(std::string iFalseString="Off", std::string iTrueString="On")
Definition: ParamSerializers.h:308
void writeToStream(ParamType const &iValue, std::ostream &oStream) const override
Definition: ParamSerializers.h:384
A vst parameter is represented by a ParamValue type which is a double in the range [0,...
Definition: ParamSerializers.h:107
This parameter handles serializing a int32 parameter.
Definition: ParamSerializers.h:269
virtual std::string toString(ParamType const &iValue, int32 iPrecision) const
Definition: ParamSerializers.h:137
tresult convertToDiscreteValue(const bool &iValue, int32 &oDiscreteValue) const override
Definition: ParamSerializers.h:339
This converters maps a list of values of type T to discrete values.
Definition: ParamSerializers.h:430
tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const override
This method should read from the stream and populate oValue accordingly (aka deserialization)
Definition: ParamSerializers.h:236
virtual void writeToStream(ParamType const &iValue, std::ostream &oStream) const
By default, this implementation simply writes the value to the stream IF it is possible (determined a...
Definition: ParamSerializers.h:129
int32 getStepCount() const override
Definition: ParamSerializers.h:331
tresult readInt64(IBStreamer &iStreamer, int64 &oValue)
Definition: ParamSerializers.h:189
Definition: Clock.h:23
tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const override
This method should read from the stream and populate oValue accordingly (aka deserialization)
Definition: ParamSerializers.h:290
tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const override
This method should read from the stream and populate oValue accordingly (aka deserialization)
Definition: ParamSerializers.h:254
tresult writeToStream(const ParamType &iValue, IBStreamer &oStreamer) const override
This method should write iValue to the stream (aka serialization)
Definition: ParamSerializers.h:508
int32 getStepCount() const override
Definition: ParamSerializers.h:73
void writeToStream(ParamType const &iValue, std::ostream &oStream) const override
By default, this implementation simply writes the value to the stream IF it is possible (determined a...
Definition: ParamSerializers.h:521
ParamValue ParamType
Definition: ParamSerializers.h:110
This implementation simply cast T to an int32 (and vice-versa).
Definition: ParamSerializers.h:63
StaticCastDiscreteConverter(int32 iStepCount)
Definition: ParamSerializers.h:67
std::string fTrueString
Definition: ParamSerializers.h:347
tresult readFromStream(IBStreamer &iStreamer, ParamType &oValue) const override
This method should read from the stream and populate oValue accordingly (aka deserialization)
Definition: ParamSerializers.h:497