diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2008-03-21 20:22:00 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2008-03-21 20:22:00 +0000 |
commit | fec2a96cec0f557cf30dde2f9bf21b76be36551d (patch) | |
tree | a1b446d153191d641f36cb30e178e3fc400be495 /libs | |
parent | aa06f1f9f8be010d4abfc5b5c2fd61ab8e39fa58 (diff) |
fix dragging that involves locked regions; auto-rebinding patch for people to experiment with (probably needs a little work)
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@3164 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r-- | libs/ardour/ardour/region_factory.h | 7 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 3 | ||||
-rw-r--r-- | libs/ardour/region_factory.cc | 14 | ||||
-rw-r--r-- | libs/ardour/session.cc | 4 | ||||
-rw-r--r-- | libs/gtkmm2ext/gtkmm2ext/barcontroller.h | 1 | ||||
-rw-r--r-- | libs/gtkmm2ext/gtkmm2ext/bindable_button.h | 5 | ||||
-rw-r--r-- | libs/gtkmm2ext/gtkmm2ext/binding_proxy.h | 1 | ||||
-rw-r--r-- | libs/pbd/controllable.cc | 2 | ||||
-rw-r--r-- | libs/pbd/pbd/controllable.h | 2 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/generic_midi_control_protocol.cc | 146 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/generic_midi_control_protocol.h | 8 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/midicontrollable.h | 6 |
12 files changed, 152 insertions, 47 deletions
diff --git a/libs/ardour/ardour/region_factory.h b/libs/ardour/ardour/region_factory.h index b944202c36..ada5afcd9c 100644 --- a/libs/ardour/ardour/region_factory.h +++ b/libs/ardour/ardour/region_factory.h @@ -42,6 +42,12 @@ class RegionFactory { static sigc::signal<void,boost::shared_ptr<Region> > CheckNewRegion; + static boost::shared_ptr<Region> create (boost::shared_ptr<const Region>); + + /* note: both of the first two should use const shared_ptr as well, but + gcc 4.1 doesn't seem to be able to disambiguate them if they do. + */ + static boost::shared_ptr<Region> create (boost::shared_ptr<Region>, nframes_t start, nframes_t length, std::string name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true); @@ -50,7 +56,6 @@ class RegionFactory { layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true); static boost::shared_ptr<Region> create (boost::shared_ptr<Source>, nframes_t start, nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true); static boost::shared_ptr<Region> create (const SourceList &, nframes_t start, nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true); - static boost::shared_ptr<Region> create (boost::shared_ptr<Region>); static boost::shared_ptr<Region> create (Session&, XMLNode&, bool); static boost::shared_ptr<Region> create (SourceList &, const XMLNode&); }; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 76590368f8..fa50212f3a 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -249,6 +249,9 @@ class Session : public PBD::StatefulDestructible bool deletion_in_progress() const { return _state_of_the_state & Deletion; } sigc::signal<void> DirtyChanged; + static sigc::signal<void> AutoBindingOn; + static sigc::signal<void> AutoBindingOff; + std::string sound_dir (bool with_path = true) const; std::string peak_dir () const; std::string dead_sound_dir () const; diff --git a/libs/ardour/region_factory.cc b/libs/ardour/region_factory.cc index 5cab802801..163cb07c6c 100644 --- a/libs/ardour/region_factory.cc +++ b/libs/ardour/region_factory.cc @@ -35,8 +35,8 @@ sigc::signal<void,boost::shared_ptr<Region> > RegionFactory::CheckNewRegion; boost::shared_ptr<Region> RegionFactory::create (boost::shared_ptr<Region> region, nframes_t start, - nframes_t length, std::string name, - layer_t layer, Region::Flag flags, bool announce) + nframes_t length, std::string name, + layer_t layer, Region::Flag flags, bool announce) { boost::shared_ptr<const AudioRegion> other; @@ -57,11 +57,11 @@ RegionFactory::create (boost::shared_ptr<Region> region, nframes_t start, } boost::shared_ptr<Region> -RegionFactory::create (boost::shared_ptr<Region> region) +RegionFactory::create (boost::shared_ptr<const Region> region) { - boost::shared_ptr<AudioRegion> other; + boost::shared_ptr<const AudioRegion> other; - if ((other = boost::dynamic_pointer_cast<AudioRegion>(region)) != 0) { + if ((other = boost::dynamic_pointer_cast<const AudioRegion>(region)) != 0) { boost::shared_ptr<Region> ret (new AudioRegion (other)); /* pure copy constructor - no CheckNewRegion emitted */ return ret; @@ -75,8 +75,8 @@ RegionFactory::create (boost::shared_ptr<Region> region) boost::shared_ptr<Region> RegionFactory::create (boost::shared_ptr<AudioRegion> region, nframes_t start, - nframes_t length, std::string name, - layer_t layer, Region::Flag flags, bool announce) + nframes_t length, std::string name, + layer_t layer, Region::Flag flags, bool announce) { return create (boost::static_pointer_cast<Region> (region), start, length, name, layer, flags, announce); } diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index d53291b178..d7c3c95d9d 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -113,6 +113,10 @@ sigc::signal<void> Session::SMPTEOffsetChanged; sigc::signal<void> Session::StartTimeChanged; sigc::signal<void> Session::EndTimeChanged; +sigc::signal<void> Session::AutoBindingOn; +sigc::signal<void> Session::AutoBindingOff; + + int Session::find_session (string str, string& path, string& snapshot, bool& isnew) { diff --git a/libs/gtkmm2ext/gtkmm2ext/barcontroller.h b/libs/gtkmm2ext/gtkmm2ext/barcontroller.h index c91f4c8a06..d149ded527 100644 --- a/libs/gtkmm2ext/gtkmm2ext/barcontroller.h +++ b/libs/gtkmm2ext/gtkmm2ext/barcontroller.h @@ -59,6 +59,7 @@ class BarController : public Gtk::Frame /* export this to allow direct connection to button events */ Gtk::Widget& event_widget() { return darea; } + PBD::Controllable* get_controllable() { return binding_proxy.get_controllable(); } protected: Gtk::Adjustment& adjustment; diff --git a/libs/gtkmm2ext/gtkmm2ext/bindable_button.h b/libs/gtkmm2ext/gtkmm2ext/bindable_button.h index 2ddd3628fc..1cde32c5ba 100644 --- a/libs/gtkmm2ext/gtkmm2ext/bindable_button.h +++ b/libs/gtkmm2ext/gtkmm2ext/bindable_button.h @@ -47,7 +47,8 @@ class BindableToggleButton : public Gtkmm2ext::StatefulToggleButton return true; } } - + + PBD::Controllable* get_controllable() { return binding_proxy.get_controllable(); } private: BindingProxy binding_proxy; }; @@ -71,6 +72,8 @@ class BindableButton : public Gtkmm2ext::StatefulButton } } + PBD::Controllable* get_controllable() { return binding_proxy.get_controllable(); } + private: BindingProxy binding_proxy; }; diff --git a/libs/gtkmm2ext/gtkmm2ext/binding_proxy.h b/libs/gtkmm2ext/gtkmm2ext/binding_proxy.h index d8f37c7649..dd9b94319d 100644 --- a/libs/gtkmm2ext/gtkmm2ext/binding_proxy.h +++ b/libs/gtkmm2ext/gtkmm2ext/binding_proxy.h @@ -40,6 +40,7 @@ class BindingProxy : public sigc::trackable bool button_press_handler (GdkEventButton *); + PBD::Controllable* get_controllable() { return &controllable; } protected: Gtkmm2ext::PopUp* prompter; diff --git a/libs/pbd/controllable.cc b/libs/pbd/controllable.cc index bf0f7f5c6d..6a0028668b 100644 --- a/libs/pbd/controllable.cc +++ b/libs/pbd/controllable.cc @@ -28,6 +28,8 @@ using namespace PBD; sigc::signal<void,Controllable*> Controllable::Destroyed; sigc::signal<bool,Controllable*> Controllable::StartLearning; sigc::signal<void,Controllable*> Controllable::StopLearning; +sigc::signal<void,Controllable*,int,int> Controllable::CreateBinding; +sigc::signal<void,Controllable*> Controllable::DeleteBinding; Glib::Mutex* Controllable::registry_lock = 0; Controllable::Controllables Controllable::registry; diff --git a/libs/pbd/pbd/controllable.h b/libs/pbd/pbd/controllable.h index 85f09726ca..17ee8f1a6f 100644 --- a/libs/pbd/pbd/controllable.h +++ b/libs/pbd/pbd/controllable.h @@ -44,6 +44,8 @@ class Controllable : public PBD::StatefulDestructible { virtual bool can_send_feedback() const { return true; } sigc::signal<void> LearningFinished; + static sigc::signal<void,PBD::Controllable*,int,int> CreateBinding; + static sigc::signal<void,PBD::Controllable*> DeleteBinding; static sigc::signal<bool,PBD::Controllable*> StartLearning; static sigc::signal<void,PBD::Controllable*> StopLearning; diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc index 720711d94b..90b6b4bda9 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc @@ -56,9 +56,17 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s) _feedback_interval = 10000; // microseconds last_feedback_time = 0; + auto_binding = FALSE; + Controllable::StartLearning.connect (mem_fun (*this, &GenericMidiControlProtocol::start_learning)); Controllable::StopLearning.connect (mem_fun (*this, &GenericMidiControlProtocol::stop_learning)); Session::SendFeedback.connect (mem_fun (*this, &GenericMidiControlProtocol::send_feedback)); + + Controllable::CreateBinding.connect (mem_fun (*this, &GenericMidiControlProtocol::create_binding)); + Controllable::DeleteBinding.connect (mem_fun (*this, &GenericMidiControlProtocol::delete_binding)); + + Session::AutoBindingOn.connect (mem_fun (*this, &GenericMidiControlProtocol::auto_binding_on)); + Session::AutoBindingOff.connect (mem_fun (*this, &GenericMidiControlProtocol::auto_binding_off)); } GenericMidiControlProtocol::~GenericMidiControlProtocol () @@ -225,6 +233,71 @@ GenericMidiControlProtocol::stop_learning (Controllable* c) } } +void +GenericMidiControlProtocol::delete_binding ( PBD::Controllable* control ) +{ + if( control != 0 ) { + Glib::Mutex::Lock lm2 (controllables_lock); + + for( MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ++iter) { + MIDIControllable* existingBinding = (*iter); + + if( control == &(existingBinding->get_controllable()) ) { + delete existingBinding; + controllables.erase (iter); + } + + } // end for midi controllables + } // end null check +} +void +GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos, int control_number) +{ + if( control != NULL ) { + Glib::Mutex::Lock lm2 (controllables_lock); + + MIDI::channel_t channel = (pos & 0xf); + MIDI::byte value = control_number; + + // Create a MIDIControllable:: + MIDIControllable* mc = new MIDIControllable (*_port, *control); + + // Remove any old binding for this midi channel/type/value pair + // Note: can't use delete_binding() here because we don't know the specific controllable we want to remove, only the midi information + for( MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ++iter) { + MIDIControllable* existingBinding = (*iter); + + if( (existingBinding->get_control_channel() & 0xf ) == channel && + existingBinding->get_control_additional() == value && + (existingBinding->get_control_type() & 0xf0 ) == MIDI::controller ) { + + delete existingBinding; + controllables.erase (iter); + } + + } // end for midi controllables + + + // Update the MIDI Controllable based on the the pos param + // Here is where a table lookup for user mappings could go; for now we'll just wing it... + mc->bind_midi( channel, MIDI::controller, value ); + + controllables.insert (mc); + } // end null test +} + +void +GenericMidiControlProtocol::auto_binding_on() +{ + auto_binding = TRUE; +} + +void +GenericMidiControlProtocol::auto_binding_off() +{ + auto_binding = FALSE; +} + XMLNode& GenericMidiControlProtocol::get_state () { @@ -269,46 +342,47 @@ GenericMidiControlProtocol::set_state (const XMLNode& node) _feedback_interval = 10000; } - Controllable* c; - - { - Glib::Mutex::Lock lm (pending_lock); - pending_controllables.clear (); - } - - Glib::Mutex::Lock lm2 (controllables_lock); - - controllables.clear (); - - nlist = node.children(); // "controls" - - if (nlist.empty()) { - return 0; - } - - nlist = nlist.front()->children (); - - for (niter = nlist.begin(); niter != nlist.end(); ++niter) { - - if ((prop = (*niter)->property ("id")) != 0) { - - ID id = prop->value (); - - c = Controllable::by_id (id); + // Are we using the autobinding feature? If so skip this part + if ( !auto_binding ) { + + Controllable* c; + + { + Glib::Mutex::Lock lm (pending_lock); + pending_controllables.clear (); + } + + Glib::Mutex::Lock lm2 (controllables_lock); + controllables.clear (); + nlist = node.children(); // "controls" + + if (nlist.empty()) { + return 0; + } + + nlist = nlist.front()->children (); + + for (niter = nlist.begin(); niter != nlist.end(); ++niter) { - if (c) { - MIDIControllable* mc = new MIDIControllable (*_port, *c); - if (mc->set_state (**niter) == 0) { - controllables.insert (mc); - } + if ((prop = (*niter)->property ("id")) != 0) { + + ID id = prop->value (); + c = session->controllable_by_id (id); - } else { - warning << string_compose (_("Generic MIDI control: controllable %1 not found (ignored)"), id) - << endmsg; + if (c) { + MIDIControllable* mc = new MIDIControllable (*_port, *c); + if (mc->set_state (**niter) == 0) { + controllables.insert (mc); + } + + } else { + warning << string_compose (_("Generic MIDI control: controllable %1 not found in session (ignored)"), + id) + << endmsg; + } } } - } - + } // end autobinding check 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 95aeb77cdb..dfff8810d1 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.h +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.h @@ -44,6 +44,7 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol { ARDOUR::microseconds_t last_feedback_time; bool do_feedback; + bool auto_binding; void _send_feedback (); void send_feedback (); @@ -59,6 +60,13 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol { void stop_learning (PBD::Controllable*); void learning_stopped (MIDIControllable*); + + void create_binding (PBD::Controllable*, int, int); + void delete_binding (PBD::Controllable*); + + void auto_binding_on(); + void auto_binding_off(); + }; #endif /* ardour_generic_midi_control_protocol_h */ diff --git a/libs/surfaces/generic_midi/midicontrollable.h b/libs/surfaces/generic_midi/midicontrollable.h index 4bac325feb..df6eea396c 100644 --- a/libs/surfaces/generic_midi/midicontrollable.h +++ b/libs/surfaces/generic_midi/midicontrollable.h @@ -63,6 +63,10 @@ class MIDIControllable : public Stateful XMLNode& get_state (void); int set_state (const XMLNode&); + void bind_midi (MIDI::channel_t, MIDI::eventType, MIDI::byte); + MIDI::channel_t get_control_channel () { return control_channel; } + MIDI::eventType get_control_type () { return control_type; } + MIDI::byte get_control_additional () { return control_additional; } private: PBD::Controllable& controllable; MIDI::Port& _port; @@ -86,8 +90,6 @@ class MIDIControllable : public Stateful void midi_sense_controller (MIDI::Parser &, MIDI::EventTwoBytes *); void midi_sense_program_change (MIDI::Parser &, MIDI::byte); void midi_sense_pitchbend (MIDI::Parser &, MIDI::pitchbend_t); - - void bind_midi (MIDI::channel_t, MIDI::eventType, MIDI::byte); }; #endif // __gm_midicontrollable_h__ |