13
0

a much better fix for track-add crashes, albeit slightly more complex

git-svn-id: svn://localhost/ardour2/trunk@1604 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2007-03-16 17:48:13 +00:00
parent bca0450c18
commit 3e36907353
9 changed files with 319 additions and 339 deletions

View File

@ -32,6 +32,7 @@
#include <pbd/fastlog.h>
#include <pbd/ringbufferNPT.h>
#include <pbd/stateful.h>
#include <pbd/rcu.h>
#include <ardour/ardour.h>
#include <ardour/configuration.h>
@ -65,24 +66,28 @@ class AudioDiskstream : public Diskstream
float capture_buffer_load() const;
string input_source (uint32_t n=0) const {
if (n < channels.size()) {
return channels[n].source ? channels[n].source->name() : "";
boost::shared_ptr<ChannelList> c = channels.reader();
if (n < c->size()) {
return (*c)[n]->source ? (*c)[n]->source->name() : "";
} else {
return "";
}
}
Port *input_source_port (uint32_t n=0) const {
if (n < channels.size()) return channels[n].source; return 0;
boost::shared_ptr<ChannelList> c = channels.reader();
if (n < c->size()) return (*c)[n]->source; return 0;
}
void set_record_enabled (bool yn);
int set_destructive (bool yn);
bool can_become_destructive (bool& requires_bounce) const;
float peak_power(uint32_t n=0) {
float x = channels[n].peak_power;
channels[n].peak_power = 0.0f;
float peak_power(uint32_t n = 0) {
boost::shared_ptr<ChannelList> c = channels.reader();
ChannelInfo* chaninfo = (*c)[n];
float x = chaninfo->peak_power;
chaninfo->peak_power = 0.0f;
if (x > 0.0f) {
return 20.0f * fast_log10(x);
} else {
@ -96,27 +101,29 @@ class AudioDiskstream : public Diskstream
int use_new_playlist ();
int use_copy_playlist ();
Sample *playback_buffer (uint32_t n=0) {
if (n < channels.size())
return channels[n].current_playback_buffer;
Sample *playback_buffer (uint32_t n = 0) {
boost::shared_ptr<ChannelList> c = channels.reader();
if (n < c->size())
return (*c)[n]->current_playback_buffer;
return 0;
}
Sample *capture_buffer (uint32_t n=0) {
if (n < channels.size())
return channels[n].current_capture_buffer;
Sample *capture_buffer (uint32_t n = 0) {
boost::shared_ptr<ChannelList> c = channels.reader();
if (n < c->size())
return (*c)[n]->current_capture_buffer;
return 0;
}
boost::shared_ptr<AudioFileSource> write_source (uint32_t n=0) {
if (n < channels.size())
return channels[n].write_source;
boost::shared_ptr<ChannelList> c = channels.reader();
if (n < c->size())
return (*c)[n]->write_source;
return boost::shared_ptr<AudioFileSource>();
}
int add_channel ();
int remove_channel ();
int add_channel (uint32_t how_many);
int remove_channel (uint32_t how_many);
/* stateful */
@ -174,12 +181,9 @@ class AudioDiskstream : public Diskstream
struct ChannelInfo {
ChannelInfo ();
ChannelInfo (nframes_t buffer_size, nframes_t speed_buffer_size, nframes_t wrap_buffer_size);
~ChannelInfo ();
void init (nframes_t buffer_size, nframes_t speed_buffer_size, nframes_t wrap_buffer_size);
void release ();
Sample *playback_wrap_buffer;
Sample *capture_wrap_buffer;
Sample *speed_buffer;
@ -208,6 +212,8 @@ class AudioDiskstream : public Diskstream
nframes_t curr_capture_cnt;
};
typedef std::vector<ChannelInfo*> ChannelList;
/* The two central butler operations */
int do_flush (Session::RunContext context, bool force = false);
int do_refill () { return _do_refill(_mixdown_buffer, _gain_buffer); }
@ -215,10 +221,10 @@ class AudioDiskstream : public Diskstream
int do_refill_with_alloc ();
int read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
nframes_t& start, nframes_t cnt,
ChannelInfo& channel_info, int channel, bool reversed);
nframes_t& start, nframes_t cnt,
ChannelInfo* channel_info, int channel, bool reversed);
void finish_capture (bool rec_monitors_input);
void finish_capture (bool rec_monitors_input, boost::shared_ptr<ChannelList>);
void transport_stopped (struct tm&, time_t, bool abort);
void init (Diskstream::Flag);
@ -253,12 +259,15 @@ class AudioDiskstream : public Diskstream
std::vector<boost::shared_ptr<AudioFileSource> > capturing_sources;
typedef vector<ChannelInfo> ChannelList;
ChannelList channels;
SerializedRCUManager<ChannelList> channels;
/* really */
private:
int _do_refill (Sample *mixdown_buffer, float *gain_buffer);
int add_channel_to (boost::shared_ptr<ChannelList>, uint32_t how_many);
int remove_channel_from (boost::shared_ptr<ChannelList>, uint32_t how_many);
};
} // namespace ARDOUR

View File

@ -21,7 +21,6 @@
#define __ardour_diskstream_h__
#include <sigc++/signal.h>
#include <boost/enable_shared_from_this.hpp>
#include <cmath>
#include <string>
@ -54,7 +53,7 @@ class Session;
class Playlist;
class IO;
class Diskstream : public PBD::StatefulDestructible, public boost::enable_shared_from_this<ARDOUR::Diskstream>
class Diskstream : public PBD::StatefulDestructible
{
public:
enum Flag {
@ -207,7 +206,6 @@ class Diskstream : public PBD::StatefulDestructible, public boost::enable_shared
virtual void playlist_modified ();
virtual void playlist_deleted (boost::weak_ptr<Playlist>);
virtual void finish_capture (bool rec_monitors_input) = 0;
virtual void transport_stopped (struct tm&, time_t, bool abort) = 0;
struct CaptureInfo {

View File

@ -165,7 +165,6 @@ class Session : public PBD::StatefulDestructible
};
boost::shared_ptr<Region> region;
boost::shared_ptr<Diskstream> diskstream;
list<AudioRange> audio_range;
list<MusicRange> music_range;
@ -362,7 +361,7 @@ class Session : public PBD::StatefulDestructible
void request_transport_speed (float speed);
void request_overwrite_buffer (Diskstream*);
void request_diskstream_speed (Diskstream&, float speed);
void request_input_change_handling (boost::shared_ptr<ARDOUR::Diskstream>);
void request_input_change_handling ();
bool locate_pending() const { return static_cast<bool>(post_transport_work&PostTransportLocate); }
bool transport_locked () const;
@ -1425,7 +1424,6 @@ class Session : public PBD::StatefulDestructible
/* disk-streams */
SerializedRCUManager<DiskstreamList> diskstreams;
SerializedRCUManager<DiskstreamList> diskstreams_input_pending;
uint32_t dstream_buffer_size;
int load_diskstreams (const XMLNode&);

File diff suppressed because it is too large Load Diff

View File

@ -64,7 +64,7 @@ Auditioner::Auditioner (Session& s)
}
if (right.length()) {
audio_diskstream()->add_channel();
audio_diskstream()->add_channel (1);
add_output_port (right, this, DataType::AUDIO);
}
@ -138,12 +138,10 @@ Auditioner::audition_region (boost::shared_ptr<Region> region)
_diskstream->playlist()->clear ();
_diskstream->playlist()->add_region (the_region, 0, 1);
while (_diskstream->n_channels() < the_region->n_channels()) {
audio_diskstream()->add_channel ();
}
while (_diskstream->n_channels() > the_region->n_channels()) {
audio_diskstream()->remove_channel ();
if (_diskstream->n_channels() < the_region->n_channels()) {
audio_diskstream()->add_channel (the_region->n_channels() - _diskstream->n_channels());
} else if (_diskstream->n_channels() > the_region->n_channels()) {
audio_diskstream()->remove_channel (_diskstream->n_channels() - the_region->n_channels());
}
/* force a panner reset now that we have all channels */

View File

@ -143,7 +143,7 @@ Diskstream::handle_input_change (IOChange change, void *src)
if (!(input_change_pending & change)) {
input_change_pending = IOChange (input_change_pending|change);
_session.request_input_change_handling (shared_from_this());
_session.request_input_change_handling ();
}
}

View File

@ -269,7 +269,6 @@ Session::Session (AudioEngine &eng,
pending_events (2048),
midi_requests (128), // the size of this should match the midi request pool size
diskstreams (new DiskstreamList),
diskstreams_input_pending (new DiskstreamList),
routes (new RouteList),
auditioner ((Auditioner*) 0),
_click_io ((IO*) 0),
@ -333,7 +332,6 @@ Session::Session (AudioEngine &eng,
pending_events (2048),
midi_requests (16),
diskstreams (new DiskstreamList),
diskstreams_input_pending (new DiskstreamList),
routes (new RouteList),
main_outs (0)
@ -2008,7 +2006,7 @@ Session::add_diskstream (boost::shared_ptr<Diskstream> dstream)
dstream->set_block_size (current_block_size);
if (_state_of_the_state & InitialConnecting) {
{
RCUWriter<DiskstreamList> writer (diskstreams);
boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
ds->push_back (dstream);
@ -3387,11 +3385,7 @@ Session::graph_reordered ()
we were connecting. do it now.
*/
boost::shared_ptr<DiskstreamList> ds = diskstreams.reader();
for (DiskstreamList::iterator i = ds->begin(); i != ds->end(); ++i) {
request_input_change_handling (*i);
}
request_input_change_handling ();
resort_routes ();

View File

@ -410,18 +410,6 @@ Session::process_event (Event* ev)
case Event::InputConfigurationChange:
post_transport_work = PostTransportWork (post_transport_work | PostTransportInputChange);
{
RCUWriter<DiskstreamList> writer (diskstreams);
boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
ds->remove (ev->diskstream);
/* writer goes out of scope, copies ds back to main */
}
{
RCUWriter<DiskstreamList> writer (diskstreams_input_pending);
boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
ds->push_back (ev->diskstream);
/* writer goes out of scope, copies ds back to main */
}
schedule_butler_transport_work ();
break;

View File

@ -49,11 +49,10 @@ using namespace sigc;
using namespace PBD;
void
Session::request_input_change_handling (boost::shared_ptr<Diskstream> ds)
Session::request_input_change_handling ()
{
if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0);
ev->diskstream = ds;
queue_event (ev);
}
}
@ -197,27 +196,9 @@ Session::butler_transport_work ()
}
if (post_transport_work & PostTransportInputChange) {
{
RCUWriter<DiskstreamList> input_writer (diskstreams_input_pending);
boost::shared_ptr<DiskstreamList> input_list = input_writer.get_copy ();
RCUWriter<DiskstreamList> dswriter (diskstreams);
boost::shared_ptr<DiskstreamList> ds = dswriter.get_copy();
for (DiskstreamList::iterator i = input_list->begin(); i != input_list->end(); ++i) {
/* make the change */
(*i)->non_realtime_input_change ();
/* now transfer it back onto the regular diskstreams list */
ds->push_back (*i);
}
input_list->clear();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->non_realtime_input_change ();
}
diskstreams_input_pending.flush ();
}
if (post_transport_work & PostTransportSpeed) {