summaryrefslogtreecommitdiff
path: root/libs/surfaces/generic_midi
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2006-07-10 20:01:47 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2006-07-10 20:01:47 +0000
commit26843b34fdd62e6f80630868c5eb3f8fee0c17f1 (patch)
treefe4001528aa6e4e360ec6392c7b1120ca75e0aa9 /libs/surfaces/generic_midi
parent05f8fcd189ca714c2c18b9fb174d5813140849df (diff)
modification to make generic MIDI actually work again
git-svn-id: svn://localhost/ardour2/trunk@673 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/surfaces/generic_midi')
-rw-r--r--libs/surfaces/generic_midi/generic_midi_control_protocol.cc87
-rw-r--r--libs/surfaces/generic_midi/generic_midi_control_protocol.h7
-rw-r--r--libs/surfaces/generic_midi/interface.cc10
-rw-r--r--libs/surfaces/generic_midi/midicontrollable.cc3
-rw-r--r--libs/surfaces/generic_midi/midicontrollable.h3
5 files changed, 96 insertions, 14 deletions
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
index dec891703e..d905c0bc41 100644
--- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
+++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
@@ -20,6 +20,9 @@
#include <algorithm>
+#include <pbd/error.h>
+#include <pbd/failed_constructor.h>
+
#include <midi++/port.h>
#include <midi++/manager.h>
#include <midi++/port_request.h>
@@ -39,9 +42,17 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
: ControlProtocol (s, _("GenericMIDI"))
{
MIDI::Manager* mm = MIDI::Manager::instance();
- MIDI::PortRequest pr ("ardour:MIDI control", "ardour:MIDI control", "duplex", "alsa/seq");
+
+ /* XXX it might be nice to run "control" through i18n, but thats a bit tricky because
+ the name is defined in ardour.rc which is likely not internationalized.
+ */
- _port = mm->add_port (pr);
+ _port = mm->port (X_("control"));
+
+ if (_port == 0) {
+ error << _("no MIDI port named \"control\" exists - generic MIDI control disabled") << endmsg;
+ throw failed_constructor();
+ }
_feedback_interval = 10000; // microseconds
last_feedback_time = 0;
@@ -112,11 +123,13 @@ GenericMidiControlProtocol::start_learning (Controllable* c)
MIDIControllable* mc = new MIDIControllable (*_port, *c);
-
{
Glib::Mutex::Lock lm (pending_lock);
- pending_controllables.push_back (mc);
- mc->learning_stopped.connect (bind (mem_fun (*this, &GenericMidiControlProtocol::learning_stopped), mc));
+ std::pair<MIDIControllables::iterator,bool> result;
+ result = pending_controllables.insert (mc);
+ if (result.second) {
+ c->LearningFinished.connect (bind (mem_fun (*this, &GenericMidiControlProtocol::learning_stopped), mc));
+ }
}
mc->learn_about_external_control ();
@@ -135,7 +148,7 @@ GenericMidiControlProtocol::learning_stopped (MIDIControllable* mc)
pending_controllables.erase (i);
}
- controllables.push_back (mc);
+ controllables.insert (mc);
}
void
@@ -156,3 +169,65 @@ GenericMidiControlProtocol::stop_learning (Controllable* c)
}
}
}
+
+XMLNode&
+GenericMidiControlProtocol::get_state ()
+{
+ XMLNode* node = new XMLNode (_name); /* node name must match protocol name */
+ XMLNode* children = new XMLNode (X_("controls"));
+
+ node->add_child_nocopy (*children);
+
+ Glib::Mutex::Lock lm2 (controllables_lock);
+ for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
+ children->add_child_nocopy ((*i)->get_state());
+ }
+
+ return *node;
+}
+
+int
+GenericMidiControlProtocol::set_state (const XMLNode& node)
+{
+ XMLNodeList nlist;
+ XMLNodeConstIterator niter;
+ Controllable* c;
+
+ {
+ Glib::Mutex::Lock lm (pending_lock);
+ pending_controllables.clear ();
+ }
+
+ Glib::Mutex::Lock lm2 (controllables_lock);
+
+ controllables.clear ();
+
+ nlist = node.children();
+
+ if (nlist.empty()) {
+ return 0;
+ }
+
+ nlist = nlist.front()->children ();
+
+ for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+
+ XMLProperty* prop;
+
+ if ((prop = (*niter)->property ("id")) != 0) {
+
+ ID id = prop->value ();
+
+ c = session->controllable_by_id (id);
+
+ if (c) {
+ MIDIControllable* mc = new MIDIControllable (*_port, *c);
+ if (mc->set_state (**niter) == 0) {
+ controllables.insert (mc);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.h b/libs/surfaces/generic_midi/generic_midi_control_protocol.h
index f86f5f6434..5f5a470b13 100644
--- a/libs/surfaces/generic_midi/generic_midi_control_protocol.h
+++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.h
@@ -1,7 +1,7 @@
#ifndef ardour_generic_midi_control_protocol_h
#define ardour_generic_midi_control_protocol_h
-#include <vector>
+#include <set>
#include <glibmm/thread.h>
#include <ardour/types.h>
@@ -32,6 +32,9 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
MIDI::Port* port () const { return _port; }
void set_feedback_interval (ARDOUR::microseconds_t);
+ XMLNode& get_state ();
+ int set_state (const XMLNode&);
+
private:
MIDI::Port* _port;
ARDOUR::microseconds_t _feedback_interval;
@@ -40,7 +43,7 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
void _send_feedback ();
void send_feedback ();
- typedef std::vector<MIDIControllable*> MIDIControllables;
+ typedef std::set<MIDIControllable*> MIDIControllables;
MIDIControllables controllables;
MIDIControllables pending_controllables;
Glib::Mutex controllables_lock;
diff --git a/libs/surfaces/generic_midi/interface.cc b/libs/surfaces/generic_midi/interface.cc
index c6c59c6589..230be694f2 100644
--- a/libs/surfaces/generic_midi/interface.cc
+++ b/libs/surfaces/generic_midi/interface.cc
@@ -1,3 +1,5 @@
+#include <pbd/failed_constructor.h>
+
#include <control_protocol/control_protocol.h>
#include "generic_midi_control_protocol.h"
@@ -6,7 +8,13 @@ using namespace ARDOUR;
ControlProtocol*
new_generic_midi_protocol (ControlProtocolDescriptor* descriptor, Session* s)
{
- GenericMidiControlProtocol* gmcp = new GenericMidiControlProtocol (*s);
+ GenericMidiControlProtocol* gmcp;
+
+ try {
+ gmcp = new GenericMidiControlProtocol (*s);
+ } catch (failed_constructor& err) {
+ return 0;
+ }
if (gmcp->set_active (true)) {
delete gmcp;
diff --git a/libs/surfaces/generic_midi/midicontrollable.cc b/libs/surfaces/generic_midi/midicontrollable.cc
index f4b7ef665b..d6135fd2a8 100644
--- a/libs/surfaces/generic_midi/midicontrollable.cc
+++ b/libs/surfaces/generic_midi/midicontrollable.cc
@@ -90,7 +90,6 @@ MIDIControllable::learn_about_external_control ()
{
drop_external_control ();
midi_learn_connection = _port.input()->any.connect (mem_fun (*this, &MIDIControllable::midi_receiver));
- learning_started ();
}
void
@@ -199,7 +198,7 @@ MIDIControllable::midi_receiver (Parser &p, byte *msg, size_t len)
bind_midi ((channel_t) (msg[0] & 0xf), eventType (msg[0] & 0xF0), msg[1]);
- learning_stopped ();
+ controllable.LearningFinished ();
}
void
diff --git a/libs/surfaces/generic_midi/midicontrollable.h b/libs/surfaces/generic_midi/midicontrollable.h
index 7dd0be1d87..ab15f9f4ab 100644
--- a/libs/surfaces/generic_midi/midicontrollable.h
+++ b/libs/surfaces/generic_midi/midicontrollable.h
@@ -53,9 +53,6 @@ class MIDIControllable : public Stateful
void stop_learning ();
void drop_external_control ();
- sigc::signal<void> learning_started;
- sigc::signal<void> learning_stopped;
-
bool get_midi_feedback () { return feedback; }
void set_midi_feedback (bool val) { feedback = val; }