void toggle_use_mmc ();
void toggle_send_mmc ();
void toggle_send_mtc ();
- void toggle_use_midi_clock ();
void toggle_use_osc ();
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_toggle_action (option_actions, X_("UseMMC"), _("Use MMC"), mem_fun (*this, &ARDOUR_UI::toggle_use_mmc));
ActionManager::session_sensitive_actions.push_back (act);
- act = ActionManager::register_toggle_action (option_actions, X_("UseMIDIClock"), _("Use MIDI Clock"), mem_fun (*this, &ARDOUR_UI::toggle_use_midi_clock));
- ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_toggle_action (option_actions, X_("SendMIDIfeedback"), _("Send MIDI feedback"), mem_fun (*this, &ARDOUR_UI::toggle_send_midi_feedback));
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::toggle_config_state ("options", "UseMMC", &Configuration::set_mmc_control, &Configuration::get_mmc_control);
}
-void
-ARDOUR_UI::toggle_use_midi_clock ()
-{
- ActionManager::toggle_config_state ("options", "UseMIDIClock", &Configuration::set_midi_clock_control, &Configuration::get_midi_clock_control);
-}
-
void
ARDOUR_UI::toggle_use_osc ()
{
} else if (PARAM_IS ("mmc-control")) {
ActionManager::map_some_state ("options", "UseMMC", &Configuration::get_mmc_control);
- } else if (PARAM_IS ("midi-clock-control")) {
- ActionManager::map_some_state ("options", "UseMIDIClock", &Configuration::get_midi_clock_control);
} else if (PARAM_IS ("midi-feedback")) {
ActionManager::map_some_state ("options", "SendMIDIfeedback", &Configuration::get_midi_feedback);
} else if (PARAM_IS ("do-not-record-plugins")) {
CONFIG_VARIABLE (bool, send_mtc, "send-mtc", false)
CONFIG_VARIABLE (bool, send_mmc, "send-mmc", true)
CONFIG_VARIABLE (bool, mmc_control, "mmc-control", true)
-CONFIG_VARIABLE (bool, midi_clock_control, "midi-clock-control", false)
CONFIG_VARIABLE (bool, midi_feedback, "midi-feedback", false)
CONFIG_VARIABLE (uint8_t, mmc_receive_device_id, "mmc-receive-device-id", 0)
CONFIG_VARIABLE (uint8_t, mmc_send_device_id, "mmc-send-device-id", 0)
void deliver_mmc (MIDI::MachineControl::Command, nframes_t);
- void spp_start (MIDI::Parser&);
- void spp_continue (MIDI::Parser&);
- void spp_stop (MIDI::Parser&);
-
- void midi_clock_start (MIDI::Parser&);
- void midi_clock_continue (MIDI::Parser&);
- void midi_clock_stop (MIDI::Parser&);
+ void spp_start (MIDI::Parser&, nframes_t timestamp);
+ void spp_continue (MIDI::Parser&, nframes_t timestamp);
+ void spp_stop (MIDI::Parser&, nframes_t timestamp);
void mmc_deferred_play (MIDI::MachineControl &);
void mmc_stop (MIDI::MachineControl &);
float average;
void reset ();
- void start (MIDI::Parser& parser);
- void stop (MIDI::Parser& parser);
- void update_midi_clock (MIDI::Parser& parser);
+ void start (MIDI::Parser& parser, nframes_t timestamp);
+ void stop (MIDI::Parser& parser, nframes_t timestamp);
+ void update_midi_clock (MIDI::Parser& parser, nframes_t timestamp);
void read_current (SafeTime *) const;
bool _started;
#include <pbd/pthread_utils.h>
#include <midi++/port.h>
+#include <midi++/jack.h>
#include <ardour/slave.h>
#include <ardour/session.h>
#include <ardour/audioengine.h>
#include <ardour/cycles.h>
#include <ardour/tempo.h>
+
#include "i18n.h"
using namespace ARDOUR;
}
void
-MIDIClock_Slave::update_midi_clock (Parser& parser)
+MIDIClock_Slave::update_midi_clock (Parser& parser, nframes_t timestamp)
{
- nframes_t now = session.engine().frame_time();
+ nframes_t now = timestamp;
SafeTime last;
read_current (&last);
average += accumulator[i];
average /= accumulator_size;
+ JACK_MidiPort *jack_port = dynamic_cast<JACK_MidiPort *>(port);
+ pthread_t process_thread_id = 0;
+ if(jack_port) {
+ process_thread_id = jack_port->get_process_thread();
+ }
- std::cerr << "got MIDI Clock message at time " << now
+ std::cerr << "Thread " << pthread_name() << " with id " << pthread_self() << " process Thread ID: " << process_thread_id
+ << " got MIDI Clock message at time " << now
<< " real delta: " << midi_clock_frame
<< " reference: " << one_ppqn_in_frames
<< " accu index: " << accumulator_index
}
void
-MIDIClock_Slave::start (Parser& parser)
+MIDIClock_Slave::start (Parser& parser, nframes_t timestamp)
{
nframes_t now = session.engine().frame_time();
}
void
-MIDIClock_Slave::stop (Parser& parser)
+MIDIClock_Slave::stop (Parser& parser, nframes_t timestamp)
{
std::cerr << "MIDIClock_Slave got stop message" << endl;
pos = last.position;
session.request_locate (pos, false);
session.request_transport_speed (0);
- this->stop(*port->input());
+ this->stop(*port->input(), now);
reset();
return false;
}
speed = midi_clock_speed;
- cerr << " final speed: " << speed << " elapsed: " << elapsed << " elapsed (scaled) " << elapsed * speed << " position: " << pos << endl;
+ cerr << " final speed: " << speed << " elapsed: " << elapsed << " elapsed (scaled) " << elapsed * speed << " position: " << pos
+ << " Thread ID: " << pthread_self() << endl;
return true;
}
Config->set_midi_clock_port_name (port_tag);
- _midi_clock_port->input()->start.connect (mem_fun (*this, &Session::midi_clock_start));
- _midi_clock_port->input()->contineu.connect (mem_fun (*this, &Session::midi_clock_continue));
- _midi_clock_port->input()->stop.connect (mem_fun (*this, &Session::midi_clock_stop));
-
out:
MIDIClock_PortChanged(); /* EMIT SIGNAL */
change_midi_ports ();
}
void
-Session::spp_start (Parser& ignored)
+Session::spp_start (Parser& ignored, nframes_t timestamp)
{
if (Config->get_mmc_control() && (Config->get_slave_source() != MTC)) {
request_transport_speed (1.0);
}
void
-Session::spp_continue (Parser& ignored)
+Session::spp_continue (Parser& ignored, nframes_t timestamp)
{
- spp_start (ignored);
+ spp_start (ignored, timestamp);
}
void
-Session::spp_stop (Parser& ignored)
+Session::spp_stop (Parser& ignored, nframes_t timestamp)
{
if (Config->get_mmc_control()) {
request_stop ();
}
}
-
+/*
void
-Session::midi_clock_start (Parser& ignored)
+Session::midi_clock_start (Parser& ignored, nframes_t timestamp)
{
- if (Config->get_midi_clock_control() && (Config->get_slave_source() == MIDIClock)) {
+ if (Config->get_slave_source() == MIDIClock) {
request_transport_speed (1.0);
}
}
void
-Session::midi_clock_continue (Parser& ignored)
+Session::midi_clock_continue (Parser& parser, nframes_t timestamp)
{
- midi_clock_start (ignored);
+ midi_clock_start (parser, 0);
}
void
-Session::midi_clock_stop (Parser& ignored)
+Session::midi_clock_stop (Parser& ignored, nframes_t timestamp)
{
- if (Config->get_midi_clock_control()) {
+ if (Config->get_slave_source() == MIDIClock) {
request_stop ();
}
}
+*/
void
Session::mmc_deferred_play (MIDI::MachineControl &mmc)
if (input_parser) {
input_parser->raw_preparse (*input_parser, ev.buffer, ev.size);
for (size_t i = 0; i < ev.size; i++) {
+ // the midi events here are used for MIDI clock only
+ input_parser->set_midi_clock_timestamp(ev.time + jack_last_frame_time(_jack_client));
input_parser->scanner (ev.buffer[i]);
}
input_parser->raw_postparse (*input_parser, ev.buffer, ev.size);
virtual void set_state (const XMLNode&);
static void set_process_thread (pthread_t);
-
+ static pthread_t get_process_thread () { return _process_thread; }
+ static bool is_process_thread();
+
protected:
std::string get_typestring () const {
return typestring;
void flush (void* jack_port_buffer);
static pthread_t _process_thread;
- static bool is_process_thread();
+
RingBuffer<Evoral::Event> non_process_thread_fifo;
Glib::Mutex non_process_thread_fifo_lock;
Signal position;
Signal song;
- Signal mtc;
+ Signal mtc;
sigc::signal<void,Parser&> mtc_qtr;
- sigc::signal<void, Parser &> all_notes_off;
- sigc::signal<void, Parser &> tune;
- sigc::signal<void, Parser &> timing;
- sigc::signal<void, Parser &> start;
- sigc::signal<void, Parser &> stop;
- sigc::signal<void, Parser &> contineu; /* note spelling */
+ sigc::signal<void, Parser &> all_notes_off;
+ sigc::signal<void, Parser &> tune;
+ sigc::signal<void, Parser &, nframes_t> timing;
+ sigc::signal<void, Parser &, nframes_t> start;
+ sigc::signal<void, Parser &, nframes_t> stop;
+ sigc::signal<void, Parser &, nframes_t> contineu; /* note spelling */
sigc::signal<void, Parser &> active_sense;
sigc::signal<void, Parser &> reset;
sigc::signal<void, Parser &> eox;
MTC_Status mtc_running() const { return _mtc_running; }
const byte *mtc_current() const { return _mtc_time; }
bool mtc_locked() const { return _mtc_locked; }
+
+ const nframes_t get_midi_clock_timestamp() const { return _midi_clock_timestamp; }
+ void set_midi_clock_timestamp(const nframes_t timestamp) { _midi_clock_timestamp = timestamp; }
sigc::signal<void,MTC_Status> mtc_status;
sigc::signal<bool> mtc_skipped;
MTC_Status _mtc_running;
bool _mtc_locked;
byte last_qtr_frame;
+
+ nframes_t _midi_clock_timestamp;
ParseState pre_variable_state;
MIDI::eventType pre_variable_msgtype;
int three_byte_msg (byte a, byte b, byte c, timestamp_t timestamp) {
byte msg[3];
- msg[0] = a;
+ msg[0] = a;
msg[1] = b;
msg[2] = c;
switch (inbyte) {
case 0xf8:
- timing (*this);
+ timing (*this, _midi_clock_timestamp);
break;
case 0xfa:
- start (*this);
+ start (*this, _midi_clock_timestamp);
break;
case 0xfb:
- contineu (*this);
+ contineu (*this, _midi_clock_timestamp);
break;
case 0xfc:
- stop (*this);
+ stop (*this, _midi_clock_timestamp);
break;
case 0xfe:
/* !!! active sense message in realtime_msg: should not reach here
}
guint read (T *dest, guint cnt);
- guint write (T *src, guint cnt);
+ guint write (T *src, guint cnt);
struct rw_vector {
T *buf[2];