1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-08-02 17:09:26 +02:00

Fix the reading of autosave files... (#610)

* Fix the reading of autosave files...

... problem was in recreating strings from buffers, but copying too many because
null terminators were lacking.

* Autosave during recording backs up all tracks correctly...

... whether to new track, or appending; and it doesn't lose the other tracks
besides the recording.

It is also unnecessary when just starting to record, so remove one call.
This commit is contained in:
Paul Licameli 2020-07-11 01:49:37 -04:00 committed by GitHub
parent 06f22e942b
commit cea658d9eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 43 deletions

View File

@ -854,10 +854,8 @@ void ProjectAudioManager::OnAudioIORate(int rate)
void ProjectAudioManager::OnAudioIOStartRecording() void ProjectAudioManager::OnAudioIOStartRecording()
{ {
auto &projectFileIO = ProjectFileIO::Get( mProject ); // Auto-save was done here before, but it is unnecessary, provided there
// Before recording is started, auto-save the file. The file will have // are sufficient autosaves when pushing or modifying undo states.
// empty tracks at the bottom where the recording will be put into
projectFileIO.AutoSave();
} }
// This is called after recording has stopped and all tracks have flushed. // This is called after recording has stopped and all tracks have flushed.
@ -931,7 +929,7 @@ void ProjectAudioManager::OnAudioIONewBlockFiles(const WaveTrackArray *tracks)
{ {
auto &project = mProject; auto &project = mProject;
auto &projectFileIO = ProjectFileIO::Get( project ); auto &projectFileIO = ProjectFileIO::Get( project );
projectFileIO.AutoSave(tracks); projectFileIO.AutoSave(true);
} }
void ProjectAudioManager::OnCommitRecording() void ProjectAudioManager::OnCommitRecording()

View File

@ -1059,7 +1059,7 @@ void ProjectFileIO::WriteXMLHeader(XMLWriter &xmlFile) const
xmlFile.Write(wxT(">\n")); xmlFile.Write(wxT(">\n"));
} }
void ProjectFileIO::WriteXML(XMLWriter &xmlFile, const WaveTrackArray *tracks) void ProjectFileIO::WriteXML(XMLWriter &xmlFile, bool recording)
// may throw // may throw
{ {
auto pProject = mpProject.lock(); auto pProject = mpProject.lock();
@ -1092,31 +1092,36 @@ void ProjectFileIO::WriteXML(XMLWriter &xmlFile, const WaveTrackArray *tracks)
tags.WriteXML(xmlFile); tags.WriteXML(xmlFile);
unsigned int ndx = 0; unsigned int ndx = 0;
if (tracks) tracklist.Any().Visit([&](Track *t)
{ {
for (auto track : *tracks) auto useTrack = t;
{ if ( recording ) {
track->WriteXML(xmlFile); // When append-recording, there is a temporary "shadow" track accumulating
// changes and displayed on the screen but it is not yet part of the
// regular track list. That is the one that we want to back up.
// SubstitutePendingChangedTrack() fetches the shadow, if the track has
// one, else it gives the same track back.
useTrack = t->SubstitutePendingChangedTrack().get();
} }
} else if ( useTrack->GetId() == TrackId{} ) {
else // This is a track added during a non-appending recording that is
{ // not yet in the undo history. The UndoManager skips backing it up
tracklist.Any().Visit([&](Track *t) // when pushing. Don't auto-save it.
{ return;
t->WriteXML(xmlFile); }
}); useTrack->WriteXML(xmlFile);
} });
xmlFile.EndTag(wxT("project")); xmlFile.EndTag(wxT("project"));
//TIMER_STOP( xml_writer_timer ); //TIMER_STOP( xml_writer_timer );
} }
bool ProjectFileIO::AutoSave(const WaveTrackArray *tracks) bool ProjectFileIO::AutoSave(bool recording)
{ {
ProjectSerializer autosave; ProjectSerializer autosave;
WriteXMLHeader(autosave); WriteXMLHeader(autosave);
WriteXML(autosave, tracks); WriteXML(autosave, recording);
if (WriteDoc("autosave", autosave)) if (WriteDoc("autosave", autosave))
{ {

View File

@ -72,7 +72,7 @@ public:
void Reset(); void Reset();
bool AutoSave(const WaveTrackArray *tracks = nullptr); bool AutoSave(bool recording = false);
bool AutoSaveDelete(sqlite3 *db = nullptr); bool AutoSaveDelete(sqlite3 *db = nullptr);
bool LoadProject(const FilePath &fileName); bool LoadProject(const FilePath &fileName);
@ -81,7 +81,7 @@ public:
XMLTagHandler *HandleXMLChild(const wxChar *tag) override; XMLTagHandler *HandleXMLChild(const wxChar *tag) override;
void WriteXMLHeader(XMLWriter &xmlFile) const; void WriteXMLHeader(XMLWriter &xmlFile) const;
void WriteXML(XMLWriter &xmlFile, const WaveTrackArray *tracks = nullptr) /* not override */; void WriteXML(XMLWriter &xmlFile, bool recording = false) /* not override */;
wxLongLong GetFreeDiskSpace(); wxLongLong GetFreeDiskSpace();

View File

@ -291,22 +291,27 @@ wxString ProjectSerializer::Decode(const wxMemoryBuffer &buffer, BlockIDs &block
return iter->second; return iter->second;
}; };
auto Convert = [&mCharSize](char *in, int len) -> wxString auto ReadString = [&mCharSize, &in, &bytes](int len) -> wxString
{ {
bytes.reserve( len + 4 );
auto data = bytes.data();
in.Read( data, len );
// Make a null terminator of the widest type
memset( data + len, '\0', 4 );
wxUString str; wxUString str;
switch (mCharSize) switch (mCharSize)
{ {
case 1: case 1:
str.assignFromUTF8(in, len); str.assignFromUTF8(data, len);
break; break;
case 2: case 2:
str.assignFromUTF16((wxChar16 *) in, len / 2); str.assignFromUTF16((wxChar16 *) data, len / 2);
break; break;
case 4: case 4:
str = wxU32CharBuffer::CreateNonOwned((wxChar32 *) in, len / 4); str = wxU32CharBuffer::CreateNonOwned((wxChar32 *) data, len / 4);
break; break;
default: default:
@ -345,10 +350,7 @@ wxString ProjectSerializer::Decode(const wxMemoryBuffer &buffer, BlockIDs &block
in.Read(&id, sizeof(id)); in.Read(&id, sizeof(id));
in.Read(&len, sizeof(len)); in.Read(&len, sizeof(len));
bytes.reserve(len); mIds[id] = ReadString(len);
in.Read(bytes.data(), len);
mIds[id] = Convert(bytes.data(), len);
} }
break; break;
@ -374,10 +376,7 @@ wxString ProjectSerializer::Decode(const wxMemoryBuffer &buffer, BlockIDs &block
in.Read(&id, sizeof(id)); in.Read(&id, sizeof(id));
in.Read(&len, sizeof(len)); in.Read(&len, sizeof(len));
bytes.reserve(len); out.WriteAttr(Lookup(id), ReadString(len));
in.Read(bytes.data(), len);
out.WriteAttr(Lookup(id), Convert(bytes.data(), len));
} }
break; break;
@ -476,10 +475,7 @@ wxString ProjectSerializer::Decode(const wxMemoryBuffer &buffer, BlockIDs &block
int len; int len;
in.Read(&len, sizeof(len)); in.Read(&len, sizeof(len));
bytes.reserve(len); out.WriteData(ReadString(len));
in.Read(bytes.data(), len);
out.WriteData(Convert(bytes.data(), len));
} }
break; break;
@ -488,10 +484,7 @@ wxString ProjectSerializer::Decode(const wxMemoryBuffer &buffer, BlockIDs &block
int len; int len;
in.Read(&len, sizeof(len)); in.Read(&len, sizeof(len));
bytes.reserve(len); out.Write(ReadString(len));
in.Read(bytes.data(), len);
out.Write(Convert(bytes.data(), len));
} }
break; break;