summaryrefslogtreecommitdiff
path: root/libs/surfaces/generic_midi
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2015-12-07 12:04:23 -0500
committerPaul Davis <paul@linuxaudiosystems.com>2015-12-07 12:38:17 -0500
commit3d79e3c116a13e455c0ea1083a25c81af9107764 (patch)
tree2acc1028523102bb82603c1b7243afab67abacf9 /libs/surfaces/generic_midi
parent2f48997dfbda7e89f9e4eabe27797321c896cb5b (diff)
adjust generic MIDI surface support to (1) properly use boost::shared_ptr<Port> (2) detect connection changes
Diffstat (limited to 'libs/surfaces/generic_midi')
-rw-r--r--libs/surfaces/generic_midi/generic_midi_control_protocol.cc80
-rw-r--r--libs/surfaces/generic_midi/generic_midi_control_protocol.h27
-rw-r--r--libs/surfaces/generic_midi/gmcp_gui.cc5
3 files changed, 101 insertions, 11 deletions
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
index 54bb65cb90..e319f65e1f 100644
--- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
+++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
@@ -34,6 +34,8 @@
#include "midi++/port.h"
+#include "ardour/async_midi_port.h"
+#include "ardour/audioengine.h"
#include "ardour/audioengine.h"
#include "ardour/filesystem_paths.h"
#include "ardour/session.h"
@@ -58,12 +60,13 @@ using namespace std;
GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
: ControlProtocol (s, _("Generic MIDI"))
+ , connection_state (ConnectionState (0))
, _motorised (false)
, _threshold (10)
, gui (0)
{
- _input_port = s.midi_input_port ();
- _output_port = s.midi_output_port ();
+ _input_port = boost::dynamic_pointer_cast<AsyncMIDIPort> (s.midi_input_port ());
+ _output_port = boost::dynamic_pointer_cast<AsyncMIDIPort> (s.midi_output_port ());
do_feedback = false;
_feedback_interval = 10000; // microseconds
@@ -94,6 +97,11 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
Route::RemoteControlIDChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context());
+ /* Catch port connections and disconnections (cross-thread) */
+ ARDOUR::AudioEngine::instance()->PortConnectedOrDisconnected.connect (port_connection, MISSING_INVALIDATOR,
+ boost::bind (&GenericMidiControlProtocol::connection_handler, this, _1, _2, _3, _4, _5),
+ midi_ui_context());
+
reload_maps ();
}
@@ -229,7 +237,9 @@ GenericMidiControlProtocol::drop_bindings ()
int
GenericMidiControlProtocol::set_active (bool /*yn*/)
{
- /* start/stop delivery/outbound thread */
+ /* nothing to do here: the MIDI UI thread in libardour handles all our
+ I/O needs.
+ */
return 0;
}
@@ -1137,3 +1147,67 @@ GenericMidiControlProtocol::set_threshold (int t)
{
_threshold = t;
}
+
+bool
+GenericMidiControlProtocol::connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn)
+{
+ if (!_input_port || !_output_port) {
+ return false;
+ }
+
+ string ni = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (boost::shared_ptr<ARDOUR::Port>(_input_port)->name());
+ string no = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (boost::shared_ptr<ARDOUR::Port>(_output_port)->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 {
+ /* not our ports */
+ return false;
+ }
+
+ 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);
+ connected ();
+
+ } else {
+
+ }
+
+ ConnectionChange (); /* emit signal for our GUI */
+
+ return true; /* connection status changed */
+}
+
+void
+GenericMidiControlProtocol::connected ()
+{
+ cerr << "Now connected\n";
+}
+
+boost::shared_ptr<Port>
+GenericMidiControlProtocol::output_port() const
+{
+ return _output_port;
+}
+
+boost::shared_ptr<Port>
+GenericMidiControlProtocol::input_port() const
+{
+ return _input_port;
+}
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.h b/libs/surfaces/generic_midi/generic_midi_control_protocol.h
index 9d51efc97d..a453716e95 100644
--- a/libs/surfaces/generic_midi/generic_midi_control_protocol.h
+++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.h
@@ -34,8 +34,9 @@ namespace PBD {
}
namespace ARDOUR {
- class Session;
+ class AsyncMIDIPort;
class MidiPort;
+ class Session;
}
namespace MIDI {
@@ -54,9 +55,9 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
int set_active (bool yn);
static bool probe() { return true; }
- ARDOUR::Port* input_port () const { return ((ARDOUR::Port*) _input_port); }
- ARDOUR::Port* output_port () const { return ((ARDOUR::Port*) _output_port); }
-
+ boost::shared_ptr<ARDOUR::Port> input_port () const;
+ boost::shared_ptr<ARDOUR::Port> output_port () const;
+
void set_feedback_interval (ARDOUR::microseconds_t);
int set_feedback (bool yn);
@@ -103,9 +104,11 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
}
PBD::Signal0<void> ConnectionChange;
+
private:
- MIDI::Port* _input_port;
- MIDI::Port* _output_port;
+ boost::shared_ptr<ARDOUR::AsyncMIDIPort> _input_port;
+ boost::shared_ptr<ARDOUR::AsyncMIDIPort> _output_port;
+
ARDOUR::microseconds_t _feedback_interval;
ARDOUR::microseconds_t last_feedback_time;
@@ -143,6 +146,16 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
void reset_controllables ();
void drop_all ();
+ 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::ScopedConnection port_connection;
+ void connected();
+
std::string _current_binding;
uint32_t _bank_size;
uint32_t _current_bank;
@@ -156,6 +169,8 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
mutable void *gui;
void build_gui ();
+
+
};
#endif /* ardour_generic_midi_control_protocol_h */
diff --git a/libs/surfaces/generic_midi/gmcp_gui.cc b/libs/surfaces/generic_midi/gmcp_gui.cc
index 427ed1d327..8e861b370d 100644
--- a/libs/surfaces/generic_midi/gmcp_gui.cc
+++ b/libs/surfaces/generic_midi/gmcp_gui.cc
@@ -65,7 +65,7 @@ private:
void bank_changed ();
void motorised_changed ();
void threshold_changed ();
-
+
void update_port_combos ();
PBD::ScopedConnection connection_change_connection;
void connection_handler ();
@@ -131,6 +131,7 @@ GMCPGUI::GMCPGUI (GenericMidiControlProtocol& p)
, motorised_button ("Motorised")
, threshold_adjustment (p.threshold(), 1, 127, 1, 10)
, threshold_spinner (threshold_adjustment)
+ , ignore_active_change (false)
{
vector<string> popdowns;
popdowns.push_back (_("Reset All"));
@@ -179,7 +180,7 @@ GMCPGUI::GMCPGUI (GenericMidiControlProtocol& p)
table->attach (*label, 0, 1, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
table->attach (output_combo, 1, 2, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
n++;
-
+
//MIDI binding file selector...
label = manage (new Label (_("MIDI Bindings:")));
label->set_alignment (0, 0.5);