Insert/Redirect refactoring, towards better MIDI support in mixer strip, and
[ardour.git] / libs / ardour / midi_track.cc
1 /*
2     Copyright (C) 2006 Paul Davis 
3         By Dave Robillard, 2006
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 #include <pbd/error.h>
20 #include <sigc++/retype.h>
21 #include <sigc++/retype_return.h>
22 #include <sigc++/bind.h>
23
24 #include <pbd/enumwriter.h>
25
26 #include <ardour/midi_track.h>
27 #include <ardour/midi_diskstream.h>
28 #include <ardour/session.h>
29 #include <ardour/redirect.h>
30 #include <ardour/midi_region.h>
31 #include <ardour/midi_source.h>
32 #include <ardour/route_group_specialized.h>
33 #include <ardour/insert.h>
34 #include <ardour/midi_playlist.h>
35 #include <ardour/panner.h>
36 #include <ardour/utils.h>
37 #include <ardour/buffer_set.h>
38 #include <ardour/meter.h>
39
40 #include "i18n.h"
41
42 using namespace std;
43 using namespace ARDOUR;
44 using namespace PBD;
45
46 MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
47         : Track (sess, name, flag, mode, DataType::MIDI)
48 {
49         MidiDiskstream::Flag dflags = MidiDiskstream::Flag (0);
50
51         if (_flags & Hidden) {
52                 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Hidden);
53         } else {
54                 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Recordable);
55         }
56
57         assert(mode != Destructive);
58
59         boost::shared_ptr<MidiDiskstream> ds (new MidiDiskstream (_session, name, dflags));
60         _session.add_diskstream (ds);
61
62         set_diskstream (boost::dynamic_pointer_cast<MidiDiskstream> (ds));
63         
64         _declickable = true;
65         _freeze_record.state = NoFreeze;
66         _saved_meter_point = _meter_point;
67         _mode = mode;
68
69         set_input_minimum(ChanCount(DataType::MIDI, 1));
70         set_input_maximum(ChanCount(DataType::MIDI, 1));
71         set_output_minimum(ChanCount(DataType::MIDI, 1));
72         set_output_maximum(ChanCount(DataType::MIDI, 1));
73 }
74
75 MidiTrack::MidiTrack (Session& sess, const XMLNode& node)
76         : Track (sess, node)
77 {
78         _set_state(node, false);
79         
80         set_input_minimum(ChanCount(DataType::MIDI, 1));
81         set_input_maximum(ChanCount(DataType::MIDI, 1));
82         set_output_minimum(ChanCount(DataType::MIDI, 1));
83         set_output_maximum(ChanCount(DataType::MIDI, 1));
84 }
85
86 MidiTrack::~MidiTrack ()
87 {
88 }
89
90
91 int
92 MidiTrack::set_diskstream (boost::shared_ptr<MidiDiskstream> ds)
93 {
94         _diskstream = ds;
95         _diskstream->set_io (*this);
96         _diskstream->set_destructive (_mode == Destructive);
97
98         _diskstream->set_record_enabled (false);
99         //_diskstream->monitor_input (false);
100
101         ic_connection.disconnect();
102         ic_connection = input_changed.connect (mem_fun (*_diskstream, &MidiDiskstream::handle_input_change));
103
104         DiskstreamChanged (); /* EMIT SIGNAL */
105
106         return 0;
107 }       
108
109 int 
110 MidiTrack::use_diskstream (string name)
111 {
112         boost::shared_ptr<MidiDiskstream> dstream;
113
114         if ((dstream = boost::dynamic_pointer_cast<MidiDiskstream>(_session.diskstream_by_name (name))) == 0) {
115                 error << string_compose(_("MidiTrack: midi diskstream \"%1\" not known by session"), name) << endmsg;
116                 return -1;
117         }
118         
119         return set_diskstream (dstream);
120 }
121
122 int 
123 MidiTrack::use_diskstream (const PBD::ID& id)
124 {
125         boost::shared_ptr<MidiDiskstream> dstream;
126
127         if ((dstream = boost::dynamic_pointer_cast<MidiDiskstream> (_session.diskstream_by_id (id))) == 0) {
128                 error << string_compose(_("MidiTrack: midi diskstream \"%1\" not known by session"), id) << endmsg;
129                 return -1;
130         }
131         
132         return set_diskstream (dstream);
133 }
134
135 boost::shared_ptr<MidiDiskstream>
136 MidiTrack::midi_diskstream() const
137 {
138         return boost::dynamic_pointer_cast<MidiDiskstream>(_diskstream);
139 }
140
141 int
142 MidiTrack::set_state (const XMLNode& node)
143 {
144         return _set_state (node, true);
145 }
146
147 int
148 MidiTrack::_set_state (const XMLNode& node, bool call_base)
149 {
150         const XMLProperty *prop;
151         XMLNodeConstIterator iter;
152
153         if (Route::_set_state (node, call_base)) {
154                 return -1;
155         }
156         
157         if ((prop = node.property (X_("mode"))) != 0) {
158                 _mode = TrackMode (string_2_enum (prop->value(), _mode));
159         } else {
160                 _mode = Normal;
161         }
162
163         if ((prop = node.property ("diskstream-id")) == 0) {
164                 
165                 /* some old sessions use the diskstream name rather than the ID */
166
167                 if ((prop = node.property ("diskstream")) == 0) {
168                         fatal << _("programming error: MidiTrack given state without diskstream!") << endmsg;
169                         /*NOTREACHED*/
170                         return -1;
171                 }
172
173                 if (use_diskstream (prop->value())) {
174                         return -1;
175                 }
176
177         } else {
178                 
179                 PBD::ID id (prop->value());
180                 
181                 if (use_diskstream (id)) {
182                         return -1;
183                 }
184         }
185
186
187         XMLNodeList nlist;
188         XMLNodeConstIterator niter;
189         XMLNode *child;
190
191         nlist = node.children();
192         for (niter = nlist.begin(); niter != nlist.end(); ++niter){
193                 child = *niter;
194
195                 if (child->name() == X_("recenable")) {
196                         _rec_enable_control.set_state (*child);
197                         _session.add_controllable (&_rec_enable_control);
198                 }
199         }
200
201         pending_state = const_cast<XMLNode*> (&node);
202
203         _session.StateReady.connect (mem_fun (*this, &MidiTrack::set_state_part_two));
204
205         return 0;
206 }
207
208 XMLNode& 
209 MidiTrack::state(bool full_state)
210 {
211         XMLNode& root (Route::state(full_state));
212         XMLNode* freeze_node;
213         char buf[64];
214
215         if (_freeze_record.playlist) {
216                 XMLNode* inode;
217
218                 freeze_node = new XMLNode (X_("freeze-info"));
219                 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
220                 freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
221
222                 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
223                         inode = new XMLNode (X_("insert"));
224                         (*i)->id.print (buf, sizeof(buf));
225                         inode->add_property (X_("id"), buf);
226                         inode->add_child_copy ((*i)->state);
227                 
228                         freeze_node->add_child_nocopy (*inode);
229                 }
230
231                 root.add_child_nocopy (*freeze_node);
232         }
233
234         /* Alignment: act as a proxy for the diskstream */
235         
236         XMLNode* align_node = new XMLNode (X_("alignment"));
237         AlignStyle as = _diskstream->alignment_style ();
238         align_node->add_property (X_("style"), enum_2_string (as));
239         root.add_child_nocopy (*align_node);
240
241         root.add_property (X_("mode"), enum_2_string (_mode));
242         
243         /* we don't return diskstream state because we don't
244            own the diskstream exclusively. control of the diskstream
245            state is ceded to the Session, even if we create the
246            diskstream.
247         */
248
249         _diskstream->id().print (buf, sizeof(buf));
250         root.add_property ("diskstream-id", buf);
251         
252         root.add_child_nocopy (_rec_enable_control.get_state());
253
254         return root;
255 }
256
257 void
258 MidiTrack::set_state_part_two ()
259 {
260         XMLNode* fnode;
261         XMLProperty* prop;
262         LocaleGuard lg (X_("POSIX"));
263
264         /* This is called after all session state has been restored but before
265            have been made ports and connections are established.
266         */
267
268         if (pending_state == 0) {
269                 return;
270         }
271
272         if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
273
274                 
275                 _freeze_record.have_mementos = false;
276                 _freeze_record.state = Frozen;
277                 
278                 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
279                         delete *i;
280                 }
281                 _freeze_record.insert_info.clear ();
282                 
283                 if ((prop = fnode->property (X_("playlist"))) != 0) {
284                         boost::shared_ptr<Playlist> pl = _session.playlist_by_name (prop->value());
285                         if (pl) {
286                                 _freeze_record.playlist = boost::dynamic_pointer_cast<MidiPlaylist> (pl);
287                         } else {
288                                 _freeze_record.playlist.reset();
289                                 _freeze_record.state = NoFreeze;
290                         return;
291                         }
292                 }
293                 
294                 if ((prop = fnode->property (X_("state"))) != 0) {
295                         _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
296                 }
297                 
298                 XMLNodeConstIterator citer;
299                 XMLNodeList clist = fnode->children();
300                 
301                 for (citer = clist.begin(); citer != clist.end(); ++citer) {
302                         if ((*citer)->name() != X_("insert")) {
303                                 continue;
304                         }
305                         
306                         if ((prop = (*citer)->property (X_("id"))) == 0) {
307                                 continue;
308                         }
309                         
310                         FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo (*((*citer)->children().front()),
311                                                                                    boost::shared_ptr<Insert>());
312                         frii->id = prop->value ();
313                         _freeze_record.insert_info.push_back (frii);
314                 }
315         }
316
317         /* Alignment: act as a proxy for the diskstream */
318
319         if ((fnode = find_named_node (*pending_state, X_("alignment"))) != 0) {
320
321                 if ((prop = fnode->property (X_("style"))) != 0) {
322
323                         /* fix for older sessions from before EnumWriter */
324
325                         string pstr;
326
327                         if (prop->value() == "capture") {
328                                 pstr = "CaptureTime";
329                         } else if (prop->value() == "existing") {
330                                 pstr = "ExistingMaterial";
331                         } else {
332                                 pstr = prop->value();
333                         }
334
335                         AlignStyle as = AlignStyle (string_2_enum (pstr, as));
336                         _diskstream->set_persistent_align_style (as);
337                 }
338         }
339         return;
340 }       
341
342 int 
343 MidiTrack::no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset, 
344                      bool session_state_changing, bool can_record, bool rec_monitors_input)
345 {
346         if (n_outputs().n_midi() == 0) {
347                 //return 0;
348                 throw; // FIXME
349         }
350
351         if (!_active) {
352                 silence (nframes, offset);
353                 //return 0; // FIXME
354         }
355
356         if (session_state_changing) {
357
358                 /* XXX is this safe to do against transport state changes? */
359
360                 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
361                 return 0;
362         }
363
364         midi_diskstream()->check_record_status (start_frame, nframes, can_record);
365
366         bool send_silence;
367         
368         if (_have_internal_generator) {
369                 /* since the instrument has no input streams,
370                    there is no reason to send any signal
371                    into the route.
372                 */
373                 send_silence = true;
374         } else {
375
376                 if (Config->get_auto_input()) {
377                         if (Config->get_monitoring_model() == SoftwareMonitoring) {
378                                 send_silence = false;
379                         } else {
380                                 send_silence = true;
381                         }
382                 } else {
383                         if (_diskstream->record_enabled()) {
384                                 if (Config->get_monitoring_model() == SoftwareMonitoring) {
385                                         send_silence = false;
386                                 } else {
387                                         send_silence = true;
388                                 }
389                         } else {
390                                 send_silence = true;
391                         }
392                 }
393         }
394
395         apply_gain_automation = false;
396
397         if (send_silence) {
398                 
399                 /* if we're sending silence, but we want the meters to show levels for the signal,
400                    meter right here.
401                 */
402                 
403                 if (_have_internal_generator) {
404                         passthru_silence (start_frame, end_frame, nframes, offset, 0, true);
405                 } else {
406                         if (_meter_point == MeterInput) {
407                                 just_meter_input (start_frame, end_frame, nframes, offset);
408                         }
409                         passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
410                 }
411
412         } else {
413         
414                 /* we're sending signal, but we may still want to meter the input. 
415                  */
416
417                 passthru (start_frame, end_frame, nframes, offset, 0, (_meter_point == MeterInput));
418         }
419
420         return 0;
421 }
422
423 int
424 MidiTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset, int declick,
425                   bool can_record, bool rec_monitors_input)
426 {
427         int dret;
428         boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
429
430         if (n_outputs().n_total() == 0 && _inserts.empty()) {
431                 return 0;
432         }
433
434         if (!_active) {
435                 silence (nframes, offset);
436                 return 0;
437         }
438
439         nframes_t transport_frame = _session.transport_frame();
440
441         if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) {
442                 /* need to do this so that the diskstream sets its
443                    playback distance to zero, thus causing diskstream::commit
444                    to do nothing.
445                    */
446                 return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
447         } 
448
449         _silent = false;
450
451         if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
452
453                 silence (nframes, offset);
454
455                 return dret;
456         }
457
458         /* special condition applies */
459
460         if (_meter_point == MeterInput) {
461                 just_meter_input (start_frame, end_frame, nframes, offset);
462         }
463
464         if (diskstream->record_enabled() && !can_record && !Config->get_auto_input()) {
465
466                 /* not actually recording, but we want to hear the input material anyway,
467                    at least potentially (depending on monitoring options)
468                    */
469
470                 passthru (start_frame, end_frame, nframes, offset, 0, true);
471
472         } else {
473                 /*
474                    XXX is it true that the earlier test on n_outputs()
475                    means that we can avoid checking it again here? i think
476                    so, because changing the i/o configuration of an IO
477                    requires holding the AudioEngine lock, which we hold
478                    while in the process() tree.
479                    */
480
481
482                 /* copy the diskstream data to all output buffers */
483
484                 //const size_t limit = n_process_buffers().n_audio();
485                 BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
486
487                 diskstream->get_playback(bufs.get_midi(0), start_frame, end_frame);
488
489                 process_output_buffers (bufs, start_frame, end_frame, nframes, offset,
490                                 (!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
491         
492         }
493
494         return 0;
495 }
496
497 int
498 MidiTrack::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset, 
499                          bool can_record, bool rec_monitors_input)
500 {
501         if (n_outputs().n_midi() == 0 && _inserts.empty()) {
502                 return 0;
503         }
504
505         if (!_active) {
506                 silence (nframes, offset);
507                 return 0;
508         }
509
510         _silent = true;
511         apply_gain_automation = false;
512
513         silence (nframes, offset);
514
515         return midi_diskstream()->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
516 }
517
518 void
519 MidiTrack::process_output_buffers (BufferSet& bufs,
520                                nframes_t start_frame, nframes_t end_frame, 
521                                nframes_t nframes, nframes_t offset, bool with_inserts, int declick,
522                                bool meter)
523 {
524         /* There's no such thing as a MIDI bus for the time being.
525          * We'll do all the MIDI route work here for now, but the long-term goal is to have
526          * Route::process_output_buffers handle everything */
527         
528         if (meter && (_meter_point == MeterInput || _meter_point == MeterPreFader)) {
529                 _meter->run(bufs, start_frame, end_frame, nframes, offset);
530         }
531
532         // Run all inserts
533         if (with_inserts) {
534                 Glib::RWLock::ReaderLock rm (insert_lock, Glib::TRY_LOCK);
535                 if (rm.locked()) {
536                         for (InsertList::iterator i = _inserts.begin(); i != _inserts.end(); ++i) {
537                                 (*i)->run (bufs, start_frame, end_frame, nframes, offset);
538                         }
539                 } 
540         }
541         
542         if (meter && (_meter_point == MeterPostFader)) {
543                 _meter->run(bufs, start_frame, end_frame, nframes, offset);
544         }
545         
546         // Main output stage
547         if (muted()) {
548                 IO::silence(nframes, offset);
549         } else {
550                 deliver_output(bufs, start_frame, end_frame, nframes, offset);
551         }
552 }
553
554 int
555 MidiTrack::export_stuff (BufferSet& bufs, nframes_t nframes, nframes_t end_frame)
556 {
557         return -1;
558 }
559
560 void
561 MidiTrack::set_latency_delay (nframes_t longest_session_latency)
562 {
563         Route::set_latency_delay (longest_session_latency);
564         _diskstream->set_roll_delay (_roll_delay);
565 }
566
567 void
568 MidiTrack::bounce (InterThreadInfo& itt)
569 {
570         throw;
571         //vector<MidiSource*> srcs;
572         //_session.write_one_midi_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
573 }
574
575
576 void
577 MidiTrack::bounce_range (nframes_t start, nframes_t end, InterThreadInfo& itt)
578 {
579         throw;
580         //vector<MidiSource*> srcs;
581         //_session.write_one_midi_track (*this, start, end, false, srcs, itt);
582 }
583
584 void
585 MidiTrack::freeze (InterThreadInfo& itt)
586 {
587 }
588
589 void
590 MidiTrack::unfreeze ()
591 {
592         _freeze_record.state = UnFrozen;
593         FreezeChange (); /* EMIT SIGNAL */
594 }
595
596 int
597 MidiTrack::set_mode (TrackMode m)
598 {
599         assert(_diskstream);
600
601         if (m != _mode) {
602
603                 if (_diskstream->set_destructive (m == Destructive)) {
604                         return -1;
605                 }
606
607                 _mode = m;
608                 
609                 TrackModeChanged (); /* EMIT SIGNAL */
610         }
611
612         return 0;
613 }