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/slave.h>
30 #include <ardour/session.h>
31 #include <ardour/audioengine.h>
32 #include <ardour/cycles.h>
36 using namespace ARDOUR;
41 MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
44 can_notify_on_unknown_rate = true;
50 MTC_Slave::~MTC_Slave()
55 MTC_Slave::rebind (MIDI::Port& p)
57 for (vector<sigc::connection>::iterator i = connections.begin(); i != connections.end(); ++i) {
63 connections.push_back (port->input()->mtc_time.connect (mem_fun (*this, &MTC_Slave::update_mtc_time)));
64 connections.push_back (port->input()->mtc_qtr.connect (mem_fun (*this, &MTC_Slave::update_mtc_qtr)));
65 connections.push_back (port->input()->mtc_status.connect (mem_fun (*this, &MTC_Slave::update_mtc_status)));
69 MTC_Slave::update_mtc_qtr (Parser& p)
71 cycles_t cnow = get_cycles ();
72 nframes_t now = session.engine().frame_time();
74 static cycles_t last_qtr = 0;
76 qtr = (long) (session.frames_per_smpte_frame() / 4);
81 current.position = mtc_frame;
82 current.timestamp = now;
85 last_inbound_frame = now;
89 MTC_Slave::update_mtc_time (const byte *msg, bool was_full)
91 nframes_t now = session.engine().frame_time();
95 smpte.minutes = msg[2];
96 smpte.seconds = msg[1];
97 smpte.frames = msg[0];
103 can_notify_on_unknown_rate = true;
108 can_notify_on_unknown_rate = true;
110 case MTC_30_FPS_DROP:
113 can_notify_on_unknown_rate = true;
118 can_notify_on_unknown_rate = true;
121 /* throttle error messages about unknown MTC rates */
122 if (can_notify_on_unknown_rate) {
123 error << _("Unknown rate/drop value in incoming MTC stream, session values used instead") << endmsg;
124 can_notify_on_unknown_rate = false;
126 smpte.rate = session.smpte_frames_per_second();
127 smpte.drop = session.smpte_drop_frames();
130 session.smpte_to_sample (smpte, mtc_frame, true, false);
135 current.position = mtc_frame;
136 current.timestamp = 0;
139 session.request_locate (mtc_frame, false);
140 session.request_transport_speed (0);
141 update_mtc_status (MIDI::Parser::MTC_Stopped);
147 /* We received the last quarter frame 7 quarter frames (1.75 mtc
148 frames) after the instance when the contents of the mtc quarter
149 frames were decided. Add time to compensate for the elapsed 1.75
151 Also compensate for audio latency.
154 mtc_frame += (long) (1.75 * session.frames_per_smpte_frame()) + session.worst_output_latency();
156 if (first_mtc_frame == 0) {
157 first_mtc_frame = mtc_frame;
158 first_mtc_time = now;
162 current.position = mtc_frame;
163 current.timestamp = now;
167 last_inbound_frame = now;
171 MTC_Slave::handle_locate (const MIDI::byte* mmc_tc)
175 mtc[3] = mmc_tc[0] & 0xf; /* hrs only */
180 update_mtc_time (mtc, true);
184 MTC_Slave::update_mtc_status (MIDI::Parser::MTC_Status status)
193 current.position = mtc_frame;
194 current.timestamp = 0;
204 current.position = mtc_frame;
205 current.timestamp = 0;
215 current.position = mtc_frame;
216 current.timestamp = 0;
224 MTC_Slave::read_current (SafeTime *st) const
229 error << _("MTC Slave: atomic read of current time failed, sleeping!") << endmsg;
237 } while (st->guard1 != st->guard2);
241 MTC_Slave::locked () const
243 return port->input()->mtc_locked();
247 MTC_Slave::ok() const
253 MTC_Slave::speed_and_position (float& speed, nframes_t& pos)
255 nframes_t now = session.engine().frame_time();
257 nframes_t frame_rate;
261 read_current (&last);
263 if (first_mtc_time == 0) {
269 /* no timecode for 1/4 second ? conclude that its stopped */
271 if (last_inbound_frame && now > last_inbound_frame && now - last_inbound_frame > session.frame_rate() / 4) {
274 session.request_locate (pos, false);
275 session.request_transport_speed (0);
276 update_mtc_status (MIDI::Parser::MTC_Stopped);
281 frame_rate = session.frame_rate();
283 speed_now = (float) ((last.position - first_mtc_frame) / (double) (now - first_mtc_time));
285 accumulator[accumulator_index++] = speed_now;
287 if (accumulator_index >= accumulator_size) {
288 have_first_accumulated_speed = true;
289 accumulator_index = 0;
292 if (have_first_accumulated_speed) {
295 for (int32_t i = 0; i < accumulator_size; ++i) {
296 total += accumulator[i];
299 mtc_speed = total / accumulator_size;
303 mtc_speed = speed_now;
307 if (mtc_speed == 0.0f) {
313 /* scale elapsed time by the current MTC speed */
315 if (last.timestamp && (now > last.timestamp)) {
316 elapsed = (nframes_t) floor (mtc_speed * (now - last.timestamp));
318 elapsed = 0; /* XXX is this right? */
322 /* now add the most recent timecode value plus the estimated elapsed interval */
324 pos = elapsed + last.position;
331 MTC_Slave::resolution() const
333 return (nframes_t) session.frames_per_smpte_frame();
339 /* XXX massive thread safety issue here. MTC could
340 be being updated as we call this. but this
341 supposed to be a realtime-safe call.
344 port->input()->reset_mtc_state ();
346 last_inbound_frame = 0;
348 current.position = 0;
349 current.timestamp = 0;
354 accumulator_index = 0;
355 have_first_accumulated_speed = false;