2 Copyright (C) 2006 Paul Davis
3 Author: David Robillard
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 // 'std::isinf()' and 'std::isnan()' are not available in MSVC.
25 #define isinf_local(val) !((bool)_finite((double)val))
26 #define isnan_local(val) (bool)_isnan((double)val)
28 #define isinf_local std::isinf
29 #define isnan_local std::isnan
33 #include "pbd/enumwriter.h"
34 #include "pbd/convert.h"
35 #include "evoral/midi_util.h"
37 #include "ardour/beats_frames_converter.h"
38 #include "ardour/buffer_set.h"
39 #include "ardour/debug.h"
40 #include "ardour/delivery.h"
41 #include "ardour/event_type_map.h"
42 #include "ardour/meter.h"
43 #include "ardour/midi_diskstream.h"
44 #include "ardour/midi_playlist.h"
45 #include "ardour/midi_port.h"
46 #include "ardour/midi_region.h"
47 #include "ardour/midi_track.h"
48 #include "ardour/parameter_types.h"
49 #include "ardour/port.h"
50 #include "ardour/processor.h"
51 #include "ardour/session.h"
52 #include "ardour/session_playlists.h"
53 #include "ardour/utils.h"
58 class InterThreadInfo;
65 using namespace ARDOUR;
68 MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
69 : Track (sess, name, flag, mode, DataType::MIDI)
70 , _immediate_events(1024) // FIXME: size?
71 , _step_edit_ring_buffer(64) // FIXME: size?
72 , _note_mode(Sustained)
73 , _step_editing (false)
74 , _input_active (true)
75 , _playback_channel_mask(0x0000ffff)
76 , _capture_channel_mask(0x0000ffff)
80 MidiTrack::~MidiTrack ()
91 _input->changed.connect_same_thread (*this, boost::bind (&MidiTrack::track_input_active, this, _1, _2));
96 boost::shared_ptr<Diskstream>
97 MidiTrack::create_diskstream ()
99 MidiDiskstream::Flag dflags = MidiDiskstream::Flag (MidiDiskstream::Recordable);
101 assert(_mode != Destructive);
103 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, name(), dflags));
108 MidiTrack::set_record_enabled (bool yn, void *src)
114 Track::set_record_enabled (yn, src);
118 MidiTrack::set_diskstream (boost::shared_ptr<Diskstream> ds)
120 /* We have to do this here, as Track::set_diskstream will cause a buffer refill,
121 and the diskstream must be set up to fill its buffers using the correct _note_mode.
123 boost::shared_ptr<MidiDiskstream> mds = boost::dynamic_pointer_cast<MidiDiskstream> (ds);
124 mds->set_note_mode (_note_mode);
126 Track::set_diskstream (ds);
128 mds->reset_tracker ();
130 _diskstream->set_track (this);
131 _diskstream->set_destructive (_mode == Destructive);
132 _diskstream->set_record_enabled (false);
134 _diskstream_data_recorded_connection.disconnect ();
135 mds->DataRecorded.connect_same_thread (
136 _diskstream_data_recorded_connection,
137 boost::bind (&MidiTrack::diskstream_data_recorded, this, _1));
139 DiskstreamChanged (); /* EMIT SIGNAL */
142 boost::shared_ptr<MidiDiskstream>
143 MidiTrack::midi_diskstream() const
145 return boost::dynamic_pointer_cast<MidiDiskstream>(_diskstream);
149 MidiTrack::set_state (const XMLNode& node, int version)
151 const XMLProperty *prop;
153 /* This must happen before Track::set_state(), as there will be a buffer
154 fill during that call, and we must fill buffers using the correct
157 if ((prop = node.property (X_("note-mode"))) != 0) {
158 _note_mode = NoteMode (string_2_enum (prop->value(), _note_mode));
160 _note_mode = Sustained;
163 if (Track::set_state (node, version)) {
167 // No destructive MIDI tracks (yet?)
170 if ((prop = node.property ("input-active")) != 0) {
171 set_input_active (string_is_affirmative (prop->value()));
174 ChannelMode playback_channel_mode = AllChannels;
175 ChannelMode capture_channel_mode = AllChannels;
177 if ((prop = node.property ("playback-channel-mode")) != 0) {
178 playback_channel_mode = ChannelMode (string_2_enum(prop->value(), playback_channel_mode));
180 if ((prop = node.property ("capture-channel-mode")) != 0) {
181 capture_channel_mode = ChannelMode (string_2_enum(prop->value(), capture_channel_mode));
183 if ((prop = node.property ("channel-mode")) != 0) {
184 /* 3.0 behaviour where capture and playback modes were not separated */
185 playback_channel_mode = ChannelMode (string_2_enum(prop->value(), playback_channel_mode));
186 capture_channel_mode = playback_channel_mode;
189 unsigned int playback_channel_mask = 0xffff;
190 unsigned int capture_channel_mask = 0xffff;
192 if ((prop = node.property ("playback-channel-mask")) != 0) {
193 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
195 if ((prop = node.property ("capture-channel-mask")) != 0) {
196 sscanf (prop->value().c_str(), "0x%x", &capture_channel_mask);
198 if ((prop = node.property ("channel-mask")) != 0) {
199 sscanf (prop->value().c_str(), "0x%x", &playback_channel_mask);
200 capture_channel_mask = playback_channel_mask;
203 set_playback_channel_mode (playback_channel_mode, playback_channel_mask);
204 set_capture_channel_mode (capture_channel_mode, capture_channel_mask);
206 pending_state = const_cast<XMLNode*> (&node);
208 if (_session.state_of_the_state() & Session::Loading) {
209 _session.StateReady.connect_same_thread (
210 *this, boost::bind (&MidiTrack::set_state_part_two, this));
212 set_state_part_two ();
219 MidiTrack::state(bool full_state)
221 XMLNode& root (Track::state(full_state));
222 XMLNode* freeze_node;
225 if (_freeze_record.playlist) {
228 freeze_node = new XMLNode (X_("freeze-info"));
229 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
230 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
232 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
233 inode = new XMLNode (X_("processor"));
234 (*i)->id.print (buf, sizeof(buf));
235 inode->add_property (X_("id"), buf);
236 inode->add_child_copy ((*i)->state);
238 freeze_node->add_child_nocopy (*inode);
241 root.add_child_nocopy (*freeze_node);
244 root.add_property("playback_channel-mode", enum_2_string(get_playback_channel_mode()));
245 root.add_property("capture_channel-mode", enum_2_string(get_capture_channel_mode()));
246 snprintf (buf, sizeof(buf), "0x%x", get_playback_channel_mask());
247 root.add_property("playback-channel-mask", buf);
248 snprintf (buf, sizeof(buf), "0x%x", get_capture_channel_mask());
249 root.add_property("capture-channel-mask", buf);
251 root.add_property ("note-mode", enum_2_string (_note_mode));
252 root.add_property ("step-editing", (_step_editing ? "yes" : "no"));
253 root.add_property ("input-active", (_input_active ? "yes" : "no"));
259 MidiTrack::set_state_part_two ()
263 LocaleGuard lg (X_("C"));
265 /* This is called after all session state has been restored but before
266 have been made ports and connections are established.
269 if (pending_state == 0) {
273 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
275 _freeze_record.state = Frozen;
277 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
280 _freeze_record.processor_info.clear ();
282 if ((prop = fnode->property (X_("playlist"))) != 0) {
283 boost::shared_ptr<Playlist> pl = _session.playlists->by_name (prop->value());
285 _freeze_record.playlist = boost::dynamic_pointer_cast<MidiPlaylist> (pl);
287 _freeze_record.playlist.reset();
288 _freeze_record.state = NoFreeze;
293 if ((prop = fnode->property (X_("state"))) != 0) {
294 _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
297 XMLNodeConstIterator citer;
298 XMLNodeList clist = fnode->children();
300 for (citer = clist.begin(); citer != clist.end(); ++citer) {
301 if ((*citer)->name() != X_("processor")) {
305 if ((prop = (*citer)->property (X_("id"))) == 0) {
309 FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
310 boost::shared_ptr<Processor>());
311 frii->id = prop->value ();
312 _freeze_record.processor_info.push_back (frii);
316 if (midi_diskstream ()) {
317 midi_diskstream()->set_block_size (_session.get_block_size ());
324 MidiTrack::update_controls(const BufferSet& bufs)
326 const MidiBuffer& buf = bufs.get_midi(0);
327 for (MidiBuffer::const_iterator e = buf.begin(); e != buf.end(); ++e) {
328 const Evoral::MIDIEvent<framepos_t>& ev = *e;
329 const Evoral::Parameter param = midi_parameter(ev.buffer(), ev.size());
330 const boost::shared_ptr<Evoral::Control> control = this->control(param);
332 control->set_double(ev.value(), _session.transport_frame(), false);
337 /** @param need_butler to be set to true if this track now needs the butler, otherwise it can be left alone
341 MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler)
343 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
345 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
346 framecnt_t playback_distance = diskstream->calculate_playback_distance(nframes);
347 if (can_internal_playback_seek(llabs(playback_distance))) {
348 /* TODO should declick, and/or note-off */
349 internal_playback_seek(playback_distance);
354 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
356 if (n_outputs().n_total() == 0 && _processors.empty()) {
362 if (_meter_point == MeterInput && (_monitoring & MonitorInput || _diskstream->record_enabled())) {
368 framepos_t transport_frame = _session.transport_frame();
371 framecnt_t playback_distance;
373 if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
374 /* need to do this so that the diskstream sets its
375 playback distance to zero, thus causing diskstream::commit
378 BufferSet bufs; /* empty set - is OK, since nothing will happen */
380 dret = diskstream->process (bufs, transport_frame, 0, playback_distance, false);
381 need_butler = diskstream->commit (playback_distance);
385 BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
387 fill_buffers_with_input (bufs, _input, nframes);
389 /* filter captured data before meter sees it */
390 filter_channels (bufs, get_capture_channel_mode(), get_capture_channel_mask());
392 if (_meter_point == MeterInput && (_monitoring & MonitorInput || _diskstream->record_enabled())) {
393 _meter->run (bufs, start_frame, end_frame, nframes, true);
399 if ((dret = diskstream->process (bufs, transport_frame, nframes, playback_distance, (monitoring_state() == MonitoringDisk))) != 0) {
400 need_butler = diskstream->commit (playback_distance);
405 /* filter playback data before we do anything else */
407 filter_channels (bufs, get_playback_channel_mode(), get_playback_channel_mask ());
409 if (monitoring_state() == MonitoringInput) {
411 /* not actually recording, but we want to hear the input material anyway,
412 at least potentially (depending on monitoring options)
415 /* because the playback buffer is event based and not a
416 * continuous stream, we need to make sure that we empty
417 * it of events every cycle to avoid it filling up with events
418 * read from disk, while we are actually monitoring input
421 diskstream->flush_playback (start_frame, end_frame);
426 /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
428 write_out_of_band_data (bufs, start_frame, end_frame, nframes);
430 /* final argument: don't waste time with automation if we're not recording or rolling */
432 process_output_buffers (bufs, start_frame, end_frame, nframes,
433 declick, (!diskstream->record_enabled() && !_session.transport_stopped()));
435 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
436 boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery> (*i);
438 d->flush_buffers (nframes);
442 need_butler = diskstream->commit (playback_distance);
448 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
450 int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
452 if (ret == 0 && _step_editing) {
453 push_midi_input_to_step_edit_ringbuffer (nframes);
460 MidiTrack::realtime_locate ()
462 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
468 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
469 (*i)->realtime_locate ();
472 midi_diskstream()->reset_tracker ();
476 MidiTrack::realtime_handle_transport_stopped ()
478 Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
484 for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
485 (*i)->realtime_handle_transport_stopped ();
490 MidiTrack::non_realtime_locate (framepos_t pos)
492 Track::non_realtime_locate(pos);
494 boost::shared_ptr<MidiPlaylist> playlist = midi_diskstream()->midi_playlist();
499 /* Get the top unmuted region at this position. */
500 boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion>(
501 playlist->top_unmuted_region_at(pos));
506 Glib::Threads::Mutex::Lock lm (_control_lock, Glib::Threads::TRY_LOCK);
511 /* Update track controllers based on its "automation". */
512 const framepos_t origin = region->position() - region->start();
513 BeatsFramesConverter bfc(_session.tempo_map(), origin);
514 for (Controls::const_iterator c = _controls.begin(); c != _controls.end(); ++c) {
515 boost::shared_ptr<MidiTrack::MidiControl> tcontrol;
516 boost::shared_ptr<Evoral::Control> rcontrol;
517 if ((tcontrol = boost::dynamic_pointer_cast<MidiTrack::MidiControl>(c->second)) &&
518 (rcontrol = region->control(tcontrol->parameter()))) {
519 const Evoral::Beats pos_beats = bfc.from(pos - origin);
520 tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()));
526 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
528 PortSet& ports (_input->ports());
530 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
532 Buffer& b (p->get_buffer (nframes));
533 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
536 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
538 const Evoral::MIDIEvent<framepos_t> ev(*e, false);
540 /* note on, since for step edit, note length is determined
544 if (ev.is_note_on()) {
545 /* we don't care about the time for this purpose */
546 _step_edit_ring_buffer.write (0, ev.type(), ev.size(), ev.buffer());
553 MidiTrack::filter_channels (BufferSet& bufs, ChannelMode mode, uint32_t mask)
555 if (mode == AllChannels) {
559 MidiBuffer& buf (bufs.get_midi (0));
561 for (MidiBuffer::iterator e = buf.begin(); e != buf.end(); ) {
563 Evoral::MIDIEvent<framepos_t> ev(*e, false);
565 if (ev.is_channel_event()) {
568 if (0 == ((1<<ev.channel()) & mask)) {
575 ev.set_channel (PBD::ffs (mask) - 1);
579 /* handled by the opening if() */
590 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
592 MidiBuffer& buf (bufs.get_midi (0));
594 update_controls (bufs);
596 // Append immediate events
598 if (_immediate_events.read_space()) {
600 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
601 name(), _immediate_events.read_space()));
603 /* write as many of the immediate events as we can, but give "true" as
604 * the last argument ("stop on overflow in destination") so that we'll
605 * ship the rest out next time.
607 * the Port::port_offset() + (nframes-1) argument puts all these events at the last
608 * possible position of the output buffer, so that we do not
609 * violate monotonicity when writing. Port::port_offset() will
610 * be non-zero if we're in a split process cycle.
612 _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
617 MidiTrack::export_stuff (BufferSet& buffers,
620 boost::shared_ptr<Processor> endpoint,
621 bool include_endpoint,
625 if (buffers.count().n_midi() == 0) {
629 boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
631 Glib::Threads::RWLock::ReaderLock rlock (_processor_lock);
633 boost::shared_ptr<MidiPlaylist> mpl = boost::dynamic_pointer_cast<MidiPlaylist>(diskstream->playlist());
638 buffers.get_midi(0).clear();
639 if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) {
643 //bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze);
648 boost::shared_ptr<Region>
649 MidiTrack::bounce (InterThreadInfo& itt)
651 return bounce_range (_session.current_start_frame(), _session.current_end_frame(), itt, main_outs(), false);
654 boost::shared_ptr<Region>
655 MidiTrack::bounce_range (framepos_t start,
657 InterThreadInfo& itt,
658 boost::shared_ptr<Processor> endpoint,
659 bool include_endpoint)
661 vector<boost::shared_ptr<Source> > srcs;
662 return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false);
666 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
668 std::cerr << "MIDI freeze currently unsupported" << std::endl;
672 MidiTrack::unfreeze ()
674 _freeze_record.state = UnFrozen;
675 FreezeChange (); /* EMIT SIGNAL */
679 MidiTrack::set_note_mode (NoteMode m)
682 midi_diskstream()->set_note_mode(m);
686 MidiTrack::describe_parameter (Evoral::Parameter param)
688 const std::string str(instrument_info().get_controller_name(param));
689 return str.empty() ? Automatable::describe_parameter(param) : str;
693 MidiTrack::midi_panic()
695 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
696 for (uint8_t channel = 0; channel <= 0xF; channel++) {
697 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), ((uint8_t) MIDI_CTL_SUSTAIN), 0 };
698 write_immediate_event(3, ev);
699 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
700 write_immediate_event(3, ev);
701 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
702 write_immediate_event(3, ev);
706 /** \return true on success, false on failure (no buffer space left)
709 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
711 if (!Evoral::midi_event_is_valid(buf, size)) {
712 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
715 const uint32_t type = midi_parameter_type(buf[0]);
716 return (_immediate_events.write (0, type, size, buf) == size);
720 MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
722 switch (param.type()) {
723 case MidiCCAutomation:
724 case MidiPgmChangeAutomation:
725 case MidiPitchBenderAutomation:
726 case MidiChannelPressureAutomation:
727 case MidiSystemExclusiveAutomation:
728 /* The track control for MIDI parameters is for immediate events to act
729 as a control surface, write/touch for them is not currently
733 Automatable::set_parameter_automation_state(param, state);
738 MidiTrack::MidiControl::set_value(double val)
740 const Evoral::Parameter ¶meter = _list ? _list->parameter() : Control::parameter();
741 const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
744 if (isinf_local(val)) {
745 cerr << "MIDIControl value is infinity" << endl;
746 } else if (isnan_local(val)) {
747 cerr << "MIDIControl value is NaN" << endl;
748 } else if (val < desc.lower) {
749 cerr << "MIDIControl value is < " << desc.lower << endl;
750 } else if (val > desc.upper) {
751 cerr << "MIDIControl value is > " << desc.upper << endl;
760 assert(val <= desc.upper);
761 if ( ! _list || ! automation_playback()) {
763 uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
764 switch(parameter.type()) {
765 case MidiCCAutomation:
766 ev[0] += MIDI_CMD_CONTROL;
767 ev[1] = parameter.id();
771 case MidiPgmChangeAutomation:
773 ev[0] += MIDI_CMD_PGM_CHANGE;
777 case MidiChannelPressureAutomation:
779 ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
783 case MidiPitchBenderAutomation:
784 ev[0] += MIDI_CMD_BENDER;
785 ev[1] = 0x7F & int(val);
786 ev[2] = 0x7F & (int(val) >> 7);
792 _route->write_immediate_event(size, ev);
795 AutomationControl::set_value(val);
799 MidiTrack::set_step_editing (bool yn)
801 if (_session.record_status() != Session::Disabled) {
805 if (yn != _step_editing) {
807 StepEditStatusChange (yn);
811 boost::shared_ptr<SMFSource>
812 MidiTrack::write_source (uint32_t)
814 return midi_diskstream()->write_source ();
818 MidiTrack::set_playback_channel_mode(ChannelMode mode, uint16_t mask)
820 ChannelMode old = get_playback_channel_mode ();
821 uint16_t old_mask = get_playback_channel_mask ();
823 if (old != mode || mask != old_mask) {
824 _set_playback_channel_mode (mode, mask);
825 PlaybackChannelModeChanged ();
826 _session.set_dirty ();
831 MidiTrack::set_capture_channel_mode(ChannelMode mode, uint16_t mask)
833 ChannelMode old = get_capture_channel_mode ();
834 uint16_t old_mask = get_capture_channel_mask ();
836 if (old != mode || mask != old_mask) {
837 _set_capture_channel_mode (mode, mask);
838 CaptureChannelModeChanged ();
839 _session.set_dirty ();
844 MidiTrack::set_playback_channel_mask (uint16_t mask)
846 uint16_t old = get_playback_channel_mask();
849 _set_playback_channel_mask (mask);
850 PlaybackChannelMaskChanged ();
851 _session.set_dirty ();
856 MidiTrack::set_capture_channel_mask (uint16_t mask)
858 uint16_t old = get_capture_channel_mask();
861 _set_capture_channel_mask (mask);
862 CaptureChannelMaskChanged ();
863 _session.set_dirty ();
867 boost::shared_ptr<MidiPlaylist>
868 MidiTrack::midi_playlist ()
870 return midi_diskstream()->midi_playlist ();
874 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
876 DataRecorded (src); /* EMIT SIGNAL */
880 MidiTrack::input_active () const
882 return _input_active;
886 MidiTrack::set_input_active (bool yn)
888 if (yn != _input_active) {
890 map_input_active (yn);
891 InputActiveChanged (); /* EMIT SIGNAL */
896 MidiTrack::map_input_active (bool yn)
902 PortSet& ports (_input->ports());
904 for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
905 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
906 if (yn != mp->input_active()) {
907 mp->set_input_active (yn);
913 MidiTrack::track_input_active (IOChange change, void* /* src */)
915 if (change.type & IOChange::ConfigurationChanged) {
916 map_input_active (_input_active);
920 boost::shared_ptr<Diskstream>
921 MidiTrack::diskstream_factory (XMLNode const & node)
923 return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
926 boost::shared_ptr<MidiBuffer>
927 MidiTrack::get_gui_feed_buffer () const
929 return midi_diskstream()->get_gui_feed_buffer ();
933 MidiTrack::act_on_mute ()
935 /* this is called right after our mute status has changed.
936 if we are now muted, send suitable output to shutdown
939 XXX we should should also stop all relevant note trackers.
942 /* If we haven't got a diskstream yet, there's nothing to worry about,
943 and we can't call get_channel_mask() anyway.
945 if (!midi_diskstream()) {
949 if (muted() || _mute_master->muted_by_others_at(MuteMaster::AllPoints)) {
950 /* only send messages for channels we are using */
952 uint16_t mask = get_playback_channel_mask();
954 for (uint8_t channel = 0; channel <= 0xF; channel++) {
956 if ((1<<channel) & mask) {
958 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
959 uint8_t ev[3] = { ((uint8_t) (MIDI_CMD_CONTROL | channel)), MIDI_CTL_SUSTAIN, 0 };
960 write_immediate_event (3, ev);
962 /* Note we do not send MIDI_CTL_ALL_NOTES_OFF here, since this may
963 silence notes that came from another non-muted track. */
967 /* Resolve active notes. */
968 midi_diskstream()->resolve_tracker(_immediate_events, 0);
973 MidiTrack::set_monitoring (MonitorChoice mc)
975 if (mc != _monitoring) {
977 Track::set_monitoring (mc);
979 /* monitoring state changed, so flush out any on notes at the
983 PortSet& ports (_output->ports());
985 for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
986 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
988 mp->require_resolve ();
992 boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
995 md->reset_tracker ();
1001 MidiTrack::monitoring_state () const
1003 MonitorState ms = Track::monitoring_state();
1004 if (ms == MonitoringSilence) {
1005 return MonitoringInput;