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
This commit is contained in:
Carl Hetherington 2010-12-09 21:34:31 +00:00
parent ebf3762fa9
commit 7d4e03e28e
5 changed files with 76 additions and 43 deletions

View file

@ -51,7 +51,7 @@ class MidiModel : public AutomatableSequence<Evoral::MusicalTime> {
public: public:
typedef Evoral::MusicalTime TimeType; typedef Evoral::MusicalTime TimeType;
MidiModel(MidiSource* s); MidiModel (boost::shared_ptr<MidiSource>);
NoteMode note_mode() const { return (percussive() ? Percussive : Sustained); } NoteMode note_mode() const { return (percussive() ? Percussive : Sustained); }
void set_note_mode(NoteMode mode) { set_percussive(mode == Percussive); }; void set_note_mode(NoteMode mode) { set_percussive(mode == Percussive); };
@ -140,8 +140,8 @@ public:
PBD::Signal0<void> ContentsChanged; PBD::Signal0<void> ContentsChanged;
const MidiSource* midi_source() const { return _midi_source; } boost::shared_ptr<const MidiSource> midi_source ();
void set_midi_source (MidiSource *); void set_midi_source (boost::shared_ptr<MidiSource>);
boost::shared_ptr<Evoral::Note<TimeType> > find_note (NotePtr); boost::shared_ptr<Evoral::Note<TimeType> > find_note (NotePtr);
boost::shared_ptr<Evoral::Note<TimeType> > find_note (gint note_id); boost::shared_ptr<Evoral::Note<TimeType> > find_note (gint note_id);
@ -181,7 +181,7 @@ private:
PBD::ScopedConnectionList _midi_source_connections; PBD::ScopedConnectionList _midi_source_connections;
// We cannot use a boost::shared_ptr here to avoid a retain cycle // We cannot use a boost::shared_ptr here to avoid a retain cycle
MidiSource* _midi_source; boost::weak_ptr<MidiSource> _midi_source;
InsertMergePolicy _insert_merge_policy; InsertMergePolicy _insert_merge_policy;
}; };

View file

@ -23,6 +23,7 @@
#include <string> #include <string>
#include <time.h> #include <time.h>
#include <glibmm/thread.h> #include <glibmm/thread.h>
#include <boost/enable_shared_from_this.hpp>
#include "pbd/stateful.h" #include "pbd/stateful.h"
#include "pbd/xml++.h" #include "pbd/xml++.h"
#include "evoral/Sequence.hpp" #include "evoral/Sequence.hpp"
@ -38,7 +39,7 @@ class MidiModel;
template<typename T> class MidiRingBuffer; template<typename T> class MidiRingBuffer;
/** Source for MIDI data */ /** Source for MIDI data */
class MidiSource : virtual public Source class MidiSource : virtual public Source, public boost::enable_shared_from_this<MidiSource>
{ {
public: public:
typedef double TimeType; typedef double TimeType;

View file

@ -38,9 +38,8 @@ using namespace std;
using namespace ARDOUR; using namespace ARDOUR;
using namespace PBD; using namespace PBD;
MidiModel::MidiModel(MidiSource* s) MidiModel::MidiModel (boost::shared_ptr<MidiSource> s)
: AutomatableSequence<TimeType>(s->session()) : AutomatableSequence<TimeType>(s->session())
, _midi_source (0)
{ {
set_midi_source (s); set_midi_source (s);
} }
@ -54,7 +53,10 @@ MidiModel::MidiModel(MidiSource* s)
MidiModel::DiffCommand* MidiModel::DiffCommand*
MidiModel::new_diff_command(const string name) MidiModel::new_diff_command(const string name)
{ {
DiffCommand* cmd = new DiffCommand(_midi_source->model(), name); boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
assert (ms);
DiffCommand* cmd = new DiffCommand (ms->model(), name);
return cmd; return cmd;
} }
@ -696,8 +698,11 @@ MidiModel::write_to (boost::shared_ptr<MidiSource> source)
const bool old_percussive = percussive(); const bool old_percussive = percussive();
set_percussive(false); set_percussive(false);
boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
assert (ms);
source->drop_model(); 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<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) { for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
source->append_event_unlocked_beats(*i); source->append_event_unlocked_beats(*i);
@ -724,14 +729,17 @@ MidiModel::sync_to_source ()
const bool old_percussive = percussive(); const bool old_percussive = percussive();
set_percussive(false); set_percussive(false);
_midi_source->mark_streaming_midi_write_started(note_mode(), _midi_source->timeline_position()); boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
assert (ms);
ms->mark_streaming_midi_write_started (note_mode(), ms->timeline_position());
for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) { for (Evoral::Sequence<TimeType>::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); set_percussive (old_percussive);
_midi_source->mark_streaming_write_completed (); ms->mark_streaming_write_completed ();
set_edited (false); set_edited (false);
@ -755,8 +763,11 @@ MidiModel::write_section_to (boost::shared_ptr<MidiSource> source, Evoral::Music
const bool old_percussive = percussive(); const bool old_percussive = percussive();
set_percussive(false); set_percussive(false);
boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
assert (ms);
source->drop_model(); 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<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) { for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
const Evoral::Event<Evoral::MusicalTime>& ev (*i); const Evoral::Event<Evoral::MusicalTime>& ev (*i);
@ -869,8 +880,11 @@ MidiModel::find_note (gint note_id)
MidiModel::WriteLock MidiModel::WriteLock
MidiModel::edit_lock() MidiModel::edit_lock()
{ {
Glib::Mutex::Lock* source_lock = new Glib::Mutex::Lock(_midi_source->mutex()); boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
_midi_source->invalidate(); // Release cached iterator's read lock on model 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)); return WriteLock(new WriteLockImpl(source_lock, _lock, _control_lock));
} }
@ -880,7 +894,10 @@ MidiModel::edit_lock()
MidiModel::WriteLock MidiModel::WriteLock
MidiModel::write_lock() MidiModel::write_lock()
{ {
assert(!_midi_source->mutex().trylock()); boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
assert (ms);
assert (!ms->mutex().trylock ());
return WriteLock(new WriteLockImpl(NULL, _lock, _control_lock)); 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 */ /* 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<MidiSource> ms = _midi_source.lock ();
assert (ms);
return ms->session().config.get_insert_merge_policy ();
} }
void void
MidiModel::set_midi_source (MidiSource* s) MidiModel::set_midi_source (boost::shared_ptr<MidiSource> s)
{ {
if (_midi_source) { boost::shared_ptr<MidiSource> old = _midi_source.lock ();
_midi_source->invalidate ();
if (old) {
old->invalidate ();
} }
_midi_source_connections.drop_connections (); _midi_source_connections.drop_connections ();
_midi_source = s; _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_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) _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 void
MidiModel::control_list_interpolation_changed (Evoral::Parameter p, Evoral::ControlList::InterpolationStyle s) MidiModel::control_list_interpolation_changed (Evoral::Parameter p, Evoral::ControlList::InterpolationStyle s)
{ {
_midi_source->set_interpolation_of (p, s); boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
assert (ms);
ms->set_interpolation_of (p, s);
} }
void void
@ -1138,7 +1163,10 @@ MidiModel::source_automation_state_changed (Evoral::Parameter p, AutoState s)
void void
MidiModel::automation_list_automation_state_changed (Evoral::Parameter p, AutoState s) MidiModel::automation_list_automation_state_changed (Evoral::Parameter p, AutoState s)
{ {
_midi_source->set_automation_state_of (p, s); boost::shared_ptr<MidiSource> ms = _midi_source.lock ();
assert (ms);
ms->set_automation_state_of (p, s);
} }
boost::shared_ptr<Evoral::Control> boost::shared_ptr<Evoral::Control>
@ -1150,14 +1178,21 @@ MidiModel::control_factory (Evoral::Parameter const & p)
automation state from our source. automation state from our source.
*/ */
assert (_midi_source); boost::shared_ptr<MidiSource> 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<AutomationList> al = boost::dynamic_pointer_cast<AutomationList> (c->list ()); boost::shared_ptr<AutomationList> al = boost::dynamic_pointer_cast<AutomationList> (c->list ());
assert (al); assert (al);
al->set_automation_state (_midi_source->automation_state_of (p)); al->set_automation_state (ms->automation_state_of (p));
return c; return c;
} }
boost::shared_ptr<const MidiSource>
MidiModel::midi_source ()
{
return _midi_source.lock ();
}

View file

@ -69,8 +69,6 @@ SMFSource::SMFSource (Session& s, const string& path, Source::Flag flags)
if (create(path)) { if (create(path)) {
throw failed_constructor (); throw failed_constructor ();
} }
load_model(true, true); // FIXME
} }
/** Constructor used for existing internal-to-session files. */ /** 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)) { if (open(_path)) {
throw failed_constructor (); throw failed_constructor ();
} }
load_model(true, true); // FIXME
} }
SMFSource::~SMFSource () SMFSource::~SMFSource ()
@ -442,8 +438,8 @@ SMFSource::load_model (bool lock, bool force_reload)
return; return;
} }
if (! _model) { if (!_model) {
_model = boost::shared_ptr<MidiModel>(new MidiModel(this)); _model = boost::shared_ptr<MidiModel> (new MidiModel (shared_from_this ()));
} else { } else {
_model->clear(); _model->clear();
} }

View file

@ -178,12 +178,12 @@ SourceFactory::create (Session& s, const XMLNode& node, bool defer_peaks)
} }
} else if (type == DataType::MIDI) { } else if (type == DataType::MIDI) {
Source* src = new SMFSource (s, node); boost::shared_ptr<SMFSource> src (new SMFSource (s, node));
src->load_model (true, true);
// boost_debug_shared_ptr_mark_interesting (src, "Source"); // boost_debug_shared_ptr_mark_interesting (src, "Source");
boost::shared_ptr<Source> ret (src); src->check_for_analysis_data_on_disk ();
ret->check_for_analysis_data_on_disk (); SourceCreated (src);
SourceCreated (ret); return src;
return ret;
} }
return boost::shared_ptr<Source>(); return boost::shared_ptr<Source>();
@ -240,7 +240,8 @@ SourceFactory::createReadable (DataType type, Session& s, const string& path,
} else if (type == DataType::MIDI) { } 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_debug_shared_ptr_mark_interesting (src, "Source");
boost::shared_ptr<Source> ret (src); boost::shared_ptr<Source> ret (src);
@ -285,16 +286,16 @@ SourceFactory::createWritable (DataType type, Session& s, const std::string& pat
} else if (type == DataType::MIDI) { } else if (type == DataType::MIDI) {
// XXX writable flags should belong to MidiSource too // XXX writable flags should belong to MidiSource too
Source* src = new SMFSource (s, path, SndFileSource::default_writable_flags); boost::shared_ptr<SMFSource> src (new SMFSource (s, path, SndFileSource::default_writable_flags));
src->load_model (true, true);
// boost_debug_shared_ptr_mark_interesting (src, "Source"); // boost_debug_shared_ptr_mark_interesting (src, "Source");
boost::shared_ptr<Source> ret (src);
// no analysis data - this is a new file // no analysis data - this is a new file
if (announce) { if (announce) {
SourceCreated (ret); SourceCreated (src);
} }
return ret; return src;
} }