mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 23:35:03 +01:00
major redesign of MIDI port heirarchy and management (part 2)
This commit is contained in:
parent
83a0c30c24
commit
1ab61b8564
62 changed files with 741 additions and 562 deletions
|
|
@ -58,8 +58,6 @@
|
||||||
#include "gtkmm2ext/popup.h"
|
#include "gtkmm2ext/popup.h"
|
||||||
#include "gtkmm2ext/window_title.h"
|
#include "gtkmm2ext/window_title.h"
|
||||||
|
|
||||||
#include "midi++/manager.h"
|
|
||||||
|
|
||||||
#include "ardour/ardour.h"
|
#include "ardour/ardour.h"
|
||||||
#include "ardour/audio_backend.h"
|
#include "ardour/audio_backend.h"
|
||||||
#include "ardour/audioengine.h"
|
#include "ardour/audioengine.h"
|
||||||
|
|
@ -1050,14 +1048,20 @@ ARDOUR_UI::update_sample_rate (framecnt_t)
|
||||||
|
|
||||||
framecnt_t rate = engine->sample_rate();
|
framecnt_t rate = engine->sample_rate();
|
||||||
|
|
||||||
if (fmod (rate, 1000.0) != 0.0) {
|
if (rate == 0) {
|
||||||
snprintf (buf, sizeof (buf), _("JACK: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"),
|
/* no sample rate available */
|
||||||
(float) rate / 1000.0f,
|
snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"red\">disconnected</span>"));
|
||||||
(engine->usecs_per_cycle() / 1000.0f));
|
|
||||||
} else {
|
} else {
|
||||||
snprintf (buf, sizeof (buf), _("JACK: <span foreground=\"green\">%" PRId64 " kHz / %4.1f ms</span>"),
|
|
||||||
rate/1000,
|
if (fmod (rate, 1000.0) != 0.0) {
|
||||||
(engine->usecs_per_cycle() * 1000.0f));
|
snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"),
|
||||||
|
(float) rate / 1000.0f,
|
||||||
|
(engine->usecs_per_cycle() / 1000.0f));
|
||||||
|
} else {
|
||||||
|
snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"green\">%" PRId64 " kHz / %4.1f ms</span>"),
|
||||||
|
rate/1000,
|
||||||
|
(engine->usecs_per_cycle() * 1000.0f));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1181,6 +1185,11 @@ ARDOUR_UI::update_disk_space()
|
||||||
char buf[64];
|
char buf[64];
|
||||||
framecnt_t fr = _session->frame_rate();
|
framecnt_t fr = _session->frame_rate();
|
||||||
|
|
||||||
|
if (fr == 0) {
|
||||||
|
/* skip update - no SR available */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!opt_frames) {
|
if (!opt_frames) {
|
||||||
/* Available space is unknown */
|
/* Available space is unknown */
|
||||||
snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">Unknown</span>"));
|
snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">Unknown</span>"));
|
||||||
|
|
@ -1663,9 +1672,16 @@ ARDOUR_UI::transport_goto_wallclock ()
|
||||||
time (&now);
|
time (&now);
|
||||||
localtime_r (&now, &tmnow);
|
localtime_r (&now, &tmnow);
|
||||||
|
|
||||||
frames = tmnow.tm_hour * (60 * 60 * _session->frame_rate());
|
int frame_rate = _session->frame_rate();
|
||||||
frames += tmnow.tm_min * (60 * _session->frame_rate());
|
|
||||||
frames += tmnow.tm_sec * _session->frame_rate();
|
if (frame_rate == 0) {
|
||||||
|
/* no frame rate available */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
frames = tmnow.tm_hour * (60 * 60 * frame_rate);
|
||||||
|
frames += tmnow.tm_min * (60 * frame_rate);
|
||||||
|
frames += tmnow.tm_sec * frame_rate;
|
||||||
|
|
||||||
_session->request_locate (frames, _session->transport_rolling ());
|
_session->request_locate (frames, _session->transport_rolling ());
|
||||||
|
|
||||||
|
|
@ -3802,7 +3818,7 @@ void
|
||||||
ARDOUR_UI::disconnect_from_jack ()
|
ARDOUR_UI::disconnect_from_jack ()
|
||||||
{
|
{
|
||||||
if (engine) {
|
if (engine) {
|
||||||
if (engine->pause ()) {
|
if (engine->stop ()) {
|
||||||
MessageDialog msg (*editor, _("Could not disconnect from JACK"));
|
MessageDialog msg (*editor, _("Could not disconnect from JACK"));
|
||||||
msg.run ();
|
msg.run ();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1258,7 +1258,8 @@ Editor::set_session (Session *t)
|
||||||
|
|
||||||
/* These signals can all be emitted by a non-GUI thread. Therefore the
|
/* These signals can all be emitted by a non-GUI thread. Therefore the
|
||||||
handlers for them must not attempt to directly interact with the GUI,
|
handlers for them must not attempt to directly interact with the GUI,
|
||||||
but use Gtkmm2ext::UI::instance()->call_slot();
|
but use PBD::Signal<T>::connect() which accepts an event loop
|
||||||
|
("context") where the handler will be asked to run.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
_session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
|
_session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
|
||||||
|
|
|
||||||
|
|
@ -2372,8 +2372,9 @@ CursorDrag::fake_locate (framepos_t t)
|
||||||
if (s->timecode_transmission_suspended ()) {
|
if (s->timecode_transmission_suspended ()) {
|
||||||
framepos_t const f = _editor->playhead_cursor->current_frame;
|
framepos_t const f = _editor->playhead_cursor->current_frame;
|
||||||
s->send_mmc_locate (f);
|
s->send_mmc_locate (f);
|
||||||
s->send_full_time_code (f);
|
// XXX need to queue full time code and SPP messages somehow
|
||||||
s->send_song_position_pointer (f);
|
// s->send_full_time_code (f);
|
||||||
|
// s->send_song_position_pointer (f);
|
||||||
}
|
}
|
||||||
|
|
||||||
show_verbose_cursor_time (t);
|
show_verbose_cursor_time (t);
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@
|
||||||
#include <gtkmm2ext/fastmeter.h>
|
#include <gtkmm2ext/fastmeter.h>
|
||||||
#include <gtkmm2ext/barcontroller.h>
|
#include <gtkmm2ext/barcontroller.h>
|
||||||
#include <gtkmm2ext/gtk_ui.h>
|
#include <gtkmm2ext/gtk_ui.h>
|
||||||
#include "midi++/manager.h"
|
|
||||||
#include "pbd/fastlog.h"
|
#include "pbd/fastlog.h"
|
||||||
#include "pbd/stacktrace.h"
|
#include "pbd/stacktrace.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,6 @@
|
||||||
#include <gtkmm2ext/doi.h>
|
#include <gtkmm2ext/doi.h>
|
||||||
#include <gtkmm2ext/slider_controller.h>
|
#include <gtkmm2ext/slider_controller.h>
|
||||||
|
|
||||||
#include "midi++/manager.h"
|
|
||||||
|
|
||||||
#include "ardour/plugin.h"
|
#include "ardour/plugin.h"
|
||||||
#include "ardour/plugin_insert.h"
|
#include "ardour/plugin_insert.h"
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@
|
||||||
|
|
||||||
#include <gtkmm2ext/utils.h>
|
#include <gtkmm2ext/utils.h>
|
||||||
#include <gtkmm2ext/barcontroller.h>
|
#include <gtkmm2ext/barcontroller.h>
|
||||||
#include "midi++/manager.h"
|
|
||||||
#include "pbd/fastlog.h"
|
#include "pbd/fastlog.h"
|
||||||
|
|
||||||
#include "ardour_ui.h"
|
#include "ardour_ui.h"
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,10 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "midi++/parser.h"
|
#include "midi++/parser.h"
|
||||||
#include "midi++/manager.h"
|
|
||||||
|
#include "ardour/async_midi_port.h"
|
||||||
|
#include "ardour/midi_port.h"
|
||||||
|
#include "ardour/audioengine.h"
|
||||||
|
|
||||||
#include "midi_tracer.h"
|
#include "midi_tracer.h"
|
||||||
#include "gui_thread.h"
|
#include "gui_thread.h"
|
||||||
|
|
@ -53,7 +56,8 @@ MidiTracer::MidiTracer ()
|
||||||
, collect_button (_("Enabled"))
|
, collect_button (_("Enabled"))
|
||||||
, delta_time_button (_("Delta times"))
|
, delta_time_button (_("Delta times"))
|
||||||
{
|
{
|
||||||
Manager::instance()->PortsChanged.connect (_manager_connection, invalidator (*this), boost::bind (&MidiTracer::ports_changed, this), gui_context());
|
ARDOUR::AudioEngine::instance()->PortRegisteredOrUnregistered.connect
|
||||||
|
(_manager_connection, invalidator (*this), boost::bind (&MidiTracer::ports_changed, this), gui_context());
|
||||||
|
|
||||||
_last_receipt.tv_sec = 0;
|
_last_receipt.tv_sec = 0;
|
||||||
_last_receipt.tv_usec = 0;
|
_last_receipt.tv_usec = 0;
|
||||||
|
|
@ -127,24 +131,49 @@ MidiTracer::ports_changed ()
|
||||||
string const c = _port_combo.get_active_text ();
|
string const c = _port_combo.get_active_text ();
|
||||||
_port_combo.clear ();
|
_port_combo.clear ();
|
||||||
|
|
||||||
boost::shared_ptr<const Manager::PortList> p = Manager::instance()->get_midi_ports ();
|
ARDOUR::PortManager::PortList pl;
|
||||||
for (Manager::PortList::const_iterator i = p->begin(); i != p->end(); ++i) {
|
ARDOUR::AudioEngine::instance()->get_ports (ARDOUR::DataType::MIDI, pl);
|
||||||
|
|
||||||
|
if (pl.empty()) {
|
||||||
|
_port_combo.set_active_text ("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ARDOUR::PortManager::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
|
||||||
_port_combo.append_text ((*i)->name());
|
_port_combo.append_text ((*i)->name());
|
||||||
}
|
}
|
||||||
|
|
||||||
_port_combo.set_active_text (c);
|
if (c.empty()) {
|
||||||
|
_port_combo.set_active_text (pl.front()->name());
|
||||||
|
} else {
|
||||||
|
_port_combo.set_active_text (c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiTracer::port_changed ()
|
MidiTracer::port_changed ()
|
||||||
{
|
{
|
||||||
|
using namespace ARDOUR;
|
||||||
|
|
||||||
disconnect ();
|
disconnect ();
|
||||||
|
|
||||||
Port* p = Manager::instance()->port (_port_combo.get_active_text());
|
boost::shared_ptr<ARDOUR::Port> p = AudioEngine::instance()->get_port_by_name (_port_combo.get_active_text());
|
||||||
|
|
||||||
if (p) {
|
if (!p) {
|
||||||
p->parser()->any.connect_same_thread (_parser_connection, boost::bind (&MidiTracer::tracer, this, _1, _2, _3));
|
std::cerr << "port not found\n";
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::shared_ptr<AsyncMIDIPort> async = boost::dynamic_pointer_cast<AsyncMIDIPort> (p);
|
||||||
|
|
||||||
|
if (!async) {
|
||||||
|
/* pure ARDOUR::MidiPort ... cannot currently attach to it because it
|
||||||
|
* has no Parser.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
async->parser()->any.connect_same_thread (_parser_connection, boost::bind (&MidiTracer::tracer, this, _1, _2, _3));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@
|
||||||
#include <gtkmm2ext/utils.h>
|
#include <gtkmm2ext/utils.h>
|
||||||
#include <gtkmm2ext/barcontroller.h>
|
#include <gtkmm2ext/barcontroller.h>
|
||||||
|
|
||||||
#include "midi++/manager.h"
|
|
||||||
#include "pbd/fastlog.h"
|
#include "pbd/fastlog.h"
|
||||||
|
|
||||||
#include "ardour/pannable.h"
|
#include "ardour/pannable.h"
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,6 @@
|
||||||
#include <gtkmm2ext/slider_controller.h>
|
#include <gtkmm2ext/slider_controller.h>
|
||||||
#include <gtkmm2ext/application.h>
|
#include <gtkmm2ext/application.h>
|
||||||
|
|
||||||
#include "midi++/manager.h"
|
|
||||||
|
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
#include "ardour/plugin.h"
|
#include "ardour/plugin.h"
|
||||||
#include "ardour/plugin_insert.h"
|
#include "ardour/plugin_insert.h"
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
#include "midi++/manager.h"
|
|
||||||
#include "midi++/mmc.h"
|
#include "midi++/mmc.h"
|
||||||
|
|
||||||
#include "ardour/audioengine.h"
|
#include "ardour/audioengine.h"
|
||||||
|
|
@ -29,9 +28,13 @@
|
||||||
#include "ardour/bundle.h"
|
#include "ardour/bundle.h"
|
||||||
#include "ardour/control_protocol_manager.h"
|
#include "ardour/control_protocol_manager.h"
|
||||||
#include "ardour/io_processor.h"
|
#include "ardour/io_processor.h"
|
||||||
|
#include "ardour/midi_port.h"
|
||||||
|
#include "ardour/midiport_manager.h"
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
#include "ardour/user_bundle.h"
|
#include "ardour/user_bundle.h"
|
||||||
#include "ardour/port.h"
|
#include "ardour/port.h"
|
||||||
|
#include "ardour/syncport_manager.h"
|
||||||
|
|
||||||
#include "control_protocol/control_protocol.h"
|
#include "control_protocol/control_protocol.h"
|
||||||
|
|
||||||
#include "gui_thread.h"
|
#include "gui_thread.h"
|
||||||
|
|
@ -452,37 +455,36 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
|
||||||
|
|
||||||
/* Ardour's sync ports */
|
/* Ardour's sync ports */
|
||||||
|
|
||||||
MIDI::Manager* midi_manager = MIDI::Manager::instance ();
|
if ((type == DataType::MIDI || type == DataType::NIL)) {
|
||||||
if (midi_manager && (type == DataType::MIDI || type == DataType::NIL)) {
|
|
||||||
boost::shared_ptr<Bundle> sync (new Bundle (_("Sync"), inputs));
|
boost::shared_ptr<Bundle> sync (new Bundle (_("Sync"), inputs));
|
||||||
MIDI::MachineControl* mmc = midi_manager->mmc ();
|
AudioEngine* ae = AudioEngine::instance();
|
||||||
AudioEngine& ae = session->engine ();
|
MIDI::MachineControl& mmc (ae->mmc());
|
||||||
|
|
||||||
if (inputs) {
|
if (inputs) {
|
||||||
sync->add_channel (
|
sync->add_channel (
|
||||||
_("MTC in"), DataType::MIDI, ae.make_port_name_non_relative (midi_manager->mtc_input_port()->name())
|
_("MTC in"), DataType::MIDI, ae->make_port_name_non_relative (ae->mtc_input_port()->name())
|
||||||
);
|
);
|
||||||
sync->add_channel (
|
sync->add_channel (
|
||||||
_("MIDI control in"), DataType::MIDI, ae.make_port_name_non_relative (midi_manager->midi_input_port()->name())
|
_("MIDI control in"), DataType::MIDI, ae->make_port_name_non_relative (ae->midi_input_port()->name())
|
||||||
);
|
);
|
||||||
sync->add_channel (
|
sync->add_channel (
|
||||||
_("MIDI clock in"), DataType::MIDI, ae.make_port_name_non_relative (midi_manager->midi_clock_input_port()->name())
|
_("MIDI clock in"), DataType::MIDI, ae->make_port_name_non_relative (ae->midi_clock_input_port()->name())
|
||||||
);
|
);
|
||||||
sync->add_channel (
|
sync->add_channel (
|
||||||
_("MMC in"), DataType::MIDI, ae.make_port_name_non_relative (mmc->input_port()->name())
|
_("MMC in"), DataType::MIDI, ae->make_port_name_non_relative (mmc.input_port()->name())
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
sync->add_channel (
|
sync->add_channel (
|
||||||
_("MTC out"), DataType::MIDI, ae.make_port_name_non_relative (midi_manager->mtc_output_port()->name())
|
_("MTC out"), DataType::MIDI, ae->make_port_name_non_relative (ae->mtc_output_port()->name())
|
||||||
);
|
);
|
||||||
sync->add_channel (
|
sync->add_channel (
|
||||||
_("MIDI control out"), DataType::MIDI, ae.make_port_name_non_relative (midi_manager->midi_output_port()->name())
|
_("MIDI control out"), DataType::MIDI, ae->make_port_name_non_relative (ae->midi_output_port()->name())
|
||||||
);
|
);
|
||||||
sync->add_channel (
|
sync->add_channel (
|
||||||
_("MIDI clock out"), DataType::MIDI, ae.make_port_name_non_relative (midi_manager->midi_clock_output_port()->name())
|
_("MIDI clock out"), DataType::MIDI, ae->make_port_name_non_relative (ae->midi_clock_output_port()->name())
|
||||||
);
|
);
|
||||||
sync->add_channel (
|
sync->add_channel (
|
||||||
_("MMC out"), DataType::MIDI, ae.make_port_name_non_relative (mmc->output_port()->name())
|
_("MMC out"), DataType::MIDI, ae->make_port_name_non_relative (mmc.output_port()->name())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,6 @@
|
||||||
#include "pbd/fpu.h"
|
#include "pbd/fpu.h"
|
||||||
#include "pbd/cpus.h"
|
#include "pbd/cpus.h"
|
||||||
|
|
||||||
#include "midi++/manager.h"
|
|
||||||
|
|
||||||
#include "ardour/audioengine.h"
|
#include "ardour/audioengine.h"
|
||||||
#include "ardour/dB.h"
|
#include "ardour/dB.h"
|
||||||
#include "ardour/rc_configuration.h"
|
#include "ardour/rc_configuration.h"
|
||||||
|
|
|
||||||
|
|
@ -49,9 +49,7 @@ class AudioPort : public Port
|
||||||
friend class PortManager;
|
friend class PortManager;
|
||||||
AudioPort (std::string const &, PortFlags);
|
AudioPort (std::string const &, PortFlags);
|
||||||
|
|
||||||
protected:
|
/* special access for PortManager only (hah, C++) */
|
||||||
friend class AudioEngine;
|
|
||||||
/* special access for engine only (hah, C++) */
|
|
||||||
Sample* engine_get_whole_audio_buffer ();
|
Sample* engine_get_whole_audio_buffer ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,9 @@
|
||||||
#include "pbd/signals.h"
|
#include "pbd/signals.h"
|
||||||
#include "pbd/stacktrace.h"
|
#include "pbd/stacktrace.h"
|
||||||
|
|
||||||
#include <jack/weakjack.h>
|
#include "midi++/mmc.h"
|
||||||
#include <jack/jack.h>
|
|
||||||
#include <jack/transport.h>
|
|
||||||
#include <jack/thread.h>
|
|
||||||
|
|
||||||
#include "ardour/ardour.h"
|
#include "ardour/ardour.h"
|
||||||
|
|
||||||
#include "ardour/data_type.h"
|
#include "ardour/data_type.h"
|
||||||
#include "ardour/session_handle.h"
|
#include "ardour/session_handle.h"
|
||||||
#include "ardour/types.h"
|
#include "ardour/types.h"
|
||||||
|
|
@ -192,6 +188,8 @@ public:
|
||||||
/* sets up the process callback thread */
|
/* sets up the process callback thread */
|
||||||
static void thread_init_callback (void *);
|
static void thread_init_callback (void *);
|
||||||
|
|
||||||
|
MIDI::MachineControl& mmc() { return _mmc; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AudioEngine ();
|
AudioEngine ();
|
||||||
|
|
||||||
|
|
@ -206,16 +204,17 @@ public:
|
||||||
gain_t session_removal_gain;
|
gain_t session_removal_gain;
|
||||||
gain_t session_removal_gain_step;
|
gain_t session_removal_gain_step;
|
||||||
bool _running;
|
bool _running;
|
||||||
|
bool _freewheeling;
|
||||||
/// number of frames between each check for changes in monitor input
|
/// number of frames between each check for changes in monitor input
|
||||||
framecnt_t monitor_check_interval;
|
framecnt_t monitor_check_interval;
|
||||||
/// time of the last monitor check in frames
|
/// time of the last monitor check in frames
|
||||||
framecnt_t last_monitor_check;
|
framecnt_t last_monitor_check;
|
||||||
/// the number of frames processed since start() was called
|
/// the number of frames processed since start() was called
|
||||||
framecnt_t _processed_frames;
|
framecnt_t _processed_frames;
|
||||||
bool _freewheeling;
|
|
||||||
bool _pre_freewheel_mmc_enabled;
|
bool _pre_freewheel_mmc_enabled;
|
||||||
Glib::Threads::Thread* m_meter_thread;
|
Glib::Threads::Thread* m_meter_thread;
|
||||||
ProcessThread* _main_thread;
|
ProcessThread* _main_thread;
|
||||||
|
MIDI::MachineControl _mmc;
|
||||||
|
|
||||||
void meter_thread ();
|
void meter_thread ();
|
||||||
void start_metering_thread ();
|
void start_metering_thread ();
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ namespace PBD {
|
||||||
extern uint64_t OrderKeys;
|
extern uint64_t OrderKeys;
|
||||||
extern uint64_t Automation;
|
extern uint64_t Automation;
|
||||||
extern uint64_t WiimoteControl;
|
extern uint64_t WiimoteControl;
|
||||||
|
extern uint64_t Ports;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,8 @@ class JACKAudioBackend : public AudioBackend {
|
||||||
typedef std::map<std::string,DeviceList> DriverDeviceMap;
|
typedef std::map<std::string,DeviceList> DriverDeviceMap;
|
||||||
|
|
||||||
mutable DriverDeviceMap all_devices;
|
mutable DriverDeviceMap all_devices;
|
||||||
|
|
||||||
|
PBD::ScopedConnection disconnect_connection;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,11 @@
|
||||||
#include "pbd/signals.h"
|
#include "pbd/signals.h"
|
||||||
#include "pbd/stacktrace.h"
|
#include "pbd/stacktrace.h"
|
||||||
|
|
||||||
namespace MIDI {
|
|
||||||
class Port;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
class Session;
|
class Session;
|
||||||
|
class AsyncMIDIPort;
|
||||||
|
|
||||||
/* this is mostly a placeholder because I suspect that at some
|
/* this is mostly a placeholder because I suspect that at some
|
||||||
point we will want to add more members to accomodate
|
point we will want to add more members to accomodate
|
||||||
|
|
@ -67,7 +65,7 @@ class MidiControlUI : public AbstractUI<MidiUIRequest>
|
||||||
ARDOUR::Session& _session;
|
ARDOUR::Session& _session;
|
||||||
PBD::ScopedConnection rebind_connection;
|
PBD::ScopedConnection rebind_connection;
|
||||||
|
|
||||||
bool midi_input_handler (Glib::IOCondition, MIDI::Port*);
|
bool midi_input_handler (Glib::IOCondition, AsyncMIDIPort*);
|
||||||
void reset_ports ();
|
void reset_ports ();
|
||||||
void clear_ports ();
|
void clear_ports ();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,10 @@ class MidiPortManager {
|
||||||
* callback.
|
* callback.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MIDI::Port* midi_input_port () { return _midi_input_port; }
|
MIDI::Port* midi_input_port () const { return _midi_input_port; }
|
||||||
MIDI::Port* midi_output_port () { return _midi_output_port; }
|
MIDI::Port* midi_output_port () const { return _midi_output_port; }
|
||||||
|
MIDI::Port* mmc_input_port () const { return _mmc_input_port; }
|
||||||
|
MIDI::Port* mmc_output_port () const { return _mmc_output_port; }
|
||||||
|
|
||||||
/* Ports used for synchronization. These have their I/O handled inside the
|
/* Ports used for synchronization. These have their I/O handled inside the
|
||||||
* process callback.
|
* process callback.
|
||||||
|
|
@ -76,8 +78,12 @@ class MidiPortManager {
|
||||||
/* asynchronously handled ports: MIDI::Port */
|
/* asynchronously handled ports: MIDI::Port */
|
||||||
MIDI::Port* _midi_input_port;
|
MIDI::Port* _midi_input_port;
|
||||||
MIDI::Port* _midi_output_port;
|
MIDI::Port* _midi_output_port;
|
||||||
|
MIDI::Port* _mmc_input_port;
|
||||||
|
MIDI::Port* _mmc_output_port;
|
||||||
boost::shared_ptr<Port> _midi_in;
|
boost::shared_ptr<Port> _midi_in;
|
||||||
boost::shared_ptr<Port> _midi_out;
|
boost::shared_ptr<Port> _midi_out;
|
||||||
|
boost::shared_ptr<Port> _mmc_in;
|
||||||
|
boost::shared_ptr<Port> _mmc_out;
|
||||||
|
|
||||||
/* synchronously handled ports: ARDOUR::MidiPort */
|
/* synchronously handled ports: ARDOUR::MidiPort */
|
||||||
boost::shared_ptr<MidiPort> _mtc_input_port;
|
boost::shared_ptr<MidiPort> _mtc_input_port;
|
||||||
|
|
|
||||||
|
|
@ -32,15 +32,17 @@
|
||||||
#include "pbd/rcu.h"
|
#include "pbd/rcu.h"
|
||||||
|
|
||||||
#include "ardour/chan_count.h"
|
#include "ardour/chan_count.h"
|
||||||
|
#include "ardour/midiport_manager.h"
|
||||||
#include "ardour/port.h"
|
#include "ardour/port.h"
|
||||||
#include "ardour/port_engine.h"
|
#include "ardour/port_engine.h"
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
class PortManager
|
class PortManager : public MidiPortManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::map<std::string,boost::shared_ptr<Port> > Ports;
|
typedef std::map<std::string,boost::shared_ptr<Port> > Ports;
|
||||||
|
typedef std::list<boost::shared_ptr<Port> > PortList;
|
||||||
|
|
||||||
PortManager ();
|
PortManager ();
|
||||||
virtual ~PortManager() {}
|
virtual ~PortManager() {}
|
||||||
|
|
@ -53,8 +55,8 @@ class PortManager
|
||||||
|
|
||||||
/* Port registration */
|
/* Port registration */
|
||||||
|
|
||||||
boost::shared_ptr<Port> register_input_port (DataType, const std::string& portname);
|
boost::shared_ptr<Port> register_input_port (DataType, const std::string& portname, bool async = false);
|
||||||
boost::shared_ptr<Port> register_output_port (DataType, const std::string& portname);
|
boost::shared_ptr<Port> register_output_port (DataType, const std::string& portname, bool async = false);
|
||||||
int unregister_port (boost::shared_ptr<Port>);
|
int unregister_port (boost::shared_ptr<Port>);
|
||||||
|
|
||||||
/* Port connectivity */
|
/* Port connectivity */
|
||||||
|
|
@ -87,6 +89,7 @@ class PortManager
|
||||||
ChanCount n_physical_inputs () const;
|
ChanCount n_physical_inputs () const;
|
||||||
|
|
||||||
int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>&);
|
int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>&);
|
||||||
|
int get_ports (DataType, PortList&);
|
||||||
|
|
||||||
void remove_all_ports ();
|
void remove_all_ports ();
|
||||||
|
|
||||||
|
|
@ -135,10 +138,32 @@ class PortManager
|
||||||
SerializedRCUManager<Ports> ports;
|
SerializedRCUManager<Ports> ports;
|
||||||
bool _port_remove_in_progress;
|
bool _port_remove_in_progress;
|
||||||
|
|
||||||
boost::shared_ptr<Port> register_port (DataType type, const std::string& portname, bool input);
|
boost::shared_ptr<Port> register_port (DataType type, const std::string& portname, bool input, bool async = false);
|
||||||
void port_registration_failure (const std::string& portname);
|
void port_registration_failure (const std::string& portname);
|
||||||
|
|
||||||
|
/** List of ports to be used between ::cycle_start() and ::cycle_end()
|
||||||
|
*/
|
||||||
|
boost::shared_ptr<Ports> _cycle_ports;
|
||||||
|
|
||||||
|
void fade_out (gain_t, gain_t, pframes_t);
|
||||||
|
void silence (pframes_t nframes);
|
||||||
|
void check_monitoring ();
|
||||||
|
/** Signal the start of an audio cycle.
|
||||||
|
* This MUST be called before any reading/writing for this cycle.
|
||||||
|
* Realtime safe.
|
||||||
|
*/
|
||||||
|
void cycle_start (pframes_t nframes);
|
||||||
|
|
||||||
|
/** Signal the end of an audio cycle.
|
||||||
|
* This signifies that the cycle began with @ref cycle_start has ended.
|
||||||
|
* This MUST be called at the end of each cycle.
|
||||||
|
* Realtime safe.
|
||||||
|
*/
|
||||||
|
void cycle_end (pframes_t nframes);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#endif /* __libardour_port_manager_h__ */
|
#endif /* __libardour_port_manager_h__ */
|
||||||
|
|
|
||||||
|
|
@ -813,7 +813,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
|
||||||
boost::shared_ptr<SessionPlaylists> playlists;
|
boost::shared_ptr<SessionPlaylists> playlists;
|
||||||
|
|
||||||
void send_mmc_locate (framepos_t);
|
void send_mmc_locate (framepos_t);
|
||||||
int send_full_time_code (framepos_t);
|
int send_full_time_code (framepos_t, pframes_t nframes);
|
||||||
void send_song_position_pointer (framepos_t);
|
void send_song_position_pointer (framepos_t);
|
||||||
|
|
||||||
bool step_editing() const { return (_step_editors > 0); }
|
bool step_editing() const { return (_step_editors > 0); }
|
||||||
|
|
|
||||||
|
|
@ -40,15 +40,12 @@
|
||||||
#define PLUSMINUS(A) ( ((A)<0) ? "-" : (((A)>0) ? "+" : "\u00B1") )
|
#define PLUSMINUS(A) ( ((A)<0) ? "-" : (((A)>0) ? "+" : "\u00B1") )
|
||||||
#define LEADINGZERO(A) ( (A)<10 ? " " : (A)<100 ? " " : (A)<1000 ? " " : "" )
|
#define LEADINGZERO(A) ( (A)<10 ? " " : (A)<100 ? " " : (A)<1000 ? " " : "" )
|
||||||
|
|
||||||
namespace MIDI {
|
|
||||||
class Port;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
class TempoMap;
|
class TempoMap;
|
||||||
class Session;
|
class Session;
|
||||||
class AudioEngine;
|
class AudioEngine;
|
||||||
|
class MidiPort;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class Slave
|
* @class Slave
|
||||||
|
|
@ -67,6 +64,15 @@ class Slave {
|
||||||
Slave() { }
|
Slave() { }
|
||||||
virtual ~Slave() {}
|
virtual ~Slave() {}
|
||||||
|
|
||||||
|
/** The slave should read any incoming information in this method
|
||||||
|
* and use it adjust its current idea of reality. If no such
|
||||||
|
* processing is required, it does need to be implemented.
|
||||||
|
*
|
||||||
|
* @param nframes specifies the number of frames-worth of data that
|
||||||
|
* can be read from any ports used by the slave.
|
||||||
|
*/
|
||||||
|
virtual int process (pframes_t) { return 0; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the most important function to implement:
|
* This is the most important function to implement:
|
||||||
* Each process cycle, Session::follow_slave will call this method.
|
* Each process cycle, Session::follow_slave will call this method.
|
||||||
|
|
@ -253,10 +259,11 @@ class TimecodeSlave : public Slave {
|
||||||
|
|
||||||
class MTC_Slave : public TimecodeSlave {
|
class MTC_Slave : public TimecodeSlave {
|
||||||
public:
|
public:
|
||||||
MTC_Slave (Session&, MIDI::Port&);
|
MTC_Slave (Session&, MidiPort&);
|
||||||
~MTC_Slave ();
|
~MTC_Slave ();
|
||||||
|
|
||||||
void rebind (MIDI::Port&);
|
void rebind (MidiPort&);
|
||||||
|
int process (pframes_t);
|
||||||
bool speed_and_position (double&, framepos_t&);
|
bool speed_and_position (double&, framepos_t&);
|
||||||
|
|
||||||
bool locked() const;
|
bool locked() const;
|
||||||
|
|
@ -274,7 +281,8 @@ class MTC_Slave : public TimecodeSlave {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Session& session;
|
Session& session;
|
||||||
MIDI::Port* port;
|
MidiPort* port;
|
||||||
|
MIDI::Parser parser;
|
||||||
PBD::ScopedConnectionList port_connections;
|
PBD::ScopedConnectionList port_connections;
|
||||||
PBD::ScopedConnection config_connection;
|
PBD::ScopedConnection config_connection;
|
||||||
bool can_notify_on_unknown_rate;
|
bool can_notify_on_unknown_rate;
|
||||||
|
|
@ -405,13 +413,14 @@ public:
|
||||||
|
|
||||||
class MIDIClock_Slave : public Slave {
|
class MIDIClock_Slave : public Slave {
|
||||||
public:
|
public:
|
||||||
MIDIClock_Slave (Session&, MIDI::Port&, int ppqn = 24);
|
MIDIClock_Slave (Session&, MidiPort&, int ppqn = 24);
|
||||||
|
|
||||||
/// Constructor for unit tests
|
/// Constructor for unit tests
|
||||||
MIDIClock_Slave (ISlaveSessionProxy* session_proxy = 0, int ppqn = 24);
|
MIDIClock_Slave (ISlaveSessionProxy* session_proxy = 0, int ppqn = 24);
|
||||||
~MIDIClock_Slave ();
|
~MIDIClock_Slave ();
|
||||||
|
|
||||||
void rebind (MIDI::Port&);
|
void rebind (MidiPort&);
|
||||||
|
int process (pframes_t);
|
||||||
bool speed_and_position (double&, framepos_t&);
|
bool speed_and_position (double&, framepos_t&);
|
||||||
|
|
||||||
bool locked() const;
|
bool locked() const;
|
||||||
|
|
@ -427,7 +436,8 @@ class MIDIClock_Slave : public Slave {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ISlaveSessionProxy* session;
|
ISlaveSessionProxy* session;
|
||||||
MIDI::Port* port;
|
MidiPort* port;
|
||||||
|
MIDI::Parser parser;
|
||||||
PBD::ScopedConnectionList port_connections;
|
PBD::ScopedConnectionList port_connections;
|
||||||
|
|
||||||
/// pulses per quarter note for one MIDI clock frame (default 24)
|
/// pulses per quarter note for one MIDI clock frame (default 24)
|
||||||
|
|
|
||||||
|
|
@ -27,17 +27,13 @@
|
||||||
#include "ardour/session_handle.h"
|
#include "ardour/session_handle.h"
|
||||||
|
|
||||||
|
|
||||||
#ifndef TICKER_H_
|
#ifndef __libardour_ticker_h__
|
||||||
#define TICKER_H_
|
#define __libardour_ticker_h__
|
||||||
|
|
||||||
namespace MIDI {
|
namespace ARDOUR {
|
||||||
class Port;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace ARDOUR
|
|
||||||
{
|
|
||||||
|
|
||||||
class Session;
|
class Session;
|
||||||
|
class MidiPort;
|
||||||
|
|
||||||
class MidiClockTicker : public SessionHandlePtr, boost::noncopyable
|
class MidiClockTicker : public SessionHandlePtr, boost::noncopyable
|
||||||
{
|
{
|
||||||
|
|
@ -45,7 +41,7 @@ public:
|
||||||
MidiClockTicker ();
|
MidiClockTicker ();
|
||||||
virtual ~MidiClockTicker();
|
virtual ~MidiClockTicker();
|
||||||
|
|
||||||
void tick (const framepos_t& transport_frames);
|
void tick (const framepos_t& transport_frames, pframes_t nframes);
|
||||||
|
|
||||||
bool has_midi_port() const { return _midi_port != 0; }
|
bool has_midi_port() const { return _midi_port != 0; }
|
||||||
|
|
||||||
|
|
@ -58,9 +54,6 @@ public:
|
||||||
/// slot for the signal session::TransportStateChange
|
/// slot for the signal session::TransportStateChange
|
||||||
void transport_state_changed();
|
void transport_state_changed();
|
||||||
|
|
||||||
/// slot for the signal session::PositionChanged
|
|
||||||
void position_changed (framepos_t position);
|
|
||||||
|
|
||||||
/// slot for the signal session::TransportLooped
|
/// slot for the signal session::TransportLooped
|
||||||
void transport_looped();
|
void transport_looped();
|
||||||
|
|
||||||
|
|
@ -70,23 +63,25 @@ public:
|
||||||
/// pulses per quarter note (default 24)
|
/// pulses per quarter note (default 24)
|
||||||
void set_ppqn(int ppqn) { _ppqn = ppqn; }
|
void set_ppqn(int ppqn) { _ppqn = ppqn; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MIDI::Port* _midi_port;
|
boost::shared_ptr<MidiPort> _midi_port;
|
||||||
int _ppqn;
|
int _ppqn;
|
||||||
double _last_tick;
|
double _last_tick;
|
||||||
|
bool _send_pos;
|
||||||
|
bool _send_state;
|
||||||
|
|
||||||
class Position;
|
class Position;
|
||||||
boost::scoped_ptr<Position> _pos;
|
boost::scoped_ptr<Position> _pos;
|
||||||
|
|
||||||
double one_ppqn_in_frames (framepos_t transport_position);
|
double one_ppqn_in_frames (framepos_t transport_position);
|
||||||
|
|
||||||
void send_midi_clock_event (pframes_t offset);
|
void send_midi_clock_event (pframes_t offset, pframes_t nframes);
|
||||||
void send_start_event (pframes_t offset);
|
void send_start_event (pframes_t offset, pframes_t nframes);
|
||||||
void send_continue_event (pframes_t offset);
|
void send_continue_event (pframes_t offset, pframes_t nframes);
|
||||||
void send_stop_event (pframes_t offset);
|
void send_stop_event (pframes_t offset, pframes_t nframes);
|
||||||
void send_position_event (uint32_t midi_clocks, pframes_t offset);
|
void send_position_event (uint32_t midi_clocks, pframes_t offset, pframes_t nframes);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// namespace
|
||||||
|
|
||||||
#endif /* TICKER_H_ */
|
#endif /* __libardour_ticker_h__ */
|
||||||
|
|
|
||||||
|
|
@ -37,10 +37,9 @@
|
||||||
#include <jack/weakjack.h>
|
#include <jack/weakjack.h>
|
||||||
|
|
||||||
#include "midi++/port.h"
|
#include "midi++/port.h"
|
||||||
#include "midi++/jack_midi_port.h"
|
|
||||||
#include "midi++/mmc.h"
|
#include "midi++/mmc.h"
|
||||||
#include "midi++/manager.h"
|
|
||||||
|
|
||||||
|
#include "ardour/async_midi_port.h"
|
||||||
#include "ardour/audio_port.h"
|
#include "ardour/audio_port.h"
|
||||||
#include "ardour/audio_backend.h"
|
#include "ardour/audio_backend.h"
|
||||||
#include "ardour/audioengine.h"
|
#include "ardour/audioengine.h"
|
||||||
|
|
@ -50,6 +49,7 @@
|
||||||
#include "ardour/internal_send.h"
|
#include "ardour/internal_send.h"
|
||||||
#include "ardour/meter.h"
|
#include "ardour/meter.h"
|
||||||
#include "ardour/midi_port.h"
|
#include "ardour/midi_port.h"
|
||||||
|
#include "ardour/midiport_manager.h"
|
||||||
#include "ardour/port.h"
|
#include "ardour/port.h"
|
||||||
#include "ardour/process_thread.h"
|
#include "ardour/process_thread.h"
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
|
|
@ -66,10 +66,11 @@ AudioEngine* AudioEngine::_instance = 0;
|
||||||
AudioEngine::AudioEngine ()
|
AudioEngine::AudioEngine ()
|
||||||
: session_remove_pending (false)
|
: session_remove_pending (false)
|
||||||
, session_removal_countdown (-1)
|
, session_removal_countdown (-1)
|
||||||
|
, _running (false)
|
||||||
|
, _freewheeling (false)
|
||||||
, monitor_check_interval (INT32_MAX)
|
, monitor_check_interval (INT32_MAX)
|
||||||
, last_monitor_check (0)
|
, last_monitor_check (0)
|
||||||
, _processed_frames (0)
|
, _processed_frames (0)
|
||||||
, _freewheeling (false)
|
|
||||||
, _pre_freewheel_mmc_enabled (false)
|
, _pre_freewheel_mmc_enabled (false)
|
||||||
, m_meter_thread (0)
|
, m_meter_thread (0)
|
||||||
, _main_thread (0)
|
, _main_thread (0)
|
||||||
|
|
@ -117,7 +118,7 @@ _thread_init_callback (void * /*arg*/)
|
||||||
|
|
||||||
SessionEvent::create_per_thread_pool (X_("Audioengine"), 512);
|
SessionEvent::create_per_thread_pool (X_("Audioengine"), 512);
|
||||||
|
|
||||||
MIDI::JackMIDIPort::set_process_thread (pthread_self());
|
AsyncMIDIPort::set_process_thread (pthread_self());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -231,8 +232,8 @@ AudioEngine::process_callback (pframes_t nframes)
|
||||||
if (_session == 0) {
|
if (_session == 0) {
|
||||||
|
|
||||||
if (!_freewheeling) {
|
if (!_freewheeling) {
|
||||||
MIDI::Manager::instance()->cycle_start(nframes);
|
PortManager::cycle_start (nframes);
|
||||||
MIDI::Manager::instance()->cycle_end();
|
PortManager::cycle_end (nframes);
|
||||||
}
|
}
|
||||||
|
|
||||||
_processed_frames = next_processed_frames;
|
_processed_frames = next_processed_frames;
|
||||||
|
|
@ -243,34 +244,22 @@ AudioEngine::process_callback (pframes_t nframes)
|
||||||
/* tell all relevant objects that we're starting a new cycle */
|
/* tell all relevant objects that we're starting a new cycle */
|
||||||
|
|
||||||
InternalSend::CycleStart (nframes);
|
InternalSend::CycleStart (nframes);
|
||||||
Port::set_global_port_buffer_offset (0);
|
|
||||||
Port::set_cycle_framecnt (nframes);
|
|
||||||
|
|
||||||
/* tell all Ports that we're starting a new cycle */
|
/* tell all Ports that we're starting a new cycle */
|
||||||
|
|
||||||
boost::shared_ptr<Ports> p = ports.reader();
|
PortManager::cycle_start (nframes);
|
||||||
|
|
||||||
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
|
|
||||||
i->second->cycle_start (nframes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* test if we are freewheeling and there are freewheel signals connected.
|
/* test if we are freewheeling and there are freewheel signals connected.
|
||||||
ardour should act normally even when freewheeling unless /it/ is
|
ardour should act normally even when freewheeling unless /it/ is
|
||||||
exporting
|
exporting (which is what Freewheel.empty() tests for).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (_freewheeling && !Freewheel.empty()) {
|
if (_freewheeling && !Freewheel.empty()) {
|
||||||
|
|
||||||
Freewheel (nframes);
|
Freewheel (nframes);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
MIDI::Manager::instance()->cycle_start(nframes);
|
|
||||||
|
|
||||||
if (_session) {
|
if (_session) {
|
||||||
_session->process (nframes);
|
_session->process (nframes);
|
||||||
}
|
}
|
||||||
|
|
||||||
MIDI::Manager::instance()->cycle_end();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_freewheeling) {
|
if (_freewheeling) {
|
||||||
|
|
@ -284,51 +273,17 @@ AudioEngine::process_callback (pframes_t nframes)
|
||||||
|
|
||||||
if (last_monitor_check + monitor_check_interval < next_processed_frames) {
|
if (last_monitor_check + monitor_check_interval < next_processed_frames) {
|
||||||
|
|
||||||
boost::shared_ptr<Ports> p = ports.reader();
|
PortManager::check_monitoring ();
|
||||||
|
|
||||||
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
|
|
||||||
|
|
||||||
bool x;
|
|
||||||
|
|
||||||
if (i->second->last_monitor() != (x = i->second->monitoring_input ())) {
|
|
||||||
i->second->set_last_monitor (x);
|
|
||||||
/* XXX I think this is dangerous, due to
|
|
||||||
a likely mutex in the signal handlers ...
|
|
||||||
*/
|
|
||||||
i->second->MonitorInputChanged (x); /* EMIT SIGNAL */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
last_monitor_check = next_processed_frames;
|
last_monitor_check = next_processed_frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_session->silent()) {
|
if (_session->silent()) {
|
||||||
|
PortManager::silence (nframes);
|
||||||
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
|
|
||||||
|
|
||||||
if (i->second->sends_output()) {
|
|
||||||
i->second->get_buffer(nframes).silence(nframes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session_remove_pending && session_removal_countdown) {
|
if (session_remove_pending && session_removal_countdown) {
|
||||||
|
|
||||||
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
|
PortManager::fade_out (session_removal_gain, session_removal_gain_step, nframes);
|
||||||
|
|
||||||
if (i->second->sends_output()) {
|
|
||||||
|
|
||||||
boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
|
|
||||||
if (ap) {
|
|
||||||
Sample* s = ap->engine_get_whole_audio_buffer ();
|
|
||||||
gain_t g = session_removal_gain;
|
|
||||||
|
|
||||||
for (pframes_t n = 0; n < nframes; ++n) {
|
|
||||||
*s++ *= g;
|
|
||||||
g -= session_removal_gain_step;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session_removal_countdown > nframes) {
|
if (session_removal_countdown > nframes) {
|
||||||
session_removal_countdown -= nframes;
|
session_removal_countdown -= nframes;
|
||||||
|
|
@ -339,11 +294,7 @@ AudioEngine::process_callback (pframes_t nframes)
|
||||||
session_removal_gain -= (nframes * session_removal_gain_step);
|
session_removal_gain -= (nframes * session_removal_gain_step);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalize ports
|
PortManager::cycle_end (nframes);
|
||||||
|
|
||||||
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
|
|
||||||
i->second->cycle_end (nframes);
|
|
||||||
}
|
|
||||||
|
|
||||||
_processed_frames = next_processed_frames;
|
_processed_frames = next_processed_frames;
|
||||||
|
|
||||||
|
|
@ -603,31 +554,45 @@ AudioEngine::start ()
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_running) {
|
if (_running) {
|
||||||
|
return 0;
|
||||||
if (_session) {
|
|
||||||
BootMessage (_("Connect session to engine"));
|
|
||||||
_session->set_frame_rate (_backend->sample_rate());
|
|
||||||
}
|
|
||||||
|
|
||||||
_processed_frames = 0;
|
|
||||||
last_monitor_check = 0;
|
|
||||||
|
|
||||||
if (_backend->start() == 0) {
|
|
||||||
_running = true;
|
|
||||||
last_monitor_check = 0;
|
|
||||||
|
|
||||||
if (_session && _session->config.get_jack_time_master()) {
|
|
||||||
_backend->set_time_master (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Running(); /* EMIT SIGNAL */
|
|
||||||
} else {
|
|
||||||
/* should report error? */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return _running ? 0 : -1;
|
/* if we're still connected (i.e. previously paused), no need to
|
||||||
|
* re-register ports.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool have_ports = (!ports.reader()->empty());
|
||||||
|
|
||||||
|
_processed_frames = 0;
|
||||||
|
last_monitor_check = 0;
|
||||||
|
|
||||||
|
if (_backend->start() == 0) {
|
||||||
|
|
||||||
|
_running = true;
|
||||||
|
last_monitor_check = 0;
|
||||||
|
|
||||||
|
if (_session) {
|
||||||
|
_session->set_frame_rate (_backend->sample_rate());
|
||||||
|
|
||||||
|
if (_session->config.get_jack_time_master()) {
|
||||||
|
_backend->set_time_master (true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!have_ports) {
|
||||||
|
PortManager::create_ports ();
|
||||||
|
}
|
||||||
|
|
||||||
|
_mmc.set_ports (mmc_input_port(), mmc_output_port());
|
||||||
|
|
||||||
|
Running(); /* EMIT SIGNAL */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* should report error ... */
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -641,6 +606,7 @@ AudioEngine::stop ()
|
||||||
|
|
||||||
if (_backend->stop () == 0) {
|
if (_backend->stop () == 0) {
|
||||||
_running = false;
|
_running = false;
|
||||||
|
_processed_frames = 0;
|
||||||
stop_metering_thread ();
|
stop_metering_thread ();
|
||||||
|
|
||||||
Stopped (); /* EMIT SIGNAL */
|
Stopped (); /* EMIT SIGNAL */
|
||||||
|
|
@ -932,7 +898,7 @@ AudioEngine::thread_init_callback (void* arg)
|
||||||
|
|
||||||
SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
|
SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512);
|
||||||
|
|
||||||
MIDI::JackMIDIPort::set_process_thread (pthread_self());
|
AsyncMIDIPort::set_process_thread (pthread_self());
|
||||||
|
|
||||||
if (arg) {
|
if (arg) {
|
||||||
AudioEngine* ae = static_cast<AudioEngine*> (arg);
|
AudioEngine* ae = static_cast<AudioEngine*> (arg);
|
||||||
|
|
@ -964,10 +930,10 @@ void
|
||||||
AudioEngine::freewheel_callback (bool onoff)
|
AudioEngine::freewheel_callback (bool onoff)
|
||||||
{
|
{
|
||||||
if (onoff) {
|
if (onoff) {
|
||||||
_pre_freewheel_mmc_enabled = MIDI::Manager::instance()->mmc()->send_enabled ();
|
_pre_freewheel_mmc_enabled = _mmc.send_enabled ();
|
||||||
MIDI::Manager::instance()->mmc()->enable_send (false);
|
_mmc.enable_send (false);
|
||||||
} else {
|
} else {
|
||||||
MIDI::Manager::instance()->mmc()->enable_send (_pre_freewheel_mmc_enabled);
|
_mmc.enable_send (_pre_freewheel_mmc_enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -991,8 +957,6 @@ void
|
||||||
AudioEngine::halted_callback (const char* why)
|
AudioEngine::halted_callback (const char* why)
|
||||||
{
|
{
|
||||||
stop_metering_thread ();
|
stop_metering_thread ();
|
||||||
|
|
||||||
MIDI::JackMIDIPort::EngineHalted (); /* EMIT SIGNAL */
|
|
||||||
Halted (why); /* EMIT SIGNAL */
|
Halted (why); /* EMIT SIGNAL */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,5 +60,6 @@ uint64_t PBD::DEBUG::TempoMap = PBD::new_debug_bit ("tempomap");
|
||||||
uint64_t PBD::DEBUG::OrderKeys = PBD::new_debug_bit ("orderkeys");
|
uint64_t PBD::DEBUG::OrderKeys = PBD::new_debug_bit ("orderkeys");
|
||||||
uint64_t PBD::DEBUG::Automation = PBD::new_debug_bit ("automation");
|
uint64_t PBD::DEBUG::Automation = PBD::new_debug_bit ("automation");
|
||||||
uint64_t PBD::DEBUG::WiimoteControl = PBD::new_debug_bit ("wiimotecontrol");
|
uint64_t PBD::DEBUG::WiimoteControl = PBD::new_debug_bit ("wiimotecontrol");
|
||||||
|
uint64_t PBD::DEBUG::Ports = PBD::new_debug_bit ("Ports");
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,6 @@
|
||||||
#include "pbd/basename.h"
|
#include "pbd/basename.h"
|
||||||
|
|
||||||
#include "midi++/port.h"
|
#include "midi++/port.h"
|
||||||
#include "midi++/manager.h"
|
|
||||||
#include "midi++/mmc.h"
|
#include "midi++/mmc.h"
|
||||||
|
|
||||||
#include "ardour/analyser.h"
|
#include "ardour/analyser.h"
|
||||||
|
|
@ -80,6 +79,7 @@
|
||||||
#include "ardour/control_protocol_manager.h"
|
#include "ardour/control_protocol_manager.h"
|
||||||
#include "ardour/filesystem_paths.h"
|
#include "ardour/filesystem_paths.h"
|
||||||
#include "ardour/midi_region.h"
|
#include "ardour/midi_region.h"
|
||||||
|
#include "ardour/midiport_manager.h"
|
||||||
#include "ardour/mix.h"
|
#include "ardour/mix.h"
|
||||||
#include "ardour/panner_manager.h"
|
#include "ardour/panner_manager.h"
|
||||||
#include "ardour/plugin_manager.h"
|
#include "ardour/plugin_manager.h"
|
||||||
|
|
@ -340,9 +340,6 @@ ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir
|
||||||
void
|
void
|
||||||
ARDOUR::init_post_engine ()
|
ARDOUR::init_post_engine ()
|
||||||
{
|
{
|
||||||
/* the MIDI Manager is needed by the ControlProtocolManager */
|
|
||||||
MIDI::Manager::create (AudioEngine::instance()->port_engine());
|
|
||||||
|
|
||||||
ControlProtocolManager::instance().discover_control_protocols ();
|
ControlProtocolManager::instance().discover_control_protocols ();
|
||||||
|
|
||||||
XMLNode* node;
|
XMLNode* node;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@
|
||||||
|
|
||||||
#include "pbd/error.h"
|
#include "pbd/error.h"
|
||||||
|
|
||||||
#include "midi++/manager.h"
|
#include "jack/jack.h"
|
||||||
|
#include "jack/thread.h"
|
||||||
|
|
||||||
#include "ardour/audioengine.h"
|
#include "ardour/audioengine.h"
|
||||||
#include "ardour/types.h"
|
#include "ardour/types.h"
|
||||||
|
|
@ -57,6 +58,7 @@ JACKAudioBackend::JACKAudioBackend (AudioEngine& e, boost::shared_ptr<JackConnec
|
||||||
, _target_systemic_input_latency (0)
|
, _target_systemic_input_latency (0)
|
||||||
, _target_systemic_output_latency (0)
|
, _target_systemic_output_latency (0)
|
||||||
{
|
{
|
||||||
|
_jack_connection->Disconnected.connect_same_thread (disconnect_connection, boost::bind (&JACKAudioBackend::disconnected, this, _1));
|
||||||
}
|
}
|
||||||
|
|
||||||
JACKAudioBackend::~JACKAudioBackend()
|
JACKAudioBackend::~JACKAudioBackend()
|
||||||
|
|
@ -897,8 +899,6 @@ JACKAudioBackend::jack_bufsize_callback (pframes_t nframes)
|
||||||
void
|
void
|
||||||
JACKAudioBackend::disconnected (const char* why)
|
JACKAudioBackend::disconnected (const char* why)
|
||||||
{
|
{
|
||||||
/* called from jack shutdown handler */
|
|
||||||
|
|
||||||
bool was_running = _running;
|
bool was_running = _running;
|
||||||
|
|
||||||
_running = false;
|
_running = false;
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,10 @@ JackConnection::close ()
|
||||||
GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
|
GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
|
||||||
|
|
||||||
if (_priv_jack) {
|
if (_priv_jack) {
|
||||||
return jack_client_close (_priv_jack);
|
int ret = jack_client_close (_priv_jack);
|
||||||
|
_jack = 0;
|
||||||
|
Disconnected (""); /* EMIT SIGNAL */
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,6 @@
|
||||||
#include "pbd/xml++.h"
|
#include "pbd/xml++.h"
|
||||||
#include "pbd/stacktrace.h"
|
#include "pbd/stacktrace.h"
|
||||||
|
|
||||||
#include "midi++/manager.h"
|
|
||||||
|
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
#include "ardour/ladspa_plugin.h"
|
#include "ardour/ladspa_plugin.h"
|
||||||
#include "ardour/buffer_set.h"
|
#include "ardour/buffer_set.h"
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,8 @@
|
||||||
#include "midi++/port.h"
|
#include "midi++/port.h"
|
||||||
|
|
||||||
#include "ardour/debug.h"
|
#include "ardour/debug.h"
|
||||||
|
#include "ardour/midi_buffer.h"
|
||||||
|
#include "ardour/midi_port.h"
|
||||||
#include "ardour/slave.h"
|
#include "ardour/slave.h"
|
||||||
#include "ardour/tempo.h"
|
#include "ardour/tempo.h"
|
||||||
|
|
||||||
|
|
@ -41,13 +43,20 @@ using namespace ARDOUR;
|
||||||
using namespace MIDI;
|
using namespace MIDI;
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
|
|
||||||
MIDIClock_Slave::MIDIClock_Slave (Session& s, MIDI::Port& p, int ppqn)
|
MIDIClock_Slave::MIDIClock_Slave (Session& s, MidiPort& p, int ppqn)
|
||||||
: ppqn (ppqn)
|
: ppqn (ppqn)
|
||||||
, bandwidth (10.0 / 60.0) // 1 BpM = 1 / 60 Hz
|
, bandwidth (10.0 / 60.0) // 1 BpM = 1 / 60 Hz
|
||||||
{
|
{
|
||||||
session = (ISlaveSessionProxy *) new SlaveSessionProxy(s);
|
session = (ISlaveSessionProxy *) new SlaveSessionProxy(s);
|
||||||
rebind (p);
|
rebind (p);
|
||||||
reset ();
|
reset ();
|
||||||
|
|
||||||
|
parser.timing.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::update_midi_clock, this, _1, _2));
|
||||||
|
parser.start.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::start, this, _1, _2));
|
||||||
|
parser.contineu.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::contineu, this, _1, _2));
|
||||||
|
parser.stop.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::stop, this, _1, _2));
|
||||||
|
parser.position.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::position, this, _1, _2, 3));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MIDIClock_Slave::MIDIClock_Slave (ISlaveSessionProxy* session_proxy, int ppqn)
|
MIDIClock_Slave::MIDIClock_Slave (ISlaveSessionProxy* session_proxy, int ppqn)
|
||||||
|
|
@ -63,20 +72,33 @@ MIDIClock_Slave::~MIDIClock_Slave()
|
||||||
delete session;
|
delete session;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
MIDIClock_Slave::rebind (MIDI::Port& p)
|
MIDIClock_Slave::process (pframes_t nframes)
|
||||||
{
|
{
|
||||||
port_connections.drop_connections();
|
MidiBuffer& mb (port->get_midi_buffer (nframes));
|
||||||
|
|
||||||
|
/* dump incoming MIDI to parser */
|
||||||
|
|
||||||
|
for (MidiBuffer::iterator b = mb.begin(); b != mb.end(); ++b) {
|
||||||
|
uint8_t* buf = (*b).buffer();
|
||||||
|
|
||||||
|
parser.set_timestamp ((*b).time());
|
||||||
|
|
||||||
|
uint32_t limit = (*b).size();
|
||||||
|
|
||||||
|
for (size_t n = 0; n < limit; ++n) {
|
||||||
|
parser.scanner (buf[n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MIDIClock_Slave::rebind (MidiPort& p)
|
||||||
|
{
|
||||||
port = &p;
|
port = &p;
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("MIDIClock_Slave: connecting to port %1\n", port->name()));
|
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("MIDIClock_Slave: connecting to port %1\n", port->name()));
|
||||||
|
|
||||||
port->parser()->timing.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::update_midi_clock, this, _1, _2));
|
|
||||||
port->parser()->start.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::start, this, _1, _2));
|
|
||||||
port->parser()->contineu.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::contineu, this, _1, _2));
|
|
||||||
port->parser()->stop.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::stop, this, _1, _2));
|
|
||||||
port->parser()->position.connect_same_thread (port_connections, boost::bind (&MIDIClock_Slave::position, this, _1, _2, 3));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,11 @@
|
||||||
|
|
||||||
#include "pbd/pthread_utils.h"
|
#include "pbd/pthread_utils.h"
|
||||||
|
|
||||||
#include "midi++/manager.h"
|
#include "ardour/async_midi_port.h"
|
||||||
#include "midi++/port.h"
|
|
||||||
|
|
||||||
#include "ardour/debug.h"
|
#include "ardour/debug.h"
|
||||||
#include "ardour/audioengine.h"
|
#include "ardour/audioengine.h"
|
||||||
|
#include "ardour/midi_port.h"
|
||||||
|
#include "ardour/midiport_manager.h"
|
||||||
#include "ardour/midi_ui.h"
|
#include "ardour/midi_ui.h"
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
#include "ardour/session_event.h"
|
#include "ardour/session_event.h"
|
||||||
|
|
@ -48,7 +48,6 @@ MidiControlUI::MidiControlUI (Session& s)
|
||||||
: AbstractUI<MidiUIRequest> (X_("midiui"))
|
: AbstractUI<MidiUIRequest> (X_("midiui"))
|
||||||
, _session (s)
|
, _session (s)
|
||||||
{
|
{
|
||||||
MIDI::Manager::instance()->PortsChanged.connect_same_thread (rebind_connection, boost::bind (&MidiControlUI::change_midi_ports, this));
|
|
||||||
_instance = this;
|
_instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,20 +82,10 @@ MidiControlUI::do_request (MidiUIRequest* req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
MidiControlUI::change_midi_ports ()
|
|
||||||
{
|
|
||||||
MidiUIRequest* req = get_request (PortChange);
|
|
||||||
if (req == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
send_request (req);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MidiControlUI::midi_input_handler (IOCondition ioc, MIDI::Port* port)
|
MidiControlUI::midi_input_handler (IOCondition ioc, AsyncMIDIPort* port)
|
||||||
{
|
{
|
||||||
DEBUG_TRACE (DEBUG::MidiIO, string_compose ("something happend on %1\n", port->name()));
|
DEBUG_TRACE (DEBUG::MidiIO, string_compose ("something happend on %1\n", ((ARDOUR::Port*)port)->name()));
|
||||||
|
|
||||||
if (ioc & ~IO_IN) {
|
if (ioc & ~IO_IN) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -106,7 +95,7 @@ MidiControlUI::midi_input_handler (IOCondition ioc, MIDI::Port* port)
|
||||||
|
|
||||||
CrossThreadChannel::drain (port->selectable());
|
CrossThreadChannel::drain (port->selectable());
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::MidiIO, string_compose ("data available on %1\n", port->name()));
|
DEBUG_TRACE (DEBUG::MidiIO, string_compose ("data available on %1\n", ((ARDOUR::Port*)port)->name()));
|
||||||
framepos_t now = _session.engine().sample_time();
|
framepos_t now = _session.engine().sample_time();
|
||||||
port->parse (now);
|
port->parse (now);
|
||||||
}
|
}
|
||||||
|
|
@ -128,22 +117,19 @@ MidiControlUI::clear_ports ()
|
||||||
void
|
void
|
||||||
MidiControlUI::reset_ports ()
|
MidiControlUI::reset_ports ()
|
||||||
{
|
{
|
||||||
clear_ports ();
|
if (port_sources.empty()) {
|
||||||
|
AsyncMIDIPort* async = dynamic_cast<AsyncMIDIPort*> (AudioEngine::instance()->midi_input_port());
|
||||||
|
|
||||||
boost::shared_ptr<const MIDI::Manager::PortList> plist = MIDI::Manager::instance()->get_midi_ports ();
|
if (!async) {
|
||||||
|
return;
|
||||||
for (MIDI::Manager::PortList::const_iterator i = plist->begin(); i != plist->end(); ++i) {
|
|
||||||
|
|
||||||
if (!(*i)->centrally_parsed()) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if ((fd = (*i)->selectable ()) >= 0) {
|
if ((fd = async->selectable ()) >= 0) {
|
||||||
Glib::RefPtr<IOSource> psrc = IOSource::create (fd, IO_IN|IO_HUP|IO_ERR);
|
Glib::RefPtr<IOSource> psrc = IOSource::create (fd, IO_IN|IO_HUP|IO_ERR);
|
||||||
|
|
||||||
psrc->connect (sigc::bind (sigc::mem_fun (this, &MidiControlUI::midi_input_handler), *i));
|
psrc->connect (sigc::bind (sigc::mem_fun (this, &MidiControlUI::midi_input_handler), async));
|
||||||
psrc->attach (_main_loop->get_context());
|
psrc->attach (_main_loop->get_context());
|
||||||
|
|
||||||
// glibmm hack: for now, store only the GSource*
|
// glibmm hack: for now, store only the GSource*
|
||||||
|
|
|
||||||
|
|
@ -66,11 +66,47 @@ MidiPortManager::port (string const & n)
|
||||||
void
|
void
|
||||||
MidiPortManager::create_ports ()
|
MidiPortManager::create_ports ()
|
||||||
{
|
{
|
||||||
_midi_in = AudioEngine::instance()->register_input_port (DataType::MIDI, _("MIDI control in"), true);
|
/* this method is idempotent
|
||||||
_midi_out = AudioEngine::instance()->register_output_port (DataType::MIDI, _("MIDI control out"), true);
|
*/
|
||||||
|
|
||||||
|
if (_midi_in) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_midi_in = AudioEngine::instance()->register_input_port (DataType::MIDI, _("control in"), true);
|
||||||
|
_midi_out = AudioEngine::instance()->register_output_port (DataType::MIDI, _("control out"), true);
|
||||||
|
|
||||||
|
_mmc_in = AudioEngine::instance()->register_input_port (DataType::MIDI, _("mmc in"), true);
|
||||||
|
_mmc_out = AudioEngine::instance()->register_output_port (DataType::MIDI, _("mmc out"), true);
|
||||||
|
|
||||||
|
/* XXX nasty type conversion needed because of the mixed inheritance
|
||||||
|
* required to integrate MIDI::IPMidiPort and ARDOUR::AsyncMIDIPort.
|
||||||
|
*
|
||||||
|
* At some point, we'll move IPMidiPort into Ardour and make it
|
||||||
|
* inherit from ARDOUR::MidiPort not MIDI::Port, and then this
|
||||||
|
* mess can go away
|
||||||
|
*/
|
||||||
|
|
||||||
_midi_input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_midi_in).get();
|
_midi_input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_midi_in).get();
|
||||||
_midi_output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_midi_out).get();
|
_midi_output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_midi_out).get();
|
||||||
|
|
||||||
|
_mmc_input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_mmc_in).get();
|
||||||
|
_mmc_output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_mmc_out).get();
|
||||||
|
|
||||||
|
/* Now register ports used for sync (MTC and MIDI Clock)
|
||||||
|
*/
|
||||||
|
|
||||||
|
boost::shared_ptr<ARDOUR::Port> p;
|
||||||
|
|
||||||
|
p = AudioEngine::instance()->register_input_port (DataType::MIDI, _("timecode in"));
|
||||||
|
_mtc_input_port = boost::dynamic_pointer_cast<MidiPort> (p);
|
||||||
|
p = AudioEngine::instance()->register_output_port (DataType::MIDI, _("timecode out"));
|
||||||
|
_mtc_output_port= boost::dynamic_pointer_cast<MidiPort> (p);
|
||||||
|
|
||||||
|
p = AudioEngine::instance()->register_input_port (DataType::MIDI, _("clock in"));
|
||||||
|
_midi_clock_input_port = boost::dynamic_pointer_cast<MidiPort> (p);
|
||||||
|
p = AudioEngine::instance()->register_output_port (DataType::MIDI, _("clock out"));
|
||||||
|
_midi_clock_output_port= boost::dynamic_pointer_cast<MidiPort> (p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -25,11 +25,12 @@
|
||||||
|
|
||||||
#include "pbd/error.h"
|
#include "pbd/error.h"
|
||||||
|
|
||||||
#include "midi++/port.h"
|
|
||||||
#include "ardour/debug.h"
|
|
||||||
#include "ardour/slave.h"
|
|
||||||
#include "ardour/session.h"
|
|
||||||
#include "ardour/audioengine.h"
|
#include "ardour/audioengine.h"
|
||||||
|
#include "ardour/debug.h"
|
||||||
|
#include "ardour/midi_buffer.h"
|
||||||
|
#include "ardour/midi_port.h"
|
||||||
|
#include "ardour/session.h"
|
||||||
|
#include "ardour/slave.h"
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
|
@ -48,8 +49,9 @@ using namespace Timecode;
|
||||||
*/
|
*/
|
||||||
const int MTC_Slave::frame_tolerance = 2;
|
const int MTC_Slave::frame_tolerance = 2;
|
||||||
|
|
||||||
MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
|
MTC_Slave::MTC_Slave (Session& s, MidiPort& p)
|
||||||
: session (s)
|
: session (s)
|
||||||
|
, port (&p)
|
||||||
{
|
{
|
||||||
can_notify_on_unknown_rate = true;
|
can_notify_on_unknown_rate = true;
|
||||||
did_reset_tc_format = false;
|
did_reset_tc_format = false;
|
||||||
|
|
@ -70,7 +72,11 @@ MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
|
||||||
session.config.ParameterChanged.connect_same_thread (config_connection, boost::bind (&MTC_Slave::parameter_changed, this, _1));
|
session.config.ParameterChanged.connect_same_thread (config_connection, boost::bind (&MTC_Slave::parameter_changed, this, _1));
|
||||||
parse_timecode_offset();
|
parse_timecode_offset();
|
||||||
reset (true);
|
reset (true);
|
||||||
rebind (p);
|
|
||||||
|
parser.mtc_time.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_time, this, _1, _2, _3));
|
||||||
|
parser.mtc_qtr.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_qtr, this, _1, _2, _3));
|
||||||
|
parser.mtc_status.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_status, this, _1));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MTC_Slave::~MTC_Slave()
|
MTC_Slave::~MTC_Slave()
|
||||||
|
|
@ -93,16 +99,35 @@ MTC_Slave::~MTC_Slave()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
MTC_Slave::process (pframes_t nframes)
|
||||||
|
{
|
||||||
|
MidiBuffer& mb (port->get_midi_buffer (nframes));
|
||||||
|
|
||||||
|
/* dump incoming MIDI to parser */
|
||||||
|
|
||||||
|
for (MidiBuffer::iterator b = mb.begin(); b != mb.end(); ++b) {
|
||||||
|
uint8_t* buf = (*b).buffer();
|
||||||
|
|
||||||
|
parser.set_timestamp ((*b).time());
|
||||||
|
|
||||||
|
uint32_t limit = (*b).size();
|
||||||
|
|
||||||
|
for (size_t n = 0; n < limit; ++n) {
|
||||||
|
parser.scanner (buf[n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MTC_Slave::rebind (MIDI::Port& p)
|
MTC_Slave::rebind (MidiPort& p)
|
||||||
{
|
{
|
||||||
port_connections.drop_connections ();
|
port_connections.drop_connections ();
|
||||||
|
|
||||||
port = &p;
|
port = &p;
|
||||||
|
|
||||||
port->parser()->mtc_time.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_time, this, _1, _2, _3));
|
|
||||||
port->parser()->mtc_qtr.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_qtr, this, _1, _2, _3));
|
|
||||||
port->parser()->mtc_status.connect_same_thread (port_connections, boost::bind (&MTC_Slave::update_mtc_status, this, _1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -154,7 +179,7 @@ MTC_Slave::outside_window (framepos_t pos) const
|
||||||
bool
|
bool
|
||||||
MTC_Slave::locked () const
|
MTC_Slave::locked () const
|
||||||
{
|
{
|
||||||
return port->parser()->mtc_locked() && last_inbound_frame !=0 && engine_dll_initstate !=0;
|
return parser.mtc_locked() && last_inbound_frame !=0 && engine_dll_initstate !=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -446,7 +471,7 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full, framepos_t now)
|
||||||
DEBUG_TRACE (DEBUG::MTC, string_compose ("new mtc_frame: %1 | MTC-FpT: %2 A3-FpT:%3\n",
|
DEBUG_TRACE (DEBUG::MTC, string_compose ("new mtc_frame: %1 | MTC-FpT: %2 A3-FpT:%3\n",
|
||||||
mtc_frame, (4.0*qtr), session.frames_per_timecode_frame()));
|
mtc_frame, (4.0*qtr), session.frames_per_timecode_frame()));
|
||||||
|
|
||||||
switch (port->parser()->mtc_running()) {
|
switch (parser.mtc_running()) {
|
||||||
case MTC_Backward:
|
case MTC_Backward:
|
||||||
mtc_frame -= mtc_off;
|
mtc_frame -= mtc_off;
|
||||||
qtr *= -1.0;
|
qtr *= -1.0;
|
||||||
|
|
@ -528,7 +553,7 @@ MTC_Slave::reset_window (framepos_t root)
|
||||||
*/
|
*/
|
||||||
framecnt_t const d = (quarter_frame_duration * 4 * frame_tolerance);
|
framecnt_t const d = (quarter_frame_duration * 4 * frame_tolerance);
|
||||||
|
|
||||||
switch (port->parser()->mtc_running()) {
|
switch (parser.mtc_running()) {
|
||||||
case MTC_Forward:
|
case MTC_Forward:
|
||||||
window_begin = root;
|
window_begin = root;
|
||||||
transport_direction = 1;
|
transport_direction = 1;
|
||||||
|
|
|
||||||
|
|
@ -390,6 +390,7 @@ Port::get_connected_latency_range (LatencyRange& range, bool playback) const
|
||||||
int
|
int
|
||||||
Port::reestablish ()
|
Port::reestablish ()
|
||||||
{
|
{
|
||||||
|
DEBUG_TRACE (DEBUG::Ports, string_compose ("re-establish %1 port %2\n", type().to_string(), _name));
|
||||||
_port_handle = port_engine.register_port (_name, type(), _flags);
|
_port_handle = port_engine.register_port (_name, type(), _flags);
|
||||||
|
|
||||||
if (_port_handle == 0) {
|
if (_port_handle == 0) {
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,12 @@
|
||||||
|
|
||||||
#include "pbd/error.h"
|
#include "pbd/error.h"
|
||||||
|
|
||||||
#include "midi++/manager.h"
|
#include "ardour/async_midi_port.h"
|
||||||
|
#include "ardour/debug.h"
|
||||||
#include "ardour/port_manager.h"
|
#include "ardour/port_manager.h"
|
||||||
#include "ardour/audio_port.h"
|
#include "ardour/audio_port.h"
|
||||||
#include "ardour/midi_port.h"
|
#include "ardour/midi_port.h"
|
||||||
|
#include "ardour/midiport_manager.h"
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
|
@ -227,6 +228,18 @@ PortManager::port_renamed (const std::string& old_relative_name, const std::stri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PortManager::get_ports (DataType type, PortList& pl)
|
||||||
|
{
|
||||||
|
boost::shared_ptr<Ports> plist = ports.reader();
|
||||||
|
for (Ports::iterator p = plist->begin(); p != plist->end(); ++p) {
|
||||||
|
if (p->second->type() == type) {
|
||||||
|
pl.push_back (p->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pl.size();
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
PortManager::get_ports (const string& port_name_pattern, DataType type, PortFlags flags, vector<string>& s)
|
PortManager::get_ports (const string& port_name_pattern, DataType type, PortFlags flags, vector<string>& s)
|
||||||
{
|
{
|
||||||
|
|
@ -262,15 +275,25 @@ PortManager::port_registration_failure (const std::string& portname)
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<Port>
|
boost::shared_ptr<Port>
|
||||||
PortManager::register_port (DataType dtype, const string& portname, bool input)
|
PortManager::register_port (DataType dtype, const string& portname, bool input, bool async)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Port> newport;
|
boost::shared_ptr<Port> newport;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (dtype == DataType::AUDIO) {
|
if (dtype == DataType::AUDIO) {
|
||||||
|
DEBUG_TRACE (DEBUG::Ports, string_compose ("registering AUDIO port %1, input %2\n",
|
||||||
|
portname, input));
|
||||||
newport.reset (new AudioPort (portname, (input ? IsInput : IsOutput)));
|
newport.reset (new AudioPort (portname, (input ? IsInput : IsOutput)));
|
||||||
} else if (dtype == DataType::MIDI) {
|
} else if (dtype == DataType::MIDI) {
|
||||||
newport.reset (new MidiPort (portname, (input ? IsInput : IsOutput)));
|
if (async) {
|
||||||
|
DEBUG_TRACE (DEBUG::Ports, string_compose ("registering ASYNC MIDI port %1, input %2\n",
|
||||||
|
portname, input));
|
||||||
|
newport.reset (new AsyncMIDIPort (portname, (input ? IsInput : IsOutput)));
|
||||||
|
} else {
|
||||||
|
DEBUG_TRACE (DEBUG::Ports, string_compose ("registering MIDI port %1, input %2\n",
|
||||||
|
portname, input));
|
||||||
|
newport.reset (new MidiPort (portname, (input ? IsInput : IsOutput)));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw PortRegistrationFailure("unable to create port (unknown type)");
|
throw PortRegistrationFailure("unable to create port (unknown type)");
|
||||||
}
|
}
|
||||||
|
|
@ -281,7 +304,6 @@ PortManager::register_port (DataType dtype, const string& portname, bool input)
|
||||||
|
|
||||||
/* writer goes out of scope, forces update */
|
/* writer goes out of scope, forces update */
|
||||||
|
|
||||||
return newport;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (PortRegistrationFailure& err) {
|
catch (PortRegistrationFailure& err) {
|
||||||
|
|
@ -292,18 +314,21 @@ PortManager::register_port (DataType dtype, const string& portname, bool input)
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
throw PortRegistrationFailure("unable to create port (unknown error)");
|
throw PortRegistrationFailure("unable to create port (unknown error)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG_TRACE (DEBUG::Ports, string_compose ("\t%2 port registration success, ports now = %1\n", ports.reader()->size(), this));
|
||||||
|
return newport;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<Port>
|
boost::shared_ptr<Port>
|
||||||
PortManager::register_input_port (DataType type, const string& portname)
|
PortManager::register_input_port (DataType type, const string& portname, bool async)
|
||||||
{
|
{
|
||||||
return register_port (type, portname, true);
|
return register_port (type, portname, true, async);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<Port>
|
boost::shared_ptr<Port>
|
||||||
PortManager::register_output_port (DataType type, const string& portname)
|
PortManager::register_output_port (DataType type, const string& portname, bool async)
|
||||||
{
|
{
|
||||||
return register_port (type, portname, false);
|
return register_port (type, portname, false, async);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -410,6 +435,8 @@ PortManager::reestablish_ports ()
|
||||||
|
|
||||||
boost::shared_ptr<Ports> p = ports.reader ();
|
boost::shared_ptr<Ports> p = ports.reader ();
|
||||||
|
|
||||||
|
DEBUG_TRACE (DEBUG::Ports, string_compose ("reestablish %1 ports\n", p->size()));
|
||||||
|
|
||||||
for (i = p->begin(); i != p->end(); ++i) {
|
for (i = p->begin(); i != p->end(); ++i) {
|
||||||
if (i->second->reestablish ()) {
|
if (i->second->reestablish ()) {
|
||||||
break;
|
break;
|
||||||
|
|
@ -422,8 +449,6 @@ PortManager::reestablish_ports ()
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
MIDI::Manager::instance()->reestablish ();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -434,12 +459,12 @@ PortManager::reconnect_ports ()
|
||||||
|
|
||||||
/* re-establish connections */
|
/* re-establish connections */
|
||||||
|
|
||||||
|
DEBUG_TRACE (DEBUG::Ports, string_compose ("reconnect %1 ports\n", p->size()));
|
||||||
|
|
||||||
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
|
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
|
||||||
i->second->reconnect ();
|
i->second->reconnect ();
|
||||||
}
|
}
|
||||||
|
|
||||||
MIDI::Manager::instance()->reconnect ();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -543,3 +568,80 @@ PortManager::graph_order_callback ()
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PortManager::cycle_start (pframes_t nframes)
|
||||||
|
{
|
||||||
|
Port::set_global_port_buffer_offset (0);
|
||||||
|
Port::set_cycle_framecnt (nframes);
|
||||||
|
|
||||||
|
_cycle_ports = ports.reader ();
|
||||||
|
|
||||||
|
for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
|
||||||
|
p->second->cycle_start (nframes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PortManager::cycle_end (pframes_t nframes)
|
||||||
|
{
|
||||||
|
for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
|
||||||
|
p->second->cycle_end (nframes);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
|
||||||
|
p->second->flush_buffers (nframes);
|
||||||
|
}
|
||||||
|
|
||||||
|
_cycle_ports.reset ();
|
||||||
|
|
||||||
|
/* we are done */
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PortManager::silence (pframes_t nframes)
|
||||||
|
{
|
||||||
|
for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
|
||||||
|
if (i->second->sends_output()) {
|
||||||
|
i->second->get_buffer(nframes).silence(nframes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PortManager::check_monitoring ()
|
||||||
|
{
|
||||||
|
for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
|
||||||
|
|
||||||
|
bool x;
|
||||||
|
|
||||||
|
if (i->second->last_monitor() != (x = i->second->monitoring_input ())) {
|
||||||
|
i->second->set_last_monitor (x);
|
||||||
|
/* XXX I think this is dangerous, due to
|
||||||
|
a likely mutex in the signal handlers ...
|
||||||
|
*/
|
||||||
|
i->second->MonitorInputChanged (x); /* EMIT SIGNAL */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PortManager::fade_out (gain_t base_gain, gain_t gain_step, pframes_t nframes)
|
||||||
|
{
|
||||||
|
for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
|
||||||
|
|
||||||
|
if (i->second->sends_output()) {
|
||||||
|
|
||||||
|
boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
|
||||||
|
if (ap) {
|
||||||
|
Sample* s = ap->engine_get_whole_audio_buffer ();
|
||||||
|
gain_t g = base_gain;
|
||||||
|
|
||||||
|
for (pframes_t n = 0; n < nframes; ++n) {
|
||||||
|
*s++ *= g;
|
||||||
|
g -= gain_step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,13 +27,12 @@
|
||||||
#include "pbd/xml++.h"
|
#include "pbd/xml++.h"
|
||||||
#include "pbd/file_utils.h"
|
#include "pbd/file_utils.h"
|
||||||
|
|
||||||
#include "midi++/manager.h"
|
|
||||||
|
|
||||||
#include "ardour/control_protocol_manager.h"
|
#include "ardour/control_protocol_manager.h"
|
||||||
#include "ardour/diskstream.h"
|
#include "ardour/diskstream.h"
|
||||||
#include "ardour/filesystem_paths.h"
|
#include "ardour/filesystem_paths.h"
|
||||||
#include "ardour/rc_configuration.h"
|
#include "ardour/rc_configuration.h"
|
||||||
#include "ardour/session_metadata.h"
|
#include "ardour/session_metadata.h"
|
||||||
|
#include "ardour/midiport_manager.h"
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
|
@ -177,15 +176,20 @@ RCConfiguration::get_state ()
|
||||||
|
|
||||||
root = new XMLNode("Ardour");
|
root = new XMLNode("Ardour");
|
||||||
|
|
||||||
MIDI::Manager* mm = MIDI::Manager::instance();
|
/* XXX
|
||||||
|
* GET STATE OF MIDI::Port HERE
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
MidiPortManager* mm = MidiPortManager::instance();
|
||||||
|
|
||||||
if (mm) {
|
if (mm) {
|
||||||
boost::shared_ptr<const MIDI::Manager::PortList> ports = mm->get_midi_ports();
|
boost::shared_ptr<const MidiPortManager::PortList> ports = mm->get_midi_ports();
|
||||||
|
|
||||||
for (MIDI::Manager::PortList::const_iterator i = ports->begin(); i != ports->end(); ++i) {
|
for (MidiPortManager::PortList::const_iterator i = ports->begin(); i != ports->end(); ++i) {
|
||||||
root->add_child_nocopy((*i)->get_state());
|
// root->add_child_nocopy ((*i)->get_state());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
root->add_child_nocopy (get_variables ());
|
root->add_child_nocopy (get_variables ());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
|
|
||||||
#include "ardour/amp.h"
|
#include "ardour/amp.h"
|
||||||
#include "ardour/analyser.h"
|
#include "ardour/analyser.h"
|
||||||
|
#include "ardour/async_midi_port.h"
|
||||||
#include "ardour/audio_buffer.h"
|
#include "ardour/audio_buffer.h"
|
||||||
#include "ardour/audio_diskstream.h"
|
#include "ardour/audio_diskstream.h"
|
||||||
#include "ardour/audio_port.h"
|
#include "ardour/audio_port.h"
|
||||||
|
|
@ -66,6 +67,7 @@
|
||||||
#include "ardour/debug.h"
|
#include "ardour/debug.h"
|
||||||
#include "ardour/filename_extensions.h"
|
#include "ardour/filename_extensions.h"
|
||||||
#include "ardour/graph.h"
|
#include "ardour/graph.h"
|
||||||
|
#include "ardour/midiport_manager.h"
|
||||||
#include "ardour/midi_track.h"
|
#include "ardour/midi_track.h"
|
||||||
#include "ardour/midi_ui.h"
|
#include "ardour/midi_ui.h"
|
||||||
#include "ardour/operations.h"
|
#include "ardour/operations.h"
|
||||||
|
|
@ -88,9 +90,7 @@
|
||||||
#include "ardour/utils.h"
|
#include "ardour/utils.h"
|
||||||
|
|
||||||
#include "midi++/port.h"
|
#include "midi++/port.h"
|
||||||
#include "midi++/jack_midi_port.h"
|
|
||||||
#include "midi++/mmc.h"
|
#include "midi++/mmc.h"
|
||||||
#include "midi++/manager.h"
|
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
|
@ -584,7 +584,8 @@ Session::when_engine_running ()
|
||||||
as it will set states for ports which the ControlProtocolManager creates.
|
as it will set states for ports which the ControlProtocolManager creates.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MIDI::Manager::instance()->set_port_states (Config->midi_port_states ());
|
// XXX set state of MIDI::Port's
|
||||||
|
// MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
|
||||||
|
|
||||||
/* And this must be done after the MIDI::Manager::set_port_states as
|
/* And this must be done after the MIDI::Manager::set_port_states as
|
||||||
* it will try to make connections whose details are loaded by set_port_states.
|
* it will try to make connections whose details are loaded by set_port_states.
|
||||||
|
|
@ -874,7 +875,12 @@ Session::hookup_io ()
|
||||||
/* Tell all IO objects to connect themselves together */
|
/* Tell all IO objects to connect themselves together */
|
||||||
|
|
||||||
IO::enable_connecting ();
|
IO::enable_connecting ();
|
||||||
MIDI::JackMIDIPort::MakeConnections ();
|
|
||||||
|
/* Now tell all "floating" ports to connect to whatever
|
||||||
|
they should be connected to.
|
||||||
|
*/
|
||||||
|
|
||||||
|
AudioEngine::instance()->reconnect_ports ();
|
||||||
|
|
||||||
/* Anyone who cares about input state, wake up and do something */
|
/* Anyone who cares about input state, wake up and do something */
|
||||||
|
|
||||||
|
|
@ -1169,7 +1175,7 @@ Session::enable_record ()
|
||||||
if (g_atomic_int_compare_and_exchange (&_record_status, rs, Recording)) {
|
if (g_atomic_int_compare_and_exchange (&_record_status, rs, Recording)) {
|
||||||
|
|
||||||
_last_record_location = _transport_frame;
|
_last_record_location = _transport_frame;
|
||||||
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordStrobe));
|
AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordStrobe));
|
||||||
|
|
||||||
if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
|
if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
|
||||||
set_track_monitor_input_status (true);
|
set_track_monitor_input_status (true);
|
||||||
|
|
@ -1190,7 +1196,7 @@ Session::disable_record (bool rt_context, bool force)
|
||||||
|
|
||||||
if ((!Config->get_latched_record_enable () && !play_loop) || force) {
|
if ((!Config->get_latched_record_enable () && !play_loop) || force) {
|
||||||
g_atomic_int_set (&_record_status, Disabled);
|
g_atomic_int_set (&_record_status, Disabled);
|
||||||
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordExit));
|
AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordExit));
|
||||||
} else {
|
} else {
|
||||||
if (rs == Recording) {
|
if (rs == Recording) {
|
||||||
g_atomic_int_set (&_record_status, Enabled);
|
g_atomic_int_set (&_record_status, Enabled);
|
||||||
|
|
@ -1244,7 +1250,7 @@ Session::maybe_enable_record ()
|
||||||
enable_record ();
|
enable_record ();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordPause));
|
AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordPause));
|
||||||
RecordStateChanged (); /* EMIT SIGNAL */
|
RecordStateChanged (); /* EMIT SIGNAL */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@
|
||||||
#include "pbd/error.h"
|
#include "pbd/error.h"
|
||||||
#include <glibmm/threads.h>
|
#include <glibmm/threads.h>
|
||||||
|
|
||||||
#include <midi++/manager.h>
|
|
||||||
#include <midi++/mmc.h>
|
#include <midi++/mmc.h>
|
||||||
|
|
||||||
#include "ardour/audioengine.h"
|
#include "ardour/audioengine.h"
|
||||||
|
|
@ -93,8 +92,8 @@ Session::pre_export ()
|
||||||
|
|
||||||
/* disable MMC output early */
|
/* disable MMC output early */
|
||||||
|
|
||||||
_pre_export_mmc_enabled = MIDI::Manager::instance()->mmc()->send_enabled ();
|
_pre_export_mmc_enabled = AudioEngine::instance()->mmc().send_enabled ();
|
||||||
MIDI::Manager::instance()->mmc()->enable_send (false);
|
AudioEngine::instance()->mmc().enable_send (false);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -237,7 +236,7 @@ Session::finalize_audio_export ()
|
||||||
|
|
||||||
export_freewheel_connection.disconnect();
|
export_freewheel_connection.disconnect();
|
||||||
|
|
||||||
MIDI::Manager::instance()->mmc()->enable_send (_pre_export_mmc_enabled);
|
AudioEngine::instance()->mmc().enable_send (_pre_export_mmc_enabled);
|
||||||
|
|
||||||
/* maybe write CUE/TOC */
|
/* maybe write CUE/TOC */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@
|
||||||
|
|
||||||
#include "midi++/mmc.h"
|
#include "midi++/mmc.h"
|
||||||
#include "midi++/port.h"
|
#include "midi++/port.h"
|
||||||
#include "midi++/manager.h"
|
|
||||||
|
|
||||||
#include "pbd/error.h"
|
#include "pbd/error.h"
|
||||||
#include "pbd/pthread_utils.h"
|
#include "pbd/pthread_utils.h"
|
||||||
|
|
@ -41,6 +40,7 @@
|
||||||
#include "ardour/audio_track.h"
|
#include "ardour/audio_track.h"
|
||||||
#include "ardour/audioengine.h"
|
#include "ardour/audioengine.h"
|
||||||
#include "ardour/debug.h"
|
#include "ardour/debug.h"
|
||||||
|
#include "ardour/midi_port.h"
|
||||||
#include "ardour/midi_track.h"
|
#include "ardour/midi_track.h"
|
||||||
#include "ardour/midi_ui.h"
|
#include "ardour/midi_ui.h"
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
|
|
@ -349,7 +349,7 @@ Session::mmc_record_enable (MIDI::MachineControl &mmc, size_t trk, bool enabled)
|
||||||
* @param t time to send.
|
* @param t time to send.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
Session::send_full_time_code (framepos_t const t)
|
Session::send_full_time_code (framepos_t const t, pframes_t nframes)
|
||||||
{
|
{
|
||||||
/* This function could easily send at a given frame offset, but would
|
/* This function could easily send at a given frame offset, but would
|
||||||
* that be useful? Does ardour do sub-block accurate locating? [DR] */
|
* that be useful? Does ardour do sub-block accurate locating? [DR] */
|
||||||
|
|
@ -424,10 +424,9 @@ Session::send_full_time_code (framepos_t const t)
|
||||||
msg[8] = timecode.frames;
|
msg[8] = timecode.frames;
|
||||||
|
|
||||||
// Send message at offset 0, sent time is for the start of this cycle
|
// Send message at offset 0, sent time is for the start of this cycle
|
||||||
if (MIDI::Manager::instance()->mtc_output_port()->midimsg (msg, sizeof (msg), 0)) {
|
|
||||||
error << _("Session: could not send full MIDI time code") << endmsg;
|
MidiBuffer& mb (AudioEngine::instance()->mtc_output_port()->get_midi_buffer (nframes));
|
||||||
return -1;
|
mb.push_back (0, sizeof (msg), msg);
|
||||||
}
|
|
||||||
|
|
||||||
_pframes_since_last_mtc = 0;
|
_pframes_since_last_mtc = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -470,7 +469,7 @@ Session::send_midi_time_code_for_cycle (framepos_t start_frame, framepos_t end_f
|
||||||
next_quarter_frame_to_send, quarter_frame_duration));
|
next_quarter_frame_to_send, quarter_frame_duration));
|
||||||
|
|
||||||
if (rint(outbound_mtc_timecode_frame + (next_quarter_frame_to_send * quarter_frame_duration)) < _transport_frame) {
|
if (rint(outbound_mtc_timecode_frame + (next_quarter_frame_to_send * quarter_frame_duration)) < _transport_frame) {
|
||||||
send_full_time_code (_transport_frame);
|
send_full_time_code (_transport_frame, nframes);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -516,9 +515,10 @@ Session::send_midi_time_code_for_cycle (framepos_t start_frame, framepos_t end_f
|
||||||
pframes_t const out_stamp = (msg_time - start_frame) / _transport_speed;
|
pframes_t const out_stamp = (msg_time - start_frame) / _transport_speed;
|
||||||
assert (out_stamp < nframes);
|
assert (out_stamp < nframes);
|
||||||
|
|
||||||
if (MIDI::Manager::instance()->mtc_output_port()->midimsg (mtc_msg, 2, out_stamp)) {
|
MidiBuffer& mb (AudioEngine::instance()->mtc_output_port()->get_midi_buffer(nframes));
|
||||||
|
if (!mb.push_back (out_stamp, 2, mtc_msg)) {
|
||||||
error << string_compose(_("Session: cannot send quarter-frame MTC message (%1)"), strerror (errno))
|
error << string_compose(_("Session: cannot send quarter-frame MTC message (%1)"), strerror (errno))
|
||||||
<< endmsg;
|
<< endmsg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -588,7 +588,7 @@ Session::mmc_step_timeout ()
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Session::send_song_position_pointer (framepos_t t)
|
Session::send_song_position_pointer (framepos_t)
|
||||||
{
|
{
|
||||||
if (midi_clock) {
|
if (midi_clock) {
|
||||||
/* Do nothing for the moment */
|
/* Do nothing for the moment */
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,6 @@
|
||||||
#include "ardour/ticker.h"
|
#include "ardour/ticker.h"
|
||||||
#include "ardour/types.h"
|
#include "ardour/types.h"
|
||||||
|
|
||||||
#include "midi++/manager.h"
|
|
||||||
#include "midi++/mmc.h"
|
#include "midi++/mmc.h"
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
@ -85,7 +84,7 @@ Session::process (pframes_t nframes)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!_engine.freewheeling() && Config->get_send_midi_clock() && transport_speed() == 1.0f && midi_clock->has_midi_port()) {
|
if (!_engine.freewheeling() && Config->get_send_midi_clock() && transport_speed() == 1.0f && midi_clock->has_midi_port()) {
|
||||||
midi_clock->tick (transport_at_start);
|
midi_clock->tick (transport_at_start, nframes);
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
/* don't bother with a message */
|
/* don't bother with a message */
|
||||||
|
|
@ -325,7 +324,7 @@ Session::process_with_events (pframes_t nframes)
|
||||||
* and prepare for rolling)
|
* and prepare for rolling)
|
||||||
*/
|
*/
|
||||||
if (_send_timecode_update) {
|
if (_send_timecode_update) {
|
||||||
send_full_time_code (_transport_frame);
|
send_full_time_code (_transport_frame, nframes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!process_can_proceed()) {
|
if (!process_can_proceed()) {
|
||||||
|
|
@ -492,6 +491,7 @@ Session::follow_slave (pframes_t nframes)
|
||||||
goto noroll;
|
goto noroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_slave->process (nframes);
|
||||||
_slave->speed_and_position (slave_speed, slave_transport_frame);
|
_slave->speed_and_position (slave_speed, slave_transport_frame);
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
|
DEBUG_TRACE (DEBUG::Slave, string_compose ("Slave position %1 speed %2\n", slave_transport_frame, slave_speed));
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,6 @@
|
||||||
|
|
||||||
#include "midi++/mmc.h"
|
#include "midi++/mmc.h"
|
||||||
#include "midi++/port.h"
|
#include "midi++/port.h"
|
||||||
#include "midi++/manager.h"
|
|
||||||
|
|
||||||
#include "evoral/SMF.hpp"
|
#include "evoral/SMF.hpp"
|
||||||
|
|
||||||
|
|
@ -359,11 +358,11 @@ Session::second_stage_init ()
|
||||||
|
|
||||||
BootMessage (_("Reset Remote Controls"));
|
BootMessage (_("Reset Remote Controls"));
|
||||||
|
|
||||||
send_full_time_code (0);
|
// send_full_time_code (0);
|
||||||
_engine.transport_locate (0);
|
_engine.transport_locate (0);
|
||||||
|
|
||||||
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
|
AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
|
||||||
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ()));
|
AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (Timecode::Time ()));
|
||||||
|
|
||||||
MIDI::Name::MidiPatchManager::instance().set_session (this);
|
MIDI::Name::MidiPatchManager::instance().set_session (this);
|
||||||
|
|
||||||
|
|
@ -3429,11 +3428,11 @@ Session::config_changed (std::string p, bool ours)
|
||||||
|
|
||||||
} else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
|
} else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
|
||||||
|
|
||||||
MIDI::Manager::instance()->mmc()->set_receive_device_id (Config->get_mmc_receive_device_id());
|
AudioEngine::instance()->mmc().set_receive_device_id (Config->get_mmc_receive_device_id());
|
||||||
|
|
||||||
} else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
|
} else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
|
||||||
|
|
||||||
MIDI::Manager::instance()->mmc()->set_send_device_id (Config->get_mmc_send_device_id());
|
AudioEngine::instance()->mmc().set_send_device_id (Config->get_mmc_send_device_id());
|
||||||
|
|
||||||
} else if (p == "midi-control") {
|
} else if (p == "midi-control") {
|
||||||
|
|
||||||
|
|
@ -3496,7 +3495,7 @@ Session::config_changed (std::string p, bool ours)
|
||||||
|
|
||||||
} else if (p == "send-mmc") {
|
} else if (p == "send-mmc") {
|
||||||
|
|
||||||
MIDI::Manager::instance()->mmc()->enable_send (Config->get_send_mmc ());
|
AudioEngine::instance()->mmc().enable_send (Config->get_send_mmc ());
|
||||||
|
|
||||||
} else if (p == "midi-feedback") {
|
} else if (p == "midi-feedback") {
|
||||||
|
|
||||||
|
|
@ -3554,13 +3553,13 @@ Session::config_changed (std::string p, bool ours)
|
||||||
|
|
||||||
} else if (p == "initial-program-change") {
|
} else if (p == "initial-program-change") {
|
||||||
|
|
||||||
if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {
|
if (AudioEngine::instance()->mmc().output_port() && Config->get_initial_program_change() >= 0) {
|
||||||
MIDI::byte buf[2];
|
MIDI::byte buf[2];
|
||||||
|
|
||||||
buf[0] = MIDI::program; // channel zero by default
|
buf[0] = MIDI::program; // channel zero by default
|
||||||
buf[1] = (Config->get_initial_program_change() & 0x7f);
|
buf[1] = (Config->get_initial_program_change() & 0x7f);
|
||||||
|
|
||||||
MIDI::Manager::instance()->mmc()->output_port()->midimsg (buf, sizeof (buf), 0);
|
AudioEngine::instance()->mmc().output_port()->midimsg (buf, sizeof (buf), 0);
|
||||||
}
|
}
|
||||||
} else if (p == "solo-mute-override") {
|
} else if (p == "solo-mute-override") {
|
||||||
// catch_up_on_solo_mute_override ();
|
// catch_up_on_solo_mute_override ();
|
||||||
|
|
@ -3624,27 +3623,27 @@ Session::load_diskstreams_2X (XMLNode const & node, int)
|
||||||
void
|
void
|
||||||
Session::setup_midi_machine_control ()
|
Session::setup_midi_machine_control ()
|
||||||
{
|
{
|
||||||
MIDI::MachineControl* mmc = MIDI::Manager::instance()->mmc ();
|
MIDI::MachineControl& mmc (AudioEngine::instance()->mmc ());
|
||||||
|
|
||||||
mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
|
mmc.Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
|
||||||
mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
|
mmc.DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
|
||||||
mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
|
mmc.Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
|
||||||
mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
|
mmc.FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
|
||||||
mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
|
mmc.Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
|
||||||
mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
|
mmc.Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
|
||||||
mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
|
mmc.RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
|
||||||
mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
|
mmc.RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
|
||||||
mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
|
mmc.RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
|
||||||
mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
|
mmc.Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
|
||||||
mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
|
mmc.Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
|
||||||
mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
|
mmc.Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
|
||||||
mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
|
mmc.TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
|
||||||
|
|
||||||
/* also handle MIDI SPP because its so common */
|
/* also handle MIDI SPP because its so common */
|
||||||
|
|
||||||
mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
|
mmc.SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
|
||||||
mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
|
mmc.SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
|
||||||
mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
|
mmc.SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<Controllable>
|
boost::shared_ptr<Controllable>
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@
|
||||||
|
|
||||||
#include "midi++/mmc.h"
|
#include "midi++/mmc.h"
|
||||||
#include "midi++/port.h"
|
#include "midi++/port.h"
|
||||||
#include "midi++/manager.h"
|
|
||||||
|
|
||||||
#include "ardour/audioengine.h"
|
#include "ardour/audioengine.h"
|
||||||
#include "ardour/auditioner.h"
|
#include "ardour/auditioner.h"
|
||||||
|
|
@ -611,10 +610,11 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
|
||||||
have_looped = false;
|
have_looped = false;
|
||||||
|
|
||||||
if (!_engine.freewheeling()) {
|
if (!_engine.freewheeling()) {
|
||||||
send_full_time_code (_transport_frame);
|
// need to queue this in the next RT cycle
|
||||||
|
_send_timecode_update = true;
|
||||||
|
|
||||||
if (!dynamic_cast<MTC_Slave*>(_slave)) {
|
if (!dynamic_cast<MTC_Slave*>(_slave)) {
|
||||||
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
|
AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
|
||||||
send_mmc_locate (_transport_frame);
|
send_mmc_locate (_transport_frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1260,7 +1260,7 @@ Session::start_transport ()
|
||||||
Timecode::Time time;
|
Timecode::Time time;
|
||||||
timecode_time_subframes (_transport_frame, time);
|
timecode_time_subframes (_transport_frame, time);
|
||||||
if (!dynamic_cast<MTC_Slave*>(_slave)) {
|
if (!dynamic_cast<MTC_Slave*>(_slave)) {
|
||||||
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
|
AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1339,7 +1339,8 @@ Session::use_sync_source (Slave* new_slave)
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
|
DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
|
||||||
|
|
||||||
send_full_time_code (_transport_frame);
|
// need to queue this for next process() cycle
|
||||||
|
_send_timecode_update = true;
|
||||||
|
|
||||||
boost::shared_ptr<RouteList> rl = routes.reader();
|
boost::shared_ptr<RouteList> rl = routes.reader();
|
||||||
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
|
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
|
||||||
|
|
@ -1380,7 +1381,7 @@ Session::switch_to_sync_source (SyncSource src)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new_slave = new MTC_Slave (*this, *MIDI::Manager::instance()->mtc_input_port());
|
new_slave = new MTC_Slave (*this, *AudioEngine::instance()->mtc_input_port());
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (failed_constructor& err) {
|
catch (failed_constructor& err) {
|
||||||
|
|
@ -1409,7 +1410,7 @@ Session::switch_to_sync_source (SyncSource src)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new_slave = new MIDIClock_Slave (*this, *MIDI::Manager::instance()->midi_clock_input_port(), 24);
|
new_slave = new MIDIClock_Slave (*this, *AudioEngine::instance()->midi_clock_input_port(), 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (failed_constructor& err) {
|
catch (failed_constructor& err) {
|
||||||
|
|
@ -1636,7 +1637,7 @@ Session::send_mmc_locate (framepos_t t)
|
||||||
if (!_engine.freewheeling()) {
|
if (!_engine.freewheeling()) {
|
||||||
Timecode::Time time;
|
Timecode::Time time;
|
||||||
timecode_time_subframes (t, time);
|
timecode_time_subframes (t, time);
|
||||||
MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (time));
|
AudioEngine::instance()->mmc().send (MIDI::MachineControlCommand (time));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,12 @@
|
||||||
#include "pbd/compose.h"
|
#include "pbd/compose.h"
|
||||||
#include "pbd/stacktrace.h"
|
#include "pbd/stacktrace.h"
|
||||||
|
|
||||||
#include "midi++/port.h"
|
|
||||||
#include "midi++/jack_midi_port.h"
|
|
||||||
#include "midi++/manager.h"
|
|
||||||
|
|
||||||
#include "evoral/midi_events.h"
|
#include "evoral/midi_events.h"
|
||||||
|
|
||||||
|
#include "ardour/async_midi_port.h"
|
||||||
#include "ardour/audioengine.h"
|
#include "ardour/audioengine.h"
|
||||||
|
#include "ardour/midi_buffer.h"
|
||||||
|
#include "ardour/midi_port.h"
|
||||||
#include "ardour/ticker.h"
|
#include "ardour/ticker.h"
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
#include "ardour/tempo.h"
|
#include "ardour/tempo.h"
|
||||||
|
|
@ -95,16 +94,16 @@ public:
|
||||||
|
|
||||||
|
|
||||||
MidiClockTicker::MidiClockTicker ()
|
MidiClockTicker::MidiClockTicker ()
|
||||||
: _midi_port (0)
|
: _ppqn (24)
|
||||||
, _ppqn (24)
|
|
||||||
, _last_tick (0.0)
|
, _last_tick (0.0)
|
||||||
|
, _send_pos (false)
|
||||||
|
, _send_state (false)
|
||||||
{
|
{
|
||||||
_pos.reset (new Position());
|
_pos.reset (new Position());
|
||||||
}
|
}
|
||||||
|
|
||||||
MidiClockTicker::~MidiClockTicker()
|
MidiClockTicker::~MidiClockTicker()
|
||||||
{
|
{
|
||||||
_midi_port = 0;
|
|
||||||
_pos.reset (0);
|
_pos.reset (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,7 +114,6 @@ MidiClockTicker::set_session (Session* s)
|
||||||
|
|
||||||
if (_session) {
|
if (_session) {
|
||||||
_session->TransportStateChange.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::transport_state_changed, this));
|
_session->TransportStateChange.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::transport_state_changed, this));
|
||||||
_session->PositionChanged.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::position_changed, this, _1));
|
|
||||||
_session->TransportLooped.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::transport_looped, this));
|
_session->TransportLooped.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::transport_looped, this));
|
||||||
_session->Located.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::session_located, this));
|
_session->Located.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::session_located, this));
|
||||||
|
|
||||||
|
|
@ -139,41 +137,20 @@ MidiClockTicker::session_located()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pos->speed == 0.0f) {
|
_send_pos = true;
|
||||||
uint32_t where = llrint (_pos->midi_beats);
|
|
||||||
send_position_event (where, 0);
|
|
||||||
} else if (_pos->speed == 1.0f) {
|
|
||||||
#if 1
|
|
||||||
/* Experimental. To really do this and have accuracy, the
|
|
||||||
stop/locate/continue sequence would need queued to send immediately
|
|
||||||
before the next midi clock. */
|
|
||||||
|
|
||||||
send_stop_event (0);
|
|
||||||
|
|
||||||
if (_pos->frame == 0) {
|
|
||||||
send_start_event (0);
|
|
||||||
} else {
|
|
||||||
uint32_t where = llrint (_pos->midi_beats);
|
|
||||||
send_position_event (where, 0);
|
|
||||||
send_continue_event (0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
/* Varispeed not supported */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiClockTicker::session_going_away ()
|
MidiClockTicker::session_going_away ()
|
||||||
{
|
{
|
||||||
SessionHandlePtr::session_going_away();
|
SessionHandlePtr::session_going_away();
|
||||||
_midi_port = 0;
|
_midi_port.reset ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiClockTicker::update_midi_clock_port()
|
MidiClockTicker::update_midi_clock_port()
|
||||||
{
|
{
|
||||||
_midi_port = MIDI::Manager::instance()->midi_clock_output_port();
|
_midi_port = AudioEngine::instance()->midi_clock_output_port();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -204,48 +181,11 @@ MidiClockTicker::transport_state_changed()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pos->speed == 1.0f) {
|
_send_state = true;
|
||||||
|
|
||||||
if (_session->get_play_loop()) {
|
|
||||||
assert(_session->locations()->auto_loop_location());
|
|
||||||
|
|
||||||
if (_pos->frame == _session->locations()->auto_loop_location()->start()) {
|
|
||||||
send_start_event(0);
|
|
||||||
} else {
|
|
||||||
send_continue_event(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (_pos->frame == 0) {
|
|
||||||
send_start_event(0);
|
|
||||||
} else {
|
|
||||||
send_continue_event(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// send_midi_clock_event (0);
|
|
||||||
|
|
||||||
} else if (_pos->speed == 0.0f) {
|
|
||||||
send_stop_event (0);
|
|
||||||
send_position_event (llrint (_pos->midi_beats), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// tick (_pos->frame);
|
// tick (_pos->frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
MidiClockTicker::position_changed (framepos_t)
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
const double speed = _session->transport_speed();
|
|
||||||
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Transport Position Change: %1, speed: %2\n", position, speed));
|
|
||||||
|
|
||||||
if (speed == 0.0f && Config->get_send_midi_clock()) {
|
|
||||||
send_position_event (position, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
_last_tick = position;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiClockTicker::transport_looped()
|
MidiClockTicker::transport_looped()
|
||||||
{
|
{
|
||||||
|
|
@ -270,18 +210,68 @@ MidiClockTicker::transport_looped()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiClockTicker::tick (const framepos_t& /* transport_frame */)
|
MidiClockTicker::tick (const framepos_t& /* transport_frame */, pframes_t nframes)
|
||||||
{
|
{
|
||||||
if (!Config->get_send_midi_clock() || _session == 0 || _session->transport_speed() != 1.0f || _midi_port == 0) {
|
if (!Config->get_send_midi_clock() || _session == 0 || _session->transport_speed() != 1.0f || _midi_port == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MIDI::JackMIDIPort* mp = dynamic_cast<MIDI::JackMIDIPort*> (_midi_port);
|
if (_send_pos) {
|
||||||
if (! mp) {
|
if (_pos->speed == 0.0f) {
|
||||||
return;
|
uint32_t where = llrint (_pos->midi_beats);
|
||||||
|
send_position_event (where, 0, nframes);
|
||||||
|
} else if (_pos->speed == 1.0f) {
|
||||||
|
#if 1
|
||||||
|
/* Experimental. To really do this and have accuracy, the
|
||||||
|
stop/locate/continue sequence would need queued to send immediately
|
||||||
|
before the next midi clock. */
|
||||||
|
|
||||||
|
send_stop_event (0, nframes);
|
||||||
|
|
||||||
|
if (_pos->frame == 0) {
|
||||||
|
send_start_event (0, nframes);
|
||||||
|
} else {
|
||||||
|
uint32_t where = llrint (_pos->midi_beats);
|
||||||
|
send_position_event (where, 0, nframes);
|
||||||
|
send_continue_event (0, nframes);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
/* Varispeed not supported */
|
||||||
|
}
|
||||||
|
|
||||||
|
_send_pos = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const framepos_t end = _pos->frame + mp->nframes_this_cycle();
|
if (_send_state) {
|
||||||
|
if (_pos->speed == 1.0f) {
|
||||||
|
if (_session->get_play_loop()) {
|
||||||
|
assert(_session->locations()->auto_loop_location());
|
||||||
|
|
||||||
|
if (_pos->frame == _session->locations()->auto_loop_location()->start()) {
|
||||||
|
send_start_event (0, nframes);
|
||||||
|
} else {
|
||||||
|
send_continue_event (0, nframes);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (_pos->frame == 0) {
|
||||||
|
send_start_event (0, nframes);
|
||||||
|
} else {
|
||||||
|
send_continue_event (0, nframes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// send_midi_clock_event (0);
|
||||||
|
|
||||||
|
} else if (_pos->speed == 0.0f) {
|
||||||
|
send_stop_event (0, nframes);
|
||||||
|
send_position_event (llrint (_pos->midi_beats), 0, nframes);
|
||||||
|
}
|
||||||
|
|
||||||
|
_send_state = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const framepos_t end = _pos->frame + nframes;
|
||||||
double iter = _last_tick;
|
double iter = _last_tick;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
@ -291,14 +281,14 @@ MidiClockTicker::tick (const framepos_t& /* transport_frame */)
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::MidiClock,
|
DEBUG_TRACE (DEBUG::MidiClock,
|
||||||
string_compose ("Tick: iter: %1, last tick time: %2, next tick time: %3, offset: %4, cycle length: %5\n",
|
string_compose ("Tick: iter: %1, last tick time: %2, next tick time: %3, offset: %4, cycle length: %5\n",
|
||||||
iter, _last_tick, next_tick, next_tick_offset, mp ? mp->nframes_this_cycle() : 0));
|
iter, _last_tick, next_tick, next_tick_offset, nframes));
|
||||||
|
|
||||||
if (!mp || (next_tick_offset >= mp->nframes_this_cycle())) {
|
if (next_tick_offset >= nframes) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next_tick_offset >= 0) {
|
if (next_tick_offset >= 0) {
|
||||||
send_midi_clock_event (next_tick_offset);
|
send_midi_clock_event (next_tick_offset, nframes);
|
||||||
}
|
}
|
||||||
|
|
||||||
iter = next_tick;
|
iter = next_tick;
|
||||||
|
|
@ -308,7 +298,6 @@ MidiClockTicker::tick (const framepos_t& /* transport_frame */)
|
||||||
_pos->frame = end;
|
_pos->frame = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
double
|
double
|
||||||
MidiClockTicker::one_ppqn_in_frames (framepos_t transport_position)
|
MidiClockTicker::one_ppqn_in_frames (framepos_t transport_position)
|
||||||
{
|
{
|
||||||
|
|
@ -322,7 +311,7 @@ MidiClockTicker::one_ppqn_in_frames (framepos_t transport_position)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiClockTicker::send_midi_clock_event (pframes_t offset)
|
MidiClockTicker::send_midi_clock_event (pframes_t offset, pframes_t nframes)
|
||||||
{
|
{
|
||||||
if (!_midi_port) {
|
if (!_midi_port) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -330,12 +319,13 @@ MidiClockTicker::send_midi_clock_event (pframes_t offset)
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Tick with offset %1\n", offset));
|
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Tick with offset %1\n", offset));
|
||||||
|
|
||||||
static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_CLOCK };
|
static uint8_t tick_byte = { MIDI_CMD_COMMON_CLOCK };
|
||||||
_midi_port->write (_midi_clock_tick, 1, offset);
|
MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
|
||||||
|
mb.push_back (offset, 1, &tick_byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiClockTicker::send_start_event (pframes_t offset)
|
MidiClockTicker::send_start_event (pframes_t offset, pframes_t nframes)
|
||||||
{
|
{
|
||||||
if (!_midi_port) {
|
if (!_midi_port) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -343,12 +333,13 @@ MidiClockTicker::send_start_event (pframes_t offset)
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Start %1\n", _last_tick));
|
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Start %1\n", _last_tick));
|
||||||
|
|
||||||
static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_START };
|
static uint8_t tick_byte = { MIDI_CMD_COMMON_START };
|
||||||
_midi_port->write (_midi_clock_tick, 1, offset);
|
MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
|
||||||
|
mb.push_back (offset, 1, &tick_byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiClockTicker::send_continue_event (pframes_t offset)
|
MidiClockTicker::send_continue_event (pframes_t offset, pframes_t nframes)
|
||||||
{
|
{
|
||||||
if (!_midi_port) {
|
if (!_midi_port) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -356,12 +347,13 @@ MidiClockTicker::send_continue_event (pframes_t offset)
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Continue %1\n", _last_tick));
|
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Continue %1\n", _last_tick));
|
||||||
|
|
||||||
static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_CONTINUE };
|
static uint8_t tick_byte = { MIDI_CMD_COMMON_CONTINUE };
|
||||||
_midi_port->write (_midi_clock_tick, 1, offset);
|
MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
|
||||||
|
mb.push_back (offset, 1, &tick_byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiClockTicker::send_stop_event (pframes_t offset)
|
MidiClockTicker::send_stop_event (pframes_t offset, pframes_t nframes)
|
||||||
{
|
{
|
||||||
if (!_midi_port) {
|
if (!_midi_port) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -369,12 +361,13 @@ MidiClockTicker::send_stop_event (pframes_t offset)
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Stop %1\n", _last_tick));
|
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Stop %1\n", _last_tick));
|
||||||
|
|
||||||
static uint8_t _midi_clock_tick[1] = { MIDI_CMD_COMMON_STOP };
|
static uint8_t tick_byte = { MIDI_CMD_COMMON_STOP };
|
||||||
_midi_port->write (_midi_clock_tick, 1, offset);
|
MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
|
||||||
|
mb.push_back (offset, 1, &tick_byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiClockTicker::send_position_event (uint32_t midi_beats, pframes_t offset)
|
MidiClockTicker::send_position_event (uint32_t midi_beats, pframes_t offset, pframes_t nframes)
|
||||||
{
|
{
|
||||||
if (!_midi_port) {
|
if (!_midi_port) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -391,7 +384,8 @@ MidiClockTicker::send_position_event (uint32_t midi_beats, pframes_t offset)
|
||||||
msg[1] = midi_beats & 0x007f;
|
msg[1] = midi_beats & 0x007f;
|
||||||
msg[2] = midi_beats >> 7;
|
msg[2] = midi_beats >> 7;
|
||||||
|
|
||||||
_midi_port->midimsg (msg, sizeof (msg), offset);
|
MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
|
||||||
|
mb.push_back (offset, 3, &msg[0]);
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Song Position Sent: %1\n", midi_beats));
|
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Song Position Sent: %1\n", midi_beats));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ path_prefix = 'libs/ardour/'
|
||||||
libardour_sources = [
|
libardour_sources = [
|
||||||
'amp.cc',
|
'amp.cc',
|
||||||
'analyser.cc',
|
'analyser.cc',
|
||||||
|
'async_midi_port.cc',
|
||||||
'audio_buffer.cc',
|
'audio_buffer.cc',
|
||||||
'audio_diskstream.cc',
|
'audio_diskstream.cc',
|
||||||
'audio_library.cc',
|
'audio_library.cc',
|
||||||
|
|
@ -126,6 +127,7 @@ libardour_sources = [
|
||||||
'midi_stretch.cc',
|
'midi_stretch.cc',
|
||||||
'midi_track.cc',
|
'midi_track.cc',
|
||||||
'midi_ui.cc',
|
'midi_ui.cc',
|
||||||
|
'midiport_manager.cc',
|
||||||
'mix.cc',
|
'mix.cc',
|
||||||
'monitor_processor.cc',
|
'monitor_processor.cc',
|
||||||
'mtc_slave.cc',
|
'mtc_slave.cc',
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@ namespace MIDI {
|
||||||
class Port;
|
class Port;
|
||||||
class Parser;
|
class Parser;
|
||||||
class MachineControlCommand;
|
class MachineControlCommand;
|
||||||
class Manager;
|
|
||||||
|
|
||||||
/** Class to handle incoming and outgoing MIDI machine control messages */
|
/** Class to handle incoming and outgoing MIDI machine control messages */
|
||||||
class MachineControl
|
class MachineControl
|
||||||
|
|
@ -95,7 +94,9 @@ class MachineControl
|
||||||
cmdResume = 0x7F
|
cmdResume = 0x7F
|
||||||
};
|
};
|
||||||
|
|
||||||
MachineControl (Manager *, ARDOUR::PortEngine&);
|
MachineControl ();
|
||||||
|
|
||||||
|
void set_ports (MIDI::Port* input, MIDI::Port* output);
|
||||||
|
|
||||||
Port* input_port() { return _input_port; }
|
Port* input_port() { return _input_port; }
|
||||||
Port* output_port() { return _output_port; }
|
Port* output_port() { return _output_port; }
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ typedef PBD::Signal3<void,Parser &, byte *, size_t> Signal;
|
||||||
|
|
||||||
class Parser {
|
class Parser {
|
||||||
public:
|
public:
|
||||||
Parser (Port &p);
|
Parser ();
|
||||||
~Parser ();
|
~Parser ();
|
||||||
|
|
||||||
/* sets the time that will be reported for any MTC or MIDI Clock
|
/* sets the time that will be reported for any MTC or MIDI Clock
|
||||||
|
|
@ -105,7 +105,6 @@ class Parser {
|
||||||
const char *midi_event_type_name (MIDI::eventType);
|
const char *midi_event_type_name (MIDI::eventType);
|
||||||
void trace (bool onoff, std::ostream *o, const std::string &prefix = "");
|
void trace (bool onoff, std::ostream *o, const std::string &prefix = "");
|
||||||
bool tracing() { return trace_stream != 0; }
|
bool tracing() { return trace_stream != 0; }
|
||||||
Port &port() { return _port; }
|
|
||||||
|
|
||||||
void set_offline (bool);
|
void set_offline (bool);
|
||||||
bool offline() const { return _offline; }
|
bool offline() const { return _offline; }
|
||||||
|
|
@ -136,7 +135,6 @@ class Parser {
|
||||||
void reset_mtc_state ();
|
void reset_mtc_state ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Port&_port;
|
|
||||||
/* tracing */
|
/* tracing */
|
||||||
|
|
||||||
std::ostream *trace_stream;
|
std::ostream *trace_stream;
|
||||||
|
|
|
||||||
|
|
@ -51,13 +51,6 @@ class Port {
|
||||||
virtual XMLNode& get_state () const;
|
virtual XMLNode& get_state () const;
|
||||||
virtual void set_state (const XMLNode&);
|
virtual void set_state (const XMLNode&);
|
||||||
|
|
||||||
// FIXME: make Manager a friend of port so these can be hidden?
|
|
||||||
|
|
||||||
/* Only for use by MidiManager. Don't ever call this. */
|
|
||||||
virtual void cycle_start (pframes_t) {}
|
|
||||||
/* Only for use by MidiManager. Don't ever call this. */
|
|
||||||
virtual void cycle_end () {}
|
|
||||||
|
|
||||||
/** Write a message to port.
|
/** Write a message to port.
|
||||||
* @param msg Raw MIDI message to send
|
* @param msg Raw MIDI message to send
|
||||||
* @param msglen Size of @a msg
|
* @param msglen Size of @a msg
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,7 @@
|
||||||
|
|
||||||
#include "midi++/mmc.h"
|
#include "midi++/mmc.h"
|
||||||
#include "midi++/port.h"
|
#include "midi++/port.h"
|
||||||
#include "midi++/jack_midi_port.h"
|
|
||||||
#include "midi++/parser.h"
|
#include "midi++/parser.h"
|
||||||
#include "midi++/manager.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace MIDI;
|
using namespace MIDI;
|
||||||
|
|
@ -197,16 +195,21 @@ static void build_mmc_cmd_map ()
|
||||||
mmc_cmd_map.insert (newpair);
|
mmc_cmd_map.insert (newpair);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MachineControl::MachineControl ()
|
||||||
MachineControl::MachineControl (Manager* m, ARDOUR::PortEngine& pengine)
|
|
||||||
{
|
{
|
||||||
build_mmc_cmd_map ();
|
build_mmc_cmd_map ();
|
||||||
|
|
||||||
_receive_device_id = 0x7f;
|
_receive_device_id = 0x7f;
|
||||||
_send_device_id = 0x7f;
|
_send_device_id = 0x7f;
|
||||||
|
}
|
||||||
|
|
||||||
_input_port = m->add_port (new JackMIDIPort ("MMC in", Port::IsInput, pengine));
|
void
|
||||||
_output_port = m->add_port (new JackMIDIPort ("MMC out", Port::IsOutput, pengine));
|
MachineControl::set_ports (MIDI::Port* ip, MIDI::Port* op)
|
||||||
|
{
|
||||||
|
port_connections.drop_connections ();
|
||||||
|
|
||||||
|
_input_port = ip;
|
||||||
|
_output_port = op;
|
||||||
|
|
||||||
_input_port->parser()->mmc.connect_same_thread (port_connections, boost::bind (&MachineControl::process_mmc_message, this, _1, _2, _3));
|
_input_port->parser()->mmc.connect_same_thread (port_connections, boost::bind (&MachineControl::process_mmc_message, this, _1, _2, _3));
|
||||||
_input_port->parser()->start.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_start, this));
|
_input_port->parser()->start.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_start, this));
|
||||||
|
|
|
||||||
|
|
@ -104,8 +104,7 @@ Parser::midi_event_type_name (eventType t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser::Parser (Port &p)
|
Parser::Parser ()
|
||||||
: _port(p)
|
|
||||||
{
|
{
|
||||||
trace_stream = 0;
|
trace_stream = 0;
|
||||||
trace_prefix = "";
|
trace_prefix = "";
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ Port::init (string const & name, Flags flags)
|
||||||
_tagname = name;
|
_tagname = name;
|
||||||
_flags = flags;
|
_flags = flags;
|
||||||
|
|
||||||
_parser = new Parser (*this);
|
_parser = new Parser ();
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
_channel[i] = new Channel (i, *this);
|
_channel[i] = new Channel (i, *this);
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,6 @@ libmidi_sources = [
|
||||||
'midi.cc',
|
'midi.cc',
|
||||||
'channel.cc',
|
'channel.cc',
|
||||||
'ipmidi_port.cc',
|
'ipmidi_port.cc',
|
||||||
'jack_midi_port.cc',
|
|
||||||
'manager.cc',
|
|
||||||
'parser.cc',
|
'parser.cc',
|
||||||
'port.cc',
|
'port.cc',
|
||||||
'midnam_patch.cc',
|
'midnam_patch.cc',
|
||||||
|
|
|
||||||
|
|
@ -32,13 +32,14 @@
|
||||||
#include "pbd/xml++.h"
|
#include "pbd/xml++.h"
|
||||||
|
|
||||||
#include "midi++/port.h"
|
#include "midi++/port.h"
|
||||||
#include "midi++/manager.h"
|
|
||||||
|
|
||||||
|
#include "ardour/audioengine.h"
|
||||||
#include "ardour/filesystem_paths.h"
|
#include "ardour/filesystem_paths.h"
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
#include "ardour/route.h"
|
#include "ardour/route.h"
|
||||||
#include "ardour/midi_ui.h"
|
#include "ardour/midi_ui.h"
|
||||||
#include "ardour/rc_configuration.h"
|
#include "ardour/rc_configuration.h"
|
||||||
|
#include "ardour/midiport_manager.h"
|
||||||
|
|
||||||
#include "generic_midi_control_protocol.h"
|
#include "generic_midi_control_protocol.h"
|
||||||
#include "midicontrollable.h"
|
#include "midicontrollable.h"
|
||||||
|
|
@ -59,8 +60,8 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
|
||||||
, _threshold (10)
|
, _threshold (10)
|
||||||
, gui (0)
|
, gui (0)
|
||||||
{
|
{
|
||||||
_input_port = MIDI::Manager::instance()->midi_input_port ();
|
_input_port = AudioEngine::instance()->midi_input_port ();
|
||||||
_output_port = MIDI::Manager::instance()->midi_output_port ();
|
_output_port = AudioEngine::instance()->midi_output_port ();
|
||||||
|
|
||||||
do_feedback = false;
|
do_feedback = false;
|
||||||
_feedback_interval = 10000; // microseconds
|
_feedback_interval = 10000; // microseconds
|
||||||
|
|
@ -338,7 +339,7 @@ GenericMidiControlProtocol::start_learning (Controllable* c)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mc) {
|
if (!mc) {
|
||||||
mc = new MIDIControllable (this, *_input_port, *c, false);
|
mc = new MIDIControllable (this, *_input_port->parser(), *c, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -435,7 +436,7 @@ GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos,
|
||||||
MIDI::byte value = control_number;
|
MIDI::byte value = control_number;
|
||||||
|
|
||||||
// Create a MIDIControllable
|
// Create a MIDIControllable
|
||||||
MIDIControllable* mc = new MIDIControllable (this, *_input_port, *control, false);
|
MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), *control, false);
|
||||||
|
|
||||||
// Remove any old binding for this midi channel/type/value pair
|
// Remove any old binding for this midi channel/type/value pair
|
||||||
// Note: can't use delete_binding() here because we don't know the specific controllable we want to remove, only the midi information
|
// Note: can't use delete_binding() here because we don't know the specific controllable we want to remove, only the midi information
|
||||||
|
|
@ -559,7 +560,7 @@ GenericMidiControlProtocol::set_state (const XMLNode& node, int version)
|
||||||
Controllable* c = Controllable::by_id (id);
|
Controllable* c = Controllable::by_id (id);
|
||||||
|
|
||||||
if (c) {
|
if (c) {
|
||||||
MIDIControllable* mc = new MIDIControllable (this, *_input_port, *c, false);
|
MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), *c, false);
|
||||||
|
|
||||||
if (mc->set_state (**niter, version) == 0) {
|
if (mc->set_state (**niter, version) == 0) {
|
||||||
controllables.push_back (mc);
|
controllables.push_back (mc);
|
||||||
|
|
@ -754,7 +755,7 @@ GenericMidiControlProtocol::create_binding (const XMLNode& node)
|
||||||
prop = node.property (X_("uri"));
|
prop = node.property (X_("uri"));
|
||||||
uri = prop->value();
|
uri = prop->value();
|
||||||
|
|
||||||
MIDIControllable* mc = new MIDIControllable (this, *_input_port, momentary);
|
MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), momentary);
|
||||||
|
|
||||||
if (mc->init (uri)) {
|
if (mc->init (uri)) {
|
||||||
delete mc;
|
delete mc;
|
||||||
|
|
@ -892,7 +893,7 @@ GenericMidiControlProtocol::create_function (const XMLNode& node)
|
||||||
|
|
||||||
prop = node.property (X_("function"));
|
prop = node.property (X_("function"));
|
||||||
|
|
||||||
MIDIFunction* mf = new MIDIFunction (*_input_port);
|
MIDIFunction* mf = new MIDIFunction (*_input_port->parser());
|
||||||
|
|
||||||
if (mf->setup (*this, prop->value(), argument, data, data_size)) {
|
if (mf->setup (*this, prop->value(), argument, data, data_size)) {
|
||||||
delete mf;
|
delete mf;
|
||||||
|
|
@ -988,7 +989,7 @@ GenericMidiControlProtocol::create_action (const XMLNode& node)
|
||||||
|
|
||||||
prop = node.property (X_("action"));
|
prop = node.property (X_("action"));
|
||||||
|
|
||||||
MIDIAction* ma = new MIDIAction (*_input_port);
|
MIDIAction* ma = new MIDIAction (*_input_port->parser());
|
||||||
|
|
||||||
if (ma->init (*this, prop->value(), data, data_size)) {
|
if (ma->init (*this, prop->value(), data, data_size)) {
|
||||||
delete ma;
|
delete ma;
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,11 @@
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <glibmm/threads.h>
|
#include <glibmm/threads.h>
|
||||||
|
|
||||||
#include "ardour/types.h"
|
#include "ardour/types.h"
|
||||||
|
|
||||||
#include "control_protocol/control_protocol.h"
|
#include "control_protocol/control_protocol.h"
|
||||||
|
|
||||||
namespace MIDI {
|
|
||||||
class Port;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace PBD {
|
namespace PBD {
|
||||||
class Controllable;
|
class Controllable;
|
||||||
class ControllableDescriptor;
|
class ControllableDescriptor;
|
||||||
|
|
@ -37,6 +34,11 @@ namespace PBD {
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
class Session;
|
class Session;
|
||||||
|
class MidiPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MIDI {
|
||||||
|
class Port;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MIDIControllable;
|
class MIDIControllable;
|
||||||
|
|
@ -51,8 +53,8 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
|
||||||
int set_active (bool yn);
|
int set_active (bool yn);
|
||||||
static bool probe() { return true; }
|
static bool probe() { return true; }
|
||||||
|
|
||||||
MIDI::Port* input_port () const { return _input_port; }
|
MIDI::Port* input_port () const { return _input_port; }
|
||||||
MIDI::Port* output_port () const { return _output_port; }
|
MIDI::Port* output_port () const { return _output_port; }
|
||||||
void set_feedback_interval (ARDOUR::microseconds_t);
|
void set_feedback_interval (ARDOUR::microseconds_t);
|
||||||
|
|
||||||
int set_feedback (bool yn);
|
int set_feedback (bool yn);
|
||||||
|
|
@ -97,8 +99,8 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MIDI::Port* _input_port;
|
MIDI::Port* _input_port;
|
||||||
MIDI::Port* _output_port;
|
MIDI::Port* _output_port;
|
||||||
ARDOUR::microseconds_t _feedback_interval;
|
ARDOUR::microseconds_t _feedback_interval;
|
||||||
ARDOUR::microseconds_t last_feedback_time;
|
ARDOUR::microseconds_t last_feedback_time;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
using namespace MIDI;
|
using namespace MIDI;
|
||||||
|
|
||||||
MIDIAction::MIDIAction (MIDI::Port& p)
|
MIDIAction::MIDIAction (MIDI::Parser& p)
|
||||||
: MIDIInvokable (p)
|
: MIDIInvokable (p)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,6 @@ namespace Gtk {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MIDI {
|
namespace MIDI {
|
||||||
class Channel;
|
|
||||||
class Port;
|
|
||||||
class Parser;
|
class Parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,7 +44,7 @@ class GenericMidiControlProtocol;
|
||||||
class MIDIAction : public MIDIInvokable
|
class MIDIAction : public MIDIInvokable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MIDIAction (MIDI::Port&);
|
MIDIAction (MIDI::Parser&);
|
||||||
virtual ~MIDIAction ();
|
virtual ~MIDIAction ();
|
||||||
|
|
||||||
int init (GenericMidiControlProtocol&, const std::string& action_name, MIDI::byte* sysex = 0, size_t ssize = 0);
|
int init (GenericMidiControlProtocol&, const std::string& action_name, MIDI::byte* sysex = 0, size_t ssize = 0);
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,9 @@
|
||||||
#include "pbd/xml++.h"
|
#include "pbd/xml++.h"
|
||||||
#include "pbd/stacktrace.h"
|
#include "pbd/stacktrace.h"
|
||||||
|
|
||||||
#include "midi++/port.h"
|
|
||||||
#include "midi++/channel.h"
|
#include "midi++/channel.h"
|
||||||
|
|
||||||
|
#include "ardour/async_midi_port.h"
|
||||||
#include "ardour/automation_control.h"
|
#include "ardour/automation_control.h"
|
||||||
#include "ardour/midi_ui.h"
|
#include "ardour/midi_ui.h"
|
||||||
#include "ardour/utils.h"
|
#include "ardour/utils.h"
|
||||||
|
|
@ -42,11 +42,11 @@ using namespace MIDI;
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
|
|
||||||
MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, Port& p, bool m)
|
MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, MIDI::Parser& p, bool m)
|
||||||
: _surface (s)
|
: _surface (s)
|
||||||
, controllable (0)
|
, controllable (0)
|
||||||
, _descriptor (0)
|
, _descriptor (0)
|
||||||
, _port (p)
|
, _parser (p)
|
||||||
, _momentary (m)
|
, _momentary (m)
|
||||||
{
|
{
|
||||||
_learned = false; /* from URI */
|
_learned = false; /* from URI */
|
||||||
|
|
@ -59,10 +59,10 @@ MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, Port& p, bool
|
||||||
feedback = true; // for now
|
feedback = true; // for now
|
||||||
}
|
}
|
||||||
|
|
||||||
MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, Port& p, Controllable& c, bool m)
|
MIDIControllable::MIDIControllable (GenericMidiControlProtocol* s, MIDI::Parser& p, Controllable& c, bool m)
|
||||||
: _surface (s)
|
: _surface (s)
|
||||||
, _descriptor (0)
|
, _descriptor (0)
|
||||||
, _port (p)
|
, _parser (p)
|
||||||
, _momentary (m)
|
, _momentary (m)
|
||||||
{
|
{
|
||||||
set_controllable (&c);
|
set_controllable (&c);
|
||||||
|
|
@ -149,7 +149,7 @@ void
|
||||||
MIDIControllable::learn_about_external_control ()
|
MIDIControllable::learn_about_external_control ()
|
||||||
{
|
{
|
||||||
drop_external_control ();
|
drop_external_control ();
|
||||||
_port.parser()->any.connect_same_thread (midi_learn_connection, boost::bind (&MIDIControllable::midi_receiver, this, _1, _2, _3));
|
_parser.any.connect_same_thread (midi_learn_connection, boost::bind (&MIDIControllable::midi_receiver, this, _1, _2, _3));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -357,12 +357,6 @@ MIDIControllable::midi_receiver (Parser &, byte *msg, size_t /*len*/)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if the our port doesn't do input anymore, forget it ... */
|
|
||||||
|
|
||||||
if (!_port.parser()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bind_midi ((channel_t) (msg[0] & 0xf), eventType (msg[0] & 0xF0), msg[1]);
|
bind_midi ((channel_t) (msg[0] & 0xf), eventType (msg[0] & 0xF0), msg[1]);
|
||||||
|
|
||||||
if (controllable) {
|
if (controllable) {
|
||||||
|
|
@ -381,49 +375,43 @@ MIDIControllable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
|
||||||
control_channel = chn;
|
control_channel = chn;
|
||||||
control_additional = additional;
|
control_additional = additional;
|
||||||
|
|
||||||
if (_port.parser() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Parser& p = *_port.parser();
|
|
||||||
|
|
||||||
int chn_i = chn;
|
int chn_i = chn;
|
||||||
switch (ev) {
|
switch (ev) {
|
||||||
case MIDI::off:
|
case MIDI::off:
|
||||||
p.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2));
|
_parser.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2));
|
||||||
|
|
||||||
/* if this is a togglee, connect to noteOn as well,
|
/* if this is a togglee, connect to noteOn as well,
|
||||||
and we'll toggle back and forth between the two.
|
and we'll toggle back and forth between the two.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (_momentary) {
|
if (_momentary) {
|
||||||
p.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2));
|
_parser.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2));
|
||||||
}
|
}
|
||||||
|
|
||||||
_control_description = "MIDI control: NoteOff";
|
_control_description = "MIDI control: NoteOff";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MIDI::on:
|
case MIDI::on:
|
||||||
p.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2));
|
_parser.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_note_on, this, _1, _2));
|
||||||
if (_momentary) {
|
if (_momentary) {
|
||||||
p.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2));
|
_parser.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[1], boost::bind (&MIDIControllable::midi_sense_note_off, this, _1, _2));
|
||||||
}
|
}
|
||||||
_control_description = "MIDI control: NoteOn";
|
_control_description = "MIDI control: NoteOn";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MIDI::controller:
|
case MIDI::controller:
|
||||||
p.channel_controller[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_controller, this, _1, _2));
|
_parser.channel_controller[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_controller, this, _1, _2));
|
||||||
snprintf (buf, sizeof (buf), "MIDI control: Controller %d", control_additional);
|
snprintf (buf, sizeof (buf), "MIDI control: Controller %d", control_additional);
|
||||||
_control_description = buf;
|
_control_description = buf;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MIDI::program:
|
case MIDI::program:
|
||||||
p.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_program_change, this, _1, _2));
|
_parser.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_program_change, this, _1, _2));
|
||||||
_control_description = "MIDI control: ProgramChange";
|
_control_description = "MIDI control: ProgramChange";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MIDI::pitchbend:
|
case MIDI::pitchbend:
|
||||||
p.channel_pitchbend[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_pitchbend, this, _1, _2));
|
_parser.channel_pitchbend[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_pitchbend, this, _1, _2));
|
||||||
_control_description = "MIDI control: Pitchbend";
|
_control_description = "MIDI control: Pitchbend";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,17 +36,20 @@ namespace PBD {
|
||||||
|
|
||||||
namespace MIDI {
|
namespace MIDI {
|
||||||
class Channel;
|
class Channel;
|
||||||
class Port;
|
|
||||||
class Parser;
|
class Parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
class GenericMidiControlProtocol;
|
class GenericMidiControlProtocol;
|
||||||
|
|
||||||
|
namespace ARDOUR {
|
||||||
|
class AsyncMIDIPort;
|
||||||
|
}
|
||||||
|
|
||||||
class MIDIControllable : public PBD::Stateful
|
class MIDIControllable : public PBD::Stateful
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MIDIControllable (GenericMidiControlProtocol *, MIDI::Port&, PBD::Controllable&, bool momentary);
|
MIDIControllable (GenericMidiControlProtocol *, MIDI::Parser&, PBD::Controllable&, bool momentary);
|
||||||
MIDIControllable (GenericMidiControlProtocol *, MIDI::Port&, bool momentary = false);
|
MIDIControllable (GenericMidiControlProtocol *, MIDI::Parser&, bool momentary = false);
|
||||||
virtual ~MIDIControllable ();
|
virtual ~MIDIControllable ();
|
||||||
|
|
||||||
int init (const std::string&);
|
int init (const std::string&);
|
||||||
|
|
@ -72,7 +75,7 @@ class MIDIControllable : public PBD::Stateful
|
||||||
|
|
||||||
bool learned() const { return _learned; }
|
bool learned() const { return _learned; }
|
||||||
|
|
||||||
MIDI::Port& get_port() const { return _port; }
|
MIDI::Parser& get_parser() { return _parser; }
|
||||||
PBD::Controllable* get_controllable() const { return controllable; }
|
PBD::Controllable* get_controllable() const { return controllable; }
|
||||||
void set_controllable (PBD::Controllable*);
|
void set_controllable (PBD::Controllable*);
|
||||||
const std::string& current_uri() const { return _current_uri; }
|
const std::string& current_uri() const { return _current_uri; }
|
||||||
|
|
@ -98,8 +101,8 @@ class MIDIControllable : public PBD::Stateful
|
||||||
GenericMidiControlProtocol* _surface;
|
GenericMidiControlProtocol* _surface;
|
||||||
PBD::Controllable* controllable;
|
PBD::Controllable* controllable;
|
||||||
PBD::ControllableDescriptor* _descriptor;
|
PBD::ControllableDescriptor* _descriptor;
|
||||||
std::string _current_uri;
|
std::string _current_uri;
|
||||||
MIDI::Port& _port;
|
MIDI::Parser& _parser;
|
||||||
bool setting;
|
bool setting;
|
||||||
int last_value;
|
int last_value;
|
||||||
float last_controllable_value;
|
float last_controllable_value;
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
using namespace MIDI;
|
using namespace MIDI;
|
||||||
|
|
||||||
MIDIFunction::MIDIFunction (MIDI::Port& p)
|
MIDIFunction::MIDIFunction (MIDI::Parser& p)
|
||||||
: MIDIInvokable (p)
|
: MIDIInvokable (p)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@
|
||||||
|
|
||||||
namespace MIDI {
|
namespace MIDI {
|
||||||
class Channel;
|
class Channel;
|
||||||
class Port;
|
|
||||||
class Parser;
|
class Parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,7 +63,7 @@ class MIDIFunction : public MIDIInvokable
|
||||||
TrackSetSoloIsolate,
|
TrackSetSoloIsolate,
|
||||||
};
|
};
|
||||||
|
|
||||||
MIDIFunction (MIDI::Port&);
|
MIDIFunction (MIDI::Parser&);
|
||||||
virtual ~MIDIFunction ();
|
virtual ~MIDIFunction ();
|
||||||
|
|
||||||
int setup (GenericMidiControlProtocol&, const std::string& function_name, const std::string& argument, MIDI::byte* sysex = 0, size_t ssize = 0);
|
int setup (GenericMidiControlProtocol&, const std::string& function_name, const std::string& argument, MIDI::byte* sysex = 0, size_t ssize = 0);
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@
|
||||||
|
|
||||||
using namespace MIDI;
|
using namespace MIDI;
|
||||||
|
|
||||||
MIDIInvokable::MIDIInvokable (MIDI::Port& p)
|
MIDIInvokable::MIDIInvokable (MIDI::Parser& p)
|
||||||
: _port (p)
|
: _parser (p)
|
||||||
{
|
{
|
||||||
data_size = 0;
|
data_size = 0;
|
||||||
data = 0;
|
data = 0;
|
||||||
|
|
@ -127,12 +127,6 @@ MIDIInvokable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
|
||||||
control_channel = chn;
|
control_channel = chn;
|
||||||
control_additional = additional;
|
control_additional = additional;
|
||||||
|
|
||||||
if (_port.parser() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Parser& p = *_port.parser();
|
|
||||||
|
|
||||||
int chn_i = chn;
|
int chn_i = chn;
|
||||||
|
|
||||||
/* incoming MIDI is parsed by Ardour' MidiUI event loop/thread, and we want our handlers to execute in that context, so we use
|
/* incoming MIDI is parsed by Ardour' MidiUI event loop/thread, and we want our handlers to execute in that context, so we use
|
||||||
|
|
@ -141,27 +135,27 @@ MIDIInvokable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
|
||||||
|
|
||||||
switch (ev) {
|
switch (ev) {
|
||||||
case MIDI::off:
|
case MIDI::off:
|
||||||
p.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_note_off, this, _1, _2));
|
_parser.channel_note_off[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_note_off, this, _1, _2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MIDI::on:
|
case MIDI::on:
|
||||||
p.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_note_on, this, _1, _2));
|
_parser.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_note_on, this, _1, _2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MIDI::controller:
|
case MIDI::controller:
|
||||||
p.channel_controller[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_controller, this, _1, _2));
|
_parser.channel_controller[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_controller, this, _1, _2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MIDI::program:
|
case MIDI::program:
|
||||||
p.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_program_change, this, _1, _2));
|
_parser.channel_program_change[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_program_change, this, _1, _2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MIDI::sysex:
|
case MIDI::sysex:
|
||||||
p.sysex.connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_sysex, this, _1, _2, _3));
|
_parser.sysex.connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_sysex, this, _1, _2, _3));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MIDI::any:
|
case MIDI::any:
|
||||||
p.any.connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_any, this, _1, _2, _3));
|
_parser.any.connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_any, this, _1, _2, _3));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@
|
||||||
|
|
||||||
namespace MIDI {
|
namespace MIDI {
|
||||||
class Channel;
|
class Channel;
|
||||||
class Port;
|
|
||||||
class Parser;
|
class Parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,12 +39,12 @@ class GenericMidiControlProtocol;
|
||||||
class MIDIInvokable : public PBD::Stateful
|
class MIDIInvokable : public PBD::Stateful
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MIDIInvokable (MIDI::Port&);
|
MIDIInvokable (MIDI::Parser&);
|
||||||
virtual ~MIDIInvokable ();
|
virtual ~MIDIInvokable ();
|
||||||
|
|
||||||
virtual int init (GenericMidiControlProtocol&, const std::string&, MIDI::byte* data = 0, size_t dsize = 0);
|
virtual int init (GenericMidiControlProtocol&, const std::string&, MIDI::byte* data = 0, size_t dsize = 0);
|
||||||
|
|
||||||
MIDI::Port& get_port() const { return _port; }
|
MIDI::Parser& get_parser() { return _parser; }
|
||||||
|
|
||||||
void bind_midi (MIDI::channel_t, MIDI::eventType, MIDI::byte);
|
void bind_midi (MIDI::channel_t, MIDI::eventType, MIDI::byte);
|
||||||
MIDI::channel_t get_control_channel () { return control_channel; }
|
MIDI::channel_t get_control_channel () { return control_channel; }
|
||||||
|
|
@ -55,7 +54,7 @@ class MIDIInvokable : public PBD::Stateful
|
||||||
protected:
|
protected:
|
||||||
GenericMidiControlProtocol* _ui;
|
GenericMidiControlProtocol* _ui;
|
||||||
std::string _invokable_name;
|
std::string _invokable_name;
|
||||||
MIDI::Port& _port;
|
MIDI::Parser& _parser;
|
||||||
PBD::ScopedConnection midi_sense_connection[2];
|
PBD::ScopedConnection midi_sense_connection[2];
|
||||||
MIDI::eventType control_type;
|
MIDI::eventType control_type;
|
||||||
MIDI::byte control_additional;
|
MIDI::byte control_additional;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include "midi++/port.h"
|
#include "midi++/port.h"
|
||||||
#include "midi++/manager.h"
|
|
||||||
|
|
||||||
#include "ardour/automation_control.h"
|
#include "ardour/automation_control.h"
|
||||||
#include "ardour/debug.h"
|
#include "ardour/debug.h"
|
||||||
|
|
|
||||||
|
|
@ -24,27 +24,27 @@
|
||||||
#include <boost/shared_array.hpp>
|
#include <boost/shared_array.hpp>
|
||||||
|
|
||||||
#include "midi++/types.h"
|
#include "midi++/types.h"
|
||||||
#include "midi++/port.h"
|
|
||||||
#include "midi++/jack_midi_port.h"
|
|
||||||
#include "midi++/ipmidi_port.h"
|
#include "midi++/ipmidi_port.h"
|
||||||
#include "midi++/manager.h"
|
|
||||||
|
|
||||||
|
#include "ardour/async_midi_port.h"
|
||||||
#include "ardour/debug.h"
|
#include "ardour/debug.h"
|
||||||
#include "ardour/rc_configuration.h"
|
#include "ardour/rc_configuration.h"
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
#include "ardour/audioengine.h"
|
#include "ardour/audioengine.h"
|
||||||
|
#include "ardour/async_midi_port.h"
|
||||||
|
#include "ardour/midiport_manager.h"
|
||||||
|
|
||||||
#include "controls.h"
|
#include "controls.h"
|
||||||
#include "mackie_control_protocol.h"
|
#include "mackie_control_protocol.h"
|
||||||
#include "surface.h"
|
#include "surface.h"
|
||||||
#include "surface_port.h"
|
#include "surface_port.h"
|
||||||
|
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Mackie;
|
using namespace Mackie;
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
|
using namespace ARDOUR;
|
||||||
|
|
||||||
/** @param input_port Input MIDI::Port; this object takes responsibility for
|
/** @param input_port Input MIDI::Port; this object takes responsibility for
|
||||||
* adding & removing it from the MIDI::Manager and destroying it. @param
|
* adding & removing it from the MIDI::Manager and destroying it. @param
|
||||||
|
|
@ -52,31 +52,16 @@ using namespace PBD;
|
||||||
*/
|
*/
|
||||||
SurfacePort::SurfacePort (Surface& s)
|
SurfacePort::SurfacePort (Surface& s)
|
||||||
: _surface (&s)
|
: _surface (&s)
|
||||||
, _input_port (0)
|
|
||||||
, _output_port (0)
|
|
||||||
{
|
{
|
||||||
if (_surface->mcp().device_info().uses_ipmidi()) {
|
if (_surface->mcp().device_info().uses_ipmidi()) {
|
||||||
_input_port = new MIDI::IPMIDIPort (_surface->mcp().ipmidi_base() +_surface->number());
|
_input_port = new MIDI::IPMIDIPort (_surface->mcp().ipmidi_base() +_surface->number());
|
||||||
_output_port = _input_port;
|
_output_port = _input_port;
|
||||||
} else {
|
} else {
|
||||||
ARDOUR::PortEngine& port_engine (ARDOUR::AudioEngine::instance()->port_engine());
|
_async_in = AudioEngine::instance()->register_input_port (DataType::MIDI, string_compose (_("%1 in"), _surface->name()), true);
|
||||||
|
_async_out = AudioEngine::instance()->register_output_port (DataType::MIDI, string_compose (_("%1 out"), _surface->name()), true);
|
||||||
|
|
||||||
_input_port = new MIDI::JackMIDIPort (string_compose (_("%1 in"), _surface->name()), MIDI::Port::IsInput, port_engine);
|
_input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in).get();
|
||||||
_output_port =new MIDI::JackMIDIPort (string_compose (_("%1 out"), _surface->name()), MIDI::Port::IsOutput, port_engine);
|
_output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_out).get();
|
||||||
|
|
||||||
/* MackieControl has its own thread for handling input from the input
|
|
||||||
* port, and we don't want anything handling output from the output
|
|
||||||
* port. This stops the Generic MIDI UI event loop in ardour from
|
|
||||||
* attempting to handle these ports.
|
|
||||||
*/
|
|
||||||
|
|
||||||
_input_port->set_centrally_parsed (false);
|
|
||||||
_output_port->set_centrally_parsed (false);
|
|
||||||
|
|
||||||
MIDI::Manager * mm = MIDI::Manager::instance();
|
|
||||||
|
|
||||||
mm->add_port (_input_port);
|
|
||||||
mm->add_port (_output_port);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,17 +71,15 @@ SurfacePort::~SurfacePort()
|
||||||
delete _input_port;
|
delete _input_port;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
MIDI::Manager* mm = MIDI::Manager::instance ();
|
if (_async_in) {
|
||||||
|
AudioEngine::instance()->unregister_port (_async_in);
|
||||||
if (_input_port) {
|
_async_in.reset ();
|
||||||
mm->remove_port (_input_port);
|
|
||||||
delete _input_port;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_output_port) {
|
if (_async_out) {
|
||||||
_output_port->drain (10000);
|
_output_port->drain (10000);
|
||||||
mm->remove_port (_output_port);
|
AudioEngine::instance()->unregister_port (_async_out);
|
||||||
delete _output_port;
|
_async_out.reset ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,16 +21,23 @@
|
||||||
#include <midi++/types.h>
|
#include <midi++/types.h>
|
||||||
|
|
||||||
#include "pbd/signals.h"
|
#include "pbd/signals.h"
|
||||||
|
|
||||||
|
|
||||||
#include "midi_byte_array.h"
|
#include "midi_byte_array.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
namespace MIDI {
|
namespace MIDI {
|
||||||
class Port;
|
|
||||||
class Parser;
|
class Parser;
|
||||||
|
class Port;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MackieControlProtocol;
|
class MackieControlProtocol;
|
||||||
|
|
||||||
|
namespace ARDOUR {
|
||||||
|
class AsyncMIDIPort;
|
||||||
|
class Port;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Mackie
|
namespace Mackie
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -49,17 +56,17 @@ public:
|
||||||
/// an easier way to output bytes via midi
|
/// an easier way to output bytes via midi
|
||||||
int write (const MidiByteArray&);
|
int write (const MidiByteArray&);
|
||||||
|
|
||||||
MIDI::Port& input_port() { return *_input_port; }
|
MIDI::Port& input_port() const { return *_input_port; }
|
||||||
const MIDI::Port& input_port() const { return *_input_port; }
|
MIDI::Port& output_port() const { return *_output_port; }
|
||||||
MIDI::Port& output_port() { return *_output_port; }
|
|
||||||
const MIDI::Port& output_port() const { return *_output_port; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mackie::Surface* _surface;
|
Mackie::Surface* _surface;
|
||||||
MIDI::Port* _input_port;
|
MIDI::Port* _input_port;
|
||||||
MIDI::Port* _output_port;
|
MIDI::Port* _output_port;
|
||||||
|
boost::shared_ptr<ARDOUR::Port> _async_in;
|
||||||
|
boost::shared_ptr<ARDOUR::Port> _async_out;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream& operator << (std::ostream& , const SurfacePort& port);
|
std::ostream& operator << (std::ostream& , const SurfacePort& port);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue