// True = success bool FindDependencies(AudacityProject *project, AliasedFileArray *outAliasedFiles) { sampleFormat format = project->GetDefaultFormat(); BlockArray blocks; GetAllSeqBlocks(project, &blocks); AliasedFileHash aliasedFileHash; BoolBlockFileHash blockFileHash; int i; for(i=0; i<(int)blocks.GetCount(); i++) { BlockFile *f = blocks[i]->f; if (f->IsAlias() && !blockFileHash[f]) { blockFileHash[f] = true; // Don't count the same blockfile twice AliasBlockFile *aliasBlockFile = (AliasBlockFile *)f; wxFileName fileName = aliasBlockFile->GetAliasedFile(); wxString fileNameStr = fileName.GetFullPath(); int blockBytes = (SAMPLE_SIZE(format) * aliasBlockFile->GetLength()); if (aliasedFileHash[fileNameStr]) aliasedFileHash[fileNameStr]->bytes += blockBytes; else { outAliasedFiles->Add(AliasedFile(fileName, blockBytes)); aliasedFileHash[fileNameStr] = &((*outAliasedFiles)[outAliasedFiles->GetCount()-1]); } } } return true; }
BlockFile *DirManager::LoadBlockFile(wxTextFile * in, sampleFormat format) { wxASSERT(projFull != ""); long summaryLen; if (!(in->GetNextLine().ToLong(&summaryLen))) return NULL; wxString blockName = in->GetNextLine(); bool alias = false; wxString aliasFullPath; long localLen, start, len, channel; if (blockName == "Alias") { alias = true; aliasFullPath = in->GetNextLine(); //if (!(in->GetNextLine().ToLong(&localLen))) // return NULL; if (!(in->GetNextLine().ToLong(&start))) return NULL; if (!(in->GetNextLine().ToLong(&len))) return NULL; if (!(in->GetNextLine().ToLong(&channel))) return NULL; blockName = in->GetNextLine(); } wxString pathName = projFull + wxFILE_SEP_PATH + blockName; BlockFile *retrieved = (BlockFile *) blockFileHash->Get(blockName); if (retrieved) { wxASSERT(retrieved->IsAlias() == alias); retrieved->Ref(); return retrieved; } else { BlockFile *newBlockFile = new BlockFile(blockName, pathName, summaryLen); if (alias) { newBlockFile->SetAliasedData(aliasFullPath, start, len, channel); aliasList.Add(aliasFullPath); } newBlockFile->mSampleFormat = format; blockFileHash->Put(blockName, (wxObject *) newBlockFile); CheckHashTableSize(); if (!wxFileExists(pathName)) return 0; return newBlockFile; } }
BlockFile *DirManager::LoadBlockFile(wxTextFile * in) { wxASSERT(projFull != ""); wxString blockName = in->GetNextLine(); bool alias = false; wxString aliasFullPath; long localLen, start, len, channel; if (blockName == "Alias") { alias = true; aliasFullPath = in->GetNextLine(); if (!(in->GetNextLine().ToLong(&localLen))) return NULL; if (!(in->GetNextLine().ToLong(&start))) return NULL; if (!(in->GetNextLine().ToLong(&len))) return NULL; if (!(in->GetNextLine().ToLong(&channel))) return NULL; blockName = in->GetNextLine(); } wxString pathName = projFull + pathChar + blockName; BlockFile *retrieved = (BlockFile *) blockFileHash->Get(blockName); if (retrieved) { wxASSERT(retrieved->IsAlias() == alias); retrieved->Ref(); return retrieved; } else { BlockFile *newBlockFile; if (alias) { newBlockFile = new BlockFile(blockName, pathName, localLen, aliasFullPath, start, len, channel); aliasList.Add(aliasFullPath); } else newBlockFile = new BlockFile(blockName, pathName); blockFileHash->Put(blockName, (wxObject *) newBlockFile); CheckHashTableSize(); if (!wxFileExists(pathName)) return 0; return newBlockFile; } }
void FindDependencies(AudacityProject *project, AliasedFileArray *outAliasedFiles) { sampleFormat format = project->GetDefaultFormat(); BlockArray blocks; GetAllSeqBlocks(project, &blocks); AliasedFileHash aliasedFileHash; BoolBlockFileHash blockFileHash; int i; for (i = 0; i < (int)blocks.GetCount(); i++) { BlockFile *f = blocks[i]->f; if (f->IsAlias() && (blockFileHash.count(f) == 0)) { // f is an alias block we have not yet counted. blockFileHash[f] = true; // Don't count the same blockfile twice. AliasBlockFile *aliasBlockFile = (AliasBlockFile *)f; wxFileName fileName = aliasBlockFile->GetAliasedFileName(); // In DirManager::ProjectFSCK(), if the user has chosen to // "Replace missing audio with silence", the code there puts in an empty wxFileName. // Don't count those in dependencies. if (!fileName.IsOk()) continue; wxString fileNameStr = fileName.GetFullPath(); int blockBytes = (SAMPLE_SIZE(format) * aliasBlockFile->GetLength()); if (aliasedFileHash.count(fileNameStr) > 0) // Already put this AliasBlockFile in aliasedFileHash. // Update block count. aliasedFileHash[fileNameStr]->mByteCount += blockBytes; else { // Haven't counted this AliasBlockFile yet. // Add to return array and internal hash. outAliasedFiles->Add(AliasedFile(fileName, blockBytes, fileName.FileExists())); aliasedFileHash[fileNameStr] = &((*outAliasedFiles)[outAliasedFiles->GetCount()-1]); } } } }
bool Sequence::ConvertToSampleFormat(sampleFormat format) { if (format == mSampleFormat) return true; if (mBlock->Count() == 0) { mSampleFormat = format; return true; } sampleFormat oldFormat = mSampleFormat; mSampleFormat = format; for (unsigned int i = 0; i < mBlock->Count(); i++) { BlockFile *oldBlock = mBlock->Item(i)->f; sampleCount len = mBlock->Item(i)->len; if (!oldBlock->IsAlias()) { BlockFile *newBlock = mDirManager->NewBlockFile(mSummary->totalSummaryBytes); samplePtr buffer1 = NewSamples(len, oldFormat); samplePtr buffer2 = NewSamples(len, mSampleFormat); oldBlock->ReadData(buffer1, oldFormat, 0, len); CopySamples(buffer1, oldFormat, buffer2, mSampleFormat, len); newBlock->WriteData(buffer2, mSampleFormat, len); mBlock->Item(i)->f = newBlock; mDirManager->Deref(oldBlock); UpdateSummaries(buffer2, mBlock->Item(i), len); DeleteSamples(buffer2); DeleteSamples(buffer1); } } return true; }
bool Sequence::ConvertToSampleFormat(sampleFormat format) { if (format == mSampleFormat) return true; if (mBlock->Count() == 0) { mSampleFormat = format; return true; } sampleFormat oldFormat = mSampleFormat; mSampleFormat = format; for (unsigned int i = 0; i < mBlock->Count(); i++) { SeqBlock *b = mBlock->Item(i); BlockFile *oldBlock = b->f; sampleCount len = b->f->GetLength(); if (!oldBlock->IsAlias()) { BlockFile *newBlock; samplePtr buffer1 = NewSamples(len, oldFormat); samplePtr buffer2 = NewSamples(len, mSampleFormat); oldBlock->ReadData(buffer1, oldFormat, 0, len); CopySamples(buffer1, oldFormat, buffer2, mSampleFormat, len); newBlock = mDirManager->NewSimpleBlockFile(buffer2, len, mSampleFormat); mBlock->Item(i)->f = newBlock; mDirManager->Deref(oldBlock); DeleteSamples(buffer2); DeleteSamples(buffer1); } } return true; }
// Given a project and a list of aliased files that should no // longer be external dependencies (selected by the user), replace // all of those alias block files with disk block files. void RemoveDependencies(AudacityProject *project, AliasedFileArray *aliasedFiles) { DirManager *dirManager = project->GetDirManager(); ProgressDialog *progress = new ProgressDialog(_("Removing Dependencies"), _("Copying audio data into project...")); int updateResult = eProgressSuccess; // Hash aliasedFiles based on their full paths and // count total number of bytes to process. AliasedFileHash aliasedFileHash; wxLongLong totalBytesToProcess = 0; unsigned int i; for (i = 0; i < aliasedFiles->GetCount(); i++) { totalBytesToProcess += aliasedFiles->Item(i).mByteCount; wxString fileNameStr = aliasedFiles->Item(i).mFileName.GetFullPath(); aliasedFileHash[fileNameStr] = &aliasedFiles->Item(i); } BlockArray blocks; GetAllSeqBlocks(project, &blocks); const sampleFormat format = project->GetDefaultFormat(); ReplacedBlockFileHash blockFileHash; wxLongLong completedBytes = 0; for (i = 0; i < blocks.GetCount(); i++) { BlockFile *f = blocks[i]->f; if (f->IsAlias() && (blockFileHash.count(f) == 0)) { // f is an alias block we have not yet processed. AliasBlockFile *aliasBlockFile = (AliasBlockFile *)f; wxFileName fileName = aliasBlockFile->GetAliasedFileName(); wxString fileNameStr = fileName.GetFullPath(); if (aliasedFileHash.count(fileNameStr) == 0) // This aliased file was not selected to be replaced. Skip it. continue; // Convert it from an aliased file to an actual file in the project. unsigned int len = aliasBlockFile->GetLength(); samplePtr buffer = NewSamples(len, format); f->ReadData(buffer, format, 0, len); BlockFile *newBlockFile = dirManager->NewSimpleBlockFile(buffer, len, format); DeleteSamples(buffer); // Update our hash so we know what block files we've done blockFileHash[f] = newBlockFile; // Update the progress bar completedBytes += SAMPLE_SIZE(format) * len; updateResult = progress->Update(completedBytes, totalBytesToProcess); if (updateResult != eProgressSuccess) break; } } // Above, we created a SimpleBlockFile contained in our project // to go with each AliasBlockFile that we wanted to migrate. // However, that didn't actually change any references to these // blockfiles in the Sequences, so we do that next... ReplaceBlockFiles(project, blockFileHash); // Subtract one from reference count of new block files; they're // now all referenced the proper number of times by the Sequences ReplacedBlockFileHash::iterator it; for( it = blockFileHash.begin(); it != blockFileHash.end(); ++it ) { BlockFile *f = it->second; dirManager->Deref(f); } delete progress; }
bool DirManager::EnsureSafeFilename(wxFileName fName) { // Quick check: If it's not even in our alias list, // then the file name is A-OK. #if 0 printf("file name: %s\n", fName.GetFullPath().c_str()); printf("string list:\n"); wxStringListNode *node = aliasList.GetFirst(); while (node) { wxString string = node->GetData(); printf("%s\n", string.c_str()); node = node->GetNext(); } #endif if (!aliasList.Member(fName.GetFullPath())) return true; // If any of the following commands fail, your guess is as // good as mine why. The following error message is the // best we can do - we'll use it if any of the renames, // creates, or deletes fail. wxString errStr = _( "Error: is directory write-protected or disk full?" ); /* i18n-hint: 'old' is part of a filename used when a file is renamed. */ // Figure out what the new name for the existing file would be. /* i18n-hint: e.g. Try to go from "mysong.wav" to "mysong-old1.wav". */ // Keep trying until we find a filename that doesn't exist. wxFileName renamedFile = fName; int i = 0; do { i++; /* i18n-hint: This is the pattern for filenames that are created when a file needs to be backed up to a different name. For example, mysong would become mysong-old1, mysong-old2, etc. */ renamedFile.SetName(wxString::Format(_("%s-old%d"), fName.GetName().c_str(), i)); } while (renamedFile.FileExists()); // Test creating a file by that name to make sure it will // be possible to do the rename wxFile testFile(renamedFile.GetFullPath(), wxFile::write); if (!testFile.IsOpened()) { wxMessageBox(errStr); return false; } if (!wxRemoveFile(renamedFile.GetFullPath())) { wxMessageBox(errStr); return false; } printf(_("Renamed file: %s\n"), (const char *)renamedFile.GetFullPath()); // Go through our block files and see if any indeed point to // the file we're concerned about. If so, point the block file // to the renamed file and when we're done, perform the rename. bool needToRename = false; wxBusyCursor busy; blockFileHash->BeginFind(); wxNode *n = blockFileHash->Next(); while(n) { BlockFile *b = (BlockFile *)n->GetData(); // don't worry, we don't rely on this cast unless IsAlias is true AliasBlockFile *ab = (AliasBlockFile*)b; if (b->IsAlias() && ab->GetAliasedFile() == fName) { needToRename = true; printf(_("Changing block %s\n"), (const char *)b->GetFileName().GetFullName()); ab->ChangeAliasedFile(renamedFile); } n = blockFileHash->Next(); } if (needToRename) { if (!wxRenameFile(fName.GetFullPath(), renamedFile.GetFullPath())) { // ACK!!! The renaming was unsuccessful!!! // (This shouldn't happen, since we tried creating a // file of this name and then deleted it just a // second earlier.) But we'll handle this scenario // just in case!!! // Put things back where they were blockFileHash->BeginFind(); n = blockFileHash->Next(); while(n) { BlockFile *b = (BlockFile *)n->GetData(); AliasBlockFile *ab = (AliasBlockFile*)b; if (b->IsAlias() && ab->GetAliasedFile() == renamedFile) ab->ChangeAliasedFile(fName); n = blockFileHash->Next(); } // Print error message and cancel the export wxMessageBox(errStr); return false; } aliasList.Delete(fName.GetFullPath()); aliasList.Add(renamedFile.GetFullPath()); } // Success!!! Either we successfully renamed the file, // or we didn't need to! return true; }
bool DirManager::EnsureSafeFilename(wxFileName fName) { // Quick check: If it's not even in our alias list, // then the file name is A-OK. if (aliasList.Index(fName.GetFullPath()) == wxNOT_FOUND) return true; /* i18n-hint: 'old' is part of a filename used when a file is renamed. */ // Figure out what the new name for the existing file would be. /* i18n-hint: e.g. Try to go from "mysong.wav" to "mysong-old1.wav". */ // Keep trying until we find a filename that doesn't exist. wxFileName renamedFile = fName; int i = 0; do { i++; /* i18n-hint: This is the pattern for filenames that are created when a file needs to be backed up to a different name. For example, mysong would become mysong-old1, mysong-old2, etc. */ renamedFile.SetName(wxString::Format(_("%s-old%d"), fName.GetName().c_str(), i)); } while (wxFileExists(renamedFile.GetFullPath())); // Test creating a file by that name to make sure it will // be possible to do the rename wxFile testFile(renamedFile.GetFullPath(), wxFile::write); if (!testFile.IsOpened()) { wxLogSysError(_("Unable to open/create test file"), renamedFile.GetFullPath().c_str()); return false; } // Close the file prior to renaming. testFile.Close(); if (!wxRemoveFile(renamedFile.GetFullPath())) { wxLogSysError(_("Unable to remove '%s'"), renamedFile.GetFullPath().c_str()); return false; } wxPrintf(_("Renamed file: %s\n"), renamedFile.GetFullPath().c_str()); // Go through our block files and see if any indeed point to // the file we're concerned about. If so, point the block file // to the renamed file and when we're done, perform the rename. bool needToRename = false; wxBusyCursor busy; BlockHash::iterator it=blockFileHash.begin(); while(it != blockFileHash.end()) { BlockFile *b = it->second; // don't worry, we don't rely on this cast unless IsAlias is true AliasBlockFile *ab = (AliasBlockFile*)b; if (b->IsAlias() && ab->GetAliasedFile() == fName) { needToRename = true; wxPrintf(_("Changing block %s\n"), b->GetFileName().GetFullName().c_str()); ab->ChangeAliasedFile(renamedFile); } it++; } if (needToRename) { if (!wxRenameFile(fName.GetFullPath(), renamedFile.GetFullPath())) { // ACK!!! The renaming was unsuccessful!!! // (This shouldn't happen, since we tried creating a // file of this name and then deleted it just a // second earlier.) But we'll handle this scenario // just in case!!! // Put things back where they were BlockHash::iterator it=blockFileHash.begin(); while(it != blockFileHash.end()) { BlockFile *b = it->second; AliasBlockFile *ab = (AliasBlockFile*)b; if (b->IsAlias() && ab->GetAliasedFile() == renamedFile) ab->ChangeAliasedFile(fName); it++; } // Print error message and cancel the export wxLogSysError(_("Unable to rename '%s' to '%s'"), fName.GetFullPath().c_str(), renamedFile.GetFullPath().c_str()); return false; } aliasList.Remove(fName.GetFullPath()); aliasList.Add(renamedFile.GetFullPath()); } // Success!!! Either we successfully renamed the file, // or we didn't need to! return true; }
bool DirManager::EnsureSafeFilename(wxString fName) { // Quick check: If it's not even in our alias list, // then the file name is A-OK. if (!aliasList.Member(fName)) return true; // If any of the following commands fail, your guess is as // good as mine why. The following error message is the // best we can do - we'll use it if any of the renames, // creates, or deletes fail. wxString errStr = "Error: is directory write-protected or disk full?"; // Figure out what the new name for the existing file // would be. Try to go from "mysong.wav" to "mysong-old1.wav". // Keep trying until we find a filename that doesn't exist. wxString pathOnly, nameOnly, extension; wxString renamedFile; ::wxSplitPath(fName, &pathOnly, &nameOnly, &extension); int i = 0; do { i++; if (extension != "") renamedFile.Printf("%s%s%s-old%d.%s", (const char *)pathOnly, (const char *)pathChar, (const char *)nameOnly, i, (const char *)extension); else renamedFile.Printf("%s%s%s-old%d", (const char *)pathOnly, (const char *)pathChar, (const char *)nameOnly, i); } while (wxFileExists(renamedFile)); // Test creating a file by that name to make sure it will // be possible to do the rename wxFile testFile(renamedFile, wxFile::write); if (!testFile.IsOpened()) { wxMessageBox(errStr); return false; } if (!wxRemoveFile(renamedFile)) { wxMessageBox(errStr); return false; } printf("Renamed file: %s\n", (const char *)renamedFile); // Go through our block files and see if any indeed point to // the file we're concerned about. If so, point the block file // to the renamed file and when we're done, perform the rename. bool needToRename = false; wxBusyCursor busy; blockFileHash->BeginFind(); wxNode *n = blockFileHash->Next(); while(n) { BlockFile *b = (BlockFile *)n->GetData(); if (b->IsAlias() && b->GetAliasedFile() == fName) { needToRename = true; printf("Changing block %s\n", (const char *)b->GetName()); b->ChangeAliasedFile(renamedFile); } n = blockFileHash->Next(); } if (needToRename) { if (!wxRenameFile(fName, renamedFile)) { // ACK!!! The renaming was unsuccessful!!! // (This shouldn't happen, since we tried creating a // file of this name and then deleted it just a // second earlier.) But we'll handle this scenario // just in case!!! // Put things back where they were blockFileHash->BeginFind(); n = blockFileHash->Next(); while(n) { BlockFile *b = (BlockFile *)n->GetData(); if (b->IsAlias() && b->GetAliasedFile() == renamedFile) b->ChangeAliasedFile(fName); n = blockFileHash->Next(); } // Print error message and cancel the export wxMessageBox(errStr); return false; } aliasList.Delete(fName); aliasList.Add(renamedFile); } // Success!!! Either we successfully renamed the file, // or we didn't need to! return true; }
// Given a project and a list of aliased files that should no // longer be self-contained (selected by the user), replace // all of those alias block files with disk block files bool RemoveDependencies(AudacityProject *project, AliasedFileArray *aliasedFiles) { DirManager *dirManager = project->GetDirManager(); GetActiveProject()->ProgressShow(_("Removing Dependencies"), _("Copying audio data into project...")); AliasedFileHash aliasedFileHash; ReplacedBlockFileHash blockFileHash; double totalBytesToProcess = 0.0; double completedBytes = 0.0; unsigned int i; for(i=0; i<aliasedFiles->GetCount(); i++) { totalBytesToProcess += (double)aliasedFiles->Item(i).bytes; wxString fileNameStr = aliasedFiles->Item(i).fileName.GetFullPath(); aliasedFileHash[fileNameStr] = &aliasedFiles->Item(i); } sampleFormat format = project->GetDefaultFormat(); BlockArray blocks; GetAllSeqBlocks(project, &blocks); for(i=0; i<blocks.GetCount(); i++) { BlockFile *f = blocks[i]->f; if (f->IsAlias() && !blockFileHash[f]) { AliasBlockFile *aliasBlockFile = (AliasBlockFile *)f; wxFileName fileName = aliasBlockFile->GetAliasedFile(); wxString fileNameStr = fileName.GetFullPath(); if (!aliasedFileHash[fileNameStr]) continue; // Convert it from an aliased file to an actual file in the project unsigned int len = aliasBlockFile->GetLength(); samplePtr buffer = NewSamples(len, format); f->ReadData(buffer, format, 0, len); BlockFile *newBlockFile = dirManager->NewSimpleBlockFile(buffer, len, format); DeleteSamples(buffer); // Update our hash so we know what block files we've done blockFileHash[f] = newBlockFile; // Update the progress bar completedBytes += (double)SAMPLE_SIZE(format) * len; int progressValue = (int)(completedBytes * 1000.0 / totalBytesToProcess); GetActiveProject()->ProgressUpdate(progressValue); } } // Above, we created a SimpleBlockFile contained in our project // to go with each AliasBlockFile that we wanted to migrate. // However, that didn't actually change any references to these // blockfiles in the Sequences, so we do that next... ReplaceBlockFiles(project, blockFileHash); // Subtract one from reference count of new block files; they're // now all referenced the proper number of times by the Sequences ReplacedBlockFileHash::iterator it; for( it = blockFileHash.begin(); it != blockFileHash.end(); ++it ) { BlockFile *f = it->second; dirManager->Deref(f); } GetActiveProject()->ProgressHide(); return true; }