2 Copyright (C) 2006 Paul Davis
3 By Dave Robillard, 2006
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.
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.
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.
19 #include <pbd/error.h>
20 #include <sigc++/retype.h>
21 #include <sigc++/retype_return.h>
22 #include <sigc++/bind.h>
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>
39 using namespace ARDOUR;
42 MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
43 : Track (sess, name, flag, mode, DataType::MIDI)
45 MidiDiskstream::Flag dflags = MidiDiskstream::Flag (0);
47 if (_flags & Hidden) {
48 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Hidden);
50 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Recordable);
53 if (mode == Destructive) {
54 dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Destructive);
57 MidiDiskstream* ds = new MidiDiskstream (_session, name, dflags);
60 _freeze_record.state = NoFreeze;
61 _saved_meter_point = _meter_point;
67 MidiTrack::MidiTrack (Session& sess, const XMLNode& node)
70 _freeze_record.state = NoFreeze;
73 _saved_meter_point = _meter_point;
76 MidiTrack::~MidiTrack ()
85 MidiTrack::set_diskstream (MidiDiskstream& ds)
91 _diskstream = &ds.ref();
92 _diskstream->set_io (*this);
93 _diskstream->set_destructive (_mode == Destructive);
95 _diskstream->set_record_enabled (false);
96 //_diskstream->monitor_input (false);
98 ic_connection.disconnect();
99 ic_connection = input_changed.connect (mem_fun (*_diskstream, &MidiDiskstream::handle_input_change));
101 DiskstreamChanged (); /* EMIT SIGNAL */
107 MidiTrack::use_diskstream (string name)
109 MidiDiskstream *dstream;
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;
116 return set_diskstream (*dstream);
120 MidiTrack::use_diskstream (const PBD::ID& id)
122 MidiDiskstream *dstream;
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;
129 return set_diskstream (*dstream);
133 MidiTrack::record_enabled () const
135 return _diskstream->record_enabled ();
139 MidiTrack::set_record_enable (bool yn, void *src)
141 if (_freeze_record.state == Frozen) {
145 if (_mix_group && src != _mix_group && _mix_group->is_active()) {
146 _mix_group->apply (&MidiTrack::set_record_enable, yn, _mix_group);
150 /* keep track of the meter point as it was before we rec-enabled */
152 if (!diskstream->record_enabled()) {
153 _saved_meter_point = _meter_point;
156 diskstream->set_record_enabled (yn, src);
158 if (diskstream->record_enabled()) {
159 set_meter_point (MeterInput, this);
161 set_meter_point (_saved_meter_point, this);
164 if (_session.get_midi_feedback()) {
165 _midi_rec_enable_control.send_feedback (record_enabled());
171 MidiTrack::midi_diskstream() const
173 return *dynamic_cast<MidiDiskstream*>(_diskstream);
177 MidiTrack::set_state (const XMLNode& node)
179 const XMLProperty *prop;
180 XMLNodeConstIterator iter;
182 if (Route::set_state (node)) {
186 if ((prop = node.property (X_("mode"))) != 0) {
187 if (prop->value() == X_("normal")) {
189 } else if (prop->value() == X_("destructive")) {
192 warning << string_compose ("unknown midi track mode \"%1\" seen and ignored", prop->value()) << endmsg;
199 if ((prop = node.property ("diskstream-id")) == 0) {
201 /* some old sessions use the diskstream name rather than the ID */
203 if ((prop = node.property ("diskstream")) == 0) {
204 fatal << _("programming error: MidiTrack given state without diskstream!") << endmsg;
209 if (use_diskstream (prop->value())) {
215 PBD::ID id (prop->value());
217 if (use_diskstream (id)) {
224 XMLNodeConstIterator niter;
227 nlist = node.children();
228 for (niter = nlist.begin(); niter != nlist.end(); ++niter){
231 if (child->name() == X_("remote_control")) {
232 if ((prop = child->property (X_("id"))) != 0) {
234 sscanf (prop->value().c_str(), "%d", &x);
235 set_remote_control_id (x);
240 pending_state = const_cast<XMLNode*> (&node);
242 _session.StateReady.connect (mem_fun (*this, &MidiTrack::set_state_part_two));
248 MidiTrack::state(bool full_state)
250 XMLNode& root (Route::state(full_state));
251 XMLNode* freeze_node;
254 if (_freeze_record.playlist) {
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);
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);
268 freeze_node->add_child_nocopy (*inode);
271 root.add_child_nocopy (*freeze_node);
274 /* Alignment: act as a proxy for the diskstream */
276 XMLNode* align_node = new XMLNode (X_("alignment"));
277 switch (_diskstream->alignment_style()) {
278 case ExistingMaterial:
279 snprintf (buf, sizeof (buf), X_("existing"));
282 snprintf (buf, sizeof (buf), X_("capture"));
285 align_node->add_property (X_("style"), buf);
286 root.add_child_nocopy (*align_node);
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);
295 root.add_property (X_("mode"), X_("normal"));
298 root.add_property (X_("mode"), X_("destructive"));
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
308 _diskstream->id().print (buf);
309 root.add_property ("diskstream-id", buf);
315 MidiTrack::set_state_part_two ()
319 LocaleGuard lg (X_("POSIX"));
321 /* This is called after all session state has been restored but before
322 have been made ports and connections are established.
325 if (pending_state == 0) {
329 if ((fnode = find_named_node (*pending_state, X_("freeze-info"))) != 0) {
332 _freeze_record.have_mementos = false;
333 _freeze_record.state = Frozen;
335 for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
338 _freeze_record.insert_info.clear ();
340 if ((prop = fnode->property (X_("playlist"))) != 0) {
341 Playlist* pl = _session.playlist_by_name (prop->value());
343 _freeze_record.playlist = dynamic_cast<MidiPlaylist*> (pl);
345 _freeze_record.playlist = 0;
346 _freeze_record.state = NoFreeze;
351 if ((prop = fnode->property (X_("state"))) != 0) {
352 _freeze_record.state = (FreezeState) atoi (prop->value().c_str());
355 XMLNodeConstIterator citer;
356 XMLNodeList clist = fnode->children();
358 for (citer = clist.begin(); citer != clist.end(); ++citer) {
359 if ((*citer)->name() != X_("insert")) {
363 if ((prop = (*citer)->property (X_("id"))) == 0) {
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);
374 /* Alignment: act as a proxy for the diskstream */
376 if ((fnode = find_named_node (*pending_state, X_("alignment"))) != 0) {
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);
390 MidiTrack::n_process_buffers ()
392 return max ((uint32_t) _diskstream->n_channels(), redirect_max_outs);
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)
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);
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)
406 if (n_outputs() == 0) {
411 silence (nframes, offset);
415 if (session_state_changing) {
417 /* XXX is this safe to do against transport state changes? */
419 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
423 midi_diskstream().check_record_status (start_frame, nframes, can_record);
427 if (_have_internal_generator) {
428 /* since the instrument has no input streams,
429 there is no reason to send any signal
435 if (_session.get_auto_input()) {
436 if (Config->get_use_sw_monitoring()) {
437 send_silence = false;
442 if (_diskstream->record_enabled()) {
443 if (Config->get_use_sw_monitoring()) {
444 send_silence = false;
454 apply_gain_automation = false;
458 /* if we're sending silence, but we want the meters to show levels for the signal,
462 if (_have_internal_generator) {
463 passthru_silence (start_frame, end_frame, nframes, offset, 0, true);
465 if (_meter_point == MeterInput) {
466 just_meter_input (start_frame, end_frame, nframes, offset);
468 passthru_silence (start_frame, end_frame, nframes, offset, 0, false);
473 /* we're sending signal, but we may still want to meter the input.
476 passthru (start_frame, end_frame, nframes, offset, 0, (_meter_point == MeterInput));
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)
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)
493 if (n_outputs() == 0 && _redirects.empty()) {
498 silence (nframes, offset);
503 apply_gain_automation = false;
505 silence (nframes, offset);
507 return midi_diskstream().process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
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,
516 // Do nothing (just bypass the Route version to avoid flaming death)
520 MidiTrack::set_name (string str, void *src)
524 if (record_enabled() && _session.actively_recording()) {
525 /* this messes things up if done while recording */
529 if (_diskstream->set_name (str)) {
533 /* save state so that the statefile fully reflects any filename changes */
535 if ((ret = IO::set_name (str, src)) == 0) {
536 _session.save_state ("");
542 MidiTrack::export_stuff (vector<unsigned char*>& buffers, uint32_t nbufs, jack_nframes_t start, jack_nframes_t nframes)
548 MidiTrack::set_latency_delay (jack_nframes_t longest_session_latency)
550 Route::set_latency_delay (longest_session_latency);
551 _diskstream->set_roll_delay (_roll_delay);
555 MidiTrack::bounce (InterThreadInfo& itt)
557 //vector<MidiSource*> srcs;
558 //_session.write_one_midi_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
563 MidiTrack::bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo& itt)
565 //vector<MidiSource*> srcs;
566 //_session.write_one_midi_track (*this, start, end, false, srcs, itt);
570 MidiTrack::freeze (InterThreadInfo& itt)
575 MidiTrack::unfreeze ()
577 _freeze_record.state = UnFrozen;
578 FreezeChange (); /* EMIT SIGNAL */
582 MidiTrack::set_mode (TrackMode m)
587 _diskstream->set_destructive (m == Destructive);