RCU-ification of AudioEngine port list, and DiskStreams. not well tested, but basically functional. better to get this in now rather than later.

git-svn-id: svn://localhost/ardour2/trunk@828 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2006-08-16 01:19:06 +00:00
parent c5619a0f98
commit 1ae0948138
36 changed files with 354 additions and 340 deletions

View file

@ -545,7 +545,7 @@ void
ARDOUR_UI::count_recenabled_diskstreams (Route& route) ARDOUR_UI::count_recenabled_diskstreams (Route& route)
{ {
Track* track = dynamic_cast<Track*>(&route); Track* track = dynamic_cast<Track*>(&route);
if (track && track->diskstream().record_enabled()) { if (track && track->diskstream()->record_enabled()) {
rec_enabled_diskstreams++; rec_enabled_diskstreams++;
} }
} }
@ -917,11 +917,6 @@ restart JACK with more ports."));
} }
} }
void
ARDOUR_UI::diskstream_added (Diskstream* ds)
{
}
void void
ARDOUR_UI::do_transport_locate (jack_nframes_t new_position) ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
{ {
@ -1172,7 +1167,7 @@ ARDOUR_UI::toggle_record_enable (uint32_t dstream)
Track* t; Track* t;
if ((t = dynamic_cast<Track*>(r.get())) != 0) { if ((t = dynamic_cast<Track*>(r.get())) != 0) {
t->diskstream().set_record_enabled (!t->diskstream().record_enabled()); t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
} }
} }
if (session == 0) { if (session == 0) {

View file

@ -520,8 +520,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
sigc::connection point_one_second_connection; sigc::connection point_one_second_connection;
sigc::connection point_zero_one_second_connection; sigc::connection point_zero_one_second_connection;
void diskstream_added (ARDOUR::Diskstream*);
gint session_menu (GdkEventButton *); gint session_menu (GdkEventButton *);
bool _will_create_new_session_automatically; bool _will_create_new_session_automatically;

View file

@ -76,10 +76,6 @@ ARDOUR_UI::connect_to_session (Session *s)
rec_button.set_sensitive (true); rec_button.set_sensitive (true);
shuttle_box.set_sensitive (true); shuttle_box.set_sensitive (true);
if (session->n_diskstreams() == 0) {
session->DiskstreamAdded.connect (mem_fun(*this, &ARDOUR_UI::diskstream_added));
}
if (connection_editor) { if (connection_editor) {
connection_editor->set_session (s); connection_editor->set_session (s);
} }

View file

@ -225,7 +225,7 @@ AudioStreamView::playlist_modified ()
} }
void void
AudioStreamView::playlist_changed (Diskstream *ds) AudioStreamView::playlist_changed (boost::shared_ptr<Diskstream> ds)
{ {
ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::playlist_changed), ds)); ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::playlist_changed), ds));
@ -399,7 +399,7 @@ AudioStreamView::setup_rec_box ()
peak_ready_connections.clear(); peak_ready_connections.clear();
// FIXME // FIXME
AudioDiskstream* ads = dynamic_cast<AudioDiskstream*>(_trackview.get_diskstream()); boost::shared_ptr<AudioDiskstream> ads = boost::dynamic_pointer_cast<AudioDiskstream>(_trackview.get_diskstream());
assert(ads); assert(ads);
for (uint32_t n=0; n < ads->n_channels(); ++n) { for (uint32_t n=0; n < ads->n_channels(); ++n) {
@ -431,8 +431,8 @@ AudioStreamView::setup_rec_box ()
AudioTrack* at; AudioTrack* at;
at = _trackview.audio_track(); /* we know what it is already */ at = _trackview.audio_track(); /* we know what it is already */
AudioDiskstream& ds = at->audio_diskstream(); boost::shared_ptr<AudioDiskstream> ds = at->audio_diskstream();
jack_nframes_t frame_pos = ds.current_capture_start (); jack_nframes_t frame_pos = ds->current_capture_start ();
gdouble xstart = _trackview.editor.frame_to_pixel (frame_pos); gdouble xstart = _trackview.editor.frame_to_pixel (frame_pos);
gdouble xend; gdouble xend;
uint32_t fill_color; uint32_t fill_color;

View file

@ -87,7 +87,7 @@ class AudioStreamView : public StreamView
void undisplay_diskstream (); void undisplay_diskstream ();
void redisplay_diskstream (); void redisplay_diskstream ();
void playlist_modified (); void playlist_modified ();
void playlist_changed (ARDOUR::Diskstream *ds); void playlist_changed (boost::shared_ptr<ARDOUR::Diskstream>);
void add_crossfade (ARDOUR::Crossfade*); void add_crossfade (ARDOUR::Crossfade*);
void remove_crossfade (ARDOUR::Crossfade*); void remove_crossfade (ARDOUR::Crossfade*);

View file

@ -1596,7 +1596,7 @@ Editor::build_track_region_context_menu (jack_nframes_t frame)
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview); AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
if (atv) { if (atv) {
Diskstream* ds; boost::shared_ptr<Diskstream> ds;
Playlist* pl; Playlist* pl;
if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) { if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
@ -1623,7 +1623,7 @@ Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview); AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
if (atv) { if (atv) {
Diskstream* ds; boost::shared_ptr<Diskstream> ds;
Playlist* pl; Playlist* pl;
AudioPlaylist* apl; AudioPlaylist* apl;
@ -3020,7 +3020,7 @@ Editor::mapped_set_selected_regionview_from_click (RouteTimeAxisView& tv, uint32
Playlist* pl; Playlist* pl;
vector<Region*> results; vector<Region*> results;
RegionView* marv; RegionView* marv;
Diskstream* ds; boost::shared_ptr<Diskstream> ds;
if ((ds = tv.get_diskstream()) == 0) { if ((ds = tv.get_diskstream()) == 0) {
/* bus */ /* bus */
@ -3246,7 +3246,7 @@ Editor::set_selected_regionview_from_region_list (Region& region, Selection::Ope
Playlist* pl; Playlist* pl;
vector<Region*> results; vector<Region*> results;
RegionView* marv; RegionView* marv;
Diskstream* ds; boost::shared_ptr<Diskstream> ds;
if ((ds = tatv->get_diskstream()) == 0) { if ((ds = tatv->get_diskstream()) == 0) {
/* bus */ /* bus */

View file

@ -317,7 +317,7 @@ Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32
case ImportToTrack: case ImportToTrack:
if (track) { if (track) {
Playlist* playlist = track->diskstream().playlist(); Playlist* playlist = track->diskstream()->playlist();
AudioRegion* copy = new AudioRegion (region); AudioRegion* copy = new AudioRegion (region);
begin_reversible_command (_("insert sndfile")); begin_reversible_command (_("insert sndfile"));
@ -334,7 +334,7 @@ Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32
{ {
boost::shared_ptr<AudioTrack> at (session->new_audio_track (in_chans, out_chans, Normal)); boost::shared_ptr<AudioTrack> at (session->new_audio_track (in_chans, out_chans, Normal));
copy = new AudioRegion (region); copy = new AudioRegion (region);
at->diskstream().playlist()->add_region (*copy, pos); at->diskstream()->playlist()->add_region (*copy, pos);
break; break;
} }
@ -342,7 +342,7 @@ Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32
{ {
boost::shared_ptr<AudioTrack> at (session->new_audio_track (in_chans, out_chans, Destructive)); boost::shared_ptr<AudioTrack> at (session->new_audio_track (in_chans, out_chans, Destructive));
copy = new AudioRegion (region); copy = new AudioRegion (region);
at->diskstream().playlist()->add_region (*copy, pos); at->diskstream()->playlist()->add_region (*copy, pos);
break; break;
} }
} }

View file

@ -188,7 +188,7 @@ Editor::do_timestretch (TimeStretchDialog& dialog)
continue; continue;
} }
if ((playlist = t->diskstream().playlist()) == 0) { if ((playlist = t->diskstream()->playlist()) == 0) {
i = tmp; i = tmp;
continue; continue;
} }

View file

@ -90,7 +90,7 @@ void
PlaylistSelector::show_for (RouteUI* ruix) PlaylistSelector::show_for (RouteUI* ruix)
{ {
vector<const char*> item; vector<const char*> item;
Diskstream* this_ds; boost::shared_ptr<Diskstream> this_ds;
string str; string str;
rui = ruix; rui = ruix;
@ -116,7 +116,7 @@ PlaylistSelector::show_for (RouteUI* ruix)
for (DSPL_Map::iterator x = dspl_map.begin(); x != dspl_map.end(); ++x) { for (DSPL_Map::iterator x = dspl_map.begin(); x != dspl_map.end(); ++x) {
Diskstream* ds = session->diskstream_by_id (x->first); boost::shared_ptr<Diskstream> ds = session->diskstream_by_id (x->first);
if (ds == 0) { if (ds == 0) {
continue; continue;
@ -243,7 +243,7 @@ PlaylistSelector::selection_changed ()
return; return;
} }
at->diskstream().use_playlist (apl); at->diskstream()->use_playlist (apl);
hide (); hide ();
} }

View file

@ -226,7 +226,7 @@ PluginSelector::set_correct_focus()
au_display.grab_focus(); au_display.grab_focus();
return; return;
} }
#endif; #endif
} }
void void

View file

@ -728,7 +728,7 @@ RouteTimeAxisView::rename_current_playlist ()
ArdourPrompter prompter (true); ArdourPrompter prompter (true);
string name; string name;
Diskstream *const ds = get_diskstream(); boost::shared_ptr<Diskstream> ds = get_diskstream();
if (!ds || ds->destructive()) if (!ds || ds->destructive())
return; return;
@ -759,7 +759,7 @@ RouteTimeAxisView::use_copy_playlist (bool prompt)
{ {
string name; string name;
Diskstream *const ds = get_diskstream(); boost::shared_ptr<Diskstream> ds = get_diskstream();
if (!ds || ds->destructive()) if (!ds || ds->destructive())
return; return;
@ -800,7 +800,7 @@ RouteTimeAxisView::use_new_playlist (bool prompt)
{ {
string name; string name;
Diskstream *const ds = get_diskstream(); boost::shared_ptr<Diskstream> ds = get_diskstream();
if (!ds || ds->destructive()) if (!ds || ds->destructive())
return; return;
@ -838,7 +838,7 @@ RouteTimeAxisView::use_new_playlist (bool prompt)
void void
RouteTimeAxisView::clear_playlist () RouteTimeAxisView::clear_playlist ()
{ {
Diskstream *const ds = get_diskstream(); boost::shared_ptr<Diskstream> ds = get_diskstream();
if (!ds || ds->destructive()) if (!ds || ds->destructive())
return; return;
@ -963,7 +963,7 @@ RouteTimeAxisView::name() const
Playlist * Playlist *
RouteTimeAxisView::playlist () const RouteTimeAxisView::playlist () const
{ {
Diskstream *ds; boost::shared_ptr<Diskstream> ds;
if ((ds = get_diskstream()) != 0) { if ((ds = get_diskstream()) != 0) {
return ds->playlist(); return ds->playlist();
@ -1013,7 +1013,7 @@ RouteTimeAxisView::hide_click ()
Region* Region*
RouteTimeAxisView::find_next_region (jack_nframes_t pos, RegionPoint point, int32_t dir) RouteTimeAxisView::find_next_region (jack_nframes_t pos, RegionPoint point, int32_t dir)
{ {
Diskstream *stream; boost::shared_ptr<Diskstream> stream;
Playlist *playlist; Playlist *playlist;
if ((stream = get_diskstream()) != 0 && (playlist = stream->playlist()) != 0) { if ((stream = get_diskstream()) != 0 && (playlist = stream->playlist()) != 0) {
@ -1027,7 +1027,7 @@ bool
RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op) RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
{ {
Playlist* what_we_got; Playlist* what_we_got;
Diskstream* ds = get_diskstream(); boost::shared_ptr<Diskstream> ds = get_diskstream();
Playlist* playlist; Playlist* playlist;
bool ret = false; bool ret = false;

View file

@ -74,7 +74,7 @@ RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, co
if (is_track()) { if (is_track()) {
boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route); boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
t->diskstream().RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed)); t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed));
_session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed)); _session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed));
@ -733,7 +733,7 @@ void
RouteUI::route_removed () RouteUI::route_removed ()
{ {
ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::route_removed)); ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::route_removed));
cerr << "Route UI @ " << this << " destroyed by impending end of route\n";
delete this; delete this;
} }
@ -905,15 +905,15 @@ RouteUI::audio_track() const
return dynamic_cast<AudioTrack*>(_route.get()); return dynamic_cast<AudioTrack*>(_route.get());
} }
Diskstream* boost::shared_ptr<Diskstream>
RouteUI::get_diskstream () const RouteUI::get_diskstream () const
{ {
boost::shared_ptr<Track> t; boost::shared_ptr<Track> t;
if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) { if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
return &t->diskstream(); return t->diskstream();
} else { } else {
return 0; return boost::shared_ptr<Diskstream> ((Diskstream*) 0);
} }
} }

View file

@ -57,7 +57,7 @@ class RouteUI : public virtual AxisView
ARDOUR::Track* track() const; ARDOUR::Track* track() const;
ARDOUR::AudioTrack* audio_track() const; ARDOUR::AudioTrack* audio_track() const;
ARDOUR::Diskstream* get_diskstream() const; boost::shared_ptr<ARDOUR::Diskstream> get_diskstream() const;
string name() const; string name() const;

View file

@ -206,7 +206,7 @@ StreamView::undisplay_diskstream ()
} }
void void
StreamView::display_diskstream (Diskstream *ds) StreamView::display_diskstream (boost::shared_ptr<Diskstream> ds)
{ {
playlist_change_connection.disconnect(); playlist_change_connection.disconnect();
playlist_changed (ds); playlist_changed (ds);
@ -224,7 +224,7 @@ StreamView::playlist_modified ()
} }
void void
StreamView::playlist_changed (Diskstream *ds) StreamView::playlist_changed (boost::shared_ptr<Diskstream> ds)
{ {
ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::playlist_changed), ds)); ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::playlist_changed), ds));
@ -263,9 +263,7 @@ StreamView::diskstream_changed ()
Track *t; Track *t;
if ((t = _trackview.track()) != 0) { if ((t = _trackview.track()) != 0) {
Diskstream& ds = t->diskstream(); Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*this, &StreamView::display_diskstream), t->diskstream()));
/* XXX grrr: when will SigC++ allow me to bind references? */
Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*this, &StreamView::display_diskstream), &ds));
} else { } else {
Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &StreamView::undisplay_diskstream)); Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &StreamView::undisplay_diskstream));
} }

View file

@ -111,13 +111,13 @@ protected:
virtual void remove_region_view (ARDOUR::Region* ); virtual void remove_region_view (ARDOUR::Region* );
void remove_rec_region (ARDOUR::Region*); void remove_rec_region (ARDOUR::Region*);
void display_diskstream (ARDOUR::Diskstream* ); void display_diskstream (boost::shared_ptr<ARDOUR::Diskstream>);
virtual void undisplay_diskstream (); virtual void undisplay_diskstream ();
virtual void redisplay_diskstream () = 0; virtual void redisplay_diskstream () = 0;
void diskstream_changed (); void diskstream_changed ();
void playlist_state_changed (ARDOUR::Change); void playlist_state_changed (ARDOUR::Change);
virtual void playlist_changed (ARDOUR::Diskstream* ); virtual void playlist_changed (boost::shared_ptr<ARDOUR::Diskstream>);
virtual void playlist_modified (); virtual void playlist_modified ();
virtual void color_handler (ColorID, uint32_t) = 0; virtual void color_handler (ColorID, uint32_t) = 0;

View file

@ -59,12 +59,10 @@ class AudioDiskstream : public Diskstream
public: public:
AudioDiskstream (Session &, const string& name, Diskstream::Flag f = Recordable); AudioDiskstream (Session &, const string& name, Diskstream::Flag f = Recordable);
AudioDiskstream (Session &, const XMLNode&); AudioDiskstream (Session &, const XMLNode&);
~AudioDiskstream();
const PBD::ID& id() const { return _id; } const PBD::ID& id() const { return _id; }
// FIXME
AudioDiskstream& ref() { _refcnt++; return *this; }
float playback_buffer_load() const; float playback_buffer_load() const;
float capture_buffer_load() const; float capture_buffer_load() const;
@ -176,9 +174,6 @@ class AudioDiskstream : public Diskstream
private: private:
/* use unref() to destroy a diskstream */
~AudioDiskstream();
struct ChannelInfo { struct ChannelInfo {
Sample *playback_wrap_buffer; Sample *playback_wrap_buffer;

View file

@ -46,7 +46,7 @@ class AudioTrack : public Track
int silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, int silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame,
jack_nframes_t offset, bool can_record, bool rec_monitors_input); jack_nframes_t offset, bool can_record, bool rec_monitors_input);
AudioDiskstream& audio_diskstream() const; boost::shared_ptr<AudioDiskstream> audio_diskstream() const;
int use_diskstream (string name); int use_diskstream (string name);
int use_diskstream (const PBD::ID& id); int use_diskstream (const PBD::ID& id);
@ -71,7 +71,7 @@ class AudioTrack : public Track
uint32_t n_process_buffers (); uint32_t n_process_buffers ();
private: private:
int set_diskstream (AudioDiskstream&, void *); int set_diskstream (boost::shared_ptr<AudioDiskstream>, void *);
int deprecated_use_diskstream_connections (); int deprecated_use_diskstream_connections ();
void set_state_part_two (); void set_state_part_two ();
void set_state_part_three (); void set_state_part_three ();

View file

@ -31,6 +31,8 @@
#include <glibmm/thread.h> #include <glibmm/thread.h>
#include <pbd/rcu.h>
#include <ardour/ardour.h> #include <ardour/ardour.h>
#include <jack/jack.h> #include <jack/jack.h>
#include <jack/transport.h> #include <jack/transport.h>
@ -189,7 +191,6 @@ class AudioEngine : public sigc::trackable
ARDOUR::Session *session; ARDOUR::Session *session;
jack_client_t *_jack; jack_client_t *_jack;
std::string jack_client_name; std::string jack_client_name;
Glib::Mutex port_lock;
Glib::Mutex _process_lock; Glib::Mutex _process_lock;
Glib::Mutex session_remove_lock; Glib::Mutex session_remove_lock;
Glib::Cond session_removed; Glib::Cond session_removed;
@ -208,7 +209,7 @@ class AudioEngine : public sigc::trackable
int _usecs_per_cycle; int _usecs_per_cycle;
typedef std::set<Port*> Ports; typedef std::set<Port*> Ports;
Ports ports; SerializedRCUManager<Ports> ports;
int process_callback (jack_nframes_t nframes); int process_callback (jack_nframes_t nframes);
void remove_all_ports (); void remove_all_ports ();

View file

@ -34,6 +34,7 @@
#include <pbd/fastlog.h> #include <pbd/fastlog.h>
#include <pbd/ringbufferNPT.h> #include <pbd/ringbufferNPT.h>
#include <pbd/stateful.h> #include <pbd/stateful.h>
#include <pbd/destructible.h>
#include <ardour/ardour.h> #include <ardour/ardour.h>
#include <ardour/configuration.h> #include <ardour/configuration.h>
@ -43,7 +44,6 @@
#include <ardour/port.h> #include <ardour/port.h>
#include <ardour/utils.h> #include <ardour/utils.h>
struct tm; struct tm;
namespace ARDOUR { namespace ARDOUR {
@ -54,7 +54,7 @@ class Session;
class Playlist; class Playlist;
class IO; class IO;
class Diskstream : public Stateful, public sigc::trackable class Diskstream : public Stateful, public sigc::trackable, public PBD::Destructible
{ {
public: public:
enum Flag { enum Flag {
@ -63,16 +63,16 @@ class Diskstream : public Stateful, public sigc::trackable
Destructive = 0x4 Destructive = 0x4
}; };
Diskstream (Session &, const string& name, Flag f = Recordable);
Diskstream (Session &, const XMLNode&);
virtual ~Diskstream();
string name () const { return _name; } string name () const { return _name; }
virtual int set_name (string str); virtual int set_name (string str);
ARDOUR::IO* io() const { return _io; } ARDOUR::IO* io() const { return _io; }
void set_io (ARDOUR::IO& io); void set_io (ARDOUR::IO& io);
virtual Diskstream& ref() { _refcnt++; return *this; }
void unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; }
uint32_t refcnt() const { return _refcnt; }
virtual float playback_buffer_load() const = 0; virtual float playback_buffer_load() const = 0;
virtual float capture_buffer_load() const = 0; virtual float capture_buffer_load() const = 0;
@ -148,15 +148,11 @@ class Diskstream : public Stateful, public sigc::trackable
static sigc::signal<void> DiskOverrun; static sigc::signal<void> DiskOverrun;
static sigc::signal<void> DiskUnderrun; static sigc::signal<void> DiskUnderrun;
static sigc::signal<void,Diskstream*> DiskstreamCreated; // XXX use a ref with sigc2
static sigc::signal<void,list<Source*>*> DeleteSources; static sigc::signal<void,list<Source*>*> DeleteSources;
protected: protected:
friend class Session; friend class Session;
Diskstream (Session &, const string& name, Flag f = Recordable);
Diskstream (Session &, const XMLNode&);
/* the Session is the only point of access for these because they require /* the Session is the only point of access for these because they require
* that the Session is "inactive" while they are called. * that the Session is "inactive" while they are called.
*/ */
@ -187,9 +183,6 @@ class Diskstream : public Stateful, public sigc::trackable
//private: //private:
/** Use unref() to destroy a diskstream */
virtual ~Diskstream();
enum TransitionType { enum TransitionType {
CaptureStart = 0, CaptureStart = 0,
CaptureEnd CaptureEnd
@ -304,8 +297,6 @@ class Diskstream : public Stateful, public sigc::trackable
jack_nframes_t scrub_buffer_size; jack_nframes_t scrub_buffer_size;
jack_nframes_t scrub_offset; jack_nframes_t scrub_offset;
uint32_t _refcnt;
sigc::connection ports_created_c; sigc::connection ports_created_c;
sigc::connection plmod_connection; sigc::connection plmod_connection;
sigc::connection plstate_connection; sigc::connection plstate_connection;

View file

@ -35,6 +35,7 @@
#include <pbd/undo.h> #include <pbd/undo.h>
#include <pbd/stateful.h> #include <pbd/stateful.h>
#include <pbd/controllable.h> #include <pbd/controllable.h>
#include <pbd/destructible.h>
#include <ardour/ardour.h> #include <ardour/ardour.h>
#include <ardour/io.h> #include <ardour/io.h>
@ -55,7 +56,7 @@ enum mute_type {
MAIN_OUTS = 0x8 MAIN_OUTS = 0x8
}; };
class Route : public IO class Route : public IO, public PBD::Destructible
{ {
protected: protected:
@ -192,8 +193,6 @@ class Route : public IO
sigc::signal<void> active_changed; sigc::signal<void> active_changed;
sigc::signal<void,void*> meter_change; sigc::signal<void,void*> meter_change;
sigc::signal<void> GoingAway;
/* gui's call this for their own purposes. */ /* gui's call this for their own purposes. */
sigc::signal<void,std::string,void*> gui_changed; sigc::signal<void,std::string,void*> gui_changed;

View file

@ -270,8 +270,9 @@ class Session : public sigc::trackable, public Stateful
vector<Sample*>& get_silent_buffers (uint32_t howmany); vector<Sample*>& get_silent_buffers (uint32_t howmany);
vector<Sample*>& get_send_buffers () { return _send_buffers; } vector<Sample*>& get_send_buffers () { return _send_buffers; }
Diskstream* diskstream_by_id (const PBD::ID& id); void add_diskstream (boost::shared_ptr<Diskstream>);
Diskstream* diskstream_by_name (string name); boost::shared_ptr<Diskstream> diskstream_by_id (const PBD::ID& id);
boost::shared_ptr<Diskstream> diskstream_by_name (string name);
bool have_captured() const { return _have_captured; } bool have_captured() const { return _have_captured; }
@ -281,9 +282,8 @@ class Session : public sigc::trackable, public Stateful
uint32_t get_next_diskstream_id() const { return n_diskstreams(); } uint32_t get_next_diskstream_id() const { return n_diskstreams(); }
uint32_t n_diskstreams() const; uint32_t n_diskstreams() const;
typedef list<Diskstream *> DiskstreamList; typedef std::list<boost::shared_ptr<Diskstream> > DiskstreamList;
typedef std::list<boost::shared_ptr<Route> > RouteList;
typedef std::list<boost::shared_ptr<Route> > RouteList;
boost::shared_ptr<RouteList> get_routes() const { boost::shared_ptr<RouteList> get_routes() const {
return routes.reader (); return routes.reader ();
@ -346,7 +346,6 @@ class Session : public sigc::trackable, public Stateful
sigc::signal<void> HaltOnXrun; sigc::signal<void> HaltOnXrun;
sigc::signal<void,boost::shared_ptr<Route> > RouteAdded; sigc::signal<void,boost::shared_ptr<Route> > RouteAdded;
sigc::signal<void,Diskstream*> DiskstreamAdded; // FIXME: make a shared_ptr
void request_roll (); void request_roll ();
void request_bounded_roll (jack_nframes_t start, jack_nframes_t end); void request_bounded_roll (jack_nframes_t start, jack_nframes_t end);
@ -1509,10 +1508,9 @@ class Session : public sigc::trackable, public Stateful
/* disk-streams */ /* disk-streams */
DiskstreamList diskstreams; SerializedRCUManager<DiskstreamList> diskstreams;
mutable Glib::RWLock diskstream_lock;
uint32_t dstream_buffer_size; uint32_t dstream_buffer_size;
void add_diskstream (Diskstream*);
int load_diskstreams (const XMLNode&); int load_diskstreams (const XMLNode&);
/* routes stuff */ /* routes stuff */
@ -1580,7 +1578,7 @@ class Session : public sigc::trackable, public Stateful
Playlist *XMLPlaylistFactory (const XMLNode&); Playlist *XMLPlaylistFactory (const XMLNode&);
void playlist_length_changed (Playlist *); void playlist_length_changed (Playlist *);
void diskstream_playlist_changed (Diskstream *); void diskstream_playlist_changed (boost::shared_ptr<Diskstream>);
/* NAMED SELECTIONS */ /* NAMED SELECTIONS */

View file

@ -19,6 +19,8 @@
#ifndef __ardour_track_h__ #ifndef __ardour_track_h__
#define __ardour_track_h__ #define __ardour_track_h__
#include <boost/shared_ptr.hpp>
#include <ardour/route.h> #include <ardour/route.h>
namespace ARDOUR { namespace ARDOUR {
@ -50,7 +52,7 @@ class Track : public Route
virtual bool can_record(); virtual bool can_record();
Diskstream& diskstream() const { return *_diskstream; } boost::shared_ptr<Diskstream> diskstream() const { return _diskstream; }
virtual int use_diskstream (string name) = 0; virtual int use_diskstream (string name) = 0;
virtual int use_diskstream (const PBD::ID& id) = 0; virtual int use_diskstream (const PBD::ID& id) = 0;
@ -100,7 +102,7 @@ class Track : public Route
virtual uint32_t n_process_buffers () = 0; virtual uint32_t n_process_buffers () = 0;
Diskstream *_diskstream; boost::shared_ptr<Diskstream> _diskstream;
MeterPoint _saved_meter_point; MeterPoint _saved_meter_point;
TrackMode _mode; TrackMode _mode;

View file

@ -71,8 +71,6 @@ AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream:
use_new_playlist (); use_new_playlist ();
in_set_state = false; in_set_state = false;
DiskstreamCreated (this); /* EMIT SIGNAL */
} }
AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node) AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node)
@ -92,8 +90,6 @@ AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node)
if (destructive()) { if (destructive()) {
use_destructive_playlist (); use_destructive_playlist ();
} }
DiskstreamCreated (this); /* EMIT SIGNAL */
} }
void void

View file

@ -55,9 +55,10 @@ AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode
dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Destructive); dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Destructive);
} }
AudioDiskstream* ds = new AudioDiskstream (_session, name, dflags); boost::shared_ptr<AudioDiskstream> ds (new AudioDiskstream (_session, name, dflags));
_session.add_diskstream (ds);
set_diskstream (*ds, this); set_diskstream (boost::dynamic_pointer_cast<AudioDiskstream> (ds), this);
} }
AudioTrack::AudioTrack (Session& sess, const XMLNode& node) AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
@ -73,18 +74,18 @@ AudioTrack::~AudioTrack ()
int int
AudioTrack::deprecated_use_diskstream_connections () AudioTrack::deprecated_use_diskstream_connections ()
{ {
AudioDiskstream& diskstream = audio_diskstream(); boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
if (diskstream.deprecated_io_node == 0) { if (diskstream->deprecated_io_node == 0) {
return 0; return 0;
} }
const XMLProperty* prop; const XMLProperty* prop;
XMLNode& node (*diskstream.deprecated_io_node); XMLNode& node (*diskstream->deprecated_io_node);
/* don't do this more than once. */ /* don't do this more than once. */
diskstream.deprecated_io_node = 0; diskstream->deprecated_io_node = 0;
set_input_minimum (-1); set_input_minimum (-1);
set_input_maximum (-1); set_input_maximum (-1);
@ -125,17 +126,13 @@ AudioTrack::deprecated_use_diskstream_connections ()
} }
int int
AudioTrack::set_diskstream (AudioDiskstream& ds, void *src) AudioTrack::set_diskstream (boost::shared_ptr<AudioDiskstream> ds, void *src)
{ {
if (_diskstream) { _diskstream = ds;
_diskstream->unref();
}
_diskstream = &ds.ref();
_diskstream->set_io (*this); _diskstream->set_io (*this);
_diskstream->set_destructive (_mode == Destructive); _diskstream->set_destructive (_mode == Destructive);
if (audio_diskstream().deprecated_io_node) { if (audio_diskstream()->deprecated_io_node) {
if (!connecting_legal) { if (!connecting_legal) {
ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections)); ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
@ -158,33 +155,33 @@ AudioTrack::set_diskstream (AudioDiskstream& ds, void *src)
int int
AudioTrack::use_diskstream (string name) AudioTrack::use_diskstream (string name)
{ {
AudioDiskstream *dstream; boost::shared_ptr<AudioDiskstream> dstream;
if ((dstream = dynamic_cast<AudioDiskstream*>(_session.diskstream_by_name (name))) == 0) { if ((dstream = boost::dynamic_pointer_cast<AudioDiskstream>(_session.diskstream_by_name (name))) == 0) {
error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), name) << endmsg; error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), name) << endmsg;
return -1; return -1;
} }
return set_diskstream (*dstream, this); return set_diskstream (dstream, this);
} }
int int
AudioTrack::use_diskstream (const PBD::ID& id) AudioTrack::use_diskstream (const PBD::ID& id)
{ {
AudioDiskstream *dstream; boost::shared_ptr<AudioDiskstream> dstream;
if ((dstream = dynamic_cast<AudioDiskstream*>(_session.diskstream_by_id (id))) == 0) { if ((dstream = boost::dynamic_pointer_cast<AudioDiskstream> (_session.diskstream_by_id (id))) == 0) {
error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), id) << endmsg; error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), id) << endmsg;
return -1; return -1;
} }
return set_diskstream (*dstream, this); return set_diskstream (dstream, this);
} }
AudioDiskstream& boost::shared_ptr<AudioDiskstream>
AudioTrack::audio_diskstream() const AudioTrack::audio_diskstream() const
{ {
return *dynamic_cast<AudioDiskstream*>(_diskstream); return boost::dynamic_pointer_cast<AudioDiskstream>(_diskstream);
} }
int int
@ -434,7 +431,7 @@ AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nf
return 0; return 0;
} }
audio_diskstream().check_record_status (start_frame, nframes, can_record); audio_diskstream()->check_record_status (start_frame, nframes, can_record);
bool send_silence; bool send_silence;
@ -501,7 +498,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
Sample* b; Sample* b;
Sample* tmpb; Sample* tmpb;
jack_nframes_t transport_frame; jack_nframes_t transport_frame;
AudioDiskstream& diskstream = audio_diskstream(); boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
{ {
Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK); Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
@ -528,13 +525,13 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
playback distance to zero, thus causing diskstream::commit playback distance to zero, thus causing diskstream::commit
to do nothing. to do nothing.
*/ */
return diskstream.process (transport_frame, 0, 0, can_record, rec_monitors_input); return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
} }
_silent = false; _silent = false;
apply_gain_automation = false; apply_gain_automation = false;
if ((dret = diskstream.process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) { if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
silence (nframes, offset); silence (nframes, offset);
@ -547,7 +544,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
just_meter_input (start_frame, end_frame, nframes, offset); just_meter_input (start_frame, end_frame, nframes, offset);
} }
if (diskstream.record_enabled() && !can_record && !_session.get_auto_input()) { if (diskstream->record_enabled() && !can_record && !_session.get_auto_input()) {
/* not actually recording, but we want to hear the input material anyway, /* not actually recording, but we want to hear the input material anyway,
at least potentially (depending on monitoring options) at least potentially (depending on monitoring options)
@ -555,7 +552,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
passthru (start_frame, end_frame, nframes, offset, 0, true); passthru (start_frame, end_frame, nframes, offset, 0, true);
} else if ((b = diskstream.playback_buffer(0)) != 0) { } else if ((b = diskstream->playback_buffer(0)) != 0) {
/* /*
XXX is it true that the earlier test on n_outputs() XXX is it true that the earlier test on n_outputs()
@ -577,8 +574,8 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
for (i = 0, n = 1; i < limit; ++i, ++n) { for (i = 0, n = 1; i < limit; ++i, ++n) {
memcpy (bufs[i], b, sizeof (Sample) * nframes); memcpy (bufs[i], b, sizeof (Sample) * nframes);
if (n < diskstream.n_channels()) { if (n < diskstream->n_channels()) {
tmpb = diskstream.playback_buffer(n); tmpb = diskstream->playback_buffer(n);
if (tmpb!=0) { if (tmpb!=0) {
b = tmpb; b = tmpb;
} }
@ -587,7 +584,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
/* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */ /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
if (!diskstream.record_enabled() && _session.transport_rolling()) { if (!diskstream->record_enabled() && _session.transport_rolling()) {
Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK); Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK);
if (am.locked() && gain_automation_playback()) { if (am.locked() && gain_automation_playback()) {
@ -623,7 +620,7 @@ AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jac
silence (nframes, offset); silence (nframes, offset);
return audio_diskstream().process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input); return audio_diskstream()->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
} }
int int
@ -637,12 +634,12 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes
gain_t this_gain = _gain; gain_t this_gain = _gain;
vector<Sample*>::iterator bi; vector<Sample*>::iterator bi;
Sample * b; Sample * b;
AudioDiskstream& diskstream = audio_diskstream(); boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
Glib::RWLock::ReaderLock rlock (redirect_lock); Glib::RWLock::ReaderLock rlock (redirect_lock);
// FIXME // FIXME
AudioPlaylist* const apl = dynamic_cast<AudioPlaylist*>(diskstream.playlist()); AudioPlaylist* const apl = dynamic_cast<AudioPlaylist*>(diskstream->playlist());
assert(apl); assert(apl);
if (apl->read (buffers[0], mix_buffer, gain_buffer, start, nframes) != nframes) { if (apl->read (buffers[0], mix_buffer, gain_buffer, start, nframes) != nframes) {
@ -654,7 +651,7 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes
b = buffers[0]; b = buffers[0];
++bi; ++bi;
for (; bi != buffers.end(); ++bi, ++n) { for (; bi != buffers.end(); ++bi, ++n) {
if (n < diskstream.n_channels()) { if (n < diskstream->n_channels()) {
if (apl->read ((*bi), mix_buffer, gain_buffer, start, nframes, n) != nframes) { if (apl->read ((*bi), mix_buffer, gain_buffer, start, nframes, n) != nframes) {
return -1; return -1;
} }
@ -751,9 +748,9 @@ AudioTrack::freeze (InterThreadInfo& itt)
string dir; string dir;
AudioRegion* region; AudioRegion* region;
string region_name; string region_name;
AudioDiskstream& diskstream = audio_diskstream(); boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
if ((_freeze_record.playlist = dynamic_cast<AudioPlaylist*>(diskstream.playlist())) == 0) { if ((_freeze_record.playlist = dynamic_cast<AudioPlaylist*>(diskstream->playlist())) == 0) {
return; return;
} }
@ -821,13 +818,13 @@ AudioTrack::freeze (InterThreadInfo& itt)
(AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags), (AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags),
false); false);
new_playlist->set_orig_diskstream_id (diskstream.id()); new_playlist->set_orig_diskstream_id (diskstream->id());
new_playlist->add_region (*region, 0); new_playlist->add_region (*region, 0);
new_playlist->set_frozen (true); new_playlist->set_frozen (true);
region->set_locked (true); region->set_locked (true);
diskstream.use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist)); diskstream->use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist));
diskstream.set_record_enabled (false); diskstream->set_record_enabled (false);
_freeze_record.state = Frozen; _freeze_record.state = Frozen;
FreezeChange(); /* EMIT SIGNAL */ FreezeChange(); /* EMIT SIGNAL */
@ -837,7 +834,7 @@ void
AudioTrack::unfreeze () AudioTrack::unfreeze ()
{ {
if (_freeze_record.playlist) { if (_freeze_record.playlist) {
audio_diskstream().use_playlist (_freeze_record.playlist); audio_diskstream()->use_playlist (_freeze_record.playlist);
if (_freeze_record.have_mementos) { if (_freeze_record.have_mementos) {

View file

@ -47,6 +47,7 @@ jack_nframes_t Port::_short_over_length = 2;
jack_nframes_t Port::_long_over_length = 10; jack_nframes_t Port::_long_over_length = 10;
AudioEngine::AudioEngine (string client_name) AudioEngine::AudioEngine (string client_name)
: ports (new Ports)
{ {
session = 0; session = 0;
session_remove_pending = false; session_remove_pending = false;
@ -270,7 +271,10 @@ AudioEngine::process_callback (jack_nframes_t nframes)
} }
if (last_monitor_check + monitor_check_interval < next_processed_frames) { if (last_monitor_check + monitor_check_interval < next_processed_frames) {
for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
boost::shared_ptr<Ports> p = ports.reader();
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
Port *port = (*i); Port *port = (*i);
bool x; bool x;
@ -329,7 +333,9 @@ AudioEngine::jack_bufsize_callback (jack_nframes_t nframes)
_usecs_per_cycle = (int) floor ((((double) nframes / frame_rate())) * 1000000.0); _usecs_per_cycle = (int) floor ((((double) nframes / frame_rate())) * 1000000.0);
last_monitor_check = 0; last_monitor_check = 0;
for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) { boost::shared_ptr<Ports> p = ports.reader();
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
(*i)->reset(); (*i)->reset();
} }
@ -400,15 +406,19 @@ AudioEngine::register_input_port (DataType type, const string& portname)
} }
} }
jack_port_t *p = jack_port_register (_jack, portname.c_str(), jack_port_t *p = jack_port_register (_jack, portname.c_str(), type.to_jack_type(), JackPortIsInput, 0);
type.to_jack_type(), JackPortIsInput, 0);
if (p) { if (p) {
Port *newport; Port *newport;
if ((newport = new Port (p)) != 0) { if ((newport = new Port (p)) != 0) {
ports.insert (ports.begin(), newport); RCUWriter<Ports> writer (ports);
boost::shared_ptr<Ports> ps = writer.get_copy ();
ps->insert (ps->begin(), newport);
/* writer goes out of scope, forces update */
} }
return newport; return newport;
} else { } else {
@ -436,8 +446,19 @@ AudioEngine::register_output_port (DataType type, const string& portname)
if ((p = jack_port_register (_jack, portname.c_str(), if ((p = jack_port_register (_jack, portname.c_str(),
type.to_jack_type(), JackPortIsOutput, 0)) != 0) { type.to_jack_type(), JackPortIsOutput, 0)) != 0) {
Port *newport = new Port (p);
ports.insert (ports.begin(), newport); Port *newport = 0;
{
RCUWriter<Ports> writer (ports);
boost::shared_ptr<Ports> ps = writer.get_copy ();
newport = new Port (p);
ps->insert (ps->begin(), newport);
/* writer goes out of scope, forces update */
}
return newport; return newport;
} else { } else {
@ -466,11 +487,19 @@ AudioEngine::unregister_port (Port *port)
if (ret == 0) { if (ret == 0) {
for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) { {
if ((*i) == port) {
ports.erase (i); RCUWriter<Ports> writer (ports);
break; boost::shared_ptr<Ports> ps = writer.get_copy ();
for (Ports::iterator i = ps->begin(); i != ps->end(); ++i) {
if ((*i) == port) {
ps->erase (i);
break;
}
} }
/* writer goes out of scope, forces update */
} }
remove_connections_for (port); remove_connections_for (port);
@ -613,7 +642,9 @@ AudioEngine::get_port_by_name (const string& portname, bool keep)
/* check to see if we have a Port for this name already */ /* check to see if we have a Port for this name already */
for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) { boost::shared_ptr<Ports> pr = ports.reader();
for (Ports::iterator i = pr->begin(); i != pr->end(); ++i) {
if (portname == (*i)->name()) { if (portname == (*i)->name()) {
return (*i); return (*i);
} }
@ -623,11 +654,20 @@ AudioEngine::get_port_by_name (const string& portname, bool keep)
if ((p = jack_port_by_name (_jack, portname.c_str())) != 0) { if ((p = jack_port_by_name (_jack, portname.c_str())) != 0) {
Port *newport = new Port (p); Port *newport = new Port (p);
if (keep && newport->is_mine (_jack)) {
ports.insert (newport); {
if (keep && newport->is_mine (_jack)) {
RCUWriter<Ports> writer (ports);
boost::shared_ptr<Ports> ps = writer.get_copy ();
ps->insert (newport);
/* writer goes out of scope, forces update */
}
} }
return newport; return newport;
} else { } else {
return 0; return 0;
} }
} }
@ -827,12 +867,19 @@ AudioEngine::remove_all_ports ()
/* process lock MUST be held */ /* process lock MUST be held */
if (_jack) { if (_jack) {
for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) { boost::shared_ptr<Ports> p = ports.reader();
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
jack_port_unregister (_jack, (*i)->_port); jack_port_unregister (_jack, (*i)->_port);
} }
} }
ports.clear (); {
RCUWriter<Ports> writer (ports);
boost::shared_ptr<Ports> ps = writer.get_copy ();
ps->clear ();
}
port_connections.clear (); port_connections.clear ();
} }
@ -932,7 +979,7 @@ AudioEngine::reconnect_to_jack ()
if (_jack) { if (_jack) {
disconnect_from_jack (); disconnect_from_jack ();
/* XXX give jackd a chance */ /* XXX give jackd a chance */
Glib::usleep (250000); Glib::usleep (250000);
} }
if (connect_to_jack (jack_client_name)) { if (connect_to_jack (jack_client_name)) {
@ -942,7 +989,9 @@ AudioEngine::reconnect_to_jack ()
Ports::iterator i; Ports::iterator i;
for (i = ports.begin(); i != ports.end(); ++i) { boost::shared_ptr<Ports> p = ports.reader ();
for (i = p->begin(); i != p->end(); ++i) {
/* XXX hack hack hack */ /* XXX hack hack hack */
@ -964,8 +1013,9 @@ AudioEngine::reconnect_to_jack ()
} }
} }
if (i != ports.end()) { if (i != p->end()) {
for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) { /* failed */
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
jack_port_unregister (_jack, (*i)->_port); jack_port_unregister (_jack, (*i)->_port);
} }
return -1; return -1;

View file

@ -49,7 +49,7 @@ Auditioner::Auditioner (Session& s)
} }
if (right.length()) { if (right.length()) {
audio_diskstream().add_channel(); audio_diskstream()->add_channel();
add_output_port (right, this, DataType::AUDIO); add_output_port (right, this, DataType::AUDIO);
} }
@ -117,11 +117,11 @@ Auditioner::audition_region (AudioRegion& region)
_diskstream->playlist()->add_region (*the_region, 0, 1, false); _diskstream->playlist()->add_region (*the_region, 0, 1, false);
while (_diskstream->n_channels() < the_region->n_channels()) { while (_diskstream->n_channels() < the_region->n_channels()) {
audio_diskstream().add_channel (); audio_diskstream()->add_channel ();
} }
while (_diskstream->n_channels() > the_region->n_channels()) { while (_diskstream->n_channels() > the_region->n_channels()) {
audio_diskstream().remove_channel (); audio_diskstream()->remove_channel ();
} }
/* force a panner reset now that we have all channels */ /* force a panner reset now that we have all channels */

View file

@ -63,7 +63,6 @@ using namespace PBD;
*/ */
jack_nframes_t Diskstream::disk_io_chunk_frames = 1024 * 256; jack_nframes_t Diskstream::disk_io_chunk_frames = 1024 * 256;
sigc::signal<void,Diskstream*> Diskstream::DiskstreamCreated;
sigc::signal<void,list<Source*>*> Diskstream::DeleteSources; sigc::signal<void,list<Source*>*> Diskstream::DeleteSources;
sigc::signal<void> Diskstream::DiskOverrun; sigc::signal<void> Diskstream::DiskOverrun;
sigc::signal<void> Diskstream::DiskUnderrun; sigc::signal<void> Diskstream::DiskUnderrun;
@ -86,7 +85,6 @@ Diskstream::Diskstream (Session& sess, const XMLNode& node)
void void
Diskstream::init (Flag f) Diskstream::init (Flag f)
{ {
_refcnt = 0;
_flags = f; _flags = f;
_io = 0; _io = 0;
_alignment_style = ExistingMaterial; _alignment_style = ExistingMaterial;

View file

@ -111,7 +111,8 @@ Route::init ()
Route::~Route () Route::~Route ()
{ {
GoingAway (); /* EMIT SIGNAL */ cerr << "deleting route " << _name << endl;
clear_redirects (this); clear_redirects (this);
if (_control_outs) { if (_control_outs) {

View file

@ -256,6 +256,7 @@ Session::Session (AudioEngine &eng,
_midi_port (default_midi_port), _midi_port (default_midi_port),
pending_events (2048), pending_events (2048),
midi_requests (128), // the size of this should match the midi request pool size midi_requests (128), // the size of this should match the midi request pool size
diskstreams (new DiskstreamList),
routes (new RouteList), routes (new RouteList),
auditioner ((Auditioner*) 0), auditioner ((Auditioner*) 0),
_click_io ((IO*) 0), _click_io ((IO*) 0),
@ -306,6 +307,7 @@ Session::Session (AudioEngine &eng,
_midi_port (default_midi_port), _midi_port (default_midi_port),
pending_events (2048), pending_events (2048),
midi_requests (16), midi_requests (16),
diskstreams (new DiskstreamList),
routes (new RouteList), routes (new RouteList),
main_outs (0) main_outs (0)
@ -438,19 +440,46 @@ Session::~Session ()
i = tmp; i = tmp;
} }
#ifdef TRACK_DESTRUCTION
cerr << "delete routes\n";
#endif /* TRACK_DESTRUCTION */
{
RCUWriter<RouteList> writer (routes);
boost::shared_ptr<RouteList> r = writer.get_copy ();
for (RouteList::iterator i = r->begin(); i != r->end(); ) {
RouteList::iterator tmp;
tmp = i;
++tmp;
cerr << "BEFORE: use count on route " << (*i)->name() << " = " << (*i).use_count() << endl;
(*i)->drop_references ();
cerr << "AFTER: use count on route " << (*i)->name() << " = " << (*i).use_count() << endl;
i = tmp;
}
r->clear ();
/* writer goes out of scope and updates master */
}
routes.flush ();
#ifdef TRACK_DESTRUCTION #ifdef TRACK_DESTRUCTION
cerr << "delete diskstreams\n"; cerr << "delete diskstreams\n";
#endif /* TRACK_DESTRUCTION */ #endif /* TRACK_DESTRUCTION */
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ) { {
DiskstreamList::iterator tmp; RCUWriter<DiskstreamList> dwriter (diskstreams);
boost::shared_ptr<DiskstreamList> dsl = dwriter.get_copy();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ) {
DiskstreamList::iterator tmp;
tmp = i; tmp = i;
++tmp; ++tmp;
delete *i; (*i)->drop_references ();
i = tmp; i = tmp;
} }
dsl->clear ();
}
diskstreams.flush ();
#ifdef TRACK_DESTRUCTION #ifdef TRACK_DESTRUCTION
cerr << "delete audio sources\n"; cerr << "delete audio sources\n";
@ -859,7 +888,7 @@ Session::playlist_length_changed (Playlist* pl)
} }
void void
Session::diskstream_playlist_changed (Diskstream* dstream) Session::diskstream_playlist_changed (boost::shared_ptr<Diskstream> dstream)
{ {
Playlist *playlist; Playlist *playlist;
@ -934,12 +963,9 @@ Session::set_auto_input (bool yn)
if (Config->get_use_hardware_monitoring() && transport_rolling()) { if (Config->get_use_hardware_monitoring() && transport_rolling()) {
/* auto-input only makes a difference if we're rolling */ /* auto-input only makes a difference if we're rolling */
/* Even though this can called from RT context we are using boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
a non-tentative rwlock here, because the action must occur.
The rarity and short potential lock duration makes this "OK" for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) { if ((*i)->record_enabled ()) {
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl; //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (!auto_input); (*i)->monitor_input (!auto_input);
@ -956,16 +982,19 @@ void
Session::reset_input_monitor_state () Session::reset_input_monitor_state ()
{ {
if (transport_rolling()) { if (transport_rolling()) {
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->record_enabled ()) { if ((*i)->record_enabled ()) {
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl; //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (Config->get_use_hardware_monitoring() && !auto_input); (*i)->monitor_input (Config->get_use_hardware_monitoring() && !auto_input);
} }
} }
} else { } else {
Glib::RWLock::ReaderLock dsm (diskstream_lock); boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->record_enabled ()) { if ((*i)->record_enabled ()) {
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl; //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (Config->get_use_hardware_monitoring()); (*i)->monitor_input (Config->get_use_hardware_monitoring());
@ -1237,13 +1266,8 @@ Session::enable_record ()
send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordStrobe); send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordStrobe);
if (Config->get_use_hardware_monitoring() && auto_input) { if (Config->get_use_hardware_monitoring() && auto_input) {
/* Even though this can be called from RT context we are using boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
a non-tentative rwlock here, because the action must occur. for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
The rarity and short potential lock duration makes this "OK"
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) { if ((*i)->record_enabled ()) {
(*i)->monitor_input (true); (*i)->monitor_input (true);
} }
@ -1272,13 +1296,9 @@ Session::disable_record (bool rt_context, bool force)
send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordExit); send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordExit);
if (Config->get_use_hardware_monitoring() && auto_input) { if (Config->get_use_hardware_monitoring() && auto_input) {
/* Even though this can be called from RT context we are using boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
a non-tentative rwlock here, because the action must occur.
The rarity and short potential lock duration makes this "OK"
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->record_enabled ()) { if ((*i)->record_enabled ()) {
(*i)->monitor_input (false); (*i)->monitor_input (false);
} }
@ -1299,13 +1319,9 @@ Session::step_back_from_record ()
g_atomic_int_set (&_record_status, Enabled); g_atomic_int_set (&_record_status, Enabled);
if (Config->get_use_hardware_monitoring()) { if (Config->get_use_hardware_monitoring()) {
/* Even though this can be called from RT context we are using boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
a non-tentative rwlock here, because the action must occur.
The rarity and short potential lock duration makes this "OK"
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (auto_input && (*i)->record_enabled ()) { if (auto_input && (*i)->record_enabled ()) {
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl; //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (false); (*i)->monitor_input (false);
@ -1428,7 +1444,6 @@ Session::set_block_size (jack_nframes_t nframes)
*/ */
{ {
Glib::RWLock::ReaderLock dsm (diskstream_lock);
vector<Sample*>::iterator i; vector<Sample*>::iterator i;
uint32_t np; uint32_t np;
@ -1475,7 +1490,8 @@ Session::set_block_size (jack_nframes_t nframes)
(*i)->set_block_size (nframes); (*i)->set_block_size (nframes);
} }
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->set_block_size (nframes); (*i)->set_block_size (nframes);
} }
@ -1863,7 +1879,7 @@ Session::new_audio_route (int input_channels, int output_channels)
} }
void void
Session::add_route (shared_ptr<Route> route) Session::add_route (boost::shared_ptr<Route> route)
{ {
{ {
RCUWriter<RouteList> writer (routes); RCUWriter<RouteList> writer (routes);
@ -1892,22 +1908,17 @@ Session::add_route (shared_ptr<Route> route)
} }
void void
Session::add_diskstream (Diskstream* dstream) Session::add_diskstream (boost::shared_ptr<Diskstream> dstream)
{ {
/* need to do this in case we're rolling at the time, to prevent false underruns */ /* need to do this in case we're rolling at the time, to prevent false underruns */
dstream->do_refill_with_alloc(); dstream->do_refill_with_alloc();
{ {
Glib::RWLock::WriterLock lm (diskstream_lock); RCUWriter<DiskstreamList> writer (diskstreams);
diskstreams.push_back (dstream); boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
ds->push_back (dstream);
} }
/* take a reference to the diskstream, preventing it from
ever being deleted until the session itself goes away,
or chooses to remove it for its own purposes.
*/
dstream->ref();
dstream->set_block_size (current_block_size); dstream->set_block_size (current_block_size);
dstream->PlaylistChanged.connect (sigc::bind (mem_fun (*this, &Session::diskstream_playlist_changed), dstream)); dstream->PlaylistChanged.connect (sigc::bind (mem_fun (*this, &Session::diskstream_playlist_changed), dstream));
@ -1918,8 +1929,6 @@ Session::add_diskstream (Diskstream* dstream)
set_dirty(); set_dirty();
save_state (_current_snapshot_name); save_state (_current_snapshot_name);
DiskstreamAdded (dstream); /* EMIT SIGNAL */
} }
void void
@ -1958,20 +1967,19 @@ Session::remove_route (shared_ptr<Route> route)
// FIXME: audio specific // FIXME: audio specific
AudioTrack* at; AudioTrack* at;
AudioDiskstream* ds = 0; boost::shared_ptr<AudioDiskstream> ds;
if ((at = dynamic_cast<AudioTrack*>(route.get())) != 0) { if ((at = dynamic_cast<AudioTrack*>(route.get())) != 0) {
ds = &at->audio_diskstream(); ds = at->audio_diskstream();
} }
if (ds) { if (ds) {
{ {
Glib::RWLock::WriterLock lm (diskstream_lock); RCUWriter<DiskstreamList> dsl (diskstreams);
diskstreams.remove (ds); boost::shared_ptr<DiskstreamList> d = dsl.get_copy();
d->remove (ds);
} }
ds->unref ();
} }
find_current_end (); find_current_end ();
@ -1983,7 +1991,9 @@ Session::remove_route (shared_ptr<Route> route)
save_state (_current_snapshot_name); save_state (_current_snapshot_name);
/* all shared ptrs to route should go out of scope here */ /* try to cause everyone to drop their references */
route->drop_references ();
} }
void void
@ -2271,11 +2281,9 @@ Session::get_maximum_extent () const
jack_nframes_t max = 0; jack_nframes_t max = 0;
jack_nframes_t me; jack_nframes_t me;
/* Don't take the diskstream lock. Caller must have other ways to boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
ensure atomicity.
*/
for (DiskstreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { for (DiskstreamList::const_iterator i = dsl->begin(); i != dsl->end(); ++i) {
Playlist* pl = (*i)->playlist(); Playlist* pl = (*i)->playlist();
if ((me = pl->get_maximum_extent()) > max) { if ((me = pl->get_maximum_extent()) > max) {
max = me; max = me;
@ -2285,32 +2293,32 @@ Session::get_maximum_extent () const
return max; return max;
} }
Diskstream * boost::shared_ptr<Diskstream>
Session::diskstream_by_name (string name) Session::diskstream_by_name (string name)
{ {
Glib::RWLock::ReaderLock lm (diskstream_lock); boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->name() == name) { if ((*i)->name() == name) {
return* i; return *i;
} }
} }
return 0; return boost::shared_ptr<Diskstream>((Diskstream*) 0);
} }
Diskstream * boost::shared_ptr<Diskstream>
Session::diskstream_by_id (const PBD::ID& id) Session::diskstream_by_id (const PBD::ID& id)
{ {
Glib::RWLock::ReaderLock lm (diskstream_lock); boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->id() == id) { if ((*i)->id() == id) {
return *i; return *i;
} }
} }
return 0; return boost::shared_ptr<Diskstream>((Diskstream*) 0);
} }
/* AudioRegion management */ /* AudioRegion management */
@ -2622,9 +2630,9 @@ Session::remove_last_capture ()
{ {
list<Region*> r; list<Region*> r;
Glib::RWLock::ReaderLock lm (diskstream_lock); boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
list<Region*>& l = (*i)->last_capture_regions(); list<Region*>& l = (*i)->last_capture_regions();
if (!l.empty()) { if (!l.empty()) {
@ -3185,10 +3193,11 @@ Session::set_all_mute (bool yn)
uint32_t uint32_t
Session::n_diskstreams () const Session::n_diskstreams () const
{ {
Glib::RWLock::ReaderLock lm (diskstream_lock);
uint32_t n = 0; uint32_t n = 0;
for (DiskstreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::const_iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) { if (!(*i)->hidden()) {
n++; n++;
} }
@ -3207,15 +3216,15 @@ Session::graph_reordered ()
return; return;
} }
Glib::RWLock::ReaderLock lm2 (diskstream_lock);
resort_routes (); resort_routes ();
/* force all diskstreams to update their capture offset values to /* force all diskstreams to update their capture offset values to
reflect any changes in latencies within the graph. reflect any changes in latencies within the graph.
*/ */
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->set_capture_offset (); (*i)->set_capture_offset ();
} }
} }
@ -3494,11 +3503,9 @@ Session::remove_named_selection (NamedSelection* named_selection)
void void
Session::reset_native_file_format () Session::reset_native_file_format ()
{ {
// jlc - WHY take routelock? boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
//RWLockMonitor lm1 (route_lock, true, __LINE__, __FILE__);
Glib::RWLock::ReaderLock lm2 (diskstream_lock);
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->reset_write_sources (false); (*i)->reset_write_sources (false);
} }
} }
@ -3608,7 +3615,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
/* call tree *MUST* hold route_lock */ /* call tree *MUST* hold route_lock */
if ((playlist = track.diskstream().playlist()) == 0) { if ((playlist = track.diskstream()->playlist()) == 0) {
goto out; goto out;
} }
@ -3618,7 +3625,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
goto out; goto out;
} }
nchans = track.audio_diskstream().n_channels(); nchans = track.audio_diskstream()->n_channels();
dir = discover_best_sound_dir (); dir = discover_best_sound_dir ();

View file

@ -248,11 +248,11 @@ Session::butler_thread_work ()
gettimeofday (&begin, 0); gettimeofday (&begin, 0);
Glib::RWLock::ReaderLock dsm (diskstream_lock); boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader ();
for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) { for (i = dsl->begin(); !transport_work_requested() && butler_should_run && i != dsl->end(); ++i) {
Diskstream* const ds = *i; boost::shared_ptr<Diskstream> ds = *i;
switch (ds->do_refill ()) { switch (ds->do_refill ()) {
case 0: case 0:
@ -271,7 +271,7 @@ Session::butler_thread_work ()
} }
if (i != diskstreams.end()) { if (i != dsl->end()) {
/* we didn't get to all the streams */ /* we didn't get to all the streams */
disk_work_outstanding = true; disk_work_outstanding = true;
} }
@ -293,7 +293,7 @@ Session::butler_thread_work ()
compute_io = true; compute_io = true;
gettimeofday (&begin, 0); gettimeofday (&begin, 0);
for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) { for (i = dsl->begin(); !transport_work_requested() && butler_should_run && i != dsl->end(); ++i) {
// cerr << "write behind for " << (*i)->name () << endl; // cerr << "write behind for " << (*i)->name () << endl;
switch ((*i)->do_flush (Session::ButlerContext)) { switch ((*i)->do_flush (Session::ButlerContext)) {
@ -322,7 +322,7 @@ Session::butler_thread_work ()
request_stop (); request_stop ();
} }
if (i != diskstreams.end()) { if (i != dsl->end()) {
/* we didn't get to all the streams */ /* we didn't get to all the streams */
disk_work_outstanding = true; disk_work_outstanding = true;
} }
@ -349,7 +349,7 @@ Session::butler_thread_work ()
Glib::Mutex::Lock lm (butler_request_lock); Glib::Mutex::Lock lm (butler_request_lock);
if (butler_should_run && (disk_work_outstanding || transport_work_requested())) { if (butler_should_run && (disk_work_outstanding || transport_work_requested())) {
// for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { // for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
// cerr << "AFTER " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl; // cerr << "AFTER " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl;
// } // }
@ -388,8 +388,8 @@ Session::overwrite_some_buffers (Diskstream* ds)
} else { } else {
Glib::RWLock::ReaderLock dm (diskstream_lock); boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->set_pending_overwrite (true); (*i)->set_pending_overwrite (true);
} }
} }

View file

@ -495,8 +495,9 @@ Session::prepare_to_export (AudioExportSpecification& spec)
/* get everyone to the right position */ /* get everyone to the right position */
{ {
Glib::RWLock::ReaderLock lm (diskstream_lock); boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)-> seek (spec.start_frame, true)) { if ((*i)-> seek (spec.start_frame, true)) {
error << string_compose (_("%1: cannot seek to %2 for export"), error << string_compose (_("%1: cannot seek to %2 for export"),
(*i)->name(), spec.start_frame) (*i)->name(), spec.start_frame)

View file

@ -66,7 +66,8 @@ Session::process (jack_nframes_t nframes)
void void
Session::prepare_diskstreams () Session::prepare_diskstreams ()
{ {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->prepare (); (*i)->prepare ();
} }
} }
@ -141,7 +142,8 @@ Session::process_routes (jack_nframes_t nframes, jack_nframes_t offset)
call path, so make sure we release any outstanding locks here before we return failure. call path, so make sure we release any outstanding locks here before we return failure.
*/ */
for (DiskstreamList::iterator ids = diskstreams.begin(); ids != diskstreams.end(); ++ids) { boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator ids = dsl->begin(); ids != dsl->end(); ++ids) {
(*ids)->recover (); (*ids)->recover ();
} }
@ -181,7 +183,8 @@ Session::silent_process_routes (jack_nframes_t nframes, jack_nframes_t offset)
call path, so make sure we release any outstanding locks here before we return failure. call path, so make sure we release any outstanding locks here before we return failure.
*/ */
for (DiskstreamList::iterator ids = diskstreams.begin(); ids != diskstreams.end(); ++ids) { boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator ids = dsl->begin(); ids != dsl->end(); ++ids) {
(*ids)->recover (); (*ids)->recover ();
} }
@ -200,7 +203,8 @@ Session::commit_diskstreams (jack_nframes_t nframes, bool &needs_butler)
float pworst = 1.0f; float pworst = 1.0f;
float cworst = 1.0f; float cworst = 1.0f;
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->hidden()) { if ((*i)->hidden()) {
continue; continue;
@ -284,12 +288,10 @@ Session::process_with_events (jack_nframes_t nframes)
end_frame = _transport_frame + nframes; end_frame = _transport_frame + nframes;
{ {
Glib::RWLock::ReaderLock dsm (diskstream_lock, Glib::TRY_LOCK);
Event* this_event; Event* this_event;
Events::iterator the_next_one; Events::iterator the_next_one;
if (!dsm.locked() || (post_transport_work & (PostTransportLocate|PostTransportStop))) { if (post_transport_work & (PostTransportLocate|PostTransportStop)) {
no_roll (nframes, 0); no_roll (nframes, 0);
return; return;
} }
@ -560,9 +562,8 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
if (slave_state == Waiting) { if (slave_state == Waiting) {
// cerr << "waiting at " << slave_transport_frame << endl; // cerr << "waiting at " << slave_transport_frame << endl;
Glib::RWLock::ReaderLock dsm (diskstream_lock, Glib::TRY_LOCK);
if (dsm.locked() && slave_transport_frame >= slave_wait_end) { if (slave_transport_frame >= slave_wait_end) {
// cerr << "\tstart at " << _transport_frame << endl; // cerr << "\tstart at " << _transport_frame << endl;
slave_state = Running; slave_state = Running;
@ -570,7 +571,9 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
bool ok = true; bool ok = true;
jack_nframes_t frame_delta = slave_transport_frame - _transport_frame; jack_nframes_t frame_delta = slave_transport_frame - _transport_frame;
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->can_internal_playback_seek (frame_delta)) { if (!(*i)->can_internal_playback_seek (frame_delta)) {
ok = false; ok = false;
break; break;
@ -578,7 +581,7 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
} }
if (ok) { if (ok) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->internal_playback_seek (frame_delta); (*i)->internal_playback_seek (frame_delta);
} }
_transport_frame += frame_delta; _transport_frame += frame_delta;
@ -682,12 +685,6 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
bool need_butler; bool need_butler;
Glib::RWLock::ReaderLock dsm (diskstream_lock, Glib::TRY_LOCK);
if (!dsm.locked()) {
goto noroll;
}
prepare_diskstreams (); prepare_diskstreams ();
silent_process_routes (nframes, offset); silent_process_routes (nframes, offset);
commit_diskstreams (nframes, need_butler); commit_diskstreams (nframes, need_butler);
@ -733,9 +730,7 @@ Session::process_without_events (jack_nframes_t nframes)
long frames_moved; long frames_moved;
{ {
Glib::RWLock::ReaderLock dsm (diskstream_lock, Glib::TRY_LOCK); if (post_transport_work & (PostTransportLocate|PostTransportStop)) {
if (!dsm.locked() || (post_transport_work & (PostTransportLocate|PostTransportStop))) {
no_roll (nframes, 0); no_roll (nframes, 0);
return; return;
} }

View file

@ -264,7 +264,6 @@ Session::first_stage_init (string fullpath, string snapshot_name)
AudioSource::AudioSourceCreated.connect (mem_fun (*this, &Session::add_audio_source)); AudioSource::AudioSourceCreated.connect (mem_fun (*this, &Session::add_audio_source));
Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist)); Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect)); Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
AudioDiskstream::DiskstreamCreated.connect (mem_fun (*this, &Session::add_diskstream));
NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection)); NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
Curve::CurveCreated.connect (mem_fun (*this, &Session::add_curve)); Curve::CurveCreated.connect (mem_fun (*this, &Session::add_curve));
AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list)); AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list));
@ -626,11 +625,10 @@ Session::load_diskstreams (const XMLNode& node)
for (citer = clist.begin(); citer != clist.end(); ++citer) { for (citer = clist.begin(); citer != clist.end(); ++citer) {
AudioDiskstream* dstream;
try { try {
dstream = new AudioDiskstream (*this, **citer); boost::shared_ptr<AudioDiskstream> dstream (new AudioDiskstream (*this, **citer));
/* added automatically by AudioDiskstreamCreated handler */ add_diskstream (dstream);
} }
catch (failed_constructor& err) { catch (failed_constructor& err) {
@ -1388,8 +1386,8 @@ Session::state(bool full_state)
child = node->add_child ("DiskStreams"); child = node->add_child ("DiskStreams");
{ {
Glib::RWLock::ReaderLock dl (diskstream_lock); boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) { if (!(*i)->hidden()) {
child->add_child_nocopy ((*i)->get_state()); child->add_child_nocopy ((*i)->get_state());
} }

View file

@ -192,8 +192,8 @@ Session::realtime_stop (bool abort)
void void
Session::butler_transport_work () Session::butler_transport_work ()
{ {
Glib::RWLock::ReaderLock dsm (diskstream_lock);
boost::shared_ptr<RouteList> r = routes.reader (); boost::shared_ptr<RouteList> r = routes.reader ();
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
if (post_transport_work & PostTransportCurveRealloc) { if (post_transport_work & PostTransportCurveRealloc) {
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
@ -202,7 +202,7 @@ Session::butler_transport_work ()
} }
if (post_transport_work & PostTransportInputChange) { if (post_transport_work & PostTransportInputChange) {
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->non_realtime_input_change (); (*i)->non_realtime_input_change ();
} }
} }
@ -218,7 +218,7 @@ Session::butler_transport_work ()
cumulative_rf_motion = 0; cumulative_rf_motion = 0;
reset_rf_scale (0); reset_rf_scale (0);
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) { if (!(*i)->hidden()) {
if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) { if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
(*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed())); (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
@ -248,9 +248,9 @@ Session::butler_transport_work ()
void void
Session::non_realtime_set_speed () Session::non_realtime_set_speed ()
{ {
Glib::RWLock::ReaderLock lm (diskstream_lock); boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->non_realtime_set_speed (); (*i)->non_realtime_set_speed ();
} }
} }
@ -258,9 +258,9 @@ Session::non_realtime_set_speed ()
void void
Session::non_realtime_overwrite () Session::non_realtime_overwrite ()
{ {
Glib::RWLock::ReaderLock lm (diskstream_lock); boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->pending_overwrite) { if ((*i)->pending_overwrite) {
(*i)->overwrite_existing_buffers (); (*i)->overwrite_existing_buffers ();
} }
@ -276,7 +276,9 @@ Session::non_realtime_stop (bool abort)
did_record = false; did_record = false;
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->get_captured_frames () != 0) { if ((*i)->get_captured_frames () != 0) {
did_record = true; did_record = true;
break; break;
@ -331,7 +333,7 @@ Session::non_realtime_stop (bool abort)
_have_captured = true; _have_captured = true;
} }
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->transport_stopped (*now, xnow, abort); (*i)->transport_stopped (*now, xnow, abort);
} }
@ -370,7 +372,7 @@ Session::non_realtime_stop (bool abort)
} }
#endif #endif
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) { if (!(*i)->hidden()) {
if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) { if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
(*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed())); (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
@ -497,7 +499,8 @@ Session::set_auto_loop (bool yn)
if (seamless_loop) { if (seamless_loop) {
// set all diskstreams to use internal looping // set all diskstreams to use internal looping
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) { if (!(*i)->hidden()) {
(*i)->set_loop (loc); (*i)->set_loop (loc);
} }
@ -505,7 +508,8 @@ Session::set_auto_loop (bool yn)
} }
else { else {
// set all diskstreams to NOT use internal looping // set all diskstreams to NOT use internal looping
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) { if (!(*i)->hidden()) {
(*i)->set_loop (0); (*i)->set_loop (0);
} }
@ -535,7 +539,8 @@ Session::set_auto_loop (bool yn)
clear_events (Event::AutoLoop); clear_events (Event::AutoLoop);
// set all diskstreams to NOT use internal looping // set all diskstreams to NOT use internal looping
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) { if (!(*i)->hidden()) {
(*i)->set_loop (0); (*i)->set_loop (0);
} }
@ -648,12 +653,10 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b
if (with_roll) { if (with_roll) {
/* switch from input if we're going to roll */ /* switch from input if we're going to roll */
if (Config->get_use_hardware_monitoring()) { if (Config->get_use_hardware_monitoring()) {
/* Even though this is called from RT context we are using
a non-tentative rwlock here, because the action must occur. boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
The rarity and short potential lock duration makes this "OK"
*/ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) { if ((*i)->record_enabled ()) {
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl; //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (!auto_input); (*i)->monitor_input (!auto_input);
@ -663,12 +666,9 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b
} else { } else {
/* otherwise we're going to stop, so do the opposite */ /* otherwise we're going to stop, so do the opposite */
if (Config->get_use_hardware_monitoring()) { if (Config->get_use_hardware_monitoring()) {
/* Even though this is called from RT context we are using boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
a non-tentative rwlock here, because the action must occur.
The rarity and short potential lock duration makes this "OK" for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) { if ((*i)->record_enabled ()) {
//cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl; //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (true); (*i)->monitor_input (true);
@ -707,12 +707,9 @@ Session::set_transport_speed (float speed, bool abort)
if (Config->get_use_hardware_monitoring()) if (Config->get_use_hardware_monitoring())
{ {
/* Even though this is called from RT context we are using boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
a non-tentative rwlock here, because the action must occur.
The rarity and short potential lock duration makes this "OK" for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) { if ((*i)->record_enabled ()) {
//cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl; //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (true); (*i)->monitor_input (true);
@ -733,12 +730,10 @@ Session::set_transport_speed (float speed, bool abort)
} }
if (Config->get_use_hardware_monitoring()) { if (Config->get_use_hardware_monitoring()) {
/* Even though this is called from RT context we are using
a non-tentative rwlock here, because the action must occur. boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
The rarity and short potential lock duration makes this "OK"
*/ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
if (auto_input && (*i)->record_enabled ()) { if (auto_input && (*i)->record_enabled ()) {
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl; //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (false); (*i)->monitor_input (false);
@ -789,7 +784,8 @@ Session::set_transport_speed (float speed, bool abort)
_last_transport_speed = _transport_speed; _last_transport_speed = _transport_speed;
_transport_speed = speed; _transport_speed = speed;
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->realtime_set_speed ((*i)->speed(), true)) { if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed); post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
} }
@ -879,7 +875,8 @@ Session::actually_start_transport ()
transport_sub_state |= PendingDeclickIn; transport_sub_state |= PendingDeclickIn;
_transport_speed = 1.0; _transport_speed = 1.0;
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->realtime_set_speed ((*i)->speed(), true); (*i)->realtime_set_speed ((*i)->speed(), true);
} }
@ -1009,7 +1006,8 @@ Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
_slave_type = src; _slave_type = src;
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) { if (!(*i)->hidden()) {
if ((*i)->realtime_set_speed ((*i)->speed(), true)) { if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
non_rt_required = true; non_rt_required = true;
@ -1200,7 +1198,6 @@ Session::update_latency_compensation (bool with_stop, bool abort)
return; return;
} }
Glib::RWLock::ReaderLock lm2 (diskstream_lock);
_worst_track_latency = 0; _worst_track_latency = 0;
boost::shared_ptr<RouteList> r = routes.reader (); boost::shared_ptr<RouteList> r = routes.reader ();
@ -1238,7 +1235,9 @@ Session::update_latency_compensation (bool with_stop, bool abort)
/* reflect any changes in latencies into capture offsets /* reflect any changes in latencies into capture offsets
*/ */
for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->set_capture_offset (); (*i)->set_capture_offset ();
} }
} }

View file

@ -41,7 +41,6 @@ using namespace PBD;
Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, DataType default_type) Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, DataType default_type)
: Route (sess, name, 1, -1, -1, -1, flag, default_type) : Route (sess, name, 1, -1, -1, -1, flag, default_type)
, _diskstream (0)
, _rec_enable_control (*this) , _rec_enable_control (*this)
{ {
_declickable = true; _declickable = true;
@ -52,7 +51,6 @@ Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, Data
Track::Track (Session& sess, const XMLNode& node, DataType default_type) Track::Track (Session& sess, const XMLNode& node, DataType default_type)
: Route (sess, "to be renamed", 0, 0, -1, -1, Route::Flag(0), default_type) : Route (sess, "to be renamed", 0, 0, -1, -1, Route::Flag(0), default_type)
, _diskstream (0)
, _rec_enable_control (*this) , _rec_enable_control (*this)
{ {
_freeze_record.state = NoFreeze; _freeze_record.state = NoFreeze;
@ -62,9 +60,6 @@ Track::Track (Session& sess, const XMLNode& node, DataType default_type)
Track::~Track () Track::~Track ()
{ {
if (_diskstream) {
_diskstream->unref();
}
} }
void void

View file

@ -6,7 +6,6 @@
#include <list> #include <list>
template<class T> template<class T>
class RCUManager class RCUManager
{ {
@ -43,7 +42,7 @@ public:
} }
virtual boost::shared_ptr<T> write_copy () boost::shared_ptr<T> write_copy ()
{ {
m_lock.lock(); m_lock.lock();
@ -68,7 +67,7 @@ public:
return new_copy; return new_copy;
} }
virtual bool update (boost::shared_ptr<T> new_value) bool update (boost::shared_ptr<T> new_value)
{ {
// we hold the lock at this point effectively blocking // we hold the lock at this point effectively blocking
// other writers. // other writers.
@ -99,6 +98,11 @@ public:
return ret; return ret;
} }
void flush () {
Glib::Mutex::Lock lm (m_lock);
m_dead_wood.clear ();
}
private: private:
Glib::Mutex m_lock; Glib::Mutex m_lock;
boost::shared_ptr<T>* current_write_old; boost::shared_ptr<T>* current_write_old;