a) dynamically loadable control surface support
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 5 Apr 2006 00:21:43 +0000 (00:21 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 5 Apr 2006 00:21:43 +0000 (00:21 +0000)
b) move tranzport and generic midi into separate dirs under "surfaces"

git-svn-id: svn://localhost/trunk/ardour2@442 d708f5d6-7413-0410-9779-e7cbd77b26cf

24 files changed:
SConstruct
gtk2_ardour/arval
libs/ardour/SConscript
libs/ardour/ardour/control_protocol.h
libs/ardour/ardour/generic_midi_control_protocol.h [deleted file]
libs/ardour/ardour/session.h
libs/ardour/ardour/tranzport_control_protocol.h [deleted file]
libs/ardour/generic_midi_control_protocol.cc [deleted file]
libs/ardour/globals.cc
libs/ardour/session.cc
libs/ardour/session_feedback.cc
libs/ardour/session_midi.cc
libs/ardour/session_state.cc
libs/ardour/tranzport_control_protocol.cc [deleted file]
libs/ardour/utils.cc
libs/pbd3/pthread_utils.cc
libs/surfaces/generic_midi/SConscript [new file with mode: 0644]
libs/surfaces/generic_midi/generic_midi_control_protocol.cc [new file with mode: 0644]
libs/surfaces/generic_midi/generic_midi_control_protocol.h [new file with mode: 0644]
libs/surfaces/generic_midi/interface.cc [new file with mode: 0644]
libs/surfaces/tranzport/SConscript [new file with mode: 0644]
libs/surfaces/tranzport/interface.cc [new file with mode: 0644]
libs/surfaces/tranzport/tranzport_control_protocol.cc [new file with mode: 0644]
libs/surfaces/tranzport/tranzport_control_protocol.h [new file with mode: 0644]

index 0806ac4d26243960c4058f244ffb5c2a8b69ed31..04d1b3545fe21caed7d8dc61084c9cc1832963fa 100644 (file)
@@ -518,6 +518,11 @@ else:
     'gtk2_ardour'
         ]
 
+surface_subdirs = [
+    'libs/surfaces/tranzport',
+    'libs/surfaces/generic_midi'
+    ]
+
 opts.Save('scache.conf', env)
 Help(opts.GenerateHelpText(env))
 
@@ -791,7 +796,7 @@ env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
 for subdir in coredirs:
     SConscript (subdir + '/SConscript')
 
-for sublistdir in [subdirs, gtk_subdirs]:
+for sublistdir in [subdirs, gtk_subdirs, surface_subdirs]:
        for subdir in sublistdir:
                SConscript (subdir + '/SConscript')
 
index 5254ad4df046587e3fd89968f650626e3eb9a487..a91943fb4d89d74c6fac3e3b589785cde47f88d3 100755 (executable)
@@ -1,3 +1,3 @@
 #!/bin/sh
 source ardev_common.sh
-exec valgrind --num-callers=12 --tool=memcheck ./ardour.bin --novst $*
+exec valgrind --db-attach=yes --num-callers=12 --tool=memcheck ./ardour.bin --novst $*
index 8bf62b9c0147b985ee0d697080305baae1f3a766..572851d2f22ddffc84853714c588f56e115e9728 100644 (file)
@@ -32,6 +32,7 @@ automation_event.cc
 configuration.cc
 connection.cc
 control_protocol.cc
+control_protocol_manager.cc
 crossfade.cc
 curve.cc
 cycle_timer.cc
@@ -42,7 +43,6 @@ externalsource.cc
 filesource.cc
 gain.cc
 gdither.cc
-generic_midi_control_protocol.cc
 globals.cc
 import.cc
 insert.cc
@@ -69,10 +69,8 @@ send.cc
 session.cc
 session_butler.cc
 session_click.cc
-session_control.cc
 session_events.cc
 session_export.cc
-session_feedback.cc
 session_midi.cc
 session_process.cc
 session_state.cc
@@ -85,7 +83,6 @@ source.cc
 state_manager.cc
 stateful.cc
 tempo.cc
-tranzport_control_protocol.cc
 utils.cc
 version.cc
 mix.cc
index c0869fad9a7a95bc9890e7e0128e959c54d64891..4088e2dd09d078bfbd4acb2b84d82291fa2f23a4 100644 (file)
@@ -16,7 +16,8 @@ class ControlProtocol : sigc::trackable {
        virtual ~ControlProtocol();
 
        virtual int init () { return 0; }
-       virtual bool active() const = 0;
+
+       sigc::signal<void> ActiveChanged;
 
        enum SendWhat {
                SendRoute,
@@ -26,6 +27,9 @@ class ControlProtocol : sigc::trackable {
        std::string name() const { return _name; }
 
        void set_send (SendWhat);
+       void set_active (bool yn);
+       bool get_active() const { return active_thread > 0; }
+
 
        bool send() const { return _send != 0; }
        bool send_route_feedback () const { return _send & SendRoute; }
@@ -35,11 +39,43 @@ class ControlProtocol : sigc::trackable {
        virtual void send_global_feedback () {}
 
   protected:
+
        ARDOUR::Session& session;
        SendWhat _send;
        std::string _name;
+       int active_thread;
+       int thread_request_pipe[2];
+       pthread_t _thread;
+
+       static void* _thread_work (void *);
+       void* thread_work ();
+
+       struct ThreadRequest {
+           enum Type {
+                   Start,
+                   Stop,
+                   Quit
+           };
+       };
+
+       int init_thread();
+       int start_thread ();
+       int stop_thread ();
+       void terminate_thread ();
+       int  poke_thread (ThreadRequest::Type);
 };
 
+extern "C" {
+       struct ControlProtocolDescriptor {
+           const char* name;
+           void*       ptr;
+           void*       module;
+           ControlProtocol* (*initialize)(ControlProtocolDescriptor*,Session*);
+           void             (*destroy)(ControlProtocolDescriptor*,ControlProtocol*);
+           
+       };
+}
+
 }
 
 #endif // ardour_control_protocols_h
diff --git a/libs/ardour/ardour/generic_midi_control_protocol.h b/libs/ardour/ardour/generic_midi_control_protocol.h
deleted file mode 100644 (file)
index 75b514f..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef ardour_generic_midi_control_protocol_h
-#define ardour_generic_midi_control_protocol_h
-
-#include <ardour/control_protocol.h>
-
-namespace MIDI {
-       class Port;
-}
-
-namespace ARDOUR {
-
-class GenericMidiControlProtocol : public ControlProtocol {
-  public:
-       GenericMidiControlProtocol (Session&);
-       virtual ~GenericMidiControlProtocol();
-
-       bool active() const;
-
-       void set_port (MIDI::Port*);
-       MIDI::Port* port () const { return _port; }
-
-       void send_route_feedback (std::list<Route*>&);
-       
-  private:
-       void route_feedback (ARDOUR::Route&, bool);
-       MIDI::Port* _port;
-};
-
-}
-
-#endif // ardour_generic_midi_control_protocol_h
index 1f6f464d24516ea73efe37ccbb5805916bbb2765..201cc48adaccd298c5341ad68d7eb96c9c709562 100644 (file)
@@ -79,8 +79,7 @@ class AudioRegion;
 class Region;
 class Playlist;
 class VSTPlugin;
-class ControlProtocol;
-class GenericMidiControlProtocol;
+class ControlProtocolManager;
 
 struct AudioExportSpecification;
 struct RouteGroup;
@@ -246,6 +245,8 @@ class Session : public sigc::trackable, public Stateful
        std::string dead_sound_dir () const;
        std::string automation_dir () const;
 
+       static string suffixed_search_path (std::string suffix);
+       static string control_protocol_path ();
        static string template_path ();
        static string template_dir ();
        static void get_template_list (list<string>&);
@@ -428,7 +429,6 @@ class Session : public sigc::trackable, public Stateful
        void set_do_not_record_plugins (bool yn);
        void set_crossfades_active (bool yn);
        void set_seamless_loop (bool yn);
-       void set_feedback (bool yn);
 
        bool get_auto_play () const { return auto_play; }
        bool get_auto_input () const { return auto_input; }
@@ -445,8 +445,6 @@ class Session : public sigc::trackable, public Stateful
        bool get_midi_control () const;
        bool get_do_not_record_plugins () const { return do_not_record_plugins; }
        bool get_crossfades_active () const { return crossfades_active; }
-       bool get_feedback() const;
-       bool get_tranzport_control() const;
 
        bool get_input_auto_connect () const;
        AutoConnectOption get_output_auto_connect () const { return output_auto_connect; }
@@ -1136,7 +1134,6 @@ class Session : public sigc::trackable, public Stateful
        bool send_mmc;
        bool mmc_control;
        bool midi_control;
-       bool midi_feedback;
 
        RingBuffer<Event*> pending_events;
 
@@ -1363,31 +1360,6 @@ class Session : public sigc::trackable, public Stateful
        void send_time_code_in_another_thread (bool full);
        void send_mmc_in_another_thread (MIDI::MachineControl::Command, jack_nframes_t frame = 0);
 
-       /* Feedback */
-
-       typedef sigc::slot<int> FeedbackFunctionPtr;
-       static void* _feedback_thread_work (void *);
-       void* feedback_thread_work ();
-       int feedback_generic_midi_function ();
-       std::list<FeedbackFunctionPtr> feedback_functions;
-       int active_feedback;
-       int feedback_request_pipe[2];
-       pthread_t feedback_thread;
-
-       struct FeedbackRequest {
-           enum Type {
-                   Start,
-                   Stop,
-                   Quit
-           };
-       };
-
-       int init_feedback();
-       int start_feedback ();
-       int stop_feedback ();
-       void terminate_feedback ();
-       int  poke_feedback (FeedbackRequest::Type);
-
        jack_nframes_t adjust_apparent_position (jack_nframes_t frames);
        
        void reset_record_status ();
@@ -1770,12 +1742,6 @@ class Session : public sigc::trackable, public Stateful
 
        LayerModel layer_model;
        CrossfadeModel xfade_model;
-
-       /* control protocols */
-
-       vector<ControlProtocol*> control_protocols;
-       GenericMidiControlProtocol* generic_midi_control_protocol;
-       void initialize_control ();
 };
 
 }; /* namespace ARDOUR */
diff --git a/libs/ardour/ardour/tranzport_control_protocol.h b/libs/ardour/ardour/tranzport_control_protocol.h
deleted file mode 100644 (file)
index 448d803..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-#ifndef ardour_tranzport_control_protocol_h
-#define ardour_tranzport_control_protocol_h
-
-#include <pthread.h>
-#include <usb.h>
-#include <ardour/control_protocol.h>
-#include <ardour/types.h>
-
-namespace ARDOUR {
-
-class TranzportControlProtocol : public ControlProtocol {
-  public:
-       TranzportControlProtocol (Session&);
-       virtual ~TranzportControlProtocol();
-
-       int init ();
-       bool active() const;
-
-       void send_route_feedback (std::list<Route*>&);
-       void send_global_feedback ();
-
-  private:
-       static const int VENDORID = 0x165b;
-       static const int PRODUCTID = 0x8101;
-       static const int READ_ENDPOINT  = 0x81;
-       static const int WRITE_ENDPOINT = 0x02;
-       const static int STATUS_OFFLINE  = 0xff;
-       const static int STATUS_ONLINE = 0x01;
-
-       enum LightID {
-               LightRecord = 0,
-               LightTrackrec,
-               LightTrackmute,
-               LightTracksolo,
-               LightAnysolo,
-               LightLoop,
-               LightPunch
-       };
-
-       enum ButtonID {
-               ButtonBattery = 0x00004000,
-               ButtonBacklight = 0x00008000,
-               ButtonTrackLeft = 0x04000000,
-               ButtonTrackRight = 0x40000000,
-               ButtonTrackRec = 0x00040000,
-               ButtonTrackMute = 0x00400000,
-               ButtonTrackSolo = 0x00000400,
-               ButtonUndo = 0x80000000,
-               ButtonIn = 0x02000000,
-               ButtonOut = 0x20000000,
-               ButtonPunch = 0x00800000,
-               ButtonLoop = 0x00080000,
-               ButtonPrev = 0x00020000,
-               ButtonAdd = 0x00200000,
-               ButtonNext = 0x00000200,
-               ButtonRewind = 0x01000000,
-               ButtonFastForward = 0x10000000,
-               ButtonStop = 0x00010000,
-               ButtonPlay = 0x00100000,
-               ButtonRecord = 0x00000100,
-               ButtonShift = 0x08000000
-       };
-               
-       pthread_t       thread;
-       uint32_t        buttonmask;
-       uint32_t        timeout;
-       uint8_t        _datawheel;
-       uint8_t        _device_status;
-       usb_dev_handle* udev;
-       Route*          current_route;
-       uint32_t        current_track_id;
-
-       bool     last_negative;
-       uint32_t last_hrs;
-       uint32_t last_mins;
-       uint32_t last_secs;
-       uint32_t last_frames;
-       jack_nframes_t last_where;
-
-       int open ();
-       int read ();
-       int write (uint8_t* cmd);
-       int close ();
-
-       int open_core (struct usb_device*);
-
-       void lcd_clear ();
-       int  lcd_write (uint8_t cell, const char *text);
-
-       int  light_on (LightID);
-       int  light_off (LightID);
-
-       void show_current_track ();
-
-       static void* _thread_work (void* arg);
-       void* thread_work ();
-
-       void button_event_battery_press (bool shifted);
-       void button_event_battery_release (bool shifted);
-       void button_event_backlight_press (bool shifted);
-       void button_event_backlight_release (bool shifted);
-       void button_event_trackleft_press (bool shifted);
-       void button_event_trackleft_release (bool shifted);
-       void button_event_trackright_press (bool shifted);
-       void button_event_trackright_release (bool shifted);
-       void button_event_trackrec_press (bool shifted);
-       void button_event_trackrec_release (bool shifted);
-       void button_event_trackmute_press (bool shifted);
-       void button_event_trackmute_release (bool shifted);
-       void button_event_tracksolo_press (bool shifted);
-       void button_event_tracksolo_release (bool shifted);
-       void button_event_undo_press (bool shifted);
-       void button_event_undo_release (bool shifted);
-       void button_event_in_press (bool shifted);
-       void button_event_in_release (bool shifted);
-       void button_event_out_press (bool shifted);
-       void button_event_out_release (bool shifted);
-       void button_event_punch_press (bool shifted);
-       void button_event_punch_release (bool shifted);
-       void button_event_loop_press (bool shifted);
-       void button_event_loop_release (bool shifted);
-       void button_event_prev_press (bool shifted);
-       void button_event_prev_release (bool shifted);
-       void button_event_add_press (bool shifted);
-       void button_event_add_release (bool shifted);
-       void button_event_next_press (bool shifted);
-       void button_event_next_release (bool shifted);
-       void button_event_rewind_press (bool shifted);
-       void button_event_rewind_release (bool shifted);
-       void button_event_fastforward_press (bool shifted);
-       void button_event_fastforward_release (bool shifted);
-       void button_event_stop_press (bool shifted);
-       void button_event_stop_release (bool shifted);
-       void button_event_play_press (bool shifted);
-       void button_event_play_release (bool shifted);
-       void button_event_record_press (bool shifted);
-       void button_event_record_release (bool shifted);
-};
-
-} // namespace
-
-#endif // ardour_tranzport_control_protocol_h
diff --git a/libs/ardour/generic_midi_control_protocol.cc b/libs/ardour/generic_midi_control_protocol.cc
deleted file mode 100644 (file)
index f9b9750..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <ardour/generic_midi_control_protocol.h>
-#include <ardour/route.h>
-#include <ardour/session.h>
-
-using namespace ARDOUR;
-
-#include "i18n.h"
-
-GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
-       : ControlProtocol  (s, _("GenericMIDI"))
-{
-       _port = 0;
-}
-
-GenericMidiControlProtocol::~GenericMidiControlProtocol ()
-{
-}
-
-void
-GenericMidiControlProtocol::set_port (MIDI::Port* p)
-{
-       _port = p;
-}
-
-void 
-GenericMidiControlProtocol::send_route_feedback (list<Route*>& routes)
-{
-       if (_port != 0) {
-
-               const int32_t bufsize = 16 * 1024;
-               int32_t bsize = bufsize;
-               MIDI::byte* buf = new MIDI::byte[bufsize];
-               MIDI::byte* end = buf;
-               
-               for (list<Route*>::iterator r = routes.begin(); r != routes.end(); ++r) {
-               end = (*r)->write_midi_feedback (end, bsize);
-               }
-               
-               if (end == buf) {
-                       delete [] buf;
-                       return;
-               } 
-               
-               session.deliver_midi (_port, buf, (int32_t) (end - buf));
-               //cerr << "MIDI feedback: wrote " << (int32_t) (end - buf) << " to midi port\n";
-       }
-}
-
-bool
-GenericMidiControlProtocol::active() const
-{
-       return _port && send();
-}
-
index 7210fcf9f5efd03d956a0b52168bfb2188f9f118..18fad73f097d3fcaf4e6dac0d98742be11d52cf8 100644 (file)
@@ -46,6 +46,7 @@
 #include <ardour/source.h>
 #include <ardour/utils.h>
 #include <ardour/session.h>
+#include <ardour/control_protocol_manager.h>
 
 #include <ardour/mix.h>
 
@@ -71,7 +72,6 @@ Change ARDOUR::PositionChanged = ARDOUR::new_change ();
 Change ARDOUR::NameChanged = ARDOUR::new_change ();
 Change ARDOUR::BoundsChanged = Change (0); // see init(), below
 
-
 static int 
 setup_midi ()
 {
@@ -266,6 +266,10 @@ ARDOUR::init (AudioEngine& engine, bool use_vst, bool try_optimization, void (*s
        /* singleton - first object is "it" */
        new PluginManager (engine);
        
+       /* singleton - first object is "it" */
+       new ControlProtocolManager ();
+       ControlProtocolManager::instance().discover_control_protocols (Session::control_protocol_path());
+       
        BoundsChanged = Change (StartChanged|PositionChanged|LengthChanged);
 
        return 0;
index 22686c6cbe844ca841d2cdee8c3e06032c013e85..216517e668333cce21691539bef14c2b61333872 100644 (file)
@@ -361,7 +361,6 @@ Session::~Session ()
        
        terminate_butler_thread ();
        terminate_midi_thread ();
-       terminate_feedback ();
        
        if (click_data && click_data != default_click) {
                delete [] click_data;
index 09e9021461c4f97b71e3cf371aa5439bb5f01b68..600567892ef38dd1c0914e29def80adf70eb506b 100644 (file)
@@ -45,198 +45,5 @@ using namespace std;
 using namespace ARDOUR;
 //using namespace sigc;
 
-int
-Session::init_feedback ()
-{
-       if (pipe (feedback_request_pipe) != 0) {
-               error << string_compose (_("cannot create feedback request pipe (%1)"),
-                                 strerror (errno))
-                     << endmsg;
-               return -1;
-       }
-
-       if (fcntl (feedback_request_pipe[0], F_SETFL, O_NONBLOCK)) {
-               error << string_compose(_("UI: cannot set O_NONBLOCK on "    "signal read pipe (%1)"), strerror (errno)) << endmsg;
-               return -1;
-       }
-
-       if (fcntl (feedback_request_pipe[1], F_SETFL, O_NONBLOCK)) {
-               error << string_compose(_("UI: cannot set O_NONBLOCK on "    "signal write pipe (%1)"), strerror (errno)) << endmsg;
-               return -1;
-       }
-
-       active_feedback = 0;
-
-       if (pthread_create_and_store ("feedback", &feedback_thread, 0, _feedback_thread_work, this)) {
-               error << _("Session: could not create feedback thread") << endmsg;
-               return -1;
-       }
-
-       return 0;
-}      
-
-int
-Session::poke_feedback (FeedbackRequest::Type why)
-{
-       char c = (char) why;
-       return !(write (feedback_request_pipe[1], &c, 1) == 1);
-}
-
-int
-Session::start_feedback ()
-{
-       return poke_feedback (FeedbackRequest::Start);
-}
-
-int
-Session::stop_feedback ()
-{
-       return poke_feedback (FeedbackRequest::Stop);
-}
-
-void
-Session::set_feedback (bool yn)
-{
-       set_dirty();
-
-       if (yn) {
-               /* make sure the feedback thread is alive */
-               start_feedback ();
-       } else {
-               /* maybe put the feedback thread to sleep */
-               stop_feedback ();
-       }
-
-       ControlChanged (Feedback); /* EMIT SIGNAL */
-}
-
-bool
-Session::get_feedback() const
-{
-       return active_feedback > 0;
-}
-
-void
-Session::terminate_feedback ()
-{
-       void* status;
-       poke_feedback (FeedbackRequest::Quit);
-       pthread_join (feedback_thread, &status);
-}
-
-void*
-Session::_feedback_thread_work (void* arg)
-{
-       return static_cast<Session*> (arg)->feedback_thread_work ();
-}
-
-void*
-Session::feedback_thread_work ()
-{
-       PBD::ThreadCreated (pthread_self(), X_("Feedback"));
-       struct pollfd pfd[1];
-       int timeout;
-
-       pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, 0);
-       pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
-
-       if (active_feedback) {
-               timeout = max (5, (int) Config->get_feedback_interval_ms());
-       } else {
-               timeout = -1;
-       }
-
-       while (1) {
-
-               pfd[0].fd = feedback_request_pipe[0];
-               pfd[0].events = POLLIN|POLLHUP|POLLERR;
-
-               if (poll (pfd, 1, timeout) < 0) {
-                       if (errno == EINTR) {
-                               continue;
-                       }
-                       error << string_compose (_("Feedback thread poll failed (%1)"),
-                                         strerror (errno))
-                             << endmsg;
-                       break;
-               }
-
-               if (pfd[0].revents & ~POLLIN) {
-                       error << _("Error on feedback thread request pipe") << endmsg;
-                       break;
-               }
-
-               if (pfd[0].revents & POLLIN) {
-
-                       char req;
-                       
-                       /* empty the pipe of all current requests */
-
-                       while (1) {
-                               size_t nread = read (feedback_request_pipe[0], &req, sizeof (req));
-
-                               if (nread == 1) {
-                                       switch ((FeedbackRequest::Type) req) {
-                                       
-                                       case FeedbackRequest::Start:
-                                               timeout = max (5, (int) Config->get_feedback_interval_ms());
-                                               active_feedback++;
-                                               break;
-                                               
-                                       case FeedbackRequest::Stop:
-                                               timeout = -1;
-                                               if (active_feedback) {
-                                                       active_feedback--;
-                                               } 
-                                               break;
-                                               
-                                       case FeedbackRequest::Quit:
-                                               pthread_exit_pbd (0);
-                                               /*NOTREACHED*/
-                                               break;
-                                               
-                                       default:
-                                               break;
-                                       }
-
-                               } else if (nread == 0) {
-                                       break;
-                               } else if (errno == EAGAIN) {
-                                       break;
-                               } else {
-                                       fatal << _("Error reading from feedback request pipe") << endmsg;
-                                       /*NOTREACHED*/
-                               }
-                       }
-               }
-               
-               if (!active_feedback || transport_stopped()) {
-                       continue;
-               }
-
-               bool send = false;
-
-               for (vector<ControlProtocol*>::iterator i = control_protocols.begin(); i != control_protocols.end(); ++i) {
-                       if ((*i)->send()) {
-                               send = true;
-                               break;
-                       }
-               }
-               
-               if (send) {
-
-                       RouteList routes = get_routes(); /* copies the routes */
-
-                       for (vector<ControlProtocol*>::iterator i = control_protocols.begin(); i != control_protocols.end(); ++i) {
-                               if ((*i)->send_route_feedback ()) {
-                                       (*i)->send_route_feedback (routes);
-                               }
-                               (*i)->send_global_feedback ();
-                       } 
-               }
-       }
-       
-       return 0;
-}
 
        
index af08d3cc3e875ac5ca5257cb120c6ab2e3aaad72..aa079f88278e4b9070ccc77e7116d6b4c94a2a58 100644 (file)
@@ -40,7 +40,6 @@
 #include <ardour/diskstream.h>
 #include <ardour/slave.h>
 #include <ardour/cycles.h>
-#include <ardour/generic_midi_control_protocol.h>
 
 #include "i18n.h"
 
@@ -170,19 +169,12 @@ Session::set_send_mmc (bool yn)
 void
 Session::set_midi_feedback (bool yn)
 {
-       if (generic_midi_control_protocol) {
-               if (yn) {
-                       generic_midi_control_protocol->set_send (ControlProtocol::SendRoute);
-               } else {
-                       generic_midi_control_protocol->set_send (ControlProtocol::SendWhat (0));
-               }
-       }
 }
 
 bool
 Session::get_midi_feedback () const
 {
-       return generic_midi_control_protocol && generic_midi_control_protocol->active();
+       return false;
 }
 
 bool
@@ -328,9 +320,9 @@ Session::set_midi_port (string port_tag)
 
        _midi_port = port;
        
-       if (generic_midi_control_protocol) {
-               generic_midi_control_protocol->set_port (port);
-       }
+       /* XXX need something to forward this to control protocols ? or just
+          use the signal below 
+       */
 
        Config->set_midi_port_name (port_tag);
 
index 5decba1d0928d986226e8d6b4739fdcda71f92fb..a78a2bdfa78337e55eb54764ddf8098884d56037 100644 (file)
@@ -81,6 +81,7 @@
 #include <ardour/location.h>
 #include <ardour/audioregion.h>
 #include <ardour/crossfade.h>
+#include <ardour/control_protocol_manager.h>
 
 #include "i18n.h"
 #include <locale.h>
@@ -165,9 +166,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
        butler_mixdown_buffer = 0;
        butler_gain_buffer = 0;
        auditioner = 0;
-       generic_midi_control_protocol = 0;
        mmc_control = false;
-       midi_feedback = false;
        midi_control = true;
        mmc = 0;
        post_transport_work = PostTransportWork (0);
@@ -302,12 +301,6 @@ Session::second_stage_init (bool new_session)
                return -1;
        }
 
-       initialize_control();
-       
-       if (init_feedback ()) {
-               return -1;
-       }
-
        if (state_tree) {
                if (set_state (*state_tree->root())) {
                        return -1;
@@ -348,7 +341,7 @@ Session::second_stage_init (bool new_session)
        deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
        deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
 
-       // XXX need to poke the feedback thread to send full state
+       ControlProtocolManager::instance().startup (*this);
 
        if (new_session) {
                _end_location_is_free = true;
@@ -2300,7 +2293,7 @@ Session::template_dir ()
 }
 
 string
-Session::template_path ()
+Session::suffixed_search_path (string suffix)
 {
        string path;
 
@@ -2317,7 +2310,8 @@ Session::template_path ()
 
        for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
                path += *i;
-               path += "templates/";
+               path += suffix;
+               path += '/';
                
                if (distance (i, split_path.end()) != 1) {
                        path += ':';
@@ -2327,6 +2321,18 @@ Session::template_path ()
        return path;
 }
 
+string
+Session::template_path ()
+{
+       return suffixed_search_path (X_("templates"));
+}
+
+string
+Session::control_protocol_path ()
+{
+       return suffixed_search_path (X_("surfaces"));
+}
+
 int
 Session::load_connections (const XMLNode& node)
 {
diff --git a/libs/ardour/tranzport_control_protocol.cc b/libs/ardour/tranzport_control_protocol.cc
deleted file mode 100644 (file)
index 9640ea4..0000000
+++ /dev/null
@@ -1,718 +0,0 @@
-#include <iostream>
-
-#include <pbd/pthread_utils.h>
-
-#include <ardour/tranzport_control_protocol.h>
-#include <ardour/route.h>
-#include <ardour/session.h>
-
-using namespace ARDOUR;
-using namespace std;
-
-#include "i18n.h"
-
-TranzportControlProtocol::TranzportControlProtocol (Session& s)
-       : ControlProtocol  (s, _("Tranzport"))
-{
-       timeout = 60000;
-       buttonmask = 0;
-       _datawheel = 0;
-       _device_status = STATUS_OFFLINE;
-       udev = 0;
-       current_route = 0;
-       current_track_id = 0;
-       last_where = max_frames;
-}
-
-TranzportControlProtocol::~TranzportControlProtocol ()
-{
-       if (udev) {
-               pthread_cancel_one (thread);
-               close ();
-       }
-}
-
-int
-TranzportControlProtocol::init ()
-{
-       if (open ()) {
-               return -1;
-       }
-
-       pthread_create_and_store (X_("Tranzport"), &thread, 0, _thread_work, this);
-
-       return 0;
-}
-
-bool
-TranzportControlProtocol::active() const
-{
-       return true;
-}
-               
-void
-TranzportControlProtocol::send_route_feedback (list<Route*>& routes)
-{
-}
-
-void
-TranzportControlProtocol::send_global_feedback ()
-{
-       jack_nframes_t where = session.transport_frame();
-
-       if (where != last_where) {
-
-               char clock_label[16];
-               SMPTE_Time smpte;
-               char* ptr = clock_label;
-
-               session.smpte_time (where, smpte);
-               memset (clock_label, ' ', sizeof (clock_label));
-               
-               if (smpte.negative) {
-                       sprintf (ptr, "-%02ld:", smpte.hours);
-               } else {
-                       sprintf (ptr, " %02ld:", smpte.hours);
-               }
-               ptr += 4;
-
-               sprintf (ptr, "%02ld:", smpte.minutes);
-               ptr += 3;
-
-               sprintf (ptr, "%02ld:", smpte.seconds);
-               ptr += 3;
-
-               sprintf (ptr, "%02ld", smpte.frames);
-               ptr += 2;
-               
-               lcd_write (7, &clock_label[0]);
-               lcd_write (8, &clock_label[4]);
-               lcd_write (9, &clock_label[8]);
-
-               last_where = where;
-       }
-}
-
-void*
-TranzportControlProtocol::_thread_work (void* arg)
-{
-       return static_cast<TranzportControlProtocol*>(arg)->thread_work ();
-}
-
-void*
-TranzportControlProtocol::thread_work ()
-{
-       cerr << "tranzport thread here, sending message to LCD\n";
-
-       while (true) {
-               if (read()) {
-                       return 0;
-               }
-               switch (_device_status) {
-               case STATUS_OFFLINE:
-                       cerr << "offline\n";
-                       break;
-               case STATUS_ONLINE:
-                       cerr << "online\n";
-                       break;
-               default:
-                       cerr << "unknown status\n";
-                       break;
-               }
-
-               if (_device_status == STATUS_ONLINE) {
-                       break;
-               }
-       }
-
-       lcd_write (0, "    ");
-       lcd_write (1, "WELC");
-       lcd_write (2, "OME ");
-       lcd_write (3, "TO  ");
-       lcd_write (4, "    ");
-       lcd_write (5, "    ");
-       lcd_write (6, "    ");
-       lcd_write (7, "ARDO");
-       lcd_write (8, "UR  ");
-       lcd_write (9, "    ");
-
-       while (true) {
-               if (read ()) {
-                       cerr << "Tranzport command received\n";
-                       break;
-               }
-       }
-
-       return 0;
-}
-
-int
-TranzportControlProtocol::open ()
-{
-       struct usb_bus *bus;
-       struct usb_device *dev;
-
-       usb_init();
-       usb_find_busses();
-       usb_find_devices();
-
-       cerr << "checking busses\n";
-       
-       for (bus = usb_busses; bus; bus = bus->next) {
-
-               cerr << "checking devices\n";
-
-               for(dev = bus->devices; dev; dev = dev->next) {
-                       cerr << "Checking " << dev->descriptor.idVendor << '/' << dev->descriptor.idProduct << endl;
-                       if (dev->descriptor.idVendor != VENDORID)
-                               continue;
-                       if (dev->descriptor.idProduct != PRODUCTID)
-                               continue;
-                       cerr << "Open this one" << endl;
-                       return open_core (dev);
-               }
-       }
-
-       error << _("Tranzport: no device detected") << endmsg;
-       return -1;
-}
-
-int
-TranzportControlProtocol::open_core (struct usb_device* dev)
-{
-       if (!(udev = usb_open (dev))) {
-               error << _("Tranzport: cannot open USB transport") << endmsg;
-               return -1;
-       }
-        
-       if (usb_claim_interface (udev, 0) < 0) {
-               error << _("Tranzport: cannot claim USB interface") << endmsg;
-               usb_close (udev);
-               udev = 0;
-               return -1;
-       }
-
-       return 0;
-}
-
-int
-TranzportControlProtocol::close ()
-{
-       int ret = 0;
-
-       if (udev == 0) {
-               return 0;
-       }
-
-       if (usb_release_interface (udev, 0) < 0) {
-               error << _("Tranzport: cannot release interface") << endmsg;
-               ret = -1;
-       }
-
-       if (usb_close (udev)) {
-               error << _("Tranzport: cannot close device") << endmsg;
-               ret = 0;
-       }
-
-       return ret;
-}
-       
-int
-TranzportControlProtocol::write (uint8_t* cmd)
-{
-       int val;
-       val = usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, timeout);
-       if (val < 0)
-               return val;
-       if (val != 8)
-               return -1;
-       return 0;
-
-}      
-
-void
-TranzportControlProtocol::lcd_clear ()
-{
-       lcd_write (0, "    ");
-       lcd_write (1, "    ");
-       lcd_write (2, "    ");
-       lcd_write (3, "    ");
-       lcd_write (4, "    ");
-       lcd_write (5, "    ");
-       lcd_write (6, "    ");
-       lcd_write (7, "    ");
-       lcd_write (8, "    ");
-       lcd_write (9, "    ");
-}
-
-int
-TranzportControlProtocol::lcd_write (uint8_t cell, const char* text)       
-{
-       uint8_t cmd[8];
-       
-       if (cell > 9) {
-               return -1;
-       }
-
-       cmd[0] = 0x00;
-       cmd[1] = 0x01;
-       cmd[2] = cell;
-       cmd[3] = text[0];
-       cmd[4] = text[1];
-       cmd[5] = text[2];
-       cmd[6] = text[3];
-       cmd[7] = 0x00;
-
-       return write (cmd);
-}
-
-int
-TranzportControlProtocol::light_on (LightID light)
-{
-       uint8_t cmd[8];
-
-       cmd[0] = 0x00;
-       cmd[1] = 0x00;
-       cmd[2] = light;
-       cmd[3] = 0x01;
-       cmd[4] = 0x00;
-       cmd[5] = 0x00;
-       cmd[6] = 0x00;
-       cmd[7] = 0x00;
-
-       return write (cmd);
-}
-
-int
-TranzportControlProtocol::light_off (LightID light)
-{
-       uint8_t cmd[8];
-
-       cmd[0] = 0x00;
-       cmd[1] = 0x00;
-       cmd[2] = light;
-       cmd[3] = 0x00;
-       cmd[4] = 0x00;
-       cmd[5] = 0x00;
-       cmd[6] = 0x00;
-       cmd[7] = 0x00;
-
-       return write (cmd);
-}
-
-int
-TranzportControlProtocol::read ()
-{
-       uint8_t buf[8];
-       int val;
-
-       memset(buf, 0, 8);
-       val = usb_interrupt_read(udev, READ_ENDPOINT, (char*) buf, 8, timeout);
-       if (val < 0) {
-               cerr << "Tranzport read error, val = " << val << endl;
-               return val;
-       }
-       if (val != 8) {
-               cerr << "Tranzport short read, val = " << val << endl;
-               return -1;
-       }
-
-       /*printf("read: %02x %02x %02x %02x %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);*/
-
-       uint32_t this_button_mask;
-       uint32_t button_changes;
-
-       _device_status = buf[1];
-       this_button_mask = 0;
-       this_button_mask |= buf[2] << 24;
-       this_button_mask |= buf[3] << 16;
-       this_button_mask |= buf[4] << 8;
-       this_button_mask |= buf[5];
-       _datawheel = buf[6];
-
-       button_changes = (this_button_mask ^ buttonmask);
-       buttonmask = this_button_mask;
-
-       if (button_changes & ButtonBattery) {
-               if (buttonmask & ButtonBattery) {
-                       button_event_battery_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_battery_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonBacklight) {
-               if (buttonmask & ButtonBacklight) {
-                       button_event_backlight_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_backlight_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonTrackLeft) {
-               if (buttonmask & ButtonTrackLeft) {
-                       button_event_trackleft_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_trackleft_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonTrackRight) {
-               if (buttonmask & ButtonTrackRight) {
-                       button_event_trackright_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_trackright_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonTrackRec) {
-               if (buttonmask & ButtonTrackRec) {
-                       button_event_trackrec_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_trackrec_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonTrackMute) {
-               if (buttonmask & ButtonTrackMute) {
-                       button_event_trackmute_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_trackmute_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonTrackSolo) {
-               if (buttonmask & ButtonTrackSolo) {
-                       button_event_tracksolo_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_tracksolo_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonUndo) {
-               if (buttonmask & ButtonUndo) {
-                       button_event_undo_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_undo_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonIn) {
-               if (buttonmask & ButtonIn) {
-                       button_event_in_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_in_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonOut) {
-               if (buttonmask & ButtonOut) {
-                       button_event_out_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_out_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonPunch) {
-               if (buttonmask & ButtonPunch) {
-                       button_event_punch_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_punch_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonLoop) {
-               if (buttonmask & ButtonLoop) {
-                       button_event_loop_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_loop_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonPrev) {
-               if (buttonmask & ButtonPrev) {
-                       button_event_prev_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_prev_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonAdd) {
-               if (buttonmask & ButtonAdd) {
-                       button_event_add_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_add_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonNext) {
-               if (buttonmask & ButtonNext) {
-                       button_event_next_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_next_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonRewind) {
-               if (buttonmask & ButtonRewind) {
-                       button_event_rewind_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_rewind_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonFastForward) {
-               if (buttonmask & ButtonFastForward) {
-                       button_event_fastforward_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_fastforward_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonStop) {
-               if (buttonmask & ButtonStop) {
-                       button_event_stop_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_stop_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonPlay) {
-               if (buttonmask & ButtonPlay) {
-                       button_event_play_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_play_release (buttonmask&ButtonShift);
-               }
-       }
-       if (button_changes & ButtonRecord) {
-               if (buttonmask & ButtonRecord) {
-                       button_event_record_press (buttonmask&ButtonShift);
-               } else {
-                       button_event_record_release (buttonmask&ButtonShift);
-               }
-       }
-               
-       return 0;
-}
-
-void
-TranzportControlProtocol::show_current_track ()
-{
-       current_route = session.route_by_remote_id (current_track_id);
-       
-       if (current_route == 0) {
-               char buf[5];
-               lcd_clear ();
-               lcd_write (0, "NO T");
-               lcd_write (1, "RACK");
-               lcd_write (2, " ID ");
-               snprintf (buf, sizeof (buf), "%4d", current_track_id);
-               lcd_write (3, buf);
-               return;
-       }
-
-       string name = current_route->name();
-
-       lcd_write (0, name.substr (0, 4).c_str());
-       lcd_write (1, name.substr (4, 4).c_str());
-}
-       
-void
-TranzportControlProtocol::button_event_battery_press (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_battery_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_backlight_press (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_backlight_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_trackleft_press (bool shifted)
-{
-       if (current_track_id == 0) {
-               current_track_id = session.nroutes() - 1;
-       } else {
-               current_track_id--;
-       }
-       
-       show_current_track ();
-}
-
-void
-TranzportControlProtocol::button_event_trackleft_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_trackright_press (bool shifted)
-{
-       if (current_track_id == session.nroutes()) {
-               current_track_id = 0;
-       } else {
-               current_track_id++;
-       }
-       
-       show_current_track ();
-}
-
-void
-TranzportControlProtocol::button_event_trackright_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_trackrec_press (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_trackrec_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_trackmute_press (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_trackmute_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_tracksolo_press (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_tracksolo_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_undo_press (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_undo_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_in_press (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_in_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_out_press (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_out_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_punch_press (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_punch_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_loop_press (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_loop_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_prev_press (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_prev_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_add_press (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_add_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_next_press (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_next_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_rewind_press (bool shifted)
-{
-       session.request_transport_speed (-2.0f);
-}
-
-void
-TranzportControlProtocol::button_event_rewind_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_fastforward_press (bool shifted)
-{
-       session.request_transport_speed (2.0f);
-}
-
-void
-TranzportControlProtocol::button_event_fastforward_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_stop_press (bool shifted)
-{
-       session.request_transport_speed (0.0);
-}
-
-void
-TranzportControlProtocol::button_event_stop_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_play_press (bool shifted)
-{
-       session.request_transport_speed (1.0);
-}
-
-void
-TranzportControlProtocol::button_event_play_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_record_press (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_record_release (bool shifted)
-{
-}
index a5b0b4f2ce2d92006b8d1e581c8e459b52425c8a..8e9a36de59861b7338539db9b19b6a0807f0eb72 100644 (file)
@@ -257,3 +257,4 @@ path_expand (string path)
        return path;
 #endif
 }
+
index 88e9aef1952e2600e253bb24502319b3eb14f9f3..323542cdf72f4f2de199535b70b8dd628c2cf512 100644 (file)
@@ -25,7 +25,7 @@
 
 #include <pbd/pthread_utils.h>
 
-using std::string;
+using namespace std;
 
 typedef std::map<string,pthread_t> ThreadMap;
 static ThreadMap all_threads;
@@ -43,6 +43,8 @@ pthread_create_and_store (string name, pthread_t  *thread, pthread_attr_t *attr,
 {
        int ret;
 
+       cerr << "Creating thread " << name << endl;
+
        if ((ret = pthread_create (thread, attr, start_routine, arg)) == 0) {
                std::pair<string,pthread_t> newpair;
                newpair.first = name;
diff --git a/libs/surfaces/generic_midi/SConscript b/libs/surfaces/generic_midi/SConscript
new file mode 100644 (file)
index 0000000..abede3f
--- /dev/null
@@ -0,0 +1,51 @@
+# -*- python -*-
+
+import os
+import glob
+
+Import('env final_prefix install_prefix final_config_prefix libraries i18n')
+
+genericmidi = env.Copy()
+
+#
+# this defines the version number of libardour_genericmidi
+# 
+
+domain = 'ardour_genericmidi'
+
+genericmidi.Append(DOMAIN = domain, MAJOR = 1, MINOR = 0, MICRO = 0)
+genericmidi.Append(CXXFLAGS = "-DPACKAGE=\\\"" + domain + "\\\"")
+genericmidi.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
+genericmidi.Append(PACKAGE = domain)
+genericmidi.Append(POTFILE = domain + '.pot')
+
+genericmidi_files=Split("""
+interface.cc
+generic_midi_control_protocol.cc
+""")
+
+genericmidi.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
+genericmidi.Append(CXXFLAGS="-DDATA_DIR=\\\""+final_prefix+"/share\\\"")
+genericmidi.Append(CXXFLAGS="-DCONFIG_DIR=\\\""+final_config_prefix+"\\\"")
+genericmidi.Append(CXXFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
+
+genericmidi.Merge ([
+            libraries['usb'],
+            libraries['ardour'],
+            libraries['sigc2'],
+            libraries['pbd3'],
+            libraries['midi++2'],
+            libraries['xml']
+            ])
+
+libardour_genericmidi = genericmidi.SharedLibrary('ardour_genericmidi', genericmidi_files)
+
+Default(libardour_genericmidi)
+
+if env['NLS']:
+       i18n (genericmidi, genericmidi_files, env)
+             
+env.Alias('tarball', env.Distribute (env['DISTTREE'],
+                                    [ 'SConscript', 'i18n.h', 'gettext.h' ] +
+                                    genericmidi_files + 
+                                    glob.glob('po/*.po') + glob.glob('*.h')))
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
new file mode 100644 (file)
index 0000000..4d64c6c
--- /dev/null
@@ -0,0 +1,55 @@
+#include <ardour/route.h>
+#include <ardour/session.h>
+
+#include "generic_midi_control_protocol.h"
+
+using namespace ARDOUR;
+
+#include "i18n.h"
+
+GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
+       : ControlProtocol  (s, _("GenericMIDI"))
+{
+       _port = 0;
+}
+
+GenericMidiControlProtocol::~GenericMidiControlProtocol ()
+{
+}
+
+void
+GenericMidiControlProtocol::set_port (MIDI::Port* p)
+{
+       _port = p;
+}
+
+void 
+GenericMidiControlProtocol::send_route_feedback (list<Route*>& routes)
+{
+       if (_port != 0) {
+
+               const int32_t bufsize = 16 * 1024;
+               int32_t bsize = bufsize;
+               MIDI::byte* buf = new MIDI::byte[bufsize];
+               MIDI::byte* end = buf;
+               
+               for (list<Route*>::iterator r = routes.begin(); r != routes.end(); ++r) {
+               end = (*r)->write_midi_feedback (end, bsize);
+               }
+               
+               if (end == buf) {
+                       delete [] buf;
+                       return;
+               } 
+               
+               session.deliver_midi (_port, buf, (int32_t) (end - buf));
+               //cerr << "MIDI feedback: wrote " << (int32_t) (end - buf) << " to midi port\n";
+       }
+}
+
+bool
+GenericMidiControlProtocol::active() const
+{
+       return _port && send();
+}
+
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.h b/libs/surfaces/generic_midi/generic_midi_control_protocol.h
new file mode 100644 (file)
index 0000000..75b514f
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef ardour_generic_midi_control_protocol_h
+#define ardour_generic_midi_control_protocol_h
+
+#include <ardour/control_protocol.h>
+
+namespace MIDI {
+       class Port;
+}
+
+namespace ARDOUR {
+
+class GenericMidiControlProtocol : public ControlProtocol {
+  public:
+       GenericMidiControlProtocol (Session&);
+       virtual ~GenericMidiControlProtocol();
+
+       bool active() const;
+
+       void set_port (MIDI::Port*);
+       MIDI::Port* port () const { return _port; }
+
+       void send_route_feedback (std::list<Route*>&);
+       
+  private:
+       void route_feedback (ARDOUR::Route&, bool);
+       MIDI::Port* _port;
+};
+
+}
+
+#endif // ardour_generic_midi_control_protocol_h
diff --git a/libs/surfaces/generic_midi/interface.cc b/libs/surfaces/generic_midi/interface.cc
new file mode 100644 (file)
index 0000000..8283b92
--- /dev/null
@@ -0,0 +1,34 @@
+#include <ardour/control_protocol.h>
+
+#include "generic_midi_control_protocol.h"
+
+using namespace ARDOUR;
+
+ControlProtocol*
+new_generic_midi_protocol (ControlProtocolDescriptor* descriptor, Session* s)
+{
+       return new GenericMidiControlProtocol (*s);
+}
+
+void
+delete_generic_midi_protocol (ControlProtocolDescriptor* descriptor, ControlProtocol* cp)
+{
+       delete cp;
+}
+
+static ControlProtocolDescriptor generic_midi_descriptor = {
+       name : "Generic MIDI",
+       ptr : 0,
+       module : 0,
+       initialize : new_generic_midi_protocol,
+       destroy : delete_generic_midi_protocol
+};
+       
+
+extern "C" {
+ControlProtocolDescriptor* 
+protocol_descriptor () {
+       return &generic_midi_descriptor;
+}
+}
+
diff --git a/libs/surfaces/tranzport/SConscript b/libs/surfaces/tranzport/SConscript
new file mode 100644 (file)
index 0000000..e43f0bc
--- /dev/null
@@ -0,0 +1,52 @@
+# -*- python -*-
+
+import os
+import glob
+
+Import('env final_prefix install_prefix final_config_prefix libraries i18n')
+
+tranzport = env.Copy()
+
+#
+# this defines the version number of libardour_tranzport
+# 
+
+domain = 'ardour_tranzport'
+
+tranzport.Append(DOMAIN = domain, MAJOR = 1, MINOR = 0, MICRO = 0)
+tranzport.Append(CXXFLAGS = "-DPACKAGE=\\\"" + domain + "\\\"")
+tranzport.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
+tranzport.Append(PACKAGE = domain)
+tranzport.Append(POTFILE = domain + '.pot')
+
+tranzport_files=Split("""
+interface.cc
+tranzport_control_protocol.cc
+""")
+
+tranzport.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
+tranzport.Append(CXXFLAGS="-DDATA_DIR=\\\""+final_prefix+"/share\\\"")
+tranzport.Append(CXXFLAGS="-DCONFIG_DIR=\\\""+final_config_prefix+"\\\"")
+tranzport.Append(CXXFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
+
+tranzport.Append(CPPPATH=libraries['ardour'].get ('CPPPATH', []))
+tranzport.Append(CPPPATH=libraries['sigc2'].get ('CPPPATH', []))
+tranzport.Append(CPPPATH=libraries['pbd3'].get ('CPPPATH', []))
+tranzport.Append(CPPPATH=libraries['midi++2'].get ('CPPPATH', []))
+
+tranzport.Merge ([
+       libraries['xml'],
+       libraries['usb']
+       ])
+
+libardour_tranzport = tranzport.SharedLibrary('ardour_tranzport', tranzport_files)
+
+Default(libardour_tranzport)
+
+if env['NLS']:
+       i18n (tranzport, tranzport_files, env)
+             
+env.Alias('tarball', env.Distribute (env['DISTTREE'],
+                                    [ 'SConscript', 'i18n.h', 'gettext.h' ] +
+                                    tranzport_files + 
+                                    glob.glob('po/*.po') + glob.glob('*.h')))
diff --git a/libs/surfaces/tranzport/interface.cc b/libs/surfaces/tranzport/interface.cc
new file mode 100644 (file)
index 0000000..a731be2
--- /dev/null
@@ -0,0 +1,34 @@
+#include <ardour/control_protocol.h>
+
+#include "tranzport_control_protocol.h"
+
+using namespace ARDOUR;
+
+ControlProtocol*
+new_tranzport_protocol (ControlProtocolDescriptor* descriptor, Session* s)
+{
+       return new TranzportControlProtocol (*s);
+}
+
+void
+delete_tranzport_protocol (ControlProtocolDescriptor* descriptor, ControlProtocol* cp)
+{
+       delete cp;
+}
+
+static ControlProtocolDescriptor tranzport_descriptor = {
+       name : "Tranzport",
+       ptr : 0,
+       module : 0,
+       initialize : new_tranzport_protocol,
+       destroy : delete_tranzport_protocol
+};
+       
+
+extern "C" {
+ControlProtocolDescriptor* 
+protocol_descriptor () {
+       return &tranzport_descriptor;
+}
+}
+
diff --git a/libs/surfaces/tranzport/tranzport_control_protocol.cc b/libs/surfaces/tranzport/tranzport_control_protocol.cc
new file mode 100644 (file)
index 0000000..518a438
--- /dev/null
@@ -0,0 +1,789 @@
+#include <iostream>
+#include <sys/time.h>
+
+#include <pbd/pthread_utils.h>
+
+#include <ardour/route.h>
+#include <ardour/session.h>
+
+#include "tranzport_control_protocol.h"
+
+using namespace ARDOUR;
+using namespace std;
+
+#include "i18n.h"
+
+TranzportControlProtocol::TranzportControlProtocol (Session& s)
+       : ControlProtocol  (s, _("Tranzport"))
+{
+       timeout = 60000;
+       buttonmask = 0;
+       _datawheel = 0;
+       _device_status = STATUS_OFFLINE;
+       udev = 0;
+       current_route = 0;
+       current_track_id = 0;
+       last_where = max_frames;
+       memset (next_screen, ' ', sizeof (next_screen));
+       memset (current_screen, ' ', sizeof (current_screen));
+}
+
+TranzportControlProtocol::~TranzportControlProtocol ()
+{
+       if (udev) {
+               lcd_clear ();
+               pthread_cancel_one (thread);
+               close ();
+       }
+}
+
+int
+TranzportControlProtocol::init ()
+{
+       if (open ()) {
+               return -1;
+       }
+
+       /* outbound thread */
+
+       init_thread ();
+
+       /* inbound thread */
+       
+       pthread_create_and_store (X_("tranzport monitor"), &thread, 0, _thread_work, this);
+
+       return 0;
+}
+
+bool
+TranzportControlProtocol::active() const
+{
+       return true;
+}
+               
+void
+TranzportControlProtocol::send_route_feedback (list<Route*>& routes)
+{
+}
+
+void
+TranzportControlProtocol::send_global_feedback ()
+{
+       show_transport_time ();
+
+       flush_lcd ();
+}
+
+void
+TranzportControlProtocol::show_transport_time ()
+{
+       jack_nframes_t where = session.transport_frame();
+       
+       if (where != last_where) {
+
+               uint8_t label[12];
+               SMPTE_Time smpte;
+               char* ptr = (char *) label;
+
+               session.smpte_time (where, smpte);
+               memset (label, ' ', sizeof (label));
+               
+               if (smpte.negative) {
+                       sprintf (ptr, "-%02ld:", smpte.hours);
+               } else {
+                       sprintf (ptr, " %02ld:", smpte.hours);
+               }
+               ptr += 4;
+
+               sprintf (ptr, "%02ld:", smpte.minutes);
+               ptr += 3;
+
+               sprintf (ptr, "%02ld:", smpte.seconds);
+               ptr += 3;
+
+               sprintf (ptr, "%02ld", smpte.frames);
+               ptr += 2;
+               
+               write_clock (label);
+
+               last_where = where;
+       }
+}
+
+void
+TranzportControlProtocol::write_clock (const uint8_t* label)
+{
+       memcpy (&next_screen[1][8], &label[0]);
+       memcpy (&next_screen[1][12], &label[4]);
+       memcpy (&next_screen[1][16], &label[8]);
+}
+
+void
+TranzportControlProtocol::flush_lcd ()
+{
+       if (memcmp (&next_screen[0][0], &current_screen[0][0], 4)) {
+               lcd_write (0, &next_screen[0][0]);
+       }
+       if (memcmp (&next_screen[0][4], &current_screen[0][4], 4)) {
+               lcd_write (1, &next_screen[0][0]);
+       }
+       if (memcmp (&next_screen[0][8], &current_screen[0][8], 4)) {
+               lcd_write (2, &next_screen[0][0]);
+       }
+       if (memcmp (&next_screen[0][12], &current_screen[0][12], 4)) {
+               lcd_write (3, &next_screen[0][0]);
+       }
+       if (memcmp (&next_screen[0][16], &current_screen[0][16], 4)) {
+               lcd_write (4, &next_screen[0][0]);
+       }
+       if (memcmp (&next_screen[1][0], &current_screen[1][0], 4)) {
+               lcd_write (5, &next_screen[0][0]);
+       }
+       if (memcmp (&next_screen[1][4], &current_screen[1][4], 4)) {
+               lcd_write (6, &next_screen[0][0]);
+       }
+       if (memcmp (&next_screen[1][8], &current_screen[1][8], 4)) {
+               lcd_write (7, &next_screen[0][0]);
+       }
+       if (memcmp (&next_screen[1][12], &current_screen[1][12], 4)) {
+               lcd_write (8, &next_screen[0][0]);
+       }
+       if (memcmp (&next_screen[1][16], &current_screen[1][16], 4)) {
+               lcd_write (9, &next_screen[0][0]);
+       }
+
+       memcpy (current_screen, next_screen, sizeof (current_screen));
+}
+
+void*
+TranzportControlProtocol::_thread_work (void* arg)
+{
+       return static_cast<TranzportControlProtocol*>(arg)->thread_work ();
+}
+
+void*
+TranzportControlProtocol::thread_work ()
+{
+       PBD::ThreadCreated (pthread_self(), X_("tranzport monitor"));
+
+       while (true) {
+               if (read()) {
+                       return 0;
+               }
+               switch (_device_status) {
+               case STATUS_OFFLINE:
+                       cerr << "offline\n";
+                       break;
+               case STATUS_ONLINE:
+                       cerr << "online\n";
+                       break;
+               default:
+                       cerr << "unknown status\n";
+                       break;
+               }
+
+               if (_device_status == STATUS_ONLINE) {
+                       break;
+               }
+       }
+
+       lcd_write (0, "    ");
+       lcd_write (1, "WELC");
+       lcd_write (2, "OME ");
+       lcd_write (3, "TO  ");
+       lcd_write (4, "    ");
+       lcd_write (5, "    ");
+       lcd_write (6, "    ");
+       lcd_write (7, "ARDO");
+       lcd_write (8, "UR  ");
+       lcd_write (9, "    ");
+
+       while (true) {
+               if (read ()) {
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+int
+TranzportControlProtocol::open ()
+{
+       struct usb_bus *bus;
+       struct usb_device *dev;
+
+       usb_init();
+       usb_find_busses();
+       usb_find_devices();
+
+       for (bus = usb_busses; bus; bus = bus->next) {
+
+               for(dev = bus->devices; dev; dev = dev->next) {
+                       if (dev->descriptor.idVendor != VENDORID)
+                               continue;
+                       if (dev->descriptor.idProduct != PRODUCTID)
+                               continue;
+                       return open_core (dev);
+               }
+       }
+
+       error << _("Tranzport: no device detected") << endmsg;
+       return -1;
+}
+
+int
+TranzportControlProtocol::open_core (struct usb_device* dev)
+{
+       if (!(udev = usb_open (dev))) {
+               error << _("Tranzport: cannot open USB transport") << endmsg;
+               return -1;
+       }
+        
+       if (usb_claim_interface (udev, 0) < 0) {
+               error << _("Tranzport: cannot claim USB interface") << endmsg;
+               usb_close (udev);
+               udev = 0;
+               return -1;
+       }
+
+       return 0;
+}
+
+int
+TranzportControlProtocol::close ()
+{
+       int ret = 0;
+
+       if (udev == 0) {
+               return 0;
+       }
+
+       if (usb_release_interface (udev, 0) < 0) {
+               error << _("Tranzport: cannot release interface") << endmsg;
+               ret = -1;
+       }
+
+       if (usb_close (udev)) {
+               error << _("Tranzport: cannot close device") << endmsg;
+               ret = 0;
+       }
+
+       return ret;
+}
+       
+int
+TranzportControlProtocol::write (uint8_t* cmd, uint32_t timeout_override)
+{
+       int val;
+       struct timeval tv1, tv2, tv_diff;
+
+       gettimeofday (&tv1, 0);
+       val = usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, timeout_override ? timeout_override : timeout);
+       gettimeofday (&tv2, 0);
+       if (val < 0)
+               return val;
+       if (val != 8)
+               return -1;
+       timersub (&tv2, &tv1, &tv_diff);
+       cerr << "time to write command = " << tv_diff.tv_sec << '.' << tv_diff.tv_usec << endl;
+       return 0;
+
+}      
+
+void
+TranzportControlProtocol::lcd_clear ()
+{
+       lcd_write (0, "    ");
+       lcd_write (1, "    ");
+       lcd_write (2, "    ");
+       lcd_write (3, "    ");
+       lcd_write (4, "    ");
+       lcd_write (5, "    ");
+       lcd_write (6, "    ");
+       lcd_write (7, "    ");
+       lcd_write (8, "    ");
+       lcd_write (9, "    ");
+}
+
+int
+TranzportControlProtocol::lcd_write (uint8_t cell, const char* text)       
+{
+       uint8_t cmd[8];
+       
+       if (cell > 9) {
+               return -1;
+       }
+
+       cmd[0] = 0x00;
+       cmd[1] = 0x01;
+       cmd[2] = cell;
+       cmd[3] = text[0];
+       cmd[4] = text[1];
+       cmd[5] = text[2];
+       cmd[6] = text[3];
+       cmd[7] = 0x00;
+
+       int index = cell%4;
+       cell /= 4;
+
+       current_screen[cell][index] = text[0];
+       current_screen[cell][index+1] = text[1];
+       current_screen[cell][index+2] = text[2];
+       current_screen[cell][index+3] = text[3];
+
+       return write (cmd, 500);
+}
+
+int
+TranzportControlProtocol::light_on (LightID light)
+{
+       uint8_t cmd[8];
+
+       cmd[0] = 0x00;
+       cmd[1] = 0x00;
+       cmd[2] = light;
+       cmd[3] = 0x01;
+       cmd[4] = 0x00;
+       cmd[5] = 0x00;
+       cmd[6] = 0x00;
+       cmd[7] = 0x00;
+
+       return write (cmd, 500);
+}
+
+int
+TranzportControlProtocol::light_off (LightID light)
+{
+       uint8_t cmd[8];
+
+       cmd[0] = 0x00;
+       cmd[1] = 0x00;
+       cmd[2] = light;
+       cmd[3] = 0x00;
+       cmd[4] = 0x00;
+       cmd[5] = 0x00;
+       cmd[6] = 0x00;
+       cmd[7] = 0x00;
+
+       return write (cmd, 500);
+}
+
+int
+TranzportControlProtocol::read (uint32_t timeout_override)
+{
+       uint8_t buf[8];
+       int val;
+
+       memset(buf, 0, 8);
+  again:
+       val = usb_interrupt_read(udev, READ_ENDPOINT, (char*) buf, 8, timeout_override ? timeout_override : timeout);
+       if (val < 0) {
+               return val;
+       }
+       if (val != 8) {
+               if (val == 0) {
+                       goto again;
+               }
+               return -1;
+       }
+
+       /* printf("read: %02x %02x %02x %02x %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);*/
+
+       uint32_t this_button_mask;
+       uint32_t button_changes;
+
+       _device_status = buf[1];
+       this_button_mask = 0;
+       this_button_mask |= buf[2] << 24;
+       this_button_mask |= buf[3] << 16;
+       this_button_mask |= buf[4] << 8;
+       this_button_mask |= buf[5];
+       _datawheel = buf[6];
+
+       button_changes = (this_button_mask ^ buttonmask);
+       buttonmask = this_button_mask;
+
+       if (button_changes & ButtonBattery) {
+               if (buttonmask & ButtonBattery) {
+                       button_event_battery_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_battery_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonBacklight) {
+               if (buttonmask & ButtonBacklight) {
+                       button_event_backlight_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_backlight_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonTrackLeft) {
+               if (buttonmask & ButtonTrackLeft) {
+                       button_event_trackleft_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_trackleft_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonTrackRight) {
+               if (buttonmask & ButtonTrackRight) {
+                       button_event_trackright_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_trackright_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonTrackRec) {
+               if (buttonmask & ButtonTrackRec) {
+                       button_event_trackrec_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_trackrec_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonTrackMute) {
+               if (buttonmask & ButtonTrackMute) {
+                       button_event_trackmute_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_trackmute_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonTrackSolo) {
+               if (buttonmask & ButtonTrackSolo) {
+                       button_event_tracksolo_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_tracksolo_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonUndo) {
+               if (buttonmask & ButtonUndo) {
+                       button_event_undo_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_undo_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonIn) {
+               if (buttonmask & ButtonIn) {
+                       button_event_in_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_in_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonOut) {
+               if (buttonmask & ButtonOut) {
+                       button_event_out_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_out_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonPunch) {
+               if (buttonmask & ButtonPunch) {
+                       button_event_punch_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_punch_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonLoop) {
+               if (buttonmask & ButtonLoop) {
+                       button_event_loop_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_loop_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonPrev) {
+               if (buttonmask & ButtonPrev) {
+                       button_event_prev_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_prev_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonAdd) {
+               if (buttonmask & ButtonAdd) {
+                       button_event_add_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_add_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonNext) {
+               if (buttonmask & ButtonNext) {
+                       button_event_next_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_next_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonRewind) {
+               if (buttonmask & ButtonRewind) {
+                       button_event_rewind_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_rewind_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonFastForward) {
+               if (buttonmask & ButtonFastForward) {
+                       button_event_fastforward_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_fastforward_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonStop) {
+               if (buttonmask & ButtonStop) {
+                       button_event_stop_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_stop_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonPlay) {
+               if (buttonmask & ButtonPlay) {
+                       button_event_play_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_play_release (buttonmask&ButtonShift);
+               }
+       }
+       if (button_changes & ButtonRecord) {
+               if (buttonmask & ButtonRecord) {
+                       button_event_record_press (buttonmask&ButtonShift);
+               } else {
+                       button_event_record_release (buttonmask&ButtonShift);
+               }
+       }
+               
+       return 0;
+}
+
+void
+TranzportControlProtocol::show_current_track ()
+{
+       current_route = session.route_by_remote_id (current_track_id);
+       
+       if (current_route == 0) {
+               char buf[5];
+               lcd_clear ();
+               lcd_write (0, "NO T");
+               lcd_write (1, "RACK");
+               lcd_write (2, " ID ");
+               snprintf (buf, sizeof (buf), "%4d", current_track_id);
+               lcd_write (3, buf);
+               return;
+       }
+
+       string name = current_route->name();
+
+       lcd_write (0, name.substr (0, 4).c_str());
+       lcd_write (1, name.substr (4, 4).c_str());
+}
+       
+void
+TranzportControlProtocol::button_event_battery_press (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_battery_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_backlight_press (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_backlight_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_trackleft_press (bool shifted)
+{
+       if (current_track_id == 0) {
+               current_track_id = session.nroutes() - 1;
+       } else {
+               current_track_id--;
+       }
+       
+       show_current_track ();
+}
+
+void
+TranzportControlProtocol::button_event_trackleft_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_trackright_press (bool shifted)
+{
+       if (current_track_id == session.nroutes()) {
+               current_track_id = 0;
+       } else {
+               current_track_id++;
+       }
+       
+       show_current_track ();
+}
+
+void
+TranzportControlProtocol::button_event_trackright_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_trackrec_press (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_trackrec_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_trackmute_press (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_trackmute_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_tracksolo_press (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_tracksolo_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_undo_press (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_undo_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_in_press (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_in_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_out_press (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_out_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_punch_press (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_punch_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_loop_press (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_loop_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_prev_press (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_prev_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_add_press (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_add_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_next_press (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_next_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_rewind_press (bool shifted)
+{
+       session.request_transport_speed (-2.0f);
+}
+
+void
+TranzportControlProtocol::button_event_rewind_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_fastforward_press (bool shifted)
+{
+       session.request_transport_speed (2.0f);
+}
+
+void
+TranzportControlProtocol::button_event_fastforward_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_stop_press (bool shifted)
+{
+       session.request_transport_speed (0.0);
+}
+
+void
+TranzportControlProtocol::button_event_stop_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_play_press (bool shifted)
+{
+       session.request_transport_speed (1.0);
+}
+
+void
+TranzportControlProtocol::button_event_play_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_record_press (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_record_release (bool shifted)
+{
+}
diff --git a/libs/surfaces/tranzport/tranzport_control_protocol.h b/libs/surfaces/tranzport/tranzport_control_protocol.h
new file mode 100644 (file)
index 0000000..5880f38
--- /dev/null
@@ -0,0 +1,147 @@
+#ifndef ardour_tranzport_control_protocol_h
+#define ardour_tranzport_control_protocol_h
+
+#include <pthread.h>
+#include <usb.h>
+#include <ardour/control_protocol.h>
+#include <ardour/types.h>
+
+namespace ARDOUR {
+
+class TranzportControlProtocol : public ControlProtocol {
+  public:
+       TranzportControlProtocol (Session&);
+       virtual ~TranzportControlProtocol();
+
+       int init ();
+       bool active() const;
+
+       void send_route_feedback (std::list<Route*>&);
+       void send_global_feedback ();
+
+  private:
+       static const int VENDORID = 0x165b;
+       static const int PRODUCTID = 0x8101;
+       static const int READ_ENDPOINT  = 0x81;
+       static const int WRITE_ENDPOINT = 0x02;
+       const static int STATUS_OFFLINE  = 0xff;
+       const static int STATUS_ONLINE = 0x01;
+
+       enum LightID {
+               LightRecord = 0,
+               LightTrackrec,
+               LightTrackmute,
+               LightTracksolo,
+               LightAnysolo,
+               LightLoop,
+               LightPunch
+       };
+
+       enum ButtonID {
+               ButtonBattery = 0x00004000,
+               ButtonBacklight = 0x00008000,
+               ButtonTrackLeft = 0x04000000,
+               ButtonTrackRight = 0x40000000,
+               ButtonTrackRec = 0x00040000,
+               ButtonTrackMute = 0x00400000,
+               ButtonTrackSolo = 0x00000400,
+               ButtonUndo = 0x80000000,
+               ButtonIn = 0x02000000,
+               ButtonOut = 0x20000000,
+               ButtonPunch = 0x00800000,
+               ButtonLoop = 0x00080000,
+               ButtonPrev = 0x00020000,
+               ButtonAdd = 0x00200000,
+               ButtonNext = 0x00000200,
+               ButtonRewind = 0x01000000,
+               ButtonFastForward = 0x10000000,
+               ButtonStop = 0x00010000,
+               ButtonPlay = 0x00100000,
+               ButtonRecord = 0x00000100,
+               ButtonShift = 0x08000000
+       };
+               
+       pthread_t       thread;
+       uint32_t        buttonmask;
+       uint32_t        timeout;
+       uint8_t        _datawheel;
+       uint8_t        _device_status;
+       usb_dev_handle* udev;
+       Route*          current_route;
+       uint32_t        current_track_id;
+       uint8_t         lcd_screen[2][20];
+
+       bool     last_negative;
+       uint32_t last_hrs;
+       uint32_t last_mins;
+       uint32_t last_secs;
+       uint32_t last_frames;
+       jack_nframes_t last_where;
+
+       int open ();
+       int read (uint32_t timeout_override = 0);
+       int write (uint8_t* cmd, uint32_t timeout_override = 0);
+       int close ();
+
+       int open_core (struct usb_device*);
+
+       void lcd_clear ();
+       int  lcd_write (uint8_t cell, const char *text);
+
+       int  light_on (LightID);
+       int  light_off (LightID);
+
+       void flush_lcd ();
+       void write_clock (const uint8_t* label);
+
+       void show_current_track ();
+       void show_transport_time ();
+
+       static void* _thread_work (void* arg);
+       void* thread_work ();
+
+       void button_event_battery_press (bool shifted);
+       void button_event_battery_release (bool shifted);
+       void button_event_backlight_press (bool shifted);
+       void button_event_backlight_release (bool shifted);
+       void button_event_trackleft_press (bool shifted);
+       void button_event_trackleft_release (bool shifted);
+       void button_event_trackright_press (bool shifted);
+       void button_event_trackright_release (bool shifted);
+       void button_event_trackrec_press (bool shifted);
+       void button_event_trackrec_release (bool shifted);
+       void button_event_trackmute_press (bool shifted);
+       void button_event_trackmute_release (bool shifted);
+       void button_event_tracksolo_press (bool shifted);
+       void button_event_tracksolo_release (bool shifted);
+       void button_event_undo_press (bool shifted);
+       void button_event_undo_release (bool shifted);
+       void button_event_in_press (bool shifted);
+       void button_event_in_release (bool shifted);
+       void button_event_out_press (bool shifted);
+       void button_event_out_release (bool shifted);
+       void button_event_punch_press (bool shifted);
+       void button_event_punch_release (bool shifted);
+       void button_event_loop_press (bool shifted);
+       void button_event_loop_release (bool shifted);
+       void button_event_prev_press (bool shifted);
+       void button_event_prev_release (bool shifted);
+       void button_event_add_press (bool shifted);
+       void button_event_add_release (bool shifted);
+       void button_event_next_press (bool shifted);
+       void button_event_next_release (bool shifted);
+       void button_event_rewind_press (bool shifted);
+       void button_event_rewind_release (bool shifted);
+       void button_event_fastforward_press (bool shifted);
+       void button_event_fastforward_release (bool shifted);
+       void button_event_stop_press (bool shifted);
+       void button_event_stop_release (bool shifted);
+       void button_event_play_press (bool shifted);
+       void button_event_play_release (bool shifted);
+       void button_event_record_press (bool shifted);
+       void button_event_record_release (bool shifted);
+};
+
+} // namespace
+
+#endif // ardour_tranzport_control_protocol_h