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