4ca86236b737c113f8587bdffabfad3f30b61d43
[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         did_reset_tc_format = false;
48         
49         last_mtc_fps_byte = session.get_mtc_timecode_bits ();
50
51         rebind (p);
52         reset ();
53 }
54
55 MTC_Slave::~MTC_Slave()
56 {
57         if (did_reset_tc_format) {
58                 session.config.set_timecode_format (saved_tc_format);
59         }
60 }
61
62 void
63 MTC_Slave::rebind (MIDI::Port& p)
64 {
65         for (vector<sigc::connection>::iterator i = connections.begin(); i != connections.end(); ++i) {
66                 (*i).disconnect ();
67         }
68
69         port = &p;
70
71         connections.push_back (port->input()->mtc_time.connect (mem_fun (*this, &MTC_Slave::update_mtc_time)));
72         connections.push_back (port->input()->mtc_qtr.connect (mem_fun (*this, &MTC_Slave::update_mtc_qtr)));
73         connections.push_back (port->input()->mtc_status.connect (mem_fun (*this, &MTC_Slave::update_mtc_status)));
74 }
75
76 void
77 MTC_Slave::update_mtc_qtr (Parser& /*p*/, int which_qtr, nframes_t now)
78 {
79         DEBUG_TRACE (DEBUG::MTC, string_compose ("qtr frame %1 at %2, valid-for-time? %3\n", which_qtr, now, qtr_frame_messages_valid_for_time));
80
81         if (qtr_frame_messages_valid_for_time) {
82
83                 if (which_qtr != 7) {
84
85                         /* leave position and speed updates for the last
86                            qtr frame message of the 8 to be taken
87                            care of in update_mtc_time(), invoked
88                            by the Parser right after this.
89                         */
90
91                         nframes_t qtr;
92                         
93                         qtr = (long) (session.frames_per_timecode_frame() / 4);
94                         mtc_frame += qtr;
95                         
96                         double speed = compute_apparent_speed (now);
97                         
98                         current.guard1++;
99                         current.position = mtc_frame;
100                         current.timestamp = now;
101                         current.speed = speed;
102                         current.guard2++;
103                 }
104
105                 last_inbound_frame = now;
106         }
107 }
108
109 void
110 MTC_Slave::update_mtc_time (const byte *msg, bool was_full, nframes_t now)
111 {
112         /* "now" can be zero if this is called from a context where we do not have or do not want
113            to use a timestamp indicating when this MTC time was received.
114         */
115
116         Timecode::Time timecode;
117         TimecodeFormat tc_format;
118         bool reset_tc = true;
119         
120         DEBUG_TRACE (DEBUG::MTC, string_compose ("full mtc time known at %1, full ? %2\n", now, was_full));
121         
122         timecode.hours = msg[3];
123         timecode.minutes = msg[2];
124         timecode.seconds = msg[1];
125         timecode.frames = msg[0];
126
127         last_mtc_fps_byte = msg[4];
128
129         switch (msg[4]) {
130         case MTC_24_FPS:
131                 timecode.rate = 24;
132                 timecode.drop = false;
133                 tc_format = timecode_24;
134                 can_notify_on_unknown_rate = true;
135                 break;
136         case MTC_25_FPS:
137                 timecode.rate = 25;
138                 timecode.drop = false;
139                 tc_format = timecode_25;
140                 can_notify_on_unknown_rate = true;
141                 break;
142         case MTC_30_FPS_DROP:
143                 timecode.rate = 30;
144                 timecode.drop = true;
145                 tc_format = timecode_30drop;
146                 can_notify_on_unknown_rate = true;
147                 break;
148         case MTC_30_FPS:
149                 timecode.rate = 30;
150                 timecode.drop = false;
151                 can_notify_on_unknown_rate = true;
152                 tc_format = timecode_30;
153                 break;
154         default:
155                 /* throttle error messages about unknown MTC rates */
156                 if (can_notify_on_unknown_rate) {
157                         error << string_compose (_("Unknown rate/drop value %1 in incoming MTC stream, session values used instead"),
158                                                  (int) msg[4])
159                               << endmsg;
160                         can_notify_on_unknown_rate = false;
161                 }
162                 timecode.rate = session.timecode_frames_per_second();
163                 timecode.drop = session.timecode_drop_frames();
164                 reset_tc = false;
165         }
166
167         if (reset_tc) {
168                 if (!did_reset_tc_format) {
169                         saved_tc_format = session.config.get_timecode_format();
170                         did_reset_tc_format = true;
171                 }
172                 session.config.set_timecode_format (tc_format);
173         }
174
175         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC time timestamp = %1 TC %2 = frame %3 (from full message ? %4)\n", 
176                                                  now, timecode, mtc_frame, was_full));
177
178         if (was_full) {
179
180                 session.timecode_to_sample (timecode, mtc_frame, true, false);
181                 session.request_locate (mtc_frame, false);
182                 session.request_transport_speed (0);
183                 update_mtc_status (MIDI::Parser::MTC_Stopped);
184
185                 reset ();
186
187         } else {
188
189                         
190                 /* we've had the first set of 8 qtr frame messages, determine position
191                            and allow continuing qtr frame messages to provide position
192                            and speed information.
193                 */
194                 
195                 qtr_frame_messages_valid_for_time = true;
196                 session.timecode_to_sample (timecode, mtc_frame, true, false);
197                 
198                 /* We received the last quarter frame 7 quarter frames (1.75 mtc
199                    frames) after the instance when the contents of the mtc quarter
200                    frames were decided. Add time to compensate for the elapsed 1.75
201                    frames. Also compensate for audio latency.
202                 */
203                 
204                 mtc_frame += (long) (1.75 * session.frames_per_timecode_frame()) + session.worst_output_latency();
205
206                 if (now) {
207                         double speed = compute_apparent_speed (now);
208                         
209                         current.guard1++;
210                         current.position = mtc_frame;
211                         current.timestamp = now;
212                         current.speed = speed;
213                         current.guard2++;
214                 }
215         }
216
217         if (now) {
218                 last_inbound_frame = now;
219         }
220 }
221
222 double
223 MTC_Slave::compute_apparent_speed (nframes64_t now)
224 {
225         if (current.timestamp != 0) {
226                 
227                 double speed = (double) ((mtc_frame - current.position) / (double) (now - current.timestamp));
228                 DEBUG_TRACE (DEBUG::MTC, string_compose ("instantaneous speed = %1 from %2 / %3\n",
229                                                          speed, mtc_frame - current.position, now - current.timestamp));
230                 
231                 /* crude low pass filter/smoother for speed */
232
233                 accumulator[accumulator_index++] = speed;
234                 
235                 if (accumulator_index >= accumulator_size) {
236                         have_first_accumulated_speed = true;
237                         accumulator_index = 0;
238                 }
239                 
240                 if (have_first_accumulated_speed) {
241                         double total = 0;
242                         
243                         for (int32_t i = 0; i < accumulator_size; ++i) {
244                                 total += accumulator[i];
245                         }
246                         
247                         speed = total / accumulator_size;
248                         DEBUG_TRACE (DEBUG::MTC, string_compose ("speed smoothed to %1\n", speed));
249                 } 
250
251                 return speed;
252                 
253         } else {
254                 
255                 return 0;
256         }
257 }
258
259 void
260 MTC_Slave::handle_locate (const MIDI::byte* mmc_tc)
261 {
262         MIDI::byte mtc[5];
263
264         mtc[4] = last_mtc_fps_byte;
265         mtc[3] = mmc_tc[0] & 0xf; /* hrs only */
266         mtc[2] = mmc_tc[1];
267         mtc[1] = mmc_tc[2];
268         mtc[0] = mmc_tc[3];
269
270         update_mtc_time (mtc, true, 0);
271 }
272
273 void
274 MTC_Slave::update_mtc_status (MIDI::Parser::MTC_Status status)
275 {
276         /* XXX !!! thread safety ... called from MIDI I/O context
277            and process() context (via ::speed_and_position())
278         */
279
280         switch (status) {
281         case MTC_Stopped:
282                 mtc_frame = 0;
283
284                 current.guard1++;
285                 current.position = mtc_frame;
286                 current.timestamp = 0;
287                 current.speed = 0;
288                 current.guard2++;
289
290                 break;
291
292         case MTC_Forward:
293                 mtc_frame = 0;
294
295                 current.guard1++;
296                 current.position = mtc_frame;
297                 current.timestamp = 0;
298                 current.speed = 0;
299                 current.guard2++;
300
301                 break;
302
303         case MTC_Backward:
304                 mtc_frame = 0;
305
306                 current.guard1++;
307                 current.position = mtc_frame;
308                 current.timestamp = 0;
309                 current.speed = 0;
310                 current.guard2++;
311
312                 break;
313         }
314 }
315
316 void
317 MTC_Slave::read_current (SafeTime *st) const
318 {
319         int tries = 0;
320
321         do {
322                 if (tries == 10) {
323                         error << _("MTC Slave: atomic read of current time failed, sleeping!") << endmsg;
324                         usleep (20);
325                         tries = 0;
326                 }
327                 *st = current;
328                 tries++;
329
330         } while (st->guard1 != st->guard2);
331 }
332
333 bool
334 MTC_Slave::locked () const
335 {
336         return port->input()->mtc_locked();
337 }
338
339 bool
340 MTC_Slave::ok() const
341 {
342         return true;
343 }
344
345 bool
346 MTC_Slave::speed_and_position (double& speed, nframes64_t& pos)
347 {
348         nframes64_t now = session.engine().frame_time();
349         SafeTime last;
350         nframes_t elapsed;
351
352         read_current (&last);
353
354         if (last.timestamp == 0) {
355                 speed = 0;
356                 pos = last.position;
357                 DEBUG_TRACE (DEBUG::MTC, string_compose ("first call to MTC_Slave::speed_and_position, pos = %1\n", last.position));
358                 return true;
359         }
360
361         /* no timecode for 1/4 second ? conclude that its stopped */
362
363         if (last_inbound_frame && now > last_inbound_frame && now - last_inbound_frame > session.frame_rate() / 4) {
364                 speed = 0;
365                 pos = last.position;
366                 session.request_locate (pos, false);
367                 session.request_transport_speed (0);
368                 update_mtc_status (MIDI::Parser::MTC_Stopped);
369                 reset();
370                 DEBUG_TRACE (DEBUG::MTC, "MTC not seen for 1/4 second - reset\n");
371                 return false;
372         }
373
374         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::speed_and_position %1 %2\n", last.speed, last.position));
375
376         if (last.speed == 0.0f) {
377
378                 elapsed = 0;
379
380         } else {
381
382                 /* scale elapsed time by the current MTC speed */
383
384                 if (last.timestamp && (now > last.timestamp)) {
385                         elapsed = (nframes_t) floor (last.speed * (now - last.timestamp));
386                         DEBUG_TRACE (DEBUG::MTC, string_compose ("last timecode received @ %1, now = %2, elapsed frames = %3 w/speed= %4\n",
387                                                                  last.timestamp, now, elapsed, speed));
388                 } else {
389                         elapsed = 0; /* XXX is this right? */
390                 }
391         }
392
393         /* now add the most recent timecode value plus the estimated elapsed interval */
394
395         pos =  elapsed + last.position;
396         speed = last.speed;
397
398         DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::speed_and_position FINAL %1 %2\n", last.speed, pos));
399
400         return true;
401 }
402
403 ARDOUR::nframes_t
404 MTC_Slave::resolution() const
405 {
406         return (nframes_t) session.frames_per_timecode_frame();
407 }
408
409 void
410 MTC_Slave::reset ()
411 {
412         /* XXX massive thread safety issue here. MTC could
413            be being updated as we call this. but this
414            supposed to be a realtime-safe call.
415         */
416
417         port->input()->reset_mtc_state ();
418
419         last_inbound_frame = 0;
420         current.guard1++;
421         current.position = 0;
422         current.timestamp = 0;
423         current.speed = 0;
424         current.guard2++;
425         accumulator_index = 0;
426         have_first_accumulated_speed = false;
427         qtr_frame_messages_valid_for_time = false;
428 }