/* * 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(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().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(value * SLIDER_GRANULARITY)); } float LFOPluginEditor::GetSliderValue(CSliderCtrl &slider) { float value = slider.GetPos() / static_cast(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(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(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(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(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 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(lParam)); } return 0; } OPENMPT_NAMESPACE_END