Cope with non-unity transport speed when sending MTC.
[ardour.git] / libs / ardour / session_midi.cc
index 6914b9db9474a9ca702732ce6db5b49fb37f8525..31e4e9ca476ee1540e8700bf43cce5a9a6c4f234 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
   Copyright (C) 1999-2002 Paul Davis
 
 #include "midi++/mmc.h"
 #include "midi++/port.h"
 #include "midi++/manager.h"
+
 #include "pbd/error.h"
 #include "pbd/pthread_utils.h"
 
+#include "timecode/time.h"
+
 #include "ardour/configuration.h"
 #include "ardour/debug.h"
 #include "ardour/audioengine.h"
@@ -46,7 +48,6 @@
 #include "ardour/audio_diskstream.h"
 #include "ardour/slave.h"
 #include "ardour/cycles.h"
-#include "ardour/timecode.h"
 
 #include "i18n.h"
 
@@ -90,7 +91,7 @@ Session::setup_midi_control ()
 }
 
 void
-Session::spp_start (Parser &, nframes_t /*timestamp*/)
+Session::spp_start (Parser &, framepos_t /*timestamp*/)
 {
        if (Config->get_mmc_control() && (!config.get_external_sync() || config.get_sync_source() != JACK)) {
                request_transport_speed (1.0);
@@ -98,13 +99,13 @@ Session::spp_start (Parser &, nframes_t /*timestamp*/)
 }
 
 void
-Session::spp_continue (Parser& ignored, nframes_t timestamp)
+Session::spp_continue (Parser& ignored, framepos_t timestamp)
 {
        spp_start (ignored, timestamp);
 }
 
 void
-Session::spp_stop (Parser&, nframes_t /*timestamp*/)
+Session::spp_stop (Parser&, framepos_t /*timestamp*/)
 {
        if (Config->get_mmc_control()) {
                request_stop ();
@@ -373,7 +374,7 @@ Session::send_full_time_code (framepos_t const t)
        if (((mtc_timecode_bits >> 5) != MIDI::MTC_25_FPS) && (transmitting_timecode_time.frames % 2)) {
                // start MTC quarter frame transmission on an even frame
                Timecode::increment (transmitting_timecode_time, config.get_subframes_per_frame());
-               outbound_mtc_timecode_frame += (nframes_t) _frames_per_timecode_frame;
+               outbound_mtc_timecode_frame += _frames_per_timecode_frame;
        }
 
        // Compensate for audio latency
@@ -403,14 +404,14 @@ Session::send_full_time_code (framepos_t const t)
 }
 
 /** Send MTC (quarter-frame) messages for this cycle.
- * Must be called exactly once per cycle from the audio thread.  Realtime safe.
+ * Must be called exactly once per cycle from the process thread.  Realtime safe.
  * This function assumes the state of full Timecode is sane, eg. the slave is
  * expecting quarter frame messages and has the right frame of reference (any
  * full MTC Timecode time messages that needed to be sent should have been sent
  * earlier already this cycle by send_full_time_code)
  */
 int
-Session::send_midi_time_code_for_cycle(nframes_t nframes)
+Session::send_midi_time_code_for_cycle (framepos_t start_frame, framepos_t end_frame, pframes_t nframes)
 {
        if (_slave || !session_send_mtc || transmitting_timecode_time.negative || (next_quarter_frame_to_send < 0)) {
                // cerr << "(MTC) Not sending MTC\n";
@@ -421,57 +422,55 @@ Session::send_midi_time_code_for_cycle(nframes_t nframes)
        assert (next_quarter_frame_to_send <= 7);
 
        /* Duration of one quarter frame */
-       nframes_t quarter_frame_duration = ((nframes_t) _frames_per_timecode_frame) >> 2;
+       framecnt_t const quarter_frame_duration = ((framecnt_t) _frames_per_timecode_frame) >> 2;
 
-       DEBUG_TRACE (DEBUG::MTC, string_compose ("TF %1 SF %2 NQ %3 FD %4\n",  _transport_frame, outbound_mtc_timecode_frame,
+       DEBUG_TRACE (DEBUG::MTC, string_compose ("TF %1 SF %2 NQ %3 FD %4\n", start_frame, outbound_mtc_timecode_frame,
                                                 next_quarter_frame_to_send, quarter_frame_duration));
 
-       assert((outbound_mtc_timecode_frame + (next_quarter_frame_to_send * quarter_frame_duration))
-                       >= _transport_frame);
-
+       assert ((outbound_mtc_timecode_frame + (next_quarter_frame_to_send * quarter_frame_duration)) >= _transport_frame);
 
-       // Send quarter frames for this cycle
-       while (_transport_frame + nframes > (outbound_mtc_timecode_frame +
-                               (next_quarter_frame_to_send * quarter_frame_duration))) {
+       /* Send quarter frames for this cycle */
+       while (end_frame > (outbound_mtc_timecode_frame + (next_quarter_frame_to_send * quarter_frame_duration))) {
 
                DEBUG_TRACE (DEBUG::MTC, string_compose ("next frame to send: %1\n", next_quarter_frame_to_send));
 
                switch (next_quarter_frame_to_send) {
                        case 0:
-                               mtc_msg[1] =  0x00 | (transmitting_timecode_time.frames & 0xf);
+                               mtc_msg[1] = 0x00 | (transmitting_timecode_time.frames & 0xf);
                                break;
                        case 1:
-                               mtc_msg[1] =  0x10 | ((transmitting_timecode_time.frames & 0xf0) >> 4);
+                               mtc_msg[1] = 0x10 | ((transmitting_timecode_time.frames & 0xf0) >> 4);
                                break;
                        case 2:
-                               mtc_msg[1] =  0x20 | (transmitting_timecode_time.seconds & 0xf);
+                               mtc_msg[1] = 0x20 | (transmitting_timecode_time.seconds & 0xf);
                                break;
                        case 3:
-                               mtc_msg[1] =  0x30 | ((transmitting_timecode_time.seconds & 0xf0) >> 4);
+                               mtc_msg[1] = 0x30 | ((transmitting_timecode_time.seconds & 0xf0) >> 4);
                                break;
                        case 4:
-                               mtc_msg[1] =  0x40 | (transmitting_timecode_time.minutes & 0xf);
+                               mtc_msg[1] = 0x40 | (transmitting_timecode_time.minutes & 0xf);
                                break;
                        case 5:
                                mtc_msg[1] = 0x50 | ((transmitting_timecode_time.minutes & 0xf0) >> 4);
                                break;
                        case 6:
-                               mtc_msg[1] = 0x60 | ((mtc_timecode_bits|transmitting_timecode_time.hours) & 0xf);
+                               mtc_msg[1] = 0x60 | ((mtc_timecode_bits | transmitting_timecode_time.hours) & 0xf);
                                break;
                        case 7:
-                               mtc_msg[1] = 0x70 | (((mtc_timecode_bits|transmitting_timecode_time.hours) & 0xf0) >> 4);
+                               mtc_msg[1] = 0x70 | (((mtc_timecode_bits | transmitting_timecode_time.hours) & 0xf0) >> 4);
                                break;
                }
 
-               const nframes_t msg_time = (outbound_mtc_timecode_frame
-                       + (quarter_frame_duration * next_quarter_frame_to_send));
+               const framepos_t msg_time = outbound_mtc_timecode_frame + (quarter_frame_duration * next_quarter_frame_to_send);
+               cout << "  " << msg_time << "\n";
 
                // This message must fall within this block or something is broken
-               assert(msg_time >= _transport_frame);
-               assert(msg_time < _transport_frame + nframes);
+               assert (msg_time >= start_frame);
+               assert (msg_time < end_frame);
 
-               nframes_t out_stamp = msg_time - _transport_frame;
-               assert(out_stamp < nframes);
+               /* convert from session frames back to JACK frames using the transport speed */
+               pframes_t const out_stamp = (msg_time - start_frame) / _transport_speed;
+               assert (out_stamp < nframes);
 
                if (MIDI::Manager::instance()->mtc_output_port()->midimsg (mtc_msg, 2, out_stamp)) {
                        error << string_compose(_("Session: cannot send quarter-frame MTC message (%1)"), strerror (errno))
@@ -494,8 +493,8 @@ Session::send_midi_time_code_for_cycle(nframes_t nframes)
                        // Wrap quarter frame counter
                        next_quarter_frame_to_send = 0;
                        // Increment timecode time twice
-                       Timecode::increment( transmitting_timecode_time, config.get_subframes_per_frame() );
-                       Timecode::increment( transmitting_timecode_time, config.get_subframes_per_frame() );
+                       Timecode::increment (transmitting_timecode_time, config.get_subframes_per_frame());
+                       Timecode::increment (transmitting_timecode_time, config.get_subframes_per_frame());
                        // Re-calculate timing of first quarter frame
                        //timecode_to_sample( transmitting_timecode_time, outbound_mtc_timecode_frame, true /* use_offset */, false );
                        outbound_mtc_timecode_frame += 8 * quarter_frame_duration;