summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/ardour_ui.cc42
-rw-r--r--gtk2_ardour/editor.cc3
-rw-r--r--gtk2_ardour/editor_drag.cc5
-rw-r--r--gtk2_ardour/gain_meter.cc1
-rw-r--r--gtk2_ardour/generic_pluginui.cc2
-rw-r--r--gtk2_ardour/level_meter.cc1
-rw-r--r--gtk2_ardour/midi_tracer.cc45
-rw-r--r--gtk2_ardour/panner_ui.cc1
-rw-r--r--gtk2_ardour/plugin_ui.cc2
-rw-r--r--gtk2_ardour/port_group.cc28
-rw-r--r--gtk2_ardour/rc_option_editor.cc2
-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
-rw-r--r--libs/midi++2/midi++/mmc.h5
-rw-r--r--libs/midi++2/midi++/parser.h4
-rw-r--r--libs/midi++2/midi++/port.h7
-rw-r--r--libs/midi++2/mmc.cc15
-rw-r--r--libs/midi++2/parser.cc3
-rw-r--r--libs/midi++2/port.cc2
-rw-r--r--libs/midi++2/wscript2
-rw-r--r--libs/surfaces/generic_midi/generic_midi_control_protocol.cc19
-rw-r--r--libs/surfaces/generic_midi/generic_midi_control_protocol.h18
-rw-r--r--libs/surfaces/generic_midi/midiaction.cc2
-rw-r--r--libs/surfaces/generic_midi/midiaction.h4
-rw-r--r--libs/surfaces/generic_midi/midicontrollable.cc38
-rw-r--r--libs/surfaces/generic_midi/midicontrollable.h15
-rw-r--r--libs/surfaces/generic_midi/midifunction.cc2
-rw-r--r--libs/surfaces/generic_midi/midifunction.h3
-rw-r--r--libs/surfaces/generic_midi/midiinvokable.cc22
-rw-r--r--libs/surfaces/generic_midi/midiinvokable.h7
-rw-r--r--libs/surfaces/mackie/surface.cc1
-rw-r--r--libs/surfaces/mackie/surface_port.cc47
-rw-r--r--libs/surfaces/mackie/surface_port.h23
62 files changed, 743 insertions, 564 deletions
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index a3ea2b1612..69e2a339dd 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -58,8 +58,6 @@
#include "gtkmm2ext/popup.h"
#include "gtkmm2ext/window_title.h"
-#include "midi++/manager.h"
-
#include "ardour/ardour.h"
#include "ardour/audio_backend.h"
#include "ardour/audioengine.h"
@@ -1050,14 +1048,20 @@ ARDOUR_UI::update_sample_rate (framecnt_t)
framecnt_t rate = engine->sample_rate();
- if (fmod (rate, 1000.0) != 0.0) {
- snprintf (buf, sizeof (buf), _("JACK: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"),
- (float) rate / 1000.0f,
- (engine->usecs_per_cycle() / 1000.0f));
+ if (rate == 0) {
+ /* no sample rate available */
+ snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"red\">disconnected</span>"));
} else {
- snprintf (buf, sizeof (buf), _("JACK: <span foreground=\"green\">%" PRId64 " kHz / %4.1f ms</span>"),
- rate/1000,
- (engine->usecs_per_cycle() * 1000.0f));
+
+ if (fmod (rate, 1000.0) != 0.0) {
+ snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"),
+ (float) rate / 1000.0f,
+ (engine->usecs_per_cycle() / 1000.0f));
+ } else {
+ snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"green\">%" PRId64 " kHz / %4.1f ms</span>"),
+ rate/1000,
+ (engine->usecs_per_cycle() * 1000.0f));
+ }
}
}
@@ -1181,6 +1185,11 @@ ARDOUR_UI::update_disk_space()
char buf[64];
framecnt_t fr = _session->frame_rate();
+ if (fr == 0) {
+ /* skip update - no SR available */
+ return;
+ }
+
if (!opt_frames) {
/* Available space is unknown */
snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">Unknown</span>"));
@@ -1662,10 +1671,17 @@ ARDOUR_UI::transport_goto_wallclock ()
time (&now);
localtime_r (&now, &tmnow);
+
+ int frame_rate = _session->frame_rate();
+
+ if (frame_rate == 0) {
+ /* no frame rate available */
+ return;
+ }
- frames = tmnow.tm_hour * (60 * 60 * _session->frame_rate());
- frames += tmnow.tm_min * (60 * _session->frame_rate());
- frames += tmnow.tm_sec * _session->frame_rate();
+ frames = tmnow.tm_hour * (60 * 60 * frame_rate);
+ frames += tmnow.tm_min * (60 * frame_rate);
+ frames += tmnow.tm_sec * frame_rate;
_session->request_locate (frames, _session->transport_rolling ());
@@ -3802,7 +3818,7 @@ void
ARDOUR_UI::disconnect_from_jack ()
{
if (engine) {
- if (engine->pause ()) {
+ if (engine->stop ()) {
MessageDialog msg (*editor, _("Could not disconnect from JACK"));
msg.run ();
}
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index 300e317a38..a0418892e7 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -1258,7 +1258,8 @@ Editor::set_session (Session *t)
/* These signals can all be emitted by a non-GUI thread. Therefore the
handlers for them must not attempt to directly interact with the GUI,
- but use Gtkmm2ext::UI::instance()->call_slot();
+ but use PBD::Signal<T>::connect() which accepts an event loop
+ ("context") where the handler will be asked to run.
*/
_session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc
index b083e851c5..3389164f50 100644
--- a/gtk2_ardour/editor_drag.cc
+++ b/gtk2_ardour/editor_drag.cc
@@ -2372,8 +2372,9 @@ CursorDrag::fake_locate (framepos_t t)
if (s->timecode_transmission_suspended ()) {
framepos_t const f = _editor->playhead_cursor->current_frame;
s->send_mmc_locate (f);
- s->send_full_time_code (f);
- s->send_song_position_pointer (f);
+ // XXX need to queue full time code and SPP messages somehow
+ // s->send_full_time_code (f);
+ // s->send_song_position_pointer (f);
}
show_verbose_cursor_time (t);
diff --git a/gtk2_ardour/gain_meter.cc b/gtk2_ardour/gain_meter.cc
index 10512b24d0..b2beb5b9a3 100644
--- a/gtk2_ardour/gain_meter.cc
+++ b/gtk2_ardour/gain_meter.cc
@@ -32,7 +32,6 @@
#include <gtkmm2ext/fastmeter.h>
#include <gtkmm2ext/barcontroller.h>
#include <gtkmm2ext/gtk_ui.h>
-#include "midi++/manager.h"
#include "pbd/fastlog.h"
#include "pbd/stacktrace.h"
diff --git a/gtk2_ardour/generic_pluginui.cc b/gtk2_ardour/generic_pluginui.cc
index 971dfc0e9b..4405d05c1c 100644
--- a/gtk2_ardour/generic_pluginui.cc
+++ b/gtk2_ardour/generic_pluginui.cc
@@ -37,8 +37,6 @@
#include <gtkmm2ext/doi.h>
#include <gtkmm2ext/slider_controller.h>
-#include "midi++/manager.h"
-
#include "ardour/plugin.h"
#include "ardour/plugin_insert.h"
#include "ardour/session.h"
diff --git a/gtk2_ardour/level_meter.cc b/gtk2_ardour/level_meter.cc
index 6f48864992..bf9823518b 100644
--- a/gtk2_ardour/level_meter.cc
+++ b/gtk2_ardour/level_meter.cc
@@ -23,7 +23,6 @@
#include <gtkmm2ext/utils.h>
#include <gtkmm2ext/barcontroller.h>
-#include "midi++/manager.h"
#include "pbd/fastlog.h"
#include "ardour_ui.h"
diff --git a/gtk2_ardour/midi_tracer.cc b/gtk2_ardour/midi_tracer.cc
index 073fd9cc15..fee339d126 100644
--- a/gtk2_ardour/midi_tracer.cc
+++ b/gtk2_ardour/midi_tracer.cc
@@ -24,7 +24,10 @@
#include <time.h>
#include "midi++/parser.h"
-#include "midi++/manager.h"
+
+#include "ardour/async_midi_port.h"
+#include "ardour/midi_port.h"
+#include "ardour/audioengine.h"
#include "midi_tracer.h"
#include "gui_thread.h"
@@ -53,7 +56,8 @@ MidiTracer::MidiTracer ()
, collect_button (_("Enabled"))
, delta_time_button (_("Delta times"))
{
- Manager::instance()->PortsChanged.connect (_manager_connection, invalidator (*this), boost::bind (&MidiTracer::ports_changed, this), gui_context());
+ ARDOUR::AudioEngine::instance()->PortRegisteredOrUnregistered.connect
+ (_manager_connection, invalidator (*this), boost::bind (&MidiTracer::ports_changed, this), gui_context());
_last_receipt.tv_sec = 0;
_last_receipt.tv_usec = 0;
@@ -126,25 +130,50 @@ MidiTracer::ports_changed ()
{
string const c = _port_combo.get_active_text ();
_port_combo.clear ();
+
+ ARDOUR::PortManager::PortList pl;
+ ARDOUR::AudioEngine::instance()->get_ports (ARDOUR::DataType::MIDI, pl);
+
+ if (pl.empty()) {
+ _port_combo.set_active_text ("");
+ return;
+ }
- boost::shared_ptr<const Manager::PortList> p = Manager::instance()->get_midi_ports ();
- for (Manager::PortList::const_iterator i = p->begin(); i != p->end(); ++i) {
+ for (ARDOUR::PortManager::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
_port_combo.append_text ((*i)->name());
}
- _port_combo.set_active_text (c);
+ if (c.empty()) {
+ _port_combo.set_active_text (pl.front()->name());
+ } else {
+ _port_combo.set_active_text (c);
+ }
}
void
MidiTracer::port_changed ()
{
+ using namespace ARDOUR;
+
disconnect ();
- Port* p = Manager::instance()->port (_port_combo.get_active_text());
+ boost::shared_ptr<ARDOUR::Port> p = AudioEngine::instance()->get_port_by_name (_port_combo.get_active_text());
+
+ if (!p) {
+ std::cerr << "port not found\n";
+ return;
+ }
+
+ boost::shared_ptr<AsyncMIDIPort> async = boost::dynamic_pointer_cast<AsyncMIDIPort> (p);
- if (p) {
- p->parser()->any.connect_same_thread (_parser_connection, boost::bind (&MidiTracer::tracer, this, _1, _2, _3));
+ if (!async) {
+ /* pure ARDOUR::MidiPort ... cannot currently attach to it because it
+ * has no Parser.
+ */
+ return;
}
+
+ async->parser()->any.connect_same_thread (_parser_connection, boost::bind (&MidiTracer::tracer, this, _1, _2, _3));
}
void
diff --git a/gtk2_ardour/panner_ui.cc b/gtk2_ardour/panner_ui.cc
index 181664bb4e..c82a44f399 100644
--- a/gtk2_ardour/panner_ui.cc
+++ b/gtk2_ardour/panner_ui.cc
@@ -21,7 +21,6 @@
#include <gtkmm2ext/utils.h>
#include <gtkmm2ext/barcontroller.h>
-#include "midi++/manager.h"
#include "pbd/fastlog.h"
#include "ardour/pannable.h"
diff --git a/gtk2_ardour/plugin_ui.cc b/gtk2_ardour/plugin_ui.cc
index d9741f5e39..713b98cdaf 100644
--- a/gtk2_ardour/plugin_ui.cc
+++ b/gtk2_ardour/plugin_ui.cc
@@ -40,8 +40,6 @@
#include <gtkmm2ext/slider_controller.h>
#include <gtkmm2ext/application.h>
-#include "midi++/manager.h"
-
#include "ardour/session.h"
#include "ardour/plugin.h"
#include "ardour/plugin_insert.h"
diff --git a/gtk2_ardour/port_group.cc b/gtk2_ardour/port_group.cc
index 5b4f151da8..f8c8e2bde2 100644
--- a/gtk2_ardour/port_group.cc
+++ b/gtk2_ardour/port_group.cc
@@ -21,7 +21,6 @@
#include <boost/shared_ptr.hpp>
#include <boost/algorithm/string.hpp>
-#include "midi++/manager.h"
#include "midi++/mmc.h"
#include "ardour/audioengine.h"
@@ -29,9 +28,13 @@
#include "ardour/bundle.h"
#include "ardour/control_protocol_manager.h"
#include "ardour/io_processor.h"
+#include "ardour/midi_port.h"
+#include "ardour/midiport_manager.h"
#include "ardour/session.h"
#include "ardour/user_bundle.h"
#include "ardour/port.h"
+#include "ardour/syncport_manager.h"
+
#include "control_protocol/control_protocol.h"
#include "gui_thread.h"
@@ -452,37 +455,36 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
/* Ardour's sync ports */
- MIDI::Manager* midi_manager = MIDI::Manager::instance ();
- if (midi_manager && (type == DataType::MIDI || type == DataType::NIL)) {
+ if ((type == DataType::MIDI || type == DataType::NIL)) {
boost::shared_ptr<Bundle> sync (new Bundle (_("Sync"), inputs));
- MIDI::MachineControl* mmc = midi_manager->mmc ();
- AudioEngine& ae = session->engine ();
+ AudioEngine* ae = AudioEngine::instance();
+ MIDI::MachineControl& mmc (ae->mmc());
if (inputs) {
sync->add_channel (
- _("MTC in"), DataType::MIDI, ae.make_port_name_non_relative (midi_manager->mtc_input_port()->name())
+ _("MTC in"), DataType::MIDI, ae->make_port_name_non_relative (ae->mtc_input_port()->name())
);
sync->add_channel (
- _("MIDI control in"), DataType::MIDI, ae.make_port_name_non_relative (midi_manager->midi_input_port()->name())
+ _("MIDI control in"), DataType::MIDI, ae->make_port_name_non_relative (ae->midi_input_port()->name())
);
sync->add_channel (
- _("MIDI clock in"), DataType::MIDI, ae.make_port_name_non_relative (midi_manager->midi_clock_input_port()->name())
+ _("MIDI clock in"), DataType::MIDI, ae->make_port_name_non_relative (ae->midi_clock_input_port()->name())
);
sync->add_channel (
- _("MMC in"), DataType::MIDI, ae.make_port_name_non_relative (mmc->input_port()->name())
+ _("MMC in"), DataType::MIDI, ae->make_port_name_non_relative (mmc.input_port()->name())
);
} else {
sync->add_channel (
- _("MTC out"), DataType::MIDI, ae.make_port_name_non_relative (midi_manager->mtc_output_port()->name())
+ _("MTC out"), DataType::MIDI, ae->make_port_name_non_relative (ae->mtc_output_port()->name())
);
sync->add_channel (
- _("MIDI control out"), DataType::MIDI, ae.make_port_name_non_relative (midi_manager->midi_output_port()->name())
+ _("MIDI control out"), DataType::MIDI, ae->make_port_name_non_relative (ae->midi_output_port()->name())
);
sync->add_channel (
- _("MIDI clock out"), DataType::MIDI, ae.make_port_name_non_relative (midi_manager->midi_clock_output_port()->name())
+ _("MIDI clock out"), DataType::MIDI, ae->make_port_name_non_relative (ae->midi_clock_output_port()->name())
);
sync->add_channel (
- _("MMC out"), DataType::MIDI, ae.make_port_name_non_relative (mmc->output_port()->name())
+ _("MMC out"), DataType::MIDI, ae->make_port_name_non_relative (mmc.output_port()->name())
);
}
diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc
index 54b96bbb8d..ed9ffda4ef 100644
--- a/gtk2_ardour/rc_option_editor.cc
+++ b/gtk2_ardour/rc_option_editor.cc
@@ -31,8 +31,6 @@
#include "pbd/fpu.h"
#include "pbd/cpus.h"
-#include "midi++/manager.h"
-
#include "ardour/audioengine.h"
#include "ardour/dB.h"
#include "ardour/rc_configuration.h"
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',
diff --git a/libs/midi++2/midi++/mmc.h b/libs/midi++2/midi++/mmc.h
index 0f362678ce..01f8bf3b8a 100644
--- a/libs/midi++2/midi++/mmc.h
+++ b/libs/midi++2/midi++/mmc.h
@@ -38,7 +38,6 @@ namespace MIDI {
class Port;
class Parser;
class MachineControlCommand;
-class Manager;
/** Class to handle incoming and outgoing MIDI machine control messages */
class MachineControl
@@ -95,7 +94,9 @@ class MachineControl
cmdResume = 0x7F
};
- MachineControl (Manager *, ARDOUR::PortEngine&);
+ MachineControl ();
+
+ void set_ports (MIDI::Port* input, MIDI::Port* output);
Port* input_port() { return _input_port; }
Port* output_port() { return _output_port; }
diff --git a/libs/midi++2/midi++/parser.h b/libs/midi++2/midi++/parser.h
index f5f343e952..44897f9d8e 100644
--- a/libs/midi++2/midi++/parser.h
+++ b/libs/midi++2/midi++/parser.h
@@ -41,7 +41,7 @@ typedef PBD::Signal3<void,Parser &, byte *, size_t> Signal;
class Parser {
public:
- Parser (Port &p);
+ Parser ();
~Parser ();
/* sets the time that will be reported for any MTC or MIDI Clock
@@ -105,7 +105,6 @@ class Parser {
const char *midi_event_type_name (MIDI::eventType);
void trace (bool onoff, std::ostream *o, const std::string &prefix = "");
bool tracing() { return trace_stream != 0; }
- Port &port() { return _port; }
void set_offline (bool);
bool offline() const { return _offline; }
@@ -136,7 +135,6 @@ class Parser {
void reset_mtc_state ();
private:
- Port&_port;
/* tracing */
std::ostream *trace_stream;
diff --git a/libs/midi++2/midi++/port.h b/libs/midi++2/midi++/port.h
index 599fabaa87..6d778beab2 100644
--- a/libs/midi++2/midi++/port.h
+++ b/libs/midi++2/midi++/port.h
@@ -51,13 +51,6 @@ class Port {
virtual XMLNode& get_state () const;
virtual void set_state (const XMLNode&);
- // FIXME: make Manager a friend of port so these can be hidden?
-
- /* Only for use by MidiManager. Don't ever call this. */
- virtual void cycle_start (pframes_t) {}
- /* Only for use by MidiManager. Don't ever call this. */
- virtual void cycle_end () {}
-
/** Write a message to port.
* @param msg Raw MIDI message to send
* @param msglen Size of @a msg
diff --git a/libs/midi++2/mmc.cc b/libs/midi++2/mmc.cc
index 0a71463721..b93dc0f260 100644
--- a/libs/midi++2/mmc.cc
+++ b/libs/midi++2/mmc.cc
@@ -27,9 +27,7 @@
#include "midi++/mmc.h"
#include "midi++/port.h"
-#include "midi++/jack_midi_port.h"
#include "midi++/parser.h"
-#include "midi++/manager.h"
using namespace std;
using namespace MIDI;
@@ -197,16 +195,21 @@ static void build_mmc_cmd_map ()
mmc_cmd_map.insert (newpair);
}
-
-MachineControl::MachineControl (Manager* m, ARDOUR::PortEngine& pengine)
+MachineControl::MachineControl ()
{
build_mmc_cmd_map ();
_receive_device_id = 0x7f;
_send_device_id = 0x7f;
+}
+
+void
+MachineControl::set_ports (MIDI::Port* ip, MIDI::Port* op)
+{
+ port_connections.drop_connections ();
- _input_port = m->add_port (new JackMIDIPort ("MMC in", Port::IsInput, pengine));
- _output_port = m->add_port (new JackMIDIPort ("MMC out", Port::IsOutput, pengine));
+ _input_port = ip;
+ _output_port = op;
_input_port->parser()->mmc.connect_same_thread (port_connections, boost::bind (&MachineControl::process_mmc_message, this, _1, _2, _3));
_input_port->parser()->start.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_start, this));
diff --git a/libs/midi++2/parser.cc b/libs/midi++2/parser.cc
index 8e3af64504..2f6b50899c 100644
--- a/libs/midi++2/parser.cc
+++ b/libs/midi++2/parser.cc
@@ -104,8 +104,7 @@ Parser::midi_event_type_name (eventType t)
}
}
-Parser::Parser (Port &p)
- : _port(p)
+Parser::Parser ()
{
trace_stream = 0;
trace_prefix = "";
diff --git a/libs/midi++2/port.cc b/libs/midi++2/port.cc
index 3e7896631a..1480202867 100644
--- a/libs/midi++2/port.cc
+++ b/libs/midi++2/port.cc
@@ -71,7 +71,7 @@ Port::init (string const & name, Flags flags)
_tagname = name;
_flags = flags;
- _parser = new Parser (*this);
+ _parser = new Parser ();
for (int i = 0; i < 16; i++) {
_channel[i] = new Channel (i, *this);
diff --git a/libs/midi++2/wscript b/libs/midi++2/wscript
index 8a4f2f6c69..0abbab7d40 100644
--- a/libs/midi++2/wscript
+++ b/libs/midi++2/wscript
@@ -31,8 +31,6 @@ libmidi_sources = [
'midi.cc',
'channel.cc',
'ipmidi_port.cc',
- 'jack_midi_port.cc',
- 'manager.cc',
'parser.cc',
'port.cc',
'midnam_patch.cc',
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
index 6da0192a8f..2820b069dc 100644
--- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
+++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
@@ -32,13 +32,14 @@
#include "pbd/xml++.h"
#include "midi++/port.h"
-#include "midi++/manager.h"
+#include "ardour/audioengine.h"
#include "ardour/filesystem_paths.h"
#include "ardour/session.h"
#include "ardour/route.h"
#include "ardour/midi_ui.h"
#include "ardour/rc_configuration.h"
+#include "ardour/midiport_manager.h"
#include "generic_midi_control_protocol.h"
#include "midicontrollable.h"
@@ -59,8 +60,8 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
, _threshold (10)
, gui (0)
{
- _input_port = MIDI::Manager::instance()->midi_input_port ();
- _output_port = MIDI::Manager::instance()->midi_output_port ();
+ _input_port = AudioEngine::instance()->midi_input_port ();
+ _output_port = AudioEngine::instance()->midi_output_port ();
do_feedback = false;
_feedback_interval = 10000; // microseconds
@@ -338,7 +339,7 @@ GenericMidiControlProtocol::start_learning (Controllable* c)
}
if (!mc) {
- mc = new MIDIControllable (this, *_input_port, *c, false);
+ mc = new MIDIControllable (this, *_input_port->parser(), *c, false);
}
{
@@ -435,7 +436,7 @@ GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos,
MIDI::byte value = control_number;
// Create a MIDIControllable
- MIDIControllable* mc = new MIDIControllable (this, *_input_port, *control, false);
+ MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), *control, false);
// Remove any old binding for this midi channel/type/value pair
// Note: can't use delete_binding() here because we don't know the specific controllable we want to remove, only the midi information
@@ -559,7 +560,7 @@ GenericMidiControlProtocol::set_state (const XMLNode& node, int version)
Controllable* c = Controllable::by_id (id);
if (c) {
- MIDIControllable* mc = new MIDIControllable (this, *_input_port, *c, false);
+ MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), *c, false);
if (mc->set_state (**niter, version) == 0) {
controllables.push_back (mc);
@@ -754,7 +755,7 @@ GenericMidiControlProtocol::create_binding (const XMLNode& node)
prop = node.property (X_("uri"));
uri = prop->value();
- MIDIControllable* mc = new MIDIControllable (this, *_input_port, momentary);
+ MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), momentary);
if (mc->init (uri)) {
delete mc;
@@ -892,7 +893,7 @@ GenericMidiControlProtocol::create_function (const XMLNode& node)
prop = node.property (X_("function"));
- MIDIFunction* mf = new MIDIFunction (*_input_port);
+ MIDIFunction* mf = new MIDIFunction (*_input_port->parser());
if (mf->setup (*this, prop->value(), argument, data, data_size)) {
delete mf;
@@ -988,7 +989,7 @@ GenericMidiControlProtocol::create_action (const XMLNode& node)
prop = node.property (X_("action"));
- MIDIAction* ma = new MIDIAction (*_input_port);
+ MIDIAction* ma = new MIDIAction (*_input_port->parser());
if (ma->init (*this, prop->value(), data, data_size)) {
delete ma;
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.h b/libs/surfaces/generic_midi/generic_midi_control_protocol.h
index a7c420cc41..a4a51b7f99 100644
--- a/libs/surfaces/generic_midi/generic_midi_control_protocol.h
+++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.h
@@ -22,14 +22,11 @@
#include <list>
#include <glibmm/threads.h>
+
#include "ardour/types.h"
#include "control_protocol/control_protocol.h"
-namespace MIDI {
- class Port;
-}
-
namespace PBD {
class Controllable;
class ControllableDescriptor;
@@ -37,6 +34,11 @@ namespace PBD {
namespace ARDOUR {
class Session;
+ class MidiPort;
+}
+
+namespace MIDI {
+ class Port;
}
class MIDIControllable;
@@ -51,8 +53,8 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
int set_active (bool yn);
static bool probe() { return true; }
- MIDI::Port* input_port () const { return _input_port; }
- MIDI::Port* output_port () const { return _output_port; }
+ MIDI::Port* input_port () const { return _input_port; }
+ MIDI::Port* output_port () const { return _output_port; }
void set_feedback_interval (ARDOUR::microseconds_t);
int set_feedback (bool yn);
@@ -97,8 +99,8 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
}
private:
- MIDI::Port* _input_port;
- MIDI::Port* _output_port;
+ MIDI::Port* _input_port;
+ MIDI::Port* _output_port;
ARDOUR::microseconds_t _feedback_interval;
ARDOUR::microseconds_t last_feedback_time;
diff --git a/libs/surfaces/generic_midi/midiaction.cc b/libs/surfaces/generic_midi/midiaction.cc
index e1eed1a49e..e537122e9c 100644
--- a/libs/surfaces/generic_midi/midiaction.cc
+++ b/libs/surfaces/generic_midi/midiaction.cc
@@ -25,7 +25,7 @@
using namespace MIDI;
-MIDIAction::MIDIAction (MIDI::Port& p)
+MIDIAction::MIDIAction (MIDI::Parser& p)
: MIDIInvokable (p)
{
}
diff --git a/libs/surfaces/generic_midi/midiaction.h b/libs/surfaces/generic_midi/midiaction.h
index 521f59f26d..e2a29143ad 100644
--- a/libs/surfaces/generic_midi/midiaction.h
+++ b/libs/surfaces/generic_midi/midiaction.h
@@ -36,8 +36,6 @@ namespace Gtk {
}
namespace MIDI {
- class Channel;
- class Port;
class Parser;
}
@@ -46,7 +44,7 @@ class GenericMidiControlProtocol;
class MIDIAction : public MIDIInvokable
{
public:
- MIDIAction (MIDI::Port&);
+ MIDIAction (MIDI::Parser&);
virtual ~MIDIAction ();
int init (GenericMidiControlProtocol&, const std::string& action_name, MIDI::byte* sysex = 0, size_t ssize = 0);
diff --git a/libs/surfaces/generic_midi/midicontrollable.cc b/libs/surfaces/generic_midi/midicontrollable.cc
index d36ccefd44..d78dd5e644 100644
--- a/libs/surfaces/generic_midi/midicontrollable.cc
+++ b/libs/surfaces/generic_midi/midicontrollable.cc
@@ -27,9 +27,9 @@
#include "pbd/xml++.h"
#include "pbd/stacktrace.h"
-#include "midi++/port.h"
#include "midi++/channel.h"
+#include "ardour/async_midi_port.h"
#include "ardour/automation_control.h"
#include "ardour/midi_ui.h"
#include "ardour/utils.h"
@@ -42,11 +42,11 @@ using namespace MIDI;
using namespace PBD;
using namespace ARDOUR;
-MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, Port& p, bool m)
+MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, MIDI::Parser& p, bool m)
: _surface (s)
, controllable (0)
, _descriptor (0)
- , _port (p)
+ , _parser (p)
, _momentary (m)
{
_learned = false; /* from URI */
@@ -59,10 +59,10 @@ MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, Port& p, bool
feedback = true; // for now
}
-MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, Port& p, Controllable& c, bool m)
+MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, MIDI::Parser& p, Controllable& c, bool m)
: _surface (s)
, _descriptor (0)
- , _port (p)
+ , _parser (p)
, _momentary (m)
{
set_controllable (&c);
@@ -149,7 +149,7 @@ void
MIDIControllable::learn_about_external_control ()
{
drop_external_control ();
- _port.parser()->any.connect_same_thread (midi_learn_connection, boost::bind (&MIDIControllable::midi_receiver, this, _1, _2, _3));
+ _parser.any.connect_same_thread (midi_learn_connection, boost::bind (&MIDIControllable::midi_receiver, this, _1, _2, _3));
}
void
@@ -357,12 +357,6 @@ MIDIControllable::midi_receiver (Parser &, byte *msg, size_t /*len*/)
return;
}
- /* if the our port doesn't do input anymore, forget it ... */
-
- if (!_port.parser()) {
- return;
- }
-
bind_midi ((channel_t) (msg[0] & 0xf), eventType (msg[0] & 0xF0), msg[1]);
if (controllable) {
@@ -381,49 +375,43 @@ MIDIControllable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
control_channel = chn;
control_additional = additional;
- if (_port.parser() == 0) {
- return;
- }
-
- Parser& p = *_port.parser();
-
int chn_i = chn;
switch (ev) {
case MIDI::off:
- p.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2));
+ _parser.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2));
/* if this is a togglee, connect to noteOn as well,
and we'll toggle back and forth between the two.
*/
if (_momentary) {
- p.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2));
+ _parser.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2));
}
_control_description = "MIDI control: NoteOff";
break;
case MIDI::on:
- p.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2));
+ _parser.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2));
if (_momentary) {
- p.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2));
+ _parser.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2));
}
_control_description = "MIDI control: NoteOn";
break;
case MIDI::controller:
- p.channel_controller[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_controller, this, _1, _2));
+ _parser.channel_controller[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_controller, this, _1, _2));
snprintf (buf, sizeof (buf), "MIDI control: Controller %d", control_additional);
_control_description = buf;
break;
case MIDI::program:
- p.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_program_change, this, _1, _2));
+ _parser.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_program_change, this, _1, _2));
_control_description = "MIDI control: ProgramChange";
break;
case MIDI::pitchbend:
- p.channel_pitchbend[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_pitchbend, this, _1, _2));
+ _parser.channel_pitchbend[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_pitchbend, this, _1, _2));
_control_description = "MIDI control: Pitchbend";
break;
diff --git a/libs/surfaces/generic_midi/midicontrollable.h b/libs/surfaces/generic_midi/midicontrollable.h
index dd9dc988b4..aeed05db4a 100644
--- a/libs/surfaces/generic_midi/midicontrollable.h
+++ b/libs/surfaces/generic_midi/midicontrollable.h
@@ -36,17 +36,20 @@ namespace PBD {
namespace MIDI {
class Channel;
- class Port;
class Parser;
}
class GenericMidiControlProtocol;
+namespace ARDOUR {
+ class AsyncMIDIPort;
+}
+
class MIDIControllable : public PBD::Stateful
{
public:
- MIDIControllable (GenericMidiControlProtocol *, MIDI::Port&, PBD::Controllable&, bool momentary);
- MIDIControllable (GenericMidiControlProtocol *, MIDI::Port&, bool momentary = false);
+ MIDIControllable (GenericMidiControlProtocol *, MIDI::Parser&, PBD::Controllable&, bool momentary);
+ MIDIControllable (GenericMidiControlProtocol *, MIDI::Parser&, bool momentary = false);
virtual ~MIDIControllable ();
int init (const std::string&);
@@ -72,7 +75,7 @@ class MIDIControllable : public PBD::Stateful
bool learned() const { return _learned; }
- MIDI::Port& get_port() const { return _port; }
+ MIDI::Parser& get_parser() { return _parser; }
PBD::Controllable* get_controllable() const { return controllable; }
void set_controllable (PBD::Controllable*);
const std::string& current_uri() const { return _current_uri; }
@@ -98,8 +101,8 @@ class MIDIControllable : public PBD::Stateful
GenericMidiControlProtocol* _surface;
PBD::Controllable* controllable;
PBD::ControllableDescriptor* _descriptor;
- std::string _current_uri;
- MIDI::Port& _port;
+ std::string _current_uri;
+ MIDI::Parser& _parser;
bool setting;
int last_value;
float last_controllable_value;
diff --git a/libs/surfaces/generic_midi/midifunction.cc b/libs/surfaces/generic_midi/midifunction.cc
index 70e9337861..b0dc95e4fc 100644
--- a/libs/surfaces/generic_midi/midifunction.cc
+++ b/libs/surfaces/generic_midi/midifunction.cc
@@ -25,7 +25,7 @@
using namespace MIDI;
-MIDIFunction::MIDIFunction (MIDI::Port& p)
+MIDIFunction::MIDIFunction (MIDI::Parser& p)
: MIDIInvokable (p)
{
}
diff --git a/libs/surfaces/generic_midi/midifunction.h b/libs/surfaces/generic_midi/midifunction.h
index 8f0b0218d0..88aff0ab0a 100644
--- a/libs/surfaces/generic_midi/midifunction.h
+++ b/libs/surfaces/generic_midi/midifunction.h
@@ -33,7 +33,6 @@
namespace MIDI {
class Channel;
- class Port;
class Parser;
}
@@ -64,7 +63,7 @@ class MIDIFunction : public MIDIInvokable
TrackSetSoloIsolate,
};
- MIDIFunction (MIDI::Port&);
+ MIDIFunction (MIDI::Parser&);
virtual ~MIDIFunction ();
int setup (GenericMidiControlProtocol&, const std::string& function_name, const std::string& argument, MIDI::byte* sysex = 0, size_t ssize = 0);
diff --git a/libs/surfaces/generic_midi/midiinvokable.cc b/libs/surfaces/generic_midi/midiinvokable.cc
index 79835835a4..42c74553d8 100644
--- a/libs/surfaces/generic_midi/midiinvokable.cc
+++ b/libs/surfaces/generic_midi/midiinvokable.cc
@@ -25,8 +25,8 @@
using namespace MIDI;
-MIDIInvokable::MIDIInvokable (MIDI::Port& p)
- : _port (p)
+MIDIInvokable::MIDIInvokable (MIDI::Parser& p)
+ : _parser (p)
{
data_size = 0;
data = 0;
@@ -127,12 +127,6 @@ MIDIInvokable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
control_channel = chn;
control_additional = additional;
- if (_port.parser() == 0) {
- return;
- }
-
- Parser& p = *_port.parser();
-
int chn_i = chn;
/* incoming MIDI is parsed by Ardour' MidiUI event loop/thread, and we want our handlers to execute in that context, so we use
@@ -141,27 +135,27 @@ MIDIInvokable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
switch (ev) {
case MIDI::off:
- p.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_note_off, this, _1, _2));
+ _parser.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_note_off, this, _1, _2));
break;
case MIDI::on:
- p.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_note_on, this, _1, _2));
+ _parser.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_note_on, this, _1, _2));
break;
case MIDI::controller:
- p.channel_controller[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_controller, this, _1, _2));
+ _parser.channel_controller[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_controller, this, _1, _2));
break;
case MIDI::program:
- p.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_program_change, this, _1, _2));
+ _parser.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_program_change, this, _1, _2));
break;
case MIDI::sysex:
- p.sysex.connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_sysex, this, _1, _2, _3));
+ _parser.sysex.connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_sysex, this, _1, _2, _3));
break;
case MIDI::any:
- p.any.connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_any, this, _1, _2, _3));
+ _parser.any.connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_any, this, _1, _2, _3));
break;
default:
diff --git a/libs/surfaces/generic_midi/midiinvokable.h b/libs/surfaces/generic_midi/midiinvokable.h
index 62cbab238c..f374a126a5 100644
--- a/libs/surfaces/generic_midi/midiinvokable.h
+++ b/libs/surfaces/generic_midi/midiinvokable.h
@@ -31,7 +31,6 @@
namespace MIDI {
class Channel;
- class Port;
class Parser;
}
@@ -40,12 +39,12 @@ class GenericMidiControlProtocol;
class MIDIInvokable : public PBD::Stateful
{
public:
- MIDIInvokable (MIDI::Port&);
+ MIDIInvokable (MIDI::Parser&);
virtual ~MIDIInvokable ();
virtual int init (GenericMidiControlProtocol&, const std::string&, MIDI::byte* data = 0, size_t dsize = 0);
- MIDI::Port& get_port() const { return _port; }
+ MIDI::Parser& get_parser() { return _parser; }
void bind_midi (MIDI::channel_t, MIDI::eventType, MIDI::byte);
MIDI::channel_t get_control_channel () { return control_channel; }
@@ -55,7 +54,7 @@ class MIDIInvokable : public PBD::Stateful
protected:
GenericMidiControlProtocol* _ui;
std::string _invokable_name;
- MIDI::Port& _port;
+ MIDI::Parser& _parser;
PBD::ScopedConnection midi_sense_connection[2];
MIDI::eventType control_type;
MIDI::byte control_additional;
diff --git a/libs/surfaces/mackie/surface.cc b/libs/surfaces/mackie/surface.cc
index 0c45a29378..23cef9d13c 100644
--- a/libs/surfaces/mackie/surface.cc
+++ b/libs/surfaces/mackie/surface.cc
@@ -24,7 +24,6 @@
#include <cmath>
#include "midi++/port.h"
-#include "midi++/manager.h"
#include "ardour/automation_control.h"
#include "ardour/debug.h"
diff --git a/libs/surfaces/mackie/surface_port.cc b/libs/surfaces/mackie/surface_port.cc
index 44db30ab1b..fd9feaff74 100644
--- a/libs/surfaces/mackie/surface_port.cc
+++ b/libs/surfaces/mackie/surface_port.cc
@@ -24,27 +24,27 @@
#include <boost/shared_array.hpp>
#include "midi++/types.h"
-#include "midi++/port.h"
-#include "midi++/jack_midi_port.h"
#include "midi++/ipmidi_port.h"
-#include "midi++/manager.h"
+#include "ardour/async_midi_port.h"
#include "ardour/debug.h"
#include "ardour/rc_configuration.h"
#include "ardour/session.h"
#include "ardour/audioengine.h"
+#include "ardour/async_midi_port.h"
+#include "ardour/midiport_manager.h"
#include "controls.h"
#include "mackie_control_protocol.h"
#include "surface.h"
#include "surface_port.h"
-
#include "i18n.h"
using namespace std;
using namespace Mackie;
using namespace PBD;
+using namespace ARDOUR;
/** @param input_port Input MIDI::Port; this object takes responsibility for
* adding & removing it from the MIDI::Manager and destroying it. @param
@@ -52,31 +52,16 @@ using namespace PBD;
*/
SurfacePort::SurfacePort (Surface& s)
: _surface (&s)
- , _input_port (0)
- , _output_port (0)
{
if (_surface->mcp().device_info().uses_ipmidi()) {
_input_port = new MIDI::IPMIDIPort (_surface->mcp().ipmidi_base() +_surface->number());
_output_port = _input_port;
} else {
- ARDOUR::PortEngine& port_engine (ARDOUR::AudioEngine::instance()->port_engine());
-
- _input_port = new MIDI::JackMIDIPort (string_compose (_("%1 in"), _surface->name()), MIDI::Port::IsInput, port_engine);
- _output_port =new MIDI::JackMIDIPort (string_compose (_("%1 out"), _surface->name()), MIDI::Port::IsOutput, port_engine);
-
- /* MackieControl has its own thread for handling input from the input
- * port, and we don't want anything handling output from the output
- * port. This stops the Generic MIDI UI event loop in ardour from
- * attempting to handle these ports.
- */
-
- _input_port->set_centrally_parsed (false);
- _output_port->set_centrally_parsed (false);
-
- MIDI::Manager * mm = MIDI::Manager::instance();
-
- mm->add_port (_input_port);
- mm->add_port (_output_port);
+ _async_in = AudioEngine::instance()->register_input_port (DataType::MIDI, string_compose (_("%1 in"), _surface->name()), true);
+ _async_out = AudioEngine::instance()->register_output_port (DataType::MIDI, string_compose (_("%1 out"), _surface->name()), true);
+
+ _input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in).get();
+ _output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_out).get();
}
}
@@ -86,17 +71,15 @@ SurfacePort::~SurfacePort()
delete _input_port;
} else {
- MIDI::Manager* mm = MIDI::Manager::instance ();
-
- if (_input_port) {
- mm->remove_port (_input_port);
- delete _input_port;
+ if (_async_in) {
+ AudioEngine::instance()->unregister_port (_async_in);
+ _async_in.reset ();
}
- if (_output_port) {
+ if (_async_out) {
_output_port->drain (10000);
- mm->remove_port (_output_port);
- delete _output_port;
+ AudioEngine::instance()->unregister_port (_async_out);
+ _async_out.reset ();
}
}
}
diff --git a/libs/surfaces/mackie/surface_port.h b/libs/surfaces/mackie/surface_port.h
index 7dc20a06f2..751ee848d7 100644
--- a/libs/surfaces/mackie/surface_port.h
+++ b/libs/surfaces/mackie/surface_port.h
@@ -21,16 +21,23 @@
#include <midi++/types.h>
#include "pbd/signals.h"
+
+
#include "midi_byte_array.h"
#include "types.h"
namespace MIDI {
- class Port;
class Parser;
+ class Port;
}
class MackieControlProtocol;
+namespace ARDOUR {
+ class AsyncMIDIPort;
+ class Port;
+}
+
namespace Mackie
{
@@ -49,17 +56,17 @@ public:
/// an easier way to output bytes via midi
int write (const MidiByteArray&);
- MIDI::Port& input_port() { return *_input_port; }
- const MIDI::Port& input_port() const { return *_input_port; }
- MIDI::Port& output_port() { return *_output_port; }
- const MIDI::Port& output_port() const { return *_output_port; }
+ MIDI::Port& input_port() const { return *_input_port; }
+ MIDI::Port& output_port() const { return *_output_port; }
protected:
private:
- Mackie::Surface* _surface;
- MIDI::Port* _input_port;
- MIDI::Port* _output_port;
+ Mackie::Surface* _surface;
+ MIDI::Port* _input_port;
+ MIDI::Port* _output_port;
+ boost::shared_ptr<ARDOUR::Port> _async_in;
+ boost::shared_ptr<ARDOUR::Port> _async_out;
};
std::ostream& operator << (std::ostream& , const SurfacePort& port);