diff --git a/src/HistoryWindow.cpp b/src/HistoryWindow.cpp index 31cd38f6b..c8bd11db7 100644 --- a/src/HistoryWindow.cpp +++ b/src/HistoryWindow.cpp @@ -117,14 +117,7 @@ HistoryWindow::HistoryWindow(AudacityProject *parent, UndoManager *manager): S.EndVerticalLay(); // ----------------------- End of main section -------------- - // Vaughan, 2010-07-30: AudacityProject::OnHistory always calls Show() - // then HistoryWindow::UpdateDisplay, so no need to do it here. - // Vaughan, 2010-10-16: Not on Windows, anyway. - // But Steve reported that on Ubuntu, View > History now crashes, - // so restore it for non-Windows. - #ifdef __WXGTK__ - DoUpdate(); - #endif + DoUpdate(); mList->SetMinSize(mList->GetSize()); Fit(); SetMinSize(GetSize()); @@ -147,6 +140,8 @@ void HistoryWindow::DoUpdate() { int i; + mManager->CalculateSpaceUsage(); + mList->DeleteAllItems(); mSelected = mManager->GetCurrentState() - 1; diff --git a/src/Menus.cpp b/src/Menus.cpp index ad0429a13..19dbebdfa 100644 --- a/src/Menus.cpp +++ b/src/Menus.cpp @@ -5133,7 +5133,6 @@ void AudacityProject::OnHistory() mHistoryWindow = new HistoryWindow(this, &mUndoManager); mHistoryWindow->Show(); mHistoryWindow->Raise(); - mHistoryWindow->UpdateDisplay(); } void AudacityProject::OnKaraoke() diff --git a/src/Project.cpp b/src/Project.cpp index 0fa217315..85d88e4f7 100644 --- a/src/Project.cpp +++ b/src/Project.cpp @@ -4625,17 +4625,16 @@ void AudacityProject::AutoSave() wxString fn = wxFileName(FileNames::AutoSaveDir(), projName + wxString(wxT(" - ")) + CreateUniqueName()).GetFullPath(); - XMLFileWriter saveFile; - try { - saveFile.Open(fn + wxT(".tmp"), wxT("wb")); + XMLStringWriter buffer(1024 * 1024); + VarSetter setter(&mAutoSaving, true, false); + WriteXMLHeader(buffer); + WriteXML(buffer); - { - VarSetter setter(&mAutoSaving, true, false); - WriteXMLHeader(saveFile); - WriteXML(saveFile); - } + XMLFileWriter saveFile; + saveFile.Open(fn + wxT(".tmp"), wxT("wb")); + saveFile.WriteSubTree(buffer); // JKC Calling XMLFileWriter::Close will close the scope. // We certainly don't want to do that, if we're doing recordingrecovery, diff --git a/src/Project.h b/src/Project.h index e61044797..e36d60671 100644 --- a/src/Project.h +++ b/src/Project.h @@ -443,7 +443,7 @@ class AUDACITY_DLL_API AudacityProject: public wxFrame, static void AllProjectsDeleteUnlock(); void PushState(wxString desc, wxString shortDesc, - int flags = PUSH_AUTOSAVE | PUSH_CALC_SPACE); + int flags = PUSH_AUTOSAVE); private: diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 625380ebd..36f035bca 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -3033,7 +3033,7 @@ void TrackPanel::Stretch(int mouseXCoordinate, int trackLeftEdge, break; } MakeParentPushState(_("Stretch Note Track"), _("Stretch"), - PUSH_CONSOLIDATE | PUSH_AUTOSAVE | PUSH_CALC_SPACE); + PUSH_CONSOLIDATE | PUSH_AUTOSAVE); mStretched = true; Refresh(false); } @@ -3620,7 +3620,7 @@ void TrackPanel::HandleSlide(wxMouseEvent & event) consolidate = true; } MakeParentPushState(msg, _("Time-Shift"), - consolidate ? (PUSH_CONSOLIDATE) : (PUSH_AUTOSAVE|PUSH_CALC_SPACE)); + consolidate ? (PUSH_CONSOLIDATE) : (PUSH_AUTOSAVE)); } } @@ -4886,7 +4886,7 @@ void TrackPanel::HandleSampleEditingButtonUp( wxMouseEvent & WXUNUSED(event)) mDrawingTrack=NULL; //Set this to NULL so it will catch improper drag events. MakeParentPushState(_("Moved Sample"), _("Sample Edit"), - PUSH_CONSOLIDATE|PUSH_AUTOSAVE|PUSH_CALC_SPACE); + PUSH_CONSOLIDATE|PUSH_AUTOSAVE); } @@ -6259,7 +6259,7 @@ bool TrackPanel::HandleTrackLocationMouseEvent(WaveTrack * track, wxRect &r, wxM !linked->MergeClips(mCapturedTrackLocation.clipidx1, mCapturedTrackLocation.clipidx2)) return false; - MakeParentPushState(_("Merged Clips"),_("Merge"), PUSH_CONSOLIDATE|PUSH_CALC_SPACE); + MakeParentPushState(_("Merged Clips"),_("Merge"), PUSH_CONSOLIDATE); handled = true; } } diff --git a/src/TrackPanel.h b/src/TrackPanel.h index 86b704045..7bd95b8fc 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -437,7 +437,7 @@ protected: // AS: Pushing the state preserves state for Undo operations. virtual void MakeParentPushState(wxString desc, wxString shortDesc, - int flags = PUSH_AUTOSAVE | PUSH_CALC_SPACE); + int flags = PUSH_AUTOSAVE); virtual void MakeParentModifyState(bool bWantsAutoSave); // if true, writes auto-save file. Should set only if you really want the state change restored after // a crash, as it can take many seconds for large (eg. 10 track-hours) projects virtual void MakeParentResize(); diff --git a/src/TrackPanelListener.h b/src/TrackPanelListener.h index 172106beb..6a2650ff1 100644 --- a/src/TrackPanelListener.h +++ b/src/TrackPanelListener.h @@ -29,7 +29,7 @@ class AUDACITY_DLL_API TrackPanelListener { virtual void TP_OnPlayKey() = 0; virtual void TP_PushState(wxString shortDesc, wxString longDesc, - int flags = PUSH_AUTOSAVE | PUSH_CALC_SPACE) = 0; + int flags = PUSH_AUTOSAVE) = 0; virtual void TP_ModifyState(bool bWantsAutoSave) = 0; // if true, writes auto-save file. Should set only if you really want the state change restored after // a crash, as it can take many seconds for large (eg. 10 track-hours) projects virtual void TP_RedrawScrollbars() = 0; diff --git a/src/UndoManager.cpp b/src/UndoManager.cpp index 50b15d478..0b92fc907 100644 --- a/src/UndoManager.cpp +++ b/src/UndoManager.cpp @@ -22,6 +22,8 @@ UndoManager #include "Audacity.h" +#include + #include "BlockFile.h" #include "Internat.h" #include "Sequence.h" @@ -29,11 +31,10 @@ UndoManager #include "WaveTrack.h" // temp #include "NoteTrack.h" // for Sonify* function declarations -#include -#include - #include "UndoManager.h" +WX_DECLARE_HASH_SET(BlockFile *, wxPointerHash, wxPointerEqual, Set ); + UndoManager::UndoManager() { current = -1; @@ -47,65 +48,60 @@ UndoManager::~UndoManager() ClearStates(); } -// 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) +void UndoManager::CalculateSpaceUsage() { 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 cur; + space.Clear(); + space.Add(0, stack.GetCount()); - 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++) + Set *prev = new Set; + Set *cur = new Set; + + for (size_t i = 0, cnt = stack.GetCount(); i < cnt; i++) + { + // Swap map pointers + Set *swap = prev; + prev = cur; + cur = swap; + + // And clean out the new current map + cur->clear(); + + // Scan all tracks at current level + WaveTrack *wt = (WaveTrack *) iter.First(stack[i]->tracks); + while (wt) + { + // Scan all clips within current track + WaveClipList::compatibility_iterator it = wt->GetClipIterator(); + while (it) { - BlockFile* pBlockFile = blocks->Item(i)->f; - if (pBlockFile->GetFileName().FileExists()) - cur[pBlockFile] = pBlockFile->GetSpaceUsage(); - } - } - wt = (WaveTrack *) iter.Next(); - } + // Scan all blockfiles within current clip + BlockArray *blocks = it->GetData()->GetSequenceBlockArray(); + for (size_t b = 0, cnt = blocks->GetCount(); b < cnt; b++) + { + BlockFile *file = blocks->Item(b)->f; - if (index > 0) { - // get a set of all blocks referenced in all prev TrackList - std::set 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); + // Accumulate space used by the file if the file didn't exist + // in the previous level + if (!prev->count(file)) + { + space[i] += file->GetSpaceUsage().GetValue(); } + + // Add file to current set + cur->insert(file); } - wt = (WaveTrack *) iter.Next(); + + it = it->GetNext(); } - } - // remove all blocks in prevBlockFiles from curBlockFiles - std::set::const_iterator prevIter; - for (prevIter = prev.begin(); prevIter != prev.end(); prevIter++) { - cur.erase(*prevIter); + wt = (WaveTrack *) iter.Next(); } } - // sum the sizes of the blocks remaining in curBlockFiles; - wxLongLong bytes = 0; - std::map::const_iterator curIter; - for (curIter = cur.begin(); curIter != cur.end(); curIter++) { - bytes += curIter->second; - } - - return bytes; + delete cur; + delete prev; } void UndoManager::GetLongDescription(unsigned int n, wxString *desc, @@ -114,10 +110,11 @@ void UndoManager::GetLongDescription(unsigned int n, wxString *desc, n -= 1; // 1 based to zero based wxASSERT(n < stack.Count()); + wxASSERT(space.Count() == stack.Count()); *desc = stack[n]->description; - *size = Internat::FormatSize(stack[n]->spaceUsage); + *size = Internat::FormatSize(space[n]); } void UndoManager::GetShortDescription(unsigned int n, wxString *desc) @@ -252,12 +249,9 @@ void UndoManager::PushState(TrackList * l, push->selectedRegion = selectedRegion; push->description = longDescription; push->shortDescription = shortDescription; - push->spaceUsage = 0; // Calculate actual value after it's on the stack. stack.Add(push); current++; - if( (flags&PUSH_CALC_SPACE)!=0) - push->spaceUsage = this->CalculateSpaceUsage(current); if (saved >= current) { saved = -1; diff --git a/src/UndoManager.h b/src/UndoManager.h index d30b438f5..5eb3ef80b 100644 --- a/src/UndoManager.h +++ b/src/UndoManager.h @@ -61,18 +61,17 @@ struct UndoStackElem { wxString description; wxString shortDescription; SelectedRegion selectedRegion; - wxLongLong spaceUsage; }; WX_DEFINE_USER_EXPORTED_ARRAY(UndoStackElem *, UndoStack, class AUDACITY_DLL_API); +WX_DEFINE_USER_EXPORTED_ARRAY_SIZE_T(size_t, SpaceArray, class AUDACITY_DLL_API); // These flags control what extra to do on a PushState -// Default is PUSH_AUTOSAVE | PUSH_CALC_SPACE +// Default is PUSH_AUTOSAVE // Frequent/faster actions use PUSH_CONSOLIDATE const int PUSH_MINIMAL = 0; const int PUSH_CONSOLIDATE = 1; -const int PUSH_CALC_SPACE = 2; -const int PUSH_AUTOSAVE = 4; +const int PUSH_AUTOSAVE = 2; class AUDACITY_DLL_API UndoManager { public: @@ -82,7 +81,7 @@ class AUDACITY_DLL_API UndoManager { void PushState(TrackList * l, const SelectedRegion &selectedRegion, wxString longDescription, wxString shortDescription, - int flags = PUSH_CALC_SPACE|PUSH_AUTOSAVE ); + int flags = PUSH_AUTOSAVE); void ModifyState(TrackList * l, const SelectedRegion &selectedRegion); void ClearStates(); @@ -105,6 +104,8 @@ class AUDACITY_DLL_API UndoManager { bool UnsavedChanges(); void StateSaved(); + void CalculateSpaceUsage(); + // void Debug(); // currently unused ///to mark as unsaved changes without changing the state/tracks. @@ -113,8 +114,6 @@ class AUDACITY_DLL_API UndoManager { void ResetODChangesFlag(); private: - wxLongLong CalculateSpaceUsage(int index); - int current; int saved; UndoStack stack; @@ -122,6 +121,8 @@ class AUDACITY_DLL_API UndoManager { wxString lastAction; int consolidationCount; + SpaceArray space; + bool mODChanges; ODLock mODChangesMutex;//mODChanges is accessed from many threads. diff --git a/src/blockfile/SimpleBlockFile.cpp b/src/blockfile/SimpleBlockFile.cpp index 6c23af7fe..96d029f93 100644 --- a/src/blockfile/SimpleBlockFile.cpp +++ b/src/blockfile/SimpleBlockFile.cpp @@ -543,8 +543,7 @@ wxLongLong SimpleBlockFile::GetSpaceUsage() return 0; } else { - wxFFile dataFile(mFileName.GetFullPath()); - return dataFile.Length(); + return sizeof(auHeader) + mSummaryInfo.totalSummaryBytes + (GetLength() * SAMPLE_SIZE(floatSample)); } } diff --git a/src/xml/XMLWriter.cpp b/src/xml/XMLWriter.cpp index 0347d73bc..d3bcc5a40 100644 --- a/src/xml/XMLWriter.cpp +++ b/src/xml/XMLWriter.cpp @@ -310,8 +310,12 @@ void XMLFileWriter::Write(const wxString &data) /// /// XMLStringWriter class /// -XMLStringWriter::XMLStringWriter() +XMLStringWriter::XMLStringWriter(size_t initialSize) { + if (initialSize) + { + Alloc(initialSize); + } } XMLStringWriter::~XMLStringWriter() diff --git a/src/xml/XMLWriter.h b/src/xml/XMLWriter.h index f3ad45670..e28aa26e9 100644 --- a/src/xml/XMLWriter.h +++ b/src/xml/XMLWriter.h @@ -103,7 +103,7 @@ class XMLStringWriter:public wxString, public XMLWriter { public: - XMLStringWriter(); + XMLStringWriter(size_t initialSize = 0); virtual ~XMLStringWriter(); void Write(const wxString &data);