From: <sag...@us...> - 2014-09-11 19:01:11
|
Revision: 4275 http://sourceforge.net/p/modplug/code/4275 Author: saga-games Date: 2014-09-11 19:01:03 +0000 (Thu, 11 Sep 2014) Log Message: ----------- [New] Added auto-suspend functionality to plugin code: If a plugin only outputs silence after a few seconds of processing, it is temporarily suspended. This feature is currently not usable from the GUI yet, it is always disabled. Modified Paths: -------------- trunk/OpenMPT/mptrack/Vstplug.cpp trunk/OpenMPT/mptrack/Vstplug.h trunk/OpenMPT/soundlib/Fastmix.cpp trunk/OpenMPT/soundlib/plugins/PlugInterface.h Modified: trunk/OpenMPT/mptrack/Vstplug.cpp =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.cpp 2014-09-09 19:36:34 UTC (rev 4274) +++ trunk/OpenMPT/mptrack/Vstplug.cpp 2014-09-11 19:01:03 UTC (rev 4275) @@ -1209,6 +1209,7 @@ if ((fValue >= 0.0f) && (fValue <= 1.0f)) m_Effect.setParameter(&m_Effect, nIndex, fValue); } + ResetSilence(); } catch (...) { ReportPlugException(mpt::String::PrintW(L"Exception in SetParameter(%1, %2)!", nIndex, fValue)); @@ -1348,6 +1349,7 @@ try { m_Effect.dispatcher(&m_Effect, effProcessEvents, 0, 0, &vstEvents, 0); + ResetSilence(); } catch (...) { ReportPlugException(mpt::String::PrintW(L"Exception in ProcessVSTEvents(numEvents:%1)!", @@ -1358,14 +1360,16 @@ // Receive events from plugin and send them to the next plugin in the chain. -void CVstPlugin::ReceiveVSTEvents(const VstEvents *events) const -//-------------------------------------------------------------- +void CVstPlugin::ReceiveVSTEvents(const VstEvents *events) +//-------------------------------------------------------- { if(m_pMixStruct == nullptr) { return; } + ResetSilence(); + // I think we should only route events to plugins that are explicitely specified as output plugins of the current plugin. // This should probably use GetOutputPlugList here if we ever get to support multiple output plugins. PLUGINDEX receiver = m_pMixStruct->GetOutputPlugin(); @@ -1698,6 +1702,7 @@ Log("Sending Midi %02X.%02X.%02X\n", event.midiData[0]&0xff, event.midiData[1]&0xff, event.midiData[2]&0xff); #endif + ResetSilence(); return vstEvents.Enqueue(reinterpret_cast<VstEvent *>(&event), insertAtFront); } @@ -1715,6 +1720,7 @@ event.sysexDump = const_cast<char *>(message); // We will make our own copy in VstEventQueue::Enqueue event.resvd2 = 0; + ResetSilence(); return vstEvents.Enqueue(reinterpret_cast<VstEvent *>(&event)); } Modified: trunk/OpenMPT/mptrack/Vstplug.h =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.h 2014-09-09 19:36:34 UTC (rev 4274) +++ trunk/OpenMPT/mptrack/Vstplug.h 2014-09-11 19:01:03 UTC (rev 4275) @@ -82,7 +82,7 @@ // Check whether a plugin can be hosted inside OpenMPT or requires bridging uint8 GetDllBits(bool fromCache = true) const; - bool IsNative(bool fromCache = true) const { return GetDllBits(fromCache) == sizeof(void *) * 8; } + bool IsNative(bool fromCache = true) const { return GetDllBits(fromCache) == sizeof(void *) * CHAR_BIT; } void WriteToCache() const; @@ -93,7 +93,7 @@ | (category << 1) | (useBridge ? 0x100 : 0) | (shareBridgeInstance ? 0x200 : 0) - | (dllBits / 8) << 10; + | ((dllBits / 8) << 10); } void DecodeCacheFlags(uint32 flags) @@ -214,6 +214,9 @@ bool ProgramsAreChunks() const { return (m_Effect.flags & effFlagsProgramChunks) != 0; } bool GetParams(float* param, VstInt32 min, VstInt32 max); bool RandomizeParams(PlugParamIndex minParam = 0, PlugParamIndex maxParam = 0); + // If true, the plugin produces an output even if silence is being fed into it. + bool ShouldProcessSilence() { return m_Effect.numInputs == 0 || ((m_Effect.flags & effFlagsNoSoundInStop) == 0 && Dispatch(effGetTailSize, 0, 0, nullptr, 0.0f) != 1); } + void ResetSilence() { m_MixState.ResetSilence(); } #ifdef MODPLUG_TRACKER forceinline CModDoc *GetModDoc(); forceinline const CModDoc *GetModDoc() const; @@ -304,7 +307,7 @@ // Process incoming and outgoing VST events. void ProcessVSTEvents(); - void ReceiveVSTEvents(const VstEvents *events) const; + void ReceiveVSTEvents(const VstEvents *events); void ProcessMixOps(float *pOutL, float *pOutR, float *leftPlugOutput, float *rightPlugOutput, size_t nSamples); @@ -323,6 +326,8 @@ void SetParameter(PlugParamIndex, PlugParamValue) {} VstInt32 GetUID() const { return 0; } VstInt32 GetVersion() const { return 0; } + bool ShouldProcessSilence() { return false; } + void ResetSilence() { } bool CanAutomateParameter(PlugParamIndex) { return false; } Modified: trunk/OpenMPT/soundlib/Fastmix.cpp =================================================================== --- trunk/OpenMPT/soundlib/Fastmix.cpp 2014-09-09 19:36:34 UTC (rev 4274) +++ trunk/OpenMPT/soundlib/Fastmix.cpp 2014-09-11 19:01:03 UTC (rev 4275) @@ -98,6 +98,7 @@ BuildMixFuncTable(FIRFilterInterpolation), // FIR SRC }; + #undef BuildMixFuncTableRamp #undef BuildMixFuncTableFilter #undef BuildMixFuncTable @@ -489,6 +490,11 @@ // Restore sample pointer in case it got changed through loop wrap-around chn.pCurrentSample = samplePointer; nchmixed += naddmix; + + if(naddmix && nMixPlugin > 0 && nMixPlugin <= MAX_MIXPLUGINS && m_MixPlugins[nMixPlugin - 1].pMixState) + { + m_MixPlugins[nMixPlugin - 1].pMixState->ResetSilence(); + } } m_nMixStat = std::max<CHANNELINDEX>(m_nMixStat, nchmixed); } @@ -497,10 +503,14 @@ void CSoundFile::ProcessPlugins(UINT nCount) //------------------------------------------ { + // If any sample channels are active or any plugin has some input, possibly suspended master plugins need to be woken up. + bool masterHasInput = (m_nMixStat > 0); + #ifdef MPT_INTMIXER const float IntToFloat = m_PlayConfig.getIntToFloat(); const float FloatToInt = m_PlayConfig.getFloatToInt(); #endif // MPT_INTMIXER + // Setup float inputs for(PLUGINDEX plug = 0; plug < MAX_MIXPLUGINS; plug++) { @@ -545,6 +555,11 @@ memset(pState->pOutBufferR, 0, nCount * sizeof(pState->pOutBufferR[0])); } pState->dwFlags &= ~SNDMIXPLUGINSTATE::psfMixReady; + + if(!plugin.IsMasterEffect() && !(pState->dwFlags & SNDMIXPLUGINSTATE::psfSilenceBypass)) + { + masterHasInput = true; + } } } // Convert mix buffer @@ -565,6 +580,25 @@ && plugin.pMixState->pOutBufferL != nullptr && plugin.pMixState->pOutBufferR != nullptr) { + if(!plugin.IsMasterEffect() && !plugin.pMixPlugin->ShouldProcessSilence() && !(plugin.pMixState->dwFlags & SNDMIXPLUGINSTATE::psfHasInput)) + { + // If plugin has no inputs and isn't a master plugin, we shouldn't let it process silence if possible. + // I have yet to encounter a plugin which actually sets this flag. + bool hasInput = false; + for(PLUGINDEX inPlug = 0; inPlug < plug; inPlug++) + { + if(m_MixPlugins[inPlug].GetOutputPlugin() == plug) + { + hasInput = true; + break; + } + } + if(!hasInput) + { + continue; + } + } + bool isMasterMix = false; if (pMixL == plugin.pMixState->pOutBufferL) { @@ -581,9 +615,11 @@ { PLUGINDEX nOutput = plugin.GetOutputPlugin(); if(nOutput > plug && nOutput != PLUGINDEX_INVALID - && m_MixPlugins[nOutput].pMixState != nullptr) + && m_MixPlugins[nOutput].pMixState != nullptr + && m_MixPlugins[nOutput].pMixPlugin != nullptr) { SNDMIXPLUGINSTATE *pOutState = m_MixPlugins[nOutput].pMixState; + if(!(pState->dwFlags & SNDMIXPLUGINSTATE::psfSilenceBypass)) m_MixPlugins[nOutput].pMixPlugin->ResetSilence(); if(pOutState->pOutBufferL != nullptr && pOutState->pOutBufferR != nullptr) { @@ -621,9 +657,24 @@ } pMixL = pOutL; pMixR = pOutR; + + if(masterHasInput) + { + // Samples or plugins are being rendered, so turn off auto-bypass for this master effect. + if(plugin.pMixPlugin != nullptr) plugin.pMixPlugin->ResetSilence(); + SNDMIXPLUGIN *chain = &plugin; + while(chain->GetOutputPlugin() != PLUGINDEX_INVALID) + { + chain = &m_MixPlugins[chain->GetOutputPlugin()]; + if(chain->pMixPlugin) + { + chain->pMixPlugin->ResetSilence(); + } + } + } } - if (plugin.IsBypassed()) + if(plugin.IsBypassed() || (plugin.IsAutoSuspendable() && (pState->dwFlags & SNDMIXPLUGINSTATE::psfSilenceBypass))) { const float * const pInL = pState->pOutBufferL; const float * const pInR = pState->pOutBufferR; @@ -635,7 +686,30 @@ } else { pObject->Process(pOutL, pOutR, nCount); + + pState->inputSilenceCount += nCount; + if(plugin.IsAutoSuspendable() && pState->inputSilenceCount >= m_MixerSettings.gdwMixingFreq * 4) + { + bool isSilent = true; + for(uint32_t i = 0; i < nCount; i++) + { + if(pOutL[i] > FLT_EPSILON || pOutL[i] < -FLT_EPSILON + || pOutR[i] > FLT_EPSILON || pOutR[i] < -FLT_EPSILON) + { + isSilent = false; + break; + } + } + if(isSilent) + { + pState->dwFlags |= SNDMIXPLUGINSTATE::psfSilenceBypass; + } else + { + pState->inputSilenceCount = 0; + } + } } + pState->dwFlags &= ~SNDMIXPLUGINSTATE::psfHasInput; } } #ifdef MPT_INTMIXER Modified: trunk/OpenMPT/soundlib/plugins/PlugInterface.h =================================================================== --- trunk/OpenMPT/soundlib/plugins/PlugInterface.h 2014-09-09 19:36:34 UTC (rev 4274) +++ trunk/OpenMPT/soundlib/plugins/PlugInterface.h 2014-09-11 19:01:03 UTC (rev 4275) @@ -70,6 +70,8 @@ virtual bool isInstrument() = 0; virtual bool CanRecieveMidiEvents() = 0; virtual void SetDryRatio(UINT param) = 0; + virtual bool ShouldProcessSilence() = 0; + virtual void ResetSilence() = 0; virtual void SetEditorPos(int32 x, int32 y) = 0; virtual void GetEditorPos(int32 &x, int32 &y) const = 0; @@ -91,13 +93,25 @@ enum PluginStateFlags { psfMixReady = 0x01, // Set when cleared + psfHasInput = 0x02, // Set when plugin has non-silent input + psfSilenceBypass = 0x04, // Bypass because of silence detection }; mixsample_t *pMixBuffer; // Stereo effect send buffer float *pOutBufferL; // Temp storage for int -> float conversion float *pOutBufferR; uint32 dwFlags; // PluginStateFlags - mixsample_t nVolDecayL, nVolDecayR; // Buffer click removal + uint32 inputSilenceCount; // How much silence has been processed? (for plugin auto-turnoff) + mixsample_t nVolDecayL, nVolDecayR; // Buffer click removal - I think these are *always* 0. + + SNDMIXPLUGINSTATE() { memset(this, 0, sizeof(*this)); } + + void ResetSilence() + { + dwFlags |= psfHasInput; + dwFlags &= ~psfSilenceBypass; + inputSilenceCount = 0; + } }; @@ -114,6 +128,7 @@ irBypass = 0x02, // Bypass effect irWetMix = 0x04, // Wet Mix (dry added) irExpandMix = 0x08, // [0%,100%] -> [-200%,200%] + irAutoSuspend = 0x10, // Plugin will automatically suspend on silence }; VstInt32 dwPluginId1; // Plugin type (kEffectMagic, kDmoMagic, kBuzzMagic) @@ -184,6 +199,8 @@ { return (Info.routingFlags & SNDMIXPLUGININFO::irExpandMix) != 0; } bool IsBypassed() const { return (Info.routingFlags & SNDMIXPLUGININFO::irBypass) != 0; } + bool IsAutoSuspendable() const + { return (Info.routingFlags & SNDMIXPLUGININFO::irAutoSuspend) != 0; } // Input routing setters void SetGain(uint8 gain) @@ -198,6 +215,8 @@ { if(expanded) Info.routingFlags |= SNDMIXPLUGININFO::irExpandMix; else Info.routingFlags &= ~SNDMIXPLUGININFO::irExpandMix; } void SetBypass(bool bypass = true) { if(pMixPlugin != nullptr) pMixPlugin->Bypass(bypass); else Info.SetBypass(bypass); } + void SetAutoSuspend(bool suspend = true) + { if(suspend) Info.routingFlags |= SNDMIXPLUGININFO::irAutoSuspend; else Info.routingFlags &= ~SNDMIXPLUGININFO::irAutoSuspend; } // Output routing getters bool IsOutputToMaster() const This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2014-09-11 23:33:41
|
Revision: 4277 http://sourceforge.net/p/modplug/code/4277 Author: saga-games Date: 2014-09-11 23:33:32 +0000 (Thu, 11 Sep 2014) Log Message: ----------- [Imp] The plugin bridge does now also create crash dumps automatically. OpenMPT's /fullMemDump command line switch also applies to these dumps. [Mod] OpenMPT: Version is now 1.24.00.03 Modified Paths: -------------- trunk/OpenMPT/common/versionNumber.h trunk/OpenMPT/mptrack/ExceptionHandler.cpp trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters trunk/OpenMPT/pluginBridge/Bridge.cpp trunk/OpenMPT/pluginBridge/Bridge.h trunk/OpenMPT/pluginBridge/BridgeCommon.h trunk/OpenMPT/pluginBridge/BridgeWrapper.cpp Added Paths: ----------- trunk/OpenMPT/common/WriteMemoryDump.h Added: trunk/OpenMPT/common/WriteMemoryDump.h =================================================================== --- trunk/OpenMPT/common/WriteMemoryDump.h (rev 0) +++ trunk/OpenMPT/common/WriteMemoryDump.h 2014-09-11 23:33:32 UTC (rev 4277) @@ -0,0 +1,64 @@ +/* + * WriteMemoryDump.h + * ----------------- + * Purpose: Code for writing memory dumps to a file. + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#include "dbghelp.h" + +OPENMPT_NAMESPACE_BEGIN + +typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType, + CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, + CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, + CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam + ); + +static bool WriteMemoryDump(_EXCEPTION_POINTERS *pExceptionInfo, const WCHAR *filename, bool fullMemDump) +{ + bool result = false; + + HMODULE hDll = ::LoadLibraryW(L"DBGHELP.DLL"); + if (hDll) + { + MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress(hDll, "MiniDumpWriteDump"); + if (pDump) + { + + HANDLE hFile = ::CreateFileW(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile != INVALID_HANDLE_VALUE) + { + _MINIDUMP_EXCEPTION_INFORMATION ExInfo; + + if(pExceptionInfo) + { + ExInfo.ThreadId = ::GetCurrentThreadId(); + ExInfo.ExceptionPointers = pExceptionInfo; + ExInfo.ClientPointers = NULL; + } + + pDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, + fullMemDump ? + (MINIDUMP_TYPE)(MiniDumpWithFullMemory | MiniDumpWithHandleData | MiniDumpWithThreadInfo | MiniDumpWithProcessThreadData | MiniDumpWithFullMemoryInfo +#if MPT_COMPILER_MSVC && MPT_MSVC_AT_LEAST(2010,0) + | MiniDumpIgnoreInaccessibleMemory | MiniDumpWithTokenInformation +#endif + ) + : + MiniDumpNormal, + pExceptionInfo ? &ExInfo : NULL, NULL, NULL); + ::CloseHandle(hFile); + + result = true; + } + } + ::FreeLibrary(hDll); + } + return result; +} + +OPENMPT_NAMESPACE_END Property changes on: trunk/OpenMPT/common/WriteMemoryDump.h ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/x-chdr \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Modified: trunk/OpenMPT/common/versionNumber.h =================================================================== --- trunk/OpenMPT/common/versionNumber.h 2014-09-11 19:18:01 UTC (rev 4276) +++ trunk/OpenMPT/common/versionNumber.h 2014-09-11 23:33:32 UTC (rev 4277) @@ -19,7 +19,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 24 #define VER_MINOR 00 -#define VER_MINORMINOR 02 +#define VER_MINORMINOR 03 //Version string. For example "1.17.02.28" #define MPT_VERSION_STR VER_STRINGIZE(VER_MAJORMAJOR) "." VER_STRINGIZE(VER_MAJOR) "." VER_STRINGIZE(VER_MINOR) "." VER_STRINGIZE(VER_MINORMINOR) Modified: trunk/OpenMPT/mptrack/ExceptionHandler.cpp =================================================================== --- trunk/OpenMPT/mptrack/ExceptionHandler.cpp 2014-09-11 19:18:01 UTC (rev 4276) +++ trunk/OpenMPT/mptrack/ExceptionHandler.cpp 2014-09-11 23:33:32 UTC (rev 4277) @@ -14,7 +14,7 @@ #include "Moddoc.h" #include <shlwapi.h> #include "ExceptionHandler.h" -#include "dbghelp.h" +#include "../common/WriteMemoryDump.h" #include "../common/version.h" @@ -23,20 +23,13 @@ bool ExceptionHandler::fullMemDump = false; - -typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType, - CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, - CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, - CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam - ); - - enum DumpMode { DumpModeCrash = 0, DumpModeWarning = 1, }; + static void GenerateDump(CString &errorMessage, _EXCEPTION_POINTERS *pExceptionInfo=NULL, DumpMode mode=DumpModeCrash) //-------------------------------------------------------------------------------------------------------------------- { @@ -60,43 +53,11 @@ } // Create minidump... - HMODULE hDll = ::LoadLibraryW(L"DBGHELP.DLL"); - if (hDll) + const mpt::PathString filename = baseRescuePath + MPT_PATHSTRING("crash.dmp"); + if(WriteMemoryDump(pExceptionInfo, filename.AsNative().c_str(), ExceptionHandler::fullMemDump)) { - MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress(hDll, "MiniDumpWriteDump"); - if (pDump) - { - const mpt::PathString filename = baseRescuePath + MPT_PATHSTRING("crash.dmp"); - - HANDLE hFile = ::CreateFileW(filename.AsNative().c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile != INVALID_HANDLE_VALUE) - { - _MINIDUMP_EXCEPTION_INFORMATION ExInfo; - - if(pExceptionInfo) - { - ExInfo.ThreadId = ::GetCurrentThreadId(); - ExInfo.ExceptionPointers = pExceptionInfo; - ExInfo.ClientPointers = NULL; - } - - pDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, - ExceptionHandler::fullMemDump ? - (MINIDUMP_TYPE)(MiniDumpWithFullMemory | MiniDumpWithHandleData | MiniDumpWithThreadInfo | MiniDumpWithProcessThreadData | MiniDumpWithFullMemoryInfo -#if MPT_COMPILER_MSVC && MPT_MSVC_AT_LEAST(2010,0) - | MiniDumpIgnoreInaccessibleMemory | MiniDumpWithTokenInformation -#endif - ) - : - MiniDumpNormal, - pExceptionInfo ? &ExInfo : NULL, NULL, NULL); - ::CloseHandle(hFile); - - errorMessage += "\n\nDebug information has been saved to\n" - + mpt::ToCString(baseRescuePath.ToWide()); - } - } - ::FreeLibrary(hDll); + errorMessage += "\n\nDebug information has been saved to\n" + + mpt::ToCString(baseRescuePath.ToWide()); } // Rescue modified files... @@ -148,7 +109,6 @@ { Reporting::Error(errorMessage, "OpenMPT Crash", pMainFrame); } - } Modified: trunk/OpenMPT/mptrack/mptrack_08.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_08.vcproj 2014-09-11 19:18:01 UTC (rev 4276) +++ trunk/OpenMPT/mptrack/mptrack_08.vcproj 2014-09-11 23:33:32 UTC (rev 4277) @@ -1554,6 +1554,10 @@ > </File> <File + RelativePath="..\common\WriteMemoryDump.h" + > + </File> + <File RelativePath=".\view_com.h" > </File> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2014-09-11 19:18:01 UTC (rev 4276) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2014-09-11 23:33:32 UTC (rev 4277) @@ -659,6 +659,7 @@ <ClInclude Include="..\common\typedefs.h" /> <ClInclude Include="..\common\version.h" /> <ClInclude Include="..\common\versionNumber.h" /> + <ClInclude Include="..\common\WriteMemoryDump.h" /> <ClInclude Include="..\pluginBridge\AEffectWrapper.h" /> <ClInclude Include="..\pluginBridge\BridgeCommon.h" /> <ClInclude Include="..\pluginBridge\BridgeWrapper.h" /> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2014-09-11 19:18:01 UTC (rev 4276) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2014-09-11 23:33:32 UTC (rev 4277) @@ -1020,6 +1020,9 @@ <ClInclude Include="..\common\mptAtomic.h"> <Filter>Header Files\common</Filter> </ClInclude> + <ClInclude Include="..\common\WriteMemoryDump.h"> + <Filter>Header Files\common</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <None Include="res\bitmap1.bmp"> Modified: trunk/OpenMPT/pluginBridge/Bridge.cpp =================================================================== --- trunk/OpenMPT/pluginBridge/Bridge.cpp 2014-09-11 19:18:01 UTC (rev 4276) +++ trunk/OpenMPT/pluginBridge/Bridge.cpp 2014-09-11 23:33:32 UTC (rev 4277) @@ -44,28 +44,35 @@ #define assert(x) #endif +#include "../common/CompilerDetect.h" +#include "../common/WriteMemoryDump.h" #include "Bridge.h" -#include "../common/thread.h" -OPENMPT_NAMESPACE_BEGIN +// Crash handler for writing memory dumps +static LONG WINAPI CrashHandler(_EXCEPTION_POINTERS *pExceptionInfo) +{ + WCHAR tempPath[MAX_PATH + 2]; + DWORD result = GetTempPathW(MAX_PATH + 1, tempPath); + if(result > 0 && result <= MAX_PATH + 1) + { + std::wstring filename = tempPath; + filename += L"OpenMPT Crash Files\\"; + CreateDirectoryW(filename.c_str(), nullptr); + tempPath[0] = 0; + const int ch = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, 0, nullptr, L"'PluginBridge 'yyyy'-'MM'-'dd ", tempPath, CountOf(tempPath)); + if(ch) GetTimeFormatW(LOCALE_SYSTEM_DEFAULT, 0, nullptr, L"HH'.'mm'.'ss'.dmp'", tempPath + ch - 1, CountOf(tempPath) - ch + 1); + filename += tempPath; -LONG PluginBridge::instanceCount = 0; -Event PluginBridge::sigQuit; + WriteMemoryDump(pExceptionInfo, filename.c_str(), OPENMPT_NAMESPACE::PluginBridge::fullMemDump); + } -// This is kind of a back-up pointer in case we couldn't sneak our pointer into the AEffect struct yet. -// It always points to the last intialized PluginBridge object. -PluginBridge *PluginBridge::latestInstance = nullptr; -WNDCLASSEX PluginBridge::windowClass; -#define WINDOWCLASSNAME _T("OpenMPTPluginBridge") + // Let Windows handle the exception... + return EXCEPTION_CONTINUE_SEARCH; +} -enum { kVstTimeInfoInit = 1 << 31 }; - -OPENMPT_NAMESPACE_END - - int _tmain(int argc, TCHAR *argv[]) { if(argc != 2) @@ -74,6 +81,8 @@ return -1; } + ::SetUnhandledExceptionFilter(CrashHandler); + uint32_t parentProcessId = _ttoi(argv[1]); OPENMPT_NAMESPACE::PluginBridge::InitializeStaticVariables(); @@ -96,7 +105,19 @@ OPENMPT_NAMESPACE_BEGIN +LONG PluginBridge::instanceCount = 0; +Event PluginBridge::sigQuit; +bool PluginBridge::fullMemDump = false; +// This is kind of a back-up pointer in case we couldn't sneak our pointer into the AEffect struct yet. +// It always points to the last intialized PluginBridge object. +PluginBridge *PluginBridge::latestInstance = nullptr; +WNDCLASSEX PluginBridge::windowClass; +#define WINDOWCLASSNAME _T("OpenMPTPluginBridge") + +enum { kVstTimeInfoInit = 1 << 31 }; + + // Initialize static stuff like the editor window class void PluginBridge::InitializeStaticVariables() { @@ -363,9 +384,10 @@ { otherPtrSize = msg->hostPtrSize; mixBufSize = msg->mixBufSize; + fullMemDump = msg->fullMemDump != 0; msg->result = 0; msg->str[CountOf(msg->str) - 1] = 0; - + #ifdef _CONSOLE SetConsoleTitleW(msg->str); #endif Modified: trunk/OpenMPT/pluginBridge/Bridge.h =================================================================== --- trunk/OpenMPT/pluginBridge/Bridge.h 2014-09-11 19:18:01 UTC (rev 4276) +++ trunk/OpenMPT/pluginBridge/Bridge.h 2014-09-11 23:33:32 UTC (rev 4277) @@ -19,6 +19,7 @@ { public: static Event sigQuit; + static bool fullMemDump; protected: static LONG instanceCount; Modified: trunk/OpenMPT/pluginBridge/BridgeCommon.h =================================================================== --- trunk/OpenMPT/pluginBridge/BridgeCommon.h 2014-09-11 19:18:01 UTC (rev 4276) +++ trunk/OpenMPT/pluginBridge/BridgeCommon.h 2014-09-11 23:33:32 UTC (rev 4277) @@ -276,6 +276,7 @@ int32_t version; // Protocol version used by host int32_t hostPtrSize; // Size of VstIntPtr in host uint32_t mixBufSize; // Interal mix buffer size (for shared memory audio buffers) + uint32_t fullMemDump; // When crashing, create full memory dumps instead of stack dumps wchar_t str[_MAX_PATH]; // Plugin file to load. Out: Error message if result != 0. }; @@ -333,13 +334,14 @@ wcsncpy(newInstance.memName, memName, CountOf(newInstance.memName) - 1); } - void Init(const wchar_t *pluginPath, uint32_t mixBufSize) + void Init(const wchar_t *pluginPath, uint32_t mixBufSize, bool fullMemDump) { SetType(MsgHeader::init, sizeof(InitMsg)); init.result = 0; init.hostPtrSize = sizeof(VstIntPtr); init.mixBufSize = mixBufSize; + init.fullMemDump = fullMemDump; wcsncpy(init.str, pluginPath, CountOf(init.str) - 1); } Modified: trunk/OpenMPT/pluginBridge/BridgeWrapper.cpp =================================================================== --- trunk/OpenMPT/pluginBridge/BridgeWrapper.cpp 2014-09-11 19:18:01 UTC (rev 4276) +++ trunk/OpenMPT/pluginBridge/BridgeWrapper.cpp 2014-09-11 23:33:32 UTC (rev 4277) @@ -15,6 +15,7 @@ #include "misc_util.h" #include "../mptrack/Mptrack.h" #include "../mptrack/Vstplug.h" +#include "../mptrack/ExceptionHandler.h" #include "../common/mptFstream.h" #include "../common/thread.h" #include "../common/StringFixer.h" @@ -211,7 +212,7 @@ otherThread = mpt::thread_member<BridgeWrapper, &BridgeWrapper::MessageThread>(this); BridgeMessage initMsg; - initMsg.Init(pluginPath.ToWide().c_str(), MIXBUFFERSIZE); + initMsg.Init(pluginPath.ToWide().c_str(), MIXBUFFERSIZE, ExceptionHandler::fullMemDump); if(!SendToBridge(initMsg)) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <man...@us...> - 2014-09-12 10:22:28
|
Revision: 4279 http://sourceforge.net/p/modplug/code/4279 Author: manxorist Date: 2014-09-12 10:22:15 +0000 (Fri, 12 Sep 2014) Log Message: ----------- Merged revision(s) 4097-4106, 4124, 4153-4172, 4174, 4176, 4266-4267 from branches/manx/io-and-endian-fixes: [Ref] Add mpt::true_type and mpt::false_type. This simplifies defining our own type traits. For compilers which support for <type_traits>, these are the same as std::true_type and std::false_type, for other compilers a simple ad-hoc C++11 compatible version is used. ........ [Ref] Add mpt::is_binary_safe<T> which shall be true for types which have a defined-endian and defined-packing in-memory representationand and can thus be directly written into binary files. ........ [Ref] Add mptIO.h. This contains a small wrapper that allows for a common interface for both, FILE* and std::ostream (and potentially anything else) file i/o, and provides small, endian-safe, writing helper functions. ........ [Fix] Fix a lot of endianness problems in WriteInstrumentHeaderStructOrField() and SaveIT(). The full test suite still does not pass on big-endian, so this is just another tiny step. ........ [Fix] In SaveModularInstrumentData, modularInstSize gets endian-swapped on big-endian and used after that without swapping it back. Fix it by using endian-safe writing function. ........ [Imp] Run the full test suite (including file saving) for libopenmpt on big-endian platforms. It finally passes. ........ [Ref] Add mpt::IO::WriteConvertEndianness(). ........ [Fix] Fix mpt::IO::WriteConvertEndianness(). ........ [Fix] Simplify mpt::IO and make it actually work with std::ostream. ........ [Fix] Add mptIO.h to MSVC projects. ........ [Fix] Fix mpt::IO::Flush(FILE*). ........ [Ref] Add read support to mpt::IO. [Ref] Use 64bit FILE* on MSVC and posix systems. Add static asserts to force 64bit file IO (breaks obscure platforms for now). ........ [Ref] mptIO: Silence stupid MSVC warnings. [Ref] mptIO: Add ReadBinaryLE and WriteBinaryLE. [Ref] mptIO: Add ReadBinaryTruncatedLE and WriteBinaryTruncatedLE. ........ [Ref] serialization_utils: Base Binaryread and Binaryrite on mpt::IO. ........ [Ref] Add byte swapping for 64bit integers. ........ [Ref] mptIO: Add adaptive-size integer (as used by serialization_utils) read and write functions. ........ [Ref] serialization_utils: Convert to mpt::IO adaptive integer I/O functions. ........ [Ref] serialization_utils: Remove unused ReadItem specializations for reading floats and doubles of the opposite size. These are not used anywhere in the code. The one single place where floating point data is read and written via serialization_utils, there is no explicit size tag at all and 32bit is assumed. ........ [Fix] mptIO: Compile fix. ........ [Ref] serialization_utils: Binaryread and Binaryrite are only ever used to write plain integers or plain floats. Enforce this via compile-time assertions. [Fix] serialization_utils: Use explicit IEEE floating point format. ........ [Ref] mptIO: Kill unused ReadBinaryLE and WriteBinaryLE. ........ [Ref] serialization_utils: Replace all usage sites of srlztn::Binarywrite and srlztn::Binaryread outside of serialization_utils with mpt::IO. ........ [Ref] serialization_utils: Document insanity in historic serialization encoding changes. ........ [Ref] mptIO: Add minSize parameter for WriteAdaptiveInt*. ........ [Fix] serialization_utils: Fix writing of map entry count values greater than 16383. ........ [Ref] mptIO: Kill WriteBinaryTruncatedLE. ........ [Fix] __builtin_bswap16 is only available since GCC 4.8 . ........ [Ref] mptIO: Remove bogus code. ........ [Fix] serialization_utils: Fix comment about change in written on-disk format. ........ [Ref] mptIO: Add maxSize parameter for WriteAdaptiveInt*. ........ [Fix] serialization_utils: Revert r4166 and write fixed size=2 AdaptiveInt64LE again for map entry count. (thanks to relabs for noticing) [Fix] serialization_utils: Actually explain the 16000 entries limit and fix the comments about the fixed-size AdaptiveInt64LE usages. (thanks to relabs for explaining) ........ [Ref] serialization_utils: Remove unused functions from public interface. [Fix] serialization_utils: Make debug output endian-clean. ........ [Ref] serialization_utils: Clarify comment once again. ........ [Fix] Do not redefine _FILE_OFFSET_BITS if already defined. ........ [Fix] mptIO: Add back support for 32 bit file offsets in FILE* and std::fstream. ........ Revision Links: -------------- http://sourceforge.net/p/modplug/code/4166 Modified Paths: -------------- trunk/OpenMPT/common/BuildSettings.h trunk/OpenMPT/common/Endianness.h trunk/OpenMPT/common/serialization_utils.cpp trunk/OpenMPT/common/serialization_utils.h trunk/OpenMPT/common/stdafx.h trunk/OpenMPT/common/typedefs.h trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/ModSequence.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/pattern.cpp trunk/OpenMPT/soundlib/tuning.cpp Added Paths: ----------- trunk/OpenMPT/common/mptIO.h Property Changed: ---------------- trunk/OpenMPT/ Index: trunk/OpenMPT =================================================================== --- trunk/OpenMPT 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT 2014-09-12 10:22:15 UTC (rev 4279) Property changes on: trunk/OpenMPT ___________________________________________________________________ Modified: svn:mergeinfo ## -3,6 +3,7 ## /branches/manx/gcc-fixes:2018-2022,2024-2048,2052-2071,2075-2077,2080,2087-2089 /branches/manx/header-dependencies-cleanups:1394-1397,1401-1402,1405-1406 /branches/manx/instrument-fields-fixes:2203-2238 +/branches/manx/io-and-endian-fixes:4097-4267 /branches/manx/lossy-export:2653-2654,2660,2664,2678,2681 /branches/manx/lossy-export-xiph:2663,2677,2680 /branches/manx/mptstring-stdstring-support:2204,2208,2212,2214,2217,2220,2224,2259,2261-2262,2264,2267 \ No newline at end of property Modified: trunk/OpenMPT/common/BuildSettings.h =================================================================== --- trunk/OpenMPT/common/BuildSettings.h 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/common/BuildSettings.h 2014-09-12 10:22:15 UTC (rev 4279) @@ -250,10 +250,6 @@ #define NO_MINIZ #endif -#if defined(MPT_PLATFORM_BIG_ENDIAN) && !defined(MODPLUG_NO_FILESAVE) -#define MODPLUG_NO_FILESAVE // file saving is broken on big endian -#endif - #if !defined(MPT_CHARSET_WIN32) && !defined(MPT_CHARSET_ICONV) && !defined(MPT_CHARSET_CODECVTUTF8) && !defined(MPT_CHARSET_INTERNAL) #define MPT_CHARSET_INTERNAL #endif @@ -378,6 +374,10 @@ #endif +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +#endif + #if MPT_COMPILER_MSVC #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS // Define to disable the "This function or variable may be unsafe" warnings. Modified: trunk/OpenMPT/common/Endianness.h =================================================================== --- trunk/OpenMPT/common/Endianness.h 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/common/Endianness.h 2014-09-12 10:22:15 UTC (rev 4279) @@ -27,12 +27,17 @@ // format. #if MPT_COMPILER_GCC +#if MPT_GCC_AT_LEAST(4,8,0) +#define bswap16 __builtin_bswap16 +#endif #if MPT_GCC_AT_LEAST(4,3,0) #define MPT_bswap32 __builtin_bswap32 +#define MPT_bswap64 __builtin_bswap64 #endif #elif MPT_COMPILER_MSVC #define MPT_bswap16 _byteswap_ushort #define MPT_bswap32 _byteswap_ulong +#define MPT_bswap64 _byteswap_uint64 #endif // catch system macros @@ -46,6 +51,11 @@ #define MPT_bswap32 bswap32 #endif #endif +#ifndef MPT_bswap64 +#ifdef bswap64 +#define MPT_bswap64 bswap64 +#endif +#endif // No intrinsics available #ifndef MPT_bswap16 @@ -54,7 +64,22 @@ #ifndef MPT_bswap32 #define MPT_bswap32(x) (((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) | ((x & 0xFF000000) >> 24)) #endif +#ifndef MPT_bswap64 +#define MPT_bswap64(x) \ + ( uint64(0) \ + | (((x >> 0) & 0xff) << 56) \ + | (((x >> 8) & 0xff) << 48) \ + | (((x >> 16) & 0xff) << 40) \ + | (((x >> 24) & 0xff) << 32) \ + | (((x >> 32) & 0xff) << 24) \ + | (((x >> 40) & 0xff) << 16) \ + | (((x >> 48) & 0xff) << 8) \ + | (((x >> 56) & 0xff) << 0) \ + ) \ +/**/ +#endif + // Deprecated. Use "SwapBytesXX" versions below. #ifdef MPT_PLATFORM_BIG_ENDIAN inline uint32 LittleEndian(uint32 x) { return MPT_bswap32(x); } @@ -69,23 +94,31 @@ #endif #if defined(MPT_PLATFORM_BIG_ENDIAN) +#define MPT_bswap64le(x) MPT_bswap64(x) #define MPT_bswap32le(x) MPT_bswap32(x) #define MPT_bswap16le(x) MPT_bswap16(x) +#define MPT_bswap64be(x) (x) #define MPT_bswap32be(x) (x) #define MPT_bswap16be(x) (x) #elif defined(MPT_PLATFORM_LITTLE_ENDIAN) +#define MPT_bswap64be(x) MPT_bswap64(x) #define MPT_bswap32be(x) MPT_bswap32(x) #define MPT_bswap16be(x) MPT_bswap16(x) +#define MPT_bswap64le(x) (x) #define MPT_bswap32le(x) (x) #define MPT_bswap16le(x) (x) #endif +inline uint64 SwapBytesBE_(uint64 value) { return MPT_bswap64be(value); } inline uint32 SwapBytesBE_(uint32 value) { return MPT_bswap32be(value); } inline uint16 SwapBytesBE_(uint16 value) { return MPT_bswap16be(value); } +inline uint64 SwapBytesLE_(uint64 value) { return MPT_bswap64le(value); } inline uint32 SwapBytesLE_(uint32 value) { return MPT_bswap32le(value); } inline uint16 SwapBytesLE_(uint16 value) { return MPT_bswap16le(value); } +inline int64 SwapBytesBE_(int64 value) { return MPT_bswap64be(value); } inline int32 SwapBytesBE_(int32 value) { return MPT_bswap32be(value); } inline int16 SwapBytesBE_(int16 value) { return MPT_bswap16be(value); } +inline int64 SwapBytesLE_(int64 value) { return MPT_bswap64le(value); } inline int32 SwapBytesLE_(int32 value) { return MPT_bswap32le(value); } inline int16 SwapBytesLE_(int16 value) { return MPT_bswap16le(value); } @@ -116,10 +149,13 @@ #undef MPT_bswap16le #undef MPT_bswap32le +#undef MPT_bswap64le #undef MPT_bswap16be #undef MPT_bswap32be +#undef MPT_bswap64be #undef MPT_bswap16 #undef MPT_bswap32 +#undef MPT_bswap64 // 1.0f --> 0x3f800000u @@ -230,6 +266,13 @@ } }; +namespace mpt { + +template <> struct is_binary_safe<IEEE754binary32Emulated<0,1,2,3> > : public mpt::true_type { }; +template <> struct is_binary_safe<IEEE754binary32Emulated<3,2,1,0> > : public mpt::true_type { }; + +} // namespace mpt + #if MPT_PLATFORM_IEEE_FLOAT struct IEEE754binary32Native @@ -298,6 +341,12 @@ } }; +namespace mpt { + +template <> struct is_binary_safe<IEEE754binary32Native> : public mpt::true_type { }; + +} // namespace mpt + #if defined(MPT_PLATFORM_LITTLE_ENDIAN) typedef IEEE754binary32Native IEEE754binary32LE; typedef IEEE754binary32Emulated<0,1,2,3> IEEE754binary32BE; Copied: trunk/OpenMPT/common/mptIO.h (from rev 4267, branches/manx/io-and-endian-fixes/common/mptIO.h) =================================================================== --- trunk/OpenMPT/common/mptIO.h (rev 0) +++ trunk/OpenMPT/common/mptIO.h 2014-09-12 10:22:15 UTC (rev 4279) @@ -0,0 +1,348 @@ +/* + * mptIO.h + * ------- + * Purpose: Basic functions for reading/writing binary and endian safe data to/from files/streams. + * Notes : This is work-in-progress. + * Some useful functions for reading and writing are still missing. + * Authors: Joern Heusipp + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#pragma once + + +#include "../common/typedefs.h" +#include "../common/Endianness.h" +#include <ios> +#include <iostream> +#include <istream> +#include <limits> +#include <ostream> +#if defined(HAS_TYPE_TRAITS) +#include <type_traits> +#endif +#include <cstdio> +#include <cstring> +#include <stdio.h> + + +OPENMPT_NAMESPACE_BEGIN + + +namespace mpt { + +namespace IO { + +typedef int64 Offset; + + + +// Returns true iff 'off' fits into 'Toff'. +template < typename Toff > +inline bool OffsetFits(IO::Offset off) +{ + return (static_cast<IO::Offset>(mpt::saturate_cast<Toff>(off)) == off); +} + + + +//STATIC_ASSERT(sizeof(std::streamoff) == 8); // Assert 64bit file support. +inline bool IsValid(std::ostream & f) { return !f.fail(); } +inline bool IsValid(std::istream & f) { return !f.fail(); } +inline bool IsValid(std::iostream & f) { return !f.fail(); } +inline IO::Offset TellRead(std::istream & f) { return f.tellg(); } +inline IO::Offset TellWrite(std::ostream & f) { return f.tellp(); } +inline bool SeekBegin(std::ostream & f) { f.seekp(0); return !f.fail(); } +inline bool SeekBegin(std::istream & f) { f.seekg(0); return !f.fail(); } +inline bool SeekBegin(std::iostream & f) { f.seekg(0); f.seekp(0); return !f.fail(); } +inline bool SeekEnd(std::ostream & f) { f.seekp(0, std::ios::end); return !f.fail(); } +inline bool SeekEnd(std::istream & f) { f.seekg(0, std::ios::end); return !f.fail(); } +inline bool SeekEnd(std::iostream & f) { f.seekg(0, std::ios::end); f.seekp(0, std::ios::end); return !f.fail(); } +inline bool SeekAbsolute(std::ostream & f, IO::Offset pos) { if(!OffsetFits<std::streamoff>(pos)) { return false; } f.seekp(pos, std::ios::beg); return !f.fail(); } +inline bool SeekAbsolute(std::istream & f, IO::Offset pos) { if(!OffsetFits<std::streamoff>(pos)) { return false; } f.seekg(pos, std::ios::beg); return !f.fail(); } +inline bool SeekAbsolute(std::iostream & f, IO::Offset pos) { if(!OffsetFits<std::streamoff>(pos)) { return false; } f.seekg(pos, std::ios::beg); f.seekp(pos, std::ios::beg); return !f.fail(); } +inline bool SeekRelative(std::ostream & f, IO::Offset off) { if(!OffsetFits<std::streamoff>(off)) { return false; } f.seekp(off, std::ios::cur); return !f.fail(); } +inline bool SeekRelative(std::istream & f, IO::Offset off) { if(!OffsetFits<std::streamoff>(off)) { return false; } f.seekg(off, std::ios::cur); return !f.fail(); } +inline bool SeekRelative(std::iostream & f, IO::Offset off) { if(!OffsetFits<std::streamoff>(off)) { return false; } f.seekg(off, std::ios::cur); f.seekp(off, std::ios::cur); return !f.fail(); } +inline IO::Offset ReadRaw(std::istream & f, uint8 * data, std::size_t size) { return f.read(reinterpret_cast<char *>(data), size) ? f.gcount() : std::streamsize(0); } +inline IO::Offset ReadRaw(std::istream & f, char * data, std::size_t size) { return f.read(data, size) ? f.gcount() : std::streamsize(0); } +inline IO::Offset ReadRaw(std::istream & f, void * data, std::size_t size) { return f.read(reinterpret_cast<char *>(data), size) ? f.gcount() : std::streamsize(0); } +inline bool WriteRaw(std::ostream & f, const uint8 * data, std::size_t size) { f.write(reinterpret_cast<const char *>(data), size); return !f.fail(); } +inline bool WriteRaw(std::ostream & f, const char * data, std::size_t size) { f.write(data, size); return !f.fail(); } +inline bool WriteRaw(std::ostream & f, const void * data, std::size_t size) { f.write(reinterpret_cast<const char *>(data), size); return !f.fail(); } +inline bool IsEof(std::istream & f) { return f.eof(); } +inline bool Flush(std::ostream & f) { f.flush(); return !f.fail(); } + + + +inline bool IsValid(FILE* & f) { return f != NULL; } + +#if MPT_COMPILER_MSVC + +inline IO::Offset TellRead(FILE* & f) { return _ftelli64(f); } +inline IO::Offset TellWrite(FILE* & f) { return _ftelli64(f); } +inline bool SeekBegin(FILE* & f) { return _fseeki64(f, 0, SEEK_SET) == 0; } +inline bool SeekEnd(FILE* & f) { return _fseeki64(f, 0, SEEK_END) == 0; } +inline bool SeekAbsolute(FILE* & f, IO::Offset pos) { return _fseeki64(f, pos, SEEK_SET) == 0; } +inline bool SeekRelative(FILE* & f, IO::Offset off) { return _fseeki64(f, off, SEEK_CUR) == 0; } + +#elif defined(_POSIX_SOURCE) && (_POSIX_SOURCE > 0) + +//STATIC_ASSERT(sizeof(off_t) == 8); +inline IO::Offset TellRead(FILE* & f) { return ftello(f); } +inline IO::Offset TellWrite(FILE* & f) { return ftello(f); } +inline bool SeekBegin(FILE* & f) { return fseeko(f, 0, SEEK_SET) == 0; } +inline bool SeekEnd(FILE* & f) { return fseeko(f, 0, SEEK_END) == 0; } +inline bool SeekAbsolute(FILE* & f, IO::Offset pos) { return OffsetFits<off_t>(pos) && (fseek(f, mpt::saturate_cast<off_t>(pos), SEEK_SET) == 0); } +inline bool SeekRelative(FILE* & f, IO::Offset off) { return OffsetFits<off_t>(off) && (fseek(f, mpt::saturate_cast<off_t>(off), SEEK_CUR) == 0); } + +#else + +//STATIC_ASSERT(sizeof(long) == 8); // Fails on 32bit non-POSIX systems for now. +inline IO::Offset TellRead(FILE* & f) { return ftell(f); } +inline IO::Offset TellWrite(FILE* & f) { return ftell(f); } +inline bool SeekBegin(FILE* & f) { return fseek(f, 0, SEEK_SET) == 0; } +inline bool SeekEnd(FILE* & f) { return fseek(f, 0, SEEK_END) == 0; } +inline bool SeekAbsolute(FILE* & f, IO::Offset pos) { return OffsetFits<long>(pos) && (fseek(f, mpt::saturate_cast<long>(pos), SEEK_SET) == 0); } +inline bool SeekRelative(FILE* & f, IO::Offset off) { return OffsetFits<long>(off) && (fseek(f, mpt::saturate_cast<long>(off), SEEK_CUR) == 0); } + +#endif + +inline IO::Offset ReadRaw(FILE * & f, uint8 * data, std::size_t size) { return fread(data, 1, size, f); } +inline IO::Offset ReadRaw(FILE * & f, char * data, std::size_t size) { return fread(data, 1, size, f); } +inline IO::Offset ReadRaw(FILE * & f, void * data, std::size_t size) { return fread(data, 1, size, f); } +inline bool WriteRaw(FILE* & f, const uint8 * data, std::size_t size) { return fwrite(data, 1, size, f) == size; } +inline bool WriteRaw(FILE* & f, const char * data, std::size_t size) { return fwrite(data, 1, size, f) == size; } +inline bool WriteRaw(FILE* & f, const void * data, std::size_t size) { return fwrite(data, 1, size, f) == size; } +inline bool IsEof(FILE * & f) { return feof(f) != 0; } +inline bool Flush(FILE* & f) { return fflush(f) == 0; } + + + +template <typename Tbinary, typename Tfile> +inline bool Read(Tfile & f, Tbinary & v) +{ + return IO::ReadRaw(f, mpt::GetRawBytes(v), sizeof(Tbinary)) == sizeof(Tbinary); +} + +template <typename Tbinary, typename Tfile> +inline bool Write(Tfile & f, const Tbinary & v) +{ + return IO::WriteRaw(f, mpt::GetRawBytes(v), sizeof(Tbinary)); +} + +template <typename T, typename Tfile> +inline bool ReadBinaryTruncatedLE(Tfile & f, T & v, std::size_t size) +{ + bool result = false; + #ifdef HAS_TYPE_TRAITS + static_assert(std::is_trivial<T>::value == true, ""); + #endif + uint8 bytes[sizeof(T)]; + std::memset(bytes, 0, sizeof(T)); + result = IO::ReadRaw(f, bytes, std::min(size, sizeof(T))) == std::min(size, sizeof(T)); + #ifdef MPT_PLATFORM_BIG_ENDIAN + std::reverse(bytes, bytes + sizeof(T)); + #endif + std::memcpy(&v, bytes, sizeof(T)); + return result; +} + +template <typename T, typename Tfile> +inline bool ReadIntLE(Tfile & f, T & v) +{ + bool result = false; + STATIC_ASSERT(std::numeric_limits<T>::is_integer); + uint8 bytes[sizeof(T)]; + std::memset(bytes, 0, sizeof(T)); + result = (IO::ReadRaw(f, bytes, sizeof(T)) == sizeof(T)); + T val = 0; + std::memcpy(&val, bytes, sizeof(T)); + v = SwapBytesReturnLE(val); + return result; +} + +template <typename T, typename Tfile> +inline bool ReadIntBE(Tfile & f, T & v) +{ + bool result = false; + STATIC_ASSERT(std::numeric_limits<T>::is_integer); + uint8 bytes[sizeof(T)]; + std::memset(bytes, 0, sizeof(T)); + result = (IO::ReadRaw(f, bytes, sizeof(T)) == sizeof(T)); + T val = 0; + std::memcpy(&val, bytes, sizeof(T)); + v = SwapBytesReturnBE(val); + return result; +} + +template <typename Tfile> +inline bool ReadAdaptiveInt16LE(Tfile & f, uint16 & v) +{ + bool result = true; + uint8 byte = 0; + std::size_t additionalBytes = 0; + v = 0; + byte = 0; + if(!IO::ReadIntLE<uint8>(f, byte)) result = false; + additionalBytes = (byte & 0x01); + v = byte >> 1; + for(std::size_t i = 0; i < additionalBytes; ++i) + { + byte = 0; + if(!IO::ReadIntLE<uint8>(f, byte)) result = false; + v |= (static_cast<uint16>(byte) << (((i+1)*8) - 1)); + } + return result; +} + +template <typename Tfile> +inline bool ReadAdaptiveInt32LE(Tfile & f, uint32 & v) +{ + bool result = true; + uint8 byte = 0; + std::size_t additionalBytes = 0; + v = 0; + byte = 0; + if(!IO::ReadIntLE<uint8>(f, byte)) result = false; + additionalBytes = (byte & 0x03); + v = byte >> 2; + for(std::size_t i = 0; i < additionalBytes; ++i) + { + byte = 0; + if(!IO::ReadIntLE<uint8>(f, byte)) result = false; + v |= (static_cast<uint32>(byte) << (((i+1)*8) - 2)); + } + return result; +} + +template <typename Tfile> +inline bool ReadAdaptiveInt64LE(Tfile & f, uint64 & v) +{ + bool result = true; + uint8 byte = 0; + std::size_t additionalBytes = 0; + v = 0; + byte = 0; + if(!IO::ReadIntLE<uint8>(f, byte)) result = false; + additionalBytes = (1 << (byte & 0x03)) - 1; + v = byte >> 2; + for(std::size_t i = 0; i < additionalBytes; ++i) + { + byte = 0; + if(!IO::ReadIntLE<uint8>(f, byte)) result = false; + v |= (static_cast<uint64>(byte) << (((i+1)*8) - 2)); + } + return result; +} + +template <typename T, typename Tfile> +inline bool WriteIntLE(Tfile & f, const T & v) +{ + STATIC_ASSERT(std::numeric_limits<T>::is_integer); + const T val = SwapBytesReturnLE(v); + uint8 bytes[sizeof(T)]; + std::memcpy(bytes, &val, sizeof(T)); + return IO::WriteRaw(f, bytes, sizeof(T)); +} + +template <typename T, typename Tfile> +inline bool WriteIntBE(Tfile & f, const T & v) +{ + STATIC_ASSERT(std::numeric_limits<T>::is_integer); + const T val = SwapBytesReturnBE(v); + uint8 bytes[sizeof(T)]; + std::memcpy(bytes, &val, sizeof(T)); + return IO::WriteRaw(f, bytes, sizeof(T)); +} + +template <typename Tfile> +inline bool WriteAdaptiveInt16LE(Tfile & f, const uint16 & v, std::size_t minSize = 0, std::size_t maxSize = 0) +{ + ASSERT(minSize == 0 || minSize == 1 || minSize == 2); + ASSERT(maxSize == 0 || maxSize == 1 || maxSize == 2); + ASSERT(maxSize == 0 || maxSize >= minSize); + if(v < 0x80 && minSize <= 1 && (1 <= maxSize || maxSize == 0)) + { + return IO::WriteIntLE<uint8>(f, static_cast<uint8>(v << 1) | 0x00); + } else if(v < 0x8000 && minSize <= 2 && (2 <= maxSize || maxSize == 0)) + { + return IO::WriteIntLE<uint16>(f, static_cast<uint16>(v << 1) | 0x01); + } else + { + ASSERT(false); + return false; + } +} + +template <typename Tfile> +inline bool WriteAdaptiveInt32LE(Tfile & f, const uint32 & v, std::size_t minSize = 0, std::size_t maxSize = 0) +{ + ASSERT(minSize == 0 || minSize == 1 || minSize == 2 || minSize == 3 || minSize == 4); + ASSERT(maxSize == 0 || maxSize == 1 || maxSize == 2 || maxSize == 3 || maxSize == 4); + ASSERT(maxSize == 0 || maxSize >= minSize); + if(v < 0x40 && minSize <= 1 && (1 <= maxSize || maxSize == 0)) + { + return IO::WriteIntLE<uint8>(f, static_cast<uint8>(v << 2) | 0x00); + } else if(v < 0x4000 && minSize <= 2 && (2 <= maxSize || maxSize == 0)) + { + return IO::WriteIntLE<uint16>(f, static_cast<uint16>(v << 2) | 0x01); + } else if(v < 0x400000 && minSize <= 3 && (3 <= maxSize || maxSize == 0)) + { + uint32 value = static_cast<uint32>(v << 2) | 0x02; + uint8 bytes[3]; + bytes[0] = static_cast<uint8>(value >> 0); + bytes[1] = static_cast<uint8>(value >> 8); + bytes[2] = static_cast<uint8>(value >> 16); + return IO::WriteRaw(f, bytes, 3); + } else if(v < 0x40000000 && minSize <= 4 && (4 <= maxSize || maxSize == 0)) + { + return IO::WriteIntLE<uint32>(f, static_cast<uint32>(v << 2) | 0x03); + } else + { + ASSERT(false); + return false; + } +} + +template <typename Tfile> +inline bool WriteAdaptiveInt64LE(Tfile & f, const uint64 & v, std::size_t minSize = 0, std::size_t maxSize = 0) +{ + ASSERT(minSize == 0 || minSize == 1 || minSize == 2 || minSize == 4 || minSize == 8); + ASSERT(maxSize == 0 || maxSize == 1 || maxSize == 2 || maxSize == 4 || maxSize == 8); + ASSERT(maxSize == 0 || maxSize >= minSize); + if(v < 0x40 && minSize <= 1 && (1 <= maxSize || maxSize == 0)) + { + return IO::WriteIntLE<uint8>(f, static_cast<uint8>(v << 2) | 0x00); + } else if(v < 0x4000 && minSize <= 2 && (2 <= maxSize || maxSize == 0)) + { + return IO::WriteIntLE<uint16>(f, static_cast<uint16>(v << 2) | 0x01); + } else if(v < 0x40000000 && minSize <= 4 && (4 <= maxSize || maxSize == 0)) + { + return IO::WriteIntLE<uint32>(f, static_cast<uint32>(v << 2) | 0x02); + } else if(v < 0x4000000000000000ull && minSize <= 8 && (8 <= maxSize || maxSize == 0)) + { + return IO::WriteIntLE<uint64>(f, static_cast<uint64>(v << 2) | 0x03); + } else + { + ASSERT(false); + return false; + } +} + +template <typename T, typename Tfile> +inline bool WriteConvertEndianness(Tfile & f, T & v) +{ + v.ConvertEndianness(); + bool result = IO::WriteRaw(f, reinterpret_cast<const uint8 *>(&v), sizeof(T)); + v.ConvertEndianness(); + return result; +} + +} // namespace IO + +} // namespace mpt + + +OPENMPT_NAMESPACE_END Modified: trunk/OpenMPT/common/serialization_utils.cpp =================================================================== --- trunk/OpenMPT/common/serialization_utils.cpp 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/common/serialization_utils.cpp 2014-09-12 10:22:15 UTC (rev 4279) @@ -50,131 +50,17 @@ return true; } - -static uint8 GetByteReq1248(const uint64 size) -//-------------------------------------------- -{ - if((size >> 6) == 0) return 1; - if((size >> (1*8+6)) == 0) return 2; - if((size >> (3*8+6)) == 0) return 4; - return 8; -} - - -static uint8 GetByteReq1234(const uint32 num) -//------------------------------------------- -{ - if((num >> 6) == 0) return 1; - if((num >> (1*8+6)) == 0) return 2; - if((num >> (2*8+6)) == 0) return 3; - return 4; -} - - -void WriteAdaptive12(std::ostream& oStrm, const uint16 num) -//--------------------------------------------------------- -{ - if(num >> 7 == 0) - Binarywrite<uint16>(oStrm, num << 1, 1); - else - Binarywrite<uint16>(oStrm, (num << 1) | 1); -} - - -void WriteAdaptive1234(std::ostream& oStrm, const uint32 num) -//----------------------------------------------------------- -{ - const uint8 bc = GetByteReq1234(num); - const uint32 sizeInstruction = (num << 2) | (bc - 1); - Binarywrite<uint32>(oStrm, sizeInstruction, bc); -} - - //Format: First bit tells whether the size indicator is 1 or 2 bytes. static void WriteAdaptive12String(std::ostream& oStrm, const std::string& str) //---------------------------------------------------------------------------- { uint16 s = static_cast<uint16>(str.size()); LimitMax(s, uint16(uint16_max / 2)); - WriteAdaptive12(oStrm, s); + mpt::IO::WriteAdaptiveInt16LE(oStrm, s); oStrm.write(str.c_str(), s); } -// Works only for arguments 1,2,4,8 -static uint8 Log2(const uint8& val) -//--------------------------------- -{ - if(val == 1) return 0; - else if(val == 2) return 1; - else if(val == 4) return 2; - else return 3; -} - - -void WriteAdaptive1248(std::ostream& oStrm, const uint64& num) -//------------------------------------------------------------ -{ - const uint8 bc = GetByteReq1248(num); - const uint64 sizeInstruction = (num << 2) | Log2(bc); - Binarywrite<uint64>(oStrm, sizeInstruction, bc); -} - - -void ReadAdaptive12(std::istream& iStrm, uint16& val) -//--------------------------------------------------- -{ - Binaryread<uint16>(iStrm, val, 1); - if(val & 1) - { - uint8 hi = 0; - Binaryread(iStrm, hi); - val &= 0xff; - val |= hi << 8; - } - val >>= 1; -} - - -void ReadAdaptive1234(std::istream& iStrm, uint32& val) -//----------------------------------------------------- -{ - Binaryread<uint32>(iStrm, val, 1); - const uint8 bc = 1 + static_cast<uint8>(val & 3); - uint8 v2 = 0; - uint8 v3 = 0; - uint8 v4 = 0; - if(bc >= 2) Binaryread(iStrm, v2); - if(bc >= 3) Binaryread(iStrm, v3); - if(bc >= 4) Binaryread(iStrm, v4); - val &= 0xff; - val |= (v2 << 8) | (v3 << 16) | (v4 << 24); - val >>= 2; -} - - -void ReadAdaptive1248(std::istream& iStrm, uint64& val) -//----------------------------------------------------- -{ - Binaryread<uint64>(iStrm, val, 1); - uint8 bc = 1 << static_cast<uint8>(val & 3); - int byte = 1; - val &= 0xff; - while(bc > 1) - { - uint8 v = 0; - Binaryread(iStrm, v); - if(byte < 8) - { - val |= uint64(v) << (byte*8); - } - byte++; - bc--; - } - val >>= 2; -} - - void WriteItemString(std::ostream& oStrm, const char* const pStr, const size_t nSize) //-------------------------------------------------------------------------------- { @@ -227,10 +113,11 @@ std::string str; if (IsPrintableId(pId, nLength)) std::copy(pId, pId + nLength, std::back_inserter<std::string>(str)); - else if (nLength <= 4) // Interpret ID as integer value. + else if (nLength <= 8) // Interpret ID as integer value. { - int32 val = 0; - memcpy(&val, pId, nLength); + int64 val = 0; + std::memcpy(&val, pId, nLength); + val = SwapBytesReturnLE(val); str = Stringify(val); } return str; @@ -379,16 +266,16 @@ { AddWriteNote(SNW_CHANGING_IDSIZE_WITH_FIXED_IDSIZESETTING); return; } if (m_nIdbytes == IdSizeVariable) //Variablesize ID? - WriteAdaptive12(mapStream, static_cast<uint16>(nIdSize)); + mpt::IO::WriteAdaptiveInt16LE(mapStream, static_cast<uint16>(nIdSize)); if(nIdSize > 0) mapStream.write(pId, nIdSize); } if (GetFlag(RwfWMapStartPosEntry)) //Startpos - WriteAdaptive1248(mapStream, rposDataStart); + mpt::IO::WriteAdaptiveInt64LE(mapStream, rposDataStart); if (GetFlag(RwfWMapSizeEntry)) //Entrysize - WriteAdaptive1248(mapStream, nDatasize); + mpt::IO::WriteAdaptiveInt64LE(mapStream, nDatasize); if (GetFlag(RwfWMapDescEntry)) //Entry descriptions WriteAdaptive12String(mapStream, std::string(pszDesc)); @@ -457,15 +344,15 @@ const uint8 flags = tempU8; if(flags != s_DefaultFlagbyte) { - WriteAdaptive1234(oStrm, 2); //Headersize - now it is 2. + mpt::IO::WriteAdaptiveInt32LE(oStrm, 2); //Headersize - now it is 2. Binarywrite<uint8>(oStrm, HeaderId_FlagByte); Binarywrite<uint8>(oStrm, flags); } else - WriteAdaptive1234(oStrm, 0); + mpt::IO::WriteAdaptiveInt32LE(oStrm, 0); if(Testbit(header, 4)) // Version(numeric)? - WriteAdaptive1248(oStrm, nVersion); + mpt::IO::WriteAdaptiveInt64LE(oStrm, nVersion); if(Testbit(flags, 0)) // Custom IDbytecount? { @@ -474,7 +361,7 @@ } if(Testbit(flags, 1)) // Fixedsize entries? - WriteAdaptive1234(oStrm, m_nFixedEntrySize); + mpt::IO::WriteAdaptiveInt32LE(oStrm, m_nFixedEntrySize); //Entrycount. Reserve two bytes(max uint16_max / 4 entries), actual value is written after writing data. m_posEntrycount = oStrm.tellp(); @@ -612,7 +499,7 @@ // Read headerdata size uint32 tempU32 = 0; - ReadAdaptive1234(iStrm, tempU32); + mpt::IO::ReadAdaptiveInt32LE(iStrm, tempU32); const uint32 headerdatasize = tempU32; // If headerdatasize != 0, read known headerdata and ignore rest. @@ -631,7 +518,7 @@ // Read version numeric if available. if (Testbit(header, 4)) { - ReadAdaptive1248(iStrm, tempU64); + mpt::IO::ReadAdaptiveInt64LE(iStrm, tempU64); m_nReadVersion = tempU64; if(tempU64 > nVersion) AddReadNote(SNR_LOADING_OBJECT_WITH_LARGER_VERSION); @@ -656,7 +543,7 @@ m_nFixedEntrySize = 0; if(Testbit(flagbyte, 1)) // Fixedsize entries? - ReadAdaptive1234(iStrm, m_nFixedEntrySize); + mpt::IO::ReadAdaptiveInt32LE(iStrm, m_nFixedEntrySize); SetFlag(RwfRMapHasStartpos, Testbit(header, 2)); SetFlag(RwfRMapHasSize, Testbit(header, 3)); @@ -670,7 +557,7 @@ if (Testbit(flagbyte, 2)) // Object description? { uint16 size = 0; - ReadAdaptive12(iStrm, size); + mpt::IO::ReadAdaptiveInt16LE(iStrm, size); iStrm.ignore(size * (GetFlag(RwfRTwoBytesDescChar) ? 2 : 1)); } @@ -678,8 +565,10 @@ iStrm.ignore(5); // Read entrycount - ReadAdaptive1248(iStrm, tempU64); - if(tempU64 > 16000) // FIXME: 16000 appear like a totally arbitrary limit. May be to avoid out-of-memory DoS. + mpt::IO::ReadAdaptiveInt64LE(iStrm, tempU64); + if(tempU64 > 16000) + // The current code can only write 16383 entries because it uses a Adaptive64LE with a fixed size=2 + // Additionally, 16000 is an arbitrary limit to avoid an out-of-memory DoS when caching the map. { AddReadNote(SNR_TOO_MANY_ENTRIES_TO_READ); return; } m_nReadEntrycount = static_cast<NumType>(tempU64); @@ -689,7 +578,7 @@ // Read map rpos if map exists. if (GetFlag(RwfRwHasMap)) { - ReadAdaptive1248(iStrm, tempU64); + mpt::IO::ReadAdaptiveInt64LE(iStrm, tempU64); if(tempU64 > static_cast<uint64>(std::numeric_limits<Offtype>::max())) { AddReadNote(SNR_INSUFFICIENT_STREAM_OFFTYPE); return; } } @@ -735,7 +624,7 @@ // Read ID. uint16 nIdsize = m_nIdbytes; if(nIdsize == IdSizeVariable) //Variablesize ID - ReadAdaptive12(iStrm, nIdsize); + mpt::IO::ReadAdaptiveInt16LE(iStrm, nIdsize); const size_t nOldEnd = m_Idarray.size(); if (nIdsize > 0 && (Util::MaxValueOfType(nOldEnd) - nOldEnd >= nIdsize)) { @@ -749,7 +638,7 @@ if(GetFlag(RwfRMapHasStartpos)) { uint64 tempU64; - ReadAdaptive1248(iStrm, tempU64); + mpt::IO::ReadAdaptiveInt64LE(iStrm, tempU64); if(tempU64 > static_cast<uint64>(std::numeric_limits<Offtype>::max())) { AddReadNote(SNR_INSUFFICIENT_STREAM_OFFTYPE); return; } mapData[i].rposStart = static_cast<RposType>(tempU64); @@ -761,7 +650,7 @@ else if(GetFlag(RwfRMapHasSize)) // Map has datasize field. { uint64 tempU64; - ReadAdaptive1248(iStrm, tempU64); + mpt::IO::ReadAdaptiveInt64LE(iStrm, tempU64); if(tempU64 > static_cast<uint64>(std::numeric_limits<Offtype>::max())) { AddReadNote(SNR_INSUFFICIENT_STREAM_OFFTYPE); return; } mapData[i].nSize = static_cast<DataSize>(tempU64); @@ -775,7 +664,7 @@ if(GetFlag(RwfRMapHasDesc)) //Map has entrydescriptions? { uint16 size = 0; - ReadAdaptive12(iStrm, size); + mpt::IO::ReadAdaptiveInt16LE(iStrm, size); if(GetFlag(RwfRTwoBytesDescChar)) iStrm.ignore(size * 2); else @@ -853,13 +742,18 @@ // Write entry count. oStrm.seekp(m_posEntrycount); - Binarywrite<size_t>(oStrm, (m_nCounter << 2) | 1, 2); + // Write a fixed size=2 Adaptive64LE because space for this value has already been reserved berforehand. + mpt::IO::WriteAdaptiveInt64LE(oStrm, m_nCounter, 2, 2); + if (GetFlag(RwfRwHasMap)) { // Write map start position. oStrm.seekp(m_posMapPosField); const uint64 rposMap = posMapStart - m_posStart; - Binarywrite<uint64>(oStrm, rposMap << 2 | 3); + + // Write a fixed size=8 Adaptive64LE because space for this value has already been reserved berforehand. + mpt::IO::WriteAdaptiveInt64LE(oStrm, rposMap, 8, 8); + } // Seek to end. Modified: trunk/OpenMPT/common/serialization_utils.h =================================================================== --- trunk/OpenMPT/common/serialization_utils.h 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/common/serialization_utils.h 2014-09-12 10:22:15 UTC (rev 4279) @@ -10,6 +10,10 @@ #pragma once +#include "../common/typedefs.h" +#include "../common/mptIO.h" +#include "../common/Endianness.h" + #include <algorithm> #include <bitset> #include <istream> @@ -24,8 +28,6 @@ #include <cstring> -#include "../common/typedefs.h" - OPENMPT_NAMESPACE_BEGIN namespace srlztn //SeRiaLiZaTioN @@ -73,15 +75,6 @@ }; -void ReadAdaptive12(std::istream& iStrm, uint16& val); -void ReadAdaptive1234(std::istream& iStrm, uint32& val); -void ReadAdaptive1248(std::istream& iStrm, uint64& val); - -void WriteAdaptive12(std::ostream& oStrm, const uint16 num); -void WriteAdaptive1234(std::ostream& oStrm, const uint32 num); -void WriteAdaptive1248(std::ostream& oStrm, const uint64& val); - - enum { IdSizeVariable = uint16_max, @@ -126,25 +119,15 @@ inline void Binarywrite(std::ostream& oStrm, const T& data) //--------------------------------------------------------- { - char b[sizeof(T)]; - std::memcpy(b, &data, sizeof(T)); - #ifdef MPT_PLATFORM_BIG_ENDIAN - std::reverse(b, b+sizeof(T)); - #endif - oStrm.write(b, sizeof(T)); + mpt::IO::WriteIntLE(oStrm, data); } -//Write only given number of bytes from the beginning. -template<class T> -inline void Binarywrite(std::ostream& oStrm, const T& data, const std::size_t bytecount) -//-------------------------------------------------------------------------------------- +template<> +inline void Binarywrite(std::ostream& oStrm, const float& data) +//------------------------------------------------------------- { - char b[sizeof(T)]; - std::memcpy(b, &data, sizeof(T)); - #ifdef MPT_PLATFORM_BIG_ENDIAN - std::reverse(b, b+sizeof(T)); - #endif - oStrm.write(b, std::min(bytecount, sizeof(T))); + IEEE754binary32LE tmp = IEEE754binary32LE(data); + mpt::IO::Write(oStrm, tmp); } template <class T> @@ -170,29 +153,24 @@ inline void Binaryread(std::istream& iStrm, T& data) //-------------------------------------------------- { - char b[sizeof(T)]; - iStrm.read(b, sizeof(T)); - #ifdef MPT_PLATFORM_BIG_ENDIAN - std::reverse(b, b+sizeof(T)); - #endif - std::memcpy(&data, b, sizeof(T)); + mpt::IO::ReadIntLE(iStrm, data); } +template<> +inline void Binaryread(std::istream& iStrm, float& data) +//------------------------------------------------------ +{ + IEEE754binary32LE tmp = IEEE754binary32LE(0.0f); + mpt::IO::Read(iStrm, tmp); + data = tmp; +} + //Read only given number of bytes to the beginning of data; data bytes are memset to 0 before reading. template <class T> inline void Binaryread(std::istream& iStrm, T& data, const Offtype bytecount) //--------------------------------------------------------------------------- { - #ifdef HAS_TYPE_TRAITS - static_assert(std::is_trivial<T>::value == true, ""); - #endif - char b[sizeof(T)]; - std::memset(b, 0, sizeof(T)); - iStrm.read(b, std::min(static_cast<std::size_t>(bytecount), sizeof(T))); - #ifdef MPT_PLATFORM_BIG_ENDIAN - std::reverse(b, b+sizeof(T)); - #endif - std::memcpy(&data, b, sizeof(T)); + mpt::IO::ReadBinaryTruncatedLE(iStrm, data, static_cast<std::size_t>(bytecount)); } @@ -209,36 +187,6 @@ Binaryread(iStrm, data, nSize); } -// Read specialization for float. If data size is 8, read double and assign it to given float. -template <> -inline void ReadItem<float>(std::istream& iStrm, float& f, const DataSize nSize) -//------------------------------------------------------------------------------ -{ - if (nSize == 8) - { - double d; - Binaryread(iStrm, d); - f = static_cast<float>(d); - } - else - Binaryread(iStrm, f); -} - -// Read specialization for double. If data size is 4, read float and assign it to given double. -template <> -inline void ReadItem<double>(std::istream& iStrm, double& d, const DataSize nSize) -//-------------------------------------------------------------------------------- -{ - if (nSize == 4) - { - float f; - Binaryread(iStrm, f); - d = f; - } - else - Binaryread(iStrm, d); -} - void ReadItemString(std::istream& iStrm, std::string& str, const DataSize); template <> @@ -259,6 +207,13 @@ public: + SsbStatus GetStatus() const + { + return m_Status; + } + +protected: + // When writing, returns the number of entries written. // When reading, returns the number of entries read not including unrecognized entries. NumType GetCounter() const {return m_nCounter;} @@ -266,13 +221,6 @@ void SetFlag(Rwf flag, bool val) {m_Flags.set(flag, val);} bool GetFlag(Rwf flag) const {return m_Flags[flag];} - SsbStatus GetStatus() const - { - return m_Status; - } - -protected: - // Write given string to log if log func is defined. void AddToLog(const char *psz); Modified: trunk/OpenMPT/common/stdafx.h =================================================================== --- trunk/OpenMPT/common/stdafx.h 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/common/stdafx.h 2014-09-12 10:22:15 UTC (rev 4279) @@ -47,6 +47,7 @@ #include "../common/typedefs.h" // <memory> // <new> +// <type_traits> // if available // <cstdarg> // <cstdint> // <stdint.h> Modified: trunk/OpenMPT/common/typedefs.h =================================================================== --- trunk/OpenMPT/common/typedefs.h 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/common/typedefs.h 2014-09-12 10:22:15 UTC (rev 4279) @@ -421,6 +421,43 @@ +OPENMPT_NAMESPACE_END +#if defined(HAS_TYPE_TRAITS) +#include <type_traits> +#endif +OPENMPT_NAMESPACE_BEGIN + +namespace mpt { + +#if defined(HAS_TYPE_TRAITS) + +typedef std::true_type true_type; +typedef std::false_type false_type; + +#else // !HAS_TYPE_TRAITS + +struct true_type { + typedef true_type type; + typedef bool value_type; + static const value_type value = true; + operator value_type () const { return value; } + value_type operator () () const { return value; } +}; + +struct false_type { + typedef true_type type; + typedef bool value_type; + static const value_type value = false; + operator value_type () const { return value; } + value_type operator () () const { return value; } +}; + +#endif // HAS_TYPE_TRAITS + +} // namespace mpt + + + #if !defined(MPT_USE_WINDOWS_H) // openmpt assumes these type have exact WIN32 semantics @@ -438,7 +475,55 @@ +namespace mpt { +// Tell which types are safe to binary write into files. +// By default, no types are safe. +// When a safe type gets defined, +// also specialize this template so that IO functions will work. +template <typename T> struct is_binary_safe : public mpt::false_type { }; + +// Specialization for byte types. +template <> struct is_binary_safe<char> : public mpt::true_type { }; +template <> struct is_binary_safe<uint8> : public mpt::true_type { }; +template <> struct is_binary_safe<int8> : public mpt::true_type { }; + +template <typename T> +struct GetRawBytesFunctor +{ + inline const uint8 * operator () (const T & v) const + { + STATIC_ASSERT(mpt::is_binary_safe<T>::value); + return reinterpret_cast<const uint8 *>(&v); + } + inline uint8 * operator () (T & v) const + { + STATIC_ASSERT(mpt::is_binary_safe<T>::value); + return reinterpret_cast<uint8 *>(&v); + } +}; + +// In order to be able to partially specialize it, +// GetRawBytes is implemented via a class template. +// Do not overload or specialize GetRawBytes directly. +// Using a wrapper (by default just around a cast to const uint8 *), +// allows for implementing raw memroy access +// via on-demand generating a cached serialized representation. +template <typename T> inline const uint8 * GetRawBytes(const T & v) +{ + STATIC_ASSERT(mpt::is_binary_safe<T>::value); + return mpt::GetRawBytesFunctor<T>()(v); +} +template <typename T> inline uint8 * GetRawBytes(T & v) +{ + STATIC_ASSERT(mpt::is_binary_safe<T>::value); + return mpt::GetRawBytesFunctor<T>()(v); +} + +} // namespace mpt + + + #if MPT_COMPILER_GCC || MPT_COMPILER_CLANG #define MPT_PRINTF_FUNC(formatstringindex,varargsindex) __attribute__((format(printf, formatstringindex, varargsindex))) #else Modified: trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj 2014-09-12 10:22:15 UTC (rev 4279) @@ -185,6 +185,7 @@ <ClInclude Include="..\common\misc_util.h" /> <ClInclude Include="..\common\mptAtomic.h" /> <ClInclude Include="..\common\mptFstream.h" /> + <ClInclude Include="..\common\mptIO.h" /> <ClInclude Include="..\common\mptPathString.h" /> <ClInclude Include="..\common\mptString.h" /> <ClInclude Include="..\common\mutex.h" /> Modified: trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/libopenmpt/libopenmpt.vcxproj.filters 2014-09-12 10:22:15 UTC (rev 4279) @@ -263,6 +263,9 @@ <ClInclude Include="..\common\mptAtomic.h"> <Filter>Header Files\common</Filter> </ClInclude> + <ClInclude Include="..\common\mptIO.h"> + <Filter>Header Files\common</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\common\AudioCriticalSection.cpp"> Modified: trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj 2014-09-12 10:22:15 UTC (rev 4279) @@ -193,6 +193,7 @@ <ClInclude Include="..\common\misc_util.h" /> <ClInclude Include="..\common\mptAtomic.h" /> <ClInclude Include="..\common\mptFstream.h" /> + <ClInclude Include="..\common\mptIO.h" /> <ClInclude Include="..\common\mptPathString.h" /> <ClInclude Include="..\common\mptString.h" /> <ClInclude Include="..\common\mutex.h" /> Modified: trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/libopenmpt/libopenmptDLL.vcxproj.filters 2014-09-12 10:22:15 UTC (rev 4279) @@ -269,6 +269,9 @@ <ClInclude Include="..\common\mptAtomic.h"> <Filter>Header Files\common</Filter> </ClInclude> + <ClInclude Include="..\common\mptIO.h"> + <Filter>Header Files\common</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\common\AudioCriticalSection.cpp"> Modified: trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj 2014-09-12 10:22:15 UTC (rev 4279) @@ -189,6 +189,7 @@ <ClInclude Include="..\common\misc_util.h" /> <ClInclude Include="..\common\mptAtomic.h" /> <ClInclude Include="..\common\mptFstream.h" /> + <ClInclude Include="..\common\mptIO.h" /> <ClInclude Include="..\common\mptPathString.h" /> <ClInclude Include="..\common\mptString.h" /> <ClInclude Include="..\common\mutex.h" /> Modified: trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/libopenmpt/libopenmpt_test.vcxproj.filters 2014-09-12 10:22:15 UTC (rev 4279) @@ -263,6 +263,9 @@ <ClInclude Include="..\common\mptAtomic.h"> <Filter>Header Files\common</Filter> </ClInclude> + <ClInclude Include="..\common\mptIO.h"> + <Filter>Header Files\common</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\common\AudioCriticalSection.cpp"> Modified: trunk/OpenMPT/mptrack/mptrack_08.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_08.vcproj 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/mptrack/mptrack_08.vcproj 2014-09-12 10:22:15 UTC (rev 4279) @@ -1346,6 +1346,10 @@ > </File> <File + RelativePath="..\common\mptIO.h" + > + </File> + <File RelativePath="..\common\mptPathString.h" > </File> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2014-09-12 10:22:15 UTC (rev 4279) @@ -649,6 +649,7 @@ <ClInclude Include="..\common\misc_util.h" /> <ClInclude Include="..\common\mptAtomic.h" /> <ClInclude Include="..\common\mptFstream.h" /> + <ClInclude Include="..\common\mptIO.h" /> <ClInclude Include="..\common\mptPathString.h" /> <ClInclude Include="..\common\mptString.h" /> <ClInclude Include="..\common\mutex.h" /> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2014-09-12 10:22:15 UTC (rev 4279) @@ -1023,6 +1023,9 @@ <ClInclude Include="..\common\WriteMemoryDump.h"> <Filter>Header Files\common</Filter> </ClInclude> + <ClInclude Include="..\common\mptIO.h"> + <Filter>Header Files\common</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <None Include="res\bitmap1.bmp"> Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2014-09-12 10:22:15 UTC (rev 4279) @@ -16,6 +16,7 @@ #include "../mptrack/moddoc.h" #include "../mptrack/TrackerSettings.h" #endif +#include "../common/mptIO.h" #include "../common/serialization_utils.h" #include "../common/mptFstream.h" #include <sstream> @@ -109,7 +110,7 @@ else //Case: Using original IT tuning. srlztn::StringToBinaryStream<uint8>(oStrm, "->MPT_ORIGINAL_IT<-"); - srlztn::Binarywrite<uint16>(oStrm, iter->second); + mpt::IO::WriteIntLE<uint16>(oStrm, iter->second); } //Writing tuning data for instruments. @@ -121,7 +122,7 @@ sf.AddToLog("Error: 210807_1"); return; } - srlztn::Binarywrite(oStrm, iter->second); + mpt::IO::WriteIntLE<uint16>(oStrm, iter->second); } } } @@ -1269,9 +1270,18 @@ itHeader.ConvertEndianness(); Order.WriteAsByte(f, itHeader.ordnum); - if(itHeader.insnum) fwrite(&inspos[0], 4, itHeader.insnum, f); - if(itHeader.smpnum) fwrite(&smppos[0], 4, itHeader.smpnum, f); - if(itHeader.patnum) fwrite(&patpos[0], 4, itHeader.patnum, f); + for(uint16 i = 0; i < itHeader.insnum; ++i) + { + mpt::IO::WriteIntLE<uint32>(f, inspos[i]); + } + for(uint16 i = 0; i < itHeader.smpnum; ++i) + { + mpt::IO::WriteIntLE<uint32>(f, smppos[i]); + } + for(uint16 i = 0; i < itHeader.patnum; ++i) + { + mpt::IO::WriteIntLE<uint32>(f, patpos[i]); + } // Writing edit history information SaveITEditHistory(this, f); @@ -1288,8 +1298,7 @@ char magic[4]; memcpy(magic, "PNAM", 4); fwrite(magic, 4, 1, f); - uint32 d = numNamedPats * MAX_PATTERNNAME; - fwrite(&d, 4, 1, f); + mpt::IO::WriteIntLE<uint32>(f, numNamedPats * MAX_PATTERNNAME); for(PATTERNINDEX nPat = 0; nPat < numNamedPats; nPat++) { @@ -1306,7 +1315,7 @@ char magic[4]; memcpy(magic, "CNAM", 4); fwrite(magic, 4, 1, f); - fwrite(&dwChnNamLen, 1, 4, f); + mpt::IO::WriteIntLE<uint32>(f, dwChnNamLen); UINT nChnNames = dwChnNamLen / MAX_CHANNELNAME; for(UINT inam = 0; inam < nChnNames; inam++) { @@ -1590,9 +1599,18 @@ // Updating offsets fseek(f, dwHdrPos, SEEK_SET); - if(itHeader.insnum) fwrite(&inspos[0], 4, itHeader.insnum, f); - if(itHeader.smpnum) fwrite(&smppos[0], 4, itHeader.smpnum, f); - if(itHeader.patnum) fwrite(&patpos[0], 4, itHeader.patnum, f); + for(uint16 i = 0; i < itHeader.insnum; ++i) + { + mpt::IO::WriteIntLE<uint32>(f, inspos[i]); + } + for(uint16 i = 0; i < itHeader.smpnum; ++i) + { + mpt::IO::WriteIntLE<uint32>(f, smppos[i]); + } + for(uint16 i = 0; i < itHeader.patnum; ++i) + { + mpt::IO::WriteIntLE<uint32>(f, patpos[i]); + } if(GetType() == MOD_TYPE_IT) { @@ -1656,7 +1674,7 @@ fout.clear(); success = false; } - fout.write(reinterpret_cast<const char*>(&MPTStartPos), sizeof(MPTStartPos)); + mpt::IO::WriteIntLE<uint32>(fout, MPTStartPos); fout.flush(); #if MPT_COMPILER_MSVC @@ -1708,7 +1726,7 @@ } // rewbs.modularPlugData - DWORD MPTxPlugDataSize = 4 + (sizeof(m_MixPlugins[i].fDryRatio)) + // 4 for ID and size of dryRatio + DWORD MPTxPlugDataSize = 4 + (sizeof(m_MixPlugins[i].fDryRatio)) + //4 for ID and size of dryRatio 4 + (sizeof(m_MixPlugins[i].defaultProgram)) + // rewbs.plugDefaultProgram 4 + 3 * sizeof(int32); // Editor data // for each extra entity, add 4 for ID, plus size of entity, plus optionally 4 for size of entity. @@ -1725,30 +1743,31 @@ fwrite(id, 1, 4, f); // write plugin size: - fwrite(&nPluginSize, 1, 4, f); - fwrite(&plugin.Info, 1, sizeof(SNDMIXPLUGININFO), f); - fwrite(&m_MixPlugins[i].nPluginDataSize, 1, 4, f); + mpt::IO::WriteIntLE<uint32>(f, nPluginSize); + SNDMIXPLUGININFO tmpPluginInfo = m_MixPlugins[i].Info; + tmpPluginInfo.ConvertEndianness(); + fwrite(&tmpPluginInfo, 1, sizeof(SNDMIXPLUGININFO), f); + mpt::IO::WriteIntLE<uint32>(f, m_MixPlugins[i].nPluginDataSize); if(m_MixPlugins[i].pPluginData) { fwrite(m_MixPlugins[i].pPluginData, 1, m_MixPlugins[i].nPluginDataSize, f); } - fwrite(&MPTxPlugDataSize, 1, 4, f); + mpt::IO::WriteIntLE<uint32>(f, MPTxPlugDataSize); // Dry/Wet ratio memcpy(id, "DWRT", 4); fwrite(id, 1, 4, f); - uint32 ratio = IEEE754binary32LE(m_MixPlugins[i].fDryRatio).GetInt32(); - fwrite(&ratio, 1, sizeof(uint32), f); + // DWRT chunk does not include a size, so better make sure we always write 4 bytes here. + STATIC_ASSERT(sizeof(IEEE754binary32LE) == 4); + mpt::IO::Write(f, IEEE754binary32LE(m_MixPlugins[i].fDryRatio)); // Default program memcpy(id, "PROG", 4); fwrite(id, 1, 4, f); // PROG chunk does not include a size, so better make sure we always write 4 bytes here. STATIC_ASSERT(sizeof(m_MixPlugins[i].defaultProgram) == sizeof(int32)); - int32 prog = m_MixPlugins[i].defaultProgram; - SwapBytesLE(prog); - fwrite(&prog, 1, sizeof(int32), f); + mpt::IO::WriteIntLE<int32>(f, m_MixPlugins[i].defaultProgram); // Editor window parameters memcpy(id, "EWND", 4); @@ -1783,9 +1802,11 @@ { memcpy(id, "CHFX", 4); fwrite(id, 1, 4, f); - nPluginSize = nChInfo * 4; - fwrite(&nPluginSize, 1, 4, f); - fwrite(chinfo, 1, nPluginSize, f); + mpt::IO::WriteIntLE<uint32>(f, nChInfo * 4); + for(uint32 i = 0; i < nChInfo; ++i) + { + mpt::IO::WriteIntLE<uint32>(f, chinfo[i]); + } } nTotalSize += nChInfo * 4 + 8; } @@ -1912,7 +1933,7 @@ //--------------------------------------------------------------------------------- { uint32 code = MAGIC4BE('M','P','T','X'); // write extension header code - fwrite(&code, 1, sizeof(uint32), f); + mpt::IO::WriteIntLE<uint32>(f, code); if (nInstruments == 0) return; @@ -1974,8 +1995,8 @@ void CSoundFile::WriteInstrumentPropertyForAllInstruments(uint32 code, int16 size, FILE* f, UINT nInstruments) const //------------------------------------------------------------------------------------------------------------------ { - fwrite(&code, 1, sizeof(uint32), f); //write code - fwrite(&size, 1, sizeof(int16), f); //write size + mpt::IO::WriteIntLE<uint32>(f, code); //write code + mpt::IO::WriteIntLE<int16>(f, size); //write size for(UINT nins=1; nins<=nInstruments; nins++) //for all instruments... { if (Instruments[nins]) @@ -1998,16 +2019,16 @@ #define WRITEMODULARHEADER(c1, c2, c3, c4, fsize) \ { \ - const uint32 code = SwapBytesReturnLE(MAGIC4BE(c1, c2, c3, c4)); \ - fwrite(&code, 1, sizeof(code), f); \ - ASSERT(fsize <= uint16_max); \ - const uint16 size = SwapBytesReturnLE(static_cast<uint16>(fsize)); \ - fwrite(&size, 1, sizeof(size), f); \ + const uint32 code = MAGIC4BE(c1, c2, c3, c4); \ + mpt::IO::WriteIntLE<uint32>(f, code); \ + ASSERT(fsize <= uint16_max); \ + const uint16 size = fsize; \ + mpt::IO::WriteIntLE<uint16>(f, size); \ } #define WRITEMODULAR(c1, c2, c3, c4, field) \ { \ WRITEMODULARHEADER(c1, c2, c3, c4, sizeof(field)) \ - fwrite(&(field), 1, sizeof(field), f); \ + mpt::IO::WriteIntLE(f, field); \ } if(m_nDefaultTempo > 255) @@ -2068,7 +2089,7 @@ //Additional flags for XM/IT/MPTM if(m_ModFlags) { - WRITEMODULAR('M','S','F','.', m_ModFlags); + WRITEMODULAR('M','S','F','.', m_ModFlags.GetRaw()); } #ifdef MODPLUG_TRACKER @@ -2287,8 +2308,7 @@ //write modular data's total size long curPos = ftell(f); // remember current pos fseek(f, sizePos, SEEK_SET); // go back to sizePos - SwapBytesLE(modularInstSize); - fwrite(&modularInstSize, 1, sizeof(modularInstSize), f); // write data + mpt::IO::WriteIntLE<uint32>(f, modularInstSize); // write data fseek(f, curPos, SEEK_SET); // go back to where we were. // Compute the size that we just wasted. Modified: trunk/OpenMPT/soundlib/ModSequence.cpp =================================================================== --- trunk/OpenMPT/soundlib/ModSequence.cpp 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/soundlib/ModSequence.cpp 2014-09-12 10:22:15 UTC (rev 4279) @@ -778,7 +778,7 @@ //----------------------------------------------------------------------------- { uint16 size; - srlztn::Binaryread<uint16>(iStrm, size); + mpt::IO::ReadIntLE<uint16>(iStrm, size); if(size > ModSpecs::mptm.ordersMax) { seq.m_sndFile.AddToLog(mpt::String::Print(str_SequenceTruncationNote, size, ModSpecs::mptm.ordersMax)); @@ -791,7 +791,7 @@ for(size_t i = 0; i < size; i++) { uint16 temp; - srlztn::Binaryread<uint16>(iStrm, temp); + mpt::IO::ReadIntLE<uint16>(iStrm, temp); seq[i] = temp; } } @@ -801,12 +801,12 @@ //---------------------------------------------------------------------- { const uint16 size = seq.GetLength(); - srlztn::Binarywrite<uint16>(oStrm, size); + mpt::IO::WriteIntLE<uint16>(oStrm, size); const ModSequenceSet::const_iterator endIter = seq.end(); for(ModSequenceSet::const_iterator citer = seq.begin(); citer != endIter; citer++) { const uint16 temp = static_cast<uint16>(*citer); - srlztn::Binarywrite<uint16>(oStrm, temp); + mpt::IO::WriteIntLE<uint16>(oStrm, temp); } } Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2014-09-12 10:22:15 UTC (rev 4279) @@ -18,6 +18,7 @@ #endif // MODPLUG_TRACKER #include "../common/version.h" #include "../common/AudioCriticalSection.h" +#include "../common/mptIO.h" #include "../common/serialization_utils.h" #include "Sndfile.h" #include "tuningcollection.h" @@ -189,8 +190,8 @@ fsize = sizeof( type );\ if(only_this_code == Util::MaxValueOfType(only_this_code)) \ { \ - fwrite(& fcode , 1 , sizeof( uint32 ) , file);\ - fwrite(& fsize , 1 , sizeof( int16 ) , file);\ + mpt::IO::WriteIntLE<uint32>(file, fcode); \ + mpt::IO::WriteIntLE<int16>(file, fsize); \ } else if(only_this_code == fcode)\ { \ ASSERT(fixedsize == fsize); \ @@ -212,8 +213,8 @@ fsize = sizeof( type );\ if(only_this_code == Util::MaxValueOfType(only_this_code)) \ { \ - fwrite(& fcode , 1 , sizeof( uint32 ) , file);\ - fwrite(& fsize , 1 , sizeof( int16 ) , file);\ + mpt::IO::WriteIntLE<uint32>(file, fcode); \ + mpt::IO::WriteIntLE<int16>(file, fsize); \ type tmp = (type)(input-> name ); \ tmp = SwapBytesReturnLE(tmp); \ fwrite(&tmp , 1 , fsize , file); \ @@ -247,8 +248,8 @@ fsize = sizeof( type ) * arraysize;\ if(only_this_code == Util::MaxValueOfType(only_this_code)) \ { \ - fwrite(& fcode , 1 , sizeof( uint32 ) , file);\ - fwrite(& fsize , 1 , sizeof( int16 ) , file);\ + mpt::IO::WriteIntLE<uint32>(file, fcode); \ + mpt::IO::WriteIntLE<int16>(file, fsize); \ } else if(only_this_code == fcode)\ { \ /* ASSERT(fixedsize <= fsize); */ \ @@ -311,8 +312,8 @@ fsize = sizeof(dwFlags); if(!only_this_code) { - fwrite(&fcode, 1, sizeof(int32), file); - fwrite(&fsize, 1, sizeof(int16), file); + mpt::IO::WriteIntLE<int32>(file, fcode); + mpt::IO::WriteIntLE<int16>(file, fsize); } dwFlags = SwapBytesReturnLE(dwFlags); fwrite(&dwFlags, 1, fsize, file); Modified: trunk/OpenMPT/soundlib/pattern.cpp =================================================================== --- trunk/OpenMPT/soundlib/pattern.cpp 2014-09-12 01:06:27 UTC (rev 4278) +++ trunk/OpenMPT/soundlib/pattern.cpp 2014-09-12 10:22:15 UTC (rev 4279) @@ -532,8 +532,6 @@ return mask; } -using srlztn::Binarywrite; -using srlztn::Binaryread; // Writes pattern data. Adapted from SaveIT. void WriteData(std::ostream& oStrm, const CPattern& pat) @@ -560,21 +558,21 @@ if(diffmask != 0) chval |= IT_bitmask_patternChanEnabled_c; ... [truncated message content] |
From: <man...@us...> - 2014-09-12 11:26:41
|
Revision: 4285 http://sourceforge.net/p/modplug/code/4285 Author: manxorist Date: 2014-09-12 11:26:26 +0000 (Fri, 12 Sep 2014) Log Message: ----------- [Ref] serialization_utils: In order to improve code readability, replace open-coded (const char*, size) tuples for Id fields with a class ID which is just a small wrapper around std::string. As IDs are really short (most of the time 4 bytes), std::string usage is fine as small-string-optimization avoids further allocations. Modified Paths: -------------- trunk/OpenMPT/common/serialization_utils.cpp trunk/OpenMPT/common/serialization_utils.h trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/ModSequence.cpp trunk/OpenMPT/soundlib/pattern.cpp trunk/OpenMPT/soundlib/patternContainer.cpp trunk/OpenMPT/soundlib/tuning.cpp trunk/OpenMPT/soundlib/tuningCollection.cpp Modified: trunk/OpenMPT/common/serialization_utils.cpp =================================================================== --- trunk/OpenMPT/common/serialization_utils.cpp 2014-09-12 11:03:26 UTC (rev 4284) +++ trunk/OpenMPT/common/serialization_utils.cpp 2014-09-12 11:26:26 UTC (rev 4285) @@ -39,17 +39,20 @@ } -static bool IsPrintableId(const char* pId, const size_t nLength) -//-------------------------------------------------------------- +bool ID::IsPrintable() const +//-------------------------- { - for(size_t i = 0; i < nLength; i++) + for(std::size_t i = 0; i < m_ID.length(); ++i) { - if (pId[i] <= 0 || isprint(pId[i]) == 0) + if(m_ID[i] <= 0 || isprint(m_ID[i]) == 0) + { return false; + } } return true; } + //Format: First bit tells whether the size indicator is 1 or 2 bytes. static void WriteAdaptive12String(std::ostream& oStrm, const std::string& str) //---------------------------------------------------------------------------- @@ -104,25 +107,30 @@ } -static std::string IdToString(const char* const pvId, const size_t nLength) -//------------------------------------------------------------------------- +std::string ID::AsString() const +//------------------------------ { - const char* pId = static_cast<const char*>(pvId); - if (nLength == 0) - return ""; - std::string str; - if (IsPrintableId(pId, nLength)) - std::copy(pId, pId + nLength, std::back_inserter<std::string>(str)); - else if (nLength <= 8) // Interpret ID as integer value. + if(IsPrintable()) { - int64 val = 0; - std::memcpy(&val, pId, nLength); - val = SwapBytesReturnLE(val); - str = Stringify(val); + return m_ID; } - return str; + if(m_ID.length() > 8) + { + return std::string(); + } + uint64 val = 0; + uint8 bytes[8]; + std::memset(bytes, 0, 8); + for(std::size_t i = 0; i < m_ID.length(); ++i) + { + bytes[i] = m_ID[i]; + } + std::memcpy(&val, bytes, m_ID.length()); + val = SwapBytesReturnLE(val); + return mpt::ToString(val); } + const char Ssb::s_EntryID[3] = {'2','2','8'}; const char tstrWriteHeader[] = "Write header with ID = %s\n"; @@ -214,7 +222,7 @@ m_fpLogFunc( tstrReadProgress, nNum, - (pRe && pRe->nIdLength < 30 && m_Idarray.size() > 0) ? IdToString(&m_Idarray[pRe->nIdpos], pRe->nIdLength).c_str() : "", + (pRe && pRe->nIdLength < 30 && m_Idarray.size() > 0) ? ID(&m_Idarray[pRe->nIdpos], pRe->nIdLength).AsString().c_str() : "", (pRe) ? pRe->rposStart : 0, (pRe && pRe->nSize != invalidDatasize) ? Stringify(pRe->nSize).c_str() : "", ""); @@ -223,14 +231,14 @@ // Called after writing an entry. -void SsbWrite::AddWriteNote(const char* pId, const size_t nIdSize, const NumType nEntryNum, const DataSize nBytecount, const RposType rposStart) -//---------------------------------------------------------------------------- +void SsbWrite::AddWriteNote(const ID &id, const NumType nEntryNum, const DataSize nBytecount, const RposType rposStart) +//--------------------------------------------------------------------------------------------------------------------- { m_Status |= SNT_PROGRESS; if (m_fpLogFunc) { { - m_fpLogFunc(tstrWriteProgress, nEntryNum, IdToString(pId, nIdSize).c_str(), rposStart, nBytecount); + m_fpLogFunc(tstrWriteProgress, nEntryNum, id.AsString().c_str(), rposStart, nBytecount); } } } @@ -245,16 +253,15 @@ } -void SsbWrite::WriteMapItem( const char* pId, - const size_t nIdSize, +void SsbWrite::WriteMapItem(const ID &id, const RposType& rposDataStart, const DataSize& nDatasize, const char* pszDesc) -//---------------------------------------------- +//---------------------------------------- { if (m_fpLogFunc) m_fpLogFunc(tstrMapEntryWrite, - (nIdSize > 0) ? IdToString(pId, nIdSize).c_str() : "", + (id.GetSize() > 0) ? id.AsString().c_str() : "", rposDataStart, nDatasize); @@ -262,14 +269,14 @@ if(m_nIdbytes > 0) { - if (m_nIdbytes != IdSizeVariable && nIdSize != m_nIdbytes) + if (m_nIdbytes != IdSizeVariable && id.GetSize() != m_nIdbytes) { AddWriteNote(SNW_CHANGING_IDSIZE_WITH_FIXED_IDSIZESETTING); return; } if (m_nIdbytes == IdSizeVariable) //Variablesize ID? - mpt::IO::WriteAdaptiveInt16LE(mapStream, static_cast<uint16>(nIdSize)); + mpt::IO::WriteAdaptiveInt16LE(mapStream, static_cast<uint16>(id.GetSize())); - if(nIdSize > 0) - mapStream.write(pId, nIdSize); + if(id.GetSize() > 0) + mapStream.write(id.GetBytes(), id.GetSize()); } if (GetFlag(RwfWMapStartPosEntry)) //Startpos @@ -296,13 +303,13 @@ } -void SsbWrite::BeginWrite(const char* pId, const size_t nIdSize, const uint64& nVersion) -//--------------------------------------------------------------------------------- +void SsbWrite::BeginWrite(const ID &id, const uint64& nVersion) +//------------------------------------------------------------- { std::ostream& oStrm = *m_pOstrm; if (m_fpLogFunc) - m_fpLogFunc(tstrWriteHeader, IdToString(pId, nIdSize).c_str()); + m_fpLogFunc(tstrWriteHeader, id.AsString().c_str()); ResetWritestatus(); @@ -316,9 +323,9 @@ // Object ID. { - uint8 idsize = static_cast<uint8>(nIdSize); + uint8 idsize = static_cast<uint8>(id.GetSize()); Binarywrite<uint8>(oStrm, idsize); - if(idsize > 0) oStrm.write(pId, nIdSize); + if(idsize > 0) oStrm.write(id.GetBytes(), id.GetSize()); } // Form header. @@ -375,8 +382,8 @@ } -SsbRead::ReadRv SsbRead::OnReadEntry(const ReadEntry* pE, const char* pId, const size_t nIdSize, const Postype& posReadBegin) -//------------------------------------------------------------------------------------------------------------------- +SsbRead::ReadRv SsbRead::OnReadEntry(const ReadEntry* pE, const ID &id, const Postype& posReadBegin) +//-------------------------------------------------------------------------------------------------- { if (pE != nullptr) AddReadNote(pE, m_nCounter); @@ -390,7 +397,7 @@ else // Entry not found. { if (m_fpLogFunc) - m_fpLogFunc(tstrNoEntryFound, IdToString(pId, nIdSize).c_str()); + m_fpLogFunc(tstrNoEntryFound, id.AsString().c_str()); return EntryNotFound; } m_nCounter++; @@ -398,8 +405,8 @@ } -void SsbWrite::OnWroteItem(const char* pId, const size_t nIdSize, const Postype& posBeforeWrite) -//----------------------------------------------------------------------------------------- +void SsbWrite::OnWroteItem(const ID &id, const Postype& posBeforeWrite) +//--------------------------------------------------------------------- { const Offtype nRawEntrySize = m_pOstrm->tellp() - posBeforeWrite; @@ -424,37 +431,21 @@ { AddWriteNote(SNW_INSUFFICIENT_FIXEDSIZE); return; } } if (GetFlag(RwfRwHasMap)) - WriteMapItem(pId, nIdSize, static_cast<RposType>(posBeforeWrite - m_posStart), nEntrySize, ""); + WriteMapItem(id, static_cast<RposType>(posBeforeWrite - m_posStart), nEntrySize, ""); if (m_fpLogFunc != nullptr) - AddWriteNote(pId, nIdSize, m_nCounter, nEntrySize, static_cast<RposType>(posBeforeWrite - m_posStart)); + AddWriteNote(id, m_nCounter, nEntrySize, static_cast<RposType>(posBeforeWrite - m_posStart)); IncrementWriteCounter(); } -void SsbRead::CompareId(std::istream& iStrm, const char* pId, const size_t nIdlength) -//--------------------------------------------------------------------------- +void SsbRead::BeginRead(const ID &id, const uint64& nVersion) +//----------------------------------------------------------- { - uint8 tempU8 = 0; - Binaryread<uint8>(iStrm, tempU8); - char buffer[256]; - if(tempU8) - iStrm.read(buffer, tempU8); - - if (tempU8 == nIdlength && nIdlength > 0 && memcmp(buffer, pId, nIdlength) == 0) - return; // Match. - - AddReadNote(SNR_OBJECTCLASS_IDMISMATCH); -} - - -void SsbRead::BeginRead(const char* pId, const size_t nLength, const uint64& nVersion) -//--------------------------------------------------------------------------------- -{ std::istream& iStrm = *m_pIstrm; if (m_fpLogFunc) - m_fpLogFunc(tstrReadingHeader, IdToString(pId, nLength).c_str()); + m_fpLogFunc(tstrReadingHeader, id.AsString().c_str()); ResetReadstatus(); @@ -467,7 +458,7 @@ { char temp[sizeof(s_EntryID)]; ArrayReader<char>(sizeof(s_EntryID))(iStrm, temp, sizeof(s_EntryID)); - if (memcmp(temp, s_EntryID, sizeof(s_EntryID))) + if(std::memcmp(temp, s_EntryID, sizeof(s_EntryID))) { AddReadNote(SNR_STARTBYTE_MISMATCH); return; @@ -475,7 +466,18 @@ } // Compare IDs. - CompareId(iStrm, pId, nLength); + uint8 storedIdLen = 0; + Binaryread<uint8>(iStrm, storedIdLen); + char storedIdBuf[256]; + MemsetZero(storedIdBuf); + if(storedIdLen > 0) + { + iStrm.read(storedIdBuf, storedIdLen); + } + if(!(id == ID(storedIdBuf, storedIdLen))) + { + AddReadNote(SNR_OBJECTCLASS_IDMISMATCH); + } if ((m_Status & SNT_FAILURE) != 0) { if (m_fpLogFunc) @@ -689,8 +691,8 @@ } -const ReadEntry* SsbRead::Find(const char* pId, const size_t nIdLength) -//----------------------------------------------------------------- +const ReadEntry* SsbRead::Find(const ID &id) +//------------------------------------------ { m_pIstrm->clear(); if (GetFlag(RwfRMapCached) == false) @@ -705,8 +707,7 @@ for(size_t i0 = 0; i0 < nEntries; i0++) { const size_t i = (i0 + m_nNextReadHint) % nEntries; - if (mapData[i].nIdLength == nIdLength && mapData[i].nIdpos < m_Idarray.size() && - memcmp(&m_Idarray[mapData[i].nIdpos], pId, mapData[i].nIdLength) == 0) + if(mapData[i].nIdpos < m_Idarray.size() && id == ID(&m_Idarray[mapData[i].nIdpos], mapData[i].nIdLength)) { m_nNextReadHint = (i + 1) % nEntries; if (mapData[i].rposStart != 0) Modified: trunk/OpenMPT/common/serialization_utils.h =================================================================== --- trunk/OpenMPT/common/serialization_utils.h 2014-09-12 11:03:26 UTC (rev 4284) +++ trunk/OpenMPT/common/serialization_utils.h 2014-09-12 11:26:26 UTC (rev 4285) @@ -197,6 +197,37 @@ +class ID +{ +private: + std::string m_ID; // NOTE: can contain null characters ('\0') +public: + ID() { } + ID(const std::string &id) : m_ID(id) { } + ID(const char *beg, const char *end) : m_ID(beg, end) { } + ID(const char *id) : m_ID(id?id:"") { } + ID(const char * str, std::size_t len) : m_ID(str, str + len) { } + template <typename T> + static ID FromInt(const T &val) + { + STATIC_ASSERT(std::numeric_limits<T>::is_integer); + char bytes[sizeof(T)]; + std::memcpy(bytes, &val, sizeof(T)); + #ifdef MPT_PLATFORM_BIG_ENDIAN + std::reverse(bytes, bytes + sizeof(T)); + #endif + return ID(bytes, bytes + sizeof(T)); + } + bool IsPrintable() const; + std::string AsString() const; + const char *GetBytes() const { return m_ID.c_str(); } + std::size_t GetSize() const { return m_ID.length(); } + bool operator == (const ID &other) const { return m_ID == other.m_ID; } + bool operator != (const ID &other) const { return m_ID != other.m_ID; } +}; + + + class Ssb { @@ -267,8 +298,7 @@ SsbRead(std::istream& iStrm); // Call this to begin reading: must be called before other read functions. - void BeginRead(const char* pId, const size_t nLength, const uint64& nVersion); - void BeginRead(const char* pszId, const uint64& nVersion) {return BeginRead(pszId, std::strlen(pszId), nVersion);} + void BeginRead(const ID &id, const uint64& nVersion); // After calling BeginRead(), this returns number of entries in the file. NumType GetNumEntries() const {return m_nReadEntrycount;} @@ -282,43 +312,35 @@ ReadIterator GetReadEnd(); // Compares given id with read entry id - IdMatchStatus CompareId(const ReadIterator& iter, const char* pszId) {return CompareId(iter, pszId, std::strlen(pszId));} - IdMatchStatus CompareId(const ReadIterator& iter, const char* pId, const size_t nIdSize); + IdMatchStatus CompareId(const ReadIterator& iter, const ID &id); uint64 GetReadVersion() {return m_nReadVersion;} // Read item using default read implementation. template <class T> - ReadRv ReadItem(T& obj, const char* pszId) {return ReadItem(obj, pszId, std::strlen(pszId), srlztn::ReadItem<T>);} + ReadRv ReadItem(T& obj, const ID &id) {return ReadItem(obj, id, srlztn::ReadItem<T>);} - template <class T> - ReadRv ReadItem(T& obj, const char* pId, const size_t nIdSize) {return ReadItem(obj, pId, nIdSize, srlztn::ReadItem<T>);} - // Read item using given function. template <class T, class FuncObj> - ReadRv ReadItem(T& obj, const char* pId, const size_t nIdSize, FuncObj); + ReadRv ReadItem(T& obj, const ID &id, FuncObj); // Read item using read iterator. template <class T> - ReadRv ReadItem(const ReadIterator& iter, T& obj) {return ReadItem(iter, obj, srlztn::ReadItem<T>);} + ReadRv ReadIterItem(const ReadIterator& iter, T& obj) {return ReadIterItem(iter, obj, srlztn::ReadItem<T>);} template <class T, class FuncObj> - ReadRv ReadItem(const ReadIterator& iter, T& obj, FuncObj func); + ReadRv ReadIterItem(const ReadIterator& iter, T& obj, FuncObj func); private: // Reads map to cache. void CacheMap(); - // Compares ID in file with expected ID. - void CompareId(std::istream& iStrm, const char* pId, const size_t nLength); - // Searches for entry with given ID. If found, returns pointer to corresponding entry, else // returns nullptr. - const ReadEntry* Find(const char* pId, const size_t nLength); - const ReadEntry* Find(const char* pszId) {return Find(pszId, std::strlen(pszId));} + const ReadEntry* Find(const ID &id); // Called after reading an object. - ReadRv OnReadEntry(const ReadEntry* pE, const char* pId, const size_t nIdSize, const Postype& posReadBegin); + ReadRv OnReadEntry(const ReadEntry* pE, const ID &id, const Postype& posReadBegin); void AddReadNote(const SsbStatus s); @@ -356,19 +378,15 @@ SsbWrite(std::ostream& oStrm); // Write header - void BeginWrite(const char* pId, const size_t nIdSize, const uint64& nVersion); - void BeginWrite(const char* pszId, const uint64& nVersion) {BeginWrite(pszId, std::strlen(pszId), nVersion);} + void BeginWrite(const ID &id, const uint64& nVersion); // Write item using default write implementation. template <class T> - void WriteItem(const T& obj, const char* pszId) {WriteItem(obj, pszId, std::strlen(pszId), &srlztn::WriteItem<T>);} + void WriteItem(const T& obj, const ID &id) {WriteItem(obj, id, &srlztn::WriteItem<T>);} - template <class T> - void WriteItem(const T& obj, const char* pId, const size_t nIdSize) {WriteItem(obj, pId, nIdSize, &srlztn::WriteItem<T>);} - // Write item using given function. template <class T, class FuncObj> - void WriteItem(const T& obj, const char* pId, const size_t nIdSize, FuncObj); + void WriteItem(const T& obj, const ID &id, FuncObj); // Writes mapping. void FinishWrite(); @@ -376,18 +394,16 @@ private: // Called after writing an item. - void OnWroteItem(const char* pId, const size_t nIdSize, const Postype& posBeforeWrite); + void OnWroteItem(const ID &id, const Postype& posBeforeWrite); void AddWriteNote(const SsbStatus s); - void AddWriteNote(const char* pId, - const size_t nIdLength, + void AddWriteNote(const ID &id, const NumType nEntryNum, const DataSize nBytecount, const RposType rposStart); // Writes mapping item to mapstream. - void WriteMapItem(const char* pId, - const size_t nIdSize, + void WriteMapItem(const ID &id, const RposType& rposDataStart, const DataSize& nDatasize, const char* pszDesc); @@ -407,66 +423,44 @@ }; - -template<typename T> -struct IdLE -{ - char b[sizeof(T)]; - IdLE(T val) - { - std::memcpy(b, &val, sizeof(T)); - #ifdef MPT_PLATFORM_BIG_ENDIAN - std::reverse(b, b+sizeof(T)); - #endif - } - const char* GetChars() const - { - return b; - } -}; - - template <class T, class FuncObj> -void SsbWrite::WriteItem(const T& obj, const char* pId, const size_t nIdSize, FuncObj Func) -//------------------------------------------------------------------------------------ +void SsbWrite::WriteItem(const T& obj, const ID &id, FuncObj Func) +//---------------------------------------------------------------- { const Postype pos = m_pOstrm->tellp(); Func(*m_pOstrm, obj); - OnWroteItem(pId, nIdSize, pos); + OnWroteItem(id, pos); } template <class T, class FuncObj> -SsbRead::ReadRv SsbRead::ReadItem(T& obj, const char* pId, const size_t nIdSize, FuncObj Func) -//------------------------------------------------------------------------------------ +SsbRead::ReadRv SsbRead::ReadItem(T& obj, const ID &id, FuncObj Func) +//------------------------------------------------------------------- { - const ReadEntry* pE = Find(pId, nIdSize); + const ReadEntry* pE = Find(id); const Postype pos = m_pIstrm->tellg(); if (pE != nullptr || GetFlag(RwfRMapHasId) == false) Func(*m_pIstrm, obj, (pE) ? (pE->nSize) : invalidDatasize); - return OnReadEntry(pE, pId, nIdSize, pos); + return OnReadEntry(pE, id, pos); } template <class T, class FuncObj> -SsbRead::ReadRv SsbRead::ReadItem(const ReadIterator& iter, T& obj, FuncObj func) -//----------------------------------------------------------------------- +SsbRead::ReadRv SsbRead::ReadIterItem(const ReadIterator& iter, T& obj, FuncObj func) +//----------------------------------------------------------------------------------- { m_pIstrm->clear(); if (iter->rposStart != 0) m_pIstrm->seekg(m_posStart + Postype(iter->rposStart)); const Postype pos = m_pIstrm->tellg(); func(*m_pIstrm, obj, iter->nSize); - return OnReadEntry(&(*iter), &m_Idarray[iter->nIdpos], iter->nIdLength, pos); + return OnReadEntry(&(*iter), ID(&m_Idarray[iter->nIdpos], iter->nIdLength), pos); } -inline SsbRead::IdMatchStatus SsbRead::CompareId(const ReadIterator& iter, const char* pId, const size_t nIdSize) -//------------------------------------------------------------------------------------------------------- +inline SsbRead::IdMatchStatus SsbRead::CompareId(const ReadIterator& iter, const ID &id) +//-------------------------------------------------------------------------------------- { - if (nIdSize == iter->nIdLength && memcmp(&m_Idarray[iter->nIdpos], pId, iter->nIdLength) == 0) - return IdMatch; - else - return IdMismatch; + return (id == ID(&m_Idarray[iter->nIdpos], iter->nIdLength)) ? IdMatch : IdMismatch; } Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2014-09-12 11:03:26 UTC (rev 4284) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2014-09-12 11:26:26 UTC (rev 4285) @@ -1020,11 +1020,11 @@ { srlztn::SsbRead ssb(iStrm); ssb.BeginRead("mptm", MptVersion::num); - ssb.ReadItem(GetTuneSpecificTunings(), "0", 1, &ReadTuningCollection); - ssb.ReadItem(*this, "1", 1, &ReadTuningMap); - ssb.ReadItem(Order, "2", 1, &ReadModSequenceOld); - ssb.ReadItem(Patterns, FileIdPatterns, strlen(FileIdPatterns), &ReadModPatterns); - ssb.ReadItem(Order, FileIdSequences, strlen(FileIdSequences), &ReadModSequences); + ssb.ReadItem(GetTuneSpecificTunings(), "0", &ReadTuningCollection); + ssb.ReadItem(*this, "1", &ReadTuningMap); + ssb.ReadItem(Order, "2", &ReadModSequenceOld); + ssb.ReadItem(Patterns, FileIdPatterns, &ReadModPatterns); + ssb.ReadItem(Order, FileIdSequences, &ReadModSequences); if(ssb.GetStatus() & srlztn::SNT_FAILURE) { @@ -1650,14 +1650,14 @@ ssb.BeginWrite("mptm", MptVersion::num); if(GetTuneSpecificTunings().GetNumTunings() > 0) - ssb.WriteItem(GetTuneSpecificTunings(), "0", 1, &WriteTuningCollection); + ssb.WriteItem(GetTuneSpecificTunings(), "0", &WriteTuningCollection); if(AreNonDefaultTuningsUsed(*this)) - ssb.WriteItem(*this, "1", 1, &WriteTuningMap); + ssb.WriteItem(*this, "1", &WriteTuningMap); if(Order.NeedsExtraDatafield()) - ssb.WriteItem(Order, "2", 1, &WriteModSequenceOld); + ssb.WriteItem(Order, "2", &WriteModSequenceOld); if(bNeedsMptPatSave) - ssb.WriteItem(Patterns, FileIdPatterns, strlen(FileIdPatterns), &WriteModPatterns); - ssb.WriteItem(Order, FileIdSequences, strlen(FileIdSequences), &WriteModSequences); + ssb.WriteItem(Patterns, FileIdPatterns, &WriteModPatterns); + ssb.WriteItem(Order, FileIdSequences, &WriteModSequences); ssb.FinishWrite(); Modified: trunk/OpenMPT/soundlib/ModSequence.cpp =================================================================== --- trunk/OpenMPT/soundlib/ModSequence.cpp 2014-09-12 11:03:26 UTC (rev 4284) +++ trunk/OpenMPT/soundlib/ModSequence.cpp 2014-09-12 11:26:26 UTC (rev 4285) @@ -819,7 +819,7 @@ ssb.WriteItem(seq.m_sName.c_str(), "n"); const uint16 nLength = seq.GetLengthTailTrimmed(); ssb.WriteItem<uint16>(nLength, "l"); - ssb.WriteItem(seq.m_pArray, "a", 1, srlztn::ArrayWriter<uint16>(nLength)); + ssb.WriteItem(seq.m_pArray, "a", srlztn::ArrayWriter<uint16>(nLength)); ssb.FinishWrite(); } @@ -838,7 +838,7 @@ ssb.ReadItem<uint16>(nSize, "l"); LimitMax(nSize, ModSpecs::mptm.ordersMax); seq.resize(MAX(nSize, ModSequenceSet::s_nCacheSize)); - ssb.ReadItem(seq.m_pArray, "a", 1, srlztn::ArrayReader<uint16>(nSize)); + ssb.ReadItem(seq.m_pArray, "a", srlztn::ArrayReader<uint16>(nSize)); } @@ -854,9 +854,9 @@ for(uint8 i = 0; i < nSeqs; i++) { if (i == seq.GetCurrentSequenceIndex()) - ssb.WriteItem(seq, srlztn::IdLE<uint8>(i).GetChars(), sizeof(i), &WriteModSequence); + ssb.WriteItem(seq, srlztn::ID::FromInt<uint8>(i), &WriteModSequence); else - ssb.WriteItem(seq.m_Sequences[i], srlztn::IdLE<uint8>(i).GetChars(), sizeof(i), &WriteModSequence); + ssb.WriteItem(seq.m_Sequences[i], srlztn::ID::FromInt<uint8>(i), &WriteModSequence); } ssb.FinishWrite(); } @@ -881,7 +881,7 @@ for(uint8 i = 0; i < nSeqs; i++) { - ssb.ReadItem(seq.m_Sequences[i], srlztn::IdLE<uint8>(i).GetChars(), sizeof(i), &ReadModSequence); + ssb.ReadItem(seq.m_Sequences[i], srlztn::ID::FromInt<uint8>(i), &ReadModSequence); } seq.m_nCurrentSeq = (nCurrent < seq.GetNumSequences()) ? nCurrent : 0; seq.CopyStorageToCache(); Modified: trunk/OpenMPT/soundlib/pattern.cpp =================================================================== --- trunk/OpenMPT/soundlib/pattern.cpp 2014-09-12 11:03:26 UTC (rev 4284) +++ trunk/OpenMPT/soundlib/pattern.cpp 2014-09-12 11:26:26 UTC (rev 4285) @@ -486,7 +486,7 @@ { srlztn::SsbWrite ssb(oStrm); ssb.BeginWrite(FileIdPattern, MptVersion::num); - ssb.WriteItem(pat, "data", strlen("data"), &WriteData); + ssb.WriteItem(pat, "data", &WriteData); // pattern time signature if(pat.GetOverrideSignature()) { @@ -504,7 +504,7 @@ ssb.BeginRead(FileIdPattern, MptVersion::num); if ((ssb.GetStatus() & srlztn::SNT_FAILURE) != 0) return; - ssb.ReadItem(pat, "data", strlen("data"), &ReadData); + ssb.ReadItem(pat, "data", &ReadData); // pattern time signature uint32 nRPB = 0, nRPM = 0; ssb.ReadItem<uint32>(nRPB, "RPB."); Modified: trunk/OpenMPT/soundlib/patternContainer.cpp =================================================================== --- trunk/OpenMPT/soundlib/patternContainer.cpp 2014-09-12 11:03:26 UTC (rev 4284) +++ trunk/OpenMPT/soundlib/patternContainer.cpp 2014-09-12 11:26:26 UTC (rev 4285) @@ -201,7 +201,7 @@ uint16 nCount = 0; for(uint16 i = 0; i < nPatterns; i++) if (patc[i]) { - ssb.WriteItem(patc[i], srlztn::IdLE<uint16>(i).GetChars(), sizeof(i), &WriteModPattern); + ssb.WriteItem(patc[i], srlztn::ID::FromInt<uint16>(i), &WriteModPattern); nCount = i + 1; } ssb.WriteItem<uint16>(nCount, "num"); // Index of last pattern + 1. @@ -225,7 +225,7 @@ patc.ResizeArray(nPatterns); for(uint16 i = 0; i < nPatterns; i++) { - ssb.ReadItem(patc[i], srlztn::IdLE<uint16>(i).GetChars(), sizeof(i), &ReadModPattern); + ssb.ReadItem(patc[i], srlztn::ID::FromInt<uint16>(i), &ReadModPattern); } } Modified: trunk/OpenMPT/soundlib/tuning.cpp =================================================================== --- trunk/OpenMPT/soundlib/tuning.cpp 2014-09-12 11:03:26 UTC (rev 4284) +++ trunk/OpenMPT/soundlib/tuning.cpp 2014-09-12 11:26:26 UTC (rev 4285) @@ -384,14 +384,14 @@ srlztn::SsbRead ssb(iStrm); ssb.BeginRead("CTB244RTI", (CTuning::GetVersion() << 24) + GetVersion()); - ssb.ReadItem(pTuning->m_TuningName, "0", 1, ReadStr); + ssb.ReadItem(pTuning->m_TuningName, "0", ReadStr); ssb.ReadItem(pTuning->m_EditMask, "1"); ssb.ReadItem(pTuning->m_TuningType, "2"); - ssb.ReadItem(pTuning->m_NoteNameMap, "3", 1, ReadNoteMap); + ssb.ReadItem(pTuning->m_NoteNameMap, "3", ReadNoteMap); ssb.ReadItem(pTuning->m_FineStepCount, "4"); // RTI entries. - ssb.ReadItem(pTuning->m_RatioTable, "RTI0", 4, ReadRatioTable); + ssb.ReadItem(pTuning->m_RatioTable, "RTI0", ReadRatioTable); ssb.ReadItem(pTuning->m_StepMin, "RTI1"); ssb.ReadItem(pTuning->m_GroupSize, "RTI2"); ssb.ReadItem(pTuning->m_GroupRatio, "RTI3"); @@ -476,11 +476,11 @@ srlztn::SsbWrite ssb(outStrm); ssb.BeginWrite("CTB244RTI", (GetVersion() << 24) + GetClassVersion()); if (m_TuningName.length() > 0) - ssb.WriteItem(m_TuningName, "0", 1, WriteStr); + ssb.WriteItem(m_TuningName, "0", WriteStr); ssb.WriteItem(m_EditMask, "1"); ssb.WriteItem(m_TuningType, "2"); if (m_NoteNameMap.size() > 0) - ssb.WriteItem(m_NoteNameMap, "3", 1, WriteNoteMap); + ssb.WriteItem(m_NoteNameMap, "3", WriteNoteMap); if (GetFineStepCount() > 0) ssb.WriteItem(m_FineStepCount, "4"); @@ -488,9 +488,9 @@ if (GetGroupRatio() > 0) ssb.WriteItem(m_GroupRatio, "RTI3"); if (tt == TT_GROUPGEOMETRIC) - ssb.WriteItem(m_RatioTable, "RTI0", 4, RatioWriter(GetGroupSize())); + ssb.WriteItem(m_RatioTable, "RTI0", RatioWriter(GetGroupSize())); if (tt == TT_GENERAL) - ssb.WriteItem(m_RatioTable, "RTI0", 4, RatioWriter()); + ssb.WriteItem(m_RatioTable, "RTI0", RatioWriter()); if (tt == TT_GEOMETRIC) ssb.WriteItem(m_GroupSize, "RTI2"); Modified: trunk/OpenMPT/soundlib/tuningCollection.cpp =================================================================== --- trunk/OpenMPT/soundlib/tuningCollection.cpp 2014-09-12 11:03:26 UTC (rev 4284) +++ trunk/OpenMPT/soundlib/tuningCollection.cpp 2014-09-12 11:26:26 UTC (rev 4285) @@ -108,12 +108,12 @@ { srlztn::SsbWrite ssb(oStrm); ssb.BeginWrite("TC", s_SerializationVersion); - ssb.WriteItem(m_Name, "0", 1, &WriteStr); + ssb.WriteItem(m_Name, "0", &WriteStr); ssb.WriteItem(m_EditMask, "1"); const size_t tcount = m_Tunings.size(); for(size_t i = 0; i<tcount; i++) - ssb.WriteItem(*m_Tunings[i], "2", 1, &WriteTuning); + ssb.WriteItem(*m_Tunings[i], "2", &WriteTuning); ssb.FinishWrite(); if(ssb.GetStatus() & srlztn::SNT_FAILURE) @@ -176,11 +176,11 @@ for(srlztn::SsbRead::ReadIterator iter = iterBeg; iter != iterEnd; iter++) { if (ssb.CompareId(iter, "0") == srlztn::SsbRead::IdMatch) - ssb.ReadItem(iter, m_Name, &ReadStr); + ssb.ReadIterItem(iter, m_Name, &ReadStr); else if (ssb.CompareId(iter, "1") == srlztn::SsbRead::IdMatch) - ssb.ReadItem(iter, m_EditMask); + ssb.ReadIterItem(iter, m_EditMask); else if (ssb.CompareId(iter, "2") == srlztn::SsbRead::IdMatch) - ssb.ReadItem(iter, *this, &ReadTuning); + ssb.ReadIterItem(iter, *this, &ReadTuning); } if(ssb.GetStatus() & srlztn::SNT_FAILURE) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2014-09-14 23:48:59
|
Revision: 4290 http://sourceforge.net/p/modplug/code/4290 Author: saga-games Date: 2014-09-14 23:48:51 +0000 (Sun, 14 Sep 2014) Log Message: ----------- [Fix] It was possible (since r4236) to re-use a key combination for the same shortcut with conflicting event types (e.g. Key Down vs. Key Down + Hold). This might have introduced new bogus shortcuts in custom keyboard profiles. [Mod] When importing the default key map into a custom key map, event types are completely ignored, so if e.g. the user has assigned a certain key on key hold but the default key map uses the same key on key down only, this version is no longer added. [Mod] Updated DE_jojo.mkb (mostly for toggling pattern follow on Scroll Lock) Revision Links: -------------- http://sourceforge.net/p/modplug/code/4236 Modified Paths: -------------- trunk/OpenMPT/mptrack/CommandSet.cpp trunk/OpenMPT/mptrack/CommandSet.h trunk/OpenMPT/mptrack/KeyConfigDlg.cpp trunk/OpenMPT/packageTemplate/extraKeymaps/DE_jojo.mkb Modified: trunk/OpenMPT/mptrack/CommandSet.cpp =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.cpp 2014-09-14 08:14:22 UTC (rev 4289) +++ trunk/OpenMPT/mptrack/CommandSet.cpp 2014-09-14 23:48:51 UTC (rev 4290) @@ -695,8 +695,8 @@ //------------------------------------------------------- -CString CCommandSet::Add(KeyCombination kc, CommandID cmd, bool overwrite, int pos) -//--------------------------------------------------------------------------------- +CString CCommandSet::Add(KeyCombination kc, CommandID cmd, bool overwrite, int pos, bool checkEventConflict) +//---------------------------------------------------------------------------------------------------------- { CString report= ""; @@ -714,7 +714,7 @@ //Check that this keycombination isn't already assigned (in this context), except for dummy keys std::pair<CommandID, KeyCombination> conflictCmd; - if((conflictCmd = IsConflicting(kc, cmd)).first != kcNull) + if((conflictCmd = IsConflicting(kc, cmd, checkEventConflict)).first != kcNull) { if (!overwrite) { @@ -746,21 +746,21 @@ } -std::pair<CommandID, KeyCombination> CCommandSet::IsConflicting(KeyCombination kc, CommandID cmd) const -//----------------------------------------------------------------------------------------------------- +std::pair<CommandID, KeyCombination> CCommandSet::IsConflicting(KeyCombination kc, CommandID cmd, bool checkEventConflict) const +//------------------------------------------------------------------------------------------------------------------------------ { if(IsDummyCommand(cmd)) // no need to search if we are adding a dummy key return std::pair<CommandID, KeyCombination>(kcNull, KeyCombination()); for(int curCmd = 0; curCmd < kcNumCommands; curCmd++) { - if(curCmd == cmd || IsDummyCommand((CommandID)curCmd)) + if(IsDummyCommand((CommandID)curCmd)) continue; for(size_t k = 0; k < commands[curCmd].kcList.size(); k++) { const KeyCombination &curKc = commands[curCmd].kcList[k]; - if(KeyCombinationConflict(curKc, kc)) + if(KeyCombinationConflict(curKc, kc, checkEventConflict)) { return std::pair<CommandID, KeyCombination>((CommandID)curCmd, curKc); } @@ -1534,7 +1534,7 @@ int fileVersion = 0; oldSpecs = nullptr; // After clearing the key set, need to fix effect letters - bool fillExistingSet = commandSet != nullptr; + const bool fillExistingSet = commandSet != nullptr; // If commandSet is valid, add new commands to it (this is used for adding the default shortcuts to existing keymaps) CCommandSet *pTempCS = fillExistingSet ? commandSet : new CCommandSet(); @@ -1637,7 +1637,7 @@ } } else { - pTempCS->Add(kc, cmd, commandSet == nullptr); + pTempCS->Add(kc, cmd, !fillExistingSet, -1, !fillExistingSet); } } } @@ -1983,15 +1983,17 @@ } -bool CCommandSet::KeyCombinationConflict(KeyCombination kc1, KeyCombination kc2) const + +bool CCommandSet::KeyCombinationConflict(KeyCombination kc1, KeyCombination kc2, bool checkEventConflict) const +//------------------------------------------------------------------------------------------------------------- { bool modConflict = (kc1.Modifier()==kc2.Modifier()); bool codeConflict = (kc1.KeyCode()==kc2.KeyCode()); bool eventConflict = ((kc1.EventType()&kc2.EventType())!=0); bool ctxConflict = (kc1.Context() == kc2.Context()); - bool crossCxtConflict = m_isParentContext[kc1.Context()][kc2.Context()] || m_isParentContext[kc2.Context()][kc1.Context()]; + bool crossCxtConflict = IsCrossContextConflict(kc1, kc2); - bool conflict = modConflict && codeConflict && eventConflict && + bool conflict = modConflict && codeConflict && (eventConflict || !checkEventConflict) && (ctxConflict || crossCxtConflict); return conflict; Modified: trunk/OpenMPT/mptrack/CommandSet.h =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.h 2014-09-14 08:14:22 UTC (rev 4289) +++ trunk/OpenMPT/mptrack/CommandSet.h 2014-09-14 23:48:51 UTC (rev 4290) @@ -1279,7 +1279,7 @@ CString EnforceAll(KeyCombination kc, CommandID cmd, bool adding); int FindCmd(int uid) const; - bool KeyCombinationConflict(KeyCombination kc1, KeyCombination kc2) const; + bool KeyCombinationConflict(KeyCombination kc1, KeyCombination kc2, bool checkEventConflict = true) const; const CModSpecifications *oldSpecs; CommandStruct commands[kcNumCommands]; @@ -1291,11 +1291,11 @@ CCommandSet(); //Population - CString Add(KeyCombination kc, CommandID cmd, bool overwrite, int pos = -1); + CString Add(KeyCombination kc, CommandID cmd, bool overwrite, int pos = -1, bool checkEventConflict = true); CString Remove(KeyCombination kc, CommandID cmd); CString Remove(int pos, CommandID cmd); - std::pair<CommandID, KeyCombination> IsConflicting(KeyCombination kc, CommandID cmd) const; + std::pair<CommandID, KeyCombination> IsConflicting(KeyCombination kc, CommandID cmd, bool checkEventConflict = true) const; bool IsCrossContextConflict(KeyCombination kc1, KeyCombination kc2) const; //Tranformation Modified: trunk/OpenMPT/mptrack/KeyConfigDlg.cpp =================================================================== --- trunk/OpenMPT/mptrack/KeyConfigDlg.cpp 2014-09-14 08:14:22 UTC (rev 4289) +++ trunk/OpenMPT/mptrack/KeyConfigDlg.cpp 2014-09-14 23:48:51 UTC (rev 4290) @@ -801,6 +801,7 @@ bool add = true; std::pair<CommandID, KeyCombination> conflictCmd; if((conflictCmd = plocalCmdSet->IsConflicting(kc, cmd)).first != kcNull + && conflictCmd.first != cmd && !plocalCmdSet->IsCrossContextConflict(kc, conflictCmd.second) && Reporting::Confirm("New shortcut (" + kc.GetKeyText() + ") conflicts with " + plocalCmdSet->GetCommandText(conflictCmd.first) + " in " + conflictCmd.second.GetContextText() + ".\nDelete the other shortcut and keep the new one?", "Shortcut Conflict") == cnfNo) { Modified: trunk/OpenMPT/packageTemplate/extraKeymaps/DE_jojo.mkb =================================================================== --- trunk/OpenMPT/packageTemplate/extraKeymaps/DE_jojo.mkb 2014-09-14 08:14:22 UTC (rev 4289) +++ trunk/OpenMPT/packageTemplate/extraKeymaps/DE_jojo.mkb 2014-09-14 23:48:51 UTC (rev 4290) @@ -23,10 +23,13 @@ 0:1026:2:118:5 //Play Pattern from Cursor: Ctrl+F7 (KeyDown|KeyHold) 0:1376:0:120:1 //Toggle MIDI Record: F9 (KeyDown) 0:1359:2:90:5 //Undo: Ctrl+Z (KeyDown|KeyHold) +0:1905:2:89:5 //Redo: Ctrl+Y (KeyDown|KeyHold) +0:1905:3:90:5 //Redo: Shift+Ctrl+Z (KeyDown|KeyHold) 0:1905:2:89:1 //Redo: Ctrl+Y (KeyDown) 0:1360:2:88:1 //Cut: Ctrl+X (KeyDown) 0:1361:2:67:1 //Copy: Ctrl+C (KeyDown) 0:1362:2:86:1 //Paste: Ctrl+V (KeyDown) +0:1362:1:45:1 //Paste: Shift+EINFG (KeyDown) 0:1363:3:86:1 //Mix Paste: Shift+Ctrl+V (KeyDown) 0:1793:1:86:1 //Paste Flood: Shift+V (KeyDown) 0:1820:6:86:5 //Push Forward Paste (Insert): Ctrl+Alt+V (KeyDown|KeyHold) @@ -84,27 +87,33 @@ 2:1858:2:66:1 //Select Beat: Ctrl+B (KeyDown) 2:1859:3:66:1 //Select Measure: Shift+Ctrl+B (KeyDown) 2:1663:2:3:1 //Toggle follow song: Ctrl+ROLLEN-FESTSTELL (KeyDown) +2:1663:0:145:1 //Toggle follow song: ROLLEN-FESTSTELL (KeyDown) 2:1003:0:13:1 //Quick Copy: EINGABE (KeyDown) 2:1004:0:32:5 //Quick Paste: LEER (KeyDown|KeyHold) 2:1897:1:32:1 //Pick up nearest instrument number: Shift+LEER (KeyDown) 2:1001:2:32:1 //Enable Recording: Ctrl+LEER (KeyDown) 2:1002:2:13:5 //Play Row: Ctrl+EINGABE (KeyDown|KeyHold) -2:1317:4:18:1 //Set row spacing on note entry: Alt (KeyDown) -2:1861:4:187:5 //Increase Row Spacing: Alt++ (KeyDown|KeyHold) -2:1862:4:189:5 //Decrease Row Spacing: Alt+- (KeyDown|KeyHold) +2:1317:4:18:1 //Set edit step on note entry: Alt (KeyDown) +2:1861:4:187:5 //Increase Edit Step: Alt++ (KeyDown|KeyHold) +2:1862:4:189:5 //Decrease Edit Step: Alt+- (KeyDown|KeyHold) 2:1685:2:9:1 //Switch to Order List: Ctrl+TABULATOR (KeyDown) 2:1806:2:68:5 //Duplicate pattern: Ctrl+D (KeyDown|KeyHold) -2:1836:2:191:1 //Edit Plugin assigned to PC Event: Ctrl+# (KeyDown) +2:1836:2:191:1 //Toggle PC Event/instrument plugin editor: Ctrl+# (KeyDown) 2:1662:6:80:1 //Toggle channel's plugin editor: Ctrl+Alt+P (KeyDown) 2:1062:0:93:1 //Show Note Properties: ANWENDUNG (KeyDown) 2:1772:2:93:1 //Show Pattern Properties: Ctrl+ANWENDUNG (KeyDown) +2:1772:5:80:1 //Show Pattern Properties: Shift+Alt+P (KeyDown) 2:1819:2:69:1 //Split Keyboard Settings dialog: Ctrl+E (KeyDown) +2:1776:1:122:1 //Toggle Loop Pattern: Shift+F11 (KeyDown) 2:1780:2:80:1 //Show playback time at current row: Ctrl+P (KeyDown) 2:1892:4:81:1 //Quantize Settings: Alt+Q (KeyDown) 2:1900:3:77:1 //Toggle Clipboard Manager: Shift+Ctrl+M (KeyDown) 2:1901:3:37:1 //Cycle to Previous Clipboard: Shift+Ctrl+NACH-LINKS (KeyDown) 2:1902:3:39:1 //Cycle to Next Clipboard: Shift+Ctrl+NACH-RECHTS (KeyDown) 2:1005:2:85:1 //Mute current Channel: Ctrl+U (KeyDown) +2:1005:0:121:1 //Mute current Channel: F10 (KeyDown) +2:1006:2:121:1 //Solo current Channel: Ctrl+F10 (KeyDown) +2:1771:6:121:1 //Unmute all channels: Ctrl+Alt+F10 (KeyDown) 2:1883:2:49:1 //Channel Record Select: Ctrl+1 (KeyDown) 2:1884:2:50:1 //Channel Split Record Select: Ctrl+2 (KeyDown) 2:1786:2:82:1 //Reset Channel: Ctrl+R (KeyDown) @@ -191,9 +200,9 @@ 3:1221:0:57:1 //Set octave 9: 9 (KeyDown) 3:1221:0:105:1 //Set octave 9: 9 (ZEHNERTASTATUR) (KeyDown) 3:1316:1:16:1 //Chord Modifier: Shift+UMSCHALT (KeyDown) -3:1667:0:220:1 //Note Cut (without instrument number): ZIRKUMFLEX (KeyDown) -3:1668:0:221:1 //Note Off (without instrument number): AKUT (KeyDown) -3:1792:0:219:1 //Note Fade (without instrument number): \xDF (KeyDown) +3:1200:0:220:1 //Note Cut: ZIRKUMFLEX (KeyDown) +3:1201:0:221:1 //Note Off: AKUT (KeyDown) +3:1791:0:219:1 //Note Fade: \xDF (KeyDown) 3:1788:0:226:1 //Parameter control(MPTm only): < (KeyDown) 3:1789:1:226:1 //Parameter control(smooth)(MPTm only): Shift+< (KeyDown) @@ -290,17 +299,20 @@ //----( Sample Context [bottom] (8) )------------ 8:1673:0:13:1 //Load Sample: EINGABE (KeyDown) +8:1907:2:81:1 //Transpose +1: Ctrl+Q (KeyDown) +8:1908:2:65:1 //Transpose -1: Ctrl+A (KeyDown) +8:1909:3:81:1 //Transpose +12: Shift+Ctrl+Q (KeyDown) +8:1910:3:65:1 //Transpose -12: Shift+Ctrl+A (KeyDown) 8:1380:2:84:1 //Trim sample around loop points: Ctrl+T (KeyDown) 8:1383:0:8:1 //Silence Sample Selection: R\xDCCK (KeyDown) 8:1384:1:78:1 //Normalise Sample: Shift+N (KeyDown) -8:1385:3:65:1 //Amplify Sample: Shift+Ctrl+A (KeyDown) 8:1385:2:77:1 //Amplify Sample: Ctrl+M (KeyDown) 8:1381:3:82:1 //Reverse Sample: Shift+Ctrl+R (KeyDown) 8:1382:0:46:1 //Delete Sample Selection: ENTF (KeyDown) 8:1386:0:107:1 //Zoom Out: + (ZEHNERTASTATUR) (KeyDown) 8:1387:0:109:1 //Zoom In: - (ZEHNERTASTATUR) (KeyDown) 8:1882:0:32:1 //Zoom into Selection: LEER (KeyDown) -8:1887:2:56:1 //Conver to 8-bit: Ctrl+8 (KeyDown) +8:1887:2:56:1 //Convert to 8-bit: Ctrl+8 (KeyDown) 8:1888:1:77:1 //Convert to Mono (Mix): Shift+M (KeyDown) 8:1889:1:76:1 //Convert to Mono (Left Channel): Shift+L (KeyDown) 8:1890:1:82:1 //Convert to Mono (Right Channel): Shift+R (KeyDown) @@ -313,9 +325,13 @@ 8:1863:1:84:1 //Tune Sample to given Note: Shift+T (KeyDown) //----( Instrument Context [bottom] (9) )------------ +9:1837:2:81:1 //Zoom In: Ctrl+Q (KeyDown) 9:1837:0:107:5 //Zoom In: + (ZEHNERTASTATUR) (KeyDown|KeyHold) +9:1838:2:65:1 //Zoom Out: Ctrl+A (KeyDown) 9:1838:0:109:5 //Zoom Out: - (ZEHNERTASTATUR) (KeyDown|KeyHold) +9:1825:3:81:1 //Select previous envelope point: Shift+Ctrl+Q (KeyDown) 9:1825:1:9:5 //Select previous envelope point: Shift+TABULATOR (KeyDown|KeyHold) +9:1826:3:65:1 //Select next envelope point: Shift+Ctrl+A (KeyDown) 9:1826:0:9:5 //Select next envelope point: TABULATOR (KeyDown|KeyHold) 9:1821:0:37:5 //Move envelope point left: NACH-LINKS (KeyDown|KeyHold) 9:1822:0:39:5 //Move envelope point right: NACH-RECHTS (KeyDown|KeyHold) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <man...@us...> - 2014-09-17 08:49:20
|
Revision: 4296 http://sourceforge.net/p/modplug/code/4296 Author: manxorist Date: 2014-09-17 08:49:10 +0000 (Wed, 17 Sep 2014) Log Message: ----------- [Ref] sounddev: Add an abstract interface for SoundDevice::Base. Modified Paths: -------------- trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mainfrm.h trunk/OpenMPT/sounddev/SoundDevice.cpp trunk/OpenMPT/sounddev/SoundDevice.h trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp trunk/OpenMPT/sounddev/SoundDeviceASIO.h Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2014-09-16 07:52:30 UTC (rev 4295) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2014-09-17 08:49:10 UTC (rev 4296) @@ -1652,14 +1652,14 @@ if(gpSoundDevice) { const LONG requestFlags = gpSoundDevice->GetRequestFlags(); - if(requestFlags & SoundDevice::Base::RequestFlagClose) + if(requestFlags & SoundDevice::IBase::RequestFlagClose) { StopPlayback(); audioCloseDevice(); - } else if(requestFlags & SoundDevice::Base::RequestFlagReset) + } else if(requestFlags & SoundDevice::IBase::RequestFlagReset) { ResetSoundCard(); - } else if(requestFlags & SoundDevice::Base::RequestFlagRestart) + } else if(requestFlags & SoundDevice::IBase::RequestFlagRestart) { RestartPlayback(); } else Modified: trunk/OpenMPT/mptrack/Mainfrm.h =================================================================== --- trunk/OpenMPT/mptrack/Mainfrm.h 2014-09-16 07:52:30 UTC (rev 4295) +++ trunk/OpenMPT/mptrack/Mainfrm.h 2014-09-17 08:49:10 UTC (rev 4296) @@ -321,7 +321,7 @@ public: // Low-Level Audio - SoundDevice::Base *gpSoundDevice; + SoundDevice::IBase *gpSoundDevice; UINT_PTR m_NotifyTimer; Dither m_Dither; Modified: trunk/OpenMPT/sounddev/SoundDevice.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.cpp 2014-09-16 07:52:30 UTC (rev 4295) +++ trunk/OpenMPT/sounddev/SoundDevice.cpp 2014-09-17 08:49:10 UTC (rev 4296) @@ -582,8 +582,8 @@ } -bool Manager::OpenDriverSettings(SoundDevice::ID id, SoundDevice::IMessageReceiver *messageReceiver, SoundDevice::Base *currentSoundDevice) -//----------------------------------------------------------------------------------------------------------------------------------------- +bool Manager::OpenDriverSettings(SoundDevice::ID id, SoundDevice::IMessageReceiver *messageReceiver, SoundDevice::IBase *currentSoundDevice) +//------------------------------------------------------------------------------------------------------------------------------------------ { bool result = false; if(currentSoundDevice && FindDeviceInfo(id).IsValid() && (currentSoundDevice->GetDeviceID() == id) && (currentSoundDevice->GetDeviceInternalID() == FindDeviceInfo(id).internalID)) @@ -591,7 +591,7 @@ result = currentSoundDevice->OpenDriverSettings(); } else { - SoundDevice::Base *dummy = CreateSoundDevice(id); + SoundDevice::IBase *dummy = CreateSoundDevice(id); if(dummy) { dummy->SetMessageReceiver(messageReceiver); @@ -603,8 +603,8 @@ } -SoundDevice::Caps Manager::GetDeviceCaps(SoundDevice::ID id, SoundDevice::Base *currentSoundDevice) -//------------------------------------------------------------------------------------------------- +SoundDevice::Caps Manager::GetDeviceCaps(SoundDevice::ID id, SoundDevice::IBase *currentSoundDevice) +//-------------------------------------------------------------------------------------------------- { if(m_DeviceCaps.find(id) == m_DeviceCaps.end()) { @@ -613,7 +613,7 @@ m_DeviceCaps[id] = currentSoundDevice->GetDeviceCaps(); } else { - SoundDevice::Base *dummy = CreateSoundDevice(id); + SoundDevice::IBase *dummy = CreateSoundDevice(id); if(dummy) { m_DeviceCaps[id] = dummy->GetDeviceCaps(); @@ -625,8 +625,8 @@ } -SoundDevice::DynamicCaps Manager::GetDeviceDynamicCaps(SoundDevice::ID id, const std::vector<uint32> &baseSampleRates, SoundDevice::IMessageReceiver *messageReceiver, SoundDevice::Base *currentSoundDevice, bool update) -//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +SoundDevice::DynamicCaps Manager::GetDeviceDynamicCaps(SoundDevice::ID id, const std::vector<uint32> &baseSampleRates, SoundDevice::IMessageReceiver *messageReceiver, SoundDevice::IBase *currentSoundDevice, bool update) +//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- { if((m_DeviceDynamicCaps.find(id) == m_DeviceDynamicCaps.end()) || update) { @@ -635,7 +635,7 @@ m_DeviceDynamicCaps[id] = currentSoundDevice->GetDeviceDynamicCaps(baseSampleRates); } else { - SoundDevice::Base *dummy = CreateSoundDevice(id); + SoundDevice::IBase *dummy = CreateSoundDevice(id); if(dummy) { dummy->SetMessageReceiver(messageReceiver); @@ -648,15 +648,15 @@ } -SoundDevice::Base * Manager::CreateSoundDevice(SoundDevice::ID id) -//---------------------------------------------------------------- +SoundDevice::IBase * Manager::CreateSoundDevice(SoundDevice::ID id) +//----------------------------------------------------------------- { const SoundDevice::Info info = FindDeviceInfo(id); if(!info.IsValid()) { return nullptr; } - SoundDevice::Base *result = nullptr; + SoundDevice::IBase *result = nullptr; switch(id.GetType()) { case TypeWAVEOUT: result = new CWaveDevice(id, info.internalID); break; Modified: trunk/OpenMPT/sounddev/SoundDevice.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.h 2014-09-16 07:52:30 UTC (rev 4295) +++ trunk/OpenMPT/sounddev/SoundDevice.h 2014-09-17 08:49:10 UTC (rev 4296) @@ -378,11 +378,85 @@ }; -//===================================== -class Base : protected IFillAudioBuffer -//===================================== +//========= +class IBase +//========= + : protected IFillAudioBuffer { +protected: + + IBase() { } + +public: + + virtual ~IBase() { } + +protected: + + virtual void FillAudioBuffer() = 0; + +public: + + static const uint32 RequestFlagClose = 1<<0; + static const uint32 RequestFlagReset = 1<<1; + static const uint32 RequestFlagRestart = 1<<2; + +public: + + virtual void SetSource(SoundDevice::ISource *source) = 0; + virtual SoundDevice::ISource *GetSource() const = 0; + virtual void SetMessageReceiver(SoundDevice::IMessageReceiver *receiver) = 0; + virtual SoundDevice::IMessageReceiver *GetMessageReceiver() const = 0; + + virtual SoundDevice::ID GetDeviceID() const = 0; + virtual SoundDevice::Type GetDeviceType() const = 0; + virtual SoundDevice::Index GetDeviceIndex() const = 0; + virtual std::wstring GetDeviceInternalID() const = 0; + + virtual SoundDevice::Caps GetDeviceCaps() const = 0; + virtual SoundDevice::DynamicCaps GetDeviceDynamicCaps(const std::vector<uint32> &baseSampleRates) = 0; + + virtual bool Init() = 0; + virtual bool Open(const SoundDevice::Settings &settings) = 0; + virtual bool Close() = 0; + virtual bool Start() = 0; + virtual void Stop(bool force = false) = 0; + + virtual uint32 GetRequestFlags() const = 0; + + virtual bool IsInited() const = 0; + virtual bool IsOpen() const = 0; + virtual bool IsPlaying() const = 0; + + virtual bool OnIdle() = 0; // return true if any work has been done + + virtual SoundDevice::Settings GetSettings() const = 0; + virtual SampleFormat GetActualSampleFormat() const = 0; + + virtual SoundDevice::BufferAttributes GetBufferAttributes() const = 0; + virtual SoundDevice::TimeInfo GetTimeInfo() const = 0; + + // Informational only, do not use for timing. + // Use GetStreamPositionFrames() for timing + virtual double GetCurrentLatency() const = 0; + virtual double GetCurrentUpdateInterval() const = 0; + + virtual int64 GetStreamPositionFrames() const = 0; + + virtual std::string GetStatistics() const = 0; + + virtual bool OpenDriverSettings() = 0; + +}; + + +//======== +class Base +//======== + : public IBase +{ + private: SoundDevice::ISource *m_Source; @@ -416,10 +490,6 @@ int64 m_StreamPositionOutputFrames; mpt::atomic_uint32_t m_RequestFlags; -public: - static const uint32 RequestFlagClose = 1<<0; - static const uint32 RequestFlagReset = 1<<1; - static const uint32 RequestFlagRestart = 1<<2; protected: @@ -493,7 +563,7 @@ bool IsOpen() const { return IsInited() && InternalIsOpen(); } bool IsPlaying() const { return m_IsPlaying; } - virtual bool OnIdle() { return false; } // return true if any work has been done + virtual bool OnIdle() { return false; } SoundDevice::Settings GetSettings() const { return m_Settings; } SampleFormat GetActualSampleFormat() const { return IsOpen() ? m_Settings.sampleFormat : SampleFormatInvalid; } @@ -501,8 +571,6 @@ SoundDevice::BufferAttributes GetBufferAttributes() const { return m_BufferAttributes; } SoundDevice::TimeInfo GetTimeInfo() const { return m_TimeInfo; } - // Informational only, do not use for timing. - // Use GetStreamPositionFrames() for timing virtual double GetCurrentLatency() const { return m_BufferAttributes.Latency; } double GetCurrentUpdateInterval() const; @@ -588,12 +656,12 @@ SoundDevice::Info FindDeviceInfo(const std::wstring &identifier) const; SoundDevice::Info FindDeviceInfoBestMatch(const std::wstring &identifier) const; - bool OpenDriverSettings(SoundDevice::ID id, SoundDevice::IMessageReceiver *messageReceiver = nullptr, SoundDevice::Base *currentSoundDevice = nullptr); + bool OpenDriverSettings(SoundDevice::ID id, SoundDevice::IMessageReceiver *messageReceiver = nullptr, SoundDevice::IBase *currentSoundDevice = nullptr); - SoundDevice::Caps GetDeviceCaps(SoundDevice::ID id, SoundDevice::Base *currentSoundDevice = nullptr); - SoundDevice::DynamicCaps GetDeviceDynamicCaps(SoundDevice::ID id, const std::vector<uint32> &baseSampleRates, SoundDevice::IMessageReceiver *messageReceiver = nullptr, SoundDevice::Base *currentSoundDevice = nullptr, bool update = false); + SoundDevice::Caps GetDeviceCaps(SoundDevice::ID id, SoundDevice::IBase *currentSoundDevice = nullptr); + SoundDevice::DynamicCaps GetDeviceDynamicCaps(SoundDevice::ID id, const std::vector<uint32> &baseSampleRates, SoundDevice::IMessageReceiver *messageReceiver = nullptr, SoundDevice::IBase *currentSoundDevice = nullptr, bool update = false); - SoundDevice::Base * CreateSoundDevice(SoundDevice::ID id); + SoundDevice::IBase * CreateSoundDevice(SoundDevice::ID id); }; Modified: trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2014-09-16 07:52:30 UTC (rev 4295) +++ trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2014-09-17 08:49:10 UTC (rev 4296) @@ -184,14 +184,14 @@ //------------------------------------------------------------------------ : SoundDevice::Base(id, internalID) { - Init(); + InitMembers(); m_QueriedFeatures.reset(); m_UsedFeatures.reset(); } -void CASIODevice::Init() -//---------------------- +void CASIODevice::InitMembers() +//----------------------------- { m_pAsioDrv = nullptr; @@ -243,7 +243,7 @@ ASSERT(!IsDriverOpen()); - Init(); + InitMembers(); Log(mpt::String::Print("ASIO: Open(%1:'%2'): %3-bit, %4 channels, %5Hz, hw-timing=%6" , GetDeviceIndex() Modified: trunk/OpenMPT/sounddev/SoundDeviceASIO.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceASIO.h 2014-09-16 07:52:30 UTC (rev 4295) +++ trunk/OpenMPT/sounddev/SoundDeviceASIO.h 2014-09-17 08:49:10 UTC (rev 4296) @@ -95,7 +95,7 @@ ~CASIODevice(); private: - void Init(); + void InitMembers(); bool HandleRequests(); // return true if any work has been done void UpdateLatency(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <man...@us...> - 2014-09-17 11:21:24
|
Revision: 4297 http://sourceforge.net/p/modplug/code/4297 Author: manxorist Date: 2014-09-17 11:21:16 +0000 (Wed, 17 Sep 2014) Log Message: ----------- [Fix] sounddev: There are cases where a Latency or UpdateInterval value of 0 ended up in the ini file. A value of 0 generally does not make any sense and clamping it to the allowed range always results in the shortest possible interval which is in most cases not the optimal result. Instead, if a value of 0 is found, use the default value now. Modified Paths: -------------- trunk/OpenMPT/mptrack/Mpdlgs.cpp trunk/OpenMPT/sounddev/SoundDevice.cpp Modified: trunk/OpenMPT/mptrack/Mpdlgs.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mpdlgs.cpp 2014-09-17 08:49:10 UTC (rev 4296) +++ trunk/OpenMPT/mptrack/Mpdlgs.cpp 2014-09-17 11:21:16 UTC (rev 4297) @@ -714,6 +714,7 @@ m_CbnLatencyMS.GetWindowText(s); m_Settings.Latency = ParseTime(s); //Check given value. + if(m_Settings.Latency == 0.0) m_Settings.Latency = m_CurrentDeviceCaps.DefaultSettings.Latency; m_Settings.Latency = Clamp(m_Settings.Latency, m_CurrentDeviceCaps.LatencyMin, m_CurrentDeviceCaps.LatencyMax); m_CbnLatencyMS.SetWindowText(PrintTime(m_Settings.Latency)); } @@ -723,6 +724,7 @@ m_CbnUpdateIntervalMS.GetWindowText(s); m_Settings.UpdateInterval = ParseTime(s); //Check given value. + if(m_Settings.UpdateInterval == 0.0) m_Settings.UpdateInterval = m_CurrentDeviceCaps.DefaultSettings.UpdateInterval; m_Settings.UpdateInterval = Clamp(m_Settings.UpdateInterval, m_CurrentDeviceCaps.UpdateIntervalMin, m_CurrentDeviceCaps.UpdateIntervalMax); m_CbnUpdateIntervalMS.SetWindowText(PrintTime(m_Settings.UpdateInterval)); } Modified: trunk/OpenMPT/sounddev/SoundDevice.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.cpp 2014-09-17 08:49:10 UTC (rev 4296) +++ trunk/OpenMPT/sounddev/SoundDevice.cpp 2014-09-17 11:21:16 UTC (rev 4297) @@ -231,6 +231,8 @@ Close(); } m_Settings = settings; + if(m_Settings.Latency == 0.0) m_Settings.Latency = m_Caps.DefaultSettings.Latency; + if(m_Settings.UpdateInterval == 0.0) m_Settings.UpdateInterval = m_Caps.DefaultSettings.UpdateInterval; m_Settings.Latency = Clamp(m_Settings.Latency, m_Caps.LatencyMin, m_Caps.LatencyMax); m_Settings.UpdateInterval = Clamp(m_Settings.UpdateInterval, m_Caps.UpdateIntervalMin, m_Caps.UpdateIntervalMax); if(!m_Settings.ChannelMapping.IsValid(m_Settings.Channels)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2014-09-22 23:11:14
|
Revision: 4298 http://sourceforge.net/p/modplug/code/4298 Author: saga-games Date: 2014-09-22 23:10:57 +0000 (Mon, 22 Sep 2014) Log Message: ----------- [Fix] MOD: Saving a sample loop with an odd length is now handled better (http://bugs.openmpt.org/view.php?id=590) [Imp] M15: Improve Exx auto slide behaviour. [Imp] Plugin bridge: Surround LoadLibrary() with try...catch just like in OpenMPT. Some plugins may crash as early as this. Modified Paths: -------------- trunk/OpenMPT/pluginBridge/Bridge.cpp trunk/OpenMPT/soundlib/Load_mod.cpp Modified: trunk/OpenMPT/pluginBridge/Bridge.cpp =================================================================== --- trunk/OpenMPT/pluginBridge/Bridge.cpp 2014-09-17 11:21:16 UTC (rev 4297) +++ trunk/OpenMPT/pluginBridge/Bridge.cpp 2014-09-22 23:10:57 UTC (rev 4298) @@ -386,7 +386,13 @@ #endif nativeEffect = nullptr; - library = LoadLibraryW(msg->str); + try + { + library = LoadLibraryW(msg->str); + } catch(...) + { + library = nullptr; + } if(library == nullptr) { Modified: trunk/OpenMPT/soundlib/Load_mod.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mod.cpp 2014-09-17 11:21:16 UTC (rev 4297) +++ trunk/OpenMPT/soundlib/Load_mod.cpp 2014-09-22 23:10:57 UTC (rev 4298) @@ -306,9 +306,9 @@ loopLength = 1; if(mptSmp.uFlags[CHN_LOOP] && (mptSmp.nLoopStart + 2u) < writeLength) { - const SmpLength loopEnd = Clamp(mptSmp.nLoopEnd, mptSmp.nLoopStart + 2u, writeLength); + const SmpLength loopEnd = Clamp(mptSmp.nLoopEnd, (mptSmp.nLoopStart & ~1) + 2u, writeLength) & ~1; loopStart = static_cast<uint16>(mptSmp.nLoopStart / 2u); - loopLength = static_cast<uint16>((loopEnd - mptSmp.nLoopStart) / 2u); + loopLength = static_cast<uint16>((loopEnd - (mptSmp.nLoopStart & ~1)) / 2u); } return writeLength; @@ -980,12 +980,23 @@ ModCommand &m = rowBase[chn]; ReadMODPatternEntry(file, m); + if(!m.param || m.command == 0x0E) + { + autoSlide[chn] = 0; + } if(m.command || m.param) { - if(m.command != 0x0E && autoSlide[chn] != 0) + if(autoSlide[chn] != 0) { - m.volcmd = (autoSlide[chn] & 0xF0) ? VOLCMD_VOLSLIDEUP : VOLCMD_VOLSLIDEDOWN; - m.vol = (autoSlide[chn] & 0xF0) ? (autoSlide[chn] >> 4) : (autoSlide[chn] & 0x0F); + if(autoSlide[chn] & 0xF0) + { + m.volcmd = VOLCMD_VOLSLIDEUP; + m.vol = autoSlide[chn] >> 4; + } else + { + m.volcmd = VOLCMD_VOLSLIDEDOWN; + m.vol = autoSlide[chn] & 0x0F; + } } if(m.command == 0x0D) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <man...@us...> - 2014-09-23 07:11:58
|
Revision: 4303 http://sourceforge.net/p/modplug/code/4303 Author: manxorist Date: 2014-09-23 07:11:50 +0000 (Tue, 23 Sep 2014) Log Message: ----------- [Var] lhasa: Update to git commit ab4ae51c0b6eb3b291f9c54f4a7d2e6d883bdca4 (2014-07-12). This adds support for the "lhx" compression variant. Modified Paths: -------------- trunk/OpenMPT/build/gen/lhasa.vcproj trunk/OpenMPT/build/gen/lhasa.vcxproj trunk/OpenMPT/build/gen/lhasa.vcxproj.filters trunk/OpenMPT/include/lhasa/NEWS trunk/OpenMPT/include/lhasa/OpenMPT.txt trunk/OpenMPT/include/lhasa/TODO trunk/OpenMPT/include/lhasa/configure.ac trunk/OpenMPT/include/lhasa/lib/Makefile.am trunk/OpenMPT/include/lhasa/lib/lh_new_decoder.c trunk/OpenMPT/include/lhasa/lib/lha_arch.h trunk/OpenMPT/include/lhasa/lib/lha_arch_unix.c trunk/OpenMPT/include/lhasa/lib/lha_arch_win32.c trunk/OpenMPT/include/lhasa/lib/lha_decoder.c trunk/OpenMPT/include/lhasa/lib/lha_input_stream.c trunk/OpenMPT/include/lhasa/lib/pm1_decoder.c trunk/OpenMPT/include/lhasa/pkg/win32/GNUmakefile trunk/OpenMPT/include/lhasa/pkg/win32/README trunk/OpenMPT/include/lhasa/src/args.txt trunk/OpenMPT/include/lhasa/src/extract.c trunk/OpenMPT/include/lhasa/src/extract.h trunk/OpenMPT/include/lhasa/src/main.c trunk/OpenMPT/include/premake4.lua Added Paths: ----------- trunk/OpenMPT/include/lhasa/lib/lhx_decoder.c Modified: trunk/OpenMPT/build/gen/lhasa.vcproj =================================================================== --- trunk/OpenMPT/build/gen/lhasa.vcproj 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/build/gen/lhasa.vcproj 2014-09-23 07:11:50 UTC (rev 4303) @@ -585,6 +585,10 @@ > </File> <File + RelativePath="..\..\include\lhasa\lib\lhx_decoder.c" + > + </File> + <File RelativePath="..\..\include\lhasa\lib\lz5_decoder.c" > </File> Modified: trunk/OpenMPT/build/gen/lhasa.vcxproj =================================================================== --- trunk/OpenMPT/build/gen/lhasa.vcxproj 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/build/gen/lhasa.vcxproj 2014-09-23 07:11:50 UTC (rev 4303) @@ -330,6 +330,8 @@ </ClCompile> <ClCompile Include="..\..\include\lhasa\lib\lha_reader.c"> </ClCompile> + <ClCompile Include="..\..\include\lhasa\lib\lhx_decoder.c"> + </ClCompile> <ClCompile Include="..\..\include\lhasa\lib\lz5_decoder.c"> </ClCompile> <ClCompile Include="..\..\include\lhasa\lib\lzs_decoder.c"> Modified: trunk/OpenMPT/build/gen/lhasa.vcxproj.filters =================================================================== --- trunk/OpenMPT/build/gen/lhasa.vcxproj.filters 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/build/gen/lhasa.vcxproj.filters 2014-09-23 07:11:50 UTC (rev 4303) @@ -2,16 +2,16 @@ <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <Filter Include="include"> - <UniqueIdentifier>{A6F4B617-6322-F44E-A3F2-588A54F34CE3}</UniqueIdentifier> + <UniqueIdentifier>{5347F1AC-E81E-434A-80CF-594FD46C8AEB}</UniqueIdentifier> </Filter> <Filter Include="include\lhasa"> - <UniqueIdentifier>{CFC29837-5222-D84F-9D05-846E8F3C7DA0}</UniqueIdentifier> + <UniqueIdentifier>{2AA988BF-BBA8-5B47-BB82-345545624965}</UniqueIdentifier> </Filter> <Filter Include="include\lhasa\lib"> - <UniqueIdentifier>{5AEAA659-17AE-2C48-805E-72AA72560879}</UniqueIdentifier> + <UniqueIdentifier>{DCDB0AF6-FE6D-244E-BADF-36BCF126672E}</UniqueIdentifier> </Filter> <Filter Include="include\lhasa\lib\public"> - <UniqueIdentifier>{FAABDB2D-4E8E-B34A-9D32-B4EA00080BA7}</UniqueIdentifier> + <UniqueIdentifier>{1EFC59C9-1EE9-6F41-880B-EEC67B9934E4}</UniqueIdentifier> </Filter> </ItemGroup> <ItemGroup> @@ -101,6 +101,9 @@ <ClCompile Include="..\..\include\lhasa\lib\lha_reader.c"> <Filter>include\lhasa\lib</Filter> </ClCompile> + <ClCompile Include="..\..\include\lhasa\lib\lhx_decoder.c"> + <Filter>include\lhasa\lib</Filter> + </ClCompile> <ClCompile Include="..\..\include\lhasa\lib\lz5_decoder.c"> <Filter>include\lhasa\lib</Filter> </ClCompile> Modified: trunk/OpenMPT/include/lhasa/NEWS =================================================================== --- trunk/OpenMPT/include/lhasa/NEWS 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/NEWS 2014-09-23 07:11:50 UTC (rev 4303) @@ -1,4 +1,16 @@ +v0.2.0 (2013-08-04): + * Decompression of archives using the -lhx- file format supported by + unlha32.dll is now supported (thanks Multi for the patch). + * The -p (print to stdout) command line option is now supported. + * The test suite should now run correctly on Windows. + + Bugs fixed: + * Bug where archives read from pipes (eg. stdin) were not extracted + beyond the first file in the archive. + * Output when using the -w (extract directory) option now correctly + matches the output of Unix lha. + v0.1.0 (2013-03-16): * There are now test archives for OS-9 and OS-9/68k (OSK) and a Modified: trunk/OpenMPT/include/lhasa/OpenMPT.txt =================================================================== --- trunk/OpenMPT/include/lhasa/OpenMPT.txt 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/OpenMPT.txt 2014-09-23 07:11:50 UTC (rev 4303) @@ -1,4 +1,5 @@ -lhasa LHA decompression library from https://github.com/fragglet/lhasa commit 13b44ac7859aad2f2b4fa76600c186f9f7f98c63 as of 2013-06-16. -No local changes made. +lhasa LHA decompression library from https://github.com/fragglet/lhasa commit ab4ae51c0b6eb3b291f9c54f4a7d2e6d883bdca4 as of 2014-07-12. +The test directory is not included in the OpenMPT repository. +No further local changes have been made. For building, premake4 is used to generate Visual Studio project files. See ../premake4.lua for details. Modified: trunk/OpenMPT/include/lhasa/TODO =================================================================== --- trunk/OpenMPT/include/lhasa/TODO 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/TODO 2014-09-23 07:11:50 UTC (rev 4303) @@ -12,7 +12,7 @@ * Decompressors for obscure algorithms: * -lh2-, -lh3- (experimental LHA?) * LHark -lh7- (modified -lh5-) - * -lx1-, -lhx- (unlha32 obscure/experimental?) + * -lx1- (unlha32 obscure/experimental?) Command line tool: * Create/update/modify archives. Modified: trunk/OpenMPT/include/lhasa/configure.ac =================================================================== --- trunk/OpenMPT/include/lhasa/configure.ac 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/configure.ac 2014-09-23 07:11:50 UTC (rev 4303) @@ -1,4 +1,4 @@ -AC_INIT(Lhasa, 0.1.0, fr...@gm..., lhasa) +AC_INIT(Lhasa, 0.2.0, fr...@gm..., lhasa) AC_CONFIG_AUX_DIR(autotools) AM_INIT_AUTOMAKE([no-define]) Modified: trunk/OpenMPT/include/lhasa/lib/Makefile.am =================================================================== --- trunk/OpenMPT/include/lhasa/lib/Makefile.am 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/lib/Makefile.am 2014-09-23 07:11:50 UTC (rev 4303) @@ -26,6 +26,7 @@ lh5_decoder.c \ lh6_decoder.c \ lh7_decoder.c \ + lhx_decoder.c \ lz5_decoder.c \ lzs_decoder.c \ pm1_decoder.c \ Modified: trunk/OpenMPT/include/lhasa/lib/lh_new_decoder.c =================================================================== --- trunk/OpenMPT/include/lhasa/lib/lh_new_decoder.c 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/lib/lh_new_decoder.c 2014-09-23 07:11:50 UTC (rev 4303) @@ -60,7 +60,7 @@ // Number of possible codes in the "temporary table" used to encode the // codes table. -#define MAX_TEMP_CODES 19 +#define MAX_TEMP_CODES 20 typedef struct { // Input bit stream. Modified: trunk/OpenMPT/include/lhasa/lib/lha_arch.h =================================================================== --- trunk/OpenMPT/include/lhasa/lib/lha_arch.h 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/lib/lha_arch.h 2014-09-23 07:11:50 UTC (rev 4303) @@ -144,15 +144,6 @@ LHAFileType lha_arch_exists(char *filename); /** - * Change to the specified directory. - * - * @param path Path to change to. - * @return Non-zero for success. - */ - -int lha_arch_chdir(char *path); - -/** * Create a symbolic link. * * If a file already exists at the location of the link to be created, it is Modified: trunk/OpenMPT/include/lhasa/lib/lha_arch_unix.c =================================================================== --- trunk/OpenMPT/include/lhasa/lib/lha_arch_unix.c 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/lib/lha_arch_unix.c 2014-09-23 07:11:50 UTC (rev 4303) @@ -163,11 +163,6 @@ } } -int lha_arch_chdir(char *path) -{ - return chdir(path) == 0; -} - int lha_arch_symlink(char *path, char *target) { unlink(path); Modified: trunk/OpenMPT/include/lhasa/lib/lha_arch_win32.c =================================================================== --- trunk/OpenMPT/include/lhasa/lib/lha_arch_win32.c 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/lib/lha_arch_win32.c 2014-09-23 07:11:50 UTC (rev 4303) @@ -194,11 +194,6 @@ return LHA_FILE_NONE; } -int lha_arch_chdir(char *path) -{ - return SetCurrentDirectoryA(path) != 0; -} - int lha_arch_symlink(char *path, char *target) { // No-op. Modified: trunk/OpenMPT/include/lhasa/lib/lha_decoder.c =================================================================== --- trunk/OpenMPT/include/lhasa/lib/lha_decoder.c 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/lib/lha_decoder.c 2014-09-23 07:11:50 UTC (rev 4303) @@ -38,6 +38,7 @@ extern LHADecoderType lha_lh5_decoder; extern LHADecoderType lha_lh6_decoder; extern LHADecoderType lha_lh7_decoder; +extern LHADecoderType lha_lhx_decoder; // PMarc compression algorithms: extern LHADecoderType lha_pm1_decoder; @@ -56,6 +57,7 @@ { "-lh5-", &lha_lh5_decoder }, { "-lh6-", &lha_lh6_decoder }, { "-lh7-", &lha_lh7_decoder }, + { "-lhx-", &lha_lhx_decoder }, { "-pm0-", &lha_null_decoder }, { "-pm1-", &lha_pm1_decoder }, { "-pm2-", &lha_pm2_decoder }, Modified: trunk/OpenMPT/include/lhasa/lib/lha_input_stream.c =================================================================== --- trunk/OpenMPT/include/lhasa/lib/lha_input_stream.c 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/lib/lha_input_stream.c 2014-09-23 07:11:50 UTC (rev 4303) @@ -328,6 +328,16 @@ { int result; + // If this is an unseekable stream of some kind, always use the + // fallback behavior, as at least this is guaranteed to work. + // This is to work around problems on Windows, where fseek() can + // seek half-way on a stream and *then* fail, leaving us in an + // unworkable situation. + + if (ftell(handle) < 0) { + return file_source_skip_fallback(handle, bytes); + } + result = fseek(handle, (long) bytes, SEEK_CUR); if (result < 0) { Added: trunk/OpenMPT/include/lhasa/lib/lhx_decoder.c =================================================================== --- trunk/OpenMPT/include/lhasa/lib/lhx_decoder.c (rev 0) +++ trunk/OpenMPT/include/lhasa/lib/lhx_decoder.c 2014-09-23 07:11:50 UTC (rev 4303) @@ -0,0 +1,45 @@ +/* + +Copyright (c) 2011, 2012, 2013, Simon Howard + +Permission to use, copy, modify, and/or distribute this software +for any purpose with or without fee is hereby granted, provided +that the above copyright notice and this permission notice appear +in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + */ + +// +// Decoder for the -lhx- algorithm. Provided by Multi. +// +// -lhx- is Unlha32.dll's original extension. Some unique archivers +// support it. +// + +// 128 KiB history ring buffer: +// -lhx-'s maximum dictionary size is 2^19. 2x ring buffer is required. + +#define HISTORY_BITS 20 /* 2^20 = 1048576. */ + +// Number of bits to encode HISTORY_BITS: + +#define OFFSET_BITS 5 + +// Name of the variable for the encoder: + +#define DECODER_NAME lha_lhx_decoder + +// The actual algorithm code is contained in lh_new_decoder.c, which +// acts as a template for -lh4-, -lh5-, -lh6-, -lh7- and -lhx-. + +#include "lh_new_decoder.c" + Property changes on: trunk/OpenMPT/include/lhasa/lib/lhx_decoder.c ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/x-csrc \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Modified: trunk/OpenMPT/include/lhasa/lib/pm1_decoder.c =================================================================== --- trunk/OpenMPT/include/lhasa/lib/pm1_decoder.c 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/lib/pm1_decoder.c 2014-09-23 07:11:50 UTC (rev 4303) @@ -73,6 +73,12 @@ // History linked list, for adaptively encoding byte values. HistoryLinkedList history_list; + + // Callback to read more compressed data from the input (see + // read_callback_wrapper below). + + LHADecoderCallback callback; + void *callback_data; } LHAPM1Decoder; // Table used to decode distance into history buffer to copy data. @@ -166,15 +172,42 @@ { 0x00 }, // -- special entry: 0, no tree }; +// Wrapper function invoked to read more data from the input. This mostly just +// calls the real function that does the read. However, when the end of file +// is reached, instead of returning zero, the buffer is filled with zero bytes +// instead. There seem to be archive files that actually depend on this +// ability to read "beyond" the length of the compressed data. + +static size_t read_callback_wrapper(void *buf, size_t buf_len, void *user_data) +{ + LHAPM1Decoder *decoder = user_data; + size_t result; + + result = decoder->callback(buf, buf_len, decoder->callback_data); + + if (result == 0) { + memset(buf, 0, buf_len); + result = buf_len; + } + + return result; +} + static int lha_pm1_init(void *data, LHADecoderCallback callback, - void *callback_data) + void *callback_data) { LHAPM1Decoder *decoder = data; memset(decoder, 0, sizeof(LHAPM1Decoder)); + // Unlike other decoders, the bitstream code must call the wrapper + // function above to read data. + + decoder->callback = callback; + decoder->callback_data = callback_data; + bit_stream_reader_init(&decoder->bit_stream_reader, - callback, callback_data); + read_callback_wrapper, decoder); decoder->output_stream_pos = 0; decoder->byte_decode_tree = NULL; @@ -663,10 +696,6 @@ command_type = read_bit(&decoder->bit_stream_reader); - if (command_type < 0) { - return 0; - } - if (command_type == 0) { return read_copy_command(decoder, buf); } else { Modified: trunk/OpenMPT/include/lhasa/pkg/win32/GNUmakefile =================================================================== --- trunk/OpenMPT/include/lhasa/pkg/win32/GNUmakefile 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/pkg/win32/GNUmakefile 2014-09-23 07:11:50 UTC (rev 4303) @@ -3,7 +3,7 @@ TOPLEVEL=../.. -EXE_FILES=$(TOPLEVEL)/src/.libs/lha.exe +EXE_FILES=$(TOPLEVEL)/src/lha.exe ZIP=$(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-win32.zip Modified: trunk/OpenMPT/include/lhasa/pkg/win32/README =================================================================== --- trunk/OpenMPT/include/lhasa/pkg/win32/README 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/pkg/win32/README 2014-09-23 07:11:50 UTC (rev 4303) @@ -2,3 +2,8 @@ Makefile to build Windows packages. Requires zip and unix2dos cygwin packages to be installed. +The configure script should be run with the right options to disable +shared libraries: + + ./configure --disable-shared --enable-static + Modified: trunk/OpenMPT/include/lhasa/src/args.txt =================================================================== --- trunk/OpenMPT/include/lhasa/src/args.txt 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/src/args.txt 2014-09-23 07:11:50 UTC (rev 4303) @@ -7,6 +7,7 @@ e/x - Extract l/v - List (normal / verbose mode) t - Test CRC + p - Print files to STDOUT Options - flags following the mode character. Options are accepted even if they are inappropriate for the mode, eg. "lha lf". @@ -23,6 +24,9 @@ in test mode, behavior is similar to extract mode, but level 2 behavior is similar to level 0. + in print mode, at quiet level 2 the filename is not + printed before the file contents. + all quiet modes imply 'f', disabling overwrite without confirmation. @@ -49,6 +53,9 @@ Also applies to test mode - the output filename of the tested file does not include the directory. + In print mode, the path is not printed in the header + before each file. + v - Verbose mode, prints extra information. in list mode, verbose mode splits the filename onto a Modified: trunk/OpenMPT/include/lhasa/src/extract.c =================================================================== --- trunk/OpenMPT/include/lhasa/src/extract.c 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/src/extract.c 2014-09-23 07:11:50 UTC (rev 4303) @@ -53,6 +53,10 @@ len = 0; + if (options->extract_path != NULL) { + len += strlen(options->extract_path) + 1; + } + if (options->use_path && header->path != NULL) { len += strlen(header->path); } @@ -70,30 +74,38 @@ result[0] = '\0'; - if (options->use_path && header->path != NULL) { - strcat(result, header->path); + if (options->extract_path != NULL) { + strcat(result, options->extract_path); + strcat(result, "/"); } - if (header->filename != NULL) { - strcat(result, header->filename); + // Add path. If it is an absolute path (contains a leading '/') + // then skip over the leading '/' to make it a relative path. + // This prevents the possibility of a security threat with a + // malicious archive that might try to write to arbitrary + // filesystem locations. + // It also removes the double '/' when using the -w option. + + if (options->use_path && header->path != NULL) { + p = header->path; + while (*p == '/') { + ++p; + } + strcat(result, p); } - // If the header contains leading '/' characters, it is an - // absolute path (eg. /etc/passwd). Strip these leading - // characters to always generate a relative path, otherwise - // it can be a security risk - extracting an archive might - // overwrite arbitrary files on the filesystem. + // The filename header field might conceivably try to include + // a path separator as well, so skip over any leading '/' + // here too. - p = result; - - while (*p == '/') { - ++p; + if (header->filename != NULL) { + p = header->filename; + while (*p == '/') { + ++p; + } + strcat(result, p); } - if (p > result) { - memmove(result, p, strlen(p) + 1); - } - return result; } @@ -163,6 +175,14 @@ fflush(stdout); } +// Print a line to stdout describing a symlink. + +static void print_symlink_line(char *src, char *dest) +{ + safe_printf("Symbolic Link %s -> %s", src, dest); + printf("\n"); +} + // Perform CRC check of an archived file. static int test_archived_file_crc(LHAReader *reader, @@ -254,63 +274,58 @@ return 1; } -// Given a file header, create its parent directories as necessary. -// If include_final is zero, the final directory in the path is not -// created. +// Given a filename, create its parent directories as necessary. -static int make_parent_directories(char *orig_path, int include_final) +static int make_parent_directories(char *orig_path) { int result; char *p; char *path; - char saved = 0; result = 1; + + // Duplicate the path and strip off any trailing '/'s: + path = strdup(orig_path); + if (path == NULL) { + exit(-1); + } + + p = path + strlen(path) - 1; + + while (p >= path && *p == '/') { + *p = '\0'; + --p; + } + // Iterate through the string, finding each path separator. At // each place, temporarily chop off the end of the path to get // each parent directory in turn. - p = path; + for (p = path; *p == '/'; ++p); - do { + for (;;) { p = strchr(p, '/'); - // Terminate string after the path separator. - - if (p != NULL) { - saved = *(p + 1); - *(p + 1) = '\0'; + if (p == NULL) { + break; } - // Check if this parent directory exists and create it; - // however, don't create the final directory in the path - // if include_final is false. This is used for handling - // directories, where we should only create missing - // parent directories - not the directory itself. - // eg. for: - // - // -lhd- subdir/subdir2/ - // - // Only create subdir/ - subdir/subdir2/ is created - // by the call to lha_reader_extract. + *p = '\0'; - if (include_final || strcmp(orig_path, path) != 0) { - if (!check_parent_directory(path)) { - result = 0; - break; - } + // Check if this parent directory exists and create it: + + if (!check_parent_directory(path)) { + result = 0; + break; } - // Restore character that was after the path separator - // and advance to the next path. + // Restore path separator and advance to the next path. - if (p != NULL) { - *(p + 1) = saved; - ++p; - } - } while (p != NULL); + *p = '/'; + ++p; + } free(path); @@ -413,7 +428,6 @@ LHAOptions *options) { ProgressCallbackData progress; - char *path; char *filename; int success; int is_dir, is_symlink; @@ -423,30 +437,6 @@ is_dir = !strcmp(header->compress_method, LHA_COMPRESS_TYPE_DIR) && !is_symlink; - // Print appropriate message and stop if we are performing a dry run. - // The message if we have an existing file is weird, but this is just - // accurately duplicating what the Unix LHA tool says. - // The symlink handling is particularly odd - they are treated as - // directories (a bleed-through of the way in which symlinks are - // stored). - - if (options->dry_run) { - if (is_dir) { - safe_printf("EXTRACT %s (directory)", filename); - } else if (header->symlink_target != NULL) { - safe_printf("EXTRACT %s|%s (directory)", - filename, header->symlink_target); - } else if (file_exists(filename)) { - safe_printf("EXTRACT %s but file is exist.", filename); - } else { - safe_printf("EXTRACT %s", filename); - } - printf("\n"); - - free(filename); - return 1; - } - // If a file already exists with this name, confirm overwrite. if (!is_dir && !is_symlink && file_exists(filename) @@ -467,17 +457,9 @@ // Create parent directories for file: - if (options->use_path && header->path != NULL) { - path = header->path; - - while (path[0] == '/') { - ++path; - } - - if (*path != '\0' && !make_parent_directories(path, !is_dir)) { - free(filename); - return 0; - } + if (!make_parent_directories(filename)) { + free(filename); + return 0; } progress.invoked = 0; @@ -499,9 +481,7 @@ printf("\n"); } } else if (is_symlink) { - safe_printf("Symbolic Link %s -> %s", filename, - header->symlink_target); - printf("\n"); + print_symlink_line(filename, header->symlink_target); } fflush(stdout); @@ -541,29 +521,65 @@ return result; } -// lha -e / -x +// lha -en / -xn / -pn: +// Simulate extracting an archive file, but just print the operations +// that would have been performed to stdout. -int extract_archive(LHAFilter *filter, LHAOptions *options) +static int extract_archive_dry_run(LHAFilter *filter, LHAOptions *options) { + char *filename; int result; - // Change directory before extract? (-w option). + result = 1; - if (options->extract_path != NULL) { - if (!make_parent_directories(options->extract_path, 1)) { - fprintf(stderr, - "Failed to create extract directory: %s.\n", - options->extract_path); - exit(-1); + for (;;) { + LHAFileHeader *header; + + header = lha_filter_next_file(filter); + + if (header == NULL) { + break; } - if (!lha_arch_chdir(options->extract_path)) { - fprintf(stderr, "Failed to change directory to %s.\n", - options->extract_path); - exit(-1); + filename = file_full_path(header, options); + + // Every line begins the same - "EXTRACT filename..." + + safe_printf("EXTRACT %s", filename); + + // After the filename we might print something extra. + // The message if we have an existing file is weird, but this + // is just accurately duplicating what the Unix LHA tool says. + // The symlink handling is particularly odd - they are treated + // as directories (a bleed-through of the way in which + // symlinks are stored). + + if (header->symlink_target != NULL) { + safe_printf("|%s (directory)", header->symlink_target); + } else if (!strcmp(header->compress_method, + LHA_COMPRESS_TYPE_DIR)) { + safe_printf(" (directory)"); + } else if (file_exists(filename)) { + safe_printf(" but file is exist."); } + printf("\n"); + + free(filename); } + return result; +} + +// lha -e / -x + +int extract_archive(LHAFilter *filter, LHAOptions *options) +{ + int result; + + if (options->dry_run) { + return extract_archive_dry_run(filter, options); + } + result = 1; for (;;) { @@ -583,3 +599,78 @@ return result; } +// Dump contents of the current file from the specified reader to stdout. + +static int print_archived_file(LHAReader *reader) +{ + char buf[512]; + size_t bytes; + + for (;;) { + bytes = lha_reader_read(reader, buf, sizeof(buf)); + if (bytes <= 0) { + break; + } + + if (fwrite(buf, 1, bytes, stdout) < bytes) { + return 0; + } + } + + return 1; +} + +// lha -p + +int print_archive(LHAFilter *filter, LHAOptions *options) +{ + LHAFileHeader *header; + int is_normal_file; + char *full_path; + + // As a weird quirk of Unix LHA, lha -pn is equivalent to lha -en: + + if (options->dry_run) { + return extract_archive_dry_run(filter, options); + } + + for (;;) { + header = lha_filter_next_file(filter); + + if (header == NULL) { + break; + } + + is_normal_file = strcmp(header->compress_method, + LHA_COMPRESS_TYPE_DIR) != 0; + + // Print "header" before the file containing the filename. + // For normal files this is a three line separator. + // Symlinks get shown in the same way as during extract. + // Directories are ignored. + + if (options->quiet < 2) { + full_path = file_full_path(header, options); + + if (header->symlink_target != NULL) { + print_symlink_line(full_path, + header->symlink_target); + } else if (is_normal_file) { + printf("::::::::\n"); + safe_printf("%s", full_path); + printf("\n::::::::\n"); + } + + free(full_path); + } + + // If this is a normal file, dump the contents to stdout. + + if (is_normal_file && !print_archived_file(filter->reader)) { + return 0; + } + } + + return 1; +} + Modified: trunk/OpenMPT/include/lhasa/src/extract.h =================================================================== --- trunk/OpenMPT/include/lhasa/src/extract.h 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/src/extract.h 2014-09-23 07:11:50 UTC (rev 4303) @@ -26,6 +26,7 @@ int test_file_crc(LHAFilter *filter, LHAOptions *options); int extract_archive(LHAFilter *filter, LHAOptions *options); +int print_archive(LHAFilter *filter, LHAOptions *options); #endif /* #ifndef LHASA_EXTRACT_H */ Modified: trunk/OpenMPT/include/lhasa/src/main.c =================================================================== --- trunk/OpenMPT/include/lhasa/src/main.c 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/src/main.c 2014-09-23 07:11:50 UTC (rev 4303) @@ -35,7 +35,8 @@ MODE_LIST, MODE_LIST_VERBOSE, MODE_CRC_CHECK, - MODE_EXTRACT + MODE_EXTRACT, + MODE_PRINT } ProgramMode; static void help_page(char *progname) @@ -44,13 +45,13 @@ PACKAGE_NAME " v" PACKAGE_VERSION " command line LHA tool " "- Copyright (C) 2011,2012 Simon Howard\n" "usage: %s [-]{lvtxe[q{num}][finv]}[w=<dir>] archive_file [file...]\n" - "commands: options:\n" - " l,v List / Verbose List f Force overwrite (no prompt)\n" - " t Test file CRC in archive i Ignore directory path\n" - " x,e Extract from archive n Perform dry run\n" - " q{num} Quiet mode\n" - " v Verbose\n" - " w=<dir> Specify extract directory\n" + "commands: options:\n" + " l,v List / Verbose List f Force overwrite (no prompt)\n" + " t Test file CRC in archive i Ignore directory path\n" + " x,e Extract from archive n Perform dry run\n" + " p Print to stdout from archive q{num} Quiet mode\n" + " v Verbose\n" + " w=<dir> Specify extract directory\n" , progname); exit(-1); @@ -101,6 +102,10 @@ result = extract_archive(&filter, options); break; + case MODE_PRINT: + result = print_archive(&filter, options); + break; + case MODE_UNKNOWN: break; } @@ -138,6 +143,8 @@ case 'e': case 'x': return MODE_EXTRACT; + case 'p': + return MODE_PRINT; default: return MODE_UNKNOWN; } Modified: trunk/OpenMPT/include/premake4.lua =================================================================== --- trunk/OpenMPT/include/premake4.lua 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/premake4.lua 2014-09-23 07:11:50 UTC (rev 4303) @@ -249,6 +249,7 @@ "../include/lhasa/lib/lha_file_header.c", "../include/lhasa/lib/lha_input_stream.c", "../include/lhasa/lib/lha_reader.c", + "../include/lhasa/lib/lhx_decoder.c", "../include/lhasa/lib/lz5_decoder.c", "../include/lhasa/lib/lzs_decoder.c", "../include/lhasa/lib/macbinary.c", This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <man...@us...> - 2014-09-23 10:21:37
|
Revision: 4304 http://sourceforge.net/p/modplug/code/4304 Author: manxorist Date: 2014-09-23 10:21:29 +0000 (Tue, 23 Sep 2014) Log Message: ----------- [Mod] Soundcard settings: When changing between mono/stereo/quad channel configurations, always reset the channel mapping to default instead of basing the new one on the previous one. [Fix] sounddev: Add stricter validation of channel mapping. Modified Paths: -------------- trunk/OpenMPT/mptrack/Mpdlgs.cpp trunk/OpenMPT/sounddev/SoundDevice.cpp trunk/OpenMPT/sounddev/SoundDevice.h trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp Modified: trunk/OpenMPT/mptrack/Mpdlgs.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mpdlgs.cpp 2014-09-23 07:11:50 UTC (rev 4303) +++ trunk/OpenMPT/mptrack/Mpdlgs.cpp 2014-09-23 10:21:29 UTC (rev 4304) @@ -491,6 +491,11 @@ //-------------------------------------------- { int usedChannels = m_CbnChannels.GetItemData(m_CbnChannels.GetCurSel()); + if(!m_Settings.ChannelMapping.IsValid(usedChannels)) + { + // If the channel mapping is not valid for the selected number of channels, reset it to default identity mapping. + m_Settings.ChannelMapping = SoundDevice::ChannelMapping(); + } GetDlgItem(IDC_STATIC_CHANNELMAPPING)->EnableWindow(m_CurrentDeviceCaps.CanChannelMapping ? TRUE : FALSE); for(int mch = 0; mch < NUM_CHANNELCOMBOBOXES; mch++) // Host channels { Modified: trunk/OpenMPT/sounddev/SoundDevice.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.cpp 2014-09-23 07:11:50 UTC (rev 4303) +++ trunk/OpenMPT/sounddev/SoundDevice.cpp 2014-09-23 10:21:29 UTC (rev 4304) @@ -91,7 +91,7 @@ { return true; } - if(ChannelToDeviceChannel.size() < channels) + if(ChannelToDeviceChannel.size() != channels) { return false; } Modified: trunk/OpenMPT/sounddev/SoundDevice.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.h 2014-09-23 07:11:50 UTC (rev 4303) +++ trunk/OpenMPT/sounddev/SoundDevice.h 2014-09-23 10:21:29 UTC (rev 4304) @@ -183,12 +183,16 @@ bool IsValid(uint32 channels) const; // Get the number of required device channels for this mapping. Derived from the maximum mapped-to channel number. - uint32 GetRequiredDeviceChannels() const + uint32 GetRequiredDeviceChannels(uint32 numHostChannels) const { - if(ChannelToDeviceChannel.empty()) + if(!IsValid(numHostChannels)) { return 0; } + if(ChannelToDeviceChannel.empty()) + { + return numHostChannels; + } uint32 maxChannel = 0; for(uint32 channel = 0; channel < ChannelToDeviceChannel.size(); ++channel) { Modified: trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2014-09-23 07:11:50 UTC (rev 4303) +++ trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2014-09-23 10:21:29 UTC (rev 4304) @@ -272,8 +272,12 @@ { throw ASIOException("Not enough output channels."); } - if(m_Settings.ChannelMapping.GetRequiredDeviceChannels() > (std::size_t)outputChannels) + if(!m_Settings.ChannelMapping.IsValid(m_Settings.Channels)) { + throw ASIOException("Channel mapping has wrong channel count."); + } + if(m_Settings.ChannelMapping.GetRequiredDeviceChannels(m_Settings.Channels) > (std::size_t)outputChannels) + { throw ASIOException("Channel mapping requires more channels than available."); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <man...@us...> - 2014-09-24 07:28:27
|
Revision: 4305 http://sourceforge.net/p/modplug/code/4305 Author: manxorist Date: 2014-09-24 07:28:15 +0000 (Wed, 24 Sep 2014) Log Message: ----------- [Ref] sounddev: Rewrite class ChannelMapping to always guarantee the class invariant. Invalid objects can no longer be contructed and get replaced with the empty mapping instead. [Ref] sounddev: Class ChannelMapping now internally knows the number of host channels. [Fix] sounddev: There were cases where incorrect channel mappings were saved to the ini file. Detect those and revert to default identity mapping in that case. Modified Paths: -------------- trunk/OpenMPT/mptrack/Mpdlgs.cpp trunk/OpenMPT/mptrack/TrackerSettings.cpp trunk/OpenMPT/sounddev/SoundDevice.cpp trunk/OpenMPT/sounddev/SoundDevice.h trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp Modified: trunk/OpenMPT/mptrack/Mpdlgs.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mpdlgs.cpp 2014-09-23 10:21:29 UTC (rev 4304) +++ trunk/OpenMPT/mptrack/Mpdlgs.cpp 2014-09-24 07:28:15 UTC (rev 4305) @@ -491,7 +491,7 @@ //-------------------------------------------- { int usedChannels = m_CbnChannels.GetItemData(m_CbnChannels.GetCurSel()); - if(!m_Settings.ChannelMapping.IsValid(usedChannels)) + if(m_Settings.ChannelMapping.GetNumHostChannels() != static_cast<uint32>(usedChannels)) { // If the channel mapping is not valid for the selected number of channels, reset it to default identity mapping. m_Settings.ChannelMapping = SoundDevice::ChannelMapping(); @@ -514,7 +514,7 @@ { const int pos = (int)::SendMessageW(combo->m_hWnd, CB_ADDSTRING, 0, (LPARAM)m_CurrentDeviceDynamicCaps.channelNames[dch].c_str()); combo->SetItemData(pos, (DWORD_PTR)dch); - if(dch == m_Settings.ChannelMapping.ToDevice(mch)) + if(static_cast<int32>(dch) == m_Settings.ChannelMapping.ToDevice(mch)) { combo->SetCurSel(pos); } @@ -738,7 +738,7 @@ if(m_CurrentDeviceCaps.CanChannelMapping) { int numChannels = std::min<int>(m_Settings.Channels, NUM_CHANNELCOMBOBOXES); - std::vector<uint32> channels(numChannels); + std::vector<int32> channels(numChannels); for(int mch = 0; mch < numChannels; mch++) // Host channels { CComboBox *combo = &m_CbnChannelMapping[mch]; Modified: trunk/OpenMPT/mptrack/TrackerSettings.cpp =================================================================== --- trunk/OpenMPT/mptrack/TrackerSettings.cpp 2014-09-23 10:21:29 UTC (rev 4304) +++ trunk/OpenMPT/mptrack/TrackerSettings.cpp 2014-09-24 07:28:15 UTC (rev 4305) @@ -450,6 +450,11 @@ m_SoundDeviceSettingsDefaults.BoostThreadPriority = m_SoundDeviceBoostThreadPriority; m_SoundDeviceSettingsDefaults.UseHardwareTiming = m_SoundDeviceUseHardwareTiming; m_SoundDeviceSettingsDefaults.ChannelMapping = m_SoundDeviceChannelMapping; + if(m_SoundDeviceSettingsDefaults.ChannelMapping.GetNumHostChannels() != m_SoundDeviceSettingsDefaults.Channels) + { + // reset invalid channel mapping to default + m_SoundDeviceSettingsDefaults.ChannelMapping = SoundDevice::ChannelMapping(m_SoundDeviceSettingsDefaults.Channels); + } m_SoundDeviceSettingsUseOldDefaults = true; } if(storedVersion < MAKE_VERSION_NUMERIC(1,21,01,26)) @@ -599,6 +604,11 @@ , DitherType(conf, L"Sound Settings", deviceInfo.GetIdentifier() + L"_" + L"DitherType", defaults.DitherType) , ChannelMapping(conf, L"Sound Settings", deviceInfo.GetIdentifier() + L"_" + L"ChannelMapping", defaults.ChannelMapping) { + if(ChannelMapping.Get().GetNumHostChannels() != Channels) + { + // reset invalid chanel mapping to default + ChannelMapping = SoundDevice::ChannelMapping(Channels); + } // store informational data (not read back, just to allow the user to mock with the raw ini file) conf.Write(L"Sound Settings", deviceInfo.GetIdentifier() + L"_" + L"ID", deviceInfo.id); conf.Write(L"Sound Settings", deviceInfo.GetIdentifier() + L"_" + L"InternalID", deviceInfo.internalID); Modified: trunk/OpenMPT/sounddev/SoundDevice.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.cpp 2014-09-23 10:21:29 UTC (rev 4304) +++ trunk/OpenMPT/sounddev/SoundDevice.cpp 2014-09-24 07:28:15 UTC (rev 4305) @@ -58,23 +58,31 @@ } -ChannelMapping::ChannelMapping(const std::vector<uint32> &mapping) -//---------------------------------------------------------------- - : ChannelToDeviceChannel(mapping) +ChannelMapping::ChannelMapping(uint32 numHostChannels) +//---------------------------------------------------- { - return; + ChannelToDeviceChannel.resize(numHostChannels); + for(uint32 channel = 0; channel < numHostChannels; ++channel) + { + ChannelToDeviceChannel[channel] = channel; + } } -ChannelMapping ChannelMapping::BaseChannel(uint32 channels, uint32 baseChannel) -//----------------------------------------------------------------------------- +ChannelMapping::ChannelMapping(const std::vector<int32> &mapping) +//--------------------------------------------------------------- { - SoundDevice::ChannelMapping result; - result.ChannelToDeviceChannel.clear(); - if(baseChannel == 0) + if(IsValid(mapping)) { - return result; + ChannelToDeviceChannel = mapping; } +} + + +ChannelMapping ChannelMapping::BaseChannel(uint32 channels, int32 baseChannel) +//---------------------------------------------------------------------------- +{ + SoundDevice::ChannelMapping result; result.ChannelToDeviceChannel.resize(channels); for(uint32 channel = 0; channel < channels; ++channel) { @@ -84,24 +92,29 @@ } -bool ChannelMapping::IsValid(uint32 channels) const -//------------------------------------------------- +bool ChannelMapping::IsValid(const std::vector<int32> &mapping) +//------------------------------------------------------------- { - if(ChannelToDeviceChannel.empty()) + if(mapping.empty()) { return true; } - if(ChannelToDeviceChannel.size() != channels) + std::map<int32, uint32> inverseMapping; + for(uint32 hostChannel = 0; hostChannel < mapping.size(); ++hostChannel) { - return false; + int32 deviceChannel = mapping[hostChannel]; + if(deviceChannel < 0) + { + return false; + } + if(deviceChannel > MaxDeviceChannel) + { + return false; + } + inverseMapping[deviceChannel] = hostChannel; } - std::map<uint32, uint32> inverseMapping; - for(uint32 channel = 0; channel < channels; ++channel) + if(inverseMapping.size() != mapping.size()) { - inverseMapping[ChannelToDeviceChannel[channel]] = channel; - } - if(inverseMapping.size() != channels) - { return false; } return true; @@ -111,14 +124,14 @@ std::string ChannelMapping::ToString() const //------------------------------------------ { - return mpt::String::Combine<uint32>(ChannelToDeviceChannel); + return mpt::String::Combine<int32>(ChannelToDeviceChannel); } ChannelMapping ChannelMapping::FromString(const std::string &str) //--------------------------------------------------------------- { - return SoundDevice::ChannelMapping(mpt::String::Split<uint32>(str)); + return SoundDevice::ChannelMapping(mpt::String::Split<int32>(str)); } @@ -235,9 +248,20 @@ if(m_Settings.UpdateInterval == 0.0) m_Settings.UpdateInterval = m_Caps.DefaultSettings.UpdateInterval; m_Settings.Latency = Clamp(m_Settings.Latency, m_Caps.LatencyMin, m_Caps.LatencyMax); m_Settings.UpdateInterval = Clamp(m_Settings.UpdateInterval, m_Caps.UpdateIntervalMin, m_Caps.UpdateIntervalMax); - if(!m_Settings.ChannelMapping.IsValid(m_Settings.Channels)) + if(m_Caps.CanChannelMapping) { - return false; + if(m_Settings.ChannelMapping.GetNumHostChannels() == 0) + { + // default mapping + m_Settings.ChannelMapping = SoundDevice::ChannelMapping(m_Settings.Channels); + } + if(m_Settings.ChannelMapping.GetNumHostChannels() != m_Settings.Channels) + { + return false; + } + } else + { + m_Settings.ChannelMapping = SoundDevice::ChannelMapping(m_Settings.Channels); } m_Flags = SoundDevice::Flags(); m_BufferAttributes.Latency = m_Settings.Latency; Modified: trunk/OpenMPT/sounddev/SoundDevice.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.h 2014-09-23 10:21:29 UTC (rev 4304) +++ trunk/OpenMPT/sounddev/SoundDevice.h 2014-09-24 07:28:15 UTC (rev 4305) @@ -159,41 +159,52 @@ private: - std::vector<uint32> ChannelToDeviceChannel; + std::vector<int32> ChannelToDeviceChannel; public: - // Construct default identity mapping + static const int32 MaxDeviceChannel = 32000; + +public: + + // Construct default empty mapping ChannelMapping(); + // Construct default identity mapping + ChannelMapping(uint32 numHostChannels); + // Construct mapping from given vector. - ChannelMapping(const std::vector<uint32> &mapping); + // Silently fall back to identity mapping if mapping is invalid. + ChannelMapping(const std::vector<int32> &mapping); // Construct mapping for #channels with a baseChannel offset. - static ChannelMapping BaseChannel(uint32 channels, uint32 baseChannel); + static ChannelMapping BaseChannel(uint32 channels, int32 baseChannel); +private: + + // check that the channel mapping is actually a 1:1 mapping + static bool IsValid(const std::vector<int32> &mapping); + public: bool operator == (const SoundDevice::ChannelMapping &cmp) const { return (ChannelToDeviceChannel == cmp.ChannelToDeviceChannel); } - - // check that the channel mapping is actually a 1:1 mapping - bool IsValid(uint32 channels) const; - + + uint32 GetNumHostChannels() const + { + return ChannelToDeviceChannel.size(); + } + // Get the number of required device channels for this mapping. Derived from the maximum mapped-to channel number. - uint32 GetRequiredDeviceChannels(uint32 numHostChannels) const + int32 GetRequiredDeviceChannels() const { - if(!IsValid(numHostChannels)) + if(ChannelToDeviceChannel.empty()) { return 0; } - if(ChannelToDeviceChannel.empty()) - { - return numHostChannels; - } - uint32 maxChannel = 0; + int32 maxChannel = 0; for(uint32 channel = 0; channel < ChannelToDeviceChannel.size(); ++channel) { if(ChannelToDeviceChannel[channel] > maxChannel) @@ -205,12 +216,8 @@ } // Convert OpenMPT channel number to the mapped device channel number. - uint32 ToDevice(uint32 channel) const + int32 ToDevice(uint32 channel) const { - if(ChannelToDeviceChannel.empty()) - { - return channel; - } if(channel >= ChannelToDeviceChannel.size()) { return channel; Modified: trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2014-09-23 10:21:29 UTC (rev 4304) +++ trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2014-09-24 07:28:15 UTC (rev 4305) @@ -272,12 +272,8 @@ { throw ASIOException("Not enough output channels."); } - if(!m_Settings.ChannelMapping.IsValid(m_Settings.Channels)) + if(m_Settings.ChannelMapping.GetRequiredDeviceChannels() > outputChannels) { - throw ASIOException("Channel mapping has wrong channel count."); - } - if(m_Settings.ChannelMapping.GetRequiredDeviceChannels(m_Settings.Channels) > (std::size_t)outputChannels) - { throw ASIOException("Channel mapping requires more channels than available."); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <man...@us...> - 2014-09-24 07:33:36
|
Revision: 4306 http://sourceforge.net/p/modplug/code/4306 Author: manxorist Date: 2014-09-24 07:33:28 +0000 (Wed, 24 Sep 2014) Log Message: ----------- [Fix] ASIO: If the corresponding soundcard is currently unavailable, some ASIO drivers allow opening the driver and report zero input and output channels in that case. Other driver do not support loading the driver at all in that case. In both cases, OpenMPT will now disallow selecting the driver in the setup dialog and hide it until restartet or the sound devices get rescanned. This avoids confusion in particular for the case where 0 channels get reported, which until now had the chance of corrupting the channel mapping. Modified Paths: -------------- trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mpdlgs.cpp trunk/OpenMPT/sounddev/SoundDevice.cpp trunk/OpenMPT/sounddev/SoundDevice.h trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2014-09-24 07:28:15 UTC (rev 4305) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2014-09-24 07:33:28 UTC (rev 4306) @@ -836,7 +836,14 @@ SoundDevice::Settings deviceSettings = TrackerSettings::Instance().GetSoundDeviceSettings(deviceID); if(!gpSoundDevice->Open(deviceSettings)) { - Reporting::Error("Unable to open sound device: Could not open sound device."); + if(!gpSoundDevice->IsAvailable()) + { + theApp.GetSoundDevicesManager()->SetDeviceUnavailable(deviceID); + Reporting::Error("Unable to open sound device: Device not available."); + } else + { + Reporting::Error("Unable to open sound device: Could not open sound device."); + } return false; } SampleFormat actualSampleFormat = gpSoundDevice->GetActualSampleFormat(); Modified: trunk/OpenMPT/mptrack/Mpdlgs.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mpdlgs.cpp 2014-09-24 07:28:15 UTC (rev 4305) +++ trunk/OpenMPT/mptrack/Mpdlgs.cpp 2014-09-24 07:33:28 UTC (rev 4306) @@ -157,7 +157,21 @@ , m_CurrentDeviceDynamicCaps(theApp.GetSoundDevicesManager()->GetDeviceDynamicCaps(dev, TrackerSettings::Instance().GetSampleRates(), CMainFrame::GetMainFrame(), CMainFrame::GetMainFrame()->gpSoundDevice, true)) , m_Settings(TrackerSettings::Instance().GetSoundDeviceSettings(dev)) { - return; + if(theApp.GetSoundDevicesManager()->IsDeviceUnavailable(dev)) + { + Reporting::Information("Device not availble. Reverting to default device."); + // if the device is unavailable, use the default device + SoundDevice::ID newdev = theApp.GetSoundDevicesManager()->FindDeviceInfoBestMatch(std::wstring()).id; + if(newdev != dev) + { + Reporting::Information("Device not availble. Reverting to default device."); + SetDevice(newdev); + UpdateEverything(); + } else + { + Reporting::Warning("Device not availble."); + } + } } @@ -172,6 +186,20 @@ { m_Settings = TrackerSettings::Instance().GetSoundDeviceSettings(dev); } + if(theApp.GetSoundDevicesManager()->IsDeviceUnavailable(dev)) + { + // if the device is unavailable, use the default device + SoundDevice::ID newdev = theApp.GetSoundDevicesManager()->FindDeviceInfoBestMatch(std::wstring()).id; + if(newdev != dev) + { + Reporting::Information("Device not availble. Reverting to default device."); + SetDevice(newdev); + UpdateEverything(); + } else + { + Reporting::Warning("Device not availble."); + } + } } @@ -314,7 +342,12 @@ } } + if(theApp.GetSoundDevicesManager()->IsDeviceUnavailable(it->id)) { + continue; + } + + { CString name = mpt::ToCString(it->name); cbi.mask = CBEIF_IMAGE | CBEIF_LPARAM | CBEIF_TEXT | CBEIF_SELECTEDIMAGE | CBEIF_OVERLAY; cbi.iItem = iItem; Modified: trunk/OpenMPT/sounddev/SoundDevice.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.cpp 2014-09-24 07:28:15 UTC (rev 4305) +++ trunk/OpenMPT/sounddev/SoundDevice.cpp 2014-09-24 07:33:28 UTC (rev 4306) @@ -148,6 +148,8 @@ , m_InternalID(internalID) { + m_DeviceUnavailableOnOpen = false; + m_BufferAttributes.Latency = m_Settings.Latency; m_BufferAttributes.UpdateInterval = m_Settings.UpdateInterval; m_BufferAttributes.NumBuffers = 0; @@ -264,6 +266,7 @@ m_Settings.ChannelMapping = SoundDevice::ChannelMapping(m_Settings.Channels); } m_Flags = SoundDevice::Flags(); + m_DeviceUnavailableOnOpen = false; m_BufferAttributes.Latency = m_Settings.Latency; m_BufferAttributes.UpdateInterval = m_Settings.UpdateInterval; m_BufferAttributes.NumBuffers = 0; @@ -451,7 +454,9 @@ //------------------------- { m_SoundDevices.clear(); + m_DeviceUnavailable.clear(); m_DeviceCaps.clear(); + m_DeviceDynamicCaps.clear(); #ifndef NO_PORTAUDIO SndDevPortaudioUnnitialize(); @@ -566,7 +571,7 @@ } if(identifier.empty()) { - return m_SoundDevices[0]; + return *begin(); } for(std::vector<SoundDevice::Info>::const_iterator it = begin(); it != end(); ++it) { @@ -643,6 +648,9 @@ if(dummy) { m_DeviceCaps[id] = dummy->GetDeviceCaps(); + } else + { + SetDeviceUnavailable(id); } delete dummy; } @@ -659,6 +667,10 @@ if(currentSoundDevice && FindDeviceInfo(id).IsValid() && (currentSoundDevice->GetDeviceID() == id) && (currentSoundDevice->GetDeviceInternalID() == FindDeviceInfo(id).internalID)) { m_DeviceDynamicCaps[id] = currentSoundDevice->GetDeviceDynamicCaps(baseSampleRates); + if(!currentSoundDevice->IsAvailable()) + { + SetDeviceUnavailable(id); + } } else { SoundDevice::IBase *dummy = CreateSoundDevice(id); @@ -666,6 +678,13 @@ { dummy->SetMessageReceiver(messageReceiver); m_DeviceDynamicCaps[id] = dummy->GetDeviceDynamicCaps(baseSampleRates); + if(!dummy->IsAvailable()) + { + SetDeviceUnavailable(id); + } + } else + { + SetDeviceUnavailable(id); } delete dummy; } Modified: trunk/OpenMPT/sounddev/SoundDevice.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.h 2014-09-24 07:28:15 UTC (rev 4305) +++ trunk/OpenMPT/sounddev/SoundDevice.h 2014-09-24 07:33:28 UTC (rev 4306) @@ -438,6 +438,7 @@ virtual bool IsInited() const = 0; virtual bool IsOpen() const = 0; + virtual bool IsAvailable() const = 0; virtual bool IsPlaying() const = 0; virtual bool OnIdle() = 0; // return true if any work has been done @@ -485,6 +486,7 @@ SoundDevice::Settings m_Settings; SoundDevice::Flags m_Flags; + bool m_DeviceUnavailableOnOpen; private: @@ -572,6 +574,7 @@ bool IsInited() const { return m_Caps.Available; } bool IsOpen() const { return IsInited() && InternalIsOpen(); } + bool IsAvailable() const { return m_Caps.Available && !m_DeviceUnavailableOnOpen; } bool IsPlaying() const { return m_IsPlaying; } virtual bool OnIdle() { return false; } @@ -648,6 +651,7 @@ { private: std::vector<SoundDevice::Info> m_SoundDevices; + std::map<SoundDevice::ID, bool> m_DeviceUnavailable; std::map<SoundDevice::ID, SoundDevice::Caps> m_DeviceCaps; std::map<SoundDevice::ID, SoundDevice::DynamicCaps> m_DeviceDynamicCaps; @@ -669,6 +673,9 @@ bool OpenDriverSettings(SoundDevice::ID id, SoundDevice::IMessageReceiver *messageReceiver = nullptr, SoundDevice::IBase *currentSoundDevice = nullptr); + void SetDeviceUnavailable(SoundDevice::ID id) { m_DeviceUnavailable[id] = true; } + bool IsDeviceUnavailable(SoundDevice::ID id) { return m_DeviceUnavailable[id]; } + SoundDevice::Caps GetDeviceCaps(SoundDevice::ID id, SoundDevice::IBase *currentSoundDevice = nullptr); SoundDevice::DynamicCaps GetDeviceDynamicCaps(SoundDevice::ID id, const std::vector<uint32> &baseSampleRates, SoundDevice::IMessageReceiver *messageReceiver = nullptr, SoundDevice::IBase *currentSoundDevice = nullptr, bool update = false); Modified: trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2014-09-24 07:28:15 UTC (rev 4305) +++ trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2014-09-24 07:33:28 UTC (rev 4306) @@ -268,6 +268,11 @@ long outputChannels = 0; asioCall(getChannels(&inputChannels, &outputChannels)); Log(mpt::String::Print("ASIO: getChannels() => inputChannels=%1 outputChannel=%2", inputChannels, outputChannels)); + if(inputChannels <= 0 && outputChannels <= 0) + { + m_DeviceUnavailableOnOpen = true; + throw ASIOException("Device unavailble."); + } if(m_Settings.Channels > outputChannels) { throw ASIOException("Not enough output channels."); @@ -1350,6 +1355,7 @@ TemporaryASIODriverOpener opener(*this); if(!IsDriverOpen()) { + m_DeviceUnavailableOnOpen = true; return caps; } @@ -1386,6 +1392,10 @@ long inputChannels = 0; long outputChannels = 0; asioCall(getChannels(&inputChannels, &outputChannels)); + if(!((inputChannels > 0) || (outputChannels > 0))) + { + m_DeviceUnavailableOnOpen = true; + } for(long i = 0; i < outputChannels; ++i) { ASIOChannelInfo channelInfo; @@ -1408,7 +1418,6 @@ { // continue } - return caps; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <man...@us...> - 2014-09-24 14:25:59
|
Revision: 4309 http://sourceforge.net/p/modplug/code/4309 Author: manxorist Date: 2014-09-24 14:25:52 +0000 (Wed, 24 Sep 2014) Log Message: ----------- [Ref] IT Compression: Convert from FILE* to std::ostream. [Ref] test: Avoid superfluous file i/o in IT compression tests. Modified Paths: -------------- trunk/OpenMPT/soundlib/ITCompression.cpp trunk/OpenMPT/soundlib/ITCompression.h trunk/OpenMPT/soundlib/SampleIO.cpp trunk/OpenMPT/test/test.cpp Modified: trunk/OpenMPT/soundlib/ITCompression.cpp =================================================================== --- trunk/OpenMPT/soundlib/ITCompression.cpp 2014-09-24 14:25:02 UTC (rev 4308) +++ trunk/OpenMPT/soundlib/ITCompression.cpp 2014-09-24 14:25:52 UTC (rev 4309) @@ -12,6 +12,8 @@ #include <stdafx.h> #include "ITCompression.h" #include "../common/misc_util.h" +#include <ostream> +#include "../common/mptIO.h" OPENMPT_NAMESPACE_BEGIN @@ -49,8 +51,8 @@ // IT 2.14 compression -ITCompression::ITCompression(const ModSample &sample, bool it215, FILE *f) : file(f), mptSample(sample), is215(it215) -//------------------------------------------------------------------------------------------------------------------- +ITCompression::ITCompression(const ModSample &sample, bool it215, std::ostream *f) : file(f), mptSample(sample), is215(it215) +//--------------------------------------------------------------------------------------------------------------------------- { packedData = new (std::nothrow) uint8[bufferSize]; sampleData = new (std::nothrow) uint8[blockSize]; @@ -77,7 +79,7 @@ else Compress<IT8BitParams>(static_cast<const int8 *>(sample.pSample) + chn, offset, remain); - if(file) fwrite(&packedData[0], packedLength, 1, file); + if(file) mpt::IO::WriteRaw(*file, &packedData[0], packedLength); packedTotalLength += packedLength; offset += baseLength; Modified: trunk/OpenMPT/soundlib/ITCompression.h =================================================================== --- trunk/OpenMPT/soundlib/ITCompression.h 2014-09-24 14:25:02 UTC (rev 4308) +++ trunk/OpenMPT/soundlib/ITCompression.h 2014-09-24 14:25:52 UTC (rev 4309) @@ -14,6 +14,7 @@ #include <vector> #include "ModSample.h" #include "FileReader.h" +#include <iosfwd> OPENMPT_NAMESPACE_BEGIN @@ -24,7 +25,7 @@ //================= { public: - ITCompression(const ModSample &sample, bool it215, FILE *f); + ITCompression(const ModSample &sample, bool it215, std::ostream *f); size_t GetCompressedSize() const { return packedTotalLength; } static const size_t bufferSize = 2 + 0xFFFF; // Our output buffer can't be longer than this. @@ -33,7 +34,7 @@ protected: std::vector<int> bwt; // Bit width table uint8 *packedData; // Compressed data for current sample block - FILE *file; // File to which compressed data will be written (can be nullptr if you only want to find out the sample size) + std::ostream *file; // File to which compressed data will be written (can be nullptr if you only want to find out the sample size) void *sampleData; // Pre-processed sample data for currently compressed sample block const ModSample &mptSample; // Sample that is being processed size_t packedLength; // Size of currently compressed sample block Modified: trunk/OpenMPT/soundlib/SampleIO.cpp =================================================================== --- trunk/OpenMPT/soundlib/SampleIO.cpp 2014-09-24 14:25:02 UTC (rev 4308) +++ trunk/OpenMPT/soundlib/SampleIO.cpp 2014-09-24 14:25:52 UTC (rev 4309) @@ -15,6 +15,7 @@ #include "SampleIO.h" #include "SampleFormatConverters.h" #include "ITCompression.h" +#include "../common/mptIO.h" OPENMPT_NAMESPACE_BEGIN @@ -736,7 +737,8 @@ else if(GetEncoding() == IT214 || GetEncoding() == IT215) { // IT2.14-encoded samples - ITCompression its(sample, GetEncoding() == IT215, f); + mpt::FILE_ostream s(f); + ITCompression its(sample, GetEncoding() == IT215, &s); len = its.GetCompressedSize(); } Modified: trunk/OpenMPT/test/test.cpp =================================================================== --- trunk/OpenMPT/test/test.cpp 2014-09-24 14:25:02 UTC (rev 4308) +++ trunk/OpenMPT/test/test.cpp 2014-09-24 14:25:52 UTC (rev 4309) @@ -1599,28 +1599,25 @@ } -static void RunITCompressionTest(const std::vector<int8> &sampleData, ChannelFlags smpFormat, bool it215, int testcount) -//---------------------------------------------------------------------------------------------------------------------- +static void RunITCompressionTest(const std::vector<int8> &sampleData, ChannelFlags smpFormat, bool it215) +//------------------------------------------------------------------------------------------------------- { - mpt::PathString filename = GetTempFilenameBase() + MPT_PATHSTRING("itcomp") + mpt::PathString::FromWide(StringifyW(testcount)) + MPT_PATHSTRING(".raw"); ModSample smp; smp.uFlags = smpFormat; smp.pSample = const_cast<int8 *>(&sampleData[0]); smp.nLength = sampleData.size() / smp.GetBytesPerSample(); + std::string data; + { - FILE *f = mpt_fopen(filename, "wb"); - ITCompression compression(smp, it215, f); - fclose(f); + std::ostringstream f; + ITCompression compression(smp, it215, &f); + data = f.str(); } { - FILE *f = mpt_fopen(filename, "rb"); - fseek(f, 0, SEEK_END); - std::vector<int8> fileData(ftell(f), 0); - fseek(f, 0, SEEK_SET); - VERIFY_EQUAL(fread(&fileData[0], fileData.size(), 1, f), 1); + std::vector<char> fileData(data.begin(), data.end()); FileReader file(&fileData[0], fileData.size()); std::vector<int8> sampleDataNew(sampleData.size(), 0); @@ -1628,19 +1625,13 @@ ITDecompression decompression(file, smp, it215); VERIFY_EQUAL_NONCONT(memcmp(&sampleData[0], &sampleDataNew[0], sampleData.size()), 0); - fclose(f); } - RemoveFile(filename); } static noinline void TestITCompression() //-------------------------------------- { - if(!ShouldRunTests()) - { - return; - } // Test loading / saving of IT-compressed samples const int sampleDataSize = 65536; std::vector<int8> sampleData(sampleDataSize, 0); @@ -1650,15 +1641,13 @@ sampleData[i] = (int8)std::rand(); } - int testcount = 0; - // Run each compression test with IT215 compression and without. for(int i = 0; i < 2; i++) { - RunITCompressionTest(sampleData, ChannelFlags(0), i == 0, testcount++); - RunITCompressionTest(sampleData, CHN_16BIT, i == 0, testcount++); - RunITCompressionTest(sampleData, CHN_STEREO, i == 0, testcount++); - RunITCompressionTest(sampleData, CHN_16BIT | CHN_STEREO, i == 0, testcount++); + RunITCompressionTest(sampleData, ChannelFlags(0), i == 0); + RunITCompressionTest(sampleData, CHN_16BIT, i == 0); + RunITCompressionTest(sampleData, CHN_STEREO, i == 0); + RunITCompressionTest(sampleData, CHN_16BIT | CHN_STEREO, i == 0); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <man...@us...> - 2014-09-24 15:16:13
|
Revision: 4310 http://sourceforge.net/p/modplug/code/4310 Author: manxorist Date: 2014-09-24 15:16:00 +0000 (Wed, 24 Sep 2014) Log Message: ----------- [Ref] mptIO: Allow NULL FILE* in mpt::FILE_ostream and related streambufs. [Fix] IT Compression: WriteSample(f=NULL, ...) broke for IT compressed samples in r4309 . Revision Links: -------------- http://sourceforge.net/p/modplug/code/4309 Modified Paths: -------------- trunk/OpenMPT/common/mptIO.h trunk/OpenMPT/soundlib/SampleIO.cpp Modified: trunk/OpenMPT/common/mptIO.h =================================================================== --- trunk/OpenMPT/common/mptIO.h 2014-09-24 14:25:52 UTC (rev 4309) +++ trunk/OpenMPT/common/mptIO.h 2014-09-24 15:16:00 UTC (rev 4310) @@ -374,10 +374,13 @@ // Only output functionality is implemented because we have no need for an input wrapper. // // During the whole lifetime of the iostream wrappers, the FILE* object is assumend to be -// - valid -// - opened for writing in non-append mode -// - opened in binary mode -// - seekable +// either +// - NULL +// or +// - valid +// - opened for writing in non-append mode +// - opened in binary mode +// - seekable // Some of these preconditions cannot be verified, // and even the others do not get verified. // Behaviour in case of any unmet preconditions is undefined. @@ -417,6 +420,10 @@ protected: virtual int_type overflow(int_type ch) { + if(!mpt::IO::IsValid(f)) + { + return traits_type::eof(); + } if(traits_type::eq_int_type(ch, traits_type::eof())) { return traits_type::eof(); @@ -430,6 +437,10 @@ } virtual int sync() { + if(!mpt::IO::IsValid(f)) + { + return -1; + } if(!mpt::IO::Flush(f)) { return -1; @@ -438,10 +449,18 @@ } virtual pos_type seekpos(pos_type pos, std::ios_base::openmode which) { + if(!mpt::IO::IsValid(f)) + { + return pos_type(off_type(-1)); + } return seekoff(pos, std::ios_base::beg, which); } virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which) { + if(!mpt::IO::IsValid(f)) + { + return pos_type(off_type(-1)); + } if(which & std::ios_base::in) { return pos_type(off_type(-1)); @@ -507,6 +526,10 @@ } ~FILE_output_buffered_streambuf() { + if(!mpt::IO::IsValid(f)) + { + return; + } WriteOut(); } private: @@ -523,6 +546,10 @@ protected: virtual int_type overflow(int_type ch) { + if(!mpt::IO::IsValid(f)) + { + return traits_type::eof(); + } if(traits_type::eq_int_type(ch, traits_type::eof())) { return traits_type::eof(); @@ -538,6 +565,10 @@ } virtual int sync() { + if(!mpt::IO::IsValid(f)) + { + return -1; + } if(!WriteOut()) { return -1; @@ -546,6 +577,10 @@ } virtual pos_type seekpos(pos_type pos, std::ios_base::openmode which) { + if(!mpt::IO::IsValid(f)) + { + return pos_type(off_type(-1)); + } if(!WriteOut()) { return pos_type(off_type(-1)); @@ -554,6 +589,10 @@ } virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which) { + if(!mpt::IO::IsValid(f)) + { + return pos_type(off_type(-1)); + } if(!WriteOut()) { return pos_type(off_type(-1)); @@ -573,13 +612,13 @@ , f(f) , buf(f, bufSize) { - mpt::IO::Flush(f); + if(mpt::IO::IsValid(f)) mpt::IO::Flush(f); } ~FILE_ostream() { flush(); buf.pubsync(); - mpt::IO::Flush(f); + if(mpt::IO::IsValid(f)) mpt::IO::Flush(f); } }; // class FILE_ostream Modified: trunk/OpenMPT/soundlib/SampleIO.cpp =================================================================== --- trunk/OpenMPT/soundlib/SampleIO.cpp 2014-09-24 14:25:52 UTC (rev 4309) +++ trunk/OpenMPT/soundlib/SampleIO.cpp 2014-09-24 15:16:00 UTC (rev 4310) @@ -738,7 +738,7 @@ { // IT2.14-encoded samples mpt::FILE_ostream s(f); - ITCompression its(sample, GetEncoding() == IT215, &s); + ITCompression its(sample, GetEncoding() == IT215, f ? &s : nullptr); len = its.GetCompressedSize(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2014-09-27 15:49:44
|
Revision: 4312 http://sourceforge.net/p/modplug/code/4312 Author: saga-games Date: 2014-09-27 15:49:35 +0000 (Sat, 27 Sep 2014) Log Message: ----------- [Imp] Song length estimation: Slightly improve calculation of nested pattern loops (http://bugs.openmpt.org/view.php?id=591) Modified Paths: -------------- trunk/OpenMPT/common/misc_util.h trunk/OpenMPT/soundlib/Snd_fx.cpp Modified: trunk/OpenMPT/common/misc_util.h =================================================================== --- trunk/OpenMPT/common/misc_util.h 2014-09-26 09:06:17 UTC (rev 4311) +++ trunk/OpenMPT/common/misc_util.h 2014-09-27 15:49:35 UTC (rev 4312) @@ -296,27 +296,6 @@ } -// Greatest Common Divisor. -template <class T> -T gcd(T a, T b) -//------------- -{ - if(a < 0) - a = -a; - if(b < 0) - b = -b; - do - { - if(a == 0) - return b; - b %= a; - if(b == 0) - return a; - a %= b; - } while(true); -} - - // Returns sign of a number (-1 for negative numbers, 1 for positive numbers, 0 for 0) template <class T> int sgn(T value) @@ -467,6 +446,38 @@ return (a >= 0) ? mpt::saturate_cast<int32>(a / c) : mpt::saturate_cast<int32>((a - (c - 1)) / c); } + // Greatest Common Divisor. Always returns non-negative number. + template <class T> + T gcd(T a, T b) + { + if(a < 0) + a = -a; + if(b < 0) + b = -b; + do + { + if(a == 0) + return b; + b %= a; + if(b == 0) + return a; + a %= b; + } while(true); + } + + // Least Common Multiple. Always returns non-negative number. + template <class T> + int lcm(T a, T b) + { + if(a < 0) + a = -a; + if(b < 0) + b = -b; + if((a | b) == 0) + return 0; + return a / gcd<T>(a, b) * b; + } + template<typename T, std::size_t n> class fixed_size_queue { Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp =================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp 2014-09-26 09:06:17 UTC (rev 4311) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2014-09-27 15:49:35 UTC (rev 4312) @@ -775,14 +775,24 @@ if(patternLoopEndedOnThisRow) { p = Patterns[nPattern].GetRow(nRow); + std::map<double, int> startTimes; + // This is really just a simple estimation for nested pattern loops. It should handle cases correctly where all parallel loops start and end on the same row. + // If one of them starts or ends "in between", it will most likely calculate a wrong duration. + // For S3M files, it's also way off. for(CHANNELINDEX nChn = 0; nChn < GetNumChannels(); p++, nChn++) { if((p->command == CMD_S3MCMDEX && p->param >= 0xB1 && p->param <= 0xBF) || (p->command == CMD_MODCMDEX && p->param >= 0x61 && p->param <= 0x6F)) { - memory.elapsedTime += (memory.elapsedTime - memory.chnSettings[nChn].patLoop) * (double)(p->param & 0x0F); + const double start = memory.chnSettings[nChn].patLoop; + if(!startTimes[start]) startTimes[start] = 1; + startTimes[start] = Util::lcm<int>(startTimes[start], 1 + (p->param & 0x0F)); } } + for(std::map<double, int>::iterator i = startTimes.begin(); i != startTimes.end(); i++) + { + memory.elapsedTime += (memory.elapsedTime - i->first) * (double)(i->second - 1); + } if(GetType() == MOD_TYPE_IT) { // IT pattern loop start row update - at the end of a pattern loop, set pattern loop start to next row (for upcoming pattern loops with missing SB0) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <man...@us...> - 2014-09-28 09:11:31
|
Revision: 4318 http://sourceforge.net/p/modplug/code/4318 Author: manxorist Date: 2014-09-28 09:11:17 +0000 (Sun, 28 Sep 2014) Log Message: ----------- [Ref] Convert the last 5 usage sites of mpt::String::Format to typesafe mpt::String::Print. Modified Paths: -------------- trunk/OpenMPT/mptrack/MIDIMapping.cpp trunk/OpenMPT/mptrack/TrackerSettings.cpp trunk/OpenMPT/soundlib/plugins/PluginManager.cpp Modified: trunk/OpenMPT/mptrack/MIDIMapping.cpp =================================================================== --- trunk/OpenMPT/mptrack/MIDIMapping.cpp 2014-09-28 08:55:05 UTC (rev 4317) +++ trunk/OpenMPT/mptrack/MIDIMapping.cpp 2014-09-28 09:11:17 UTC (rev 4318) @@ -25,7 +25,7 @@ if(m_Active) flags[0] = '1'; if(m_CaptureMIDI) flags[1] = '1'; if(m_AllowPatternEdit) flags[2] = '1'; - return mpt::String::Format("%s:%d:%x:%d:%d:%d", flags, (int)GetChannel(), (int)GetEvent(), (int)GetController(), (int)m_PluginIndex, m_Parameter); + return mpt::String::Print("%1:%2:%3:%4:%5:%6", flags, (int)GetChannel(), mpt::fmt::hex((int)GetEvent()), (int)GetController(), (int)m_PluginIndex, m_Parameter); } Modified: trunk/OpenMPT/mptrack/TrackerSettings.cpp =================================================================== --- trunk/OpenMPT/mptrack/TrackerSettings.cpp 2014-09-28 08:55:05 UTC (rev 4317) +++ trunk/OpenMPT/mptrack/TrackerSettings.cpp 2014-09-28 09:11:17 UTC (rev 4318) @@ -257,7 +257,7 @@ GetDefaultColourScheme(rgbCustomColors); for(int ncol = 0; ncol < MAX_MODCOLORS; ncol++) { - const std::string colorName = mpt::String::Format("Color%02d", ncol); + const std::string colorName = mpt::String::Print("Color%1", mpt::fmt::dec0<2>(ncol)); rgbCustomColors[ncol] = conf.Read<uint32>("Display", colorName, rgbCustomColors[ncol]); } // AutoSave @@ -343,11 +343,11 @@ theApp.GetDefaultMidiMacro(macros); for(int isfx = 0; isfx < 16; isfx++) { - mpt::String::Copy(macros.szMidiSFXExt[isfx], conf.Read<std::string>("Zxx Macros", mpt::String::Format("SF%X", isfx), macros.szMidiSFXExt[isfx])); + mpt::String::Copy(macros.szMidiSFXExt[isfx], conf.Read<std::string>("Zxx Macros", mpt::String::Print("SF%1", mpt::fmt::HEX(isfx)), macros.szMidiSFXExt[isfx])); } for(int izxx = 0; izxx < 128; izxx++) { - mpt::String::Copy(macros.szMidiZXXExt[izxx], conf.Read<std::string>("Zxx Macros", mpt::String::Format("Z%02X", izxx | 0x80), macros.szMidiZXXExt[izxx])); + mpt::String::Copy(macros.szMidiZXXExt[izxx], conf.Read<std::string>("Zxx Macros", mpt::String::Print("Z%1", mpt::fmt::HEX0<2>(izxx | 0x80)), macros.szMidiZXXExt[izxx])); } @@ -847,7 +847,7 @@ // Display (Colors) for(int ncol = 0; ncol < MAX_MODCOLORS; ncol++) { - conf.Write<uint32>("Display", mpt::String::Format("Color%02d", ncol), rgbCustomColors[ncol]); + conf.Write<uint32>("Display", mpt::String::Print("Color%1", mpt::fmt::dec0<2>(ncol)), rgbCustomColors[ncol]); } // AutoSave @@ -889,11 +889,11 @@ theApp.GetDefaultMidiMacro(macros); for(int isfx = 0; isfx < 16; isfx++) { - conf.Write<std::string>("Zxx Macros", mpt::String::Format("SF%X", isfx), macros.szMidiSFXExt[isfx]); + conf.Write<std::string>("Zxx Macros", mpt::String::Print("SF%1", mpt::fmt::HEX(isfx)), macros.szMidiSFXExt[isfx]); } for(int izxx = 0; izxx < 128; izxx++) { - conf.Write<std::string>("Zxx Macros", mpt::String::Format("Z%02X", izxx | 0x80), macros.szMidiZXXExt[izxx]); + conf.Write<std::string>("Zxx Macros", mpt::String::Print("Z%1", mpt::fmt::HEX0<2>(izxx | 0x80)), macros.szMidiZXXExt[izxx]); } // MRU list Modified: trunk/OpenMPT/soundlib/plugins/PluginManager.cpp =================================================================== --- trunk/OpenMPT/soundlib/plugins/PluginManager.cpp 2014-09-28 08:55:05 UTC (rev 4317) +++ trunk/OpenMPT/soundlib/plugins/PluginManager.cpp 2014-09-28 09:11:17 UTC (rev 4318) @@ -69,7 +69,7 @@ const std::string libName = libraryName.ToUTF8(); const uint32 crc = crc32(0, reinterpret_cast<const Bytef *>(&libName[0]), libName.length()); - const std::string IDs = mpt::String::Format("%08X%08X%08X", SwapBytesReturnLE(pluginId1), SwapBytesReturnLE(pluginId2), SwapBytesReturnLE(crc)); + const std::string IDs = mpt::fmt::HEX0<8>(SwapBytesReturnLE(pluginId1)) + mpt::fmt::HEX0<8>(SwapBytesReturnLE(pluginId2)) + mpt::fmt::HEX0<8>(SwapBytesReturnLE(crc)); const std::string flagsKey = IDs + ".Flags"; mpt::PathString writePath = dllPath; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <man...@us...> - 2014-09-28 09:23:10
|
Revision: 4319 http://sourceforge.net/p/modplug/code/4319 Author: manxorist Date: 2014-09-28 09:22:57 +0000 (Sun, 28 Sep 2014) Log Message: ----------- [Ref] Move mpt::String::Format to test.cpp as the test cases are the only place left where sprintf-like functionality is required (in order to validate our own formatting functions) outside of mptrack/ (which currently still uses MFC sprintf variants all over the place). Modified Paths: -------------- trunk/OpenMPT/common/mptString.cpp trunk/OpenMPT/common/mptString.h trunk/OpenMPT/test/test.cpp Modified: trunk/OpenMPT/common/mptString.cpp =================================================================== --- trunk/OpenMPT/common/mptString.cpp 2014-09-28 09:11:17 UTC (rev 4318) +++ trunk/OpenMPT/common/mptString.cpp 2014-09-28 09:22:57 UTC (rev 4319) @@ -62,38 +62,7 @@ namespace mpt { namespace String { -#ifdef MODPLUG_TRACKER -std::string Format(const char *format, ...) -{ - #if MPT_COMPILER_MSVC - va_list argList; - va_start(argList, format); - - // Count the needed array size. - const size_t nCount = _vscprintf(format, argList); // null character not included. - std::vector<char> buf(nCount + 1); // + 1 is for null terminator. - vsprintf_s(&(buf[0]), buf.size(), format, argList); - - va_end(argList); - return &(buf[0]); - #else - va_list argList; - va_start(argList, format); - int size = vsnprintf(NULL, 0, format, argList); // get required size, requires c99 compliant vsnprintf which msvc does not have - va_end(argList); - std::vector<char> temp(size + 1); - va_start(argList, format); - vsnprintf(&(temp[0]), size + 1, format, argList); - va_end(argList); - return &(temp[0]); - #endif -} - -#endif - - - /* default 1:1 mapping static const uint32 CharsetTableISO8859_1[256] = { Modified: trunk/OpenMPT/common/mptString.h =================================================================== --- trunk/OpenMPT/common/mptString.h 2014-09-28 09:11:17 UTC (rev 4318) +++ trunk/OpenMPT/common/mptString.h 2014-09-28 09:22:57 UTC (rev 4319) @@ -30,17 +30,6 @@ { -#ifdef MODPLUG_TRACKER -// There are 4 reasons why this is not available for library code: -// 1. printf-like functionality is not type-safe. -// 2. There are portability problems with char/wchar_t and the semantics of %s/%ls/%S . -// 3. There are portability problems with specifying format for 64bit integers. -// 4. Formatting of floating point values depends on the currently set C locale. -// A library is not allowed to mock with that and thus cannot influence the behavior in this case. -std::string MPT_PRINTF_FUNC(1,2) Format(const char * format, ...); -#endif - - // Remove whitespace at start of string static inline std::string LTrim(std::string str, const std::string &whitespace = " \n\r\t") //----------------------------------------------------------------------------------------- Modified: trunk/OpenMPT/test/test.cpp =================================================================== --- trunk/OpenMPT/test/test.cpp 2014-09-28 09:11:17 UTC (rev 4318) +++ trunk/OpenMPT/test/test.cpp 2014-09-28 09:22:57 UTC (rev 4319) @@ -244,10 +244,52 @@ } + +#ifdef MODPLUG_TRACKER + +// In tracker debug builds, the sprintf-like function is retained in order to be able to validate our own formatting against sprintf. + +// There are 4 reasons why this is not available for library code: +// 1. printf-like functionality is not type-safe. +// 2. There are portability problems with char/wchar_t and the semantics of %s/%ls/%S . +// 3. There are portability problems with specifying format for 64bit integers. +// 4. Formatting of floating point values depends on the currently set C locale. +// A library is not allowed to mock with that and thus cannot influence the behavior in this case. + +static std::string MPT_PRINTF_FUNC(1,2) StringFormat(const char * format, ...); + +static std::string StringFormat(const char *format, ...) +{ + #if MPT_COMPILER_MSVC + va_list argList; + va_start(argList, format); + + // Count the needed array size. + const size_t nCount = _vscprintf(format, argList); // null character not included. + std::vector<char> buf(nCount + 1); // + 1 is for null terminator. + vsprintf_s(&(buf[0]), buf.size(), format, argList); + + va_end(argList); + return &(buf[0]); + #else + va_list argList; + va_start(argList, format); + int size = vsnprintf(NULL, 0, format, argList); // get required size, requires c99 compliant vsnprintf which msvc does not have + va_end(argList); + std::vector<char> temp(size + 1); + va_start(argList, format); + vsnprintf(&(temp[0]), size + 1, format, argList); + va_end(argList); + return &(temp[0]); + #endif +} + +#endif + static void TestFloatFormat(double x, const char * format, mpt::FormatFlags f, std::size_t width = 0, int precision = -1) { #ifdef MODPLUG_TRACKER - std::string str_sprintf = mpt::String::Format(format, x); + std::string str_sprintf = StringFormat(format, x); #endif std::string str_iostreams = mpt::Format().SetFlags(f).SetWidth(width).SetPrecision(precision).ToString(x); std::string str_parsed = mpt::Format().ParsePrintf(format).ToString(x); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <man...@us...> - 2014-09-29 07:14:14
|
Revision: 4321 http://sourceforge.net/p/modplug/code/4321 Author: manxorist Date: 2014-09-29 07:13:52 +0000 (Mon, 29 Sep 2014) Log Message: ----------- [Mod] Soundcard settings: No longer display a modal dialog when chaging to the soundcard tab in case of a unavailable sound device being selected. Instead, just select the best matching device immediately. In case of changing to a unavailable device, retain the modal dialog box as silently modifying the underlying combo box would be evenmore annoying. [Mod] Soundcard settings: Add a hidden setting [Sound Settings]PreferSameTypeIfDeviceUnavailable=0 which optionally changes the algorithm for selecting the fallback device if the device selected by the user (or read from the configuration) is currently unavailable. When this setting is set, a device of the same type as the currently selected is preferred instead of just defaulting to wave mapper. Modified Paths: -------------- trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mpdlgs.cpp trunk/OpenMPT/mptrack/Mpdlgs.h trunk/OpenMPT/mptrack/TrackerSettings.cpp trunk/OpenMPT/mptrack/TrackerSettings.h trunk/OpenMPT/sounddev/SoundDevice.cpp trunk/OpenMPT/sounddev/SoundDevice.h Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2014-09-29 06:38:49 UTC (rev 4320) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2014-09-29 07:13:52 UTC (rev 4321) @@ -1887,7 +1887,7 @@ CPropertySheet dlg("OpenMPT Setup", this, m_nLastOptionsPage); COptionsGeneral general; - COptionsSoundcard sounddlg(TrackerSettings::Instance().GetSoundDeviceID()); + COptionsSoundcard sounddlg(TrackerSettings::Instance().m_SoundDeviceIdentifier); COptionsSampleEditor smpeditor; COptionsKeyboard keyboard; COptionsColors colors; Modified: trunk/OpenMPT/mptrack/Mpdlgs.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mpdlgs.cpp 2014-09-29 06:38:49 UTC (rev 4320) +++ trunk/OpenMPT/mptrack/Mpdlgs.cpp 2014-09-29 07:13:52 UTC (rev 4321) @@ -149,15 +149,42 @@ } -COptionsSoundcard::COptionsSoundcard(SoundDevice::ID dev) -//------------------------------------------------------- +COptionsSoundcard::COptionsSoundcard(std::wstring deviceIdentifier) +//----------------------------------------------------------------- : CPropertyPage(IDD_OPTIONS_SOUNDCARD) - , m_InitialDevice(dev) + , m_InitialDeviceIdentifier(deviceIdentifier) { return; } +void COptionsSoundcard::SetInitialDevice() +//---------------------------------------- +{ + bool ok = false; + std::set<SoundDevice::ID> triedSet; + while(!ok) + { + m_CurrentDeviceInfo = theApp.GetSoundDevicesManager()->FindDeviceInfoBestMatch(m_InitialDeviceIdentifier, TrackerSettings::Instance().m_SoundDevicePreferSameTypeIfDeviceUnavailable); + SoundDevice::ID dev = m_CurrentDeviceInfo.id; + if(triedSet.find(dev) != triedSet.end()) + { + Reporting::Error("No sound device available."); + break; + } + m_CurrentDeviceCaps = theApp.GetSoundDevicesManager()->GetDeviceCaps(dev, CMainFrame::GetMainFrame()->gpSoundDevice); + m_CurrentDeviceDynamicCaps = theApp.GetSoundDevicesManager()->GetDeviceDynamicCaps(dev, TrackerSettings::Instance().GetSampleRates(), CMainFrame::GetMainFrame(), CMainFrame::GetMainFrame()->gpSoundDevice, true); + if(theApp.GetSoundDevicesManager()->IsDeviceUnavailable(dev)) + { + triedSet.insert(dev); + m_InitialDeviceIdentifier = m_CurrentDeviceInfo.GetIdentifier(); + continue; // makes progress because FindDeviceInfoBestMatch will not return devices again that were found out to be unavailable + } + ok = true; + } +} + + void COptionsSoundcard::SetDevice(SoundDevice::ID dev, bool forceReload) //---------------------------------------------------------------------- { @@ -171,16 +198,22 @@ } if(theApp.GetSoundDevicesManager()->IsDeviceUnavailable(dev)) { - // if the device is unavailable, use the default device - SoundDevice::ID newdev = theApp.GetSoundDevicesManager()->FindDeviceInfoBestMatch(std::wstring()).id; + SoundDevice::ID newdev; + if(TrackerSettings::Instance().m_SoundDevicePreferSameTypeIfDeviceUnavailable) + { // try finding a device of the same type + newdev = theApp.GetSoundDevicesManager()->FindDeviceInfoBestMatch(m_CurrentDeviceInfo.GetIdentifier(), true).id; + } else + { // if the device is unavailable, use the default device + newdev = theApp.GetSoundDevicesManager()->FindDeviceInfoBestMatch(std::wstring()).id; + } if(newdev != dev) { - Reporting::Information("Device not availble. Reverting to default device."); + Reporting::Information("Device not available. Reverting to default device."); SetDevice(newdev); UpdateEverything(); } else { - Reporting::Warning("Device not availble."); + Reporting::Warning("Device not available."); } } } @@ -204,7 +237,7 @@ //------------------------------------ { CPropertyPage::OnInitDialog(); - SetDevice(m_InitialDevice, true); + SetInitialDevice(); UpdateEverything(); return TRUE; } Modified: trunk/OpenMPT/mptrack/Mpdlgs.h =================================================================== --- trunk/OpenMPT/mptrack/Mpdlgs.h 2014-09-29 06:38:49 UTC (rev 4320) +++ trunk/OpenMPT/mptrack/Mpdlgs.h 2014-09-29 07:13:52 UTC (rev 4321) @@ -32,7 +32,8 @@ CStatic m_StaticChannelMapping[NUM_CHANNELCOMBOBOXES]; CComboBox m_CbnChannelMapping[NUM_CHANNELCOMBOBOXES]; - SoundDevice::ID m_InitialDevice; + std::wstring m_InitialDeviceIdentifier; + void SetInitialDevice(); void SetDevice(SoundDevice::ID dev, bool forceReload=false); SoundDevice::Info m_CurrentDeviceInfo; @@ -41,7 +42,7 @@ SoundDevice::Settings m_Settings; public: - COptionsSoundcard(SoundDevice::ID sd); + COptionsSoundcard(std::wstring deviceIdentifier); void UpdateStatistics(); Modified: trunk/OpenMPT/mptrack/TrackerSettings.cpp =================================================================== --- trunk/OpenMPT/mptrack/TrackerSettings.cpp 2014-09-29 06:38:49 UTC (rev 4320) +++ trunk/OpenMPT/mptrack/TrackerSettings.cpp 2014-09-29 07:13:52 UTC (rev 4321) @@ -173,6 +173,7 @@ , m_SoundDeviceSettingsUseOldDefaults(false) , m_SoundDeviceID_DEPRECATED(SoundDevice::ID()) , m_SoundDeviceIdentifier(conf, "Sound Settings", "Device", std::wstring()) + , m_SoundDevicePreferSameTypeIfDeviceUnavailable(conf, "Sound Settings", "PreferSameTypeIfDeviceUnavailable", false) , MixerMaxChannels(conf, "Sound Settings", "MixChannels", MixerSettings().m_nMaxMixChannels) , MixerDSPMask(conf, "Sound Settings", "Quality", MixerSettings().DSPMask) , MixerFlags(conf, "Sound Settings", "SoundSetup", MixerSettings().MixerFlags) Modified: trunk/OpenMPT/mptrack/TrackerSettings.h =================================================================== --- trunk/OpenMPT/mptrack/TrackerSettings.h 2014-09-29 06:38:49 UTC (rev 4320) +++ trunk/OpenMPT/mptrack/TrackerSettings.h 2014-09-29 07:13:52 UTC (rev 4321) @@ -379,6 +379,7 @@ SoundDevice::Settings GetSoundDeviceSettingsDefaults() const; Setting<std::wstring> m_SoundDeviceIdentifier; + Setting<bool> m_SoundDevicePreferSameTypeIfDeviceUnavailable; SoundDevice::ID GetSoundDeviceID() const; void SetSoundDeviceID(const SoundDevice::ID &id); SoundDevice::Settings GetSoundDeviceSettings(const SoundDevice::ID &device) const; Modified: trunk/OpenMPT/sounddev/SoundDevice.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.cpp 2014-09-29 06:38:49 UTC (rev 4320) +++ trunk/OpenMPT/sounddev/SoundDevice.cpp 2014-09-29 07:13:52 UTC (rev 4321) @@ -562,8 +562,8 @@ } -SoundDevice::Info Manager::FindDeviceInfoBestMatch(const std::wstring &identifier) const -//-------------------------------------------------------------------------------------- +SoundDevice::Info Manager::FindDeviceInfoBestMatch(const std::wstring &identifier, bool preferSameType) +//----------------------------------------------------------------------------------------------------- { if(m_SoundDevices.empty()) { @@ -575,7 +575,7 @@ } for(std::vector<SoundDevice::Info>::const_iterator it = begin(); it != end(); ++it) { - if(it->GetIdentifier() == identifier) + if((it->GetIdentifier() == identifier) && !IsDeviceUnavailable(it->id)) { // exact match return *it; } @@ -589,7 +589,7 @@ // just find the first WASAPI device. for(std::vector<SoundDevice::Info>::const_iterator it = begin(); it != end(); ++it) { - if(it->id.GetType() == TypePORTAUDIO_WASAPI) + if((it->id.GetType() == TypePORTAUDIO_WASAPI) && !IsDeviceUnavailable(it->id)) { return *it; } @@ -604,8 +604,20 @@ case TypeASIO: case TypePORTAUDIO_WDMKS: case TypePORTAUDIO_ASIO: - // default to first device - return *begin(); + if(preferSameType) + { + for(std::vector<SoundDevice::Info>::const_iterator it = begin(); it != end(); ++it) + { + if((it->id.GetType() == type) && !IsDeviceUnavailable(it->id)) + { + return *it; + } + } + } else + { + // default to first device + return *begin(); + } break; } // invalid Modified: trunk/OpenMPT/sounddev/SoundDevice.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.h 2014-09-29 06:38:49 UTC (rev 4320) +++ trunk/OpenMPT/sounddev/SoundDevice.h 2014-09-29 07:13:52 UTC (rev 4321) @@ -669,7 +669,7 @@ SoundDevice::Info FindDeviceInfo(SoundDevice::ID id) const; SoundDevice::Info FindDeviceInfo(const std::wstring &identifier) const; - SoundDevice::Info FindDeviceInfoBestMatch(const std::wstring &identifier) const; + SoundDevice::Info FindDeviceInfoBestMatch(const std::wstring &identifier, bool preferSameType = false); bool OpenDriverSettings(SoundDevice::ID id, SoundDevice::IMessageReceiver *messageReceiver = nullptr, SoundDevice::IBase *currentSoundDevice = nullptr); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <man...@us...> - 2014-09-29 09:01:26
|
Revision: 4323 http://sourceforge.net/p/modplug/code/4323 Author: manxorist Date: 2014-09-29 09:01:08 +0000 (Mon, 29 Sep 2014) Log Message: ----------- [Ref] sounddev: Having both, a (type,index) tuple (SoundDevice::ID) and a string based identifier (SoundDevice::Identifier) to identify sound device got way too confusing. Rework the SoundDevice::Manager interface to always expect the string based identifier. The old SoundDevice::ID is still used internally and exposed for the purpose of importing old ini files. All other cases now use SoundDevice::Identifier. [Ref] sounddev: Related cleanups. Modified Paths: -------------- trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mainfrm.h trunk/OpenMPT/mptrack/Mpdlgs.cpp trunk/OpenMPT/mptrack/Mpdlgs.h trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/mptrack/TrackerSettings.cpp trunk/OpenMPT/mptrack/TrackerSettings.h trunk/OpenMPT/sounddev/SoundDevice.cpp trunk/OpenMPT/sounddev/SoundDevice.h trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp trunk/OpenMPT/sounddev/SoundDeviceASIO.h trunk/OpenMPT/sounddev/SoundDeviceDirectSound.cpp trunk/OpenMPT/sounddev/SoundDeviceDirectSound.h trunk/OpenMPT/sounddev/SoundDevicePortAudio.cpp trunk/OpenMPT/sounddev/SoundDevicePortAudio.h trunk/OpenMPT/sounddev/SoundDeviceThread.h trunk/OpenMPT/sounddev/SoundDeviceWaveout.cpp trunk/OpenMPT/sounddev/SoundDeviceWaveout.h Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2014-09-29 08:25:21 UTC (rev 4322) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2014-09-29 09:01:08 UTC (rev 4323) @@ -243,19 +243,21 @@ OnUpdateFrameTitle(false); // Check for valid sound device - if(!theApp.GetSoundDevicesManager()->FindDeviceInfo(TrackerSettings::Instance().GetSoundDeviceID()).IsValid()) + SoundDevice::Identifier dev = TrackerSettings::Instance().GetSoundDeviceIdentifier(); + if(!theApp.GetSoundDevicesManager()->FindDeviceInfo(dev).IsValid()) { // Fall back to default WaveOut device - TrackerSettings::Instance().SetSoundDeviceID(SoundDevice::ID()); + dev = theApp.GetSoundDevicesManager()->FindDeviceInfoBestMatch(dev, TrackerSettings::Instance().m_SoundDevicePreferSameTypeIfDeviceUnavailable).GetIdentifier(); + TrackerSettings::Instance().SetSoundDeviceIdentifier(dev); } if(TrackerSettings::Instance().MixerSamplerate == 0) { TrackerSettings::Instance().MixerSamplerate = MixerSettings().gdwMixingFreq; #ifndef NO_ASIO // If no mixing rate is specified and we're using ASIO, get a mixing rate supported by the device. - if(TrackerSettings::Instance().GetSoundDeviceID().GetType() == SoundDevice::TypeASIO) + if(SoundDevice::ParseType(dev) == SoundDevice::TypeASIO) { - TrackerSettings::Instance().MixerSamplerate = theApp.GetSoundDevicesManager()->GetDeviceDynamicCaps(TrackerSettings::Instance().GetSoundDeviceID(), TrackerSettings::Instance().GetSampleRates(), CMainFrame::GetMainFrame(), CMainFrame::GetMainFrame()->gpSoundDevice).currentSampleRate; + TrackerSettings::Instance().MixerSamplerate = theApp.GetSoundDevicesManager()->GetDeviceDynamicCaps(dev, TrackerSettings::Instance().GetSampleRates(), CMainFrame::GetMainFrame(), CMainFrame::GetMainFrame()->gpSoundDevice).currentSampleRate; } #endif // NO_ASIO } @@ -810,8 +812,8 @@ Reporting::Error("Unable to open sound device: Invalid mixer settings."); return false; } - const SoundDevice::ID deviceID = TrackerSettings::Instance().GetSoundDeviceID(); - if(gpSoundDevice && (gpSoundDevice->GetDeviceID() != deviceID)) + const SoundDevice::Identifier deviceIdentifier = TrackerSettings::Instance().GetSoundDeviceIdentifier(); + if(gpSoundDevice && (gpSoundDevice->GetDeviceIdentifier() != deviceIdentifier)) { gpSoundDevice->Stop(); gpSoundDevice->Close(); @@ -824,7 +826,7 @@ } if(!gpSoundDevice) { - gpSoundDevice = theApp.GetSoundDevicesManager()->CreateSoundDevice(deviceID); + gpSoundDevice = theApp.GetSoundDevicesManager()->CreateSoundDevice(deviceIdentifier); } if(!gpSoundDevice) { @@ -833,12 +835,12 @@ } gpSoundDevice->SetMessageReceiver(this); gpSoundDevice->SetSource(this); - SoundDevice::Settings deviceSettings = TrackerSettings::Instance().GetSoundDeviceSettings(deviceID); + SoundDevice::Settings deviceSettings = TrackerSettings::Instance().GetSoundDeviceSettings(deviceIdentifier); if(!gpSoundDevice->Open(deviceSettings)) { if(!gpSoundDevice->IsAvailable()) { - theApp.GetSoundDevicesManager()->SetDeviceUnavailable(deviceID); + theApp.GetSoundDevicesManager()->SetDeviceUnavailable(deviceIdentifier); Reporting::Error("Unable to open sound device: Device not available."); } else { @@ -854,7 +856,7 @@ } deviceSettings.sampleFormat = actualSampleFormat; TrackerSettings::Instance().MixerSamplerate = gpSoundDevice->GetSettings().Samplerate; - TrackerSettings::Instance().SetSoundDeviceSettings(deviceID, deviceSettings); + TrackerSettings::Instance().SetSoundDeviceSettings(deviceIdentifier, deviceSettings); return true; } @@ -1680,16 +1682,16 @@ BOOL CMainFrame::ResetSoundCard() //------------------------------- { - return CMainFrame::SetupSoundCard(TrackerSettings::Instance().GetSoundDeviceSettings(TrackerSettings::Instance().GetSoundDeviceID()), TrackerSettings::Instance().GetSoundDeviceID(), TrackerSettings::Instance().m_SoundSettingsStopMode, true); + return CMainFrame::SetupSoundCard(TrackerSettings::Instance().GetSoundDeviceSettings(TrackerSettings::Instance().GetSoundDeviceIdentifier()), TrackerSettings::Instance().GetSoundDeviceIdentifier(), TrackerSettings::Instance().m_SoundSettingsStopMode, true); } -BOOL CMainFrame::SetupSoundCard(SoundDevice::Settings deviceSettings, SoundDevice::ID deviceID, SoundDevice::StopMode stoppedMode, bool forceReset) -//------------------------------------------------------------------------------------------------------------------------------------------------- +BOOL CMainFrame::SetupSoundCard(SoundDevice::Settings deviceSettings, SoundDevice::Identifier deviceIdentifier, SoundDevice::StopMode stoppedMode, bool forceReset) +//----------------------------------------------------------------------------------------------------------------------------------------------------------------- { if(forceReset - || (TrackerSettings::Instance().GetSoundDeviceID() != deviceID) - || (TrackerSettings::Instance().GetSoundDeviceSettings(deviceID) != deviceSettings) + || (TrackerSettings::Instance().GetSoundDeviceIdentifier() != deviceIdentifier) + || (TrackerSettings::Instance().GetSoundDeviceSettings(deviceIdentifier) != deviceSettings) || (TrackerSettings::Instance().m_SoundSettingsStopMode != stoppedMode) ) { @@ -1716,8 +1718,8 @@ deviceSettings.KeepDeviceRunning = true; break; } - TrackerSettings::Instance().SetSoundDeviceID(deviceID); - TrackerSettings::Instance().SetSoundDeviceSettings(deviceID, deviceSettings); + TrackerSettings::Instance().SetSoundDeviceIdentifier(deviceIdentifier); + TrackerSettings::Instance().SetSoundDeviceSettings(deviceIdentifier, deviceSettings); TrackerSettings::Instance().MixerOutputChannels = deviceSettings.Channels; TrackerSettings::Instance().MixerSamplerate = deviceSettings.Samplerate; if(pActiveMod) Modified: trunk/OpenMPT/mptrack/Mainfrm.h =================================================================== --- trunk/OpenMPT/mptrack/Mainfrm.h 2014-09-29 08:25:21 UTC (rev 4322) +++ trunk/OpenMPT/mptrack/Mainfrm.h 2014-09-29 09:01:08 UTC (rev 4323) @@ -494,7 +494,7 @@ void IdleHandlerSounddevice(); BOOL ResetSoundCard(); - BOOL SetupSoundCard(SoundDevice::Settings deviceSettings, SoundDevice::ID deviceID, SoundDevice::StopMode stoppedMode, bool forceReset = false); + BOOL SetupSoundCard(SoundDevice::Settings deviceSettings, SoundDevice::Identifier deviceIdentifier, SoundDevice::StopMode stoppedMode, bool forceReset = false); BOOL SetupMiscOptions(); BOOL SetupPlayer(); Modified: trunk/OpenMPT/mptrack/Mpdlgs.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mpdlgs.cpp 2014-09-29 08:25:21 UTC (rev 4322) +++ trunk/OpenMPT/mptrack/Mpdlgs.cpp 2014-09-29 09:01:08 UTC (rev 4323) @@ -162,11 +162,11 @@ //---------------------------------------- { bool ok = false; - std::set<SoundDevice::ID> triedSet; + std::set<SoundDevice::Identifier> triedSet; while(!ok) { m_CurrentDeviceInfo = theApp.GetSoundDevicesManager()->FindDeviceInfoBestMatch(m_InitialDeviceIdentifier, TrackerSettings::Instance().m_SoundDevicePreferSameTypeIfDeviceUnavailable); - SoundDevice::ID dev = m_CurrentDeviceInfo.id; + SoundDevice::Identifier dev = m_CurrentDeviceInfo.GetIdentifier(); if(triedSet.find(dev) != triedSet.end()) { Reporting::Error("No sound device available."); @@ -186,10 +186,10 @@ } -void COptionsSoundcard::SetDevice(SoundDevice::ID dev, bool forceReload) -//---------------------------------------------------------------------- +void COptionsSoundcard::SetDevice(SoundDevice::Identifier dev, bool forceReload) +//------------------------------------------------------------------------------ { - bool deviceChanged = (dev != m_CurrentDeviceInfo.id); + bool deviceChanged = (dev != m_CurrentDeviceInfo.GetIdentifier()); m_CurrentDeviceInfo = theApp.GetSoundDevicesManager()->FindDeviceInfo(dev); m_CurrentDeviceCaps = theApp.GetSoundDevicesManager()->GetDeviceCaps(dev, CMainFrame::GetMainFrame()->gpSoundDevice); m_CurrentDeviceDynamicCaps = theApp.GetSoundDevicesManager()->GetDeviceDynamicCaps(dev, TrackerSettings::Instance().GetSampleRates(), CMainFrame::GetMainFrame(), CMainFrame::GetMainFrame()->gpSoundDevice, true); @@ -199,14 +199,7 @@ } if(theApp.GetSoundDevicesManager()->IsDeviceUnavailable(dev)) { - SoundDevice::ID newdev; - if(TrackerSettings::Instance().m_SoundDevicePreferSameTypeIfDeviceUnavailable) - { // try finding a device of the same type - newdev = theApp.GetSoundDevicesManager()->FindDeviceInfoBestMatch(m_CurrentDeviceInfo.GetIdentifier(), true).id; - } else - { // if the device is unavailable, use the default device - newdev = theApp.GetSoundDevicesManager()->FindDeviceInfoBestMatch(std::wstring()).id; - } + SoundDevice::Identifier newdev = theApp.GetSoundDevicesManager()->FindDeviceInfoBestMatch(m_CurrentDeviceInfo.GetIdentifier(), TrackerSettings::Instance().m_SoundDevicePreferSameTypeIfDeviceUnavailable).GetIdentifier(); if(newdev != dev) { Reporting::Information("Device not available. Reverting to default device."); @@ -360,7 +353,7 @@ } } - if(theApp.GetSoundDevicesManager()->IsDeviceUnavailable(it->id)) + if(theApp.GetSoundDevicesManager()->IsDeviceUnavailable(it->GetIdentifier())) { continue; } @@ -582,7 +575,7 @@ int n = m_CbnDevice.GetCurSel(); if(n >= 0) { - SetDevice(SoundDevice::ID::FromIdRaw(m_CbnDevice.GetItemData(n))); + SetDevice(theApp.GetSoundDevicesManager()->FindDeviceInfo(SoundDevice::ID::FromIdRaw(m_CbnDevice.GetItemData(n))).GetIdentifier()); UpdateDevice(); OnSettingsChanged(); } @@ -608,7 +601,11 @@ void COptionsSoundcard::OnSoundCardDriverPanel() //---------------------------------------------- { - theApp.GetSoundDevicesManager()->OpenDriverSettings(SoundDevice::ID::FromIdRaw(m_CbnDevice.GetItemData(m_CbnDevice.GetCurSel())), CMainFrame::GetMainFrame(), CMainFrame::GetMainFrame()->gpSoundDevice); + theApp.GetSoundDevicesManager()->OpenDriverSettings( + theApp.GetSoundDevicesManager()->FindDeviceInfo(SoundDevice::ID::FromIdRaw(m_CbnDevice.GetItemData(m_CbnDevice.GetCurSel()))).GetIdentifier(), + CMainFrame::GetMainFrame(), + CMainFrame::GetMainFrame()->gpSoundDevice + ); } @@ -763,7 +760,6 @@ UINT n = m_CbnDither.GetCurSel(); m_Settings.DitherType = (DitherMode)(n); } - const SoundDevice::ID dev = m_CurrentDeviceInfo.id; // Latency { CString s; @@ -801,8 +797,8 @@ m_Settings.ChannelMapping = SoundDevice::ChannelMapping(); } } - CMainFrame::GetMainFrame()->SetupSoundCard(m_Settings, m_CurrentDeviceInfo.id, (SoundDevice::StopMode)m_CbnStoppedMode.GetCurSel()); - SetDevice(m_CurrentDeviceInfo.id, true); // Poll changed ASIO sample format and channel names + CMainFrame::GetMainFrame()->SetupSoundCard(m_Settings, m_CurrentDeviceInfo.GetIdentifier(), (SoundDevice::StopMode)m_CbnStoppedMode.GetCurSel()); + SetDevice(m_CurrentDeviceInfo.GetIdentifier(), true); // Poll changed ASIO sample format and channel names UpdateDevice(); UpdateStatistics(); CPropertyPage::OnOK(); Modified: trunk/OpenMPT/mptrack/Mpdlgs.h =================================================================== --- trunk/OpenMPT/mptrack/Mpdlgs.h 2014-09-29 08:25:21 UTC (rev 4322) +++ trunk/OpenMPT/mptrack/Mpdlgs.h 2014-09-29 09:01:08 UTC (rev 4323) @@ -32,10 +32,10 @@ CStatic m_StaticChannelMapping[NUM_CHANNELCOMBOBOXES]; CComboBox m_CbnChannelMapping[NUM_CHANNELCOMBOBOXES]; - std::wstring m_InitialDeviceIdentifier; + SoundDevice::Identifier m_InitialDeviceIdentifier; void SetInitialDevice(); - void SetDevice(SoundDevice::ID dev, bool forceReload=false); + void SetDevice(SoundDevice::Identifier dev, bool forceReload=false); SoundDevice::Info m_CurrentDeviceInfo; SoundDevice::Caps m_CurrentDeviceCaps; SoundDevice::DynamicCaps m_CurrentDeviceDynamicCaps; Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2014-09-29 08:25:21 UTC (rev 4322) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2014-09-29 09:01:08 UTC (rev 4323) @@ -914,11 +914,11 @@ if(TrackerSettings::Instance().m_SoundDeviceSettingsUseOldDefaults) { // get the old default device - TrackerSettings::Instance().m_SoundDeviceIdentifier = m_pSoundDevicesManager->FindDeviceInfo(TrackerSettings::Instance().m_SoundDeviceID_DEPRECATED).GetIdentifier(); + TrackerSettings::Instance().SetSoundDeviceIdentifier(m_pSoundDevicesManager->FindDeviceInfo(TrackerSettings::Instance().m_SoundDeviceID_DEPRECATED).GetIdentifier()); // apply old global sound device settings to each found device for(std::vector<SoundDevice::Info>::const_iterator it = m_pSoundDevicesManager->begin(); it != m_pSoundDevicesManager->end(); ++it) { - TrackerSettings::Instance().SetSoundDeviceSettings(it->id, TrackerSettings::Instance().GetSoundDeviceSettingsDefaults()); + TrackerSettings::Instance().SetSoundDeviceSettings(it->GetIdentifier(), TrackerSettings::Instance().GetSoundDeviceSettingsDefaults()); } } Modified: trunk/OpenMPT/mptrack/TrackerSettings.cpp =================================================================== --- trunk/OpenMPT/mptrack/TrackerSettings.cpp 2014-09-29 08:25:21 UTC (rev 4322) +++ trunk/OpenMPT/mptrack/TrackerSettings.cpp 2014-09-29 09:01:08 UTC (rev 4323) @@ -658,20 +658,20 @@ return m_SoundDeviceSettingsDefaults; } -SoundDevice::ID TrackerSettings::GetSoundDeviceID() const -//------------------------------------------------------- +SoundDevice::Identifier TrackerSettings::GetSoundDeviceIdentifier() const +//----------------------------------------------------------------------- { - return theApp.GetSoundDevicesManager()->FindDeviceInfoBestMatch(m_SoundDeviceIdentifier).id; + return m_SoundDeviceIdentifier; } -void TrackerSettings::SetSoundDeviceID(const SoundDevice::ID &id) -//--------------------------------------------------------------- +void TrackerSettings::SetSoundDeviceIdentifier(const SoundDevice::Identifier &identifier) +//--------------------------------------------------------------------------------------- { - m_SoundDeviceIdentifier = theApp.GetSoundDevicesManager()->FindDeviceInfo(id).GetIdentifier(); + m_SoundDeviceIdentifier = identifier; } -SoundDevice::Settings TrackerSettings::GetSoundDeviceSettings(const SoundDevice::ID &device) const -//------------------------------------------------------------------------------------------------ +SoundDevice::Settings TrackerSettings::GetSoundDeviceSettings(const SoundDevice::Identifier &device) const +//-------------------------------------------------------------------------------------------------------- { const SoundDevice::Info deviceInfo = theApp.GetSoundDevicesManager()->FindDeviceInfo(device); if(!deviceInfo.IsValid()) @@ -684,8 +684,8 @@ return settings; } -void TrackerSettings::SetSoundDeviceSettings(const SoundDevice::ID &device, const SoundDevice::Settings &settings) -//---------------------------------------------------------------------------------------------------------------- +void TrackerSettings::SetSoundDeviceSettings(const SoundDevice::Identifier &device, const SoundDevice::Settings &settings) +//------------------------------------------------------------------------------------------------------------------------ { const SoundDevice::Info deviceInfo = theApp.GetSoundDevicesManager()->FindDeviceInfo(device); if(!deviceInfo.IsValid()) Modified: trunk/OpenMPT/mptrack/TrackerSettings.h =================================================================== --- trunk/OpenMPT/mptrack/TrackerSettings.h 2014-09-29 08:25:21 UTC (rev 4322) +++ trunk/OpenMPT/mptrack/TrackerSettings.h 2014-09-29 09:01:08 UTC (rev 4323) @@ -380,10 +380,10 @@ Setting<std::wstring> m_SoundDeviceIdentifier; Setting<bool> m_SoundDevicePreferSameTypeIfDeviceUnavailable; - SoundDevice::ID GetSoundDeviceID() const; - void SetSoundDeviceID(const SoundDevice::ID &id); - SoundDevice::Settings GetSoundDeviceSettings(const SoundDevice::ID &device) const; - void SetSoundDeviceSettings(const SoundDevice::ID &device, const SoundDevice::Settings &settings); + SoundDevice::Identifier GetSoundDeviceIdentifier() const; + void SetSoundDeviceIdentifier(const SoundDevice::Identifier &identifier); + SoundDevice::Settings GetSoundDeviceSettings(const SoundDevice::Identifier &device) const; + void SetSoundDeviceSettings(const SoundDevice::Identifier &device, const SoundDevice::Settings &settings); Setting<uint32> MixerMaxChannels; Setting<uint32> MixerDSPMask; Modified: trunk/OpenMPT/sounddev/SoundDevice.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.cpp 2014-09-29 08:25:21 UTC (rev 4322) +++ trunk/OpenMPT/sounddev/SoundDevice.cpp 2014-09-29 09:01:08 UTC (rev 4323) @@ -140,12 +140,11 @@ // SoundDevice::Base base class // -Base::Base(SoundDevice::ID id, const std::wstring &internalID) -//------------------------------------------------------------ +Base::Base(SoundDevice::Info info) +//-------------------------------- : m_Source(nullptr) , m_MessageReceiver(nullptr) - , m_ID(id) - , m_InternalID(internalID) + , m_Info(info) { m_DeviceUnavailableOnOpen = false; @@ -525,8 +524,8 @@ } -SoundDevice::Info Manager::FindDeviceInfo(const std::wstring &identifier) const -//----------------------------------------------------------------------------- +SoundDevice::Info Manager::FindDeviceInfo(SoundDevice::Identifier identifier) const +//--------------------------------------------------------------------------------- { if(m_SoundDevices.empty()) { @@ -547,8 +546,8 @@ } -static SoundDevice::Type ParseType(const std::wstring &identifier) -//---------------------------------------------------------------- +SoundDevice::Type ParseType(const SoundDevice::Identifier &identifier) +//-------------------------------------------------------------------- { for(int i = 0; i < TypeNUM_DEVTYPES; ++i) { @@ -562,8 +561,8 @@ } -SoundDevice::Info Manager::FindDeviceInfoBestMatch(const std::wstring &identifier, bool preferSameType) -//----------------------------------------------------------------------------------------------------- +SoundDevice::Info Manager::FindDeviceInfoBestMatch(SoundDevice::Identifier identifier, bool preferSameType) +//--------------------------------------------------------------------------------------------------------- { if(m_SoundDevices.empty()) { @@ -575,7 +574,7 @@ } for(std::vector<SoundDevice::Info>::const_iterator it = begin(); it != end(); ++it) { - if((it->GetIdentifier() == identifier) && !IsDeviceUnavailable(it->id)) + if((it->GetIdentifier() == identifier) && !IsDeviceUnavailable(it->GetIdentifier())) { // exact match return *it; } @@ -589,7 +588,7 @@ // just find the first WASAPI device. for(std::vector<SoundDevice::Info>::const_iterator it = begin(); it != end(); ++it) { - if((it->id.GetType() == TypePORTAUDIO_WASAPI) && !IsDeviceUnavailable(it->id)) + if((it->id.GetType() == TypePORTAUDIO_WASAPI) && !IsDeviceUnavailable(it->GetIdentifier())) { return *it; } @@ -608,7 +607,7 @@ { for(std::vector<SoundDevice::Info>::const_iterator it = begin(); it != end(); ++it) { - if((it->id.GetType() == type) && !IsDeviceUnavailable(it->id)) + if((it->id.GetType() == type) && !IsDeviceUnavailable(it->GetIdentifier())) { return *it; } @@ -625,16 +624,16 @@ } -bool Manager::OpenDriverSettings(SoundDevice::ID id, SoundDevice::IMessageReceiver *messageReceiver, SoundDevice::IBase *currentSoundDevice) -//------------------------------------------------------------------------------------------------------------------------------------------ +bool Manager::OpenDriverSettings(SoundDevice::Identifier identifier, SoundDevice::IMessageReceiver *messageReceiver, SoundDevice::IBase *currentSoundDevice) +//---------------------------------------------------------------------------------------------------------------------------------------------------------- { bool result = false; - if(currentSoundDevice && FindDeviceInfo(id).IsValid() && (currentSoundDevice->GetDeviceID() == id) && (currentSoundDevice->GetDeviceInternalID() == FindDeviceInfo(id).internalID)) + if(currentSoundDevice && FindDeviceInfo(identifier).IsValid() && (currentSoundDevice->GetDeviceIdentifier() == identifier)) { result = currentSoundDevice->OpenDriverSettings(); } else { - SoundDevice::IBase *dummy = CreateSoundDevice(id); + SoundDevice::IBase *dummy = CreateSoundDevice(identifier); if(dummy) { dummy->SetMessageReceiver(messageReceiver); @@ -646,82 +645,82 @@ } -SoundDevice::Caps Manager::GetDeviceCaps(SoundDevice::ID id, SoundDevice::IBase *currentSoundDevice) -//-------------------------------------------------------------------------------------------------- +SoundDevice::Caps Manager::GetDeviceCaps(SoundDevice::Identifier identifier, SoundDevice::IBase *currentSoundDevice) +//------------------------------------------------------------------------------------------------------------------ { - if(m_DeviceCaps.find(id) == m_DeviceCaps.end()) + if(m_DeviceCaps.find(identifier) == m_DeviceCaps.end()) { - if(currentSoundDevice && FindDeviceInfo(id).IsValid() && (currentSoundDevice->GetDeviceID() == id) && (currentSoundDevice->GetDeviceInternalID() == FindDeviceInfo(id).internalID)) + if(currentSoundDevice && FindDeviceInfo(identifier).IsValid() && (currentSoundDevice->GetDeviceIdentifier() == identifier)) { - m_DeviceCaps[id] = currentSoundDevice->GetDeviceCaps(); + m_DeviceCaps[identifier] = currentSoundDevice->GetDeviceCaps(); } else { - SoundDevice::IBase *dummy = CreateSoundDevice(id); + SoundDevice::IBase *dummy = CreateSoundDevice(identifier); if(dummy) { - m_DeviceCaps[id] = dummy->GetDeviceCaps(); + m_DeviceCaps[identifier] = dummy->GetDeviceCaps(); } else { - SetDeviceUnavailable(id); + SetDeviceUnavailable(identifier); } delete dummy; } } - return m_DeviceCaps[id]; + return m_DeviceCaps[identifier]; } -SoundDevice::DynamicCaps Manager::GetDeviceDynamicCaps(SoundDevice::ID id, const std::vector<uint32> &baseSampleRates, SoundDevice::IMessageReceiver *messageReceiver, SoundDevice::IBase *currentSoundDevice, bool update) -//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +SoundDevice::DynamicCaps Manager::GetDeviceDynamicCaps(SoundDevice::Identifier identifier, const std::vector<uint32> &baseSampleRates, SoundDevice::IMessageReceiver *messageReceiver, SoundDevice::IBase *currentSoundDevice, bool update) +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- { - if((m_DeviceDynamicCaps.find(id) == m_DeviceDynamicCaps.end()) || update) + if((m_DeviceDynamicCaps.find(identifier) == m_DeviceDynamicCaps.end()) || update) { - if(currentSoundDevice && FindDeviceInfo(id).IsValid() && (currentSoundDevice->GetDeviceID() == id) && (currentSoundDevice->GetDeviceInternalID() == FindDeviceInfo(id).internalID)) + if(currentSoundDevice && FindDeviceInfo(identifier).IsValid() && (currentSoundDevice->GetDeviceIdentifier() == identifier)) { - m_DeviceDynamicCaps[id] = currentSoundDevice->GetDeviceDynamicCaps(baseSampleRates); + m_DeviceDynamicCaps[identifier] = currentSoundDevice->GetDeviceDynamicCaps(baseSampleRates); if(!currentSoundDevice->IsAvailable()) { - SetDeviceUnavailable(id); + SetDeviceUnavailable(identifier); } } else { - SoundDevice::IBase *dummy = CreateSoundDevice(id); + SoundDevice::IBase *dummy = CreateSoundDevice(identifier); if(dummy) { dummy->SetMessageReceiver(messageReceiver); - m_DeviceDynamicCaps[id] = dummy->GetDeviceDynamicCaps(baseSampleRates); + m_DeviceDynamicCaps[identifier] = dummy->GetDeviceDynamicCaps(baseSampleRates); if(!dummy->IsAvailable()) { - SetDeviceUnavailable(id); + SetDeviceUnavailable(identifier); } } else { - SetDeviceUnavailable(id); + SetDeviceUnavailable(identifier); } delete dummy; } } - return m_DeviceDynamicCaps[id]; + return m_DeviceDynamicCaps[identifier]; } -SoundDevice::IBase * Manager::CreateSoundDevice(SoundDevice::ID id) -//----------------------------------------------------------------- +SoundDevice::IBase * Manager::CreateSoundDevice(SoundDevice::Identifier identifier) +//--------------------------------------------------------------------------------- { - const SoundDevice::Info info = FindDeviceInfo(id); + const SoundDevice::Info info = FindDeviceInfo(identifier); if(!info.IsValid()) { return nullptr; } SoundDevice::IBase *result = nullptr; - switch(id.GetType()) + switch(info.id.GetType()) { - case TypeWAVEOUT: result = new CWaveDevice(id, info.internalID); break; + case TypeWAVEOUT: result = new CWaveDevice(info); break; #ifndef NO_DSOUND - case TypeDSOUND: result = new CDSoundDevice(id, info.internalID); break; + case TypeDSOUND: result = new CDSoundDevice(info); break; #endif // NO_DSOUND #ifndef NO_ASIO - case TypeASIO: result = new CASIODevice(id, info.internalID); break; + case TypeASIO: result = new CASIODevice(info); break; #endif // NO_ASIO #ifndef NO_PORTAUDIO case TypePORTAUDIO_WASAPI: @@ -729,7 +728,7 @@ case TypePORTAUDIO_WMME: case TypePORTAUDIO_DS: case TypePORTAUDIO_ASIO: - result = SndDevPortaudioIsInitialized() ? new CPortaudioDevice(id, info.internalID) : nullptr; + result = SndDevPortaudioIsInitialized() ? new CPortaudioDevice(info) : nullptr; break; #endif // NO_PORTAUDIO } @@ -743,7 +742,7 @@ result = nullptr; return nullptr; } - m_DeviceCaps[id] = result->GetDeviceCaps(); // update cached caps + m_DeviceCaps[identifier] = result->GetDeviceCaps(); // update cached caps return result; } Modified: trunk/OpenMPT/sounddev/SoundDevice.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.h 2014-09-29 08:25:21 UTC (rev 4322) +++ trunk/OpenMPT/sounddev/SoundDevice.h 2014-09-29 09:01:08 UTC (rev 4323) @@ -154,6 +154,59 @@ }; +typedef std::wstring Identifier; + +SoundDevice::Type ParseType(const SoundDevice::Identifier &identifier); + + +struct Info +{ + SoundDevice::ID id; + std::wstring name; + std::wstring apiName; + std::wstring internalID; + bool isDefault; + Info() : id(TypeINVALID, 0), isDefault(false) { } + Info(SoundDevice::ID id, const std::wstring &name, const std::wstring &apiName, const std::wstring &internalID = std::wstring()) + : id(id) + , name(name) + , apiName(apiName) + , internalID(internalID) + , isDefault(false) + { + return; + } + bool IsValid() const + { + return id.IsValid(); + } + SoundDevice::Identifier GetIdentifier() const + { + if(!IsValid()) + { + return std::wstring(); + } + std::wstring result = apiName; + result += L"_"; + if(!internalID.empty()) + { + result += internalID; // safe to not contain special characters + } else if(!name.empty()) + { + // UTF8-encode the name and convert the utf8 to hex. + // This ensures that no special characters are contained in the configuration key. + std::string utf8String = mpt::To(mpt::CharsetUTF8, name); + std::wstring hexString = Util::BinToHex(std::vector<char>(utf8String.begin(), utf8String.end())); + result += hexString; + } else + { + result += mpt::ToWString(id.GetIndex()); + } + return result; + } +}; + + struct ChannelMapping { @@ -420,10 +473,12 @@ virtual void SetMessageReceiver(SoundDevice::IMessageReceiver *receiver) = 0; virtual SoundDevice::IMessageReceiver *GetMessageReceiver() const = 0; + virtual SoundDevice::Info GetDeviceInfo() const = 0; virtual SoundDevice::ID GetDeviceID() const = 0; virtual SoundDevice::Type GetDeviceType() const = 0; virtual SoundDevice::Index GetDeviceIndex() const = 0; virtual std::wstring GetDeviceInternalID() const = 0; + virtual SoundDevice::Identifier GetDeviceIdentifier() const = 0; virtual SoundDevice::Caps GetDeviceCaps() const = 0; virtual SoundDevice::DynamicCaps GetDeviceDynamicCaps(const std::vector<uint32> &baseSampleRates) = 0; @@ -474,10 +529,8 @@ SoundDevice::ISource *m_Source; SoundDevice::IMessageReceiver *m_MessageReceiver; - const SoundDevice::ID m_ID; + const SoundDevice::Info m_Info; - std::wstring m_InternalID; - private: SoundDevice::Caps m_Caps; @@ -545,7 +598,7 @@ protected: - Base(SoundDevice::ID id, const std::wstring &internalID); + Base(SoundDevice::Info info); public: @@ -556,10 +609,12 @@ void SetMessageReceiver(SoundDevice::IMessageReceiver *receiver) { m_MessageReceiver = receiver; } SoundDevice::IMessageReceiver *GetMessageReceiver() const { return m_MessageReceiver; } - SoundDevice::ID GetDeviceID() const { return m_ID; } - SoundDevice::Type GetDeviceType() const { return m_ID.GetType(); } - SoundDevice::Index GetDeviceIndex() const { return m_ID.GetIndex(); } - std::wstring GetDeviceInternalID() const { return m_InternalID; } + SoundDevice::Info GetDeviceInfo() const { return m_Info; } + SoundDevice::ID GetDeviceID() const { return m_Info.id; } + SoundDevice::Type GetDeviceType() const { return m_Info.id.GetType(); } + SoundDevice::Index GetDeviceIndex() const { return m_Info.id.GetIndex(); } + std::wstring GetDeviceInternalID() const { return m_Info.internalID; } + SoundDevice::Identifier GetDeviceIdentifier() const { return m_Info.GetIdentifier(); } SoundDevice::Caps GetDeviceCaps() const { return m_Caps; } virtual SoundDevice::DynamicCaps GetDeviceDynamicCaps(const std::vector<uint32> &baseSampleRates); @@ -597,63 +652,15 @@ }; -struct Info -{ - SoundDevice::ID id; - std::wstring name; - std::wstring apiName; - std::wstring internalID; - bool isDefault; - Info() : id(TypeINVALID, 0), isDefault(false) { } - Info(SoundDevice::ID id, const std::wstring &name, const std::wstring &apiName, const std::wstring &internalID = std::wstring()) - : id(id) - , name(name) - , apiName(apiName) - , internalID(internalID) - , isDefault(false) - { - return; - } - bool IsValid() const - { - return id.IsValid(); - } - std::wstring GetIdentifier() const - { - if(!IsValid()) - { - return std::wstring(); - } - std::wstring result = apiName; - result += L"_"; - if(!internalID.empty()) - { - result += internalID; // safe to not contain special characters - } else if(!name.empty()) - { - // UTF8-encode the name and convert the utf8 to hex. - // This ensures that no special characters are contained in the configuration key. - std::string utf8String = mpt::To(mpt::CharsetUTF8, name); - std::wstring hexString = Util::BinToHex(std::vector<char>(utf8String.begin(), utf8String.end())); - result += hexString; - } else - { - result += mpt::ToWString(id.GetIndex()); - } - return result; - } -}; - - //=========== class Manager //=========== { private: std::vector<SoundDevice::Info> m_SoundDevices; - std::map<SoundDevice::ID, bool> m_DeviceUnavailable; - std::map<SoundDevice::ID, SoundDevice::Caps> m_DeviceCaps; - std::map<SoundDevice::ID, SoundDevice::DynamicCaps> m_DeviceDynamicCaps; + std::map<SoundDevice::Identifier, bool> m_DeviceUnavailable; + std::map<SoundDevice::Identifier, SoundDevice::Caps> m_DeviceCaps; + std::map<SoundDevice::Identifier, SoundDevice::DynamicCaps> m_DeviceDynamicCaps; public: Manager(); @@ -668,18 +675,18 @@ const std::vector<SoundDevice::Info> & GetDeviceInfos() const { return m_SoundDevices; } SoundDevice::Info FindDeviceInfo(SoundDevice::ID id) const; - SoundDevice::Info FindDeviceInfo(const std::wstring &identifier) const; - SoundDevice::Info FindDeviceInfoBestMatch(const std::wstring &identifier, bool preferSameType = false); + SoundDevice::Info FindDeviceInfo(SoundDevice::Identifier identifier) const; + SoundDevice::Info FindDeviceInfoBestMatch(SoundDevice::Identifier identifier, bool preferSameType); - bool OpenDriverSettings(SoundDevice::ID id, SoundDevice::IMessageReceiver *messageReceiver = nullptr, SoundDevice::IBase *currentSoundDevice = nullptr); + bool OpenDriverSettings(SoundDevice::Identifier identifier, SoundDevice::IMessageReceiver *messageReceiver = nullptr, SoundDevice::IBase *currentSoundDevice = nullptr); - void SetDeviceUnavailable(SoundDevice::ID id) { m_DeviceUnavailable[id] = true; } - bool IsDeviceUnavailable(SoundDevice::ID id) { return m_DeviceUnavailable[id]; } + void SetDeviceUnavailable(SoundDevice::Identifier identifier) { m_DeviceUnavailable[identifier] = true; } + bool IsDeviceUnavailable(SoundDevice::Identifier identifier) { return m_DeviceUnavailable[identifier]; } - SoundDevice::Caps GetDeviceCaps(SoundDevice::ID id, SoundDevice::IBase *currentSoundDevice = nullptr); - SoundDevice::DynamicCaps GetDeviceDynamicCaps(SoundDevice::ID id, const std::vector<uint32> &baseSampleRates, SoundDevice::IMessageReceiver *messageReceiver = nullptr, SoundDevice::IBase *currentSoundDevice = nullptr, bool update = false); + SoundDevice::Caps GetDeviceCaps(SoundDevice::Identifier identifier, SoundDevice::IBase *currentSoundDevice = nullptr); + SoundDevice::DynamicCaps GetDeviceDynamicCaps(SoundDevice::Identifier identifier, const std::vector<uint32> &baseSampleRates, SoundDevice::IMessageReceiver *messageReceiver = nullptr, SoundDevice::IBase *currentSoundDevice = nullptr, bool update = false); - SoundDevice::IBase * CreateSoundDevice(SoundDevice::ID id); + SoundDevice::IBase * CreateSoundDevice(SoundDevice::Identifier identifier); }; Modified: trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2014-09-29 08:25:21 UTC (rev 4322) +++ trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2014-09-29 09:01:08 UTC (rev 4323) @@ -180,9 +180,9 @@ } -CASIODevice::CASIODevice(SoundDevice::ID id, const std::wstring &internalID) -//------------------------------------------------------------------------ - : SoundDevice::Base(id, internalID) +CASIODevice::CASIODevice(SoundDevice::Info info) +//---------------------------------------------- + : SoundDevice::Base(info) { InitMembers(); m_QueriedFeatures.reset(); Modified: trunk/OpenMPT/sounddev/SoundDeviceASIO.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceASIO.h 2014-09-29 08:25:21 UTC (rev 4322) +++ trunk/OpenMPT/sounddev/SoundDeviceASIO.h 2014-09-29 09:01:08 UTC (rev 4323) @@ -91,7 +91,7 @@ void SetRenderSilence(bool silence, bool wait=false); public: - CASIODevice(SoundDevice::ID id, const std::wstring &internalID); + CASIODevice(SoundDevice::Info info); ~CASIODevice(); private: Modified: trunk/OpenMPT/sounddev/SoundDeviceDirectSound.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceDirectSound.cpp 2014-09-29 08:25:21 UTC (rev 4322) +++ trunk/OpenMPT/sounddev/SoundDeviceDirectSound.cpp 2014-09-29 09:01:08 UTC (rev 4323) @@ -73,9 +73,9 @@ } -CDSoundDevice::CDSoundDevice(SoundDevice::ID id, const std::wstring &internalID) -//---------------------------------------------------------------------------- - : CSoundDeviceWithThread(id, internalID) +CDSoundDevice::CDSoundDevice(SoundDevice::Info info) +//-------------------------------------------------- + : CSoundDeviceWithThread(info) , m_piDS(NULL) , m_pPrimary(NULL) , m_pMixBuffer(NULL) Modified: trunk/OpenMPT/sounddev/SoundDeviceDirectSound.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceDirectSound.h 2014-09-29 08:25:21 UTC (rev 4322) +++ trunk/OpenMPT/sounddev/SoundDeviceDirectSound.h 2014-09-29 09:01:08 UTC (rev 4323) @@ -43,7 +43,7 @@ DWORD m_dwLatency; public: - CDSoundDevice(SoundDevice::ID id, const std::wstring &internalID); + CDSoundDevice(SoundDevice::Info info); ~CDSoundDevice(); public: Modified: trunk/OpenMPT/sounddev/SoundDevicePortAudio.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDevicePortAudio.cpp 2014-09-29 08:25:21 UTC (rev 4322) +++ trunk/OpenMPT/sounddev/SoundDevicePortAudio.cpp 2014-09-29 09:01:08 UTC (rev 4323) @@ -37,11 +37,11 @@ #include "../include/portaudio/src/common/pa_debugprint.h" -CPortaudioDevice::CPortaudioDevice(SoundDevice::ID id, const std::wstring &internalID) -//---------------------------------------------------------------------------------- - : SoundDevice::Base(id, internalID) +CPortaudioDevice::CPortaudioDevice(SoundDevice::Info info) +//-------------------------------------------------------- + : SoundDevice::Base(info) { - m_HostApi = SndDevTypeToHostApi(id.GetType()); + m_HostApi = SndDevTypeToHostApi(info.id.GetType()); MemsetZero(m_StreamParameters); m_Stream = 0; m_StreamInfo = 0; Modified: trunk/OpenMPT/sounddev/SoundDevicePortAudio.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDevicePortAudio.h 2014-09-29 08:25:21 UTC (rev 4322) +++ trunk/OpenMPT/sounddev/SoundDevicePortAudio.h 2014-09-29 09:01:08 UTC (rev 4323) @@ -44,7 +44,7 @@ double m_CurrentRealLatency; // seconds public: - CPortaudioDevice(SoundDevice::ID id, const std::wstring &internalID); + CPortaudioDevice(SoundDevice::Info info); ~CPortaudioDevice(); public: Modified: trunk/OpenMPT/sounddev/SoundDeviceThread.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceThread.h 2014-09-29 08:25:21 UTC (rev 4322) +++ trunk/OpenMPT/sounddev/SoundDeviceThread.h 2014-09-29 09:01:08 UTC (rev 4323) @@ -82,7 +82,7 @@ void SetWakeupEvent(HANDLE ev); void SetWakeupInterval(double seconds); public: - CSoundDeviceWithThread(SoundDevice::ID id, const std::wstring &internalID) : SoundDevice::Base(id, internalID), m_AudioThread(*this) {} + CSoundDeviceWithThread(SoundDevice::Info info) : SoundDevice::Base(info), m_AudioThread(*this) {} virtual ~CSoundDeviceWithThread() {} bool InternalStart(); void InternalStop(); Modified: trunk/OpenMPT/sounddev/SoundDeviceWaveout.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceWaveout.cpp 2014-09-29 08:25:21 UTC (rev 4322) +++ trunk/OpenMPT/sounddev/SoundDeviceWaveout.cpp 2014-09-29 09:01:08 UTC (rev 4323) @@ -42,9 +42,9 @@ static const std::size_t WAVEOUT_MAXBUFFERSIZE = 65536; -CWaveDevice::CWaveDevice(SoundDevice::ID id, const std::wstring &internalID) -//------------------------------------------------------------------------ - : CSoundDeviceWithThread(id, internalID) +CWaveDevice::CWaveDevice(SoundDevice::Info info) +//---------------------------------------------- + : CSoundDeviceWithThread(info) { m_ThreadWakeupEvent; m_hWaveOut = NULL; Modified: trunk/OpenMPT/sounddev/SoundDeviceWaveout.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceWaveout.h 2014-09-29 08:25:21 UTC (rev 4322) +++ trunk/OpenMPT/sounddev/SoundDeviceWaveout.h 2014-09-29 09:01:08 UTC (rev 4323) @@ -44,7 +44,7 @@ std::vector<std::vector<char> > m_WaveBuffersData; public: - CWaveDevice(SoundDevice::ID id, const std::wstring &internalID); + CWaveDevice(SoundDevice::Info info); ~CWaveDevice(); public: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <man...@us...> - 2014-09-29 12:22:02
|
Revision: 4324 http://sourceforge.net/p/modplug/code/4324 Author: manxorist Date: 2014-09-29 12:21:46 +0000 (Mon, 29 Sep 2014) Log Message: ----------- [Ref] Rename mpt::To(Charset to, string) to mpt::ToCharset(Charset to, string). Modified Paths: -------------- trunk/OpenMPT/common/Logging.cpp trunk/OpenMPT/common/mptPathString.cpp trunk/OpenMPT/common/mptPathString.h trunk/OpenMPT/common/mptString.cpp trunk/OpenMPT/common/mptString.h trunk/OpenMPT/libopenmpt/libopenmpt_impl.cpp trunk/OpenMPT/mptrack/AboutDialog.cpp trunk/OpenMPT/mptrack/Mpdlgs.cpp trunk/OpenMPT/mptrack/StreamEncoderFLAC.cpp trunk/OpenMPT/mptrack/StreamEncoderMP3.cpp trunk/OpenMPT/mptrack/StreamEncoderOpus.cpp trunk/OpenMPT/mptrack/StreamEncoderVorbis.cpp trunk/OpenMPT/mptrack/View_tre.cpp trunk/OpenMPT/sounddev/SoundDevice.h trunk/OpenMPT/soundlib/Load_ams.cpp trunk/OpenMPT/soundlib/Load_itp.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/WAVTools.cpp trunk/OpenMPT/test/test.cpp trunk/OpenMPT/unarchiver/unarchiver.cpp Modified: trunk/OpenMPT/common/Logging.cpp =================================================================== --- trunk/OpenMPT/common/Logging.cpp 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/common/Logging.cpp 2014-09-29 12:21:46 UTC (rev 4324) @@ -128,7 +128,7 @@ } if(s_logfile) { - fprintf(s_logfile, "%s+%s %s(%i): %s [%s]\n", TimeAsAsString(cur).c_str(), TimeDiffAsString(diff).c_str(), context.file, context.line, mpt::To(mpt::CharsetUTF8, message).c_str(), context.function); + fprintf(s_logfile, "%s+%s %s(%i): %s [%s]\n", TimeAsAsString(cur).c_str(), TimeDiffAsString(diff).c_str(), context.file, context.line, mpt::ToCharset(mpt::CharsetUTF8, message).c_str(), context.function); fflush(s_logfile); } } @@ -143,7 +143,7 @@ #if defined(MPT_WITH_CHARSET_LOCALE) << mpt::ToLocale(message) #else - << mpt::To(mpt::CharsetUTF8, message) + << mpt::ToCharset(mpt::CharsetUTF8, message) #endif << " [" << context.function << "]" << std::endl; Modified: trunk/OpenMPT/common/mptPathString.cpp =================================================================== --- trunk/OpenMPT/common/mptPathString.cpp 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/common/mptPathString.cpp 2014-09-29 12:21:46 UTC (rev 4324) @@ -174,7 +174,7 @@ // that filenames we get from MFC are always encoded in our hacked UTF8-in-CString encoding. // Instead, we use a rough heuristic: if the string is parseable as UTF8, we assume it is. // This fails for CP_ACP strings, that are also valid UTF8. That's the trade-off here. - if(mpt::To(mpt::CharsetUTF8, mpt::ToWide(mpt::CharsetUTF8, path.GetString())) == path.GetString()) + if(mpt::ToCharset(mpt::CharsetUTF8, mpt::ToWide(mpt::CharsetUTF8, path.GetString())) == path.GetString()) { // utf8 return mpt::PathString::FromUTF8(path.GetString()); @@ -228,7 +228,7 @@ #if defined(MPT_WITH_CHARSET_LOCALE) return fopen(filename.AsNative().c_str(), mode ? mpt::ToLocale(mode).c_str() : nullptr); #else - return fopen(filename.AsNative().c_str(), mode ? mpt::To(mpt::CharsetUTF8, mode).c_str() : nullptr); + return fopen(filename.AsNative().c_str(), mode ? mpt::ToCharset(mpt::CharsetUTF8, mode).c_str() : nullptr); #endif #endif // MPT_OS_WINDOWS } Modified: trunk/OpenMPT/common/mptPathString.h =================================================================== --- trunk/OpenMPT/common/mptPathString.h 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/common/mptPathString.h 2014-09-29 12:21:46 UTC (rev 4324) @@ -138,7 +138,7 @@ #if defined(MPT_WITH_CHARSET_LOCALE) MPT_DEPRECATED_PATH std::string ToLocale() const { return mpt::ToLocale(path); } #endif - std::string ToUTF8() const { return mpt::To(mpt::CharsetUTF8, path); } + std::string ToUTF8() const { return mpt::ToCharset(mpt::CharsetUTF8, path); } std::wstring ToWide() const { return path; } #if defined(MPT_WITH_CHARSET_LOCALE) MPT_DEPRECATED_PATH static PathString FromLocale(const std::string &path) { return PathString(mpt::ToWide(mpt::CharsetLocale, path)); } @@ -172,18 +172,18 @@ // conversions #if defined(MPT_WITH_CHARSET_LOCALE) std::string ToLocale() const { return path; } - std::string ToUTF8() const { return mpt::To(mpt::CharsetUTF8, mpt::CharsetLocale, path); } + std::string ToUTF8() const { return mpt::ToCharset(mpt::CharsetUTF8, mpt::CharsetLocale, path); } std::wstring ToWide() const { return mpt::ToWide(mpt::CharsetLocale, path); } static PathString FromLocale(const std::string &path) { return PathString(path); } - static PathString FromUTF8(const std::string &path) { return PathString(mpt::To(mpt::CharsetLocale, mpt::CharsetUTF8, path)); } - static PathString FromWide(const std::wstring &path) { return PathString(mpt::To(mpt::CharsetLocale, path)); } + static PathString FromUTF8(const std::string &path) { return PathString(mpt::ToCharset(mpt::CharsetLocale, mpt::CharsetUTF8, path)); } + static PathString FromWide(const std::wstring &path) { return PathString(mpt::ToCharset(mpt::CharsetLocale, path)); } RawPathString AsNative() const { return path; } static PathString FromNative(const RawPathString &path) { return PathString(path); } #else std::string ToUTF8() const { return path; } std::wstring ToWide() const { return mpt::ToWide(mpt::CharsetUTF8, path); } static PathString FromUTF8(const std::string &path) { return path; } - static PathString FromWide(const std::wstring &path) { return PathString(mpt::To(mpt::CharsetUTF8, path)); } + static PathString FromWide(const std::wstring &path) { return PathString(mpt::ToCharset(mpt::CharsetUTF8, path)); } RawPathString AsNative() const { return path; } static PathString FromNative(const RawPathString &path) { return PathString(path); } #endif Modified: trunk/OpenMPT/common/mptString.cpp =================================================================== --- trunk/OpenMPT/common/mptString.cpp 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/common/mptString.cpp 2014-09-29 12:21:46 UTC (rev 4324) @@ -1012,11 +1012,11 @@ return String::DecodeImpl(from, str); } -std::string To(Charset to, const std::wstring &str) +std::string ToCharset(Charset to, const std::wstring &str) { return String::EncodeImpl<std::string>(to, str); } -std::string To(Charset to, Charset from, const std::string &str) +std::string ToCharset(Charset to, Charset from, const std::string &str) { return String::ConvertImpl<std::string>(to, from, str); } @@ -1048,12 +1048,12 @@ return ToWide(CharsetLocale, str.GetString()); #endif } -std::string To(Charset to, const CString &str) +std::string ToCharset(Charset to, const CString &str) { #ifdef UNICODE - return To(to, str.GetString()); + return ToCharset(to, str.GetString()); #else - return To(to, CharsetLocale, str.GetString()); + return ToCharset(to, CharsetLocale, str.GetString()); #endif } @@ -1080,9 +1080,9 @@ { return str.GetString(); } -std::string To(Charset to, const CStringW &str) +std::string ToCharset(Charset to, const CStringW &str) { - return To(to, str.GetString()); + return ToCharset(to, str.GetString()); } CString ToCString(const CStringW &str) { @@ -1131,10 +1131,10 @@ std::string ToString(const char & x) { return std::string(1, x); } std::string ToString(const wchar_t & x) { return mpt::ToLocale(std::wstring(1, x)); } #else -std::string ToString(const std::wstring & x) { return mpt::To(mpt::CharsetUTF8, x); } -std::string ToString(const wchar_t * const & x) { return mpt::To(mpt::CharsetUTF8, x); } +std::string ToString(const std::wstring & x) { return mpt::ToCharset(mpt::CharsetUTF8, x); } +std::string ToString(const wchar_t * const & x) { return mpt::ToCharset(mpt::CharsetUTF8, x); } std::string ToString(const char & x) { return std::string(1, x); } -std::string ToString(const wchar_t & x) { return mpt::To(mpt::CharsetUTF8, std::wstring(1, x)); } +std::string ToString(const wchar_t & x) { return mpt::ToCharset(mpt::CharsetUTF8, std::wstring(1, x)); } #endif std::string ToString(const bool & x) { return ToStringHelper(x); } std::string ToString(const signed char & x) { return ToStringHelper(x); } Modified: trunk/OpenMPT/common/mptString.h =================================================================== --- trunk/OpenMPT/common/mptString.h 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/common/mptString.h 2014-09-29 12:21:46 UTC (rev 4324) @@ -184,8 +184,8 @@ // 'to' is UTF8. // Invalid source bytes or characters that are not representable in the // destination charset will be replaced by some replacement character or string. -std::string To(Charset to, const std::wstring &str); -std::string To(Charset to, Charset from, const std::string &str); +std::string ToCharset(Charset to, const std::wstring &str); +std::string ToCharset(Charset to, Charset from, const std::string &str); #if defined(_MFC_VER) @@ -201,11 +201,11 @@ // This should also be used when converting from TCHAR strings. // If UNICODE is defined, this is a completely lossless operation. std::wstring ToWide(const CString &str); -std::string To(Charset to, const CString &str); +std::string ToCharset(Charset to, const CString &str); // Provide un-ambiguous conversion from wide string literal. static inline std::wstring ToWide(const wchar_t * str) { return ToWide(str ? std::wstring(str) : std::wstring()); } -static inline std::string To(Charset to, const wchar_t * str) { return To(to, str ? std::wstring(str) : std::wstring()); } +static inline std::string ToCharset(Charset to, const wchar_t * str) { return ToCharset(to, str ? std::wstring(str) : std::wstring()); } static inline CString ToCString(const wchar_t * str) { return ToCString(str ? std::wstring(str) : std::wstring()); } #ifdef UNICODE @@ -218,7 +218,7 @@ CStringW ToCStringW(Charset from, const std::string &str); CStringW ToCStringW(const CStringW &str); std::wstring ToWide(const CStringW &str); -std::string To(Charset to, const CStringW &str); +std::string ToCharset(Charset to, const CStringW &str); CString ToCString(const CStringW &str); #endif // UNICODE @@ -234,8 +234,8 @@ // windows AND a UTF8 locale is set. // Invalid source bytes or characters that are not representable in the // destination charset will be replaced by some replacement character or string. -template <typename Tsrc> inline std::string ToLocale(const Tsrc &str) { return To(CharsetLocale, str); } -static inline std::string ToLocale(Charset from, const std::string &str) { return To(CharsetLocale, from, str); } +template <typename Tsrc> inline std::string ToLocale(const Tsrc &str) { return ToCharset(CharsetLocale, str); } +static inline std::string ToLocale(Charset from, const std::string &str) { return ToCharset(CharsetLocale, from, str); } #endif Modified: trunk/OpenMPT/libopenmpt/libopenmpt_impl.cpp =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt_impl.cpp 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/libopenmpt/libopenmpt_impl.cpp 2014-09-29 12:21:46 UTC (rev 4324) @@ -281,7 +281,7 @@ } std::string module_impl::mod_string_to_utf8( const std::string & encoded ) const { - return mpt::To( mpt::CharsetUTF8, m_sndFile->GetCharset(), encoded ); + return mpt::ToCharset( mpt::CharsetUTF8, m_sndFile->GetCharset(), encoded ); } void module_impl::apply_mixer_settings( std::int32_t samplerate, int channels ) { if ( Modified: trunk/OpenMPT/mptrack/AboutDialog.cpp =================================================================== --- trunk/OpenMPT/mptrack/AboutDialog.cpp 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/mptrack/AboutDialog.cpp 2014-09-29 12:21:46 UTC (rev 4324) @@ -237,7 +237,7 @@ SetDlgItemText(IDC_EDIT2, CString("Build Date: ") + MptVersion::GetBuildDateString().c_str()); SetDlgItemText(IDC_EDIT3, CString("OpenMPT ") + MptVersion::GetVersionStringExtended().c_str()); m_static.SubclassDlgItem(IDC_CREDITS,this); - m_static.SetCredits((mpt::String::Replace(mpt::To(mpt::CharsetLocale, mpt::CharsetUTF8, MptVersion::GetFullCreditsString()), "\n", "|") + "|" + mpt::String::Replace(MptVersion::GetContactString(), "\n", "|" ) + "||||||").c_str()); + m_static.SetCredits((mpt::String::Replace(mpt::ToCharset(mpt::CharsetLocale, mpt::CharsetUTF8, MptVersion::GetFullCreditsString()), "\n", "|") + "|" + mpt::String::Replace(MptVersion::GetContactString(), "\n", "|" ) + "||||||").c_str()); m_static.SetSpeed(DISPLAY_SLOW); m_static.SetColor(BACKGROUND_COLOR, RGB(138, 165, 219)); // Background Colour m_static.SetTransparent(); // Set parts of bitmaps with RGB(192,192,192) transparent Modified: trunk/OpenMPT/mptrack/Mpdlgs.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mpdlgs.cpp 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/mptrack/Mpdlgs.cpp 2014-09-29 12:21:46 UTC (rev 4324) @@ -61,7 +61,7 @@ static double ParseTime(CString str) { - return ConvertStrTo<double>(mpt::To(mpt::CharsetASCII, str)) / 1000.0; + return ConvertStrTo<double>(mpt::ToCharset(mpt::CharsetASCII, str)) / 1000.0; } Modified: trunk/OpenMPT/mptrack/StreamEncoderFLAC.cpp =================================================================== --- trunk/OpenMPT/mptrack/StreamEncoderFLAC.cpp 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/mptrack/StreamEncoderFLAC.cpp 2014-09-29 12:21:46 UTC (rev 4324) @@ -118,7 +118,7 @@ if(!field.empty() && !data.empty()) { FLAC__StreamMetadata_VorbisComment_Entry entry; - FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, field.c_str(), mpt::To(mpt::CharsetUTF8, data).c_str()); + FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, field.c_str(), mpt::ToCharset(mpt::CharsetUTF8, data).c_str()); FLAC__metadata_object_vorbiscomment_append_comment(flac_metadata[0], entry, false); } } Modified: trunk/OpenMPT/mptrack/StreamEncoderMP3.cpp =================================================================== --- trunk/OpenMPT/mptrack/StreamEncoderMP3.cpp 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/mptrack/StreamEncoderMP3.cpp 2014-09-29 12:21:46 UTC (rev 4324) @@ -184,17 +184,17 @@ s.write(reinterpret_cast<const char*>(&tHeader), sizeof(tHeader)); // Write TIT2 (Title), TCOM / TPE1 (Composer), TALB (Album), TCON (Genre), TYER / TDRC (Date), WXXX (URL), TENC (Encoder), COMM (Comment) - WriteID3v2Frame("TIT2", mpt::To(mpt::CharsetUTF8, tags.title), s); - WriteID3v2Frame("TPE1", mpt::To(mpt::CharsetUTF8, tags.artist), s); - WriteID3v2Frame("TCOM", mpt::To(mpt::CharsetUTF8, tags.artist), s); - WriteID3v2Frame("TALB", mpt::To(mpt::CharsetUTF8, tags.album), s); - WriteID3v2Frame("TCON", mpt::To(mpt::CharsetUTF8, tags.genre), s); - //WriteID3v2Frame("TYER", mpt::To(mpt::CharsetUTF8, tags.year), s); // Deprecated - WriteID3v2Frame("TDRC", mpt::To(mpt::CharsetUTF8, tags.year), s); - WriteID3v2Frame("TBPM", mpt::To(mpt::CharsetUTF8, tags.bpm), s); - WriteID3v2Frame("WXXX", mpt::To(mpt::CharsetUTF8, tags.url), s); - WriteID3v2Frame("TENC", mpt::To(mpt::CharsetUTF8, tags.encoder), s); - WriteID3v2Frame("COMM", mpt::To(mpt::CharsetUTF8, tags.comments), s); + WriteID3v2Frame("TIT2", mpt::ToCharset(mpt::CharsetUTF8, tags.title), s); + WriteID3v2Frame("TPE1", mpt::ToCharset(mpt::CharsetUTF8, tags.artist), s); + WriteID3v2Frame("TCOM", mpt::ToCharset(mpt::CharsetUTF8, tags.artist), s); + WriteID3v2Frame("TALB", mpt::ToCharset(mpt::CharsetUTF8, tags.album), s); + WriteID3v2Frame("TCON", mpt::ToCharset(mpt::CharsetUTF8, tags.genre), s); + //WriteID3v2Frame("TYER", mpt::ToCharset(mpt::CharsetUTF8, tags.year), s); // Deprecated + WriteID3v2Frame("TDRC", mpt::ToCharset(mpt::CharsetUTF8, tags.year), s); + WriteID3v2Frame("TBPM", mpt::ToCharset(mpt::CharsetUTF8, tags.bpm), s); + WriteID3v2Frame("WXXX", mpt::ToCharset(mpt::CharsetUTF8, tags.url), s); + WriteID3v2Frame("TENC", mpt::ToCharset(mpt::CharsetUTF8, tags.encoder), s); + WriteID3v2Frame("COMM", mpt::ToCharset(mpt::CharsetUTF8, tags.comments), s); // Write Padding for(size_t i = 0; i < ID3v2_PADDING; i++) @@ -557,13 +557,13 @@ virtual void WriteMetatags(const FileTags &tags) { // Lame API expects Latin1, which is sad, but we cannot change that. - if(!tags.title.empty()) lame.id3tag_set_title( gfp, mpt::To(mpt::CharsetISO8859_1, tags.title ).c_str()); - if(!tags.artist.empty()) lame.id3tag_set_artist( gfp, mpt::To(mpt::CharsetISO8859_1, tags.artist ).c_str()); - if(!tags.album.empty()) lame.id3tag_set_album( gfp, mpt::To(mpt::CharsetISO8859_1, tags.album ).c_str()); - if(!tags.year.empty()) lame.id3tag_set_year( gfp, mpt::To(mpt::CharsetISO8859_1, tags.year ).c_str()); - if(!tags.comments.empty()) lame.id3tag_set_comment( gfp, mpt::To(mpt::CharsetISO8859_1, tags.comments).c_str()); - if(!tags.trackno.empty()) lame.id3tag_set_track( gfp, mpt::To(mpt::CharsetISO8859_1, tags.trackno ).c_str()); - if(!tags.genre.empty()) lame.id3tag_set_genre( gfp, mpt::To(mpt::CharsetISO8859_1, tags.genre ).c_str()); + if(!tags.title.empty()) lame.id3tag_set_title( gfp, mpt::ToCharset(mpt::CharsetISO8859_1, tags.title ).c_str()); + if(!tags.artist.empty()) lame.id3tag_set_artist( gfp, mpt::ToCharset(mpt::CharsetISO8859_1, tags.artist ).c_str()); + if(!tags.album.empty()) lame.id3tag_set_album( gfp, mpt::ToCharset(mpt::CharsetISO8859_1, tags.album ).c_str()); + if(!tags.year.empty()) lame.id3tag_set_year( gfp, mpt::ToCharset(mpt::CharsetISO8859_1, tags.year ).c_str()); + if(!tags.comments.empty()) lame.id3tag_set_comment( gfp, mpt::ToCharset(mpt::CharsetISO8859_1, tags.comments).c_str()); + if(!tags.trackno.empty()) lame.id3tag_set_track( gfp, mpt::ToCharset(mpt::CharsetISO8859_1, tags.trackno ).c_str()); + if(!tags.genre.empty()) lame.id3tag_set_genre( gfp, mpt::ToCharset(mpt::CharsetISO8859_1, tags.genre ).c_str()); } virtual void WriteInterleaved(size_t count, const float *interleaved) { Modified: trunk/OpenMPT/mptrack/StreamEncoderOpus.cpp =================================================================== --- trunk/OpenMPT/mptrack/StreamEncoderOpus.cpp 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/mptrack/StreamEncoderOpus.cpp 2014-09-29 12:21:46 UTC (rev 4324) @@ -326,7 +326,7 @@ { if(!field.empty() && !data.empty()) { - opus_comments.push_back(field + "=" + mpt::To(mpt::CharsetUTF8, data)); + opus_comments.push_back(field + "=" + mpt::ToCharset(mpt::CharsetUTF8, data)); } } public: Modified: trunk/OpenMPT/mptrack/StreamEncoderVorbis.cpp =================================================================== --- trunk/OpenMPT/mptrack/StreamEncoderVorbis.cpp 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/mptrack/StreamEncoderVorbis.cpp 2014-09-29 12:21:46 UTC (rev 4324) @@ -291,7 +291,7 @@ { if(!field.empty() && !data.empty()) { - vorbis.vorbis_comment_add_tag(&vc, field.c_str(), mpt::To(mpt::CharsetUTF8, data).c_str()); + vorbis.vorbis_comment_add_tag(&vc, field.c_str(), mpt::ToCharset(mpt::CharsetUTF8, data).c_str()); } } public: Modified: trunk/OpenMPT/mptrack/View_tre.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_tre.cpp 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/mptrack/View_tre.cpp 2014-09-29 12:21:46 UTC (rev 4324) @@ -1745,7 +1745,7 @@ } else if(wfd.nFileSizeHigh > 0 || wfd.nFileSizeLow >= 16) { // Get lower-case file extension without dot. - const std::string ext = mpt::To(mpt::CharsetUTF8, mpt::PathString::FromNative(wfd.cFileName).GetFileExt().ToWide()); + const std::string ext = mpt::ToCharset(mpt::CharsetUTF8, mpt::PathString::FromNative(wfd.cFileName).GetFileExt().ToWide()); char s[16]; mpt::String::Copy(s, ext); Modified: trunk/OpenMPT/sounddev/SoundDevice.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.h 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/sounddev/SoundDevice.h 2014-09-29 12:21:46 UTC (rev 4324) @@ -195,7 +195,7 @@ { // UTF8-encode the name and convert the utf8 to hex. // This ensures that no special characters are contained in the configuration key. - std::string utf8String = mpt::To(mpt::CharsetUTF8, name); + std::string utf8String = mpt::ToCharset(mpt::CharsetUTF8, name); std::wstring hexString = Util::BinToHex(std::vector<char>(utf8String.begin(), utf8String.end())); result += hexString; } else Modified: trunk/OpenMPT/soundlib/Load_ams.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_ams.cpp 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/soundlib/Load_ams.cpp 2014-09-29 12:21:46 UTC (rev 4324) @@ -469,7 +469,7 @@ std::string str; std::copy(textOut.begin(), textOut.end(), std::back_inserter(str)); - str = mpt::To(mpt::CharsetCP437, mpt::CharsetCP437AMS, str); + str = mpt::ToCharset(mpt::CharsetCP437, mpt::CharsetCP437AMS, str); // Packed text doesn't include any line breaks! songMessage.ReadFixedLineLength(str.c_str(), str.length(), 76, 0); @@ -895,7 +895,7 @@ { std::string str; file.ReadString<mpt::String::spacePadded>(str, composerLength); - str = mpt::To(mpt::CharsetCP437, mpt::CharsetCP437AMS2, str); + str = mpt::ToCharset(mpt::CharsetCP437, mpt::CharsetCP437AMS2, str); songMessage.Read(str.c_str(), str.length(), SongMessage::leAutodetect); songArtist = str; } @@ -938,7 +938,7 @@ } std::string str; std::copy(textOut.begin(), textOut.begin() + descriptionHeader.unpackedLen, std::back_inserter(str)); - str = mpt::To(mpt::CharsetCP437, mpt::CharsetCP437AMS2, str); + str = mpt::ToCharset(mpt::CharsetCP437, mpt::CharsetCP437AMS2, str); // Packed text doesn't include any line breaks! songMessage.ReadFixedLineLength(str.c_str(), str.length(), 74, 0); } Modified: trunk/OpenMPT/soundlib/Load_itp.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_itp.cpp 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/soundlib/Load_itp.cpp 2014-09-29 12:21:46 UTC (rev 4324) @@ -157,7 +157,7 @@ file.ReadString<mpt::String::maybeNullTerminated>(path, size); if(version <= 0x00000102) { - path = mpt::To(mpt::CharsetUTF8, mpt::CharsetLocale, path); + path = mpt::ToCharset(mpt::CharsetUTF8, mpt::CharsetLocale, path); } m_szInstrumentPath[ins] = mpt::PathString::FromUTF8(path); Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2014-09-29 12:21:46 UTC (rev 4324) @@ -2375,9 +2375,9 @@ for(PLUGINDEX i = 0; i < MAX_MIXPLUGINS; i++) { #if defined(MODPLUG_TRACKER) - const std::string name = mpt::To(mpt::CharsetUTF8, mpt::CharsetLocale, m_MixPlugins[i].Info.szLibraryName); + const std::string name = mpt::ToCharset(mpt::CharsetUTF8, mpt::CharsetLocale, m_MixPlugins[i].Info.szLibraryName); #else - const std::string name = mpt::To(mpt::CharsetUTF8, mpt::CharsetWindows1252, m_MixPlugins[i].Info.szLibraryName); + const std::string name = mpt::ToCharset(mpt::CharsetUTF8, mpt::CharsetWindows1252, m_MixPlugins[i].Info.szLibraryName); #endif mpt::String::Copy(m_MixPlugins[i].Info.szLibraryName, name); } Modified: trunk/OpenMPT/soundlib/WAVTools.cpp =================================================================== --- trunk/OpenMPT/soundlib/WAVTools.cpp 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/soundlib/WAVTools.cpp 2014-09-29 12:21:46 UTC (rev 4324) @@ -507,7 +507,7 @@ void WAVWriter::WriteTag(RIFFChunk::id_type id, const std::wstring &wideText) //--------------------------------------------------------------------------- { - std::string text = mpt::To(mpt::CharsetWindows1252, wideText); + std::string text = mpt::ToCharset(mpt::CharsetWindows1252, wideText); if(!text.empty()) { const size_t length = text.length() + 1; Modified: trunk/OpenMPT/test/test.cpp =================================================================== --- trunk/OpenMPT/test/test.cpp 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/test/test.cpp 2014-09-29 12:21:46 UTC (rev 4324) @@ -556,9 +556,9 @@ } // Charset conversions (basic sanity checks) - VERIFY_EQUAL(mpt::To(mpt::CharsetUTF8, L"a"), "a"); - VERIFY_EQUAL(mpt::To(mpt::CharsetISO8859_1, L"a"), "a"); - VERIFY_EQUAL(mpt::To(mpt::CharsetASCII, L"a"), "a"); + VERIFY_EQUAL(mpt::ToCharset(mpt::CharsetUTF8, L"a"), "a"); + VERIFY_EQUAL(mpt::ToCharset(mpt::CharsetISO8859_1, L"a"), "a"); + VERIFY_EQUAL(mpt::ToCharset(mpt::CharsetASCII, L"a"), "a"); VERIFY_EQUAL(mpt::ToWide(mpt::CharsetUTF8, "a"), L"a"); VERIFY_EQUAL(mpt::ToWide(mpt::CharsetISO8859_1, "a"), L"a"); VERIFY_EQUAL(mpt::ToWide(mpt::CharsetASCII, "a"), L"a"); @@ -570,30 +570,30 @@ // Check that some character replacement is done (and not just empty strings or truncated strings are returned) // We test german umlaut-a (U+00E4) and CJK U+5BB6 - VERIFY_EQUAL(EndsWith(mpt::To(mpt::CharsetASCII,L"abc\u00E4xyz"),"xyz"),true); - VERIFY_EQUAL(EndsWith(mpt::To(mpt::CharsetISO8859_1,L"abc\u00E4xyz"),"xyz"),true); - VERIFY_EQUAL(EndsWith(mpt::To(mpt::CharsetCP437,L"abc\u00E4xyz"),"xyz"),true); - VERIFY_EQUAL(EndsWith(mpt::To(mpt::CharsetUTF8,L"abc\u00E4xyz"),"xyz"),true); - VERIFY_EQUAL(BeginsWith(mpt::To(mpt::CharsetASCII,L"abc\u00E4xyz"),"abc"),true); - VERIFY_EQUAL(BeginsWith(mpt::To(mpt::CharsetISO8859_1,L"abc\u00E4xyz"),"abc"),true); - VERIFY_EQUAL(BeginsWith(mpt::To(mpt::CharsetCP437,L"abc\u00E4xyz"),"abc"),true); - VERIFY_EQUAL(BeginsWith(mpt::To(mpt::CharsetUTF8,L"abc\u00E4xyz"),"abc"),true); + VERIFY_EQUAL(EndsWith(mpt::ToCharset(mpt::CharsetASCII,L"abc\u00E4xyz"),"xyz"),true); + VERIFY_EQUAL(EndsWith(mpt::ToCharset(mpt::CharsetISO8859_1,L"abc\u00E4xyz"),"xyz"),true); + VERIFY_EQUAL(EndsWith(mpt::ToCharset(mpt::CharsetCP437,L"abc\u00E4xyz"),"xyz"),true); + VERIFY_EQUAL(EndsWith(mpt::ToCharset(mpt::CharsetUTF8,L"abc\u00E4xyz"),"xyz"),true); + VERIFY_EQUAL(BeginsWith(mpt::ToCharset(mpt::CharsetASCII,L"abc\u00E4xyz"),"abc"),true); + VERIFY_EQUAL(BeginsWith(mpt::ToCharset(mpt::CharsetISO8859_1,L"abc\u00E4xyz"),"abc"),true); + VERIFY_EQUAL(BeginsWith(mpt::ToCharset(mpt::CharsetCP437,L"abc\u00E4xyz"),"abc"),true); + VERIFY_EQUAL(BeginsWith(mpt::ToCharset(mpt::CharsetUTF8,L"abc\u00E4xyz"),"abc"),true); #if defined(MPT_WITH_CHARSET_LOCALE) - VERIFY_EQUAL(EndsWith(mpt::To(mpt::CharsetLocale,L"abc\u00E4xyz"),"xyz"),true); - VERIFY_EQUAL(BeginsWith(mpt::To(mpt::CharsetLocale,L"abc\u00E4xyz"),"abc"),true); + VERIFY_EQUAL(EndsWith(mpt::ToCharset(mpt::CharsetLocale,L"abc\u00E4xyz"),"xyz"),true); + VERIFY_EQUAL(BeginsWith(mpt::ToCharset(mpt::CharsetLocale,L"abc\u00E4xyz"),"abc"),true); #endif - VERIFY_EQUAL(EndsWith(mpt::To(mpt::CharsetASCII,L"abc\u5BB6xyz"),"xyz"),true); - VERIFY_EQUAL(EndsWith(mpt::To(mpt::CharsetISO8859_1,L"abc\u5BB6xyz"),"xyz"),true); - VERIFY_EQUAL(EndsWith(mpt::To(mpt::CharsetCP437,L"abc\u5BB6xyz"),"xyz"),true); - VERIFY_EQUAL(EndsWith(mpt::To(mpt::CharsetUTF8,L"abc\u5BB6xyz"),"xyz"),true); - VERIFY_EQUAL(BeginsWith(mpt::To(mpt::CharsetASCII,L"abc\u5BB6xyz"),"abc"),true); - VERIFY_EQUAL(BeginsWith(mpt::To(mpt::CharsetISO8859_1,L"abc\u5BB6xyz"),"abc"),true); - VERIFY_EQUAL(BeginsWith(mpt::To(mpt::CharsetCP437,L"abc\u5BB6xyz"),"abc"),true); - VERIFY_EQUAL(BeginsWith(mpt::To(mpt::CharsetUTF8,L"abc\u5BB6xyz"),"abc"),true); + VERIFY_EQUAL(EndsWith(mpt::ToCharset(mpt::CharsetASCII,L"abc\u5BB6xyz"),"xyz"),true); + VERIFY_EQUAL(EndsWith(mpt::ToCharset(mpt::CharsetISO8859_1,L"abc\u5BB6xyz"),"xyz"),true); + VERIFY_EQUAL(EndsWith(mpt::ToCharset(mpt::CharsetCP437,L"abc\u5BB6xyz"),"xyz"),true); + VERIFY_EQUAL(EndsWith(mpt::ToCharset(mpt::CharsetUTF8,L"abc\u5BB6xyz"),"xyz"),true); + VERIFY_EQUAL(BeginsWith(mpt::ToCharset(mpt::CharsetASCII,L"abc\u5BB6xyz"),"abc"),true); + VERIFY_EQUAL(BeginsWith(mpt::ToCharset(mpt::CharsetISO8859_1,L"abc\u5BB6xyz"),"abc"),true); + VERIFY_EQUAL(BeginsWith(mpt::ToCharset(mpt::CharsetCP437,L"abc\u5BB6xyz"),"abc"),true); + VERIFY_EQUAL(BeginsWith(mpt::ToCharset(mpt::CharsetUTF8,L"abc\u5BB6xyz"),"abc"),true); #if defined(MPT_WITH_CHARSET_LOCALE) - VERIFY_EQUAL(EndsWith(mpt::To(mpt::CharsetLocale,L"abc\u5BB6xyz"),"xyz"),true); - VERIFY_EQUAL(BeginsWith(mpt::To(mpt::CharsetLocale,L"abc\u5BB6xyz"),"abc"),true); + VERIFY_EQUAL(EndsWith(mpt::ToCharset(mpt::CharsetLocale,L"abc\u5BB6xyz"),"xyz"),true); + VERIFY_EQUAL(BeginsWith(mpt::ToCharset(mpt::CharsetLocale,L"abc\u5BB6xyz"),"abc"),true); #endif VERIFY_EQUAL(EndsWith(mpt::ToWide(mpt::CharsetASCII,"abc\xC3\xA4xyz"),L"xyz"),true); @@ -626,17 +626,17 @@ // We test german umlaut-a (U+00E4) and CJK U+5BB6 // cp437 - VERIFY_EQUAL(mpt::To(mpt::CharsetCP437,L"abc\u00E4xyz"),"abc\x84xyz"); + VERIFY_EQUAL(mpt::ToCharset(mpt::CharsetCP437,L"abc\u00E4xyz"),"abc\x84xyz"); VERIFY_EQUAL(L"abc\u00E4xyz",mpt::ToWide(mpt::CharsetCP437,"abc\x84xyz")); // iso8859 - VERIFY_EQUAL(mpt::To(mpt::CharsetISO8859_1,L"abc\u00E4xyz"),"abc\xE4xyz"); + VERIFY_EQUAL(mpt::ToCharset(mpt::CharsetISO8859_1,L"abc\u00E4xyz"),"abc\xE4xyz"); VERIFY_EQUAL(L"abc\u00E4xyz",mpt::ToWide(mpt::CharsetISO8859_1,"abc\xE4xyz")); // utf8 - VERIFY_EQUAL(mpt::To(mpt::CharsetUTF8,L"abc\u00E4xyz"),"abc\xC3\xA4xyz"); + VERIFY_EQUAL(mpt::ToCharset(mpt::CharsetUTF8,L"abc\u00E4xyz"),"abc\xC3\xA4xyz"); VERIFY_EQUAL(L"abc\u00E4xyz",mpt::ToWide(mpt::CharsetUTF8,"abc\xC3\xA4xyz")); - VERIFY_EQUAL(mpt::To(mpt::CharsetUTF8,L"abc\u5BB6xyz"),"abc\xE5\xAE\xB6xyz"); + VERIFY_EQUAL(mpt::ToCharset(mpt::CharsetUTF8,L"abc\u5BB6xyz"),"abc\xE5\xAE\xB6xyz"); VERIFY_EQUAL(L"abc\u5BB6xyz",mpt::ToWide(mpt::CharsetUTF8,"abc\xE5\xAE\xB6xyz")); // Path conversions Modified: trunk/OpenMPT/unarchiver/unarchiver.cpp =================================================================== --- trunk/OpenMPT/unarchiver/unarchiver.cpp 2014-09-29 09:01:08 UTC (rev 4323) +++ trunk/OpenMPT/unarchiver/unarchiver.cpp 2014-09-29 12:21:46 UTC (rev 4324) @@ -97,7 +97,7 @@ { continue; } - const std::string ext = mpt::To(mpt::CharsetUTF8, GetExtension(at(i).name.ToWide())); + const std::string ext = mpt::ToCharset(mpt::CharsetUTF8, GetExtension(at(i).name.ToWide())); // Compare with list of preferred extensions if(std::find_if(extensions.begin(), extensions.end(), find_str(ext.c_str())) != extensions.end()) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <man...@us...> - 2014-09-29 13:43:35
|
Revision: 4326 http://sourceforge.net/p/modplug/code/4326 Author: manxorist Date: 2014-09-29 13:43:27 +0000 (Mon, 29 Sep 2014) Log Message: ----------- [Ref] Avoid source code duplication and implement RTrim, LTrim, Trim and Replace as templates. Modified Paths: -------------- trunk/OpenMPT/common/mptString.h trunk/OpenMPT/test/test.cpp Modified: trunk/OpenMPT/common/mptString.h =================================================================== --- trunk/OpenMPT/common/mptString.h 2014-09-29 12:38:02 UTC (rev 4325) +++ trunk/OpenMPT/common/mptString.h 2014-09-29 13:43:27 UTC (rev 4326) @@ -30,79 +30,70 @@ { +template <typename Tstring> struct Traits { + static const char * GetDefaultWhitespace() { return " \n\r\t"; } +}; + +template <> struct Traits<std::string> { + static const char * GetDefaultWhitespace() { return " \n\r\t"; } +}; + +template <> struct Traits<std::wstring> { + static const wchar_t * GetDefaultWhitespace() { return L" \n\r\t"; } +}; + + // Remove whitespace at start of string -static inline std::string LTrim(std::string str, const std::string &whitespace = " \n\r\t") -//----------------------------------------------------------------------------------------- +template <typename Tstring> +inline Tstring LTrim(Tstring str, const Tstring &whitespace = mpt::String::Traits<Tstring>::GetDefaultWhitespace()) +//----------------------------------------------------------------------------------------------------------------- { - std::string::size_type pos = str.find_first_not_of(whitespace); - if(pos != std::string::npos) + typename Tstring::size_type pos = str.find_first_not_of(whitespace); + if(pos != Tstring::npos) { str.erase(str.begin(), str.begin() + pos); - } else if(pos == std::string::npos && str.length() > 0 && str.find_last_of(whitespace) == str.length() - 1) + } else if(pos == Tstring::npos && str.length() > 0 && str.find_last_of(whitespace) == str.length() - 1) { - return std::string(); + return Tstring(); } return str; } -static inline std::wstring LTrim(std::wstring str, const std::wstring &whitespace = L" \n\r\t") -{ - std::wstring::size_type pos = str.find_first_not_of(whitespace); - if(pos != std::wstring::npos) - { - str.erase(str.begin(), str.begin() + pos); - } else if(pos == std::wstring::npos && str.length() > 0 && str.find_last_of(whitespace) == str.length() - 1) - { - return std::wstring(); - } - return str; -} // Remove whitespace at end of string -static inline std::string RTrim(std::string str, const std::string &whitespace = " \n\r\t") -//----------------------------------------------------------------------------------------- +template <typename Tstring> +inline Tstring RTrim(Tstring str, const Tstring &whitespace = mpt::String::Traits<Tstring>::GetDefaultWhitespace()) +//----------------------------------------------------------------------------------------------------------------- { - std::string::size_type pos = str.find_last_not_of(whitespace); - if(pos != std::string::npos) + typename Tstring::size_type pos = str.find_last_not_of(whitespace); + if(pos != Tstring::npos) { str.erase(str.begin() + pos + 1, str.end()); - } else if(pos == std::string::npos && str.length() > 0 && str.find_first_of(whitespace) == 0) + } else if(pos == Tstring::npos && str.length() > 0 && str.find_first_of(whitespace) == 0) { - return std::string(); + return Tstring(); } return str; } -static inline std::wstring RTrim(std::wstring str, const std::wstring &whitespace = L" \n\r\t") -{ - std::wstring::size_type pos = str.find_last_not_of(whitespace); - if(pos != std::wstring::npos) - { - str.erase(str.begin() + pos + 1, str.end()); - } else if(pos == std::wstring::npos && str.length() > 0 && str.find_first_of(whitespace) == 0) - { - return std::wstring(); - } - return str; -} // Remove whitespace at start and end of string -static inline std::string Trim(std::string str, const std::string &whitespace = " \n\r\t") -//---------------------------------------------------------------------------------------- +template <typename Tstring> +inline Tstring Trim(Tstring str, const Tstring &whitespace = mpt::String::Traits<Tstring>::GetDefaultWhitespace()) +//---------------------------------------------------------------------------------------------------------------- { return RTrim(LTrim(str, whitespace), whitespace); } -static inline std::wstring Trim(std::wstring str, const std::wstring &whitespace = L" \n\r\t") -{ - return RTrim(LTrim(str, whitespace), whitespace); -} -static inline std::string Replace(std::string str, const std::string &oldStr, const std::string &newStr) -//------------------------------------------------------------------------------------------------------ +template <typename Tstring, typename Tstring2, typename Tstring3> +inline Tstring Replace(Tstring str, const Tstring2 &oldStr_, const Tstring3 &newStr_) +//----------------------------------------------------------------------------------- { std::size_t pos = 0; - while((pos = str.find(oldStr, pos)) != std::string::npos) + const Tstring oldStr = oldStr_; + const Tstring newStr = newStr_; + while((pos = str.find(oldStr, pos)) != Tstring::npos) { str.replace(pos, oldStr.length(), newStr); pos += newStr.length(); @@ -111,18 +102,6 @@ } -static inline std::wstring Replace(std::wstring str, const std::wstring &oldStr, const std::wstring &newStr) -{ - std::size_t pos = 0; - while((pos = str.find(oldStr, pos)) != std::string::npos) - { - str.replace(pos, oldStr.length(), newStr); - pos += newStr.length(); - } - return str; -} - - } // namespace String Modified: trunk/OpenMPT/test/test.cpp =================================================================== --- trunk/OpenMPT/test/test.cpp 2014-09-29 12:38:02 UTC (rev 4325) +++ trunk/OpenMPT/test/test.cpp 2014-09-29 13:43:27 UTC (rev 4326) @@ -531,9 +531,9 @@ VERIFY_EQUAL( mpt::saturate_cast<uint32>(static_cast<double>(std::numeric_limits<int64>::max())), std::numeric_limits<uint32>::max() ); - VERIFY_EQUAL( mpt::String::LTrim(" "), "" ); - VERIFY_EQUAL( mpt::String::RTrim(" "), "" ); - VERIFY_EQUAL( mpt::String::Trim(" "), "" ); + VERIFY_EQUAL( mpt::String::LTrim(std::string(" ")), "" ); + VERIFY_EQUAL( mpt::String::RTrim(std::string(" ")), "" ); + VERIFY_EQUAL( mpt::String::Trim(std::string(" ")), "" ); // weird things with std::string containing \0 in the middle and trimming \0 VERIFY_EQUAL( std::string("\0\ta\0b ",6).length(), (std::size_t)6 ); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2014-09-29 23:59:28
|
Revision: 4330 http://sourceforge.net/p/modplug/code/4330 Author: saga-games Date: 2014-09-29 23:59:15 +0000 (Mon, 29 Sep 2014) Log Message: ----------- [Fix] Linear frequency slide mode (in all formats except XM) is now implemented using frequencies instead of periods. This fixes some horrible inaccuracies which can add up very quickly when using extra-fine slides in IT. [Fix] MT2: Frequency slides were broken (libopenmpt only) Modified Paths: -------------- trunk/OpenMPT/mptrack/View_smp.cpp trunk/OpenMPT/soundlib/Snd_fx.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/Sndmix.cpp Modified: trunk/OpenMPT/mptrack/View_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_smp.cpp 2014-09-29 23:37:44 UTC (rev 4329) +++ trunk/OpenMPT/mptrack/View_smp.cpp 2014-09-29 23:59:15 UTC (rev 4330) @@ -2399,7 +2399,7 @@ CSoundFile &sndFile = pModDoc->GetrSoundFile(); ModSample &sample = sndFile.GetSample(m_nSample); - uint32 freq = sndFile.GetFreqFromPeriod(sndFile.GetPeriodFromNote(note + (sndFile.GetType() == MOD_TYPE_XM ? sample.RelativeTone : 0), sample.nFineTune, sample.nC5Speed), sample.nC5Speed, 0); + uint32 freq = sndFile.GetFreqFromPeriod(sndFile.GetPeriodFromNote(note + (sndFile.GetType() == MOD_TYPE_XM ? sample.RelativeTone : 0), sample.nFineTune, sample.nC5Speed), 0); const std::string s = mpt::String::Print("%1 (%2.%3 Hz)", sndFile.GetNoteName((ModCommand::NOTE)note), Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp =================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp 2014-09-29 23:37:44 UTC (rev 4329) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2014-09-29 23:59:15 UTC (rev 4330) @@ -3141,10 +3141,10 @@ { if ((pChn->nPeriod) && (param)) { - if(m_SongFlags[SONG_LINEARSLIDES] && !(GetType() & (MOD_TYPE_XM | MOD_TYPE_MT2))) + if(m_SongFlags[SONG_LINEARSLIDES] && GetType() != MOD_TYPE_XM) { int oldPeriod = pChn->nPeriod; - pChn->nPeriod = Util::muldivr(pChn->nPeriod, LinearSlideDownTable[param & 0x0F], 65536); + pChn->nPeriod = Util::muldivr(pChn->nPeriod, LinearSlideUpTable[param & 0x0F], 65536); if(oldPeriod == pChn->nPeriod) { pChn->nPeriod--; @@ -3176,10 +3176,10 @@ { if ((pChn->nPeriod) && (param)) { - if (m_SongFlags[SONG_LINEARSLIDES] && !(GetType() & (MOD_TYPE_XM | MOD_TYPE_MT2))) + if (m_SongFlags[SONG_LINEARSLIDES] && GetType() != MOD_TYPE_XM) { int oldPeriod = pChn->nPeriod; - pChn->nPeriod = Util::muldivr(pChn->nPeriod, LinearSlideUpTable[param & 0x0F], 65536); + pChn->nPeriod = Util::muldivr(pChn->nPeriod, LinearSlideDownTable[param & 0x0F], 65536); if(oldPeriod == pChn->nPeriod) { pChn->nPeriod++; @@ -3211,10 +3211,10 @@ { if ((pChn->nPeriod) && (param)) { - if(m_SongFlags[SONG_LINEARSLIDES] && !(GetType() & (MOD_TYPE_XM | MOD_TYPE_MT2))) + if(m_SongFlags[SONG_LINEARSLIDES] && GetType() != MOD_TYPE_XM) { int oldPeriod = pChn->nPeriod; - pChn->nPeriod = Util::muldivr(pChn->nPeriod, FineLinearSlideDownTable[param & 0x0F], 65536); + pChn->nPeriod = Util::muldivr(pChn->nPeriod, FineLinearSlideUpTable[param & 0x0F], 65536); if(oldPeriod == pChn->nPeriod) { pChn->nPeriod--; @@ -3246,10 +3246,10 @@ { if ((pChn->nPeriod) && (param)) { - if(m_SongFlags[SONG_LINEARSLIDES] && !(GetType() & (MOD_TYPE_XM | MOD_TYPE_MT2))) + if(m_SongFlags[SONG_LINEARSLIDES] && GetType() != MOD_TYPE_XM) { int oldPeriod = pChn->nPeriod; - pChn->nPeriod = Util::muldivr(pChn->nPeriod, FineLinearSlideUpTable[param & 0x0F], 65536); + pChn->nPeriod = Util::muldivr(pChn->nPeriod, FineLinearSlideDownTable[param & 0x0F], 65536); if(oldPeriod == pChn->nPeriod) { pChn->nPeriod++; @@ -3359,9 +3359,9 @@ if (pChn->nPeriod < pChn->nPortamentoDest) { int32 delta = pChn->nPortamentoSlide; - if(m_SongFlags[SONG_LINEARSLIDES] && !(GetType() & (MOD_TYPE_XM | MOD_TYPE_MT2))) + if(m_SongFlags[SONG_LINEARSLIDES] && GetType() != MOD_TYPE_XM) { - UINT n = pChn->nPortamentoSlide >> 2; + UINT n = pChn->nPortamentoSlide / 4; if (n > 255) n = 255; // Return (a*b+c/2)/c - no divide error // Table is 65536*2(n/192) @@ -3374,9 +3374,9 @@ if (pChn->nPeriod > pChn->nPortamentoDest) { int32 delta = -pChn->nPortamentoSlide; - if(m_SongFlags[SONG_LINEARSLIDES] && !(GetType() & (MOD_TYPE_XM|MOD_TYPE_MT2))) + if(m_SongFlags[SONG_LINEARSLIDES] && GetType() != MOD_TYPE_XM) { - UINT n = pChn->nPortamentoSlide >> 2; + UINT n = pChn->nPortamentoSlide / 4; if (n > 255) n = 255; delta = Util::muldivr(pChn->nPeriod, LinearSlideDownTable[n], 65536) - pChn->nPeriod; if (delta > -1) delta = -1; @@ -4640,7 +4640,7 @@ { // IT Linear slides if (!pChn->nPeriod) return; - if(m_SongFlags[SONG_LINEARSLIDES] && !(GetType() & (MOD_TYPE_XM | MOD_TYPE_MT2))) + if(m_SongFlags[SONG_LINEARSLIDES] && GetType() != MOD_TYPE_XM) { int32 nOldPeriod = pChn->nPeriod; if (nFreqSlide < 0) @@ -4649,7 +4649,7 @@ if (n) { if (n > 255) n = 255; - pChn->nPeriod = Util::muldivr(pChn->nPeriod, LinearSlideDownTable[n], 65536); + pChn->nPeriod = Util::muldivr(pChn->nPeriod, LinearSlideUpTable[n], 65536); if (pChn->nPeriod == nOldPeriod) pChn->nPeriod = nOldPeriod-1; } } else @@ -4658,7 +4658,7 @@ if (n) { if (n > 255) n = 255; - pChn->nPeriod = Util::muldivr(pChn->nPeriod, LinearSlideUpTable[n], 65536); + pChn->nPeriod = Util::muldivr(pChn->nPeriod, LinearSlideDownTable[n], 65536); if (pChn->nPeriod == nOldPeriod) pChn->nPeriod = nOldPeriod+1; } } @@ -4930,11 +4930,12 @@ if (!period) return 0; // This essentially implements std::lower_bound, with the difference that we don't need an iterable container. uint32 minNote = NOTE_MIN, maxNote = NOTE_MAX, count = maxNote - minNote + 1; + const bool periodIsFreq = m_SongFlags[SONG_LINEARSLIDES] && GetType() != MOD_TYPE_XM; while(count > 0) { const uint32 step = count / 2, midNote = minNote + step; uint32 n = GetPeriodFromNote(midNote, nFineTune, nC5Speed); - if(n > period || !n) + if((n > period && !periodIsFreq) || (n < period && periodIsFreq) || !n) { minNote = midNote + 1; count -= step + 1; @@ -4951,13 +4952,14 @@ //------------------------------------------------------------------------------- { if (note == NOTE_NONE || (note >= NOTE_MIN_SPECIAL)) return 0; - if (GetType() & (MOD_TYPE_IT|MOD_TYPE_MPT|MOD_TYPE_MT2|MOD_TYPE_S3M|MOD_TYPE_STM|MOD_TYPE_MDL|MOD_TYPE_ULT|MOD_TYPE_WAV + if (GetType() & (MOD_TYPE_IT|MOD_TYPE_MPT|MOD_TYPE_MT2|MOD_TYPE_S3M|MOD_TYPE_STM|MOD_TYPE_MDL|MOD_TYPE_ULT|MOD_TYPE_WAV|MOD_TYPE_669 |MOD_TYPE_FAR|MOD_TYPE_DMF|MOD_TYPE_PTM|MOD_TYPE_AMS|MOD_TYPE_AMS2|MOD_TYPE_DBM|MOD_TYPE_AMF|MOD_TYPE_PSM|MOD_TYPE_J2B|MOD_TYPE_IMF)) { note -= NOTE_MIN; if(m_SongFlags[SONG_LINEARSLIDES]) { - return (FreqS3MTable[note % 12] << 5) >> (note / 12); + // In IT linear slide mode, periods are equal to frequency. + return Util::muldiv_unsigned(nC5Speed, LinearSlideUpTable[(note % 12) * 16] << (note / 12), 65536 << 5); } else { if (!nC5Speed) nC5Speed = 8363; @@ -5019,8 +5021,8 @@ // Converts period value to sample frequency. Return value is fixed point, with FREQ_FRACBITS fractional bits. -UINT CSoundFile::GetFreqFromPeriod(UINT period, UINT nC5Speed, int nPeriodFrac) const -//----------------------------------------------------------------------------------- +UINT CSoundFile::GetFreqFromPeriod(UINT period, int nPeriodFrac) const +//-------------------------------------------------------------------- { if (!period) return 0; if (GetType() & (MOD_TYPE_MED|MOD_TYPE_MOD|MOD_TYPE_DIGI|MOD_TYPE_MTM|MOD_TYPE_669|MOD_TYPE_AMF0)) @@ -5061,8 +5063,9 @@ { if(m_SongFlags[SONG_LINEARSLIDES]) { - if (!nC5Speed) nC5Speed = 8363; - return Util::muldiv(nC5Speed, (1712L << 8) << FREQ_FRACBITS, (period << 8) + nPeriodFrac); + // IT linear slides already use frequencies instead of periods. + static_assert(FREQ_FRACBITS <= 8, "Check this shift operator"); + return uint32(((uint64(period) << 8) + nPeriodFrac) >> (8 - FREQ_FRACBITS)); } else { return Util::muldiv(8363, (1712L << 8) << FREQ_FRACBITS, (period << 8) + nPeriodFrac); Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2014-09-29 23:37:44 UTC (rev 4329) +++ trunk/OpenMPT/soundlib/Sndfile.h 2014-09-29 23:59:15 UTC (rev 4330) @@ -876,7 +876,7 @@ // Period/Note functions UINT GetNoteFromPeriod(UINT period, int nFineTune = 0, UINT nC5Speed = 0) const; UINT GetPeriodFromNote(UINT note, int nFineTune, UINT nC5Speed) const; - UINT GetFreqFromPeriod(UINT period, UINT nC5Speed, int nPeriodFrac = 0) const; + UINT GetFreqFromPeriod(UINT period, int nPeriodFrac = 0) const; // Misc functions ModSample &GetSample(SAMPLEINDEX sample) { ASSERT(sample <= m_nSamples && sample < CountOf(Samples)); return Samples[sample]; } const ModSample &GetSample(SAMPLEINDEX sample) const { ASSERT(sample <= m_nSamples && sample < CountOf(Samples)); return Samples[sample]; } Modified: trunk/OpenMPT/soundlib/Sndmix.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndmix.cpp 2014-09-29 23:37:44 UTC (rev 4329) +++ trunk/OpenMPT/soundlib/Sndmix.cpp 2014-09-29 23:59:15 UTC (rev 4330) @@ -912,11 +912,11 @@ { l = -l; LimitMax(l, 255); - period = Util::muldiv(period, LinearSlideUpTable[l], 0x10000); + period = Util::muldiv(period, LinearSlideDownTable[l], 65536); } else { LimitMax(l, 255); - period = Util::muldiv(period, LinearSlideDownTable[l], 0x10000); + period = Util::muldiv(period, LinearSlideUpTable[l], 65536); } } //End: Original behavior. } @@ -1341,18 +1341,18 @@ vdelta = (vdelta * (int)chn.nVibratoDepth) >> vdepth; int16 midiDelta = static_cast<int16>(-vdelta); // Periods are upside down - if (m_SongFlags[SONG_LINEARSLIDES] && (GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT))) + if (m_SongFlags[SONG_LINEARSLIDES] && GetType() != MOD_TYPE_XM) { int l = vdelta; if (l < 0) { l = -l; - vdelta = Util::muldiv(period, LinearSlideDownTable[l >> 2], 0x10000) - period; - if (l & 0x03) vdelta += Util::muldiv(period, FineLinearSlideDownTable[l & 0x03], 0x10000) - period; + vdelta = Util::muldiv(period, LinearSlideUpTable[l >> 2], 65536) - period; + if (l & 0x03) vdelta += Util::muldiv(period, FineLinearSlideDownTable[l & 0x03], 65536) - period; } else { - vdelta = Util::muldiv(period, LinearSlideUpTable[l >> 2], 0x10000) - period; - if (l & 0x03) vdelta += Util::muldiv(period, FineLinearSlideUpTable[l & 0x03], 0x10000) - period; + vdelta = Util::muldiv(period, LinearSlideDownTable[l >> 2], 65536) - period; + if (l & 0x03) vdelta += Util::muldiv(period, FineLinearSlideUpTable[l & 0x03], 65536) - period; } } period += vdelta; @@ -1402,6 +1402,13 @@ const ModSample *pSmp = pChn->pModSample; const bool alternativeTuning = pChn->pModInstrument && pChn->pModInstrument->pTuning; + // In IT linear slide mode, we use frequencies, otherwise we use periods, which are upside down. + // In this context, the "up" tables refer to the tables that increase frequency, and the down tables are the ones that decrease frequency. + const uint32 (&upTable)[256] = m_SongFlags[SONG_LINEARSLIDES] ? LinearSlideUpTable : LinearSlideDownTable; + const uint32 (&downTable)[256] = m_SongFlags[SONG_LINEARSLIDES] ? LinearSlideDownTable : LinearSlideUpTable; + const uint32 (&fineUpTable)[16] = m_SongFlags[SONG_LINEARSLIDES] ? FineLinearSlideUpTable : FineLinearSlideDownTable; + const uint32 (&fineDownTable)[16] = m_SongFlags[SONG_LINEARSLIDES] ? FineLinearSlideDownTable : FineLinearSlideUpTable; + // IT compatibility: Autovibrato is so much different in IT that I just put this in a separate code block, to get rid of a dozen IsCompatibilityMode() calls. if(IsCompatibleMode(TRK_IMPULSETRACKER) && !alternativeTuning) { @@ -1449,17 +1456,17 @@ int l = abs(vdelta); if(vdelta < 0) { - vdelta = Util::muldiv(period, LinearSlideDownTable[l >> 2], 0x10000) - period; + vdelta = Util::muldiv(period, upTable[l >> 2], 0x10000) - period; if (l & 0x03) { - vdelta += Util::muldiv(period, FineLinearSlideDownTable[l & 0x03], 0x10000) - period; + vdelta += Util::muldiv(period, fineUpTable[l & 0x03], 0x10000) - period; } } else { - vdelta = Util::muldiv(period, LinearSlideUpTable[l >> 2], 0x10000) - period; + vdelta = Util::muldiv(period, downTable[l >> 2], 0x10000) - period; if (l & 0x03) { - vdelta += Util::muldiv(period, FineLinearSlideUpTable[l & 0x03], 0x10000) - period; + vdelta += Util::muldiv(period, fineDownTable[l & 0x03], 0x10000) - period; } } period -= vdelta; @@ -1527,20 +1534,20 @@ } else //Original behavior { - if (GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT)) + if (GetType() != MOD_TYPE_XM) { int df1, df2; if (n < 0) { n = -n; UINT n1 = n >> 8; - df1 = LinearSlideUpTable[n1]; - df2 = LinearSlideUpTable[n1+1]; + df1 = downTable[n1]; + df2 = downTable[n1+1]; } else { UINT n1 = n >> 8; - df1 = LinearSlideDownTable[n1]; - df2 = LinearSlideDownTable[n1+1]; + df1 = upTable[n1]; + df2 = upTable[n1+1]; } n >>= 2; period = Util::muldiv(period, df1 + ((df2 - df1) * (n & 0x3F) >> 6), 256); @@ -1630,7 +1637,7 @@ const ModInstrument *pIns = pChn->pModInstrument; if(GetType() != MOD_TYPE_MPT || pIns == nullptr || pIns->pTuning == nullptr) { - freq = GetFreqFromPeriod(period, pChn->nC5Speed, periodFrac); + freq = GetFreqFromPeriod(period, periodFrac); } else { freq = pChn->m_Freq; @@ -1834,15 +1841,7 @@ { // Only recompute this whole thing in case the base period has changed. pChn->cachedPeriod = period; - for(uint32 i = NOTE_MIN; i < NOTE_MAX; i++) - { - int32 n = GetPeriodFromNote(i, pChn->nFineTune, pChn->nC5Speed); - if(n > 0 && n <= period) - { - pChn->glissandoPeriod = n; - break; - } - } + pChn->glissandoPeriod = GetPeriodFromNote(GetNoteFromPeriod(period, pChn->nFineTune, pChn->nC5Speed), pChn->nFineTune, pChn->nC5Speed); } period = pChn->glissandoPeriod; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2014-09-30 12:33:59
|
Revision: 4334 http://sourceforge.net/p/modplug/code/4334 Author: saga-games Date: 2014-09-30 12:33:48 +0000 (Tue, 30 Sep 2014) Log Message: ----------- [Imp] Sample tab: Make finetune and transpose setting modifications undoable [Fix] Sample tab: When editing XM vibrato settings, the edit cursor always jumped back to the first character in the edit field. [Ref] Document IT fine slide tables in Tables.cpp [Mod] OpenMPT: Version is now 1.24.00.05 Modified Paths: -------------- trunk/OpenMPT/common/versionNumber.h trunk/OpenMPT/mptrack/Ctrl_smp.cpp trunk/OpenMPT/soundlib/Tables.cpp Modified: trunk/OpenMPT/common/versionNumber.h =================================================================== --- trunk/OpenMPT/common/versionNumber.h 2014-09-30 07:20:20 UTC (rev 4333) +++ trunk/OpenMPT/common/versionNumber.h 2014-09-30 12:33:48 UTC (rev 4334) @@ -19,7 +19,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 24 #define VER_MINOR 00 -#define VER_MINORMINOR 04 +#define VER_MINORMINOR 05 //Version string. For example "1.17.02.28" #define MPT_VERSION_STR VER_STRINGIZE(VER_MAJORMAJOR) "." VER_STRINGIZE(VER_MAJOR) "." VER_STRINGIZE(VER_MINOR) "." VER_STRINGIZE(VER_MINORMINOR) Modified: trunk/OpenMPT/mptrack/Ctrl_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2014-09-30 07:20:20 UTC (rev 4333) +++ trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2014-09-30 12:33:48 UTC (rev 4334) @@ -2459,7 +2459,7 @@ if (IsLocked()) return; int nPan = GetDlgItemInt(IDC_EDIT9); if (nPan < 0) nPan = 0; - //rewbs.fix36944: sample pan range to 0-64. + if (m_sndFile.GetType() == MOD_TYPE_XM) { if (nPan > 255) nPan = 255; // displayed panning will be 0-255 with XM @@ -2468,7 +2468,7 @@ if (nPan > 64) nPan = 64; // displayed panning will be 0-64 with anything but XM. nPan = nPan << 2; // so we x4 to get MPT's internal 0-256 range. } - //end rewbs.fix36944 + if (nPan != m_sndFile.GetSample(m_nSample).nPan) { m_sndFile.GetSample(m_nSample).nPan = (uint16)nPan; @@ -2482,6 +2482,7 @@ { if (IsLocked()) return; int n = GetDlgItemInt(IDC_EDIT5); + m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_none, "Finetune"); if (m_sndFile.m_nType & (MOD_TYPE_IT|MOD_TYPE_S3M|MOD_TYPE_MPT)) { if ((n > 0) && (n <= (m_sndFile.GetType() == MOD_TYPE_S3M ? 65535 : 9999999)) && (n != (int)m_sndFile.GetSample(m_nSample).nC5Speed)) @@ -2521,6 +2522,7 @@ int n = (NOTE_MIDDLEC - NOTE_MIN) - (m_CbnBaseNote.GetCurSel() + BASENOTE_MIN); ModSample &sample = m_sndFile.GetSample(m_nSample); + m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_none, "Transpose"); if (m_sndFile.GetType() & (MOD_TYPE_IT|MOD_TYPE_S3M|MOD_TYPE_MPT)) { @@ -3230,7 +3232,7 @@ // Propagate changes to all samples that belong to this instrument. for(std::set<SAMPLEINDEX>::const_iterator sample = referencedSamples.begin(); sample != referencedSamples.end(); sample++) { - if(*sample <= m_sndFile.GetNumSamples()) + if(*sample <= m_sndFile.GetNumSamples() && *sample != m_nSample) { m_sndFile.GetSample(*sample).nVibDepth = m_sndFile.GetSample(m_nSample).nVibDepth; m_sndFile.GetSample(*sample).nVibType = m_sndFile.GetSample(m_nSample).nVibType; Modified: trunk/OpenMPT/soundlib/Tables.cpp =================================================================== --- trunk/OpenMPT/soundlib/Tables.cpp 2014-09-30 07:20:20 UTC (rev 4333) +++ trunk/OpenMPT/soundlib/Tables.cpp 2014-09-30 12:33:48 UTC (rev 4334) @@ -585,7 +585,9 @@ -// Apart from a few small differences, this table seems to contain elements with a difference of 59. +// round(65536 * 2**(n/768)) +// 768 = 64 extra-fine finetune steps for 12 notes +// Table content is in 16.16 format const uint32 FineLinearSlideUpTable[16] = { 65536, 65595, 65654, 65714, 65773, 65832, 65892, 65951, @@ -593,7 +595,13 @@ }; -// Apart from a few small differences, this table seems to contain elements with a difference of 59. +// round(65536 * 2**(-n/768)) +// 768 = 64 extra-fine finetune steps for 12 notes +// Table content is in 16.16 format +// Note that there are a few errors in this table (typos?), but well, this table comes straight from ITTECH.TXT... +// Entry 0 (65535) should be 65536 (this value is unused and most likely stored this way so that it fits in a 16-bit integer) +// Entry 11 (64888) should be 64889 - rounding error? +// Entry 15 (64645) should be 64655 - typo? const uint32 FineLinearSlideDownTable[16] = { 65535, 65477, 65418, 65359, 65300, 65241, 65182, 65123, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2014-09-30 13:00:27
|
Revision: 4335 http://sourceforge.net/p/modplug/code/4335 Author: saga-games Date: 2014-09-30 13:00:13 +0000 (Tue, 30 Sep 2014) Log Message: ----------- [Fix] Sample tab: Properly label Ramp Up and Ramp Down in XM autovibrato (mislabeled since forever) [Imp] Sample tab: Don't show unsupported sample vibrato types in IT (ramp up) and XM (random) [Imp] Mod Conversion: Remove unsupported sample vibrato types when converting to IT (ramp up) and XM (random) Modified Paths: -------------- trunk/OpenMPT/mptrack/Ctrl_smp.cpp trunk/OpenMPT/soundlib/ModSample.cpp Modified: trunk/OpenMPT/mptrack/Ctrl_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2014-09-30 12:33:48 UTC (rev 4334) +++ trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2014-09-30 13:00:13 UTC (rev 4335) @@ -243,13 +243,6 @@ m_SpinVolume.SetRange(0, 64); m_SpinGlobalVol.SetRange(0, 64); - // Auto vibrato - m_ComboAutoVib.AddString("Sine"); - m_ComboAutoVib.AddString("Square"); - m_ComboAutoVib.AddString("Ramp Up"); - m_ComboAutoVib.AddString("Ramp Down"); - m_ComboAutoVib.AddString("Random"); - for (UINT i = BASENOTE_MIN; i < BASENOTE_MAX; i++) { CHAR s[32]; @@ -714,12 +707,32 @@ transp = (int)sample.RelativeTone; } int basenote = 60 - transp; - if (basenote < BASENOTE_MIN) basenote = BASENOTE_MIN; - if (basenote >= BASENOTE_MAX) basenote = BASENOTE_MAX-1; + Limit(basenote, BASENOTE_MIN, BASENOTE_MAX - 1); basenote -= BASENOTE_MIN; if (basenote != m_CbnBaseNote.GetCurSel()) m_CbnBaseNote.SetCurSel(basenote); - // AutoVibrato - m_ComboAutoVib.SetCurSel(sample.nVibType); + + // Auto vibrato + // Ramp up and ramp down are swapped in XM - probably because they ramp up the *period* instead of *frequency*. + const VibratoType rampUp = m_sndFile.GetType() == MOD_TYPE_XM ? VIB_RAMP_DOWN : VIB_RAMP_UP; + const VibratoType rampDown = m_sndFile.GetType() == MOD_TYPE_XM ? VIB_RAMP_UP : VIB_RAMP_DOWN; + m_ComboAutoVib.ResetContent(); + m_ComboAutoVib.SetItemData(m_ComboAutoVib.AddString(_T("Sine")), VIB_SINE); + m_ComboAutoVib.SetItemData(m_ComboAutoVib.AddString(_T("Square")), VIB_SQUARE); + if(m_sndFile.GetType() != MOD_TYPE_IT || sample.nVibType == VIB_RAMP_UP) + m_ComboAutoVib.SetItemData(m_ComboAutoVib.AddString(_T("Ramp Up")), rampUp); + m_ComboAutoVib.SetItemData(m_ComboAutoVib.AddString(_T("Ramp Down")), rampDown); + if(m_sndFile.GetType() != MOD_TYPE_XM || sample.nVibType == VIB_RANDOM) + m_ComboAutoVib.SetItemData(m_ComboAutoVib.AddString(_T("Random")), VIB_RANDOM); + + for(int i = 0; i < m_ComboAutoVib.GetCount(); i++) + { + if(m_ComboAutoVib.GetItemData(i) == sample.nVibType) + { + m_ComboAutoVib.SetCurSel(i); + break; + } + } + SetDlgItemInt(IDC_EDIT14, (UINT)sample.nVibSweep); SetDlgItemInt(IDC_EDIT15, (UINT)sample.nVibDepth); SetDlgItemInt(IDC_EDIT16, (UINT)sample.nVibRate); @@ -2556,7 +2569,7 @@ int n = m_ComboAutoVib.GetCurSel(); if (n >= 0) { - m_sndFile.GetSample(m_nSample).nVibType = static_cast<uint8>(n); + m_sndFile.GetSample(m_nSample).nVibType = static_cast<uint8>(m_ComboAutoVib.GetItemData(n)); PropagateAutoVibratoChanges(); SetModified(HINT_SAMPLEINFO, false); @@ -3232,13 +3245,13 @@ // Propagate changes to all samples that belong to this instrument. for(std::set<SAMPLEINDEX>::const_iterator sample = referencedSamples.begin(); sample != referencedSamples.end(); sample++) { - if(*sample <= m_sndFile.GetNumSamples() && *sample != m_nSample) + if(*sample <= m_sndFile.GetNumSamples()) { m_sndFile.GetSample(*sample).nVibDepth = m_sndFile.GetSample(m_nSample).nVibDepth; m_sndFile.GetSample(*sample).nVibType = m_sndFile.GetSample(m_nSample).nVibType; m_sndFile.GetSample(*sample).nVibRate = m_sndFile.GetSample(m_nSample).nVibRate; m_sndFile.GetSample(*sample).nVibSweep = m_sndFile.GetSample(m_nSample).nVibSweep; - m_modDoc.UpdateAllViews(nullptr, HINT_SAMPLEINFO | ((*sample) << HINT_SHIFT_SMP)); + m_modDoc.UpdateAllViews(nullptr, HINT_SAMPLEINFO | ((*sample) << HINT_SHIFT_SMP), (CObject *)this); } } } Modified: trunk/OpenMPT/soundlib/ModSample.cpp =================================================================== --- trunk/OpenMPT/soundlib/ModSample.cpp 2014-09-30 12:33:48 UTC (rev 4334) +++ trunk/OpenMPT/soundlib/ModSample.cpp 2014-09-30 13:00:13 UTC (rev 4335) @@ -86,6 +86,14 @@ nVibSweep = 255 - nVibSweep; } } + // Convert incompatible autovibrato types + if(toType == MOD_TYPE_IT && nVibType == VIB_RAMP_UP) + { + nVibType = VIB_RAMP_DOWN; + } else if(toType == MOD_TYPE_XM && nVibType == VIB_RANDOM) + { + nVibType = VIB_SINE; + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <man...@us...> - 2014-10-01 08:16:38
|
Revision: 4338 http://sourceforge.net/p/modplug/code/4338 Author: manxorist Date: 2014-10-01 08:16:21 +0000 (Wed, 01 Oct 2014) Log Message: ----------- [Ref] Implement mpt::String::Print as a function templated on the string type of the passed format string. [Ref] test: Add test cases for mpt::String::Print. Modified Paths: -------------- trunk/OpenMPT/common/mptString.h trunk/OpenMPT/test/test.cpp Modified: trunk/OpenMPT/common/mptString.h =================================================================== --- trunk/OpenMPT/common/mptString.h 2014-10-01 07:16:19 UTC (rev 4337) +++ trunk/OpenMPT/common/mptString.h 2014-10-01 08:16:21 UTC (rev 4338) @@ -316,10 +316,10 @@ std::wstring ToWString(const double & x); std::wstring ToWString(const long double & x); -template <typename Tstring> struct ToStringTHelper {}; -template <> struct ToStringTHelper<std::string> { template <typename T> inline std::string operator() (const T & x) { return ToString(x); } }; -template <> struct ToStringTHelper<std::wstring> { template <typename T> inline std::wstring operator() (const T & x) { return ToWString(x); } }; -template<typename Tstring, typename T> inline Tstring ToStringT(const T & x) { return ToStringTHelper<Tstring>()(x); } +template <typename Tstring> struct ToStringTFunctor {}; +template <> struct ToStringTFunctor<std::string> { template <typename T> inline std::string operator() (const T & x) { return ToString(x); } }; +template <> struct ToStringTFunctor<std::wstring> { template <typename T> inline std::wstring operator() (const T & x) { return ToWString(x); } }; +template<typename Tstring, typename T> inline Tstring ToStringT(const T & x) { return ToStringTFunctor<Tstring>()(x); } struct fmt_base { @@ -586,6 +586,16 @@ namespace detail { +template <typename T> struct to_string_type { }; +template <> struct to_string_type<std::string > { typedef std::string type; }; +template <> struct to_string_type<char > { typedef std::string type; }; +template <> struct to_string_type<char * > { typedef std::string type; }; +template <> struct to_string_type<const char * > { typedef std::string type; }; +template <> struct to_string_type<std::wstring > { typedef std::wstring type; }; +template <> struct to_string_type<wchar_t > { typedef std::wstring type; }; +template <> struct to_string_type<wchar_t * > { typedef std::wstring type; }; +template <> struct to_string_type<const wchar_t *> { typedef std::wstring type; }; + std::string PrintImpl(const std::string & format , const std::string & x1 = std::string() , const std::string & x2 = std::string() @@ -610,80 +620,96 @@ } // namespace detail -template< - typename T1 +// C and C++ string version + +template<typename Tformat > -std::string Print(const std::string & format +typename mpt::String::detail::to_string_type<Tformat>::type Print(const Tformat & format +) +{ + typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring; + return detail::PrintImpl(format + ); +} + +template<typename Tformat + , typename T1 +> +typename mpt::String::detail::to_string_type<Tformat>::type Print(const Tformat & format , const T1& x1 ) { + typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring; return detail::PrintImpl(format - , ToString(x1) + , ToStringTFunctor<Tstring>()(x1) ); } -template< - typename T1, - typename T2 +template<typename Tformat + , typename T1 + , typename T2 > -std::string Print(const std::string & format +typename mpt::String::detail::to_string_type<Tformat>::type Print(const Tformat & format , const T1& x1 , const T2& x2 ) { + typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring; return detail::PrintImpl(format - , ToString(x1) - , ToString(x2) + , ToStringTFunctor<Tstring>()(x1) + , ToStringTFunctor<Tstring>()(x2) ); } -template< - typename T1, - typename T2, - typename T3 +template<typename Tformat + , typename T1 + , typename T2 + , typename T3 > -std::string Print(const std::string & format +typename mpt::String::detail::to_string_type<Tformat>::type Print(const Tformat & format , const T1& x1 , const T2& x2 , const T3& x3 ) { + typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring; return detail::PrintImpl(format - , ToString(x1) - , ToString(x2) - , ToString(x3) + , ToStringTFunctor<Tstring>()(x1) + , ToStringTFunctor<Tstring>()(x2) + , ToStringTFunctor<Tstring>()(x3) ); } -template< - typename T1, - typename T2, - typename T3, - typename T4 +template<typename Tformat + , typename T1 + , typename T2 + , typename T3 + , typename T4 > -std::string Print(const std::string & format +typename mpt::String::detail::to_string_type<Tformat>::type Print(const Tformat & format , const T1& x1 , const T2& x2 , const T3& x3 , const T4& x4 ) { + typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring; return detail::PrintImpl(format - , ToString(x1) - , ToString(x2) - , ToString(x3) - , ToString(x4) + , ToStringTFunctor<Tstring>()(x1) + , ToStringTFunctor<Tstring>()(x2) + , ToStringTFunctor<Tstring>()(x3) + , ToStringTFunctor<Tstring>()(x4) ); } -template< - typename T1, - typename T2, - typename T3, - typename T4, - typename T5 +template<typename Tformat + , typename T1 + , typename T2 + , typename T3 + , typename T4 + , typename T5 > -std::string Print(const std::string & format +typename mpt::String::detail::to_string_type<Tformat>::type Print(const Tformat & format , const T1& x1 , const T2& x2 , const T3& x3 @@ -691,24 +717,25 @@ , const T5& x5 ) { + typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring; return detail::PrintImpl(format - , ToString(x1) - , ToString(x2) - , ToString(x3) - , ToString(x4) - , ToString(x5) + , ToStringTFunctor<Tstring>()(x1) + , ToStringTFunctor<Tstring>()(x2) + , ToStringTFunctor<Tstring>()(x3) + , ToStringTFunctor<Tstring>()(x4) + , ToStringTFunctor<Tstring>()(x5) ); } -template< - typename T1, - typename T2, - typename T3, - typename T4, - typename T5, - typename T6 +template<typename Tformat + , typename T1 + , typename T2 + , typename T3 + , typename T4 + , typename T5 + , typename T6 > -std::string Print(const std::string & format +typename mpt::String::detail::to_string_type<Tformat>::type Print(const Tformat & format , const T1& x1 , const T2& x2 , const T3& x3 @@ -717,26 +744,27 @@ , const T6& x6 ) { + typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring; return detail::PrintImpl(format - , ToString(x1) - , ToString(x2) - , ToString(x3) - , ToString(x4) - , ToString(x5) - , ToString(x6) + , ToStringTFunctor<Tstring>()(x1) + , ToStringTFunctor<Tstring>()(x2) + , ToStringTFunctor<Tstring>()(x3) + , ToStringTFunctor<Tstring>()(x4) + , ToStringTFunctor<Tstring>()(x5) + , ToStringTFunctor<Tstring>()(x6) ); } -template< - typename T1, - typename T2, - typename T3, - typename T4, - typename T5, - typename T6, - typename T7 +template<typename Tformat + , typename T1 + , typename T2 + , typename T3 + , typename T4 + , typename T5 + , typename T6 + , typename T7 > -std::string Print(const std::string & format +typename mpt::String::detail::to_string_type<Tformat>::type Print(const Tformat & format , const T1& x1 , const T2& x2 , const T3& x3 @@ -746,28 +774,29 @@ , const T7& x7 ) { + typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring; return detail::PrintImpl(format - , ToString(x1) - , ToString(x2) - , ToString(x3) - , ToString(x4) - , ToString(x5) - , ToString(x6) - , ToString(x7) + , ToStringTFunctor<Tstring>()(x1) + , ToStringTFunctor<Tstring>()(x2) + , ToStringTFunctor<Tstring>()(x3) + , ToStringTFunctor<Tstring>()(x4) + , ToStringTFunctor<Tstring>()(x5) + , ToStringTFunctor<Tstring>()(x6) + , ToStringTFunctor<Tstring>()(x7) ); } -template< - typename T1, - typename T2, - typename T3, - typename T4, - typename T5, - typename T6, - typename T7, - typename T8 +template<typename Tformat + , typename T1 + , typename T2 + , typename T3 + , typename T4 + , typename T5 + , typename T6 + , typename T7 + , typename T8 > -std::string Print(const std::string & format +typename mpt::String::detail::to_string_type<Tformat>::type Print(const Tformat & format , const T1& x1 , const T2& x2 , const T3& x3 @@ -778,92 +807,109 @@ , const T8& x8 ) { + typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring; return detail::PrintImpl(format - , ToString(x1) - , ToString(x2) - , ToString(x3) - , ToString(x4) - , ToString(x5) - , ToString(x6) - , ToString(x7) - , ToString(x8) + , ToStringTFunctor<Tstring>()(x1) + , ToStringTFunctor<Tstring>()(x2) + , ToStringTFunctor<Tstring>()(x3) + , ToStringTFunctor<Tstring>()(x4) + , ToStringTFunctor<Tstring>()(x5) + , ToStringTFunctor<Tstring>()(x6) + , ToStringTFunctor<Tstring>()(x7) + , ToStringTFunctor<Tstring>()(x8) ); } -template< - typename T1 +// array version for literals + +template<typename Tformat, std::size_t N > -std::wstring PrintW(const std::wstring & format +typename mpt::String::detail::to_string_type<Tformat>::type Print(const Tformat (&format)[N] +) +{ + typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring; + return detail::PrintImpl(format + ); +} + +template<typename Tformat, std::size_t N + , typename T1 +> +typename mpt::String::detail::to_string_type<Tformat>::type Print(const Tformat (&format)[N] , const T1& x1 ) { + typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring; return detail::PrintImpl(format - , ToWString(x1) + , ToStringTFunctor<Tstring>()(x1) ); } -template< - typename T1, - typename T2 +template<typename Tformat, std::size_t N + , typename T1 + , typename T2 > -std::wstring PrintW(const std::wstring & format +typename mpt::String::detail::to_string_type<Tformat>::type Print(const Tformat (&format)[N] , const T1& x1 , const T2& x2 ) { + typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring; return detail::PrintImpl(format - , ToWString(x1) - , ToWString(x2) + , ToStringTFunctor<Tstring>()(x1) + , ToStringTFunctor<Tstring>()(x2) ); } -template< - typename T1, - typename T2, - typename T3 +template<typename Tformat, std::size_t N + , typename T1 + , typename T2 + , typename T3 > -std::wstring PrintW(const std::wstring & format +typename mpt::String::detail::to_string_type<Tformat>::type Print(const Tformat (&format)[N] , const T1& x1 , const T2& x2 , const T3& x3 ) { + typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring; return detail::PrintImpl(format - , ToWString(x1) - , ToWString(x2) - , ToWString(x3) + , ToStringTFunctor<Tstring>()(x1) + , ToStringTFunctor<Tstring>()(x2) + , ToStringTFunctor<Tstring>()(x3) ); } -template< - typename T1, - typename T2, - typename T3, - typename T4 +template<typename Tformat, std::size_t N + , typename T1 + , typename T2 + , typename T3 + , typename T4 > -std::wstring PrintW(const std::wstring & format +typename mpt::String::detail::to_string_type<Tformat>::type Print(const Tformat (&format)[N] , const T1& x1 , const T2& x2 , const T3& x3 , const T4& x4 ) { + typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring; return detail::PrintImpl(format - , ToWString(x1) - , ToWString(x2) - , ToWString(x3) - , ToWString(x4) + , ToStringTFunctor<Tstring>()(x1) + , ToStringTFunctor<Tstring>()(x2) + , ToStringTFunctor<Tstring>()(x3) + , ToStringTFunctor<Tstring>()(x4) ); } -template< - typename T1, - typename T2, - typename T3, - typename T4, - typename T5 +template<typename Tformat, std::size_t N + , typename T1 + , typename T2 + , typename T3 + , typename T4 + , typename T5 > -std::wstring PrintW(const std::wstring & format +typename mpt::String::detail::to_string_type<Tformat>::type Print(const Tformat (&format)[N] , const T1& x1 , const T2& x2 , const T3& x3 @@ -871,24 +917,25 @@ , const T5& x5 ) { + typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring; return detail::PrintImpl(format - , ToWString(x1) - , ToWString(x2) - , ToWString(x3) - , ToWString(x4) - , ToWString(x5) + , ToStringTFunctor<Tstring>()(x1) + , ToStringTFunctor<Tstring>()(x2) + , ToStringTFunctor<Tstring>()(x3) + , ToStringTFunctor<Tstring>()(x4) + , ToStringTFunctor<Tstring>()(x5) ); } -template< - typename T1, - typename T2, - typename T3, - typename T4, - typename T5, - typename T6 +template<typename Tformat, std::size_t N + , typename T1 + , typename T2 + , typename T3 + , typename T4 + , typename T5 + , typename T6 > -std::wstring PrintW(const std::wstring & format +typename mpt::String::detail::to_string_type<Tformat>::type Print(const Tformat (&format)[N] , const T1& x1 , const T2& x2 , const T3& x3 @@ -897,26 +944,27 @@ , const T6& x6 ) { + typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring; return detail::PrintImpl(format - , ToWString(x1) - , ToWString(x2) - , ToWString(x3) - , ToWString(x4) - , ToWString(x5) - , ToWString(x6) + , ToStringTFunctor<Tstring>()(x1) + , ToStringTFunctor<Tstring>()(x2) + , ToStringTFunctor<Tstring>()(x3) + , ToStringTFunctor<Tstring>()(x4) + , ToStringTFunctor<Tstring>()(x5) + , ToStringTFunctor<Tstring>()(x6) ); } -template< - typename T1, - typename T2, - typename T3, - typename T4, - typename T5, - typename T6, - typename T7 +template<typename Tformat, std::size_t N + , typename T1 + , typename T2 + , typename T3 + , typename T4 + , typename T5 + , typename T6 + , typename T7 > -std::wstring PrintW(const std::wstring & format +typename mpt::String::detail::to_string_type<Tformat>::type Print(const Tformat (&format)[N] , const T1& x1 , const T2& x2 , const T3& x3 @@ -926,28 +974,29 @@ , const T7& x7 ) { + typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring; return detail::PrintImpl(format - , ToWString(x1) - , ToWString(x2) - , ToWString(x3) - , ToWString(x4) - , ToWString(x5) - , ToWString(x6) - , ToWString(x7) + , ToStringTFunctor<Tstring>()(x1) + , ToStringTFunctor<Tstring>()(x2) + , ToStringTFunctor<Tstring>()(x3) + , ToStringTFunctor<Tstring>()(x4) + , ToStringTFunctor<Tstring>()(x5) + , ToStringTFunctor<Tstring>()(x6) + , ToStringTFunctor<Tstring>()(x7) ); } -template< - typename T1, - typename T2, - typename T3, - typename T4, - typename T5, - typename T6, - typename T7, - typename T8 +template<typename Tformat, std::size_t N + , typename T1 + , typename T2 + , typename T3 + , typename T4 + , typename T5 + , typename T6 + , typename T7 + , typename T8 > -std::wstring PrintW(const std::wstring & format +typename mpt::String::detail::to_string_type<Tformat>::type Print(const Tformat (&format)[N] , const T1& x1 , const T2& x2 , const T3& x3 @@ -958,18 +1007,21 @@ , const T8& x8 ) { + typedef typename mpt::String::detail::to_string_type<Tformat>::type Tstring; return detail::PrintImpl(format - , ToWString(x1) - , ToWString(x2) - , ToWString(x3) - , ToWString(x4) - , ToWString(x5) - , ToWString(x6) - , ToWString(x7) - , ToWString(x8) + , ToStringTFunctor<Tstring>()(x1) + , ToStringTFunctor<Tstring>()(x2) + , ToStringTFunctor<Tstring>()(x3) + , ToStringTFunctor<Tstring>()(x4) + , ToStringTFunctor<Tstring>()(x5) + , ToStringTFunctor<Tstring>()(x6) + , ToStringTFunctor<Tstring>()(x7) + , ToStringTFunctor<Tstring>()(x8) ); } +#define PrintW Print + } } // namespace mpt::String OPENMPT_NAMESPACE_END Modified: trunk/OpenMPT/test/test.cpp =================================================================== --- trunk/OpenMPT/test/test.cpp 2014-10-01 07:16:19 UTC (rev 4337) +++ trunk/OpenMPT/test/test.cpp 2014-10-01 08:16:21 UTC (rev 4338) @@ -437,6 +437,29 @@ VERIFY_EQUAL(mpt::wfmt::fix(6.12345, 7, 3), L" 6.123"); VERIFY_EQUAL(mpt::wfmt::flt(6.12345, 0, 4), L"6.123"); + // basic functionality + VERIFY_EQUAL(mpt::String::Print("%1%2%3",1,2,3), "123"); + VERIFY_EQUAL(mpt::String::Print("%1%1%1",1,2,3), "111"); + VERIFY_EQUAL(mpt::String::Print("%3%3%3",1,2,3), "333"); + + // template argument deduction of string type + VERIFY_EQUAL(mpt::String::Print(std::string("%1%2%3"),1,2,3), "123"); + VERIFY_EQUAL(mpt::String::Print(std::wstring(L"%1%2%3"),1,2,3), L"123"); + VERIFY_EQUAL(mpt::String::Print(L"%1%2%3",1,2,3), L"123"); + VERIFY_EQUAL(mpt::String::PrintW(L"%1%2%3",1,2,3), L"123"); + + // escaping and error behviour of '%' + VERIFY_EQUAL(mpt::String::Print("%"), "%"); + VERIFY_EQUAL(mpt::String::Print("%%"), "%"); + VERIFY_EQUAL(mpt::String::Print("%%%"), "%%"); + VERIFY_EQUAL(mpt::String::Print("%1", "a"), "a"); + VERIFY_EQUAL(mpt::String::Print("%1%", "a"), "a%"); + VERIFY_EQUAL(mpt::String::Print("%1%%", "a"), "a%"); + VERIFY_EQUAL(mpt::String::Print("%1%%%", "a"), "a%%"); + VERIFY_EQUAL(mpt::String::Print("%%1", "a"), "%1"); + VERIFY_EQUAL(mpt::String::Print("%%%1", "a"), "%a"); + VERIFY_EQUAL(mpt::String::Print("%b", "a"), "%b"); + } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |