X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fmidi_scene_changer.cc;h=07eb549e664fb3848ea43bed71d899e229ca959a;hb=47ba20143e06445a9977f4757d816439ea8042d0;hp=285a370402eade62ccfd61e6fffb937b365f140c;hpb=9254e80c396265f484adb3b7bf5f0b502d096107;p=ardour.git diff --git a/libs/ardour/midi_scene_changer.cc b/libs/ardour/midi_scene_changer.cc index 285a370402..07eb549e66 100644 --- a/libs/ardour/midi_scene_changer.cc +++ b/libs/ardour/midi_scene_changer.cc @@ -24,12 +24,13 @@ #include "ardour/async_midi_port.h" #include "ardour/event_type_map.h" +#include "ardour/midi_buffer.h" #include "ardour/midi_port.h" #include "ardour/midi_scene_change.h" #include "ardour/midi_scene_changer.h" #include "ardour/session.h" -#include "i18n.h" +#include "pbd/i18n.h" using namespace ARDOUR; @@ -40,14 +41,14 @@ MIDISceneChanger::MIDISceneChanger (Session& s) , last_program_message_time (-1) , last_delivered_program (-1) , last_delivered_bank (-1) - + { - /* catch any add/remove/clear etc. for all Locations */ + /* catch any add/remove/clear etc. for all Locations */ _session.locations()->changed.connect_same_thread (*this, boost::bind (&MIDISceneChanger::locations_changed, this)); _session.locations()->added.connect_same_thread (*this, boost::bind (&MIDISceneChanger::locations_changed, this)); _session.locations()->removed.connect_same_thread (*this, boost::bind (&MIDISceneChanger::locations_changed, this)); - /* catch class-based signal that notifies of us changes in the scene change state of any Location */ + /* catch class-based signal that notifies of us changes in the scene change state of any Location */ Location::scene_changed.connect_same_thread (*this, boost::bind (&MIDISceneChanger::locations_changed, this)); } @@ -62,7 +63,7 @@ MIDISceneChanger::locations_changed () } /** Use the session's list of locations to collect all patch changes. - * + * * This is called whenever the locations change in anyway. */ void @@ -82,10 +83,10 @@ MIDISceneChanger::gather (const Locations::LocationList& locations) if (msc) { - if (msc->bank() >= 0) { - have_seen_bank_changes = true; - } - + if (msc->bank() >= 0) { + have_seen_bank_changes = true; + } + scenes.insert (std::make_pair ((*l)->start(), msc)); } } @@ -95,10 +96,14 @@ MIDISceneChanger::gather (const Locations::LocationList& locations) void MIDISceneChanger::rt_deliver (MidiBuffer& mbuf, framepos_t when, boost::shared_ptr msc) { + if (!msc->active()) { + return; + } + uint8_t buf[4]; size_t cnt; - MIDIOutputActivity (); /* EMIT SIGNAL */ + MIDIOutputActivity (); /* EMIT SIGNAL */ if ((cnt = msc->get_bank_msb_message (buf, sizeof (buf))) > 0) { mbuf.push_back (when, cnt, buf); @@ -120,6 +125,10 @@ MIDISceneChanger::rt_deliver (MidiBuffer& mbuf, framepos_t when, boost::shared_p void MIDISceneChanger::non_rt_deliver (boost::shared_ptr msc) { + if (!msc->active()) { + return; + } + uint8_t buf[4]; size_t cnt; boost::shared_ptr aport = boost::dynamic_pointer_cast(output_port); @@ -128,8 +137,8 @@ MIDISceneChanger::non_rt_deliver (boost::shared_ptr msc) non-RT/process context. Using zero means "deliver them as early as possible" (practically speaking, in the next process callback). */ - - MIDIOutputActivity (); /* EMIT SIGNAL */ + + MIDIOutputActivity (); /* EMIT SIGNAL */ if ((cnt = msc->get_bank_msb_message (buf, sizeof (buf))) > 0) { aport->write (buf, cnt, 0); @@ -155,7 +164,7 @@ MIDISceneChanger::run (framepos_t start, framepos_t end) } Glib::Threads::RWLock::ReaderLock lm (scene_lock, Glib::Threads::TRY_LOCK); - + if (!lm.locked()) { return; } @@ -170,9 +179,9 @@ MIDISceneChanger::run (framepos_t start, framepos_t end) if (i->first >= end) { break; } - + rt_deliver (mbuf, i->first - start, i->second); - + ++i; } } @@ -188,9 +197,9 @@ MIDISceneChanger::locate (framepos_t pos) if (scenes.empty()) { return; } - + Scenes::const_iterator i = scenes.lower_bound (pos); - + if (i != scenes.end()) { if (i->first != pos) { @@ -214,25 +223,28 @@ MIDISceneChanger::locate (framepos_t pos) if (msc->program() != last_delivered_program || msc->bank() != last_delivered_bank) { non_rt_deliver (msc); } -} +} void -MIDISceneChanger::set_input_port (MIDI::Port* mp) +MIDISceneChanger::set_input_port (boost::shared_ptr mp) { - input_port = mp; - incoming_connections.drop_connections(); - - if (input_port) { - + input_port.reset (); + + boost::shared_ptr async = boost::dynamic_pointer_cast (mp); + + if (async) { + + input_port = mp; + /* midi port is asynchronous. MIDI parsing will be carried out * by the MIDI UI thread which will emit the relevant signals * and thus invoke our callbacks as necessary. */ for (int channel = 0; channel < 16; ++channel) { - input_port->parser()->channel_bank_change[channel].connect_same_thread (incoming_connections, boost::bind (&MIDISceneChanger::bank_change_input, this, _1, _2, channel)); - input_port->parser()->channel_program_change[channel].connect_same_thread (incoming_connections, boost::bind (&MIDISceneChanger::program_change_input, this, _1, _2, channel)); + async->parser()->channel_bank_change[channel].connect_same_thread (incoming_connections, boost::bind (&MIDISceneChanger::bank_change_input, this, _1, _2, channel)); + async->parser()->channel_program_change[channel].connect_same_thread (incoming_connections, boost::bind (&MIDISceneChanger::program_change_input, this, _1, _2, channel)); } } } @@ -250,7 +262,7 @@ MIDISceneChanger::set_recording (bool yn) } bool -MIDISceneChanger::recording() const +MIDISceneChanger::recording() const { return _session.transport_rolling() && _session.get_record_enabled(); } @@ -259,9 +271,9 @@ void MIDISceneChanger::bank_change_input (MIDI::Parser& /*parser*/, unsigned short, int) { if (recording()) { - have_seen_bank_changes = true; - } - MIDIInputActivity (); /* EMIT SIGNAL */ + have_seen_bank_changes = true; + } + MIDIInputActivity (); /* EMIT SIGNAL */ } void @@ -272,59 +284,62 @@ MIDISceneChanger::program_change_input (MIDI::Parser& parser, MIDI::byte program last_program_message_time = time; if (!recording()) { - MIDIInputActivity (); /* EMIT SIGNAL */ - jump_to (input_port->channel (channel)->bank(), program); + + MIDIInputActivity (); /* EMIT SIGNAL */ + + int bank = -1; + if (have_seen_bank_changes) { + bank = boost::dynamic_pointer_cast(input_port)->channel (channel)->bank(); + } + + jump_to (bank, program); return; } Locations* locations (_session.locations ()); Location* loc; bool new_mark = false; - framecnt_t slop = (framecnt_t) floor ((Config->get_inter_scene_gap_msecs() / 1000.0) * _session.frame_rate()); /* check for marker at current location */ - loc = locations->mark_at (time, slop); + loc = locations->mark_at (time, Config->get_inter_scene_gap_frames()); if (!loc) { /* create a new marker at the desired position */ - + std::string new_name; if (!locations->next_available_name (new_name, _("Scene "))) { std::cerr << "No new marker name available\n"; return; } - + loc = new Location (_session, time, time, new_name, Location::IsMark); new_mark = true; } - unsigned short bank; - - if (have_seen_bank_changes) { - bank = input_port->channel (channel)->bank(); - } else { - bank = -1; - } + int bank = -1; + if (have_seen_bank_changes) { + bank = boost::dynamic_pointer_cast(input_port)->channel (channel)->bank(); + } MIDISceneChange* msc =new MIDISceneChange (channel, bank, program & 0x7f); - /* check for identical scene change so we can re-use color, if any */ + /* check for identical scene change so we can re-use color, if any */ - Locations::LocationList copy (locations->list()); + Locations::LocationList copy (locations->list()); - for (Locations::LocationList::const_iterator l = copy.begin(); l != copy.end(); ++l) { - boost::shared_ptr sc = boost::dynamic_pointer_cast((*l)->scene_change()); + for (Locations::LocationList::const_iterator l = copy.begin(); l != copy.end(); ++l) { + boost::shared_ptr sc = boost::dynamic_pointer_cast((*l)->scene_change()); - if (sc && (*sc.get()) == *msc) { - msc->set_color (sc->color ()); - break; - } - } + if (sc && (*sc.get()) == *msc) { + msc->set_color (sc->color ()); + break; + } + } loc->set_scene_change (boost::shared_ptr (msc)); - + /* this will generate a "changed" signal to be emitted by locations, and we will call ::gather() to update our list of MIDI events. */ @@ -333,7 +348,7 @@ MIDISceneChanger::program_change_input (MIDI::Parser& parser, MIDI::byte program locations->add (loc); } - MIDIInputActivity (); /* EMIT SIGNAL */ + MIDIInputActivity (); /* EMIT SIGNAL */ } void