1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762 |
- #include "stdafx.h"
- #ifdef MPT_WITH_VST
- #include "Vstplug.h"
- #ifdef MODPLUG_TRACKER
- #include "Moddoc.h"
- #include "Mainfrm.h"
- #include "AbstractVstEditor.h"
- #include "VSTEditor.h"
- #include "DefaultVstEditor.h"
- #include "ExceptionHandler.h"
- #endif
- #include "../soundlib/Sndfile.h"
- #include "../soundlib/MIDIEvents.h"
- #include "MIDIMappingDialog.h"
- #include "../common/mptStringBuffer.h"
- #include "FileDialog.h"
- #include "../pluginBridge/BridgeWrapper.h"
- #include "../pluginBridge/BridgeOpCodes.h"
- #include "../soundlib/plugins/OpCodes.h"
- #include "../soundlib/plugins/PluginManager.h"
- #include "../misc/mptOSException.h"
- using namespace Vst;
- DECLARE_FLAGSET(Vst::VstTimeInfoFlags)
- OPENMPT_NAMESPACE_BEGIN
- static VstTimeInfo g_timeInfoFallback = { 0 };
- #ifdef MPT_ALL_LOGGING
- #define VST_LOG
- #endif
- using VstCrash = Windows::SEH::Code;
- bool CVstPlugin::MaskCrashes() noexcept
- {
- return m_maskCrashes;
- }
- template <typename Tfn>
- DWORD CVstPlugin::SETryOrError(bool maskCrashes, Tfn fn)
- {
- DWORD exception = 0;
- if(maskCrashes)
- {
- exception = Windows::SEH::TryOrError(fn);
- if(exception)
- {
- ExceptionHandler::TaintProcess(ExceptionHandler::TaintReason::Plugin);
- }
- } else
- {
- fn();
- }
- return exception;
- }
- template <typename Tfn>
- DWORD CVstPlugin::SETryOrError(Tfn fn)
- {
- DWORD exception = 0;
- if(MaskCrashes())
- {
- exception = Windows::SEH::TryOrError(fn);
- if(exception)
- {
- ExceptionHandler::TaintProcess(ExceptionHandler::TaintReason::Plugin);
- }
- } else
- {
- #ifdef MODPLUG_TRACKER
- ExceptionHandler::ContextSetter ectxguard{&m_Ectx};
- #endif
- fn();
- }
- return exception;
- }
- AEffect *CVstPlugin::LoadPlugin(bool maskCrashes, VSTPluginLib &plugin, HMODULE &library, BridgeMode bridgeMode)
- {
- const mpt::PathString &pluginPath = plugin.dllPath;
- AEffect *effect = nullptr;
- library = nullptr;
- const bool isNative = plugin.IsNative(false);
- if(bridgeMode != BridgeMode::Automatic || plugin.useBridge || !isNative)
- {
- if(bridgeMode == BridgeMode::DetectRequiredBridgeMode)
- {
-
- plugin.modernBridge = true;
- try
- {
- effect = BridgeWrapper::Create(plugin, false);
- if(effect != nullptr)
- {
- return effect;
- }
- } catch(BridgeWrapper::BridgeNotFoundException &)
- {
- } catch(BridgeWrapper::BridgeException &)
- {
- }
-
- plugin.useBridge = true;
- plugin.modernBridge = false;
- }
- try
- {
- effect = BridgeWrapper::Create(plugin, bridgeMode == BridgeMode::DetectRequiredBridgeMode);
- if(effect != nullptr)
- {
- return effect;
- }
- } catch(BridgeWrapper::BridgeNotFoundException &)
- {
-
- if(!isNative)
- {
- Reporting::Error("Could not locate the plugin bridge executable, which is required for running non-native plugins.", "OpenMPT Plugin Bridge");
- return nullptr;
- }
- } catch(BridgeWrapper::BridgeException &e)
- {
-
- if(isNative)
- {
- const CString msg =
- MPT_CFORMAT("The following error occurred while trying to load\n{}\n\n{}\n\nDo you want to try to load the plugin natively?")
- (plugin.dllPath, mpt::get_exception_text<mpt::ustring>(e));
- if(Reporting::Confirm(msg, _T("OpenMPT Plugin Bridge")) == cnfNo)
- {
- return nullptr;
- }
- } else
- {
- Reporting::Error(mpt::get_exception_text<mpt::ustring>(e), "OpenMPT Plugin Bridge");
- return nullptr;
- }
- }
-
-
- plugin.useBridge = false;
- plugin.modernBridge = true;
- }
- {
- #ifdef MODPLUG_TRACKER
- ExceptionHandler::Context ectx{ MPT_UFORMAT("VST Plugin: {}")(plugin.dllPath.ToUnicode()) };
- ExceptionHandler::ContextSetter ectxguard{&ectx};
- #endif
- DWORD exception = SETryOrError(maskCrashes, [&](){ library = LoadLibrary(pluginPath.AsNative().c_str()); });
- if(exception)
- {
- CVstPluginManager::ReportPlugException(MPT_UFORMAT("Exception caught while loading {}")(pluginPath));
- return nullptr;
- }
- }
- if(library == nullptr)
- {
- DWORD error = GetLastError();
- if(error == ERROR_MOD_NOT_FOUND)
- {
- return nullptr;
- } else if(error == ERROR_DLL_INIT_FAILED)
- {
-
-
-
-
- CVstPluginManager::ReportPlugException(U_("Plugin initialization failed. This may be caused by loading too many plugins.\nTry activating the Plugin Bridge for this plugin."));
- }
- #ifdef _DEBUG
- mpt::ustring buf = MPT_UFORMAT("Warning: encountered problem when loading plugin dll. Error {}: {}")
- ( mpt::ufmt::hex(error)
- , mpt::ToUnicode(mpt::windows::GetErrorMessage(error))
- );
- Reporting::Error(buf, "DEBUG: Error when loading plugin dll");
- #endif
- }
- if(library != nullptr && library != INVALID_HANDLE_VALUE)
- {
- auto pMainProc = (Vst::MainProc)GetProcAddress(library, "VSTPluginMain");
- if(pMainProc == nullptr)
- {
- pMainProc = (Vst::MainProc)GetProcAddress(library, "main");
- }
- if(pMainProc != nullptr)
- {
- #ifdef MODPLUG_TRACKER
- ExceptionHandler::Context ectx{ MPT_UFORMAT("VST Plugin: {}")(plugin.dllPath.ToUnicode()) };
- ExceptionHandler::ContextSetter ectxguard{&ectx};
- #endif
- DWORD exception = SETryOrError(maskCrashes, [&](){ effect = pMainProc(CVstPlugin::MasterCallBack); });
- if(exception)
- {
- return nullptr;
- }
- } else
- {
- #ifdef VST_LOG
- MPT_LOG_GLOBAL(LogDebug, "VST", MPT_UFORMAT("Entry point not found! (handle={})")(mpt::ufmt::PTR(library)));
- #endif
- return nullptr;
- }
- }
- return effect;
- }
- static void operator|= (Vst::VstTimeInfoFlags &lhs, Vst::VstTimeInfoFlags rhs)
- {
- lhs = (lhs | rhs).as_enum();
- }
- intptr_t VSTCALLBACK CVstPlugin::MasterCallBack(AEffect *effect, VstOpcodeToHost opcode, int32 index, intptr_t value, void *ptr, float opt)
- {
- #ifdef VST_LOG
- MPT_LOG_GLOBAL(LogDebug, "VST", MPT_UFORMAT("VST plugin to host: Eff: {}, Opcode = {}, Index = {}, Value = {}, PTR = {}, OPT = {}\n")(
- mpt::ufmt::PTR(effect), mpt::ufmt::val(opcode),
- mpt::ufmt::val(index), mpt::ufmt::PTR(value), mpt::ufmt::PTR(ptr), mpt::ufmt::flt(opt, 3)));
- MPT_TRACE();
- #else
- MPT_UNREFERENCED_PARAMETER(opt);
- #endif
- enum
- {
- HostDoNotKnow = 0,
- HostCanDo = 1,
- HostCanNotDo = -1
- };
- CVstPlugin *pVstPlugin = nullptr;
- if(effect != nullptr)
- {
- pVstPlugin = static_cast<CVstPlugin *>(effect->reservedForHost1);
- }
- switch(opcode)
- {
-
- case audioMasterAutomate:
-
-
-
- if(pVstPlugin != nullptr && pVstPlugin->m_isInitialized && pVstPlugin->CanAutomateParameter(index))
- {
-
- pVstPlugin->AutomateParameter((PlugParamIndex)index);
- }
- return 0;
-
- case audioMasterVersion:
- return kVstVersion;
-
-
- case audioMasterCurrentId:
- return (effect != nullptr) ? effect->uniqueID : 0;
-
- case audioMasterIdle:
- theApp.GetPluginManager()->OnIdle();
- return 0;
-
-
-
- case audioMasterPinConnected:
- if (value)
- return (index < 2) ? 0 : 1;
- else
- return (index < 2) ? 0 : 1;
-
-
- case audioMasterWantMidi:
- return 1;
-
-
- case audioMasterGetTime:
- if(pVstPlugin)
- {
- VstTimeInfo &timeInfo = pVstPlugin->timeInfo;
- MemsetZero(timeInfo);
- timeInfo.sampleRate = pVstPlugin->m_nSampleRate;
- CSoundFile &sndFile = pVstPlugin->GetSoundFile();
- if(pVstPlugin->IsSongPlaying())
- {
- timeInfo.flags |= kVstTransportPlaying;
- if(pVstPlugin->GetSoundFile().m_SongFlags[SONG_PATTERNLOOP]) timeInfo.flags |= kVstTransportCycleActive;
- timeInfo.samplePos = sndFile.GetTotalSampleCount();
- if(pVstPlugin->m_positionChanged)
- {
- timeInfo.flags |= kVstTransportChanged;
- pVstPlugin->lastBarStartPos = -1.0;
- }
- } else
- {
- timeInfo.flags |= kVstTransportChanged;
- timeInfo.samplePos = 0;
- pVstPlugin->lastBarStartPos = -1.0;
- }
- if((value & kVstNanosValid))
- {
- timeInfo.flags |= kVstNanosValid;
- timeInfo.nanoSeconds = static_cast<double>(Util::mul32to64_unsigned(timeGetTime(), 1000000));
- }
- if((value & kVstPpqPosValid))
- {
- timeInfo.flags |= kVstPpqPosValid;
- if (timeInfo.flags & kVstTransportPlaying)
- {
- timeInfo.ppqPos = (timeInfo.samplePos / timeInfo.sampleRate) * (sndFile.GetCurrentBPM() / 60.0);
- } else
- {
- timeInfo.ppqPos = 0;
- }
- ROWINDEX rpm = pVstPlugin->GetSoundFile().m_PlayState.m_nCurrentRowsPerMeasure;
- if(!rpm)
- rpm = 4;
- if((pVstPlugin->GetSoundFile().m_PlayState.m_nRow % rpm) == 0)
- {
- pVstPlugin->lastBarStartPos = std::floor(timeInfo.ppqPos);
- }
- if(pVstPlugin->lastBarStartPos >= 0)
- {
- timeInfo.barStartPos = pVstPlugin->lastBarStartPos;
- timeInfo.flags |= kVstBarsValid;
- }
- }
- if((value & kVstTempoValid))
- {
- timeInfo.tempo = sndFile.GetCurrentBPM();
- if (timeInfo.tempo)
- {
- timeInfo.flags |= kVstTempoValid;
- }
- }
- if((value & kVstTimeSigValid))
- {
- timeInfo.flags |= kVstTimeSigValid;
-
-
- ROWINDEX rpb = std::max(sndFile.m_PlayState.m_nCurrentRowsPerBeat, ROWINDEX(1));
- timeInfo.timeSigNumerator = std::max(sndFile.m_PlayState.m_nCurrentRowsPerMeasure, rpb) / rpb;
- timeInfo.timeSigDenominator = 4;
- }
- return ToIntPtr(&timeInfo);
- } else
- {
- MemsetZero(g_timeInfoFallback);
- return ToIntPtr(&g_timeInfoFallback);
- }
-
- case audioMasterProcessEvents:
- if(pVstPlugin != nullptr && ptr != nullptr)
- {
- pVstPlugin->ReceiveVSTEvents(static_cast<VstEvents *>(ptr));
- return 1;
- }
- break;
-
- case audioMasterSetTime:
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: Set Time"));
- break;
-
- case audioMasterTempoAt:
-
- if (pVstPlugin != nullptr)
- {
- return mpt::saturate_round<int32>(pVstPlugin->GetSoundFile().GetCurrentBPM() * 10000);
- }
- return (125 * 10000);
-
- case audioMasterGetNumAutomatableParameters:
-
- if(pVstPlugin != nullptr)
- {
- return pVstPlugin->GetNumParameters();
- }
- break;
-
- case audioMasterGetParameterQuantization:
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: Audio Master Get Parameter Quantization"));
- break;
-
- case audioMasterIOChanged:
- if(pVstPlugin != nullptr)
- {
- CriticalSection cs;
- return pVstPlugin->InitializeIOBuffers() ? 1 : 0;
- }
- break;
-
- case audioMasterNeedIdle:
- if(pVstPlugin != nullptr)
- {
- pVstPlugin->m_needIdle = true;
- }
- return 1;
-
- case audioMasterSizeWindow:
- if(pVstPlugin != nullptr)
- {
- CAbstractVstEditor *pVstEditor = pVstPlugin->GetEditor();
- if (pVstEditor && pVstEditor->IsResizable())
- {
- pVstEditor->SetSize(index, static_cast<int>(value));
- }
- }
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: Size Window"));
- return 1;
- case audioMasterGetSampleRate:
- if(pVstPlugin)
- {
- return pVstPlugin->m_nSampleRate;
- } else
- {
-
- return TrackerSettings::Instance().GetMixerSettings().gdwMixingFreq;
- }
- case audioMasterGetBlockSize:
- return MIXBUFFERSIZE;
- case audioMasterGetInputLatency:
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: Get Input Latency"));
- break;
- case audioMasterGetOutputLatency:
- if(pVstPlugin)
- {
- return mpt::saturate_round<intptr_t>(pVstPlugin->GetOutputLatency() * pVstPlugin->GetSoundFile().GetSampleRate());
- }
- break;
-
- case audioMasterGetPreviousPlug:
- if(pVstPlugin != nullptr)
- {
- std::vector<IMixPlugin *> list;
- if(pVstPlugin->GetInputPlugList(list) != 0)
- {
-
- CVstPlugin *plugin = dynamic_cast<CVstPlugin *>(list[0]);
- if(plugin != nullptr)
- {
- return ToIntPtr(&plugin->m_Effect);
- }
- }
- }
- break;
-
- case audioMasterGetNextPlug:
- if(pVstPlugin != nullptr)
- {
- std::vector<IMixPlugin *> list;
- if(pVstPlugin->GetOutputPlugList(list) != 0)
- {
-
- CVstPlugin *plugin = dynamic_cast<CVstPlugin *>(list[0]);
- if(plugin != nullptr)
- {
- return ToIntPtr(&plugin->m_Effect);
- }
- }
- }
- break;
-
-
- case audioMasterWillReplaceOrAccumulate:
- return 1;
- case audioMasterGetCurrentProcessLevel:
- if(pVstPlugin != nullptr && pVstPlugin->GetSoundFile().IsRenderingToDisc())
- return kVstProcessLevelOffline;
- else
- return kVstProcessLevelRealtime;
- break;
-
- case audioMasterGetAutomationState:
-
-
-
- return kVstAutomationReadWrite;
- case audioMasterOfflineStart:
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: Offlinestart"));
- break;
- case audioMasterOfflineRead:
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: Offlineread"));
- break;
- case audioMasterOfflineWrite:
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: Offlinewrite"));
- break;
- case audioMasterOfflineGetCurrentPass:
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: OfflineGetcurrentpass"));
- break;
- case audioMasterOfflineGetCurrentMetaPass:
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: OfflineGetCurrentMetapass"));
- break;
-
- case audioMasterSetOutputSampleRate:
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: Set Output Sample Rate"));
- break;
-
- case audioMasterGetOutputSpeakerArrangement:
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: Get Output Speaker Arrangement"));
- break;
- case audioMasterGetVendorString:
- strcpy((char *) ptr, TrackerSettings::Instance().vstHostVendorString.Get().c_str());
- return 1;
- case audioMasterGetProductString:
- strcpy((char *) ptr, TrackerSettings::Instance().vstHostProductString.Get().c_str());
- return 1;
- case audioMasterGetVendorVersion:
- return TrackerSettings::Instance().vstHostVendorVersion;
- case audioMasterVendorSpecific:
- return 0;
-
- case audioMasterSetIcon:
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: Set Icon"));
- break;
-
- case audioMasterCanDo:
-
- if(!strcmp((char*)ptr, HostCanDo::sendVstEvents)
- || !strcmp((char *)ptr, HostCanDo::sendVstMidiEvent)
- || !strcmp((char *)ptr, HostCanDo::sendVstTimeInfo)
- || !strcmp((char *)ptr, HostCanDo::receiveVstEvents)
- || !strcmp((char *)ptr, HostCanDo::receiveVstMidiEvent)
- || !strcmp((char *)ptr, HostCanDo::supplyIdle)
- || !strcmp((char *)ptr, HostCanDo::sizeWindow)
- || !strcmp((char *)ptr, HostCanDo::openFileSelector)
- || !strcmp((char *)ptr, HostCanDo::closeFileSelector)
- || !strcmp((char *)ptr, HostCanDo::acceptIOChanges)
- || !strcmp((char *)ptr, HostCanDo::reportConnectionChanges))
- {
- return HostCanDo;
- } else
- {
- return HostCanNotDo;
- }
- case audioMasterGetLanguage:
- return kVstLangEnglish;
-
- case audioMasterOpenWindow:
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: Open Window"));
- break;
-
- case audioMasterCloseWindow:
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: Close Window"));
- break;
-
- case audioMasterGetDirectory:
-
-
-
-
- break;
-
- case audioMasterUpdateDisplay:
- if(pVstPlugin != nullptr)
- {
-
- CAbstractVstEditor *pVstEditor = pVstPlugin->GetEditor();
- if(pVstEditor && ::IsWindow(pVstEditor->m_hWnd))
- {
- pVstEditor->UpdateDisplay();
- }
- }
- return 0;
-
-
- case audioMasterBeginEdit:
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: Begin Edit"));
- break;
-
- case audioMasterEndEdit:
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: End Edit"));
- break;
-
- case audioMasterOpenFileSelector:
-
-
- case audioMasterCloseFileSelector:
- if(pVstPlugin != nullptr && ptr != nullptr)
- {
- return pVstPlugin->VstFileSelector(opcode == audioMasterCloseFileSelector, *static_cast<VstFileSelect *>(ptr));
- }
-
- case audioMasterEditFile:
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: Edit File"));
- break;
-
-
-
- case audioMasterGetChunkFile:
- #ifdef MODPLUG_TRACKER
- if(pVstPlugin && pVstPlugin->GetModDoc())
- {
- mpt::ustring pathStr = TrackerSettings::Instance().pluginProjectPath;
- if(pathStr.empty())
- {
- pathStr = U_("%1");
- }
- const mpt::PathString projectPath = pVstPlugin->GetModDoc()->GetPathNameMpt().GetPath();
- const mpt::PathString projectFile = pVstPlugin->GetModDoc()->GetPathNameMpt().GetFullFileName();
- pathStr = mpt::String::Replace(pathStr, U_("%1"), U_("?1?"));
- pathStr = mpt::String::Replace(pathStr, U_("%2"), U_("?2?"));
- pathStr = mpt::String::Replace(pathStr, U_("?1?"), projectPath.ToUnicode());
- pathStr = mpt::String::Replace(pathStr, U_("?2?"), projectFile.ToUnicode());
- mpt::PathString path = mpt::PathString::FromUnicode(pathStr);
- if(path.empty())
- {
- return 0;
- }
- path.EnsureTrailingSlash();
- ::SHCreateDirectoryEx(NULL, path.AsNative().c_str(), nullptr);
- path += projectFile;
- strcpy(static_cast<char*>(ptr), path.ToLocale().c_str());
- return 1;
- }
- #endif
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: Get Chunk File"));
- break;
-
-
- case audioMasterGetInputSpeakerArrangement:
- MPT_LOG_GLOBAL(LogDebug, "VST", U_("VST plugin to host: Get Input Speaker Arrangement"));
- break;
- }
-
- return 0;
- }
- intptr_t CVstPlugin::VstFileSelector(bool destructor, VstFileSelect &fileSel)
- {
- if(!destructor)
- {
- fileSel.returnMultiplePaths = nullptr;
- fileSel.numReturnPaths = 0;
- fileSel.reserved = 0;
- std::string returnPath;
- if(fileSel.command != kVstDirectorySelect)
- {
-
- std::string extensions, workingDir;
- for(int32 i = 0; i < fileSel.numFileTypes; i++)
- {
- const VstFileType &type = fileSel.fileTypes[i];
- extensions += type.name;
- extensions += "|";
- #if MPT_OS_WINDOWS
- extensions += "*.";
- extensions += type.dosType;
- #elif MPT_OS_MACOSX_OR_IOS
- extensions += "*";
- extensions += type.macType;
- #elif MPT_OS_GENERIC_UNIX
- extensions += "*.";
- extensions += type.unixType;
- #else
- #error Platform-specific code missing
- #endif
- extensions += "|";
- }
- extensions += "|";
- if(fileSel.initialPath != nullptr)
- {
- workingDir = fileSel.initialPath;
- } else
- {
-
-
- }
- FileDialog dlg = OpenFileDialog();
- if(fileSel.command == kVstFileSave)
- {
- dlg = SaveFileDialog();
- } else if(fileSel.command == kVstMultipleFilesLoad)
- {
- dlg = OpenFileDialog().AllowMultiSelect();
- }
- dlg.ExtensionFilter(extensions)
- .WorkingDirectory(mpt::PathString::FromLocale(workingDir))
- .AddPlace(GetPluginFactory().dllPath.GetPath());
- if(!dlg.Show(GetEditor()))
- return 0;
- if(fileSel.command == kVstMultipleFilesLoad)
- {
-
- const auto &files = dlg.GetFilenames();
- fileSel.numReturnPaths = mpt::saturate_cast<int32>(files.size());
- fileSel.returnMultiplePaths = new (std::nothrow) char *[fileSel.numReturnPaths];
- if(!fileSel.returnMultiplePaths)
- return 0;
- for(int32 i = 0; i < fileSel.numReturnPaths; i++)
- {
- const std::string fname_ = files[i].ToLocale();
- char *fname = new (std::nothrow) char[fname_.length() + 1];
- if(fname)
- strcpy(fname, fname_.c_str());
- fileSel.returnMultiplePaths[i] = fname;
- }
- return 1;
- } else
- {
-
-
- if(FourCC("VOPM") == GetUID())
- {
- fileSel.sizeReturnPath = _MAX_PATH;
- }
- returnPath = dlg.GetFirstFile().ToLocale();
- }
- } else
- {
-
- BrowseForFolder dlg(mpt::PathString::FromLocale(fileSel.initialPath != nullptr ? fileSel.initialPath : ""), mpt::ToCString(mpt::Charset::Locale, fileSel.title != nullptr ? fileSel.title : ""));
- if(!dlg.Show(GetEditor()))
- return 0;
- returnPath = dlg.GetDirectory().ToLocale();
- if(FourCC("VSTr") == GetUID() && fileSel.returnPath != nullptr && fileSel.sizeReturnPath == 0)
- {
-
-
-
- fileSel.sizeReturnPath = mpt::saturate_cast<int32>(returnPath.length() + 1);
- }
- }
-
- if(fileSel.returnPath == nullptr || fileSel.sizeReturnPath == 0)
- {
-
- fileSel.sizeReturnPath = mpt::saturate_cast<int32>(returnPath.length() + 1);
- fileSel.returnPath = new(std::nothrow) char[fileSel.sizeReturnPath];
- if(fileSel.returnPath == nullptr)
- {
- return 0;
- }
- fileSel.reserved = 1;
- } else
- {
- fileSel.reserved = 0;
- }
- const auto len = std::min(returnPath.size(), static_cast<size_t>(fileSel.sizeReturnPath - 1));
- strncpy(fileSel.returnPath, returnPath.data(), len);
- fileSel.returnPath[len] = '\0';
- fileSel.numReturnPaths = 1;
- fileSel.returnMultiplePaths = nullptr;
- return 1;
- } else
- {
-
- if(fileSel.command == kVstMultipleFilesLoad && fileSel.returnMultiplePaths != nullptr)
- {
- for(int32 i = 0; i < fileSel.numReturnPaths; i++)
- {
- if(fileSel.returnMultiplePaths[i] != nullptr)
- {
- delete[] fileSel.returnMultiplePaths[i];
- }
- }
- delete[] fileSel.returnMultiplePaths;
- fileSel.returnMultiplePaths = nullptr;
- } else
- {
- if(fileSel.reserved == 1 && fileSel.returnPath != nullptr)
- {
- delete[] fileSel.returnPath;
- fileSel.returnPath = nullptr;
- }
- }
- return 1;
- }
- }
- CVstPlugin::CVstPlugin(bool maskCrashes, HMODULE hLibrary, VSTPluginLib &factory, SNDMIXPLUGIN &mixStruct, AEffect &effect, CSoundFile &sndFile)
- : IMidiPlugin(factory, sndFile, &mixStruct)
- , m_maskCrashes(maskCrashes)
- , m_Effect(effect)
- , timeInfo{}
- , isBridged(!memcmp(&effect.reservedForHost2, "OMPT", 4))
- , m_hLibrary(hLibrary)
- , m_nSampleRate(sndFile.GetSampleRate())
- , m_isInitialized(false)
- , m_needIdle(false)
- {
-
- Initialize();
- InsertIntoFactoryList();
- m_isInitialized = true;
- }
- void CVstPlugin::Initialize()
- {
- m_Ectx = { MPT_UFORMAT("VST Plugin: {}")(m_Factory.dllPath.ToUnicode()) };
-
- m_pMixStruct->Info.dwPluginId1 = m_Factory.pluginId1 = m_Effect.magic;
- m_pMixStruct->Info.dwPluginId2 = m_Factory.pluginId2 = m_Effect.uniqueID;
-
- m_Effect.reservedForHost1 = this;
- m_nSampleRate = m_SndFile.GetSampleRate();
-
- Dispatch(effSetSampleRate, 0, 0, nullptr, static_cast<float>(m_nSampleRate));
- Dispatch(effSetBlockSize, 0, MIXBUFFERSIZE, nullptr, 0.0f);
- Dispatch(effOpen, 0, 0, nullptr, 0.0f);
-
- m_isVst2 = Dispatch(effGetVstVersion, 0,0, nullptr, 0.0f) >= 2;
- if(m_isVst2)
- {
-
-
- VstSpeakerArrangement sa{};
- sa.numChannels = 2;
- sa.type = kSpeakerArrStereo;
- for(std::size_t i = 0; i < std::size(sa.speakers); i++)
- {
-
- switch(i)
- {
- case 0:
- sa.speakers[i].type = kSpeakerL;
- mpt::String::WriteAutoBuf(sa.speakers[i].name) = "Left";
- break;
- case 1:
- sa.speakers[i].type = kSpeakerR;
- mpt::String::WriteAutoBuf(sa.speakers[i].name) = "Right";
- break;
- default:
- sa.speakers[i].type = kSpeakerUndefined;
- break;
- }
- }
-
-
-
-
- if(GetUID() != FourCC("CSI4"))
- {
-
- Dispatch(effSetSpeakerArrangement, 0, ToIntPtr(&sa), &sa, 0.0f);
- }
-
-
- VstPinProperties tempPinProperties;
- Dispatch(effGetInputProperties, 0, 0, &tempPinProperties, 0);
- Dispatch(effGetOutputProperties, 0, 0, &tempPinProperties, 0);
- Dispatch(effConnectInput, 0, 1, nullptr, 0.0f);
- if (m_Effect.numInputs > 1) Dispatch(effConnectInput, 1, 1, nullptr, 0.0f);
- Dispatch(effConnectOutput, 0, 1, nullptr, 0.0f);
- if (m_Effect.numOutputs > 1) Dispatch(effConnectOutput, 1, 1, nullptr, 0.0f);
-
- for(int32 i = 2; i < m_Effect.numInputs; i++)
- Dispatch(effConnectInput, i, 0, nullptr, 0.0f);
- for(int32 i = 2; i < m_Effect.numOutputs; i++)
- Dispatch(effConnectOutput, i, 0, nullptr, 0.0f);
- }
-
- Dispatch(effSetSampleRate, 0, 0, nullptr, static_cast<float>(m_nSampleRate));
- Dispatch(effSetBlockSize, 0, MIXBUFFERSIZE, nullptr, 0.0f);
- if(m_Effect.numPrograms > 0)
- {
- BeginSetProgram(0);
- EndSetProgram();
- }
- InitializeIOBuffers();
- Dispatch(effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f);
- m_isInstrument = IsInstrument();
- RecalculateGain();
- m_pProcessFP = (m_Effect.flags & effFlagsCanReplacing) ? m_Effect.processReplacing : m_Effect.process;
-
- Dispatch(effSetSampleRate, 0, 0, nullptr, static_cast<float>(m_nSampleRate));
-
-
-
-
-
- if(GetUID() == FourCC("KLWV")
- || GetUID() == FourCC("KLM1")
- || GetUID() == FourCC("dfhe")
- || GetUID() == FourCC("dfh2"))
- {
- Resume();
- Suspend();
- }
- }
- bool CVstPlugin::InitializeIOBuffers()
- {
-
-
- return m_mixBuffer.Initialize(std::max(m_Effect.numInputs, int32(2)), m_Effect.numOutputs);
- }
- CVstPlugin::~CVstPlugin()
- {
- CriticalSection cs;
- CloseEditor();
- if (m_isVst2)
- {
- Dispatch(effConnectInput, 0, 0, nullptr, 0);
- if (m_Effect.numInputs > 1) Dispatch(effConnectInput, 1, 0, nullptr, 0);
- Dispatch(effConnectOutput, 0, 0, nullptr, 0);
- if (m_Effect.numOutputs > 1) Dispatch(effConnectOutput, 1, 0, nullptr, 0);
- }
- CVstPlugin::Suspend();
- m_isInitialized = false;
- Dispatch(effClose, 0, 0, nullptr, 0);
- if(TrackerSettings::Instance().BrokenPluginsWorkaroundVSTNeverUnloadAnyPlugin)
- {
-
-
- } else
- {
- if(m_hLibrary)
- {
- FreeLibrary(m_hLibrary);
- }
- }
- }
- void CVstPlugin::Release()
- {
- delete this;
- }
- void CVstPlugin::Idle()
- {
- if(m_needIdle)
- {
- if(!(Dispatch(effIdle, 0, 0, nullptr, 0.0f)))
- m_needIdle = false;
- }
- if (m_pEditor && m_pEditor->m_hWnd)
- {
- Dispatch(effEditIdle, 0, 0, nullptr, 0.0f);
- }
- }
- int32 CVstPlugin::GetNumPrograms() const
- {
- return std::max(m_Effect.numPrograms, int32(0));
- }
- PlugParamIndex CVstPlugin::GetNumParameters() const
- {
- return m_Effect.numParams;
- }
- bool CVstPlugin::CanAutomateParameter(PlugParamIndex index)
- {
- return (Dispatch(effCanBeAutomated, index, 0, nullptr, 0.0f) != 0);
- }
- int32 CVstPlugin::GetUID() const
- {
- return m_Effect.uniqueID;
- }
- int32 CVstPlugin::GetVersion() const
- {
- return m_Effect.version;
- }
- intptr_t CVstPlugin::DispatchSEH(bool maskCrashes, AEffect *effect, VstOpcodeToPlugin opCode, int32 index, intptr_t value, void *ptr, float opt, unsigned long &exception)
- {
- if(effect->dispatcher != nullptr)
- {
- intptr_t result = 0;
- DWORD e = SETryOrError(maskCrashes, [&](){ result = effect->dispatcher(effect, opCode, index, value, ptr, opt); });
- if(e)
- {
- exception = e;
- }
- return result;
- }
- return 0;
- }
- intptr_t CVstPlugin::Dispatch(VstOpcodeToPlugin opCode, int32 index, intptr_t value, void *ptr, float opt)
- {
- #ifdef VST_LOG
- {
- mpt::ustring codeStr;
- if(opCode >= 0 && static_cast<std::size_t>(opCode) < std::size(VstOpCodes))
- {
- codeStr = mpt::ToUnicode(mpt::Charset::ASCII, VstOpCodes[opCode]);
- } else
- {
- codeStr = mpt::ufmt::val(opCode);
- }
- MPT_LOG_GLOBAL(LogDebug, "VST", MPT_UFORMAT("About to Dispatch({}) (Plugin=\"{}\"), index: {}, value: {}, ptr: {}, opt: {}!\n")(codeStr, m_Factory.libraryName, index, mpt::ufmt::PTR(value), mpt::ufmt::PTR(ptr), mpt::ufmt::flt(opt, 3)));
- }
- #endif
- if(!m_Effect.dispatcher)
- {
- return 0;
- }
- intptr_t result = 0;
- {
- DWORD exception = SETryOrError([&](){ result = m_Effect.dispatcher(&m_Effect, opCode, index, value, ptr, opt); });
- if(exception)
- {
- mpt::ustring codeStr;
- if(opCode < mpt::saturate_cast<int32>(std::size(VstOpCodes)))
- {
- codeStr = mpt::ToUnicode(mpt::Charset::ASCII, VstOpCodes[opCode]);
- } else
- {
- codeStr = mpt::ufmt::val(opCode);
- }
- ReportPlugException(MPT_UFORMAT("Exception {} in Dispatch({})")(mpt::ufmt::HEX0<8>(exception), codeStr));
- }
- }
- return result;
- }
- int32 CVstPlugin::GetCurrentProgram()
- {
- if(m_Effect.numPrograms > 0)
- {
- return static_cast<int32>(Dispatch(effGetProgram, 0, 0, nullptr, 0));
- }
- return 0;
- }
- CString CVstPlugin::GetCurrentProgramName()
- {
- std::vector<char> s(256, 0);
-
- Dispatch(effGetProgramName, 0, 0, s.data(), 0);
- return mpt::ToCString(mpt::Charset::Locale, s.data());
- }
- void CVstPlugin::SetCurrentProgramName(const CString &name)
- {
- Dispatch(effSetProgramName, 0, 0, const_cast<char *>(mpt::ToCharset(mpt::Charset::Locale, name.Left(kVstMaxProgNameLen)).c_str()), 0.0f);
- }
- CString CVstPlugin::GetProgramName(int32 program)
- {
-
- std::vector<char> rawname(256, 0);
- if(program < m_Effect.numPrograms)
- {
- if(Dispatch(effGetProgramNameIndexed, program, -1 , rawname.data(), 0) != 1)
- {
-
- rawname.assign(256, 0);
- int32 curProg = GetCurrentProgram();
- if(program != curProg)
- {
- SetCurrentProgram(program);
- }
- Dispatch(effGetProgramName, 0, 0, rawname.data(), 0);
- if(program != curProg)
- {
- SetCurrentProgram(curProg);
- }
- }
- }
- return mpt::ToCString(mpt::Charset::Locale, rawname.data());
- }
- void CVstPlugin::SetCurrentProgram(int32 nIndex)
- {
- if(m_Effect.numPrograms > 0)
- {
- if(nIndex < m_Effect.numPrograms)
- {
- BeginSetProgram(nIndex);
- EndSetProgram();
- }
- }
- }
- void CVstPlugin::BeginSetProgram(int32 program)
- {
- Dispatch(effBeginSetProgram, 0, 0, nullptr, 0);
- if(program != -1)
- Dispatch(effSetProgram, 0, program, nullptr, 0);
- }
- void CVstPlugin::EndSetProgram()
- {
- Dispatch(effEndSetProgram, 0, 0, nullptr, 0);
- }
- void CVstPlugin::BeginGetProgram(int32 program)
- {
- if(program != -1)
- Dispatch(effSetProgram, 0, program, nullptr, 0);
- if(isBridged)
- Dispatch(effVendorSpecific, kVendorOpenMPT, kBeginGetProgram, nullptr, 0);
- }
- void CVstPlugin::EndGetProgram()
- {
- if(isBridged)
- Dispatch(effVendorSpecific, kVendorOpenMPT, kEndGetProgram, nullptr, 0);
- }
- PlugParamValue CVstPlugin::GetParameter(PlugParamIndex nIndex)
- {
- float fResult = 0;
- if(nIndex < m_Effect.numParams && m_Effect.getParameter != nullptr)
- {
- DWORD exception = SETryOrError([&](){ fResult = m_Effect.getParameter(&m_Effect, nIndex); });
- if(exception)
- {
-
- }
- }
- return fResult;
- }
- void CVstPlugin::SetParameter(PlugParamIndex nIndex, PlugParamValue fValue)
- {
- DWORD exception = 0;
- if(nIndex < m_Effect.numParams && m_Effect.setParameter)
- {
- exception = SETryOrError([&](){ m_Effect.setParameter(&m_Effect, nIndex, fValue); });
- }
- ResetSilence();
- if(exception)
- {
-
- }
- }
- CString CVstPlugin::GetParamPropertyString(PlugParamIndex param, Vst::VstOpcodeToPlugin opcode)
- {
- if(m_Effect.numParams > 0 && param < m_Effect.numParams)
- {
-
- std::vector<char> s(256, 0);
- Dispatch(opcode, param, 0, s.data(), 0);
- return mpt::ToCString(mpt::Charset::Locale, s.data());
- }
- return CString();
- }
- CString CVstPlugin::GetParamName(PlugParamIndex param)
- {
- VstParameterProperties properties{};
- if(param < m_Effect.numParams && Dispatch(effGetParameterProperties, param, 0, &properties, 0.0f) == 1)
- {
- mpt::String::SetNullTerminator(properties.label);
- return mpt::ToCString(mpt::Charset::Locale, properties.label);
- } else
- {
- return GetParamPropertyString(param, effGetParamName);
- }
- }
- CString CVstPlugin::GetDefaultEffectName()
- {
- if(m_isVst2)
- {
- std::vector<char> s(256, 0);
- Dispatch(effGetEffectName, 0, 0, s.data(), 0);
- return mpt::ToCString(mpt::Charset::Locale, s.data());
- }
- return CString();
- }
- void CVstPlugin::Resume()
- {
- const uint32 sampleRate = m_SndFile.GetSampleRate();
-
- m_MixState.nVolDecayL = 0;
- m_MixState.nVolDecayR = 0;
- if(m_isResumed)
- {
- Dispatch(effStopProcess, 0, 0, nullptr, 0.0f);
- Dispatch(effMainsChanged, 0, 0, nullptr, 0.0f);
- }
- if (sampleRate != m_nSampleRate)
- {
- m_nSampleRate = sampleRate;
- Dispatch(effSetSampleRate, 0, 0, nullptr, static_cast<float>(m_nSampleRate));
- }
- Dispatch(effSetBlockSize, 0, MIXBUFFERSIZE, nullptr, 0.0f);
-
- Dispatch(effMainsChanged, 0, 1, nullptr, 0.0f);
- Dispatch(effStartProcess, 0, 0, nullptr, 0.0f);
- m_isResumed = true;
- }
- void CVstPlugin::Suspend()
- {
- if(m_isResumed)
- {
- Dispatch(effStopProcess, 0, 0, nullptr, 0.0f);
- Dispatch(effMainsChanged, 0, 0, nullptr, 0.0f);
- m_isResumed = false;
- }
- }
- void CVstPlugin::ProcessVSTEvents()
- {
-
- if(m_Effect.dispatcher != nullptr && vstEvents.Finalise() > 0)
- {
- DWORD exception = SETryOrError([&](){ m_Effect.dispatcher(&m_Effect, effProcessEvents, 0, 0, &vstEvents, 0); });
- ResetSilence();
- if(exception)
- {
- ReportPlugException(MPT_UFORMAT("Exception {} in ProcessVSTEvents(numEvents:{})!")(
- mpt::ufmt::HEX0<8>(exception),
- vstEvents.size()));
- }
- }
- }
- void CVstPlugin::ReceiveVSTEvents(const VstEvents *events)
- {
- if(m_pMixStruct == nullptr)
- {
- return;
- }
- ResetSilence();
-
-
- PLUGINDEX receiver = m_pMixStruct->GetOutputPlugin();
- if(receiver != PLUGINDEX_INVALID)
- {
- IMixPlugin *plugin = m_SndFile.m_MixPlugins[receiver].pMixPlugin;
- CVstPlugin *vstPlugin = dynamic_cast<CVstPlugin *>(plugin);
-
- for(const auto &ev : *events)
- {
- if(vstPlugin != nullptr)
- {
-
- vstPlugin->vstEvents.Enqueue(ev);
- } else if(plugin != nullptr)
- {
- if(ev->type == kVstMidiType)
- {
- plugin->MidiSend(static_cast<const VstMidiEvent *>(ev)->midiData);
- } else if(ev->type == kVstSysExType)
- {
- auto event = static_cast<const VstMidiSysexEvent *>(ev);
- plugin->MidiSysexSend(mpt::as_span(mpt::byte_cast<const std::byte *>(event->sysexDump), event->dumpBytes));
- }
- }
- }
- }
- #ifdef MODPLUG_TRACKER
- if(m_recordMIDIOut)
- {
-
- for(const auto &ev : *events)
- {
- if(ev->type == kVstMidiType)
- {
- VstMidiEvent *event = static_cast<VstMidiEvent *>(ev);
- ::SendNotifyMessage(CMainFrame::GetMainFrame()->GetMidiRecordWnd(), WM_MOD_MIDIMSG, event->midiData, reinterpret_cast<LPARAM>(this));
- }
- }
- }
- #endif
- }
- void CVstPlugin::Process(float *pOutL, float *pOutR, uint32 numFrames)
- {
- ProcessVSTEvents();
-
- if(m_pProcessFP != nullptr && m_mixBuffer.Ok())
- {
- int32 numInputs = m_Effect.numInputs, numOutputs = m_Effect.numOutputs;
-
-
- if (numInputs == 1)
- {
- float *plugInputL = m_mixBuffer.GetInputBuffer(0);
- float *plugInputR = m_mixBuffer.GetInputBuffer(1);
- for (uint32 i = 0; i < numFrames; i++)
- {
- plugInputL[i] = 0.5f * (plugInputL[i] + plugInputR[i]);
- }
- }
- float **outputBuffers = m_mixBuffer.GetOutputBufferArray();
- if(!isBridged)
- {
- m_mixBuffer.ClearOutputBuffers(numFrames);
- }
-
- MPT_ASSERT(numFrames <= MIXBUFFERSIZE);
- {
- DWORD exception = SETryOrError([&](){ m_pProcessFP(&m_Effect, m_mixBuffer.GetInputBufferArray(), outputBuffers, numFrames); });
- if(exception)
- {
- Bypass();
- mpt::ustring processMethod = (m_Effect.flags & effFlagsCanReplacing) ? U_("processReplacing") : U_("process");
- ReportPlugException(MPT_UFORMAT("The plugin threw an exception ({}) in {}. It has automatically been set to \"Bypass\".")(mpt::ufmt::HEX0<8>(exception), processMethod));
- }
- }
-
- if(numOutputs > 2)
- {
- MPT_ASSERT(outputBuffers != nullptr);
-
- int32 outs = numOutputs;
-
- if((outs % 2u) == 1) outs--;
-
- for(int32 iOut = 2; iOut < outs; iOut++)
- {
- for(uint32 i = 0; i < numFrames; i++)
- {
- outputBuffers[iOut % 2u][i] += outputBuffers[iOut][i];
- }
- }
-
- if(outs != numOutputs)
- {
-
- for(uint32 i = 0; i < numFrames; i++)
- {
- float v = 0.5f * outputBuffers[outs][i];
- outputBuffers[0][i] += v;
- outputBuffers[1][i] += v;
- }
- }
- }
- if(numOutputs != 0)
- {
- MPT_ASSERT(outputBuffers != nullptr);
- ProcessMixOps(pOutL, pOutR, outputBuffers[0], outputBuffers[numOutputs > 1 ? 1 : 0], numFrames);
- }
-
- if(isBridged && Dispatch(effVendorSpecific, kVendorOpenMPT, kCloseOldProcessingMemory, nullptr, 0.0f) != 0)
- {
- InitializeIOBuffers();
- }
- }
- vstEvents.Clear();
- m_positionChanged = false;
- }
- bool CVstPlugin::MidiSend(uint32 dwMidiCode)
- {
-
-
-
-
-
- bool insertAtFront = (MIDIEvents::GetTypeFromEvent(dwMidiCode) == MIDIEvents::evNoteOff);
- VstMidiEvent event{};
- event.type = kVstMidiType;
- event.byteSize = sizeof(event);
- event.midiData = dwMidiCode;
- ResetSilence();
- return vstEvents.Enqueue(&event, insertAtFront);
- }
- bool CVstPlugin::MidiSysexSend(mpt::const_byte_span sysex)
- {
- VstMidiSysexEvent event{};
- event.type = kVstSysExType;
- event.byteSize = sizeof(event);
- event.dumpBytes = mpt::saturate_cast<int32>(sysex.size());
- event.sysexDump = sysex.data();
- ResetSilence();
- return vstEvents.Enqueue(&event);
- }
- void CVstPlugin::HardAllNotesOff()
- {
- constexpr uint32 SCRATCH_BUFFER_SIZE = 64;
- float out[2][SCRATCH_BUFFER_SIZE];
-
- const bool wasSuspended = !IsResumed();
- if(wasSuspended)
- {
- Resume();
- }
- const bool isWavestation = GetUID() == FourCC("KLWV");
- const bool isSawer = GetUID() == FourCC("SaWR");
- for(uint8 mc = 0; mc < m_MidiCh.size(); mc++)
- {
- PlugInstrChannel &channel = m_MidiCh[mc];
- channel.ResetProgram();
- SendMidiPitchBend(mc, EncodePitchBendParam(MIDIEvents::pitchBendCentre));
- if(!isWavestation && !isSawer)
- {
-
-
-
-
- MidiSend(MIDIEvents::CC(MIDIEvents::MIDICC_AllControllersOff, mc, 0));
- }
- if(!isSawer)
- {
-
- MidiSend(MIDIEvents::CC(MIDIEvents::MIDICC_AllNotesOff, mc, 0));
- }
- MidiSend(MIDIEvents::CC(MIDIEvents::MIDICC_AllSoundOff, mc, 0));
- for(std::size_t i = 0; i < std::size(channel.noteOnMap); i++)
- {
- for(auto &c : channel.noteOnMap[i])
- {
- while(c != 0)
- {
- MidiSend(MIDIEvents::NoteOff(mc, static_cast<uint8>(i), 0));
- c--;
- }
- }
- }
- }
-
- while(vstEvents.GetNumQueuedEvents() > 0)
- {
- Process(out[0], out[1], SCRATCH_BUFFER_SIZE);
- }
- if(wasSuspended)
- {
- Suspend();
- }
- }
- void CVstPlugin::SaveAllParameters()
- {
- if(m_pMixStruct == nullptr)
- {
- return;
- }
- m_pMixStruct->defaultProgram = -1;
- if(ProgramsAreChunks())
- {
- void *p = nullptr;
-
- intptr_t byteSize = Dispatch(effGetChunk, 0, 0, &p, 0);
- if (!p)
- {
-
- byteSize = Dispatch(effGetChunk, 1, 0, &p, 0);
- } else
- {
-
- m_pMixStruct->defaultProgram = GetCurrentProgram();
- }
- if (p != nullptr)
- {
- LimitMax(byteSize, Util::MaxValueOfType(byteSize) - 4);
- try
- {
- m_pMixStruct->pluginData.resize(byteSize + 4);
- auto data = m_pMixStruct->pluginData.data();
- memcpy(data, "fEvN", 4);
- memcpy(data + 4, p, byteSize);
- return;
- } catch(mpt::out_of_memory e)
- {
- mpt::delete_out_of_memory(e);
- }
- }
- }
-
- IMixPlugin::SaveAllParameters();
- }
- void CVstPlugin::RestoreAllParameters(int32 program)
- {
- if(m_pMixStruct != nullptr && m_pMixStruct->pluginData.size() >= 4)
- {
- auto data = m_pMixStruct->pluginData.data();
- if (!memcmp(data, "fEvN", 4))
- {
- if ((program>=0) && (program < m_Effect.numPrograms))
- {
-
- Dispatch(effSetChunk, 0, m_pMixStruct->pluginData.size() - 4, data + 4, 0);
- SetCurrentProgram(program);
- } else
- {
-
- BeginSetProgram(-1);
- Dispatch(effSetChunk, 1, m_pMixStruct->pluginData.size() - 4, data + 4, 0);
- EndSetProgram();
- }
- } else
- {
- IMixPlugin::RestoreAllParameters(program);
- }
- }
- }
- CAbstractVstEditor *CVstPlugin::OpenEditor()
- {
- try
- {
- if(HasEditor())
- return new COwnerVstEditor(*this);
- else
- return new CDefaultVstEditor(*this);
- } catch(mpt::out_of_memory e)
- {
- mpt::delete_out_of_memory(e);
- ReportPlugException(U_("Exception in OpenEditor()"));
- return nullptr;
- }
- }
- void CVstPlugin::Bypass(bool bypass)
- {
- Dispatch(effSetBypass, bypass ? 1 : 0, 0, nullptr, 0.0f);
- IMixPlugin::Bypass(bypass);
- }
- void CVstPlugin::NotifySongPlaying(bool playing)
- {
- m_isSongPlaying = playing;
- }
- bool CVstPlugin::IsInstrument() const
- {
- return ((m_Effect.flags & effFlagsIsSynth) || (!m_Effect.numInputs));
- }
- bool CVstPlugin::CanRecieveMidiEvents()
- {
- return Dispatch(effCanDo, 0, 0, const_cast<char *>(PluginCanDo::receiveVstMidiEvent), 0.0f) != 0;
- }
- void CVstPlugin::ReportPlugException(const mpt::ustring &text) const
- {
- CVstPluginManager::ReportPlugException(MPT_UFORMAT("{} (Plugin: {})")(text, m_Factory.libraryName));
- }
- void CVstPlugin::CacheProgramNames(int32 firstProg, int32 lastProg)
- {
- if(isBridged)
- {
- int32 offsets[2] = { firstProg, lastProg };
- Dispatch(effVendorSpecific, kVendorOpenMPT, kCacheProgramNames, offsets, 0.0f);
- }
- }
- void CVstPlugin::CacheParameterNames(int32 firstParam, int32 lastParam)
- {
- if(isBridged)
- {
- int32 offsets[2] = { firstParam, lastParam };
- Dispatch(effVendorSpecific, kVendorOpenMPT, kCacheParameterInfo, offsets, 0.0f);
- }
- }
- IMixPlugin::ChunkData CVstPlugin::GetChunk(bool isBank)
- {
- std::byte *chunk = nullptr;
- auto size = Dispatch(effGetChunk, isBank ? 0 : 1, 0, &chunk, 0);
- if(chunk == nullptr)
- {
- size = 0;
- }
- return ChunkData(chunk, size);
- }
- void CVstPlugin::SetChunk(const ChunkData &chunk, bool isBank)
- {
- Dispatch(effSetChunk, isBank ? 0 : 1, chunk.size(), const_cast<std::byte *>(chunk.data()), 0);
- }
- OPENMPT_NAMESPACE_END
- #endif
|