Audacity  2.2.2
Classes | Typedefs | Enumerations | Functions
Dependencies.cpp File Reference
#include "Audacity.h"
#include "Dependencies.h"
#include <wx/button.h>
#include <wx/defs.h>
#include <wx/dialog.h>
#include <wx/filename.h>
#include <wx/hashmap.h>
#include <wx/progdlg.h>
#include <wx/choice.h>
#include <wx/clipbrd.h>
#include <wx/dataobj.h>
#include "BlockFile.h"
#include "DirManager.h"
#include "Internat.h"
#include "Prefs.h"
#include "Project.h"
#include "Sequence.h"
#include "ShuttleGui.h"
#include "WaveTrack.h"
#include "WaveClip.h"
#include "widgets/ErrorDialog.h"
#include <unordered_map>

Go to the source code of this file.

Classes

class  DependencyDialog
 DependencyDialog shows dependencies of an AudacityProject on AliasedFile s. More...
 

Typedefs

using AliasedFileHash = std::unordered_map< wxString, AliasedFile * >
 
using ReplacedBlockFileHash = std::unordered_map< BlockFile *, BlockFilePtr >
 
using BoolBlockFileHash = std::unordered_map< BlockFile *, bool >
 

Enumerations

enum  { FileListID = 6000, CopySelectedFilesButtonID, CopyNamesToClipboardID, FutureActionChoiceID }
 

Functions

static void GetAllSeqBlocks (AudacityProject *project, BlockPtrArray *outBlocks)
 
static void ReplaceBlockFiles (BlockPtrArray &blocks, ReplacedBlockFileHash &hash)
 
void FindDependencies (AudacityProject *project, AliasedFileArray &outAliasedFiles)
 
static void RemoveDependencies (AudacityProject *project, AliasedFileArray &aliasedFiles)
 
 EVT_BUTTON (wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
 
DependencyDialog::OnYes EVT_BUTTON (wxID_CANCEL, DependencyDialog::OnCancel) DependencyDialog
 
static const wxString kStdMsg ()
 
static const wxString kExtraMsgForMissingFiles ()
 
bool ShowDependencyDialogIfNeeded (AudacityProject *project, bool isSaving)
 

Typedef Documentation

using AliasedFileHash = std::unordered_map<wxString, AliasedFile*>

Definition at line 63 of file Dependencies.cpp.

using BoolBlockFileHash = std::unordered_map<BlockFile *, bool>

Definition at line 68 of file Dependencies.cpp.

using ReplacedBlockFileHash = std::unordered_map<BlockFile *, BlockFilePtr>

Definition at line 67 of file Dependencies.cpp.

Enumeration Type Documentation

anonymous enum
Enumerator
FileListID 
CopySelectedFilesButtonID 
CopyNamesToClipboardID 
FutureActionChoiceID 

Definition at line 288 of file Dependencies.cpp.

Function Documentation

EVT_BUTTON ( wxID_NO  ,
DependencyDialog::OnNo   
)
DependencyDialog::OnYes EVT_BUTTON ( wxID_CANCEL  ,
DependencyDialog::OnCancel   
)

Definition at line 303 of file Dependencies.cpp.

References eIsCreating.

312 : wxDialogWrapper(parent, id, _("Project Depends on Other Audio Files"),
313  wxDefaultPosition, wxDefaultSize,
314  (isSaving ?
315  (wxDEFAULT_DIALOG_STYLE & ~wxCLOSE_BOX) : // no close box when saving
316  wxDEFAULT_DIALOG_STYLE) |
317  wxRESIZE_BORDER),
318  mProject(project),
319  mAliasedFiles(aliasedFiles),
320  mIsSaving(isSaving),
321  mHasMissingFiles(false),
322  mHasNonMissingFiles(false),
323  mMessageStaticText(NULL),
324  mFileListCtrl(NULL),
325  mCopySelectedFilesButton(NULL),
326  mCopyAllFilesButton(NULL),
327  mFutureActionChoice(NULL)
328 {
329  SetName(GetTitle());
330  ShuttleGui S(this, eIsCreating);
331  PopulateOrExchange(S);
332 }
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI...
Definition: ShuttleGui.h:409
_("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 FindDependencies ( AudacityProject project,
AliasedFileArray outAliasedFiles 
)

Definition at line 113 of file Dependencies.cpp.

References format, AliasBlockFile::GetAliasedFileName(), GetAllSeqBlocks(), AudacityProject::GetDefaultFormat(), and SAMPLE_SIZE.

Referenced by Exporter::GetFilename(), and ShowDependencyDialogIfNeeded().

115 {
116  sampleFormat format = project->GetDefaultFormat();
117 
118  BlockPtrArray blocks;
119  GetAllSeqBlocks(project, &blocks);
120 
121  AliasedFileHash aliasedFileHash;
122  BoolBlockFileHash blockFileHash;
123 
124  for (const auto &blockFile : blocks) {
125  const auto &f = blockFile->f;
126  if (f->IsAlias() && (blockFileHash.count( &*f ) == 0))
127  {
128  // f is an alias block we have not yet counted.
129  blockFileHash[ &*f ] = true; // Don't count the same blockfile twice.
130  auto aliasBlockFile = static_cast<AliasBlockFile*>( &*f );
131  const wxFileName &fileName = aliasBlockFile->GetAliasedFileName();
132 
133  // In DirManager::ProjectFSCK(), if the user has chosen to
134  // "Replace missing audio with silence", the code there puts in an empty wxFileName.
135  // Don't count those in dependencies.
136  if (!fileName.IsOk())
137  continue;
138 
139  const wxString &fileNameStr = fileName.GetFullPath();
140  auto blockBytes = (SAMPLE_SIZE(format) *
141  aliasBlockFile->GetLength());
142  if (aliasedFileHash.count(fileNameStr) > 0)
143  // Already put this AliasBlockFile in aliasedFileHash.
144  // Update block count.
145  aliasedFileHash[fileNameStr]->mByteCount += blockBytes;
146  else
147  {
148  // Haven't counted this AliasBlockFile yet.
149  // Add to return array and internal hash.
150 
151  // PRL: do this in two steps so that we move instead of copying.
152  // We don't have a moving push_back in all compilers.
153  outAliasedFiles.push_back(AliasedFile{});
154  outAliasedFiles.back() =
155  AliasedFile {
156  wxFileNameWrapper { fileName },
157  wxLongLong(blockBytes), fileName.FileExists()
158  };
159  aliasedFileHash[fileNameStr] = &outAliasedFiles.back();
160  }
161  }
162  }
163 }
#define SAMPLE_SIZE(SampleFormat)
Definition: Types.h:198
static void GetAllSeqBlocks(AudacityProject *project, BlockPtrArray *outBlocks)
std::vector< SeqBlock * > BlockPtrArray
Definition: Sequence.h:52
const wxFileName & GetAliasedFileName() const
Definition: BlockFile.h:278
int format
Definition: ExportPCM.cpp:56
std::unordered_map< wxString, AliasedFile * > AliasedFileHash
sampleFormat
Definition: Types.h:188
std::unordered_map< BlockFile *, bool > BoolBlockFileHash
sampleFormat GetDefaultFormat()
Definition: Project.h:197
An audio file that is referenced (pointed into) directly from an Audacity .aup file rather thna Audac...
Definition: Dependencies.h:24
A BlockFile that refers to data in an existing file.
Definition: BlockFile.h:251
static void GetAllSeqBlocks ( AudacityProject project,
BlockPtrArray outBlocks 
)
static

Definition at line 73 of file Dependencies.cpp.

References TrackListIterator::First(), WaveTrack::GetAllClips(), Sequence::GetBlockArray(), Track::GetKind(), AudacityProject::GetTracks(), TrackListIterator::Next(), and Track::Wave.

Referenced by FindDependencies(), and RemoveDependencies().

75 {
76  TrackList *tracks = project->GetTracks();
77  TrackListIterator iter(tracks);
78  Track *t = iter.First();
79  while (t) {
80  if (t->GetKind() == Track::Wave) {
81  WaveTrack *waveTrack = static_cast<WaveTrack*>(t);
82  for(const auto &clip : waveTrack->GetAllClips()) {
83  Sequence *sequence = clip->GetSequence();
84  BlockArray &blocks = sequence->GetBlockArray();
85  int i;
86  for (i = 0; i < (int)blocks.size(); i++)
87  outBlocks->push_back(&blocks[i]);
88  }
89  }
90  t = iter.Next();
91  }
92 }
A list of TrackListNode items.
Definition: Track.h:619
A WaveTrack contains WaveClip(s). A WaveClip contains a Sequence. A Sequence is primarily an interfac...
Definition: Sequence.h:54
BlockArray & GetBlockArray()
Definition: Sequence.h:194
IteratorRange< AllClipsIterator > GetAllClips()
Definition: WaveTrack.h:435
virtual int GetKind() const
Definition: Track.h:330
A Track that contains audio waveform data.
Definition: WaveTrack.h:60
Fundamental data object of Audacity, placed in the TrackPanel. Classes derived form it include the Wa...
Definition: Track.h:102
An iterator for a TrackList.
Definition: Track.h:402
TrackList * GetTracks()
Definition: Project.h:192
static const wxString kExtraMsgForMissingFiles ( )
static

Definition at line 341 of file Dependencies.cpp.

References _().

Referenced by DependencyDialog::PopulateList().

342 {
343  return
344 _("\n\nFiles shown as MISSING have been moved or deleted and cannot be copied.\
345 \nRestore them to their original location to be able to copy into project.");
346 }
_("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
static const wxString kStdMsg ( )
static

Definition at line 334 of file Dependencies.cpp.

References _().

Referenced by DependencyDialog::PopulateList(), and DependencyDialog::PopulateOrExchange().

335 {
336  return
337 _("Copying these files into your project will remove this dependency.\
338 \nThis is safer, but needs more disk space.");
339 }
_("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
static void RemoveDependencies ( AudacityProject project,
AliasedFileArray aliasedFiles 
)
static

Definition at line 168 of file Dependencies.cpp.

References _(), format, AliasBlockFile::GetAliasedFileName(), GetAllSeqBlocks(), AudacityProject::GetDefaultFormat(), AudacityProject::GetDirManager(), SampleBuffer::ptr(), ReplaceBlockFiles(), SAMPLE_SIZE, Success, and ProgressDialog::Update().

Referenced by DependencyDialog::OnCopySelectedFiles(), and ShowDependencyDialogIfNeeded().

171 {
172  const auto &dirManager = project->GetDirManager();
173 
174  ProgressDialog progress
175  (_("Removing Dependencies"),
176  _("Copying audio data into project..."));
177  auto updateResult = ProgressResult::Success;
178 
179  // Hash aliasedFiles based on their full paths and
180  // count total number of bytes to process.
181  AliasedFileHash aliasedFileHash;
182  wxLongLong totalBytesToProcess = 0;
183  for (auto &aliasedFile : aliasedFiles) {
184  totalBytesToProcess += aliasedFile.mByteCount;
185  const wxString &fileNameStr = aliasedFile.mFileName.GetFullPath();
186  aliasedFileHash[fileNameStr] = &aliasedFile;
187  }
188 
189  BlockPtrArray blocks;
190  GetAllSeqBlocks(project, &blocks);
191 
192  const sampleFormat format = project->GetDefaultFormat();
193  ReplacedBlockFileHash blockFileHash;
194  wxLongLong completedBytes = 0;
195  for (const auto blockFile : blocks) {
196  const auto &f = blockFile->f;
197  if (f->IsAlias() && (blockFileHash.count( &*f ) == 0))
198  {
199  // f is an alias block we have not yet processed.
200  auto aliasBlockFile = static_cast<AliasBlockFile*>( &*f );
201  const wxFileName &fileName = aliasBlockFile->GetAliasedFileName();
202  const wxString &fileNameStr = fileName.GetFullPath();
203 
204  if (aliasedFileHash.count(fileNameStr) == 0)
205  // This aliased file was not selected to be replaced. Skip it.
206  continue;
207 
208  // Convert it from an aliased file to an actual file in the project.
209  auto len = aliasBlockFile->GetLength();
210  BlockFilePtr newBlockFile;
211  {
212  SampleBuffer buffer(len, format);
213  // We tolerate exceptions from NewSimpleBlockFile and so we
214  // can allow exceptions from ReadData too
215  f->ReadData(buffer.ptr(), format, 0, len);
216  newBlockFile =
217  dirManager->NewSimpleBlockFile(buffer.ptr(), len, format);
218  }
219 
220  // Update our hash so we know what block files we've done
221  blockFileHash[ &*f ] = newBlockFile;
222 
223  // Update the progress bar
224  completedBytes += SAMPLE_SIZE(format) * len;
225  updateResult = progress.Update(completedBytes, totalBytesToProcess);
226  if (updateResult != ProgressResult::Success)
227  // leave the project unchanged
228  return;
229  }
230  }
231 
232  // COMMIT OPERATIONS needing NOFAIL-GUARANTEE:
233 
234  // Above, we created a SimpleBlockFile contained in our project
235  // to go with each AliasBlockFile that we wanted to migrate.
236  // However, that didn't actually change any references to these
237  // blockfiles in the Sequences, so we do that next...
238  ReplaceBlockFiles(blocks, blockFileHash);
239 }
ProgressDialog Class.
#define SAMPLE_SIZE(SampleFormat)
Definition: Types.h:198
static void GetAllSeqBlocks(AudacityProject *project, BlockPtrArray *outBlocks)
const std::shared_ptr< DirManager > & GetDirManager()
Definition: Project.cpp:1429
std::shared_ptr< BlockFile > BlockFilePtr
Definition: BlockFile.h:48
std::vector< SeqBlock * > BlockPtrArray
Definition: Sequence.h:52
const wxFileName & GetAliasedFileName() const
Definition: BlockFile.h:278
int format
Definition: ExportPCM.cpp:56
std::unordered_map< wxString, AliasedFile * > AliasedFileHash
sampleFormat
Definition: Types.h:188
sampleFormat GetDefaultFormat()
Definition: Project.h:197
_("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
std::unordered_map< BlockFile *, BlockFilePtr > ReplacedBlockFileHash
A BlockFile that refers to data in an existing file.
Definition: BlockFile.h:251
static void ReplaceBlockFiles(BlockPtrArray &blocks, ReplacedBlockFileHash &hash)
static void ReplaceBlockFiles ( BlockPtrArray blocks,
ReplacedBlockFileHash hash 
)
static

Definition at line 99 of file Dependencies.cpp.

Referenced by RemoveDependencies().

102 {
103  for (const auto &pBlock : blocks) {
104  auto &f = pBlock->f;
105  const auto src = &*f;
106  if (hash.count( src ) > 0) {
107  const auto &dst = hash[src];
108  f = dst;
109  }
110  }
111 }
bool ShowDependencyDialogIfNeeded ( AudacityProject project,
bool  isSaving 
)

Definition at line 597 of file Dependencies.cpp.

References _(), AudacityMessageBox(), FindDependencies(), gPrefs, and RemoveDependencies().

Referenced by AudacityProject::DoSave(), and AudacityProject::OnCheckDependencies().

599 {
600  AliasedFileArray aliasedFiles;
601  FindDependencies(project, aliasedFiles);
602 
603  if (aliasedFiles.empty()) {
604  if (!isSaving)
605  {
606  wxString msg =
607 _("Your project is currently self-contained; it does not depend on any external audio files. \
608 \n\nIf you change the project to a state that has external dependencies on imported \
609 files, it will no longer be self-contained. If you then Save without copying those files in, \
610 you may lose data.");
611  AudacityMessageBox(msg,
612  _("Dependency Check"),
613  wxOK | wxICON_INFORMATION,
614  project);
615  }
616  return true; // Nothing to do.
617  }
618 
619  if (isSaving)
620  {
621  wxString action =
622  gPrefs->Read(
623  wxT("/FileFormats/SaveProjectWithDependencies"),
624  wxT("ask"));
625  if (action == wxT("copy"))
626  {
627  // User always wants to remove dependencies
628  RemoveDependencies(project, aliasedFiles);
629  return true;
630  }
631  if (action == wxT("never"))
632  // User never wants to remove dependencies
633  return true;
634  }
635 
636  DependencyDialog dlog(project, -1, project, aliasedFiles, isSaving);
637  int returnCode = dlog.ShowModal();
638  if (returnCode == wxID_CANCEL)
639  return false;
640  else if (returnCode == wxID_YES)
641  RemoveDependencies(project, aliasedFiles);
642 
643  return true;
644 }
AudacityPrefs * gPrefs
Definition: Prefs.cpp:73
void FindDependencies(AudacityProject *project, AliasedFileArray &outAliasedFiles)
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
static void RemoveDependencies(AudacityProject *project, AliasedFileArray &aliasedFiles)
std::list< AliasedFile > AliasedFileArray
Definition: Dependencies.h:53
DependencyDialog shows dependencies of an AudacityProject on AliasedFile s.
_("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