diff --git a/src/DirManager.cpp b/src/DirManager.cpp index 5889cfd7b..526c3c164 100644 --- a/src/DirManager.cpp +++ b/src/DirManager.cpp @@ -86,9 +86,6 @@ #endif #include "FileNames.h" -#include "blockfile/LegacyBlockFile.h" -#include "blockfile/LegacyAliasBlockFile.h" -#include "blockfile/SilentBlockFile.h" #include "blockfile/ODPCMAliasBlockFile.h" #include "blockfile/ODDecodeBlockFile.h" #include "InconsistencyException.h" @@ -98,8 +95,6 @@ #include "widgets/ErrorDialog.h" #include "widgets/ProgressDialog.h" -#include "ondemand/ODManager.h" - #if defined(__WXMAC__) #include #include @@ -1340,6 +1335,24 @@ BlockFilePtr DirManager::CopyBlockFile(const BlockFilePtr &b) return b2; } +namespace { + +using Deserializers = + std::unordered_map< wxString, DirManager::BlockFileDeserializer >; +Deserializers &GetDeserializers() +{ + static Deserializers sDeserializers; + return sDeserializers; +} + +} + +DirManager::RegisteredBlockFileDeserializer::RegisteredBlockFileDeserializer( + const wxString &tag, BlockFileDeserializer function ) +{ + GetDeserializers()[tag] = function; +} + bool DirManager::HandleXMLTag(const wxChar *tag, const wxChar **attrs) { if( !mLoadingTarget ) @@ -1350,60 +1363,21 @@ bool DirManager::HandleXMLTag(const wxChar *tag, const wxChar **attrs) BlockFilePtr &target = mLoadingTarget(); mLoadingTarget = nullptr; - if (!wxStricmp(tag, wxT("silentblockfile"))) { - // Silent blocks don't actually have a file associated, so - // we don't need to worry about the hash table at all - target = SilentBlockFile::BuildFromXML(*this, attrs); - return true; - } - else if ( !wxStricmp(tag, wxT("simpleblockfile")) ) - pBlockFile = SimpleBlockFile::BuildFromXML(*this, attrs); - else if( !wxStricmp(tag, wxT("pcmaliasblockfile")) ) - pBlockFile = PCMAliasBlockFile::BuildFromXML(*this, attrs); - else if( !wxStricmp(tag, wxT("odpcmaliasblockfile")) ) - { - pBlockFile = ODPCMAliasBlockFile::BuildFromXML(*this, attrs); - //in the case of loading an OD file, we need to schedule the ODManager to begin OD computing of summary - //However, because we don't have access to the track or even the Sequence from this call, we mark a flag - //in the ODMan and check it later. - ODManager::MarkLoadedODFlag(); - } - else if( !wxStricmp(tag, wxT("oddecodeblockfile")) ) - { - pBlockFile = ODDecodeBlockFile::BuildFromXML(*this, attrs); - ODManager::MarkLoadedODFlag(); - } - else if( !wxStricmp(tag, wxT("blockfile")) || - !wxStricmp(tag, wxT("legacyblockfile")) ) { - // Support Audacity version 1.1.1 project files - - int i=0; - bool alias = false; - - while(attrs[i]) { - if (!wxStricmp(attrs[i], wxT("alias"))) { - if (wxAtoi(attrs[i+1])==1) - alias = true; - } - i++; - if (attrs[i]) - i++; - } - - if (alias) - pBlockFile = LegacyAliasBlockFile::BuildFromXML(projFull, attrs); - else - pBlockFile = LegacyBlockFile::BuildFromXML(projFull, attrs, - mLoadingBlockLen, - mLoadingFormat); - } - else + auto &table = GetDeserializers(); + auto iter = table.find( tag ); + if ( iter == table.end() ) return false; + pBlockFile = iter->second( *this, attrs ); if (!pBlockFile) // BuildFromXML failed, or we didn't find a valid blockfile tag. return false; + if (!pBlockFile->GetFileName().name.IsOk()) + // Silent blocks don't actually have a file associated, so + // we don't need to worry about the hash table at all + return true; + // Check the length here so we don't have to do it in each BuildFromXML method. if ((mMaxSamples != ~size_t(0)) && // is initialized (pBlockFile->GetLength() > mMaxSamples)) diff --git a/src/DirManager.h b/src/DirManager.h index 27b14b738..9b96d185c 100644 --- a/src/DirManager.h +++ b/src/DirManager.h @@ -68,6 +68,16 @@ class PROFILE_DLL_API DirManager final : public XMLTagHandler { static void RecursivelyRemove(const FilePaths& filePathArray, int count, int bias, int flags, const wxChar* message = nullptr); + // Type of a function that builds a block file, using attributes from XML + using BlockFileDeserializer = + std::function< BlockFilePtr( DirManager&, const wxChar ** ) >; + // Typically a statically declared object, + // registers a function for an XML tag + struct RegisteredBlockFileDeserializer { + RegisteredBlockFileDeserializer( + const wxString &tag, BlockFileDeserializer function ); + }; + private: // MM: Construct DirManager // Don't call this directly but use Create() instead @@ -162,7 +172,9 @@ class PROFILE_DLL_API DirManager final : public XMLTagHandler { { mLoadingTarget = loadingTarget; } + sampleFormat GetLoadingFormat() const { return mLoadingFormat; } void SetLoadingFormat(sampleFormat format) { mLoadingFormat = format; } + size_t GetLoadingBlockLength() const { return mLoadingBlockLen; } void SetLoadingBlockLength(size_t len) { mLoadingBlockLen = len; } // Note: following affects only the loading of block files when opening a project diff --git a/src/blockfile/LegacyAliasBlockFile.cpp b/src/blockfile/LegacyAliasBlockFile.cpp index 98260a336..4b95047a7 100644 --- a/src/blockfile/LegacyAliasBlockFile.cpp +++ b/src/blockfile/LegacyAliasBlockFile.cpp @@ -17,6 +17,7 @@ #include #include "LegacyBlockFile.h" +#include "../DirManager.h" #include "../FileFormats.h" #include "../xml/XMLTagHandler.h" @@ -147,3 +148,36 @@ BlockFilePtr LegacyAliasBlockFile::BuildFromXML(const FilePath &projDir, const w void LegacyAliasBlockFile::Recover(){ WriteSummary(); } + +static const auto sFactory = []( DirManager &dm, const wxChar **attrs ){ + + // Support Audacity version 1.1.1 project files + + int i=0; + bool alias = false; + + while(attrs[i]) { + if (!wxStricmp(attrs[i], wxT("alias"))) { + if (wxAtoi(attrs[i+1])==1) + alias = true; + } + i++; + if (attrs[i]) + i++; + } + + if (alias) + return LegacyAliasBlockFile::BuildFromXML( + dm.GetProjectDataDir(), attrs); + else + return LegacyBlockFile::BuildFromXML(dm.GetProjectDataDir(), attrs, + dm.GetLoadingBlockLength(), + dm.GetLoadingFormat()); +}; + +static DirManager::RegisteredBlockFileDeserializer sRegistration1 { + "blockfile", sFactory +}; +static DirManager::RegisteredBlockFileDeserializer sRegistration2 { + "legacyblockfile", sFactory +}; diff --git a/src/blockfile/ODDecodeBlockFile.cpp b/src/blockfile/ODDecodeBlockFile.cpp index ed75f60cb..f9692ca2d 100644 --- a/src/blockfile/ODDecodeBlockFile.cpp +++ b/src/blockfile/ODDecodeBlockFile.cpp @@ -29,6 +29,7 @@ The summary is eventually computed and written to a file in a background thread. #include "../DirManager.h" #include "../FileFormats.h" +#include "../ondemand/ODManager.h" #include "NotYetAvailableException.h" const int bheaderTagLen = 20; @@ -524,3 +525,11 @@ void ODDecodeBlockFile::ChangeAudioFile(wxFileNameWrapper &&newAudioFile) +static DirManager::RegisteredBlockFileDeserializer sRegistration { + "oddecodeblockfile", + []( DirManager &dm, const wxChar **attrs ){ + auto result = ODDecodeBlockFile::BuildFromXML( dm, attrs ); + ODManager::MarkLoadedODFlag(); + return result; + } +}; diff --git a/src/blockfile/ODPCMAliasBlockFile.cpp b/src/blockfile/ODPCMAliasBlockFile.cpp index 7b698a40e..22df522ee 100644 --- a/src/blockfile/ODPCMAliasBlockFile.cpp +++ b/src/blockfile/ODPCMAliasBlockFile.cpp @@ -561,4 +561,15 @@ void ODPCMAliasBlockFile::UnlockRead() const mReadDataMutex.Unlock(); } +static DirManager::RegisteredBlockFileDeserializer sRegistration { + "odpcmaliasblockfile", + []( DirManager &dm, const wxChar **attrs ){ + auto result = ODPCMAliasBlockFile::BuildFromXML( dm, attrs ); + //in the case of loading an OD file, we need to schedule the ODManager to begin OD computing of summary + //However, because we don't have access to the track or even the Sequence from this call, we mark a flag + //in the ODMan and check it later. + ODManager::MarkLoadedODFlag(); + return result; + } +}; diff --git a/src/blockfile/PCMAliasBlockFile.cpp b/src/blockfile/PCMAliasBlockFile.cpp index 2fca965bd..19035ed6d 100644 --- a/src/blockfile/PCMAliasBlockFile.cpp +++ b/src/blockfile/PCMAliasBlockFile.cpp @@ -200,3 +200,9 @@ void PCMAliasBlockFile::Recover(void) WriteSummary(); } +static DirManager::RegisteredBlockFileDeserializer sRegistration { + "pcmaliasblockfile", + []( DirManager &dm, const wxChar **attrs ){ + return PCMAliasBlockFile::BuildFromXML( dm, attrs ); + } +}; diff --git a/src/blockfile/SilentBlockFile.cpp b/src/blockfile/SilentBlockFile.cpp index 6ace01f3a..00b3470db 100644 --- a/src/blockfile/SilentBlockFile.cpp +++ b/src/blockfile/SilentBlockFile.cpp @@ -12,6 +12,7 @@ #include "SilentBlockFile.h" #include "../FileFormats.h" +#include "../DirManager.h" #include "../xml/XMLTagHandler.h" SilentBlockFile::SilentBlockFile(size_t sampleLen): @@ -91,3 +92,9 @@ auto SilentBlockFile::GetSpaceUsage() const -> DiskByteCount return 0; } +static DirManager::RegisteredBlockFileDeserializer sRegistration { + "silentblockfile", + []( DirManager &dm, const wxChar **attrs ){ + return SilentBlockFile::BuildFromXML( dm, attrs ); + } +}; diff --git a/src/blockfile/SimpleBlockFile.cpp b/src/blockfile/SimpleBlockFile.cpp index b5e284051..42db44c88 100644 --- a/src/blockfile/SimpleBlockFile.cpp +++ b/src/blockfile/SimpleBlockFile.cpp @@ -610,3 +610,10 @@ bool SimpleBlockFile::GetCache() return false; #endif } + +static DirManager::RegisteredBlockFileDeserializer sRegistration { + "simpleblockfile", + []( DirManager &dm, const wxChar **attrs ){ + return SimpleBlockFile::BuildFromXML( dm, attrs ); + } +};