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