mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-17 04:06:26 +01:00
Fix MIDI region loading.
Add model loading and destroying to SMFSource. Load and display MIDI region data on session load. git-svn-id: svn://localhost/ardour2/trunk@1947 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
41c128155a
commit
b0e91bfa08
14 changed files with 187 additions and 126 deletions
|
|
@ -86,6 +86,14 @@ MidiRegionView::init (Gdk::Color& basic_color, bool wfd)
|
|||
_region->StateChanged.connect (mem_fun(*this, &MidiRegionView::region_changed));
|
||||
|
||||
set_colors ();
|
||||
|
||||
boost::shared_ptr<MidiRegion> mr = boost::dynamic_pointer_cast<MidiRegion> (_region);
|
||||
mr->midi_source(0)->load_model();
|
||||
|
||||
begin_write();
|
||||
for (size_t i=0; i < mr->midi_source(0)->model().n_events(); ++i)
|
||||
add_event(mr->midi_source(0)->model().event_at(i));
|
||||
end_write();
|
||||
}
|
||||
|
||||
MidiRegionView::~MidiRegionView ()
|
||||
|
|
|
|||
|
|
@ -35,9 +35,14 @@ public:
|
|||
MidiModel(size_t size=0);
|
||||
~MidiModel();
|
||||
|
||||
void clear() { _events.clear(); }
|
||||
|
||||
/** Resizes vector if necessary (NOT realtime safe) */
|
||||
void append(const MidiBuffer& data);
|
||||
|
||||
/** Resizes vector if necessary (NOT realtime safe) */
|
||||
void append(const MidiEvent& ev);
|
||||
|
||||
inline const MidiEvent& event_at(unsigned i) const { return _events[i]; }
|
||||
|
||||
inline size_t n_events() const { return _events.size(); }
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ public:
|
|||
protected:
|
||||
|
||||
/* playlist "callbacks" */
|
||||
void flush_notifications ();
|
||||
|
||||
void finalize_split_region (boost::shared_ptr<Region> original, boost::shared_ptr<Region> left, boost::shared_ptr<Region> right);
|
||||
|
||||
|
|
@ -66,7 +65,6 @@ protected:
|
|||
void remove_dependents (boost::shared_ptr<Region> region);
|
||||
|
||||
private:
|
||||
XMLNode& state (bool full_state);
|
||||
void dump () const;
|
||||
|
||||
bool region_changed (Change, boost::shared_ptr<Region>);
|
||||
|
|
|
|||
|
|
@ -78,9 +78,6 @@ class MidiRegion : public Region
|
|||
MidiRegion (boost::shared_ptr<MidiSource>, const XMLNode&);
|
||||
MidiRegion (SourceList &, const XMLNode&);
|
||||
|
||||
private:
|
||||
friend class Playlist;
|
||||
|
||||
private:
|
||||
nframes_t _read_at (const SourceList&, MidiRingBuffer& dst,
|
||||
nframes_t position,
|
||||
|
|
@ -89,6 +86,10 @@ class MidiRegion : public Region
|
|||
|
||||
void recompute_at_start ();
|
||||
void recompute_at_end ();
|
||||
|
||||
protected:
|
||||
|
||||
int set_live_state (const XMLNode&, Change&, bool send);
|
||||
};
|
||||
|
||||
} /* namespace ARDOUR */
|
||||
|
|
|
|||
|
|
@ -69,6 +69,9 @@ class MidiSource : public Source
|
|||
XMLNode& get_state ();
|
||||
int set_state (const XMLNode&);
|
||||
|
||||
virtual void load_model(bool lock=true) = 0;
|
||||
virtual void destroy_model() = 0;
|
||||
|
||||
MidiModel& model() { return _model; }
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -75,10 +75,11 @@ public:
|
|||
|
||||
protected:
|
||||
XMLNode& state (bool full);
|
||||
|
||||
int _set_state (const XMLNode&, bool call_base);
|
||||
|
||||
private:
|
||||
int set_diskstream (boost::shared_ptr<MidiDiskstream> ds);
|
||||
|
||||
void set_state_part_two ();
|
||||
void set_state_part_three ();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -87,6 +87,9 @@ class SMFSource : public MidiSource {
|
|||
int set_state (const XMLNode&);
|
||||
|
||||
void seek_to(nframes_t time);
|
||||
|
||||
void load_model(bool lock=true);
|
||||
void destroy_model();
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
|||
|
|
@ -63,3 +63,26 @@ MidiModel::append(const MidiBuffer& buf)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/** Append \a in_event to model. NOT (even remotely) realtime safe.
|
||||
*
|
||||
* Timestamps of events in \a buf are expected to be relative to
|
||||
* the start of this model (t=0) and MUST be monotonically increasing
|
||||
* and MUST be >= the latest event currently in the model.
|
||||
*
|
||||
* Events in buf are deep copied.
|
||||
*/
|
||||
void
|
||||
MidiModel::append(const MidiEvent& in_event)
|
||||
{
|
||||
assert(_events.empty() || in_event.time >= _events.back().time);
|
||||
|
||||
_events.push_back(in_event);
|
||||
MidiEvent& my_event = _events.back();
|
||||
assert(my_event.time == in_event.time);
|
||||
assert(my_event.size == in_event.size);
|
||||
|
||||
my_event.buffer = new Byte[my_event.size];
|
||||
memcpy(my_event.buffer, in_event.buffer, my_event.size);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,9 +46,9 @@ MidiPlaylist::MidiPlaylist (Session& session, const XMLNode& node, bool hidden)
|
|||
const XMLProperty* prop = node.property("type");
|
||||
assert(prop && DataType(prop->value()) == DataType::MIDI);
|
||||
|
||||
in_set_state = true;
|
||||
in_set_state++;
|
||||
set_state (node);
|
||||
in_set_state = false;
|
||||
in_set_state--;
|
||||
}
|
||||
|
||||
MidiPlaylist::MidiPlaylist (Session& session, string name, bool hidden)
|
||||
|
|
@ -109,6 +109,10 @@ MidiPlaylist::MidiPlaylist (boost::shared_ptr<const MidiPlaylist> other, nframes
|
|||
MidiPlaylist::~MidiPlaylist ()
|
||||
{
|
||||
GoingAway (); /* EMIT SIGNAL */
|
||||
|
||||
/* drop connections to signals */
|
||||
|
||||
notify_callbacks ();
|
||||
}
|
||||
|
||||
struct RegionSortByLayer {
|
||||
|
|
@ -159,26 +163,14 @@ MidiPlaylist::read (MidiRingBuffer& dst, nframes_t start,
|
|||
void
|
||||
MidiPlaylist::remove_dependents (boost::shared_ptr<Region> region)
|
||||
{
|
||||
/* MIDI regions have no dependents (crossfades) */
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MidiPlaylist::flush_notifications ()
|
||||
{
|
||||
Playlist::flush_notifications();
|
||||
|
||||
if (in_flush) {
|
||||
return;
|
||||
}
|
||||
|
||||
in_flush = true;
|
||||
|
||||
in_flush = false;
|
||||
}
|
||||
|
||||
void
|
||||
MidiPlaylist::refresh_dependents (boost::shared_ptr<Region> r)
|
||||
{
|
||||
/* MIDI regions have no dependents (crossfades) */
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -226,38 +218,24 @@ MidiPlaylist::finalize_split_region (boost::shared_ptr<Region> original, boost::
|
|||
void
|
||||
MidiPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
|
||||
{
|
||||
/* MIDI regions have no dependents (crossfades) */
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
MidiPlaylist::set_state (const XMLNode& node)
|
||||
{
|
||||
if (!in_set_state) {
|
||||
Playlist::set_state (node);
|
||||
}
|
||||
in_set_state++;
|
||||
freeze ();
|
||||
|
||||
// Actually Charles, I don't much care for children
|
||||
|
||||
/*
|
||||
XMLNodeList nlist = node.children();
|
||||
Playlist::set_state (node);
|
||||
|
||||
for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
|
||||
XMLNode* const child = *niter;
|
||||
|
||||
}*/
|
||||
thaw();
|
||||
in_set_state--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
MidiPlaylist::state (bool full_state)
|
||||
{
|
||||
XMLNode& node = Playlist::state (full_state);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void
|
||||
MidiPlaylist::dump () const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include <pbd/basename.h>
|
||||
#include <pbd/xml++.h>
|
||||
#include <pbd/enumwriter.h>
|
||||
|
||||
#include <ardour/midi_region.h>
|
||||
#include <ardour/session.h>
|
||||
|
|
@ -174,29 +175,18 @@ XMLNode&
|
|||
MidiRegion::state (bool full)
|
||||
{
|
||||
XMLNode& node (Region::state (full));
|
||||
XMLNode *child;
|
||||
char buf[64];
|
||||
char buf2[64];
|
||||
LocaleGuard lg (X_("POSIX"));
|
||||
|
||||
snprintf (buf, sizeof (buf), "0x%x", (int) _flags);
|
||||
node.add_property ("flags", buf);
|
||||
|
||||
node.add_property ("flags", enum_2_string (_flags));
|
||||
|
||||
for (uint32_t n=0; n < _sources.size(); ++n) {
|
||||
snprintf (buf2, sizeof(buf2), "source-%d", n);
|
||||
_sources[n]->id().print (buf, sizeof(buf));
|
||||
node.add_property (buf2, buf);
|
||||
}
|
||||
|
||||
snprintf (buf, sizeof (buf), "%u", (uint32_t) _sources.size());
|
||||
node.add_property ("channels", buf);
|
||||
|
||||
child = node.add_child ("Envelope");
|
||||
|
||||
if ( ! full) {
|
||||
child->add_property ("default", "yes");
|
||||
}
|
||||
|
||||
if (full && _extra_xml) {
|
||||
node.add_child_copy (*_extra_xml);
|
||||
}
|
||||
|
|
@ -205,32 +195,52 @@ MidiRegion::state (bool full)
|
|||
}
|
||||
|
||||
int
|
||||
MidiRegion::set_state (const XMLNode& node)
|
||||
MidiRegion::set_live_state (const XMLNode& node, Change& what_changed, bool send)
|
||||
{
|
||||
const XMLNodeList& nlist = node.children();
|
||||
const XMLProperty *prop;
|
||||
LocaleGuard lg (X_("POSIX"));
|
||||
|
||||
Region::set_state (node);
|
||||
Region::set_live_state (node, what_changed, false);
|
||||
|
||||
uint32_t old_flags = _flags;
|
||||
|
||||
if ((prop = node.property ("flags")) != 0) {
|
||||
_flags = Flag (strtol (prop->value().c_str(), (char **) 0, 16));
|
||||
_flags = Flag (string_2_enum (prop->value(), _flags));
|
||||
|
||||
//_flags = Flag (strtol (prop->value().c_str(), (char **) 0, 16));
|
||||
|
||||
_flags = Flag (_flags & ~Region::LeftOfSplit);
|
||||
_flags = Flag (_flags & ~Region::RightOfSplit);
|
||||
}
|
||||
|
||||
/* Now find child items */
|
||||
for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
||||
|
||||
XMLNode *child;
|
||||
//XMLProperty *prop;
|
||||
|
||||
child = (*niter);
|
||||
|
||||
/** Hello, children */
|
||||
if ((old_flags ^ _flags) & Muted) {
|
||||
what_changed = Change (what_changed|MuteChanged);
|
||||
}
|
||||
if ((old_flags ^ _flags) & Opaque) {
|
||||
what_changed = Change (what_changed|OpacityChanged);
|
||||
}
|
||||
if ((old_flags ^ _flags) & Locked) {
|
||||
what_changed = Change (what_changed|LockChanged);
|
||||
}
|
||||
|
||||
if (send) {
|
||||
send_change (what_changed);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
MidiRegion::set_state (const XMLNode& node)
|
||||
{
|
||||
/* Region::set_state() calls the virtual set_live_state(),
|
||||
which will get us back to AudioRegion::set_live_state()
|
||||
to handle the relevant stuff.
|
||||
*/
|
||||
|
||||
return Region::set_state (node);
|
||||
}
|
||||
|
||||
void
|
||||
MidiRegion::recompute_at_end ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
#include <sigc++/retype_return.h>
|
||||
#include <sigc++/bind.h>
|
||||
|
||||
#include <pbd/enumwriter.h>
|
||||
|
||||
#include <ardour/midi_track.h>
|
||||
#include <ardour/midi_diskstream.h>
|
||||
#include <ardour/session.h>
|
||||
|
|
@ -72,10 +74,7 @@ MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mo
|
|||
MidiTrack::MidiTrack (Session& sess, const XMLNode& node)
|
||||
: Track (sess, node)
|
||||
{
|
||||
_freeze_record.state = NoFreeze;
|
||||
set_state (node);
|
||||
_declickable = true;
|
||||
_saved_meter_point = _meter_point;
|
||||
_set_state(node, false);
|
||||
|
||||
set_input_minimum(ChanCount(DataType::MIDI, 1));
|
||||
set_input_maximum(ChanCount(DataType::MIDI, 1));
|
||||
|
|
@ -140,23 +139,22 @@ MidiTrack::midi_diskstream() const
|
|||
|
||||
int
|
||||
MidiTrack::set_state (const XMLNode& node)
|
||||
{
|
||||
return _set_state (node, true);
|
||||
}
|
||||
|
||||
int
|
||||
MidiTrack::_set_state (const XMLNode& node, bool call_base)
|
||||
{
|
||||
const XMLProperty *prop;
|
||||
XMLNodeConstIterator iter;
|
||||
|
||||
if (Route::set_state (node)) {
|
||||
if (Route::_set_state (node, call_base)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if ((prop = node.property (X_("mode"))) != 0) {
|
||||
if (prop->value() == X_("normal")) {
|
||||
_mode = Normal;
|
||||
} else if (prop->value() == X_("destructive")) {
|
||||
_mode = Destructive;
|
||||
} else {
|
||||
warning << string_compose ("unknown midi track mode \"%1\" seen and ignored", prop->value()) << endmsg;
|
||||
_mode = Normal;
|
||||
}
|
||||
_mode = TrackMode (string_2_enum (prop->value(), _mode));
|
||||
} else {
|
||||
_mode = Normal;
|
||||
}
|
||||
|
|
@ -193,12 +191,9 @@ MidiTrack::set_state (const XMLNode& node)
|
|||
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
|
||||
child = *niter;
|
||||
|
||||
if (child->name() == X_("remote_control")) {
|
||||
if ((prop = child->property (X_("id"))) != 0) {
|
||||
int32_t x;
|
||||
sscanf (prop->value().c_str(), "%d", &x);
|
||||
set_remote_control_id (x);
|
||||
}
|
||||
if (child->name() == X_("recenable")) {
|
||||
_rec_enable_control.set_state (*child);
|
||||
_session.add_controllable (&_rec_enable_control);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -221,8 +216,7 @@ MidiTrack::state(bool full_state)
|
|||
|
||||
freeze_node = new XMLNode (X_("freeze-info"));
|
||||
freeze_node->add_property ("playlist", _freeze_record.playlist->name());
|
||||
snprintf (buf, sizeof (buf), "%d", (int) _freeze_record.state);
|
||||
freeze_node->add_property ("state", buf);
|
||||
freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
|
||||
|
||||
for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
|
||||
inode = new XMLNode (X_("insert"));
|
||||
|
|
@ -239,31 +233,12 @@ MidiTrack::state(bool full_state)
|
|||
/* Alignment: act as a proxy for the diskstream */
|
||||
|
||||
XMLNode* align_node = new XMLNode (X_("alignment"));
|
||||
switch (_diskstream->alignment_style()) {
|
||||
case ExistingMaterial:
|
||||
snprintf (buf, sizeof (buf), X_("existing"));
|
||||
break;
|
||||
case CaptureTime:
|
||||
snprintf (buf, sizeof (buf), X_("capture"));
|
||||
break;
|
||||
}
|
||||
align_node->add_property (X_("style"), buf);
|
||||
AlignStyle as = _diskstream->alignment_style ();
|
||||
align_node->add_property (X_("style"), enum_2_string (as));
|
||||
root.add_child_nocopy (*align_node);
|
||||
|
||||
XMLNode* remote_control_node = new XMLNode (X_("remote_control"));
|
||||
snprintf (buf, sizeof (buf), "%d", _remote_control_id);
|
||||
remote_control_node->add_property (X_("id"), buf);
|
||||
root.add_child_nocopy (*remote_control_node);
|
||||
|
||||
switch (_mode) {
|
||||
case Normal:
|
||||
root.add_property (X_("mode"), X_("normal"));
|
||||
break;
|
||||
case Destructive:
|
||||
root.add_property (X_("mode"), X_("destructive"));
|
||||
break;
|
||||
}
|
||||
|
||||
root.add_property (X_("mode"), enum_2_string (_mode));
|
||||
|
||||
/* we don't return diskstream state because we don't
|
||||
own the diskstream exclusively. control of the diskstream
|
||||
state is ceded to the Session, even if we create the
|
||||
|
|
@ -272,6 +247,8 @@ MidiTrack::state(bool full_state)
|
|||
|
||||
_diskstream->id().print (buf, sizeof(buf));
|
||||
root.add_property ("diskstream-id", buf);
|
||||
|
||||
root.add_child_nocopy (_rec_enable_control.get_state());
|
||||
|
||||
return root;
|
||||
}
|
||||
|
|
@ -314,7 +291,7 @@ MidiTrack::set_state_part_two ()
|
|||
}
|
||||
|
||||
if ((prop = fnode->property (X_("state"))) != 0) {
|
||||
_freeze_record.state = (FreezeState) atoi (prop->value().c_str());
|
||||
_freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
|
||||
}
|
||||
|
||||
XMLNodeConstIterator citer;
|
||||
|
|
@ -341,11 +318,21 @@ MidiTrack::set_state_part_two ()
|
|||
if ((fnode = find_named_node (*pending_state, X_("alignment"))) != 0) {
|
||||
|
||||
if ((prop = fnode->property (X_("style"))) != 0) {
|
||||
if (prop->value() == "existing") {
|
||||
_diskstream->set_persistent_align_style (ExistingMaterial);
|
||||
} else if (prop->value() == "capture") {
|
||||
_diskstream->set_persistent_align_style (CaptureTime);
|
||||
|
||||
/* fix for older sessions from before EnumWriter */
|
||||
|
||||
string pstr;
|
||||
|
||||
if (prop->value() == "capture") {
|
||||
pstr = "CaptureTime";
|
||||
} else if (prop->value() == "existing") {
|
||||
pstr = "ExistingMaterial";
|
||||
} else {
|
||||
pstr = prop->value();
|
||||
}
|
||||
|
||||
AlignStyle as = AlignStyle (string_2_enum (pstr, as));
|
||||
_diskstream->set_persistent_align_style (as);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#include <ardour/playlist.h>
|
||||
#include <ardour/audioplaylist.h>
|
||||
#include <ardour/audio_track.h>
|
||||
#include <ardour/midi_playlist.h>
|
||||
#include <ardour/midi_track.h>
|
||||
#include <ardour/tempo.h>
|
||||
#include <ardour/audiosource.h>
|
||||
#include <ardour/audioregion.h>
|
||||
|
|
@ -93,11 +95,11 @@ Session::memento_command_factory(XMLNode *n)
|
|||
return new MementoCommand<Locations>(_locations, before, after);
|
||||
} else if (obj_T == typeid (TempoMap).name()) {
|
||||
return new MementoCommand<TempoMap>(*_tempo_map, before, after);
|
||||
} else if (obj_T == typeid (Playlist).name() || obj_T == typeid (AudioPlaylist).name()) {
|
||||
} else if (obj_T == typeid (Playlist).name() || obj_T == typeid (AudioPlaylist).name() || obj_T == typeid (MidiPlaylist).name()) {
|
||||
if (boost::shared_ptr<Playlist> pl = playlist_by_name(child->property("name")->value())) {
|
||||
return new MementoCommand<Playlist>(*(pl.get()), before, after);
|
||||
}
|
||||
} else if (obj_T == typeid (Route).name() || obj_T == typeid (AudioTrack).name()) {
|
||||
} else if (obj_T == typeid (Route).name() || obj_T == typeid (AudioTrack).name() || obj_T == typeid(MidiTrack).name()) {
|
||||
return new MementoCommand<Route>(*route_by_id(id), before, after);
|
||||
} else if (obj_T == typeid (Curve).name() || obj_T == typeid (AutomationList).name()) {
|
||||
if (automation_lists.count(id))
|
||||
|
|
|
|||
|
|
@ -1110,7 +1110,7 @@ Session::set_state (const XMLNode& node)
|
|||
|
||||
/* Object loading order:
|
||||
|
||||
MIDI
|
||||
MIDI Control
|
||||
Path
|
||||
extra
|
||||
Options/Config
|
||||
|
|
@ -1397,7 +1397,6 @@ Session::XMLAudioRegionFactory (const XMLNode& node, bool full)
|
|||
nchans = atoi (prop->value().c_str());
|
||||
}
|
||||
|
||||
|
||||
if ((prop = node.property ("name")) == 0) {
|
||||
cerr << "no name for this region\n";
|
||||
abort ();
|
||||
|
|
@ -1461,7 +1460,6 @@ Session::XMLAudioRegionFactory (const XMLNode& node, bool full)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
return region;
|
||||
|
||||
}
|
||||
|
|
@ -1477,7 +1475,7 @@ Session::XMLMidiRegionFactory (const XMLNode& node, bool full)
|
|||
const XMLProperty* prop;
|
||||
boost::shared_ptr<Source> source;
|
||||
boost::shared_ptr<MidiSource> ms;
|
||||
MidiRegion::SourceList sources;
|
||||
SourceList sources;
|
||||
uint32_t nchans = 1;
|
||||
|
||||
if (node.name() != X_("Region")) {
|
||||
|
|
@ -1487,6 +1485,11 @@ Session::XMLMidiRegionFactory (const XMLNode& node, bool full)
|
|||
if ((prop = node.property (X_("channels"))) != 0) {
|
||||
nchans = atoi (prop->value().c_str());
|
||||
}
|
||||
|
||||
if ((prop = node.property ("name")) == 0) {
|
||||
cerr << "no name for this region\n";
|
||||
abort ();
|
||||
}
|
||||
|
||||
// Multiple midi channels? that's just crazy talk
|
||||
assert(nchans == 1);
|
||||
|
|
@ -1515,6 +1518,17 @@ Session::XMLMidiRegionFactory (const XMLNode& node, bool full)
|
|||
|
||||
try {
|
||||
boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
|
||||
/* a final detail: this is the one and only place that we know how long missing files are */
|
||||
|
||||
if (region->whole_file()) {
|
||||
for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
|
||||
boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
|
||||
if (sfp) {
|
||||
sfp->set_length (region->length());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
|
|
@ -1534,8 +1548,6 @@ Session::get_sources_as_xml ()
|
|||
node->add_child_nocopy (i->second->get_state());
|
||||
}
|
||||
|
||||
/* XXX get MIDI and other sources here */
|
||||
|
||||
return *node;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -754,3 +754,33 @@ SMFSource::read_var_len() const
|
|||
|
||||
return value;
|
||||
}
|
||||
|
||||
void
|
||||
SMFSource::load_model(bool lock)
|
||||
{
|
||||
if (lock)
|
||||
Glib::Mutex::Lock lm (_lock);
|
||||
|
||||
_model.clear();
|
||||
|
||||
fseek(_fd, _header_size, 0);
|
||||
|
||||
nframes_t time = 0;
|
||||
MidiEvent ev;
|
||||
|
||||
int ret;
|
||||
while ((ret = read_event(ev)) >= 0) {
|
||||
time += ev.time;
|
||||
ev.time = time;
|
||||
if (ret > 0) { // didn't skip (meta) event
|
||||
_model.append(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SMFSource::destroy_model()
|
||||
{
|
||||
_model.clear();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue