lppro: handle new slots and new routes and improve color display
This commit is contained in:
parent
5deea0c077
commit
a49c961189
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
#include <cmath>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -151,11 +152,11 @@ LaunchPadPro::LaunchPadPro (ARDOUR::Session& s)
|
|||||||
build_color_map ();
|
build_color_map ();
|
||||||
build_pad_map ();
|
build_pad_map ();
|
||||||
|
|
||||||
Trigger::TriggerPropertyChange.connect (trigger_connections, invalidator (*this), boost::bind (&LaunchPadPro::trigger_property_change, this, _1, _2, _3), this);
|
Trigger::TriggerPropertyChange.connect (trigger_connections, invalidator (*this), boost::bind (&LaunchPadPro::trigger_property_change, this, _1, _2), this);
|
||||||
|
|
||||||
session->RecordStateChanged.connect(session_connections, invalidator(*this), boost::bind (&LaunchPadPro::record_state_changed, this), this);
|
|
||||||
session->TransportStateChange.connect(session_connections, invalidator(*this), boost::bind (&LaunchPadPro::transport_state_changed, this), this);
|
|
||||||
|
|
||||||
|
session->RecordStateChanged.connect (session_connections, invalidator(*this), boost::bind (&LaunchPadPro::record_state_changed, this), this);
|
||||||
|
session->TransportStateChange.connect (session_connections, invalidator(*this), boost::bind (&LaunchPadPro::transport_state_changed, this), this);
|
||||||
|
session->RouteAdded.connect (session_connections, invalidator(*this), boost::bind (&LaunchPadPro::viewport_changed, this), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchPadPro::~LaunchPadPro ()
|
LaunchPadPro::~LaunchPadPro ()
|
||||||
@ -253,7 +254,7 @@ LaunchPadPro::begin_using_device ()
|
|||||||
|
|
||||||
/* catch current selection, if any so that we can wire up the pads if appropriate */
|
/* catch current selection, if any so that we can wire up the pads if appropriate */
|
||||||
stripable_selection_changed ();
|
stripable_selection_changed ();
|
||||||
map_triggers ();
|
viewport_changed ();
|
||||||
|
|
||||||
return MIDISurface::begin_using_device ();
|
return MIDISurface::begin_using_device ();
|
||||||
}
|
}
|
||||||
@ -547,7 +548,6 @@ LaunchPadPro::set_device_mode (DeviceMode m)
|
|||||||
|
|
||||||
switch (m) {
|
switch (m) {
|
||||||
case Standalone:
|
case Standalone:
|
||||||
std::cerr << "entering standalone mode\n";
|
|
||||||
live_or_programmer.push_back (0xe);
|
live_or_programmer.push_back (0xe);
|
||||||
live_or_programmer.push_back (0x0);
|
live_or_programmer.push_back (0x0);
|
||||||
live_or_programmer.push_back (0xf7);
|
live_or_programmer.push_back (0xf7);
|
||||||
@ -576,7 +576,6 @@ LaunchPadPro::set_device_mode (DeviceMode m)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Programmer:
|
case Programmer:
|
||||||
std::cerr << "entering programmer mode\n";
|
|
||||||
live_or_programmer.push_back (0xe);
|
live_or_programmer.push_back (0xe);
|
||||||
live_or_programmer.push_back (0x1);
|
live_or_programmer.push_back (0x1);
|
||||||
live_or_programmer.push_back (0xf7);
|
live_or_programmer.push_back (0xf7);
|
||||||
@ -1340,13 +1339,10 @@ LaunchPadPro::pad_long_press (Pad& pad)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LaunchPadPro::trigger_property_change (PropertyChange pc, int x, int y)
|
LaunchPadPro::trigger_property_change (PropertyChange pc, Trigger* t)
|
||||||
{
|
{
|
||||||
TriggerPtr trigger (session->trigger_at (x, y));
|
int x = t->box().order();
|
||||||
|
int y = t->index();
|
||||||
if (!trigger) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::Launchpad, string_compose ("prop change %1 for trigger at %2, %3\n", pc, x, y));
|
DEBUG_TRACE (DEBUG::Launchpad, string_compose ("prop change %1 for trigger at %2, %3\n", pc, x, y));
|
||||||
|
|
||||||
@ -1360,39 +1356,57 @@ LaunchPadPro::trigger_property_change (PropertyChange pc, int x, int y)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pc.contains (Properties::running)) {
|
/* name property change is sent when slots are loaded or unloaded */
|
||||||
|
|
||||||
|
PropertyChange our_interests;
|
||||||
|
our_interests.add (Properties::running);
|
||||||
|
our_interests.add (Properties::name);;
|
||||||
|
|
||||||
|
if (pc.contains (our_interests)) {
|
||||||
|
|
||||||
int pid = (11 + ((7 - y) * 10)) + x;
|
int pid = (11 + ((7 - y) * 10)) + x;
|
||||||
|
|
||||||
MidiByteArray msg;
|
MidiByteArray msg;
|
||||||
|
std::shared_ptr<Route> r = session->get_remote_nth_route (scroll_x_offset + x);
|
||||||
|
|
||||||
switch (trigger->state()) {
|
if (!r || !t->region()) {
|
||||||
case Trigger::Stopped:
|
|
||||||
msg.push_back (0x90);
|
msg.push_back (0x90);
|
||||||
msg.push_back (pid);
|
msg.push_back (pid);
|
||||||
msg.push_back (find_closest_palette_color (trigger->color ()));
|
msg.push_back (0x0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
switch (t->state()) {
|
||||||
|
case Trigger::Stopped:
|
||||||
|
std::cerr << "stopped, use color\n";
|
||||||
|
msg.push_back (0x90);
|
||||||
|
msg.push_back (pid);
|
||||||
|
msg.push_back (find_closest_palette_color (r->presentation_info().color()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Trigger::WaitingToStart:
|
case Trigger::WaitingToStart:
|
||||||
|
case Trigger::Stopping:
|
||||||
|
std::cerr << "wts/stp\n";
|
||||||
msg.push_back (0x91); /* channel 1=> pulsing */
|
msg.push_back (0x91); /* channel 1=> pulsing */
|
||||||
msg.push_back (pid);
|
msg.push_back (pid);
|
||||||
msg.push_back (0x27);
|
msg.push_back (find_closest_palette_color (r->presentation_info().color()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Trigger::Running:
|
case Trigger::Running:
|
||||||
|
std::cerr << "runing\n";
|
||||||
|
/* choose contrasting color from the base one */
|
||||||
|
msg.push_back (0x90);
|
||||||
|
msg.push_back (pid);
|
||||||
|
msg.push_back (find_closest_palette_color (HSV(r->presentation_info().color()).opposite()));
|
||||||
|
break;
|
||||||
|
|
||||||
case Trigger::WaitingForRetrigger:
|
case Trigger::WaitingForRetrigger:
|
||||||
case Trigger::WaitingToStop:
|
case Trigger::WaitingToStop:
|
||||||
case Trigger::WaitingToSwitch:
|
case Trigger::WaitingToSwitch:
|
||||||
/* XXX choose contrasting color from the base one */
|
std::cerr << "waiting\n";
|
||||||
msg.push_back (0x90);
|
msg.push_back (0x91);
|
||||||
msg.push_back (pid);
|
msg.push_back (pid);
|
||||||
msg.push_back (0x10);
|
msg.push_back (find_closest_palette_color (HSV(r->presentation_info().color()).opposite()));
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
msg.push_back (0x90);
|
|
||||||
msg.push_back (pid);
|
|
||||||
msg.push_back (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
daw_write (msg);
|
daw_write (msg);
|
||||||
@ -1410,10 +1424,18 @@ LaunchPadPro::map_triggers ()
|
|||||||
void
|
void
|
||||||
LaunchPadPro::map_triggerbox (int x)
|
LaunchPadPro::map_triggerbox (int x)
|
||||||
{
|
{
|
||||||
MidiByteArray msg (sysex_header);
|
MIDI::byte msg[3];
|
||||||
|
|
||||||
msg.push_back (0x3);
|
msg[0] = 0x90;
|
||||||
msg.push_back (0x3);
|
|
||||||
|
std::shared_ptr<Route> r = session->get_remote_nth_route (scroll_x_offset + x);
|
||||||
|
int palette_index;
|
||||||
|
|
||||||
|
if (r) {
|
||||||
|
palette_index = find_closest_palette_color (r->presentation_info().color());
|
||||||
|
} else {
|
||||||
|
palette_index = 0x0;
|
||||||
|
}
|
||||||
|
|
||||||
for (int y = 0; y < 8; ++y) {
|
for (int y = 0; y < 8; ++y) {
|
||||||
|
|
||||||
@ -1421,25 +1443,18 @@ LaunchPadPro::map_triggerbox (int x)
|
|||||||
int yp = y + scroll_y_offset;
|
int yp = y + scroll_y_offset;
|
||||||
|
|
||||||
int pid = (11 + ((7 - y) * 10)) + x;
|
int pid = (11 + ((7 - y) * 10)) + x;
|
||||||
|
msg[1] = pid;
|
||||||
|
|
||||||
TriggerPtr t = session->trigger_at (xp, yp);
|
TriggerPtr t = session->trigger_at (xp, yp);
|
||||||
int color;
|
|
||||||
|
|
||||||
if (!t) {
|
if (!t || !t->region()) {
|
||||||
color = 0x0;
|
msg[2] = 0x0;
|
||||||
} else {
|
} else {
|
||||||
color = t->color();
|
msg[2] = palette_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.push_back (pid);
|
daw_write (msg, 3);
|
||||||
msg.push_back (UINT_RGBA_R (color)/2);
|
|
||||||
msg.push_back (UINT_RGBA_G (color)/2);
|
|
||||||
msg.push_back (UINT_RGBA_B (color)/2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.push_back (0xf7);
|
|
||||||
daw_write (msg);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1591,12 +1606,14 @@ LaunchPadPro::build_color_map ()
|
|||||||
|
|
||||||
for (size_t n = 0; n < sizeof (novation_color_chart_left_side) / sizeof (novation_color_chart_left_side[0]); ++n) {
|
for (size_t n = 0; n < sizeof (novation_color_chart_left_side) / sizeof (novation_color_chart_left_side[0]); ++n) {
|
||||||
uint32_t color = novation_color_chart_left_side[n];
|
uint32_t color = novation_color_chart_left_side[n];
|
||||||
|
/* Add 1 to account for missing zero at zero in the table */
|
||||||
std::pair<int,uint32_t> p (1 + n, color);
|
std::pair<int,uint32_t> p (1 + n, color);
|
||||||
color_map.insert (p);
|
color_map.insert (p);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t n = 0; n < sizeof (novation_color_chart_right_side) / sizeof (novation_color_chart_right_side[0]); ++n) {
|
for (size_t n = 0; n < sizeof (novation_color_chart_right_side) / sizeof (novation_color_chart_right_side[0]); ++n) {
|
||||||
uint32_t color = novation_color_chart_right_side[n];
|
uint32_t color = novation_color_chart_right_side[n];
|
||||||
|
/* Add 40 to account for start offset number shown in page 10 of the LP manual */
|
||||||
std::pair<int,uint32_t> p (40 + n, color);
|
std::pair<int,uint32_t> p (40 + n, color);
|
||||||
color_map.insert (p);
|
color_map.insert (p);
|
||||||
}
|
}
|
||||||
@ -1605,7 +1622,7 @@ LaunchPadPro::build_color_map ()
|
|||||||
int
|
int
|
||||||
LaunchPadPro::find_closest_palette_color (uint32_t color)
|
LaunchPadPro::find_closest_palette_color (uint32_t color)
|
||||||
{
|
{
|
||||||
int64_t distance = std::numeric_limits<int64_t>::max();
|
auto distance = std::numeric_limits<double>::max();
|
||||||
int index = -1;
|
int index = -1;
|
||||||
|
|
||||||
NearestMap::iterator n = nearest_map.find (color);
|
NearestMap::iterator n = nearest_map.find (color);
|
||||||
@ -1613,13 +1630,19 @@ LaunchPadPro::find_closest_palette_color (uint32_t color)
|
|||||||
return n->second;
|
return n->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const & c : color_map) {
|
HSV hsv_c (color);
|
||||||
int p = c.second;
|
|
||||||
|
for (auto const & c : color_map) {
|
||||||
|
|
||||||
|
HSV hsv_p (c.second);
|
||||||
|
|
||||||
|
double chr = M_PI * (hsv_c.h / 180.0);
|
||||||
|
double phr = M_PI * (hsv_p.h /180.0);
|
||||||
|
double t1 = (sin (chr) * hsv_c.s * hsv_c.v) - (sin (phr) * hsv_p.s* hsv_p.v);
|
||||||
|
double t2 = (cos (chr) * hsv_c.s * hsv_c.v) - (cos (phr) * hsv_p.s * hsv_p.v);
|
||||||
|
double t3 = hsv_c.v - hsv_p.v;
|
||||||
|
double d = (t1 * t1) + (t2 * t2) + (0.5 * (t3 * t3));
|
||||||
|
|
||||||
int64_t rd = UINT_RGBA_R(p) - UINT_RGBA_R(color);
|
|
||||||
int64_t gd = UINT_RGBA_G(p) - UINT_RGBA_G(color);
|
|
||||||
int64_t bd = UINT_RGBA_B(p) - UINT_RGBA_B(color);
|
|
||||||
int64_t d = (rd * rd) + (gd * gd) + (bd * bd);
|
|
||||||
|
|
||||||
if (d < distance) {
|
if (d < distance) {
|
||||||
index = c.first;
|
index = c.first;
|
||||||
@ -1631,3 +1654,31 @@ LaunchPadPro::find_closest_palette_color (uint32_t color)
|
|||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LaunchPadPro::viewport_changed ()
|
||||||
|
{
|
||||||
|
route_connections.drop_connections ();
|
||||||
|
|
||||||
|
for (int n = 0; n < 8; ++n) {
|
||||||
|
std::shared_ptr<Route> r = session->get_remote_nth_route (scroll_x_offset + n);
|
||||||
|
if (r) {
|
||||||
|
r->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&LaunchPadPro::viewport_changed, this), this);
|
||||||
|
r->presentation_info().PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&LaunchPadPro::route_property_change, this, _1, n), this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
map_triggers ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LaunchPadPro::route_property_change (PropertyChange const & pc, int col)
|
||||||
|
{
|
||||||
|
if (pc.contains (Properties::color)) {
|
||||||
|
map_triggerbox (col);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (pc.contains (Properties::selected)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -52,6 +52,7 @@ namespace ARDOUR {
|
|||||||
class Port;
|
class Port;
|
||||||
class MidiBuffer;
|
class MidiBuffer;
|
||||||
class MidiTrack;
|
class MidiTrack;
|
||||||
|
class Trigger;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ArdourSurface {
|
namespace ArdourSurface {
|
||||||
@ -423,7 +424,7 @@ class LaunchPadPro : public MIDISurface
|
|||||||
void pad_press (Pad&);
|
void pad_press (Pad&);
|
||||||
void pad_long_press (Pad&);
|
void pad_long_press (Pad&);
|
||||||
|
|
||||||
void trigger_property_change (PBD::PropertyChange, int x, int y);
|
void trigger_property_change (PBD::PropertyChange, ARDOUR::Trigger*);
|
||||||
PBD::ScopedConnectionList trigger_connections;
|
PBD::ScopedConnectionList trigger_connections;
|
||||||
|
|
||||||
void display_session_layout ();
|
void display_session_layout ();
|
||||||
@ -432,6 +433,10 @@ class LaunchPadPro : public MIDISurface
|
|||||||
|
|
||||||
void map_triggers ();
|
void map_triggers ();
|
||||||
void map_triggerbox (int col);
|
void map_triggerbox (int col);
|
||||||
|
|
||||||
|
void viewport_changed ();
|
||||||
|
void route_property_change (PBD::PropertyChange const &, int x);
|
||||||
|
PBD::ScopedConnectionList route_connections;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user