// get the sum of the sizes of all blocks this track list
// references.  However, if a block is referred to multiple
// times it is only counted once.  Return value is in bytes.
wxLongLong UndoManager::CalculateSpaceUsage(int index)
{
   TrackListOfKindIterator iter(Track::Wave);
   WaveTrack *wt;
   WaveClipList::compatibility_iterator it;
   BlockArray *blocks;
   unsigned int i;

   // get a map of all blocks referenced in this TrackList
   std::map<BlockFile*, wxLongLong> cur;

   wt = (WaveTrack *) iter.First(stack[index]->tracks);
   while (wt) {
      for (it = wt->GetClipIterator(); it; it = it->GetNext()) {
         blocks = it->GetData()->GetSequenceBlockArray();
         for (i = 0; i < blocks->GetCount(); i++) 
         {
            BlockFile* pBlockFile = blocks->Item(i)->f;
            if (pBlockFile->GetFileName().FileExists())
               cur[pBlockFile] = pBlockFile->GetSpaceUsage();
         }
      }
      wt = (WaveTrack *) iter.Next();
   }

   if (index > 0) {
      // get a set of all blocks referenced in all prev TrackList
      std::set<BlockFile*> prev;
      while (--index) {
         wt = (WaveTrack *) iter.First(stack[index]->tracks);
         while (wt) {
            for (it = wt->GetClipIterator(); it; it = it->GetNext()) {
               blocks = it->GetData()->GetSequenceBlockArray();
               for (i = 0; i < blocks->GetCount(); i++) {
                  prev.insert(blocks->Item(i)->f);
               }
            }
            wt = (WaveTrack *) iter.Next();
         }
      }

      // remove all blocks in prevBlockFiles from curBlockFiles
      std::set<BlockFile*>::const_iterator prevIter;
      for (prevIter = prev.begin(); prevIter != prev.end(); prevIter++) {
         cur.erase(*prevIter);
      }
   }

   // sum the sizes of the blocks remaining in curBlockFiles;
   wxLongLong bytes = 0;
   std::map<BlockFile*, wxLongLong>::const_iterator curIter;
   for (curIter = cur.begin(); curIter != cur.end(); curIter++) {
      bytes += curIter->second;
   }

   return bytes;
}
Exemple #2
0
// Find out how much additional space was used to execute
// this operation.
//
// Computed by getting a list of all blocks referenced by
// *this* TrackList and removing all blocks referenced by
// any previous TrackList.
wxLongLong TrackList::GetAdditionalSpaceUsage(UndoStack *stack)
{
   TrackListNode *p;
   // get a map of all blocks referenced in this TrackList
   std::map<BlockFile*,wxLongLong> curBlockFiles;
   for (p = head; p; p = p->next) {
      if (p->t->GetKind() == Track::Wave) {
         WaveTrack* track = ((WaveTrack*)p->t);
         for (WaveClipList::Node* it=track->GetClipIterator(); it; it=it->GetNext())
         {
            WaveClip* clip = it->GetData();
            BlockArray *blocks = clip->GetSequenceBlockArray();
            for (unsigned int i = 0; i < blocks->GetCount(); i++)
               curBlockFiles[blocks->Item(i)->f] = blocks->Item(i)->f->GetSpaceUsage();
         }
      }
   }

   // get a set of all blocks referenced in all prev TrackList
   std::set<BlockFile*> prevBlockFiles;
   unsigned int undoStackIdx = 0;
   for (; undoStackIdx < stack->GetCount(); undoStackIdx++) {
      UndoStackElem *stackElem = stack->Item(undoStackIdx);
      if (stackElem->tracks == this)
         break;
      for (p = stackElem->tracks->head; p; p = p->next) {
         if (p->t->GetKind() == Track::Wave) {
            WaveTrack* track = ((WaveTrack*)p->t);
            for (WaveClipList::Node* it=track->GetClipIterator(); it; it=it->GetNext())
            {
               WaveClip* clip = it->GetData();
               BlockArray *blocks = clip->GetSequenceBlockArray();
               for (unsigned int i = 0; i < blocks->GetCount(); i++)
                  prevBlockFiles.insert(blocks->Item(i)->f);
            }         
         }
      }
   }

   // remove all blocks in prevBlockFiles from curBlockFiles
   std::set<BlockFile*>::const_iterator prevIter = prevBlockFiles.begin();
   for (; prevIter != prevBlockFiles.end(); prevIter++)
      curBlockFiles.erase(*prevIter);

   // sum the sizes of the blocks remaining in curBlockFiles;
   std::map<BlockFile*,wxLongLong>::const_iterator curBfIter =
      curBlockFiles.begin();
   wxLongLong bytes = 0;
   for (;curBfIter != curBlockFiles.end(); curBfIter++)
      bytes += curBfIter->second;

   return bytes;
}
Exemple #3
0
// 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;
}
Exemple #4
0
///by default creates the order of the wavetrack to load.
void ODDecodeTask::Update()
{

   std::vector<ODDecodeBlockFile*> tempBlocks;

   mWaveTrackMutex.Lock();

   for(size_t j=0;j<mWaveTracks.size();j++)
   {
      if(mWaveTracks[j])
      {
         WaveClip *clip;
         BlockArray *blocks;
         Sequence *seq;

         //gather all the blockfiles that we should process in the wavetrack.
         WaveClipList::compatibility_iterator node = mWaveTracks[j]->GetClipIterator();

         while(node) {
            clip = node->GetData();
            seq = clip->GetSequence();
            //TODO:this lock is way to big since the whole file is one sequence.  find a way to break it down.
            seq->LockDeleteUpdateMutex();

            //See Sequence::Delete() for why need this for now..
            blocks = clip->GetSequenceBlockArray();
            int i;
            int insertCursor;

            insertCursor =0;//OD TODO:see if this works, removed from inner loop (bfore was n*n)
            for(i=0; i<(int)blocks->GetCount(); i++)
            {
               //since we have more than one ODBlockFile, we will need type flags to cast.
               if(!blocks->Item(i)->f->IsDataAvailable() && ((ODDecodeBlockFile*)blocks->Item(i)->f)->GetDecodeType()==this->GetODType())
               {
                  blocks->Item(i)->f->Ref();
                  ((ODDecodeBlockFile*)blocks->Item(i)->f)->SetStart(blocks->Item(i)->start);
                  ((ODDecodeBlockFile*)blocks->Item(i)->f)->SetClipOffset((sampleCount)(clip->GetStartTime()*clip->GetRate()));

                  //these will always be linear within a sequence-lets take advantage of this by keeping a cursor.
                  while(insertCursor<(int)tempBlocks.size()&&
                     (sampleCount)(tempBlocks[insertCursor]->GetStart()+tempBlocks[insertCursor]->GetClipOffset()) <
                        (sampleCount)(((ODDecodeBlockFile*)blocks->Item(i)->f)->GetStart()+((ODDecodeBlockFile*)blocks->Item(i)->f)->GetClipOffset()))
                     insertCursor++;

                  tempBlocks.insert(tempBlocks.begin()+insertCursor++,(ODDecodeBlockFile*)blocks->Item(i)->f);
               }
            }

            seq->UnlockDeleteUpdateMutex();
            node = node->GetNext();
         }
      }
   }
   mWaveTrackMutex.Unlock();

   //get the new order.
   OrderBlockFiles(tempBlocks);
}
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]);
         }
      }
   } 
}
Exemple #6
0
// get the sum of the sizes of all blocks this track list
// references.  However, if a block is referred to multiple
// times it is only counted once.  Return value is in bytes
unsigned int TrackList::GetSpaceUsage()
{
   // the map guarantees that I only count each block once
   std::map<BlockFile*,unsigned int> blockFiles;
   for (TrackListNode *p = head; p; p = p->next) {
      if (p->t->GetKind() == Track::Wave) {
         BlockArray *blocks = ((WaveTrack*)p->t)->GetSequence()->GetBlockArray();
         for (unsigned int i = 0; i < blocks->GetCount(); i++)
            blockFiles[blocks->Item(i)->f] = blocks->Item(i)->f->GetSpaceUsage();
      }
   }

   std::map<BlockFile*,unsigned int>::const_iterator bfIter;
   unsigned int bytes = 0;
   for (bfIter = blockFiles.begin(); bfIter != blockFiles.end(); bfIter++)
      bytes += bfIter->second;

   return bytes;
}
///by default creates the order of the wavetrack to load.
void ODComputeSummaryTask::Update()
{

   std::vector<ODPCMAliasBlockFile*> tempBlocks;
   mWaveTrackMutex.Lock();
   if(mWaveTrack)
   {
      WaveClip *clip;
      BlockArray *blocks;
      Sequence *seq;
      
      //gather all the blockfiles that we should process in the wavetrack.
      WaveClipList::Node* node = mWaveTrack->GetClipIterator();
      while(node) {
         clip = node->GetData();
         seq = clip->GetSequence();
         //TODO:this lock is way to big since the whole file is one sequence.  find a way to break it down.
         seq->LockDeleteUpdateMutex();
         
         //See Sequence::Delete() for why need this for now..
         blocks = clip->GetSequenceBlockArray();
         int i;
         for(i=0; i<(int)blocks->GetCount(); i++)
         {
            //in the future if we have more than one ODBlockFile, we will need type flags to cast.
            if(!blocks->Item(i)->f->IsSummaryAvailable())
            {
               blocks->Item(i)->f->Ref();
               ((ODPCMAliasBlockFile*)blocks->Item(i)->f)->SetStart(blocks->Item(i)->start);
               tempBlocks.push_back((ODPCMAliasBlockFile*)blocks->Item(i)->f);
               
            }
         }   
         
         seq->UnlockDeleteUpdateMutex();
         node = node->GetNext();
      }
   }
   mWaveTrackMutex.Unlock();
   
   //get the new order.
   OrderBlockFiles(tempBlocks);
}
// Given an Audacity project and a hash mapping aliased block
// files to un-aliased block files, walk through all of the
// tracks and replace each aliased block file with its replacement.
// Note that this code respects reference-counting and thus the
// process of making a project self-contained is actually undoable.
void ReplaceBlockFiles(AudacityProject *project,
		                 ReplacedBlockFileHash &hash)
{
   DirManager *dirManager = project->GetDirManager();
   BlockArray blocks;
   GetAllSeqBlocks(project, &blocks);

   int i;
   for (i = 0; i < (int)blocks.GetCount(); i++) {
      if (hash.count(blocks[i]->f) > 0) {
         BlockFile *src = blocks[i]->f;
         BlockFile *dst = hash[src];

         dirManager->Deref(src);
         dirManager->Ref(dst);

         blocks[i]->f = dst;
      }
   }
}
// Given a project, returns a single array of all SeqBlocks
// in the current set of tracks.  Enumerating that array allows
// you to process all block files in the current set.
void GetAllSeqBlocks(AudacityProject *project,
                     BlockArray *outBlocks)
{
   TrackList *tracks = project->GetTracks();
   TrackListIterator iter(tracks);
   Track *t = iter.First();
   while (t) {
      if (t->GetKind() == Track::Wave) {
         WaveTrack *waveTrack = (WaveTrack *)t;
         WaveClipList::compatibility_iterator node = waveTrack->GetClipIterator();
         while(node) {
            WaveClip *clip = node->GetData();
            Sequence *sequence = clip->GetSequence();
            BlockArray *blocks = sequence->GetBlockArray();
            int i;
            for (i = 0; i < (int)blocks->GetCount(); i++)
               outBlocks->Add(blocks->Item(i));
            node = node->GetNext();
         }
      }
      t = iter.Next();
   }
}
Exemple #10
0
// get the sum of the sizes of all blocks this track list
// references.  However, if a block is referred to multiple
// times it is only counted once.  Return value is in bytes
wxLongLong TrackList::GetSpaceUsage()
{
   // the map guarantees that I only count each block once
   std::map<BlockFile*,wxLongLong> blockFiles;
   for (TrackListNode *p = head; p; p = p->next) {
      if (p->t->GetKind() == Track::Wave) {
         WaveTrack* track = ((WaveTrack*)p->t);
         for (WaveClipList::Node* it=track->GetClipIterator(); it; it=it->GetNext())
         {
            WaveClip* clip = it->GetData();
            BlockArray *blocks = clip->GetSequenceBlockArray();
            for (unsigned int i = 0; i < blocks->GetCount(); i++)
               blockFiles[blocks->Item(i)->f] = blocks->Item(i)->f->GetSpaceUsage();
         }
      }
   }

   std::map<BlockFile*,wxLongLong>::const_iterator bfIter;
   wxLongLong bytes = 0;
   for (bfIter = blockFiles.begin(); bfIter != blockFiles.end(); bfIter++)
      bytes += bfIter->second;

   return bytes;
}
// 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;
}
Exemple #12
0
// 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;
}
///creates the order of the wavetrack to load.
///by default left to right, or frome the point the user has clicked.
void ODComputeSummaryTask::Update()
{
   std::vector<ODPCMAliasBlockFile*> tempBlocks;

   mWaveTrackMutex.Lock();

   for(size_t j=0;j<mWaveTracks.size();j++)
   {
      if(mWaveTracks[j])
      {
         WaveClip *clip;
         BlockArray *blocks;
         Sequence *seq;

         //gather all the blockfiles that we should process in the wavetrack.
         WaveClipList::compatibility_iterator node = mWaveTracks[j]->GetClipIterator();

         while(node) {
            clip = node->GetData();
            seq = clip->GetSequence();
            //This lock may be way too big since the whole file is one sequence.
            //TODO: test for large files and find a way to break it down.
            seq->LockDeleteUpdateMutex();

            //See Sequence::Delete() for why need this for now..
            //We don't need the mBlockFilesMutex here because it is only for the vector list.
            //These are existing blocks, and its wavetrack or blockfiles won't be deleted because
            //of the respective mWaveTrackMutex lock and LockDeleteUpdateMutex() call.
            blocks = clip->GetSequenceBlockArray();
            int i;
            int insertCursor;

            insertCursor =0;//OD TODO:see if this works, removed from inner loop (bfore was n*n)

            for(i=0; i<(int)blocks->GetCount(); i++)
            {
               //if there is data but no summary, this blockfile needs summarizing.
               if(blocks->Item(i)->f->IsDataAvailable() && !blocks->Item(i)->f->IsSummaryAvailable())
               {
                  blocks->Item(i)->f->Ref();
                  ((ODPCMAliasBlockFile*)blocks->Item(i)->f)->SetStart(blocks->Item(i)->start);
                  ((ODPCMAliasBlockFile*)blocks->Item(i)->f)->SetClipOffset((sampleCount)(clip->GetStartTime()*clip->GetRate()));

                  //these will always be linear within a sequence-lets take advantage of this by keeping a cursor.
                  while(insertCursor<(int)tempBlocks.size()&&
                     (sampleCount)(tempBlocks[insertCursor]->GetStart()+tempBlocks[insertCursor]->GetClipOffset()) <
                        (sampleCount)(((ODPCMAliasBlockFile*)blocks->Item(i)->f)->GetStart()+((ODPCMAliasBlockFile*)blocks->Item(i)->f)->GetClipOffset()))
                     insertCursor++;

                  tempBlocks.insert(tempBlocks.begin()+insertCursor++,(ODPCMAliasBlockFile*)blocks->Item(i)->f);
               }
            }
            seq->UnlockDeleteUpdateMutex();
            node = node->GetNext();
         }
      }
   }
   mWaveTrackMutex.Unlock();

   //get the new order.
   mBlockFilesMutex.Lock();
   OrderBlockFiles(tempBlocks);
   mBlockFilesMutex.Unlock();

   MarkUpdateRan();
}