| @@ -32,6 +32,8 @@ | |||||
| #include "linuxincludes.h" | #include "linuxincludes.h" | ||||
| #include <dlfcn.h> | #include <dlfcn.h> | ||||
| #include <sys/file.h> | #include <sys/file.h> | ||||
| #include <sys/types.h> | |||||
| #include <sys/ptrace.h> | |||||
| #include "../../../src/juce_core/basics/juce_StandardHeader.h" | #include "../../../src/juce_core/basics/juce_StandardHeader.h" | ||||
| BEGIN_JUCE_NAMESPACE | BEGIN_JUCE_NAMESPACE | ||||
| @@ -339,6 +341,26 @@ void Process::terminate() | |||||
| exit (0); | exit (0); | ||||
| } | } | ||||
| bool juce_isRunningUnderDebugger() throw() | |||||
| { | |||||
| static char testResult = 0; | |||||
| if (testResult == 0) | |||||
| { | |||||
| testResult = (ptrace (PTRACE_TRACEME, 0, 0, 0) < 0) ? 1 : -1; | |||||
| if (testResult < 0) | |||||
| ptrace (PTRACE_DETACH, 0, (caddr_t) 1, 0); | |||||
| } | |||||
| return testResult > 0; | |||||
| } | |||||
| bool Process::isRunningUnderDebugger() throw() | |||||
| { | |||||
| return juce_isRunningUnderDebugger(); | |||||
| } | |||||
| void Process::raisePrivilege() | void Process::raisePrivilege() | ||||
| { | { | ||||
| // If running suid root, change effective user | // If running suid root, change effective user | ||||
| @@ -1,364 +1,386 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| 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. | |||||
| ============================================================================== | |||||
| */ | |||||
| #include "../../../src/juce_core/basics/juce_StandardHeader.h" | |||||
| #include <pthread.h> | |||||
| #include <sched.h> | |||||
| #include <sys/file.h> | |||||
| #include <Carbon/Carbon.h> | |||||
| 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_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_signal (&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_API juce_threadEntryPoint (void*); | |||||
| void* threadEntryProc (void* userData) throw() | |||||
| { | |||||
| juce_threadEntryPoint (userData); | |||||
| return 0; | |||||
| } | |||||
| void* juce_createThread (void* userData) throw() | |||||
| { | |||||
| pthread_t handle = 0; | |||||
| if (pthread_create (&handle, 0, threadEntryProc, userData) == 0) | |||||
| { | |||||
| pthread_detach (handle); | |||||
| return (void*) handle; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| void juce_killThread (void* handle) throw() | |||||
| { | |||||
| if (handle != 0) | |||||
| pthread_cancel ((pthread_t) handle); | |||||
| } | |||||
| void juce_setCurrentThreadName (const String& /*name*/) throw() | |||||
| { | |||||
| } | |||||
| int Thread::getCurrentThreadId() throw() | |||||
| { | |||||
| return (int) pthread_self(); | |||||
| } | |||||
| void juce_setThreadPriority (void* handle, int priority) throw() | |||||
| { | |||||
| if (handle == 0) | |||||
| handle = (void*) pthread_self(); | |||||
| struct sched_param param; | |||||
| int policy; | |||||
| pthread_getschedparam ((pthread_t) handle, &policy, ¶m); | |||||
| param.sched_priority = jlimit (1, 127, 1 + (priority * 126) / 11); | |||||
| pthread_setschedparam ((pthread_t) handle, policy, ¶m); | |||||
| } | |||||
| void Thread::yield() throw() | |||||
| { | |||||
| sched_yield(); | |||||
| } | |||||
| void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) throw() | |||||
| { | |||||
| // xxx | |||||
| 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); | |||||
| } | |||||
| //============================================================================== | |||||
| void Process::raisePrivilege() | |||||
| { | |||||
| jassertfalse | |||||
| } | |||||
| void Process::lowerPrivilege() | |||||
| { | |||||
| jassertfalse | |||||
| } | |||||
| void Process::terminate() | |||||
| { | |||||
| ExitToShell(); | |||||
| } | |||||
| void Process::setPriority (ProcessPriority p) | |||||
| { | |||||
| // xxx | |||||
| } | |||||
| void* Process::loadDynamicLibrary (const String& name) | |||||
| { | |||||
| // xxx needs to use bundles | |||||
| FSSpec fs; | |||||
| if (PlatformUtilities::makeFSSpecFromPath (&fs, name)) | |||||
| { | |||||
| CFragConnectionID connID; | |||||
| Ptr mainPtr; | |||||
| Str255 errorMessage; | |||||
| Str63 nm; | |||||
| PlatformUtilities::copyToStr63 (nm, name); | |||||
| const OSErr err = GetDiskFragment (&fs, 0, kCFragGoesToEOF, nm, kReferenceCFrag, &connID, &mainPtr, errorMessage); | |||||
| if (err == noErr) | |||||
| return (void*)connID; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| void Process::freeDynamicLibrary (void* handle) | |||||
| { | |||||
| if (handle != 0) | |||||
| CloseConnection ((CFragConnectionID*)&handle); | |||||
| } | |||||
| void* Process::getProcedureEntryPoint (void* h, const String& procedureName) | |||||
| { | |||||
| if (h != 0) | |||||
| { | |||||
| CFragSymbolClass cl; | |||||
| Ptr ptr; | |||||
| Str255 name; | |||||
| PlatformUtilities::copyToStr255 (name, procedureName); | |||||
| if (FindSymbol ((CFragConnectionID) h, name, &ptr, &cl) == noErr) | |||||
| { | |||||
| return ptr; | |||||
| } | |||||
| } | |||||
| 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 | |||||
| /* | |||||
| ============================================================================== | |||||
| 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. | |||||
| ============================================================================== | |||||
| */ | |||||
| #include "../../../src/juce_core/basics/juce_StandardHeader.h" | |||||
| #include <pthread.h> | |||||
| #include <sched.h> | |||||
| #include <sys/file.h> | |||||
| #include <sys/types.h> | |||||
| #include <sys/ptrace.h> | |||||
| #include <Carbon/Carbon.h> | |||||
| 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_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_signal (&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_API juce_threadEntryPoint (void*); | |||||
| void* threadEntryProc (void* userData) throw() | |||||
| { | |||||
| juce_threadEntryPoint (userData); | |||||
| return 0; | |||||
| } | |||||
| void* juce_createThread (void* userData) throw() | |||||
| { | |||||
| pthread_t handle = 0; | |||||
| if (pthread_create (&handle, 0, threadEntryProc, userData) == 0) | |||||
| { | |||||
| pthread_detach (handle); | |||||
| return (void*) handle; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| void juce_killThread (void* handle) throw() | |||||
| { | |||||
| if (handle != 0) | |||||
| pthread_cancel ((pthread_t) handle); | |||||
| } | |||||
| void juce_setCurrentThreadName (const String& /*name*/) throw() | |||||
| { | |||||
| } | |||||
| int Thread::getCurrentThreadId() throw() | |||||
| { | |||||
| return (int) pthread_self(); | |||||
| } | |||||
| void juce_setThreadPriority (void* handle, int priority) throw() | |||||
| { | |||||
| if (handle == 0) | |||||
| handle = (void*) pthread_self(); | |||||
| struct sched_param param; | |||||
| int policy; | |||||
| pthread_getschedparam ((pthread_t) handle, &policy, ¶m); | |||||
| param.sched_priority = jlimit (1, 127, 1 + (priority * 126) / 11); | |||||
| pthread_setschedparam ((pthread_t) handle, policy, ¶m); | |||||
| } | |||||
| void Thread::yield() throw() | |||||
| { | |||||
| sched_yield(); | |||||
| } | |||||
| void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) throw() | |||||
| { | |||||
| // xxx | |||||
| 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_isRunningUnderDebugger() throw() | |||||
| { | |||||
| static char testResult = 0; | |||||
| if (testResult == 0) | |||||
| { | |||||
| testResult = (ptrace (PT_TRACE_ME, 0, 0, 0) < 0) ? 1 : -1; | |||||
| if (testResult < 0) | |||||
| ptrace (PT_DETACH, 0, (caddr_t) 1, 0); | |||||
| } | |||||
| return testResult > 0; | |||||
| } | |||||
| bool Process::isRunningUnderDebugger() throw() | |||||
| { | |||||
| return juce_isRunningUnderDebugger(); | |||||
| } | |||||
| void Process::raisePrivilege() | |||||
| { | |||||
| jassertfalse | |||||
| } | |||||
| void Process::lowerPrivilege() | |||||
| { | |||||
| jassertfalse | |||||
| } | |||||
| void Process::terminate() | |||||
| { | |||||
| ExitToShell(); | |||||
| } | |||||
| void Process::setPriority (ProcessPriority p) | |||||
| { | |||||
| // xxx | |||||
| } | |||||
| void* Process::loadDynamicLibrary (const String& name) | |||||
| { | |||||
| // xxx needs to use bundles | |||||
| FSSpec fs; | |||||
| if (PlatformUtilities::makeFSSpecFromPath (&fs, name)) | |||||
| { | |||||
| CFragConnectionID connID; | |||||
| Ptr mainPtr; | |||||
| Str255 errorMessage; | |||||
| Str63 nm; | |||||
| PlatformUtilities::copyToStr63 (nm, name); | |||||
| const OSErr err = GetDiskFragment (&fs, 0, kCFragGoesToEOF, nm, kReferenceCFrag, &connID, &mainPtr, errorMessage); | |||||
| if (err == noErr) | |||||
| return (void*)connID; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| void Process::freeDynamicLibrary (void* handle) | |||||
| { | |||||
| if (handle != 0) | |||||
| CloseConnection ((CFragConnectionID*)&handle); | |||||
| } | |||||
| void* Process::getProcedureEntryPoint (void* h, const String& procedureName) | |||||
| { | |||||
| if (h != 0) | |||||
| { | |||||
| CFragSymbolClass cl; | |||||
| Ptr ptr; | |||||
| Str255 name; | |||||
| PlatformUtilities::copyToStr255 (name, procedureName); | |||||
| if (FindSymbol ((CFragConnectionID) h, name, &ptr, &cl) == noErr) | |||||
| { | |||||
| return ptr; | |||||
| } | |||||
| } | |||||
| 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 | |||||
| @@ -299,6 +299,17 @@ void Process::setPriority (ProcessPriority prior) | |||||
| } | } | ||||
| } | } | ||||
| bool juce_isRunningUnderDebugger() throw() | |||||
| { | |||||
| return IsDebuggerPresent() != FALSE; | |||||
| } | |||||
| bool Process::isRunningUnderDebugger() throw() | |||||
| { | |||||
| return juce_isRunningUnderDebugger(); | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| void Process::raisePrivilege() | void Process::raisePrivilege() | ||||
| { | { | ||||
| @@ -35,12 +35,31 @@ | |||||
| #include <windows.h> | #include <windows.h> | ||||
| #include <float.h> | #include <float.h> | ||||
| #pragma warning (disable : 4312) | #pragma warning (disable : 4312) | ||||
| #elif defined LINUX | |||||
| #include <float.h> | |||||
| #include <sys/time.h> | |||||
| #include <X11/Xlib.h> | |||||
| #include <X11/Xutil.h> | |||||
| #include <X11/Xatom.h> | |||||
| #undef Font | |||||
| #undef KeyPress | |||||
| #undef Drawable | |||||
| #undef Time | |||||
| class VSTPluginWindow; | |||||
| #else | #else | ||||
| #include <Carbon/Carbon.h> | #include <Carbon/Carbon.h> | ||||
| #endif | #endif | ||||
| #include "../../../../../juce.h" | #include "../../../../../juce.h" | ||||
| #include "juce_VSTPluginInstance.h" | #include "juce_VSTPluginInstance.h" | ||||
| #if JUCE_LINUX | |||||
| #define Font JUCE_NAMESPACE::Font | |||||
| #define KeyPress JUCE_NAMESPACE::KeyPress | |||||
| #define Drawable JUCE_NAMESPACE::Drawable | |||||
| #define Time JUCE_NAMESPACE::Time | |||||
| #endif | |||||
| #include "../juce_PluginDescription.h" | #include "../juce_PluginDescription.h" | ||||
| #if ! JUCE_WIN32 | #if ! JUCE_WIN32 | ||||
| @@ -173,6 +192,117 @@ static void* NewCFMFromMachO (void* const machofp) throw() | |||||
| #endif | #endif | ||||
| #endif | #endif | ||||
| //============================================================================== | |||||
| #if JUCE_LINUX | |||||
| BEGIN_JUCE_NAMESPACE | |||||
| extern Display* display; | |||||
| extern XContext improbableNumber; | |||||
| END_JUCE_NAMESPACE | |||||
| typedef void (*EventProcPtr) (XEvent* ev); | |||||
| static bool xErrorTriggered; | |||||
| static int temporaryErrorHandler (Display*, XErrorEvent*) | |||||
| { | |||||
| xErrorTriggered = true; | |||||
| return 0; | |||||
| } | |||||
| static int getPropertyFromXWindow (Window handle, Atom atom) | |||||
| { | |||||
| XErrorHandler oldErrorHandler = XSetErrorHandler (temporaryErrorHandler); | |||||
| xErrorTriggered = false; | |||||
| int userSize; | |||||
| unsigned long bytes, userCount; | |||||
| unsigned char* data; | |||||
| Atom userType; | |||||
| XGetWindowProperty (display, handle, atom, 0, 1, false, AnyPropertyType, | |||||
| &userType, &userSize, &userCount, &bytes, &data); | |||||
| XSetErrorHandler (oldErrorHandler); | |||||
| return (userCount == 1 && ! xErrorTriggered) ? *(int*) data | |||||
| : 0; | |||||
| } | |||||
| static Window getChildWindow (Window windowToCheck) | |||||
| { | |||||
| Window rootWindow, parentWindow; | |||||
| Window* childWindows; | |||||
| unsigned int numChildren; | |||||
| XQueryTree (display, | |||||
| windowToCheck, | |||||
| &rootWindow, | |||||
| &parentWindow, | |||||
| &childWindows, | |||||
| &numChildren); | |||||
| if (numChildren > 0) | |||||
| return childWindows [0]; | |||||
| return 0; | |||||
| } | |||||
| static void translateJuceToXButtonModifiers (const MouseEvent& e, XEvent& ev) throw() | |||||
| { | |||||
| if (e.mods.isLeftButtonDown()) | |||||
| { | |||||
| ev.xbutton.button = Button1; | |||||
| ev.xbutton.state |= Button1Mask; | |||||
| } | |||||
| else if (e.mods.isRightButtonDown()) | |||||
| { | |||||
| ev.xbutton.button = Button3; | |||||
| ev.xbutton.state |= Button3Mask; | |||||
| } | |||||
| else if (e.mods.isMiddleButtonDown()) | |||||
| { | |||||
| ev.xbutton.button = Button2; | |||||
| ev.xbutton.state |= Button2Mask; | |||||
| } | |||||
| } | |||||
| static void translateJuceToXMotionModifiers (const MouseEvent& e, XEvent& ev) throw() | |||||
| { | |||||
| if (e.mods.isLeftButtonDown()) | |||||
| ev.xmotion.state |= Button1Mask; | |||||
| else if (e.mods.isRightButtonDown()) | |||||
| ev.xmotion.state |= Button3Mask; | |||||
| else if (e.mods.isMiddleButtonDown()) | |||||
| ev.xmotion.state |= Button2Mask; | |||||
| } | |||||
| static void translateJuceToXCrossingModifiers (const MouseEvent& e, XEvent& ev) throw() | |||||
| { | |||||
| if (e.mods.isLeftButtonDown()) | |||||
| ev.xcrossing.state |= Button1Mask; | |||||
| else if (e.mods.isRightButtonDown()) | |||||
| ev.xcrossing.state |= Button3Mask; | |||||
| else if (e.mods.isMiddleButtonDown()) | |||||
| ev.xcrossing.state |= Button2Mask; | |||||
| } | |||||
| static void translateJuceToXMouseWheelModifiers (const MouseEvent& e, const float increment, XEvent& ev) throw() | |||||
| { | |||||
| if (increment < 0) | |||||
| { | |||||
| ev.xbutton.button = Button5; | |||||
| ev.xbutton.state |= Button5Mask; | |||||
| } | |||||
| else if (increment > 0) | |||||
| { | |||||
| ev.xbutton.button = Button4; | |||||
| ev.xbutton.state |= Button4Mask; | |||||
| } | |||||
| } | |||||
| #endif | |||||
| //============================================================================== | //============================================================================== | ||||
| static VoidArray activeModules; | static VoidArray activeModules; | ||||
| @@ -217,9 +347,9 @@ public: | |||||
| ModuleHandle (const File& file_) | ModuleHandle (const File& file_) | ||||
| : file (file_), | : file (file_), | ||||
| moduleMain (0), | moduleMain (0), | ||||
| #if JUCE_WIN32 | |||||
| #if JUCE_WIN32 || JUCE_LINUX | |||||
| hModule (0) | hModule (0) | ||||
| #else | |||||
| #elif JUCE_MAC | |||||
| fragId (0), | fragId (0), | ||||
| resHandle (0), | resHandle (0), | ||||
| bundleRef (0), | bundleRef (0), | ||||
| @@ -228,9 +358,9 @@ public: | |||||
| { | { | ||||
| activeModules.add (this); | activeModules.add (this); | ||||
| #if JUCE_WIN32 | |||||
| #if JUCE_WIN32 || JUCE_LINUX | |||||
| fullParentDirectoryPathName = file_.getParentDirectory().getFullPathName(); | fullParentDirectoryPathName = file_.getParentDirectory().getFullPathName(); | ||||
| #else | |||||
| #elif JUCE_MAC | |||||
| PlatformUtilities::makeFSSpecFromPath (&parentDirFSSpec, file_.getParentDirectory().getFullPathName()); | PlatformUtilities::makeFSSpecFromPath (&parentDirFSSpec, file_.getParentDirectory().getFullPathName()); | ||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -246,27 +376,13 @@ public: | |||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| //============================================================================== | //============================================================================== | ||||
| #if JUCE_WIN32 | |||||
| HMODULE hModule; | |||||
| #if JUCE_WIN32 || JUCE_LINUX | |||||
| void* hModule; | |||||
| String fullParentDirectoryPathName; | String fullParentDirectoryPathName; | ||||
| static HMODULE loadDLL (const TCHAR* filename) throw() | |||||
| { | |||||
| HMODULE h = 0; | |||||
| __try | |||||
| { | |||||
| h = LoadLibrary (filename); | |||||
| } | |||||
| __finally | |||||
| { | |||||
| } | |||||
| return h; | |||||
| } | |||||
| bool open() | bool open() | ||||
| { | { | ||||
| #if JUCE_WIN32 | |||||
| static bool timePeriodSet = false; | static bool timePeriodSet = false; | ||||
| if (! timePeriodSet) | if (! timePeriodSet) | ||||
| @@ -274,18 +390,16 @@ public: | |||||
| timePeriodSet = true; | timePeriodSet = true; | ||||
| timeBeginPeriod (2); | timeBeginPeriod (2); | ||||
| } | } | ||||
| #endif | |||||
| pluginName = file.getFileNameWithoutExtension(); | pluginName = file.getFileNameWithoutExtension(); | ||||
| hModule = loadDLL (file.getFullPathName()); | |||||
| hModule = Process::loadDynamicLibrary (file.getFullPathName()); | |||||
| if (hModule == 0) | |||||
| return false; | |||||
| moduleMain = (MainCall) GetProcAddress (hModule, "VSTPluginMain"); | |||||
| moduleMain = (MainCall) Process::getProcedureEntryPoint (hModule, "VSTPluginMain"); | |||||
| if (moduleMain == 0) | if (moduleMain == 0) | ||||
| moduleMain = (MainCall) GetProcAddress (hModule, "main"); | |||||
| moduleMain = (MainCall) Process::getProcedureEntryPoint (hModule, "main"); | |||||
| return moduleMain != 0; | return moduleMain != 0; | ||||
| } | } | ||||
| @@ -294,16 +408,7 @@ public: | |||||
| { | { | ||||
| _fpreset(); // (doesn't do any harm) | _fpreset(); // (doesn't do any harm) | ||||
| if (hModule != 0) | |||||
| { | |||||
| __try | |||||
| { | |||||
| FreeLibrary (hModule); | |||||
| } | |||||
| __finally | |||||
| { | |||||
| } | |||||
| } | |||||
| Process::freeDynamicLibrary (hModule); | |||||
| } | } | ||||
| void closeEffect (AEffect* eff) | void closeEffect (AEffect* eff) | ||||
| @@ -758,7 +863,11 @@ void VSTPluginInstance::processBlock (AudioSampleBuffer& buffer, | |||||
| { | { | ||||
| #if JUCE_WIN32 | #if JUCE_WIN32 | ||||
| vstHostTime.nanoSeconds = timeGetTime() * 1000000.0; | vstHostTime.nanoSeconds = timeGetTime() * 1000000.0; | ||||
| #else | |||||
| #elif JUCE_LINUX | |||||
| timeval micro; | |||||
| gettimeofday (µ, 0); | |||||
| vstHostTime.nanoSeconds = micro.tv_usec * 1000.0; | |||||
| #elif JUCE_MAC | |||||
| UnsignedWide micro; | UnsignedWide micro; | ||||
| Microseconds (µ); | Microseconds (µ); | ||||
| vstHostTime.nanoSeconds = micro.lo * 1000.0; | vstHostTime.nanoSeconds = micro.lo * 1000.0; | ||||
| @@ -944,6 +1053,9 @@ public: | |||||
| #if JUCE_WIN32 | #if JUCE_WIN32 | ||||
| sizeCheckCount = 0; | sizeCheckCount = 0; | ||||
| pluginHWND = 0; | pluginHWND = 0; | ||||
| #elif JUCE_LINUX | |||||
| pluginWindow = None; | |||||
| pluginProc = None; | |||||
| #else | #else | ||||
| pluginViewRef = 0; | pluginViewRef = 0; | ||||
| #endif | #endif | ||||
| @@ -1014,9 +1126,16 @@ public: | |||||
| { | { | ||||
| repaint(); | repaint(); | ||||
| } | } | ||||
| #else | |||||
| #elif JUCE_WIN32 | |||||
| if (pluginHWND != 0) | if (pluginHWND != 0) | ||||
| MoveWindow (pluginHWND, x, y, getWidth(), getHeight(), TRUE); | MoveWindow (pluginHWND, x, y, getWidth(), getHeight(), TRUE); | ||||
| #elif JUCE_LINUX | |||||
| if (pluginWindow != 0) | |||||
| { | |||||
| XResizeWindow (display, pluginWindow, getWidth(), getHeight()); | |||||
| XMoveWindow (display, pluginWindow, x, y); | |||||
| XMapRaised (display, pluginWindow); | |||||
| } | |||||
| #endif | #endif | ||||
| recursiveResize = false; | recursiveResize = false; | ||||
| @@ -1072,6 +1191,23 @@ public: | |||||
| #if JUCE_MAC | #if JUCE_MAC | ||||
| dispatch (effEditDraw, 0, 0, 0, 0); | dispatch (effEditDraw, 0, 0, 0, 0); | ||||
| #elif JUCE_LINUX | |||||
| if (pluginWindow != 0) | |||||
| { | |||||
| const Rectangle clip (g.getClipBounds()); | |||||
| XEvent ev; | |||||
| zerostruct (ev); | |||||
| ev.xexpose.type = Expose; | |||||
| ev.xexpose.display = display; | |||||
| ev.xexpose.window = pluginWindow; | |||||
| ev.xexpose.x = clip.getX(); | |||||
| ev.xexpose.y = clip.getY(); | |||||
| ev.xexpose.width = clip.getWidth(); | |||||
| ev.xexpose.height = clip.getHeight(); | |||||
| sendEventToChild (&ev); | |||||
| } | |||||
| #endif | #endif | ||||
| } | } | ||||
| } | } | ||||
| @@ -1123,6 +1259,29 @@ public: | |||||
| { | { | ||||
| PostEvent (::mouseDown, 0); | PostEvent (::mouseDown, 0); | ||||
| } | } | ||||
| #elif JUCE_LINUX | |||||
| if (pluginWindow == 0) | |||||
| return; | |||||
| toFront (true); | |||||
| XEvent ev; | |||||
| zerostruct (ev); | |||||
| ev.xbutton.display = display; | |||||
| ev.xbutton.type = ButtonPress; | |||||
| ev.xbutton.window = pluginWindow; | |||||
| ev.xbutton.root = RootWindow (display, DefaultScreen (display)); | |||||
| ev.xbutton.time = CurrentTime; | |||||
| ev.xbutton.x = e.x; | |||||
| ev.xbutton.y = e.y; | |||||
| ev.xbutton.x_root = e.getScreenX(); | |||||
| ev.xbutton.y_root = e.getScreenY(); | |||||
| translateJuceToXButtonModifiers (e, ev); | |||||
| sendEventToChild (&ev); | |||||
| #else | #else | ||||
| (void) e; | (void) e; | ||||
| @@ -1152,9 +1311,12 @@ private: | |||||
| HWND pluginHWND; | HWND pluginHWND; | ||||
| void* originalWndProc; | void* originalWndProc; | ||||
| int sizeCheckCount; | int sizeCheckCount; | ||||
| #else | |||||
| #elif JUCE_MAC | |||||
| HIViewRef pluginViewRef; | HIViewRef pluginViewRef; | ||||
| WindowRef pluginWindowRef; | WindowRef pluginWindowRef; | ||||
| #elif JUCE_LINUX | |||||
| Window pluginWindow; | |||||
| EventProcPtr pluginProc; | |||||
| #endif | #endif | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -1231,7 +1393,7 @@ private: | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #else | |||||
| #elif JUCE_MAC | |||||
| HIViewRef root = HIViewGetRoot ((WindowRef) getWindowHandle()); | HIViewRef root = HIViewGetRoot ((WindowRef) getWindowHandle()); | ||||
| HIViewFindByID (root, kHIViewWindowContentID, &root); | HIViewFindByID (root, kHIViewWindowContentID, &root); | ||||
| pluginViewRef = HIViewGetFirstSubview (root); | pluginViewRef = HIViewGetFirstSubview (root); | ||||
| @@ -1269,6 +1431,30 @@ private: | |||||
| h = 150; | h = 150; | ||||
| } | } | ||||
| } | } | ||||
| #elif JUCE_LINUX | |||||
| pluginWindow = getChildWindow ((Window) getWindowHandle()); | |||||
| if (pluginWindow != 0) | |||||
| pluginProc = (EventProcPtr) getPropertyFromXWindow (pluginWindow, | |||||
| XInternAtom (display, "_XEventProc", False)); | |||||
| int w = 250, h = 150; | |||||
| if (rect != 0) | |||||
| { | |||||
| w = rect->right - rect->left; | |||||
| h = rect->bottom - rect->top; | |||||
| if (w == 0 || h == 0) | |||||
| { | |||||
| w = 250; | |||||
| h = 150; | |||||
| } | |||||
| } | |||||
| if (pluginWindow != 0) | |||||
| XMapRaised (display, pluginWindow); | |||||
| #endif | #endif | ||||
| // double-check it's not too tiny | // double-check it's not too tiny | ||||
| @@ -1310,10 +1496,14 @@ private: | |||||
| DestroyWindow (pluginHWND); | DestroyWindow (pluginHWND); | ||||
| pluginHWND = 0; | pluginHWND = 0; | ||||
| #else | |||||
| #elif JUCE_MAC | |||||
| dispatch (effEditSleep, 0, 0, 0, 0); | dispatch (effEditSleep, 0, 0, 0, 0); | ||||
| pluginViewRef = 0; | pluginViewRef = 0; | ||||
| stopTimer(); | stopTimer(); | ||||
| #elif JUCE_LINUX | |||||
| stopTimer(); | |||||
| pluginWindow = 0; | |||||
| pluginProc = 0; | |||||
| #endif | #endif | ||||
| } | } | ||||
| } | } | ||||
| @@ -1408,6 +1598,168 @@ private: | |||||
| return DefWindowProc (hW, message, wParam, lParam); | return DefWindowProc (hW, message, wParam, lParam); | ||||
| } | } | ||||
| #endif | #endif | ||||
| #if JUCE_LINUX | |||||
| //============================================================================== | |||||
| // overload mouse/keyboard events to forward them to the plugin's inner window.. | |||||
| void sendEventToChild (XEvent* event) | |||||
| { | |||||
| if (pluginProc != 0) | |||||
| { | |||||
| // if the plugin publishes an event procedure, pass the event directly.. | |||||
| pluginProc (event); | |||||
| } | |||||
| else if (pluginWindow != 0) | |||||
| { | |||||
| // if the plugin has a window, then send the event to the window so that | |||||
| // its message thread will pick it up.. | |||||
| XSendEvent (display, pluginWindow, False, 0L, event); | |||||
| XFlush (display); | |||||
| } | |||||
| } | |||||
| void mouseEnter (const MouseEvent& e) | |||||
| { | |||||
| if (pluginWindow != 0) | |||||
| { | |||||
| XEvent ev; | |||||
| zerostruct (ev); | |||||
| ev.xcrossing.display = display; | |||||
| ev.xcrossing.type = EnterNotify; | |||||
| ev.xcrossing.window = pluginWindow; | |||||
| ev.xcrossing.root = RootWindow (display, DefaultScreen (display)); | |||||
| ev.xcrossing.time = CurrentTime; | |||||
| ev.xcrossing.x = e.x; | |||||
| ev.xcrossing.y = e.y; | |||||
| ev.xcrossing.x_root = e.getScreenX(); | |||||
| ev.xcrossing.y_root = e.getScreenY(); | |||||
| ev.xcrossing.mode = NotifyNormal; // NotifyGrab, NotifyUngrab | |||||
| ev.xcrossing.detail = NotifyAncestor; // NotifyVirtual, NotifyInferior, NotifyNonlinear,NotifyNonlinearVirtual | |||||
| translateJuceToXCrossingModifiers (e, ev); | |||||
| sendEventToChild (&ev); | |||||
| } | |||||
| } | |||||
| void mouseExit (const MouseEvent& e) | |||||
| { | |||||
| if (pluginWindow != 0) | |||||
| { | |||||
| XEvent ev; | |||||
| zerostruct (ev); | |||||
| ev.xcrossing.display = display; | |||||
| ev.xcrossing.type = LeaveNotify; | |||||
| ev.xcrossing.window = pluginWindow; | |||||
| ev.xcrossing.root = RootWindow (display, DefaultScreen (display)); | |||||
| ev.xcrossing.time = CurrentTime; | |||||
| ev.xcrossing.x = e.x; | |||||
| ev.xcrossing.y = e.y; | |||||
| ev.xcrossing.x_root = e.getScreenX(); | |||||
| ev.xcrossing.y_root = e.getScreenY(); | |||||
| ev.xcrossing.mode = NotifyNormal; // NotifyGrab, NotifyUngrab | |||||
| ev.xcrossing.detail = NotifyAncestor; // NotifyVirtual, NotifyInferior, NotifyNonlinear,NotifyNonlinearVirtual | |||||
| ev.xcrossing.focus = hasKeyboardFocus (true); // TODO - yes ? | |||||
| translateJuceToXCrossingModifiers (e, ev); | |||||
| sendEventToChild (&ev); | |||||
| } | |||||
| } | |||||
| void mouseMove (const MouseEvent& e) | |||||
| { | |||||
| if (pluginWindow != 0) | |||||
| { | |||||
| XEvent ev; | |||||
| zerostruct (ev); | |||||
| ev.xmotion.display = display; | |||||
| ev.xmotion.type = MotionNotify; | |||||
| ev.xmotion.window = pluginWindow; | |||||
| ev.xmotion.root = RootWindow (display, DefaultScreen (display)); | |||||
| ev.xmotion.time = CurrentTime; | |||||
| ev.xmotion.is_hint = NotifyNormal; | |||||
| ev.xmotion.x = e.x; | |||||
| ev.xmotion.y = e.y; | |||||
| ev.xmotion.x_root = e.getScreenX(); | |||||
| ev.xmotion.y_root = e.getScreenY(); | |||||
| sendEventToChild (&ev); | |||||
| } | |||||
| } | |||||
| void mouseDrag (const MouseEvent& e) | |||||
| { | |||||
| if (pluginWindow != 0) | |||||
| { | |||||
| XEvent ev; | |||||
| zerostruct (ev); | |||||
| ev.xmotion.display = display; | |||||
| ev.xmotion.type = MotionNotify; | |||||
| ev.xmotion.window = pluginWindow; | |||||
| ev.xmotion.root = RootWindow (display, DefaultScreen (display)); | |||||
| ev.xmotion.time = CurrentTime; | |||||
| ev.xmotion.x = e.x ; | |||||
| ev.xmotion.y = e.y; | |||||
| ev.xmotion.x_root = e.getScreenX(); | |||||
| ev.xmotion.y_root = e.getScreenY(); | |||||
| ev.xmotion.is_hint = NotifyNormal; | |||||
| translateJuceToXMotionModifiers (e, ev); | |||||
| sendEventToChild (&ev); | |||||
| } | |||||
| } | |||||
| void mouseUp (const MouseEvent& e) | |||||
| { | |||||
| if (pluginWindow != 0) | |||||
| { | |||||
| XEvent ev; | |||||
| zerostruct (ev); | |||||
| ev.xbutton.display = display; | |||||
| ev.xbutton.type = ButtonRelease; | |||||
| ev.xbutton.window = pluginWindow; | |||||
| ev.xbutton.root = RootWindow (display, DefaultScreen (display)); | |||||
| ev.xbutton.time = CurrentTime; | |||||
| ev.xbutton.x = e.x; | |||||
| ev.xbutton.y = e.y; | |||||
| ev.xbutton.x_root = e.getScreenX(); | |||||
| ev.xbutton.y_root = e.getScreenY(); | |||||
| translateJuceToXButtonModifiers (e, ev); | |||||
| sendEventToChild (&ev); | |||||
| } | |||||
| } | |||||
| void mouseWheelMove (const MouseEvent& e, | |||||
| float incrementX, | |||||
| float incrementY) | |||||
| { | |||||
| if (pluginWindow != 0) | |||||
| { | |||||
| XEvent ev; | |||||
| zerostruct (ev); | |||||
| ev.xbutton.display = display; | |||||
| ev.xbutton.type = ButtonPress; | |||||
| ev.xbutton.window = pluginWindow; | |||||
| ev.xbutton.root = RootWindow (display, DefaultScreen (display)); | |||||
| ev.xbutton.time = CurrentTime; | |||||
| ev.xbutton.x = e.x; | |||||
| ev.xbutton.y = e.y; | |||||
| ev.xbutton.x_root = e.getScreenX(); | |||||
| ev.xbutton.y_root = e.getScreenY(); | |||||
| translateJuceToXMouseWheelModifiers (e, incrementY, ev); | |||||
| sendEventToChild (&ev); | |||||
| // TODO - put a usleep here ? | |||||
| ev.xbutton.type = ButtonRelease; | |||||
| sendEventToChild (&ev); | |||||
| } | |||||
| } | |||||
| #endif | |||||
| }; | }; | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -2533,9 +2885,12 @@ bool VSTPluginFormat::fileMightContainThisPluginType (const File& f) | |||||
| #endif | #endif | ||||
| return false; | return false; | ||||
| #else | |||||
| #elif JUCE_WIN32 | |||||
| return f.existsAsFile() | return f.existsAsFile() | ||||
| && f.hasFileExtension (T(".dll")); | && f.hasFileExtension (T(".dll")); | ||||
| #elif JUCE_LINUX | |||||
| return f.existsAsFile() | |||||
| && f.hasFileExtension (T(".so")); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -2543,9 +2898,11 @@ const FileSearchPath VSTPluginFormat::getDefaultLocationsToSearch() | |||||
| { | { | ||||
| #if JUCE_MAC | #if JUCE_MAC | ||||
| return FileSearchPath ("~/Library/Audio/Plug-Ins/VST;/Library/Audio/Plug-Ins/VST"); | return FileSearchPath ("~/Library/Audio/Plug-Ins/VST;/Library/Audio/Plug-Ins/VST"); | ||||
| #else | |||||
| #elif JUCE_WIN32 | |||||
| const String programFiles (File::getSpecialLocation (File::globalApplicationsDirectory).getFullPathName()); | const String programFiles (File::getSpecialLocation (File::globalApplicationsDirectory).getFullPathName()); | ||||
| return FileSearchPath (programFiles + "\\Steinberg\\VstPlugins"); | return FileSearchPath (programFiles + "\\Steinberg\\VstPlugins"); | ||||
| #elif JUCE_LINUX | |||||
| return FileSearchPath ("/usr/lib/vst"); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -5160,7 +5160,7 @@ static const unsigned char temp9[] = {47,42,13,10,32,32,61,61,61,61,61,61,61,61, | |||||
| 46,76,105,98,34,41,13,10,32,35,101,110,100,105,102,13,10,35,101,108,105,102,32,100,101,102,105,110,101,100,32,40,76,73,78,85,88,41,13,10, | 46,76,105,98,34,41,13,10,32,35,101,110,100,105,102,13,10,35,101,108,105,102,32,100,101,102,105,110,101,100,32,40,76,73,78,85,88,41,13,10, | ||||
| 32,35,105,110,99,108,117,100,101,32,60,71,76,47,103,108,46,104,62,13,10,32,35,105,110,99,108,117,100,101,32,60,71,76,47,103,108,117,116,46, | 32,35,105,110,99,108,117,100,101,32,60,71,76,47,103,108,46,104,62,13,10,32,35,105,110,99,108,117,100,101,32,60,71,76,47,103,108,117,116,46, | ||||
| 104,62,13,10,32,35,117,110,100,101,102,32,75,101,121,80,114,101,115,115,13,10,35,101,108,115,101,13,10,32,35,105,110,99,108,117,100,101,32,60, | 104,62,13,10,32,35,117,110,100,101,102,32,75,101,121,80,114,101,115,115,13,10,35,101,108,115,101,13,10,32,35,105,110,99,108,117,100,101,32,60, | ||||
| 97,103,108,47,97,103,108,46,104,62,13,10,32,35,105,110,99,108,117,100,101,32,60,103,108,117,116,47,103,108,117,116,46,104,62,13,10,35,101,110, | |||||
| 65,71,76,47,97,103,108,46,104,62,13,10,32,35,105,110,99,108,117,100,101,32,60,71,76,85,84,47,103,108,117,116,46,104,62,13,10,35,101,110, | |||||
| 100,105,102,13,10,13,10,35,105,102,110,100,101,102,32,71,76,95,66,71,82,65,95,69,88,84,13,10,32,35,100,101,102,105,110,101,32,71,76,95, | 100,105,102,13,10,13,10,35,105,102,110,100,101,102,32,71,76,95,66,71,82,65,95,69,88,84,13,10,32,35,100,101,102,105,110,101,32,71,76,95, | ||||
| 66,71,82,65,95,69,88,84,32,48,120,56,48,101,49,13,10,35,101,110,100,105,102,13,10,13,10,47,47,61,61,61,61,61,61,61,61,61,61,61, | 66,71,82,65,95,69,88,84,32,48,120,56,48,101,49,13,10,35,101,110,100,105,102,13,10,13,10,47,47,61,61,61,61,61,61,61,61,61,61,61, | ||||
| 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, | 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61, | ||||
| @@ -343,6 +343,22 @@ public: | |||||
| void handleAsyncUpdate(); | void handleAsyncUpdate(); | ||||
| /** @internal */ | /** @internal */ | ||||
| const String getTooltip() { return label->getTooltip(); } | const String getTooltip() { return label->getTooltip(); } | ||||
| /** @internal */ | |||||
| void mouseDown (const MouseEvent&); | |||||
| /** @internal */ | |||||
| void mouseDrag (const MouseEvent&); | |||||
| /** @internal */ | |||||
| void mouseUp (const MouseEvent&); | |||||
| /** @internal */ | |||||
| void lookAndFeelChanged(); | |||||
| /** @internal */ | |||||
| void paint (Graphics&); | |||||
| /** @internal */ | |||||
| void resized(); | |||||
| /** @internal */ | |||||
| bool keyStateChanged(); | |||||
| /** @internal */ | |||||
| bool keyPressed (const KeyPress&); | |||||
| //============================================================================== | //============================================================================== | ||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| @@ -367,15 +383,6 @@ private: | |||||
| Label* label; | Label* label; | ||||
| String textWhenNothingSelected, noChoicesMessage; | String textWhenNothingSelected, noChoicesMessage; | ||||
| void mouseDown (const MouseEvent&); | |||||
| void mouseDrag (const MouseEvent&); | |||||
| void mouseUp (const MouseEvent&); | |||||
| void lookAndFeelChanged(); | |||||
| void paint (Graphics&); | |||||
| void resized(); | |||||
| bool keyStateChanged(); | |||||
| bool keyPressed (const KeyPress&); | |||||
| void showPopup(); | void showPopup(); | ||||
| ItemInfo* getItemForId (const int id) const throw(); | ItemInfo* getItemForId (const int id) const throw(); | ||||
| @@ -190,6 +190,10 @@ | |||||
| //============================================================================== | //============================================================================== | ||||
| // Assertions.. | // Assertions.. | ||||
| BEGIN_JUCE_NAMESPACE | |||||
| extern bool juce_isRunningUnderDebugger() throw(); | |||||
| END_JUCE_NAMESPACE | |||||
| #if JUCE_MSVC || DOXYGEN | #if JUCE_MSVC || DOXYGEN | ||||
| #if JUCE_USE_INTRINSICS | #if JUCE_USE_INTRINSICS | ||||
| @@ -202,7 +206,7 @@ | |||||
| @see jassert() | @see jassert() | ||||
| */ | */ | ||||
| #define jassertfalse { juce_LogCurrentAssertion; __debugbreak(); } | |||||
| #define jassertfalse { juce_LogCurrentAssertion; if (juce_isRunningUnderDebugger()) __debugbreak(); } | |||||
| #else | #else | ||||
| /** This will always cause an assertion failure. | /** This will always cause an assertion failure. | ||||
| @@ -210,12 +214,12 @@ | |||||
| @see jassert() | @see jassert() | ||||
| */ | */ | ||||
| #define jassertfalse { juce_LogCurrentAssertion; __asm int 3 } | |||||
| #define jassertfalse { juce_LogCurrentAssertion; if (juce_isRunningUnderDebugger()) { __asm int 3 } } | |||||
| #endif | #endif | ||||
| #elif defined (JUCE_MAC) | #elif defined (JUCE_MAC) | ||||
| #define jassertfalse { juce_LogCurrentAssertion; Debugger(); } | |||||
| #define jassertfalse { juce_LogCurrentAssertion; if (juce_isRunningUnderDebugger()) Debugger(); } | |||||
| #elif defined (JUCE_GCC) || defined (JUCE_LINUX) | #elif defined (JUCE_GCC) || defined (JUCE_LINUX) | ||||
| #define jassertfalse { juce_LogCurrentAssertion; asm("int $3"); } | |||||
| #define jassertfalse { juce_LogCurrentAssertion; if (juce_isRunningUnderDebugger()) asm("int $3"); } | |||||
| #endif | #endif | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -54,12 +54,20 @@ | |||||
| //============================================================================== | //============================================================================== | ||||
| #include "../../../juce_Config.h" | #include "../../../juce_Config.h" | ||||
| //============================================================================== | |||||
| #ifdef JUCE_NAMESPACE | |||||
| #define BEGIN_JUCE_NAMESPACE namespace JUCE_NAMESPACE { | |||||
| #define END_JUCE_NAMESPACE } | |||||
| #else | |||||
| #define BEGIN_JUCE_NAMESPACE | |||||
| #define END_JUCE_NAMESPACE | |||||
| #endif | |||||
| //============================================================================== | |||||
| // This sets up the JUCE_WIN32, JUCE_MAC, or JUCE_LINUX macros | // This sets up the JUCE_WIN32, JUCE_MAC, or JUCE_LINUX macros | ||||
| #include "juce_PlatformDefs.h" | #include "juce_PlatformDefs.h" | ||||
| //============================================================================== | |||||
| // Now we'll include any OS headers we need.. (at this point we are outside the Juce namespace). | // Now we'll include any OS headers we need.. (at this point we are outside the Juce namespace). | ||||
| #if JUCE_MSVC | #if JUCE_MSVC | ||||
| #pragma warning (push) | #pragma warning (push) | ||||
| #pragma warning (disable: 4514 4245 4100) | #pragma warning (disable: 4514 4245 4100) | ||||
| @@ -93,15 +101,6 @@ | |||||
| #pragma warning (pop) | #pragma warning (pop) | ||||
| #endif | #endif | ||||
| //============================================================================== | |||||
| #ifdef JUCE_NAMESPACE | |||||
| #define BEGIN_JUCE_NAMESPACE namespace JUCE_NAMESPACE { | |||||
| #define END_JUCE_NAMESPACE } | |||||
| #else | |||||
| #define BEGIN_JUCE_NAMESPACE | |||||
| #define END_JUCE_NAMESPACE | |||||
| #endif | |||||
| //============================================================================== | //============================================================================== | ||||
| // DLL building settings on Win32 | // DLL building settings on Win32 | ||||
| #if JUCE_MSVC | #if JUCE_MSVC | ||||
| @@ -439,15 +439,19 @@ bool File::isAChildOf (const File& potentialParent) const throw() | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| const File File::getChildFile (String relativePath) const throw() | |||||
| bool File::isAbsolutePath (const String& path) throw() | |||||
| { | { | ||||
| if (relativePath.startsWithChar (T('/')) | |||||
| || relativePath.startsWithChar (T('\\')) | |||||
| return path.startsWithChar (T('/')) || path.startsWithChar (T('\\')) | |||||
| #if JUCE_WIN32 | #if JUCE_WIN32 | ||||
| || (relativePath.isNotEmpty() && ((const String&) relativePath)[1] == T(':'))) | |||||
| || (path.isNotEmpty() && ((const String&) path)[1] == T(':')); | |||||
| #else | #else | ||||
| || relativePath.startsWithChar (T('~'))) | |||||
| || path.startsWithChar (T('~')); | |||||
| #endif | #endif | ||||
| } | |||||
| const File File::getChildFile (String relativePath) const throw() | |||||
| { | |||||
| if (isAbsolutePath (relativePath)) | |||||
| { | { | ||||
| // the path is really absolute.. | // the path is really absolute.. | ||||
| return File (relativePath); | return File (relativePath); | ||||
| @@ -182,7 +182,7 @@ public: | |||||
| be relative to. If this is actually a file rather than | be relative to. If this is actually a file rather than | ||||
| a directory, its parent directory will be used instead. | a directory, its parent directory will be used instead. | ||||
| If it doesn't exist, it's assumed to be a directory. | If it doesn't exist, it's assumed to be a directory. | ||||
| @see getChildFile | |||||
| @see getChildFile, isAbsolutePath | |||||
| */ | */ | ||||
| const String getRelativePathFrom (const File& directoryToBeRelativeTo) const throw(); | const String getRelativePathFrom (const File& directoryToBeRelativeTo) const throw(); | ||||
| @@ -834,6 +834,10 @@ public: | |||||
| */ | */ | ||||
| static bool areFileNamesCaseSensitive(); | static bool areFileNamesCaseSensitive(); | ||||
| /** Returns true if the string seems to be a fully-specified absolute path. | |||||
| */ | |||||
| static bool isAbsolutePath (const String& path) throw(); | |||||
| //============================================================================== | //============================================================================== | ||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| @@ -93,6 +93,11 @@ public: | |||||
| */ | */ | ||||
| static void lowerPrivilege(); | static void lowerPrivilege(); | ||||
| //============================================================================== | |||||
| /** Returns true if this process is being hosted by a debugger. | |||||
| */ | |||||
| static bool isRunningUnderDebugger() throw(); | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Loads a dynamically-linked library into the process's address space. | /** Loads a dynamically-linked library into the process's address space. | ||||