예제 #1
0
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
}
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #4
0
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;
}
예제 #5
0
파일: Dither.cpp 프로젝트: kode54/Cog
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;
	}
}
예제 #6
0
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;
}
예제 #7
0
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);
}
예제 #8
0
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)
예제 #9
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
}
예제 #10
0
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();
}
예제 #11
0
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;
}
예제 #12
0
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);
}
예제 #13
0
	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);
	}
예제 #14
0
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;
}
예제 #15
0
void Logger::operator () (LogLevel level, const mpt::ustring &text)
//-----------------------------------------------------------------
{
	DoLog(context, LogLevelToString(level) + MPT_USTRING(": ") + text);
}
예제 #16
0
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);
}
예제 #17
0
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
}
예제 #18
0
	{
		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