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>
118#if defined(HAVE_UPDATES_CHECK)
130#ifdef EXPERIMENTAL_EASY_CHANGE_KEY_BINDINGS
142#if defined(USE_BREAKPAD)
144#elif defined(USE_CRASHPAD)
148#ifdef EXPERIMENTAL_SCOREALIGN
156 static char*THIS_FILE= __FILE__;
157 #define new new(_NORMAL_BLOCK, THIS_FILE, __LINE__)
163#include "../images/Audacity-splash.xpm"
171#ifdef HAS_CUSTOM_URL_HANDLING
186static void wxOnAssert(
const wxChar *fileName,
int lineNumber,
const wxChar *msg)
189 wxPrintf(
"ASSERTION FAILED: %s\n%s: %d\n", (
const char *)wxString(msg).mb_str(), (
const char *)wxString(fileName).mb_str(), lineNumber);
191 wxPrintf(
"ASSERTION FAILED!\n%s: %d\n", (
const char *)wxString(fileName).mb_str(), lineNumber);
207 bool resetPrefs =
false;
208 wxString langCode =
gPrefs->
Read(
wxT(
"/Locale/Language"), wxEmptyString);
209 bool writeLang =
false;
213 wxT(
"FirstTime.ini"));
216 const wxString fullPath{
fn.GetFullPath()};
220 wxCONFIG_USE_LOCAL_FILE);
224 if (ini.Read(
wxT(
"/FromInno/Language"), &lang) && !lang.empty())
232 langCode.Replace(
wxT(
"0"),
wxT(
"@"));
235 ini.Read(
wxT(
"/FromInno/ResetPrefs"), &resetPrefs,
false);
237 bool gone = wxRemoveFile(fullPath);
241 XO(
"Failed to remove %s").
Format(fullPath),
247 if (langCode.empty())
270 bool newPrefsInitialized =
false;
271 gPrefs->
Read(
wxT(
"/NewPrefsInitialized"), &newPrefsInitialized,
false);
272 if (newPrefsInitialized) {
296 (vMajor == 1 && vMinor < 3) ||
297 (vMajor == 1 && vMinor == 3 && vMicro < 13)) {
320 long dock, order, show, x, y, w, h;
336 const auto orderKey = group +
wxT(
"/Order");
337 if(
gPrefs->
Read(orderKey, &orderValue) && orderValue >= order)
365 if ((0<vMajor && vMajor < 2) ||
366 (vMajor == 2 && vMinor < 2))
372 if ((0<vMajor && vMajor < 2) ||
373 (vMajor == 2 && vMinor < 4))
387 if (std::pair{ vMajor, vMinor } < std::pair{ 3, 1 } ) {
392 if(std::pair{vMajor, vMinor} < std::pair{3, 2})
404 if(std::tuple{ vMajor, vMinor, vMicro } < std::tuple{ 3, 2, 3 })
412 if (std::pair { vMajor, vMinor } < std::pair { 3, 4 })
420 if (std::pair { vMajor, vMinor } < std::pair { 3, 5 })
426 if (std::pair { vMajor, vMinor } < std::pair { 3, 6 })
444#if defined(USE_BREAKPAD) || defined(USE_CRASHPAD)
445 wxFileName databasePath;
447 databasePath.AppendDir(
"crashreports");
448 databasePath.Mkdir(wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL);
450 if(databasePath.DirExists())
452 const auto sentryRelease = wxString::Format(
453 "audacity@%d.%d.%d", AUDACITY_VERSION, AUDACITY_RELEASE, AUDACITY_REVISION);
454#if defined(USE_BREAKPAD)
458 #if defined(CRASH_REPORT_URL)
462 {
"version", wxString(AUDACITY_VERSION_STRING).ToUTF8().data() },
463 {
"sentry[release]", sentryRelease.ToUTF8().data() }
466#elif defined(USE_CRASHPAD)
470 const wxFileName crashpadHandlerPath(executableDir, CRASHPAD_HANDLER_NAME);
471 const wxFileName crashreporterPath(executableDir, CRASHREPORTER_NAME);
472 const wxFileName metricsDir = databasePath;
473 std::vector<std::string> arguments = {
474 wxString::Format(
"--crashreporter-path=%s", crashreporterPath.GetFullPath()).ToUTF8().data(),
475#if defined(CRASH_REPORT_URL)
477 "--crashreporter-argument=-u=%s",
478 CRASH_REPORT_URL).ToUTF8().data(),
480 "--crashreporter-argument=-a=version=\"%s\",sentry[release]=\"%s\"",
481 AUDACITY_VERSION_STRING,
482 sentryRelease).ToUTF8().data()
492 catch (std::exception& e)
494 wxLogError(
"Crashpad init error: %s", e.what());
498#elif !defined(_DEBUG)
499#if defined(HAS_CRASH_REPORT)
500#if defined(wxUSE_ON_FATAL_EXCEPTION) && wxUSE_ON_FATAL_EXCEPTION
501 wxHandleFatalExceptions();
547 wxTheApp->SetExitOnFrameDelete(
true);
579#ifdef EXPERIMENTAL_SCOREALIGN
580 CloseScoreAlignDialog();
586 #if !defined(__WXMAC__)
600 logger->SaveLog(logFile.GetFullPath());
604 std::unique_ptr<wxLog>{ wxLog::SetActiveTarget(NULL) };
617#if defined(__WXGTK__) && defined(HAVE_GTK)
637#include <glib-object.h>
639typedef struct _GnomeProgram GnomeProgram;
640typedef struct _GnomeModuleInfo GnomeModuleInfo;
641typedef struct _GnomeClient GnomeClient;
653 GNOME_INTERACT_ERRORS,
663typedef GnomeProgram * (*_gnome_program_init_fn)(
const char *,
665 const GnomeModuleInfo *,
670typedef const GnomeModuleInfo * (*_libgnomeui_module_info_get_fn)();
671typedef GnomeClient * (*_gnome_master_client_fn)(void);
672typedef void (*GnomeInteractFunction)(GnomeClient *,
676typedef void (*_gnome_client_request_interaction_fn)(GnomeClient *,
678 GnomeInteractFunction,
680typedef void (*_gnome_interaction_key_return_fn)(gint, gboolean);
682static _gnome_client_request_interaction_fn gnome_client_request_interaction;
683static _gnome_interaction_key_return_fn gnome_interaction_key_return;
685static void interact_cb(GnomeClient * ,
690 wxCloseEvent e(wxEVT_QUERY_END_SESSION, wxID_ANY);
696 gnome_interaction_key_return(
key, e.GetVeto());
699static gboolean save_yourself_cb(GnomeClient *client,
703 GnomeInteractStyle interact,
707 if (!shutdown || interact != GNOME_INTERACT_ANY) {
715 gnome_client_request_interaction(client,
729 const char *libgnomeui =
"libgnomeui-2.so";
730 const char *libgnome =
"libgnome-2.so";
732 const char *libgnomeui =
"libgnomeui-2.so.0";
733 const char *libgnome =
"libgnome-2.so.0";
736 mArgv[0].reset(strdup(
"Audacity"));
738 mGnomeui = dlopen(libgnomeui, RTLD_NOW);
743 mGnome = dlopen(libgnome, RTLD_NOW);
748 _gnome_program_init_fn gnome_program_init = (_gnome_program_init_fn)
749 dlsym(mGnome,
"gnome_program_init");
750 _libgnomeui_module_info_get_fn libgnomeui_module_info_get = (_libgnomeui_module_info_get_fn)
751 dlsym(mGnomeui,
"libgnomeui_module_info_get");
752 _gnome_master_client_fn gnome_master_client = (_gnome_master_client_fn)
753 dlsym(mGnomeui,
"gnome_master_client");
755 gnome_client_request_interaction = (_gnome_client_request_interaction_fn)
756 dlsym(mGnomeui,
"gnome_client_request_interaction");
757 gnome_interaction_key_return = (_gnome_interaction_key_return_fn)
758 dlsym(mGnomeui,
"gnome_interaction_key_return");
761 if (!gnome_program_init || !libgnomeui_module_info_get) {
765 gnome_program_init(mArgv[0].get(),
767 libgnomeui_module_info_get(),
769 reinterpret_cast<char**
>(mArgv),
772 mClient = gnome_master_client();
773 if (mClient == NULL) {
777 g_signal_connect(mClient,
"save-yourself", G_CALLBACK(save_yourself_cb), NULL);
780 virtual ~GnomeShutdown()
790 GnomeClient *mClient;
795GnomeShutdown GnomeShutdownInstance;
808#define IPC_APPL wxT("audacity")
809#define IPC_TOPIC wxT("System")
823 bool OnExec(
const wxString & WXUNUSED(topic),
824 const wxString & data)
858#if defined(__WXMAC__)
863#include <ApplicationServices/ApplicationServices.h>
872 wxDISABLE_DEBUG_SUPPORT();
880 ProcessSerialNumber psn = { 0, kCurrentProcess };
881 TransformProcessType(&psn, kProcessTransformToUIElementApplication);
887#elif defined(__WXGTK__) && defined(NDEBUG)
899 wxDISABLE_DEBUG_SUPPORT();
906 freopen(
"/dev/null",
"w", stdout);
907 freopen(
"/dev/null",
"w", stderr);
912#elif defined(__WXGTK__)
916wxIMPLEMENT_WX_THEME_SUPPORT
922 wxDISABLE_DEBUG_SUPPORT();
930wxIMPLEMENT_WX_THEME_SUPPORT
931extern "C" int WINAPI WinMain(HINSTANCE hInstance,
932 HINSTANCE hPrevInstance,
933 wxCmdLineArgType lpCmdLine,
936 static CommandLineArgs::MSWParser wxArgs;
940 wxDISABLE_DEBUG_SUPPORT();
942 return wxEntry(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
975#ifdef HAS_CUSTOM_URL_HANDLING
976void AudacityApp::MacOpenURL (
const wxString& url)
986#define ID_IPC_SERVER 6200
987#define ID_IPC_SOCKET 6201
990#define kAudacityAppTimerID 0
1038 auto proj = pProj.get();
1040 if (!fullPathStr.empty())
1043 if (wxFile::Exists(fullPathStr))
1062"%s could not be found.\n\nIt has been removed from the list of recent files.")
1072 return GuardedCall< bool >( [&]{
return MRUOpen( fullPathStr ); } );
1086 const auto &fullPathStr = history[ n ];
1120 window.RequestUserAttention();
1125 #ifdef HAS_CUSTOM_URL_HANDLING
1128 const auto utf8Url =
name.ToUTF8();
1129 const size_t prefixSize =
urlPrefix.Length();
1131 if (utf8Url.length() <= prefixSize)
1135 { utf8Url.data() + prefixSize,
1136 utf8Url.length() - prefixSize });
1151 wxLogMessage(
wxT(
"MRUOpen failed"));
1158#if defined(__WXMSW__)
1159#define WL(lang, sublang) (lang), (sublang),
1161#define WL(lang,sublang)
1164#if wxCHECK_VERSION(3, 0, 1) && !wxCHECK_VERSION(3, 1, 6)
1165wxLanguageInfo userLangs[] =
1168 { wxLANGUAGE_USER_DEFINED,
wxT(
"eu"),
WL(0, SUBLANG_DEFAULT)
wxT(
"Basque"), wxLayout_LeftToRight },
1174#if defined(HAS_CRASH_REPORT)
1175 CrashReport::Generate(wxDebugReport::Context_Exception);
1184#pragma warning( push )
1185#pragma warning( disable : 4702)
1202 auto pException = std::current_exception();
1216 try { std::rethrow_exception( pException ); }
1228 return wxApp::OnExceptionInMainLoop();
1234#pragma warning( pop )
1255 wxConfigBase::Set(
nullptr);
1275 bool bMaximized =
false;
1276 bool bIconized =
false;
1280 wxImage logoimage((
const char**)Audacity_splash_xpm);
1281 logoimage.Scale(logoimage.GetWidth() * (2.0 / 3.0), logoimage.GetHeight() * (2.0 / 3.0), wxIMAGE_QUALITY_HIGH);
1282 if (GetLayoutDirection() == wxLayout_RightToLeft)
1283 logoimage = logoimage.Mirror();
1284 wxBitmap logo(logoimage);
1288 wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_NO_TIMEOUT,
1292 wndRect.GetTopLeft(),
1298 mSplashScreen->Bind(wxEVT_DESTROY, [
this](wxWindowDestroyEvent& event) {
1322 const int fadeDurationMs = 120;
1323 const int fadeStepMs = 16;
1325 const int maxTransparency = 255;
1326 const int numSteps = fadeDurationMs / fadeStepMs;
1327 const int transparencyDecrement = maxTransparency / numSteps;
1329 int currentAlpha = maxTransparency;
1344 mSplashTimer.Bind(wxEVT_TIMER, [
this, currentAlpha, transparencyDecrement](wxTimerEvent& evt)
mutable {
1345 currentAlpha -= transparencyDecrement;
1349 else if (currentAlpha <= 0) {
1355 mSplashScreen->SetTransparent(currentAlpha);
1370 -> std::unique_ptr<BasicUI::WindowPlacement> {
1371 return std::make_unique<wxWidgetsWindowPlacement>(
1380 XO(
"SQLite library failed to initialize. Audacity cannot continue.") );
1388#if defined(__WXMAC__)
1390 wxSystemOptions::SetOption(wxMAC_WINDOW_PLAIN_TRANSITION, 1);
1396#if defined(__WXGTK3__) && defined(HAVE_GTK)
1397 GtkWidget *combo = gtk_combo_box_new();
1398 GtkCssProvider *provider = gtk_css_provider_new();
1399 gtk_css_provider_load_from_data(GTK_CSS_PROVIDER(provider),
1402 ".linked combobox box.linked button,\n"
1403 ".horizontal.linked entry,\n"
1404 ".horizontal.linked button,\n"
1405 ".horizontal.linked combobox box.linked button,\n"
1407 " padding-top: 0px;\n"
1408 " padding-bottom: 0px;\n"
1409 " padding-left: 4px;\n"
1410 " padding-right: 4px;\n"
1412 " font-size: 95%;\n"
1414 gtk_style_context_add_provider_for_screen(gtk_widget_get_screen(combo),
1415 GTK_STYLE_PROVIDER (provider),
1416 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
1417 g_object_unref(provider);
1418 g_object_unref(combo);
1419#elif defined(__WXGTK__) && defined(HAVE_GTK)
1420 gtk_rc_parse_string(
"style \"audacity\" {\n"
1421 " GtkButton::inner_border = { 0, 0, 0, 0 }\n"
1422 " GtkEntry::inner_border = { 0, 0, 0, 0 }\n"
1426 "widget_class \"*GtkCombo*\" style \"audacity\"");
1429 wxTheApp->SetAppName(
AppName);
1431 wxTheApp->SetAppDisplayName(
AppName);
1432 wxTheApp->SetVendorName(
AppName);
1434 ::wxInitAllImageHandlers();
1437 wxFileSystem::AddHandler(
safenew wxZipFSHandler);
1457 wxEventLoopGuarantor eventLoop;
1468#if wxCHECK_VERSION(3, 0, 1) && !wxCHECK_VERSION(3, 1, 6)
1469 for (
size_t i = 0, cnt = WXSIZEOF(userLangs); i < cnt; i++)
1471 wxLocale::AddLanguage(userLangs[i]);
1510 using namespace std::chrono;
1513 std::this_thread::sleep_for(100ms);
1526#if defined(__WXMAC__)
1527 SetExitOnFrameDelete(
false);
1533 PreferenceKey(FileNames::Operation::Temp, FileNames::PathType::_None);
1554 return std::make_unique<SettingsWX>(
1569 wxString journalFileName;
1570 const bool playingJournal = parser->Found(
"j", &journalFileName);
1572#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) && !defined(__CYGWIN__)
1573 if (!playingJournal)
1577 if (parser->Found(
wxT(
"v")))
1579 wxPrintf(
"Audacity v%s\n", AUDACITY_VERSION_STRING);
1584 if (parser->Found(
wxT(
"b"), &lval))
1586 if (lval < 256 || lval > 100000000)
1588 wxPrintf(
_(
"Block size must be within 256 to 100000000\n"));
1606 wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI | wxEVT_CATEGORY_USER_INPUT);
1620 auto fileMenu = std::make_unique<wxMenu>();
1621 auto urecentMenu = std::make_unique<wxMenu>();
1622 auto recentMenu = urecentMenu.get();
1623 fileMenu->Append(wxID_NEW, wxString(
_(
"&New")) +
wxT(
"\tCtrl+N"));
1624 fileMenu->Append(wxID_OPEN, wxString(
_(
"&Open...")) +
wxT(
"\tCtrl+O"));
1625 fileMenu->AppendSubMenu(urecentMenu.release(),
_(
"Open &Recent..."));
1626 fileMenu->Append(wxID_ABOUT,
_(
"&About Audacity..."));
1627 fileMenu->Append(wxID_PREFERENCES, wxString(
_(
"&Preferences...")) +
wxT(
"\tCtrl+,"));
1630 auto menuBar = std::make_unique<wxMenuBar>();
1631 menuBar->Append(fileMenu.release(),
_(
"&File"));
1635 wxMenuBar::MacSetCommonMenuBar(menuBar.release());
1639 recentFiles.UseMenu(recentMenu);
1645 std::vector<wxString> failedPlugins;
1650 if(!newPlugins.empty())
1654 failedPlugins =
reg.GetFailedPluginsPaths();
1687 bool splashFadeOut = !playingJournal;
1690#if defined(HAVE_UPDATES_CHECK)
1700 int vMajorInit, vMinorInit, vMicroInit;
1702 if (vMajorInit != AUDACITY_VERSION || vMinorInit != AUDACITY_RELEASE
1703 || vMicroInit != AUDACITY_REVISION) {
1709 bool didRecoverAnything =
false;
1711 if (!playingJournal)
1722 if (
project && !didRecoverAnything)
1724 if (parser->Found(
wxT(
"t")))
1730 for (
size_t i = 0, cnt = parser->GetParamCount(); i < cnt; i++)
1737 if(!failedPlugins.empty())
1740 dialog->Bind(wxEVT_CLOSE_WINDOW, [dialog](wxCloseEvent&) { dialog->Destroy(); });
1753#ifdef EXPERIMENTAL_EASY_CHANGE_KEY_BINDINGS
1756 if (::wxGetMouseState().ShiftDown()) {
1773#if defined(__WXMAC__)
1781 bool permsReset =
false;
1782 gPrefs->
Read(
wxT(
"/MicrophonePermissionsReset"), &permsReset,
false);
1784 system(
"tccutil reset Microphone org.audacityteam.audacity");
1789#if defined(__WXMAC__)
1791 Bind(wxEVT_MENU_OPEN, [=](wxMenuEvent &event)
1793 wxSetlocale(LC_NUMERIC, wxString(
wxT(
"C")));
1797 Bind(wxEVT_MENU_CLOSE, [=](wxMenuEvent &event)
1804#ifdef HAS_CUSTOM_URL_HANDLING
1809 if (parser->Found(
"u", &url))
1811 auto utf8Url = url.ToUTF8();
1824 auto result = wxApp::OnRun();
1864 if(event.GetKeyCode() == WXK_ESCAPE) {
1869 auto scrubbing = scrubber.HasMark();
1874 gAudioIO->IsAudioTokenActive(token) &&
1875 gAudioIO->GetNumCaptureChannels() == 0) ||
1893 if( wxDirExists( dir ) ){
1898 wxFileName
name( dir +
"/junkname.cfg" );
1899 if(
name.Mkdir( wxS_DIR_DEFAULT , wxPATH_MKDIR_FULL ) )
1912 if (tempFromPrefs.length() > 0 && tempFromPrefs[0] !=
wxT(
'/'))
1913 tempFromPrefs =
wxT(
"");
1931 struct stat tempStatBuf;
1932 if ( lstat(temp.mb_str(), &tempStatBuf) != 0 ) {
1936 if ( geteuid() != tempStatBuf.st_uid ) {
1946"Audacity could not find a safe place to store temporary files.\nAudacity needs a place where automatic cleanup programs won't delete the temporary files.\nPlease enter an appropriate directory in the preferences dialog."));
1949"Audacity could not find a place to store temporary files.\nPlease enter an appropriate directory in the preferences dialog."));
1959"Audacity is now going to exit. Please launch Audacity again to use the new temporary directory."));
1975#if defined(__WXMSW__)
1982 wxString
name = wxString::Format(
wxT(
"audacity-lock-%s"), wxGetUserId());
1984 auto checker = std::make_unique<wxSingleInstanceChecker>();
1986 auto runningTwoCopiesStr =
XO(
"Running two copies of Audacity simultaneously may cause\ndata loss or cause your system to crash.\n\n");
1988 if (!checker->Create(
name, dir))
1994"Audacity was not able to lock the temporary files directory.\nThis folder may be in use by another copy of Audacity.\n")
1995 + runningTwoCopiesStr
1996 +
XO(
"Do you still want to start Audacity?");
1999 XO(
"Error Locking Temporary Folder"),
2000 wxYES_NO | wxICON_EXCLAMATION, NULL);
2004 else if ( checker->IsAnotherRunning() ) {
2014 if (parser->Found(
wxT(
"v")))
2016 wxPrintf(
"Audacity v%s\n", AUDACITY_VERSION_STRING);
2023 for (
size_t i = 0, cnt = parser->GetParamCount(); i < cnt; i++)
2025 wxFileName filename(parser->GetParam(i));
2026 if (filename.MakeAbsolute())
2028 filenames.push_back(filename.GetLongPath());
2032 #ifdef HAS_CUSTOM_URL_HANDLING
2034 parser->Found(
"u", &url);
2046 for (
int i = 0; i < 50; i++)
2048 std::unique_ptr<wxConnectionBase> conn{ client.MakeConnection(wxEmptyString,
IPC_APPL,
IPC_TOPIC) };
2052 #ifdef HAS_CUSTOM_URL_HANDLING
2060 if (filenames.size() > 0)
2062 for (
size_t i = 0, cnt = filenames.size(); i < cnt; i++)
2064 ok = conn->Execute(filenames[i]);
2070 ok = conn->Execute(wxEmptyString);
2077 using namespace std::chrono;
2078 std::this_thread::sleep_for(10ms);
2083"The system has detected that another copy of Audacity is running.\n")
2084 + runningTwoCopiesStr
2086"Use the New or Open commands in the currently running Audacity\nprocess to open multiple projects simultaneously.\n");
2088 prompt,
XO(
"Audacity is already running"),
2089 wxOK | wxICON_ERROR);
2101#if defined(__UNIX__)
2114 bool isServer =
false;
2118 struct sembuf op = {};
2122 key_t memkey = ftok(datadir.c_str(), 0);
2123 key_t servkey = ftok(datadir.c_str(), 1);
2124 key_t lockkey = ftok(datadir.c_str(), 2);
2128 int memid = shmget(memkey,
sizeof(
int), IPC_CREAT | S_IRUSR | S_IWUSR);
2132 XO(
"Unable to create shared memory segment.\n\n"
2133 "error code=%d : \"%s\".").
Format(errno, strerror(errno)),
2134 XO(
"Audacity Startup Failure"),
2135 wxOK | wxICON_ERROR);
2140 int *portnum = (
int *) shmat(memid,
nullptr, 0);
2143 int servid = semget(servkey, 1, IPC_CREAT | S_IRUSR | S_IWUSR);
2146 int lockid = semget(lockkey, 1, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
2159 semctl(servid, 0, SETVAL, 1);
2160 semctl(lockid, 0, SETVAL, 1);
2166 op.sem_flg = SEM_UNDO;
2167 if (semop(lockid, &op, 1) == -1 || semop(servid, &op, 1) == -1)
2170 XO(
"Unable to acquire semaphores.\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);
2183 else if (errno != EEXIST)
2186 XO(
"Unable to create semaphores.\n\n"
2187 "This is likely due to a resource shortage\n"
2188 "and a reboot may be required."),
2189 XO(
"Audacity Startup Failure"),
2190 wxOK | wxICON_ERROR);
2199 lockid = semget(lockkey, 1, 0);
2205 op.sem_flg = SEM_UNDO;
2206 if (semop(lockid, &op, 1) == -1)
2209 XO(
"Unable to acquire lock semaphore.\n\n"
2210 "This is likely due to a resource shortage\n"
2211 "and a reboot may be required."),
2212 XO(
"Audacity Startup Failure"),
2213 wxOK | wxICON_ERROR);
2223 op.sem_flg = IPC_NOWAIT | SEM_UNDO;
2224 if (semop(servid, &op, 1) == 0)
2228 else if (errno != EAGAIN)
2231 XO(
"Unable to acquire server semaphore.\n\n"
2232 "This is likely due to a resource shortage\n"
2233 "and a reboot may be required."),
2234 XO(
"Audacity Startup Failure"),
2235 wxOK | wxICON_ERROR);
2248 auto serv = std::make_unique<wxSocketServer>(addr, wxSOCKET_NOWAIT);
2249 if (serv && serv->IsOk())
2252 serv->SetNotify(wxSOCKET_CONNECTION_FLAG);
2259 *portnum = addr.Service();
2268 semop(lockid, &op, 1);
2274 XO(
"The Audacity IPC server failed to initialize.\n\n"
2275 "This is likely due to a resource shortage\n"
2276 "and a reboot may be required."),
2277 XO(
"Audacity Startup Failure"),
2278 wxOK | wxICON_ERROR);
2289 addr.Service(*portnum);
2294 semop(lockid, &op, 1);
2305 sock->SetFlags(wxSOCKET_WAITALL);
2308 sock->Connect(addr,
true);
2309 if (!sock->IsConnected())
2315 XO(
"An unrecoverable error has occurred during startup"),
2316 XO(
"Audacity Startup Failure"),
2317 wxOK | wxICON_ERROR);
2332 if (parser->Found(
wxT(
"v")))
2334 wxPrintf(
"Audacity v%s\n", AUDACITY_VERSION_STRING);
2339#ifdef HAS_CUSTOM_URL_HANDLING
2342 if (parser->Found(
wxT(
"u"), &url))
2347 auto str = url.c_str().AsWChar();
2349 sock->WriteMsg(
str, (url.length() + 1) *
sizeof(*
str));
2354#if defined(__WXMAC__)
2358 for (
const auto &filename:
ofqueue)
2360 auto str = filename.c_str().AsWChar();
2361 sock->WriteMsg(
str, (filename.length() + 1) *
sizeof(*
str));
2367 for (
size_t j = 0, cnt = parser->GetParamCount(); j < cnt; ++j)
2369 wxFileName filename(parser->GetParam(j));
2370 if (filename.MakeAbsolute())
2372 const wxString param = filename.GetLongPath();
2373 sock->WriteMsg((
const wxChar *) param, (param.length() + 1) *
sizeof(wxChar));
2378 sock->WriteMsg(wxEmptyString,
sizeof(wxChar));
2397 sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
2405 wxSocketBase *sock = evt.GetSocket();
2407 if (evt.GetSocketEvent() == wxSOCKET_LOST)
2414 wxChar
name[PATH_MAX];
2415 sock->ReadMsg(&
name,
sizeof(
name));
2428 auto parser = std::make_unique<wxCmdLineParser>(
argc,
argv);
2436 parser->AddOption(
wxT(
"b"),
wxT(
"blocksize"),
_(
"set max disk block size in bytes"),
2437 wxCMD_LINE_VAL_NUMBER);
2439 const auto journalOptionDescription =
2443 _(
"replay a journal file");
2445 parser->AddOption(
wxT(
"j"),
wxT(
"journal"), journalOptionDescription);
2448 parser->AddSwitch(
wxT(
"h"),
wxT(
"help"),
_(
"this help message"),
2449 wxCMD_LINE_OPTION_HELP);
2452 parser->AddSwitch(
wxT(
"t"),
wxT(
"test"),
_(
"run self diagnostics"));
2455 parser->AddSwitch(
wxT(
"v"),
wxT(
"version"),
_(
"display Audacity version"));
2459 parser->AddParam(
_(
"audio or project file name"),
2460 wxCMD_LINE_VAL_STRING,
2461 wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL);
2463#ifdef HAS_CUSTOM_URL_HANDLING
2465 parser->AddOption(
wxT(
"u"),
wxT(
"url"),
_(
"Handle 'audacity://' url"));
2469 if (parser->Parse() == 0)
2477 bool mustVeto =
false;
2480 mustVeto = wxDialog::OSXHasModalDialogsOpen();
2491 bool force = !
event.CanVeto();
2522 bool bFalse =
false;
2538#ifdef HAS_NETWORKING
2660#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) && !defined(__CYGWIN__)
2664 bool bWantAssociateFiles =
true;
2665 if (
gPrefs->
Read(
wxT(
"/WantAssociateFiles"), &bWantAssociateFiles) &&
2666 !bWantAssociateFiles)
2672 wxRegKey associateFileTypes;
2674 auto IsDefined = [&](
const wxString &type)
2676 associateFileTypes.SetName(wxString::Format(
wxT(
"HKCR\\%s"), type));
2677 bool bKeyExists = associateFileTypes.Exists();
2681 associateFileTypes.SetName(wxString::Format(
wxT(
"HKCU\\Software\\Classes\\%s"), type));
2682 bKeyExists = associateFileTypes.Exists();
2687 auto DefineType = [&](
const wxString &type)
2689 wxString root_key =
wxT(
"HKCU\\Software\\Classes\\");
2692 associateFileTypes.SetName(wxString::Format(
wxT(
"%s%s"), root_key, type));
2693 if (!associateFileTypes.Create(
true))
2696 root_key =
wxT(
"HKCR\\");
2697 associateFileTypes.SetName(wxString::Format(
wxT(
"%s%s"), root_key, type));
2698 if (!associateFileTypes.Create(
true))
2705 if (!root_key.empty())
2707 associateFileTypes =
wxT(
"Audacity.Project");
2714 if (IsDefined(
wxT(
".aup3")) && IsDefined(
wxT(
".aup")) && IsDefined(
wxT(
"Audacity.Project")))
2724"Audacity project (.aup3) files are not currently \nassociated with Audacity. \n\nAssociate them, so they open on double-click?"),
2725 XO(
"Audacity Project Files"),
2726 wxYES_NO | wxICON_QUESTION);
2728 if (wantAssoc == wxNO)
2742 root_key = DefineType(
wxT(
".aup3"));
2743 if (root_key.empty())
2749 DefineType(
wxT(
".aup"));
2751 associateFileTypes =
wxT(
"Audacity.Project");
2752 associateFileTypes.SetName(root_key +
wxT(
"Audacity.Project"));
2753 if (!associateFileTypes.Exists())
2755 associateFileTypes.Create(
true);
2756 associateFileTypes =
wxT(
"Audacity Project File");
2759 associateFileTypes.SetName(root_key +
wxT(
"Audacity.Project\\shell"));
2760 if (!associateFileTypes.Exists())
2762 associateFileTypes.Create(
true);
2763 associateFileTypes =
wxT(
"");
2766 associateFileTypes.SetName(root_key +
wxT(
"Audacity.Project\\shell\\open"));
2767 if (!associateFileTypes.Exists())
2769 associateFileTypes.Create(
true);
2772 associateFileTypes.SetName(root_key +
wxT(
"Audacity.Project\\shell\\open\\command"));
2773 wxString tmpRegAudPath;
2774 if(associateFileTypes.Exists())
2776 tmpRegAudPath = associateFileTypes.QueryDefaultValue().Lower();
2779 if (!associateFileTypes.Exists() ||
2780 (tmpRegAudPath.Find(
wxT(
"audacity.exe")) >= 0))
2782 associateFileTypes.Create(
true);
2783 associateFileTypes = (wxString)
argv[0] + (wxString)
wxT(
" \"%1\"");
2790 associateFileTypes.SetName(root_key +
wxT(
"Audacity.Project\\shell\\open\\ddeexec"));
2791 if (!associateFileTypes.Exists())
2793 associateFileTypes.Create(
true);
2794 associateFileTypes =
wxT(
"%1");
2797 associateFileTypes.SetName(root_key +
wxT(
"Audacity.Project\\shell\\open\\ddeexec\\Application"));
2798 if (!associateFileTypes.Exists())
2800 associateFileTypes.Create(
true);
2804 associateFileTypes.SetName(root_key +
wxT(
"Audacity.Project\\shell\\open\\ddeexec\\Topic"));
2805 if (!associateFileTypes.Exists())
2807 associateFileTypes.Create(
true);
2817 static std::once_flag configSetupFlag;
2818 std::call_once(configSetupFlag, [&]{
2821 wxTheApp->GetAppName(), wxEmptyString,
2822 configFileName.GetFullPath(),
2823 wxEmptyString, wxCONFIG_USE_LOCAL_FILE);
2824 wxConfigBase::Set(
gConfig.get());
2826 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()
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
void RegisterBuiltinEffects()
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)
std::unique_ptr< wxSplashScreen > mSplashScreen
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)
void HideSplashScreen(bool fadeOut=true)
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
BuiltinEffectsModule::Registration< FadeOut > fadeOut
static CommandContext::TargetFactory::SubstituteInUnique< InteractiveOutputTargets > scope
const std::string_view urlPrefix
std::string ToUTF8(const std::wstring &wstr)