Revert completely mystifying stupidity in a previous patch of mine, and (properly...
[ardour.git] / libs / ardour / mtc_slave.cc
1 /*
2     Copyright (C) 2002-4 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 #include <iostream>
20 #include <errno.h>
21 #include <poll.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include "pbd/error.h"
25 #include "pbd/failed_constructor.h"
26 #include "pbd/pthread_utils.h"
27
28 #include "midi++/port.h"
29 #include "ardour/debug.h"
30 #include "ardour/slave.h"
31 #include "ardour/session.h"
32 #include "ardour/audioengine.h"
33 #include "ardour/cycles.h"
34
35 #include "i18n.h"
36
37 using namespace std;
38 using namespace ARDOUR;
39 using namespace sigc;
40 using namespace MIDI;
41 using namespace PBD;
42
43 MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
44         : session (s)
45 {
46         can_notify_on_unknown_rate = true;
47
48         last_mtc_fps_byte = session.get_mtc_timecode_bits ();
49
50         rebind (p);
51         reset ();
52 }
53
54 MTC_Slave::~MTC_Slave()
55 {
56 }
57
58 void
59 MTC_Slave::rebind (MIDI::Port& p)
60 {
61         for (vector<sigc::connection>::iterator i = connections.begin(); i != connections.end(); ++i) {
62                 (*i).disconnect ();
63         }
64
65         port = &p;
66
67         connections.push_back (port->input()->mtc_time.connect (mem_fun (*this, &MTC_Slave::update_mtc_time)));
68         connections.push_back (port->input()->mtc_qtr.connect (mem_fun (*this, &MTC_Slave::update_mtc_qtr)));
69         connections.push_back (port->input()->mtc_status.connect (mem_fun (*this, &MTC_Slave::update_mtc_status)));
70 }
71
72 void
73 MTC_Slave::update_mtc_qtr (Parser& /*p*/)
74 {
75         nframes64_t now = session.engine().frame_time();
76         nframes_t qtr;
77
78         qtr = (long) (session.frames_per_timecode_frame() / 4);
79         mtc_frame += qtr;
80         
81         double speed = compute_apparent_speed (now);
82
83         current.guard1++;
84         current.position = mtc_frame;
85         current.timestamp = now;
86         current.speed = speed;
87         current.guard2++;
88
89         last_inbound_frame = now;
90 }
91
92 void
93 MTC_Slave::update_mtc_time (const byte *msg, bool was_full)
94 {
95         nframes64_t now = session.engine().frame_time();
96         Timecode::Time timecode;
97
98         timecode.hours = msg[3];
99         timecode.minutes = msg[2];
100         timecode.seconds = msg[1];
101         timecode.frames = msg[0];
102
103         last_mtc_fps_byte = msg[4];
104
105         switch (msg[4]) {
106         case MTC_24_FPS:
107                 timecode.rate = 24;
108                 timecode.drop = false;
109                 can_notify_on_unknown_rate = true;
110                 break;
111         case MTC_25_FPS:
112                 timecode.rate = 25;
113                 timecode.drop = false;
114                 can_notify_on_unknown_rate = true;
115                 break;
116         case MTC_30_FPS_DROP:
117                 timecode.rate = 30;
118                 timecode.drop = true;
119                 can_notify_on_unknown_rate = true;
120                 break;
121         case MTC_30_FPS:
122                 timecode.rate = 30;
123                 timecode.drop = false;
124                 can_notify_on_unknown_rate = true;
125                 break;
126         default:
127                 /* throttle error messages about unknown MTC rates */
128                 if (can_notify_on_unknown_rate) {
129                         error << string_compose (_("Unknown rate/drop value %1 in incoming MTC stream, session values used instead"),
130                                                  (int) msg[4])
131                               << endmsg;
132                         can_notify_on_unknown_rate = false;
133                 }
134                 timecode.rate = session.timecode_frames_per_second();
135                 timecode.drop = session.timecode_drop_frames();
136         }
137
138         session.timecode_to_sample (timecode, mtc_frame, true, false);
139
140         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC time timestamp = %1 TC %2 = frame %3 (from full message ? %4)\n", 
141                                                  now, timecode, mtc_frame, was_full));
142
143         if (was_full) {
144
145                 session.request_locate (mtc_frame, false);
146                 session.request_transport_speed (0);
147                 update_mtc_status (MIDI::Parser::MTC_Stopped);
148                 reset ();
149
150         } else {
151
152
153                 /* We received the last quarter frame 7 quarter frames (1.75 mtc
154                    frames) after the instance when the contents of the mtc quarter
155                    frames were decided. Add time to compensate for the elapsed 1.75
156                    frames.
157                    Also compensate for audio latency.
158                 */
159 #if 0           
160                 mtc_frame += (long) (1.75 * session.frames_per_timecode_frame()) + session.worst_output_latency();
161
162                 /* leave speed alone here. compute it only as we receive qtr frame messages */
163                 
164                 current.guard1++;
165                 current.position = mtc_frame;
166                 current.timestamp = now;
167                 current.guard2++;
168
169                 DEBUG_TRACE (DEBUG::MTC, string_compose ("stored TC frame = %1 @ %2, sp = %3\n", mtc_frame, now, speed));
170 #endif
171         }
172
173         last_inbound_frame = now;
174 }
175
176 double
177 MTC_Slave::compute_apparent_speed (nframes64_t now)
178 {
179         if (current.timestamp != 0) {
180                 
181                 double speed = (double) ((mtc_frame - current.position) / (double) (now - current.timestamp));
182                 DEBUG_TRACE (DEBUG::MTC, string_compose ("instantaneous speed = %1 from %2 - %3 / %4 - %5\n",
183                                                          speed, mtc_frame, current.position, now, current.timestamp));
184                 
185                 accumulator[accumulator_index++] = speed;
186                 
187                 if (accumulator_index >= accumulator_size) {
188                         have_first_accumulated_speed = true;
189                         accumulator_index = 0;
190                 }
191                 
192                 if (have_first_accumulated_speed) {
193                         double total = 0;
194                         
195                         for (int32_t i = 0; i < accumulator_size; ++i) {
196                                 total += accumulator[i];
197                         }
198                         
199                         speed = total / accumulator_size;
200                         DEBUG_TRACE (DEBUG::MTC, string_compose ("speed smoothed to %1\n", speed));
201                 } 
202
203                 return speed;
204                 
205         } else {
206                 
207                 return 0;
208         }
209 }
210
211 void
212 MTC_Slave::handle_locate (const MIDI::byte* mmc_tc)
213 {
214         MIDI::byte mtc[5];
215
216         mtc[4] = last_mtc_fps_byte;
217         mtc[3] = mmc_tc[0] & 0xf; /* hrs only */
218         mtc[2] = mmc_tc[1];
219         mtc[1] = mmc_tc[2];
220         mtc[0] = mmc_tc[3];
221
222         update_mtc_time (mtc, true);
223 }
224
225 void
226 MTC_Slave::update_mtc_status (MIDI::Parser::MTC_Status status)
227 {
228         /* XXX !!! thread safety ... called from MIDI I/O context
229            and process() context (via ::speed_and_position())
230         */
231
232         switch (status) {
233         case MTC_Stopped:
234                 mtc_frame = 0;
235
236                 current.guard1++;
237                 current.position = mtc_frame;
238                 current.timestamp = 0;
239                 current.speed = 0;
240                 current.guard2++;
241
242                 break;
243
244         case MTC_Forward:
245                 mtc_frame = 0;
246
247                 current.guard1++;
248                 current.position = mtc_frame;
249                 current.timestamp = 0;
250                 current.speed = 0;
251                 current.guard2++;
252
253                 break;
254
255         case MTC_Backward:
256                 mtc_frame = 0;
257
258                 current.guard1++;
259                 current.position = mtc_frame;
260                 current.timestamp = 0;
261                 current.speed = 0;
262                 current.guard2++;
263
264                 break;
265         }
266 }
267
268 void
269 MTC_Slave::read_current (SafeTime *st) const
270 {
271         int tries = 0;
272
273         do {
274                 if (tries == 10) {
275                         error << _("MTC Slave: atomic read of current time failed, sleeping!") << endmsg;
276                         usleep (20);
277                         tries = 0;
278                 }
279                 *st = current;
280                 tries++;
281
282         } while (st->guard1 != st->guard2);
283 }
284
285 bool
286 MTC_Slave::locked () const
287 {
288         return port->input()->mtc_locked();
289 }
290
291 bool
292 MTC_Slave::ok() const
293 {
294         return true;
295 }
296
297 bool
298 MTC_Slave::speed_and_position (double& speed, nframes64_t& pos)
299 {
300         nframes64_t now = session.engine().frame_time();
301         SafeTime last;
302         nframes_t elapsed;
303
304         read_current (&last);
305
306         if (last.timestamp == 0) {
307                 speed = 0;
308                 pos = last.position;
309                 DEBUG_TRACE (DEBUG::MTC, string_compose ("first call to MTC_Slave::speed_and_position, pos = %1\n", last.position));
310                 return true;
311         }
312
313         /* no timecode for 1/4 second ? conclude that its stopped */
314
315         if (last_inbound_frame && now > last_inbound_frame && now - last_inbound_frame > session.frame_rate() / 4) {
316                 speed = 0;
317                 pos = last.position;
318                 session.request_locate (pos, false);
319                 session.request_transport_speed (0);
320                 update_mtc_status (MIDI::Parser::MTC_Stopped);
321                 reset();
322                 DEBUG_TRACE (DEBUG::MTC, "MTC not seen for 1/4 second - reset\n");
323                 return false;
324         }
325
326         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::speed_and_position %1 %2\n", last.speed, last.position));
327
328         if (last.speed == 0.0f) {
329
330                 elapsed = 0;
331
332         } else {
333
334                 /* scale elapsed time by the current MTC speed */
335
336                 if (last.timestamp && (now > last.timestamp)) {
337                         elapsed = (nframes_t) floor (speed * (now - last.timestamp));
338                 } else {
339                         elapsed = 0; /* XXX is this right? */
340                 }
341         }
342
343         /* now add the most recent timecode value plus the estimated elapsed interval */
344
345         pos =  elapsed + last.position;
346         speed = last.speed;
347
348         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::speed_and_position FINAL %1 %2\n", last.speed, pos));
349
350         return true;
351 }
352
353 ARDOUR::nframes_t
354 MTC_Slave::resolution() const
355 {
356         return (nframes_t) session.frames_per_timecode_frame();
357 }
358
359 void
360 MTC_Slave::reset ()
361 {
362         /* XXX massive thread safety issue here. MTC could
363            be being updated as we call this. but this
364            supposed to be a realtime-safe call.
365         */
366
367         port->input()->reset_mtc_state ();
368
369         last_inbound_frame = 0;
370         current.guard1++;
371         current.position = 0;
372         current.timestamp = 0;
373         current.speed = 0;
374         current.guard2++;
375         accumulator_index = 0;
376         have_first_accumulated_speed = false;
377 }