mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-10 16:46:35 +01:00
Move MIDI control port ownership into the MIDI Manager, since control port state should be Ardour-wide, not per-session. Fix up port connection state management.
git-svn-id: svn://localhost/ardour2/branches/3.0@7394 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
3549189f87
commit
648a169d8f
17 changed files with 152 additions and 131 deletions
|
|
@ -164,8 +164,6 @@ SessionOptionEditor::SessionOptionEditor (Session* s)
|
||||||
sigc::mem_fun (*_session_config, &SessionConfiguration::set_sync_source)
|
sigc::mem_fun (*_session_config, &SessionConfiguration::set_sync_source)
|
||||||
);
|
);
|
||||||
|
|
||||||
s->MTC_PortChanged.connect (_session_connections, invalidator (*this), boost::bind (&SessionOptionEditor::populate_sync_options, this, s, ssrc), gui_context());
|
|
||||||
s->MIDIClock_PortChanged.connect (_session_connections, invalidator (*this), boost::bind (&SessionOptionEditor::populate_sync_options, this, s, ssrc), gui_context());
|
|
||||||
s->config.ParameterChanged.connect (_session_connections, invalidator (*this), ui_bind (&SessionOptionEditor::follow_sync_state, this, _1, s, ssrc), gui_context());
|
s->config.ParameterChanged.connect (_session_connections, invalidator (*this), ui_bind (&SessionOptionEditor::follow_sync_state, this, _1, s, ssrc), gui_context());
|
||||||
|
|
||||||
populate_sync_options (s, ssrc);
|
populate_sync_options (s, ssrc);
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ class RCConfiguration : public Configuration
|
||||||
XMLNode * instant_xml (const std::string& str);
|
XMLNode * instant_xml (const std::string& str);
|
||||||
|
|
||||||
XMLNode* control_protocol_state () { return _control_protocol_state; }
|
XMLNode* control_protocol_state () { return _control_protocol_state; }
|
||||||
|
std::list<XMLNode*> midi_port_states () { return _midi_port_states; }
|
||||||
|
|
||||||
/* define accessor methods */
|
/* define accessor methods */
|
||||||
|
|
||||||
|
|
@ -80,6 +81,11 @@ class RCConfiguration : public Configuration
|
||||||
#undef CONFIG_VARIABLE_SPECIAL
|
#undef CONFIG_VARIABLE_SPECIAL
|
||||||
|
|
||||||
XMLNode* _control_protocol_state;
|
XMLNode* _control_protocol_state;
|
||||||
|
|
||||||
|
/** MIDI port nodes from the RC configuration. We store them so that we can set their
|
||||||
|
state once the audio engine and hence ports are up.
|
||||||
|
*/
|
||||||
|
std::list<XMLNode*> _midi_port_states;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* XXX: rename this */
|
/* XXX: rename this */
|
||||||
|
|
|
||||||
|
|
@ -638,19 +638,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
|
||||||
PBD::Signal1<void,boost::shared_ptr<Bundle> > BundleAdded;
|
PBD::Signal1<void,boost::shared_ptr<Bundle> > BundleAdded;
|
||||||
PBD::Signal1<void,boost::shared_ptr<Bundle> > BundleRemoved;
|
PBD::Signal1<void,boost::shared_ptr<Bundle> > BundleRemoved;
|
||||||
|
|
||||||
/* MIDI control */
|
void midi_panic ();
|
||||||
|
|
||||||
void midi_panic(void);
|
|
||||||
MIDI::Port *mtc_input_port() const { return _mtc_input_port; }
|
|
||||||
MIDI::Port *mtc_output_port() const { return _mtc_output_port; }
|
|
||||||
MIDI::Port *midi_input_port() const { return _midi_input_port; }
|
|
||||||
MIDI::Port *midi_output_port() const { return _midi_output_port; }
|
|
||||||
MIDI::Port *midi_clock_input_port() const { return _midi_clock_input_port; }
|
|
||||||
MIDI::Port *midi_clock_output_port() const { return _midi_clock_output_port; }
|
|
||||||
|
|
||||||
PBD::Signal0<void> MTC_PortChanged;
|
|
||||||
PBD::Signal0<void> MIDI_PortChanged;
|
|
||||||
PBD::Signal0<void> MIDIClock_PortChanged;
|
|
||||||
|
|
||||||
/* Scrubbing */
|
/* Scrubbing */
|
||||||
|
|
||||||
|
|
@ -944,13 +932,6 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
|
||||||
|
|
||||||
void check_declick_out ();
|
void check_declick_out ();
|
||||||
|
|
||||||
MIDI::MachineControl* _mmc;
|
|
||||||
MIDI::Port* _mtc_input_port;
|
|
||||||
MIDI::Port* _mtc_output_port;
|
|
||||||
MIDI::Port* _midi_input_port;
|
|
||||||
MIDI::Port* _midi_output_port;
|
|
||||||
MIDI::Port* _midi_clock_input_port;
|
|
||||||
MIDI::Port* _midi_clock_output_port;
|
|
||||||
std::string _path;
|
std::string _path;
|
||||||
std::string _name;
|
std::string _name;
|
||||||
bool _is_new;
|
bool _is_new;
|
||||||
|
|
|
||||||
|
|
@ -328,12 +328,17 @@ ARDOUR::init (bool use_vst, bool try_optimization)
|
||||||
void
|
void
|
||||||
ARDOUR::init_post_engine ()
|
ARDOUR::init_post_engine ()
|
||||||
{
|
{
|
||||||
|
/* the MIDI Manager is needed by the ControlProtocolManager */
|
||||||
|
MIDI::Manager::create (AudioEngine::instance()->jack());
|
||||||
|
|
||||||
ControlProtocolManager::instance().discover_control_protocols ();
|
ControlProtocolManager::instance().discover_control_protocols ();
|
||||||
|
|
||||||
XMLNode* node;
|
XMLNode* node;
|
||||||
if ((node = Config->control_protocol_state()) != 0) {
|
if ((node = Config->control_protocol_state()) != 0) {
|
||||||
ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
|
ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MIDI::Manager::instance()->set_port_states (Config->midi_port_states ());
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,10 @@ RCConfiguration::RCConfiguration ()
|
||||||
|
|
||||||
RCConfiguration::~RCConfiguration ()
|
RCConfiguration::~RCConfiguration ()
|
||||||
{
|
{
|
||||||
|
for (list<XMLNode*>::iterator i = _midi_port_states.begin(); i != _midi_port_states.end(); ++i) {
|
||||||
|
delete *i;
|
||||||
|
}
|
||||||
|
|
||||||
delete _control_protocol_state;
|
delete _control_protocol_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -254,19 +258,24 @@ RCConfiguration::set_state (const XMLNode& root, int /*version*/)
|
||||||
XMLNodeConstIterator niter;
|
XMLNodeConstIterator niter;
|
||||||
XMLNode *node;
|
XMLNode *node;
|
||||||
|
|
||||||
|
for (list<XMLNode*>::iterator i = _midi_port_states.begin(); i != _midi_port_states.end(); ++i) {
|
||||||
|
delete *i;
|
||||||
|
}
|
||||||
|
|
||||||
|
_midi_port_states.clear ();
|
||||||
|
|
||||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||||
|
|
||||||
node = *niter;
|
node = *niter;
|
||||||
|
|
||||||
if (node->name() == "Config") {
|
if (node->name() == "Config") {
|
||||||
|
|
||||||
set_variables (*node);
|
set_variables (*node);
|
||||||
|
|
||||||
} else if (node->name() == "Extra") {
|
} else if (node->name() == "Extra") {
|
||||||
_extra_xml = new XMLNode (*node);
|
_extra_xml = new XMLNode (*node);
|
||||||
|
|
||||||
} else if (node->name() == ControlProtocolManager::state_node_name) {
|
} else if (node->name() == ControlProtocolManager::state_node_name) {
|
||||||
_control_protocol_state = new XMLNode (*node);
|
_control_protocol_state = new XMLNode (*node);
|
||||||
|
} else if (node->name() == MIDI::Port::state_node_name) {
|
||||||
|
_midi_port_states.push_back (new XMLNode (*node));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,7 @@
|
||||||
|
|
||||||
#include "midi++/port.h"
|
#include "midi++/port.h"
|
||||||
#include "midi++/mmc.h"
|
#include "midi++/mmc.h"
|
||||||
|
#include "midi++/manager.h"
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
|
@ -136,7 +137,6 @@ Session::Session (AudioEngine &eng,
|
||||||
: _engine (eng),
|
: _engine (eng),
|
||||||
_target_transport_speed (0.0),
|
_target_transport_speed (0.0),
|
||||||
_requested_return_frame (-1),
|
_requested_return_frame (-1),
|
||||||
_mmc (0),
|
|
||||||
_session_dir (new SessionDirectory(fullpath)),
|
_session_dir (new SessionDirectory(fullpath)),
|
||||||
state_tree (0),
|
state_tree (0),
|
||||||
_butler (new Butler (*this)),
|
_butler (new Butler (*this)),
|
||||||
|
|
@ -302,15 +302,6 @@ Session::destroy ()
|
||||||
|
|
||||||
Crossfade::set_buffer_size (0);
|
Crossfade::set_buffer_size (0);
|
||||||
|
|
||||||
delete _mmc;
|
|
||||||
|
|
||||||
delete _mtc_input_port;
|
|
||||||
delete _mtc_output_port;
|
|
||||||
delete _midi_input_port;
|
|
||||||
delete _midi_output_port;
|
|
||||||
delete _midi_clock_input_port;
|
|
||||||
delete _midi_clock_output_port;
|
|
||||||
|
|
||||||
/* not strictly necessary, but doing it here allows the shared_ptr debugging to work */
|
/* not strictly necessary, but doing it here allows the shared_ptr debugging to work */
|
||||||
playlists.reset ();
|
playlists.reset ();
|
||||||
|
|
||||||
|
|
@ -971,7 +962,7 @@ Session::enable_record ()
|
||||||
if (g_atomic_int_compare_and_exchange (&_record_status, rs, Recording)) {
|
if (g_atomic_int_compare_and_exchange (&_record_status, rs, Recording)) {
|
||||||
|
|
||||||
_last_record_location = _transport_frame;
|
_last_record_location = _transport_frame;
|
||||||
_mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordStrobe));
|
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordStrobe));
|
||||||
|
|
||||||
if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
|
if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
|
||||||
|
|
||||||
|
|
@ -999,7 +990,7 @@ Session::disable_record (bool rt_context, bool force)
|
||||||
|
|
||||||
if ((!Config->get_latched_record_enable () && !play_loop) || force) {
|
if ((!Config->get_latched_record_enable () && !play_loop) || force) {
|
||||||
g_atomic_int_set (&_record_status, Disabled);
|
g_atomic_int_set (&_record_status, Disabled);
|
||||||
_mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordExit));
|
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordExit));
|
||||||
} else {
|
} else {
|
||||||
if (rs == Recording) {
|
if (rs == Recording) {
|
||||||
g_atomic_int_set (&_record_status, Enabled);
|
g_atomic_int_set (&_record_status, Enabled);
|
||||||
|
|
@ -1059,7 +1050,7 @@ Session::maybe_enable_record ()
|
||||||
enable_record ();
|
enable_record ();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordPause));
|
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordPause));
|
||||||
RecordStateChanged (); /* EMIT SIGNAL */
|
RecordStateChanged (); /* EMIT SIGNAL */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3858,14 +3849,8 @@ Session::get_available_sync_options () const
|
||||||
vector<SyncSource> ret;
|
vector<SyncSource> ret;
|
||||||
|
|
||||||
ret.push_back (JACK);
|
ret.push_back (JACK);
|
||||||
|
|
||||||
if (mtc_input_port()) {
|
|
||||||
ret.push_back (MTC);
|
ret.push_back (MTC);
|
||||||
}
|
|
||||||
|
|
||||||
if (midi_clock_input_port()) {
|
|
||||||
ret.push_back (MIDIClock);
|
ret.push_back (MIDIClock);
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -130,8 +130,9 @@ Session::mmc_record_pause (MIDI::MachineControl &/*mmc*/)
|
||||||
void
|
void
|
||||||
Session::mmc_record_strobe (MIDI::MachineControl &/*mmc*/)
|
Session::mmc_record_strobe (MIDI::MachineControl &/*mmc*/)
|
||||||
{
|
{
|
||||||
if (!Config->get_mmc_control())
|
if (!Config->get_mmc_control()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* record strobe does an implicit "Play" command */
|
/* record strobe does an implicit "Play" command */
|
||||||
|
|
||||||
|
|
@ -358,7 +359,7 @@ Session::send_full_time_code (nframes64_t const t)
|
||||||
|
|
||||||
_send_timecode_update = false;
|
_send_timecode_update = false;
|
||||||
|
|
||||||
if (_mtc_output_port == 0 || !session_send_mtc || _slave) {
|
if (!session_send_mtc || _slave) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -393,7 +394,7 @@ Session::send_full_time_code (nframes64_t const t)
|
||||||
msg[8] = timecode.frames;
|
msg[8] = timecode.frames;
|
||||||
|
|
||||||
// Send message at offset 0, sent time is for the start of this cycle
|
// Send message at offset 0, sent time is for the start of this cycle
|
||||||
if (_mtc_output_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;
|
error << _("Session: could not send full MIDI time code") << endmsg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -411,7 +412,7 @@ Session::send_full_time_code (nframes64_t const t)
|
||||||
int
|
int
|
||||||
Session::send_midi_time_code_for_cycle(nframes_t nframes)
|
Session::send_midi_time_code_for_cycle(nframes_t nframes)
|
||||||
{
|
{
|
||||||
if (_mtc_output_port == 0 || _slave || !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";
|
// cerr << "(MTC) Not sending MTC\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -472,7 +473,7 @@ Session::send_midi_time_code_for_cycle(nframes_t nframes)
|
||||||
nframes_t out_stamp = msg_time - _transport_frame;
|
nframes_t out_stamp = msg_time - _transport_frame;
|
||||||
assert(out_stamp < nframes);
|
assert(out_stamp < nframes);
|
||||||
|
|
||||||
if (_mtc_output_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))
|
error << string_compose(_("Session: cannot send quarter-frame MTC message (%1)"), strerror (errno))
|
||||||
<< endmsg;
|
<< endmsg;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
|
|
@ -277,17 +277,6 @@ Session::first_stage_init (string fullpath, string snapshot_name)
|
||||||
|
|
||||||
Delivery::disable_panners ();
|
Delivery::disable_panners ();
|
||||||
IO::disable_connecting ();
|
IO::disable_connecting ();
|
||||||
|
|
||||||
/* Create MIDI control ports */
|
|
||||||
|
|
||||||
MIDI::Manager* m = MIDI::Manager::instance ();
|
|
||||||
|
|
||||||
_mtc_input_port = m->add_port (new MIDI::Port ("MTC in", MIDI::Port::IsInput, _engine.jack()));
|
|
||||||
_mtc_output_port = m->add_port (new MIDI::Port ("MTC out", MIDI::Port::IsOutput, _engine.jack()));
|
|
||||||
_midi_input_port = m->add_port (new MIDI::Port ("MIDI control in", MIDI::Port::IsInput, _engine.jack()));
|
|
||||||
_midi_output_port = m->add_port (new MIDI::Port ("MIDI control out", MIDI::Port::IsOutput, _engine.jack()));
|
|
||||||
_midi_clock_input_port = m->add_port (new MIDI::Port ("MIDI clock in", MIDI::Port::IsInput, _engine.jack()));
|
|
||||||
_midi_clock_output_port = m->add_port (new MIDI::Port ("MIDI clock out", MIDI::Port::IsOutput, _engine.jack()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -365,8 +354,8 @@ Session::second_stage_init ()
|
||||||
send_full_time_code (0);
|
send_full_time_code (0);
|
||||||
_engine.transport_locate (0);
|
_engine.transport_locate (0);
|
||||||
|
|
||||||
_mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
|
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
|
||||||
_mmc->send (MIDI::MachineControlCommand (Timecode::Time ()));
|
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ()));
|
||||||
|
|
||||||
MidiClockTicker::instance().set_session (this);
|
MidiClockTicker::instance().set_session (this);
|
||||||
MIDI::Name::MidiPatchManager::instance().set_session (this);
|
MIDI::Name::MidiPatchManager::instance().set_session (this);
|
||||||
|
|
@ -3203,11 +3192,11 @@ Session::config_changed (std::string p, bool ours)
|
||||||
|
|
||||||
} else if (p == "mmc-device-id" || p == "mmc-receive-id") {
|
} else if (p == "mmc-device-id" || p == "mmc-receive-id") {
|
||||||
|
|
||||||
_mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
|
MIDI::Manager::instance()->mmc()->set_receive_device_id (Config->get_mmc_receive_device_id());
|
||||||
|
|
||||||
} else if (p == "mmc-send-id") {
|
} else if (p == "mmc-send-id") {
|
||||||
|
|
||||||
_mmc->set_send_device_id (Config->get_mmc_send_device_id());
|
MIDI::Manager::instance()->mmc()->set_send_device_id (Config->get_mmc_send_device_id());
|
||||||
|
|
||||||
} else if (p == "midi-control") {
|
} else if (p == "midi-control") {
|
||||||
|
|
||||||
|
|
@ -3265,7 +3254,7 @@ Session::config_changed (std::string p, bool ours)
|
||||||
|
|
||||||
} else if (p == "send-mmc") {
|
} else if (p == "send-mmc") {
|
||||||
|
|
||||||
_mmc->enable_send (Config->get_send_mmc ());
|
MIDI::Manager::instance()->mmc()->enable_send (Config->get_send_mmc ());
|
||||||
|
|
||||||
} else if (p == "midi-feedback") {
|
} else if (p == "midi-feedback") {
|
||||||
|
|
||||||
|
|
@ -3307,13 +3296,13 @@ Session::config_changed (std::string p, bool ours)
|
||||||
sync_order_keys ("session");
|
sync_order_keys ("session");
|
||||||
} else if (p == "initial-program-change") {
|
} else if (p == "initial-program-change") {
|
||||||
|
|
||||||
if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
|
if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {
|
||||||
MIDI::byte buf[2];
|
MIDI::byte buf[2];
|
||||||
|
|
||||||
buf[0] = MIDI::program; // channel zero by default
|
buf[0] = MIDI::program; // channel zero by default
|
||||||
buf[1] = (Config->get_initial_program_change() & 0x7f);
|
buf[1] = (Config->get_initial_program_change() & 0x7f);
|
||||||
|
|
||||||
_mmc->output_port()->midimsg (buf, sizeof (buf), 0);
|
MIDI::Manager::instance()->mmc()->output_port()->midimsg (buf, sizeof (buf), 0);
|
||||||
}
|
}
|
||||||
} else if (p == "solo-mute-override") {
|
} else if (p == "solo-mute-override") {
|
||||||
// catch_up_on_solo_mute_override ();
|
// catch_up_on_solo_mute_override ();
|
||||||
|
|
@ -3362,29 +3351,29 @@ Session::load_diskstreams_2X (XMLNode const & node, int)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create our MachineControl object and connect things to it */
|
/** Connect things to the MMC object */
|
||||||
void
|
void
|
||||||
Session::setup_midi_machine_control ()
|
Session::setup_midi_machine_control ()
|
||||||
{
|
{
|
||||||
_mmc = new MIDI::MachineControl (_engine.jack());
|
MIDI::MachineControl* mmc = MIDI::Manager::instance()->mmc ();
|
||||||
|
|
||||||
_mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
|
mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
|
||||||
_mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
|
mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
|
||||||
_mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
|
mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
|
||||||
_mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
|
mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
|
||||||
_mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
|
mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
|
||||||
_mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
|
mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
|
||||||
_mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
|
mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
|
||||||
_mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
|
mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
|
||||||
_mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
|
mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
|
||||||
_mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
|
mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
|
||||||
_mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
|
mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
|
||||||
_mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
|
mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
|
||||||
_mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
|
mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
|
||||||
|
|
||||||
/* also handle MIDI SPP because its so common */
|
/* also handle MIDI SPP because its so common */
|
||||||
|
|
||||||
_mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this, _1, _2));
|
mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this, _1, _2));
|
||||||
_mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this, _1, _2));
|
mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this, _1, _2));
|
||||||
_mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this, _1, _2));
|
mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this, _1, _2));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "midi++/mmc.h"
|
#include "midi++/mmc.h"
|
||||||
#include "midi++/port.h"
|
#include "midi++/port.h"
|
||||||
|
#include "midi++/manager.h"
|
||||||
|
|
||||||
#include "ardour/ardour.h"
|
#include "ardour/ardour.h"
|
||||||
#include "ardour/audioengine.h"
|
#include "ardour/audioengine.h"
|
||||||
|
|
@ -184,7 +185,7 @@ Session::realtime_stop (bool abort, bool clear_state)
|
||||||
// FIXME: where should this really be? [DR]
|
// FIXME: where should this really be? [DR]
|
||||||
//send_full_time_code();
|
//send_full_time_code();
|
||||||
|
|
||||||
_mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
|
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
|
||||||
send_mmc_locate (_transport_frame);
|
send_mmc_locate (_transport_frame);
|
||||||
|
|
||||||
if (_transport_speed < 0.0f) {
|
if (_transport_speed < 0.0f) {
|
||||||
|
|
@ -1133,7 +1134,7 @@ Session::start_transport ()
|
||||||
|
|
||||||
Timecode::Time time;
|
Timecode::Time time;
|
||||||
timecode_time_subframes (_transport_frame, time);
|
timecode_time_subframes (_transport_frame, time);
|
||||||
_mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
|
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
|
||||||
|
|
||||||
TransportStateChange (); /* EMIT SIGNAL */
|
TransportStateChange (); /* EMIT SIGNAL */
|
||||||
}
|
}
|
||||||
|
|
@ -1246,19 +1247,13 @@ Session::switch_to_sync_source (SyncSource src)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_mtc_input_port) {
|
|
||||||
try {
|
try {
|
||||||
new_slave = new MTC_Slave (*this, *_mtc_input_port);
|
new_slave = new MTC_Slave (*this, *MIDI::Manager::instance()->mtc_input_port());
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (failed_constructor& err) {
|
catch (failed_constructor& err) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
error << _("No MTC port defined: MTC slaving is impossible.") << endmsg;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MIDIClock:
|
case MIDIClock:
|
||||||
|
|
@ -1266,19 +1261,13 @@ Session::switch_to_sync_source (SyncSource src)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_midi_clock_input_port) {
|
|
||||||
try {
|
try {
|
||||||
new_slave = new MIDIClock_Slave (*this, *_midi_clock_input_port, 24);
|
new_slave = new MIDIClock_Slave (*this, *MIDI::Manager::instance()->midi_clock_input_port(), 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (failed_constructor& err) {
|
catch (failed_constructor& err) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
error << _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JACK:
|
case JACK:
|
||||||
|
|
@ -1570,5 +1559,5 @@ Session::send_mmc_locate (nframes64_t t)
|
||||||
{
|
{
|
||||||
Timecode::Time time;
|
Timecode::Time time;
|
||||||
timecode_time_subframes (t, time);
|
timecode_time_subframes (t, time);
|
||||||
_mmc->send (MIDI::MachineControlCommand (time));
|
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (time));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "midi++/port.h"
|
#include "midi++/port.h"
|
||||||
|
#include "midi++/manager.h"
|
||||||
#include "evoral/midi_events.h"
|
#include "evoral/midi_events.h"
|
||||||
#include "ardour/ticker.h"
|
#include "ardour/ticker.h"
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
|
|
@ -45,7 +46,6 @@ void MidiClockTicker::set_session (Session* s)
|
||||||
Ticker::set_session (s);
|
Ticker::set_session (s);
|
||||||
|
|
||||||
if (_session) {
|
if (_session) {
|
||||||
_session->MIDIClock_PortChanged.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::update_midi_clock_port, this));
|
|
||||||
_session->TransportStateChange.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::transport_state_changed, this));
|
_session->TransportStateChange.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::transport_state_changed, this));
|
||||||
_session->PositionChanged.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::position_changed, this, _1));
|
_session->PositionChanged.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::position_changed, this, _1));
|
||||||
_session->TransportLooped.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::transport_looped, this));
|
_session->TransportLooped.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::transport_looped, this));
|
||||||
|
|
@ -62,7 +62,7 @@ MidiClockTicker::session_going_away ()
|
||||||
|
|
||||||
void MidiClockTicker::update_midi_clock_port()
|
void MidiClockTicker::update_midi_clock_port()
|
||||||
{
|
{
|
||||||
_midi_port = _session->midi_clock_output_port();
|
_midi_port = MIDI::Manager::instance()->midi_clock_output_port();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MidiClockTicker::transport_state_changed()
|
void MidiClockTicker::transport_state_changed()
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include "midi++/manager.h"
|
#include "midi++/manager.h"
|
||||||
#include "midi++/channel.h"
|
#include "midi++/channel.h"
|
||||||
#include "midi++/port.h"
|
#include "midi++/port.h"
|
||||||
|
#include "midi++/mmc.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace MIDI;
|
using namespace MIDI;
|
||||||
|
|
@ -34,12 +35,23 @@ using namespace PBD;
|
||||||
|
|
||||||
Manager *Manager::theManager = 0;
|
Manager *Manager::theManager = 0;
|
||||||
|
|
||||||
Manager::Manager ()
|
Manager::Manager (jack_client_t* jack)
|
||||||
{
|
{
|
||||||
|
_mmc = new MachineControl (this, jack);
|
||||||
|
|
||||||
|
_mtc_input_port = add_port (new MIDI::Port ("MTC in", Port::IsInput, jack));
|
||||||
|
_mtc_output_port = add_port (new MIDI::Port ("MTC out", Port::IsOutput, jack));
|
||||||
|
_midi_input_port = add_port (new MIDI::Port ("MIDI control in", Port::IsInput, jack));
|
||||||
|
_midi_output_port = add_port (new MIDI::Port ("MIDI control out", Port::IsOutput, jack));
|
||||||
|
_midi_clock_input_port = add_port (new MIDI::Port ("MIDI clock in", Port::IsInput, jack));
|
||||||
|
_midi_clock_output_port = add_port (new MIDI::Port ("MIDI clock out", Port::IsOutput, jack));
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager::~Manager ()
|
Manager::~Manager ()
|
||||||
{
|
{
|
||||||
|
delete _mmc;
|
||||||
|
|
||||||
|
/* This will delete our MTC etc. ports */
|
||||||
for (PortList::iterator p = _ports.begin(); p != _ports.end(); ++p) {
|
for (PortList::iterator p = _ports.begin(); p != _ports.end(); ++p) {
|
||||||
delete *p;
|
delete *p;
|
||||||
}
|
}
|
||||||
|
|
@ -77,10 +89,10 @@ Manager::cycle_end()
|
||||||
|
|
||||||
/** Re-register ports that disappear on JACK shutdown */
|
/** Re-register ports that disappear on JACK shutdown */
|
||||||
void
|
void
|
||||||
Manager::reestablish (void* a)
|
Manager::reestablish (jack_client_t* jack)
|
||||||
{
|
{
|
||||||
for (PortList::const_iterator p = _ports.begin(); p != _ports.end(); ++p) {
|
for (PortList::const_iterator p = _ports.begin(); p != _ports.end(); ++p) {
|
||||||
(*p)->reestablish (a);
|
(*p)->reestablish (jack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,3 +119,20 @@ Manager::port (string const & n)
|
||||||
|
|
||||||
return *p;
|
return *p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Manager::create (jack_client_t* jack)
|
||||||
|
{
|
||||||
|
assert (theManager == 0);
|
||||||
|
theManager = new Manager (jack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Manager::set_port_states (list<XMLNode*> s)
|
||||||
|
{
|
||||||
|
for (list<XMLNode*>::iterator i = s.begin(); i != s.end(); ++i) {
|
||||||
|
for (PortList::const_iterator j = _ports.begin(); j != _ports.end(); ++j) {
|
||||||
|
(*j)->set_state (**i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@
|
||||||
|
|
||||||
namespace MIDI {
|
namespace MIDI {
|
||||||
|
|
||||||
|
class MachineControl;
|
||||||
|
|
||||||
class Manager {
|
class Manager {
|
||||||
public:
|
public:
|
||||||
~Manager ();
|
~Manager ();
|
||||||
|
|
@ -46,22 +48,32 @@ class Manager {
|
||||||
*/
|
*/
|
||||||
void cycle_end();
|
void cycle_end();
|
||||||
|
|
||||||
|
MachineControl* mmc () const { return _mmc; }
|
||||||
|
Port *mtc_input_port() const { return _mtc_input_port; }
|
||||||
|
Port *mtc_output_port() const { return _mtc_output_port; }
|
||||||
|
Port *midi_input_port() const { return _midi_input_port; }
|
||||||
|
Port *midi_output_port() const { return _midi_output_port; }
|
||||||
|
Port *midi_clock_input_port() const { return _midi_clock_input_port; }
|
||||||
|
Port *midi_clock_output_port() const { return _midi_clock_output_port; }
|
||||||
|
|
||||||
Port* add_port (Port *);
|
Port* add_port (Port *);
|
||||||
|
|
||||||
Port* port (std::string const &);
|
Port* port (std::string const &);
|
||||||
|
|
||||||
|
void set_port_states (std::list<XMLNode*>);
|
||||||
|
|
||||||
typedef std::list<Port *> PortList;
|
typedef std::list<Port *> PortList;
|
||||||
|
|
||||||
const PortList& get_midi_ports() const { return _ports; }
|
const PortList& get_midi_ports() const { return _ports; }
|
||||||
|
|
||||||
|
static void create (jack_client_t* jack);
|
||||||
|
|
||||||
static Manager *instance () {
|
static Manager *instance () {
|
||||||
if (theManager == 0) {
|
assert (theManager);
|
||||||
theManager = new Manager;
|
|
||||||
}
|
|
||||||
return theManager;
|
return theManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reestablish (void *);
|
void reestablish (jack_client_t *);
|
||||||
void reconnect ();
|
void reconnect ();
|
||||||
|
|
||||||
PBD::Signal0<void> PortsChanged;
|
PBD::Signal0<void> PortsChanged;
|
||||||
|
|
@ -69,9 +81,17 @@ class Manager {
|
||||||
private:
|
private:
|
||||||
/* This is a SINGLETON pattern */
|
/* This is a SINGLETON pattern */
|
||||||
|
|
||||||
Manager ();
|
Manager (jack_client_t *);
|
||||||
static Manager *theManager;
|
static Manager *theManager;
|
||||||
|
|
||||||
|
MIDI::MachineControl* _mmc;
|
||||||
|
MIDI::Port* _mtc_input_port;
|
||||||
|
MIDI::Port* _mtc_output_port;
|
||||||
|
MIDI::Port* _midi_input_port;
|
||||||
|
MIDI::Port* _midi_output_port;
|
||||||
|
MIDI::Port* _midi_clock_input_port;
|
||||||
|
MIDI::Port* _midi_clock_output_port;
|
||||||
|
|
||||||
std::list<Port*> _ports;
|
std::list<Port*> _ports;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ namespace MIDI {
|
||||||
class Port;
|
class Port;
|
||||||
class Parser;
|
class Parser;
|
||||||
class MachineControlCommand;
|
class MachineControlCommand;
|
||||||
|
class Manager;
|
||||||
|
|
||||||
/** Class to handle incoming and outgoing MIDI machine control messages */
|
/** Class to handle incoming and outgoing MIDI machine control messages */
|
||||||
class MachineControl
|
class MachineControl
|
||||||
|
|
@ -88,7 +89,7 @@ class MachineControl
|
||||||
cmdResume = 0x7F
|
cmdResume = 0x7F
|
||||||
};
|
};
|
||||||
|
|
||||||
MachineControl (jack_client_t *);
|
MachineControl (Manager *, jack_client_t *);
|
||||||
|
|
||||||
Port* output_port() { return _output_port; }
|
Port* output_port() { return _output_port; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -126,13 +126,15 @@ class Port {
|
||||||
|
|
||||||
nframes_t nframes_this_cycle() const { return _nframes_this_cycle; }
|
nframes_t nframes_this_cycle() const { return _nframes_this_cycle; }
|
||||||
|
|
||||||
void reestablish (void *);
|
void reestablish (jack_client_t *);
|
||||||
void reconnect ();
|
void reconnect ();
|
||||||
|
|
||||||
static void set_process_thread (pthread_t);
|
static void set_process_thread (pthread_t);
|
||||||
static pthread_t get_process_thread () { return _process_thread; }
|
static pthread_t get_process_thread () { return _process_thread; }
|
||||||
static bool is_process_thread();
|
static bool is_process_thread();
|
||||||
|
|
||||||
|
static std::string state_node_name;
|
||||||
|
|
||||||
static PBD::Signal0<void> MakeConnections;
|
static PBD::Signal0<void> MakeConnections;
|
||||||
static PBD::Signal0<void> JackHalted;
|
static PBD::Signal0<void> JackHalted;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -195,15 +195,15 @@ static void build_mmc_cmd_map ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MachineControl::MachineControl (jack_client_t* jack)
|
MachineControl::MachineControl (Manager* m, jack_client_t* jack)
|
||||||
{
|
{
|
||||||
build_mmc_cmd_map ();
|
build_mmc_cmd_map ();
|
||||||
|
|
||||||
_receive_device_id = 0;
|
_receive_device_id = 0;
|
||||||
_send_device_id = 0x7f;
|
_send_device_id = 0x7f;
|
||||||
|
|
||||||
_input_port = Manager::instance()->add_port (new Port ("MMC in", Port::IsInput, jack));
|
_input_port = m->add_port (new Port ("MMC in", Port::IsInput, jack));
|
||||||
_output_port = Manager::instance()->add_port (new Port ("MMC out", Port::IsOutput, jack));
|
_output_port = m->add_port (new Port ("MMC out", Port::IsOutput, jack));
|
||||||
|
|
||||||
_input_port->parser()->mmc.connect_same_thread (port_connections, boost::bind (&MachineControl::process_mmc_message, this, _1, _2, _3));
|
_input_port->parser()->mmc.connect_same_thread (port_connections, boost::bind (&MachineControl::process_mmc_message, this, _1, _2, _3));
|
||||||
_input_port->parser()->start.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_start, this, _1, _2));
|
_input_port->parser()->start.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_start, this, _1, _2));
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ using namespace PBD;
|
||||||
pthread_t Port::_process_thread;
|
pthread_t Port::_process_thread;
|
||||||
Signal0<void> Port::JackHalted;
|
Signal0<void> Port::JackHalted;
|
||||||
Signal0<void> Port::MakeConnections;
|
Signal0<void> Port::MakeConnections;
|
||||||
|
string Port::state_node_name = "MIDI-port";
|
||||||
|
|
||||||
Port::Port (string const & name, Flags flags, jack_client_t* jack_client)
|
Port::Port (string const & name, Flags flags, jack_client_t* jack_client)
|
||||||
: _currently_in_cycle (false)
|
: _currently_in_cycle (false)
|
||||||
|
|
@ -406,7 +407,7 @@ Port::create_port ()
|
||||||
XMLNode&
|
XMLNode&
|
||||||
Port::get_state () const
|
Port::get_state () const
|
||||||
{
|
{
|
||||||
XMLNode* root = new XMLNode ("MIDI-port");
|
XMLNode* root = new XMLNode (state_node_name);
|
||||||
root->add_property ("tag", _tagname);
|
root->add_property ("tag", _tagname);
|
||||||
|
|
||||||
if (_flags == IsInput) {
|
if (_flags == IsInput) {
|
||||||
|
|
@ -459,6 +460,10 @@ Port::set_state (const XMLNode& node)
|
||||||
{
|
{
|
||||||
const XMLProperty* prop;
|
const XMLProperty* prop;
|
||||||
|
|
||||||
|
if ((prop = node.property ("tag")) == 0 || prop->value() != _tagname) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ((prop = node.property ("connections")) != 0 && _jack_port) {
|
if ((prop = node.property ("connections")) != 0 && _jack_port) {
|
||||||
_connections = prop->value ();
|
_connections = prop->value ();
|
||||||
}
|
}
|
||||||
|
|
@ -498,9 +503,9 @@ Port::is_process_thread()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Port::reestablish (void* jack)
|
Port::reestablish (jack_client_t* jack)
|
||||||
{
|
{
|
||||||
_jack_client = static_cast<jack_client_t*> (jack);
|
_jack_client = jack;
|
||||||
int const r = create_port ();
|
int const r = create_port ();
|
||||||
|
|
||||||
if (r) {
|
if (r) {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include "pbd/xml++.h"
|
#include "pbd/xml++.h"
|
||||||
|
|
||||||
#include "midi++/port.h"
|
#include "midi++/port.h"
|
||||||
|
#include "midi++/manager.h"
|
||||||
|
|
||||||
#include "ardour/filesystem_paths.h"
|
#include "ardour/filesystem_paths.h"
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
|
|
@ -56,8 +57,8 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
|
||||||
, gui (0)
|
, gui (0)
|
||||||
{
|
{
|
||||||
|
|
||||||
_input_port = s.midi_input_port ();
|
_input_port = MIDI::Manager::instance()->midi_input_port ();
|
||||||
_output_port = s.midi_output_port ();
|
_output_port = MIDI::Manager::instance()->midi_output_port ();
|
||||||
|
|
||||||
do_feedback = false;
|
do_feedback = false;
|
||||||
_feedback_interval = 10000; // microseconds
|
_feedback_interval = 10000; // microseconds
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue