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 ()
 

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

1219{
1220}

◆ ~AudacityApp()

AudacityApp::~AudacityApp ( )

Definition at line 1248 of file AudacityApp.cpp.

1249{
1250}

Member Function Documentation

◆ AssociateFileTypes()

void AudacityApp::AssociateFileTypes ( )

Definition at line 2576 of file AudacityApp.cpp.

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

1232{
1233 //Reset the current wxConfigBase instance manually
1234 //to avoid double deletion in wxWidgets 3.2
1235 //See Bug #5511
1236 wxConfigBase::Set(nullptr);
1237 gConfig.reset();
1238 wxApp::CleanUp();
1239}
static std::shared_ptr< wxConfigBase > gConfig

References gConfig.

◆ CreateSingleInstanceChecker()

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

Definition at line 1897 of file AudacityApp.cpp.

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

1767{
1768 mCmdHandler = std::make_unique<CommandHandler>();
1769 //SetNextHandler(mCmdHandler);
1770}
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 1222 of file AudacityApp.cpp.

1223{
1225 {
1227 }
1228 return wxApp::Initialize(argc, argv);
1229}
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 1414 of file AudacityApp.cpp.

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

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

945{
946 if (!gInited)
947 return;
948
949 // This method should only be used on the Mac platform
950 // when no project windows are open.
951
952 if (AllProjects{}.empty())
953 (void) ProjectManager::New();
954}
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 932 of file AudacityApp.cpp.

933{
934 ofqueue.push_back(fileName);
935}
static wxArrayString ofqueue

References ofqueue.

◆ MacPrintFile()

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

Definition at line 938 of file AudacityApp.cpp.

939{
940 ofqueue.push_back(fileName);
941}

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

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

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

References BasicUI::CallAfter(), TrackList::ClearPendingTracks(), AudacityException::DelayedHandlerAction(), ProjectHistory::Get(), TrackList::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 2425 of file AudacityApp.cpp.

2426{
2427 gIsQuitting = true;
2428 while(Pending())
2429 {
2430 Dispatch();
2431 }
2432
2434
2435 if(gPrefs)
2436 {
2437 bool bFalse = false;
2438 //Should we change the commands.cfg location next startup?
2439 if(gPrefs->Read(wxT("/QDeleteCmdCfgLocation"), &bFalse))
2440 {
2441 gPrefs->DeleteEntry(wxT("/QDeleteCmdCfgLocation"));
2442 gPrefs->Write(wxT("/DeleteCmdCfgLocation"), true);
2443 gPrefs->Flush();
2444 }
2445 }
2446
2448
2450
2451 DeinitFFT();
2452
2453#ifdef HAS_NETWORKING
2455#endif
2456
2458
2459 // Terminate the PluginManager (must be done before deleting the locale)
2461
2462 return 0;
2463}
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, 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 1153 of file AudacityApp.cpp.

1154{
1155#if defined(HAS_CRASH_REPORT)
1156 CrashReport::Generate(wxDebugReport::Context_Exception);
1157#endif
1158
1159 exit(-1);
1160}

◆ OnIdle()

void AudacityApp::OnIdle ( wxIdleEvent &  evt)

Definition at line 1750 of file AudacityApp.cpp.

1751{
1752 evt.Skip();
1753 try {
1754 if ( Journal::Dispatch() )
1755 evt.RequestMore();
1756 }
1757 catch( ... ) {
1758 // Hmm, wxWidgets doesn't guard calls to the idle handler as for other
1759 // events. So replicate some of the try-catch logic here.
1761 // Fall through and return, allowing delayed handler action of
1762 // AudacityException to clean up
1763 }
1764}
bool OnExceptionInMainLoop() override
bool Dispatch()
Definition: Journal.cpp:291

References Journal::Dispatch(), and OnExceptionInMainLoop().

Here is the call graph for this function:

◆ OnInit()

bool AudacityApp::OnInit ( )
override

Definition at line 1334 of file AudacityApp.cpp.

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

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

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

1780{
1781 if(event.GetKeyCode() == WXK_ESCAPE) {
1782 // Stop play, including scrub, but not record
1783 if ( auto project = ::GetActiveProject().lock() ) {
1784 auto token = ProjectAudioIO::Get( *project ).GetAudioIOToken();
1785 auto &scrubber = Scrubber::Get( *project );
1786 auto scrubbing = scrubber.HasMark();
1787 if (scrubbing)
1788 scrubber.Cancel();
1789 auto gAudioIO = AudioIO::Get();
1790 if((token > 0 &&
1791 gAudioIO->IsAudioTokenActive(token) &&
1792 gAudioIO->GetNumCaptureChannels() == 0) ||
1793 scrubbing)
1794 // ESC out of other play (but not record)
1795 ProjectAudioManager::Get( *project ).Stop();
1796 else
1797 event.Skip();
1798 }
1799 }
1800
1801 event.Skip();
1802}
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:188

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

2476{
2477 // This function shadows a similar function
2478 // in Menus.cpp, but should only be used on the Mac platform.
2479#ifdef __WXMAC__
2480 // Modeless dialog, consistent with other Mac applications
2481 // Not more than one at once!
2482 const auto instance = AboutDialog::ActiveIntance();
2483 if (instance)
2484 instance->Raise();
2485 else
2486 // This dialog deletes itself when dismissed
2487 (safenew AboutDialog{ nullptr })->Show(true);
2488#else
2489 wxASSERT(false);
2490#endif
2491}
The AboutDialog shows the program version and developer credits.
Definition: AboutDialog.h:32
static AboutDialog * ActiveIntance()
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 2542 of file AudacityApp.cpp.

2543{
2544 // This function shadows a similar function
2545 // in Menus.cpp, but should only be used on the Mac platform
2546 // when no project windows are open. This check assures that
2547 // this happens, and enable the same code to be present on
2548 // all platforms.
2549
2550 // LL: Removed "if" to allow closing based on final project count.
2551 // if(AllProjects{}.empty())
2552 QuitAudacity();
2553
2554 // LL: Veto quit if projects are still open. This can happen
2555 // if the user selected Cancel in a Save dialog.
2556 event.Skip(AllProjects{}.empty());
2557
2558}

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

Here is the call graph for this function:

◆ OnMenuNew()

void AudacityApp::OnMenuNew ( wxCommandEvent &  event)

Definition at line 2493 of file AudacityApp.cpp.

2494{
2495 // This function shadows a similar function
2496 // in Menus.cpp, but should only be used on the Mac platform
2497 // when no project windows are open. This check assures that
2498 // this happens, and enable the same code to be present on
2499 // all platforms.
2500
2501 if(AllProjects{}.empty())
2502 (void) ProjectManager::New();
2503 else
2504 event.Skip();
2505}

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

Here is the call graph for this function:

◆ OnMenuOpen()

void AudacityApp::OnMenuOpen ( wxCommandEvent &  event)

Definition at line 2508 of file AudacityApp.cpp.

2509{
2510 // This function shadows a similar function
2511 // in Menus.cpp, but should only be used on the Mac platform
2512 // when no project windows are open. This check assures that
2513 // this happens, and enable the same code to be present on
2514 // all platforms.
2515
2516
2517 if(AllProjects{}.empty())
2519 else
2520 event.Skip();
2521
2522
2523}
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 2525 of file AudacityApp.cpp.

2526{
2527 // This function shadows a similar function
2528 // in Menus.cpp, but should only be used on the Mac platform
2529 // when no project windows are open. This check assures that
2530 // this happens, and enable the same code to be present on
2531 // all platforms.
2532
2533 if(AllProjects{}.empty()) {
2534 GlobalPrefsDialog dialog(nullptr /* parent */, nullptr );
2535 dialog.ShowModal();
2536 }
2537 else
2538 event.Skip();
2539
2540}

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

Here is the call graph for this function:

◆ OnMRUClear()

void AudacityApp::OnMRUClear ( wxCommandEvent &  event)

Definition at line 1056 of file AudacityApp.cpp.

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

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

2393{
2394 bool mustVeto = false;
2395
2396#ifdef __WXMAC__
2397 mustVeto = wxDialog::OSXHasModalDialogsOpen();
2398#endif
2399
2400 if ( mustVeto )
2401 event.Veto(true);
2402 else
2403 OnEndSession(event);
2404}
void OnEndSession(wxCloseEvent &event)

References OnEndSession().

Here is the call graph for this function:

◆ OnReceiveCommand()

void AudacityApp::OnReceiveCommand ( AppCommandEvent event)

Definition at line 1773 of file AudacityApp.cpp.

1774{
1775 wxASSERT(NULL != mCmdHandler);
1776 mCmdHandler->OnReceiveCommand(event);
1777}

References mCmdHandler.

◆ OnRun()

int AudacityApp::OnRun ( )
override

Definition at line 1740 of file AudacityApp.cpp.

1741{
1742 // Returns 0 to the command line if the run completed normally
1743 auto result = wxApp::OnRun();
1744 if (result == 0)
1745 // If not otherwise abnormal, report any journal sync failure
1746 result = Journal::GetExitCode();
1747 return result;
1748}
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 1081 of file AudacityApp.cpp.

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

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

1243{
1244 return sOSXIsGUIApplication;
1245}

References IMPLEMENT_WX_THEME_SUPPORT::sOSXIsGUIApplication.

◆ ParseCommandLine()

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

Definition at line 2343 of file AudacityApp.cpp.

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

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

1052{
1053 return GuardedCall< bool >( [&]{ return MRUOpen( fullPathStr ); } );
1054}

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: