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