From 6ffd8a954363475fb4b0aa15320fbb10ed3acb71 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 2 May 2014 18:44:04 -0400 Subject: a variety of changes to finalize (?) (MIDI) SceneChange functionality --- libs/ardour/ardour/midi_scene_change.h | 2 +- libs/ardour/ardour/midi_scene_changer.h | 6 ++- libs/ardour/ardour/scene_change.h | 8 +-- libs/ardour/ardour/scene_changer.h | 1 + libs/ardour/midi_scene_change.cc | 8 ++- libs/ardour/midi_scene_changer.cc | 90 ++++++++++++++++++++++++++++----- libs/ardour/scene_change.cc | 6 --- 7 files changed, 87 insertions(+), 34 deletions(-) diff --git a/libs/ardour/ardour/midi_scene_change.h b/libs/ardour/ardour/midi_scene_change.h index 86793c57fb..1a27446367 100644 --- a/libs/ardour/ardour/midi_scene_change.h +++ b/libs/ardour/ardour/midi_scene_change.h @@ -32,7 +32,7 @@ class MidiPort; class MIDISceneChange : public SceneChange { public: - MIDISceneChange (framepos_t time, int channel, int bank = -1, int program = -1); + MIDISceneChange (int channel, int bank = -1, int program = -1); MIDISceneChange (const XMLNode&, int version); ~MIDISceneChange (); diff --git a/libs/ardour/ardour/midi_scene_changer.h b/libs/ardour/ardour/midi_scene_changer.h index 369e47d9ea..e2c62a2656 100644 --- a/libs/ardour/ardour/midi_scene_changer.h +++ b/libs/ardour/ardour/midi_scene_changer.h @@ -20,6 +20,8 @@ #ifndef __libardour_midi_scene_changer_h__ #define __libardour_midi_scene_changer_h__ +#include + #include "ardour/scene_changer.h" namespace ARDOUR @@ -46,6 +48,7 @@ class MIDISceneChanger : public SceneChanger MIDI::Port* input_port; boost::shared_ptr output_port; + Glib::Threads::RWLock scene_lock; Scenes scenes; bool _recording; framepos_t last_bank_message_time; @@ -57,7 +60,8 @@ class MIDISceneChanger : public SceneChanger void gather (); bool recording () const; void jump_to (int bank, int program); - void deliver (MidiBuffer&, framepos_t, boost::shared_ptr); + void rt_deliver (MidiBuffer&, framepos_t, boost::shared_ptr); + void non_rt_deliver (boost::shared_ptr); void bank_change_input (MIDI::Parser&, unsigned short, int channel); void program_change_input (MIDI::Parser&, MIDI::byte, int channel); diff --git a/libs/ardour/ardour/scene_change.h b/libs/ardour/ardour/scene_change.h index b81766b0ea..1f856beedf 100644 --- a/libs/ardour/ardour/scene_change.h +++ b/libs/ardour/ardour/scene_change.h @@ -30,17 +30,11 @@ namespace ARDOUR class SceneChange : public PBD::Stateful { public: - SceneChange (framepos_t t) : _time (t) {}; + SceneChange () {}; virtual ~SceneChange () {}; - void set_time (framepos_t); - framepos_t time() const { return _time; } - static boost::shared_ptr factory (const XMLNode&, int version); static std::string xml_node_name; - - private: - framepos_t _time; }; } /* namespace */ diff --git a/libs/ardour/ardour/scene_changer.h b/libs/ardour/ardour/scene_changer.h index d5ba984e92..e171a23094 100644 --- a/libs/ardour/ardour/scene_changer.h +++ b/libs/ardour/ardour/scene_changer.h @@ -48,6 +48,7 @@ class SceneChanger : public SessionHandleRef virtual ~SceneChanger () {}; virtual void run (framepos_t start, framepos_t end) = 0; + virtual void locate (framepos_t where) = 0; }; } /* namespace */ diff --git a/libs/ardour/midi_scene_change.cc b/libs/ardour/midi_scene_change.cc index d0a14cba50..dae8acfc21 100644 --- a/libs/ardour/midi_scene_change.cc +++ b/libs/ardour/midi_scene_change.cc @@ -28,9 +28,8 @@ using namespace PBD; using namespace ARDOUR; -MIDISceneChange::MIDISceneChange (framepos_t time, int c, int b, int p) - : SceneChange (time) - , _bank (b) +MIDISceneChange::MIDISceneChange (int c, int b, int p) + : _bank (b) , _program (p) , _channel (c & 0xf) { @@ -44,8 +43,7 @@ MIDISceneChange::MIDISceneChange (framepos_t time, int c, int b, int p) } MIDISceneChange::MIDISceneChange (const XMLNode& node, int version) - : SceneChange (0) - , _bank (-1) + : _bank (-1) , _program (-1) , _channel (-1) { diff --git a/libs/ardour/midi_scene_changer.cc b/libs/ardour/midi_scene_changer.cc index 65503cb0c1..fcc20b850f 100644 --- a/libs/ardour/midi_scene_changer.cc +++ b/libs/ardour/midi_scene_changer.cc @@ -22,6 +22,7 @@ #include "midi++/parser.h" #include "midi++/port.h" +#include "ardour/async_midi_port.h" #include "ardour/event_type_map.h" #include "ardour/midi_port.h" #include "ardour/midi_scene_change.h" @@ -65,6 +66,8 @@ MIDISceneChanger::gather () const Locations::LocationList& locations (_session.locations()->list()); boost::shared_ptr sc; + Glib::Threads::RWLock::WriterLock lm (scene_lock); + scenes.clear (); for (Locations::LocationList::const_iterator l = locations.begin(); l != locations.end(); ++l) { @@ -72,16 +75,16 @@ MIDISceneChanger::gather () if ((sc = (*l)->scene_change()) != 0) { boost::shared_ptr msc = boost::dynamic_pointer_cast (sc); - + if (msc) { - scenes.insert (std::make_pair (msc->time(), msc)); + scenes.insert (std::make_pair ((*l)->start(), msc)); } } } } void -MIDISceneChanger::deliver (MidiBuffer& mbuf, framepos_t when, boost::shared_ptr msc) +MIDISceneChanger::rt_deliver (MidiBuffer& mbuf, framepos_t when, boost::shared_ptr msc) { uint8_t buf[4]; size_t cnt; @@ -102,12 +105,45 @@ MIDISceneChanger::deliver (MidiBuffer& mbuf, framepos_t when, boost::shared_ptr< last_delivered_program = msc->program(); } } - + +void +MIDISceneChanger::non_rt_deliver (boost::shared_ptr msc) +{ + uint8_t buf[4]; + size_t cnt; + boost::shared_ptr aport = boost::dynamic_pointer_cast(output_port); + + /* We use zero as the timestamp for these messages because we are in a + non-RT/process context. Using zero means "deliver them as early as + possible" (practically speaking, in the next process callback). + */ + + if ((cnt = msc->get_bank_msb_message (buf, sizeof (buf))) > 0) { + aport->write (buf, cnt, 0); + + if ((cnt = msc->get_bank_lsb_message (buf, sizeof (buf))) > 0) { + aport->write (buf, cnt, 0); + } + + last_delivered_bank = msc->bank(); + } + + if ((cnt = msc->get_program_message (buf, sizeof (buf))) > 0) { + aport->write (buf, cnt, 0); + last_delivered_program = msc->program(); + } +} void MIDISceneChanger::run (framepos_t start, framepos_t end) { - if (!output_port || recording()) { + if (!output_port || recording() || !_session.transport_rolling()) { + return; + } + + Glib::Threads::RWLock::ReaderLock lm (scene_lock, Glib::Threads::TRY_LOCK); + + if (!lm.locked()) { return; } @@ -121,9 +157,9 @@ MIDISceneChanger::run (framepos_t start, framepos_t end) if (i->first >= end) { break; } + + rt_deliver (mbuf, i->first - start, i->second); - deliver (mbuf, i->first - start, i->second); - ++i; } } @@ -131,15 +167,41 @@ MIDISceneChanger::run (framepos_t start, framepos_t end) void MIDISceneChanger::locate (framepos_t pos) { - Scenes::const_iterator i = scenes.upper_bound (pos); + boost::shared_ptr msc; + framepos_t when; - if (i == scenes.end()) { - return; + { + Glib::Threads::RWLock::ReaderLock lm (scene_lock); + + if (scenes.empty()) { + return; + } + + Scenes::const_iterator i = scenes.lower_bound (pos); + + if (i != scenes.end()) { + + if (i->first != pos) { + /* i points to first scene with position > pos, so back + * up, if possible. + */ + if (i != scenes.begin()) { + --i; + } else { + return; + } + } + } else { + /* go back to the final scene and use it */ + --i; + } + + when = i->first; + msc = i->second; } - if (i->second->program() != last_delivered_program || i->second->bank() != last_delivered_bank) { - // MidiBuffer& mbuf (output_port->get_midi_buffer (end-start)); - // deliver (mbuf, i->first, i->second); + if (msc->program() != last_delivered_program || msc->bank() != last_delivered_bank) { + non_rt_deliver (msc); } } @@ -229,7 +291,7 @@ MIDISceneChanger::program_change_input (MIDI::Parser& parser, MIDI::byte program unsigned short bank = input_port->channel (channel)->bank(); - MIDISceneChange* msc =new MIDISceneChange (loc->start(), channel, bank, program & 0x7f); + MIDISceneChange* msc =new MIDISceneChange (channel, bank, program & 0x7f); loc->set_scene_change (boost::shared_ptr (msc)); diff --git a/libs/ardour/scene_change.cc b/libs/ardour/scene_change.cc index dec6a11f85..eda260382b 100644 --- a/libs/ardour/scene_change.cc +++ b/libs/ardour/scene_change.cc @@ -37,9 +37,3 @@ SceneChange::factory (const XMLNode& node, int version) return boost::shared_ptr(); } - -void -SceneChange::set_time (framepos_t t) -{ - _time = t; -} -- cgit v1.2.3