#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"
MIDISceneChanger::MIDISceneChanger (Session& s)
: SceneChanger (s)
, _recording (true)
- , last_bank_message_time (-1)
+ , have_seen_bank_changes (false)
, last_program_message_time (-1)
, last_delivered_program (-1)
, last_delivered_bank (-1)
{
- _session.locations()->changed.connect_same_thread (*this, boost::bind (&MIDISceneChanger::locations_changed, this, _1));
- Location::scene_changed.connect_same_thread (*this, boost::bind (&MIDISceneChanger::gather, this));
+ /* 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 */
+ Location::scene_changed.connect_same_thread (*this, boost::bind (&MIDISceneChanger::locations_changed, this));
}
MIDISceneChanger::~MIDISceneChanger ()
}
void
-MIDISceneChanger::locations_changed (Locations::Change)
+MIDISceneChanger::locations_changed ()
{
- gather ();
+ _session.locations()->apply (*this, &MIDISceneChanger::gather);
}
/** Use the session's list of locations to collect all patch changes.
* This is called whenever the locations change in anyway.
*/
void
-MIDISceneChanger::gather ()
+MIDISceneChanger::gather (const Locations::LocationList& locations)
{
- const Locations::LocationList& locations (_session.locations()->list());
boost::shared_ptr<SceneChange> sc;
Glib::Threads::RWLock::WriterLock lm (scene_lock);
if ((sc = (*l)->scene_change()) != 0) {
boost::shared_ptr<MIDISceneChange> msc = boost::dynamic_pointer_cast<MIDISceneChange> (sc);
-
+
if (msc) {
+
+ if (msc->bank() >= 0) {
+ have_seen_bank_changes = true;
+ }
+
scenes.insert (std::make_pair ((*l)->start(), msc));
}
}
uint8_t buf[4];
size_t cnt;
+ MIDIOutputActivity (); /* EMIT SIGNAL */
+
if ((cnt = msc->get_bank_msb_message (buf, sizeof (buf))) > 0) {
mbuf.push_back (when, cnt, buf);
non-RT/process context. Using zero means "deliver them as early as
possible" (practically speaking, in the next process callback).
*/
+
+ MIDIOutputActivity (); /* EMIT SIGNAL */
if ((cnt = msc->get_bank_msb_message (buf, sizeof (buf))) > 0) {
aport->write (buf, cnt, 0);
}
void
-MIDISceneChanger::bank_change_input (MIDI::Parser& parser, unsigned short, int)
+ MIDISceneChanger::bank_change_input (MIDI::Parser& /*parser*/, unsigned short, int)
{
- if (!recording()) {
- return;
+ if (recording()) {
+ have_seen_bank_changes = true;
}
-
- last_bank_message_time = parser.get_timestamp ();
+ MIDIInputActivity (); /* EMIT SIGNAL */
}
void
last_program_message_time = time;
if (!recording()) {
+ MIDIInputActivity (); /* EMIT SIGNAL */
jump_to (input_port->channel (channel)->bank(), program);
return;
}
new_mark = true;
}
- unsigned short bank = input_port->channel (channel)->bank();
+ unsigned short bank;
+
+ if (have_seen_bank_changes) {
+ bank = input_port->channel (channel)->bank();
+ } else {
+ bank = -1;
+ }
MIDISceneChange* msc =new MIDISceneChange (channel, bank, program & 0x7f);
+ /* check for identical scene change so we can re-use color, if any */
+
+ Locations::LocationList copy (locations->list());
+
+ for (Locations::LocationList::const_iterator l = copy.begin(); l != copy.end(); ++l) {
+ boost::shared_ptr<MIDISceneChange> sc = boost::dynamic_pointer_cast<MIDISceneChange>((*l)->scene_change());
+
+ if (sc && (*sc.get()) == *msc) {
+ msc->set_color (sc->color ());
+ break;
+ }
+ }
+
loc->set_scene_change (boost::shared_ptr<MIDISceneChange> (msc));
/* this will generate a "changed" signal to be emitted by locations,
if (new_mark) {
locations->add (loc);
}
+
+ MIDIInputActivity (); /* EMIT SIGNAL */
}
void