26#include <wx/wxcrtvararg.h>
28#include <wx/evtloop.h>
30#include <wx/docview.h>
34#include <wx/snglinst.h>
36#include <wx/stdpaths.h>
38#include <wx/fontmap.h>
44#include <wx/filename.h>
62#include <wx/msw/registry.h>
117#if defined(HAVE_UPDATES_CHECK)
129#ifdef EXPERIMENTAL_EASY_CHANGE_KEY_BINDINGS
141#if defined(USE_BREAKPAD)
143#elif defined(USE_CRASHPAD)
147#ifdef EXPERIMENTAL_SCOREALIGN
155 static char*THIS_FILE= __FILE__;
156 #define new new(_NORMAL_BLOCK, THIS_FILE, __LINE__)
162#include "../images/Audacity-splash.xpm"
170#ifdef HAS_CUSTOM_URL_HANDLING
175static wxString urlPrefix =
wxT(
"url:");
185static void wxOnAssert(
const wxChar *fileName,
int lineNumber,
const wxChar *msg)
188 wxPrintf(
"ASSERTION FAILED: %s\n%s: %d\n", (
const char *)wxString(msg).mb_str(), (
const char *)wxString(fileName).mb_str(), lineNumber);
190 wxPrintf(
"ASSERTION FAILED!\n%s: %d\n", (
const char *)wxString(fileName).mb_str(), lineNumber);
206 bool resetPrefs =
false;
207 wxString langCode =
gPrefs->
Read(
wxT(
"/Locale/Language"), wxEmptyString);
208 bool writeLang =
false;
212 wxT(
"FirstTime.ini"));
215 const wxString fullPath{
fn.GetFullPath()};
219 wxCONFIG_USE_LOCAL_FILE);
223 if (ini.Read(
wxT(
"/FromInno/Language"), &lang) && !lang.empty())
231 langCode.Replace(
wxT(
"0"),
wxT(
"@"));
234 ini.Read(
wxT(
"/FromInno/ResetPrefs"), &resetPrefs,
false);
236 bool gone = wxRemoveFile(fullPath);
240 XO(
"Failed to remove %s").
Format(fullPath),
246 if (langCode.empty())
269 bool newPrefsInitialized =
false;
270 gPrefs->
Read(
wxT(
"/NewPrefsInitialized"), &newPrefsInitialized,
false);
271 if (newPrefsInitialized) {
295 (vMajor == 1 && vMinor < 3) ||
296 (vMajor == 1 && vMinor == 3 && vMicro < 13)) {
319 long dock, order, show, x, y, w, h;
335 const auto orderKey = group +
wxT(
"/Order");
336 if(
gPrefs->
Read(orderKey, &orderValue) && orderValue >= order)
364 if ((0<vMajor && vMajor < 2) ||
365 (vMajor == 2 && vMinor < 2))
371 if ((0<vMajor && vMajor < 2) ||
372 (vMajor == 2 && vMinor < 4))
386 if (std::pair{ vMajor, vMinor } < std::pair{ 3, 1 } ) {
391 if(std::pair{vMajor, vMinor} < std::pair{3, 2})
403 if(std::tuple{ vMajor, vMinor, vMicro } < std::tuple{ 3, 2, 3 })
411 if (std::pair { vMajor, vMinor } < std::pair { 3, 4 })
419 if (std::pair { vMajor, vMinor } < std::pair { 3, 5 })
425 if (std::pair { vMajor, vMinor } < std::pair { 3, 6 })
443#if defined(USE_BREAKPAD) || defined(USE_CRASHPAD)
444 wxFileName databasePath;
446 databasePath.AppendDir(
"crashreports");
447 databasePath.Mkdir(wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL);
449 if(databasePath.DirExists())
451 const auto sentryRelease = wxString::Format(
452 "audacity@%d.%d.%d", AUDACITY_VERSION, AUDACITY_RELEASE, AUDACITY_REVISION);
453#if defined(USE_BREAKPAD)
457 #if defined(CRASH_REPORT_URL)
461 {
"version", wxString(AUDACITY_VERSION_STRING).ToUTF8().data() },
462 {
"sentry[release]", sentryRelease.ToUTF8().data() }
465#elif defined(USE_CRASHPAD)
469 const wxFileName crashpadHandlerPath(executableDir, CRASHPAD_HANDLER_NAME);
470 const wxFileName crashreporterPath(executableDir, CRASHREPORTER_NAME);
471 const wxFileName metricsDir = databasePath;
472 std::vector<std::string> arguments = {
473 wxString::Format(
"--crashreporter-path=%s", crashreporterPath.GetFullPath()).ToUTF8().data(),
474#if defined(CRASH_REPORT_URL)
476 "--crashreporter-argument=-u=%s",
477 CRASH_REPORT_URL).ToUTF8().data(),
479 "--crashreporter-argument=-a=version=\"%s\",sentry[release]=\"%s\"",
480 AUDACITY_VERSION_STRING,
481 sentryRelease).ToUTF8().data()
491 catch (std::exception& e)
493 wxLogError(
"Crashpad init error: %s", e.what());
497#elif !defined(_DEBUG)
498#if defined(HAS_CRASH_REPORT)
499#if defined(wxUSE_ON_FATAL_EXCEPTION) && wxUSE_ON_FATAL_EXCEPTION
500 wxHandleFatalExceptions();
546 wxTheApp->SetExitOnFrameDelete(
true);
578#ifdef EXPERIMENTAL_SCOREALIGN
579 CloseScoreAlignDialog();
585 #if !defined(__WXMAC__)
599 logger->SaveLog(logFile.GetFullPath());
603 std::unique_ptr<wxLog>{ wxLog::SetActiveTarget(NULL) };
616#if defined(__WXGTK__) && defined(HAVE_GTK)
636#include <glib-object.h>
638typedef struct _GnomeProgram GnomeProgram;
639typedef struct _GnomeModuleInfo GnomeModuleInfo;
640typedef struct _GnomeClient GnomeClient;
652 GNOME_INTERACT_ERRORS,
662typedef GnomeProgram * (*_gnome_program_init_fn)(
const char *,
664 const GnomeModuleInfo *,
669typedef const GnomeModuleInfo * (*_libgnomeui_module_info_get_fn)();
670typedef GnomeClient * (*_gnome_master_client_fn)(void);
671typedef void (*GnomeInteractFunction)(GnomeClient *,
675typedef void (*_gnome_client_request_interaction_fn)(GnomeClient *,
677 GnomeInteractFunction,
679typedef void (*_gnome_interaction_key_return_fn)(gint, gboolean);
681static _gnome_client_request_interaction_fn gnome_client_request_interaction;
682static _gnome_interaction_key_return_fn gnome_interaction_key_return;
684static void interact_cb(GnomeClient * ,
689 wxCloseEvent e(wxEVT_QUERY_END_SESSION, wxID_ANY);
695 gnome_interaction_key_return(
key, e.GetVeto());
698static gboolean save_yourself_cb(GnomeClient *client,
702 GnomeInteractStyle interact,
706 if (!shutdown || interact != GNOME_INTERACT_ANY) {
714 gnome_client_request_interaction(client,
728 const char *libgnomeui =
"libgnomeui-2.so";
729 const char *libgnome =
"libgnome-2.so";
731 const char *libgnomeui =
"libgnomeui-2.so.0";
732 const char *libgnome =
"libgnome-2.so.0";
735 mArgv[0].reset(strdup(
"Audacity"));
737 mGnomeui = dlopen(libgnomeui, RTLD_NOW);
742 mGnome = dlopen(libgnome, RTLD_NOW);
747 _gnome_program_init_fn gnome_program_init = (_gnome_program_init_fn)
748 dlsym(mGnome,
"gnome_program_init");
749 _libgnomeui_module_info_get_fn libgnomeui_module_info_get = (_libgnomeui_module_info_get_fn)
750 dlsym(mGnomeui,
"libgnomeui_module_info_get");
751 _gnome_master_client_fn gnome_master_client = (_gnome_master_client_fn)
752 dlsym(mGnomeui,
"gnome_master_client");
754 gnome_client_request_interaction = (_gnome_client_request_interaction_fn)
755 dlsym(mGnomeui,
"gnome_client_request_interaction");
756 gnome_interaction_key_return = (_gnome_interaction_key_return_fn)
757 dlsym(mGnomeui,
"gnome_interaction_key_return");
760 if (!gnome_program_init || !libgnomeui_module_info_get) {
764 gnome_program_init(mArgv[0].get(),
766 libgnomeui_module_info_get(),
768 reinterpret_cast<char**
>(mArgv),
771 mClient = gnome_master_client();
772 if (mClient == NULL) {
776 g_signal_connect(mClient,
"save-yourself", G_CALLBACK(save_yourself_cb), NULL);
779 virtual ~GnomeShutdown()
789 GnomeClient *mClient;
794GnomeShutdown GnomeShutdownInstance;
807#define IPC_APPL wxT("audacity")
808#define IPC_TOPIC wxT("System")
822 bool OnExec(
const wxString & WXUNUSED(topic),
823 const wxString & data)
857#if defined(__WXMAC__)
862#include <ApplicationServices/ApplicationServices.h>
871 wxDISABLE_DEBUG_SUPPORT();
879 ProcessSerialNumber psn = { 0, kCurrentProcess };
880 TransformProcessType(&psn, kProcessTransformToUIElementApplication);
886#elif defined(__WXGTK__) && defined(NDEBUG)
898 wxDISABLE_DEBUG_SUPPORT();
905 freopen(
"/dev/null",
"w", stdout);
906 freopen(
"/dev/null",
"w", stderr);
911#elif defined(__WXGTK__)
915wxIMPLEMENT_WX_THEME_SUPPORT
921 wxDISABLE_DEBUG_SUPPORT();
929wxIMPLEMENT_WX_THEME_SUPPORT
930extern "C" int WINAPI WinMain(HINSTANCE hInstance,
931 HINSTANCE hPrevInstance,
932 wxCmdLineArgType lpCmdLine,
935 static CommandLineArgs::MSWParser wxArgs;
939 wxDISABLE_DEBUG_SUPPORT();
941 return wxEntry(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
974#ifdef HAS_CUSTOM_URL_HANDLING
975void AudacityApp::MacOpenURL (
const wxString& url)
978 ofqueue.push_back(urlPrefix + url);
985#define ID_IPC_SERVER 6200
986#define ID_IPC_SOCKET 6201
989#define kAudacityAppTimerID 0
1037 auto proj = pProj.get();
1039 if (!fullPathStr.empty())
1042 if (wxFile::Exists(fullPathStr))
1061"%s could not be found.\n\nIt has been removed from the list of recent files.")
1071 return GuardedCall< bool >( [&]{
return MRUOpen( fullPathStr ); } );
1085 const auto &fullPathStr = history[ n ];
1119 window.RequestUserAttention();
1124 #ifdef HAS_CUSTOM_URL_HANDLING
1125 if (
name.StartsWith(urlPrefix))
1127 const auto utf8Url =
name.ToUTF8();
1128 const size_t prefixSize = urlPrefix.Length();
1130 if (utf8Url.length() <= prefixSize)
1134 { utf8Url.data() + prefixSize,
1135 utf8Url.length() - prefixSize });
1150 wxLogMessage(
wxT(
"MRUOpen failed"));
1157#if defined(__WXMSW__)
1158#define WL(lang, sublang) (lang), (sublang),
1160#define WL(lang,sublang)
1163#if wxCHECK_VERSION(3, 0, 1) && !wxCHECK_VERSION(3, 1, 6)
1164wxLanguageInfo userLangs[] =
1167 { wxLANGUAGE_USER_DEFINED,
wxT(
"eu"),
WL(0, SUBLANG_DEFAULT)
wxT(
"Basque"), wxLayout_LeftToRight },
1173#if defined(HAS_CRASH_REPORT)
1174 CrashReport::Generate(wxDebugReport::Context_Exception);
1183#pragma warning( push )
1184#pragma warning( disable : 4702)
1201 auto pException = std::current_exception();
1215 try { std::rethrow_exception( pException ); }
1227 return wxApp::OnExceptionInMainLoop();
1233#pragma warning( pop )
1254 wxConfigBase::Set(
nullptr);
1280 -> std::unique_ptr<BasicUI::WindowPlacement> {
1281 return std::make_unique<wxWidgetsWindowPlacement>(
1290 XO(
"SQLite library failed to initialize. Audacity cannot continue.") );
1298#if defined(__WXMAC__)
1300 wxSystemOptions::SetOption(wxMAC_WINDOW_PLAIN_TRANSITION, 1);
1306#if defined(__WXGTK3__) && defined(HAVE_GTK)
1307 GtkWidget *combo = gtk_combo_box_new();
1308 GtkCssProvider *provider = gtk_css_provider_new();
1309 gtk_css_provider_load_from_data(GTK_CSS_PROVIDER(provider),
1312 ".linked combobox box.linked button,\n"
1313 ".horizontal.linked entry,\n"
1314 ".horizontal.linked button,\n"
1315 ".horizontal.linked combobox box.linked button,\n"
1317 " padding-top: 0px;\n"
1318 " padding-bottom: 0px;\n"
1319 " padding-left: 4px;\n"
1320 " padding-right: 4px;\n"
1322 " font-size: 95%;\n"
1324 gtk_style_context_add_provider_for_screen(gtk_widget_get_screen(combo),
1325 GTK_STYLE_PROVIDER (provider),
1326 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
1327 g_object_unref(provider);
1328 g_object_unref(combo);
1329#elif defined(__WXGTK__) && defined(HAVE_GTK)
1330 gtk_rc_parse_string(
"style \"audacity\" {\n"
1331 " GtkButton::inner_border = { 0, 0, 0, 0 }\n"
1332 " GtkEntry::inner_border = { 0, 0, 0, 0 }\n"
1336 "widget_class \"*GtkCombo*\" style \"audacity\"");
1339 wxTheApp->SetAppName(
AppName);
1341 wxTheApp->SetAppDisplayName(
AppName);
1342 wxTheApp->SetVendorName(
AppName);
1344 ::wxInitAllImageHandlers();
1347 wxFileSystem::AddHandler(
safenew wxZipFSHandler);
1365 wxEventLoopGuarantor eventLoop;
1376#if wxCHECK_VERSION(3, 0, 1) && !wxCHECK_VERSION(3, 1, 6)
1377 for (
size_t i = 0, cnt = WXSIZEOF(userLangs); i < cnt; i++)
1379 wxLocale::AddLanguage(userLangs[i]);
1418 using namespace std::chrono;
1421 std::this_thread::sleep_for(100ms);
1434#if defined(__WXMAC__)
1435 SetExitOnFrameDelete(
false);
1441 PreferenceKey(FileNames::Operation::Temp, FileNames::PathType::_None);
1462 return std::make_unique<SettingsWX>(
1477 wxString journalFileName;
1478 const bool playingJournal = parser->Found(
"j", &journalFileName);
1480#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) && !defined(__CYGWIN__)
1481 if (!playingJournal)
1485 if (parser->Found(
wxT(
"v")))
1487 wxPrintf(
"Audacity v%s\n", AUDACITY_VERSION_STRING);
1492 if (parser->Found(
wxT(
"b"), &lval))
1494 if (lval < 256 || lval > 100000000)
1496 wxPrintf(
_(
"Block size must be within 256 to 100000000\n"));
1507 wxImage logoimage((
const char **)Audacity_splash_xpm);
1508 logoimage.Scale(logoimage.GetWidth() * (2.0/3.0), logoimage.GetHeight() * (2.0/3.0), wxIMAGE_QUALITY_HIGH);
1509 if( GetLayoutDirection() == wxLayout_RightToLeft)
1510 logoimage = logoimage.Mirror();
1511 wxBitmap logo(logoimage);
1518 bool bMaximized =
false;
1519 bool bIconized =
false;
1522 wxSplashScreen temporarywindow(
1524 wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_NO_TIMEOUT,
1528 wndRect.GetTopLeft(),
1540 temporarywindow.SetPosition( wndRect.GetTopLeft() );
1542 temporarywindow.Center();
1543 temporarywindow.SetTitle(
_(
"Audacity is starting up..."));
1544 SetTopWindow(&temporarywindow);
1545 temporarywindow.Raise();
1549 wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI);
1563 auto fileMenu = std::make_unique<wxMenu>();
1564 auto urecentMenu = std::make_unique<wxMenu>();
1565 auto recentMenu = urecentMenu.get();
1566 fileMenu->Append(wxID_NEW, wxString(
_(
"&New")) +
wxT(
"\tCtrl+N"));
1567 fileMenu->Append(wxID_OPEN, wxString(
_(
"&Open...")) +
wxT(
"\tCtrl+O"));
1568 fileMenu->AppendSubMenu(urecentMenu.release(),
_(
"Open &Recent..."));
1569 fileMenu->Append(wxID_ABOUT,
_(
"&About Audacity..."));
1570 fileMenu->Append(wxID_PREFERENCES, wxString(
_(
"&Preferences...")) +
wxT(
"\tCtrl+,"));
1573 auto menuBar = std::make_unique<wxMenuBar>();
1574 menuBar->Append(fileMenu.release(),
_(
"&File"));
1578 wxMenuBar::MacSetCommonMenuBar(menuBar.release());
1582 recentFiles.UseMenu(recentMenu);
1585 temporarywindow.Show(
false);
1589 std::vector<wxString> failedPlugins;
1593 if(!newPlugins.empty())
1597 failedPlugins =
reg.GetFailedPluginsPaths();
1629#if defined(HAVE_UPDATES_CHECK)
1639 int vMajorInit, vMinorInit, vMicroInit;
1641 if (vMajorInit != AUDACITY_VERSION || vMinorInit != AUDACITY_RELEASE
1642 || vMicroInit != AUDACITY_REVISION) {
1648 bool didRecoverAnything =
false;
1650 if (!playingJournal)
1661 if (
project && !didRecoverAnything)
1663 if (parser->Found(
wxT(
"t")))
1669 for (
size_t i = 0, cnt = parser->GetParamCount(); i < cnt; i++)
1676 if(!failedPlugins.empty())
1679 dialog->Bind(wxEVT_CLOSE_WINDOW, [dialog](wxCloseEvent&) { dialog->Destroy(); });
1692#ifdef EXPERIMENTAL_EASY_CHANGE_KEY_BINDINGS
1695 if (::wxGetMouseState().ShiftDown()) {
1712#if defined(__WXMAC__)
1720 bool permsReset =
false;
1721 gPrefs->
Read(
wxT(
"/MicrophonePermissionsReset"), &permsReset,
false);
1723 system(
"tccutil reset Microphone org.audacityteam.audacity");
1728#if defined(__WXMAC__)
1730 Bind(wxEVT_MENU_OPEN, [=](wxMenuEvent &event)
1732 wxSetlocale(LC_NUMERIC, wxString(
wxT(
"C")));
1736 Bind(wxEVT_MENU_CLOSE, [=](wxMenuEvent &event)
1743#ifdef HAS_CUSTOM_URL_HANDLING
1748 if (parser->Found(
"u", &url))
1750 auto utf8Url = url.ToUTF8();
1763 auto result = wxApp::OnRun();
1803 if(event.GetKeyCode() == WXK_ESCAPE) {
1808 auto scrubbing = scrubber.HasMark();
1813 gAudioIO->IsAudioTokenActive(token) &&
1814 gAudioIO->GetNumCaptureChannels() == 0) ||
1832 if( wxDirExists( dir ) ){
1837 wxFileName
name( dir +
"/junkname.cfg" );
1838 if(
name.Mkdir( wxS_DIR_DEFAULT , wxPATH_MKDIR_FULL ) )
1851 if (tempFromPrefs.length() > 0 && tempFromPrefs[0] !=
wxT(
'/'))
1852 tempFromPrefs =
wxT(
"");
1870 struct stat tempStatBuf;
1871 if ( lstat(temp.mb_str(), &tempStatBuf) != 0 ) {
1875 if ( geteuid() != tempStatBuf.st_uid ) {
1885"Audacity could not find a safe place to store temporary files.\nAudacity needs a place where automatic cleanup programs won't delete the temporary files.\nPlease enter an appropriate directory in the preferences dialog."));
1888"Audacity could not find a place to store temporary files.\nPlease enter an appropriate directory in the preferences dialog."));
1898"Audacity is now going to exit. Please launch Audacity again to use the new temporary directory."));
1914#if defined(__WXMSW__)
1921 wxString
name = wxString::Format(
wxT(
"audacity-lock-%s"), wxGetUserId());
1923 auto checker = std::make_unique<wxSingleInstanceChecker>();
1925 auto runningTwoCopiesStr =
XO(
"Running two copies of Audacity simultaneously may cause\ndata loss or cause your system to crash.\n\n");
1927 if (!checker->Create(
name, dir))
1933"Audacity was not able to lock the temporary files directory.\nThis folder may be in use by another copy of Audacity.\n")
1934 + runningTwoCopiesStr
1935 +
XO(
"Do you still want to start Audacity?");
1938 XO(
"Error Locking Temporary Folder"),
1939 wxYES_NO | wxICON_EXCLAMATION, NULL);
1943 else if ( checker->IsAnotherRunning() ) {
1953 if (parser->Found(
wxT(
"v")))
1955 wxPrintf(
"Audacity v%s\n", AUDACITY_VERSION_STRING);
1962 for (
size_t i = 0, cnt = parser->GetParamCount(); i < cnt; i++)
1964 wxFileName filename(parser->GetParam(i));
1965 if (filename.MakeAbsolute())
1967 filenames.push_back(filename.GetLongPath());
1971 #ifdef HAS_CUSTOM_URL_HANDLING
1973 parser->Found(
"u", &url);
1985 for (
int i = 0; i < 50; i++)
1987 std::unique_ptr<wxConnectionBase> conn{ client.MakeConnection(wxEmptyString,
IPC_APPL,
IPC_TOPIC) };
1991 #ifdef HAS_CUSTOM_URL_HANDLING
1994 if (!conn->Execute(urlPrefix + url))
1999 if (filenames.size() > 0)
2001 for (
size_t i = 0, cnt = filenames.size(); i < cnt; i++)
2003 ok = conn->Execute(filenames[i]);
2009 ok = conn->Execute(wxEmptyString);
2016 using namespace std::chrono;
2017 std::this_thread::sleep_for(10ms);
2022"The system has detected that another copy of Audacity is running.\n")
2023 + runningTwoCopiesStr
2025"Use the New or Open commands in the currently running Audacity\nprocess to open multiple projects simultaneously.\n");
2027 prompt,
XO(
"Audacity is already running"),
2028 wxOK | wxICON_ERROR);
2040#if defined(__UNIX__)
2053 bool isServer =
false;
2057 struct sembuf op = {};
2061 key_t memkey = ftok(datadir.c_str(), 0);
2062 key_t servkey = ftok(datadir.c_str(), 1);
2063 key_t lockkey = ftok(datadir.c_str(), 2);
2067 int memid = shmget(memkey,
sizeof(
int), IPC_CREAT | S_IRUSR | S_IWUSR);
2071 XO(
"Unable to create shared memory segment.\n\n"
2072 "error code=%d : \"%s\".").
Format(errno, strerror(errno)),
2073 XO(
"Audacity Startup Failure"),
2074 wxOK | wxICON_ERROR);
2079 int *portnum = (
int *) shmat(memid,
nullptr, 0);
2082 int servid = semget(servkey, 1, IPC_CREAT | S_IRUSR | S_IWUSR);
2085 int lockid = semget(lockkey, 1, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
2098 semctl(servid, 0, SETVAL, 1);
2099 semctl(lockid, 0, SETVAL, 1);
2105 op.sem_flg = SEM_UNDO;
2106 if (semop(lockid, &op, 1) == -1 || semop(servid, &op, 1) == -1)
2109 XO(
"Unable to acquire semaphores.\n\n"
2110 "This is likely due to a resource shortage\n"
2111 "and a reboot may be required."),
2112 XO(
"Audacity Startup Failure"),
2113 wxOK | wxICON_ERROR);
2122 else if (errno != EEXIST)
2125 XO(
"Unable to create semaphores.\n\n"
2126 "This is likely due to a resource shortage\n"
2127 "and a reboot may be required."),
2128 XO(
"Audacity Startup Failure"),
2129 wxOK | wxICON_ERROR);
2138 lockid = semget(lockkey, 1, 0);
2144 op.sem_flg = SEM_UNDO;
2145 if (semop(lockid, &op, 1) == -1)
2148 XO(
"Unable to acquire lock semaphore.\n\n"
2149 "This is likely due to a resource shortage\n"
2150 "and a reboot may be required."),
2151 XO(
"Audacity Startup Failure"),
2152 wxOK | wxICON_ERROR);
2162 op.sem_flg = IPC_NOWAIT | SEM_UNDO;
2163 if (semop(servid, &op, 1) == 0)
2167 else if (errno != EAGAIN)
2170 XO(
"Unable to acquire server semaphore.\n\n"
2171 "This is likely due to a resource shortage\n"
2172 "and a reboot may be required."),
2173 XO(
"Audacity Startup Failure"),
2174 wxOK | wxICON_ERROR);
2187 auto serv = std::make_unique<wxSocketServer>(addr, wxSOCKET_NOWAIT);
2188 if (serv && serv->IsOk())
2191 serv->SetNotify(wxSOCKET_CONNECTION_FLAG);
2198 *portnum = addr.Service();
2207 semop(lockid, &op, 1);
2213 XO(
"The Audacity IPC server failed to initialize.\n\n"
2214 "This is likely due to a resource shortage\n"
2215 "and a reboot may be required."),
2216 XO(
"Audacity Startup Failure"),
2217 wxOK | wxICON_ERROR);
2228 addr.Service(*portnum);
2233 semop(lockid, &op, 1);
2244 sock->SetFlags(wxSOCKET_WAITALL);
2247 sock->Connect(addr,
true);
2248 if (!sock->IsConnected())
2254 XO(
"An unrecoverable error has occurred during startup"),
2255 XO(
"Audacity Startup Failure"),
2256 wxOK | wxICON_ERROR);
2271 if (parser->Found(
wxT(
"v")))
2273 wxPrintf(
"Audacity v%s\n", AUDACITY_VERSION_STRING);
2278#ifdef HAS_CUSTOM_URL_HANDLING
2281 if (parser->Found(
wxT(
"u"), &url))
2285 url = urlPrefix + url;
2286 auto str = url.c_str().AsWChar();
2288 sock->WriteMsg(
str, (url.length() + 1) *
sizeof(*
str));
2293#if defined(__WXMAC__)
2297 for (
const auto &filename:
ofqueue)
2299 auto str = filename.c_str().AsWChar();
2300 sock->WriteMsg(
str, (filename.length() + 1) *
sizeof(*
str));
2306 for (
size_t j = 0, cnt = parser->GetParamCount(); j < cnt; ++j)
2308 wxFileName filename(parser->GetParam(j));
2309 if (filename.MakeAbsolute())
2311 const wxString param = filename.GetLongPath();
2312 sock->WriteMsg((
const wxChar *) param, (param.length() + 1) *
sizeof(wxChar));
2317 sock->WriteMsg(wxEmptyString,
sizeof(wxChar));
2336 sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
2344 wxSocketBase *sock = evt.GetSocket();
2346 if (evt.GetSocketEvent() == wxSOCKET_LOST)
2353 wxChar
name[PATH_MAX];
2354 sock->ReadMsg(&
name,
sizeof(
name));
2367 auto parser = std::make_unique<wxCmdLineParser>(
argc,
argv);
2375 parser->AddOption(
wxT(
"b"),
wxT(
"blocksize"),
_(
"set max disk block size in bytes"),
2376 wxCMD_LINE_VAL_NUMBER);
2378 const auto journalOptionDescription =
2382 _(
"replay a journal file");
2384 parser->AddOption(
wxT(
"j"),
wxT(
"journal"), journalOptionDescription);
2387 parser->AddSwitch(
wxT(
"h"),
wxT(
"help"),
_(
"this help message"),
2388 wxCMD_LINE_OPTION_HELP);
2391 parser->AddSwitch(
wxT(
"t"),
wxT(
"test"),
_(
"run self diagnostics"));
2394 parser->AddSwitch(
wxT(
"v"),
wxT(
"version"),
_(
"display Audacity version"));
2398 parser->AddParam(
_(
"audio or project file name"),
2399 wxCMD_LINE_VAL_STRING,
2400 wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL);
2402#ifdef HAS_CUSTOM_URL_HANDLING
2404 parser->AddOption(
wxT(
"u"),
wxT(
"url"),
_(
"Handle 'audacity://' url"));
2408 if (parser->Parse() == 0)
2416 bool mustVeto =
false;
2419 mustVeto = wxDialog::OSXHasModalDialogsOpen();
2430 bool force = !
event.CanVeto();
2461 bool bFalse =
false;
2477#ifdef HAS_NETWORKING
2599#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) && !defined(__CYGWIN__)
2603 bool bWantAssociateFiles =
true;
2604 if (
gPrefs->
Read(
wxT(
"/WantAssociateFiles"), &bWantAssociateFiles) &&
2605 !bWantAssociateFiles)
2611 wxRegKey associateFileTypes;
2613 auto IsDefined = [&](
const wxString &type)
2615 associateFileTypes.SetName(wxString::Format(
wxT(
"HKCR\\%s"), type));
2616 bool bKeyExists = associateFileTypes.Exists();
2620 associateFileTypes.SetName(wxString::Format(
wxT(
"HKCU\\Software\\Classes\\%s"), type));
2621 bKeyExists = associateFileTypes.Exists();
2626 auto DefineType = [&](
const wxString &type)
2628 wxString root_key =
wxT(
"HKCU\\Software\\Classes\\");
2631 associateFileTypes.SetName(wxString::Format(
wxT(
"%s%s"), root_key, type));
2632 if (!associateFileTypes.Create(
true))
2635 root_key =
wxT(
"HKCR\\");
2636 associateFileTypes.SetName(wxString::Format(
wxT(
"%s%s"), root_key, type));
2637 if (!associateFileTypes.Create(
true))
2644 if (!root_key.empty())
2646 associateFileTypes =
wxT(
"Audacity.Project");
2653 if (IsDefined(
wxT(
".aup3")) && IsDefined(
wxT(
".aup")) && IsDefined(
wxT(
"Audacity.Project")))
2663"Audacity project (.aup3) files are not currently \nassociated with Audacity. \n\nAssociate them, so they open on double-click?"),
2664 XO(
"Audacity Project Files"),
2665 wxYES_NO | wxICON_QUESTION);
2667 if (wantAssoc == wxNO)
2681 root_key = DefineType(
wxT(
".aup3"));
2682 if (root_key.empty())
2688 DefineType(
wxT(
".aup"));
2690 associateFileTypes =
wxT(
"Audacity.Project");
2691 associateFileTypes.SetName(root_key +
wxT(
"Audacity.Project"));
2692 if (!associateFileTypes.Exists())
2694 associateFileTypes.Create(
true);
2695 associateFileTypes =
wxT(
"Audacity Project File");
2698 associateFileTypes.SetName(root_key +
wxT(
"Audacity.Project\\shell"));
2699 if (!associateFileTypes.Exists())
2701 associateFileTypes.Create(
true);
2702 associateFileTypes =
wxT(
"");
2705 associateFileTypes.SetName(root_key +
wxT(
"Audacity.Project\\shell\\open"));
2706 if (!associateFileTypes.Exists())
2708 associateFileTypes.Create(
true);
2711 associateFileTypes.SetName(root_key +
wxT(
"Audacity.Project\\shell\\open\\command"));
2712 wxString tmpRegAudPath;
2713 if(associateFileTypes.Exists())
2715 tmpRegAudPath = associateFileTypes.QueryDefaultValue().Lower();
2718 if (!associateFileTypes.Exists() ||
2719 (tmpRegAudPath.Find(
wxT(
"audacity.exe")) >= 0))
2721 associateFileTypes.Create(
true);
2722 associateFileTypes = (wxString)
argv[0] + (wxString)
wxT(
" \"%1\"");
2729 associateFileTypes.SetName(root_key +
wxT(
"Audacity.Project\\shell\\open\\ddeexec"));
2730 if (!associateFileTypes.Exists())
2732 associateFileTypes.Create(
true);
2733 associateFileTypes =
wxT(
"%1");
2736 associateFileTypes.SetName(root_key +
wxT(
"Audacity.Project\\shell\\open\\ddeexec\\Application"));
2737 if (!associateFileTypes.Exists())
2739 associateFileTypes.Create(
true);
2743 associateFileTypes.SetName(root_key +
wxT(
"Audacity.Project\\shell\\open\\ddeexec\\Topic"));
2744 if (!associateFileTypes.Exists())
2746 associateFileTypes.Create(
true);
2756 static std::once_flag configSetupFlag;
2757 std::call_once(configSetupFlag, [&]{
2760 wxTheApp->GetAppName(), wxEmptyString,
2761 configFileName.GetFullPath(),
2762 wxEmptyString, wxCONFIG_USE_LOCAL_FILE);
2763 wxConfigBase::Set(
gConfig.get());
2765 return std::make_unique<SettingsWX>(
gConfig);
AUDACITY_DLL_API std::weak_ptr< AudacityProject > GetActiveProject()
Handle changing of active project and keep global project pointer.
EVT_MENU(OnSetPlayRegionToSelectionID, AdornedRulerPanel::OnSetPlayRegionToSelection) EVT_COMMAND(OnTogglePinnedStateID
Headers and event table macros for AppCommandEvent.
#define EVT_APP_COMMAND(winid, fn)
void SetToExtantDirectory(wxString &result, const wxString &dir)
int main(int argc, char *argv[])
#define WL(lang, sublang)
EVT_MENU_RANGE(FileHistory::ID_RECENT_FIRST, FileHistory::ID_RECENT_LAST, AudacityApp::OnMRUFile) bool AudacityApp
#define kAudacityAppTimerID
static void QuitAudacity(bool bForce)
static bool CloseAllProjects(bool force)
static std::shared_ptr< wxConfigBase > gConfig
static wxArrayString ofqueue
static audacity::ApplicationSettings::Scope applicationSettingsScope
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
bool ShowAutoRecoveryDialogIfNeeded(AudacityProject *&pproj, bool *didRecoverAnything)
void RunBenchmark(wxWindow *parent, AudacityProject &project)
Contains declarations for the CommandHandler class.
PrefsPanel::Factory DirectoriesPrefsFactory()
const TranslatableString name
BoolSetting SkipEffectsScanAtStartup
PrefsPanel::Factory KeyConfigPrefsFactory(const CommandID &name)
std::unique_ptr< Character[], freer > MallocString
std::unique_ptr< T, Destroyer< T > > Destroy_ptr
a convenience for using Destroyer
const std::wstring AppName
This program's name.
Declare a class for performing HTTP requests.
void SetPreferencesVersion(int vMajor, int vMinor, int vMicro)
audacity::BasicSettings * gPrefs
void GetPreferencesVersion(int &vMajor, int &vMinor, int &vMicro)
void InitPreferences(std::unique_ptr< audacity::BasicSettings > uPrefs)
void ResetPreferences()
Call this to reset preferences to an (almost)-"new" default state.
#define AUDACITY_PREFS_VERSION_STRING
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,...
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 ...
accessors for certain important windows associated with each project
declares abstract base class Track, TrackList, and iterators over TrackList
Declare a class that handles managing of updates.
The AboutDialog shows the program version and developer credits.
static AboutDialog * ActiveIntance()
const_iterator begin() const
An event 'envelope' for sending Command objects through the wxwidgets event loop.
void HandleAppInitialized()
AudacityApp is the 'main' class for Audacity.
void OnQueryEndSession(wxCloseEvent &event)
void OnMenuExit(wxCommandEvent &event)
void MacPrintFile(const wxString &fileName) override
bool OSXIsGUIApplication() override
bool MRUOpen(const FilePath &fileName)
void OnKeyDown(wxKeyEvent &event)
void OnMenuPreferences(wxCommandEvent &event)
bool OnExceptionInMainLoop() override
void OnServerEvent(wxSocketEvent &evt)
void OnEndSession(wxCloseEvent &event)
void MacNewFile() override
void OnTimer(wxTimerEvent &event)
bool Initialize(int &argc, wxChar **argv) override
std::unique_ptr< CommandHandler > mCmdHandler
std::unique_ptr< wxSingleInstanceChecker > mChecker
void MacFinishLaunching()
Observer::Subscription mThemeChangeSubscription
void OnMRUFile(wxCommandEvent &event)
void AssociateFileTypes()
void OnMenuOpen(wxCommandEvent &event)
std::unique_ptr< wxCmdLineParser > ParseCommandLine()
void OnFatalException() override
void OnIdle(wxIdleEvent &)
void OnMRUClear(wxCommandEvent &event)
int OnExit(void) override
void OnMenuAbout(wxCommandEvent &event)
bool CreateSingleInstanceChecker(const wxString &dir)
void InitCommandHandler()
void MacOpenFile(const wxString &fileName) override
void OnMenuNew(wxCommandEvent &event)
static void OnThemeChange(struct ThemeChangeMessage)
bool SafeMRUOpen(const wxString &fileName)
void OnReceiveCommand(AppCommandEvent &event)
std::unique_ptr< IPCServ > mIPCServ
void OnSocketEvent(wxSocketEvent &evt)
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 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.
static AudacityLogger * Get()
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
static ExportPluginRegistry & Get()
Similar to wxFileHistory, but customized to our needs.
void Save(audacity::BasicSettings &config)
static FileHistory & Global()
static void Destroy()
Destroys the dialog to prevent Audacity from hanging on exit.
static result_type Call(Arguments &&...arguments)
Null check of the installed function is done for you.
typename GlobalVariable< Tag, const std::function< Signature >, Default, Options... >::Scope Scope
bool OnExec(const wxString &WXUNUSED(topic), const wxString &data)
wxConnectionBase * OnAcceptConnection(const wxString &topic) override
IPCServ(const wxString &appl)
static void Destroy()
Destroys the log window (if any)
static ModuleManager & Get()
int Dispatch(ModuleDispatchTypes type)
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
static PendingTracks & Get(AudacityProject &project)
void ClearPendingTracks(std::vector< std::shared_ptr< Track > > *pAdded=nullptr)
Forget pending track additions and changes;.
static bool IsHostProcess()
Returns true if current process is considered to be a plugin host process.
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
int GetAudioIOToken() const
static ProjectAudioIO & Get(AudacityProject &project)
void Stop(bool stopStream=true)
static ProjectAudioManager & Get(AudacityProject &project)
static bool InitializeSQL()
static bool IsAlreadyOpen(const FilePath &projPathName)
static ProjectHistory & Get(AudacityProject &project)
static AudacityProject * New()
static void SaveWindowSize()
static void OpenFiles(AudacityProject *proj)
static AudacityProject * OpenProject(AudacityProject *pGivenProject, const FilePath &fileNameArg, bool addtohistory, bool reuseNonemptyProject)
Open a file into an AudacityProject, returning the project, or nullptr for failure.
static void SetClosingAll(bool closing)
static ProjectSettings & Get(AudacityProject &project)
bool GetShowSplashScreen() const
static Scrubber & Get(AudacityProject &project)
static void SetMaxDiskBlockSize(size_t bytes)
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined */
static bool LoadPreferredTheme()
bool RegisterScheme(std::string_view scheme)
Associates a new scheme with Audacity.
static URLSchemesRegistry & Get()
Retrieves the registry instance.
void HandleURL(std::string_view url)
static void Start(bool suppressModal)
static Viewport & Get(AudacityProject &project)
static void Show(AudacityProject &project)
virtual bool Flush() noexcept=0
virtual bool Exists(const wxString &key) const
Returns true if group or entry exists.
GroupScope BeginGroup(const wxString &prefix)
Appends a prefix to the current group or sets a new absolute path. Group that was set as current befo...
bool DeleteGroup(const wxString &key)
Deletes specified group if exists.
virtual bool Write(const wxString &key, bool value)=0
bool DeleteEntry(const wxString &key)
Deletes specified entry if exists.
virtual bool Read(const wxString &key, bool *value) const =0
virtual wxArrayString GetChildGroups() const =0
Returns all child groups within the current group.
static NetworkManager & GetInstance()
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
Services * Install(Services *pInstance)
Install an implementation; return the previously installed instance.
void CallAfter(Action action)
Schedule an action to be done later, and in the main thread.
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
UTILITY_API const char *const * argv
A copy of argv; responsibility of application startup to assign it.
UTILITY_API int argc
A copy of argc; responsibility of application startup to assign it.
IMPORT_EXPORT_API ExportResult Show(ExportTask exportTask)
FILES_API FilePath Configuration()
FILES_API FilePath ResourcesDir()
FILES_API wxString PreferenceKey(FileNames::Operation op, FileNames::PathType type)
FILES_API FilePath StateDir()
Audacity user state directory.
FILES_API void InitializePathList()
FILES_API FilePath DataDir()
Audacity user data directory.
FILES_API void UpdateDefaultPath(Operation op, const FilePath &path)
FILES_API const FilePaths & AudacityPathList()
A list of directories that should be searched for Audacity files (plug-ins, help files,...
AUDACITY_DLL_API wxString SetLang(const wxString &lang)
bool sOSXIsGUIApplication
bool Begin(const FilePath &dataDir)
void SetInputFileName(const wxString &path)
wxString GetSystemLanguageCode(const FilePaths &pathList)
FILES_API bool IsTempDirectoryNameOK(const FilePath &Name)
FILES_API wxString TempDir()
FILES_API void ResetTempDir()
FILES_API const FilePath & DefaultTempDir()
THEME_RESOURCES_API void Load()
auto Dispatch(Head_t< Types > &object, const TupleLike &functions, Args &&... args) -> std::enable_if_t< TypeListCheck_v< Types >, R >
void PopulatePreferences()
BuiltinCommandsModule::Registration< CompareAudioCommand > reg
static CommandContext::TargetFactory::SubstituteInUnique< InteractiveOutputTargets > scope
std::string ToUTF8(const std::wstring &wstr)