From ff3c2e9fceed6da93f8476bc4dd7b153f65c16da Mon Sep 17 00:00:00 2001 From: jules Date: Sun, 16 Mar 2008 14:55:35 +0000 Subject: [PATCH] --- build/linux/JUCE.make | 20 +- .../juce_linux_Files.cpp | 182 +------ .../juce_linux_Threads.cpp | 222 +-------- .../platform_specific_code/juce_mac_Files.cpp | 201 +------- .../juce_mac_Threads.cpp | 192 +------- .../juce_posix_SharedCode.cpp | 466 ++++++++++++++++++ docs/JUCE changelist.txt | 3 +- extras/juce demo/src/ApplicationStartup.cpp | 2 +- .../audio/plugins/juce_PluginDescription.cpp | 2 +- 9 files changed, 520 insertions(+), 770 deletions(-) create mode 100644 build/macosx/platform_specific_code/juce_posix_SharedCode.cpp diff --git a/build/linux/JUCE.make b/build/linux/JUCE.make index e478299d94..276e383608 100644 --- a/build/linux/JUCE.make +++ b/build/linux/JUCE.make @@ -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 $<) diff --git a/build/linux/platform_specific_code/juce_linux_Files.cpp b/build/linux/platform_specific_code/juce_linux_Files.cpp index 2084a1f3dd..2da857e5d7 100644 --- a/build/linux/platform_specific_code/juce_linux_Files.cpp +++ b/build/linux/platform_specific_code/juce_linux_Files.cpp @@ -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 { diff --git a/build/linux/platform_specific_code/juce_linux_Threads.cpp b/build/linux/platform_specific_code/juce_linux_Threads.cpp index a282004c3c..5a5bf68372 100644 --- a/build/linux/platform_specific_code/juce_linux_Threads.cpp +++ b/build/linux/platform_specific_code/juce_linux_Threads.cpp @@ -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 diff --git a/build/macosx/platform_specific_code/juce_mac_Files.cpp b/build/macosx/platform_specific_code/juce_mac_Files.cpp index 70e53d051d..ba4d1e17da 100644 --- a/build/macosx/platform_specific_code/juce_mac_Files.cpp +++ b/build/macosx/platform_specific_code/juce_mac_Files.cpp @@ -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) { diff --git a/build/macosx/platform_specific_code/juce_mac_Threads.cpp b/build/macosx/platform_specific_code/juce_mac_Threads.cpp index 2fa3b1d928..174f2f503d 100644 --- a/build/macosx/platform_specific_code/juce_mac_Threads.cpp +++ b/build/macosx/platform_specific_code/juce_mac_Threads.cpp @@ -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 diff --git a/build/macosx/platform_specific_code/juce_posix_SharedCode.cpp b/build/macosx/platform_specific_code/juce_posix_SharedCode.cpp new file mode 100644 index 0000000000..20492c4325 --- /dev/null +++ b/build/macosx/platform_specific_code/juce_posix_SharedCode.cpp @@ -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; + } + } +} + diff --git a/docs/JUCE changelist.txt b/docs/JUCE changelist.txt index df657c82bd..fe1618c5ea 100644 --- a/docs/JUCE changelist.txt +++ b/docs/JUCE changelist.txt @@ -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 diff --git a/extras/juce demo/src/ApplicationStartup.cpp b/extras/juce demo/src/ApplicationStartup.cpp index 776dc22f24..3e4441c4d8 100644 --- a/extras/juce demo/src/ApplicationStartup.cpp +++ b/extras/juce demo/src/ApplicationStartup.cpp @@ -103,7 +103,7 @@ public: bool moreThanOneInstanceAllowed() { - return true; + return false; } void anotherInstanceStarted (const String& commandLine) diff --git a/src/juce_appframework/audio/plugins/juce_PluginDescription.cpp b/src/juce_appframework/audio/plugins/juce_PluginDescription.cpp index 1873557239..96d385f42e 100644 --- a/src/juce_appframework/audio/plugins/juce_PluginDescription.cpp +++ b/src/juce_appframework/audio/plugins/juce_PluginDescription.cpp @@ -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) {