1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-09 08:12:40 +02:00

Should fix the single instance detection on OSX

The problem was that different temp directories can
be specified when using Portable Settings.  This caused
the single instance checker to look for it's lock file
in different locations so it was unable to detect that
another instance was running.

This changes the directory for the lock file to be the
user's home directory (which is the default for the checker
anyway).  This allow the user to still specify different
temp directories in the Portable Settings and ensure's 
that only one instance (per user) ever runs.

It now checks the single instance before initializing
preferences since preferences are modified during initialization
which could interere with an already running instance.

In addition, the Mac now uses the DDE IPC startup to 
ensure all files are opened by the single Audacity instance.
Normally this is not needed since we also support the OSX
mechanism for opening by an existing process.  But, that
only works if the exact same Audacity.app is used.  There
are instances when this is not always the case.

I also ran across a problem with language initialization.

Since preferences were initialized before the locale was set,
dialogs would be shown in English.  I've made a change that sets
the language to the system language until the preferences are
loaded and then resets it to the user selected language.
This commit is contained in:
lllucius 2015-01-07 19:39:44 +00:00
parent 70285448c9
commit 945e68ba89
2 changed files with 59 additions and 88 deletions

View File

@ -564,8 +564,6 @@ GnomeShutdown GnomeShutdownInstance;
#endif
#if defined(__WXMSW__) || defined(__WXGTK__)
//
// DDE support for opening multiple files with one instance
// of Audacity.
@ -649,8 +647,6 @@ public:
};
};
#endif
#ifndef __WXMAC__
IMPLEMENT_APP(AudacityApp)
/* make the application class known to wxWidgets for dynamic construction */
@ -1041,9 +1037,6 @@ bool AudacityApp::OnInit()
wxSystemOptions::SetOption( wxMAC_WINDOW_PLAIN_TRANSITION, 1 );
#endif
// LL: Moved here from InitPreferences() to ensure VST effect
// discovery writes configuration to the correct directory
// on OSX with case-sensitive file systems.
#ifdef AUDACITY_NAME
wxString appName = wxT(AUDACITY_NAME);
wxString vendorName = wxT(AUDACITY_NAME);
@ -1063,6 +1056,20 @@ bool AudacityApp::OnInit()
wxFileSystem::AddHandler(new wxZipFSHandler);
// Use the system language for dialogs that are displayed before
// the user selected language is available from preferences.
mLocale = NULL;
InitLang(GetSystemLanguageCode());
// Check for another running instance. This must be done before
// any activities that may modify the same resources of the other
// instance, like initializing preferences.
if (!CreateSingleInstanceChecker()) {
return false;
}
// Now we know we're the only instance running, so we're safe to
// initialize preferences
InitPreferences();
#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) && !defined(__CYGWIN__)
@ -1161,18 +1168,15 @@ bool AudacityApp::OnInit()
wxGetUserId().c_str());
#endif //__WXMAC__
// Locale
// wxWidgets 2.3 has a much nicer wxLocale API. We can make this code much
// better once we move to wx 2.3/2.4.
// Reset the language now that translation paths and preferences are available
wxString lang = gPrefs->Read(wxT("/Locale/Language"), wxT(""));
if (lang == wxT(""))
lang = GetSystemLanguageCode();
mLocale = NULL;
InitLang( lang );
// Init DirManager, which initializes the temp directory
// If this fails, we must exit the program.
@ -1515,52 +1519,44 @@ bool AudacityApp::InitTempDir()
{
// We need to find a temp directory location.
wxString tempFromPrefs = gPrefs->Read(wxT("/Directories/TempDir"), wxT(""));
wxString tempDefaultLoc = wxGetApp().defaultTempDir;
wxFileName temp;
wxArrayString paths;
paths.Add(gPrefs->Read(wxT("/Directories/TempDir"), wxEmptyString));
paths.Add(defaultTempDir);
wxString temp = wxT("");
for (size_t i = 0, cnt = paths.GetCount(); i < cnt; i++)
{
temp.SetPath(paths[i]);
temp.AppendDir(wxGetUserId() + wxT("-temp-dir"));
#ifdef __WXGTK__
if (tempFromPrefs.Length() > 0 && tempFromPrefs[0] != wxT('/'))
tempFromPrefs = wxT("");
#endif
if (temp.IsOk() && temp.IsAbsolute())
{
if (temp.DirExists() || temp.Mkdir(0755, wxPATH_MKDIR_FULL))
{
#ifdef __UNIX__
// Check temp directory ownership on *nix systems only
wxStructStat stats;
if (wxLstat(temp.GetFullPath(), &stats) != 0 || stats.st_uid != geteuid())
{
temp.Clear();
continue;
}
// Stop wxWidgets from printing its own error messages
// The permissions don't always seem to be set on
// some platforms. Hopefully this fixes it...
chmod(OSFILENAME(temp.GetFullPath()), 0755);
#endif
wxLogNull logNo;
// Try temp dir that was stored in prefs first
if (tempFromPrefs != wxT("")) {
if (wxDirExists(tempFromPrefs))
temp = tempFromPrefs;
else if (wxMkdir(tempFromPrefs, 0755))
temp = tempFromPrefs;
}
// If that didn't work, try the default location
if (temp==wxT("") && tempDefaultLoc != wxT("")) {
if (wxDirExists(tempDefaultLoc))
temp = tempDefaultLoc;
else if (wxMkdir(tempDefaultLoc, 0755))
temp = tempDefaultLoc;
}
// Check temp directory ownership on *nix systems only
#ifdef __UNIX__
struct stat tempStatBuf;
if ( lstat(temp.mb_str(), &tempStatBuf) != 0 ) {
temp.clear();
}
else {
if ( geteuid() != tempStatBuf.st_uid ) {
temp.clear();
gPrefs->Write(wxT("/Directories/TempDir"), paths[i]) && gPrefs->Flush();
DirManager::SetTempDir(temp.GetFullPath());
break;
}
}
temp.Clear();
}
#endif
if (temp == wxT("")) {
if (!temp.IsOk())
{
// Failed
wxMessageBox(_("Audacity could not find a place to store temporary files.\nPlease enter an appropriate directory in the preferences dialog."));
@ -1572,44 +1568,25 @@ bool AudacityApp::InitTempDir()
return false;
}
// The permissions don't always seem to be set on
// some platforms. Hopefully this fixes it...
#ifdef __UNIX__
chmod(OSFILENAME(temp), 0755);
#endif
bool bSuccess = gPrefs->Write(wxT("/Directories/TempDir"), temp) && gPrefs->Flush();
DirManager::SetTempDir(temp);
// Make sure the temp dir isn't locked by another process.
if (!CreateSingleInstanceChecker(temp))
return false;
return bSuccess;
return true;
}
// Return true if there are no other instances of Audacity running,
// false otherwise.
//
// Use "dir" for creating lockfiles (on OS X and Unix).
bool AudacityApp::CreateSingleInstanceChecker(wxString dir)
bool AudacityApp::CreateSingleInstanceChecker()
{
wxLogNull dontLog;
wxString name = wxString::Format(wxT("audacity-lock-%s"), wxGetUserId().c_str());
wxString name = wxString(wxT(".")) + IPC_APPL;
mChecker = new wxSingleInstanceChecker();
#if defined(__WXMSW__) || defined(__WXGTK__)
wxString appl = IPC_APPL;
#if defined(__WXGTK__)
appl.Printf(wxT("%s/%s.sock"), dir.c_str(), IPC_APPL);
#endif
#if defined(__WXGTK__) || defined(__WXMAC__)
appl = wxGetHomeDir() + wxT("/") + name + wxT(".sock");
#endif
wxString runningTwoCopiesStr = _("Running two copies of Audacity simultaneously may cause\ndata loss or cause your system to crash.\n\n");
if (!mChecker->Create(name, dir)) {
if (!mChecker->Create(name + wxT(".lock"), wxGetHomeDir())) {
// Error initializing the wxSingleInstanceChecker. We don't know
// whether there is another instance running or not.
@ -1627,7 +1604,6 @@ bool AudacityApp::CreateSingleInstanceChecker(wxString dir)
}
}
else if ( mChecker->IsAnotherRunning() ) {
#if defined(__WXMSW__) || defined(__WXGTK__)
// Get the 1st argument (filename) if there is one.
wxString cmd;
if (argc > 1) {
@ -1642,10 +1618,10 @@ bool AudacityApp::CreateSingleInstanceChecker(wxString dir)
wxClient client;
wxConnectionBase *conn;
// We try up to 10 times since there's a small window
// We try up to 50 times since there's a small window
// where the DDE server on Windows may not have been fully
// initialized.
for (int i = 0; i < 10; i++) {
for (int i = 0; i < 50; i++) {
conn = client.MakeConnection(wxEmptyString,
appl,
IPC_TOPIC);
@ -1663,7 +1639,7 @@ bool AudacityApp::CreateSingleInstanceChecker(wxString dir)
}
wxMilliSleep(100);
}
#endif
// There is another copy of Audacity running. Force quit.
wxString prompt =
@ -1676,10 +1652,8 @@ bool AudacityApp::CreateSingleInstanceChecker(wxString dir)
return false;
}
#if defined(__WXMSW__) || defined(__WXGTK__)
// Create the DDE server
mIPCServ = new IPCServ(appl);
#endif
return true;
}
@ -1843,9 +1817,7 @@ int AudacityApp::OnExit()
Dispatch();
}
#if defined(__WXMSW__) || defined(__WXGTK__)
delete mIPCServ;
#endif
Importer::Get().Terminate();

View File

@ -220,16 +220,15 @@ class AudacityApp:public wxApp {
void DeInitCommandHandler();
bool InitTempDir();
bool CreateSingleInstanceChecker(wxString dir);
bool CreateSingleInstanceChecker();
/* utility method for printing the command line help message */
void PrintCommandLineHelp(void);
bool mWindowRectAlreadySaved;
#if defined(__WXMSW__) || defined(__WXGTK__)
IPCServ *mIPCServ;
#endif
public:
DECLARE_EVENT_TABLE()
};