mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-05 14:18:53 +02:00
Manage block files with std::shared_ptr, BlockHash stores weak_ptr
This commit is contained in:
commit
3dfed7a79a
@ -338,7 +338,7 @@ bool RecordingRecoveryHandler::HandleXMLTag(const wxChar *tag,
|
||||
BlockArray array;
|
||||
array.resize(1);
|
||||
dirManager->SetLoadingTarget(&array, 0);
|
||||
BlockFile *& blockFile = array[0].f;
|
||||
auto &blockFile = array[0].f;
|
||||
|
||||
if (!dirManager->HandleXMLTag(tag, attrs) || !blockFile)
|
||||
{
|
||||
|
@ -101,7 +101,6 @@ ArrayOf<char> BlockFile::fullSummary;
|
||||
/// @param samples The number of samples this BlockFile contains.
|
||||
BlockFile::BlockFile(wxFileNameWrapper &&fileName, sampleCount samples):
|
||||
mLockCount(0),
|
||||
mRefCount(1),
|
||||
mFileName(std::move(fileName)),
|
||||
mLen(samples),
|
||||
mSummaryInfo(samples)
|
||||
@ -109,10 +108,15 @@ BlockFile::BlockFile(wxFileNameWrapper &&fileName, sampleCount samples):
|
||||
mSilentLog=FALSE;
|
||||
}
|
||||
|
||||
// static
|
||||
unsigned long BlockFile::gBlockFileDestructionCount { 0 };
|
||||
|
||||
BlockFile::~BlockFile()
|
||||
{
|
||||
if (!IsLocked() && mFileName.HasName())
|
||||
wxRemoveFile(mFileName.GetFullPath());
|
||||
|
||||
++gBlockFileDestructionCount;
|
||||
}
|
||||
|
||||
/// Returns the file name of the disk file associated with this
|
||||
@ -160,28 +164,6 @@ bool BlockFile::IsLocked()
|
||||
return mLockCount > 0;
|
||||
}
|
||||
|
||||
/// Increases the reference count of this block by one. Only
|
||||
/// DirManager should call this method.
|
||||
void BlockFile::Ref() const
|
||||
{
|
||||
mRefCount++;
|
||||
BLOCKFILE_DEBUG_OUTPUT("Ref", mRefCount);
|
||||
}
|
||||
|
||||
/// Decreases the reference count of this block by one. If this
|
||||
/// causes the count to become zero, deletes the associated disk
|
||||
/// file and deletes this object
|
||||
bool BlockFile::Deref() const
|
||||
{
|
||||
mRefCount--;
|
||||
BLOCKFILE_DEBUG_OUTPUT("Deref", mRefCount);
|
||||
if (mRefCount <= 0) {
|
||||
delete this;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Get a buffer containing a summary block describing this sample
|
||||
/// data. This must be called by derived classes when they
|
||||
/// are constructed, to allow them to construct their summary data,
|
||||
|
@ -43,6 +43,15 @@ class SummaryInfo {
|
||||
|
||||
|
||||
|
||||
class BlockFile;
|
||||
using BlockFilePtr = std::shared_ptr<BlockFile>;
|
||||
|
||||
template< typename Result, typename... Args >
|
||||
inline std::shared_ptr< Result > make_blockfile (Args && ... args)
|
||||
{
|
||||
return std::make_shared< Result > ( std::forward< Args > ( args )... );
|
||||
}
|
||||
|
||||
class PROFILE_DLL_API BlockFile /* not final, abstract */ {
|
||||
public:
|
||||
|
||||
@ -52,6 +61,8 @@ class PROFILE_DLL_API BlockFile /* not final, abstract */ {
|
||||
BlockFile(wxFileNameWrapper &&fileName, sampleCount samples);
|
||||
virtual ~BlockFile();
|
||||
|
||||
static unsigned long gBlockFileDestructionCount;
|
||||
|
||||
// Reading
|
||||
|
||||
/// Retrieves audio data from this BlockFile
|
||||
@ -127,7 +138,7 @@ class PROFILE_DLL_API BlockFile /* not final, abstract */ {
|
||||
virtual bool IsSummaryBeingComputed(){return false;}
|
||||
|
||||
/// Create a NEW BlockFile identical to this, using the given filename
|
||||
virtual BlockFile * Copy(wxFileNameWrapper &&newFileName) = 0;
|
||||
virtual BlockFilePtr Copy(wxFileNameWrapper &&newFileName) = 0;
|
||||
|
||||
virtual wxLongLong GetSpaceUsage() const = 0;
|
||||
|
||||
@ -154,17 +165,6 @@ class PROFILE_DLL_API BlockFile /* not final, abstract */ {
|
||||
|
||||
private:
|
||||
|
||||
friend class DirManager;
|
||||
friend class AudacityApp;
|
||||
//needed for Ref/Deref access.
|
||||
friend class ODComputeSummaryTask;
|
||||
friend class ODDecodeTask;
|
||||
friend class ODPCMAliasBlockFile;
|
||||
|
||||
virtual void Ref() const;
|
||||
virtual bool Deref() const;
|
||||
virtual int RefCount(){return mRefCount;}
|
||||
|
||||
protected:
|
||||
/// Calculate summary data for the given sample data
|
||||
/// Overrides have differing details of memory management
|
||||
@ -185,7 +185,6 @@ class PROFILE_DLL_API BlockFile /* not final, abstract */ {
|
||||
|
||||
private:
|
||||
int mLockCount;
|
||||
mutable int mRefCount;
|
||||
|
||||
static ArrayOf<char> fullSummary;
|
||||
|
||||
|
@ -45,9 +45,10 @@
|
||||
WX_DECLARE_HASH_MAP(wxString, AliasedFile *,
|
||||
wxStringHash, wxStringEqual, AliasedFileHash);
|
||||
|
||||
WX_DECLARE_HASH_MAP(BlockFile *, BlockFile *,
|
||||
// These two hash types are used only inside short scopes
|
||||
// so it is safe to key them by plain pointers.
|
||||
WX_DECLARE_HASH_MAP(BlockFile *, BlockFilePtr,
|
||||
wxPointerHash, wxPointerEqual, ReplacedBlockFileHash);
|
||||
|
||||
WX_DECLARE_HASH_MAP(BlockFile *, bool,
|
||||
wxPointerHash, wxPointerEqual, BoolBlockFileHash);
|
||||
|
||||
@ -89,14 +90,11 @@ static void ReplaceBlockFiles(AudacityProject *project,
|
||||
|
||||
int i;
|
||||
for (i = 0; i < (int)blocks.size(); i++) {
|
||||
if (hash.count(blocks[i]->f) > 0) {
|
||||
BlockFile *src = blocks[i]->f;
|
||||
BlockFile *dst = hash[src];
|
||||
|
||||
dirManager->Deref(src);
|
||||
dirManager->Ref(dst);
|
||||
|
||||
blocks[i]->f = dst;
|
||||
auto &f = blocks[i]->f;
|
||||
const auto src = &*f;
|
||||
if (hash.count( src ) > 0) {
|
||||
const auto &dst = hash[src];
|
||||
f = dst;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -113,12 +111,12 @@ void FindDependencies(AudacityProject *project,
|
||||
BoolBlockFileHash blockFileHash;
|
||||
|
||||
for (const auto &blockFile : blocks) {
|
||||
BlockFile *f = blockFile->f;
|
||||
if (f->IsAlias() && (blockFileHash.count(f) == 0))
|
||||
const auto &f = blockFile->f;
|
||||
if (f->IsAlias() && (blockFileHash.count( &*f ) == 0))
|
||||
{
|
||||
// f is an alias block we have not yet counted.
|
||||
blockFileHash[f] = true; // Don't count the same blockfile twice.
|
||||
AliasBlockFile *aliasBlockFile = static_cast<AliasBlockFile*>(f);
|
||||
blockFileHash[ &*f ] = true; // Don't count the same blockfile twice.
|
||||
auto aliasBlockFile = static_cast<AliasBlockFile*>( &*f );
|
||||
const wxFileName &fileName = aliasBlockFile->GetAliasedFileName();
|
||||
|
||||
// In DirManager::ProjectFSCK(), if the user has chosen to
|
||||
@ -183,11 +181,11 @@ static void RemoveDependencies(AudacityProject *project,
|
||||
ReplacedBlockFileHash blockFileHash;
|
||||
wxLongLong completedBytes = 0;
|
||||
for (const auto blockFile : blocks) {
|
||||
BlockFile *f = blockFile->f;
|
||||
if (f->IsAlias() && (blockFileHash.count(f) == 0))
|
||||
const auto &f = blockFile->f;
|
||||
if (f->IsAlias() && (blockFileHash.count( &*f ) == 0))
|
||||
{
|
||||
// f is an alias block we have not yet processed.
|
||||
AliasBlockFile *aliasBlockFile = static_cast<AliasBlockFile*>(f);
|
||||
auto aliasBlockFile = static_cast<AliasBlockFile*>( &*f );
|
||||
const wxFileName &fileName = aliasBlockFile->GetAliasedFileName();
|
||||
const wxString &fileNameStr = fileName.GetFullPath();
|
||||
|
||||
@ -197,7 +195,7 @@ static void RemoveDependencies(AudacityProject *project,
|
||||
|
||||
// Convert it from an aliased file to an actual file in the project.
|
||||
unsigned int len = aliasBlockFile->GetLength();
|
||||
BlockFile *newBlockFile;
|
||||
BlockFilePtr newBlockFile;
|
||||
{
|
||||
SampleBuffer buffer(len, format);
|
||||
f->ReadData(buffer.ptr(), format, 0, len);
|
||||
@ -206,7 +204,7 @@ static void RemoveDependencies(AudacityProject *project,
|
||||
}
|
||||
|
||||
// Update our hash so we know what block files we've done
|
||||
blockFileHash[f] = newBlockFile;
|
||||
blockFileHash[ &*f ] = newBlockFile;
|
||||
|
||||
// Update the progress bar
|
||||
completedBytes += SAMPLE_SIZE(format) * len;
|
||||
@ -221,11 +219,6 @@ static void RemoveDependencies(AudacityProject *project,
|
||||
// However, that didn't actually change any references to these
|
||||
// blockfiles in the Sequences, so we do that next...
|
||||
ReplaceBlockFiles(project, blockFileHash);
|
||||
|
||||
// Subtract one from reference count of NEW block files; they're
|
||||
// now all referenced the proper number of times by the Sequences
|
||||
for (const auto &pair : blockFileHash)
|
||||
dirManager->Deref(pair.second);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -319,6 +319,8 @@ DirManager::DirManager()
|
||||
{
|
||||
wxLogDebug(wxT("DirManager: Created new instance."));
|
||||
|
||||
mLastBlockFileDestructionCount = BlockFile::gBlockFileDestructionCount;
|
||||
|
||||
// Seed the random number generator.
|
||||
// this need not be strictly uniform or random, but it should give
|
||||
// unclustered numbers
|
||||
@ -347,8 +349,11 @@ DirManager::DirManager()
|
||||
|
||||
// toplevel pool hash is fully populated to begin
|
||||
{
|
||||
int i;
|
||||
for(i=0; i< 256; i++) dirTopPool[i]=0;
|
||||
// We can bypass the accessor function while initializing
|
||||
auto &balanceInfo = mBalanceInfo;
|
||||
auto &dirTopPool = balanceInfo.dirTopPool;
|
||||
for(int i = 0; i < 256; ++i)
|
||||
dirTopPool[i] = 0;
|
||||
}
|
||||
|
||||
// Make sure there is plenty of space for temp files
|
||||
@ -435,6 +440,8 @@ bool DirManager::SetProject(wxString& newProjPath, wxString& newProjName, const
|
||||
saved version of the old project must not be moved,
|
||||
otherwise the old project would not be safe.) */
|
||||
|
||||
int trueTotal = 0;
|
||||
|
||||
{
|
||||
/*i18n-hint: This title appears on a dialog that indicates the progress in doing something.*/
|
||||
ProgressDialog progress(_("Progress"),
|
||||
@ -447,12 +454,15 @@ bool DirManager::SetProject(wxString& newProjPath, wxString& newProjName, const
|
||||
int count = 0;
|
||||
while ((iter != mBlockFileHash.end()) && success)
|
||||
{
|
||||
BlockFile *b = iter->second;
|
||||
BlockFilePtr b = iter->second.lock();
|
||||
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
if (b->IsLocked())
|
||||
success = CopyToNewProjectDirectory(b);
|
||||
success = CopyToNewProjectDirectory( &*b );
|
||||
else{
|
||||
success = MoveToNewProjectDirectory(b);
|
||||
success = MoveToNewProjectDirectory( &*b );
|
||||
}
|
||||
|
||||
progress.Update(count, total);
|
||||
@ -461,6 +471,9 @@ bool DirManager::SetProject(wxString& newProjPath, wxString& newProjName, const
|
||||
count++;
|
||||
}
|
||||
|
||||
// in case there are any nulls
|
||||
trueTotal = count;
|
||||
|
||||
if (!success) {
|
||||
// If the move failed, we try to move/copy as many files
|
||||
// back as possible so that no damage was done. (No sense
|
||||
@ -473,8 +486,12 @@ bool DirManager::SetProject(wxString& newProjPath, wxString& newProjName, const
|
||||
BlockHash::iterator iter = mBlockFileHash.begin();
|
||||
while (iter != mBlockFileHash.end())
|
||||
{
|
||||
BlockFile *b = iter->second;
|
||||
MoveToNewProjectDirectory(b);
|
||||
BlockFilePtr b = iter->second.lock();
|
||||
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
MoveToNewProjectDirectory(&*b);
|
||||
|
||||
if (count >= 0)
|
||||
progress.Update(count, total);
|
||||
@ -496,7 +513,7 @@ bool DirManager::SetProject(wxString& newProjPath, wxString& newProjName, const
|
||||
// loading a project; in this latter case, the movement code does
|
||||
// nothing because SetProject is called before there are any
|
||||
// blockfiles. Cleanup code trigger is the same
|
||||
if (mBlockFileHash.size()>0){
|
||||
if (trueTotal > 0) {
|
||||
// Clean up after ourselves; look for empty directories in the old
|
||||
// and NEW project directories. The easiest way to do this is to
|
||||
// recurse depth-first and rmdir every directory seen in old and
|
||||
@ -638,6 +655,12 @@ int DirManager::BalanceMidAdd(int topnum, int midkey)
|
||||
{
|
||||
// enter the midlevel directory if it doesn't exist
|
||||
|
||||
auto &balanceInfo = GetBalanceInfo();
|
||||
auto &dirMidPool = balanceInfo.dirMidPool;
|
||||
auto &dirMidFull = balanceInfo.dirMidFull;
|
||||
auto &dirTopPool = balanceInfo.dirTopPool;
|
||||
auto &dirTopFull = balanceInfo.dirTopFull;
|
||||
|
||||
if(dirMidPool.find(midkey) == dirMidPool.end() &&
|
||||
dirMidFull.find(midkey) == dirMidFull.end()){
|
||||
dirMidPool[midkey]=0;
|
||||
@ -656,6 +679,10 @@ int DirManager::BalanceMidAdd(int topnum, int midkey)
|
||||
|
||||
void DirManager::BalanceFileAdd(int midkey)
|
||||
{
|
||||
auto &balanceInfo = GetBalanceInfo();
|
||||
auto &dirMidPool = balanceInfo.dirMidPool;
|
||||
auto &dirMidFull = balanceInfo.dirMidFull;
|
||||
|
||||
// increment the midlevel directory usage information
|
||||
if(dirMidPool.find(midkey) != dirMidPool.end()){
|
||||
dirMidPool[midkey]++;
|
||||
@ -688,11 +715,46 @@ void DirManager::BalanceInfoAdd(const wxString &file)
|
||||
}
|
||||
}
|
||||
|
||||
auto DirManager::GetBalanceInfo() -> BalanceInfo &
|
||||
{
|
||||
// Before returning the map,
|
||||
// see whether any block files have disappeared,
|
||||
// and if so update
|
||||
|
||||
auto count = BlockFile::gBlockFileDestructionCount;
|
||||
if ( mLastBlockFileDestructionCount != count ) {
|
||||
auto it = mBlockFileHash.begin(), end = mBlockFileHash.end();
|
||||
while (it != end)
|
||||
{
|
||||
BlockFilePtr ptr { it->second.lock() };
|
||||
if (!ptr) {
|
||||
auto name = it->first;
|
||||
mBlockFileHash.erase( it++ );
|
||||
BalanceInfoDel( name );
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
mLastBlockFileDestructionCount = count;
|
||||
|
||||
return mBalanceInfo;
|
||||
}
|
||||
|
||||
// Note that this will try to clean up directories out from under even
|
||||
// locked blockfiles; this is actually harmless as the rmdir will fail
|
||||
// on non-empty directories.
|
||||
void DirManager::BalanceInfoDel(const wxString &file)
|
||||
{
|
||||
// do not use GetBalanceInfo(),
|
||||
// rather this function will be called from there.
|
||||
auto &balanceInfo = mBalanceInfo;
|
||||
auto &dirMidPool = balanceInfo.dirMidPool;
|
||||
auto &dirMidFull = balanceInfo.dirMidFull;
|
||||
auto &dirTopPool = balanceInfo.dirTopPool;
|
||||
auto &dirTopFull = balanceInfo.dirTopFull;
|
||||
|
||||
const wxChar *s=file.c_str();
|
||||
if(s[0]==wxT('e')){
|
||||
// this is one of the modern two-deep managed files
|
||||
@ -754,6 +816,11 @@ void DirManager::BalanceInfoDel(const wxString &file)
|
||||
// perform maintainence
|
||||
wxFileNameWrapper DirManager::MakeBlockFileName()
|
||||
{
|
||||
auto &balanceInfo = GetBalanceInfo();
|
||||
auto &dirMidPool = balanceInfo.dirMidPool;
|
||||
auto &dirTopPool = balanceInfo.dirTopPool;
|
||||
auto &dirTopFull = balanceInfo.dirTopFull;
|
||||
|
||||
wxFileNameWrapper ret;
|
||||
wxString baseFileName;
|
||||
|
||||
@ -841,7 +908,7 @@ wxFileNameWrapper DirManager::MakeBlockFileName()
|
||||
|
||||
baseFileName.Printf(wxT("e%02x%02x%03x"),topnum,midnum,filenum);
|
||||
|
||||
if (mBlockFileHash.find(baseFileName) == mBlockFileHash.end()){
|
||||
if (!ContainsBlockFile(baseFileName)) {
|
||||
// not in the hash, good.
|
||||
if (!this->AssignFile(ret, baseFileName, true))
|
||||
{
|
||||
@ -863,7 +930,7 @@ wxFileNameWrapper DirManager::MakeBlockFileName()
|
||||
return std::move(ret);
|
||||
}
|
||||
|
||||
BlockFile *DirManager::NewSimpleBlockFile(
|
||||
BlockFilePtr DirManager::NewSimpleBlockFile(
|
||||
samplePtr sampleData, sampleCount sampleLen,
|
||||
sampleFormat format,
|
||||
bool allowDeferredWrite)
|
||||
@ -871,26 +938,24 @@ BlockFile *DirManager::NewSimpleBlockFile(
|
||||
wxFileNameWrapper filePath{ MakeBlockFileName() };
|
||||
const wxString fileName{ filePath.GetName() };
|
||||
|
||||
BlockFile *newBlockFile =
|
||||
new SimpleBlockFile(std::move(filePath), sampleData, sampleLen, format,
|
||||
allowDeferredWrite);
|
||||
auto newBlockFile = make_blockfile<SimpleBlockFile>
|
||||
(std::move(filePath), sampleData, sampleLen, format, allowDeferredWrite);
|
||||
|
||||
mBlockFileHash[fileName]=newBlockFile;
|
||||
mBlockFileHash[fileName] = newBlockFile;
|
||||
|
||||
return newBlockFile;
|
||||
}
|
||||
|
||||
BlockFile *DirManager::NewAliasBlockFile(
|
||||
BlockFilePtr DirManager::NewAliasBlockFile(
|
||||
const wxString &aliasedFile, sampleCount aliasStart,
|
||||
sampleCount aliasLen, int aliasChannel)
|
||||
{
|
||||
wxFileNameWrapper filePath{ MakeBlockFileName() };
|
||||
const wxString fileName = filePath.GetName();
|
||||
|
||||
BlockFile *newBlockFile =
|
||||
new PCMAliasBlockFile(std::move(filePath),
|
||||
wxFileNameWrapper{aliasedFile},
|
||||
aliasStart, aliasLen, aliasChannel);
|
||||
auto newBlockFile = make_blockfile<PCMAliasBlockFile>
|
||||
(std::move(filePath), wxFileNameWrapper{aliasedFile},
|
||||
aliasStart, aliasLen, aliasChannel);
|
||||
|
||||
mBlockFileHash[fileName]=newBlockFile;
|
||||
aliasList.Add(aliasedFile);
|
||||
@ -898,16 +963,16 @@ BlockFile *DirManager::NewAliasBlockFile(
|
||||
return newBlockFile;
|
||||
}
|
||||
|
||||
BlockFile *DirManager::NewODAliasBlockFile(
|
||||
BlockFilePtr DirManager::NewODAliasBlockFile(
|
||||
const wxString &aliasedFile, sampleCount aliasStart,
|
||||
sampleCount aliasLen, int aliasChannel)
|
||||
{
|
||||
wxFileNameWrapper filePath{ MakeBlockFileName() };
|
||||
const wxString fileName{ filePath.GetName() };
|
||||
|
||||
BlockFile *newBlockFile =
|
||||
new ODPCMAliasBlockFile(std::move(filePath),
|
||||
wxFileNameWrapper{aliasedFile}, aliasStart, aliasLen, aliasChannel);
|
||||
auto newBlockFile = make_blockfile<ODPCMAliasBlockFile>
|
||||
(std::move(filePath), wxFileNameWrapper{aliasedFile},
|
||||
aliasStart, aliasLen, aliasChannel);
|
||||
|
||||
mBlockFileHash[fileName]=newBlockFile;
|
||||
aliasList.Add(aliasedFile);
|
||||
@ -915,16 +980,16 @@ BlockFile *DirManager::NewODAliasBlockFile(
|
||||
return newBlockFile;
|
||||
}
|
||||
|
||||
BlockFile *DirManager::NewODDecodeBlockFile(
|
||||
BlockFilePtr DirManager::NewODDecodeBlockFile(
|
||||
const wxString &aliasedFile, sampleCount aliasStart,
|
||||
sampleCount aliasLen, int aliasChannel, int decodeType)
|
||||
{
|
||||
wxFileNameWrapper filePath{ MakeBlockFileName() };
|
||||
const wxString fileName{ filePath.GetName() };
|
||||
|
||||
BlockFile *newBlockFile =
|
||||
new ODDecodeBlockFile(std::move(filePath),
|
||||
wxFileNameWrapper{aliasedFile}, aliasStart, aliasLen, aliasChannel, decodeType);
|
||||
auto newBlockFile = make_blockfile<ODDecodeBlockFile>
|
||||
(std::move(filePath), wxFileNameWrapper{ aliasedFile },
|
||||
aliasStart, aliasLen, aliasChannel, decodeType);
|
||||
|
||||
mBlockFileHash[fileName]=newBlockFile;
|
||||
aliasList.Add(aliasedFile); //OD TODO: check to see if we need to remove this when done decoding.
|
||||
@ -939,26 +1004,29 @@ bool DirManager::ContainsBlockFile(const BlockFile *b) const
|
||||
return false;
|
||||
auto result = b->GetFileName();
|
||||
BlockHash::const_iterator it = mBlockFileHash.find(result.name.GetName());
|
||||
return it != mBlockFileHash.end() && it->second == b;
|
||||
if (it == mBlockFileHash.end())
|
||||
return false;
|
||||
BlockFilePtr ptr = it->second.lock();
|
||||
return ptr && (b == &*ptr);
|
||||
}
|
||||
|
||||
bool DirManager::ContainsBlockFile(const wxString &filepath) const
|
||||
{
|
||||
// check what the hash returns in case the blockfile is from a different project
|
||||
BlockHash::const_iterator it = mBlockFileHash.find(filepath);
|
||||
return it != mBlockFileHash.end();
|
||||
return it != mBlockFileHash.end() &&
|
||||
BlockFilePtr{ it->second.lock() };
|
||||
}
|
||||
|
||||
// Adds one to the reference count of the block file,
|
||||
// UNLESS it is "locked", then it makes a NEW copy of
|
||||
// the BlockFile.
|
||||
BlockFile *DirManager::CopyBlockFile(BlockFile *b)
|
||||
BlockFilePtr DirManager::CopyBlockFile(const BlockFilePtr &b)
|
||||
{
|
||||
auto result = b->GetFileName();
|
||||
const auto &fn = result.name;
|
||||
|
||||
if (!b->IsLocked()) {
|
||||
b->Ref();
|
||||
//mchinen:July 13 2009 - not sure about this, but it needs to be added to the hash to be able to save if not locked.
|
||||
//note that this shouldn't hurt mBlockFileHash's that already contain the filename, since it should just overwrite.
|
||||
//but it's something to watch out for.
|
||||
@ -970,7 +1038,7 @@ BlockFile *DirManager::CopyBlockFile(BlockFile *b)
|
||||
}
|
||||
|
||||
// Copy the blockfile
|
||||
BlockFile *b2;
|
||||
BlockFilePtr b2;
|
||||
if (!fn.IsOk())
|
||||
// Block files with uninitialized filename (i.e. SilentBlockFile)
|
||||
// just need an in-memory copy.
|
||||
@ -991,7 +1059,7 @@ BlockFile *DirManager::CopyBlockFile(BlockFile *b)
|
||||
{
|
||||
if( !wxCopyFile(fn.GetFullPath(),
|
||||
newFile.GetFullPath()) )
|
||||
return NULL;
|
||||
return {};
|
||||
}
|
||||
|
||||
// Done with fn
|
||||
@ -1000,7 +1068,7 @@ BlockFile *DirManager::CopyBlockFile(BlockFile *b)
|
||||
b2 = b->Copy(std::move(newFile));
|
||||
|
||||
if (b2 == NULL)
|
||||
return NULL;
|
||||
return {};
|
||||
|
||||
mBlockFileHash[newName]=b2;
|
||||
aliasList.Add(newPath);
|
||||
@ -1014,9 +1082,9 @@ bool DirManager::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
|
||||
if( mLoadingTarget == NULL )
|
||||
return false;
|
||||
|
||||
BlockFile* pBlockFile = NULL;
|
||||
BlockFilePtr pBlockFile {};
|
||||
|
||||
BlockFile *&target = mLoadingTarget->at(mLoadingTargetIdx).f;
|
||||
BlockFilePtr &target = mLoadingTarget->at(mLoadingTargetIdx).f;
|
||||
|
||||
if (!wxStricmp(tag, wxT("silentblockfile"))) {
|
||||
// Silent blocks don't actually have a file associated, so
|
||||
@ -1079,7 +1147,6 @@ bool DirManager::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
|
||||
// See http://bugzilla.audacityteam.org/show_bug.cgi?id=451#c13.
|
||||
// Lock pBlockFile so that the ~BlockFile() will not DELETE the file on disk.
|
||||
pBlockFile->Lock();
|
||||
delete pBlockFile;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
@ -1092,20 +1159,19 @@ bool DirManager::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
|
||||
//
|
||||
|
||||
wxString name = target->GetFileName().name.GetName();
|
||||
BlockFile *retrieved = mBlockFileHash[name];
|
||||
auto &wRetrieved = mBlockFileHash[name];
|
||||
BlockFilePtr retrieved = wRetrieved.lock();
|
||||
if (retrieved) {
|
||||
// Lock it in order to DELETE it safely, i.e. without having
|
||||
// it DELETE the file, too...
|
||||
target->Lock();
|
||||
delete target;
|
||||
|
||||
Ref(retrieved); // Add one to its reference count
|
||||
target = retrieved;
|
||||
return true;
|
||||
}
|
||||
|
||||
// This is a NEW object
|
||||
mBlockFileHash[name] = target;
|
||||
wRetrieved = target;
|
||||
// MakeBlockFileName wasn't used so we must add the directory
|
||||
// balancing information
|
||||
BalanceInfoAdd(name);
|
||||
@ -1192,38 +1258,6 @@ bool DirManager::CopyToNewProjectDirectory(BlockFile *f)
|
||||
return MoveOrCopyToNewProjectDirectory(f, true);
|
||||
}
|
||||
|
||||
void DirManager::Ref(BlockFile * f)
|
||||
{
|
||||
f->Ref();
|
||||
//printf("Ref(%d): %s\n",
|
||||
// f->mRefCount,
|
||||
// (const char *)f->mFileName.GetFullPath().mb_str());
|
||||
}
|
||||
|
||||
int DirManager::GetRefCount(BlockFile * f)
|
||||
{
|
||||
return f->mRefCount;
|
||||
}
|
||||
|
||||
void DirManager::Deref(BlockFile * f)
|
||||
{
|
||||
const wxString theFileName = f->GetFileName().name.GetName();
|
||||
|
||||
//printf("Deref(%d): %s\n",
|
||||
// f->mRefCount-1,
|
||||
// (const char *)f->mFileName.GetFullPath().mb_str());
|
||||
|
||||
if (f->Deref()) {
|
||||
// If Deref() returned true, the reference count reached zero
|
||||
// and this block is no longer needed. Remove it from the hash
|
||||
// table.
|
||||
|
||||
mBlockFileHash.erase(theFileName);
|
||||
BalanceInfoDel(theFileName);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool DirManager::EnsureSafeFilename(const wxFileName &fName)
|
||||
{
|
||||
// Quick check: If it's not even in our alias list,
|
||||
@ -1284,13 +1318,17 @@ bool DirManager::EnsureSafeFilename(const wxFileName &fName)
|
||||
BlockHash::iterator iter = mBlockFileHash.begin();
|
||||
while (iter != mBlockFileHash.end())
|
||||
{
|
||||
BlockFile *b = iter->second;
|
||||
BlockFilePtr b = iter->second.lock();
|
||||
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
// don't worry, we don't rely on this cast unless IsAlias is true
|
||||
AliasBlockFile *ab = (AliasBlockFile*)b;
|
||||
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.
|
||||
ODDecodeBlockFile *db = (ODDecodeBlockFile*)b;
|
||||
auto db = static_cast< ODDecodeBlockFile * > ( &*b );
|
||||
|
||||
if (b->IsAlias() && ab->GetAliasedFileName() == fName) {
|
||||
needToRename = true;
|
||||
@ -1323,9 +1361,13 @@ bool DirManager::EnsureSafeFilename(const wxFileName &fName)
|
||||
BlockHash::iterator iter = mBlockFileHash.begin();
|
||||
while (iter != mBlockFileHash.end())
|
||||
{
|
||||
BlockFile *b = iter->second;
|
||||
AliasBlockFile *ab = (AliasBlockFile*)b;
|
||||
ODDecodeBlockFile *db = (ODDecodeBlockFile*)b;
|
||||
BlockFilePtr b = iter->second.lock();
|
||||
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
auto ab = static_cast< AliasBlockFile * > ( &*b );
|
||||
auto db = static_cast< ODDecodeBlockFile * > ( &*b );
|
||||
|
||||
if (b->IsAlias() && (ab->GetAliasedFileName() == fName))
|
||||
ab->UnlockRead();
|
||||
@ -1347,9 +1389,13 @@ bool DirManager::EnsureSafeFilename(const wxFileName &fName)
|
||||
BlockHash::iterator iter = mBlockFileHash.begin();
|
||||
while (iter != mBlockFileHash.end())
|
||||
{
|
||||
BlockFile *b = iter->second;
|
||||
AliasBlockFile *ab = (AliasBlockFile*)b;
|
||||
ODDecodeBlockFile *db = (ODDecodeBlockFile*)b;
|
||||
BlockFilePtr b = iter->second.lock();
|
||||
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
auto ab = static_cast< AliasBlockFile * > ( &*b );
|
||||
auto db = static_cast< ODDecodeBlockFile * > ( &*b );
|
||||
|
||||
if (b->IsAlias() && ab->GetAliasedFileName() == fName)
|
||||
{
|
||||
@ -1477,11 +1523,17 @@ _("Project check of \"%s\" folder \
|
||||
BlockHash::iterator iter = missingAliasedFileAUFHash.begin();
|
||||
while (iter != missingAliasedFileAUFHash.end())
|
||||
{
|
||||
// This type caste is safe. We checked that it's an alias block file earlier.
|
||||
AliasBlockFile *b = (AliasBlockFile*)iter->second;
|
||||
// This type cast is safe. We checked that it's an alias block file earlier.
|
||||
BlockFilePtr b = iter->second.lock();
|
||||
|
||||
wxASSERT(b);
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
auto ab = static_cast< AliasBlockFile * > ( &*b );
|
||||
if (action == 1)
|
||||
// Silence error logging for this block in this session.
|
||||
b->SilenceAliasLog();
|
||||
ab->SilenceAliasLog();
|
||||
else if (action == 2)
|
||||
{
|
||||
// silence the blockfiles by yanking the filename
|
||||
@ -1490,8 +1542,8 @@ _("Project check of \"%s\" folder \
|
||||
// There, if the mAliasedFileName is bad, it zeroes the data.
|
||||
wxFileNameWrapper dummy;
|
||||
dummy.Clear();
|
||||
b->ChangeAliasedFileName(std::move(dummy));
|
||||
b->Recover();
|
||||
ab->ChangeAliasedFileName(std::move(dummy));
|
||||
ab->Recover();
|
||||
nResult = FSCKstatus_CHANGED | FSCKstatus_SAVE_AUP;
|
||||
}
|
||||
++iter;
|
||||
@ -1539,7 +1591,12 @@ _("Project check of \"%s\" folder \
|
||||
BlockHash::iterator iter = missingAUFHash.begin();
|
||||
while (iter != missingAUFHash.end())
|
||||
{
|
||||
BlockFile *b = iter->second;
|
||||
BlockFilePtr b = iter->second.lock();
|
||||
|
||||
wxASSERT(b);
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
if(action==0){
|
||||
//regenerate from data
|
||||
b->Recover();
|
||||
@ -1598,7 +1655,12 @@ _("Project check of \"%s\" folder \
|
||||
BlockHash::iterator iter = missingAUHash.begin();
|
||||
while (iter != missingAUHash.end())
|
||||
{
|
||||
BlockFile *b = iter->second;
|
||||
BlockFilePtr b = iter->second.lock();
|
||||
|
||||
wxASSERT(b);
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
if (action == 2)
|
||||
{
|
||||
//regenerate with zeroes
|
||||
@ -1705,10 +1767,15 @@ void DirManager::FindMissingAliasedFiles(
|
||||
while (iter != mBlockFileHash.end())
|
||||
{
|
||||
wxString key = iter->first; // file name and extension
|
||||
BlockFile *b = iter->second;
|
||||
BlockFilePtr b = iter->second.lock();
|
||||
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
if (b->IsAlias())
|
||||
{
|
||||
const wxFileName &aliasedFileName = ((AliasBlockFile*)b)->GetAliasedFileName();
|
||||
const wxFileName &aliasedFileName =
|
||||
static_cast< AliasBlockFile* > ( &*b )->GetAliasedFileName();
|
||||
wxString aliasedFileFullPath = aliasedFileName.GetFullPath();
|
||||
// wxEmptyString can happen if user already chose to "replace... with silence".
|
||||
if ((aliasedFileFullPath != wxEmptyString) &&
|
||||
@ -1719,7 +1786,7 @@ void DirManager::FindMissingAliasedFiles(
|
||||
missingAliasedFilePathHash.end()) // Add it only once.
|
||||
// Not actually using the block here, just the path,
|
||||
// so set the block to NULL to create the entry.
|
||||
missingAliasedFilePathHash[aliasedFileFullPath] = NULL;
|
||||
missingAliasedFilePathHash[aliasedFileFullPath] = {};
|
||||
}
|
||||
}
|
||||
++iter;
|
||||
@ -1740,7 +1807,11 @@ void DirManager::FindMissingAUFs(
|
||||
while (iter != mBlockFileHash.end())
|
||||
{
|
||||
const wxString &key = iter->first;
|
||||
BlockFile *b = iter->second;
|
||||
BlockFilePtr b = iter->second.lock();
|
||||
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
if (b->IsAlias() && b->IsSummaryAvailable())
|
||||
{
|
||||
/* don't look in hash; that might find files the user moved
|
||||
@ -1766,7 +1837,11 @@ void DirManager::FindMissingAUs(
|
||||
while (iter != mBlockFileHash.end())
|
||||
{
|
||||
const wxString &key = iter->first;
|
||||
BlockFile *b = iter->second;
|
||||
BlockFilePtr b = iter->second.lock();
|
||||
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
if (!b->IsAlias())
|
||||
{
|
||||
wxFileNameWrapper fileName{ MakeBlockFilePath(key) };
|
||||
@ -1866,7 +1941,11 @@ void DirManager::FillBlockfilesCache()
|
||||
iter = mBlockFileHash.begin();
|
||||
while (iter != mBlockFileHash.end())
|
||||
{
|
||||
BlockFile *b = iter->second;
|
||||
BlockFilePtr b = iter->second.lock();
|
||||
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
if (b->GetNeedFillCache())
|
||||
numNeed++;
|
||||
++iter;
|
||||
@ -1882,7 +1961,11 @@ void DirManager::FillBlockfilesCache()
|
||||
int current = 0;
|
||||
while (iter != mBlockFileHash.end())
|
||||
{
|
||||
BlockFile *b = iter->second;
|
||||
BlockFilePtr b = iter->second.lock();
|
||||
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
if (b->GetNeedFillCache() && (GetFreeMemory() > lowMem)) {
|
||||
b->FillCache();
|
||||
}
|
||||
@ -1903,7 +1986,11 @@ void DirManager::WriteCacheToDisk()
|
||||
iter = mBlockFileHash.begin();
|
||||
while (iter != mBlockFileHash.end())
|
||||
{
|
||||
BlockFile *b = iter->second;
|
||||
BlockFilePtr b = iter->second.lock();
|
||||
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
if (b->GetNeedWriteCacheToDisk())
|
||||
numNeed++;
|
||||
++iter;
|
||||
@ -1919,7 +2006,11 @@ void DirManager::WriteCacheToDisk()
|
||||
int current = 0;
|
||||
while (iter != mBlockFileHash.end())
|
||||
{
|
||||
BlockFile *b = iter->second;
|
||||
BlockFilePtr b = iter->second.lock();
|
||||
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
if (b->GetNeedWriteCacheToDisk())
|
||||
{
|
||||
b->WriteCacheToDisk();
|
||||
|
@ -32,7 +32,12 @@ class SequenceTest;
|
||||
#define FSCKstatus_SAVE_AUP 0x4 // used in combination with FSCKstatus_CHANGED
|
||||
|
||||
WX_DECLARE_HASH_MAP(int, int, wxIntegerHash, wxIntegerEqual, DirHash);
|
||||
WX_DECLARE_HASH_MAP(wxString, BlockFile*, wxStringHash, wxStringEqual, BlockHash);
|
||||
|
||||
class BlockFile;
|
||||
using BlockFilePtr = std::shared_ptr<BlockFile>;
|
||||
|
||||
WX_DECLARE_HASH_MAP(wxString, std::weak_ptr<BlockFile>, wxStringHash,
|
||||
wxStringEqual, BlockHash);
|
||||
|
||||
wxMemorySize GetFreeMemory();
|
||||
|
||||
@ -56,18 +61,22 @@ class PROFILE_DLL_API DirManager final : public XMLTagHandler {
|
||||
|
||||
wxLongLong GetFreeDiskSpace();
|
||||
|
||||
BlockFile *NewSimpleBlockFile(samplePtr sampleData,
|
||||
BlockFilePtr
|
||||
NewSimpleBlockFile(samplePtr sampleData,
|
||||
sampleCount sampleLen,
|
||||
sampleFormat format,
|
||||
bool allowDeferredWrite = false);
|
||||
|
||||
BlockFile *NewAliasBlockFile( const wxString &aliasedFile, sampleCount aliasStart,
|
||||
BlockFilePtr
|
||||
NewAliasBlockFile( const wxString &aliasedFile, sampleCount aliasStart,
|
||||
sampleCount aliasLen, int aliasChannel);
|
||||
|
||||
BlockFile *NewODAliasBlockFile( const wxString &aliasedFile, sampleCount aliasStart,
|
||||
BlockFilePtr
|
||||
NewODAliasBlockFile( const wxString &aliasedFile, sampleCount aliasStart,
|
||||
sampleCount aliasLen, int aliasChannel);
|
||||
|
||||
BlockFile *NewODDecodeBlockFile( const wxString &aliasedFile, sampleCount aliasStart,
|
||||
BlockFilePtr
|
||||
NewODDecodeBlockFile( const wxString &aliasedFile, sampleCount aliasStart,
|
||||
sampleCount aliasLen, int aliasChannel, int decodeType);
|
||||
|
||||
/// Returns true if the blockfile pointed to by b is contained by the DirManager
|
||||
@ -78,7 +87,7 @@ class PROFILE_DLL_API DirManager final : public XMLTagHandler {
|
||||
// Adds one to the reference count of the block file,
|
||||
// UNLESS it is "locked", then it makes a NEW copy of
|
||||
// the BlockFile.
|
||||
BlockFile *CopyBlockFile(BlockFile *b);
|
||||
BlockFilePtr CopyBlockFile(const BlockFilePtr &b);
|
||||
|
||||
BlockFile *LoadBlockFile(const wxChar **attrs, sampleFormat format);
|
||||
void SaveBlockFile(BlockFile *f, int depth, FILE *fp);
|
||||
@ -93,12 +102,6 @@ class PROFILE_DLL_API DirManager final : public XMLTagHandler {
|
||||
|
||||
bool EnsureSafeFilename(const wxFileName &fName);
|
||||
|
||||
void Ref(BlockFile * f);
|
||||
void Deref(BlockFile * f);
|
||||
|
||||
// For debugging only
|
||||
int GetRefCount(BlockFile * f);
|
||||
|
||||
void SetLoadingTarget(BlockArray *pArray, unsigned idx)
|
||||
{
|
||||
mLoadingTarget = pArray;
|
||||
@ -171,10 +174,19 @@ class PROFILE_DLL_API DirManager final : public XMLTagHandler {
|
||||
bool MoveOrCopyToNewProjectDirectory(BlockFile *f, bool copy);
|
||||
|
||||
BlockHash mBlockFileHash; // repository for blockfiles
|
||||
DirHash dirTopPool; // available toplevel dirs
|
||||
DirHash dirTopFull; // full toplevel dirs
|
||||
DirHash dirMidPool; // available two-level dirs
|
||||
DirHash dirMidFull; // full two-level dirs
|
||||
|
||||
// Hashes for management of the sub-directory tree of _data
|
||||
struct BalanceInfo
|
||||
{
|
||||
DirHash dirTopPool; // available toplevel dirs
|
||||
DirHash dirTopFull; // full toplevel dirs
|
||||
DirHash dirMidPool; // available two-level dirs
|
||||
DirHash dirMidFull; // full two-level dirs
|
||||
} mBalanceInfo;
|
||||
|
||||
// Accessor for the balance info, may need to do a delayed update for
|
||||
// deletion in case other threads delete block files
|
||||
BalanceInfo &GetBalanceInfo();
|
||||
|
||||
void BalanceInfoDel(const wxString&);
|
||||
void BalanceInfoAdd(const wxString&);
|
||||
@ -196,6 +208,8 @@ class PROFILE_DLL_API DirManager final : public XMLTagHandler {
|
||||
|
||||
sampleCount mMaxSamples; // max samples per block
|
||||
|
||||
unsigned long mLastBlockFileDestructionCount { 0 };
|
||||
|
||||
static wxString globaltemp;
|
||||
wxString mytemp;
|
||||
static int numDirManagers;
|
||||
|
@ -34,6 +34,7 @@ using std::isinf;
|
||||
namespace std {
|
||||
using std::tr1::shared_ptr;
|
||||
using std::tr1::weak_ptr;
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::tr1::remove_reference;
|
||||
|
||||
template<typename X> struct default_delete
|
||||
|
@ -75,19 +75,6 @@ Sequence::Sequence(const Sequence &orig, const std::shared_ptr<DirManager> &proj
|
||||
|
||||
Sequence::~Sequence()
|
||||
{
|
||||
DerefAllFiles();
|
||||
}
|
||||
|
||||
void Sequence::DerefAllFiles()
|
||||
{
|
||||
for (size_t i = 0, nn = mBlock.size(); i < nn; i++)
|
||||
{
|
||||
BlockFile *& pOldFile = mBlock[i].f;
|
||||
if (pOldFile) {
|
||||
mDirManager->Deref(pOldFile);
|
||||
pOldFile = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sampleCount Sequence::GetMaxBlockSize() const
|
||||
@ -176,7 +163,7 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged)
|
||||
for (size_t i = 0, nn = mBlock.size(); i < nn && bSuccess; i++)
|
||||
{
|
||||
SeqBlock &oldSeqBlock = mBlock[i];
|
||||
BlockFile* oldBlockFile = oldSeqBlock.f;
|
||||
const auto &oldBlockFile = oldSeqBlock.f;
|
||||
|
||||
sampleCount len = oldBlockFile->GetLength();
|
||||
|
||||
@ -210,8 +197,6 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged)
|
||||
// Invalidate all the old, non-aliased block files.
|
||||
// Aliased files will be converted at save, per comment above.
|
||||
|
||||
DerefAllFiles();
|
||||
|
||||
// Replace with NEW blocks.
|
||||
mBlock.swap(newBlockArray);
|
||||
}
|
||||
@ -277,7 +262,7 @@ bool Sequence::GetMinMax(sampleCount start, sampleCount len,
|
||||
{
|
||||
float block0Min, block0Max, block0RMS;
|
||||
const SeqBlock &theBlock = mBlock[block0];
|
||||
BlockFile *const theFile = theBlock.f;
|
||||
const auto &theFile = theBlock.f;
|
||||
theFile->GetMinMax(&block0Min, &block0Max, &block0RMS);
|
||||
|
||||
if (block0Min < min || block0Max > max) {
|
||||
@ -302,7 +287,7 @@ bool Sequence::GetMinMax(sampleCount start, sampleCount len,
|
||||
{
|
||||
float block1Min, block1Max, block1RMS;
|
||||
const SeqBlock &theBlock = mBlock[block1];
|
||||
BlockFile *const theFile = theBlock.f;
|
||||
const auto &theFile = theBlock.f;
|
||||
theFile->GetMinMax(&block1Min, &block1Max, &block1RMS);
|
||||
|
||||
if (block1Min < min || block1Max > max) {
|
||||
@ -351,7 +336,7 @@ bool Sequence::GetRMS(sampleCount start, sampleCount len,
|
||||
for (unsigned b = block0 + 1; b < block1; b++) {
|
||||
float blockMin, blockMax, blockRMS;
|
||||
const SeqBlock &theBlock = mBlock[b];
|
||||
BlockFile *const theFile = theBlock.f;
|
||||
const auto &theFile = theBlock.f;
|
||||
theFile->GetMinMax(&blockMin, &blockMax, &blockRMS);
|
||||
|
||||
const sampleCount fileLen = theFile->GetLength();
|
||||
@ -364,7 +349,7 @@ bool Sequence::GetRMS(sampleCount start, sampleCount len,
|
||||
// If not, we need read some samples and summaries from disk.
|
||||
{
|
||||
const SeqBlock &theBlock = mBlock[block0];
|
||||
BlockFile *const theFile = theBlock.f;
|
||||
const auto &theFile = theBlock.f;
|
||||
s0 = start - theBlock.start;
|
||||
l0 = len;
|
||||
maxl0 = theBlock.start + theFile->GetLength() - start;
|
||||
@ -381,7 +366,7 @@ bool Sequence::GetRMS(sampleCount start, sampleCount len,
|
||||
|
||||
if (block1 > block0) {
|
||||
const SeqBlock &theBlock = mBlock[block1];
|
||||
BlockFile *const theFile = theBlock.f;
|
||||
const auto &theFile = theBlock.f;
|
||||
|
||||
s0 = 0;
|
||||
l0 = (start + len) - theBlock.start;
|
||||
@ -429,7 +414,7 @@ bool Sequence::Copy(sampleCount s0, sampleCount s1, std::unique_ptr<Sequence> &d
|
||||
|
||||
const SeqBlock &block0 = mBlock[b0];
|
||||
if (s0 != block0.start) {
|
||||
BlockFile *const file = block0.f;
|
||||
const auto &file = block0.f;
|
||||
blocklen = std::min(s1, block0.start + file->GetLength()) - s0;
|
||||
wxASSERT(file->IsAlias() || (blocklen <= mMaxSamples)); // Vaughan, 2012-02-29
|
||||
Get(b0, buffer.ptr(), mSampleFormat, s0, blocklen);
|
||||
@ -446,7 +431,7 @@ bool Sequence::Copy(sampleCount s0, sampleCount s1, std::unique_ptr<Sequence> &d
|
||||
// Do the last block
|
||||
if (b1 > b0) {
|
||||
const SeqBlock &block = mBlock[b1];
|
||||
BlockFile *const file = block.f;
|
||||
const auto &file = block.f;
|
||||
blocklen = (s1 - block.start);
|
||||
wxASSERT(file->IsAlias() || (blocklen <= mMaxSamples)); // Vaughan, 2012-02-29
|
||||
if (blocklen < file->GetLength()) {
|
||||
@ -547,10 +532,9 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
mSampleFormat, block,
|
||||
splitPoint, length - splitPoint);
|
||||
|
||||
BlockFile *const file =
|
||||
auto file =
|
||||
mDirManager->NewSimpleBlockFile(buffer.ptr(), largerBlockLen, mSampleFormat);
|
||||
|
||||
mDirManager->Deref(block.f);
|
||||
block.f = file;
|
||||
|
||||
for (unsigned int i = b + 1; i < numBlocks; i++)
|
||||
@ -617,7 +601,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
|
||||
for (i = 2; i < srcNumBlocks - 2; i++) {
|
||||
const SeqBlock &block = srcBlock[i];
|
||||
BlockFile *const file = mDirManager->CopyBlockFile(block.f);
|
||||
auto file = mDirManager->CopyBlockFile(block.f);
|
||||
if (!file) {
|
||||
wxASSERT(false); // TODO: Handle this better, alert the user of failure.
|
||||
return false;
|
||||
@ -635,8 +619,6 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
Blockify(newBlock, s + lastStart, sampleBuffer.ptr(), rightLen);
|
||||
}
|
||||
|
||||
mDirManager->Deref(splitBlock.f);
|
||||
|
||||
// Copy remaining blocks to NEW block array and
|
||||
// swap the NEW block array in for the old
|
||||
for (i = b + 1; i < numBlocks; i++)
|
||||
@ -676,20 +658,18 @@ bool Sequence::InsertSilence(sampleCount s0, sampleCount len)
|
||||
|
||||
sTrack.mBlock.reserve((len + idealSamples - 1) / idealSamples);
|
||||
|
||||
BlockFile *silentFile = 0;
|
||||
BlockFilePtr silentFile {};
|
||||
if (len >= idealSamples)
|
||||
silentFile = new SilentBlockFile(idealSamples);
|
||||
silentFile = make_blockfile<SilentBlockFile>(idealSamples);
|
||||
while (len >= idealSamples) {
|
||||
sTrack.mBlock.push_back(SeqBlock(silentFile, pos));
|
||||
mDirManager->Ref(silentFile);
|
||||
|
||||
pos += idealSamples;
|
||||
len -= idealSamples;
|
||||
}
|
||||
if (silentFile)
|
||||
mDirManager->Deref(silentFile);
|
||||
if (len) {
|
||||
sTrack.mBlock.push_back(SeqBlock(new SilentBlockFile(len), pos));
|
||||
sTrack.mBlock.push_back(SeqBlock(
|
||||
make_blockfile<SilentBlockFile>(len), pos));
|
||||
pos += len;
|
||||
}
|
||||
|
||||
@ -771,9 +751,9 @@ unsigned int Sequence::GetODFlags()
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
for (unsigned int i = 0; i < mBlock.size(); i++) {
|
||||
BlockFile *const file = mBlock[i].f;
|
||||
const auto &file = mBlock[i].f;
|
||||
if(!file->IsDataAvailable())
|
||||
ret |= (static_cast<ODDecodeBlockFile*>(file))->GetDecodeType();
|
||||
ret |= (static_cast< ODDecodeBlockFile * >( &*file ))->GetDecodeType();
|
||||
else if(!file->IsSummaryAvailable())
|
||||
ret |= ODTask::eODPCMSummary;
|
||||
}
|
||||
@ -971,7 +951,7 @@ void Sequence::HandleXMLEndTag(const wxChar *tag)
|
||||
Internat::ToString(((wxLongLong)mMaxSamples).ToDouble(), 0).c_str());
|
||||
len = mMaxSamples;
|
||||
}
|
||||
block.f = new SilentBlockFile(len);
|
||||
block.f = make_blockfile<SilentBlockFile>(len);
|
||||
wxLogWarning(
|
||||
wxT("Gap detected in project file. Replacing missing block file with silence."));
|
||||
mErrorOpening = true;
|
||||
@ -1114,7 +1094,7 @@ int Sequence::FindBlock(sampleCount pos) const
|
||||
bool Sequence::Read(samplePtr buffer, sampleFormat format,
|
||||
const SeqBlock &b, sampleCount start, sampleCount len) const
|
||||
{
|
||||
BlockFile *f = b.f;
|
||||
const auto &f = b.f;
|
||||
|
||||
wxASSERT(start >= 0);
|
||||
wxASSERT(start + len <= f->GetLength());
|
||||
@ -1150,11 +1130,8 @@ bool Sequence::CopyWrite(SampleBuffer &scratch,
|
||||
Read(scratch.ptr(), mSampleFormat, b, 0, length);
|
||||
memcpy(scratch.ptr() + start*sampleSize, buffer, len*sampleSize);
|
||||
|
||||
BlockFile *const oldBlockFile = b.f;
|
||||
b.f = mDirManager->NewSimpleBlockFile(scratch.ptr(), length, mSampleFormat);
|
||||
|
||||
mDirManager->Deref(oldBlockFile);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1232,8 +1209,7 @@ bool Sequence::Set(samplePtr buffer, sampleFormat format,
|
||||
if (start == block.start &&
|
||||
blen == fileLength) {
|
||||
|
||||
mDirManager->Deref(block.f);
|
||||
block.f = new SilentBlockFile(blen);
|
||||
block.f = make_blockfile<SilentBlockFile>(blen);
|
||||
}
|
||||
else {
|
||||
// Odd partial blocks of silence at start or end.
|
||||
@ -1541,9 +1517,9 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format,
|
||||
);
|
||||
// FIXME: TRAP_ERR This could throw an exception that should(?) be converted to return false.
|
||||
if (blockFileLog)
|
||||
static_cast<SimpleBlockFile*>(newLastBlock.f)->SaveXML(*blockFileLog);
|
||||
static_cast< SimpleBlockFile * >( &*newLastBlock.f )
|
||||
->SaveXML( *blockFileLog );
|
||||
|
||||
mDirManager->Deref(lastBlock.f);
|
||||
lastBlock = newLastBlock;
|
||||
|
||||
len -= addLen;
|
||||
@ -1554,7 +1530,7 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format,
|
||||
while (len) {
|
||||
const sampleCount idealSamples = GetIdealBlockSize();
|
||||
const sampleCount l = std::min(idealSamples, len);
|
||||
BlockFile *pFile;
|
||||
BlockFilePtr pFile;
|
||||
if (format == mSampleFormat) {
|
||||
pFile = mDirManager->NewSimpleBlockFile(buffer, l, mSampleFormat,
|
||||
blockFileLog != NULL);
|
||||
@ -1567,7 +1543,7 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format,
|
||||
|
||||
// FIXME: TRAP_ERR This could throw an exception that should(?) be converted to return false.
|
||||
if (blockFileLog)
|
||||
static_cast<SimpleBlockFile*>(pFile)->SaveXML(*blockFileLog);
|
||||
static_cast< SimpleBlockFile * >( &*pFile )->SaveXML( *blockFileLog );
|
||||
|
||||
mBlock.push_back(SeqBlock(pFile, mNumSamples));
|
||||
|
||||
@ -1649,12 +1625,10 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
|
||||
Read(scratch.ptr() + (pos * sampleSize), mSampleFormat,
|
||||
b, pos + len, newLen - pos);
|
||||
|
||||
BlockFile *const oldFile = b.f;
|
||||
b = SeqBlock(
|
||||
mDirManager->NewSimpleBlockFile(scratch.ptr(), newLen, mSampleFormat),
|
||||
b.start
|
||||
);
|
||||
mDirManager->Deref(oldFile);
|
||||
|
||||
for (unsigned int j = b0 + 1; j < numBlocks; j++)
|
||||
mBlock[j].start -= len;
|
||||
@ -1685,7 +1659,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
|
||||
if (!scratch.ptr())
|
||||
scratch.Allocate(scratchSize, mSampleFormat);
|
||||
Read(scratch.ptr(), mSampleFormat, preBlock, 0, preBufferLen);
|
||||
BlockFile *const pFile =
|
||||
auto pFile =
|
||||
mDirManager->NewSimpleBlockFile(scratch.ptr(), preBufferLen, mSampleFormat);
|
||||
|
||||
newBlock.push_back(SeqBlock(pFile, preBlock.start));
|
||||
@ -1703,8 +1677,6 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
|
||||
|
||||
newBlock.erase(newBlock.end() - 1);
|
||||
Blockify(newBlock, prepreBlock.start, scratch.ptr(), sum);
|
||||
|
||||
mDirManager->Deref(prepreBlock.f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -1712,15 +1684,6 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
|
||||
// right on the beginning of a block.
|
||||
}
|
||||
|
||||
if (b0 != b1) {
|
||||
mDirManager->Deref(preBlock.f);
|
||||
}
|
||||
|
||||
// Next, DELETE blocks strictly between b0 and b1
|
||||
for (i = b0 + 1; i < b1; i++) {
|
||||
mDirManager->Deref(mBlock[i].f);
|
||||
}
|
||||
|
||||
// Now, symmetrically, grab the samples in block b1 after the
|
||||
// deletion point into postBuffer. If this is enough samples
|
||||
// for its own block, or if this would be the last block in
|
||||
@ -1736,7 +1699,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
|
||||
scratch.Allocate(postBufferLen, mSampleFormat);
|
||||
sampleCount pos = (start + len) - postBlock.start;
|
||||
Read(scratch.ptr(), mSampleFormat, postBlock, pos, postBufferLen);
|
||||
BlockFile *const file =
|
||||
auto file =
|
||||
mDirManager->NewSimpleBlockFile(scratch.ptr(), postBufferLen, mSampleFormat);
|
||||
|
||||
newBlock.push_back(SeqBlock(file, start));
|
||||
@ -1755,15 +1718,12 @@ bool Sequence::Delete(sampleCount start, sampleCount len)
|
||||
|
||||
Blockify(newBlock, start, scratch.ptr(), sum);
|
||||
b1++;
|
||||
|
||||
mDirManager->Deref(postpostBlock.f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The sample where we begin deletion happens to fall
|
||||
// right on the end of a block.
|
||||
}
|
||||
mDirManager->Deref(postBlock.f);
|
||||
|
||||
// Copy the remaining blocks over from the old array
|
||||
for (i = b1 + 1; i < numBlocks; i++)
|
||||
@ -1820,11 +1780,11 @@ void Sequence::DebugPrintf(wxString *dest) const
|
||||
for (i = 0; i < mBlock.size(); i++) {
|
||||
const SeqBlock &seqBlock = mBlock[i];
|
||||
*dest += wxString::Format
|
||||
(wxT(" Block %3u: start %8lld, len %8lld, refs %d, "),
|
||||
(wxT(" Block %3u: start %8lld, len %8lld, refs %ld, "),
|
||||
i,
|
||||
(long long) seqBlock.start,
|
||||
seqBlock.f ? (long long) seqBlock.f->GetLength() : 0,
|
||||
seqBlock.f ? mDirManager->GetRefCount(seqBlock.f) : 0);
|
||||
seqBlock.f ? seqBlock.f.use_count() : 0);
|
||||
|
||||
if (seqBlock.f)
|
||||
*dest += seqBlock.f->GetFileName().name.GetFullName();
|
||||
@ -1855,7 +1815,7 @@ int Sequence::GetMaxDiskBlockSize()
|
||||
return sMaxDiskBlockSize;
|
||||
}
|
||||
|
||||
void Sequence::AppendBlockFile(BlockFile* blockFile)
|
||||
void Sequence::AppendBlockFile(const BlockFilePtr &blockFile)
|
||||
{
|
||||
// We assume blockFile has the correct ref count already
|
||||
|
||||
|
@ -30,20 +30,22 @@ typedef wxLongLong_t sampleCount; /** < A native 64-bit integer type, because
|
||||
#endif
|
||||
|
||||
class BlockFile;
|
||||
using BlockFilePtr = std::shared_ptr<BlockFile>;
|
||||
|
||||
class DirManager;
|
||||
|
||||
// This is an internal data structure! For advanced use only.
|
||||
class SeqBlock {
|
||||
public:
|
||||
BlockFile * f;
|
||||
BlockFilePtr f;
|
||||
///the sample in the global wavetrack that this block starts at.
|
||||
sampleCount start;
|
||||
|
||||
SeqBlock()
|
||||
: f(NULL), start(0)
|
||||
: f{}, start(0)
|
||||
{}
|
||||
|
||||
SeqBlock(BlockFile *f_, sampleCount start_)
|
||||
SeqBlock(const BlockFilePtr &f_, sampleCount start_)
|
||||
: f(f_), start(start_)
|
||||
{}
|
||||
|
||||
@ -123,7 +125,7 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
|
||||
// be registered within the dir manager hash. This is the case
|
||||
// when the blockfile is created using DirManager::NewSimpleBlockFile or
|
||||
// loaded from an XML file via DirManager::HandleXMLTag
|
||||
void AppendBlockFile(BlockFile* blockFile);
|
||||
void AppendBlockFile(const BlockFilePtr &blockFile);
|
||||
|
||||
bool SetSilence(sampleCount s0, sampleCount len);
|
||||
bool InsertSilence(sampleCount s0, sampleCount len);
|
||||
@ -236,8 +238,6 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
|
||||
// Private methods
|
||||
//
|
||||
|
||||
void DerefAllFiles();
|
||||
|
||||
int FindBlock(sampleCount pos) const;
|
||||
|
||||
bool AppendBlock(const SeqBlock &b);
|
||||
|
@ -100,17 +100,17 @@ void UndoManager::CalculateSpaceUsage()
|
||||
BlockArray *blocks = clip->GetSequenceBlockArray();
|
||||
for (const auto &block : *blocks)
|
||||
{
|
||||
BlockFile *file = block.f;
|
||||
const auto &file = block.f;
|
||||
|
||||
// Accumulate space used by the file if the file didn't exist
|
||||
// in the previous level
|
||||
if (prev->count(file) == 0 && cur->count(file) == 0)
|
||||
if (prev->count( &*file ) == 0 && cur->count( &*file ) == 0)
|
||||
{
|
||||
space[i] += file->GetSpaceUsage().GetValue();
|
||||
}
|
||||
|
||||
// Add file to current set
|
||||
cur->insert(file);
|
||||
cur->insert( &*file );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,14 +51,12 @@ LegacyAliasBlockFile::~LegacyAliasBlockFile()
|
||||
/// the summary data to a NEW file.
|
||||
///
|
||||
/// @param newFileName The filename to copy the summary data to.
|
||||
BlockFile *LegacyAliasBlockFile::Copy(wxFileNameWrapper &&newFileName)
|
||||
BlockFilePtr LegacyAliasBlockFile::Copy(wxFileNameWrapper &&newFileName)
|
||||
{
|
||||
BlockFile *newBlockFile =
|
||||
new LegacyAliasBlockFile(std::move(newFileName),
|
||||
wxFileNameWrapper{mAliasedFileName}, mAliasStart,
|
||||
mLen, mAliasChannel,
|
||||
mSummaryInfo.totalSummaryBytes,
|
||||
mSummaryInfo.fields < 3);
|
||||
auto newBlockFile = make_blockfile<LegacyAliasBlockFile>
|
||||
(std::move(newFileName), wxFileNameWrapper{ mAliasedFileName },
|
||||
mAliasStart, mLen, mAliasChannel,
|
||||
mSummaryInfo.totalSummaryBytes, mSummaryInfo.fields < 3);
|
||||
|
||||
return newBlockFile;
|
||||
}
|
||||
@ -83,7 +81,7 @@ void LegacyAliasBlockFile::SaveXML(XMLWriter &xmlFile)
|
||||
// BuildFromXML methods should always return a BlockFile, not NULL,
|
||||
// even if the result is flawed (e.g., refers to nonexistent file),
|
||||
// as testing will be done in DirManager::ProjectFSCK().
|
||||
BlockFile *LegacyAliasBlockFile::BuildFromXML(const wxString &projDir, const wxChar **attrs)
|
||||
BlockFilePtr LegacyAliasBlockFile::BuildFromXML(const wxString &projDir, const wxChar **attrs)
|
||||
{
|
||||
wxFileNameWrapper summaryFileName;
|
||||
wxFileNameWrapper aliasFileName;
|
||||
@ -133,9 +131,9 @@ BlockFile *LegacyAliasBlockFile::BuildFromXML(const wxString &projDir, const wxC
|
||||
}
|
||||
}
|
||||
|
||||
return new LegacyAliasBlockFile(std::move(summaryFileName), std::move(aliasFileName),
|
||||
aliasStart, aliasLen, aliasChannel,
|
||||
summaryLen, noRMS);
|
||||
return make_blockfile<LegacyAliasBlockFile>
|
||||
(std::move(summaryFileName), std::move(aliasFileName),
|
||||
aliasStart, aliasLen, aliasChannel, summaryLen, noRMS);
|
||||
}
|
||||
|
||||
// regenerates the summary info, doesn't deal with missing alias files
|
||||
|
@ -32,10 +32,10 @@ class LegacyAliasBlockFile final : public PCMAliasBlockFile
|
||||
virtual ~LegacyAliasBlockFile();
|
||||
|
||||
void SaveXML(XMLWriter &xmlFile) override;
|
||||
BlockFile *Copy(wxFileNameWrapper &&fileName) override;
|
||||
BlockFilePtr Copy(wxFileNameWrapper &&fileName) override;
|
||||
void Recover() override;
|
||||
|
||||
static BlockFile *BuildFromXML(const wxString &projDir, const wxChar **attrs);
|
||||
static BlockFilePtr BuildFromXML(const wxString &projDir, const wxChar **attrs);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -294,7 +294,7 @@ void LegacyBlockFile::SaveXML(XMLWriter &xmlFile)
|
||||
// even if the result is flawed (e.g., refers to nonexistent file),
|
||||
// as testing will be done in DirManager::ProjectFSCK().
|
||||
/// static
|
||||
BlockFile *LegacyBlockFile::BuildFromXML(const wxString &projDir, const wxChar **attrs,
|
||||
BlockFilePtr LegacyBlockFile::BuildFromXML(const wxString &projDir, const wxChar **attrs,
|
||||
sampleCount len, sampleFormat format)
|
||||
{
|
||||
wxFileNameWrapper fileName;
|
||||
@ -328,19 +328,19 @@ BlockFile *LegacyBlockFile::BuildFromXML(const wxString &projDir, const wxChar *
|
||||
}
|
||||
}
|
||||
|
||||
return new LegacyBlockFile(std::move(fileName), format, summaryLen, len, noRMS);
|
||||
return make_blockfile<LegacyBlockFile>
|
||||
(std::move(fileName), format, summaryLen, len, noRMS);
|
||||
}
|
||||
|
||||
/// Create a copy of this BlockFile, but using a different disk file.
|
||||
///
|
||||
/// @param newFileName The name of the NEW file to use.
|
||||
BlockFile *LegacyBlockFile::Copy(wxFileNameWrapper &&newFileName)
|
||||
BlockFilePtr LegacyBlockFile::Copy(wxFileNameWrapper &&newFileName)
|
||||
{
|
||||
return new LegacyBlockFile(std::move(newFileName),
|
||||
mFormat,
|
||||
mSummaryInfo.totalSummaryBytes,
|
||||
mLen,
|
||||
mSummaryInfo.fields < 3);
|
||||
return make_blockfile<LegacyBlockFile>
|
||||
(std::move(newFileName),
|
||||
mFormat, mSummaryInfo.totalSummaryBytes,
|
||||
mLen, mSummaryInfo.fields < 3);
|
||||
}
|
||||
|
||||
wxLongLong LegacyBlockFile::GetSpaceUsage() const
|
||||
|
@ -54,13 +54,13 @@ class LegacyBlockFile final : public BlockFile {
|
||||
sampleCount start, sampleCount len) const override;
|
||||
|
||||
/// Create a NEW block file identical to this one
|
||||
BlockFile *Copy(wxFileNameWrapper &&newFileName) override;
|
||||
BlockFilePtr Copy(wxFileNameWrapper &&newFileName) override;
|
||||
/// Write an XML representation of this file
|
||||
void SaveXML(XMLWriter &xmlFile) override;
|
||||
wxLongLong GetSpaceUsage() const override;
|
||||
void Recover() override;
|
||||
|
||||
static BlockFile *BuildFromXML(const wxString &dir, const wxChar **attrs,
|
||||
static BlockFilePtr BuildFromXML(const wxString &dir, const wxChar **attrs,
|
||||
sampleCount len,
|
||||
sampleFormat format);
|
||||
|
||||
|
@ -158,9 +158,9 @@ bool ODDecodeBlockFile::Read64K(float *buffer, sampleCount start, sampleCount le
|
||||
/// Construct a NEW PCMAliasBlockFile based on this one.
|
||||
/// otherwise construct an ODPCMAliasBlockFile that still needs to be computed.
|
||||
/// @param newFileName The filename to copy the summary data to.
|
||||
BlockFile *ODDecodeBlockFile::Copy(wxFileNameWrapper &&newFileName)
|
||||
BlockFilePtr ODDecodeBlockFile::Copy(wxFileNameWrapper &&newFileName)
|
||||
{
|
||||
BlockFile *newBlockFile;
|
||||
BlockFilePtr newBlockFile;
|
||||
|
||||
//mAliasedFile can change so we lock readdatamutex, which is responsible for it.
|
||||
LockRead();
|
||||
@ -172,10 +172,10 @@ BlockFile *ODDecodeBlockFile::Copy(wxFileNameWrapper &&newFileName)
|
||||
else
|
||||
{
|
||||
//Summary File might exist in this case, but it probably (99.999% of the time) won't.
|
||||
newBlockFile = new ODDecodeBlockFile(std::move(newFileName),
|
||||
wxFileNameWrapper{mAudioFileName}, mAliasStart,
|
||||
mLen, mAliasChannel, mType,
|
||||
mMin, mMax, mRMS,IsSummaryAvailable());
|
||||
newBlockFile = make_blockfile<ODDecodeBlockFile>
|
||||
(std::move(newFileName), wxFileNameWrapper{mAudioFileName},
|
||||
mAliasStart, mLen, mAliasChannel, mType,
|
||||
mMin, mMax, mRMS, IsSummaryAvailable());
|
||||
//The client code will need to schedule this blockfile for OD decoding if it is going to a NEW track.
|
||||
//It can do this by checking for IsDataAvailable()==false.
|
||||
}
|
||||
@ -222,7 +222,7 @@ void ODDecodeBlockFile::SaveXML(XMLWriter &xmlFile)
|
||||
// BuildFromXML methods should always return a BlockFile, not NULL,
|
||||
// even if the result is flawed (e.g., refers to nonexistent file),
|
||||
// as testing will be done in DirManager::ProjectFSCK().
|
||||
BlockFile *ODDecodeBlockFile::BuildFromXML(DirManager &dm, const wxChar **attrs)
|
||||
BlockFilePtr ODDecodeBlockFile::BuildFromXML(DirManager &dm, const wxChar **attrs)
|
||||
{
|
||||
wxFileNameWrapper summaryFileName;
|
||||
wxFileNameWrapper audioFileName;
|
||||
@ -274,10 +274,9 @@ BlockFile *ODDecodeBlockFile::BuildFromXML(DirManager &dm, const wxChar **attrs)
|
||||
}
|
||||
}
|
||||
|
||||
return new ODDecodeBlockFile(std::move(summaryFileName), std::move(audioFileName),
|
||||
aliasStart, aliasLen, aliasChannel,decodeType,
|
||||
0,0,0, false);
|
||||
|
||||
return make_blockfile<ODDecodeBlockFile>
|
||||
(std::move(summaryFileName), std::move(audioFileName),
|
||||
aliasStart, aliasLen, aliasChannel, decodeType, 0, 0, 0, false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -77,13 +77,13 @@ class ODDecodeBlockFile final : public SimpleBlockFile
|
||||
|
||||
|
||||
///Makes NEW ODPCMAliasBlockFile or PCMAliasBlockFile depending on summary availability
|
||||
BlockFile *Copy(wxFileNameWrapper &&fileName) override;
|
||||
BlockFilePtr Copy(wxFileNameWrapper &&fileName) override;
|
||||
|
||||
///Saves as xml ODPCMAliasBlockFile or PCMAliasBlockFile depending on summary availability
|
||||
void SaveXML(XMLWriter &xmlFile) override;
|
||||
|
||||
///Reconstructs from XML a ODPCMAliasBlockFile and reschedules it for OD loading
|
||||
static BlockFile *BuildFromXML(DirManager &dm, const wxChar **attrs);
|
||||
static BlockFilePtr BuildFromXML(DirManager &dm, const wxChar **attrs);
|
||||
|
||||
///Writes the summary file if summary data is available
|
||||
void Recover(void) override;
|
||||
|
@ -74,33 +74,6 @@ ODPCMAliasBlockFile::~ODPCMAliasBlockFile()
|
||||
{
|
||||
}
|
||||
|
||||
/// Increases the reference count of this block by one. Only
|
||||
/// DirManager should call this method.
|
||||
/// This method has been overidden to be threadsafe. It is important especially
|
||||
/// if two blockfiles deref at the same time resulting in a double deletion of the file
|
||||
void ODPCMAliasBlockFile::Ref() const
|
||||
{
|
||||
mRefMutex.Lock();
|
||||
BlockFile::Ref();
|
||||
mRefMutex.Unlock();
|
||||
}
|
||||
|
||||
/// Decreases the reference count of this block by one. If this
|
||||
/// causes the count to become zero, deletes the associated disk
|
||||
/// file and deletes this object
|
||||
bool ODPCMAliasBlockFile::Deref() const
|
||||
{
|
||||
bool ret;
|
||||
mDerefMutex.Lock();
|
||||
ret = BlockFile::Deref();
|
||||
if(!ret)
|
||||
{
|
||||
//Deref returns true when deleted, in which case we should not be touching instance variables, or ever calling this function again.
|
||||
mDerefMutex.Unlock();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Check to see if we have the file for these calls.
|
||||
@ -216,9 +189,9 @@ bool ODPCMAliasBlockFile::Read64K(float *buffer, sampleCount start, sampleCount
|
||||
/// Construct a NEW PCMAliasBlockFile based on this one.
|
||||
/// otherwise construct an ODPCMAliasBlockFile that still needs to be computed.
|
||||
/// @param newFileName The filename to copy the summary data to.
|
||||
BlockFile *ODPCMAliasBlockFile::Copy(wxFileNameWrapper &&newFileName)
|
||||
BlockFilePtr ODPCMAliasBlockFile::Copy(wxFileNameWrapper &&newFileName)
|
||||
{
|
||||
BlockFile *newBlockFile;
|
||||
BlockFilePtr newBlockFile;
|
||||
|
||||
//mAliasedFile can change so we lock readdatamutex, which is responsible for it.
|
||||
LockRead();
|
||||
@ -228,19 +201,18 @@ BlockFile *ODPCMAliasBlockFile::Copy(wxFileNameWrapper &&newFileName)
|
||||
//PCMAliasBlockFile is to lock on exit, and this will cause orphaned blockfiles..
|
||||
if(IsSummaryAvailable() && mHasBeenSaved)
|
||||
{
|
||||
newBlockFile = new PCMAliasBlockFile(std::move(newFileName),
|
||||
wxFileNameWrapper{mAliasedFileName}, mAliasStart,
|
||||
mLen, mAliasChannel,
|
||||
mMin, mMax, mRMS);
|
||||
newBlockFile = make_blockfile<PCMAliasBlockFile>
|
||||
(std::move(newFileName), wxFileNameWrapper{mAliasedFileName},
|
||||
mAliasStart, mLen, mAliasChannel, mMin, mMax, mRMS);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//Summary File might exist in this case, but it might not.
|
||||
newBlockFile = new ODPCMAliasBlockFile(std::move(newFileName),
|
||||
wxFileNameWrapper{mAliasedFileName}, mAliasStart,
|
||||
mLen, mAliasChannel,
|
||||
mMin, mMax, mRMS,IsSummaryAvailable());
|
||||
newBlockFile = make_blockfile<ODPCMAliasBlockFile>
|
||||
(std::move(newFileName), wxFileNameWrapper{mAliasedFileName},
|
||||
mAliasStart, mLen, mAliasChannel, mMin, mMax, mRMS,
|
||||
IsSummaryAvailable());
|
||||
//The client code will need to schedule this blockfile for OD summarizing if it is going to a NEW track.
|
||||
}
|
||||
|
||||
@ -290,7 +262,7 @@ void ODPCMAliasBlockFile::SaveXML(XMLWriter &xmlFile)
|
||||
// BuildFromXML methods should always return a BlockFile, not NULL,
|
||||
// even if the result is flawed (e.g., refers to nonexistent file),
|
||||
// as testing will be done in DirManager::ProjectFSCK().
|
||||
BlockFile *ODPCMAliasBlockFile::BuildFromXML(DirManager &dm, const wxChar **attrs)
|
||||
BlockFilePtr ODPCMAliasBlockFile::BuildFromXML(DirManager &dm, const wxChar **attrs)
|
||||
{
|
||||
wxFileNameWrapper summaryFileName;
|
||||
wxFileNameWrapper aliasFileName;
|
||||
@ -339,9 +311,9 @@ BlockFile *ODPCMAliasBlockFile::BuildFromXML(DirManager &dm, const wxChar **attr
|
||||
}
|
||||
}
|
||||
|
||||
return new ODPCMAliasBlockFile(std::move(summaryFileName), std::move(aliasFileName),
|
||||
aliasStart, aliasLen, aliasChannel,
|
||||
0,0,0, false);
|
||||
return make_blockfile<ODPCMAliasBlockFile>
|
||||
(std::move(summaryFileName), std::move(aliasFileName),
|
||||
aliasStart, aliasLen, aliasChannel, 0, 0, 0, false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -75,13 +75,13 @@ class ODPCMAliasBlockFile final : public PCMAliasBlockFile
|
||||
bool Read64K(float *buffer, sampleCount start, sampleCount len) override;
|
||||
|
||||
///Makes NEW ODPCMAliasBlockFile or PCMAliasBlockFile depending on summary availability
|
||||
BlockFile *Copy(wxFileNameWrapper &&fileName) override;
|
||||
BlockFilePtr Copy(wxFileNameWrapper &&fileName) override;
|
||||
|
||||
///Saves as xml ODPCMAliasBlockFile or PCMAliasBlockFile depending on summary availability
|
||||
void SaveXML(XMLWriter &xmlFile) override;
|
||||
|
||||
///Reconstructs from XML a ODPCMAliasBlockFile and reschedules it for OD loading
|
||||
static BlockFile *BuildFromXML(DirManager &dm, const wxChar **attrs);
|
||||
static BlockFilePtr BuildFromXML(DirManager &dm, const wxChar **attrs);
|
||||
|
||||
///Writes the summary file if summary data is available
|
||||
void Recover(void) override;
|
||||
@ -143,13 +143,6 @@ protected:
|
||||
sampleFormat format, ArrayOf<char> &cleanup) override;
|
||||
|
||||
private:
|
||||
//Thread-safe versions
|
||||
void Ref() const override;
|
||||
bool Deref() const override;
|
||||
//needed for Ref/Deref access.
|
||||
friend class DirManager;
|
||||
friend class ODComputeSummaryTask;
|
||||
friend class ODDecodeTask;
|
||||
|
||||
ODLock mWriteSummaryMutex;
|
||||
|
||||
@ -162,11 +155,6 @@ protected:
|
||||
//lock the read data - libsndfile can't handle two reads at once?
|
||||
mutable ODLock mReadDataMutex;
|
||||
|
||||
|
||||
//lock the Ref counting
|
||||
mutable ODLock mDerefMutex;
|
||||
mutable ODLock mRefMutex;
|
||||
|
||||
mutable ODLock mSummaryAvailableMutex;
|
||||
bool mSummaryAvailable;
|
||||
bool mSummaryBeingComputed;
|
||||
|
@ -150,12 +150,11 @@ int PCMAliasBlockFile::ReadData(samplePtr data, sampleFormat format,
|
||||
/// the summary data to a NEW file.
|
||||
///
|
||||
/// @param newFileName The filename to copy the summary data to.
|
||||
BlockFile *PCMAliasBlockFile::Copy(wxFileNameWrapper &&newFileName)
|
||||
BlockFilePtr PCMAliasBlockFile::Copy(wxFileNameWrapper &&newFileName)
|
||||
{
|
||||
BlockFile *newBlockFile = new PCMAliasBlockFile(std::move(newFileName),
|
||||
wxFileNameWrapper{mAliasedFileName}, mAliasStart,
|
||||
mLen, mAliasChannel,
|
||||
mMin, mMax, mRMS);
|
||||
auto newBlockFile = make_blockfile<PCMAliasBlockFile>
|
||||
(std::move(newFileName), wxFileNameWrapper{mAliasedFileName},
|
||||
mAliasStart, mLen, mAliasChannel, mMin, mMax, mRMS);
|
||||
|
||||
return newBlockFile;
|
||||
}
|
||||
@ -179,7 +178,7 @@ void PCMAliasBlockFile::SaveXML(XMLWriter &xmlFile)
|
||||
// BuildFromXML methods should always return a BlockFile, not NULL,
|
||||
// even if the result is flawed (e.g., refers to nonexistent file),
|
||||
// as testing will be done in DirManager::ProjectFSCK().
|
||||
BlockFile *PCMAliasBlockFile::BuildFromXML(DirManager &dm, const wxChar **attrs)
|
||||
BlockFilePtr PCMAliasBlockFile::BuildFromXML(DirManager &dm, const wxChar **attrs)
|
||||
{
|
||||
wxFileNameWrapper summaryFileName;
|
||||
wxFileNameWrapper aliasFileName;
|
||||
@ -249,9 +248,9 @@ BlockFile *PCMAliasBlockFile::BuildFromXML(DirManager &dm, const wxChar **attrs)
|
||||
}
|
||||
}
|
||||
|
||||
return new PCMAliasBlockFile(std::move(summaryFileName), std::move(aliasFileName),
|
||||
aliasStart, aliasLen, aliasChannel,
|
||||
min, max, rms);
|
||||
return make_blockfile<PCMAliasBlockFile>
|
||||
(std::move(summaryFileName), std::move(aliasFileName),
|
||||
aliasStart, aliasLen, aliasChannel, min, max, rms);
|
||||
}
|
||||
|
||||
void PCMAliasBlockFile::Recover(void)
|
||||
|
@ -41,10 +41,10 @@ class PCMAliasBlockFile /* not final */ : public AliasBlockFile
|
||||
sampleCount start, sampleCount len) const override;
|
||||
|
||||
void SaveXML(XMLWriter &xmlFile) override;
|
||||
BlockFile *Copy(wxFileNameWrapper &&fileName) override;
|
||||
BlockFilePtr Copy(wxFileNameWrapper &&fileName) override;
|
||||
void Recover() override;
|
||||
|
||||
static BlockFile *BuildFromXML(DirManager &dm, const wxChar **attrs);
|
||||
static BlockFilePtr BuildFromXML(DirManager &dm, const wxChar **attrs);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -51,7 +51,7 @@ void SilentBlockFile::SaveXML(XMLWriter &xmlFile)
|
||||
// even if the result is flawed (e.g., refers to nonexistent file),
|
||||
// as testing will be done in DirManager::ProjectFSCK().
|
||||
/// static
|
||||
BlockFile *SilentBlockFile::BuildFromXML(DirManager & WXUNUSED(dm), const wxChar **attrs)
|
||||
BlockFilePtr SilentBlockFile::BuildFromXML(DirManager & WXUNUSED(dm), const wxChar **attrs)
|
||||
{
|
||||
long nValue;
|
||||
sampleCount len = 0;
|
||||
@ -71,13 +71,13 @@ BlockFile *SilentBlockFile::BuildFromXML(DirManager & WXUNUSED(dm), const wxChar
|
||||
len = nValue;
|
||||
}
|
||||
|
||||
return new SilentBlockFile(len);
|
||||
return make_blockfile<SilentBlockFile>(len);
|
||||
}
|
||||
|
||||
/// Create a copy of this BlockFile
|
||||
BlockFile *SilentBlockFile::Copy(wxFileNameWrapper &&)
|
||||
BlockFilePtr SilentBlockFile::Copy(wxFileNameWrapper &&)
|
||||
{
|
||||
BlockFile *newBlockFile = new SilentBlockFile(mLen);
|
||||
auto newBlockFile = make_blockfile<SilentBlockFile>(mLen);
|
||||
|
||||
return newBlockFile;
|
||||
}
|
||||
|
@ -39,13 +39,13 @@ class SilentBlockFile final : public BlockFile {
|
||||
sampleCount start, sampleCount len) const override;
|
||||
|
||||
/// Create a NEW block file identical to this one
|
||||
BlockFile *Copy(wxFileNameWrapper &&newFileName) override;
|
||||
BlockFilePtr Copy(wxFileNameWrapper &&newFileName) override;
|
||||
/// Write an XML representation of this file
|
||||
void SaveXML(XMLWriter &xmlFile) override;
|
||||
wxLongLong GetSpaceUsage() const override;
|
||||
void Recover() override { };
|
||||
|
||||
static BlockFile *BuildFromXML(DirManager &dm, const wxChar **attrs);
|
||||
static BlockFilePtr BuildFromXML(DirManager &dm, const wxChar **attrs);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -492,7 +492,7 @@ void SimpleBlockFile::SaveXML(XMLWriter &xmlFile)
|
||||
// even if the result is flawed (e.g., refers to nonexistent file),
|
||||
// as testing will be done in DirManager::ProjectFSCK().
|
||||
/// static
|
||||
BlockFile *SimpleBlockFile::BuildFromXML(DirManager &dm, const wxChar **attrs)
|
||||
BlockFilePtr SimpleBlockFile::BuildFromXML(DirManager &dm, const wxChar **attrs)
|
||||
{
|
||||
wxFileNameWrapper fileName;
|
||||
float min = 0.0f, max = 0.0f, rms = 0.0f;
|
||||
@ -532,16 +532,17 @@ BlockFile *SimpleBlockFile::BuildFromXML(DirManager &dm, const wxChar **attrs)
|
||||
}
|
||||
}
|
||||
|
||||
return new SimpleBlockFile(std::move(fileName), len, min, max, rms);
|
||||
return make_blockfile<SimpleBlockFile>
|
||||
(std::move(fileName), len, min, max, rms);
|
||||
}
|
||||
|
||||
/// Create a copy of this BlockFile, but using a different disk file.
|
||||
///
|
||||
/// @param newFileName The name of the NEW file to use.
|
||||
BlockFile *SimpleBlockFile::Copy(wxFileNameWrapper &&newFileName)
|
||||
BlockFilePtr SimpleBlockFile::Copy(wxFileNameWrapper &&newFileName)
|
||||
{
|
||||
BlockFile *newBlockFile = new SimpleBlockFile(std::move(newFileName), mLen,
|
||||
mMin, mMax, mRMS);
|
||||
auto newBlockFile = make_blockfile<SimpleBlockFile>
|
||||
(std::move(newFileName), mLen, mMin, mMax, mRMS);
|
||||
|
||||
return newBlockFile;
|
||||
}
|
||||
|
@ -68,14 +68,14 @@ class PROFILE_DLL_API SimpleBlockFile /* not final */ : public BlockFile {
|
||||
sampleCount start, sampleCount len) const override;
|
||||
|
||||
/// Create a NEW block file identical to this one
|
||||
BlockFile *Copy(wxFileNameWrapper &&newFileName) override;
|
||||
BlockFilePtr Copy(wxFileNameWrapper &&newFileName) override;
|
||||
/// Write an XML representation of this file
|
||||
void SaveXML(XMLWriter &xmlFile) override;
|
||||
|
||||
wxLongLong GetSpaceUsage() const override;
|
||||
void Recover() override;
|
||||
|
||||
static BlockFile *BuildFromXML(DirManager &dm, const wxChar **attrs);
|
||||
static BlockFilePtr BuildFromXML(DirManager &dm, const wxChar **attrs);
|
||||
|
||||
bool GetNeedWriteCacheToDisk() override;
|
||||
void WriteCacheToDisk() override;
|
||||
|
@ -49,8 +49,6 @@ void ODComputeSummaryTask::Terminate()
|
||||
//The terminate block won't allow DoSomeInternal and this method to be run async, so this is thread-safe.
|
||||
//Deref the block files since they are ref'ed when put into the array.
|
||||
mBlockFilesMutex.Lock();
|
||||
for(unsigned int i=0;i<mBlockFiles.size();i++)
|
||||
mBlockFiles[i]->Deref();
|
||||
mBlockFiles.clear();
|
||||
mBlockFilesMutex.Unlock();
|
||||
}
|
||||
@ -66,7 +64,6 @@ void ODComputeSummaryTask::DoSomeInternal()
|
||||
return;
|
||||
}
|
||||
|
||||
ODPCMAliasBlockFile* bf;
|
||||
sampleCount blockStartSample = 0;
|
||||
sampleCount blockEndSample = 0;
|
||||
bool success =false;
|
||||
@ -74,12 +71,12 @@ void ODComputeSummaryTask::DoSomeInternal()
|
||||
mBlockFilesMutex.Lock();
|
||||
for(size_t i=0; i < mWaveTracks.size() && mBlockFiles.size();i++)
|
||||
{
|
||||
bf = mBlockFiles[0];
|
||||
const auto &bf = mBlockFiles[0];
|
||||
|
||||
//first check to see if the ref count is at least 2. It should have one
|
||||
//from when we added it to this instance's mBlockFiles array, and one from
|
||||
//the Wavetrack/sequence. If it doesn't it has been deleted and we should forget it.
|
||||
if(bf->RefCount()>=2)
|
||||
if(bf.use_count() >= 2)
|
||||
{
|
||||
bf->DoWriteSummary();
|
||||
success = true;
|
||||
@ -94,8 +91,6 @@ void ODComputeSummaryTask::DoSomeInternal()
|
||||
mMaxBlockFiles--;
|
||||
}
|
||||
|
||||
//Release the refcount we placed on it.
|
||||
bf->Deref();
|
||||
//take it out of the array - we are done with it.
|
||||
mBlockFiles.erase(mBlockFiles.begin());
|
||||
|
||||
@ -170,7 +165,7 @@ void ODComputeSummaryTask::CalculatePercentComplete()
|
||||
///by default left to right, or frome the point the user has clicked.
|
||||
void ODComputeSummaryTask::Update()
|
||||
{
|
||||
std::vector<ODPCMAliasBlockFile*> tempBlocks;
|
||||
std::vector< std::shared_ptr< ODPCMAliasBlockFile > > tempBlocks;
|
||||
|
||||
mWaveTrackMutex.Lock();
|
||||
|
||||
@ -202,11 +197,11 @@ void ODComputeSummaryTask::Update()
|
||||
{
|
||||
//if there is data but no summary, this blockfile needs summarizing.
|
||||
SeqBlock &block = (*blocks)[i];
|
||||
BlockFile *const file = block.f;
|
||||
const auto &file = block.f;
|
||||
if(file->IsDataAvailable() && !file->IsSummaryAvailable())
|
||||
{
|
||||
file->Ref();
|
||||
ODPCMAliasBlockFile *const odpcmaFile = static_cast<ODPCMAliasBlockFile*>(file);
|
||||
const auto odpcmaFile =
|
||||
std::static_pointer_cast<ODPCMAliasBlockFile>(file);
|
||||
odpcmaFile->SetStart(block.start);
|
||||
odpcmaFile->SetClipOffset((sampleCount)(clip->GetStartTime()*clip->GetRate()));
|
||||
|
||||
@ -235,11 +230,9 @@ void ODComputeSummaryTask::Update()
|
||||
|
||||
|
||||
///Computes the summary calculation queue order of the blockfiles
|
||||
void ODComputeSummaryTask::OrderBlockFiles(std::vector<ODPCMAliasBlockFile*> &unorderedBlocks)
|
||||
void ODComputeSummaryTask::OrderBlockFiles
|
||||
(std::vector< std::shared_ptr< ODPCMAliasBlockFile > > &unorderedBlocks)
|
||||
{
|
||||
//we are going to take things out of the array. But first deref them since we ref them when we put them in.
|
||||
for(unsigned int i=0;i<mBlockFiles.size();i++)
|
||||
mBlockFiles[i]->Deref();
|
||||
mBlockFiles.clear();
|
||||
//Order the blockfiles into our queue in a fancy convenient way. (this could be user-prefs)
|
||||
//for now just put them in linear. We start the order from the first block that includes the ondemand sample
|
||||
@ -253,7 +246,7 @@ void ODComputeSummaryTask::OrderBlockFiles(std::vector<ODPCMAliasBlockFile*> &un
|
||||
//check to see if the refcount is at least two before we add it to the list.
|
||||
//There should be one Ref() from the one added by this ODTask, and one from the track.
|
||||
//If there isn't, then the block was deleted for some reason and we should ignore it.
|
||||
if(unorderedBlocks[i]->RefCount()>=2)
|
||||
if(unorderedBlocks[i].use_count() >= 2)
|
||||
{
|
||||
//test if the blockfiles are near the task cursor. we use the last mBlockFiles[0] as our point of reference
|
||||
//and add ones that are closer.
|
||||
@ -277,7 +270,6 @@ void ODComputeSummaryTask::OrderBlockFiles(std::vector<ODPCMAliasBlockFile*> &un
|
||||
else
|
||||
{
|
||||
//Otherwise, let it be deleted and forget about it.
|
||||
unorderedBlocks[i]->Deref();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,8 @@ protected:
|
||||
void Update() override;
|
||||
|
||||
///Orders the input as either On-Demand or default layered order.
|
||||
void OrderBlockFiles(std::vector<ODPCMAliasBlockFile*> &unorderedBlocks);
|
||||
void OrderBlockFiles
|
||||
(std::vector< std::shared_ptr< ODPCMAliasBlockFile > > &unorderedBlocks);
|
||||
|
||||
///tells us whether or not Update has been run at least once.
|
||||
void MarkUpdateRan();
|
||||
@ -72,7 +73,7 @@ protected:
|
||||
|
||||
//mBlockFiles is touched on several threads- the OD terminate thread, and the task thread, so we need to mutex it.
|
||||
ODLock mBlockFilesMutex;
|
||||
std::vector<ODPCMAliasBlockFile*> mBlockFiles;
|
||||
std::vector< std::shared_ptr< ODPCMAliasBlockFile > > mBlockFiles;
|
||||
int mMaxBlockFiles;
|
||||
int mComputedBlockFiles;
|
||||
ODLock mHasUpdateRanMutex;
|
||||
|
@ -42,7 +42,6 @@ void ODDecodeTask::DoSomeInternal()
|
||||
return;
|
||||
}
|
||||
|
||||
ODDecodeBlockFile* bf;
|
||||
ODFileDecoder* decoder;
|
||||
sampleCount blockStartSample = 0;
|
||||
sampleCount blockEndSample = 0;
|
||||
@ -50,21 +49,21 @@ void ODDecodeTask::DoSomeInternal()
|
||||
|
||||
for(size_t i=0; i < mWaveTracks.size() && mBlockFiles.size();i++)
|
||||
{
|
||||
bf = mBlockFiles[0];
|
||||
const auto &bf = mBlockFiles[0];
|
||||
|
||||
int ret = 1;
|
||||
|
||||
//first check to see if the ref count is at least 2. It should have one
|
||||
//from when we added it to this instance's mBlockFiles array, and one from
|
||||
//the Wavetrack/sequence. If it doesn't it has been deleted and we should forget it.
|
||||
if(bf->RefCount()>=2)
|
||||
if(bf.use_count()>=2)
|
||||
{
|
||||
//OD TODO: somehow pass the bf a reference to the decoder that manages it's file.
|
||||
//we need to ensure that the filename won't change or be moved. We do this by calling LockRead(),
|
||||
//which the dirmanager::EnsureSafeFilename also does.
|
||||
bf->LockRead();
|
||||
//Get the decoder. If the file was moved, we need to create another one and init it.
|
||||
decoder=GetOrCreateMatchingFileDecoder(bf);
|
||||
decoder = GetOrCreateMatchingFileDecoder( &*bf );
|
||||
if(!decoder->IsInitialized())
|
||||
decoder->Init();
|
||||
bf->SetODFileDecoder(decoder);
|
||||
@ -87,7 +86,6 @@ void ODDecodeTask::DoSomeInternal()
|
||||
|
||||
//Release the refcount we placed on it if we are successful
|
||||
if(ret >= 0 ) {
|
||||
bf->Deref();
|
||||
//take it out of the array - we are done with it.
|
||||
mBlockFiles.erase(mBlockFiles.begin());
|
||||
|
||||
@ -127,8 +125,7 @@ bool ODDecodeTask::SeekingAllowed()
|
||||
///by default creates the order of the wavetrack to load.
|
||||
void ODDecodeTask::Update()
|
||||
{
|
||||
|
||||
std::vector<ODDecodeBlockFile*> tempBlocks;
|
||||
std::vector< std::shared_ptr< ODDecodeBlockFile > > tempBlocks;
|
||||
|
||||
mWaveTrackMutex.Lock();
|
||||
|
||||
@ -155,12 +152,12 @@ void ODDecodeTask::Update()
|
||||
{
|
||||
//since we have more than one ODBlockFile, we will need type flags to cast.
|
||||
SeqBlock &block = (*blocks)[i];
|
||||
BlockFile *const file = block.f;
|
||||
ODDecodeBlockFile *oddbFile;
|
||||
const auto &file = block.f;
|
||||
std::shared_ptr<ODDecodeBlockFile> oddbFile;
|
||||
if (!file->IsDataAvailable() &&
|
||||
(oddbFile = static_cast<ODDecodeBlockFile*>(file))->GetDecodeType() == this->GetODType())
|
||||
(oddbFile =
|
||||
std::static_pointer_cast<ODDecodeBlockFile>(file))->GetDecodeType() == this->GetODType())
|
||||
{
|
||||
file->Ref();
|
||||
oddbFile->SetStart(block.start);
|
||||
oddbFile->SetClipOffset((sampleCount)(clip->GetStartTime()*clip->GetRate()));
|
||||
|
||||
@ -187,11 +184,9 @@ void ODDecodeTask::Update()
|
||||
|
||||
|
||||
///Orders the input as either On-Demand or default layered order.
|
||||
void ODDecodeTask::OrderBlockFiles(std::vector<ODDecodeBlockFile*> &unorderedBlocks)
|
||||
void ODDecodeTask::OrderBlockFiles
|
||||
(std::vector< std::shared_ptr< ODDecodeBlockFile > > &unorderedBlocks)
|
||||
{
|
||||
//we are going to take things out of the array. But first deref them since we ref them when we put them in.
|
||||
for(unsigned int i=0;i<mBlockFiles.size();i++)
|
||||
mBlockFiles[i]->Deref();
|
||||
mBlockFiles.clear();
|
||||
//TODO:order the blockfiles into our queue in a fancy convenient way. (this could be user-prefs)
|
||||
//for now just put them in linear. We start the order from the first block that includes the ondemand sample
|
||||
@ -204,7 +199,7 @@ void ODDecodeTask::OrderBlockFiles(std::vector<ODDecodeBlockFile*> &unorderedBlo
|
||||
//check to see if the refcount is at least two before we add it to the list.
|
||||
//There should be one Ref() from the one added by this ODTask, and one from the track.
|
||||
//If there isn't, then the block was deleted for some reason and we should ignore it.
|
||||
if(unorderedBlocks[i]->RefCount()>=2)
|
||||
if(unorderedBlocks[i].use_count() >= 2)
|
||||
{
|
||||
//test if the blockfiles are near the task cursor. we use the last mBlockFiles[0] as our point of reference
|
||||
//and add ones that are closer.
|
||||
@ -228,8 +223,6 @@ void ODDecodeTask::OrderBlockFiles(std::vector<ODDecodeBlockFile*> &unorderedBlo
|
||||
}
|
||||
else
|
||||
{
|
||||
//Otherwise, let it be deleted and forget about it.
|
||||
unorderedBlocks[i]->Deref();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,10 +85,11 @@ protected:
|
||||
void Update() override;
|
||||
|
||||
///Orders the input as either On-Demand or default layered order.
|
||||
void OrderBlockFiles(std::vector<ODDecodeBlockFile*> &unorderedBlocks);
|
||||
void OrderBlockFiles
|
||||
(std::vector< std::shared_ptr< ODDecodeBlockFile > > &unorderedBlocks);
|
||||
|
||||
|
||||
std::vector<ODDecodeBlockFile*> mBlockFiles;
|
||||
std::vector<std::shared_ptr<ODDecodeBlockFile>> mBlockFiles;
|
||||
std::vector<movable_ptr<ODFileDecoder>> mDecoders;
|
||||
|
||||
int mMaxBlockFiles;
|
||||
|
Loading…
x
Reference in New Issue
Block a user