add new novation LK4 surface support
This commit is contained in:
parent
22411416ca
commit
cac849fe6d
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
283
libs/surfaces/launchkey_4/gui.cc
Normal file
283
libs/surfaces/launchkey_4/gui.cc
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
101
libs/surfaces/launchkey_4/gui.h
Normal file
101
libs/surfaces/launchkey_4/gui.h
Normal 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__ */
|
2715
libs/surfaces/launchkey_4/launchkey_4.cc
Normal file
2715
libs/surfaces/launchkey_4/launchkey_4.cc
Normal file
File diff suppressed because it is too large
Load Diff
408
libs/surfaces/launchkey_4/launchkey_4.h
Normal file
408
libs/surfaces/launchkey_4/launchkey_4.h
Normal 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__ */
|
88
libs/surfaces/launchkey_4/launchkey_4_interface.cc
Normal file
88
libs/surfaces/launchkey_4/launchkey_4_interface.cc
Normal 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; }
|
52
libs/surfaces/launchkey_4/wscript
Normal file
52
libs/surfaces/launchkey_4/wscript
Normal 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'
|
@ -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')
|
||||
|
Loading…
Reference in New Issue
Block a user