@@ -26,7 +26,7 @@ ifeq ($(CONFIG),Release) | |||||
OBJDIR := ../../bin/intermediate_linux/Release | OBJDIR := ../../bin/intermediate_linux/Release | ||||
OUTDIR := ../../bin | OUTDIR := ../../bin | ||||
CPPFLAGS := -MMD -D "LINUX=1" -D "NDEBUG=1" -I "../../" -I "/usr/include" -I "/usr/include/freetype2" | 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) | CXXFLAGS := $(CFLAGS) | ||||
LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -s | LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -s | ||||
LDDEPS := | LDDEPS := | ||||
@@ -60,6 +60,7 @@ OBJECTS := \ | |||||
$(OBJDIR)/juce_Socket.o \ | $(OBJDIR)/juce_Socket.o \ | ||||
$(OBJDIR)/juce_URL.o \ | $(OBJDIR)/juce_URL.o \ | ||||
$(OBJDIR)/juce_BufferedInputStream.o \ | $(OBJDIR)/juce_BufferedInputStream.o \ | ||||
$(OBJDIR)/juce_FileInputSource.o \ | |||||
$(OBJDIR)/juce_GZIPCompressorOutputStream.o \ | $(OBJDIR)/juce_GZIPCompressorOutputStream.o \ | ||||
$(OBJDIR)/juce_GZIPDecompressorInputStream.o \ | $(OBJDIR)/juce_GZIPDecompressorInputStream.o \ | ||||
$(OBJDIR)/juce_MemoryInputStream.o \ | $(OBJDIR)/juce_MemoryInputStream.o \ | ||||
@@ -126,6 +127,8 @@ OBJECTS := \ | |||||
$(OBJDIR)/juce_AudioFormat.o \ | $(OBJDIR)/juce_AudioFormat.o \ | ||||
$(OBJDIR)/juce_AudioFormatManager.o \ | $(OBJDIR)/juce_AudioFormatManager.o \ | ||||
$(OBJDIR)/juce_AudioSubsectionReader.o \ | $(OBJDIR)/juce_AudioSubsectionReader.o \ | ||||
$(OBJDIR)/juce_AudioThumbnail.o \ | |||||
$(OBJDIR)/juce_AudioThumbnailCache.o \ | |||||
$(OBJDIR)/juce_FlacAudioFormat.o \ | $(OBJDIR)/juce_FlacAudioFormat.o \ | ||||
$(OBJDIR)/juce_OggVorbisAudioFormat.o \ | $(OBJDIR)/juce_OggVorbisAudioFormat.o \ | ||||
$(OBJDIR)/juce_WavAudioFormat.o \ | $(OBJDIR)/juce_WavAudioFormat.o \ | ||||
@@ -568,6 +571,11 @@ $(OBJDIR)/juce_BufferedInputStream.o: ../../src/juce_core/io/streams/juce_Buffer | |||||
@echo $(notdir $<) | @echo $(notdir $<) | ||||
@$(CXX) $(CXXFLAGS) -o $@ -c $< | @$(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 | $(OBJDIR)/juce_GZIPCompressorOutputStream.o: ../../src/juce_core/io/streams/juce_GZIPCompressorOutputStream.cpp | ||||
-@$(CMD_MKOBJDIR) | -@$(CMD_MKOBJDIR) | ||||
@echo $(notdir $<) | @echo $(notdir $<) | ||||
@@ -898,6 +906,16 @@ $(OBJDIR)/juce_AudioSubsectionReader.o: ../../src/juce_appframework/audio/audio_ | |||||
@echo $(notdir $<) | @echo $(notdir $<) | ||||
@$(CXX) $(CXXFLAGS) -o $@ -c $< | @$(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 | $(OBJDIR)/juce_FlacAudioFormat.o: ../../src/juce_appframework/audio/audio_file_formats/juce_FlacAudioFormat.cpp | ||||
-@$(CMD_MKOBJDIR) | -@$(CMD_MKOBJDIR) | ||||
@echo $(notdir $<) | @echo $(notdir $<) | ||||
@@ -57,48 +57,22 @@ BEGIN_JUCE_NAMESPACE | |||||
#include "../../../src/juce_core/basics/juce_Time.h" | #include "../../../src/juce_core/basics/juce_Time.h" | ||||
#include "../../../src/juce_core/io/network/juce_URL.h" | #include "../../../src/juce_core/io/network/juce_URL.h" | ||||
#include "../../../src/juce_core/io/files/juce_NamedPipe.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, | void juce_getFileTimes (const String& fileName, | ||||
int64& modificationTime, | int64& modificationTime, | ||||
int64& accessTime, | int64& accessTime, | ||||
@@ -112,10 +86,6 @@ void juce_getFileTimes (const String& fileName, | |||||
const int res = stat (fileName.toUTF8(), &info); | const int res = stat (fileName.toUTF8(), &info); | ||||
if (res == 0) | 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; | modificationTime = (int64) info.st_mtime * 1000; | ||||
accessTime = (int64) info.st_atime * 1000; | accessTime = (int64) info.st_atime * 1000; | ||||
creationTime = (int64) info.st_ctime * 1000; | creationTime = (int64) info.st_ctime * 1000; | ||||
@@ -134,11 +104,6 @@ bool juce_setFileTimes (const String& fileName, | |||||
return utime (fileName.toUTF8(), ×) == 0; | 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() | bool juce_setFileReadOnly (const String& fileName, bool isReadOnly) throw() | ||||
{ | { | ||||
struct stat info; | struct stat info; | ||||
@@ -157,14 +122,6 @@ bool juce_setFileReadOnly (const String& fileName, bool isReadOnly) throw() | |||||
return chmod (fileName.toUTF8(), info.st_mode) == 0; | 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() | bool juce_copyFile (const String& s, const String& d) throw() | ||||
{ | { | ||||
const File source (s), dest (d); | const File source (s), dest (d); | ||||
@@ -196,97 +153,6 @@ bool juce_copyFile (const String& s, const String& d) throw() | |||||
return ok; | 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() | const StringArray juce_getFileSystemRoots() throw() | ||||
{ | { | ||||
StringArray s; | StringArray s; | ||||
@@ -294,28 +160,7 @@ const StringArray juce_getFileSystemRoots() throw() | |||||
return s; | 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() | bool File::isOnCDRomDrive() const throw() | ||||
{ | { | ||||
struct statfs buf; | struct statfs buf; | ||||
@@ -353,7 +198,6 @@ bool File::isOnHardDisk() const throw() | |||||
return true; | return true; | ||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
const File File::getSpecialLocation (const SpecialLocationType type) | const File File::getSpecialLocation (const SpecialLocationType type) | ||||
{ | { | ||||
@@ -439,10 +283,6 @@ bool File::setAsCurrentWorkingDirectory() const throw() | |||||
return chdir (getFullPathName().toUTF8()) == 0; | return chdir (getFullPathName().toUTF8()) == 0; | ||||
} | } | ||||
//============================================================================== | |||||
const tchar File::separator = T('/'); | |||||
const tchar* File::separatorString = T("/"); | |||||
//============================================================================== | //============================================================================== | ||||
struct FindFileStruct | struct FindFileStruct | ||||
{ | { | ||||
@@ -40,12 +40,17 @@ BEGIN_JUCE_NAMESPACE | |||||
#include "../../../src/juce_core/threads/juce_CriticalSection.h" | #include "../../../src/juce_core/threads/juce_CriticalSection.h" | ||||
#include "../../../src/juce_core/threads/juce_WaitableEvent.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_Thread.h" | ||||
#include "../../../src/juce_core/threads/juce_Process.h" | #include "../../../src/juce_core/threads/juce_Process.h" | ||||
#include "../../../src/juce_core/io/files/juce_File.h" | #include "../../../src/juce_core/io/files/juce_File.h" | ||||
#include "../../../src/juce_core/basics/juce_SystemStats.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 | #ifndef CPU_ISSET | ||||
#undef SUPPORT_AFFINITIES | #undef SUPPORT_AFFINITIES | ||||
#endif | #endif | ||||
@@ -169,143 +174,6 @@ void Thread::yield() throw() | |||||
sched_yield(); | 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 | // 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 | #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 | END_JUCE_NAMESPACE |
@@ -50,12 +50,18 @@ BEGIN_JUCE_NAMESPACE | |||||
#include "../../../src/juce_core/basics/juce_SystemStats.h" | #include "../../../src/juce_core/basics/juce_SystemStats.h" | ||||
#include "../../../src/juce_core/misc/juce_PlatformUtilities.h" | #include "../../../src/juce_core/misc/juce_PlatformUtilities.h" | ||||
#include "../../../src/juce_core/io/files/juce_NamedPipe.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; | 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; | const unsigned int macTimeToUnixTimeDiff = 0x7c25be90; | ||||
static uint64 utcDateTimeToUnixTime (const UTCDateTime& d) throw() | static uint64 utcDateTimeToUnixTime (const UTCDateTime& d) throw() | ||||
@@ -328,11 +286,6 @@ bool juce_setFileTimes (const String& fileName, | |||||
return false; | 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() | bool juce_setFileReadOnly (const String& fileName, bool isReadOnly) throw() | ||||
{ | { | ||||
const char* const fileNameUTF8 = fileName.toUTF8(); | const char* const fileNameUTF8 = fileName.toUTF8(); | ||||
@@ -358,16 +311,6 @@ bool juce_setFileReadOnly (const String& fileName, bool isReadOnly) throw() | |||||
return ok; | 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() | bool juce_copyFile (const String& src, const String& dst) throw() | ||||
{ | { | ||||
const File destFile (dst); | const File destFile (dst); | ||||
@@ -446,97 +389,6 @@ bool juce_copyFile (const String& src, const String& dst) throw() | |||||
return false; | 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() | const StringArray juce_getFileSystemRoots() throw() | ||||
{ | { | ||||
StringArray s; | StringArray s; | ||||
@@ -544,40 +396,6 @@ const StringArray juce_getFileSystemRoots() throw() | |||||
return s; | 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() | 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)); | return ! (isOnCDRomDrive() || isFileOnDriveType (this, (const char**) nonHDTypes)); | ||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
const File File::getSpecialLocation (const SpecialLocationType type) | 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_WaitableEvent.h" | ||||
#include "../../../src/juce_core/threads/juce_Thread.h" | #include "../../../src/juce_core/threads/juce_Thread.h" | ||||
#include "../../../src/juce_core/threads/juce_Process.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/misc/juce_PlatformUtilities.h" | ||||
#include "../../../src/juce_core/io/files/juce_File.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*); | void JUCE_API juce_threadEntryPoint (void*); | ||||
@@ -215,15 +112,6 @@ void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) throw() | |||||
jassertfalse | 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() | bool JUCE_CALLTYPE juce_isRunningUnderDebugger() throw() | ||||
{ | { | ||||
@@ -311,77 +199,5 @@ void* Process::getProcedureEntryPoint (void* h, const String& procedureName) | |||||
return 0; | 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 | 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 method: PlatformUtilities::launchEmailWithAttachments | ||||
- new classes: AudioThumbnail and AudioThumbnailCache, which allow easy rendering of low-res waveform previews | - 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. | - 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 | Changelist for version 1.45 | ||||
@@ -103,7 +103,7 @@ public: | |||||
bool moreThanOneInstanceAllowed() | bool moreThanOneInstanceAllowed() | ||||
{ | { | ||||
return true; | |||||
return false; | |||||
} | } | ||||
void anotherInstanceStarted (const String& commandLine) | void anotherInstanceStarted (const String& commandLine) | ||||
@@ -57,9 +57,9 @@ PluginDescription::PluginDescription (const PluginDescription& other) throw() | |||||
manufacturerName (other.manufacturerName), | manufacturerName (other.manufacturerName), | ||||
version (other.version), | version (other.version), | ||||
file (other.file), | file (other.file), | ||||
lastFileModTime (other.lastFileModTime), | |||||
uid (other.uid), | uid (other.uid), | ||||
isInstrument (other.isInstrument), | isInstrument (other.isInstrument), | ||||
lastFileModTime (other.lastFileModTime), | |||||
numInputChannels (other.numInputChannels), | numInputChannels (other.numInputChannels), | ||||
numOutputChannels (other.numOutputChannels) | numOutputChannels (other.numOutputChannels) | ||||
{ | { | ||||