mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-02 08:39:46 +02:00
Break dependency cycles with Sequence, DirManager, BlockFile classes
This commit is contained in:
commit
ddd5fa6bd6
@ -340,10 +340,9 @@ bool RecordingRecoveryHandler::HandleXMLTag(const wxChar *tag,
|
||||
const auto &dirManager = mProject->GetDirManager();
|
||||
dirManager->SetLoadingFormat(seq->GetSampleFormat());
|
||||
|
||||
BlockArray array;
|
||||
array.resize(1);
|
||||
dirManager->SetLoadingTarget(&array, 0);
|
||||
auto &blockFile = array[0].f;
|
||||
BlockFilePtr blockFile;
|
||||
dirManager->SetLoadingTarget(
|
||||
[&]() -> BlockFilePtr& { return blockFile; } );
|
||||
|
||||
if (!dirManager->HandleXMLTag(tag, attrs) || !blockFile)
|
||||
{
|
||||
|
@ -359,7 +359,7 @@ void BenchmarkDialog::OnRun( wxCommandEvent & WXUNUSED(event))
|
||||
HoldPrint(true);
|
||||
|
||||
ZoomInfo zoomInfo(0.0, ZoomInfo::GetDefaultZoom());
|
||||
auto dd = std::make_shared<DirManager>();
|
||||
auto dd = DirManager::Create();
|
||||
const auto t = TrackFactory{ dd, &zoomInfo }.NewWaveTrack(int16Sample);
|
||||
|
||||
t->SetRate(1);
|
||||
|
@ -53,7 +53,6 @@ out.
|
||||
#include "sndfile.h"
|
||||
#include "FileException.h"
|
||||
#include "FileFormats.h"
|
||||
#include "MissingAliasFileDialog.h"
|
||||
|
||||
// msmeyer: Define this to add debug output via wxPrintf()
|
||||
//#define DEBUG_BLOCKFILE
|
||||
@ -134,6 +133,16 @@ void BlockFile::SetFileName(wxFileNameWrapper &&name)
|
||||
mFileName=std::move(name);
|
||||
}
|
||||
|
||||
const wxFileNameWrapper &BlockFile::GetExternalFileName() const
|
||||
{
|
||||
static wxFileNameWrapper empty;
|
||||
return empty;
|
||||
}
|
||||
|
||||
void BlockFile::SetExternalFileName( wxFileNameWrapper && )
|
||||
{
|
||||
wxASSERT( false );
|
||||
}
|
||||
|
||||
/// Marks this BlockFile as "locked." A locked BlockFile may not
|
||||
/// be moved or deleted, only copied. Locking a BlockFile prevents
|
||||
@ -479,6 +488,23 @@ bool BlockFile::Read64K(float *buffer,
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace {
|
||||
BlockFile::MissingAliasFileFoundHook &GetMissingAliasFileFound()
|
||||
{
|
||||
static BlockFile::MissingAliasFileFoundHook theHook;
|
||||
return theHook;
|
||||
}
|
||||
}
|
||||
|
||||
auto BlockFile::SetMissingAliasFileFound( MissingAliasFileFoundHook hook )
|
||||
-> MissingAliasFileFoundHook
|
||||
{
|
||||
auto &theHook = GetMissingAliasFileFound();
|
||||
auto result = theHook;
|
||||
theHook = hook;
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t BlockFile::CommonReadData(
|
||||
bool mayThrow,
|
||||
const wxFileName &fileName, bool &mSilentLog,
|
||||
@ -537,8 +563,9 @@ size_t BlockFile::CommonReadData(
|
||||
|
||||
if (pAliasFile) {
|
||||
// Set a marker to display an error message for the silence
|
||||
if (!MissingAliasFilesDialog::ShouldShow())
|
||||
MissingAliasFilesDialog::Mark(pAliasFile);
|
||||
auto hook = GetMissingAliasFileFound();
|
||||
if (hook)
|
||||
hook( pAliasFile );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -707,6 +734,16 @@ AliasBlockFile::~AliasBlockFile()
|
||||
{
|
||||
}
|
||||
|
||||
const wxFileNameWrapper &AliasBlockFile::GetExternalFileName() const
|
||||
{
|
||||
return GetAliasedFileName();
|
||||
}
|
||||
|
||||
void AliasBlockFile::SetExternalFileName( wxFileNameWrapper &&newName )
|
||||
{
|
||||
ChangeAliasedFileName( std::move( newName ) );
|
||||
}
|
||||
|
||||
/// Read the summary of this alias block from disk. Since the audio data
|
||||
/// is elsewhere, this consists of reading the entire summary file.
|
||||
/// Fill with zeroes and return false if data are unavailable for any reason.
|
||||
|
@ -18,6 +18,8 @@
|
||||
|
||||
#include "ondemand/ODTaskThread.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
class XMLWriter;
|
||||
|
||||
class SummaryInfo {
|
||||
@ -49,6 +51,14 @@ inline std::shared_ptr< Result > make_blockfile (Args && ... args)
|
||||
class PROFILE_DLL_API BlockFile /* not final, abstract */ {
|
||||
public:
|
||||
|
||||
// Type of function to be called when opening of an alias block file for read
|
||||
// discovers that the other audio file it depends on is absent
|
||||
using MissingAliasFileFoundHook =
|
||||
std::function< void(const AliasBlockFile*) >;
|
||||
// Install a hook, and return the previous hook
|
||||
static MissingAliasFileFoundHook
|
||||
SetMissingAliasFileFound( MissingAliasFileFoundHook hook );
|
||||
|
||||
// Constructor / Destructor
|
||||
|
||||
/// Construct a BlockFile.
|
||||
@ -104,6 +114,12 @@ class PROFILE_DLL_API BlockFile /* not final, abstract */ {
|
||||
virtual GetFileNameResult GetFileName() const;
|
||||
virtual void SetFileName(wxFileNameWrapper &&name);
|
||||
|
||||
// Managing an external file dependency
|
||||
// Default always returns empty
|
||||
virtual const wxFileNameWrapper &GetExternalFileName() const;
|
||||
// Default does nothing (and gives assertion violation in debug)
|
||||
virtual void SetExternalFileName( wxFileNameWrapper &&newName );
|
||||
|
||||
size_t GetLength() const { return mLen; }
|
||||
void SetLength(size_t newLen) { mLen = newLen; }
|
||||
|
||||
@ -268,10 +284,13 @@ class AliasBlockFile /* not final */ : public BlockFile
|
||||
//
|
||||
// These methods are for advanced use only!
|
||||
//
|
||||
const wxFileName &GetAliasedFileName() const { return mAliasedFileName; }
|
||||
const wxFileNameWrapper &GetAliasedFileName() const { return mAliasedFileName; }
|
||||
void ChangeAliasedFileName(wxFileNameWrapper &&newAliasedFile);
|
||||
bool IsAlias() const override { return true; }
|
||||
|
||||
const wxFileNameWrapper &GetExternalFileName() const override;
|
||||
void SetExternalFileName( wxFileNameWrapper &&newName ) override;
|
||||
|
||||
protected:
|
||||
// Introduce a NEW virtual.
|
||||
/// Write the summary to disk, using the derived ReadData() to get the data
|
||||
|
@ -49,7 +49,7 @@ AliasedFile s.
|
||||
#include <wx/dataobj.h>
|
||||
#include <wx/stattext.h>
|
||||
|
||||
#include "BlockFile.h"
|
||||
#include "blockfile/SimpleBlockFile.h"
|
||||
#include "DirManager.h"
|
||||
#include "Prefs.h"
|
||||
#include "Project.h"
|
||||
@ -204,11 +204,14 @@ static void RemoveDependencies(AudacityProject *project,
|
||||
BlockFilePtr newBlockFile;
|
||||
{
|
||||
SampleBuffer buffer(len, format);
|
||||
// We tolerate exceptions from NewSimpleBlockFile and so we
|
||||
// can allow exceptions from ReadData too
|
||||
// We tolerate exceptions from NewBlockFile
|
||||
// and so we can allow exceptions from ReadData too
|
||||
f->ReadData(buffer.ptr(), format, 0, len);
|
||||
newBlockFile =
|
||||
dirManager->NewSimpleBlockFile(buffer.ptr(), len, format);
|
||||
dirManager->NewBlockFile( [&]( wxFileNameWrapper filePath ) {
|
||||
return make_blockfile<SimpleBlockFile>(
|
||||
std::move(filePath), buffer.ptr(), len, format);
|
||||
} );
|
||||
}
|
||||
|
||||
// Update our hash so we know what block files we've done
|
||||
|
@ -85,23 +85,14 @@
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include "Clipboard.h"
|
||||
#include "BlockFile.h"
|
||||
#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"
|
||||
#include "Project.h"
|
||||
#include "Prefs.h"
|
||||
#include "Sequence.h"
|
||||
#include "widgets/Warning.h"
|
||||
#include "widgets/ErrorDialog.h"
|
||||
#include "widgets/ProgressDialog.h"
|
||||
|
||||
#include "ondemand/ODManager.h"
|
||||
|
||||
#if defined(__WXMAC__)
|
||||
#include <mach/mach.h>
|
||||
#include <mach/vm_statistics.h>
|
||||
@ -356,6 +347,19 @@ wxString DirManager::globaltemp;
|
||||
int DirManager::numDirManagers = 0;
|
||||
bool DirManager::dontDeleteTempFiles = false;
|
||||
|
||||
namespace {
|
||||
|
||||
// Global tracking of all outstanding DirManagers
|
||||
std::vector< std::weak_ptr< DirManager > > sDirManagers;
|
||||
|
||||
}
|
||||
|
||||
std::shared_ptr<DirManager> DirManager::Create()
|
||||
{
|
||||
auto result = std::shared_ptr< DirManager >( safenew DirManager );
|
||||
sDirManagers.push_back( result );
|
||||
return result;
|
||||
}
|
||||
|
||||
DirManager::DirManager()
|
||||
{
|
||||
@ -385,8 +389,6 @@ DirManager::DirManager()
|
||||
projPath = wxT("");
|
||||
projName = wxT("");
|
||||
|
||||
mLoadingTarget = NULL;
|
||||
mLoadingTargetIdx = 0;
|
||||
mMaxSamples = ~size_t(0);
|
||||
|
||||
// toplevel pool hash is fully populated to begin
|
||||
@ -410,6 +412,13 @@ DirManager::DirManager()
|
||||
|
||||
DirManager::~DirManager()
|
||||
{
|
||||
auto start = sDirManagers.begin(), finish = sDirManagers.end(),
|
||||
iter = std::remove_if( start, finish,
|
||||
[=]( const std::weak_ptr<DirManager> &ptr ){
|
||||
return ptr.expired() || ptr.lock().get() == this;
|
||||
} );
|
||||
sDirManagers.erase( iter, finish );
|
||||
|
||||
numDirManagers--;
|
||||
if (numDirManagers == 0) {
|
||||
CleanTempDir();
|
||||
@ -1171,71 +1180,17 @@ wxFileNameWrapper DirManager::MakeBlockFileName()
|
||||
return ret;
|
||||
}
|
||||
|
||||
BlockFilePtr DirManager::NewSimpleBlockFile(
|
||||
samplePtr sampleData, size_t sampleLen,
|
||||
sampleFormat format,
|
||||
bool allowDeferredWrite)
|
||||
BlockFilePtr DirManager::NewBlockFile( const BlockFileFactory &factory )
|
||||
{
|
||||
wxFileNameWrapper filePath{ MakeBlockFileName() };
|
||||
const wxString fileName{ filePath.GetName() };
|
||||
|
||||
auto newBlockFile = make_blockfile<SimpleBlockFile>
|
||||
(std::move(filePath), sampleData, sampleLen, format, allowDeferredWrite);
|
||||
|
||||
auto newBlockFile = factory( std::move(filePath) );
|
||||
mBlockFileHash[fileName] = newBlockFile;
|
||||
|
||||
return newBlockFile;
|
||||
}
|
||||
|
||||
BlockFilePtr DirManager::NewAliasBlockFile(
|
||||
const FilePath &aliasedFile, sampleCount aliasStart,
|
||||
size_t aliasLen, int aliasChannel)
|
||||
{
|
||||
wxFileNameWrapper filePath{ MakeBlockFileName() };
|
||||
const wxString fileName = filePath.GetName();
|
||||
|
||||
auto newBlockFile = make_blockfile<PCMAliasBlockFile>
|
||||
(std::move(filePath), wxFileNameWrapper{aliasedFile},
|
||||
aliasStart, aliasLen, aliasChannel);
|
||||
|
||||
mBlockFileHash[fileName]=newBlockFile;
|
||||
aliasList.push_back(aliasedFile);
|
||||
|
||||
return newBlockFile;
|
||||
}
|
||||
|
||||
BlockFilePtr DirManager::NewODAliasBlockFile(
|
||||
const FilePath &aliasedFile, sampleCount aliasStart,
|
||||
size_t aliasLen, int aliasChannel)
|
||||
{
|
||||
wxFileNameWrapper filePath{ MakeBlockFileName() };
|
||||
const wxString fileName{ filePath.GetName() };
|
||||
|
||||
auto newBlockFile = make_blockfile<ODPCMAliasBlockFile>
|
||||
(std::move(filePath), wxFileNameWrapper{aliasedFile},
|
||||
aliasStart, aliasLen, aliasChannel);
|
||||
|
||||
mBlockFileHash[fileName]=newBlockFile;
|
||||
aliasList.push_back(aliasedFile);
|
||||
|
||||
return newBlockFile;
|
||||
}
|
||||
|
||||
BlockFilePtr DirManager::NewODDecodeBlockFile(
|
||||
const FilePath &aliasedFile, sampleCount aliasStart,
|
||||
size_t aliasLen, int aliasChannel, int decodeType)
|
||||
{
|
||||
wxFileNameWrapper filePath{ MakeBlockFileName() };
|
||||
const wxString fileName{ filePath.GetName() };
|
||||
|
||||
auto newBlockFile = make_blockfile<ODDecodeBlockFile>
|
||||
(std::move(filePath), wxFileNameWrapper{ aliasedFile },
|
||||
aliasStart, aliasLen, aliasChannel, decodeType);
|
||||
|
||||
mBlockFileHash[fileName]=newBlockFile;
|
||||
aliasList.push_back(aliasedFile); //OD TODO: check to see if we need to remove this when done decoding.
|
||||
//I don't immediately see a place where aliased files remove when a file is closed.
|
||||
|
||||
auto &aliasName = newBlockFile->GetExternalFileName();
|
||||
if ( aliasName.IsOk() )
|
||||
//OD TODO: check to see if we need to remove this when done decoding.
|
||||
//I don't immediately see a place where aliased files remove when a file is closed.
|
||||
aliasList.push_back( aliasName.GetFullPath() );
|
||||
return newBlockFile;
|
||||
}
|
||||
|
||||
@ -1324,69 +1279,49 @@ 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 == NULL )
|
||||
if( !mLoadingTarget )
|
||||
return false;
|
||||
|
||||
BlockFilePtr pBlockFile {};
|
||||
|
||||
BlockFilePtr &target = mLoadingTarget->at(mLoadingTargetIdx).f;
|
||||
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))
|
||||
@ -1564,25 +1499,11 @@ bool DirManager::EnsureSafeFilename(const wxFileName &fName)
|
||||
{
|
||||
BlockFilePtr b = iter->second.lock();
|
||||
if (b) {
|
||||
// don't worry, we don't rely on this cast unless IsAlias is true
|
||||
auto ab = static_cast< AliasBlockFile * > ( &*b );
|
||||
|
||||
// don't worry, we don't rely on this cast unless ISDataAvailable is false
|
||||
// which means that it still needs to access the file.
|
||||
auto db = static_cast< ODDecodeBlockFile * > ( &*b );
|
||||
|
||||
if (b->IsAlias() && ab->GetAliasedFileName() == fName) {
|
||||
if (fName.IsOk() && b->GetExternalFileName() == fName) {
|
||||
needToRename = true;
|
||||
|
||||
//ODBlocks access the aliased file on another thread, so we need to pause them before this continues.
|
||||
readLocks.push_back( ab->LockForRead() );
|
||||
}
|
||||
//now for encoded OD blocks (e.g. flac)
|
||||
else if (!b->IsDataAvailable() && db->GetEncodedAudioFilename() == fName) {
|
||||
needToRename = true;
|
||||
|
||||
//ODBlocks access the aliased file on another thread, so we need to pause them before this continues.
|
||||
readLocks.push_back( db->LockForRead() );
|
||||
readLocks.push_back( b->LockForRead() );
|
||||
}
|
||||
}
|
||||
++iter;
|
||||
@ -1614,19 +1535,12 @@ bool DirManager::EnsureSafeFilename(const wxFileName &fName)
|
||||
{
|
||||
BlockFilePtr b = iter2->second.lock();
|
||||
if (b) {
|
||||
auto ab = static_cast< AliasBlockFile * > ( &*b );
|
||||
auto db = static_cast< ODDecodeBlockFile * > ( &*b );
|
||||
|
||||
if (b->IsAlias() && ab->GetAliasedFileName() == fName)
|
||||
{
|
||||
ab->ChangeAliasedFileName(wxFileNameWrapper{ renamedFileName });
|
||||
if (fName.IsOk() && b->GetExternalFileName() == fName) {
|
||||
b->SetExternalFileName(wxFileNameWrapper{ renamedFileName });
|
||||
wxPrintf(_("Changed block %s to new alias name\n"),
|
||||
b->GetFileName().name.GetFullName());
|
||||
|
||||
}
|
||||
else if (!b->IsDataAvailable() && db->GetEncodedAudioFilename() == fName) {
|
||||
db->ChangeAudioFile(wxFileNameWrapper{ renamedFileName });
|
||||
}
|
||||
}
|
||||
++iter2;
|
||||
}
|
||||
@ -1744,7 +1658,12 @@ void DirManager::FindOrphanBlockFiles(
|
||||
const FilePaths &filePathArray, // input: all files in project directory
|
||||
FilePaths &orphanFilePathArray) // output: orphan files
|
||||
{
|
||||
DirManager *clipboardDM = NULL;
|
||||
std::vector< std::shared_ptr<DirManager> > otherDirManagers;
|
||||
for ( auto &wPtr : sDirManagers ) {
|
||||
auto sPtr = wPtr.lock();
|
||||
if ( sPtr && sPtr.get() != this )
|
||||
otherDirManagers.push_back( sPtr );
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < filePathArray.size(); i++)
|
||||
{
|
||||
@ -1757,17 +1676,15 @@ void DirManager::FindOrphanBlockFiles(
|
||||
(ext.IsSameAs(wxT("au"), false) ||
|
||||
ext.IsSameAs(wxT("auf"), false)))
|
||||
{
|
||||
if (!clipboardDM) {
|
||||
auto &clipTracks = Clipboard::Get().GetTracks();
|
||||
|
||||
auto track = *clipTracks.Any().first;
|
||||
if (track)
|
||||
clipboardDM = track->GetDirManager().get();
|
||||
}
|
||||
|
||||
// Ignore it if it exists in the clipboard (from a previously closed project)
|
||||
if (!(clipboardDM && clipboardDM->ContainsBlockFile(basename)))
|
||||
orphanFilePathArray.push_back(fullname.GetFullPath());
|
||||
if ( std::any_of( otherDirManagers.begin(), otherDirManagers.end(),
|
||||
[&]( const std::shared_ptr< DirManager > &ptr ){
|
||||
return ptr->ContainsBlockFile( basename );
|
||||
}
|
||||
) )
|
||||
continue;
|
||||
|
||||
orphanFilePathArray.push_back(fullname.GetFullPath());
|
||||
}
|
||||
}
|
||||
for ( const auto &orphan : orphanFilePathArray )
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "audacity/Types.h"
|
||||
#include "xml/XMLTagHandler.h"
|
||||
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
|
||||
class wxFileNameWrapper;
|
||||
@ -67,9 +68,25 @@ 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
|
||||
DirManager();
|
||||
|
||||
public:
|
||||
|
||||
static std::shared_ptr< DirManager > Create();
|
||||
|
||||
virtual ~DirManager();
|
||||
|
||||
size_t NumBlockFiles() const { return mBlockFileHash.size(); }
|
||||
@ -107,23 +124,8 @@ class PROFILE_DLL_API DirManager final : public XMLTagHandler {
|
||||
|
||||
wxLongLong GetFreeDiskSpace();
|
||||
|
||||
BlockFilePtr
|
||||
NewSimpleBlockFile(samplePtr sampleData,
|
||||
size_t sampleLen,
|
||||
sampleFormat format,
|
||||
bool allowDeferredWrite = false);
|
||||
|
||||
BlockFilePtr
|
||||
NewAliasBlockFile( const FilePath &aliasedFile, sampleCount aliasStart,
|
||||
size_t aliasLen, int aliasChannel);
|
||||
|
||||
BlockFilePtr
|
||||
NewODAliasBlockFile( const FilePath &aliasedFile, sampleCount aliasStart,
|
||||
size_t aliasLen, int aliasChannel);
|
||||
|
||||
BlockFilePtr
|
||||
NewODDecodeBlockFile( const FilePath &aliasedFile, sampleCount aliasStart,
|
||||
size_t aliasLen, int aliasChannel, int decodeType);
|
||||
using BlockFileFactory = std::function< BlockFilePtr( wxFileNameWrapper ) >;
|
||||
BlockFilePtr NewBlockFile( const BlockFileFactory &factory );
|
||||
|
||||
/// Returns true if the blockfile pointed to by b is contained by the DirManager
|
||||
bool ContainsBlockFile(const BlockFile *b) const;
|
||||
@ -150,12 +152,14 @@ class PROFILE_DLL_API DirManager final : public XMLTagHandler {
|
||||
|
||||
bool EnsureSafeFilename(const wxFileName &fName);
|
||||
|
||||
void SetLoadingTarget(BlockArray *pArray, unsigned idx)
|
||||
using LoadingTarget = std::function< BlockFilePtr &() >;
|
||||
void SetLoadingTarget( LoadingTarget loadingTarget )
|
||||
{
|
||||
mLoadingTarget = pArray;
|
||||
mLoadingTargetIdx = idx;
|
||||
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
|
||||
@ -248,8 +252,7 @@ class PROFILE_DLL_API DirManager final : public XMLTagHandler {
|
||||
|
||||
FilePaths aliasList;
|
||||
|
||||
BlockArray *mLoadingTarget;
|
||||
unsigned mLoadingTargetIdx;
|
||||
LoadingTarget mLoadingTarget;
|
||||
sampleFormat mLoadingFormat;
|
||||
size_t mLoadingBlockLen;
|
||||
|
||||
|
@ -131,3 +131,12 @@ namespace MissingAliasFilesDialog {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Arrange callback from low levels of block file I/O to detect missing files
|
||||
static struct InstallHook{ InstallHook() {
|
||||
auto hook = [](const AliasBlockFile *pAliasFile){
|
||||
if (!MissingAliasFilesDialog::ShouldShow())
|
||||
MissingAliasFilesDialog::Mark(pAliasFile);
|
||||
};
|
||||
BlockFile::SetMissingAliasFileFound( hook );
|
||||
} } installHook;
|
||||
|
@ -1130,8 +1130,7 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id,
|
||||
MissingAliasFilesDialog::SetShouldShow(true);
|
||||
|
||||
// MM: DirManager is created dynamically, freed on demand via ref-counting
|
||||
// MM: We don't need to Ref() here because it start with refcount=1
|
||||
mDirManager = std::make_shared<DirManager>();
|
||||
mDirManager = DirManager::Create();
|
||||
|
||||
mLastSavedTracks.reset();
|
||||
|
||||
@ -5371,7 +5370,7 @@ void AudacityProject::ResetProjectToEmpty() {
|
||||
SelectActions::DoSelectAll(*this);
|
||||
TrackActions::DoRemoveTracks(*this);
|
||||
// A new DirManager.
|
||||
mDirManager = std::make_shared<DirManager>();
|
||||
mDirManager = DirManager::Create();
|
||||
mTrackFactory.reset(safenew TrackFactory{ mDirManager, &mViewInfo });
|
||||
|
||||
// mLastSavedTrack code copied from OnCloseWindow.
|
||||
|
103
src/Sequence.cpp
103
src/Sequence.cpp
@ -40,10 +40,10 @@
|
||||
#include <wx/ffile.h>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "blockfile/ODDecodeBlockFile.h"
|
||||
#include "DirManager.h"
|
||||
|
||||
#include "blockfile/SilentBlockFile.h"
|
||||
#include "blockfile/SimpleBlockFile.h"
|
||||
|
||||
#include "InconsistencyException.h"
|
||||
|
||||
@ -457,6 +457,17 @@ namespace {
|
||||
{
|
||||
return numSamples > wxLL(9223372036854775807);
|
||||
}
|
||||
|
||||
BlockFilePtr NewSimpleBlockFile( DirManager &dm,
|
||||
samplePtr sampleData, size_t sampleLen,
|
||||
sampleFormat format,
|
||||
bool allowDeferredWrite = false)
|
||||
{
|
||||
return dm.NewBlockFile( [&]( wxFileNameWrapper filePath ) {
|
||||
return make_blockfile<SimpleBlockFile>(
|
||||
std::move(filePath), sampleData, sampleLen, format, allowDeferredWrite);
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
@ -549,7 +560,7 @@ void Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
splitPoint, length - splitPoint, true);
|
||||
|
||||
auto file =
|
||||
mDirManager->NewSimpleBlockFile(
|
||||
NewSimpleBlockFile( *mDirManager,
|
||||
// largerBlockLen is not more than mMaxSamples...
|
||||
buffer.ptr(), largerBlockLen.as_size_t(), mSampleFormat);
|
||||
|
||||
@ -709,41 +720,6 @@ void Sequence::InsertSilence(sampleCount s0, sampleCount len)
|
||||
Paste(s0, &sTrack);
|
||||
}
|
||||
|
||||
void Sequence::AppendAlias(const FilePath &fullPath,
|
||||
sampleCount start,
|
||||
size_t len, int channel, bool useOD)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
// Quick check to make sure that it doesn't overflow
|
||||
if (Overflows((mNumSamples.as_double()) + ((double)len)))
|
||||
THROW_INCONSISTENCY_EXCEPTION;
|
||||
|
||||
SeqBlock newBlock(
|
||||
useOD?
|
||||
mDirManager->NewODAliasBlockFile(fullPath, start, len, channel):
|
||||
mDirManager->NewAliasBlockFile(fullPath, start, len, channel),
|
||||
mNumSamples
|
||||
);
|
||||
mBlock.push_back(newBlock);
|
||||
mNumSamples += len;
|
||||
}
|
||||
|
||||
void Sequence::AppendCoded(const FilePath &fName, sampleCount start,
|
||||
size_t len, int channel, int decodeType)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
// Quick check to make sure that it doesn't overflow
|
||||
if (Overflows((mNumSamples.as_double()) + ((double)len)))
|
||||
THROW_INCONSISTENCY_EXCEPTION;
|
||||
|
||||
SeqBlock newBlock(
|
||||
mDirManager->NewODDecodeBlockFile(fName, start, len, channel, decodeType),
|
||||
mNumSamples
|
||||
);
|
||||
mBlock.push_back(newBlock);
|
||||
mNumSamples += len;
|
||||
}
|
||||
|
||||
void Sequence::AppendBlock
|
||||
(DirManager &mDirManager,
|
||||
BlockArray &mBlock, sampleCount &mNumSamples, const SeqBlock &b)
|
||||
@ -765,20 +741,6 @@ void Sequence::AppendBlock
|
||||
// function gets called in an inner loop.
|
||||
}
|
||||
|
||||
///gets an int with OD flags so that we can determine which ODTasks should be run on this track after save/open, etc.
|
||||
unsigned int Sequence::GetODFlags()
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
for (unsigned int i = 0; i < mBlock.size(); i++) {
|
||||
const auto &file = mBlock[i].f;
|
||||
if(!file->IsDataAvailable())
|
||||
ret |= (static_cast< ODDecodeBlockFile * >( &*file ))->GetDecodeType();
|
||||
else if(!file->IsSummaryAvailable())
|
||||
ret |= ODTask::eODPCMSummary;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
sampleCount Sequence::GetBlockStart(sampleCount position) const
|
||||
{
|
||||
int b = FindBlock(position);
|
||||
@ -867,7 +829,9 @@ bool Sequence::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
|
||||
} // while
|
||||
|
||||
mBlock.push_back(wb);
|
||||
mDirManager->SetLoadingTarget(&mBlock, mBlock.size() - 1);
|
||||
auto index = mBlock.size() - 1;
|
||||
mDirManager->SetLoadingTarget(
|
||||
[this, index] () -> BlockFilePtr& { return mBlock[index].f; } );
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1265,13 +1229,13 @@ void Sequence::SetSamples(samplePtr buffer, sampleFormat format,
|
||||
else
|
||||
ClearSamples(scratch.ptr(), mSampleFormat, bstart, blen);
|
||||
|
||||
block.f = mDirManager->NewSimpleBlockFile(
|
||||
block.f = NewSimpleBlockFile( *mDirManager,
|
||||
scratch.ptr(), fileLength, mSampleFormat);
|
||||
}
|
||||
else {
|
||||
// Avoid reading the disk when the replacement is total
|
||||
if (useBuffer)
|
||||
block.f = mDirManager->NewSimpleBlockFile(
|
||||
block.f = NewSimpleBlockFile( *mDirManager,
|
||||
useBuffer, fileLength, mSampleFormat);
|
||||
else
|
||||
block.f = make_blockfile<SilentBlockFile>(fileLength);
|
||||
@ -1597,7 +1561,7 @@ void Sequence::Append(samplePtr buffer, sampleFormat format,
|
||||
const auto newLastBlockLen = length + addLen;
|
||||
|
||||
SeqBlock newLastBlock(
|
||||
mDirManager->NewSimpleBlockFile(
|
||||
NewSimpleBlockFile( *mDirManager,
|
||||
buffer2.ptr(), newLastBlockLen, mSampleFormat,
|
||||
blockFileLog != NULL
|
||||
),
|
||||
@ -1623,12 +1587,12 @@ void Sequence::Append(samplePtr buffer, sampleFormat format,
|
||||
const auto addedLen = std::min(idealSamples, len);
|
||||
BlockFilePtr pFile;
|
||||
if (format == mSampleFormat) {
|
||||
pFile = mDirManager->NewSimpleBlockFile(
|
||||
pFile = NewSimpleBlockFile( *mDirManager,
|
||||
buffer, addedLen, mSampleFormat, blockFileLog != NULL);
|
||||
}
|
||||
else {
|
||||
CopySamples(buffer, format, buffer2.ptr(), mSampleFormat, addedLen);
|
||||
pFile = mDirManager->NewSimpleBlockFile(
|
||||
pFile = NewSimpleBlockFile( *mDirManager,
|
||||
buffer2.ptr(), addedLen, mSampleFormat, blockFileLog != NULL);
|
||||
}
|
||||
|
||||
@ -1671,7 +1635,7 @@ void Sequence::Blockify
|
||||
int newLen = ((i + 1) * len / num) - offset;
|
||||
samplePtr bufStart = buffer + (offset * SAMPLE_SIZE(mSampleFormat));
|
||||
|
||||
b.f = mDirManager.NewSimpleBlockFile(bufStart, newLen, mSampleFormat);
|
||||
b.f = NewSimpleBlockFile( mDirManager, bufStart, newLen, mSampleFormat );
|
||||
|
||||
list.push_back(b);
|
||||
}
|
||||
@ -1733,7 +1697,7 @@ void Sequence::Delete(sampleCount start, sampleCount len)
|
||||
( pos + len ).as_size_t(), newLen - pos, true);
|
||||
|
||||
auto newFile =
|
||||
mDirManager->NewSimpleBlockFile(scratch.ptr(), newLen, mSampleFormat);
|
||||
NewSimpleBlockFile( *mDirManager, scratch.ptr(), newLen, mSampleFormat );
|
||||
|
||||
// Don't make a duplicate array. We can still give STRONG-GUARANTEE
|
||||
// if we modify only one block in place.
|
||||
@ -1777,7 +1741,7 @@ void Sequence::Delete(sampleCount start, sampleCount len)
|
||||
ensureSampleBufferSize(scratch, mSampleFormat, scratchSize, preBufferLen);
|
||||
Read(scratch.ptr(), mSampleFormat, preBlock, 0, preBufferLen, true);
|
||||
auto pFile =
|
||||
mDirManager->NewSimpleBlockFile(scratch.ptr(), preBufferLen, mSampleFormat);
|
||||
NewSimpleBlockFile( *mDirManager, scratch.ptr(), preBufferLen, mSampleFormat );
|
||||
|
||||
newBlock.push_back(SeqBlock(pFile, preBlock.start));
|
||||
} else {
|
||||
@ -1823,7 +1787,7 @@ void Sequence::Delete(sampleCount start, sampleCount len)
|
||||
auto pos = (start + len - postBlock.start).as_size_t();
|
||||
Read(scratch.ptr(), mSampleFormat, postBlock, pos, postBufferLen, true);
|
||||
auto file =
|
||||
mDirManager->NewSimpleBlockFile(scratch.ptr(), postBufferLen, mSampleFormat);
|
||||
NewSimpleBlockFile( *mDirManager, scratch.ptr(), postBufferLen, mSampleFormat );
|
||||
|
||||
newBlock.push_back(SeqBlock(file, start));
|
||||
} else {
|
||||
@ -2014,6 +1978,23 @@ size_t Sequence::GetMaxDiskBlockSize()
|
||||
return sMaxDiskBlockSize;
|
||||
}
|
||||
|
||||
void Sequence::AppendBlockFile( const BlockFileFactory &factory, size_t len )
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
// Quick check to make sure that it doesn't overflow
|
||||
if (Overflows((mNumSamples.as_double()) + ((double)len)))
|
||||
THROW_INCONSISTENCY_EXCEPTION;
|
||||
|
||||
SeqBlock newBlock(
|
||||
mDirManager->NewBlockFile( [&]( wxFileNameWrapper filePath ){
|
||||
return factory( std::move( filePath ), len );
|
||||
} ),
|
||||
mNumSamples
|
||||
);
|
||||
mBlock.push_back(newBlock);
|
||||
mNumSamples += len;
|
||||
}
|
||||
|
||||
void Sequence::AppendBlockFile(const BlockFilePtr &blockFile)
|
||||
{
|
||||
// We assume blockFile has the correct ref count already
|
||||
|
@ -23,6 +23,7 @@ class BlockFile;
|
||||
using BlockFilePtr = std::shared_ptr<BlockFile>;
|
||||
|
||||
class DirManager;
|
||||
class wxFileNameWrapper;
|
||||
|
||||
// This is an internal data structure! For advanced use only.
|
||||
class SeqBlock {
|
||||
@ -107,21 +108,18 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
|
||||
void Append(samplePtr buffer, sampleFormat format, size_t len,
|
||||
XMLWriter* blockFileLog=NULL);
|
||||
void Delete(sampleCount start, sampleCount len);
|
||||
void AppendAlias(const FilePath &fullPath,
|
||||
sampleCount start,
|
||||
size_t len, int channel, bool useOD);
|
||||
|
||||
void AppendCoded(const FilePath &fName, sampleCount start,
|
||||
size_t len, int channel, int decodeType);
|
||||
|
||||
///gets an int with OD flags so that we can determine which ODTasks should be run on this track after save/open, etc.
|
||||
unsigned int GetODFlags();
|
||||
using BlockFileFactory =
|
||||
std::function< BlockFilePtr( wxFileNameWrapper, size_t /* len */ ) >;
|
||||
// An overload of AppendBlockFile that passes the factory to DirManager
|
||||
// which supplies it with a file name
|
||||
void AppendBlockFile( const BlockFileFactory &factory, size_t len );
|
||||
|
||||
// Append a blockfile. The blockfile pointer is then "owned" by the
|
||||
// sequence. This function is used by the recording log crash recovery
|
||||
// code, but may be useful for other purposes. The blockfile must already
|
||||
// be registered within the dir manager hash. This is the case
|
||||
// when the blockfile is created using DirManager::NewSimpleBlockFile or
|
||||
// when the blockfile is created using SimpleBlockFile or
|
||||
// loaded from an XML file via DirManager::HandleXMLTag
|
||||
void AppendBlockFile(const BlockFilePtr &blockFile);
|
||||
|
||||
|
@ -1448,30 +1448,51 @@ void WaveClip::Append(samplePtr buffer, sampleFormat format,
|
||||
}
|
||||
}
|
||||
|
||||
#include "blockfile/ODPCMAliasBlockFile.h"
|
||||
void WaveClip::AppendAlias(const FilePath &fName, sampleCount start,
|
||||
size_t len, int channel,bool useOD)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
// use STRONG-GUARANTEE
|
||||
mSequence->AppendAlias(fName, start, len, channel,useOD);
|
||||
mSequence->AppendBlockFile(
|
||||
[&]( wxFileNameWrapper filePath, size_t len ) {
|
||||
return useOD
|
||||
? make_blockfile<ODPCMAliasBlockFile>(
|
||||
std::move(filePath), wxFileNameWrapper{ fName },
|
||||
start, len, channel)
|
||||
: make_blockfile<PCMAliasBlockFile>(
|
||||
std::move(filePath), wxFileNameWrapper{ fName },
|
||||
start, len, channel);
|
||||
},
|
||||
len
|
||||
);
|
||||
|
||||
// use NOFAIL-GUARANTEE
|
||||
UpdateEnvelopeTrackLen();
|
||||
MarkChanged();
|
||||
}
|
||||
|
||||
#include "blockfile/ODDecodeBlockFile.h"
|
||||
void WaveClip::AppendCoded(const FilePath &fName, sampleCount start,
|
||||
size_t len, int channel, int decodeType)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
// use STRONG-GUARANTEE
|
||||
mSequence->AppendCoded(fName, start, len, channel, decodeType);
|
||||
mSequence->AppendBlockFile(
|
||||
[&]( wxFileNameWrapper filePath, size_t len ) {
|
||||
return make_blockfile<ODDecodeBlockFile>(
|
||||
std::move(filePath), wxFileNameWrapper{ fName },
|
||||
start, len, channel, decodeType);
|
||||
},
|
||||
len
|
||||
) ;
|
||||
|
||||
// use NOFAIL-GUARANTEE
|
||||
UpdateEnvelopeTrackLen();
|
||||
MarkChanged();
|
||||
}
|
||||
|
||||
|
||||
void WaveClip::Flush()
|
||||
// NOFAIL-GUARANTEE that the clip will be in a flushed state.
|
||||
// PARTIAL-GUARANTEE in case of exceptions:
|
||||
|
@ -1599,12 +1599,21 @@ void WaveTrack::AppendCoded(const FilePath &fName, sampleCount start,
|
||||
}
|
||||
|
||||
///gets an int with OD flags so that we can determine which ODTasks should be run on this track after save/open, etc.
|
||||
#include "blockfile/ODDecodeBlockFile.h"
|
||||
unsigned int WaveTrack::GetODFlags() const
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
for (const auto &clip : mClips)
|
||||
{
|
||||
ret = ret | clip->GetSequence()->GetODFlags();
|
||||
auto sequence = clip->GetSequence();
|
||||
const auto &blocks = sequence->GetBlockArray();
|
||||
for ( const auto &block : blocks ) {
|
||||
const auto &file = block.f;
|
||||
if(!file->IsDataAvailable())
|
||||
ret |= (static_cast< ODDecodeBlockFile * >( &*file ))->GetDecodeType();
|
||||
else if(!file->IsSummaryAvailable())
|
||||
ret |= ODTask::eODPCMSummary;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <sndfile.h>
|
||||
|
||||
#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
|
||||
};
|
||||
|
@ -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;
|
||||
@ -502,6 +503,18 @@ void ODDecodeBlockFile::UnlockRead() const
|
||||
mReadDataMutex.Unlock();
|
||||
}
|
||||
|
||||
const wxFileNameWrapper &ODDecodeBlockFile::GetExternalFileName() const
|
||||
{
|
||||
if ( !IsDataAvailable() )
|
||||
return GetEncodedAudioFilename();
|
||||
return SimpleBlockFile::GetExternalFileName();
|
||||
}
|
||||
|
||||
void ODDecodeBlockFile::SetExternalFileName( wxFileNameWrapper &&newName )
|
||||
{
|
||||
ChangeAudioFile( std::move( newName ) );
|
||||
}
|
||||
|
||||
/// Modify this block to point at a different file. This is generally
|
||||
/// looked down on, but it is necessary in one case: see
|
||||
/// DirManager::EnsureSafeFilename().
|
||||
@ -512,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;
|
||||
}
|
||||
};
|
||||
|
@ -56,6 +56,9 @@ class ODDecodeBlockFile final : public SimpleBlockFile
|
||||
/// Returns TRUE if the summary has not yet been written, but is actively being computed and written to disk
|
||||
bool IsSummaryBeingComputed() override { return false; }
|
||||
|
||||
const wxFileNameWrapper &GetExternalFileName() const override;
|
||||
void SetExternalFileName( wxFileNameWrapper &&newName ) override;
|
||||
|
||||
//Calls that rely on summary files need to be overidden
|
||||
DiskByteCount GetSpaceUsage() const override;
|
||||
/// Gets extreme values for the specified region
|
||||
@ -138,7 +141,7 @@ class ODDecodeBlockFile final : public SimpleBlockFile
|
||||
|
||||
///// Get the name of the file where the audio data for this block is
|
||||
/// stored.
|
||||
const wxFileName &GetEncodedAudioFilename()
|
||||
const wxFileNameWrapper &GetEncodedAudioFilename() const
|
||||
{
|
||||
return mAudioFileName;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -200,3 +200,9 @@ void PCMAliasBlockFile::Recover(void)
|
||||
WriteSummary();
|
||||
}
|
||||
|
||||
static DirManager::RegisteredBlockFileDeserializer sRegistration {
|
||||
"pcmaliasblockfile",
|
||||
[]( DirManager &dm, const wxChar **attrs ){
|
||||
return PCMAliasBlockFile::BuildFromXML( dm, attrs );
|
||||
}
|
||||
};
|
||||
|
@ -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 );
|
||||
}
|
||||
};
|
||||
|
@ -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 );
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user