major redesign of MIDI port heirarchy and management (part 2)

This commit is contained in:
Paul Davis 2013-08-07 22:22:11 -04:00
parent 83a0c30c24
commit 1ab61b8564
62 changed files with 741 additions and 562 deletions

View file

@ -58,8 +58,6 @@
#include "gtkmm2ext/popup.h" #include "gtkmm2ext/popup.h"
#include "gtkmm2ext/window_title.h" #include "gtkmm2ext/window_title.h"
#include "midi++/manager.h"
#include "ardour/ardour.h" #include "ardour/ardour.h"
#include "ardour/audio_backend.h" #include "ardour/audio_backend.h"
#include "ardour/audioengine.h" #include "ardour/audioengine.h"
@ -1050,14 +1048,20 @@ ARDOUR_UI::update_sample_rate (framecnt_t)
framecnt_t rate = engine->sample_rate(); framecnt_t rate = engine->sample_rate();
if (fmod (rate, 1000.0) != 0.0) { if (rate == 0) {
snprintf (buf, sizeof (buf), _("JACK: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"), /* no sample rate available */
(float) rate / 1000.0f, snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"red\">disconnected</span>"));
(engine->usecs_per_cycle() / 1000.0f));
} else { } else {
snprintf (buf, sizeof (buf), _("JACK: <span foreground=\"green\">%" PRId64 " kHz / %4.1f ms</span>"),
rate/1000, if (fmod (rate, 1000.0) != 0.0) {
(engine->usecs_per_cycle() * 1000.0f)); 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]; char buf[64];
framecnt_t fr = _session->frame_rate(); framecnt_t fr = _session->frame_rate();
if (fr == 0) {
/* skip update - no SR available */
return;
}
if (!opt_frames) { if (!opt_frames) {
/* Available space is unknown */ /* Available space is unknown */
snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">Unknown</span>")); snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">Unknown</span>"));
@ -1663,9 +1672,16 @@ ARDOUR_UI::transport_goto_wallclock ()
time (&now); time (&now);
localtime_r (&now, &tmnow); localtime_r (&now, &tmnow);
frames = tmnow.tm_hour * (60 * 60 * _session->frame_rate()); int frame_rate = _session->frame_rate();
frames += tmnow.tm_min * (60 * _session->frame_rate());
frames += tmnow.tm_sec * _session->frame_rate(); if (frame_rate == 0) {
/* no frame rate available */
return;
}
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 ()); _session->request_locate (frames, _session->transport_rolling ());
@ -3802,7 +3818,7 @@ void
ARDOUR_UI::disconnect_from_jack () ARDOUR_UI::disconnect_from_jack ()
{ {
if (engine) { if (engine) {
if (engine->pause ()) { if (engine->stop ()) {
MessageDialog msg (*editor, _("Could not disconnect from JACK")); MessageDialog msg (*editor, _("Could not disconnect from JACK"));
msg.run (); msg.run ();
} }

View file

@ -1258,7 +1258,8 @@ Editor::set_session (Session *t)
/* These signals can all be emitted by a non-GUI thread. Therefore the /* 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, 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()); _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());

View file

@ -2372,8 +2372,9 @@ CursorDrag::fake_locate (framepos_t t)
if (s->timecode_transmission_suspended ()) { if (s->timecode_transmission_suspended ()) {
framepos_t const f = _editor->playhead_cursor->current_frame; framepos_t const f = _editor->playhead_cursor->current_frame;
s->send_mmc_locate (f); s->send_mmc_locate (f);
s->send_full_time_code (f); // XXX need to queue full time code and SPP messages somehow
s->send_song_position_pointer (f); // s->send_full_time_code (f);
// s->send_song_position_pointer (f);
} }
show_verbose_cursor_time (t); show_verbose_cursor_time (t);

View file

@ -32,7 +32,6 @@
#include <gtkmm2ext/fastmeter.h> #include <gtkmm2ext/fastmeter.h>
#include <gtkmm2ext/barcontroller.h> #include <gtkmm2ext/barcontroller.h>
#include <gtkmm2ext/gtk_ui.h> #include <gtkmm2ext/gtk_ui.h>
#include "midi++/manager.h"
#include "pbd/fastlog.h" #include "pbd/fastlog.h"
#include "pbd/stacktrace.h" #include "pbd/stacktrace.h"

View file

@ -37,8 +37,6 @@
#include <gtkmm2ext/doi.h> #include <gtkmm2ext/doi.h>
#include <gtkmm2ext/slider_controller.h> #include <gtkmm2ext/slider_controller.h>
#include "midi++/manager.h"
#include "ardour/plugin.h" #include "ardour/plugin.h"
#include "ardour/plugin_insert.h" #include "ardour/plugin_insert.h"
#include "ardour/session.h" #include "ardour/session.h"

View file

@ -23,7 +23,6 @@
#include <gtkmm2ext/utils.h> #include <gtkmm2ext/utils.h>
#include <gtkmm2ext/barcontroller.h> #include <gtkmm2ext/barcontroller.h>
#include "midi++/manager.h"
#include "pbd/fastlog.h" #include "pbd/fastlog.h"
#include "ardour_ui.h" #include "ardour_ui.h"

View file

@ -24,7 +24,10 @@
#include <time.h> #include <time.h>
#include "midi++/parser.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 "midi_tracer.h"
#include "gui_thread.h" #include "gui_thread.h"
@ -53,7 +56,8 @@ MidiTracer::MidiTracer ()
, collect_button (_("Enabled")) , collect_button (_("Enabled"))
, delta_time_button (_("Delta times")) , 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_sec = 0;
_last_receipt.tv_usec = 0; _last_receipt.tv_usec = 0;
@ -127,24 +131,49 @@ MidiTracer::ports_changed ()
string const c = _port_combo.get_active_text (); string const c = _port_combo.get_active_text ();
_port_combo.clear (); _port_combo.clear ();
boost::shared_ptr<const Manager::PortList> p = Manager::instance()->get_midi_ports (); ARDOUR::PortManager::PortList pl;
for (Manager::PortList::const_iterator i = p->begin(); i != p->end(); ++i) { ARDOUR::AudioEngine::instance()->get_ports (ARDOUR::DataType::MIDI, pl);
if (pl.empty()) {
_port_combo.set_active_text ("");
return;
}
for (ARDOUR::PortManager::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
_port_combo.append_text ((*i)->name()); _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 void
MidiTracer::port_changed () MidiTracer::port_changed ()
{ {
using namespace ARDOUR;
disconnect (); 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) { if (!p) {
p->parser()->any.connect_same_thread (_parser_connection, boost::bind (&MidiTracer::tracer, this, _1, _2, _3)); std::cerr << "port not found\n";
return;
} }
boost::shared_ptr<AsyncMIDIPort> async = boost::dynamic_pointer_cast<AsyncMIDIPort> (p);
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 void

View file

@ -21,7 +21,6 @@
#include <gtkmm2ext/utils.h> #include <gtkmm2ext/utils.h>
#include <gtkmm2ext/barcontroller.h> #include <gtkmm2ext/barcontroller.h>
#include "midi++/manager.h"
#include "pbd/fastlog.h" #include "pbd/fastlog.h"
#include "ardour/pannable.h" #include "ardour/pannable.h"

View file

@ -40,8 +40,6 @@
#include <gtkmm2ext/slider_controller.h> #include <gtkmm2ext/slider_controller.h>
#include <gtkmm2ext/application.h> #include <gtkmm2ext/application.h>
#include "midi++/manager.h"
#include "ardour/session.h" #include "ardour/session.h"
#include "ardour/plugin.h" #include "ardour/plugin.h"
#include "ardour/plugin_insert.h" #include "ardour/plugin_insert.h"

View file

@ -21,7 +21,6 @@
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include "midi++/manager.h"
#include "midi++/mmc.h" #include "midi++/mmc.h"
#include "ardour/audioengine.h" #include "ardour/audioengine.h"
@ -29,9 +28,13 @@
#include "ardour/bundle.h" #include "ardour/bundle.h"
#include "ardour/control_protocol_manager.h" #include "ardour/control_protocol_manager.h"
#include "ardour/io_processor.h" #include "ardour/io_processor.h"
#include "ardour/midi_port.h"
#include "ardour/midiport_manager.h"
#include "ardour/session.h" #include "ardour/session.h"
#include "ardour/user_bundle.h" #include "ardour/user_bundle.h"
#include "ardour/port.h" #include "ardour/port.h"
#include "ardour/syncport_manager.h"
#include "control_protocol/control_protocol.h" #include "control_protocol/control_protocol.h"
#include "gui_thread.h" #include "gui_thread.h"
@ -452,37 +455,36 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
/* Ardour's sync ports */ /* Ardour's sync ports */
MIDI::Manager* midi_manager = MIDI::Manager::instance (); if ((type == DataType::MIDI || type == DataType::NIL)) {
if (midi_manager && (type == DataType::MIDI || type == DataType::NIL)) {
boost::shared_ptr<Bundle> sync (new Bundle (_("Sync"), inputs)); boost::shared_ptr<Bundle> sync (new Bundle (_("Sync"), inputs));
MIDI::MachineControl* mmc = midi_manager->mmc (); AudioEngine* ae = AudioEngine::instance();
AudioEngine& ae = session->engine (); MIDI::MachineControl& mmc (ae->mmc());
if (inputs) { if (inputs) {
sync->add_channel ( 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 ( 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 ( 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 ( 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 { } else {
sync->add_channel ( 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 ( 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 ( 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 ( 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())
); );
} }

View file

@ -31,8 +31,6 @@
#include "pbd/fpu.h" #include "pbd/fpu.h"
#include "pbd/cpus.h" #include "pbd/cpus.h"
#include "midi++/manager.h"
#include "ardour/audioengine.h" #include "ardour/audioengine.h"
#include "ardour/dB.h" #include "ardour/dB.h"
#include "ardour/rc_configuration.h" #include "ardour/rc_configuration.h"

View file

@ -49,9 +49,7 @@ class AudioPort : public Port
friend class PortManager; friend class PortManager;
AudioPort (std::string const &, PortFlags); AudioPort (std::string const &, PortFlags);
protected: /* special access for PortManager only (hah, C++) */
friend class AudioEngine;
/* special access for engine only (hah, C++) */
Sample* engine_get_whole_audio_buffer (); Sample* engine_get_whole_audio_buffer ();
private: private:

View file

@ -36,13 +36,9 @@
#include "pbd/signals.h" #include "pbd/signals.h"
#include "pbd/stacktrace.h" #include "pbd/stacktrace.h"
#include <jack/weakjack.h> #include "midi++/mmc.h"
#include <jack/jack.h>
#include <jack/transport.h>
#include <jack/thread.h>
#include "ardour/ardour.h" #include "ardour/ardour.h"
#include "ardour/data_type.h" #include "ardour/data_type.h"
#include "ardour/session_handle.h" #include "ardour/session_handle.h"
#include "ardour/types.h" #include "ardour/types.h"
@ -192,6 +188,8 @@ public:
/* sets up the process callback thread */ /* sets up the process callback thread */
static void thread_init_callback (void *); static void thread_init_callback (void *);
MIDI::MachineControl& mmc() { return _mmc; }
private: private:
AudioEngine (); AudioEngine ();
@ -206,16 +204,17 @@ public:
gain_t session_removal_gain; gain_t session_removal_gain;
gain_t session_removal_gain_step; gain_t session_removal_gain_step;
bool _running; bool _running;
bool _freewheeling;
/// number of frames between each check for changes in monitor input /// number of frames between each check for changes in monitor input
framecnt_t monitor_check_interval; framecnt_t monitor_check_interval;
/// time of the last monitor check in frames /// time of the last monitor check in frames
framecnt_t last_monitor_check; framecnt_t last_monitor_check;
/// the number of frames processed since start() was called /// the number of frames processed since start() was called
framecnt_t _processed_frames; framecnt_t _processed_frames;
bool _freewheeling;
bool _pre_freewheel_mmc_enabled; bool _pre_freewheel_mmc_enabled;
Glib::Threads::Thread* m_meter_thread; Glib::Threads::Thread* m_meter_thread;
ProcessThread* _main_thread; ProcessThread* _main_thread;
MIDI::MachineControl _mmc;
void meter_thread (); void meter_thread ();
void start_metering_thread (); void start_metering_thread ();

View file

@ -63,6 +63,7 @@ namespace PBD {
extern uint64_t OrderKeys; extern uint64_t OrderKeys;
extern uint64_t Automation; extern uint64_t Automation;
extern uint64_t WiimoteControl; extern uint64_t WiimoteControl;
extern uint64_t Ports;
} }
} }

View file

@ -178,6 +178,8 @@ class JACKAudioBackend : public AudioBackend {
typedef std::map<std::string,DeviceList> DriverDeviceMap; typedef std::map<std::string,DeviceList> DriverDeviceMap;
mutable DriverDeviceMap all_devices; mutable DriverDeviceMap all_devices;
PBD::ScopedConnection disconnect_connection;
}; };
} // namespace } // namespace

View file

@ -26,13 +26,11 @@
#include "pbd/signals.h" #include "pbd/signals.h"
#include "pbd/stacktrace.h" #include "pbd/stacktrace.h"
namespace MIDI {
class Port;
}
namespace ARDOUR { namespace ARDOUR {
class Session; class Session;
class AsyncMIDIPort;
/* this is mostly a placeholder because I suspect that at some /* this is mostly a placeholder because I suspect that at some
point we will want to add more members to accomodate point we will want to add more members to accomodate
@ -67,7 +65,7 @@ class MidiControlUI : public AbstractUI<MidiUIRequest>
ARDOUR::Session& _session; ARDOUR::Session& _session;
PBD::ScopedConnection rebind_connection; PBD::ScopedConnection rebind_connection;
bool midi_input_handler (Glib::IOCondition, MIDI::Port*); bool midi_input_handler (Glib::IOCondition, AsyncMIDIPort*);
void reset_ports (); void reset_ports ();
void clear_ports (); void clear_ports ();

View file

@ -56,8 +56,10 @@ class MidiPortManager {
* callback. * callback.
*/ */
MIDI::Port* midi_input_port () { return _midi_input_port; } MIDI::Port* midi_input_port () const { return _midi_input_port; }
MIDI::Port* midi_output_port () { return _midi_output_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 /* Ports used for synchronization. These have their I/O handled inside the
* process callback. * process callback.
@ -76,8 +78,12 @@ class MidiPortManager {
/* asynchronously handled ports: MIDI::Port */ /* asynchronously handled ports: MIDI::Port */
MIDI::Port* _midi_input_port; MIDI::Port* _midi_input_port;
MIDI::Port* _midi_output_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_in;
boost::shared_ptr<Port> _midi_out; boost::shared_ptr<Port> _midi_out;
boost::shared_ptr<Port> _mmc_in;
boost::shared_ptr<Port> _mmc_out;
/* synchronously handled ports: ARDOUR::MidiPort */ /* synchronously handled ports: ARDOUR::MidiPort */
boost::shared_ptr<MidiPort> _mtc_input_port; boost::shared_ptr<MidiPort> _mtc_input_port;

View file

@ -32,15 +32,17 @@
#include "pbd/rcu.h" #include "pbd/rcu.h"
#include "ardour/chan_count.h" #include "ardour/chan_count.h"
#include "ardour/midiport_manager.h"
#include "ardour/port.h" #include "ardour/port.h"
#include "ardour/port_engine.h" #include "ardour/port_engine.h"
namespace ARDOUR { namespace ARDOUR {
class PortManager class PortManager : public MidiPortManager
{ {
public: public:
typedef std::map<std::string,boost::shared_ptr<Port> > Ports; typedef std::map<std::string,boost::shared_ptr<Port> > Ports;
typedef std::list<boost::shared_ptr<Port> > PortList;
PortManager (); PortManager ();
virtual ~PortManager() {} virtual ~PortManager() {}
@ -53,8 +55,8 @@ class PortManager
/* Port registration */ /* Port registration */
boost::shared_ptr<Port> register_input_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); boost::shared_ptr<Port> register_output_port (DataType, const std::string& portname, bool async = false);
int unregister_port (boost::shared_ptr<Port>); int unregister_port (boost::shared_ptr<Port>);
/* Port connectivity */ /* Port connectivity */
@ -87,6 +89,7 @@ class PortManager
ChanCount n_physical_inputs () const; 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 (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>&);
int get_ports (DataType, PortList&);
void remove_all_ports (); void remove_all_ports ();
@ -135,10 +138,32 @@ class PortManager
SerializedRCUManager<Ports> ports; SerializedRCUManager<Ports> ports;
bool _port_remove_in_progress; 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); 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 } // namespace
#endif /* __libardour_port_manager_h__ */ #endif /* __libardour_port_manager_h__ */

View file

@ -813,7 +813,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
boost::shared_ptr<SessionPlaylists> playlists; boost::shared_ptr<SessionPlaylists> playlists;
void send_mmc_locate (framepos_t); 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); void send_song_position_pointer (framepos_t);
bool step_editing() const { return (_step_editors > 0); } bool step_editing() const { return (_step_editors > 0); }

View file

@ -40,15 +40,12 @@
#define PLUSMINUS(A) ( ((A)<0) ? "-" : (((A)>0) ? "+" : "\u00B1") ) #define PLUSMINUS(A) ( ((A)<0) ? "-" : (((A)>0) ? "+" : "\u00B1") )
#define LEADINGZERO(A) ( (A)<10 ? " " : (A)<100 ? " " : (A)<1000 ? " " : "" ) #define LEADINGZERO(A) ( (A)<10 ? " " : (A)<100 ? " " : (A)<1000 ? " " : "" )
namespace MIDI {
class Port;
}
namespace ARDOUR { namespace ARDOUR {
class TempoMap; class TempoMap;
class Session; class Session;
class AudioEngine; class AudioEngine;
class MidiPort;
/** /**
* @class Slave * @class Slave
@ -67,6 +64,15 @@ class Slave {
Slave() { } Slave() { }
virtual ~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: * This is the most important function to implement:
* Each process cycle, Session::follow_slave will call this method. * Each process cycle, Session::follow_slave will call this method.
@ -253,10 +259,11 @@ class TimecodeSlave : public Slave {
class MTC_Slave : public TimecodeSlave { class MTC_Slave : public TimecodeSlave {
public: public:
MTC_Slave (Session&, MIDI::Port&); MTC_Slave (Session&, MidiPort&);
~MTC_Slave (); ~MTC_Slave ();
void rebind (MIDI::Port&); void rebind (MidiPort&);
int process (pframes_t);
bool speed_and_position (double&, framepos_t&); bool speed_and_position (double&, framepos_t&);
bool locked() const; bool locked() const;
@ -274,7 +281,8 @@ class MTC_Slave : public TimecodeSlave {
private: private:
Session& session; Session& session;
MIDI::Port* port; MidiPort* port;
MIDI::Parser parser;
PBD::ScopedConnectionList port_connections; PBD::ScopedConnectionList port_connections;
PBD::ScopedConnection config_connection; PBD::ScopedConnection config_connection;
bool can_notify_on_unknown_rate; bool can_notify_on_unknown_rate;
@ -405,13 +413,14 @@ public:
class MIDIClock_Slave : public Slave { class MIDIClock_Slave : public Slave {
public: public:
MIDIClock_Slave (Session&, MIDI::Port&, int ppqn = 24); MIDIClock_Slave (Session&, MidiPort&, int ppqn = 24);
/// Constructor for unit tests /// Constructor for unit tests
MIDIClock_Slave (ISlaveSessionProxy* session_proxy = 0, int ppqn = 24); MIDIClock_Slave (ISlaveSessionProxy* session_proxy = 0, int ppqn = 24);
~MIDIClock_Slave (); ~MIDIClock_Slave ();
void rebind (MIDI::Port&); void rebind (MidiPort&);
int process (pframes_t);
bool speed_and_position (double&, framepos_t&); bool speed_and_position (double&, framepos_t&);
bool locked() const; bool locked() const;
@ -427,7 +436,8 @@ class MIDIClock_Slave : public Slave {
protected: protected:
ISlaveSessionProxy* session; ISlaveSessionProxy* session;
MIDI::Port* port; MidiPort* port;
MIDI::Parser parser;
PBD::ScopedConnectionList port_connections; PBD::ScopedConnectionList port_connections;
/// pulses per quarter note for one MIDI clock frame (default 24) /// pulses per quarter note for one MIDI clock frame (default 24)

View file

@ -27,17 +27,13 @@
#include "ardour/session_handle.h" #include "ardour/session_handle.h"
#ifndef TICKER_H_ #ifndef __libardour_ticker_h__
#define TICKER_H_ #define __libardour_ticker_h__
namespace MIDI { namespace ARDOUR {
class Port;
}
namespace ARDOUR
{
class Session; class Session;
class MidiPort;
class MidiClockTicker : public SessionHandlePtr, boost::noncopyable class MidiClockTicker : public SessionHandlePtr, boost::noncopyable
{ {
@ -45,7 +41,7 @@ public:
MidiClockTicker (); MidiClockTicker ();
virtual ~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; } bool has_midi_port() const { return _midi_port != 0; }
@ -58,9 +54,6 @@ public:
/// slot for the signal session::TransportStateChange /// slot for the signal session::TransportStateChange
void transport_state_changed(); void transport_state_changed();
/// slot for the signal session::PositionChanged
void position_changed (framepos_t position);
/// slot for the signal session::TransportLooped /// slot for the signal session::TransportLooped
void transport_looped(); void transport_looped();
@ -70,23 +63,25 @@ public:
/// pulses per quarter note (default 24) /// pulses per quarter note (default 24)
void set_ppqn(int ppqn) { _ppqn = ppqn; } void set_ppqn(int ppqn) { _ppqn = ppqn; }
private: private:
MIDI::Port* _midi_port; boost::shared_ptr<MidiPort> _midi_port;
int _ppqn; int _ppqn;
double _last_tick; double _last_tick;
bool _send_pos;
bool _send_state;
class Position; class Position;
boost::scoped_ptr<Position> _pos; boost::scoped_ptr<Position> _pos;
double one_ppqn_in_frames (framepos_t transport_position); double one_ppqn_in_frames (framepos_t transport_position);
void send_midi_clock_event (pframes_t offset); void send_midi_clock_event (pframes_t offset, pframes_t nframes);
void send_start_event (pframes_t offset); void send_start_event (pframes_t offset, pframes_t nframes);
void send_continue_event (pframes_t offset); void send_continue_event (pframes_t offset, pframes_t nframes);
void send_stop_event (pframes_t offset); void send_stop_event (pframes_t offset, pframes_t nframes);
void send_position_event (uint32_t midi_clocks, pframes_t offset); void send_position_event (uint32_t midi_clocks, pframes_t offset, pframes_t nframes);
}; };
} }
// namespace
#endif /* TICKER_H_ */ #endif /* __libardour_ticker_h__ */

View file

@ -37,10 +37,9 @@
#include <jack/weakjack.h> #include <jack/weakjack.h>
#include "midi++/port.h" #include "midi++/port.h"
#include "midi++/jack_midi_port.h"
#include "midi++/mmc.h" #include "midi++/mmc.h"
#include "midi++/manager.h"
#include "ardour/async_midi_port.h"
#include "ardour/audio_port.h" #include "ardour/audio_port.h"
#include "ardour/audio_backend.h" #include "ardour/audio_backend.h"
#include "ardour/audioengine.h" #include "ardour/audioengine.h"
@ -50,6 +49,7 @@
#include "ardour/internal_send.h" #include "ardour/internal_send.h"
#include "ardour/meter.h" #include "ardour/meter.h"
#include "ardour/midi_port.h" #include "ardour/midi_port.h"
#include "ardour/midiport_manager.h"
#include "ardour/port.h" #include "ardour/port.h"
#include "ardour/process_thread.h" #include "ardour/process_thread.h"
#include "ardour/session.h" #include "ardour/session.h"
@ -66,10 +66,11 @@ AudioEngine* AudioEngine::_instance = 0;
AudioEngine::AudioEngine () AudioEngine::AudioEngine ()
: session_remove_pending (false) : session_remove_pending (false)
, session_removal_countdown (-1) , session_removal_countdown (-1)
, _running (false)
, _freewheeling (false)
, monitor_check_interval (INT32_MAX) , monitor_check_interval (INT32_MAX)
, last_monitor_check (0) , last_monitor_check (0)
, _processed_frames (0) , _processed_frames (0)
, _freewheeling (false)
, _pre_freewheel_mmc_enabled (false) , _pre_freewheel_mmc_enabled (false)
, m_meter_thread (0) , m_meter_thread (0)
, _main_thread (0) , _main_thread (0)
@ -117,7 +118,7 @@ _thread_init_callback (void * /*arg*/)
SessionEvent::create_per_thread_pool (X_("Audioengine"), 512); SessionEvent::create_per_thread_pool (X_("Audioengine"), 512);
MIDI::JackMIDIPort::set_process_thread (pthread_self()); AsyncMIDIPort::set_process_thread (pthread_self());
} }
void void
@ -231,8 +232,8 @@ AudioEngine::process_callback (pframes_t nframes)
if (_session == 0) { if (_session == 0) {
if (!_freewheeling) { if (!_freewheeling) {
MIDI::Manager::instance()->cycle_start(nframes); PortManager::cycle_start (nframes);
MIDI::Manager::instance()->cycle_end(); PortManager::cycle_end (nframes);
} }
_processed_frames = next_processed_frames; _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 */ /* tell all relevant objects that we're starting a new cycle */
InternalSend::CycleStart (nframes); 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 */ /* tell all Ports that we're starting a new cycle */
boost::shared_ptr<Ports> p = ports.reader(); PortManager::cycle_start (nframes);
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
i->second->cycle_start (nframes);
}
/* test if we are freewheeling and there are freewheel signals connected. /* test if we are freewheeling and there are freewheel signals connected.
ardour should act normally even when freewheeling unless /it/ is ardour should act normally even when freewheeling unless /it/ is
exporting exporting (which is what Freewheel.empty() tests for).
*/ */
if (_freewheeling && !Freewheel.empty()) { if (_freewheeling && !Freewheel.empty()) {
Freewheel (nframes); Freewheel (nframes);
} else { } else {
MIDI::Manager::instance()->cycle_start(nframes);
if (_session) { if (_session) {
_session->process (nframes); _session->process (nframes);
} }
MIDI::Manager::instance()->cycle_end();
} }
if (_freewheeling) { if (_freewheeling) {
@ -284,51 +273,17 @@ AudioEngine::process_callback (pframes_t nframes)
if (last_monitor_check + monitor_check_interval < next_processed_frames) { if (last_monitor_check + monitor_check_interval < next_processed_frames) {
boost::shared_ptr<Ports> p = ports.reader(); PortManager::check_monitoring ();
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 */
}
}
last_monitor_check = next_processed_frames; last_monitor_check = next_processed_frames;
} }
if (_session->silent()) { if (_session->silent()) {
PortManager::silence (nframes);
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
if (i->second->sends_output()) {
i->second->get_buffer(nframes).silence(nframes);
}
}
} }
if (session_remove_pending && session_removal_countdown) { if (session_remove_pending && session_removal_countdown) {
for (Ports::iterator i = p->begin(); i != p->end(); ++i) { PortManager::fade_out (session_removal_gain, session_removal_gain_step, nframes);
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;
}
}
}
}
if (session_removal_countdown > nframes) { if (session_removal_countdown > nframes) {
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); session_removal_gain -= (nframes * session_removal_gain_step);
} }
// Finalize ports PortManager::cycle_end (nframes);
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
i->second->cycle_end (nframes);
}
_processed_frames = next_processed_frames; _processed_frames = next_processed_frames;
@ -603,31 +554,45 @@ AudioEngine::start ()
return -1; return -1;
} }
if (!_running) { if (_running) {
return 0;
if (_session) {
BootMessage (_("Connect session to engine"));
_session->set_frame_rate (_backend->sample_rate());
}
_processed_frames = 0;
last_monitor_check = 0;
if (_backend->start() == 0) {
_running = true;
last_monitor_check = 0;
if (_session && _session->config.get_jack_time_master()) {
_backend->set_time_master (true);
}
Running(); /* EMIT SIGNAL */
} else {
/* should report error? */
}
} }
return _running ? 0 : -1; /* 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;
if (_backend->start() == 0) {
_running = true;
last_monitor_check = 0;
if (_session) {
_session->set_frame_rate (_backend->sample_rate());
if (_session->config.get_jack_time_master()) {
_backend->set_time_master (true);
}
}
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 int
@ -641,6 +606,7 @@ AudioEngine::stop ()
if (_backend->stop () == 0) { if (_backend->stop () == 0) {
_running = false; _running = false;
_processed_frames = 0;
stop_metering_thread (); stop_metering_thread ();
Stopped (); /* EMIT SIGNAL */ Stopped (); /* EMIT SIGNAL */
@ -932,7 +898,7 @@ AudioEngine::thread_init_callback (void* arg)
SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512); SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
MIDI::JackMIDIPort::set_process_thread (pthread_self()); AsyncMIDIPort::set_process_thread (pthread_self());
if (arg) { if (arg) {
AudioEngine* ae = static_cast<AudioEngine*> (arg); AudioEngine* ae = static_cast<AudioEngine*> (arg);
@ -964,10 +930,10 @@ void
AudioEngine::freewheel_callback (bool onoff) AudioEngine::freewheel_callback (bool onoff)
{ {
if (onoff) { if (onoff) {
_pre_freewheel_mmc_enabled = MIDI::Manager::instance()->mmc()->send_enabled (); _pre_freewheel_mmc_enabled = _mmc.send_enabled ();
MIDI::Manager::instance()->mmc()->enable_send (false); _mmc.enable_send (false);
} else { } 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) AudioEngine::halted_callback (const char* why)
{ {
stop_metering_thread (); stop_metering_thread ();
MIDI::JackMIDIPort::EngineHalted (); /* EMIT SIGNAL */
Halted (why); /* EMIT SIGNAL */ Halted (why); /* EMIT SIGNAL */
} }

View file

@ -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::OrderKeys = PBD::new_debug_bit ("orderkeys");
uint64_t PBD::DEBUG::Automation = PBD::new_debug_bit ("automation"); uint64_t PBD::DEBUG::Automation = PBD::new_debug_bit ("automation");
uint64_t PBD::DEBUG::WiimoteControl = PBD::new_debug_bit ("wiimotecontrol"); uint64_t PBD::DEBUG::WiimoteControl = PBD::new_debug_bit ("wiimotecontrol");
uint64_t PBD::DEBUG::Ports = PBD::new_debug_bit ("Ports");

View file

@ -67,7 +67,6 @@
#include "pbd/basename.h" #include "pbd/basename.h"
#include "midi++/port.h" #include "midi++/port.h"
#include "midi++/manager.h"
#include "midi++/mmc.h" #include "midi++/mmc.h"
#include "ardour/analyser.h" #include "ardour/analyser.h"
@ -80,6 +79,7 @@
#include "ardour/control_protocol_manager.h" #include "ardour/control_protocol_manager.h"
#include "ardour/filesystem_paths.h" #include "ardour/filesystem_paths.h"
#include "ardour/midi_region.h" #include "ardour/midi_region.h"
#include "ardour/midiport_manager.h"
#include "ardour/mix.h" #include "ardour/mix.h"
#include "ardour/panner_manager.h" #include "ardour/panner_manager.h"
#include "ardour/plugin_manager.h" #include "ardour/plugin_manager.h"
@ -340,9 +340,6 @@ ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir
void void
ARDOUR::init_post_engine () ARDOUR::init_post_engine ()
{ {
/* the MIDI Manager is needed by the ControlProtocolManager */
MIDI::Manager::create (AudioEngine::instance()->port_engine());
ControlProtocolManager::instance().discover_control_protocols (); ControlProtocolManager::instance().discover_control_protocols ();
XMLNode* node; XMLNode* node;

View file

@ -24,7 +24,8 @@
#include "pbd/error.h" #include "pbd/error.h"
#include "midi++/manager.h" #include "jack/jack.h"
#include "jack/thread.h"
#include "ardour/audioengine.h" #include "ardour/audioengine.h"
#include "ardour/types.h" #include "ardour/types.h"
@ -57,6 +58,7 @@ JACKAudioBackend::JACKAudioBackend (AudioEngine& e, boost::shared_ptr<JackConnec
, _target_systemic_input_latency (0) , _target_systemic_input_latency (0)
, _target_systemic_output_latency (0) , _target_systemic_output_latency (0)
{ {
_jack_connection->Disconnected.connect_same_thread (disconnect_connection, boost::bind (&JACKAudioBackend::disconnected, this, _1));
} }
JACKAudioBackend::~JACKAudioBackend() JACKAudioBackend::~JACKAudioBackend()
@ -897,8 +899,6 @@ JACKAudioBackend::jack_bufsize_callback (pframes_t nframes)
void void
JACKAudioBackend::disconnected (const char* why) JACKAudioBackend::disconnected (const char* why)
{ {
/* called from jack shutdown handler */
bool was_running = _running; bool was_running = _running;
_running = false; _running = false;

View file

@ -135,7 +135,10 @@ JackConnection::close ()
GET_PRIVATE_JACK_POINTER_RET (_jack, -1); GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
if (_priv_jack) { 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; return 0;

View file

@ -36,8 +36,6 @@
#include "pbd/xml++.h" #include "pbd/xml++.h"
#include "pbd/stacktrace.h" #include "pbd/stacktrace.h"
#include "midi++/manager.h"
#include "ardour/session.h" #include "ardour/session.h"
#include "ardour/ladspa_plugin.h" #include "ardour/ladspa_plugin.h"
#include "ardour/buffer_set.h" #include "ardour/buffer_set.h"

View file

@ -31,6 +31,8 @@
#include "midi++/port.h" #include "midi++/port.h"
#include "ardour/debug.h" #include "ardour/debug.h"
#include "ardour/midi_buffer.h"
#include "ardour/midi_port.h"
#include "ardour/slave.h" #include "ardour/slave.h"
#include "ardour/tempo.h" #include "ardour/tempo.h"
@ -41,13 +43,20 @@ using namespace ARDOUR;
using namespace MIDI; using namespace MIDI;
using namespace PBD; 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) : ppqn (ppqn)
, bandwidth (10.0 / 60.0) // 1 BpM = 1 / 60 Hz , bandwidth (10.0 / 60.0) // 1 BpM = 1 / 60 Hz
{ {
session = (ISlaveSessionProxy *) new SlaveSessionProxy(s); session = (ISlaveSessionProxy *) new SlaveSessionProxy(s);
rebind (p); rebind (p);
reset (); 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) MIDIClock_Slave::MIDIClock_Slave (ISlaveSessionProxy* session_proxy, int ppqn)
@ -63,20 +72,33 @@ MIDIClock_Slave::~MIDIClock_Slave()
delete session; delete session;
} }
void int
MIDIClock_Slave::rebind (MIDI::Port& p) MIDIClock_Slave::process (pframes_t nframes)
{ {
port_connections.drop_connections(); 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
MIDIClock_Slave::rebind (MidiPort& p)
{
port = &p; port = &p;
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("MIDIClock_Slave: connecting to port %1\n", port->name())); DEBUG_TRACE (DEBUG::MidiClock, string_compose ("MIDIClock_Slave: connecting to port %1\n", port->name()));
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));
} }
void void

View file

@ -22,11 +22,11 @@
#include "pbd/pthread_utils.h" #include "pbd/pthread_utils.h"
#include "midi++/manager.h" #include "ardour/async_midi_port.h"
#include "midi++/port.h"
#include "ardour/debug.h" #include "ardour/debug.h"
#include "ardour/audioengine.h" #include "ardour/audioengine.h"
#include "ardour/midi_port.h"
#include "ardour/midiport_manager.h"
#include "ardour/midi_ui.h" #include "ardour/midi_ui.h"
#include "ardour/session.h" #include "ardour/session.h"
#include "ardour/session_event.h" #include "ardour/session_event.h"
@ -48,7 +48,6 @@ MidiControlUI::MidiControlUI (Session& s)
: AbstractUI<MidiUIRequest> (X_("midiui")) : AbstractUI<MidiUIRequest> (X_("midiui"))
, _session (s) , _session (s)
{ {
MIDI::Manager::instance()->PortsChanged.connect_same_thread (rebind_connection, boost::bind (&MidiControlUI::change_midi_ports, this));
_instance = 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 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) { if (ioc & ~IO_IN) {
return false; return false;
@ -106,7 +95,7 @@ MidiControlUI::midi_input_handler (IOCondition ioc, MIDI::Port* port)
CrossThreadChannel::drain (port->selectable()); 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(); framepos_t now = _session.engine().sample_time();
port->parse (now); port->parse (now);
} }
@ -128,22 +117,19 @@ MidiControlUI::clear_ports ()
void void
MidiControlUI::reset_ports () MidiControlUI::reset_ports ()
{ {
clear_ports (); if (port_sources.empty()) {
AsyncMIDIPort* async = dynamic_cast<AsyncMIDIPort*> (AudioEngine::instance()->midi_input_port());
boost::shared_ptr<const MIDI::Manager::PortList> plist = MIDI::Manager::instance()->get_midi_ports (); if (!async) {
return;
for (MIDI::Manager::PortList::const_iterator i = plist->begin(); i != plist->end(); ++i) {
if (!(*i)->centrally_parsed()) {
continue;
} }
int fd; 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); 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()); psrc->attach (_main_loop->get_context());
// glibmm hack: for now, store only the GSource* // glibmm hack: for now, store only the GSource*

View file

@ -66,11 +66,47 @@ MidiPortManager::port (string const & n)
void void
MidiPortManager::create_ports () MidiPortManager::create_ports ()
{ {
_midi_in = AudioEngine::instance()->register_input_port (DataType::MIDI, _("MIDI control in"), true); /* this method is idempotent
_midi_out = AudioEngine::instance()->register_output_port (DataType::MIDI, _("MIDI control out"), true); */
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_input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_midi_in).get();
_midi_output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_midi_out).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 void

View file

@ -25,11 +25,12 @@
#include "pbd/error.h" #include "pbd/error.h"
#include "midi++/port.h"
#include "ardour/debug.h"
#include "ardour/slave.h"
#include "ardour/session.h"
#include "ardour/audioengine.h" #include "ardour/audioengine.h"
#include "ardour/debug.h"
#include "ardour/midi_buffer.h"
#include "ardour/midi_port.h"
#include "ardour/session.h"
#include "ardour/slave.h"
#include "i18n.h" #include "i18n.h"
@ -48,8 +49,9 @@ using namespace Timecode;
*/ */
const int MTC_Slave::frame_tolerance = 2; 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) : session (s)
, port (&p)
{ {
can_notify_on_unknown_rate = true; can_notify_on_unknown_rate = true;
did_reset_tc_format = false; 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)); session.config.ParameterChanged.connect_same_thread (config_connection, boost::bind (&MTC_Slave::parameter_changed, this, _1));
parse_timecode_offset(); parse_timecode_offset();
reset (true); 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() 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 void
MTC_Slave::rebind (MIDI::Port& p) MTC_Slave::rebind (MidiPort& p)
{ {
port_connections.drop_connections (); port_connections.drop_connections ();
port = &p; 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 void
@ -154,7 +179,7 @@ MTC_Slave::outside_window (framepos_t pos) const
bool bool
MTC_Slave::locked () const 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 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", 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())); mtc_frame, (4.0*qtr), session.frames_per_timecode_frame()));
switch (port->parser()->mtc_running()) { switch (parser.mtc_running()) {
case MTC_Backward: case MTC_Backward:
mtc_frame -= mtc_off; mtc_frame -= mtc_off;
qtr *= -1.0; qtr *= -1.0;
@ -528,7 +553,7 @@ MTC_Slave::reset_window (framepos_t root)
*/ */
framecnt_t const d = (quarter_frame_duration * 4 * frame_tolerance); framecnt_t const d = (quarter_frame_duration * 4 * frame_tolerance);
switch (port->parser()->mtc_running()) { switch (parser.mtc_running()) {
case MTC_Forward: case MTC_Forward:
window_begin = root; window_begin = root;
transport_direction = 1; transport_direction = 1;

View file

@ -390,6 +390,7 @@ Port::get_connected_latency_range (LatencyRange& range, bool playback) const
int int
Port::reestablish () 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); _port_handle = port_engine.register_port (_name, type(), _flags);
if (_port_handle == 0) { if (_port_handle == 0) {

View file

@ -19,11 +19,12 @@
#include "pbd/error.h" #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/port_manager.h"
#include "ardour/audio_port.h" #include "ardour/audio_port.h"
#include "ardour/midi_port.h" #include "ardour/midi_port.h"
#include "ardour/midiport_manager.h"
#include "i18n.h" #include "i18n.h"
@ -227,6 +228,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 int
PortManager::get_ports (const string& port_name_pattern, DataType type, PortFlags flags, vector<string>& s) PortManager::get_ports (const string& port_name_pattern, DataType type, PortFlags flags, vector<string>& s)
{ {
@ -262,15 +275,25 @@ PortManager::port_registration_failure (const std::string& portname)
} }
boost::shared_ptr<Port> 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; boost::shared_ptr<Port> newport;
try { try {
if (dtype == DataType::AUDIO) { 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))); newport.reset (new AudioPort (portname, (input ? IsInput : IsOutput)));
} else if (dtype == DataType::MIDI) { } 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 { } else {
throw PortRegistrationFailure("unable to create port (unknown type)"); 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 */ /* writer goes out of scope, forces update */
return newport;
} }
catch (PortRegistrationFailure& err) { catch (PortRegistrationFailure& err) {
@ -292,18 +314,21 @@ PortManager::register_port (DataType dtype, const string& portname, bool input)
} catch (...) { } catch (...) {
throw PortRegistrationFailure("unable to create port (unknown error)"); 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> 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> 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 int
@ -410,6 +435,8 @@ PortManager::reestablish_ports ()
boost::shared_ptr<Ports> p = ports.reader (); 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) { for (i = p->begin(); i != p->end(); ++i) {
if (i->second->reestablish ()) { if (i->second->reestablish ()) {
break; break;
@ -422,8 +449,6 @@ PortManager::reestablish_ports ()
return -1; return -1;
} }
MIDI::Manager::instance()->reestablish ();
return 0; return 0;
} }
@ -434,12 +459,12 @@ PortManager::reconnect_ports ()
/* re-establish connections */ /* 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) { for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
i->second->reconnect (); i->second->reconnect ();
} }
MIDI::Manager::instance()->reconnect ();
return 0; return 0;
} }
@ -543,3 +568,80 @@ PortManager::graph_order_callback ()
return 0; 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;
}
}
}
}
}

View file

@ -27,13 +27,12 @@
#include "pbd/xml++.h" #include "pbd/xml++.h"
#include "pbd/file_utils.h" #include "pbd/file_utils.h"
#include "midi++/manager.h"
#include "ardour/control_protocol_manager.h" #include "ardour/control_protocol_manager.h"
#include "ardour/diskstream.h" #include "ardour/diskstream.h"
#include "ardour/filesystem_paths.h" #include "ardour/filesystem_paths.h"
#include "ardour/rc_configuration.h" #include "ardour/rc_configuration.h"
#include "ardour/session_metadata.h" #include "ardour/session_metadata.h"
#include "ardour/midiport_manager.h"
#include "i18n.h" #include "i18n.h"
@ -177,15 +176,20 @@ RCConfiguration::get_state ()
root = new XMLNode("Ardour"); 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) { 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) { for (MidiPortManager::PortList::const_iterator i = ports->begin(); i != ports->end(); ++i) {
root->add_child_nocopy((*i)->get_state()); // root->add_child_nocopy ((*i)->get_state());
} }
} }
#endif
root->add_child_nocopy (get_variables ()); root->add_child_nocopy (get_variables ());

View file

@ -49,6 +49,7 @@
#include "ardour/amp.h" #include "ardour/amp.h"
#include "ardour/analyser.h" #include "ardour/analyser.h"
#include "ardour/async_midi_port.h"
#include "ardour/audio_buffer.h" #include "ardour/audio_buffer.h"
#include "ardour/audio_diskstream.h" #include "ardour/audio_diskstream.h"
#include "ardour/audio_port.h" #include "ardour/audio_port.h"
@ -66,6 +67,7 @@
#include "ardour/debug.h" #include "ardour/debug.h"
#include "ardour/filename_extensions.h" #include "ardour/filename_extensions.h"
#include "ardour/graph.h" #include "ardour/graph.h"
#include "ardour/midiport_manager.h"
#include "ardour/midi_track.h" #include "ardour/midi_track.h"
#include "ardour/midi_ui.h" #include "ardour/midi_ui.h"
#include "ardour/operations.h" #include "ardour/operations.h"
@ -88,9 +90,7 @@
#include "ardour/utils.h" #include "ardour/utils.h"
#include "midi++/port.h" #include "midi++/port.h"
#include "midi++/jack_midi_port.h"
#include "midi++/mmc.h" #include "midi++/mmc.h"
#include "midi++/manager.h"
#include "i18n.h" #include "i18n.h"
@ -584,7 +584,8 @@ Session::when_engine_running ()
as it will set states for ports which the ControlProtocolManager creates. 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 /* 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. * 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 */ /* Tell all IO objects to connect themselves together */
IO::enable_connecting (); 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 */ /* 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)) { if (g_atomic_int_compare_and_exchange (&_record_status, rs, Recording)) {
_last_record_location = _transport_frame; _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()) { if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
set_track_monitor_input_status (true); 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) { if ((!Config->get_latched_record_enable () && !play_loop) || force) {
g_atomic_int_set (&_record_status, Disabled); 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 { } else {
if (rs == Recording) { if (rs == Recording) {
g_atomic_int_set (&_record_status, Enabled); g_atomic_int_set (&_record_status, Enabled);
@ -1244,7 +1250,7 @@ Session::maybe_enable_record ()
enable_record (); enable_record ();
} }
} else { } else {
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordPause)); AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordPause));
RecordStateChanged (); /* EMIT SIGNAL */ RecordStateChanged (); /* EMIT SIGNAL */
} }

View file

@ -21,7 +21,6 @@
#include "pbd/error.h" #include "pbd/error.h"
#include <glibmm/threads.h> #include <glibmm/threads.h>
#include <midi++/manager.h>
#include <midi++/mmc.h> #include <midi++/mmc.h>
#include "ardour/audioengine.h" #include "ardour/audioengine.h"
@ -93,8 +92,8 @@ Session::pre_export ()
/* disable MMC output early */ /* disable MMC output early */
_pre_export_mmc_enabled = MIDI::Manager::instance()->mmc()->send_enabled (); _pre_export_mmc_enabled = AudioEngine::instance()->mmc().send_enabled ();
MIDI::Manager::instance()->mmc()->enable_send (false); AudioEngine::instance()->mmc().enable_send (false);
return 0; return 0;
} }
@ -237,7 +236,7 @@ Session::finalize_audio_export ()
export_freewheel_connection.disconnect(); 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 */ /* maybe write CUE/TOC */

View file

@ -31,7 +31,6 @@
#include "midi++/mmc.h" #include "midi++/mmc.h"
#include "midi++/port.h" #include "midi++/port.h"
#include "midi++/manager.h"
#include "pbd/error.h" #include "pbd/error.h"
#include "pbd/pthread_utils.h" #include "pbd/pthread_utils.h"
@ -41,6 +40,7 @@
#include "ardour/audio_track.h" #include "ardour/audio_track.h"
#include "ardour/audioengine.h" #include "ardour/audioengine.h"
#include "ardour/debug.h" #include "ardour/debug.h"
#include "ardour/midi_port.h"
#include "ardour/midi_track.h" #include "ardour/midi_track.h"
#include "ardour/midi_ui.h" #include "ardour/midi_ui.h"
#include "ardour/session.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. * @param t time to send.
*/ */
int 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 /* This function could easily send at a given frame offset, but would
* that be useful? Does ardour do sub-block accurate locating? [DR] */ * 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; msg[8] = timecode.frames;
// Send message at offset 0, sent time is for the start of this cycle // Send message at offset 0, sent time is for the start of this cycle
if (MIDI::Manager::instance()->mtc_output_port()->midimsg (msg, sizeof (msg), 0)) {
error << _("Session: could not send full MIDI time code") << endmsg; MidiBuffer& mb (AudioEngine::instance()->mtc_output_port()->get_midi_buffer (nframes));
return -1; mb.push_back (0, sizeof (msg), msg);
}
_pframes_since_last_mtc = 0; _pframes_since_last_mtc = 0;
return 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)); next_quarter_frame_to_send, quarter_frame_duration));
if (rint(outbound_mtc_timecode_frame + (next_quarter_frame_to_send * quarter_frame_duration)) < _transport_frame) { 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; 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; pframes_t const out_stamp = (msg_time - start_frame) / _transport_speed;
assert (out_stamp < nframes); 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)) error << string_compose(_("Session: cannot send quarter-frame MTC message (%1)"), strerror (errno))
<< endmsg; << endmsg;
return -1; return -1;
} }
@ -588,7 +588,7 @@ Session::mmc_step_timeout ()
void void
Session::send_song_position_pointer (framepos_t t) Session::send_song_position_pointer (framepos_t)
{ {
if (midi_clock) { if (midi_clock) {
/* Do nothing for the moment */ /* Do nothing for the moment */

View file

@ -40,7 +40,6 @@
#include "ardour/ticker.h" #include "ardour/ticker.h"
#include "ardour/types.h" #include "ardour/types.h"
#include "midi++/manager.h"
#include "midi++/mmc.h" #include "midi++/mmc.h"
#include "i18n.h" #include "i18n.h"
@ -85,7 +84,7 @@ Session::process (pframes_t nframes)
try { try {
if (!_engine.freewheeling() && Config->get_send_midi_clock() && transport_speed() == 1.0f && midi_clock->has_midi_port()) { 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 (...) { } catch (...) {
/* don't bother with a message */ /* don't bother with a message */
@ -325,7 +324,7 @@ Session::process_with_events (pframes_t nframes)
* and prepare for rolling) * and prepare for rolling)
*/ */
if (_send_timecode_update) { if (_send_timecode_update) {
send_full_time_code (_transport_frame); send_full_time_code (_transport_frame, nframes);
} }
if (!process_can_proceed()) { if (!process_can_proceed()) {
@ -492,6 +491,7 @@ Session::follow_slave (pframes_t nframes)
goto noroll; goto noroll;
} }
_slave->process (nframes);
_slave->speed_and_position (slave_speed, slave_transport_frame); _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)); DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));

View file

@ -60,7 +60,6 @@
#include "midi++/mmc.h" #include "midi++/mmc.h"
#include "midi++/port.h" #include "midi++/port.h"
#include "midi++/manager.h"
#include "evoral/SMF.hpp" #include "evoral/SMF.hpp"
@ -359,11 +358,11 @@ Session::second_stage_init ()
BootMessage (_("Reset Remote Controls")); BootMessage (_("Reset Remote Controls"));
send_full_time_code (0); // send_full_time_code (0);
_engine.transport_locate (0); _engine.transport_locate (0);
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset)); AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ())); AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (Timecode::Time ()));
MIDI::Name::MidiPatchManager::instance().set_session (this); 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") { } 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") { } 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") { } else if (p == "midi-control") {
@ -3496,7 +3495,7 @@ Session::config_changed (std::string p, bool ours)
} else if (p == "send-mmc") { } 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") { } else if (p == "midi-feedback") {
@ -3554,13 +3553,13 @@ Session::config_changed (std::string p, bool ours)
} else if (p == "initial-program-change") { } 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]; MIDI::byte buf[2];
buf[0] = MIDI::program; // channel zero by default buf[0] = MIDI::program; // channel zero by default
buf[1] = (Config->get_initial_program_change() & 0x7f); buf[1] = (Config->get_initial_program_change() & 0x7f);
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") { } else if (p == "solo-mute-override") {
// catch_up_on_solo_mute_override (); // catch_up_on_solo_mute_override ();
@ -3624,27 +3623,27 @@ Session::load_diskstreams_2X (XMLNode const & node, int)
void void
Session::setup_midi_machine_control () Session::setup_midi_machine_control ()
{ {
MIDI::MachineControl* mmc = MIDI::Manager::instance()->mmc (); MIDI::MachineControl& mmc (AudioEngine::instance()->mmc ());
mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1)); mmc.Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1)); mmc.DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1)); mmc.Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1)); mmc.FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1)); mmc.Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1)); mmc.Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1)); mmc.RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1)); mmc.RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1)); mmc.RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2)); mmc.Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2)); mmc.Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3)); mmc.Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3)); mmc.TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
/* also handle MIDI SPP because its so common */ /* also handle MIDI SPP because its so common */
mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this)); 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.SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this)); mmc.SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
} }
boost::shared_ptr<Controllable> boost::shared_ptr<Controllable>

View file

@ -33,7 +33,6 @@
#include "midi++/mmc.h" #include "midi++/mmc.h"
#include "midi++/port.h" #include "midi++/port.h"
#include "midi++/manager.h"
#include "ardour/audioengine.h" #include "ardour/audioengine.h"
#include "ardour/auditioner.h" #include "ardour/auditioner.h"
@ -611,10 +610,11 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
have_looped = false; have_looped = false;
if (!_engine.freewheeling()) { 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)) { 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); send_mmc_locate (_transport_frame);
} }
} }
@ -1260,7 +1260,7 @@ Session::start_transport ()
Timecode::Time time; Timecode::Time time;
timecode_time_subframes (_transport_frame, time); timecode_time_subframes (_transport_frame, time);
if (!dynamic_cast<MTC_Slave*>(_slave)) { 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));
} }
} }
@ -1339,7 +1339,8 @@ Session::use_sync_source (Slave* new_slave)
DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _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(); boost::shared_ptr<RouteList> rl = routes.reader();
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) { for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
@ -1380,7 +1381,7 @@ Session::switch_to_sync_source (SyncSource src)
} }
try { 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) { catch (failed_constructor& err) {
@ -1409,7 +1410,7 @@ Session::switch_to_sync_source (SyncSource src)
} }
try { 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) { catch (failed_constructor& err) {
@ -1636,7 +1637,7 @@ Session::send_mmc_locate (framepos_t t)
if (!_engine.freewheeling()) { if (!_engine.freewheeling()) {
Timecode::Time time; Timecode::Time time;
timecode_time_subframes (t, time); timecode_time_subframes (t, time);
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (time)); AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (time));
} }
} }

View file

@ -19,13 +19,12 @@
#include "pbd/compose.h" #include "pbd/compose.h"
#include "pbd/stacktrace.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 "evoral/midi_events.h"
#include "ardour/async_midi_port.h"
#include "ardour/audioengine.h" #include "ardour/audioengine.h"
#include "ardour/midi_buffer.h"
#include "ardour/midi_port.h"
#include "ardour/ticker.h" #include "ardour/ticker.h"
#include "ardour/session.h" #include "ardour/session.h"
#include "ardour/tempo.h" #include "ardour/tempo.h"
@ -95,16 +94,16 @@ public:
MidiClockTicker::MidiClockTicker () MidiClockTicker::MidiClockTicker ()
: _midi_port (0) : _ppqn (24)
, _ppqn (24)
, _last_tick (0.0) , _last_tick (0.0)
, _send_pos (false)
, _send_state (false)
{ {
_pos.reset (new Position()); _pos.reset (new Position());
} }
MidiClockTicker::~MidiClockTicker() MidiClockTicker::~MidiClockTicker()
{ {
_midi_port = 0;
_pos.reset (0); _pos.reset (0);
} }
@ -115,7 +114,6 @@ MidiClockTicker::set_session (Session* s)
if (_session) { if (_session) {
_session->TransportStateChange.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::transport_state_changed, this)); _session->TransportStateChange.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::transport_state_changed, this));
_session->PositionChanged.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::position_changed, this, _1));
_session->TransportLooped.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::transport_looped, this)); _session->TransportLooped.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::transport_looped, this));
_session->Located.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::session_located, this)); _session->Located.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::session_located, this));
@ -139,41 +137,20 @@ MidiClockTicker::session_located()
return; return;
} }
if (_pos->speed == 0.0f) { _send_pos = true;
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 */
}
} }
void void
MidiClockTicker::session_going_away () MidiClockTicker::session_going_away ()
{ {
SessionHandlePtr::session_going_away(); SessionHandlePtr::session_going_away();
_midi_port = 0; _midi_port.reset ();
} }
void void
MidiClockTicker::update_midi_clock_port() MidiClockTicker::update_midi_clock_port()
{ {
_midi_port = MIDI::Manager::instance()->midi_clock_output_port(); _midi_port = AudioEngine::instance()->midi_clock_output_port();
} }
void void
@ -204,48 +181,11 @@ MidiClockTicker::transport_state_changed()
return; return;
} }
if (_pos->speed == 1.0f) { _send_state = true;
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);
}
// tick (_pos->frame); // 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 void
MidiClockTicker::transport_looped() MidiClockTicker::transport_looped()
{ {
@ -270,18 +210,68 @@ MidiClockTicker::transport_looped()
} }
void 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) { if (!Config->get_send_midi_clock() || _session == 0 || _session->transport_speed() != 1.0f || _midi_port == 0) {
return; return;
} }
MIDI::JackMIDIPort* mp = dynamic_cast<MIDI::JackMIDIPort*> (_midi_port); if (_send_pos) {
if (! mp) { if (_pos->speed == 0.0f) {
return; 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; double iter = _last_tick;
while (true) { while (true) {
@ -291,14 +281,14 @@ MidiClockTicker::tick (const framepos_t& /* transport_frame */)
DEBUG_TRACE (DEBUG::MidiClock, DEBUG_TRACE (DEBUG::MidiClock,
string_compose ("Tick: iter: %1, last tick time: %2, next tick time: %3, offset: %4, cycle length: %5\n", 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; break;
} }
if (next_tick_offset >= 0) { if (next_tick_offset >= 0) {
send_midi_clock_event (next_tick_offset); send_midi_clock_event (next_tick_offset, nframes);
} }
iter = next_tick; iter = next_tick;
@ -308,7 +298,6 @@ MidiClockTicker::tick (const framepos_t& /* transport_frame */)
_pos->frame = end; _pos->frame = end;
} }
double double
MidiClockTicker::one_ppqn_in_frames (framepos_t transport_position) MidiClockTicker::one_ppqn_in_frames (framepos_t transport_position)
{ {
@ -322,7 +311,7 @@ MidiClockTicker::one_ppqn_in_frames (framepos_t transport_position)
} }
void void
MidiClockTicker::send_midi_clock_event (pframes_t offset) MidiClockTicker::send_midi_clock_event (pframes_t offset, pframes_t nframes)
{ {
if (!_midi_port) { if (!_midi_port) {
return; 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)); DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Tick with offset %1\n", offset));
static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_CLOCK }; static uint8_t tick_byte = { MIDI_CMD_COMMON_CLOCK };
_midi_port->write (_midi_clock_tick, 1, offset); MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
mb.push_back (offset, 1, &tick_byte);
} }
void void
MidiClockTicker::send_start_event (pframes_t offset) MidiClockTicker::send_start_event (pframes_t offset, pframes_t nframes)
{ {
if (!_midi_port) { if (!_midi_port) {
return; return;
@ -343,12 +333,13 @@ MidiClockTicker::send_start_event (pframes_t offset)
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Start %1\n", _last_tick)); DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Start %1\n", _last_tick));
static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_START }; static uint8_t tick_byte = { MIDI_CMD_COMMON_START };
_midi_port->write (_midi_clock_tick, 1, offset); MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
mb.push_back (offset, 1, &tick_byte);
} }
void void
MidiClockTicker::send_continue_event (pframes_t offset) MidiClockTicker::send_continue_event (pframes_t offset, pframes_t nframes)
{ {
if (!_midi_port) { if (!_midi_port) {
return; return;
@ -356,12 +347,13 @@ MidiClockTicker::send_continue_event (pframes_t offset)
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Continue %1\n", _last_tick)); DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Continue %1\n", _last_tick));
static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_CONTINUE }; static uint8_t tick_byte = { MIDI_CMD_COMMON_CONTINUE };
_midi_port->write (_midi_clock_tick, 1, offset); MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
mb.push_back (offset, 1, &tick_byte);
} }
void void
MidiClockTicker::send_stop_event (pframes_t offset) MidiClockTicker::send_stop_event (pframes_t offset, pframes_t nframes)
{ {
if (!_midi_port) { if (!_midi_port) {
return; return;
@ -369,12 +361,13 @@ MidiClockTicker::send_stop_event (pframes_t offset)
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Stop %1\n", _last_tick)); DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Stop %1\n", _last_tick));
static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_STOP }; static uint8_t tick_byte = { MIDI_CMD_COMMON_STOP };
_midi_port->write (_midi_clock_tick, 1, offset); MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
mb.push_back (offset, 1, &tick_byte);
} }
void 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) { if (!_midi_port) {
return; return;
@ -391,7 +384,8 @@ MidiClockTicker::send_position_event (uint32_t midi_beats, pframes_t offset)
msg[1] = midi_beats & 0x007f; msg[1] = midi_beats & 0x007f;
msg[2] = midi_beats >> 7; 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)); DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Song Position Sent: %1\n", midi_beats));
} }

View file

@ -21,6 +21,7 @@ path_prefix = 'libs/ardour/'
libardour_sources = [ libardour_sources = [
'amp.cc', 'amp.cc',
'analyser.cc', 'analyser.cc',
'async_midi_port.cc',
'audio_buffer.cc', 'audio_buffer.cc',
'audio_diskstream.cc', 'audio_diskstream.cc',
'audio_library.cc', 'audio_library.cc',
@ -126,6 +127,7 @@ libardour_sources = [
'midi_stretch.cc', 'midi_stretch.cc',
'midi_track.cc', 'midi_track.cc',
'midi_ui.cc', 'midi_ui.cc',
'midiport_manager.cc',
'mix.cc', 'mix.cc',
'monitor_processor.cc', 'monitor_processor.cc',
'mtc_slave.cc', 'mtc_slave.cc',

View file

@ -38,7 +38,6 @@ namespace MIDI {
class Port; class Port;
class Parser; class Parser;
class MachineControlCommand; class MachineControlCommand;
class Manager;
/** Class to handle incoming and outgoing MIDI machine control messages */ /** Class to handle incoming and outgoing MIDI machine control messages */
class MachineControl class MachineControl
@ -95,7 +94,9 @@ class MachineControl
cmdResume = 0x7F cmdResume = 0x7F
}; };
MachineControl (Manager *, ARDOUR::PortEngine&); MachineControl ();
void set_ports (MIDI::Port* input, MIDI::Port* output);
Port* input_port() { return _input_port; } Port* input_port() { return _input_port; }
Port* output_port() { return _output_port; } Port* output_port() { return _output_port; }

View file

@ -41,7 +41,7 @@ typedef PBD::Signal3<void,Parser &, byte *, size_t> Signal;
class Parser { class Parser {
public: public:
Parser (Port &p); Parser ();
~Parser (); ~Parser ();
/* sets the time that will be reported for any MTC or MIDI Clock /* 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); const char *midi_event_type_name (MIDI::eventType);
void trace (bool onoff, std::ostream *o, const std::string &prefix = ""); void trace (bool onoff, std::ostream *o, const std::string &prefix = "");
bool tracing() { return trace_stream != 0; } bool tracing() { return trace_stream != 0; }
Port &port() { return _port; }
void set_offline (bool); void set_offline (bool);
bool offline() const { return _offline; } bool offline() const { return _offline; }
@ -136,7 +135,6 @@ class Parser {
void reset_mtc_state (); void reset_mtc_state ();
private: private:
Port&_port;
/* tracing */ /* tracing */
std::ostream *trace_stream; std::ostream *trace_stream;

View file

@ -51,13 +51,6 @@ class Port {
virtual XMLNode& get_state () const; virtual XMLNode& get_state () const;
virtual void set_state (const XMLNode&); 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. /** Write a message to port.
* @param msg Raw MIDI message to send * @param msg Raw MIDI message to send
* @param msglen Size of @a msg * @param msglen Size of @a msg

View file

@ -27,9 +27,7 @@
#include "midi++/mmc.h" #include "midi++/mmc.h"
#include "midi++/port.h" #include "midi++/port.h"
#include "midi++/jack_midi_port.h"
#include "midi++/parser.h" #include "midi++/parser.h"
#include "midi++/manager.h"
using namespace std; using namespace std;
using namespace MIDI; using namespace MIDI;
@ -197,16 +195,21 @@ static void build_mmc_cmd_map ()
mmc_cmd_map.insert (newpair); mmc_cmd_map.insert (newpair);
} }
MachineControl::MachineControl ()
MachineControl::MachineControl (Manager* m, ARDOUR::PortEngine& pengine)
{ {
build_mmc_cmd_map (); build_mmc_cmd_map ();
_receive_device_id = 0x7f; _receive_device_id = 0x7f;
_send_device_id = 0x7f; _send_device_id = 0x7f;
}
_input_port = m->add_port (new JackMIDIPort ("MMC in", Port::IsInput, pengine)); void
_output_port = m->add_port (new JackMIDIPort ("MMC out", Port::IsOutput, pengine)); MachineControl::set_ports (MIDI::Port* ip, MIDI::Port* op)
{
port_connections.drop_connections ();
_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()->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)); _input_port->parser()->start.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_start, this));

View file

@ -104,8 +104,7 @@ Parser::midi_event_type_name (eventType t)
} }
} }
Parser::Parser (Port &p) Parser::Parser ()
: _port(p)
{ {
trace_stream = 0; trace_stream = 0;
trace_prefix = ""; trace_prefix = "";

View file

@ -71,7 +71,7 @@ Port::init (string const & name, Flags flags)
_tagname = name; _tagname = name;
_flags = flags; _flags = flags;
_parser = new Parser (*this); _parser = new Parser ();
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
_channel[i] = new Channel (i, *this); _channel[i] = new Channel (i, *this);

View file

@ -31,8 +31,6 @@ libmidi_sources = [
'midi.cc', 'midi.cc',
'channel.cc', 'channel.cc',
'ipmidi_port.cc', 'ipmidi_port.cc',
'jack_midi_port.cc',
'manager.cc',
'parser.cc', 'parser.cc',
'port.cc', 'port.cc',
'midnam_patch.cc', 'midnam_patch.cc',

View file

@ -32,13 +32,14 @@
#include "pbd/xml++.h" #include "pbd/xml++.h"
#include "midi++/port.h" #include "midi++/port.h"
#include "midi++/manager.h"
#include "ardour/audioengine.h"
#include "ardour/filesystem_paths.h" #include "ardour/filesystem_paths.h"
#include "ardour/session.h" #include "ardour/session.h"
#include "ardour/route.h" #include "ardour/route.h"
#include "ardour/midi_ui.h" #include "ardour/midi_ui.h"
#include "ardour/rc_configuration.h" #include "ardour/rc_configuration.h"
#include "ardour/midiport_manager.h"
#include "generic_midi_control_protocol.h" #include "generic_midi_control_protocol.h"
#include "midicontrollable.h" #include "midicontrollable.h"
@ -59,8 +60,8 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
, _threshold (10) , _threshold (10)
, gui (0) , gui (0)
{ {
_input_port = MIDI::Manager::instance()->midi_input_port (); _input_port = AudioEngine::instance()->midi_input_port ();
_output_port = MIDI::Manager::instance()->midi_output_port (); _output_port = AudioEngine::instance()->midi_output_port ();
do_feedback = false; do_feedback = false;
_feedback_interval = 10000; // microseconds _feedback_interval = 10000; // microseconds
@ -338,7 +339,7 @@ GenericMidiControlProtocol::start_learning (Controllable* c)
} }
if (!mc) { 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; MIDI::byte value = control_number;
// Create a MIDIControllable // 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 // 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 // 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); Controllable* c = Controllable::by_id (id);
if (c) { 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) { if (mc->set_state (**niter, version) == 0) {
controllables.push_back (mc); controllables.push_back (mc);
@ -754,7 +755,7 @@ GenericMidiControlProtocol::create_binding (const XMLNode& node)
prop = node.property (X_("uri")); prop = node.property (X_("uri"));
uri = prop->value(); uri = prop->value();
MIDIControllable* mc = new MIDIControllable (this, *_input_port, momentary); MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), momentary);
if (mc->init (uri)) { if (mc->init (uri)) {
delete mc; delete mc;
@ -892,7 +893,7 @@ GenericMidiControlProtocol::create_function (const XMLNode& node)
prop = node.property (X_("function")); 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)) { if (mf->setup (*this, prop->value(), argument, data, data_size)) {
delete mf; delete mf;
@ -988,7 +989,7 @@ GenericMidiControlProtocol::create_action (const XMLNode& node)
prop = node.property (X_("action")); 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)) { if (ma->init (*this, prop->value(), data, data_size)) {
delete ma; delete ma;

View file

@ -22,14 +22,11 @@
#include <list> #include <list>
#include <glibmm/threads.h> #include <glibmm/threads.h>
#include "ardour/types.h" #include "ardour/types.h"
#include "control_protocol/control_protocol.h" #include "control_protocol/control_protocol.h"
namespace MIDI {
class Port;
}
namespace PBD { namespace PBD {
class Controllable; class Controllable;
class ControllableDescriptor; class ControllableDescriptor;
@ -37,6 +34,11 @@ namespace PBD {
namespace ARDOUR { namespace ARDOUR {
class Session; class Session;
class MidiPort;
}
namespace MIDI {
class Port;
} }
class MIDIControllable; class MIDIControllable;
@ -51,8 +53,8 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
int set_active (bool yn); int set_active (bool yn);
static bool probe() { return true; } static bool probe() { return true; }
MIDI::Port* input_port () const { return _input_port; } MIDI::Port* input_port () const { return _input_port; }
MIDI::Port* output_port () const { return _output_port; } MIDI::Port* output_port () const { return _output_port; }
void set_feedback_interval (ARDOUR::microseconds_t); void set_feedback_interval (ARDOUR::microseconds_t);
int set_feedback (bool yn); int set_feedback (bool yn);
@ -97,8 +99,8 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
} }
private: private:
MIDI::Port* _input_port; MIDI::Port* _input_port;
MIDI::Port* _output_port; MIDI::Port* _output_port;
ARDOUR::microseconds_t _feedback_interval; ARDOUR::microseconds_t _feedback_interval;
ARDOUR::microseconds_t last_feedback_time; ARDOUR::microseconds_t last_feedback_time;

View file

@ -25,7 +25,7 @@
using namespace MIDI; using namespace MIDI;
MIDIAction::MIDIAction (MIDI::Port& p) MIDIAction::MIDIAction (MIDI::Parser& p)
: MIDIInvokable (p) : MIDIInvokable (p)
{ {
} }

View file

@ -36,8 +36,6 @@ namespace Gtk {
} }
namespace MIDI { namespace MIDI {
class Channel;
class Port;
class Parser; class Parser;
} }
@ -46,7 +44,7 @@ class GenericMidiControlProtocol;
class MIDIAction : public MIDIInvokable class MIDIAction : public MIDIInvokable
{ {
public: public:
MIDIAction (MIDI::Port&); MIDIAction (MIDI::Parser&);
virtual ~MIDIAction (); virtual ~MIDIAction ();
int init (GenericMidiControlProtocol&, const std::string& action_name, MIDI::byte* sysex = 0, size_t ssize = 0); int init (GenericMidiControlProtocol&, const std::string& action_name, MIDI::byte* sysex = 0, size_t ssize = 0);

View file

@ -27,9 +27,9 @@
#include "pbd/xml++.h" #include "pbd/xml++.h"
#include "pbd/stacktrace.h" #include "pbd/stacktrace.h"
#include "midi++/port.h"
#include "midi++/channel.h" #include "midi++/channel.h"
#include "ardour/async_midi_port.h"
#include "ardour/automation_control.h" #include "ardour/automation_control.h"
#include "ardour/midi_ui.h" #include "ardour/midi_ui.h"
#include "ardour/utils.h" #include "ardour/utils.h"
@ -42,11 +42,11 @@ using namespace MIDI;
using namespace PBD; using namespace PBD;
using namespace ARDOUR; using namespace ARDOUR;
MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, Port& p, bool m) MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, MIDI::Parser& p, bool m)
: _surface (s) : _surface (s)
, controllable (0) , controllable (0)
, _descriptor (0) , _descriptor (0)
, _port (p) , _parser (p)
, _momentary (m) , _momentary (m)
{ {
_learned = false; /* from URI */ _learned = false; /* from URI */
@ -59,10 +59,10 @@ MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, Port& p, bool
feedback = true; // for now 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) : _surface (s)
, _descriptor (0) , _descriptor (0)
, _port (p) , _parser (p)
, _momentary (m) , _momentary (m)
{ {
set_controllable (&c); set_controllable (&c);
@ -149,7 +149,7 @@ void
MIDIControllable::learn_about_external_control () MIDIControllable::learn_about_external_control ()
{ {
drop_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 void
@ -357,12 +357,6 @@ MIDIControllable::midi_receiver (Parser &, byte *msg, size_t /*len*/)
return; 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]); bind_midi ((channel_t) (msg[0] & 0xf), eventType (msg[0] & 0xF0), msg[1]);
if (controllable) { if (controllable) {
@ -381,49 +375,43 @@ MIDIControllable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
control_channel = chn; control_channel = chn;
control_additional = additional; control_additional = additional;
if (_port.parser() == 0) {
return;
}
Parser& p = *_port.parser();
int chn_i = chn; int chn_i = chn;
switch (ev) { switch (ev) {
case MIDI::off: 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, /* if this is a togglee, connect to noteOn as well,
and we'll toggle back and forth between the two. and we'll toggle back and forth between the two.
*/ */
if (_momentary) { 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"; _control_description = "MIDI control: NoteOff";
break; break;
case MIDI::on: 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) { 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"; _control_description = "MIDI control: NoteOn";
break; break;
case MIDI::controller: 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); snprintf (buf, sizeof (buf), "MIDI control: Controller %d", control_additional);
_control_description = buf; _control_description = buf;
break; break;
case MIDI::program: 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"; _control_description = "MIDI control: ProgramChange";
break; break;
case MIDI::pitchbend: 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"; _control_description = "MIDI control: Pitchbend";
break; break;

View file

@ -36,17 +36,20 @@ namespace PBD {
namespace MIDI { namespace MIDI {
class Channel; class Channel;
class Port;
class Parser; class Parser;
} }
class GenericMidiControlProtocol; class GenericMidiControlProtocol;
namespace ARDOUR {
class AsyncMIDIPort;
}
class MIDIControllable : public PBD::Stateful class MIDIControllable : public PBD::Stateful
{ {
public: public:
MIDIControllable (GenericMidiControlProtocol *, MIDI::Port&, PBD::Controllable&, bool momentary); MIDIControllable (GenericMidiControlProtocol *, MIDI::Parser&, PBD::Controllable&, bool momentary);
MIDIControllable (GenericMidiControlProtocol *, MIDI::Port&, bool momentary = false); MIDIControllable (GenericMidiControlProtocol *, MIDI::Parser&, bool momentary = false);
virtual ~MIDIControllable (); virtual ~MIDIControllable ();
int init (const std::string&); int init (const std::string&);
@ -72,7 +75,7 @@ class MIDIControllable : public PBD::Stateful
bool learned() const { return _learned; } 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; } PBD::Controllable* get_controllable() const { return controllable; }
void set_controllable (PBD::Controllable*); void set_controllable (PBD::Controllable*);
const std::string& current_uri() const { return _current_uri; } const std::string& current_uri() const { return _current_uri; }
@ -98,8 +101,8 @@ class MIDIControllable : public PBD::Stateful
GenericMidiControlProtocol* _surface; GenericMidiControlProtocol* _surface;
PBD::Controllable* controllable; PBD::Controllable* controllable;
PBD::ControllableDescriptor* _descriptor; PBD::ControllableDescriptor* _descriptor;
std::string _current_uri; std::string _current_uri;
MIDI::Port& _port; MIDI::Parser& _parser;
bool setting; bool setting;
int last_value; int last_value;
float last_controllable_value; float last_controllable_value;

View file

@ -25,7 +25,7 @@
using namespace MIDI; using namespace MIDI;
MIDIFunction::MIDIFunction (MIDI::Port& p) MIDIFunction::MIDIFunction (MIDI::Parser& p)
: MIDIInvokable (p) : MIDIInvokable (p)
{ {
} }

View file

@ -33,7 +33,6 @@
namespace MIDI { namespace MIDI {
class Channel; class Channel;
class Port;
class Parser; class Parser;
} }
@ -64,7 +63,7 @@ class MIDIFunction : public MIDIInvokable
TrackSetSoloIsolate, TrackSetSoloIsolate,
}; };
MIDIFunction (MIDI::Port&); MIDIFunction (MIDI::Parser&);
virtual ~MIDIFunction (); virtual ~MIDIFunction ();
int setup (GenericMidiControlProtocol&, const std::string& function_name, const std::string& argument, MIDI::byte* sysex = 0, size_t ssize = 0); int setup (GenericMidiControlProtocol&, const std::string& function_name, const std::string& argument, MIDI::byte* sysex = 0, size_t ssize = 0);

View file

@ -25,8 +25,8 @@
using namespace MIDI; using namespace MIDI;
MIDIInvokable::MIDIInvokable (MIDI::Port& p) MIDIInvokable::MIDIInvokable (MIDI::Parser& p)
: _port (p) : _parser (p)
{ {
data_size = 0; data_size = 0;
data = 0; data = 0;
@ -127,12 +127,6 @@ MIDIInvokable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
control_channel = chn; control_channel = chn;
control_additional = additional; control_additional = additional;
if (_port.parser() == 0) {
return;
}
Parser& p = *_port.parser();
int chn_i = chn; 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 /* 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) { switch (ev) {
case MIDI::off: 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; break;
case MIDI::on: 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; break;
case MIDI::controller: 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; break;
case MIDI::program: 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; break;
case MIDI::sysex: 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; break;
case MIDI::any: 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; break;
default: default:

View file

@ -31,7 +31,6 @@
namespace MIDI { namespace MIDI {
class Channel; class Channel;
class Port;
class Parser; class Parser;
} }
@ -40,12 +39,12 @@ class GenericMidiControlProtocol;
class MIDIInvokable : public PBD::Stateful class MIDIInvokable : public PBD::Stateful
{ {
public: public:
MIDIInvokable (MIDI::Port&); MIDIInvokable (MIDI::Parser&);
virtual ~MIDIInvokable (); virtual ~MIDIInvokable ();
virtual int init (GenericMidiControlProtocol&, const std::string&, MIDI::byte* data = 0, size_t dsize = 0); 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); void bind_midi (MIDI::channel_t, MIDI::eventType, MIDI::byte);
MIDI::channel_t get_control_channel () { return control_channel; } MIDI::channel_t get_control_channel () { return control_channel; }
@ -55,7 +54,7 @@ class MIDIInvokable : public PBD::Stateful
protected: protected:
GenericMidiControlProtocol* _ui; GenericMidiControlProtocol* _ui;
std::string _invokable_name; std::string _invokable_name;
MIDI::Port& _port; MIDI::Parser& _parser;
PBD::ScopedConnection midi_sense_connection[2]; PBD::ScopedConnection midi_sense_connection[2];
MIDI::eventType control_type; MIDI::eventType control_type;
MIDI::byte control_additional; MIDI::byte control_additional;

View file

@ -24,7 +24,6 @@
#include <cmath> #include <cmath>
#include "midi++/port.h" #include "midi++/port.h"
#include "midi++/manager.h"
#include "ardour/automation_control.h" #include "ardour/automation_control.h"
#include "ardour/debug.h" #include "ardour/debug.h"

View file

@ -24,27 +24,27 @@
#include <boost/shared_array.hpp> #include <boost/shared_array.hpp>
#include "midi++/types.h" #include "midi++/types.h"
#include "midi++/port.h"
#include "midi++/jack_midi_port.h"
#include "midi++/ipmidi_port.h" #include "midi++/ipmidi_port.h"
#include "midi++/manager.h"
#include "ardour/async_midi_port.h"
#include "ardour/debug.h" #include "ardour/debug.h"
#include "ardour/rc_configuration.h" #include "ardour/rc_configuration.h"
#include "ardour/session.h" #include "ardour/session.h"
#include "ardour/audioengine.h" #include "ardour/audioengine.h"
#include "ardour/async_midi_port.h"
#include "ardour/midiport_manager.h"
#include "controls.h" #include "controls.h"
#include "mackie_control_protocol.h" #include "mackie_control_protocol.h"
#include "surface.h" #include "surface.h"
#include "surface_port.h" #include "surface_port.h"
#include "i18n.h" #include "i18n.h"
using namespace std; using namespace std;
using namespace Mackie; using namespace Mackie;
using namespace PBD; using namespace PBD;
using namespace ARDOUR;
/** @param input_port Input MIDI::Port; this object takes responsibility for /** @param input_port Input MIDI::Port; this object takes responsibility for
* adding & removing it from the MIDI::Manager and destroying it. @param * adding & removing it from the MIDI::Manager and destroying it. @param
@ -52,31 +52,16 @@ using namespace PBD;
*/ */
SurfacePort::SurfacePort (Surface& s) SurfacePort::SurfacePort (Surface& s)
: _surface (&s) : _surface (&s)
, _input_port (0)
, _output_port (0)
{ {
if (_surface->mcp().device_info().uses_ipmidi()) { if (_surface->mcp().device_info().uses_ipmidi()) {
_input_port = new MIDI::IPMIDIPort (_surface->mcp().ipmidi_base() +_surface->number()); _input_port = new MIDI::IPMIDIPort (_surface->mcp().ipmidi_base() +_surface->number());
_output_port = _input_port; _output_port = _input_port;
} else { } else {
ARDOUR::PortEngine& port_engine (ARDOUR::AudioEngine::instance()->port_engine()); _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 = new MIDI::JackMIDIPort (string_compose (_("%1 in"), _surface->name()), MIDI::Port::IsInput, port_engine); _input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in).get();
_output_port =new MIDI::JackMIDIPort (string_compose (_("%1 out"), _surface->name()), MIDI::Port::IsOutput, port_engine); _output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_out).get();
/* 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);
} }
} }
@ -86,17 +71,15 @@ SurfacePort::~SurfacePort()
delete _input_port; delete _input_port;
} else { } else {
MIDI::Manager* mm = MIDI::Manager::instance (); if (_async_in) {
AudioEngine::instance()->unregister_port (_async_in);
if (_input_port) { _async_in.reset ();
mm->remove_port (_input_port);
delete _input_port;
} }
if (_output_port) { if (_async_out) {
_output_port->drain (10000); _output_port->drain (10000);
mm->remove_port (_output_port); AudioEngine::instance()->unregister_port (_async_out);
delete _output_port; _async_out.reset ();
} }
} }
} }

View file

@ -21,16 +21,23 @@
#include <midi++/types.h> #include <midi++/types.h>
#include "pbd/signals.h" #include "pbd/signals.h"
#include "midi_byte_array.h" #include "midi_byte_array.h"
#include "types.h" #include "types.h"
namespace MIDI { namespace MIDI {
class Port;
class Parser; class Parser;
class Port;
} }
class MackieControlProtocol; class MackieControlProtocol;
namespace ARDOUR {
class AsyncMIDIPort;
class Port;
}
namespace Mackie namespace Mackie
{ {
@ -49,17 +56,17 @@ public:
/// an easier way to output bytes via midi /// an easier way to output bytes via midi
int write (const MidiByteArray&); int write (const MidiByteArray&);
MIDI::Port& input_port() { return *_input_port; } MIDI::Port& input_port() const { return *_input_port; }
const MIDI::Port& input_port() const { return *_input_port; } MIDI::Port& output_port() const { return *_output_port; }
MIDI::Port& output_port() { return *_output_port; }
const MIDI::Port& output_port() const { return *_output_port; }
protected: protected:
private: private:
Mackie::Surface* _surface; Mackie::Surface* _surface;
MIDI::Port* _input_port; MIDI::Port* _input_port;
MIDI::Port* _output_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); std::ostream& operator << (std::ostream& , const SurfacePort& port);