part one of hiding Diskstreams and making them a private object of a Track

git-svn-id: svn://localhost/ardour2/branches/3.0@6802 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2010-03-27 14:41:24 +00:00
parent 4be50fc81b
commit 5e8b3f0832
18 changed files with 62 additions and 208 deletions

View File

@ -174,7 +174,7 @@ class AudioDiskstream : public Diskstream
protected:
friend class AudioTrack;
int process (nframes_t transport_frame, nframes_t nframes, bool can_record, bool rec_monitors_input);
int process (nframes_t transport_frame, nframes_t nframes, bool can_record, bool rec_monitors_input, bool& need_butler);
bool commit (nframes_t nframes);
private:

View File

@ -38,8 +38,8 @@ class AudioTrack : public Track
int set_mode (TrackMode m);
bool can_use_mode (TrackMode m, bool& bounce_required);
int roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
int declick, bool can_record, bool rec_monitors_input);
int roll (nframes_t nframes, framepos_t start_frame, framepos_t end_frame,
int declick, bool can_record, bool rec_monitors_input, bool& need_butler);
boost::shared_ptr<AudioDiskstream> audio_diskstream() const;

View File

@ -180,10 +180,8 @@ class Diskstream : public SessionObject
protected:
friend class Track;
virtual void prepare ();
virtual int process (nframes_t transport_frame, nframes_t nframes, bool can_record, bool rec_monitors_input) = 0;
virtual int process (nframes_t transport_frame, nframes_t nframes, bool can_record, bool rec_monitors_input, bool& need_butler) = 0;
virtual bool commit (nframes_t nframes) = 0;
virtual void recover (); /* called if commit will not be called, but process was */
//private:
@ -273,7 +271,6 @@ class Diskstream : public SessionObject
AlignStyle _alignment_style;
bool _scrubbing;
bool _slaved;
bool _processed;
Location* loop_location;
nframes_t overwrite_frame;
off_t overwrite_offset;
@ -289,7 +286,6 @@ class Diskstream : public SessionObject
nframes_t file_frame;
nframes_t playback_sample;
nframes_t playback_distance;
bool commit_should_unlock;
uint32_t _read_data_count;
uint32_t _write_data_count;

View File

@ -136,7 +136,7 @@ class MidiDiskstream : public Diskstream
protected:
friend class MidiTrack;
int process (nframes_t transport_frame, nframes_t nframes, bool can_record, bool rec_monitors_input);
int process (nframes_t transport_frame, nframes_t nframes, bool can_record, bool rec_monitors_input, bool& need_butler);
bool commit (nframes_t nframes);
static nframes_t midi_readahead;

View File

@ -38,8 +38,8 @@ public:
MidiTrack (Session&, string name, Route::Flag f = Route::Flag (0), TrackMode m = Normal);
~MidiTrack ();
int roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
int declick, bool can_record, bool rec_monitors_input);
int roll (nframes_t nframes, framepos_t start_frame, framepos_t end_frame,
int declick, bool can_record, bool rec_monitors_input, bool& need_butler);
void handle_transport_stopped (bool abort, bool did_locate, bool flush_processors);

View File

@ -99,13 +99,13 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou
/* these are the core of the API of a Route. see the protected sections as well */
virtual int roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
int declick, bool can_record, bool rec_monitors_input);
int declick, bool can_record, bool rec_monitors_input, bool& need_butler);
virtual int no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
bool state_changing, bool can_record, bool rec_monitors_input);
virtual int silent_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
bool can_record, bool rec_monitors_input);
bool can_record, bool rec_monitors_input, bool& need_butler);
virtual void toggle_monitor_input ();
virtual bool can_record() { return false; }

View File

@ -934,10 +934,9 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
PBD::ScopedConnection export_freewheel_connection;
void prepare_diskstreams ();
void commit_diskstreams (nframes_t, bool& session_requires_butler);
int process_routes (nframes_t);
int silent_process_routes (nframes_t);
void get_diskstream_statistics ();
int process_routes (nframes_t, bool& need_butler);
int silent_process_routes (nframes_t, bool& need_butler);
bool get_rec_monitors_input () {
if (actively_recording()) {

View File

@ -46,15 +46,16 @@ class Track : public Route
virtual bool can_use_mode (TrackMode /*m*/, bool& /*bounce_required*/) { return false; }
PBD::Signal0<void> TrackModeChanged;
virtual int no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
virtual int no_roll (nframes_t nframes, framepos_t start_frame, framepos_t end_frame,
bool state_changing, bool can_record, bool rec_monitors_input);
int silent_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
bool can_record, bool rec_monitors_input);
int silent_roll (nframes_t nframes, framepos_t start_frame, framepos_t end_frame,
bool can_record, bool rec_monitors_input, bool& need_butler);
virtual int roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
int declick, bool can_record, bool rec_monitors_input) = 0;
virtual int roll (nframes_t nframes, framepos_t start_frame, framepos_t end_frame,
int declick, bool can_record, bool rec_monitors_input, bool& need_butler) = 0;
bool needs_butler() const { return _needs_butler; }
void toggle_monitor_input ();
bool can_record();
@ -100,6 +101,7 @@ class Track : public Route
boost::shared_ptr<Diskstream> _diskstream;
MeterPoint _saved_meter_point;
TrackMode _mode;
bool _needs_butler;
ChanCount input_streams () const;

View File

@ -425,7 +425,7 @@ AudioDiskstream::prepare_record_status(nframes_t capture_start_frame)
}
int
AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can_record, bool rec_monitors_input)
AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can_record, bool rec_monitors_input, bool& need_butler)
{
uint32_t n;
boost::shared_ptr<ChannelList> c = channels.reader();
@ -437,22 +437,9 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can
bool re = record_enabled ();
bool collect_playback = false;
/* if we've already processed the frames corresponding to this call,
just return. this allows multiple routes that are taking input
from this diskstream to call our ::process() method, but have
this stuff only happen once. more commonly, it allows both
the AudioTrack that is using this AudioDiskstream *and* the Session
to call process() without problems.
*/
if (_processed) {
return 0;
}
commit_should_unlock = false;
playback_distance = 0;
if (!_io || !_io->active()) {
_processed = true;
return 0;
}
@ -461,20 +448,15 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can
nominally_recording = (can_record && re);
if (nframes == 0) {
_processed = true;
return 0;
}
/* This lock is held until the end of AudioDiskstream::commit, so these two functions
must always be called as a pair. The only exception is if this function
returns a non-zero value, in which case, ::commit should not be called.
*/
Glib::Mutex::Lock sm (state_lock, Glib::TRY_LOCK);
// If we can't take the state lock return.
if (!state_lock.trylock()) {
if (!sm.locked()) {
return 1;
}
commit_should_unlock = true;
adjust_capture_position = 0;
for (chan = c->begin(); chan != c->end(); ++chan) {
@ -669,19 +651,11 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can
ret = 0;
if (commit (nframes)) {
need_butler = true;
}
out:
_processed = true;
if (ret) {
/* we're exiting with failure, so ::commit will not
be called. unlock the state lock.
*/
commit_should_unlock = false;
state_lock.unlock();
}
return ret;
}
@ -704,7 +678,7 @@ AudioDiskstream::process_varispeed_playback(nframes_t nframes, boost::shared_ptr
}
bool
AudioDiskstream::commit (nframes_t /*nframes*/)
AudioDiskstream::commit (nframes_t /* nframes */)
{
bool need_butler = false;
@ -748,12 +722,6 @@ AudioDiskstream::commit (nframes_t /*nframes*/)
}
}
if (commit_should_unlock) {
state_lock.unlock();
}
_processed = false;
return need_butler;
}

View File

@ -376,14 +376,14 @@ AudioTrack::set_state_part_two ()
int
AudioTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, int declick,
bool can_record, bool rec_monitors_input)
bool can_record, bool rec_monitors_input, bool& need_butler)
{
int dret;
Sample* b;
Sample* tmpb;
nframes_t transport_frame;
boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
{
Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
if (lm.locked()) {
@ -410,13 +410,13 @@ AudioTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
playback distance to zero, thus causing diskstream::commit
to do nothing.
*/
return diskstream->process (transport_frame, 0, can_record, rec_monitors_input);
return diskstream->process (transport_frame, 0, can_record, rec_monitors_input, need_butler);
}
_silent = false;
_amp->apply_gain_automation(false);
if ((dret = diskstream->process (transport_frame, nframes, can_record, rec_monitors_input)) != 0) {
if ((dret = diskstream->process (transport_frame, nframes, can_record, rec_monitors_input, need_butler)) != 0) {
silence (nframes);
return dret;
}

View File

@ -199,7 +199,7 @@ Auditioner::audition_region (boost::shared_ptr<Region> region)
int
Auditioner::play_audition (nframes_t nframes)
{
bool need_butler;
bool need_butler = false;
nframes_t this_nframes;
int ret;
@ -210,14 +210,11 @@ Auditioner::play_audition (nframes_t nframes)
this_nframes = min (nframes, length - current_frame);
_diskstream->prepare ();
if ((ret = roll (this_nframes, current_frame, current_frame + nframes, false, false, false)) != 0) {
if ((ret = roll (this_nframes, current_frame, current_frame + nframes, false, false, false, need_butler)) != 0) {
silence (nframes);
return ret;
}
need_butler = _diskstream->commit (this_nframes);
current_frame += this_nframes;
if (current_frame >= length) {

View File

@ -104,7 +104,6 @@ Diskstream::init (Flag f)
last_recordable_frame = max_frames;
_roll_delay = 0;
_capture_offset = 0;
_processed = false;
_slaved = false;
adjust_capture_position = 0;
last_possibly_recording = 0;
@ -118,7 +117,6 @@ Diskstream::init (Flag f)
playback_distance = 0;
_read_data_count = 0;
_write_data_count = 0;
commit_should_unlock = false;
pending_overwrite = false;
overwrite_frame = 0;
@ -219,22 +217,6 @@ Diskstream::realtime_set_speed (double sp, bool global)
return _buffer_reallocation_required || _seek_required;
}
void
Diskstream::prepare ()
{
_processed = false;
playback_distance = 0;
}
void
Diskstream::recover ()
{
if (commit_should_unlock) {
state_lock.unlock();
}
_processed = false;
}
void
Diskstream::set_capture_offset ()
{

View File

@ -487,7 +487,7 @@ trace_midi (ostream& o, MIDI::byte *msg, size_t len)
#endif
int
MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can_record, bool rec_monitors_input)
MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can_record, bool rec_monitors_input, bool& need_butler)
{
int ret = -1;
nframes_t rec_offset = 0;
@ -495,39 +495,22 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can_
bool nominally_recording;
bool re = record_enabled ();
/* if we've already processed the frames corresponding to this call,
just return. this allows multiple routes that are taking input
from this diskstream to call our ::process() method, but have
this stuff only happen once. more commonly, it allows both
the AudioTrack that is using this AudioDiskstream *and* the Session
to call process() without problems.
*/
if (_processed) {
return 0;
}
commit_should_unlock = false;
playback_distance = 0;
check_record_status (transport_frame, nframes, can_record);
nominally_recording = (can_record && re);
if (nframes == 0) {
_processed = true;
return 0;
}
/* This lock is held until the end of ::commit, so these two functions
must always be called as a pair. The only exception is if this function
returns a non-zero value, in which case, ::commit should not be called.
*/
Glib::Mutex::Lock sm (state_lock, Glib::TRY_LOCK);
// If we can't take the state lock return.
if (!state_lock.trylock()) {
if (!sm.locked()) {
return 1;
}
commit_should_unlock = true;
adjust_capture_position = 0;
if (nominally_recording || (_session.get_record_enabled() && _session.config.get_punch_in())) {
@ -586,17 +569,9 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can_
ret = 0;
_processed = true;
if (ret) {
/* we're exiting with failure, so ::commit will not
be called. unlock the state lock.
*/
commit_should_unlock = false;
state_lock.unlock();
}
if (commit (nframes)) {
need_butler = true;
}
return ret;
}
@ -627,12 +602,6 @@ MidiDiskstream::commit (nframes_t nframes)
" = " << frames_written - frames_read
<< " + " << nframes << " < " << midi_readahead << " = " << need_butler << ")" << endl;*/
if (commit_should_unlock) {
state_lock.unlock();
}
_processed = false;
return need_butler;
}

View File

@ -298,8 +298,8 @@ MidiTrack::set_state_part_two ()
}
int
MidiTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, int declick,
bool can_record, bool rec_monitors_input)
MidiTrack::roll (nframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick,
bool can_record, bool rec_monitors_input, bool& needs_butler)
{
int dret;
boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
@ -330,12 +330,12 @@ MidiTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
playback distance to zero, thus causing diskstream::commit
to do nothing.
*/
return diskstream->process (transport_frame, 0, can_record, rec_monitors_input);
return diskstream->process (transport_frame, 0, can_record, rec_monitors_input, needs_butler);
}
_silent = false;
if ((dret = diskstream->process (transport_frame, nframes, can_record, rec_monitors_input)) != 0) {
if ((dret = diskstream->process (transport_frame, nframes, can_record, rec_monitors_input, needs_butler)) != 0) {
silence (nframes);
return dret;
}

View File

@ -2687,7 +2687,7 @@ Route::check_initial_delay (nframes_t nframes, nframes_t& transport_frame)
int
Route::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, int declick,
bool /*can_record*/, bool /*rec_monitors_input*/)
bool /*can_record*/, bool /*rec_monitors_input*/, bool& /* need_butler */)
{
{
// automation snapshot can also be called from the non-rt context
@ -2723,7 +2723,7 @@ Route::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, int
int
Route::silent_roll (nframes_t nframes, sframes_t /*start_frame*/, sframes_t /*end_frame*/,
bool /*can_record*/, bool /*rec_monitors_input*/)
bool /*can_record*/, bool /*rec_monitors_input*/, bool& /* need_butler */)
{
silence (nframes);
return 0;

View File

@ -2103,9 +2103,6 @@ Session::add_diskstream (boost::shared_ptr<Diskstream> dstream)
diskstream_playlist_changed (boost::weak_ptr<Diskstream> (dstream));
dstream->RecordEnableChanged.connect_same_thread (*this, boost::bind (&Session::update_have_rec_enabled_diskstream, this));
dstream->prepare ();
}
void

View File

@ -81,15 +81,6 @@ Session::process (nframes_t nframes)
MIDI::Manager::instance()->cycle_end();
}
void
Session::prepare_diskstreams ()
{
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->prepare ();
}
}
int
Session::fail_roll (nframes_t nframes)
{
@ -128,7 +119,7 @@ Session::no_roll (nframes_t nframes)
}
int
Session::process_routes (nframes_t nframes)
Session::process_routes (nframes_t nframes, bool& need_butler)
{
bool record_active;
int declick = get_transport_declick_required();
@ -155,18 +146,7 @@ Session::process_routes (nframes_t nframes)
(*i)->set_pending_declick (declick);
if ((ret = (*i)->roll (nframes, start_frame, end_frame, declick, record_active, rec_monitors)) < 0) {
/* we have to do this here. Route::roll() for an AudioTrack will have called AudioDiskstream::process(),
and the DS will expect AudioDiskstream::commit() to be called. but we're aborting from that
call path, so make sure we release any outstanding locks here before we return failure.
*/
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator ids = dsl->begin(); ids != dsl->end(); ++ids) {
(*ids)->recover ();
}
if ((ret = (*i)->roll (nframes, start_frame, end_frame, declick, record_active, rec_monitors, need_butler)) < 0) {
stop_transport ();
return -1;
}
@ -176,7 +156,7 @@ Session::process_routes (nframes_t nframes)
}
int
Session::silent_process_routes (nframes_t nframes)
Session::silent_process_routes (nframes_t nframes, bool& need_butler)
{
bool record_active = actively_recording();
int declick = get_transport_declick_required();
@ -199,18 +179,7 @@ Session::silent_process_routes (nframes_t nframes)
continue;
}
if ((ret = (*i)->silent_roll (nframes, start_frame, end_frame, record_active, rec_monitors)) < 0) {
/* we have to do this here. Route::roll() for an AudioTrack will have called AudioDiskstream::process(),
and the DS will expect AudioDiskstream::commit() to be called. but we're aborting from that
call path, so make sure we release any outstanding locks here before we return failure.
*/
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator ids = dsl->begin(); ids != dsl->end(); ++ids) {
(*ids)->recover ();
}
if ((ret = (*i)->silent_roll (nframes, start_frame, end_frame, record_active, rec_monitors, need_butler)) < 0) {
stop_transport ();
return -1;
}
@ -220,7 +189,7 @@ Session::silent_process_routes (nframes_t nframes)
}
void
Session::commit_diskstreams (nframes_t nframes, bool &needs_butler)
Session::get_diskstream_statistics ()
{
int dret;
float pworst = 1.0f;
@ -233,21 +202,6 @@ Session::commit_diskstreams (nframes_t nframes, bool &needs_butler)
continue;
}
/* force all diskstreams not handled by a Route to call do their stuff.
Note: the diskstreams that were handled by a route will just return zero
from this call, because they know they were processed. So in fact, this
also runs commit() for every diskstream.
*/
if ((dret = (*i)->process (_transport_frame, nframes, actively_recording(), get_rec_monitors_input())) == 0) {
if ((*i)->commit (nframes)) {
needs_butler = true;
}
} else if (dret < 0) {
(*i)->recover();
}
pworst = min (pworst, (*i)->playback_buffer_load());
cworst = min (cworst, (*i)->capture_buffer_load());
}
@ -394,16 +348,11 @@ Session::process_with_events (nframes_t nframes)
click (_transport_frame, this_nframes);
/* now process frames between now and the first event in this block */
prepare_diskstreams ();
if (process_routes (this_nframes)) {
if (process_routes (this_nframes, session_needs_butler)) {
fail_roll (nframes);
return;
}
commit_diskstreams (this_nframes, session_needs_butler);
nframes -= this_nframes;
if (frames_moved < 0) {
@ -746,9 +695,7 @@ Session::follow_slave_silently (nframes_t nframes, float slave_speed)
bool need_butler;
prepare_diskstreams ();
silent_process_routes (nframes);
commit_diskstreams (nframes, need_butler);
silent_process_routes (nframes, need_butler);
if (need_butler) {
_butler->summon ();
@ -826,8 +773,6 @@ Session::process_without_events (nframes_t nframes)
click (_transport_frame, nframes);
prepare_diskstreams ();
if (_transport_speed == 1.0) {
frames_moved = (long) nframes;
} else {
@ -836,13 +781,11 @@ Session::process_without_events (nframes_t nframes)
frames_moved = (long) interpolation.interpolate (0, nframes, 0, 0);
}
if (process_routes (nframes)) {
if (process_routes (nframes, session_needs_butler)) {
fail_roll (nframes);
return;
}
commit_diskstreams (nframes, session_needs_butler);
if (frames_moved < 0) {
decrement_transport_position (-frames_moved);
} else {

View File

@ -234,7 +234,7 @@ Track::zero_diskstream_id_in_xml (XMLNode& node)
}
int
Track::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
Track::no_roll (nframes_t nframes, framepos_t start_frame, framepos_t end_frame,
bool session_state_changing, bool can_record, bool /*rec_monitors_input*/)
{
if (n_outputs().n_total() == 0) {
@ -329,8 +329,8 @@ Track::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
}
int
Track::silent_roll (nframes_t nframes, sframes_t /*start_frame*/, sframes_t /*end_frame*/,
bool can_record, bool rec_monitors_input)
Track::silent_roll (nframes_t nframes, framepos_t /*start_frame*/, framepos_t /*end_frame*/,
bool can_record, bool rec_monitors_input, bool& need_butler)
{
if (n_outputs().n_total() == 0 && _processors.empty()) {
return 0;
@ -346,7 +346,7 @@ Track::silent_roll (nframes_t nframes, sframes_t /*start_frame*/, sframes_t /*en
silence (nframes);
return diskstream()->process (_session.transport_frame(), nframes, can_record, rec_monitors_input);
return diskstream()->process (_session.transport_frame(), nframes, can_record, rec_monitors_input, need_butler);
}
ChanCount
@ -360,3 +360,4 @@ Track::input_streams () const
return cc;
}