Audacity 3.2.0
FileNames.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 FileNames.cpp
6
7 James Crook
8
9********************************************************************//********************************************************************/
22
23#include "FileNames.h"
24
25
26
27#include <memory>
28
29#include <wx/defs.h>
30#include <wx/filename.h>
31#include <wx/stdpaths.h>
32#include <wx/utils.h>
33#include "BasicUI.h"
34#include "Prefs.h"
35#include "Internat.h"
36#include "ModuleConstants.h"
38#include "wxFileNameWrapper.h"
39
40#if defined(__WXMAC__) || defined(__WXGTK__)
41#include <dlfcn.h>
42#endif
43
44#if defined(__WXMSW__)
45#include <windows.h>
46#endif
47
49 FileNames::AllFiles{ XO("All files"), { wxT("") } }
50 /* i18n-hint an Audacity project is the state of the program, stored as
51 files that can be reopened to resume the session later */
52 , FileNames::AudacityProjects{ XO("AUP3 project files"), { wxT("aup3") }, true }
54#if defined(__WXMSW__)
55 XO("Dynamically Linked Libraries"), { wxT("dll") }, true
56#elif defined(__WXMAC__)
57 XO("Dynamic Libraries"), { wxT("dylib") }, true
58#else
59 XO("Dynamically Linked Libraries"), { wxT("so*") }, true
60#endif
61 }
62 , FileNames::TextFiles{ XO("Text files"), { wxT("txt") }, true }
63 , FileNames::XMLFiles{ XO("XML files"), { wxT("xml"), wxT("XML") }, true }
64;
65
66wxString FileNames::FormatWildcard( const FileTypes &fileTypes )
67{
68 // |-separated list of:
69 // [ Description,
70 // ( if appendExtensions, then ' (', globs, ')' ),
71 // '|',
72 // globs ]
73 // where globs is a ;-separated list of filename patterns, which are
74 // '*' for an empty extension, else '*.' then the extension
75 // Only the part before | is displayed in the choice drop-down of file
76 // dialogs
77 //
78 // Exceptional case: if there is only one type and its description is empty,
79 // then just give the globs with no |
80 // Another exception: an empty description, when there is more than one
81 // type, is replaced with a default
82 // Another exception: if an extension contains a dot, it is interpreted as
83 // not really an extension, but a literal filename
84
85 const wxString dot{ '.' };
86 const auto makeGlobs = [&dot]( const FileExtensions &extensions ){
87 wxString globs;
88 for ( const auto &extension: extensions ) {
89 if ( !globs.empty() )
90 globs += ';';
91 if ( extension.Contains( dot ) )
92 globs += extension;
93 else {
94 globs += '*';
95 if ( !extension.empty() ) {
96 globs += '.';
97 globs += extension;
98 }
99 }
100 }
101 return globs;
102 };
103
104 const auto defaultDescription = []( const FileExtensions &extensions ){
105 // Assume extensions is not empty
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];
110 }
111 /* i18n-hint a type or types such as "txt" or "txt, xml" will be
112 substituted for %s */
113 return XO("%s files").Format( exts );
114 };
115
116 if ( fileTypes.size() == 1 && fileTypes[0].description.empty() ) {
117 return makeGlobs( fileTypes[0].extensions );
118 }
119 else {
120 wxString result;
121 for ( const auto &fileType : fileTypes ) {
122 const auto &extensions = fileType.extensions;
123 if (extensions.empty())
124 continue;
125
126 if (!result.empty())
127 result += '|';
128
129 const auto globs = makeGlobs( extensions );
130
131 auto mask = fileType.description;
132 if ( mask.empty() )
133 mask = defaultDescription( extensions );
134 if ( fileType.appendExtensions )
135 mask.Join( XO("(%s)").Format( globs ), " " );
136 result += mask.Translation();
137 result += '|';
138 result += globs;
139 }
140 return result;
141 }
142}
143
145 const FilePath& file1, const FilePath& file2, bool overwrite)
146{
147#ifdef __WXMSW__
148
149 // workaround not needed
150 return wxCopyFile(file1, file2, overwrite);
151
152#else
153 // PRL: Compensate for buggy wxCopyFile that returns false success,
154 // which was a cause of case 4 in comment 10 of
155 // http://bugzilla.audacityteam.org/show_bug.cgi?id=1759
156 // Destination file was created, but was empty
157 // Bug was introduced after wxWidgets 2.8.12 at commit
158 // 0597e7f977c87d107e24bf3e95ebfa3d60efc249 of wxWidgets repo
159
160 bool existed = wxFileExists(file2);
161 bool result = wxCopyFile(file1, file2, overwrite) &&
162 wxFile{ file1 }.Length() == wxFile{ file2 }.Length();
163 if (!result && !existed)
164 wxRemoveFile(file2);
165 return result;
166
167#endif
168}
169
170bool FileNames::HardLinkFile( const FilePath& file1, const FilePath& file2 )
171{
172#ifdef __WXMSW__
173
174 // Fix forced ASCII conversions and wrong argument order - MJB - 29/01/2019
175 //return ::CreateHardLinkA( file1.c_str(), file2.c_str(), NULL );
176 return ( 0 != ::CreateHardLink( file2, file1, NULL ) );
177
178#else
179
180 return 0 == ::link( file1.c_str(), file2.c_str() );
181
182#endif
183}
184
185wxString FileNames::MkDir(const wxString &Str)
186{
187 // Behaviour of wxFileName::DirExists() and wxFileName::MkDir() has
188 // changed between wx2.6 and wx2.8, so we use static functions instead.
189 if (!wxFileName::DirExists(Str))
190 wxFileName::Mkdir(Str, 511, wxPATH_MKDIR_FULL);
191
192 return Str;
193}
194
195// originally an ExportMultipleDialog method. Append suffix if newName appears in otherNames.
196void FileNames::MakeNameUnique(FilePaths &otherNames,
197 wxFileName &newName)
198{
199 if (otherNames.Index(newName.GetFullName(), false) >= 0) {
200 int i=2;
201 wxString orig = newName.GetName();
202 do {
203 newName.SetName(wxString::Format(wxT("%s-%d"), orig, i));
204 i++;
205 } while (otherNames.Index(newName.GetFullName(), false) >= 0);
206 }
207 otherNames.push_back(newName.GetFullName());
208}
209
210// The APP name has upercase first letter (so that Quit Audacity is correctly
211// capitalised on Mac, but we want lower case APP name in paths.
212// This function does that substitution, IF the last component of
213// the path is 'Audacity'.
214wxString FileNames::LowerCaseAppNameInPath( const wxString & dirIn){
215 wxString dir = dirIn;
216 // BUG 1577 Capitalisation of Audacity in path...
217 if( dir.EndsWith( "Audacity" ) )
218 {
219 int nChars = dir.length() - wxString( "Audacity" ).length();
220 dir = dir.Left( nChars ) + "audacity";
221 }
222 return dir;
223}
224
225namespace // Implementation for user directories
226{
227enum class DirTarget
228{
229 Cache,
230 Config,
231 Data,
232 State,
234};
235
236static FilePath gTargetDirs[size_t(DirTarget::_targetCount)] = {};
237
238#if defined(__WXGTK__)
239struct XDGDirConfig final
240{
241 wxString dirEnvVar;
243};
244
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")}
250};
251
252static_assert(
253 sizeof(gXDGUnixDirs) / sizeof(*gXDGUnixDirs) == size_t(DirTarget::_targetCount),
254 "Not all DirTarget cases were implemented!"
255);
256
258{
259 static const auto oldUnixDataDir = wxFileName::GetHomeDir() + wxT("/.audacity-data");
260 static const auto oldUnixDataDirExists = wxDirExists(oldUnixDataDir);
261 // Compatibility: Use old user data dir folder, if it already exists
262 if (oldUnixDataDirExists)
263 return oldUnixDataDir;
264
265 // see if the XDG_*_HOME env var is defined. if it is, use its value.
266 // if it isn't, use the default XDG-specified value.
267 wxString newDir;
268 const auto [dirEnvVar, dirDefault] = gXDGUnixDirs[size_t(target)];
269 if (!wxGetEnv(dirEnvVar, &newDir) || newDir.empty())
270 newDir = wxFileName::GetHomeDir() + dirDefault;
271
272#ifdef AUDACITY_NAME
273 newDir = newDir + wxT("/" AUDACITY_NAME);
274#else
275 newDir = newDir + wxT("/audacity");
276#endif
277
278 return newDir;
279}
280#endif
281
282FilePath GetUserTargetDir(DirTarget target, bool allowRoaming)
283{
284 auto& dir = gTargetDirs[size_t(target)];
285 if (dir.empty())
286 {
287 // If there is a directory "Portable Settings" relative to the
288 // executable's EXE file, the prefs are stored in there, otherwise
289 // the prefs are stored in the user data dir provided by the OS.
290 wxFileName exePath(PlatformCompatibility::GetExecutablePath());
291#if defined(__WXMAC__)
292 // Path ends for example in "Audacity.app/Contents/MacOSX"
293 //exePath.RemoveLastDir();
294 //exePath.RemoveLastDir();
295 // just remove the MacOSX part.
296 exePath.RemoveLastDir();
297#endif
298 wxFileName portablePrefsPath(exePath.GetPath(), wxT("Portable Settings"));
299
300 if (::wxDirExists(portablePrefsPath.GetFullPath()))
301 {
302 // Use "Portable Settings" folder
303 dir = portablePrefsPath.GetFullPath();
304 } else
305 {
306#if defined(__WXGTK__)
307 // Use XDG Base Directory compliant folders
308 wxString newDir(GetXDGTargetDir(target));
309#else
310 // Use OS-provided user data dir folder
311 wxString newDir(FileNames::LowerCaseAppNameInPath(
312 allowRoaming ? wxStandardPaths::Get().GetUserDataDir() :
313 wxStandardPaths::Get().GetUserLocalDataDir()));
314#endif
315 dir = FileNames::MkDir(newDir);
316 }
317 }
318 return dir;
319}
320} // End of implementation for user directories
321
322FilePath FileNames::CacheDir() { return GetUserTargetDir(DirTarget::Cache, false); }
323FilePath FileNames::ConfigDir() { return GetUserTargetDir(DirTarget::Config, true); }
324FilePath FileNames::DataDir() { return GetUserTargetDir(DirTarget::Data, true); }
325FilePath FileNames::StateDir() { return GetUserTargetDir(DirTarget::State, false); }
326
328#if __WXMSW__
329 static auto resourcesDir = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath();
330#else
331 static auto resourcesDir = LowerCaseAppNameInPath(wxStandardPaths::Get().GetResourcesDir());
332#endif
333 return resourcesDir;
334}
335
337{
338#if defined(__WXMAC__)
339 wxFileName exePath(PlatformCompatibility::GetExecutablePath());
340 // Path ends for example in "Audacity.app/Contents/MacOSX"
341 //exePath.RemoveLastDir();
342 //exePath.RemoveLastDir();
343 // just remove the MacOSX part.
344 exePath.RemoveLastDir();
345
346 //for mac this puts us within the .app: Audacity.app/Contents/SharedSupport/
347 return wxFileName( exePath.GetPath()+wxT("/help/manual"), wxEmptyString ).GetFullPath();
348#else
349 //linux goes into /*prefix*/share/audacity/
350 //windows (probably) goes into the dir containing the .exe
351 wxString dataDir = FileNames::LowerCaseAppNameInPath( wxStandardPaths::Get().GetDataDir());
352 return wxFileName( dataDir+wxT("/help/manual"), wxEmptyString ).GetFullPath();
353#endif
354}
355
357{
358 // Don't force creation of it
359 return wxFileName{ DataDir(), wxT("Chains") }.GetFullPath();
360}
361
363{
364 return FileNames::MkDir( wxFileName( DataDir(), wxT("Macros") ).GetFullPath() );
365}
366
368{
369 return FileNames::MkDir( wxFileName( DataDir(), wxT("NRP") ).GetFullPath() );
370}
371
373{
374 return wxFileName( NRPDir(), wxT("noisegate.nrp") ).GetFullPath();
375}
376
378{
379 return FileNames::MkDir( wxFileName( DataDir(), wxT("Plug-Ins") ).GetFullPath() );
380}
381
383{
384 return wxFileName( ConfigDir(), wxT("audacity.cfg") ).GetFullPath();
385}
386
388{
389 return wxFileName( ConfigDir(), wxT("pluginregistry.cfg") ).GetFullPath();
390}
391
393{
394 return wxFileName( ConfigDir(), wxT("pluginsettings.cfg") ).GetFullPath();
395}
396
398{
399 wxFileName baseDir;
400
401#if defined(__WXMAC__)
403
404 // Path ends for example in "Audacity.app/Contents/MacOSX"
405 //baseDir.RemoveLastDir();
406 //baseDir.RemoveLastDir();
407 // just remove the MacOSX part.
408 baseDir.RemoveLastDir();
409#elif defined(__WXMSW__)
410 // Don't use wxStandardPaths::Get().GetDataDir() since it removes
411 // the "Debug" directory in debug builds.
413#else
414 // Linux goes into /*prefix*/share/audacity/
415 baseDir = FileNames::LowerCaseAppNameInPath(wxStandardPaths::Get().GetPluginsDir());
416#endif
417
418 return baseDir.GetPath();
419}
420
422{
423 wxFileName modulesDir(BaseDir(), wxEmptyString);
424
425 modulesDir.AppendDir(wxT("modules"));
426
427 return modulesDir.GetFullPath();
428}
429
430//
431// Returns the full path of program module (.exe, .dll, .so, .dylib) containing address
432//
434{
435 wxFileName name;
436
437#if defined(__WXMAC__) || defined(__WXGTK__)
438#define OSFILENAME(X) ((char *) (const char *)(X).fn_str())
439#define OSINPUT(X) OSFILENAME(X)
440 Dl_info info;
441 if (dladdr(addr, &info)) {
442 char realname[PLATFORM_MAX_PATH + 1];
443 int len;
444 name = LAT1CTOWX(info.dli_fname);
445 len = readlink(OSINPUT(name.GetFullPath()), realname, PLATFORM_MAX_PATH);
446 if (len > 0) {
447 realname[len] = 0;
448 name.SetFullName(LAT1CTOWX(realname));
449 }
450 }
451#elif defined(__WXMSW__) && defined(_UNICODE)
452 // The GetModuleHandlEx() function did not appear until Windows XP and
453 // GetModuleFileName() did appear until Windows 2000, so we have to
454 // check for them at runtime.
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");
463
464 if (gmhe != NULL && gmfn != NULL) {
465 HMODULE module;
466 if (gmhe(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
467 (LPTSTR) addr,
468 &module)) {
469 TCHAR path[MAX_PATH];
470 DWORD nSize;
471
472 nSize = gmfn(module, path, MAX_PATH);
473 if (nSize && nSize < MAX_PATH) {
474 name = LAT1CTOWX(path);
475 }
476 }
477 }
478#endif
479
480 return name.GetFullPath();
481}
482
483
485 if( Path.IsEmpty() )
486 return false;
487#ifndef _WIN32
488 return true;
489#else
490 wxFileNameWrapper filePath( Path );
491 return filePath.DirExists() && !filePath.FileExists();
492#endif
493}
494
496{
497 wxFileNameWrapper result;
498
499#ifdef _WIN32
500 wxFileName defaultPath( wxStandardPaths::Get().GetDocumentsDir(), "" );
501
502 defaultPath.AppendDir( AppName );
503 result.SetPath( gPrefs->Read( preference, defaultPath.GetPath( wxPATH_GET_VOLUME ) ) );
504
505 // MJB: Bug 1899 & Bug 2007. Only create directory if the result is the default path
506 bool bIsDefaultPath = result == defaultPath;
507 if( !bIsDefaultPath )
508 {
509 // IF the prefs directory doesn't exist - (Deleted by our user perhaps?)
510 // or exists as a file
511 // THEN fallback to using the default directory.
512 bIsDefaultPath = !IsPathAvailable( result.GetPath(wxPATH_GET_VOLUME|wxPATH_GET_SEPARATOR ) );
513 if( bIsDefaultPath )
514 {
515 result.SetPath( defaultPath.GetPath( wxPATH_GET_VOLUME ) );
516 // Don't write to gPrefs.
517 // We typically do it later, (if directory actually gets used)
518 }
519 }
520 if ( bIsDefaultPath )
521 {
522 // The default path might not exist since it is a sub-directory of 'Documents'
523 // There is no error if the path could not be created. That's OK.
524 // The dialog that Audacity offers will allow the user to select a valid directory.
525 result.Mkdir(0755, wxPATH_MKDIR_FULL);
526 }
527#else
528 result.AssignHomeDir();
529 result.SetPath(gPrefs->Read( preference, result.GetPath() + "/Documents"));
530#endif
531
532 return result;
533}
534
536{
537 wxString key;
538 switch (op) {
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:
554 default:
555 break;
556 }
557
558 switch (type) {
559 case FileNames::PathType::User:
560 key += "/Default"; break;
561 case FileNames::PathType::LastUsed:
562 key += "/LastUsed"; break;
563 case FileNames::PathType::_None:
564 default:
565 break;
566 }
567
568 return key;
569}
570
572{
573 auto key = PreferenceKey(op, PathType::User);
574
575 if (key.empty())
576 return wxString{};
577
578 // If the user specified a default path, then use that
579 FilePath path = gPrefs->Read(key, wxT(""));
580 if (!path.empty()) {
581 return path;
582 }
583
584 // Maybe the last used path is available
585 key = PreferenceKey(op, PathType::LastUsed);
586 path = gPrefs->Read(key, wxT(""));
587 if (!path.empty()) {
588 return path;
589 }
590
591 // Last resort is to simply return the default folder
592 return DefaultToDocumentsFolder("").GetPath();
593}
594
595void FileNames::UpdateDefaultPath(Operation op, const FilePath &path)
596{
597 if (path.empty())
598 return;
599 wxString key;
600 if (op == Operation::Temp) {
601 key = PreferenceKey(op, PathType::_None);
602 }
603 else {
604 key = PreferenceKey(op, PathType::LastUsed);
605 }
606 if (!key.empty()) {
607 gPrefs->Write(key, path);
608 gPrefs->Flush();
609 }
610}
611
613
615{
616 return sAudacityPathList;
617}
618
620{
621 sAudacityPathList = std::move( list );
622}
623
624// static
626 FilePaths &pathList)
627{
628 wxFileNameWrapper pathNorm { pathArg };
629 pathNorm.Normalize();
630 const wxString newpath{ pathNorm.GetFullPath() };
631
632 for(const auto &path : pathList) {
633 if (pathNorm == wxFileNameWrapper{ path })
634 return;
635 }
636
637 pathList.push_back(newpath);
638}
639
640// static
641void FileNames::AddMultiPathsToPathList(const wxString &multiPathStringArg,
642 FilePaths &pathList)
643{
644 wxString multiPathString(multiPathStringArg);
645 while (!multiPathString.empty()) {
646 wxString onePath = multiPathString.BeforeFirst(wxPATH_SEP[0]);
647 multiPathString = multiPathString.AfterFirst(wxPATH_SEP[0]);
648 AddUniquePathToPathList(onePath, pathList);
649 }
650}
651
652#include <wx/log.h>
653
654// static
655void FileNames::FindFilesInPathList(const wxString & pattern,
656 const FilePaths & pathList,
657 FilePaths & results,
658 int flags)
659{
660 wxLogNull nolog;
661
662 if (pattern.empty()) {
663 return;
664 }
665
667
668 for(size_t i = 0; i < pathList.size(); i++) {
669 ff = pathList[i] + wxFILE_SEP_PATH + pattern;
670 wxDir::GetAllFiles(ff.GetPath(), &results, ff.GetFullName(), flags);
671 }
672}
673
675 const TranslatableString & message)
676{
677 bool status = wxFileName::IsDirWritable(path);
678
679 if (!status)
680 {
681 using namespace BasicUI;
683 message +
684 XO("\n%s does not have write permissions.").Format(path),
686 .Caption(XO("Error"))
687 .IconStyle(Icon::Error)
688 .ButtonStyle(Button::Ok)
689 );
690 }
691
692 return status;
693}
694
695// Using this with wxStringArray::Sort will give you a list that
696// is alphabetical, without depending on case. If you use the
697// default sort, you will get strings with 'R' before 'a', because it is in caps.
698int FileNames::CompareNoCase(const wxString& first, const wxString& second)
699{
700 return first.CmpNoCase(second);
701}
702
703// Create a unique filename using the passed prefix and suffix
704wxString FileNames::CreateUniqueName(const wxString &prefix,
705 const wxString &suffix /* = wxEmptyString */)
706{
707 static int count = 0;
708
709 return wxString::Format(wxT("%s %s N-%i.%s"),
710 prefix,
711 wxDateTime::Now().Format(wxT("%Y-%m-%d %H-%M-%S")),
712 ++count,
713 suffix);
714}
715
717{
718 return wxT("aup3unsaved");
719}
720
721// How to detect whether the file system of a path is FAT
722// No apparent way to do it with wxWidgets
723#if defined(__DARWIN__)
724#include <sys/mount.h>
726{
727 struct statfs fs;
728 if (statfs(wxPathOnly(path).c_str(), &fs))
729 // Error from statfs
730 return false;
731 return 0 == strcmp(fs.f_fstypename, "msdos");
732}
733#elif defined(__linux__)
734#include <sys/statfs.h>
735#include "/usr/include/linux/magic.h"
737{
738 struct statfs fs;
739 if (statfs(wxPathOnly(path).c_str(), &fs))
740 // Error from statfs
741 return false;
742 return fs.f_type == MSDOS_SUPER_MAGIC;
743}
744#elif defined(_WIN32)
745#include <fileapi.h>
747{
748 wxFileNameWrapper fileName{path};
749 if (!fileName.HasVolume())
750 return false;
751 auto volume = AbbreviatePath(fileName) + wxT("\\");
752 DWORD volumeFlags;
753 wxChar volumeType[64];
754 if (!::GetVolumeInformationW(
755 volume.wc_str(), NULL, 0, NULL, NULL,
756 &volumeFlags,
757 volumeType,
758 WXSIZEOF(volumeType)))
759 return false;
760 wxString type(volumeType);
761 if (type == wxT("FAT") || type == wxT("FAT32"))
762 return true;
763 return false;
764}
765#else
767{
768 return false;
769}
770#endif
771
772wxString FileNames::AbbreviatePath( const wxFileName &fileName )
773{
774 wxString target;
775#ifdef __WXMSW__
776
777 // Drive letter plus colon
778 target = fileName.GetVolume() + wxT(":");
779
780#else
781
782 // Shorten the path, arbitrarily to 3 components
783 auto path = fileName;
784 path.SetFullName(wxString{});
785 while(path.GetDirCount() > 3)
786 path.RemoveLastDir();
787 target = path.GetFullPath();
788
789#endif
790 return target;
791}
wxT("CloseDown"))
Toolkit-neutral facade for basic user interface services.
const TranslatableString name
Definition: Distortion.cpp:76
static FilePaths sAudacityPathList
Definition: FileNames.cpp:612
#define OSINPUT(X)
#define PLATFORM_MAX_PATH
Definition: FileNames.h:42
XO("Cut/Copy/Paste")
static const auto exts
Definition: ImportAUP.cpp:56
#define LAT1CTOWX(X)
Definition: Internat.h:158
const std::wstring AppName
This program's name.
static const AudacityProject::AttachedObjects::RegisteredFactory key
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
wxString FilePath
Definition: Project.h:21
std::vector< FileNames::FileType > FileTypes
Definition: SelectFile.h:23
FILES_API const FileType XMLFiles
Definition: FileNames.h:73
FILES_API const FileType AllFiles
Definition: FileNames.h:70
FILES_API const FileType DynamicLibraries
Definition: FileNames.h:72
FILES_API const FileType TextFiles
Definition: FileNames.h:73
FILES_API const FileType AudacityProjects
Definition: FileNames.h:71
Abstract base class used in importing a file.
static const FilePath & GetExecutablePath()
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.
Definition: BasicUI.cpp:196
MessageBoxResult ShowMessageBox(const TranslatableString &message, MessageBoxOptions options={})
Show a modal message box with either Ok or Yes and No, and optionally Cancel.
Definition: BasicUI.h:277
FILES_API FilePath MacroDir()
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)]
Definition: FileNames.cpp:236
FilePath GetXDGTargetDir(DirTarget target)
Definition: FileNames.cpp:257
const XDGDirConfig gXDGUnixDirs[]
Definition: FileNames.cpp:245
FilePath GetUserTargetDir(DirTarget target, bool allowRoaming)
Definition: FileNames.cpp:282
MessageBoxOptions && Caption(TranslatableString caption_) &&
Definition: BasicUI.h:101
Definition: Dither.cpp:67