From: <sag...@us...> - 2013-11-12 20:54:23
|
Revision: 3198 http://sourceforge.net/p/modplug/code/3198 Author: saga-games Date: 2013-11-12 20:54:13 +0000 (Tue, 12 Nov 2013) Log Message: ----------- [Ref] Moved some code from Vstplug.cpp to DmoToVst.cpp and PluginManager.cpp to make this monster slightly less bulky. Modified Paths: -------------- trunk/OpenMPT/common/misc_util.cpp trunk/OpenMPT/common/misc_util.h trunk/OpenMPT/mptrack/Vstplug.cpp trunk/OpenMPT/mptrack/Vstplug.h trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp Added Paths: ----------- trunk/OpenMPT/soundlib/plugins/DmoToVst.cpp trunk/OpenMPT/soundlib/plugins/PluginManager.cpp Modified: trunk/OpenMPT/common/misc_util.cpp =================================================================== --- trunk/OpenMPT/common/misc_util.cpp 2013-11-12 20:26:19 UTC (rev 3197) +++ trunk/OpenMPT/common/misc_util.cpp 2013-11-12 20:54:13 UTC (rev 3198) @@ -131,3 +131,43 @@ #endif // ENABLE_ASM + + +#ifdef MODPLUG_TRACKER + +namespace Util +{ + std::wstring CLSIDToString(CLSID clsid) + //------------------------------------- + { + std::wstring str; + LPOLESTR tmp = nullptr; + StringFromCLSID(clsid, &tmp); + if(tmp) + { + str = tmp; + CoTaskMemFree(tmp); + tmp = nullptr; + } + return str; + } + + + bool StringToCLSID(const std::wstring &str, CLSID &clsid) + //------------------------------------------------------- + { + std::vector<OLECHAR> tmp(str.c_str(), str.c_str() + str.length() + 1); + return CLSIDFromString(&tmp[0], &clsid) == S_OK; + } + + + bool IsCLSID(const std::wstring &str) + //----------------------------------- + { + CLSID clsid = CLSID(); + std::vector<OLECHAR> tmp(str.c_str(), str.c_str() + str.length() + 1); + return CLSIDFromString(&tmp[0], &clsid) == S_OK; + } +} // namespace Util + +#endif // MODPLUG_TRACKER Modified: trunk/OpenMPT/common/misc_util.h =================================================================== --- trunk/OpenMPT/common/misc_util.h 2013-11-12 20:26:19 UTC (rev 3197) +++ trunk/OpenMPT/common/misc_util.h 2013-11-12 20:54:13 UTC (rev 3198) @@ -510,3 +510,14 @@ } #endif // ENABLE_ASM + +#ifdef MODPLUG_TRACKER + +namespace Util +{ + std::wstring CLSIDToString(CLSID clsid); + bool StringToCLSID(const std::wstring &str, CLSID &clsid); + bool IsCLSID(const std::wstring &str); +} // namespace Util + +#endif // MODPLUG_TRACKER \ No newline at end of file Modified: trunk/OpenMPT/mptrack/Vstplug.cpp =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.cpp 2013-11-12 20:26:19 UTC (rev 3197) +++ trunk/OpenMPT/mptrack/Vstplug.cpp 2013-11-12 20:54:13 UTC (rev 3198) @@ -1,7 +1,7 @@ /* * vstplug.cpp * ----------- - * Purpose: Plugin handling (loading and processing plugins) + * Purpose: Plugin handling / processing * Notes : (currently none) * Authors: OpenMPT Devs * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. @@ -9,642 +9,26 @@ #include "stdafx.h" -#include <uuids.h> -#include <dmoreg.h> -#include <shlwapi.h> -#include <medparam.h> -#include "mainfrm.h" -#include "vstplug.h" +#include "Mainfrm.h" +#include "Vstplug.h" #include "VstPresets.h" -#include "moddoc.h" -#include "Sndfile.h" -#include "AbstractVstEditor.h" //rewbs.defaultPlugGUI -#include "VstEditor.h" //rewbs.defaultPlugGUI -#include "defaultvsteditor.h" //rewbs.defaultPlugGUI +#include "Moddoc.h" +#include "../soundlib/Sndfile.h" +#include "AbstractVstEditor.h" +#include "VstEditor.h" +#include "DefaultVstEditor.h" #include "../soundlib/MIDIEvents.h" -#include "../common/version.h" -#include "midimappingdialog.h" +#include "MIDIMappingDialog.h" #include "../common/StringFixer.h" #include "MemoryMappedFile.h" #include "../soundlib/FileReader.h" -#include "../soundlib/plugins/JBridge.h" #include "FileDialog.h" #include "../common/mptFstream.h" -#ifdef VST_USE_ALTERNATIVE_MAGIC //Pelya's plugin ID fix. Breaks fx presets, so let's avoid it for now. -#include "../zlib/zlib.h" //For CRC32 calculation (to detect plugins with same UID) -#endif // VST_USE_ALTERNATIVE_MAGIC #ifndef NO_VST -char CVstPluginManager::s_szHostProductString[64] = "OpenMPT"; -char CVstPluginManager::s_szHostVendorString[64] = "OpenMPT project"; -VstIntPtr CVstPluginManager::s_nHostVendorVersion = MptVersion::num; - //#define VST_LOG -#define DMO_LOG -AEffect *DmoToVst(VSTPluginLib *pLib); - -#ifdef VST_USE_ALTERNATIVE_MAGIC -UINT32 CalculateCRC32fromFilename(const char *s) -//---------------------------------------------- -{ - char fn[_MAX_PATH]; - mpt::String::Copy(fn, s); - int f; - for(f = 0; fn[f] != 0; f++) fn[f] = toupper(fn[f]); - return LittleEndian(crc32(0, (BYTE *)fn, f)); - -} -#endif // VST_USE_ALTERNATIVE_MAGIC - - -static HRESULT CLSIDFromWString(const std::wstring &str, CLSID *clsid) -//-------------------------------------------------------------------- -{ - std::vector<OLECHAR> tmp(str.c_str(), str.c_str() + str.length() + 1); - return CLSIDFromString(&tmp[0], clsid); -} - - -VstIntPtr VSTCALLBACK CVstPluginManager::MasterCallBack(AEffect *effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void *ptr, float opt) -//---------------------------------------------------------------------------------------------------------------------------------------------- -{ - CVstPluginManager *that = theApp.GetPluginManager(); - if (that) - { - return that->VstCallback(effect, opcode, index, value, ptr, opt); - } - return 0; -} - - -bool CVstPluginManager::CreateMixPluginProc(SNDMIXPLUGIN &mixPlugin, CSoundFile &sndFile) -//--------------------------------------------------------------------------------------- -{ - CVstPluginManager *that = theApp.GetPluginManager(); - if(that) - { - return that->CreateMixPlugin(mixPlugin, sndFile); - } - return false; -} - - -CVstPluginManager::CVstPluginManager() -//------------------------------------ -{ - m_pVstHead = nullptr; - //m_bNeedIdle = FALSE; //rewbs.VSTCompliance - now member of plugin class - CSoundFile::gpMixPluginCreateProc = CreateMixPluginProc; - EnumerateDirectXDMOs(); -} - - -CVstPluginManager::~CVstPluginManager() -//------------------------------------- -{ - CSoundFile::gpMixPluginCreateProc = nullptr; - while (m_pVstHead) - { - VSTPluginLib *p = m_pVstHead; - m_pVstHead = m_pVstHead->pNext; - if (m_pVstHead) m_pVstHead->pPrev = nullptr; - p->pPrev = p->pNext = nullptr; - while ((volatile void *)(p->pPluginsList) != nullptr) - { - p->pPluginsList->Release(); - } - delete p; - } -} - - -bool CVstPluginManager::IsValidPlugin(const VSTPluginLib *pLib) -//------------------------------------------------------------- -{ - VSTPluginLib *p = m_pVstHead; - while (p) - { - if (p == pLib) return true; - p = p->pNext; - } - return false; -} - - -void CVstPluginManager::EnumerateDirectXDMOs() -//-------------------------------------------- -{ - HKEY hkEnum; - WCHAR keyname[128]; - LONG cr; - DWORD index; - - cr = RegOpenKey(HKEY_LOCAL_MACHINE, "software\\classes\\DirectShow\\MediaObjects\\Categories\\f3602b3f-0592-48df-a4cd-674721e7ebeb", &hkEnum); - index = 0; - while (cr == ERROR_SUCCESS) - { - if ((cr = RegEnumKeyW(hkEnum, index, keyname, CountOf(keyname))) == ERROR_SUCCESS) - { - CLSID clsid; - std::wstring formattedKey = std::wstring(L"{") + std::wstring(keyname) + std::wstring(L"}"); - if(CLSIDFromWString(formattedKey, &clsid) == S_OK) - { - HKEY hksub; - formattedKey = std::wstring(L"software\\classes\\DirectShow\\MediaObjects\\") + std::wstring(keyname); - if (RegOpenKeyW(HKEY_LOCAL_MACHINE, formattedKey.c_str(), &hksub) == ERROR_SUCCESS) - { - WCHAR name[64]; - DWORD datatype = REG_SZ; - DWORD datasize = sizeof(name); - - if(ERROR_SUCCESS == RegQueryValueExW(hksub, nullptr, 0, &datatype, (LPBYTE)name, &datasize)) - { - StringFromGUID2(clsid, keyname, 100); - - VSTPluginLib *p = new VSTPluginLib(mpt::PathString::FromWide(keyname), mpt::PathString::FromWide(name)); - p->pNext = m_pVstHead; - p->pluginId1 = kDmoMagic; - p->pluginId2 = clsid.Data1; - p->category = VSTPluginLib::catDMO; - #ifdef DMO_LOG - Log("Found \"%s\" clsid=%s\n", p->libraryName.AsNative().c_str(), p->dllPath.AsNative().c_str()); - #endif - if (m_pVstHead) m_pVstHead->pPrev = p; - m_pVstHead = p; - } - RegCloseKey(hksub); - } - } - } - index++; - } - if (hkEnum) RegCloseKey(hkEnum); -} - - -void CVstPluginManager::LoadPlugin(const mpt::PathString &pluginPath, AEffect *&effect, HINSTANCE &library) -//--------------------------------------------------------------------------------------------------------- -{ - library = nullptr; - effect = nullptr; - - try - { - library = LoadLibraryW(pluginPath.ToWide().c_str()); - - if(library == nullptr) - { - DWORD error = GetLastError(); - -#ifdef _DEBUG - if(error != ERROR_MOD_NOT_FOUND) // "File not found errors" are annoying. - { - TCHAR szBuf[256]; - wsprintf(szBuf, "Warning: encountered problem when loading plugin dll. Error %x: %s", error, GetErrorMessage(error).c_str()); - Reporting::Error(szBuf, "DEBUG: Error when loading plugin dll"); - } -#endif //_DEBUG - - if(error == ERROR_MOD_NOT_FOUND) - { - // No point in trying with JBride, either... - return; - } - } - } catch(...) - { - CVstPluginManager::ReportPlugException("Exception caught in LoadLibrary (%s)", pluginPath.ToLocale().c_str()); - } - - if(library != nullptr && library != INVALID_HANDLE_VALUE) - { - // Try loading the VST plugin. - PVSTPLUGENTRY pMainProc = (PVSTPLUGENTRY)GetProcAddress(library, "VSTPluginMain"); - if(pMainProc == nullptr) - { - pMainProc = (PVSTPLUGENTRY)GetProcAddress(library, "main"); - } - - if(pMainProc != nullptr) - { - effect = pMainProc(MasterCallBack); - } else - { -#ifdef VST_LOG - Log("Entry point not found! (handle=%08X)\n", library); -#endif // VST_LOG - } - } - - if(effect == nullptr) - { - // Try loading the plugin using JBridge instead. - FreeLibrary(library); - library = nullptr; - effect = JBridge::LoadBridgedPlugin(MasterCallBack, pluginPath); - } -} - - -// Extract instrument and category information from plugin. -void GetPluginInformation(AEffect *effect, VSTPluginLib &library) -//--------------------------------------------------------------- -{ - library.category = static_cast<VSTPluginLib::PluginCategory>(effect->dispatcher(effect, effGetPlugCategory, 0, 0, nullptr, 0.0f)); - library.isInstrument = ((effect->flags & effFlagsIsSynth) || !effect->numInputs); - - if(library.isInstrument) - { - library.category = VSTPluginLib::catSynth; - } else if(library.category >= VSTPluginLib::numCategories) - { - library.category = VSTPluginLib::catUnknown; - } -} - - -// -// PluginCache format: -// LibraryName = ID100000ID200000 -// ID100000ID200000 = FullDllPath -// ID100000ID200000.Flags = Plugin Flags (isInstrument + category). - -VSTPluginLib *CVstPluginManager::AddPlugin(const mpt::PathString &dllPath, bool fromCache, const bool checkFileExistence, CString *const errStr) -//---------------------------------------------------------------------------------------------------------------------------------------------- -{ - const mpt::PathString fileName = dllPath.GetFileName(); - - if(checkFileExistence && (PathFileExistsW(dllPath.AsNative().c_str()) == FALSE)) - { - if(errStr) - { - *errStr += "\nUnable to find "; - *errStr += dllPath.ToCString(); - } - } - - VSTPluginLib *pDup = m_pVstHead; - while(pDup != nullptr) - { - if(!dllPath.CompareNoCase(dllPath, pDup->dllPath)) return pDup; - pDup = pDup->pNext; - } - // Look if the plugin info is stored in the PluginCache - if(fromCache) - { - const char *cacheSection = "PluginCache"; - SettingsContainer & cacheFile = theApp.GetPluginCache(); - - std::string IDs = cacheFile.Read<std::string>(cacheSection, fileName.ToLocale(), ""); - - if(IDs.length() >= 16) - { - // Get path from cache file - mpt::PathString realPath = cacheFile.Read<mpt::PathString>(cacheSection, IDs, MPT_PATHSTRING("")); - realPath = theApp.RelativePathToAbsolute(realPath); - - if(!realPath.empty() && !dllPath.CompareNoCase(realPath, dllPath)) - { - VSTPluginLib *p = new (std::nothrow) VSTPluginLib(dllPath, fileName); - if(p == nullptr) - { - return nullptr; - } - p->pNext = m_pVstHead; - if (m_pVstHead) m_pVstHead->pPrev = p; - m_pVstHead = p; - - // Extract plugin Ids - for (UINT i=0; i<16; i++) - { - UINT n = IDs[i] - '0'; - if (n > 9) n = IDs[i] + 10 - 'A'; - n &= 0x0f; - if (i < 8) - { - p->pluginId1 = (p->pluginId1 << 4) | n; - } else - { - p->pluginId2 = (p->pluginId2 << 4) | n; - } - } - - std::string flagKey = mpt::String::Format("%s.Flags", IDs.c_str()); - p->DecodeCacheFlags(cacheFile.Read<int32>(cacheSection, flagKey, 0)); - - #ifdef VST_USE_ALTERNATIVE_MAGIC - if( p->pluginId1 == kEffectMagic ) - { - p->pluginId1 = CalculateCRC32fromFilename(p->libraryName); // Make Plugin ID unique for sure (for VSTs with same UID) - }; - #endif // VST_USE_ALTERNATIVE_MAGIC - #ifdef VST_LOG - Log("Plugin \"%s\" found in PluginCache\n", p->libraryName); - #endif // VST_LOG - return p; - } else - { - #ifdef VST_LOG - Log("Plugin \"%s\" mismatch in PluginCache: \"%s\" [%s]=\"%s\"\n", s, dllPath, (LPCTSTR)IDs, (LPCTSTR)strFullPath); - #endif // VST_LOG - } - } - } - - // If this key contains a file name on program launch, a plugin previously crashed OpenMPT. - theApp.GetSettings().Write<mpt::PathString>("VST Plugins", "FailedPlugin", dllPath); - - AEffect *pEffect; - HINSTANCE hLib; - bool validPlug = false; - - VSTPluginLib *p = new (std::nothrow) VSTPluginLib(dllPath, fileName); - if(p == nullptr) - { - return nullptr; - } - p->pNext = m_pVstHead; - - try - { - LoadPlugin(dllPath, pEffect, hLib); - - if(pEffect != nullptr && pEffect->magic == kEffectMagic && pEffect->dispatcher != nullptr) - { - pEffect->dispatcher(pEffect, effOpen, 0, 0, 0, 0); - - if (m_pVstHead) m_pVstHead->pPrev = p; - m_pVstHead = p; - -#ifdef VST_USE_ALTERNATIVE_MAGIC - p->pluginId1 = CalculateCRC32fromFilename(p->libraryName); // Make Plugin ID unique for sure -#else - p->pluginId1 = pEffect->magic; -#endif // VST_USE_ALTERNATIVE_MAGIC - p->pluginId2 = pEffect->uniqueID; - - GetPluginInformation(pEffect, *p); - -#ifdef VST_LOG - int nver = pEffect->dispatcher(pEffect, effGetVstVersion, 0,0, nullptr, 0); - if (!nver) nver = pEffect->version; - Log("%-20s: v%d.0, %d in, %d out, %2d programs, %2d params, flags=0x%04X realQ=%d offQ=%d\n", - p->libraryName, nver, - pEffect->numInputs, pEffect->numOutputs, - pEffect->numPrograms, pEffect->numParams, - pEffect->flags, pEffect->realQualities, pEffect->offQualities); -#endif // VST_LOG - - pEffect->dispatcher(pEffect, effClose, 0, 0, 0, 0); - - validPlug = true; - } - - FreeLibrary(hLib); - } catch(...) - { - CVstPluginManager::ReportPlugException("Exception while trying to load plugin \"%s\"!\n", p->libraryName); - } - - // Now it should be safe to assume that this plugin loaded properly. :) - theApp.GetSettings().Write<std::string>("VST Plugins", "FailedPlugin", ""); - - // If OK, write the information in PluginCache - if(validPlug) - { - const std::string cacheSection = "PluginCache"; - SettingsContainer & cacheFile = theApp.GetPluginCache(); - std::string IDs = mpt::String::Format("%08X%08X", p->pluginId1, p->pluginId2); - std::string flagsKey = mpt::String::Format("%s.Flags", IDs); - - mpt::PathString writePath = dllPath; - if(theApp.IsPortableMode()) - { - theApp.AbsolutePathToRelative(writePath); - } - - cacheFile.Write<mpt::PathString>(cacheSection, IDs, writePath); - cacheFile.Write<mpt::PathString>(cacheSection, IDs, dllPath); - cacheFile.Write<std::string>(cacheSection, p->libraryName.ToLocale(), IDs); - cacheFile.Write<int32>(cacheSection, flagsKey, p->EncodeCacheFlags()); - } else - { - delete p; - } - - return (validPlug ? m_pVstHead : nullptr); -} - - -bool CVstPluginManager::RemovePlugin(VSTPluginLib *pFactory) -//---------------------------------------------------------- -{ - VSTPluginLib *p = m_pVstHead; - - while (p) - { - if (p == pFactory) - { - if (p == m_pVstHead) m_pVstHead = p->pNext; - if (p->pPrev) p->pPrev->pNext = p->pNext; - if (p->pNext) p->pNext->pPrev = p->pPrev; - p->pPrev = p->pNext = nullptr; - - try - { - CriticalSection cs; - - while ((volatile void *)(p->pPluginsList) != nullptr) - { - p->pPluginsList->Release(); - } - delete p; - } catch (...) - { - CVstPluginManager::ReportPlugException("Exception while trying to release plugin \"%s\"!\n", pFactory->libraryName); - } - - return true; - } - p = p->pNext; - } - return false; -} - - -bool CVstPluginManager::CreateMixPlugin(SNDMIXPLUGIN &mixPlugin, CSoundFile &sndFile) -//----------------------------------------------------------------------------------- -{ - UINT nMatch = 0; - VSTPluginLib *pFound = nullptr; - - VSTPluginLib *p = m_pVstHead; - - while(p) - { - bool b1 = false, b2 = false; - if((p->pluginId1 == mixPlugin.Info.dwPluginId1) - && (p->pluginId2 == mixPlugin.Info.dwPluginId2)) - { - b1 = true; - } - if(!mpt::strnicmp(p->libraryName.ToLocale().c_str(), mixPlugin.GetLibraryName(), 64)) - { - b2 = true; - } - if((b1) && (b2)) - { - nMatch = 3; - pFound = p; - } else - if((b1) && (nMatch < 2)) - { - nMatch = 2; - pFound = p; - } else - if((b2) && (nMatch < 1)) - { - nMatch = 1; - pFound = p; - } - p = p->pNext; - } - - if(mixPlugin.Info.dwPluginId1 == kDmoMagic) - { - if (!pFound) return FALSE; - AEffect *pEffect = DmoToVst(pFound); - if ((pEffect) && (pEffect->dispatcher) && (pEffect->magic == kDmoMagic)) - { - bool result = false; - CVstPlugin *pVstPlug = new (std::nothrow) CVstPlugin(NULL, *pFound, mixPlugin, *pEffect, sndFile); - if(pVstPlug) - { - result = true; - } - return result; - } - } - - if((!pFound) && strcmp(mixPlugin.GetLibraryName(), "")) - { - // Try finding the plugin DLL in the plugin directory instead. - mpt::PathString fullPath; - fullPath = TrackerDirectories::Instance().GetDefaultDirectory(DIR_PLUGINS); - if(fullPath.empty()) - { - fullPath = theApp.GetAppDirPath() + MPT_PATHSTRING("Plugins\\"); - } - if(!fullPath.HasTrailingSlash()) - { - fullPath += MPT_PATHSTRING("\\"); - } - fullPath += mpt::PathString::FromLocale(mixPlugin.GetLibraryName()) + MPT_PATHSTRING(".dll"); - - pFound = AddPlugin(fullPath); - if(!pFound) - { - std::string cacheSection = "PluginCache"; - SettingsContainer & cacheFile = theApp.GetPluginCache(); - std::string IDs = cacheFile.Read<std::string>(cacheSection, mixPlugin.GetLibraryName(), ""); - if (IDs.length() >= 16) - { - fullPath = cacheFile.Read<mpt::PathString>(cacheSection, IDs, MPT_PATHSTRING("")); - if(!fullPath.empty()) pFound = AddPlugin(fullPath); - } - } - } - - if (pFound) - { - - AEffect *pEffect = nullptr; - HINSTANCE hLibrary = nullptr; - bool validPlugin = false; - - try - { - LoadPlugin(pFound->dllPath, pEffect, hLibrary); - - if(pEffect != nullptr && pEffect->dispatcher != nullptr && pEffect->magic == kEffectMagic) - { - validPlugin = true; - - const bool oldIsInstrument = pFound->isInstrument; - const VSTPluginLib::PluginCategory oldCategory = pFound->category; - - GetPluginInformation(pEffect, *pFound); - - if(oldIsInstrument != pFound->isInstrument || oldCategory != pFound->category) - { - // Update cached information - const std::string cacheSection = "PluginCache"; - SettingsContainer & cacheFile = theApp.GetPluginCache(); - std::string flagsKey = mpt::String::Format("%08X%08X.Flags", pFound->pluginId1, pFound->pluginId2); - cacheFile.Write<int32>(cacheSection, flagsKey, pFound->EncodeCacheFlags()); - } - - CVstPlugin *pVstPlug = new (std::nothrow) CVstPlugin(hLibrary, *pFound, mixPlugin, *pEffect, sndFile); - if(pVstPlug == nullptr) - { - validPlugin = false; - } - } - - if(!validPlugin) - { - FreeLibrary(hLibrary); - } - } catch(...) - { - CVstPluginManager::ReportPlugException("Exception while trying to create plugin \"%s\"!\n", pFound->libraryName); - } - - return validPlugin; - } else - { - // "plug not found" notification code MOVED to CSoundFile::Create - #ifdef VST_LOG - Log("Unknown plugin\n"); - #endif - } - return false; -} - - -void CVstPluginManager::OnIdle() -//------------------------------ -{ - VSTPluginLib *pFactory = m_pVstHead; - - while (pFactory) - { - CVstPlugin *p = pFactory->pPluginsList; - while (p) - { - //rewbs. VSTCompliance: A specific plug has requested indefinite periodic processing time. - if (p->m_bNeedIdle) - { - if (!(p->Dispatch(effIdle, 0, 0, nullptr, 0.0f))) - p->m_bNeedIdle=false; - } - //We need to update all open editors - if ((p->m_pEditor) && (p->m_pEditor->m_hWnd)) - { - p->m_pEditor->UpdateParamDisplays(); - } - //end rewbs. VSTCompliance: - - p = p->m_pNext; - } - pFactory = pFactory->pNext; - } - -} - -//rewbs.VSTCompliance: Added support for lots of opcodes VstIntPtr CVstPluginManager::VstCallback(AEffect *effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void *ptr, float /*opt*/) //----------------------------------------------------------------------------------------------------------------------------------- { @@ -1053,7 +437,6 @@ return 0; } -//end rewbs. VSTCompliance: // Helper function for file selection dialog stuff. @@ -1229,27 +612,6 @@ } -void CVstPluginManager::ReportPlugException(LPCSTR format,...) -//------------------------------------------------------------ -{ - CHAR cBuf[1024]; - va_list va; - va_start(va, format); - wvsprintf(cBuf, format, va); - Reporting::Notification(cBuf); -#ifdef VST_LOG - Log(cBuf); -#endif - - //Stop song - TODO: figure out why this causes a kernel hang from IASIO->release(); -/* END_CRITICAL(); - CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); - if (pMainFrm) pMainFrm->StopMod(); -*/ - va_end(va); -} - - ////////////////////////////////////////////////////////////////////////////// // // CVstPlugin @@ -1275,7 +637,7 @@ m_MixState.pOutBufferL = mixBuffer.GetInputBuffer(0); m_MixState.pOutBufferR = mixBuffer.GetInputBuffer(1); - m_bSongPlaying = false; //rewbs.VSTCompliance + m_bSongPlaying = false; m_bPlugResumed = false; m_nSampleRate = uint32_max; @@ -1490,6 +852,12 @@ } +#ifdef MODPLUG_TRACKER +CModDoc *CVstPlugin::GetModDoc() { return m_SndFile.GetpModDoc(); } +const CModDoc *CVstPlugin::GetModDoc() const { return m_SndFile.GetpModDoc(); } +#endif // MODPLUG_TRACKER + + void CVstPlugin::GetPluginType(LPSTR pszType) //------------------------------------------- { @@ -1556,7 +924,6 @@ param[p - min] = GetParameter(p); return true; - } @@ -1816,7 +1183,7 @@ CString CVstPlugin::GetParamPropertyString(VstInt32 param, VstInt32 opcode) //------------------------------------------------------------------------- { - CHAR s[MAX(kVstMaxParamStrLen + 1, 64)]; // Increased to 64 bytes since 32 bytes doesn't seem to suffice for all plugs. Kind of ridiculous if you consider that kVstMaxParamStrLen = 8... + char s[MAX(kVstMaxParamStrLen + 1, 64)]; // Increased to 64 bytes since 32 bytes doesn't seem to suffice for all plugs. Kind of ridiculous if you consider that kVstMaxParamStrLen = 8... s[0] = '\0'; if(m_Effect.numParams > 0 && param < m_Effect.numParams) @@ -2561,13 +1928,13 @@ //--------------------------------------------------------------------------------------------- { note -= NOTE_MIN; - VSTInstrChannel *pMidiCh = &m_MidiCh[midiChn & 0x0f]; + VSTInstrChannel &chn = m_MidiCh[midiChn & 0x0f]; - if (!(pMidiCh->noteOnMap[note][sourceTrackerChn])) + if(!chn.noteOnMap[note][sourceTrackerChn]) return false; - pMidiCh->noteOnMap[note][sourceTrackerChn]--; - pMidiCh->noteOnMap[note][destTrackerChn]++; + chn.noteOnMap[note][sourceTrackerChn]--; + chn.noteOnMap[note][destTrackerChn]++; return true; } //end rewbs.introVST @@ -2959,541 +2326,6 @@ } - -////////////////////////////////////////////////////////////////////////////////////////////////// -// -// DirectX Media Object support -// - -//============ -class CDmo2Vst -//============ -{ -protected: - IMediaObject *m_pMediaObject; - IMediaObjectInPlace *m_pMediaProcess; - IMediaParamInfo *m_pParamInfo; - IMediaParams *m_pMediaParams; - ULONG m_nSamplesPerSec; - AEffect m_Effect; - REFERENCE_TIME m_DataTime; - int16 *m_pMixBuffer; - int16 m_MixBuffer[MIXBUFFERSIZE * 2 + 16]; // 16-bit Stereo interleaved - -public: - CDmo2Vst(IMediaObject *pMO, IMediaObjectInPlace *pMOIP, DWORD uid); - ~CDmo2Vst(); - AEffect *GetEffect() { return &m_Effect; } - VstIntPtr Dispatcher(VstInt32 opCode, VstInt32 index, VstIntPtr value, void *ptr, float opt); - void SetParameter(VstInt32 index, float parameter); - float GetParameter(VstInt32 index); - void Process(float * const *inputs, float **outputs, int samples); - -public: - static VstIntPtr VSTCALLBACK DmoDispatcher(AEffect *effect, VstInt32 opCode, VstInt32 index, VstIntPtr value, void *ptr, float opt); - static void VSTCALLBACK DmoSetParameter(AEffect *effect, VstInt32 index, float parameter); - static float VSTCALLBACK DmoGetParameter(AEffect *effect, VstInt32 index); - static void VSTCALLBACK DmoProcess(AEffect *effect, float **inputs, float **outputs, VstInt32 sampleframes); - -protected: - // Stream conversion functions - void InterleaveFloatToInt16(const float *inLeft, const float *inRight, int nsamples); - void DeinterleaveInt16ToFloat(float *outLeft, float *outRight, int nsamples) const; -#ifdef ENABLE_SSE - void SSEInterleaveFloatToInt16(const float *inLeft, const float *inRight, int nsamples); - void SSEDeinterleaveInt16ToFloat(float *outLeft, float *outRight, int nsamples) const; -#endif // ENABLE_SSE -}; - - -CDmo2Vst::CDmo2Vst(IMediaObject *pMO, IMediaObjectInPlace *pMOIP, DWORD uid) -//-------------------------------------------------------------------------- -{ - m_pMediaObject = pMO; - m_pMediaProcess = pMOIP; - m_pParamInfo = nullptr; - m_pMediaParams = nullptr; - MemsetZero(m_Effect); - m_Effect.magic = kDmoMagic; - m_Effect.numPrograms = 0; - m_Effect.numParams = 0; - m_Effect.numInputs = 2; - m_Effect.numOutputs = 2; - m_Effect.flags = 0; // see constants - m_Effect.ioRatio = 1.0f; - m_Effect.object = this; - m_Effect.uniqueID = uid; - m_Effect.version = 2; - m_nSamplesPerSec = 44100; - m_DataTime = 0; - if (FAILED(m_pMediaObject->QueryInterface(IID_IMediaParamInfo, (void **)&m_pParamInfo))) m_pParamInfo = nullptr; - if (m_pParamInfo) - { - DWORD dwParamCount = 0; - m_pParamInfo->GetParamCount(&dwParamCount); - m_Effect.numParams = dwParamCount; - } - if (FAILED(m_pMediaObject->QueryInterface(IID_IMediaParams, (void **)&m_pMediaParams))) m_pMediaParams = nullptr; - m_pMixBuffer = (int16 *)((((intptr_t)m_MixBuffer) + 15) & ~15); - // Callbacks - m_Effect.dispatcher = DmoDispatcher; - m_Effect.setParameter = DmoSetParameter; - m_Effect.getParameter = DmoGetParameter; - m_Effect.process = DmoProcess; - m_Effect.processReplacing = nullptr; -} - - -CDmo2Vst::~CDmo2Vst() -//------------------- -{ - if (m_pMediaParams) - { - m_pMediaParams->Release(); - m_pMediaParams = nullptr; - } - if (m_pParamInfo) - { - m_pParamInfo->Release(); - m_pParamInfo = nullptr; - } - if (m_pMediaProcess) - { - m_pMediaProcess->Release(); - m_pMediaProcess = nullptr; - } - if (m_pMediaObject) - { - m_pMediaObject->Release(); - m_pMediaObject = nullptr; - } -} - - -VstIntPtr CDmo2Vst::DmoDispatcher(AEffect *effect, VstInt32 opCode, VstInt32 index, VstIntPtr value, void *ptr, float opt) -//------------------------------------------------------------------------------------------------------------------------ -{ - if (effect) - { - CDmo2Vst *that = (CDmo2Vst *)effect->object; - if (that) return that->Dispatcher(opCode, index, value, ptr, opt); - } - return 0; -} - - -void CDmo2Vst::DmoSetParameter(AEffect *effect, VstInt32 index, float parameter) -//------------------------------------------------------------------------------ -{ - if (effect) - { - CDmo2Vst *that = (CDmo2Vst *)effect->object; - if (that) that->SetParameter(index, parameter); - } -} - - -float CDmo2Vst::DmoGetParameter(AEffect *effect, VstInt32 index) -//---------------------------------------------------------- -{ - if (effect) - { - CDmo2Vst *that = (CDmo2Vst *)effect->object; - if (that) return that->GetParameter(index); - } - return 0; -} - - -void CDmo2Vst::DmoProcess(AEffect *effect, float **inputs, float **outputs, VstInt32 sampleframes) -//------------------------------------------------------------------------------------------------ -{ - if (effect) - { - CDmo2Vst *that = (CDmo2Vst *)effect->object; - if (that) that->Process(inputs, outputs, sampleframes); - } -} - - -VstIntPtr CDmo2Vst::Dispatcher(VstInt32 opCode, VstInt32 index, VstIntPtr value, void *ptr, float opt) -//---------------------------------------------------------------------------------------------------- -{ - switch(opCode) - { - case effOpen: - break; - - case effClose: - m_Effect.object = nullptr; - delete this; - return 0; - - case effGetParamName: - case effGetParamLabel: - case effGetParamDisplay: - if ((index < m_Effect.numParams) && (m_pParamInfo)) - { - MP_PARAMINFO mpi; - LPSTR pszName = (LPSTR)ptr; - - mpi.mpType = MPT_INT; - mpi.szUnitText[0] = 0; - mpi.szLabel[0] = 0; - pszName[0] = 0; - if (m_pParamInfo->GetParamInfo(index, &mpi) == S_OK) - { - if (opCode == effGetParamDisplay) - { - MP_DATA md; - - if ((m_pMediaParams) && (m_pMediaParams->GetParam(index, &md) == S_OK)) - { - switch(mpi.mpType) - { - case MPT_FLOAT: - { - int nValue = (int)(md * 100.0f + 0.5f); - bool bNeg = false; - if (nValue < 0) { bNeg = true; nValue = -nValue; } - wsprintf(pszName, (bNeg) ? "-%d.%02d" : "%d.%02d", nValue/100, nValue%100); - } - break; - - case MPT_BOOL: - strcpy(pszName, ((int)md) ? "Yes" : "No"); - break; - - case MPT_ENUM: - { - WCHAR *text = nullptr; - m_pParamInfo->GetParamText(index, &text); - - const int nValue = (int)(md * (mpi.mpdMaxValue - mpi.mpdMinValue) + 0.5f); - // Always skip first two strings (param name, unit name) - for(int i = 0; i < nValue + 2; i++) - { - text += wcslen(text) + 1; - } - WideCharToMultiByte(CP_ACP, 0, text, -1, pszName, 32, nullptr, nullptr); - } - break; - - case MPT_INT: - default: - wsprintf(pszName, "%d", (int)md); - break; - } - } - } else - { - WideCharToMultiByte(CP_ACP, 0, (opCode == effGetParamName) ? mpi.szLabel : mpi.szUnitText, -1, pszName, 32, nullptr, nullptr); - } - } - } - break; - - case effCanBeAutomated: - return (index < m_Effect.numParams); - - case effSetSampleRate: - m_nSamplesPerSec = (int)opt; - { - - m_Effect.initialDelay = 0; - REFERENCE_TIME time; // Unit 100-nanoseconds - if(m_pMediaProcess->GetLatency(&time) == S_OK) - { - m_Effect.initialDelay = static_cast<VstInt32>(time * m_nSamplesPerSec / (10 * 1000 * 1000)); - } - } - break; - - case effMainsChanged: - if (value) - { - DMO_MEDIA_TYPE mt; - WAVEFORMATEX wfx; - - mt.majortype = MEDIATYPE_Audio; - mt.subtype = MEDIASUBTYPE_PCM; - mt.bFixedSizeSamples = TRUE; - mt.bTemporalCompression = FALSE; - mt.formattype = FORMAT_WaveFormatEx; - mt.pUnk = nullptr; - mt.pbFormat = (LPBYTE)&wfx; - mt.cbFormat = sizeof(WAVEFORMATEX); - mt.lSampleSize = 2 * sizeof(int16); - wfx.wFormatTag = WAVE_FORMAT_PCM; - wfx.nChannels = 2; - wfx.nSamplesPerSec = m_nSamplesPerSec; - wfx.wBitsPerSample = sizeof(int16) * 8; - wfx.nBlockAlign = wfx.nChannels * (wfx.wBitsPerSample / 8); - wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; - wfx.cbSize = 0; - if (FAILED(m_pMediaObject->SetInputType(0, &mt, 0)) - || FAILED(m_pMediaObject->SetOutputType(0, &mt, 0))) - { - #ifdef DMO_LOG - Log("DMO: Failed to set I/O media type\n"); - #endif - return -1; - } - } else - { - m_pMediaObject->Flush(); - m_pMediaObject->SetInputType(0, nullptr, DMO_SET_TYPEF_CLEAR); - m_pMediaObject->SetOutputType(0, nullptr, DMO_SET_TYPEF_CLEAR); - m_DataTime = 0; - } - break; - } - return 0; -} - - -void CDmo2Vst::SetParameter(VstInt32 index, float fValue) -//------------------------------------------------------- -{ - MP_PARAMINFO mpi; - - if ((index < m_Effect.numParams) && (m_pParamInfo) && (m_pMediaParams)) - { - MemsetZero(mpi); - if (m_pParamInfo->GetParamInfo(index, &mpi) == S_OK) - { - float fMin = mpi.mpdMinValue; - float fMax = mpi.mpdMaxValue; - - if (mpi.mpType == MPT_BOOL) - { - fMin = 0; - fMax = 1; - fValue = (fValue > 0.5f) ? 1.0f : 0.0f; - } - if (fMax > fMin) fValue *= (fMax - fMin); - fValue += fMin; - if (fValue < fMin) fValue = fMin; - if (fValue > fMax) fValue = fMax; - if (mpi.mpType != MPT_FLOAT) fValue = (float)(int)fValue; - m_pMediaParams->SetParam(index, fValue); - } - } -} - - -float CDmo2Vst::GetParameter(VstInt32 index) -//------------------------------------------ -{ - if ((index < m_Effect.numParams) && (m_pParamInfo) && (m_pMediaParams)) - { - MP_PARAMINFO mpi; - MP_DATA md; - - MemsetZero(mpi); - md = 0; - if (m_pParamInfo->GetParamInfo(index, &mpi) == S_OK - && m_pMediaParams->GetParam(index, &md) == S_OK) - { - float fValue, fMin, fMax, fDefault; - - fValue = md; - fMin = mpi.mpdMinValue; - fMax = mpi.mpdMaxValue; - fDefault = mpi.mpdNeutralValue; - if (mpi.mpType == MPT_BOOL) - { - fMin = 0; - fMax = 1; - } - fValue -= fMin; - if (fMax > fMin) fValue /= (fMax - fMin); - return fValue; - } - } - return 0; -} - - -static const float _f2si = 32768.0f; -static const float _si2f = 1.0f / 32768.0f; - -// Interleave two float streams into one int16 stereo stream. -void CDmo2Vst::InterleaveFloatToInt16(const float *inLeft, const float *inRight, int samples) -//------------------------------------------------------------------------------------------- -{ - int16 *outBuf = m_pMixBuffer; - for(int i = samples; i != 0; i--) - { - *(outBuf++) = static_cast<int16>(Clamp(*(inLeft++) * _f2si, static_cast<float>(int16_min), static_cast<float>(int16_max))); - *(outBuf++) = static_cast<int16>(Clamp(*(inRight++) * _f2si, static_cast<float>(int16_min), static_cast<float>(int16_max))); - } -} - - -// Deinterleave an int16 stereo stream into two float streams. -void CDmo2Vst::DeinterleaveInt16ToFloat(float *outLeft, float *outRight, int samples) const -//----------------------------------------------------------------------------------------- -{ - const int16 *inBuf = m_pMixBuffer; - for(int i = samples; i != 0; i--) - { - *outLeft++ += _si2f * static_cast<float>(*inBuf++); - *outRight++ += _si2f * static_cast<float>(*inBuf++); - } -} - - -#ifdef ENABLE_SSE -// Interleave two float streams into one int16 stereo stream using SSE magic. -void CDmo2Vst::SSEInterleaveFloatToInt16(const float *inLeft, const float *inRight, int samples) -//---------------------------------------------------------------------------------------------- -{ - int16 *outBuf = m_pMixBuffer; - _asm - { - mov eax, inLeft - mov edx, inRight - mov ebx, outBuf - mov ecx, samples - movss xmm2, _f2si - xorps xmm0, xmm0 - xorps xmm1, xmm1 - shufps xmm2, xmm2, 0x00 - pxor mm0, mm0 - inc ecx - shr ecx, 1 -mainloop: - movlps xmm0, [eax] - movlps xmm1, [edx] - mulps xmm0, xmm2 - mulps xmm1, xmm2 - add ebx, 8 - cvtps2pi mm0, xmm0 // mm0 = [ x2l | x1l ] - add eax, 8 - cvtps2pi mm1, xmm1 // mm1 = [ x2r | x1r ] - add edx, 8 - packssdw mm0, mm1 // mm0 = [x2r|x1r|x2l|x1l] - pshufw mm0, mm0, 0xD8 - dec ecx - movq [ebx-8], mm0 - jnz mainloop - emms - } -} - - -// Deinterleave an int16 stereo stream into two float streams using SSE magic. -void CDmo2Vst::SSEDeinterleaveInt16ToFloat(float *outLeft, float *outRight, int samples) const -//-------------------------------------------------------------------------------------------- -{ - const int16 *inBuf = m_pMixBuffer; - _asm { - mov ebx, inBuf - mov eax, outLeft - mov edx, outRight - mov ecx, samples - movss xmm7, _si2f - inc ecx - shr ecx, 1 - shufps xmm7, xmm7, 0x00 - xorps xmm0, xmm0 - xorps xmm1, xmm1 - xorps xmm2, xmm2 -mainloop: - movq mm0, [ebx] // mm0 = [x2r|x2l|x1r|x1l] - add ebx, 8 - pxor mm1, mm1 - pxor mm2, mm2 - punpcklwd mm1, mm0 // mm1 = [x1r|0|x1l|0] - punpckhwd mm2, mm0 // mm2 = [x2r|0|x2l|0] - psrad mm1, 16 // mm1 = [x1r|x1l] - movlps xmm2, [eax] - psrad mm2, 16 // mm2 = [x2r|x2l] - cvtpi2ps xmm0, mm1 // xmm0 = [ ? | ? |x1r|x1l] - dec ecx - cvtpi2ps xmm1, mm2 // xmm1 = [ ? | ? |x2r|x2l] - movhps xmm2, [edx] // xmm2 = [y2r|y1r|y2l|y1l] - movlhps xmm0, xmm1 // xmm0 = [x2r|x2l|x1r|x1l] - shufps xmm0, xmm0, 0xD8 - lea eax, [eax+8] - mulps xmm0, xmm7 - addps xmm0, xmm2 - lea edx, [edx+8] - movlps [eax-8], xmm0 - movhps [edx-8], xmm0 - jnz mainloop - emms - } -} - -#endif // ENABLE_SSE - - -void CDmo2Vst::Process(float * const *inputs, float **outputs, int samples) -//------------------------------------------------------------------------- -{ - if(m_pMixBuffer == nullptr || samples <= 0) - { - return; - } - -#ifdef ENABLE_SSE - if(GetProcSupport() & PROCSUPPORT_SSE) - { - SSEInterleaveFloatToInt16(inputs[0], inputs[1], samples); - m_pMediaProcess->Process(samples * 2 * sizeof(int16), reinterpret_cast<BYTE *>(m_pMixBuffer), m_DataTime, DMO_INPLACE_NORMAL); - SSEDeinterleaveInt16ToFloat(outputs[0], outputs[1], samples); - } else -#endif // ENABLE_SSE - { - InterleaveFloatToInt16(inputs[0], inputs[1], samples); - m_pMediaProcess->Process(samples * 2 * sizeof(int16), reinterpret_cast<BYTE *>(m_pMixBuffer), m_DataTime, DMO_INPLACE_NORMAL); - DeinterleaveInt16ToFloat(outputs[0], outputs[1], samples); - } - - m_DataTime += Util::muldiv(samples, 10000000, m_nSamplesPerSec); -} - - -AEffect *DmoToVst(VSTPluginLib *pLib) -//----------------------------------- -{ - CLSID clsid; - - if (CLSIDFromWString(pLib->dllPath.ToWide(), &clsid) == S_OK) - { - IMediaObject *pMO = nullptr; - IMediaObjectInPlace *pMOIP = nullptr; - if ((CoCreateInstance(clsid, nullptr, CLSCTX_INPROC_SERVER, IID_IMediaObject, (VOID **)&pMO) == S_OK) && (pMO)) - { - if (pMO->QueryInterface(IID_IMediaObjectInPlace, (void **)&pMOIP) != S_OK) pMOIP = nullptr; - } else pMO = nullptr; - if ((pMO) && (pMOIP)) - { - DWORD dwInputs, dwOutputs; - - dwInputs = dwOutputs = 0; - pMO->GetStreamCount(&dwInputs, &dwOutputs); - if (dwInputs == 1 && dwOutputs == 1) - { - CDmo2Vst *p = new CDmo2Vst(pMO, pMOIP, clsid.Data1); - return (p) ? p->GetEffect() : nullptr; - } - #ifdef DMO_LOG - Log("%s: Unable to use this DMO\n", pLib->libraryName); - #endif - } - #ifdef DMO_LOG - else Log("%s: Failed to get IMediaObject & IMediaObjectInPlace interfaces\n", pLib->libraryName); - #endif - if (pMO) pMO->Release(); - if (pMOIP) pMOIP->Release(); - } - return nullptr; -} - - #endif // NO_VST Modified: trunk/OpenMPT/mptrack/Vstplug.h =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.h 2013-11-12 20:26:19 UTC (rev 3197) +++ trunk/OpenMPT/mptrack/Vstplug.h 2013-11-12 20:54:13 UTC (rev 3198) @@ -17,9 +17,8 @@ #include "../soundlib/Snd_defs.h" #include "../soundlib/plugins/PluginMixBuffer.h" +#include "../soundlib/plugins/PlugInterface.h" -#include "../common/StringFixer.h" - //#define kBuzzMagic 'Buzz' #define kDmoMagic 'DXMO' @@ -188,8 +187,8 @@ bool GetParams(float* param, VstInt32 min, VstInt32 max); bool RandomizeParams(PlugParamIndex minParam = 0, PlugParamIndex maxParam = 0); #ifdef MODPLUG_TRACKER - inline CModDoc *GetModDoc() { return m_SndFile.GetpModDoc(); } - inline const CModDoc *GetModDoc() const { return m_SndFile.GetpModDoc(); } + forceinline CModDoc *GetModDoc(); + forceinline const CModDoc *GetModDoc() const; #endif // MODPLUG_TRACKER inline CSoundFile &GetSoundFile() { return m_SndFile; } inline const CSoundFile &GetSoundFile() const { return m_SndFile; } @@ -340,14 +339,14 @@ protected: void EnumerateDirectXDMOs(); - void LoadPlugin(const mpt::PathString &pluginPath, AEffect *&effect, HINSTANCE &library); + AEffect *LoadPlugin(const mpt::PathString &pluginPath, HINSTANCE &library); protected: VstIntPtr VstCallback(AEffect *effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void *ptr, float opt); VstIntPtr VstFileSelector(bool destructor, VstFileSelect *fileSel, const AEffect *effect); static VstIntPtr VSTCALLBACK MasterCallBack(AEffect *effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void *ptr, float opt); static bool CreateMixPluginProc(SNDMIXPLUGIN &, CSoundFile &); - VstTimeInfo timeInfo; //rewbs.VSTcompliance + VstTimeInfo timeInfo; public: static char s_szHostProductString[64]; Modified: trunk/OpenMPT/mptrack/mptrack_08.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_08.vcproj 2013-11-12 20:26:19 UTC (rev 3197) +++ trunk/OpenMPT/mptrack/mptrack_08.vcproj 2013-11-12 20:54:13 UTC (rev 3198) @@ -339,10 +339,18 @@ > </File> <File + RelativePath="..\soundlib\plugins\DmoToVst.cpp" + > + </File> + <File RelativePath="..\soundlib\plugins\JBridge.cpp" > </File> <File + RelativePath="..\soundlib\plugins\PluginManager.cpp" + > + </File> + <File RelativePath=".\mainbar.cpp" > </File> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2013-11-12 20:26:19 UTC (rev 3197) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2013-11-12 20:54:13 UTC (rev 3198) @@ -476,7 +476,9 @@ <ClCompile Include="..\soundlib\mod_specifications.cpp" /> <ClCompile Include="..\soundlib\pattern.cpp" /> <ClCompile Include="..\soundlib\patternContainer.cpp" /> + <ClCompile Include="..\soundlib\plugins\DmoToVst.cpp" /> <ClCompile Include="..\soundlib\plugins\JBridge.cpp" /> + <ClCompile Include="..\soundlib\plugins\PluginManager.cpp" /> <ClCompile Include="..\soundlib\RowVisitor.cpp" /> <ClCompile Include="..\soundlib\S3MTools.cpp" /> <ClCompile Include="..\soundlib\SampleFormats.cpp" /> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2013-11-12 20:26:19 UTC (rev 3197) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2013-11-12 20:54:13 UTC (rev 3198) @@ -493,6 +493,12 @@ <ClCompile Include="..\common\mptPathString.cpp"> <Filter>Source Files\common</Filter> </ClCompile> + <ClCompile Include="..\soundlib\plugins\PluginManager.cpp"> + <Filter>Source Files\soundlib\plugins</Filter> + </ClCompile> + <ClCompile Include="..\soundlib\plugins\DmoToVst.cpp"> + <Filter>Source Files\soundlib\plugins</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\soundlib\Loaders.h"> Modified: trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2013-11-12 20:26:19 UTC (rev 3197) +++ trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2013-11-12 20:54:13 UTC (rev 3198) @@ -44,43 +44,9 @@ static int g_asio_startcount = 0; -static std::wstring CLSIDToString(CLSID clsid) -//-------------------------------------------- +std::vector<SoundDeviceInfo> CASIODevice::EnumerateDevices() +//---------------------------------------------------------- { - std::wstring str; - LPOLESTR tmp = nullptr; - StringFromCLSID(clsid, &tmp); - if(tmp) - { - str = tmp; - CoTaskMemFree(tmp); - tmp = nullptr; - } - return str; -} - - -static CLSID StringToCLSID(const std::wstring &str) -//------------------------------------------------- -{ - CLSID clsid = CLSID(); - std::vector<OLECHAR> tmp(str.c_str(), str.c_str() + str.length() + 1); - CLSIDFromString(&tmp[0], &clsid); - return clsid; -} - - -static bool IsCLSID(const std::wstring &str) -{ - CLSID clsid = CLSID(); - std::vector<OLECHAR> tmp(str.c_str(), str.c_str() + str.length() + 1); - return CLSIDFromString(&tmp[0], &clsid) == S_OK; -} - - -std::vector<SoundDeviceInfo> CASIODevice::EnumerateDevices() -//----------------------------------------------------------- -{ std::vector<SoundDeviceInfo> devices; LONG cr; @@ -128,7 +94,7 @@ if(ERROR_SUCCESS == RegQueryValueExW(hksub, L"CLSID", 0, &datatype, (LPBYTE)idBuf, &datasize)) { const std::wstring internalID = idBuf; - if(IsCLSID(internalID)) + if(Util::IsCLSID(internalID)) { #ifdef ASIO_LOG Log(" clsid=\"%s\"\n", mpt::String::Encode(idBuf, mpt::CharsetLocale).c_str()); @@ -463,7 +429,8 @@ return; } - CLSID clsid = StringToCLSID(GetDeviceInternalID()); + CLSID clsid; + Util::StringToCLSID(GetDeviceInternalID(), clsid); if (CoCreateInstance(clsid,0,CLSCTX_INPROC_SERVER, clsid, (void **)&m_pAsioDrv) == S_OK) { m_pAsioDrv->init((void *)m_Settings.hWnd); Added: trunk/OpenMPT/soundlib/plugins/DmoToVst.cpp =================================================================== --- trunk/OpenMPT/soundlib/plugins/DmoToVst.cpp (rev 0) +++ trunk/OpenMPT/soundlib/plugins/DmoToVst.cpp 2013-11-12 20:54:13 UTC (rev 3198) @@ -0,0 +1,554 @@ +/* + * DmoToVst.cpp + * ------------ + * Purpose: DirectX Media Object to VST plugin adapter class. + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#include "stdafx.h" + +#ifndef NO_VST +#include <uuids.h> +#include <dmoreg.h> +#include <medparam.h> +#include "../../mptrack/Vstplug.h" +#include "../Snd_defs.h" +#include "../../common/misc_util.h" + +#define DMO_LOG + + +//============ +class CDmo2Vst +//============ +{ +protected: + IMediaObject *m_pMediaObject; + IMediaObjectInPlace *m_pMediaProcess; + IMediaParamInfo *m_pParamInfo; + IMediaParams *m_pMediaParams; + ULONG m_nSamplesPerSec; + AEffect m_Effect; + REFERENCE_TIME m_DataTime; + int16 *m_pMixBuffer; + int16 m_MixBuffer[MIXBUFFERSIZE * 2 + 16]; // 16-bit Stereo interleaved + +public: + CDmo2Vst(IMediaObject *pMO, IMediaObjectInPlace *pMOIP, DWORD uid); + ~CDmo2Vst(); + AEffect *GetEffect() { return &m_Effect; } + VstIntPtr Dispatcher(VstInt32 opCode, VstInt32 index, VstIntPtr value, void *ptr, float opt); + void SetParameter(VstInt32 index, float parameter); + float GetParameter(VstInt32 index); + void Process(float * const *inputs, float **outputs, int samples); + +public: + static VstIntPtr VSTCALLBACK DmoDispatcher(AEffect *effect, VstInt32 opCode, VstInt32 index, VstIntPtr value, void *ptr, float opt); + static void VSTCALLBACK DmoSetParameter(AEffect *effect, VstInt32 index, float parameter); + static float VSTCALLBACK DmoGetParameter(AEffect *effect, VstInt32 index); + static void VSTCALLBACK DmoProcess(AEffect *effect, float **inputs, float **outputs, VstInt32 sampleframes); + +protected: + // Stream conversion functions + void InterleaveFloatToInt16(const float *inLeft, const float *inRight, int nsamples); + void DeinterleaveInt16ToFloat(float *outLeft, float *outRight, int nsamples) const; +#ifdef ENABLE_SSE + void SSEInterleaveFloatToInt16(const float *inLeft, const float *inRight, int nsamples); + void SSEDeinterleaveInt16ToFloat(float *outLeft, float *outRight, int nsamples) const; +#endif // ENABLE_SSE +}; + + +CDmo2Vst::CDmo2Vst(IMediaObject *pMO, IMediaObjectInPlace *pMOIP, DWORD uid) +//-------------------------------------------------------------------------- +{ + m_pMediaObject = pMO; + m_pMediaProcess = pMOIP; + m_pParamInfo = nullptr; + m_pMediaParams = nullptr; + + MemsetZero(m_Effect); + m_Effect.magic = kDmoMagic; + m_Effect.numPrograms = 0; + m_Effect.numParams = 0; + m_Effect.numInputs = 2; + m_Effect.numOutputs = 2; + m_Effect.flags = 0; // see constants + m_Effect.ioRatio = 1.0f; + m_Effect.object = this; + m_Effect.uniqueID = uid; + m_Effect.version = 2; + + m_nSamplesPerSec = 44100; + m_DataTime = 0; + if (FAILED(m_pMediaObject->QueryInterface(IID_IMediaParamInfo, (void **)&m_pParamInfo))) m_pParamInfo = nullptr; + if (m_pParamInfo) + { + DWORD dwParamCount = 0; + m_pParamInfo->GetParamCount(&dwParamCount); + m_Effect.numParams = dwParamCount; + } + if (FAILED(m_pMediaObject->QueryInterface(IID_IMediaParams, (void **)&m_pMediaParams))) m_pMediaParams = nullptr; + m_pMixBuffer = (int16 *)((((intptr_t)m_MixBuffer) + 15) & ~15); + // Callbacks + m_Effect.dispatcher = DmoDispatcher; + m_Effect.setParameter = DmoSetParameter; + m_Effect.getParameter = DmoGetParameter; + m_Effect.process = DmoProcess; + m_Effect.processReplacing = nullptr; +} + + +CDmo2Vst::~CDmo2Vst() +//------------------- +{ + if (m_pMediaParams) + { + m_pMediaParams->Release(); + m_pMediaParams = nullptr; + } + if (m_pParamInfo) + { + m_pParamInfo->Release(); + m_pParamInfo = nullptr; + } + if (m_pMediaProcess) + { + m_pMediaProcess->Release(); + m_pMediaProcess = nullptr; + } + if (m_pMediaObject) + { + m_pMediaObject->Release(); + m_pMediaObject = nullptr; + } +} + + +VstIntPtr CDmo2Vst::DmoDispatcher(AEffect *effect, VstInt32 opCode, VstInt32 index, VstIntPtr value, void *ptr, float opt) +//------------------------------------------------------------------------------------------------------------------------ +{ + if (effect) + { + CDmo2Vst *that = (CDmo2Vst *)effect->object; + if (that) return that->Dispatcher(opCode, index, value, ptr, opt); + } + return 0; +} + + +void CDmo2Vst::DmoSetParameter(AEffect *effect, VstInt32 index, float parameter) +//------------------------------------------------------------------------------ +{ + if (effect) + { + CDmo2Vst *that = (CDmo2Vst *)effect->object; + if (that) that->SetParameter(index, parameter); + } +} + + +float CDmo2Vst::DmoGetParameter(AEffect *effect, VstInt32 index) +//---------------------------------------------------------- +{ + if (effect) + { + CDmo2Vst *that = (CDmo2Vst *)effect->object; + if (that) return that->GetParameter(index); + } + return 0; +} + + +void CDmo2Vst::DmoProcess(AEffect *effect, float **inputs, float **outputs, VstInt32 sampleframes) +//------------------------------------------------------------------------------------------------ +{ + if (effect) + { + CDmo2Vst *that = (CDmo2Vst *)effect->object; + if (that) that->Process(inputs, outputs, sampleframes); + } +} + + +VstIntPtr CDmo2Vst::Dispatcher(VstInt32 opCode, VstInt32 index, VstIntPtr value, void *ptr, float opt) +//---------------------------------------------------------------------------------------------------- +{ + switch(opCode) + { + case effOpen: + break; + + case effClose: + m_Effect.object = nullptr; + delete this; + return 0; + + case effGetParamName: + case effGetParamLabel: + case effGetParamDisplay: + if ((index < m_Effect.numParams) && (m_pParamInfo)) + { + MP_PARAMINFO mpi; + char *pszName = (char *)ptr; + + mpi.mpType = MPT_INT; + mpi.szUnitText[0] = 0; + mpi.szLabel[0] = 0; + pszName[0] = 0; + if (m_pParamInfo->GetParamInfo(index, &mpi) == S_OK) + { + if (opCode == effGetParamDisplay) + { + MP_DATA md; + + if ((m_pMediaParams) && (m_pMediaParams->GetParam(index, &md) == S_OK)) + { + switch(mpi.mpType) + { + case MPT_FLOAT: + { + int nValue = (int)(md * 100.0f + 0.5f); + bool bNeg = false; + if (nValue < 0) { bNeg = true; nValue = -nValue; } + wsprintf(pszName, (bNeg) ? "-%d.%02d" : "%d.%02d", nValue/100, nValue%100); + } + break; + + case MPT_BOOL: + strcpy(pszName, ((int)md) ? "Yes" : "No"); + break; + + case MPT_ENUM: + { + WCHAR *text = nullptr; + m_pParamInfo->GetParamText(index, &text); + + const int nValue = (int)(md * (mpi.mpdMaxValue - mpi.mpdMinValue) + 0.5f); + // Always skip first two strings (param name, unit name) + for(int i = 0; i < nValue + 2; i++) + { + text += wcslen(text) + 1; + } + WideCharToMultiByte(CP_ACP, 0, text, -1, pszName, 32, nullptr, nullptr); + } + break; + + case MPT_INT: + default: + wsprintf(pszName, "%d", (int)md); + break; + } + } + } else + { + WideCharToMultiByte(CP_ACP, 0, (opCode == effGetParamName) ? mpi.szLabel : mpi.szUnitText, -1, pszName, 32, nullptr, nullptr); + } + } + } + break; + + case effCanBeAutomated: + return (index < m_Effect.numParams); + + case effSetSampleRate: + m_nSamplesPerSec = (int)opt; + { + + m_Effect.initialDelay = 0; + REFERENCE_TIME time; // Unit 100-nanoseconds + if(m_pMediaProcess->GetLatency(&time) == S_OK) + { + m_Effect.initialDelay = static_cast<VstInt32>(time * m_nSamplesPerSec / (10 * 1000 * 1000)); + } + } + break; + + case effMainsChanged: + if (value) + { + DMO_MEDIA_TYPE mt; + WAVEFORMATEX wfx; + + mt.majortype = MEDIATYPE_Audio; + mt.subtype = MEDIASUBTYPE_PCM; + mt.bFixedSizeSamples = TRUE; + mt.bTemporalCompression = FALSE; + mt.formattype = FORMAT_WaveFormatEx; + mt.pUnk = nullptr; + mt.pbFormat = (LPBYTE)&wfx; + mt.cbFormat = sizeof(WAVEFORMATEX); + mt.lSampleSize = 2 * sizeof(int16); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = 2; + wfx.nSamplesPerSec = m_nSamplesPerSec; + wfx.wBitsPerSample = sizeof(int16) * 8; + wfx.nBlockAlign = wfx.nChannels * (wfx.wBitsPerSample / 8); + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + wfx.cbSize = 0; + if (FAILED(m_pMediaObject->SetInputType(0, &mt, 0)) + || FAILED(m_pMediaObject->SetOutputType(0, &mt, 0))) + { +#ifdef DMO_LOG + Log("DMO: Failed to set I/O media type\n"); +#endif + return -1; + } + } else + { + m_pMediaObject->Flush(); + m_pMediaObject->SetInputType(0, nullptr, DMO_SET_TYPEF_CLEAR); + m_pMediaObject->SetOutputType(0, nullptr, DMO_SET_TYPEF_CLEAR); + m_DataTime = 0; + } + break; + } + return 0; +} + + +void CDmo2Vst::SetParameter(VstInt32 index, float fValue) +//------------------------------------------------------- +{ + MP_PARAMINFO mpi; + + if ((index < m_Effect.numParams) && (m_pParamInfo) && (m_pMediaParams)) + { + MemsetZero(mpi); + if (m_pParamInfo->GetParamInfo(index, &mpi) == S_OK) + { + float fMin = mpi.mpdMinValue; + float fMax = mpi.mpdMaxValue; + + if (mpi.mpType == MPT_BOOL) + { + fMin = 0; + fMax = 1; + fValue = (fValue > 0.5f) ? 1.0f : 0.0f; + } + if (fMax > fMin) fValue *= (fMax - fMin); + fValue += fMin; + if (fValue < fMin) fValue = fMin; + if (fValue > fMax) fValue = fMax; + if (mpi.mpType != MPT_FLOAT) fValue = (float)(int)fValue; + m_pMediaParams->SetParam(index, fValue); + } + } +} + + +float CDmo2Vst::GetParameter(VstInt32 index) +//------------------------------------------ +{ + if ((index < m_Effect.numParams) && (m_pParamInfo) && (m_pMediaParams)) + { + MP_PARAMINFO mpi; + MP_DATA md; + + MemsetZero(mpi); + md = 0; + if (m_pParamInfo->GetParamInfo(index, &mpi) == S_OK + && m_pMediaParams->GetParam(index, &md) == S_OK) + { + float fValue, fMin, fMax, fDefault; + + fValue = md; + fMin = mpi.mpdMinValue; + fMax = mpi.mpdMaxValue; + fDefault = mpi.mpdNeutralValue; + if (mpi.mpType == MPT_BOOL) + { + fMin = 0; + fMax = 1; + } + fValue -= fMin; + if (fMax > fMin) fValue /= (fMax - fMin); + return fValue; + } + } + return 0; +} + + +static const float _f2si = 32768.0f; +static const float _si2f = 1.0f / 32768.0f; + +// Interleave two float streams into one int16 stereo stream. +void CDmo2Vst::InterleaveFloatToInt16(const float *inLeft, const float *inRight, int samples) +//------------------------------------------------------------------------------------------- +{ + int16 *outBuf = m_pMixBuffer; + for(int i = samples; i != 0; i--) + { + *(outBuf++) = static_cast<int16>(Clamp(*(inLeft++) * _f2si, static_cast<float>(int16_min), static_cast<float>(int16_max))); + *(outBuf++) = static_cast<int16>(Clamp(*(inRight++) * _f2si, static_cast<float>(int16_min), static_cast<float>(int16_max))); + } +} + + +// Deinterleave an int16 stereo stream into two float streams. +void CDmo2Vst::DeinterleaveInt16ToFloat(float *outLeft, float *outRight, int samples) const +//----------------------------------------------------------------------------------------- +{ + const int16 *inBuf = m_pMixBuffer; + for(int i = samples; i != 0; i--) + { + *outLeft++ += _si2f * static_cast<float>(*inBuf++); + *outRight++ += _si2f * static_cast<float>(*inBuf++); + } +} + + +#ifdef ENABLE_SSE +// Interleave two float streams into one int16 stereo stream using SSE magic. +void CDmo2Vst::SSEInterleaveFloatToInt16(const float *inLeft, const float *inRight, int samples) +//---------------------------------------------------------------------------------------------- +{ + int16 *outBuf = m_pMixBuffer; + _asm + { + mov eax, inLeft + mov edx, inRight + mov ebx, outBuf + mov ecx, samples + movss xmm2, _f2si + xorps xmm0, xmm0 + xorps xmm1, xmm1 + shufps xmm2, xmm2, 0x00 + pxor mm0, mm0 + inc ecx + shr ecx, 1 +mainloop: + movlps xmm0, [eax] + movlps xmm1, [edx] + mulps xmm0, xmm2 + mulps xmm1, xmm2 + add ebx, 8 + cvtps2pi mm0, xmm0 // mm0 = [ x2l | x1l ] + add eax, 8 + cvtps2pi mm1, xmm1 // mm1 = [ x2r | x1r ] + add edx, 8 + packssdw mm0, mm1 // mm0 = [x2r|x1r|x2l|x1l] + pshufw mm0, mm0, 0xD8 + dec ecx + movq [ebx-8], mm0 + jnz mainloop + emms + } +} + + +// Deinterleave an int16 stereo stream into two float streams using SSE magic. +void CDmo2Vst::SSEDeinterleaveInt16ToFloat(float *outLeft, float *outRight, int samples) const +//-------------------------------------------------------------------------------------------- +{ + const int16 *inBuf = m_pMixBuffer; + _asm { + mov ebx, inBuf + mov eax, outLeft + mov edx, outRight + mov ecx, samples + movss xmm7, _si2f + inc ecx + shr ecx, 1 + shufps xmm7, xmm7, 0x00 + xorps xmm0, xmm0 + xorps xmm1, xmm1 + xorps xmm2, xmm2 +mainloop: + movq mm0, [ebx] // mm0 = [x2r|x2l|x1r|x1l] + add ebx, 8 + pxor mm1, mm1 + pxor mm2, mm2 + punpcklwd mm1, mm0 // mm1 = [x1r|0|x1l|0] + punpckhwd mm2, mm0 // mm2 = [x2r|0|x2l|0] + psrad mm1, 16 // mm1 = [x1r|x1l] + movlps xmm2, [eax] + psrad mm2, 16 // mm2 = [x2r|x2l] + cvtpi2ps xmm0, mm1 // xmm0 = [ ? | ? |x1r|x1l] + dec ecx + cvtpi2ps xmm1, mm2 // xmm1 = [ ? | ? |x2r|x2l] + movhps xmm2, [edx] // xmm2 = [y2r|y1r|y2l|y1l] + movlhps xmm0, xmm1 // xmm0 = [x2r|x2l|x1r|x1l] + shufps xmm0, xmm0, 0xD8 + lea eax, [eax+8] + mulps xmm0, xmm7 + addps xmm0, xmm2 + lea edx, [edx+8] + movlps [eax-8], xmm0 + movhps [edx-8], xmm0 + jnz mainloop + emms + } +} + +#endif // ENABLE_SSE + + +void CDmo2Vst::Process(float * const *inputs, float **outputs, int samples) +//------------------------------------------------------------------------- +{ + if(m_pMixBuffer == nullptr || samples <= 0) + { + return; + } + +#ifdef ENABLE_SSE + if(GetProcSupport() & PROCSUPPORT_SSE) + { + SSEInterleaveFloatToInt16(inputs[0], inputs[1], samples); + m_pMediaProcess->Process(samples * 2 * sizeof(int16), reinterpret_cast<BYTE *>(m_pMixBuffer), m_DataTime, DMO_INPLACE_NORMAL); + SSEDeinterleaveInt16ToFloat(outputs[0], outputs[1], samples); + } else +#endif // ENABLE_SSE + { + InterleaveFloatToInt16(inputs[0], inputs[1], samples); + m_pMediaProcess->Process(samples * 2 * sizeof(int16), reinterpret_cast<BYTE *>(m_pMixBuffer), m_DataTime, DMO_INPLACE_NORMAL); + DeinterleaveInt16ToFloat(outputs[0], outputs[1], samples); + } + + m_DataTime += Util::muldiv(samples, 10000000, m_nSamplesPerSec); +} + + +// The actual adapter function. +AEffect *DmoToVst(VSTPluginLib &lib) +//---------------------------------- +{ + CLSID clsid; + if (Util::StringToCLSID(lib.dllPath.ToWide(), clsid)) + { + IMediaObject *pMO = nullptr; + IMediaObjectInPlace *pMOIP = nullptr; + if ((CoCreateInstance(clsid, nullptr, CLSCTX_INPROC_SERVER, IID_IMediaObject, (VOID **)&pMO) == S_OK) && (pMO)) + { + if (pMO->Q... [truncated message content] |