Mechanism for case-sensitivity on Unix-style OS, integration code by @paulfd
This commit is contained in:
parent
fe6cc016d7
commit
06755812db
5 changed files with 100 additions and 8 deletions
|
|
@ -31,6 +31,7 @@
|
|||
#include "Oversampler.h"
|
||||
#include "AtomicGuard.h"
|
||||
#include "absl/types/span.h"
|
||||
#include "absl/strings/match.h"
|
||||
#include <memory>
|
||||
#include <sndfile.hh>
|
||||
#include <thread>
|
||||
|
|
@ -105,11 +106,65 @@ sfz::FilePool::~FilePool()
|
|||
thread.join();
|
||||
}
|
||||
|
||||
bool sfz::FilePool::checkSample(std::string& filename) const noexcept
|
||||
{
|
||||
fs::path path { rootDirectory / filename };
|
||||
std::error_code ec;
|
||||
if (fs::exists(path, ec))
|
||||
return true;
|
||||
|
||||
fs::path oldPath = std::move(path);
|
||||
path = oldPath.root_path();
|
||||
|
||||
static const fs::path dot { "." };
|
||||
static const fs::path dotdot { ".." };
|
||||
|
||||
for (const fs::path &part : oldPath.relative_path()) {
|
||||
if (part == dot || part == dotdot) {
|
||||
path /= part;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fs::exists(path / part, ec)) {
|
||||
path /= part;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto it = path.empty() ? fs::directory_iterator{ dot, ec } : fs::directory_iterator{ path, ec };
|
||||
if (ec) {
|
||||
DBG("Error creating a directory iterator for " << filename << " (Error code: " << ec.message() << ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto searchPredicate = [&part](const fs::directory_entry &ent) -> bool {
|
||||
return absl::EqualsIgnoreCase(
|
||||
ent.path().filename().native(), part.native());
|
||||
};
|
||||
|
||||
while (it != fs::directory_iterator{} && !searchPredicate(*it))
|
||||
it.increment(ec);
|
||||
|
||||
if (it == fs::directory_iterator{}) {
|
||||
DBG("File not found, could not resolve " << filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
path /= it->path().filename();
|
||||
}
|
||||
|
||||
const auto newPath = fs::relative(path, rootDirectory, ec);
|
||||
if (ec) {
|
||||
DBG("Error extracting the new relative path for " << filename << " (Error code: " << ec.message() << ")");
|
||||
return false;
|
||||
}
|
||||
DBG("Updating " << filename << " to " << newPath.native());
|
||||
filename = newPath.string();
|
||||
return true;
|
||||
}
|
||||
|
||||
absl::optional<sfz::FilePool::FileInformation> sfz::FilePool::getFileInformation(const std::string& filename) noexcept
|
||||
{
|
||||
fs::path file { rootDirectory / filename };
|
||||
if (!fs::exists(file))
|
||||
return {};
|
||||
|
||||
SndfileHandle sndFile(file.string().c_str());
|
||||
if (sndFile.channels() != 1 && sndFile.channels() != 2) {
|
||||
|
|
@ -135,6 +190,7 @@ absl::optional<sfz::FilePool::FileInformation> sfz::FilePool::getFileInformation
|
|||
bool sfz::FilePool::preloadFile(const std::string& filename, uint32_t maxOffset) noexcept
|
||||
{
|
||||
fs::path file { rootDirectory / filename };
|
||||
|
||||
if (!fs::exists(file))
|
||||
return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -157,6 +157,15 @@ public:
|
|||
*/
|
||||
bool preloadFile(const std::string& filename, uint32_t maxOffset) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Check that the sample exists. If not, try to find it in a case insensitive way.
|
||||
*
|
||||
* @param filename the sample filename; may be updated by the method
|
||||
* @return true if the sample exists or was updated properly
|
||||
* @return false if no sample was found even with a case insensitive search
|
||||
*/
|
||||
bool checkSample(std::string& filename) const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Clear all preloaded files.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -224,17 +224,30 @@ bool sfz::Synth::loadSfzFile(const fs::path& file)
|
|||
|
||||
auto currentRegion = regions.begin();
|
||||
auto lastRegion = regions.rbegin();
|
||||
auto removeCurrentRegion = [¤tRegion, &lastRegion]() {
|
||||
if (currentRegion->get() == nullptr)
|
||||
return;
|
||||
|
||||
DBG("Removing the region with sample " << currentRegion->get()->sample);
|
||||
std::iter_swap(currentRegion, lastRegion);
|
||||
++lastRegion;
|
||||
};
|
||||
|
||||
while (currentRegion < lastRegion.base()) {
|
||||
auto region = currentRegion->get();
|
||||
|
||||
if (!region->isGenerator()) {
|
||||
auto fileInformation = resources.filePool.getFileInformation(region->sample);
|
||||
if (!fileInformation) {
|
||||
DBG("Removing the region with sample " << region->sample);
|
||||
std::iter_swap(currentRegion, lastRegion);
|
||||
++lastRegion;
|
||||
if (!resources.filePool.checkSample(region->sample)) {
|
||||
removeCurrentRegion();
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto fileInformation = resources.filePool.getFileInformation(region->sample);
|
||||
if (!fileInformation) {
|
||||
removeCurrentRegion();
|
||||
continue;
|
||||
}
|
||||
|
||||
region->sampleEnd = std::min(region->sampleEnd, fileInformation->end);
|
||||
|
||||
if (fileInformation->loopBegin != Default::loopRange.getStart() &&
|
||||
|
|
@ -254,7 +267,8 @@ bool sfz::Synth::loadSfzFile(const fs::path& file)
|
|||
|
||||
// TODO: adjust with LFO targets
|
||||
const auto maxOffset { region->offset + region->offsetRandom };
|
||||
resources.filePool.preloadFile(region->sample, maxOffset);
|
||||
if (!resources.filePool.preloadFile(region->sample, maxOffset))
|
||||
removeCurrentRegion();
|
||||
}
|
||||
|
||||
for (auto note = 0; note < 128; note++) {
|
||||
|
|
|
|||
|
|
@ -483,3 +483,13 @@ TEST_CASE("[Files] Looped regions taken from files and possibly overriden")
|
|||
REQUIRE( synth.getRegionView(1)->loopRange == sfz::Range<uint32_t>{ 77554, 186582 } );
|
||||
REQUIRE( synth.getRegionView(2)->loopRange == sfz::Range<uint32_t>{ 4, 124 } );
|
||||
}
|
||||
|
||||
TEST_CASE("[Files] Case sentitiveness")
|
||||
{
|
||||
sfz::Synth synth;
|
||||
synth.loadSfzFile(fs::current_path() / "tests/TestFiles/case_insensitive.sfz");
|
||||
REQUIRE(synth.getNumRegions() == 3);
|
||||
REQUIRE(synth.getRegionView(0)->sample == "dummy1.wav");
|
||||
REQUIRE(synth.getRegionView(1)->sample == "Regions/dummy.wav");
|
||||
REQUIRE(synth.getRegionView(2)->sample == "Regions/dummy.wav");
|
||||
}
|
||||
|
|
|
|||
3
tests/TestFiles/case_insensitive.sfz
Normal file
3
tests/TestFiles/case_insensitive.sfz
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<region> key=61 sample=Dummy1.wav
|
||||
<region> key=61 sample=REGIONS/Dummy.wav
|
||||
<region> key=61 sample=REGIonS\Dummy.wav
|
||||
Loading…
Add table
Reference in a new issue