7c7f1d98ce82ffc75e6020454db9952c5b6a8b87
[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 <jack/jack.h>
26
27 #include <sigc++/signal.h>
28 #include <ardour/ardour.h>
29 #include <midi++/parser.h>
30 #include <midi++/types.h>
31
32 namespace MIDI {
33         class Port;
34 }
35
36 namespace ARDOUR {
37 class Session;
38
39 class Slave {
40   public:
41         Slave() { }
42         virtual ~Slave() {}
43
44         virtual bool speed_and_position (float&, nframes_t&) = 0;
45         virtual bool locked() const = 0;
46         virtual bool ok() const = 0;
47         virtual bool starting() const { return false; }
48         virtual nframes_t resolution() const = 0;
49         virtual bool requires_seekahead () const = 0;
50         virtual bool is_always_synced() const { return false; }
51 };
52
53 struct SafeTime {
54     int guard1;
55     nframes_t   position;
56     nframes_t   timestamp;
57     int guard2;
58
59     SafeTime() {
60             guard1 = 0;
61             guard2 = 0;
62             timestamp = 0;
63     }
64 };
65
66 class MTC_Slave : public Slave, public sigc::trackable {
67   public:
68         MTC_Slave (Session&, MIDI::Port&);
69         ~MTC_Slave ();
70
71         void rebind (MIDI::Port&);
72         bool speed_and_position (float&, nframes_t&);
73
74         bool locked() const;
75         bool ok() const;
76         void handle_locate (const MIDI::byte*);
77
78         nframes_t resolution() const;
79         bool requires_seekahead () const { return true; }
80
81   private:
82         Session&    session;
83         MIDI::Port* port;
84         std::vector<sigc::connection> connections;
85         bool        can_notify_on_unknown_rate;
86
87         SafeTime    current;
88         nframes_t   mtc_frame;               /* current time */
89         nframes_t   last_inbound_frame;      /* when we got it; audio clocked */
90
91         float       mtc_speed;
92         nframes_t   first_mtc_frame;
93         nframes_t   first_mtc_time;
94
95         static const int32_t accumulator_size = 128;
96         float   accumulator[accumulator_size];
97         int32_t accumulator_index;
98         bool    have_first_accumulated_speed;
99
100         void reset ();
101         void update_mtc_qtr (MIDI::Parser&);
102         void update_mtc_time (const MIDI::byte *, bool);
103         void update_mtc_status (MIDI::Parser::MTC_Status);
104         void read_current (SafeTime *) const;
105 };
106
107 class MIDIClock_Slave : public Slave, public sigc::trackable {
108   public:
109         MIDIClock_Slave (Session&, MIDI::Port&, int ppqn = 24);
110         ~MIDIClock_Slave ();
111
112         void rebind (MIDI::Port&);
113         bool speed_and_position (float&, nframes_t&);
114
115         bool locked() const;
116         bool ok() const;
117         bool starting() const { return false; }
118
119         nframes_t resolution() const;
120         bool requires_seekahead () const { return true; }
121
122   private:
123         Session&    session;
124         MIDI::Port* port;
125         std::vector<sigc::connection> connections;
126
127         int         ppqn;
128         double      one_ppqn_in_frames;
129
130         SafeTime    current;
131         nframes_t   midi_clock_frame;               /* current time */
132         nframes_t   last_inbound_frame;             /* when we got it; audio clocked */
133
134         float       midi_clock_speed;
135         nframes_t   first_midi_clock_frame;
136         nframes_t   first_midi_clock_time;
137
138         // keep four beats of history ( 4 * 24 ppqn )
139         static const int32_t accumulator_size = 96;
140         float   accumulator[accumulator_size];
141         int32_t accumulator_index;
142         bool    have_first_accumulated_speed;
143         float   average;
144
145         void reset ();
146         void start (MIDI::Parser& parser);
147         void stop (MIDI::Parser& parser);
148         void update_midi_clock (MIDI::Parser& parser);
149         void read_current (SafeTime *) const;
150
151         bool _started;
152 };
153
154 class ADAT_Slave : public Slave
155 {
156   public:
157         ADAT_Slave () {}
158         ~ADAT_Slave () {}
159
160         bool speed_and_position (float& speed, nframes_t& pos) {
161                 speed = 0;
162                 pos = 0;
163                 return false;
164         }
165
166         bool locked() const { return false; }
167         bool ok() const { return false; }
168         nframes_t resolution() const { return 1; }
169         bool requires_seekahead () const { return true; }
170 };
171
172 class JACK_Slave : public Slave
173 {
174   public:
175         JACK_Slave (jack_client_t*);
176         ~JACK_Slave ();
177
178         bool speed_and_position (float& speed, nframes_t& pos);
179
180         bool starting() const { return _starting; }
181         bool locked() const;
182         bool ok() const;
183         nframes_t resolution() const { return 1; }
184         bool requires_seekahead () const { return false; }
185         void reset_client (jack_client_t* jack);
186         bool is_always_synced() const { return true; }
187
188   private:
189         jack_client_t* jack;
190         float speed;
191         bool _starting;
192 };
193
194 } /* namespace */
195
196 #endif /* __ardour_slave_h__ */