diff options
author | Carl Hetherington <carl@carlh.net> | 2010-07-08 22:55:20 +0000 |
---|---|---|
committer | Carl Hetherington <carl@carlh.net> | 2010-07-08 22:55:20 +0000 |
commit | 648a169d8ff9987ba727e9ba50af4f33da6db165 (patch) | |
tree | d8e250205004633a9f5c94e15e8f3826fac183b6 /libs | |
parent | 3549189f87813b8c9f01f2f6484b34cf923a65ad (diff) |
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
Diffstat (limited to 'libs')
-rw-r--r-- | libs/ardour/ardour/rc_configuration.h | 6 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 21 | ||||
-rw-r--r-- | libs/ardour/globals.cc | 5 | ||||
-rw-r--r-- | libs/ardour/rc_configuration.cc | 15 | ||||
-rw-r--r-- | libs/ardour/session.cc | 27 | ||||
-rw-r--r-- | libs/ardour/session_midi.cc | 11 | ||||
-rw-r--r-- | libs/ardour/session_state.cc | 61 | ||||
-rw-r--r-- | libs/ardour/session_transport.cc | 37 | ||||
-rw-r--r-- | libs/ardour/ticker.cc | 4 | ||||
-rw-r--r-- | libs/midi++2/manager.cc | 35 | ||||
-rw-r--r-- | libs/midi++2/midi++/manager.h | 30 | ||||
-rw-r--r-- | libs/midi++2/midi++/mmc.h | 3 | ||||
-rw-r--r-- | libs/midi++2/midi++/port.h | 4 | ||||
-rw-r--r-- | libs/midi++2/mmc.cc | 6 | ||||
-rw-r--r-- | libs/midi++2/port.cc | 11 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/generic_midi_control_protocol.cc | 5 |
16 files changed, 152 insertions, 129 deletions
diff --git a/libs/ardour/ardour/rc_configuration.h b/libs/ardour/ardour/rc_configuration.h index de697a0b88..d54fd1b4e8 100644 --- a/libs/ardour/ardour/rc_configuration.h +++ b/libs/ardour/ardour/rc_configuration.h @@ -52,6 +52,7 @@ class RCConfiguration : public Configuration XMLNode * instant_xml (const std::string& str); XMLNode* control_protocol_state () { return _control_protocol_state; } + std::list<XMLNode*> midi_port_states () { return _midi_port_states; } /* define accessor methods */ @@ -80,6 +81,11 @@ class RCConfiguration : public Configuration #undef CONFIG_VARIABLE_SPECIAL 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 */ diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 890fde45e3..4a77a13b97 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -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> > BundleRemoved; - /* MIDI control */ - - 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; + void midi_panic (); /* Scrubbing */ @@ -944,13 +932,6 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi 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 _name; bool _is_new; diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc index 111b824c28..3aa6d6990d 100644 --- a/libs/ardour/globals.cc +++ b/libs/ardour/globals.cc @@ -328,12 +328,17 @@ ARDOUR::init (bool use_vst, bool try_optimization) void ARDOUR::init_post_engine () { + /* the MIDI Manager is needed by the ControlProtocolManager */ + MIDI::Manager::create (AudioEngine::instance()->jack()); + ControlProtocolManager::instance().discover_control_protocols (); XMLNode* node; if ((node = Config->control_protocol_state()) != 0) { ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version); } + + MIDI::Manager::instance()->set_port_states (Config->midi_port_states ()); } int diff --git a/libs/ardour/rc_configuration.cc b/libs/ardour/rc_configuration.cc index a50a994f87..3ca4868f63 100644 --- a/libs/ardour/rc_configuration.cc +++ b/libs/ardour/rc_configuration.cc @@ -68,6 +68,10 @@ 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; } @@ -254,19 +258,24 @@ RCConfiguration::set_state (const XMLNode& root, int /*version*/) XMLNodeConstIterator niter; 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) { node = *niter; if (node->name() == "Config") { - set_variables (*node); - } else if (node->name() == "Extra") { _extra_xml = new XMLNode (*node); - } else if (node->name() == ControlProtocolManager::state_node_name) { _control_protocol_state = new XMLNode (*node); + } else if (node->name() == MIDI::Port::state_node_name) { + _midi_port_states.push_back (new XMLNode (*node)); } } diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index a098bc3948..a19fa791d8 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -100,6 +100,7 @@ #include "midi++/port.h" #include "midi++/mmc.h" +#include "midi++/manager.h" #include "i18n.h" @@ -136,7 +137,6 @@ Session::Session (AudioEngine &eng, : _engine (eng), _target_transport_speed (0.0), _requested_return_frame (-1), - _mmc (0), _session_dir (new SessionDirectory(fullpath)), state_tree (0), _butler (new Butler (*this)), @@ -302,15 +302,6 @@ Session::destroy () 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 */ playlists.reset (); @@ -971,7 +962,7 @@ Session::enable_record () if (g_atomic_int_compare_and_exchange (&_record_status, rs, Recording)) { _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()) { @@ -999,7 +990,7 @@ Session::disable_record (bool rt_context, bool force) if ((!Config->get_latched_record_enable () && !play_loop) || force) { 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 { if (rs == Recording) { g_atomic_int_set (&_record_status, Enabled); @@ -1059,7 +1050,7 @@ Session::maybe_enable_record () enable_record (); } } else { - _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordPause)); + MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordPause)); RecordStateChanged (); /* EMIT SIGNAL */ } @@ -3858,14 +3849,8 @@ Session::get_available_sync_options () const vector<SyncSource> ret; ret.push_back (JACK); - - if (mtc_input_port()) { - ret.push_back (MTC); - } - - if (midi_clock_input_port()) { - ret.push_back (MIDIClock); - } + ret.push_back (MTC); + ret.push_back (MIDIClock); return ret; } diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc index 29040dc4df..3a27b1803b 100644 --- a/libs/ardour/session_midi.cc +++ b/libs/ardour/session_midi.cc @@ -130,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 */ @@ -358,7 +359,7 @@ Session::send_full_time_code (nframes64_t const t) _send_timecode_update = false; - if (_mtc_output_port == 0 || !session_send_mtc || _slave) { + if (!session_send_mtc || _slave) { return 0; } @@ -393,7 +394,7 @@ Session::send_full_time_code (nframes64_t const t) msg[8] = timecode.frames; // 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; return -1; } @@ -411,7 +412,7 @@ Session::send_full_time_code (nframes64_t const t) int 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"; return 0; } @@ -472,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_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)) << endmsg; return -1; diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index f6bdfdb4cc..7f067ae407 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -277,17 +277,6 @@ Session::first_stage_init (string fullpath, string snapshot_name) Delivery::disable_panners (); 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 @@ -365,8 +354,8 @@ Session::second_stage_init () send_full_time_code (0); _engine.transport_locate (0); - _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset)); - _mmc->send (MIDI::MachineControlCommand (Timecode::Time ())); + MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset)); + MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ())); MidiClockTicker::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") { - _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") { - _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") { @@ -3265,7 +3254,7 @@ Session::config_changed (std::string p, bool ours) } 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") { @@ -3307,13 +3296,13 @@ Session::config_changed (std::string p, bool ours) sync_order_keys ("session"); } 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]; buf[0] = MIDI::program; // channel zero by default 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") { // catch_up_on_solo_mute_override (); @@ -3362,29 +3351,29 @@ Session::load_diskstreams_2X (XMLNode const & node, int) return 0; } -/** Create our MachineControl object and connect things to it */ +/** Connect things to the MMC object */ void 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->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->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->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->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->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->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->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->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->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->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->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->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->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3)); /* also handle MIDI SPP because its so common */ - _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->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, 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->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this, _1, _2)); } diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 037d041895..7c00538e44 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -30,6 +30,7 @@ #include "midi++/mmc.h" #include "midi++/port.h" +#include "midi++/manager.h" #include "ardour/ardour.h" #include "ardour/audioengine.h" @@ -184,7 +185,7 @@ Session::realtime_stop (bool abort, bool clear_state) // FIXME: where should this really be? [DR] //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); if (_transport_speed < 0.0f) { @@ -1133,7 +1134,7 @@ Session::start_transport () Timecode::Time 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 */ } @@ -1246,17 +1247,11 @@ Session::switch_to_sync_source (SyncSource src) return; } - if (_mtc_input_port) { - try { - new_slave = new MTC_Slave (*this, *_mtc_input_port); - } - - catch (failed_constructor& err) { - return; - } + try { + new_slave = new MTC_Slave (*this, *MIDI::Manager::instance()->mtc_input_port()); + } - } else { - error << _("No MTC port defined: MTC slaving is impossible.") << endmsg; + catch (failed_constructor& err) { return; } break; @@ -1266,17 +1261,11 @@ Session::switch_to_sync_source (SyncSource src) return; } - if (_midi_clock_input_port) { - try { - new_slave = new MIDIClock_Slave (*this, *_midi_clock_input_port, 24); - } - - catch (failed_constructor& err) { - return; - } - - } else { - error << _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg; + try { + new_slave = new MIDIClock_Slave (*this, *MIDI::Manager::instance()->midi_clock_input_port(), 24); + } + + catch (failed_constructor& err) { return; } break; @@ -1570,5 +1559,5 @@ Session::send_mmc_locate (nframes64_t t) { Timecode::Time time; timecode_time_subframes (t, time); - _mmc->send (MIDI::MachineControlCommand (time)); + MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (time)); } diff --git a/libs/ardour/ticker.cc b/libs/ardour/ticker.cc index f1792e3ffd..98f0632c45 100644 --- a/libs/ardour/ticker.cc +++ b/libs/ardour/ticker.cc @@ -19,6 +19,7 @@ */ #include "midi++/port.h" +#include "midi++/manager.h" #include "evoral/midi_events.h" #include "ardour/ticker.h" #include "ardour/session.h" @@ -45,7 +46,6 @@ void MidiClockTicker::set_session (Session* s) Ticker::set_session (s); 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->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)); @@ -62,7 +62,7 @@ MidiClockTicker::session_going_away () 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() diff --git a/libs/midi++2/manager.cc b/libs/midi++2/manager.cc index c8094d4d4f..cab42d8d81 100644 --- a/libs/midi++2/manager.cc +++ b/libs/midi++2/manager.cc @@ -27,6 +27,7 @@ #include "midi++/manager.h" #include "midi++/channel.h" #include "midi++/port.h" +#include "midi++/mmc.h" using namespace std; using namespace MIDI; @@ -34,12 +35,23 @@ using namespace PBD; 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 () { + delete _mmc; + + /* This will delete our MTC etc. ports */ for (PortList::iterator p = _ports.begin(); p != _ports.end(); ++p) { delete *p; } @@ -77,10 +89,10 @@ Manager::cycle_end() /** Re-register ports that disappear on JACK shutdown */ void -Manager::reestablish (void* a) +Manager::reestablish (jack_client_t* jack) { 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; } + +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); + } + } +} diff --git a/libs/midi++2/midi++/manager.h b/libs/midi++2/midi++/manager.h index 2193c1eb23..6ee9dbf68b 100644 --- a/libs/midi++2/midi++/manager.h +++ b/libs/midi++2/midi++/manager.h @@ -29,6 +29,8 @@ namespace MIDI { +class MachineControl; + class Manager { public: ~Manager (); @@ -46,22 +48,32 @@ class Manager { */ 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* port (std::string const &); + void set_port_states (std::list<XMLNode*>); + typedef std::list<Port *> PortList; const PortList& get_midi_ports() const { return _ports; } + static void create (jack_client_t* jack); + static Manager *instance () { - if (theManager == 0) { - theManager = new Manager; - } + assert (theManager); return theManager; } - void reestablish (void *); + void reestablish (jack_client_t *); void reconnect (); PBD::Signal0<void> PortsChanged; @@ -69,8 +81,16 @@ class Manager { private: /* This is a SINGLETON pattern */ - Manager (); + Manager (jack_client_t *); 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; }; diff --git a/libs/midi++2/midi++/mmc.h b/libs/midi++2/midi++/mmc.h index ec3eb8bbb1..20063c3e91 100644 --- a/libs/midi++2/midi++/mmc.h +++ b/libs/midi++2/midi++/mmc.h @@ -32,6 +32,7 @@ namespace MIDI { class Port; class Parser; class MachineControlCommand; +class Manager; /** Class to handle incoming and outgoing MIDI machine control messages */ class MachineControl @@ -88,7 +89,7 @@ class MachineControl cmdResume = 0x7F }; - MachineControl (jack_client_t *); + MachineControl (Manager *, jack_client_t *); Port* output_port() { return _output_port; } diff --git a/libs/midi++2/midi++/port.h b/libs/midi++2/midi++/port.h index 6d1191866b..d0b6249ebe 100644 --- a/libs/midi++2/midi++/port.h +++ b/libs/midi++2/midi++/port.h @@ -126,12 +126,14 @@ class Port { nframes_t nframes_this_cycle() const { return _nframes_this_cycle; } - void reestablish (void *); + void reestablish (jack_client_t *); void reconnect (); static void set_process_thread (pthread_t); static pthread_t get_process_thread () { return _process_thread; } static bool is_process_thread(); + + static std::string state_node_name; static PBD::Signal0<void> MakeConnections; static PBD::Signal0<void> JackHalted; diff --git a/libs/midi++2/mmc.cc b/libs/midi++2/mmc.cc index 69bdabf1e5..930666a027 100644 --- a/libs/midi++2/mmc.cc +++ b/libs/midi++2/mmc.cc @@ -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 (); _receive_device_id = 0; _send_device_id = 0x7f; - _input_port = Manager::instance()->add_port (new Port ("MMC in", Port::IsInput, jack)); - _output_port = Manager::instance()->add_port (new Port ("MMC out", Port::IsOutput, jack)); + _input_port = m->add_port (new Port ("MMC in", Port::IsInput, 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()->start.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_start, this, _1, _2)); diff --git a/libs/midi++2/port.cc b/libs/midi++2/port.cc index a6097c89dc..65cba24eb0 100644 --- a/libs/midi++2/port.cc +++ b/libs/midi++2/port.cc @@ -42,6 +42,7 @@ using namespace PBD; pthread_t Port::_process_thread; Signal0<void> Port::JackHalted; Signal0<void> Port::MakeConnections; +string Port::state_node_name = "MIDI-port"; Port::Port (string const & name, Flags flags, jack_client_t* jack_client) : _currently_in_cycle (false) @@ -406,7 +407,7 @@ Port::create_port () XMLNode& Port::get_state () const { - XMLNode* root = new XMLNode ("MIDI-port"); + XMLNode* root = new XMLNode (state_node_name); root->add_property ("tag", _tagname); if (_flags == IsInput) { @@ -459,6 +460,10 @@ Port::set_state (const XMLNode& node) { const XMLProperty* prop; + if ((prop = node.property ("tag")) == 0 || prop->value() != _tagname) { + return; + } + if ((prop = node.property ("connections")) != 0 && _jack_port) { _connections = prop->value (); } @@ -498,9 +503,9 @@ Port::is_process_thread() } 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 (); if (r) { diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc index de7c00171b..89d353cf79 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc @@ -30,6 +30,7 @@ #include "pbd/xml++.h" #include "midi++/port.h" +#include "midi++/manager.h" #include "ardour/filesystem_paths.h" #include "ardour/session.h" @@ -56,8 +57,8 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s) , gui (0) { - _input_port = s.midi_input_port (); - _output_port = s.midi_output_port (); + _input_port = MIDI::Manager::instance()->midi_input_port (); + _output_port = MIDI::Manager::instance()->midi_output_port (); do_feedback = false; _feedback_interval = 10000; // microseconds |