Allolib  1.0
C++ Components For Interactive Multimedia
al_PresetSequencer.hpp
1 #ifndef AL_PRESETSEQUENCER_H
2 #define AL_PRESETSEQUENCER_H
3 
4 /* Allocore --
5  Multimedia / virtual environment application class library
6 
7  Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology,
8  UCSB. Copyright (C) 2012-2016. The Regents of the University of California.
9  All rights reserved.
10 
11  Redistribution and use in source and binary forms, with or without
12  modification, are permitted provided that the following conditions are
13  met:
14 
15  Redistributions of source code must retain the above copyright
16  notice, this list of conditions and the following disclaimer.
17 
18  Redistributions in binary form must reproduce the above
19  copyright notice, this list of conditions and the following disclaimer in the
20  documentation and/or other materials provided with the
21  distribution.
22 
23  Neither the name of the University of California nor the names
24  of its contributors may be used to endorse or promote products derived from
25  this software without specific prior written permission.
26 
27  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
28  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
31  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
34  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
36  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
37  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 
39  File description:
40  Preset sequencing
41 
42  File author(s):
43  AndrĂ©s Cabrera mantaraya36@gmail.com
44 */
45 
46 #include <atomic>
47 #include <condition_variable>
48 #include <functional>
49 #include <future>
50 #include <mutex>
51 #include <queue>
52 #include <string>
53 #include <thread>
54 #include <utility>
55 
56 #include "al/protocol/al_OSC.hpp"
57 #include "al/ui/al_PresetHandler.hpp"
58 
59 namespace al {
60 
61 class SequenceRecorder;
62 class Composition;
63 
119  friend class Composition;
120 
121  public:
123  TimeMasterMode timeMasterMode = TimeMasterMode::TIME_MASTER_CPU);
124  ~PresetSequencer() override;
125 
126  typedef enum { PRESET, EVENT, PARAMETER } StepType;
127 
128  struct Step {
129  StepType type = PRESET;
130  std::string name;
131  float morphTime; // The time to get to the preset
132  float waitTime; // The time to stay in the preset before the next step
133  std::vector<ParameterField> params;
134  };
135 
136  typedef struct {
137  std::string eventName;
138  std::function<void(void *data, std::vector<ParameterField> &params)>
139  callback;
140  void *callbackData;
141  } EventCallback;
142 
152  void playSequence(std::string sequenceName, double timeScale = 1.0f,
153  double timeOffset = 0.0);
154 
155  void stopSequence(bool triggerCallbacks = true);
156 
163  void setTime(double time);
164 
168  void rewind();
169 
170  bool playbackFinished() { return mSteps.size() == mCurrentStep; }
171 
178  std::vector<std::string> getSequenceList();
179 
190  void setDirectory(std::string directory) { mDirectory = directory; }
191 
198  void setHandlerSubDirectory(std::string subDir);
199 
200  inline bool running() { return mRunning; }
201 
211 
218  return registerPresetHandler(presetHandler);
219  }
220 
222  return registerParameter(param);
223  }
224 
225  PresetSequencer &registerParameter(ParameterMeta &param) {
226  mParameters.push_back(&param);
227  return *this;
228  }
229 
239  std::vector<Step> loadSequence(std::string sequenceName,
240  double timeScale = 1.0);
241 
242  std::string currentSequence() { return mCurrentSequence; }
243 
253  std::string eventName,
254  std::function<void(void *data, std::vector<ParameterField> &params)>
255  callback,
256  void *data);
257 
258  void setOSCSubPath(std::string subPath) { mOSCsubPath = subPath; }
259 
267  std::function<void(PresetSequencer *sender)> beginCallback);
268 
269  void enableBeginCallback(bool enable) { mBeginCallbackEnabled = enable; }
270 
271  void toggleEnableBeginCallback() {
272  mBeginCallbackEnabled = !mBeginCallbackEnabled;
273  }
274 
283  std::function<void(bool finished, PresetSequencer *sender)> endCallback);
284 
285  void enableEndCallback(bool enable) { mEndCallbackEnabled = enable; }
286  void toggleEnableEndCallback() { mEndCallbackEnabled = !mEndCallbackEnabled; }
287 
288  void registerTimeChangeCallback(std::function<void(float)> func,
289  float minTimeDeltaSec = -1.0);
290 
291  float getSequenceStartOffset(std::string sequenceName);
292  float getSequenceTotalDuration(std::string sequenceName);
293 
294  // For programmatic control of the sequencer:
295  void clearSteps();
296 
304  void appendStep(Step &newStep);
305 
306  void setTimeMaster(TimeMasterMode masterMode);
307 
315  void stepSequencer(double dt);
316 
321 
322  void setSequencerStepTime(double stepTime) { mGranularity = stepTime * 1e9; }
323 
324  protected:
325  virtual bool consumeMessage(osc::Message &m,
326  std::string rootOSCPath) override;
327 
328  void processTimeChangeRequest();
329  void updateTime(double time);
330 
331  void updateSequencer();
332 
333  private:
334  static void sequencerFunction(PresetSequencer *sequencer);
335 
336  std::string buildFullPath(std::string sequenceName);
337 
338  void startCpuThread();
339  void stopCpuThread();
340 
341  std::vector<Step> mSteps;
342  std::string mDirectory;
343  PresetHandler *mPresetHandler{nullptr};
344  std::vector<ParameterMeta *> mParameters;
345  std::string mOSCsubPath;
346  std::string mCurrentSequence;
347 
348  std::atomic<float> mTimeRequest{-1.0f}; // Request setting the current time.
349  // Passes info to playback thread
350 
351  TimeMasterMode mTimeMasterMode;
352 
353  bool mSequencerActive{false};
354  bool mRunning;
355  bool mStartRunning;
356  std::queue<Step> mParameterList;
357  double mCurrentTime = 0.0; // Current time (in seconds)
358  double mTargetTime;
359  double mLastPresetTime; // To anchor parameter deltas
360  double mParameterTargetTime;
361  double mLastTimeUpdate = 0.0;
362  double mStepTime;
363 
364  uint64_t mGranularity = 10e6; // nanoseconds
365  bool mBeginCallbackEnabled;
366  std::function<void(PresetSequencer *)> mBeginCallback;
367  bool mEndCallbackEnabled;
368  std::function<void(bool, PresetSequencer *)> mEndCallback;
369  std::vector<EventCallback> mEventCallbacks;
370  std::vector<std::function<void(float)>> mTimeChangeCallbacks;
371  float mTimeChangeMinTimeDelta = 0.05f;
372 
373  // CPU thread
374 
375  // std::chrono::high_resolution_clock::time_point mSequenceStart =
376  // std::chrono::high_resolution_clock::now();
377  std::unique_ptr<std::thread> mSequencerThread;
378  std::mutex mSequenceLock;
379  uint64_t mCurrentStep;
380  PresetHandler::ParameterStates mStartValues;
381  std::mutex mPlayWaitLock;
382  std::condition_variable mPlayWaitVariable;
383  // std::mutex mPlayStartedLock;
384  // std::condition_variable mPlayStartedVariable;
385  std::shared_ptr<std::promise<void>> mPlayPromiseObj;
386 };
387 
388 } // namespace al
389 
390 #endif // AL_PRESETSEQUENCER_H
The ParameterMeta class defines the base interface for Parameter metadata.
The PresetHandler class handles sorting and recalling of presets.
The PresetSequencer class allows triggering presets from a PresetHandler over time.
PresetSequencer & operator<<(PresetHandler &presetHandler)
Register PresetHandler through the << operator.
void appendStep(Step &newStep)
appendStep
void setDirectory(std::string directory)
setDirectory sets the working directory for the PresetSequencer
std::vector< std::string > getSequenceList()
getSequenceList returns a list of sequences in the current sequence directory
void stepSequencer(double dt)
step sequencer forward dt amount of time
void registerEventCommand(std::string eventName, std::function< void(void *data, std::vector< ParameterField > &params)> callback, void *data)
registerEventCommand registers a function associated with an event command
void registerBeginCallback(std::function< void(PresetSequencer *sender)> beginCallback)
registerBeginCallback
void registerEndCallback(std::function< void(bool finished, PresetSequencer *sender)> endCallback)
registerEndCallback
virtual bool consumeMessage(osc::Message &m, std::string rootOSCPath) override
Returns true if message was consumed by this class.
std::vector< Step > loadSequence(std::string sequenceName, double timeScale=1.0)
Load steps from a sequence file.
void setHandlerSubDirectory(std::string subDir)
Sets the sub-directory for the registered PresetHandler.
void stepSequencer()
move sequencer forward by time set using setSequencerStepTime()
PresetSequencer & registerPresetHandler(PresetHandler &presetHandler)
Register preset handler with sequencer.
void setTime(double time)
Set time into the current sequence.
void rewind()
Load sequence an prepare for playback.
void playSequence(std::string sequenceName, double timeScale=1.0f, double timeOffset=0.0)
Start playing the sequence specified.
Definition: al_App.hpp:23