Ardour  9.0-pre0-582-g084a23a80d
transport_fsm.h
Go to the documentation of this file.
1 #ifndef _ardour_transport_fsm_h_
2 #define _ardour_transport_fsm_h_
3 
4 #include <list>
5 #include <queue>
6 
7 #include <boost/intrusive/list.hpp>
8 #include <optional>
9 
10 #include <string>
11 #include <utility>
12 #include <iostream>
13 
14 #include "pbd/demangle.h"
15 #include "pbd/pool.h"
16 
17 #include "ardour/debug.h"
18 #include "ardour/types.h"
19 
20 namespace ARDOUR
21 {
22 
23 class TransportAPI;
24 
26 {
27  /* All code related to this object is expected to be run synchronously
28  * and single-threaded from the process callback. It can be re-entrant
29  * if handling one transport state change queues another state change,
30  * but that is handled explicitly (see the @p processing member and
31  * its usage).
32  */
33 
34  public:
35  enum EventType {
44  };
45 
46  struct Event : public boost::intrusive::list_base_hook<> {
48  /* for stop and speed */
51  /* for locate */
55  bool force;
56  /* for SetSpeed */
57  double speed;
58 
60  : type (t)
61  , abort_capture (false)
62  , clear_state (false)
63  , ltd (MustStop)
64  , target (0)
65  , for_loop_end (false)
66  , force (false)
67  {
68  assert (t != StopTransport);
69  assert (t != Locate);
70  }
71  Event (EventType t, bool ab, bool cl)
72  : type (t)
73  , abort_capture (ab)
74  , clear_state (cl)
75  , ltd (MustStop)
76  , target (0)
77  , for_loop_end (false)
78  , force (false)
79  {
80  assert (t == StopTransport);
81  }
82  Event (EventType t, samplepos_t pos, LocateTransportDisposition l, bool lp, bool f4c)
83  : type (t)
84  , abort_capture (false)
85  , clear_state (false)
86  , ltd (l)
87  , target (pos)
88  , for_loop_end (lp)
89  , force (f4c)
90  {
91  assert (t == Locate);
92  }
93  /* here we drop the event type as the first argument in order
94  disambiguate from the StopTransport case above (compiler can
95  cast double-to-bool and complains. C++11 would allow "=
96  delete" as an alternate fix, but this is fine.
97  */
98  Event (double sp)
99  : type (SetSpeed)
100  , speed (sp)
101  {
102  }
103 
104  void* operator new (size_t);
105  void operator delete (void *ptr, size_t /*size*/);
106 
107  static void init_pool ();
108 
109  private:
110  static PBD::Pool* pool;
111 
112  };
113 
115 
116  void hard_stop ();
117 
118  void start () {
119  init ();
120  }
121 
122  void stop () {
123  /* should we do anything here? this method is modelled on the
124  boost::msm design, but its not clear that we ever need to
125  do anything like this.
126  */
127  }
128 
129  enum MotionState {
135  };
136 
137  enum ButlerState {
140  };
141 
146  };
147 
148  std::string current_state () const;
149 
150  double transport_speed() const { return _transport_speed; }
151 
152  double default_speed() const { return _default_speed; }
153  void set_default_speed(double spd) const { _default_speed = spd; }
154 
155  private:
160 
161  void init();
162 
163  /* transition actions */
164 
166  void start_playback ();
167  void stop_playback (Event const &);
169  void locate_for_loop (Event const &);
170  void roll_after_locate () const;
171  void start_locate_while_stopped (Event const &) const;
172  void interrupt_locate (Event const &) const;
174  bool set_speed (Event const &);
175 
176  /* guards */
177 
180 
181  public:
182  bool locating () const { return _motion_state == WaitingForLocate; }
183  bool rolling () const { return _motion_state == Rolling; }
184  bool stopped () const { return _motion_state == Stopped; }
185  bool stopping () const { return _motion_state == DeclickToStop; }
189  bool forwards() const { return _direction_state == Forwards; }
190  bool backwards() const { return _direction_state == Backwards; }
191  bool reversing() const { return _direction_state == Reversing; }
192  bool will_roll_forwards() const;
193 
194  void enqueue (Event* ev);
195 
196  private:
197 
201 
202  void process_events ();
203  bool process_event (Event&, bool was_deferred, bool& deferred);
204 
206 
208  typedef boost::intrusive::list<Event> EventList;
212  mutable std::optional<bool> current_roll_after_locate_status;
214  mutable double _default_speed;
216 
217  void defer (Event& ev);
218  void bad_transition (Event const &);
219  void set_roll_after (bool) const;
223 };
224 
225 } /* end namespace ARDOUR */
226 
227 #endif
Definition: pool.h:40
Temporal::samplepos_t samplepos_t
LocateTransportDisposition ltd
Definition: transport_fsm.h:52
static PBD::Pool * pool
Event(EventType t, samplepos_t pos, LocateTransportDisposition l, bool lp, bool f4c)
Definition: transport_fsm.h:82
Event(EventType t, bool ab, bool cl)
Definition: transport_fsm.h:71
double transport_speed() const
void transition(ButlerState)
bool process_event(Event &, bool was_deferred, bool &deferred)
ButlerState _butler_state
bool should_not_roll_after_locate() const
void interrupt_locate(Event const &) const
void enqueue(Event *ev)
void start_locate_after_declick()
void start_declick_for_locate(Event const &)
bool stopped() const
void start_locate_while_stopped(Event const &) const
int compute_transport_speed() const
void set_default_speed(double spd) const
double default_speed() const
bool locating() const
void schedule_butler_for_transport_work() const
bool should_roll_after_locate() const
void roll_after_locate() const
bool compute_should_roll(LocateTransportDisposition) const
bool stopping() const
boost::intrusive::list< Event > EventList
void set_roll_after(bool) const
DirectionState _direction_state
bool waiting_for_butler() const
void transition(DirectionState)
bool reversing() const
double most_recently_requested_speed
std::optional< bool > current_roll_after_locate_status
void stop_playback(Event const &)
void locate_for_loop(Event const &)
bool will_roll_forwards() const
TransportAPI * api
void bad_transition(Event const &)
std::string current_state() const
bool set_speed(Event const &)
MotionState _motion_state
bool forwards() const
bool backwards() const
TransportFSM(TransportAPI &tapi)
void defer(Event &ev)
void transition(MotionState)
bool declicking_for_locate() const
bool rolling() const
bool declick_in_progress() const