Add support for PreSonus Faderport2 (2018 model)
authorBen Loftis <ben@harrisonconsoles.com>
Tue, 31 Jul 2018 12:46:20 +0000 (14:46 +0200)
committerRobin Gareus <robin@gareus.org>
Tue, 31 Jul 2018 12:54:20 +0000 (14:54 +0200)
This is a cleaned-up, foward-ported version of Ben's
Mixbus patch (d6694c5b31).

14 files changed:
libs/ardour/globals.cc
libs/ardour/port_manager.cc
libs/surfaces/faderport8/actions.cc
libs/surfaces/faderport8/callbacks.cc
libs/surfaces/faderport8/faderport2_interface.cc [new file with mode: 0644]
libs/surfaces/faderport8/faderport8.cc
libs/surfaces/faderport8/faderport8.h
libs/surfaces/faderport8/fp8_base.h
libs/surfaces/faderport8/fp8_controls.cc
libs/surfaces/faderport8/fp8_controls.h
libs/surfaces/faderport8/fp8_strip.cc
libs/surfaces/faderport8/fp8_strip.h
libs/surfaces/faderport8/gui.cc
libs/surfaces/faderport8/wscript

index c205d6ec5817c422c72cf9a13b7ead97c37c1ff7..ef3e95ea294505ba751091bd2b1dc051b9053bc4 100644 (file)
@@ -578,6 +578,8 @@ ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir
        reserved_io_names[_("Mackie")] = false;
        reserved_io_names[_("FaderPort Recv")] = false;
        reserved_io_names[_("FaderPort Send")] = false;
+       reserved_io_names[_("FaderPort2 Recv")] = false;
+       reserved_io_names[_("FaderPort2 Send")] = false;
        reserved_io_names[_("FaderPort8 Recv")] = false;
        reserved_io_names[_("FaderPort8 Send")] = false;
        reserved_io_names[_("FaderPort16 Recv")] = false;
index 6e879f2c589e0b89b65a088728f561963645084e..1cac85332b898ed184ec3b45c1a89250b2060c02 100644 (file)
@@ -950,6 +950,7 @@ PortManager::port_is_control_only (std::string const& name)
                        X_(".*FaderPort .*"),
                        X_(".*FaderPort8 .*"),
                        X_(".*FaderPort16 .*"),
+                       X_(".*FaderPort2 .*"),
                        X_(".*US-2400 .*"),
                        X_(".*Mackie .*"),
                };
index b09fa32355974d6d1cfff939e8da5e2131e537dc..62282ec531f669c0469d69cdc15957a5d1739a1f 100644 (file)
@@ -23,6 +23,7 @@
 #include "ardour/plugin_insert.h"
 #include "ardour/session.h"
 #include "ardour/session_configuration.h"
+#include "ardour/track.h"
 #include "ardour/types.h"
 
 #include "gtkmm2ext/actions.h"
@@ -39,6 +40,9 @@ using namespace ArdourSurface::FP_NAMESPACE::FP8Types;
 #define BindMethod(ID, CB) \
        _ctrls.button (FP8Controls::ID).released.connect_same_thread (button_connections, boost::bind (&FaderPort8:: CB, this));
 
+#define BindMethod2(ID, ACT, CB) \
+       _ctrls.button (FP8Controls::ID). ACT .connect_same_thread (button_connections, boost::bind (&FaderPort8:: CB, this));
+
 #define BindFunction(ID, ACT, CB, ...) \
        _ctrls.button (FP8Controls::ID). ACT .connect_same_thread (button_connections, boost::bind (&FaderPort8:: CB, this, __VA_ARGS__));
 
@@ -57,11 +61,11 @@ _ctrls.button (ID).released.connect_same_thread (button_connections, boost::bind
 void
 FaderPort8::setup_actions ()
 {
-       BindMethod (BtnPlay, button_play);
-       BindMethod (BtnStop, button_stop);
-       BindMethod (BtnLoop, button_loop);
-       BindMethod (BtnRecord, button_record);
-       BindMethod (BtnClick, button_metronom);
+       BindMethod2 (BtnPlay, pressed, button_play);
+       BindMethod2 (BtnStop, pressed, button_stop);
+       BindMethod2 (BtnLoop, pressed, button_loop);
+       BindMethod2 (BtnRecord, pressed, button_record);
+       BindMethod2 (BtnClick, pressed, button_metronom);
        BindAction (BtnRedo, "Editor", "redo");
 
        BindAction (BtnSave, "Common", "Save");
@@ -93,7 +97,11 @@ FaderPort8::setup_actions ()
        BindFunction (BtnALatch, released, button_automation, ARDOUR::Latch);
 
        _ctrls.button (FP8Controls::BtnEncoder).pressed.connect_same_thread (button_connections, boost::bind (&FaderPort8::button_encoder, this));
+#ifdef FADERPORT2
+       _ctrls.button (FP8Controls::BtnParam).pressed.connect_same_thread (button_connections, boost::bind (&FaderPort8::button_encoder, this));
+#else
        _ctrls.button (FP8Controls::BtnParam).pressed.connect_same_thread (button_connections, boost::bind (&FaderPort8::button_parameter, this));
+#endif
 
 
        BindMethod (BtnBypass, button_bypass);
@@ -105,6 +113,9 @@ FaderPort8::setup_actions ()
        BindMethod (BtnLink, button_link);
        BindMethod (BtnLock, button_lock);
 
+       BindMethod (BtnChanLock, button_chanlock);  //FP2 only
+       BindMethod (BtnFlip, button_flip);   //FP2 only
+
        // user-specific
        for (FP8Controls::UserButtonMap::const_iterator i = _ctrls.user_buttons ().begin ();
                        i != _ctrls.user_buttons ().end (); ++i) {
@@ -179,6 +190,20 @@ FaderPort8::button_open ()
                AccessAction ("Common", "addExistingAudioFiles");
        }
 }
+
+void
+FaderPort8::button_chanlock ()
+{
+       _chan_locked = !_chan_locked;
+
+       _ctrls.button (FP8Controls::BtnChannel).set_blinking (_chan_locked);
+}
+
+void
+FaderPort8::button_flip ()
+{
+}
+
 void
 FaderPort8::button_lock ()
 {
@@ -218,7 +243,7 @@ FaderPort8::button_automation (ARDOUR::AutoState as)
        switch (fadermode) {
                case ModePlugins:
 #if 0 // Plugin Control Automation Mode
-                       for ( std::list <ProcessorCtrl>::iterator i = _proc_params.begin(); i != _proc_params.end(); ++i) {
+                       for (std::list <ProcessorCtrl>::iterator i = _proc_params.begin(); i != _proc_params.end(); ++i) {
                                ((*i).ac)->set_automation_state (as);
                        }
 #endif
@@ -450,11 +475,21 @@ FaderPort8::handle_encoder_link (int steps)
 void
 FaderPort8::button_arm (bool press)
 {
+#ifdef FADERPORT2
+       boost::shared_ptr<Stripable> s = first_selected_stripable();
+       if (press && s) {
+               boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(s);
+               if (t) {
+                       t->rec_enable_control()->set_value (!t->rec_enable_control()->get_value(), PBD::Controllable::UseGroup);
+               }
+       }
+#else
        FaderMode fadermode = _ctrls.fader_mode ();
        if (fadermode == ModeTrack || fadermode == ModePan) {
                _ctrls.button (FP8Controls::BtnArm).set_active (press);
                ARMButtonChange (press); /* EMIT SIGNAL */
        }
+#endif
 }
 
 void
@@ -466,6 +501,7 @@ FaderPort8::button_prev_next (bool next)
                        break;
                case NavMaster:
                case NavScroll:
+               case NavPan:
                        bank (!next, false);
                        break;
                case NavBank:
@@ -533,6 +569,8 @@ FaderPort8::button_encoder ()
                                }
                        }
                        break;
+               case NavPan:
+                       break;
                case NavSection:
                        // TODO nudge
                        break;
@@ -620,6 +658,9 @@ FaderPort8::encoder_navigate (bool neg, int steps)
                                AccessAction ("Common", "nudge-playhead-forward");
                        }
                        break;
+               case NavPan:
+                       abort(); /*NOTREACHED*/
+                       break;
        }
 }
 
index fe3cdfc28ec91dddda0061dbe20853f7c11db4fc..f757781223a7e020800a2d1e091b42da6a576da5 100644 (file)
@@ -63,13 +63,13 @@ FaderPort8::send_session_state ()
        notify_mute_changed ();
        notify_parameter_changed ("clicking");
 
-       notify_automation_mode_changed (); // XXX (stip specific, see below)
+       notify_route_state_changed (); // XXX (stip specific, see below)
 }
 
 // TODO: AutomationState display of plugin & send automation
 // TODO: link/lock control AS.
 void
-FaderPort8::notify_automation_mode_changed ()
+FaderPort8::notify_route_state_changed ()
 {
        boost::shared_ptr<Stripable> s = first_selected_stripable();
        boost::shared_ptr<AutomationControl> ac;
@@ -92,6 +92,9 @@ FaderPort8::notify_automation_mode_changed ()
                _ctrls.button (FP8Controls::BtnATouch).set_active (false);
                _ctrls.button (FP8Controls::BtnARead).set_active (false);
                _ctrls.button (FP8Controls::BtnAWrite).set_active (false);
+#ifdef FADERPORT2
+               _ctrls.button (FP8Controls::BtnArm).set_active (false);
+#endif
                return;
        }
 
@@ -101,6 +104,12 @@ FaderPort8::notify_automation_mode_changed ()
        _ctrls.button (FP8Controls::BtnARead).set_active (as == Play);
        _ctrls.button (FP8Controls::BtnAWrite).set_active (as == Write);
        _ctrls.button (FP8Controls::BtnALatch).set_active (as == Latch);
+
+#ifdef FADERPORT2
+       /* handle the Faderport's track-arm button */
+       ac = s->rec_enable_control ();
+       _ctrls.button (FP8Controls::BtnArm).set_active (ac ? ac->get_value() : false);
+#endif
 }
 
 void
diff --git a/libs/surfaces/faderport8/faderport2_interface.cc b/libs/surfaces/faderport8/faderport2_interface.cc
new file mode 100644 (file)
index 0000000..93c9737
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2017 Robin Gareus <robin@gareus.org>
+ * Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <pbd/failed_constructor.h>
+
+#include "control_protocol/control_protocol.h"
+#include "faderport8.h"
+
+using namespace ARDOUR;
+using namespace ArdourSurface::FP_NAMESPACE;
+
+static ControlProtocol*
+new_faderport2_midi_protocol (ControlProtocolDescriptor* /*descriptor*/, Session* s)
+{
+       FaderPort8* fp;
+
+       try {
+               fp =  new FaderPort8 (*s);
+       } catch (failed_constructor& err) {
+               return 0;
+       }
+
+       if (fp->set_active (true)) {
+               delete fp;
+               return 0;
+       }
+
+       return fp;
+}
+
+static void
+delete_faderport2_midi_protocol (ControlProtocolDescriptor* /*descriptor*/, ControlProtocol* cp)
+{
+       delete cp;
+}
+
+static bool
+probe_faderport2_midi_protocol (ControlProtocolDescriptor* /*descriptor*/)
+{
+       return FaderPort8::probe ();
+}
+
+static void*
+faderport2_request_buffer_factory (uint32_t num_requests)
+{
+       return FaderPort8::request_factory (num_requests);
+}
+
+static ControlProtocolDescriptor faderport2_midi_descriptor = {
+       /*name :              */    "PreSonus FaderPort2",
+       /*id :                */    "uri://ardour.org/surfaces/faderport2:0",
+       /*ptr :               */    0,
+       /*module :            */    0,
+       /*mandatory :         */    0,
+       /*supports_feedback : */    true,
+       /*probe :             */    probe_faderport2_midi_protocol,
+       /*initialize :        */    new_faderport2_midi_protocol,
+       /*destroy :           */    delete_faderport2_midi_protocol,
+       /*request_buffer_factory */ faderport2_request_buffer_factory
+};
+
+extern "C" ARDOURSURFACE_API
+ControlProtocolDescriptor* protocol_descriptor () {
+       return &faderport2_midi_descriptor;
+}
index b10868aeede66b2ae0d5d14ca446c51f442090a8..70fed25766028c9d70070ea39a8dadec47967175 100644 (file)
@@ -89,6 +89,8 @@ debug_2byte_msg (std::string const& msg, int b0, int b1)
 FaderPort8::FaderPort8 (Session& s)
 #ifdef FADERPORT16
        : ControlProtocol (s, _("PreSonus FaderPort16"))
+#elif defined FADERPORT2
+       : ControlProtocol (s, _("PreSonus FaderPort2"))
 #else
        : ControlProtocol (s, _("PreSonus FaderPort8"))
 #endif
@@ -107,6 +109,7 @@ FaderPort8::FaderPort8 (Session& s)
        , gui (0)
        , _link_enabled (false)
        , _link_locked (false)
+       , _chan_locked (false)
        , _clock_mode (1)
        , _scribble_mode (2)
        , _two_line_text (false)
@@ -118,6 +121,9 @@ FaderPort8::FaderPort8 (Session& s)
 #ifdef FADERPORT16
        inp  = AudioEngine::instance()->register_input_port (DataType::MIDI, "FaderPort16 Recv", true);
        outp = AudioEngine::instance()->register_output_port (DataType::MIDI, "FaderPort16 Send", true);
+#elif defined FADERPORT2
+       inp  = AudioEngine::instance()->register_input_port (DataType::MIDI, "FaderPort2 Recv", true);
+       outp = AudioEngine::instance()->register_output_port (DataType::MIDI, "FaderPort2 Send", true);
 #else
        inp  = AudioEngine::instance()->register_input_port (DataType::MIDI, "FaderPort8 Recv", true);
        outp = AudioEngine::instance()->register_output_port (DataType::MIDI, "FaderPort8 Send", true);
@@ -131,10 +137,13 @@ FaderPort8::FaderPort8 (Session& s)
 
 #ifdef FADERPORT16
        _input_bundle.reset (new ARDOUR::Bundle (_("FaderPort16 (Receive)"), true));
-       _output_bundle.reset (new ARDOUR::Bundle (_("FaderPort16 (Send) "), false));
+       _output_bundle.reset (new ARDOUR::Bundle (_("FaderPort16 (Send)"), false));
+#elif defined FADERPORT2
+       _input_bundle.reset (new ARDOUR::Bundle (_("FaderPort2 (Receive)"), true));
+       _output_bundle.reset (new ARDOUR::Bundle (_("FaderPort2 (Send)"), false));
 #else
        _input_bundle.reset (new ARDOUR::Bundle (_("FaderPort8 (Receive)"), true));
-       _output_bundle.reset (new ARDOUR::Bundle (_("FaderPort8 (Send) "), false));
+       _output_bundle.reset (new ARDOUR::Bundle (_("FaderPort8 (Send)"), false));
 #endif
 
        _input_bundle->add_channel (
@@ -309,7 +318,7 @@ FaderPort8::close ()
        DEBUG_TRACE (DEBUG::FaderPort8, "FaderPort8::close\n");
        stop_midi_handling ();
        session_connections.drop_connections ();
-       automation_state_connections.drop_connections ();
+       route_state_connections.drop_connections ();
        assigned_stripable_connections.drop_connections ();
        _assigned_strips.clear ();
        drop_ctrl_connections ();
@@ -588,7 +597,15 @@ FaderPort8::controller_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb)
                encoder_navigate (tb->value & dir_mask ? true : false, tb->value & step_mask);
        }
        if (tb->controller_number == 0x10) {
+#ifdef FADERPORT2
+               if (_ctrls.nav_mode() == NavPan) {
+                       encoder_parameter (tb->value & dir_mask ? true : false, tb->value & step_mask);
+               } else {
+                       encoder_navigate (tb->value & dir_mask ? true : false, tb->value & step_mask);
+               }
+#else
                encoder_parameter (tb->value & dir_mask ? true : false, tb->value & step_mask);
+#endif
        }
 }
 
@@ -974,6 +991,16 @@ FaderPort8::assign_stripables (bool select_only)
                set_periodic_display_mode (FP8Strip::Stripables);
        }
 
+#ifdef FADERPORT2
+       boost::shared_ptr<Stripable> s = first_selected_stripable();
+       if (s) {
+               _ctrls.strip(0).set_stripable (s, _ctrls.fader_mode() == ModePan);
+       } else {
+               _ctrls.strip(0).unset_controllables ( FP8Strip::CTRL_ALL );
+       }
+       return;
+#endif
+
        int n_strips = strips.size();
        int channel_off = get_channel_off (_ctrls.mix_mode ());
        channel_off = std::min (channel_off, n_strips - N_STRIPS);
@@ -1752,7 +1779,7 @@ FaderPort8::notify_fader_mode_changed ()
                        break;
        }
        assign_strips ();
-       notify_automation_mode_changed ();
+       notify_route_state_changed ();
 }
 
 void
@@ -1828,6 +1855,20 @@ FaderPort8::notify_stripable_property_changed (boost::weak_ptr<Stripable> ws, co
        }
 }
 
+#ifdef FADERPORT2
+void
+FaderPort8::stripable_selection_changed ()
+{
+       if (!_device_active || _chan_locked) {
+               return;
+       }
+       route_state_connections.drop_connections ();
+       assign_stripables (false);
+       subscribe_to_strip_signals ();
+}
+
+#else
+
 void
 FaderPort8::stripable_selection_changed ()
 {
@@ -1837,7 +1878,7 @@ FaderPort8::stripable_selection_changed ()
                 */
                return;
        }
-       automation_state_connections.drop_connections();
+       route_state_connections.drop_connections();
 
        switch (_ctrls.fader_mode ()) {
                case ModePlugins:
@@ -1869,21 +1910,34 @@ FaderPort8::stripable_selection_changed ()
                _ctrls.strip(id).select_button ().set_blinking (sel && s == first_selected_stripable ());
        }
 
-       /* track automation-mode of primary selection */
+       subscribe_to_strip_signals ();
+}
+#endif
+
+void
+FaderPort8::subscribe_to_strip_signals ()
+{
+       /* keep track of automation-mode of primary selection, shared buttons */
        boost::shared_ptr<Stripable> s = first_selected_stripable();
        if (s) {
                boost::shared_ptr<AutomationControl> ac;
                ac = s->gain_control();
                if (ac && ac->alist()) {
-                       ac->alist()->automation_state_changed.connect (automation_state_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::notify_automation_mode_changed, this), this);
+                       ac->alist()->automation_state_changed.connect (route_state_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::notify_route_state_changed, this), this);
                }
                ac = s->pan_azimuth_control();
                if (ac && ac->alist()) {
-                       ac->alist()->automation_state_changed.connect (automation_state_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::notify_automation_mode_changed, this), this);
+                       ac->alist()->automation_state_changed.connect (route_state_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::notify_route_state_changed, this), this);
+               }
+#ifdef FADERPORT2
+               ac = s->rec_enable_control();
+               if (ac) {
+                       ac->Changed.connect (route_state_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::notify_route_state_changed, this), this);
                }
+#endif
        }
        /* set lights */
-       notify_automation_mode_changed ();
+       notify_route_state_changed ();
 }
 
 
@@ -1968,6 +2022,12 @@ FaderPort8::select_prev_next (bool next)
 void
 FaderPort8::bank (bool down, bool page)
 {
+#ifdef FADERPORT2
+       // XXX this should preferably be in actions.cc
+       AccessAction ("Editor", down ? "select-prev-stripable" : "select-next-stripable");
+       return;
+#endif
+
        int dt = page ? N_STRIPS : 1;
        if (down) {
                dt *= -1;
index 1f5c25e3fd728e5462cc09e9175be8d15e4b6551..1ef2690c8785c31595deb049d61f6f6eadd9376d 100644 (file)
@@ -201,9 +201,10 @@ private:
        void notify_pi_property_changed (const PBD::PropertyChange&);
        void notify_stripable_property_changed (boost::weak_ptr<ARDOUR::Stripable>, const PBD::PropertyChange&);
        void stripable_selection_changed ();
+       void subscribe_to_strip_signals ();
 
        PBD::ScopedConnection selection_connection;
-       PBD::ScopedConnectionList automation_state_connections;
+       PBD::ScopedConnectionList route_state_connections;
        PBD::ScopedConnectionList modechange_connections;
        /* **************************************************************************/
        struct ProcessorCtrl {
@@ -265,7 +266,7 @@ private:
        void notify_history_changed ();
        void notify_solo_changed ();
        void notify_mute_changed ();
-       void notify_automation_mode_changed ();
+       void notify_route_state_changed ();
        void notify_plugin_active_changed ();
 
        /* actions */
@@ -290,6 +291,9 @@ private:
        void button_prev_next (bool);
        void button_action (const std::string& group, const std::string& item);
 
+       void button_chanlock (); /* FP2 only */
+       void button_flip (); /* FP2 only */
+
        void button_encoder ();
        void button_parameter ();
        void encoder_navigate (bool, int);
@@ -317,6 +321,8 @@ private:
        bool _link_enabled;
        bool _link_locked; // can only be true if _link_enabled
 
+       bool _chan_locked; /* FP2 only */
+
        /* user prefs */
        uint32_t _clock_mode;
        uint32_t _scribble_mode;
index a77b4a67f0a270bdc6eae3fdbbb9d888134d631c..2c9f46cb54f136abb16998a51fb86e5405bbfb99 100644 (file)
 #include "pbd/signals.h"
 
 #ifdef FADERPORT16
-#define FP_NAMESPACE FP16
+# define FP_NAMESPACE FP16
+#elif defined FADERPORT2
+# define FP_NAMESPACE FP2
 #else
-#define FP_NAMESPACE FP8
+# define FP_NAMESPACE FP8
 #endif
 
 namespace ArdourSurface { namespace FP_NAMESPACE {
@@ -157,7 +159,8 @@ namespace FP8Types {
                NavBank,
                NavMaster,
                NavSection,
-               NavMarker
+               NavMarker,
+               NavPan /* FP2 only */
        };
 
        enum MixMode {
index 81c733ad55355f72b0e676d757cb76eb2b2a0de9..b0727c84a832a3bf472b01c3d630d95742c399b6 100644 (file)
@@ -61,7 +61,11 @@ bool FP8ButtonInterface::force_change = false;
 
 FP8Controls::FP8Controls (FP8Base& b)
        : _fadermode (ModeTrack)
+#ifdef FADERPORT2
+       , _navmode (NavScroll)
+#else
        , _navmode (NavMaster)
+#endif
        , _mixmode (MixAll)
        , _display_timecode (false)
 {
@@ -72,6 +76,38 @@ FP8Controls::FP8Controls (FP8Base& b)
        NEWBUTTON (0x5e, BtnPlay, false);
        NEWBUTTON (0x5f, BtnRecord, false);
 
+#ifdef FADERPORT2
+
+       NEWSHIFTBUTTON (0x4a, BtnARead, BtnAOff, true);
+       NEWSHIFTBUTTON (0x4b, BtnAWrite, BtnATrim, true);
+       NEWSHIFTBUTTON (0x4d, BtnATouch, BtnALatch, true);
+
+       NEWSHIFTBUTTON (0x2e, BtnPrev, BtnUndo, false);
+       NEWSHIFTBUTTON (0x2f, BtnNext, BtnRedo, false);
+
+       NEWSHIFTBUTTON (0x2a, BtnPan, BtnFlip, true);  //TODO: Flip Pan knob to fader ...?
+
+       NEWSHIFTBUTTON (0x36, BtnChannel, BtnChanLock, true);
+
+       NEWSHIFTBUTTON (0x38, BtnScroll,  BtnZoom, true);
+
+       NEWSHIFTBUTTON (0x3a, BtnMaster,  BtnF1, false);
+       NEWSHIFTBUTTON (0x3b, BtnClick,   BtnF2, false);
+       NEWSHIFTBUTTON (0x3c, BtnSection, BtnF3, false);
+       NEWSHIFTBUTTON (0x3d, BtnMarker,  BtnF4, false);
+
+       //these buttons do not exist in FP2, but they need to exist in the ctrlmap:
+       NEWBUTTON (0x71, BtnBank, false);
+       NEWBUTTON (0x72, BtnF5, false);
+       NEWBUTTON (0x73, BtnF6, false);
+       NEWBUTTON (0x74, BtnF7, false);
+       NEWBUTTON (0x75, BtnF8, false);
+       NEWBUTTON (0x76, BtnUser1, false);
+       NEWBUTTON (0x77, BtnUser2, false);
+       NEWBUTTON (0x78, BtnUser3, false);
+       NEWBUTTON (0x79, BtnSave, false);
+
+#else
        NEWSHIFTBUTTON (0x4a, BtnARead, BtnUser3, true);
        NEWSHIFTBUTTON (0x4b, BtnAWrite, BtnUser2, true);
        NEWSHIFTBUTTON (0x4c, BtnATrim, BtnRedo, true);
@@ -91,10 +127,12 @@ FP8Controls::FP8Controls (FP8Base& b)
        NEWSHIFTBUTTON (0x3c, BtnSection, BtnF7, false);
        NEWSHIFTBUTTON (0x3d, BtnMarker,  BtnF8, false);
 
+       NEWBUTTON (0x2a, BtnPan, false);
+#endif
+
        NEWSHIFTBUTTON (0x28, BtnTrack, BtnTimecode, false);
        NEWBUTTON (0x2b, BtnPlugins, false);
        NEWBUTTON (0x29, BtnSend, false);
-       NEWBUTTON (0x2a, BtnPan, false);
 
        NEWSHIFTBUTTON (0x00, BtnArm, BtnArmAll, false);
        NEWBUTTON (0x01, BtnSoloClear, false);
@@ -131,6 +169,9 @@ FP8Controls::FP8Controls (FP8Base& b)
        BindNav (BtnMaster,  NavMaster);
        BindNav (BtnSection, NavSection);
        BindNav (BtnMarker,  NavMarker);
+#ifdef FADERPORT2
+       BindNav (BtnPan,     NavPan);
+#endif
 
 #define BindFader(BTN, MODE)\
        button (BTN).released.connect_same_thread (button_connections, boost::bind (&FP8Controls::set_fader_mode, this, MODE))
@@ -138,7 +179,9 @@ FP8Controls::FP8Controls (FP8Base& b)
        BindFader (BtnTrack,   ModeTrack);
        BindFader (BtnPlugins, ModePlugins);
        BindFader (BtnSend,    ModeSend);
+#ifndef FADERPORT2
        BindFader (BtnPan,     ModePan);
+#endif
 
 
 #define BindMix(BTN, MODE)\
@@ -260,6 +303,14 @@ FP8Controls::initialize ()
        button (BtnMFX).set_color (0x0000ffff);
        button (BtnMUser).set_color (0x0000ffff);
 
+#ifdef FADERPORT2
+       /* encoder mode-switches are orange, to match the Master switch physical color */
+       button (BtnLink).set_color (0x000000ff);
+       button (BtnChannel).set_color (0x0000ffff);
+       button (BtnScroll).set_color (0x0000ffff);
+       button (BtnPan).set_color (0xffffffff);
+#endif
+
        for (uint8_t id = 0; id < N_STRIPS; ++id) {
                chanstrip[id]->initialize ();
        }
@@ -268,7 +319,11 @@ FP8Controls::initialize ()
        all_lights_off ();
 
        /* default modes */
+#ifdef FADERPORT2
+       button (BtnScroll).set_active (true);
+#else
        button (BtnMaster).set_active (true);
+#endif
        button (BtnTrack).set_active (true);
        button (BtnMAll).set_active (true);
        button (BtnTimecode).set_active (_display_timecode);
@@ -357,6 +412,9 @@ FP8Controls::set_nav_mode (NavigationMode m)
        button (BtnMaster).set_active (m == NavMaster);
        button (BtnSection).set_active (m == NavSection);
        button (BtnMarker).set_active (m == NavMarker);
+#ifdef FADERPORT2
+       button (BtnPan).set_active (m == NavPan);
+#endif
        _navmode = m;
 }
 
index 6cdc3b440d3bbd7ddbd7921d77605407032733f1..548d07191c514537934b2765b57bb88d2bede383 100644 (file)
@@ -112,6 +112,10 @@ public:
                BtnLink,
                BtnLock,
 
+               /* FP2 only */
+               BtnChanLock,
+               BtnFlip
+
        };
 
        typedef std::map <ButtonId, std::string> UserButtonMap;
@@ -126,9 +130,15 @@ public:
        PBD::Signal0<void> FaderModeChanged;
        PBD::Signal0<void> MixModeChanged;
 
+#ifdef FADERPORT2
+       FP8Types::FaderMode fader_mode () const { return FP8Types::ModeTrack; }
+       FP8Types::MixMode mix_mode () const { return FP8Types::MixUser; }
+#else
        FP8Types::FaderMode fader_mode () const { return _fadermode; }
-       FP8Types::NavigationMode nav_mode () const { return _navmode; }
        FP8Types::MixMode mix_mode () const { return _mixmode; }
+#endif
+
+       FP8Types::NavigationMode nav_mode () const { return _navmode; }
        bool display_timecode () const { return _display_timecode; }
 
        FP8ButtonInterface& button (ButtonId id);
index 169847382035ecb8a64f2d8b9d719c1e4c0a558f..080b774c098e9025b9b0fbfc5d60b1b8f946bb42 100644 (file)
@@ -733,8 +733,10 @@ void
 FP8Strip::periodic ()
 {
        periodic_update_fader ();
+#ifndef FADERPORT2
        periodic_update_meter ();
        if (_displaymode != PluginSelect && _displaymode != PluginParam) {
                periodic_update_timecode (_base.clock_mode ());
        }
+#endif
 }
index c56c34c00777dbe4240702efb55f6eac9a235647..fc16d0f417010325c502210c1aa3e4cf3dfb47a0 100644 (file)
@@ -30,6 +30,8 @@
 
 #ifdef FADERPORT16
 # define N_STRIPS 16
+#elif defined FADERPORT2
+# define N_STRIPS 1
 #else
 # define N_STRIPS 8
 #endif
index 63bd72dd4621b7a04d097fad5baa0d64b45c449e..8d4d2f0450bb8691befbbed5d7882668f2355519 100644 (file)
@@ -95,6 +95,8 @@ FP8GUI::FP8GUI (FaderPort8& p)
        std::string data_file_path;
 #ifdef FADERPORT16
        string name = "faderport16-small.png";
+#elif defined FADERPORT2
+       string name = ""; // TODO
 #else
        string name = "faderport8-small.png";
 #endif
index 61e22994428709a19c9086985869193a1cc5ab5a..4485e5d0e42f7ca970a3e76f95937ce635f87099 100644 (file)
@@ -47,5 +47,18 @@ def build(bld):
     obj.use          = 'libardour libardour_cp libgtkmm2ext libpbd'
     obj.install_path = os.path.join(bld.env['LIBDIR'], 'surfaces')
 
+    obj = bld(features = 'cxx cxxshlib')
+    obj.source       = list(fp8_16_sources)
+    obj.source      += [ 'faderport2_interface.cc' ]
+    obj.defines      = [ 'PACKAGE="ardour_faderport8"' ]
+    obj.defines     += [ 'ARDOURSURFACE_DLL_EXPORTS' ]
+    obj.defines     += [ 'FADERPORT2' ]
+    obj.includes     = [ '.' ]
+    obj.name         = 'libardour_faderport2'
+    obj.target       = 'ardour_faderport2'
+    obj.uselib       = 'GTKMM GTK GDK XML'
+    obj.use          = 'libardour libardour_cp libgtkmm2ext libpbd'
+    obj.install_path = os.path.join(bld.env['LIBDIR'], 'surfaces')
+
 def shutdown():
     autowaf.shutdown()