30#include <wx/filename.h>
31#include <wx/stdpaths.h>
40#if defined(__WXMAC__) || defined(__WXGTK__)
55 XO(
"Dynamically Linked Libraries"), {
wxT(
"dll") },
true
56#elif defined(__WXMAC__)
57 XO(
"Dynamic Libraries"), {
wxT(
"dylib") },
true
59 XO(
"Dynamically Linked Libraries"), {
wxT(
"so*") },
true
85 const wxString dot{
'.' };
88 for (
const auto &extension: extensions ) {
91 if ( extension.Contains( dot ) )
95 if ( !extension.empty() ) {
104 const auto defaultDescription = [](
const FileExtensions &extensions ){
106 wxString
exts = extensions[0];
107 for (
size_t ii = 1,
size = extensions.size(); ii <
size; ++ii ) {
108 exts +=
XO(
", ").Translation();
109 exts += extensions[ii];
113 return XO(
"%s files").Format(
exts );
116 if ( fileTypes.size() == 1 && fileTypes[0].description.empty() ) {
117 return makeGlobs( fileTypes[0].extensions );
121 for (
const auto &fileType : fileTypes ) {
122 const auto &extensions = fileType.extensions;
123 if (extensions.empty())
129 const auto globs = makeGlobs( extensions );
131 auto mask = fileType.description;
133 mask = defaultDescription( extensions );
134 if ( fileType.appendExtensions )
135 mask.Join(
XO(
"(%s)").
Format( globs ),
" " );
136 result += mask.Translation();
150 return wxCopyFile(file1, file2, overwrite);
160 bool existed = wxFileExists(file2);
161 bool result = wxCopyFile(file1, file2, overwrite) &&
162 wxFile{ file1 }.Length() == wxFile{ file2 }.Length();
163 if (!result && !existed)
176 return ( 0 != ::CreateHardLink( file2, file1, NULL ) );
180 return 0 == ::link( file1.c_str(), file2.c_str() );
189 if (!wxFileName::DirExists(Str))
190 wxFileName::Mkdir(Str, 511, wxPATH_MKDIR_FULL);
199 if (otherNames.Index(newName.GetFullName(),
false) >= 0) {
201 wxString orig = newName.GetName();
203 newName.SetName(wxString::Format(
wxT(
"%s-%d"), orig, i));
205 }
while (otherNames.Index(newName.GetFullName(),
false) >= 0);
207 otherNames.push_back(newName.GetFullName());
215 wxString dir = dirIn;
217 if( dir.EndsWith(
"Audacity" ) )
219 int nChars = dir.length() - wxString(
"Audacity" ).length();
220 dir = dir.Left( nChars ) +
"audacity";
238#if defined(__WXGTK__)
246 {
wxT(
"XDG_CACHE_HOME"),
wxT(
"/.cache") },
247 {
wxT(
"XDG_CONFIG_HOME"),
wxT(
"/.config") },
248 {
wxT(
"XDG_DATA_HOME"),
wxT(
"/.local/share")},
249 {
wxT(
"XDG_STATE_HOME"),
wxT(
"/.local/state")}
254 "Not all DirTarget cases were implemented!"
259 static const auto oldUnixDataDir = wxFileName::GetHomeDir() +
wxT(
"/.audacity-data");
260 static const auto oldUnixDataDirExists = wxDirExists(oldUnixDataDir);
262 if (oldUnixDataDirExists)
263 return oldUnixDataDir;
268 const auto [dirEnvVar, dirDefault] =
gXDGUnixDirs[size_t(target)];
269 if (!wxGetEnv(dirEnvVar, &newDir) || newDir.empty())
270 newDir = wxFileName::GetHomeDir() + dirDefault;
273 newDir = newDir +
wxT(
"/" AUDACITY_NAME);
275 newDir = newDir +
wxT(
"/audacity");
291#if defined(__WXMAC__)
296 exePath.RemoveLastDir();
298 wxFileName portablePrefsPath(exePath.GetPath(),
wxT(
"Portable Settings"));
300 if (::wxDirExists(portablePrefsPath.GetFullPath()))
303 dir = portablePrefsPath.GetFullPath();
306#if defined(__WXGTK__)
338#if defined(__WXMAC__)
344 exePath.RemoveLastDir();
347 return wxFileName( exePath.GetPath()+
wxT(
"/help/manual"), wxEmptyString ).GetFullPath();
352 return wxFileName( dataDir+
wxT(
"/help/manual"), wxEmptyString ).GetFullPath();
359 return wxFileName{
DataDir(),
wxT(
"Chains") }.GetFullPath();
374 return wxFileName(
NRPDir(),
wxT(
"noisegate.nrp") ).GetFullPath();
384 return wxFileName(
ConfigDir(),
wxT(
"audacity.cfg") ).GetFullPath();
389 return wxFileName(
ConfigDir(),
wxT(
"pluginregistry.cfg") ).GetFullPath();
394 return wxFileName(
ConfigDir(),
wxT(
"pluginsettings.cfg") ).GetFullPath();
401#if defined(__WXMAC__)
408 baseDir.RemoveLastDir();
409#elif defined(__WXMSW__)
418 return baseDir.GetPath();
423 wxFileName modulesDir(
BaseDir(), wxEmptyString);
425 modulesDir.AppendDir(
wxT(
"modules"));
427 return modulesDir.GetFullPath();
437#if defined(__WXMAC__) || defined(__WXGTK__)
438#define OSFILENAME(X) ((char *) (const char *)(X).fn_str())
439#define OSINPUT(X) OSFILENAME(X)
441 if (dladdr(addr, &info)) {
451#elif defined(__WXMSW__) && defined(_UNICODE)
455 typedef BOOL (WINAPI *getmodulehandleex)(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE* phModule);
456 typedef DWORD (WINAPI *getmodulefilename)(HMODULE hModule, LPWCH lpFilename, DWORD nSize);
457 getmodulehandleex gmhe =
458 (getmodulehandleex) GetProcAddress(GetModuleHandle(TEXT(
"kernel32.dll")),
459 "GetModuleHandleExW");
460 getmodulefilename gmfn =
461 (getmodulefilename) GetProcAddress(GetModuleHandle(TEXT(
"kernel32.dll")),
462 "GetModuleFileNameW");
464 if (gmhe != NULL && gmfn != NULL) {
466 if (gmhe(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
469 TCHAR path[MAX_PATH];
472 nSize = gmfn(module, path, MAX_PATH);
473 if (nSize && nSize < MAX_PATH) {
480 return name.GetFullPath();
491 return filePath.DirExists() && !filePath.FileExists();
502 defaultPath.AppendDir(
AppName );
503 result.SetPath(
gPrefs->
Read( preference, defaultPath.GetPath( wxPATH_GET_VOLUME ) ) );
506 bool bIsDefaultPath = result == defaultPath;
507 if( !bIsDefaultPath )
512 bIsDefaultPath = !
IsPathAvailable( result.GetPath(wxPATH_GET_VOLUME|wxPATH_GET_SEPARATOR ) );
515 result.SetPath( defaultPath.GetPath( wxPATH_GET_VOLUME ) );
520 if ( bIsDefaultPath )
525 result.Mkdir(0755, wxPATH_MKDIR_FULL);
528 result.AssignHomeDir();
529 result.SetPath(
gPrefs->
Read( preference, result.GetPath() +
"/Documents"));
539 case FileNames::Operation::Temp:
540 key =
wxT(
"/Directories/TempDir");
break;
541 case FileNames::Operation::Presets:
542 key =
wxT(
"/Presets/Path");
break;
543 case FileNames::Operation::Open:
544 key =
wxT(
"/Directories/Open");
break;
545 case FileNames::Operation::Save:
546 key =
wxT(
"/Directories/Save");
break;
547 case FileNames::Operation::Import:
548 key =
wxT(
"/Directories/Import");
break;
549 case FileNames::Operation::Export:
550 key =
wxT(
"/Directories/Export");
break;
551 case FileNames::Operation::MacrosOut:
552 key =
wxT(
"/Directories/MacrosOut");
break;
553 case FileNames::Operation::_None:
559 case FileNames::PathType::User:
560 key +=
"/Default";
break;
561 case FileNames::PathType::LastUsed:
562 key +=
"/LastUsed";
break;
563 case FileNames::PathType::_None:
600 if (op == Operation::Temp) {
614 const auto extension = fName.AfterLast(
wxT(
'.'));
616 extension.IsSameAs(
wxT(
"gro"),
false) ||
617 extension.IsSameAs(
wxT(
"midi"),
false) ||
618 extension.IsSameAs(
wxT(
"mid"),
false);
638 pathNorm.Normalize();
639 const wxString newpath{ pathNorm.GetFullPath() };
641 for(
const auto &path : pathList) {
646 pathList.push_back(newpath);
653 wxString multiPathString(multiPathStringArg);
654 while (!multiPathString.empty()) {
655 wxString onePath = multiPathString.BeforeFirst(wxPATH_SEP[0]);
656 multiPathString = multiPathString.AfterFirst(wxPATH_SEP[0]);
671 if (pattern.empty()) {
677 for(
size_t i = 0; i < pathList.size(); i++) {
678 ff = pathList[i] + wxFILE_SEP_PATH + pattern;
679 wxDir::GetAllFiles(ff.GetPath(), &results, ff.GetFullName(), flags);
686 bool status = wxFileName::IsDirWritable(path);
693 XO(
"\n%s does not have write permissions.").
Format(path),
696 .IconStyle(Icon::Error)
697 .ButtonStyle(Button::Ok)
709 return first.CmpNoCase(second);
714 const wxString &suffix )
716 static int count = 0;
718 return wxString::Format(
wxT(
"%s %s N-%i.%s"),
720 wxDateTime::Now().
Format(
wxT(
"%Y-%m-%d %H-%M-%S")),
727 return wxT(
"aup3unsaved");
732#if defined(__DARWIN__)
733#include <sys/mount.h>
737 if (statfs(wxPathOnly(path).c_str(), &fs))
740 return 0 == strcmp(fs.f_fstypename,
"msdos");
742#elif defined(__linux__)
743#include <sys/statfs.h>
744#include "/usr/include/linux/magic.h"
748 if (statfs(wxPathOnly(path).c_str(), &fs))
751 return fs.f_type == MSDOS_SUPER_MAGIC;
758 if (!fileName.HasVolume())
762 wxChar volumeType[64];
763 if (!::GetVolumeInformationW(
764 volume.wc_str(), NULL, 0, NULL, NULL,
767 WXSIZEOF(volumeType)))
769 wxString type(volumeType);
770 if (type ==
wxT(
"FAT") || type ==
wxT(
"FAT32"))
787 target = fileName.GetVolume() +
wxT(
":");
792 auto path = fileName;
793 path.SetFullName(wxString{});
794 while(path.GetDirCount() > 3)
795 path.RemoveLastDir();
796 target = path.GetFullPath();
Toolkit-neutral facade for basic user interface services.
static const AudacityProject::AttachedObjects::RegisteredFactory key
const TranslatableString name
static FilePaths sAudacityPathList
#define PLATFORM_MAX_PATH
const std::wstring AppName
This program's name.
audacity::BasicSettings * gPrefs
std::vector< FileNames::FileType > FileTypes
FILES_API const FileType XMLFiles
FILES_API const FileType AllFiles
FILES_API const FileType DynamicLibraries
FILES_API const FileType TextFiles
FILES_API const FileType AudacityProjects
Holds a msgid for the translation catalog; may also bind format arguments.
virtual bool Flush() noexcept=0
virtual bool Write(const wxString &key, bool value)=0
virtual bool Read(const wxString &key, bool *value) const =0
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
MessageBoxResult ShowMessageBox(const TranslatableString &message, MessageBoxOptions options={})
Show a modal message box with either Ok or Yes and No, and optionally Cancel.
FILES_API FilePath MacroDir()
FILES_API bool IsMidi(const FilePath &fName)
FILES_API bool IsOnFATFileSystem(const FilePath &path)
FILES_API FilePath PlugInDir()
The user plug-in directory (not a system one)
FILES_API FilePath Configuration()
FILES_API bool HardLinkFile(const FilePath &file1, const FilePath &file2)
FILES_API FilePath HtmlHelpDir()
FILES_API FilePath NRPFile()
FILES_API bool IsPathAvailable(const FilePath &Path)
FILES_API wxString LowerCaseAppNameInPath(const wxString &dirIn)
FILES_API wxString CreateUniqueName(const wxString &prefix, const wxString &suffix=wxEmptyString)
FILES_API wxString MkDir(const wxString &Str)
FILES_API wxFileNameWrapper DefaultToDocumentsFolder(const wxString &preference)
FILES_API wxString UnsavedProjectExtension()
FILES_API void AddUniquePathToPathList(const FilePath &path, FilePaths &pathList)
FILES_API FilePath ResourcesDir()
FILES_API FilePath ConfigDir()
Audacity user config directory.
FILES_API wxString PreferenceKey(FileNames::Operation op, FileNames::PathType type)
FILES_API FilePath StateDir()
Audacity user state directory.
FILES_API void FindFilesInPathList(const wxString &pattern, const FilePaths &pathList, FilePaths &results, int flags=wxDIR_FILES)
FILES_API bool DoCopyFile(const FilePath &file1, const FilePath &file2, bool overwrite=true)
FILES_API FilePath CacheDir()
Audacity user cache directory.
FILES_API bool WritableLocationCheck(const FilePath &path, const TranslatableString &message)
Check location on writable access and return true if checked successfully.
FILES_API void AddMultiPathsToPathList(const wxString &multiPathString, FilePaths &pathList)
FILES_API FilePath PathFromAddr(void *addr)
FILES_API wxString AbbreviatePath(const wxFileName &fileName)
Give enough of the path to identify the device. (On Windows, drive letter plus ':')
FILES_API wxString FormatWildcard(const FileTypes &fileTypes)
FILES_API FilePath BaseDir()
FILES_API FilePath DataDir()
Audacity user data directory.
FILES_API void UpdateDefaultPath(Operation op, const FilePath &path)
FILES_API FilePath ModulesDir()
FILES_API FilePath PluginRegistry()
FILES_API FilePath LegacyChainDir()
FILES_API FilePath NRPDir()
FILES_API void MakeNameUnique(FilePaths &otherNames, wxFileName &newName)
FILES_API int CompareNoCase(const wxString &first, const wxString &second)
FILES_API FilePath FindDefaultPath(Operation op)
FILES_API FilePath PluginSettings()
FILES_API const FilePaths & AudacityPathList()
A list of directories that should be searched for Audacity files (plug-ins, help files,...
FILES_API void SetAudacityPathList(FilePaths list)
static FilePath gTargetDirs[size_t(DirTarget::_targetCount)]
FilePath GetXDGTargetDir(DirTarget target)
const XDGDirConfig gXDGUnixDirs[]
FilePath GetUserTargetDir(DirTarget target, bool allowRoaming)
MessageBoxOptions && Caption(TranslatableString caption_) &&