major redesign of MIDI port heirarchy and management (part 2)
This commit is contained in:
parent
83a0c30c24
commit
1ab61b8564
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
#include <gtkmm2ext/utils.h>
|
||||
#include <gtkmm2ext/barcontroller.h>
|
||||
#include "midi++/manager.h"
|
||||
#include "pbd/fastlog.h"
|
||||
|
||||
#include "ardour_ui.h"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <gtkmm2ext/utils.h>
|
||||
#include <gtkmm2ext/barcontroller.h>
|
||||
|
||||
#include "midi++/manager.h"
|
||||
#include "pbd/fastlog.h"
|
||||
|
||||
#include "ardour/pannable.h"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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())
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -63,6 +63,7 @@ namespace PBD {
|
|||
extern uint64_t OrderKeys;
|
||||
extern uint64_t Automation;
|
||||
extern uint64_t WiimoteControl;
|
||||
extern uint64_t Ports;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -178,6 +178,8 @@ class JACKAudioBackend : public AudioBackend {
|
|||
typedef std::map<std::string,DeviceList> DriverDeviceMap;
|
||||
|
||||
mutable DriverDeviceMap all_devices;
|
||||
|
||||
PBD::ScopedConnection disconnect_connection;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -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 ();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 ());
|
||||
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -104,8 +104,7 @@ Parser::midi_event_type_name (eventType t)
|
|||
}
|
||||
}
|
||||
|
||||
Parser::Parser (Port &p)
|
||||
: _port(p)
|
||||
Parser::Parser ()
|
||||
{
|
||||
trace_stream = 0;
|
||||
trace_prefix = "";
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
using namespace MIDI;
|
||||
|
||||
MIDIAction::MIDIAction (MIDI::Port& p)
|
||||
MIDIAction::MIDIAction (MIDI::Parser& p)
|
||||
: MIDIInvokable (p)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
using namespace MIDI;
|
||||
|
||||
MIDIFunction::MIDIFunction (MIDI::Port& p)
|
||||
MIDIFunction::MIDIFunction (MIDI::Parser& p)
|
||||
: MIDIInvokable (p)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <cmath>
|
||||
|
||||
#include "midi++/port.h"
|
||||
#include "midi++/manager.h"
|
||||
|
||||
#include "ardour/automation_control.h"
|
||||
#include "ardour/debug.h"
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue