1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-01 16:19:43 +02:00

AudacityApp.cpp and some others freed from cyclic link dependencies

This commit is contained in:
Paul Licameli 2019-05-17 16:30:05 -04:00
commit 597cdb7428
57 changed files with 1274 additions and 925 deletions

View File

@ -98,6 +98,7 @@ public:
};
class wxDialog;
class wxWindow;
class EffectUIHostInterface;
class EffectUIClientInterface;

View File

@ -56,6 +56,10 @@ src/BlockFile.cpp
src/BlockFile.h
src/CellularPanel.cpp
src/CellularPanel.h
src/Clipboard.cpp
src/Clipboard.h
src/CrashReport.cpp
src/CrashReport.h
src/ClassicThemeAsCeeCode.h
src/CrossFade.cpp
src/CrossFade.h
@ -125,6 +129,8 @@ src/MemoryX.h
src/Menus.cpp
src/Menus.h
src/MenusMac.cpp
src/MissingAliasFileDialog.cpp
src/MissingAliasFileDialog.h
src/Mix.cpp
src/Mix.h
src/MixerBoard.cpp

View File

@ -1274,6 +1274,7 @@
5EBD243D1F74C50800132E0A /* eu_ES.po in Sources */ = {isa = PBXBuildFile; fileRef = 5EBD243C1F74C50800132E0A /* eu_ES.po */; };
5EBD35861F78D37A0084D13F /* pt_PT.po in Sources */ = {isa = PBXBuildFile; fileRef = 5EBD35851F78D37A0084D13F /* pt_PT.po */; };
5EC7ED061E101C5C0052CAE2 /* NotYetAvailableException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5EC7ED041E101C5C0052CAE2 /* NotYetAvailableException.cpp */; };
5ECF728A22887B3B007F2A35 /* MissingAliasFileDialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5ECF728822887B3B007F2A35 /* MissingAliasFileDialog.cpp */; };
5ED1D0AD1CDE55BD00471E3C /* Overlay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5ED1D0A91CDE55BD00471E3C /* Overlay.cpp */; };
5ED1D0AE1CDE55BD00471E3C /* OverlayPanel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5ED1D0AB1CDE55BD00471E3C /* OverlayPanel.cpp */; };
5ED1D0B11CDE560C00471E3C /* BackedPanel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5ED1D0AF1CDE560C00471E3C /* BackedPanel.cpp */; };
@ -1290,6 +1291,9 @@
5EF3E65F203FDFE9006C6882 /* SetEnvelopeCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5EF3E65D203FDFE9006C6882 /* SetEnvelopeCommand.cpp */; };
5EF3E662203FE73C006C6882 /* DragCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5EF3E660203FE73C006C6882 /* DragCommand.cpp */; };
5EF958851DEB121800191280 /* InconsistencyException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5EF958831DEB121800191280 /* InconsistencyException.cpp */; };
5EFEAD9E22723E390077DFF6 /* Clipboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5EFEAD9C22723E390077DFF6 /* Clipboard.cpp */; };
5EFEADA02273382D0077DFF6 /* AudacityApp.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5EFEAD9F2273382D0077DFF6 /* AudacityApp.mm */; };
5EFEADA322733DD30077DFF6 /* CrashReport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5EFEADA122733DD30077DFF6 /* CrashReport.cpp */; };
65326EC72253D70900844F28 /* common.c in Sources */ = {isa = PBXBuildFile; fileRef = 65326EAA2253D70900844F28 /* common.c */; };
65326EC82253D70900844F28 /* common.h in Headers */ = {isa = PBXBuildFile; fileRef = 65326EAB2253D70900844F28 /* common.h */; };
65326EC92253D70900844F28 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 65326EAC2253D70900844F28 /* config.h */; };
@ -3284,6 +3288,8 @@
5EC7ED041E101C5C0052CAE2 /* NotYetAvailableException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NotYetAvailableException.cpp; sourceTree = "<group>"; };
5EC7ED051E101C5C0052CAE2 /* NotYetAvailableException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotYetAvailableException.h; sourceTree = "<group>"; };
5ECCE7651DE49834009900E9 /* AudacityException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudacityException.h; sourceTree = "<group>"; };
5ECF728822887B3B007F2A35 /* MissingAliasFileDialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MissingAliasFileDialog.cpp; sourceTree = "<group>"; };
5ECF728922887B3B007F2A35 /* MissingAliasFileDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MissingAliasFileDialog.h; sourceTree = "<group>"; };
5ED18DB61CC16B1E00FAFE95 /* Reverb_libSoX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reverb_libSoX.h; sourceTree = "<group>"; };
5ED18DB71CC290AB00FAFE95 /* wxFileNameWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wxFileNameWrapper.h; sourceTree = "<group>"; };
5ED1D0A91CDE55BD00471E3C /* Overlay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Overlay.cpp; sourceTree = "<group>"; };
@ -3318,6 +3324,11 @@
5EF3E661203FE73C006C6882 /* DragCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DragCommand.h; sourceTree = "<group>"; };
5EF958831DEB121800191280 /* InconsistencyException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InconsistencyException.cpp; sourceTree = "<group>"; };
5EF958841DEB121800191280 /* InconsistencyException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InconsistencyException.h; sourceTree = "<group>"; };
5EFEAD9C22723E390077DFF6 /* Clipboard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Clipboard.cpp; sourceTree = "<group>"; };
5EFEAD9D22723E390077DFF6 /* Clipboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Clipboard.h; sourceTree = "<group>"; };
5EFEAD9F2273382D0077DFF6 /* AudacityApp.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AudacityApp.mm; sourceTree = "<group>"; };
5EFEADA122733DD30077DFF6 /* CrashReport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CrashReport.cpp; sourceTree = "<group>"; };
5EFEADA222733DD30077DFF6 /* CrashReport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CrashReport.h; sourceTree = "<group>"; };
65326E9E2253D2BE00844F28 /* libmp3lame.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libmp3lame.a; sourceTree = BUILT_PRODUCTS_DIR; };
65326EA72253D68900844F28 /* libmpg123.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libmpg123.a; sourceTree = BUILT_PRODUCTS_DIR; };
65326EA92253D70900844F28 /* AUTHORS */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = AUTHORS; sourceTree = "<group>"; };
@ -4285,6 +4296,8 @@
1790AFDA09883BFD008A330A /* Benchmark.cpp */,
1790AFE809883BFD008A330A /* BlockFile.cpp */,
5E0A1CDB20E95FF7001AAF8D /* CellularPanel.cpp */,
5EFEAD9C22723E390077DFF6 /* Clipboard.cpp */,
5EFEADA122733DD30077DFF6 /* CrashReport.cpp */,
1790AFF409883BFD008A330A /* CrossFade.cpp */,
2849B4600A7444BE00ECF12D /* Dependencies.cpp */,
28D000A31A32920C00367B21 /* DeviceChange.cpp */,
@ -4315,6 +4328,7 @@
1865A9B61004490500946EE6 /* LyricsWindow.cpp */,
28EBA7FF0A78FAF800C8BB1F /* Matrix.cpp */,
1790B0A709883BFD008A330A /* Menus.cpp */,
5ECF728822887B3B007F2A35 /* MissingAliasFileDialog.cpp */,
1790B0AB09883BFD008A330A /* Mix.cpp */,
289E75081006D0BD00CEF79B /* MixerBoard.cpp */,
280A8B4519F4403B0091DE70 /* ModuleManager.cpp */,
@ -4381,7 +4395,9 @@
1790AFE909883BFD008A330A /* BlockFile.h */,
5E0A1CDC20E95FF7001AAF8D /* CellularPanel.h */,
5E60AC79214C31B100A82791 /* ClassicThemeAsCeeCode.h */,
5EFEAD9D22723E390077DFF6 /* Clipboard.h */,
1790AFF009883BFD008A330A /* configtemplate.h */,
5EFEADA222733DD30077DFF6 /* CrashReport.h */,
1790AFF509883BFD008A330A /* CrossFade.h */,
5E60AC7A214C31B100A82791 /* DarkThemeAsCeeCode.h */,
2849B4610A7444BE00ECF12D /* Dependencies.h */,
@ -4420,6 +4436,7 @@
28EBA8000A78FAF800C8BB1F /* Matrix.h */,
5E61EE0C1CBAA6BB0009FCF1 /* MemoryX.h */,
1790B0A809883BFD008A330A /* Menus.h */,
5ECF728922887B3B007F2A35 /* MissingAliasFileDialog.h */,
1790B0AC09883BFD008A330A /* Mix.h */,
289E75091006D0BD00CEF79B /* MixerBoard.h */,
280A8B4619F4403B0091DE70 /* ModuleManager.h */,
@ -4479,6 +4496,7 @@
2844163A1B82D6BC0000574D /* WaveTrackLocation.h */,
28FC1AFA0A47762C00A188AE /* WrappedType.h */,
5ED18DB71CC290AB00FAFE95 /* wxFileNameWrapper.h */,
5EFEAD9F2273382D0077DFF6 /* AudacityApp.mm */,
1790AFDC09883BFD008A330A /* blockfile */,
174D9025098C78AF00D5909F /* commands */,
1790AFFD09883BFD008A330A /* effects */,
@ -8223,6 +8241,7 @@
5E15125C1DB000DC00702E29 /* LabelTrackVRulerControls.cpp in Sources */,
1790B12509883BFD008A330A /* SimpleBlockFile.cpp in Sources */,
1790B12609883BFD008A330A /* BlockFile.cpp in Sources */,
5EFEADA02273382D0077DFF6 /* AudacityApp.mm in Sources */,
1790B12A09883BFD008A330A /* CrossFade.cpp in Sources */,
1790B12B09883BFD008A330A /* DirManager.cpp in Sources */,
1790B12C09883BFD008A330A /* Dither.cpp in Sources */,
@ -8495,6 +8514,7 @@
28851FAD1027F16500152EE1 /* CommandType.cpp in Sources */,
28851FAE1027F16500152EE1 /* CompareAudioCommand.cpp in Sources */,
28851FAF1027F16500152EE1 /* GetTrackInfoCommand.cpp in Sources */,
5EFEADA322733DD30077DFF6 /* CrashReport.cpp in Sources */,
28851FB01027F16500152EE1 /* HelpCommand.cpp in Sources */,
28851FB11027F16500152EE1 /* MessageCommand.cpp in Sources */,
28851FB21027F16500152EE1 /* SelectCommand.cpp in Sources */,
@ -8523,6 +8543,7 @@
28884949131B6CF600B59735 /* ca.po in Sources */,
2888494A131B6CF600B59735 /* ca_ES@valencia.po in Sources */,
2888494B131B6CF600B59735 /* cs.po in Sources */,
5ECF728A22887B3B007F2A35 /* MissingAliasFileDialog.cpp in Sources */,
2888494C131B6CF600B59735 /* cy.po in Sources */,
2888494D131B6CF600B59735 /* da.po in Sources */,
2888494E131B6CF600B59735 /* de.po in Sources */,
@ -8594,6 +8615,7 @@
5E19D655217D51190024D0B1 /* PluginMenus.cpp in Sources */,
EDFCEBB518894B9E00C98E51 /* Equalization48x.cpp in Sources */,
2801127B1943EE0E00D98A16 /* HelpSystem.cpp in Sources */,
5EFEAD9E22723E390077DFF6 /* Clipboard.cpp in Sources */,
28F67179197DFA1C00075C32 /* FormatClassifier.cpp in Sources */,
28F6717A197DFA1C00075C32 /* MultiFormatReader.cpp in Sources */,
28F6717B197DFA1C00075C32 /* SpecPowerMeter.cpp in Sources */,

View File

@ -109,9 +109,6 @@
class wxWindow;
void QuitAudacity(bool bForce);
void QuitAudacity();
// Please try to support unlimited path length instead of using PLATFORM_MAX_PATH!
// Define one constant for maximum path value, so we don't have to do
// platform-specific conditionals everywhere we want to check it.

View File

@ -26,8 +26,6 @@ It handles initialization and termination by subclassing wxApp.
#include <vld.h>
#endif
#include "TranslatableStringArray.h"
#include <wx/setup.h> // for wxUSE_* macros
#include <wx/wxcrtvararg.h>
#include <wx/defs.h>
@ -36,7 +34,6 @@ It handles initialization and termination by subclassing wxApp.
#include <wx/docview.h>
#include <wx/event.h>
#include <wx/ipc.h>
#include <wx/log.h>
#include <wx/window.h>
#include <wx/intl.h>
#include <wx/menu.h>
@ -73,6 +70,8 @@ It handles initialization and termination by subclassing wxApp.
#include "AColor.h"
#include "AudioIO.h"
#include "Benchmark.h"
#include "Clipboard.h"
#include "CrashReport.h"
#include "DirManager.h"
#include "commands/CommandHandler.h"
#include "commands/AppCommandEvent.h"
@ -82,6 +81,7 @@ It handles initialization and termination by subclassing wxApp.
#include "LangChoice.h"
#include "Languages.h"
#include "Menus.h"
#include "MissingAliasFileDialog.h"
#include "PluginManager.h"
#include "Project.h"
#include "Screenshot.h"
@ -244,11 +244,6 @@ It handles initialization and termination by subclassing wxApp.
/// Custom events
////////////////////////////////////////////////////////////
wxDEFINE_EVENT( EVT_CLIPBOARD_CHANGE, wxCommandEvent);
DEFINE_EVENT_TYPE(EVT_OPEN_AUDIO_FILE);
wxDEFINE_EVENT(EVT_LANGUAGE_CHANGE, wxCommandEvent);
#if 0
#ifdef __WXGTK__
static void wxOnAssert(const wxChar *fileName, int lineNumber, const wxChar *msg)
@ -269,10 +264,11 @@ static void wxOnAssert(const wxChar *fileName, int lineNumber, const wxChar *msg
#endif
static bool gInited = false;
bool gIsQuitting = false;
static bool gIsQuitting = false;
void QuitAudacity(bool bForce)
static void QuitAudacity(bool bForce)
{
// guard against recursion
if (gIsQuitting)
return;
@ -290,29 +286,17 @@ void QuitAudacity(bool bForce)
if (gAudacityProjects.empty())
{
#ifdef __WXMAC__
AudacityProject::DeleteClipboard();
Clipboard::Get().Clear();
#endif
}
else
/*end+*/
{
SaveWindowSize();
while (gAudacityProjects.size())
bool closedAll = AllProjects::Close( bForce );
if ( !closedAll )
{
// Closing the project has global side-effect
// of deletion from gAudacityProjects
if (bForce)
{
gAudacityProjects[0]->Close(true);
}
else
{
if (!gAudacityProjects[0]->Close())
{
gIsQuitting = false;
return;
}
}
gIsQuitting = false;
return;
}
}
@ -339,89 +323,11 @@ void QuitAudacity(bool bForce)
}
}
void QuitAudacity()
static void QuitAudacity()
{
QuitAudacity(false);
}
void SaveWindowSize()
{
if (wxGetApp().GetWindowRectAlreadySaved())
{
return;
}
bool validWindowForSaveWindowSize = FALSE;
AudacityProject * validProject = NULL;
bool foundIconizedProject = FALSE;
size_t numProjects = gAudacityProjects.size();
for (size_t i = 0; i < numProjects; i++)
{
if (!gAudacityProjects[i]->IsIconized()) {
validWindowForSaveWindowSize = TRUE;
validProject = gAudacityProjects[i].get();
i = numProjects;
}
else
foundIconizedProject = TRUE;
}
if (validWindowForSaveWindowSize)
{
wxRect windowRect = validProject->GetRect();
wxRect normalRect = validProject->GetNormalizedWindowState();
bool wndMaximized = validProject->IsMaximized();
gPrefs->Write(wxT("/Window/X"), windowRect.GetX());
gPrefs->Write(wxT("/Window/Y"), windowRect.GetY());
gPrefs->Write(wxT("/Window/Width"), windowRect.GetWidth());
gPrefs->Write(wxT("/Window/Height"), windowRect.GetHeight());
gPrefs->Write(wxT("/Window/Maximized"), wndMaximized);
gPrefs->Write(wxT("/Window/Normal_X"), normalRect.GetX());
gPrefs->Write(wxT("/Window/Normal_Y"), normalRect.GetY());
gPrefs->Write(wxT("/Window/Normal_Width"), normalRect.GetWidth());
gPrefs->Write(wxT("/Window/Normal_Height"), normalRect.GetHeight());
gPrefs->Write(wxT("/Window/Iconized"), FALSE);
}
else
{
if (foundIconizedProject) {
validProject = gAudacityProjects[0].get();
bool wndMaximized = validProject->IsMaximized();
wxRect normalRect = validProject->GetNormalizedWindowState();
// store only the normal rectangle because the itemized rectangle
// makes no sense for an opening project window
gPrefs->Write(wxT("/Window/X"), normalRect.GetX());
gPrefs->Write(wxT("/Window/Y"), normalRect.GetY());
gPrefs->Write(wxT("/Window/Width"), normalRect.GetWidth());
gPrefs->Write(wxT("/Window/Height"), normalRect.GetHeight());
gPrefs->Write(wxT("/Window/Maximized"), wndMaximized);
gPrefs->Write(wxT("/Window/Normal_X"), normalRect.GetX());
gPrefs->Write(wxT("/Window/Normal_Y"), normalRect.GetY());
gPrefs->Write(wxT("/Window/Normal_Width"), normalRect.GetWidth());
gPrefs->Write(wxT("/Window/Normal_Height"), normalRect.GetHeight());
gPrefs->Write(wxT("/Window/Iconized"), TRUE);
}
else {
// this would be a very strange case that might possibly occur on the Mac
// Audacity would have to be running with no projects open
// in this case we are going to write only the default values
wxRect defWndRect;
GetDefaultWindowRect(&defWndRect);
gPrefs->Write(wxT("/Window/X"), defWndRect.GetX());
gPrefs->Write(wxT("/Window/Y"), defWndRect.GetY());
gPrefs->Write(wxT("/Window/Width"), defWndRect.GetWidth());
gPrefs->Write(wxT("/Window/Height"), defWndRect.GetHeight());
gPrefs->Write(wxT("/Window/Maximized"), FALSE);
gPrefs->Write(wxT("/Window/Normal_X"), defWndRect.GetX());
gPrefs->Write(wxT("/Window/Normal_Y"), defWndRect.GetY());
gPrefs->Write(wxT("/Window/Normal_Width"), defWndRect.GetWidth());
gPrefs->Write(wxT("/Window/Normal_Height"), defWndRect.GetHeight());
gPrefs->Write(wxT("/Window/Iconized"), FALSE);
}
}
gPrefs->Flush();
wxGetApp().SetWindowRectAlreadySaved(TRUE);
}
#if defined(__WXGTK__) && defined(HAVE_GTK)
///////////////////////////////////////////////////////////////////////////////
@ -724,10 +630,6 @@ void AudacityApp::MacNewFile()
#endif //__WXMAC__
#define ID_RECENT_CLEAR 6100
#define ID_RECENT_FIRST 6101
#define ID_RECENT_LAST 6112
// IPC communication
#define ID_IPC_SERVER 6200
#define ID_IPC_SOCKET 6201
@ -745,17 +647,23 @@ BEGIN_EVENT_TABLE(AudacityApp, wxApp)
EVT_MENU(wxID_OPEN, AudacityApp::OnMenuOpen)
EVT_MENU(wxID_ABOUT, AudacityApp::OnMenuAbout)
EVT_MENU(wxID_PREFERENCES, AudacityApp::OnMenuPreferences)
EVT_MENU(wxID_EXIT, AudacityApp::OnMenuExit)
#endif
// Associate the handler with the menu id on all operating systems, even
// if they don't have an application menu bar like in macOS, so that
// other parts of the program can send the application a shut-down
// event
EVT_MENU(wxID_EXIT, AudacityApp::OnMenuExit)
#ifndef __WXMSW__
EVT_SOCKET(ID_IPC_SERVER, AudacityApp::OnServerEvent)
EVT_SOCKET(ID_IPC_SOCKET, AudacityApp::OnSocketEvent)
#endif
// Recent file event handlers.
EVT_MENU(ID_RECENT_CLEAR, AudacityApp::OnMRUClear)
EVT_MENU_RANGE(ID_RECENT_FIRST, ID_RECENT_LAST, AudacityApp::OnMRUFile)
EVT_MENU(FileHistory::ID_RECENT_CLEAR, AudacityApp::OnMRUClear)
EVT_MENU_RANGE(FileHistory::ID_RECENT_FIRST, FileHistory::ID_RECENT_LAST,
AudacityApp::OnMRUFile)
// Handle AppCommandEvents (usually from a script)
EVT_APP_COMMAND(wxID_ANY, AudacityApp::OnReceiveCommand)
@ -822,15 +730,16 @@ bool AudacityApp::SafeMRUOpen(const wxString &fullPathStr)
void AudacityApp::OnMRUClear(wxCommandEvent& WXUNUSED(event))
{
mRecentFiles->Clear();
FileHistory::Global().Clear();
}
//vvv Basically, anything from Recent Files is treated as a .aup, until proven otherwise,
// then it tries to Import(). Very questionable handling, imo.
// Better, for example, to check the file type early on.
void AudacityApp::OnMRUFile(wxCommandEvent& event) {
int n = event.GetId() - ID_RECENT_FIRST;
const auto &fullPathStr = mRecentFiles->GetHistoryFile(n);
int n = event.GetId() - FileHistory::ID_RECENT_FIRST;
auto &history = FileHistory::Global();
const auto &fullPathStr = history.GetHistoryFile(n);
// Try to open only if not already open.
// Test IsAlreadyOpen() here even though AudacityProject::MRUOpen() also now checks,
@ -841,7 +750,7 @@ void AudacityApp::OnMRUFile(wxCommandEvent& event) {
// -- if open fails for some exceptional reason of resource exhaustion that
// the user can correct, leave the file in history.
if (!AudacityProject::IsAlreadyOpen(fullPathStr) && !MRUOpen(fullPathStr))
mRecentFiles->RemoveFileFromHistory(n);
history.RemoveFileFromHistory(n);
}
void AudacityApp::OnTimer(wxTimerEvent& WXUNUSED(event))
@ -885,18 +794,13 @@ void AudacityApp::OnTimer(wxTimerEvent& WXUNUSED(event))
}
// Check if a warning for missing aliased files should be displayed
if (ShouldShowMissingAliasedFileWarning()) {
if (MissingAliasFilesDialog::ShouldShow()) {
// find which project owns the blockfile
// note: there may be more than 1, but just go with the first one.
//size_t numProjects = gAudacityProjects.size();
AProjectHolder offendingProject;
wxString missingFileName;
{
ODLocker locker { &m_LastMissingBlockFileLock };
offendingProject = m_LastMissingBlockFileProject.lock();
missingFileName = m_LastMissingBlockFilePath;
}
auto marked = MissingAliasFilesDialog::Marked();
AProjectHolder offendingProject = marked.second;
wxString missingFileName = marked.first;
// if there are no projects open, don't show the warning (user has closed it)
if (offendingProject) {
@ -918,64 +822,15 @@ locations of the missing files."), missingFileName);
if (offendingProject->GetMissingAliasFileDialog()) {
offendingProject->GetMissingAliasFileDialog()->Raise();
} else {
ShowAliasMissingDialog(offendingProject.get(), _("Files Missing"),
MissingAliasFilesDialog::Show(offendingProject.get(), _("Files Missing"),
errorMessage, wxT(""), true);
}
}
// Only show this warning once per event (playback/menu item/etc).
SetMissingAliasedFileWarningShouldShow(false);
MissingAliasFilesDialog::SetShouldShow(false);
}
}
void AudacityApp::MarkAliasedFilesMissingWarning(const AliasBlockFile *b)
{
ODLocker locker { &m_LastMissingBlockFileLock };
if (b) {
size_t numProjects = gAudacityProjects.size();
for (size_t ii = 0; ii < numProjects; ++ii) {
// search each project for the blockfile
if (gAudacityProjects[ii]->GetDirManager()->ContainsBlockFile(b)) {
m_LastMissingBlockFileProject = gAudacityProjects[ii];
break;
}
}
}
else
m_LastMissingBlockFileProject = {};
if (b)
m_LastMissingBlockFilePath = b->GetAliasedFileName().GetFullPath();
else
m_LastMissingBlockFilePath = wxString{};
}
void AudacityApp::SetMissingAliasedFileWarningShouldShow(bool b)
{
// Note that this is can be called by both the main thread and other threads.
// I don't believe we need a mutex because we are checking zero vs non-zero,
// and the setting from other threads will always be non-zero (true), and the
// setting from the main thread is always false.
m_aliasMissingWarningShouldShow = b;
// reset the warnings as they were probably marked by a previous run
if (m_aliasMissingWarningShouldShow) {
MarkAliasedFilesMissingWarning( nullptr );
}
}
bool AudacityApp::ShouldShowMissingAliasedFileWarning()
{
ODLocker locker { &m_LastMissingBlockFileLock };
auto ptr = m_LastMissingBlockFileProject.lock();
return ptr && m_aliasMissingWarningShouldShow;
}
AudacityLogger *AudacityApp::GetLogger()
{
// Use dynamic_cast so that we get a NULL ptr if we haven't yet
// setup our logger.
return dynamic_cast<AudacityLogger *>(wxLog::GetActiveTarget());
}
#if defined(__WXMSW__)
#define WL(lang, sublang) (lang), (sublang),
#else
@ -992,101 +847,10 @@ wxLanguageInfo userLangs[] =
};
#endif
wxString AudacityApp::InitLang( wxString langCode )
{
if ( langCode.empty() )
langCode = gPrefs->Read(wxT("/Locale/Language"), wxEmptyString);
// Use the system default language if one wasn't specified or if the user selected System.
if (langCode.empty())
{
langCode = GetSystemLanguageCode();
}
// Initialize the language
return SetLang(langCode);
}
wxString AudacityApp::SetLang( const wxString & lang )
{
wxString result = lang;
mLocale.reset();
#if defined(__WXMAC__)
// This should be reviewed again during the wx3 conversion.
// On OSX, if the LANG environment variable isn't set when
// using a language like Japanese, an assertion will trigger
// because conversion to Japanese from "?" doesn't return a
// valid length, so make OSX happy by defining/overriding
// the LANG environment variable with U.S. English for now.
wxSetEnv(wxT("LANG"), wxT("en_US.UTF-8"));
#endif
const wxLanguageInfo *info = NULL;
if (!lang.empty()) {
info = wxLocale::FindLanguageInfo(lang);
if (!info)
::AudacityMessageBox(wxString::Format(_("Language \"%s\" is unknown"), lang));
}
if (!info)
{
result = GetSystemLanguageCode();
info = wxLocale::FindLanguageInfo(result);
if (!info)
return result;
}
mLocale = std::make_unique<wxLocale>(info->Language);
for(unsigned int i=0; i<audacityPathList.size(); i++)
mLocale->AddCatalogLookupPathPrefix(audacityPathList[i]);
// LL: Must add the wxWidgets catalog manually since the search
// paths were not set up when mLocale was created. The
// catalogs are search in LIFO order, so add wxstd first.
mLocale->AddCatalog(wxT("wxstd"));
// AUDACITY_NAME is legitimately used on some *nix configurations.
#ifdef AUDACITY_NAME
mLocale->AddCatalog(wxT(AUDACITY_NAME));
#else
mLocale->AddCatalog(IPC_APPL);
#endif
// Initialize internationalisation (number formats etc.)
//
// This must go _after_ creating the wxLocale instance because
// creating the wxLocale instance sets the application-wide locale.
Internat::Init();
// Notify listeners of language changes
{
wxCommandEvent evt(EVT_LANGUAGE_CHANGE);
ProcessEvent(evt);
}
// PRL: Moved this, do it only after language intialized
// Unused strings that we want to be translated, even though
// we're not using them yet...
wxString future1 = _("Master Gain Control");
return result;
}
wxString AudacityApp::GetLang() const
{
if (mLocale)
return mLocale->GetSysName();
else
return {};
}
void AudacityApp::OnFatalException()
{
#if defined(EXPERIMENTAL_CRASH_REPORT)
GenerateCrashReport(wxDebugReport::Context_Exception);
CrashReport::Generate(wxDebugReport::Context_Exception);
#endif
exit(-1);
@ -1150,59 +914,6 @@ bool AudacityApp::OnExceptionInMainLoop()
#pragma warning( pop )
#endif //_MSC_VER
#if defined(EXPERIMENTAL_CRASH_REPORT)
void AudacityApp::GenerateCrashReport(wxDebugReport::Context ctx)
{
wxDebugReportCompress rpt;
rpt.AddAll(ctx);
wxFileName fn(FileNames::DataDir(), wxT("audacity.cfg"));
rpt.AddFile(fn.GetFullPath(), _TS("Audacity Configuration"));
rpt.AddFile(FileNames::PluginRegistry(), wxT("Plugin Registry"));
rpt.AddFile(FileNames::PluginSettings(), wxT("Plugin Settings"));
if (ctx == wxDebugReport::Context_Current)
{
auto saveLang = GetLang();
InitLang( wxT("en") );
auto cleanup = finally( [&]{ InitLang( saveLang ); } );
rpt.AddText(wxT("audiodev.txt"), gAudioIO->GetDeviceInfo(), wxT("Audio Device Info"));
#ifdef EXPERIMENTAL_MIDI_OUT
rpt.AddText(wxT("mididev.txt"), gAudioIO->GetMidiDeviceInfo(), wxT("MIDI Device Info"));
#endif
}
AudacityLogger *logger = GetLogger();
if (logger)
{
rpt.AddText(wxT("log.txt"), logger->GetLog(), _TS("Audacity Log"));
}
bool ok = wxDebugReportPreviewStd().Show(rpt);
#if defined(__WXMSW__)
wxEventLoop::SetCriticalWindow(NULL);
#endif
if (ok && rpt.Process())
{
AudacityTextEntryDialog dlg(NULL,
_("Report generated to:"),
_("Audacity Support Data"),
rpt.GetCompressedFileName(),
wxOK | wxCENTER);
dlg.SetName(dlg.GetTitle());
dlg.ShowModal();
wxLogMessage(wxT("Report generated to: %s"),
rpt.GetCompressedFileName());
rpt.Reset();
}
}
#endif
int AudacityApp::FilterEvent(wxEvent & event)
{
(void)event;// compiler food (stops unused parameter warning)
@ -1280,15 +991,8 @@ bool AudacityApp::OnInit()
// Ensure we have an event loop during initialization
wxEventLoopGuarantor eventLoop;
// wxWidgets will clean up the logger for the main thread, so we can say
// safenew. See:
// http://docs.wxwidgets.org/3.0/classwx_log.html#a2525bf54fa3f31dc50e6e3cd8651e71d
std::unique_ptr < wxLog >
{ wxLog::SetActiveTarget(safenew AudacityLogger) }; // DELETE old
mLocale = NULL;
m_aliasMissingWarningShouldShow = true;
// cause initialization of wxWidgets' global logger target
(void) AudacityLogger::Get();
#if defined(__WXMAC__)
// Disable window animation
@ -1318,6 +1022,7 @@ bool AudacityApp::OnInit()
//
// Paths: set search path and temp dir path
//
FilePaths audacityPathList;
#ifdef __WXGTK__
/* Search path (for plug-ins, translations etc) is (in this order):
@ -1331,10 +1036,12 @@ bool AudacityApp::OnInit()
if (!envTempDir.empty()) {
/* On Unix systems, the environment variable TMPDIR may point to
an unusual path when /tmp and /var/tmp are not desirable. */
defaultTempDir.Printf(wxT("%s/audacity-%s"), envTempDir, wxGetUserId());
FileNames::SetDefaultTempDir( wxString::Format(
wxT("%s/audacity-%s"), envTempDir, wxGetUserId() ) );
} else {
/* On Unix systems, the default temp dir is in /var/tmp. */
defaultTempDir.Printf(wxT("/var/tmp/audacity-%s"), wxGetUserId());
FileNames::SetDefaultTempDir( wxString::Format(
wxT("/var/tmp/audacity-%s"), wxGetUserId() ) );
}
// DA: Path env variable.
@ -1344,36 +1051,36 @@ bool AudacityApp::OnInit()
wxString pathVar = wxGetenv(wxT("DARKAUDACITY_PATH"));
#endif
if (!pathVar.empty())
AddMultiPathsToPathList(pathVar, audacityPathList);
AddUniquePathToPathList(::wxGetCwd(), audacityPathList);
FileNames::AddMultiPathsToPathList(pathVar, audacityPathList);
FileNames::AddUniquePathToPathList(::wxGetCwd(), audacityPathList);
#ifdef AUDACITY_NAME
AddUniquePathToPathList(wxString::Format(wxT("%s/.%s-files"),
FileNames::AddUniquePathToPathList(wxString::Format(wxT("%s/.%s-files"),
home, wxT(AUDACITY_NAME)),
audacityPathList);
AddUniquePathToPathList(wxString::Format(wxT("%s/share/%s"),
FileNames::AddUniquePathToPathList(wxString::Format(wxT("%s/share/%s"),
wxT(INSTALL_PREFIX), wxT(AUDACITY_NAME)),
audacityPathList);
AddUniquePathToPathList(wxString::Format(wxT("%s/share/doc/%s"),
FileNames::AddUniquePathToPathList(wxString::Format(wxT("%s/share/doc/%s"),
wxT(INSTALL_PREFIX), wxT(AUDACITY_NAME)),
audacityPathList);
#else //AUDACITY_NAME
AddUniquePathToPathList(wxString::Format(wxT("%s/.audacity-files"),
FileNames::AddUniquePathToPathList(wxString::Format(wxT("%s/.audacity-files"),
home),
audacityPathList);
AddUniquePathToPathList(wxString::Format(wxT("%s/share/audacity"),
FileNames::AddUniquePathToPathList(wxString::Format(wxT("%s/share/audacity"),
wxT(INSTALL_PREFIX)),
audacityPathList);
AddUniquePathToPathList(wxString::Format(wxT("%s/share/doc/audacity"),
FileNames::AddUniquePathToPathList(wxString::Format(wxT("%s/share/doc/audacity"),
wxT(INSTALL_PREFIX)),
audacityPathList);
#endif //AUDACITY_NAME
AddUniquePathToPathList(wxString::Format(wxT("%s/share/locale"),
FileNames::AddUniquePathToPathList(wxString::Format(wxT("%s/share/locale"),
wxT(INSTALL_PREFIX)),
audacityPathList);
AddUniquePathToPathList(wxString::Format(wxT("./locale")),
FileNames::AddUniquePathToPathList(wxString::Format(wxT("./locale")),
audacityPathList);
#endif //__WXGTK__
@ -1396,38 +1103,43 @@ bool AudacityApp::OnInit()
#ifdef __WXMSW__
// On Windows, the path to the Audacity program is in argv[0]
wxString progPath = wxPathOnly(argv[0]);
AddUniquePathToPathList(progPath, audacityPathList);
AddUniquePathToPathList(progPath + wxT("\\Languages"), audacityPathList);
FileNames::AddUniquePathToPathList(progPath, audacityPathList);
FileNames::AddUniquePathToPathList(progPath + wxT("\\Languages"), audacityPathList);
// See bug #1271 for explanation of location
tmpDirLoc = FileNames::MkDir(wxStandardPaths::Get().GetUserLocalDataDir());
defaultTempDir.Printf(wxT("%s\\SessionData"),
tmpDirLoc);
FileNames::SetDefaultTempDir( wxString::Format(
wxT("%s\\SessionData"), tmpDirLoc ) );
#endif //__WXWSW__
#ifdef __WXMAC__
// On Mac OS X, the path to the Audacity program is in argv[0]
wxString progPath = wxPathOnly(argv[0]);
AddUniquePathToPathList(progPath, audacityPathList);
FileNames::AddUniquePathToPathList(progPath, audacityPathList);
// If Audacity is a "bundle" package, then the root directory is
// the great-great-grandparent of the directory containing the executable.
//AddUniquePathToPathList(progPath + wxT("/../../../"), audacityPathList);
//FileNames::AddUniquePathToPathList(progPath + wxT("/../../../"), audacityPathList);
// These allow for searching the "bundle"
AddUniquePathToPathList(progPath + wxT("/../"), audacityPathList);
AddUniquePathToPathList(progPath + wxT("/../Resources"), audacityPathList);
FileNames::AddUniquePathToPathList(
progPath + wxT("/../"), audacityPathList);
FileNames::AddUniquePathToPathList(
progPath + wxT("/../Resources"), audacityPathList);
// JKC Bug 1220: Using an actual temp directory for session data on Mac was
// wrong because it would get cleared out on a reboot.
defaultTempDir.Printf(wxT("%s/Library/Application Support/audacity/SessionData"),
tmpDirLoc);
FileNames::SetDefaultTempDir( wxString::Format(
wxT("%s/Library/Application Support/audacity/SessionData"), tmpDirLoc) );
//defaultTempDir.Printf(wxT("%s/audacity-%s"),
//FileNames::SetDefaultTempDir( wxString::Format(
// wxT("%s/audacity-%s"),
// tmpDirLoc,
// wxGetUserId());
// wxGetUserId() ) );
#endif //__WXMAC__
FileNames::SetAudacityPathList( std::move( audacityPathList ) );
// Define languanges for which we have translations, but that are not yet
// supported by wxWidgets.
//
@ -1447,10 +1159,6 @@ bool AudacityApp::OnInit()
this->AssociateFileTypes();
#endif
// TODO - read the number of files to store in history from preferences
mRecentFiles = std::make_unique<FileHistory>(ID_RECENT_LAST - ID_RECENT_FIRST + 1, ID_RECENT_CLEAR);
mRecentFiles->Load(*gPrefs, wxT("RecentFiles"));
theTheme.EnsureInitialised();
// AColor depends on theTheme.
@ -1594,8 +1302,9 @@ bool AudacityApp::OnInit()
wxMenuBar::MacSetCommonMenuBar(menuBar.release());
}
mRecentFiles->UseMenu(recentMenu);
mRecentFiles->AddFilesToMenu(recentMenu);
auto &recentFiles = FileHistory::Global();
recentFiles.UseMenu(recentMenu);
recentFiles.AddFilesToMenu(recentMenu);
SetExitOnFrameDelete(false);
@ -1686,8 +1395,6 @@ bool AudacityApp::OnInit()
ModuleManager::Get().Dispatch(AppInitialized);
mWindowRectAlreadySaved = FALSE;
mTimer.SetOwner(this, kAudacityAppTimerID);
mTimer.Start(200);
@ -1730,36 +1437,6 @@ void AudacityApp::OnKeyDown(wxKeyEvent &event)
event.Skip();
}
// We now disallow temp directory name that puts it where cleaner apps will
// try to clean out the files.
bool AudacityApp::IsTempDirectoryNameOK( const wxString & Name ){
if( Name.empty() )
return false;
wxFileName tmpFile;
tmpFile.AssignTempFileName(wxT("nn"));
// use Long Path to expand out any abbreviated long substrings.
wxString BadPath = tmpFile.GetLongPath();
::wxRemoveFile(tmpFile.GetFullPath());
#ifdef __WXMAC__
// This test is to fix bug 1220 on a 1.x to 2.x to 2.1.3 upgrade.
// It is less permissive than we could be as it stops a path
// with this string ANYWHERE within it rather than excluding just
// the paths that the earlier Audacities used to create.
if( Name.Contains( "/tmp/") )
return false;
BadPath = BadPath.BeforeLast( '/' ) + "/";
wxFileName cmpFile( Name );
wxString NameCanonical = cmpFile.GetLongPath( ) + "/";
#else
BadPath = BadPath.BeforeLast( '\\' ) + "\\";
wxFileName cmpFile( Name );
wxString NameCanonical = cmpFile.GetLongPath( ) + "\\";
#endif
return !(NameCanonical.StartsWith( BadPath ));
}
// Ensures directory is created and puts the name into result.
// result is unchanged if unsuccessful.
void SetToExtantDirectory( wxString & result, const wxString & dir ){
@ -1781,7 +1458,7 @@ bool AudacityApp::InitTempDir()
// We need to find a temp directory location.
wxString tempFromPrefs = gPrefs->Read(wxT("/Directories/TempDir"), wxT(""));
wxString tempDefaultLoc = wxGetApp().defaultTempDir;
auto tempDefaultLoc = FileNames::DefaultTempDir();
wxString temp;
@ -1795,7 +1472,7 @@ bool AudacityApp::InitTempDir()
wxLogNull logNo;
// Try temp dir that was stored in prefs first
if( IsTempDirectoryNameOK( tempFromPrefs ) )
if( FileNames::IsTempDirectoryNameOK( tempFromPrefs ) )
SetToExtantDirectory( temp, tempFromPrefs );
// If that didn't work, try the default location
@ -1818,7 +1495,7 @@ bool AudacityApp::InitTempDir()
if (temp.empty()) {
// Failed
if( !IsTempDirectoryNameOK( tempFromPrefs ) ) {
if( !FileNames::IsTempDirectoryNameOK( tempFromPrefs ) ) {
AudacityMessageBox(_("Audacity could not find a safe place to store temporary files.\nAudacity needs a place where automatic cleanup programs won't delete the temporary files.\nPlease enter an appropriate directory in the preferences dialog."));
} else {
AudacityMessageBox(_("Audacity could not find a place to store temporary files.\nPlease enter an appropriate directory in the preferences dialog."));
@ -2103,54 +1780,6 @@ std::unique_ptr<wxCmdLineParser> AudacityApp::ParseCommandLine()
return{};
}
// static
void AudacityApp::AddUniquePathToPathList(const FilePath &pathArg,
FilePaths &pathList)
{
wxFileName pathNorm = pathArg;
pathNorm.Normalize();
const wxString newpath{ pathNorm.GetFullPath() };
for(unsigned int i=0; i<pathList.size(); i++) {
if (wxFileName(newpath) == wxFileName(pathList[i]))
return;
}
pathList.push_back(newpath);
}
// static
void AudacityApp::AddMultiPathsToPathList(const wxString &multiPathStringArg,
FilePaths &pathList)
{
wxString multiPathString(multiPathStringArg);
while (!multiPathString.empty()) {
wxString onePath = multiPathString.BeforeFirst(wxPATH_SEP[0]);
multiPathString = multiPathString.AfterFirst(wxPATH_SEP[0]);
AddUniquePathToPathList(onePath, pathList);
}
}
// static
void AudacityApp::FindFilesInPathList(const wxString & pattern,
const FilePaths & pathList,
FilePaths & results,
int flags)
{
wxLogNull nolog;
if (pattern.empty()) {
return;
}
wxFileName ff;
for(size_t i = 0; i < pathList.size(); i++) {
ff = pathList[i] + wxFILE_SEP_PATH + pattern;
wxDir::GetAllFiles(ff.GetPath(), &results, ff.GetFullName(), flags);
}
}
void AudacityApp::OnQueryEndSession(wxCloseEvent & event)
{
bool mustVeto = false;
@ -2171,27 +1800,15 @@ void AudacityApp::OnEndSession(wxCloseEvent & event)
// Try to close each open window. If the user hits Cancel
// in a Save Changes dialog, don't continue.
if (!gAudacityProjects.empty()) {
while (gAudacityProjects.size()) {
// Closing the project has side-effect of
// deletion from gAudacityProjects
if (force) {
gAudacityProjects[0]->Close(true);
}
else if (!gAudacityProjects[0]->Close()) {
gIsQuitting = false;
event.Veto();
break;
}
}
gIsQuitting = true;
bool closedAll = AllProjects::Close( force );
if ( !closedAll )
{
gIsQuitting = false;
event.Veto();
}
}
void AudacityApp::AddFileToHistory(const FilePath & name)
{
mRecentFiles->AddFileToHistory(name);
}
int AudacityApp::OnExit()
{
gIsQuitting = true;
@ -2214,7 +1831,7 @@ int AudacityApp::OnExit()
}
}
mRecentFiles->Save(*gPrefs, wxT("RecentFiles"));
FileHistory::Global().Save(*gPrefs, wxT("RecentFiles"));
FinishPreferences();

View File

@ -20,15 +20,14 @@
#include "Experimental.h"
#include <wx/app.h> // to inherit
#include <wx/dir.h> // for wxDIR_FILES
#include <wx/timer.h> // member variable
#include "ondemand/ODTaskThread.h"
#if defined(EXPERIMENTAL_CRASH_REPORT)
#include <wx/debugrpt.h> // for wxDebugReport::Context
#endif
#include "MemoryX.h"
class wxSingleInstanceChecker;
class wxSocketEvent;
class wxSocketServer;
@ -37,26 +36,8 @@ class IPCServ;
class Importer;
class CommandHandler;
class AppCommandEvent;
class AudacityLogger;
class AudacityProject;
class FileHistory;
void SaveWindowSize();
void QuitAudacity(bool bForce);
void QuitAudacity();
extern bool gIsQuitting;
// An event emitted by the application whenever the global clipboard's
// contents change.
wxDECLARE_EXPORTED_EVENT( AUDACITY_DLL_API,
EVT_CLIPBOARD_CHANGE, wxCommandEvent);
// Asynchronous open
DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_OPEN_AUDIO_FILE, -1);
class BlockFile;
class AliasBlockFile;
class AudacityApp final : public wxApp {
@ -70,18 +51,6 @@ class AudacityApp final : public wxApp {
int FilterEvent(wxEvent & event) override;
// If no input language given, defaults first to choice in preferences, then
// to system language.
// Returns the language actually used which is not lang if lang cannot be found.
wxString InitLang( wxString lang = {} );
// If no input language given, defaults to system language.
// Returns the language actually used which is not lang if lang cannot be found.
wxString SetLang( const wxString & lang );
// Returns the last language code that was set
wxString GetLang() const;
// These are currently only used on Mac OS, where it's
// possible to have a menu bar but no windows open. It doesn't
// hurt any other platforms, though.
@ -112,22 +81,6 @@ class AudacityApp final : public wxApp {
void OnServerEvent(wxSocketEvent & evt);
void OnSocketEvent(wxSocketEvent & evt);
/** \brief Mark playback as having missing aliased blockfiles
*
* Playback will continue, but the missing files will be silenced
* ShouldShowMissingAliasedFileWarning can be called to determine
* if the user should be notified
*/
void MarkAliasedFilesMissingWarning(const AliasBlockFile *b);
/** \brief Changes the behavior of missing aliased blockfiles warnings
*/
void SetMissingAliasedFileWarningShouldShow(bool b);
/** \brief Returns true if the user should be notified of missing alias warnings
*/
bool ShouldShowMissingAliasedFileWarning();
#ifdef __WXMAC__
// In response to Apple Events
void MacOpenFile(const wxString &fileName) override;
@ -139,70 +92,20 @@ class AudacityApp final : public wxApp {
void AssociateFileTypes();
#endif
/** \brief A list of directories that should be searched for Audacity files
* (plug-ins, help files, etc.).
*
* On Unix this will include the directory Audacity was installed into,
* plus the current user's .audacity-data/Plug-Ins directory. Additional
* directories can be specified using the AUDACITY_PATH environment
* variable. On Windows or Mac OS, this will include the directory
* which contains the Audacity program. */
FilePaths audacityPathList;
/** \brief Default temp directory */
wxString defaultTempDir;
// Useful functions for working with search paths
static void AddUniquePathToPathList(const FilePath &path,
FilePaths &pathList);
static void AddMultiPathsToPathList(const wxString &multiPathString,
FilePaths &pathList);
static void FindFilesInPathList(const wxString & pattern,
const FilePaths & pathList,
FilePaths &results,
int flags = wxDIR_FILES);
static bool IsTempDirectoryNameOK( const wxString & Name );
FileHistory *GetRecentFiles() {return mRecentFiles.get();}
void AddFileToHistory(const FilePath & name);
bool GetWindowRectAlreadySaved()const {return mWindowRectAlreadySaved;}
void SetWindowRectAlreadySaved(bool alreadySaved) {mWindowRectAlreadySaved = alreadySaved;}
AudacityLogger *GetLogger();
#if defined(EXPERIMENTAL_CRASH_REPORT)
void GenerateCrashReport(wxDebugReport::Context ctx);
#endif
#ifdef __WXMAC__
void MacActivateApp();
#endif
// Set and Get values of the version major/minor/micro keys in audacity.cfg when Audacity first opens
void SetVersionKeysInit( int major, int minor, int micro)
{ mVersionMajorKeyInit = major; mVersionMinorKeyInit = minor; mVersionMicroKeyInit = micro;}
void GetVersionKeysInit( int& major, int& minor, int& micro) const
{ major = mVersionMajorKeyInit; minor = mVersionMinorKeyInit; micro = mVersionMicroKeyInit;}
private:
std::unique_ptr<CommandHandler> mCmdHandler;
std::unique_ptr<FileHistory> mRecentFiles;
std::unique_ptr<wxLocale> mLocale;
std::unique_ptr<wxSingleInstanceChecker> mChecker;
wxTimer mTimer;
bool m_aliasMissingWarningShouldShow;
std::weak_ptr< AudacityProject > m_LastMissingBlockFileProject;
wxString m_LastMissingBlockFilePath;
ODLock m_LastMissingBlockFileLock;
void InitCommandHandler();
bool InitTempDir();
@ -210,19 +113,12 @@ class AudacityApp final : public wxApp {
std::unique_ptr<wxCmdLineParser> ParseCommandLine();
bool mWindowRectAlreadySaved;
#if defined(__WXMSW__)
std::unique_ptr<IPCServ> mIPCServ;
#else
std::unique_ptr<wxSocketServer> mIPCServ;
#endif
// values of the version major/minor/micro keys in audacity.cfg when Audacity first opens
int mVersionMajorKeyInit{};
int mVersionMinorKeyInit{};
int mVersionMicroKeyInit{};
public:
DECLARE_EVENT_TABLE()
};

23
src/AudacityApp.mm Normal file
View File

@ -0,0 +1,23 @@
#ifdef __WXMAC__
#include "AudacityApp.h"
#include <AppKit/NSApplication.h>
// One Mac-only method of class AudacityApp that uses Objective-C is kept
// here so that AudacityApp.cpp can be just C++
// The function is not presently used. See commit
// a05d039055909d7d1dc2d4f31e1fe0659a3207dd
// whih added this function, and later commit
// e359383d3bebd583b894c9ee9d02cce2be318b56
// which made it unused. Maybe it will need future use.
void AudacityApp::MacActivateApp()
{
id app = [NSApplication sharedApplication];
if ( [app respondsToSelector:@selector(activateIgnoringOtherApps:)] )
[app activateIgnoringOtherApps:YES];
}
#endif

View File

@ -22,6 +22,7 @@ Provides thread-safe logging based on the wxWidgets log facility.
#include "FileNames.h"
#include "ShuttleGui.h"
#include <mutex>
#include <wx/filedlg.h>
#include <wx/log.h>
#include <wx/frame.h>
@ -50,6 +51,22 @@ enum
LoggerID_Close
};
AudacityLogger *AudacityLogger::Get()
{
static std::once_flag flag;
std::call_once( flag, []{
// wxWidgets will clean up the logger for the main thread, so we can say
// safenew. See:
// http://docs.wxwidgets.org/3.0/classwx_log.html#a2525bf54fa3f31dc50e6e3cd8651e71d
std::unique_ptr < wxLog > // DELETE any previous logger
{ wxLog::SetActiveTarget(safenew AudacityLogger) };
} );
// Use dynamic_cast so that we get a NULL ptr in case our logger
// is no longer the target.
return dynamic_cast<AudacityLogger *>(wxLog::GetActiveTarget());
}
AudacityLogger::AudacityLogger()
: wxEvtHandler(),
wxLog()

View File

@ -27,7 +27,9 @@ class wxTextCtrl;
class AudacityLogger final : public wxEvtHandler, public wxLog {
public:
AudacityLogger();
// Get the singleton instance or null
static AudacityLogger *Get();
void Show(bool show = true);
@ -40,6 +42,8 @@ class AudacityLogger final : public wxEvtHandler, public wxLog {
void DoLogText(const wxString & msg) override;
private:
AudacityLogger();
void OnCloseWindow(wxCloseEvent & e);
void OnClose(wxCommandEvent & e);
void OnClear(wxCommandEvent & e);

View File

@ -438,6 +438,7 @@ TimeTrack and AudioIOListener and whether the playback is looped.
#include "portmixer.h"
#endif
#include <wx/app.h>
#include <wx/wxcrtvararg.h>
#include <wx/log.h>
#include <wx/textctrl.h>
@ -447,7 +448,7 @@ TimeTrack and AudioIOListener and whether the playback is looped.
#include <wx/sstream.h>
#include <wx/txtstrm.h>
#include "AudacityApp.h"
#include "MissingAliasFileDialog.h"
#include "Mix.h"
#include "Resample.h"
#include "RingBuffer.h"
@ -2058,7 +2059,7 @@ int AudioIO::StartStream(const TransportTracks &tracks,
}
// Enable warning popups for unfound aliased blockfiles.
wxGetApp().SetMissingAliasedFileWarningShouldShow(true);
MissingAliasFilesDialog::SetShouldShow(true);
commit = true;
return mStreamToken;

View File

@ -53,7 +53,7 @@ out.
#include "sndfile.h"
#include "FileException.h"
#include "FileFormats.h"
#include "AudacityApp.h"
#include "MissingAliasFileDialog.h"
// msmeyer: Define this to add debug output via wxPrintf()
//#define DEBUG_BLOCKFILE
@ -537,8 +537,8 @@ size_t BlockFile::CommonReadData(
if (pAliasFile) {
// Set a marker to display an error message for the silence
if (!wxGetApp().ShouldShowMissingAliasedFileWarning())
wxGetApp().MarkAliasedFilesMissingWarning(pAliasFile);
if (!MissingAliasFilesDialog::ShouldShow())
MissingAliasFilesDialog::Mark(pAliasFile);
}
}
}

56
src/Clipboard.cpp Normal file
View File

@ -0,0 +1,56 @@
/**********************************************************************
Audacity: A Digital Audio Editor
Clipboard.cpp
*//*******************************************************************/
#include "Clipboard.h"
#include "Track.h"
wxDEFINE_EVENT( EVT_CLIPBOARD_CHANGE, wxCommandEvent);
Clipboard::Clipboard()
: mTracks { TrackList::Create() }
{
}
Clipboard::~Clipboard() = default;
Clipboard &Clipboard::Get()
{
static Clipboard instance;
return instance;
}
//static
const TrackList &Clipboard::GetTracks() const
{
return *mTracks;
}
void Clipboard::Clear()
{
mT0 = 0.0;
mT1 = 0.0;
mProject = nullptr;
mTracks->Clear();
// Emit an event for listeners
AddPendingEvent( wxCommandEvent{ EVT_CLIPBOARD_CHANGE } );
}
void Clipboard::Assign( TrackList && newContents,
double t0, double t1, AudacityProject *pProject )
{
newContents.Swap( *mTracks );
newContents.Clear();
mT0 = t0;
mT1 = t1;
mProject = pProject;
// Emit an event for listeners
AddPendingEvent( wxCommandEvent{ EVT_CLIPBOARD_CHANGE } );
}

56
src/Clipboard.h Normal file
View File

@ -0,0 +1,56 @@
/**********************************************************************
Audacity: A Digital Audio Editor
Clipboard.h
Paul Licameli
**********************************************************************/
#ifndef __AUDACITY_CLIPBOARD__
#define __AUDACITY_CLIPBOARD__
#include "Audacity.h"
#include <memory>
#include <wx/event.h> // to inherit wxEvtHandler
class AudacityProject;
class TrackList;
// An event emitted by the clipboard whenever its contents change.
wxDECLARE_EXPORTED_EVENT( AUDACITY_DLL_API,
EVT_CLIPBOARD_CHANGE, wxCommandEvent );
class Clipboard final
: public wxEvtHandler
{
public:
static Clipboard &Get();
const TrackList &GetTracks() const;
double T0() const { return mT0; }
double T1() const { return mT1; }
double Duration() const { return mT1 - mT0; }
AudacityProject *Project() const { return mProject; }
void Clear();
void Assign(
TrackList && newContents, double t0, double t1,
AudacityProject *pProject );
private:
Clipboard();
~Clipboard();
std::shared_ptr<TrackList> mTracks;
AudacityProject *mProject{};
double mT0{ 0 };
double mT1{ 0 };
};
#endif

77
src/CrashReport.cpp Normal file
View File

@ -0,0 +1,77 @@
/**********************************************************************
Audacity: A Digital Audio Editor
CrashReport.cpp
*//*******************************************************************/
#include "Audacity.h"
#include "CrashReport.h"
#include "Experimental.h"
#if defined(EXPERIMENTAL_CRASH_REPORT)
#include "wxFileNameWrapper.h"
#include "AudacityLogger.h"
#include "AudioIO.h"
#include "FileNames.h"
#include "Internat.h"
#include "prefs/GUIPrefs.h"
#include "widgets/ErrorDialog.h"
namespace CrashReport {
void Generate(wxDebugReport::Context ctx)
{
wxDebugReportCompress rpt;
rpt.AddAll(ctx);
wxFileNameWrapper fn{ FileNames::DataDir(), wxT("audacity.cfg") };
rpt.AddFile(fn.GetFullPath(), _TS("Audacity Configuration"));
rpt.AddFile(FileNames::PluginRegistry(), wxT("Plugin Registry"));
rpt.AddFile(FileNames::PluginSettings(), wxT("Plugin Settings"));
if (ctx == wxDebugReport::Context_Current)
{
auto saveLang = GUIPrefs::GetLang();
GUIPrefs::InitLang( wxT("en") );
auto cleanup = finally( [&]{ GUIPrefs::InitLang( saveLang ); } );
rpt.AddText(wxT("audiodev.txt"), gAudioIO->GetDeviceInfo(), wxT("Audio Device Info"));
#ifdef EXPERIMENTAL_MIDI_OUT
rpt.AddText(wxT("mididev.txt"), gAudioIO->GetMidiDeviceInfo(), wxT("MIDI Device Info"));
#endif
}
auto logger = AudacityLogger::Get();
if (logger)
{
rpt.AddText(wxT("log.txt"), logger->GetLog(), _TS("Audacity Log"));
}
bool ok = wxDebugReportPreviewStd().Show(rpt);
#if defined(__WXMSW__)
wxEventLoop::SetCriticalWindow(NULL);
#endif
if (ok && rpt.Process())
{
AudacityTextEntryDialog dlg(NULL,
_("Report generated to:"),
_("Audacity Support Data"),
rpt.GetCompressedFileName(),
wxOK | wxCENTER);
dlg.SetName(dlg.GetTitle());
dlg.ShowModal();
wxLogMessage(wxT("Report generated to: %s"),
rpt.GetCompressedFileName());
rpt.Reset();
}
}
}
#endif

29
src/CrashReport.h Normal file
View File

@ -0,0 +1,29 @@
/**********************************************************************
Audacity: A Digital Audio Editor
CrashReport.h
Paul Licameli
split from AudacityApp.h
**********************************************************************/
#ifndef __AUDACITY_CRASH_REPORT__
#define __AUDACITY_CRASH_REPORT__
#include "Audacity.h"
#include "Experimental.h"
#if defined(EXPERIMENTAL_CRASH_REPORT)
#include <wx/debugrpt.h>
namespace CrashReport
{
void Generate(wxDebugReport::Context ctx);
}
#endif
#endif

View File

@ -68,7 +68,6 @@
#include <wx/wxcrtvararg.h>
#include <wx/defs.h>
#include <wx/app.h>
#include <wx/dir.h>
#include <wx/log.h>
#include <wx/filefn.h>
@ -86,7 +85,7 @@
#include <sys/stat.h>
#endif
#include "AudacityApp.h"
#include "Clipboard.h"
#include "FileNames.h"
#include "blockfile/LegacyBlockFile.h"
#include "blockfile/LegacyAliasBlockFile.h"
@ -94,6 +93,7 @@
#include "blockfile/ODPCMAliasBlockFile.h"
#include "blockfile/ODDecodeBlockFile.h"
#include "InconsistencyException.h"
#include "MissingAliasFileDialog.h"
#include "Project.h"
#include "Prefs.h"
#include "Sequence.h"
@ -1701,12 +1701,12 @@ int DirManager::ProjectFSCK(const bool bForceError, const bool bAutoRecoverMode)
//
// MISSING ALIASED AUDIO FILES
//
wxGetApp().SetMissingAliasedFileWarningShouldShow(false);
BlockHash missingAliasedFileAUFHash; // (.auf) AliasBlockFiles whose aliased files are missing
BlockHash missingAliasedFilePathHash; // full paths of missing aliased files
this->FindMissingAliasedFiles(missingAliasedFileAUFHash, missingAliasedFilePathHash);
MissingAliasFilesDialog::SetShouldShow(false);
BlockHash missingAliasFilesAUFHash; // (.auf) AliasBlockFiles whose aliased files are missing
BlockHash missingAliasFilesPathHash; // full paths of missing aliased files
this->FindMissingAliasFiles(missingAliasFilesAUFHash, missingAliasFilesPathHash);
if ((nResult != FSCKstatus_CLOSE_REQ) && !missingAliasedFileAUFHash.empty())
if ((nResult != FSCKstatus_CLOSE_REQ) && !missingAliasFilesAUFHash.empty())
{
// In auto-recover mode, we always create silent blocks, and do not ask user.
// This makes sure the project is complete next time we open it.
@ -1728,7 +1728,7 @@ _("Project check of \"%s\" folder \
\nproject in its current state, unless you \"Close \
\nproject immediately\" on further error alerts.");
wxString msg;
msg.Printf(msgA, this->projName, (long long) missingAliasedFilePathHash.size());
msg.Printf(msgA, this->projName, (long long) missingAliasFilesPathHash.size());
const wxChar *buttons[] =
{_("Close project immediately with no changes"),
_("Treat missing audio as silence (this session only)"),
@ -1743,8 +1743,8 @@ _("Project check of \"%s\" folder \
else
{
// LL: A progress dialog should probably be used here
BlockHash::iterator iter = missingAliasedFileAUFHash.begin();
while (iter != missingAliasedFileAUFHash.end())
BlockHash::iterator iter = missingAliasFilesAUFHash.begin();
while (iter != missingAliasFilesAUFHash.end())
{
// This type cast is safe. We checked that it's an alias block file earlier.
BlockFilePtr b = iter->second.lock();
@ -1989,7 +1989,7 @@ other projects. \
// Summarize and flush the log.
if (bForceError ||
!missingAliasedFileAUFHash.empty() ||
!missingAliasFilesAUFHash.empty() ||
!missingAUFHash.empty() ||
!missingAUHash.empty() ||
!orphanFilePathArray.empty())
@ -2005,13 +2005,13 @@ other projects. \
wxOK | wxICON_EXCLAMATION);
}
wxGetApp().SetMissingAliasedFileWarningShouldShow(true);
MissingAliasFilesDialog::SetShouldShow(true);
return nResult;
}
void DirManager::FindMissingAliasedFiles(
BlockHash& missingAliasedFileAUFHash, // output: (.auf) AliasBlockFiles whose aliased files are missing
BlockHash& missingAliasedFilePathHash) // output: full paths of missing aliased files
void DirManager::FindMissingAliasFiles(
BlockHash& missingAliasFilesAUFHash, // output: (.auf) AliasBlockFiles whose aliased files are missing
BlockHash& missingAliasFilesPathHash) // output: full paths of missing aliased files
{
BlockHash::iterator iter = mBlockFileHash.begin();
while (iter != mBlockFileHash.end())
@ -2028,20 +2028,20 @@ void DirManager::FindMissingAliasedFiles(
if ((!aliasedFileFullPath.empty()) &&
!aliasedFileName.FileExists())
{
missingAliasedFileAUFHash[key] = b;
if (missingAliasedFilePathHash.find(aliasedFileFullPath) ==
missingAliasedFilePathHash.end()) // Add it only once.
missingAliasFilesAUFHash[key] = b;
if (missingAliasFilesPathHash.find(aliasedFileFullPath) ==
missingAliasFilesPathHash.end()) // Add it only once.
// Not actually using the block here, just the path,
// so set the block to NULL to create the entry.
missingAliasedFilePathHash[aliasedFileFullPath] = {};
missingAliasFilesPathHash[aliasedFileFullPath] = {};
}
}
}
++iter;
}
iter = missingAliasedFilePathHash.begin();
while (iter != missingAliasedFilePathHash.end())
iter = missingAliasFilesPathHash.begin();
while (iter != missingAliasFilesPathHash.end())
{
wxLogWarning(_("Missing aliased audio file: '%s'"), iter->first);
++iter;
@ -2124,13 +2124,11 @@ void DirManager::FindOrphanBlockFiles(
ext.IsSameAs(wxT("auf"), false)))
{
if (!clipboardDM) {
TrackList *clipTracks = AudacityProject::GetClipboardTracks();
auto &clipTracks = Clipboard::Get().GetTracks();
if (clipTracks) {
auto track = *clipTracks->Any().first;
if (track)
clipboardDM = track->GetDirManager().get();
}
auto track = *clipTracks.Any().first;
if (track)
clipboardDM = track->GetDirManager().get();
}
// Ignore it if it exists in the clipboard (from a previously closed project)

View File

@ -159,9 +159,9 @@ class PROFILE_DLL_API DirManager final : public XMLTagHandler {
// Too complicated during auto-recover. Just correct problems the "safest" way.
int ProjectFSCK(const bool bForceError, const bool bAutoRecoverMode);
void FindMissingAliasedFiles(
BlockHash& missingAliasedFileAUFHash, // output: (.auf) AliasBlockFiles whose aliased files are missing
BlockHash& missingAliasedFilePathHash); // output: full paths of missing aliased files
void FindMissingAliasFiles(
BlockHash& missingAliasFilesAUFHash, // output: (.auf) AliasBlockFiles whose aliased files are missing
BlockHash& missingAliasFilesPathHash); // output: full paths of missing aliased files
void FindMissingAUFs(
BlockHash& missingAUFHash); // output: missing (.auf) AliasBlockFiles
void FindMissingAUs(

View File

@ -475,3 +475,109 @@ FileNames::SelectFile(Operation op,
wildcard, flags, parent, wxDefaultCoord, wxDefaultCoord);
});
}
/** \brief Default temp directory */
static FilePath sDefaultTempDir;
const FilePath &FileNames::DefaultTempDir()
{
return sDefaultTempDir;
}
void FileNames::SetDefaultTempDir( const FilePath &tempDir )
{
sDefaultTempDir = tempDir;
}
// We now disallow temp directory name that puts it where cleaner apps will
// try to clean out the files.
bool FileNames::IsTempDirectoryNameOK( const FilePath & Name )
{
if( Name.empty() )
return false;
wxFileName tmpFile;
tmpFile.AssignTempFileName(wxT("nn"));
// use Long Path to expand out any abbreviated long substrings.
wxString BadPath = tmpFile.GetLongPath();
::wxRemoveFile(tmpFile.GetFullPath());
#ifdef __WXMAC__
// This test is to fix bug 1220 on a 1.x to 2.x to 2.1.3 upgrade.
// It is less permissive than we could be as it stops a path
// with this string ANYWHERE within it rather than excluding just
// the paths that the earlier Audacities used to create.
if( Name.Contains( "/tmp/") )
return false;
BadPath = BadPath.BeforeLast( '/' ) + "/";
wxFileName cmpFile( Name );
wxString NameCanonical = cmpFile.GetLongPath( ) + "/";
#else
BadPath = BadPath.BeforeLast( '\\' ) + "\\";
wxFileName cmpFile( Name );
wxString NameCanonical = cmpFile.GetLongPath( ) + "\\";
#endif
return !(NameCanonical.StartsWith( BadPath ));
}
static FilePaths sAudacityPathList;
const FilePaths &FileNames::AudacityPathList()
{
return sAudacityPathList;
}
void FileNames::SetAudacityPathList( FilePaths list )
{
sAudacityPathList = std::move( list );
}
// static
void FileNames::AddUniquePathToPathList(const FilePath &pathArg,
FilePaths &pathList)
{
wxFileNameWrapper pathNorm { pathArg };
pathNorm.Normalize();
const wxString newpath{ pathNorm.GetFullPath() };
for(const auto &path : pathList) {
if (pathNorm == wxFileNameWrapper{ path })
return;
}
pathList.push_back(newpath);
}
// static
void FileNames::AddMultiPathsToPathList(const wxString &multiPathStringArg,
FilePaths &pathList)
{
wxString multiPathString(multiPathStringArg);
while (!multiPathString.empty()) {
wxString onePath = multiPathString.BeforeFirst(wxPATH_SEP[0]);
multiPathString = multiPathString.AfterFirst(wxPATH_SEP[0]);
AddUniquePathToPathList(onePath, pathList);
}
}
#include <wx/log.h>
// static
void FileNames::FindFilesInPathList(const wxString & pattern,
const FilePaths & pathList,
FilePaths & results,
int flags)
{
wxLogNull nolog;
if (pattern.empty()) {
return;
}
wxFileNameWrapper ff;
for(size_t i = 0; i < pathList.size(); i++) {
ff = pathList[i] + wxFILE_SEP_PATH + pattern;
wxDir::GetAllFiles(ff.GetPath(), &results, ff.GetFullName(), flags);
}
}

View File

@ -13,6 +13,7 @@
#include "Audacity.h"
#include <wx/dir.h> // for wxDIR_FILES
#include <wx/string.h> // function return value
#include "audacity/Types.h"
@ -36,6 +37,21 @@ public:
static wxString MkDir(const wxString &Str);
static wxString TempDir();
static const FilePath &DefaultTempDir();
static void SetDefaultTempDir( const FilePath &tempDir );
static bool IsTempDirectoryNameOK( const FilePath & Name );
/** \brief A list of directories that should be searched for Audacity files
* (plug-ins, help files, etc.).
*
* On Unix this will include the directory Audacity was installed into,
* plus the current user's .audacity-data/Plug-Ins directory. Additional
* directories can be specified using the AUDACITY_PATH environment
* variable. On Windows or Mac OS, this will include the directory
* which contains the Audacity program. */
static const FilePaths &AudacityPathList();
static void SetAudacityPathList( FilePaths list );
// originally an ExportMultiple method. Append suffix if newName appears in otherNames.
static void MakeNameUnique(
FilePaths &otherNames, wxFileName &newName);
@ -119,6 +135,16 @@ public:
int flags,
wxWindow *parent);
// Useful functions for working with search paths
static void AddUniquePathToPathList(const FilePath &path,
FilePaths &pathList);
static void AddMultiPathsToPathList(const wxString &multiPathString,
FilePaths &pathList);
static void FindFilesInPathList(const wxString & pattern,
const FilePaths & pathList,
FilePaths &results,
int flags = wxDIR_FILES);
private:
// Private constructors: No one is ever going to instantiate it.
//

View File

@ -33,7 +33,7 @@ undo memory so as to free up space.
#include <wx/textctrl.h>
#include "AudioIO.h"
#include "AudacityApp.h"
#include "Clipboard.h"
#include "../images/Arrow.xpm"
#include "../images/Empty9x16.xpm"
#include "UndoManager.h"
@ -155,7 +155,8 @@ HistoryWindow::HistoryWindow(AudacityProject *parent, UndoManager *manager):
&HistoryWindow::OnAudioIO,
this);
wxTheApp->Bind(EVT_CLIPBOARD_CHANGE, &HistoryWindow::UpdateDisplay, this);
Clipboard::Get().Bind(
EVT_CLIPBOARD_CHANGE, &HistoryWindow::UpdateDisplay, this);
manager->Bind(EVT_UNDO_PUSHED, &HistoryWindow::UpdateDisplay, this);
manager->Bind(EVT_UNDO_MODIFIED, &HistoryWindow::UpdateDisplay, this);
manager->Bind(EVT_UNDO_RESET, &HistoryWindow::UpdateDisplay, this);
@ -263,8 +264,7 @@ void HistoryWindow::OnDiscard(wxCommandEvent & WXUNUSED(event))
void HistoryWindow::OnDiscardClipboard(wxCommandEvent & WXUNUSED(event))
{
AudacityProject::ClearClipboard();
DoUpdate();
Clipboard::Get().Clear();
}
void HistoryWindow::OnItemSelected(wxListEvent &event)

View File

@ -32,6 +32,7 @@
#include "Audacity.h"
#include "Languages.h"
#include "MemoryX.h"
#include "audacity/Types.h"
@ -41,8 +42,6 @@
#include "FileNames.h"
#include "AudacityApp.h"
#include <unordered_map>
using LangHash = std::unordered_map<wxString, wxString>;
@ -50,18 +49,18 @@ using LangHash = std::unordered_map<wxString, wxString>;
static bool TranslationExists(const FilePaths &audacityPathList, wxString code)
{
FilePaths results;
wxGetApp().FindFilesInPathList(wxString::Format(wxT("%s/audacity.mo"),
FileNames::FindFilesInPathList(wxString::Format(wxT("%s/audacity.mo"),
code),
audacityPathList,
results);
#if defined(__WXMAC__)
wxGetApp().FindFilesInPathList(wxString::Format(wxT("%s.lproj/audacity.mo"),
FileNames::FindFilesInPathList(wxString::Format(wxT("%s.lproj/audacity.mo"),
code),
audacityPathList,
results);
#endif
wxGetApp().FindFilesInPathList(wxString::Format(wxT("%s/LC_MESSAGES/audacity.mo"),
FileNames::FindFilesInPathList(wxString::Format(wxT("%s/LC_MESSAGES/audacity.mo"),
code),
audacityPathList,
results);
@ -203,12 +202,13 @@ void GetLanguages(wxArrayString &langCodes, wxArrayString &langNames)
localLanguageName[code] = name;
}
auto audacityPathList = wxGetApp().audacityPathList;
auto audacityPathList = FileNames::AudacityPathList();
#if defined(__WXGTK__)
wxGetApp().AddUniquePathToPathList(wxString::Format(wxT("%s/share/locale"),
wxT(INSTALL_PREFIX)),
audacityPathList);
FileNames::AddUniquePathToPathList(
wxString::Format(wxT("%s/share/locale"),
wxT(INSTALL_PREFIX)),
audacityPathList);
#endif
// For each language in our list we look for a corresponding entry in

View File

@ -125,6 +125,10 @@ audacity_SOURCES = \
Benchmark.h \
CellularPanel.cpp \
CellularPanel.h \
Clipboard.cpp \
Clipboard.h \
CrashReport.cpp \
CrashReport.h \
Dependencies.cpp \
Dependencies.h \
DeviceChange.cpp \
@ -180,6 +184,8 @@ audacity_SOURCES = \
MemoryX.h \
Menus.cpp \
Menus.h \
MissingAliasFileDialog.cpp \
MissingAliasFileDialog.h \
Mix.cpp \
Mix.h \
MixerBoard.cpp \

View File

@ -297,12 +297,13 @@ am__audacity_SOURCES_DIST = BlockFile.cpp BlockFile.h DirManager.cpp \
AutoRecovery.h BatchCommandDialog.cpp BatchCommandDialog.h \
BatchCommands.cpp BatchCommands.h BatchProcessDialog.cpp \
BatchProcessDialog.h Benchmark.cpp Benchmark.h \
CellularPanel.cpp CellularPanel.h Dependencies.cpp \
Dependencies.h DeviceChange.cpp DeviceChange.h \
DeviceManager.cpp DeviceManager.h Diags.cpp Diags.h \
Envelope.cpp Envelope.h Experimental.h FFmpeg.cpp FFmpeg.h \
FFT.cpp FFT.h FileException.cpp FileException.h FileIO.cpp \
FileIO.h FileNames.cpp FileNames.h float_cast.h FreqWindow.cpp \
CellularPanel.cpp CellularPanel.h Clipboard.cpp Clipboard.h \
CrashReport.cpp CrashReport.h Dependencies.cpp Dependencies.h \
DeviceChange.cpp DeviceChange.h DeviceManager.cpp \
DeviceManager.h Diags.cpp Diags.h Envelope.cpp Envelope.h \
Experimental.h FFmpeg.cpp FFmpeg.h FFT.cpp FFT.h \
FileException.cpp FileException.h FileIO.cpp FileIO.h \
FileNames.cpp FileNames.h float_cast.h FreqWindow.cpp \
FreqWindow.h HelpText.cpp HelpText.h HistoryWindow.cpp \
HistoryWindow.h HitTestResult.h ImageManipulation.cpp \
ImageManipulation.h InconsistencyException.cpp \
@ -311,9 +312,10 @@ am__audacity_SOURCES_DIST = BlockFile.cpp BlockFile.h DirManager.cpp \
LabelTrack.cpp LabelTrack.h LangChoice.cpp LangChoice.h \
Languages.cpp Languages.h Legacy.cpp Legacy.h Lyrics.cpp \
Lyrics.h LyricsWindow.cpp LyricsWindow.h MacroMagic.h \
Matrix.cpp Matrix.h MemoryX.h Menus.cpp Menus.h Mix.cpp Mix.h \
MixerBoard.cpp MixerBoard.h ModuleManager.cpp ModuleManager.h \
NumberScale.h PitchName.cpp PitchName.h \
Matrix.cpp Matrix.h MemoryX.h Menus.cpp Menus.h \
MissingAliasFileDialog.cpp MissingAliasFileDialog.h Mix.cpp \
Mix.h MixerBoard.cpp MixerBoard.h ModuleManager.cpp \
ModuleManager.h NumberScale.h PitchName.cpp PitchName.h \
PlatformCompatibility.cpp PlatformCompatibility.h \
PluginManager.cpp PluginManager.h Printing.cpp Printing.h \
Profiler.cpp Profiler.h Project.cpp Project.h RealFFTf.cpp \
@ -633,6 +635,7 @@ am_audacity_OBJECTS = $(am__objects_1) audacity-AboutDialog.$(OBJEXT) \
audacity-BatchCommands.$(OBJEXT) \
audacity-BatchProcessDialog.$(OBJEXT) \
audacity-Benchmark.$(OBJEXT) audacity-CellularPanel.$(OBJEXT) \
audacity-Clipboard.$(OBJEXT) audacity-CrashReport.$(OBJEXT) \
audacity-Dependencies.$(OBJEXT) \
audacity-DeviceChange.$(OBJEXT) \
audacity-DeviceManager.$(OBJEXT) audacity-Diags.$(OBJEXT) \
@ -648,9 +651,10 @@ am_audacity_OBJECTS = $(am__objects_1) audacity-AboutDialog.$(OBJEXT) \
audacity-LangChoice.$(OBJEXT) audacity-Languages.$(OBJEXT) \
audacity-Legacy.$(OBJEXT) audacity-Lyrics.$(OBJEXT) \
audacity-LyricsWindow.$(OBJEXT) audacity-Matrix.$(OBJEXT) \
audacity-Menus.$(OBJEXT) audacity-Mix.$(OBJEXT) \
audacity-MixerBoard.$(OBJEXT) audacity-ModuleManager.$(OBJEXT) \
audacity-PitchName.$(OBJEXT) \
audacity-Menus.$(OBJEXT) \
audacity-MissingAliasFileDialog.$(OBJEXT) \
audacity-Mix.$(OBJEXT) audacity-MixerBoard.$(OBJEXT) \
audacity-ModuleManager.$(OBJEXT) audacity-PitchName.$(OBJEXT) \
audacity-PlatformCompatibility.$(OBJEXT) \
audacity-PluginManager.$(OBJEXT) audacity-Printing.$(OBJEXT) \
audacity-Profiler.$(OBJEXT) audacity-Project.$(OBJEXT) \
@ -1243,7 +1247,6 @@ pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
@ -1347,12 +1350,13 @@ audacity_SOURCES = $(libaudacity_la_SOURCES) AboutDialog.cpp \
AutoRecovery.h BatchCommandDialog.cpp BatchCommandDialog.h \
BatchCommands.cpp BatchCommands.h BatchProcessDialog.cpp \
BatchProcessDialog.h Benchmark.cpp Benchmark.h \
CellularPanel.cpp CellularPanel.h Dependencies.cpp \
Dependencies.h DeviceChange.cpp DeviceChange.h \
DeviceManager.cpp DeviceManager.h Diags.cpp Diags.h \
Envelope.cpp Envelope.h Experimental.h FFmpeg.cpp FFmpeg.h \
FFT.cpp FFT.h FileException.cpp FileException.h FileIO.cpp \
FileIO.h FileNames.cpp FileNames.h float_cast.h FreqWindow.cpp \
CellularPanel.cpp CellularPanel.h Clipboard.cpp Clipboard.h \
CrashReport.cpp CrashReport.h Dependencies.cpp Dependencies.h \
DeviceChange.cpp DeviceChange.h DeviceManager.cpp \
DeviceManager.h Diags.cpp Diags.h Envelope.cpp Envelope.h \
Experimental.h FFmpeg.cpp FFmpeg.h FFT.cpp FFT.h \
FileException.cpp FileException.h FileIO.cpp FileIO.h \
FileNames.cpp FileNames.h float_cast.h FreqWindow.cpp \
FreqWindow.h HelpText.cpp HelpText.h HistoryWindow.cpp \
HistoryWindow.h HitTestResult.h ImageManipulation.cpp \
ImageManipulation.h InconsistencyException.cpp \
@ -1361,9 +1365,10 @@ audacity_SOURCES = $(libaudacity_la_SOURCES) AboutDialog.cpp \
LabelTrack.cpp LabelTrack.h LangChoice.cpp LangChoice.h \
Languages.cpp Languages.h Legacy.cpp Legacy.h Lyrics.cpp \
Lyrics.h LyricsWindow.cpp LyricsWindow.h MacroMagic.h \
Matrix.cpp Matrix.h MemoryX.h Menus.cpp Menus.h Mix.cpp Mix.h \
MixerBoard.cpp MixerBoard.h ModuleManager.cpp ModuleManager.h \
NumberScale.h PitchName.cpp PitchName.h \
Matrix.cpp Matrix.h MemoryX.h Menus.cpp Menus.h \
MissingAliasFileDialog.cpp MissingAliasFileDialog.h Mix.cpp \
Mix.h MixerBoard.cpp MixerBoard.h ModuleManager.cpp \
ModuleManager.h NumberScale.h PitchName.cpp PitchName.h \
PlatformCompatibility.cpp PlatformCompatibility.h \
PluginManager.cpp PluginManager.h Printing.cpp Printing.h \
Profiler.cpp Profiler.h Project.cpp Project.h RealFFTf.cpp \
@ -2492,6 +2497,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-Benchmark.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-BlockFile.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-CellularPanel.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-Clipboard.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-CrashReport.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-Dependencies.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-DeviceChange.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-DeviceManager.Po@am__quote@
@ -2521,6 +2528,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-LyricsWindow.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-Matrix.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-Menus.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-MissingAliasFileDialog.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-Mix.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-MixerBoard.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-ModuleManager.Po@am__quote@
@ -3399,6 +3407,34 @@ audacity-CellularPanel.obj: CellularPanel.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o audacity-CellularPanel.obj `if test -f 'CellularPanel.cpp'; then $(CYGPATH_W) 'CellularPanel.cpp'; else $(CYGPATH_W) '$(srcdir)/CellularPanel.cpp'; fi`
audacity-Clipboard.o: Clipboard.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT audacity-Clipboard.o -MD -MP -MF $(DEPDIR)/audacity-Clipboard.Tpo -c -o audacity-Clipboard.o `test -f 'Clipboard.cpp' || echo '$(srcdir)/'`Clipboard.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/audacity-Clipboard.Tpo $(DEPDIR)/audacity-Clipboard.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='Clipboard.cpp' object='audacity-Clipboard.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o audacity-Clipboard.o `test -f 'Clipboard.cpp' || echo '$(srcdir)/'`Clipboard.cpp
audacity-Clipboard.obj: Clipboard.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT audacity-Clipboard.obj -MD -MP -MF $(DEPDIR)/audacity-Clipboard.Tpo -c -o audacity-Clipboard.obj `if test -f 'Clipboard.cpp'; then $(CYGPATH_W) 'Clipboard.cpp'; else $(CYGPATH_W) '$(srcdir)/Clipboard.cpp'; fi`
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/audacity-Clipboard.Tpo $(DEPDIR)/audacity-Clipboard.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='Clipboard.cpp' object='audacity-Clipboard.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o audacity-Clipboard.obj `if test -f 'Clipboard.cpp'; then $(CYGPATH_W) 'Clipboard.cpp'; else $(CYGPATH_W) '$(srcdir)/Clipboard.cpp'; fi`
audacity-CrashReport.o: CrashReport.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT audacity-CrashReport.o -MD -MP -MF $(DEPDIR)/audacity-CrashReport.Tpo -c -o audacity-CrashReport.o `test -f 'CrashReport.cpp' || echo '$(srcdir)/'`CrashReport.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/audacity-CrashReport.Tpo $(DEPDIR)/audacity-CrashReport.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CrashReport.cpp' object='audacity-CrashReport.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o audacity-CrashReport.o `test -f 'CrashReport.cpp' || echo '$(srcdir)/'`CrashReport.cpp
audacity-CrashReport.obj: CrashReport.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT audacity-CrashReport.obj -MD -MP -MF $(DEPDIR)/audacity-CrashReport.Tpo -c -o audacity-CrashReport.obj `if test -f 'CrashReport.cpp'; then $(CYGPATH_W) 'CrashReport.cpp'; else $(CYGPATH_W) '$(srcdir)/CrashReport.cpp'; fi`
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/audacity-CrashReport.Tpo $(DEPDIR)/audacity-CrashReport.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CrashReport.cpp' object='audacity-CrashReport.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o audacity-CrashReport.obj `if test -f 'CrashReport.cpp'; then $(CYGPATH_W) 'CrashReport.cpp'; else $(CYGPATH_W) '$(srcdir)/CrashReport.cpp'; fi`
audacity-Dependencies.o: Dependencies.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT audacity-Dependencies.o -MD -MP -MF $(DEPDIR)/audacity-Dependencies.Tpo -c -o audacity-Dependencies.o `test -f 'Dependencies.cpp' || echo '$(srcdir)/'`Dependencies.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/audacity-Dependencies.Tpo $(DEPDIR)/audacity-Dependencies.Po
@ -3749,6 +3785,20 @@ audacity-Menus.obj: Menus.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o audacity-Menus.obj `if test -f 'Menus.cpp'; then $(CYGPATH_W) 'Menus.cpp'; else $(CYGPATH_W) '$(srcdir)/Menus.cpp'; fi`
audacity-MissingAliasFileDialog.o: MissingAliasFileDialog.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT audacity-MissingAliasFileDialog.o -MD -MP -MF $(DEPDIR)/audacity-MissingAliasFileDialog.Tpo -c -o audacity-MissingAliasFileDialog.o `test -f 'MissingAliasFileDialog.cpp' || echo '$(srcdir)/'`MissingAliasFileDialog.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/audacity-MissingAliasFileDialog.Tpo $(DEPDIR)/audacity-MissingAliasFileDialog.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='MissingAliasFileDialog.cpp' object='audacity-MissingAliasFileDialog.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o audacity-MissingAliasFileDialog.o `test -f 'MissingAliasFileDialog.cpp' || echo '$(srcdir)/'`MissingAliasFileDialog.cpp
audacity-MissingAliasFileDialog.obj: MissingAliasFileDialog.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT audacity-MissingAliasFileDialog.obj -MD -MP -MF $(DEPDIR)/audacity-MissingAliasFileDialog.Tpo -c -o audacity-MissingAliasFileDialog.obj `if test -f 'MissingAliasFileDialog.cpp'; then $(CYGPATH_W) 'MissingAliasFileDialog.cpp'; else $(CYGPATH_W) '$(srcdir)/MissingAliasFileDialog.cpp'; fi`
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/audacity-MissingAliasFileDialog.Tpo $(DEPDIR)/audacity-MissingAliasFileDialog.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='MissingAliasFileDialog.cpp' object='audacity-MissingAliasFileDialog.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o audacity-MissingAliasFileDialog.obj `if test -f 'MissingAliasFileDialog.cpp'; then $(CYGPATH_W) 'MissingAliasFileDialog.cpp'; else $(CYGPATH_W) '$(srcdir)/MissingAliasFileDialog.cpp'; fi`
audacity-Mix.o: Mix.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT audacity-Mix.o -MD -MP -MF $(DEPDIR)/audacity-Mix.Tpo -c -o audacity-Mix.o `test -f 'Mix.cpp' || echo '$(srcdir)/'`Mix.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/audacity-Mix.Tpo $(DEPDIR)/audacity-Mix.Po

View File

@ -31,8 +31,8 @@
#include "Experimental.h"
#include "AdornedRulerPanel.h"
#include "AudacityApp.h"
#include "AudioIO.h"
#include "Clipboard.h"
#include "LabelTrack.h"
#include "ModuleManager.h"
#ifdef USE_MIDI
@ -491,7 +491,7 @@ CommandFlag MenuManager::GetUpdateFlags
#endif
);
if((AudacityProject::msClipT1 - AudacityProject::msClipT0) > 0.0)
if( Clipboard::Get().Duration() > 0 )
flags |= ClipboardFlag;
auto &undoManager = *project.GetUndoManager();
@ -537,7 +537,7 @@ CommandFlag MenuManager::GetUpdateFlags
}
}
if (wxGetApp().GetRecentFiles()->GetCount() > 0)
if (FileHistory::Global().GetCount() > 0)
flags |= HaveRecentFiles;
if (project.IsSyncLocked())

View File

@ -180,7 +180,6 @@ bool DoAudacityCommand(
/// Namespace for functions for Help menu
namespace HelpActions {
void DoHelpWelcome( AudacityProject & );
void DoShowLog( AudacityProject& );
}
#endif

View File

@ -0,0 +1,133 @@
/*********************************************************************
\class MissingAliasFileDialog
\brief Special case of ErrorDialog for reporting missing alias files.
*//*******************************************************************/
#include "MissingAliasFileDialog.h"
#include <mutex>
#include "BlockFile.h"
#include "DirManager.h"
#include "Project.h"
#include "widgets/ErrorDialog.h"
// special case for alias missing dialog because we keep track of if it exists.
class MissingAliasFileDialog final : public ErrorDialog
{
public:
MissingAliasFileDialog(AudacityProject *parent,
const wxString & dlogTitle,
const wxString & message,
const wxString & helpURL,
const bool Close = true, const bool modal = true);
virtual ~MissingAliasFileDialog();
};
MissingAliasFileDialog::MissingAliasFileDialog(AudacityProject *parent,
const wxString & dlogTitle,
const wxString & message,
const wxString & helpURL,
const bool Close, const bool modal):
ErrorDialog(parent, dlogTitle, message, helpURL, Close, modal)
{
parent->SetMissingAliasFileDialog(this);
}
MissingAliasFileDialog::~MissingAliasFileDialog()
{
static_cast<AudacityProject *>(GetParent())
->SetMissingAliasFileDialog( nullptr );
}
namespace MissingAliasFilesDialog {
namespace{
bool m_missingAliasFilesWarningShouldShow{ true };
std::weak_ptr< AudacityProject > m_LastMissingBlockFileProject;
wxString m_LastMissingBlockFilePath;
std::mutex m_LastMissingBlockFileLock;
}
using Lock = std::unique_lock< std::mutex >;
void Show(AudacityProject *parent,
const wxString &dlogTitle,
const wxString &message,
const wxString &helpPage,
const bool Close)
{
wxASSERT(parent); // to justify safenew
ErrorDialog *dlog = safenew MissingAliasFileDialog(parent, dlogTitle, message, helpPage, Close, false);
// Don't center because in many cases (effect, export, etc) there will be a progress bar in the center that blocks this.
// instead put it just above or on the top of the project.
wxPoint point;
point.x = 0;
point.y = parent ? parent->GetPosition().y - 200 : 100;
if (point.y < 100)
point.y = 100;
dlog->SetPosition(point);
dlog->CentreOnParent(wxHORIZONTAL);
// This needs to be modeless because user may need to
// stop playback AND read dialog's instructions.
dlog->Show();
// ANSWER-ME: Vigilant Sentry flags this method as not deleting dlog, so a mem leak.
// PRL: answer is that the parent window guarantees destruction of the dialog
// but in practice Destroy() in OnOK does that
}
void Mark(const AliasBlockFile *b)
{
Lock lock{ m_LastMissingBlockFileLock };
if (b) {
size_t numProjects = gAudacityProjects.size();
for (size_t ii = 0; ii < numProjects; ++ii) {
// search each project for the blockfile
if (gAudacityProjects[ii]->GetDirManager()->ContainsBlockFile(b)) {
m_LastMissingBlockFileProject = gAudacityProjects[ii];
break;
}
}
}
else
m_LastMissingBlockFileProject = {};
if (b)
m_LastMissingBlockFilePath = b->GetAliasedFileName().GetFullPath();
else
m_LastMissingBlockFilePath = wxString{};
}
std::pair< wxString, std::shared_ptr<AudacityProject> > Marked()
{
Lock lock{ m_LastMissingBlockFileLock };
return { m_LastMissingBlockFilePath, m_LastMissingBlockFileProject.lock() };
}
bool ShouldShow()
{
Lock lock{ m_LastMissingBlockFileLock };
auto ptr = m_LastMissingBlockFileProject.lock();
return ptr && m_missingAliasFilesWarningShouldShow;
}
void SetShouldShow(bool b)
{
// Note that this is can be called by both the main thread and other threads.
// I don't believe we need a mutex because we are checking zero vs non-zero,
// and the setting from other threads will always be non-zero (true), and the
// setting from the main thread is always false.
m_missingAliasFilesWarningShouldShow = b;
// reset the warnings as they were probably marked by a previous run
if (m_missingAliasFilesWarningShouldShow) {
Mark( nullptr );
}
}
}

View File

@ -0,0 +1,42 @@
#ifndef __AUDACITY_MISSING_ALIAS_FILES_DIALOG__
#define __AUDACITY_MISSING_ALIAS_FILES_DIALOG__
class AliasBlockFile;
class AudacityProject;
class wxDialog;
#include <memory>
#include <utility>
#include <wx/string.h>
namespace MissingAliasFilesDialog {
/** \brief Mark playback as having missing aliased blockfiles
*
* Playback will continue, but the missing files will be silenced
* ShouldShow can be called to determine
* if the user should be notified
*/
void Mark(const AliasBlockFile *b);
// Retrieve information left by Mark
std::pair< wxString, std::shared_ptr<AudacityProject> > Marked();
/** \brief Changes the behavior of missing aliased blockfiles warnings
*/
void SetShouldShow(bool b);
/** \brief Returns true if the user should be notified of missing alias warnings
*/
bool ShouldShow();
/// Displays a custom modeless error dialog for aliased file errors
void Show(AudacityProject *parent,
const wxString &dlogTitle,
const wxString &message,
const wxString &helpPage,
const bool Close = true);
}
#endif

View File

@ -28,7 +28,6 @@ i.e. an alternative to the usual interface, for Audacity.
#include <wx/string.h>
#include <wx/filename.h>
#include "AudacityApp.h"
#include "FileNames.h"
#include "PluginManager.h"
@ -212,7 +211,7 @@ ModuleManager::~ModuleManager()
// static
void ModuleManager::Initialize(CommandHandler &cmdHandler)
{
const auto &audacityPathList = wxGetApp().audacityPathList;
const auto &audacityPathList = FileNames::AudacityPathList();
FilePaths pathList;
FilePaths files;
wxString pathVar;
@ -221,18 +220,18 @@ void ModuleManager::Initialize(CommandHandler &cmdHandler)
// Code from LoadLadspa that might be useful in load modules.
pathVar = wxGetenv(wxT("AUDACITY_MODULES_PATH"));
if (!pathVar.empty())
wxGetApp().AddMultiPathsToPathList(pathVar, pathList);
FileNames::AddMultiPathsToPathList(pathVar, pathList);
for (i = 0; i < audacityPathList.size(); i++) {
wxString prefix = audacityPathList[i] + wxFILE_SEP_PATH;
wxGetApp().AddUniquePathToPathList(prefix + wxT("modules"),
FileNames::AddUniquePathToPathList(prefix + wxT("modules"),
pathList);
}
#if defined(__WXMSW__)
wxGetApp().FindFilesInPathList(wxT("*.dll"), pathList, files);
FileNames::FindFilesInPathList(wxT("*.dll"), pathList, files);
#else
wxGetApp().FindFilesInPathList(wxT("*.so"), pathList, files);
FileNames::FindFilesInPathList(wxT("*.so"), pathList, files);
#endif
wxString saveOldCWD = ::wxGetCwd();
@ -357,19 +356,19 @@ bool ModuleManager::DiscoverProviders()
if (!pathVar.empty())
{
wxGetApp().AddMultiPathsToPathList(pathVar, pathList);
FileNames::AddMultiPathsToPathList(pathVar, pathList);
}
else
{
wxGetApp().AddUniquePathToPathList(FileNames::ModulesDir(), pathList);
FileNames::AddUniquePathToPathList(FileNames::ModulesDir(), pathList);
}
#if defined(__WXMSW__)
wxGetApp().FindFilesInPathList(wxT("*.dll"), pathList, provList);
FileNames::FindFilesInPathList(wxT("*.dll"), pathList, provList);
#elif defined(__WXMAC__)
wxGetApp().FindFilesInPathList(wxT("*.dylib"), pathList, provList);
FileNames::FindFilesInPathList(wxT("*.dylib"), pathList, provList);
#else
wxGetApp().FindFilesInPathList(wxT("*.so"), pathList, provList);
FileNames::FindFilesInPathList(wxT("*.so"), pathList, provList);
#endif
PluginManager & pm = PluginManager::Get();

View File

@ -60,10 +60,10 @@
#include <wx/filename.h>
#include <wx/stdpaths.h>
#include "AudacityApp.h"
#include "FileNames.h"
#include "Languages.h"
#include "prefs/GUIPrefs.h"
#include "widgets/ErrorDialog.h"
std::unique_ptr<AudacityPrefs> ugPrefs {};
@ -216,7 +216,7 @@ void InitPreferences()
}
}
langCode = wxGetApp().InitLang( langCode );
langCode = GUIPrefs::InitLang( langCode );
// User requested that the preferences be completely reset
if (resetPrefs)
@ -261,7 +261,7 @@ void InitPreferences()
int vMinor = gPrefs->Read(wxT("/Version/Minor"), (long) 0);
int vMicro = gPrefs->Read(wxT("/Version/Micro"), (long) 0);
wxGetApp().SetVersionKeysInit(vMajor, vMinor, vMicro); // make a note of these initial values
gPrefs->SetVersionKeysInit(vMajor, vMinor, vMicro); // make a note of these initial values
// for use by ToolManager::ReadConfig()
// These integer version keys were introduced april 4 2011 for 1.3.13

View File

@ -58,6 +58,26 @@ public:
long style = wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_GLOBAL_FILE,
const wxMBConv& conv = wxConvAuto());
bool GetEditClipsCanMove();
// Set and Get values of the version major/minor/micro keys in audacity.cfg when Audacity first opens
void SetVersionKeysInit( int major, int minor, int micro)
{
mVersionMajorKeyInit = major;
mVersionMinorKeyInit = minor;
mVersionMicroKeyInit = micro;
}
void GetVersionKeysInit( int& major, int& minor, int& micro) const
{
major = mVersionMajorKeyInit;
minor = mVersionMinorKeyInit;
micro = mVersionMicroKeyInit;
}
// values of the version major/minor/micro keys in audacity.cfg
// when Audacity first opens
int mVersionMajorKeyInit{};
int mVersionMinorKeyInit{};
int mVersionMicroKeyInit{};
};
/// Packages a table of user-visible choices each with an internal code string,

View File

@ -94,10 +94,11 @@ scroll information. It also has some status flags.
#endif
#include "AdornedRulerPanel.h"
#include "Clipboard.h"
#include "widgets/FileHistory.h"
#include "FreqWindow.h"
#include "effects/Contrast.h"
#include "AutoRecovery.h"
#include "AudacityApp.h"
#include "AColor.h"
#include "AudioIO.h"
#include "BatchProcessDialog.h"
@ -111,6 +112,7 @@ scroll information. It also has some status flags.
#include "Legacy.h"
#include "LyricsWindow.h"
#include "Menus.h"
#include "MissingAliasFileDialog.h"
#include "Mix.h"
#include "NoteTrack.h"
#include "Prefs.h"
@ -170,10 +172,109 @@ scroll information. It also has some status flags.
#include "widgets/WindowAccessible.h"
#endif
std::shared_ptr<TrackList> AudacityProject::msClipboard{ TrackList::Create() };
double AudacityProject::msClipT0 = 0.0;
double AudacityProject::msClipT1 = 0.0;
AudacityProject *AudacityProject::msClipProject = NULL;
bool AllProjects::sbClosing = false;
bool AllProjects::sbWindowRectAlreadySaved = false;
bool AllProjects::Close( bool force )
{
ValueRestorer<bool> cleanup{ sbClosing, true };
if (gAudacityProjects.size())
SaveWindowSize();
while (gAudacityProjects.size())
{
// Closing the project has global side-effect
// of deletion from gAudacityProjects
if ( force )
{
gAudacityProjects[0]->Close(true);
}
else
{
if (!gAudacityProjects[0]->Close())
return false;
}
}
return true;
}
void AllProjects::SaveWindowSize()
{
if (sbWindowRectAlreadySaved)
{
return;
}
bool validWindowForSaveWindowSize = FALSE;
AudacityProject * validProject = NULL;
bool foundIconizedProject = FALSE;
size_t numProjects = gAudacityProjects.size();
for (size_t i = 0; i < numProjects; i++)
{
if (!gAudacityProjects[i]->IsIconized()) {
validWindowForSaveWindowSize = TRUE;
validProject = gAudacityProjects[i].get();
i = numProjects;
}
else
foundIconizedProject = TRUE;
}
if (validWindowForSaveWindowSize)
{
wxRect windowRect = validProject->GetRect();
wxRect normalRect = validProject->GetNormalizedWindowState();
bool wndMaximized = validProject->IsMaximized();
gPrefs->Write(wxT("/Window/X"), windowRect.GetX());
gPrefs->Write(wxT("/Window/Y"), windowRect.GetY());
gPrefs->Write(wxT("/Window/Width"), windowRect.GetWidth());
gPrefs->Write(wxT("/Window/Height"), windowRect.GetHeight());
gPrefs->Write(wxT("/Window/Maximized"), wndMaximized);
gPrefs->Write(wxT("/Window/Normal_X"), normalRect.GetX());
gPrefs->Write(wxT("/Window/Normal_Y"), normalRect.GetY());
gPrefs->Write(wxT("/Window/Normal_Width"), normalRect.GetWidth());
gPrefs->Write(wxT("/Window/Normal_Height"), normalRect.GetHeight());
gPrefs->Write(wxT("/Window/Iconized"), FALSE);
}
else
{
if (foundIconizedProject) {
validProject = gAudacityProjects[0].get();
bool wndMaximized = validProject->IsMaximized();
wxRect normalRect = validProject->GetNormalizedWindowState();
// store only the normal rectangle because the itemized rectangle
// makes no sense for an opening project window
gPrefs->Write(wxT("/Window/X"), normalRect.GetX());
gPrefs->Write(wxT("/Window/Y"), normalRect.GetY());
gPrefs->Write(wxT("/Window/Width"), normalRect.GetWidth());
gPrefs->Write(wxT("/Window/Height"), normalRect.GetHeight());
gPrefs->Write(wxT("/Window/Maximized"), wndMaximized);
gPrefs->Write(wxT("/Window/Normal_X"), normalRect.GetX());
gPrefs->Write(wxT("/Window/Normal_Y"), normalRect.GetY());
gPrefs->Write(wxT("/Window/Normal_Width"), normalRect.GetWidth());
gPrefs->Write(wxT("/Window/Normal_Height"), normalRect.GetHeight());
gPrefs->Write(wxT("/Window/Iconized"), TRUE);
}
else {
// this would be a very strange case that might possibly occur on the Mac
// Audacity would have to be running with no projects open
// in this case we are going to write only the default values
wxRect defWndRect;
GetDefaultWindowRect(&defWndRect);
gPrefs->Write(wxT("/Window/X"), defWndRect.GetX());
gPrefs->Write(wxT("/Window/Y"), defWndRect.GetY());
gPrefs->Write(wxT("/Window/Width"), defWndRect.GetWidth());
gPrefs->Write(wxT("/Window/Height"), defWndRect.GetHeight());
gPrefs->Write(wxT("/Window/Maximized"), FALSE);
gPrefs->Write(wxT("/Window/Normal_X"), defWndRect.GetX());
gPrefs->Write(wxT("/Window/Normal_Y"), defWndRect.GetY());
gPrefs->Write(wxT("/Window/Normal_Width"), defWndRect.GetWidth());
gPrefs->Write(wxT("/Window/Normal_Height"), defWndRect.GetHeight());
gPrefs->Write(wxT("/Window/Iconized"), FALSE);
}
}
gPrefs->Flush();
sbWindowRectAlreadySaved = true;
}
ODLock &AudacityProject::AllProjectDeleteMutex()
{
static ODLock theMutex;
@ -946,6 +1047,13 @@ enum {
};
// PRL: This event type definition used to be in AudacityApp.h, which created
// a bad compilation dependency. The event was never emitted anywhere. I
// preserve it and its handler here but I move it to remove the dependency.
// Asynchronous open
DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_OPEN_AUDIO_FILE, -1);
DEFINE_EVENT_TYPE(EVT_OPEN_AUDIO_FILE);
BEGIN_EVENT_TABLE(AudacityProject, wxFrame)
EVT_MENU(wxID_ANY, AudacityProject::OnMenu)
EVT_MOUSE_EVENTS(AudacityProject::OnMouseEvent)
@ -1018,7 +1126,7 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id,
mStatusBar->SetName(wxT("status_line")); // not localized
mProjectNo = mProjectCounter++; // Bug 322
wxGetApp().SetMissingAliasedFileWarningShouldShow(true);
MissingAliasFilesDialog::SetShouldShow(true);
// MM: DirManager is created dynamically, freed on demand via ref-counting
// MM: We don't need to Ref() here because it start with refcount=1
@ -1429,12 +1537,12 @@ void AudacityProject::UpdatePrefs()
void AudacityProject::SetMissingAliasFileDialog(wxDialog *dialog)
{
mAliasMissingWarningDialog = dialog;
mMissingAliasFilesWarningDialog = dialog;
}
wxDialog *AudacityProject::GetMissingAliasFileDialog()
{
return mAliasMissingWarningDialog;
return mMissingAliasFilesWarningDialog;
}
void AudacityProject::RedrawProject(const bool bForceWaveTracks /*= false*/)
@ -2553,7 +2661,7 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event)
//
// LL: Save before doing anything else to the window that might make
// its size change.
SaveWindowSize();
AllProjects::SaveWindowSize();
mIsDeleting = true;
@ -2567,10 +2675,11 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event)
quitOnClose = !mMenuClose;
#endif
// DanH: If we're definitely about to quit, DELETE the clipboard.
// DanH: If we're definitely about to quit, clear the clipboard.
// Doing this after Deref'ing the DirManager causes problems.
if ((gAudacityProjects.size() == 1) && (quitOnClose || gIsQuitting))
DeleteClipboard();
if ((gAudacityProjects.size() == 1) &&
(quitOnClose || AllProjects::Closing()))
Clipboard::Get().Clear();
// JKC: For Win98 and Linux do not detach the menu bar.
// We want wxWidgets to clean it up for us.
@ -2671,14 +2780,17 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event)
gAudioIO->SetListener(gActiveProject);
}
if (gAudacityProjects.empty() && !gIsQuitting) {
if (gAudacityProjects.empty() && !AllProjects::Closing()) {
#if !defined(__WXMAC__)
if (quitOnClose) {
QuitAudacity();
// Simulate the application Exit menu item
wxCommandEvent evt{ wxEVT_MENU, wxID_EXIT };
wxTheApp->AddPendingEvent( evt );
}
else {
wxGetApp().SetWindowRectAlreadySaved(FALSE);
AllProjects::Reset();
// For non-Mac, always keep at least one project window open
CreateNewAudacityProject();
}
#endif
@ -3125,9 +3237,8 @@ void AudacityProject::OpenFile(const FilePath &fileNameArg, bool addtohistory)
// else any asynch calls into the blockfile code will not have
// finished logging errors (if any) before the call to ProjectFSCK()
if (addtohistory) {
wxGetApp().AddFileToHistory(fileName);
}
if (addtohistory)
FileHistory::Global().AddFileToHistory(fileName);
}
// Use a finally block here, because there are calls to Save() below which
@ -4289,7 +4400,7 @@ bool AudacityProject::Import(const FilePath &fileName, WaveTrackArray* pTrackArr
if (!success)
return false;
wxGetApp().AddFileToHistory(fileName);
FileHistory::Global().AddFileToHistory(fileName);
// no more errors, commit
cleanup.release();
@ -4368,7 +4479,7 @@ bool AudacityProject::SaveAs(const wxString & newFileName, bool bWantSaveCopy /*
success = DoSave(!bOwnsNewAupName || bWantSaveCopy, bWantSaveCopy);
if (success && addToHistory) {
wxGetApp().AddFileToHistory(mFileName);
FileHistory::Global().AddFileToHistory(mFileName);
}
if (!success || bWantSaveCopy) // bWantSaveCopy doesn't actually change current project.
{
@ -4538,7 +4649,7 @@ will be irreversibly overwritten."), fName, fName);
success = DoSave(!bOwnsNewAupName || bWantSaveCopy, bWantSaveCopy, bLossless);
if (success) {
wxGetApp().AddFileToHistory(mFileName);
FileHistory::Global().AddFileToHistory(mFileName);
if( !bHasPath )
{
gPrefs->Write( wxT("/SaveAs/Path"), filename.GetPath());
@ -4694,32 +4805,6 @@ void AudacityProject::SetStateTo(unsigned int n)
GetMenuManager(*this).ModifyUndoMenuItems(*this);
}
//
// Clipboard methods
//
//static
TrackList *AudacityProject::GetClipboardTracks()
{
return msClipboard.get();
}
//static
void AudacityProject::DeleteClipboard()
{
msClipboard.reset();
}
void AudacityProject::ClearClipboard()
{
msClipT0 = 0.0;
msClipT1 = 0.0;
msClipProject = NULL;
if (msClipboard) {
msClipboard->Clear();
}
}
// Utility function called by other zoom methods
void AudacityProject::Zoom(double level)
{
@ -5300,7 +5385,7 @@ bool AudacityProject::ExportFromTimerRecording(wxFileName fnFile, int iFormat, i
{
Exporter e;
wxGetApp().SetMissingAliasedFileWarningShouldShow(true);
MissingAliasFilesDialog::SetShouldShow(true);
return e.ProcessFromTimerRecording(this, false, 0.0, mTracks->GetEndTime(), fnFile, iFormat, iSubFormat, iFilterIndex);
}
@ -5376,7 +5461,7 @@ bool AudacityProject::SaveFromTimerRecording(wxFileName fnFile) {
bSuccess = DoSave(true, false);
if (bSuccess) {
wxGetApp().AddFileToHistory(mFileName);
FileHistory::Global().AddFileToHistory(mFileName);
mbLoadedFromAup = true;
SetProjectTitle();
}

View File

@ -150,6 +150,23 @@ class ImportXMLTagHandler final : public XMLTagHandler
AudacityProject* mProject;
};
class AllProjects
{
public:
// Return true if all projects do close (always so if force == true)
// But if return is false, that means the user cancelled close of at least
// one un-saved project.
static bool Close( bool force = false );
static void SaveWindowSize();
static bool Closing() { return sbClosing; }
static void Reset() { sbWindowRectAlreadySaved = false; }
private:
static bool sbClosing;
static bool sbWindowRectAlreadySaved;
};
class EffectPlugs;
class CommandContext;
class CommandManager;
@ -381,10 +398,7 @@ public:
void ZoomOutByFactor( double ZoomFactor );
// Other commands
static TrackList *GetClipboardTracks();
static void ClearClipboard();
static void DeleteClipboard();
int GetProjectNumber(){ return mProjectNo;};
static int CountUnnamed();
static void RefreshAllTitles(bool bShowProjectNumbers );
@ -583,13 +597,6 @@ public:
std::shared_ptr<TrackList> mLastSavedTracks;
public:
// Clipboard (static because it is shared by all projects)
static std::shared_ptr<TrackList> msClipboard;
static AudacityProject *msClipProject;
static double msClipT0;
static double msClipT1;
///Prevents DELETE from external thread - for e.g. use of GetActiveProject
//shared by all projects
static ODLock &AllProjectDeleteMutex();
@ -638,7 +645,7 @@ private:
Destroy_ptr<ContrastDialog> mContrastDialog;
// dialog for missing alias warnings
wxDialog *mAliasMissingWarningDialog{};
wxDialog *mMissingAliasFilesWarningDialog{};
bool mShownOnce{ false };

View File

@ -26,6 +26,7 @@ UndoManager
#include <wx/hashset.h>
#include "BlockFile.h"
#include "Clipboard.h"
#include "Diags.h"
#include "Project.h"
#include "Sequence.h"
@ -141,7 +142,7 @@ void UndoManager::CalculateSpaceUsage()
}
mClipboardSpaceUsage = CalculateUsage(
*AudacityProject::GetClipboardTracks(), nullptr);
Clipboard::Get().GetTracks(), nullptr);
//TIMER_STOP( space_calc );
}

View File

@ -25,7 +25,7 @@ code out of ModuleManager.
#include "CommandBuilder.h"
#include "AppCommandEvent.h"
#include "../Project.h"
#include "../AudacityApp.h"
#include <wx/app.h>
#include <wx/string.h>
// Declare static class members
@ -110,8 +110,10 @@ int ExecCommand2(wxString *pIn, wxString *pOut)
OldStyleCommandPointer cmd = builder.GetCommand();
AppCommandEvent ev;
ev.SetCommand(cmd);
AudacityApp & App = wxGetApp();
App.OnReceiveCommand(ev);
// Use SafelyProcessEvent, which stops exceptions, because this is
// expected to be reached from within the XLisp runtime
wxTheApp->SafelyProcessEvent( ev );
*pOut = wxEmptyString;
}

View File

@ -8,7 +8,6 @@
**********************************************************************/
#include "../../AudacityApp.h"
#include "LoadNyquist.h"
#include <wx/log.h>
@ -129,7 +128,7 @@ wxString NyquistEffectsModule::GetDescription()
bool NyquistEffectsModule::Initialize()
{
const auto &audacityPathList = wxGetApp().audacityPathList;
const auto &audacityPathList = FileNames::AudacityPathList();
for (size_t i = 0, cnt = audacityPathList.size(); i < cnt; i++)
{

View File

@ -54,7 +54,6 @@ effects from this one class.
#include <wx/stdpaths.h>
#include "../EffectManager.h"
#include "../../AudacityApp.h"
#include "../../DirManager.h"
#include "../../FileNames.h"
#include "../../LabelTrack.h"
@ -70,6 +69,7 @@ effects from this one class.
#include "../../widgets/ErrorDialog.h"
#include "../../Prefs.h"
#include "../../wxFileNameWrapper.h"
#include "../../prefs/GUIPrefs.h"
#include "../../prefs/WaveformSettings.h"
#include "../../widgets/NumericTextCtrl.h"
#include "../../widgets/ProgressDialog.h"
@ -655,7 +655,7 @@ bool NyquistEffect::Process()
mProps += wxString::Format(wxT("(putprop '*AUDACITY* (list %d %d %d) 'VERSION)\n"), AUDACITY_VERSION, AUDACITY_RELEASE, AUDACITY_REVISION);
wxString lang = gPrefs->Read(wxT("/Locale/Language"), wxT(""));
lang = (lang.empty())? wxGetApp().SetLang(lang) : lang;
lang = (lang.empty())? GUIPrefs::SetLang(lang) : lang;
mProps += wxString::Format(wxT("(putprop '*AUDACITY* \"%s\" 'LANGUAGE)\n"), lang);
mProps += wxString::Format(wxT("(setf *DECIMAL-SEPARATOR* #\\%c)\n"), wxNumberFormatter::GetDecimalSeparator());
@ -2350,15 +2350,15 @@ void NyquistEffect::OSCallback()
FilePaths NyquistEffect::GetNyquistSearchPath()
{
const auto &audacityPathList = wxGetApp().audacityPathList;
const auto &audacityPathList = FileNames::AudacityPathList();
FilePaths pathList;
for (size_t i = 0; i < audacityPathList.size(); i++)
{
wxString prefix = audacityPathList[i] + wxFILE_SEP_PATH;
wxGetApp().AddUniquePathToPathList(prefix + wxT("nyquist"), pathList);
wxGetApp().AddUniquePathToPathList(prefix + wxT("plugins"), pathList);
wxGetApp().AddUniquePathToPathList(prefix + wxT("plug-ins"), pathList);
FileNames::AddUniquePathToPathList(prefix + wxT("nyquist"), pathList);
FileNames::AddUniquePathToPathList(prefix + wxT("plugins"), pathList);
FileNames::AddUniquePathToPathList(prefix + wxT("plug-ins"), pathList);
}
pathList.push_back(FileNames::PlugInDir());

View File

@ -674,8 +674,8 @@ bool Exporter::GetFilename()
// This causes problems for the exporter, so we don't allow it.
// Overwritting non-missing aliased files is okay.
// Also, this can only happen for uncompressed audio.
bool overwritingMissingAlias;
overwritingMissingAlias = false;
bool overwritingMissingAliasFiles;
overwritingMissingAliasFiles = false;
for (size_t i = 0; i < gAudacityProjects.size(); i++) {
AliasedFileArray aliasedFiles;
FindDependencies(gAudacityProjects[i].get(), aliasedFiles);
@ -687,11 +687,11 @@ bool Exporter::GetFilename()
The file cannot be written because the path is needed to restore the original audio to the project.\n\
Choose Help > Diagnostics > Check Dependencies to view the locations of all missing files.\n\
If you still wish to export, please choose a different filename or folder."));
overwritingMissingAlias = true;
overwritingMissingAliasFiles = true;
}
}
}
if (overwritingMissingAlias)
if (overwritingMissingAliasFiles)
continue;
if (mFilename.FileExists()) {

View File

@ -1,6 +1,6 @@
#include "../Audacity.h" // for USE_* macros
#include "../AdornedRulerPanel.h"
#include "../AudacityApp.h" // for EVT_CLIPBOARD_CHANGE
#include "../Clipboard.h"
#include "../LabelTrack.h"
#include "../Menus.h"
#include "../NoteTrack.h"
@ -78,7 +78,8 @@ bool DoPasteNothingSelected(AudacityProject &project)
return false;
else
{
auto clipTrackRange = AudacityProject::msClipboard->Any< const Track >();
const auto &clipboard = Clipboard::Get();
auto clipTrackRange = clipboard.GetTracks().Any< const Track >();
if (clipTrackRange.empty())
return true; // nothing to paste
@ -90,7 +91,7 @@ bool DoPasteNothingSelected(AudacityProject &project)
Track *pNewTrack;
pClip->TypeSwitch(
[&](const WaveTrack *wc) {
if ((AudacityProject::msClipProject != &project))
if ((clipboard.Project() != &project))
// Cause duplication of block files on disk, when copy is
// between projects
locker.create(wc);
@ -136,8 +137,8 @@ bool DoPasteNothingSelected(AudacityProject &project)
// So do it at the sample rate of the project
AudacityProject *p = GetActiveProject();
double projRate = p->GetRate();
double quantT0 = QUANTIZED_TIME(AudacityProject::msClipT0, projRate);
double quantT1 = QUANTIZED_TIME(AudacityProject::msClipT1, projRate);
double quantT0 = QUANTIZED_TIME(clipboard.T0(), projRate);
double quantT1 = QUANTIZED_TIME(clipboard.T1(), projRate);
selectedRegion.setTimes(
0.0, // anywhere else and this should be
// half a sample earlier
@ -296,7 +297,8 @@ void OnCut(const CommandContext &context)
}
}
AudacityProject::ClearClipboard();
auto &clipboard = Clipboard::Get();
clipboard.Clear();
auto pNewClipboard = TrackList::Create();
auto &newClipboard = *pNewClipboard;
@ -318,8 +320,12 @@ void OnCut(const CommandContext &context)
);
// Survived possibility of exceptions. Commit changes to the clipboard now.
newClipboard.Swap(*AudacityProject::msClipboard);
wxTheApp->AddPendingEvent( wxCommandEvent{ EVT_CLIPBOARD_CHANGE } );
clipboard.Assign(
std::move( newClipboard ),
selectedRegion.t0(),
selectedRegion.t1(),
&project
);
// Proceed to change the project. If this throws, the project will be
// rolled back by the top level handler.
@ -347,10 +353,6 @@ void OnCut(const CommandContext &context)
}
);
AudacityProject::msClipT0 = selectedRegion.t0();
AudacityProject::msClipT1 = selectedRegion.t1();
AudacityProject::msClipProject = &project;
selectedRegion.collapseToT0();
project.PushState(_("Cut to the clipboard"), _("Cut"));
@ -401,7 +403,8 @@ void OnCopy(const CommandContext &context)
}
}
AudacityProject::ClearClipboard();
auto &clipboard = Clipboard::Get();
clipboard.Clear();
auto pNewClipboard = TrackList::Create();
auto &newClipboard = *pNewClipboard;
@ -413,12 +416,8 @@ void OnCopy(const CommandContext &context)
}
// Survived possibility of exceptions. Commit changes to the clipboard now.
newClipboard.Swap(*AudacityProject::msClipboard);
wxTheApp->AddPendingEvent( wxCommandEvent{ EVT_CLIPBOARD_CHANGE } );
AudacityProject::msClipT0 = selectedRegion.t0();
AudacityProject::msClipT1 = selectedRegion.t1();
AudacityProject::msClipProject = &project;
clipboard.Assign( std::move( newClipboard ),
selectedRegion.t0(), selectedRegion.t1(), &project );
//Make sure the menus/toolbar states get updated
trackPanel->Refresh(false);
@ -441,7 +440,8 @@ void OnPaste(const CommandContext &context)
if (DoPasteNothingSelected(project))
return;
auto clipTrackRange = AudacityProject::msClipboard->Any< const Track >();
const auto &clipboard = Clipboard::Get();
auto clipTrackRange = clipboard.GetTracks().Any< const Track >();
if (clipTrackRange.empty())
return;
@ -492,8 +492,7 @@ void OnPaste(const CommandContext &context)
{
// Must perform sync-lock adjustment before incrementing n
if (n->IsSyncLockSelected()) {
auto newT1 = t0 +
(AudacityProject::msClipT1 - AudacityProject::msClipT0);
auto newT1 = t0 + clipboard.Duration();
if (t1 != newT1 && t1 <= n->GetEndTime()) {
n->SyncLockAdjust(t1, newT1);
bPastedSomething = true;
@ -554,7 +553,7 @@ void OnPaste(const CommandContext &context)
n->TypeSwitch(
[&](WaveTrack *wn){
const auto wc = static_cast<const WaveTrack *>(c);
if (AudacityProject::msClipProject != &project)
if (clipboard.Project() != &project)
// Cause duplication of block files on disk, when copy is
// between projects
locker.create(wc);
@ -566,8 +565,7 @@ void OnPaste(const CommandContext &context)
// a label track.
ln->Clear(t0, t1);
ln->ShiftLabelsOnInsert(
AudacityProject::msClipT1 - AudacityProject::msClipT0, t0);
ln->ShiftLabelsOnInsert( clipboard.Duration(), t0 );
bPastedSomething |= ln->PasteOver(t0, c);
},
@ -611,8 +609,7 @@ void OnPaste(const CommandContext &context)
} // if (n->GetSelected())
else if (n->IsSyncLockSelected())
{
auto newT1 = t0 +
(AudacityProject::msClipT1 - AudacityProject::msClipT0);
auto newT1 = t0 + clipboard.Duration();
if (t1 != newT1 && t1 <= n->GetEndTime()) {
n->SyncLockAdjust(t1, newT1);
bPastedSomething = true;
@ -628,9 +625,9 @@ void OnPaste(const CommandContext &context)
if ( *pN && ! *pC )
{
const auto wc =
*AudacityProject::msClipboard->Any< const WaveTrack >().rbegin();
*clipboard.GetTracks().Any< const WaveTrack >().rbegin();
Maybe<WaveTrack::Locker> locker;
if (AudacityProject::msClipProject != &project && wc)
if (clipboard.Project() != &project && wc)
// Cause duplication of block files on disk, when copy is
// between projects
locker.create(static_cast<const WaveTrack*>(wc));
@ -647,9 +644,9 @@ void OnPaste(const CommandContext &context)
else {
auto tmp = trackFactory->NewWaveTrack(
wt->GetSampleFormat(), wt->GetRate());
tmp->InsertSilence(0.0,
tmp->InsertSilence( 0.0,
// MJS: Is this correct?
AudacityProject::msClipT1 - AudacityProject::msClipT0);
clipboard.Duration() );
tmp->Flush();
bPastedSomething = true;
@ -665,12 +662,11 @@ void OnPaste(const CommandContext &context)
// As above, only shift labels if sync-lock is on.
if (isSyncLocked)
lt->ShiftLabelsOnInsert(
AudacityProject::msClipT1 - AudacityProject::msClipT0, t0);
clipboard.Duration(), t0);
},
[&](Track *n) {
if (n->IsSyncLockSelected())
n->SyncLockAdjust(t1, t0 +
AudacityProject::msClipT1 - AudacityProject::msClipT0);
n->SyncLockAdjust(t1, t0 + clipboard.Duration() );
}
);
}
@ -679,8 +675,7 @@ void OnPaste(const CommandContext &context)
if (bPastedSomething)
{
selectedRegion.setT1(
t0 + AudacityProject::msClipT1 - AudacityProject::msClipT0);
selectedRegion.setT1( t0 + clipboard.Duration() );
project.PushState(_("Pasted from the clipboard"), _("Paste"));
@ -724,7 +719,8 @@ void OnSplitCut(const CommandContext &context)
auto tracks = project.GetTracks();
auto &selectedRegion = project.GetViewInfo().selectedRegion;
AudacityProject::ClearClipboard();
auto &clipboard = Clipboard::Get();
clipboard.Clear();
auto pNewClipboard = TrackList::Create();
auto &newClipboard = *pNewClipboard;
@ -750,12 +746,8 @@ void OnSplitCut(const CommandContext &context)
);
// Survived possibility of exceptions. Commit changes to the clipboard now.
newClipboard.Swap(*AudacityProject::msClipboard);
wxTheApp->AddPendingEvent( wxCommandEvent{ EVT_CLIPBOARD_CHANGE } );
AudacityProject::msClipT0 = selectedRegion.t0();
AudacityProject::msClipT1 = selectedRegion.t1();
AudacityProject::msClipProject = &project;
clipboard.Assign( std::move( newClipboard ),
selectedRegion.t0(), selectedRegion.t1(), &project );
project.PushState(_("Split-cut to the clipboard"), _("Split Cut"));

View File

@ -1,10 +1,10 @@
#include "../Audacity.h" // for USE_* macros
#include "../Experimental.h"
#include "../AudacityApp.h"
#include "../BatchCommands.h"
#include "../FileNames.h"
#include "../LabelTrack.h"
#include "../MissingAliasFileDialog.h"
#include "../NoteTrack.h"
#include "../Prefs.h"
#include "../Printing.h"
@ -33,7 +33,7 @@ void DoExport
Exporter e;
wxGetApp().SetMissingAliasedFileWarningShouldShow(true);
MissingAliasFilesDialog::SetShouldShow(true);
double t0 = 0.0;
double t1 = tracks->GetEndTime();
@ -81,7 +81,7 @@ void DoExport
}
else
{
wxGetApp().AddFileToHistory(filename);
FileHistory::Global().AddFileToHistory(filename);
// We're in batch mode, the file does not exist already.
// We really can proceed without prompting.
int nChannels = MacroCommands::IsMono() ? 1 : 2;
@ -131,7 +131,7 @@ AudacityProject *DoImportMIDI(
pProject->ZoomAfterImport(pTrack);
pNewProject = nullptr;
wxGetApp().AddFileToHistory(fileName);
FileHistory::Global().AddFileToHistory(fileName);
return pProject;
}
@ -231,7 +231,7 @@ void OnExportSelection(const CommandContext &context)
auto &selectedRegion = project.GetViewInfo().selectedRegion;
Exporter e;
wxGetApp().SetMissingAliasedFileWarningShouldShow(true);
MissingAliasFilesDialog::SetShouldShow(true);
e.SetFileDialogTitle( _("Export Selected Audio") );
e.Process(&project, true, selectedRegion.t0(),
selectedRegion.t1());
@ -303,7 +303,7 @@ void OnExportMultiple(const CommandContext &context)
auto &project = context.project;
ExportMultiple em(&project);
wxGetApp().SetMissingAliasedFileWarningShouldShow(true);
MissingAliasFilesDialog::SetShouldShow(true);
em.ShowModal();
}
@ -396,7 +396,7 @@ void OnImport(const CommandContext &context)
// An import trigger for the alias missing dialog might not be intuitive, but
// this serves to track the file if the users zooms in and such.
wxGetApp().SetMissingAliasedFileWarningShouldShow(true);
MissingAliasFilesDialog::SetShouldShow(true);
wxArrayString selectedFiles = project.ShowOpenDialog(wxT(""));
if (selectedFiles.size() == 0) {
@ -542,7 +542,9 @@ void OnPrint(const CommandContext &context)
void OnExit(const CommandContext &WXUNUSED(context) )
{
QuitAudacity();
// Simulate the application Exit menu item
wxCommandEvent evt{ wxEVT_MENU, wxID_EXIT };
wxTheApp->AddPendingEvent( evt );
}
}; // struct Handler
@ -597,8 +599,9 @@ MenuTable::BaseItemPtr FileMenu( AudacityProject& )
,
Special( [](AudacityProject &, wxMenu &theMenu){
// Recent Files and Recent Projects menus
wxGetApp().GetRecentFiles()->UseMenu( &theMenu );
wxGetApp().GetRecentFiles()->AddFilesToMenu( &theMenu );
auto &history = FileHistory::Global();
history.UseMenu( &theMenu );
history.AddFilesToMenu( &theMenu );
wxWeakRef<wxMenu> recentFilesMenu{ &theMenu };
wxTheApp->CallAfter( [=] {

View File

@ -4,9 +4,9 @@
#include <wx/textctrl.h>
#include "../AboutDialog.h"
#include "../AudacityApp.h"
#include "../AudacityLogger.h"
#include "../AudioIO.h"
#include "../CrashReport.h"
#include "../Dependencies.h"
#include "../FileNames.h"
#include "../Project.h"
@ -75,14 +75,6 @@ namespace HelpActions {
// exported helper functions
void DoShowLog( AudacityProject & )
{
AudacityLogger *logger = wxGetApp().GetLogger();
if (logger) {
logger->Show();
}
}
void DoHelpWelcome( AudacityProject &project )
{
SplashDialog::Show2( &project );
@ -135,7 +127,10 @@ void OnMidiDeviceInfo(const CommandContext &context)
void OnShowLog( const CommandContext &context )
{
DoShowLog( context.project );
auto logger = AudacityLogger::Get();
if (logger) {
logger->Show();
}
}
#if defined(EXPERIMENTAL_CRASH_REPORT)
@ -146,7 +141,7 @@ void OnCrashReport(const CommandContext &WXUNUSED(context) )
char *p = 0;
*p = 1234;
#endif
wxGetApp().GenerateCrashReport(wxDebugReport::Context_Current);
CrashReport::Generate(wxDebugReport::Context_Current);
}
#endif
@ -165,8 +160,9 @@ void OnAbout(const CommandContext &context)
{
#ifdef __WXMAC__
// Modeless dialog, consistent with other Mac applications
wxCommandEvent dummy;
wxGetApp().OnMenuAbout(dummy);
// Simulate the application Exit menu item
wxCommandEvent evt{ wxEVT_MENU, wxID_ABOUT };
wxTheApp->AddPendingEvent( evt );
#else
auto &project = context.project;

View File

@ -1,5 +1,5 @@
#include "../AudacityApp.h" // for EVT_CLIPBOARD_CHANGE
#include "../AudioIO.h"
#include "../Clipboard.h"
#include "../LabelTrack.h"
#include "../Menus.h"
#include "../Prefs.h"
@ -164,7 +164,7 @@ using EditDestFunction = std::shared_ptr<Track> (WaveTrack::*)(double, double);
//Functions copy the edited regions to clipboard, possibly in multiple tracks
//This probably should not be called if *action() changes the timeline, because
// the copy needs to happen by track, and the timeline change by group.
void EditClipboardByLabel(
void EditClipboardByLabel( AudacityProject &project,
TrackList &tracks, const SelectedRegion &selectedRegion,
EditDestFunction action )
{
@ -178,7 +178,8 @@ void EditClipboardByLabel(
// apply only on the selected track
const bool allTracks = (tracks.Selected< WaveTrack >()).empty();
AudacityProject::ClearClipboard();
auto &clipboard = Clipboard::Get();
clipboard.Clear();
auto pNewClipboard = TrackList::Create();
auto &newClipboard = *pNewClipboard;
@ -231,11 +232,8 @@ void EditClipboardByLabel(
}
// Survived possibility of exceptions. Commit changes to the clipboard now.
newClipboard.Swap(*AudacityProject::msClipboard);
wxTheApp->AddPendingEvent( wxCommandEvent{ EVT_CLIPBOARD_CHANGE } );
AudacityProject::msClipT0 = regions.front().start;
AudacityProject::msClipT1 = regions.back().end;
clipboard.Assign( std::move( newClipboard ),
regions.front().start, regions.back().end, &project );
}
}
@ -363,7 +361,8 @@ void OnCutLabels(const CommandContext &context)
// Because of grouping the copy may need to operate on different tracks than
// the clear, so we do these actions separately.
EditClipboardByLabel( tracks, selectedRegion, &WaveTrack::CopyNonconst );
EditClipboardByLabel( project,
tracks, selectedRegion, &WaveTrack::CopyNonconst );
if( gPrefs->Read( wxT( "/GUI/EnableCutLines" ), ( long )0 ) )
EditByLabel(
@ -371,8 +370,6 @@ void OnCutLabels(const CommandContext &context)
else
EditByLabel( tracks, selectedRegion, &WaveTrack::Clear, true );
AudacityProject::msClipProject = &project;
selectedRegion.collapseToT0();
project.PushState(
@ -416,9 +413,8 @@ void OnSplitCutLabels(const CommandContext &context)
if( selectedRegion.isPoint() )
return;
EditClipboardByLabel( tracks, selectedRegion, &WaveTrack::SplitCut );
AudacityProject::msClipProject = &project;
EditClipboardByLabel( project,
tracks, selectedRegion, &WaveTrack::SplitCut );
project.PushState(
/* i18n-hint: (verb) Audacity has just split cut the labeled audio
@ -483,9 +479,8 @@ void OnCopyLabels(const CommandContext &context)
if( selectedRegion.isPoint() )
return;
EditClipboardByLabel( tracks, selectedRegion, &WaveTrack::CopyNonconst );
AudacityProject::msClipProject = &project;
EditClipboardByLabel( project,
tracks, selectedRegion, &WaveTrack::CopyNonconst );
project.PushState( _( "Copied labeled audio regions to clipboard" ),
/* i18n-hint: (verb)*/

View File

@ -1,12 +1,12 @@
#include "../Audacity.h"
#include "../Experimental.h"
#include "../AudacityApp.h"
#include "../AudioIO.h"
#include "../BatchProcessDialog.h"
#include "../Benchmark.h"
#include "../FreqWindow.h"
#include "../Menus.h"
#include "../MissingAliasFileDialog.h"
#include "../PluginManager.h"
#include "../Prefs.h"
#include "../Project.h"
@ -412,7 +412,7 @@ bool DoEffect(
project.SelectAllIfNone();
}
wxGetApp().SetMissingAliasedFileWarningShouldShow(true);
MissingAliasFilesDialog::SetShouldShow(true);
auto nTracksOriginally = project.GetTrackCount();
wxWindow *focus = wxWindow::FindFocus();

View File

@ -1,9 +1,9 @@
#include "../Audacity.h"
#include "../Experimental.h"
#include "../AudacityApp.h"
#include "../LabelTrack.h"
#include "../Menus.h"
#include "../MissingAliasFileDialog.h"
#include "../Mix.h"
#include "../Prefs.h"
@ -43,7 +43,7 @@ void DoMixAndRender
auto defaultFormat = project.GetDefaultFormat();
auto trackPanel = project.GetTrackPanel();
wxGetApp().SetMissingAliasedFileWarningShouldShow(true);
MissingAliasFilesDialog::SetShouldShow(true);
WaveTrack::Holder uNewLeft, uNewRight;
::MixAndRender(

View File

@ -457,7 +457,11 @@ void OnTimerRecord(const CommandContext &context)
// No action required
break;
case POST_TIMER_RECORD_CLOSE:
wxTheApp->CallAfter( []{ QuitAudacity(); } );
wxTheApp->CallAfter( []{
// Simulate the application Exit menu item
wxCommandEvent evt{ wxEVT_MENU, wxID_EXIT };
wxTheApp->AddPendingEvent( evt );
} );
break;
case POST_TIMER_RECORD_RESTART:
// Restart System

View File

@ -7,7 +7,6 @@
#ifdef __WXMAC__
#include "../AudacityApp.h"
#include "../Menus.h"
#include "../Project.h"
#include "../commands/CommandContext.h"
@ -160,15 +159,6 @@ MenuTable::BaseItemPtr ExtraWindowItems( AudacityProject & )
#undef XXO
#undef FN
// One more Objective C++ function for another class scope, kept in this file
void AudacityApp::MacActivateApp()
{
id app = [NSApplication sharedApplication];
if ( [app respondsToSelector:@selector(activateIgnoringOtherApps:)] )
[app activateIgnoringOtherApps:YES];
}
#else
// Not WXMAC. Stub functions.

View File

@ -32,8 +32,8 @@
#include <wx/filename.h>
#include <wx/utils.h>
#include "../FileNames.h"
#include "../Prefs.h"
#include "../AudacityApp.h"
#include "../ShuttleGui.h"
#include "../widgets/ErrorDialog.h"
@ -147,14 +147,15 @@ void DirectoriesPrefs::PopulateOrExchange(ShuttleGui & S)
void DirectoriesPrefs::OnChooseTempDir(wxCommandEvent & e)
{
wxString oldTempDir = gPrefs->Read(wxT("/Directories/TempDir"), wxGetApp().defaultTempDir);
wxString oldTempDir =
gPrefs->Read(wxT("/Directories/TempDir"), FileNames::DefaultTempDir());
// Because we went through InitTempDir() during initialisation,
// the old temp directory name in prefs should already be OK. Just in case there is
// some way we hadn't thought of for it to be not OK,
// we avoid prompting with it in that case and use the suggested default instead.
if( !AudacityApp::IsTempDirectoryNameOK( oldTempDir ) )
oldTempDir = wxGetApp().defaultTempDir;
if( !FileNames::IsTempDirectoryNameOK( oldTempDir ) )
oldTempDir = FileNames::DefaultTempDir();
wxDirDialogWrapper dlog(this,
_("Choose a location to place the temporary directory"),
@ -182,7 +183,7 @@ void DirectoriesPrefs::OnChooseTempDir(wxCommandEvent & e)
// If the default temp dir or user's pref dir don't end in '/' they cause
// wxFileName's == operator to construct a wxFileName representing a file
// (that doesn't exist) -- hence the constructor calls
if (tmpDirPath != wxFileName(wxGetApp().defaultTempDir, wxT("")) &&
if (tmpDirPath != wxFileName(FileNames::DefaultTempDir(), wxT("")) &&
tmpDirPath != wxFileName(mTempDir->GetValue(), wxT("")) &&
(dirsInPath.size() == 0 ||
dirsInPath[dirsInPath.size()-1] != newDirName))
@ -225,7 +226,7 @@ bool DirectoriesPrefs::Validate()
tempDir.SetPath(mTempDir->GetValue());
wxString path{tempDir.GetPath()};
if( !AudacityApp::IsTempDirectoryNameOK( path ) ) {
if( !FileNames::IsTempDirectoryNameOK( path ) ) {
AudacityMessageBox(
wxString::Format(_("Directory %s is not suitable (at risk of being cleaned out)"),
path),

View File

@ -22,9 +22,10 @@
#include "../Experimental.h"
#include <wx/app.h>
#include <wx/defs.h>
#include "../AudacityApp.h"
#include "../FileNames.h"
#include "../Languages.h"
#include "../Theme.h"
#include "../Prefs.h"
@ -34,6 +35,10 @@
#include "ThemePrefs.h"
#include "../AColor.h"
#include "../TranslatableStringArray.h"
#include "../widgets/ErrorDialog.h"
wxDEFINE_EVENT(EVT_LANGUAGE_CHANGE, wxCommandEvent);
GUIPrefs::GUIPrefs(wxWindow * parent, wxWindowID winid)
/* i18n-hint: refers to Audacity's user interface settings */
@ -256,7 +261,7 @@ bool GUIPrefs::Commit()
// If language has changed, we want to change it now, not on the next reboot.
wxString lang = gPrefs->Read(wxT("/Locale/Language"), wxT(""));
wxString usedLang = wxGetApp().SetLang(lang);
wxString usedLang = SetLang(lang);
// Bug 1523: Previously didn't check no-language (=System Language)
if (!(lang.empty()) && (lang != usedLang)) {
// lang was not usable and is not system language. We got overridden.
@ -267,6 +272,99 @@ bool GUIPrefs::Commit()
return true;
}
wxString GUIPrefs::InitLang( wxString langCode )
{
if ( langCode.empty() )
langCode = gPrefs->Read(wxT("/Locale/Language"), wxEmptyString);
// Use the system default language if one wasn't specified or if the user selected System.
if (langCode.empty())
{
langCode = GetSystemLanguageCode();
}
// Initialize the language
return SetLang(langCode);
}
static std::unique_ptr<wxLocale> sLocale;
wxString GUIPrefs::SetLang( const wxString & lang )
{
wxString result = lang;
sLocale.reset();
#if defined(__WXMAC__)
// This should be reviewed again during the wx3 conversion.
// On OSX, if the LANG environment variable isn't set when
// using a language like Japanese, an assertion will trigger
// because conversion to Japanese from "?" doesn't return a
// valid length, so make OSX happy by defining/overriding
// the LANG environment variable with U.S. English for now.
wxSetEnv(wxT("LANG"), wxT("en_US.UTF-8"));
#endif
const wxLanguageInfo *info = NULL;
if (!lang.empty()) {
info = wxLocale::FindLanguageInfo(lang);
if (!info)
::AudacityMessageBox(wxString::Format(_("Language \"%s\" is unknown"), lang));
}
if (!info)
{
result = GetSystemLanguageCode();
info = wxLocale::FindLanguageInfo(result);
if (!info)
return result;
}
sLocale = std::make_unique<wxLocale>(info->Language);
for( const auto &path : FileNames::AudacityPathList() )
sLocale->AddCatalogLookupPathPrefix( path );
// LL: Must add the wxWidgets catalog manually since the search
// paths were not set up when mLocale was created. The
// catalogs are search in LIFO order, so add wxstd first.
sLocale->AddCatalog(wxT("wxstd"));
// AUDACITY_NAME is legitimately used on some *nix configurations.
#ifdef AUDACITY_NAME
sLocale->AddCatalog(wxT(AUDACITY_NAME));
#else
sLocale->AddCatalog(IPC_APPL);
#endif
// Initialize internationalisation (number formats etc.)
//
// This must go _after_ creating the wxLocale instance because
// creating the wxLocale instance sets the application-wide locale.
Internat::Init();
// Notify listeners of language changes
{
wxCommandEvent evt(EVT_LANGUAGE_CHANGE);
wxTheApp->ProcessEvent(evt);
}
// PRL: Moved this, do it only after language intialized
// Unused strings that we want to be translated, even though
// we're not using them yet...
wxString future1 = _("Master Gain Control");
return result;
}
wxString GUIPrefs::GetLang()
{
if (sLocale)
return sLocale->GetSysName();
else
return {};
}
PrefsPanel::Factory
GUIPrefsFactory = [](wxWindow *parent, wxWindowID winid)
{

View File

@ -37,6 +37,18 @@ class GUIPrefs final : public PrefsPanel
static void GetRangeChoices(
wxArrayStringEx *pChoices, wxArrayStringEx *pCodes);
// If no input language given, defaults first to choice in preferences, then
// to system language.
// Returns the language actually used which is not lang if lang cannot be found.
static wxString InitLang( wxString lang = {} );
// If no input language given, defaults to system language.
// Returns the language actually used which is not lang if lang cannot be found.
static wxString SetLang( const wxString & lang );
// Returns the last language code that was set
static wxString GetLang();
private:
void Populate();

View File

@ -52,8 +52,6 @@
#include <wx/minifram.h>
#include <wx/popupwin.h>
#include "../AudacityApp.h"
#include "ControlToolBar.h"
#include "DeviceToolBar.h"
#include "EditToolBar.h"
@ -672,7 +670,7 @@ void ToolManager::ReadConfig()
ToolBarConfiguration::Legacy topLegacy, botLegacy;
int vMajor, vMinor, vMicro;
wxGetApp().GetVersionKeysInit(vMajor, vMinor, vMicro);
gPrefs->GetVersionKeysInit(vMajor, vMinor, vMicro);
bool useLegacyDock = false;
// note that vMajor, vMinor, and vMicro will all be zero if either it's a new audacity.cfg file
// or the version is less than 1.3.13 (when there were no version keys according to the comments in

View File

@ -12,16 +12,12 @@
\class ErrorDialog
\brief Gives an Error message with an option for help.
*//*****************************************************************//**
\class AliasedFileMissingDialog
\brief Special case of ErrorDialog for reporting missing alias files.
*//********************************************************************/
#include "../Audacity.h"
#include "ErrorDialog.h"
#include <wx/app.h>
#include <wx/button.h>
#include <wx/icon.h>
#include <wx/dialog.h>
@ -37,43 +33,14 @@
#include "../AllThemeResources.h"
#include "../ShuttleGui.h"
#include "../HelpText.h"
#include "../Project.h"
#include "../Prefs.h"
#include "HelpSystem.h"
// special case for alias missing dialog because we keep track of if it exists.
class AliasedFileMissingDialog final : public ErrorDialog
{
public:
AliasedFileMissingDialog(AudacityProject *parent,
const wxString & dlogTitle,
const wxString & message,
const wxString & helpURL,
const bool Close = true, const bool modal = true);
virtual ~AliasedFileMissingDialog();
};
BEGIN_EVENT_TABLE(ErrorDialog, wxDialogWrapper)
EVT_BUTTON( wxID_OK, ErrorDialog::OnOk)
EVT_BUTTON( wxID_HELP, ErrorDialog::OnHelp)
END_EVENT_TABLE()
AliasedFileMissingDialog::AliasedFileMissingDialog(AudacityProject *parent,
const wxString & dlogTitle,
const wxString & message,
const wxString & helpURL,
const bool Close, const bool modal):
ErrorDialog(parent, dlogTitle, message, helpURL, Close, modal)
{
parent->SetMissingAliasFileDialog(this);
}
AliasedFileMissingDialog::~AliasedFileMissingDialog()
{
((AudacityProject*)GetParent())->SetMissingAliasFileDialog(NULL);
}
ErrorDialog::ErrorDialog(
wxWindow *parent,
const wxString & dlogTitle,
@ -202,34 +169,6 @@ void ShowModelessErrorDialog(wxWindow *parent,
// but in practice Destroy() in OnOK does that
}
void ShowAliasMissingDialog(AudacityProject *parent,
const wxString &dlogTitle,
const wxString &message,
const wxString &helpPage,
const bool Close)
{
wxASSERT(parent); // to justify safenew
ErrorDialog *dlog = safenew AliasedFileMissingDialog(parent, dlogTitle, message, helpPage, Close, false);
// Don't center because in many cases (effect, export, etc) there will be a progress bar in the center that blocks this.
// instead put it just above or on the top of the project.
wxPoint point;
point.x = 0;
point.y = parent ? parent->GetPosition().y - 200 : 100;
if (point.y < 100)
point.y = 100;
dlog->SetPosition(point);
dlog->CentreOnParent(wxHORIZONTAL);
// This needs to be modeless because user may need to
// stop playback AND read dialog's instructions.
dlog->Show();
// ANSWER-ME: Vigilant Sentry flags this method as not deleting dlog, so a mem leak.
// PRL: answer is that the parent window guarantees destruction of the dialog
// but in practice Destroy() in OnOK does that
}
extern wxString AudacityMessageBoxCaptionStr()
{
return _("Message");

View File

@ -18,6 +18,8 @@
#include <wx/msgdlg.h> // to inherit
#include "wxPanelWrapper.h" // to inherit
class AliasBlockFile;
class AudacityProject;
class ErrorDialog /* not final */ : public wxDialogWrapper
@ -56,13 +58,6 @@ void ShowModelessErrorDialog(wxWindow *parent,
const wxString &helpPage,
bool Close = true);
/// Displays a custom modeless error dialog for aliased file errors
void ShowAliasMissingDialog(AudacityProject *parent,
const wxString &dlogTitle,
const wxString &message,
const wxString &helpPage,
const bool Close = true);
extern wxString AudacityMessageBoxCaptionStr();
// Do not use wxMessageBox!! Its default window title does not translate!

View File

@ -9,7 +9,7 @@
*******************************************************************//**
\class FileHistory
\brief Similar to FileHistory, but customized to our needs.
\brief Similar to wxFileHistory, but customized to our needs.
*//*******************************************************************/
@ -21,6 +21,9 @@
#include <wx/menu.h>
#include "../Internat.h"
#include "../Prefs.h"
#include <mutex>
FileHistory::FileHistory(size_t maxfiles, wxWindowID base)
{
@ -32,6 +35,19 @@ FileHistory::~FileHistory()
{
}
FileHistory &FileHistory::Global()
{
// TODO - read the number of files to store in history from preferences
static FileHistory history{
ID_RECENT_LAST - ID_RECENT_FIRST + 1, ID_RECENT_CLEAR };
static std::once_flag flag;
std::call_once( flag, [&]{
history.Load(*gPrefs, wxT("RecentFiles"));
});
return history;
}
// File history management
void FileHistory::AddFileToHistory(const FilePath & file, bool update)
{

View File

@ -28,6 +28,15 @@ class AUDACITY_DLL_API FileHistory
FileHistory(size_t maxfiles = 12, wxWindowID idbase = wxID_FILE);
virtual ~FileHistory();
// These constants define the range of IDs reserved by the global file history
enum {
ID_RECENT_CLEAR = 6100,
ID_RECENT_FIRST = 6101,
ID_RECENT_LAST = 6112
};
static FileHistory &Global();
void AddFileToHistory(const FilePath & file, bool update = true);
void RemoveFileFromHistory(size_t i, bool update = true);
void Clear();

View File

@ -21,8 +21,6 @@ for each problem encountered, since there can be many orphans.
#include "../Audacity.h"
#include "MultiDialog.h"
#include "../Project.h"
#include <wx/app.h>
#include <wx/button.h>
#include <wx/dialog.h>
@ -34,7 +32,7 @@ for each problem encountered, since there can be many orphans.
#include <wx/artprov.h>
#include <wx/radiobox.h>
#include "../Menus.h"
#include "../AudacityLogger.h"
#include "wxPanelWrapper.h"
class MultiDialog final : public wxDialogWrapper
@ -153,8 +151,10 @@ void MultiDialog::OnOK(wxCommandEvent & WXUNUSED(event))
void MultiDialog::OnShowLog(wxCommandEvent & WXUNUSED(event))
{
auto project = GetActiveProject();
HelpActions::DoShowLog(*project);
auto logger = AudacityLogger::Get();
if (logger) {
logger->Show();
}
}

View File

@ -20,7 +20,9 @@ class wxArrayString;
class wxFileNameWrapper : public wxFileName
{
public:
explicit
using wxFileName::wxFileName;
explicit
wxFileNameWrapper(const wxFileName &that)
: wxFileName(that)
{}

View File

@ -137,6 +137,8 @@
<ClCompile Include="..\..\..\src\BlockFile.cpp" />
<ClCompile Include="..\..\..\src\blockfile\NotYetAvailableException.cpp" />
<ClCompile Include="..\..\..\src\CellularPanel.cpp" />
<ClCompile Include="..\..\..\src\Clipboard.cpp" />
<ClCompile Include="..\..\..\src\CrashReport.cpp" />
<ClCompile Include="..\..\..\src\commands\AudacityCommand.cpp" />
<ClCompile Include="..\..\..\src\commands\CommandContext.cpp" />
<ClCompile Include="..\..\..\src\commands\CommandTargets.cpp" />
@ -201,6 +203,7 @@
<ClCompile Include="..\..\..\src\menus\TransportMenus.cpp" />
<ClCompile Include="..\..\..\src\menus\ViewMenus.cpp" />
<ClCompile Include="..\..\..\src\menus\WindowMenus.cpp" />
<ClCompile Include="..\..\..\src\MissingAliasFileDialog.cpp" />
<ClCompile Include="..\..\..\src\Mix.cpp" />
<ClCompile Include="..\..\..\src\MixerBoard.cpp" />
<ClCompile Include="..\..\..\lib-src\lib-widget-extra\NonGuiThread.cpp" />
@ -496,6 +499,8 @@
<ClInclude Include="..\..\..\src\BlockFile.h" />
<ClInclude Include="..\..\..\src\blockfile\NotYetAvailableException.h" />
<ClInclude Include="..\..\..\src\CellularPanel.h" />
<ClInclude Include="..\..\..\src\Clipboard.h" />
<ClInclude Include="..\..\..\src\CrashReport.h" />
<ClInclude Include="..\..\..\src\commands\AudacityCommand.h" />
<ClInclude Include="..\..\..\src\commands\CommandContext.h" />
<ClInclude Include="..\..\..\src\commands\CommandFlag.h" />
@ -623,6 +628,7 @@
<ClInclude Include="..\..\..\src\MacroMagic.h" />
<ClInclude Include="..\..\..\src\Matrix.h" />
<ClInclude Include="..\..\..\src\Menus.h" />
<ClInclude Include="..\..\..\src\MissingAliasFileDialog.h" />
<ClInclude Include="..\..\..\src\Mix.h" />
<ClInclude Include="..\..\..\src\MixerBoard.h" />
<ClInclude Include="..\..\..\lib-src\lib-widget-extra\NonGuiThread.h" />
@ -1271,4 +1277,4 @@
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\ny.targets" />
</ImportGroup>
</Project>
</Project>

View File

@ -221,6 +221,9 @@
<ClCompile Include="..\..\..\src\Menus.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\MissingAliasFileDialog.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\Mix.cpp">
<Filter>src</Filter>
</ClCompile>
@ -1088,6 +1091,12 @@
<ClCompile Include="..\..\..\src\CellularPanel.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\Clipboard.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\CrashReport.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\menus\WindowMenus.cpp">
<Filter>src\menus</Filter>
</ClCompile>
@ -1258,6 +1267,9 @@
<ClInclude Include="..\..\..\src\Menus.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\MissingAliasFileDialog.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\Mix.h">
<Filter>src</Filter>
</ClInclude>
@ -2209,6 +2221,12 @@
<ClInclude Include="..\..\..\src\CellularPanel.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\Clipboard.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\CrashReport.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\AdornedRulerPanel.h">
<Filter>src</Filter>
</ClInclude>
@ -2452,4 +2470,4 @@
<Filter>Resources</Filter>
</Manifest>
</ItemGroup>
</Project>
</Project>