Audacity  2.2.2
Classes | Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes | List of all members
DirManager Class Referencefinal

Creates and manages BlockFile objects. More...

#include <DirManager.h>

Inheritance diagram for DirManager:
XMLTagHandler

Classes

struct  BalanceInfo
 

Public Member Functions

 DirManager ()
 
virtual ~DirManager ()
 
bool SetProject (wxString &newProjPath, wxString &newProjName, const bool bCreate)
 
wxString GetProjectDataDir ()
 
wxString GetProjectName ()
 
wxLongLong GetFreeDiskSpace ()
 
BlockFilePtr NewSimpleBlockFile (samplePtr sampleData, size_t sampleLen, sampleFormat format, bool allowDeferredWrite=false)
 
BlockFilePtr NewAliasBlockFile (const wxString &aliasedFile, sampleCount aliasStart, size_t aliasLen, int aliasChannel)
 
BlockFilePtr NewODAliasBlockFile (const wxString &aliasedFile, sampleCount aliasStart, size_t aliasLen, int aliasChannel)
 
BlockFilePtr NewODDecodeBlockFile (const wxString &aliasedFile, sampleCount aliasStart, size_t aliasLen, int aliasChannel, int decodeType)
 
bool ContainsBlockFile (const BlockFile *b) const
 Returns true if the blockfile pointed to by b is contained by the DirManager. More...
 
bool ContainsBlockFile (const wxString &filepath) const
 Check for existing using filename using complete filename. More...
 
BlockFilePtr CopyBlockFile (const BlockFilePtr &b)
 
BlockFileLoadBlockFile (const wxChar **attrs, sampleFormat format)
 
void SaveBlockFile (BlockFile *f, int depth, FILE *fp)
 
std::pair< bool, wxString > CopyToNewProjectDirectory (BlockFile *f)
 
bool EnsureSafeFilename (const wxFileName &fName)
 
void SetLoadingTarget (BlockArray *pArray, unsigned idx)
 
void SetLoadingFormat (sampleFormat format)
 
void SetLoadingBlockLength (size_t len)
 
void SetLoadingMaxSamples (size_t max)
 
bool HandleXMLTag (const wxChar *tag, const wxChar **attrs) override
 
XMLTagHandlerHandleXMLChild (const wxChar *WXUNUSED(tag)) override
 
bool AssignFile (wxFileNameWrapper &filename, const wxString &value, bool check)
 
int ProjectFSCK (const bool bForceError, const bool bAutoRecoverMode)
 
void FindMissingAliasedFiles (BlockHash &missingAliasedFileAUFHash, BlockHash &missingAliasedFilePathHash)
 
void FindMissingAUFs (BlockHash &missingAUFHash)
 
void FindMissingAUs (BlockHash &missingAUHash)
 
void FindOrphanBlockFiles (const wxArrayString &filePathArray, wxArrayString &orphanFilePathArray)
 
void RemoveOrphanBlockfiles ()
 
wxString GetDataFilesDir () const
 
void SetLocalTempDir (const wxString &path)
 
void WriteCacheToDisk ()
 
void FillBlockfilesCache ()
 
- Public Member Functions inherited from XMLTagHandler
 XMLTagHandler ()
 
virtual ~XMLTagHandler ()
 
virtual void HandleXMLEndTag (const wxChar *WXUNUSED(tag))
 
virtual void HandleXMLContent (const wxString &WXUNUSED(content))
 
virtual XMLTagHandlerHandleXMLChild (const wxChar *tag)=0
 
bool ReadXMLTag (const char *tag, const char **attrs)
 
void ReadXMLEndTag (const char *tag)
 
void ReadXMLContent (const char *s, int len)
 
XMLTagHandlerReadXMLChild (const char *tag)
 

Static Public Member Functions

static void SetTempDir (const wxString &_temp)
 
static void CleanTempDir ()
 
static void CleanDir (const wxString &path, const wxString &dirSpec, const wxString &fileSpec, const wxString &msg, int flags=0)
 
static void SetDontDeleteTempFiles ()
 

Private Member Functions

wxFileNameWrapper MakeBlockFileName ()
 
wxFileNameWrapper MakeBlockFilePath (const wxString &value)
 
BalanceInfoGetBalanceInfo ()
 
void BalanceInfoDel (const wxString &)
 
void BalanceInfoAdd (const wxString &)
 
void BalanceFileAdd (int)
 
int BalanceMidAdd (int, int)
 

Private Attributes

BlockHash mBlockFileHash
 
struct DirManager::BalanceInfo mBalanceInfo
 
wxString projName
 
wxString projPath
 
wxString projFull
 
wxString lastProject
 
wxArrayString aliasList
 
BlockArraymLoadingTarget
 
unsigned mLoadingTargetIdx
 
sampleFormat mLoadingFormat
 
size_t mLoadingBlockLen
 
size_t mMaxSamples
 
unsigned long mLastBlockFileDestructionCount { 0 }
 
wxString mytemp
 

Static Private Attributes

static wxString globaltemp
 
static int numDirManagers = 0
 
static bool dontDeleteTempFiles = false
 

Detailed Description

Creates and manages BlockFile objects.

This class manages the files that a project uses to store most of its data. It creates NEW BlockFile objects, which can be used to store any type of data. BlockFiles support all of the common file operations, but they also support reference counting, so two different parts of a project can point to the same block of data.

For example, a track might contain 10 blocks of data representing its audio. If you copy the last 5 blocks and paste at the end of the file, no NEW blocks need to be created - we just store pointers to NEW ones. When part of a track is deleted, the affected blocks decrement their reference counts, and when they reach zero they are deleted. This same mechanism is also used to implement Undo.

The DirManager, besides mapping filenames to absolute paths, also hashes all of the block names used in a project, so that when reading a project from disk, multiple copies of the same block still get mapped to the same BlockFile object.

The blockfile/directory scheme is rather complicated with two different schemes. The current scheme uses two levels of subdirectories - up to 256 'eXX' and up to 256 'dYY' directories within each of the 'eXX' dirs, where XX and YY are hex chars. In each of the dXX directories there are up to 256 audio files (e.g. .au or .auf). They have a filename scheme of 'eXXYYZZZZ', where XX and YY refers to the subdirectories as above. The 'ZZZZ' component is generated randomly for some reason. The XX and YY components are sequential. DirManager fills up the current dYY subdir until 256 are created, and moves on to the next one.

So for example, the first blockfile created may be 'e00/d00/e0000a23b.au' and the next 'e00/d00/e000015e8.au', and the 257th may be 'e00/d01/e0001f02a.au'. On close the blockfiles that are no longer referenced by the project (edited or deleted) are removed, along with the consequent empty directories.

Definition at line 52 of file DirManager.h.

Constructor & Destructor Documentation

DirManager::DirManager ( )

Definition at line 369 of file DirManager.cpp.

References _(), DirManager::BalanceInfo::dirTopPool, BlockFile::gBlockFileDestructionCount, globaltemp, mBalanceInfo, mLastBlockFileDestructionCount, mLoadingTarget, mLoadingTargetIdx, mMaxSamples, mytemp, numDirManagers, projName, projPath, and ShowWarningDialog().

370 {
371  wxLogDebug(wxT("DirManager: Created new instance."));
372 
374 
375  // Seed the random number generator.
376  // this need not be strictly uniform or random, but it should give
377  // unclustered numbers
378  srand(time(NULL));
379 
380  // Set up local temp subdir
381  // Previously, Audacity just named project temp directories "project0",
382  // "project1" and so on. But with the advent of recovery code, we need a
383  // unique name even after a crash. So we create a random project index
384  // and make sure it is not used already. This will not pose any performance
385  // penalties as long as the number of open Audacity projects is much
386  // lower than RAND_MAX.
387  do {
388  mytemp = globaltemp + wxFILE_SEP_PATH +
389  wxString::Format(wxT("project%d"), rand());
390  } while (wxDirExists(mytemp));
391 
392  numDirManagers++;
393 
394  projPath = wxT("");
395  projName = wxT("");
396 
397  mLoadingTarget = NULL;
398  mLoadingTargetIdx = 0;
399  mMaxSamples = ~size_t(0);
400 
401  // toplevel pool hash is fully populated to begin
402  {
403  // We can bypass the accessor function while initializing
404  auto &balanceInfo = mBalanceInfo;
405  auto &dirTopPool = balanceInfo.dirTopPool;
406  for(int i = 0; i < 256; ++i)
407  dirTopPool[i] = 0;
408  }
409 
410  // Make sure there is plenty of space for temp files
411  wxLongLong freeSpace = 0;
412  if (wxGetDiskSpace(globaltemp, NULL, &freeSpace)) {
413  if (freeSpace < wxLongLong(wxLL(100 * 1048576))) {
414  ShowWarningDialog(NULL, wxT("DiskSpaceWarning"),
415  _("There is very little free disk space left on this volume.\nPlease select another temporary directory in Preferences."));
416  }
417  }
418 }
wxString projName
Definition: DirManager.h:211
static wxString globaltemp
Definition: DirManager.h:228
size_t mMaxSamples
Definition: DirManager.h:224
static unsigned long gBlockFileDestructionCount
Definition: BlockFile.h:65
static int numDirManagers
Definition: DirManager.h:230
unsigned mLoadingTargetIdx
Definition: DirManager.h:220
wxString projPath
Definition: DirManager.h:212
int ShowWarningDialog(wxWindow *parent, const wxString &internalDialogName, const wxString &message, bool showCancelButton, const wxString &footer)
Definition: Warning.cpp:93
struct DirManager::BalanceInfo mBalanceInfo
BlockArray * mLoadingTarget
Definition: DirManager.h:219
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
wxString mytemp
Definition: DirManager.h:229
unsigned long mLastBlockFileDestructionCount
Definition: DirManager.h:226
DirManager::~DirManager ( )
virtual

Definition at line 420 of file DirManager.cpp.

References _(), CleanDir(), CleanTempDir(), kCleanDirsOnlyIfEmpty, kCleanTopDirToo, mytemp, numDirManagers, and projFull.

421 {
422  numDirManagers--;
423  if (numDirManagers == 0) {
424  CleanTempDir();
425  //::wxRmdir(temp);
426  } else if( projFull.IsEmpty() && !mytemp.IsEmpty()) {
427  CleanDir(mytemp, wxEmptyString, ".DS_Store", _("Cleaning project temporary files"), kCleanTopDirToo | kCleanDirsOnlyIfEmpty );
428  }
429 }
static void CleanDir(const wxString &path, const wxString &dirSpec, const wxString &fileSpec, const wxString &msg, int flags=0)
Definition: DirManager.cpp:444
static int numDirManagers
Definition: DirManager.h:230
wxString projFull
Definition: DirManager.h:213
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
wxString mytemp
Definition: DirManager.h:229
static void CleanTempDir()
Definition: DirManager.cpp:436

Member Function Documentation

bool DirManager::AssignFile ( wxFileNameWrapper filename,
const wxString &  value,
bool  check 
)

Definition at line 752 of file DirManager.cpp.

References _(), and MakeBlockFilePath().

Referenced by PCMAliasBlockFile::BuildFromXML(), SimpleBlockFile::BuildFromXML(), ODPCMAliasBlockFile::BuildFromXML(), ODDecodeBlockFile::BuildFromXML(), CopyToNewProjectDirectory(), and MakeBlockFileName().

755 {
756  wxFileNameWrapper dir{ MakeBlockFilePath(value) };
757 
758  if(diskcheck){
759  // verify that there's no possible collision on disk. If there
760  // is, log the problem and return FALSE so that MakeBlockFileName
761  // can try again
762 
763  wxDir checkit(dir.GetFullPath());
764  if(!checkit.IsOpened()) return FALSE;
765 
766  // this code is only valid if 'value' has no extention; that
767  // means, effectively, AssignFile may be called with 'diskcheck'
768  // set to true only if called from MakeFileBlockName().
769 
770  wxString filespec;
771  filespec.Printf(wxT("%s.*"),value);
772  if(checkit.HasFiles(filespec)){
773  // collision with on-disk state!
774  wxString collision;
775  checkit.GetFirst(&collision,filespec);
776 
777  wxLogWarning(_("Audacity found an orphan block file: %s. \nPlease consider saving and reloading the project to perform a complete project check."),
778  collision);
779 
780  return FALSE;
781  }
782  }
783  fileName.Assign(dir.GetFullPath(),value);
784  return fileName.IsOk();
785 }
wxFileNameWrapper MakeBlockFilePath(const wxString &value)
Definition: DirManager.cpp:720
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
void DirManager::BalanceFileAdd ( int  midkey)
private

Definition at line 824 of file DirManager.cpp.

References GetBalanceInfo().

Referenced by BalanceInfoAdd(), and MakeBlockFileName().

825 {
826  auto &balanceInfo = GetBalanceInfo();
827  auto &dirMidPool = balanceInfo.dirMidPool;
828  auto &dirMidFull = balanceInfo.dirMidFull;
829 
830  // increment the midlevel directory usage information
831  if(dirMidPool.find(midkey) != dirMidPool.end()){
832  dirMidPool[midkey]++;
833  if(dirMidPool[midkey]>=256){
834  // this middir is now full; move it to the full hash
835  dirMidPool.erase(midkey);
836  dirMidFull[midkey]=256;
837  }
838  }else{
839  // this case only triggers in absurdly large projects; we still
840  // need to track directory fill even if we're over 256/256/256
841  dirMidPool[midkey]++;
842  }
843 }
BalanceInfo & GetBalanceInfo()
Definition: DirManager.cpp:862
void DirManager::BalanceInfoAdd ( const wxString &  file)
private

Definition at line 845 of file DirManager.cpp.

References BalanceFileAdd(), BalanceMidAdd(), and hexchar_to_int().

Referenced by HandleXMLTag().

846 {
847  const wxChar *s=file;
848  if(s[0]==wxT('e')){
849  // this is one of the modern two-deep managed files
850  // convert filename to keys
851  unsigned int topnum = (hexchar_to_int(s[1]) << 4) |
852  hexchar_to_int(s[2]);
853  unsigned int midnum = (hexchar_to_int(s[3]) << 4) |
854  hexchar_to_int(s[4]);
855  unsigned int midkey=topnum<<8|midnum;
856 
857  BalanceMidAdd(topnum,midkey);
858  BalanceFileAdd(midkey);
859  }
860 }
void BalanceFileAdd(int)
Definition: DirManager.cpp:824
int BalanceMidAdd(int, int)
Definition: DirManager.cpp:798
static unsigned int hexchar_to_int(unsigned int x)
Definition: DirManager.cpp:787
void DirManager::BalanceInfoDel ( const wxString &  file)
private

Definition at line 892 of file DirManager.cpp.

References DirManager::BalanceInfo::dirMidPool, hexchar_to_int(), mBalanceInfo, mytemp, and projFull.

893 {
894  // do not use GetBalanceInfo(),
895  // rather this function will be called from there.
896  auto &balanceInfo = mBalanceInfo;
897  auto &dirMidPool = balanceInfo.dirMidPool;
898  auto &dirMidFull = balanceInfo.dirMidFull;
899  auto &dirTopPool = balanceInfo.dirTopPool;
900  auto &dirTopFull = balanceInfo.dirTopFull;
901 
902  const wxChar *s=file;
903  if(s[0]==wxT('e')){
904  // this is one of the modern two-deep managed files
905 
906  unsigned int topnum = (hexchar_to_int(s[1]) << 4) |
907  hexchar_to_int(s[2]);
908  unsigned int midnum = (hexchar_to_int(s[3]) << 4) |
909  hexchar_to_int(s[4]);
910  unsigned int midkey=topnum<<8|midnum;
911 
912  // look for midkey in the mid pool
913  if(dirMidFull.find(midkey) != dirMidFull.end()){
914  // in the full pool
915 
916  if(--dirMidFull[midkey]<256){
917  // move out of full into available
918  dirMidPool[midkey]=dirMidFull[midkey];
919  dirMidFull.erase(midkey);
920  }
921  }else{
922  if(--dirMidPool[midkey]<1){
923  // erasing the key here is OK; we have provision to add it
924  // back if its needed (unlike the dirTopPool hash)
925  dirMidPool.erase(midkey);
926 
927  // DELETE the actual directory
928  wxString dir=(projFull != wxT("")? projFull: mytemp);
929  dir += wxFILE_SEP_PATH;
930  dir += file.Mid(0,3);
931  dir += wxFILE_SEP_PATH;
932  dir += wxT("d");
933  dir += file.Mid(3,2);
934  wxFileName::Rmdir(dir);
935 
936  // also need to remove from toplevel
937  if(dirTopFull.find(topnum) != dirTopFull.end()){
938  // in the full pool
939  if(--dirTopFull[topnum]<256){
940  // move out of full into available
941  dirTopPool[topnum]=dirTopFull[topnum];
942  dirTopFull.erase(topnum);
943  }
944  }else{
945  if(--dirTopPool[topnum]<1){
946  // do *not* erase the hash entry from dirTopPool
947  // *do* DELETE the actual directory
948  wxString dir=(projFull != wxT("")? projFull: mytemp);
949  dir += wxFILE_SEP_PATH;
950  dir += file.Mid(0,3);
951  wxFileName::Rmdir(dir);
952  }
953  }
954  }
955  }
956  }
957 }
struct DirManager::BalanceInfo mBalanceInfo
wxString projFull
Definition: DirManager.h:213
wxString mytemp
Definition: DirManager.h:229
static unsigned int hexchar_to_int(unsigned int x)
Definition: DirManager.cpp:787
int DirManager::BalanceMidAdd ( int  topnum,
int  midkey 
)
private

Definition at line 798 of file DirManager.cpp.

References GetBalanceInfo().

Referenced by BalanceInfoAdd(), and MakeBlockFileName().

799 {
800  // enter the midlevel directory if it doesn't exist
801 
802  auto &balanceInfo = GetBalanceInfo();
803  auto &dirMidPool = balanceInfo.dirMidPool;
804  auto &dirMidFull = balanceInfo.dirMidFull;
805  auto &dirTopPool = balanceInfo.dirTopPool;
806  auto &dirTopFull = balanceInfo.dirTopFull;
807 
808  if(dirMidPool.find(midkey) == dirMidPool.end() &&
809  dirMidFull.find(midkey) == dirMidFull.end()){
810  dirMidPool[midkey]=0;
811 
812  // increment toplevel directory fill
813  dirTopPool[topnum]++;
814  if(dirTopPool[topnum]>=256){
815  // this toplevel is now full; move it to the full hash
816  dirTopPool.erase(topnum);
817  dirTopFull[topnum]=256;
818  }
819  return 1;
820  }
821  return 0;
822 }
BalanceInfo & GetBalanceInfo()
Definition: DirManager.cpp:862
void DirManager::CleanDir ( const wxString &  path,
const wxString &  dirSpec,
const wxString &  fileSpec,
const wxString &  msg,
int  flags = 0 
)
static

Definition at line 444 of file DirManager.cpp.

References dontDeleteTempFiles, kCleanDirs, kCleanFiles, kCleanTopDirToo, RecursivelyEnumerate(), and RecursivelyRemove().

Referenced by CleanTempDir(), SetProject(), and ~DirManager().

450 {
452  return; // do nothing
453 
454  wxArrayString filePathArray, dirPathArray;
455 
456  int countFiles =
457  RecursivelyEnumerate(path, filePathArray, dirSpec, fileSpec, true, false);
458  int countDirs =
459  RecursivelyEnumerate(path, dirPathArray, dirSpec, fileSpec, false, true);
460 
461  // Subtract 1 because we don't want to DELETE the global temp directory,
462  // which this will find and list last.
463  if ((flags & kCleanTopDirToo)==0) {
464  // Remove the globaltemp itself from the array so that it is not deleted.
465  --countDirs;
466  dirPathArray.resize(countDirs);
467  }
468 
469  auto count = countFiles + countDirs;
470  if (count == 0)
471  return;
472 
473  RecursivelyRemove(filePathArray, count, 0, flags | kCleanFiles, msg);
474  RecursivelyRemove(dirPathArray, count, countFiles, flags | kCleanDirs, msg);
475 }
static int RecursivelyEnumerate(wxString dirPath, wxArrayString &filePathArray, wxString dirspec, wxString filespec, bool bFiles, bool bDirs, int progress_count=0, int progress_bias=0, ProgressDialog *progress=NULL)
Definition: DirManager.cpp:162
static bool dontDeleteTempFiles
Definition: DirManager.h:231
static void RecursivelyRemove(wxArrayString &filePathArray, int count, int bias, int flags, const wxChar *message=NULL)
Definition: DirManager.cpp:303
void DirManager::CleanTempDir ( )
static

Definition at line 436 of file DirManager.cpp.

References _(), CleanDir(), and globaltemp.

Referenced by TimerRecordDialog::ExecutePostRecordActions(), and ~DirManager().

437 {
438  // with default flags (none) this does not clean the top directory, and may remove non-empty
439  // directories.
440  CleanDir(globaltemp, wxT("project*"), wxEmptyString, _("Cleaning up temporary files"));
441 }
static void CleanDir(const wxString &path, const wxString &dirSpec, const wxString &fileSpec, const wxString &msg, int flags=0)
Definition: DirManager.cpp:444
static wxString globaltemp
Definition: DirManager.h:228
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
bool DirManager::ContainsBlockFile ( const BlockFile b) const

Returns true if the blockfile pointed to by b is contained by the DirManager.

Definition at line 1145 of file DirManager.cpp.

References BlockFile::GetFileName(), and mBlockFileHash.

Referenced by FindOrphanBlockFiles(), and MakeBlockFileName().

1146 {
1147  if (!b)
1148  return false;
1149  auto result = b->GetFileName();
1150  BlockHash::const_iterator it = mBlockFileHash.find(result.name.GetName());
1151  if (it == mBlockFileHash.end())
1152  return false;
1153  BlockFilePtr ptr = it->second.lock();
1154  return ptr && (b == &*ptr);
1155 }
std::shared_ptr< BlockFile > BlockFilePtr
Definition: BlockFile.h:48
BlockHash mBlockFileHash
Definition: DirManager.h:191
virtual GetFileNameResult GetFileName() const
Definition: BlockFile.cpp:127
bool DirManager::ContainsBlockFile ( const wxString &  filepath) const

Check for existing using filename using complete filename.

Definition at line 1157 of file DirManager.cpp.

References mBlockFileHash.

1158 {
1159  // check what the hash returns in case the blockfile is from a different project
1160  BlockHash::const_iterator it = mBlockFileHash.find(filepath);
1161  return it != mBlockFileHash.end() &&
1162  BlockFilePtr{ it->second.lock() };
1163 }
std::shared_ptr< BlockFile > BlockFilePtr
Definition: BlockFile.h:48
BlockHash mBlockFileHash
Definition: DirManager.h:191
BlockFilePtr DirManager::CopyBlockFile ( const BlockFilePtr b)

Definition at line 1169 of file DirManager.cpp.

References mBlockFileHash, and THROW_INCONSISTENCY_EXCEPTION.

Referenced by Sequence::AppendBlock().

1170 {
1171  if (!b)
1173 
1174  auto result = b->GetFileName();
1175  const auto &fn = result.name;
1176 
1177  if (!b->IsLocked()) {
1178  //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.
1179  //note that this shouldn't hurt mBlockFileHash's that already contain the filename, since it should just overwrite.
1180  //but it's something to watch out for.
1181  //
1182  // LLL: Except for silent block files which have uninitialized filename.
1183  if (fn.IsOk())
1184  mBlockFileHash[fn.GetName()] = b;
1185  return b;
1186  }
1187 
1188  // Copy the blockfile
1189  BlockFilePtr b2;
1190  if (!fn.IsOk())
1191  // Block files with uninitialized filename (i.e. SilentBlockFile)
1192  // just need an in-memory copy.
1193  b2 = b->Copy(wxFileNameWrapper{});
1194  else
1195  {
1196  wxFileNameWrapper newFile{ MakeBlockFileName() };
1197  const wxString newName{newFile.GetName()};
1198  const wxString newPath{ newFile.GetFullPath() };
1199 
1200  // We assume that the NEW file should have the same extension
1201  // as the existing file
1202  newFile.SetExt(fn.GetExt());
1203 
1204  //some block files such as ODPCMAliasBlockFIle don't always have
1205  //a summary file, so we should check before we copy.
1206  if(b->IsSummaryAvailable())
1207  {
1208  if( !FileNames::CopyFile(fn.GetFullPath(),
1209  newFile.GetFullPath()) )
1210  // Disk space exhaustion, maybe
1211  throw FileException{
1212  FileException::Cause::Write, newFile };
1213  }
1214 
1215  // Done with fn
1216  result.mLocker.reset();
1217 
1218  b2 = b->Copy(std::move(newFile));
1219 
1220  mBlockFileHash[newName] = b2;
1221  aliasList.Add(newPath);
1222  }
1223 
1224  if (!b2)
1226 
1227  return b2;
1228 }
#define THROW_INCONSISTENCY_EXCEPTION
std::shared_ptr< BlockFile > BlockFilePtr
Definition: BlockFile.h:48
static bool CopyFile(const wxString &file1, const wxString &file2, bool overwrite=true)
Definition: FileNames.cpp:46
BlockHash mBlockFileHash
Definition: DirManager.h:191
wxArrayString aliasList
Definition: DirManager.h:217
wxFileNameWrapper MakeBlockFileName()
Definition: DirManager.cpp:961
std::pair< bool, wxString > DirManager::CopyToNewProjectDirectory ( BlockFile f)

Definition at line 1332 of file DirManager.cpp.

References AssignFile(), FileNames::CopyFile(), BlockFile::GetFileName(), BlockFile::IsSummaryAvailable(), BlockFile::IsSummaryBeingComputed(), BlockFile::GetFileNameResult::name, and BlockFile::SetFileName().

Referenced by SetProject().

1333 {
1334  wxString newPath;
1335  auto result = f->GetFileName();
1336  const auto &oldFileNameRef = result.name;
1337 
1338  // Check that this BlockFile corresponds to a file on disk
1339  //ANSWER-ME: Is this checking only for SilentBlockFiles, in which case
1340  // (!oldFileName.IsOk()) is a more correct check?
1341  if (oldFileNameRef.GetName().IsEmpty()) {
1342  return { true, newPath };
1343  }
1344 
1345  wxFileNameWrapper newFileName;
1346  if (!this->AssignFile(newFileName, oldFileNameRef.GetFullName(), false)
1347  // Another sanity check against blockfiles getting reassigned an empty
1348  // name, as apparently happened in
1349  // http://forum.audacityteam.org/viewtopic.php?f=47&t=97787 :
1350  || newFileName.GetFullName().empty() )
1351  return { false, {} };
1352 
1353  newPath = newFileName.GetFullPath();
1354 
1355  if (newFileName != oldFileNameRef) {
1356  //check to see that summary exists before we copy.
1357  bool summaryExisted = f->IsSummaryAvailable();
1358  auto oldPath = oldFileNameRef.GetFullPath();
1359  if (summaryExisted) {
1360  auto success = FileNames::CopyFile(oldPath, newPath);
1361  if (!success)
1362  return { false, {} };
1363  }
1364 
1365  if (!summaryExisted && (f->IsSummaryAvailable() || f->IsSummaryBeingComputed())) {
1366  // PRL: These steps apply only in case of "on-demand" files that have
1367  // not completed their asynchronous loading yet -- a very unusual
1368  // circumstance.
1369 
1370  // We will need to remember the old file name, so copy it
1371  wxFileName oldFileName{ oldFileNameRef };
1372 
1373  // Now we can free any lock (and should, if as the comment below says, we need
1374  // the other threads to progress)
1375  result.mLocker.reset();
1376 
1377  f->SetFileName(std::move(newFileName));
1378 
1379  //there is a small chance that the summary has begun to be computed on a different thread with the
1380  //original filename. we need to catch this case by waiting for it to finish and then copy.
1381 
1382  //block to make sure OD files don't get written while we are changing file names.
1383  //(It is important that OD files set this lock while computing their summary files.)
1384  while(f->IsSummaryBeingComputed() && !f->IsSummaryAvailable())
1385  ::wxMilliSleep(50);
1386 
1387  //check to make sure the oldfile exists.
1388  //if it doesn't, we can assume it was written to the NEW name, which is fine.
1389  if (oldFileName.FileExists())
1390  {
1391  bool ok = FileNames::CopyFile(oldPath, newPath);
1392  if (!ok)
1393  return { false, {} };
1394  }
1395  }
1396  }
1397 
1398  return { true, newPath };
1399 }
virtual bool IsSummaryBeingComputed()
Returns TRUE if the summary has not yet been written, but is actively being computed and written to d...
Definition: BlockFile.h:146
static bool CopyFile(const wxString &file1, const wxString &file2, bool overwrite=true)
Definition: FileNames.cpp:46
virtual void SetFileName(wxFileNameWrapper &&name)
sets the file name the summary info will be saved in. threadsafe.
Definition: BlockFile.cpp:133
virtual GetFileNameResult GetFileName() const
Definition: BlockFile.cpp:127
const wxFileName & name
Definition: BlockFile.h:99
virtual bool IsSummaryAvailable() const
Returns TRUE if this block's complete summary has been computed and is ready (for OD) ...
Definition: BlockFile.h:140
bool AssignFile(wxFileNameWrapper &filename, const wxString &value, bool check)
Definition: DirManager.cpp:752
bool DirManager::EnsureSafeFilename ( const wxFileName &  fName)

Definition at line 1401 of file DirManager.cpp.

References _(), aliasList, ODDecodeBlockFile::ChangeAudioFile(), and mBlockFileHash.

1402 {
1403  // Quick check: If it's not even in our alias list,
1404  // then the file name is A-OK.
1405 
1406  const wxString fullPath{fName.GetFullPath()};
1407  if (aliasList.Index(fullPath) == wxNOT_FOUND)
1408  return true;
1409 
1410  /* i18n-hint: 'old' is part of a filename used when a file is renamed. */
1411  // Figure out what the NEW name for the existing file would be.
1412  /* i18n-hint: e.g. Try to go from "mysong.wav" to "mysong-old1.wav". */
1413  // Keep trying until we find a filename that doesn't exist.
1414 
1415  wxFileNameWrapper renamedFileName{ fName };
1416  int i = 0;
1417  do {
1418  i++;
1419  /* i18n-hint: This is the pattern for filenames that are created
1420  * when a file needs to be backed up to a different name. For
1421  * example, mysong would become mysong-old1, mysong-old2, etc. */
1422  renamedFileName.SetName(wxString::Format(_("%s-old%d"), fName.GetName(), i));
1423  } while (renamedFileName.FileExists());
1424 
1425  // Test creating a file by that name to make sure it will
1426  // be possible to do the rename
1427 
1428  const wxString renamedFullPath{ renamedFileName.GetFullPath() };
1429  wxFile testFile(renamedFullPath, wxFile::write);
1430  if (!testFile.IsOpened()) {
1431  { // need braces to avoid compiler warning about ambiguous else, see the macro
1432  wxLogSysError(_("Unable to open/create test file."),
1433  renamedFullPath);
1434  }
1435  return false;
1436  }
1437 
1438  // Close the file prior to renaming.
1439  testFile.Close();
1440 
1441  if (!wxRemoveFile(renamedFullPath)) {
1442  /* i18n-hint: %s is the name of a file.*/
1443  { // need braces to avoid compiler warning about ambiguous else, see the macro
1444  wxLogSysError(_("Unable to remove '%s'."),
1445  renamedFullPath);
1446  }
1447  return false;
1448  }
1449 
1450  wxPrintf(_("Renamed file: %s\n"), renamedFullPath);
1451 
1452  // Go through our block files and see if any indeed point to
1453  // the file we're concerned about. If so, point the block file
1454  // to the renamed file and when we're done, perform the rename.
1455 
1456  bool needToRename = false;
1457  wxBusyCursor busy;
1458  BlockHash::iterator iter = mBlockFileHash.begin();
1459  std::vector< BlockFile::ReadLock > readLocks;
1460  while (iter != mBlockFileHash.end())
1461  {
1462  BlockFilePtr b = iter->second.lock();
1463  if (b) {
1464  // don't worry, we don't rely on this cast unless IsAlias is true
1465  auto ab = static_cast< AliasBlockFile * > ( &*b );
1466 
1467  // don't worry, we don't rely on this cast unless ISDataAvailable is false
1468  // which means that it still needs to access the file.
1469  auto db = static_cast< ODDecodeBlockFile * > ( &*b );
1470 
1471  if (b->IsAlias() && ab->GetAliasedFileName() == fName) {
1472  needToRename = true;
1473 
1474  //ODBlocks access the aliased file on another thread, so we need to pause them before this continues.
1475  readLocks.push_back( ab->LockForRead() );
1476  }
1477  //now for encoded OD blocks (e.g. flac)
1478  else if (!b->IsDataAvailable() && db->GetEncodedAudioFilename() == fName) {
1479  needToRename = true;
1480 
1481  //ODBlocks access the aliased file on another thread, so we need to pause them before this continues.
1482  readLocks.push_back( db->LockForRead() );
1483  }
1484  }
1485  ++iter;
1486  }
1487 
1488  if (needToRename) {
1489  if (!wxRenameFile(fullPath,
1490  renamedFullPath))
1491  {
1492  // ACK!!! The renaming was unsuccessful!!!
1493  // (This shouldn't happen, since we tried creating a
1494  // file of this name and then deleted it just a
1495  // second earlier.) But we'll handle this scenario
1496  // just in case!!!
1497 
1498  // Print error message and cancel the export
1499  wxLogSysError(_("Unable to rename '%s' to '%s'."),
1500  fullPath,
1501  renamedFullPath);
1502 
1503  // Destruction of readLocks puts things back where they were
1504  return false;
1505  }
1506  else
1507  {
1508  //point the aliases to the NEW filename.
1509  BlockHash::iterator iter = mBlockFileHash.begin();
1510  while (iter != mBlockFileHash.end())
1511  {
1512  BlockFilePtr b = iter->second.lock();
1513  if (b) {
1514  auto ab = static_cast< AliasBlockFile * > ( &*b );
1515  auto db = static_cast< ODDecodeBlockFile * > ( &*b );
1516 
1517  if (b->IsAlias() && ab->GetAliasedFileName() == fName)
1518  {
1519  ab->ChangeAliasedFileName(wxFileNameWrapper{ renamedFileName });
1520  wxPrintf(_("Changed block %s to new alias name\n"),
1521  b->GetFileName().name.GetFullName());
1522 
1523  }
1524  else if (!b->IsDataAvailable() && db->GetEncodedAudioFilename() == fName) {
1525  db->ChangeAudioFile(wxFileNameWrapper{ renamedFileName });
1526  }
1527  }
1528  ++iter;
1529  }
1530 
1531  }
1532 
1533  aliasList.Remove(fullPath);
1534  aliasList.Add(renamedFullPath);
1535  }
1536 
1537  // Success!!! Either we successfully renamed the file,
1538  // or we didn't need to!
1539  return true;
1540 }
An AliasBlockFile that references uncompressed data in an existing file.
std::shared_ptr< BlockFile > BlockFilePtr
Definition: BlockFile.h:48
void ChangeAudioFile(wxFileNameWrapper &&newAudioFile)
BlockHash mBlockFileHash
Definition: DirManager.h:191
wxArrayString aliasList
Definition: DirManager.h:217
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
A BlockFile that refers to data in an existing file.
Definition: BlockFile.h:251
void DirManager::FillBlockfilesCache ( )

Definition at line 2062 of file DirManager.cpp.

References _(), GetFreeMemory(), gPrefs, mBlockFileHash, and ProgressDialog::Update().

2063 {
2064 #ifdef DEPRECATED_AUDIO_CACHE
2065  // See http://bugzilla.audacityteam.org/show_bug.cgi?id=545.
2066  bool cacheBlockFiles = false;
2067  gPrefs->Read(wxT("/Directories/CacheBlockFiles"), &cacheBlockFiles);
2068 
2069  if (!cacheBlockFiles)
2070  return; // user opted not to cache block files
2071 
2072  int lowMem = gPrefs->Read(wxT("/Directories/CacheLowMem"), 16l);
2073  if (lowMem < 16) {
2074  lowMem = 16;
2075  }
2076  lowMem <<= 20;
2077 
2078  BlockHash::iterator iter;
2079  int numNeed = 0;
2080 
2081  iter = mBlockFileHash.begin();
2082  while (iter != mBlockFileHash.end())
2083  {
2084  BlockFilePtr b = iter->second.lock();
2085  if (b) {
2086  if (b->GetNeedFillCache())
2087  numNeed++;
2088  }
2089  ++iter;
2090  }
2091 
2092  if (numNeed == 0)
2093  return;
2094 
2095  ProgressDialog progress(_("Caching audio"),
2096  _("Caching audio into memory"));
2097 
2098  iter = mBlockFileHash.begin();
2099  int current = 0;
2100  while (iter != mBlockFileHash.end())
2101  {
2102  BlockFilePtr b = iter->second.lock();
2103  if (b) {
2104  if (b->GetNeedFillCache() && (GetFreeMemory() > lowMem)) {
2105  b->FillCache();
2106  }
2107 
2108  if (!progress.Update(current, numNeed))
2109  break; // user cancelled progress dialog, stop caching
2110  current++;
2111  }
2112  ++iter;
2113  }
2114 #endif // DEPRECATED_AUDIO_CACHE
2115 }
AudacityPrefs * gPrefs
Definition: Prefs.cpp:73
ProgressDialog Class.
wxMemorySize GetFreeMemory()
Definition: DirManager.cpp:120
std::shared_ptr< BlockFile > BlockFilePtr
Definition: BlockFile.h:48
BlockHash mBlockFileHash
Definition: DirManager.h:191
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
void DirManager::FindMissingAliasedFiles ( BlockHash missingAliasedFileAUFHash,
BlockHash missingAliasedFilePathHash 
)

Definition at line 1906 of file DirManager.cpp.

References _(), and mBlockFileHash.

Referenced by ProjectFSCK().

1909 {
1910  BlockHash::iterator iter = mBlockFileHash.begin();
1911  while (iter != mBlockFileHash.end())
1912  {
1913  wxString key = iter->first; // file name and extension
1914  BlockFilePtr b = iter->second.lock();
1915  if (b) {
1916  if (b->IsAlias())
1917  {
1918  const wxFileName &aliasedFileName =
1919  static_cast< AliasBlockFile* > ( &*b )->GetAliasedFileName();
1920  wxString aliasedFileFullPath = aliasedFileName.GetFullPath();
1921  // wxEmptyString can happen if user already chose to "replace... with silence".
1922  if ((aliasedFileFullPath != wxEmptyString) &&
1923  !aliasedFileName.FileExists())
1924  {
1925  missingAliasedFileAUFHash[key] = b;
1926  if (missingAliasedFilePathHash.find(aliasedFileFullPath) ==
1927  missingAliasedFilePathHash.end()) // Add it only once.
1928  // Not actually using the block here, just the path,
1929  // so set the block to NULL to create the entry.
1930  missingAliasedFilePathHash[aliasedFileFullPath] = {};
1931  }
1932  }
1933  }
1934  ++iter;
1935  }
1936 
1937  iter = missingAliasedFilePathHash.begin();
1938  while (iter != missingAliasedFilePathHash.end())
1939  {
1940  wxLogWarning(_("Missing aliased audio file: '%s'"), iter->first);
1941  ++iter;
1942  }
1943 }
std::shared_ptr< BlockFile > BlockFilePtr
Definition: BlockFile.h:48
BlockHash mBlockFileHash
Definition: DirManager.h:191
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
A BlockFile that refers to data in an existing file.
Definition: BlockFile.h:251
void DirManager::FindMissingAUFs ( BlockHash missingAUFHash)

Definition at line 1945 of file DirManager.cpp.

References _(), MakeBlockFilePath(), and mBlockFileHash.

Referenced by ProjectFSCK().

1947 {
1948  BlockHash::iterator iter = mBlockFileHash.begin();
1949  while (iter != mBlockFileHash.end())
1950  {
1951  const wxString &key = iter->first;
1952  BlockFilePtr b = iter->second.lock();
1953  if (b) {
1954  if (b->IsAlias() && b->IsSummaryAvailable())
1955  {
1956  /* don't look in hash; that might find files the user moved
1957  that the Blockfile abstraction can't find itself */
1958  wxFileNameWrapper fileName{ MakeBlockFilePath(key) };
1959  fileName.SetName(key);
1960  fileName.SetExt(wxT("auf"));
1961  if (!fileName.FileExists())
1962  {
1963  missingAUFHash[key] = b;
1964  wxLogWarning(_("Missing alias (.auf) block file: '%s'"),
1965  fileName.GetFullPath());
1966  }
1967  }
1968  }
1969  ++iter;
1970  }
1971 }
std::shared_ptr< BlockFile > BlockFilePtr
Definition: BlockFile.h:48
wxFileNameWrapper MakeBlockFilePath(const wxString &value)
Definition: DirManager.cpp:720
BlockHash mBlockFileHash
Definition: DirManager.h:191
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
void DirManager::FindMissingAUs ( BlockHash missingAUHash)

Definition at line 1973 of file DirManager.cpp.

References _(), MakeBlockFilePath(), and mBlockFileHash.

Referenced by ProjectFSCK().

1975 {
1976  BlockHash::iterator iter = mBlockFileHash.begin();
1977  while (iter != mBlockFileHash.end())
1978  {
1979  const wxString &key = iter->first;
1980  BlockFilePtr b = iter->second.lock();
1981  if (b) {
1982  if (!b->IsAlias())
1983  {
1984  wxFileNameWrapper fileName{ MakeBlockFilePath(key) };
1985  fileName.SetName(key);
1986  fileName.SetExt(wxT("au"));
1987  const auto path = fileName.GetFullPath();
1988  if (!fileName.FileExists() ||
1989  wxFile{ path }.Length() == 0)
1990  {
1991  missingAUHash[key] = b;
1992  wxLogWarning(_("Missing data block file: '%s'"), path);
1993  }
1994  }
1995  }
1996  ++iter;
1997  }
1998 }
std::shared_ptr< BlockFile > BlockFilePtr
Definition: BlockFile.h:48
wxFileNameWrapper MakeBlockFilePath(const wxString &value)
Definition: DirManager.cpp:720
BlockHash mBlockFileHash
Definition: DirManager.h:191
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
void DirManager::FindOrphanBlockFiles ( const wxArrayString &  filePathArray,
wxArrayString &  orphanFilePathArray 
)

Definition at line 2001 of file DirManager.cpp.

References _(), ContainsBlockFile(), TrackListIterator::First(), AudacityProject::GetClipboardTracks(), Track::GetDirManager(), and mBlockFileHash.

Referenced by ProjectFSCK(), and RemoveOrphanBlockfiles().

2004 {
2005  DirManager *clipboardDM = NULL;
2006 
2007  for (size_t i = 0; i < filePathArray.GetCount(); i++)
2008  {
2009  const wxFileName &fullname = filePathArray[i];
2010  wxString basename = fullname.GetName();
2011  const wxString ext{fullname.GetExt()};
2012  if ((mBlockFileHash.find(basename) == mBlockFileHash.end()) && // is orphan
2013  // Consider only Audacity data files.
2014  // Specifically, ignore <branding> JPG and <import> OGG ("Save Compressed Copy").
2015  (ext.IsSameAs(wxT("au")) ||
2016  ext.IsSameAs(wxT("auf"))))
2017  {
2018  if (!clipboardDM) {
2020 
2021  if (clipTracks) {
2022  TrackListIterator clipIter(clipTracks);
2023  Track *track = clipIter.First();
2024  if (track)
2025  clipboardDM = track->GetDirManager().get();
2026  }
2027  }
2028 
2029  // Ignore it if it exists in the clipboard (from a previously closed project)
2030  if (!(clipboardDM && clipboardDM->ContainsBlockFile(basename)))
2031  orphanFilePathArray.Add(fullname.GetFullPath());
2032  }
2033  }
2034  for (size_t i = 0; i < orphanFilePathArray.GetCount(); i++)
2035  wxLogWarning(_("Orphan block file: '%s'"), orphanFilePathArray[i]);
2036 }
A list of TrackListNode items.
Definition: Track.h:618
Creates and manages BlockFile objects.
Definition: DirManager.h:52
const std::shared_ptr< DirManager > & GetDirManager() const
Definition: Track.h:299
Fundamental data object of Audacity, placed in the TrackPanel. Classes derived form it include the Wa...
Definition: Track.h:101
BlockHash mBlockFileHash
Definition: DirManager.h:191
static TrackList * GetClipboardTracks()
Definition: Project.cpp:4882
An iterator for a TrackList.
Definition: Track.h:401
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
bool ContainsBlockFile(const BlockFile *b) const
Returns true if the blockfile pointed to by b is contained by the DirManager.
auto DirManager::GetBalanceInfo ( )
private

Definition at line 862 of file DirManager.cpp.

References BlockFile::gBlockFileDestructionCount, and name.

Referenced by BalanceFileAdd(), BalanceMidAdd(), and MakeBlockFileName().

863 {
864  // Before returning the map,
865  // see whether any block files have disappeared,
866  // and if so update
867 
869  if ( mLastBlockFileDestructionCount != count ) {
870  auto it = mBlockFileHash.begin(), end = mBlockFileHash.end();
871  while (it != end)
872  {
873  BlockFilePtr ptr { it->second.lock() };
874  if (!ptr) {
875  auto name = it->first;
876  mBlockFileHash.erase( it++ );
877  BalanceInfoDel( name );
878  }
879  else
880  ++it;
881  }
882  }
883 
885 
886  return mBalanceInfo;
887 }
static unsigned long gBlockFileDestructionCount
Definition: BlockFile.h:65
std::shared_ptr< BlockFile > BlockFilePtr
Definition: BlockFile.h:48
void BalanceInfoDel(const wxString &)
Definition: DirManager.cpp:892
struct DirManager::BalanceInfo mBalanceInfo
BlockHash mBlockFileHash
Definition: DirManager.h:191
const wxChar * name
Definition: Distortion.cpp:94
unsigned long mLastBlockFileDestructionCount
Definition: DirManager.h:226
wxString DirManager::GetDataFilesDir ( ) const

Definition at line 710 of file DirManager.cpp.

References mytemp, and projFull.

Referenced by MakeBlockFilePath().

711 {
712  return projFull != wxT("")? projFull: mytemp;
713 }
wxString projFull
Definition: DirManager.h:213
wxString mytemp
Definition: DirManager.h:229
wxLongLong DirManager::GetFreeDiskSpace ( )

Definition at line 689 of file DirManager.cpp.

References mytemp, and projPath.

690 {
691  wxLongLong freeSpace = -1;
692  wxFileName path;
693 
694  path.SetPath(projPath.IsEmpty() ? mytemp : projPath);
695 
696  // Use the parent directory if the project directory hasn't yet been created
697  if (!path.DirExists())
698  {
699  path.RemoveLastDir();
700  }
701 
702  if (!wxGetDiskSpace(path.GetFullPath(), NULL, &freeSpace))
703  {
704  freeSpace = -1;
705  }
706 
707  return freeSpace;
708 }
wxString projPath
Definition: DirManager.h:212
wxString mytemp
Definition: DirManager.h:229
wxString DirManager::GetProjectDataDir ( )
wxString DirManager::GetProjectName ( )

Definition at line 684 of file DirManager.cpp.

References projName.

685 {
686  return projName;
687 }
wxString projName
Definition: DirManager.h:211
XMLTagHandler* DirManager::HandleXMLChild ( const wxChar *  WXUNUSEDtag)
inlineoverride

Definition at line 126 of file DirManager.h.

127  { return NULL; }
bool DirManager::HandleXMLTag ( const wxChar *  tag,
const wxChar **  attrs 
)
overridevirtual

Implements XMLTagHandler.

Definition at line 1230 of file DirManager.cpp.

References BalanceInfoAdd(), LegacyAliasBlockFile::BuildFromXML(), PCMAliasBlockFile::BuildFromXML(), SilentBlockFile::BuildFromXML(), LegacyBlockFile::BuildFromXML(), SimpleBlockFile::BuildFromXML(), ODPCMAliasBlockFile::BuildFromXML(), ODDecodeBlockFile::BuildFromXML(), ODManager::MarkLoadedODFlag(), mBlockFileHash, mLoadingBlockLen, mLoadingFormat, mLoadingTarget, mLoadingTargetIdx, mMaxSamples, name, and projFull.

1231 {
1232  if( mLoadingTarget == NULL )
1233  return false;
1234 
1235  BlockFilePtr pBlockFile {};
1236 
1238 
1239  if (!wxStricmp(tag, wxT("silentblockfile"))) {
1240  // Silent blocks don't actually have a file associated, so
1241  // we don't need to worry about the hash table at all
1242  target = SilentBlockFile::BuildFromXML(*this, attrs);
1243  return true;
1244  }
1245  else if ( !wxStricmp(tag, wxT("simpleblockfile")) )
1246  pBlockFile = SimpleBlockFile::BuildFromXML(*this, attrs);
1247  else if( !wxStricmp(tag, wxT("pcmaliasblockfile")) )
1248  pBlockFile = PCMAliasBlockFile::BuildFromXML(*this, attrs);
1249  else if( !wxStricmp(tag, wxT("odpcmaliasblockfile")) )
1250  {
1251  pBlockFile = ODPCMAliasBlockFile::BuildFromXML(*this, attrs);
1252  //in the case of loading an OD file, we need to schedule the ODManager to begin OD computing of summary
1253  //However, because we don't have access to the track or even the Sequence from this call, we mark a flag
1254  //in the ODMan and check it later.
1256  }
1257  else if( !wxStricmp(tag, wxT("oddecodeblockfile")) )
1258  {
1259  pBlockFile = ODDecodeBlockFile::BuildFromXML(*this, attrs);
1261  }
1262  else if( !wxStricmp(tag, wxT("blockfile")) ||
1263  !wxStricmp(tag, wxT("legacyblockfile")) ) {
1264  // Support Audacity version 1.1.1 project files
1265 
1266  int i=0;
1267  bool alias = false;
1268 
1269  while(attrs[i]) {
1270  if (!wxStricmp(attrs[i], wxT("alias"))) {
1271  if (wxAtoi(attrs[i+1])==1)
1272  alias = true;
1273  }
1274  i++;
1275  if (attrs[i])
1276  i++;
1277  }
1278 
1279  if (alias)
1280  pBlockFile = LegacyAliasBlockFile::BuildFromXML(projFull, attrs);
1281  else
1282  pBlockFile = LegacyBlockFile::BuildFromXML(projFull, attrs,
1284  mLoadingFormat);
1285  }
1286  else
1287  return false;
1288 
1289  if (!pBlockFile)
1290  // BuildFromXML failed, or we didn't find a valid blockfile tag.
1291  return false;
1292 
1293  // Check the length here so we don't have to do it in each BuildFromXML method.
1294  if ((mMaxSamples != ~size_t(0)) && // is initialized
1295  (pBlockFile->GetLength() > mMaxSamples))
1296  {
1297  // See http://bugzilla.audacityteam.org/show_bug.cgi?id=451#c13.
1298  // Lock pBlockFile so that the ~BlockFile() will not DELETE the file on disk.
1299  pBlockFile->Lock();
1300  return false;
1301  }
1302  else
1303  target = pBlockFile;
1304 
1305  //
1306  // If the block we loaded is already in the hash table, then the
1307  // object we just loaded is a duplicate, so we DELETE it and
1308  // return a reference to the existing object instead.
1309  //
1310 
1311  wxString name = target->GetFileName().name.GetName();
1312  auto &wRetrieved = mBlockFileHash[name];
1313  BlockFilePtr retrieved = wRetrieved.lock();
1314  if (retrieved) {
1315  // Lock it in order to DELETE it safely, i.e. without having
1316  // it DELETE the file, too...
1317  target->Lock();
1318 
1319  target = retrieved;
1320  return true;
1321  }
1322 
1323  // This is a NEW object
1324  wRetrieved = target;
1325  // MakeBlockFileName wasn't used so we must add the directory
1326  // balancing information
1327  BalanceInfoAdd(name);
1328 
1329  return true;
1330 }
static BlockFilePtr BuildFromXML(DirManager &dm, const wxChar **attrs)
void BalanceInfoAdd(const wxString &)
Definition: DirManager.cpp:845
size_t mMaxSamples
Definition: DirManager.h:224
size_t mLoadingBlockLen
Definition: DirManager.h:222
unsigned mLoadingTargetIdx
Definition: DirManager.h:220
static BlockFilePtr BuildFromXML(const wxString &dir, const wxChar **attrs, size_t len, sampleFormat format)
static
static BlockFilePtr BuildFromXML(DirManager &dm, const wxChar **attrs)
Reconstructs from XML a ODPCMAliasBlockFile and reschedules it for OD loading.
std::shared_ptr< BlockFile > BlockFilePtr
Definition: BlockFile.h:48
BlockArray * mLoadingTarget
Definition: DirManager.h:219
sampleFormat mLoadingFormat
Definition: DirManager.h:221
static void MarkLoadedODFlag()
sets a flag that is set if we have loaded some OD blockfiles from PCM.
Definition: ODManager.cpp:508
BlockHash mBlockFileHash
Definition: DirManager.h:191
wxString projFull
Definition: DirManager.h:213
static BlockFilePtr BuildFromXML(DirManager &dm, const wxChar **attrs)
Reconstructs from XML a ODDecodeBlockFile and reschedules it for OD loading.
static BlockFilePtr BuildFromXML(DirManager &dm, const wxChar **attrs)
static
static BlockFilePtr BuildFromXML(DirManager &dm, const wxChar **attrs)
static
const wxChar * name
Definition: Distortion.cpp:94
static BlockFilePtr BuildFromXML(const wxString &projDir, const wxChar **attrs)
BlockFile* DirManager::LoadBlockFile ( const wxChar **  attrs,
sampleFormat  format 
)
wxFileNameWrapper DirManager::MakeBlockFileName ( )
private

Definition at line 961 of file DirManager.cpp.

References AssignFile(), BalanceFileAdd(), BalanceMidAdd(), ContainsBlockFile(), and GetBalanceInfo().

Referenced by NewAliasBlockFile(), NewODAliasBlockFile(), NewODDecodeBlockFile(), and NewSimpleBlockFile().

962 {
963  auto &balanceInfo = GetBalanceInfo();
964  auto &dirMidPool = balanceInfo.dirMidPool;
965  auto &dirTopPool = balanceInfo.dirTopPool;
966  auto &dirTopFull = balanceInfo.dirTopFull;
967 
968  wxFileNameWrapper ret;
969  wxString baseFileName;
970 
971  unsigned int filenum,midnum,topnum,midkey;
972 
973  while(1){
974 
975  /* blockfiles are divided up into heirarchical directories.
976  Each toplevel directory is represented by "e" + two unique
977  hexadecimal digits, for a total possible number of 256
978  toplevels. Each toplevel contains up to 256 subdirs named
979  "d" + two hex digits. Each subdir contains 'a number' of
980  files. */
981 
982  filenum=0;
983  midnum=0;
984  topnum=0;
985 
986  // first action: if there is no available two-level directory in
987  // the available pool, try to make one
988 
989  if(dirMidPool.empty()){
990 
991  // is there a toplevel directory with space for a NEW subdir?
992 
993  if(!dirTopPool.empty()){
994 
995  // there's still a toplevel with room for a subdir
996 
997  DirHash::iterator iter = dirTopPool.begin();
998  int newcount = 0;
999  topnum = iter->first;
1000 
1001 
1002  // search for unused midlevels; linear search adequate
1003  // add 32 NEW topnum/midnum dirs full of prospective filenames to midpool
1004  for(midnum=0;midnum<256;midnum++){
1005  midkey=(topnum<<8)+midnum;
1006  if(BalanceMidAdd(topnum,midkey)){
1007  newcount++;
1008  if(newcount>=32)break;
1009  }
1010  }
1011 
1012  if(dirMidPool.empty()){
1013  // all the midlevels in this toplevel are in use yet the
1014  // toplevel claims some are free; this implies multiple
1015  // internal logic faults, but simply giving up and going
1016  // into an infinite loop isn't acceptible. Just in case,
1017  // for some reason, we get here, dynamite this toplevel so
1018  // we don't just fail.
1019 
1020  // this is 'wrong', but the best we can do given that
1021  // something else is also wrong. It will contain the
1022  // problem so we can keep going without worry.
1023  dirTopPool.erase(topnum);
1024  dirTopFull[topnum]=256;
1025  }
1026  continue;
1027  }
1028  }
1029 
1030  if(dirMidPool.empty()){
1031  // still empty, thus an absurdly large project; all dirs are
1032  // full to 256/256/256; keep working, but fall back to 'big
1033  // filenames' and randomized placement
1034 
1035  filenum = rand();
1036  midnum = (int)(256.*rand()/(RAND_MAX+1.));
1037  topnum = (int)(256.*rand()/(RAND_MAX+1.));
1038  midkey=(topnum<<8)+midnum;
1039 
1040 
1041  }else{
1042 
1043  DirHash::iterator iter = dirMidPool.begin();
1044  midkey = iter->first;
1045 
1046  // split the retrieved 16 bit directory key into two 8 bit numbers
1047  topnum = midkey >> 8;
1048  midnum = midkey & 0xff;
1049  filenum = (int)(4096.*rand()/(RAND_MAX+1.));
1050 
1051  }
1052 
1053  baseFileName.Printf(wxT("e%02x%02x%03x"),topnum,midnum,filenum);
1054 
1055  if (!ContainsBlockFile(baseFileName)) {
1056  // not in the hash, good.
1057  if (!this->AssignFile(ret, baseFileName, true))
1058  {
1059  // this indicates an on-disk collision, likely due to an
1060  // orphan blockfile. We should try again, but first
1061  // alert the balancing info there's a phantom file here;
1062  // if the directory is nearly full of orphans we neither
1063  // want performance to suffer nor potentially get into an
1064  // infinite loop if all possible filenames are taken by
1065  // orphans (unlikely but possible)
1066  BalanceFileAdd(midkey);
1067 
1068  }else break;
1069  }
1070  }
1071  // FIXME: Might we get here without midkey having been set?
1072  // Seemed like a possible problem in these changes in .aup directory hierarchy.
1073  BalanceFileAdd(midkey);
1074  return ret;
1075 }
void BalanceFileAdd(int)
Definition: DirManager.cpp:824
int BalanceMidAdd(int, int)
Definition: DirManager.cpp:798
bool ContainsBlockFile(const BlockFile *b) const
Returns true if the blockfile pointed to by b is contained by the DirManager.
BalanceInfo & GetBalanceInfo()
Definition: DirManager.cpp:862
bool AssignFile(wxFileNameWrapper &filename, const wxString &value, bool check)
Definition: DirManager.cpp:752
wxFileNameWrapper DirManager::MakeBlockFilePath ( const wxString &  value)
private

Definition at line 720 of file DirManager.cpp.

References _(), and GetDataFilesDir().

Referenced by AssignFile(), FindMissingAUFs(), and FindMissingAUs().

720  {
721 
722  wxFileNameWrapper dir;
723  dir.AssignDir(GetDataFilesDir());
724 
725  if(value.GetChar(0)==wxT('d')){
726  // this file is located in a subdirectory tree
727  int location=value.Find(wxT('b'));
728  wxString subdir=value.Mid(0,location);
729  dir.AppendDir(subdir);
730 
731  if(!dir.DirExists())
732  dir.Mkdir();
733  }
734 
735  if(value.GetChar(0)==wxT('e')){
736  // this file is located in a NEW style two-deep subdirectory tree
737  wxString topdir=value.Mid(0,3);
738  wxString middir=wxT("d");
739  middir.Append(value.Mid(3,2));
740 
741  dir.AppendDir(topdir);
742  dir.AppendDir(middir);
743 
744  if(!dir.DirExists() && !dir.Mkdir(0777,wxPATH_MKDIR_FULL))
745  { // need braces to avoid compiler warning about ambiguous else, see the macro
746  wxLogSysError(_("mkdir in DirManager::MakeBlockFilePath failed."));
747  }
748  }
749  return dir;
750 }
wxString GetDataFilesDir() const
Definition: DirManager.cpp:710
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
BlockFilePtr DirManager::NewAliasBlockFile ( const wxString &  aliasedFile,
sampleCount  aliasStart,
size_t  aliasLen,
int  aliasChannel 
)

Definition at line 1093 of file DirManager.cpp.

References aliasList, MakeBlockFileName(), and mBlockFileHash.

1096 {
1097  wxFileNameWrapper filePath{ MakeBlockFileName() };
1098  const wxString fileName = filePath.GetName();
1099 
1100  auto newBlockFile = make_blockfile<PCMAliasBlockFile>
1101  (std::move(filePath), wxFileNameWrapper{aliasedFile},
1102  aliasStart, aliasLen, aliasChannel);
1103 
1104  mBlockFileHash[fileName]=newBlockFile;
1105  aliasList.Add(aliasedFile);
1106 
1107  return newBlockFile;
1108 }
BlockHash mBlockFileHash
Definition: DirManager.h:191
wxArrayString aliasList
Definition: DirManager.h:217
wxFileNameWrapper MakeBlockFileName()
Definition: DirManager.cpp:961
BlockFilePtr DirManager::NewODAliasBlockFile ( const wxString &  aliasedFile,
sampleCount  aliasStart,
size_t  aliasLen,
int  aliasChannel 
)

Definition at line 1110 of file DirManager.cpp.

References aliasList, MakeBlockFileName(), and mBlockFileHash.

1113 {
1114  wxFileNameWrapper filePath{ MakeBlockFileName() };
1115  const wxString fileName{ filePath.GetName() };
1116 
1117  auto newBlockFile = make_blockfile<ODPCMAliasBlockFile>
1118  (std::move(filePath), wxFileNameWrapper{aliasedFile},
1119  aliasStart, aliasLen, aliasChannel);
1120 
1121  mBlockFileHash[fileName]=newBlockFile;
1122  aliasList.Add(aliasedFile);
1123 
1124  return newBlockFile;
1125 }
BlockHash mBlockFileHash
Definition: DirManager.h:191
wxArrayString aliasList
Definition: DirManager.h:217
wxFileNameWrapper MakeBlockFileName()
Definition: DirManager.cpp:961
BlockFilePtr DirManager::NewODDecodeBlockFile ( const wxString &  aliasedFile,
sampleCount  aliasStart,
size_t  aliasLen,
int  aliasChannel,
int  decodeType 
)

Definition at line 1127 of file DirManager.cpp.

References aliasList, MakeBlockFileName(), and mBlockFileHash.

1130 {
1131  wxFileNameWrapper filePath{ MakeBlockFileName() };
1132  const wxString fileName{ filePath.GetName() };
1133 
1134  auto newBlockFile = make_blockfile<ODDecodeBlockFile>
1135  (std::move(filePath), wxFileNameWrapper{ aliasedFile },
1136  aliasStart, aliasLen, aliasChannel, decodeType);
1137 
1138  mBlockFileHash[fileName]=newBlockFile;
1139  aliasList.Add(aliasedFile); //OD TODO: check to see if we need to remove this when done decoding.
1140  //I don't immediately see a place where aliased files remove when a file is closed.
1141 
1142  return newBlockFile;
1143 }
BlockHash mBlockFileHash
Definition: DirManager.h:191
wxArrayString aliasList
Definition: DirManager.h:217
wxFileNameWrapper MakeBlockFileName()
Definition: DirManager.cpp:961
BlockFilePtr DirManager::NewSimpleBlockFile ( samplePtr  sampleData,
size_t  sampleLen,
sampleFormat  format,
bool  allowDeferredWrite = false 
)

Definition at line 1077 of file DirManager.cpp.

References format, MakeBlockFileName(), and mBlockFileHash.

Referenced by Sequence::Append(), Sequence::Blockify(), Sequence::Delete(), and Sequence::SetSamples().

1081 {
1082  wxFileNameWrapper filePath{ MakeBlockFileName() };
1083  const wxString fileName{ filePath.GetName() };
1084 
1085  auto newBlockFile = make_blockfile<SimpleBlockFile>
1086  (std::move(filePath), sampleData, sampleLen, format, allowDeferredWrite);
1087 
1088  mBlockFileHash[fileName] = newBlockFile;
1089 
1090  return newBlockFile;
1091 }
int format
Definition: ExportPCM.cpp:56
BlockHash mBlockFileHash
Definition: DirManager.h:191
wxFileNameWrapper MakeBlockFileName()
Definition: DirManager.cpp:961
int DirManager::ProjectFSCK ( const bool  bForceError,
const bool  bAutoRecoverMode 
)

Definition at line 1549 of file DirManager.cpp.

References _(), AudacityMessageBox(), FindMissingAliasedFiles(), FindMissingAUFs(), FindMissingAUs(), FindOrphanBlockFiles(), FSCKstatus_CHANGED, FSCKstatus_CLOSE_REQ, FSCKstatus_SAVE_AUP, GuardedCall(), ODManager::HasLoadedODFlag(), mBlockFileHash, mytemp, projFull, projName, RecursivelyCountSubdirs(), RecursivelyEnumerateWithProgress(), RecursivelyRemoveEmptyDirs(), AudacityApp::SetMissingAliasedFileWarningShouldShow(), ShowMultiDialog(), and wxGetApp().

1550 {
1551  // In earlier versions of this method, enumerations of errors were
1552  // all done in sequence, then the user was prompted for each type of error.
1553  // The enumerations are now interleaved with prompting, because, for example,
1554  // user choosing to replace missing aliased block files with silence
1555  // needs to put in SilentBlockFiles and DELETE the corresponding auf files,
1556  // so those would then not be cumulated in missingAUFHash.
1557  // We still do the FindX methods outside the conditionals,
1558  // so the log always shows all found errors.
1559 
1560  int action; // choice of action for each type of error
1561  int nResult = 0;
1562 
1563  if (bForceError && !bAutoRecoverMode)
1564  {
1565  // TODO: Replace with more user friendly error message?
1566  /* i18n-hint: The audacity project file is XML and has 'tags' in it,
1567  rather like html tags <something>some stuff</something>.
1568  This error message is about the tags that hold the sequence information.
1569  The error message is confusing to users in English, and could just say
1570  "Found problems with <sequence> when checking project file." */
1571  wxString msg = _("Project check read faulty Sequence tags.");
1572  const wxChar *buttons[] =
1573  {_("Close project immediately with no changes"),
1574  _("Continue with repairs noted in log, and check for more errors. This will save the project in its current state, unless you \"Close project immediately\" on further error alerts."),
1575  NULL};
1576  wxLog::FlushActive(); // MultiDialog has "Show Log..." button, so make sure log is current.
1577  action = ShowMultiDialog(msg, _("Warning - Problems Reading Sequence Tags"), buttons);
1578  if (action == 0)
1579  nResult = FSCKstatus_CLOSE_REQ;
1580  else
1582  }
1583 
1584  wxArrayString filePathArray; // *all* files in the project directory/subdirectories
1585  wxString dirPath = (projFull != wxT("") ? projFull : mytemp);
1587  dirPath,
1588  filePathArray, // output: all files in project directory tree
1589  wxEmptyString, // All dirs
1590  wxEmptyString, // All files
1591  true, false,
1592  mBlockFileHash.size(), // rough guess of how many BlockFiles will be found/processed, for progress
1593  _("Inspecting project file data"));
1594 
1595  //
1596  // MISSING ALIASED AUDIO FILES
1597  //
1599  BlockHash missingAliasedFileAUFHash; // (.auf) AliasBlockFiles whose aliased files are missing
1600  BlockHash missingAliasedFilePathHash; // full paths of missing aliased files
1601  this->FindMissingAliasedFiles(missingAliasedFileAUFHash, missingAliasedFilePathHash);
1602 
1603  if ((nResult != FSCKstatus_CLOSE_REQ) && !missingAliasedFileAUFHash.empty())
1604  {
1605  // In auto-recover mode, we always create silent blocks, and do not ask user.
1606  // This makes sure the project is complete next time we open it.
1607  if (bAutoRecoverMode)
1608  action = 2;
1609  else
1610  {
1611  wxString msgA =
1612 _("Project check of \"%s\" folder \
1613 \ndetected %lld missing external audio file(s) \
1614 \n('aliased files'). There is no way for Audacity \
1615 \nto recover these files automatically. \
1616 \n\nIf you choose the first or second option below, \
1617 \nyou can try to find and restore the missing files \
1618 \nto their previous location. \
1619 \n\nNote that for the second option, the waveform \
1620 \nmay not show silence. \
1621 \n\nIf you choose the third option, this will save the \
1622 \nproject in its current state, unless you \"Close \
1623 \nproject immediately\" on further error alerts.");
1624  wxString msg;
1625  msg.Printf(msgA, this->projName, (long long) missingAliasedFilePathHash.size());
1626  const wxChar *buttons[] =
1627  {_("Close project immediately with no changes"),
1628  _("Treat missing audio as silence (this session only)"),
1629  _("Replace missing audio with silence (permanent immediately)."),
1630  NULL};
1631  wxLog::FlushActive(); // MultiDialog has "Show Log..." button, so make sure log is current.
1632  action = ShowMultiDialog(msg, _("Warning - Missing Aliased File(s)"), buttons);
1633  }
1634 
1635  if (action == 0)
1636  nResult = FSCKstatus_CLOSE_REQ;
1637  else
1638  {
1639  // LL: A progress dialog should probably be used here
1640  BlockHash::iterator iter = missingAliasedFileAUFHash.begin();
1641  while (iter != missingAliasedFileAUFHash.end())
1642  {
1643  // This type cast is safe. We checked that it's an alias block file earlier.
1644  BlockFilePtr b = iter->second.lock();
1645  wxASSERT(b);
1646  if (b) {
1647  auto ab = static_cast< AliasBlockFile * > ( &*b );
1648 
1649  if (action == 2)
1650  {
1651  // silence the blockfiles by yanking the filename
1652  // This is done, eventually, in PCMAliasBlockFile::ReadData()
1653  // and ODPCMAliasBlockFile::ReadData, in the stack of b->Recover().
1654  // There, if the mAliasedFileName is bad, it zeroes the data.
1655  wxFileNameWrapper dummy;
1656  dummy.Clear();
1657  ab->ChangeAliasedFileName(std::move(dummy));
1658 
1659  // If recovery fails for one file, silence it,
1660  // and don't try to recover other files but
1661  // silence them too. GuardedCall will cause an appropriate
1662  // error message for the user.
1663  GuardedCall(
1664  [&] { ab->Recover(); },
1665  [&] (AudacityException*) { action = 1; }
1666  );
1667 
1669  }
1670 
1671  if (action == 1)
1672  // Silence error logging for this block in this session.
1673  ab->SilenceAliasLog();
1674  }
1675  ++iter;
1676  }
1677  if ((action == 2) && bAutoRecoverMode)
1678  wxLogWarning(_(" Project check replaced missing aliased file(s) with silence."));
1679  }
1680  }
1681 
1682  //
1683  // MISSING ALIAS (.AUF) AliasBlockFiles
1684  //
1685  // Alias summary regeneration must happen after checking missing aliased files.
1686  //
1687  BlockHash missingAUFHash; // missing (.auf) AliasBlockFiles
1688  this->FindMissingAUFs(missingAUFHash);
1689  if ((nResult != FSCKstatus_CLOSE_REQ) && !missingAUFHash.empty())
1690  {
1691  // In auto-recover mode, we just recreate the alias files, and do not ask user.
1692  // This makes sure the project is complete next time we open it.
1693  if (bAutoRecoverMode)
1694  action = 0;
1695  else
1696  {
1697  wxString msgA =
1698 _("Project check of \"%s\" folder \
1699 \ndetected %lld missing alias (.auf) blockfile(s). \
1700 \nAudacity can fully regenerate these files \
1701 \nfrom the current audio in the project.");
1702  wxString msg;
1703  msg.Printf(msgA, this->projName, (long long) missingAUFHash.size());
1704  const wxChar *buttons[] = {_("Regenerate alias summary files (safe and recommended)"),
1705  _("Fill in silence for missing display data (this session only)"),
1706  _("Close project immediately with no further changes"),
1707  NULL};
1708  wxLog::FlushActive(); // MultiDialog has "Show Log..." button, so make sure log is current.
1709  action = ShowMultiDialog(msg, _("Warning - Missing Alias Summary File(s)"), buttons);
1710  }
1711 
1712  if (action == 2)
1713  nResult = FSCKstatus_CLOSE_REQ;
1714  else
1715  {
1716  // LL: A progress dialog should probably be used here
1717  BlockHash::iterator iter = missingAUFHash.begin();
1718  while (iter != missingAUFHash.end())
1719  {
1720  BlockFilePtr b = iter->second.lock();
1721  wxASSERT(b);
1722  if (b) {
1723  if(action==0) {
1724  //regenerate from data
1725  // If recovery fails for one file, silence it,
1726  // and don't try to recover other files but
1727  // silence them too. GuardedCall will cause an appropriate
1728  // error message for the user.
1729  GuardedCall(
1730  [&] {
1731  b->Recover();
1732  nResult |= FSCKstatus_CHANGED;
1733  },
1734  [&] (AudacityException*) { action = 1; }
1735  );
1736  }
1737 
1738  if (action==1){
1739  // Silence error logging for this block in this session.
1740  b->SilenceLog();
1741  }
1742  }
1743  ++iter;
1744  }
1745  if ((action == 0) && bAutoRecoverMode)
1746  wxLogWarning(_(" Project check regenerated missing alias summary file(s)."));
1747  }
1748  }
1749 
1750  //
1751  // MISSING (.AU) SimpleBlockFiles
1752  //
1753  BlockHash missingAUHash; // missing data (.au) blockfiles
1754  this->FindMissingAUs(missingAUHash);
1755  if ((nResult != FSCKstatus_CLOSE_REQ) && !missingAUHash.empty())
1756  {
1757  // In auto-recover mode, we just always create silent blocks.
1758  // This makes sure the project is complete next time we open it.
1759  if (bAutoRecoverMode)
1760  action = 2;
1761  else
1762  {
1763  wxString msgA =
1764 _("Project check of \"%s\" folder \
1765 \ndetected %lld missing audio data (.au) blockfile(s), \
1766 \nprobably due to a bug, system crash, or accidental \
1767 \ndeletion. There is no way for Audacity to recover \
1768 \nthese missing files automatically. \
1769 \n\nIf you choose the first or second option below, \
1770 \nyou can try to find and restore the missing files \
1771 \nto their previous location. \
1772 \n\nNote that for the second option, the waveform \
1773 \nmay not show silence.");
1774  wxString msg;
1775  msg.Printf(msgA, this->projName, (long long) missingAUHash.size());
1776  const wxChar *buttons[] =
1777  {_("Close project immediately with no further changes"),
1778  _("Treat missing audio as silence (this session only)"),
1779  _("Replace missing audio with silence (permanent immediately)"),
1780  NULL};
1781  wxLog::FlushActive(); // MultiDialog has "Show Log..." button, so make sure log is current.
1782  action = ShowMultiDialog(msg, _("Warning - Missing Audio Data Block File(s)"), buttons);
1783  }
1784 
1785  if (action == 0)
1786  nResult = FSCKstatus_CLOSE_REQ;
1787  else
1788  {
1789  // LL: A progress dialog should probably be used here
1790  BlockHash::iterator iter = missingAUHash.begin();
1791  while (iter != missingAUHash.end())
1792  {
1793  BlockFilePtr b = iter->second.lock();
1794  wxASSERT(b);
1795  if (b) {
1796  if (action == 2)
1797  {
1798  //regenerate from data
1799  // If recovery fails for one file, silence it,
1800  // and don't try to recover other files but
1801  // silence them too. GuardedCall will cause an appropriate
1802  // error message for the user.
1803  GuardedCall(
1804  [&] {
1805  //regenerate with zeroes
1806  b->Recover();
1807  nResult |= FSCKstatus_CHANGED;
1808  },
1809  [&] (AudacityException*) { action = 1; }
1810  );
1811  }
1812 
1813  if (action == 1)
1814  b->SilenceLog();
1815  }
1816  ++iter;
1817  }
1818  if ((action == 2) && bAutoRecoverMode)
1819  wxLogWarning(_(" Project check replaced missing audio data block file(s) with silence."));
1820  }
1821  }
1822 
1823  //
1824  // ORPHAN BLOCKFILES (.au and .auf files that are not in the project.)
1825  //
1826  wxArrayString orphanFilePathArray; // orphan .au and .auf files
1827  this->FindOrphanBlockFiles(filePathArray, orphanFilePathArray);
1828 
1829  if ((nResult != FSCKstatus_CLOSE_REQ) && !orphanFilePathArray.IsEmpty())
1830  {
1831  // In auto-recover mode, leave orphan blockfiles alone.
1832  // They will be deleted when project is saved the first time.
1833  if (bAutoRecoverMode)
1834  {
1835  wxLogWarning(_(" Project check ignored orphan block file(s). They will be deleted when project is saved."));
1836  action = 1;
1837  }
1838  else
1839  {
1840  wxString msgA =
1841 _("Project check of \"%s\" folder \
1842 \nfound %d orphan block file(s). These files are \
1843 \nunused by this project, but might belong to \
1844 other projects. \
1845 \nThey are doing no harm and are small.");
1846  wxString msg;
1847  msg.Printf(msgA, this->projName, (int)orphanFilePathArray.GetCount());
1848 
1849  const wxChar *buttons[] =
1850  {_("Continue without deleting; ignore the extra files this session"),
1851  _("Close project immediately with no further changes"),
1852  _("Delete orphan files (permanent immediately)"),
1853  NULL};
1854  wxLog::FlushActive(); // MultiDialog has "Show Log..." button, so make sure log is current.
1855  action = ShowMultiDialog(msg, _("Warning - Orphan Block File(s)"), buttons);
1856  }
1857 
1858  if (action == 1)
1859  nResult = FSCKstatus_CLOSE_REQ;
1860  // Nothing is done if (action == 0).
1861  else if (action == 2)
1862  {
1863  // FSCKstatus_CHANGED was bogus here.
1864  // The files are deleted, so "Undo Project Repair" could not do anything.
1865  // Plus they affect none of the valid tracks, so incorrect to mark them changed,
1866  // and no need for refresh.
1867  // nResult |= FSCKstatus_CHANGED;
1868  for (size_t i = 0; i < orphanFilePathArray.GetCount(); i++)
1869  wxRemoveFile(orphanFilePathArray[i]);
1870  }
1871  }
1872 
1873  if ((nResult != FSCKstatus_CLOSE_REQ) && !ODManager::HasLoadedODFlag())
1874  {
1875  // Remove any empty directories.
1876  ProgressDialog pProgress
1877  (_("Progress"),
1878  _("Cleaning up unused directories in project data"));
1879  // nDirCount is for updating pProgress. +1 because we may DELETE dirPath.
1880  int nDirCount = RecursivelyCountSubdirs(dirPath) + 1;
1881  RecursivelyRemoveEmptyDirs(dirPath, nDirCount, &pProgress);
1882  }
1883 
1884  // Summarize and flush the log.
1885  if (bForceError ||
1886  !missingAliasedFileAUFHash.empty() ||
1887  !missingAUFHash.empty() ||
1888  !missingAUHash.empty() ||
1889  !orphanFilePathArray.IsEmpty())
1890  {
1891  wxLogWarning(_("Project check found file inconsistencies inspecting the loaded project data."));
1892  wxLog::FlushActive(); // Flush is modal and will clear the log (both desired).
1893 
1894  // In auto-recover mode, we didn't do any ShowMultiDialog calls above, so put up an alert.
1895  if (bAutoRecoverMode)
1897  _("Project check found file inconsistencies during automatic recovery.\n\nSelect 'Show Log...' in the Help menu to see details."),
1898  _("Warning: Problems in Automatic Recovery"),
1899  wxOK | wxICON_EXCLAMATION);
1900  }
1901 
1903  return nResult;
1904 }
static int RecursivelyRemoveEmptyDirs(wxString dirPath, int nDirCount=0, ProgressDialog *pProgress=NULL)
Definition: DirManager.cpp:258
wxString projName
Definition: DirManager.h:211
#define FSCKstatus_SAVE_AUP
Definition: DirManager.h:33
root of a hierarchy of classes that are thrown and caught by Audacity.
ProgressDialog Class.
void SetMissingAliasedFileWarningShouldShow(bool b)
Changes the behavior of missing aliased blockfiles warnings.
static int RecursivelyCountSubdirs(wxString dirPath)
Definition: DirManager.cpp:238
#define FSCKstatus_CHANGED
Definition: DirManager.h:32
int AudacityMessageBox(const wxString &message, const wxString &caption=AudacityMessageBoxCaptionStr(), long style=wxOK|wxCENTRE, wxWindow *parent=NULL, int x=wxDefaultCoord, int y=wxDefaultCoord)
Definition: ErrorDialog.h:92
void FindMissingAliasedFiles(BlockHash &missingAliasedFileAUFHash, BlockHash &missingAliasedFilePathHash)
void FindMissingAUFs(BlockHash &missingAUFHash)
std::shared_ptr< BlockFile > BlockFilePtr
Definition: BlockFile.h:48
void FindMissingAUs(BlockHash &missingAUHash)
BlockHash mBlockFileHash
Definition: DirManager.h:191
static bool HasLoadedODFlag()
returns a flag that is set if we have loaded some OD blockfiles from PCM.
Definition: ODManager.cpp:522
R GuardedCall(const F1 &body, const F2 &handler=F2::Default(), const F3 &delayedHandler={})
wxString projFull
Definition: DirManager.h:213
int ShowMultiDialog(const wxString &message, const wxString &title, const wxChar **buttons, const wxString &boxMsg, bool log)
std::unordered_map< wxString, std::weak_ptr< BlockFile > > BlockHash
Definition: DirManager.h:40
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
wxString mytemp
Definition: DirManager.h:229
A BlockFile that refers to data in an existing file.
Definition: BlockFile.h:251
static int RecursivelyEnumerateWithProgress(wxString dirPath, wxArrayString &filePathArray, wxString dirspec, wxString filespec, bool bFiles, bool bDirs, int progress_count, const wxChar *message)
Definition: DirManager.cpp:216
#define FSCKstatus_CLOSE_REQ
Definition: DirManager.h:31
AudacityApp & wxGetApp()
void FindOrphanBlockFiles(const wxArrayString &filePathArray, wxArrayString &orphanFilePathArray)
void DirManager::RemoveOrphanBlockfiles ( )

Definition at line 2039 of file DirManager.cpp.

References _(), FindOrphanBlockFiles(), mBlockFileHash, mytemp, projFull, and RecursivelyEnumerateWithProgress().

2040 {
2041  wxArrayString filePathArray; // *all* files in the project directory/subdirectories
2042  wxString dirPath = (projFull != wxT("") ? projFull : mytemp);
2044  dirPath,
2045  filePathArray, // output: all files in project directory tree
2046  wxEmptyString, // All dirs
2047  wxEmptyString, // All files
2048  true, false,
2049  mBlockFileHash.size(), // rough guess of how many BlockFiles will be found/processed, for progress
2050  _("Inspecting project file data"));
2051 
2052  wxArrayString orphanFilePathArray;
2053  this->FindOrphanBlockFiles(
2054  filePathArray, // input: all files in project directory tree
2055  orphanFilePathArray); // output: orphan files
2056 
2057  // Remove all orphan blockfiles.
2058  for (size_t i = 0; i < orphanFilePathArray.GetCount(); i++)
2059  wxRemoveFile(orphanFilePathArray[i]);
2060 }
BlockHash mBlockFileHash
Definition: DirManager.h:191
wxString projFull
Definition: DirManager.h:213
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
wxString mytemp
Definition: DirManager.h:229
static int RecursivelyEnumerateWithProgress(wxString dirPath, wxArrayString &filePathArray, wxString dirspec, wxString filespec, bool bFiles, bool bDirs, int progress_count, const wxChar *message)
Definition: DirManager.cpp:216
void FindOrphanBlockFiles(const wxArrayString &filePathArray, wxArrayString &orphanFilePathArray)
void DirManager::SaveBlockFile ( BlockFile f,
int  depth,
FILE *  fp 
)
static void DirManager::SetDontDeleteTempFiles ( )
inlinestatic

Definition at line 176 of file DirManager.h.

Referenced by AudacityApp::OnInit().

176 { dontDeleteTempFiles = true; }
static bool dontDeleteTempFiles
Definition: DirManager.h:231
void DirManager::SetLoadingBlockLength ( size_t  len)
inline

Definition at line 120 of file DirManager.h.

Referenced by Sequence::HandleXMLTag().

120 { mLoadingBlockLen = len; }
size_t mLoadingBlockLen
Definition: DirManager.h:222
void DirManager::SetLoadingFormat ( sampleFormat  format)
inline

Definition at line 119 of file DirManager.h.

References format.

Referenced by Sequence::HandleXMLChild().

119 { mLoadingFormat = format; }
int format
Definition: ExportPCM.cpp:56
sampleFormat mLoadingFormat
Definition: DirManager.h:221
void DirManager::SetLoadingMaxSamples ( size_t  max)
inline

Definition at line 123 of file DirManager.h.

Referenced by Sequence::HandleXMLTag().

123 { mMaxSamples = max; }
size_t mMaxSamples
Definition: DirManager.h:224
void DirManager::SetLoadingTarget ( BlockArray pArray,
unsigned  idx 
)
inline

Definition at line 114 of file DirManager.h.

Referenced by Sequence::HandleXMLTag().

115  {
116  mLoadingTarget = pArray;
117  mLoadingTargetIdx = idx;
118  }
unsigned mLoadingTargetIdx
Definition: DirManager.h:220
BlockArray * mLoadingTarget
Definition: DirManager.h:219
void DirManager::SetLocalTempDir ( const wxString &  path)

Definition at line 715 of file DirManager.cpp.

References mytemp.

716 {
717  mytemp = path;
718 }
wxString mytemp
Definition: DirManager.h:229
bool DirManager::SetProject ( wxString &  newProjPath,
wxString &  newProjName,
const bool  bCreate 
)

Definition at line 477 of file DirManager.cpp.

References _(), CleanDir(), CopyToNewProjectDirectory(), kCleanTopDirToo, mBlockFileHash, mytemp, OSFILENAME, projFull, projName, projPath, Success, and ProgressDialog::Update().

478 {
479  bool moving = true;
480  wxString oldPath = this->projPath;
481  wxString oldName = this->projName;
482  wxString oldFull = projFull;
483  wxString oldLoc = projFull;
484  if (oldLoc == wxT(""))
485  oldLoc = mytemp;
486 
487  if (newProjPath == wxT(""))
488  newProjPath = ::wxGetCwd();
489 
490  this->projPath = newProjPath;
491  this->projName = newProjName;
492  if (newProjPath.Last() == wxFILE_SEP_PATH)
493  this->projFull = newProjPath + newProjName;
494  else
495  this->projFull = newProjPath + wxFILE_SEP_PATH + newProjName;
496 
497  wxString cleanupLoc1=oldLoc;
498  wxString cleanupLoc2=projFull;
499 
500  bool created = false;
501 
502  if (bCreate) {
503  if (!wxDirExists(projFull)) {
504  if (!wxMkdir(projFull)) {
505  this->projFull = oldFull;
506  this->projPath = oldPath;
507  this->projName = oldName;
508  return false;
509  }
510  else
511  created = true;
512  }
513 
514  #ifdef __UNIX__
515  chmod(OSFILENAME(projFull), 0775);
516  #endif
517 
518  #ifdef __WXMAC__
519  chmod(OSFILENAME(projFull), 0775);
520  #endif
521 
522  } else {
523  if (!wxDirExists(projFull)) {
524  this->projFull = oldFull;
525  this->projPath = oldPath;
526  this->projName = oldName;
527  return false;
528  }
529  }
530 
531  /* Move all files into this NEW directory. Files which are
532  "locked" get copied instead of moved. (This happens when
533  we perform a Save As - the files which belonged to the last
534  saved version of the old project must not be moved,
535  otherwise the old project would not be safe.) */
536 
537  int trueTotal = 0;
538 
539  {
540  /*i18n-hint: This title appears on a dialog that indicates the progress in doing something.*/
541  ProgressDialog progress(_("Progress"),
542  _("Saving project data files"));
543 
544  int total = mBlockFileHash.size();
545 
546  bool success = true;
547  int count = 0;
548  wxArrayString newPaths;
549  for (const auto &pair : mBlockFileHash)
550  {
551  wxString newPath;
552  BlockFilePtr b = pair.second.lock();
553  if (b) {
554  // FIXME: TRAP_ERR
555  // JKC: The 'success' variable and recovery strategy looks
556  // broken/bogus to me. Would need to be using &= to catch
557  // failure in one of the copies/moves. Besides which,
558  // our temporary files are going to be deleted when we exit
559  // anyway, if saving from temporary to named project.
560 
561  if( progress.Update(count, total) != ProgressResult::Success )
562  success = false;
563  else {
564  moving = moving && !b->IsLocked();
565  auto result = CopyToNewProjectDirectory( &*b );
566  success = result.first;
567  newPath = result.second;
568  }
569 
570  if (success) {
571  count++;
572  }
573  else
574  break;
575  }
576 
577  newPaths.push_back( newPath );
578  }
579 
580  // in case there are any nulls
581  trueTotal = count;
582 
583  if (success) {
584  auto size = newPaths.size();
585  wxASSERT( size == mBlockFileHash.size() );
586 
587  // Commit changes to filenames in the BlockFile objects, and removal
588  // of files at old paths, ONLY NOW! This must be nothrow.
589 
590  // This copy-then-delete procedure is needed to make it safe to
591  // attempt save to another storage device, but fail.
592 
593  // It has the consequence that saving a project from one part of
594  // the device to another will not succeed unless there is sufficient
595  // space to hold originals and copies at the same time. Perhaps the
596  // extra cautions are not needed in that case, and the old procedure
597  // of renaming first, and reversing the renamings in case of failure,
598  // could still work safely.
599 
600  // But I don't know whether wxWidgets gives us a reliable means to
601  // distinguish that case.
602 
603  // I will err on the side of safety and simplicity and follow the
604  // same procedure in all cases.
605 
606  size_t ii = 0;
607  for (const auto &pair : mBlockFileHash)
608  {
609  BlockFilePtr b = pair.second.lock();
610 
611  if (b) {
612  if (moving || !b->IsLocked()) {
613  auto result = b->GetFileName();
614  auto oldPath = result.name.GetFullPath();
615  if (!oldPath.empty())
616  wxRemoveFile( oldPath );
617  }
618 
619  if (ii < size)
620  b->SetFileName(
621  wxFileNameWrapper{ wxFileName{ newPaths[ii] } } );
622  }
623 
624  ++ii;
625  }
626  }
627  else {
628  this->projFull = oldFull;
629  this->projPath = oldPath;
630  this->projName = oldName;
631 
632  if (created)
633  CleanDir(
634  cleanupLoc2,
635  wxEmptyString,
636  wxEmptyString,
637  _("Cleaning up after failed save"),
639 
640  return false;
641  }
642  }
643 
644  // Some subtlety; SetProject is used both to move a temp project
645  // into a permanent home as well as just set up path variables when
646  // loading a project; in this latter case, the movement code does
647  // nothing because SetProject is called before there are any
648  // blockfiles. Cleanup code trigger is the same
649 
650  // Do the cleanup of the temporary directory only if not saving-as, which we
651  // detect by having done copies rather than moves.
652  if (moving && trueTotal > 0) {
653  // Clean up after ourselves; boldly remove all files and directories
654  // in the tree. (Unlike what the earlier version of this comment said.)
655  // Because this is a relocation of the project, not the case of closing
656  // a persistent project.
657 
658  // You may think the loops above guarantee that all files we put in the
659  // folders have been moved away already, but:
660  // to fix bug1567 on Mac, we need to find the extraneous .DS_Store files
661  // that we didn't put there, but that Finder may insert into the folders,
662  // and mercilessly remove them, in addition to removing the directories.
663 
664  CleanDir(
665  cleanupLoc1,
666  wxEmptyString, // EmptyString => ALL directories.
667  // If the next line were wxEmptyString, ALL files would be removed.
668  ".DS_Store", // Other project files should already have been removed.
669  _("Cleaning up cache directories"),
671 
672  //This destroys the empty dirs of the OD block files, which are yet to come.
673  //Dont know if this will make the project dirty, but I doubt it. (mchinen)
674  // count += RecursivelyEnumerate(cleanupLoc2, dirlist, wxEmptyString, false, true);
675  }
676  return true;
677 }
wxString projName
Definition: DirManager.h:211
static void CleanDir(const wxString &path, const wxString &dirSpec, const wxString &fileSpec, const wxString &msg, int flags=0)
Definition: DirManager.cpp:444
ProgressDialog Class.
wxString projPath
Definition: DirManager.h:212
#define OSFILENAME(X)
Definition: Internat.h:173
std::shared_ptr< BlockFile > BlockFilePtr
Definition: BlockFile.h:48
BlockHash mBlockFileHash
Definition: DirManager.h:191
std::pair< bool, wxString > CopyToNewProjectDirectory(BlockFile *f)
wxString projFull
Definition: DirManager.h:213
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
wxString mytemp
Definition: DirManager.h:229
static void DirManager::SetTempDir ( const wxString &  _temp)
inlinestatic

Definition at line 60 of file DirManager.h.

Referenced by AudacityApp::InitTempDir().

60 { globaltemp = _temp; }
static wxString globaltemp
Definition: DirManager.h:228
void DirManager::WriteCacheToDisk ( )

Definition at line 2117 of file DirManager.cpp.

References _(), mBlockFileHash, and ProgressDialog::Update().

2118 {
2119  BlockHash::iterator iter;
2120  int numNeed = 0;
2121 
2122  iter = mBlockFileHash.begin();
2123  while (iter != mBlockFileHash.end())
2124  {
2125  BlockFilePtr b = iter->second.lock();
2126  if (b) {
2127  if (b->GetNeedWriteCacheToDisk())
2128  numNeed++;
2129  }
2130  ++iter;
2131  }
2132 
2133  if (numNeed == 0)
2134  return;
2135 
2136  ProgressDialog progress(_("Saving recorded audio"),
2137  _("Saving recorded audio to disk"));
2138 
2139  iter = mBlockFileHash.begin();
2140  int current = 0;
2141  while (iter != mBlockFileHash.end())
2142  {
2143  BlockFilePtr b = iter->second.lock();
2144  if (b) {
2145  if (b->GetNeedWriteCacheToDisk())
2146  {
2147  b->WriteCacheToDisk();
2148  progress.Update(current, numNeed);
2149  }
2150  current++;
2151  }
2152  ++iter;
2153  }
2154 }
ProgressDialog Class.
std::shared_ptr< BlockFile > BlockFilePtr
Definition: BlockFile.h:48
BlockHash mBlockFileHash
Definition: DirManager.h:191
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand

Member Data Documentation

wxArrayString DirManager::aliasList
private
bool DirManager::dontDeleteTempFiles = false
staticprivate

Definition at line 231 of file DirManager.h.

Referenced by CleanDir().

wxString DirManager::globaltemp
staticprivate

Definition at line 228 of file DirManager.h.

Referenced by CleanTempDir(), and DirManager().

wxString DirManager::lastProject
private

Definition at line 215 of file DirManager.h.

struct DirManager::BalanceInfo DirManager::mBalanceInfo
private

Referenced by BalanceInfoDel(), and DirManager().

BlockHash DirManager::mBlockFileHash
private
unsigned long DirManager::mLastBlockFileDestructionCount { 0 }
private

Definition at line 226 of file DirManager.h.

Referenced by DirManager().

size_t DirManager::mLoadingBlockLen
private

Definition at line 222 of file DirManager.h.

Referenced by HandleXMLTag().

sampleFormat DirManager::mLoadingFormat
private

Definition at line 221 of file DirManager.h.

Referenced by HandleXMLTag().

BlockArray* DirManager::mLoadingTarget
private

Definition at line 219 of file DirManager.h.

Referenced by DirManager(), and HandleXMLTag().

unsigned DirManager::mLoadingTargetIdx
private

Definition at line 220 of file DirManager.h.

Referenced by DirManager(), and HandleXMLTag().

size_t DirManager::mMaxSamples
private

Definition at line 224 of file DirManager.h.

Referenced by DirManager(), and HandleXMLTag().

wxString DirManager::mytemp
private
int DirManager::numDirManagers = 0
staticprivate

Definition at line 230 of file DirManager.h.

Referenced by DirManager(), and ~DirManager().

wxString DirManager::projFull
private
wxString DirManager::projName
private

Definition at line 211 of file DirManager.h.

Referenced by DirManager(), GetProjectName(), ProjectFSCK(), and SetProject().

wxString DirManager::projPath
private

Definition at line 212 of file DirManager.h.

Referenced by DirManager(), GetFreeDiskSpace(), and SetProject().


The documentation for this class was generated from the following files: