diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2006-07-10 20:01:47 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2006-07-10 20:01:47 +0000 |
commit | 26843b34fdd62e6f80630868c5eb3f8fee0c17f1 (patch) | |
tree | fe4001528aa6e4e360ec6392c7b1120ca75e0aa9 /libs | |
parent | 05f8fcd189ca714c2c18b9fb174d5813140849df (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')
-rw-r--r-- | libs/ardour/ardour/control_protocol_manager.h | 1 | ||||
-rw-r--r-- | libs/ardour/control_protocol_manager.cc | 5 | ||||
-rw-r--r-- | libs/gtkmm2ext/binding_proxy.cc | 12 | ||||
-rw-r--r-- | libs/gtkmm2ext/gtkmm2ext/binding_proxy.h | 3 | ||||
-rw-r--r-- | libs/gtkmm2ext/popup.cc | 14 | ||||
-rw-r--r-- | libs/pbd/pbd/controllable.h | 2 | ||||
-rw-r--r-- | libs/surfaces/control_protocol/control_protocol/control_protocol.h | 4 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/generic_midi_control_protocol.cc | 87 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/generic_midi_control_protocol.h | 7 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/interface.cc | 10 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/midicontrollable.cc | 3 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/midicontrollable.h | 3 | ||||
-rw-r--r-- | libs/surfaces/tranzport/tranzport_control_protocol.cc | 12 | ||||
-rw-r--r-- | libs/surfaces/tranzport/tranzport_control_protocol.h | 3 |
14 files changed, 142 insertions, 24 deletions
diff --git a/libs/ardour/ardour/control_protocol_manager.h b/libs/ardour/ardour/control_protocol_manager.h index 9202696dff..8eda7a4555 100644 --- a/libs/ardour/ardour/control_protocol_manager.h +++ b/libs/ardour/ardour/control_protocol_manager.h @@ -23,6 +23,7 @@ struct ControlProtocolInfo { std::string path; bool requested; bool mandatory; + XMLNode* state; }; class ControlProtocolManager : public sigc::trackable, public Stateful diff --git a/libs/ardour/control_protocol_manager.cc b/libs/ardour/control_protocol_manager.cc index c2fb188953..0370886a35 100644 --- a/libs/ardour/control_protocol_manager.cc +++ b/libs/ardour/control_protocol_manager.cc @@ -49,6 +49,10 @@ ControlProtocolManager::set_session (Session& s) if ((*i)->requested || (*i)->mandatory) { instantiate (**i); (*i)->requested = false; + + if ((*i)->state) { + (*i)->protocol->set_state (*(*i)->state); + } } } } @@ -181,6 +185,7 @@ ControlProtocolManager::control_protocol_discover (string path) cpi->protocol = 0; cpi->requested = false; cpi->mandatory = descriptor->mandatory; + cpi->state = 0; control_protocol_info.push_back (cpi); diff --git a/libs/gtkmm2ext/binding_proxy.cc b/libs/gtkmm2ext/binding_proxy.cc index a29cb41632..3a2f5bbbc8 100644 --- a/libs/gtkmm2ext/binding_proxy.cc +++ b/libs/gtkmm2ext/binding_proxy.cc @@ -62,7 +62,8 @@ BindingProxy::button_press_handler (GdkEventButton *ev) if (Controllable::StartLearning (&controllable)) { string prompt = _("operate controller now"); prompter.set_text (prompt); - prompter.show_all (); + prompter.touch (); // shows popup + learning_connection = controllable.LearningFinished.connect (mem_fun (*this, &BindingProxy::learning_finished)); } return true; } @@ -70,9 +71,18 @@ BindingProxy::button_press_handler (GdkEventButton *ev) return false; } +void +BindingProxy::learning_finished () +{ + learning_connection.disconnect (); + prompter.touch (); // hides popup +} + + bool BindingProxy::prompter_hiding (GdkEventAny *ev) { + learning_connection.disconnect (); Controllable::StopLearning (&controllable); return false; } diff --git a/libs/gtkmm2ext/gtkmm2ext/binding_proxy.h b/libs/gtkmm2ext/gtkmm2ext/binding_proxy.h index 365668f72c..a26c8ace2a 100644 --- a/libs/gtkmm2ext/gtkmm2ext/binding_proxy.h +++ b/libs/gtkmm2ext/gtkmm2ext/binding_proxy.h @@ -46,7 +46,8 @@ class BindingProxy : public sigc::trackable PBD::Controllable& controllable; guint bind_button; guint bind_statemask; - + sigc::connection learning_connection; + void learning_finished (); bool prompter_hiding (GdkEventAny *); }; diff --git a/libs/gtkmm2ext/popup.cc b/libs/gtkmm2ext/popup.cc index 0a48ebfc59..a8ffc4af66 100644 --- a/libs/gtkmm2ext/popup.cc +++ b/libs/gtkmm2ext/popup.cc @@ -73,11 +73,12 @@ PopUp::remove () { hide (); + if (popdown_time != 0 && timeout != -1) { + gtk_timeout_remove (timeout); + } + if (delete_on_hide) { std::cerr << "deleting prompter\n"; - if (popdown_time != 0 && timeout != -1) { - gtk_timeout_remove (timeout); - } gtk_idle_add (idle_delete, this); } } @@ -125,11 +126,12 @@ PopUp::on_delete_event (GdkEventAny* ev) { hide(); + if (popdown_time != 0 && timeout != -1) { + gtk_timeout_remove (timeout); + } + if (delete_on_hide) { std::cerr << "deleting prompter\n" << endl; - if (popdown_time != 0 && timeout != -1) { - gtk_timeout_remove (timeout); - } gtk_idle_add (idle_delete, this); } diff --git a/libs/pbd/pbd/controllable.h b/libs/pbd/pbd/controllable.h index 4948e4e4a0..c46e477b6e 100644 --- a/libs/pbd/pbd/controllable.h +++ b/libs/pbd/pbd/controllable.h @@ -21,6 +21,8 @@ class Controllable : public virtual sigc::trackable, public Stateful { virtual bool can_send_feedback() const { return true; } + sigc::signal<void> LearningFinished; + static sigc::signal<void,Controllable*> Created; static sigc::signal<void,Controllable*> GoingAway; diff --git a/libs/surfaces/control_protocol/control_protocol/control_protocol.h b/libs/surfaces/control_protocol/control_protocol/control_protocol.h index 69135f2b4b..2bd23f5b48 100644 --- a/libs/surfaces/control_protocol/control_protocol/control_protocol.h +++ b/libs/surfaces/control_protocol/control_protocol/control_protocol.h @@ -26,7 +26,7 @@ #include <vector> #include <list> #include <sigc++/sigc++.h> - +#include <pbd/stateful.h> #include <control_protocol/basic_ui.h> namespace ARDOUR { @@ -34,7 +34,7 @@ namespace ARDOUR { class Route; class Session; -class ControlProtocol : public sigc::trackable, public BasicUI { +class ControlProtocol : public sigc::trackable, public Stateful, public BasicUI { public: ControlProtocol (Session&, std::string name); virtual ~ControlProtocol(); 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; } diff --git a/libs/surfaces/tranzport/tranzport_control_protocol.cc b/libs/surfaces/tranzport/tranzport_control_protocol.cc index 09ab88e4ed..1fe9b7231a 100644 --- a/libs/surfaces/tranzport/tranzport_control_protocol.cc +++ b/libs/surfaces/tranzport/tranzport_control_protocol.cc @@ -1574,3 +1574,15 @@ TranzportControlProtocol::print (int row, int col, const char *text) } } +XMLNode& +TranzportControlProtocol::get_state () +{ + XMLNode* node = new XMLNode (_name); /* node name must match protocol name */ + return *node; +} + +int +TranzportControlProtocol::set_state (const XMLNode& node) +{ + return 0; +} diff --git a/libs/surfaces/tranzport/tranzport_control_protocol.h b/libs/surfaces/tranzport/tranzport_control_protocol.h index 546cc2f2af..e6e1a83e46 100644 --- a/libs/surfaces/tranzport/tranzport_control_protocol.h +++ b/libs/surfaces/tranzport/tranzport_control_protocol.h @@ -23,6 +23,9 @@ class TranzportControlProtocol : public ARDOUR::ControlProtocol static bool probe (); + XMLNode& get_state (); + int set_state (const XMLNode&); + private: static const int VENDORID = 0x165b; static const int PRODUCTID = 0x8101; |