mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
This commit is contained in:
parent
bc15e07250
commit
fb815110ca
11 changed files with 876 additions and 441 deletions
|
|
@ -32,6 +32,8 @@
|
|||
#include "linuxincludes.h"
|
||||
#include <dlfcn.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include "../../../src/juce_core/basics/juce_StandardHeader.h"
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
|
@ -339,6 +341,26 @@ void Process::terminate()
|
|||
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()
|
||||
{
|
||||
// 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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,12 +35,31 @@
|
|||
#include <windows.h>
|
||||
#include <float.h>
|
||||
#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
|
||||
#include <Carbon/Carbon.h>
|
||||
#endif
|
||||
|
||||
#include "../../../../../juce.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"
|
||||
|
||||
#if ! JUCE_WIN32
|
||||
|
|
@ -173,6 +192,117 @@ static void* NewCFMFromMachO (void* const machofp) throw()
|
|||
#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;
|
||||
|
||||
|
|
@ -217,9 +347,9 @@ public:
|
|||
ModuleHandle (const File& file_)
|
||||
: file (file_),
|
||||
moduleMain (0),
|
||||
#if JUCE_WIN32
|
||||
#if JUCE_WIN32 || JUCE_LINUX
|
||||
hModule (0)
|
||||
#else
|
||||
#elif JUCE_MAC
|
||||
fragId (0),
|
||||
resHandle (0),
|
||||
bundleRef (0),
|
||||
|
|
@ -228,9 +358,9 @@ public:
|
|||
{
|
||||
activeModules.add (this);
|
||||
|
||||
#if JUCE_WIN32
|
||||
#if JUCE_WIN32 || JUCE_LINUX
|
||||
fullParentDirectoryPathName = file_.getParentDirectory().getFullPathName();
|
||||
#else
|
||||
#elif JUCE_MAC
|
||||
PlatformUtilities::makeFSSpecFromPath (&parentDirFSSpec, file_.getParentDirectory().getFullPathName());
|
||||
#endif
|
||||
}
|
||||
|
|
@ -246,27 +376,13 @@ public:
|
|||
juce_UseDebuggingNewOperator
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_WIN32
|
||||
HMODULE hModule;
|
||||
#if JUCE_WIN32 || JUCE_LINUX
|
||||
void* hModule;
|
||||
String fullParentDirectoryPathName;
|
||||
|
||||
static HMODULE loadDLL (const TCHAR* filename) throw()
|
||||
{
|
||||
HMODULE h = 0;
|
||||
|
||||
__try
|
||||
{
|
||||
h = LoadLibrary (filename);
|
||||
}
|
||||
__finally
|
||||
{
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
bool open()
|
||||
{
|
||||
#if JUCE_WIN32
|
||||
static bool timePeriodSet = false;
|
||||
|
||||
if (! timePeriodSet)
|
||||
|
|
@ -274,18 +390,16 @@ public:
|
|||
timePeriodSet = true;
|
||||
timeBeginPeriod (2);
|
||||
}
|
||||
#endif
|
||||
|
||||
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)
|
||||
moduleMain = (MainCall) GetProcAddress (hModule, "main");
|
||||
moduleMain = (MainCall) Process::getProcedureEntryPoint (hModule, "main");
|
||||
|
||||
return moduleMain != 0;
|
||||
}
|
||||
|
|
@ -294,16 +408,7 @@ public:
|
|||
{
|
||||
_fpreset(); // (doesn't do any harm)
|
||||
|
||||
if (hModule != 0)
|
||||
{
|
||||
__try
|
||||
{
|
||||
FreeLibrary (hModule);
|
||||
}
|
||||
__finally
|
||||
{
|
||||
}
|
||||
}
|
||||
Process::freeDynamicLibrary (hModule);
|
||||
}
|
||||
|
||||
void closeEffect (AEffect* eff)
|
||||
|
|
@ -758,7 +863,11 @@ void VSTPluginInstance::processBlock (AudioSampleBuffer& buffer,
|
|||
{
|
||||
#if JUCE_WIN32
|
||||
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;
|
||||
Microseconds (µ);
|
||||
vstHostTime.nanoSeconds = micro.lo * 1000.0;
|
||||
|
|
@ -944,6 +1053,9 @@ public:
|
|||
#if JUCE_WIN32
|
||||
sizeCheckCount = 0;
|
||||
pluginHWND = 0;
|
||||
#elif JUCE_LINUX
|
||||
pluginWindow = None;
|
||||
pluginProc = None;
|
||||
#else
|
||||
pluginViewRef = 0;
|
||||
#endif
|
||||
|
|
@ -1014,9 +1126,16 @@ public:
|
|||
{
|
||||
repaint();
|
||||
}
|
||||
#else
|
||||
#elif JUCE_WIN32
|
||||
if (pluginHWND != 0)
|
||||
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
|
||||
|
||||
recursiveResize = false;
|
||||
|
|
@ -1072,6 +1191,23 @@ public:
|
|||
|
||||
#if JUCE_MAC
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
@ -1123,6 +1259,29 @@ public:
|
|||
{
|
||||
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
|
||||
(void) e;
|
||||
|
||||
|
|
@ -1152,9 +1311,12 @@ private:
|
|||
HWND pluginHWND;
|
||||
void* originalWndProc;
|
||||
int sizeCheckCount;
|
||||
#else
|
||||
#elif JUCE_MAC
|
||||
HIViewRef pluginViewRef;
|
||||
WindowRef pluginWindowRef;
|
||||
#elif JUCE_LINUX
|
||||
Window pluginWindow;
|
||||
EventProcPtr pluginProc;
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -1231,7 +1393,7 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#elif JUCE_MAC
|
||||
HIViewRef root = HIViewGetRoot ((WindowRef) getWindowHandle());
|
||||
HIViewFindByID (root, kHIViewWindowContentID, &root);
|
||||
pluginViewRef = HIViewGetFirstSubview (root);
|
||||
|
|
@ -1269,6 +1431,30 @@ private:
|
|||
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
|
||||
|
||||
// double-check it's not too tiny
|
||||
|
|
@ -1310,10 +1496,14 @@ private:
|
|||
DestroyWindow (pluginHWND);
|
||||
|
||||
pluginHWND = 0;
|
||||
#else
|
||||
#elif JUCE_MAC
|
||||
dispatch (effEditSleep, 0, 0, 0, 0);
|
||||
pluginViewRef = 0;
|
||||
stopTimer();
|
||||
#elif JUCE_LINUX
|
||||
stopTimer();
|
||||
pluginWindow = 0;
|
||||
pluginProc = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -1408,6 +1598,168 @@ private:
|
|||
return DefWindowProc (hW, message, wParam, lParam);
|
||||
}
|
||||
#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
|
||||
|
||||
return false;
|
||||
#else
|
||||
#elif JUCE_WIN32
|
||||
return f.existsAsFile()
|
||||
&& f.hasFileExtension (T(".dll"));
|
||||
#elif JUCE_LINUX
|
||||
return f.existsAsFile()
|
||||
&& f.hasFileExtension (T(".so"));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -2543,9 +2898,11 @@ const FileSearchPath VSTPluginFormat::getDefaultLocationsToSearch()
|
|||
{
|
||||
#if JUCE_MAC
|
||||
return FileSearchPath ("~/Library/Audio/Plug-Ins/VST;/Library/Audio/Plug-Ins/VST");
|
||||
#else
|
||||
#elif JUCE_WIN32
|
||||
const String programFiles (File::getSpecialLocation (File::globalApplicationsDirectory).getFullPathName());
|
||||
|
||||
return FileSearchPath (programFiles + "\\Steinberg\\VstPlugins");
|
||||
#elif JUCE_LINUX
|
||||
return FileSearchPath ("/usr/lib/vst");
|
||||
#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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -343,6 +343,22 @@ public:
|
|||
void handleAsyncUpdate();
|
||||
/** @internal */
|
||||
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
|
||||
|
|
@ -367,15 +383,6 @@ private:
|
|||
Label* label;
|
||||
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();
|
||||
|
||||
ItemInfo* getItemForId (const int id) const throw();
|
||||
|
|
|
|||
|
|
@ -190,6 +190,10 @@
|
|||
//==============================================================================
|
||||
// Assertions..
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
extern bool juce_isRunningUnderDebugger() throw();
|
||||
END_JUCE_NAMESPACE
|
||||
|
||||
#if JUCE_MSVC || DOXYGEN
|
||||
|
||||
#if JUCE_USE_INTRINSICS
|
||||
|
|
@ -202,7 +206,7 @@
|
|||
|
||||
@see jassert()
|
||||
*/
|
||||
#define jassertfalse { juce_LogCurrentAssertion; __debugbreak(); }
|
||||
#define jassertfalse { juce_LogCurrentAssertion; if (juce_isRunningUnderDebugger()) __debugbreak(); }
|
||||
#else
|
||||
/** This will always cause an assertion failure.
|
||||
|
||||
|
|
@ -210,12 +214,12 @@
|
|||
|
||||
@see jassert()
|
||||
*/
|
||||
#define jassertfalse { juce_LogCurrentAssertion; __asm int 3 }
|
||||
#define jassertfalse { juce_LogCurrentAssertion; if (juce_isRunningUnderDebugger()) { __asm int 3 } }
|
||||
#endif
|
||||
#elif defined (JUCE_MAC)
|
||||
#define jassertfalse { juce_LogCurrentAssertion; Debugger(); }
|
||||
#define jassertfalse { juce_LogCurrentAssertion; if (juce_isRunningUnderDebugger()) Debugger(); }
|
||||
#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
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -54,12 +54,20 @@
|
|||
//==============================================================================
|
||||
#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
|
||||
#include "juce_PlatformDefs.h"
|
||||
|
||||
//==============================================================================
|
||||
// Now we'll include any OS headers we need.. (at this point we are outside the Juce namespace).
|
||||
|
||||
#if JUCE_MSVC
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4514 4245 4100)
|
||||
|
|
@ -93,15 +101,6 @@
|
|||
#pragma warning (pop)
|
||||
#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
|
||||
#if JUCE_MSVC
|
||||
|
|
|
|||
|
|
@ -439,15 +439,19 @@ bool File::isAChildOf (const File& potentialParent) const throw()
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
bool File::isAbsolutePath (const String& path) throw()
|
||||
{
|
||||
return path.startsWithChar (T('/')) || path.startsWithChar (T('\\'))
|
||||
#if JUCE_WIN32
|
||||
|| (path.isNotEmpty() && ((const String&) path)[1] == T(':'));
|
||||
#else
|
||||
|| path.startsWithChar (T('~'));
|
||||
#endif
|
||||
}
|
||||
|
||||
const File File::getChildFile (String relativePath) const throw()
|
||||
{
|
||||
if (relativePath.startsWithChar (T('/'))
|
||||
|| relativePath.startsWithChar (T('\\'))
|
||||
#if JUCE_WIN32
|
||||
|| (relativePath.isNotEmpty() && ((const String&) relativePath)[1] == T(':')))
|
||||
#else
|
||||
|| relativePath.startsWithChar (T('~')))
|
||||
#endif
|
||||
if (isAbsolutePath (relativePath))
|
||||
{
|
||||
// the path is really absolute..
|
||||
return File (relativePath);
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ public:
|
|||
be relative to. If this is actually a file rather than
|
||||
a directory, its parent directory will be used instead.
|
||||
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();
|
||||
|
||||
|
|
@ -834,6 +834,10 @@ public:
|
|||
*/
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -93,6 +93,11 @@ public:
|
|||
*/
|
||||
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.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue