openshot-audio  0.1.7
juce_posix_SharedCode.h
Go to the documentation of this file.
1 /*
2  ==============================================================================
3 
4  This file is part of the juce_core module of the JUCE library.
5  Copyright (c) 2015 - ROLI Ltd.
6 
7  Permission to use, copy, modify, and/or distribute this software for any purpose with
8  or without fee is hereby granted, provided that the above copyright notice and this
9  permission notice appear in all copies.
10 
11  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
12  TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
13  NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
15  IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16  CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 
18  ------------------------------------------------------------------------------
19 
20  NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
21  All other JUCE modules are covered by a dual GPL/commercial license, so if you are
22  using any other modules, be sure to check that you also comply with their license.
23 
24  For more details, visit www.juce.com
25 
26  ==============================================================================
27 */
28 
30 {
31  pthread_mutexattr_t atts;
32  pthread_mutexattr_init (&atts);
33  pthread_mutexattr_settype (&atts, PTHREAD_MUTEX_RECURSIVE);
34  #if ! JUCE_ANDROID
35  pthread_mutexattr_setprotocol (&atts, PTHREAD_PRIO_INHERIT);
36  #endif
37  pthread_mutex_init (&lock, &atts);
38  pthread_mutexattr_destroy (&atts);
39 }
40 
41 CriticalSection::~CriticalSection() noexcept { pthread_mutex_destroy (&lock); }
42 void CriticalSection::enter() const noexcept { pthread_mutex_lock (&lock); }
43 bool CriticalSection::tryEnter() const noexcept { return pthread_mutex_trylock (&lock) == 0; }
44 void CriticalSection::exit() const noexcept { pthread_mutex_unlock (&lock); }
45 
46 //==============================================================================
47 WaitableEvent::WaitableEvent (const bool useManualReset) noexcept
48  : triggered (false), manualReset (useManualReset)
49 {
50  pthread_cond_init (&condition, 0);
51 
52  pthread_mutexattr_t atts;
53  pthread_mutexattr_init (&atts);
54  #if ! JUCE_ANDROID
55  pthread_mutexattr_setprotocol (&atts, PTHREAD_PRIO_INHERIT);
56  #endif
57  pthread_mutex_init (&mutex, &atts);
58 }
59 
61 {
62  pthread_cond_destroy (&condition);
63  pthread_mutex_destroy (&mutex);
64 }
65 
66 bool WaitableEvent::wait (const int timeOutMillisecs) const noexcept
67 {
68  pthread_mutex_lock (&mutex);
69 
70  if (! triggered)
71  {
72  if (timeOutMillisecs < 0)
73  {
74  do
75  {
76  pthread_cond_wait (&condition, &mutex);
77  }
78  while (! triggered);
79  }
80  else
81  {
82  struct timeval now;
83  gettimeofday (&now, 0);
84 
85  struct timespec time;
86  time.tv_sec = now.tv_sec + (timeOutMillisecs / 1000);
87  time.tv_nsec = (now.tv_usec + ((timeOutMillisecs % 1000) * 1000)) * 1000;
88 
89  if (time.tv_nsec >= 1000000000)
90  {
91  time.tv_nsec -= 1000000000;
92  time.tv_sec++;
93  }
94 
95  do
96  {
97  if (pthread_cond_timedwait (&condition, &mutex, &time) == ETIMEDOUT)
98  {
99  pthread_mutex_unlock (&mutex);
100  return false;
101  }
102  }
103  while (! triggered);
104  }
105  }
106 
107  if (! manualReset)
108  triggered = false;
109 
110  pthread_mutex_unlock (&mutex);
111  return true;
112 }
113 
115 {
116  pthread_mutex_lock (&mutex);
117 
118  if (! triggered)
119  {
120  triggered = true;
121  pthread_cond_broadcast (&condition);
122  }
123 
124  pthread_mutex_unlock (&mutex);
125 }
126 
128 {
129  pthread_mutex_lock (&mutex);
130  triggered = false;
131  pthread_mutex_unlock (&mutex);
132 }
133 
134 //==============================================================================
135 void JUCE_CALLTYPE Thread::sleep (int millisecs)
136 {
137  struct timespec time;
138  time.tv_sec = millisecs / 1000;
139  time.tv_nsec = (millisecs % 1000) * 1000000;
140  nanosleep (&time, nullptr);
141 }
142 
144 {
145  #if JUCE_ANDROID
146  _exit (EXIT_FAILURE);
147  #else
148  std::_Exit (EXIT_FAILURE);
149  #endif
150 }
151 
152 //==============================================================================
153 const juce_wchar File::separator = '/';
154 const String File::separatorString ("/");
155 
156 //==============================================================================
158 {
159  HeapBlock<char> heapBuffer;
160 
161  char localBuffer [1024];
162  char* cwd = getcwd (localBuffer, sizeof (localBuffer) - 1);
163  size_t bufferSize = 4096;
164 
165  while (cwd == nullptr && errno == ERANGE)
166  {
167  heapBuffer.malloc (bufferSize);
168  cwd = getcwd (heapBuffer, bufferSize - 1);
169  bufferSize += 1024;
170  }
171 
172  return File (CharPointer_UTF8 (cwd));
173 }
174 
176 {
177  return chdir (getFullPathName().toUTF8()) == 0;
178 }
179 
180 //==============================================================================
181 // The unix siginterrupt function is deprecated - this does the same job.
182 int juce_siginterrupt (int sig, int flag)
183 {
184  struct ::sigaction act;
185  (void) ::sigaction (sig, nullptr, &act);
186 
187  if (flag != 0)
188  act.sa_flags &= ~SA_RESTART;
189  else
190  act.sa_flags |= SA_RESTART;
191 
192  return ::sigaction (sig, &act, nullptr);
193 }
194 
195 //==============================================================================
196 namespace
197 {
198  #if JUCE_LINUX || (JUCE_IOS && ! __DARWIN_ONLY_64_BIT_INO_T) // (this iOS stuff is to avoid a simulator bug)
199  typedef struct stat64 juce_statStruct;
200  #define JUCE_STAT stat64
201  #else
202  typedef struct stat juce_statStruct;
203  #define JUCE_STAT stat
204  #endif
205 
206  bool juce_stat (const String& fileName, juce_statStruct& info)
207  {
208  return fileName.isNotEmpty()
209  && JUCE_STAT (fileName.toUTF8(), &info) == 0;
210  }
211 
212  // if this file doesn't exist, find a parent of it that does..
213  bool juce_doStatFS (File f, struct statfs& result)
214  {
215  for (int i = 5; --i >= 0;)
216  {
217  if (f.exists())
218  break;
219 
220  f = f.getParentDirectory();
221  }
222 
223  return statfs (f.getFullPathName().toUTF8(), &result) == 0;
224  }
225 
226  #if (JUCE_MAC && MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || JUCE_IOS
227  static int64 getCreationTime (const juce_statStruct& s) noexcept { return (int64) s.st_birthtime; }
228  #else
229  static int64 getCreationTime (const juce_statStruct& s) noexcept { return (int64) s.st_ctime; }
230  #endif
231 
232  void updateStatInfoForFile (const String& path, bool* const isDir, int64* const fileSize,
233  Time* const modTime, Time* const creationTime, bool* const isReadOnly)
234  {
235  if (isDir != nullptr || fileSize != nullptr || modTime != nullptr || creationTime != nullptr)
236  {
237  juce_statStruct info;
238  const bool statOk = juce_stat (path, info);
239 
240  if (isDir != nullptr) *isDir = statOk && ((info.st_mode & S_IFDIR) != 0);
241  if (fileSize != nullptr) *fileSize = statOk ? (int64) info.st_size : 0;
242  if (modTime != nullptr) *modTime = Time (statOk ? (int64) info.st_mtime * 1000 : 0);
243  if (creationTime != nullptr) *creationTime = Time (statOk ? getCreationTime (info) * 1000 : 0);
244  }
245 
246  if (isReadOnly != nullptr)
247  *isReadOnly = access (path.toUTF8(), W_OK) != 0;
248  }
249 
250  Result getResultForErrno()
251  {
252  return Result::fail (String (strerror (errno)));
253  }
254 
255  Result getResultForReturnValue (int value)
256  {
257  return value == -1 ? getResultForErrno() : Result::ok();
258  }
259 
260  int getFD (void* handle) noexcept { return (int) (pointer_sized_int) handle; }
261  void* fdToVoidPointer (int fd) noexcept { return (void*) (pointer_sized_int) fd; }
262 }
263 
264 bool File::isDirectory() const
265 {
266  juce_statStruct info;
267 
268  return fullPath.isNotEmpty()
269  && (juce_stat (fullPath, info) && ((info.st_mode & S_IFDIR) != 0));
270 }
271 
272 bool File::exists() const
273 {
274  return fullPath.isNotEmpty()
275  && access (fullPath.toUTF8(), F_OK) == 0;
276 }
277 
278 bool File::existsAsFile() const
279 {
280  return exists() && ! isDirectory();
281 }
282 
284 {
285  juce_statStruct info;
286  return juce_stat (fullPath, info) ? info.st_size : 0;
287 }
288 
290 {
291  juce_statStruct info;
292  return juce_stat (fullPath, info) ? (uint64) info.st_ino : 0;
293 }
294 
295 //==============================================================================
297 {
298  if (exists())
299  return access (fullPath.toUTF8(), W_OK) == 0;
300 
301  if ((! isDirectory()) && fullPath.containsChar (separator))
303 
304  return false;
305 }
306 
307 static bool setFileModeFlags (const String& fullPath, mode_t flags, bool shouldSet) noexcept
308 {
309  juce_statStruct info;
310  if (! juce_stat (fullPath, info))
311  return false;
312 
313  info.st_mode &= 0777;
314 
315  if (shouldSet)
316  info.st_mode |= flags;
317  else
318  info.st_mode &= ~flags;
319 
320  return chmod (fullPath.toUTF8(), info.st_mode) == 0;
321 }
322 
323 bool File::setFileReadOnlyInternal (bool shouldBeReadOnly) const
324 {
325  // Hmm.. should we give global write permission or just the current user?
326  return setFileModeFlags (fullPath, S_IWUSR | S_IWGRP | S_IWOTH, ! shouldBeReadOnly);
327 }
328 
329 bool File::setFileExecutableInternal (bool shouldBeExecutable) const
330 {
331  return setFileModeFlags (fullPath, S_IXUSR | S_IXGRP | S_IXOTH, shouldBeExecutable);
332 }
333 
334 void File::getFileTimesInternal (int64& modificationTime, int64& accessTime, int64& creationTime) const
335 {
336  modificationTime = 0;
337  accessTime = 0;
338  creationTime = 0;
339 
340  juce_statStruct info;
341 
342  if (juce_stat (fullPath, info))
343  {
344  modificationTime = (int64) info.st_mtime * 1000;
345  accessTime = (int64) info.st_atime * 1000;
346  creationTime = (int64) info.st_ctime * 1000;
347  }
348 }
349 
350 bool File::setFileTimesInternal (int64 modificationTime, int64 accessTime, int64 /*creationTime*/) const
351 {
352  juce_statStruct info;
353 
354  if ((modificationTime != 0 || accessTime != 0) && juce_stat (fullPath, info))
355  {
356  struct utimbuf times;
357  times.actime = accessTime != 0 ? (time_t) (accessTime / 1000) : info.st_atime;
358  times.modtime = modificationTime != 0 ? (time_t) (modificationTime / 1000) : info.st_mtime;
359 
360  return utime (fullPath.toUTF8(), &times) == 0;
361  }
362 
363  return false;
364 }
365 
366 bool File::deleteFile() const
367 {
368  if (! exists())
369  return true;
370 
371  if (isDirectory())
372  return rmdir (fullPath.toUTF8()) == 0;
373 
374  return remove (fullPath.toUTF8()) == 0;
375 }
376 
377 bool File::moveInternal (const File& dest) const
378 {
379  if (rename (fullPath.toUTF8(), dest.getFullPathName().toUTF8()) == 0)
380  return true;
381 
382  if (hasWriteAccess() && copyInternal (dest))
383  {
384  if (deleteFile())
385  return true;
386 
387  dest.deleteFile();
388  }
389 
390  return false;
391 }
392 
393 Result File::createDirectoryInternal (const String& fileName) const
394 {
395  return getResultForReturnValue (mkdir (fileName.toUTF8(), 0777));
396 }
397 
398 //=====================================================================
399 int64 juce_fileSetPosition (void* handle, int64 pos)
400 {
401  if (handle != 0 && lseek (getFD (handle), pos, SEEK_SET) == pos)
402  return pos;
403 
404  return -1;
405 }
406 
407 void FileInputStream::openHandle()
408 {
409  const int f = open (file.getFullPathName().toUTF8(), O_RDONLY, 00644);
410 
411  if (f != -1)
412  fileHandle = fdToVoidPointer (f);
413  else
414  status = getResultForErrno();
415 }
416 
418 {
419  if (fileHandle != 0)
420  close (getFD (fileHandle));
421 }
422 
423 size_t FileInputStream::readInternal (void* const buffer, const size_t numBytes)
424 {
425  ssize_t result = 0;
426 
427  if (fileHandle != 0)
428  {
429  result = ::read (getFD (fileHandle), buffer, numBytes);
430 
431  if (result < 0)
432  {
433  status = getResultForErrno();
434  result = 0;
435  }
436  }
437 
438  return (size_t) result;
439 }
440 
441 //==============================================================================
442 void FileOutputStream::openHandle()
443 {
444  if (file.exists())
445  {
446  const int f = open (file.getFullPathName().toUTF8(), O_RDWR, 00644);
447 
448  if (f != -1)
449  {
450  currentPosition = lseek (f, 0, SEEK_END);
451 
452  if (currentPosition >= 0)
453  {
454  fileHandle = fdToVoidPointer (f);
455  }
456  else
457  {
458  status = getResultForErrno();
459  close (f);
460  }
461  }
462  else
463  {
464  status = getResultForErrno();
465  }
466  }
467  else
468  {
469  const int f = open (file.getFullPathName().toUTF8(), O_RDWR + O_CREAT, 00644);
470 
471  if (f != -1)
472  fileHandle = fdToVoidPointer (f);
473  else
474  status = getResultForErrno();
475  }
476 }
477 
478 void FileOutputStream::closeHandle()
479 {
480  if (fileHandle != 0)
481  {
482  close (getFD (fileHandle));
483  fileHandle = 0;
484  }
485 }
486 
487 ssize_t FileOutputStream::writeInternal (const void* const data, const size_t numBytes)
488 {
489  ssize_t result = 0;
490 
491  if (fileHandle != 0)
492  {
493  result = ::write (getFD (fileHandle), data, numBytes);
494 
495  if (result == -1)
496  status = getResultForErrno();
497  }
498 
499  return result;
500 }
501 
502 void FileOutputStream::flushInternal()
503 {
504  if (fileHandle != 0)
505  {
506  if (fsync (getFD (fileHandle)) == -1)
507  status = getResultForErrno();
508 
509  #if JUCE_ANDROID
510  // This stuff tells the OS to asynchronously update the metadata
511  // that the OS has cached aboud the file - this metadata is used
512  // when the device is acting as a USB drive, and unless it's explicitly
513  // refreshed, it'll get out of step with the real file.
514  const LocalRef<jstring> t (javaString (file.getFullPathName()));
515  android.activity.callVoidMethod (JuceAppActivity.scanFile, t.get());
516  #endif
517  }
518 }
519 
521 {
522  if (fileHandle == 0)
523  return status;
524 
525  flush();
526  return getResultForReturnValue (ftruncate (getFD (fileHandle), (off_t) currentPosition));
527 }
528 
529 //==============================================================================
530 String SystemStats::getEnvironmentVariable (const String& name, const String& defaultValue)
531 {
532  if (const char* s = ::getenv (name.toUTF8()))
533  return String::fromUTF8 (s);
534 
535  return defaultValue;
536 }
537 
538 //==============================================================================
539 void MemoryMappedFile::openInternal (const File& file, AccessMode mode)
540 {
541  jassert (mode == readOnly || mode == readWrite);
542 
543  if (range.getStart() > 0)
544  {
545  const long pageSize = sysconf (_SC_PAGE_SIZE);
546  range.setStart (range.getStart() - (range.getStart() % pageSize));
547  }
548 
549  fileHandle = open (file.getFullPathName().toUTF8(),
550  mode == readWrite ? (O_CREAT + O_RDWR) : O_RDONLY, 00644);
551 
552  if (fileHandle != -1)
553  {
554  void* m = mmap (0, (size_t) range.getLength(),
555  mode == readWrite ? (PROT_READ | PROT_WRITE) : PROT_READ,
556  MAP_SHARED, fileHandle,
557  (off_t) range.getStart());
558 
559  if (m != MAP_FAILED)
560  {
561  address = m;
562  madvise (m, (size_t) range.getLength(), MADV_SEQUENTIAL);
563  }
564  else
565  {
566  range = Range<int64>();
567  }
568  }
569 }
570 
572 {
573  if (address != nullptr)
574  munmap (address, (size_t) range.getLength());
575 
576  if (fileHandle != 0)
577  close (fileHandle);
578 }
579 
580 //==============================================================================
581 #if JUCE_PROJUCER_LIVE_BUILD
582 extern "C" const char* juce_getCurrentExecutablePath();
583 #endif
584 
587 {
588  #if JUCE_PROJUCER_LIVE_BUILD
589  return File (juce_getCurrentExecutablePath());
590  #elif JUCE_ANDROID
591  return File (android.appFile);
592  #else
593  struct DLAddrReader
594  {
595  static String getFilename()
596  {
597  Dl_info exeInfo;
598  dladdr ((void*) juce_getExecutableFile, &exeInfo);
599  return CharPointer_UTF8 (exeInfo.dli_fname);
600  }
601  };
602 
603  static String filename (DLAddrReader::getFilename());
605  #endif
606 }
607 
608 //==============================================================================
610 {
611  struct statfs buf;
612  if (juce_doStatFS (*this, buf))
613  return (int64) buf.f_bsize * (int64) buf.f_bavail; // Note: this returns space available to non-super user
614 
615  return 0;
616 }
617 
619 {
620  struct statfs buf;
621  if (juce_doStatFS (*this, buf))
622  return (int64) buf.f_bsize * (int64) buf.f_blocks;
623 
624  return 0;
625 }
626 
628 {
629  #if JUCE_MAC
630  struct VolAttrBuf
631  {
632  u_int32_t length;
633  attrreference_t mountPointRef;
634  char mountPointSpace [MAXPATHLEN];
635  } attrBuf;
636 
637  struct attrlist attrList;
638  zerostruct (attrList); // (can't use "= { 0 }" on this object because it's typedef'ed as a C struct)
639  attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
640  attrList.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME;
641 
642  File f (*this);
643 
644  for (;;)
645  {
646  if (getattrlist (f.getFullPathName().toUTF8(), &attrList, &attrBuf, sizeof (attrBuf), 0) == 0)
647  return String::fromUTF8 (((const char*) &attrBuf.mountPointRef) + attrBuf.mountPointRef.attr_dataoffset,
648  (int) attrBuf.mountPointRef.attr_length);
649 
650  const File parent (f.getParentDirectory());
651 
652  if (f == parent)
653  break;
654 
655  f = parent;
656  }
657  #endif
658 
659  return String();
660 }
661 
663 {
664  int result = 0;
665 /* int fd = open (getFullPathName().toUTF8(), O_RDONLY | O_NONBLOCK);
666 
667  char info [512];
668 
669  #ifndef HDIO_GET_IDENTITY
670  #define HDIO_GET_IDENTITY 0x030d
671  #endif
672 
673  if (ioctl (fd, HDIO_GET_IDENTITY, info) == 0)
674  {
675  DBG (String (info + 20, 20));
676  result = String (info + 20, 20).trim().getIntValue();
677  }
678 
679  close (fd);*/
680  return result;
681 }
682 
683 //==============================================================================
684 #if ! JUCE_IOS
685 void juce_runSystemCommand (const String&);
686 void juce_runSystemCommand (const String& command)
687 {
688  int result = system (command.toUTF8());
689  (void) result;
690 }
691 
694 {
695  // slight bodge here, as we just pipe the output into a temp file and read it...
697  .getNonexistentChildFile (String::toHexString (Random::getSystemRandom().nextInt()), ".tmp", false));
698 
699  juce_runSystemCommand (command + " > " + tempFile.getFullPathName());
700 
701  String result (tempFile.loadFileAsString());
702  tempFile.deleteFile();
703  return result;
704 }
705 #endif
706 
707 //==============================================================================
708 #if JUCE_IOS
710 {
711 public:
712  Pimpl (const String&, int)
713  : handle (1), refCount (1) // On iOS just fake success..
714  {
715  }
716 
717  int handle, refCount;
718 };
719 
720 #else
721 
723 {
724 public:
725  Pimpl (const String& lockName, const int timeOutMillisecs)
726  : handle (0), refCount (1)
727  {
728  #if JUCE_MAC
729  if (! createLockFile (File ("~/Library/Caches/com.juce.locks").getChildFile (lockName), timeOutMillisecs))
730  // Fallback if the user's home folder is on a network drive with no ability to lock..
731  createLockFile (File ("/tmp/com.juce.locks").getChildFile (lockName), timeOutMillisecs);
732 
733  #else
734  File tempFolder ("/var/tmp");
735  if (! tempFolder.isDirectory())
736  tempFolder = "/tmp";
737 
738  createLockFile (tempFolder.getChildFile (lockName), timeOutMillisecs);
739  #endif
740  }
741 
743  {
744  closeFile();
745  }
746 
747  bool createLockFile (const File& file, const int timeOutMillisecs)
748  {
749  file.create();
750  handle = open (file.getFullPathName().toUTF8(), O_RDWR);
751 
752  if (handle != 0)
753  {
754  struct flock fl;
755  zerostruct (fl);
756 
757  fl.l_whence = SEEK_SET;
758  fl.l_type = F_WRLCK;
759 
760  const int64 endTime = Time::currentTimeMillis() + timeOutMillisecs;
761 
762  for (;;)
763  {
764  const int result = fcntl (handle, F_SETLK, &fl);
765 
766  if (result >= 0)
767  return true;
768 
769  const int error = errno;
770 
771  if (error != EINTR)
772  {
773  if (error == EBADF || error == ENOTSUP)
774  return false;
775 
776  if (timeOutMillisecs == 0
777  || (timeOutMillisecs > 0 && Time::currentTimeMillis() >= endTime))
778  break;
779 
780  Thread::sleep (10);
781  }
782  }
783  }
784 
785  closeFile();
786  return true; // only false if there's a file system error. Failure to lock still returns true.
787  }
788 
789  void closeFile()
790  {
791  if (handle != 0)
792  {
793  struct flock fl;
794  zerostruct (fl);
795 
796  fl.l_whence = SEEK_SET;
797  fl.l_type = F_UNLCK;
798 
799  while (! (fcntl (handle, F_SETLKW, &fl) >= 0 || errno != EINTR))
800  {}
801 
802  close (handle);
803  handle = 0;
804  }
805  }
806 
808 };
809 #endif
810 
812 {
813 }
814 
816 {
817 }
818 
819 bool InterProcessLock::enter (const int timeOutMillisecs)
820 {
821  const ScopedLock sl (lock);
822 
823  if (pimpl == nullptr)
824  {
825  pimpl = new Pimpl (name, timeOutMillisecs);
826 
827  if (pimpl->handle == 0)
828  pimpl = nullptr;
829  }
830  else
831  {
832  pimpl->refCount++;
833  }
834 
835  return pimpl != nullptr;
836 }
837 
839 {
840  const ScopedLock sl (lock);
841 
842  // Trying to release the lock too many times!
843  jassert (pimpl != nullptr);
844 
845  if (pimpl != nullptr && --(pimpl->refCount) == 0)
846  pimpl = nullptr;
847 }
848 
849 //==============================================================================
850 void JUCE_API juce_threadEntryPoint (void*);
851 
852 extern "C" void* threadEntryProc (void*);
853 extern "C" void* threadEntryProc (void* userData)
854 {
856  {
857  #if JUCE_ANDROID
858  const AndroidThreadScope androidEnv;
859  #endif
860 
861  juce_threadEntryPoint (userData);
862  }
863 
864  return nullptr;
865 }
866 
867 void Thread::launchThread()
868 {
869  threadHandle = 0;
870  pthread_t handle = 0;
871 
872  if (pthread_create (&handle, 0, threadEntryProc, this) == 0)
873  {
874  pthread_detach (handle);
875  threadHandle = (void*) handle;
876  threadId = (ThreadID) threadHandle;
877  }
878 }
879 
880 void Thread::closeThreadHandle()
881 {
882  threadId = 0;
883  threadHandle = 0;
884 }
885 
886 void Thread::killThread()
887 {
888  if (threadHandle != 0)
889  {
890  #if JUCE_ANDROID
891  jassertfalse; // pthread_cancel not available!
892  #else
893  pthread_cancel ((pthread_t) threadHandle);
894  #endif
895  }
896 }
897 
899 {
900  #if JUCE_IOS || (JUCE_MAC && defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
902  {
903  [[NSThread currentThread] setName: juceStringToNS (name)];
904  }
905  #elif JUCE_LINUX
906  #if (__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2012
907  pthread_setname_np (pthread_self(), name.toRawUTF8());
908  #else
909  prctl (PR_SET_NAME, name.toRawUTF8(), 0, 0, 0);
910  #endif
911  #endif
912 }
913 
914 bool Thread::setThreadPriority (void* handle, int priority)
915 {
916  struct sched_param param;
917  int policy;
918  priority = jlimit (0, 10, priority);
919 
920  if (handle == nullptr)
921  handle = (void*) pthread_self();
922 
923  if (pthread_getschedparam ((pthread_t) handle, &policy, &param) != 0)
924  return false;
925 
926  policy = priority == 0 ? SCHED_OTHER : SCHED_RR;
927 
928  const int minPriority = sched_get_priority_min (policy);
929  const int maxPriority = sched_get_priority_max (policy);
930 
931  param.sched_priority = ((maxPriority - minPriority) * priority) / 10 + minPriority;
932  return pthread_setschedparam ((pthread_t) handle, policy, &param) == 0;
933 }
934 
936 {
937  return (ThreadID) pthread_self();
938 }
939 
941 {
942  sched_yield();
943 }
944 
945 //==============================================================================
946 /* Remove this macro if you're having problems compiling the cpu affinity
947  calls (the API for these has changed about quite a bit in various Linux
948  versions, and a lot of distros seem to ship with obsolete versions)
949 */
950 #if defined (CPU_ISSET) && ! defined (SUPPORT_AFFINITIES)
951  #define SUPPORT_AFFINITIES 1
952 #endif
953 
955 {
956  #if SUPPORT_AFFINITIES
957  cpu_set_t affinity;
958  CPU_ZERO (&affinity);
959 
960  for (int i = 0; i < 32; ++i)
961  if ((affinityMask & (1 << i)) != 0)
962  CPU_SET (i, &affinity);
963 
964  #if (! JUCE_ANDROID) && ((! JUCE_LINUX) || ((__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2004))
965  pthread_setaffinity_np (pthread_self(), sizeof (cpu_set_t), &affinity);
966  #else
967  // NB: this call isn't really correct because it sets the affinity of the process,
968  // not the thread. But it's included here as a fallback for people who are using
969  // ridiculously old versions of glibc
970  sched_setaffinity (getpid(), sizeof (cpu_set_t), &affinity);
971  #endif
972 
973  sched_yield();
974 
975  #else
976  // affinities aren't supported because either the appropriate header files weren't found,
977  // or the SUPPORT_AFFINITIES macro was turned off
978  jassertfalse;
979  ignoreUnused (affinityMask);
980  #endif
981 }
982 
983 //==============================================================================
984 bool DynamicLibrary::open (const String& name)
985 {
986  close();
987  handle = dlopen (name.isEmpty() ? nullptr : name.toUTF8().getAddress(), RTLD_LOCAL | RTLD_NOW);
988  return handle != nullptr;
989 }
990 
992 {
993  if (handle != nullptr)
994  {
995  dlclose (handle);
996  handle = nullptr;
997  }
998 }
999 
1000 void* DynamicLibrary::getFunction (const String& functionName) noexcept
1001 {
1002  return handle != nullptr ? dlsym (handle, functionName.toUTF8()) : nullptr;
1003 }
1004 
1005 
1006 
1007 //==============================================================================
1009 {
1010 public:
1011  ActiveProcess (const StringArray& arguments, int streamFlags)
1012  : childPID (0), pipeHandle (0), readHandle (0)
1013  {
1014  // Looks like you're trying to launch a non-existent exe or a folder (perhaps on OSX
1015  // you're trying to launch the .app folder rather than the actual binary inside it?)
1016  jassert ((! arguments[0].containsChar ('/'))
1017  || File::getCurrentWorkingDirectory().getChildFile (arguments[0]).existsAsFile());
1018 
1019  int pipeHandles[2] = { 0 };
1020 
1021  if (pipe (pipeHandles) == 0)
1022  {
1023  const pid_t result = fork();
1024 
1025  if (result < 0)
1026  {
1027  close (pipeHandles[0]);
1028  close (pipeHandles[1]);
1029  }
1030  else if (result == 0)
1031  {
1032  // we're the child process..
1033  close (pipeHandles[0]); // close the read handle
1034 
1035  if ((streamFlags & wantStdOut) != 0)
1036  dup2 (pipeHandles[1], 1); // turns the pipe into stdout
1037  else
1038  close (STDOUT_FILENO);
1039 
1040  if ((streamFlags & wantStdErr) != 0)
1041  dup2 (pipeHandles[1], 2);
1042  else
1043  close (STDERR_FILENO);
1044 
1045  close (pipeHandles[1]);
1046 
1047  Array<char*> argv;
1048  for (int i = 0; i < arguments.size(); ++i)
1049  if (arguments[i].isNotEmpty())
1050  argv.add (const_cast<char*> (arguments[i].toUTF8().getAddress()));
1051 
1052  argv.add (nullptr);
1053 
1054  execvp (argv[0], argv.getRawDataPointer());
1055  exit (-1);
1056  }
1057  else
1058  {
1059  // we're the parent process..
1060  childPID = result;
1061  pipeHandle = pipeHandles[0];
1062  close (pipeHandles[1]); // close the write handle
1063  }
1064  }
1065  }
1066 
1068  {
1069  if (readHandle != 0)
1070  fclose (readHandle);
1071 
1072  if (pipeHandle != 0)
1073  close (pipeHandle);
1074  }
1075 
1077  {
1078  if (childPID != 0)
1079  {
1080  int childState;
1081  const int pid = waitpid (childPID, &childState, WNOHANG);
1082  return pid == 0 || ! (WIFEXITED (childState) || WIFSIGNALED (childState));
1083  }
1084 
1085  return false;
1086  }
1087 
1088  int read (void* const dest, const int numBytes) noexcept
1089  {
1090  jassert (dest != nullptr);
1091 
1092  #ifdef fdopen
1093  #error // the zlib headers define this function as NULL!
1094  #endif
1095 
1096  if (readHandle == 0 && childPID != 0)
1097  readHandle = fdopen (pipeHandle, "r");
1098 
1099  if (readHandle != 0)
1100  return (int) fread (dest, 1, (size_t) numBytes, readHandle);
1101 
1102  return 0;
1103  }
1104 
1106  {
1107  return ::kill (childPID, SIGKILL) == 0;
1108  }
1109 
1111  {
1112  if (childPID != 0)
1113  {
1114  int childState = 0;
1115  const int pid = waitpid (childPID, &childState, WNOHANG);
1116 
1117  if (pid >= 0 && WIFEXITED (childState))
1118  return WEXITSTATUS (childState);
1119  }
1120 
1121  return 0;
1122  }
1123 
1125 
1126 private:
1127  int pipeHandle;
1128  FILE* readHandle;
1129 
1131 };
1132 
1133 bool ChildProcess::start (const String& command, int streamFlags)
1134 {
1135  return start (StringArray::fromTokens (command, true), streamFlags);
1136 }
1137 
1138 bool ChildProcess::start (const StringArray& args, int streamFlags)
1139 {
1140  if (args.size() == 0)
1141  return false;
1142 
1143  activeProcess = new ActiveProcess (args, streamFlags);
1144 
1145  if (activeProcess->childPID == 0)
1146  activeProcess = nullptr;
1147 
1148  return activeProcess != nullptr;
1149 }
1150 
1151 //==============================================================================
1153 {
1154  Pimpl (HighResolutionTimer& t) : owner (t), thread (0), shouldStop (false)
1155  {
1156  }
1157 
1159  {
1160  jassert (thread == 0);
1161  }
1162 
1163  void start (int newPeriod)
1164  {
1165  if (periodMs != newPeriod)
1166  {
1167  if (thread != pthread_self())
1168  {
1169  stop();
1170 
1171  periodMs = newPeriod;
1172  shouldStop = false;
1173 
1174  if (pthread_create (&thread, nullptr, timerThread, this) == 0)
1175  setThreadToRealtime (thread, (uint64) newPeriod);
1176  else
1177  jassertfalse;
1178  }
1179  else
1180  {
1181  periodMs = newPeriod;
1182  shouldStop = false;
1183  }
1184  }
1185  }
1186 
1187  void stop()
1188  {
1189  if (thread != 0)
1190  {
1191  shouldStop = true;
1192 
1193  while (thread != 0 && thread != pthread_self())
1194  Thread::yield();
1195  }
1196  }
1197 
1199  int volatile periodMs;
1200 
1201 private:
1202  pthread_t thread;
1203  bool volatile shouldStop;
1204 
1205  static void* timerThread (void* param)
1206  {
1207  #if JUCE_ANDROID
1208  const AndroidThreadScope androidEnv;
1209  #else
1210  int dummy;
1211  pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &dummy);
1212  #endif
1213 
1214  reinterpret_cast<Pimpl*> (param)->timerThread();
1215  return nullptr;
1216  }
1217 
1218  void timerThread()
1219  {
1220  int lastPeriod = periodMs;
1221  Clock clock (lastPeriod);
1222 
1223  while (! shouldStop)
1224  {
1225  clock.wait();
1227 
1228  if (lastPeriod != periodMs)
1229  {
1230  lastPeriod = periodMs;
1231  clock = Clock (lastPeriod);
1232  }
1233  }
1234 
1235  periodMs = 0;
1236  thread = 0;
1237  }
1238 
1239  struct Clock
1240  {
1241  #if JUCE_MAC || JUCE_IOS
1242  Clock (double millis) noexcept
1243  {
1244  mach_timebase_info_data_t timebase;
1245  (void) mach_timebase_info (&timebase);
1246  delta = (((uint64_t) (millis * 1000000.0)) * timebase.denom) / timebase.numer;
1247  time = mach_absolute_time();
1248  }
1249 
1250  void wait() noexcept
1251  {
1252  time += delta;
1253  mach_wait_until (time);
1254  }
1255 
1256  uint64_t time, delta;
1257 
1258  #elif JUCE_ANDROID
1259  Clock (double millis) noexcept : delta ((uint64) (millis * 1000000))
1260  {
1261  }
1262 
1263  void wait() noexcept
1264  {
1265  struct timespec t;
1266  t.tv_sec = (time_t) (delta / 1000000000);
1267  t.tv_nsec = (long) (delta % 1000000000);
1268  nanosleep (&t, nullptr);
1269  }
1270 
1271  uint64 delta;
1272  #else
1273  Clock (double millis) noexcept : delta ((uint64) (millis * 1000000))
1274  {
1275  struct timespec t;
1276  clock_gettime (CLOCK_MONOTONIC, &t);
1277  time = (uint64) (1000000000 * (int64) t.tv_sec + (int64) t.tv_nsec);
1278  }
1279 
1280  void wait() noexcept
1281  {
1282  time += delta;
1283 
1284  struct timespec t;
1285  t.tv_sec = (time_t) (time / 1000000000);
1286  t.tv_nsec = (long) (time % 1000000000);
1287 
1288  clock_nanosleep (CLOCK_MONOTONIC, TIMER_ABSTIME, &t, nullptr);
1289  }
1290 
1291  uint64 time, delta;
1292  #endif
1293  };
1294 
1295  static bool setThreadToRealtime (pthread_t thread, uint64 periodMs)
1296  {
1297  #if JUCE_MAC || JUCE_IOS
1298  thread_time_constraint_policy_data_t policy;
1299  policy.period = (uint32_t) (periodMs * 1000000);
1300  policy.computation = 50000;
1301  policy.constraint = policy.period;
1302  policy.preemptible = true;
1303 
1304  return thread_policy_set (pthread_mach_thread_np (thread),
1305  THREAD_TIME_CONSTRAINT_POLICY,
1306  (thread_policy_t) &policy,
1307  THREAD_TIME_CONSTRAINT_POLICY_COUNT) == KERN_SUCCESS;
1308 
1309  #else
1310  (void) periodMs;
1311  struct sched_param param;
1312  param.sched_priority = sched_get_priority_max (SCHED_RR);
1313  return pthread_setschedparam (thread, SCHED_RR, &param) == 0;
1314 
1315  #endif
1316  }
1317 
1319 };
void * ThreadID
Definition: juce_Thread.h:224
Definition: juce_MemoryMappedFile.h:43
String getVolumeLabel() const
Definition: juce_posix_SharedCode.h:627
bool setAsCurrentWorkingDirectory() const
Definition: juce_posix_SharedCode.h:175
void enter() const noexcept
Definition: juce_posix_SharedCode.h:42
static String toHexString(int number)
Definition: juce_String.cpp:1925
bool enter(int timeOutMillisecs=-1)
Definition: juce_posix_SharedCode.h:819
bool open(const String &name)
Definition: juce_posix_SharedCode.h:984
~ActiveProcess()
Definition: juce_posix_SharedCode.h:1067
~WaitableEvent() noexcept
Definition: juce_posix_SharedCode.h:60
int pointer_sized_int
Definition: juce_MathsFunctions.h:86
Pimpl(const String &lockName, const int timeOutMillisecs)
Definition: juce_posix_SharedCode.h:725
struct backing_store_struct * info
Definition: jmemsys.h:183
~CriticalSection() noexcept
Definition: juce_posix_SharedCode.h:41
File() noexcept
Definition: juce_File.h:57
#define noexcept
Definition: juce_CompilerSupport.h:141
File juce_getExecutableFile()
Definition: juce_posix_SharedCode.h:586
void exit()
Definition: juce_posix_SharedCode.h:838
int getVolumeSerialNumber() const
Definition: juce_posix_SharedCode.h:662
bool existsAsFile() const
Definition: juce_posix_SharedCode.h:278
bool start(const String &command, int streamFlags=wantStdOut|wantStdErr)
Definition: juce_posix_SharedCode.h:1133
bool exists() const
Definition: juce_posix_SharedCode.h:272
String appFile
Definition: juce_android_JNIHelpers.h:250
Definition: juce_ScopedLock.h:59
static String getEnvironmentVariable(const String &name, const String &defaultValue)
Definition: juce_posix_SharedCode.h:530
Definition: juce_Time.h:41
File getChildFile(StringRef relativeOrAbsolutePath) const
Definition: juce_File.cpp:358
Definition: juce_ChildProcess.h:57
void malloc(const size_t newNumElements, const size_t elementSize=sizeof(ElementType))
Definition: juce_HeapBlock.h:220
Definition: juce_CharPointer_UTF8.h:38
~Pimpl()
Definition: juce_posix_SharedCode.h:1158
String juce_getOutputFromCommand(const String &)
Definition: juce_posix_SharedCode.h:693
static void JUCE_CALLTYPE setCurrentThreadAffinityMask(uint32 affinityMask)
Definition: juce_posix_SharedCode.h:954
static ThreadID JUCE_CALLTYPE getCurrentThreadId()
Definition: juce_posix_SharedCode.h:935
static File getCurrentWorkingDirectory()
Definition: juce_posix_SharedCode.h:157
void add(const ElementType &newElement)
Definition: juce_Array.h:392
int juce_siginterrupt(int sig, int flag)
Definition: juce_posix_SharedCode.h:182
int read(void *, int) override
Definition: juce_FileInputStream.cpp:50
#define JUCE_CALLTYPE
Definition: juce_PlatformDefs.h:50
static void JUCE_CALLTYPE yield()
Definition: juce_posix_SharedCode.h:940
#define jassertfalse
Definition: juce_PlatformDefs.h:141
#define false
Definition: ordinals.h:83
ValueType getLength() const noexcept
Definition: juce_Range.h:98
Definition: juce_String.h:43
Definition: juce_Result.h:61
void * threadEntryProc(void *)
Definition: juce_posix_SharedCode.h:853
static const String separatorString
Definition: juce_File.h:908
void signal() const noexcept
Definition: juce_posix_SharedCode.h:114
void juce_runSystemCommand(const String &)
Definition: juce_posix_SharedCode.h:686
void ignoreUnused(const Type1 &) noexcept
Definition: juce_core.h:280
#define JUCE_API
Definition: juce_StandardHeader.h:139
bool isNotEmpty() const noexcept
Definition: juce_String.h:308
AndroidSystem android
Definition: juce_android_SystemStats.cpp:158
virtual void hiResTimerCallback()=0
Definition: juce_HighResolutionTimer.h:46
#define const
void start(int newPeriod)
Definition: juce_posix_SharedCode.h:1163
bool containsChar(juce_wchar character) const noexcept
Definition: juce_String.cpp:1058
JOCTET * buffer
Definition: juce_JPEGLoader.cpp:302
void reset() const noexcept
Definition: juce_posix_SharedCode.h:127
void zerostruct(Type &structure) noexcept
Definition: juce_Memory.h:38
uint64 getFileIdentifier() const
Definition: juce_posix_SharedCode.h:289
bool deleteFile() const
Definition: juce_posix_SharedCode.h:366
String loadFileAsString() const
Definition: juce_File.cpp:487
void close()
Definition: juce_win32_Threads.cpp:390
int64 getVolumeTotalSize() const
Definition: juce_posix_SharedCode.h:618
png_structrp int mode
Definition: juce_PNGLoader.cpp:1243
static StringArray fromTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
Definition: juce_StringArray.cpp:403
there are legal restrictions on arithmetic coding Invalid progressive parameters caller expects u Cannot quantize more than d color components Adobe APP14 flags
Definition: juce_JPEGLoader.cpp:127
ActiveProcess(const StringArray &arguments, int streamFlags)
Definition: juce_posix_SharedCode.h:1011
int volatile periodMs
Definition: juce_posix_SharedCode.h:1199
unsigned long long uint64
Definition: juce_MathsFunctions.h:62
unsigned int uint32
Definition: juce_MathsFunctions.h:51
HighResolutionTimer & owner
Definition: juce_posix_SharedCode.h:1198
Result create() const
Definition: juce_File.cpp:429
bool killProcess() const noexcept
Definition: juce_posix_SharedCode.h:1105
int64 getBytesFreeOnVolume() const
Definition: juce_posix_SharedCode.h:609
static int64 currentTimeMillis() noexcept
Definition: juce_Time.cpp:196
void flush() override
Definition: juce_FileOutputStream.cpp:79
static void JUCE_CALLTYPE setCurrentThreadName(const String &newThreadName)
Definition: juce_posix_SharedCode.h:898
bool isRunning() const noexcept
Definition: juce_posix_SharedCode.h:1076
static void JUCE_CALLTYPE terminate()
Definition: juce_posix_SharedCode.h:143
int64 getSize() const
Definition: juce_posix_SharedCode.h:283
static const juce_wchar separator
Definition: juce_File.h:903
#define EXIT_FAILURE
Definition: jerror.c:32
bool hasWriteAccess() const
Definition: juce_posix_SharedCode.h:296
#define JUCE_STAT
Definition: juce_posix_SharedCode.h:203
png_uint_32 length
Definition: juce_PNGLoader.cpp:2078
bool isEmpty() const noexcept
Definition: juce_String.h:302
static Random & getSystemRandom() noexcept
Definition: juce_Random.cpp:64
CriticalSection() noexcept
Definition: juce_posix_SharedCode.h:29
long long int64
Definition: juce_MathsFunctions.h:60
int handle
Definition: juce_posix_SharedCode.h:807
int refCount
Definition: juce_posix_SharedCode.h:807
#define SEEK_SET
#define JUCE_AUTORELEASEPOOL
void JUCE_API juce_threadEntryPoint(void *)
Definition: juce_core.cpp:112
int size() const noexcept
Definition: juce_StringArray.h:121
Definition: juce_StringArray.h:39
void setStart(const ValueType newStart) noexcept
Definition: juce_Range.h:111
bool write(const void *, size_t) override
Definition: juce_FileOutputStream.cpp:85
bool isDirectory() const
Definition: juce_posix_SharedCode.h:264
bool wait(int timeOutMilliseconds=-1) const noexcept
Definition: juce_posix_SharedCode.h:66
Type jlimit(const Type lowerLimit, const Type upperLimit, const Type valueToConstrain) noexcept
Definition: juce_MathsFunctions.h:220
InterProcessLock(const String &name)
Definition: juce_posix_SharedCode.h:811
void * getFunction(const String &functionName) noexcept
Definition: juce_posix_SharedCode.h:1000
Definition: juce_Array.h:60
#define jassert(a)
Definition: juce_PlatformDefs.h:146
static String fromUTF8(const char *utf8buffer, int bufferSizeBytes=-1)
Definition: juce_String.cpp:2112
bool tryEnter() const noexcept
Definition: juce_posix_SharedCode.h:43
const char * toRawUTF8() const
Definition: juce_String.cpp:2061
Definition: juce_android_JNIHelpers.h:111
int refCount
Definition: juce_core.cpp:808
void
Definition: juce_PNGLoader.cpp:1173
#define JUCE_DECLARE_NON_COPYABLE(className)
Definition: juce_PlatformDefs.h:191
uint32 getExitCode() const noexcept
Definition: juce_posix_SharedCode.h:1110
Definition: juce_File.h:822
static void JUCE_CALLTYPE sleep(int milliseconds)
Definition: juce_posix_SharedCode.h:135
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
Definition: juce_PlatformDefs.h:198
Definition: juce_android_JNIHelpers.h:381
Definition: juce_HeapBlock.h:90
WaitableEvent(bool manualReset=false) noexcept
Definition: juce_posix_SharedCode.h:47
Definition: juce_posix_SharedCode.h:1152
Definition: juce_MemoryMappedFile.h:44
Result truncate()
Definition: juce_posix_SharedCode.h:520
int handle
Definition: juce_core.cpp:808
Definition: juce_ChildProcess.h:58
static File JUCE_CALLTYPE getSpecialLocation(const SpecialLocationType type)
Definition: juce_android_Files.cpp:49
~InterProcessLock()
Definition: juce_posix_SharedCode.h:815
~FileInputStream()
Definition: juce_posix_SharedCode.h:417
const String & getFullPathName() const noexcept
Definition: juce_File.h:150
JSAMPIMAGE data
Definition: jpeglib.h:945
#define SEEK_END
int read(void *const dest, const int numBytes) noexcept
Definition: juce_posix_SharedCode.h:1088
ElementType * getRawDataPointer() noexcept
Definition: juce_Array.h:319
void closeFile()
Definition: juce_posix_SharedCode.h:789
Pimpl(HighResolutionTimer &t)
Definition: juce_posix_SharedCode.h:1154
ValueType getStart() const noexcept
Definition: juce_Range.h:95
void exit() const noexcept
Definition: juce_posix_SharedCode.h:44
Definition: juce_File.h:45
CharType * getAddress() const noexcept
Definition: juce_CharPointer_UTF8.h:74
int childPID
Definition: juce_posix_SharedCode.h:1124
void close()
Definition: juce_posix_SharedCode.h:991
int64 juce_fileSetPosition(void *handle, int64 pos)
Definition: juce_posix_SharedCode.h:399
void callVoidMethod(jmethodID methodID,...) const
Definition: juce_android_JNIHelpers.h:91
~Pimpl()
Definition: juce_posix_SharedCode.h:742
~MemoryMappedFile()
Definition: juce_posix_SharedCode.h:571
void stop()
Definition: juce_posix_SharedCode.h:1187
bool createLockFile(const File &file, const int timeOutMillisecs)
Definition: juce_posix_SharedCode.h:747
wchar_t juce_wchar
Definition: juce_CharacterFunctions.h:49
CharPointer_UTF8 toUTF8() const
Definition: juce_String.cpp:2057
File getParentDirectory() const
Definition: juce_File.cpp:304
Definition: juce_posix_SharedCode.h:1008
GlobalRef activity
Definition: juce_android_JNIHelpers.h:249
static Result fail(const String &errorMessage) noexcept
Definition: juce_Result.cpp:70
Definition: juce_posix_SharedCode.h:722