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:
parent
ebf3762fa9
commit
7d4e03e28e
@ -51,7 +51,7 @@ class MidiModel : public AutomatableSequence<Evoral::MusicalTime> {
|
||||
public:
|
||||
typedef Evoral::MusicalTime TimeType;
|
||||
|
||||
MidiModel(MidiSource* s);
|
||||
MidiModel (boost::shared_ptr<MidiSource>);
|
||||
|
||||
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<void> ContentsChanged;
|
||||
|
||||
const MidiSource* midi_source() const { return _midi_source; }
|
||||
void set_midi_source (MidiSource *);
|
||||
boost::shared_ptr<const MidiSource> midi_source ();
|
||||
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 (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<MidiSource> _midi_source;
|
||||
InsertMergePolicy _insert_merge_policy;
|
||||
};
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
#include <glibmm/thread.h>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include "pbd/stateful.h"
|
||||
#include "pbd/xml++.h"
|
||||
#include "evoral/Sequence.hpp"
|
||||
@ -38,7 +39,7 @@ class MidiModel;
|
||||
template<typename T> class MidiRingBuffer;
|
||||
|
||||
/** Source for MIDI data */
|
||||
class MidiSource : virtual public Source
|
||||
class MidiSource : virtual public Source, public boost::enable_shared_from_this<MidiSource>
|
||||
{
|
||||
public:
|
||||
typedef double TimeType;
|
||||
|
@ -38,9 +38,8 @@ using namespace std;
|
||||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
MidiModel::MidiModel(MidiSource* s)
|
||||
MidiModel::MidiModel (boost::shared_ptr<MidiSource> s)
|
||||
: AutomatableSequence<TimeType>(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<MidiSource> 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<MidiSource> source)
|
||||
const bool old_percussive = percussive();
|
||||
set_percussive(false);
|
||||
|
||||
boost::shared_ptr<MidiSource> 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<TimeType>::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<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) {
|
||||
_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<MidiSource> source, Evoral::Music
|
||||
const bool old_percussive = percussive();
|
||||
set_percussive(false);
|
||||
|
||||
boost::shared_ptr<MidiSource> 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<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
|
||||
const Evoral::Event<Evoral::MusicalTime>& 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<MidiSource> 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<MidiSource> 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<MidiSource> 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<MidiSource> s)
|
||||
{
|
||||
if (_midi_source) {
|
||||
_midi_source->invalidate ();
|
||||
boost::shared_ptr<MidiSource> 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<MidiSource> 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<MidiSource> ms = _midi_source.lock ();
|
||||
assert (ms);
|
||||
|
||||
ms->set_automation_state_of (p, s);
|
||||
}
|
||||
|
||||
boost::shared_ptr<Evoral::Control>
|
||||
@ -1150,14 +1178,21 @@ MidiModel::control_factory (Evoral::Parameter const & p)
|
||||
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 ());
|
||||
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<const MidiSource>
|
||||
MidiModel::midi_source ()
|
||||
{
|
||||
return _midi_source.lock ();
|
||||
}
|
||||
|
@ -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<MidiModel>(new MidiModel(this));
|
||||
if (!_model) {
|
||||
_model = boost::shared_ptr<MidiModel> (new MidiModel (shared_from_this ()));
|
||||
} else {
|
||||
_model->clear();
|
||||
}
|
||||
|
@ -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<SMFSource> src (new SMFSource (s, node));
|
||||
src->load_model (true, true);
|
||||
// boost_debug_shared_ptr_mark_interesting (src, "Source");
|
||||
boost::shared_ptr<Source> 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<Source>();
|
||||
@ -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<Source> 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<SMFSource> 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<Source> ret (src);
|
||||
|
||||
// no analysis data - this is a new file
|
||||
|
||||
if (announce) {
|
||||
SourceCreated (ret);
|
||||
SourceCreated (src);
|
||||
}
|
||||
return ret;
|
||||
return src;
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user