summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2013-08-07 22:22:11 -0400
committerPaul Davis <paul@linuxaudiosystems.com>2013-08-07 22:22:11 -0400
commit1ab61b8564f9934c533d1c1a229888bc7e2fd557 (patch)
treebaa1b05b50c018ca0edbda936b35de58adb29d94 /libs/ardour
parent83a0c30c24ce6bb6e3e718c267a82fbaffc33b4b (diff)
major redesign of MIDI port heirarchy and management (part 2)
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/audio_port.h4
-rw-r--r--libs/ardour/ardour/audioengine.h11
-rw-r--r--libs/ardour/ardour/debug.h1
-rw-r--r--libs/ardour/ardour/jack_audiobackend.h2
-rw-r--r--libs/ardour/ardour/midi_ui.h6
-rw-r--r--libs/ardour/ardour/midiport_manager.h10
-rw-r--r--libs/ardour/ardour/port_manager.h35
-rw-r--r--libs/ardour/ardour/session.h2
-rw-r--r--libs/ardour/ardour/slave.h30
-rw-r--r--libs/ardour/ardour/ticker.h53
-rw-r--r--libs/ardour/audioengine.cc138
-rw-r--r--libs/ardour/debug.cc1
-rw-r--r--libs/ardour/globals.cc5
-rw-r--r--libs/ardour/jack_audiobackend.cc6
-rw-r--r--libs/ardour/jack_connection.cc5
-rw-r--r--libs/ardour/ladspa_plugin.cc2
-rw-r--r--libs/ardour/midi_clock_slave.cc44
-rw-r--r--libs/ardour/midi_ui.cc40
-rw-r--r--libs/ardour/midiport_manager.cc40
-rw-r--r--libs/ardour/mtc_slave.cc49
-rw-r--r--libs/ardour/port.cc1
-rw-r--r--libs/ardour/port_manager.cc128
-rw-r--r--libs/ardour/rc_configuration.cc16
-rw-r--r--libs/ardour/session.cc20
-rw-r--r--libs/ardour/session_export.cc7
-rw-r--r--libs/ardour/session_midi.cc20
-rw-r--r--libs/ardour/session_process.cc6
-rw-r--r--libs/ardour/session_state.cc53
-rw-r--r--libs/ardour/session_transport.cc19
-rw-r--r--libs/ardour/ticker.cc180
-rw-r--r--libs/ardour/wscript2
31 files changed, 555 insertions, 381 deletions
diff --git a/libs/ardour/ardour/audio_port.h b/libs/ardour/ardour/audio_port.h
index f5affb0580..f87b134e9e 100644
--- a/libs/ardour/ardour/audio_port.h
+++ b/libs/ardour/ardour/audio_port.h
@@ -49,9 +49,7 @@ class AudioPort : public Port
friend class PortManager;
AudioPort (std::string const &, PortFlags);
- protected:
- friend class AudioEngine;
- /* special access for engine only (hah, C++) */
+ /* special access for PortManager only (hah, C++) */
Sample* engine_get_whole_audio_buffer ();
private:
diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h
index 6fb13b7ae0..509d330f12 100644
--- a/libs/ardour/ardour/audioengine.h
+++ b/libs/ardour/ardour/audioengine.h
@@ -36,13 +36,9 @@
#include "pbd/signals.h"
#include "pbd/stacktrace.h"
-#include <jack/weakjack.h>
-#include <jack/jack.h>
-#include <jack/transport.h>
-#include <jack/thread.h>
+#include "midi++/mmc.h"
#include "ardour/ardour.h"
-
#include "ardour/data_type.h"
#include "ardour/session_handle.h"
#include "ardour/types.h"
@@ -192,6 +188,8 @@ public:
/* sets up the process callback thread */
static void thread_init_callback (void *);
+ MIDI::MachineControl& mmc() { return _mmc; }
+
private:
AudioEngine ();
@@ -206,16 +204,17 @@ public:
gain_t session_removal_gain;
gain_t session_removal_gain_step;
bool _running;
+ bool _freewheeling;
/// number of frames between each check for changes in monitor input
framecnt_t monitor_check_interval;
/// time of the last monitor check in frames
framecnt_t last_monitor_check;
/// the number of frames processed since start() was called
framecnt_t _processed_frames;
- bool _freewheeling;
bool _pre_freewheel_mmc_enabled;
Glib::Threads::Thread* m_meter_thread;
ProcessThread* _main_thread;
+ MIDI::MachineControl _mmc;
void meter_thread ();
void start_metering_thread ();
diff --git a/libs/ardour/ardour/debug.h b/libs/ardour/ardour/debug.h
index 202d0cc424..5811f7a484 100644
--- a/libs/ardour/ardour/debug.h
+++ b/libs/ardour/ardour/debug.h
@@ -63,6 +63,7 @@ namespace PBD {
extern uint64_t OrderKeys;
extern uint64_t Automation;
extern uint64_t WiimoteControl;
+ extern uint64_t Ports;
}
}
diff --git a/libs/ardour/ardour/jack_audiobackend.h b/libs/ardour/ardour/jack_audiobackend.h
index 9fa3d0c1cc..ada7ce8e33 100644
--- a/libs/ardour/ardour/jack_audiobackend.h
+++ b/libs/ardour/ardour/jack_audiobackend.h
@@ -178,6 +178,8 @@ class JACKAudioBackend : public AudioBackend {
typedef std::map<std::string,DeviceList> DriverDeviceMap;
mutable DriverDeviceMap all_devices;
+
+ PBD::ScopedConnection disconnect_connection;
};
} // namespace
diff --git a/libs/ardour/ardour/midi_ui.h b/libs/ardour/ardour/midi_ui.h
index 34e97494be..c15a530057 100644
--- a/libs/ardour/ardour/midi_ui.h
+++ b/libs/ardour/ardour/midi_ui.h
@@ -26,13 +26,11 @@
#include "pbd/signals.h"
#include "pbd/stacktrace.h"
-namespace MIDI {
- class Port;
-}
namespace ARDOUR {
class Session;
+class AsyncMIDIPort;
/* this is mostly a placeholder because I suspect that at some
point we will want to add more members to accomodate
@@ -67,7 +65,7 @@ class MidiControlUI : public AbstractUI<MidiUIRequest>
ARDOUR::Session& _session;
PBD::ScopedConnection rebind_connection;
- bool midi_input_handler (Glib::IOCondition, MIDI::Port*);
+ bool midi_input_handler (Glib::IOCondition, AsyncMIDIPort*);
void reset_ports ();
void clear_ports ();
diff --git a/libs/ardour/ardour/midiport_manager.h b/libs/ardour/ardour/midiport_manager.h
index 9c45e60341..df33038f2b 100644
--- a/libs/ardour/ardour/midiport_manager.h
+++ b/libs/ardour/ardour/midiport_manager.h
@@ -56,8 +56,10 @@ class MidiPortManager {
* callback.
*/
- MIDI::Port* midi_input_port () { return _midi_input_port; }
- MIDI::Port* midi_output_port () { return _midi_output_port; }
+ MIDI::Port* midi_input_port () const { return _midi_input_port; }
+ MIDI::Port* midi_output_port () const { return _midi_output_port; }
+ MIDI::Port* mmc_input_port () const { return _mmc_input_port; }
+ MIDI::Port* mmc_output_port () const { return _mmc_output_port; }
/* Ports used for synchronization. These have their I/O handled inside the
* process callback.
@@ -76,8 +78,12 @@ class MidiPortManager {
/* asynchronously handled ports: MIDI::Port */
MIDI::Port* _midi_input_port;
MIDI::Port* _midi_output_port;
+ MIDI::Port* _mmc_input_port;
+ MIDI::Port* _mmc_output_port;
boost::shared_ptr<Port> _midi_in;
boost::shared_ptr<Port> _midi_out;
+ boost::shared_ptr<Port> _mmc_in;
+ boost::shared_ptr<Port> _mmc_out;
/* synchronously handled ports: ARDOUR::MidiPort */
boost::shared_ptr<MidiPort> _mtc_input_port;
diff --git a/libs/ardour/ardour/port_manager.h b/libs/ardour/ardour/port_manager.h
index 06e4939101..895294810e 100644
--- a/libs/ardour/ardour/port_manager.h
+++ b/libs/ardour/ardour/port_manager.h
@@ -32,15 +32,17 @@
#include "pbd/rcu.h"
#include "ardour/chan_count.h"
+#include "ardour/midiport_manager.h"
#include "ardour/port.h"
#include "ardour/port_engine.h"
namespace ARDOUR {
-class PortManager
+class PortManager : public MidiPortManager
{
public:
typedef std::map<std::string,boost::shared_ptr<Port> > Ports;
+ typedef std::list<boost::shared_ptr<Port> > PortList;
PortManager ();
virtual ~PortManager() {}
@@ -53,8 +55,8 @@ class PortManager
/* Port registration */
- boost::shared_ptr<Port> register_input_port (DataType, const std::string& portname);
- boost::shared_ptr<Port> register_output_port (DataType, const std::string& portname);
+ boost::shared_ptr<Port> register_input_port (DataType, const std::string& portname, bool async = false);
+ boost::shared_ptr<Port> register_output_port (DataType, const std::string& portname, bool async = false);
int unregister_port (boost::shared_ptr<Port>);
/* Port connectivity */
@@ -87,7 +89,8 @@ class PortManager
ChanCount n_physical_inputs () const;
int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>&);
-
+ int get_ports (DataType, PortList&);
+
void remove_all_ports ();
/* per-Port monitoring */
@@ -135,9 +138,31 @@ class PortManager
SerializedRCUManager<Ports> ports;
bool _port_remove_in_progress;
- boost::shared_ptr<Port> register_port (DataType type, const std::string& portname, bool input);
+ boost::shared_ptr<Port> register_port (DataType type, const std::string& portname, bool input, bool async = false);
void port_registration_failure (const std::string& portname);
+
+ /** List of ports to be used between ::cycle_start() and ::cycle_end()
+ */
+ boost::shared_ptr<Ports> _cycle_ports;
+
+ void fade_out (gain_t, gain_t, pframes_t);
+ void silence (pframes_t nframes);
+ void check_monitoring ();
+ /** 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 (pframes_t nframes);
};
+
+
} // namespace
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index a12f816c1e..a47c13046d 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -813,7 +813,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
boost::shared_ptr<SessionPlaylists> playlists;
void send_mmc_locate (framepos_t);
- int send_full_time_code (framepos_t);
+ int send_full_time_code (framepos_t, pframes_t nframes);
void send_song_position_pointer (framepos_t);
bool step_editing() const { return (_step_editors > 0); }
diff --git a/libs/ardour/ardour/slave.h b/libs/ardour/ardour/slave.h
index 4408da2d25..adf425ea43 100644
--- a/libs/ardour/ardour/slave.h
+++ b/libs/ardour/ardour/slave.h
@@ -40,15 +40,12 @@
#define PLUSMINUS(A) ( ((A)<0) ? "-" : (((A)>0) ? "+" : "\u00B1") )
#define LEADINGZERO(A) ( (A)<10 ? " " : (A)<100 ? " " : (A)<1000 ? " " : "" )
-namespace MIDI {
- class Port;
-}
-
namespace ARDOUR {
class TempoMap;
class Session;
class AudioEngine;
+class MidiPort;
/**
* @class Slave
@@ -67,6 +64,15 @@ class Slave {
Slave() { }
virtual ~Slave() {}
+ /** The slave should read any incoming information in this method
+ * and use it adjust its current idea of reality. If no such
+ * processing is required, it does need to be implemented.
+ *
+ * @param nframes specifies the number of frames-worth of data that
+ * can be read from any ports used by the slave.
+ */
+ virtual int process (pframes_t) { return 0; }
+
/**
* This is the most important function to implement:
* Each process cycle, Session::follow_slave will call this method.
@@ -253,10 +259,11 @@ class TimecodeSlave : public Slave {
class MTC_Slave : public TimecodeSlave {
public:
- MTC_Slave (Session&, MIDI::Port&);
+ MTC_Slave (Session&, MidiPort&);
~MTC_Slave ();
- void rebind (MIDI::Port&);
+ void rebind (MidiPort&);
+ int process (pframes_t);
bool speed_and_position (double&, framepos_t&);
bool locked() const;
@@ -274,7 +281,8 @@ class MTC_Slave : public TimecodeSlave {
private:
Session& session;
- MIDI::Port* port;
+ MidiPort* port;
+ MIDI::Parser parser;
PBD::ScopedConnectionList port_connections;
PBD::ScopedConnection config_connection;
bool can_notify_on_unknown_rate;
@@ -405,13 +413,14 @@ public:
class MIDIClock_Slave : public Slave {
public:
- MIDIClock_Slave (Session&, MIDI::Port&, int ppqn = 24);
+ MIDIClock_Slave (Session&, MidiPort&, int ppqn = 24);
/// Constructor for unit tests
MIDIClock_Slave (ISlaveSessionProxy* session_proxy = 0, int ppqn = 24);
~MIDIClock_Slave ();
- void rebind (MIDI::Port&);
+ void rebind (MidiPort&);
+ int process (pframes_t);
bool speed_and_position (double&, framepos_t&);
bool locked() const;
@@ -427,7 +436,8 @@ class MIDIClock_Slave : public Slave {
protected:
ISlaveSessionProxy* session;
- MIDI::Port* port;
+ MidiPort* port;
+ MIDI::Parser parser;
PBD::ScopedConnectionList port_connections;
/// pulses per quarter note for one MIDI clock frame (default 24)
diff --git a/libs/ardour/ardour/ticker.h b/libs/ardour/ardour/ticker.h
index b6e5376c12..7f0d1987fc 100644
--- a/libs/ardour/ardour/ticker.h
+++ b/libs/ardour/ardour/ticker.h
@@ -27,17 +27,13 @@
#include "ardour/session_handle.h"
-#ifndef TICKER_H_
-#define TICKER_H_
+#ifndef __libardour_ticker_h__
+#define __libardour_ticker_h__
-namespace MIDI {
- class Port;
-}
-
-namespace ARDOUR
-{
+namespace ARDOUR {
class Session;
+class MidiPort;
class MidiClockTicker : public SessionHandlePtr, boost::noncopyable
{
@@ -45,7 +41,7 @@ public:
MidiClockTicker ();
virtual ~MidiClockTicker();
- void tick (const framepos_t& transport_frames);
+ void tick (const framepos_t& transport_frames, pframes_t nframes);
bool has_midi_port() const { return _midi_port != 0; }
@@ -58,9 +54,6 @@ public:
/// slot for the signal session::TransportStateChange
void transport_state_changed();
- /// slot for the signal session::PositionChanged
- void position_changed (framepos_t position);
-
/// slot for the signal session::TransportLooped
void transport_looped();
@@ -70,23 +63,25 @@ public:
/// pulses per quarter note (default 24)
void set_ppqn(int ppqn) { _ppqn = ppqn; }
-private:
- MIDI::Port* _midi_port;
- int _ppqn;
- double _last_tick;
-
- class Position;
- boost::scoped_ptr<Position> _pos;
-
- double one_ppqn_in_frames (framepos_t transport_position);
-
- void send_midi_clock_event (pframes_t offset);
- void send_start_event (pframes_t offset);
- void send_continue_event (pframes_t offset);
- void send_stop_event (pframes_t offset);
- void send_position_event (uint32_t midi_clocks, pframes_t offset);
+ private:
+ boost::shared_ptr<MidiPort> _midi_port;
+ int _ppqn;
+ double _last_tick;
+ bool _send_pos;
+ bool _send_state;
+
+ class Position;
+ boost::scoped_ptr<Position> _pos;
+
+ double one_ppqn_in_frames (framepos_t transport_position);
+
+ void send_midi_clock_event (pframes_t offset, pframes_t nframes);
+ void send_start_event (pframes_t offset, pframes_t nframes);
+ void send_continue_event (pframes_t offset, pframes_t nframes);
+ void send_stop_event (pframes_t offset, pframes_t nframes);
+ void send_position_event (uint32_t midi_clocks, pframes_t offset, pframes_t nframes);
};
-
}
+ // namespace
-#endif /* TICKER_H_ */
+#endif /* __libardour_ticker_h__ */
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 0c88e7c0fd..9c04529384 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -37,10 +37,9 @@
#include <jack/weakjack.h>
#include "midi++/port.h"
-#include "midi++/jack_midi_port.h"
#include "midi++/mmc.h"
-#include "midi++/manager.h"
+#include "ardour/async_midi_port.h"
#include "ardour/audio_port.h"
#include "ardour/audio_backend.h"
#include "ardour/audioengine.h"
@@ -50,6 +49,7 @@
#include "ardour/internal_send.h"
#include "ardour/meter.h"
#include "ardour/midi_port.h"
+#include "ardour/midiport_manager.h"
#include "ardour/port.h"
#include "ardour/process_thread.h"
#include "ardour/session.h"
@@ -66,10 +66,11 @@ AudioEngine* AudioEngine::_instance = 0;
AudioEngine::AudioEngine ()
: session_remove_pending (false)
, session_removal_countdown (-1)
+ , _running (false)
+ , _freewheeling (false)
, monitor_check_interval (INT32_MAX)
, last_monitor_check (0)
, _processed_frames (0)
- , _freewheeling (false)
, _pre_freewheel_mmc_enabled (false)
, m_meter_thread (0)
, _main_thread (0)
@@ -117,7 +118,7 @@ _thread_init_callback (void * /*arg*/)
SessionEvent::create_per_thread_pool (X_("Audioengine"), 512);
- MIDI::JackMIDIPort::set_process_thread (pthread_self());
+ AsyncMIDIPort::set_process_thread (pthread_self());
}
void
@@ -231,8 +232,8 @@ AudioEngine::process_callback (pframes_t nframes)
if (_session == 0) {
if (!_freewheeling) {
- MIDI::Manager::instance()->cycle_start(nframes);
- MIDI::Manager::instance()->cycle_end();
+ PortManager::cycle_start (nframes);
+ PortManager::cycle_end (nframes);
}
_processed_frames = next_processed_frames;
@@ -243,34 +244,22 @@ AudioEngine::process_callback (pframes_t nframes)
/* tell all relevant objects that we're starting a new cycle */
InternalSend::CycleStart (nframes);
- Port::set_global_port_buffer_offset (0);
- Port::set_cycle_framecnt (nframes);
/* tell all Ports that we're starting a new cycle */
- boost::shared_ptr<Ports> p = ports.reader();
-
- for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
- i->second->cycle_start (nframes);
- }
+ PortManager::cycle_start (nframes);
/* test if we are freewheeling and there are freewheel signals connected.
ardour should act normally even when freewheeling unless /it/ is
- exporting
+ exporting (which is what Freewheel.empty() tests for).
*/
if (_freewheeling && !Freewheel.empty()) {
-
Freewheel (nframes);
-
} else {
- MIDI::Manager::instance()->cycle_start(nframes);
-
if (_session) {
_session->process (nframes);
}
-
- MIDI::Manager::instance()->cycle_end();
}
if (_freewheeling) {
@@ -283,52 +272,18 @@ AudioEngine::process_callback (pframes_t nframes)
}
if (last_monitor_check + monitor_check_interval < next_processed_frames) {
-
- boost::shared_ptr<Ports> p = ports.reader();
-
- for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
-
- bool x;
-
- if (i->second->last_monitor() != (x = i->second->monitoring_input ())) {
- i->second->set_last_monitor (x);
- /* XXX I think this is dangerous, due to
- a likely mutex in the signal handlers ...
- */
- i->second->MonitorInputChanged (x); /* EMIT SIGNAL */
- }
- }
+
+ PortManager::check_monitoring ();
last_monitor_check = next_processed_frames;
}
if (_session->silent()) {
-
- for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
-
- if (i->second->sends_output()) {
- i->second->get_buffer(nframes).silence(nframes);
- }
- }
+ PortManager::silence (nframes);
}
if (session_remove_pending && session_removal_countdown) {
- for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
-
- if (i->second->sends_output()) {
-
- boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
- if (ap) {
- Sample* s = ap->engine_get_whole_audio_buffer ();
- gain_t g = session_removal_gain;
-
- for (pframes_t n = 0; n < nframes; ++n) {
- *s++ *= g;
- g -= session_removal_gain_step;
- }
- }
- }
- }
+ PortManager::fade_out (session_removal_gain, session_removal_gain_step, nframes);
if (session_removal_countdown > nframes) {
session_removal_countdown -= nframes;
@@ -339,11 +294,7 @@ AudioEngine::process_callback (pframes_t nframes)
session_removal_gain -= (nframes * session_removal_gain_step);
}
- // Finalize ports
-
- for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
- i->second->cycle_end (nframes);
- }
+ PortManager::cycle_end (nframes);
_processed_frames = next_processed_frames;
@@ -574,7 +525,7 @@ AudioEngine::set_backend (const std::string& name, const std::string& arg1, cons
}
drop_backend ();
-
+
try {
cerr << "Instantiate " << b->second->name << " with " << arg1 << " + " << arg2 << endl;
@@ -603,31 +554,45 @@ AudioEngine::start ()
return -1;
}
- if (!_running) {
+ if (_running) {
+ return 0;
+ }
- if (_session) {
- BootMessage (_("Connect session to engine"));
- _session->set_frame_rate (_backend->sample_rate());
- }
+ /* if we're still connected (i.e. previously paused), no need to
+ * re-register ports.
+ */
+
+ bool have_ports = (!ports.reader()->empty());
- _processed_frames = 0;
- last_monitor_check = 0;
+ _processed_frames = 0;
+ last_monitor_check = 0;
+
+ if (_backend->start() == 0) {
- if (_backend->start() == 0) {
- _running = true;
- last_monitor_check = 0;
+ _running = true;
+ last_monitor_check = 0;
+
+ if (_session) {
+ _session->set_frame_rate (_backend->sample_rate());
- if (_session && _session->config.get_jack_time_master()) {
+ if (_session->config.get_jack_time_master()) {
_backend->set_time_master (true);
}
-
- Running(); /* EMIT SIGNAL */
- } else {
- /* should report error? */
}
- }
- return _running ? 0 : -1;
+ if (!have_ports) {
+ PortManager::create_ports ();
+ }
+
+ _mmc.set_ports (mmc_input_port(), mmc_output_port());
+
+ Running(); /* EMIT SIGNAL */
+
+ return 0;
+ }
+
+ /* should report error ... */
+ return -1;
}
int
@@ -641,6 +606,7 @@ AudioEngine::stop ()
if (_backend->stop () == 0) {
_running = false;
+ _processed_frames = 0;
stop_metering_thread ();
Stopped (); /* EMIT SIGNAL */
@@ -932,7 +898,7 @@ AudioEngine::thread_init_callback (void* arg)
SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
- MIDI::JackMIDIPort::set_process_thread (pthread_self());
+ AsyncMIDIPort::set_process_thread (pthread_self());
if (arg) {
AudioEngine* ae = static_cast<AudioEngine*> (arg);
@@ -964,10 +930,10 @@ void
AudioEngine::freewheel_callback (bool onoff)
{
if (onoff) {
- _pre_freewheel_mmc_enabled = MIDI::Manager::instance()->mmc()->send_enabled ();
- MIDI::Manager::instance()->mmc()->enable_send (false);
+ _pre_freewheel_mmc_enabled = _mmc.send_enabled ();
+ _mmc.enable_send (false);
} else {
- MIDI::Manager::instance()->mmc()->enable_send (_pre_freewheel_mmc_enabled);
+ _mmc.enable_send (_pre_freewheel_mmc_enabled);
}
}
@@ -991,8 +957,6 @@ void
AudioEngine::halted_callback (const char* why)
{
stop_metering_thread ();
-
- MIDI::JackMIDIPort::EngineHalted (); /* EMIT SIGNAL */
Halted (why); /* EMIT SIGNAL */
}
diff --git a/libs/ardour/debug.cc b/libs/ardour/debug.cc
index afd5da2169..fb122dd83c 100644
--- a/libs/ardour/debug.cc
+++ b/libs/ardour/debug.cc
@@ -60,5 +60,6 @@ uint64_t PBD::DEBUG::TempoMap = PBD::new_debug_bit ("tempomap");
uint64_t PBD::DEBUG::OrderKeys = PBD::new_debug_bit ("orderkeys");
uint64_t PBD::DEBUG::Automation = PBD::new_debug_bit ("automation");
uint64_t PBD::DEBUG::WiimoteControl = PBD::new_debug_bit ("wiimotecontrol");
+uint64_t PBD::DEBUG::Ports = PBD::new_debug_bit ("Ports");
diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc
index d744368fe7..fbce336283 100644
--- a/libs/ardour/globals.cc
+++ b/libs/ardour/globals.cc
@@ -67,7 +67,6 @@
#include "pbd/basename.h"
#include "midi++/port.h"
-#include "midi++/manager.h"
#include "midi++/mmc.h"
#include "ardour/analyser.h"
@@ -80,6 +79,7 @@
#include "ardour/control_protocol_manager.h"
#include "ardour/filesystem_paths.h"
#include "ardour/midi_region.h"
+#include "ardour/midiport_manager.h"
#include "ardour/mix.h"
#include "ardour/panner_manager.h"
#include "ardour/plugin_manager.h"
@@ -340,9 +340,6 @@ ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir
void
ARDOUR::init_post_engine ()
{
- /* the MIDI Manager is needed by the ControlProtocolManager */
- MIDI::Manager::create (AudioEngine::instance()->port_engine());
-
ControlProtocolManager::instance().discover_control_protocols ();
XMLNode* node;
diff --git a/libs/ardour/jack_audiobackend.cc b/libs/ardour/jack_audiobackend.cc
index 19158aacc9..2e0d90202f 100644
--- a/libs/ardour/jack_audiobackend.cc
+++ b/libs/ardour/jack_audiobackend.cc
@@ -24,7 +24,8 @@
#include "pbd/error.h"
-#include "midi++/manager.h"
+#include "jack/jack.h"
+#include "jack/thread.h"
#include "ardour/audioengine.h"
#include "ardour/types.h"
@@ -57,6 +58,7 @@ JACKAudioBackend::JACKAudioBackend (AudioEngine& e, boost::shared_ptr<JackConnec
, _target_systemic_input_latency (0)
, _target_systemic_output_latency (0)
{
+ _jack_connection->Disconnected.connect_same_thread (disconnect_connection, boost::bind (&JACKAudioBackend::disconnected, this, _1));
}
JACKAudioBackend::~JACKAudioBackend()
@@ -897,8 +899,6 @@ JACKAudioBackend::jack_bufsize_callback (pframes_t nframes)
void
JACKAudioBackend::disconnected (const char* why)
{
- /* called from jack shutdown handler */
-
bool was_running = _running;
_running = false;
diff --git a/libs/ardour/jack_connection.cc b/libs/ardour/jack_connection.cc
index 57950b0e17..d48e3355b5 100644
--- a/libs/ardour/jack_connection.cc
+++ b/libs/ardour/jack_connection.cc
@@ -135,7 +135,10 @@ JackConnection::close ()
GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
if (_priv_jack) {
- return jack_client_close (_priv_jack);
+ int ret = jack_client_close (_priv_jack);
+ _jack = 0;
+ Disconnected (""); /* EMIT SIGNAL */
+ return ret;
}
return 0;
diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc
index 5a6e577f2d..6a2636e4f4 100644
--- a/libs/ardour/ladspa_plugin.cc
+++ b/libs/ardour/ladspa_plugin.cc
@@ -36,8 +36,6 @@
#include "pbd/xml++.h"
#include "pbd/stacktrace.h"
-#include "midi++/manager.h"
-
#include "ardour/session.h"
#include "ardour/ladspa_plugin.h"
#include "ardour/buffer_set.h"
diff --git a/libs/ardour/midi_clock_slave.cc b/libs/ardour/midi_clock_slave.cc
index 6f54d17d02..752644e9f4 100644
--- a/libs/ardour/midi_clock_slave.cc
+++ b/libs/ardour/midi_clock_slave.cc
@@ -31,6 +31,8 @@
#include "midi++/port.h"
#include "ardour/debug.h"
+#include "ardour/midi_buffer.h"
+#include "ardour/midi_port.h"
#include "ardour/slave.h"
#include "ardour/tempo.h"
@@ -41,13 +43,20 @@ using namespace ARDOUR;
using namespace MIDI;
using namespace PBD;
-MIDIClock_Slave::MIDIClock_Slave (Session& s, MIDI::Port& p, int ppqn)
+MIDIClock_Slave::MIDIClock_Slave (Session& s, MidiPort& p, int ppqn)
: ppqn (ppqn)
, bandwidth (10.0 / 60.0) // 1 BpM = 1 / 60 Hz
{
session = (ISlaveSessionProxy *) new SlaveSessionProxy(s);
rebind (p);
reset ();
+
+ parser.timing.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::update_midi_clock, this, _1, _2));
+ parser.start.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::start, this, _1, _2));
+ parser.contineu.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::contineu, this, _1, _2));
+ parser.stop.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::stop, this, _1, _2));
+ parser.position.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::position, this, _1, _2, 3));
+
}
MIDIClock_Slave::MIDIClock_Slave (ISlaveSessionProxy* session_proxy, int ppqn)
@@ -63,20 +72,33 @@ MIDIClock_Slave::~MIDIClock_Slave()
delete session;
}
-void
-MIDIClock_Slave::rebind (MIDI::Port& p)
+int
+MIDIClock_Slave::process (pframes_t nframes)
{
- port_connections.drop_connections();
+ MidiBuffer& mb (port->get_midi_buffer (nframes));
- port = &p;
+ /* dump incoming MIDI to parser */
- DEBUG_TRACE (DEBUG::MidiClock, string_compose ("MIDIClock_Slave: connecting to port %1\n", port->name()));
+ for (MidiBuffer::iterator b = mb.begin(); b != mb.end(); ++b) {
+ uint8_t* buf = (*b).buffer();
+
+ parser.set_timestamp ((*b).time());
- port->parser()->timing.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::update_midi_clock, this, _1, _2));
- port->parser()->start.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::start, this, _1, _2));
- port->parser()->contineu.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::contineu, this, _1, _2));
- port->parser()->stop.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::stop, this, _1, _2));
- port->parser()->position.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::position, this, _1, _2, 3));
+ uint32_t limit = (*b).size();
+
+ for (size_t n = 0; n < limit; ++n) {
+ parser.scanner (buf[n]);
+ }
+ }
+
+ return 0;
+}
+
+void
+MIDIClock_Slave::rebind (MidiPort& p)
+{
+ port = &p;
+ DEBUG_TRACE (DEBUG::MidiClock, string_compose ("MIDIClock_Slave: connecting to port %1\n", port->name()));
}
void
diff --git a/libs/ardour/midi_ui.cc b/libs/ardour/midi_ui.cc
index 0d9ac17601..e75c05c593 100644
--- a/libs/ardour/midi_ui.cc
+++ b/libs/ardour/midi_ui.cc
@@ -22,11 +22,11 @@
#include "pbd/pthread_utils.h"
-#include "midi++/manager.h"
-#include "midi++/port.h"
-
+#include "ardour/async_midi_port.h"
#include "ardour/debug.h"
#include "ardour/audioengine.h"
+#include "ardour/midi_port.h"
+#include "ardour/midiport_manager.h"
#include "ardour/midi_ui.h"
#include "ardour/session.h"
#include "ardour/session_event.h"
@@ -48,7 +48,6 @@ MidiControlUI::MidiControlUI (Session& s)
: AbstractUI<MidiUIRequest> (X_("midiui"))
, _session (s)
{
- MIDI::Manager::instance()->PortsChanged.connect_same_thread (rebind_connection, boost::bind (&MidiControlUI::change_midi_ports, this));
_instance = this;
}
@@ -83,20 +82,10 @@ MidiControlUI::do_request (MidiUIRequest* req)
}
}
-void
-MidiControlUI::change_midi_ports ()
-{
- MidiUIRequest* req = get_request (PortChange);
- if (req == 0) {
- return;
- }
- send_request (req);
-}
-
bool
-MidiControlUI::midi_input_handler (IOCondition ioc, MIDI::Port* port)
+MidiControlUI::midi_input_handler (IOCondition ioc, AsyncMIDIPort* port)
{
- DEBUG_TRACE (DEBUG::MidiIO, string_compose ("something happend on %1\n", port->name()));
+ DEBUG_TRACE (DEBUG::MidiIO, string_compose ("something happend on %1\n", ((ARDOUR::Port*)port)->name()));
if (ioc & ~IO_IN) {
return false;
@@ -106,7 +95,7 @@ MidiControlUI::midi_input_handler (IOCondition ioc, MIDI::Port* port)
CrossThreadChannel::drain (port->selectable());
- DEBUG_TRACE (DEBUG::MidiIO, string_compose ("data available on %1\n", port->name()));
+ DEBUG_TRACE (DEBUG::MidiIO, string_compose ("data available on %1\n", ((ARDOUR::Port*)port)->name()));
framepos_t now = _session.engine().sample_time();
port->parse (now);
}
@@ -128,22 +117,19 @@ MidiControlUI::clear_ports ()
void
MidiControlUI::reset_ports ()
{
- clear_ports ();
-
- boost::shared_ptr<const MIDI::Manager::PortList> plist = MIDI::Manager::instance()->get_midi_ports ();
+ if (port_sources.empty()) {
+ AsyncMIDIPort* async = dynamic_cast<AsyncMIDIPort*> (AudioEngine::instance()->midi_input_port());
- for (MIDI::Manager::PortList::const_iterator i = plist->begin(); i != plist->end(); ++i) {
-
- if (!(*i)->centrally_parsed()) {
- continue;
+ if (!async) {
+ return;
}
int fd;
- if ((fd = (*i)->selectable ()) >= 0) {
+ if ((fd = async->selectable ()) >= 0) {
Glib::RefPtr<IOSource> psrc = IOSource::create (fd, IO_IN|IO_HUP|IO_ERR);
-
- psrc->connect (sigc::bind (sigc::mem_fun (this, &MidiControlUI::midi_input_handler), *i));
+
+ psrc->connect (sigc::bind (sigc::mem_fun (this, &MidiControlUI::midi_input_handler), async));
psrc->attach (_main_loop->get_context());
// glibmm hack: for now, store only the GSource*
diff --git a/libs/ardour/midiport_manager.cc b/libs/ardour/midiport_manager.cc
index fb27800762..ec525fd9f8 100644
--- a/libs/ardour/midiport_manager.cc
+++ b/libs/ardour/midiport_manager.cc
@@ -66,11 +66,47 @@ MidiPortManager::port (string const & n)
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);
+ /* this method is idempotent
+ */
+
+ if (_midi_in) {
+ return;
+ }
+
+ _midi_in = AudioEngine::instance()->register_input_port (DataType::MIDI, _("control in"), true);
+ _midi_out = AudioEngine::instance()->register_output_port (DataType::MIDI, _("control out"), true);
+
+ _mmc_in = AudioEngine::instance()->register_input_port (DataType::MIDI, _("mmc in"), true);
+ _mmc_out = AudioEngine::instance()->register_output_port (DataType::MIDI, _("mmc out"), true);
+ /* XXX nasty type conversion needed because of the mixed inheritance
+ * required to integrate MIDI::IPMidiPort and ARDOUR::AsyncMIDIPort.
+ *
+ * At some point, we'll move IPMidiPort into Ardour and make it
+ * inherit from ARDOUR::MidiPort not MIDI::Port, and then this
+ * mess can go away
+ */
+
_midi_input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_midi_in).get();
_midi_output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_midi_out).get();
+
+ _mmc_input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_mmc_in).get();
+ _mmc_output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_mmc_out).get();
+
+ /* Now register ports used for sync (MTC and MIDI Clock)
+ */
+
+ boost::shared_ptr<ARDOUR::Port> p;
+
+ p = AudioEngine::instance()->register_input_port (DataType::MIDI, _("timecode in"));
+ _mtc_input_port = boost::dynamic_pointer_cast<MidiPort> (p);
+ p = AudioEngine::instance()->register_output_port (DataType::MIDI, _("timecode out"));
+ _mtc_output_port= boost::dynamic_pointer_cast<MidiPort> (p);
+
+ p = AudioEngine::instance()->register_input_port (DataType::MIDI, _("clock in"));
+ _midi_clock_input_port = boost::dynamic_pointer_cast<MidiPort> (p);
+ p = AudioEngine::instance()->register_output_port (DataType::MIDI, _("clock out"));
+ _midi_clock_output_port= boost::dynamic_pointer_cast<MidiPort> (p);
}
void
diff --git a/libs/ardour/mtc_slave.cc b/libs/ardour/mtc_slave.cc
index 0f2761c350..b42b4989d2 100644
--- a/libs/ardour/mtc_slave.cc
+++ b/libs/ardour/mtc_slave.cc
@@ -25,11 +25,12 @@
#include "pbd/error.h"
-#include "midi++/port.h"
+#include "ardour/audioengine.h"
#include "ardour/debug.h"
-#include "ardour/slave.h"
+#include "ardour/midi_buffer.h"
+#include "ardour/midi_port.h"
#include "ardour/session.h"
-#include "ardour/audioengine.h"
+#include "ardour/slave.h"
#include "i18n.h"
@@ -48,8 +49,9 @@ using namespace Timecode;
*/
const int MTC_Slave::frame_tolerance = 2;
-MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
+MTC_Slave::MTC_Slave (Session& s, MidiPort& p)
: session (s)
+ , port (&p)
{
can_notify_on_unknown_rate = true;
did_reset_tc_format = false;
@@ -70,7 +72,11 @@ MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
session.config.ParameterChanged.connect_same_thread (config_connection, boost::bind (&MTC_Slave::parameter_changed, this, _1));
parse_timecode_offset();
reset (true);
- rebind (p);
+
+ parser.mtc_time.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_time, this, _1, _2, _3));
+ parser.mtc_qtr.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_qtr, this, _1, _2, _3));
+ parser.mtc_status.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_status, this, _1));
+
}
MTC_Slave::~MTC_Slave()
@@ -93,16 +99,35 @@ MTC_Slave::~MTC_Slave()
}
}
+int
+MTC_Slave::process (pframes_t nframes)
+{
+ MidiBuffer& mb (port->get_midi_buffer (nframes));
+
+ /* dump incoming MIDI to parser */
+
+ for (MidiBuffer::iterator b = mb.begin(); b != mb.end(); ++b) {
+ uint8_t* buf = (*b).buffer();
+
+ parser.set_timestamp ((*b).time());
+
+ uint32_t limit = (*b).size();
+
+ for (size_t n = 0; n < limit; ++n) {
+ parser.scanner (buf[n]);
+ }
+ }
+
+ return 0;
+}
+
void
-MTC_Slave::rebind (MIDI::Port& p)
+MTC_Slave::rebind (MidiPort& p)
{
port_connections.drop_connections ();
port = &p;
- port->parser()->mtc_time.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_time, this, _1, _2, _3));
- port->parser()->mtc_qtr.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_qtr, this, _1, _2, _3));
- port->parser()->mtc_status.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_status, this, _1));
}
void
@@ -154,7 +179,7 @@ MTC_Slave::outside_window (framepos_t pos) const
bool
MTC_Slave::locked () const
{
- return port->parser()->mtc_locked() && last_inbound_frame !=0 && engine_dll_initstate !=0;
+ return parser.mtc_locked() && last_inbound_frame !=0 && engine_dll_initstate !=0;
}
bool
@@ -446,7 +471,7 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full, framepos_t now)
DEBUG_TRACE (DEBUG::MTC, string_compose ("new mtc_frame: %1 | MTC-FpT: %2 A3-FpT:%3\n",
mtc_frame, (4.0*qtr), session.frames_per_timecode_frame()));
- switch (port->parser()->mtc_running()) {
+ switch (parser.mtc_running()) {
case MTC_Backward:
mtc_frame -= mtc_off;
qtr *= -1.0;
@@ -528,7 +553,7 @@ MTC_Slave::reset_window (framepos_t root)
*/
framecnt_t const d = (quarter_frame_duration * 4 * frame_tolerance);
- switch (port->parser()->mtc_running()) {
+ switch (parser.mtc_running()) {
case MTC_Forward:
window_begin = root;
transport_direction = 1;
diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc
index 571d227711..7dc11c6d3d 100644
--- a/libs/ardour/port.cc
+++ b/libs/ardour/port.cc
@@ -390,6 +390,7 @@ Port::get_connected_latency_range (LatencyRange& range, bool playback) const
int
Port::reestablish ()
{
+ DEBUG_TRACE (DEBUG::Ports, string_compose ("re-establish %1 port %2\n", type().to_string(), _name));
_port_handle = port_engine.register_port (_name, type(), _flags);
if (_port_handle == 0) {
diff --git a/libs/ardour/port_manager.cc b/libs/ardour/port_manager.cc
index 5c807a6979..41331fe3a5 100644
--- a/libs/ardour/port_manager.cc
+++ b/libs/ardour/port_manager.cc
@@ -19,11 +19,12 @@
#include "pbd/error.h"
-#include "midi++/manager.h"
-
+#include "ardour/async_midi_port.h"
+#include "ardour/debug.h"
#include "ardour/port_manager.h"
#include "ardour/audio_port.h"
#include "ardour/midi_port.h"
+#include "ardour/midiport_manager.h"
#include "i18n.h"
@@ -228,6 +229,18 @@ PortManager::port_renamed (const std::string& old_relative_name, const std::stri
}
int
+PortManager::get_ports (DataType type, PortList& pl)
+{
+ boost::shared_ptr<Ports> plist = ports.reader();
+ for (Ports::iterator p = plist->begin(); p != plist->end(); ++p) {
+ if (p->second->type() == type) {
+ pl.push_back (p->second);
+ }
+ }
+ return pl.size();
+}
+
+int
PortManager::get_ports (const string& port_name_pattern, DataType type, PortFlags flags, vector<string>& s)
{
if (!_impl) {
@@ -262,15 +275,25 @@ PortManager::port_registration_failure (const std::string& portname)
}
boost::shared_ptr<Port>
-PortManager::register_port (DataType dtype, const string& portname, bool input)
+PortManager::register_port (DataType dtype, const string& portname, bool input, bool async)
{
boost::shared_ptr<Port> newport;
try {
if (dtype == DataType::AUDIO) {
+ DEBUG_TRACE (DEBUG::Ports, string_compose ("registering AUDIO port %1, input %2\n",
+ portname, input));
newport.reset (new AudioPort (portname, (input ? IsInput : IsOutput)));
} else if (dtype == DataType::MIDI) {
- newport.reset (new MidiPort (portname, (input ? IsInput : IsOutput)));
+ if (async) {
+ DEBUG_TRACE (DEBUG::Ports, string_compose ("registering ASYNC MIDI port %1, input %2\n",
+ portname, input));
+ newport.reset (new AsyncMIDIPort (portname, (input ? IsInput : IsOutput)));
+ } else {
+ DEBUG_TRACE (DEBUG::Ports, string_compose ("registering MIDI port %1, input %2\n",
+ portname, input));
+ newport.reset (new MidiPort (portname, (input ? IsInput : IsOutput)));
+ }
} else {
throw PortRegistrationFailure("unable to create port (unknown type)");
}
@@ -281,7 +304,6 @@ PortManager::register_port (DataType dtype, const string& portname, bool input)
/* writer goes out of scope, forces update */
- return newport;
}
catch (PortRegistrationFailure& err) {
@@ -292,18 +314,21 @@ PortManager::register_port (DataType dtype, const string& portname, bool input)
} catch (...) {
throw PortRegistrationFailure("unable to create port (unknown error)");
}
+
+ DEBUG_TRACE (DEBUG::Ports, string_compose ("\t%2 port registration success, ports now = %1\n", ports.reader()->size(), this));
+ return newport;
}
boost::shared_ptr<Port>
-PortManager::register_input_port (DataType type, const string& portname)
+PortManager::register_input_port (DataType type, const string& portname, bool async)
{
- return register_port (type, portname, true);
+ return register_port (type, portname, true, async);
}
boost::shared_ptr<Port>
-PortManager::register_output_port (DataType type, const string& portname)
+PortManager::register_output_port (DataType type, const string& portname, bool async)
{
- return register_port (type, portname, false);
+ return register_port (type, portname, false, async);
}
int
@@ -410,6 +435,8 @@ PortManager::reestablish_ports ()
boost::shared_ptr<Ports> p = ports.reader ();
+ DEBUG_TRACE (DEBUG::Ports, string_compose ("reestablish %1 ports\n", p->size()));
+
for (i = p->begin(); i != p->end(); ++i) {
if (i->second->reestablish ()) {
break;
@@ -422,8 +449,6 @@ PortManager::reestablish_ports ()
return -1;
}
- MIDI::Manager::instance()->reestablish ();
-
return 0;
}
@@ -434,12 +459,12 @@ PortManager::reconnect_ports ()
/* re-establish connections */
+ DEBUG_TRACE (DEBUG::Ports, string_compose ("reconnect %1 ports\n", p->size()));
+
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
i->second->reconnect ();
}
- MIDI::Manager::instance()->reconnect ();
-
return 0;
}
@@ -543,3 +568,80 @@ PortManager::graph_order_callback ()
return 0;
}
+
+void
+PortManager::cycle_start (pframes_t nframes)
+{
+ Port::set_global_port_buffer_offset (0);
+ Port::set_cycle_framecnt (nframes);
+
+ _cycle_ports = ports.reader ();
+
+ for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
+ p->second->cycle_start (nframes);
+ }
+}
+
+void
+PortManager::cycle_end (pframes_t nframes)
+{
+ for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
+ p->second->cycle_end (nframes);
+ }
+
+ for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
+ p->second->flush_buffers (nframes);
+ }
+
+ _cycle_ports.reset ();
+
+ /* we are done */
+}
+
+void
+PortManager::silence (pframes_t nframes)
+{
+ for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
+ if (i->second->sends_output()) {
+ i->second->get_buffer(nframes).silence(nframes);
+ }
+ }
+}
+
+void
+PortManager::check_monitoring ()
+{
+ for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
+
+ bool x;
+
+ if (i->second->last_monitor() != (x = i->second->monitoring_input ())) {
+ i->second->set_last_monitor (x);
+ /* XXX I think this is dangerous, due to
+ a likely mutex in the signal handlers ...
+ */
+ i->second->MonitorInputChanged (x); /* EMIT SIGNAL */
+ }
+ }
+}
+
+void
+PortManager::fade_out (gain_t base_gain, gain_t gain_step, pframes_t nframes)
+{
+ for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
+
+ if (i->second->sends_output()) {
+
+ boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
+ if (ap) {
+ Sample* s = ap->engine_get_whole_audio_buffer ();
+ gain_t g = base_gain;
+
+ for (pframes_t n = 0; n < nframes; ++n) {
+ *s++ *= g;
+ g -= gain_step;
+ }
+ }
+ }
+ }
+}
diff --git a/libs/ardour/rc_configuration.cc b/libs/ardour/rc_configuration.cc
index 8127267975..007d6041db 100644
--- a/libs/ardour/rc_configuration.cc
+++ b/libs/ardour/rc_configuration.cc
@@ -27,13 +27,12 @@
#include "pbd/xml++.h"
#include "pbd/file_utils.h"
-#include "midi++/manager.h"
-
#include "ardour/control_protocol_manager.h"
#include "ardour/diskstream.h"
#include "ardour/filesystem_paths.h"
#include "ardour/rc_configuration.h"
#include "ardour/session_metadata.h"
+#include "ardour/midiport_manager.h"
#include "i18n.h"
@@ -177,15 +176,20 @@ RCConfiguration::get_state ()
root = new XMLNode("Ardour");
- MIDI::Manager* mm = MIDI::Manager::instance();
+ /* XXX
+ * GET STATE OF MIDI::Port HERE
+ */
+#if 0
+ MidiPortManager* mm = MidiPortManager::instance();
if (mm) {
- boost::shared_ptr<const MIDI::Manager::PortList> ports = mm->get_midi_ports();
+ boost::shared_ptr<const MidiPortManager::PortList> ports = mm->get_midi_ports();
- for (MIDI::Manager::PortList::const_iterator i = ports->begin(); i != ports->end(); ++i) {
- root->add_child_nocopy((*i)->get_state());
+ for (MidiPortManager::PortList::const_iterator i = ports->begin(); i != ports->end(); ++i) {
+ // root->add_child_nocopy ((*i)->get_state());
}
}
+#endif
root->add_child_nocopy (get_variables ());
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 9667bbcd2c..cc4a99b11f 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -49,6 +49,7 @@
#include "ardour/amp.h"
#include "ardour/analyser.h"
+#include "ardour/async_midi_port.h"
#include "ardour/audio_buffer.h"
#include "ardour/audio_diskstream.h"
#include "ardour/audio_port.h"
@@ -66,6 +67,7 @@
#include "ardour/debug.h"
#include "ardour/filename_extensions.h"
#include "ardour/graph.h"
+#include "ardour/midiport_manager.h"
#include "ardour/midi_track.h"
#include "ardour/midi_ui.h"
#include "ardour/operations.h"
@@ -88,9 +90,7 @@
#include "ardour/utils.h"
#include "midi++/port.h"
-#include "midi++/jack_midi_port.h"
#include "midi++/mmc.h"
-#include "midi++/manager.h"
#include "i18n.h"
@@ -584,7 +584,8 @@ Session::when_engine_running ()
as it will set states for ports which the ControlProtocolManager creates.
*/
- MIDI::Manager::instance()->set_port_states (Config->midi_port_states ());
+ // XXX set state of MIDI::Port's
+ // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
/* And this must be done after the MIDI::Manager::set_port_states as
* it will try to make connections whose details are loaded by set_port_states.
@@ -874,7 +875,12 @@ Session::hookup_io ()
/* Tell all IO objects to connect themselves together */
IO::enable_connecting ();
- MIDI::JackMIDIPort::MakeConnections ();
+
+ /* Now tell all "floating" ports to connect to whatever
+ they should be connected to.
+ */
+
+ AudioEngine::instance()->reconnect_ports ();
/* Anyone who cares about input state, wake up and do something */
@@ -1169,7 +1175,7 @@ Session::enable_record ()
if (g_atomic_int_compare_and_exchange (&_record_status, rs, Recording)) {
_last_record_location = _transport_frame;
- MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordStrobe));
+ AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordStrobe));
if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
set_track_monitor_input_status (true);
@@ -1190,7 +1196,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);
- MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordExit));
+ AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordExit));
} else {
if (rs == Recording) {
g_atomic_int_set (&_record_status, Enabled);
@@ -1244,7 +1250,7 @@ Session::maybe_enable_record ()
enable_record ();
}
} else {
- MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordPause));
+ AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordPause));
RecordStateChanged (); /* EMIT SIGNAL */
}
diff --git a/libs/ardour/session_export.cc b/libs/ardour/session_export.cc
index 0db4fc33bb..ab37e915bf 100644
--- a/libs/ardour/session_export.cc
+++ b/libs/ardour/session_export.cc
@@ -21,7 +21,6 @@
#include "pbd/error.h"
#include <glibmm/threads.h>
-#include <midi++/manager.h>
#include <midi++/mmc.h>
#include "ardour/audioengine.h"
@@ -93,8 +92,8 @@ Session::pre_export ()
/* disable MMC output early */
- _pre_export_mmc_enabled = MIDI::Manager::instance()->mmc()->send_enabled ();
- MIDI::Manager::instance()->mmc()->enable_send (false);
+ _pre_export_mmc_enabled = AudioEngine::instance()->mmc().send_enabled ();
+ AudioEngine::instance()->mmc().enable_send (false);
return 0;
}
@@ -237,7 +236,7 @@ Session::finalize_audio_export ()
export_freewheel_connection.disconnect();
- MIDI::Manager::instance()->mmc()->enable_send (_pre_export_mmc_enabled);
+ AudioEngine::instance()->mmc().enable_send (_pre_export_mmc_enabled);
/* maybe write CUE/TOC */
diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc
index d137e5167c..07a34283e3 100644
--- a/libs/ardour/session_midi.cc
+++ b/libs/ardour/session_midi.cc
@@ -31,7 +31,6 @@
#include "midi++/mmc.h"
#include "midi++/port.h"
-#include "midi++/manager.h"
#include "pbd/error.h"
#include "pbd/pthread_utils.h"
@@ -41,6 +40,7 @@
#include "ardour/audio_track.h"
#include "ardour/audioengine.h"
#include "ardour/debug.h"
+#include "ardour/midi_port.h"
#include "ardour/midi_track.h"
#include "ardour/midi_ui.h"
#include "ardour/session.h"
@@ -349,7 +349,7 @@ Session::mmc_record_enable (MIDI::MachineControl &mmc, size_t trk, bool enabled)
* @param t time to send.
*/
int
-Session::send_full_time_code (framepos_t const t)
+Session::send_full_time_code (framepos_t const t, pframes_t nframes)
{
/* This function could easily send at a given frame offset, but would
* that be useful? Does ardour do sub-block accurate locating? [DR] */
@@ -424,10 +424,9 @@ Session::send_full_time_code (framepos_t const t)
msg[8] = timecode.frames;
// Send message at offset 0, sent time is for the start of this cycle
- if (MIDI::Manager::instance()->mtc_output_port()->midimsg (msg, sizeof (msg), 0)) {
- error << _("Session: could not send full MIDI time code") << endmsg;
- return -1;
- }
+
+ MidiBuffer& mb (AudioEngine::instance()->mtc_output_port()->get_midi_buffer (nframes));
+ mb.push_back (0, sizeof (msg), msg);
_pframes_since_last_mtc = 0;
return 0;
@@ -470,7 +469,7 @@ Session::send_midi_time_code_for_cycle (framepos_t start_frame, framepos_t end_f
next_quarter_frame_to_send, quarter_frame_duration));
if (rint(outbound_mtc_timecode_frame + (next_quarter_frame_to_send * quarter_frame_duration)) < _transport_frame) {
- send_full_time_code (_transport_frame);
+ send_full_time_code (_transport_frame, nframes);
return 0;
}
@@ -516,9 +515,10 @@ Session::send_midi_time_code_for_cycle (framepos_t start_frame, framepos_t end_f
pframes_t const out_stamp = (msg_time - start_frame) / _transport_speed;
assert (out_stamp < nframes);
- if (MIDI::Manager::instance()->mtc_output_port()->midimsg (mtc_msg, 2, out_stamp)) {
+ MidiBuffer& mb (AudioEngine::instance()->mtc_output_port()->get_midi_buffer(nframes));
+ if (!mb.push_back (out_stamp, 2, mtc_msg)) {
error << string_compose(_("Session: cannot send quarter-frame MTC message (%1)"), strerror (errno))
- << endmsg;
+ << endmsg;
return -1;
}
@@ -588,7 +588,7 @@ Session::mmc_step_timeout ()
void
-Session::send_song_position_pointer (framepos_t t)
+Session::send_song_position_pointer (framepos_t)
{
if (midi_clock) {
/* Do nothing for the moment */
diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc
index cecbd88f65..6a24198bec 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -40,7 +40,6 @@
#include "ardour/ticker.h"
#include "ardour/types.h"
-#include "midi++/manager.h"
#include "midi++/mmc.h"
#include "i18n.h"
@@ -85,7 +84,7 @@ Session::process (pframes_t nframes)
try {
if (!_engine.freewheeling() && Config->get_send_midi_clock() && transport_speed() == 1.0f && midi_clock->has_midi_port()) {
- midi_clock->tick (transport_at_start);
+ midi_clock->tick (transport_at_start, nframes);
}
} catch (...) {
/* don't bother with a message */
@@ -325,7 +324,7 @@ Session::process_with_events (pframes_t nframes)
* and prepare for rolling)
*/
if (_send_timecode_update) {
- send_full_time_code (_transport_frame);
+ send_full_time_code (_transport_frame, nframes);
}
if (!process_can_proceed()) {
@@ -492,6 +491,7 @@ Session::follow_slave (pframes_t nframes)
goto noroll;
}
+ _slave->process (nframes);
_slave->speed_and_position (slave_speed, slave_transport_frame);
DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index cae3b9720a..c4522f76e7 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -60,7 +60,6 @@
#include "midi++/mmc.h"
#include "midi++/port.h"
-#include "midi++/manager.h"
#include "evoral/SMF.hpp"
@@ -359,11 +358,11 @@ Session::second_stage_init ()
BootMessage (_("Reset Remote Controls"));
- send_full_time_code (0);
+ // send_full_time_code (0);
_engine.transport_locate (0);
- MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
- MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ()));
+ AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
+ AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (Timecode::Time ()));
MIDI::Name::MidiPatchManager::instance().set_session (this);
@@ -3429,11 +3428,11 @@ Session::config_changed (std::string p, bool ours)
} else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
- MIDI::Manager::instance()->mmc()->set_receive_device_id (Config->get_mmc_receive_device_id());
+ AudioEngine::instance()->mmc().set_receive_device_id (Config->get_mmc_receive_device_id());
} else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
- MIDI::Manager::instance()->mmc()->set_send_device_id (Config->get_mmc_send_device_id());
+ AudioEngine::instance()->mmc().set_send_device_id (Config->get_mmc_send_device_id());
} else if (p == "midi-control") {
@@ -3496,7 +3495,7 @@ Session::config_changed (std::string p, bool ours)
} else if (p == "send-mmc") {
- MIDI::Manager::instance()->mmc()->enable_send (Config->get_send_mmc ());
+ AudioEngine::instance()->mmc().enable_send (Config->get_send_mmc ());
} else if (p == "midi-feedback") {
@@ -3554,13 +3553,13 @@ Session::config_changed (std::string p, bool ours)
} else if (p == "initial-program-change") {
- if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {
+ if (AudioEngine::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);
- MIDI::Manager::instance()->mmc()->output_port()->midimsg (buf, sizeof (buf), 0);
+ AudioEngine::instance()->mmc().output_port()->midimsg (buf, sizeof (buf), 0);
}
} else if (p == "solo-mute-override") {
// catch_up_on_solo_mute_override ();
@@ -3624,27 +3623,27 @@ Session::load_diskstreams_2X (XMLNode const & node, int)
void
Session::setup_midi_machine_control ()
{
- 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));
+ MIDI::MachineControl& mmc (AudioEngine::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));
/* also handle MIDI SPP because its so common */
- mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
- mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
- mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
+ mmc.SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
+ mmc.SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
+ mmc.SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
}
boost::shared_ptr<Controllable>
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index 08e9a89481..44a885cd1c 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -33,7 +33,6 @@
#include "midi++/mmc.h"
#include "midi++/port.h"
-#include "midi++/manager.h"
#include "ardour/audioengine.h"
#include "ardour/auditioner.h"
@@ -611,10 +610,11 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
have_looped = false;
if (!_engine.freewheeling()) {
- send_full_time_code (_transport_frame);
+ // need to queue this in the next RT cycle
+ _send_timecode_update = true;
if (!dynamic_cast<MTC_Slave*>(_slave)) {
- MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
+ AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
send_mmc_locate (_transport_frame);
}
}
@@ -1260,7 +1260,7 @@ Session::start_transport ()
Timecode::Time time;
timecode_time_subframes (_transport_frame, time);
if (!dynamic_cast<MTC_Slave*>(_slave)) {
- MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
+ AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
}
}
@@ -1338,8 +1338,9 @@ Session::use_sync_source (Slave* new_slave)
_slave = new_slave;
DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
-
- send_full_time_code (_transport_frame);
+
+ // need to queue this for next process() cycle
+ _send_timecode_update = true;
boost::shared_ptr<RouteList> rl = routes.reader();
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
@@ -1380,7 +1381,7 @@ Session::switch_to_sync_source (SyncSource src)
}
try {
- new_slave = new MTC_Slave (*this, *MIDI::Manager::instance()->mtc_input_port());
+ new_slave = new MTC_Slave (*this, *AudioEngine::instance()->mtc_input_port());
}
catch (failed_constructor& err) {
@@ -1409,7 +1410,7 @@ Session::switch_to_sync_source (SyncSource src)
}
try {
- new_slave = new MIDIClock_Slave (*this, *MIDI::Manager::instance()->midi_clock_input_port(), 24);
+ new_slave = new MIDIClock_Slave (*this, *AudioEngine::instance()->midi_clock_input_port(), 24);
}
catch (failed_constructor& err) {
@@ -1636,7 +1637,7 @@ Session::send_mmc_locate (framepos_t t)
if (!_engine.freewheeling()) {
Timecode::Time time;
timecode_time_subframes (t, time);
- MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (time));
+ AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (time));
}
}
diff --git a/libs/ardour/ticker.cc b/libs/ardour/ticker.cc
index f32cdf9415..0ed4427b72 100644
--- a/libs/ardour/ticker.cc
+++ b/libs/ardour/ticker.cc
@@ -19,13 +19,12 @@
#include "pbd/compose.h"
#include "pbd/stacktrace.h"
-#include "midi++/port.h"
-#include "midi++/jack_midi_port.h"
-#include "midi++/manager.h"
-
#include "evoral/midi_events.h"
+#include "ardour/async_midi_port.h"
#include "ardour/audioengine.h"
+#include "ardour/midi_buffer.h"
+#include "ardour/midi_port.h"
#include "ardour/ticker.h"
#include "ardour/session.h"
#include "ardour/tempo.h"
@@ -95,16 +94,16 @@ public:
MidiClockTicker::MidiClockTicker ()
- : _midi_port (0)
- , _ppqn (24)
+ : _ppqn (24)
, _last_tick (0.0)
+ , _send_pos (false)
+ , _send_state (false)
{
_pos.reset (new Position());
}
MidiClockTicker::~MidiClockTicker()
{
- _midi_port = 0;
_pos.reset (0);
}
@@ -115,7 +114,6 @@ MidiClockTicker::set_session (Session* s)
if (_session) {
_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));
_session->Located.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::session_located, this));
@@ -139,41 +137,20 @@ MidiClockTicker::session_located()
return;
}
- if (_pos->speed == 0.0f) {
- uint32_t where = llrint (_pos->midi_beats);
- send_position_event (where, 0);
- } else if (_pos->speed == 1.0f) {
-#if 1
- /* Experimental. To really do this and have accuracy, the
- stop/locate/continue sequence would need queued to send immediately
- before the next midi clock. */
-
- send_stop_event (0);
-
- if (_pos->frame == 0) {
- send_start_event (0);
- } else {
- uint32_t where = llrint (_pos->midi_beats);
- send_position_event (where, 0);
- send_continue_event (0);
- }
-#endif
- } else {
- /* Varispeed not supported */
- }
+ _send_pos = true;
}
void
MidiClockTicker::session_going_away ()
{
SessionHandlePtr::session_going_away();
- _midi_port = 0;
+ _midi_port.reset ();
}
void
MidiClockTicker::update_midi_clock_port()
{
- _midi_port = MIDI::Manager::instance()->midi_clock_output_port();
+ _midi_port = AudioEngine::instance()->midi_clock_output_port();
}
void
@@ -204,49 +181,12 @@ MidiClockTicker::transport_state_changed()
return;
}
- if (_pos->speed == 1.0f) {
-
- if (_session->get_play_loop()) {
- assert(_session->locations()->auto_loop_location());
-
- if (_pos->frame == _session->locations()->auto_loop_location()->start()) {
- send_start_event(0);
- } else {
- send_continue_event(0);
- }
-
- } else if (_pos->frame == 0) {
- send_start_event(0);
- } else {
- send_continue_event(0);
- }
-
- // send_midi_clock_event (0);
-
- } else if (_pos->speed == 0.0f) {
- send_stop_event (0);
- send_position_event (llrint (_pos->midi_beats), 0);
- }
+ _send_state = true;
// tick (_pos->frame);
}
void
-MidiClockTicker::position_changed (framepos_t)
-{
-#if 0
- const double speed = _session->transport_speed();
- DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Transport Position Change: %1, speed: %2\n", position, speed));
-
- if (speed == 0.0f && Config->get_send_midi_clock()) {
- send_position_event (position, 0);
- }
-
- _last_tick = position;
-#endif
-}
-
-void
MidiClockTicker::transport_looped()
{
Location* loop_location = _session->locations()->auto_loop_location();
@@ -270,18 +210,68 @@ MidiClockTicker::transport_looped()
}
void
-MidiClockTicker::tick (const framepos_t& /* transport_frame */)
+MidiClockTicker::tick (const framepos_t& /* transport_frame */, pframes_t nframes)
{
if (!Config->get_send_midi_clock() || _session == 0 || _session->transport_speed() != 1.0f || _midi_port == 0) {
return;
}
- MIDI::JackMIDIPort* mp = dynamic_cast<MIDI::JackMIDIPort*> (_midi_port);
- if (! mp) {
- return;
+ if (_send_pos) {
+ if (_pos->speed == 0.0f) {
+ uint32_t where = llrint (_pos->midi_beats);
+ send_position_event (where, 0, nframes);
+ } else if (_pos->speed == 1.0f) {
+#if 1
+ /* Experimental. To really do this and have accuracy, the
+ stop/locate/continue sequence would need queued to send immediately
+ before the next midi clock. */
+
+ send_stop_event (0, nframes);
+
+ if (_pos->frame == 0) {
+ send_start_event (0, nframes);
+ } else {
+ uint32_t where = llrint (_pos->midi_beats);
+ send_position_event (where, 0, nframes);
+ send_continue_event (0, nframes);
+ }
+#endif
+ } else {
+ /* Varispeed not supported */
+ }
+
+ _send_pos = true;
}
- const framepos_t end = _pos->frame + mp->nframes_this_cycle();
+ if (_send_state) {
+ if (_pos->speed == 1.0f) {
+ if (_session->get_play_loop()) {
+ assert(_session->locations()->auto_loop_location());
+
+ if (_pos->frame == _session->locations()->auto_loop_location()->start()) {
+ send_start_event (0, nframes);
+ } else {
+ send_continue_event (0, nframes);
+ }
+
+ } else if (_pos->frame == 0) {
+ send_start_event (0, nframes);
+ } else {
+ send_continue_event (0, nframes);
+ }
+
+ // send_midi_clock_event (0);
+
+ } else if (_pos->speed == 0.0f) {
+ send_stop_event (0, nframes);
+ send_position_event (llrint (_pos->midi_beats), 0, nframes);
+ }
+
+ _send_state = false;
+ }
+
+
+ const framepos_t end = _pos->frame + nframes;
double iter = _last_tick;
while (true) {
@@ -291,14 +281,14 @@ MidiClockTicker::tick (const framepos_t& /* transport_frame */)
DEBUG_TRACE (DEBUG::MidiClock,
string_compose ("Tick: iter: %1, last tick time: %2, next tick time: %3, offset: %4, cycle length: %5\n",
- iter, _last_tick, next_tick, next_tick_offset, mp ? mp->nframes_this_cycle() : 0));
+ iter, _last_tick, next_tick, next_tick_offset, nframes));
- if (!mp || (next_tick_offset >= mp->nframes_this_cycle())) {
+ if (next_tick_offset >= nframes) {
break;
}
if (next_tick_offset >= 0) {
- send_midi_clock_event (next_tick_offset);
+ send_midi_clock_event (next_tick_offset, nframes);
}
iter = next_tick;
@@ -308,7 +298,6 @@ MidiClockTicker::tick (const framepos_t& /* transport_frame */)
_pos->frame = end;
}
-
double
MidiClockTicker::one_ppqn_in_frames (framepos_t transport_position)
{
@@ -322,7 +311,7 @@ MidiClockTicker::one_ppqn_in_frames (framepos_t transport_position)
}
void
-MidiClockTicker::send_midi_clock_event (pframes_t offset)
+MidiClockTicker::send_midi_clock_event (pframes_t offset, pframes_t nframes)
{
if (!_midi_port) {
return;
@@ -330,12 +319,13 @@ MidiClockTicker::send_midi_clock_event (pframes_t offset)
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Tick with offset %1\n", offset));
- static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_CLOCK };
- _midi_port->write (_midi_clock_tick, 1, offset);
+ static uint8_t tick_byte = { MIDI_CMD_COMMON_CLOCK };
+ MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
+ mb.push_back (offset, 1, &tick_byte);
}
void
-MidiClockTicker::send_start_event (pframes_t offset)
+MidiClockTicker::send_start_event (pframes_t offset, pframes_t nframes)
{
if (!_midi_port) {
return;
@@ -343,12 +333,13 @@ MidiClockTicker::send_start_event (pframes_t offset)
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Start %1\n", _last_tick));
- static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_START };
- _midi_port->write (_midi_clock_tick, 1, offset);
+ static uint8_t tick_byte = { MIDI_CMD_COMMON_START };
+ MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
+ mb.push_back (offset, 1, &tick_byte);
}
void
-MidiClockTicker::send_continue_event (pframes_t offset)
+MidiClockTicker::send_continue_event (pframes_t offset, pframes_t nframes)
{
if (!_midi_port) {
return;
@@ -356,12 +347,13 @@ MidiClockTicker::send_continue_event (pframes_t offset)
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Continue %1\n", _last_tick));
- static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_CONTINUE };
- _midi_port->write (_midi_clock_tick, 1, offset);
+ static uint8_t tick_byte = { MIDI_CMD_COMMON_CONTINUE };
+ MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
+ mb.push_back (offset, 1, &tick_byte);
}
void
-MidiClockTicker::send_stop_event (pframes_t offset)
+MidiClockTicker::send_stop_event (pframes_t offset, pframes_t nframes)
{
if (!_midi_port) {
return;
@@ -369,12 +361,13 @@ MidiClockTicker::send_stop_event (pframes_t offset)
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Stop %1\n", _last_tick));
- static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_STOP };
- _midi_port->write (_midi_clock_tick, 1, offset);
+ static uint8_t tick_byte = { MIDI_CMD_COMMON_STOP };
+ MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
+ mb.push_back (offset, 1, &tick_byte);
}
void
-MidiClockTicker::send_position_event (uint32_t midi_beats, pframes_t offset)
+MidiClockTicker::send_position_event (uint32_t midi_beats, pframes_t offset, pframes_t nframes)
{
if (!_midi_port) {
return;
@@ -391,7 +384,8 @@ MidiClockTicker::send_position_event (uint32_t midi_beats, pframes_t offset)
msg[1] = midi_beats & 0x007f;
msg[2] = midi_beats >> 7;
- _midi_port->midimsg (msg, sizeof (msg), offset);
+ MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
+ mb.push_back (offset, 3, &msg[0]);
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Song Position Sent: %1\n", midi_beats));
}
diff --git a/libs/ardour/wscript b/libs/ardour/wscript
index d48a4d6d85..f13c4e5eef 100644
--- a/libs/ardour/wscript
+++ b/libs/ardour/wscript
@@ -21,6 +21,7 @@ path_prefix = 'libs/ardour/'
libardour_sources = [
'amp.cc',
'analyser.cc',
+ 'async_midi_port.cc',
'audio_buffer.cc',
'audio_diskstream.cc',
'audio_library.cc',
@@ -126,6 +127,7 @@ libardour_sources = [
'midi_stretch.cc',
'midi_track.cc',
'midi_ui.cc',
+ 'midiport_manager.cc',
'mix.cc',
'monitor_processor.cc',
'mtc_slave.cc',