Fix broken whitespace. I'd apologize for the compile times if it was my fault :D
[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
25 #include "pbd/error.h"
26 #include "pbd/enumwriter.h"
27 #include "pbd/failed_constructor.h"
28 #include "pbd/pthread_utils.h"
29
30 #include "midi++/port.h"
31 #include "ardour/debug.h"
32 #include "ardour/slave.h"
33 #include "ardour/session.h"
34 #include "ardour/audioengine.h"
35 #include "ardour/pi_controller.h"
36
37 #include "i18n.h"
38
39 using namespace std;
40 using namespace ARDOUR;
41 using namespace MIDI;
42 using namespace PBD;
43
44 /* length (in timecode frames) of the "window" that we consider legal given receipt of
45    a given timecode position. Ardour will try to chase within this window, and will
46    stop+locate+wait+chase if timecode arrives outside of it. The window extends entirely
47    in the current direction of motion, so if any timecode arrives that is before the most
48    recently received position (and without the direction of timecode reversing too), we
49    will stop+locate+wait+chase.
50 */
51
52 const int MTC_Slave::frame_tolerance = 2;
53
54 MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
55         : session (s)
56 {
57         can_notify_on_unknown_rate = true;
58         did_reset_tc_format = false;
59         reset_pending = 0;
60         reset_position = false;
61
62         pic = new PIChaser();
63
64         last_mtc_fps_byte = session.get_mtc_timecode_bits ();
65         mtc_frame = 0;
66
67         speed_accumulator_size = 16;
68         speed_accumulator = new double[speed_accumulator_size];
69
70         rebind (p);
71         reset (true);
72 }
73
74 MTC_Slave::~MTC_Slave()
75 {
76         if (did_reset_tc_format) {
77                 session.config.set_timecode_format (saved_tc_format);
78         }
79
80         delete pic;
81         delete [] speed_accumulator;
82 }
83
84 bool
85 MTC_Slave::give_slave_full_control_over_transport_speed() const
86 {
87         return true; // for PiC control */
88         // return false; // for Session-level computed varispeed
89 }
90
91 void
92 MTC_Slave::rebind (MIDI::Port& p)
93 {
94         port_connections.drop_connections ();
95
96         port = &p;
97
98         port->parser()->mtc_time.connect_same_thread (port_connections,  boost::bind (&MTC_Slave::update_mtc_time, this, _1, _2, _3));
99         port->parser()->mtc_qtr.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_qtr, this, _1, _2, _3));
100         port->parser()->mtc_status.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_status, this, _1));
101 }
102
103 void
104 MTC_Slave::update_mtc_qtr (Parser& /*p*/, int which_qtr, framepos_t now)
105 {
106         DEBUG_TRACE (DEBUG::MTC, string_compose ("qtr frame %1 at %2\n", which_qtr, now));
107         maybe_reset ();
108         last_inbound_frame = now;
109 }
110
111 void
112 MTC_Slave::update_mtc_time (const byte *msg, bool was_full, framepos_t now)
113 {
114         /* "now" can be zero if this is called from a context where we do not have or do not want
115            to use a timestamp indicating when this MTC time was received. example: when we received
116            a locate command via MMC.
117         */
118
119         if (now) {
120                 maybe_reset ();
121         }
122
123         Timecode::Time timecode;
124         TimecodeFormat tc_format;
125         bool reset_tc = true;
126         framepos_t window_root = -1;
127
128         DEBUG_TRACE (DEBUG::MTC, string_compose ("full mtc time known at %1, full ? %2\n", now, was_full));
129
130         timecode.hours = msg[3];
131         timecode.minutes = msg[2];
132         timecode.seconds = msg[1];
133         timecode.frames = msg[0];
134
135         last_mtc_fps_byte = msg[4];
136
137         switch (msg[4]) {
138         case MTC_24_FPS:
139                 timecode.rate = 24;
140                 timecode.drop = false;
141                 tc_format = timecode_24;
142                 can_notify_on_unknown_rate = true;
143                 break;
144         case MTC_25_FPS:
145                 timecode.rate = 25;
146                 timecode.drop = false;
147                 tc_format = timecode_25;
148                 can_notify_on_unknown_rate = true;
149                 break;
150         case MTC_30_FPS_DROP:
151                 timecode.rate = 30;
152                 timecode.drop = true;
153                 tc_format = timecode_30drop;
154                 can_notify_on_unknown_rate = true;
155                 break;
156         case MTC_30_FPS:
157                 timecode.rate = 30;
158                 timecode.drop = false;
159                 can_notify_on_unknown_rate = true;
160                 tc_format = timecode_30;
161                 break;
162         default:
163                 /* throttle error messages about unknown MTC rates */
164                 if (can_notify_on_unknown_rate) {
165                         error << string_compose (_("Unknown rate/drop value %1 in incoming MTC stream, session values used instead"),
166                                                  (int) msg[4])
167                               << endmsg;
168                         can_notify_on_unknown_rate = false;
169                 }
170                 timecode.rate = session.timecode_frames_per_second();
171                 timecode.drop = session.timecode_drop_frames();
172                 reset_tc = false;
173         }
174
175         if (reset_tc) {
176                 if (!did_reset_tc_format) {
177                         saved_tc_format = session.config.get_timecode_format();
178                         did_reset_tc_format = true;
179                 }
180                 session.config.set_timecode_format (tc_format);
181         }
182
183         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC time timestamp = %1 TC %2 = frame %3 (from full message ? %4)\n",
184                                                  now, timecode, mtc_frame, was_full));
185
186         if (was_full || outside_window (mtc_frame)) {
187
188                 session.timecode_to_sample (timecode, mtc_frame, true, false);
189                 session.request_locate (mtc_frame, false);
190                 session.request_transport_speed (0);
191                 update_mtc_status (MIDI::MTC_Stopped);
192                 reset (false);
193                 reset_window (mtc_frame);
194
195         } else {
196
197                 /* we've had the first set of 8 qtr frame messages, determine position
198                    and allow continuing qtr frame messages to provide position
199                    and speed information.
200                 */
201
202                 /* do a careful conversion of the timecode value to a position
203                    so that we take drop/nondrop and all that nonsense into
204                    consideration.
205                 */
206
207                 session.timecode_to_sample (timecode, mtc_frame, true, false);
208
209                 /* We received the last quarter frame 7 quarter frames (1.75 mtc
210                    frames) after the instance when the contents of the mtc quarter
211                    frames were decided. Add time to compensate for the elapsed 1.75
212                    frames. Also compensate for audio latency.
213                 */
214
215                 mtc_frame += (long) (1.75 * session.frames_per_timecode_frame()) + session.worst_playback_latency();
216
217
218                 if (now) {
219
220                         if (last_mtc_timestamp == 0) {
221
222                                 last_mtc_timestamp = now;
223                                 last_mtc_frame = mtc_frame;
224
225                         } else {
226
227                                 if (give_slave_full_control_over_transport_speed()) {
228                                         /* PIC
229                                          *
230                                          * its not the average, but we will assign it to current.speed below
231                                          */
232
233                                     static framepos_t last_seen_timestamp = 0;
234                                     static framepos_t last_seen_position = 0;
235
236                                     if ((now - last_seen_timestamp) < 300) {
237                                         mtc_frame = (mtc_frame + last_seen_position)/2;
238                                     }
239
240                                     last_seen_timestamp = now;
241                                     last_seen_position = mtc_frame;
242
243
244
245                                 } else {
246
247                                         /* Non-PiC
248                                          */
249
250                                         framepos_t time_delta = (now - last_mtc_timestamp);
251
252                                         if (time_delta != 0) {
253                                                 double apparent_speed = (mtc_frame - last_mtc_frame) / (double) (time_delta);
254
255                                                 process_apparent_speed (apparent_speed);
256                                                 DEBUG_TRACE (DEBUG::Slave, string_compose ("apparent speed was %1 average is now %2\n", apparent_speed, average_speed));
257                                         } else {
258                                                 DEBUG_TRACE (DEBUG::Slave, string_compose ("no apparent calc, average is %1\n", average_speed));
259                                         }
260
261                                         /* every second, recalibrate the starting point for the speed measurement */
262                                         if (mtc_frame - last_mtc_frame > session.frame_rate()) {
263                                                 last_mtc_timestamp = now;
264                                                 last_mtc_frame = mtc_frame;
265                                         }
266                                 }
267                         }
268
269                         current.guard1++;
270                         current.position = mtc_frame;
271                         current.timestamp = now;
272                         current.speed = average_speed;
273                         current.guard2++;
274                         window_root = mtc_frame;
275                 }
276         }
277
278         if (now) {
279                 last_inbound_frame = now;
280         }
281
282         if (window_root >= 0) {
283                 reset_window (window_root);
284         }
285 }
286
287 void
288 MTC_Slave::process_apparent_speed (double this_speed)
289 {
290         DEBUG_TRACE (DEBUG::MTC, string_compose ("speed cnt %1 sz %2 have %3\n", speed_accumulator_cnt, speed_accumulator_size, have_first_speed_accumulator));
291
292         /* clamp to an expected range */
293
294         if (this_speed > 4.0 || this_speed < -4.0) {
295                 this_speed = average_speed;
296         }
297
298         if (speed_accumulator_cnt >= speed_accumulator_size) {
299                 have_first_speed_accumulator = true;
300                 speed_accumulator_cnt = 0;
301         }
302
303         speed_accumulator[speed_accumulator_cnt++] = this_speed;
304
305         if (have_first_speed_accumulator) {
306                 average_speed = 0.0;
307                 for (size_t i = 0; i < speed_accumulator_size; ++i) {
308                         average_speed += speed_accumulator[i];
309                 }
310                 average_speed /= speed_accumulator_size;
311         }
312 }
313
314 void
315 MTC_Slave::handle_locate (const MIDI::byte* mmc_tc)
316 {
317         MIDI::byte mtc[5];
318
319         mtc[4] = last_mtc_fps_byte;
320         mtc[3] = mmc_tc[0] & 0xf; /* hrs only */
321         mtc[2] = mmc_tc[1];
322         mtc[1] = mmc_tc[2];
323         mtc[0] = mmc_tc[3];
324
325         update_mtc_time (mtc, true, 0);
326 }
327
328 void
329 MTC_Slave::update_mtc_status (MIDI::MTC_Status status)
330 {
331         /* XXX !!! thread safety ... called from MIDI I/O context
332            and process() context (via ::speed_and_position())
333         */
334
335         switch (status) {
336         case MTC_Stopped:
337                 current.guard1++;
338                 current.position = mtc_frame;
339                 current.timestamp = 0;
340                 current.speed = 0;
341                 current.guard2++;
342
343                 break;
344
345         case MTC_Forward:
346                 current.guard1++;
347                 current.position = mtc_frame;
348                 current.timestamp = 0;
349                 current.speed = 0;
350                 current.guard2++;
351                 break;
352
353         case MTC_Backward:
354                 current.guard1++;
355                 current.position = mtc_frame;
356                 current.timestamp = 0;
357                 current.speed = 0;
358                 current.guard2++;
359                 break;
360         }
361
362 }
363
364 void
365 MTC_Slave::read_current (SafeTime *st) const
366 {
367         int tries = 0;
368
369         do {
370                 if (tries == 10) {
371                         error << _("MTC Slave: atomic read of current time failed, sleeping!") << endmsg;
372                         usleep (20);
373                         tries = 0;
374                 }
375                 *st = current;
376                 tries++;
377
378         } while (st->guard1 != st->guard2);
379 }
380
381 bool
382 MTC_Slave::locked () const
383 {
384         return port->parser()->mtc_locked();
385 }
386
387 bool
388 MTC_Slave::ok() const
389 {
390         return true;
391 }
392
393 bool
394 MTC_Slave::speed_and_position (double& speed, framepos_t& pos)
395 {
396         framepos_t now = session.engine().frame_time();
397         SafeTime last;
398         framecnt_t elapsed;
399         bool in_control = false;
400
401         read_current (&last);
402
403         if (last.timestamp == 0) {
404                 speed = 0;
405                 pos = last.position;
406                 DEBUG_TRACE (DEBUG::MTC, string_compose ("first call to MTC_Slave::speed_and_position, pos = %1\n", last.position));
407                 return true;
408         }
409
410         /* no timecode for 1/4 second ? conclude that its stopped */
411
412         if (last_inbound_frame && now > last_inbound_frame && now - last_inbound_frame > session.frame_rate() / 4) {
413                 speed = 0;
414                 pos = last.position;
415                 session.request_locate (pos, false);
416                 session.request_transport_speed (0);
417                 queue_reset (false);
418                 DEBUG_TRACE (DEBUG::MTC, "MTC not seen for 1/4 second - reset pending\n");
419                 return false;
420         }
421
422         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::speed_and_position %1 %2\n", last.speed, last.position));
423
424         if (give_slave_full_control_over_transport_speed()) {
425                 in_control = (session.slave_state() == Session::Running);
426                 framepos_t pic_want_locate = 0;
427                 //framepos_t slave_pos = session.audible_frame();
428                 framepos_t slave_pos = session.transport_frame();
429                 static double average_speed = 0;
430
431                 framepos_t ref_now = session.engine().frame_time_at_cycle_start();
432                 average_speed = pic->get_ratio (last.timestamp, last.position, ref_now, slave_pos, in_control, session.engine().frames_per_cycle());
433
434                 pic_want_locate = pic->want_locate();
435
436                 if (in_control && pic_want_locate) {
437                         last.speed = average_speed + (double) (pic_want_locate - session.transport_frame()) / (double)session.get_block_size();
438                         std::cout << "locate req " << pic_want_locate << " speed: " << average_speed << "\n";
439                 } else {
440                         last.speed = average_speed;
441                 }
442         }
443
444         if (last.speed == 0.0f) {
445
446                 elapsed = 0;
447
448         } else {
449
450                 /* scale elapsed time by the current MTC speed */
451
452                 if (last.timestamp && (now > last.timestamp)) {
453                         elapsed = (framecnt_t) floor (last.speed * (now - last.timestamp));
454                         DEBUG_TRACE (DEBUG::MTC, string_compose ("last timecode received @ %1, now = %2, elapsed frames = %3 w/speed= %4\n",
455                                                                  last.timestamp, now, elapsed, last.speed));
456                 } else {
457                         elapsed = 0; /* XXX is this right? */
458                 }
459         }
460
461         /* now add the most recent timecode value plus the estimated elapsed interval */
462
463         if (in_control) {
464                 pos = session.transport_frame();
465         } else {
466                 pos = last.position + elapsed;
467         }
468
469         speed = last.speed;
470
471         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::speed_and_position FINAL %1 %2\n", last.speed, pos));
472
473
474         DEBUG_TRACE (DEBUG::MTC, string_compose ("last = %1 elapsed = %2 pos = %3 speed = %4\n", last.position, elapsed, pos, speed));
475
476         return true;
477 }
478
479 ARDOUR::framecnt_t
480 MTC_Slave::resolution () const
481 {
482         return (framecnt_t) session.frames_per_timecode_frame();
483 }
484
485 void
486 MTC_Slave::queue_reset (bool reset_pos)
487 {
488         Glib::Mutex::Lock lm (reset_lock);
489         reset_pending++;
490         if (reset_pos) {
491                 reset_position = true;
492         }
493 }
494
495 void
496 MTC_Slave::maybe_reset ()
497 {
498         Glib::Mutex::Lock lm (reset_lock);
499
500         if (reset_pending) {
501                 reset (reset_position);
502                 reset_pending = 0;
503                 reset_position = false;
504         }
505 }
506
507 void
508 MTC_Slave::reset (bool with_position)
509 {
510         if (with_position) {
511                 last_inbound_frame = 0;
512                 current.guard1++;
513                 current.position = 0;
514                 current.timestamp = 0;
515                 current.speed = 0;
516                 current.guard2++;
517         } else {
518                 last_inbound_frame = 0;
519                 current.guard1++;
520                 current.timestamp = 0;
521                 current.speed = 0;
522                 current.guard2++;
523         }
524
525         window_begin = 0;
526         window_end = 0;
527         last_mtc_frame = 0;
528         last_mtc_timestamp = 0;
529
530         average_speed = 0;
531         have_first_speed_accumulator = false;
532         speed_accumulator_cnt = 0;
533
534         pic->reset();
535 }
536
537 void
538 MTC_Slave::reset_window (framepos_t root)
539 {
540
541         /* if we're waiting for the master to catch us after seeking ahead, keep the window
542            of acceptable MTC frames wide open. otherwise, shrink it down to just 2 video frames
543            ahead of the window root (taking direction into account).
544         */
545
546         switch (port->parser()->mtc_running()) {
547         case MTC_Forward:
548                 window_begin = root;
549                 if (session.slave_state() == Session::Running) {
550                         window_end = root + (session.frames_per_timecode_frame() * frame_tolerance);
551                 } else {
552                         window_end = root + seekahead_distance ();
553                 }
554                 break;
555
556         case MTC_Backward:
557                 if (session.slave_state() == Session::Running) {
558                         framecnt_t const d = session.frames_per_timecode_frame() * frame_tolerance;
559                         if (root > d) {
560                                 window_begin = root - d;
561                                 window_end = root;
562                         } else {
563                                 window_begin = 0;
564                         }
565                 } else {
566                         framecnt_t const d = seekahead_distance ();
567                         if (root > d) {
568                                 window_begin = root - d;
569                         } else {
570                                 window_begin = 0;
571                         }
572                 }
573                 window_end = root;
574                 break;
575
576         default:
577                 /* do nothing */
578                 break;
579         }
580
581         DEBUG_TRACE (DEBUG::MTC, string_compose ("legal MTC window now %1 .. %2\n", window_begin, window_end));
582 }
583
584 ARDOUR::framecnt_t
585 MTC_Slave::seekahead_distance () const
586 {
587         /* 1 second */
588         return session.frame_rate();
589 }
590
591 bool
592 MTC_Slave::outside_window (framepos_t pos) const
593 {
594         return ((pos < window_begin) || (pos > window_end));
595 }