- port to minGw
git-svn-id: http://moon:8086/svn/software/trunk/projects/JaySynth@235 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user