147 lines
4.6 KiB
C++
147 lines
4.6 KiB
C++
|
/*
|
||
|
* VSTEditor.cpp
|
||
|
* -------------
|
||
|
* Purpose: Implementation of the custom plugin editor window that is used if a plugin provides an own editor GUI.
|
||
|
* Notes : (currently none)
|
||
|
* Authors: OpenMPT Devs
|
||
|
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||
|
*/
|
||
|
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "resource.h"
|
||
|
#include "Vstplug.h"
|
||
|
#include "VSTEditor.h"
|
||
|
|
||
|
|
||
|
OPENMPT_NAMESPACE_BEGIN
|
||
|
|
||
|
|
||
|
#ifdef MPT_WITH_VST
|
||
|
|
||
|
BEGIN_MESSAGE_MAP(COwnerVstEditor, CAbstractVstEditor)
|
||
|
ON_WM_ERASEBKGND()
|
||
|
ON_WM_PAINT()
|
||
|
// Messages from plugin bridge to check whether a key would be handled by OpenMPT
|
||
|
// We need an offset to WM_USER because the editor window receives some spurious WM_USER messages (from MFC?) when it gets activated
|
||
|
ON_MESSAGE(WM_USER + 4000 + WM_KEYDOWN - WM_KEYFIRST, &COwnerVstEditor::OnPreTranslateKeyDown)
|
||
|
ON_MESSAGE(WM_USER + 4000 + WM_KEYUP - WM_KEYFIRST, &COwnerVstEditor::OnPreTranslateKeyUp)
|
||
|
ON_MESSAGE(WM_USER + 4000 + WM_SYSKEYDOWN - WM_KEYFIRST, &COwnerVstEditor::OnPreTranslateSysKeyDown)
|
||
|
ON_MESSAGE(WM_USER + 4000 + WM_SYSKEYUP - WM_KEYFIRST, &COwnerVstEditor::OnPreTranslateSysKeyUp)
|
||
|
END_MESSAGE_MAP()
|
||
|
|
||
|
|
||
|
void COwnerVstEditor::OnPaint()
|
||
|
{
|
||
|
CAbstractVstEditor::OnPaint();
|
||
|
auto &plugin = static_cast<const CVstPlugin &>(m_VstPlugin);
|
||
|
if(plugin.isBridged)
|
||
|
{
|
||
|
// Force redrawing for the plugin window in the bridged process.
|
||
|
// Otherwise, bridged plugin GUIs will not always be refreshed properly (e.g. when restoring OpenMPT from minimized state).
|
||
|
// Synth1 is a good candidate for testing this behaviour.
|
||
|
CRect rect;
|
||
|
if(m_plugWindow.GetUpdateRect(&rect, FALSE))
|
||
|
{
|
||
|
CWnd *child = m_plugWindow.GetWindow(GW_CHILD | GW_HWNDFIRST);
|
||
|
if(child)
|
||
|
child->RedrawWindow(&rect, nullptr, RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_UPDATENOW);
|
||
|
}
|
||
|
} else
|
||
|
{
|
||
|
// For plugins that change their size without telling the host through audioMasterSizeWindow, e.g. Roland D-50
|
||
|
CRect rect;
|
||
|
m_plugWindow.GetClientRect(rect);
|
||
|
if(rect.Width() != m_width || rect.Height() != m_height)
|
||
|
{
|
||
|
SetSize(rect.Width(), rect.Height());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void COwnerVstEditor::UpdateParamDisplays()
|
||
|
{
|
||
|
CAbstractVstEditor::UpdateParamDisplays();
|
||
|
// We trust that the plugin GUI can update its display with a bit of idle time.
|
||
|
static_cast<CVstPlugin &>(m_VstPlugin).Dispatch(Vst::effEditIdle, 0, 0, nullptr, 0.0f);
|
||
|
}
|
||
|
|
||
|
bool COwnerVstEditor::OpenEditor(CWnd *parent)
|
||
|
{
|
||
|
Create(IDD_PLUGINEDITOR, parent);
|
||
|
|
||
|
// Some plugins (e.g. ProteusVX) need to be planted into another control or else they will break our window proc, making the window unusable.
|
||
|
m_plugWindow.Create(nullptr, WS_CHILD | WS_VISIBLE, CRect(0, 0, 100, 100), this);
|
||
|
|
||
|
// Set editor window size
|
||
|
Vst::ERect rect{};
|
||
|
Vst::ERect *pRect = nullptr;
|
||
|
CVstPlugin &vstPlug = static_cast<CVstPlugin &>(m_VstPlugin);
|
||
|
vstPlug.Dispatch(Vst::effEditGetRect, 0, 0, &pRect, 0);
|
||
|
if(pRect) rect = *pRect;
|
||
|
vstPlug.Dispatch(Vst::effEditOpen, 0, 0, m_plugWindow.m_hWnd, 0);
|
||
|
vstPlug.Dispatch(Vst::effEditGetRect, 0, 0, &pRect, 0);
|
||
|
if(pRect) rect = *pRect;
|
||
|
if(rect.right > rect.left && rect.bottom > rect.top)
|
||
|
{
|
||
|
// Plugin provided valid window size.
|
||
|
SetSize(rect.Width(), rect.Height());
|
||
|
}
|
||
|
|
||
|
vstPlug.Dispatch(Vst::effEditTop, 0,0, nullptr, 0.0f);
|
||
|
vstPlug.Dispatch(Vst::effEditIdle, 0,0, nullptr, 0.0f);
|
||
|
|
||
|
// Set knob mode to linear (2) instead of circular (0) for those plugins that support it (e.g. Steinberg VB-1)
|
||
|
vstPlug.Dispatch(Vst::effSetEditKnobMode, 0, 2, nullptr, 0.0f);
|
||
|
|
||
|
return CAbstractVstEditor::OpenEditor(parent);
|
||
|
}
|
||
|
|
||
|
|
||
|
void COwnerVstEditor::DoClose()
|
||
|
{
|
||
|
// Prevent some plugins from storing a bogus window size (e.g. Electri-Q)
|
||
|
ShowWindow(SW_HIDE);
|
||
|
if(m_isMinimized) OnNcLButtonDblClk(HTCAPTION, CPoint(0, 0));
|
||
|
static_cast<CVstPlugin &>(m_VstPlugin).Dispatch(Vst::effEditClose, 0, 0, nullptr, 0.0f);
|
||
|
CAbstractVstEditor::DoClose();
|
||
|
}
|
||
|
|
||
|
|
||
|
bool COwnerVstEditor::SetSize(int contentWidth, int contentHeight)
|
||
|
{
|
||
|
if(contentWidth < 0 || contentHeight < 0 || !m_hWnd)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
m_width = contentWidth;
|
||
|
m_height = contentHeight;
|
||
|
|
||
|
CRect rcWnd, rcClient;
|
||
|
|
||
|
// Get border / menu size.
|
||
|
GetWindowRect(&rcWnd);
|
||
|
GetClientRect(&rcClient);
|
||
|
|
||
|
// Narrow plugin GUIs may force the number of menu bar lines (and thus the required window height) to change
|
||
|
WindowSizeAdjuster adjuster(*this);
|
||
|
|
||
|
const int windowWidth = rcWnd.Width() - rcClient.Width() + contentWidth;
|
||
|
const int windowHeight = rcWnd.Height() - rcClient.Height() + contentHeight;
|
||
|
SetWindowPos(NULL, 0, 0,
|
||
|
windowWidth, windowHeight,
|
||
|
SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
|
||
|
m_plugWindow.SetWindowPos(NULL, 0, 0,
|
||
|
contentWidth, contentHeight,
|
||
|
SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif // MPT_WITH_VST
|
||
|
|
||
|
|
||
|
OPENMPT_NAMESPACE_END
|