VST3: fetch midi mappings all at once, use it for note/sound-off
[carla.git] / source / modules / juce_core / native / juce_linux_Files.cpp
blobdce73fcc2bfb48bae4d60f1b329c26c3239432d7
1 /*
2 ==============================================================================
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
20 ==============================================================================
23 #if JUCE_BSD
24 extern char** environ;
25 #endif
27 namespace juce
30 enum
32 U_ISOFS_SUPER_MAGIC = 0x9660, // linux/iso_fs.h
33 U_MSDOS_SUPER_MAGIC = 0x4d44, // linux/msdos_fs.h
34 U_NFS_SUPER_MAGIC = 0x6969, // linux/nfs_fs.h
35 U_SMB_SUPER_MAGIC = 0x517B // linux/smb_fs.h
38 bool File::isOnCDRomDrive() const
40 struct statfs buf;
42 return statfs (getFullPathName().toUTF8(), &buf) == 0
43 && buf.f_type == (unsigned int) U_ISOFS_SUPER_MAGIC;
46 bool File::isOnHardDisk() const
48 struct statfs buf;
50 if (statfs (getFullPathName().toUTF8(), &buf) == 0)
52 switch (buf.f_type)
54 case U_ISOFS_SUPER_MAGIC: // CD-ROM
55 case U_MSDOS_SUPER_MAGIC: // Probably floppy (but could be mounted FAT filesystem)
56 case U_NFS_SUPER_MAGIC: // Network NFS
57 case U_SMB_SUPER_MAGIC: // Network Samba
58 return false;
60 default: break;
64 // Assume so if this fails for some reason
65 return true;
68 bool File::isOnRemovableDrive() const
70 jassertfalse; // xxx not implemented for linux!
71 return false;
74 String File::getVersion() const
76 return {}; // xxx not yet implemented
79 //==============================================================================
80 static File resolveXDGFolder (const char* const type, const char* const fallbackFolder)
82 StringArray confLines;
83 File ("~/.config/user-dirs.dirs").readLines (confLines);
85 for (int i = 0; i < confLines.size(); ++i)
87 const String line (confLines[i].trimStart());
89 if (line.startsWith (type))
91 // eg. resolve XDG_MUSIC_DIR="$HOME/Music" to /home/user/Music
92 const File f (line.replace ("$HOME", File ("~").getFullPathName())
93 .fromFirstOccurrenceOf ("=", false, false)
94 .trim().unquoted());
96 if (f.isDirectory())
97 return f;
101 return File (fallbackFolder);
104 const char* const* juce_argv = nullptr;
105 int juce_argc = 0;
107 File File::getSpecialLocation (const SpecialLocationType type)
109 switch (type)
111 case userHomeDirectory:
113 if (const char* homeDir = getenv ("HOME"))
114 return File (CharPointer_UTF8 (homeDir));
116 if (auto* pw = getpwuid (getuid()))
117 return File (CharPointer_UTF8 (pw->pw_dir));
119 return {};
122 case userDocumentsDirectory: return resolveXDGFolder ("XDG_DOCUMENTS_DIR", "~/Documents");
123 case userMusicDirectory: return resolveXDGFolder ("XDG_MUSIC_DIR", "~/Music");
124 case userMoviesDirectory: return resolveXDGFolder ("XDG_VIDEOS_DIR", "~/Videos");
125 case userPicturesDirectory: return resolveXDGFolder ("XDG_PICTURES_DIR", "~/Pictures");
126 case userDesktopDirectory: return resolveXDGFolder ("XDG_DESKTOP_DIR", "~/Desktop");
127 case userApplicationDataDirectory: return resolveXDGFolder ("XDG_CONFIG_HOME", "~/.config");
128 case commonDocumentsDirectory:
129 case commonApplicationDataDirectory: return File ("/opt");
130 case globalApplicationsDirectory: return File ("/usr");
132 case tempDirectory:
134 if (const char* tmpDir = getenv ("TMPDIR"))
135 return File (CharPointer_UTF8 (tmpDir));
137 return File ("/tmp");
140 case invokedExecutableFile:
141 if (juce_argv != nullptr && juce_argc > 0)
142 return File (String (CharPointer_UTF8 (juce_argv[0])));
143 // Falls through
144 JUCE_FALLTHROUGH
146 case currentExecutableFile:
147 case currentApplicationFile:
148 #if ! JUCE_STANDALONE_APPLICATION
149 return juce_getExecutableFile();
150 #endif
151 // deliberate fall-through if this is not a shared-library
152 JUCE_FALLTHROUGH
154 case hostApplicationPath:
156 #if JUCE_BSD
157 return juce_getExecutableFile();
158 #else
159 const File f ("/proc/self/exe");
160 return f.isSymbolicLink() ? f.getLinkedTarget() : juce_getExecutableFile();
161 #endif
164 default:
165 jassertfalse; // unknown type?
166 break;
169 return {};
172 //==============================================================================
173 bool File::moveToTrash() const
175 if (! exists())
176 return true;
178 File trashCan ("~/.Trash");
180 if (! trashCan.isDirectory())
181 trashCan = "~/.local/share/Trash/files";
183 if (! trashCan.isDirectory())
184 return false;
186 return moveFileTo (trashCan.getNonexistentChildFile (getFileNameWithoutExtension(),
187 getFileExtension()));
190 //==============================================================================
191 static bool isFileExecutable (const String& filename)
193 juce_statStruct info;
195 return juce_stat (filename, info)
196 && S_ISREG (info.st_mode)
197 && access (filename.toUTF8(), X_OK) == 0;
200 bool Process::openDocument (const String& fileName, const String& parameters)
202 const auto cmdString = [&]
204 if (fileName.startsWithIgnoreCase ("file:")
205 || File::createFileWithoutCheckingPath (fileName).isDirectory()
206 || ! isFileExecutable (fileName))
208 const auto singleCommand = fileName.trim().quoted();
210 StringArray cmdLines;
212 for (auto browserName : { "xdg-open", "/etc/alternatives/x-www-browser", "firefox", "mozilla",
213 "google-chrome", "chromium-browser", "opera", "konqueror" })
215 cmdLines.add (String (browserName) + " " + singleCommand);
218 return cmdLines.joinIntoString (" || ");
221 return (fileName.replace (" ", "\\ ", false) + " " + parameters).trim();
222 }();
224 const char* const argv[] = { "/bin/sh", "-c", cmdString.toUTF8(), nullptr };
226 #if JUCE_USE_VFORK
227 const auto cpid = vfork();
228 #else
229 const auto cpid = fork();
230 #endif
232 if (cpid == 0)
234 #if ! JUCE_USE_VFORK
235 setsid();
236 #endif
238 // Child process
239 if (execve (argv[0], (char**) argv, environ) < 0)
240 _exit (0);
243 return cpid >= 0;
246 void File::revealToUser() const
248 if (isDirectory())
249 startAsProcess();
250 else if (getParentDirectory().exists())
251 getParentDirectory().startAsProcess();
254 } // namespace juce