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)
 
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
 
std::unique_ptr< IPCServmIPCServ
 

Detailed Description

AudacityApp is the 'main' class for Audacity.

It handles initialization and termination by subclassing wxApp.

Definition at line 38 of file AudacityApp.h.

Constructor & Destructor Documentation

◆ AudacityApp()

AudacityApp::AudacityApp ( )

Definition at line 1236 of file AudacityApp.cpp.

1237{
1238}

◆ ~AudacityApp()

AudacityApp::~AudacityApp ( )

Definition at line 1266 of file AudacityApp.cpp.

1267{
1268}

Member Function Documentation

◆ AssociateFileTypes()

void AudacityApp::AssociateFileTypes ( )

Definition at line 2600 of file AudacityApp.cpp.

2601{
2602 // Check pref in case user has already decided against it.
2603 bool bWantAssociateFiles = true;
2604 if (gPrefs->Read(wxT("/WantAssociateFiles"), &bWantAssociateFiles) &&
2605 !bWantAssociateFiles)
2606 {
2607 // User has already decided against it
2608 return;
2609 }
2610
2611 wxRegKey associateFileTypes;
2612
2613 auto IsDefined = [&](const wxString &type)
2614 {
2615 associateFileTypes.SetName(wxString::Format(wxT("HKCR\\%s"), type));
2616 bool bKeyExists = associateFileTypes.Exists();
2617 if (!bKeyExists)
2618 {
2619 // Not at HKEY_CLASSES_ROOT. Try HKEY_CURRENT_USER.
2620 associateFileTypes.SetName(wxString::Format(wxT("HKCU\\Software\\Classes\\%s"), type));
2621 bKeyExists = associateFileTypes.Exists();
2622 }
2623 return bKeyExists;
2624 };
2625
2626 auto DefineType = [&](const wxString &type)
2627 {
2628 wxString root_key = wxT("HKCU\\Software\\Classes\\");
2629
2630 // Start with HKEY_CLASSES_CURRENT_USER.
2631 associateFileTypes.SetName(wxString::Format(wxT("%s%s"), root_key, type));
2632 if (!associateFileTypes.Create(true))
2633 {
2634 // Not at HKEY_CLASSES_CURRENT_USER. Try HKEY_CURRENT_ROOT.
2635 root_key = wxT("HKCR\\");
2636 associateFileTypes.SetName(wxString::Format(wxT("%s%s"), root_key, type));
2637 if (!associateFileTypes.Create(true))
2638 {
2639 // Actually, can't create keys. Empty root_key to flag failure.
2640 root_key.empty();
2641 }
2642 }
2643
2644 if (!root_key.empty())
2645 {
2646 associateFileTypes = wxT("Audacity.Project"); // Finally set value for the key
2647 }
2648
2649 return root_key;
2650 };
2651
2652 // Check for legacy and UP types
2653 if (IsDefined(wxT(".aup3")) && IsDefined(wxT(".aup")) && IsDefined(wxT("Audacity.Project")))
2654 {
2655 // Already defined, so bail
2656 return;
2657 }
2658
2659 // File types are not currently associated.
2660 int wantAssoc =
2662 XO(
2663"Audacity project (.aup3) files are not currently \nassociated with Audacity. \n\nAssociate them, so they open on double-click?"),
2664 XO("Audacity Project Files"),
2665 wxYES_NO | wxICON_QUESTION);
2666
2667 if (wantAssoc == wxNO)
2668 {
2669 // User said no. Set a pref so we don't keep asking.
2670 gPrefs->Write(wxT("/WantAssociateFiles"), false);
2671 gPrefs->Flush();
2672 return;
2673 }
2674
2675 // Show that user wants associations
2676 gPrefs->Write(wxT("/WantAssociateFiles"), true);
2677 gPrefs->Flush();
2678
2679 wxString root_key;
2680
2681 root_key = DefineType(wxT(".aup3"));
2682 if (root_key.empty())
2683 {
2684 //v Warn that we can't set keys. Ask whether to set pref for no retry?
2685 }
2686 else
2687 {
2688 DefineType(wxT(".aup"));
2689
2690 associateFileTypes = wxT("Audacity.Project"); // Finally set value for .AUP key
2691 associateFileTypes.SetName(root_key + wxT("Audacity.Project"));
2692 if (!associateFileTypes.Exists())
2693 {
2694 associateFileTypes.Create(true);
2695 associateFileTypes = wxT("Audacity Project File");
2696 }
2697
2698 associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell"));
2699 if (!associateFileTypes.Exists())
2700 {
2701 associateFileTypes.Create(true);
2702 associateFileTypes = wxT("");
2703 }
2704
2705 associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open"));
2706 if (!associateFileTypes.Exists())
2707 {
2708 associateFileTypes.Create(true);
2709 }
2710
2711 associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open\\command"));
2712 wxString tmpRegAudPath;
2713 if(associateFileTypes.Exists())
2714 {
2715 tmpRegAudPath = associateFileTypes.QueryDefaultValue().Lower();
2716 }
2717
2718 if (!associateFileTypes.Exists() ||
2719 (tmpRegAudPath.Find(wxT("audacity.exe")) >= 0))
2720 {
2721 associateFileTypes.Create(true);
2722 associateFileTypes = (wxString)argv[0] + (wxString)wxT(" \"%1\"");
2723 }
2724
2725#if 0
2726 // These can be use later to support more startup messages
2727 // like maybe "Import into existing project" or some such.
2728 // Leaving here for an example...
2729 associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open\\ddeexec"));
2730 if (!associateFileTypes.Exists())
2731 {
2732 associateFileTypes.Create(true);
2733 associateFileTypes = wxT("%1");
2734 }
2735
2736 associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open\\ddeexec\\Application"));
2737 if (!associateFileTypes.Exists())
2738 {
2739 associateFileTypes.Create(true);
2740 associateFileTypes = IPC_APPL;
2741 }
2742
2743 associateFileTypes.SetName(root_key + wxT("Audacity.Project\\shell\\open\\ddeexec\\Topic"));
2744 if (!associateFileTypes.Exists())
2745 {
2746 associateFileTypes.Create(true);
2747 associateFileTypes = IPC_TOPIC;
2748 }
2749#endif
2750 }
2751}
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 1249 of file AudacityApp.cpp.

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

References gConfig.

◆ CreateSingleInstanceChecker()

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

Definition at line 1919 of file AudacityApp.cpp.

1920{
1921 wxString name = wxString::Format(wxT("audacity-lock-%s"), wxGetUserId());
1922 mChecker.reset();
1923 auto checker = std::make_unique<wxSingleInstanceChecker>();
1924
1925 auto runningTwoCopiesStr = XO("Running two copies of Audacity simultaneously may cause\ndata loss or cause your system to crash.\n\n");
1926
1927 if (!checker->Create(name, dir))
1928 {
1929 // Error initializing the wxSingleInstanceChecker. We don't know
1930 // whether there is another instance running or not.
1931
1932 auto prompt = XO(
1933"Audacity was not able to lock the temporary files directory.\nThis folder may be in use by another copy of Audacity.\n")
1934 + runningTwoCopiesStr
1935 + XO("Do you still want to start Audacity?");
1936 int action = AudacityMessageBox(
1937 prompt,
1938 XO("Error Locking Temporary Folder"),
1939 wxYES_NO | wxICON_EXCLAMATION, NULL);
1940 if (action == wxNO)
1941 return false;
1942 }
1943 else if ( checker->IsAnotherRunning() ) {
1944 // Parse the command line to ensure correct syntax, but
1945 // ignore options other than -v, and only use the filenames, if any.
1946 auto parser = ParseCommandLine();
1947 if (!parser)
1948 {
1949 // Complaints have already been made
1950 return false;
1951 }
1952
1953 if (parser->Found(wxT("v")))
1954 {
1955 wxPrintf("Audacity v%s\n", AUDACITY_VERSION_STRING);
1956 return false;
1957 }
1958
1959 // Windows and Linux require absolute file names as command may
1960 // not come from current working directory.
1961 FilePaths filenames;
1962 for (size_t i = 0, cnt = parser->GetParamCount(); i < cnt; i++)
1963 {
1964 wxFileName filename(parser->GetParam(i));
1965 if (filename.MakeAbsolute())
1966 {
1967 filenames.push_back(filename.GetLongPath());
1968 }
1969 }
1970
1971 #ifdef HAS_CUSTOM_URL_HANDLING
1972 wxString url;
1973 parser->Found("u", &url);
1974 #endif
1975
1976
1977 // On Windows, we attempt to make a connection
1978 // to an already active Audacity. If successful, we send
1979 // the first command line argument (the audio file name)
1980 // to that Audacity for processing.
1981 wxClient client;
1982
1983 // We try up to 50 times since there's a small window
1984 // where the server may not have been fully initialized.
1985 for (int i = 0; i < 50; i++)
1986 {
1987 std::unique_ptr<wxConnectionBase> conn{ client.MakeConnection(wxEmptyString, IPC_APPL, IPC_TOPIC) };
1988 if (conn)
1989 {
1990 bool ok = false;
1991 #ifdef HAS_CUSTOM_URL_HANDLING
1992 if (!url.empty())
1993 {
1994 if (!conn->Execute(urlPrefix + url))
1995 return false;
1996 }
1997 #endif
1998
1999 if (filenames.size() > 0)
2000 {
2001 for (size_t i = 0, cnt = filenames.size(); i < cnt; i++)
2002 {
2003 ok = conn->Execute(filenames[i]);
2004 }
2005 }
2006 else
2007 {
2008 // Send an empty string to force existing Audacity to front
2009 ok = conn->Execute(wxEmptyString);
2010 }
2011
2012 if (ok)
2013 return false;
2014 }
2015
2016 using namespace std::chrono;
2017 std::this_thread::sleep_for(10ms);
2018 }
2019 // There is another copy of Audacity running. Force quit.
2020
2021 auto prompt = XO(
2022"The system has detected that another copy of Audacity is running.\n")
2023 + runningTwoCopiesStr
2024 + XO(
2025"Use the New or Open commands in the currently running Audacity\nprocess to open multiple projects simultaneously.\n");
2027 prompt, XO("Audacity is already running"),
2028 wxOK | wxICON_ERROR);
2029
2030 return false;
2031 }
2032
2033 // Create the DDE IPC server
2034 mIPCServ = std::make_unique<IPCServ>(IPC_APPL);
2035 mChecker = std::move(checker);
2036 return true;
2037}
const TranslatableString name
Definition: Distortion.cpp:76
std::unique_ptr< wxSingleInstanceChecker > mChecker
Definition: AudacityApp.h:119
std::unique_ptr< wxCmdLineParser > ParseCommandLine()
std::unique_ptr< IPCServ > mIPCServ
Definition: AudacityApp.h:131
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.

References AudacityMessageBox(), IPC_APPL, IPC_TOPIC, mChecker, mIPCServ, name, ParseCommandLine(), wxT(), and XO().

Referenced by InitPart2().

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

◆ InitCommandHandler()

void AudacityApp::InitCommandHandler ( )
private

Definition at line 1788 of file AudacityApp.cpp.

1789{
1790 mCmdHandler = std::make_unique<CommandHandler>();
1791 //SetNextHandler(mCmdHandler);
1792}
std::unique_ptr< CommandHandler > mCmdHandler
Definition: AudacityApp.h:117

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 1240 of file AudacityApp.cpp.

1241{
1243 {
1245 }
1246 return wxApp::Initialize(argc, argv);
1247}
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 1432 of file AudacityApp.cpp.

1433{
1434#if defined(__WXMAC__)
1435 SetExitOnFrameDelete(false);
1436#endif
1437
1438 // Make sure the temp dir isn't locked by another process.
1439 {
1440 auto key =
1441 PreferenceKey(FileNames::Operation::Temp, FileNames::PathType::_None);
1442 auto temp = gPrefs->Read(key);
1443 if (temp.empty() || !CreateSingleInstanceChecker(temp)) {
1445 return false;
1446 }
1447 }
1448
1449 //<<<< Try to avoid dialogs before this point.
1450 // The reason is that InitTempDir starts the single instance checker.
1451 // If we're waiitng in a dialog before then we can very easily
1452 // start multiple instances, defeating the single instance checker.
1453
1454 // Initialize the CommandHandler
1456
1457 // Initialize the ModuleManager, including loading found modules
1459
1460 // Initialize the PluginManager
1461 PluginManager::Get().Initialize( [](const FilePath &localFileName){
1462 return std::make_unique<SettingsWX>(
1463 AudacityFileConfig::Create({}, {}, localFileName)
1464 );
1465 });
1466
1467 // Parse command line and handle options that might require
1468 // immediate exit...no need to initialize all of the audio
1469 // stuff to display the version string.
1470 std::shared_ptr< wxCmdLineParser > parser{ ParseCommandLine() };
1471 if (!parser)
1472 {
1473 // Either user requested help or a parsing error occurred
1474 exit(1);
1475 }
1476
1477 wxString journalFileName;
1478 const bool playingJournal = parser->Found("j", &journalFileName);
1479
1480#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) && !defined(__CYGWIN__)
1481 if (!playingJournal)
1482 this->AssociateFileTypes();
1483#endif
1484
1485 if (parser->Found(wxT("v")))
1486 {
1487 wxPrintf("Audacity v%s\n", AUDACITY_VERSION_STRING);
1488 exit(0);
1489 }
1490
1491 long lval;
1492 if (parser->Found(wxT("b"), &lval))
1493 {
1494 if (lval < 256 || lval > 100000000)
1495 {
1496 wxPrintf(_("Block size must be within 256 to 100000000\n"));
1497 exit(1);
1498 }
1499
1501 }
1502
1503 if (playingJournal)
1504 Journal::SetInputFileName( journalFileName );
1505
1506 // BG: Create a temporary window to set as the top window
1507 wxImage logoimage((const char **)Audacity_splash_xpm);
1508 logoimage.Scale(logoimage.GetWidth() * (2.0/3.0), logoimage.GetHeight() * (2.0/3.0), wxIMAGE_QUALITY_HIGH);
1509 if( GetLayoutDirection() == wxLayout_RightToLeft)
1510 logoimage = logoimage.Mirror();
1511 wxBitmap logo(logoimage);
1512
1514 {
1515 // Bug 718: Position splash screen on same screen
1516 // as where Audacity project will appear.
1517 wxRect wndRect;
1518 bool bMaximized = false;
1519 bool bIconized = false;
1520 GetNextWindowPlacement(&wndRect, &bMaximized, &bIconized);
1521
1522 wxSplashScreen temporarywindow(
1523 logo,
1524 wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_NO_TIMEOUT,
1525 0,
1526 NULL,
1527 wxID_ANY,
1528 wndRect.GetTopLeft(),
1529 wxDefaultSize,
1530 wxSTAY_ON_TOP);
1531
1532 // Unfortunately with the Windows 10 Creators update, the splash screen
1533 // now appears before setting its position.
1534 // On a dual monitor screen it will appear on one screen and then
1535 // possibly jump to the second.
1536 // We could fix this by writing our own splash screen and using Hide()
1537 // until the splash scren was correctly positioned, then Show()
1538
1539 // Possibly move it on to the second screen...
1540 temporarywindow.SetPosition( wndRect.GetTopLeft() );
1541 // Centered on whichever screen it is on.
1542 temporarywindow.Center();
1543 temporarywindow.SetTitle(_("Audacity is starting up..."));
1544 SetTopWindow(&temporarywindow);
1545 temporarywindow.Raise();
1546
1547 // ANSWER-ME: Why is YieldFor needed at all?
1548 //wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI|wxEVT_CATEGORY_USER_INPUT|wxEVT_CATEGORY_UNKNOWN);
1549 wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI);
1550
1551 //JKC: Would like to put module loading here.
1552
1553 // More initialization
1554
1555 InitDitherers();
1556 AudioIO::Init();
1557
1558#ifdef __WXMAC__
1559
1560 // On the Mac, users don't expect a program to quit when you close the last window.
1561 // Create a menubar that will show when all project windows are closed.
1562
1563 auto fileMenu = std::make_unique<wxMenu>();
1564 auto urecentMenu = std::make_unique<wxMenu>();
1565 auto recentMenu = urecentMenu.get();
1566 fileMenu->Append(wxID_NEW, wxString(_("&New")) + wxT("\tCtrl+N"));
1567 fileMenu->Append(wxID_OPEN, wxString(_("&Open...")) + wxT("\tCtrl+O"));
1568 fileMenu->AppendSubMenu(urecentMenu.release(), _("Open &Recent..."));
1569 fileMenu->Append(wxID_ABOUT, _("&About Audacity..."));
1570 fileMenu->Append(wxID_PREFERENCES, wxString(_("&Preferences...")) + wxT("\tCtrl+,"));
1571
1572 {
1573 auto menuBar = std::make_unique<wxMenuBar>();
1574 menuBar->Append(fileMenu.release(), _("&File"));
1575
1576 // PRL: Are we sure wxWindows will not leak this menuBar?
1577 // The online documentation is not explicit.
1578 wxMenuBar::MacSetCommonMenuBar(menuBar.release());
1579 }
1580
1581 auto &recentFiles = FileHistory::Global();
1582 recentFiles.UseMenu(recentMenu);
1583
1584#endif //__WXMAC__
1585 temporarywindow.Show(false);
1586 }
1587
1588 //Search for the new plugins
1589 std::vector<wxString> failedPlugins;
1590 if(!playingJournal && !SkipEffectsScanAtStartup.Read())
1591 {
1592 auto newPlugins = PluginManager::Get().CheckPluginUpdates();
1593 if(!newPlugins.empty())
1594 {
1595 PluginStartupRegistration reg(newPlugins);
1596 reg.Run();
1597 failedPlugins = reg.GetFailedPluginsPaths();
1598 }
1599 }
1600
1601 // Must do this before creating the first project, else the early exit path
1602 // may crash
1604 return false;
1605
1606 // Workaround Bug 1377 - Crash after Audacity starts and low disk space warning appears
1607 // The temporary splash window is closed AND cleaned up, before attempting to create
1608 // a project and possibly creating a modal warning dialog by doing so.
1609 // Also fixes problem of warning being obscured.
1610 // Downside is that we have no splash screen for the (brief) time that we spend
1611 // creating the project.
1612 // Root cause is problem with wxSplashScreen and other dialogs co-existing, that
1613 // seemed to arrive with wx3.
1614 {
1616 }
1617
1618 if (!playingJournal && ProjectSettings::Get(*project).GetShowSplashScreen())
1619 {
1620 // This may do a check-for-updates at every start up.
1621 // Mainly this is to tell users of ALPHAS who don't know that they have an ALPHA.
1622 // Disabled for now, after discussion.
1623 // project->MayCheckForUpdates();
1624#ifdef HAS_WHATS_NEW
1626#endif
1627 }
1628
1629#if defined(HAVE_UPDATES_CHECK)
1630 UpdateManager::Start(playingJournal);
1631#endif
1632
1635
1636 // Bug1561: delay the recovery dialog, to avoid crashes.
1637 CallAfter( [=] () mutable {
1638 // Remove duplicate shortcuts when there's a change of version
1639 int vMajorInit, vMinorInit, vMicroInit;
1640 GetPreferencesVersion(vMajorInit, vMinorInit, vMicroInit);
1641 if (vMajorInit != AUDACITY_VERSION || vMinorInit != AUDACITY_RELEASE
1642 || vMicroInit != AUDACITY_REVISION) {
1644 }
1645 //
1646 // Auto-recovery
1647 //
1648 bool didRecoverAnything = false;
1649 // This call may reassign project (passed by reference)
1650 if (!playingJournal)
1651 {
1652 if (!ShowAutoRecoveryDialogIfNeeded(project, &didRecoverAnything))
1653 {
1654 QuitAudacity(true);
1655 }
1656 }
1657
1658 //
1659 // Remainder of command line parsing, but only if we didn't recover
1660 //
1661 if (project && !didRecoverAnything)
1662 {
1663 if (parser->Found(wxT("t")))
1664 {
1665 RunBenchmark( nullptr, *project);
1666 QuitAudacity(true);
1667 }
1668
1669 for (size_t i = 0, cnt = parser->GetParamCount(); i < cnt; i++)
1670 {
1671 // PRL: Catch any exceptions, don't try this file again, continue to
1672 // other files.
1673 SafeMRUOpen(parser->GetParam(i));
1674 }
1675
1676 if(!failedPlugins.empty())
1677 {
1678 auto dialog = safenew IncompatiblePluginsDialog(GetTopWindow(), wxID_ANY, ScanType::Startup, failedPlugins);
1679 dialog->Bind(wxEVT_CLOSE_WINDOW, [dialog](wxCloseEvent&) { dialog->Destroy(); });
1680 dialog->Show();
1681 }
1682 }
1683 } );
1684
1685 gInited = true;
1686
1688
1689 mTimer.SetOwner(this, kAudacityAppTimerID);
1690 mTimer.Start(200);
1691
1692#ifdef EXPERIMENTAL_EASY_CHANGE_KEY_BINDINGS
1694 [](const CommandID &id){
1695 if (::wxGetMouseState().ShiftDown()) {
1696 // Only want one page of the preferences
1697 PrefsPanel::Factories factories;
1698 factories.push_back(KeyConfigPrefsFactory( id ));
1699 const auto pProject = GetActiveProject().lock();
1700 auto pWindow = FindProjectFrame( pProject.get() );
1701 // pProject may be null
1702 GlobalPrefsDialog dialog( pWindow, pProject.get(), factories );
1703 dialog.ShowModal();
1705 return true;
1706 }
1707 else
1708 return false;
1709 } };
1710#endif
1711
1712#if defined(__WXMAC__)
1713 // The first time this version of Audacity is run or when the preferences
1714 // are reset, execute the "tccutil" command to reset the microphone permissions
1715 // currently assigned to Audacity. The end result is that the user will be
1716 // prompted to approve/deny Audacity access (again).
1717 //
1718 // This should resolve confusion of why Audacity appears to record, but only
1719 // gets silence due to Audacity being denied microphone access previously.
1720 bool permsReset = false;
1721 gPrefs->Read(wxT("/MicrophonePermissionsReset"), &permsReset, false);
1722 if (!permsReset) {
1723 system("tccutil reset Microphone org.audacityteam.audacity");
1724 gPrefs->Write(wxT("/MicrophonePermissionsReset"), true);
1725 }
1726#endif
1727
1728#if defined(__WXMAC__)
1729 // Bug 2709: Workaround CoreSVG locale issue
1730 Bind(wxEVT_MENU_OPEN, [=](wxMenuEvent &event)
1731 {
1732 wxSetlocale(LC_NUMERIC, wxString(wxT("C")));
1733 event.Skip();
1734 });
1735
1736 Bind(wxEVT_MENU_CLOSE, [=](wxMenuEvent &event)
1737 {
1738 wxSetlocale(LC_NUMERIC, Languages::GetLocaleName());
1739 event.Skip();
1740 });
1741#endif
1742
1743#ifdef HAS_CUSTOM_URL_HANDLING
1744 // Schemes are case insensitive as per RFC: https://www.rfc-editor.org/rfc/rfc3986#section-3.1
1745 URLSchemesRegistry::Get().RegisterScheme(AUDACITY_NAME);
1746
1747 wxString url;
1748 if (parser->Found("u", &url))
1749 {
1750 auto utf8Url = url.ToUTF8();
1751 URLSchemesRegistry::Get().HandleURL({ utf8Url.data(), utf8Url.length() });
1752 }
1753#endif
1754
1756
1757 return TRUE;
1758}
AUDACITY_DLL_API std::weak_ptr< AudacityProject > GetActiveProject()
wxImage(22, 22)
#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
void GetNextWindowPlacement(wxRect *nextRect, bool *pMaximized, bool *pIconized)
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:121
void AssociateFileTypes()
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:1895
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(), GetNextWindowPlacement(), GetPreferencesVersion(), ProjectSettings::GetShowSplashScreen(), gInited, FileHistory::Global(), gPrefs, AppEvents::ProviderBase::HandleAppInitialized(), URLSchemesRegistry::HandleURL(), 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(), SkipEffectsScanAtStartup, UpdateManager::Start(), Startup, audacity::BasicSettings::Write(), wxImage(), and wxT().

Referenced by OnInit().

Here is the caller graph for this function:

◆ InitTempDir()

bool AudacityApp::InitTempDir ( )
private

Definition at line 1842 of file AudacityApp.cpp.

1843{
1844 // We need to find a temp directory location.
1845 auto tempFromPrefs = TempDirectory::TempDir();
1846 auto tempDefaultLoc = TempDirectory::DefaultTempDir();
1847
1848 wxString temp;
1849
1850 #ifdef __WXGTK__
1851 if (tempFromPrefs.length() > 0 && tempFromPrefs[0] != wxT('/'))
1852 tempFromPrefs = wxT("");
1853 #endif
1854
1855 // Stop wxWidgets from printing its own error messages
1856
1857 wxLogNull logNo;
1858
1859 // Try temp dir that was stored in prefs first
1860 if( TempDirectory::IsTempDirectoryNameOK( tempFromPrefs ) )
1861 SetToExtantDirectory( temp, tempFromPrefs );
1862
1863 // If that didn't work, try the default location
1864
1865 if (temp.empty())
1866 SetToExtantDirectory( temp, tempDefaultLoc );
1867
1868 // Check temp directory ownership on *nix systems only
1869 #ifdef __UNIX__
1870 struct stat tempStatBuf;
1871 if ( lstat(temp.mb_str(), &tempStatBuf) != 0 ) {
1872 temp.clear();
1873 }
1874 else {
1875 if ( geteuid() != tempStatBuf.st_uid ) {
1876 temp.clear();
1877 }
1878 }
1879 #endif
1880
1881 if (temp.empty()) {
1882 // Failed
1883 if( !TempDirectory::IsTempDirectoryNameOK( tempFromPrefs ) ) {
1885"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."));
1886 } else {
1888"Audacity could not find a place to store temporary files.\nPlease enter an appropriate directory in the preferences dialog."));
1889 }
1890
1891 // Only want one page of the preferences
1892 PrefsPanel::Factories factories;
1893 factories.push_back(DirectoriesPrefsFactory());
1894 GlobalPrefsDialog dialog(nullptr, nullptr, factories);
1895 dialog.ShowModal();
1896
1898"Audacity is now going to exit. Please launch Audacity again to use the new temporary directory."));
1899 return false;
1900 }
1901
1902 // The permissions don't always seem to be set on
1903 // some platforms. Hopefully this fixes it...
1904 #ifdef __UNIX__
1905 chmod(OSFILENAME(temp), 0700);
1906 #endif
1907
1909 FileNames::UpdateDefaultPath(FileNames::Operation::Temp, temp);
1910
1911 return true;
1912}
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 962 of file AudacityApp.cpp.

963{
964 if (!gInited)
965 return;
966
967 // This method should only be used on the Mac platform
968 // when no project windows are open.
969
970 if (AllProjects{}.empty())
971 (void) ProjectManager::New();
972}
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 950 of file AudacityApp.cpp.

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

References ofqueue.

◆ MacPrintFile()

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

Definition at line 956 of file AudacityApp.cpp.

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

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 2428 of file AudacityApp.cpp.

2429{
2430 bool force = !event.CanVeto();
2431
2432 // Try to close each open window. If the user hits Cancel
2433 // in a Save Changes dialog, don't continue.
2434 gIsQuitting = true;
2435 if (AllProjects{}.size())
2436 // PRL: Always did at least once before close might be vetoed
2437 // though I don't know why that is important
2439 bool closedAll = CloseAllProjects( force );
2440 if ( !closedAll )
2441 {
2442 gIsQuitting = false;
2443 event.Veto();
2444 }
2445}
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 1187 of file AudacityApp.cpp.

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

2448{
2449 gIsQuitting = true;
2450 while(Pending())
2451 {
2452 Dispatch();
2453 }
2454
2456
2458
2459 if(gPrefs)
2460 {
2461 bool bFalse = false;
2462 //Should we change the commands.cfg location next startup?
2463 if(gPrefs->Read(wxT("/QDeleteCmdCfgLocation"), &bFalse))
2464 {
2465 gPrefs->DeleteEntry(wxT("/QDeleteCmdCfgLocation"));
2466 gPrefs->Write(wxT("/DeleteCmdCfgLocation"), true);
2467 gPrefs->Flush();
2468 }
2469 }
2470
2472
2474
2475 DeinitFFT();
2476
2477#ifdef HAS_NETWORKING
2479#endif
2480
2482
2483 // Terminate the PluginManager (must be done before deleting the locale)
2485
2486 return 0;
2487}
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 1171 of file AudacityApp.cpp.

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

◆ OnIdle()

void AudacityApp::OnIdle ( wxIdleEvent &  evt)

Definition at line 1770 of file AudacityApp.cpp.

1771{
1772 evt.Skip();
1773 try {
1774 HandleAppIdle();
1775
1776 if ( Journal::Dispatch() )
1777 evt.RequestMore();
1778 }
1779 catch( ... ) {
1780 // Hmm, wxWidgets doesn't guard calls to the idle handler as for other
1781 // events. So replicate some of the try-catch logic here.
1783 // Fall through and return, allowing delayed handler action of
1784 // AudacityException to clean up
1785 }
1786}
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 1352 of file AudacityApp.cpp.

1353{
1354 // JKC: ANSWER-ME: Who actually added the event loop guarantor?
1355 // Although 'blame' says Leland, I think it came from a donated patch.
1356
1357 // PRL: It was added by LL at 54676a72285ba7ee3a69920e91fa390a71ef10c9 :
1358 // " Ensure OnInit() has an event loop
1359 // And allow events to flow so the splash window updates under GTK"
1360 // then mistakenly lost in the merge at
1361 // 37168ebbf67ae869ab71a3b5cbbf1d2a48e824aa
1362 // then restored at 7687972aa4b2199f0717165235f3ef68ade71e08
1363
1364 // Ensure we have an event loop during initialization
1365 wxEventLoopGuarantor eventLoop;
1366
1367 OnInit0();
1368
1370
1371 // Define languages for which we have translations, but that are not yet
1372 // supported by wxWidgets.
1373 //
1374 // TODO: The whole Language initialization really need to be reworked.
1375 // It's all over the place.
1376#if wxCHECK_VERSION(3, 0, 1) && !wxCHECK_VERSION(3, 1, 6)
1377 for (size_t i = 0, cnt = WXSIZEOF(userLangs); i < cnt; i++)
1378 {
1379 wxLocale::AddLanguage(userLangs[i]);
1380 }
1381#endif
1382
1383 // Initialize preferences and language
1384 {
1387 }
1388
1390
1391 {
1392 wxBusyCursor busy;
1394 }
1395
1396 // AColor depends on theTheme.
1397 AColor::Init();
1398
1399 // If this fails, we must exit the program.
1400 if (!InitTempDir()) {
1402 return false;
1403 }
1404
1406
1407#ifdef __WXMAC__
1408 // Bug2437: When files are opened from Finder and another instance of
1409 // Audacity is running, we must return from OnInit() to wxWidgets before
1410 // MacOpenFile is called, informing us of the paths that need to be
1411 // opened. So use CallAfter() to delay the rest of initialization.
1412 // See CreateSingleInstanceChecker() where we send those paths over a
1413 // socket to the prior instance.
1414
1415 // This call is what probably makes the sleep unnecessary:
1417
1418 using namespace std::chrono;
1419 // This sleep may be unnecessary, but it is harmless. It less NS framework
1420 // events arrive on another thread, but it might not always be long enough.
1421 std::this_thread::sleep_for(100ms);
1422 CallAfter([this]{
1423 if (!InitPart2())
1424 exit(-1);
1425 });
1426 return true;
1427#else
1428 return InitPart2();
1429#endif
1430}
void InitPreferences(std::unique_ptr< audacity::BasicSettings > uPrefs)
Definition: Prefs.cpp:231
THEME_API Theme theTheme
Definition: Theme.cpp:82
static void Init()
Definition: AColor.cpp:535
bool InitPart2()
void MacFinishLaunching()
Observer::Subscription mThemeChangeSubscription
Definition: AudacityApp.h:115
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(), Observer::Publisher< Message, NotifyAll >::Subscribe(), and theTheme.

Here is the call graph for this function:

◆ OnInit0()

void AudacityApp::OnInit0 ( )
private

Definition at line 1271 of file AudacityApp.cpp.

1272{
1273 // Inject basic GUI services behind the facades
1274 {
1275 static wxWidgetsBasicUI uiServices;
1276 (void)BasicUI::Install(&uiServices);
1277
1280 -> std::unique_ptr<BasicUI::WindowPlacement> {
1281 return std::make_unique<wxWidgetsWindowPlacement>(
1283 } };
1284 }
1285
1286 // Fire up SQLite
1288 this->CallAfter([]{
1290 XO("SQLite library failed to initialize. Audacity cannot continue.") );
1291 QuitAudacity( true );
1292 });
1293
1294
1295 // cause initialization of wxWidgets' global logger target
1296 (void) AudacityLogger::Get();
1297
1298#if defined(__WXMAC__)
1299 // Disable window animation
1300 wxSystemOptions::SetOption(wxMAC_WINDOW_PLAIN_TRANSITION, 1);
1301#endif
1302
1303 // Some GTK themes produce larger combo boxes that make them taller
1304 // than our single toolbar height restriction. This will remove some
1305 // of the extra space themes add.
1306#if defined(__WXGTK3__) && defined(HAVE_GTK)
1307 GtkWidget *combo = gtk_combo_box_new();
1308 GtkCssProvider *provider = gtk_css_provider_new();
1309 gtk_css_provider_load_from_data(GTK_CSS_PROVIDER(provider),
1310 ".linked entry,\n"
1311 ".linked button,\n"
1312 ".linked combobox box.linked button,\n"
1313 ".horizontal.linked entry,\n"
1314 ".horizontal.linked button,\n"
1315 ".horizontal.linked combobox box.linked button,\n"
1316 "combobox {\n"
1317 " padding-top: 0px;\n"
1318 " padding-bottom: 0px;\n"
1319 " padding-left: 4px;\n"
1320 " padding-right: 4px;\n"
1321 " margin: 0px;\n"
1322 " font-size: 95%;\n"
1323 "}", -1, NULL);
1324 gtk_style_context_add_provider_for_screen(gtk_widget_get_screen(combo),
1325 GTK_STYLE_PROVIDER (provider),
1326 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
1327 g_object_unref(provider);
1328 g_object_unref(combo);
1329#elif defined(__WXGTK__) && defined(HAVE_GTK)
1330 gtk_rc_parse_string("style \"audacity\" {\n"
1331 " GtkButton::inner_border = { 0, 0, 0, 0 }\n"
1332 " GtkEntry::inner_border = { 0, 0, 0, 0 }\n"
1333 " xthickness = 4\n"
1334 " ythickness = 0\n"
1335 "}\n"
1336 "widget_class \"*GtkCombo*\" style \"audacity\"");
1337#endif
1338
1339 wxTheApp->SetAppName(AppName);
1340 // Explicitly set since OSX will use it for the "Quit" menu item
1341 wxTheApp->SetAppDisplayName(AppName);
1342 wxTheApp->SetVendorName(AppName);
1343
1344 ::wxInitAllImageHandlers();
1345
1346 // AddHandler takes ownership
1347 wxFileSystem::AddHandler(safenew wxZipFSHandler);
1348}
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 1801 of file AudacityApp.cpp.

1802{
1803 if(event.GetKeyCode() == WXK_ESCAPE) {
1804 // Stop play, including scrub, but not record
1805 if ( auto project = ::GetActiveProject().lock() ) {
1806 auto token = ProjectAudioIO::Get( *project ).GetAudioIOToken();
1807 auto &scrubber = Scrubber::Get( *project );
1808 auto scrubbing = scrubber.HasMark();
1809 if (scrubbing)
1810 scrubber.Cancel();
1811 auto gAudioIO = AudioIO::Get();
1812 if((token > 0 &&
1813 gAudioIO->IsAudioTokenActive(token) &&
1814 gAudioIO->GetNumCaptureChannels() == 0) ||
1815 scrubbing)
1816 // ESC out of other play (but not record)
1817 ProjectAudioManager::Get( *project ).Stop();
1818 else
1819 event.Skip();
1820 }
1821 }
1822
1823 event.Skip();
1824}
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 2499 of file AudacityApp.cpp.

2500{
2501 // This function shadows a similar function
2502 // in Menus.cpp, but should only be used on the Mac platform.
2503#ifdef __WXMAC__
2504 // Modeless dialog, consistent with other Mac applications
2505 // Not more than one at once!
2506 const auto instance = AboutDialog::ActiveIntance();
2507 if (instance)
2508 instance->Raise();
2509 else
2510 // This dialog deletes itself when dismissed
2511 (safenew AboutDialog{ nullptr })->Show(true);
2512#else
2513 wxASSERT(false);
2514#endif
2515}
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 2566 of file AudacityApp.cpp.

2567{
2568 // This function shadows a similar function
2569 // in Menus.cpp, but should only be used on the Mac platform
2570 // when no project windows are open. This check assures that
2571 // this happens, and enable the same code to be present on
2572 // all platforms.
2573
2574 // LL: Removed "if" to allow closing based on final project count.
2575 // if(AllProjects{}.empty())
2576 QuitAudacity();
2577
2578 // LL: Veto quit if projects are still open. This can happen
2579 // if the user selected Cancel in a Save dialog.
2580 event.Skip(AllProjects{}.empty());
2581
2582}

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

Here is the call graph for this function:

◆ OnMenuNew()

void AudacityApp::OnMenuNew ( wxCommandEvent &  event)

Definition at line 2517 of file AudacityApp.cpp.

2518{
2519 // This function shadows a similar function
2520 // in Menus.cpp, but should only be used on the Mac platform
2521 // when no project windows are open. This check assures that
2522 // this happens, and enable the same code to be present on
2523 // all platforms.
2524
2525 if(AllProjects{}.empty())
2526 (void) ProjectManager::New();
2527 else
2528 event.Skip();
2529}

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

Here is the call graph for this function:

◆ OnMenuOpen()

void AudacityApp::OnMenuOpen ( wxCommandEvent &  event)

Definition at line 2532 of file AudacityApp.cpp.

2533{
2534 // This function shadows a similar function
2535 // in Menus.cpp, but should only be used on the Mac platform
2536 // when no project windows are open. This check assures that
2537 // this happens, and enable the same code to be present on
2538 // all platforms.
2539
2540
2541 if(AllProjects{}.empty())
2543 else
2544 event.Skip();
2545
2546
2547}
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 2549 of file AudacityApp.cpp.

2550{
2551 // This function shadows a similar function
2552 // in Menus.cpp, but should only be used on the Mac platform
2553 // when no project windows are open. This check assures that
2554 // this happens, and enable the same code to be present on
2555 // all platforms.
2556
2557 if(AllProjects{}.empty()) {
2558 GlobalPrefsDialog dialog(nullptr /* parent */, nullptr );
2559 dialog.ShowModal();
2560 }
2561 else
2562 event.Skip();
2563
2564}

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

Here is the call graph for this function:

◆ OnMRUClear()

void AudacityApp::OnMRUClear ( wxCommandEvent &  event)

Definition at line 1074 of file AudacityApp.cpp.

1075{
1077}
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 1082 of file AudacityApp.cpp.

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

2415{
2416 bool mustVeto = false;
2417
2418#ifdef __WXMAC__
2419 mustVeto = wxDialog::OSXHasModalDialogsOpen();
2420#endif
2421
2422 if ( mustVeto )
2423 event.Veto(true);
2424 else
2425 OnEndSession(event);
2426}
void OnEndSession(wxCloseEvent &event)

References OnEndSession().

Here is the call graph for this function:

◆ OnReceiveCommand()

void AudacityApp::OnReceiveCommand ( AppCommandEvent event)

Definition at line 1795 of file AudacityApp.cpp.

1796{
1797 wxASSERT(NULL != mCmdHandler);
1798 mCmdHandler->OnReceiveCommand(event);
1799}

References mCmdHandler.

◆ OnRun()

int AudacityApp::OnRun ( )
override

Definition at line 1760 of file AudacityApp.cpp.

1761{
1762 // Returns 0 to the command line if the run completed normally
1763 auto result = wxApp::OnRun();
1764 if (result == 0)
1765 // If not otherwise abnormal, report any journal sync failure
1766 result = Journal::GetExitCode();
1767 return result;
1768}
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 1099 of file AudacityApp.cpp.

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

References TranslatableString::empty(), URLSchemesRegistry::Get(), GetActiveProject(), GetProjectFrame(), gInited, URLSchemesRegistry::HandleURL(), name, ofqueue, project, SafeMRUOpen(), and wxT().

Here is the call graph for this function:

◆ OSXIsGUIApplication()

bool AudacityApp::OSXIsGUIApplication ( )
override

Definition at line 1260 of file AudacityApp.cpp.

1261{
1262 return sOSXIsGUIApplication;
1263}

References IMPLEMENT_WX_THEME_SUPPORT::sOSXIsGUIApplication.

◆ ParseCommandLine()

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

Definition at line 2365 of file AudacityApp.cpp.

2366{
2367 auto parser = std::make_unique<wxCmdLineParser>(argc, argv);
2368 if (!parser)
2369 {
2370 return nullptr;
2371 }
2372
2373 /*i18n-hint: This controls the number of bytes that Audacity will
2374 * use when writing files to the disk */
2375 parser->AddOption(wxT("b"), wxT("blocksize"), _("set max disk block size in bytes"),
2376 wxCMD_LINE_VAL_NUMBER);
2377
2378 const auto journalOptionDescription =
2379 /*i18n-hint: brief help message for Audacity's command-line options
2380 A journal contains a sequence of user interface interactions to be repeated
2381 "log," "trail," "trace" have somewhat similar meanings */
2382 _("replay a journal file");
2383
2384 parser->AddOption(wxT("j"), wxT("journal"), journalOptionDescription);
2385
2386 /*i18n-hint: This displays a list of available options */
2387 parser->AddSwitch(wxT("h"), wxT("help"), _("this help message"),
2388 wxCMD_LINE_OPTION_HELP);
2389
2390 /*i18n-hint: This runs a set of automatic tests on Audacity itself */
2391 parser->AddSwitch(wxT("t"), wxT("test"), _("run self diagnostics"));
2392
2393 /*i18n-hint: This displays the Audacity version */
2394 parser->AddSwitch(wxT("v"), wxT("version"), _("display Audacity version"));
2395
2396 /*i18n-hint: This is a list of one or more files that Audacity
2397 * should open upon startup */
2398 parser->AddParam(_("audio or project file name"),
2399 wxCMD_LINE_VAL_STRING,
2400 wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL);
2401
2402#ifdef HAS_CUSTOM_URL_HANDLING
2403 /* i18n-hint: This option is used to handle custom URLs in Audacity */
2404 parser->AddOption(wxT("u"), wxT("url"), _("Handle 'audacity://' url"));
2405#endif
2406
2407 // Run the parser
2408 if (parser->Parse() == 0)
2409 return parser;
2410
2411 return{};
2412}

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 1069 of file AudacityApp.cpp.

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

References MRUOpen().

Referenced by InitPart2(), and OnTimer().

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 119 of file AudacityApp.h.

Referenced by CreateSingleInstanceChecker().

◆ mCmdHandler

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

Definition at line 117 of file AudacityApp.h.

Referenced by InitCommandHandler(), and OnReceiveCommand().

◆ mIPCServ

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

Definition at line 131 of file AudacityApp.h.

Referenced by CreateSingleInstanceChecker().

◆ mThemeChangeSubscription

Observer::Subscription AudacityApp::mThemeChangeSubscription
private

Definition at line 115 of file AudacityApp.h.

Referenced by OnInit().

◆ mTimer

wxTimer AudacityApp::mTimer
private

Definition at line 121 of file AudacityApp.h.

Referenced by InitPart2().


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