mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-30 10:27:44 +01:00
support for old-school automation loading
git-svn-id: svn://localhost/ardour2/trunk@1039 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
8856a12bb8
commit
1987df571c
9 changed files with 350 additions and 31 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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") {
|
||||
|
|
@ -1679,6 +1684,84 @@ IO::get_automation_state ()
|
|||
return (_gain_automation_curve.get_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 ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue