The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

452 lines
13KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-7 by Raw Material Software ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the
  7. GNU General Public License, as published by the Free Software Foundation;
  8. either version 2 of the License, or (at your option) any later version.
  9. JUCE is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with JUCE; if not, visit www.gnu.org/licenses or write to the
  15. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. Boston, MA 02111-1307 USA
  17. ------------------------------------------------------------------------------
  18. If you'd like to release a closed-source product which uses JUCE, commercial
  19. licenses are also available: visit www.rawmaterialsoftware.com/juce for
  20. more information.
  21. ==============================================================================
  22. */
  23. // (This file gets included by juce_linux_NativeCode.cpp, rather than being
  24. // compiled on its own).
  25. #ifdef JUCE_INCLUDED_FILE
  26. #define U_ISOFS_SUPER_MAGIC (short) 0x9660 // linux/iso_fs.h
  27. #define U_MSDOS_SUPER_MAGIC (short) 0x4d44 // linux/msdos_fs.h
  28. #define U_NFS_SUPER_MAGIC (short) 0x6969 // linux/nfs_fs.h
  29. #define U_SMB_SUPER_MAGIC (short) 0x517B // linux/smb_fs.h
  30. //==============================================================================
  31. void juce_getFileTimes (const String& fileName,
  32. int64& modificationTime,
  33. int64& accessTime,
  34. int64& creationTime) throw()
  35. {
  36. modificationTime = 0;
  37. accessTime = 0;
  38. creationTime = 0;
  39. struct stat info;
  40. const int res = stat (fileName.toUTF8(), &info);
  41. if (res == 0)
  42. {
  43. modificationTime = (int64) info.st_mtime * 1000;
  44. accessTime = (int64) info.st_atime * 1000;
  45. creationTime = (int64) info.st_ctime * 1000;
  46. }
  47. }
  48. bool juce_setFileTimes (const String& fileName,
  49. int64 modificationTime,
  50. int64 accessTime,
  51. int64 creationTime) throw()
  52. {
  53. struct utimbuf times;
  54. times.actime = (time_t) (accessTime / 1000);
  55. times.modtime = (time_t) (modificationTime / 1000);
  56. return utime (fileName.toUTF8(), &times) == 0;
  57. }
  58. bool juce_setFileReadOnly (const String& fileName, bool isReadOnly) throw()
  59. {
  60. struct stat info;
  61. const int res = stat (fileName.toUTF8(), &info);
  62. if (res != 0)
  63. return false;
  64. info.st_mode &= 0777; // Just permissions
  65. if( isReadOnly )
  66. info.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
  67. else
  68. // Give everybody write permission?
  69. info.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
  70. return chmod (fileName.toUTF8(), info.st_mode) == 0;
  71. }
  72. bool juce_copyFile (const String& s, const String& d) throw()
  73. {
  74. const File source (s), dest (d);
  75. FileInputStream* in = source.createInputStream();
  76. bool ok = false;
  77. if (in != 0)
  78. {
  79. if (dest.deleteFile())
  80. {
  81. FileOutputStream* const out = dest.createOutputStream();
  82. if (out != 0)
  83. {
  84. const int bytesCopied = out->writeFromInputStream (*in, -1);
  85. delete out;
  86. ok = (bytesCopied == source.getSize());
  87. if (! ok)
  88. dest.deleteFile();
  89. }
  90. }
  91. delete in;
  92. }
  93. return ok;
  94. }
  95. const StringArray juce_getFileSystemRoots() throw()
  96. {
  97. StringArray s;
  98. s.add (T("/"));
  99. return s;
  100. }
  101. //==============================================================================
  102. bool File::isOnCDRomDrive() const throw()
  103. {
  104. struct statfs buf;
  105. if (statfs (getFullPathName().toUTF8(), &buf) == 0)
  106. return (buf.f_type == U_ISOFS_SUPER_MAGIC);
  107. // Assume not if this fails for some reason
  108. return false;
  109. }
  110. bool File::isOnHardDisk() const throw()
  111. {
  112. struct statfs buf;
  113. if (statfs (getFullPathName().toUTF8(), &buf) == 0)
  114. {
  115. switch (buf.f_type)
  116. {
  117. case U_ISOFS_SUPER_MAGIC: // CD-ROM
  118. case U_MSDOS_SUPER_MAGIC: // Probably floppy (but could be mounted FAT filesystem)
  119. case U_NFS_SUPER_MAGIC: // Network NFS
  120. case U_SMB_SUPER_MAGIC: // Network Samba
  121. return false;
  122. default:
  123. // Assume anything else is a hard-disk (but note it could
  124. // be a RAM disk. There isn't a good way of determining
  125. // this for sure)
  126. return true;
  127. }
  128. }
  129. // Assume so if this fails for some reason
  130. return true;
  131. }
  132. bool File::isOnRemovableDrive() const throw()
  133. {
  134. jassertfalse // xxx not implemented for linux!
  135. return false;
  136. }
  137. bool File::isHidden() const throw()
  138. {
  139. return getFileName().startsWithChar (T('.'));
  140. }
  141. //==============================================================================
  142. const File File::getSpecialLocation (const SpecialLocationType type)
  143. {
  144. switch (type)
  145. {
  146. case userHomeDirectory:
  147. {
  148. const char* homeDir = getenv ("HOME");
  149. if (homeDir == 0)
  150. {
  151. struct passwd* const pw = getpwuid (getuid());
  152. if (pw != 0)
  153. homeDir = pw->pw_dir;
  154. }
  155. return File (String::fromUTF8 ((const uint8*) homeDir));
  156. }
  157. case userDocumentsDirectory:
  158. case userMusicDirectory:
  159. case userMoviesDirectory:
  160. case userApplicationDataDirectory:
  161. return File ("~");
  162. case userDesktopDirectory:
  163. return File ("~/Desktop");
  164. case commonApplicationDataDirectory:
  165. return File ("/var");
  166. case globalApplicationsDirectory:
  167. return File ("/usr");
  168. case tempDirectory:
  169. {
  170. File tmp ("/var/tmp");
  171. if (! tmp.isDirectory())
  172. {
  173. tmp = T("/tmp");
  174. if (! tmp.isDirectory())
  175. tmp = File::getCurrentWorkingDirectory();
  176. }
  177. return tmp;
  178. }
  179. case currentExecutableFile:
  180. case currentApplicationFile:
  181. return juce_getExecutableFile();
  182. default:
  183. jassertfalse // unknown type?
  184. break;
  185. }
  186. return File::nonexistent;
  187. }
  188. //==============================================================================
  189. const File File::getCurrentWorkingDirectory() throw()
  190. {
  191. char buf [2048];
  192. return File (String::fromUTF8 ((const uint8*) getcwd (buf, sizeof (buf))));
  193. }
  194. bool File::setAsCurrentWorkingDirectory() const throw()
  195. {
  196. return chdir (getFullPathName().toUTF8()) == 0;
  197. }
  198. //==============================================================================
  199. const String File::getVersion() const throw()
  200. {
  201. return String::empty; // xxx not yet implemented
  202. }
  203. //==============================================================================
  204. const File File::getLinkedTarget() const throw()
  205. {
  206. char buffer [4096];
  207. size_t numChars = readlink ((const char*) getFullPathName().toUTF8(),
  208. buffer, sizeof (buffer));
  209. if (numChars > 0 && numChars <= sizeof (buffer))
  210. return File (String::fromUTF8 ((const uint8*) buffer, (int) numChars));
  211. return *this;
  212. }
  213. //==============================================================================
  214. bool File::moveToTrash() const throw()
  215. {
  216. if (! exists())
  217. return true;
  218. File trashCan (T("~/.Trash"));
  219. if (! trashCan.isDirectory())
  220. trashCan = T("~/.local/share/Trash/files");
  221. if (! trashCan.isDirectory())
  222. return false;
  223. return moveFileTo (trashCan.getNonexistentChildFile (getFileNameWithoutExtension(),
  224. getFileExtension()));
  225. }
  226. //==============================================================================
  227. struct FindFileStruct
  228. {
  229. String parentDir, wildCard;
  230. DIR* dir;
  231. bool getNextMatch (String& result, bool* const isDir, bool* const isHidden, int64* const fileSize,
  232. Time* const modTime, Time* const creationTime, bool* const isReadOnly) throw()
  233. {
  234. const char* const wildcardUTF8 = wildCard.toUTF8();
  235. for (;;)
  236. {
  237. struct dirent* const de = readdir (dir);
  238. if (de == 0)
  239. break;
  240. if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0)
  241. {
  242. result = String::fromUTF8 ((const uint8*) de->d_name);
  243. const String path (parentDir + result);
  244. if (isDir != 0 || fileSize != 0)
  245. {
  246. struct stat info;
  247. const bool statOk = (stat (path.toUTF8(), &info) == 0);
  248. if (isDir != 0)
  249. *isDir = path.isEmpty() || (statOk && ((info.st_mode & S_IFDIR) != 0));
  250. if (isHidden != 0)
  251. *isHidden = (de->d_name[0] == '.');
  252. if (fileSize != 0)
  253. *fileSize = statOk ? info.st_size : 0;
  254. }
  255. if (modTime != 0 || creationTime != 0)
  256. {
  257. int64 m, a, c;
  258. juce_getFileTimes (path, m, a, c);
  259. if (modTime != 0)
  260. *modTime = m;
  261. if (creationTime != 0)
  262. *creationTime = c;
  263. }
  264. if (isReadOnly != 0)
  265. *isReadOnly = ! juce_canWriteToFile (path);
  266. return true;
  267. }
  268. }
  269. return false;
  270. }
  271. };
  272. // returns 0 on failure
  273. void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile,
  274. bool* isDir, bool* isHidden, int64* fileSize, Time* modTime,
  275. Time* creationTime, bool* isReadOnly) throw()
  276. {
  277. DIR* d = opendir (directory.toUTF8());
  278. if (d != 0)
  279. {
  280. FindFileStruct* ff = new FindFileStruct();
  281. ff->parentDir = directory;
  282. if (!ff->parentDir.endsWithChar (File::separator))
  283. ff->parentDir += File::separator;
  284. ff->wildCard = wildCard;
  285. if (wildCard == T("*.*"))
  286. ff->wildCard = T("*");
  287. ff->dir = d;
  288. if (ff->getNextMatch (firstResultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly))
  289. {
  290. return ff;
  291. }
  292. else
  293. {
  294. firstResultFile = String::empty;
  295. isDir = false;
  296. isHidden = false;
  297. closedir (d);
  298. delete ff;
  299. }
  300. }
  301. return 0;
  302. }
  303. bool juce_findFileNext (void* handle, String& resultFile,
  304. bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, Time* creationTime, bool* isReadOnly) throw()
  305. {
  306. FindFileStruct* const ff = (FindFileStruct*) handle;
  307. if (ff != 0)
  308. return ff->getNextMatch (resultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
  309. return false;
  310. }
  311. void juce_findFileClose (void* handle) throw()
  312. {
  313. FindFileStruct* const ff = (FindFileStruct*) handle;
  314. if (ff != 0)
  315. {
  316. closedir (ff->dir);
  317. delete ff;
  318. }
  319. }
  320. bool juce_launchFile (const String& fileName,
  321. const String& parameters) throw()
  322. {
  323. String cmdString (fileName);
  324. cmdString << " " << parameters;
  325. if (URL::isProbablyAWebsiteURL (fileName)
  326. || URL::isProbablyAnEmailAddress (fileName))
  327. {
  328. // create a command that tries to launch a bunch of likely browsers
  329. const char* const browserNames[] = { "/etc/alternatives/x-www-browser", "firefox", "mozilla", "konqueror", "opera" };
  330. StringArray cmdLines;
  331. for (int i = 0; i < numElementsInArray (browserNames); ++i)
  332. cmdLines.add (String (browserNames[i]) + T(" ") + cmdString.trim().quoted());
  333. cmdString = cmdLines.joinIntoString (T(" || "));
  334. }
  335. if (cmdString.startsWithIgnoreCase (T("file:")))
  336. cmdString = cmdString.substring (5);
  337. const char* const argv[4] = { "/bin/sh", "-c", (const char*) cmdString.toUTF8(), 0 };
  338. const int cpid = fork();
  339. if (cpid == 0)
  340. {
  341. setsid();
  342. // Child process
  343. execve (argv[0], (char**) argv, environ);
  344. exit (0);
  345. }
  346. return cpid >= 0;
  347. }
  348. #endif