static noinline void DoLog(const mpt::log::Context &context, mpt::ustring message) //-------------------------------------------------------------------------------- { // remove eol if already present message = mpt::String::RTrim(message, MPT_USTRING("\r\n")); #if defined(MODPLUG_TRACKER) static uint64_t s_lastlogtime = 0; uint64 cur = mpt::Date::ANSI::Now(); uint64 diff = cur/10000 - s_lastlogtime; s_lastlogtime = cur/10000; #ifdef LOG_TO_FILE { static FILE * s_logfile = nullptr; if(!s_logfile) { s_logfile = mpt_fopen(MPT_PATHSTRING("mptrack.log"), "a"); } if(s_logfile) { fprintf(s_logfile, mpt::ToCharset(mpt::CharsetUTF8, mpt::String::Print(MPT_USTRING("%1+%2 %3(%4): %5 [%6]\n" , mpt::Date::ANSI::ToString(cur) , mpt::ufmt::dec<6>(diff) , mpt::ToUnicode(mpt::CharsetASCII, context.file) , context.line , message , mpt::ToUnicode(mpt::CharsetASCII, context.function) ))).c_str()); fflush(s_logfile); } } #endif // LOG_TO_FILE { OutputDebugStringW(mpt::String::PrintW(L"%1(%2): +%3 %4 [%5]\n" , mpt::ToWide(mpt::CharsetASCII, context.file) , context.line , mpt::wfmt::dec<6>(diff) , message , mpt::ToWide(mpt::CharsetASCII, context.function) ).c_str()); } #else // !MODPLUG_TRACKER std::clog << "openmpt: " << context.file << "(" << context.line << ")" << ": " #if defined(MPT_WITH_CHARSET_LOCALE) << mpt::ToLocale(message) #else << mpt::ToCharset(mpt::CharsetUTF8, message) #endif << " [" << context.function << "]" << std::endl; #endif // MODPLUG_TRACKER }
std::vector<BuildVariant> BuildVariants::GetBuildVariants() { std::vector<BuildVariant> result; #if 0 // VS2010 BuildVariant Win32old = { 1, MPT_USTRING("win32old"), 32, PROCSUPPORT_i586 , 0, 0, mpt::Windows::Version::WinXP , mpt::Windows::Version::WinXP , mpt::Wine::Version(1,0,0) }; BuildVariant Win64old = { 1, MPT_USTRING("win64old"), 64, PROCSUPPORT_AMD64 , 2, 0, mpt::Windows::Version::WinXP64 , mpt::Windows::Version::WinXP64, mpt::Wine::Version(1,4,0) }; BuildVariant Win32 = { 2, MPT_USTRING("win32" ), 32, PROCSUPPORT_x86_SSE2, 2, 0, mpt::Windows::Version::WinXP , mpt::Windows::Version::Win7 , mpt::Wine::Version(1,4,0) }; BuildVariant Win64 = { 2, MPT_USTRING("win64" ), 64, PROCSUPPORT_AMD64 , 2, 0, mpt::Windows::Version::WinXP64 , mpt::Windows::Version::Win7 , mpt::Wine::Version(1,4,0) }; result.push_back(Win32old); result.push_back(Win64old); result.push_back(Win32); result.push_back(Win64); #else // VS2015 BuildVariant Win32old = { 1, MPT_USTRING("win32old"), 32, PROCSUPPORT_i586 , 0, 0, mpt::Windows::Version::WinXP , mpt::Windows::Version::WinXP , mpt::Wine::Version(1,4,0) }; BuildVariant Win64old = { 1, MPT_USTRING("win64old"), 64, PROCSUPPORT_AMD64 , 2, 0, mpt::Windows::Version::WinXP64 , mpt::Windows::Version::WinXP64, mpt::Wine::Version(1,4,0) }; BuildVariant Win32 = { 2, MPT_USTRING("win32" ), 32, PROCSUPPORT_x86_SSE2, 2, 0, mpt::Windows::Version::WinVista, mpt::Windows::Version::Win7 , mpt::Wine::Version(1,8,0) }; BuildVariant Win64 = { 2, MPT_USTRING("win64" ), 64, PROCSUPPORT_AMD64 , 2, 0, mpt::Windows::Version::WinVista, mpt::Windows::Version::Win7 , mpt::Wine::Version(1,8,0) }; result.push_back(Win32old); result.push_back(Win64old); result.push_back(Win32); result.push_back(Win64); #endif std::stable_sort(result.begin(), result.end(), CompareBuildVariantsByScore); return result; }
SoundDevice::Caps CWaveDevice::InternalGetDeviceCaps() //-------------------------------------------------- { MPT_TRACE(); SoundDevice::Caps caps; caps.Available = true; caps.CanUpdateInterval = true; caps.CanSampleFormat = true; caps.CanExclusiveMode = (GetDeviceIndex() > 0); // no direct mode for WAVE_MAPPER, makes no sense there caps.CanBoostThreadPriority = true; caps.CanKeepDeviceRunning = false; caps.CanUseHardwareTiming = false; caps.CanChannelMapping = false; caps.CanInput = false; caps.HasNamedInputSources = false; caps.CanDriverPanel = false; caps.HasInternalDither = false; caps.ExclusiveModeDescription = MPT_USTRING("Use direct mode"); if(GetSysInfo().IsWine) { caps.DefaultSettings.sampleFormat = SampleFormatInt16; } else if(GetSysInfo().WindowsVersion.IsAtLeast(mpt::Windows::Version::WinVista)) { caps.DefaultSettings.sampleFormat = SampleFormatFloat32; } else { caps.DefaultSettings.sampleFormat = SampleFormatInt16; } return caps; }
SoundDevice::Statistics CWaveDevice::GetStatistics() const //-------------------------------------------------------- { MPT_TRACE(); SoundDevice::Statistics result; result.InstantaneousLatency = InterlockedExchangeAdd(&m_nBuffersPending, 0) * m_nWaveBufferSize * 1.0 / m_Settings.GetBytesPerSecond(); result.LastUpdateInterval = 1.0 * m_nWaveBufferSize / m_Settings.GetBytesPerSecond(); uint32 bugs = m_DriverBugs.load(); if(bugs != 0) { result.text = mpt::format(MPT_USTRING("Problematic driver detected! Error flags: %1"))(mpt::ufmt::hex0<8>(bugs)); } else { result.text = mpt::format(MPT_USTRING("Driver working as expected."))(); } return result; }
OPENMPT_NAMESPACE_BEGIN ////////////////////////////////////////////////////////////////////////// // Noise Shaping (Dithering) mpt::ustring Dither::GetModeName(DitherMode mode) { switch(mode) { case DitherNone : return MPT_USTRING("no" ); break; case DitherDefault: return MPT_USTRING("default"); break; case DitherModPlug: return MPT_USTRING("0.5 bit"); break; case DitherSimple : return MPT_USTRING("1 bit" ); break; default : return MPT_USTRING("" ); break; } }
OPENMPT_NAMESPACE_BEGIN #ifndef NO_DMO #define DMO_LOG IMixPlugin* DMOPlugin::Create(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct) //------------------------------------------------------------------------------------------------ { CLSID clsid; if (Util::VerifyStringToCLSID(factory.dllPath.ToWide(), clsid)) { IMediaObject *pMO = nullptr; IMediaObjectInPlace *pMOIP = nullptr; if ((CoCreateInstance(clsid, nullptr, CLSCTX_INPROC_SERVER, IID_IMediaObject, (VOID **)&pMO) == S_OK) && (pMO)) { if (pMO->QueryInterface(IID_IMediaObjectInPlace, (void **)&pMOIP) != S_OK) pMOIP = nullptr; } else pMO = nullptr; if ((pMO) && (pMOIP)) { DWORD dwInputs = 0, dwOutputs = 0; pMO->GetStreamCount(&dwInputs, &dwOutputs); if (dwInputs == 1 && dwOutputs == 1) { DMOPlugin *p = new (std::nothrow) DMOPlugin(factory, sndFile, mixStruct, pMO, pMOIP, clsid.Data1); return p; } #ifdef DMO_LOG Log(factory.libraryName.ToUnicode() + MPT_USTRING(": Unable to use this DMO")); #endif } #ifdef DMO_LOG else Log(factory.libraryName.ToUnicode() + MPT_USTRING(": Failed to get IMediaObject & IMediaObjectInPlace interfaces")); #endif if (pMO) pMO->Release(); if (pMOIP) pMOIP->Release(); } return nullptr; }
FLACEncoder::FLACEncoder() //------------------------ { Encoder::Traits traits; traits.fileExtension = MPT_PATHSTRING("flac"); traits.fileShortDescription = MPT_USTRING("FLAC"); traits.fileDescription = MPT_USTRING("FLAC"); traits.encoderSettingsName = MPT_USTRING("FLAC"); traits.encoderName = MPT_USTRING("libFLAC"); traits.description = MPT_USTRING(""); traits.description += mpt::String::Print(MPT_USTRING("Free Lossless Audio Codec\n")); traits.description += mpt::String::Print(MPT_USTRING("Vendor: %1\n"), mpt::ToUnicode(mpt::CharsetASCII, FLAC__VENDOR_STRING)); traits.description += mpt::String::Print(MPT_USTRING("Version: %1\n"), mpt::ToUnicode(mpt::CharsetASCII, FLAC__VERSION_STRING)); traits.description += mpt::String::Print(MPT_USTRING("API: %1.%2.%3\n"), FLAC_API_VERSION_CURRENT, FLAC_API_VERSION_REVISION, FLAC_API_VERSION_AGE); traits.canTags = true; traits.maxChannels = 4; traits.samplerates = TrackerSettings::Instance().GetSampleRates(); traits.modes = Encoder::ModeEnumerated; for(std::size_t i = 0; i < traits.samplerates.size(); ++i) { int samplerate = traits.samplerates[i]; for(int channels = 1; channels <= traits.maxChannels; channels *= 2) { for(int bytes = 3; bytes >= 1; --bytes) { Encoder::Format format; format.Samplerate = samplerate; format.Channels = channels; format.Sampleformat = (SampleFormat)(bytes * 8); format.Description = mpt::String::Print(MPT_USTRING("%1 Bit"), bytes * 8); format.Bitrate = 0; traits.formats.push_back(format); } } } traits.defaultSamplerate = 48000; traits.defaultChannels = 2; traits.defaultMode = Encoder::ModeEnumerated; traits.defaultFormat = 0; SetTraits(traits); }
std::vector<SoundDevice::Info> CWaveDevice::EnumerateDevices(SoundDevice::SysInfo /* sysInfo */ ) //----------------------------------------------------------------------------------------------- { MPT_TRACE(); std::vector<SoundDevice::Info> devices; UINT numDevs = waveOutGetNumDevs(); for(UINT index = 0; index <= numDevs; ++index) { SoundDevice::Info info; info.type = TypeWAVEOUT; info.internalID = mpt::ufmt::dec(index); info.apiName = MPT_USTRING("WaveOut"); info.useNameAsIdentifier = true; WAVEOUTCAPSW woc; MemsetZero(woc); if(waveOutGetDevCapsW((index == 0) ? WAVE_MAPPER : (index - 1), &woc, sizeof(woc)) == MMSYSERR_NOERROR) { info.name = mpt::ToUnicode(woc.szPname); info.extraData[MPT_USTRING("DriverID")] = mpt::format(MPT_USTRING("%1:%2"))(mpt::ufmt::hex0<4>(woc.wMid), mpt::ufmt::hex0<4>(woc.wPid)); info.extraData[MPT_USTRING("DriverVersion")] = mpt::format(MPT_USTRING("%3.%4"))(mpt::ufmt::dec((static_cast<uint32>(woc.vDriverVersion) >> 24) & 0xff), mpt::ufmt::dec((static_cast<uint32>(woc.vDriverVersion) >> 0) & 0xff)); } else if(index == 0)
mpt::ustring BuildVariants::GuessCurrentBuildName() { #if (MPT_ARCH_BITS == 64) if(CurrentBuildIsModern()) { return MPT_USTRING("win64"); } else { return MPT_USTRING("win64old"); } #elif (MPT_ARCH_BITS == 32) if(CurrentBuildIsModern()) { return MPT_USTRING("win32"); } else { return MPT_USTRING("win32old"); } #else return mpt::ustring(); #endif }
mpt::ustring TypeToString(SoundDevice::Type type) //----------------------------------------------- { switch(type) { case TypeWAVEOUT: return MPT_USTRING("WaveOut"); break; case TypeDSOUND: return MPT_USTRING("DirectSound"); break; case TypeASIO: return MPT_USTRING("ASIO"); break; case TypePORTAUDIO_WASAPI: return MPT_USTRING("WASAPI"); break; case TypePORTAUDIO_WDMKS: return MPT_USTRING("WDM-KS"); break; case TypePORTAUDIO_WMME: return MPT_USTRING("MME"); break; case TypePORTAUDIO_DS: return MPT_USTRING("DS"); break; case TypePORTAUDIO_ASIO: return MPT_USTRING("ASIO"); break; } return mpt::ustring(); }
bool CWaveDevice::CheckResult(MMRESULT result) //-------------------------------------------- { if(result == MMSYSERR_NOERROR) { return true; } if(!m_Failed) { // only show the first error m_Failed = true; WCHAR errortext[MAXERRORLENGTH + 1]; MemsetZero(errortext); waveOutGetErrorTextW(result, errortext, MAXERRORLENGTH); SendDeviceMessage(LogError, mpt::format(MPT_USTRING("WaveOut error: 0x%1: %2"))(mpt::ufmt::hex0<8>(result), mpt::ToUnicode(errortext))); } RequestClose(); return false; }
WAVEncoder::WAVEncoder() //---------------------- { Encoder::Traits traits; traits.fileExtension = MPT_PATHSTRING("wav"); traits.fileShortDescription = MPT_USTRING("Wave"); traits.fileDescription = MPT_USTRING("Wave"); traits.encoderSettingsName = MPT_USTRING("Wave"); traits.encoderName = MPT_USTRING("OpenMPT"); traits.description = MPT_USTRING("Microsoft RIFF WAVE"); traits.canTags = true; traits.canCues = true; traits.maxChannels = 4; traits.samplerates = TrackerSettings::Instance().GetSampleRates(); traits.modes = Encoder::ModeEnumerated; for(std::size_t i = 0; i < traits.samplerates.size(); ++i) { int samplerate = traits.samplerates[i]; for(int channels = 1; channels <= traits.maxChannels; channels *= 2) { for(int bytes = 5; bytes >= 1; --bytes) { Encoder::Format format; format.Samplerate = samplerate; format.Channels = channels; if(bytes == 5) { format.Sampleformat = SampleFormatFloat32; format.Description = MPT_USTRING("Floating Point"); } else { format.Sampleformat = (SampleFormat)(bytes * 8); format.Description = mpt::String::Print(MPT_USTRING("%1 Bit"), bytes * 8); } format.Bitrate = 0; traits.formats.push_back(format); } } } traits.defaultSamplerate = 48000; traits.defaultChannels = 2; traits.defaultMode = Encoder::ModeEnumerated; traits.defaultFormat = 0; SetTraits(traits); }
virtual void WriteMetatags(const FileTags &tags) { ASSERT(inited && !started); flac_metadata[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT); AddCommentField("ENCODER", tags.encoder); if(writeTags) { AddCommentField("SOURCEMEDIA", MPT_USTRING("tracked music file")); AddCommentField("TITLE", tags.title ); AddCommentField("ARTIST", tags.artist ); AddCommentField("ALBUM", tags.album ); AddCommentField("DATE", tags.year ); AddCommentField("COMMENT", tags.comments ); AddCommentField("GENRE", tags.genre ); AddCommentField("CONTACT", tags.url ); AddCommentField("BPM", tags.bpm ); // non-standard AddCommentField("TRACKNUMBER", tags.trackno ); } FLAC__stream_encoder_set_metadata(encoder, flac_metadata, 1); }
bool CWaveDevice::InternalClose() //------------------------------- { MPT_TRACE(); if(m_hWaveOut) { waveOutReset(m_hWaveOut); m_JustStarted = false; InterlockedExchange(&m_nBuffersPending, 0); m_nWriteBuffer = 0; m_nDoneBuffer = 0; while(m_nPreparedHeaders > 0) { m_nPreparedHeaders--; waveOutUnprepareHeader(m_hWaveOut, &m_WaveBuffers[m_nPreparedHeaders], sizeof(WAVEHDR)); } waveOutClose(m_hWaveOut); m_hWaveOut = NULL; } #ifdef _DEBUG if(m_DriverBugs.load()) { SendDeviceMessage(LogError, MPT_USTRING("Errors were detected while playing sound:\n") + GetStatistics().text); } #endif m_DriverBugs = 0; m_Failed = false; if(m_ThreadWakeupEvent) { CloseHandle(m_ThreadWakeupEvent); m_ThreadWakeupEvent = NULL; } { MPT_LOCK_GUARD<mpt::mutex> guard(m_PositionWraparoundMutex); MemsetZero(m_PositionLast); m_PositionWrappedCount = 0; } return true; }
void Logger::operator () (LogLevel level, const mpt::ustring &text) //----------------------------------------------------------------- { DoLog(context, LogLevelToString(level) + MPT_USTRING(": ") + text); }
void CSelectPluginDlg::UpdatePluginsList(int32 forceSelect /* = 0*/) //------------------------------------------------------------------ { CVstPluginManager *pManager = theApp.GetPluginManager(); m_treePlugins.SetRedraw(FALSE); m_treePlugins.DeleteAllItems(); static const struct { VSTPluginLib::PluginCategory category; const WCHAR *description; } categories[] = { { VSTPluginLib::catEffect, L"Audio Effects" }, { VSTPluginLib::catGenerator, L"Tone Generators" }, { VSTPluginLib::catRestoration, L"Audio Restauration" }, { VSTPluginLib::catSurroundFx, L"Surround Effects" }, { VSTPluginLib::catRoomFx, L"Room Effects" }, { VSTPluginLib::catSpacializer, L"Spacializers" }, { VSTPluginLib::catMastering, L"Mastering Plugins" }, { VSTPluginLib::catAnalysis, L"Analysis Plugins" }, { VSTPluginLib::catOfflineProcess, L"Offline Processing" }, { VSTPluginLib::catShell, L"Shell Plugins" }, { VSTPluginLib::catUnknown, L"Unsorted" }, { VSTPluginLib::catDMO, L"DirectX Media Audio Effects" }, { VSTPluginLib::catSynth, L"Instrument Plugins" }, }; std::bitset<VSTPluginLib::numCategories> categoryUsed; HTREEITEM categoryFolders[VSTPluginLib::numCategories]; for(size_t i = CountOf(categories); i != 0; ) { i--; categoryFolders[categories[i].category] = AddTreeItem(categories[i].description, IMAGE_FOLDER, false); } HTREEITEM noPlug = AddTreeItem(L"No plugin (empty slot)", IMAGE_NOPLUGIN, false); HTREEITEM currentPlug = noPlug; bool foundCurrentPlug = false; const bool nameFilterActive = !m_nameFilter.empty(); auto currentTags = mpt::String::Split<mpt::ustring>(m_nameFilter, MPT_USTRING(" ")); if(pManager) { bool first = true; for(auto p : *pManager) { ASSERT(p); const VSTPluginLib &plug = *p; if(nameFilterActive) { // Apply name filter bool matches = false; // Search in plugin names { mpt::ustring displayName = mpt::ToLowerCase(plug.libraryName.ToUnicode()); if(displayName.find(m_nameFilter, 0) != displayName.npos) { matches = true; } } // Search in plugin tags if(!matches) { mpt::ustring tags = mpt::ToLowerCase(plug.tags); for(const auto &tag : currentTags) { if(!tag.empty() && tags.find(tag, 0) != tags.npos) { matches = true; break; } } } // Search in plugin vendors if(!matches) { mpt::ustring vendor = mpt::ToLowerCase(mpt::ToUnicode(plug.vendor)); if(vendor.find(m_nameFilter, 0) != vendor.npos) { matches = true; } } if(!matches) continue; } std::wstring title = plug.libraryName.AsNative(); if(!plug.IsNativeFromCache()) { title += mpt::String::Print(L" (%1-Bit)", plug.GetDllBits()); } HTREEITEM h = AddTreeItem(title.c_str(), plug.isInstrument ? IMAGE_PLUGININSTRUMENT : IMAGE_EFFECTPLUGIN, true, categoryFolders[plug.category], reinterpret_cast<LPARAM>(&plug)); categoryUsed[plug.category] = true; if(nameFilterActive) { // If filter is active, expand nodes. m_treePlugins.EnsureVisible(h); if(first) { first = false; m_treePlugins.SelectItem(h); } } if(forceSelect != 0 && plug.pluginId2 == forceSelect) { // Forced selection (e.g. just after add plugin) currentPlug = h; foundCurrentPlug = true; } if(m_pPlugin && !foundCurrentPlug) { //Which plugin should be selected? if(m_pPlugin->pMixPlugin) { //Current slot's plugin IMixPlugin *pPlugin = m_pPlugin->pMixPlugin; if (&pPlugin->GetPluginFactory() == &plug) { currentPlug = h; } } else if(m_pPlugin->Info.dwPluginId1 != 0 || m_pPlugin->Info.dwPluginId2 != 0) { //Plugin with matching ID to current slot's plug if(plug.pluginId1 == m_pPlugin->Info.dwPluginId1 && plug.pluginId2 == m_pPlugin->Info.dwPluginId2) { currentPlug = h; } } else if(plug.pluginId2 == TrackerSettings::Instance().gnPlugWindowLast) { // Previously selected plugin currentPlug = h; } if(currentPlug == h) { foundCurrentPlug = true; } } } } // Remove empty categories for(size_t i = 0; i < CountOf(categoryFolders); i++) { if(!categoryUsed[i]) { m_treePlugins.DeleteItem(categoryFolders[i]); } } m_treePlugins.SetRedraw(TRUE); if(!nameFilterActive || currentPlug != noPlug) { m_treePlugins.SelectItem(currentPlug); } m_treePlugins.SetItemState(currentPlug, TVIS_BOLD, TVIS_BOLD); m_treePlugins.EnsureVisible(currentPlug); }
OPENMPT_NAMESPACE_BEGIN // Version changelog: // v1.03: - Relative unicode instrument paths instead of absolute ANSI paths // - Per-path variable string length // - Embedded samples are IT-compressed // (rev. 3249) // v1.02: Explicitely updated format to use new instrument flags representation (rev. 483) // v1.01: Added option to embed instrument headers bool CSoundFile::ReadITProject(FileReader &file, ModLoadingFlags loadFlags) //------------------------------------------------------------------------- { #ifndef MPT_EXTERNAL_SAMPLES // Doesn't really make sense to support this format when there's no support for external files... MPT_UNREFERENCED_PARAMETER(file); MPT_UNREFERENCED_PARAMETER(loadFlags); return false; #else // MPT_EXTERNAL_SAMPLES enum ITPSongFlags { ITP_EMBEDMIDICFG = 0x00001, // Embed macros in file ITP_ITOLDEFFECTS = 0x00004, // Old Impulse Tracker effect implementations ITP_ITCOMPATGXX = 0x00008, // IT "Compatible Gxx" (IT's flag to behave more like other trackers w/r/t portamento effects) ITP_LINEARSLIDES = 0x00010, // Linear slides vs. Amiga slides ITP_EXFILTERRANGE = 0x08000, // Cutoff Filter has double frequency range (up to ~10Khz) ITP_ITPROJECT = 0x20000, // Is a project file ITP_ITPEMBEDIH = 0x40000, // Embed instrument headers in project file }; uint32 version; FileReader::off_t size; file.Rewind(); // Check file ID if(!file.CanRead(12 + 4 + 24 + 4) || file.ReadUint32LE() != MAGIC4BE('.','i','t','p') // Magic bytes || (version = file.ReadUint32LE()) > 0x00000103 // Format version || version < 0x00000100) { return false; } else if(loadFlags == onlyVerifyHeader) { return true; } InitializeGlobals(MOD_TYPE_IT); m_playBehaviour.reset(); file.ReadString<mpt::String::maybeNullTerminated>(m_songName, file.ReadUint32LE()); // Song comments m_songMessage.Read(file, file.ReadUint32LE(), SongMessage::leCR); // Song global config const uint32 songFlags = file.ReadUint32LE(); if(!(songFlags & ITP_ITPROJECT)) { return false; } if(songFlags & ITP_EMBEDMIDICFG) m_SongFlags.set(SONG_EMBEDMIDICFG); if(songFlags & ITP_ITOLDEFFECTS) m_SongFlags.set(SONG_ITOLDEFFECTS); if(songFlags & ITP_ITCOMPATGXX) m_SongFlags.set(SONG_ITCOMPATGXX); if(songFlags & ITP_LINEARSLIDES) m_SongFlags.set(SONG_LINEARSLIDES); if(songFlags & ITP_EXFILTERRANGE) m_SongFlags.set(SONG_EXFILTERRANGE); m_nDefaultGlobalVolume = file.ReadUint32LE(); m_nSamplePreAmp = file.ReadUint32LE(); m_nDefaultSpeed = std::max(uint32(1), file.ReadUint32LE()); m_nDefaultTempo.Set(std::max(uint32(32), file.ReadUint32LE())); m_nChannels = static_cast<CHANNELINDEX>(file.ReadUint32LE()); if(m_nChannels == 0 || m_nChannels > MAX_BASECHANNELS) { return false; } // channel name string length (=MAX_CHANNELNAME) size = file.ReadUint32LE(); // Channels' data for(CHANNELINDEX chn = 0; chn < m_nChannels; chn++) { ChnSettings[chn].nPan = std::min(static_cast<uint16>(file.ReadUint32LE()), uint16(256)); ChnSettings[chn].dwFlags.reset(); uint32 flags = file.ReadUint32LE(); if(flags & 0x100) ChnSettings[chn].dwFlags.set(CHN_MUTE); if(flags & 0x800) ChnSettings[chn].dwFlags.set(CHN_SURROUND); ChnSettings[chn].nVolume = std::min(static_cast<uint16>(file.ReadUint32LE()), uint16(64)); file.ReadString<mpt::String::maybeNullTerminated>(ChnSettings[chn].szName, size); } // Song mix plugins { FileReader plugChunk = file.ReadChunk(file.ReadUint32LE()); LoadMixPlugins(plugChunk); } // MIDI Macro config file.ReadStructPartial(m_MidiCfg, file.ReadUint32LE()); m_MidiCfg.Sanitize(); // Song Instruments m_nInstruments = static_cast<INSTRUMENTINDEX>(file.ReadUint32LE()); if(m_nInstruments >= MAX_INSTRUMENTS) { return false; } // Instruments' paths if(version <= 0x00000102) { size = file.ReadUint32LE(); // path string length } std::vector<mpt::PathString> instrPaths(GetNumInstruments()); for(INSTRUMENTINDEX ins = 0; ins < GetNumInstruments(); ins++) { if(version > 0x00000102) { size = file.ReadUint32LE(); // path string length } std::string path; file.ReadString<mpt::String::maybeNullTerminated>(path, size); if(version <= 0x00000102) { instrPaths[ins] = mpt::PathString::FromLocaleSilent(path); } else { instrPaths[ins] = mpt::PathString::FromUTF8(path); } } // Song Orders size = file.ReadUint32LE(); Order.ReadAsByte(file, size, size, 0xFF, 0xFE); // Song Patterns const PATTERNINDEX numPats = static_cast<PATTERNINDEX>(file.ReadUint32LE()); const PATTERNINDEX numNamedPats = static_cast<PATTERNINDEX>(file.ReadUint32LE()); size_t patNameLen = file.ReadUint32LE(); // Size of each pattern name FileReader pattNames = file.ReadChunk(numNamedPats * patNameLen); // modcommand data length size = file.ReadUint32LE(); if(size != 6) { return false; } for(PATTERNINDEX pat = 0; pat < numPats; pat++) { const ROWINDEX numRows = file.ReadUint32LE(); FileReader patternChunk = file.ReadChunk(numRows * size * GetNumChannels()); // Allocate pattern if(!(loadFlags & loadPatternData) || !Patterns.Insert(pat, numRows)) { pattNames.Skip(patNameLen); continue; } if(pat < numNamedPats) { char patName[32]; pattNames.ReadString<mpt::String::maybeNullTerminated>(patName, patNameLen); Patterns[pat].SetName(patName); } // Pattern data size_t numCommands = GetNumChannels() * numRows; if(patternChunk.CanRead(sizeof(MODCOMMAND_ORIGINAL) * numCommands)) { ModCommand *target = Patterns[pat].GetpModCommand(0, 0); while(numCommands-- != 0) { STATIC_ASSERT(sizeof(MODCOMMAND_ORIGINAL) == 6); MODCOMMAND_ORIGINAL data; patternChunk.ReadStruct(data); if(data.command >= MAX_EFFECTS) data.command = CMD_NONE; if(data.volcmd >= MAX_VOLCMDS) data.volcmd = VOLCMD_NONE; if(data.note > NOTE_MAX && data.note < NOTE_MIN_SPECIAL) data.note = NOTE_NONE; *(target++) = data; } } } // Load embedded samples // Read original number of samples m_nSamples = static_cast<SAMPLEINDEX>(file.ReadUint32LE()); LimitMax(m_nSamples, SAMPLEINDEX(MAX_SAMPLES - 1)); // Read number of embedded samples uint32 embeddedSamples = file.ReadUint32LE(); // Read samples for(uint32 smp = 0; smp < embeddedSamples; smp++) { SAMPLEINDEX realSample = static_cast<SAMPLEINDEX>(file.ReadUint32LE()); ITSample sampleHeader; file.ReadConvertEndianness(sampleHeader); FileReader sampleData = file.ReadChunk(file.ReadUint32LE()); if(realSample >= 1 && realSample <= GetNumSamples() && !memcmp(sampleHeader.id, "IMPS", 4) && (loadFlags & loadSampleData)) { sampleHeader.ConvertToMPT(Samples[realSample]); mpt::String::Read<mpt::String::nullTerminated>(m_szNames[realSample], sampleHeader.name); // Read sample data sampleHeader.GetSampleFormat().ReadSample(Samples[realSample], sampleData); } } // Load instruments for(INSTRUMENTINDEX ins = 0; ins < GetNumInstruments(); ins++) { if(instrPaths[ins].empty()) continue; if(!file.GetFileName().empty()) { instrPaths[ins] = instrPaths[ins].RelativePathToAbsolute(file.GetFileName().GetPath()); } #ifdef MODPLUG_TRACKER else if(GetpModDoc() != nullptr) { instrPaths[ins] = instrPaths[ins].RelativePathToAbsolute(GetpModDoc()->GetPathNameMpt().GetPath()); } #endif // MODPLUG_TRACKER InputFile f(instrPaths[ins]); FileReader file = GetFileReader(f); if(!ReadInstrumentFromFile(ins + 1, file, true)) { AddToLog(LogWarning, MPT_USTRING("Unable to open instrument: ") + instrPaths[ins].ToUnicode()); } } // Extra info data uint32 code = file.ReadUint32LE(); // Embed instruments' header [v1.01] if(version >= 0x00000101 && (songFlags & ITP_ITPEMBEDIH) && code == MAGIC4BE('E', 'B', 'I', 'H')) { code = file.ReadUint32LE(); INSTRUMENTINDEX ins = 1; while(ins <= GetNumInstruments() && file.CanRead(4)) { if(code == MAGIC4BE('M', 'P', 'T', 'S')) { break; } else if(code == MAGIC4BE('S', 'E', 'P', '@') || code == MAGIC4BE('M', 'P', 'T', 'X')) { // jump code - switch to next instrument ins++; } else { ReadExtendedInstrumentProperty(Instruments[ins], code, file); } code = file.ReadUint32LE(); } } // Song extensions if(code == MAGIC4BE('M', 'P', 'T', 'S')) { file.SkipBack(4); LoadExtendedSongProperties(file); } m_nMaxPeriod = 0xF000; m_nMinPeriod = 8; // Before OpenMPT 1.20.01.09, the MIDI macros were always read from the file, even if the "embed" flag was not set. if(m_dwLastSavedWithVersion >= MAKE_VERSION_NUMERIC(1,20,01,09) && !m_SongFlags[SONG_EMBEDMIDICFG]) { m_MidiCfg.Reset(); } else if(!m_MidiCfg.IsMacroDefaultSetupUsed()) { m_SongFlags.set(SONG_EMBEDMIDICFG); } m_madeWithTracker = "OpenMPT " + MptVersion::ToStr(m_dwLastSavedWithVersion); return true; #endif // MPT_EXTERNAL_SAMPLES }
{ SoundDevice::Info info; info.type = TypeWAVEOUT; info.internalID = mpt::ufmt::dec(index); info.apiName = MPT_USTRING("WaveOut"); info.useNameAsIdentifier = true; WAVEOUTCAPSW woc; MemsetZero(woc); if(waveOutGetDevCapsW((index == 0) ? WAVE_MAPPER : (index - 1), &woc, sizeof(woc)) == MMSYSERR_NOERROR) { info.name = mpt::ToUnicode(woc.szPname); info.extraData[MPT_USTRING("DriverID")] = mpt::format(MPT_USTRING("%1:%2"))(mpt::ufmt::hex0<4>(woc.wMid), mpt::ufmt::hex0<4>(woc.wPid)); info.extraData[MPT_USTRING("DriverVersion")] = mpt::format(MPT_USTRING("%3.%4"))(mpt::ufmt::dec((static_cast<uint32>(woc.vDriverVersion) >> 24) & 0xff), mpt::ufmt::dec((static_cast<uint32>(woc.vDriverVersion) >> 0) & 0xff)); } else if(index == 0) { info.name = mpt::format(MPT_USTRING("Auto (Wave Mapper)"))(); } else { info.name = mpt::format(MPT_USTRING("Device %1"))(index - 1); } info.isDefault = (index == 0); devices.push_back(info); } return devices; } #endif // MPT_OS_WINDOWS } // namespace SoundDevice