2 Copyright (C) 2002-4 Paul Davis
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.
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.
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.
22 #include <sys/types.h>
24 #include "pbd/error.h"
25 #include "pbd/failed_constructor.h"
26 #include "pbd/pthread_utils.h"
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"
38 using namespace ARDOUR;
43 MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
46 can_notify_on_unknown_rate = true;
47 did_reset_tc_format = false;
49 last_mtc_fps_byte = session.get_mtc_timecode_bits ();
55 MTC_Slave::~MTC_Slave()
57 if (did_reset_tc_format) {
58 session.config.set_timecode_format (saved_tc_format);
63 MTC_Slave::rebind (MIDI::Port& p)
65 for (vector<sigc::connection>::iterator i = connections.begin(); i != connections.end(); ++i) {
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)));
77 MTC_Slave::update_mtc_qtr (Parser& /*p*/, int which_qtr, nframes_t now)
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));
81 if (qtr_frame_messages_valid_for_time) {
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.
93 qtr = (long) (session.frames_per_timecode_frame() / 4);
96 double speed = compute_apparent_speed (now);
99 current.position = mtc_frame;
100 current.timestamp = now;
101 current.speed = speed;
105 last_inbound_frame = now;
110 MTC_Slave::update_mtc_time (const byte *msg, bool was_full, nframes_t now)
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.
116 Timecode::Time timecode;
117 TimecodeFormat tc_format;
118 bool reset_tc = true;
120 DEBUG_TRACE (DEBUG::MTC, string_compose ("full mtc time known at %1, full ? %2\n", now, was_full));
122 timecode.hours = msg[3];
123 timecode.minutes = msg[2];
124 timecode.seconds = msg[1];
125 timecode.frames = msg[0];
127 last_mtc_fps_byte = msg[4];
132 timecode.drop = false;
133 tc_format = timecode_24;
134 can_notify_on_unknown_rate = true;
138 timecode.drop = false;
139 tc_format = timecode_25;
140 can_notify_on_unknown_rate = true;
142 case MTC_30_FPS_DROP:
144 timecode.drop = true;
145 tc_format = timecode_30drop;
146 can_notify_on_unknown_rate = true;
150 timecode.drop = false;
151 can_notify_on_unknown_rate = true;
152 tc_format = timecode_30;
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"),
160 can_notify_on_unknown_rate = false;
162 timecode.rate = session.timecode_frames_per_second();
163 timecode.drop = session.timecode_drop_frames();
168 if (!did_reset_tc_format) {
169 saved_tc_format = session.config.get_timecode_format();
170 did_reset_tc_format = true;
172 session.config.set_timecode_format (tc_format);
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));
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);
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.
195 qtr_frame_messages_valid_for_time = true;
196 session.timecode_to_sample (timecode, mtc_frame, true, false);
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.
204 mtc_frame += (long) (1.75 * session.frames_per_timecode_frame()) + session.worst_output_latency();
207 double speed = compute_apparent_speed (now);
210 current.position = mtc_frame;
211 current.timestamp = now;
212 current.speed = speed;
218 last_inbound_frame = now;
223 MTC_Slave::compute_apparent_speed (nframes64_t now)
225 if (current.timestamp != 0) {
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));
231 /* crude low pass filter/smoother for speed */
233 accumulator[accumulator_index++] = speed;
235 if (accumulator_index >= accumulator_size) {
236 have_first_accumulated_speed = true;
237 accumulator_index = 0;
240 if (have_first_accumulated_speed) {
243 for (int32_t i = 0; i < accumulator_size; ++i) {
244 total += accumulator[i];
247 speed = total / accumulator_size;
248 DEBUG_TRACE (DEBUG::MTC, string_compose ("speed smoothed to %1\n", speed));
260 MTC_Slave::handle_locate (const MIDI::byte* mmc_tc)
264 mtc[4] = last_mtc_fps_byte;
265 mtc[3] = mmc_tc[0] & 0xf; /* hrs only */
270 update_mtc_time (mtc, true, 0);
274 MTC_Slave::update_mtc_status (MIDI::Parser::MTC_Status status)
276 /* XXX !!! thread safety ... called from MIDI I/O context
277 and process() context (via ::speed_and_position())
285 current.position = mtc_frame;
286 current.timestamp = 0;
296 current.position = mtc_frame;
297 current.timestamp = 0;
307 current.position = mtc_frame;
308 current.timestamp = 0;
317 MTC_Slave::read_current (SafeTime *st) const
323 error << _("MTC Slave: atomic read of current time failed, sleeping!") << endmsg;
330 } while (st->guard1 != st->guard2);
334 MTC_Slave::locked () const
336 return port->input()->mtc_locked();
340 MTC_Slave::ok() const
346 MTC_Slave::speed_and_position (double& speed, nframes64_t& pos)
348 nframes64_t now = session.engine().frame_time();
352 read_current (&last);
354 if (last.timestamp == 0) {
357 DEBUG_TRACE (DEBUG::MTC, string_compose ("first call to MTC_Slave::speed_and_position, pos = %1\n", last.position));
361 /* no timecode for 1/4 second ? conclude that its stopped */
363 if (last_inbound_frame && now > last_inbound_frame && now - last_inbound_frame > session.frame_rate() / 4) {
366 session.request_locate (pos, false);
367 session.request_transport_speed (0);
368 update_mtc_status (MIDI::Parser::MTC_Stopped);
370 DEBUG_TRACE (DEBUG::MTC, "MTC not seen for 1/4 second - reset\n");
374 DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::speed_and_position %1 %2\n", last.speed, last.position));
376 if (last.speed == 0.0f) {
382 /* scale elapsed time by the current MTC speed */
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));
389 elapsed = 0; /* XXX is this right? */
393 /* now add the most recent timecode value plus the estimated elapsed interval */
395 pos = elapsed + last.position;
398 DEBUG_TRACE (DEBUG::MTC, string_compose ("MTC::speed_and_position FINAL %1 %2\n", last.speed, pos));
404 MTC_Slave::resolution() const
406 return (nframes_t) session.frames_per_timecode_frame();
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.
417 port->input()->reset_mtc_state ();
419 last_inbound_frame = 0;
421 current.position = 0;
422 current.timestamp = 0;
425 accumulator_index = 0;
426 have_first_accumulated_speed = false;
427 qtr_frame_messages_valid_for_time = false;