audacia/src/DirManager.h
2019-12-14 01:48:15 -05:00

283 lines
9.8 KiB
C++

/**********************************************************************
Audacity: A Digital Audio Editor
DirManager.h
Dominic Mazzoni
**********************************************************************/
#ifndef _DIRMANAGER_
#define _DIRMANAGER_
#include "audacity/Types.h"
#include "xml/XMLTagHandler.h"
#include <functional>
#include <memory>
#include <unordered_map>
#include "ClientData.h"
class wxFileNameWrapper;
class AudacityProject;
class BlockArray;
class BlockFile;
class ProgressDialog;
using DirHash = std::unordered_map<int, int>;
class BlockFile;
using BlockFilePtr = std::shared_ptr<BlockFile>;
using BlockHash = std::unordered_map< wxString, std::weak_ptr<BlockFile> >;
wxMemorySize GetFreeMemory();
enum {
kCleanTopDirToo = 1, // The top directory can be excluded from clean.
kCleanDirsOnlyIfEmpty = 2, // Otherwise non empty dirs may be removed.
kCleanFiles = 4, // Remove files
kCleanDirs = 8 // Remove dirs.
};
class PROFILE_DLL_API DirManager final
: public XMLTagHandler
, public ClientData::Base
, public std::enable_shared_from_this< DirManager >
{
public:
static DirManager &Get( AudacityProject &project );
static const DirManager &Get( const AudacityProject &project );
static DirManager &Reset( AudacityProject &project );
static void Destroy( AudacityProject &project );
static int RecursivelyEnumerate(const FilePath &dirPath,
FilePaths& filePathArray, // output: all files in dirPath tree
wxString dirspec,
wxString filespec,
bool bFiles, bool bDirs,
int progress_count = 0,
int progress_bias = 0,
ProgressDialog* progress = nullptr);
static int RecursivelyEnumerateWithProgress(const FilePath &dirPath,
FilePaths& filePathArray, // output: all files in dirPath tree
wxString dirspec,
wxString filespec,
bool bFiles, bool bDirs,
int progress_count,
const TranslatableString &message);
static int RecursivelyCountSubdirs( const FilePath &dirPath );
static int RecursivelyRemoveEmptyDirs(const FilePath &dirPath,
int nDirCount = 0,
ProgressDialog* pProgress = nullptr);
static void RecursivelyRemove(const FilePaths& filePathArray, int count, int bias,
int flags, const TranslatableString &message = {});
// 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();
DirManager( const DirManager & ) PROHIBITED;
DirManager &operator=( const DirManager & ) PROHIBITED;
virtual ~DirManager();
size_t NumBlockFiles() const { return mBlockFileHash.size(); }
static void SetTempDir(const wxString &_temp) { globaltemp = _temp; }
class ProjectSetter
{
public:
ProjectSetter(
DirManager &dirManager,
FilePath& newProjPath, // assigns it if empty
const FilePath& newProjName, const bool bCreate, bool moving);
~ProjectSetter();
bool Ok();
void Commit();
private:
struct Impl;
std::unique_ptr<Impl> mpImpl;
};
// Returns true on success.
// If SetProject is told NOT to create the directory
// but it doesn't already exist, SetProject fails and returns false.
// This function simply creates a ProjectSetter and commits it if successful.
// Using ProjectSetter directly allows separation of those steps.
bool SetProject(
FilePath& newProjPath, // assigns it if empty
const FilePath& newProjName, const bool bCreate);
FilePath GetProjectDataDir();
FilePath GetProjectName();
wxLongLong GetFreeDiskSpace();
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;
/// Check for existing using filename using complete filename
bool ContainsBlockFile(const wxString &filepath) const;
// Adds one to the reference count of the block file,
// UNLESS it is "locked", then it makes a NEW copy of
// the BlockFile.
// May throw an exception in case of disk space exhaustion, otherwise
// returns non-null.
BlockFilePtr CopyBlockFile(const BlockFilePtr &b);
BlockFile *LoadBlockFile(const wxChar **attrs, sampleFormat format);
void SaveBlockFile(BlockFile *f, int depth, FILE *fp);
#if LEGACY_PROJECT_FILE_SUPPORT
BlockFile *LoadBlockFile(wxTextFile * in, sampleFormat format);
void SaveBlockFile(BlockFile * f, wxTextFile * out);
#endif
std::pair<bool, FilePath>
LinkOrCopyToNewProjectDirectory(BlockFile *f, bool &link);
bool EnsureSafeFilename(const wxFileName &fName);
using LoadingTarget = std::function< BlockFilePtr &() >;
void SetLoadingTarget( LoadingTarget loadingTarget )
{
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
void SetLoadingMaxSamples(size_t max) { mMaxSamples = max; }
bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override;
XMLTagHandler *HandleXMLChild(const wxChar * WXUNUSED(tag)) override
{ return NULL; }
bool AssignFile(wxFileNameWrapper &filename, const wxString &value, bool check);
// Clean the temp dir. Note that now where we have auto recovery the temp
// dir is not cleaned at start up anymore. But it is cleaned when the
// program is exited normally.
static void CleanTempDir();
static void CleanDir(
const FilePath &path,
const wxString &dirSpec,
const wxString &fileSpec,
const TranslatableString &msg,
int flags = 0);
void FindMissingAliasFiles(
BlockHash& missingAliasFilesAUFHash, // output: (.auf) AliasBlockFiles whose aliased files are missing
BlockHash& missingAliasFilesPathHash); // output: full paths of missing aliased files
void FindMissingAUFs(
BlockHash& missingAUFHash); // output: missing (.auf) AliasBlockFiles
void FindMissingAUs(
BlockHash& missingAUHash); // missing data (.au) blockfiles
// Find .au and .auf files that are not in the project.
void FindOrphanBlockFiles(
const FilePaths &filePathArray, // input: all files in project directory
FilePaths &orphanFilePathArray); // output: orphan files
// Remove all orphaned blockfiles without user interaction. This is
// generally safe, because orphaned blockfiles are not referenced by the
// project and thus worthless anyway.
void RemoveOrphanBlockfiles();
// Get directory where data files are in. Note that projects are normally
// not interested in this information, but it is important for the
// auto-save functionality
FilePath GetDataFilesDir() const;
// This should only be used by the auto save functionality
void SetLocalTempDir(const wxString &path);
// Do not DELETE any temporary files on exit. This is only called if
// auto recovery is cancelled and should be retried later
static void SetDontDeleteTempFiles() { dontDeleteTempFiles = true; }
// Write all write-cached block files to disc, if any
void WriteCacheToDisk();
// (Try to) fill cache of blockfiles, if caching is enabled (otherwise do
// nothing)
// A no-fail operation that does not throw
void FillBlockfilesCache();
private:
wxFileNameWrapper MakeBlockFileName();
wxFileNameWrapper MakeBlockFilePath(const wxString &value);
BlockHash mBlockFileHash; // repository for blockfiles
// 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&);
void BalanceFileAdd(int);
int BalanceMidAdd(int, int);
FilePath projName;
FilePath projPath;
FilePath projFull;
FilePaths aliasList;
LoadingTarget mLoadingTarget;
sampleFormat mLoadingFormat;
size_t mLoadingBlockLen;
size_t mMaxSamples; // max samples per block
unsigned long mLastBlockFileDestructionCount { 0 };
static wxString globaltemp;
wxString mytemp;
static int numDirManagers;
static bool dontDeleteTempFiles;
};
#endif