@@ -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. | ||||