diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2015-11-24 18:00:11 -0500 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2015-11-24 18:00:11 -0500 |
commit | a15cf9f0b32d45a237bbd12adf0e2b985a817eeb (patch) | |
tree | 251f631533a3670daf3bdfd0c23b7f6161a2361c | |
parent | 2f1cdd3ffe0c8d1b9498e8edbd950b18e082dd00 (diff) |
get faderport i/o working, basics of identifying control activity
-rw-r--r-- | libs/midi++2/parser.cc | 2 | ||||
-rw-r--r-- | libs/surfaces/faderport/faderport.cc | 512 | ||||
-rw-r--r-- | libs/surfaces/faderport/faderport.h (renamed from libs/surfaces/faderport/faderport_midi_protocol.h) | 112 | ||||
-rw-r--r-- | libs/surfaces/faderport/faderport_interface.cc | 14 | ||||
-rw-r--r-- | libs/surfaces/faderport/faderport_midi_protocol.cc | 270 | ||||
-rw-r--r-- | libs/surfaces/faderport/fmcp_gui.cc | 16 | ||||
-rw-r--r-- | libs/surfaces/faderport/wscript | 2 |
7 files changed, 627 insertions, 301 deletions
diff --git a/libs/midi++2/parser.cc b/libs/midi++2/parser.cc index e11094d26f..fcee844cef 100644 --- a/libs/midi++2/parser.cc +++ b/libs/midi++2/parser.cc @@ -174,7 +174,7 @@ Parser::trace_event (Parser &, MIDI::byte *msg, size_t len) *o << trace_prefix << "Channel " << (msg[0]&0xF)+1 - << " PolyPressure" + << " PolyPressure " << (int) msg[1] << endmsg; break; diff --git a/libs/surfaces/faderport/faderport.cc b/libs/surfaces/faderport/faderport.cc new file mode 100644 index 0000000000..4cc541bf7b --- /dev/null +++ b/libs/surfaces/faderport/faderport.cc @@ -0,0 +1,512 @@ +/* + Copyright (C) 2006 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include <stdint.h> + +#include <sstream> +#include <algorithm> + +#include <glibmm/fileutils.h> +#include <glibmm/miscutils.h> + +#include "pbd/controllable_descriptor.h" +#include "pbd/error.h" +#include "pbd/failed_constructor.h" +#include "pbd/file_utils.h" +#include "pbd/xml++.h" +#include "pbd/compose.h" + +#include "midi++/port.h" + +#include "ardour/audioengine.h" +#include "ardour/filesystem_paths.h" +#include "ardour/session.h" +#include "ardour/route.h" +#include "ardour/midi_ui.h" +#include "ardour/midi_port.h" +#include "ardour/rc_configuration.h" +#include "ardour/midiport_manager.h" +#include "ardour/debug.h" +#include "ardour/async_midi_port.h" + +#include "faderport.h" + +using namespace ARDOUR; +using namespace PBD; +using namespace Glib; +using namespace std; + +#include "i18n.h" + +#define midi_ui_context() MidiControlUI::instance() /* a UICallback-derived object that specifies the event loop for signal handling */ + +FaderPort::FaderPort (Session& s) + : ControlProtocol (s, _("Faderport")) + , _motorised (true) + , _threshold (10) + , gui (0) + , connection_state (ConnectionState (0)) + , _device_active (false) + , fader_msb (0) + , fader_lsb (0) +{ + boost::shared_ptr<ARDOUR::Port> inp; + boost::shared_ptr<ARDOUR::Port> outp; + + inp = AudioEngine::instance()->register_input_port (DataType::MIDI, "Faderport Recv", true); + outp = AudioEngine::instance()->register_output_port (DataType::MIDI, "Faderport Send", true); + + _input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(inp); + _output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(outp); + + if (_input_port == 0 || _output_port == 0) { + throw failed_constructor(); + } + + do_feedback = false; + _feedback_interval = 10 * 1000; // microseconds + last_feedback_time = 0; + native_counter = 0; + + _current_bank = 0; + _bank_size = 0; + + /* handle device inquiry response */ + _input_port->parser()->sysex.connect_same_thread (midi_connections, boost::bind (&FaderPort::sysex_handler, this, _1, _2, _3)); + /* handle switches */ + _input_port->parser()->poly_pressure.connect_same_thread (midi_connections, boost::bind (&FaderPort::switch_handler, this, _1, _2)); + /* handle encoder */ + _input_port->parser()->pitchbend.connect_same_thread (midi_connections, boost::bind (&FaderPort::encoder_handler, this, _1, _2)); + /* handle fader */ + _input_port->parser()->controller.connect_same_thread (midi_connections, boost::bind (&FaderPort::fader_handler, this, _1, _2)); + + /* 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, &FaderPort::midi_input_handler), _input_port)); + _input_port->xthread().attach (midi_ui_context()->main_loop()->get_context()); + + Session::SendFeedback.connect_same_thread (*this, boost::bind (&FaderPort::send_feedback, this)); + //Session::SendFeedback.connect (*this, MISSING_INVALIDATOR, boost::bind (&FaderPort::send_feedback, this), midi_ui_context());; + + /* this one is cross-thread */ + + Route::RemoteControlIDChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&FaderPort::reset_controllables, this), midi_ui_context()); + + /* Catch port connections and disconnections */ + ARDOUR::AudioEngine::instance()->PortConnectedOrDisconnected.connect (port_connection, MISSING_INVALIDATOR, boost::bind (&FaderPort::connection_handler, this, _1, _2, _3, _4, _5), midi_ui_context()); + +} + +FaderPort::~FaderPort () +{ + if (_input_port) { + DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("unregistering input port %1\n", boost::shared_ptr<ARDOUR::Port>(_input_port)->name())); + AudioEngine::instance()->unregister_port (_input_port); + _input_port.reset (); + } + + if (_output_port) { +// _output_port->drain (10000); //ToDo: is this necessary? It hangs the shutdown, for me + DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("unregistering output port %1\n", boost::shared_ptr<ARDOUR::Port>(_output_port)->name())); + AudioEngine::instance()->unregister_port (_output_port); + _output_port.reset (); + } + + tear_down_gui (); +} + +void +FaderPort::switch_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb) +{ + switch (tb->controller_number) { + case Mute: + cerr << "Mute\n"; + break; + case Solo: + cerr << "Solo\n"; + break; + case Rec: + cerr << "Rec\n"; + break; + case Left: + cerr << "Left\n"; + break; + case Bank: + cerr << "Bank\n"; + break; + case Right: + cerr << "Right\n"; + break; + case Output: + cerr << "Output\n"; + break; + case Read: + cerr << "Read\n"; + break; + case Write: + cerr << "Write\n"; + break; + case Touch: + cerr << "Touch\n"; + break; + case Off: + cerr << "Off\n"; + break; + case Mix: + cerr << "Mix\n"; + break; + case Proj: + cerr << "Proj\n"; + break; + case Trns: + cerr << "Trns\n"; + break; + case Undo: + cerr << "Undo\n"; + break; + case Shift: + cerr << "Shift\n"; + break; + case Punch: + cerr << "Punch\n"; + break; + case User: + cerr << "User\n"; + break; + case Loop: + cerr << "Loop\n"; + break; + case Rewind: + cerr << "Rewind\n"; + break; + case Ffwd: + cerr << "Ffwd\n"; + break; + case Stop: + cerr << "Stop\n"; + break; + case Play: + cerr << "Play\n"; + break; + case RecEnable: + cerr << "RecEnable\n"; + break; + case Fader: + cerr << "Fader touch\n"; + break; + default: + cerr << "eh?\n"; + } + + /* send feedback to turn on the LED */ + + MIDI::byte buf[3]; + buf[0] = 0xa0; + buf[1] = tb->controller_number; + buf[2] = tb->value; + + _output_port->write (buf, 3, 0); +} + +void +FaderPort::encoder_handler (MIDI::Parser &, MIDI::pitchbend_t pb) +{ + if (pb < 8192) { + cerr << "Encoder right\n"; + } else { + cerr << "Encoder left\n"; + } +} + +void +FaderPort::fader_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb) +{ + bool was_fader = false; + + if (tb->controller_number == 0x0) { + fader_msb = tb->value; + was_fader = true; + } else if (tb->controller_number == 0x20) { + fader_lsb = tb->value; + was_fader = true; + } + + if (was_fader) { + cerr << "Fader now at " << ((fader_msb<<7)|fader_lsb) << endl; + } +} + +void +FaderPort::sysex_handler (MIDI::Parser &p, MIDI::byte *buf, size_t sz) +{ + if (sz < 17) { + return; + } + + if (buf[2] == 0x7f && + buf[3] == 0x06 && + buf[4] == 0x02 && + buf[5] == 0x0 && + buf[6] == 0x1 && + buf[7] == 0x06 && + buf[8] == 0x02 && + buf[9] == 0x0 && + buf[10] == 0x01 && + buf[11] == 0x0) { + _device_active = true; + + cerr << "FaderPort identified\n"; + + /* put it into native mode */ + + MIDI::byte native[3]; + native[0] = 0x91; + native[1] = 0x00; + native[2] = 0x64; + + _output_port->write (native, 3, 0); + } +} + +int +FaderPort::set_active (bool /*yn*/) +{ + return 0; +} + +void +FaderPort::set_feedback_interval (microseconds_t ms) +{ + _feedback_interval = ms; +} + +void +FaderPort::send_feedback () +{ + /* This is executed in RT "process" context", so no blocking calls + */ + + if (!do_feedback) { + return; + } + + microseconds_t now = get_microseconds (); + + if (last_feedback_time != 0) { + if ((now - last_feedback_time) < _feedback_interval) { + return; + } + } + + last_feedback_time = now; +} + +bool +FaderPort::midi_input_handler (Glib::IOCondition ioc, boost::shared_ptr<ARDOUR::AsyncMIDIPort> port) +{ + DEBUG_TRACE (DEBUG::MidiIO, string_compose ("something happend on %1\n", boost::shared_ptr<MIDI::Port>(port)->name())); + + if (ioc & ~IO_IN) { + return false; + } + + if (ioc & IO_IN) { + + if (port) { + port->clear (); + } + + DEBUG_TRACE (DEBUG::MidiIO, string_compose ("data available on %1\n", boost::shared_ptr<MIDI::Port>(port)->name())); + framepos_t now = session->engine().sample_time(); + port->parse (now); + } + + return true; +} + + +XMLNode& +FaderPort::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); + + return node; +} + +int +FaderPort::set_state (const XMLNode& node, int version) +{ + XMLNodeList nlist; + XMLNodeConstIterator niter; + XMLNode const* child; + + if (ControlProtocol::set_state (node, version)) { + 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); + } + } + + return 0; +} + +int +FaderPort::set_feedback (bool yn) +{ + do_feedback = yn; + last_feedback_time = 0; + return 0; +} + +bool +FaderPort::get_feedback () const +{ + return do_feedback; +} + +void +FaderPort::set_current_bank (uint32_t b) +{ + _current_bank = b; +// reset_controllables (); +} + +void +FaderPort::next_bank () +{ + _current_bank++; +// reset_controllables (); +} + +void +FaderPort::prev_bank() +{ + if (_current_bank) { + _current_bank--; +// reset_controllables (); + } +} + +void +FaderPort::set_motorised (bool m) +{ + _motorised = m; +} + +void +FaderPort::set_threshold (int t) +{ + _threshold = t; +} + +void +FaderPort::reset_controllables () +{ +} + +bool +FaderPort::connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn) +{ + if (!_input_port || !_output_port) { + return false; + } + + 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()); + + std::cerr << "Checking " << name1 << (yn ? " + " : " - " ) << name2 << " vs. " << ni << " & " << no << std::endl; + + if (ni == name1 || ni == name2) { + if (yn) { + connection_state |= InputConnected; + } else { + connection_state &= ~InputConnected; + } + } else if (no == name1 || no == name2) { + if (yn) { + connection_state |= OutputConnected; + } else { + connection_state &= ~OutputConnected; + } + } else { + /* not our ports */ + return false; + } + + if ((connection_state & (InputConnected|OutputConnected)) == (InputConnected|OutputConnected)) { + + /* XXX this is a horrible hack. Without a short sleep here, + something prevents the device wakeup messages from being + sent and/or the responses from being received. + */ + + g_usleep (100000); + connected (); + + } else { + DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 disconnected (input or output or both)\n", _name)); + _device_active = false; + } + + return true; /* connection status changed */ +} + +void +FaderPort::connected () +{ + std::cerr << "faderport connected\n"; + + /* send device inquiry */ + + MIDI::byte buf[6]; + + buf[0] = 0xf0; + buf[1] = 0x7e; + buf[2] = 0x7f; + buf[3] = 0x06; + buf[4] = 0x01; + buf[5] = 0xf7; + + _output_port->write (buf, 6, 0); +} diff --git a/libs/surfaces/faderport/faderport_midi_protocol.h b/libs/surfaces/faderport/faderport.h index 85dfb9342c..0bf28123b1 100644 --- a/libs/surfaces/faderport/faderport_midi_protocol.h +++ b/libs/surfaces/faderport/faderport.h @@ -17,8 +17,8 @@ */ -#ifndef ardour_generic_midi_control_protocol_h -#define ardour_generic_midi_control_protocol_h +#ifndef ardour_surface_faderport_h +#define ardour_surface_faderport_h #include <list> #include <glibmm/threads.h> @@ -60,13 +60,20 @@ class MIDIControllable; class MIDIFunction; class MIDIAction; -class FaderportMidiControlProtocol : public ARDOUR::ControlProtocol { +class FaderPort : public ARDOUR::ControlProtocol { public: - FaderportMidiControlProtocol (ARDOUR::Session&); - virtual ~FaderportMidiControlProtocol(); + FaderPort (ARDOUR::Session&); + virtual ~FaderPort(); int set_active (bool yn); - static bool probe() { return true; } //do SysEx device check here? + + /* It would be nice to send a device query message here to see if + * faderport is out there. But the probe() API doesn't provide + * a set of ports to be checked, so there's really no nice + * way to do this. We would have to fall back on the PortManager + * and get a list of all physical ports. Could be done .... + */ + static bool probe() { return true; } void set_feedback_interval (ARDOUR::microseconds_t); @@ -84,6 +91,8 @@ class FaderportMidiControlProtocol : public ARDOUR::ControlProtocol { void next_bank (); void prev_bank (); + void reset_controllables (); + void set_motorised (bool); bool motorised () const { @@ -96,11 +105,11 @@ class FaderportMidiControlProtocol : public ARDOUR::ControlProtocol { return _threshold; } + bool device_active() const { return _device_active; } + private: - MIDI::Port* _input_port; - MIDI::Port* _output_port; - boost::shared_ptr<ARDOUR::Port> _async_in; - boost::shared_ptr<ARDOUR::Port> _async_out; + boost::shared_ptr<ARDOUR::AsyncMIDIPort> _input_port; + boost::shared_ptr<ARDOUR::AsyncMIDIPort> _output_port; ARDOUR::microseconds_t _feedback_interval; ARDOUR::microseconds_t last_feedback_time; @@ -109,10 +118,9 @@ class FaderportMidiControlProtocol : public ARDOUR::ControlProtocol { bool do_feedback; void send_feedback (); - PBD::ScopedConnection midi_recv_connection; - void midi_receiver (MIDI::Parser &p, MIDI::byte *, size_t); + PBD::ScopedConnectionList midi_connections; - bool midi_input_handler (Glib::IOCondition ioc, ARDOUR::AsyncMIDIPort* port); + bool midi_input_handler (Glib::IOCondition ioc, boost::shared_ptr<ARDOUR::AsyncMIDIPort> port); std::string _current_binding; uint32_t _bank_size; @@ -127,6 +135,82 @@ class FaderportMidiControlProtocol : public ARDOUR::ControlProtocol { mutable void *gui; void build_gui (); + + 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; + + enum ConnectionState { + InputConnected = 0x1, + OutputConnected = 0x2 + }; + + int connection_state; + void connected (); + bool _device_active; + int fader_msb; + int fader_lsb; + + void sysex_handler (MIDI::Parser &p, MIDI::byte *, size_t); + void switch_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb); + void encoder_handler (MIDI::Parser &, MIDI::pitchbend_t pb); + void fader_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb); + + enum InButtonID { + Mute = 18, + Solo = 17, + Rec = 16, + Left = 19, + Bank = 20, + Right = 21, + Output = 22, + Read = 10, + Write = 9, + Touch = 8, + Off = 23, + Mix = 11, + Proj = 12, + Trns = 13, + Undo = 14, + Shift = 2, + Punch = 1, + User = 0, + Loop = 15, + Rewind = 3, + Ffwd = 4, + Stop = 5, + Play = 6, + RecEnable = 7, + Fader = 127, + }; + + /* + enum OutButtonID { + Mute = 18, + Solo = 17, + Rec = 16, + Left = 19, + Bank = 20, + Right = 21, + Output = 22, + Read = 10, + Write = 9, + Touch = 8, + Off = 23, + Mix = 11, + Proj = 12, + Trns = 13, + Undo = 14, + Shift = 2, + Punch = 1, + User = 0, + Loop = 15, + Rewind = 3, + Ffwd = 4, + Stop = 5, + Play = 6, + RecEnable = 7, + } + */ }; -#endif /* ardour_generic_midi_control_protocol_h */ +#endif /* ardour_surface_faderport_h */ diff --git a/libs/surfaces/faderport/faderport_interface.cc b/libs/surfaces/faderport/faderport_interface.cc index c7c2815a15..77809b7dbf 100644 --- a/libs/surfaces/faderport/faderport_interface.cc +++ b/libs/surfaces/faderport/faderport_interface.cc @@ -20,27 +20,27 @@ #include <pbd/failed_constructor.h> #include "control_protocol/control_protocol.h" -#include "faderport_midi_protocol.h" +#include "faderport.h" using namespace ARDOUR; static ControlProtocol* new_faderport_midi_protocol (ControlProtocolDescriptor* /*descriptor*/, Session* s) { - FaderportMidiControlProtocol* fmcp; + FaderPort* fp; try { - fmcp = new FaderportMidiControlProtocol (*s); + fp = new FaderPort (*s); } catch (failed_constructor& err) { return 0; } - if (fmcp->set_active (true)) { - delete fmcp; + if (fp->set_active (true)) { + delete fp; return 0; } - return fmcp; + return fp; } static void @@ -52,7 +52,7 @@ delete_faderport_midi_protocol (ControlProtocolDescriptor* /*descriptor*/, Contr static bool probe_faderport_midi_protocol (ControlProtocolDescriptor* /*descriptor*/) { - return FaderportMidiControlProtocol::probe (); + return FaderPort::probe (); } static ControlProtocolDescriptor faderport_midi_descriptor = { diff --git a/libs/surfaces/faderport/faderport_midi_protocol.cc b/libs/surfaces/faderport/faderport_midi_protocol.cc deleted file mode 100644 index 23cfc2e430..0000000000 --- a/libs/surfaces/faderport/faderport_midi_protocol.cc +++ /dev/null @@ -1,270 +0,0 @@ -/* - Copyright (C) 2006 Paul Davis - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include <stdint.h> - -#include <sstream> -#include <algorithm> - -#include <glibmm/fileutils.h> -#include <glibmm/miscutils.h> - -#include "pbd/controllable_descriptor.h" -#include "pbd/error.h" -#include "pbd/failed_constructor.h" -#include "pbd/file_utils.h" -#include "pbd/xml++.h" -#include "pbd/compose.h" - -#include "midi++/port.h" - -#include "ardour/audioengine.h" -#include "ardour/filesystem_paths.h" -#include "ardour/session.h" -#include "ardour/route.h" -#include "ardour/midi_ui.h" -#include "ardour/midi_port.h" -#include "ardour/rc_configuration.h" -#include "ardour/midiport_manager.h" -#include "ardour/debug.h" -#include "ardour/async_midi_port.h" - -#include "faderport_midi_protocol.h" - -using namespace ARDOUR; -using namespace PBD; -using namespace Glib; -using namespace std; - -#include "i18n.h" - -#define midi_ui_context() MidiControlUI::instance() /* a UICallback-derived object that specifies the event loop for signal handling */ - -FaderportMidiControlProtocol::FaderportMidiControlProtocol (Session& s) - : ControlProtocol (s, _("Faderport")) - , _motorised (true) - , _threshold (10) - , gui (0) -{ - _async_in = AudioEngine::instance()->register_input_port (DataType::MIDI, "Faderport Recv", true); - _async_out = AudioEngine::instance()->register_output_port (DataType::MIDI, "Faderport Send", true); - - if (_async_in == 0 || _async_out == 0) { - throw failed_constructor(); - } - - _input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in).get(); - _output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_out).get(); - - do_feedback = false; - _feedback_interval = 10 * 1000; // microseconds - last_feedback_time = 0; - native_counter = 0; - - _current_bank = 0; - _bank_size = 0; - -//NOTE TO PAUL: -// "midi_receiver" and "midi_input_handler" -// were 2 different approaches to try to capture MIDI data; neither seems to work as expected. - - -//not sure if this should do anything - (*_input_port).parser()->any.connect_same_thread (midi_recv_connection, boost::bind (&FaderportMidiControlProtocol::midi_receiver, this, _1, _2, _3)); - -//this is raw port acces (?) -// _input_port->xthread().set_receive_handler (sigc::bind (sigc::mem_fun (this, &FaderportMidiControlProtocol::midi_input_handler), _input_port)); - - Session::SendFeedback.connect_same_thread (*this, boost::bind (&FaderportMidiControlProtocol::send_feedback, this)); - //Session::SendFeedback.connect (*this, MISSING_INVALIDATOR, boost::bind (&FaderportMidiControlProtocol::send_feedback, this), midi_ui_context());; - - /* this one is cross-thread */ - - //Route::RemoteControlIDChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&FaderportMidiControlProtocol::reset_controllables, this), midi_ui_context()); - -} - -FaderportMidiControlProtocol::~FaderportMidiControlProtocol () -{ - if (_input_port) { - DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("unregistering input port %1\n", _async_in->name())); - AudioEngine::instance()->unregister_port (_async_in); - _async_in.reset ((ARDOUR::Port*) 0); - } - - if (_output_port) { -// _output_port->drain (10000); //ToDo: is this necessary? It hangs the shutdown, for me - DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("unregistering output port %1\n", _async_out->name())); - AudioEngine::instance()->unregister_port (_async_out); - _async_out.reset ((ARDOUR::Port*) 0); - } - - tear_down_gui (); -} - -void -FaderportMidiControlProtocol::midi_receiver (MIDI::Parser &p, MIDI::byte *, size_t) -{ -//NOTE: this never did anything -// printf("got some midi\n"); -} - - -int -FaderportMidiControlProtocol::set_active (bool /*yn*/) -{ - return 0; -} - -void -FaderportMidiControlProtocol::set_feedback_interval (microseconds_t ms) -{ - _feedback_interval = ms; -} - -void -FaderportMidiControlProtocol::send_feedback () -{ - /* This is executed in RT "process" context", so no blocking calls - */ - - if (!do_feedback) { - return; - } - - microseconds_t now = get_microseconds (); - - if (last_feedback_time != 0) { - if ((now - last_feedback_time) < _feedback_interval) { - return; - } - } - - //occasionally tell the Faderport to go into "Native" mode - //ToDo: trigger this on MIDI port connection ? - native_counter++; - if (native_counter > 10) { - native_counter = 0; - MIDI::byte midibuf[64]; - MIDI::byte *buf = midibuf; - *buf++ = (0x91); - *buf++ = (0x00); - *buf++ = (0x64); - _output_port->write (buf, 3, 0); - } - - last_feedback_time = now; -} - -bool -FaderportMidiControlProtocol::midi_input_handler (Glib::IOCondition ioc, ARDOUR::AsyncMIDIPort* port) -{ - DEBUG_TRACE (DEBUG::MidiIO, string_compose ("something happend on %1\n", ((ARDOUR::Port*)port)->name())); - - if (ioc & ~IO_IN) { - return false; - } - - if (ioc & IO_IN) { - - AsyncMIDIPort* asp = dynamic_cast<AsyncMIDIPort*> (port); - if (asp) { - asp->clear (); - } - - DEBUG_TRACE (DEBUG::MidiIO, string_compose ("data available on %1\n", ((ARDOUR::Port*)port)->name())); -// framepos_t now = _session.engine().sample_time(); -// port->parse (now); - } - - return true; -} - - -XMLNode& -FaderportMidiControlProtocol::get_state () -{ - XMLNode& node (ControlProtocol::get_state()); - char buf[32]; - - return node; -} - -int -FaderportMidiControlProtocol::set_state (const XMLNode& node, int version) -{ - XMLNodeList nlist; - XMLNodeConstIterator niter; - const XMLProperty* prop; - - if (ControlProtocol::set_state (node, version)) { - return -1; - } - - return 0; -} - -int -FaderportMidiControlProtocol::set_feedback (bool yn) -{ - do_feedback = yn; - last_feedback_time = 0; - return 0; -} - -bool -FaderportMidiControlProtocol::get_feedback () const -{ - return do_feedback; -} - -void -FaderportMidiControlProtocol::set_current_bank (uint32_t b) -{ - _current_bank = b; -// reset_controllables (); -} - -void -FaderportMidiControlProtocol::next_bank () -{ - _current_bank++; -// reset_controllables (); -} - -void -FaderportMidiControlProtocol::prev_bank() -{ - if (_current_bank) { - _current_bank--; -// reset_controllables (); - } -} - -void -FaderportMidiControlProtocol::set_motorised (bool m) -{ - _motorised = m; -} - -void -FaderportMidiControlProtocol::set_threshold (int t) -{ - _threshold = t; -} diff --git a/libs/surfaces/faderport/fmcp_gui.cc b/libs/surfaces/faderport/fmcp_gui.cc index 1569b88d01..46239af57c 100644 --- a/libs/surfaces/faderport/fmcp_gui.cc +++ b/libs/surfaces/faderport/fmcp_gui.cc @@ -31,18 +31,18 @@ #include "gtkmm2ext/gtk_ui.h" #include "gtkmm2ext/utils.h" -#include "faderport_midi_protocol.h" +#include "faderport.h" #include "i18n.h" class GMCPGUI : public Gtk::VBox { public: - GMCPGUI (FaderportMidiControlProtocol&); + GMCPGUI (FaderPort&); ~GMCPGUI (); private: - FaderportMidiControlProtocol& cp; + FaderPort& cp; Gtk::ComboBoxText map_combo; Gtk::Adjustment bank_adjustment; Gtk::SpinButton bank_spinner; @@ -63,17 +63,17 @@ using namespace Gtk; using namespace Gtkmm2ext; void* -FaderportMidiControlProtocol::get_gui () const +FaderPort::get_gui () const { if (!gui) { - const_cast<FaderportMidiControlProtocol*>(this)->build_gui (); + const_cast<FaderPort*>(this)->build_gui (); } static_cast<Gtk::VBox*>(gui)->show_all(); return gui; } void -FaderportMidiControlProtocol::tear_down_gui () +FaderPort::tear_down_gui () { if (gui) { Gtk::Widget *w = static_cast<Gtk::VBox*>(gui)->get_parent(); @@ -87,14 +87,14 @@ FaderportMidiControlProtocol::tear_down_gui () } void -FaderportMidiControlProtocol::build_gui () +FaderPort::build_gui () { gui = (void*) new GMCPGUI (*this); } /*--------------------*/ -GMCPGUI::GMCPGUI (FaderportMidiControlProtocol& p) +GMCPGUI::GMCPGUI (FaderPort& p) : cp (p) , bank_adjustment (1, 1, 100, 1, 10) , bank_spinner (bank_adjustment) diff --git a/libs/surfaces/faderport/wscript b/libs/surfaces/faderport/wscript index e3efc70ed5..73f4504d2b 100644 --- a/libs/surfaces/faderport/wscript +++ b/libs/surfaces/faderport/wscript @@ -15,7 +15,7 @@ def configure(conf): def build(bld): obj = bld(features = 'cxx cxxshlib') obj.source = ''' - faderport_midi_protocol.cc + faderport.cc fmcp_gui.cc faderport_interface.cc ''' |