audacia/src/FileNames.cpp

268 lines
7.7 KiB
C++
Raw Normal View History

/**********************************************************************
Audacity: A Digital Audio Editor
FileNames.cpp
James Crook
********************************************************************//**
\class FileNames
\brief Provides Static functions to yield filenames.
2014-06-03 20:30:19 +00:00
This class helps us with setting a base path, and makes it easier
for us to keep track of the different kinds of files we read and write
from.
JKC: In time I plan to add all file names and file extensions
used throughout Audacity into this one place.
*//********************************************************************/
2013-11-01 12:15:01 +00:00
#include "Audacity.h"
#include <wx/defs.h>
#include <wx/filename.h>
#include <wx/intl.h>
#include <wx/stdpaths.h>
#include "Prefs.h"
#include "FileNames.h"
Fixes detection problems on Mac and possibly Windows (Bug #290) This should fix the detection problems on the Mac and may even help with issues on Windows and Linux. On any of the platforms, the main issue is the search path for libraries and how absolute path names are handled. The Mac seems to be especially susceptible since there isn't one concrete location where libraries are stored. Windows handles absolute paths differently and allows runtime updates to the environment variables (and if push comes to shove, provides the SetDllDirectory() function), so if problems still exist, they should be easy to circumvent. This patch does three things: 1) It adds a shell script on OSX that takes care of starting Audacity after reassigning and clearing the DYLD_LIBRARY_PATH environment variable. This will allow loading of libraries from their absolute path rather than searching DYLD_LIBRARY_PATH first. This script should be transparent to the user, but it will affect people running Audacity with gdb as they will have to specifically target Audacity.app/Contents/MacOS/Audacity instead of the Audacity.app bundle. Not big deal really. If ppl no enough to use gdb from the command line, they should be able to figure it out. 2) It corrects detection of a monolithic FFmpeg library. This is one where avformat, avcodec, and avutil have all been linked into one large library. The main issue here was that under OSX and Linux, looking for symbols that should reside in avutil and avcodec, would always succeed since dlsym() on these platforms not only scans the requested library, but any dependent libraries as well. And when avformat was loaded, it would pull in it's dependent libraries as well. Another issue here was the if it was determined that the library was not monolithic, the library was never unloaded, so those dependent libraries may have come from the wrong location since they would have been loaded via the normal search paths and not by absolute path name. 3) It adds a method to FileNames which returns the full path name of a loaded module that contains an address. In the case of FFmpeg, it is used to verify that a routine from a specific library is actually being used from that library or not. It is also used to show (in Help->Show log) the directory from which a library was actually loaded.
2011-02-23 01:41:40 +00:00
#include "Internat.h"
#include "PlatformCompatibility.h"
Fixes detection problems on Mac and possibly Windows (Bug #290) This should fix the detection problems on the Mac and may even help with issues on Windows and Linux. On any of the platforms, the main issue is the search path for libraries and how absolute path names are handled. The Mac seems to be especially susceptible since there isn't one concrete location where libraries are stored. Windows handles absolute paths differently and allows runtime updates to the environment variables (and if push comes to shove, provides the SetDllDirectory() function), so if problems still exist, they should be easy to circumvent. This patch does three things: 1) It adds a shell script on OSX that takes care of starting Audacity after reassigning and clearing the DYLD_LIBRARY_PATH environment variable. This will allow loading of libraries from their absolute path rather than searching DYLD_LIBRARY_PATH first. This script should be transparent to the user, but it will affect people running Audacity with gdb as they will have to specifically target Audacity.app/Contents/MacOS/Audacity instead of the Audacity.app bundle. Not big deal really. If ppl no enough to use gdb from the command line, they should be able to figure it out. 2) It corrects detection of a monolithic FFmpeg library. This is one where avformat, avcodec, and avutil have all been linked into one large library. The main issue here was that under OSX and Linux, looking for symbols that should reside in avutil and avcodec, would always succeed since dlsym() on these platforms not only scans the requested library, but any dependent libraries as well. And when avformat was loaded, it would pull in it's dependent libraries as well. Another issue here was the if it was determined that the library was not monolithic, the library was never unloaded, so those dependent libraries may have come from the wrong location since they would have been loaded via the normal search paths and not by absolute path name. 3) It adds a method to FileNames which returns the full path name of a loaded module that contains an address. In the case of FFmpeg, it is used to verify that a routine from a specific library is actually being used from that library or not. It is also used to show (in Help->Show log) the directory from which a library was actually loaded.
2011-02-23 01:41:40 +00:00
#if defined(__WXMAC__) || defined(__WXGTK__)
#include <dlfcn.h>
#endif
2011-02-24 04:38:40 +00:00
#if defined(__WXMSW__)
#include <windows.h>
#endif
static wxString gDataDir;
wxString FileNames::MkDir(const wxString &Str)
{
// Behaviour of wxFileName::DirExists() and wxFileName::MkDir() has
// changed between wx2.6 and wx2.8, so we use static functions instead.
if (!wxFileName::DirExists(Str))
wxFileName::Mkdir(Str, 511, wxPATH_MKDIR_FULL);
return Str;
}
/// Returns the directory used for temp files.
/// \todo put a counter in here to see if it gets used a lot.
2014-06-03 20:30:19 +00:00
/// if it does, then maybe we should cache the path name
/// each time.
wxString FileNames::TempDir()
{
return FileNames::MkDir(gPrefs->Read(wxT("/Directories/TempDir"), wxT("")));
}
// originally an ExportMultiple method. Append suffix if newName appears in otherNames.
void FileNames::MakeNameUnique(wxArrayString &otherNames, wxFileName &newName)
{
if (otherNames.Index(newName.GetFullName(), false) >= 0) {
int i=2;
wxString orig = newName.GetName();
do {
newName.SetName(wxString::Format(wxT("%s-%d"), orig.c_str(), i));
i++;
} while (otherNames.Index(newName.GetFullName(), false) >= 0);
}
otherNames.Add(newName.GetFullName());
}
//
// Audacity user data directories
wxString FileNames::AutoSaveDir()
{
wxFileName autoSaveDir(FileNames::DataDir(), wxT("AutoSave"));
return FileNames::MkDir(autoSaveDir.GetFullPath());
}
wxString FileNames::DataDir()
{
// LLL: Wouldn't you know that as of WX 2.6.2, there is a conflict
// between wxStandardPaths and wxConfig under Linux. The latter
// creates a normal file as "$HOME/.audacity", while the former
// expects the ".audacity" portion to be a directory.
if (gDataDir.IsEmpty())
{
// If there is a directory "Portable Settings" relative to the
// executable's EXE file, the prefs are stored in there, otherwise
// the prefs are stored in the user data dir provided by the OS.
wxFileName exePath(PlatformCompatibility::GetExecutablePath());
#if defined(__WXMAC__)
// This removes (for instance) "Audacity.app/Contents/MacOSX"
exePath.RemoveLastDir();
exePath.RemoveLastDir();
exePath.RemoveLastDir();
#endif
wxFileName portablePrefsPath(exePath.GetPath(), wxT("Portable Settings"));
2014-06-03 20:30:19 +00:00
if (::wxDirExists(portablePrefsPath.GetFullPath()))
{
// Use "Portable Settings" folder
gDataDir = portablePrefsPath.GetFullPath();
} else
{
// Use OS-provided user data dir folder
wxString dataDir;
#if defined( __WXGTK__ )
dataDir = wxStandardPaths::Get().GetUserDataDir() + wxT("-data");
#else
dataDir = wxStandardPaths::Get().GetUserDataDir();
#endif
gDataDir = FileNames::MkDir(dataDir);
}
}
2014-06-03 20:30:19 +00:00
return gDataDir;
}
wxString FileNames::HtmlHelpDir()
{
#if defined(__WXMAC__)
wxFileName exePath(PlatformCompatibility::GetExecutablePath());
// This removes (for instance) "Audacity.app/Contents/MacOSX"
exePath.RemoveLastDir();
exePath.RemoveLastDir();
exePath.RemoveLastDir();
2014-06-03 20:30:19 +00:00
return wxFileName( exePath.GetPath()+wxT("/help/manual"), wxEmptyString ).GetFullPath();
#else
//linux goes into /*prefix*/share/audacity/
//windows goes into the dir containing the .exe
wxString exeDir = wxStandardPaths::Get().GetDataDir();
2014-06-03 20:30:19 +00:00
//for mac this puts us within the .app: Audacity.app/Contents/SharedSupport/
return wxFileName( exeDir+wxT("/help/manual"), wxEmptyString ).GetFullPath();
2014-06-03 20:30:19 +00:00
#endif
}
wxString FileNames::HtmlHelpIndexFile(bool quick)
{
wxString htmlHelpIndex;
if(quick)
htmlHelpIndex = wxFileName( HtmlHelpDir(), wxT("quick_help.html") ).GetFullPath();
else
htmlHelpIndex = wxFileName( HtmlHelpDir(), wxT("index.html") ).GetFullPath();
return htmlHelpIndex;
}
wxString FileNames::ChainDir()
{
return FileNames::MkDir( wxFileName( DataDir(), wxT("Chains") ).GetFullPath() );
}
wxString FileNames::NRPDir()
{
return FileNames::MkDir( wxFileName( DataDir(), wxT("NRP") ).GetFullPath() );
}
wxString FileNames::NRPFile()
{
return wxFileName( NRPDir(), wxT("noisegate.nrp") ).GetFullPath();
}
wxString FileNames::PlugInDir()
{
return FileNames::MkDir( wxFileName( DataDir(), wxT("Plug-Ins") ).GetFullPath() );
}
wxString FileNames::PluginsCache()
{
return wxFileName( DataDir(), wxT("plugins.cfg") ).GetFullPath();
}
wxString FileNames::ThemeDir()
{
return FileNames::MkDir( wxFileName( DataDir(), wxT("Theme") ).GetFullPath() );
}
wxString FileNames::ThemeComponentsDir()
{
return FileNames::MkDir( wxFileName( ThemeDir(), wxT("Components") ).GetFullPath() );
}
wxString FileNames::ThemeCachePng()
{
return wxFileName( ThemeDir(), wxT("ImageCache.png") ).GetFullPath();
}
wxString FileNames::ThemeCacheHtm()
{
return wxFileName( ThemeDir(), wxT("ImageCache.htm") ).GetFullPath();
}
wxString FileNames::ThemeImageDefsAsCee()
{
return wxFileName( ThemeDir(), wxT("ThemeImageDefsAsCee.h") ).GetFullPath();
}
wxString FileNames::ThemeCacheAsCee( )
{
return wxFileName( ThemeDir(), wxT("ThemeAsCeeCode.h") ).GetFullPath();
}
wxString FileNames::ThemeComponent(const wxString &Str)
{
return wxFileName( ThemeComponentsDir(), Str, wxT("png") ).GetFullPath();
}
Fixes detection problems on Mac and possibly Windows (Bug #290) This should fix the detection problems on the Mac and may even help with issues on Windows and Linux. On any of the platforms, the main issue is the search path for libraries and how absolute path names are handled. The Mac seems to be especially susceptible since there isn't one concrete location where libraries are stored. Windows handles absolute paths differently and allows runtime updates to the environment variables (and if push comes to shove, provides the SetDllDirectory() function), so if problems still exist, they should be easy to circumvent. This patch does three things: 1) It adds a shell script on OSX that takes care of starting Audacity after reassigning and clearing the DYLD_LIBRARY_PATH environment variable. This will allow loading of libraries from their absolute path rather than searching DYLD_LIBRARY_PATH first. This script should be transparent to the user, but it will affect people running Audacity with gdb as they will have to specifically target Audacity.app/Contents/MacOS/Audacity instead of the Audacity.app bundle. Not big deal really. If ppl no enough to use gdb from the command line, they should be able to figure it out. 2) It corrects detection of a monolithic FFmpeg library. This is one where avformat, avcodec, and avutil have all been linked into one large library. The main issue here was that under OSX and Linux, looking for symbols that should reside in avutil and avcodec, would always succeed since dlsym() on these platforms not only scans the requested library, but any dependent libraries as well. And when avformat was loaded, it would pull in it's dependent libraries as well. Another issue here was the if it was determined that the library was not monolithic, the library was never unloaded, so those dependent libraries may have come from the wrong location since they would have been loaded via the normal search paths and not by absolute path name. 3) It adds a method to FileNames which returns the full path name of a loaded module that contains an address. In the case of FFmpeg, it is used to verify that a routine from a specific library is actually being used from that library or not. It is also used to show (in Help->Show log) the directory from which a library was actually loaded.
2011-02-23 01:41:40 +00:00
//
// Returns the full path of program module (.exe, .dll, .so, .dylib) containing address
//
wxString FileNames::PathFromAddr(void *addr)
{
wxFileName name;
#if defined(__WXMAC__) || defined(__WXGTK__)
Dl_info info;
if (dladdr(addr, &info)) {
char realname[PLATFORM_MAX_PATH + 1];
int len;
Fixes detection problems on Mac and possibly Windows (Bug #290) This should fix the detection problems on the Mac and may even help with issues on Windows and Linux. On any of the platforms, the main issue is the search path for libraries and how absolute path names are handled. The Mac seems to be especially susceptible since there isn't one concrete location where libraries are stored. Windows handles absolute paths differently and allows runtime updates to the environment variables (and if push comes to shove, provides the SetDllDirectory() function), so if problems still exist, they should be easy to circumvent. This patch does three things: 1) It adds a shell script on OSX that takes care of starting Audacity after reassigning and clearing the DYLD_LIBRARY_PATH environment variable. This will allow loading of libraries from their absolute path rather than searching DYLD_LIBRARY_PATH first. This script should be transparent to the user, but it will affect people running Audacity with gdb as they will have to specifically target Audacity.app/Contents/MacOS/Audacity instead of the Audacity.app bundle. Not big deal really. If ppl no enough to use gdb from the command line, they should be able to figure it out. 2) It corrects detection of a monolithic FFmpeg library. This is one where avformat, avcodec, and avutil have all been linked into one large library. The main issue here was that under OSX and Linux, looking for symbols that should reside in avutil and avcodec, would always succeed since dlsym() on these platforms not only scans the requested library, but any dependent libraries as well. And when avformat was loaded, it would pull in it's dependent libraries as well. Another issue here was the if it was determined that the library was not monolithic, the library was never unloaded, so those dependent libraries may have come from the wrong location since they would have been loaded via the normal search paths and not by absolute path name. 3) It adds a method to FileNames which returns the full path name of a loaded module that contains an address. In the case of FFmpeg, it is used to verify that a routine from a specific library is actually being used from that library or not. It is also used to show (in Help->Show log) the directory from which a library was actually loaded.
2011-02-23 01:41:40 +00:00
name = LAT1CTOWX(info.dli_fname);
len = readlink(OSINPUT(name.GetFullPath()), realname, PLATFORM_MAX_PATH);
if (len > 0) {
realname[len] = 0;
name.SetFullName(LAT1CTOWX(realname));
}
Fixes detection problems on Mac and possibly Windows (Bug #290) This should fix the detection problems on the Mac and may even help with issues on Windows and Linux. On any of the platforms, the main issue is the search path for libraries and how absolute path names are handled. The Mac seems to be especially susceptible since there isn't one concrete location where libraries are stored. Windows handles absolute paths differently and allows runtime updates to the environment variables (and if push comes to shove, provides the SetDllDirectory() function), so if problems still exist, they should be easy to circumvent. This patch does three things: 1) It adds a shell script on OSX that takes care of starting Audacity after reassigning and clearing the DYLD_LIBRARY_PATH environment variable. This will allow loading of libraries from their absolute path rather than searching DYLD_LIBRARY_PATH first. This script should be transparent to the user, but it will affect people running Audacity with gdb as they will have to specifically target Audacity.app/Contents/MacOS/Audacity instead of the Audacity.app bundle. Not big deal really. If ppl no enough to use gdb from the command line, they should be able to figure it out. 2) It corrects detection of a monolithic FFmpeg library. This is one where avformat, avcodec, and avutil have all been linked into one large library. The main issue here was that under OSX and Linux, looking for symbols that should reside in avutil and avcodec, would always succeed since dlsym() on these platforms not only scans the requested library, but any dependent libraries as well. And when avformat was loaded, it would pull in it's dependent libraries as well. Another issue here was the if it was determined that the library was not monolithic, the library was never unloaded, so those dependent libraries may have come from the wrong location since they would have been loaded via the normal search paths and not by absolute path name. 3) It adds a method to FileNames which returns the full path name of a loaded module that contains an address. In the case of FFmpeg, it is used to verify that a routine from a specific library is actually being used from that library or not. It is also used to show (in Help->Show log) the directory from which a library was actually loaded.
2011-02-23 01:41:40 +00:00
}
2011-04-04 22:51:48 +00:00
#elif defined(__WXMSW__) && defined(_UNICODE)
// The GetModuleHandlEx() function did not appear until Windows XP and
2014-06-03 20:30:19 +00:00
// GetModuleFileName() did appear until Windows 2000, so we have to
// check for them at runtime.
typedef BOOL (WINAPI *getmodulehandleex)(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE* phModule);
typedef DWORD (WINAPI *getmodulefilename)(HMODULE hModule, LPWCH lpFilename, DWORD nSize);
getmodulehandleex gmhe =
(getmodulehandleex) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
"GetModuleHandleExW");
getmodulefilename gmfn =
(getmodulefilename) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
"GetModuleFileNameW");
if (gmhe != NULL && gmfn != NULL) {
HMODULE module;
if (gmhe(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPTSTR) addr,
&module)) {
TCHAR path[MAX_PATH];
DWORD nSize;
nSize = gmfn(module, path, MAX_PATH);
if (nSize && nSize < MAX_PATH) {
name = LAT1CTOWX(path);
}
Fixes detection problems on Mac and possibly Windows (Bug #290) This should fix the detection problems on the Mac and may even help with issues on Windows and Linux. On any of the platforms, the main issue is the search path for libraries and how absolute path names are handled. The Mac seems to be especially susceptible since there isn't one concrete location where libraries are stored. Windows handles absolute paths differently and allows runtime updates to the environment variables (and if push comes to shove, provides the SetDllDirectory() function), so if problems still exist, they should be easy to circumvent. This patch does three things: 1) It adds a shell script on OSX that takes care of starting Audacity after reassigning and clearing the DYLD_LIBRARY_PATH environment variable. This will allow loading of libraries from their absolute path rather than searching DYLD_LIBRARY_PATH first. This script should be transparent to the user, but it will affect people running Audacity with gdb as they will have to specifically target Audacity.app/Contents/MacOS/Audacity instead of the Audacity.app bundle. Not big deal really. If ppl no enough to use gdb from the command line, they should be able to figure it out. 2) It corrects detection of a monolithic FFmpeg library. This is one where avformat, avcodec, and avutil have all been linked into one large library. The main issue here was that under OSX and Linux, looking for symbols that should reside in avutil and avcodec, would always succeed since dlsym() on these platforms not only scans the requested library, but any dependent libraries as well. And when avformat was loaded, it would pull in it's dependent libraries as well. Another issue here was the if it was determined that the library was not monolithic, the library was never unloaded, so those dependent libraries may have come from the wrong location since they would have been loaded via the normal search paths and not by absolute path name. 3) It adds a method to FileNames which returns the full path name of a loaded module that contains an address. In the case of FFmpeg, it is used to verify that a routine from a specific library is actually being used from that library or not. It is also used to show (in Help->Show log) the directory from which a library was actually loaded.
2011-02-23 01:41:40 +00:00
}
}
#endif
return name.GetFullPath();
}