From 83a0c30c24ce6bb6e3e718c267a82fbaffc33b4b Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Wed, 7 Aug 2013 22:21:36 -0400 Subject: major redesign of MIDI port heirarchy and management basic, very flaky functionality is back. program unstable at present --- libs/ardour/ardour/midiport_manager.h | 94 +++++++ libs/ardour/midiport_manager.cc | 89 +++++++ libs/midi++2/jack_midi_port.cc | 474 ---------------------------------- libs/midi++2/manager.cc | 183 ------------- libs/midi++2/midi++/jack_midi_port.h | 104 -------- libs/midi++2/midi++/manager.h | 107 -------- 6 files changed, 183 insertions(+), 868 deletions(-) create mode 100644 libs/ardour/ardour/midiport_manager.h create mode 100644 libs/ardour/midiport_manager.cc delete mode 100644 libs/midi++2/jack_midi_port.cc delete mode 100644 libs/midi++2/manager.cc delete mode 100644 libs/midi++2/midi++/jack_midi_port.h delete mode 100644 libs/midi++2/midi++/manager.h diff --git a/libs/ardour/ardour/midiport_manager.h b/libs/ardour/ardour/midiport_manager.h new file mode 100644 index 0000000000..9c45e60341 --- /dev/null +++ b/libs/ardour/ardour/midiport_manager.h @@ -0,0 +1,94 @@ +/* + Copyright (C) 1998 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __midiport_manager_h__ +#define __midiport_manager_h__ + +#include + +#include + +#include "pbd/rcu.h" + +#include "midi++/types.h" +#include "midi++/port.h" + +#include "ardour/types.h" + +namespace ARDOUR { + +class MidiPort; +class Port; + +class MidiPortManager { + public: + MidiPortManager(); + virtual ~MidiPortManager (); + + MidiPort* add_port (MidiPort *); + void remove_port (MidiPort *); + + MidiPort* port (const std::string&); + + /* Ports used for control. These are read/written to outside of the + * process callback (asynchronously with respect to when data + * actually arrives). + * + * More detail: we do actually read/write data for these ports + * inside the process callback, but incoming data is only parsed + * and outgoing data is only generated *outside* the process + * callback. + */ + + MIDI::Port* midi_input_port () { return _midi_input_port; } + MIDI::Port* midi_output_port () { return _midi_output_port; } + + /* Ports used for synchronization. These have their I/O handled inside the + * process callback. + */ + + boost::shared_ptr mtc_input_port() const { return _mtc_input_port; } + boost::shared_ptr mtc_output_port() const { return _mtc_output_port; } + boost::shared_ptr midi_clock_input_port() const { return _midi_clock_input_port; } + boost::shared_ptr midi_clock_output_port() const { return _midi_clock_output_port; } + + void set_port_states (std::list); + + PBD::Signal0 PortsChanged; + + protected: + /* asynchronously handled ports: MIDI::Port */ + MIDI::Port* _midi_input_port; + MIDI::Port* _midi_output_port; + boost::shared_ptr _midi_in; + boost::shared_ptr _midi_out; + + /* synchronously handled ports: ARDOUR::MidiPort */ + boost::shared_ptr _mtc_input_port; + boost::shared_ptr _mtc_output_port; + boost::shared_ptr _midi_clock_input_port; + boost::shared_ptr _midi_clock_output_port; + + void create_ports (); + +}; + +} // namespace MIDI + +#endif // __midi_port_manager_h__ diff --git a/libs/ardour/midiport_manager.cc b/libs/ardour/midiport_manager.cc new file mode 100644 index 0000000000..fb27800762 --- /dev/null +++ b/libs/ardour/midiport_manager.cc @@ -0,0 +1,89 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include "ardour/audioengine.h" +#include "ardour/async_midi_port.h" +#include "ardour/midiport_manager.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace std; +using namespace MIDI; +using namespace PBD; + + +MidiPortManager::MidiPortManager () +{ +} + +MidiPortManager::~MidiPortManager () +{ + if (_midi_in) { + AudioEngine::instance()->unregister_port (_midi_in); + } + if (_midi_in) { + AudioEngine::instance()->unregister_port (_midi_in); + } + if (_mtc_input_port) { + AudioEngine::instance()->unregister_port (_mtc_input_port); + } + if (_mtc_output_port) { + AudioEngine::instance()->unregister_port (_mtc_output_port); + } + if (_midi_clock_input_port) { + AudioEngine::instance()->unregister_port (_midi_clock_input_port); + } + if (_midi_clock_output_port) { + AudioEngine::instance()->unregister_port (_midi_clock_output_port); + } + +} + +MidiPort* +MidiPortManager::port (string const & n) +{ + boost::shared_ptr mp = boost::dynamic_pointer_cast (AudioEngine::instance()->get_port_by_name (n)); + return mp.get(); +} + +void +MidiPortManager::create_ports () +{ + _midi_in = AudioEngine::instance()->register_input_port (DataType::MIDI, _("MIDI control in"), true); + _midi_out = AudioEngine::instance()->register_output_port (DataType::MIDI, _("MIDI control out"), true); + + _midi_input_port = boost::dynamic_pointer_cast(_midi_in).get(); + _midi_output_port = boost::dynamic_pointer_cast(_midi_out).get(); +} + +void +MidiPortManager::set_port_states (list s) +{ + PortManager::PortList pl; + + AudioEngine::instance()->get_ports (DataType::MIDI, pl); + + for (list::iterator i = s.begin(); i != s.end(); ++i) { + for (PortManager::PortList::const_iterator j = pl.begin(); j != pl.end(); ++j) { + // (*j)->set_state (**i); + } + } +} + diff --git a/libs/midi++2/jack_midi_port.cc b/libs/midi++2/jack_midi_port.cc deleted file mode 100644 index 8ba27759bc..0000000000 --- a/libs/midi++2/jack_midi_port.cc +++ /dev/null @@ -1,474 +0,0 @@ -/* - Copyright (C) 1998 Paul Barton-Davis - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id$ -*/ -#include -#include -#include -#include - -#include "pbd/xml++.h" -#include "pbd/error.h" -#include "pbd/failed_constructor.h" -#include "pbd/convert.h" -#include "pbd/strsplit.h" -#include "pbd/stacktrace.h" - -#include "midi++/types.h" -#include "midi++/jack_midi_port.h" -#include "midi++/channel.h" - -using namespace MIDI; -using namespace std; -using namespace PBD; - -namespace Evoral { -template class EventRingBuffer; -} - -pthread_t JackMIDIPort::_process_thread; -Signal0 JackMIDIPort::EngineHalted; -Signal0 JackMIDIPort::MakeConnections; - -JackMIDIPort::JackMIDIPort (string const & name, Flags flags, ARDOUR::PortEngine& pengine) - : Port (name, flags) - , _port_engine (pengine) - , _port_handle (0) - , _currently_in_cycle (false) - , _nframes_this_cycle (0) - , _last_write_timestamp (0) - , output_fifo (512) - , input_fifo (1024) - , xthread (true) -{ - init (name, flags); -} - -JackMIDIPort::JackMIDIPort (const XMLNode& node, ARDOUR::PortEngine& pengine) - : Port (node) - , _port_engine (pengine) - , _port_handle (0) - , _currently_in_cycle (false) - , _nframes_this_cycle (0) - , _last_write_timestamp (0) - , output_fifo (512) - , input_fifo (1024) - , xthread (true) -{ - Descriptor desc (node); - init (desc.tag, desc.flags); - set_state (node); -} - -void -JackMIDIPort::init (const string& /*name*/, Flags /*flags*/) -{ - if (!create_port ()) { - _ok = true; - } - - MakeConnections.connect_same_thread (connect_connection, boost::bind (&JackMIDIPort::make_connections, this)); - EngineHalted.connect_same_thread (halt_connection, boost::bind (&JackMIDIPort::engine_halted, this)); -} - - -JackMIDIPort::~JackMIDIPort () -{ - if (_port_handle) { - _port_engine.unregister_port (_port_handle); - _port_handle = 0; - } -} - -void -JackMIDIPort::parse (framecnt_t timestamp) -{ - byte buf[512]; - - /* NOTE: parsing is done (if at all) by initiating a read from - the port. Each port implementation calls on the parser - once it has data ready. - */ - - _parser->set_timestamp (timestamp); - - while (1) { - - // cerr << "+++ READ ON " << name() << endl; - - int nread = read (buf, sizeof (buf)); - - // cerr << "-- READ (" << nread << " ON " << name() << endl; - - if (nread > 0) { - if ((size_t) nread < sizeof (buf)) { - break; - } else { - continue; - } - } else if (nread == 0) { - break; - } else if (errno == EAGAIN) { - break; - } else { - fatal << "Error reading from MIDI port " << name() << endmsg; - /*NOTREACHED*/ - } - } -} - -void -JackMIDIPort::cycle_start (pframes_t nframes) -{ - assert (_port_handle); - - _currently_in_cycle = true; - _nframes_this_cycle = nframes; - - assert(_nframes_this_cycle == nframes); - - if (sends_output()) { - void *buffer = _port_engine.get_buffer (_port_handle, nframes); - jack_midi_clear_buffer (buffer); - flush (buffer); - } - - if (receives_input()) { - void* buffer = _port_engine.get_buffer (_port_handle, nframes); - const pframes_t event_count = _port_engine.get_midi_event_count (buffer); - - pframes_t time; - size_t size; - uint8_t* buf; - timestamp_t cycle_start_frame = _port_engine.sample_time_at_cycle_start (); - - for (pframes_t i = 0; i < event_count; ++i) { - _port_engine.midi_event_get (time, size, &buf, buffer, i); - input_fifo.write (cycle_start_frame + time, (Evoral::EventType) 0, size, buf); - } - - if (event_count) { - xthread.wakeup (); - } - } -} - -void -JackMIDIPort::cycle_end () -{ - if (sends_output()) { - flush (_port_engine.get_buffer (_port_handle, _nframes_this_cycle)); - } - - _currently_in_cycle = false; - _nframes_this_cycle = 0; -} - -void -JackMIDIPort::engine_halted () -{ - _port_handle = 0; -} - -void -JackMIDIPort::drain (int check_interval_usecs) -{ - RingBuffer< Evoral::Event >::rw_vector vec = { { 0, 0 }, { 0, 0} }; - - if (is_process_thread()) { - error << "Process thread called MIDI::JackMIDIPort::drain() - this cannot work" << endmsg; - return; - } - - while (1) { - output_fifo.get_write_vector (&vec); - if (vec.len[0] + vec.len[1] >= output_fifo.bufsize() - 1) { - break; - } - usleep (check_interval_usecs); - } -} - -int -JackMIDIPort::write (const byte * msg, size_t msglen, timestamp_t timestamp) -{ - int ret = 0; - - if (!_port_handle) { - /* poof ! make it just vanish into thin air, since we are no - longer connected to JACK. - */ - return msglen; - } - - if (!sends_output()) { - return ret; - } - - if (!is_process_thread()) { - - Glib::Threads::Mutex::Lock lm (output_fifo_lock); - RingBuffer< Evoral::Event >::rw_vector vec = { { 0, 0 }, { 0, 0} }; - - output_fifo.get_write_vector (&vec); - - if (vec.len[0] + vec.len[1] < 1) { - error << "no space in FIFO for non-process thread MIDI write" << endmsg; - return 0; - } - - if (vec.len[0]) { - if (!vec.buf[0]->owns_buffer()) { - vec.buf[0]->set_buffer (0, 0, true); - } - vec.buf[0]->set (msg, msglen, timestamp); - } else { - if (!vec.buf[1]->owns_buffer()) { - vec.buf[1]->set_buffer (0, 0, true); - } - vec.buf[1]->set (msg, msglen, timestamp); - } - - output_fifo.increment_write_idx (1); - - ret = msglen; - - } else { - - if (timestamp >= _nframes_this_cycle) { - std::cerr << "attempting to write MIDI event of " << msglen << " bytes at time " - << timestamp << " of " << _nframes_this_cycle - << " (this will not work - needs a code fix)" - << std::endl; - } - - if (_currently_in_cycle) { - if (timestamp == 0) { - timestamp = _last_write_timestamp; - } - - if ((ret = _port_engine.midi_event_put (_port_engine.get_buffer (_port_handle, _nframes_this_cycle), - timestamp, msg, msglen)) == 0) { - ret = msglen; - _last_write_timestamp = timestamp; - - } else { - cerr << "write of " << msglen << " @ " << timestamp << " failed, port holds " - << _port_engine.get_midi_event_count (_port_engine.get_buffer (_port_handle, _nframes_this_cycle)) - << " port is " << _port_handle - << " ntf = " << _nframes_this_cycle - << " buf = " << _port_engine.get_buffer (_port_handle, _nframes_this_cycle) - << " ret = " << ret - << endl; - PBD::stacktrace (cerr, 20); - ret = 0; - } - } else { - cerr << "write to JACK midi port failed: not currently in a process cycle." << endl; - PBD::stacktrace (cerr, 20); - } - } - - if (ret > 0 && _parser) { - // ardour doesn't care about this and neither should your app, probably - // output_parser->raw_preparse (*output_parser, msg, ret); - for (int i = 0; i < ret; i++) { - _parser->scanner (msg[i]); - } - // ardour doesn't care about this and neither should your app, probably - // output_parser->raw_postparse (*output_parser, msg, ret); - } - - return ret; -} - -void -JackMIDIPort::flush (void* port_buffer) -{ - RingBuffer< Evoral::Event >::rw_vector vec = { { 0, 0 }, { 0, 0 } }; - size_t written; - - output_fifo.get_read_vector (&vec); - - if (vec.len[0] + vec.len[1]) { - // cerr << "Flush " << vec.len[0] + vec.len[1] << " events from non-process FIFO\n"; - } - - if (vec.len[0]) { - Evoral::Event* evp = vec.buf[0]; - - for (size_t n = 0; n < vec.len[0]; ++n, ++evp) { - _port_engine.midi_event_put (port_buffer, (timestamp_t) evp->time(), evp->buffer(), evp->size()); - } - } - - if (vec.len[1]) { - Evoral::Event* evp = vec.buf[1]; - - for (size_t n = 0; n < vec.len[1]; ++n, ++evp) { - _port_engine.midi_event_put (port_buffer, (timestamp_t) evp->time(), evp->buffer(), evp->size()); - } - } - - if ((written = vec.len[0] + vec.len[1]) != 0) { - output_fifo.increment_read_idx (written); - } -} - -int -JackMIDIPort::read (byte *, size_t) -{ - if (!receives_input()) { - return 0; - } - - timestamp_t time; - Evoral::EventType type; - uint32_t size; - byte buffer[input_fifo.capacity()]; - - while (input_fifo.read (&time, &type, &size, buffer)) { - _parser->set_timestamp (time); - for (uint32_t i = 0; i < size; ++i) { - _parser->scanner (buffer[i]); - } - } - - return 0; -} - -int -JackMIDIPort::create_port () -{ - ARDOUR::PortFlags f = ARDOUR::PortFlags (0); - - /* convert MIDI::Port::Flags to ARDOUR::PortFlags ... sigh */ - - if (_flags & IsInput) { - f = ARDOUR::PortFlags (f | ARDOUR::IsInput); - } - - if (_flags & IsOutput) { - f = ARDOUR::PortFlags (f | ARDOUR::IsOutput); - } - - _port_handle = _port_engine.register_port (_tagname, ARDOUR::DataType::MIDI, f); - - return _port_handle == 0 ? -1 : 0; -} - -XMLNode& -JackMIDIPort::get_state () const -{ - XMLNode& root = Port::get_state (); - -#if 0 - byte device_inquiry[6]; - - device_inquiry[0] = 0xf0; - device_inquiry[0] = 0x7e; - device_inquiry[0] = 0x7f; - device_inquiry[0] = 0x06; - device_inquiry[0] = 0x02; - device_inquiry[0] = 0xf7; - - write (device_inquiry, sizeof (device_inquiry), 0); -#endif - - if (_port_handle) { - - vector connections; - _port_engine.get_connections (_port_handle, connections); - string connection_string; - for (vector::iterator i = connections.begin(); i != connections.end(); ++i) { - if (i != connections.begin()) { - connection_string += ','; - } - connection_string += *i; - } - - if (!connection_string.empty()) { - root.add_property ("connections", connection_string); - } - } else { - if (!_connections.empty()) { - root.add_property ("connections", _connections); - } - } - - return root; -} - -void -JackMIDIPort::set_state (const XMLNode& node) -{ - const XMLProperty* prop; - - if ((prop = node.property ("tag")) == 0 || prop->value() != _tagname) { - return; - } - - Port::set_state (node); - - if ((prop = node.property ("connections")) != 0) { - _connections = prop->value (); - } -} - -void -JackMIDIPort::make_connections () -{ - if (!_connections.empty()) { - vector ports; - split (_connections, ports, ','); - for (vector::iterator x = ports.begin(); x != ports.end(); ++x) { - _port_engine.connect (_port_handle, *x); - /* ignore failures */ - } - } - - connect_connection.disconnect (); -} - -void -JackMIDIPort::set_process_thread (pthread_t thr) -{ - _process_thread = thr; -} - -bool -JackMIDIPort::is_process_thread() -{ - return (pthread_self() == _process_thread); -} - -void -JackMIDIPort::reestablish () -{ - int const r = create_port (); - - if (r) { - PBD::error << "could not reregister ports for " << name() << endmsg; - } -} - -void -JackMIDIPort::reconnect () -{ - make_connections (); -} diff --git a/libs/midi++2/manager.cc b/libs/midi++2/manager.cc deleted file mode 100644 index 3df9681dd3..0000000000 --- a/libs/midi++2/manager.cc +++ /dev/null @@ -1,183 +0,0 @@ -/* - Copyright (C) 1998-99 Paul Barton-Davis - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id$ -*/ - -#include - -#include - -#include "pbd/error.h" - -#include "midi++/types.h" -#include "midi++/manager.h" -#include "midi++/channel.h" -#include "midi++/port.h" -#include "midi++/jack_midi_port.h" -#include "midi++/mmc.h" - -using namespace std; -using namespace MIDI; -using namespace PBD; - -Manager *Manager::theManager = 0; - -Manager::Manager (ARDOUR::PortEngine& eng) - : _ports (new PortList) -{ - _mmc = new MachineControl (this, eng); - - _mtc_input_port = add_port (new MIDI::JackMIDIPort ("MTC in", Port::IsInput, eng)); - _mtc_output_port = add_port (new MIDI::JackMIDIPort ("MTC out", Port::IsOutput, eng)); - _midi_input_port = add_port (new MIDI::JackMIDIPort ("MIDI control in", Port::IsInput, eng)); - _midi_output_port = add_port (new MIDI::JackMIDIPort ("MIDI control out", Port::IsOutput, eng)); - _midi_clock_input_port = add_port (new MIDI::JackMIDIPort ("MIDI clock in", Port::IsInput, eng)); - _midi_clock_output_port = add_port (new MIDI::JackMIDIPort ("MIDI clock out", Port::IsOutput, eng)); -} - -Manager::~Manager () -{ - delete _mmc; - - /* This will delete our MTC etc. ports */ - - boost::shared_ptr pr = _ports.reader (); - for (PortList::iterator p = pr->begin(); p != pr->end(); ++p) { - delete *p; - } - - if (theManager == this) { - theManager = 0; - } -} - -Port * -Manager::add_port (Port* p) -{ - { - RCUWriter writer (_ports); - boost::shared_ptr pw = writer.get_copy (); - pw->push_back (p); - } - - PortsChanged (); /* EMIT SIGNAL */ - - return p; -} - -void -Manager::remove_port (Port* p) -{ - { - RCUWriter writer (_ports); - boost::shared_ptr pw = writer.get_copy (); - pw->remove (p); - } - - PortsChanged (); /* EMIT SIGNAL */ -} - -void -Manager::cycle_start (pframes_t nframes) -{ - boost::shared_ptr pr = _ports.reader (); - - for (PortList::iterator p = pr->begin(); p != pr->end(); ++p) { - (*p)->cycle_start (nframes); - } -} - -void -Manager::cycle_end() -{ - boost::shared_ptr pr = _ports.reader (); - - for (PortList::iterator p = pr->begin(); p != pr->end(); ++p) { - (*p)->cycle_end (); - } -} - -/** Re-register ports that disappear on JACK shutdown */ -void -Manager::reestablish () -{ - boost::shared_ptr pr = _ports.reader (); - - for (PortList::const_iterator p = pr->begin(); p != pr->end(); ++p) { - JackMIDIPort* pp = dynamic_cast (*p); - if (pp) { - pp->reestablish (); - } - } -} - -/** Re-connect ports after a reestablish () */ -void -Manager::reconnect () -{ - boost::shared_ptr pr = _ports.reader (); - - for (PortList::const_iterator p = pr->begin(); p != pr->end(); ++p) { - JackMIDIPort* pp = dynamic_cast (*p); - if (pp) { - pp->reconnect (); - } - } -} - -Port* -Manager::port (string const & n) -{ - boost::shared_ptr pr = _ports.reader (); - - PortList::const_iterator p = pr->begin(); - while (p != pr->end() && (*p)->name() != n) { - ++p; - } - - if (p == pr->end()) { - return 0; - } - - return *p; -} - -void -Manager::create (ARDOUR::PortEngine& eng) -{ - assert (theManager == 0); - theManager = new Manager (eng); -} - -void -Manager::set_port_states (list s) -{ - boost::shared_ptr pr = _ports.reader (); - - for (list::iterator i = s.begin(); i != s.end(); ++i) { - for (PortList::const_iterator j = pr->begin(); j != pr->end(); ++j) { - (*j)->set_state (**i); - } - } -} - -void -Manager::destroy () -{ - delete theManager; - theManager = 0; -} diff --git a/libs/midi++2/midi++/jack_midi_port.h b/libs/midi++2/midi++/jack_midi_port.h deleted file mode 100644 index 492756067c..0000000000 --- a/libs/midi++2/midi++/jack_midi_port.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - Copyright (C) 1998-2010 Paul Barton-Davis - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef __libmidi_port_h__ -#define __libmidi_port_h__ - -#include -#include - -#include "pbd/xml++.h" -#include "pbd/crossthread.h" -#include "pbd/signals.h" -#include "pbd/ringbuffer.h" - -#include "evoral/Event.hpp" -#include "evoral/EventRingBuffer.hpp" - -#include "midi++/types.h" -#include "midi++/parser.h" -#include "midi++/port.h" - -#include "ardour/port_engine.h" - -namespace MIDI { - -class Channel; -class PortRequest; - -class JackMIDIPort : public Port { - public: - JackMIDIPort (std::string const &, Port::Flags, ARDOUR::PortEngine&); - JackMIDIPort (const XMLNode&, ARDOUR::PortEngine&); - ~JackMIDIPort (); - - XMLNode& get_state () const; - void set_state (const XMLNode&); - - void cycle_start (pframes_t nframes); - void cycle_end (); - - void parse (framecnt_t timestamp); - int write (const byte *msg, size_t msglen, timestamp_t timestamp); - int read (byte *buf, size_t bufsize); - void drain (int check_interval_usecs); - int selectable () const { return xthread.selectable(); } - - pframes_t nframes_this_cycle() const { return _nframes_this_cycle; } - - void reestablish (); - void reconnect (); - - static void set_process_thread (pthread_t); - static pthread_t get_process_thread () { return _process_thread; } - static bool is_process_thread(); - - static PBD::Signal0 MakeConnections; - static PBD::Signal0 EngineHalted; - -private: - ARDOUR::PortEngine& _port_engine; - ARDOUR::PortEngine::PortHandle _port_handle; - - bool _currently_in_cycle; - pframes_t _nframes_this_cycle; - timestamp_t _last_write_timestamp; - RingBuffer< Evoral::Event > output_fifo; - Evoral::EventRingBuffer input_fifo; - Glib::Threads::Mutex output_fifo_lock; - CrossThreadChannel xthread; - - int create_port (); - - /** Channel used to signal to the MidiControlUI that input has arrived */ - - std::string _connections; - PBD::ScopedConnection connect_connection; - PBD::ScopedConnection halt_connection; - void flush (void* port_buffer); - void engine_halted (); - void make_connections (); - void init (std::string const &, Flags); - - static pthread_t _process_thread; - -}; - -} // namespace MIDI - -#endif // __libmidi_port_h__ diff --git a/libs/midi++2/midi++/manager.h b/libs/midi++2/midi++/manager.h deleted file mode 100644 index 7f4df5c6c8..0000000000 --- a/libs/midi++2/midi++/manager.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - Copyright (C) 1998 Paul Barton-Davis - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef __midi_manager_h__ -#define __midi_manager_h__ - -#include - -#include - -#include "pbd/rcu.h" - -#include "midi++/types.h" -#include "midi++/port.h" - -namespace ARDOUR { - class PortEngine; -} - -namespace MIDI { - -class MachineControl; - -class Manager { - public: - ~Manager (); - - /** Signal the start of an audio cycle. - * This MUST be called before any reading/writing for this cycle. - * Realtime safe. - */ - void cycle_start (pframes_t nframes); - - /** Signal the end of an audio cycle. - * This signifies that the cycle began with @ref cycle_start has ended. - * This MUST be called at the end of each cycle. - * Realtime safe. - */ - 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 *); - void remove_port (Port *); - - Port* port (std::string const &); - - void set_port_states (std::list); - - typedef std::list PortList; - - boost::shared_ptr get_midi_ports() const { return _ports.reader (); } - - static void create (ARDOUR::PortEngine&); - - static Manager *instance () { - return theManager; - } - static void destroy (); - - void reestablish (); - void reconnect (); - - PBD::Signal0 PortsChanged; - - private: - /* This is a SINGLETON pattern */ - - Manager (ARDOUR::PortEngine&); - 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; - - SerializedRCUManager _ports; -}; - -} // namespace MIDI - -#endif // __midi_manager_h__ -- cgit v1.2.3