- Changed IO's vector<Port*>'s to PortList
[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
36 #include "i18n.h"
37
38 using namespace std;
39 using namespace ARDOUR;
40 using namespace PBD;
41
42 MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
43         : Track (sess, name, flag, mode, DataType::MIDI)
44 {
45         MidiDiskstream::Flag dflags = MidiDiskstream::Flag (0);
46
47         if (_flags & Hidden) {
48                 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Hidden);
49         } else {
50                 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Recordable);
51         }
52
53         if (mode == Destructive) {
54                 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Destructive);
55         }
56
57         MidiDiskstream* ds = new MidiDiskstream (_session, name, dflags);
58         
59         _declickable = true;
60         _freeze_record.state = NoFreeze;
61         _saved_meter_point = _meter_point;
62         _mode = mode;
63
64         set_diskstream (*ds);
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         if (_diskstream) {
79                 _diskstream->unref();
80         }
81 }
82
83
84 int
85 MidiTrack::set_diskstream (MidiDiskstream& ds)
86 {
87         if (_diskstream) {
88                 _diskstream->unref();
89         }
90
91         _diskstream = &ds.ref();
92         _diskstream->set_io (*this);
93         _diskstream->set_destructive (_mode == Destructive);
94
95         _diskstream->set_record_enabled (false);
96         //_diskstream->monitor_input (false);
97
98         ic_connection.disconnect();
99         ic_connection = input_changed.connect (mem_fun (*_diskstream, &MidiDiskstream::handle_input_change));
100
101         DiskstreamChanged (); /* EMIT SIGNAL */
102
103         return 0;
104 }       
105
106 int 
107 MidiTrack::use_diskstream (string name)
108 {
109         MidiDiskstream *dstream;
110
111         if ((dstream = dynamic_cast<MidiDiskstream*>(_session.diskstream_by_name (name))) == 0) {
112           error << string_compose(_("MidiTrack: midi diskstream \"%1\" not known by session"), name) << endmsg;
113                 return -1;
114         }
115         
116         return set_diskstream (*dstream);
117 }
118
119 int 
120 MidiTrack::use_diskstream (const PBD::ID& id)
121 {
122         MidiDiskstream *dstream;
123
124         if ((dstream = dynamic_cast<MidiDiskstream*>(_session.diskstream_by_id (id))) == 0) {
125                 error << string_compose(_("MidiTrack: midi diskstream \"%1\" not known by session"), id) << endmsg;
126                 return -1;
127         }
128         
129         return set_diskstream (*dstream);
130 }
131
132 bool
133 MidiTrack::record_enabled () const
134 {
135         return _diskstream->record_enabled ();
136 }
137
138 void
139 MidiTrack::set_record_enable (bool yn, void *src)
140 {
141         if (_freeze_record.state == Frozen) {
142                 return;
143         }
144 #if 0
145         if (_mix_group && src != _mix_group && _mix_group->is_active()) {
146                 _mix_group->apply (&MidiTrack::set_record_enable, yn, _mix_group);
147                 return;
148         }
149
150         /* keep track of the meter point as it was before we rec-enabled */
151
152         if (!diskstream->record_enabled()) {
153                 _saved_meter_point = _meter_point;
154         }
155         
156         diskstream->set_record_enabled (yn, src);
157
158         if (diskstream->record_enabled()) {
159                 set_meter_point (MeterInput, this);
160         } else {
161                 set_meter_point (_saved_meter_point, this);
162         }
163
164         if (_session.get_midi_feedback()) {
165                 _midi_rec_enable_control.send_feedback (record_enabled());
166         }
167 #endif
168 }
169
170 MidiDiskstream&
171 MidiTrack::midi_diskstream() const
172 {
173         return *dynamic_cast<MidiDiskstream*>(_diskstream);
174 }
175
176 int
177 MidiTrack::set_state (const XMLNode& node)
178 {
179         const XMLProperty *prop;
180         XMLNodeConstIterator iter;
181
182         if (Route::set_state (node)) {
183                 return -1;
184         }
185
186         if ((prop = node.property (X_("mode"))) != 0) {
187                 if (prop->value() == X_("normal")) {
188                         _mode = Normal;
189                 } else if (prop->value() == X_("destructive")) {
190                         _mode = Destructive;
191                 } else {
192                         warning << string_compose ("unknown midi track mode \"%1\" seen and ignored", prop->value()) << endmsg;
193                         _mode = Normal;
194                 }
195         } else {
196                 _mode = Normal;
197         }
198
199         if ((prop = node.property ("diskstream-id")) == 0) {
200                 
201                 /* some old sessions use the diskstream name rather than the ID */
202
203                 if ((prop = node.property ("diskstream")) == 0) {
204                         fatal << _("programming error: MidiTrack given state without diskstream!") << endmsg;
205                         /*NOTREACHED*/
206                         return -1;
207                 }
208
209                 if (use_diskstream (prop->value())) {
210                         return -1;
211                 }
212
213         } else {
214                 
215                 PBD::ID id (prop->value());
216                 
217                 if (use_diskstream (id)) {
218                         return -1;
219                 }
220         }
221
222
223         XMLNodeList nlist;
224         XMLNodeConstIterator niter;
225         XMLNode *child;
226
227         nlist = node.children();
228         for (niter = nlist.begin(); niter != nlist.end(); ++niter){
229                 child = *niter;
230
231                 if (child->name() == X_("remote_control")) {
232                         if ((prop = child->property (X_("id"))) != 0) {
233                                 int32_t x;
234                                 sscanf (prop->value().c_str(), "%d", &x);
235                                 set_remote_control_id (x);
236                         }
237                 }
238         }
239
240         pending_state = const_cast<XMLNode*> (&node);
241
242         _session.StateReady.connect (mem_fun (*this, &MidiTrack::set_state_part_two));
243
244         return 0;
245 }
246
247 XMLNode& 
248 MidiTrack::state(bool full_state)
249 {
250         XMLNode& root (Route::state(full_state));
251         XMLNode* freeze_node;
252         char buf[64];
253
254         if (_freeze_record.playlist) {
255                 XMLNode* inode;
256
257                 freeze_node = new XMLNode (X_("freeze-info"));
258                 freeze_node->add_property ("playlist", _freeze_record.playlist->name());
259                 snprintf (buf, sizeof (buf), "%d", (int) _freeze_record.state);
260                 freeze_node->add_property ("state", buf);
261
262                 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
263                         inode = new XMLNode (X_("insert"));
264                         (*i)->id.print (buf);
265                         inode->add_property (X_("id"), buf);
266                         inode->add_child_copy ((*i)->state);
267                 
268                         freeze_node->add_child_nocopy (*inode);
269                 }
270
271                 root.add_child_nocopy (*freeze_node);
272         }
273
274         /* Alignment: act as a proxy for the diskstream */
275         
276         XMLNode* align_node = new XMLNode (X_("alignment"));
277         switch (_diskstream->alignment_style()) {
278         case ExistingMaterial:
279                 snprintf (buf, sizeof (buf), X_("existing"));
280                 break;
281         case CaptureTime:
282                 snprintf (buf, sizeof (buf), X_("capture"));
283                 break;
284         }
285         align_node->add_property (X_("style"), buf);
286         root.add_child_nocopy (*align_node);
287
288         XMLNode* remote_control_node = new XMLNode (X_("remote_control"));
289         snprintf (buf, sizeof (buf), "%d", _remote_control_id);
290         remote_control_node->add_property (X_("id"), buf);
291         root.add_child_nocopy (*remote_control_node);
292
293         switch (_mode) {
294         case Normal:
295                 root.add_property (X_("mode"), X_("normal"));
296                 break;
297         case Destructive:
298                 root.add_property (X_("mode"), X_("destructive"));
299                 break;
300         }
301
302         /* we don't return diskstream state because we don't
303            own the diskstream exclusively. control of the diskstream
304            state is ceded to the Session, even if we create the
305            diskstream.
306         */
307
308         _diskstream->id().print (buf);
309         root.add_property ("diskstream-id", buf);
310
311         return root;
312 }
313
314 void
315 MidiTrack::set_state_part_two ()
316 {
317         XMLNode* fnode;
318         XMLProperty* prop;
319         LocaleGuard lg (X_("POSIX"));
320
321         /* This is called after all session state has been restored but before
322            have been made ports and connections are established.
323         */
324
325         if (pending_state == 0) {
326                 return;
327         }
328
329         if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
330
331                 
332                 _freeze_record.have_mementos = false;
333                 _freeze_record.state = Frozen;
334                 
335                 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
336                         delete *i;
337                 }
338                 _freeze_record.insert_info.clear ();
339                 
340                 if ((prop = fnode->property (X_("playlist"))) != 0) {
341                         Playlist* pl = _session.playlist_by_name (prop->value());
342                         if (pl) {
343                                 _freeze_record.playlist = dynamic_cast<MidiPlaylist*> (pl);
344                         } else {
345                                 _freeze_record.playlist = 0;
346                                 _freeze_record.state = NoFreeze;
347                         return;
348                         }
349                 }
350                 
351                 if ((prop = fnode->property (X_("state"))) != 0) {
352                         _freeze_record.state = (FreezeState) atoi (prop->value().c_str());
353                 }
354                 
355                 XMLNodeConstIterator citer;
356                 XMLNodeList clist = fnode->children();
357                 
358                 for (citer = clist.begin(); citer != clist.end(); ++citer) {
359                         if ((*citer)->name() != X_("insert")) {
360                                 continue;
361                         }
362                         
363                         if ((prop = (*citer)->property (X_("id"))) == 0) {
364                                 continue;
365                         }
366                         
367                         FreezeRecordInsertInfo* frii = new FreezeRecordInsertInfo (*((*citer)->children().front()),
368                                                                                    boost::shared_ptr<Insert>());
369                         frii->id = prop->value ();
370                         _freeze_record.insert_info.push_back (frii);
371                 }
372         }
373
374         /* Alignment: act as a proxy for the diskstream */
375
376         if ((fnode = find_named_node (*pending_state, X_("alignment"))) != 0) {
377
378                 if ((prop = fnode->property (X_("style"))) != 0) {
379                         if (prop->value() == "existing") {
380                                 _diskstream->set_persistent_align_style (ExistingMaterial);
381                         } else if (prop->value() == "capture") {
382                                 _diskstream->set_persistent_align_style (CaptureTime);
383                         }
384                 }
385         }
386         return;
387 }       
388
389 uint32_t
390 MidiTrack::n_process_buffers ()
391 {
392         return max ((uint32_t) _diskstream->n_channels(), redirect_max_outs);
393 }
394
395 void
396 MidiTrack::passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter)
397 {
398         uint32_t nbufs = n_process_buffers ();
399         process_output_buffers (_session.get_silent_buffers (nbufs), nbufs, start_frame, end_frame, nframes, offset, true, declick, meter);
400 }
401
402 int 
403 MidiTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, 
404                      bool session_state_changing, bool can_record, bool rec_monitors_input)
405 {
406         if (n_outputs() == 0) {
407                 return 0;
408         }
409
410         if (!_active) {
411                 silence (nframes, offset);
412                 return 0;
413         }
414
415         if (session_state_changing) {
416
417                 /* XXX is this safe to do against transport state changes? */
418
419                 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
420                 return 0;
421         }
422
423         midi_diskstream().check_record_status (start_frame, nframes, can_record);
424
425         bool send_silence;
426         
427         if (_have_internal_generator) {
428                 /* since the instrument has no input streams,
429                    there is no reason to send any signal
430                    into the route.
431                 */
432                 send_silence = true;
433         } else {
434
435                 if (_session.get_auto_input()) {
436                         if (Config->get_use_sw_monitoring()) {
437                                 send_silence = false;
438                         } else {
439                                 send_silence = true;
440                         }
441                 } else {
442                         if (_diskstream->record_enabled()) {
443                                 if (Config->get_use_sw_monitoring()) {
444                                         send_silence = false;
445                                 } else {
446                                         send_silence = true;
447                                 }
448                         } else {
449                                 send_silence = true;
450                         }
451                 }
452         }
453
454         apply_gain_automation = false;
455
456         if (send_silence) {
457                 
458                 /* if we're sending silence, but we want the meters to show levels for the signal,
459                    meter right here.
460                 */
461                 
462                 if (_have_internal_generator) {
463                         passthru_silence (start_frame, end_frame, nframes, offset, 0, true);
464                 } else {
465                         if (_meter_point == MeterInput) {
466                                 just_meter_input (start_frame, end_frame, nframes, offset);
467                         }
468                         passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
469                 }
470
471         } else {
472         
473                 /* we're sending signal, but we may still want to meter the input. 
474                  */
475
476                 passthru (start_frame, end_frame, nframes, offset, 0, (_meter_point == MeterInput));
477         }
478
479         return 0;
480 }
481
482 int
483 MidiTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, int declick,
484                   bool can_record, bool rec_monitors_input)
485 {
486         return 0;
487 }
488
489 int
490 MidiTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, 
491                          bool can_record, bool rec_monitors_input)
492 {
493         if (n_outputs() == 0 && _redirects.empty()) {
494                 return 0;
495         }
496
497         if (!_active) {
498                 silence (nframes, offset);
499                 return 0;
500         }
501
502         _silent = true;
503         apply_gain_automation = false;
504
505         silence (nframes, offset);
506
507         return midi_diskstream().process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
508 }
509
510 void
511 MidiTrack::process_output_buffers (vector<Sample*>& bufs, uint32_t nbufs,
512                                jack_nframes_t start_frame, jack_nframes_t end_frame, 
513                                jack_nframes_t nframes, jack_nframes_t offset, bool with_redirects, int declick,
514                                bool meter)
515 {
516         // Do nothing (just bypass the Route version to avoid flaming death)
517 }
518
519 int
520 MidiTrack::set_name (string str, void *src)
521 {
522         int ret;
523
524         if (record_enabled() && _session.actively_recording()) {
525                 /* this messes things up if done while recording */
526                 return -1;
527         }
528
529         if (_diskstream->set_name (str)) {
530                 return -1;
531         }
532
533         /* save state so that the statefile fully reflects any filename changes */
534
535         if ((ret = IO::set_name (str, src)) == 0) {
536                 _session.save_state ("");
537         }
538         return ret;
539 }
540
541 int
542 MidiTrack::export_stuff (vector<unsigned char*>& buffers, uint32_t nbufs, jack_nframes_t start, jack_nframes_t nframes)
543 {
544         return 0;
545 }
546
547 void
548 MidiTrack::set_latency_delay (jack_nframes_t longest_session_latency)
549 {
550         Route::set_latency_delay (longest_session_latency);
551         _diskstream->set_roll_delay (_roll_delay);
552 }
553
554 void
555 MidiTrack::bounce (InterThreadInfo& itt)
556 {
557         //vector<MidiSource*> srcs;
558         //_session.write_one_midi_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
559 }
560
561
562 void
563 MidiTrack::bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo& itt)
564 {
565         //vector<MidiSource*> srcs;
566         //_session.write_one_midi_track (*this, start, end, false, srcs, itt);
567 }
568
569 void
570 MidiTrack::freeze (InterThreadInfo& itt)
571 {
572 }
573
574 void
575 MidiTrack::unfreeze ()
576 {
577         _freeze_record.state = UnFrozen;
578         FreezeChange (); /* EMIT SIGNAL */
579 }
580
581 void
582 MidiTrack::set_mode (TrackMode m)
583 {
584         if (_diskstream) {
585                 if (_mode != m) {
586                         _mode = m;
587                         _diskstream->set_destructive (m == Destructive);
588                         ModeChanged();
589                 }
590         }
591 }