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

1226{
1227}

◆ ~AudacityApp()

AudacityApp::~AudacityApp ( )

Definition at line 1255 of file AudacityApp.cpp.

1256{
1257}

Member Function Documentation

◆ AssociateFileTypes()

void AudacityApp::AssociateFileTypes ( )

Definition at line 2587 of file AudacityApp.cpp.

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

1239{
1240 //Reset the current wxConfigBase instance manually
1241 //to avoid double deletion in wxWidgets 3.2
1242 //See Bug #5511
1243 wxConfigBase::Set(nullptr);
1244 gConfig.reset();
1245 wxApp::CleanUp();
1246}
static std::shared_ptr< wxConfigBase > gConfig

References gConfig.

◆ CreateSingleInstanceChecker()

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

Definition at line 1906 of file AudacityApp.cpp.

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

1776{
1777 mCmdHandler = std::make_unique<CommandHandler>();
1778 //SetNextHandler(mCmdHandler);
1779}
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 1229 of file AudacityApp.cpp.

1230{
1232 {
1234 }
1235 return wxApp::Initialize(argc, argv);
1236}
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 1421 of file AudacityApp.cpp.

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

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

952{
953 if (!gInited)
954 return;
955
956 // This method should only be used on the Mac platform
957 // when no project windows are open.
958
959 if (AllProjects{}.empty())
960 (void) ProjectManager::New();
961}
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 939 of file AudacityApp.cpp.

940{
941 ofqueue.push_back(fileName);
942}
static wxArrayString ofqueue

References ofqueue.

◆ MacPrintFile()

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

Definition at line 945 of file AudacityApp.cpp.

946{
947 ofqueue.push_back(fileName);
948}

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

2416{
2417 bool force = !event.CanVeto();
2418
2419 // Try to close each open window. If the user hits Cancel
2420 // in a Save Changes dialog, don't continue.
2421 gIsQuitting = true;
2422 if (AllProjects{}.size())
2423 // PRL: Always did at least once before close might be vetoed
2424 // though I don't know why that is important
2426 bool closedAll = CloseAllProjects( force );
2427 if ( !closedAll )
2428 {
2429 gIsQuitting = false;
2430 event.Veto();
2431 }
2432}
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 1176 of file AudacityApp.cpp.

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

2435{
2436 gIsQuitting = true;
2437 while(Pending())
2438 {
2439 Dispatch();
2440 }
2441
2443
2445
2446 if(gPrefs)
2447 {
2448 bool bFalse = false;
2449 //Should we change the commands.cfg location next startup?
2450 if(gPrefs->Read(wxT("/QDeleteCmdCfgLocation"), &bFalse))
2451 {
2452 gPrefs->DeleteEntry(wxT("/QDeleteCmdCfgLocation"));
2453 gPrefs->Write(wxT("/DeleteCmdCfgLocation"), true);
2454 gPrefs->Flush();
2455 }
2456 }
2457
2459
2461
2462 DeinitFFT();
2463
2464#ifdef HAS_NETWORKING
2466#endif
2467
2469
2470 // Terminate the PluginManager (must be done before deleting the locale)
2472
2473 return 0;
2474}
void DeinitFFT()
Definition: FFT.cpp:112
static void Deinit()
Definition: AudioIO.cpp:218
void Save(audacity::BasicSettings &config)
bool Terminate()
Definition: Import.cpp:200
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 1160 of file AudacityApp.cpp.

1161{
1162#if defined(HAS_CRASH_REPORT)
1163 CrashReport::Generate(wxDebugReport::Context_Exception);
1164#endif
1165
1166 exit(-1);
1167}

◆ OnIdle()

void AudacityApp::OnIdle ( wxIdleEvent &  evt)

Definition at line 1757 of file AudacityApp.cpp.

1758{
1759 evt.Skip();
1760 try {
1761 HandleAppIdle();
1762
1763 if ( Journal::Dispatch() )
1764 evt.RequestMore();
1765 }
1766 catch( ... ) {
1767 // Hmm, wxWidgets doesn't guard calls to the idle handler as for other
1768 // events. So replicate some of the try-catch logic here.
1770 // Fall through and return, allowing delayed handler action of
1771 // AudacityException to clean up
1772 }
1773}
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 1341 of file AudacityApp.cpp.

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

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

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

1789{
1790 if(event.GetKeyCode() == WXK_ESCAPE) {
1791 // Stop play, including scrub, but not record
1792 if ( auto project = ::GetActiveProject().lock() ) {
1793 auto token = ProjectAudioIO::Get( *project ).GetAudioIOToken();
1794 auto &scrubber = Scrubber::Get( *project );
1795 auto scrubbing = scrubber.HasMark();
1796 if (scrubbing)
1797 scrubber.Cancel();
1798 auto gAudioIO = AudioIO::Get();
1799 if((token > 0 &&
1800 gAudioIO->IsAudioTokenActive(token) &&
1801 gAudioIO->GetNumCaptureChannels() == 0) ||
1802 scrubbing)
1803 // ESC out of other play (but not record)
1804 ProjectAudioManager::Get( *project ).Stop();
1805 else
1806 event.Skip();
1807 }
1808 }
1809
1810 event.Skip();
1811}
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 2486 of file AudacityApp.cpp.

2487{
2488 // This function shadows a similar function
2489 // in Menus.cpp, but should only be used on the Mac platform.
2490#ifdef __WXMAC__
2491 // Modeless dialog, consistent with other Mac applications
2492 // Not more than one at once!
2493 const auto instance = AboutDialog::ActiveIntance();
2494 if (instance)
2495 instance->Raise();
2496 else
2497 // This dialog deletes itself when dismissed
2498 (safenew AboutDialog{ nullptr })->Show(true);
2499#else
2500 wxASSERT(false);
2501#endif
2502}
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 2553 of file AudacityApp.cpp.

2554{
2555 // This function shadows a similar function
2556 // in Menus.cpp, but should only be used on the Mac platform
2557 // when no project windows are open. This check assures that
2558 // this happens, and enable the same code to be present on
2559 // all platforms.
2560
2561 // LL: Removed "if" to allow closing based on final project count.
2562 // if(AllProjects{}.empty())
2563 QuitAudacity();
2564
2565 // LL: Veto quit if projects are still open. This can happen
2566 // if the user selected Cancel in a Save dialog.
2567 event.Skip(AllProjects{}.empty());
2568
2569}

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

Here is the call graph for this function:

◆ OnMenuNew()

void AudacityApp::OnMenuNew ( wxCommandEvent &  event)

Definition at line 2504 of file AudacityApp.cpp.

2505{
2506 // This function shadows a similar function
2507 // in Menus.cpp, but should only be used on the Mac platform
2508 // when no project windows are open. This check assures that
2509 // this happens, and enable the same code to be present on
2510 // all platforms.
2511
2512 if(AllProjects{}.empty())
2513 (void) ProjectManager::New();
2514 else
2515 event.Skip();
2516}

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

Here is the call graph for this function:

◆ OnMenuOpen()

void AudacityApp::OnMenuOpen ( wxCommandEvent &  event)

Definition at line 2519 of file AudacityApp.cpp.

2520{
2521 // This function shadows a similar function
2522 // in Menus.cpp, but should only be used on the Mac platform
2523 // when no project windows are open. This check assures that
2524 // this happens, and enable the same code to be present on
2525 // all platforms.
2526
2527
2528 if(AllProjects{}.empty())
2530 else
2531 event.Skip();
2532
2533
2534}
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 2536 of file AudacityApp.cpp.

2537{
2538 // This function shadows a similar function
2539 // in Menus.cpp, but should only be used on the Mac platform
2540 // when no project windows are open. This check assures that
2541 // this happens, and enable the same code to be present on
2542 // all platforms.
2543
2544 if(AllProjects{}.empty()) {
2545 GlobalPrefsDialog dialog(nullptr /* parent */, nullptr );
2546 dialog.ShowModal();
2547 }
2548 else
2549 event.Skip();
2550
2551}

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

Here is the call graph for this function:

◆ OnMRUClear()

void AudacityApp::OnMRUClear ( wxCommandEvent &  event)

Definition at line 1063 of file AudacityApp.cpp.

1064{
1066}
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 1071 of file AudacityApp.cpp.

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

2402{
2403 bool mustVeto = false;
2404
2405#ifdef __WXMAC__
2406 mustVeto = wxDialog::OSXHasModalDialogsOpen();
2407#endif
2408
2409 if ( mustVeto )
2410 event.Veto(true);
2411 else
2412 OnEndSession(event);
2413}
void OnEndSession(wxCloseEvent &event)

References OnEndSession().

Here is the call graph for this function:

◆ OnReceiveCommand()

void AudacityApp::OnReceiveCommand ( AppCommandEvent event)

Definition at line 1782 of file AudacityApp.cpp.

1783{
1784 wxASSERT(NULL != mCmdHandler);
1785 mCmdHandler->OnReceiveCommand(event);
1786}

References mCmdHandler.

◆ OnRun()

int AudacityApp::OnRun ( )
override

Definition at line 1747 of file AudacityApp.cpp.

1748{
1749 // Returns 0 to the command line if the run completed normally
1750 auto result = wxApp::OnRun();
1751 if (result == 0)
1752 // If not otherwise abnormal, report any journal sync failure
1753 result = Journal::GetExitCode();
1754 return result;
1755}
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 1088 of file AudacityApp.cpp.

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

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

1250{
1251 return sOSXIsGUIApplication;
1252}

References IMPLEMENT_WX_THEME_SUPPORT::sOSXIsGUIApplication.

◆ ParseCommandLine()

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

Definition at line 2352 of file AudacityApp.cpp.

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

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

1059{
1060 return GuardedCall< bool >( [&]{ return MRUOpen( fullPathStr ); } );
1061}

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: