From 7d4e03e28e58a9315f163738f35559f57b099d37 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 9 Dec 2010 21:34:31 +0000 Subject: [PATCH] Use a weak_ptr rather than a bald pointer for _midi_source in MidiModel. git-svn-id: svn://localhost/ardour2/branches/3.0@8228 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/midi_model.h | 8 ++-- libs/ardour/ardour/midi_source.h | 3 +- libs/ardour/midi_model.cc | 79 +++++++++++++++++++++++--------- libs/ardour/smf_source.cc | 8 +--- libs/ardour/source_factory.cc | 21 +++++---- 5 files changed, 76 insertions(+), 43 deletions(-) diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h index e959535a36..27ffa4d8a2 100644 --- a/libs/ardour/ardour/midi_model.h +++ b/libs/ardour/ardour/midi_model.h @@ -51,7 +51,7 @@ class MidiModel : public AutomatableSequence { public: typedef Evoral::MusicalTime TimeType; - MidiModel(MidiSource* s); + MidiModel (boost::shared_ptr); NoteMode note_mode() const { return (percussive() ? Percussive : Sustained); } void set_note_mode(NoteMode mode) { set_percussive(mode == Percussive); }; @@ -140,8 +140,8 @@ public: PBD::Signal0 ContentsChanged; - const MidiSource* midi_source() const { return _midi_source; } - void set_midi_source (MidiSource *); + boost::shared_ptr midi_source (); + void set_midi_source (boost::shared_ptr); boost::shared_ptr > find_note (NotePtr); boost::shared_ptr > find_note (gint note_id); @@ -181,7 +181,7 @@ private: PBD::ScopedConnectionList _midi_source_connections; // We cannot use a boost::shared_ptr here to avoid a retain cycle - MidiSource* _midi_source; + boost::weak_ptr _midi_source; InsertMergePolicy _insert_merge_policy; }; diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h index e40ccff291..33a0c3c1fa 100644 --- a/libs/ardour/ardour/midi_source.h +++ b/libs/ardour/ardour/midi_source.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "pbd/stateful.h" #include "pbd/xml++.h" #include "evoral/Sequence.hpp" @@ -38,7 +39,7 @@ class MidiModel; template class MidiRingBuffer; /** Source for MIDI data */ -class MidiSource : virtual public Source +class MidiSource : virtual public Source, public boost::enable_shared_from_this { public: typedef double TimeType; diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc index 5f6b07c67d..8fbfde0ee7 100644 --- a/libs/ardour/midi_model.cc +++ b/libs/ardour/midi_model.cc @@ -38,9 +38,8 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -MidiModel::MidiModel(MidiSource* s) +MidiModel::MidiModel (boost::shared_ptr s) : AutomatableSequence(s->session()) - , _midi_source (0) { set_midi_source (s); } @@ -54,7 +53,10 @@ MidiModel::MidiModel(MidiSource* s) MidiModel::DiffCommand* MidiModel::new_diff_command(const string name) { - DiffCommand* cmd = new DiffCommand(_midi_source->model(), name); + boost::shared_ptr ms = _midi_source.lock (); + assert (ms); + + DiffCommand* cmd = new DiffCommand (ms->model(), name); return cmd; } @@ -696,8 +698,11 @@ MidiModel::write_to (boost::shared_ptr source) const bool old_percussive = percussive(); set_percussive(false); + boost::shared_ptr ms = _midi_source.lock (); + assert (ms); + source->drop_model(); - source->mark_streaming_midi_write_started(note_mode(), _midi_source->timeline_position()); + source->mark_streaming_midi_write_started (note_mode(), ms->timeline_position ()); for (Evoral::Sequence::const_iterator i = begin(0, true); i != end(); ++i) { source->append_event_unlocked_beats(*i); @@ -724,14 +729,17 @@ MidiModel::sync_to_source () const bool old_percussive = percussive(); set_percussive(false); - _midi_source->mark_streaming_midi_write_started(note_mode(), _midi_source->timeline_position()); + boost::shared_ptr ms = _midi_source.lock (); + assert (ms); + + ms->mark_streaming_midi_write_started (note_mode(), ms->timeline_position()); for (Evoral::Sequence::const_iterator i = begin(0, true); i != end(); ++i) { - _midi_source->append_event_unlocked_beats(*i); + ms->append_event_unlocked_beats(*i); } set_percussive (old_percussive); - _midi_source->mark_streaming_write_completed (); + ms->mark_streaming_write_completed (); set_edited (false); @@ -755,8 +763,11 @@ MidiModel::write_section_to (boost::shared_ptr source, Evoral::Music const bool old_percussive = percussive(); set_percussive(false); + boost::shared_ptr ms = _midi_source.lock (); + assert (ms); + source->drop_model(); - source->mark_streaming_midi_write_started(note_mode(), _midi_source->timeline_position()); + source->mark_streaming_midi_write_started (note_mode(), ms->timeline_position()); for (Evoral::Sequence::const_iterator i = begin(0, true); i != end(); ++i) { const Evoral::Event& ev (*i); @@ -869,8 +880,11 @@ MidiModel::find_note (gint note_id) MidiModel::WriteLock MidiModel::edit_lock() { - Glib::Mutex::Lock* source_lock = new Glib::Mutex::Lock(_midi_source->mutex()); - _midi_source->invalidate(); // Release cached iterator's read lock on model + boost::shared_ptr ms = _midi_source.lock (); + assert (ms); + + Glib::Mutex::Lock* source_lock = new Glib::Mutex::Lock (ms->mutex()); + ms->invalidate(); // Release cached iterator's read lock on model return WriteLock(new WriteLockImpl(source_lock, _lock, _control_lock)); } @@ -880,7 +894,10 @@ MidiModel::edit_lock() MidiModel::WriteLock MidiModel::write_lock() { - assert(!_midi_source->mutex().trylock()); + boost::shared_ptr ms = _midi_source.lock (); + assert (ms); + + assert (!ms->mutex().trylock ()); return WriteLock(new WriteLockImpl(NULL, _lock, _control_lock)); } @@ -1081,25 +1098,30 @@ MidiModel::insert_merge_policy () const { /* XXX ultimately this should be a per-track or even per-model policy */ - return _midi_source->session().config.get_insert_merge_policy(); + boost::shared_ptr ms = _midi_source.lock (); + assert (ms); + + return ms->session().config.get_insert_merge_policy (); } void -MidiModel::set_midi_source (MidiSource* s) +MidiModel::set_midi_source (boost::shared_ptr s) { - if (_midi_source) { - _midi_source->invalidate (); + boost::shared_ptr old = _midi_source.lock (); + + if (old) { + old->invalidate (); } _midi_source_connections.drop_connections (); _midi_source = s; - _midi_source->InterpolationChanged.connect_same_thread ( + s->InterpolationChanged.connect_same_thread ( _midi_source_connections, boost::bind (&MidiModel::source_interpolation_changed, this, _1, _2) ); - _midi_source->AutomationStateChanged.connect_same_thread ( + s->AutomationStateChanged.connect_same_thread ( _midi_source_connections, boost::bind (&MidiModel::source_automation_state_changed, this, _1, _2) ); } @@ -1124,7 +1146,10 @@ MidiModel::source_interpolation_changed (Evoral::Parameter p, Evoral::ControlLis void MidiModel::control_list_interpolation_changed (Evoral::Parameter p, Evoral::ControlList::InterpolationStyle s) { - _midi_source->set_interpolation_of (p, s); + boost::shared_ptr ms = _midi_source.lock (); + assert (ms); + + ms->set_interpolation_of (p, s); } void @@ -1138,7 +1163,10 @@ MidiModel::source_automation_state_changed (Evoral::Parameter p, AutoState s) void MidiModel::automation_list_automation_state_changed (Evoral::Parameter p, AutoState s) { - _midi_source->set_automation_state_of (p, s); + boost::shared_ptr ms = _midi_source.lock (); + assert (ms); + + ms->set_automation_state_of (p, s); } boost::shared_ptr @@ -1150,14 +1178,21 @@ MidiModel::control_factory (Evoral::Parameter const & p) automation state from our source. */ - assert (_midi_source); + boost::shared_ptr ms = _midi_source.lock (); + assert (ms); - c->list()->set_interpolation (_midi_source->interpolation_of (p)); + c->list()->set_interpolation (ms->interpolation_of (p)); boost::shared_ptr al = boost::dynamic_pointer_cast (c->list ()); assert (al); - al->set_automation_state (_midi_source->automation_state_of (p)); + al->set_automation_state (ms->automation_state_of (p)); return c; } + +boost::shared_ptr +MidiModel::midi_source () +{ + return _midi_source.lock (); +} diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index 4e939a3762..78c3e55811 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -69,8 +69,6 @@ SMFSource::SMFSource (Session& s, const string& path, Source::Flag flags) if (create(path)) { throw failed_constructor (); } - - load_model(true, true); // FIXME } /** Constructor used for existing internal-to-session files. */ @@ -94,8 +92,6 @@ SMFSource::SMFSource (Session& s, const XMLNode& node, bool must_exist) if (open(_path)) { throw failed_constructor (); } - - load_model(true, true); // FIXME } SMFSource::~SMFSource () @@ -442,8 +438,8 @@ SMFSource::load_model (bool lock, bool force_reload) return; } - if (! _model) { - _model = boost::shared_ptr(new MidiModel(this)); + if (!_model) { + _model = boost::shared_ptr (new MidiModel (shared_from_this ())); } else { _model->clear(); } diff --git a/libs/ardour/source_factory.cc b/libs/ardour/source_factory.cc index f886f952bd..b7c4a8ff56 100644 --- a/libs/ardour/source_factory.cc +++ b/libs/ardour/source_factory.cc @@ -178,12 +178,12 @@ SourceFactory::create (Session& s, const XMLNode& node, bool defer_peaks) } } else if (type == DataType::MIDI) { - Source* src = new SMFSource (s, node); + boost::shared_ptr src (new SMFSource (s, node)); + src->load_model (true, true); // boost_debug_shared_ptr_mark_interesting (src, "Source"); - boost::shared_ptr ret (src); - ret->check_for_analysis_data_on_disk (); - SourceCreated (ret); - return ret; + src->check_for_analysis_data_on_disk (); + SourceCreated (src); + return src; } return boost::shared_ptr(); @@ -240,7 +240,8 @@ SourceFactory::createReadable (DataType type, Session& s, const string& path, } else if (type == DataType::MIDI) { - Source* src = new SMFSource (s, path, SMFSource::Flag(0)); + SMFSource* src = new SMFSource (s, path, SMFSource::Flag(0)); + src->load_model (true, true); // boost_debug_shared_ptr_mark_interesting (src, "Source"); boost::shared_ptr ret (src); @@ -285,16 +286,16 @@ SourceFactory::createWritable (DataType type, Session& s, const std::string& pat } else if (type == DataType::MIDI) { // XXX writable flags should belong to MidiSource too - Source* src = new SMFSource (s, path, SndFileSource::default_writable_flags); + boost::shared_ptr src (new SMFSource (s, path, SndFileSource::default_writable_flags)); + src->load_model (true, true); // boost_debug_shared_ptr_mark_interesting (src, "Source"); - boost::shared_ptr ret (src); // no analysis data - this is a new file if (announce) { - SourceCreated (ret); + SourceCreated (src); } - return ret; + return src; }