- clean working copy for leaving SVN
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define JUCE_INCLUDED_AAX_IN_MM 1
|
||||
#include "juce_AAX_Wrapper.cpp"
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#define UseExtendedThingResource 1
|
||||
#include <AudioUnit/AudioUnit.r>
|
||||
|
||||
//==============================================================================
|
||||
/* The AppConfig.h file should be a file in your project, containing info to describe the
|
||||
plugin's name, type, etc. The introjucer will generate this file automatically for you.
|
||||
|
||||
You may need to adjust the include path of your project to make sure it can be
|
||||
found by this include statement. (Don't hack this file to change the include path)
|
||||
*/
|
||||
#include "AppConfig.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// component resources for Audio Unit
|
||||
#define RES_ID 1000
|
||||
#define COMP_TYPE JucePlugin_AUMainType
|
||||
#define COMP_SUBTYPE JucePlugin_AUSubType
|
||||
#define COMP_MANUF JucePlugin_AUManufacturerCode
|
||||
#define VERSION JucePlugin_VersionCode
|
||||
#define NAME JucePlugin_Manufacturer ": " JucePlugin_Name
|
||||
#define DESCRIPTION JucePlugin_Desc
|
||||
#define ENTRY_POINT JucePlugin_AUExportPrefixQuoted "Entry"
|
||||
|
||||
#include "AUResources.r"
|
||||
|
||||
//==============================================================================
|
||||
// component resources for Audio Unit Carbon View
|
||||
|
||||
#ifndef BUILD_AU_CARBON_UI
|
||||
#define BUILD_AU_CARBON_UI 1
|
||||
#endif
|
||||
|
||||
#if BUILD_AU_CARBON_UI
|
||||
#define RES_ID 2000
|
||||
#define COMP_TYPE kAudioUnitCarbonViewComponentType
|
||||
#define COMP_SUBTYPE JucePlugin_AUSubType
|
||||
#define COMP_MANUF JucePlugin_AUManufacturerCode
|
||||
#define VERSION JucePlugin_VersionCode
|
||||
#define NAME JucePlugin_Manufacturer ": " JucePlugin_Name " View"
|
||||
#define DESCRIPTION NAME
|
||||
#define ENTRY_POINT JucePlugin_AUExportPrefixQuoted "ViewEntry"
|
||||
|
||||
#include "AUResources.r"
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// Your project must contain an AppConfig.h file with your project-specific settings in it,
|
||||
// and your header search path must make it accessible to the module's files.
|
||||
#include "AppConfig.h"
|
||||
|
||||
#include "../utility/juce_CheckSettingMacros.h"
|
||||
|
||||
#if JucePlugin_Build_RTAS
|
||||
|
||||
#include "juce_RTAS_DigiCode_Header.h"
|
||||
|
||||
/*
|
||||
This file is used to include and build the required digidesign CPP files without your project
|
||||
needing to reference the files directly. Because these files will be found via your include path,
|
||||
this means that the project doesn't have to change to cope with people's SDKs being in different
|
||||
locations.
|
||||
|
||||
Important note on Windows: In your project settings for the three juce_RTAS_DigiCode.cpp files and
|
||||
the juce_RTAS_Wrapper.cpp file, you need to set the calling convention to "__stdcall".
|
||||
If you don't do this, you'll get some unresolved externals and will spend a long time wondering what's
|
||||
going on... All the other files in your project can be set to use the normal __cdecl convention.
|
||||
|
||||
If you get an error building the includes statements below, check your paths - there's a full
|
||||
list of the necessary Digidesign paths in juce_RTAS_Wrapper.cpp
|
||||
*/
|
||||
|
||||
#if WINDOWS_VERSION
|
||||
#undef _UNICODE
|
||||
#undef UNICODE
|
||||
#endif
|
||||
|
||||
#include <CEffectGroup.cpp>
|
||||
#include <CEffectGroupMIDI.cpp>
|
||||
#include <CEffectMIDIUtils.cpp>
|
||||
#include <CEffectProcess.cpp>
|
||||
#include <CEffectProcessAS.cpp>
|
||||
#include <CEffectType.cpp>
|
||||
#include <CEffectTypeRTAS.cpp>
|
||||
#include <ChunkDataParser.cpp>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// Your project must contain an AppConfig.h file with your project-specific settings in it,
|
||||
// and your header search path must make it accessible to the module's files.
|
||||
#include "AppConfig.h"
|
||||
|
||||
#include "../utility/juce_CheckSettingMacros.h"
|
||||
|
||||
#if JucePlugin_Build_RTAS
|
||||
|
||||
#include "juce_RTAS_DigiCode_Header.h"
|
||||
|
||||
/*
|
||||
This file is used to include and build the required digidesign CPP files without your project
|
||||
needing to reference the files directly. Because these files will be found via your include path,
|
||||
this means that the project doesn't have to change to cope with people's SDKs being in different
|
||||
locations.
|
||||
|
||||
Important note on Windows: In your project settings for the three juce_RTAS_DigiCode.cpp files and
|
||||
the juce_RTAS_Wrapper.cpp file, you need to set the calling convention to "__stdcall".
|
||||
If you don't do this, you'll get some unresolved externals and will spend a long time wondering what's
|
||||
going on... All the other files in your project can be set to use the normal __cdecl convention.
|
||||
|
||||
If you get an error building the includes statements below, check your paths - there's a full
|
||||
list of the necessary Digidesign paths in juce_RTAS_Wrapper.cpp
|
||||
*/
|
||||
|
||||
#include <CEffectProcessMIDI.cpp>
|
||||
#include <PlugInUtils.cpp>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// Your project must contain an AppConfig.h file with your project-specific settings in it,
|
||||
// and your header search path must make it accessible to the module's files.
|
||||
#include "AppConfig.h"
|
||||
|
||||
#include "../utility/juce_CheckSettingMacros.h"
|
||||
|
||||
#if JucePlugin_Build_RTAS
|
||||
|
||||
#include "juce_RTAS_DigiCode_Header.h"
|
||||
|
||||
/*
|
||||
This file is used to include and build the required digidesign CPP files without your project
|
||||
needing to reference the files directly. Because these files will be found via your include path,
|
||||
this means that the project doesn't have to change to cope with people's SDKs being in different
|
||||
locations.
|
||||
|
||||
Important note on Windows: In your project settings for the three juce_RTAS_DigiCode.cpp files and
|
||||
the juce_RTAS_Wrapper.cpp file, you need to set the calling convention to "__stdcall".
|
||||
If you don't do this, you'll get some unresolved externals and will spend a long time wondering what's
|
||||
going on... All the other files in your project can be set to use the normal __cdecl convention.
|
||||
|
||||
If you get an error building the includes statements below, check your paths - there's a full
|
||||
list of the necessary Digidesign paths in juce_RTAS_Wrapper.cpp
|
||||
*/
|
||||
|
||||
#if WINDOWS_VERSION
|
||||
#undef _UNICODE
|
||||
#undef UNICODE
|
||||
|
||||
#define DllMain DllMainRTAS
|
||||
#include <DLLMain.cpp>
|
||||
#undef DllMain
|
||||
#include <DefaultSwap.cpp>
|
||||
|
||||
#else
|
||||
#include <PlugInInitialize.cpp>
|
||||
#include <Dispatcher.cpp>
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#if _MSC_VER
|
||||
short __stdcall NewPlugIn (void*) { return 0; }
|
||||
short __stdcall _PI_GetRoutineDescriptor (long, void*) { return 0; }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_RTAS_DIGICODE_HEADER_H_INCLUDED
|
||||
#define JUCE_RTAS_DIGICODE_HEADER_H_INCLUDED
|
||||
|
||||
#if JucePlugin_Build_RTAS
|
||||
|
||||
//==============================================================================
|
||||
#if JucePlugin_Build_RTAS
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#define kCompileAsCodeResource 0
|
||||
#define kBuildStandAlone 0
|
||||
#define kNoDSP 0
|
||||
#define kNoDAE 0
|
||||
#define kNoSDS 0
|
||||
#define kNoViews 0
|
||||
#define kUseDSPCodeDecode 0
|
||||
|
||||
#define WIN32 1
|
||||
#define WINDOWS_VERSION 1
|
||||
#define PLUGIN_SDK_BUILD 1
|
||||
#define PLUGIN_SDK_DIRECTMIDI 1
|
||||
|
||||
// the Digidesign projects all use a struct alignment of 2..
|
||||
#pragma pack (2)
|
||||
#pragma warning (disable: 4267 4996 4311 4312 4103 4121 4100 4127 4189 4245 4389 4512 4701)
|
||||
|
||||
#include <ForcedInclude.h>
|
||||
|
||||
#else
|
||||
|
||||
#define kCompileAsCodeResource 0
|
||||
#define kNoDSP 1
|
||||
#define kNoDAE 0
|
||||
#define kNoSDS 0
|
||||
#define kNoViews 0
|
||||
#define kUseDSPCodeDecode 0
|
||||
|
||||
#define MAC_VERSION 1
|
||||
#define PLUGIN_SDK_BUILD 1
|
||||
#define PLUGIN_SDK_DIRECTMIDI 1
|
||||
#define DIGI_PASCAL
|
||||
|
||||
#include <MacAlwaysInclude.h>
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // JUCE_RTAS_DIGICODE_HEADER_H_INCLUDED
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
/*
|
||||
This dummy file is added to the resources section of the project to
|
||||
force XCode to create some resources for the dpm. If there aren't any
|
||||
resources, PT will refuse to load the plugin..
|
||||
*/
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// Your project must contain an AppConfig.h file with your project-specific settings in it,
|
||||
// and your header search path must make it accessible to the module's files.
|
||||
#include "AppConfig.h"
|
||||
|
||||
#include "../utility/juce_CheckSettingMacros.h"
|
||||
|
||||
#if JucePlugin_Build_RTAS
|
||||
|
||||
// Horrible carbon-based fix for a cocoa bug, where an NSWindow that wraps a carbon
|
||||
// window fails to keep its position updated when the user drags the window around..
|
||||
#define WINDOWPOSITION_BODGE 1
|
||||
#define JUCE_MAC_WINDOW_VISIBITY_BODGE 1
|
||||
|
||||
#include "../utility/juce_IncludeSystemHeaders.h"
|
||||
#include "../utility/juce_IncludeModuleHeaders.h"
|
||||
#include "../utility/juce_CarbonVisibility.h"
|
||||
|
||||
//==============================================================================
|
||||
void initialiseMacRTAS();
|
||||
void initialiseMacRTAS()
|
||||
{
|
||||
#if ! JUCE_64BIT
|
||||
NSApplicationLoad();
|
||||
#endif
|
||||
}
|
||||
|
||||
void* attachSubWindow (void*, Component*);
|
||||
void* attachSubWindow (void* hostWindowRef, Component* comp)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
#if 0
|
||||
// This was suggested as a way to improve passing keypresses to the host, but
|
||||
// a side-effect seems to be occasional rendering artifacts.
|
||||
HIWindowChangeClass ((WindowRef) hostWindowRef, kFloatingWindowClass);
|
||||
#endif
|
||||
|
||||
NSWindow* hostWindow = [[NSWindow alloc] initWithWindowRef: hostWindowRef];
|
||||
[hostWindow retain];
|
||||
[hostWindow setCanHide: YES];
|
||||
[hostWindow setReleasedWhenClosed: YES];
|
||||
NSRect oldWindowFrame = [hostWindow frame];
|
||||
|
||||
NSView* content = [hostWindow contentView];
|
||||
NSRect f = [content frame];
|
||||
f.size.width = comp->getWidth();
|
||||
f.size.height = comp->getHeight();
|
||||
[content setFrame: f];
|
||||
|
||||
const CGFloat mainScreenHeight = [[[NSScreen screens] objectAtIndex: 0] frame].size.height;
|
||||
|
||||
#if WINDOWPOSITION_BODGE
|
||||
{
|
||||
Rect winBounds;
|
||||
GetWindowBounds ((WindowRef) hostWindowRef, kWindowContentRgn, &winBounds);
|
||||
NSRect w = [hostWindow frame];
|
||||
w.origin.x = winBounds.left;
|
||||
w.origin.y = mainScreenHeight - winBounds.bottom;
|
||||
[hostWindow setFrame: w display: NO animate: NO];
|
||||
}
|
||||
#endif
|
||||
|
||||
NSPoint windowPos = [hostWindow convertBaseToScreen: f.origin];
|
||||
windowPos.x = windowPos.x + jmax (0.0f, (oldWindowFrame.size.width - f.size.width) / 2.0f);
|
||||
windowPos.y = mainScreenHeight - (windowPos.y + f.size.height);
|
||||
|
||||
comp->setTopLeftPosition ((int) windowPos.x, (int) windowPos.y);
|
||||
|
||||
#if ! JucePlugin_EditorRequiresKeyboardFocus
|
||||
comp->addToDesktop (ComponentPeer::windowIsTemporary | ComponentPeer::windowIgnoresKeyPresses);
|
||||
#else
|
||||
comp->addToDesktop (ComponentPeer::windowIsTemporary);
|
||||
#endif
|
||||
|
||||
comp->setVisible (true);
|
||||
|
||||
NSView* pluginView = (NSView*) comp->getWindowHandle();
|
||||
NSWindow* pluginWindow = [pluginView window];
|
||||
|
||||
[hostWindow addChildWindow: pluginWindow
|
||||
ordered: NSWindowAbove];
|
||||
[hostWindow orderFront: nil];
|
||||
[pluginWindow orderFront: nil];
|
||||
|
||||
attachWindowHidingHooks (comp, (WindowRef) hostWindowRef, hostWindow);
|
||||
|
||||
return hostWindow;
|
||||
}
|
||||
}
|
||||
|
||||
void removeSubWindow (void*, Component*);
|
||||
void removeSubWindow (void* nsWindow, Component* comp)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
NSView* pluginView = (NSView*) comp->getWindowHandle();
|
||||
NSWindow* hostWindow = (NSWindow*) nsWindow;
|
||||
NSWindow* pluginWindow = [pluginView window];
|
||||
|
||||
removeWindowHidingHooks (comp);
|
||||
[hostWindow removeChildWindow: pluginWindow];
|
||||
comp->removeFromDesktop();
|
||||
[hostWindow release];
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
bool isJuceWindow (WindowRef w)
|
||||
{
|
||||
for (int i = ComponentPeer::getNumPeers(); --i >= 0;)
|
||||
{
|
||||
ComponentPeer* peer = ComponentPeer::getPeer(i);
|
||||
NSView* view = (NSView*) peer->getNativeHandle();
|
||||
|
||||
if ([[view window] windowRef] == w)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void forwardCurrentKeyEventToHostWindow();
|
||||
void forwardCurrentKeyEventToHostWindow()
|
||||
{
|
||||
WindowRef w = FrontNonFloatingWindow();
|
||||
WindowRef original = w;
|
||||
|
||||
while (IsValidWindowPtr (w) && isJuceWindow (w))
|
||||
{
|
||||
w = GetNextWindowOfClass (w, kDocumentWindowClass, true);
|
||||
|
||||
if (w == original)
|
||||
break;
|
||||
}
|
||||
|
||||
if (! isJuceWindow (w))
|
||||
{
|
||||
ActivateWindow (w, true);
|
||||
repostCurrentNSEvent();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
EXPORTS
|
||||
NewPlugIn @1
|
||||
_PI_GetRoutineDescriptor @2
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// Your project must contain an AppConfig.h file with your project-specific settings in it,
|
||||
// and your header search path must make it accessible to the module's files.
|
||||
#include "AppConfig.h"
|
||||
|
||||
#include "../utility/juce_CheckSettingMacros.h"
|
||||
|
||||
// (these functions are in their own file because of problems including windows.h
|
||||
// at the same time as the Digi headers)
|
||||
|
||||
#if JucePlugin_Build_RTAS
|
||||
|
||||
#define _DO_NOT_DECLARE_INTERLOCKED_INTRINSICS_IN_MEMORY // (workaround for a VC build problem)
|
||||
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0500
|
||||
#undef STRICT
|
||||
#define STRICT
|
||||
#include <intrin.h>
|
||||
#include <windows.h>
|
||||
|
||||
#pragma pack (push, 8)
|
||||
#include "../utility/juce_IncludeModuleHeaders.h"
|
||||
#pragma pack (pop)
|
||||
|
||||
//==============================================================================
|
||||
void JUCE_CALLTYPE attachSubWindow (void* hostWindow,
|
||||
int& titleW, int& titleH,
|
||||
Component* comp)
|
||||
{
|
||||
RECT clientRect;
|
||||
GetClientRect ((HWND) hostWindow, &clientRect);
|
||||
|
||||
titleW = clientRect.right - clientRect.left;
|
||||
titleH = jmax (0, (int) (clientRect.bottom - clientRect.top) - comp->getHeight());
|
||||
comp->setTopLeftPosition (0, titleH);
|
||||
|
||||
comp->addToDesktop (0);
|
||||
|
||||
HWND plugWnd = (HWND) comp->getWindowHandle();
|
||||
SetParent (plugWnd, (HWND) hostWindow);
|
||||
|
||||
DWORD val = GetWindowLong (plugWnd, GWL_STYLE);
|
||||
val = (val & ~WS_POPUP) | WS_CHILD;
|
||||
SetWindowLong (plugWnd, GWL_STYLE, val);
|
||||
|
||||
val = GetWindowLong ((HWND) hostWindow, GWL_STYLE);
|
||||
SetWindowLong ((HWND) hostWindow, GWL_STYLE, val | WS_CLIPCHILDREN);
|
||||
}
|
||||
|
||||
void JUCE_CALLTYPE resizeHostWindow (void* hostWindow,
|
||||
int& titleW, int& titleH,
|
||||
Component* comp)
|
||||
{
|
||||
RECT clientRect, windowRect;
|
||||
GetClientRect ((HWND) hostWindow, &clientRect);
|
||||
GetWindowRect ((HWND) hostWindow, &windowRect);
|
||||
const int borderW = (windowRect.right - windowRect.left) - (clientRect.right - clientRect.left);
|
||||
const int borderH = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top);
|
||||
|
||||
SetWindowPos ((HWND) hostWindow, 0, 0, 0,
|
||||
borderW + jmax (titleW, comp->getWidth()),
|
||||
borderH + comp->getHeight() + titleH,
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER);
|
||||
}
|
||||
|
||||
#if ! JucePlugin_EditorRequiresKeyboardFocus
|
||||
|
||||
namespace
|
||||
{
|
||||
HWND findMDIParentOf (HWND w)
|
||||
{
|
||||
const int frameThickness = GetSystemMetrics (SM_CYFIXEDFRAME);
|
||||
|
||||
while (w != 0)
|
||||
{
|
||||
HWND parent = GetParent (w);
|
||||
|
||||
if (parent == 0)
|
||||
break;
|
||||
|
||||
TCHAR windowType [32] = { 0 };
|
||||
GetClassName (parent, windowType, 31);
|
||||
|
||||
if (String (windowType).equalsIgnoreCase ("MDIClient"))
|
||||
{
|
||||
w = parent;
|
||||
break;
|
||||
}
|
||||
|
||||
RECT windowPos, parentPos;
|
||||
GetWindowRect (w, &windowPos);
|
||||
GetWindowRect (parent, &parentPos);
|
||||
|
||||
int dw = (parentPos.right - parentPos.left) - (windowPos.right - windowPos.left);
|
||||
int dh = (parentPos.bottom - parentPos.top) - (windowPos.bottom - windowPos.top);
|
||||
|
||||
if (dw > 100 || dh > 100)
|
||||
break;
|
||||
|
||||
w = parent;
|
||||
|
||||
if (dw == 2 * frameThickness)
|
||||
break;
|
||||
}
|
||||
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
void JUCE_CALLTYPE passFocusToHostWindow (void* hostWindow)
|
||||
{
|
||||
SetFocus (findMDIParentOf ((HWND) hostWindow));
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,990 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// Your project must contain an AppConfig.h file with your project-specific settings in it,
|
||||
// and your header search path must make it accessible to the module's files.
|
||||
#include "AppConfig.h"
|
||||
|
||||
#include "../utility/juce_CheckSettingMacros.h"
|
||||
|
||||
#if JucePlugin_Build_RTAS
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// (this is a workaround for a build problem in VC9)
|
||||
#define _DO_NOT_DECLARE_INTERLOCKED_INTRINSICS_IN_MEMORY
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#include "juce_RTAS_DigiCode_Header.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <Mac2Win.H>
|
||||
#endif
|
||||
|
||||
/* Note about include paths
|
||||
------------------------
|
||||
|
||||
To be able to include all the Digidesign headers correctly, you'll need to add this
|
||||
lot to your include path:
|
||||
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\EffectClasses
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\ProcessClasses
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\ProcessClasses\Interfaces
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\Utilities
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\RTASP_Adapt
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\CoreClasses
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\Controls
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\Meters
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\ViewClasses
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\DSPClasses
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\Interfaces
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\common
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\common\Platform
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\SignalProcessing\Public
|
||||
C:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugIns\DSPManager\Interfaces
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\SADriver\Interfaces
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\DigiPublic\Interfaces
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\Fic\Interfaces\DAEClient
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\NewFileLibs\Cmn
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\NewFileLibs\DOA
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\AlturaSource\PPC_H
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\AlturaSource\AppSupport
|
||||
c:\yourdirectory\PT_80_SDK\AlturaPorts\DigiPublic
|
||||
c:\yourdirectory\PT_80_SDK\AvidCode\AVX2sdk\AVX\avx2\avx2sdk\inc
|
||||
c:\yourdirectory\PT_80_SDK\xplat\AVX\avx2\avx2sdk\inc
|
||||
|
||||
NB. If you hit a huge pile of bugs around here, make sure that you've not got the
|
||||
Apple QuickTime headers before the PT headers in your path, because there are
|
||||
some filename clashes between them.
|
||||
|
||||
*/
|
||||
#include <CEffectGroupMIDI.h>
|
||||
#include <CEffectProcessMIDI.h>
|
||||
#include <CEffectProcessRTAS.h>
|
||||
#include <CCustomView.h>
|
||||
#include <CEffectTypeRTAS.h>
|
||||
#include <CPluginControl.h>
|
||||
#include <CPluginControl_OnOff.h>
|
||||
#include <FicProcessTokens.h>
|
||||
#include <ExternalVersionDefines.h>
|
||||
|
||||
//==============================================================================
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack (push, 8)
|
||||
#pragma warning (disable: 4263 4264)
|
||||
#endif
|
||||
|
||||
#include "../utility/juce_IncludeModuleHeaders.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack (pop)
|
||||
|
||||
// This JUCE_RTAS_LINK_TO_DEBUG_LIB setting can be used to force linkage
|
||||
// against only the release build of the RTAS lib, since in older SDKs there
|
||||
// can be problems with the debug build.
|
||||
#if JUCE_DEBUG && ! defined (JUCE_RTAS_LINK_TO_DEBUG_LIB)
|
||||
#define JUCE_RTAS_LINK_TO_DEBUG_LIB 1
|
||||
#endif
|
||||
|
||||
#if JUCE_RTAS_LINK_TO_DEBUG_LIB
|
||||
#define PT_LIB_PATH JucePlugin_WinBag_path "\\Debug\\lib\\"
|
||||
#else
|
||||
#define PT_LIB_PATH JucePlugin_WinBag_path "\\Release\\lib\\"
|
||||
#endif
|
||||
|
||||
#pragma comment(lib, PT_LIB_PATH "DAE.lib")
|
||||
#pragma comment(lib, PT_LIB_PATH "DigiExt.lib")
|
||||
#pragma comment(lib, PT_LIB_PATH "DSI.lib")
|
||||
#pragma comment(lib, PT_LIB_PATH "PluginLib.lib")
|
||||
#pragma comment(lib, PT_LIB_PATH "DSPManager.lib")
|
||||
#pragma comment(lib, PT_LIB_PATH "DSPManagerClientLib.lib")
|
||||
#pragma comment(lib, PT_LIB_PATH "RTASClientLib.lib")
|
||||
#endif
|
||||
|
||||
#undef Component
|
||||
#undef MemoryBlock
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_WINDOWS
|
||||
extern void JUCE_CALLTYPE attachSubWindow (void* hostWindow, int& titleW, int& titleH, juce::Component* comp);
|
||||
extern void JUCE_CALLTYPE resizeHostWindow (void* hostWindow, int& titleW, int& titleH, juce::Component* comp);
|
||||
#if ! JucePlugin_EditorRequiresKeyboardFocus
|
||||
extern void JUCE_CALLTYPE passFocusToHostWindow (void* hostWindow);
|
||||
#endif
|
||||
#else
|
||||
extern void* attachSubWindow (void* hostWindowRef, juce::Component* comp);
|
||||
extern void removeSubWindow (void* nsWindow, juce::Component* comp);
|
||||
extern void forwardCurrentKeyEventToHostWindow();
|
||||
#endif
|
||||
|
||||
#if ! (JUCE_DEBUG || defined (JUCE_RTAS_PLUGINGESTALT_IS_CACHEABLE))
|
||||
#define JUCE_RTAS_PLUGINGESTALT_IS_CACHEABLE 1
|
||||
#endif
|
||||
|
||||
const int midiBufferSize = 1024;
|
||||
const OSType juceChunkType = 'juce';
|
||||
static const int bypassControlIndex = 1;
|
||||
|
||||
static int numInstances = 0;
|
||||
|
||||
//==============================================================================
|
||||
class JucePlugInProcess : public CEffectProcessMIDI,
|
||||
public CEffectProcessRTAS,
|
||||
public AudioProcessorListener,
|
||||
public AudioPlayHead
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
JucePlugInProcess()
|
||||
: sampleRate (44100.0)
|
||||
{
|
||||
juceFilter = createPluginFilterOfType (AudioProcessor::wrapperType_RTAS);
|
||||
|
||||
AddChunk (juceChunkType, "Juce Audio Plugin Data");
|
||||
|
||||
++numInstances;
|
||||
}
|
||||
|
||||
~JucePlugInProcess()
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
if (mLoggedIn)
|
||||
MIDILogOut();
|
||||
|
||||
midiBufferNode = nullptr;
|
||||
midiTransport = nullptr;
|
||||
|
||||
if (juceFilter != nullptr)
|
||||
{
|
||||
juceFilter->releaseResources();
|
||||
juceFilter = nullptr;
|
||||
}
|
||||
|
||||
if (--numInstances == 0)
|
||||
{
|
||||
#if JUCE_MAC
|
||||
// Hack to allow any NSWindows to clear themselves up before returning to PT..
|
||||
for (int i = 20; --i >= 0;)
|
||||
MessageManager::getInstance()->runDispatchLoopUntil (1);
|
||||
#endif
|
||||
|
||||
shutdownJuce_GUI();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class JuceCustomUIView : public CCustomView,
|
||||
public Timer
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
JuceCustomUIView (AudioProcessor* ap, JucePlugInProcess* p)
|
||||
: filter (ap), process (p)
|
||||
{
|
||||
// setting the size in here crashes PT for some reason, so keep it simple..
|
||||
}
|
||||
|
||||
~JuceCustomUIView()
|
||||
{
|
||||
deleteEditorComp();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void updateSize()
|
||||
{
|
||||
if (editorComp == nullptr)
|
||||
{
|
||||
editorComp = filter->createEditorIfNeeded();
|
||||
jassert (editorComp != nullptr);
|
||||
}
|
||||
|
||||
if (editorComp->getWidth() != 0 && editorComp->getHeight() != 0)
|
||||
{
|
||||
Rect oldRect;
|
||||
GetRect (&oldRect);
|
||||
|
||||
Rect r;
|
||||
r.left = 0;
|
||||
r.top = 0;
|
||||
r.right = editorComp->getWidth();
|
||||
r.bottom = editorComp->getHeight();
|
||||
SetRect (&r);
|
||||
|
||||
if (oldRect.right != r.right || oldRect.bottom != r.bottom)
|
||||
startTimer (50);
|
||||
}
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
if (! juce::Component::isMouseButtonDownAnywhere())
|
||||
{
|
||||
stopTimer();
|
||||
|
||||
// Send a token to the host to tell it about the resize
|
||||
SSetProcessWindowResizeToken token (process->fRootNameId, process->fRootNameId);
|
||||
FicSDSDispatchToken (&token);
|
||||
}
|
||||
}
|
||||
|
||||
void attachToWindow (GrafPtr port)
|
||||
{
|
||||
if (port != 0)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
updateSize();
|
||||
|
||||
#if JUCE_WINDOWS
|
||||
void* const hostWindow = (void*) ASI_GethWnd ((WindowPtr) port);
|
||||
#else
|
||||
void* const hostWindow = (void*) GetWindowFromPort (port);
|
||||
#endif
|
||||
wrapper = nullptr;
|
||||
wrapper = new EditorCompWrapper (hostWindow, editorComp, this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
deleteEditorComp();
|
||||
}
|
||||
}
|
||||
|
||||
void DrawContents (Rect*)
|
||||
{
|
||||
#if JUCE_WINDOWS
|
||||
if (wrapper != nullptr)
|
||||
{
|
||||
if (ComponentPeer* const peer = wrapper->getPeer())
|
||||
peer->repaint (wrapper->getLocalBounds()); // (seems to be required in PT6.4, but not in 7.x)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void DrawBackground (Rect*) {}
|
||||
|
||||
//==============================================================================
|
||||
private:
|
||||
AudioProcessor* const filter;
|
||||
JucePlugInProcess* const process;
|
||||
ScopedPointer<juce::Component> wrapper;
|
||||
ScopedPointer<AudioProcessorEditor> editorComp;
|
||||
|
||||
void deleteEditorComp()
|
||||
{
|
||||
if (editorComp != nullptr || wrapper != nullptr)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
PopupMenu::dismissAllActiveMenus();
|
||||
|
||||
if (juce::Component* const modalComponent = juce::Component::getCurrentlyModalComponent())
|
||||
modalComponent->exitModalState (0);
|
||||
|
||||
filter->editorBeingDeleted (editorComp);
|
||||
|
||||
editorComp = nullptr;
|
||||
wrapper = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// A component to hold the AudioProcessorEditor, and cope with some housekeeping
|
||||
// chores when it changes or repaints.
|
||||
class EditorCompWrapper : public juce::Component
|
||||
#if ! JUCE_MAC
|
||||
, public FocusChangeListener
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
EditorCompWrapper (void* const hostWindow_,
|
||||
Component* const editorComp,
|
||||
JuceCustomUIView* const owner_)
|
||||
: hostWindow (hostWindow_),
|
||||
owner (owner_),
|
||||
titleW (0),
|
||||
titleH (0)
|
||||
{
|
||||
#if ! JucePlugin_EditorRequiresKeyboardFocus
|
||||
setMouseClickGrabsKeyboardFocus (false);
|
||||
setWantsKeyboardFocus (false);
|
||||
#endif
|
||||
setOpaque (true);
|
||||
setBroughtToFrontOnMouseClick (true);
|
||||
setBounds (editorComp->getBounds());
|
||||
editorComp->setTopLeftPosition (0, 0);
|
||||
addAndMakeVisible (editorComp);
|
||||
|
||||
#if JUCE_WINDOWS
|
||||
attachSubWindow (hostWindow, titleW, titleH, this);
|
||||
#else
|
||||
nsWindow = attachSubWindow (hostWindow, this);
|
||||
#endif
|
||||
setVisible (true);
|
||||
|
||||
#if JUCE_WINDOWS && ! JucePlugin_EditorRequiresKeyboardFocus
|
||||
Desktop::getInstance().addFocusChangeListener (this);
|
||||
#endif
|
||||
}
|
||||
|
||||
~EditorCompWrapper()
|
||||
{
|
||||
removeChildComponent (getEditor());
|
||||
|
||||
#if JUCE_WINDOWS && ! JucePlugin_EditorRequiresKeyboardFocus
|
||||
Desktop::getInstance().removeFocusChangeListener (this);
|
||||
#endif
|
||||
|
||||
#if JUCE_MAC
|
||||
removeSubWindow (nsWindow, this);
|
||||
#endif
|
||||
}
|
||||
|
||||
void paint (Graphics&) override {}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
if (juce::Component* const ed = getEditor())
|
||||
ed->setBounds (getLocalBounds());
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
#if JUCE_WINDOWS
|
||||
void globalFocusChanged (juce::Component*) override
|
||||
{
|
||||
#if ! JucePlugin_EditorRequiresKeyboardFocus
|
||||
if (hasKeyboardFocus (true))
|
||||
passFocusToHostWindow (hostWindow);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void childBoundsChanged (juce::Component* child) override
|
||||
{
|
||||
setSize (child->getWidth(), child->getHeight());
|
||||
child->setTopLeftPosition (0, 0);
|
||||
|
||||
#if JUCE_WINDOWS
|
||||
resizeHostWindow (hostWindow, titleW, titleH, this);
|
||||
#endif
|
||||
owner->updateSize();
|
||||
}
|
||||
|
||||
void userTriedToCloseWindow() override {}
|
||||
|
||||
#if JUCE_MAC && JucePlugin_EditorRequiresKeyboardFocus
|
||||
bool keyPressed (const KeyPress& kp) override
|
||||
{
|
||||
owner->updateSize();
|
||||
forwardCurrentKeyEventToHostWindow();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
void* const hostWindow;
|
||||
void* nsWindow;
|
||||
JuceCustomUIView* const owner;
|
||||
int titleW, titleH;
|
||||
|
||||
juce::Component* getEditor() const { return getChildComponent (0); }
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EditorCompWrapper)
|
||||
};
|
||||
};
|
||||
|
||||
JuceCustomUIView* getView() const
|
||||
{
|
||||
return dynamic_cast <JuceCustomUIView*> (fOurPlugInView);
|
||||
}
|
||||
|
||||
void GetViewRect (Rect* size) override
|
||||
{
|
||||
if (JuceCustomUIView* const v = getView())
|
||||
v->updateSize();
|
||||
|
||||
CEffectProcessRTAS::GetViewRect (size);
|
||||
}
|
||||
|
||||
CPlugInView* CreateCPlugInView() override
|
||||
{
|
||||
return new JuceCustomUIView (juceFilter, this);
|
||||
}
|
||||
|
||||
void SetViewPort (GrafPtr port) override
|
||||
{
|
||||
CEffectProcessRTAS::SetViewPort (port);
|
||||
|
||||
if (JuceCustomUIView* const v = getView())
|
||||
v->attachToWindow (port);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
ComponentResult GetDelaySamplesLong (long* aNumSamples) override
|
||||
{
|
||||
if (aNumSamples != nullptr)
|
||||
*aNumSamples = juceFilter != nullptr ? juceFilter->getLatencySamples() : 0;
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void EffectInit() override
|
||||
{
|
||||
sampleRate = (double) GetSampleRate();
|
||||
jassert (sampleRate > 0);
|
||||
const int maxBlockSize = (int) CEffectProcessRTAS::GetMaximumRTASQuantum();
|
||||
jassert (maxBlockSize > 0);
|
||||
|
||||
SFicPlugInStemFormats stems;
|
||||
GetProcessType()->GetStemFormats (&stems);
|
||||
|
||||
juceFilter->setPlayConfigDetails (fNumInputs, fNumOutputs, sampleRate, maxBlockSize);
|
||||
|
||||
AddControl (new CPluginControl_OnOff ('bypa', "Master Bypass\nMastrByp\nMByp\nByp", false, true));
|
||||
DefineMasterBypassControlIndex (bypassControlIndex);
|
||||
|
||||
for (int i = 0; i < juceFilter->getNumParameters(); ++i)
|
||||
AddControl (new JucePluginControl (juceFilter, i));
|
||||
|
||||
// we need to do this midi log-in to get timecode, regardless of whether
|
||||
// the plugin actually uses midi...
|
||||
if (MIDILogIn() == noErr)
|
||||
{
|
||||
#if JucePlugin_WantsMidiInput
|
||||
if (CEffectType* const type = dynamic_cast <CEffectType*> (this->GetProcessType()))
|
||||
{
|
||||
char nodeName [64];
|
||||
type->GetProcessTypeName (63, nodeName);
|
||||
p2cstrcpy (nodeName, reinterpret_cast <unsigned char*> (nodeName));
|
||||
|
||||
midiBufferNode = new CEffectMIDIOtherBufferedNode (&mMIDIWorld,
|
||||
8192,
|
||||
eLocalNode,
|
||||
nodeName,
|
||||
midiBuffer);
|
||||
|
||||
midiBufferNode->Initialize (0xffff, true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
midiTransport = new CEffectMIDITransport (&mMIDIWorld);
|
||||
midiEvents.ensureSize (2048);
|
||||
|
||||
channels.calloc (jmax (juceFilter->getNumInputChannels(),
|
||||
juceFilter->getNumOutputChannels()));
|
||||
|
||||
juceFilter->setPlayHead (this);
|
||||
juceFilter->addListener (this);
|
||||
|
||||
juceFilter->prepareToPlay (sampleRate, maxBlockSize);
|
||||
}
|
||||
|
||||
void RenderAudio (float** inputs, float** outputs, long numSamples) override
|
||||
{
|
||||
#if JucePlugin_WantsMidiInput
|
||||
midiEvents.clear();
|
||||
|
||||
const Cmn_UInt32 bufferSize = mRTGlobals->mHWBufferSizeInSamples;
|
||||
|
||||
if (midiBufferNode != nullptr)
|
||||
{
|
||||
if (midiBufferNode->GetAdvanceScheduleTime() != bufferSize)
|
||||
midiBufferNode->SetAdvanceScheduleTime (bufferSize);
|
||||
|
||||
if (midiBufferNode->FillMIDIBuffer (mRTGlobals->mRunningTime, numSamples) == noErr)
|
||||
{
|
||||
jassert (midiBufferNode->GetBufferPtr() != nullptr);
|
||||
const int numMidiEvents = midiBufferNode->GetBufferSize();
|
||||
|
||||
for (int i = 0; i < numMidiEvents; ++i)
|
||||
{
|
||||
const DirectMidiPacket& m = midiBuffer[i];
|
||||
|
||||
jassert ((int) m.mTimestamp < numSamples);
|
||||
|
||||
midiEvents.addEvent (m.mData, m.mLength,
|
||||
jlimit (0, (int) numSamples - 1, (int) m.mTimestamp));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if JUCE_DEBUG || JUCE_LOG_ASSERTIONS
|
||||
const int numMidiEventsComingIn = midiEvents.getNumEvents();
|
||||
(void) numMidiEventsComingIn;
|
||||
#endif
|
||||
|
||||
{
|
||||
const ScopedLock sl (juceFilter->getCallbackLock());
|
||||
|
||||
const int numIn = juceFilter->getNumInputChannels();
|
||||
const int numOut = juceFilter->getNumOutputChannels();
|
||||
const int totalChans = jmax (numIn, numOut);
|
||||
|
||||
if (juceFilter->isSuspended())
|
||||
{
|
||||
for (int i = 0; i < numOut; ++i)
|
||||
FloatVectorOperations::clear (outputs [i], numSamples);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < numOut; ++i)
|
||||
{
|
||||
channels[i] = outputs [i];
|
||||
|
||||
if (i < numIn && inputs != outputs)
|
||||
FloatVectorOperations::copy (outputs [i], inputs[i], numSamples);
|
||||
}
|
||||
|
||||
for (; i < numIn; ++i)
|
||||
channels [i] = inputs [i];
|
||||
}
|
||||
|
||||
AudioSampleBuffer chans (channels, totalChans, numSamples);
|
||||
|
||||
if (mBypassed)
|
||||
juceFilter->processBlockBypassed (chans, midiEvents);
|
||||
else
|
||||
juceFilter->processBlock (chans, midiEvents);
|
||||
}
|
||||
}
|
||||
|
||||
if (! midiEvents.isEmpty())
|
||||
{
|
||||
#if JucePlugin_ProducesMidiOutput
|
||||
const juce::uint8* midiEventData;
|
||||
int midiEventSize, midiEventPosition;
|
||||
MidiBuffer::Iterator i (midiEvents);
|
||||
|
||||
while (i.getNextEvent (midiEventData, midiEventSize, midiEventPosition))
|
||||
{
|
||||
//jassert (midiEventPosition >= 0 && midiEventPosition < (int) numSamples);
|
||||
}
|
||||
#elif JUCE_DEBUG || JUCE_LOG_ASSERTIONS
|
||||
// if your plugin creates midi messages, you'll need to set
|
||||
// the JucePlugin_ProducesMidiOutput macro to 1 in your
|
||||
// JucePluginCharacteristics.h file
|
||||
jassert (midiEvents.getNumEvents() <= numMidiEventsComingIn);
|
||||
#endif
|
||||
|
||||
midiEvents.clear();
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
ComponentResult GetChunkSize (OSType chunkID, long* size) override
|
||||
{
|
||||
if (chunkID == juceChunkType)
|
||||
{
|
||||
tempFilterData.reset();
|
||||
juceFilter->getStateInformation (tempFilterData);
|
||||
|
||||
*size = sizeof (SFicPlugInChunkHeader) + tempFilterData.getSize();
|
||||
return noErr;
|
||||
}
|
||||
|
||||
return CEffectProcessMIDI::GetChunkSize (chunkID, size);
|
||||
}
|
||||
|
||||
ComponentResult GetChunk (OSType chunkID, SFicPlugInChunk* chunk) override
|
||||
{
|
||||
if (chunkID == juceChunkType)
|
||||
{
|
||||
if (tempFilterData.getSize() == 0)
|
||||
juceFilter->getStateInformation (tempFilterData);
|
||||
|
||||
chunk->fSize = sizeof (SFicPlugInChunkHeader) + tempFilterData.getSize();
|
||||
tempFilterData.copyTo ((void*) chunk->fData, 0, tempFilterData.getSize());
|
||||
|
||||
tempFilterData.reset();
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
return CEffectProcessMIDI::GetChunk (chunkID, chunk);
|
||||
}
|
||||
|
||||
ComponentResult SetChunk (OSType chunkID, SFicPlugInChunk* chunk) override
|
||||
{
|
||||
if (chunkID == juceChunkType)
|
||||
{
|
||||
tempFilterData.reset();
|
||||
|
||||
if (chunk->fSize - sizeof (SFicPlugInChunkHeader) > 0)
|
||||
{
|
||||
juceFilter->setStateInformation ((void*) chunk->fData,
|
||||
chunk->fSize - sizeof (SFicPlugInChunkHeader));
|
||||
}
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
return CEffectProcessMIDI::SetChunk (chunkID, chunk);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
ComponentResult UpdateControlValue (long controlIndex, long value) override
|
||||
{
|
||||
if (controlIndex != bypassControlIndex)
|
||||
juceFilter->setParameter (controlIndex - 2, longToFloat (value));
|
||||
else
|
||||
mBypassed = (value > 0);
|
||||
|
||||
return CProcess::UpdateControlValue (controlIndex, value);
|
||||
}
|
||||
|
||||
#if JUCE_WINDOWS
|
||||
Boolean HandleKeystroke (EventRecord* e) override
|
||||
{
|
||||
if (juce::Component* modalComp = juce::Component::getCurrentlyModalComponent())
|
||||
{
|
||||
if (juce::Component* focused = modalComp->getCurrentlyFocusedComponent())
|
||||
{
|
||||
switch (e->message & charCodeMask)
|
||||
{
|
||||
case kReturnCharCode:
|
||||
case kEnterCharCode: focused->keyPressed (KeyPress (KeyPress::returnKey)); break;
|
||||
case kEscapeCharCode: focused->keyPressed (KeyPress (KeyPress::escapeKey)); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
bool getCurrentPosition (AudioPlayHead::CurrentPositionInfo& info) override
|
||||
{
|
||||
Cmn_Float64 bpm = 120.0;
|
||||
Cmn_Int32 num = 4, denom = 4;
|
||||
Cmn_Int64 ticks = 0;
|
||||
Cmn_Bool isPlaying = false;
|
||||
|
||||
if (midiTransport != nullptr)
|
||||
{
|
||||
midiTransport->GetCurrentTempo (&bpm);
|
||||
midiTransport->IsTransportPlaying (&isPlaying);
|
||||
midiTransport->GetCurrentMeter (&num, &denom);
|
||||
|
||||
// (The following is a work-around because GetCurrentTickPosition() doesn't work correctly).
|
||||
Cmn_Int64 sampleLocation;
|
||||
|
||||
if (isPlaying)
|
||||
midiTransport->GetCurrentRTASSampleLocation (&sampleLocation);
|
||||
else
|
||||
midiTransport->GetCurrentTDMSampleLocation (&sampleLocation);
|
||||
|
||||
midiTransport->GetCustomTickPosition (&ticks, sampleLocation);
|
||||
|
||||
info.timeInSamples = (int64) sampleLocation;
|
||||
info.timeInSeconds = sampleLocation / sampleRate;
|
||||
}
|
||||
else
|
||||
{
|
||||
info.timeInSamples = 0;
|
||||
info.timeInSeconds = 0;
|
||||
}
|
||||
|
||||
info.bpm = bpm;
|
||||
info.timeSigNumerator = num;
|
||||
info.timeSigDenominator = denom;
|
||||
info.isPlaying = isPlaying;
|
||||
info.isRecording = false;
|
||||
info.ppqPosition = ticks / 960000.0;
|
||||
info.ppqPositionOfLastBarStart = 0; //xxx no idea how to get this correctly..
|
||||
info.isLooping = false;
|
||||
info.ppqLoopStart = 0;
|
||||
info.ppqLoopEnd = 0;
|
||||
|
||||
double framesPerSec = 24.0;
|
||||
|
||||
switch (fTimeCodeInfo.mFrameRate)
|
||||
{
|
||||
case ficFrameRate_24Frame: info.frameRate = AudioPlayHead::fps24; break;
|
||||
case ficFrameRate_25Frame: info.frameRate = AudioPlayHead::fps25; framesPerSec = 25.0; break;
|
||||
case ficFrameRate_2997NonDrop: info.frameRate = AudioPlayHead::fps2997; framesPerSec = 29.97002997; break;
|
||||
case ficFrameRate_2997DropFrame: info.frameRate = AudioPlayHead::fps2997drop; framesPerSec = 29.97002997; break;
|
||||
case ficFrameRate_30NonDrop: info.frameRate = AudioPlayHead::fps30; framesPerSec = 30.0; break;
|
||||
case ficFrameRate_30DropFrame: info.frameRate = AudioPlayHead::fps30drop; framesPerSec = 30.0; break;
|
||||
case ficFrameRate_23976: info.frameRate = AudioPlayHead::fps24; framesPerSec = 23.976; break;
|
||||
default: info.frameRate = AudioPlayHead::fpsUnknown; break;
|
||||
}
|
||||
|
||||
info.editOriginTime = fTimeCodeInfo.mFrameOffset / framesPerSec;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void audioProcessorParameterChanged (AudioProcessor*, int index, float newValue) override
|
||||
{
|
||||
SetControlValue (index + 2, floatToLong (newValue));
|
||||
}
|
||||
|
||||
void audioProcessorParameterChangeGestureBegin (AudioProcessor*, int index) override
|
||||
{
|
||||
TouchControl (index + 2);
|
||||
}
|
||||
|
||||
void audioProcessorParameterChangeGestureEnd (AudioProcessor*, int index) override
|
||||
{
|
||||
ReleaseControl (index + 2);
|
||||
}
|
||||
|
||||
void audioProcessorChanged (AudioProcessor*) override
|
||||
{
|
||||
// xxx is there an RTAS equivalent?
|
||||
}
|
||||
|
||||
private:
|
||||
ScopedPointer<AudioProcessor> juceFilter;
|
||||
MidiBuffer midiEvents;
|
||||
ScopedPointer<CEffectMIDIOtherBufferedNode> midiBufferNode;
|
||||
ScopedPointer<CEffectMIDITransport> midiTransport;
|
||||
DirectMidiPacket midiBuffer [midiBufferSize];
|
||||
|
||||
juce::MemoryBlock tempFilterData;
|
||||
HeapBlock<float*> channels;
|
||||
double sampleRate;
|
||||
|
||||
static float longToFloat (const long n) noexcept
|
||||
{
|
||||
return (float) ((((double) n) + (double) 0x80000000) / (double) 0xffffffff);
|
||||
}
|
||||
|
||||
static long floatToLong (const float n) noexcept
|
||||
{
|
||||
return roundToInt (jlimit (-(double) 0x80000000, (double) 0x7fffffff,
|
||||
n * (double) 0xffffffff - (double) 0x80000000));
|
||||
}
|
||||
|
||||
void bypassBuffers (float** const inputs, float** const outputs, const long numSamples) const
|
||||
{
|
||||
for (int i = fNumOutputs; --i >= 0;)
|
||||
{
|
||||
if (i < fNumInputs)
|
||||
FloatVectorOperations::copy (outputs[i], inputs[i], numSamples);
|
||||
else
|
||||
FloatVectorOperations::clear (outputs[i], numSamples);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class JucePluginControl : public CPluginControl
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
JucePluginControl (AudioProcessor* const juceFilter_, const int index_)
|
||||
: juceFilter (juceFilter_),
|
||||
index (index_)
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
OSType GetID() const { return index + 1; }
|
||||
long GetDefaultValue() const { return floatToLong (juceFilter->getParameterDefaultValue (index)); }
|
||||
void SetDefaultValue (long) {}
|
||||
long GetNumSteps() const { return juceFilter->getParameterNumSteps (index); }
|
||||
|
||||
long ConvertStringToValue (const char* valueString) const
|
||||
{
|
||||
return floatToLong (String (valueString).getFloatValue());
|
||||
}
|
||||
|
||||
Cmn_Bool IsKeyValid (long key) const { return true; }
|
||||
|
||||
void GetNameOfLength (char* name, int maxLength, OSType inControllerType) const
|
||||
{
|
||||
// Pro-tools expects all your parameters to have valid names!
|
||||
jassert (juceFilter->getParameterName (index, maxLength).isNotEmpty());
|
||||
|
||||
juceFilter->getParameterName (index, maxLength).copyToUTF8 (name, (size_t) maxLength + 1);
|
||||
}
|
||||
|
||||
long GetPriority() const { return kFicCooperativeTaskPriority; }
|
||||
|
||||
long GetOrientation() const
|
||||
{
|
||||
return juceFilter->isParameterOrientationInverted (index)
|
||||
? kDAE_RightMinLeftMax | kDAE_TopMinBottomMax | kDAE_RotarySingleDotMode | kDAE_RotaryRightMinLeftMax
|
||||
: kDAE_LeftMinRightMax | kDAE_BottomMinTopMax | kDAE_RotarySingleDotMode | kDAE_RotaryLeftMinRightMax;
|
||||
}
|
||||
|
||||
long GetControlType() const { return kDAE_ContinuousValues; }
|
||||
|
||||
void GetValueString (char* valueString, int maxLength, long value) const
|
||||
{
|
||||
juceFilter->getParameterText (index, maxLength).copyToUTF8 (valueString, (size_t) maxLength + 1);
|
||||
}
|
||||
|
||||
Cmn_Bool IsAutomatable() const
|
||||
{
|
||||
return juceFilter->isParameterAutomatable (index);
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
AudioProcessor* const juceFilter;
|
||||
const int index;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (JucePluginControl)
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class JucePlugInGroup : public CEffectGroupMIDI
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
JucePlugInGroup()
|
||||
{
|
||||
DefineManufacturerNamesAndID (JucePlugin_Manufacturer, JucePlugin_RTASManufacturerCode);
|
||||
DefinePlugInNamesAndVersion (createRTASName().toUTF8(), JucePlugin_VersionCode);
|
||||
|
||||
#if JUCE_RTAS_PLUGINGESTALT_IS_CACHEABLE
|
||||
AddGestalt (pluginGestalt_IsCacheable);
|
||||
#endif
|
||||
}
|
||||
|
||||
~JucePlugInGroup()
|
||||
{
|
||||
shutdownJuce_GUI();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void CreateEffectTypes()
|
||||
{
|
||||
const short channelConfigs[][2] = { JucePlugin_PreferredChannelConfigurations };
|
||||
const int numConfigs = numElementsInArray (channelConfigs);
|
||||
|
||||
// You need to actually add some configurations to the JucePlugin_PreferredChannelConfigurations
|
||||
// value in your JucePluginCharacteristics.h file..
|
||||
jassert (numConfigs > 0);
|
||||
|
||||
for (int i = 0; i < numConfigs; ++i)
|
||||
{
|
||||
if (channelConfigs[i][0] <= 8 && channelConfigs[i][1] <= 8)
|
||||
{
|
||||
CEffectType* const type
|
||||
= new CEffectTypeRTAS ('jcaa' + i,
|
||||
JucePlugin_RTASProductId,
|
||||
JucePlugin_RTASCategory);
|
||||
|
||||
type->DefineTypeNames (createRTASName().toRawUTF8());
|
||||
type->DefineSampleRateSupport (eSupports48kAnd96kAnd192k);
|
||||
|
||||
type->DefineStemFormats (getFormatForChans (channelConfigs [i][0] != 0 ? channelConfigs [i][0] : channelConfigs [i][1]),
|
||||
getFormatForChans (channelConfigs [i][1] != 0 ? channelConfigs [i][1] : channelConfigs [i][0]));
|
||||
|
||||
#if ! JucePlugin_RTASDisableBypass
|
||||
type->AddGestalt (pluginGestalt_CanBypass);
|
||||
#endif
|
||||
|
||||
#if JucePlugin_RTASDisableMultiMono
|
||||
type->AddGestalt (pluginGestalt_DoesntSupportMultiMono);
|
||||
#endif
|
||||
|
||||
type->AddGestalt (pluginGestalt_SupportsVariableQuanta);
|
||||
type->AttachEffectProcessCreator (createNewProcess);
|
||||
|
||||
AddEffectType (type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
CEffectGroupMIDI::Initialize();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
private:
|
||||
static CEffectProcess* createNewProcess()
|
||||
{
|
||||
#if JUCE_WINDOWS
|
||||
Process::setCurrentModuleInstanceHandle (gThisModule);
|
||||
#endif
|
||||
|
||||
initialiseJuce_GUI();
|
||||
|
||||
return new JucePlugInProcess();
|
||||
}
|
||||
|
||||
static String createRTASName()
|
||||
{
|
||||
return String (JucePlugin_Name) + "\n"
|
||||
+ String (JucePlugin_Desc);
|
||||
}
|
||||
|
||||
static EPlugIn_StemFormat getFormatForChans (const int numChans) noexcept
|
||||
{
|
||||
switch (numChans)
|
||||
{
|
||||
case 0: return ePlugIn_StemFormat_Generic;
|
||||
case 1: return ePlugIn_StemFormat_Mono;
|
||||
case 2: return ePlugIn_StemFormat_Stereo;
|
||||
case 3: return ePlugIn_StemFormat_LCR;
|
||||
case 4: return ePlugIn_StemFormat_Quad;
|
||||
case 5: return ePlugIn_StemFormat_5dot0;
|
||||
case 6: return ePlugIn_StemFormat_5dot1;
|
||||
|
||||
#if PT_VERS_MAJOR >= 9
|
||||
case 7: return ePlugIn_StemFormat_7dot0DTS;
|
||||
case 8: return ePlugIn_StemFormat_7dot1DTS;
|
||||
#else
|
||||
case 7: return ePlugIn_StemFormat_7dot0;
|
||||
case 8: return ePlugIn_StemFormat_7dot1;
|
||||
#endif
|
||||
|
||||
default: jassertfalse; break; // hmm - not a valid number of chans for RTAS..
|
||||
}
|
||||
|
||||
return ePlugIn_StemFormat_Generic;
|
||||
}
|
||||
};
|
||||
|
||||
void initialiseMacRTAS();
|
||||
|
||||
CProcessGroupInterface* CProcessGroup::CreateProcessGroup()
|
||||
{
|
||||
#if JUCE_MAC
|
||||
initialiseMacRTAS();
|
||||
#endif
|
||||
|
||||
return new JucePlugInGroup();
|
||||
}
|
||||
|
||||
#endif
|
||||
+394
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_STANDALONEFILTERWINDOW_H_INCLUDED
|
||||
#define JUCE_STANDALONEFILTERWINDOW_H_INCLUDED
|
||||
|
||||
extern AudioProcessor* JUCE_CALLTYPE createPluginFilter();
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
An object that creates and plays a standalone instance of an AudioProcessor.
|
||||
|
||||
The object will create your processor using the same createPluginFilter()
|
||||
function that the other plugin wrappers use, and will run it through the
|
||||
computer's audio/MIDI devices using AudioDeviceManager and AudioProcessorPlayer.
|
||||
*/
|
||||
class StandalonePluginHolder
|
||||
{
|
||||
public:
|
||||
/** Creates an instance of the default plugin.
|
||||
|
||||
The settings object can be a PropertySet that the class should use to
|
||||
store its settings - the object that is passed-in will be owned by this
|
||||
class and deleted automatically when no longer needed. (It can also be null)
|
||||
*/
|
||||
StandalonePluginHolder (PropertySet* settingsToUse, bool takeOwnershipOfSettings)
|
||||
: settings (settingsToUse, takeOwnershipOfSettings)
|
||||
{
|
||||
createPlugin();
|
||||
setupAudioDevices();
|
||||
reloadPluginState();
|
||||
startPlaying();
|
||||
}
|
||||
|
||||
~StandalonePluginHolder()
|
||||
{
|
||||
deletePlugin();
|
||||
shutDownAudioDevices();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void createPlugin()
|
||||
{
|
||||
AudioProcessor::setTypeOfNextNewPlugin (AudioProcessor::wrapperType_Standalone);
|
||||
processor = createPluginFilter();
|
||||
jassert (processor != nullptr); // Your createPluginFilter() function must return a valid object!
|
||||
AudioProcessor::setTypeOfNextNewPlugin (AudioProcessor::wrapperType_Undefined);
|
||||
|
||||
processor->setPlayConfigDetails (JucePlugin_MaxNumInputChannels,
|
||||
JucePlugin_MaxNumOutputChannels,
|
||||
44100, 512);
|
||||
}
|
||||
|
||||
void deletePlugin()
|
||||
{
|
||||
stopPlaying();
|
||||
processor = nullptr;
|
||||
}
|
||||
|
||||
static String getFilePatterns (const String& fileSuffix)
|
||||
{
|
||||
if (fileSuffix.isEmpty())
|
||||
return String();
|
||||
|
||||
return (fileSuffix.startsWithChar ('.') ? "*" : "*.") + fileSuffix;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
File getLastFile() const
|
||||
{
|
||||
File f;
|
||||
|
||||
if (settings != nullptr)
|
||||
f = File (settings->getValue ("lastStateFile"));
|
||||
|
||||
if (f == File::nonexistent)
|
||||
f = File::getSpecialLocation (File::userDocumentsDirectory);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
void setLastFile (const FileChooser& fc)
|
||||
{
|
||||
if (settings != nullptr)
|
||||
settings->setValue ("lastStateFile", fc.getResult().getFullPathName());
|
||||
}
|
||||
|
||||
/** Pops up a dialog letting the user save the processor's state to a file. */
|
||||
void askUserToSaveState (const String& fileSuffix = String())
|
||||
{
|
||||
FileChooser fc (TRANS("Save current state"), getLastFile(), getFilePatterns (fileSuffix));
|
||||
|
||||
if (fc.browseForFileToSave (true))
|
||||
{
|
||||
setLastFile (fc);
|
||||
|
||||
MemoryBlock data;
|
||||
processor->getStateInformation (data);
|
||||
|
||||
if (! fc.getResult().replaceWithData (data.getData(), data.getSize()))
|
||||
AlertWindow::showMessageBox (AlertWindow::WarningIcon,
|
||||
TRANS("Error whilst saving"),
|
||||
TRANS("Couldn't write to the specified file!"));
|
||||
}
|
||||
}
|
||||
|
||||
/** Pops up a dialog letting the user re-load the processor's state from a file. */
|
||||
void askUserToLoadState (const String& fileSuffix = String())
|
||||
{
|
||||
FileChooser fc (TRANS("Load a saved state"), getLastFile(), getFilePatterns (fileSuffix));
|
||||
|
||||
if (fc.browseForFileToOpen())
|
||||
{
|
||||
setLastFile (fc);
|
||||
|
||||
MemoryBlock data;
|
||||
|
||||
if (fc.getResult().loadFileAsData (data))
|
||||
processor->setStateInformation (data.getData(), (int) data.getSize());
|
||||
else
|
||||
AlertWindow::showMessageBox (AlertWindow::WarningIcon,
|
||||
TRANS("Error whilst loading"),
|
||||
TRANS("Couldn't read from the specified file!"));
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void startPlaying()
|
||||
{
|
||||
player.setProcessor (processor);
|
||||
}
|
||||
|
||||
void stopPlaying()
|
||||
{
|
||||
player.setProcessor (nullptr);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Shows an audio properties dialog box modally. */
|
||||
void showAudioSettingsDialog()
|
||||
{
|
||||
DialogWindow::LaunchOptions o;
|
||||
o.content.setOwned (new AudioDeviceSelectorComponent (deviceManager,
|
||||
processor->getNumInputChannels(),
|
||||
processor->getNumInputChannels(),
|
||||
processor->getNumOutputChannels(),
|
||||
processor->getNumOutputChannels(),
|
||||
true, false,
|
||||
true, false));
|
||||
o.content->setSize (500, 450);
|
||||
|
||||
o.dialogTitle = TRANS("Audio Settings");
|
||||
o.dialogBackgroundColour = Colour (0xfff0f0f0);
|
||||
o.escapeKeyTriggersCloseButton = true;
|
||||
o.useNativeTitleBar = true;
|
||||
o.resizable = false;
|
||||
|
||||
o.launchAsync();
|
||||
}
|
||||
|
||||
void saveAudioDeviceState()
|
||||
{
|
||||
if (settings != nullptr)
|
||||
{
|
||||
ScopedPointer<XmlElement> xml (deviceManager.createStateXml());
|
||||
settings->setValue ("audioSetup", xml);
|
||||
}
|
||||
}
|
||||
|
||||
void reloadAudioDeviceState()
|
||||
{
|
||||
ScopedPointer<XmlElement> savedState;
|
||||
|
||||
if (settings != nullptr)
|
||||
savedState = settings->getXmlValue ("audioSetup");
|
||||
|
||||
deviceManager.initialise (processor->getNumInputChannels(),
|
||||
processor->getNumOutputChannels(),
|
||||
savedState,
|
||||
true);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void savePluginState()
|
||||
{
|
||||
if (settings != nullptr && processor != nullptr)
|
||||
{
|
||||
MemoryBlock data;
|
||||
processor->getStateInformation (data);
|
||||
|
||||
settings->setValue ("filterState", data.toBase64Encoding());
|
||||
}
|
||||
}
|
||||
|
||||
void reloadPluginState()
|
||||
{
|
||||
if (settings != nullptr)
|
||||
{
|
||||
MemoryBlock data;
|
||||
|
||||
if (data.fromBase64Encoding (settings->getValue ("filterState")) && data.getSize() > 0)
|
||||
processor->setStateInformation (data.getData(), (int) data.getSize());
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
OptionalScopedPointer<PropertySet> settings;
|
||||
ScopedPointer<AudioProcessor> processor;
|
||||
AudioDeviceManager deviceManager;
|
||||
AudioProcessorPlayer player;
|
||||
|
||||
private:
|
||||
void setupAudioDevices()
|
||||
{
|
||||
deviceManager.addAudioCallback (&player);
|
||||
deviceManager.addMidiInputCallback (String::empty, &player);
|
||||
|
||||
reloadAudioDeviceState();
|
||||
}
|
||||
|
||||
void shutDownAudioDevices()
|
||||
{
|
||||
saveAudioDeviceState();
|
||||
|
||||
deviceManager.removeMidiInputCallback (String::empty, &player);
|
||||
deviceManager.removeAudioCallback (&player);
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StandalonePluginHolder)
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A class that can be used to run a simple standalone application containing your filter.
|
||||
|
||||
Just create one of these objects in your JUCEApplicationBase::initialise() method, and
|
||||
let it do its work. It will create your filter object using the same createPluginFilter() function
|
||||
that the other plugin wrappers use.
|
||||
*/
|
||||
class StandaloneFilterWindow : public DocumentWindow,
|
||||
public ButtonListener // (can't use Button::Listener due to VC2005 bug)
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a window with a given title and colour.
|
||||
The settings object can be a PropertySet that the class should use to
|
||||
store its settings (it can also be null). If takeOwnershipOfSettings is
|
||||
true, then the settings object will be owned and deleted by this object.
|
||||
*/
|
||||
StandaloneFilterWindow (const String& title,
|
||||
Colour backgroundColour,
|
||||
PropertySet* settingsToUse,
|
||||
bool takeOwnershipOfSettings)
|
||||
: DocumentWindow (title, backgroundColour, DocumentWindow::minimiseButton | DocumentWindow::closeButton),
|
||||
optionsButton ("options")
|
||||
{
|
||||
setTitleBarButtonsRequired (DocumentWindow::minimiseButton | DocumentWindow::closeButton, false);
|
||||
|
||||
Component::addAndMakeVisible (optionsButton);
|
||||
optionsButton.addListener (this);
|
||||
optionsButton.setTriggeredOnMouseDown (true);
|
||||
|
||||
pluginHolder = new StandalonePluginHolder (settingsToUse, takeOwnershipOfSettings);
|
||||
|
||||
createEditorComp();
|
||||
|
||||
if (PropertySet* props = pluginHolder->settings)
|
||||
{
|
||||
const int x = props->getIntValue ("windowX", -100);
|
||||
const int y = props->getIntValue ("windowY", -100);
|
||||
|
||||
if (x != -100 && y != -100)
|
||||
setBoundsConstrained (juce::Rectangle<int> (x, y, getWidth(), getHeight()));
|
||||
else
|
||||
centreWithSize (getWidth(), getHeight());
|
||||
}
|
||||
else
|
||||
{
|
||||
centreWithSize (getWidth(), getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
~StandaloneFilterWindow()
|
||||
{
|
||||
if (PropertySet* props = pluginHolder->settings)
|
||||
{
|
||||
props->setValue ("windowX", getX());
|
||||
props->setValue ("windowY", getY());
|
||||
}
|
||||
|
||||
pluginHolder->stopPlaying();
|
||||
deleteEditorComp();
|
||||
pluginHolder = nullptr;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
AudioProcessor* getAudioProcessor() const noexcept { return pluginHolder->processor; }
|
||||
AudioDeviceManager& getDeviceManager() const noexcept { return pluginHolder->deviceManager; }
|
||||
|
||||
void createEditorComp()
|
||||
{
|
||||
setContentOwned (getAudioProcessor()->createEditorIfNeeded(), true);
|
||||
}
|
||||
|
||||
void deleteEditorComp()
|
||||
{
|
||||
if (AudioProcessorEditor* ed = dynamic_cast<AudioProcessorEditor*> (getContentComponent()))
|
||||
{
|
||||
pluginHolder->processor->editorBeingDeleted (ed);
|
||||
clearContentComponent();
|
||||
}
|
||||
}
|
||||
|
||||
/** Deletes and re-creates the plugin, resetting it to its default state. */
|
||||
void resetToDefaultState()
|
||||
{
|
||||
pluginHolder->stopPlaying();
|
||||
deleteEditorComp();
|
||||
pluginHolder->deletePlugin();
|
||||
|
||||
if (PropertySet* props = pluginHolder->settings)
|
||||
props->removeValue ("filterState");
|
||||
|
||||
pluginHolder->createPlugin();
|
||||
createEditorComp();
|
||||
pluginHolder->startPlaying();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void closeButtonPressed() override
|
||||
{
|
||||
JUCEApplicationBase::quit();
|
||||
}
|
||||
|
||||
void buttonClicked (Button*) override
|
||||
{
|
||||
PopupMenu m;
|
||||
m.addItem (1, TRANS("Audio Settings..."));
|
||||
m.addSeparator();
|
||||
m.addItem (2, TRANS("Save current state..."));
|
||||
m.addItem (3, TRANS("Load a saved state..."));
|
||||
m.addSeparator();
|
||||
m.addItem (4, TRANS("Reset to default state"));
|
||||
|
||||
switch (m.showAt (&optionsButton))
|
||||
{
|
||||
case 1: pluginHolder->showAudioSettingsDialog(); break;
|
||||
case 2: pluginHolder->askUserToSaveState(); break;
|
||||
case 3: pluginHolder->askUserToLoadState(); break;
|
||||
case 4: resetToDefaultState(); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
DocumentWindow::resized();
|
||||
optionsButton.setBounds (8, 6, 60, getTitleBarHeight() - 8);
|
||||
}
|
||||
|
||||
ScopedPointer<StandalonePluginHolder> pluginHolder;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
TextButton optionsButton;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StandaloneFilterWindow)
|
||||
};
|
||||
|
||||
|
||||
#endif // JUCE_STANDALONEFILTERWINDOW_H_INCLUDED
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// Your project must contain an AppConfig.h file with your project-specific settings in it,
|
||||
// and your header search path must make it accessible to the module's files.
|
||||
#include "AppConfig.h"
|
||||
|
||||
#include "../utility/juce_CheckSettingMacros.h"
|
||||
|
||||
#if JucePlugin_Build_VST || JucePlugin_Build_VST3
|
||||
|
||||
#define JUCE_MAC_WINDOW_VISIBITY_BODGE 1
|
||||
|
||||
#include "../utility/juce_IncludeSystemHeaders.h"
|
||||
#include "../utility/juce_IncludeModuleHeaders.h"
|
||||
#include "../utility/juce_FakeMouseMoveGenerator.h"
|
||||
#include "../utility/juce_CarbonVisibility.h"
|
||||
|
||||
//==============================================================================
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#if ! JUCE_64BIT
|
||||
void updateEditorCompBounds (Component*);
|
||||
void updateEditorCompBounds (Component* comp)
|
||||
{
|
||||
HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int)
|
||||
comp->getProperties() ["dummyViewRef"].toString().getHexValue64();
|
||||
|
||||
HIRect r;
|
||||
HIViewGetFrame (dummyView, &r);
|
||||
HIViewRef root;
|
||||
HIViewFindByID (HIViewGetRoot (HIViewGetWindow (dummyView)), kHIViewWindowContentID, &root);
|
||||
HIViewConvertRect (&r, HIViewGetSuperview (dummyView), root);
|
||||
|
||||
Rect windowPos;
|
||||
GetWindowBounds (HIViewGetWindow (dummyView), kWindowContentRgn, &windowPos);
|
||||
|
||||
comp->setTopLeftPosition ((int) (windowPos.left + r.origin.x),
|
||||
(int) (windowPos.top + r.origin.y));
|
||||
}
|
||||
|
||||
static pascal OSStatus viewBoundsChangedEvent (EventHandlerCallRef, EventRef, void* user)
|
||||
{
|
||||
updateEditorCompBounds ((Component*) user);
|
||||
return noErr;
|
||||
}
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
void initialiseMac();
|
||||
void initialiseMac()
|
||||
{
|
||||
#if ! JUCE_64BIT
|
||||
NSApplicationLoad();
|
||||
#endif
|
||||
}
|
||||
|
||||
void* attachComponentToWindowRef (Component* comp, void* parentWindowOrView, bool isNSView);
|
||||
void* attachComponentToWindowRef (Component* comp, void* parentWindowOrView, bool isNSView)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
#if ! JUCE_64BIT
|
||||
if (! isNSView)
|
||||
{
|
||||
NSWindow* hostWindow = [[NSWindow alloc] initWithWindowRef: parentWindowOrView];
|
||||
[hostWindow retain];
|
||||
[hostWindow setCanHide: YES];
|
||||
[hostWindow setReleasedWhenClosed: YES];
|
||||
|
||||
HIViewRef parentView = 0;
|
||||
|
||||
WindowAttributes attributes;
|
||||
GetWindowAttributes ((WindowRef) parentWindowOrView, &attributes);
|
||||
if ((attributes & kWindowCompositingAttribute) != 0)
|
||||
{
|
||||
HIViewRef root = HIViewGetRoot ((WindowRef) parentWindowOrView);
|
||||
HIViewFindByID (root, kHIViewWindowContentID, &parentView);
|
||||
|
||||
if (parentView == 0)
|
||||
parentView = root;
|
||||
}
|
||||
else
|
||||
{
|
||||
GetRootControl ((WindowRef) parentWindowOrView, (ControlRef*) &parentView);
|
||||
|
||||
if (parentView == 0)
|
||||
CreateRootControl ((WindowRef) parentWindowOrView, (ControlRef*) &parentView);
|
||||
}
|
||||
|
||||
// It seems that the only way to successfully position our overlaid window is by putting a dummy
|
||||
// HIView into the host's carbon window, and then catching events to see when it gets repositioned
|
||||
HIViewRef dummyView = 0;
|
||||
HIImageViewCreate (0, &dummyView);
|
||||
HIRect r = { {0, 0}, { (float) comp->getWidth(), (float) comp->getHeight()} };
|
||||
HIViewSetFrame (dummyView, &r);
|
||||
HIViewAddSubview (parentView, dummyView);
|
||||
comp->getProperties().set ("dummyViewRef", String::toHexString ((pointer_sized_int) (void*) dummyView));
|
||||
|
||||
EventHandlerRef ref;
|
||||
const EventTypeSpec kControlBoundsChangedEvent = { kEventClassControl, kEventControlBoundsChanged };
|
||||
InstallEventHandler (GetControlEventTarget (dummyView), NewEventHandlerUPP (viewBoundsChangedEvent), 1, &kControlBoundsChangedEvent, (void*) comp, &ref);
|
||||
comp->getProperties().set ("boundsEventRef", String::toHexString ((pointer_sized_int) (void*) ref));
|
||||
|
||||
updateEditorCompBounds (comp);
|
||||
|
||||
#if ! JucePlugin_EditorRequiresKeyboardFocus
|
||||
comp->addToDesktop (ComponentPeer::windowIsTemporary | ComponentPeer::windowIgnoresKeyPresses);
|
||||
#else
|
||||
comp->addToDesktop (ComponentPeer::windowIsTemporary);
|
||||
#endif
|
||||
|
||||
comp->setVisible (true);
|
||||
comp->toFront (false);
|
||||
|
||||
NSView* pluginView = (NSView*) comp->getWindowHandle();
|
||||
NSWindow* pluginWindow = [pluginView window];
|
||||
[pluginWindow setExcludedFromWindowsMenu: YES];
|
||||
[pluginWindow setCanHide: YES];
|
||||
|
||||
[hostWindow addChildWindow: pluginWindow
|
||||
ordered: NSWindowAbove];
|
||||
[hostWindow orderFront: nil];
|
||||
[pluginWindow orderFront: nil];
|
||||
|
||||
attachWindowHidingHooks (comp, (WindowRef) parentWindowOrView, hostWindow);
|
||||
|
||||
return hostWindow;
|
||||
}
|
||||
#endif
|
||||
|
||||
(void) isNSView;
|
||||
NSView* parentView = [(NSView*) parentWindowOrView retain];
|
||||
|
||||
#if JucePlugin_EditorRequiresKeyboardFocus
|
||||
comp->addToDesktop (0, parentView);
|
||||
#else
|
||||
comp->addToDesktop (ComponentPeer::windowIgnoresKeyPresses, parentView);
|
||||
#endif
|
||||
|
||||
// (this workaround is because Wavelab provides a zero-size parent view..)
|
||||
if ([parentView frame].size.height == 0)
|
||||
[((NSView*) comp->getWindowHandle()) setFrameOrigin: NSZeroPoint];
|
||||
|
||||
comp->setVisible (true);
|
||||
comp->toFront (false);
|
||||
|
||||
[[parentView window] setAcceptsMouseMovedEvents: YES];
|
||||
return parentView;
|
||||
}
|
||||
}
|
||||
|
||||
void detachComponentFromWindowRef (Component* comp, void* window, bool isNSView);
|
||||
void detachComponentFromWindowRef (Component* comp, void* window, bool isNSView)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
#if ! JUCE_64BIT
|
||||
if (! isNSView)
|
||||
{
|
||||
EventHandlerRef ref = (EventHandlerRef) (void*) (pointer_sized_int)
|
||||
comp->getProperties() ["boundsEventRef"].toString().getHexValue64();
|
||||
RemoveEventHandler (ref);
|
||||
|
||||
removeWindowHidingHooks (comp);
|
||||
|
||||
HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int)
|
||||
comp->getProperties() ["dummyViewRef"].toString().getHexValue64();
|
||||
|
||||
if (HIViewIsValid (dummyView))
|
||||
CFRelease (dummyView);
|
||||
|
||||
NSWindow* hostWindow = (NSWindow*) window;
|
||||
NSView* pluginView = (NSView*) comp->getWindowHandle();
|
||||
NSWindow* pluginWindow = [pluginView window];
|
||||
|
||||
[pluginView retain];
|
||||
[hostWindow removeChildWindow: pluginWindow];
|
||||
[pluginWindow close];
|
||||
comp->removeFromDesktop();
|
||||
[pluginView release];
|
||||
|
||||
[hostWindow release];
|
||||
|
||||
static bool needToRunMessageLoop = ! getHostType().isReaper();
|
||||
|
||||
// The event loop needs to be run between closing the window and deleting the plugin,
|
||||
// presumably to let the cocoa objects get tidied up. Leaving out this line causes crashes
|
||||
// in Live when you delete the plugin with its window open.
|
||||
// (Doing it this way rather than using a single longer timout means that we can guarantee
|
||||
// how many messages will be dispatched, which seems to be vital in Reaper)
|
||||
if (needToRunMessageLoop)
|
||||
for (int i = 20; --i >= 0;)
|
||||
MessageManager::getInstance()->runDispatchLoopUntil (1);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
(void) isNSView;
|
||||
comp->removeFromDesktop();
|
||||
[(id) window release];
|
||||
}
|
||||
}
|
||||
|
||||
void setNativeHostWindowSize (void* window, Component* component, int newWidth, int newHeight, bool isNSView);
|
||||
void setNativeHostWindowSize (void* window, Component* component, int newWidth, int newHeight, bool isNSView)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
#if ! JUCE_64BIT
|
||||
if (! isNSView)
|
||||
{
|
||||
if (HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int)
|
||||
component->getProperties() ["dummyViewRef"].toString().getHexValue64())
|
||||
{
|
||||
HIRect frameRect;
|
||||
HIViewGetFrame (dummyView, &frameRect);
|
||||
frameRect.size.width = newWidth;
|
||||
frameRect.size.height = newHeight;
|
||||
HIViewSetFrame (dummyView, &frameRect);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
(void) isNSView;
|
||||
|
||||
if (NSView* hostView = (NSView*) window)
|
||||
{
|
||||
const int dx = newWidth - component->getWidth();
|
||||
const int dy = newHeight - component->getHeight();
|
||||
|
||||
NSRect r = [hostView frame];
|
||||
r.size.width += dx;
|
||||
r.size.height += dy;
|
||||
r.origin.y -= dy;
|
||||
[hostView setFrame: r];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkWindowVisibility (void* window, Component* comp, bool isNSView);
|
||||
void checkWindowVisibility (void* window, Component* comp, bool isNSView)
|
||||
{
|
||||
(void) window; (void) comp; (void) isNSView;
|
||||
|
||||
#if ! JUCE_64BIT
|
||||
if (! isNSView)
|
||||
comp->setVisible ([((NSWindow*) window) isVisible]);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool forwardCurrentKeyEventToHost (Component* comp, bool isNSView);
|
||||
bool forwardCurrentKeyEventToHost (Component* comp, bool isNSView)
|
||||
{
|
||||
#if ! JUCE_64BIT
|
||||
if (! isNSView)
|
||||
{
|
||||
NSWindow* win = [(NSView*) comp->getWindowHandle() window];
|
||||
[[win parentWindow] makeKeyWindow];
|
||||
repostCurrentNSEvent();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
(void) comp; (void) isNSView;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // (juce namespace)
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// Your project must contain an AppConfig.h file with your project-specific settings in it,
|
||||
// and your header search path must make it accessible to the module's files.
|
||||
#include "AppConfig.h"
|
||||
#include "../utility/juce_CheckSettingMacros.h"
|
||||
|
||||
#if JucePlugin_Build_VST3
|
||||
|
||||
#define JUCE_MAC_WINDOW_VISIBITY_BODGE 1
|
||||
|
||||
#include "../utility/juce_IncludeSystemHeaders.h"
|
||||
#include "../utility/juce_IncludeModuleHeaders.h"
|
||||
#include "../utility/juce_FakeMouseMoveGenerator.h"
|
||||
#include "../utility/juce_CarbonVisibility.h"
|
||||
|
||||
#undef Component
|
||||
#undef Point
|
||||
|
||||
//==============================================================================
|
||||
namespace juce
|
||||
{
|
||||
static void initialiseMac()
|
||||
{
|
||||
#if ! JUCE_64BIT
|
||||
NSApplicationLoad();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ! JUCE_64BIT
|
||||
static void updateComponentPos (Component* const comp)
|
||||
{
|
||||
DBG ("updateComponentPos()");
|
||||
|
||||
HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int)
|
||||
comp->getProperties() ["dummyViewRef"].toString().getHexValue64();
|
||||
|
||||
HIRect r;
|
||||
HIViewGetFrame (dummyView, &r);
|
||||
HIViewRef root;
|
||||
HIViewFindByID (HIViewGetRoot (HIViewGetWindow (dummyView)), kHIViewWindowContentID, &root);
|
||||
HIViewConvertRect (&r, HIViewGetSuperview (dummyView), root);
|
||||
|
||||
Rect windowPos;
|
||||
GetWindowBounds (HIViewGetWindow (dummyView), kWindowContentRgn, &windowPos);
|
||||
|
||||
comp->setTopLeftPosition ((int) (windowPos.left + r.origin.x),
|
||||
(int) (windowPos.top + r.origin.y));
|
||||
}
|
||||
|
||||
static pascal OSStatus viewBoundsChangedEvent (EventHandlerCallRef, EventRef, void* user)
|
||||
{
|
||||
updateComponentPos ((Component*) user);
|
||||
return noErr;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void* attachComponentToWindowRef (Component* comp, void* windowRef, bool isHIView)
|
||||
{
|
||||
DBG ("attachComponentToWindowRef()");
|
||||
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
#if JUCE_64BIT
|
||||
(void) isHIView;
|
||||
NSView* parentView = (NSView*) windowRef;
|
||||
|
||||
#if JucePlugin_EditorRequiresKeyboardFocus
|
||||
comp->addToDesktop (0, parentView);
|
||||
#else
|
||||
comp->addToDesktop (ComponentPeer::windowIgnoresKeyPresses, parentView);
|
||||
#endif
|
||||
|
||||
// (this workaround is because Wavelab provides a zero-size parent view..)
|
||||
if ([parentView frame].size.height == 0)
|
||||
[((NSView*) comp->getWindowHandle()) setFrameOrigin: NSZeroPoint];
|
||||
|
||||
comp->setVisible (true);
|
||||
comp->toFront (false);
|
||||
|
||||
[[parentView window] setAcceptsMouseMovedEvents: YES];
|
||||
return parentView;
|
||||
|
||||
#else
|
||||
//treat NSView like 64bit
|
||||
if (! isHIView)
|
||||
{
|
||||
NSView* parentView = (NSView*) windowRef;
|
||||
|
||||
#if JucePlugin_EditorRequiresKeyboardFocus
|
||||
comp->addToDesktop (0, parentView);
|
||||
#else
|
||||
comp->addToDesktop (ComponentPeer::windowIgnoresKeyPresses, parentView);
|
||||
#endif
|
||||
|
||||
// (this workaround is because Wavelab provides a zero-size parent view..)
|
||||
if ([parentView frame].size.height == 0)
|
||||
[((NSView*) comp->getWindowHandle()) setFrameOrigin: NSZeroPoint];
|
||||
|
||||
comp->setVisible (true);
|
||||
comp->toFront (false);
|
||||
|
||||
[[parentView window] setAcceptsMouseMovedEvents: YES];
|
||||
return parentView;
|
||||
}
|
||||
|
||||
NSWindow* hostWindow = [[NSWindow alloc] initWithWindowRef: windowRef];
|
||||
[hostWindow retain];
|
||||
[hostWindow setCanHide: YES];
|
||||
[hostWindow setReleasedWhenClosed: YES];
|
||||
|
||||
HIViewRef parentView = nullptr;
|
||||
|
||||
WindowAttributes attributes;
|
||||
GetWindowAttributes ((WindowRef) windowRef, &attributes);
|
||||
|
||||
if ((attributes & kWindowCompositingAttribute) != 0)
|
||||
{
|
||||
HIViewRef root = HIViewGetRoot ((WindowRef) windowRef);
|
||||
HIViewFindByID (root, kHIViewWindowContentID, &parentView);
|
||||
|
||||
if (parentView == nullptr)
|
||||
parentView = root;
|
||||
}
|
||||
else
|
||||
{
|
||||
GetRootControl ((WindowRef) windowRef, (ControlRef*) &parentView);
|
||||
|
||||
if (parentView == nullptr)
|
||||
CreateRootControl ((WindowRef) windowRef, (ControlRef*) &parentView);
|
||||
}
|
||||
|
||||
// It seems that the only way to successfully position our overlaid window is by putting a dummy
|
||||
// HIView into the host's carbon window, and then catching events to see when it gets repositioned
|
||||
HIViewRef dummyView = 0;
|
||||
HIImageViewCreate (0, &dummyView);
|
||||
HIRect r = { {0, 0}, { (float) comp->getWidth(), (float) comp->getHeight()} };
|
||||
HIViewSetFrame (dummyView, &r);
|
||||
HIViewAddSubview (parentView, dummyView);
|
||||
comp->getProperties().set ("dummyViewRef", String::toHexString ((pointer_sized_int) (void*) dummyView));
|
||||
|
||||
EventHandlerRef ref;
|
||||
const EventTypeSpec kControlBoundsChangedEvent = { kEventClassControl, kEventControlBoundsChanged };
|
||||
InstallEventHandler (GetControlEventTarget (dummyView), NewEventHandlerUPP (viewBoundsChangedEvent), 1, &kControlBoundsChangedEvent, (void*) comp, &ref);
|
||||
comp->getProperties().set ("boundsEventRef", String::toHexString ((pointer_sized_int) (void*) ref));
|
||||
|
||||
updateComponentPos (comp);
|
||||
|
||||
#if ! JucePlugin_EditorRequiresKeyboardFocus
|
||||
comp->addToDesktop (ComponentPeer::windowIsTemporary | ComponentPeer::windowIgnoresKeyPresses);
|
||||
#else
|
||||
comp->addToDesktop (ComponentPeer::windowIsTemporary);
|
||||
#endif
|
||||
|
||||
comp->setVisible (true);
|
||||
comp->toFront (false);
|
||||
|
||||
NSView* pluginView = (NSView*) comp->getWindowHandle();
|
||||
NSWindow* pluginWindow = [pluginView window];
|
||||
[pluginWindow setExcludedFromWindowsMenu: YES];
|
||||
[pluginWindow setCanHide: YES];
|
||||
|
||||
[hostWindow addChildWindow: pluginWindow
|
||||
ordered: NSWindowAbove];
|
||||
[hostWindow orderFront: nil];
|
||||
[pluginWindow orderFront: nil];
|
||||
|
||||
attachWindowHidingHooks (comp, (WindowRef) windowRef, hostWindow);
|
||||
|
||||
return hostWindow;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void detachComponentFromWindowRef (Component* comp, void* nsWindow, bool isHIView)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
#if ! JUCE_64BIT
|
||||
if (isHIView)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
EventHandlerRef ref = (EventHandlerRef) (void*) (pointer_sized_int)
|
||||
comp->getProperties() ["boundsEventRef"].toString().getHexValue64();
|
||||
RemoveEventHandler (ref);
|
||||
|
||||
removeWindowHidingHooks (comp);
|
||||
|
||||
HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int)
|
||||
comp->getProperties() ["dummyViewRef"].toString().getHexValue64();
|
||||
|
||||
if (HIViewIsValid (dummyView))
|
||||
CFRelease (dummyView);
|
||||
|
||||
NSWindow* hostWindow = (NSWindow*) nsWindow;
|
||||
NSView* pluginView = (NSView*) comp->getWindowHandle();
|
||||
NSWindow* pluginWindow = [pluginView window];
|
||||
|
||||
[hostWindow removeChildWindow: pluginWindow];
|
||||
comp->removeFromDesktop();
|
||||
|
||||
[hostWindow release];
|
||||
}
|
||||
|
||||
// The event loop needs to be run between closing the window and deleting the plugin,
|
||||
// presumably to let the cocoa objects get tidied up. Leaving out this line causes crashes
|
||||
// in Live and Reaper when you delete the plugin with its window open.
|
||||
// (Doing it this way rather than using a single longer timout means that we can guarantee
|
||||
// how many messages will be dispatched, which seems to be vital in Reaper)
|
||||
for (int i = 20; --i >= 0;)
|
||||
MessageManager::getInstance()->runDispatchLoopUntil (1);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
(void) nsWindow; (void) isHIView;
|
||||
comp->removeFromDesktop();
|
||||
}
|
||||
}
|
||||
|
||||
static void setNativeHostWindowSize (void* nsWindow, Component* component, int newWidth, int newHeight, bool isHIView)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
#if ! JUCE_64BIT
|
||||
if (isHIView)
|
||||
{
|
||||
if (HIViewRef dummyView = (HIViewRef) (void*) (pointer_sized_int)
|
||||
component->getProperties() ["dummyViewRef"].toString().getHexValue64())
|
||||
{
|
||||
HIRect frameRect;
|
||||
HIViewGetFrame (dummyView, &frameRect);
|
||||
frameRect.size.width = newWidth;
|
||||
frameRect.size.height = newHeight;
|
||||
HIViewSetFrame (dummyView, &frameRect);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
(void) nsWindow; (void) isHIView;
|
||||
component->setSize (newWidth, newHeight);
|
||||
}
|
||||
}
|
||||
} // (juce namespace)
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_AUDIO_PLUGIN_CLIENT_H_INCLUDED
|
||||
#define JUCE_AUDIO_PLUGIN_CLIENT_H_INCLUDED
|
||||
|
||||
#include "../juce_gui_basics/juce_gui_basics.h"
|
||||
#include "../juce_audio_basics/juce_audio_basics.h"
|
||||
#include "../juce_audio_processors/juce_audio_processors.h"
|
||||
#include "utility/juce_CheckSettingMacros.h"
|
||||
|
||||
namespace juce
|
||||
{
|
||||
#include "utility/juce_PluginHostType.h"
|
||||
}
|
||||
|
||||
#endif // JUCE_AUDIO_PLUGIN_CLIENT_H_INCLUDED
|
||||
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"id": "juce_audio_plugin_client",
|
||||
"name": "JUCE audio plugin wrapper classes",
|
||||
"version": "3.1.1",
|
||||
"description": "Classes for building VST, VST3, RTAS, AAX and AU plugins.",
|
||||
"website": "http://www.juce.com/juce",
|
||||
"license": "GPL/Commercial",
|
||||
|
||||
"dependencies": [ { "id": "juce_gui_basics", "version": "matching" },
|
||||
{ "id": "juce_audio_basics", "version": "matching" },
|
||||
{ "id": "juce_audio_processors", "version": "matching" } ],
|
||||
|
||||
"include": "juce_audio_plugin_client.h",
|
||||
|
||||
"compile": [ { "file": "VST/juce_VST_Wrapper.cpp" },
|
||||
{ "file": "VST/juce_VST_Wrapper.mm", "target": "xcode" },
|
||||
{ "file": "VST3/juce_VST3_Wrapper.cpp" },
|
||||
{ "file": "VST3/juce_VST3_Wrapper.mm", "target": "xcode" },
|
||||
{ "file": "RTAS/juce_RTAS_DigiCode1.cpp", "warnings": "disabled", "stdcall": "1", "target": "xcode, msvc" },
|
||||
{ "file": "RTAS/juce_RTAS_DigiCode2.cpp", "warnings": "disabled", "stdcall": "1", "target": "xcode, msvc" },
|
||||
{ "file": "RTAS/juce_RTAS_DigiCode3.cpp", "warnings": "disabled", "stdcall": "1", "target": "xcode, msvc" },
|
||||
{ "file": "RTAS/juce_RTAS_MacResources.r", "target": "xcode", "RTASOnly": "1" },
|
||||
{ "file": "RTAS/juce_RTAS_MacUtilities.mm", "target": "xcode" },
|
||||
{ "file": "RTAS/juce_RTAS_WinResources.rsr", "target": "msvc" },
|
||||
{ "file": "RTAS/juce_RTAS_WinUtilities.cpp", "target": "msvc", "warnings": "disabled", "stdcall": "1" },
|
||||
{ "file": "RTAS/juce_RTAS_Wrapper.cpp", "warnings": "disabled", "stdcall": "1", "target": "xcode, msvc" },
|
||||
{ "file": "AU/juce_AU_Resources.r", "target": "xcode", "AudioUnitOnly": "1" },
|
||||
{ "file": "AU/juce_AU_Wrapper.mm", "target": "xcode" },
|
||||
{ "file": "AAX/juce_AAX_Wrapper.cpp", "target": "xcode, msvc" },
|
||||
{ "file": "AAX/juce_AAX_Wrapper.mm", "target": "xcode" },
|
||||
{ "file": "utility/juce_PluginUtilities.cpp" }
|
||||
],
|
||||
|
||||
"browse": [ "AU/*.cpp",
|
||||
"AU/*.mm",
|
||||
"AU/*.h",
|
||||
"RTAS/*.cpp",
|
||||
"RTAS/*.mm",
|
||||
"RTAS/*.h",
|
||||
"VST/*",
|
||||
"VST3/*",
|
||||
"AAX/*",
|
||||
"utility/*"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_CARBONVISIBILITY_H_INCLUDED
|
||||
#define JUCE_CARBONVISIBILITY_H_INCLUDED
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_SUPPORT_CARBON && JUCE_MAC_WINDOW_VISIBITY_BODGE
|
||||
|
||||
/* When you wrap a WindowRef as an NSWindow, it seems to bugger up the HideWindow
|
||||
function, so when the host tries (and fails) to hide the window, this stuff catches
|
||||
the event and forces it to update.
|
||||
*/
|
||||
static pascal OSStatus windowVisibilityBodge (EventHandlerCallRef, EventRef e, void* user)
|
||||
{
|
||||
NSWindow* hostWindow = (NSWindow*) user;
|
||||
|
||||
switch (GetEventKind (e))
|
||||
{
|
||||
case kEventWindowInit: [hostWindow display]; break;
|
||||
case kEventWindowShown: [hostWindow orderFront: nil]; break;
|
||||
case kEventWindowHidden: [hostWindow orderOut: nil]; break;
|
||||
}
|
||||
|
||||
return eventNotHandledErr;
|
||||
}
|
||||
|
||||
static void attachWindowHidingHooks (Component* comp, void* hostWindowRef, NSWindow* nsWindow)
|
||||
{
|
||||
const EventTypeSpec eventsToCatch[] =
|
||||
{
|
||||
{ kEventClassWindow, kEventWindowInit },
|
||||
{ kEventClassWindow, kEventWindowShown },
|
||||
{ kEventClassWindow, kEventWindowHidden }
|
||||
};
|
||||
|
||||
EventHandlerRef ref;
|
||||
InstallWindowEventHandler ((WindowRef) hostWindowRef,
|
||||
NewEventHandlerUPP (windowVisibilityBodge),
|
||||
GetEventTypeCount (eventsToCatch), eventsToCatch,
|
||||
(void*) nsWindow, &ref);
|
||||
|
||||
comp->getProperties().set ("carbonEventRef", String::toHexString ((pointer_sized_int) (void*) ref));
|
||||
}
|
||||
|
||||
static void removeWindowHidingHooks (Component* comp)
|
||||
{
|
||||
if (comp != nullptr)
|
||||
RemoveEventHandler ((EventHandlerRef) (void*) (pointer_sized_int)
|
||||
comp->getProperties() ["carbonEventRef"].toString().getHexValue64());
|
||||
}
|
||||
|
||||
#elif JUCE_MAC
|
||||
static void attachWindowHidingHooks (void*, void*, void*) {}
|
||||
static void removeWindowHidingHooks (void*) {}
|
||||
#endif
|
||||
|
||||
#endif // JUCE_CARBONVISIBILITY_H_INCLUDED
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// The following checks should cause a compile error if you've forgotten to
|
||||
// define all your plugin settings properly..
|
||||
|
||||
#if ! (JucePlugin_Build_VST || JucePlugin_Build_VST3 \
|
||||
|| JucePlugin_Build_AU || JucePlugin_Build_RTAS || JucePlugin_Build_AAX \
|
||||
|| JucePlugin_Build_Standalone || JucePlugin_Build_LV2)
|
||||
#error "You need to enable at least one plugin format!"
|
||||
#endif
|
||||
|
||||
#ifndef JucePlugin_IsSynth
|
||||
#error "You need to define the JucePlugin_IsSynth value!"
|
||||
#endif
|
||||
|
||||
#ifndef JucePlugin_ManufacturerCode
|
||||
#error "You need to define the JucePlugin_ManufacturerCode value!"
|
||||
#endif
|
||||
|
||||
#ifndef JucePlugin_PluginCode
|
||||
#error "You need to define the JucePlugin_PluginCode value!"
|
||||
#endif
|
||||
|
||||
#ifndef JucePlugin_ProducesMidiOutput
|
||||
#error "You need to define the JucePlugin_ProducesMidiOutput value!"
|
||||
#endif
|
||||
|
||||
#ifndef JucePlugin_WantsMidiInput
|
||||
#error "You need to define the JucePlugin_WantsMidiInput value!"
|
||||
#endif
|
||||
|
||||
#ifndef JucePlugin_MaxNumInputChannels
|
||||
#error "You need to define the JucePlugin_MaxNumInputChannels value!"
|
||||
#endif
|
||||
|
||||
#ifndef JucePlugin_MaxNumOutputChannels
|
||||
#error "You need to define the JucePlugin_MaxNumOutputChannels value!"
|
||||
#endif
|
||||
|
||||
#ifndef JucePlugin_PreferredChannelConfigurations
|
||||
#error "You need to define the JucePlugin_PreferredChannelConfigurations value!"
|
||||
#endif
|
||||
|
||||
#ifdef JucePlugin_Latency
|
||||
#error "JucePlugin_Latency is now deprecated - instead, call the AudioProcessor::setLatencySamples() method if your plugin has a non-zero delay"
|
||||
#endif
|
||||
|
||||
#ifndef JucePlugin_SilenceInProducesSilenceOut
|
||||
#error "You need to define the JucePlugin_SilenceInProducesSilenceOut value!"
|
||||
#endif
|
||||
|
||||
#ifndef JucePlugin_EditorRequiresKeyboardFocus
|
||||
#error "You need to define the JucePlugin_EditorRequiresKeyboardFocus value!"
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
#if _WIN64 || (__LP64__ && (defined (__APPLE_CPP__) || defined (__APPLE_CC__)))
|
||||
#undef JucePlugin_Build_RTAS
|
||||
#define JucePlugin_Build_RTAS 0
|
||||
#endif
|
||||
|
||||
#if ! (defined (_MSC_VER) || defined (__APPLE_CPP__) || defined (__APPLE_CC__))
|
||||
#undef JucePlugin_Build_VST3
|
||||
#define JucePlugin_Build_VST3 0
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
#if JucePlugin_Build_RTAS && _MSC_VER && ! defined (JucePlugin_WinBag_path)
|
||||
#error "You need to define the JucePlugin_WinBag_path value!"
|
||||
#endif
|
||||
|
||||
#if JucePlugin_Build_LV2 && ! defined (JucePlugin_LV2URI)
|
||||
#error "You need to define the JucePlugin_LV2URI value!"
|
||||
#endif
|
||||
|
||||
#if JucePlugin_Build_AAX && ! defined (JucePlugin_AAXIdentifier)
|
||||
#error "You need to define the JucePlugin_AAXIdentifier value!"
|
||||
#endif
|
||||
|
||||
#if defined (__ppc__)
|
||||
#undef JucePlugin_Build_AAX
|
||||
#define JucePlugin_Build_AAX 0
|
||||
#endif
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef JUCE_FAKEMOUSEMOVEGENERATOR_H_INCLUDED
|
||||
#define JUCE_FAKEMOUSEMOVEGENERATOR_H_INCLUDED
|
||||
|
||||
#if JUCE_MAC && JUCE_SUPPORT_CARBON
|
||||
|
||||
//==============================================================================
|
||||
// Helper class to workaround carbon windows not getting mouse-moves..
|
||||
class FakeMouseMoveGenerator : private Timer
|
||||
{
|
||||
public:
|
||||
FakeMouseMoveGenerator()
|
||||
{
|
||||
startTimer (1000 / 30);
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
// workaround for carbon windows not getting mouse-moves..
|
||||
const Point<float> screenPos (Desktop::getInstance().getMainMouseSource().getScreenPosition());
|
||||
|
||||
if (screenPos != lastScreenPos)
|
||||
{
|
||||
lastScreenPos = screenPos;
|
||||
const ModifierKeys mods (ModifierKeys::getCurrentModifiers());
|
||||
|
||||
if (! mods.isAnyMouseButtonDown())
|
||||
if (Component* const comp = Desktop::getInstance().findComponentAt (screenPos.roundToInt()))
|
||||
if (ComponentPeer* const peer = comp->getPeer())
|
||||
if (! peer->isFocused())
|
||||
peer->handleMouseEvent (0, peer->globalToLocal (screenPos), mods, Time::currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Point<float> lastScreenPos;
|
||||
};
|
||||
|
||||
#else
|
||||
struct FakeMouseMoveGenerator {};
|
||||
#endif
|
||||
|
||||
#endif // JUCE_FAKEMOUSEMOVEGENERATOR_H_INCLUDED
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../juce_audio_plugin_client.h"
|
||||
|
||||
using namespace juce;
|
||||
|
||||
namespace juce
|
||||
{
|
||||
#if JUCE_MAC && ! DOXYGEN
|
||||
#define Point juce::Point
|
||||
#define Component juce::Component
|
||||
|
||||
void repostCurrentNSEvent();
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
inline const PluginHostType& getHostType()
|
||||
{
|
||||
static PluginHostType hostType;
|
||||
return hostType;
|
||||
}
|
||||
}
|
||||
|
||||
extern AudioProcessor* JUCE_CALLTYPE createPluginFilterOfType (AudioProcessor::WrapperType);
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JUCE_WINDOWS
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x500
|
||||
#undef STRICT
|
||||
#define STRICT 1
|
||||
#include <windows.h>
|
||||
#include <float.h>
|
||||
#pragma warning (disable : 4312 4355)
|
||||
#ifdef __INTEL_COMPILER
|
||||
#pragma warning (disable : 1899)
|
||||
#endif
|
||||
|
||||
#elif JUCE_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
|
||||
|
||||
#else
|
||||
#if ! (defined (JUCE_SUPPORT_CARBON) || defined (__LP64__))
|
||||
#define JUCE_SUPPORT_CARBON 1
|
||||
#endif
|
||||
|
||||
#if JUCE_SUPPORT_CARBON
|
||||
#define Point CarbonDummyPointName
|
||||
#define Component CarbonDummyCompName
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include <Carbon/Carbon.h>
|
||||
#undef Point
|
||||
#undef Component
|
||||
#else
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#endif
|
||||
#include <objc/runtime.h>
|
||||
#include <objc/objc.h>
|
||||
#include <objc/message.h>
|
||||
#endif
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
//==============================================================================
|
||||
class PluginHostType
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
PluginHostType() : type (getHostType()) {}
|
||||
PluginHostType (const PluginHostType& other) noexcept : type (other.type) {}
|
||||
PluginHostType& operator= (const PluginHostType& other) noexcept { type = other.type; return *this; }
|
||||
|
||||
//==============================================================================
|
||||
enum HostType
|
||||
{
|
||||
UnknownHost,
|
||||
AbletonLive6,
|
||||
AbletonLive7,
|
||||
AbletonLive8,
|
||||
AbletonLiveGeneric,
|
||||
AdobeAudition,
|
||||
AdobePremierePro,
|
||||
AppleLogic,
|
||||
Ardour,
|
||||
CakewalkSonar8,
|
||||
CakewalkSonarGeneric,
|
||||
DigidesignProTools,
|
||||
DigitalPerformer,
|
||||
FruityLoops,
|
||||
MagixSamplitude,
|
||||
MergingPyramix,
|
||||
MuseReceptorGeneric,
|
||||
Reaper,
|
||||
SteinbergCubase4,
|
||||
SteinbergCubase5,
|
||||
SteinbergCubase5Bridged,
|
||||
SteinbergCubase6,
|
||||
SteinbergCubase7,
|
||||
SteinbergCubaseGeneric,
|
||||
SteinbergNuendo3,
|
||||
SteinbergNuendo4,
|
||||
SteinbergNuendo5,
|
||||
SteinbergNuendoGeneric,
|
||||
SteinbergWavelab5,
|
||||
SteinbergWavelab6,
|
||||
SteinbergWavelab7,
|
||||
SteinbergWavelab8,
|
||||
SteinbergWavelabGeneric,
|
||||
SteinbergTestHost,
|
||||
StudioOne,
|
||||
Tracktion3,
|
||||
TracktionGeneric,
|
||||
WaveBurner,
|
||||
VBVSTScanner
|
||||
};
|
||||
|
||||
HostType type;
|
||||
|
||||
//==============================================================================
|
||||
bool isAbletonLive() const noexcept { return type == AbletonLive6 || type == AbletonLive7 || type == AbletonLive8 || type == AbletonLiveGeneric; }
|
||||
bool isAdobeAudition() const noexcept { return type == AdobeAudition; }
|
||||
bool isArdour() const noexcept { return type == Ardour; }
|
||||
bool isDigitalPerformer() const noexcept { return type == DigitalPerformer; }
|
||||
bool isCubase() const noexcept { return type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase5Bridged || type == SteinbergCubase6 || type == SteinbergCubase7 || type == SteinbergCubaseGeneric; }
|
||||
bool isCubaseBridged() const noexcept { return type == SteinbergCubase5Bridged; }
|
||||
bool isLogic() const noexcept { return type == AppleLogic; }
|
||||
bool isFruityLoops() const noexcept { return type == FruityLoops; }
|
||||
bool isNuendo() const noexcept { return type == SteinbergNuendo3 || type == SteinbergNuendo4 || type == SteinbergNuendo5 || type == SteinbergNuendoGeneric; }
|
||||
bool isPremiere() const noexcept { return type == AdobePremierePro; }
|
||||
bool isPyramix() const noexcept { return type == MergingPyramix; }
|
||||
bool isReceptor() const noexcept { return type == MuseReceptorGeneric; }
|
||||
bool isReaper() const noexcept { return type == Reaper; }
|
||||
bool isSamplitude() const noexcept { return type == MagixSamplitude; }
|
||||
bool isSonar() const noexcept { return type == CakewalkSonar8 || type == CakewalkSonarGeneric; }
|
||||
bool isSteinbergTestHost() const noexcept{ return type == SteinbergTestHost; }
|
||||
bool isSteinberg() const noexcept { return isCubase() || isNuendo() || isWavelab() || isSteinbergTestHost(); }
|
||||
bool isStudioOne() const noexcept { return type == StudioOne; }
|
||||
bool isTracktion() const noexcept { return type == Tracktion3 || type == TracktionGeneric; }
|
||||
bool isVBVSTScanner() const noexcept { return type == VBVSTScanner; }
|
||||
bool isWaveBurner() const noexcept { return type == WaveBurner; }
|
||||
bool isWavelab() const noexcept { return isWavelabLegacy() || type == SteinbergWavelab7 || type == SteinbergWavelab8 || type == SteinbergWavelabGeneric; }
|
||||
bool isWavelabLegacy() const noexcept { return type == SteinbergWavelab5 || type == SteinbergWavelab6; }
|
||||
|
||||
//==============================================================================
|
||||
const char* getHostDescription() const noexcept
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case AbletonLive6: return "Ableton Live 6";
|
||||
case AbletonLive7: return "Ableton Live 7";
|
||||
case AbletonLive8: return "Ableton Live 8";
|
||||
case AbletonLiveGeneric: return "Ableton Live";
|
||||
case AdobeAudition: return "Adobe Audition";
|
||||
case AdobePremierePro: return "Adobe Premiere";
|
||||
case AppleLogic: return "Apple Logic";
|
||||
case CakewalkSonar8: return "Cakewalk Sonar 8";
|
||||
case CakewalkSonarGeneric: return "Cakewalk Sonar";
|
||||
case DigidesignProTools: return "ProTools";
|
||||
case DigitalPerformer: return "DigitalPerformer";
|
||||
case FruityLoops: return "FruityLoops";
|
||||
case MagixSamplitude: return "Magix Samplitude";
|
||||
case MergingPyramix: return "Pyramix";
|
||||
case MuseReceptorGeneric: return "Muse Receptor";
|
||||
case Reaper: return "Reaper";
|
||||
case SteinbergCubase4: return "Steinberg Cubase 4";
|
||||
case SteinbergCubase5: return "Steinberg Cubase 5";
|
||||
case SteinbergCubase5Bridged: return "Steinberg Cubase 5 Bridged";
|
||||
case SteinbergCubase6: return "Steinberg Cubase 6";
|
||||
case SteinbergCubase7: return "Steinberg Cubase 7";
|
||||
case SteinbergCubaseGeneric: return "Steinberg Cubase";
|
||||
case SteinbergNuendo3: return "Steinberg Nuendo 3";
|
||||
case SteinbergNuendo4: return "Steinberg Nuendo 4";
|
||||
case SteinbergNuendo5: return "Steinberg Nuendo 5";
|
||||
case SteinbergNuendoGeneric: return "Steinberg Nuendo";
|
||||
case SteinbergWavelab5: return "Steinberg Wavelab 5";
|
||||
case SteinbergWavelab6: return "Steinberg Wavelab 6";
|
||||
case SteinbergWavelab7: return "Steinberg Wavelab 7";
|
||||
case SteinbergWavelab8: return "Steinberg Wavelab 8";
|
||||
case SteinbergWavelabGeneric: return "Steinberg Wavelab";
|
||||
case SteinbergTestHost: return "Steinberg TestHost";
|
||||
case StudioOne: return "Studio One";
|
||||
case Tracktion3: return "Tracktion 3";
|
||||
case TracktionGeneric: return "Tracktion";
|
||||
case VBVSTScanner: return "VBVSTScanner";
|
||||
case WaveBurner: return "WaveBurner";
|
||||
default: break;
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static String getHostPath()
|
||||
{
|
||||
return File::getSpecialLocation (File::hostApplicationPath).getFullPathName();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
private:
|
||||
static HostType getHostType()
|
||||
{
|
||||
const String hostPath (getHostPath());
|
||||
const String hostFilename (File (hostPath).getFileName());
|
||||
|
||||
#if JUCE_MAC
|
||||
if (hostPath.containsIgnoreCase ("Live 6.")) return AbletonLive6;
|
||||
if (hostPath.containsIgnoreCase ("Live 7.")) return AbletonLive7;
|
||||
if (hostPath.containsIgnoreCase ("Live 8.")) return AbletonLive8;
|
||||
if (hostFilename.containsIgnoreCase ("Live")) return AbletonLiveGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("Adobe Premiere")) return AdobePremierePro;
|
||||
if (hostFilename.contains ("Logic")) return AppleLogic;
|
||||
if (hostFilename.containsIgnoreCase ("Pro Tools")) return DigidesignProTools;
|
||||
if (hostFilename.containsIgnoreCase ("Nuendo 3")) return SteinbergNuendo3;
|
||||
if (hostFilename.containsIgnoreCase ("Nuendo 4")) return SteinbergNuendo4;
|
||||
if (hostFilename.containsIgnoreCase ("Nuendo 5")) return SteinbergNuendo5;
|
||||
if (hostFilename.containsIgnoreCase ("Nuendo")) return SteinbergNuendoGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase 4")) return SteinbergCubase4;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase 5")) return SteinbergCubase5;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase 6")) return SteinbergCubase6;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase 7")) return SteinbergCubase7;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase")) return SteinbergCubaseGeneric;
|
||||
if (hostPath.containsIgnoreCase ("Wavelab 7")) return SteinbergWavelab7;
|
||||
if (hostPath.containsIgnoreCase ("Wavelab 8")) return SteinbergWavelab8;
|
||||
if (hostFilename.containsIgnoreCase ("Wavelab")) return SteinbergWavelabGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("WaveBurner")) return WaveBurner;
|
||||
if (hostFilename.contains ("Digital Performer")) return DigitalPerformer;
|
||||
if (hostFilename.containsIgnoreCase ("reaper")) return Reaper;
|
||||
if (hostPath.containsIgnoreCase ("Studio One")) return StudioOne;
|
||||
if (hostPath.containsIgnoreCase ("Tracktion 3")) return Tracktion3;
|
||||
if (hostFilename.containsIgnoreCase ("Tracktion")) return TracktionGeneric;
|
||||
|
||||
#elif JUCE_WINDOWS
|
||||
if (hostFilename.containsIgnoreCase ("Live 6.")) return AbletonLive6;
|
||||
if (hostFilename.containsIgnoreCase ("Live 7.")) return AbletonLive7;
|
||||
if (hostFilename.containsIgnoreCase ("Live 8.")) return AbletonLive8;
|
||||
if (hostFilename.containsIgnoreCase ("Live ")) return AbletonLiveGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("Audition")) return AdobeAudition;
|
||||
if (hostFilename.containsIgnoreCase ("Adobe Premiere")) return AdobePremierePro;
|
||||
if (hostFilename.containsIgnoreCase ("ProTools")) return DigidesignProTools;
|
||||
if (hostPath.containsIgnoreCase ("SONAR 8")) return CakewalkSonar8;
|
||||
if (hostFilename.containsIgnoreCase ("SONAR")) return CakewalkSonarGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("Logic")) return AppleLogic;
|
||||
if (hostPath.containsIgnoreCase ("Tracktion 3")) return Tracktion3;
|
||||
if (hostFilename.containsIgnoreCase ("Tracktion")) return TracktionGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("reaper")) return Reaper;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase4")) return SteinbergCubase4;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase5")) return SteinbergCubase5;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase6")) return SteinbergCubase6;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase7")) return SteinbergCubase7;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase")) return SteinbergCubaseGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("VSTBridgeApp")) return SteinbergCubase5Bridged;
|
||||
if (hostPath.containsIgnoreCase ("Wavelab 5")) return SteinbergWavelab5;
|
||||
if (hostPath.containsIgnoreCase ("Wavelab 6")) return SteinbergWavelab6;
|
||||
if (hostPath.containsIgnoreCase ("Wavelab 7")) return SteinbergWavelab7;
|
||||
if (hostPath.containsIgnoreCase ("Wavelab 8")) return SteinbergWavelab8;
|
||||
if (hostPath.containsIgnoreCase ("Nuendo")) return SteinbergNuendoGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("Wavelab")) return SteinbergWavelabGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("TestHost")) return SteinbergTestHost;
|
||||
if (hostFilename.containsIgnoreCase ("rm-host")) return MuseReceptorGeneric;
|
||||
if (hostFilename.startsWith ("FL")) return FruityLoops;
|
||||
if (hostFilename.contains ("ilbridge.")) return FruityLoops;
|
||||
if (hostPath.containsIgnoreCase ("Studio One")) return StudioOne;
|
||||
if (hostPath.containsIgnoreCase ("Digital Performer")) return DigitalPerformer;
|
||||
if (hostFilename.containsIgnoreCase ("VST_Scanner")) return VBVSTScanner;
|
||||
if (hostPath.containsIgnoreCase ("Merging Technologies")) return MergingPyramix;
|
||||
if (hostFilename.startsWithIgnoreCase ("Sam")) return MagixSamplitude;
|
||||
|
||||
#elif JUCE_LINUX
|
||||
if (hostFilename.containsIgnoreCase ("Ardour")) return Ardour;
|
||||
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
return UnknownHost;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if _MSC_VER || defined (__MINGW32__) || defined (__MINGW64__)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
// Your project must contain an AppConfig.h file with your project-specific settings in it,
|
||||
// and your header search path must make it accessible to the module's files.
|
||||
#include "AppConfig.h"
|
||||
|
||||
#include "../utility/juce_CheckSettingMacros.h"
|
||||
#include "juce_IncludeModuleHeaders.h"
|
||||
|
||||
#if _MSC_VER || JUCE_MINGW
|
||||
|
||||
#if JucePlugin_Build_RTAS
|
||||
extern "C" BOOL WINAPI DllMainRTAS (HINSTANCE, DWORD, LPVOID);
|
||||
#endif
|
||||
|
||||
extern "C" BOOL WINAPI DllMain (HINSTANCE instance, DWORD reason, LPVOID reserved)
|
||||
{
|
||||
if (reason == DLL_PROCESS_ATTACH)
|
||||
Process::setCurrentModuleInstanceHandle (instance);
|
||||
|
||||
#if JucePlugin_Build_RTAS
|
||||
if (GetModuleHandleA ("DAE.DLL") != 0)
|
||||
{
|
||||
#if JucePlugin_Build_AAX
|
||||
if (! File::getSpecialLocation (File::currentExecutableFile).hasFileExtension ("aaxplugin"))
|
||||
#endif
|
||||
return DllMainRTAS (instance, reason, reserved);
|
||||
}
|
||||
#endif
|
||||
|
||||
(void) reserved;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
/** Somewhere in the codebase of your plugin, you need to implement this function
|
||||
and make it return a new instance of the filter subclass that you're building.
|
||||
*/
|
||||
extern AudioProcessor* JUCE_CALLTYPE createPluginFilter();
|
||||
|
||||
AudioProcessor* JUCE_CALLTYPE createPluginFilterOfType (AudioProcessor::WrapperType type)
|
||||
{
|
||||
AudioProcessor::setTypeOfNextNewPlugin (type);
|
||||
AudioProcessor* const pluginInstance = createPluginFilter();
|
||||
AudioProcessor::setTypeOfNextNewPlugin (AudioProcessor::wrapperType_Undefined);
|
||||
|
||||
// your createPluginFilter() method must return an object!
|
||||
jassert (pluginInstance != nullptr && pluginInstance->wrapperType == type);
|
||||
|
||||
return pluginInstance;
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JUCE_WINDOWS
|
||||
|
||||
namespace juce
|
||||
{
|
||||
// This function is in juce_win32_Windowing.cpp
|
||||
extern bool offerKeyMessageToJUCEWindow (MSG&);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
static HHOOK mouseWheelHook = 0, keyboardHook = 0;
|
||||
static int numHookUsers = 0;
|
||||
|
||||
struct WindowsHooks
|
||||
{
|
||||
WindowsHooks()
|
||||
{
|
||||
if (numHookUsers++ == 0)
|
||||
{
|
||||
mouseWheelHook = SetWindowsHookEx (WH_MOUSE, mouseWheelHookCallback,
|
||||
(HINSTANCE) Process::getCurrentModuleInstanceHandle(),
|
||||
GetCurrentThreadId());
|
||||
|
||||
keyboardHook = SetWindowsHookEx (WH_GETMESSAGE, keyboardHookCallback,
|
||||
(HINSTANCE) Process::getCurrentModuleInstanceHandle(),
|
||||
GetCurrentThreadId());
|
||||
}
|
||||
}
|
||||
|
||||
~WindowsHooks()
|
||||
{
|
||||
if (--numHookUsers == 0)
|
||||
{
|
||||
if (mouseWheelHook != 0)
|
||||
{
|
||||
UnhookWindowsHookEx (mouseWheelHook);
|
||||
mouseWheelHook = 0;
|
||||
}
|
||||
|
||||
if (keyboardHook != 0)
|
||||
{
|
||||
UnhookWindowsHookEx (keyboardHook);
|
||||
keyboardHook = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK mouseWheelHookCallback (int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (nCode >= 0 && wParam == WM_MOUSEWHEEL)
|
||||
{
|
||||
// using a local copy of this struct to support old mingw libraries
|
||||
struct MOUSEHOOKSTRUCTEX_ : public MOUSEHOOKSTRUCT { DWORD mouseData; };
|
||||
|
||||
const MOUSEHOOKSTRUCTEX_& hs = *(MOUSEHOOKSTRUCTEX_*) lParam;
|
||||
|
||||
if (Component* const comp = Desktop::getInstance().findComponentAt (Point<int> (hs.pt.x, hs.pt.y)))
|
||||
if (comp->getWindowHandle() != 0)
|
||||
return PostMessage ((HWND) comp->getWindowHandle(), WM_MOUSEWHEEL,
|
||||
hs.mouseData & 0xffff0000, (hs.pt.x & 0xffff) | (hs.pt.y << 16));
|
||||
}
|
||||
|
||||
return CallNextHookEx (mouseWheelHook, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK keyboardHookCallback (int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
MSG& msg = *(MSG*) lParam;
|
||||
|
||||
if (nCode == HC_ACTION && wParam == PM_REMOVE
|
||||
&& offerKeyMessageToJUCEWindow (msg))
|
||||
{
|
||||
zerostruct (msg);
|
||||
msg.message = WM_USER;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return CallNextHookEx (keyboardHook, nCode, wParam, lParam);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user