Audacity 3.2.0
Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | List of all members
AudacityApp Class Referencefinal

AudacityApp is the 'main' class for Audacity. More...

#include <AudacityApp.h>

Inheritance diagram for AudacityApp:
[legend]
Collaboration diagram for AudacityApp:
[legend]

Public Member Functions

 AudacityApp ()
 
 ~AudacityApp ()
 
bool Initialize (int &argc, wxChar **argv) override
 
bool OSXIsGUIApplication () override
 
void CleanUp () override
 
bool OnInit () override
 
bool InitPart2 ()
 
int OnRun () override
 
int OnExit (void) override
 
void OnFatalException () override
 
bool OnExceptionInMainLoop () override
 
void OnIdle (wxIdleEvent &)
 
void OnMenuAbout (wxCommandEvent &event)
 
void OnMenuNew (wxCommandEvent &event)
 
void OnMenuOpen (wxCommandEvent &event)
 
void OnMenuPreferences (wxCommandEvent &event)
 
void OnMenuExit (wxCommandEvent &event)
 
void OnQueryEndSession (wxCloseEvent &event)
 
void OnEndSession (wxCloseEvent &event)
 
void OnMRUClear (wxCommandEvent &event)
 
void OnMRUFile (wxCommandEvent &event)
 
bool MRUOpen (const FilePath &fileName)
 
bool SafeMRUOpen (const wxString &fileName)
 
void OnReceiveCommand (AppCommandEvent &event)
 
void OnKeyDown (wxKeyEvent &event)
 
void OnTimer (wxTimerEvent &event)
 
void OnServerEvent (wxSocketEvent &evt)
 
void OnSocketEvent (wxSocketEvent &evt)
 
void MacOpenFile (const wxString &fileName) override
 
void MacPrintFile (const wxString &fileName) override
 
void MacNewFile () override
 
void AssociateFileTypes ()
 
void MacActivateApp ()
 
void MacFinishLaunching ()
 

Static Public Member Functions

static void OnThemeChange (struct ThemeChangeMessage)
 

Private Member Functions

void OnInit0 ()
 
void InitCommandHandler ()
 
bool InitTempDir ()
 
bool CreateSingleInstanceChecker (const wxString &dir)
 
void ShowSplashScreen ()
 
void HideSplashScreen (bool fadeOut=true)
 
std::unique_ptr< wxCmdLineParser > ParseCommandLine ()
 
- Private Member Functions inherited from AppEvents::ProviderBase
virtual ~ProviderBase ()=default
 
void HandleAppInitialized ()
 
void HandleAppIdle ()
 
void HandleAppClosing ()
 

Private Attributes

Observer::Subscription mThemeChangeSubscription
 
std::unique_ptr< CommandHandlermCmdHandler
 
std::unique_ptr< wxSingleInstanceChecker > mChecker
 
wxTimer mTimer
 
wxTimer mSplashTimer
 
std::unique_ptr< wxSplashScreen > mSplashScreen
 
std::unique_ptr< IPCServmIPCServ
 

Detailed Description

AudacityApp is the 'main' class for Audacity.

It handles initialization and termination by subclassing wxApp.

Definition at line 39 of file AudacityApp.h.

Constructor & Destructor Documentation

◆ AudacityApp()

AudacityApp::AudacityApp ( )

Definition at line 1237 of file AudacityApp.cpp.

1238{
1239}

◆ ~AudacityApp()

AudacityApp::~AudacityApp ( )

Definition at line 1267 of file AudacityApp.cpp.

1268{
1269}

Member Function Documentation

◆ AssociateFileTypes()

void AudacityApp::AssociateFileTypes ( )

Definition at line 2661 of file AudacityApp.cpp.

2662{
2663 // Check pref in case user has already decided against it.
2664 bool bWantAssociateFiles = true;
2665 if (gPrefs->Read(wxT("/WantAssociateFiles"), &bWantAssociateFiles) &&
2666 !bWantAssociateFiles)
2667 {
2668 // User has already decided against it
2669 return;
2670 }
2671
2672 wxRegKey associateFileTypes;
2673
2674 auto IsDefined = [&](const wxString &type)
2675 {
2676 associateFileTypes.SetName(wxString::Format(wxT("HKCR\\%s"), type));
2677 bool bKeyExists = associateFileTypes.Exists();
2678 if (!bKeyExists)
2679 {
2680 // Not at HKEY_CLASSES_ROOT. Try HKEY_CURRENT_USER.
2681 associateFileTypes.SetName(wxString::Format(wxT("HKCU\\Software\\Classes\\%s"), type));
2682 bKeyExists = associateFileTypes.Exists();
2683 }
2684 return bKeyExists;
2685 };
2686
2687 auto DefineType = [&](const wxString &type)
2688 {
2689 wxString root_key = wxT("HKCU\\Software\\Classes\\");
2690
2691 // Start with HKEY_CLASSES_CURRENT_USER.
2692 associateFileTypes.SetName(wxString::Format(wxT("%s%s"), root_key, type));
2693 if (!associateFileTypes.Create(true))
2694 {
2695 // Not at HKEY_CLASSES_CURRENT_USER. Try HKEY_CURRENT_ROOT.
2696 root_key = wxT("HKCR\\");
2697 associateFileTypes.SetName(wxString::Format(wxT("%s%s"), root_key, type));
2698 if (!associateFileTypes.Create(true))
2699 {
2700 // Actually, can't create keys. Empty root_key to flag failure.
2701 root_key.empty();
2702 }
2703 }
2704
2705 if (!root_key.empty())
2706 {
2707 associateFileTypes = wxT("Audacity.Project"); // Finally set value for the key
2708 }
2709
2710 return root_key;
2711 };
2712
2713 // Check for legacy and UP types
2714 if (IsDefined(wxT(".aup3")) && IsDefined(wxT(".aup")) && IsDefined(wxT("Audacity.Project")))
2715 {
2716 // Already defined, so bail
2717 return;
2718 }
2719
2720 // File types are not currently associated.
2721 int wantAssoc =
2723 XO(
2724"Audacity project (.aup3) files are not currently \nassociated with Audacity. \n\nAssociate them, so they open on double-click?"),
2725 XO("Audacity Project Files"),
2726 wxYES_NO | wxICON_QUESTION);
2727
2728 if (wantAssoc == wxNO)
2729 {
2730 // User said no. Set a pref so we don't keep asking.
2731 gPrefs->Write(wxT("/WantAssociateFiles"), false);
2732 gPrefs->Flush();
2733 return;
2734 }
2735
2736 // Show that user wants associations
2737 gPrefs->Write(wxT("/WantAssociateFiles"), true);
2738 gPrefs->Flush();
2739
2740 wxString root_key;
2741
2742 root_key = DefineType(wxT(".aup3"));
2743 if (root_key.empty())
2744 {
2745 //v Warn that we can't set keys. Ask whether to set pref for no retry?
2746 }
2747 else
2748 {
2749 DefineType(wxT(".aup"));
2750
2751 associateFileTypes = wxT("Audacity.Project"); // Finally set value for .AUP key
2752 associateFileTypes.SetName(root_key + wxT("Audacity.Project"));
2753 if (!associateFileTypes.Exists())
2754 {
2755 associateFileTypes.Create(true);
2756 associateFileTypes = wxT("Audacity Project File");
2757 }
2758
2759 associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell"));
2760 if (!associateFileTypes.Exists())
2761 {
2762 associateFileTypes.Create(true);
2763 associateFileTypes = wxT("");
2764 }
2765
2766 associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open"));
2767 if (!associateFileTypes.Exists())
2768 {
2769 associateFileTypes.Create(true);
2770 }
2771
2772 associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open\\command"));
2773 wxString tmpRegAudPath;
2774 if(associateFileTypes.Exists())
2775 {
2776 tmpRegAudPath = associateFileTypes.QueryDefaultValue().Lower();
2777 }
2778
2779 if (!associateFileTypes.Exists() ||
2780 (tmpRegAudPath.Find(wxT("audacity.exe")) >= 0))
2781 {
2782 associateFileTypes.Create(true);
2783 associateFileTypes = (wxString)argv[0] + (wxString)wxT(" \"%1\"");
2784 }
2785
2786#if 0
2787 // These can be use later to support more startup messages
2788 // like maybe "Import into existing project" or some such.
2789 // Leaving here for an example...
2790 associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open\\ddeexec"));
2791 if (!associateFileTypes.Exists())
2792 {
2793 associateFileTypes.Create(true);
2794 associateFileTypes = wxT("%1");
2795 }
2796
2797 associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open\\ddeexec\\Application"));
2798 if (!associateFileTypes.Exists())
2799 {
2800 associateFileTypes.Create(true);
2801 associateFileTypes = IPC_APPL;
2802 }
2803
2804 associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open\\ddeexec\\Topic"));
2805 if (!associateFileTypes.Exists())
2806 {
2807 associateFileTypes.Create(true);
2808 associateFileTypes = IPC_TOPIC;
2809 }
2810#endif
2811 }
2812}
wxT("CloseDown"))
#define IPC_APPL
#define IPC_TOPIC
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
XO("Cut/Copy/Paste")
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
virtual bool Flush() noexcept=0
virtual bool Write(const wxString &key, bool value)=0
virtual bool Read(const wxString &key, bool *value) const =0
UTILITY_API const char *const * argv
A copy of argv; responsibility of application startup to assign it.

References CommandLineArgs::argv, AudacityMessageBox(), audacity::BasicSettings::Flush(), gPrefs, IPC_APPL, IPC_TOPIC, audacity::BasicSettings::Read(), audacity::BasicSettings::Write(), wxT(), and XO().

Referenced by InitPart2().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CleanUp()

void AudacityApp::CleanUp ( )
override

Definition at line 1250 of file AudacityApp.cpp.

1251{
1252 //Reset the current wxConfigBase instance manually
1253 //to avoid double deletion in wxWidgets 3.2
1254 //See Bug #5511
1255 wxConfigBase::Set(nullptr);
1256 gConfig.reset();
1257 wxApp::CleanUp();
1258}
static std::shared_ptr< wxConfigBase > gConfig

References gConfig.

◆ CreateSingleInstanceChecker()

bool AudacityApp::CreateSingleInstanceChecker ( const wxString &  dir)
private

Definition at line 1980 of file AudacityApp.cpp.

1981{
1982 wxString name = wxString::Format(wxT("audacity-lock-%s"), wxGetUserId());
1983 mChecker.reset();
1984 auto checker = std::make_unique<wxSingleInstanceChecker>();
1985
1986 auto runningTwoCopiesStr = XO("Running two copies of Audacity simultaneously may cause\ndata loss or cause your system to crash.\n\n");
1987
1988 if (!checker->Create(name, dir))
1989 {
1990 // Error initializing the wxSingleInstanceChecker. We don't know
1991 // whether there is another instance running or not.
1992
1993 auto prompt = XO(
1994"Audacity was not able to lock the temporary files directory.\nThis folder may be in use by another copy of Audacity.\n")
1995 + runningTwoCopiesStr
1996 + XO("Do you still want to start Audacity?");
1997 int action = AudacityMessageBox(
1998 prompt,
1999 XO("Error Locking Temporary Folder"),
2000 wxYES_NO | wxICON_EXCLAMATION, NULL);
2001 if (action == wxNO)
2002 return false;
2003 }
2004 else if ( checker->IsAnotherRunning() ) {
2005 // Parse the command line to ensure correct syntax, but
2006 // ignore options other than -v, and only use the filenames, if any.
2007 auto parser = ParseCommandLine();
2008 if (!parser)
2009 {
2010 // Complaints have already been made
2011 return false;
2012 }
2013
2014 if (parser->Found(wxT("v")))
2015 {
2016 wxPrintf("Audacity v%s\n", AUDACITY_VERSION_STRING);
2017 return false;
2018 }
2019
2020 // Windows and Linux require absolute file names as command may
2021 // not come from current working directory.
2022 FilePaths filenames;
2023 for (size_t i = 0, cnt = parser->GetParamCount(); i < cnt; i++)
2024 {
2025 wxFileName filename(parser->GetParam(i));
2026 if (filename.MakeAbsolute())
2027 {
2028 filenames.push_back(filename.GetLongPath());
2029 }
2030 }
2031
2032 #ifdef HAS_CUSTOM_URL_HANDLING
2033 wxString url;
2034 parser->Found("u", &url);
2035 #endif
2036
2037
2038 // On Windows, we attempt to make a connection
2039 // to an already active Audacity. If successful, we send
2040 // the first command line argument (the audio file name)
2041 // to that Audacity for processing.
2042 wxClient client;
2043
2044 // We try up to 50 times since there's a small window
2045 // where the server may not have been fully initialized.
2046 for (int i = 0; i < 50; i++)
2047 {
2048 std::unique_ptr<wxConnectionBase> conn{ client.MakeConnection(wxEmptyString, IPC_APPL, IPC_TOPIC) };
2049 if (conn)
2050 {
2051 bool ok = false;
2052 #ifdef HAS_CUSTOM_URL_HANDLING
2053 if (!url.empty())
2054 {
2055 if (!conn->Execute(urlPrefix + url))
2056 return false;
2057 }
2058 #endif
2059
2060 if (filenames.size() > 0)
2061 {
2062 for (size_t i = 0, cnt = filenames.size(); i < cnt; i++)
2063 {
2064 ok = conn->Execute(filenames[i]);
2065 }
2066 }
2067 else
2068 {
2069 // Send an empty string to force existing Audacity to front
2070 ok = conn->Execute(wxEmptyString);
2071 }
2072
2073 if (ok)
2074 return false;
2075 }
2076
2077 using namespace std::chrono;
2078 std::this_thread::sleep_for(10ms);
2079 }
2080 // There is another copy of Audacity running. Force quit.
2081
2082 auto prompt = XO(
2083"The system has detected that another copy of Audacity is running.\n")
2084 + runningTwoCopiesStr
2085 + XO(
2086"Use the New or Open commands in the currently running Audacity\nprocess to open multiple projects simultaneously.\n");
2088 prompt, XO("Audacity is already running"),
2089 wxOK | wxICON_ERROR);
2090
2091 return false;
2092 }
2093
2094 // Create the DDE IPC server
2095 mIPCServ = std::make_unique<IPCServ>(IPC_APPL);
2096 mChecker = std::move(checker);
2097 return true;
2098}
wxString name
Definition: TagsEditor.cpp:166
std::unique_ptr< wxSingleInstanceChecker > mChecker
Definition: AudacityApp.h:120
std::unique_ptr< wxCmdLineParser > ParseCommandLine()
std::unique_ptr< IPCServ > mIPCServ
Definition: AudacityApp.h:136
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.

References AudacityMessageBox(), IPC_APPL, IPC_TOPIC, mChecker, mIPCServ, name, ParseCommandLine(), audacity::cloud::audiocom::anonymous_namespace{OAuthService.cpp}::urlPrefix, wxT(), and XO().

Referenced by InitPart2().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ HideSplashScreen()

void AudacityApp::HideSplashScreen ( bool  fadeOut = true)
private

Definition at line 1320 of file AudacityApp.cpp.

1321{
1322 const int fadeDurationMs = 120;
1323 const int fadeStepMs = 16;
1324
1325 const int maxTransparency = 255;
1326 const int numSteps = fadeDurationMs / fadeStepMs;
1327 const int transparencyDecrement = maxTransparency / numSteps;
1328
1329 int currentAlpha = maxTransparency;
1330
1331 // Splash was already destroyed
1332 if (!mSplashScreen) {
1333 return;
1334 }
1335
1336 if (!fadeOut) {
1337 mSplashScreen->Destroy();
1338 mSplashScreen.release();
1339 return;
1340 }
1341
1342 mSplashTimer.Start(fadeStepMs);
1343
1344 mSplashTimer.Bind(wxEVT_TIMER, [this, currentAlpha, transparencyDecrement](wxTimerEvent& evt) mutable {
1345 currentAlpha -= transparencyDecrement;
1346 if (!mSplashScreen) {
1347 mSplashTimer.Stop();
1348 }
1349 else if (currentAlpha <= 0) {
1350 mSplashTimer.Stop();
1351 mSplashScreen->Destroy();
1352 mSplashScreen.release();
1353 }
1354 else if (mSplashScreen->CanSetTransparent()) {
1355 mSplashScreen->SetTransparent(currentAlpha);
1356 }
1357 });
1358}
std::unique_ptr< wxSplashScreen > mSplashScreen
Definition: AudacityApp.h:124
wxTimer mSplashTimer
Definition: AudacityApp.h:123
BuiltinEffectsModule::Registration< FadeOut > fadeOut

References anonymous_namespace{RegisterBuiltinEffects.cpp}::fadeOut, mSplashScreen, and mSplashTimer.

Referenced by InitPart2().

Here is the caller graph for this function:

◆ InitCommandHandler()

void AudacityApp::InitCommandHandler ( )
private

Definition at line 1849 of file AudacityApp.cpp.

1850{
1851 mCmdHandler = std::make_unique<CommandHandler>();
1852 //SetNextHandler(mCmdHandler);
1853}
std::unique_ptr< CommandHandler > mCmdHandler
Definition: AudacityApp.h:118

References mCmdHandler.

Referenced by InitPart2().

Here is the caller graph for this function:

◆ Initialize()

bool AudacityApp::Initialize ( int &  argc,
wxChar **  argv 
)
override

Definition at line 1241 of file AudacityApp.cpp.

1242{
1244 {
1246 }
1247 return wxApp::Initialize(argc, argv);
1248}
static bool IsHostProcess()
Returns true if current process is considered to be a plugin host process.
Definition: PluginHost.cpp:202
UTILITY_API int argc
A copy of argc; responsibility of application startup to assign it.

References CommandLineArgs::argc, CommandLineArgs::argv, anonymous_namespace{AudacityApp.cpp}::InitCrashreports(), Journal::Events::anonymous_namespace{JournalEvents.cpp}::Initialize(), and PluginHost::IsHostProcess().

Here is the call graph for this function:

◆ InitPart2()

bool AudacityApp::InitPart2 ( )

Definition at line 1524 of file AudacityApp.cpp.

1525{
1526#if defined(__WXMAC__)
1527 SetExitOnFrameDelete(false);
1528#endif
1529
1530 // Make sure the temp dir isn't locked by another process.
1531 {
1532 auto key =
1533 PreferenceKey(FileNames::Operation::Temp, FileNames::PathType::_None);
1534 auto temp = gPrefs->Read(key);
1535 if (temp.empty() || !CreateSingleInstanceChecker(temp)) {
1537 return false;
1538 }
1539 }
1540
1541 //<<<< Try to avoid dialogs before this point.
1542 // The reason is that InitTempDir starts the single instance checker.
1543 // If we're waiitng in a dialog before then we can very easily
1544 // start multiple instances, defeating the single instance checker.
1545
1546 // Initialize the CommandHandler
1548
1549 // Initialize the ModuleManager, including loading found modules
1551
1552 // Initialize the PluginManager
1553 PluginManager::Get().Initialize( [](const FilePath &localFileName){
1554 return std::make_unique<SettingsWX>(
1555 AudacityFileConfig::Create({}, {}, localFileName)
1556 );
1557 });
1558
1559 // Parse command line and handle options that might require
1560 // immediate exit...no need to initialize all of the audio
1561 // stuff to display the version string.
1562 std::shared_ptr< wxCmdLineParser > parser{ ParseCommandLine() };
1563 if (!parser)
1564 {
1565 // Either user requested help or a parsing error occurred
1566 exit(1);
1567 }
1568
1569 wxString journalFileName;
1570 const bool playingJournal = parser->Found("j", &journalFileName);
1571
1572#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) && !defined(__CYGWIN__)
1573 if (!playingJournal)
1574 this->AssociateFileTypes();
1575#endif
1576
1577 if (parser->Found(wxT("v")))
1578 {
1579 wxPrintf("Audacity v%s\n", AUDACITY_VERSION_STRING);
1580 exit(0);
1581 }
1582
1583 long lval;
1584 if (parser->Found(wxT("b"), &lval))
1585 {
1586 if (lval < 256 || lval > 100000000)
1587 {
1588 wxPrintf(_("Block size must be within 256 to 100000000\n"));
1589 exit(1);
1590 }
1591
1593 }
1594
1595 if (playingJournal)
1596 Journal::SetInputFileName( journalFileName );
1597
1599
1601
1602 {
1603 // ANSWER-ME: Why is YieldFor needed at all?
1604 //Leo: allegedly it hangs on CJK input otherwise, #805
1605 //wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI|wxEVT_CATEGORY_USER_INPUT|wxEVT_CATEGORY_UNKNOWN);
1606 wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI | wxEVT_CATEGORY_USER_INPUT);
1607
1608 //JKC: Would like to put module loading here.
1609
1610 // More initialization
1611
1612 InitDitherers();
1613 AudioIO::Init();
1614
1615#ifdef __WXMAC__
1616
1617 // On the Mac, users don't expect a program to quit when you close the last window.
1618 // Create a menubar that will show when all project windows are closed.
1619
1620 auto fileMenu = std::make_unique<wxMenu>();
1621 auto urecentMenu = std::make_unique<wxMenu>();
1622 auto recentMenu = urecentMenu.get();
1623 fileMenu->Append(wxID_NEW, wxString(_("&New")) + wxT("\tCtrl+N"));
1624 fileMenu->Append(wxID_OPEN, wxString(_("&Open...")) + wxT("\tCtrl+O"));
1625 fileMenu->AppendSubMenu(urecentMenu.release(), _("Open &Recent..."));
1626 fileMenu->Append(wxID_ABOUT, _("&About Audacity..."));
1627 fileMenu->Append(wxID_PREFERENCES, wxString(_("&Preferences...")) + wxT("\tCtrl+,"));
1628
1629 {
1630 auto menuBar = std::make_unique<wxMenuBar>();
1631 menuBar->Append(fileMenu.release(), _("&File"));
1632
1633 // PRL: Are we sure wxWindows will not leak this menuBar?
1634 // The online documentation is not explicit.
1635 wxMenuBar::MacSetCommonMenuBar(menuBar.release());
1636 }
1637
1638 auto &recentFiles = FileHistory::Global();
1639 recentFiles.UseMenu(recentMenu);
1640
1641#endif //__WXMAC__
1642 }
1643
1644 //Search for the new plugins
1645 std::vector<wxString> failedPlugins;
1646 if(!playingJournal && !SkipEffectsScanAtStartup.Read())
1647 {
1648 HideSplashScreen(true);
1649 auto newPlugins = PluginManager::Get().CheckPluginUpdates();
1650 if(!newPlugins.empty())
1651 {
1652 PluginStartupRegistration reg(newPlugins);
1653 reg.Run();
1654 failedPlugins = reg.GetFailedPluginsPaths();
1655 }
1656 }
1657
1658 // Must do this before creating the first project, else the early exit path
1659 // may crash
1661 return false;
1662
1663 // Workaround Bug 1377 - Crash after Audacity starts and low disk space warning appears
1664 // The temporary splash window is closed AND cleaned up, before attempting to create
1665 // a project and possibly creating a modal warning dialog by doing so.
1666 // Also fixes problem of warning being obscured.
1667 // Downside is that we have no splash screen for the (brief) time that we spend
1668 // creating the project.
1669 // Root cause is problem with wxSplashScreen and other dialogs co-existing, that
1670 // seemed to arrive with wx3.
1671 {
1673 }
1674
1675 if (!playingJournal && ProjectSettings::Get(*project).GetShowSplashScreen())
1676 {
1677 // This may do a check-for-updates at every start up.
1678 // Mainly this is to tell users of ALPHAS who don't know that they have an ALPHA.
1679 // Disabled for now, after discussion.
1680 // project->MayCheckForUpdates();
1681#ifdef HAS_WHATS_NEW
1683#endif
1684 }
1685
1686 // Update Manager may spawn a modal dialog, we need to hide the splash screen before that
1687 bool splashFadeOut = !playingJournal;
1688 HideSplashScreen(splashFadeOut);
1689
1690#if defined(HAVE_UPDATES_CHECK)
1691 UpdateManager::Start(playingJournal);
1692#endif
1693
1696
1697 // Bug1561: delay the recovery dialog, to avoid crashes.
1698 CallAfter( [=] () mutable {
1699 // Remove duplicate shortcuts when there's a change of version
1700 int vMajorInit, vMinorInit, vMicroInit;
1701 GetPreferencesVersion(vMajorInit, vMinorInit, vMicroInit);
1702 if (vMajorInit != AUDACITY_VERSION || vMinorInit != AUDACITY_RELEASE
1703 || vMicroInit != AUDACITY_REVISION) {
1705 }
1706 //
1707 // Auto-recovery
1708 //
1709 bool didRecoverAnything = false;
1710 // This call may reassign project (passed by reference)
1711 if (!playingJournal)
1712 {
1713 if (!ShowAutoRecoveryDialogIfNeeded(project, &didRecoverAnything))
1714 {
1715 QuitAudacity(true);
1716 }
1717 }
1718
1719 //
1720 // Remainder of command line parsing, but only if we didn't recover
1721 //
1722 if (project && !didRecoverAnything)
1723 {
1724 if (parser->Found(wxT("t")))
1725 {
1726 RunBenchmark( nullptr, *project);
1727 QuitAudacity(true);
1728 }
1729
1730 for (size_t i = 0, cnt = parser->GetParamCount(); i < cnt; i++)
1731 {
1732 // PRL: Catch any exceptions, don't try this file again, continue to
1733 // other files.
1734 SafeMRUOpen(parser->GetParam(i));
1735 }
1736
1737 if(!failedPlugins.empty())
1738 {
1739 auto dialog = safenew IncompatiblePluginsDialog(GetTopWindow(), wxID_ANY, ScanType::Startup, failedPlugins);
1740 dialog->Bind(wxEVT_CLOSE_WINDOW, [dialog](wxCloseEvent&) { dialog->Destroy(); });
1741 dialog->Show();
1742 }
1743 }
1744 } );
1745
1746 gInited = true;
1747
1749
1750 mTimer.SetOwner(this, kAudacityAppTimerID);
1751 mTimer.Start(200);
1752
1753#ifdef EXPERIMENTAL_EASY_CHANGE_KEY_BINDINGS
1755 [](const CommandID &id){
1756 if (::wxGetMouseState().ShiftDown()) {
1757 // Only want one page of the preferences
1758 PrefsPanel::Factories factories;
1759 factories.push_back(KeyConfigPrefsFactory( id ));
1760 const auto pProject = GetActiveProject().lock();
1761 auto pWindow = FindProjectFrame( pProject.get() );
1762 // pProject may be null
1763 GlobalPrefsDialog dialog( pWindow, pProject.get(), factories );
1764 dialog.ShowModal();
1766 return true;
1767 }
1768 else
1769 return false;
1770 } };
1771#endif
1772
1773#if defined(__WXMAC__)
1774 // The first time this version of Audacity is run or when the preferences
1775 // are reset, execute the "tccutil" command to reset the microphone permissions
1776 // currently assigned to Audacity. The end result is that the user will be
1777 // prompted to approve/deny Audacity access (again).
1778 //
1779 // This should resolve confusion of why Audacity appears to record, but only
1780 // gets silence due to Audacity being denied microphone access previously.
1781 bool permsReset = false;
1782 gPrefs->Read(wxT("/MicrophonePermissionsReset"), &permsReset, false);
1783 if (!permsReset) {
1784 system("tccutil reset Microphone org.audacityteam.audacity");
1785 gPrefs->Write(wxT("/MicrophonePermissionsReset"), true);
1786 }
1787#endif
1788
1789#if defined(__WXMAC__)
1790 // Bug 2709: Workaround CoreSVG locale issue
1791 Bind(wxEVT_MENU_OPEN, [=](wxMenuEvent &event)
1792 {
1793 wxSetlocale(LC_NUMERIC, wxString(wxT("C")));
1794 event.Skip();
1795 });
1796
1797 Bind(wxEVT_MENU_CLOSE, [=](wxMenuEvent &event)
1798 {
1799 wxSetlocale(LC_NUMERIC, Languages::GetLocaleName());
1800 event.Skip();
1801 });
1802#endif
1803
1804#ifdef HAS_CUSTOM_URL_HANDLING
1805 // Schemes are case insensitive as per RFC: https://www.rfc-editor.org/rfc/rfc3986#section-3.1
1806 URLSchemesRegistry::Get().RegisterScheme(AUDACITY_NAME);
1807
1808 wxString url;
1809 if (parser->Found("u", &url))
1810 {
1811 auto utf8Url = url.ToUTF8();
1812 URLSchemesRegistry::Get().HandleURL({ utf8Url.data(), utf8Url.length() });
1813 }
1814#endif
1815
1817
1818 return TRUE;
1819}
AUDACITY_DLL_API std::weak_ptr< AudacityProject > GetActiveProject()
#define kAudacityAppTimerID
static void QuitAudacity(bool bForce)
static bool gInited
bool ShowAutoRecoveryDialogIfNeeded(AudacityProject *&pproj, bool *didRecoverAnything)
void RunBenchmark(wxWindow *parent, AudacityProject &project)
Definition: Benchmark.cpp:91
BoolSetting SkipEffectsScanAtStartup
#define _(s)
Definition: Internat.h:73
PrefsPanel::Factory KeyConfigPrefsFactory(const CommandID &name)
#define safenew
Definition: MemoryX.h:10
@ AppInitialized
static const AudacityProject::AttachedObjects::RegisteredFactory key
void FinishPreferences()
Definition: Prefs.cpp:262
void GetPreferencesVersion(int &vMajor, int &vMinor, int &vMicro)
Definition: Prefs.cpp:239
wxString FilePath
Definition: Project.h:21
wxFrame * FindProjectFrame(AudacityProject *project)
Get a pointer to the window associated with a project, or null if the given pointer is null,...
void InitDitherers()
const auto project
int id
wxTimer mTimer
Definition: AudacityApp.h:122
void AssociateFileTypes()
void HideSplashScreen(bool fadeOut=true)
void ShowSplashScreen()
bool CreateSingleInstanceChecker(const wxString &dir)
void InitCommandHandler()
bool SafeMRUOpen(const wxString &fileName)
static std::unique_ptr< AudacityFileConfig > Create(const wxString &appName={}, const wxString &vendorName={}, const wxString &localFilename={}, const wxString &globalFilename={}, long style=wxCONFIG_USE_LOCAL_FILE|wxCONFIG_USE_GLOBAL_FILE, const wxMBConv &conv=wxConvAuto())
Require a call to this factory, to guarantee proper two-phase initialization.
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
static void Init()
Definition: AudioIO.cpp:190
static ExportPluginRegistry & Get()
static FileHistory & Global()
Definition: FileHistory.cpp:39
typename GlobalVariable< GlobalMenuHook, const std::function< bool(const CommandID &) >, nullptr, Options... >::Scope Scope
static Importer & Get()
Definition: Import.cpp:103
bool Initialize()
Definition: Import.cpp:167
static void RebuildAllMenuBars()
void RemoveDuplicateShortcuts()
static MenuCreator & Get(AudacityProject &project)
Definition: MenuCreator.cpp:91
static ModuleManager & Get()
int Dispatch(ModuleDispatchTypes type)
std::map< wxString, std::vector< wxString > > CheckPluginUpdates()
Ensures that all currently registered plugins still exist and scans for new ones.
void Initialize(ConfigFactory factory)
static PluginManager & Get()
std::vector< PrefsPanel::PrefsNode > Factories
Definition: PrefsPanel.h:72
static AudacityProject * New()
static ProjectSettings & Get(AudacityProject &project)
bool GetShowSplashScreen() const
static void SetMaxDiskBlockSize(size_t bytes)
Definition: Sequence.cpp:1892
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:207
bool RegisterScheme(std::string_view scheme)
Associates a new scheme with Audacity.
static URLSchemesRegistry & Get()
Retrieves the registry instance.
void HandleURL(std::string_view url)
static void Start(bool suppressModal)
static void Show(AudacityProject &project)
void CallAfter(Action action)
Schedule an action to be done later, and in the main thread.
Definition: BasicUI.cpp:214
FILES_API wxString PreferenceKey(FileNames::Operation op, FileNames::PathType type)
FILES_API FilePath DataDir()
Audacity user data directory.
bool Begin(const FilePath &dataDir)
Definition: Journal.cpp:226
void SetInputFileName(const wxString &path)
Definition: Journal.cpp:221
wxString GetLocaleName()
Definition: Languages.cpp:390
BuiltinCommandsModule::Registration< CompareAudioCommand > reg
static CommandContext::TargetFactory::SubstituteInUnique< InteractiveOutputTargets > scope

References _, AppInitialized, AssociateFileTypes(), Journal::Begin(), BasicUI::CallAfter(), PluginManager::CheckPluginUpdates(), AudacityFileConfig::Create(), CreateSingleInstanceChecker(), FileNames::DataDir(), ModuleManager::Dispatch(), FindProjectFrame(), FinishPreferences(), ExportPluginRegistry::Get(), Importer::Get(), ModuleManager::Get(), PluginManager::Get(), URLSchemesRegistry::Get(), MenuCreator::Get(), ProjectSettings::Get(), GetActiveProject(), Languages::GetLocaleName(), GetPreferencesVersion(), ProjectSettings::GetShowSplashScreen(), gInited, FileHistory::Global(), gPrefs, AppEvents::ProviderBase::HandleAppInitialized(), URLSchemesRegistry::HandleURL(), HideSplashScreen(), id, AudioIO::Init(), InitCommandHandler(), InitDitherers(), ExportPluginRegistry::Initialize(), Importer::Initialize(), ModuleManager::Initialize(), PluginManager::Initialize(), kAudacityAppTimerID, key, KeyConfigPrefsFactory(), mTimer, ProjectManager::New(), ParseCommandLine(), FileNames::PreferenceKey(), project, QuitAudacity(), audacity::BasicSettings::Read(), Setting< T >::Read(), MenuCreator::RebuildAllMenuBars(), anonymous_namespace{CompareAudioCommand.cpp}::reg, URLSchemesRegistry::RegisterScheme(), MenuCreator::RemoveDuplicateShortcuts(), RunBenchmark(), SafeMRUOpen(), safenew, anonymous_namespace{wxCommandTargets.cpp}::scope, Journal::SetInputFileName(), Sequence::SetMaxDiskBlockSize(), WhatsNewDialog::Show(), ShowAutoRecoveryDialogIfNeeded(), PrefsDialog::ShowModal(), ShowSplashScreen(), SkipEffectsScanAtStartup, UpdateManager::Start(), Startup, audacity::BasicSettings::Write(), and wxT().

Referenced by OnInit().

Here is the caller graph for this function:

◆ InitTempDir()

bool AudacityApp::InitTempDir ( )
private

Definition at line 1903 of file AudacityApp.cpp.

1904{
1905 // We need to find a temp directory location.
1906 auto tempFromPrefs = TempDirectory::TempDir();
1907 auto tempDefaultLoc = TempDirectory::DefaultTempDir();
1908
1909 wxString temp;
1910
1911 #ifdef __WXGTK__
1912 if (tempFromPrefs.length() > 0 && tempFromPrefs[0] != wxT('/'))
1913 tempFromPrefs = wxT("");
1914 #endif
1915
1916 // Stop wxWidgets from printing its own error messages
1917
1918 wxLogNull logNo;
1919
1920 // Try temp dir that was stored in prefs first
1921 if( TempDirectory::IsTempDirectoryNameOK( tempFromPrefs ) )
1922 SetToExtantDirectory( temp, tempFromPrefs );
1923
1924 // If that didn't work, try the default location
1925
1926 if (temp.empty())
1927 SetToExtantDirectory( temp, tempDefaultLoc );
1928
1929 // Check temp directory ownership on *nix systems only
1930 #ifdef __UNIX__
1931 struct stat tempStatBuf;
1932 if ( lstat(temp.mb_str(), &tempStatBuf) != 0 ) {
1933 temp.clear();
1934 }
1935 else {
1936 if ( geteuid() != tempStatBuf.st_uid ) {
1937 temp.clear();
1938 }
1939 }
1940 #endif
1941
1942 if (temp.empty()) {
1943 // Failed
1944 if( !TempDirectory::IsTempDirectoryNameOK( tempFromPrefs ) ) {
1946"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."));
1947 } else {
1949"Audacity could not find a place to store temporary files.\nPlease enter an appropriate directory in the preferences dialog."));
1950 }
1951
1952 // Only want one page of the preferences
1953 PrefsPanel::Factories factories;
1954 factories.push_back(DirectoriesPrefsFactory());
1955 GlobalPrefsDialog dialog(nullptr, nullptr, factories);
1956 dialog.ShowModal();
1957
1959"Audacity is now going to exit. Please launch Audacity again to use the new temporary directory."));
1960 return false;
1961 }
1962
1963 // The permissions don't always seem to be set on
1964 // some platforms. Hopefully this fixes it...
1965 #ifdef __UNIX__
1966 chmod(OSFILENAME(temp), 0700);
1967 #endif
1968
1970 FileNames::UpdateDefaultPath(FileNames::Operation::Temp, temp);
1971
1972 return true;
1973}
void SetToExtantDirectory(wxString &result, const wxString &dir)
PrefsPanel::Factory DirectoriesPrefsFactory()
#define OSFILENAME(X)
FILES_API void UpdateDefaultPath(Operation op, const FilePath &path)
FILES_API bool IsTempDirectoryNameOK(const FilePath &Name)
FILES_API wxString TempDir()
FILES_API void ResetTempDir()
FILES_API const FilePath & DefaultTempDir()

References AudacityMessageBox(), TempDirectory::DefaultTempDir(), DirectoriesPrefsFactory(), TempDirectory::IsTempDirectoryNameOK(), OSFILENAME, TempDirectory::ResetTempDir(), SetToExtantDirectory(), PrefsDialog::ShowModal(), TempDirectory::TempDir(), FileNames::UpdateDefaultPath(), wxT(), and XO().

Referenced by OnInit().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ MacActivateApp()

void AudacityApp::MacActivateApp ( )

◆ MacFinishLaunching()

void AudacityApp::MacFinishLaunching ( )

Referenced by OnInit().

Here is the caller graph for this function:

◆ MacNewFile()

void AudacityApp::MacNewFile ( )
override

Definition at line 963 of file AudacityApp.cpp.

964{
965 if (!gInited)
966 return;
967
968 // This method should only be used on the Mac platform
969 // when no project windows are open.
970
971 if (AllProjects{}.empty())
972 (void) ProjectManager::New();
973}
bool empty() const
Definition: Project.h:47

References AllProjects::empty(), gInited, and ProjectManager::New().

Here is the call graph for this function:

◆ MacOpenFile()

void AudacityApp::MacOpenFile ( const wxString &  fileName)
override

Definition at line 951 of file AudacityApp.cpp.

952{
953 ofqueue.push_back(fileName);
954}
static wxArrayString ofqueue

References ofqueue.

◆ MacPrintFile()

void AudacityApp::MacPrintFile ( const wxString &  fileName)
override

Definition at line 957 of file AudacityApp.cpp.

958{
959 ofqueue.push_back(fileName);
960}

References ofqueue.

◆ MRUOpen()

bool AudacityApp::MRUOpen ( const FilePath fileName)

Referenced by OnMRUFile(), and SafeMRUOpen().

Here is the caller graph for this function:

◆ OnEndSession()

void AudacityApp::OnEndSession ( wxCloseEvent &  event)

Definition at line 2489 of file AudacityApp.cpp.

2490{
2491 bool force = !event.CanVeto();
2492
2493 // Try to close each open window. If the user hits Cancel
2494 // in a Save Changes dialog, don't continue.
2495 gIsQuitting = true;
2496 if (AllProjects{}.size())
2497 // PRL: Always did at least once before close might be vetoed
2498 // though I don't know why that is important
2500 bool closedAll = CloseAllProjects( force );
2501 if ( !closedAll )
2502 {
2503 gIsQuitting = false;
2504 event.Veto();
2505 }
2506}
static bool gIsQuitting
static bool CloseAllProjects(bool force)
size_t size() const
Definition: Project.cpp:17
static void SaveWindowSize()

References CloseAllProjects(), gIsQuitting, ProjectManager::SaveWindowSize(), and AllProjects::size().

Referenced by OnQueryEndSession().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ OnExceptionInMainLoop()

bool AudacityApp::OnExceptionInMainLoop ( )
override

Definition at line 1188 of file AudacityApp.cpp.

1189{
1190 // This function is invoked from catch blocks in the wxWidgets framework,
1191 // and throw; without argument re-throws the exception being handled,
1192 // letting us dispatch according to its type.
1193
1194 try { throw; }
1195 catch ( AudacityException &e ) {
1196 (void)e;// Compiler food
1197 // Here is the catch-all for our own exceptions
1198
1199 // Use CallAfter to delay this to the next pass of the event loop,
1200 // rather than risk doing it inside stack unwinding.
1201 auto pProject = ::GetActiveProject().lock();
1202 auto pException = std::current_exception();
1203 CallAfter( [pException, pProject] {
1204
1205 // Restore the state of the project to what it was before the
1206 // failed operation
1207 if (pProject) {
1208 ProjectHistory::Get( *pProject ).RollbackState();
1209
1210 // Forget pending changes in the TrackList
1212 Viewport::Get(*pProject).Redraw();
1213 }
1214
1215 // Give the user an alert
1216 try { std::rethrow_exception( pException ); }
1217 catch( AudacityException &e )
1218 { e.DelayedHandlerAction(); }
1219
1220 } );
1221
1222 // Don't quit the program
1223 return true;
1224 }
1225 catch ( ... ) {
1226 // There was some other type of exception we don't know.
1227 // Let the inherited function do throw; again and whatever else it does.
1228 return wxApp::OnExceptionInMainLoop();
1229 }
1230 // Shouldn't ever reach this line
1231 return false;
1232}
Base class for exceptions specially processed by the application.
virtual void DelayedHandlerAction()=0
Action to do in the main thread at idle time of the event loop.
static PendingTracks & Get(AudacityProject &project)
void ClearPendingTracks(std::vector< std::shared_ptr< Track > > *pAdded=nullptr)
Forget pending track additions and changes;.
static ProjectHistory & Get(AudacityProject &project)
void Redraw()
Definition: Viewport.cpp:753
static Viewport & Get(AudacityProject &project)
Definition: Viewport.cpp:33

References BasicUI::CallAfter(), PendingTracks::ClearPendingTracks(), AudacityException::DelayedHandlerAction(), ProjectHistory::Get(), PendingTracks::Get(), Viewport::Get(), GetActiveProject(), Viewport::Redraw(), and ProjectHistory::RollbackState().

Referenced by OnIdle().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ OnExit()

int AudacityApp::OnExit ( void  )
override

Definition at line 2508 of file AudacityApp.cpp.

2509{
2510 gIsQuitting = true;
2511 while(Pending())
2512 {
2513 Dispatch();
2514 }
2515
2517
2519
2520 if(gPrefs)
2521 {
2522 bool bFalse = false;
2523 //Should we change the commands.cfg location next startup?
2524 if(gPrefs->Read(wxT("/QDeleteCmdCfgLocation"), &bFalse))
2525 {
2526 gPrefs->DeleteEntry(wxT("/QDeleteCmdCfgLocation"));
2527 gPrefs->Write(wxT("/DeleteCmdCfgLocation"), true);
2528 gPrefs->Flush();
2529 }
2530 }
2531
2533
2535
2536 DeinitFFT();
2537
2538#ifdef HAS_NETWORKING
2540#endif
2541
2543
2544 // Terminate the PluginManager (must be done before deleting the locale)
2546
2547 return 0;
2548}
void DeinitFFT()
Definition: FFT.cpp:112
static void Deinit()
Definition: AudioIO.cpp:218
void Save(audacity::BasicSettings &config)
bool Terminate()
Definition: Import.cpp:201
bool DeleteEntry(const wxString &key)
Deletes specified entry if exists.
auto Dispatch(Head_t< Types > &object, const TupleLike &functions, Args &&... args) -> std::enable_if_t< TypeListCheck_v< Types >, R >
Definition: TypeSwitch.h:313

References AudioIO::Deinit(), DeinitFFT(), audacity::BasicSettings::DeleteEntry(), TypeSwitch::Dispatch(), FinishPreferences(), audacity::BasicSettings::Flush(), Importer::Get(), PluginManager::Get(), audacity::network_manager::NetworkManager::GetInstance(), gIsQuitting, FileHistory::Global(), gPrefs, AppEvents::ProviderBase::HandleAppClosing(), audacity::BasicSettings::Read(), FileHistory::Save(), Importer::Terminate(), PluginManager::Terminate(), audacity::network_manager::NetworkManager::Terminate(), audacity::BasicSettings::Write(), and wxT().

Here is the call graph for this function:

◆ OnFatalException()

void AudacityApp::OnFatalException ( )
override

Definition at line 1172 of file AudacityApp.cpp.

1173{
1174#if defined(HAS_CRASH_REPORT)
1175 CrashReport::Generate(wxDebugReport::Context_Exception);
1176#endif
1177
1178 exit(-1);
1179}

◆ OnIdle()

void AudacityApp::OnIdle ( wxIdleEvent &  evt)

Definition at line 1831 of file AudacityApp.cpp.

1832{
1833 evt.Skip();
1834 try {
1835 HandleAppIdle();
1836
1837 if ( Journal::Dispatch() )
1838 evt.RequestMore();
1839 }
1840 catch( ... ) {
1841 // Hmm, wxWidgets doesn't guard calls to the idle handler as for other
1842 // events. So replicate some of the try-catch logic here.
1844 // Fall through and return, allowing delayed handler action of
1845 // AudacityException to clean up
1846 }
1847}
bool OnExceptionInMainLoop() override
bool Dispatch()
Definition: Journal.cpp:291

References Journal::Dispatch(), AppEvents::ProviderBase::HandleAppIdle(), and OnExceptionInMainLoop().

Here is the call graph for this function:

◆ OnInit()

bool AudacityApp::OnInit ( )
override

Definition at line 1442 of file AudacityApp.cpp.

1443{
1445
1446 // JKC: ANSWER-ME: Who actually added the event loop guarantor?
1447 // Although 'blame' says Leland, I think it came from a donated patch.
1448
1449 // PRL: It was added by LL at 54676a72285ba7ee3a69920e91fa390a71ef10c9 :
1450 // " Ensure OnInit() has an event loop
1451 // And allow events to flow so the splash window updates under GTK"
1452 // then mistakenly lost in the merge at
1453 // 37168ebbf67ae869ab71a3b5cbbf1d2a48e824aa
1454 // then restored at 7687972aa4b2199f0717165235f3ef68ade71e08
1455
1456 // Ensure we have an event loop during initialization
1457 wxEventLoopGuarantor eventLoop;
1458
1459 OnInit0();
1460
1462
1463 // Define languages for which we have translations, but that are not yet
1464 // supported by wxWidgets.
1465 //
1466 // TODO: The whole Language initialization really need to be reworked.
1467 // It's all over the place.
1468#if wxCHECK_VERSION(3, 0, 1) && !wxCHECK_VERSION(3, 1, 6)
1469 for (size_t i = 0, cnt = WXSIZEOF(userLangs); i < cnt; i++)
1470 {
1471 wxLocale::AddLanguage(userLangs[i]);
1472 }
1473#endif
1474
1475 // Initialize preferences and language
1476 {
1479 }
1480
1482
1483 {
1484 wxBusyCursor busy;
1486 }
1487
1488 // AColor depends on theTheme.
1489 AColor::Init();
1490
1491 // If this fails, we must exit the program.
1492 if (!InitTempDir()) {
1494 return false;
1495 }
1496
1498
1499#ifdef __WXMAC__
1500 // Bug2437: When files are opened from Finder and another instance of
1501 // Audacity is running, we must return from OnInit() to wxWidgets before
1502 // MacOpenFile is called, informing us of the paths that need to be
1503 // opened. So use CallAfter() to delay the rest of initialization.
1504 // See CreateSingleInstanceChecker() where we send those paths over a
1505 // socket to the prior instance.
1506
1507 // This call is what probably makes the sleep unnecessary:
1509
1510 using namespace std::chrono;
1511 // This sleep may be unnecessary, but it is harmless. It less NS framework
1512 // events arrive on another thread, but it might not always be long enough.
1513 std::this_thread::sleep_for(100ms);
1514 CallAfter([this]{
1515 if (!InitPart2())
1516 exit(-1);
1517 });
1518 return true;
1519#else
1520 return InitPart2();
1521#endif
1522}
void InitPreferences(std::unique_ptr< audacity::BasicSettings > uPrefs)
Definition: Prefs.cpp:231
void RegisterBuiltinEffects()
THEME_API Theme theTheme
Definition: Theme.cpp:82
static void Init()
Definition: AColor.cpp:531
bool InitPart2()
void MacFinishLaunching()
Observer::Subscription mThemeChangeSubscription
Definition: AudacityApp.h:116
bool InitTempDir()
static void OnThemeChange(struct ThemeChangeMessage)
static result_type Call(Arguments &&...arguments)
Null check of the installed function is done for you.
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
Definition: Observer.h:199
static bool LoadPreferredTheme()
Definition: Theme.cpp:162
FILES_API void InitializePathList()
THEME_RESOURCES_API void Load()

References GlobalHook< ApplicationSettings, std::unique_ptr< BasicSettings >()>::Call(), BasicUI::CallAfter(), FinishPreferences(), AColor::Init(), FileNames::InitializePathList(), InitPart2(), InitPreferences(), InitTempDir(), ThemeResources::Load(), ThemeBase::LoadPreferredTheme(), MacFinishLaunching(), mThemeChangeSubscription, OnInit0(), OnThemeChange(), anonymous_namespace{AudacityApp.cpp}::PopulatePreferences(), RegisterBuiltinEffects(), Observer::Publisher< Message, NotifyAll >::Subscribe(), and theTheme.

Here is the call graph for this function:

◆ OnInit0()

void AudacityApp::OnInit0 ( )
private

Definition at line 1361 of file AudacityApp.cpp.

1362{
1363 // Inject basic GUI services behind the facades
1364 {
1365 static wxWidgetsBasicUI uiServices;
1366 (void)BasicUI::Install(&uiServices);
1367
1370 -> std::unique_ptr<BasicUI::WindowPlacement> {
1371 return std::make_unique<wxWidgetsWindowPlacement>(
1373 } };
1374 }
1375
1376 // Fire up SQLite
1378 this->CallAfter([]{
1380 XO("SQLite library failed to initialize. Audacity cannot continue.") );
1381 QuitAudacity( true );
1382 });
1383
1384
1385 // cause initialization of wxWidgets' global logger target
1386 (void) AudacityLogger::Get();
1387
1388#if defined(__WXMAC__)
1389 // Disable window animation
1390 wxSystemOptions::SetOption(wxMAC_WINDOW_PLAIN_TRANSITION, 1);
1391#endif
1392
1393 // Some GTK themes produce larger combo boxes that make them taller
1394 // than our single toolbar height restriction. This will remove some
1395 // of the extra space themes add.
1396#if defined(__WXGTK3__) && defined(HAVE_GTK)
1397 GtkWidget *combo = gtk_combo_box_new();
1398 GtkCssProvider *provider = gtk_css_provider_new();
1399 gtk_css_provider_load_from_data(GTK_CSS_PROVIDER(provider),
1400 ".linked entry,\n"
1401 ".linked button,\n"
1402 ".linked combobox box.linked button,\n"
1403 ".horizontal.linked entry,\n"
1404 ".horizontal.linked button,\n"
1405 ".horizontal.linked combobox box.linked button,\n"
1406 "combobox {\n"
1407 " padding-top: 0px;\n"
1408 " padding-bottom: 0px;\n"
1409 " padding-left: 4px;\n"
1410 " padding-right: 4px;\n"
1411 " margin: 0px;\n"
1412 " font-size: 95%;\n"
1413 "}", -1, NULL);
1414 gtk_style_context_add_provider_for_screen(gtk_widget_get_screen(combo),
1415 GTK_STYLE_PROVIDER (provider),
1416 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
1417 g_object_unref(provider);
1418 g_object_unref(combo);
1419#elif defined(__WXGTK__) && defined(HAVE_GTK)
1420 gtk_rc_parse_string("style \"audacity\" {\n"
1421 " GtkButton::inner_border = { 0, 0, 0, 0 }\n"
1422 " GtkEntry::inner_border = { 0, 0, 0, 0 }\n"
1423 " xthickness = 4\n"
1424 " ythickness = 0\n"
1425 "}\n"
1426 "widget_class \"*GtkCombo*\" style \"audacity\"");
1427#endif
1428
1429 wxTheApp->SetAppName(AppName);
1430 // Explicitly set since OSX will use it for the "Quit" menu item
1431 wxTheApp->SetAppDisplayName(AppName);
1432 wxTheApp->SetVendorName(AppName);
1433
1434 ::wxInitAllImageHandlers();
1435
1436 // AddHandler takes ownership
1437 wxFileSystem::AddHandler(safenew wxZipFSHandler);
1438}
const std::wstring AppName
This program's name.
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
static AudacityLogger * Get()
static bool InitializeSQL()
An implementation of BasicUI::Services in terms of the wxWidgets toolkit.
Services * Install(Services *pInstance)
Install an implementation; return the previously installed instance.
Definition: BasicUI.cpp:204

References AppName, AudacityMessageBox(), BasicUI::CallAfter(), AudacityLogger::Get(), GetProjectFrame(), ProjectFileIO::InitializeSQL(), BasicUI::Install(), project, QuitAudacity(), safenew, anonymous_namespace{wxCommandTargets.cpp}::scope, and XO().

Referenced by OnInit().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ OnKeyDown()

void AudacityApp::OnKeyDown ( wxKeyEvent &  event)

Definition at line 1862 of file AudacityApp.cpp.

1863{
1864 if(event.GetKeyCode() == WXK_ESCAPE) {
1865 // Stop play, including scrub, but not record
1866 if ( auto project = ::GetActiveProject().lock() ) {
1867 auto token = ProjectAudioIO::Get( *project ).GetAudioIOToken();
1868 auto &scrubber = Scrubber::Get( *project );
1869 auto scrubbing = scrubber.HasMark();
1870 if (scrubbing)
1871 scrubber.Cancel();
1872 auto gAudioIO = AudioIO::Get();
1873 if((token > 0 &&
1874 gAudioIO->IsAudioTokenActive(token) &&
1875 gAudioIO->GetNumCaptureChannels() == 0) ||
1876 scrubbing)
1877 // ESC out of other play (but not record)
1878 ProjectAudioManager::Get( *project ).Stop();
1879 else
1880 event.Skip();
1881 }
1882 }
1883
1884 event.Skip();
1885}
static AudioIO * Get()
Definition: AudioIO.cpp:126
int GetAudioIOToken() const
static ProjectAudioIO & Get(AudacityProject &project)
void Stop(bool stopStream=true)
static ProjectAudioManager & Get(AudacityProject &project)
static Scrubber & Get(AudacityProject &project)
Definition: Scrubbing.cpp:186

References AudioIO::Get(), ProjectAudioIO::Get(), ProjectAudioManager::Get(), Scrubber::Get(), GetActiveProject(), ProjectAudioIO::GetAudioIOToken(), project, and ProjectAudioManager::Stop().

Here is the call graph for this function:

◆ OnMenuAbout()

void AudacityApp::OnMenuAbout ( wxCommandEvent &  event)

Definition at line 2560 of file AudacityApp.cpp.

2561{
2562 // This function shadows a similar function
2563 // in Menus.cpp, but should only be used on the Mac platform.
2564#ifdef __WXMAC__
2565 // Modeless dialog, consistent with other Mac applications
2566 // Not more than one at once!
2567 const auto instance = AboutDialog::ActiveIntance();
2568 if (instance)
2569 instance->Raise();
2570 else
2571 // This dialog deletes itself when dismissed
2572 (safenew AboutDialog{ nullptr })->Show(true);
2573#else
2574 wxASSERT(false);
2575#endif
2576}
The AboutDialog shows the program version and developer credits.
Definition: AboutDialog.h:32
static AboutDialog * ActiveIntance()
IMPORT_EXPORT_API ExportResult Show(ExportTask exportTask)

References AboutDialog::ActiveIntance(), safenew, and ExportProgressUI::Show().

Here is the call graph for this function:

◆ OnMenuExit()

void AudacityApp::OnMenuExit ( wxCommandEvent &  event)

Definition at line 2627 of file AudacityApp.cpp.

2628{
2629 // This function shadows a similar function
2630 // in Menus.cpp, but should only be used on the Mac platform
2631 // when no project windows are open. This check assures that
2632 // this happens, and enable the same code to be present on
2633 // all platforms.
2634
2635 // LL: Removed "if" to allow closing based on final project count.
2636 // if(AllProjects{}.empty())
2637 QuitAudacity();
2638
2639 // LL: Veto quit if projects are still open. This can happen
2640 // if the user selected Cancel in a Save dialog.
2641 event.Skip(AllProjects{}.empty());
2642
2643}

References AllProjects::empty(), and QuitAudacity().

Here is the call graph for this function:

◆ OnMenuNew()

void AudacityApp::OnMenuNew ( wxCommandEvent &  event)

Definition at line 2578 of file AudacityApp.cpp.

2579{
2580 // This function shadows a similar function
2581 // in Menus.cpp, but should only be used on the Mac platform
2582 // when no project windows are open. This check assures that
2583 // this happens, and enable the same code to be present on
2584 // all platforms.
2585
2586 if(AllProjects{}.empty())
2587 (void) ProjectManager::New();
2588 else
2589 event.Skip();
2590}

References AllProjects::empty(), and ProjectManager::New().

Here is the call graph for this function:

◆ OnMenuOpen()

void AudacityApp::OnMenuOpen ( wxCommandEvent &  event)

Definition at line 2593 of file AudacityApp.cpp.

2594{
2595 // This function shadows a similar function
2596 // in Menus.cpp, but should only be used on the Mac platform
2597 // when no project windows are open. This check assures that
2598 // this happens, and enable the same code to be present on
2599 // all platforms.
2600
2601
2602 if(AllProjects{}.empty())
2604 else
2605 event.Skip();
2606
2607
2608}
static void OpenFiles(AudacityProject *proj)

References AllProjects::empty(), and ProjectManager::OpenFiles().

Here is the call graph for this function:

◆ OnMenuPreferences()

void AudacityApp::OnMenuPreferences ( wxCommandEvent &  event)

Definition at line 2610 of file AudacityApp.cpp.

2611{
2612 // This function shadows a similar function
2613 // in Menus.cpp, but should only be used on the Mac platform
2614 // when no project windows are open. This check assures that
2615 // this happens, and enable the same code to be present on
2616 // all platforms.
2617
2618 if(AllProjects{}.empty()) {
2619 GlobalPrefsDialog dialog(nullptr /* parent */, nullptr );
2620 dialog.ShowModal();
2621 }
2622 else
2623 event.Skip();
2624
2625}

References AllProjects::empty(), and PrefsDialog::ShowModal().

Here is the call graph for this function:

◆ OnMRUClear()

void AudacityApp::OnMRUClear ( wxCommandEvent &  event)

Definition at line 1075 of file AudacityApp.cpp.

1076{
1078}
void Clear()
Definition: FileHistory.cpp:92

References FileHistory::Clear(), and FileHistory::Global().

Here is the call graph for this function:

◆ OnMRUFile()

void AudacityApp::OnMRUFile ( wxCommandEvent &  event)

Definition at line 1083 of file AudacityApp.cpp.

1083 {
1084 int n = event.GetId() - FileHistory::ID_RECENT_FIRST;
1085 auto &history = FileHistory::Global();
1086 const auto &fullPathStr = history[ n ];
1087
1088 // Try to open only if not already open.
1089 // Test IsAlreadyOpen() here even though AudacityProject::MRUOpen() also now checks,
1090 // because we don't want to Remove() just because it already exists,
1091 // and AudacityApp::OnMacOpenFile() calls MRUOpen() directly.
1092 // that method does not return the bad result.
1093 // PRL: Don't call SafeMRUOpen
1094 // -- if open fails for some exceptional reason of resource exhaustion that
1095 // the user can correct, leave the file in history.
1096 if (!ProjectFileManager::IsAlreadyOpen(fullPathStr) && !MRUOpen(fullPathStr))
1097 history.Remove(n);
1098}
bool MRUOpen(const FilePath &fileName)
static bool IsAlreadyOpen(const FilePath &projPathName)

References FileHistory::Global(), FileHistory::ID_RECENT_FIRST, ProjectFileManager::IsAlreadyOpen(), and MRUOpen().

Here is the call graph for this function:

◆ OnQueryEndSession()

void AudacityApp::OnQueryEndSession ( wxCloseEvent &  event)

Definition at line 2475 of file AudacityApp.cpp.

2476{
2477 bool mustVeto = false;
2478
2479#ifdef __WXMAC__
2480 mustVeto = wxDialog::OSXHasModalDialogsOpen();
2481#endif
2482
2483 if ( mustVeto )
2484 event.Veto(true);
2485 else
2486 OnEndSession(event);
2487}
void OnEndSession(wxCloseEvent &event)

References OnEndSession().

Here is the call graph for this function:

◆ OnReceiveCommand()

void AudacityApp::OnReceiveCommand ( AppCommandEvent event)

Definition at line 1856 of file AudacityApp.cpp.

1857{
1858 wxASSERT(NULL != mCmdHandler);
1859 mCmdHandler->OnReceiveCommand(event);
1860}

References mCmdHandler.

◆ OnRun()

int AudacityApp::OnRun ( )
override

Definition at line 1821 of file AudacityApp.cpp.

1822{
1823 // Returns 0 to the command line if the run completed normally
1824 auto result = wxApp::OnRun();
1825 if (result == 0)
1826 // If not otherwise abnormal, report any journal sync failure
1827 result = Journal::GetExitCode();
1828 return result;
1829}
int GetExitCode()
Definition: Journal.cpp:386

References Journal::GetExitCode().

Here is the call graph for this function:

◆ OnServerEvent()

void AudacityApp::OnServerEvent ( wxSocketEvent &  evt)

◆ OnSocketEvent()

void AudacityApp::OnSocketEvent ( wxSocketEvent &  evt)

◆ OnThemeChange()

static void AudacityApp::OnThemeChange ( struct ThemeChangeMessage  )
static

Referenced by OnInit().

Here is the caller graph for this function:

◆ OnTimer()

void AudacityApp::OnTimer ( wxTimerEvent &  event)

Definition at line 1100 of file AudacityApp.cpp.

1101{
1102 // Filenames are queued when Audacity receives a few of the
1103 // AppleEvent messages (via wxWidgets). So, open any that are
1104 // in the queue and clean the queue.
1105 if (gInited) {
1106 if (ofqueue.size()) {
1107 // Load each file on the queue
1108 while (ofqueue.size()) {
1109 wxString name;
1110 name.swap(ofqueue[0]);
1111 ofqueue.erase( ofqueue.begin() );
1112
1113 // Get the user's attention if no file name was specified
1114 if (name.empty()) {
1115 // Get the users attention
1116 if (auto project = GetActiveProject().lock()) {
1117 auto &window = GetProjectFrame( *project );
1118 window.Maximize();
1119 window.Raise();
1120 window.RequestUserAttention();
1121 }
1122 continue;
1123 }
1124
1125 #ifdef HAS_CUSTOM_URL_HANDLING
1126 if (name.StartsWith(urlPrefix))
1127 {
1128 const auto utf8Url = name.ToUTF8();
1129 const size_t prefixSize = urlPrefix.Length();
1130
1131 if (utf8Url.length() <= prefixSize)
1132 continue;
1133
1135 { utf8Url.data() + prefixSize,
1136 utf8Url.length() - prefixSize });
1137 }
1138 else
1139 #endif
1140 // TODO: Handle failures better.
1141 // Some failures are OK, e.g. file not found, just would-be-nices to do better,
1142 // so FAIL_MSG is more a case of an enhancement request than an actual problem.
1143 // LL: In all but one case an appropriate message is already displayed. The
1144 // instance that a message is NOT displayed is when a failure to write
1145 // to the config file has occurred.
1146 // PRL: Catch any exceptions, don't try this file again, continue to
1147 // other files.
1148 if (!SafeMRUOpen(name)) {
1149 // Just log it. Assertion failure is not appropriate on valid
1150 // defensive path against bad file data.
1151 wxLogMessage(wxT("MRUOpen failed"));
1152 }
1153 }
1154 }
1155 }
1156}

References URLSchemesRegistry::Get(), GetActiveProject(), GetProjectFrame(), gInited, URLSchemesRegistry::HandleURL(), name, ofqueue, project, SafeMRUOpen(), audacity::cloud::audiocom::anonymous_namespace{OAuthService.cpp}::urlPrefix, and wxT().

Here is the call graph for this function:

◆ OSXIsGUIApplication()

bool AudacityApp::OSXIsGUIApplication ( )
override

Definition at line 1261 of file AudacityApp.cpp.

1262{
1263 return sOSXIsGUIApplication;
1264}

References IMPLEMENT_WX_THEME_SUPPORT::sOSXIsGUIApplication.

◆ ParseCommandLine()

std::unique_ptr< wxCmdLineParser > AudacityApp::ParseCommandLine ( )
private

Definition at line 2426 of file AudacityApp.cpp.

2427{
2428 auto parser = std::make_unique<wxCmdLineParser>(argc, argv);
2429 if (!parser)
2430 {
2431 return nullptr;
2432 }
2433
2434 /*i18n-hint: This controls the number of bytes that Audacity will
2435 * use when writing files to the disk */
2436 parser->AddOption(wxT("b"), wxT("blocksize"), _("set max disk block size in bytes"),
2437 wxCMD_LINE_VAL_NUMBER);
2438
2439 const auto journalOptionDescription =
2440 /*i18n-hint: brief help message for Audacity's command-line options
2441 A journal contains a sequence of user interface interactions to be repeated
2442 "log," "trail," "trace" have somewhat similar meanings */
2443 _("replay a journal file");
2444
2445 parser->AddOption(wxT("j"), wxT("journal"), journalOptionDescription);
2446
2447 /*i18n-hint: This displays a list of available options */
2448 parser->AddSwitch(wxT("h"), wxT("help"), _("this help message"),
2449 wxCMD_LINE_OPTION_HELP);
2450
2451 /*i18n-hint: This runs a set of automatic tests on Audacity itself */
2452 parser->AddSwitch(wxT("t"), wxT("test"), _("run self diagnostics"));
2453
2454 /*i18n-hint: This displays the Audacity version */
2455 parser->AddSwitch(wxT("v"), wxT("version"), _("display Audacity version"));
2456
2457 /*i18n-hint: This is a list of one or more files that Audacity
2458 * should open upon startup */
2459 parser->AddParam(_("audio or project file name"),
2460 wxCMD_LINE_VAL_STRING,
2461 wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL);
2462
2463#ifdef HAS_CUSTOM_URL_HANDLING
2464 /* i18n-hint: This option is used to handle custom URLs in Audacity */
2465 parser->AddOption(wxT("u"), wxT("url"), _("Handle 'audacity://' url"));
2466#endif
2467
2468 // Run the parser
2469 if (parser->Parse() == 0)
2470 return parser;
2471
2472 return{};
2473}

References _, CommandLineArgs::argc, CommandLineArgs::argv, and wxT().

Referenced by CreateSingleInstanceChecker(), and InitPart2().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SafeMRUOpen()

bool AudacityApp::SafeMRUOpen ( const wxString &  fileName)

Definition at line 1070 of file AudacityApp.cpp.

1071{
1072 return GuardedCall< bool >( [&]{ return MRUOpen( fullPathStr ); } );
1073}

References MRUOpen().

Referenced by InitPart2(), and OnTimer().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ShowSplashScreen()

void AudacityApp::ShowSplashScreen ( )
private

Definition at line 1271 of file AudacityApp.cpp.

1271 {
1272 // Bug 718: Position splash screen on same screen
1273 // as where Audacity project will appear.
1274 wxRect wndRect;
1275 bool bMaximized = false;
1276 bool bIconized = false;
1277 GetNextWindowPlacement(&wndRect, &bMaximized, &bIconized);
1278
1279 // BG: Create a temporary window to set as the top window
1280 wxImage logoimage((const char**)Audacity_splash_xpm);
1281 logoimage.Scale(logoimage.GetWidth() * (2.0 / 3.0), logoimage.GetHeight() * (2.0 / 3.0), wxIMAGE_QUALITY_HIGH);
1282 if (GetLayoutDirection() == wxLayout_RightToLeft)
1283 logoimage = logoimage.Mirror();
1284 wxBitmap logo(logoimage);
1285
1286 mSplashScreen = std::make_unique<wxSplashScreen>(
1287 logo,
1288 wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_NO_TIMEOUT,
1289 0,
1290 nullptr,
1291 wxID_ANY,
1292 wndRect.GetTopLeft(),
1293 wxDefaultSize,
1294 wxSTAY_ON_TOP);
1295
1296 // If the user interacts with another top level window while the splash screen is visible
1297 // it gets destroyed automatically, need to hanlde that to prevent the fade out of deleted object
1298 mSplashScreen->Bind(wxEVT_DESTROY, [this](wxWindowDestroyEvent& event) {
1299 mSplashScreen.release();
1300 event.Skip();
1301 }
1302 );
1303
1304 // Unfortunately with the Windows 10 Creators update, the splash screen
1305 // now appears before setting its position.
1306 // On a dual monitor screen it will appear on one screen and then
1307 // possibly jump to the second.
1308 // We could fix this by writing our own splash screen and using Hide()
1309 // until the splash scren was correctly positioned, then Show()
1310
1311 // Possibly move it on to the second screen...
1312 mSplashScreen->SetPosition(wndRect.GetTopLeft());
1313 // Centered on whichever screen it is on.
1314 mSplashScreen->Center();
1315 mSplashScreen->SetTitle(_("Audacity is starting up..."));
1316 SetTopWindow(mSplashScreen.get());
1317 mSplashScreen->Raise();
1318}
wxImage(22, 22)
void GetNextWindowPlacement(wxRect *nextRect, bool *pMaximized, bool *pIconized)

References _, GetNextWindowPlacement(), mSplashScreen, and wxImage().

Referenced by InitPart2().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ mChecker

std::unique_ptr<wxSingleInstanceChecker> AudacityApp::mChecker
private

Definition at line 120 of file AudacityApp.h.

Referenced by CreateSingleInstanceChecker().

◆ mCmdHandler

std::unique_ptr<CommandHandler> AudacityApp::mCmdHandler
private

Definition at line 118 of file AudacityApp.h.

Referenced by InitCommandHandler(), and OnReceiveCommand().

◆ mIPCServ

std::unique_ptr<IPCServ> AudacityApp::mIPCServ
private

Definition at line 136 of file AudacityApp.h.

Referenced by CreateSingleInstanceChecker().

◆ mSplashScreen

std::unique_ptr<wxSplashScreen> AudacityApp::mSplashScreen
private

Definition at line 124 of file AudacityApp.h.

Referenced by HideSplashScreen(), and ShowSplashScreen().

◆ mSplashTimer

wxTimer AudacityApp::mSplashTimer
private

Definition at line 123 of file AudacityApp.h.

Referenced by HideSplashScreen().

◆ mThemeChangeSubscription

Observer::Subscription AudacityApp::mThemeChangeSubscription
private

Definition at line 116 of file AudacityApp.h.

Referenced by OnInit().

◆ mTimer

wxTimer AudacityApp::mTimer
private

Definition at line 122 of file AudacityApp.h.

Referenced by InitPart2().


The documentation for this class was generated from the following files: