diff --git a/src-ui/app/editor-impl/SCXTEditorResponseHandlers.cpp b/src-ui/app/editor-impl/SCXTEditorResponseHandlers.cpp index 421a3cb8..71627ca1 100644 --- a/src-ui/app/editor-impl/SCXTEditorResponseHandlers.cpp +++ b/src-ui/app/editor-impl/SCXTEditorResponseHandlers.cpp @@ -422,7 +422,7 @@ void SCXTEditor::onMissingResolutionWorkItemList( { for (const auto &wi : items) { - SCLOG("Missing resolution work item"); + SCLOG("Missing resolution " << (wi.isMultiUsed ? "multi-use " : "") << "work item"); SCLOG(" path : " << wi.path.u8string()); SCLOG(" id : " << wi.missingID.to_string()); } diff --git a/src/engine/missing_resolution.cpp b/src/engine/missing_resolution.cpp index 53d6f21a..a9523d87 100644 --- a/src/engine/missing_resolution.cpp +++ b/src/engine/missing_resolution.cpp @@ -32,7 +32,6 @@ namespace scxt::engine std::vector collectMissingResolutionWorkItems(const Engine &e) { std::vector res; - const auto &sm = e.getSampleManager(); auto it = sm->samplesBegin(); while (it != sm->samplesEnd()) @@ -40,11 +39,125 @@ std::vector collectMissingResolutionWorkItems(const E const auto &[id, s] = *it; if (s->isMissingPlaceholder) { - res.push_back({id, s->mFileName}); + res.push_back({id, s->mFileName, false}); } it++; } + std::sort(res.begin(), res.end(), + [](const auto &a, const auto &b) { return a.path.u8string() < b.path.u8string(); }); + + auto rit = 0; + auto rnext = 1; + while (rnext < res.size()) + { + if (res[rit].missingID.sameMD5As(res[rnext].missingID) && res[rit].path == res[rnext].path) + { + res[rit].isMultiUsed = true; + res.erase(res.begin() + rnext); + } + else + { + rnext++; + rit++; + } + } + return res; } + +void resolveSingleFileMissingWorkItem(engine::Engine &e, const MissingResolutionWorkItem &mwi, + const fs::path &p) +{ + + auto smp = e.getSampleManager()->loadSampleByPath(p); + SCLOG("Resolving : " << p.u8string()); + SCLOG(" Was : " << mwi.missingID.to_string()); + SCLOG(" To : " << smp->to_string()); + if (smp.has_value()) + { + for (auto &p : *(e.getPatch())) + { + for (auto &g : *p) + { + for (auto &z : *g) + { + int vidx{0}; + for (auto &v : z->variantData.variants) + { + if (v.active && v.sampleID == mwi.missingID) + { + SCLOG(" Zone : " << z->getName()); + v.sampleID = *smp; + z->attachToSampleAtVariation( + *(e.getSampleManager()), *smp, vidx, + engine::Zone::SampleInformationRead::ENDPOINTS); + } + vidx++; + } + } + } + } + } +} + +void resolveMultiFileMissingWorkItem(engine::Engine &e, const MissingResolutionWorkItem &mwi, + const fs::path &p) +{ + bool isSF2{false}, isMultiSample{false}; + if (extensionMatches(p, ".sf2")) + { + isSF2 = true; + } + + if (!isSF2 && !isMultiSample) + { + SCLOG("Cant deteremine multi style for " << p.u8string()); + e.getMessageController()->reportErrorToClient( + "Unable to resolve missing with multifile", + "Can't determine the multifile type for path '" + p.u8string() + "''"); + return; + } + + for (auto &pt : *(e.getPatch())) + { + for (auto &g : *pt) + { + for (auto &z : *g) + { + int vidx{0}; + for (auto &v : z->variantData.variants) + { + if (v.active && v.sampleID.sameMD5As(mwi.missingID)) + { + std::optional nid; + if (isSF2) + { + nid = e.getSampleManager()->loadSampleFromSF2( + p, nullptr, v.sampleID.multiAddress[0], v.sampleID.multiAddress[1], + v.sampleID.multiAddress[2]); + } + if (isMultiSample) + { + nid = e.getSampleManager()->loadSampleFromMultiSample( + p, v.sampleID.multiAddress[2], mwi.missingID); + } + if (nid.has_value()) + { + SCLOG("Re-attaching to multi in " << z->getName()); + SCLOG(" Was : " << v.sampleID.to_string()); + SCLOG(" To : " << nid->to_string()); + v.sampleID = *nid; + z->attachToSampleAtVariation( + *(e.getSampleManager()), *nid, vidx, + engine::Zone::SampleInformationRead::ENDPOINTS); + } + } + vidx++; + } + } + } + } +} + } // namespace scxt::engine \ No newline at end of file diff --git a/src/engine/missing_resolution.h b/src/engine/missing_resolution.h index 221bbc92..73d10fc4 100644 --- a/src/engine/missing_resolution.h +++ b/src/engine/missing_resolution.h @@ -37,10 +37,16 @@ struct MissingResolutionWorkItem { SampleID missingID; fs::path path; + bool isMultiUsed{false}; }; std::vector collectMissingResolutionWorkItems(const Engine &e); +void resolveSingleFileMissingWorkItem(engine::Engine &e, const MissingResolutionWorkItem &mwi, + const fs::path &p); + +void resolveMultiFileMissingWorkItem(engine::Engine &e, const MissingResolutionWorkItem &mwi, + const fs::path &p); } // namespace scxt::engine #endif // MISSING_RESOLUTION_H diff --git a/src/json/missing_resolution_traits.h b/src/json/missing_resolution_traits.h index 0f57853f..4b83da0d 100644 --- a/src/json/missing_resolution_traits.h +++ b/src/json/missing_resolution_traits.h @@ -40,13 +40,11 @@ namespace scxt::json { SC_STREAMDEF(scxt::engine::MissingResolutionWorkItem, SC_FROM({ - v = { - {"i", from.missingID}, - {"p", from.path.u8string()}, - }; + v = {{"i", from.missingID}, {"p", from.path.u8string()}, {"m", from.isMultiUsed}}; }), SC_TO({ findIf(v, "i", to.missingID); + findOrSet(v, "m", false, to.isMultiUsed); std::string fp; findIf(v, "p", fp); to.path = fs::path(fs::u8path(fp)); diff --git a/src/messaging/client/missing_resolution_messages.h b/src/messaging/client/missing_resolution_messages.h index 7a04111e..b18f5429 100644 --- a/src/messaging/client/missing_resolution_messages.h +++ b/src/messaging/client/missing_resolution_messages.h @@ -47,34 +47,14 @@ inline void doResolveSample(const resolveSamplePayload_t &payload, engine::Engin { auto mwi = std::get<0>(payload); auto p = fs::path(fs::u8path(std::get<1>(payload))); - auto smp = e.getSampleManager()->loadSampleByPath(p); - SCLOG("Resolving : " << p.u8string()); - SCLOG(" Was : " << mwi.missingID.to_string()); - SCLOG(" To : " << smp->to_string()); - if (smp.has_value()) + + if (mwi.isMultiUsed) + { + engine::resolveMultiFileMissingWorkItem(e, mwi, p); + } + else { - for (auto &p : *(e.getPatch())) - { - for (auto &g : *p) - { - for (auto &z : *g) - { - int vidx{0}; - for (auto &v : z->variantData.variants) - { - if (v.active && v.sampleID == mwi.missingID) - { - SCLOG(" Zone : " << z->getName()); - v.sampleID = *smp; - z->attachToSampleAtVariation( - *(e.getSampleManager()), *smp, vidx, - engine::Zone::SampleInformationRead::ENDPOINTS); - } - vidx++; - } - } - } - } + engine::resolveSingleFileMissingWorkItem(e, mwi, p); } e.getSampleManager()->purgeUnreferencedSamples(); e.sendFullRefreshToClient(); diff --git a/src/sample/sample_manager.cpp b/src/sample/sample_manager.cpp index 781894a5..8751ac6f 100644 --- a/src/sample/sample_manager.cpp +++ b/src/sample/sample_manager.cpp @@ -64,6 +64,8 @@ void SampleManager::restoreFromSampleAddressesAndIDs(const sampleAddressesAndIds nid = loadSampleFromMultiSample(addr.path, addr.region, id); } break; + // add something here? don't forget to add it in the multi resolver too in + // resolveSingleFileMissingWorkItem } if (nid.has_value()) diff --git a/src/utils.h b/src/utils.h index 3e5e866f..38f1c8c3 100644 --- a/src/utils.h +++ b/src/utils.h @@ -123,6 +123,8 @@ struct SampleID bool isValid() const { return md5[0] != 'x' && md5[1] != '\0'; } + bool sameMD5As(const SampleID &other) const { return strncmp(md5, other.md5, md5len) == 0; } + void setAsInvalid() { memset(md5, 0, sizeof(md5));