diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2006-10-31 18:08:16 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2006-10-31 18:08:16 +0000 |
commit | 1987df571c861e89fa96dd1622bdc9908d0d768d (patch) | |
tree | 4b84b575c35d9fec0e67f47b7c0b0d80808313c5 | |
parent | 8856a12bb89d78461b3d9ae384e9efc1bc64e4d6 (diff) |
support for old-school automation loading
git-svn-id: svn://localhost/ardour2/trunk@1039 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r-- | libs/ardour/ardour/automation_event.h | 3 | ||||
-rw-r--r-- | libs/ardour/ardour/io.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/panner.h | 23 | ||||
-rw-r--r-- | libs/ardour/ardour/redirect.h | 5 | ||||
-rw-r--r-- | libs/ardour/io.cc | 83 | ||||
-rw-r--r-- | libs/ardour/panner.cc | 132 | ||||
-rw-r--r-- | libs/ardour/redirect.cc | 78 | ||||
-rw-r--r-- | libs/ardour/route.cc | 48 | ||||
-rw-r--r-- | libs/ardour/sndfilesource.cc | 8 |
9 files changed, 350 insertions, 31 deletions
diff --git a/libs/ardour/ardour/automation_event.h b/libs/ardour/ardour/automation_event.h index 24d73faaa4..459ec2b6cf 100644 --- a/libs/ardour/ardour/automation_event.h +++ b/libs/ardour/ardour/automation_event.h @@ -86,6 +86,8 @@ class AutomationList : public PBD::StatefulDestructible void reposition_for_rt_add (double when); void rt_add (double when, double value); void add (double when, double value); + /* this should be private but old-school automation loading needs it in IO/Redirect */ + void fast_simple_add (double when, double value); void reset_range (double start, double end); void erase_range (double start, double end); @@ -211,7 +213,6 @@ class AutomationList : public PBD::StatefulDestructible iterator rt_insertion_point; double rt_pos; - void fast_simple_add (double when, double value); void maybe_signal_changed (); void mark_dirty (); void _x_scale (double factor); diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index 2783ee4140..3090e21310 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -313,6 +313,7 @@ public: virtual int set_automation_state (const XMLNode&); virtual XMLNode& get_automation_state (); + virtual int load_automation (std::string path); /* AudioTrack::deprecated_use_diskstream_connections() needs these */ diff --git a/libs/ardour/ardour/panner.h b/libs/ardour/ardour/panner.h index 47e30e43d7..32d512c253 100644 --- a/libs/ardour/ardour/panner.h +++ b/libs/ardour/ardour/panner.h @@ -91,6 +91,10 @@ class StreamPanner : public sigc::trackable, public Stateful Panner & get_parent() { return parent; } + /* old school automation loading */ + + virtual int load (istream&, string path, uint32_t&) = 0; + protected: friend class Panner; Panner& parent; @@ -146,6 +150,10 @@ class BaseStereoPanner : public StreamPanner Curve& automation() { return _automation; } + /* old school automation loading */ + + int load (istream&, string path, uint32_t&); + protected: float left; float right; @@ -208,6 +216,10 @@ class Multi2dPanner : public StreamPanner XMLNode& get_state (void); int set_state (const XMLNode&); + /* old school automation loading */ + + int load (istream&, string path, uint32_t&); + private: Curve _automation; void update (); @@ -285,7 +297,11 @@ class Panner : public std::vector<StreamPanner*>, public Stateful, public sigc:: void set_position (float x, StreamPanner& orig); void set_position (float x, float y, StreamPanner& orig); void set_position (float x, float y, float z, StreamPanner& orig); - + + /* old school automation */ + + int load (); + private: Session& _session; @@ -295,6 +311,11 @@ class Panner : public std::vector<StreamPanner*>, public Stateful, public sigc:: LinkDirection _link_direction; static float current_automation_version_number; + + /* old school automation handling */ + + std::string automation_path; + void set_name (std::string); }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/redirect.h b/libs/ardour/ardour/redirect.h index ccfd8590b2..847b9b8c13 100644 --- a/libs/ardour/ardour/redirect.h +++ b/libs/ardour/ardour/redirect.h @@ -127,12 +127,15 @@ class Redirect : public IO int set_automation_state (const XMLNode&); XMLNode& get_automation_state (); - + private: bool _active; Placement _placement; uint32_t _sort_key; void* _gui; /* generic, we don't know or care what this is */ + + int old_set_automation_state (const XMLNode&); + int load_automation (std::string path); }; } // namespace ARDOUR diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index 02adc3d53d..0804369b94 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -1425,6 +1425,7 @@ int IO::panners_became_legal () { _panner->reset (_noutputs, pans_required()); + _panner->load (); // automation panner_legal_c.disconnect (); return 0; } @@ -1611,6 +1612,10 @@ IO::set_state (const XMLNode& node) _gain = _desired_gain; } + if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) { + /* old school automation handling */ + } + for (iter = node.children().begin(); iter != node.children().end(); ++iter) { if ((*iter)->name() == "Panner") { @@ -1680,6 +1685,84 @@ IO::get_automation_state () } int +IO::load_automation (string path) +{ + string fullpath; + ifstream in; + char line[128]; + uint32_t linecnt = 0; + float version; + LocaleGuard lg (X_("POSIX")); + + fullpath = _session.automation_dir(); + fullpath += path; + + in.open (fullpath.c_str()); + + if (!in) { + fullpath = _session.automation_dir(); + fullpath += _session.snap_name(); + fullpath += '-'; + fullpath += path; + + in.open (fullpath.c_str()); + + if (!in) { + error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg; + return -1; + } + } + + clear_automation (); + + while (in.getline (line, sizeof(line), '\n')) { + char type; + jack_nframes_t when; + double value; + + if (++linecnt == 1) { + if (memcmp (line, "version", 7) == 0) { + if (sscanf (line, "version %f", &version) != 1) { + error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg; + return -1; + } + } else { + error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg; + return -1; + } + + continue; + } + + if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) { + warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg; + continue; + } + + switch (type) { + case 'g': + _gain_automation_curve.fast_simple_add (when, value); + break; + + case 's': + break; + + case 'm': + break; + + case 'p': + /* older (pre-1.0) versions of ardour used this */ + break; + + default: + warning << _("dubious automation event found (and ignored)") << endmsg; + } + } + + return 0; +} + +int IO::connecting_became_legal () { int ret; diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc index 306757297d..00b31f314d 100644 --- a/libs/ardour/panner.cc +++ b/libs/ardour/panner.cc @@ -231,6 +231,39 @@ BaseStereoPanner::set_automation_state (AutoState state) } } +int +BaseStereoPanner::load (istream& in, string path, uint32_t& linecnt) +{ + char line[128]; + LocaleGuard lg (X_("POSIX")); + + _automation.clear (); + + while (in.getline (line, sizeof (line), '\n')) { + jack_nframes_t when; + double value; + + ++linecnt; + + if (strcmp (line, "end") == 0) { + break; + } + + if (sscanf (line, "%" PRIu32 " %lf", &when, &value) != 2) { + warning << string_compose(_("badly formatted pan automation event record at line %1 of %2 (ignored) [%3]"), linecnt, path, line) << endmsg; + continue; + } + + _automation.fast_simple_add (when, value); + } + + /* now that we are done loading */ + + _automation.StateChanged (Change (0)); + + return 0; +} + void BaseStereoPanner::distribute (Sample* src, Sample** obufs, gain_t gain_coeff, nframes_t nframes) { @@ -676,6 +709,12 @@ Multi2dPanner::factory (Panner& p) return new Multi2dPanner (p); } +int +Multi2dPanner::load (istream& in, string path, uint32_t& linecnt) +{ + return 0; +} + XMLNode& Multi2dPanner::get_state (void) { @@ -733,6 +772,8 @@ Multi2dPanner::set_state (const XMLNode& node) Panner::Panner (string name, Session& s) : _session (s) { + set_name (name); + _linked = false; _link_direction = SameDirection; _bypassed = false; @@ -1121,6 +1162,16 @@ Panner::set_state (const XMLNode& node) } } + /* don't try to do old-school automation loading if it wasn't marked as existing */ + + if ((prop = node.property (X_("automation")))) { + + /* automation path is relative */ + + automation_path = _session.automation_dir(); + automation_path += prop->value (); + } + return 0; } @@ -1280,3 +1331,84 @@ Panner::set_position (float xpos, float ypos, float zpos, StreamPanner& orig) } } } + +/* old school automation handling */ + +void +Panner::set_name (string str) +{ + automation_path = _session.automation_dir(); + automation_path += _session.snap_name(); + automation_path += "-pan-"; + automation_path += legalize_for_path (str); + automation_path += ".automation"; +} + +int +Panner::load () +{ + char line[128]; + uint32_t linecnt = 0; + float version; + iterator sp; + LocaleGuard lg (X_("POSIX")); + + if (automation_path.length() == 0) { + return 0; + } + + if (access (automation_path.c_str(), F_OK)) { + return 0; + } + + ifstream in (automation_path.c_str()); + + if (!in) { + error << string_compose (_("cannot open pan automation file %1 (%2)"), + automation_path, strerror (errno)) + << endmsg; + return -1; + } + + sp = begin(); + + while (in.getline (line, sizeof(line), '\n')) { + + if (++linecnt == 1) { + if (memcmp (line, X_("version"), 7) == 0) { + if (sscanf (line, "version %f", &version) != 1) { + error << string_compose(_("badly formed version number in pan automation event file \"%1\""), automation_path) << endmsg; + return -1; + } + } else { + error << string_compose(_("no version information in pan automation event file \"%1\" (first line = %2)"), + automation_path, line) << endmsg; + return -1; + } + + continue; + } + + if (strlen (line) == 0 || line[0] == '#') { + continue; + } + + if (strcmp (line, "begin") == 0) { + + if (sp == end()) { + error << string_compose (_("too many panner states found in pan automation file %1"), + automation_path) + << endmsg; + return -1; + } + + if ((*sp)->load (in, automation_path, linecnt)) { + return -1; + } + + ++sp; + } + } + + return 0; +} diff --git a/libs/ardour/redirect.cc b/libs/ardour/redirect.cc index 5623e5d510..0f3e9adce3 100644 --- a/libs/ardour/redirect.cc +++ b/libs/ardour/redirect.cc @@ -244,10 +244,11 @@ Redirect::set_state (const XMLNode& node) } else if ((*niter)->name() == X_("Automation")) { + XMLProperty *prop; if ((prop = (*niter)->property ("path")) != 0) { - warning << string_compose (_("old automation data found for %1, ignored"), _name) << endmsg; + old_set_automation_state (*(*niter)); } else { set_automation_state (*(*niter)); } @@ -298,6 +299,81 @@ Redirect::set_state (const XMLNode& node) return 0; } +int +Redirect::old_set_automation_state (const XMLNode& node) +{ + const XMLProperty *prop; + + if ((prop = node.property ("path")) != 0) { + load_automation (prop->value()); + } else { + warning << string_compose(_("%1: Automation node has no path property"), _name) << endmsg; + } + + if ((prop = node.property ("visible")) != 0) { + uint32_t what; + stringstream sstr; + + visible_parameter_automation.clear (); + + sstr << prop->value(); + while (1) { + sstr >> what; + if (sstr.fail()) { + break; + } + mark_automation_visible (what, true); + } + } + + return 0; +} + +int +Redirect::load_automation (string path) +{ + string fullpath; + + if (path[0] == '/') { // legacy + fullpath = path; + } else { + fullpath = _session.automation_dir(); + fullpath += path; + } + ifstream in (fullpath.c_str()); + + if (!in) { + warning << string_compose(_("%1: cannot open %2 to load automation data (%3)"), _name, fullpath, strerror (errno)) << endmsg; + return 1; + } + + Glib::Mutex::Lock lm (_automation_lock); + set<uint32_t> tosave; + parameter_automation.clear (); + + while (in) { + double when; + double value; + uint32_t port; + + in >> port; if (!in) break; + in >> when; if (!in) goto bad; + in >> value; if (!in) goto bad; + + AutomationList& al = automation_list (port); + al.add (when, value); + tosave.insert (port); + } + + return 0; + + bad: + error << string_compose(_("%1: cannot load automation data from %2"), _name, fullpath) << endmsg; + parameter_automation.clear (); + return -1; +} + + void Redirect::what_has_automation (set<uint32_t>& s) const { diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index b204ad76dc..10505053f9 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -1499,7 +1499,7 @@ Route::_set_state (const XMLNode& node, bool call_base) return -1; } - if ((prop = node.property ("flags")) != 0) { + if ((prop = node.property (X_("flags"))) != 0) { int x; sscanf (prop->value().c_str(), "0x%x", &x); _flags = Flag (x); @@ -1507,20 +1507,20 @@ Route::_set_state (const XMLNode& node, bool call_base) _flags = Flag (0); } - if ((prop = node.property ("default-type")) != 0) { + if ((prop = node.property (X_("default-type"))) != 0) { _default_type = DataType(prop->value()); assert(_default_type != DataType::NIL); } - if ((prop = node.property ("phase-invert")) != 0) { + if ((prop = node.property (X_("phase-invert"))) != 0) { set_phase_invert(prop->value()=="yes"?true:false, this); } - if ((prop = node.property ("active")) != 0) { + if ((prop = node.property (X_("active"))) != 0) { set_active (prop->value() == "yes"); } - if ((prop = node.property ("muted")) != 0) { + if ((prop = node.property (X_("muted"))) != 0) { bool yn = prop->value()=="yes"?true:false; /* force reset of mute status */ @@ -1530,7 +1530,7 @@ Route::_set_state (const XMLNode& node, bool call_base) mute_gain = desired_mute_gain; } - if ((prop = node.property ("soloed")) != 0) { + if ((prop = node.property (X_("soloed"))) != 0) { bool yn = prop->value()=="yes"?true:false; /* force reset of solo status */ @@ -1540,23 +1540,23 @@ Route::_set_state (const XMLNode& node, bool call_base) solo_gain = desired_solo_gain; } - if ((prop = node.property ("mute-affects-pre-fader")) != 0) { + if ((prop = node.property (X_("mute-affects-pre-fader"))) != 0) { _mute_affects_pre_fader = (prop->value()=="yes")?true:false; } - if ((prop = node.property ("mute-affects-post-fader")) != 0) { + if ((prop = node.property (X_("mute-affects-post-fader"))) != 0) { _mute_affects_post_fader = (prop->value()=="yes")?true:false; } - if ((prop = node.property ("mute-affects-control-outs")) != 0) { + if ((prop = node.property (X_("mute-affects-control-outs"))) != 0) { _mute_affects_control_outs = (prop->value()=="yes")?true:false; } - if ((prop = node.property ("mute-affects-main-outs")) != 0) { + if ((prop = node.property (X_("mute-affects-main-outs"))) != 0) { _mute_affects_main_outs = (prop->value()=="yes")?true:false; } - if ((prop = node.property ("edit-group")) != 0) { + if ((prop = node.property (X_("edit-group"))) != 0) { RouteGroup* edit_group = _session.edit_group_by_name(prop->value()); if(edit_group == 0) { error << string_compose(_("Route %1: unknown edit group \"%2 in saved state (ignored)"), _name, prop->value()) << endmsg; @@ -1565,7 +1565,7 @@ Route::_set_state (const XMLNode& node, bool call_base) } } - if ((prop = node.property ("order-keys")) != 0) { + if ((prop = node.property (X_("order-keys"))) != 0) { long n; @@ -1602,7 +1602,7 @@ Route::_set_state (const XMLNode& node, bool call_base) delete deferred_state; } - deferred_state = new XMLNode("deferred state"); + deferred_state = new XMLNode(X_("deferred state")); /* set parent class properties before anything else */ @@ -1621,7 +1621,7 @@ Route::_set_state (const XMLNode& node, bool call_base) child = *niter; - if (child->name() == "Send") { + if (child->name() == X_("Send")) { if (!IO::ports_legal) { @@ -1632,7 +1632,7 @@ Route::_set_state (const XMLNode& node, bool call_base) add_redirect_from_xml (*child); } - } else if (child->name() == "Insert") { + } else if (child->name() == X_("Insert")) { if (!IO::ports_legal) { @@ -1643,7 +1643,13 @@ Route::_set_state (const XMLNode& node, bool call_base) add_redirect_from_xml (*child); } - } else if (child->name() == "ControlOuts") { + } else if (child->name() == X_("Automation")) { + + if ((prop = child->property (X_("path"))) != 0) { + load_automation (prop->value()); + } + + } else if (child->name() == X_("ControlOuts")) { string coutname = _name; coutname += _("[control]"); @@ -1651,25 +1657,25 @@ Route::_set_state (const XMLNode& node, bool call_base) _control_outs = new IO (_session, coutname); _control_outs->set_state (**(child->children().begin())); - } else if (child->name() == "Comment") { + } else if (child->name() == X_("Comment")) { /* XXX this is a terrible API design in libxml++ */ XMLNode *cmt = *(child->children().begin()); _comment = cmt->content(); - } else if (child->name() == "extra") { + } else if (child->name() == X_("extra")) { _extra_xml = new XMLNode (*child); - } else if (child->name() == "solo") { + } else if (child->name() == X_("solo")) { _solo_control.set_state (*child); _session.add_controllable (&_solo_control); - } else if (child->name() == "mute") { + } else if (child->name() == X_("mute")) { _mute_control.set_state (*child); _session.add_controllable (&_mute_control); } } - if ((prop = node.property ("mix-group")) != 0) { + if ((prop = node.property (X_("mix-group"))) != 0) { RouteGroup* mix_group = _session.mix_group_by_name(prop->value()); if (mix_group == 0) { error << string_compose(_("Route %1: unknown mix group \"%2 in saved state (ignored)"), _name, prop->value()) << endmsg; diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc index 5e6f512e53..cb4334c7cb 100644 --- a/libs/ardour/sndfilesource.cc +++ b/libs/ardour/sndfilesource.cc @@ -507,14 +507,10 @@ SndFileSource::set_header_timeline_position () nframes_t SndFileSource::write_float (Sample* data, nframes_t frame_pos, nframes_t cnt) { - nframes_t where; - - where = sf_seek (sf, frame_pos, SEEK_SET|SFM_WRITE); - - if (where != frame_pos) { + if (sf_seek (sf, frame_pos, SEEK_SET|SFM_WRITE) < 0) { char errbuf[256]; sf_error_str (0, errbuf, sizeof (errbuf) - 1); - error << string_compose (_("%1: cannot seek to %2, now at %3 (libsndfile error: %4"), _path, frame_pos, where, errbuf) << endmsg; + error << string_compose (_("%1: cannot seek to %2 (libsndfile error: %3"), _path, frame_pos, errbuf) << endmsg; return 0; } |