Browse Source

tags/2021-05-28
jules 18 years ago
parent
commit
fb815110ca
11 changed files with 874 additions and 439 deletions
  1. +22
    -0
      build/linux/platform_specific_code/juce_linux_Threads.cpp
  2. +386
    -364
      build/macosx/platform_specific_code/juce_mac_Threads.cpp
  3. +11
    -0
      build/win32/platform_specific_code/juce_win32_Threads.cpp
  4. +401
    -44
      extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.cpp
  5. +1
    -1
      extras/juce demo/src/BinaryData.cpp
  6. +16
    -9
      src/juce_appframework/gui/components/controls/juce_ComboBox.h
  7. +8
    -4
      src/juce_core/basics/juce_PlatformDefs.h
  8. +10
    -11
      src/juce_core/basics/juce_StandardHeader.h
  9. +9
    -5
      src/juce_core/io/files/juce_File.cpp
  10. +5
    -1
      src/juce_core/io/files/juce_File.h
  11. +5
    -0
      src/juce_core/threads/juce_Process.h

+ 22
- 0
build/linux/platform_specific_code/juce_linux_Threads.cpp View File

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


+ 386
- 364
build/macosx/platform_specific_code/juce_mac_Threads.cpp View File

@@ -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, &param);
param.sched_priority = jlimit (1, 127, 1 + (priority * 126) / 11);
pthread_setschedparam ((pthread_t) handle, policy, &param);
}
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, &param);
param.sched_priority = jlimit (1, 127, 1 + (priority * 126) / 11);
pthread_setschedparam ((pthread_t) handle, policy, &param);
}

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

+ 11
- 0
build/win32/platform_specific_code/juce_win32_Threads.cpp View File

@@ -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()
{


+ 401
- 44
extras/audio plugin host/src/plugins/vst/juce_VSTPluginInstance.cpp View File

@@ -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 (&micro, 0);
vstHostTime.nanoSeconds = micro.tv_usec * 1000.0;
#elif JUCE_MAC
UnsignedWide micro;
Microseconds (&micro);
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
}

+ 1
- 1
extras/juce demo/src/BinaryData.cpp View File

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


+ 16
- 9
src/juce_appframework/gui/components/controls/juce_ComboBox.h View File

@@ -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();


+ 8
- 4
src/juce_core/basics/juce_PlatformDefs.h View File

@@ -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
//==============================================================================


+ 10
- 11
src/juce_core/basics/juce_StandardHeader.h View File

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


+ 9
- 5
src/juce_core/io/files/juce_File.cpp View File

@@ -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
|| (relativePath.isNotEmpty() && ((const String&) relativePath)[1] == T(':')))
|| (path.isNotEmpty() && ((const String&) path)[1] == T(':'));
#else
|| relativePath.startsWithChar (T('~')))
|| path.startsWithChar (T('~'));
#endif
}
const File File::getChildFile (String relativePath) const throw()
{
if (isAbsolutePath (relativePath))
{
// the path is really absolute..
return File (relativePath);


+ 5
- 1
src/juce_core/io/files/juce_File.h View File

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


+ 5
- 0
src/juce_core/threads/juce_Process.h View File

@@ -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…
Cancel
Save