Remove believed-unnecessary and broken MIDI thru option;
[ardour.git] / libs / ardour / ardour / slave.h
1 /*
2     Copyright (C) 2002 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifndef __ardour_slave_h__
21 #define __ardour_slave_h__
22
23 #include <vector>
24
25 #include <glibmm/thread.h>
26
27 #include <jack/jack.h>
28
29 #include "pbd/signals.h"
30
31 #include "ardour/types.h"
32 #include "midi++/parser.h"
33 #include "midi++/types.h"
34
35 class PIChaser;
36
37 namespace MIDI {
38         class Port;
39 }
40
41 namespace ARDOUR {
42
43 class TempoMap;
44 class Session;
45
46 /**
47  * @class Slave
48  *
49  * @brief The Slave interface can be used to sync ARDOURs tempo to an external source
50  * like MTC, MIDI Clock, etc.
51  *
52  * The name of the interface may be a bit misleading: A subclass of Slave actually
53  * acts as a time master for ARDOUR, that means ARDOUR will try to follow the
54  * speed and transport position of the implementation of Slave.
55  * Therefore it is rather that class, that makes ARDOUR a slave by connecting it
56  * to its external time master.
57  */
58 class Slave {
59   public:
60         Slave() { }
61         virtual ~Slave() {}
62
63         /**
64          * This is the most important function to implement:
65          * Each process cycle, Session::follow_slave will call this method.
66          *  and after the method call they should
67          *
68          * Session::follow_slave will then try to follow the given
69          * <em>position</em> using a delay locked loop (DLL),
70          * starting with the first given transport speed.
71          * If the values of speed and position contradict each other,
72          * ARDOUR will always follow the position and disregard the speed.
73          * Although, a correct speed is important so that ARDOUR
74          * can sync to the master time source quickly.
75          *
76          * For background information on delay locked loops,
77          * see http://www.kokkinizita.net/papers/usingdll.pdf
78          *
79          * The method has the following precondition:
80          * <ul>
81          *   <li>
82          *       Slave::ok() should return true, otherwise playback will stop
83          *       immediately and the method will not be called
84          *   </li>
85          *   <li>
86          *     when the references speed and position are passed into the Slave
87          *     they are uninitialized
88          *   </li>
89          * </ul>
90          *
91          * After the method call the following postconditions should be met:
92          * <ul>
93          *    <li>
94          *       The first position value on transport start should be 0,
95          *       otherwise ARDOUR will try to locate to the new position
96          *       rather than move to it
97          *    </li>
98          *    <li>
99          *      the references speed and position should be assigned
100          *      to the Slaves current requested transport speed
101          *      and transport position.
102          *    </li>
103          *   <li>
104          *     Slave::resolution() should be greater than the maximum distance of
105          *     ARDOURs transport position to the slaves requested transport position.
106          *   </li>
107          *   <li>Slave::locked() should return true, otherwise Session::no_roll will be called</li>
108          *   <li>Slave::starting() should be false, otherwise the transport will not move until it becomes true</li>     *
109          * </ul>
110          *
111          * @param speed - The transport speed requested
112          * @param position - The transport position requested
113          * @return - The return value is currently ignored (see Session::follow_slave)
114          */
115         virtual bool speed_and_position (double& speed, framepos_t& position) = 0;
116
117         /**
118          * reports to ARDOUR whether the Slave is currently synced to its external
119          * time source.
120          *
121          * @return - when returning false, the transport will stop rolling
122          */
123         virtual bool locked() const = 0;
124
125         /**
126          * reports to ARDOUR whether the slave is in a sane state
127          *
128          * @return - when returning false, the transport will be stopped and the slave
129          * disconnected from ARDOUR.
130          */
131         virtual bool ok() const = 0;
132
133         /**
134          * reports to ARDOUR whether the slave is in the process of starting
135          * to roll
136          *
137          * @return - when returning false, transport will not move until this method returns true
138          */
139         virtual bool starting() const { return false; }
140
141         /**
142          * @return - the timing resolution of the Slave - If the distance of ARDOURs transport
143          * to the slave becomes greater than the resolution, sound will stop
144          */
145         virtual framecnt_t resolution() const = 0;
146
147         /**
148          * @return - when returning true, ARDOUR will wait for seekahead_distance() before transport
149          * starts rolling
150          */
151         virtual bool requires_seekahead () const = 0;
152
153         /**
154          * @return the number of frames that this slave wants to seek ahead. Relevant
155          * only if requires_seekahead() returns true.
156          */
157
158         virtual framecnt_t seekahead_distance() const { return 0; }
159
160         /**
161          * @return - when returning true, ARDOUR will use transport speed 1.0 no matter what
162          *           the slave returns
163          */
164         virtual bool is_always_synced() const { return false; }
165
166         /**
167          * @return - whether ARDOUR should use the slave speed without any adjustments
168          */
169         virtual bool give_slave_full_control_over_transport_speed() const { return false; }
170 };
171
172 /// We need this wrapper for testability, it's just too hard to mock up a session class
173 class ISlaveSessionProxy {
174   public:
175         virtual ~ISlaveSessionProxy() {}
176         virtual TempoMap&  tempo_map()                 const   { return *((TempoMap *) 0); }
177         virtual framecnt_t frame_rate()                const   { return 0; }
178         virtual framepos_t audible_frame ()            const   { return 0; }
179         virtual framepos_t transport_frame ()          const   { return 0; }
180         virtual pframes_t  frames_since_cycle_start () const   { return 0; }
181         virtual framepos_t frame_time ()               const   { return 0; }
182
183         virtual void request_locate (framepos_t /*frame*/, bool with_roll = false) {
184                 (void) with_roll;
185         }
186         virtual void request_transport_speed (double /*speed*/)                   {}
187 };
188
189
190 /// The Session Proxy for use in real Ardour
191 class SlaveSessionProxy : public ISlaveSessionProxy {
192         Session&    session;
193
194   public:
195         SlaveSessionProxy(Session &s) : session(s) {}
196
197         TempoMap&  tempo_map()                 const;
198         framecnt_t frame_rate()                const;
199         framepos_t audible_frame ()            const;
200         framepos_t transport_frame ()          const;
201         pframes_t  frames_since_cycle_start () const;
202         framepos_t frame_time ()               const;
203
204         void request_locate (framepos_t frame, bool with_roll = false);
205         void request_transport_speed (double speed);
206 };
207
208 struct SafeTime {
209         volatile int guard1;
210         framepos_t   position;
211         framepos_t   timestamp;
212         double       speed;
213         volatile int guard2;
214
215         SafeTime() {
216                 guard1 = 0;
217                 position = 0;
218                 timestamp = 0;
219                 speed = 0;
220                 guard2 = 0;
221         }
222 };
223
224 class MTC_Slave : public Slave {
225   public:
226         MTC_Slave (Session&, MIDI::Port&);
227         ~MTC_Slave ();
228
229         void rebind (MIDI::Port&);
230         bool speed_and_position (double&, framepos_t&);
231
232         bool locked() const;
233         bool ok() const;
234         void handle_locate (const MIDI::byte*);
235
236         framecnt_t resolution () const;
237         bool requires_seekahead () const { return true; }
238         framecnt_t seekahead_distance() const;
239         bool give_slave_full_control_over_transport_speed() const;
240
241   private:
242         Session&    session;
243         MIDI::Port* port;
244         PBD::ScopedConnectionList port_connections;
245         bool        can_notify_on_unknown_rate;
246         PIChaser* pic;
247
248         static const int frame_tolerance;
249
250         SafeTime       current;
251         framepos_t     mtc_frame;               /* current time */
252         framepos_t     last_inbound_frame;      /* when we got it; audio clocked */
253         MIDI::byte     last_mtc_fps_byte;
254         framepos_t     window_begin;
255         framepos_t     window_end;
256         framepos_t     last_mtc_timestamp;
257         framepos_t     last_mtc_frame;
258         bool           did_reset_tc_format;
259         TimecodeFormat saved_tc_format;
260         size_t         speed_accumulator_size;
261         double*        speed_accumulator;
262         size_t         speed_accumulator_cnt;
263         bool           have_first_speed_accumulator;
264         double         average_speed;
265         Glib::Mutex    reset_lock;
266         uint32_t       reset_pending;
267         bool           reset_position;
268
269         void reset (bool with_pos);
270         void queue_reset (bool with_pos);
271         void maybe_reset ();
272
273         void update_mtc_qtr (MIDI::Parser&, int, framepos_t);
274         void update_mtc_time (const MIDI::byte *, bool, framepos_t);
275         void update_mtc_status (MIDI::MTC_Status);
276         void read_current (SafeTime *) const;
277         void reset_window (framepos_t);
278         bool outside_window (framepos_t) const;
279         void process_apparent_speed (double);
280 };
281
282 class MIDIClock_Slave : public Slave {
283   public:
284         MIDIClock_Slave (Session&, MIDI::Port&, int ppqn = 24);
285
286         /// Constructor for unit tests
287         MIDIClock_Slave (ISlaveSessionProxy* session_proxy = 0, int ppqn = 24);
288         ~MIDIClock_Slave ();
289
290         void rebind (MIDI::Port&);
291         bool speed_and_position (double&, framepos_t&);
292
293         bool locked() const;
294         bool ok() const;
295         bool starting() const;
296
297         framecnt_t resolution () const;
298         bool requires_seekahead () const { return false; }
299         bool give_slave_full_control_over_transport_speed() const { return true; }
300
301         void set_bandwidth (double a_bandwith) { bandwidth = a_bandwith; }
302
303   protected:
304         ISlaveSessionProxy* session;
305         MIDI::Port* port;
306         PBD::ScopedConnectionList port_connections;
307
308         /// pulses per quarter note for one MIDI clock frame (default 24)
309         int         ppqn;
310
311         /// the duration of one ppqn in frame time
312         double      one_ppqn_in_frames;
313
314         /// the timestamp of the first MIDI clock message
315         framepos_t  first_timestamp;
316
317         /// the time stamp and should-be transport position of the last inbound MIDI clock message
318         framepos_t  last_timestamp;
319         double      should_be_position;
320
321         /// the number of midi clock messages received (zero-based)
322         /// since start
323         long midi_clock_count;
324
325         //the delay locked loop (DLL), see www.kokkinizita.net/papers/usingdll.pdf
326
327         /// time at the beginning of the MIDI clock frame
328         double t0;
329
330         /// calculated end of the MIDI clock frame
331         double t1;
332
333         /// loop error = real value - expected value
334         double e;
335
336         /// second order loop error
337         double e2;
338
339         /// DLL filter bandwidth
340         double bandwidth;
341
342         /// DLL filter coefficients
343         double b, c, omega;
344
345         void reset ();
346         void start (MIDI::Parser& parser, framepos_t timestamp);
347         void contineu (MIDI::Parser& parser, framepos_t timestamp);
348         void stop (MIDI::Parser& parser, framepos_t timestamp);
349         void position (MIDI::Parser& parser, MIDI::byte* message, size_t size);
350         // we can't use continue because it is a C++ keyword
351         void calculate_one_ppqn_in_frames_at(framepos_t time);
352         framepos_t calculate_song_position(uint16_t song_position_in_sixteenth_notes);
353         void calculate_filter_coefficients();
354         void update_midi_clock (MIDI::Parser& parser, framepos_t timestamp);
355         void read_current (SafeTime *) const;
356         bool stop_if_no_more_clock_events(framepos_t& pos, framepos_t now);
357
358         /// whether transport should be rolling
359         bool _started;
360
361         /// is true if the MIDI Start message has just been received until
362         /// the first MIDI Clock Event
363         bool _starting;
364 };
365
366 class JACK_Slave : public Slave
367 {
368   public:
369         JACK_Slave (jack_client_t*);
370         ~JACK_Slave ();
371
372         bool speed_and_position (double& speed, framepos_t& pos);
373
374         bool starting() const { return _starting; }
375         bool locked() const;
376         bool ok() const;
377         framecnt_t resolution () const { return 1; }
378         bool requires_seekahead () const { return false; }
379         void reset_client (jack_client_t* jack);
380         bool is_always_synced() const { return true; }
381
382   private:
383         jack_client_t* jack;
384         double speed;
385         bool _starting;
386 };
387
388 } /* namespace */
389
390 #endif /* __ardour_slave_h__ */