mirror of https://github.com/AxioDL/amuse.git
Initial work on VST editor UI
This commit is contained in:
parent
fd0dd8922a
commit
6f7a7405d7
|
@ -1,8 +1,15 @@
|
|||
unset(VST_MAIN_SRC CACHE)
|
||||
find_file(VST_MAIN_SRC vst36/vstplugmain.cpp)
|
||||
if (NOT (${VST_MAIN_SRC} STREQUAL "VST_MAIN_SRC-NOTFOUND"))
|
||||
message(STATUS "${VST_MAIN_SRC} Found VST SDK; building plugin")
|
||||
set(VST3_SDK_ROOT "" CACHE PATH "Path to VST 3.x SDK directory containing 'public.sdk' and 'plugininterfaces'")
|
||||
if (WIN32 AND (EXISTS ${VST3_SDK_ROOT}))
|
||||
message(STATUS "Found VST SDK; building plugin")
|
||||
include_directories(${VST3_SDK_ROOT} ${VST3_SDK_ROOT}/public.sdk/source/vst2.x)
|
||||
set(VST2_DIR ${VST3_SDK_ROOT}/public.sdk/source/vst2.x)
|
||||
add_definitions(${BOO_SYS_DEFINES})
|
||||
add_library(amuse-vst SHARED
|
||||
VSTBackend.hpp VSTBackend.cpp
|
||||
VSTEditor.hpp VSTEditor.cpp ${VST_MAIN_SRC})
|
||||
VSTEditor.hpp VSTEditor.cpp
|
||||
${VST2_DIR}/vstplugmain.cpp
|
||||
${VST2_DIR}/audioeffect.cpp
|
||||
${VST2_DIR}/audioeffectx.cpp)
|
||||
target_link_libraries(amuse-vst amuse boo soxr ${ZLIB_LIBRARIES} ${BOO_SYS_LIBS} Msimg32 logvisor athena-core)
|
||||
set_target_properties(amuse-vst PROPERTIES LINK_FLAGS "/EXPORT:VSTPluginMain")
|
||||
endif()
|
||||
|
|
|
@ -71,8 +71,8 @@ struct VSTVoiceEngine : boo::BaseAudioVoiceEngine
|
|||
|
||||
VSTVoiceEngine()
|
||||
{
|
||||
m_mixInfo.m_periodFrames = 512;
|
||||
m_mixInfo.m_sampleRate = 96000.0;
|
||||
m_mixInfo.m_periodFrames = 1024;
|
||||
m_mixInfo.m_sampleRate = 44100.0;
|
||||
m_mixInfo.m_sampleFormat = SOXR_FLOAT32_I;
|
||||
m_mixInfo.m_bitsPerSample = 32;
|
||||
_buildAudioRenderClient();
|
||||
|
@ -131,17 +131,23 @@ static logvisor::Module Log("amuse::AudioUnitBackend");
|
|||
VSTBackend::VSTBackend(audioMasterCallback cb)
|
||||
: AudioEffectX(cb, 0, 0), m_editor(*this)
|
||||
{
|
||||
isSynth();
|
||||
setUniqueID(kBackendID);
|
||||
setNumInputs(0);
|
||||
setNumOutputs(2);
|
||||
canProcessReplacing();
|
||||
setEditor(&m_editor);
|
||||
sizeWindow(800, 520);
|
||||
|
||||
m_booBackend = std::make_unique<VSTVoiceEngine>();
|
||||
m_voxAlloc.emplace(*m_booBackend);
|
||||
m_engine.emplace(*m_voxAlloc);
|
||||
}
|
||||
|
||||
VSTBackend::~VSTBackend()
|
||||
{
|
||||
editor = nullptr;
|
||||
}
|
||||
|
||||
AEffEditor* VSTBackend::getEditor()
|
||||
{
|
||||
return &m_editor;
|
||||
|
@ -151,6 +157,16 @@ VstInt32 VSTBackend::processEvents(VstEvents* events)
|
|||
{
|
||||
VSTVoiceEngine& engine = static_cast<VSTVoiceEngine&>(*m_booBackend);
|
||||
|
||||
/* Handle group load request */
|
||||
int reqGroup = engine.m_reqGroup;
|
||||
if (engine.m_curGroup != reqGroup)
|
||||
{
|
||||
engine.m_curGroup = reqGroup;
|
||||
if (engine.m_curSeq)
|
||||
engine.m_curSeq->kill();
|
||||
engine.m_curSeq = m_engine->seqPlay(reqGroup, -1, nullptr);
|
||||
}
|
||||
|
||||
if (engine.m_midiReceiver)
|
||||
{
|
||||
for (VstInt32 i=0 ; i<events->numEvents ; ++i)
|
||||
|
@ -172,16 +188,6 @@ void VSTBackend::processReplacing(float**, float** outputs, VstInt32 sampleFrame
|
|||
{
|
||||
VSTVoiceEngine& engine = static_cast<VSTVoiceEngine&>(*m_booBackend);
|
||||
|
||||
/* Handle group load request */
|
||||
int reqGroup = engine.m_reqGroup;
|
||||
if (engine.m_curGroup != reqGroup)
|
||||
{
|
||||
engine.m_curGroup = reqGroup;
|
||||
if (engine.m_curSeq)
|
||||
engine.m_curSeq->kill();
|
||||
engine.m_curSeq = m_engine->seqPlay(reqGroup, -1, nullptr);
|
||||
}
|
||||
|
||||
/* Output buffers */
|
||||
engine.m_renderFrames = sampleFrames;
|
||||
engine.m_outputData = outputs;
|
||||
|
@ -207,6 +213,12 @@ VstPlugCategory VSTBackend::getPlugCategory()
|
|||
return kPlugCategSynth;
|
||||
}
|
||||
|
||||
bool VSTBackend::getEffectName(char* text)
|
||||
{
|
||||
strcpy(text, "Amuse");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VSTBackend::getProductString(char* text)
|
||||
{
|
||||
strcpy(text, "Amuse");
|
||||
|
@ -219,6 +231,12 @@ bool VSTBackend::getVendorString(char* text)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool VSTBackend::getProgramNameIndexed(VstInt32 category, VstInt32 index, char* text)
|
||||
{
|
||||
strcpy(text, "Sampler");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VSTBackend::getOutputProperties(VstInt32 index, VstPinProperties* properties)
|
||||
{
|
||||
bool returnCode = false;
|
||||
|
@ -226,6 +244,7 @@ bool VSTBackend::getOutputProperties(VstInt32 index, VstPinProperties* propertie
|
|||
{
|
||||
strcpy(properties->label, "Amuse Out");
|
||||
properties->flags = kVstPinIsStereo | kVstPinIsActive;
|
||||
properties->arrangementType = kSpeakerArrStereo;
|
||||
returnCode = true;
|
||||
}
|
||||
return returnCode;
|
||||
|
@ -247,12 +266,13 @@ void VSTBackend::setBlockSize(VstInt32 blockSize)
|
|||
{
|
||||
AudioEffectX::setBlockSize(blockSize);
|
||||
VSTVoiceEngine& engine = static_cast<VSTVoiceEngine&>(*m_booBackend);
|
||||
engine.m_interleavedBuf.resize(blockSize * 2);
|
||||
engine._rebuildAudioRenderClient(engine.mixInfo().m_sampleRate, blockSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AudioEffect* createEffectInstance(audioMasterCallback audioMaster)
|
||||
{
|
||||
return new VSTBackend(audioMaster);
|
||||
}
|
||||
|
||||
return new amuse::VSTBackend(audioMaster);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __AMUSE_VSTBACKEND_HPP__
|
||||
#define __AMUSE_VSTBACKEND_HPP__
|
||||
|
||||
#include <vst36/audioeffectx.h>
|
||||
#include "audioeffectx.h"
|
||||
#include "VSTEditor.hpp"
|
||||
#include <memory>
|
||||
#include "optional.hpp"
|
||||
|
@ -34,13 +34,16 @@ class VSTBackend : public AudioEffectX
|
|||
VSTEditor m_editor;
|
||||
public:
|
||||
VSTBackend(audioMasterCallback cb);
|
||||
~VSTBackend();
|
||||
AEffEditor* getEditor();
|
||||
VstInt32 processEvents(VstEvents* events);
|
||||
void processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames);
|
||||
VstInt32 canDo(char* text);
|
||||
VstPlugCategory getPlugCategory();
|
||||
bool getEffectName(char* text);
|
||||
bool getProductString(char* text);
|
||||
bool getVendorString(char* text);
|
||||
bool getProgramNameIndexed(VstInt32 category, VstInt32 index, char* text);
|
||||
bool getOutputProperties(VstInt32 index, VstPinProperties* properties);
|
||||
VstInt32 getNumMidiInputChannels();
|
||||
void setSampleRate(float sampleRate);
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#include "VSTEditor.hpp"
|
||||
#include "VSTBackend.hpp"
|
||||
|
||||
extern void* hInstance;
|
||||
static WNDPROC OriginalListViewProc = 0;
|
||||
|
||||
namespace amuse
|
||||
{
|
||||
|
||||
|
@ -15,14 +18,227 @@ bool VSTEditor::getRect(ERect** rect)
|
|||
return true;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK VSTEditor::WindowProc(HWND hwnd,
|
||||
UINT uMsg,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
VSTEditor& editor = *reinterpret_cast<VSTEditor*>(GetWindowLongPtrW(hwnd, 0));
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_NOTIFY:
|
||||
{
|
||||
NMHDR& itemAct = *reinterpret_cast<LPNMHDR>(lParam);
|
||||
switch (itemAct.code)
|
||||
{
|
||||
case HDN_BEGINTRACK:
|
||||
return TRUE;
|
||||
case NM_CLICK:
|
||||
{
|
||||
NMITEMACTIVATE& itemAct = *reinterpret_cast<LPNMITEMACTIVATE>(lParam);
|
||||
if (itemAct.hdr.hwndFrom == editor.m_collectionListView)
|
||||
editor.selectCollection(itemAct.iItem);
|
||||
else if (itemAct.hdr.hwndFrom == editor.m_groupFileListView)
|
||||
editor.selectGroupFile(itemAct.iItem);
|
||||
else if (itemAct.hdr.hwndFrom == editor.m_groupListView)
|
||||
editor.selectGroup(itemAct.iItem);
|
||||
else if (itemAct.hdr.hwndFrom == editor.m_pageListView)
|
||||
editor.selectPage(itemAct.iItem);
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
default:
|
||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CALLBACK VSTEditor::ColHeaderWindowProc(HWND hwnd,
|
||||
UINT uMsg,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_SETCURSOR:
|
||||
return TRUE;
|
||||
case WM_LBUTTONDBLCLK:
|
||||
return 0;
|
||||
case WM_PAINT:
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
HDC dc = BeginPaint(hwnd, &ps);
|
||||
RECT rect;
|
||||
GetClientRect(hwnd, &rect);
|
||||
|
||||
TRIVERTEX verts[] =
|
||||
{
|
||||
{rect.left, rect.top, 0x6000, 0x6000, 0x7000, 0xff00},
|
||||
{rect.right, rect.bottom, 0x2000, 0x2000, 0x2800, 0xff00}
|
||||
};
|
||||
GRADIENT_RECT grect = {0, 1};
|
||||
GradientFill(dc, verts, 2, &grect, 1, GRADIENT_FILL_RECT_V);
|
||||
|
||||
SetTextColor(dc, RGB(255,255,255));
|
||||
SetBkMode(dc, TRANSPARENT);
|
||||
SelectObject(dc, GetStockObject(ANSI_VAR_FONT));
|
||||
rect.left += 6;
|
||||
|
||||
LPWSTR str = LPWSTR(GetWindowLongPtrW(hwnd, GWLP_USERDATA));
|
||||
DrawText(dc, str, -1, &rect, DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS);
|
||||
|
||||
EndPaint(hwnd, &ps);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return CallWindowProc(OriginalListViewProc, hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
bool VSTEditor::open(void* ptr)
|
||||
{
|
||||
AEffEditor::open(ptr);
|
||||
#if _WIN32
|
||||
#elif __APPLE__
|
||||
#else
|
||||
#endif
|
||||
HWND hostView = HWND(ptr);
|
||||
|
||||
WNDCLASSW notifyCls =
|
||||
{
|
||||
CS_HREDRAW | CS_VREDRAW,
|
||||
WindowProc,
|
||||
0,
|
||||
8,
|
||||
HINSTANCE(hInstance),
|
||||
nullptr,
|
||||
nullptr,
|
||||
HBRUSH(COLOR_BACKGROUND),
|
||||
nullptr,
|
||||
L"VSTNotify"
|
||||
};
|
||||
RegisterClassW(¬ifyCls);
|
||||
|
||||
m_rootView = CreateWindowW(L"VSTNotify",
|
||||
L"",
|
||||
WS_CHILD,
|
||||
0, 0,
|
||||
m_windowRect.right,
|
||||
m_windowRect.bottom,
|
||||
hostView,
|
||||
nullptr,
|
||||
HINSTANCE(hInstance),
|
||||
nullptr);
|
||||
SetWindowLongPtrW(m_rootView, 0, LONG_PTR(this));
|
||||
ShowWindow(m_rootView, SW_SHOW);
|
||||
|
||||
LV_COLUMN column = {};
|
||||
column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
|
||||
column.fmt = LVCFMT_LEFT | LVCFMT_FIXED_WIDTH;
|
||||
column.cx = 200;
|
||||
|
||||
m_collectionListView = CreateWindowW(WC_LISTVIEW,
|
||||
L"",
|
||||
WS_CHILD | WS_BORDER | LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER,
|
||||
0, 0,
|
||||
201,
|
||||
m_windowRect.bottom - m_windowRect.top,
|
||||
m_rootView,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
column.pszText = L"Collection";
|
||||
HWND header = ListView_GetHeader(m_collectionListView);
|
||||
SetWindowLongPtrW(header, GWLP_USERDATA, LONG_PTR(column.pszText));
|
||||
OriginalListViewProc = WNDPROC(SetWindowLongPtr(header, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc)));
|
||||
ListView_SetBkColor(m_collectionListView, RGB(64,64,64));
|
||||
ListView_InsertColumn(m_collectionListView, 0, &column);
|
||||
ShowWindow(m_collectionListView, SW_SHOW);
|
||||
|
||||
m_groupFileListView = CreateWindowW(WC_LISTVIEW,
|
||||
L"",
|
||||
WS_CHILD | WS_BORDER | LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER,
|
||||
200, 0,
|
||||
201,
|
||||
m_windowRect.bottom - m_windowRect.top,
|
||||
m_rootView,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
column.pszText = L"File";
|
||||
header = ListView_GetHeader(m_groupFileListView);
|
||||
SetWindowLongPtrW(header, GWLP_USERDATA, LONG_PTR(column.pszText));
|
||||
SetWindowLongPtr(header, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc));
|
||||
ListView_SetBkColor(m_groupFileListView, RGB(64,64,64));
|
||||
ListView_InsertColumn(m_groupFileListView, 0, &column);
|
||||
ShowWindow(m_groupFileListView, SW_SHOW);
|
||||
|
||||
m_groupListView = CreateWindowW(WC_LISTVIEW,
|
||||
L"",
|
||||
WS_CHILD | WS_BORDER | LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER,
|
||||
400, 0,
|
||||
201,
|
||||
m_windowRect.bottom - m_windowRect.top,
|
||||
m_rootView,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
column.pszText = L"Group";
|
||||
header = ListView_GetHeader(m_groupListView);
|
||||
SetWindowLongPtrW(header, GWLP_USERDATA, LONG_PTR(column.pszText));
|
||||
SetWindowLongPtr(header, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc));
|
||||
ListView_SetBkColor(m_groupListView, RGB(64,64,64));
|
||||
ListView_InsertColumn(m_groupListView, 0, &column);
|
||||
ShowWindow(m_groupListView, SW_SHOW);
|
||||
|
||||
m_pageListView = CreateWindowW(WC_LISTVIEW,
|
||||
L"",
|
||||
WS_CHILD | WS_BORDER | LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER,
|
||||
600, 0,
|
||||
200,
|
||||
m_windowRect.bottom - m_windowRect.top,
|
||||
m_rootView,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
column.pszText = L"Page";
|
||||
header = ListView_GetHeader(m_pageListView);
|
||||
SetWindowLongPtrW(header, GWLP_USERDATA, LONG_PTR(column.pszText));
|
||||
SetWindowLongPtr(header, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc));
|
||||
ListView_SetBkColor(m_pageListView, RGB(64,64,64));
|
||||
ListView_InsertColumn(m_pageListView, 0, &column);
|
||||
ShowWindow(m_pageListView, SW_SHOW);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VSTEditor::close()
|
||||
{
|
||||
AEffEditor::close();
|
||||
UnregisterClassW(L"VSTNotify", HINSTANCE(hInstance));
|
||||
}
|
||||
|
||||
void VSTEditor::update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void VSTEditor::selectCollection(int idx)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void VSTEditor::selectGroupFile(int idx)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void VSTEditor::selectGroup(int idx)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void VSTEditor::selectPage(int idx)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
#ifndef __AMUSE_VSTEDITOR_HPP__
|
||||
#define __AMUSE_VSTEDITOR_HPP__
|
||||
|
||||
#include <vst36/aeffeditor.h>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
|
||||
#include "aeffeditor.h"
|
||||
|
||||
namespace amuse
|
||||
{
|
||||
|
@ -11,12 +15,38 @@ class VSTBackend;
|
|||
class VSTEditor : public AEffEditor
|
||||
{
|
||||
VSTBackend& m_backend;
|
||||
ERect m_windowRect = {10, 10, 410, 520};
|
||||
ERect m_windowRect = {0, 0, 520, 800};
|
||||
|
||||
HWND m_rootView;
|
||||
HWND m_collectionListView;
|
||||
HWND m_groupFileListView;
|
||||
HWND m_groupListView;
|
||||
HWND m_pageListView;
|
||||
|
||||
static LRESULT CALLBACK WindowProc(
|
||||
_In_ HWND hwnd,
|
||||
_In_ UINT uMsg,
|
||||
_In_ WPARAM wParam,
|
||||
_In_ LPARAM lParam
|
||||
);
|
||||
static LRESULT CALLBACK ColHeaderWindowProc(
|
||||
_In_ HWND hwnd,
|
||||
_In_ UINT uMsg,
|
||||
_In_ WPARAM wParam,
|
||||
_In_ LPARAM lParam
|
||||
);
|
||||
public:
|
||||
VSTEditor(VSTBackend& backend);
|
||||
|
||||
bool getRect(ERect** rect);
|
||||
bool open(void* ptr);
|
||||
void close();
|
||||
void update();
|
||||
|
||||
void selectCollection(int idx);
|
||||
void selectGroupFile(int idx);
|
||||
void selectGroup(int idx);
|
||||
void selectPage(int idx);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#include "amuse/Voice.hpp"
|
||||
#include "amuse/Submix.hpp"
|
||||
#include "amuse/Engine.hpp"
|
||||
#include <syslog.h>
|
||||
|
||||
namespace amuse
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue