launchpad: work on a single implementation for both Mini and X devices

This is not complete, because the symol names are identical, and there's no way (yet)
to ensure which versions Ardour will use if both are dynamically loaded.
This commit is contained in:
Paul Davis 2023-11-03 21:00:57 -06:00
parent a038ac1fb6
commit 9b511ce973
5 changed files with 153 additions and 23 deletions

View File

@ -90,7 +90,11 @@ LPX_GUI::LPX_GUI (LaunchPadX& p)
_table.set_homogeneous (false);
std::string data_file_path;
#ifdef LAUNCHPAD_MINI
std::string name = "launchpad-mini.png";
#else
std::string name = "launchpad-x.png";
#endif
Searchpath spath(ARDOUR::ardour_data_search_path());
spath.add_subdirectory_to_paths ("icons");
find_file (spath, name, data_file_path);

View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2016 Paul Davis <paul@linuxaudiosystems.com>
*
* 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.,
o * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdexcept>
#include "pbd/error.h"
#include "ardour/rc_configuration.h"
#include "control_protocol/control_protocol.h"
#include "lpx.h"
using namespace ARDOUR;
using namespace PBD;
using namespace ArdourSurface;
static ControlProtocol*
new_lpmini (Session* s)
{
LaunchPadX * lpm = nullptr;
try {
lpm = new LaunchPadX (*s);
/* do not set active here - wait for set_state() */
}
catch (std::exception & e) {
error << "Error instantiating LaunchPad Mini support: " << e.what() << endmsg;
delete lpm;
lpm = nullptr;
}
return lpm;
}
static void
delete_lpmini (ControlProtocol* cp)
{
try
{
delete cp;
}
catch ( std::exception & e )
{
std::cout << "Exception caught trying to finalize LaunchPad Mini support: " << e.what() << std::endl;
}
}
static bool
probe_lpmini_midi_protocol ()
{
std::string i, o;
return LaunchPadX::probe (i, o);
}
static ControlProtocolDescriptor lpmini_descriptor = {
/* name */ "Novation LaunchPad Mini",
/* id */ "uri://ardour.org/surfaces/lpmini:0",
/* module */ 0,
/* available */ 0,
/* probe_port */ probe_lpmini_midi_protocol,
/* match usb */ 0, // LaunchPadX::match_usb,
/* initialize */ new_lpmini,
/* destroy */ delete_lpmini,
};
extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { return &lpmini_descriptor; }

View File

@ -32,19 +32,19 @@ using namespace ArdourSurface;
static ControlProtocol*
new_lpx (Session* s)
{
LaunchPadX * p2 = 0;
LaunchPadX * lpx = nullptr;
try {
p2 = new LaunchPadX (*s);
lpx = new LaunchPadX (*s);
/* do not set active here - wait for set_state() */
}
catch (std::exception & e) {
error << "Error instantiating LaunchPad X support: " << e.what() << endmsg;
delete p2;
p2 = 0;
delete lpx;
lpx = nullptr;
}
return p2;
return lpx;
}
static void
@ -72,7 +72,7 @@ static ControlProtocolDescriptor lpx_descriptor = {
/* name */ "Novation LaunchPad X",
/* id */ "uri://ardour.org/surfaces/lpx:0",
/* module */ 0,
/* available */ LaunchPadX::available,
/* available */ 0,
/* probe_port */ probe_lpx_midi_protocol,
/* match usb */ 0, // LaunchPadX::match_usb,
/* initialize */ new_lpx,

View File

@ -76,8 +76,15 @@ using namespace Gtkmm2ext;
#include "pbd/abstract_ui.cc" // instantiate template
#define NOVATION 0x1235
#ifdef LAUNCHPAD_MINI
#define LAUNCHPADX 0x0113
static const std::vector<MIDI::byte> sysex_header ({ 0xf0, 0x00, 0x20, 0x29, 0x2, 0xd });
#else
#define LAUNCHPADX 0x0103
static const std::vector<MIDI::byte> sysex_header ({ 0xf0, 0x00, 0x20, 0x29, 0x2, 0xc });
#endif
static int first_fader = 0x9;
bool
@ -106,7 +113,11 @@ LaunchPadX::probe (std::string& i, std::string& o)
return false;
}
#ifdef LAUNCHPAD_MINI
std::regex rx (X_("Launchpad Mini.*MIDI"));
#else
std::regex rx (X_("Launchpad X.*MIDI"));
#endif
auto has_lppro = [&rx](string const &s) {
std::string pn = AudioEngine::instance()->get_hardware_port_name_by_name(s);
@ -126,7 +137,11 @@ LaunchPadX::probe (std::string& i, std::string& o)
}
LaunchPadX::LaunchPadX (ARDOUR::Session& s)
#ifdef LAUNCHPAD_MINI
: MIDISurface (s, X_("Novation LaunchPad Mini"), X_("LaunchPad Mini"), true)
#else
: MIDISurface (s, X_("Novation LaunchPad X"), X_("LaunchPad X"), true)
#endif
, logo_color (4)
, scroll_x_offset (0)
, scroll_y_offset (0)
@ -318,13 +333,21 @@ LaunchPadX::set_state (const XMLNode & node, int version)
std::string
LaunchPadX::input_port_name () const
{
#ifdef LAUNCHPAD_MINI
return X_(":Launchpad Mini MK3.*MIDI (In|2)");
#else
return X_(":Launchpad X MK3.*MIDI (In|2)");
#endif
}
std::string
LaunchPadX::output_port_name () const
{
#ifdef LAUNCHPAD_MINI
return X_(":Launchpad Mini MK3.*MIDI (Out|2)");
#else
return X_(":Launchpad X MK3.*MIDI (Out|2)");
#endif
}
void
@ -363,7 +386,7 @@ LaunchPadX::build_pad_map ()
for (int row = 0; row < 8; ++row) {
for (int col = 0; col < 8; ++col) {
int pid = (11 + (row * 10)) + col;
std::pair<int,Pad> p (pid, Pad (pid, col, 7 - row, &LaunchPadX::pad_press, &LaunchPadX::pad_long_press));
std::pair<int,Pad> p (pid, Pad (pid, col, 7 - row, &LaunchPadX::pad_press)); // , &LaunchPadX::pad_long_press));
if (!pad_map.insert (p).second) abort();
}
}
@ -607,16 +630,19 @@ LaunchPadX::handle_midi_controller_message (MIDI::Parser& parser, MIDI::EventTwo
return;
}
DEBUG_TRACE (DEBUG::Launchpad, string_compose ("CC %1 (value %2)\n", (int) ev->controller_number, (int) ev->value));
DEBUG_TRACE (DEBUG::Launchpad, string_compose ("CC %1 (value %2) layout %3 mode %4\n", (int) ev->controller_number, (int) ev->value, _current_layout, _session_mode));
if (_current_layout == SessionLayout && _session_mode == MixerMode) {
std::cerr << "possible fader!\n";
/* Trap fader move messages and act on them */
if (ev->controller_number >= first_fader && ev->controller_number < first_fader+8) {
std::cerr << "actual fader\n";
fader_move (ev->controller_number, ev->value);
return;
}
}
std::cerr << "not a fader\n";
PadMap::iterator p = pad_map.find (ev->controller_number);
if (p == pad_map.end()) {
return;
@ -735,7 +761,11 @@ LaunchPadX::connect_daw_ports ()
* newer ALSA and other platforms.
*/
#ifdef LAUNCHPAD_MINI
std::regex rx (X_("Launchpad Mini.*(DAW|MIDI 1)"), std::regex::extended);
#else
std::regex rx (X_("Launchpad X.*(DAW|MIDI 1)"), std::regex::extended);
#endif
auto is_dawport = [&rx](string const &s) {
std::string pn = AudioEngine::instance()->get_hardware_port_name_by_name(s);
@ -1595,7 +1625,7 @@ LaunchPadX::setup_faders (FaderBank bank)
msg.push_back (0); /* unipolar */
break;
}
msg.push_back (0x18+n); /* CC number */
msg.push_back (first_fader+n); /* CC number */
msg.push_back (random() % 127); /* color */
}

View File

@ -2,6 +2,11 @@
from waflib.extras import autowaf as autowaf
import os
lpxm_sources = [
'lpx.cc',
'gui.cc',
]
def options(opt):
pass
@ -9,22 +14,32 @@ def configure(conf):
autowaf.check_pkg(conf, 'pangomm-1.4', uselib_store='PANGOMM', atleast_version='1.4', mandatory=True)
autowaf.check_pkg(conf, 'cairomm-1.0', uselib_store='CAIROMM', atleast_version='1.8.4', mandatory=True)
def build(bld):
obj = bld(features = 'cxx cxxshlib')
obj.source = '''
lpx.cc
interface.cc
gui.cc
'''
obj.defines = [ 'PACKAGE="ardour_launchpad_x"' ]
obj.defines += [ 'ARDOURSURFACE_DLL_EXPORTS' ]
obj.defines += [ 'VERSIONSTRING="' + bld.env['VERSION'] + '"' ]
obj.includes = ['.', '..', './launchpad_x']
obj.name = 'libardour_launchpad_x'
obj.target = 'ardour_launchpad_x'
obj.uselib = 'CAIROMM PANGOMM USB GTKMM SIGCPP XML OSX'
obj.use = 'libardour libardour_cp libardour_midisurface libgtkmm2ext libpbd libevoral libcanvas libtemporal'
obj.install_path = os.path.join(bld.env['LIBDIR'], 'surfaces')
obj.source = list(lpxm_sources)
obj.source += [ 'launchpad_mini_interface.cc' ]
obj.defines = [ 'PACKAGE="ardour_launchpad_mini"' ]
obj.defines += [ 'ARDOURSURFACE_DLL_EXPORTS' ]
obj.defines += [ 'LAUNCHPAD_MINI' ]
obj.includes = ['.', ]
obj.name = 'libardour_launchpad_mini'
obj.target = 'ardour_launchpad_mini'
obj.uselib = 'CAIROMM PANGOMM USB GTKMM SIGCPP XML OSX'
obj.use = 'libardour libardour_cp libardour_midisurface libgtkmm2ext libpbd libevoral libcanvas libtemporal'
obj.install_path = os.path.join(bld.env['LIBDIR'], 'surfaces')
obj = bld(features = 'cxx cxxshlib')
obj.source = list(lpxm_sources)
obj.source += [ 'launchpad_x_interface.cc' ]
obj.defines = [ 'PACKAGE="ardour_launchpad_x"' ]
obj.defines += [ 'ARDOURSURFACE_DLL_EXPORTS' ]
obj.includes = ['.', ]
obj.name = 'libardour_launchpad_x'
obj.target = 'ardour_launchpad_x'
obj.uselib = 'CAIROMM PANGOMM USB GTKMM SIGCPP XML OSX'
obj.use = 'libardour libardour_cp libardour_midisurface libgtkmm2ext libpbd libevoral libcanvas libtemporal'
obj.install_path = os.path.join(bld.env['LIBDIR'], 'surfaces')
def shutdown():
autowaf.shutdown()