--- /dev/null
+#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)));
+}
--- /dev/null
+/*
+ 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;
+}
--- /dev/null
+/*
+ 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
#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"
, device_buffer (0)
, frame_buffer (Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, cols, rows))
{
+ build_led_map ();
}
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];
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) {
return 0;
}
+
+void
+Push2::write (int port, const MidiByteArray& data)
+{
+ /* immediate delivery */
+ _output_port[port]->write (&data[0], data.size(), 0);
+}