restore ability to create TOC and CUE files during export. this is an option in a...
[ardour.git] / libs / ardour / midi_track.cc
1 /*
2     Copyright (C) 2006 Paul Davis
3     Author: David Robillard
4
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.
9
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.
14
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.
18 */
19
20 #include "pbd/error.h"
21
22 #include "pbd/enumwriter.h"
23 #include "pbd/convert.h"
24 #include "midi++/events.h"
25 #include "evoral/midi_util.h"
26
27 #include "ardour/amp.h"
28 #include "ardour/buffer_set.h"
29 #include "ardour/debug.h"
30 #include "ardour/delivery.h"
31 #include "ardour/io_processor.h"
32 #include "ardour/meter.h"
33 #include "ardour/midi_diskstream.h"
34 #include "ardour/midi_playlist.h"
35 #include "ardour/midi_port.h"
36 #include "ardour/midi_region.h"
37 #include "ardour/midi_source.h"
38 #include "ardour/midi_track.h"
39 #include "ardour/panner.h"
40 #include "ardour/port.h"
41 #include "ardour/processor.h"
42 #include "ardour/route_group_specialized.h"
43 #include "ardour/session.h"
44 #include "ardour/session_playlists.h"
45 #include "ardour/utils.h"
46
47 #include "i18n.h"
48
49 using namespace std;
50 using namespace ARDOUR;
51 using namespace PBD;
52
53 MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
54         : Track (sess, name, flag, mode, DataType::MIDI)
55         , _immediate_events(1024) // FIXME: size?
56         , _step_edit_ring_buffer(64) // FIXME: size?
57         , _note_mode(Sustained)
58         , _step_editing (false)
59         , _midi_thru (true)
60         , _input_active (true)
61 {
62 }
63
64 MidiTrack::~MidiTrack ()
65 {
66 }
67
68 int
69 MidiTrack::init ()
70 {
71         if (Track::init ()) {
72                 return -1;
73         }
74
75         _input->changed.connect_same_thread (*this, boost::bind (&MidiTrack::track_input_active, this, _1, _2));
76
77         return 0;
78 }
79
80 boost::shared_ptr<Diskstream>
81 MidiTrack::create_diskstream ()
82 {
83         MidiDiskstream::Flag dflags = MidiDiskstream::Flag (0);
84
85         if (_flags & Hidden) {
86                 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Hidden);
87         } else {
88                 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Recordable);
89         }
90
91         assert(_mode != Destructive);
92
93         return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, name(), dflags));
94 }
95
96
97 void
98 MidiTrack::set_record_enabled (bool yn, void *src)
99 {
100         if (_step_editing) {
101                 return;
102         }
103
104         Track::set_record_enabled (yn, src);
105 }
106
107 void
108 MidiTrack::set_diskstream (boost::shared_ptr<Diskstream> ds)
109 {
110         Track::set_diskstream (ds);
111
112         midi_diskstream()->reset_tracker ();    
113
114         _diskstream->set_track (this);
115         _diskstream->set_destructive (_mode == Destructive);
116         _diskstream->set_record_enabled (false);
117
118         _diskstream_data_recorded_connection.disconnect ();
119         boost::shared_ptr<MidiDiskstream> mds = boost::dynamic_pointer_cast<MidiDiskstream> (ds);
120         mds->DataRecorded.connect_same_thread (
121                 _diskstream_data_recorded_connection,
122                 boost::bind (&MidiTrack::diskstream_data_recorded, this, _1));
123
124         DiskstreamChanged (); /* EMIT SIGNAL */
125 }
126
127 boost::shared_ptr<MidiDiskstream>
128 MidiTrack::midi_diskstream() const
129 {
130         return boost::dynamic_pointer_cast<MidiDiskstream>(_diskstream);
131 }
132
133 int
134 MidiTrack::set_state (const XMLNode& node, int version)
135 {
136         const XMLProperty *prop;
137
138         if (Track::set_state (node, version)) {
139                 return -1;
140         }
141
142         // No destructive MIDI tracks (yet?)
143         _mode = Normal;
144
145         if ((prop = node.property (X_("note-mode"))) != 0) {
146                 _note_mode = NoteMode (string_2_enum (prop->value(), _note_mode));
147         } else {
148                 _note_mode = Sustained;
149         }
150
151         if ((prop = node.property ("midi-thru")) != 0) {
152                 set_midi_thru (string_is_affirmative (prop->value()));
153         }
154
155         if ((prop = node.property ("input-active")) != 0) {
156                 set_input_active (string_is_affirmative (prop->value()));
157         }
158
159         pending_state = const_cast<XMLNode*> (&node);
160
161         if (_session.state_of_the_state() & Session::Loading) {
162                 _session.StateReady.connect_same_thread (
163                         *this, boost::bind (&MidiTrack::set_state_part_two, this));
164         } else {
165                 set_state_part_two ();
166         }
167
168         return 0;
169 }
170
171 XMLNode&
172 MidiTrack::state(bool full_state)
173 {
174         XMLNode& root (Track::state(full_state));
175         XMLNode* freeze_node;
176         char buf[64];
177
178         if (_freeze_record.playlist) {
179                 XMLNode* inode;
180
181                 freeze_node = new XMLNode (X_("freeze-info"));
182                 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
183                 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
184
185                 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
186                         inode = new XMLNode (X_("processor"));
187                         (*i)->id.print (buf, sizeof(buf));
188                         inode->add_property (X_("id"), buf);
189                         inode->add_child_copy ((*i)->state);
190
191                         freeze_node->add_child_nocopy (*inode);
192                 }
193
194                 root.add_child_nocopy (*freeze_node);
195         }
196
197         root.add_property (X_("note-mode"), enum_2_string (_note_mode));
198
199         root.add_property ("step-editing", (_step_editing ? "yes" : "no"));
200         root.add_property ("note-mode", enum_2_string (_note_mode));
201         root.add_property ("midi-thru", (_midi_thru ? "yes" : "no"));
202         root.add_property ("input-active", (_input_active ? "yes" : "no"));
203
204         return root;
205 }
206
207 void
208 MidiTrack::set_state_part_two ()
209 {
210         XMLNode* fnode;
211         XMLProperty* prop;
212         LocaleGuard lg (X_("POSIX"));
213
214         /* This is called after all session state has been restored but before
215            have been made ports and connections are established.
216         */
217
218         if (pending_state == 0) {
219                 return;
220         }
221
222         if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
223
224                 _freeze_record.state = Frozen;
225
226                 for (vector<FreezeRecordProcessorInfo*>::iterator i = _freeze_record.processor_info.begin(); i != _freeze_record.processor_info.end(); ++i) {
227                         delete *i;
228                 }
229                 _freeze_record.processor_info.clear ();
230
231                 if ((prop = fnode->property (X_("playlist"))) != 0) {
232                         boost::shared_ptr<Playlist> pl = _session.playlists->by_name (prop->value());
233                         if (pl) {
234                                 _freeze_record.playlist = boost::dynamic_pointer_cast<MidiPlaylist> (pl);
235                         } else {
236                                 _freeze_record.playlist.reset();
237                                 _freeze_record.state = NoFreeze;
238                         return;
239                         }
240                 }
241
242                 if ((prop = fnode->property (X_("state"))) != 0) {
243                         _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
244                 }
245
246                 XMLNodeConstIterator citer;
247                 XMLNodeList clist = fnode->children();
248
249                 for (citer = clist.begin(); citer != clist.end(); ++citer) {
250                         if ((*citer)->name() != X_("processor")) {
251                                 continue;
252                         }
253
254                         if ((prop = (*citer)->property (X_("id"))) == 0) {
255                                 continue;
256                         }
257
258                         FreezeRecordProcessorInfo* frii = new FreezeRecordProcessorInfo (*((*citer)->children().front()),
259                                                                                    boost::shared_ptr<Processor>());
260                         frii->id = prop->value ();
261                         _freeze_record.processor_info.push_back (frii);
262                 }
263         }
264
265         if (midi_diskstream ()) {
266                 midi_diskstream()->set_block_size (_session.get_block_size ());
267         }
268
269         return;
270 }
271
272 int
273 MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& need_butler)
274 {
275         Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
276         if (!lm.locked()) {
277                 return 0;
278         }
279
280         boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
281
282         automation_snapshot (start_frame);
283
284         if (n_outputs().n_total() == 0 && _processors.empty()) {
285                 return 0;
286         }
287
288         if (!_active) {
289                 silence (nframes);
290                 return 0;
291         }
292
293         framepos_t transport_frame = _session.transport_frame();
294
295         int dret;
296         framecnt_t playback_distance;
297
298         if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
299                 /* need to do this so that the diskstream sets its
300                    playback distance to zero, thus causing diskstream::commit
301                    to do nothing.
302                    */
303                 dret = diskstream->process (transport_frame, 0, playback_distance);
304                 need_butler = diskstream->commit (playback_distance);
305                 return dret;
306         }
307
308         _silent = false;
309
310         if ((dret = diskstream->process (transport_frame, nframes, playback_distance)) != 0) {
311                 need_butler = diskstream->commit (playback_distance);
312                 silence (nframes);
313                 return dret;
314         }
315
316         /* special condition applies */
317
318         if (_meter_point == MeterInput) {
319                 _input->process_input (_meter, start_frame, end_frame, nframes);
320         }
321
322         if (monitoring_state() == MonitoringInput) {
323
324                 /* not actually recording, but we want to hear the input material anyway,
325                    at least potentially (depending on monitoring options)
326                 */
327
328                 passthru (start_frame, end_frame, nframes, 0);
329
330         } else {
331                 /*
332                    XXX is it true that the earlier test on n_outputs()
333                    means that we can avoid checking it again here? i think
334                    so, because changing the i/o configuration of an IO
335                    requires holding the AudioEngine lock, which we hold
336                    while in the process() tree.
337                    */
338
339
340                 /* copy the diskstream data to all output buffers */
341
342                 //const size_t limit = n_process_buffers().n_audio();
343                 BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
344                 MidiBuffer& mbuf (bufs.get_midi (0));
345
346                 /* we are a MIDI track, so we always start the chain with a single-channel diskstream */
347                 ChanCount c;
348                 c.set_audio (0);
349                 c.set_midi (1);
350                 bufs.set_count (c);
351
352                 diskstream->get_playback (mbuf, nframes);
353
354                 /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
355
356                 write_out_of_band_data (bufs, start_frame, end_frame, nframes);
357
358                 /* final argument: don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
359
360                 process_output_buffers (
361                         bufs, start_frame, end_frame, nframes,
362                         declick, (!diskstream->record_enabled() && !_session.transport_stopped())
363                         );
364         }
365
366         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
367                 boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery> (*i);
368                 if (d) {
369                         d->flush_buffers (nframes, end_frame - start_frame - 1);
370                 }
371         }
372
373         need_butler = diskstream->commit (playback_distance);
374         
375         return 0;
376 }
377
378 int
379 MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing)
380 {
381         int ret = Track::no_roll (nframes, start_frame, end_frame, state_changing);
382
383         if (ret == 0 && _step_editing) {
384                 push_midi_input_to_step_edit_ringbuffer (nframes);
385         }
386
387         return ret;
388 }
389
390 void
391 MidiTrack::realtime_locate ()
392 {
393         Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
394
395         if (!lm.locked ()) {
396                 return;
397         }
398
399         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
400                 (*i)->realtime_locate ();
401         }
402
403         midi_diskstream()->reset_tracker ();
404 }
405
406 void
407 MidiTrack::realtime_handle_transport_stopped ()
408 {
409         Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
410
411         if (!lm.locked ()) {
412                 return;
413         }
414
415         for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
416                 (*i)->realtime_handle_transport_stopped ();
417         }
418 }
419
420 void
421 MidiTrack::push_midi_input_to_step_edit_ringbuffer (framecnt_t nframes)
422 {
423         PortSet& ports (_input->ports());
424
425         for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
426
427                 Buffer& b (p->get_buffer (nframes));
428                 const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
429                 assert (mb);
430
431                 for (MidiBuffer::const_iterator e = mb->begin(); e != mb->end(); ++e) {
432
433                         const Evoral::MIDIEvent<framepos_t> ev(*e, false);
434
435                         /* note on, since for step edit, note length is determined
436                            elsewhere
437                         */
438
439                         if (ev.is_note_on()) {
440                                 /* we don't care about the time for this purpose */
441                                 _step_edit_ring_buffer.write (0, ev.type(), ev.size(), ev.buffer());
442                         }
443                 }
444         }
445 }
446
447 void
448 MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framepos_t /*end*/, framecnt_t nframes)
449 {
450         MidiBuffer& buf (bufs.get_midi (0));
451
452         // Append immediate events
453
454         if (_immediate_events.read_space()) {
455
456                 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
457                                                             name(), _immediate_events.read_space()));
458
459                 /* write as many of the immediate events as we can, but give "true" as
460                  * the last argument ("stop on overflow in destination") so that we'll
461                  * ship the rest out next time.
462                  *
463                  * the (nframes-1) argument puts all these events at the last
464                  * possible position of the output buffer, so that we do not
465                  * violate monotonicity when writing.
466                  */
467
468                 _immediate_events.read (buf, 0, 1, nframes-1, true);
469         }
470
471         // MIDI thru: send incoming data "through" output
472         if (_midi_thru && _session.transport_speed() != 0.0f && _input->n_ports().n_midi()) {
473                 buf.merge_in_place (_input->midi(0)->get_midi_buffer(nframes));
474         }
475 }
476
477 int
478 MidiTrack::export_stuff (BufferSet& /*bufs*/, framecnt_t /*nframes*/, framepos_t /*end_frame*/)
479 {
480         return -1;
481 }
482
483 boost::shared_ptr<Region>
484 MidiTrack::bounce (InterThreadInfo& /*itt*/)
485 {
486         std::cerr << "MIDI bounce currently unsupported" << std::endl;
487         return boost::shared_ptr<Region> ();
488 }
489
490
491 boost::shared_ptr<Region>
492 MidiTrack::bounce_range (framepos_t /*start*/, framepos_t /*end*/, InterThreadInfo& /*itt*/, bool /*enable_processing*/)
493 {
494         std::cerr << "MIDI bounce range currently unsupported" << std::endl;
495         return boost::shared_ptr<Region> ();
496 }
497
498 void
499 MidiTrack::freeze_me (InterThreadInfo& /*itt*/)
500 {
501         std::cerr << "MIDI freeze currently unsupported" << std::endl;
502 }
503
504 void
505 MidiTrack::unfreeze ()
506 {
507         _freeze_record.state = UnFrozen;
508         FreezeChange (); /* EMIT SIGNAL */
509 }
510
511 void
512 MidiTrack::set_note_mode (NoteMode m)
513 {
514         _note_mode = m;
515         midi_diskstream()->set_note_mode(m);
516 }
517
518 void
519 MidiTrack::midi_panic()
520 {
521         DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers panic data\n", name()));
522         for (uint8_t channel = 0; channel <= 0xF; channel++) {
523                 uint8_t ev[3] = { MIDI_CMD_CONTROL | channel, MIDI_CTL_SUSTAIN, 0 };
524                 write_immediate_event(3, ev);
525                 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
526                 write_immediate_event(3, ev);
527                 ev[1] = MIDI_CTL_RESET_CONTROLLERS;
528                 write_immediate_event(3, ev);
529         }
530 }
531
532 /** \return true on success, false on failure (no buffer space left)
533  */
534 bool
535 MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
536 {
537         if (!Evoral::midi_event_is_valid(buf, size)) {
538                 cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl;
539                 return false;
540         }
541         const uint32_t type = EventTypeMap::instance().midi_event_type(buf[0]);
542         return (_immediate_events.write(0, type, size, buf) == size);
543 }
544
545 void
546 MidiTrack::MidiControl::set_value(double val)
547 {
548         bool valid = false;
549         if (isinf(val)) {
550                 cerr << "MIDIControl value is infinity" << endl;
551         } else if (isnan(val)) {
552                 cerr << "MIDIControl value is NaN" << endl;
553         } else if (val < _list->parameter().min()) {
554                 cerr << "MIDIControl value is < " << _list->parameter().min() << endl;
555         } else if (val > _list->parameter().max()) {
556                 cerr << "MIDIControl value is > " << _list->parameter().max() << endl;
557         } else {
558                 valid = true;
559         }
560
561         if (!valid) {
562                 return;
563         }
564
565         assert(val <= _list->parameter().max());
566         if ( ! automation_playback()) {
567                 size_t size = 3;
568                 uint8_t ev[3] = { _list->parameter().channel(), int(val), 0 };
569                 switch(_list->parameter().type()) {
570                 case MidiCCAutomation:
571                         ev[0] += MIDI_CMD_CONTROL;
572                         ev[1] = _list->parameter().id();
573                         ev[2] = int(val);
574                         break;
575
576                 case MidiPgmChangeAutomation:
577                         size = 2;
578                         ev[0] += MIDI_CMD_PGM_CHANGE;
579                         ev[1] = int(val);
580                         break;
581
582                 case MidiChannelPressureAutomation:
583                         size = 2;
584                         ev[0] += MIDI_CMD_CHANNEL_PRESSURE;
585                         ev[1] = int(val);
586                         break;
587
588                 case MidiPitchBenderAutomation:
589                         ev[0] += MIDI_CMD_BENDER;
590                         ev[1] = 0x7F & int(val);
591                         ev[2] = 0x7F & (int(val) >> 7);
592                         break;
593
594                 default:
595                         assert(false);
596                 }
597                 _route->write_immediate_event(size,  ev);
598         }
599
600         AutomationControl::set_value(val);
601 }
602
603 void
604 MidiTrack::set_step_editing (bool yn)
605 {
606         if (_session.record_status() != Session::Disabled) {
607                 return;
608         }
609
610         if (yn != _step_editing) {
611                 _step_editing = yn;
612                 StepEditStatusChange (yn);
613         }
614 }
615
616 void
617 MidiTrack::set_midi_thru (bool yn)
618 {
619         _midi_thru = yn;
620 }
621
622 boost::shared_ptr<SMFSource>
623 MidiTrack::write_source (uint32_t)
624 {
625         return midi_diskstream()->write_source ();
626 }
627
628 void
629 MidiTrack::set_channel_mode (ChannelMode mode, uint16_t mask)
630 {
631         midi_diskstream()->set_channel_mode (mode, mask);
632 }
633
634 ChannelMode
635 MidiTrack::get_channel_mode ()
636 {
637         return midi_diskstream()->get_channel_mode ();
638 }
639
640 uint16_t
641 MidiTrack::get_channel_mask ()
642 {
643         return midi_diskstream()->get_channel_mask ();
644 }
645
646 boost::shared_ptr<MidiPlaylist>
647 MidiTrack::midi_playlist ()
648 {
649         return midi_diskstream()->midi_playlist ();
650 }
651
652 void
653 MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
654 {
655         DataRecorded (src); /* EMIT SIGNAL */
656 }
657
658 bool
659 MidiTrack::input_active () const
660 {
661         return _input_active;
662 }
663
664 void
665 MidiTrack::set_input_active (bool yn)
666 {
667         if (yn != _input_active) {
668                 _input_active = yn;
669                 map_input_active (yn);
670                 InputActiveChanged (); /* EMIT SIGNAL */
671         }
672 }
673
674 void
675 MidiTrack::map_input_active (bool yn)
676 {
677         if (!_input) {
678                 return;
679         }
680
681         PortSet& ports (_input->ports());
682
683         for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
684                 boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
685                 if (yn != mp->input_active()) {
686                         mp->set_input_active (yn);
687                 }
688         }
689 }
690
691 void
692 MidiTrack::track_input_active (IOChange change, void* /* src */)
693 {
694         if (change.type & IOChange::ConfigurationChanged) {
695                 map_input_active (_input_active);
696         }
697 }
698
699 boost::shared_ptr<Diskstream>
700 MidiTrack::diskstream_factory (XMLNode const & node)
701 {
702         return boost::shared_ptr<Diskstream> (new MidiDiskstream (_session, node));
703 }
704
705 boost::shared_ptr<MidiBuffer>
706 MidiTrack::get_gui_feed_buffer () const
707 {
708         return midi_diskstream()->get_gui_feed_buffer ();
709 }
710
711 void
712 MidiTrack::act_on_mute ()
713 {
714         /* this is called right after our mute status has changed.
715            if we are now muted, send suitable output to shutdown
716            all our notes.
717
718            XXX we should should also stop all relevant note trackers.
719         */
720
721         if (muted()) {
722                 /* only send messages for channels we are using */
723
724                 uint16_t mask = get_channel_mask();
725
726                 for (uint8_t channel = 0; channel <= 0xF; channel++) {
727
728                         if ((1<<channel) & mask) {
729
730                                 DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 delivers mute message to channel %2\n", name(), channel+1));
731                                 uint8_t ev[3] = { MIDI_CMD_CONTROL | channel, MIDI_CTL_SUSTAIN, 0 };
732                                 write_immediate_event (3, ev);
733                                 ev[1] = MIDI_CTL_ALL_NOTES_OFF;
734                                 write_immediate_event (3, ev);
735                         }
736                 }
737         }
738 }
739         
740 void
741 MidiTrack::set_monitoring (MonitorChoice mc)
742 {
743         Track::set_monitoring (mc);
744
745         boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
746
747         if (md) {
748                 md->reset_tracker ();
749         }
750 }
751
752 MonitorState
753 MidiTrack::monitoring_state () const
754 {
755         /* Explicit requests */
756         
757         if (_monitoring & MonitorInput) {
758                 return MonitoringInput;
759         }
760                 
761         if (_monitoring & MonitorDisk) {
762                 return MonitoringDisk;
763         }
764
765         if (_session.transport_rolling()) {
766                 return MonitoringDisk;
767         } 
768
769         /* the return value here doesn't mean that we're actually monitoring
770          * input, let alone input *audio*. but it means that we are NOT 
771          * monitoring silence. this allows us to still hear any audio generated
772          * by using internal generation techniques
773          */
774
775         return MonitoringInput;
776 }