get faderport i/o working, basics of identifying control activity
authorPaul Davis <paul@linuxaudiosystems.com>
Tue, 24 Nov 2015 23:00:11 +0000 (18:00 -0500)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 24 Nov 2015 23:00:11 +0000 (18:00 -0500)
libs/midi++2/parser.cc
libs/surfaces/faderport/faderport.cc [new file with mode: 0644]
libs/surfaces/faderport/faderport.h [new file with mode: 0644]
libs/surfaces/faderport/faderport_interface.cc
libs/surfaces/faderport/faderport_midi_protocol.cc [deleted file]
libs/surfaces/faderport/faderport_midi_protocol.h [deleted file]
libs/surfaces/faderport/fmcp_gui.cc
libs/surfaces/faderport/wscript

index e11094d26fd917f8f2718865826b576f7074ef0a..fcee844cefa5e05cc107c68f5dbc99b3c65750d4 100644 (file)
@@ -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 (file)
index 0000000..4cc541b
--- /dev/null
@@ -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.h b/libs/surfaces/faderport/faderport.h
new file mode 100644 (file)
index 0000000..0bf2812
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+    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.
+
+*/
+
+#ifndef ardour_surface_faderport_h
+#define ardour_surface_faderport_h
+
+#include <list>
+#include <glibmm/threads.h>
+
+#include "ardour/types.h"
+
+#include "control_protocol/control_protocol.h"
+
+namespace PBD {
+       class Controllable;
+       class ControllableDescriptor;
+}
+
+#include <midi++/types.h>
+
+//#include "pbd/signals.h"
+
+
+//#include "midi_byte_array.h"
+#include "types.h"
+
+#include "glibmm/main.h"
+
+namespace MIDI {
+       class Parser;
+       class Port;
+}
+
+
+namespace ARDOUR {
+       class AsyncMIDIPort;
+       class Port;
+       class Session;
+       class MidiPort;
+}
+
+
+class MIDIControllable;
+class MIDIFunction;
+class MIDIAction;
+
+class FaderPort : public ARDOUR::ControlProtocol {
+  public:
+       FaderPort (ARDOUR::Session&);
+       virtual ~FaderPort();
+
+       int set_active (bool yn);
+
+       /* 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);
+
+       int set_feedback (bool yn);
+       bool get_feedback () const;
+
+       XMLNode& get_state ();
+       int set_state (const XMLNode&, int version);
+
+       bool has_editor () const { return true; }
+       void* get_gui () const;
+       void  tear_down_gui ();
+
+       void set_current_bank (uint32_t);
+       void next_bank ();
+       void prev_bank ();
+
+       void reset_controllables ();
+
+       void set_motorised (bool);
+
+       bool motorised () const {
+               return _motorised;
+       }
+
+       void set_threshold (int);
+
+       int threshold () const {
+               return _threshold;
+       }
+
+       bool device_active() const { return _device_active; }
+
+  private:
+       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;
+       int native_counter;
+
+       bool  do_feedback;
+       void  send_feedback ();
+
+       PBD::ScopedConnectionList midi_connections;
+
+       bool midi_input_handler (Glib::IOCondition ioc, boost::shared_ptr<ARDOUR::AsyncMIDIPort> port);
+
+       std::string _current_binding;
+       uint32_t _bank_size;
+       uint32_t _current_bank;
+       /** true if this surface is motorised.  If it is, we assume
+           that the surface's controls are never out of sync with
+           Ardour's state, so we don't have to take steps to avoid
+           values jumping around when things are not in sync.
+       */
+       bool _motorised;
+       int _threshold;
+
+       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_surface_faderport_h */
index c7c2815a15099369b8c4cea99eb7999f67f93710..77809b7dbf071e5bb1f44065e3fa63b5de4040a7 100644 (file)
 #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 (file)
index 23cfc2e..0000000
+++ /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/faderport_midi_protocol.h b/libs/surfaces/faderport/faderport_midi_protocol.h
deleted file mode 100644 (file)
index 85dfb93..0000000
+++ /dev/null
@@ -1,132 +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.
-
-*/
-
-#ifndef ardour_generic_midi_control_protocol_h
-#define ardour_generic_midi_control_protocol_h
-
-#include <list>
-#include <glibmm/threads.h>
-
-#include "ardour/types.h"
-
-#include "control_protocol/control_protocol.h"
-
-namespace PBD {
-       class Controllable;
-       class ControllableDescriptor;
-}
-
-#include <midi++/types.h>
-
-//#include "pbd/signals.h"
-
-
-//#include "midi_byte_array.h"
-#include "types.h"
-
-#include "glibmm/main.h"
-
-namespace MIDI {
-       class Parser;
-       class Port;
-}
-
-
-namespace ARDOUR {
-       class AsyncMIDIPort;
-       class Port;
-       class Session;
-       class MidiPort;
-}
-
-
-class MIDIControllable;
-class MIDIFunction;
-class MIDIAction;
-
-class FaderportMidiControlProtocol : public ARDOUR::ControlProtocol {
-  public:
-       FaderportMidiControlProtocol (ARDOUR::Session&);
-       virtual ~FaderportMidiControlProtocol();
-
-       int set_active (bool yn);
-       static bool probe() { return true; }  //do SysEx device check here?
-
-       void set_feedback_interval (ARDOUR::microseconds_t);
-
-       int set_feedback (bool yn);
-       bool get_feedback () const;
-
-       XMLNode& get_state ();
-       int set_state (const XMLNode&, int version);
-
-       bool has_editor () const { return true; }
-       void* get_gui () const;
-       void  tear_down_gui ();
-
-       void set_current_bank (uint32_t);
-       void next_bank ();
-       void prev_bank ();
-
-       void set_motorised (bool);
-
-       bool motorised () const {
-               return _motorised;
-       }
-
-       void set_threshold (int);
-
-       int threshold () const {
-               return _threshold;
-       }
-
-  private:
-       MIDI::Port* _input_port;
-       MIDI::Port* _output_port;
-       boost::shared_ptr<ARDOUR::Port> _async_in;
-       boost::shared_ptr<ARDOUR::Port> _async_out;
-
-       ARDOUR::microseconds_t _feedback_interval;
-       ARDOUR::microseconds_t last_feedback_time;
-       int native_counter;
-
-       bool  do_feedback;
-       void  send_feedback ();
-
-       PBD::ScopedConnection midi_recv_connection;
-       void midi_receiver (MIDI::Parser &p, MIDI::byte *, size_t);
-
-       bool midi_input_handler (Glib::IOCondition ioc, ARDOUR::AsyncMIDIPort* port);
-
-       std::string _current_binding;
-       uint32_t _bank_size;
-       uint32_t _current_bank;
-       /** true if this surface is motorised.  If it is, we assume
-           that the surface's controls are never out of sync with
-           Ardour's state, so we don't have to take steps to avoid
-           values jumping around when things are not in sync.
-       */
-       bool _motorised;
-       int _threshold;
-
-       mutable void *gui;
-       void build_gui ();
-};
-
-#endif /* ardour_generic_midi_control_protocol_h */
index 1569b88d01208081984b99b5dc30c22ed3b2b45c..46239af57c63ab87939dd02836c24c482051a5e9 100644 (file)
 #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)
index e3efc70ed50d27620b7f33db9f80a08b5dc18926..73f4504d2bcfc2a29543766e3b6d37546f39e2f2 100644 (file)
@@ -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
     '''