16#include <wx/evtloop.h>
77 auto result = std::make_shared< ProjectFileManager >( parent );
98 projectFileManager.ReadProjectFile(filename,
true);
100 if (projectFileManager.mLastSavedTracks) {
101 for (
auto wt : projectFileManager.mLastSavedTracks->Any<
WaveTrack>())
103 projectFileManager.mLastSavedTracks.reset();
120 "FAQ:Errors_on_opening_or_recovering_an_Audacity_project";
122using Pair = std::pair< const char *, const char * >;
125 "not well-formed (invalid token)",
126 "Error:_not_well-formed_(invalid_token)_at_line_x"
129 "reference to invalid character number",
130 "Error_Opening_Project:_Reference_to_invalid_character_number_at_line_x"
143 if ( !libraryError.
empty() ) {
146 auto msgid = libraryError.
MSGID().
GET();
148 [&](
const Pair &pair ) {
149 return msgid.Contains( pair.first ); }
152 auto url = found->second;
166 const FilePath &fileName,
bool discardAutosave )
176 auto parseResult = projectFileIO.LoadProject(fileName, discardAutosave);
177 const bool bParseSuccess = parseResult.has_value();
180 std::optional<TranslatableString> linkTypeChangeReason;
206 leader = left ?
nullptr
214 mLastSavedTracks->Add(newTrack);
223 [
this](
Track& track) {
224 mLastSavedTracks->Add(
231 [&](
const auto& errorMessage) { otherError = errorMessage; err =
true; },
232 [&](
const auto& unlinkReason) { linkTypeChangeReason = unlinkReason; });
235 if(linkTypeChangeReason && !discardAutosave)
243"This feature is not supported in Audacity versions past 3.3.3.\n"
244"These stereo tracks have been split into mono tracks.\n"
245"As a result, some realtime effects may be missing.\n"
246"Please verify that everything works as intended before saving."
247 ).
Format(linkTypeChangeReason->Translation()));
250 parseResult->Commit();
253 projectFileIO.AutoSaveDelete();
254 else if (projectFileIO.IsRecovered()) {
255 bool resaved =
false;
257 if (!projectFileIO.IsTemporary() &&
258 !linkTypeChangeReason)
262 resaved = projectFileIO.SaveProject(fileName,
nullptr);
268"This project was not saved properly the last time Audacity ran.\n\n"
269"It has been recovered to the last snapshot.")
271"This project was not saved properly the last time Audacity ran.\n\n"
272"It has been recovered to the last snapshot, but you must save it\n"
273"to preserve its contents."),
274 XO(
"Project Recovered"),
286 (bParseSuccess ? otherError : projectFileIO.GetLastError()),
296 mProject, [
this](
auto& path,
bool rename)
302 if (projectFileIO.IsTemporary())
307 return DoSave(projectFileIO.GetFileName(),
false);
327 ProjectDisabler(wxWindow *w)
330 mWindow->GetEventHandler()->SetEvtHandlerEnabled(
false);
334 mWindow->GetEventHandler()->SetEvtHandlerEnabled(
true);
358 wxULongLong fileSize = wxFileName::GetSize(projectFileIO.GetFileName());
360 wxDiskspaceSize_t freeSpace;
363 if (freeSpace.GetValue() <= fileSize.GetValue())
366 XO(
"Insufficient Disk Space"),
367 XO(
"The project size exceeds the available free space on the target disk.\n\n"
368 "Please select a different disk with more free space."),
369 "Error:_Disk_full_or_not_writable"
379 std::optional<ProjectFileIO::BackupProject> pBackupProject;
380 if (fromSaveAs && wxFileExists(fileName))
382 pBackupProject.emplace(projectFileIO, fileName);
383 if (!pBackupProject->IsOk())
389 if (wxFileName::GetSize(projectFileIO.GetFileName()) > UINT32_MAX)
392 XO(
"Error Saving Project"),
393 XO(
"The project exceeds the maximum size of 4GB when writing to a FAT32 formatted filesystem."),
394 "Error:_Unsuitable_drive"
405 if (!projectFileIO.HasConnection()) {
408 XO(
"Error Saving Project"),
410 "Error:_Disk_full_or_not_writable",
416 proj.SetProjectName(wxFileName(fileName).GetName());
417 projectFileIO.SetProjectTitle();
435 pBackupProject->Discard();
447 auto oldFileName = projectFileIO.GetFileName();
449 bool bOwnsNewName = !projectFileIO.IsTemporary() && (oldFileName == newFileName);
453 if( !bOwnsNewName && wxFileExists(newFileName)) {
456 XO(
"The project was not saved because the file name provided would overwrite another project.\nPlease try again and select an original name."),
457 XO(
"Error Saving Project"),
463 auto success =
DoSave(newFileName, !bOwnsNewName);
464 if (success && addToHistory) {
480 if (projectFileIO.IsTemporary()) {
481 filename.SetPath(defaultSavePath);
482 filename.SetName(
project.GetProjectName());
485 filename = projectFileIO.GetFileName();
490 filename.SetPath(defaultSavePath);
496 bool bPrompt = (
project.mBatchMode == 0) || (projectFileIO.GetFileName().empty());
504 fName =
SelectFile(FileNames::Operation::Save,
507 filename.GetFullName(),
510 wxFD_SAVE | wxRESIZE_BORDER,
519 filename.SetExt(
wxT(
"aup3"));
521 if ((!bPrompt || !allowOverwrite) && filename.FileExists()) {
525 XO(
"The project was not saved because the file name provided would overwrite another project.\nPlease try again and select an original name."),
526 XO(
"Error Saving Project"),
532 fName = filename.GetFullPath();
534 bOwnsNewName = !projectFileIO.IsTemporary() && ( projectFileIO.GetFileName() == fName );
538 if (!bOwnsNewName && filename.FileExists()) {
545 int mayOverwrite = ( projectFileIO.GetFileName() == fName ) ? 2 : 1;
548 if (openProjectName.SameAs(fName)) {
550 if (mayOverwrite == 0)
555 if (mayOverwrite > 0) {
559 Do you want to overwrite the project:\n\"%s\"?\n\n\
560 If you select \"Yes\" the project\n\"%s\"\n\
561 will be irreversibly overwritten.").Format( fName, fName );
567 XO(
"Overwrite Project Warning"),
568 wxYES_NO | wxNO_DEFAULT | wxICON_WARNING,
570 if (result == wxNO) {
573 if (result == wxCANCEL) {
581 XO(
"The project was not saved because the selected project is open in another window.\nPlease try again and select an original name."),
582 XO(
"Error Saving Project"),
602 auto success =
DoSave(fName, !bOwnsNewName);
616 wxFileName filename = fileName;
619 if (fileName.empty())
621 if (projectFileIO.IsTemporary())
623 filename.SetPath(defaultSavePath);
627 filename = projectFileIO.GetFileName();
634 filename.SetPath(defaultSavePath);
638 XO(
"%sSave Copy of Project \"%s\" As...")
641 bool bPrompt = (
project.mBatchMode == 0) || (projectFileIO.GetFileName().empty());
653 fName =
SelectFile(FileNames::Operation::Export,
656 filename.GetFullName(),
659 wxFD_SAVE | wxRESIZE_BORDER,
670 filename.SetExt(
wxT(
"aup3"));
682 if (filename.FileExists())
686 XO(
"Saving a copy must not overwrite an existing saved project.\nPlease try again and select an original name."),
687 XO(
"Error Saving Copy of Project"),
688 wxOK | wxICON_ERROR);
699 wxULongLong fileSize = wxFileName::GetSize(projectFileIO.GetFileName());
701 wxDiskspaceSize_t freeSpace;
704 if (freeSpace.GetValue() <= fileSize.GetValue())
707 XO(
"Insufficient Disk Space"),
708 XO(
"The project size exceeds the available free space on the target disk.\n\n"
709 "Please select a different disk with more free space."),
710 "Error:_Unsuitable_drive"
719 if (fileSize > UINT32_MAX)
722 XO(
"Error Saving Project"),
723 XO(
"The project exceeds the maximum size of 4GB when writing to a FAT32 formatted filesystem."),
724 "Error:_Unsuitable_drive"
736 fName = filename.GetFullPath();
740 if (!projectFileIO.SaveCopy(fName))
744 nullptr, msg,
XO(
"Error Saving Project"), wxOK | wxICON_ERROR);
762 wxString sNewFileName = fnFile.GetFullPath();
767 if (!projectFileIO.IsModified()) {
768 sOldFilename = projectFileIO.GetFileName();
774 if (wxFileExists(sNewFileName)) {
778 auto success =
DoSave(sNewFileName,
true);
804 !projectFileIO.WasCompacted() &&
823 return projectFileIO.OpenProject();
847 projectFileIO.CloseProject();
869 wxArrayString selected;
872 XO(
"Select one or more files"),
876 wxFD_OPEN | wxFD_MULTIPLE | wxRESIZE_BORDER);
884 const auto &saveType = fileTypes[ index ];
889 if (dialogResult == wxID_OK) {
903 const wxFileName newProjPathName(projPathName);
905 iter = std::find_if( start, finish,
909 if (iter != finish) {
911 XO(
"%s is already open in another window.")
912 .Format( newProjPathName.GetName() );
913 wxLogError(errMsg.Translation());
916 XO(
"Error Opening Project"),
924 const FilePath &fileNameArg,
bool addtohistory)
944 if (fileName.Lower().EndsWith(
wxT(
".aup3.bak")))
948"You are trying to open an automatically created backup file.\nDoing this may result in severe data loss.\n\nPlease open the actual Audacity project file instead."),
949 XO(
"Warning - Backup File Detected"),
955 if (!::wxFileExists(fileName)) {
957 XO(
"Could not open file: %s").
Format( fileName ),
958 XO(
"Error Opening File"),
966 wxFFile ff(fileName,
wxT(
"rb"));
968 auto cleanup =
finally([&]
976 if (!ff.IsOpened()) {
978 XO(
"Could not open file: %s").
Format( fileName ),
979 XO(
"Error opening file"),
986 auto numRead = ff.Read(buf, 6);
989 XO(
"File may be invalid or corrupted: \n%s").
Format( fileName ),
990 XO(
"Error Opening File or Project"),
996 if (wxStrncmp(buf,
"SQLite", 6) != 0)
999#ifdef EXPERIMENTAL_DRAG_DROP_PLUG_INS
1008 auto &
project = chooser(
false);
1014 if (!fileName.AfterLast(
'.').IsSameAs(
wxT(
"lof"),
false))
1025 XO(
"Project resides on FAT formatted drive.\n"
1026 "Copy it to another drive to open it.")))
1031 auto &
project = chooser(
true);
1044 for (
auto iter =
tracks.begin(); iter !=
tracks.end();) {
1045 auto t = (*iter++)->SharedPointer();
1046 const auto linkType = t->GetLinkType();
1050 if (!t->LinkConsistencyFix()) {
1051 onError(
XO(
"A channel of a stereo track was missing."));
1052 unlinkedTrack =
nullptr;
1054 if (!unlinkedTrack) {
1056 t->NChannels() == 1) {
1059 assert(t->GetOwner().get() == &
tracks);
1064 iter =
tracks.Find(t.get());
1071 if (
const auto left =
dynamic_cast<WaveTrack*
>(unlinkedTrack.get())) {
1072 if (
const auto right =
dynamic_cast<WaveTrack*
>(t.get())) {
1074 assert(right->GetOwner().get() == &
tracks);
1075 left->SetPan(-1.0f);
1076 right->SetPan(1.0f);
1080 if(left->GetRate() != right->GetRate())
1082 onUnlink(
XO(
"This project contained stereo tracks with different sample rates per channel."));
1083 if(left->GetSampleFormat() != right->GetSampleFormat())
1085 onUnlink(
XO(
"This project contained stereo tracks with different sample formats in channels."));
1087 onUnlink(
XO(
"This project contained stereo tracks with non-aligned content."));
1090 unlinkedTrack =
nullptr;
1093 if (
const auto message = t->GetErrorOpening()) {
1095 wxT(
"Track %s had error reading clip values from project file."),
1103 const FilePath &fileName,
bool addtohistory)
1118 const bool bParseSuccess = results.parseSuccess;
1119 const auto &errorStr = results.errorString;
1120 const bool err = results.trackError;
1122 if (bParseSuccess && !err) {
1127 viewport.HandleResize();
1128 trackPanel.Refresh(
false);
1132 trackPanel.Update();
1140 if (bParseSuccess && !err) {
1141 if (projectFileIO.IsRecovered())
1144 history.PushState(
XO(
"Project was recovered"),
XO(
"Recover"));
1164 wxLogError(
wxT(
"Could not parse file \"%s\". \nError: %s"), fileName, errorStr.Debug());
1167 XO(
"Error Opening Project"),
1184 std::vector<Track*> results;
1188 wxFileName
fn(fileName);
1190 bool initiallyEmpty =
tracks.empty();
1192 wxString trackNameBase =
fn.GetName();
1198 const bool projectHasSolo =
1200 if (projectHasSolo) {
1201 for (
auto &group : newTracks)
1202 if (
auto pTrack =
dynamic_cast<PlayableTrack*
>(group.get()))
1203 pTrack->SetMute(
true);
1206 for (
auto &group : newTracks) {
1207 if (
auto pTrack =
dynamic_cast<WaveTrack*
>(group.get()))
1208 results.push_back(pTrack);
1217 const bool useSuffix = results.size() > 1;
1219 for (
const auto &newTrack : results) {
1221 newTrack->SetSelected(
true);
1224 newTrack->SetName(
XC(
"%s %d",
"clip name template")
1225 .Format(trackNameBase, i + 1).Translation());
1227 newTrack->SetName(trackNameBase);
1229 newTrack->TypeSwitch([&](
WaveTrack &wt) {
1232 const auto trackName = wt.
GetName();
1233 for (
const auto &interval : wt.
Intervals())
1234 interval->SetName(trackName);
1238 history.PushState(
XO(
"Imported '%s'").Format( fileName ),
1241#if defined(__WXGTK__)
1247 wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI | wxEVT_CATEGORY_USER_INPUT);
1252 if (initiallyEmpty && projectFileIO.IsTemporary()) {
1254 project.SetInitialImportPath(
fn.GetPath());
1255 projectFileIO.SetProjectTitle();
1269 if (!projectFileIO.LoadProject(fileName,
false))
1273 for (
const Track *pTrack : srcTracks)
1274 pTrack->PasteInto(dest, destTracks);
1294 mImportFileHandle = &importFileHandle;
1300 if (ImportDlg.ShowModal() == wxID_CANCEL)
1311 constexpr double ProgressSteps { 1000.0 };
1312 if(!mProgressDialog)
1314 wxFileName ff( mImportFileHandle->GetFilename() );
1315 auto title =
XO(
"Importing %s").Format( mImportFileHandle->GetFileDescription() );
1318 auto result = mProgressDialog->Poll(progress * ProgressSteps, ProgressSteps);
1320 mImportFileHandle->Cancel();
1322 mImportFileHandle->Stop();
1327 mProgressDialog.reset();
1328 if(result == ImportResult::Error)
1330 auto message = mImportFileHandle->GetErrorMessage();
1331 if(!message.empty())
1348 wxArrayString fileNames;
1349 fileNames.Add(fileName);
1350 return Import(std::move(fileNames), addToHistory);
1357 std::vector<wxString> { fileNames.begin(), fileNames.end() },
1362 Track* lastTrack =
nullptr;
1364 assert(!range.empty());
1367 lastTrack = *(range.rbegin());
1369 const auto project = wProject.lock();
1370 const auto track = wTrack.lock();
1371 if (!project || !track)
1373 auto& viewPort = Viewport::Get(*project);
1374 TrackFocus::Get(*project).Set(track.get(), true);
1375 viewPort.ZoomFitHorizontally();
1376 viewPort.ShowTrack(*track);
1377 viewPort.HandleResize();
1385 const std::vector<std::shared_ptr<ClipMirAudioReader>>& readers,
1388 const auto isBeatsAndMeasures =
project.ViewIsBeatsAndMeasures();
1389 const auto projectTempo =
project.GetTempo();
1393 XO(
"Music Information Retrieval"),
XO(
"Analyzing imported audio"),
1396 const auto reportProgress = [&](
double progressFraction) {
1397 const auto result = progress->Poll(
1398 (count + progressFraction) / readers.size() * 1000, 1000);
1403 std::vector<std::shared_ptr<MIR::AnalyzedAudioClip>> analyzedClips;
1404 analyzedClips.reserve(readers.size());
1406 readers.begin(), readers.end(), std::back_inserter(analyzedClips),
1407 [&](
const std::shared_ptr<ClipMirAudioReader>& reader) {
1408 const MIR::ProjectSyncInfoInput input {
1409 *reader, reader->filename, reader->tags, reportProgress,
1410 projectTempo, projectWasEmpty, isBeatsAndMeasures,
1414 return std::make_shared<AnalyzedWaveClip>(reader, syncInfo);
1416 return analyzedClips;
1421 const std::vector<FilePath>& fileNames,
bool addToHistory)
1423 const auto projectWasEmpty =
1425 std::vector<std::shared_ptr<ClipMirAudioReader>> resultingReaders;
1426 const auto success = std::all_of(
1427 fileNames.begin(), fileNames.end(), [&](
const FilePath& fileName) {
1428 std::shared_ptr<ClipMirAudioReader> resultingReader;
1429 const auto success = DoImport(fileName, addToHistory, resultingReader);
1430 if (success && resultingReader)
1431 resultingReaders.push_back(std::move(resultingReader));
1437 if (!resultingReaders.empty())
1439 const auto pProj =
mProject.shared_from_this();
1442 const auto analyzedClips =
1452 const FilePath& fileName,
bool addToHistory,
1453 std::shared_ptr<ClipMirAudioReader>& resultingReader)
1462#ifdef EXPERIMENTAL_IMPORT_AUP3
1464 if (fileName.AfterLast(
'.').IsSameAs(
wxT(
"aup3"),
false)) {
1470 if (initiallyEmpty && projectFileIO.IsTemporary()) {
1471 wxFileName
fn(fileName);
1473 project.SetInitialImportPath(
fn.GetPath());
1474 projectFileIO.SetProjectTitle();
1477 history.PushState(
XO(
"Imported '%s'").
Format(fileName),
XO(
"Import"));
1484 errorMessage = projectFileIO.GetLastError();
1485 if (errorMessage.
empty()) {
1486 errorMessage =
XO(
"Failed to import project");
1491 XO(
"Error Importing"),
1492 errorMessage,
wxT(
"Importing_Audio"));
1501 bool committed =
false;
1502 auto cleanup =
finally([&]{
1506 auto newTags = oldTags->Duplicate();
1509#ifndef EXPERIMENTAL_IMPORT_AUP3
1511 if (fileName.AfterLast(
'.').IsSameAs(
wxT(
"aup3"),
false)) {
1513 XO(
"Error Importing"),
1514 XO(
"Cannot import AUP3 format. Use File > Open instead"),
1520 ImportProgress importProgress(
project);
1521 std::optional<LibFileFormats::AcidizerTags> acidTags;
1524 newTracks, newTags.get(), acidTags, errorMessage);
1525 if (!errorMessage.
empty()) {
1529 XO(
"Error Importing"), errorMessage,
wxT(
"Importing_Audio"));
1535 for (
auto track : newTracks)
1538 if (newTracks.size() == 1)
1540 const auto waveTrack =
dynamic_cast<WaveTrack*
>(newTracks[0].get());
1543 if (waveTrack && !waveTrack->GetClipInterfaces().empty())
1545 std::move(acidTags), fileName.ToStdString(),
1559 if (fileName.AfterLast(
'.').IsSameAs(
wxT(
"lof"),
false)) {
1569 if (fileName.AfterLast(
'.').IsSameAs(
wxT(
"aup"),
false)) {
1572 if (initiallyEmpty && projectFileIO.IsTemporary()) {
1573 wxFileName
fn(fileName);
1575 project.SetInitialImportPath(
fn.GetPath());
1576 projectFileIO.SetProjectTitle();
1581 history.PushState(
XO(
"Imported '%s'").
Format( fileName ),
XO(
"Import"));
1587 AddImportedTracks(fileName, std::move(newTracks));
1606 S.StartVerticalLay(
true);
1608 S.AddFixedText(text,
false, 500);
1614 FindWindowById(wxID_YES,
this)->Bind(wxEVT_BUTTON, &CompactDialog::OnYes,
this);
1615 FindWindowById(wxID_NO,
this)->Bind(wxEVT_BUTTON, &CompactDialog::OnNo,
this);
1616 FindWindowById(wxID_HELP,
this)->Bind(wxEVT_BUTTON, &CompactDialog::OnGetURL,
this);
1623 void OnYes(wxCommandEvent &WXUNUSED(evt))
1628 void OnNo(wxCommandEvent &WXUNUSED(evt))
1646 bool isBatch =
project.mBatchMode > 0;
1649 projectFileIO.ReopenProject();
1651 auto savedState = undoManager.GetSavedState();
1652 const auto currentState = undoManager.GetCurrentState();
1653 if (savedState < 0) {
1654 undoManager.StateSaved();
1655 savedState = undoManager.GetSavedState();
1656 if (savedState < 0) {
1661 const auto least = std::min<size_t>(savedState, currentState);
1662 const auto greatest = std::max<size_t>(savedState, currentState);
1663 std::vector<const TrackList*> trackLists;
1666 trackLists.push_back(pTracks);
1668 undoManager.VisitStates(
fn, least, 1 + least);
1669 if (least != greatest)
1670 undoManager.VisitStates(
fn, greatest, 1 + greatest);
1672 int64_t total = projectFileIO.GetTotalUsage();
1673 int64_t used = projectFileIO.GetCurrentUsage(trackLists);
1675 auto before = wxFileName::GetSize(projectFileIO.GetFileName());
1678 XO(
"Compacting this project will free up disk space by removing unused bytes within the file.\n\n"
1679 "There is %s of free disk space and this project is currently using %s.\n"
1681 "If you proceed, the current Undo/Redo History and clipboard contents will be discarded "
1682 "and you will recover approximately %s of disk space.\n"
1684 "Do you want to continue?")
1688 if (isBatch || dlg.ShowModal() == wxYES)
1691 undoManager.RemoveStates(1 + greatest, undoManager.GetNumStates());
1694 if (least < greatest)
1695 undoManager.RemoveStates(least + 1, greatest);
1698 undoManager.RemoveStates(0, least);
1701 if (&
mProject == clipboard.Project().lock().get())
1706 auto before = wxFileName::GetSize(projectFileIO.GetFileName());
1708 projectFileIO.Compact(trackLists,
true);
1710 auto after = wxFileName::GetSize(projectFileIO.GetFileName());
1715 XO(
"Compacting actually freed %s of disk space.")
1717 XO(
"Compact Project"));
1720 undoManager.RenameState( undoManager.GetCurrentState(),
1721 XO(
"Compacted project file"),
1731 bShowProjectNumbers ? pProject->GetProjectNumber() : -1 );
1739 if( window.IsIconized() )
1750 return ptr->GetProjectName().empty();
1755 _(
"[Project %02i] "),
project.GetProjectNumber() + 1 );
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
Toolkit-neutral facade for basic user interface services.
Declare functions to perform UTF-8 to std::wstring conversions.
The interface that all file import "plugins" (if you want to call them that) must implement....
std::vector< std::shared_ptr< Track > > TrackHolders
std::unique_ptr< const BasicUI::WindowPlacement > ProjectFramePlacement(AudacityProject *project)
Make a WindowPlacement object suitable for project (which may be null)
@ Cancel
Open was cancelled by the extension.
@ Handled
Save was handled by the extension.
@ Continue
Save was not handled by the extension.
@ Veto
Extension vetoed the close.
static const AudacityProject::AttachedObjects::RegisteredFactory sFileManagerKey
static void RefreshAllTitles(bool bShowProjectNumbers)
an object holding per-project preferred sample rate
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
accessors for certain important windows associated with each project
FilePath SelectFile(FileNames::Operation op, const TranslatableString &message, const FilePath &default_path, const FilePath &default_filename, const FileExtension &default_extension, const FileTypes &fileTypes, int flags, wxWindow *parent)
void DoProjectTempoChange(ChannelGroup &group, double newTempo)
static Settings & settings()
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
An AudacityException with no visible message.
const_iterator end() const
Container::value_type value_type
const_iterator begin() const
Wrap wxMessageDialog so that caption IS translatable.
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
virtual int GetFilterIndex() const
virtual wxString GetPath() const
virtual void GetPaths(wxArrayString &paths) const
virtual void SetFilterIndex(int filterIndex)
static TranslatableString WriteFailureMessage(const wxFileName &fileName)
void Append(const FilePath &file)
static FileHistory & Global()
FILES_API const FileType AudacityProjects
static void ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
const wxString & GET() const
Explicit conversion to wxString, meant to be ugly-looking and demanding of a comment why it's correct...
Base class for FlacImportFileHandle, LOFImportFileHandle, MP3ImportFileHandle, OggImportFileHandle an...
virtual wxInt32 GetStreamCount()=0
virtual void SetStreamUsage(wxInt32 StreamID, bool Use)=0
Interface used to report on import state and progress.
static void SetLastOpenType(const FileNames::FileType &type)
FileNames::FileTypes GetFileTypes(const FileNames::FileType &extraType={})
bool Import(AudacityProject &project, const FilePath &fName, ImportProgressListener *importProgressListener, WaveTrackFactory *trackFactory, TrackHolders &tracks, Tags *tags, std::optional< LibFileFormats::AcidizerTags > &outAcidTags, TranslatableString &errorMessage)
static size_t SelectDefaultOpenType(const FileNames::FileTypes &fileTypes)
static void SetDefaultOpenType(const FileNames::FileType &type)
static TranslatableString FormatSize(wxLongLong size)
Convert a number to a string while formatting it in bytes, KB, MB, GB.
Makes a temporary project that doesn't display on the screen.
AudacityProject & Project()
AudioTrack subclass that can also be audibly replayed by the program.
static PluginManager & Get()
void SetProjectTitle(int number=-1)
static ProjectFileIO & Get(AudacityProject &project)
const FilePath & GetFileName() const
static void FixTracks(TrackList &tracks, const std::function< void(const TranslatableString &)> &onError, const std::function< void(const TranslatableString &)> &onUnlink)
Attempts to find and fix problems in tracks.
std::shared_ptr< TrackList > mLastSavedTracks
static bool IsAlreadyOpen(const FilePath &projPathName)
AudacityProject & mProject
void CompactProjectOnClose()
bool Import(const FilePath &fileName, bool addToHistory=true)
bool ImportAndRunTempoDetection(const std::vector< FilePath > &fileNames, bool addToHistory)
bool SaveCopy(const FilePath &fileName=wxT(""))
bool SaveAs(bool allowOverwrite=false)
static void DiscardAutosave(const FilePath &filename)
void AddImportedTracks(const FilePath &fileName, TrackHolders &&newTracks)
static wxArrayString ShowOpenDialog(FileNames::Operation op, const FileNames::FileType &extraType={})
Show an open dialogue for opening audio files, and possibly other sorts of files.
bool DoSave(const FilePath &fileName, bool fromSaveAs)
bool SaveFromTimerRecording(wxFileName fnFile)
static AudacityProject * OpenFile(const ProjectChooserFn &chooser, const FilePath &fileName, bool addtohistory=true)
ReadProjectResults ReadProjectFile(const FilePath &fileName, bool discardAutosave=false)
bool DoImport(const FilePath &fileName, bool addToHistory, std::shared_ptr< ClipMirAudioReader > &resultingReader)
std::function< AudacityProject &(bool)> ProjectChooserFn
A function that returns a project to use for opening a file; argument is true if opening a project fi...
static ProjectFileManager & Get(AudacityProject &project)
ProjectFileManager(AudacityProject &project)
AudacityProject * OpenProjectFile(const FilePath &fileName, bool addtohistory)
static ProjectHistory & Get(AudacityProject &project)
static ProjectSettings & Get(AudacityProject &project)
static ProjectStatus & Get(AudacityProject &project)
void Set(const TranslatableString &msg, StatusBarField field=MainStatusBarField())
static ProjectTimeSignature & Get(AudacityProject &project)
static RealtimeEffectList & Get(AudacityProject &project)
void Clear()
Use only in the main thread. Sends Remove messages.
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
TitleRestorer(wxTopLevelWindow &window, AudacityProject &project)
Abstract base class for an object holding data associated with points on a time axis.
std::shared_ptr< Track > Holder
const wxString & GetName() const
Name is always the same for all channels of a group.
virtual Holder Duplicate(DuplicateOptions={}) const
public nonvirtual duplication function that invokes Clone()
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
static TrackListHolder Create(AudacityProject *pOwner)
auto Any() -> TrackIterRange< TrackType >
static TrackList & Get(AudacityProject &project)
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
static TrackPanel & Get(AudacityProject &project)
Holds a msgid for the translation catalog; may also bind format arguments.
Identifier MSGID() const
MSGID is the English lookup key in the catalog, not necessarily for user's eyes if locale is some oth...
static UndoManager & Get(AudacityProject &project)
bool UnsavedChanges() const
An error dialog about unwritable location, that allows to navigate to settings quickly.
Can be thrown when user cancels operations, as with a progress dialog. Delayed handler does nothing.
void ZoomFitHorizontallyAndShowTrack(Track *pTrack)
static Viewport & Get(AudacityProject &project)
static WaveTrackFactory & Get(AudacityProject &project)
A Track that contains audio waveform data.
void ZipClips(bool mustAlign=true)
double GetRate() const override
void OnYes(wxCommandEvent &WXUNUSED(evt))
void OnGetURL(wxCommandEvent &WXUNUSED(evt))
CompactDialog(TranslatableString text)
void OnNo(wxCommandEvent &WXUNUSED(evt))
void OnImportResult(ImportResult result) override
Used to report on import result for file handle passed as argument to OnImportFileOpened.
ImportProgress(AudacityProject &project)
void OnImportProgress(double progress) override
bool OnImportFileOpened(ImportFileHandle &importFileHandle) override
wxWeakRef< AudacityProject > mProject
std::unique_ptr< BasicUI::ProgressDialog > mProgressDialog
void CallAfter(Action action)
Schedule an action to be done later, and in the main thread.
void ShowErrorDialog(const WindowPlacement &placement, const TranslatableString &dlogTitle, const TranslatableString &message, const ManualPageID &helpPage, const ErrorDialogOptions &options={})
Show an error dialog with a link to the manual for further help.
MessageBoxResult ShowMessageBox(const TranslatableString &message, MessageBoxOptions options={})
Show a modal message box with either Ok or Yes and No, and optionally Cancel.
std::unique_ptr< ProgressDialog > MakeProgress(const TranslatableString &title, const TranslatableString &message, unsigned flags=(ProgressShowStop|ProgressShowCancel), const TranslatableString &remainingLabelText={})
Create and display a progress dialog.
FILES_API bool IsOnFATFileSystem(const FilePath &path)
FILES_API bool IsPathAvailable(const FilePath &Path)
FILES_API wxString AbbreviatePath(const wxFileName &fileName)
Give enough of the path to identify the device. (On Windows, drive letter plus ':')
FILES_API void UpdateDefaultPath(Operation op, const FilePath &path)
FILES_API int CompareNoCase(const wxString &first, const wxString &second)
FILES_API FilePath FindDefaultPath(Operation op)
std::optional< ProjectSyncInfo > GetProjectSyncInfo(const ProjectSyncInfoInput &in)
void SynchronizeProject(const std::vector< std::shared_ptr< AnalyzedAudioClip > > &clips, ProjectInterface &project, bool projectWasEmpty)
void SelectNone(AudacityProject &project)
FILES_API bool FATFilesystemDenied(const FilePath &path, const TranslatableString &msg, const BasicUI::WindowPlacement &placement={})
FILES_API wxString UnsavedProjectFileName()
TRACK_API TrackList * Find(const UndoStackElem &state)
WAVE_TRACK_API void CloseLock(WaveTrack &track) noexcept
Should be called upon project close. Not balanced by unlocking calls.
bool ImportProject(AudacityProject &dest, const FilePath &fileName)
std::pair< const char *, const char * > Pair
const Pair helpURLTable[]
wxString FindHelpUrl(const TranslatableString &libraryError)
const char *const defaultHelpUrl
std::vector< std::shared_ptr< MIR::AnalyzedAudioClip > > RunTempoDetection(const std::vector< std::shared_ptr< ClipMirAudioReader > > &readers, const MIR::ProjectInterface &project, bool projectWasEmpty)
TranslatableString Message(unsigned trackCount)
std::string ToUTF8(const std::wstring &wstr)
wxString ToWXString(const std::string &str)
const char * end(const char *str) noexcept
const char * begin(const char *str) noexcept
Options for variations of error dialogs; the default is for modal dialogs.
static void OnLoad(AudacityProject &project)
static OnOpenAction OnOpen(AudacityProject &project, const std::string &path)
static OnSaveAction OnSave(AudacityProject &project, const ProjectSaveCallback &projectSaveCallback)
static OnCloseAction OnClose(AudacityProject &project)
Choices when duplicating a track.
DuplicateOptions Backup() &&
Holds one item with description and time range for the UndoManager.