X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fsession_midi.cc;h=3a27b1803bbfb4a7db27d508cbf9417d0f14fc5c;hb=7ab8dbc2fe679d75821ca585dd7c2663f640116e;hp=bd06fe78eebcf56742d4b36e5604e97aa8d179f2;hpb=738387f9a417537e768d56d3fc4afcb9dc82d66b;p=ardour.git diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc index bd06fe78ee..3a27b1803b 100644 --- a/libs/ardour/session_midi.cc +++ b/libs/ardour/session_midi.cc @@ -56,10 +56,6 @@ using namespace PBD; using namespace MIDI; using namespace Glib; -MachineControl::CommandSignature MMC_CommandSignature; -MachineControl::ResponseSignature MMC_ResponseSignature; - - void Session::midi_panic() { @@ -75,397 +71,12 @@ Session::midi_panic() } } -int -Session::use_config_midi_ports () -{ - string port_name; - - if (default_mmc_port) { - set_mmc_port (default_mmc_port->name()); - } else { - set_mmc_port (""); - } - - if (default_mtc_port) { - set_mtc_port (default_mtc_port->name()); - } else { - set_mtc_port (""); - } - - if (default_midi_port) { - set_midi_port (default_midi_port->name()); - } else { - set_midi_port (""); - } - - if (default_midi_clock_port) { - set_midi_clock_port (default_midi_clock_port->name()); - } else { - set_midi_clock_port (""); - } - - return 0; -} - - -/*********************************************************************** - MTC, MMC, etc. -**********************************************************************/ - -int -Session::set_mtc_port (string port_tag) -{ - MTC_Slave *ms; - - if (port_tag.length() == 0) { - - if (_slave && ((ms = dynamic_cast (_slave)) != 0)) { - error << _("Ardour is slaved to MTC - port cannot be reset") << endmsg; - return -1; - } - - if (_mtc_port == 0) { - return 0; - } - - _mtc_port = 0; - goto out; - } - - MIDI::Port* port; - - if ((port = MIDI::Manager::instance()->port (port_tag)) == 0) { - error << string_compose (_("unknown port %1 requested for MTC"), port_tag) << endl; - return -1; - } - - _mtc_port = port; - - if (_slave && ((ms = dynamic_cast (_slave)) != 0)) { - ms->rebind (*port); - } - - Config->set_mtc_port_name (port_tag); - - out: - MTC_PortChanged(); /* EMIT SIGNAL */ - set_dirty(); - return 0; -} - -void -Session::set_mmc_receive_device_id (uint32_t device_id) -{ - if (mmc) { - mmc->set_receive_device_id (device_id); - } -} - -void -Session::set_mmc_send_device_id (uint32_t device_id) -{ - if (mmc) { - mmc->set_send_device_id (device_id); - } -} - -int -Session::set_mmc_port (string port_tag) -{ - MIDI::byte old_recv_device_id = 0; - MIDI::byte old_send_device_id = 0; - bool reset_id = false; - - if (port_tag.length() == 0) { - if (_mmc_port == 0) { - return 0; - } - _mmc_port = 0; - goto out; - } - - MIDI::Port* port; - - if ((port = MIDI::Manager::instance()->port (port_tag)) == 0) { - return -1; - } - - _mmc_port = port; - - if (mmc) { - old_recv_device_id = mmc->receive_device_id(); - old_recv_device_id = mmc->send_device_id(); - reset_id = true; - delete mmc; - } - - mmc = new MIDI::MachineControl (*_mmc_port, 1.0, - MMC_CommandSignature, - MMC_ResponseSignature); - - if (reset_id) { - mmc->set_receive_device_id (old_recv_device_id); - mmc->set_send_device_id (old_send_device_id); - } - - mmc->Play.connect (*this, boost::bind (&Session::mmc_deferred_play, this, _1)); - mmc->DeferredPlay.connect (*this, boost::bind (&Session::mmc_deferred_play, this, _1)); - mmc->Stop.connect (*this, boost::bind (&Session::mmc_stop, this, _1)); - mmc->FastForward.connect (*this, boost::bind (&Session::mmc_fast_forward, this, _1)); - mmc->Rewind.connect (*this, boost::bind (&Session::mmc_rewind, this, _1)); - mmc->Pause.connect (*this, boost::bind (&Session::mmc_pause, this, _1)); - mmc->RecordPause.connect (*this, boost::bind (&Session::mmc_record_pause, this, _1)); - mmc->RecordStrobe.connect (*this, boost::bind (&Session::mmc_record_strobe, this, _1)); - mmc->RecordExit.connect (*this, boost::bind (&Session::mmc_record_exit, this, _1)); - mmc->Locate.connect (*this, boost::bind (&Session::mmc_locate, this, _1, _2)); - mmc->Step.connect (*this, boost::bind (&Session::mmc_step, this, _1, _2)); - mmc->Shuttle.connect (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3)); - mmc->TrackRecordStatusChange.connect (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3)); - - - /* also handle MIDI SPP because its so common */ - - _mmc_port->input()->start.connect (*this, boost::bind (&Session::spp_start, this, _1, _2)); - _mmc_port->input()->contineu.connect (*this, boost::bind (&Session::spp_continue, this, _1, _2)); - _mmc_port->input()->stop.connect (*this, boost::bind (&Session::spp_stop, this, _1, _2)); - - Config->set_mmc_port_name (port_tag); - - out: - MMC_PortChanged(); /* EMIT SIGNAL */ - set_dirty(); - return 0; -} - -int -Session::set_midi_port (string /*port_tag*/) -{ -#if 0 - if (port_tag.length() == 0) { - if (_midi_port == 0) { - return 0; - } - _midi_port = 0; - goto out; - } - - MIDI::Port* port; - - if ((port = MIDI::Manager::instance()->port (port_tag)) == 0) { - return -1; - } - - _midi_port = port; - - /* XXX need something to forward this to control protocols ? or just - use the signal below - */ - - Config->set_midi_port_name (port_tag); - - out: -#endif - MIDI_PortChanged(); /* EMIT SIGNAL */ - set_dirty(); - return 0; -} - -int -Session::set_midi_clock_port (string port_tag) -{ - MIDIClock_Slave *ms; - - if (port_tag.length() == 0) { - - if (_slave && ((ms = dynamic_cast (_slave)) != 0)) { - error << _("Ardour is slaved to MIDI Clock - port cannot be reset") << endmsg; - return -1; - } - - if (_midi_clock_port == 0) { - return 0; - } - - _midi_clock_port = 0; - goto out; - } - - MIDI::Port* port; - - if ((port = MIDI::Manager::instance()->port (port_tag)) == 0) { - error << string_compose (_("unknown port %1 requested for MIDI Clock"), port_tag) << endl; - return -1; - } - - _midi_clock_port = port; - - if (_slave && ((ms = dynamic_cast (_slave)) != 0)) { - ms->rebind (*port); - } - - Config->set_midi_clock_port_name (port_tag); - - out: - MIDIClock_PortChanged(); /* EMIT SIGNAL */ - set_dirty(); - return 0; -} - -void -Session::set_trace_midi_input (bool yn, MIDI::Port* port) -{ - MIDI::Parser* input_parser; - - cerr << "enabling tracing: " << yn << " for input port " << port->name() << endl; - - if (port) { - if ((input_parser = port->input()) != 0) { - input_parser->trace (yn, &cout, "input: "); - } - } else { - - if (_mmc_port) { - if ((input_parser = _mmc_port->input()) != 0) { - input_parser->trace (yn, &cout, "input: "); - } - } - - if (_mtc_port && _mtc_port != _mmc_port) { - if ((input_parser = _mtc_port->input()) != 0) { - input_parser->trace (yn, &cout, "input: "); - } - } - - if (_midi_port && _midi_port != _mmc_port && _midi_port != _mtc_port ) { - if ((input_parser = _midi_port->input()) != 0) { - input_parser->trace (yn, &cout, "input: "); - } - } - - if (_midi_clock_port - && _midi_clock_port != _mmc_port - && _midi_clock_port != _mtc_port - && _midi_clock_port != _midi_port) { - if ((input_parser = _midi_clock_port->input()) != 0) { - input_parser->trace (yn, &cout, "input: "); - } - } - } - - Config->set_trace_midi_input (yn); -} - -void -Session::set_trace_midi_output (bool yn, MIDI::Port* port) -{ - MIDI::Parser* output_parser; - - if (port) { - if ((output_parser = port->output()) != 0) { - output_parser->trace (yn, &cout, "output: "); - } - } else { - if (_mmc_port) { - if ((output_parser = _mmc_port->output()) != 0) { - output_parser->trace (yn, &cout, "output: "); - } - } - - if (_mtc_port && _mtc_port != _mmc_port) { - if ((output_parser = _mtc_port->output()) != 0) { - output_parser->trace (yn, &cout, "output: "); - } - } - - if (_midi_port && _midi_port != _mmc_port && _midi_port != _mtc_port ) { - if ((output_parser = _midi_port->output()) != 0) { - output_parser->trace (yn, &cout, "output: "); - } - } - - } - - Config->set_trace_midi_output (yn); -} - -bool -Session::get_trace_midi_input(MIDI::Port *port) -{ - MIDI::Parser* input_parser; - if (port) { - if ((input_parser = port->input()) != 0) { - return input_parser->tracing(); - } - } - else { - if (_mmc_port) { - if ((input_parser = _mmc_port->input()) != 0) { - return input_parser->tracing(); - } - } - - if (_mtc_port) { - if ((input_parser = _mtc_port->input()) != 0) { - return input_parser->tracing(); - } - } - - if (_midi_port) { - if ((input_parser = _midi_port->input()) != 0) { - return input_parser->tracing(); - } - } - } - - return false; -} - -bool -Session::get_trace_midi_output(MIDI::Port *port) -{ - MIDI::Parser* output_parser; - if (port) { - if ((output_parser = port->output()) != 0) { - return output_parser->tracing(); - } - } - else { - if (_mmc_port) { - if ((output_parser = _mmc_port->output()) != 0) { - return output_parser->tracing(); - } - } - - if (_mtc_port) { - if ((output_parser = _mtc_port->output()) != 0) { - return output_parser->tracing(); - } - } - - if (_midi_port) { - if ((output_parser = _midi_port->output()) != 0) { - return output_parser->tracing(); - } - } - } - - return false; - -} - void Session::setup_midi_control () { outbound_mtc_timecode_frame = 0; next_quarter_frame_to_send = 0; - /* setup the MMC buffer */ - - mmc_buffer[0] = 0xf0; // SysEx - mmc_buffer[1] = 0x7f; // Real Time SysEx ID for MMC - mmc_buffer[2] = (mmc ? mmc->send_device_id() : 0x7f); - mmc_buffer[3] = 0x6; // MCC - /* Set up the qtr frame message */ mtc_msg[0] = 0xf1; @@ -519,8 +130,9 @@ Session::mmc_record_pause (MIDI::MachineControl &/*mmc*/) void Session::mmc_record_strobe (MIDI::MachineControl &/*mmc*/) { - if (!Config->get_mmc_control()) + if (!Config->get_mmc_control()) { return; + } /* record strobe does an implicit "Play" command */ @@ -734,9 +346,10 @@ Session::mmc_record_enable (MIDI::MachineControl &mmc, size_t trk, bool enabled) /** Send MTC Full Frame message (complete Timecode time) for the start of this cycle. * This resets the MTC code, the next quarter frame message that is sent will be * the first one with the beginning of this cycle as the new start point. + * @param t time to send. */ int -Session::send_full_time_code(nframes_t /*nframes*/) +Session::send_full_time_code (nframes64_t const t) { /* This function could easily send at a given frame offset, but would * that be useful? Does ardour do sub-block accurate locating? [DR] */ @@ -746,26 +359,25 @@ Session::send_full_time_code(nframes_t /*nframes*/) _send_timecode_update = false; - if (_mtc_port == 0 || !session_send_mtc) { + if (!session_send_mtc || _slave) { return 0; } - // Get timecode time for this transport frame - sample_to_timecode(_transport_frame, timecode, true /* use_offset */, false /* no subframes */); + // Get timecode time for the given time + sample_to_timecode (t, timecode, true /* use_offset */, false /* no subframes */); transmitting_timecode_time = timecode; - outbound_mtc_timecode_frame = _transport_frame; + outbound_mtc_timecode_frame = t; // I don't understand this bit yet.. [DR] 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() ); + Timecode::increment (transmitting_timecode_time, config.get_subframes_per_frame()); outbound_mtc_timecode_frame += (nframes_t) _frames_per_timecode_frame; } // Compensate for audio latency outbound_mtc_timecode_frame += _worst_output_latency; - next_quarter_frame_to_send = 0; // Sync slave to the same Timecode time as we are on @@ -781,10 +393,8 @@ Session::send_full_time_code(nframes_t /*nframes*/) msg[7] = timecode.seconds; msg[8] = timecode.frames; - cerr << "MTC: Sending full time code at " << outbound_mtc_timecode_frame << endl; - // Send message at offset 0, sent time is for the start of this cycle - if (_mtc_port->midimsg (msg, sizeof (msg), 0)) { + if (MIDI::Manager::instance()->mtc_output_port()->midimsg (msg, sizeof (msg), 0)) { error << _("Session: could not send full MIDI time code") << endmsg; return -1; } @@ -802,24 +412,22 @@ Session::send_full_time_code(nframes_t /*nframes*/) int Session::send_midi_time_code_for_cycle(nframes_t nframes) { - assert (next_quarter_frame_to_send >= 0); - assert (next_quarter_frame_to_send <= 7); - - if (_mtc_port == 0 || !session_send_mtc || transmitting_timecode_time.negative - /*|| (next_quarter_frame_to_send < 0)*/ ) { + if (_slave || !session_send_mtc || transmitting_timecode_time.negative || (next_quarter_frame_to_send < 0)) { // cerr << "(MTC) Not sending MTC\n"; return 0; } + assert (next_quarter_frame_to_send >= 0); + assert (next_quarter_frame_to_send <= 7); + /* Duration of one quarter frame */ nframes_t quarter_frame_duration = ((long) _frames_per_timecode_frame) >> 2; - DEBUG_TRACE (DEBUG::MTC, string_compose ("TF %1 SF %2 NQ %3 FD %\4n", _transport_frame, outbound_mtc_timecode_frame, + DEBUG_TRACE (DEBUG::MTC, string_compose ("TF %1 SF %2 NQ %3 FD %4\n", _transport_frame, outbound_mtc_timecode_frame, next_quarter_frame_to_send, quarter_frame_duration)); - // FIXME: this should always be true - //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 @@ -865,7 +473,7 @@ Session::send_midi_time_code_for_cycle(nframes_t nframes) nframes_t out_stamp = msg_time - _transport_frame; assert(out_stamp < nframes); - if (_mtc_port->midimsg (mtc_msg, 2, out_stamp)) { + 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)) << endmsg; return -1; @@ -891,8 +499,6 @@ Session::send_midi_time_code_for_cycle(nframes_t nframes) // 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; - // Compensate for audio latency - outbound_mtc_timecode_frame += _worst_output_latency; } } @@ -903,69 +509,6 @@ Session::send_midi_time_code_for_cycle(nframes_t nframes) OUTBOUND MMC STUFF **********************************************************************/ -void -Session::deliver_mmc (MIDI::MachineControl::Command cmd, nframes_t where) -{ - using namespace MIDI; - int nbytes = 4; - Timecode::Time timecode; - - if (_mmc_port == 0 || !session_send_mmc) { - // cerr << "Not delivering MMC " << _mmc_port << " - " << session_send_mmc << endl; - return; - } - - mmc_buffer[nbytes++] = cmd; - - // cerr << "delivering MMC, cmd = " << hex << (int) cmd << dec << endl; - - switch (cmd) { - case MachineControl::cmdLocate: - timecode_time_subframes (where, timecode); - - mmc_buffer[nbytes++] = 0x6; // byte count - mmc_buffer[nbytes++] = 0x1; // "TARGET" subcommand - mmc_buffer[nbytes++] = timecode.hours; - mmc_buffer[nbytes++] = timecode.minutes; - mmc_buffer[nbytes++] = timecode.seconds; - mmc_buffer[nbytes++] = timecode.frames; - mmc_buffer[nbytes++] = timecode.subframes; - break; - - case MachineControl::cmdStop: - break; - - case MachineControl::cmdPlay: - /* always convert Play into Deferred Play */ - /* Why? [DR] */ - mmc_buffer[4] = MachineControl::cmdDeferredPlay; - break; - - case MachineControl::cmdDeferredPlay: - break; - - case MachineControl::cmdRecordStrobe: - break; - - case MachineControl::cmdRecordExit: - break; - - case MachineControl::cmdRecordPause: - break; - - default: - nbytes = 0; - }; - - if (nbytes) { - - mmc_buffer[nbytes++] = 0xf7; // terminate SysEx/MMC message - - if (_mmc_port->midimsg (mmc_buffer, nbytes, 0)) { - error << string_compose(_("MMC: cannot send command %1%2%3"), &hex, cmd, &dec) << endmsg; - } - } -} bool Session::mmc_step_timeout ()