surfaces; convert push2 to inherit from MIDISurface

This commit is contained in:
Paul Davis 2022-10-14 13:56:00 -06:00
parent 4fbf3028aa
commit 99712e7585
7 changed files with 55 additions and 412 deletions

View File

@ -87,6 +87,7 @@ namespace PBD {
LIBARDOUR_API extern DebugBits ProcessThreads;
LIBARDOUR_API extern DebugBits Processors;
LIBARDOUR_API extern DebugBits Push2;
LIBARDOUR_API extern DebugBits MIDISurface;
LIBARDOUR_API extern DebugBits Selection;
LIBARDOUR_API extern DebugBits SessionEvents;
LIBARDOUR_API extern DebugBits Slave;

View File

@ -82,6 +82,7 @@ PBD::DebugBits PBD::DEBUG::Ports = PBD::new_debug_bit ("Ports");
PBD::DebugBits PBD::DEBUG::ProcessThreads = PBD::new_debug_bit ("processthreads");
PBD::DebugBits PBD::DEBUG::Processors = PBD::new_debug_bit ("processors");
PBD::DebugBits PBD::DEBUG::Push2 = PBD::new_debug_bit ("push2");
PBD::DebugBits PBD::DEBUG::MIDISurface = PBD::new_debug_bit ("midisurface");
PBD::DebugBits PBD::DEBUG::Selection = PBD::new_debug_bit ("selection");
PBD::DebugBits PBD::DEBUG::SessionEvents = PBD::new_debug_bit ("sessionevents");
PBD::DebugBits PBD::DEBUG::Slave = PBD::new_debug_bit ("slave");

View File

@ -33,11 +33,13 @@ using namespace ARDOUR;
using namespace Glib;
using namespace PBD;
MIDISurface::MIDISurface (ARDOUR::Session& s, std::string const & namestr, bool use_pad_filter)
MIDISurface::MIDISurface (ARDOUR::Session& s, std::string const & namestr, std::string const & port_prefix, bool use_pad_filter)
: ControlProtocol (s, namestr)
, AbstractUI<MidiSurfaceRequest> (namestr)
, with_pad_filter (use_pad_filter)
, _in_use (false)
, port_name_prefix (port_prefix)
, _connection_state (ConnectionState (0))
{
ARDOUR::AudioEngine::instance()->PortRegisteredOrUnregistered.connect (port_connections, MISSING_INVALIDATOR, boost::bind (&MIDISurface::port_registration_handler, this), this);
@ -52,8 +54,8 @@ MIDISurface::ports_acquire ()
/* setup ports */
_async_in = AudioEngine::instance()->register_input_port (DataType::MIDI, X_("Push 2 in"), true);
_async_out = AudioEngine::instance()->register_output_port (DataType::MIDI, X_("Push 2 out"), true);
_async_in = AudioEngine::instance()->register_input_port (DataType::MIDI, string_compose (X_("%1 in"), port_name_prefix), true);
_async_out = AudioEngine::instance()->register_output_port (DataType::MIDI, string_compose (X_("%1 out"), port_name_prefix), true);
if (_async_in == 0 || _async_out == 0) {
DEBUG_TRACE (DEBUG::MIDISurface, "cannot register ports\n");
@ -74,7 +76,7 @@ MIDISurface::ports_acquire ()
*/
if (with_pad_filter) {
boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in)->add_shadow_port (string_compose (_("%1 Pads"), X_("Push 2")), boost::bind (&MIDISurface::pad_filter, this, _1, _2));
boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in)->add_shadow_port (string_compose (_("%1 Pads"), port_name_prefix), boost::bind (&MIDISurface::pad_filter, this, _1, _2));
boost::shared_ptr<MidiPort> shadow_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in)->shadow_port();
if (shadow_port) {
@ -378,12 +380,25 @@ int
MIDISurface::begin_using_device ()
{
_in_use = true;
connect_session_signals ();
return 0;
}
int
MIDISurface::stop_using_device ()
{
session_connections.drop_connections ();
_in_use = false;
return 0;
}
void
MIDISurface::drop ()
{
/* do this before stopping the event loop, so that we don't get any notifications */
port_connections.drop_connections ();
stop_using_device ();
device_release ();
ports_release ();
}

View File

@ -44,7 +44,7 @@ class MIDISurface : public ARDOUR::ControlProtocol
, public AbstractUI<MidiSurfaceRequest>
{
public:
MIDISurface (ARDOUR::Session&, std::string const & name, bool use_pad_filter);
MIDISurface (ARDOUR::Session&, std::string const & name, std::string const & port_name_prefix, bool use_pad_filter);
~MIDISurface ();
boost::shared_ptr<ARDOUR::Port> input_port();
@ -71,9 +71,10 @@ class MIDISurface : public ARDOUR::ControlProtocol
CONTROL_PROTOCOL_THREADS_NEED_TEMPO_MAP_DECL();
private:
protected:
bool with_pad_filter;
bool _in_use;
std::string port_name_prefix;
MIDI::Port* _input_port;
MIDI::Port* _output_port;
@ -122,4 +123,6 @@ class MIDISurface : public ARDOUR::ControlProtocol
virtual int stop_using_device ();
virtual int device_acquire () = 0;
virtual void device_release () = 0;
void drop ();
};

View File

@ -97,15 +97,12 @@ row_interval_semitones (const Push2::RowInterval row_interval, const bool inkey)
}
Push2::Push2 (ARDOUR::Session& s)
: ControlProtocol (s, std::string (X_("Ableton Push 2")))
, AbstractUI<Push2Request> (name())
: MIDISurface (s, X_("Ableton Push 2"), X_("Push 2"), true)
, _handle (0)
, _in_use (false)
, _modifier_state (None)
, _splash_start (0)
, _current_layout (0)
, _previous_layout (0)
, _connection_state (ConnectionState (0))
, _gui (0)
, _mode (MusicalMode::IonianMajor)
, _row_interval (Fourth)
@ -141,31 +138,13 @@ Push2::Push2 (ARDOUR::Session& s)
_splash_layout = new SplashLayout (*this, *session, "splash");
run_event_loop ();
/* Ports exist for the life of this instance */
ports_acquire ();
/* catch arrival and departure of Push2 itself */
ARDOUR::AudioEngine::instance()->PortRegisteredOrUnregistered.connect (port_connections, MISSING_INVALIDATOR, boost::bind (&Push2::port_registration_handler, this), this);
/* Catch port connections and disconnections */
ARDOUR::AudioEngine::instance()->PortConnectedOrDisconnected.connect (port_connections, MISSING_INVALIDATOR, boost::bind (&Push2::connection_handler, this, _1, _2, _3, _4, _5), this);
/* Push 2 ports might already be there */
port_registration_handler ();
}
Push2::~Push2 ()
{
DEBUG_TRACE (DEBUG::Push2, "push2 control surface object being destroyed\n");
/* do this before stopping the event loop, so that we don't get any notifications */
port_connections.drop_connections ();
stop_using_device ();
device_release ();
ports_release ();
MIDISurface::drop ();
if (_current_layout) {
_canvas->root()->remove (_current_layout);
@ -206,6 +185,7 @@ Push2::begin_using_device ()
{
DEBUG_TRACE (DEBUG::Push2, "begin using device\n");
/* set up periodic task used to push a frame buffer to the
* device (25fps). The device can handle 60fps, but we don't
* need that frame rate.
@ -215,8 +195,6 @@ Push2::begin_using_device ()
_vblank_connection = vblank_timeout->connect (sigc::mem_fun (*this, &Push2::vblank));
vblank_timeout->attach (main_loop()->get_context());
connect_session_signals ();
init_buttons (true);
init_touch_strip ();
reset_pad_colors ();
@ -227,9 +205,7 @@ Push2::begin_using_device ()
request_pressure_mode ();
_in_use = true;
return 0;
return MIDISurface::begin_using_device ();
}
int
@ -252,89 +228,8 @@ Push2::stop_using_device ()
}
_vblank_connection.disconnect ();
session_connections.drop_connections ();
_in_use = false;
return 0;
}
int
Push2::ports_acquire ()
{
DEBUG_TRACE (DEBUG::Push2, "acquiring ports\n");
/* setup ports */
_async_in = AudioEngine::instance()->register_input_port (DataType::MIDI, X_("Push 2 in"), true);
_async_out = AudioEngine::instance()->register_output_port (DataType::MIDI, X_("Push 2 out"), true);
if (_async_in == 0 || _async_out == 0) {
DEBUG_TRACE (DEBUG::Push2, "cannot register ports\n");
return -1;
}
/* We do not add our ports to the input/output bundles because we don't
* want users wiring them by hand. They could use JACK tools if they
* really insist on that (and use JACK)
*/
_input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in).get();
_output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_out).get();
/* Create a shadow port where, depending on the state of the surface,
* we will make pad note on/off events appear. The surface code will
* automatically this port to the first selected MIDI track.
*/
boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in)->add_shadow_port (string_compose (_("%1 Pads"), X_("Push 2")), boost::bind (&Push2::pad_filter, this, _1, _2));
boost::shared_ptr<MidiPort> shadow_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in)->shadow_port();
if (shadow_port) {
_output_bundle.reset (new ARDOUR::Bundle (_("Push 2 Pads"), false));
_output_bundle->add_channel (
shadow_port->name(),
ARDOUR::DataType::MIDI,
session->engine().make_port_name_non_relative (shadow_port->name())
);
}
session->BundleAddedOrRemoved ();
connect_to_parser ();
/* Connect input port to event loop */
AsyncMIDIPort* asp;
asp = dynamic_cast<AsyncMIDIPort*> (_input_port);
asp->xthread().set_receive_handler (sigc::bind (sigc::mem_fun (this, &Push2::midi_input_handler), _input_port));
asp->xthread().attach (main_loop()->get_context());
return 0;
}
void
Push2::ports_release ()
{
DEBUG_TRACE (DEBUG::Push2, "releasing ports\n");
/* wait for button data to be flushed */
AsyncMIDIPort* asp;
asp = dynamic_cast<AsyncMIDIPort*> (_output_port);
asp->drain (10000, 500000);
{
Glib::Threads::Mutex::Lock em (AudioEngine::instance()->process_lock());
AudioEngine::instance()->unregister_port (_async_in);
AudioEngine::instance()->unregister_port (_async_out);
}
_async_in.reset ((ARDOUR::Port*) 0);
_async_out.reset ((ARDOUR::Port*) 0);
_input_port = 0;
_output_port = 0;
return MIDISurface::stop_using_device ();
}
int
@ -369,6 +264,7 @@ void
Push2::device_release ()
{
DEBUG_TRACE (DEBUG::Push2, "releasing device\n");
if (_handle) {
libusb_release_interface (_handle, 0x00);
libusb_close (_handle);
@ -376,18 +272,6 @@ Push2::device_release ()
}
}
list<boost::shared_ptr<ARDOUR::Bundle> >
Push2::bundles ()
{
list<boost::shared_ptr<ARDOUR::Bundle> > b;
if (_output_bundle) {
b.push_back (_output_bundle);
}
return b;
}
void
Push2::strip_buttons_off ()
{
@ -474,19 +358,6 @@ Push2::request_factory (uint32_t num_requests)
return request_buffer_factory (num_requests);
}
void
Push2::do_request (Push2Request * req)
{
if (req->type == CallSlot) {
call_slot (MISSING_INVALIDATOR, req->the_slot);
} else if (req->type == Quit) {
stop_using_device ();
}
}
void
Push2::splash ()
{
@ -566,59 +437,6 @@ Push2::init_touch_strip ()
write (msg);
}
void
Push2::write (const MidiByteArray& data)
{
/* immediate delivery */
_output_port->write (&data[0], data.size(), 0);
}
bool
Push2::midi_input_handler (IOCondition ioc, MIDI::Port* port)
{
if (ioc & ~IO_IN) {
DEBUG_TRACE (DEBUG::Push2, "MIDI port closed\n");
return false;
}
if (ioc & IO_IN) {
DEBUG_TRACE (DEBUG::Push2, string_compose ("something happened on %1\n", port->name()));
AsyncMIDIPort* asp = dynamic_cast<AsyncMIDIPort*>(port);
if (asp) {
asp->clear ();
}
DEBUG_TRACE (DEBUG::Push2, string_compose ("data available on %1\n", port->name()));
if (_in_use) {
samplepos_t now = AudioEngine::instance()->sample_time();
port->parse (now);
}
}
return true;
}
void
Push2::connect_to_parser ()
{
DEBUG_TRACE (DEBUG::Push2, string_compose ("Connecting to signals on port %2\n", _input_port->name()));
MIDI::Parser* p = _input_port->parser();
/* Incoming sysex */
p->sysex.connect_same_thread (*this, boost::bind (&Push2::handle_midi_sysex, this, _1, _2, _3));
/* V-Pot messages are Controller */
p->controller.connect_same_thread (*this, boost::bind (&Push2::handle_midi_controller_message, this, _1, _2));
/* Button messages are NoteOn */
p->note_on.connect_same_thread (*this, boost::bind (&Push2::handle_midi_note_on_message, this, _1, _2));
/* Button messages are NoteOn but libmidi++ sends note-on w/velocity = 0 as note-off so catch them too */
p->note_off.connect_same_thread (*this, boost::bind (&Push2::handle_midi_note_on_message, this, _1, _2));
/* Fader messages are Pitchbend */
p->channel_pitchbend[0].connect_same_thread (*this, boost::bind (&Push2::handle_midi_pitchbend_message, this, _1, _2));
}
void
Push2::handle_midi_sysex (MIDI::Parser&, MIDI::byte* raw_bytes, size_t sz)
{
@ -884,37 +702,6 @@ Push2::handle_midi_pitchbend_message (MIDI::Parser&, MIDI::pitchbend_t pb)
{
}
void
Push2::thread_init ()
{
pthread_set_name (event_loop_name().c_str());
PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048);
ARDOUR::SessionEvent::create_per_thread_pool (event_loop_name(), 128);
set_thread_priority ();
}
void
Push2::connect_session_signals()
{
// receive routes added
//session->RouteAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_routes_added, this, _1), this);
// receive VCAs added
//session->vca_manager().VCAAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_vca_added, this, _1), this);
// receive record state toggled
session->RecordStateChanged.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_record_state_changed, this), this);
// receive transport state changed
session->TransportStateChange.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_transport_state_changed, this), this);
session->TransportLooped.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_loop_state_changed, this), this);
// receive punch-in and punch-out
Config->ParameterChanged.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_parameter_changed, this, _1), this);
session->config.ParameterChanged.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_parameter_changed, this, _1), this);
// receive rude solo changed
session->SoloActive.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_solo_active_changed, this, _1), this);
}
void
Push2::notify_record_state_changed ()
{
@ -1014,15 +801,7 @@ Push2::notify_solo_active_changed (bool yn)
XMLNode&
Push2::get_state() const
{
XMLNode& node (ControlProtocol::get_state());
XMLNode* child;
child = new XMLNode (X_("Input"));
child->add_child_nocopy (_async_in->get_state());
node.add_child_nocopy (*child);
child = new XMLNode (X_("Output"));
child->add_child_nocopy (_async_out->get_state());
node.add_child_nocopy (*child);
XMLNode& node (MIDISurface::get_state());
node.set_property (X_("root"), _scale_root);
node.set_property (X_("root-octave"), _root_octave);
@ -1039,28 +818,10 @@ Push2::set_state (const XMLNode & node, int version)
int retval = 0;
if (ControlProtocol::set_state (node, version)) {
if (MIDISurface::set_state (node, version)) {
return -1;
}
XMLNode* child;
if ((child = node.child (X_("Input"))) != 0) {
XMLNode* portnode = child->child (Port::state_node_name.c_str());
if (portnode) {
portnode->remove_property ("name");
_async_in->set_state (*portnode, version);
}
}
if ((child = node.child (X_("Output"))) != 0) {
XMLNode* portnode = child->child (Port::state_node_name.c_str());
if (portnode) {
portnode->remove_property ("name");
_async_out->set_state (*portnode, version);
}
}
node.get_property (X_("root"), _scale_root);
node.get_property (X_("root-octave"), _root_octave);
node.get_property (X_("in-key"), _in_key);
@ -1199,117 +960,30 @@ Push2::pad_filter (MidiBuffer& in, MidiBuffer& out) const
return matched;
}
void
Push2::port_registration_handler ()
std::string
Push2::input_port_name () const
{
if (!_async_in || !_async_out) {
/* ports not registered yet */
return;
}
if (_async_in->connected() && _async_out->connected()) {
/* don't waste cycles here */
return;
}
#ifdef __APPLE__
/* the origin of the numeric magic identifiers is known only to Ableton
and may change in time. This is part of how CoreMIDI works.
*/
std::string input_port_name = X_("system:midi_capture_1319078870");
std::string output_port_name = X_("system:midi_playback_3409210341");
return X_("system:midi_capture_1319078870");
#else
std::string input_port_name = X_("Ableton Push 2 MIDI 1 in");
std::string output_port_name = X_("Ableton Push 2 MIDI 1 out");
return X_("Ableton Push 2 MIDI 1 in");
#endif
std::vector<std::string> in;
std::vector<std::string> out;
AudioEngine::instance()->get_ports (string_compose (".*%1", input_port_name), DataType::MIDI, PortFlags (IsPhysical|IsOutput), in);
AudioEngine::instance()->get_ports (string_compose (".*%1", output_port_name), DataType::MIDI, PortFlags (IsPhysical|IsInput), out);
if (!in.empty() && !out.empty()) {
if (!_async_in->connected()) {
AudioEngine::instance()->connect (_async_in->name(), in.front());
}
if (!_async_out->connected()) {
AudioEngine::instance()->connect (_async_out->name(), out.front());
}
}
}
bool
Push2::connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn)
std::string
Push2::output_port_name () const
{
DEBUG_TRACE (DEBUG::FaderPort, "FaderPort::connection_handler start\n");
if (!_input_port || !_output_port) {
return false;
}
std::string ni = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (boost::shared_ptr<ARDOUR::Port>(_async_in)->name());
std::string no = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (boost::shared_ptr<ARDOUR::Port>(_async_out)->name());
if (ni == name1 || ni == name2) {
if (yn) {
_connection_state |= InputConnected;
} else {
_connection_state &= ~InputConnected;
}
} else if (no == name1 || no == name2) {
if (yn) {
_connection_state |= OutputConnected;
} else {
_connection_state &= ~OutputConnected;
}
} else {
DEBUG_TRACE (DEBUG::Push2, string_compose ("Connections between %1 and %2 changed, but I ignored it\n", name1, name2));
/* not our ports */
return false;
}
DEBUG_TRACE (DEBUG::Push2, string_compose ("our ports changed connection state: %1 -> %2 connected ? %3\n",
name1, name2, yn));
if ((_connection_state & (InputConnected|OutputConnected)) == (InputConnected|OutputConnected)) {
/* XXX this is a horrible hack. Without a short sleep here,
something prevents the device wakeup messages from being
sent and/or the responses from being received.
*/
g_usleep (100000);
DEBUG_TRACE (DEBUG::Push2, "device now connected for both input and output\n");
/* may not have the device open if it was just plugged
in. Really need USB device detection rather than MIDI port
detection for this to work well.
*/
device_acquire ();
begin_using_device ();
} else {
DEBUG_TRACE (DEBUG::FaderPort, "Device disconnected (input or output or both) or not yet fully connected\n");
stop_using_device ();
}
ConnectionChange (); /* emit signal for our GUI */
DEBUG_TRACE (DEBUG::FaderPort, "FaderPort::connection_handler end\n");
return true; /* connection status changed */
}
boost::shared_ptr<Port>
Push2::output_port()
{
return _async_out;
}
boost::shared_ptr<Port>
Push2::input_port()
{
return _async_in;
#ifdef __APPLE__
/* the origin of the numeric magic identifiers is known only to Ableton
and may change in time. This is part of how CoreMIDI works.
*/
return X_("system:midi_playback_3409210341");
#else
return X_("Ableton Push 2 MIDI 1 out");
#endif
}
int

View File

@ -40,7 +40,8 @@
#include "gtkmm2ext/colors.h"
#include "midi_byte_array.h"
#include "midi_surface/midi_byte_array.h"
#include "midi_surface/midi_surface.h"
namespace MIDI {
class Parser;
@ -55,18 +56,11 @@ namespace ARDOUR {
namespace ArdourSurface {
struct Push2Request : public BaseUI::BaseRequestObject {
public:
Push2Request () {}
~Push2Request () {}
};
class P2GUI;
class Push2Layout;
class Push2Canvas;
class Push2 : public ARDOUR::ControlProtocol
, public AbstractUI<Push2Request>
class Push2 : public MIDISurface
{
public:
enum ButtonID {
@ -305,7 +299,8 @@ class Push2 : public ARDOUR::ControlProtocol
static bool probe ();
static void* request_factory (uint32_t);
std::list<boost::shared_ptr<ARDOUR::Bundle> > bundles ();
std::string input_port_name () const;
std::string output_port_name () const;
bool has_editor () const { return true; }
void* get_gui () const;
@ -315,11 +310,6 @@ class Push2 : public ARDOUR::ControlProtocol
XMLNode& get_state() const;
int set_state (const XMLNode & node, int version);
PBD::Signal0<void> ConnectionChange;
boost::shared_ptr<ARDOUR::Port> input_port();
boost::shared_ptr<ARDOUR::Port> output_port();
int pad_note (int row, int col) const;
PBD::Signal0<void> PadChange;
@ -438,8 +428,6 @@ class Push2 : public ARDOUR::ControlProtocol
void strip_buttons_off ();
void write (const MidiByteArray&);
uint8_t get_color_index (Gtkmm2ext::Color rgba);
Gtkmm2ext::Color get_color (ColorName);
@ -449,8 +437,6 @@ class Push2 : public ARDOUR::ControlProtocol
libusb_device_handle* usb_handle() const { return _handle; }
ARDOUR::Session & get_session() { return *session; }
bool stop_down () const { return _stop_down; }
typedef std::map<int,boost::shared_ptr<Pad> > PadMap;
@ -459,21 +445,14 @@ class Push2 : public ARDOUR::ControlProtocol
boost::shared_ptr<Pad> pad_by_xy (int x, int y);
boost::shared_ptr<Button> lower_button_by_column (uint32_t col);
CONTROL_PROTOCOL_THREADS_NEED_TEMPO_MAP_DECL();
private:
libusb_device_handle* _handle;
bool _in_use;
ModifierState _modifier_state;
void do_request (Push2Request*);
int begin_using_device ();
int stop_using_device ();
int device_acquire ();
void device_release ();
int ports_acquire ();
void ports_release ();
void run_event_loop ();
void stop_event_loop ();
@ -515,29 +494,12 @@ class Push2 : public ARDOUR::ControlProtocol
void build_maps ();
// Bundle to represent our input ports
boost::shared_ptr<ARDOUR::Bundle> _input_bundle;
// Bundle to represent our output ports
boost::shared_ptr<ARDOUR::Bundle> _output_bundle;
MIDI::Port* _input_port;
MIDI::Port* _output_port;
boost::shared_ptr<ARDOUR::Port> _async_in;
boost::shared_ptr<ARDOUR::Port> _async_out;
void connect_to_parser ();
void handle_midi_pitchbend_message (MIDI::Parser&, MIDI::pitchbend_t);
void handle_midi_controller_message (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);
bool midi_input_handler (Glib::IOCondition ioc, MIDI::Port* port);
void thread_init ();
PBD::ScopedConnectionList session_connections;
void connect_session_signals ();
void notify_record_state_changed ();
void notify_transport_state_changed ();
void notify_loop_state_changed ();
@ -649,19 +611,6 @@ class Push2 : public ARDOUR::ControlProtocol
boost::weak_ptr<ARDOUR::MidiTrack> _current_pad_target;
void port_registration_handler ();
enum ConnectionState {
InputConnected = 0x1,
OutputConnected = 0x2
};
int _connection_state;
bool connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn);
PBD::ScopedConnectionList port_connections;
void connected ();
/* GUI */
mutable P2GUI* _gui;

View File

@ -38,11 +38,11 @@ def build(bld):
obj.defines = [ 'PACKAGE="ardour_push2"' ]
obj.defines += [ 'ARDOURSURFACE_DLL_EXPORTS' ]
obj.defines += [ 'VERSIONSTRING="' + bld.env['VERSION'] + '"' ]
obj.includes = ['.', './push2']
obj.includes = ['.', '..', './push2']
obj.name = 'libardour_push2'
obj.target = 'ardour_push2'
obj.uselib = 'CAIROMM PANGOMM USB GTKMM SIGCPP XML OSX'
obj.use = 'libardour libardour_cp libgtkmm2ext libpbd libevoral libcanvas libtemporal'
obj.use = 'libardour libardour_cp lib_midisurface libgtkmm2ext libpbd libevoral libcanvas libtemporal'
obj.install_path = os.path.join(bld.env['LIBDIR'], 'surfaces')
def shutdown():