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