/*
- Copyright (C) 2000-2003 Paul Davis
+ Copyright (C) 2000-2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: diskstream.cc 567 2006-06-07 14:54:12Z trutkin $
*/
#include <fstream>
+#include <cassert>
#include <cstdio>
#include <unistd.h>
#include <cmath>
#include <sys/stat.h>
#include <sys/mman.h>
+#include <sigc++/bind.h>
+
#include <pbd/error.h>
#include <pbd/basename.h>
#include <glibmm/thread.h>
#include <ardour/utils.h>
#include <ardour/configuration.h>
#include <ardour/audiofilesource.h>
-#include <ardour/destructive_filesource.h>
#include <ardour/send.h>
#include <ardour/playlist.h>
#include <ardour/cycle_timer.h>
using namespace ARDOUR;
using namespace PBD;
-jack_nframes_t Diskstream::disk_io_chunk_frames;
+/* XXX This goes uninitialized when there is no ~/.ardour2 directory.
+ * I can't figure out why, so this will do for now (just stole the
+ * default from configuration_vars.h). 0 is not a good value for
+ * allocating buffer sizes..
+ */
+ARDOUR::nframes_t Diskstream::disk_io_chunk_frames = 1024 * 256;
-sigc::signal<void,Diskstream*> Diskstream::DiskstreamCreated;
-//sigc::signal<void,list<AudioFileSource*>*> Diskstream::DeleteSources;
sigc::signal<void> Diskstream::DiskOverrun;
sigc::signal<void> Diskstream::DiskUnderrun;
: _name (name)
, _session (sess)
{
-#if 0
- /* prevent any write sources from being created */
-
- in_set_state = true;
-
init (flag);
- //use_new_playlist ();
-
- in_set_state = false;
- DiskstreamCreated (this); /* EMIT SIGNAL */
-#endif
}
Diskstream::Diskstream (Session& sess, const XMLNode& node)
: _session (sess)
-
{
-#if 0
- in_set_state = true;
init (Recordable);
-
- /*if (set_state (node)) {
- in_set_state = false;
- throw failed_constructor();
- }*/
-
- in_set_state = false;
-
- //if (destructive()) {
- // use_destructive_playlist ();
- //}
- DiskstreamCreated (this); /* EMIT SIGNAL */
-#endif
}
void
Diskstream::init (Flag f)
{
- _id = new_id();
- _refcnt = 0;
_flags = f;
_io = 0;
_alignment_style = ExistingMaterial;
playback_distance = 0;
_read_data_count = 0;
_write_data_count = 0;
- deprecated_io_node = 0;
-
- /* there are no channels at this point, so these
- two calls just get speed_buffer_size and wrap_buffer
- size setup without duplicating their code.
- */
-
- //set_block_size (_session.get_block_size());
- //allocate_temporary_buffers ();
+ commit_should_unlock = false;
pending_overwrite = false;
overwrite_frame = 0;
overwrite_queued = false;
input_change_pending = NoChange;
-
- //add_channel ();
- _n_channels = 0;//1;
}
Diskstream::~Diskstream ()
{
- // Taken by child.. assure lock?
- //Glib::Mutex::Lock lm (state_lock);
-
- //if (_playlist) {
- // _playlist->unref ();
- //}
+ if (_playlist)
+ _playlist->release ();
+}
- //for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
- // destroy_channel((*chan));
- //}
-
- //channels.clear();
+void
+Diskstream::set_io (IO& io)
+{
+ _io = &io;
+ set_align_style_from_io ();
}
void
}
}
+void
+Diskstream::non_realtime_set_speed ()
+{
+ if (_buffer_reallocation_required)
+ {
+ Glib::Mutex::Lock lm (state_lock);
+ allocate_temporary_buffers ();
+
+ _buffer_reallocation_required = false;
+ }
+
+ if (_seek_required) {
+ if (speed() != 1.0f || speed() != -1.0f) {
+ seek ((nframes_t) (_session.transport_frame() * (double) speed()), true);
+ }
+ else {
+ seek (_session.transport_frame(), true);
+ }
+
+ _seek_required = false;
+ }
+}
+
bool
Diskstream::realtime_set_speed (double sp, bool global)
{
if (new_speed != _actual_speed) {
- jack_nframes_t required_wrap_size = (jack_nframes_t) floor (_session.get_block_size() *
+ nframes_t required_wrap_size = (nframes_t) floor (_session.get_block_size() *
fabs (new_speed)) + 1;
if (required_wrap_size > wrap_buffer_size) {
if (!global) {
_seek_required = true;
}
- speed_changed (); /* EMIT SIGNAL */
+ SpeedChanged (); /* EMIT SIGNAL */
}
return _buffer_reallocation_required || _seek_required;
void
Diskstream::recover ()
{
- state_lock.unlock();
+ if (commit_should_unlock) {
+ state_lock.unlock();
+ }
_processed = false;
}
return;
}
-
if (a != _alignment_style) {
_alignment_style = a;
AlignmentStyleChanged ();
return 0;
}
-jack_nframes_t
+ARDOUR::nframes_t
Diskstream::get_capture_start_frame (uint32_t n)
{
Glib::Mutex::Lock lm (capture_info_lock);
}
}
-jack_nframes_t
+ARDOUR::nframes_t
Diskstream::get_captured_frames (uint32_t n)
{
Glib::Mutex::Lock lm (capture_info_lock);
}
void
-Diskstream::set_roll_delay (jack_nframes_t nframes)
+Diskstream::set_roll_delay (ARDOUR::nframes_t nframes)
{
_roll_delay = nframes;
}
playlist_modified();
}
+int
+Diskstream::use_playlist (boost::shared_ptr<Playlist> playlist)
+{
+ {
+ Glib::Mutex::Lock lm (state_lock);
+
+ if (playlist == _playlist) {
+ return 0;
+ }
+
+ plmod_connection.disconnect ();
+ plgone_connection.disconnect ();
+
+ if (_playlist) {
+ _playlist->release();
+ }
+
+ _playlist = playlist;
+ _playlist->use();
+
+ if (!in_set_state && recordable()) {
+ reset_write_sources (false);
+ }
+
+ plmod_connection = _playlist->Modified.connect (mem_fun (*this, &Diskstream::playlist_modified));
+ plgone_connection = _playlist->GoingAway.connect (bind (mem_fun (*this, &Diskstream::playlist_deleted), boost::weak_ptr<Playlist>(_playlist)));
+ }
+
+ /* don't do this if we've already asked for it *or* if we are setting up
+ the diskstream for the very first time - the input changed handling will
+ take care of the buffer refill.
+ */
+
+ if (!overwrite_queued && !(_session.state_of_the_state() & Session::CannotSave)) {
+ _session.request_overwrite_buffer (this);
+ overwrite_queued = true;
+ }
+
+ PlaylistChanged (); /* EMIT SIGNAL */
+ _session.set_dirty ();
+
+ return 0;
+}
+
void
Diskstream::playlist_changed (Change ignored)
{
}
}
+void
+Diskstream::playlist_deleted (boost::weak_ptr<Playlist> wpl)
+{
+ boost::shared_ptr<Playlist> pl (wpl.lock());
+
+ if (pl == _playlist) {
+
+ /* this catches an ordering issue with session destruction. playlists
+ are destroyed before diskstreams. we have to invalidate any handles
+ we have to the playlist.
+ */
+
+ if (_playlist) {
+ _playlist.reset ();
+ }
+ }
+}
+
int
-Diskstream::set_name (string str, void *src)
+Diskstream::set_name (string str)
{
if (str != _name) {
assert(playlist());
}
void
-Diskstream::set_destructive (bool yn)
+Diskstream::remove_region_from_last_capture (boost::weak_ptr<Region> wregion)
{
- if (yn != destructive()) {
- reset_write_sources (true, true);
- if (yn) {
- _flags |= Destructive;
- } else {
- _flags &= ~Destructive;
- }
+ boost::shared_ptr<Region> region (wregion.lock());
+
+ if (!region) {
+ return;
}
+
+ _last_capture_regions.remove (region);
}
+