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