2 Copyright (C) 2000-2003 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 $Id: diskstream.cc 567 2006-06-07 14:54:12Z trutkin $
34 #include <pbd/error.h>
35 #include <pbd/basename.h>
36 #include <glibmm/thread.h>
37 #include <pbd/xml++.h>
39 #include <ardour/ardour.h>
40 #include <ardour/audioengine.h>
41 #include <ardour/midi_diskstream.h>
42 #include <ardour/utils.h>
43 #include <ardour/configuration.h>
44 #include <ardour/smf_source.h>
45 #include <ardour/destructive_filesource.h>
46 #include <ardour/send.h>
47 #include <ardour/midi_playlist.h>
48 #include <ardour/cycle_timer.h>
49 #include <ardour/midi_region.h>
55 using namespace ARDOUR;
58 sigc::signal<void,list<SMFSource*>*> MidiDiskstream::DeleteSources;
60 MidiDiskstream::MidiDiskstream (Session &sess, const string &name, Diskstream::Flag flag)
61 : Diskstream(sess, name, flag)
64 /* prevent any write sources from being created */
73 DiskstreamCreated (this); /* EMIT SIGNAL */
76 MidiDiskstream::MidiDiskstream (Session& sess, const XMLNode& node)
77 : Diskstream(sess, node)
83 if (set_state (node)) {
85 throw failed_constructor();
91 use_destructive_playlist ();
94 DiskstreamCreated (this); /* EMIT SIGNAL */
98 MidiDiskstream::init (Diskstream::Flag f)
102 /* there are no channels at this point, so these
103 two calls just get speed_buffer_size and wrap_buffer
104 size setup without duplicating their code.
107 set_block_size (_session.get_block_size());
108 allocate_temporary_buffers ();
110 /* FIXME: this is now done before the above. OK? */
111 /*pending_overwrite = false;
113 overwrite_queued = false;
114 input_change_pending = NoChange;*/
119 MidiDiskstream::~MidiDiskstream ()
121 Glib::Mutex::Lock lm (state_lock);
128 MidiDiskstream::handle_input_change (IOChange change, void *src)
130 Glib::Mutex::Lock lm (state_lock);
132 if (!(input_change_pending & change)) {
133 input_change_pending = IOChange (input_change_pending|change);
134 _session.request_input_change_handling ();
139 MidiDiskstream::non_realtime_input_change ()
144 MidiDiskstream::get_input_sources ()
149 MidiDiskstream::find_and_use_playlist (const string& name)
152 MidiPlaylist* playlist;
154 if ((pl = _session.playlist_by_name (name)) == 0) {
155 playlist = new MidiPlaylist(_session, name);
159 if ((playlist = dynamic_cast<MidiPlaylist*> (pl)) == 0) {
160 error << string_compose(_("MidiDiskstream: Playlist \"%1\" isn't a midi playlist"), name) << endmsg;
164 return use_playlist (playlist);
168 MidiDiskstream::use_playlist (Playlist* playlist)
170 assert(dynamic_cast<MidiPlaylist*>(playlist));
173 Glib::Mutex::Lock lm (state_lock);
175 if (playlist == _playlist) {
179 plstate_connection.disconnect();
180 plmod_connection.disconnect ();
181 plgone_connection.disconnect ();
187 _playlist = dynamic_cast<MidiPlaylist*>(playlist);
190 if (!in_set_state && recordable()) {
191 reset_write_sources (false);
194 plstate_connection = _playlist->StateChanged.connect (mem_fun (*this, &MidiDiskstream::playlist_changed));
195 plmod_connection = _playlist->Modified.connect (mem_fun (*this, &MidiDiskstream::playlist_modified));
196 plgone_connection = _playlist->GoingAway.connect (mem_fun (*this, &MidiDiskstream::playlist_deleted));
199 if (!overwrite_queued) {
200 _session.request_overwrite_buffer (this);
201 overwrite_queued = true;
204 PlaylistChanged (); /* EMIT SIGNAL */
205 _session.set_dirty ();
211 MidiDiskstream::use_new_playlist ()
214 MidiPlaylist* playlist;
216 if (!in_set_state && destructive()) {
221 newname = Playlist::bump_name (_playlist->name(), _session);
223 newname = Playlist::bump_name (_name, _session);
226 if ((playlist = new MidiPlaylist (_session, newname, hidden())) != 0) {
227 playlist->set_orig_diskstream_id (id());
228 return use_playlist (playlist);
235 MidiDiskstream::use_copy_playlist ()
241 if (_playlist == 0) {
242 error << string_compose(_("MidiDiskstream %1: there is no existing playlist to make a copy of!"), _name) << endmsg;
247 MidiPlaylist* playlist;
249 newname = Playlist::bump_name (_playlist->name(), _session);
251 if ((playlist = new MidiPlaylist (*_playlist, newname)) != 0) {
252 playlist->set_orig_diskstream_id (id());
253 return use_playlist (playlist);
261 MidiDiskstream::playlist_deleted (Playlist* pl)
263 /* this catches an ordering issue with session destruction. playlists
264 are destroyed before diskstreams. we have to invalidate any handles
265 we have to the playlist.
273 MidiDiskstream::setup_destructive_playlist ()
275 /* a single full-sized region */
277 //MidiRegion* region = new MidiRegion (srcs, 0, max_frames, _name);
278 //_playlist->add_region (*region, 0);
282 MidiDiskstream::use_destructive_playlist ()
284 /* use the sources associated with the single full-extent region */
286 Playlist::RegionList* rl = _playlist->regions_at (0);
289 reset_write_sources (false, true);
293 MidiRegion* region = dynamic_cast<MidiRegion*> (rl->front());
296 throw failed_constructor();
301 /* the source list will never be reset for a destructive track */
305 MidiDiskstream::set_io (IO& io)
308 set_align_style_from_io ();
312 MidiDiskstream::non_realtime_set_speed ()
314 if (_buffer_reallocation_required)
316 Glib::Mutex::Lock lm (state_lock);
317 allocate_temporary_buffers ();
319 _buffer_reallocation_required = false;
322 if (_seek_required) {
323 if (speed() != 1.0f || speed() != -1.0f) {
324 seek ((jack_nframes_t) (_session.transport_frame() * (double) speed()), true);
327 seek (_session.transport_frame(), true);
330 _seek_required = false;
335 MidiDiskstream::check_record_status (jack_nframes_t transport_frame, jack_nframes_t nframes, bool can_record)
340 MidiDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes, jack_nframes_t offset, bool can_record, bool rec_monitors_input)
346 MidiDiskstream::commit (jack_nframes_t nframes)
352 MidiDiskstream::set_pending_overwrite (bool yn)
354 /* called from audio thread, so we can use the read ptr and playback sample as we wish */
356 pending_overwrite = yn;
358 overwrite_frame = playback_sample;
359 //overwrite_offset = channels.front().playback_buf->get_read_ptr();
363 MidiDiskstream::overwrite_existing_buffers ()
369 MidiDiskstream::seek (jack_nframes_t frame, bool complete_refill)
375 MidiDiskstream::can_internal_playback_seek (jack_nframes_t distance)
381 MidiDiskstream::internal_playback_seek (jack_nframes_t distance)
387 MidiDiskstream::read (RawMidi* buf, RawMidi* mixdown_buffer, char * workbuf, jack_nframes_t& start, jack_nframes_t cnt, bool reversed)
393 MidiDiskstream::do_refill (RawMidi* mixdown_buffer, float* gain_buffer, char * workbuf)
399 MidiDiskstream::do_flush (char * workbuf, bool force_flush)
405 MidiDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture)
410 MidiDiskstream::finish_capture (bool rec_monitors_input)
415 MidiDiskstream::set_record_enabled (bool yn, void* src)
420 MidiDiskstream::get_state ()
422 XMLNode* node = new XMLNode ("MidiDiskstream");
424 LocaleGuard lg (X_("POSIX"));
426 snprintf (buf, sizeof(buf), "0x%x", _flags);
427 node->add_property ("flags", buf);
429 node->add_property ("playlist", _playlist->name());
431 snprintf (buf, sizeof(buf), "%f", _visible_speed);
432 node->add_property ("speed", buf);
434 node->add_property("name", _name);
435 snprintf (buf, sizeof(buf), "%" PRIu64, id());
436 node->add_property("id", buf);
438 if (!_capturing_sources.empty() && _session.get_record_enabled()) {
440 XMLNode* cs_child = new XMLNode (X_("CapturingSources"));
441 XMLNode* cs_grandchild;
443 for (vector<SMFSource*>::iterator i = _capturing_sources.begin(); i != _capturing_sources.end(); ++i) {
444 cs_grandchild = new XMLNode (X_("file"));
445 cs_grandchild->add_property (X_("path"), (*i)->path());
446 cs_child->add_child_nocopy (*cs_grandchild);
449 /* store the location where capture will start */
453 if (_session.get_punch_in() && ((pi = _session.locations()->auto_punch_location()) != 0)) {
454 snprintf (buf, sizeof (buf), "%" PRIu32, pi->start());
456 snprintf (buf, sizeof (buf), "%" PRIu32, _session.transport_frame());
459 cs_child->add_property (X_("at"), buf);
460 node->add_child_nocopy (*cs_child);
464 node->add_child_copy (*_extra_xml);
471 MidiDiskstream::set_state (const XMLNode& node)
473 const XMLProperty* prop;
474 XMLNodeList nlist = node.children();
475 XMLNodeIterator niter;
477 XMLNode* capture_pending_node = 0;
478 LocaleGuard lg (X_("POSIX"));
482 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
483 if ((*niter)->name() == IO::state_node_name) {
484 deprecated_io_node = new XMLNode (**niter);
487 if ((*niter)->name() == X_("CapturingSources")) {
488 capture_pending_node = *niter;
492 /* prevent write sources from being created */
496 if ((prop = node.property ("name")) != 0) {
497 _name = prop->value();
500 if (deprecated_io_node) {
501 if ((prop = deprecated_io_node->property ("id")) != 0) {
502 sscanf (prop->value().c_str(), "%" PRIu64, &_id);
505 if ((prop = node.property ("id")) != 0) {
506 sscanf (prop->value().c_str(), "%" PRIu64, &_id);
510 if ((prop = node.property ("flags")) != 0) {
511 _flags = strtol (prop->value().c_str(), 0, 0);
514 if ((prop = node.property ("channels")) != 0) {
515 nchans = atoi (prop->value().c_str());
518 if ((prop = node.property ("playlist")) == 0) {
523 bool had_playlist = (_playlist != 0);
525 if (find_and_use_playlist (prop->value())) {
530 _playlist->set_orig_diskstream_id (_id);
533 if (!destructive() && capture_pending_node) {
534 /* destructive streams have one and only one source per channel,
535 and so they never end up in pending capture in any useful
538 use_pending_capture_data (*capture_pending_node);
543 if ((prop = node.property ("speed")) != 0) {
544 double sp = atof (prop->value().c_str());
546 if (realtime_set_speed (sp, false)) {
547 non_realtime_set_speed ();
551 in_set_state = false;
553 /* make sure this is clear before we do anything else */
555 _capturing_sources.clear ();
557 /* write sources are handled when we handle the input set
558 up of the IO that owns this DS (::non_realtime_input_change())
561 in_set_state = false;
567 MidiDiskstream::use_new_write_source (uint32_t n)
573 MidiDiskstream::reset_write_sources (bool mark_write_complete, bool force)
578 MidiDiskstream::rename_write_sources ()
584 MidiDiskstream::set_block_size (jack_nframes_t nframes)
589 MidiDiskstream::allocate_temporary_buffers ()
594 MidiDiskstream::monitor_input (bool yn)
599 MidiDiskstream::set_align_style_from_io ()
605 MidiDiskstream::playback_buffer_load () const
611 MidiDiskstream::capture_buffer_load () const
618 MidiDiskstream::use_pending_capture_data (XMLNode& node)