402 lines
10 KiB
C++
402 lines
10 KiB
C++
|
/*
|
||
|
* LFOPluginEditor.cpp
|
||
|
* -------------------
|
||
|
* Purpose: Editor interface for the LFO plugin.
|
||
|
* Notes : (currently none)
|
||
|
* Authors: Johannes Schultz (OpenMPT Devs)
|
||
|
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||
|
*/
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
|
||
|
#include "LFOPluginEditor.h"
|
||
|
#include "../Mptrack.h"
|
||
|
#include "../UpdateHints.h"
|
||
|
#include "../../soundlib/Sndfile.h"
|
||
|
#include "../../soundlib/MIDIEvents.h"
|
||
|
#include "../../mptrack/resource.h"
|
||
|
|
||
|
OPENMPT_NAMESPACE_BEGIN
|
||
|
|
||
|
BEGIN_MESSAGE_MAP(LFOPluginEditor, CAbstractVstEditor)
|
||
|
//{{AFX_MSG_MAP(LFOPluginEditor)
|
||
|
ON_WM_HSCROLL()
|
||
|
ON_COMMAND(IDC_BUTTON1, &LFOPluginEditor::OnPluginEditor)
|
||
|
ON_COMMAND(IDC_CHECK1, &LFOPluginEditor::OnPolarityChanged)
|
||
|
ON_COMMAND(IDC_CHECK2, &LFOPluginEditor::OnTempoSyncChanged)
|
||
|
ON_COMMAND(IDC_CHECK3, &LFOPluginEditor::OnBypassChanged)
|
||
|
ON_COMMAND(IDC_CHECK4, &LFOPluginEditor::OnLoopModeChanged)
|
||
|
ON_COMMAND_RANGE(IDC_RADIO1, IDC_RADIO1 + LFOPlugin::kNumWaveforms - 1, &LFOPluginEditor::OnWaveformChanged)
|
||
|
ON_CBN_SELCHANGE(IDC_COMBO1, &LFOPluginEditor::OnPlugParameterChanged)
|
||
|
ON_CBN_SELCHANGE(IDC_COMBO2, &LFOPluginEditor::OnOutputPlugChanged)
|
||
|
ON_CBN_SELCHANGE(IDC_COMBO3, &LFOPluginEditor::OnMidiCCChanged)
|
||
|
ON_COMMAND(IDC_RADIO7, &LFOPluginEditor::OnParameterChanged)
|
||
|
ON_COMMAND(IDC_RADIO8, &LFOPluginEditor::OnParameterChanged)
|
||
|
ON_EN_UPDATE(IDC_EDIT1, &LFOPluginEditor::OnParameterChanged)
|
||
|
ON_MESSAGE(LFOPlugin::WM_PARAM_UDPATE, &LFOPluginEditor::OnUpdateParam)
|
||
|
//}}AFX_MSG_MAP
|
||
|
END_MESSAGE_MAP()
|
||
|
|
||
|
|
||
|
void LFOPluginEditor::DoDataExchange(CDataExchange* pDX)
|
||
|
{
|
||
|
CDialog::DoDataExchange(pDX);
|
||
|
//{{AFX_DATA_MAP(LFOPluginEditor)
|
||
|
DDX_Control(pDX, IDC_COMBO1, m_plugParam);
|
||
|
DDX_Control(pDX, IDC_COMBO2, m_outPlug);
|
||
|
DDX_Control(pDX, IDC_COMBO3, m_midiCC);
|
||
|
DDX_Control(pDX, IDC_SLIDER1, m_amplitudeSlider);
|
||
|
DDX_Control(pDX, IDC_SLIDER2, m_offsetSlider);
|
||
|
DDX_Control(pDX, IDC_SLIDER3, m_frequencySlider);
|
||
|
DDX_Control(pDX, IDC_EDIT1, m_midiChnEdit);
|
||
|
DDX_Control(pDX, IDC_SPIN1, m_midiChnSpin);
|
||
|
//}}AFX_DATA_MAP
|
||
|
}
|
||
|
|
||
|
|
||
|
LFOPluginEditor::LFOPluginEditor(LFOPlugin &plugin)
|
||
|
: CAbstractVstEditor(plugin)
|
||
|
, m_lfoPlugin(plugin)
|
||
|
, m_locked(true)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
bool LFOPluginEditor::OpenEditor(CWnd *parent)
|
||
|
{
|
||
|
m_locked = true;
|
||
|
Create(IDD_LFOPLUGIN, parent);
|
||
|
|
||
|
m_midiChnSpin.SetRange32(1, 16);
|
||
|
m_midiCC.SetRedraw(FALSE);
|
||
|
CString s;
|
||
|
for(unsigned int i = 0; i < 128; i++)
|
||
|
{
|
||
|
s.Format(_T("%3u: "), i);
|
||
|
s += mpt::ToCString(mpt::Charset::UTF8, MIDIEvents::MidiCCNames[i]);
|
||
|
m_midiCC.AddString(s);
|
||
|
}
|
||
|
if(m_lfoPlugin.m_outputToCC && m_lfoPlugin.m_outputParam != LFOPlugin::INVALID_OUTPUT_PARAM)
|
||
|
{
|
||
|
m_midiCC.SetCurSel(m_lfoPlugin.m_outputParam & 0x7F);
|
||
|
SetDlgItemInt(IDC_EDIT1, 1 + ((m_lfoPlugin.m_outputParam & 0xF00) >> 8));
|
||
|
} else
|
||
|
{
|
||
|
SetDlgItemInt(IDC_EDIT1, 1);
|
||
|
}
|
||
|
m_midiCC.SetRedraw(TRUE);
|
||
|
|
||
|
UpdateView(PluginHint().Info().Names());
|
||
|
|
||
|
for(int32 i = 0; i < LFOPlugin::kLFONumParameters; i++)
|
||
|
{
|
||
|
UpdateParam(i);
|
||
|
}
|
||
|
UpdateParamDisplays();
|
||
|
|
||
|
m_locked = false;
|
||
|
// Avoid weird WM_COMMAND message (following a WM_ACTIVATE message) activating a wrong waveform when closing the plugin editor while the pattern editor is open
|
||
|
GetDlgItem(IDC_RADIO1 + m_lfoPlugin.m_waveForm)->SetFocus();
|
||
|
return CAbstractVstEditor::OpenEditor(parent);
|
||
|
}
|
||
|
|
||
|
|
||
|
void LFOPluginEditor::UpdateParamDisplays()
|
||
|
{
|
||
|
CAbstractVstEditor::UpdateParamDisplays();
|
||
|
m_locked = true;
|
||
|
CheckRadioButton(IDC_RADIO7, IDC_RADIO8, m_lfoPlugin.m_outputToCC ? IDC_RADIO8 : IDC_RADIO7);
|
||
|
m_plugParam.SetRedraw(FALSE);
|
||
|
IMixPlugin *outPlug = m_lfoPlugin.GetOutputPlugin();
|
||
|
if(outPlug != nullptr)
|
||
|
{
|
||
|
if(LONG_PTR(outPlug) != GetWindowLongPtr(m_plugParam, GWLP_USERDATA))
|
||
|
{
|
||
|
m_plugParam.ResetContent();
|
||
|
AddPluginParameternamesToCombobox(m_plugParam, *outPlug);
|
||
|
if(!m_lfoPlugin.m_outputToCC)
|
||
|
m_plugParam.SetCurSel(m_lfoPlugin.m_outputParam);
|
||
|
SetWindowLongPtr(m_plugParam, GWLP_USERDATA, LONG_PTR(outPlug));
|
||
|
}
|
||
|
GetDlgItem(IDC_BUTTON1)->EnableWindow(outPlug ? TRUE :FALSE);
|
||
|
} else
|
||
|
{
|
||
|
m_plugParam.ResetContent();
|
||
|
SetWindowLongPtr(m_plugParam, GWLP_USERDATA, 0);
|
||
|
}
|
||
|
m_plugParam.SetRedraw(TRUE);
|
||
|
m_locked = false;
|
||
|
}
|
||
|
|
||
|
|
||
|
void LFOPluginEditor::UpdateParam(int32 p)
|
||
|
{
|
||
|
LFOPlugin::Parameters param = static_cast<LFOPlugin::Parameters>(p);
|
||
|
CAbstractVstEditor::UpdateParam(p);
|
||
|
m_locked = true;
|
||
|
switch(param)
|
||
|
{
|
||
|
case LFOPlugin::kAmplitude:
|
||
|
InitSlider(m_amplitudeSlider, LFOPlugin::kAmplitude);
|
||
|
break;
|
||
|
case LFOPlugin::kOffset:
|
||
|
InitSlider(m_offsetSlider, LFOPlugin::kOffset);
|
||
|
break;
|
||
|
case LFOPlugin::kFrequency:
|
||
|
InitSlider(m_frequencySlider, LFOPlugin::kFrequency);
|
||
|
break;
|
||
|
case LFOPlugin::kTempoSync:
|
||
|
CheckDlgButton(IDC_CHECK2, m_lfoPlugin.m_tempoSync ? BST_CHECKED : BST_UNCHECKED);
|
||
|
InitSlider(m_frequencySlider, LFOPlugin::kFrequency);
|
||
|
break;
|
||
|
case LFOPlugin::kWaveform:
|
||
|
CheckRadioButton(IDC_RADIO1, IDC_RADIO1 + LFOPlugin::kNumWaveforms - 1, IDC_RADIO1 + m_lfoPlugin.m_waveForm);
|
||
|
break;
|
||
|
case LFOPlugin::kPolarity:
|
||
|
CheckDlgButton(IDC_CHECK1, m_lfoPlugin.m_polarity ? BST_CHECKED : BST_UNCHECKED);
|
||
|
break;
|
||
|
case LFOPlugin::kBypassed:
|
||
|
CheckDlgButton(IDC_CHECK3, m_lfoPlugin.m_bypassed ? BST_CHECKED : BST_UNCHECKED);
|
||
|
break;
|
||
|
case LFOPlugin::kLoopMode:
|
||
|
CheckDlgButton(IDC_CHECK4, m_lfoPlugin.m_oneshot ? BST_CHECKED : BST_UNCHECKED);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
m_locked = false;
|
||
|
}
|
||
|
|
||
|
|
||
|
void LFOPluginEditor::UpdateView(UpdateHint hint)
|
||
|
{
|
||
|
CAbstractVstEditor::UpdateView(hint);
|
||
|
if(hint.GetType()[HINT_PLUGINNAMES | HINT_MIXPLUGINS])
|
||
|
{
|
||
|
PLUGINDEX hintPlug = hint.ToType<PluginHint>().GetPlugin();
|
||
|
if(hintPlug > 0 && hintPlug <= m_lfoPlugin.GetSlot())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
CString s;
|
||
|
IMixPlugin *outPlugin = m_lfoPlugin.GetOutputPlugin();
|
||
|
m_outPlug.SetRedraw(FALSE);
|
||
|
m_outPlug.ResetContent();
|
||
|
for(PLUGINDEX out = m_lfoPlugin.GetSlot() + 1; out < MAX_MIXPLUGINS; out++)
|
||
|
{
|
||
|
const SNDMIXPLUGIN &outPlug = m_lfoPlugin.GetSoundFile().m_MixPlugins[out];
|
||
|
if(outPlug.IsValidPlugin())
|
||
|
{
|
||
|
mpt::ustring libName = outPlug.GetLibraryName();
|
||
|
s.Format(_T("FX%d: "), out + 1);
|
||
|
s += mpt::ToCString(libName);
|
||
|
if(outPlug.GetName() != U_("") && libName != outPlug.GetName())
|
||
|
{
|
||
|
s += _T(" (");
|
||
|
s += mpt::ToCString(outPlug.GetName());
|
||
|
s += _T(")");
|
||
|
}
|
||
|
|
||
|
int n = m_outPlug.AddString(s);
|
||
|
m_outPlug.SetItemData(n, out);
|
||
|
if(outPlugin == outPlug.pMixPlugin)
|
||
|
{
|
||
|
m_outPlug.SetCurSel(n);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
m_outPlug.SetRedraw(TRUE);
|
||
|
m_outPlug.Invalidate(FALSE);
|
||
|
m_plugParam.Invalidate(FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void LFOPluginEditor::InitSlider(CSliderCtrl &slider, LFOPlugin::Parameters param)
|
||
|
{
|
||
|
slider.SetRange(0, SLIDER_GRANULARITY);
|
||
|
slider.SetTicFreq(SLIDER_GRANULARITY / 10);
|
||
|
SetSliderValue(slider, m_lfoPlugin.GetParameter(param));
|
||
|
SetSliderText(param);
|
||
|
}
|
||
|
|
||
|
|
||
|
void LFOPluginEditor::SetSliderText(LFOPlugin::Parameters param)
|
||
|
{
|
||
|
CString s = m_lfoPlugin.GetParamName(param) + _T(": ") + m_lfoPlugin.GetFormattedParamValue(param);
|
||
|
SetDlgItemText(IDC_STATIC1 + param, s);
|
||
|
}
|
||
|
|
||
|
|
||
|
void LFOPluginEditor::SetSliderValue(CSliderCtrl &slider, float value)
|
||
|
{
|
||
|
slider.SetPos(mpt::saturate_round<int>(value * SLIDER_GRANULARITY));
|
||
|
}
|
||
|
|
||
|
|
||
|
float LFOPluginEditor::GetSliderValue(CSliderCtrl &slider)
|
||
|
{
|
||
|
float value = slider.GetPos() / static_cast<float>(SLIDER_GRANULARITY);
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
|
||
|
void LFOPluginEditor::OnHScroll(UINT nCode, UINT nPos, CScrollBar *pSB)
|
||
|
{
|
||
|
CAbstractVstEditor::OnHScroll(nCode, nPos, pSB);
|
||
|
if(!m_locked && nCode != SB_ENDSCROLL && pSB != nullptr)
|
||
|
{
|
||
|
auto slider = reinterpret_cast<CSliderCtrl *>(pSB);
|
||
|
LFOPlugin::Parameters param;
|
||
|
if(slider == &m_amplitudeSlider)
|
||
|
param = LFOPlugin::kAmplitude;
|
||
|
else if(slider == &m_offsetSlider)
|
||
|
param = LFOPlugin::kOffset;
|
||
|
else if(slider == &m_frequencySlider)
|
||
|
param = LFOPlugin::kFrequency;
|
||
|
else
|
||
|
return;
|
||
|
|
||
|
float value = GetSliderValue(*slider);
|
||
|
m_lfoPlugin.SetParameter(param, value);
|
||
|
m_lfoPlugin.AutomateParameter(param);
|
||
|
SetSliderText(param);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void LFOPluginEditor::OnPolarityChanged()
|
||
|
{
|
||
|
if(!m_locked)
|
||
|
{
|
||
|
m_lfoPlugin.m_polarity = IsDlgButtonChecked(IDC_CHECK1) != BST_UNCHECKED;
|
||
|
m_lfoPlugin.AutomateParameter(LFOPlugin::kPolarity);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void LFOPluginEditor::OnTempoSyncChanged()
|
||
|
{
|
||
|
if(!m_locked)
|
||
|
{
|
||
|
m_lfoPlugin.m_tempoSync = IsDlgButtonChecked(IDC_CHECK2) != BST_UNCHECKED;
|
||
|
m_lfoPlugin.RecalculateFrequency();
|
||
|
m_lfoPlugin.AutomateParameter(LFOPlugin::kTempoSync);
|
||
|
InitSlider(m_frequencySlider, LFOPlugin::kFrequency);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void LFOPluginEditor::OnBypassChanged()
|
||
|
{
|
||
|
if(!m_locked)
|
||
|
{
|
||
|
m_lfoPlugin.m_bypassed = IsDlgButtonChecked(IDC_CHECK3) != BST_UNCHECKED;
|
||
|
m_lfoPlugin.AutomateParameter(LFOPlugin::kBypassed);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void LFOPluginEditor::OnLoopModeChanged()
|
||
|
{
|
||
|
if(!m_locked)
|
||
|
{
|
||
|
m_lfoPlugin.m_oneshot = IsDlgButtonChecked(IDC_CHECK4) != BST_UNCHECKED;
|
||
|
m_lfoPlugin.AutomateParameter(LFOPlugin::kLoopMode);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void LFOPluginEditor::OnWaveformChanged(UINT nID)
|
||
|
{
|
||
|
if(!m_locked)
|
||
|
{
|
||
|
m_lfoPlugin.m_waveForm = static_cast<LFOPlugin::LFOWaveform>(nID - IDC_RADIO1);
|
||
|
m_lfoPlugin.AutomateParameter(LFOPlugin::kWaveform);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void LFOPluginEditor::OnPlugParameterChanged()
|
||
|
{
|
||
|
if(!m_locked)
|
||
|
{
|
||
|
CheckRadioButton(IDC_RADIO7, IDC_RADIO8, IDC_RADIO7);
|
||
|
OnParameterChanged();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void LFOPluginEditor::OnMidiCCChanged()
|
||
|
{
|
||
|
if(!m_locked)
|
||
|
{
|
||
|
CheckRadioButton(IDC_RADIO7, IDC_RADIO8, IDC_RADIO8);
|
||
|
OnParameterChanged();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void LFOPluginEditor::OnParameterChanged()
|
||
|
{
|
||
|
if(!m_locked)
|
||
|
{
|
||
|
m_locked = true;
|
||
|
PlugParamIndex param = 0;
|
||
|
bool outputToCC = IsDlgButtonChecked(IDC_RADIO8) != BST_UNCHECKED;
|
||
|
if(outputToCC)
|
||
|
{
|
||
|
param = ((Clamp(GetDlgItemInt(IDC_EDIT1), 1u, 16u) - 1) << 8);
|
||
|
if(m_lfoPlugin.m_outputToCC || m_midiCC.GetCurSel() >= 0)
|
||
|
param |= (m_midiCC.GetCurSel() & 0x7F);
|
||
|
} else
|
||
|
{
|
||
|
if(!m_lfoPlugin.m_outputToCC || m_plugParam.GetCurSel() >= 0)
|
||
|
param = static_cast<PlugParamIndex>(m_plugParam.GetItemData(m_plugParam.GetCurSel()));
|
||
|
}
|
||
|
m_lfoPlugin.m_outputToCC = outputToCC;
|
||
|
m_lfoPlugin.m_outputParam = param;
|
||
|
m_lfoPlugin.SetModified();
|
||
|
m_locked = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void LFOPluginEditor::OnOutputPlugChanged()
|
||
|
{
|
||
|
if(!m_locked)
|
||
|
{
|
||
|
PLUGINDEX plug = static_cast<PLUGINDEX>(m_outPlug.GetItemData(m_outPlug.GetCurSel()));
|
||
|
if(plug > m_lfoPlugin.GetSlot())
|
||
|
{
|
||
|
m_lfoPlugin.GetSoundFile().m_MixPlugins[m_lfoPlugin.GetSlot()].SetOutputPlugin(plug);
|
||
|
m_lfoPlugin.SetModified();
|
||
|
UpdateParamDisplays();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void LFOPluginEditor::OnPluginEditor()
|
||
|
{
|
||
|
std::vector<IMixPlugin *> plug;
|
||
|
if(m_lfoPlugin.GetOutputPlugList(plug) && plug.front() != nullptr)
|
||
|
{
|
||
|
plug.front()->ToggleEditor();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
LRESULT LFOPluginEditor::OnUpdateParam(WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
if(wParam == m_lfoPlugin.GetSlot())
|
||
|
{
|
||
|
UpdateParam(static_cast<int32>(lParam));
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
OPENMPT_NAMESPACE_END
|