13
0

add new novation LK4 surface support

This commit is contained in:
Paul Davis 2024-08-29 18:31:00 -06:00
parent 22411416ca
commit cac849fe6d
10 changed files with 3653 additions and 2 deletions

View File

@ -19,7 +19,7 @@ export GTK2_RC_FILES=/nonexistent
# can find all the components.
#
export ARDOUR_SURFACES_PATH=$libs/surfaces/osc:$libs/surfaces/faderport8:$libs/surfaces/faderport:$libs/surfaces/generic_midi:$libs/surfaces/tranzport:$libs/surfaces/powermate:$libs/surfaces/mackie:$libs/surfaces/us2400:$libs/surfaces/wiimote:$libs/surfaces/push2:$libs/surfaces/maschine2:$libs/surfaces/cc121:$libs/surfaces/launch_control_xl:$libs/surfaces/contourdesign:$libs/surfaces/websockets:$libs/surfaces/console1:$libs/surfaces/launchpad_pro:$libs/surfaces/launchpad_x
export ARDOUR_SURFACES_PATH=$libs/surfaces/osc:$libs/surfaces/faderport8:$libs/surfaces/faderport:$libs/surfaces/generic_midi:$libs/surfaces/tranzport:$libs/surfaces/powermate:$libs/surfaces/mackie:$libs/surfaces/us2400:$libs/surfaces/wiimote:$libs/surfaces/push2:$libs/surfaces/maschine2:$libs/surfaces/cc121:$libs/surfaces/launch_control_xl:$libs/surfaces/contourdesign:$libs/surfaces/websockets:$libs/surfaces/console1:$libs/surfaces/launchpad_pro:$libs/surfaces/launchpad_x:$libs/surfaces/launchkey_4
export ARDOUR_PANNER_PATH=$libs/panners
export ARDOUR_DATA_PATH=$TOP/share:$TOP/build:$TOP/gtk2_ardour:$TOP/build/gtk2_ardour
export ARDOUR_MIDIMAPS_PATH=$TOP/share/midi_maps

View File

@ -69,6 +69,7 @@ namespace PBD {
LIBARDOUR_API extern DebugBits LatencyRoute;
LIBARDOUR_API extern DebugBits LaunchControlXL;
LIBARDOUR_API extern DebugBits Launchpad;
LIBARDOUR_API extern DebugBits Launchkey;
LIBARDOUR_API extern DebugBits Layering;
LIBARDOUR_API extern DebugBits MIDISurface;
LIBARDOUR_API extern DebugBits MTC;

View File

@ -64,6 +64,7 @@ PBD::DebugBits PBD::DEBUG::LatencyIO = PBD::new_debug_bit ("latencyio");
PBD::DebugBits PBD::DEBUG::LatencyRoute = PBD::new_debug_bit ("latencyroute");
PBD::DebugBits PBD::DEBUG::LaunchControlXL = PBD::new_debug_bit("launchcontrolxl");
PBD::DebugBits PBD::DEBUG::Launchpad = PBD::new_debug_bit ("launchpad");
PBD::DebugBits PBD::DEBUG::Launchkey = PBD::new_debug_bit ("launchkey");
PBD::DebugBits PBD::DEBUG::Layering = PBD::new_debug_bit ("layering");
PBD::DebugBits PBD::DEBUG::MIDISurface = PBD::new_debug_bit ("midisurface");
PBD::DebugBits PBD::DEBUG::MTC = PBD::new_debug_bit ("mtc");

View File

@ -0,0 +1,283 @@
/*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <gtkmm/alignment.h>
#include <gtkmm/label.h>
#include <gtkmm/liststore.h>
#include "pbd/unwind.h"
#include "pbd/strsplit.h"
#include "pbd/file_utils.h"
#include "gtkmm2ext/bindings.h"
#include "gtkmm2ext/gui_thread.h"
#include "gtkmm2ext/utils.h"
#include "ardour/audioengine.h"
#include "ardour/filesystem_paths.h"
#include "ardour/parameter_descriptor.h"
#include "launchkey_4.h"
#include "gui.h"
#include "pbd/i18n.h"
#ifdef LAUNCHPAD_MINI
#define LAUNCHPAD_NAMESPACE LP_MINI
#else
#define LAUNCHPAD_NAMESPACE LP_X
#endif
using namespace PBD;
using namespace ARDOUR;
using namespace ArdourSurface;
using namespace ArdourSurface::LAUNCHPAD_NAMESPACE;
using namespace Gtk;
using namespace Gtkmm2ext;
void*
LaunchKey4::get_gui () const
{
if (!_gui) {
const_cast<LaunchKey4*>(this)->build_gui ();
}
static_cast<Gtk::VBox*>(_gui)->show_all();
return _gui;
}
void
LaunchKey4::tear_down_gui ()
{
if (_gui) {
Gtk::Widget *w = static_cast<Gtk::VBox*>(_gui)->get_parent();
if (w) {
w->hide();
delete w;
}
}
delete _gui;
_gui = 0;
}
void
LaunchKey4::build_gui ()
{
_gui = new LK4_GUI (*this);
}
/*--------------------*/
LK4_GUI::LK4_GUI (LaunchKey4& p)
: _lp (p)
, _table (2, 5)
, _action_table (5, 4)
, _ignore_active_change (false)
{
set_border_width (12);
_table.set_row_spacings (4);
_table.set_col_spacings (6);
_table.set_border_width (12);
_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);
if (!data_file_path.empty()) {
_image.set (data_file_path);
_hpacker.pack_start (_image, false, false);
}
Gtk::Label* l;
int row = 0;
_input_combo.pack_start (_midi_port_columns.short_name);
_output_combo.pack_start (_midi_port_columns.short_name);
_input_combo.signal_changed().connect (sigc::bind (sigc::mem_fun (*this, &LK4_GUI::active_port_changed), &_input_combo, true));
_output_combo.signal_changed().connect (sigc::bind (sigc::mem_fun (*this, &LK4_GUI::active_port_changed), &_output_combo, false));
l = manage (new Gtk::Label);
l->set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Incoming MIDI on:")));
l->set_alignment (1.0, 0.5);
_table.attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
_table.attach (_input_combo, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
row++;
l = manage (new Gtk::Label);
l->set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Outgoing MIDI on:")));
l->set_alignment (1.0, 0.5);
_table.attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
_table.attach (_output_combo, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
row++;
_hpacker.pack_start (_table, true, true);
set_spacing (12);
pack_start (_hpacker, false, false);
/* update the port connection combos */
update_port_combos ();
/* catch future changes to connection state */
ARDOUR::AudioEngine::instance()->PortRegisteredOrUnregistered.connect (_port_connections, invalidator (*this), boost::bind (&LK4_GUI::connection_handler, this), gui_context());
ARDOUR::AudioEngine::instance()->PortPrettyNameChanged.connect (_port_connections, invalidator (*this), boost::bind (&LK4_GUI::connection_handler, this), gui_context());
_lp.ConnectionChange.connect (_port_connections, invalidator (*this), boost::bind (&LK4_GUI::connection_handler, this), gui_context());
}
LK4_GUI::~LK4_GUI ()
{
}
void
LK4_GUI::connection_handler ()
{
/* ignore all changes to combobox active strings here, because we're
updating them to match a new ("external") reality - we were called
because port connections have changed.
*/
PBD::Unwinder<bool> ici (_ignore_active_change, true);
update_port_combos ();
}
void
LK4_GUI::update_port_combos ()
{
std::vector<std::string> midi_inputs;
std::vector<std::string> midi_outputs;
if (!_lp.input_port() || !_lp.output_port()) {
return;
}
ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsOutput|ARDOUR::IsTerminal), midi_inputs);
ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsInput|ARDOUR::IsTerminal), midi_outputs);
Glib::RefPtr<Gtk::ListStore> input = build_midi_port_list (midi_inputs, true);
Glib::RefPtr<Gtk::ListStore> output = build_midi_port_list (midi_outputs, false);
bool input_found = false;
bool output_found = false;
int n;
_input_combo.set_model (input);
_output_combo.set_model (output);
Gtk::TreeModel::Children children = input->children();
Gtk::TreeModel::Children::iterator i;
i = children.begin();
++i; /* skip "Disconnected" */
for (n = 1; i != children.end(); ++i, ++n) {
std::string port_name = (*i)[_midi_port_columns.full_name];
if (_lp.input_port()->connected_to (port_name)) {
_input_combo.set_active (n);
input_found = true;
break;
}
}
if (!input_found) {
_input_combo.set_active (0); /* disconnected */
}
children = output->children();
i = children.begin();
++i; /* skip "Disconnected" */
for (n = 1; i != children.end(); ++i, ++n) {
std::string port_name = (*i)[_midi_port_columns.full_name];
if (_lp.output_port()->connected_to (port_name)) {
_output_combo.set_active (n);
output_found = true;
break;
}
}
if (!output_found) {
_output_combo.set_active (0); /* disconnected */
}
}
Glib::RefPtr<Gtk::ListStore>
LK4_GUI::build_midi_port_list (std::vector<std::string> const & ports, bool for_input)
{
Glib::RefPtr<Gtk::ListStore> store = ListStore::create (_midi_port_columns);
TreeModel::Row row;
row = *store->append ();
row[_midi_port_columns.full_name] = std::string();
row[_midi_port_columns.short_name] = _("Disconnected");
for (std::vector<std::string>::const_iterator p = ports.begin(); p != ports.end(); ++p) {
row = *store->append ();
row[_midi_port_columns.full_name] = *p;
std::string pn = ARDOUR::AudioEngine::instance()->get_pretty_name_by_name (*p);
if (pn.empty ()) {
pn = (*p).substr ((*p).find (':') + 1);
}
row[_midi_port_columns.short_name] = pn;
}
return store;
}
void
LK4_GUI::active_port_changed (Gtk::ComboBox* combo, bool for_input)
{
if (_ignore_active_change) {
return;
}
TreeModel::iterator active = combo->get_active ();
std::string new_port = (*active)[_midi_port_columns.full_name];
if (new_port.empty()) {
if (for_input) {
_lp.input_port()->disconnect_all ();
} else {
_lp.output_port()->disconnect_all ();
}
return;
}
if (for_input) {
if (!_lp.input_port()->connected_to (new_port)) {
_lp.input_port()->disconnect_all ();
_lp.input_port()->connect (new_port);
}
} else {
if (!_lp.output_port()->connected_to (new_port)) {
_lp.output_port()->disconnect_all ();
_lp.output_port()->connect (new_port);
}
}
}

View File

@ -0,0 +1,101 @@
/*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __ardour_lpx_gui_h__
#define __ardour_lpx_gui_h__
#include <vector>
#include <string>
#include <gtkmm/box.h>
#include <gtkmm/button.h>
#include <gtkmm/combobox.h>
#include <gtkmm/image.h>
#include <gtkmm/table.h>
#include <gtkmm/treestore.h>
#include <gtkmm/spinbutton.h>
#include <gtkmm/notebook.h>
namespace Gtk {
class ListStore;
}
#include "ardour/mode.h"
#include "launchkey_4.h"
namespace ArdourSurface { namespace LAUNCHPAD_NAMESPACE {
class LK4_GUI : public Gtk::VBox
{
public:
LK4_GUI (LaunchKey4&);
~LK4_GUI ();
private:
LaunchKey4& _lp;
Gtk::HBox _hpacker;
Gtk::Table _table;
Gtk::Table _action_table;
Gtk::ComboBox _input_combo;
Gtk::ComboBox _output_combo;
Gtk::Image _image;
void update_port_combos ();
void connection_handler ();
PBD::ScopedConnectionList _port_connections;
struct MidiPortColumns : public Gtk::TreeModel::ColumnRecord {
MidiPortColumns() {
add (short_name);
add (full_name);
}
Gtk::TreeModelColumn<std::string> short_name;
Gtk::TreeModelColumn<std::string> full_name;
};
MidiPortColumns _midi_port_columns;
bool _ignore_active_change;
Glib::RefPtr<Gtk::ListStore> build_midi_port_list (std::vector<std::string> const & ports, bool for_input);
void active_port_changed (Gtk::ComboBox*,bool for_input);
#if 0
struct PressureModeColumns : public Gtk::TreeModel::ColumnRecord {
PressureModeColumns() {
add (mode);
add (name);
}
Gtk::TreeModelColumn<Push2::PressureMode> mode;
Gtk::TreeModelColumn<std::string> name;
};
PressureModeColumns _pressure_mode_columns;
Glib::RefPtr<Gtk::ListStore> build_pressure_mode_columns ();
Gtk::ComboBox _pressure_mode_selector;
Gtk::Label _pressure_mode_label;
void reprogram_pressure_mode ();
#endif
};
} } /* namespaces */
#endif /* __ardour_lpx_gui_h__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,408 @@
/*
* Copyright (C) 2016-2018 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __ardour_lk4_h__
#define __ardour_lk4_h__
#include <functional>
#include <list>
#include <map>
#include <stack>
#include <set>
#include <vector>
#include <libusb.h>
#define ABSTRACT_UI_EXPORTS
#include "pbd/abstract_ui.h"
#include "midi++/types.h"
#include "ardour/mode.h"
#include "ardour/types.h"
#include "control_protocol/control_protocol.h"
#include "control_protocol/types.h"
#include "gtkmm2ext/colors.h"
#include "midi_surface/midi_byte_array.h"
#include "midi_surface/midi_surface.h"
namespace MIDI {
class Parser;
class Port;
}
namespace ARDOUR {
class AutomationControl;
class Plugin;
class PluginInsert;
class Port;
class MidiBuffer;
class MidiTrack;
class Trigger;
}
#ifdef LAUNCHPAD_MINI
#define LAUNCHPAD_NAMESPACE LP_MINI
#else
#define LAUNCHPAD_NAMESPACE LP_X
#endif
namespace ArdourSurface { namespace LAUNCHPAD_NAMESPACE {
class LK4_GUI;
class LaunchKey4 : public MIDISurface
{
public:
/* use hex for these constants, because we'll see them (as note numbers
and CC numbers) in hex within MIDI messages when debugging.
*/
enum ButtonID {
Button1 = 0x25,
Button2 = 0x26,
Button3 = 0x27,
Button4 = 0x28,
Button5 = 0x29,
Button6 = 0x2a,
Button7 = 0x2b,
Button8 = 0x2c,
Button9 = 0x2d,
Volume = 0x0b,
Custom1 = 0x0c,
Custom2 = 0x0d,
Custom3 = 0x0e,
Custom4 = 0x0f,
PartA = 0x10,
PartB = 0x11,
Split = 0x12,
Layer = 0x13,
Shift = 0x13,
// Settings = 0x23,
TrackLeft = 0x67,
TrackRight =0x66,
Up = 0x6a,
Down = 0x6b,
CaptureMidi = 0x3,
Undo = 0x4d,
Quantize = 0x4b,
Metronome = 0x4c,
// Stop = 0x34 .. sends Stop
// Play = 0x36 .. sends Play
Play = 0x73,
Stop = 0x74,
RecEnable = 0x75,
Loop = 0x76,
Function = 0x69,
Scene = 0x68,
EncUp = 0x33,
EncDown = 0x44,
};
enum KnobID {
Knob1 = 0x55,
Knob2 = 0x56,
Knob3 = 0x57,
Knob4 = 0x58,
Knob5 = 0x59,
Knob6 = 0x5a,
Knob7 = 0x5b,
Knob8 = 0x5c,
};
LaunchKey4 (ARDOUR::Session&);
~LaunchKey4 ();
static bool available ();
static bool match_usb (uint16_t, uint16_t);
static bool probe (std::string&, std::string&);
std::string input_port_name () const;
std::string output_port_name () const;
bool has_editor () const { return true; }
void* get_gui () const;
void tear_down_gui ();
int set_active (bool yn);
XMLNode& get_state() const;
int set_state (const XMLNode & node, int version);
private:
enum FaderBank {
VolumeFaders,
PanFaders,
SendAFaders,
SendBFaders,
};
struct Pad {
enum ColorMode {
Static = 0x0,
Flashing = 0x1,
Pulsing = 0x2
};
typedef void (LaunchKey4::*PadMethod)(Pad&, int velocity);
Pad (int pid, int xx, int yy)
: id (pid)
, x (xx)
, y (yy)
{
}
Pad () : id (-1), x (-1), y (-1)
{
}
int id;
int x;
int y;
sigc::connection timeout_connection;
};
void relax (Pad& p);
void relax (Pad&, int);
std::set<int> consumed;
Pad pads[16];
void build_pad_map ();
typedef std::map<int,uint32_t> ColorMap;
ColorMap color_map;
void build_color_map ();
int find_closest_palette_color (uint32_t);
typedef std::map<uint32_t,int> NearestMap;
NearestMap nearest_map;
int begin_using_device ();
int stop_using_device ();
int device_acquire () { return 0; }
void device_release () { }
void run_event_loop ();
void stop_event_loop ();
void finish_begin_using_device ();
void stripable_selection_changed ();
void select_stripable (int col);
std::weak_ptr<ARDOUR::MidiTrack> _current_pad_target;
void handle_midi_controller_message (MIDI::Parser&, MIDI::EventTwoBytes*);
void handle_midi_controller_message_chnF (MIDI::Parser&, MIDI::EventTwoBytes*);
void handle_midi_note_on_message (MIDI::Parser&, MIDI::EventTwoBytes*);
void handle_midi_note_off_message (MIDI::Parser&, MIDI::EventTwoBytes*);
void handle_midi_sysex (MIDI::Parser&, MIDI::byte *, size_t count);
MIDI::Port* _daw_in_port;
MIDI::Port* _daw_out_port;
std::shared_ptr<ARDOUR::Port> _daw_in;
std::shared_ptr<ARDOUR::Port> _daw_out;
void port_registration_handler ();
int ports_acquire ();
void ports_release ();
void connect_daw_ports ();
void daw_write (const MidiByteArray&);
void daw_write (MIDI::byte const *, size_t);
void reconnect_for_programmer ();
void reconnect_for_session ();
mutable LK4_GUI* _gui;
void build_gui ();
void maybe_start_press_timeout (Pad& pad);
void start_press_timeout (Pad& pad);
bool long_press_timeout (int pad_id);
void button_press (int button);
void button_release (int button);
void trigger_property_change (PBD::PropertyChange, ARDOUR::Trigger*);
void trigger_pad_light (Pad& pad, std::shared_ptr<ARDOUR::Route> r, ARDOUR::Trigger* t);
PBD::ScopedConnectionList trigger_connections;
void display_session_layout ();
void transport_state_changed ();
void record_state_changed ();
void map_selection ();
void map_mute_solo ();
void map_rec_enable ();
void map_triggers ();
void map_triggerbox (int col);
void route_property_change (PBD::PropertyChange const &, int x);
PBD::ScopedConnectionList route_connections;
void fader_move (int which, int val);
void automation_control_change (int n, std::weak_ptr<ARDOUR::AutomationControl>);
PBD::ScopedConnectionList control_connections;
FaderBank current_fader_bank;
bool revert_layout_on_fader_release;
void use_encoders (bool);
void encoder (int which, int step);
void knob (int which, int value);
int scroll_x_offset;
int scroll_y_offset;
uint16_t device_pid;
enum DisplayTarget {
StationaryDisplay = 0x20,
GlobalTemporaryDisplay = 0x21,
DAWPadFunctionDisplay = 0x22,
DawDrumrackModeDisplay = 0x23,
MixerPotMode = 0x24,
PluginPotMode = 0x25,
SendPotMode = 0x26,
TransportPotMode = 0x27,
FaderMode = 0x28,
};
void select_display_target (DisplayTarget dt);
void set_display_target (DisplayTarget dt, int field, std::string const &, bool display = false);
void configure_display (DisplayTarget dt, int config);
void set_plugin_encoder_name (int encoder, int field, std::string const &);
void set_daw_mode (bool);
int mode_channel;
enum PadFunction {
MuteSolo,
Triggers,
};
PadFunction pad_function;
void set_pad_function (PadFunction);
void pad_mute_solo (Pad&);
void pad_trigger (Pad&, int velocity);
void pad_release (Pad&);
bool shift_pressed;
bool layer_pressed;
void function_press ();
void undo_press ();
void metronome_press ();
void quantize_press ();
void button_left ();
void button_right ();
void button_down ();
void button_up ();
/* stripables */
int32_t bank_start;
PBD::ScopedConnectionList stripable_connections;
std::shared_ptr<ARDOUR::Stripable> stripable[8];
void stripables_added ();
void stripable_property_change (PBD::PropertyChange const& what_changed, uint32_t which);
void switch_bank (uint32_t);
void solo_changed ();
void mute_changed (uint32_t which);
void rec_enable_changed (uint32_t which);
enum LightingMode {
Off,
Solid,
Flash,
Pulse,
};
void light_button (int which, LightingMode, int color_index);
void light_pad (int pid, LightingMode, int color_index);
enum ButtonMode {
ButtonsRecEnable,
ButtonsSelect
};
ButtonMode button_mode;
void toggle_button_mode ();
void show_selection (int which);
void show_rec_enable (int which);
void show_mute (int which);
void show_solo (int which);
enum EncoderMode {
EncoderPlugins,
EncoderMixer,
EncoderSendA,
EncoderTransport
};
EncoderMode encoder_mode;
int encoder_bank;
void set_encoder_bank (int);
void set_encoder_mode (EncoderMode);
void set_encoder_titles_to_route_names ();
void setup_screen_for_encoder_plugins ();
void label_encoders ();
void show_encoder_value (int which, std::shared_ptr<ARDOUR::Plugin> plugin, int control, std::shared_ptr<ARDOUR::AutomationControl> ac, bool display);
void encoder_plugin (int which, int step);
void encoder_mixer (int which, int step);
void encoder_pan (int which, int step);
void encoder_level (int which, int step);
void encoder_senda (int which, int step);
void encoder_transport (int which, int step);
void transport_shuttle (int step);
void zoom (int step);
void loop_start_move (int step);
void loop_end_move (int step);
void jump_to_marker (int step);
void light_pad (int pad_id, int color_index);
void unlight_pad (int pad_id);
void all_pads (int color_index);
void all_pads_out ();
void show_scene_ids ();
void scene_press ();
void in_msecs (int msecs, std::function<void()> func);
std::weak_ptr<ARDOUR::AutomationControl> controls[24];
std::weak_ptr<ARDOUR::Plugin> current_plugin;
void plugin_selected (std::weak_ptr<ARDOUR::PluginInsert>);
uint32_t num_plugin_controls;
};
} } /* namespaces */
#endif /* __ardour_lk4_h__ */

View File

@ -0,0 +1,88 @@
/*
* 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.,
* 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 "launchkey_4.h"
#ifdef LAUNCHPAD_MINI
#define LAUNCHPAD_NAMESPACE LP_MINI
#else
#define LAUNCHPAD_NAMESPACE LP_X
#endif
using namespace ARDOUR;
using namespace PBD;
using namespace ArdourSurface::LAUNCHPAD_NAMESPACE;
static ControlProtocol*
new_lk4 (Session* s)
{
LaunchKey4 * lk4 = nullptr;
try {
lk4 = new LaunchKey4 (*s);
/* do not set active here - wait for set_state() */
}
catch (std::exception & e) {
error << "Error instantiating LaunchKey 4 support: " << e.what() << endmsg;
delete lk4;
lk4 = nullptr;
}
return lk4;
}
static void
delete_lk4 (ControlProtocol* cp)
{
try
{
delete cp;
}
catch ( std::exception & e )
{
std::cout << "Exception caught trying to finalize LaunchKey 4 support: " << e.what() << std::endl;
}
}
static bool
probe_lk4_midi_protocol ()
{
std::string i, o;
return LaunchKey4::probe (i, o);
}
static ControlProtocolDescriptor lk4_descriptor = {
/* name */ "Novation LaunchKey 4",
/* id */ "uri://ardour.org/surfaces/launchkey4:0",
/* module */ 0,
/* available */ 0,
/* probe_port */ probe_lk4_midi_protocol,
/* match usb */ 0, // LaunchKey4::match_usb,
/* initialize */ new_lk4,
/* destroy */ delete_lk4,
};
extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { return &lk4_descriptor; }

View File

@ -0,0 +1,52 @@
#!/usr/bin/env python
from waflib.extras import autowaf as autowaf
import os
lpxm_sources = [
'launchkey_4.cc',
'gui.cc',
]
def options(opt):
pass
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 = list(lpxm_sources)
# obj.source += [ 'launchkey_4_interface.cc' ]
# obj.defines = [ 'PACKAGE="ardour_launchkey_mini"' ]
# obj.defines += [ 'ARDOURSURFACE_DLL_EXPORTS' ]
# obj.defines += [ 'LAUNCHKEY_MINI' ]
# obj.includes = ['.', ]
# obj.name = 'libardour_launchkey_mini'
# obj.target = 'ardour_launchkey_mini'
# obj.uselib = 'CAIROMM PANGOMM USB 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')
# if bld.is_defined('YTK'):
# obj.use += ' libytkmm'
# obj.uselib += ' GLIBMM GIOMM'
# else:
# obj.uselib += ' GTKMM'
obj = bld(features = 'cxx cxxshlib')
obj.source = list(lpxm_sources)
obj.source += [ 'launchkey_4_interface.cc' ]
obj.defines = [ 'PACKAGE="ardour_launchpad_x"' ]
obj.defines += [ 'ARDOURSURFACE_DLL_EXPORTS' ]
obj.includes = ['.', ]
obj.name = 'libardour_launchkey_4'
obj.target = 'ardour_launchkey_4'
obj.uselib = 'CAIROMM PANGOMM USB 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')
if bld.is_defined('YTK'):
obj.use += ' libytkmm'
obj.uselib += ' GLIBMM GIOMM'
else:
obj.uselib += ' GTKMM'

View File

@ -22,7 +22,8 @@ children = [
'osc',
'console1',
'launchpad_pro',
'launchpad_x'
'launchpad_x',
'launchkey_4'
]
def options(opt):
@ -81,6 +82,7 @@ def build(bld):
bld.recurse('console1')
bld.recurse('launchpad_pro')
bld.recurse('launchpad_x')
bld.recurse('launchkey_4')
if bld.is_defined('BUILD_WIIMOTE'):
bld.recurse('wiimote')