1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-14 15:48:21 +02:00

Save lossless copy of project

This commit is contained in:
Steve Daulton 2018-05-14 21:09:07 +01:00
parent 30f1fa58a1
commit 419ecd411d
4 changed files with 196 additions and 159 deletions

@ -338,14 +338,22 @@ void AudacityProject::CreateMenusAndCommands()
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
c->AddSeparator();
c->AddItem(wxT("Close"), XXO("&Close"), FN(OnClose), wxT("Ctrl+W")); c->AddItem(wxT("Close"), XXO("&Close"), FN(OnClose), wxT("Ctrl+W"));
c->AddSeparator();
c->BeginSubMenu( _("&Save Project") );
c->AddItem(wxT("Save"), XXO("&Save Project"), FN(OnSave), wxT("Ctrl+S"), c->AddItem(wxT("Save"), XXO("&Save Project"), FN(OnSave), wxT("Ctrl+S"),
AudioIONotBusyFlag | UnsavedChangesFlag, AudioIONotBusyFlag | UnsavedChangesFlag,
AudioIONotBusyFlag | UnsavedChangesFlag); AudioIONotBusyFlag | UnsavedChangesFlag);
c->AddItem(wxT("SaveAs"), XXO("Save Project &As..."), FN(OnSaveAs)); c->AddItem(wxT("SaveAs"), XXO("Save Project &As..."), FN(OnSaveAs));
// TODO: The next two items should be disabled if project is empty
c->AddItem(wxT("SaveCopy"), XXO("Save Lossless Copy of Project..."), FN(OnSaveCopy));
#ifdef USE_LIBVORBIS
c->AddItem(wxT("SaveCompressed"), XXO("&Save Compressed Copy of Project..."), FN(OnSaveCompressed));
#endif
c->EndSubMenu();
c->AddSeparator();
c->BeginSubMenu( _("&Export") ); c->BeginSubMenu( _("&Export") );
@ -382,13 +390,9 @@ void AudacityProject::CreateMenusAndCommands()
c->AddItem(wxT("ExportMIDI"), XXO("Export MI&DI..."), FN(OnExportMIDI), c->AddItem(wxT("ExportMIDI"), XXO("Export MI&DI..."), FN(OnExportMIDI),
AudioIONotBusyFlag | NoteTracksExistFlag, AudioIONotBusyFlag | NoteTracksExistFlag,
AudioIONotBusyFlag | NoteTracksExistFlag); AudioIONotBusyFlag | NoteTracksExistFlag);
#endif
#ifdef USE_LIBVORBIS
c->AddSeparator();
c->AddItem(wxT("SaveCompressed"), XXO("&Save Compressed Copy of Project..."), FN(OnSaveCompressed));
#endif #endif
c->EndSubMenu(); c->EndSubMenu();
c->AddSeparator();
c->BeginSubMenu(_("&Import")); c->BeginSubMenu(_("&Import"));
c->AddItem(wxT("ImportAudio"), XXO("&Audio..."), FN(OnImport), wxT("Ctrl+Shift+I")); c->AddItem(wxT("ImportAudio"), XXO("&Audio..."), FN(OnImport), wxT("Ctrl+Shift+I"));
@ -4736,6 +4740,11 @@ void AudacityProject::OnSaveAs(const CommandContext &WXUNUSED(context) )
SaveAs(); SaveAs();
} }
void AudacityProject::OnSaveCopy(const CommandContext &WXUNUSED(context) )
{
SaveAs(true, true);
}
#ifdef USE_LIBVORBIS #ifdef USE_LIBVORBIS
void AudacityProject::OnSaveCompressed(const CommandContext &WXUNUSED(context) ) void AudacityProject::OnSaveCompressed(const CommandContext &WXUNUSED(context) )
{ {

@ -220,6 +220,7 @@ void OnOpen(const CommandContext &context );
void OnClose(const CommandContext &context ); void OnClose(const CommandContext &context );
void OnSave(const CommandContext &context ); void OnSave(const CommandContext &context );
void OnSaveAs(const CommandContext &context ); void OnSaveAs(const CommandContext &context );
void OnSaveCopy(const CommandContext &context );
#ifdef USE_LIBVORBIS #ifdef USE_LIBVORBIS
void OnSaveCompressed(const CommandContext &context ); void OnSaveCompressed(const CommandContext &context );
#endif #endif

@ -3733,7 +3733,7 @@ void AudacityProject::WriteXMLHeader(XMLWriter &xmlFile) const
xmlFile.Write(wxT(">\n")); xmlFile.Write(wxT(">\n"));
} }
void AudacityProject::WriteXML(XMLWriter &xmlFile, bool bWantSaveCompressed) void AudacityProject::WriteXML(XMLWriter &xmlFile, bool bWantSaveCopy)
// may throw // may throw
{ {
//TIMER_START( "AudacityProject::WriteXML", xml_writer_timer ); //TIMER_START( "AudacityProject::WriteXML", xml_writer_timer );
@ -3787,7 +3787,7 @@ void AudacityProject::WriteXML(XMLWriter &xmlFile, bool bWantSaveCompressed)
t = iter.First(); t = iter.First();
unsigned int ndx = 0; unsigned int ndx = 0;
while (t) { while (t) {
if ((t->GetKind() == Track::Wave) && bWantSaveCompressed) if ((t->GetKind() == Track::Wave) && bWantSaveCopy)
{ {
auto wt = static_cast<const WaveTrack *>(t); auto wt = static_cast<const WaveTrack *>(t);
@ -3882,16 +3882,17 @@ bool AudacityProject::Save()
// Assumes AudacityProject::mFileName has been set to the desired path. // Assumes AudacityProject::mFileName has been set to the desired path.
bool AudacityProject::DoSave bool AudacityProject::DoSave (const bool fromSaveAs,
(const bool fromSaveAs, const bool bWantSaveCompressed) const bool bWantSaveCopy,
const bool bLossless /*= false*/)
{ {
// See explanation above // See explanation above
// ProjectDisabler disabler(this); // ProjectDisabler disabler(this);
wxASSERT_MSG(!bWantSaveCompressed || fromSaveAs, "Compressed SHOULD only be availabele from SaveAs"); wxASSERT_MSG(!bWantSaveCopy || fromSaveAs, "Copy Project SHOULD only be availabele from SaveAs");
// Some confirmation dialogs // Some confirmation dialogs
if (!bWantSaveCompressed) if (!bWantSaveCopy)
{ {
TrackListIterator iter(GetTracks()); TrackListIterator iter(GetTracks());
bool bHasTracks = (iter.First() != NULL); bool bHasTracks = (iter.First() != NULL);
@ -3991,16 +3992,13 @@ bool AudacityProject::DoSave
return (success = false); return (success = false);
} }
if (bWantSaveCompressed) if (bWantSaveCopy)
{ {
// Do this before saving the .aup, because we accumulate // Do this before saving the .aup, because we accumulate
// mStrOtherNamesArray which affects the contents of the .aup // mStrOtherNamesArray which affects the contents of the .aup
//v Move this condition into SaveCompressedWaveTracks() if want to support other formats. // This populates the array mStrOtherNamesArray
#ifdef USE_LIBVORBIS success = this->SaveCopyWaveTracks(project, bLossless);
// This populates the array mStrOtherNamesArray
success = this->SaveCompressedWaveTracks(project);
#endif
} }
if (!success) if (!success)
@ -4016,7 +4014,7 @@ bool AudacityProject::DoSave
XMLFileWriter saveFile{ mFileName, _("Error Saving Project") }; XMLFileWriter saveFile{ mFileName, _("Error Saving Project") };
success = GuardedCall< bool >( [&] { success = GuardedCall< bool >( [&] {
WriteXMLHeader(saveFile); WriteXMLHeader(saveFile);
WriteXML(saveFile, bWantSaveCompressed); WriteXML(saveFile, bWantSaveCopy);
// Flushes files, forcing space exhaustion errors before trying // Flushes files, forcing space exhaustion errors before trying
// SetProject(): // SetProject():
saveFile.PreCommit(); saveFile.PreCommit();
@ -4031,7 +4029,7 @@ bool AudacityProject::DoSave
if (!success) if (!success)
return false; return false;
if (fromSaveAs && !bWantSaveCompressed) { if (fromSaveAs && !bWantSaveCopy) {
// We are about to move files from the current directory to // We are about to move files from the current directory to
// the NEW directory. We need to make sure files that belonged // the NEW directory. We need to make sure files that belonged
// to the last saved project don't get erased, so we "lock" them, so that // to the last saved project don't get erased, so we "lock" them, so that
@ -4078,7 +4076,7 @@ bool AudacityProject::DoSave
// SAVE HAS SUCCEEDED -- following are further no-fail commit operations. // SAVE HAS SUCCEEDED -- following are further no-fail commit operations.
if ( !bWantSaveCompressed ) if ( !bWantSaveCopy )
{ {
// Now that we have saved the file, we can DELETE the auto-saved version // Now that we have saved the file, we can DELETE the auto-saved version
DeleteCurrentAutoSaveFile(); DeleteCurrentAutoSaveFile();
@ -4137,111 +4135,124 @@ bool AudacityProject::DoSave
return true; return true;
} }
bool AudacityProject::SaveCopyWaveTracks(const wxString & strProjectPathName,
const bool bLossless /*= false*/)
{
wxString extension, fileFormat;
#ifdef USE_LIBVORBIS #ifdef USE_LIBVORBIS
bool AudacityProject::SaveCompressedWaveTracks(const wxString & strProjectPathName) // full path for aup except extension if (bLossless) {
{ extension = wxT("wav");
// Some of this is similar to code in ExportMultiple::ExportMultipleByTrack fileFormat = wxT("WAVFLT");
// but that code is really tied into the dialogs. } else {
extension = wxT("ogg");
// Copy the tracks because we're going to do some state changes before exporting. fileFormat = wxT("OGG");
Track* pTrack;
WaveTrack* pWaveTrack;
TrackListOfKindIterator iter(Track::Wave, GetTracks());
unsigned int numWaveTracks = 0;
auto ppSavedTrackList = TrackList::Create();
auto &pSavedTrackList = *ppSavedTrackList;
for (pTrack = iter.First(); pTrack != NULL; pTrack = iter.Next())
{
numWaveTracks++;
pWaveTrack = (WaveTrack*)pTrack;
pSavedTrackList.Add(mTrackFactory->DuplicateWaveTrack(*pWaveTrack));
}
auto cleanup = finally( [&] {
// Restore the saved track states and clean up.
TrackListIterator savedTrackIter(&pSavedTrackList);
Track *pSavedTrack;
for (pTrack = iter.First(), pSavedTrack = savedTrackIter.First();
((pTrack != NULL) && (pSavedTrack != NULL));
pTrack = iter.Next(), pSavedTrack = savedTrackIter.Next())
{
pWaveTrack = static_cast<WaveTrack*>(pTrack);
auto pSavedWaveTrack = static_cast<const WaveTrack*>(pSavedTrack);
pWaveTrack->SetSelected(pSavedTrack->GetSelected());
pWaveTrack->SetMute(pSavedWaveTrack->GetMute());
pWaveTrack->SetSolo(pSavedWaveTrack->GetSolo());
pWaveTrack->SetGain(((WaveTrack*)pSavedTrack)->GetGain());
pWaveTrack->SetPan(((WaveTrack*)pSavedTrack)->GetPan());
}
} );
if (numWaveTracks == 0)
// Nothing to save compressed => success. Delete the copies and go.
return true;
// Okay, now some bold state-faking to default values.
for (pTrack = iter.First(); pTrack != NULL; pTrack = iter.Next())
{
pWaveTrack = (WaveTrack*)pTrack;
pWaveTrack->SetSelected(false);
pWaveTrack->SetMute(false);
pWaveTrack->SetSolo(false);
pWaveTrack->SetGain(1.0);
pWaveTrack->SetPan(0.0);
}
wxString strDataDirPathName = strProjectPathName + wxT("_data");
if (!wxFileName::DirExists(strDataDirPathName) &&
!wxFileName::Mkdir(strDataDirPathName, 0777, wxPATH_MKDIR_FULL))
return false;
strDataDirPathName += wxFileName::GetPathSeparator();
// Export all WaveTracks to OGG.
bool bSuccess = true;
// This accumulates the names of the .ogg files, to be written as
// dependencies in the .aup file
mStrOtherNamesArray.clear();
Exporter theExporter;
Track* pRightTrack;
wxFileName uniqueTrackFileName;
for (pTrack = iter.First(); ((pTrack != NULL) && bSuccess); pTrack = iter.Next())
{
if (pTrack->GetKind() == Track::Wave)
{
SelectionStateChanger changer{ GetSelectionState(), *GetTracks() };
pTrack->SetSelected(true);
if (pTrack->GetLinked())
{
pRightTrack = iter.Next();
pRightTrack->SetSelected(true);
}
else
pRightTrack = NULL;
uniqueTrackFileName = wxFileName(strDataDirPathName, pTrack->GetName(), wxT("ogg"));
FileNames::MakeNameUnique(mStrOtherNamesArray, uniqueTrackFileName);
bSuccess =
theExporter.Process(this, pRightTrack ? 2 : 1,
wxT("OGG"), uniqueTrackFileName.GetFullPath(), true,
pTrack->GetStartTime(), pTrack->GetEndTime());
if (!bSuccess)
// If only some exports succeed, the cleanup is not done here
// but trusted to the caller
break;
}
}
return bSuccess;
} }
#else
extension = wxT("wav");
fileFormat = wxT("WAVFLT");
#endif #endif
// Some of this is similar to code in ExportMultiple::ExportMultipleByTrack
// but that code is really tied into the dialogs.
// Copy the tracks because we're going to do some state changes before exporting.
Track* pTrack;
WaveTrack* pWaveTrack;
TrackListOfKindIterator iter(Track::Wave, GetTracks());
unsigned int numWaveTracks = 0;
auto ppSavedTrackList = TrackList::Create();
auto &pSavedTrackList = *ppSavedTrackList;
for (pTrack = iter.First(); pTrack != NULL; pTrack = iter.Next())
{
numWaveTracks++;
pWaveTrack = (WaveTrack*)pTrack;
pSavedTrackList.Add(mTrackFactory->DuplicateWaveTrack(*pWaveTrack));
}
auto cleanup = finally( [&] {
// Restore the saved track states and clean up.
TrackListIterator savedTrackIter(&pSavedTrackList);
Track *pSavedTrack;
for (pTrack = iter.First(), pSavedTrack = savedTrackIter.First();
((pTrack != NULL) && (pSavedTrack != NULL));
pTrack = iter.Next(), pSavedTrack = savedTrackIter.Next())
{
pWaveTrack = static_cast<WaveTrack*>(pTrack);
auto pSavedWaveTrack = static_cast<const WaveTrack*>(pSavedTrack);
pWaveTrack->SetSelected(pSavedTrack->GetSelected());
pWaveTrack->SetMute(pSavedWaveTrack->GetMute());
pWaveTrack->SetSolo(pSavedWaveTrack->GetSolo());
pWaveTrack->SetGain(((WaveTrack*)pSavedTrack)->GetGain());
pWaveTrack->SetPan(((WaveTrack*)pSavedTrack)->GetPan());
}
} );
if (numWaveTracks == 0)
// Nothing to save compressed => success. Delete the copies and go.
return true;
// Okay, now some bold state-faking to default values.
for (pTrack = iter.First(); pTrack != NULL; pTrack = iter.Next())
{
pWaveTrack = (WaveTrack*)pTrack;
pWaveTrack->SetSelected(false);
pWaveTrack->SetMute(false);
pWaveTrack->SetSolo(false);
pWaveTrack->SetGain(1.0);
pWaveTrack->SetPan(0.0);
}
wxString strDataDirPathName = strProjectPathName + wxT("_data");
if (!wxFileName::DirExists(strDataDirPathName) &&
!wxFileName::Mkdir(strDataDirPathName, 0777, wxPATH_MKDIR_FULL))
return false;
strDataDirPathName += wxFileName::GetPathSeparator();
// Export all WaveTracks to OGG.
bool bSuccess = true;
// This accumulates the names of the track files, to be written as
// dependencies in the .aup file
mStrOtherNamesArray.clear();
Exporter theExporter;
Track* pRightTrack;
wxFileName uniqueTrackFileName;
for (pTrack = iter.First(); ((pTrack != NULL) && bSuccess); pTrack = iter.Next())
{
if (pTrack->GetKind() == Track::Wave)
{
SelectionStateChanger changer{ GetSelectionState(), *GetTracks() };
pTrack->SetSelected(true);
if (pTrack->GetLinked())
{
pRightTrack = iter.Next();
pRightTrack->SetSelected(true);
}
else
pRightTrack = NULL;
uniqueTrackFileName = wxFileName(strDataDirPathName, pTrack->GetName(), extension);
FileNames::MakeNameUnique(mStrOtherNamesArray, uniqueTrackFileName);
bSuccess =
theExporter.Process(this, pRightTrack ? 2 : 1,
fileFormat, uniqueTrackFileName.GetFullPath(), true,
pTrack->GetStartTime(), pTrack->GetEndTime());
if (!bSuccess)
// If only some exports succeed, the cleanup is not done here
// but trusted to the caller
break;
}
}
return bSuccess;
}
std::vector< std::shared_ptr< Track > > std::vector< std::shared_ptr< Track > >
@ -4410,7 +4421,7 @@ bool AudacityProject::Import(const wxString &fileName, WaveTrackArray* pTrackArr
return true; return true;
} }
bool AudacityProject::SaveAs(const wxString & newFileName, bool bWantSaveCompressed /*= false*/, bool addToHistory /*= true*/) bool AudacityProject::SaveAs(const wxString & newFileName, bool bWantSaveCopy /*= false*/, bool addToHistory /*= true*/)
{ {
// This version of SaveAs is invoked only from scripting and does not // This version of SaveAs is invoked only from scripting and does not
// prompt for a file name // prompt for a file name
@ -4433,7 +4444,7 @@ bool AudacityProject::SaveAs(const wxString & newFileName, bool bWantSaveCompres
mFileName = newFileName; mFileName = newFileName;
bool success = false; bool success = false;
auto cleanup = finally( [&] { auto cleanup = finally( [&] {
if (!success || bWantSaveCompressed) if (!success || bWantSaveCopy)
// Restore file name on error // Restore file name on error
mFileName = oldFileName; mFileName = oldFileName;
} ); } );
@ -4441,12 +4452,12 @@ bool AudacityProject::SaveAs(const wxString & newFileName, bool bWantSaveCompres
//Don't change the title, unless we succeed. //Don't change the title, unless we succeed.
//SetProjectTitle(); //SetProjectTitle();
success = DoSave(!bOwnsNewAupName || bWantSaveCompressed, bWantSaveCompressed); success = DoSave(!bOwnsNewAupName || bWantSaveCopy, bWantSaveCopy);
if (success && addToHistory) { if (success && addToHistory) {
wxGetApp().AddFileToHistory(mFileName); wxGetApp().AddFileToHistory(mFileName);
} }
if (!success || bWantSaveCompressed) // bWantSaveCompressed doesn't actually change current project. if (!success || bWantSaveCopy) // bWantSaveCopy doesn't actually change current project.
{ {
} }
else { else {
@ -4458,43 +4469,59 @@ bool AudacityProject::SaveAs(const wxString & newFileName, bool bWantSaveCompres
} }
bool AudacityProject::SaveAs(bool bWantSaveCompressed /*= false*/) bool AudacityProject::SaveAs(bool bWantSaveCopy /*= false*/, bool bLossless /*= false*/)
{ {
TitleRestorer Restorer(this); // RAII TitleRestorer Restorer(this); // RAII
bool bHasPath = true; bool bHasPath = true;
wxFileName filename(mFileName); wxFileName filename(mFileName);
// Save a copy of the project with 32-bit float tracks.
if (bLossless)
bWantSaveCopy = true;
// Bug 1304: Set a default file path if none was given. For Save/SaveAs // Bug 1304: Set a default file path if none was given. For Save/SaveAs
if( filename.GetFullPath().IsEmpty() ){ if( filename.GetFullPath().IsEmpty() ){
bHasPath = false; bHasPath = false;
filename = FileNames::DefaultToDocumentsFolder(wxT("/SaveAs/Path")); filename = FileNames::DefaultToDocumentsFolder(wxT("/SaveAs/Path"));
} }
wxString sDialogTitle; wxString title;
if (bWantSaveCompressed) wxString message;
if (bWantSaveCopy)
{ {
if (ShowWarningDialog(this, wxT("FirstProjectSave"), if (bLossless)
_("\ {
'Save Compressed Project' is for an Audacity project, not an audio file.\n\ title = wxString::Format(_("%sSave Lossless Copy of Project \"%s\" As..."),
Restorer.sProjNumber,Restorer.sProjName);
message = _("\
'Save Lossless Copy of Project' is for an Audacity project, not an audio file.\n\
For an audio file that will open in other apps, use 'Export'.\n\n\
\
Lossless copies of project are a good way to backup your project, \n\
with no loss of quality, but the projects are large.\n");
}
else
{
title = wxString::Format(_("%sSave Compressed Copy of Project \"%s\" As..."),
Restorer.sProjNumber,Restorer.sProjName);
message = _("\
'Save Compressed Copy of Project' is for an Audacity project, not an audio file.\n\
For an audio file that will open in other apps, use 'Export'.\n\n\ For an audio file that will open in other apps, use 'Export'.\n\n\
\ \
Compressed project files are a good way to transmit your project online, \n\ Compressed project files are a good way to transmit your project online, \n\
but they have some loss of fidelity.\n\n\ but they have some loss of fidelity.\n");
\ }
To open a compressed project takes longer than usual, as it imports \n\
each compressed track.\n"),
true) != wxID_OK)
return false;
sDialogTitle.Printf(_("%sSave Compressed Project \"%s\" As..."), Restorer.sProjNumber,Restorer.sProjName);
} }
else else
{ {
if (ShowWarningDialog(this, wxT("FirstProjectSave"), title = wxString::Format(_("%sSave Project \"%s\" As..."),
_("\ Restorer.sProjNumber, Restorer.sProjName);
message = _("\
'Save Project' is for an Audacity project, not an audio file.\n\ 'Save Project' is for an Audacity project, not an audio file.\n\
For an audio file that will open in other apps, use 'Export'.\n"), For an audio file that will open in other apps, use 'Export'.\n");
true) != wxID_OK) }
return false; if (ShowWarningDialog(this, wxT("FirstProjectSave"), message, true) != wxID_OK)
sDialogTitle.Printf(_("%sSave Project \"%s\" As..."), Restorer.sProjNumber, Restorer.sProjName); {
return false;
} }
// JKC: I removed 'wxFD_OVERWRITE_PROMPT' because we are checking // JKC: I removed 'wxFD_OVERWRITE_PROMPT' because we are checking
@ -4502,7 +4529,7 @@ For an audio file that will open in other apps, use 'Export'.\n"),
// We disallow overwrite because we would have to DELETE the many // We disallow overwrite because we would have to DELETE the many
// smaller files too, or prompt to move them. // smaller files too, or prompt to move them.
wxString fName = FileNames::SelectFile(FileNames::Operation::Export, wxString fName = FileNames::SelectFile(FileNames::Operation::Export,
sDialogTitle, title,
filename.GetPath(), filename.GetPath(),
filename.GetFullName(), filename.GetFullName(),
wxT("aup"), wxT("aup"),
@ -4517,7 +4544,7 @@ For an audio file that will open in other apps, use 'Export'.\n"),
filename.SetExt(wxT("aup")); filename.SetExt(wxT("aup"));
fName = filename.GetFullPath(); fName = filename.GetFullPath();
if (bWantSaveCompressed && filename.FileExists()) { if (bWantSaveCopy && filename.FileExists()) {
// Saving a copy of the project should never overwrite an existing project. // Saving a copy of the project should never overwrite an existing project.
AudacityMessageDialog m( AudacityMessageDialog m(
NULL, NULL,
@ -4584,12 +4611,12 @@ will be irreversibly overwritten."), fName, fName);
mFileName = fName; mFileName = fName;
bool success = false; bool success = false;
auto cleanup = finally( [&] { auto cleanup = finally( [&] {
if (!success || bWantSaveCompressed) if (!success || bWantSaveCopy)
// Restore file name on error // Restore file name on error
mFileName = oldFileName; mFileName = oldFileName;
} ); } );
success = DoSave(!bOwnsNewAupName || bWantSaveCompressed, bWantSaveCompressed); success = DoSave(!bOwnsNewAupName || bWantSaveCopy, bWantSaveCopy, bLossless);
if (success) { if (success) {
wxGetApp().AddFileToHistory(mFileName); wxGetApp().AddFileToHistory(mFileName);
@ -4599,7 +4626,7 @@ will be irreversibly overwritten."), fName, fName);
gPrefs->Flush(); gPrefs->Flush();
} }
} }
if (!success || bWantSaveCompressed) // bWantSaveCompressed doesn't actually change current project. if (!success || bWantSaveCopy) // bWantSaveCopy doesn't actually change current project.
{ {
} }
else { else {

@ -288,13 +288,13 @@ public:
TrackHolders &&newTracks); TrackHolders &&newTracks);
bool Save(); bool Save();
bool SaveAs(bool bWantSaveCompressed = false); bool SaveAs(bool bWantSaveCopy = false, bool bLossless = false);
bool SaveAs(const wxString & newFileName, bool bWantSaveCompressed = false, bool addToHistory = true); bool SaveAs(const wxString & newFileName, bool bWantSaveCopy = false, bool addToHistory = true);
#ifdef USE_LIBVORBIS // strProjectPathName is full path for aup except extension
bool SaveCompressedWaveTracks(const wxString & strProjectPathName); // full path for aup except extension bool SaveCopyWaveTracks(const wxString & strProjectPathName, bool bLossless = false);
#endif
private: private:
bool DoSave(bool fromSaveAs, bool bWantSaveCompressed); bool DoSave(bool fromSaveAs, bool bWantSaveCopy, bool bLossless = false);
public: public:
void Clear(); void Clear();
@ -550,7 +550,7 @@ public:
bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override; bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override;
XMLTagHandler *HandleXMLChild(const wxChar *tag) override; XMLTagHandler *HandleXMLChild(const wxChar *tag) override;
void WriteXML( void WriteXML(
XMLWriter &xmlFile, bool bWantSaveCompressed) /* not override */; XMLWriter &xmlFile, bool bWantSaveCopy) /* not override */;
void WriteXMLHeader(XMLWriter &xmlFile) const; void WriteXMLHeader(XMLWriter &xmlFile) const;