mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-17 20:26:30 +01:00
convert GenericMIDI into a real control protocol module, with its own event loop and ports
This commit is contained in:
parent
1ced4067aa
commit
d100c92731
2 changed files with 202 additions and 41 deletions
|
|
@ -41,6 +41,7 @@
|
||||||
#include "pbd/error.h"
|
#include "pbd/error.h"
|
||||||
#include "pbd/failed_constructor.h"
|
#include "pbd/failed_constructor.h"
|
||||||
#include "pbd/file_utils.h"
|
#include "pbd/file_utils.h"
|
||||||
|
#include "pbd/i18n.h"
|
||||||
#include "pbd/strsplit.h"
|
#include "pbd/strsplit.h"
|
||||||
#include "pbd/types_convert.h"
|
#include "pbd/types_convert.h"
|
||||||
#include "pbd/xml++.h"
|
#include "pbd/xml++.h"
|
||||||
|
|
@ -63,37 +64,47 @@
|
||||||
#include "midifunction.h"
|
#include "midifunction.h"
|
||||||
#include "midiaction.h"
|
#include "midiaction.h"
|
||||||
|
|
||||||
|
#include "pbd/abstract_ui.cc" // instantiate template
|
||||||
|
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
|
using namespace Glib;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#include "pbd/i18n.h"
|
|
||||||
|
|
||||||
#define midi_ui_context() MidiControlUI::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
|
|
||||||
|
|
||||||
GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
|
GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
|
||||||
: ControlProtocol (s, _("Generic MIDI"))
|
: ControlProtocol (s, _("Generic MIDI"))
|
||||||
|
, AbstractUI<GenericMIDIRequest> (name())
|
||||||
, connection_state (ConnectionState (0))
|
, connection_state (ConnectionState (0))
|
||||||
, _motorised (false)
|
, _motorised (false)
|
||||||
, _threshold (10)
|
, _threshold (10)
|
||||||
, gui (0)
|
, gui (0)
|
||||||
{
|
{
|
||||||
// _input_port = boost::dynamic_pointer_cast<AsyncMIDIPort> (s.midi_input_port ());
|
boost::shared_ptr<ARDOUR::Port> inp;
|
||||||
// _output_port = boost::dynamic_pointer_cast<AsyncMIDIPort> (s.midi_output_port ());
|
boost::shared_ptr<ARDOUR::Port> outp;
|
||||||
|
|
||||||
|
inp = AudioEngine::instance()->register_input_port (DataType::MIDI, _("MIDI Control In"), true);
|
||||||
|
outp = AudioEngine::instance()->register_output_port (DataType::MIDI, _("MIDI Control Out"), true);
|
||||||
|
|
||||||
|
if (inp == 0 || outp == 0) {
|
||||||
|
throw failed_constructor();
|
||||||
|
}
|
||||||
|
|
||||||
|
_input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(inp);
|
||||||
|
_output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(outp);
|
||||||
|
|
||||||
_input_bundle.reset (new ARDOUR::Bundle (_("Generic MIDI Control In"), true));
|
_input_bundle.reset (new ARDOUR::Bundle (_("Generic MIDI Control In"), true));
|
||||||
_output_bundle.reset (new ARDOUR::Bundle (_("Generic MIDI Control Out"), false));
|
_output_bundle.reset (new ARDOUR::Bundle (_("Generic MIDI Control Out"), false));
|
||||||
|
|
||||||
_input_bundle->add_channel (
|
_input_bundle->add_channel (
|
||||||
boost::static_pointer_cast<MidiPort>(_input_port)->name(),
|
inp->name(),
|
||||||
ARDOUR::DataType::MIDI,
|
ARDOUR::DataType::MIDI,
|
||||||
session->engine().make_port_name_non_relative (boost::static_pointer_cast<MidiPort>(_input_port)->name())
|
session->engine().make_port_name_non_relative (inp->name())
|
||||||
);
|
);
|
||||||
|
|
||||||
_output_bundle->add_channel (
|
_output_bundle->add_channel (
|
||||||
boost::static_pointer_cast<MidiPort>(_output_port)->name(),
|
outp->name(),
|
||||||
ARDOUR::DataType::MIDI,
|
ARDOUR::DataType::MIDI,
|
||||||
session->engine().make_port_name_non_relative (boost::static_pointer_cast<MidiPort>(_output_port)->name())
|
session->engine().make_port_name_non_relative (outp->name())
|
||||||
);
|
);
|
||||||
|
|
||||||
session->BundleAddedOrRemoved ();
|
session->BundleAddedOrRemoved ();
|
||||||
|
|
@ -105,7 +116,7 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
|
||||||
_current_bank = 0;
|
_current_bank = 0;
|
||||||
_bank_size = 0;
|
_bank_size = 0;
|
||||||
|
|
||||||
/* these signals are emitted by the MidiControlUI's event loop thread
|
/* these signals are emitted by our event loop thread
|
||||||
* and we may as well handle them right there in the same the same
|
* and we may as well handle them right there in the same the same
|
||||||
* thread
|
* thread
|
||||||
*/
|
*/
|
||||||
|
|
@ -119,22 +130,36 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Session::SendFeedback.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::send_feedback, this));
|
Session::SendFeedback.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::send_feedback, this));
|
||||||
//Session::SendFeedback.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::send_feedback, this), midi_ui_context());;
|
|
||||||
|
|
||||||
/* this one is cross-thread */
|
/* this one is cross-thread */
|
||||||
|
|
||||||
PresentationInfo::Change.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context());
|
PresentationInfo::Change.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), this);
|
||||||
|
|
||||||
/* Catch port connections and disconnections (cross-thread) */
|
/* Catch port connections and disconnections (cross-thread) */
|
||||||
ARDOUR::AudioEngine::instance()->PortConnectedOrDisconnected.connect (port_connection, MISSING_INVALIDATOR,
|
ARDOUR::AudioEngine::instance()->PortConnectedOrDisconnected.connect (port_connection, MISSING_INVALIDATOR,
|
||||||
boost::bind (&GenericMidiControlProtocol::connection_handler, this, _1, _2, _3, _4, _5),
|
boost::bind (&GenericMidiControlProtocol::connection_handler, this, _1, _2, _3, _4, _5),
|
||||||
midi_ui_context());
|
this);
|
||||||
|
|
||||||
reload_maps ();
|
reload_maps ();
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericMidiControlProtocol::~GenericMidiControlProtocol ()
|
GenericMidiControlProtocol::~GenericMidiControlProtocol ()
|
||||||
{
|
{
|
||||||
|
if (_input_port) {
|
||||||
|
DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("unregistering input port %1\n", boost::shared_ptr<ARDOUR::Port>(_input_port)->name()));
|
||||||
|
Glib::Threads::Mutex::Lock em (AudioEngine::instance()->process_lock());
|
||||||
|
AudioEngine::instance()->unregister_port (_input_port);
|
||||||
|
_input_port.reset ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_output_port) {
|
||||||
|
_output_port->drain (10000, 250000); /* check every 10 msecs, wait up to 1/4 second for the port to drain */
|
||||||
|
DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("unregistering output port %1\n", boost::shared_ptr<ARDOUR::Port>(_output_port)->name()));
|
||||||
|
Glib::Threads::Mutex::Lock em (AudioEngine::instance()->process_lock());
|
||||||
|
AudioEngine::instance()->unregister_port (_output_port);
|
||||||
|
_output_port.reset ();
|
||||||
|
}
|
||||||
|
|
||||||
drop_all ();
|
drop_all ();
|
||||||
tear_down_gui ();
|
tear_down_gui ();
|
||||||
}
|
}
|
||||||
|
|
@ -279,12 +304,57 @@ GenericMidiControlProtocol::drop_bindings ()
|
||||||
_current_bank = 0;
|
_current_bank = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
GenericMidiControlProtocol::set_active (bool /*yn*/)
|
GenericMidiControlProtocol::do_request (GenericMIDIRequest* req)
|
||||||
{
|
{
|
||||||
/* nothing to do here: the MIDI UI thread in libardour handles all our
|
if (req->type == CallSlot) {
|
||||||
I/O needs.
|
|
||||||
*/
|
call_slot (MISSING_INVALIDATOR, req->the_slot);
|
||||||
|
|
||||||
|
} else if (req->type == Quit) {
|
||||||
|
|
||||||
|
stop ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
GenericMidiControlProtocol::stop ()
|
||||||
|
{
|
||||||
|
BaseUI::quit ();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GenericMidiControlProtocol::thread_init ()
|
||||||
|
{
|
||||||
|
pthread_set_name (event_loop_name().c_str());
|
||||||
|
|
||||||
|
PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048);
|
||||||
|
ARDOUR::SessionEvent::create_per_thread_pool (event_loop_name(), 128);
|
||||||
|
|
||||||
|
set_thread_priority ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
GenericMidiControlProtocol::set_active (bool yn)
|
||||||
|
{
|
||||||
|
DEBUG_TRACE (DEBUG::GenericMidi, string_compose("GenericMIDI::set_active init with yn: '%1'\n", yn));
|
||||||
|
|
||||||
|
if (yn == active()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yn) {
|
||||||
|
BaseUI::run ();
|
||||||
|
} else {
|
||||||
|
BaseUI::quit ();
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlProtocol::set_active (yn);
|
||||||
|
|
||||||
|
DEBUG_TRACE (DEBUG::GenericMidi, string_compose("GenericMIDI::set_active done with yn: '%1'\n", yn));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -539,6 +609,17 @@ GenericMidiControlProtocol::get_state ()
|
||||||
{
|
{
|
||||||
XMLNode& node (ControlProtocol::get_state());
|
XMLNode& node (ControlProtocol::get_state());
|
||||||
|
|
||||||
|
|
||||||
|
XMLNode* child;
|
||||||
|
|
||||||
|
child = new XMLNode (X_("Input"));
|
||||||
|
child->add_child_nocopy (boost::shared_ptr<ARDOUR::Port>(_input_port)->get_state());
|
||||||
|
node.add_child_nocopy (*child);
|
||||||
|
|
||||||
|
child = new XMLNode (X_("Output"));
|
||||||
|
child->add_child_nocopy (boost::shared_ptr<ARDOUR::Port>(_output_port)->get_state());
|
||||||
|
node.add_child_nocopy (*child);
|
||||||
|
|
||||||
node.set_property (X_("feedback-interval"), _feedback_interval);
|
node.set_property (X_("feedback-interval"), _feedback_interval);
|
||||||
node.set_property (X_("threshold"), _threshold);
|
node.set_property (X_("threshold"), _threshold);
|
||||||
node.set_property (X_("motorized"), _motorised);
|
node.set_property (X_("motorized"), _motorised);
|
||||||
|
|
@ -572,11 +653,26 @@ GenericMidiControlProtocol::set_state (const XMLNode& node, int version)
|
||||||
{
|
{
|
||||||
XMLNodeList nlist;
|
XMLNodeList nlist;
|
||||||
XMLNodeConstIterator niter;
|
XMLNodeConstIterator niter;
|
||||||
|
XMLNode const* child;
|
||||||
|
|
||||||
if (ControlProtocol::set_state (node, version)) {
|
if (ControlProtocol::set_state (node, version)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((child = node.child (X_("Input"))) != 0) {
|
||||||
|
XMLNode* portnode = child->child (Port::state_node_name.c_str());
|
||||||
|
if (portnode) {
|
||||||
|
boost::shared_ptr<ARDOUR::Port>(_input_port)->set_state (*portnode, version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((child = node.child (X_("Output"))) != 0) {
|
||||||
|
XMLNode* portnode = child->child (Port::state_node_name.c_str());
|
||||||
|
if (portnode) {
|
||||||
|
boost::shared_ptr<ARDOUR::Port>(_output_port)->set_state (*portnode, version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!node.get_property ("feedback-interval", _feedback_interval)) {
|
if (!node.get_property ("feedback-interval", _feedback_interval)) {
|
||||||
_feedback_interval = 10000;
|
_feedback_interval = 10000;
|
||||||
}
|
}
|
||||||
|
|
@ -623,15 +719,18 @@ GenericMidiControlProtocol::set_state (const XMLNode& node, int version)
|
||||||
|
|
||||||
if (load_dynamic_bindings) {
|
if (load_dynamic_bindings) {
|
||||||
Glib::Threads::Mutex::Lock lm2 (controllables_lock);
|
Glib::Threads::Mutex::Lock lm2 (controllables_lock);
|
||||||
nlist = node.children(); // "Controls"
|
XMLNode* controls_node = node.child (X_("Controls"));
|
||||||
|
|
||||||
|
if (controls_node) {
|
||||||
|
|
||||||
|
nlist = controls_node->children();
|
||||||
|
|
||||||
if (!nlist.empty()) {
|
if (!nlist.empty()) {
|
||||||
nlist = nlist.front()->children(); // "MIDIControllable" ...
|
|
||||||
|
|
||||||
if (!nlist.empty()) {
|
|
||||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||||
|
|
||||||
PBD::ID id;
|
PBD::ID id;
|
||||||
|
|
||||||
if ((*niter)->get_property ("id", id)) {
|
if ((*niter)->get_property ("id", id)) {
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Relearned binding for session: Control ID: %1\n", id.to_s()));
|
DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Relearned binding for session: Control ID: %1\n", id.to_s()));
|
||||||
|
|
@ -1450,10 +1549,14 @@ GenericMidiControlProtocol::set_threshold (int t)
|
||||||
bool
|
bool
|
||||||
GenericMidiControlProtocol::connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn)
|
GenericMidiControlProtocol::connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn)
|
||||||
{
|
{
|
||||||
|
bool input_was_connected = (connection_state & InputConnected);
|
||||||
|
|
||||||
if (!_input_port || !_output_port) {
|
if (!_input_port || !_output_port) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("connection change: %1 and %2 connected ? %3\n", name1, name2, yn));
|
||||||
|
|
||||||
string ni = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (boost::shared_ptr<ARDOUR::Port>(_input_port)->name());
|
string ni = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (boost::shared_ptr<ARDOUR::Port>(_input_port)->name());
|
||||||
string no = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (boost::shared_ptr<ARDOUR::Port>(_output_port)->name());
|
string no = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (boost::shared_ptr<ARDOUR::Port>(_output_port)->name());
|
||||||
|
|
||||||
|
|
@ -1474,18 +1577,14 @@ GenericMidiControlProtocol::connection_handler (boost::weak_ptr<ARDOUR::Port>, s
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((connection_state & (InputConnected|OutputConnected)) == (InputConnected|OutputConnected)) {
|
if (connection_state & InputConnected) {
|
||||||
|
if (!input_was_connected) {
|
||||||
/* XXX this is a horrible hack. Without a short sleep here,
|
start_midi_handling ();
|
||||||
something prevents the device wakeup messages from being
|
}
|
||||||
sent and/or the responses from being received.
|
|
||||||
*/
|
|
||||||
|
|
||||||
g_usleep (100000);
|
|
||||||
connected ();
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
if (input_was_connected) {
|
||||||
|
stop_midi_handling ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionChange (); /* emit signal for our GUI */
|
ConnectionChange (); /* emit signal for our GUI */
|
||||||
|
|
@ -1493,11 +1592,6 @@ GenericMidiControlProtocol::connection_handler (boost::weak_ptr<ARDOUR::Port>, s
|
||||||
return true; /* connection status changed */
|
return true; /* connection status changed */
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
GenericMidiControlProtocol::connected ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<Port>
|
boost::shared_ptr<Port>
|
||||||
GenericMidiControlProtocol::output_port() const
|
GenericMidiControlProtocol::output_port() const
|
||||||
{
|
{
|
||||||
|
|
@ -1518,3 +1612,52 @@ GenericMidiControlProtocol::maybe_start_touch (boost::shared_ptr<Controllable> c
|
||||||
actl->start_touch (session->audible_sample ());
|
actl->start_touch (session->audible_sample ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
GenericMidiControlProtocol::start_midi_handling ()
|
||||||
|
{
|
||||||
|
/* This connection means that whenever data is ready from the input
|
||||||
|
* port, the relevant thread will invoke our ::midi_input_handler()
|
||||||
|
* method, which will read the data, and invoke the parser.
|
||||||
|
*/
|
||||||
|
|
||||||
|
_input_port->xthread().set_receive_handler (sigc::bind (sigc::mem_fun (this, &GenericMidiControlProtocol::midi_input_handler), boost::weak_ptr<AsyncMIDIPort> (_input_port)));
|
||||||
|
_input_port->xthread().attach (main_loop()->get_context());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GenericMidiControlProtocol::stop_midi_handling ()
|
||||||
|
{
|
||||||
|
midi_connections.drop_connections ();
|
||||||
|
|
||||||
|
/* Note: the input handler is still active at this point, but we're no
|
||||||
|
* longer connected to any of the parser signals
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GenericMidiControlProtocol::midi_input_handler (Glib::IOCondition ioc, boost::weak_ptr<ARDOUR::AsyncMIDIPort> wport)
|
||||||
|
{
|
||||||
|
boost::shared_ptr<AsyncMIDIPort> port (wport.lock());
|
||||||
|
|
||||||
|
if (!port) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("something happend on %1\n", boost::shared_ptr<MIDI::Port>(port)->name()));
|
||||||
|
|
||||||
|
if (ioc & ~IO_IN) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioc & IO_IN) {
|
||||||
|
|
||||||
|
port->clear ();
|
||||||
|
DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("data available on %1\n", boost::shared_ptr<MIDI::Port>(port)->name()));
|
||||||
|
samplepos_t now = session->engine().sample_time();
|
||||||
|
port->parse (now);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,9 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <glibmm/threads.h>
|
#include <glibmm/threads.h>
|
||||||
|
|
||||||
|
#define ABSTRACT_UI_EXPORTS
|
||||||
|
#include "pbd/abstract_ui.h"
|
||||||
|
|
||||||
#include "ardour/types.h"
|
#include "ardour/types.h"
|
||||||
#include "ardour/port.h"
|
#include "ardour/port.h"
|
||||||
|
|
||||||
|
|
@ -48,11 +51,23 @@ class MIDIControllable;
|
||||||
class MIDIFunction;
|
class MIDIFunction;
|
||||||
class MIDIAction;
|
class MIDIAction;
|
||||||
|
|
||||||
class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
|
struct GenericMIDIRequest : public BaseUI::BaseRequestObject {
|
||||||
|
public:
|
||||||
|
GenericMIDIRequest () {}
|
||||||
|
~GenericMIDIRequest () {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class GenericMidiControlProtocol : public ARDOUR::ControlProtocol, public AbstractUI<GenericMIDIRequest> {
|
||||||
public:
|
public:
|
||||||
GenericMidiControlProtocol (ARDOUR::Session&);
|
GenericMidiControlProtocol (ARDOUR::Session&);
|
||||||
virtual ~GenericMidiControlProtocol();
|
virtual ~GenericMidiControlProtocol();
|
||||||
|
|
||||||
|
void do_request (GenericMIDIRequest*);
|
||||||
|
int stop ();
|
||||||
|
|
||||||
|
void thread_init ();
|
||||||
|
|
||||||
int set_active (bool yn);
|
int set_active (bool yn);
|
||||||
static bool probe() { return true; }
|
static bool probe() { return true; }
|
||||||
|
|
||||||
|
|
@ -169,7 +184,6 @@ private:
|
||||||
int connection_state;
|
int connection_state;
|
||||||
bool connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn);
|
bool connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn);
|
||||||
PBD::ScopedConnection port_connection;
|
PBD::ScopedConnection port_connection;
|
||||||
void connected();
|
|
||||||
|
|
||||||
std::string _current_binding;
|
std::string _current_binding;
|
||||||
uint32_t _bank_size;
|
uint32_t _bank_size;
|
||||||
|
|
@ -185,7 +199,11 @@ private:
|
||||||
mutable void *gui;
|
mutable void *gui;
|
||||||
void build_gui ();
|
void build_gui ();
|
||||||
|
|
||||||
|
PBD::ScopedConnectionList midi_connections;
|
||||||
|
|
||||||
|
bool midi_input_handler (Glib::IOCondition ioc, boost::weak_ptr<ARDOUR::AsyncMIDIPort> port);
|
||||||
|
void start_midi_handling ();
|
||||||
|
void stop_midi_handling ();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ardour_generic_midi_control_protocol_h */
|
#endif /* ardour_generic_midi_control_protocol_h */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue