@@ -26,7 +26,7 @@ ifeq ($(CONFIG),Release) | |||
OBJDIR := ../../bin/intermediate_linux/Release | |||
OUTDIR := ../../bin | |||
CPPFLAGS := -MMD -D "LINUX=1" -D "NDEBUG=1" -I "../../" -I "/usr/include" -I "/usr/include/freetype2" | |||
CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -O2 -Wall | |||
CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -O2 -O2 -Wall -fvisibility=hidden | |||
CXXFLAGS := $(CFLAGS) | |||
LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -s | |||
LDDEPS := | |||
@@ -60,6 +60,7 @@ OBJECTS := \ | |||
$(OBJDIR)/juce_Socket.o \ | |||
$(OBJDIR)/juce_URL.o \ | |||
$(OBJDIR)/juce_BufferedInputStream.o \ | |||
$(OBJDIR)/juce_FileInputSource.o \ | |||
$(OBJDIR)/juce_GZIPCompressorOutputStream.o \ | |||
$(OBJDIR)/juce_GZIPDecompressorInputStream.o \ | |||
$(OBJDIR)/juce_MemoryInputStream.o \ | |||
@@ -126,6 +127,8 @@ OBJECTS := \ | |||
$(OBJDIR)/juce_AudioFormat.o \ | |||
$(OBJDIR)/juce_AudioFormatManager.o \ | |||
$(OBJDIR)/juce_AudioSubsectionReader.o \ | |||
$(OBJDIR)/juce_AudioThumbnail.o \ | |||
$(OBJDIR)/juce_AudioThumbnailCache.o \ | |||
$(OBJDIR)/juce_FlacAudioFormat.o \ | |||
$(OBJDIR)/juce_OggVorbisAudioFormat.o \ | |||
$(OBJDIR)/juce_WavAudioFormat.o \ | |||
@@ -568,6 +571,11 @@ $(OBJDIR)/juce_BufferedInputStream.o: ../../src/juce_core/io/streams/juce_Buffer | |||
@echo $(notdir $<) | |||
@$(CXX) $(CXXFLAGS) -o $@ -c $< | |||
$(OBJDIR)/juce_FileInputSource.o: ../../src/juce_core/io/streams/juce_FileInputSource.cpp | |||
-@$(CMD_MKOBJDIR) | |||
@echo $(notdir $<) | |||
@$(CXX) $(CXXFLAGS) -o $@ -c $< | |||
$(OBJDIR)/juce_GZIPCompressorOutputStream.o: ../../src/juce_core/io/streams/juce_GZIPCompressorOutputStream.cpp | |||
-@$(CMD_MKOBJDIR) | |||
@echo $(notdir $<) | |||
@@ -898,6 +906,16 @@ $(OBJDIR)/juce_AudioSubsectionReader.o: ../../src/juce_appframework/audio/audio_ | |||
@echo $(notdir $<) | |||
@$(CXX) $(CXXFLAGS) -o $@ -c $< | |||
$(OBJDIR)/juce_AudioThumbnail.o: ../../src/juce_appframework/audio/audio_file_formats/juce_AudioThumbnail.cpp | |||
-@$(CMD_MKOBJDIR) | |||
@echo $(notdir $<) | |||
@$(CXX) $(CXXFLAGS) -o $@ -c $< | |||
$(OBJDIR)/juce_AudioThumbnailCache.o: ../../src/juce_appframework/audio/audio_file_formats/juce_AudioThumbnailCache.cpp | |||
-@$(CMD_MKOBJDIR) | |||
@echo $(notdir $<) | |||
@$(CXX) $(CXXFLAGS) -o $@ -c $< | |||
$(OBJDIR)/juce_FlacAudioFormat.o: ../../src/juce_appframework/audio/audio_file_formats/juce_FlacAudioFormat.cpp | |||
-@$(CMD_MKOBJDIR) | |||
@echo $(notdir $<) | |||
@@ -57,48 +57,22 @@ BEGIN_JUCE_NAMESPACE | |||
#include "../../../src/juce_core/basics/juce_Time.h" | |||
#include "../../../src/juce_core/io/network/juce_URL.h" | |||
#include "../../../src/juce_core/io/files/juce_NamedPipe.h" | |||
static File executableFile; | |||
#include "../../../src/juce_core/threads/juce_InterProcessLock.h" | |||
#include "../../../src/juce_core/threads/juce_Thread.h" | |||
//============================================================================== | |||
bool juce_isDirectory (const String& fileName) throw() | |||
{ | |||
if (fileName.isEmpty()) | |||
return true; | |||
struct stat info; | |||
const int res = stat (fileName.toUTF8(), &info); | |||
if (res == 0) | |||
return (info.st_mode & S_IFDIR) != 0; | |||
return false; | |||
} | |||
bool juce_fileExists (const String& fileName, const bool dontCountDirectories) throw() | |||
{ | |||
if (fileName.isEmpty()) | |||
return false; | |||
bool exists = access (fileName.toUTF8(), F_OK) == 0; | |||
if (exists && dontCountDirectories && juce_isDirectory (fileName)) | |||
exists = false; | |||
/* | |||
Note that a lot of methods that you'd expect to find in this file actually | |||
live in juce_posix_SharedCode.cpp! | |||
*/ | |||
#include "../../macosx/platform_specific_code/juce_posix_SharedCode.cpp" | |||
return exists; | |||
} | |||
int64 juce_getFileSize (const String& fileName) throw() | |||
{ | |||
struct stat info; | |||
const int res = stat (fileName.toUTF8(), &info); | |||
if (res == 0) | |||
return info.st_size; | |||
//============================================================================== | |||
static File executableFile; | |||
return 0; | |||
} | |||
//============================================================================== | |||
void juce_getFileTimes (const String& fileName, | |||
int64& modificationTime, | |||
int64& accessTime, | |||
@@ -112,10 +86,6 @@ void juce_getFileTimes (const String& fileName, | |||
const int res = stat (fileName.toUTF8(), &info); | |||
if (res == 0) | |||
{ | |||
/* | |||
* Note: On Linux the st_ctime field is defined as last change time | |||
* rather than creation. | |||
*/ | |||
modificationTime = (int64) info.st_mtime * 1000; | |||
accessTime = (int64) info.st_atime * 1000; | |||
creationTime = (int64) info.st_ctime * 1000; | |||
@@ -134,11 +104,6 @@ bool juce_setFileTimes (const String& fileName, | |||
return utime (fileName.toUTF8(), ×) == 0; | |||
} | |||
bool juce_canWriteToFile (const String& fileName) throw() | |||
{ | |||
return access (fileName.toUTF8(), W_OK) == 0; | |||
} | |||
bool juce_setFileReadOnly (const String& fileName, bool isReadOnly) throw() | |||
{ | |||
struct stat info; | |||
@@ -157,14 +122,6 @@ bool juce_setFileReadOnly (const String& fileName, bool isReadOnly) throw() | |||
return chmod (fileName.toUTF8(), info.st_mode) == 0; | |||
} | |||
bool juce_deleteFile (const String& fileName) throw() | |||
{ | |||
if (juce_isDirectory (fileName)) | |||
return rmdir (fileName.toUTF8()) == 0; | |||
else | |||
return remove (fileName.toUTF8()) == 0; | |||
} | |||
bool juce_copyFile (const String& s, const String& d) throw() | |||
{ | |||
const File source (s), dest (d); | |||
@@ -196,97 +153,6 @@ bool juce_copyFile (const String& s, const String& d) throw() | |||
return ok; | |||
} | |||
bool juce_moveFile (const String& source, const String& dest) throw() | |||
{ | |||
if (rename (source.toUTF8(), dest.toUTF8()) == 0) | |||
return true; | |||
if (! juce_canWriteToFile (source)) | |||
return false; | |||
if (juce_copyFile (source, dest)) | |||
{ | |||
if (juce_deleteFile (source)) | |||
return true; | |||
juce_deleteFile (dest); | |||
} | |||
return false; | |||
} | |||
void juce_createDirectory (const String& fileName) throw() | |||
{ | |||
mkdir (fileName.toUTF8(), 0777); | |||
} | |||
void* juce_fileOpen (const String& fileName, bool forWriting) throw() | |||
{ | |||
const char* mode = "rb"; | |||
if (forWriting) | |||
{ | |||
if (juce_fileExists (fileName, false)) | |||
{ | |||
FILE* f = fopen (fileName.toUTF8(), "r+b"); | |||
if (f != 0) | |||
fseek (f, 0, SEEK_END); | |||
return (void*) f; | |||
} | |||
else | |||
{ | |||
mode = "w+b"; | |||
} | |||
} | |||
return (void*)fopen (fileName.toUTF8(), mode); | |||
} | |||
void juce_fileClose (void* handle) throw() | |||
{ | |||
if (handle != 0) | |||
fclose ((FILE*) handle); | |||
} | |||
int juce_fileRead (void* handle, void* buffer, int size) throw() | |||
{ | |||
if (handle != 0) | |||
return fread (buffer, 1, size, (FILE*) handle); | |||
return 0; | |||
} | |||
int juce_fileWrite (void* handle, const void* buffer, int size) throw() | |||
{ | |||
if (handle != 0) | |||
return fwrite (buffer, 1, size, (FILE*) handle); | |||
return 0; | |||
} | |||
int64 juce_fileSetPosition (void* handle, int64 pos) throw() | |||
{ | |||
if (handle != 0 && fseek ((FILE*) handle, (long) pos, SEEK_SET) == 0) | |||
return pos; | |||
return -1; | |||
} | |||
int64 juce_fileGetPosition (void* handle) throw() | |||
{ | |||
if (handle != 0) | |||
return ftell ((FILE*) handle); | |||
else | |||
return -1; | |||
} | |||
void juce_fileFlush (void* handle) throw() | |||
{ | |||
if (handle != 0) | |||
fflush ((FILE*) handle); | |||
} | |||
const StringArray juce_getFileSystemRoots() throw() | |||
{ | |||
StringArray s; | |||
@@ -294,28 +160,7 @@ const StringArray juce_getFileSystemRoots() throw() | |||
return s; | |||
} | |||
const String juce_getVolumeLabel (const String& filenameOnVolume, | |||
int& volumeSerialNumber) throw() | |||
{ | |||
// There is no equivalent on Linux | |||
volumeSerialNumber = 0; | |||
return String::empty; | |||
} | |||
int64 File::getBytesFreeOnVolume() const throw() | |||
{ | |||
struct statfs buf; | |||
int64 free_space = 0; | |||
if (statfs (getFullPathName().toUTF8(), &buf) == 0) | |||
{ | |||
// Note: this returns space available to non-super user | |||
free_space = (int64) buf.f_bsize * (int64) buf.f_bavail; | |||
} | |||
return free_space; | |||
} | |||
//============================================================================== | |||
bool File::isOnCDRomDrive() const throw() | |||
{ | |||
struct statfs buf; | |||
@@ -353,7 +198,6 @@ bool File::isOnHardDisk() const throw() | |||
return true; | |||
} | |||
//============================================================================== | |||
const File File::getSpecialLocation (const SpecialLocationType type) | |||
{ | |||
@@ -439,10 +283,6 @@ bool File::setAsCurrentWorkingDirectory() const throw() | |||
return chdir (getFullPathName().toUTF8()) == 0; | |||
} | |||
//============================================================================== | |||
const tchar File::separator = T('/'); | |||
const tchar* File::separatorString = T("/"); | |||
//============================================================================== | |||
struct FindFileStruct | |||
{ | |||
@@ -40,12 +40,17 @@ BEGIN_JUCE_NAMESPACE | |||
#include "../../../src/juce_core/threads/juce_CriticalSection.h" | |||
#include "../../../src/juce_core/threads/juce_WaitableEvent.h" | |||
#include "../../../src/juce_core/threads/juce_InterProcessLock.h" | |||
#include "../../../src/juce_core/threads/juce_Thread.h" | |||
#include "../../../src/juce_core/threads/juce_Process.h" | |||
#include "../../../src/juce_core/io/files/juce_File.h" | |||
#include "../../../src/juce_core/basics/juce_SystemStats.h" | |||
//============================================================================== | |||
/* | |||
Note that a lot of methods that you'd expect to find in this file actually | |||
live in juce_posix_SharedCode.cpp! | |||
*/ | |||
#ifndef CPU_ISSET | |||
#undef SUPPORT_AFFINITIES | |||
#endif | |||
@@ -169,143 +174,6 @@ void Thread::yield() throw() | |||
sched_yield(); | |||
} | |||
void JUCE_CALLTYPE Thread::sleep (int millisecs) throw() | |||
{ | |||
struct timespec time; | |||
time.tv_sec = millisecs / 1000; | |||
time.tv_nsec = (millisecs % 1000) * 1000000; | |||
nanosleep (&time, 0); | |||
} | |||
//============================================================================== | |||
CriticalSection::CriticalSection() throw() | |||
{ | |||
pthread_mutexattr_t atts; | |||
pthread_mutexattr_init (&atts); | |||
pthread_mutexattr_settype (&atts, PTHREAD_MUTEX_RECURSIVE); | |||
pthread_mutex_init (&internal, &atts); | |||
} | |||
CriticalSection::~CriticalSection() throw() | |||
{ | |||
pthread_mutex_destroy (&internal); | |||
} | |||
void CriticalSection::enter() const throw() | |||
{ | |||
pthread_mutex_lock (&internal); | |||
} | |||
bool CriticalSection::tryEnter() const throw() | |||
{ | |||
return pthread_mutex_trylock (&internal) == 0; | |||
} | |||
void CriticalSection::exit() const throw() | |||
{ | |||
pthread_mutex_unlock (&internal); | |||
} | |||
//============================================================================== | |||
struct EventStruct | |||
{ | |||
pthread_cond_t condition; | |||
pthread_mutex_t mutex; | |||
bool triggered; | |||
}; | |||
WaitableEvent::WaitableEvent() throw() | |||
{ | |||
EventStruct* const es = new EventStruct(); | |||
es->triggered = false; | |||
pthread_cond_init (&es->condition, 0); | |||
pthread_mutex_init (&es->mutex, 0); | |||
internal = es; | |||
} | |||
WaitableEvent::~WaitableEvent() throw() | |||
{ | |||
EventStruct* const es = (EventStruct*)internal; | |||
pthread_cond_destroy (&es->condition); | |||
pthread_mutex_destroy (&es->mutex); | |||
delete es; | |||
} | |||
bool WaitableEvent::wait (const int timeOutMillisecs) const throw() | |||
{ | |||
EventStruct* const es = (EventStruct*)internal; | |||
bool ok = true; | |||
pthread_mutex_lock (&es->mutex); | |||
if (! es->triggered) | |||
{ | |||
if (timeOutMillisecs < 0) | |||
{ | |||
pthread_cond_wait (&es->condition, &es->mutex); | |||
} | |||
else | |||
{ | |||
struct timespec time; | |||
struct timeval t; | |||
int timeout = 0; | |||
gettimeofday (&t, 0); | |||
time.tv_sec = t.tv_sec + (timeOutMillisecs / 1000); | |||
time.tv_nsec = (t.tv_usec + ((timeOutMillisecs % 1000) * 1000)) * 1000; | |||
while (time.tv_nsec >= 1000000000) | |||
{ | |||
time.tv_nsec -= 1000000000; | |||
time.tv_sec++; | |||
} | |||
while (! timeout) | |||
{ | |||
timeout = pthread_cond_timedwait (&es->condition, &es->mutex, &time); | |||
if (! timeout) | |||
// Success | |||
break; | |||
if (timeout == EINTR) | |||
// Go round again | |||
timeout = 0; | |||
} | |||
} | |||
ok = es->triggered; | |||
} | |||
es->triggered = false; | |||
pthread_mutex_unlock (&es->mutex); | |||
return ok; | |||
} | |||
void WaitableEvent::signal() const throw() | |||
{ | |||
EventStruct* const es = (EventStruct*)internal; | |||
pthread_mutex_lock (&es->mutex); | |||
es->triggered = true; | |||
pthread_cond_broadcast (&es->condition); | |||
pthread_mutex_unlock (&es->mutex); | |||
} | |||
void WaitableEvent::reset() const throw() | |||
{ | |||
EventStruct* const es = (EventStruct*)internal; | |||
pthread_mutex_lock (&es->mutex); | |||
es->triggered = false; | |||
pthread_mutex_unlock (&es->mutex); | |||
} | |||
//============================================================================== | |||
// sets the process to 0=low priority, 1=normal, 2=high, 3=realtime | |||
@@ -404,82 +272,4 @@ void* Process::getProcedureEntryPoint (void* libraryHandle, const String& proced | |||
#endif | |||
//============================================================================== | |||
InterProcessLock::InterProcessLock (const String& name_) throw() | |||
: internal (0), | |||
name (name_), | |||
reentrancyLevel (0) | |||
{ | |||
const File tempDir (File::getSpecialLocation (File::tempDirectory)); | |||
const File temp (tempDir.getChildFile (name)); | |||
temp.create(); | |||
internal = (void*) open (temp.getFullPathName().toUTF8(), 'a'); | |||
} | |||
InterProcessLock::~InterProcessLock() throw() | |||
{ | |||
while (reentrancyLevel > 0) | |||
this->exit(); | |||
#if JUCE_64BIT | |||
close ((long long) internal); | |||
#else | |||
close ((int) internal); | |||
#endif | |||
} | |||
bool InterProcessLock::enter (const int timeOutMillisecs) throw() | |||
{ | |||
if (internal == 0) | |||
return false; | |||
if (reentrancyLevel != 0) | |||
return true; | |||
if (timeOutMillisecs <= 0) | |||
{ | |||
if (flock ((long) internal, | |||
timeOutMillisecs < 0 ? LOCK_EX | |||
: (LOCK_EX | LOCK_NB)) == 0) | |||
{ | |||
++reentrancyLevel; | |||
return true; | |||
} | |||
} | |||
else | |||
{ | |||
const int64 endTime = Time::currentTimeMillis() + timeOutMillisecs; | |||
for (;;) | |||
{ | |||
if (flock ((long) internal, LOCK_EX | LOCK_NB) == 0) | |||
{ | |||
++reentrancyLevel; | |||
return true; | |||
} | |||
if (Time::currentTimeMillis() >= endTime) | |||
break; | |||
Thread::sleep (10); | |||
} | |||
} | |||
return false; | |||
} | |||
void InterProcessLock::exit() throw() | |||
{ | |||
if (reentrancyLevel > 0 && internal != 0) | |||
{ | |||
--reentrancyLevel; | |||
const int result = flock ((long) internal, LOCK_UN); | |||
(void) result; | |||
jassert (result == 0); | |||
} | |||
} | |||
END_JUCE_NAMESPACE |
@@ -50,12 +50,18 @@ BEGIN_JUCE_NAMESPACE | |||
#include "../../../src/juce_core/basics/juce_SystemStats.h" | |||
#include "../../../src/juce_core/misc/juce_PlatformUtilities.h" | |||
#include "../../../src/juce_core/io/files/juce_NamedPipe.h" | |||
#include "../../../src/juce_core/threads/juce_InterProcessLock.h" | |||
#include "../../../src/juce_core/threads/juce_Thread.h" | |||
//============================================================================== | |||
const tchar File::separator = T('/'); | |||
const tchar* File::separatorString = T("/"); | |||
/* | |||
Note that a lot of methods that you'd expect to find in this file actually | |||
live in juce_posix_SharedCode.cpp! | |||
*/ | |||
#include "juce_posix_SharedCode.cpp" | |||
//============================================================================== | |||
static File executableFile; | |||
@@ -193,54 +199,6 @@ const String PlatformUtilities::convertToPrecomposedUnicode (const String& s) | |||
} | |||
//============================================================================== | |||
static bool juce_stat (const String& fileName, struct stat& info) throw() | |||
{ | |||
return fileName.isNotEmpty() | |||
&& (stat (fileName.toUTF8(), &info) == 0); | |||
} | |||
//============================================================================== | |||
bool juce_isDirectory (const String& fileName) throw() | |||
{ | |||
if (fileName.isEmpty()) | |||
return true; | |||
struct stat info; | |||
return juce_stat (fileName, info) | |||
&& ((info.st_mode & S_IFDIR) != 0); | |||
} | |||
bool juce_fileExists (const String& fileName, const bool dontCountDirectories) throw() | |||
{ | |||
if (fileName.isEmpty()) | |||
return false; | |||
const char* const fileNameUTF8 = fileName.toUTF8(); | |||
bool exists = access (fileNameUTF8, F_OK) == 0; | |||
if (exists && dontCountDirectories) | |||
{ | |||
struct stat info; | |||
const int res = stat (fileNameUTF8, &info); | |||
if (res == 0 && (info.st_mode & S_IFDIR) != 0) | |||
exists = false; | |||
} | |||
return exists; | |||
} | |||
int64 juce_getFileSize (const String& fileName) throw() | |||
{ | |||
struct stat info; | |||
if (juce_stat (fileName, info)) | |||
return info.st_size; | |||
return 0; | |||
} | |||
const unsigned int macTimeToUnixTimeDiff = 0x7c25be90; | |||
static uint64 utcDateTimeToUnixTime (const UTCDateTime& d) throw() | |||
@@ -328,11 +286,6 @@ bool juce_setFileTimes (const String& fileName, | |||
return false; | |||
} | |||
bool juce_canWriteToFile (const String& fileName) throw() | |||
{ | |||
return access (fileName.toUTF8(), W_OK) == 0; | |||
} | |||
bool juce_setFileReadOnly (const String& fileName, bool isReadOnly) throw() | |||
{ | |||
const char* const fileNameUTF8 = fileName.toUTF8(); | |||
@@ -358,16 +311,6 @@ bool juce_setFileReadOnly (const String& fileName, bool isReadOnly) throw() | |||
return ok; | |||
} | |||
bool juce_deleteFile (const String& fileName) throw() | |||
{ | |||
const char* const fileNameUTF8 = fileName.toUTF8(); | |||
if (juce_isDirectory (fileName)) | |||
return rmdir (fileNameUTF8) == 0; | |||
else | |||
return remove (fileNameUTF8) == 0; | |||
} | |||
bool juce_copyFile (const String& src, const String& dst) throw() | |||
{ | |||
const File destFile (dst); | |||
@@ -446,97 +389,6 @@ bool juce_copyFile (const String& src, const String& dst) throw() | |||
return false; | |||
} | |||
bool juce_moveFile (const String& source, const String& dest) throw() | |||
{ | |||
if (rename (source.toUTF8(), dest.toUTF8()) == 0) | |||
return true; | |||
if (juce_canWriteToFile (source) | |||
&& juce_copyFile (source, dest)) | |||
{ | |||
if (juce_deleteFile (source)) | |||
return true; | |||
juce_deleteFile (dest); | |||
} | |||
return false; | |||
} | |||
void juce_createDirectory (const String& fileName) throw() | |||
{ | |||
mkdir (fileName.toUTF8(), 0777); | |||
} | |||
void* juce_fileOpen (const String& fileName, bool forWriting) throw() | |||
{ | |||
const char* const fileNameUTF8 = fileName.toUTF8(); | |||
int flags = O_RDONLY; | |||
if (forWriting) | |||
{ | |||
if (juce_fileExists (fileName, false)) | |||
{ | |||
const int f = open (fileNameUTF8, O_RDWR, 00644); | |||
if (f != -1) | |||
lseek (f, 0, SEEK_END); | |||
return (void*) f; | |||
} | |||
else | |||
{ | |||
flags = O_RDWR + O_CREAT; | |||
} | |||
} | |||
return (void*) open (fileNameUTF8, flags, 00644); | |||
} | |||
void juce_fileClose (void* handle) throw() | |||
{ | |||
if (handle != 0) | |||
close ((int) handle); | |||
} | |||
int juce_fileRead (void* handle, void* buffer, int size) throw() | |||
{ | |||
if (handle != 0) | |||
return read ((int) handle, buffer, size); | |||
return 0; | |||
} | |||
int juce_fileWrite (void* handle, const void* buffer, int size) throw() | |||
{ | |||
if (handle != 0) | |||
return write ((int) handle, buffer, size); | |||
return 0; | |||
} | |||
int64 juce_fileSetPosition (void* handle, int64 pos) throw() | |||
{ | |||
if (handle != 0 && lseek ((int) handle, pos, SEEK_SET) == pos) | |||
return pos; | |||
return -1; | |||
} | |||
int64 juce_fileGetPosition (void* handle) throw() | |||
{ | |||
if (handle != 0) | |||
return lseek ((int) handle, 0, SEEK_CUR); | |||
else | |||
return -1; | |||
} | |||
void juce_fileFlush (void* handle) throw() | |||
{ | |||
if (handle != 0) | |||
fsync ((int) handle); | |||
} | |||
const StringArray juce_getFileSystemRoots() throw() | |||
{ | |||
StringArray s; | |||
@@ -544,40 +396,6 @@ const StringArray juce_getFileSystemRoots() throw() | |||
return s; | |||
} | |||
const String juce_getVolumeLabel (const String& filenameOnVolume, int& volumeSerialNumber) throw() | |||
{ | |||
volumeSerialNumber = 0; | |||
return String::empty; | |||
} | |||
// if this file doesn't exist, find a parent of it that does.. | |||
static bool doStatFS (const File* file, struct statfs& result) throw() | |||
{ | |||
File f (*file); | |||
for (int i = 5; --i >= 0;) | |||
{ | |||
if (f.exists()) | |||
break; | |||
f = f.getParentDirectory(); | |||
} | |||
return statfs (f.getFullPathName().toUTF8(), &result) == 0; | |||
} | |||
int64 File::getBytesFreeOnVolume() const throw() | |||
{ | |||
int64 free_space = 0; | |||
struct statfs buf; | |||
if (doStatFS (this, buf)) | |||
// Note: this returns space available to non-super user | |||
free_space = (int64) buf.f_bsize * (int64) buf.f_bavail; | |||
return free_space; | |||
} | |||
//============================================================================== | |||
static bool isFileOnDriveType (const File* const f, const char** types) throw() | |||
{ | |||
@@ -609,6 +427,7 @@ bool File::isOnHardDisk() const throw() | |||
return ! (isOnCDRomDrive() || isFileOnDriveType (this, (const char**) nonHDTypes)); | |||
} | |||
//============================================================================== | |||
const File File::getSpecialLocation (const SpecialLocationType type) | |||
{ | |||
@@ -43,117 +43,14 @@ BEGIN_JUCE_NAMESPACE | |||
#include "../../../src/juce_core/threads/juce_WaitableEvent.h" | |||
#include "../../../src/juce_core/threads/juce_Thread.h" | |||
#include "../../../src/juce_core/threads/juce_Process.h" | |||
#include "../../../src/juce_core/threads/juce_InterProcessLock.h" | |||
#include "../../../src/juce_core/misc/juce_PlatformUtilities.h" | |||
#include "../../../src/juce_core/io/files/juce_File.h" | |||
//============================================================================== | |||
CriticalSection::CriticalSection() throw() | |||
{ | |||
pthread_mutexattr_t atts; | |||
pthread_mutexattr_init (&atts); | |||
pthread_mutexattr_settype (&atts, PTHREAD_MUTEX_RECURSIVE); | |||
pthread_mutex_init (&internal, &atts); | |||
} | |||
CriticalSection::~CriticalSection() throw() | |||
{ | |||
pthread_mutex_destroy (&internal); | |||
} | |||
void CriticalSection::enter() const throw() | |||
{ | |||
pthread_mutex_lock (&internal); | |||
} | |||
bool CriticalSection::tryEnter() const throw() | |||
{ | |||
return pthread_mutex_trylock (&internal) == 0; | |||
} | |||
void CriticalSection::exit() const throw() | |||
{ | |||
pthread_mutex_unlock (&internal); | |||
} | |||
//============================================================================== | |||
struct EventStruct | |||
{ | |||
pthread_cond_t condition; | |||
pthread_mutex_t mutex; | |||
bool triggered; | |||
}; | |||
WaitableEvent::WaitableEvent() throw() | |||
{ | |||
EventStruct* const es = new EventStruct(); | |||
es->triggered = false; | |||
pthread_cond_init (&es->condition, 0); | |||
pthread_mutex_init (&es->mutex, 0); | |||
internal = es; | |||
} | |||
WaitableEvent::~WaitableEvent() throw() | |||
{ | |||
EventStruct* const es = (EventStruct*) internal; | |||
pthread_cond_destroy (&es->condition); | |||
pthread_mutex_destroy (&es->mutex); | |||
delete es; | |||
} | |||
bool WaitableEvent::wait (const int timeOutMillisecs) const throw() | |||
{ | |||
EventStruct* const es = (EventStruct*) internal; | |||
bool ok = true; | |||
pthread_mutex_lock (&es->mutex); | |||
if (! es->triggered) | |||
{ | |||
if (timeOutMillisecs < 0) | |||
{ | |||
pthread_cond_wait (&es->condition, &es->mutex); | |||
} | |||
else | |||
{ | |||
struct timespec time; | |||
time.tv_sec = timeOutMillisecs / 1000; | |||
time.tv_nsec = (timeOutMillisecs % 1000) * 1000000; | |||
pthread_cond_timedwait_relative_np (&es->condition, &es->mutex, &time); | |||
} | |||
ok = es->triggered; | |||
} | |||
es->triggered = false; | |||
pthread_mutex_unlock (&es->mutex); | |||
return ok; | |||
} | |||
void WaitableEvent::signal() const throw() | |||
{ | |||
EventStruct* const es = (EventStruct*) internal; | |||
pthread_mutex_lock (&es->mutex); | |||
es->triggered = true; | |||
pthread_cond_broadcast (&es->condition); | |||
pthread_mutex_unlock (&es->mutex); | |||
} | |||
void WaitableEvent::reset() const throw() | |||
{ | |||
EventStruct* const es = (EventStruct*) internal; | |||
pthread_mutex_lock (&es->mutex); | |||
es->triggered = false; | |||
pthread_mutex_unlock (&es->mutex); | |||
} | |||
/* | |||
Note that a lot of methods that you'd expect to find in this file actually | |||
live in juce_posix_SharedCode.cpp! | |||
*/ | |||
//============================================================================== | |||
void JUCE_API juce_threadEntryPoint (void*); | |||
@@ -215,15 +112,6 @@ void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) throw() | |||
jassertfalse | |||
} | |||
void JUCE_CALLTYPE Thread::sleep (int millisecs) throw() | |||
{ | |||
struct timespec time; | |||
time.tv_sec = millisecs / 1000; | |||
time.tv_nsec = (millisecs % 1000) * 1000000; | |||
nanosleep (&time, 0); | |||
} | |||
//============================================================================== | |||
bool JUCE_CALLTYPE juce_isRunningUnderDebugger() throw() | |||
{ | |||
@@ -311,77 +199,5 @@ void* Process::getProcedureEntryPoint (void* h, const String& procedureName) | |||
return 0; | |||
} | |||
//============================================================================== | |||
InterProcessLock::InterProcessLock (const String& name_) throw() | |||
: internal (0), | |||
name (name_), | |||
reentrancyLevel (0) | |||
{ | |||
const File tempDir (File::getSpecialLocation (File::tempDirectory)); | |||
const File temp (tempDir.getChildFile (name)); | |||
temp.create(); | |||
internal = (void*) open (temp.getFullPathName().toUTF8(), O_NONBLOCK | O_RDONLY); | |||
} | |||
InterProcessLock::~InterProcessLock() throw() | |||
{ | |||
while (reentrancyLevel > 0) | |||
this->exit(); | |||
close ((int) internal); | |||
} | |||
bool InterProcessLock::enter (const int timeOutMillisecs) throw() | |||
{ | |||
if (internal == 0) | |||
return false; | |||
if (reentrancyLevel != 0) | |||
return true; | |||
if (timeOutMillisecs <= 0) | |||
{ | |||
if (flock ((int) internal, | |||
timeOutMillisecs < 0 ? LOCK_EX | |||
: (LOCK_EX | LOCK_NB)) == 0) | |||
{ | |||
++reentrancyLevel; | |||
return true; | |||
} | |||
} | |||
else | |||
{ | |||
const int64 endTime = Time::currentTimeMillis() + timeOutMillisecs; | |||
for (;;) | |||
{ | |||
if (flock ((int) internal, LOCK_EX | LOCK_NB) == 0) | |||
{ | |||
++reentrancyLevel; | |||
return true; | |||
} | |||
if (Time::currentTimeMillis() >= endTime) | |||
break; | |||
Thread::sleep (10); | |||
} | |||
} | |||
return false; | |||
} | |||
void InterProcessLock::exit() throw() | |||
{ | |||
if (reentrancyLevel > 0 && internal != 0) | |||
{ | |||
--reentrancyLevel; | |||
const int result = flock ((int) internal, LOCK_UN); | |||
(void) result; | |||
jassert (result == 0); | |||
} | |||
} | |||
END_JUCE_NAMESPACE |
@@ -0,0 +1,466 @@ | |||
/* | |||
============================================================================== | |||
This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
Copyright 2004-7 by Raw Material Software ltd. | |||
------------------------------------------------------------------------------ | |||
JUCE can be redistributed and/or modified under the terms of the | |||
GNU General Public License, as published by the Free Software Foundation; | |||
either version 2 of the License, or (at your option) any later version. | |||
JUCE is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||
Boston, MA 02111-1307 USA | |||
------------------------------------------------------------------------------ | |||
If you'd like to release a closed-source product which uses JUCE, commercial | |||
licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||
more information. | |||
============================================================================== | |||
*/ | |||
/* | |||
This file contains posix routines that are common to both the Linux and Mac builds. | |||
It gets included directly in the cpp files for these platforms. | |||
*/ | |||
//============================================================================== | |||
CriticalSection::CriticalSection() throw() | |||
{ | |||
pthread_mutexattr_t atts; | |||
pthread_mutexattr_init (&atts); | |||
pthread_mutexattr_settype (&atts, PTHREAD_MUTEX_RECURSIVE); | |||
pthread_mutex_init (&internal, &atts); | |||
} | |||
CriticalSection::~CriticalSection() throw() | |||
{ | |||
pthread_mutex_destroy (&internal); | |||
} | |||
void CriticalSection::enter() const throw() | |||
{ | |||
pthread_mutex_lock (&internal); | |||
} | |||
bool CriticalSection::tryEnter() const throw() | |||
{ | |||
return pthread_mutex_trylock (&internal) == 0; | |||
} | |||
void CriticalSection::exit() const throw() | |||
{ | |||
pthread_mutex_unlock (&internal); | |||
} | |||
//============================================================================== | |||
struct EventStruct | |||
{ | |||
pthread_cond_t condition; | |||
pthread_mutex_t mutex; | |||
bool triggered; | |||
}; | |||
WaitableEvent::WaitableEvent() throw() | |||
{ | |||
EventStruct* const es = new EventStruct(); | |||
es->triggered = false; | |||
pthread_cond_init (&es->condition, 0); | |||
pthread_mutex_init (&es->mutex, 0); | |||
internal = es; | |||
} | |||
WaitableEvent::~WaitableEvent() throw() | |||
{ | |||
EventStruct* const es = (EventStruct*) internal; | |||
pthread_cond_destroy (&es->condition); | |||
pthread_mutex_destroy (&es->mutex); | |||
delete es; | |||
} | |||
bool WaitableEvent::wait (const int timeOutMillisecs) const throw() | |||
{ | |||
EventStruct* const es = (EventStruct*) internal; | |||
bool ok = true; | |||
pthread_mutex_lock (&es->mutex); | |||
if (! es->triggered) | |||
{ | |||
if (timeOutMillisecs < 0) | |||
{ | |||
pthread_cond_wait (&es->condition, &es->mutex); | |||
} | |||
else | |||
{ | |||
struct timespec time; | |||
#if JUCE_MAC | |||
time.tv_sec = timeOutMillisecs / 1000; | |||
time.tv_nsec = (timeOutMillisecs % 1000) * 1000000; | |||
pthread_cond_timedwait_relative_np (&es->condition, &es->mutex, &time); | |||
#else | |||
struct timeval t; | |||
int timeout = 0; | |||
gettimeofday (&t, 0); | |||
time.tv_sec = t.tv_sec + (timeOutMillisecs / 1000); | |||
time.tv_nsec = (t.tv_usec + ((timeOutMillisecs % 1000) * 1000)) * 1000; | |||
while (time.tv_nsec >= 1000000000) | |||
{ | |||
time.tv_nsec -= 1000000000; | |||
time.tv_sec++; | |||
} | |||
while (! timeout) | |||
{ | |||
timeout = pthread_cond_timedwait (&es->condition, &es->mutex, &time); | |||
if (! timeout) | |||
// Success | |||
break; | |||
if (timeout == EINTR) | |||
// Go round again | |||
timeout = 0; | |||
} | |||
#endif | |||
} | |||
ok = es->triggered; | |||
} | |||
es->triggered = false; | |||
pthread_mutex_unlock (&es->mutex); | |||
return ok; | |||
} | |||
void WaitableEvent::signal() const throw() | |||
{ | |||
EventStruct* const es = (EventStruct*) internal; | |||
pthread_mutex_lock (&es->mutex); | |||
es->triggered = true; | |||
pthread_cond_broadcast (&es->condition); | |||
pthread_mutex_unlock (&es->mutex); | |||
} | |||
void WaitableEvent::reset() const throw() | |||
{ | |||
EventStruct* const es = (EventStruct*) internal; | |||
pthread_mutex_lock (&es->mutex); | |||
es->triggered = false; | |||
pthread_mutex_unlock (&es->mutex); | |||
} | |||
//============================================================================== | |||
void JUCE_CALLTYPE Thread::sleep (int millisecs) throw() | |||
{ | |||
struct timespec time; | |||
time.tv_sec = millisecs / 1000; | |||
time.tv_nsec = (millisecs % 1000) * 1000000; | |||
nanosleep (&time, 0); | |||
} | |||
//============================================================================== | |||
const tchar File::separator = T('/'); | |||
const tchar* File::separatorString = T("/"); | |||
//============================================================================== | |||
bool juce_copyFile (const String& s, const String& d) throw(); | |||
static bool juce_stat (const String& fileName, struct stat& info) throw() | |||
{ | |||
return fileName.isNotEmpty() | |||
&& (stat (fileName.toUTF8(), &info) == 0); | |||
} | |||
bool juce_isDirectory (const String& fileName) throw() | |||
{ | |||
struct stat info; | |||
return fileName.isEmpty() | |||
|| (juce_stat (fileName, info) | |||
&& ((info.st_mode & S_IFDIR) != 0)); | |||
} | |||
bool juce_fileExists (const String& fileName, const bool dontCountDirectories) throw() | |||
{ | |||
if (fileName.isEmpty()) | |||
return false; | |||
const char* const fileNameUTF8 = fileName.toUTF8(); | |||
bool exists = access (fileNameUTF8, F_OK) == 0; | |||
if (exists && dontCountDirectories) | |||
{ | |||
struct stat info; | |||
const int res = stat (fileNameUTF8, &info); | |||
if (res == 0 && (info.st_mode & S_IFDIR) != 0) | |||
exists = false; | |||
} | |||
return exists; | |||
} | |||
int64 juce_getFileSize (const String& fileName) throw() | |||
{ | |||
struct stat info; | |||
return juce_stat (fileName, info) ? info.st_size : 0; | |||
} | |||
//============================================================================== | |||
bool juce_canWriteToFile (const String& fileName) throw() | |||
{ | |||
return access (fileName.toUTF8(), W_OK) == 0; | |||
} | |||
bool juce_deleteFile (const String& fileName) throw() | |||
{ | |||
const char* const fileNameUTF8 = fileName.toUTF8(); | |||
if (juce_isDirectory (fileName)) | |||
return rmdir (fileNameUTF8) == 0; | |||
else | |||
return remove (fileNameUTF8) == 0; | |||
} | |||
bool juce_moveFile (const String& source, const String& dest) throw() | |||
{ | |||
if (rename (source.toUTF8(), dest.toUTF8()) == 0) | |||
return true; | |||
if (juce_canWriteToFile (source) | |||
&& juce_copyFile (source, dest)) | |||
{ | |||
if (juce_deleteFile (source)) | |||
return true; | |||
juce_deleteFile (dest); | |||
} | |||
return false; | |||
} | |||
void juce_createDirectory (const String& fileName) throw() | |||
{ | |||
mkdir (fileName.toUTF8(), 0777); | |||
} | |||
void* juce_fileOpen (const String& fileName, bool forWriting) throw() | |||
{ | |||
const char* const fileNameUTF8 = fileName.toUTF8(); | |||
int flags = O_RDONLY; | |||
if (forWriting) | |||
{ | |||
if (juce_fileExists (fileName, false)) | |||
{ | |||
const int f = open (fileNameUTF8, O_RDWR, 00644); | |||
if (f != -1) | |||
lseek (f, 0, SEEK_END); | |||
return (void*) f; | |||
} | |||
else | |||
{ | |||
flags = O_RDWR + O_CREAT; | |||
} | |||
} | |||
return (void*) open (fileNameUTF8, flags, 00644); | |||
} | |||
void juce_fileClose (void* handle) throw() | |||
{ | |||
if (handle != 0) | |||
close ((int) handle); | |||
} | |||
int juce_fileRead (void* handle, void* buffer, int size) throw() | |||
{ | |||
if (handle != 0) | |||
return read ((int) handle, buffer, size); | |||
return 0; | |||
} | |||
int juce_fileWrite (void* handle, const void* buffer, int size) throw() | |||
{ | |||
if (handle != 0) | |||
return write ((int) handle, buffer, size); | |||
return 0; | |||
} | |||
int64 juce_fileSetPosition (void* handle, int64 pos) throw() | |||
{ | |||
if (handle != 0 && lseek ((int) handle, pos, SEEK_SET) == pos) | |||
return pos; | |||
return -1; | |||
} | |||
int64 juce_fileGetPosition (void* handle) throw() | |||
{ | |||
if (handle != 0) | |||
return lseek ((int) handle, 0, SEEK_CUR); | |||
else | |||
return -1; | |||
} | |||
void juce_fileFlush (void* handle) throw() | |||
{ | |||
if (handle != 0) | |||
fsync ((int) handle); | |||
} | |||
//============================================================================== | |||
// if this file doesn't exist, find a parent of it that does.. | |||
static bool doStatFS (const File* file, struct statfs& result) throw() | |||
{ | |||
File f (*file); | |||
for (int i = 5; --i >= 0;) | |||
{ | |||
if (f.exists()) | |||
break; | |||
f = f.getParentDirectory(); | |||
} | |||
return statfs (f.getFullPathName().toUTF8(), &result) == 0; | |||
} | |||
int64 File::getBytesFreeOnVolume() const throw() | |||
{ | |||
int64 free_space = 0; | |||
struct statfs buf; | |||
if (doStatFS (this, buf)) | |||
// Note: this returns space available to non-super user | |||
free_space = (int64) buf.f_bsize * (int64) buf.f_bavail; | |||
return free_space; | |||
} | |||
const String juce_getVolumeLabel (const String& filenameOnVolume, | |||
int& volumeSerialNumber) throw() | |||
{ | |||
// There is no equivalent on Linux | |||
volumeSerialNumber = 0; | |||
return String::empty; | |||
} | |||
//============================================================================== | |||
#if JUCE_64BIT | |||
#define filedesc ((long long) internal) | |||
#else | |||
#define filedesc ((int) internal) | |||
#endif | |||
InterProcessLock::InterProcessLock (const String& name_) throw() | |||
: internal (0), | |||
name (name_), | |||
reentrancyLevel (0) | |||
{ | |||
const File tempDir (File::getSpecialLocation (File::tempDirectory)); | |||
const File temp (tempDir.getChildFile (name)); | |||
temp.create(); | |||
internal = (void*) open (temp.getFullPathName().toUTF8(), O_RDWR); | |||
} | |||
InterProcessLock::~InterProcessLock() throw() | |||
{ | |||
while (reentrancyLevel > 0) | |||
this->exit(); | |||
close (filedesc); | |||
} | |||
bool InterProcessLock::enter (const int timeOutMillisecs) throw() | |||
{ | |||
if (internal == 0) | |||
return false; | |||
if (reentrancyLevel != 0) | |||
return true; | |||
const int64 endTime = Time::currentTimeMillis() + timeOutMillisecs; | |||
struct flock fl; | |||
zerostruct (fl); | |||
fl.l_whence = SEEK_SET; | |||
fl.l_type = F_WRLCK; | |||
for (;;) | |||
{ | |||
const int result = fcntl (filedesc, F_SETLK, &fl); | |||
if (result >= 0) | |||
{ | |||
++reentrancyLevel; | |||
return true; | |||
} | |||
if (errno != EINTR) | |||
{ | |||
if (timeOutMillisecs == 0 | |||
|| (timeOutMillisecs > 0 && Time::currentTimeMillis() >= endTime)) | |||
break; | |||
Thread::sleep (10); | |||
} | |||
} | |||
return false; | |||
} | |||
void InterProcessLock::exit() throw() | |||
{ | |||
if (reentrancyLevel > 0 && internal != 0) | |||
{ | |||
--reentrancyLevel; | |||
struct flock fl; | |||
zerostruct (fl); | |||
fl.l_whence = SEEK_SET; | |||
fl.l_type = F_UNLCK; | |||
for (;;) | |||
{ | |||
const int result = fcntl (filedesc, F_SETLKW, &fl); | |||
if (result >= 0 || errno != EINTR) | |||
break; | |||
} | |||
} | |||
} | |||
@@ -23,7 +23,8 @@ Changelist for version 1.46 | |||
- new method: PlatformUtilities::launchEmailWithAttachments | |||
- new classes: AudioThumbnail and AudioThumbnailCache, which allow easy rendering of low-res waveform previews | |||
- new classes: InputSource and FileInputSource. These encapsulate some kind of resource, and also replace the XmlInputSource class. | |||
- moved some of the posix code that was the same in the mac and linux builds into a single, shared file | |||
- fixed InterprocessLock on mac/linux so that it can't get stuck when an app quits unexpectedly | |||
============================================================================== | |||
Changelist for version 1.45 | |||
@@ -103,7 +103,7 @@ public: | |||
bool moreThanOneInstanceAllowed() | |||
{ | |||
return true; | |||
return false; | |||
} | |||
void anotherInstanceStarted (const String& commandLine) | |||
@@ -57,9 +57,9 @@ PluginDescription::PluginDescription (const PluginDescription& other) throw() | |||
manufacturerName (other.manufacturerName), | |||
version (other.version), | |||
file (other.file), | |||
lastFileModTime (other.lastFileModTime), | |||
uid (other.uid), | |||
isInstrument (other.isInstrument), | |||
lastFileModTime (other.lastFileModTime), | |||
numInputChannels (other.numInputChannels), | |||
numOutputChannels (other.numOutputChannels) | |||
{ | |||