File: ShuttleAutomation.h

package info (click to toggle)
audacity 3.7.7%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 134,800 kB
  • sloc: cpp: 366,277; ansic: 198,323; lisp: 7,761; sh: 3,414; python: 1,501; xml: 1,385; perl: 854; makefile: 125
file content (337 lines) | stat: -rw-r--r-- 14,215 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
/**********************************************************************

  Audacity: A Digital Audio Editor

  @file ShuttleAutomation.h

  Paul Licameli split from SettingsVisitor.h

**********************************************************************/

#ifndef __AUDACITY_SHUTTLE_AUTOMATION__
#define __AUDACITY_SHUTTLE_AUTOMATION__

#include <type_traits>
#include "EffectInterface.h"
#include "SettingsVisitor.h"

class Effect;
//! Interface for manipulations of an Effect's settings
/*!
 It is meant to be stateless, so all member functions are const
 */
class COMMAND_PARAMETERS_API EffectParameterMethods {
public:
   virtual ~EffectParameterMethods();
   virtual void Reset(Effect &effect) const = 0;
   virtual void Visit(Effect &effect,
      SettingsVisitor &visitor, EffectSettings &settings) const = 0;
   virtual void Visit(const Effect &effect,
      ConstSettingsVisitor &visitor, const EffectSettings &settings) const = 0;
   virtual void Get(const Effect &effect, const EffectSettings &settings,
      CommandParameters & parms) const = 0;
   virtual bool Set(Effect &effect,
      const CommandParameters & parms, EffectSettings &settings) const = 0;
};

//! Generates EffectParameterMethods overrides from variadic template arguments.
/*!
For each effect parameter, the function...
   Reset resets it to a default
   Visit visits it with a SettingsVisitor object; there are overloads taking
      SettingsVisitor and ConstSettingsVisitor
   Get serializes it to a string
   Set deserializes it from a string and returns a success flag (if there is
      failure, parameters might not all be unchanged)

The constructor optionally takes an argument which is a function to be called at
the end of Reset or Set, and returning a value for Set.

 @tparam EffectType subclass of Effect,
    expected to define a public static member function FetchParameters,
    taking EffectType & and EffectSettings &,
    and returning a pointer to something that holds the parameters
 @tparam Parameters a pack of non-type template parameters, whose types are
    specializations of the class template EffectParameter

 TODO in C++20: could use simply `auto ...Parameters` if they are `constexpr`
*/
template <typename EffectType, const auto &...Parameters>
class CapturedParameters : public EffectParameterMethods {
public:
   using Params = std::remove_pointer_t< decltype(
      // When all effects become stateless, EffectType argument won't be needed
      EffectType::FetchParameters(
         std::declval<EffectType&>(), std::declval<EffectSettings &>())
   ) >;

   virtual ~CapturedParameters() = default;

   // Another helper type
   // boolean argument is true if updating (not resetting defaults)
   // Returns true if successful, but that is ignored when resetting
   // When all effects become stateless, EffectType argument won't be needed
   using PostSetFunction =
      std::function< bool(EffectType&, EffectSettings &, Params &, bool) >;

   // Constructors

   CapturedParameters() {}

   template< typename Fn,
      // Require that the argument be callable with appropriate arguments
      typename = decltype( std::declval<Fn>()(
         std::declval<EffectType &>(), std::declval<EffectSettings &>(),
         std::declval<Params &>(), true) )
   >
   // Like the previous, but with an argument,
   // which is called at the end of Reset or Set.  Its return value is
   // ignored in Reset() and passed as the result of Set.
   explicit CapturedParameters(Fn &&PostSet)
      : PostSetFn{ std::forward<Fn>(PostSet) }
   {}

   void Reset(Effect &effect) const override {
      EffectSettings dummy;
      if (auto pStruct = EffectType::FetchParameters(
         static_cast<EffectType&>(effect), dummy))
         DoReset(effect, dummy, *pStruct, *this);
   }
   void Visit(Effect &effect,
      SettingsVisitor &visitor, EffectSettings &settings)
      const override {
      if (auto pStruct = EffectType::FetchParameters(
         static_cast<EffectType&>(effect), settings))
         DoVisit<false>(*pStruct, visitor);
   }
   void Visit(const Effect &effect,
      ConstSettingsVisitor &visitor, const EffectSettings &settings)
      const override {
      // const_cast the effect...
      auto &nonconstEffect = const_cast<Effect&>(effect);
      // ... and the settings ...
      auto &nonconstSettings = const_cast<EffectSettings&>(settings);
      // ... but only to fetch the structure and pass it as const &
      if (auto pStruct = EffectType::FetchParameters(
         static_cast<EffectType&>(nonconstEffect), nonconstSettings))
         DoVisit(*pStruct, visitor);
   }
   void Get(const Effect &effect, const EffectSettings &settings,
      CommandParameters & parms) const override {
      // const_cast the effect...
      auto &nonconstEffect = const_cast<Effect &>(effect);
      // ... and the settings ...
      auto &nonconstSettings = const_cast<EffectSettings&>(settings);
      // ... but only to fetch the structure and pass it as const &
      if (auto pStruct = EffectType::FetchParameters(
         static_cast<EffectType&>(nonconstEffect), nonconstSettings))
         DoGet(*pStruct, parms);
   }
   bool Set(Effect &effect, const CommandParameters & parms,
      EffectSettings &settings) const override {
      if (auto pStruct = EffectType::FetchParameters(
         static_cast<EffectType&>(effect), settings))
         return DoSet(effect, settings, *pStruct, *this, parms);
      else
         return false;
   }

private:
   PostSetFunction PostSetFn;

   // Function templates.  There are functions to treat individual parameters,
   // sometimes with two overloads, and variadic functions that use
   // fold expressions that apply to the sequence of parameters.

   template< typename Member, typename Type, typename Value >
   static void ResetOne(Params &structure,
      const EffectParameter< Params, Member, Type, Value > &param) {
      // Do one assignment of the default value
      structure.*(param.mem) = param.def;
   }
   static void DoReset(Effect &effect, EffectSettings settings,
      Params &structure,
      const CapturedParameters &This) {
      (ResetOne(structure, Parameters), ...);
      // Call the post-set function after all other assignments
      if (This.PostSetFn)
         This.PostSetFn(
            static_cast<EffectType&>(effect), settings, structure, false);
   }

   template< bool Const, typename Member, typename Type, typename Value >
   static void VisitOne(Params &structure, SettingsVisitorBase<Const> &visitor,
      const EffectParameter< Params, Member, Type, Value > &param) {
      // Visit one variable
      visitor.Define( structure.*(param.mem), param.key,
         static_cast<Member>(param.def),
         static_cast<Member>(param.min),
         static_cast<Member>(param.max),
         static_cast<Member>(param.scale) );
   }
   // More specific overload for enumeration parameters
   template< bool Const, typename Member >
   static void VisitOne(Params &structure, SettingsVisitorBase<Const> &visitor,
      const EnumParameter<Params, Member> &param) {
      // Visit one enumeration variable, passing the table of names
      visitor.DefineEnum( structure.*(param.mem),
         param.key, param.def, param.symbols, param.nSymbols );
   }
   template<bool Const>
   static void DoVisit(Params &structure, SettingsVisitorBase<Const> &visitor) {
      (VisitOne<Const>(structure, visitor, Parameters), ...);
   }

   template< typename Member, typename Type, typename Value >
   static void GetOne(const Params &structure, CommandParameters & parms,
      const EffectParameter< Params, Member, Type, Value > &param) {
      // Serialize one variable
      parms.Write( param.key, static_cast<Value>(structure.*(param.mem)) );
   }
   // More specific overload for enumeration parameters
   template< typename Member >
   static void GetOne(const Params &structure, CommandParameters & parms,
      const EnumParameter<Params, Member> &param) {
      // Serialize one enumeration variable as a string identifier, not a number
      parms.Write(
         param.key, param.symbols[ structure.*(param.mem) ].Internal() );
   }
   static void DoGet(const Params &structure, CommandParameters &parms) {
      (GetOne(structure, parms, Parameters), ...);
   }

   template< typename Member, typename Type, typename Value >
   static bool SetOne(Params &structure,
      const CommandParameters &parms,
      const EffectParameter< Params, Member, Type, Value > &param) {
      // Deserialize and assign one variable (or fail)
      Value temp;
      if (!parms.ReadAndVerify(param.key, &temp, param.def,
         param.min, param.max))
         return false;
      structure.*(param.mem) = temp;
      return true;
   }
   // More specific overload for enumeration parameters
   template< typename Member >
   static bool SetOne(Params &structure,
      const CommandParameters &parms,
      const EnumParameter<Params, Member> &param) {
      // Deserialize and assign one enumeration variable (or fail)
      int temp;
      if (!parms.ReadAndVerify(param.key, &temp, param.def,
         param.symbols, param.nSymbols))
         return false;
      structure.*(param.mem) = temp;
      return true;
   }
   static bool DoSet(Effect &effect,
      EffectSettings &settings, Params &structure,
      const CapturedParameters &This, const CommandParameters &parms) {
      if (!(SetOne(structure, parms, Parameters) && ...))
         return false;
      // Call the post-set function after all other assignments, or return
      // true if no function was given
      return !This.PostSetFn ||
         This.PostSetFn(
            static_cast<EffectType&>(effect), settings, structure, true);
   }
};

/**************************************************************************//**
\brief SettingsVisitor that gets parameter values into a string.
********************************************************************************/
class COMMAND_PARAMETERS_API ShuttleGetAutomation final
   : public ConstSettingsVisitor
{
public:
   ConstSettingsVisitor & Optional(const bool & var) override;
   void Define(bool var, const wxChar * key, bool vdefault,
      bool vmin, bool vmax, bool vscl) override;
   void Define(int var, const wxChar * key, int vdefault,
      int vmin, int vmax, int vscl) override;
   void Define(size_t var, const wxChar * key, int vdefault,
      int vmin, int vmax, int vscl) override;
   void Define(float var, const wxChar * key, float vdefault,
      float vmin, float vmax, float vscl) override;
   void Define(double var, const wxChar * key, float vdefault,
      float vmin, float vmax, float vscl) override;
   void Define(double var, const wxChar * key, double vdefault,
      double vmin, double vmax, double vscl) override;
   void Define(const wxString &var,  const wxChar * key, wxString vdefault,
      wxString vmin, wxString vmax, wxString vscl) override;
   void DefineEnum(int var, const wxChar * key, int vdefault,
      const EnumValueSymbol strings[], size_t nStrings) override;
};

/**************************************************************************//**
\brief SettingsVisitor that sets parameters to a value (from a string)
********************************************************************************/
class COMMAND_PARAMETERS_API ShuttleSetAutomation final : public SettingsVisitor
{
public:
   ShuttleSetAutomation() {}
   bool bOK{ false };
   bool bWrite{ false };

   bool CouldGet(const wxString &key);
   void SetForValidating( CommandParameters * pEap) {
      mpEap = pEap;
      bOK = true;
      bWrite = false;
   }
   void SetForWriting(CommandParameters * pEap) {
      mpEap = pEap;
      bOK = true;
      bWrite = true;
   }

   SettingsVisitor & Optional( bool & var ) override;
   void Define( bool & var, const wxChar * key, bool vdefault,
      bool vmin, bool vmax, bool vscl ) override;
   void Define( int & var, const wxChar * key, int vdefault,
      int vmin, int vmax, int vscl ) override;
   void Define( size_t & var, const wxChar * key, int vdefault,
      int vmin, int vmax, int vscl ) override;
   void Define( float & var, const wxChar * key, float vdefault,
      float vmin, float vmax, float vscl ) override;
   void Define( double & var, const wxChar * key, float vdefault,
      float vmin, float vmax, float vscl ) override;
   void Define( double & var, const wxChar * key, double vdefault,
      double vmin, double vmax, double vscl ) override;
   void Define( wxString &var,  const wxChar * key, wxString vdefault,
      wxString vmin, wxString vmax, wxString vscl ) override;
   void DefineEnum( int &var, const wxChar * key, int vdefault,
      const EnumValueSymbol strings[], size_t nStrings ) override;
};

/**************************************************************************//**
\brief SettingsVisitor that sets parameters to their default values.
********************************************************************************/
class COMMAND_PARAMETERS_API ShuttleDefaults final : public SettingsVisitor
{
public:
   wxString Result;
   
   SettingsVisitor & Optional( bool & var ) override;
   SettingsVisitor & OptionalY( bool & var ) override;
   SettingsVisitor & OptionalN( bool & var ) override;
   void Define( bool & var, const wxChar * key, bool vdefault,
      bool vmin, bool vmax, bool vscl ) override;
   void Define( int & var, const wxChar * key, int vdefault,
      int vmin, int vmax, int vscl ) override;
   void Define( size_t & var, const wxChar * key, int vdefault,
      int vmin, int vmax, int vscl ) override;
   void Define( float & var, const wxChar * key, float vdefault,
      float vmin, float vmax, float vscl ) override;
   void Define( double & var, const wxChar * key, float vdefault,
      float vmin, float vmax, float vscl ) override;
   void Define( double & var, const wxChar * key, double vdefault,
      double vmin, double vmax, double vscl ) override;
   void Define( wxString &var,  const wxChar * key, wxString vdefault,
      wxString vmin, wxString vmax, wxString vscl ) override;
   void DefineEnum( int &var, const wxChar * key, int vdefault,
      const EnumValueSymbol strings[], size_t nStrings ) override;
};

#endif