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));
|
_region->StateChanged.connect (mem_fun(*this, &MidiRegionView::region_changed));
|
||||||
|
|
||||||
set_colors ();
|
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 ()
|
MidiRegionView::~MidiRegionView ()
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,14 @@ public:
|
||||||
MidiModel(size_t size=0);
|
MidiModel(size_t size=0);
|
||||||
~MidiModel();
|
~MidiModel();
|
||||||
|
|
||||||
|
void clear() { _events.clear(); }
|
||||||
|
|
||||||
/** Resizes vector if necessary (NOT realtime safe) */
|
/** Resizes vector if necessary (NOT realtime safe) */
|
||||||
void append(const MidiBuffer& data);
|
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 const MidiEvent& event_at(unsigned i) const { return _events[i]; }
|
||||||
|
|
||||||
inline size_t n_events() const { return _events.size(); }
|
inline size_t n_events() const { return _events.size(); }
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,6 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/* playlist "callbacks" */
|
/* playlist "callbacks" */
|
||||||
void flush_notifications ();
|
|
||||||
|
|
||||||
void finalize_split_region (boost::shared_ptr<Region> original, boost::shared_ptr<Region> left, boost::shared_ptr<Region> right);
|
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);
|
void remove_dependents (boost::shared_ptr<Region> region);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
XMLNode& state (bool full_state);
|
|
||||||
void dump () const;
|
void dump () const;
|
||||||
|
|
||||||
bool region_changed (Change, boost::shared_ptr<Region>);
|
bool region_changed (Change, boost::shared_ptr<Region>);
|
||||||
|
|
|
||||||
|
|
@ -78,9 +78,6 @@ class MidiRegion : public Region
|
||||||
MidiRegion (boost::shared_ptr<MidiSource>, const XMLNode&);
|
MidiRegion (boost::shared_ptr<MidiSource>, const XMLNode&);
|
||||||
MidiRegion (SourceList &, const XMLNode&);
|
MidiRegion (SourceList &, const XMLNode&);
|
||||||
|
|
||||||
private:
|
|
||||||
friend class Playlist;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nframes_t _read_at (const SourceList&, MidiRingBuffer& dst,
|
nframes_t _read_at (const SourceList&, MidiRingBuffer& dst,
|
||||||
nframes_t position,
|
nframes_t position,
|
||||||
|
|
@ -89,6 +86,10 @@ class MidiRegion : public Region
|
||||||
|
|
||||||
void recompute_at_start ();
|
void recompute_at_start ();
|
||||||
void recompute_at_end ();
|
void recompute_at_end ();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
int set_live_state (const XMLNode&, Change&, bool send);
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace ARDOUR */
|
} /* namespace ARDOUR */
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,9 @@ class MidiSource : public Source
|
||||||
XMLNode& get_state ();
|
XMLNode& get_state ();
|
||||||
int set_state (const XMLNode&);
|
int set_state (const XMLNode&);
|
||||||
|
|
||||||
|
virtual void load_model(bool lock=true) = 0;
|
||||||
|
virtual void destroy_model() = 0;
|
||||||
|
|
||||||
MidiModel& model() { return _model; }
|
MidiModel& model() { return _model; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
|
|
@ -75,10 +75,11 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
XMLNode& state (bool full);
|
XMLNode& state (bool full);
|
||||||
|
|
||||||
|
int _set_state (const XMLNode&, bool call_base);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int set_diskstream (boost::shared_ptr<MidiDiskstream> ds);
|
int set_diskstream (boost::shared_ptr<MidiDiskstream> ds);
|
||||||
|
|
||||||
void set_state_part_two ();
|
void set_state_part_two ();
|
||||||
void set_state_part_three ();
|
void set_state_part_three ();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,9 @@ class SMFSource : public MidiSource {
|
||||||
int set_state (const XMLNode&);
|
int set_state (const XMLNode&);
|
||||||
|
|
||||||
void seek_to(nframes_t time);
|
void seek_to(nframes_t time);
|
||||||
|
|
||||||
|
void load_model(bool lock=true);
|
||||||
|
void destroy_model();
|
||||||
|
|
||||||
private:
|
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");
|
const XMLProperty* prop = node.property("type");
|
||||||
assert(prop && DataType(prop->value()) == DataType::MIDI);
|
assert(prop && DataType(prop->value()) == DataType::MIDI);
|
||||||
|
|
||||||
in_set_state = true;
|
in_set_state++;
|
||||||
set_state (node);
|
set_state (node);
|
||||||
in_set_state = false;
|
in_set_state--;
|
||||||
}
|
}
|
||||||
|
|
||||||
MidiPlaylist::MidiPlaylist (Session& session, string name, bool hidden)
|
MidiPlaylist::MidiPlaylist (Session& session, string name, bool hidden)
|
||||||
|
|
@ -109,6 +109,10 @@ MidiPlaylist::MidiPlaylist (boost::shared_ptr<const MidiPlaylist> other, nframes
|
||||||
MidiPlaylist::~MidiPlaylist ()
|
MidiPlaylist::~MidiPlaylist ()
|
||||||
{
|
{
|
||||||
GoingAway (); /* EMIT SIGNAL */
|
GoingAway (); /* EMIT SIGNAL */
|
||||||
|
|
||||||
|
/* drop connections to signals */
|
||||||
|
|
||||||
|
notify_callbacks ();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RegionSortByLayer {
|
struct RegionSortByLayer {
|
||||||
|
|
@ -159,26 +163,14 @@ MidiPlaylist::read (MidiRingBuffer& dst, nframes_t start,
|
||||||
void
|
void
|
||||||
MidiPlaylist::remove_dependents (boost::shared_ptr<Region> region)
|
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
|
void
|
||||||
MidiPlaylist::refresh_dependents (boost::shared_ptr<Region> r)
|
MidiPlaylist::refresh_dependents (boost::shared_ptr<Region> r)
|
||||||
{
|
{
|
||||||
|
/* MIDI regions have no dependents (crossfades) */
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -226,38 +218,24 @@ MidiPlaylist::finalize_split_region (boost::shared_ptr<Region> original, boost::
|
||||||
void
|
void
|
||||||
MidiPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
|
MidiPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
|
||||||
{
|
{
|
||||||
|
/* MIDI regions have no dependents (crossfades) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
MidiPlaylist::set_state (const XMLNode& node)
|
MidiPlaylist::set_state (const XMLNode& node)
|
||||||
{
|
{
|
||||||
if (!in_set_state) {
|
in_set_state++;
|
||||||
Playlist::set_state (node);
|
freeze ();
|
||||||
}
|
|
||||||
|
|
||||||
// Actually Charles, I don't much care for children
|
Playlist::set_state (node);
|
||||||
|
|
||||||
/*
|
|
||||||
XMLNodeList nlist = node.children();
|
|
||||||
|
|
||||||
for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
thaw();
|
||||||
|
in_set_state--;
|
||||||
XMLNode* const child = *niter;
|
|
||||||
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XMLNode&
|
|
||||||
MidiPlaylist::state (bool full_state)
|
|
||||||
{
|
|
||||||
XMLNode& node = Playlist::state (full_state);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiPlaylist::dump () const
|
MidiPlaylist::dump () const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include <pbd/basename.h>
|
#include <pbd/basename.h>
|
||||||
#include <pbd/xml++.h>
|
#include <pbd/xml++.h>
|
||||||
|
#include <pbd/enumwriter.h>
|
||||||
|
|
||||||
#include <ardour/midi_region.h>
|
#include <ardour/midi_region.h>
|
||||||
#include <ardour/session.h>
|
#include <ardour/session.h>
|
||||||
|
|
@ -174,29 +175,18 @@ XMLNode&
|
||||||
MidiRegion::state (bool full)
|
MidiRegion::state (bool full)
|
||||||
{
|
{
|
||||||
XMLNode& node (Region::state (full));
|
XMLNode& node (Region::state (full));
|
||||||
XMLNode *child;
|
|
||||||
char buf[64];
|
char buf[64];
|
||||||
char buf2[64];
|
char buf2[64];
|
||||||
LocaleGuard lg (X_("POSIX"));
|
LocaleGuard lg (X_("POSIX"));
|
||||||
|
|
||||||
snprintf (buf, sizeof (buf), "0x%x", (int) _flags);
|
node.add_property ("flags", enum_2_string (_flags));
|
||||||
node.add_property ("flags", buf);
|
|
||||||
|
|
||||||
for (uint32_t n=0; n < _sources.size(); ++n) {
|
for (uint32_t n=0; n < _sources.size(); ++n) {
|
||||||
snprintf (buf2, sizeof(buf2), "source-%d", n);
|
snprintf (buf2, sizeof(buf2), "source-%d", n);
|
||||||
_sources[n]->id().print (buf, sizeof(buf));
|
_sources[n]->id().print (buf, sizeof(buf));
|
||||||
node.add_property (buf2, 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) {
|
if (full && _extra_xml) {
|
||||||
node.add_child_copy (*_extra_xml);
|
node.add_child_copy (*_extra_xml);
|
||||||
}
|
}
|
||||||
|
|
@ -205,32 +195,52 @@ MidiRegion::state (bool full)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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;
|
const XMLProperty *prop;
|
||||||
LocaleGuard lg (X_("POSIX"));
|
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) {
|
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 */
|
if ((old_flags ^ _flags) & Muted) {
|
||||||
for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
what_changed = Change (what_changed|MuteChanged);
|
||||||
|
}
|
||||||
XMLNode *child;
|
if ((old_flags ^ _flags) & Opaque) {
|
||||||
//XMLProperty *prop;
|
what_changed = Change (what_changed|OpacityChanged);
|
||||||
|
}
|
||||||
child = (*niter);
|
if ((old_flags ^ _flags) & Locked) {
|
||||||
|
what_changed = Change (what_changed|LockChanged);
|
||||||
/** Hello, children */
|
}
|
||||||
|
|
||||||
|
if (send) {
|
||||||
|
send_change (what_changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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
|
void
|
||||||
MidiRegion::recompute_at_end ()
|
MidiRegion::recompute_at_end ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@
|
||||||
#include <sigc++/retype_return.h>
|
#include <sigc++/retype_return.h>
|
||||||
#include <sigc++/bind.h>
|
#include <sigc++/bind.h>
|
||||||
|
|
||||||
|
#include <pbd/enumwriter.h>
|
||||||
|
|
||||||
#include <ardour/midi_track.h>
|
#include <ardour/midi_track.h>
|
||||||
#include <ardour/midi_diskstream.h>
|
#include <ardour/midi_diskstream.h>
|
||||||
#include <ardour/session.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)
|
MidiTrack::MidiTrack (Session& sess, const XMLNode& node)
|
||||||
: Track (sess, node)
|
: Track (sess, node)
|
||||||
{
|
{
|
||||||
_freeze_record.state = NoFreeze;
|
_set_state(node, false);
|
||||||
set_state (node);
|
|
||||||
_declickable = true;
|
|
||||||
_saved_meter_point = _meter_point;
|
|
||||||
|
|
||||||
set_input_minimum(ChanCount(DataType::MIDI, 1));
|
set_input_minimum(ChanCount(DataType::MIDI, 1));
|
||||||
set_input_maximum(ChanCount(DataType::MIDI, 1));
|
set_input_maximum(ChanCount(DataType::MIDI, 1));
|
||||||
|
|
@ -140,23 +139,22 @@ MidiTrack::midi_diskstream() const
|
||||||
|
|
||||||
int
|
int
|
||||||
MidiTrack::set_state (const XMLNode& node)
|
MidiTrack::set_state (const XMLNode& node)
|
||||||
|
{
|
||||||
|
return _set_state (node, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
MidiTrack::_set_state (const XMLNode& node, bool call_base)
|
||||||
{
|
{
|
||||||
const XMLProperty *prop;
|
const XMLProperty *prop;
|
||||||
XMLNodeConstIterator iter;
|
XMLNodeConstIterator iter;
|
||||||
|
|
||||||
if (Route::set_state (node)) {
|
if (Route::_set_state (node, call_base)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((prop = node.property (X_("mode"))) != 0) {
|
if ((prop = node.property (X_("mode"))) != 0) {
|
||||||
if (prop->value() == X_("normal")) {
|
_mode = TrackMode (string_2_enum (prop->value(), _mode));
|
||||||
_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;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
_mode = Normal;
|
_mode = Normal;
|
||||||
}
|
}
|
||||||
|
|
@ -193,12 +191,9 @@ MidiTrack::set_state (const XMLNode& node)
|
||||||
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
|
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
|
||||||
child = *niter;
|
child = *niter;
|
||||||
|
|
||||||
if (child->name() == X_("remote_control")) {
|
if (child->name() == X_("recenable")) {
|
||||||
if ((prop = child->property (X_("id"))) != 0) {
|
_rec_enable_control.set_state (*child);
|
||||||
int32_t x;
|
_session.add_controllable (&_rec_enable_control);
|
||||||
sscanf (prop->value().c_str(), "%d", &x);
|
|
||||||
set_remote_control_id (x);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -221,8 +216,7 @@ MidiTrack::state(bool full_state)
|
||||||
|
|
||||||
freeze_node = new XMLNode (X_("freeze-info"));
|
freeze_node = new XMLNode (X_("freeze-info"));
|
||||||
freeze_node->add_property ("playlist", _freeze_record.playlist->name());
|
freeze_node->add_property ("playlist", _freeze_record.playlist->name());
|
||||||
snprintf (buf, sizeof (buf), "%d", (int) _freeze_record.state);
|
freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
|
||||||
freeze_node->add_property ("state", buf);
|
|
||||||
|
|
||||||
for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
|
for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
|
||||||
inode = new XMLNode (X_("insert"));
|
inode = new XMLNode (X_("insert"));
|
||||||
|
|
@ -239,31 +233,12 @@ MidiTrack::state(bool full_state)
|
||||||
/* Alignment: act as a proxy for the diskstream */
|
/* Alignment: act as a proxy for the diskstream */
|
||||||
|
|
||||||
XMLNode* align_node = new XMLNode (X_("alignment"));
|
XMLNode* align_node = new XMLNode (X_("alignment"));
|
||||||
switch (_diskstream->alignment_style()) {
|
AlignStyle as = _diskstream->alignment_style ();
|
||||||
case ExistingMaterial:
|
align_node->add_property (X_("style"), enum_2_string (as));
|
||||||
snprintf (buf, sizeof (buf), X_("existing"));
|
|
||||||
break;
|
|
||||||
case CaptureTime:
|
|
||||||
snprintf (buf, sizeof (buf), X_("capture"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
align_node->add_property (X_("style"), buf);
|
|
||||||
root.add_child_nocopy (*align_node);
|
root.add_child_nocopy (*align_node);
|
||||||
|
|
||||||
XMLNode* remote_control_node = new XMLNode (X_("remote_control"));
|
root.add_property (X_("mode"), enum_2_string (_mode));
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we don't return diskstream state because we don't
|
/* we don't return diskstream state because we don't
|
||||||
own the diskstream exclusively. control of the diskstream
|
own the diskstream exclusively. control of the diskstream
|
||||||
state is ceded to the Session, even if we create the
|
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));
|
_diskstream->id().print (buf, sizeof(buf));
|
||||||
root.add_property ("diskstream-id", buf);
|
root.add_property ("diskstream-id", buf);
|
||||||
|
|
||||||
|
root.add_child_nocopy (_rec_enable_control.get_state());
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
@ -314,7 +291,7 @@ MidiTrack::set_state_part_two ()
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((prop = fnode->property (X_("state"))) != 0) {
|
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;
|
XMLNodeConstIterator citer;
|
||||||
|
|
@ -341,11 +318,21 @@ MidiTrack::set_state_part_two ()
|
||||||
if ((fnode = find_named_node (*pending_state, X_("alignment"))) != 0) {
|
if ((fnode = find_named_node (*pending_state, X_("alignment"))) != 0) {
|
||||||
|
|
||||||
if ((prop = fnode->property (X_("style"))) != 0) {
|
if ((prop = fnode->property (X_("style"))) != 0) {
|
||||||
if (prop->value() == "existing") {
|
|
||||||
_diskstream->set_persistent_align_style (ExistingMaterial);
|
/* fix for older sessions from before EnumWriter */
|
||||||
} else if (prop->value() == "capture") {
|
|
||||||
_diskstream->set_persistent_align_style (CaptureTime);
|
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;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@
|
||||||
#include <ardour/playlist.h>
|
#include <ardour/playlist.h>
|
||||||
#include <ardour/audioplaylist.h>
|
#include <ardour/audioplaylist.h>
|
||||||
#include <ardour/audio_track.h>
|
#include <ardour/audio_track.h>
|
||||||
|
#include <ardour/midi_playlist.h>
|
||||||
|
#include <ardour/midi_track.h>
|
||||||
#include <ardour/tempo.h>
|
#include <ardour/tempo.h>
|
||||||
#include <ardour/audiosource.h>
|
#include <ardour/audiosource.h>
|
||||||
#include <ardour/audioregion.h>
|
#include <ardour/audioregion.h>
|
||||||
|
|
@ -93,11 +95,11 @@ Session::memento_command_factory(XMLNode *n)
|
||||||
return new MementoCommand<Locations>(_locations, before, after);
|
return new MementoCommand<Locations>(_locations, before, after);
|
||||||
} else if (obj_T == typeid (TempoMap).name()) {
|
} else if (obj_T == typeid (TempoMap).name()) {
|
||||||
return new MementoCommand<TempoMap>(*_tempo_map, before, after);
|
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())) {
|
if (boost::shared_ptr<Playlist> pl = playlist_by_name(child->property("name")->value())) {
|
||||||
return new MementoCommand<Playlist>(*(pl.get()), before, after);
|
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);
|
return new MementoCommand<Route>(*route_by_id(id), before, after);
|
||||||
} else if (obj_T == typeid (Curve).name() || obj_T == typeid (AutomationList).name()) {
|
} else if (obj_T == typeid (Curve).name() || obj_T == typeid (AutomationList).name()) {
|
||||||
if (automation_lists.count(id))
|
if (automation_lists.count(id))
|
||||||
|
|
|
||||||
|
|
@ -1110,7 +1110,7 @@ Session::set_state (const XMLNode& node)
|
||||||
|
|
||||||
/* Object loading order:
|
/* Object loading order:
|
||||||
|
|
||||||
MIDI
|
MIDI Control
|
||||||
Path
|
Path
|
||||||
extra
|
extra
|
||||||
Options/Config
|
Options/Config
|
||||||
|
|
@ -1397,7 +1397,6 @@ Session::XMLAudioRegionFactory (const XMLNode& node, bool full)
|
||||||
nchans = atoi (prop->value().c_str());
|
nchans = atoi (prop->value().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((prop = node.property ("name")) == 0) {
|
if ((prop = node.property ("name")) == 0) {
|
||||||
cerr << "no name for this region\n";
|
cerr << "no name for this region\n";
|
||||||
abort ();
|
abort ();
|
||||||
|
|
@ -1461,7 +1460,6 @@ Session::XMLAudioRegionFactory (const XMLNode& node, bool full)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return region;
|
return region;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1477,7 +1475,7 @@ Session::XMLMidiRegionFactory (const XMLNode& node, bool full)
|
||||||
const XMLProperty* prop;
|
const XMLProperty* prop;
|
||||||
boost::shared_ptr<Source> source;
|
boost::shared_ptr<Source> source;
|
||||||
boost::shared_ptr<MidiSource> ms;
|
boost::shared_ptr<MidiSource> ms;
|
||||||
MidiRegion::SourceList sources;
|
SourceList sources;
|
||||||
uint32_t nchans = 1;
|
uint32_t nchans = 1;
|
||||||
|
|
||||||
if (node.name() != X_("Region")) {
|
if (node.name() != X_("Region")) {
|
||||||
|
|
@ -1487,6 +1485,11 @@ Session::XMLMidiRegionFactory (const XMLNode& node, bool full)
|
||||||
if ((prop = node.property (X_("channels"))) != 0) {
|
if ((prop = node.property (X_("channels"))) != 0) {
|
||||||
nchans = atoi (prop->value().c_str());
|
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
|
// Multiple midi channels? that's just crazy talk
|
||||||
assert(nchans == 1);
|
assert(nchans == 1);
|
||||||
|
|
@ -1515,6 +1518,17 @@ Session::XMLMidiRegionFactory (const XMLNode& node, bool full)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
|
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;
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1534,8 +1548,6 @@ Session::get_sources_as_xml ()
|
||||||
node->add_child_nocopy (i->second->get_state());
|
node->add_child_nocopy (i->second->get_state());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX get MIDI and other sources here */
|
|
||||||
|
|
||||||
return *node;
|
return *node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -754,3 +754,33 @@ SMFSource::read_var_len() const
|
||||||
|
|
||||||
return value;
|
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