summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2016-06-16 10:02:46 -0400
committerPaul Davis <paul@linuxaudiosystems.com>2016-09-27 14:59:29 -0500
commit67698b8232c8e99c0de65a5444f1b3b86f4f6297 (patch)
tree0cf36bc71bf45ed584ff06477a2920a8cfc234ca
parente0be45de3885264e5e9a045ebf3bf55cd2707c0c (diff)
push2: port registration, LED setup
-rw-r--r--libs/surfaces/push2/leds.cc150
-rw-r--r--libs/surfaces/push2/midi_byte_array.cc96
-rw-r--r--libs/surfaces/push2/midi_byte_array.h76
-rw-r--r--libs/surfaces/push2/push2.cc49
-rw-r--r--libs/surfaces/push2/push2.h69
-rw-r--r--libs/surfaces/push2/render.cc4
-rw-r--r--libs/surfaces/push2/wscript2
7 files changed, 441 insertions, 5 deletions
diff --git a/libs/surfaces/push2/leds.cc b/libs/surfaces/push2/leds.cc
new file mode 100644
index 0000000000..1e5423e17a
--- /dev/null
+++ b/libs/surfaces/push2/leds.cc
@@ -0,0 +1,150 @@
+#include <algorithm>
+
+#include "push2.h"
+
+using namespace ArdourSurface;
+using std::make_pair;
+using std::max;
+using std::min;
+
+void
+Push2::LED::set_color (uint8_t ci)
+{
+ color_index = max (uint8_t(0), min (uint8_t(127), ci));
+}
+
+void
+Push2::LED::set_state (LED::State s)
+{
+ state = s;
+}
+
+MidiByteArray
+Push2::LED::update ()
+{
+ MidiByteArray msg;
+
+ switch (type) {
+ case Pad:
+ case TouchStrip:
+ msg.push_back (0x90);
+ break;
+ case ColorButton:
+ case WhiteButton:
+ msg.push_back (0xb0);
+ break;
+ }
+
+ msg.push_back (state);
+ msg.push_back (color_index);
+
+ return msg;
+}
+
+void
+Push2::set_led_color (uint32_t id, uint8_t color_index)
+{
+ leds[id].set_color (color_index);
+ // write (leds[id].update ());
+}
+
+void
+Push2::build_led_map ()
+{
+ uint8_t id = 0;
+ uint8_t extra;
+
+ /* Touch strip - there is only one */
+
+ leds.insert (make_pair (id, LED (id, LED::TouchStrip, 12)));
+ id++;
+
+ /* Pads
+
+ Pad 0 is in the bottom left corner, id rises going left=>right
+ across each row
+ */
+
+ for (extra = 36; id < 64; ++id, ++extra) {
+ leds.insert (make_pair (id, LED (id, LED::Pad, extra)));
+ }
+
+ /* Buttons
+
+ We start with Button 0 at the upper left of the surface, increasing
+ across the device and wrapping, until we're at the Master button on
+ the right.
+
+ Then we descend down the left side. Then down the right side of the
+ pads. Finally the column on the far right., going clockwise around
+ each 4-way diagonal button.
+
+ 66 buttons in total
+ */
+
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 3)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 9)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 102)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 103)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 104)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 105)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 106)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 107)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 108)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 109)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 30)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 59)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 118)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 52)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 110)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 112)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 119)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 53)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 111)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 113)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 60)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 61)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 29)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 20)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 21)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 22)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 23)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 24)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 25)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 26)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 27)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 28)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 35)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 117)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 116)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 88)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 87)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 90)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 89)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 86)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 85)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 43)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 42)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 41)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 40)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 39)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 38)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 37)));
+ leds.insert (make_pair (id, LED (id, LED::ColorButton, 36)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 46)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 45)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 47)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 44)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 56)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 57)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 58)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 31)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 50)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 51)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 55)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 63)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 54)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 62)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 49)));
+ leds.insert (make_pair (id, LED (id, LED::WhiteButton, 48)));
+}
diff --git a/libs/surfaces/push2/midi_byte_array.cc b/libs/surfaces/push2/midi_byte_array.cc
new file mode 100644
index 0000000000..45d0439a75
--- /dev/null
+++ b/libs/surfaces/push2/midi_byte_array.cc
@@ -0,0 +1,96 @@
+/*
+ Copyright (C) 2006,2007 John Anderson
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "midi_byte_array.h"
+
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <algorithm>
+#include <cstdarg>
+#include <iomanip>
+#include <stdexcept>
+
+using namespace std;
+
+MidiByteArray::MidiByteArray (size_t size, MIDI::byte array[])
+ : std::vector<MIDI::byte>()
+{
+ for (size_t i = 0; i < size; ++i)
+ {
+ push_back (array[i]);
+ }
+}
+
+MidiByteArray::MidiByteArray (size_t count, MIDI::byte first, ...)
+ : vector<MIDI::byte>()
+{
+ push_back (first);
+ va_list var_args;
+ va_start (var_args, first);
+ for (size_t i = 1; i < count; ++i)
+ {
+ MIDI::byte b = va_arg (var_args, int);
+ push_back (b);
+ }
+ va_end (var_args);
+}
+
+
+void MidiByteArray::copy (size_t count, MIDI::byte * arr)
+{
+ for (size_t i = 0; i < count; ++i) {
+ push_back (arr[i]);
+ }
+}
+
+MidiByteArray & operator << (MidiByteArray & mba, const MIDI::byte & b)
+{
+ mba.push_back (b);
+ return mba;
+}
+
+MidiByteArray & operator << (MidiByteArray & mba, const MidiByteArray & barr)
+{
+ back_insert_iterator<MidiByteArray> bit (mba);
+ copy (barr.begin(), barr.end(), bit);
+ return mba;
+}
+
+ostream & operator << (ostream & os, const MidiByteArray & mba)
+{
+ os << "[";
+ char fill = os.fill('0');
+ for (MidiByteArray::const_iterator it = mba.begin(); it != mba.end(); ++it) {
+ if (it != mba.begin()) os << " ";
+ os << hex << setw(2) << (int)*it;
+ }
+ os.fill (fill);
+ os << dec;
+ os << "]";
+ return os;
+}
+
+MidiByteArray & operator << (MidiByteArray & mba, const std::string & st)
+{
+ /* note that this assumes that "st" is ASCII encoded
+ */
+
+ mba.insert (mba.end(), st.begin(), st.end());
+ return mba;
+}
diff --git a/libs/surfaces/push2/midi_byte_array.h b/libs/surfaces/push2/midi_byte_array.h
new file mode 100644
index 0000000000..3d3bcecd28
--- /dev/null
+++ b/libs/surfaces/push2/midi_byte_array.h
@@ -0,0 +1,76 @@
+/*
+ Copyright (C) 2006,2007 John Anderson
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#ifndef midi_byte_array_h
+#define midi_byte_array_h
+
+#include <iostream>
+#include <vector>
+
+#include <boost/shared_array.hpp>
+
+//#include <midi++/types.h>
+namespace MIDI {
+ typedef unsigned char byte;
+}
+
+/**
+ To make building arrays of bytes easier. Thusly:
+
+ MidiByteArray mba;
+ mba << 0xf0 << 0x00 << 0xf7;
+
+ MidiByteArray buf;
+ buf << mba;
+
+ MidiByteArray direct( 3, 0xf0, 0x00, 0xf7 );
+
+ cout << mba << endl;
+ cout << buf << endl;
+ cout << direct << endl;
+
+ will all result in "f0 00 f7" being output to stdout
+*/
+class MidiByteArray : public std::vector<MIDI::byte>
+{
+public:
+ MidiByteArray() : std::vector<MIDI::byte>() {}
+
+ MidiByteArray( size_t count, MIDI::byte array[] );
+
+ /**
+ Accepts a preceding count, and then a list of bytes
+ */
+ MidiByteArray( size_t count, MIDI::byte first, ... );
+
+ /// copy the given number of bytes from the given array
+ void copy( size_t count, MIDI::byte arr[] );
+};
+
+/// append the given byte to the end of the array
+MidiByteArray & operator << ( MidiByteArray & mba, const MIDI::byte & b );
+
+/// append the given string to the end of the array
+MidiByteArray & operator << ( MidiByteArray & mba, const std::string & );
+
+/// append the given array to the end of this array
+MidiByteArray & operator << ( MidiByteArray & mba, const MidiByteArray & barr );
+
+/// output the bytes as hex to the given stream
+std::ostream & operator << ( std::ostream & os, const MidiByteArray & mba );
+
+#endif
diff --git a/libs/surfaces/push2/push2.cc b/libs/surfaces/push2/push2.cc
index be25357e26..92e05cfee1 100644
--- a/libs/surfaces/push2/push2.cc
+++ b/libs/surfaces/push2/push2.cc
@@ -25,6 +25,9 @@
#include "pbd/failed_constructor.h"
#include "ardour/debug.h"
+#include "ardour/audioengine.h"
+#include "ardour/async_midi_port.h"
+#include "ardour/midiport_manager.h"
#include "push2.h"
@@ -52,6 +55,7 @@ Push2::Push2 (Session& s)
, device_buffer (0)
, frame_buffer (Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, cols, rows))
{
+ build_led_map ();
}
Push2::~Push2 ()
@@ -62,11 +66,15 @@ Push2::~Push2 ()
int
Push2::open ()
{
+ int err;
+
if ((handle = libusb_open_device_with_vid_pid (NULL, ABLETON, PUSH2)) == 0) {
return -1;
}
- libusb_claim_interface (handle, 0x00);
+ if ((err = libusb_claim_interface (handle, 0x00))) {
+ return -1;
+ }
device_frame_buffer[0] = new uint16_t[rows*pixels_per_row];
device_frame_buffer[1] = new uint16_t[rows*pixels_per_row];
@@ -80,12 +88,44 @@ Push2::open ()
frame_header[3] = 0x89;
memset (&frame_header[4], 0, 12);
+ /* setup ports */
+
+ _async_in[0] = AudioEngine::instance()->register_input_port (DataType::MIDI, X_("push2 in1"), true);
+ _async_out[0] = AudioEngine::instance()->register_output_port (DataType::MIDI, X_("push2 out1"), true);
+
+ if (_async_in[0] == 0 || _async_out[0] == 0) {
+ return -1;
+ }
+
+ _input_port[1] = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in[1]).get();
+ _output_port[1] = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_out[1]).get();
+
+ _async_in[1] = AudioEngine::instance()->register_input_port (DataType::MIDI, X_("push2 in2"), true);
+ _async_out[1] = AudioEngine::instance()->register_output_port (DataType::MIDI, X_("push2 out2"), true);
+
+ if (_async_in[1] == 0 || _async_out[1] == 0) {
+ return -1;
+ }
+
+ _input_port[1] = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in[1]).get();
+ _output_port[1] = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_out[1]).get();
+
return 0;
}
int
Push2::close ()
{
+ AudioEngine::instance()->unregister_port (_async_in[0]);
+ AudioEngine::instance()->unregister_port (_async_out[0]);
+ AudioEngine::instance()->unregister_port (_async_in[1]);
+ AudioEngine::instance()->unregister_port (_async_out[1]);
+
+ _async_in[0].reset ((ARDOUR::Port*) 0);
+ _async_out[0].reset ((ARDOUR::Port*) 0);
+ _async_in[1].reset ((ARDOUR::Port*) 0);
+ _async_out[1].reset ((ARDOUR::Port*) 0);
+
vblank_connection.disconnect ();
if (handle) {
@@ -303,3 +343,10 @@ Push2::set_active (bool yn)
return 0;
}
+
+void
+Push2::write (int port, const MidiByteArray& data)
+{
+ /* immediate delivery */
+ _output_port[port]->write (&data[0], data.size(), 0);
+}
diff --git a/libs/surfaces/push2/push2.h b/libs/surfaces/push2/push2.h
index fb301a62a7..1b8c948986 100644
--- a/libs/surfaces/push2/push2.h
+++ b/libs/surfaces/push2/push2.h
@@ -35,10 +35,22 @@
#include "ardour/types.h"
#include "control_protocol/control_protocol.h"
+#include "midi_byte_array.h"
+
namespace Cairo {
class ImageSurface;
}
+namespace MIDI {
+ class Parser;
+ class Port;
+}
+
+namespace ARDOUR {
+ class AsyncMIDIPort;
+ class Port;
+}
+
namespace ArdourSurface {
struct Push2Request : public BaseUI::BaseRequestObject {
@@ -78,6 +90,63 @@ class Push2 : public ARDOUR::ControlProtocol
int close ();
int render ();
bool vblank ();
+
+ struct LED
+ {
+ enum State {
+ Off,
+ OneShot24th,
+ OneShot16th,
+ OneShot8th,
+ OneShot4th,
+ OneShot2th,
+ Pulsing24th,
+ Pulsing16th,
+ Pulsing8th,
+ Pulsing4th,
+ Pulsing2th,
+ Blinking24th,
+ Blinking16th,
+ Blinking8th,
+ Blinking4th,
+ Blinking2th
+ };
+
+ enum Type {
+ Pad,
+ ColorButton,
+ WhiteButton,
+ TouchStrip,
+ };
+
+
+
+ uint8_t id;
+ Type type;
+ uint8_t extra;
+ uint8_t color_index;
+ uint8_t state;
+
+ LED (uint8_t i, Type t, uint8_t e) : id (i), type (t), extra (e), color_index (0), state (Off) {}
+ LED () : id (0), type (Pad), extra (0), color_index (0), state (Off) {}
+
+ MidiByteArray update ();
+
+ void set_color (uint8_t color_index);
+ void set_state (State state);
+ };
+
+ std::map<int,LED> leds;
+ void set_led_color (uint32_t id, uint8_t color_index);
+ void set_led_state (uint32_t id, LED::State);
+ void build_led_map ();
+
+ MIDI::Port* _input_port[2];
+ MIDI::Port* _output_port[2];
+ boost::shared_ptr<ARDOUR::Port> _async_in[2];
+ boost::shared_ptr<ARDOUR::Port> _async_out[2];
+
+ void write (int port, const MidiByteArray&);
};
diff --git a/libs/surfaces/push2/render.cc b/libs/surfaces/push2/render.cc
deleted file mode 100644
index 27a145df1d..0000000000
--- a/libs/surfaces/push2/render.cc
+++ /dev/null
@@ -1,4 +0,0 @@
-#include <libusb.h>
-#include <unistd.h>
-#include <assert.h>
-
diff --git a/libs/surfaces/push2/wscript b/libs/surfaces/push2/wscript
index 379f1199d7..b69a13ec0e 100644
--- a/libs/surfaces/push2/wscript
+++ b/libs/surfaces/push2/wscript
@@ -22,6 +22,8 @@ def build(bld):
obj.source = '''
push2.cc
interface.cc
+ midi_byte_array.cc
+ leds.cc
'''
obj.export_includes = ['.']
obj.defines = [ 'PACKAGE="ardour_push2"' ]