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

View File

@ -1258,7 +1258,8 @@ Editor::set_session (Session *t)
/* These signals can all be emitted by a non-GUI thread. Therefore the
handlers for them must not attempt to directly interact with the GUI,
but use Gtkmm2ext::UI::instance()->call_slot();
but use PBD::Signal<T>::connect() which accepts an event loop
("context") where the handler will be asked to run.
*/
_session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());

View File

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

View File

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

View File

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

View File

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

View File

@ -24,7 +24,10 @@
#include <time.h>
#include "midi++/parser.h"
#include "midi++/manager.h"
#include "ardour/async_midi_port.h"
#include "ardour/midi_port.h"
#include "ardour/audioengine.h"
#include "midi_tracer.h"
#include "gui_thread.h"
@ -53,7 +56,8 @@ MidiTracer::MidiTracer ()
, collect_button (_("Enabled"))
, delta_time_button (_("Delta times"))
{
Manager::instance()->PortsChanged.connect (_manager_connection, invalidator (*this), boost::bind (&MidiTracer::ports_changed, this), gui_context());
ARDOUR::AudioEngine::instance()->PortRegisteredOrUnregistered.connect
(_manager_connection, invalidator (*this), boost::bind (&MidiTracer::ports_changed, this), gui_context());
_last_receipt.tv_sec = 0;
_last_receipt.tv_usec = 0;
@ -126,25 +130,50 @@ MidiTracer::ports_changed ()
{
string const c = _port_combo.get_active_text ();
_port_combo.clear ();
ARDOUR::PortManager::PortList pl;
ARDOUR::AudioEngine::instance()->get_ports (ARDOUR::DataType::MIDI, pl);
boost::shared_ptr<const Manager::PortList> p = Manager::instance()->get_midi_ports ();
for (Manager::PortList::const_iterator i = p->begin(); i != p->end(); ++i) {
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.set_active_text (c);
if (c.empty()) {
_port_combo.set_active_text (pl.front()->name());
} else {
_port_combo.set_active_text (c);
}
}
void
MidiTracer::port_changed ()
{
using namespace ARDOUR;
disconnect ();
Port* p = Manager::instance()->port (_port_combo.get_active_text());
boost::shared_ptr<ARDOUR::Port> p = AudioEngine::instance()->get_port_by_name (_port_combo.get_active_text());
if (p) {
p->parser()->any.connect_same_thread (_parser_connection, boost::bind (&MidiTracer::tracer, this, _1, _2, _3));
if (!p) {
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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -63,6 +63,7 @@ namespace PBD {
extern uint64_t OrderKeys;
extern uint64_t Automation;
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;
mutable DriverDeviceMap all_devices;
PBD::ScopedConnection disconnect_connection;
};
} // namespace

View File

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

View File

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

View File

@ -32,15 +32,17 @@
#include "pbd/rcu.h"
#include "ardour/chan_count.h"
#include "ardour/midiport_manager.h"
#include "ardour/port.h"
#include "ardour/port_engine.h"
namespace ARDOUR {
class PortManager
class PortManager : public MidiPortManager
{
public:
typedef std::map<std::string,boost::shared_ptr<Port> > Ports;
typedef std::list<boost::shared_ptr<Port> > PortList;
PortManager ();
virtual ~PortManager() {}
@ -53,8 +55,8 @@ class PortManager
/* Port registration */
boost::shared_ptr<Port> register_input_port (DataType, const std::string& portname);
boost::shared_ptr<Port> register_output_port (DataType, const std::string& portname);
boost::shared_ptr<Port> register_input_port (DataType, const std::string& portname, bool async = false);
boost::shared_ptr<Port> register_output_port (DataType, const std::string& portname, bool async = false);
int unregister_port (boost::shared_ptr<Port>);
/* Port connectivity */
@ -87,7 +89,8 @@ class PortManager
ChanCount n_physical_inputs () const;
int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>&);
int get_ports (DataType, PortList&);
void remove_all_ports ();
/* per-Port monitoring */
@ -135,9 +138,31 @@ class PortManager
SerializedRCUManager<Ports> ports;
bool _port_remove_in_progress;
boost::shared_ptr<Port> register_port (DataType type, const std::string& portname, bool input);
boost::shared_ptr<Port> register_port (DataType type, const std::string& portname, bool input, bool async = false);
void port_registration_failure (const std::string& portname);
/** List of ports to be used between ::cycle_start() and ::cycle_end()
*/
boost::shared_ptr<Ports> _cycle_ports;
void fade_out (gain_t, gain_t, pframes_t);
void silence (pframes_t nframes);
void check_monitoring ();
/** Signal the start of an audio cycle.
* This MUST be called before any reading/writing for this cycle.
* Realtime safe.
*/
void cycle_start (pframes_t nframes);
/** Signal the end of an audio cycle.
* This signifies that the cycle began with @ref cycle_start has ended.
* This MUST be called at the end of each cycle.
* Realtime safe.
*/
void cycle_end (pframes_t nframes);
};
} // namespace

View File

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

View File

@ -40,15 +40,12 @@
#define PLUSMINUS(A) ( ((A)<0) ? "-" : (((A)>0) ? "+" : "\u00B1") )
#define LEADINGZERO(A) ( (A)<10 ? " " : (A)<100 ? " " : (A)<1000 ? " " : "" )
namespace MIDI {
class Port;
}
namespace ARDOUR {
class TempoMap;
class Session;
class AudioEngine;
class MidiPort;
/**
* @class Slave
@ -67,6 +64,15 @@ class Slave {
Slave() { }
virtual ~Slave() {}
/** The slave should read any incoming information in this method
* and use it adjust its current idea of reality. If no such
* processing is required, it does need to be implemented.
*
* @param nframes specifies the number of frames-worth of data that
* can be read from any ports used by the slave.
*/
virtual int process (pframes_t) { return 0; }
/**
* This is the most important function to implement:
* Each process cycle, Session::follow_slave will call this method.
@ -253,10 +259,11 @@ class TimecodeSlave : public Slave {
class MTC_Slave : public TimecodeSlave {
public:
MTC_Slave (Session&, MIDI::Port&);
MTC_Slave (Session&, MidiPort&);
~MTC_Slave ();
void rebind (MIDI::Port&);
void rebind (MidiPort&);
int process (pframes_t);
bool speed_and_position (double&, framepos_t&);
bool locked() const;
@ -274,7 +281,8 @@ class MTC_Slave : public TimecodeSlave {
private:
Session& session;
MIDI::Port* port;
MidiPort* port;
MIDI::Parser parser;
PBD::ScopedConnectionList port_connections;
PBD::ScopedConnection config_connection;
bool can_notify_on_unknown_rate;
@ -405,13 +413,14 @@ public:
class MIDIClock_Slave : public Slave {
public:
MIDIClock_Slave (Session&, MIDI::Port&, int ppqn = 24);
MIDIClock_Slave (Session&, MidiPort&, int ppqn = 24);
/// Constructor for unit tests
MIDIClock_Slave (ISlaveSessionProxy* session_proxy = 0, int ppqn = 24);
~MIDIClock_Slave ();
void rebind (MIDI::Port&);
void rebind (MidiPort&);
int process (pframes_t);
bool speed_and_position (double&, framepos_t&);
bool locked() const;
@ -427,7 +436,8 @@ class MIDIClock_Slave : public Slave {
protected:
ISlaveSessionProxy* session;
MIDI::Port* port;
MidiPort* port;
MIDI::Parser parser;
PBD::ScopedConnectionList port_connections;
/// pulses per quarter note for one MIDI clock frame (default 24)

View File

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

View File

@ -37,10 +37,9 @@
#include <jack/weakjack.h>
#include "midi++/port.h"
#include "midi++/jack_midi_port.h"
#include "midi++/mmc.h"
#include "midi++/manager.h"
#include "ardour/async_midi_port.h"
#include "ardour/audio_port.h"
#include "ardour/audio_backend.h"
#include "ardour/audioengine.h"
@ -50,6 +49,7 @@
#include "ardour/internal_send.h"
#include "ardour/meter.h"
#include "ardour/midi_port.h"
#include "ardour/midiport_manager.h"
#include "ardour/port.h"
#include "ardour/process_thread.h"
#include "ardour/session.h"
@ -66,10 +66,11 @@ AudioEngine* AudioEngine::_instance = 0;
AudioEngine::AudioEngine ()
: session_remove_pending (false)
, session_removal_countdown (-1)
, _running (false)
, _freewheeling (false)
, monitor_check_interval (INT32_MAX)
, last_monitor_check (0)
, _processed_frames (0)
, _freewheeling (false)
, _pre_freewheel_mmc_enabled (false)
, m_meter_thread (0)
, _main_thread (0)
@ -117,7 +118,7 @@ _thread_init_callback (void * /*arg*/)
SessionEvent::create_per_thread_pool (X_("Audioengine"), 512);
MIDI::JackMIDIPort::set_process_thread (pthread_self());
AsyncMIDIPort::set_process_thread (pthread_self());
}
void
@ -231,8 +232,8 @@ AudioEngine::process_callback (pframes_t nframes)
if (_session == 0) {
if (!_freewheeling) {
MIDI::Manager::instance()->cycle_start(nframes);
MIDI::Manager::instance()->cycle_end();
PortManager::cycle_start (nframes);
PortManager::cycle_end (nframes);
}
_processed_frames = next_processed_frames;
@ -243,34 +244,22 @@ AudioEngine::process_callback (pframes_t nframes)
/* tell all relevant objects that we're starting a new cycle */
InternalSend::CycleStart (nframes);
Port::set_global_port_buffer_offset (0);
Port::set_cycle_framecnt (nframes);
/* tell all Ports that we're starting a new cycle */
boost::shared_ptr<Ports> p = ports.reader();
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
i->second->cycle_start (nframes);
}
PortManager::cycle_start (nframes);
/* test if we are freewheeling and there are freewheel signals connected.
ardour should act normally even when freewheeling unless /it/ is
exporting
exporting (which is what Freewheel.empty() tests for).
*/
if (_freewheeling && !Freewheel.empty()) {
Freewheel (nframes);
} else {
MIDI::Manager::instance()->cycle_start(nframes);
if (_session) {
_session->process (nframes);
}
MIDI::Manager::instance()->cycle_end();
}
if (_freewheeling) {
@ -283,52 +272,18 @@ AudioEngine::process_callback (pframes_t nframes)
}
if (last_monitor_check + monitor_check_interval < next_processed_frames) {
boost::shared_ptr<Ports> p = ports.reader();
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
bool x;
if (i->second->last_monitor() != (x = i->second->monitoring_input ())) {
i->second->set_last_monitor (x);
/* XXX I think this is dangerous, due to
a likely mutex in the signal handlers ...
*/
i->second->MonitorInputChanged (x); /* EMIT SIGNAL */
}
}
PortManager::check_monitoring ();
last_monitor_check = next_processed_frames;
}
if (_session->silent()) {
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
if (i->second->sends_output()) {
i->second->get_buffer(nframes).silence(nframes);
}
}
PortManager::silence (nframes);
}
if (session_remove_pending && session_removal_countdown) {
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
if (i->second->sends_output()) {
boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
if (ap) {
Sample* s = ap->engine_get_whole_audio_buffer ();
gain_t g = session_removal_gain;
for (pframes_t n = 0; n < nframes; ++n) {
*s++ *= g;
g -= session_removal_gain_step;
}
}
}
}
PortManager::fade_out (session_removal_gain, session_removal_gain_step, nframes);
if (session_removal_countdown > nframes) {
session_removal_countdown -= nframes;
@ -339,11 +294,7 @@ AudioEngine::process_callback (pframes_t nframes)
session_removal_gain -= (nframes * session_removal_gain_step);
}
// Finalize ports
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
i->second->cycle_end (nframes);
}
PortManager::cycle_end (nframes);
_processed_frames = next_processed_frames;
@ -574,7 +525,7 @@ AudioEngine::set_backend (const std::string& name, const std::string& arg1, cons
}
drop_backend ();
try {
cerr << "Instantiate " << b->second->name << " with " << arg1 << " + " << arg2 << endl;
@ -603,31 +554,45 @@ AudioEngine::start ()
return -1;
}
if (!_running) {
if (_running) {
return 0;
}
if (_session) {
BootMessage (_("Connect session to engine"));
_session->set_frame_rate (_backend->sample_rate());
}
/* if we're still connected (i.e. previously paused), no need to
* re-register ports.
*/
bool have_ports = (!ports.reader()->empty());
_processed_frames = 0;
_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 (_backend->start() == 0) {
_running = true;
last_monitor_check = 0;
if (_session && _session->config.get_jack_time_master()) {
if (_session->config.get_jack_time_master()) {
_backend->set_time_master (true);
}
Running(); /* EMIT SIGNAL */
} else {
/* should report error? */
}
}
return _running ? 0 : -1;
if (!have_ports) {
PortManager::create_ports ();
}
_mmc.set_ports (mmc_input_port(), mmc_output_port());
Running(); /* EMIT SIGNAL */
return 0;
}
/* should report error ... */
return -1;
}
int
@ -641,6 +606,7 @@ AudioEngine::stop ()
if (_backend->stop () == 0) {
_running = false;
_processed_frames = 0;
stop_metering_thread ();
Stopped (); /* EMIT SIGNAL */
@ -932,7 +898,7 @@ AudioEngine::thread_init_callback (void* arg)
SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
MIDI::JackMIDIPort::set_process_thread (pthread_self());
AsyncMIDIPort::set_process_thread (pthread_self());
if (arg) {
AudioEngine* ae = static_cast<AudioEngine*> (arg);
@ -964,10 +930,10 @@ void
AudioEngine::freewheel_callback (bool onoff)
{
if (onoff) {
_pre_freewheel_mmc_enabled = MIDI::Manager::instance()->mmc()->send_enabled ();
MIDI::Manager::instance()->mmc()->enable_send (false);
_pre_freewheel_mmc_enabled = _mmc.send_enabled ();
_mmc.enable_send (false);
} else {
MIDI::Manager::instance()->mmc()->enable_send (_pre_freewheel_mmc_enabled);
_mmc.enable_send (_pre_freewheel_mmc_enabled);
}
}
@ -991,8 +957,6 @@ void
AudioEngine::halted_callback (const char* why)
{
stop_metering_thread ();
MIDI::JackMIDIPort::EngineHalted (); /* EMIT SIGNAL */
Halted (why); /* EMIT SIGNAL */
}

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

View File

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

View File

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

View File

@ -135,7 +135,10 @@ JackConnection::close ()
GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
if (_priv_jack) {
return jack_client_close (_priv_jack);
int ret = jack_client_close (_priv_jack);
_jack = 0;
Disconnected (""); /* EMIT SIGNAL */
return ret;
}
return 0;

View File

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

View File

@ -31,6 +31,8 @@
#include "midi++/port.h"
#include "ardour/debug.h"
#include "ardour/midi_buffer.h"
#include "ardour/midi_port.h"
#include "ardour/slave.h"
#include "ardour/tempo.h"
@ -41,13 +43,20 @@ using namespace ARDOUR;
using namespace MIDI;
using namespace PBD;
MIDIClock_Slave::MIDIClock_Slave (Session& s, MIDI::Port& p, int ppqn)
MIDIClock_Slave::MIDIClock_Slave (Session& s, MidiPort& p, int ppqn)
: ppqn (ppqn)
, bandwidth (10.0 / 60.0) // 1 BpM = 1 / 60 Hz
{
session = (ISlaveSessionProxy *) new SlaveSessionProxy(s);
rebind (p);
reset ();
parser.timing.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::update_midi_clock, this, _1, _2));
parser.start.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::start, this, _1, _2));
parser.contineu.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::contineu, this, _1, _2));
parser.stop.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::stop, this, _1, _2));
parser.position.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::position, this, _1, _2, 3));
}
MIDIClock_Slave::MIDIClock_Slave (ISlaveSessionProxy* session_proxy, int ppqn)
@ -63,20 +72,33 @@ MIDIClock_Slave::~MIDIClock_Slave()
delete session;
}
void
MIDIClock_Slave::rebind (MIDI::Port& p)
int
MIDIClock_Slave::process (pframes_t nframes)
{
port_connections.drop_connections();
MidiBuffer& mb (port->get_midi_buffer (nframes));
/* 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;
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

View File

@ -22,11 +22,11 @@
#include "pbd/pthread_utils.h"
#include "midi++/manager.h"
#include "midi++/port.h"
#include "ardour/async_midi_port.h"
#include "ardour/debug.h"
#include "ardour/audioengine.h"
#include "ardour/midi_port.h"
#include "ardour/midiport_manager.h"
#include "ardour/midi_ui.h"
#include "ardour/session.h"
#include "ardour/session_event.h"
@ -48,7 +48,6 @@ MidiControlUI::MidiControlUI (Session& s)
: AbstractUI<MidiUIRequest> (X_("midiui"))
, _session (s)
{
MIDI::Manager::instance()->PortsChanged.connect_same_thread (rebind_connection, boost::bind (&MidiControlUI::change_midi_ports, this));
_instance = this;
}
@ -83,20 +82,10 @@ MidiControlUI::do_request (MidiUIRequest* req)
}
}
void
MidiControlUI::change_midi_ports ()
{
MidiUIRequest* req = get_request (PortChange);
if (req == 0) {
return;
}
send_request (req);
}
bool
MidiControlUI::midi_input_handler (IOCondition ioc, MIDI::Port* port)
MidiControlUI::midi_input_handler (IOCondition ioc, AsyncMIDIPort* port)
{
DEBUG_TRACE (DEBUG::MidiIO, string_compose ("something happend on %1\n", port->name()));
DEBUG_TRACE (DEBUG::MidiIO, string_compose ("something happend on %1\n", ((ARDOUR::Port*)port)->name()));
if (ioc & ~IO_IN) {
return false;
@ -106,7 +95,7 @@ MidiControlUI::midi_input_handler (IOCondition ioc, MIDI::Port* port)
CrossThreadChannel::drain (port->selectable());
DEBUG_TRACE (DEBUG::MidiIO, string_compose ("data available on %1\n", port->name()));
DEBUG_TRACE (DEBUG::MidiIO, string_compose ("data available on %1\n", ((ARDOUR::Port*)port)->name()));
framepos_t now = _session.engine().sample_time();
port->parse (now);
}
@ -128,22 +117,19 @@ MidiControlUI::clear_ports ()
void
MidiControlUI::reset_ports ()
{
clear_ports ();
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 ();
for (MIDI::Manager::PortList::const_iterator i = plist->begin(); i != plist->end(); ++i) {
if (!(*i)->centrally_parsed()) {
continue;
if (!async) {
return;
}
int fd;
if ((fd = (*i)->selectable ()) >= 0) {
if ((fd = async->selectable ()) >= 0) {
Glib::RefPtr<IOSource> psrc = IOSource::create (fd, IO_IN|IO_HUP|IO_ERR);
psrc->connect (sigc::bind (sigc::mem_fun (this, &MidiControlUI::midi_input_handler), *i));
psrc->connect (sigc::bind (sigc::mem_fun (this, &MidiControlUI::midi_input_handler), async));
psrc->attach (_main_loop->get_context());
// glibmm hack: for now, store only the GSource*

View File

@ -66,11 +66,47 @@ MidiPortManager::port (string const & n)
void
MidiPortManager::create_ports ()
{
_midi_in = AudioEngine::instance()->register_input_port (DataType::MIDI, _("MIDI control in"), true);
_midi_out = AudioEngine::instance()->register_output_port (DataType::MIDI, _("MIDI control out"), true);
/* this method is idempotent
*/
if (_midi_in) {
return;
}
_midi_in = AudioEngine::instance()->register_input_port (DataType::MIDI, _("control in"), true);
_midi_out = AudioEngine::instance()->register_output_port (DataType::MIDI, _("control out"), true);
_mmc_in = AudioEngine::instance()->register_input_port (DataType::MIDI, _("mmc in"), true);
_mmc_out = AudioEngine::instance()->register_output_port (DataType::MIDI, _("mmc out"), true);
/* XXX nasty type conversion needed because of the mixed inheritance
* required to integrate MIDI::IPMidiPort and ARDOUR::AsyncMIDIPort.
*
* At some point, we'll move IPMidiPort into Ardour and make it
* inherit from ARDOUR::MidiPort not MIDI::Port, and then this
* mess can go away
*/
_midi_input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_midi_in).get();
_midi_output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_midi_out).get();
_mmc_input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_mmc_in).get();
_mmc_output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_mmc_out).get();
/* Now register ports used for sync (MTC and MIDI Clock)
*/
boost::shared_ptr<ARDOUR::Port> p;
p = AudioEngine::instance()->register_input_port (DataType::MIDI, _("timecode in"));
_mtc_input_port = boost::dynamic_pointer_cast<MidiPort> (p);
p = AudioEngine::instance()->register_output_port (DataType::MIDI, _("timecode out"));
_mtc_output_port= boost::dynamic_pointer_cast<MidiPort> (p);
p = AudioEngine::instance()->register_input_port (DataType::MIDI, _("clock in"));
_midi_clock_input_port = boost::dynamic_pointer_cast<MidiPort> (p);
p = AudioEngine::instance()->register_output_port (DataType::MIDI, _("clock out"));
_midi_clock_output_port= boost::dynamic_pointer_cast<MidiPort> (p);
}
void

View File

@ -25,11 +25,12 @@
#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/debug.h"
#include "ardour/midi_buffer.h"
#include "ardour/midi_port.h"
#include "ardour/session.h"
#include "ardour/slave.h"
#include "i18n.h"
@ -48,8 +49,9 @@ using namespace Timecode;
*/
const int MTC_Slave::frame_tolerance = 2;
MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
MTC_Slave::MTC_Slave (Session& s, MidiPort& p)
: session (s)
, port (&p)
{
can_notify_on_unknown_rate = true;
did_reset_tc_format = false;
@ -70,7 +72,11 @@ MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
session.config.ParameterChanged.connect_same_thread (config_connection, boost::bind (&MTC_Slave::parameter_changed, this, _1));
parse_timecode_offset();
reset (true);
rebind (p);
parser.mtc_time.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_time, this, _1, _2, _3));
parser.mtc_qtr.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_qtr, this, _1, _2, _3));
parser.mtc_status.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_status, this, _1));
}
MTC_Slave::~MTC_Slave()
@ -93,16 +99,35 @@ MTC_Slave::~MTC_Slave()
}
}
int
MTC_Slave::process (pframes_t nframes)
{
MidiBuffer& mb (port->get_midi_buffer (nframes));
/* dump incoming MIDI to parser */
for (MidiBuffer::iterator b = mb.begin(); b != mb.end(); ++b) {
uint8_t* buf = (*b).buffer();
parser.set_timestamp ((*b).time());
uint32_t limit = (*b).size();
for (size_t n = 0; n < limit; ++n) {
parser.scanner (buf[n]);
}
}
return 0;
}
void
MTC_Slave::rebind (MIDI::Port& p)
MTC_Slave::rebind (MidiPort& p)
{
port_connections.drop_connections ();
port = &p;
port->parser()->mtc_time.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_time, this, _1, _2, _3));
port->parser()->mtc_qtr.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_qtr, this, _1, _2, _3));
port->parser()->mtc_status.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_status, this, _1));
}
void
@ -154,7 +179,7 @@ MTC_Slave::outside_window (framepos_t pos) const
bool
MTC_Slave::locked () const
{
return port->parser()->mtc_locked() && last_inbound_frame !=0 && engine_dll_initstate !=0;
return parser.mtc_locked() && last_inbound_frame !=0 && engine_dll_initstate !=0;
}
bool
@ -446,7 +471,7 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full, framepos_t now)
DEBUG_TRACE (DEBUG::MTC, string_compose ("new mtc_frame: %1 | MTC-FpT: %2 A3-FpT:%3\n",
mtc_frame, (4.0*qtr), session.frames_per_timecode_frame()));
switch (port->parser()->mtc_running()) {
switch (parser.mtc_running()) {
case MTC_Backward:
mtc_frame -= mtc_off;
qtr *= -1.0;
@ -528,7 +553,7 @@ MTC_Slave::reset_window (framepos_t root)
*/
framecnt_t const d = (quarter_frame_duration * 4 * frame_tolerance);
switch (port->parser()->mtc_running()) {
switch (parser.mtc_running()) {
case MTC_Forward:
window_begin = root;
transport_direction = 1;

View File

@ -390,6 +390,7 @@ Port::get_connected_latency_range (LatencyRange& range, bool playback) const
int
Port::reestablish ()
{
DEBUG_TRACE (DEBUG::Ports, string_compose ("re-establish %1 port %2\n", type().to_string(), _name));
_port_handle = port_engine.register_port (_name, type(), _flags);
if (_port_handle == 0) {

View File

@ -19,11 +19,12 @@
#include "pbd/error.h"
#include "midi++/manager.h"
#include "ardour/async_midi_port.h"
#include "ardour/debug.h"
#include "ardour/port_manager.h"
#include "ardour/audio_port.h"
#include "ardour/midi_port.h"
#include "ardour/midiport_manager.h"
#include "i18n.h"
@ -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
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>
PortManager::register_port (DataType dtype, const string& portname, bool input)
PortManager::register_port (DataType dtype, const string& portname, bool input, bool async)
{
boost::shared_ptr<Port> newport;
try {
if (dtype == DataType::AUDIO) {
DEBUG_TRACE (DEBUG::Ports, string_compose ("registering AUDIO port %1, input %2\n",
portname, input));
newport.reset (new AudioPort (portname, (input ? IsInput : IsOutput)));
} else if (dtype == DataType::MIDI) {
newport.reset (new MidiPort (portname, (input ? IsInput : IsOutput)));
if (async) {
DEBUG_TRACE (DEBUG::Ports, string_compose ("registering ASYNC MIDI port %1, input %2\n",
portname, input));
newport.reset (new AsyncMIDIPort (portname, (input ? IsInput : IsOutput)));
} else {
DEBUG_TRACE (DEBUG::Ports, string_compose ("registering MIDI port %1, input %2\n",
portname, input));
newport.reset (new MidiPort (portname, (input ? IsInput : IsOutput)));
}
} else {
throw PortRegistrationFailure("unable to create port (unknown type)");
}
@ -281,7 +304,6 @@ PortManager::register_port (DataType dtype, const string& portname, bool input)
/* writer goes out of scope, forces update */
return newport;
}
catch (PortRegistrationFailure& err) {
@ -292,18 +314,21 @@ PortManager::register_port (DataType dtype, const string& portname, bool input)
} catch (...) {
throw PortRegistrationFailure("unable to create port (unknown error)");
}
DEBUG_TRACE (DEBUG::Ports, string_compose ("\t%2 port registration success, ports now = %1\n", ports.reader()->size(), this));
return newport;
}
boost::shared_ptr<Port>
PortManager::register_input_port (DataType type, const string& portname)
PortManager::register_input_port (DataType type, const string& portname, bool async)
{
return register_port (type, portname, true);
return register_port (type, portname, true, async);
}
boost::shared_ptr<Port>
PortManager::register_output_port (DataType type, const string& portname)
PortManager::register_output_port (DataType type, const string& portname, bool async)
{
return register_port (type, portname, false);
return register_port (type, portname, false, async);
}
int
@ -410,6 +435,8 @@ PortManager::reestablish_ports ()
boost::shared_ptr<Ports> p = ports.reader ();
DEBUG_TRACE (DEBUG::Ports, string_compose ("reestablish %1 ports\n", p->size()));
for (i = p->begin(); i != p->end(); ++i) {
if (i->second->reestablish ()) {
break;
@ -422,8 +449,6 @@ PortManager::reestablish_ports ()
return -1;
}
MIDI::Manager::instance()->reestablish ();
return 0;
}
@ -434,12 +459,12 @@ PortManager::reconnect_ports ()
/* re-establish connections */
DEBUG_TRACE (DEBUG::Ports, string_compose ("reconnect %1 ports\n", p->size()));
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
i->second->reconnect ();
}
MIDI::Manager::instance()->reconnect ();
return 0;
}
@ -543,3 +568,80 @@ PortManager::graph_order_callback ()
return 0;
}
void
PortManager::cycle_start (pframes_t nframes)
{
Port::set_global_port_buffer_offset (0);
Port::set_cycle_framecnt (nframes);
_cycle_ports = ports.reader ();
for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
p->second->cycle_start (nframes);
}
}
void
PortManager::cycle_end (pframes_t nframes)
{
for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
p->second->cycle_end (nframes);
}
for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
p->second->flush_buffers (nframes);
}
_cycle_ports.reset ();
/* we are done */
}
void
PortManager::silence (pframes_t nframes)
{
for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
if (i->second->sends_output()) {
i->second->get_buffer(nframes).silence(nframes);
}
}
}
void
PortManager::check_monitoring ()
{
for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
bool x;
if (i->second->last_monitor() != (x = i->second->monitoring_input ())) {
i->second->set_last_monitor (x);
/* XXX I think this is dangerous, due to
a likely mutex in the signal handlers ...
*/
i->second->MonitorInputChanged (x); /* EMIT SIGNAL */
}
}
}
void
PortManager::fade_out (gain_t base_gain, gain_t gain_step, pframes_t nframes)
{
for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
if (i->second->sends_output()) {
boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
if (ap) {
Sample* s = ap->engine_get_whole_audio_buffer ();
gain_t g = base_gain;
for (pframes_t n = 0; n < nframes; ++n) {
*s++ *= g;
g -= gain_step;
}
}
}
}
}

View File

@ -27,13 +27,12 @@
#include "pbd/xml++.h"
#include "pbd/file_utils.h"
#include "midi++/manager.h"
#include "ardour/control_protocol_manager.h"
#include "ardour/diskstream.h"
#include "ardour/filesystem_paths.h"
#include "ardour/rc_configuration.h"
#include "ardour/session_metadata.h"
#include "ardour/midiport_manager.h"
#include "i18n.h"
@ -177,15 +176,20 @@ RCConfiguration::get_state ()
root = new XMLNode("Ardour");
MIDI::Manager* mm = MIDI::Manager::instance();
/* XXX
* GET STATE OF MIDI::Port HERE
*/
#if 0
MidiPortManager* mm = MidiPortManager::instance();
if (mm) {
boost::shared_ptr<const MIDI::Manager::PortList> ports = mm->get_midi_ports();
boost::shared_ptr<const MidiPortManager::PortList> ports = mm->get_midi_ports();
for (MIDI::Manager::PortList::const_iterator i = ports->begin(); i != ports->end(); ++i) {
root->add_child_nocopy((*i)->get_state());
for (MidiPortManager::PortList::const_iterator i = ports->begin(); i != ports->end(); ++i) {
// root->add_child_nocopy ((*i)->get_state());
}
}
#endif
root->add_child_nocopy (get_variables ());

View File

@ -49,6 +49,7 @@
#include "ardour/amp.h"
#include "ardour/analyser.h"
#include "ardour/async_midi_port.h"
#include "ardour/audio_buffer.h"
#include "ardour/audio_diskstream.h"
#include "ardour/audio_port.h"
@ -66,6 +67,7 @@
#include "ardour/debug.h"
#include "ardour/filename_extensions.h"
#include "ardour/graph.h"
#include "ardour/midiport_manager.h"
#include "ardour/midi_track.h"
#include "ardour/midi_ui.h"
#include "ardour/operations.h"
@ -88,9 +90,7 @@
#include "ardour/utils.h"
#include "midi++/port.h"
#include "midi++/jack_midi_port.h"
#include "midi++/mmc.h"
#include "midi++/manager.h"
#include "i18n.h"
@ -584,7 +584,8 @@ Session::when_engine_running ()
as it will set states for ports which the ControlProtocolManager creates.
*/
MIDI::Manager::instance()->set_port_states (Config->midi_port_states ());
// XXX set state of MIDI::Port's
// MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
/* And this must be done after the MIDI::Manager::set_port_states as
* it will try to make connections whose details are loaded by set_port_states.
@ -874,7 +875,12 @@ Session::hookup_io ()
/* Tell all IO objects to connect themselves together */
IO::enable_connecting ();
MIDI::JackMIDIPort::MakeConnections ();
/* Now tell all "floating" ports to connect to whatever
they should be connected to.
*/
AudioEngine::instance()->reconnect_ports ();
/* Anyone who cares about input state, wake up and do something */
@ -1169,7 +1175,7 @@ Session::enable_record ()
if (g_atomic_int_compare_and_exchange (&_record_status, rs, Recording)) {
_last_record_location = _transport_frame;
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordStrobe));
AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordStrobe));
if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
set_track_monitor_input_status (true);
@ -1190,7 +1196,7 @@ Session::disable_record (bool rt_context, bool force)
if ((!Config->get_latched_record_enable () && !play_loop) || force) {
g_atomic_int_set (&_record_status, Disabled);
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordExit));
AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordExit));
} else {
if (rs == Recording) {
g_atomic_int_set (&_record_status, Enabled);
@ -1244,7 +1250,7 @@ Session::maybe_enable_record ()
enable_record ();
}
} else {
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordPause));
AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordPause));
RecordStateChanged (); /* EMIT SIGNAL */
}

View File

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

View File

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

View File

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

View File

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

View File

@ -33,7 +33,6 @@
#include "midi++/mmc.h"
#include "midi++/port.h"
#include "midi++/manager.h"
#include "ardour/audioengine.h"
#include "ardour/auditioner.h"
@ -611,10 +610,11 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
have_looped = false;
if (!_engine.freewheeling()) {
send_full_time_code (_transport_frame);
// need to queue this in the next RT cycle
_send_timecode_update = true;
if (!dynamic_cast<MTC_Slave*>(_slave)) {
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
send_mmc_locate (_transport_frame);
}
}
@ -1260,7 +1260,7 @@ Session::start_transport ()
Timecode::Time time;
timecode_time_subframes (_transport_frame, time);
if (!dynamic_cast<MTC_Slave*>(_slave)) {
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
}
}
@ -1338,8 +1338,9 @@ Session::use_sync_source (Slave* new_slave)
_slave = new_slave;
DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
send_full_time_code (_transport_frame);
// need to queue this for next process() cycle
_send_timecode_update = true;
boost::shared_ptr<RouteList> rl = routes.reader();
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
@ -1380,7 +1381,7 @@ Session::switch_to_sync_source (SyncSource src)
}
try {
new_slave = new MTC_Slave (*this, *MIDI::Manager::instance()->mtc_input_port());
new_slave = new MTC_Slave (*this, *AudioEngine::instance()->mtc_input_port());
}
catch (failed_constructor& err) {
@ -1409,7 +1410,7 @@ Session::switch_to_sync_source (SyncSource src)
}
try {
new_slave = new MIDIClock_Slave (*this, *MIDI::Manager::instance()->midi_clock_input_port(), 24);
new_slave = new MIDIClock_Slave (*this, *AudioEngine::instance()->midi_clock_input_port(), 24);
}
catch (failed_constructor& err) {
@ -1636,7 +1637,7 @@ Session::send_mmc_locate (framepos_t t)
if (!_engine.freewheeling()) {
Timecode::Time time;
timecode_time_subframes (t, time);
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (time));
AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (time));
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -51,13 +51,6 @@ class Port {
virtual XMLNode& get_state () const;
virtual void set_state (const XMLNode&);
// FIXME: make Manager a friend of port so these can be hidden?
/* Only for use by MidiManager. Don't ever call this. */
virtual void cycle_start (pframes_t) {}
/* Only for use by MidiManager. Don't ever call this. */
virtual void cycle_end () {}
/** Write a message to port.
* @param msg Raw MIDI message to send
* @param msglen Size of @a msg

View File

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

View File

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

View File

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

View File

@ -32,13 +32,14 @@
#include "pbd/xml++.h"
#include "midi++/port.h"
#include "midi++/manager.h"
#include "ardour/audioengine.h"
#include "ardour/filesystem_paths.h"
#include "ardour/session.h"
#include "ardour/route.h"
#include "ardour/midi_ui.h"
#include "ardour/rc_configuration.h"
#include "ardour/midiport_manager.h"
#include "generic_midi_control_protocol.h"
#include "midicontrollable.h"
@ -59,8 +60,8 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
, _threshold (10)
, gui (0)
{
_input_port = MIDI::Manager::instance()->midi_input_port ();
_output_port = MIDI::Manager::instance()->midi_output_port ();
_input_port = AudioEngine::instance()->midi_input_port ();
_output_port = AudioEngine::instance()->midi_output_port ();
do_feedback = false;
_feedback_interval = 10000; // microseconds
@ -338,7 +339,7 @@ GenericMidiControlProtocol::start_learning (Controllable* c)
}
if (!mc) {
mc = new MIDIControllable (this, *_input_port, *c, false);
mc = new MIDIControllable (this, *_input_port->parser(), *c, false);
}
{
@ -435,7 +436,7 @@ GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos,
MIDI::byte value = control_number;
// Create a MIDIControllable
MIDIControllable* mc = new MIDIControllable (this, *_input_port, *control, false);
MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), *control, false);
// Remove any old binding for this midi channel/type/value pair
// Note: can't use delete_binding() here because we don't know the specific controllable we want to remove, only the midi information
@ -559,7 +560,7 @@ GenericMidiControlProtocol::set_state (const XMLNode& node, int version)
Controllable* c = Controllable::by_id (id);
if (c) {
MIDIControllable* mc = new MIDIControllable (this, *_input_port, *c, false);
MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), *c, false);
if (mc->set_state (**niter, version) == 0) {
controllables.push_back (mc);
@ -754,7 +755,7 @@ GenericMidiControlProtocol::create_binding (const XMLNode& node)
prop = node.property (X_("uri"));
uri = prop->value();
MIDIControllable* mc = new MIDIControllable (this, *_input_port, momentary);
MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), momentary);
if (mc->init (uri)) {
delete mc;
@ -892,7 +893,7 @@ GenericMidiControlProtocol::create_function (const XMLNode& node)
prop = node.property (X_("function"));
MIDIFunction* mf = new MIDIFunction (*_input_port);
MIDIFunction* mf = new MIDIFunction (*_input_port->parser());
if (mf->setup (*this, prop->value(), argument, data, data_size)) {
delete mf;
@ -988,7 +989,7 @@ GenericMidiControlProtocol::create_action (const XMLNode& node)
prop = node.property (X_("action"));
MIDIAction* ma = new MIDIAction (*_input_port);
MIDIAction* ma = new MIDIAction (*_input_port->parser());
if (ma->init (*this, prop->value(), data, data_size)) {
delete ma;

View File

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

View File

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

View File

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

View File

@ -27,9 +27,9 @@
#include "pbd/xml++.h"
#include "pbd/stacktrace.h"
#include "midi++/port.h"
#include "midi++/channel.h"
#include "ardour/async_midi_port.h"
#include "ardour/automation_control.h"
#include "ardour/midi_ui.h"
#include "ardour/utils.h"
@ -42,11 +42,11 @@ using namespace MIDI;
using namespace PBD;
using namespace ARDOUR;
MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, Port& p, bool m)
MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, MIDI::Parser& p, bool m)
: _surface (s)
, controllable (0)
, _descriptor (0)
, _port (p)
, _parser (p)
, _momentary (m)
{
_learned = false; /* from URI */
@ -59,10 +59,10 @@ MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, Port& p, bool
feedback = true; // for now
}
MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, Port& p, Controllable& c, bool m)
MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, MIDI::Parser& p, Controllable& c, bool m)
: _surface (s)
, _descriptor (0)
, _port (p)
, _parser (p)
, _momentary (m)
{
set_controllable (&c);
@ -149,7 +149,7 @@ void
MIDIControllable::learn_about_external_control ()
{
drop_external_control ();
_port.parser()->any.connect_same_thread (midi_learn_connection, boost::bind (&MIDIControllable::midi_receiver, this, _1, _2, _3));
_parser.any.connect_same_thread (midi_learn_connection, boost::bind (&MIDIControllable::midi_receiver, this, _1, _2, _3));
}
void
@ -357,12 +357,6 @@ MIDIControllable::midi_receiver (Parser &, byte *msg, size_t /*len*/)
return;
}
/* if the our port doesn't do input anymore, forget it ... */
if (!_port.parser()) {
return;
}
bind_midi ((channel_t) (msg[0] & 0xf), eventType (msg[0] & 0xF0), msg[1]);
if (controllable) {
@ -381,49 +375,43 @@ MIDIControllable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
control_channel = chn;
control_additional = additional;
if (_port.parser() == 0) {
return;
}
Parser& p = *_port.parser();
int chn_i = chn;
switch (ev) {
case MIDI::off:
p.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2));
_parser.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2));
/* if this is a togglee, connect to noteOn as well,
and we'll toggle back and forth between the two.
*/
if (_momentary) {
p.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2));
_parser.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2));
}
_control_description = "MIDI control: NoteOff";
break;
case MIDI::on:
p.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2));
_parser.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2));
if (_momentary) {
p.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2));
_parser.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2));
}
_control_description = "MIDI control: NoteOn";
break;
case MIDI::controller:
p.channel_controller[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_controller, this, _1, _2));
_parser.channel_controller[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_controller, this, _1, _2));
snprintf (buf, sizeof (buf), "MIDI control: Controller %d", control_additional);
_control_description = buf;
break;
case MIDI::program:
p.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_program_change, this, _1, _2));
_parser.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_program_change, this, _1, _2));
_control_description = "MIDI control: ProgramChange";
break;
case MIDI::pitchbend:
p.channel_pitchbend[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_pitchbend, this, _1, _2));
_parser.channel_pitchbend[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_pitchbend, this, _1, _2));
_control_description = "MIDI control: Pitchbend";
break;

View File

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

View File

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

View File

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

View File

@ -25,8 +25,8 @@
using namespace MIDI;
MIDIInvokable::MIDIInvokable (MIDI::Port& p)
: _port (p)
MIDIInvokable::MIDIInvokable (MIDI::Parser& p)
: _parser (p)
{
data_size = 0;
data = 0;
@ -127,12 +127,6 @@ MIDIInvokable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
control_channel = chn;
control_additional = additional;
if (_port.parser() == 0) {
return;
}
Parser& p = *_port.parser();
int chn_i = chn;
/* incoming MIDI is parsed by Ardour' MidiUI event loop/thread, and we want our handlers to execute in that context, so we use
@ -141,27 +135,27 @@ MIDIInvokable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
switch (ev) {
case MIDI::off:
p.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_note_off, this, _1, _2));
_parser.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_note_off, this, _1, _2));
break;
case MIDI::on:
p.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_note_on, this, _1, _2));
_parser.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_note_on, this, _1, _2));
break;
case MIDI::controller:
p.channel_controller[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_controller, this, _1, _2));
_parser.channel_controller[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_controller, this, _1, _2));
break;
case MIDI::program:
p.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_program_change, this, _1, _2));
_parser.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_program_change, this, _1, _2));
break;
case MIDI::sysex:
p.sysex.connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_sysex, this, _1, _2, _3));
_parser.sysex.connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_sysex, this, _1, _2, _3));
break;
case MIDI::any:
p.any.connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_any, this, _1, _2, _3));
_parser.any.connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_any, this, _1, _2, _3));
break;
default:

View File

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

View File

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

View File

@ -24,27 +24,27 @@
#include <boost/shared_array.hpp>
#include "midi++/types.h"
#include "midi++/port.h"
#include "midi++/jack_midi_port.h"
#include "midi++/ipmidi_port.h"
#include "midi++/manager.h"
#include "ardour/async_midi_port.h"
#include "ardour/debug.h"
#include "ardour/rc_configuration.h"
#include "ardour/session.h"
#include "ardour/audioengine.h"
#include "ardour/async_midi_port.h"
#include "ardour/midiport_manager.h"
#include "controls.h"
#include "mackie_control_protocol.h"
#include "surface.h"
#include "surface_port.h"
#include "i18n.h"
using namespace std;
using namespace Mackie;
using namespace PBD;
using namespace ARDOUR;
/** @param input_port Input MIDI::Port; this object takes responsibility for
* adding & removing it from the MIDI::Manager and destroying it. @param
@ -52,31 +52,16 @@ using namespace PBD;
*/
SurfacePort::SurfacePort (Surface& s)
: _surface (&s)
, _input_port (0)
, _output_port (0)
{
if (_surface->mcp().device_info().uses_ipmidi()) {
_input_port = new MIDI::IPMIDIPort (_surface->mcp().ipmidi_base() +_surface->number());
_output_port = _input_port;
} else {
ARDOUR::PortEngine& port_engine (ARDOUR::AudioEngine::instance()->port_engine());
_input_port = new MIDI::JackMIDIPort (string_compose (_("%1 in"), _surface->name()), MIDI::Port::IsInput, port_engine);
_output_port =new MIDI::JackMIDIPort (string_compose (_("%1 out"), _surface->name()), MIDI::Port::IsOutput, port_engine);
/* MackieControl has its own thread for handling input from the input
* port, and we don't want anything handling output from the output
* port. This stops the Generic MIDI UI event loop in ardour from
* attempting to handle these ports.
*/
_input_port->set_centrally_parsed (false);
_output_port->set_centrally_parsed (false);
MIDI::Manager * mm = MIDI::Manager::instance();
mm->add_port (_input_port);
mm->add_port (_output_port);
_async_in = AudioEngine::instance()->register_input_port (DataType::MIDI, string_compose (_("%1 in"), _surface->name()), true);
_async_out = AudioEngine::instance()->register_output_port (DataType::MIDI, string_compose (_("%1 out"), _surface->name()), true);
_input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in).get();
_output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_out).get();
}
}
@ -86,17 +71,15 @@ SurfacePort::~SurfacePort()
delete _input_port;
} else {
MIDI::Manager* mm = MIDI::Manager::instance ();
if (_input_port) {
mm->remove_port (_input_port);
delete _input_port;
if (_async_in) {
AudioEngine::instance()->unregister_port (_async_in);
_async_in.reset ();
}
if (_output_port) {
if (_async_out) {
_output_port->drain (10000);
mm->remove_port (_output_port);
delete _output_port;
AudioEngine::instance()->unregister_port (_async_out);
_async_out.reset ();
}
}
}

View File

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