123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506 |
- /*
- * MIDIMappingDialog.cpp
- * ---------------------
- * Purpose: Implementation of OpenMPT's MIDI mapping dialog, for mapping incoming MIDI messages to plugin parameters.
- * 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 "Mainfrm.h"
- #include "Moddoc.h"
- #include "MIDIMappingDialog.h"
- #include "InputHandler.h"
- #include "../soundlib/MIDIEvents.h"
- #include "../soundlib/mod_specifications.h"
- #include "../soundlib/plugins/PlugInterface.h"
- #include "../common/mptStringBuffer.h"
- #ifndef NO_PLUGINS
- OPENMPT_NAMESPACE_BEGIN
- CMIDIMappingDialog::CMIDIMappingDialog(CWnd *pParent, CSoundFile &rSndfile)
- : CDialog(IDD_MIDIPARAMCONTROL, pParent)
- , m_sndFile(rSndfile)
- , m_rMIDIMapper(m_sndFile.GetMIDIMapper())
- {
- CMainFrame::GetInputHandler()->Bypass(true);
- oldMIDIRecondWnd = CMainFrame::GetMainFrame()->GetMidiRecordWnd();
- }
- CMIDIMappingDialog::~CMIDIMappingDialog()
- {
- CMainFrame::GetMainFrame()->SetMidiRecordWnd(oldMIDIRecondWnd);
- CMainFrame::GetInputHandler()->Bypass(false);
- }
- void CMIDIMappingDialog::DoDataExchange(CDataExchange* pDX)
- {
- CDialog::DoDataExchange(pDX);
- DDX_Control(pDX, IDC_COMBO_CONTROLLER, m_ControllerCBox);
- DDX_Control(pDX, IDC_COMBO_PLUGIN, m_PluginCBox);
- DDX_Control(pDX, IDC_COMBO_PARAM, m_PlugParamCBox);
- DDX_Control(pDX, IDC_LIST1, m_List);
- DDX_Control(pDX, IDC_COMBO_CHANNEL, m_ChannelCBox);
- DDX_Control(pDX, IDC_COMBO_EVENT, m_EventCBox);
- DDX_Control(pDX, IDC_SPINMOVEMAPPING, m_SpinMoveMapping);
- }
- BEGIN_MESSAGE_MAP(CMIDIMappingDialog, CDialog)
- ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST1, &CMIDIMappingDialog::OnSelectionChanged)
- ON_BN_CLICKED(IDC_CHECKACTIVE, &CMIDIMappingDialog::OnBnClickedCheckactive)
- ON_BN_CLICKED(IDC_CHECKCAPTURE, &CMIDIMappingDialog::OnBnClickedCheckCapture)
- ON_CBN_SELCHANGE(IDC_COMBO_CONTROLLER, &CMIDIMappingDialog::OnCbnSelchangeComboController)
- ON_CBN_SELCHANGE(IDC_COMBO_CHANNEL, &CMIDIMappingDialog::OnCbnSelchangeComboChannel)
- ON_CBN_SELCHANGE(IDC_COMBO_PLUGIN, &CMIDIMappingDialog::OnCbnSelchangeComboPlugin)
- ON_CBN_SELCHANGE(IDC_COMBO_PARAM, &CMIDIMappingDialog::OnCbnSelchangeComboParam)
- ON_CBN_SELCHANGE(IDC_COMBO_EVENT, &CMIDIMappingDialog::OnCbnSelchangeComboEvent)
- ON_BN_CLICKED(IDC_BUTTON_ADD, &CMIDIMappingDialog::OnBnClickedButtonAdd)
- ON_BN_CLICKED(IDC_BUTTON_REPLACE, &CMIDIMappingDialog::OnBnClickedButtonReplace)
- ON_BN_CLICKED(IDC_BUTTON_REMOVE, &CMIDIMappingDialog::OnBnClickedButtonRemove)
- ON_MESSAGE(WM_MOD_MIDIMSG, &CMIDIMappingDialog::OnMidiMsg)
- ON_NOTIFY(UDN_DELTAPOS, IDC_SPINMOVEMAPPING, &CMIDIMappingDialog::OnDeltaposSpinmovemapping)
- ON_BN_CLICKED(IDC_CHECK_PATRECORD, &CMIDIMappingDialog::OnBnClickedCheckPatRecord)
- ON_NOTIFY_EX(TTN_NEEDTEXT, 0, &CMIDIMappingDialog::OnToolTipNotify)
- END_MESSAGE_MAP()
- LRESULT CMIDIMappingDialog::OnMidiMsg(WPARAM dwMidiDataParam, LPARAM)
- {
- uint32 midiData = static_cast<uint32>(dwMidiDataParam);
- if(IsDlgButtonChecked(IDC_CHECK_MIDILEARN))
- {
- for(int i = 0; i < m_EventCBox.GetCount(); i++)
- {
- if(static_cast<MIDIEvents::EventType>(m_EventCBox.GetItemData(i)) == MIDIEvents::GetTypeFromEvent(midiData))
- {
- m_ChannelCBox.SetCurSel(1 + MIDIEvents::GetChannelFromEvent(midiData));
- m_EventCBox.SetCurSel(i);
- if(MIDIEvents::GetTypeFromEvent(midiData) == MIDIEvents::evControllerChange)
- {
- uint8 cc = MIDIEvents::GetDataByte1FromEvent(midiData);
- if(m_lastCC >= 32 || cc != m_lastCC + 32)
- {
- // Ignore second CC message of 14-bit CC.
- m_ControllerCBox.SetCurSel(cc);
- }
- m_lastCC = cc;
- }
- OnCbnSelchangeComboChannel();
- OnCbnSelchangeComboEvent();
- OnCbnSelchangeComboController();
- break;
- }
- }
- }
- return 1;
- }
- BOOL CMIDIMappingDialog::OnInitDialog()
- {
- CDialog::OnInitDialog();
- // Add events
- m_EventCBox.SetItemData(m_EventCBox.AddString(_T("Controller Change")), MIDIEvents::evControllerChange);
- m_EventCBox.SetItemData(m_EventCBox.AddString(_T("Polyphonic Aftertouch")), MIDIEvents::evPolyAftertouch);
- m_EventCBox.SetItemData(m_EventCBox.AddString(_T("Channel Aftertouch")), MIDIEvents::evChannelAftertouch);
-
- // Add controller names
- CString s;
- for(uint8 i = MIDIEvents::MIDICC_start; i <= MIDIEvents::MIDICC_end; i++)
- {
- s.Format(_T("%3u "), i);
- s += mpt::ToCString(mpt::Charset::UTF8, MIDIEvents::MidiCCNames[i]);
- m_ControllerCBox.AddString(s);
- }
- // Add plugin names
- AddPluginNamesToCombobox(m_PluginCBox, m_sndFile.m_MixPlugins);
- // Initialize mapping table
- static constexpr CListCtrlEx::Header headers[] =
- {
- { _T("Channel"), 58, LVCFMT_LEFT },
- { _T("Event / Controller"), 176, LVCFMT_LEFT },
- { _T("Plugin"), 120, LVCFMT_LEFT },
- { _T("Parameter"), 120, LVCFMT_LEFT },
- { _T("Capture"), 40, LVCFMT_LEFT },
- { _T("Pattern Record"), 40, LVCFMT_LEFT }
- };
- m_List.SetHeaders(headers);
- m_List.SetExtendedStyle(m_List.GetExtendedStyle() | LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
- // Add directives to list
- for(size_t i = 0; i < m_rMIDIMapper.GetCount(); i++)
- {
- InsertItem(m_rMIDIMapper.GetDirective(i), int(i));
- }
- if(m_rMIDIMapper.GetCount() > 0 && m_Setting.IsDefault())
- {
- SelectItem(0);
- OnSelectionChanged();
- } else
- {
- UpdateDialog();
- }
- GetDlgItem(IDC_CHECK_PATRECORD)->EnableWindow((m_sndFile.GetType() == MOD_TYPE_MPT) ? TRUE : FALSE);
- CMainFrame::GetMainFrame()->SetMidiRecordWnd(GetSafeHwnd());
- CheckDlgButton(IDC_CHECK_MIDILEARN, BST_CHECKED);
- EnableToolTips(TRUE);
- return TRUE; // return TRUE unless you set the focus to a control
- }
- int CMIDIMappingDialog::InsertItem(const CMIDIMappingDirective &m, int insertAt)
- {
- CString s;
- if(m.GetAnyChannel())
- s = _T("Any");
- else
- s.Format(_T("Ch %u"), m.GetChannel());
- insertAt = m_List.InsertItem(insertAt, s);
- if(insertAt == -1)
- return -1;
- m_List.SetCheck(insertAt, m.IsActive() ? TRUE : FALSE);
- switch(m.GetEvent())
- {
- case MIDIEvents::evControllerChange:
- s.Format(_T("CC %u: "), m.GetController());
- if(m.GetController() <= MIDIEvents::MIDICC_end) s += mpt::ToCString(mpt::Charset::UTF8, MIDIEvents::MidiCCNames[m.GetController()]);
- break;
- case MIDIEvents::evPolyAftertouch:
- s = _T("Polyphonic Aftertouch"); break;
- case MIDIEvents::evChannelAftertouch:
- s = _T("Channel Aftertouch"); break;
- default:
- s.Format(_T("0x%02X"), m.GetEvent()); break;
- }
- m_List.SetItemText(insertAt, 1, s);
- const PLUGINDEX plugindex = m.GetPlugIndex();
- if(plugindex > 0 && plugindex < MAX_MIXPLUGINS)
- {
- const SNDMIXPLUGIN &plug = m_sndFile.m_MixPlugins[plugindex - 1];
- s.Format(_T("FX%u: "), plugindex);
- s += mpt::ToCString(plug.GetName());
- m_List.SetItemText(insertAt, 2, s);
- if(plug.pMixPlugin != nullptr)
- s = plug.pMixPlugin->GetFormattedParamName(m.GetParamIndex());
- else
- s.Empty();
- m_List.SetItemText(insertAt, 3, s);
- }
- m_List.SetItemText(insertAt, 4, m.GetCaptureMIDI() ? _T("Capt") : _T(""));
- m_List.SetItemText(insertAt, 5, m.GetAllowPatternEdit() ? _T("Rec") : _T(""));
- return insertAt;
- }
- void CMIDIMappingDialog::SelectItem(int i)
- {
- m_List.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED);
- m_List.SetSelectionMark(i);
- }
- void CMIDIMappingDialog::UpdateDialog(int selItem)
- {
- CheckDlgButton(IDC_CHECKACTIVE, m_Setting.IsActive() ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(IDC_CHECKCAPTURE, m_Setting.GetCaptureMIDI() ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(IDC_CHECK_PATRECORD, m_Setting.GetAllowPatternEdit() ? BST_CHECKED : BST_UNCHECKED);
- m_ChannelCBox.SetCurSel(m_Setting.GetChannel());
- m_EventCBox.SetCurSel(-1);
- for(int i = 0; i < m_EventCBox.GetCount(); i++)
- {
- if(m_EventCBox.GetItemData(i) == m_Setting.GetEvent())
- {
- m_EventCBox.SetCurSel(i);
- break;
- }
- }
- m_ControllerCBox.SetCurSel(m_Setting.GetController());
- m_PluginCBox.SetCurSel(m_Setting.GetPlugIndex() - 1);
- m_PlugParamCBox.SetCurSel(m_Setting.GetParamIndex());
- UpdateEvent();
- UpdateParameters();
- bool enableMover = selItem >= 0;
- if(enableMover)
- {
- const bool previousEqual = (selItem > 0 && m_rMIDIMapper.AreOrderEqual(selItem - 1, selItem));
- const bool nextEqual = (selItem + 1 < m_List.GetItemCount() && m_rMIDIMapper.AreOrderEqual(selItem, selItem + 1));
- enableMover = previousEqual || nextEqual;
- }
- m_SpinMoveMapping.EnableWindow(enableMover);
- }
- void CMIDIMappingDialog::UpdateEvent()
- {
- m_ControllerCBox.EnableWindow(m_Setting.GetEvent() == MIDIEvents::evControllerChange ? TRUE : FALSE);
- if(m_Setting.GetEvent() != MIDIEvents::evControllerChange)
- m_ControllerCBox.SetCurSel(0);
- }
- void CMIDIMappingDialog::UpdateParameters()
- {
- m_PlugParamCBox.SetRedraw(FALSE);
- m_PlugParamCBox.ResetContent();
- AddPluginParameternamesToCombobox(m_PlugParamCBox, m_sndFile.m_MixPlugins[m_Setting.GetPlugIndex() - 1]);
- m_PlugParamCBox.SetCurSel(m_Setting.GetParamIndex());
- m_PlugParamCBox.SetRedraw(TRUE);
- m_PlugParamCBox.Invalidate();
- }
- void CMIDIMappingDialog::OnSelectionChanged(NMHDR *pNMHDR, LRESULT * /*pResult*/)
- {
- int i;
- if(pNMHDR != nullptr)
- {
- NMLISTVIEW *nmlv = (NMLISTVIEW *)pNMHDR;
- if(((nmlv->uOldState ^ nmlv->uNewState) & INDEXTOSTATEIMAGEMASK(3)) != 0 && nmlv->uOldState != 0)
- {
- // Check box status changed
- CMIDIMappingDirective m = m_rMIDIMapper.GetDirective(nmlv->iItem);
- m.SetActive(nmlv->uNewState == INDEXTOSTATEIMAGEMASK(2));
- m_rMIDIMapper.SetDirective(nmlv->iItem, m);
- SetModified();
- if(nmlv->iItem == m_List.GetSelectionMark())
- CheckDlgButton(IDC_CHECKACTIVE, nmlv->uNewState == INDEXTOSTATEIMAGEMASK(2) ? BST_CHECKED : BST_UNCHECKED);
- }
- if(nmlv->uNewState & LVIS_SELECTED)
- i = nmlv->iItem;
- else
- return;
- } else
- {
- i = m_List.GetSelectionMark();
- }
- if(i < 0 || (size_t)i >= m_rMIDIMapper.GetCount()) return;
- m_Setting = m_rMIDIMapper.GetDirective(i);
- UpdateDialog(i);
- }
- void CMIDIMappingDialog::OnBnClickedCheckactive()
- {
- m_Setting.SetActive(IsDlgButtonChecked(IDC_CHECKACTIVE) == BST_CHECKED);
- }
- void CMIDIMappingDialog::OnBnClickedCheckCapture()
- {
- m_Setting.SetCaptureMIDI(IsDlgButtonChecked(IDC_CHECKCAPTURE) == BST_CHECKED);
- }
- void CMIDIMappingDialog::OnBnClickedCheckPatRecord()
- {
- m_Setting.SetAllowPatternEdit(IsDlgButtonChecked(IDC_CHECK_PATRECORD) == BST_CHECKED);
- }
- void CMIDIMappingDialog::OnCbnSelchangeComboController()
- {
- m_Setting.SetController(m_ControllerCBox.GetCurSel());
- }
- void CMIDIMappingDialog::OnCbnSelchangeComboChannel()
- {
- m_Setting.SetChannel(m_ChannelCBox.GetCurSel());
- }
- void CMIDIMappingDialog::OnCbnSelchangeComboPlugin()
- {
- int i = m_PluginCBox.GetCurSel();
- if(i < 0 || i >= MAX_MIXPLUGINS) return;
- m_Setting.SetPlugIndex(i+1);
- UpdateParameters();
- }
- void CMIDIMappingDialog::OnCbnSelchangeComboParam()
- {
- m_Setting.SetParamIndex(m_PlugParamCBox.GetCurSel());
- }
- void CMIDIMappingDialog::OnCbnSelchangeComboEvent()
- {
- uint8 eventType = static_cast<uint8>(m_EventCBox.GetItemData(m_EventCBox.GetCurSel()));
- m_Setting.SetEvent(eventType);
- UpdateEvent();
- }
- void CMIDIMappingDialog::OnBnClickedButtonAdd()
- {
- if(m_sndFile.GetModSpecifications().MIDIMappingDirectivesMax <= m_rMIDIMapper.GetCount())
- {
- Reporting::Information("Maximum amount of MIDI Mapping directives reached.");
- } else
- {
- const size_t i = m_rMIDIMapper.AddDirective(m_Setting);
- SetModified();
- SelectItem(InsertItem(m_Setting, static_cast<int>(i)));
- OnSelectionChanged();
- }
- }
- void CMIDIMappingDialog::OnBnClickedButtonReplace()
- {
- const int i = m_List.GetSelectionMark();
- if(i >= 0 && (size_t)i < m_rMIDIMapper.GetCount())
- {
- const size_t newIndex = m_rMIDIMapper.SetDirective(i, m_Setting);
- SetModified();
- m_List.DeleteItem(i);
- SelectItem(InsertItem(m_Setting, static_cast<int>(newIndex)));
- OnSelectionChanged();
- }
- }
- void CMIDIMappingDialog::OnBnClickedButtonRemove()
- {
- int i = m_List.GetSelectionMark();
- if(i >= 0 && (size_t)i < m_rMIDIMapper.GetCount())
- {
- m_rMIDIMapper.RemoveDirective(i);
- SetModified();
- m_List.DeleteItem(i);
- if(m_List.GetItemCount() > 0)
- {
- if(i < m_List.GetItemCount())
- SelectItem(i);
- else
- SelectItem(i - 1);
- }
- i = m_List.GetSelectionMark();
- if(i >= 0 && (size_t)i < m_rMIDIMapper.GetCount())
- m_Setting = m_rMIDIMapper.GetDirective(i);
- OnSelectionChanged();
- }
- }
- void CMIDIMappingDialog::OnDeltaposSpinmovemapping(NMHDR *pNMHDR, LRESULT *pResult)
- {
- const int index = m_List.GetSelectionMark();
- if(index < 0 || index >= m_List.GetItemCount()) return;
- LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
- int newIndex = -1;
- if(pNMUpDown->iDelta < 0) //Up
- {
- if(index - 1 >= 0 && m_rMIDIMapper.AreOrderEqual(index-1, index))
- {
- newIndex = index - 1;
- }
- } else //Down
- {
- if(index + 1 < m_List.GetItemCount() && m_rMIDIMapper.AreOrderEqual(index, index+1))
- {
- newIndex = index + 1;
- }
- }
- if(newIndex != -1)
- {
- m_rMIDIMapper.Swap(size_t(newIndex), size_t(index));
- m_List.DeleteItem(index);
- InsertItem(m_rMIDIMapper.GetDirective(newIndex), newIndex);
- SelectItem(newIndex);
- }
-
- *pResult = 0;
- }
- BOOL CMIDIMappingDialog::OnToolTipNotify(UINT, NMHDR * pNMHDR, LRESULT *)
- {
- TOOLTIPTEXT *pTTT = (TOOLTIPTEXT*)pNMHDR;
- const TCHAR *text = _T("");
- UINT_PTR nID = pNMHDR->idFrom;
- if(pTTT->uFlags & TTF_IDISHWND)
- {
- // idFrom is actually the HWND of the tool
- nID = ::GetDlgCtrlID((HWND)nID);
- }
- switch(nID)
- {
- case IDC_CHECKCAPTURE:
- text = _T("The event is not passed to any further MIDI mappings or recording facilities.");
- break;
- case IDC_CHECKACTIVE:
- text = _T("The MIDI mapping is enabled and can be processed.");
- break;
- case IDC_CHECK_PATRECORD:
- text = _T("Parameter changes are recorded into patterns as Parameter Control events.");
- break;
- case IDC_CHECK_MIDILEARN:
- text = _T("Listens to incoming MIDI data to automatically fill in the appropriate data.");
- break;
- case IDC_SPINMOVEMAPPING:
- text = _T("Change the processing order of the current selected MIDI mapping.");
- break;
- case IDC_COMBO_CHANNEL:
- text = _T("The MIDI channel to listen on for this event.");
- break;
- case IDC_COMBO_EVENT:
- text = _T("The MIDI event to listen for.");
- break;
- case IDC_COMBO_CONTROLLER:
- text = _T("The MIDI controler to listen for.");
- break;
- }
- mpt::String::WriteWinBuf(pTTT->szText) = mpt::winstring(text);
- return TRUE;
- }
- void CMIDIMappingDialog::SetModified()
- {
- if(m_sndFile.GetpModDoc() != nullptr)
- m_sndFile.GetpModDoc()->SetModified();
- }
- OPENMPT_NAMESPACE_END
- #endif // NO_PLUGINS
|