BridgeWrapper.cpp 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291
  1. /*
  2. * BridgeWrapper.cpp
  3. * -----------------
  4. * Purpose: VST plugin bridge wrapper (host side)
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #include "stdafx.h"
  10. #ifdef MPT_WITH_VST
  11. #include "BridgeWrapper.h"
  12. #include "../soundlib/plugins/PluginManager.h"
  13. #include "../mptrack/Mainfrm.h"
  14. #include "../mptrack/Mptrack.h"
  15. #include "../mptrack/Vstplug.h"
  16. #include "../mptrack/ExceptionHandler.h"
  17. #include "../common/mptFileIO.h"
  18. #include "../common/mptStringBuffer.h"
  19. #include "../common/misc_util.h"
  20. using namespace Vst;
  21. OPENMPT_NAMESPACE_BEGIN
  22. std::vector<BridgeCommon *> BridgeCommon::m_plugins;
  23. HWND BridgeCommon::m_communicationWindow = nullptr;
  24. int BridgeCommon::m_instanceCount = 0;
  25. thread_local bool BridgeCommon::m_isAudioThread = false;
  26. std::size_t GetPluginArchPointerSize(PluginArch arch)
  27. {
  28. std::size_t result = 0;
  29. switch(arch)
  30. {
  31. case PluginArch_x86:
  32. result = 4;
  33. break;
  34. case PluginArch_amd64:
  35. result = 8;
  36. break;
  37. case PluginArch_arm:
  38. result = 4;
  39. break;
  40. case PluginArch_arm64:
  41. result = 8;
  42. break;
  43. default:
  44. result = 0;
  45. break;
  46. }
  47. return result;
  48. }
  49. ComponentPluginBridge::ComponentPluginBridge(PluginArch arch, Generation generation)
  50. : ComponentBase(ComponentTypeBundled)
  51. , arch(arch)
  52. , generation(generation)
  53. {
  54. }
  55. bool ComponentPluginBridge::DoInitialize()
  56. {
  57. mpt::PathString archName;
  58. switch(arch)
  59. {
  60. case PluginArch_x86:
  61. if(mpt::OS::Windows::HostCanRun(mpt::OS::Windows::GetHostArchitecture(), mpt::OS::Windows::Architecture::x86) == mpt::OS::Windows::EmulationLevel::NA)
  62. {
  63. return false;
  64. }
  65. archName = P_("x86");
  66. break;
  67. case PluginArch_amd64:
  68. if(mpt::OS::Windows::HostCanRun(mpt::OS::Windows::GetHostArchitecture(), mpt::OS::Windows::Architecture::amd64) == mpt::OS::Windows::EmulationLevel::NA)
  69. {
  70. return false;
  71. }
  72. archName = P_("amd64");
  73. break;
  74. case PluginArch_arm:
  75. if(mpt::OS::Windows::HostCanRun(mpt::OS::Windows::GetHostArchitecture(), mpt::OS::Windows::Architecture::arm) == mpt::OS::Windows::EmulationLevel::NA)
  76. {
  77. return false;
  78. }
  79. archName = P_("arm");
  80. break;
  81. case PluginArch_arm64:
  82. if(mpt::OS::Windows::HostCanRun(mpt::OS::Windows::GetHostArchitecture(), mpt::OS::Windows::Architecture::arm64) == mpt::OS::Windows::EmulationLevel::NA)
  83. {
  84. return false;
  85. }
  86. archName = P_("arm64");
  87. break;
  88. default:
  89. break;
  90. }
  91. if(archName.empty())
  92. {
  93. return false;
  94. }
  95. exeName = mpt::PathString();
  96. const mpt::PathString generationSuffix = (generation == Generation::Legacy) ? P_("Legacy") : P_("");
  97. const mpt::PathString exeNames[] =
  98. {
  99. theApp.GetInstallPath() + P_("PluginBridge") + generationSuffix + P_("-") + archName + P_(".exe"), // Local
  100. theApp.GetInstallBinPath() + archName + P_("\\") + P_("PluginBridge") + generationSuffix + P_(".exe"), // Multi-arch
  101. theApp.GetInstallBinPath() + archName + P_("\\") + P_("PluginBridge") + generationSuffix + P_("-") + archName + P_(".exe") // Multi-arch transitional
  102. };
  103. for(const auto &candidate : exeNames)
  104. {
  105. if(candidate.IsFile())
  106. {
  107. exeName = candidate;
  108. break;
  109. }
  110. }
  111. if(exeName.empty())
  112. {
  113. availability = AvailabilityMissing;
  114. return false;
  115. }
  116. std::vector<WCHAR> exePath(MAX_PATH);
  117. while(GetModuleFileNameW(0, exePath.data(), mpt::saturate_cast<DWORD>(exePath.size())) >= exePath.size())
  118. {
  119. exePath.resize(exePath.size() * 2);
  120. }
  121. uint64 mptVersion = BridgeWrapper::GetFileVersion(exePath.data());
  122. uint64 bridgeVersion = BridgeWrapper::GetFileVersion(exeName.ToWide().c_str());
  123. if(bridgeVersion != mptVersion)
  124. {
  125. availability = AvailabilityWrongVersion;
  126. return false;
  127. }
  128. availability = AvailabilityOK;
  129. return true;
  130. }
  131. PluginArch BridgeWrapper::GetNativePluginBinaryType()
  132. {
  133. PluginArch result = PluginArch_unknown;
  134. switch(mpt::OS::Windows::GetProcessArchitecture())
  135. {
  136. case mpt::OS::Windows::Architecture::x86:
  137. result = PluginArch_x86;
  138. break;
  139. case mpt::OS::Windows::Architecture::amd64:
  140. result = PluginArch_amd64;
  141. break;
  142. case mpt::OS::Windows::Architecture::arm:
  143. result = PluginArch_arm;
  144. break;
  145. case mpt::OS::Windows::Architecture::arm64:
  146. result = PluginArch_arm64;
  147. break;
  148. default:
  149. result = PluginArch_unknown;
  150. break;
  151. }
  152. return result;
  153. }
  154. // Check whether we need to load a 32-bit or 64-bit wrapper.
  155. PluginArch BridgeWrapper::GetPluginBinaryType(const mpt::PathString &pluginPath)
  156. {
  157. PluginArch type = PluginArch_unknown;
  158. mpt::ifstream file(pluginPath, std::ios::in | std::ios::binary);
  159. if(file.is_open())
  160. {
  161. IMAGE_DOS_HEADER dosHeader;
  162. IMAGE_NT_HEADERS ntHeader;
  163. file.read(reinterpret_cast<char *>(&dosHeader), sizeof(dosHeader));
  164. if(dosHeader.e_magic == IMAGE_DOS_SIGNATURE)
  165. {
  166. file.seekg(dosHeader.e_lfanew);
  167. file.read(reinterpret_cast<char *>(&ntHeader), sizeof(ntHeader));
  168. MPT_ASSERT((ntHeader.FileHeader.Characteristics & IMAGE_FILE_DLL) != 0);
  169. switch(ntHeader.FileHeader.Machine)
  170. {
  171. case IMAGE_FILE_MACHINE_I386:
  172. type = PluginArch_x86;
  173. break;
  174. case IMAGE_FILE_MACHINE_AMD64:
  175. type = PluginArch_amd64;
  176. break;
  177. #if defined(MPT_WITH_WINDOWS10)
  178. case IMAGE_FILE_MACHINE_ARM:
  179. type = PluginArch_arm;
  180. break;
  181. case IMAGE_FILE_MACHINE_ARM64:
  182. type = PluginArch_arm64;
  183. break;
  184. #endif // MPT_WITH_WINDOWS10
  185. default:
  186. type = PluginArch_unknown;
  187. break;
  188. }
  189. }
  190. }
  191. return type;
  192. }
  193. uint64 BridgeWrapper::GetFileVersion(const WCHAR *exePath)
  194. {
  195. DWORD verHandle = 0;
  196. DWORD verSize = GetFileVersionInfoSizeW(exePath, &verHandle);
  197. uint64 result = 0;
  198. if(verSize == 0)
  199. {
  200. return result;
  201. }
  202. char *verData = new(std::nothrow) char[verSize];
  203. if(verData && GetFileVersionInfoW(exePath, verHandle, verSize, verData))
  204. {
  205. UINT size = 0;
  206. void *lpBuffer = nullptr;
  207. if(VerQueryValue(verData, _T("\\"), &lpBuffer, &size) && size != 0)
  208. {
  209. auto *verInfo = static_cast<const VS_FIXEDFILEINFO *>(lpBuffer);
  210. if(verInfo->dwSignature == 0xfeef04bd)
  211. {
  212. result = (uint64(HIWORD(verInfo->dwFileVersionMS)) << 48)
  213. | (uint64(LOWORD(verInfo->dwFileVersionMS)) << 32)
  214. | (uint64(HIWORD(verInfo->dwFileVersionLS)) << 16)
  215. | uint64(LOWORD(verInfo->dwFileVersionLS));
  216. }
  217. }
  218. }
  219. delete[] verData;
  220. return result;
  221. }
  222. // Create a plugin bridge object
  223. AEffect *BridgeWrapper::Create(const VSTPluginLib &plugin, bool forceLegacy)
  224. {
  225. BridgeWrapper *wrapper = new(std::nothrow) BridgeWrapper();
  226. BridgeWrapper *sharedInstance = nullptr;
  227. const Generation wantedGeneration = (plugin.modernBridge && !forceLegacy) ? Generation::Modern : Generation::Legacy;
  228. // Should we share instances?
  229. if(plugin.shareBridgeInstance)
  230. {
  231. // Well, then find some instance to share with!
  232. CVstPlugin *vstPlug = dynamic_cast<CVstPlugin *>(plugin.pPluginsList);
  233. while(vstPlug != nullptr)
  234. {
  235. if(vstPlug->isBridged)
  236. {
  237. BridgeWrapper *instance = FromIntPtr<BridgeWrapper>(vstPlug->Dispatch(effVendorSpecific, kVendorOpenMPT, kGetWrapperPointer, nullptr, 0.0f));
  238. if(wantedGeneration == instance->m_Generation)
  239. {
  240. sharedInstance = instance;
  241. break;
  242. }
  243. }
  244. vstPlug = dynamic_cast<CVstPlugin *>(vstPlug->GetNextInstance());
  245. }
  246. }
  247. try
  248. {
  249. if(wrapper != nullptr && wrapper->Init(plugin.dllPath, wantedGeneration, sharedInstance) && wrapper->m_queueMem.Good())
  250. {
  251. return &wrapper->m_sharedMem->effect;
  252. }
  253. delete wrapper;
  254. return nullptr;
  255. } catch(BridgeException &)
  256. {
  257. delete wrapper;
  258. throw;
  259. }
  260. }
  261. BridgeWrapper::BridgeWrapper()
  262. {
  263. m_thisPluginID = static_cast<int32>(m_plugins.size());
  264. m_plugins.push_back(this);
  265. if(m_instanceCount == 1)
  266. CreateCommunicationWindow(WindowProc);
  267. }
  268. BridgeWrapper::~BridgeWrapper()
  269. {
  270. if(m_instanceCount == 1)
  271. DestroyWindow(m_communicationWindow);
  272. }
  273. // Initialize and launch bridge
  274. bool BridgeWrapper::Init(const mpt::PathString &pluginPath, Generation bridgeGeneration, BridgeWrapper *sharedInstace)
  275. {
  276. static uint32 plugId = 0;
  277. plugId++;
  278. const DWORD procId = GetCurrentProcessId();
  279. const std::wstring mapName = MPT_WFORMAT("Local\\openmpt-{}-{}")(procId, plugId);
  280. // Create our shared memory object.
  281. if(!m_queueMem.Create(mapName.c_str(), sizeof(SharedMemLayout))
  282. || !CreateSignals(mapName.c_str()))
  283. {
  284. throw BridgeException("Could not initialize plugin bridge memory.");
  285. }
  286. m_sharedMem = m_queueMem.Data<SharedMemLayout>();
  287. if(sharedInstace == nullptr)
  288. {
  289. // Create a new bridge instance
  290. const PluginArch arch = GetPluginBinaryType(pluginPath);
  291. bool available = false;
  292. ComponentPluginBridge::Availability availability = ComponentPluginBridge::AvailabilityUnknown;
  293. switch(arch)
  294. {
  295. case PluginArch_x86:
  296. if(available = (bridgeGeneration == Generation::Modern) ? IsComponentAvailable(pluginBridge_x86) : IsComponentAvailable(pluginBridgeLegacy_x86); !available)
  297. availability = (bridgeGeneration == Generation::Modern) ? pluginBridge_x86->GetAvailability() : pluginBridgeLegacy_x86->GetAvailability();
  298. break;
  299. case PluginArch_amd64:
  300. if(available = (bridgeGeneration == Generation::Modern) ? IsComponentAvailable(pluginBridge_amd64) : IsComponentAvailable(pluginBridgeLegacy_amd64); !available)
  301. availability = (bridgeGeneration == Generation::Modern) ? pluginBridge_amd64->GetAvailability() : pluginBridgeLegacy_amd64->GetAvailability();
  302. break;
  303. #if defined(MPT_WITH_WINDOWS10)
  304. case PluginArch_arm:
  305. if(available = (bridgeGeneration == Generation::Modern) ? IsComponentAvailable(pluginBridge_arm) : IsComponentAvailable(pluginBridgeLegacy_arm); !available)
  306. availability = (bridgeGeneration == Generation::Modern) ? pluginBridge_arm->GetAvailability() : pluginBridgeLegacy_arm->GetAvailability();
  307. break;
  308. case PluginArch_arm64:
  309. if(available = (bridgeGeneration == Generation::Modern) ? IsComponentAvailable(pluginBridge_arm64) : IsComponentAvailable(pluginBridgeLegacy_arm64); !available)
  310. availability = (bridgeGeneration == Generation::Modern) ? pluginBridge_arm64->GetAvailability() : pluginBridgeLegacy_arm64->GetAvailability();
  311. break;
  312. #endif // MPT_WITH_WINDOWS10
  313. default:
  314. break;
  315. }
  316. if(arch == PluginArch_unknown)
  317. {
  318. return false;
  319. }
  320. if(!available)
  321. {
  322. switch(availability)
  323. {
  324. case ComponentPluginBridge::AvailabilityMissing:
  325. // Silently fail if bridge is missing.
  326. throw BridgeNotFoundException();
  327. break;
  328. case ComponentPluginBridge::AvailabilityWrongVersion:
  329. throw BridgeException("The plugin bridge version does not match your OpenMPT version.");
  330. break;
  331. default:
  332. throw BridgeNotFoundException();
  333. break;
  334. }
  335. }
  336. const ComponentPluginBridge *const pluginBridge =
  337. (arch == PluginArch_x86 && bridgeGeneration == Generation::Modern) ? static_cast<const ComponentPluginBridge *>(pluginBridge_x86.get()) :
  338. (arch == PluginArch_x86 && bridgeGeneration == Generation::Legacy) ? static_cast<const ComponentPluginBridge *>(pluginBridgeLegacy_x86.get()) :
  339. (arch == PluginArch_amd64 && bridgeGeneration == Generation::Modern) ? static_cast<const ComponentPluginBridge *>(pluginBridge_amd64.get()) :
  340. (arch == PluginArch_amd64 && bridgeGeneration == Generation::Legacy) ? static_cast<const ComponentPluginBridge *>(pluginBridgeLegacy_amd64.get()) :
  341. #if defined(MPT_WITH_WINDOWS10)
  342. (arch == PluginArch_arm && bridgeGeneration == Generation::Modern) ? static_cast<const ComponentPluginBridge *>(pluginBridge_arm.get()) :
  343. (arch == PluginArch_arm && bridgeGeneration == Generation::Legacy) ? static_cast<const ComponentPluginBridge *>(pluginBridgeLegacy_arm.get()) :
  344. (arch == PluginArch_arm64 && bridgeGeneration == Generation::Modern) ? static_cast<const ComponentPluginBridge *>(pluginBridge_arm64.get()) :
  345. (arch == PluginArch_arm64 && bridgeGeneration == Generation::Legacy) ? static_cast<const ComponentPluginBridge *>(pluginBridgeLegacy_arm64.get()) :
  346. #endif // MPT_WITH_WINDOWS10
  347. nullptr;
  348. if(!pluginBridge)
  349. {
  350. return false;
  351. }
  352. m_Generation = bridgeGeneration;
  353. const mpt::PathString exeName = pluginBridge->GetFileName();
  354. m_otherPtrSize = static_cast<int32>(GetPluginArchPointerSize(arch));
  355. std::wstring cmdLine = MPT_WFORMAT("{} {}")(mapName, procId);
  356. STARTUPINFOW info;
  357. MemsetZero(info);
  358. info.cb = sizeof(info);
  359. PROCESS_INFORMATION processInfo;
  360. MemsetZero(processInfo);
  361. if(!CreateProcessW(exeName.ToWide().c_str(), cmdLine.data(), NULL, NULL, FALSE, 0, NULL, NULL, &info, &processInfo))
  362. {
  363. throw BridgeException("Failed to launch plugin bridge.");
  364. }
  365. CloseHandle(processInfo.hThread);
  366. m_otherProcess = processInfo.hProcess;
  367. } else
  368. {
  369. // Re-use existing bridge instance
  370. m_otherPtrSize = sharedInstace->m_otherPtrSize;
  371. m_otherProcess.DuplicateFrom(sharedInstace->m_otherProcess);
  372. BridgeMessage msg;
  373. msg.NewInstance(mapName.c_str());
  374. if(!sharedInstace->SendToBridge(msg))
  375. {
  376. // Something went wrong, try a new instance
  377. return Init(pluginPath, bridgeGeneration, nullptr);
  378. }
  379. }
  380. // Initialize bridge
  381. m_sharedMem->effect.object = this;
  382. m_sharedMem->effect.dispatcher = DispatchToPlugin;
  383. m_sharedMem->effect.setParameter = SetParameter;
  384. m_sharedMem->effect.getParameter = GetParameter;
  385. m_sharedMem->effect.process = Process;
  386. std::memcpy(&(m_sharedMem->effect.reservedForHost2), "OMPT", 4);
  387. m_sigAutomation.Create(true);
  388. m_sharedMem->hostCommWindow = m_communicationWindow;
  389. const HANDLE objects[] = {m_sigBridgeReady, m_otherProcess};
  390. if(WaitForMultipleObjects(mpt::saturate_cast<DWORD>(std::size(objects)), objects, FALSE, 10000) != WAIT_OBJECT_0)
  391. {
  392. throw BridgeException("Could not connect to plugin bridge, it probably crashed.");
  393. }
  394. m_otherPluginID = m_sharedMem->bridgePluginID;
  395. BridgeMessage initMsg;
  396. initMsg.Init(pluginPath.ToWide().c_str(), MIXBUFFERSIZE, m_thisPluginID, ExceptionHandler::fullMemDump);
  397. if(!SendToBridge(initMsg))
  398. {
  399. throw BridgeException("Could not initialize plugin bridge, it probably crashed.");
  400. } else if(initMsg.init.result != 1)
  401. {
  402. throw BridgeException(mpt::ToCharset(mpt::Charset::UTF8, initMsg.init.str).c_str());
  403. }
  404. if(m_sharedMem->effect.flags & effFlagsCanReplacing)
  405. m_sharedMem->effect.processReplacing = ProcessReplacing;
  406. if(m_sharedMem->effect.flags & effFlagsCanDoubleReplacing)
  407. m_sharedMem->effect.processDoubleReplacing = ProcessDoubleReplacing;
  408. return true;
  409. }
  410. // Send an arbitrary message to the bridge.
  411. // Returns true if the message was processed by the bridge.
  412. bool BridgeWrapper::SendToBridge(BridgeMessage &sendMsg)
  413. {
  414. const bool inAudioThread = m_isAudioThread || CMainFrame::GetMainFrame()->InAudioThread();
  415. auto &messages = m_sharedMem->ipcMessages;
  416. const auto msgID = CopyToSharedMemory(sendMsg, messages);
  417. if(msgID < 0)
  418. return false;
  419. BridgeMessage &sharedMsg = messages[msgID];
  420. if(!inAudioThread)
  421. {
  422. if(SendMessage(m_sharedMem->bridgeCommWindow, WM_BRIDGE_MESSAGE_TO_BRIDGE, m_otherPluginID, msgID) == WM_BRIDGE_SUCCESS)
  423. {
  424. sharedMsg.CopyTo(sendMsg);
  425. return true;
  426. }
  427. return false;
  428. }
  429. // Audio thread: Use signals instead of window messages
  430. m_sharedMem->audioThreadToBridgeMsgID = msgID;
  431. m_sigToBridgeAudio.Send();
  432. // Wait until we get the result from the bridge
  433. DWORD result;
  434. const HANDLE objects[] = {m_sigToBridgeAudio.confirm, m_sigToHostAudio.send, m_otherProcess};
  435. do
  436. {
  437. result = WaitForMultipleObjects(mpt::saturate_cast<DWORD>(std::size(objects)), objects, FALSE, INFINITE);
  438. if(result == WAIT_OBJECT_0)
  439. {
  440. // Message got answered
  441. sharedMsg.CopyTo(sendMsg);
  442. break;
  443. } else if(result == WAIT_OBJECT_0 + 1)
  444. {
  445. ParseNextMessage(m_sharedMem->audioThreadToHostMsgID);
  446. m_sigToHostAudio.Confirm();
  447. }
  448. } while(result != WAIT_OBJECT_0 + 2 && result != WAIT_FAILED);
  449. return (result == WAIT_OBJECT_0);
  450. }
  451. // Receive a message from the host and translate it.
  452. void BridgeWrapper::ParseNextMessage(int msgID)
  453. {
  454. auto &msg = m_sharedMem->ipcMessages[msgID];
  455. switch(msg.header.type)
  456. {
  457. case MsgHeader::dispatch:
  458. DispatchToHost(msg.dispatch);
  459. break;
  460. case MsgHeader::errorMsg:
  461. // TODO Showing a message box here will deadlock as the main thread can be in a waiting state
  462. //throw BridgeErrorException(msg.error.str);
  463. break;
  464. }
  465. }
  466. void BridgeWrapper::DispatchToHost(DispatchMsg &msg)
  467. {
  468. // Various dispatch data - depending on the opcode, one of those might be used.
  469. std::vector<char> extraData;
  470. MappedMemory auxMem;
  471. // Content of ptr is usually stored right after the message header, ptr field indicates size.
  472. void *ptr = (msg.ptr != 0) ? (&msg + 1) : nullptr;
  473. if(msg.size > sizeof(BridgeMessage))
  474. {
  475. if(!auxMem.Open(static_cast<const wchar_t *>(ptr)))
  476. {
  477. return;
  478. }
  479. ptr = auxMem.Data();
  480. }
  481. void *origPtr = ptr;
  482. switch(msg.opcode)
  483. {
  484. case audioMasterProcessEvents:
  485. // VstEvents* in [ptr]
  486. TranslateBridgeToVstEvents(extraData, ptr);
  487. ptr = extraData.data();
  488. break;
  489. case audioMasterVendorSpecific:
  490. if(msg.index != kVendorOpenMPT || msg.value != kUpdateProcessingBuffer)
  491. {
  492. break;
  493. }
  494. [[fallthrough]];
  495. case audioMasterIOChanged:
  496. {
  497. // If the song is playing, the rendering thread might be active at the moment,
  498. // so we should keep the current processing memory alive until it is done for sure.
  499. const CVstPlugin *plug = static_cast<CVstPlugin *>(m_sharedMem->effect.reservedForHost1);
  500. const bool isPlaying = plug != nullptr && plug->IsResumed();
  501. if(isPlaying)
  502. {
  503. m_oldProcessMem.CopyFrom(m_processMem);
  504. }
  505. // Set up new processing file
  506. m_processMem.Open(static_cast<wchar_t *>(ptr));
  507. if(isPlaying)
  508. {
  509. msg.result = 1;
  510. return;
  511. }
  512. }
  513. break;
  514. case audioMasterUpdateDisplay:
  515. m_cachedProgNames.clear();
  516. m_cachedParamInfo.clear();
  517. break;
  518. case audioMasterOpenFileSelector:
  519. TranslateBridgeToVstFileSelect(extraData, ptr, static_cast<size_t>(msg.ptr));
  520. ptr = extraData.data();
  521. break;
  522. }
  523. intptr_t result = CVstPlugin::MasterCallBack(&m_sharedMem->effect, static_cast<VstOpcodeToHost>(msg.opcode), msg.index, static_cast<intptr_t>(msg.value), ptr, msg.opt);
  524. msg.result = static_cast<int32>(result);
  525. // Post-fix some opcodes
  526. switch(msg.opcode)
  527. {
  528. case audioMasterGetTime:
  529. // VstTimeInfo* in [return value]
  530. if(msg.result != 0)
  531. {
  532. m_sharedMem->timeInfo = *FromIntPtr<VstTimeInfo>(result);
  533. }
  534. break;
  535. case audioMasterGetDirectory:
  536. // char* in [return value]
  537. if(msg.result != 0)
  538. {
  539. char *target = static_cast<char *>(ptr);
  540. strncpy(target, FromIntPtr<const char>(result), static_cast<size_t>(msg.ptr - 1));
  541. target[msg.ptr - 1] = 0;
  542. }
  543. break;
  544. case audioMasterOpenFileSelector:
  545. if(msg.result != 0)
  546. {
  547. std::vector<char> fileSelect;
  548. TranslateVstFileSelectToBridge(fileSelect, *static_cast<const VstFileSelect *>(ptr), m_otherPtrSize);
  549. std::memcpy(origPtr, fileSelect.data(), std::min(fileSelect.size(), static_cast<size_t>(msg.ptr)));
  550. // Directly free memory on host side, we don't need it anymore
  551. CVstPlugin::MasterCallBack(&m_sharedMem->effect, audioMasterCloseFileSelector, msg.index, static_cast<intptr_t>(msg.value), ptr, msg.opt);
  552. }
  553. break;
  554. }
  555. }
  556. intptr_t VSTCALLBACK BridgeWrapper::DispatchToPlugin(AEffect *effect, VstOpcodeToPlugin opcode, int32 index, intptr_t value, void *ptr, float opt)
  557. {
  558. BridgeWrapper *that = static_cast<BridgeWrapper *>(effect->object);
  559. if(that != nullptr)
  560. {
  561. return that->DispatchToPlugin(opcode, index, value, ptr, opt);
  562. }
  563. return 0;
  564. }
  565. intptr_t BridgeWrapper::DispatchToPlugin(VstOpcodeToPlugin opcode, int32 index, intptr_t value, void *ptr, float opt)
  566. {
  567. std::vector<char> dispatchData(sizeof(DispatchMsg), 0);
  568. int64 ptrOut = 0;
  569. bool copyPtrBack = false, ptrIsSize = true;
  570. char *ptrC = static_cast<char *>(ptr);
  571. switch(opcode)
  572. {
  573. case effGetParamLabel:
  574. case effGetParamDisplay:
  575. case effGetParamName:
  576. if(index >= m_cachedParamInfoStart && index < m_cachedParamInfoStart + mpt::saturate_cast<int32>(m_cachedParamInfo.size()))
  577. {
  578. if(opcode == effGetParamLabel)
  579. strcpy(ptrC, m_cachedParamInfo[index - m_cachedParamInfoStart].label);
  580. else if(opcode == effGetParamDisplay)
  581. strcpy(ptrC, m_cachedParamInfo[index - m_cachedParamInfoStart].display);
  582. else if(opcode == effGetParamName)
  583. strcpy(ptrC, m_cachedParamInfo[index - m_cachedParamInfoStart].name);
  584. return 1;
  585. }
  586. [[fallthrough]];
  587. case effGetProgramName:
  588. case effString2Parameter:
  589. case effGetProgramNameIndexed:
  590. case effGetEffectName:
  591. case effGetErrorText:
  592. case effGetVendorString:
  593. case effGetProductString:
  594. case effShellGetNextPlugin:
  595. // Name in [ptr]
  596. if(opcode == effGetProgramNameIndexed && !m_cachedProgNames.empty())
  597. {
  598. // First check if we have cached this program name
  599. if(index >= m_cachedProgNameStart && index < m_cachedProgNameStart + mpt::saturate_cast<int32>(m_cachedProgNames.size() / kCachedProgramNameLength))
  600. {
  601. strcpy(ptrC, &m_cachedProgNames[(index - m_cachedProgNameStart) * kCachedProgramNameLength]);
  602. return 1;
  603. }
  604. }
  605. ptrOut = 256;
  606. copyPtrBack = true;
  607. break;
  608. case effSetProgramName:
  609. m_cachedProgNames.clear();
  610. [[fallthrough]];
  611. case effCanDo:
  612. // char* in [ptr]
  613. ptrOut = strlen(ptrC) + 1;
  614. dispatchData.insert(dispatchData.end(), ptrC, ptrC + ptrOut);
  615. break;
  616. case effIdle:
  617. // The plugin bridge will generate these messages by itself
  618. return 0;
  619. case effEditGetRect:
  620. // ERect** in [ptr]
  621. ptrOut = sizeof(ERect);
  622. copyPtrBack = true;
  623. break;
  624. case effEditOpen:
  625. // HWND in [ptr] - Note: Window handles are interoperable between 32-bit and 64-bit applications in Windows (http://msdn.microsoft.com/en-us/library/windows/desktop/aa384203%28v=vs.85%29.aspx)
  626. ptrOut = reinterpret_cast<int64>(ptr);
  627. ptrIsSize = false;
  628. m_cachedProgNames.clear();
  629. m_cachedParamInfo.clear();
  630. break;
  631. case effEditIdle:
  632. // The plugin bridge will generate these messages by itself
  633. return 0;
  634. case effGetChunk:
  635. // void** in [ptr] for chunk data address
  636. {
  637. static uint32 chunkId = 0;
  638. const std::wstring mapName = L"Local\\openmpt-" + mpt::wfmt::val(GetCurrentProcessId()) + L"-chunkdata-" + mpt::wfmt::val(chunkId++);
  639. ptrOut = (mapName.length() + 1) * sizeof(wchar_t);
  640. PushToVector(dispatchData, *mapName.c_str(), static_cast<size_t>(ptrOut));
  641. }
  642. break;
  643. case effSetChunk:
  644. // void* in [ptr] for chunk data
  645. ptrOut = value;
  646. dispatchData.insert(dispatchData.end(), ptrC, ptrC + value);
  647. m_cachedProgNames.clear();
  648. m_cachedParamInfo.clear();
  649. break;
  650. case effProcessEvents:
  651. // VstEvents* in [ptr]
  652. // We process in a separate memory segment to save a bridge communication message.
  653. {
  654. std::vector<char> events;
  655. TranslateVstEventsToBridge(events, *static_cast<VstEvents *>(ptr), m_otherPtrSize);
  656. if(m_eventMem.Size() < events.size())
  657. {
  658. // Resize memory
  659. static uint32 chunkId = 0;
  660. const std::wstring mapName = L"Local\\openmpt-" + mpt::wfmt::val(GetCurrentProcessId()) + L"-events-" + mpt::wfmt::val(chunkId++);
  661. ptrOut = (mapName.length() + 1) * sizeof(wchar_t);
  662. PushToVector(dispatchData, *mapName.c_str(), static_cast<size_t>(ptrOut));
  663. m_eventMem.Create(mapName.c_str(), static_cast<uint32>(events.size() + 1024));
  664. opcode = effVendorSpecific;
  665. index = kVendorOpenMPT;
  666. value = kUpdateEventMemName;
  667. }
  668. std::memcpy(m_eventMem.Data(), events.data(), events.size());
  669. }
  670. if(opcode != effVendorSpecific)
  671. {
  672. return 1;
  673. }
  674. break;
  675. case effGetInputProperties:
  676. case effGetOutputProperties:
  677. // VstPinProperties* in [ptr]
  678. ptrOut = sizeof(VstPinProperties);
  679. copyPtrBack = true;
  680. break;
  681. case effOfflineNotify:
  682. // VstAudioFile* in [ptr]
  683. ptrOut = sizeof(VstAudioFile) * value;
  684. // TODO
  685. return 0;
  686. break;
  687. case effOfflinePrepare:
  688. case effOfflineRun:
  689. // VstOfflineTask* in [ptr]
  690. ptrOut = sizeof(VstOfflineTask) * value;
  691. // TODO
  692. return 0;
  693. break;
  694. case effProcessVarIo:
  695. // VstVariableIo* in [ptr]
  696. ptrOut = sizeof(VstVariableIo);
  697. // TODO
  698. return 0;
  699. break;
  700. case effSetSpeakerArrangement:
  701. // VstSpeakerArrangement* in [value] and [ptr]
  702. ptrOut = sizeof(VstSpeakerArrangement) * 2;
  703. PushToVector(dispatchData, *static_cast<VstSpeakerArrangement *>(ptr));
  704. PushToVector(dispatchData, *FromIntPtr<VstSpeakerArrangement>(value));
  705. break;
  706. case effVendorSpecific:
  707. if(index == kVendorOpenMPT)
  708. {
  709. switch(value)
  710. {
  711. case kGetWrapperPointer:
  712. return ToIntPtr<BridgeWrapper>(this);
  713. case kCloseOldProcessingMemory:
  714. {
  715. intptr_t result = m_oldProcessMem.Good();
  716. m_oldProcessMem.Close();
  717. return result;
  718. }
  719. case kCacheProgramNames:
  720. {
  721. int32 *prog = static_cast<int32 *>(ptr);
  722. m_cachedProgNameStart = prog[0];
  723. ptrOut = std::max(static_cast<int64>(sizeof(int32) * 2), static_cast<int64>((prog[1] - prog[0]) * kCachedProgramNameLength));
  724. dispatchData.insert(dispatchData.end(), ptrC, ptrC + 2 * sizeof(int32));
  725. }
  726. break;
  727. case kCacheParameterInfo:
  728. {
  729. int32 *param = static_cast<int32 *>(ptr);
  730. m_cachedParamInfoStart = param[0];
  731. ptrOut = std::max(static_cast<int64>(sizeof(int32) * 2), static_cast<int64>((param[1] - param[0]) * sizeof(ParameterInfo)));
  732. dispatchData.insert(dispatchData.end(), ptrC, ptrC + 2 * sizeof(int32));
  733. }
  734. break;
  735. case kBeginGetProgram:
  736. ptrOut = m_sharedMem->effect.numParams * sizeof(float);
  737. break;
  738. case kEndGetProgram:
  739. m_cachedParamValues.clear();
  740. return 1;
  741. }
  742. }
  743. break;
  744. case effGetTailSize:
  745. return m_sharedMem->tailSize;
  746. case effGetParameterProperties:
  747. // VstParameterProperties* in [ptr]
  748. if(index >= m_cachedParamInfoStart && index < m_cachedParamInfoStart + mpt::saturate_cast<int32>(m_cachedParamInfo.size()))
  749. {
  750. *static_cast<VstParameterProperties *>(ptr) = m_cachedParamInfo[index - m_cachedParamInfoStart].props;
  751. return 1;
  752. }
  753. ptrOut = sizeof(VstParameterProperties);
  754. copyPtrBack = true;
  755. break;
  756. case effGetMidiProgramName:
  757. case effGetCurrentMidiProgram:
  758. // MidiProgramName* in [ptr]
  759. ptrOut = sizeof(MidiProgramName);
  760. copyPtrBack = true;
  761. break;
  762. case effGetMidiProgramCategory:
  763. // MidiProgramCategory* in [ptr]
  764. ptrOut = sizeof(MidiProgramCategory);
  765. copyPtrBack = true;
  766. break;
  767. case effGetMidiKeyName:
  768. // MidiKeyName* in [ptr]
  769. ptrOut = sizeof(MidiKeyName);
  770. copyPtrBack = true;
  771. break;
  772. case effBeginSetProgram:
  773. m_isSettingProgram = true;
  774. break;
  775. case effEndSetProgram:
  776. m_isSettingProgram = false;
  777. if(m_sharedMem->automationQueue.pendingEvents)
  778. {
  779. SendAutomationQueue();
  780. }
  781. m_cachedProgNames.clear();
  782. m_cachedParamInfo.clear();
  783. break;
  784. case effGetSpeakerArrangement:
  785. // VstSpeakerArrangement* in [value] and [ptr]
  786. ptrOut = sizeof(VstSpeakerArrangement) * 2;
  787. copyPtrBack = true;
  788. break;
  789. case effBeginLoadBank:
  790. case effBeginLoadProgram:
  791. // VstPatchChunkInfo* in [ptr]
  792. ptrOut = sizeof(VstPatchChunkInfo);
  793. m_cachedProgNames.clear();
  794. m_cachedParamInfo.clear();
  795. break;
  796. default:
  797. MPT_ASSERT(ptr == nullptr);
  798. }
  799. if(ptrOut != 0 && ptrIsSize)
  800. {
  801. // In case we only reserve space and don't copy stuff over...
  802. dispatchData.resize(sizeof(DispatchMsg) + static_cast<size_t>(ptrOut), 0);
  803. }
  804. uint32 extraSize = static_cast<uint32>(dispatchData.size() - sizeof(DispatchMsg));
  805. // Create message header
  806. BridgeMessage &msg = *reinterpret_cast<BridgeMessage *>(dispatchData.data());
  807. msg.Dispatch(opcode, index, value, ptrOut, opt, extraSize);
  808. const bool useAuxMem = dispatchData.size() > sizeof(BridgeMessage);
  809. AuxMem *auxMem = nullptr;
  810. if(useAuxMem)
  811. {
  812. // Extra data doesn't fit in message - use secondary memory
  813. if(dispatchData.size() > std::numeric_limits<uint32>::max())
  814. return 0;
  815. auxMem = GetAuxMemory(mpt::saturate_cast<uint32>(dispatchData.size()));
  816. if(auxMem == nullptr)
  817. return 0;
  818. // First, move message data to shared memory...
  819. std::memcpy(auxMem->memory.Data(), &dispatchData[sizeof(DispatchMsg)], extraSize);
  820. // ...Now put the shared memory name in the message instead.
  821. std::memcpy(&dispatchData[sizeof(DispatchMsg)], auxMem->name, sizeof(auxMem->name));
  822. }
  823. try
  824. {
  825. if(!SendToBridge(msg) && opcode != effClose)
  826. {
  827. return 0;
  828. }
  829. } catch(...)
  830. {
  831. // Don't do anything for now.
  832. #if 0
  833. if(opcode != effClose)
  834. {
  835. throw;
  836. }
  837. #endif
  838. }
  839. const DispatchMsg &resultMsg = msg.dispatch;
  840. // cppcheck false-positive
  841. // cppcheck-suppress nullPointerRedundantCheck
  842. const void *extraData = useAuxMem ? auxMem->memory.Data<const char>() : reinterpret_cast<const char *>(&resultMsg + 1);
  843. // Post-fix some opcodes
  844. switch(opcode)
  845. {
  846. case effClose:
  847. m_sharedMem->effect.object = nullptr;
  848. delete this;
  849. return 0;
  850. case effGetProgramName:
  851. case effGetParamLabel:
  852. case effGetParamDisplay:
  853. case effGetParamName:
  854. case effString2Parameter:
  855. case effGetProgramNameIndexed:
  856. case effGetEffectName:
  857. case effGetErrorText:
  858. case effGetVendorString:
  859. case effGetProductString:
  860. case effShellGetNextPlugin:
  861. // Name in [ptr]
  862. strcpy(ptrC, static_cast<const char *>(extraData));
  863. break;
  864. case effEditGetRect:
  865. // ERect** in [ptr]
  866. m_editRect = *static_cast<const ERect *>(extraData);
  867. *static_cast<const ERect **>(ptr) = &m_editRect;
  868. break;
  869. case effGetChunk:
  870. // void** in [ptr] for chunk data address
  871. if(const wchar_t *str = static_cast<const wchar_t *>(extraData); m_getChunkMem.Open(str))
  872. *static_cast<void **>(ptr) = m_getChunkMem.Data();
  873. else
  874. return 0;
  875. break;
  876. case effVendorSpecific:
  877. if(index == kVendorOpenMPT && resultMsg.result == 1)
  878. {
  879. switch(value)
  880. {
  881. case kCacheProgramNames:
  882. m_cachedProgNames.assign(static_cast<const char *>(extraData), static_cast<const char *>(extraData) + ptrOut);
  883. break;
  884. case kCacheParameterInfo:
  885. {
  886. const ParameterInfo *params = static_cast<const ParameterInfo *>(extraData);
  887. m_cachedParamInfo.assign(params, params + ptrOut / sizeof(ParameterInfo));
  888. break;
  889. }
  890. case kBeginGetProgram:
  891. m_cachedParamValues.assign(static_cast<const float *>(extraData), static_cast<const float *>(extraData) + ptrOut / sizeof(float));
  892. break;
  893. }
  894. }
  895. break;
  896. case effGetSpeakerArrangement:
  897. // VstSpeakerArrangement* in [value] and [ptr]
  898. m_speakers[0] = *static_cast<const VstSpeakerArrangement *>(extraData);
  899. m_speakers[1] = *(static_cast<const VstSpeakerArrangement *>(extraData) + 1);
  900. *static_cast<VstSpeakerArrangement *>(ptr) = m_speakers[0];
  901. *FromIntPtr<VstSpeakerArrangement>(value) = m_speakers[1];
  902. break;
  903. default:
  904. // TODO: Translate VstVariableIo, offline tasks
  905. if(copyPtrBack)
  906. {
  907. std::memcpy(ptr, extraData, static_cast<size_t>(ptrOut));
  908. }
  909. }
  910. if(auxMem != nullptr)
  911. {
  912. auxMem->used = false;
  913. }
  914. return static_cast<intptr_t>(resultMsg.result);
  915. }
  916. // Allocate auxiliary shared memory for too long bridge messages
  917. BridgeWrapper::AuxMem *BridgeWrapper::GetAuxMemory(uint32 size)
  918. {
  919. std::size_t index = std::size(m_auxMems);
  920. for(int pass = 0; pass < 2; pass++)
  921. {
  922. for(std::size_t i = 0; i < std::size(m_auxMems); i++)
  923. {
  924. if(m_auxMems[i].size >= size || pass == 1)
  925. {
  926. // Good candidate - is it taken yet?
  927. bool expected = false;
  928. if(m_auxMems[i].used.compare_exchange_strong(expected, true))
  929. {
  930. index = i;
  931. break;
  932. }
  933. }
  934. }
  935. if(index != std::size(m_auxMems))
  936. break;
  937. }
  938. if(index == std::size(m_auxMems))
  939. return nullptr;
  940. AuxMem &auxMem = m_auxMems[index];
  941. if(auxMem.size >= size && auxMem.memory.Good())
  942. {
  943. // Re-use as-is
  944. return &auxMem;
  945. }
  946. // Create new memory with appropriate size
  947. static_assert(sizeof(DispatchMsg) + sizeof(auxMem.name) <= sizeof(BridgeMessage), "Check message sizes, this will crash!");
  948. static unsigned int auxMemCount = 0;
  949. mpt::String::WriteAutoBuf(auxMem.name) = MPT_WFORMAT("Local\\openmpt-{}-auxmem-{}")(GetCurrentProcessId(), auxMemCount++);
  950. if(auxMem.memory.Create(auxMem.name, size))
  951. {
  952. auxMem.size = size;
  953. return &auxMem;
  954. } else
  955. {
  956. auxMem.used = false;
  957. return nullptr;
  958. }
  959. }
  960. // Send any pending automation events
  961. void BridgeWrapper::SendAutomationQueue()
  962. {
  963. m_sigAutomation.Reset();
  964. BridgeMessage msg;
  965. msg.Automate();
  966. if(!SendToBridge(msg))
  967. {
  968. // Failed (plugin probably crashed) - auto-fix event count
  969. m_sharedMem->automationQueue.pendingEvents = 0;
  970. }
  971. m_sigAutomation.Trigger();
  972. }
  973. void VSTCALLBACK BridgeWrapper::SetParameter(AEffect *effect, int32 index, float parameter)
  974. {
  975. BridgeWrapper *that = static_cast<BridgeWrapper *>(effect->object);
  976. if(that)
  977. {
  978. try
  979. {
  980. that->SetParameter(index, parameter);
  981. } catch(...)
  982. {
  983. // Be quiet about exceptions here
  984. }
  985. }
  986. }
  987. void BridgeWrapper::SetParameter(int32 index, float parameter)
  988. {
  989. const CVstPlugin *plug = static_cast<CVstPlugin *>(m_sharedMem->effect.reservedForHost1);
  990. AutomationQueue &autoQueue = m_sharedMem->automationQueue;
  991. if(m_isSettingProgram || (plug && plug->IsResumed()))
  992. {
  993. // Queue up messages while rendering to reduce latency introduced by every single bridge call
  994. uint32 i;
  995. while((i = autoQueue.pendingEvents.fetch_add(1)) >= std::size(autoQueue.params))
  996. {
  997. // Queue full!
  998. if(i == std::size(autoQueue.params))
  999. {
  1000. // We're the first to notice that it's full
  1001. SendAutomationQueue();
  1002. } else
  1003. {
  1004. // Wait until queue is emptied by someone else (this branch is very unlikely to happen)
  1005. WaitForSingleObject(m_sigAutomation, INFINITE);
  1006. }
  1007. }
  1008. autoQueue.params[i].index = index;
  1009. autoQueue.params[i].value = parameter;
  1010. return;
  1011. } else if(autoQueue.pendingEvents)
  1012. {
  1013. // Actually, this should never happen as pending events are cleared before processing and at the end of a set program event.
  1014. SendAutomationQueue();
  1015. }
  1016. BridgeMessage msg;
  1017. msg.SetParameter(index, parameter);
  1018. SendToBridge(msg);
  1019. }
  1020. float VSTCALLBACK BridgeWrapper::GetParameter(AEffect *effect, int32 index)
  1021. {
  1022. BridgeWrapper *that = static_cast<BridgeWrapper *>(effect->object);
  1023. if(that)
  1024. {
  1025. if(static_cast<size_t>(index) < that->m_cachedParamValues.size())
  1026. return that->m_cachedParamValues[index];
  1027. try
  1028. {
  1029. return that->GetParameter(index);
  1030. } catch(...)
  1031. {
  1032. // Be quiet about exceptions here
  1033. }
  1034. }
  1035. return 0.0f;
  1036. }
  1037. float BridgeWrapper::GetParameter(int32 index)
  1038. {
  1039. BridgeMessage msg;
  1040. msg.GetParameter(index);
  1041. if(SendToBridge(msg))
  1042. {
  1043. return msg.parameter.value;
  1044. }
  1045. return 0.0f;
  1046. }
  1047. void VSTCALLBACK BridgeWrapper::Process(AEffect *effect, float **inputs, float **outputs, int32 sampleFrames)
  1048. {
  1049. BridgeWrapper *that = static_cast<BridgeWrapper *>(effect->object);
  1050. if(sampleFrames != 0 && that != nullptr)
  1051. {
  1052. that->BuildProcessBuffer(ProcessMsg::process, effect->numInputs, effect->numOutputs, inputs, outputs, sampleFrames);
  1053. }
  1054. }
  1055. void VSTCALLBACK BridgeWrapper::ProcessReplacing(AEffect *effect, float **inputs, float **outputs, int32 sampleFrames)
  1056. {
  1057. BridgeWrapper *that = static_cast<BridgeWrapper *>(effect->object);
  1058. if(sampleFrames != 0 && that != nullptr)
  1059. {
  1060. that->BuildProcessBuffer(ProcessMsg::processReplacing, effect->numInputs, effect->numOutputs, inputs, outputs, sampleFrames);
  1061. }
  1062. }
  1063. void VSTCALLBACK BridgeWrapper::ProcessDoubleReplacing(AEffect *effect, double **inputs, double **outputs, int32 sampleFrames)
  1064. {
  1065. BridgeWrapper *that = static_cast<BridgeWrapper *>(effect->object);
  1066. if(sampleFrames != 0 && that != nullptr)
  1067. {
  1068. that->BuildProcessBuffer(ProcessMsg::processDoubleReplacing, effect->numInputs, effect->numOutputs, inputs, outputs, sampleFrames);
  1069. }
  1070. }
  1071. template <typename buf_t>
  1072. void BridgeWrapper::BuildProcessBuffer(ProcessMsg::ProcessType type, int32 numInputs, int32 numOutputs, buf_t **inputs, buf_t **outputs, int32 sampleFrames)
  1073. {
  1074. if(!m_processMem.Good())
  1075. {
  1076. MPT_ASSERT_NOTREACHED();
  1077. return;
  1078. }
  1079. ProcessMsg *processMsg = m_processMem.Data<ProcessMsg>();
  1080. new(processMsg) ProcessMsg{type, numInputs, numOutputs, sampleFrames};
  1081. // Anticipate that many plugins will query the play position in a process call and send it along the process call
  1082. // to save some valuable inter-process calls.
  1083. m_sharedMem->timeInfo = *FromIntPtr<VstTimeInfo>(CVstPlugin::MasterCallBack(&m_sharedMem->effect, audioMasterGetTime, 0, kVstNanosValid | kVstPpqPosValid | kVstTempoValid | kVstBarsValid | kVstCyclePosValid | kVstTimeSigValid | kVstSmpteValid | kVstClockValid, nullptr, 0.0f));
  1084. buf_t *ptr = reinterpret_cast<buf_t *>(processMsg + 1);
  1085. for(int32 i = 0; i < numInputs; i++)
  1086. {
  1087. std::memcpy(ptr, inputs[i], sampleFrames * sizeof(buf_t));
  1088. ptr += sampleFrames;
  1089. }
  1090. // Theoretically, we should memcpy() instead of memset() here in process(), but OpenMPT always clears the output buffer before processing so it doesn't matter.
  1091. memset(ptr, 0, numOutputs * sampleFrames * sizeof(buf_t));
  1092. // In case we called Process() from the GUI thread (panic button or song stop => CSoundFile::SuspendPlugins)
  1093. m_isAudioThread = true;
  1094. m_sigProcessAudio.Send();
  1095. const HANDLE objects[] = {m_sigProcessAudio.confirm, m_sigToHostAudio.send, m_otherProcess};
  1096. DWORD result;
  1097. do
  1098. {
  1099. result = WaitForMultipleObjects(mpt::saturate_cast<DWORD>(std::size(objects)), objects, FALSE, INFINITE);
  1100. if(result == WAIT_OBJECT_0 + 1)
  1101. {
  1102. ParseNextMessage(m_sharedMem->audioThreadToHostMsgID);
  1103. m_sigToHostAudio.Confirm();
  1104. }
  1105. } while(result != WAIT_OBJECT_0 && result != WAIT_OBJECT_0 + 2 && result != WAIT_FAILED);
  1106. m_isAudioThread = false;
  1107. for(int32 i = 0; i < numOutputs; i++)
  1108. {
  1109. //std::memcpy(outputs[i], ptr, sampleFrames * sizeof(buf_t));
  1110. outputs[i] = ptr; // Exactly what you don't want plugins to do usually (bend your output pointers)... muahahaha!
  1111. ptr += sampleFrames;
  1112. }
  1113. // Did we receive any audioMasterProcessEvents data?
  1114. if(auto *events = m_eventMem.Data<int32>(); events != nullptr && *events != 0)
  1115. {
  1116. std::vector<char> eventCache;
  1117. TranslateBridgeToVstEvents(eventCache, events);
  1118. *events = 0;
  1119. CVstPlugin::MasterCallBack(&m_sharedMem->effect, audioMasterProcessEvents, 0, 0, eventCache.data(), 0.0f);
  1120. }
  1121. }
  1122. LRESULT CALLBACK BridgeWrapper::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1123. {
  1124. if(hwnd == m_communicationWindow && wParam < m_plugins.size())
  1125. {
  1126. auto *that = static_cast<BridgeWrapper *>(m_plugins[wParam]);
  1127. if(that != nullptr && uMsg == WM_BRIDGE_MESSAGE_TO_HOST)
  1128. {
  1129. that->ParseNextMessage(static_cast<int>(lParam));
  1130. return WM_BRIDGE_SUCCESS;
  1131. }
  1132. }
  1133. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  1134. }
  1135. #endif // MPT_WITH_VST
  1136. OPENMPT_NAMESPACE_END