mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-09 23:34:20 +00:00
Add new ReaperEmbeddedViewPluginDemo example
This commit is contained in:
parent
63a40188d9
commit
4b0b245b55
4 changed files with 597 additions and 0 deletions
407
examples/Plugins/ReaperEmbeddedViewPluginDemo.h
Normal file
407
examples/Plugins/ReaperEmbeddedViewPluginDemo.h
Normal file
|
|
@ -0,0 +1,407 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE examples.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
The code included in this file is provided under the terms of the ISC license
|
||||
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
|
||||
To use, copy, modify, and/or distribute this software for any purpose with or
|
||||
without fee is hereby granted provided that the above copyright notice and
|
||||
this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES,
|
||||
WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR
|
||||
PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
The block below describes the properties of this PIP. A PIP is a short snippet
|
||||
of code that can be read by the Projucer and used to generate a JUCE project.
|
||||
|
||||
BEGIN_JUCE_PIP_METADATA
|
||||
|
||||
name: ReaperEmbeddedViewDemo
|
||||
version: 1.0.0
|
||||
vendor: JUCE
|
||||
website: http://juce.com
|
||||
description: An audio plugin which embeds a secondary view in VST2 and
|
||||
VST3 formats in REAPER
|
||||
|
||||
dependencies: juce_audio_basics, juce_audio_devices, juce_audio_formats,
|
||||
juce_audio_plugin_client, juce_audio_processors,
|
||||
juce_audio_utils, juce_core, juce_data_structures,
|
||||
juce_events, juce_graphics, juce_gui_basics, juce_gui_extra
|
||||
exporters: xcode_mac, vs2019, linux_make
|
||||
|
||||
moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1
|
||||
|
||||
type: AudioProcessor
|
||||
mainClass: ReaperEmbeddedViewDemo
|
||||
|
||||
useLocalCopy: 1
|
||||
|
||||
END_JUCE_PIP_METADATA
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/* This demo shows how to use the VSTCallbackHandler and VST3ClientExtensions
|
||||
classes to provide extended functionality in compatible VST/VST3 hosts.
|
||||
|
||||
If this project is built as a VST or VST3 plugin and loaded in REAPER
|
||||
6.29 or higher, it will provide an embedded level meter in the track
|
||||
control panel. To enable the embedded view, right-click on the plugin
|
||||
and select "Show embedded UI in TCP".
|
||||
|
||||
The plugin's editor also include a button which can be used to toggle
|
||||
all inserts on and off.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <pluginterfaces/base/ftypes.h>
|
||||
#include <pluginterfaces/base/funknown.h>
|
||||
#include <pluginterfaces/vst/ivsthostapplication.h>
|
||||
|
||||
namespace reaper
|
||||
{
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wzero-as-null-pointer-constant",
|
||||
"-Wunused-parameter")
|
||||
|
||||
using namespace Steinberg;
|
||||
using INT_PTR = pointer_sized_int;
|
||||
using uint32 = Steinberg::uint32;
|
||||
|
||||
#include "extern/reaper_plugin_fx_embed.h"
|
||||
#include "extern/reaper_vst3_interfaces.h"
|
||||
|
||||
//==============================================================================
|
||||
/* These should live in a file which is guaranteed to be compiled only once
|
||||
(i.e. a .cpp file, normally). This demo is a bit special, because we know
|
||||
that this header will only be included in a single translation unit.
|
||||
*/
|
||||
DEF_CLASS_IID (IReaperHostApplication)
|
||||
DEF_CLASS_IID (IReaperUIEmbedInterface)
|
||||
|
||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
struct EmbeddedViewListener
|
||||
{
|
||||
virtual ~EmbeddedViewListener() = default;
|
||||
virtual Steinberg::TPtrInt handledEmbeddedUIMessage (int msg,
|
||||
Steinberg::TPtrInt parm2,
|
||||
Steinberg::TPtrInt parm3) = 0;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class EmbeddedUI : public reaper::IReaperUIEmbedInterface
|
||||
{
|
||||
public:
|
||||
explicit EmbeddedUI (EmbeddedViewListener& demo) : listener (demo) {}
|
||||
|
||||
Steinberg::TPtrInt embed_message (int msg,
|
||||
Steinberg::TPtrInt parm2,
|
||||
Steinberg::TPtrInt parm3) override
|
||||
{
|
||||
return listener.handledEmbeddedUIMessage (msg, parm2, parm3);
|
||||
}
|
||||
|
||||
Steinberg::uint32 PLUGIN_API addRef() override { return (Steinberg::uint32) ++refCount; }
|
||||
Steinberg::uint32 PLUGIN_API release() override { return (Steinberg::uint32) --refCount; }
|
||||
|
||||
Steinberg::tresult PLUGIN_API queryInterface (const Steinberg::TUID tuid, void** obj) override
|
||||
{
|
||||
if (std::memcmp (tuid, iid, sizeof (Steinberg::TUID)) == 0)
|
||||
{
|
||||
*obj = this;
|
||||
return Steinberg::kResultOk;
|
||||
}
|
||||
|
||||
*obj = nullptr;
|
||||
return Steinberg::kNoInterface;
|
||||
}
|
||||
|
||||
private:
|
||||
EmbeddedViewListener& listener;
|
||||
std::atomic<int> refCount { 1 };
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class Editor : public AudioProcessorEditor
|
||||
{
|
||||
public:
|
||||
explicit Editor (AudioProcessor& proc,
|
||||
AudioParameterFloat& param,
|
||||
void (*globalBypass) (int))
|
||||
: AudioProcessorEditor (proc), attachment (param, slider)
|
||||
{
|
||||
addAndMakeVisible (slider);
|
||||
addAndMakeVisible (bypassButton);
|
||||
|
||||
// Clicking will bypass *everything*
|
||||
bypassButton.onClick = [globalBypass] { if (globalBypass != nullptr) globalBypass (-1); };
|
||||
|
||||
setSize (300, 80);
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
auto b = getLocalBounds();
|
||||
slider.setBounds (b.removeFromTop (40));
|
||||
bypassButton.setBounds (b);
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
g.fillAll (Colours::darkgrey);
|
||||
}
|
||||
|
||||
private:
|
||||
Slider slider;
|
||||
TextButton bypassButton { "global bypass" };
|
||||
SliderParameterAttachment attachment;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class ReaperEmbeddedViewDemo : public AudioProcessor,
|
||||
public VSTCallbackHandler,
|
||||
public VST3ClientExtensions,
|
||||
private EmbeddedViewListener,
|
||||
private Timer
|
||||
{
|
||||
public:
|
||||
ReaperEmbeddedViewDemo()
|
||||
{
|
||||
addParameter (gain = new AudioParameterFloat ("gain", "Gain", 0.0f, 1.0f, 0.5f));
|
||||
startTimerHz (60);
|
||||
}
|
||||
|
||||
void prepareToPlay (double, int) override {}
|
||||
void reset() override {}
|
||||
|
||||
void releaseResources() override {}
|
||||
|
||||
void processBlock (AudioBuffer<float>& audio, MidiBuffer&) override { processBlockImpl (audio); }
|
||||
void processBlock (AudioBuffer<double>& audio, MidiBuffer&) override { processBlockImpl (audio); }
|
||||
|
||||
//==============================================================================
|
||||
AudioProcessorEditor* createEditor() override { return new Editor (*this, *gain, globalBypassFn); }
|
||||
bool hasEditor() const override { return true; }
|
||||
|
||||
//==============================================================================
|
||||
const String getName() const override { return "ReaperEmbeddedViewDemo"; }
|
||||
|
||||
bool acceptsMidi() const override { return false; }
|
||||
bool producesMidi() const override { return false; }
|
||||
bool isMidiEffect() const override { return false; }
|
||||
|
||||
double getTailLengthSeconds() const override { return 0.0; }
|
||||
|
||||
//==============================================================================
|
||||
int getNumPrograms() override { return 1; }
|
||||
int getCurrentProgram() override { return 0; }
|
||||
void setCurrentProgram (int) override {}
|
||||
const String getProgramName (int) override { return {}; }
|
||||
|
||||
void changeProgramName (int, const String&) override {}
|
||||
|
||||
//==============================================================================
|
||||
void getStateInformation (MemoryBlock& destData) override
|
||||
{
|
||||
MemoryOutputStream (destData, true).writeFloat (*gain);
|
||||
}
|
||||
|
||||
void setStateInformation (const void* data, int sizeInBytes) override
|
||||
{
|
||||
gain->setValueNotifyingHost (MemoryInputStream (data,
|
||||
static_cast<size_t> (sizeInBytes),
|
||||
false).readFloat());
|
||||
}
|
||||
|
||||
int32_t queryIEditController (const Steinberg::TUID tuid, void** obj) override
|
||||
{
|
||||
if (std::memcmp (tuid, embeddedUi.iid, sizeof (Steinberg::TUID)) == 0)
|
||||
{
|
||||
*obj = &embeddedUi;
|
||||
return Steinberg::kResultOk;
|
||||
}
|
||||
|
||||
*obj = nullptr;
|
||||
return Steinberg::kNoInterface;
|
||||
}
|
||||
|
||||
void setIHostApplication (Steinberg::FUnknown* ptr) override
|
||||
{
|
||||
if (ptr == nullptr)
|
||||
return;
|
||||
|
||||
void* objPtr = nullptr;
|
||||
|
||||
if (ptr->queryInterface (reaper::IReaperHostApplication::iid, &objPtr) == Steinberg::kResultOk)
|
||||
{
|
||||
if (void* fnPtr = static_cast<reaper::IReaperHostApplication*> (objPtr)->getReaperApi ("BypassFxAllTracks"))
|
||||
globalBypassFn = reinterpret_cast<void (*) (int)> (fnPtr);
|
||||
}
|
||||
}
|
||||
|
||||
pointer_sized_int handleVstPluginCanDo (int32, pointer_sized_int, void* ptr, float) override
|
||||
{
|
||||
if (auto* str = static_cast<const char*> (ptr))
|
||||
{
|
||||
if (strcmp (str, "hasCockosEmbeddedUI") == 0)
|
||||
return 0xbeef0000;
|
||||
|
||||
if (strcmp (str, "hasCockosExtensions") == 0)
|
||||
return 0xbeef0000;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
pointer_sized_int handleVstManufacturerSpecific (int32,
|
||||
pointer_sized_int value,
|
||||
void* ptr,
|
||||
float opt) override
|
||||
{
|
||||
return (pointer_sized_int) handledEmbeddedUIMessage ((int) opt,
|
||||
(Steinberg::TPtrInt) value,
|
||||
(Steinberg::TPtrInt) ptr);
|
||||
}
|
||||
|
||||
void handleVstHostCallbackAvailable (std::function<VstHostCallbackType>&& hostcb) override
|
||||
{
|
||||
char functionName[] = "BypassFxAllTracks";
|
||||
globalBypassFn = reinterpret_cast<void (*) (int)> (hostcb ((int32_t) 0xdeadbeef, (int32_t) 0xdeadf00d, 0, functionName, 0.0));
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Float>
|
||||
void processBlockImpl (AudioBuffer<Float>& audio)
|
||||
{
|
||||
audio.applyGain (*gain);
|
||||
|
||||
const auto minMax = audio.findMinMax (0, 0, audio.getNumSamples());
|
||||
const auto newMax = (float) std::max (std::abs (minMax.getStart()), std::abs (minMax.getEnd()));
|
||||
|
||||
auto loaded = storedLevel.load();
|
||||
while (loaded < newMax && ! storedLevel.compare_exchange_weak (loaded, newMax)) {}
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
levelToDraw = std::max (levelToDraw * 0.95f, storedLevel.exchange (0.0f));
|
||||
}
|
||||
|
||||
Steinberg::TPtrInt getSizeInfo (reaper::REAPER_FXEMBED_SizeHints* sizeHints)
|
||||
{
|
||||
if (sizeHints == nullptr)
|
||||
return 0;
|
||||
|
||||
sizeHints->preferred_aspect = 1 << 16;
|
||||
sizeHints->minimum_aspect = 1 << 16;
|
||||
sizeHints->min_height = sizeHints->min_width = 50;
|
||||
sizeHints->max_height = sizeHints->max_width = 1000;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Steinberg::TPtrInt doPaint (reaper::REAPER_FXEMBED_IBitmap* bitmap,
|
||||
reaper::REAPER_FXEMBED_DrawInfo* drawInfo)
|
||||
{
|
||||
if (bitmap == nullptr || drawInfo == nullptr)
|
||||
return 0;
|
||||
|
||||
Image img (juce::Image::PixelFormat::ARGB, bitmap->getWidth(), bitmap->getHeight(), true);
|
||||
Graphics g (img);
|
||||
|
||||
g.fillAll (Colours::black);
|
||||
|
||||
const auto bounds = g.getClipBounds();
|
||||
const auto corner = 3.0f;
|
||||
|
||||
g.setColour (Colours::darkgrey);
|
||||
g.fillRoundedRectangle (bounds.withSizeKeepingCentre (20, bounds.getHeight() - 6).toFloat(),
|
||||
corner);
|
||||
|
||||
const auto minDb = -50.0f;
|
||||
const auto maxDb = 6.0f;
|
||||
const auto levelInDb = Decibels::gainToDecibels (levelToDraw, minDb);
|
||||
const auto fractionOfHeight = jmap (levelInDb, minDb, maxDb, 0.0f, 1.0f);
|
||||
const auto trackBounds = bounds.withSizeKeepingCentre (16, bounds.getHeight() - 10).toFloat();
|
||||
|
||||
g.setColour (Colours::black);
|
||||
const auto zeroDbIndicatorY = trackBounds.proportionOfHeight (jmap (0.0f,
|
||||
minDb,
|
||||
maxDb,
|
||||
0.0f,
|
||||
1.0f));
|
||||
g.drawHorizontalLine ((int) (trackBounds.getBottom() - zeroDbIndicatorY),
|
||||
trackBounds.getX(),
|
||||
trackBounds.getRight());
|
||||
|
||||
g.setGradientFill (ColourGradient (Colours::darkgreen,
|
||||
{ 0.0f, (float) bounds.getHeight() },
|
||||
Colours::darkred,
|
||||
{ 0.0f, 0.0f },
|
||||
false));
|
||||
|
||||
g.fillRoundedRectangle (trackBounds.withHeight (trackBounds.proportionOfHeight (fractionOfHeight))
|
||||
.withBottomY (trackBounds.getBottom()),
|
||||
corner);
|
||||
|
||||
Image::BitmapData imgData { img, Image::BitmapData::readOnly };
|
||||
const auto pixelsWidth = imgData.pixelStride * imgData.width;
|
||||
|
||||
auto* px = bitmap->getBits();
|
||||
const auto rowSpan = bitmap->getRowSpan();
|
||||
const auto numRows = bitmap->getHeight();
|
||||
|
||||
for (int y = 0; y < numRows; ++y)
|
||||
std::memcpy (px + (y * rowSpan), imgData.getLinePointer (y), (size_t) pixelsWidth);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
Steinberg::TPtrInt handledEmbeddedUIMessage (int msg,
|
||||
Steinberg::TPtrInt parm2,
|
||||
Steinberg::TPtrInt parm3) override
|
||||
{
|
||||
switch (msg)
|
||||
{
|
||||
case REAPER_FXEMBED_WM_IS_SUPPORTED:
|
||||
return 1;
|
||||
|
||||
case REAPER_FXEMBED_WM_PAINT:
|
||||
return doPaint (reinterpret_cast<reaper::REAPER_FXEMBED_IBitmap*> (parm2),
|
||||
reinterpret_cast<reaper::REAPER_FXEMBED_DrawInfo*> (parm3));
|
||||
|
||||
case REAPER_FXEMBED_WM_GETMINMAXINFO:
|
||||
return getSizeInfo (reinterpret_cast<reaper::REAPER_FXEMBED_SizeHints*> (parm3));
|
||||
|
||||
// Implementing mouse behaviour is left as an exercise for the reaper, I mean reader
|
||||
case REAPER_FXEMBED_WM_CREATE: break;
|
||||
case REAPER_FXEMBED_WM_DESTROY: break;
|
||||
case REAPER_FXEMBED_WM_SETCURSOR: break;
|
||||
case REAPER_FXEMBED_WM_MOUSEMOVE: break;
|
||||
case REAPER_FXEMBED_WM_LBUTTONDOWN: break;
|
||||
case REAPER_FXEMBED_WM_LBUTTONUP: break;
|
||||
case REAPER_FXEMBED_WM_LBUTTONDBLCLK: break;
|
||||
case REAPER_FXEMBED_WM_RBUTTONDOWN: break;
|
||||
case REAPER_FXEMBED_WM_RBUTTONUP: break;
|
||||
case REAPER_FXEMBED_WM_RBUTTONDBLCLK: break;
|
||||
case REAPER_FXEMBED_WM_MOUSEWHEEL: break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
AudioParameterFloat* gain = nullptr;
|
||||
void (*globalBypassFn) (int) = nullptr;
|
||||
EmbeddedUI embeddedUi { *this };
|
||||
|
||||
std::atomic<float> storedLevel { 0.0f };
|
||||
float levelToDraw = 0.0f;
|
||||
};
|
||||
19
examples/Plugins/extern/LICENSE.md
vendored
Normal file
19
examples/Plugins/extern/LICENSE.md
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
The files in this folder were copied from the [reaper-sdk
|
||||
repository](https://github.com/justinfrankel/reaper-sdk) on Github. At the time
|
||||
of writing, these files were distributed under the following license:
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
140
examples/Plugins/extern/reaper_plugin_fx_embed.h
vendored
Normal file
140
examples/Plugins/extern/reaper_plugin_fx_embed.h
vendored
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
#ifndef _REAPER_PLUGIN_FX_EMBED_H_
|
||||
#define _REAPER_PLUGIN_FX_EMBED_H_
|
||||
|
||||
|
||||
/*
|
||||
* to support via VST2: canDo("hasCockosEmbeddedUI") should return 0xbeef0000
|
||||
* dispatcher will be called with opcode=effVendorSpecific, index=effEditDraw, value=parm2, ptr=(void*)(INT_PTR)parm3, opt=message (REAPER_FXEMBED_WM_*)
|
||||
*
|
||||
* to support via VST3: IController should support IReaperUIEmbedInterface, see reaper_vst3_interfaces.h
|
||||
*
|
||||
* to support via LV2: todo
|
||||
*/
|
||||
|
||||
// these alias to win32's WM_*
|
||||
|
||||
|
||||
#define REAPER_FXEMBED_WM_IS_SUPPORTED 0x0000
|
||||
/* return 1 if embedding is supported and available
|
||||
* return -1 if embedding is supported and unavailable
|
||||
* return 0 if embedding is not supported
|
||||
*/
|
||||
|
||||
#define REAPER_FXEMBED_WM_CREATE 0x0001 // called when embedding begins (return value ignored)
|
||||
#define REAPER_FXEMBED_WM_DESTROY 0x0002 // called when embedding ends (return value ignored)
|
||||
|
||||
|
||||
|
||||
typedef struct REAPER_FXEMBED_DrawInfo // alias of REAPER_inline_positioninfo
|
||||
{
|
||||
int context; // 0=unknown (v6.23 and earlier), 1=TCP, 2=MCP
|
||||
int dpi; // 0=unknown (v6.23 and earlier), otherwise 24.8 fixed point (256=100%)
|
||||
int mousewheel_amt; // for REAPER_FXEMBED_WM_MOUSEWHEEL, 120 = step, typically
|
||||
double _res2;
|
||||
|
||||
int width, height;
|
||||
int mouse_x, mouse_y;
|
||||
|
||||
int flags; // REAPER_FXEMBED_DRAWINFO_FLAG_PAINT_OPTIONAL etc
|
||||
int _res3;
|
||||
|
||||
void *spare[6];
|
||||
} REAPER_FXEMBED_DrawInfo;
|
||||
|
||||
#define REAPER_FXEMBED_DRAWINFO_FLAG_PAINT_OPTIONAL 1
|
||||
#define REAPER_FXEMBED_DRAWINFO_FLAG_LBUTTON_CAPTURED 0x10000
|
||||
#define REAPER_FXEMBED_DRAWINFO_FLAG_RBUTTON_CAPTURED 0x20000
|
||||
|
||||
#define REAPER_FXEMBED_WM_PAINT 0x000F
|
||||
/*
|
||||
* draw embedded UI.
|
||||
* parm2: REAPER_FXEMBED_IBitmap * to draw into. note
|
||||
* parm3: REAPER_FXEMBED_DrawInfo *
|
||||
*
|
||||
* if flags has REAPER_FXEMBED_DRAWINFO_FLAG_PAINT_OPTIONAL set, update is optional. if no change since last draw, return 0.
|
||||
* if flags has REAPER_FXEMBED_DRAWINFO_FLAG_LBUTTON_CAPTURED set, left mouse button is down and captured
|
||||
* if flags has REAPER_FXEMBED_DRAWINFO_FLAG_RBUTTON_CAPTURED set, right mouse button is down and captured
|
||||
*
|
||||
* HiDPI:
|
||||
* if REAPER_FXEMBED_IBitmap::Extended(REAPER_FXEMBED_EXT_GET_ADVISORY_SCALING,NULL) returns nonzero, then it is a 24.8 scalefactor for UI drawing
|
||||
*
|
||||
* return 1 if drawing occurred, 0 otherwise.
|
||||
*
|
||||
*/
|
||||
|
||||
#define REAPER_FXEMBED_WM_SETCURSOR 0x0020 // parm3: REAPER_FXEMBED_DrawInfo*. set mouse cursor and return REAPER_FXEMBED_RETNOTIFY_HANDLED, or return 0.
|
||||
|
||||
#define REAPER_FXEMBED_WM_GETMINMAXINFO 0x0024
|
||||
/*
|
||||
* get size hints. parm3 = (REAPER_FXEMBED_SizeHints*). return 1 if supported
|
||||
* note that these are just hints, the actual size may vary
|
||||
*/
|
||||
typedef struct REAPER_FXEMBED_SizeHints { // alias to MINMAXINFO
|
||||
int preferred_aspect; // 16.16 fixed point (65536 = 1:1, 32768 = 1:2, etc)
|
||||
int minimum_aspect; // 16.16 fixed point
|
||||
|
||||
int _res1, _res2, _res3, _res4;
|
||||
|
||||
int min_width, min_height;
|
||||
int max_width, max_height;
|
||||
} REAPER_FXEMBED_SizeHints;
|
||||
|
||||
/*
|
||||
* mouse messages
|
||||
* parm3 = (REAPER_FXEMBED_DrawInfo*)
|
||||
* capture is automatically set on mouse down, released on mouse up
|
||||
* when not captured, will always receive a mousemove when exiting the window
|
||||
*/
|
||||
|
||||
#define REAPER_FXEMBED_WM_MOUSEMOVE 0x0200
|
||||
#define REAPER_FXEMBED_WM_LBUTTONDOWN 0x0201
|
||||
#define REAPER_FXEMBED_WM_LBUTTONUP 0x0202
|
||||
#define REAPER_FXEMBED_WM_LBUTTONDBLCLK 0x0203
|
||||
#define REAPER_FXEMBED_WM_RBUTTONDOWN 0x0204
|
||||
#define REAPER_FXEMBED_WM_RBUTTONUP 0x0205
|
||||
#define REAPER_FXEMBED_WM_RBUTTONDBLCLK 0x0206
|
||||
#define REAPER_FXEMBED_WM_MOUSEWHEEL 0x020A
|
||||
|
||||
|
||||
/* REAPER_FXEMBED_WM_SETCURSOR should return REAPER_FXEMBED_RETNOTIFY_HANDLED if a cursor was set
|
||||
*/
|
||||
#define REAPER_FXEMBED_RETNOTIFY_HANDLED 0x0000001
|
||||
|
||||
/* if the mouse messages return with REAPER_FXEMBED_RETNOTIFY_INVALIDATE set, a non-optional
|
||||
* redraw is initiated (generally sooner than the next timer-based redraw)
|
||||
*/
|
||||
#define REAPER_FXEMBED_RETNOTIFY_INVALIDATE 0x1000000
|
||||
|
||||
/*
|
||||
* bitmap interface
|
||||
* this is an alias of LICE_IBitmap etc from WDL/lice/lice.h
|
||||
*
|
||||
*/
|
||||
#define REAPER_FXEMBED_RGBA(r,g,b,a) (((b)&0xff)|(((g)&0xff)<<8)|(((r)&0xff)<<16)|(((a)&0xff)<<24))
|
||||
#define REAPER_FXEMBED_GETB(v) ((v)&0xff)
|
||||
#define REAPER_FXEMBED_GETG(v) (((v)>>8)&0xff)
|
||||
#define REAPER_FXEMBED_GETR(v) (((v)>>16)&0xff)
|
||||
#define REAPER_FXEMBED_GETA(v) (((v)>>24)&0xff)
|
||||
|
||||
#ifdef __cplusplus
|
||||
class REAPER_FXEMBED_IBitmap // alias of LICE_IBitmap
|
||||
{
|
||||
public:
|
||||
virtual ~REAPER_FXEMBED_IBitmap() { }
|
||||
|
||||
virtual unsigned int *getBits()=0;
|
||||
virtual int getWidth()=0;
|
||||
virtual int getHeight()=0;
|
||||
virtual int getRowSpan()=0; // includes any off-bitmap data. this is in sizeof(unsigned int) units, not bytes.
|
||||
virtual bool isFlipped() { return false; }
|
||||
virtual bool resize(int w, int h)=0;
|
||||
|
||||
virtual void *getDC() { return 0; } // do not use
|
||||
|
||||
virtual INT_PTR Extended(int id, void* data) { return 0; }
|
||||
};
|
||||
#endif
|
||||
|
||||
#define REAPER_FXEMBED_EXT_GET_ADVISORY_SCALING 0x2003 // data ignored, returns .8 fixed point. returns 0 if unscaled
|
||||
|
||||
#endif
|
||||
31
examples/Plugins/extern/reaper_vst3_interfaces.h
vendored
Normal file
31
examples/Plugins/extern/reaper_vst3_interfaces.h
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef _REAPER_VST3_INTERFACES_H_
|
||||
#define _REAPER_VST3_INTERFACES_H_
|
||||
|
||||
class IReaperHostApplication : public FUnknown // available from IHostApplication in REAPER v5.02+
|
||||
{
|
||||
public:
|
||||
// Gets a REAPER Extension API function by name, returns NULL is failed
|
||||
virtual void* PLUGIN_API getReaperApi(CStringA funcname) = 0;
|
||||
|
||||
virtual void* PLUGIN_API getReaperParent(uint32 w) = 0; // get parent track(=1), take(=2), project(=3), fxdsp(=4), trackchan(=5)
|
||||
|
||||
// Multi-purpose function, returns NULL if unsupported
|
||||
virtual void* PLUGIN_API reaperExtended(uint32 call, void *parm1, void *parm2, void *parm3) = 0;
|
||||
|
||||
static const FUID iid;
|
||||
};
|
||||
|
||||
DECLARE_CLASS_IID (IReaperHostApplication, 0x79655E36, 0x77EE4267, 0xA573FEF7, 0x4912C27C)
|
||||
|
||||
class IReaperUIEmbedInterface : public FUnknown // supported by REAPER v6.24+, queried from plug-in IController
|
||||
{
|
||||
public:
|
||||
// note: VST2 uses CanDo "hasCockosEmbeddedUI"==0xbeef0000, then opcode=effVendorSpecific, index=effEditDraw, opt=(float)msg, value=parm2, ptr=parm3
|
||||
// see reaper_plugin_fx_embed.h
|
||||
virtual Steinberg::TPtrInt embed_message(int msg, Steinberg::TPtrInt parm2, Steinberg::TPtrInt parm3) = 0;
|
||||
|
||||
static const FUID iid;
|
||||
};
|
||||
|
||||
DECLARE_CLASS_IID (IReaperUIEmbedInterface, 0x049bf9e7, 0xbc74ead0, 0xc4101e86, 0x7f725981)
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue