Merge pull request #614 from jpcima/reloading
Avoid reloading invalid files in a loop
This commit is contained in:
commit
872bc69b1c
4 changed files with 52 additions and 29 deletions
|
|
@ -35,6 +35,9 @@
|
||||||
|
|
||||||
namespace sfz {
|
namespace sfz {
|
||||||
|
|
||||||
|
// unless set to permissive, the loader rejects sfz files with errors
|
||||||
|
static constexpr bool loaderParsesPermissively = true;
|
||||||
|
|
||||||
Synth::Synth()
|
Synth::Synth()
|
||||||
: impl_(new Impl) // NOLINT: (paul) I don't get why clang-tidy complains here
|
: impl_(new Impl) // NOLINT: (paul) I don't get why clang-tidy complains here
|
||||||
{
|
{
|
||||||
|
|
@ -252,7 +255,7 @@ void Synth::Impl::clear()
|
||||||
masterOpcodes_.clear();
|
masterOpcodes_.clear();
|
||||||
groupOpcodes_.clear();
|
groupOpcodes_.clear();
|
||||||
unknownOpcodes_.clear();
|
unknownOpcodes_.clear();
|
||||||
modificationTime_ = fs::file_time_type::min();
|
modificationTime_ = absl::nullopt;
|
||||||
|
|
||||||
// set default controllers
|
// set default controllers
|
||||||
// midistate is reset above
|
// midistate is reset above
|
||||||
|
|
@ -493,18 +496,22 @@ bool Synth::loadSfzFile(const fs::path& file)
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
fs::path realFile = fs::canonical(file, ec);
|
fs::path realFile = fs::canonical(file, ec);
|
||||||
|
|
||||||
impl.parser_.parseFile(ec ? file : realFile);
|
bool success = true;
|
||||||
|
Parser& parser = impl.parser_;
|
||||||
|
parser.parseFile(ec ? file : realFile);
|
||||||
|
|
||||||
// permissive parsing for compatibility
|
// permissive parsing for compatibility
|
||||||
if (false) {
|
if (!loaderParsesPermissively)
|
||||||
if (impl.parser_.getErrorCount() > 0)
|
success = parser.getErrorCount() == 0;
|
||||||
return false;
|
|
||||||
|
success = success && !impl.regions_.empty();
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
parser.clear();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (impl.regions_.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
impl.finalizeSfzLoad();
|
impl.finalizeSfzLoad();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -515,18 +522,22 @@ bool Synth::loadSfzString(const fs::path& path, absl::string_view text)
|
||||||
|
|
||||||
impl.clear();
|
impl.clear();
|
||||||
|
|
||||||
impl.parser_.parseString(path, text);
|
bool success = true;
|
||||||
|
Parser& parser = impl.parser_;
|
||||||
|
parser.parseString(path, text);
|
||||||
|
|
||||||
// permissive parsing for compatibility
|
// permissive parsing for compatibility
|
||||||
if (false) {
|
if (!loaderParsesPermissively)
|
||||||
if (impl.parser_.getErrorCount() > 0)
|
success = parser.getErrorCount() == 0;
|
||||||
return false;
|
|
||||||
|
success = success && !impl.regions_.empty();
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
parser.clear();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (impl.regions_.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
impl.finalizeSfzLoad();
|
impl.finalizeSfzLoad();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1668,22 +1679,33 @@ void Synth::Impl::resetAllControllers(int delay) noexcept
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::file_time_type Synth::Impl::checkModificationTime()
|
absl::optional<fs::file_time_type> Synth::Impl::checkModificationTime() const
|
||||||
{
|
{
|
||||||
auto returnedTime = modificationTime_;
|
absl::optional<fs::file_time_type> resultTime;
|
||||||
for (const auto& file : parser_.getIncludedFiles()) {
|
for (const auto& file : parser_.getIncludedFiles()) {
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
const auto fileTime = fs::last_write_time(file, ec);
|
const auto fileTime = fs::last_write_time(file, ec);
|
||||||
if (!ec && returnedTime < fileTime)
|
if (!ec) {
|
||||||
returnedTime = fileTime;
|
if (!resultTime || fileTime > *resultTime)
|
||||||
|
resultTime = fileTime;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return returnedTime;
|
return resultTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Synth::shouldReloadFile()
|
bool Synth::shouldReloadFile()
|
||||||
{
|
{
|
||||||
Impl& impl = *impl_;
|
Impl& impl = *impl_;
|
||||||
return (impl.checkModificationTime() > impl.modificationTime_);
|
|
||||||
|
absl::optional<fs::file_time_type> then = impl.modificationTime_;
|
||||||
|
if (!then) // file not loaded or failed
|
||||||
|
return false;
|
||||||
|
|
||||||
|
absl::optional<fs::file_time_type> now = impl.checkModificationTime();
|
||||||
|
if (!now) // file not currently existing
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return *now > *then;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Synth::shouldReloadScala()
|
bool Synth::shouldReloadScala()
|
||||||
|
|
|
||||||
|
|
@ -110,9 +110,9 @@ struct Synth::Impl final: public Parser::Listener {
|
||||||
/**
|
/**
|
||||||
* @brief Get the modification time of all included sfz files
|
* @brief Get the modification time of all included sfz files
|
||||||
*
|
*
|
||||||
* @return fs::file_time_type
|
* @return absl::optional<fs::file_time_type>
|
||||||
*/
|
*/
|
||||||
fs::file_time_type checkModificationTime();
|
absl::optional<fs::file_time_type> checkModificationTime() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check all regions and start voices for note on events
|
* @brief Check all regions and start voices for note on events
|
||||||
|
|
@ -277,7 +277,7 @@ struct Synth::Impl final: public Parser::Listener {
|
||||||
std::chrono::time_point<std::chrono::high_resolution_clock> lastGarbageCollection_;
|
std::chrono::time_point<std::chrono::high_resolution_clock> lastGarbageCollection_;
|
||||||
|
|
||||||
Parser parser_;
|
Parser parser_;
|
||||||
fs::file_time_type modificationTime_ { };
|
absl::optional<fs::file_time_type> modificationTime_ { };
|
||||||
|
|
||||||
std::array<float, config::numCCs> defaultCCValues_;
|
std::array<float, config::numCCs> defaultCCValues_;
|
||||||
std::bitset<config::numCCs> currentUsedCCs_;
|
std::bitset<config::numCCs> currentUsedCCs_;
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ Parser::~Parser()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::reset()
|
void Parser::clear()
|
||||||
{
|
{
|
||||||
_pathsIncluded.clear();
|
_pathsIncluded.clear();
|
||||||
_currentDefinitions = _externalDefinitions;
|
_currentDefinitions = _externalDefinitions;
|
||||||
|
|
@ -51,7 +51,7 @@ void Parser::parseString(const fs::path& path, absl::string_view sfzView)
|
||||||
|
|
||||||
void Parser::parseVirtualFile(const fs::path& path, std::unique_ptr<Reader> reader)
|
void Parser::parseVirtualFile(const fs::path& path, std::unique_ptr<Reader> reader)
|
||||||
{
|
{
|
||||||
reset();
|
clear();
|
||||||
|
|
||||||
if (_listener)
|
if (_listener)
|
||||||
_listener->onParseBegin();
|
_listener->onParseBegin();
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ public:
|
||||||
Parser();
|
Parser();
|
||||||
~Parser();
|
~Parser();
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
void addExternalDefinition(absl::string_view id, absl::string_view value);
|
void addExternalDefinition(absl::string_view id, absl::string_view value);
|
||||||
void clearExternalDefinitions();
|
void clearExternalDefinitions();
|
||||||
|
|
||||||
|
|
@ -71,7 +73,6 @@ private:
|
||||||
void processDirective();
|
void processDirective();
|
||||||
void processHeader();
|
void processHeader();
|
||||||
void processOpcode();
|
void processOpcode();
|
||||||
void reset();
|
|
||||||
|
|
||||||
// errors and warnings
|
// errors and warnings
|
||||||
void emitError(const SourceRange& range, const std::string& message);
|
void emitError(const SourceRange& range, const std::string& message);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue