[SCM] libopenmpt/upstream: New upstream version 0.2.8461~beta26

jcowgill at users.alioth.debian.org jcowgill at users.alioth.debian.org
Sun Jul 9 11:59:13 UTC 2017


The following commit has been merged in the upstream branch:
commit f32cdc3ad7caac3602d9e0dab4282b267dc0cad2
Author: James Cowgill <james410 at cowgill.org.uk>
Date:   Sun Jul 9 12:51:59 2017 +0100

    New upstream version 0.2.8461~beta26

diff --git a/Makefile.am b/Makefile.am
index 87ba1a7..3023ce7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -105,7 +105,7 @@ nobase_include_HEADERS =
 
 pkgconfig_DATA += libopenmpt/libopenmpt.pc
 lib_LTLIBRARIES += libopenmpt.la
-libopenmpt_la_LDFLAGS = -version-info 0:25:0
+libopenmpt_la_LDFLAGS = -version-info 0:26:0
 nobase_include_HEADERS += libopenmpt/libopenmpt.h libopenmpt/libopenmpt.hpp libopenmpt/libopenmpt_version.h libopenmpt/libopenmpt_config.h libopenmpt/libopenmpt_stream_callbacks_fd.h libopenmpt/libopenmpt_stream_callbacks_file.h libopenmpt/libopenmpt_ext.hpp
 libopenmpt_la_CPPFLAGS = -DLIBOPENMPT_BUILD -I$(srcdir)/build/svn_version -I$(srcdir)/ -I$(srcdir)/common $(ZLIB_CFLAGS) $(MPG123_CFLAGS) $(OGG_CFLAGS) $(VORBIS_CFLAGS) $(VORBISFILE_CFLAGS) $(LTDL_CPPFLAGS) $(DL_CPPFLAGS)
 libopenmpt_la_CXXFLAGS = $(ZLIB_CFLAGS) $(MPG123_CFLAGS) $(OGG_CFLAGS) $(VORBIS_CFLAGS) $(VORBISFILE_CFLAGS)
diff --git a/Makefile.in b/Makefile.in
index 3713042..37bb72f 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1184,7 +1184,7 @@ nobase_include_HEADERS = libopenmpt/libopenmpt.h \
 	libopenmpt/libopenmpt_stream_callbacks_fd.h \
 	libopenmpt/libopenmpt_stream_callbacks_file.h \
 	libopenmpt/libopenmpt_ext.hpp $(am__append_7)
-libopenmpt_la_LDFLAGS = -version-info 0:25:0
+libopenmpt_la_LDFLAGS = -version-info 0:26:0
 libopenmpt_la_CPPFLAGS = -DLIBOPENMPT_BUILD -I$(srcdir)/build/svn_version -I$(srcdir)/ -I$(srcdir)/common $(ZLIB_CFLAGS) $(MPG123_CFLAGS) $(OGG_CFLAGS) $(VORBIS_CFLAGS) $(VORBISFILE_CFLAGS) $(LTDL_CPPFLAGS) $(DL_CPPFLAGS)
 libopenmpt_la_CXXFLAGS = $(ZLIB_CFLAGS) $(MPG123_CFLAGS) $(OGG_CFLAGS) $(VORBIS_CFLAGS) $(VORBISFILE_CFLAGS)
 libopenmpt_la_CFLAGS = $(ZLIB_CFLAGS) $(MPG123_CFLAGS) $(OGG_CFLAGS) $(VORBIS_CFLAGS) $(VORBISFILE_CFLAGS)
@@ -5598,9 +5598,9 @@ distclean-generic:
 maintainer-clean-generic:
 	@echo "This command is intended for maintainers to use"
 	@echo "it deletes files that may require special tools to rebuild."
+ at DX_COND_doc_FALSE@uninstall-local:
 @DX_COND_doc_FALSE at install-data-local:
 @DX_COND_doc_FALSE at clean-local:
- at DX_COND_doc_FALSE@uninstall-local:
 clean: clean-am
 
 clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
diff --git a/common/mptTime.cpp b/common/mptTime.cpp
index 16193d8..a458e02 100644
--- a/common/mptTime.cpp
+++ b/common/mptTime.cpp
@@ -88,48 +88,77 @@ Unix::Unix()
 	return;
 }
 
-Unix::Unix(time_t unixtime)
-//-------------------------
+Unix::Unix(int64 unixtime)
+//------------------------
 	: Value(unixtime)
 {
 	return;
 }
 
-Unix::operator time_t () const
-//----------------------------
+Unix::operator int64 () const
+//---------------------------
 {
 	return Value;
 }
 
+static int32 ToDaynum(int32 year, int32 month, int32 day)
+//-------------------------------------------------------
+{
+	month = (month + 9) % 12;
+	year = year - (month / 10);
+	int32 daynum = year*365 + year/4 - year/100 + year/400 + (month*306 + 5)/10 + (day - 1);
+	return daynum;
+}
+
+static void FromDaynum(int32 d, int32 & year, int32 & month, int32 & day)
+//-----------------------------------------------------------------------
+{
+	int64 g = d;
+	int64 y,ddd,mi,mm,dd;
+
+	y = (10000*g + 14780)/3652425;
+	ddd = g - (365*y + y/4 - y/100 + y/400);
+	if(ddd < 0)
+	{
+		y = y - 1;
+		ddd = g - (365*y + y/4 - y/100 + y/400);
+	}
+	mi = (100*ddd + 52)/3060;
+	mm = (mi + 2)%12 + 1;
+	y = y + (mi + 2)/12;
+	dd = ddd - (mi*306 + 5)/10 + 1;
+
+	year = static_cast<int32>(y);
+	month = static_cast<int32>(mm);
+	day = static_cast<int32>(dd);
+}
+
 mpt::Date::Unix Unix::FromUTC(tm timeUtc)
 //---------------------------------------
 {
-	#if MPT_COMPILER_MSVC
-		return mpt::Date::Unix(_mkgmtime(&timeUtc));
-	#else // !MPT_COMPILER_MSVC
-		// There is no portable way in C/C++ to convert between time_t and struct tm in UTC.
-		// Approximate it as good as possible without implementing full date handling logic.
-		// NOTE:
-		// This can be wrong for dates during DST switch.
-		tm t = timeUtc;
-		time_t localSinceEpoch = mktime(&t);
-		const tm * tmpLocal = localtime(&localSinceEpoch);
-		if(!tmpLocal)
-		{
-			return mpt::Date::Unix(localSinceEpoch);
-		}
-		tm localTM = *tmpLocal;
-		const tm * tmpUTC = gmtime(&localSinceEpoch);
-		if(!tmpUTC)
-		{
-			return mpt::Date::Unix(localSinceEpoch);
-		}
-		tm utcTM = *tmpUTC;
-		double offset = difftime(mktime(&localTM), mktime(&utcTM));
-		double timeScaleFactor = difftime(2, 1);
-		time_t utcSinceEpoch = localSinceEpoch + Util::Round<time_t>(offset / timeScaleFactor);
-		return mpt::Date::Unix(utcSinceEpoch);
-	#endif // MPT_COMPILER_MSVC
+	int32 daynum = ToDaynum(timeUtc.tm_year+1900, timeUtc.tm_mon+1, timeUtc.tm_mday);
+	int64 seconds = static_cast<int64>(daynum - ToDaynum(1970,1,1))*24*60*60 + timeUtc.tm_hour*60*60 + timeUtc.tm_min*60 + timeUtc.tm_sec;
+	return mpt::Date::Unix(seconds);
+}
+
+tm Unix::AsUTC() const 
+//--------------------
+{
+	int64 tmp = Value;
+	int64 seconds = tmp % 60; tmp /= 60;
+	int64 minutes = tmp % 60; tmp /= 60;
+	int64 hours   = tmp % 24; tmp /= 24;
+	int32 year = 0, month = 0, day = 0;
+	FromDaynum(static_cast<int32>(tmp) + ToDaynum(1970,1,1), year, month, day);
+	tm result;
+	MemsetZero(result);
+	result.tm_year = year - 1900;
+	result.tm_mon = month - 1;
+	result.tm_mday = day;
+	result.tm_hour = static_cast<int32>(hours);
+	result.tm_min = static_cast<int32>(minutes);
+	result.tm_sec = static_cast<int32>(seconds);
+	return result;
 }
 
 mpt::ustring ToShortenedISO8601(tm date)
diff --git a/common/mptTime.h b/common/mptTime.h
index a1b5033..9d876f1 100644
--- a/common/mptTime.h
+++ b/common/mptTime.h
@@ -44,15 +44,16 @@ mpt::ustring ToString(uint64 time100ns); // i.e. 2015-01-15 18:32:01.718
 
 class Unix
 {
-// time_t counts 1s since 1970-01-01T00:00Z
+// int64 counts 1s since 1970-01-01T00:00Z
 private:
-	time_t Value;
+	int64 Value;
 public:
 	Unix();
-	explicit Unix(time_t unixtime);
-	operator time_t () const;
+	explicit Unix(int64 unixtime);
+	operator int64 () const;
 public:
 	static mpt::Date::Unix FromUTC(tm timeUtc);
+	tm AsUTC() const;
 };
 
 mpt::ustring ToShortenedISO8601(tm date); // i.e. 2015-01-15T18:32:01Z
diff --git a/common/versionNumber.h b/common/versionNumber.h
index 1016fb6..92c02ca 100644
--- a/common/versionNumber.h
+++ b/common/versionNumber.h
@@ -19,7 +19,7 @@ OPENMPT_NAMESPACE_BEGIN
 #define VER_MAJORMAJOR          1
 #define VER_MAJOR               26
 #define VER_MINOR               12
-#define VER_MINORMINOR          00
+#define VER_MINORMINOR          01
 
 //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)
diff --git a/configure b/configure
index 93cff57..18e0272 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for libopenmpt 0.2.8414-autotools.
+# Generated by GNU Autoconf 2.69 for libopenmpt 0.2.8461-autotools.
 #
 # Report bugs to <https://bugs.openmpt.org/>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='libopenmpt'
 PACKAGE_TARNAME='libopenmpt'
-PACKAGE_VERSION='0.2.8414-autotools'
-PACKAGE_STRING='libopenmpt 0.2.8414-autotools'
+PACKAGE_VERSION='0.2.8461-autotools'
+PACKAGE_STRING='libopenmpt 0.2.8461-autotools'
 PACKAGE_BUGREPORT='https://bugs.openmpt.org/'
 PACKAGE_URL='https://lib.openmpt.org/'
 
@@ -1477,7 +1477,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures libopenmpt 0.2.8414-autotools to adapt to many kinds of systems.
+\`configure' configures libopenmpt 0.2.8461-autotools to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1547,7 +1547,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of libopenmpt 0.2.8414-autotools:";;
+     short | recursive ) echo "Configuration of libopenmpt 0.2.8461-autotools:";;
    esac
   cat <<\_ACEOF
 
@@ -1742,7 +1742,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-libopenmpt configure 0.2.8414-autotools
+libopenmpt configure 0.2.8461-autotools
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2232,7 +2232,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by libopenmpt $as_me 0.2.8414-autotools, which was
+It was created by libopenmpt $as_me 0.2.8461-autotools, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3103,7 +3103,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='libopenmpt'
- VERSION='0.2.8414-autotools'
+ VERSION='0.2.8461-autotools'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -16645,10 +16645,10 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 $as_echo "#define MPT_SVNURL \"https://source.openmpt.org/svn/openmpt/branches/OpenMPT-1.26\"" >>confdefs.h
 
 
-$as_echo "#define MPT_SVNVERSION \"8414\"" >>confdefs.h
+$as_echo "#define MPT_SVNVERSION \"8461\"" >>confdefs.h
 
 
-$as_echo "#define MPT_SVNDATE \"2017-07-02T15:45:36.459660Z\"" >>confdefs.h
+$as_echo "#define MPT_SVNDATE \"2017-07-07T12:47:24.457926Z\"" >>confdefs.h
 
 
 $as_echo "#define MPT_PACKAGE true" >>confdefs.h
@@ -21303,7 +21303,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by libopenmpt $as_me 0.2.8414-autotools, which was
+This file was extended by libopenmpt $as_me 0.2.8461-autotools, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -21370,7 +21370,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-libopenmpt config.status 0.2.8414-autotools
+libopenmpt config.status 0.2.8461-autotools
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
index 6152691..1575db5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT([libopenmpt], [0.2.8414-autotools], [https://bugs.openmpt.org/], [libopenmpt], [https://lib.openmpt.org/])
+AC_INIT([libopenmpt], [0.2.8461-autotools], [https://bugs.openmpt.org/], [libopenmpt], [https://lib.openmpt.org/])
 AC_PREREQ([2.68])
 
 AC_CONFIG_MACRO_DIR([m4])
@@ -21,8 +21,8 @@ AC_PROG_CXX
 AC_PROG_INSTALL
 
 AC_DEFINE([MPT_SVNURL], ["https://source.openmpt.org/svn/openmpt/branches/OpenMPT-1.26"], [svn version])
-AC_DEFINE([MPT_SVNVERSION], ["8414"], [svn version])
-AC_DEFINE([MPT_SVNDATE], ["2017-07-02T15:45:36.459660Z"], [svn date])
+AC_DEFINE([MPT_SVNVERSION], ["8461"], [svn version])
+AC_DEFINE([MPT_SVNDATE], ["2017-07-07T12:47:24.457926Z"], [svn date])
 AC_DEFINE([MPT_PACKAGE], [true], [is package])
 
 
diff --git a/libopenmpt/dox/changelog.md b/libopenmpt/dox/changelog.md
index f180507..0d2648a 100644
--- a/libopenmpt/dox/changelog.md
+++ b/libopenmpt/dox/changelog.md
@@ -5,6 +5,18 @@ Changelog {#changelog}
 For fully detailed change log, please see the source repository directly. This
 is just a high-level summary.
 
+### libopenmpt 0.2-beta26 (2017-07-07)
+
+ *  [**Bug**] Possible crashes with malformed PLM and PSM files.
+ *  [**Bug**] mktime() and localtime() were used for song date parsing.
+    These functions are not guaranteed to be thread-safe by the standard.
+    Furthermore, some standard library implementations are buggy and may cause
+    the program to abort in out-of-memory situations. These functions are now no
+    longer used.
+
+ *  Loops shorter than four sample points at the end of a sample could cause the
+    sample data before the loop to become corrupted.
+
 ### libopenmpt 0.2-beta25 (2017-07-02)
 
  *  PT36: Enable VBlank timing as specified in file and read song comment.
diff --git a/soundlib/Fastmix.cpp b/soundlib/Fastmix.cpp
index a70395a..cf76493 100644
--- a/soundlib/Fastmix.cpp
+++ b/soundlib/Fastmix.cpp
@@ -187,13 +187,12 @@ static inline void UpdateLookaheadPointers(const int8* &samplePointer, const int
 	// If there is no interpolation happening, there is no lookahead happening the sample read-out is exact.
 	if(chn.dwFlags[CHN_LOOP] && chn.resamplingMode != SRCMODE_NEAREST)
 	{
-		const bool loopEndsAtSampleEnd = chn.pModSample->uFlags[CHN_LOOP] && chn.pModSample->nLoopEnd == chn.pModSample->nLength && chn.pModSample->nLength >= InterpolationMaxLookahead;
 		const bool inSustainLoop = chn.InSustainLoop();
 
 		// Do not enable wraparound magic if we're previewing a custom loop!
 		if(inSustainLoop || chn.nLoopEnd == chn.pModSample->nLoopEnd)
 		{
-			SmpLength lookaheadOffset = (loopEndsAtSampleEnd ? 0 : (3 * InterpolationMaxLookahead)) + chn.pModSample->nLength - chn.nLoopEnd;
+			SmpLength lookaheadOffset = 3 * InterpolationMaxLookahead + chn.pModSample->nLength - chn.nLoopEnd;
 			if(inSustainLoop)
 			{
 				lookaheadOffset += 4 * InterpolationMaxLookahead;
diff --git a/soundlib/Load_plm.cpp b/soundlib/Load_plm.cpp
index 3548108..de1ad65 100644
--- a/soundlib/Load_plm.cpp
+++ b/soundlib/Load_plm.cpp
@@ -372,13 +372,10 @@ bool CSoundFile::ReadPLM(FileReader &file, ModLoadingFlags loadFlags)
 	}
 	// Module ends with the last row of the last order item
 	ROWINDEX endPatSize = maxPos % rowsPerPat;
-	if(endPatSize > 0)
+	ORDERINDEX endOrder = static_cast<ORDERINDEX>(maxPos / rowsPerPat);
+	if(endPatSize > 0 && Order.IsValidPat(endOrder))
 	{
-		PATTERNINDEX endPat = Order[maxPos / rowsPerPat];
-		if(Patterns.IsValidPat(endPat))
-		{
-			Patterns[endPat].Resize(endPatSize, false);
-		}
+		Patterns[Order[endOrder]].Resize(endPatSize, false);
 	}
 	// If there are still any non-existent patterns in our order list, insert some blank patterns.
 	PATTERNINDEX blankPat = PATTERNINDEX_INVALID;
diff --git a/soundlib/Load_psm.cpp b/soundlib/Load_psm.cpp
index df95e52..156a0d9 100644
--- a/soundlib/Load_psm.cpp
+++ b/soundlib/Load_psm.cpp
@@ -1049,6 +1049,7 @@ struct PACKED PSM16SampleHeader
 	// Convert sample header to OpenMPT's internal format
 	void ConvertToMPT(ModSample &mptSmp) const
 	{
+		mptSmp.Initialize();
 		mpt::String::Read<mpt::String::nullTerminated>(mptSmp.filename, filename);
 
 		mptSmp.nLength = length;
@@ -1058,7 +1059,7 @@ struct PACKED PSM16SampleHeader
 		// Why on earth would you want to use both systems at the same time?
 		mptSmp.nC5Speed = Util::Round<uint32>(c2freq * std::pow(2.0, ((finetune ^ 0x08) - 0x78) / (12.0 * 16.0))); // ModSample::TransposeToFrequency(mptSmp.RelativeTone + (finetune >> 4) - 7, MOD2XMFineTune(finetune & 0x0F));
 
-		mptSmp.nVolume = volume << 2;
+		mptSmp.nVolume = std::min<uint8>(volume, 64) * 4;
 
 		mptSmp.uFlags.reset();
 		if(flags & PSM16SampleHeader::smp16Bit)
@@ -1187,15 +1188,16 @@ bool CSoundFile::ReadPSM16(FileReader &file, ModLoadingFlags loadFlags)
 			}
 
 			SAMPLEINDEX smp = sampleHeader.sampleNumber;
-			if(smp < MAX_SAMPLES)
+			if(smp > 0 && smp < MAX_SAMPLES)
 			{
 				m_nSamples = std::max(m_nSamples, smp);
 
-				mpt::String::Read<mpt::String::nullTerminated>(m_szNames[smp], sampleHeader.name);
 				sampleHeader.ConvertToMPT(Samples[smp]);
+				mpt::String::Read<mpt::String::nullTerminated>(m_szNames[smp], sampleHeader.name);
 
-				if((loadFlags & loadSampleData) && file.Seek(sampleHeader.offset))
+				if(loadFlags & loadSampleData)
 				{
+					file.Seek(sampleHeader.offset);
 					sampleHeader.GetSampleFormat().ReadSample(Samples[smp], file);
 				}
 			}
diff --git a/soundlib/Sndfile.cpp b/soundlib/Sndfile.cpp
index 3e83336..3bba6a9 100644
--- a/soundlib/Sndfile.cpp
+++ b/soundlib/Sndfile.cpp
@@ -57,17 +57,10 @@ mpt::ustring FileHistory::AsISO8601() const
 		// Calculate the date when editing finished.
 		double openSeconds = (double)openTime / (double)HISTORY_TIMER_PRECISION;
 		tm tmpLoadDate = loadDate;
-		time_t loadDateSinceEpoch = mpt::Date::Unix::FromUTC(tmpLoadDate);
-		double timeScaleFactor = difftime(2, 1);
-		time_t saveDateSinceEpoch = loadDateSinceEpoch + Util::Round<time_t>(openSeconds / timeScaleFactor);
-		const tm * tmpSaveDate = gmtime(&saveDateSinceEpoch);
-		if(tmpSaveDate)
-		{
-			date = *tmpSaveDate;
-		}
+		int64 loadDateSinceEpoch = mpt::Date::Unix::FromUTC(tmpLoadDate);
+		int64 saveDateSinceEpoch = loadDateSinceEpoch + Util::Round<int64>(openSeconds);
+		date = mpt::Date::Unix(saveDateSinceEpoch).AsUTC();
 	}
-	// We assume date in UTC here.
-	// This is not 100% correct because FileHistory does not contain complete timezone information.
 	return mpt::Date::ToShortenedISO8601(date);
 }
 
diff --git a/soundlib/modsmp_ctrl.cpp b/soundlib/modsmp_ctrl.cpp
index 0fc2108..5df4ac8 100644
--- a/soundlib/modsmp_ctrl.cpp
+++ b/soundlib/modsmp_ctrl.cpp
@@ -265,13 +265,10 @@ void PrecomputeLoopsImpl(ModSample &smp, const CSoundFile &sndFile)
 {
 	const int numChannels = smp.GetNumChannels();
 	const int copySamples = numChannels * InterpolationMaxLookahead;
-	// Optimization: Put normal loop wraparound buffer right at the sample end if the normal loop ends there.
-	// Note that we can't do this for sustain loops, as we would get clicks at the sample end after releasing the loop.
-	const bool loopEndsAtSampleEnd = smp.uFlags[CHN_LOOP] && smp.nLoopEnd == smp.nLength && smp.nLength >= InterpolationMaxLookahead;
 	
 	T *sampleData = static_cast<T *>(smp.pSample);
 	T *afterSampleStart = sampleData + smp.nLength * numChannels;
-	T *loopLookAheadStart = afterSampleStart + (loopEndsAtSampleEnd ? -2 * copySamples : copySamples);
+	T *loopLookAheadStart = afterSampleStart + copySamples;
 	T *sustainLookAheadStart = loopLookAheadStart + 4 * copySamples;
 
 	// Hold sample on the same level as the last sampling point at the end to prevent extra pops with interpolation.
diff --git a/test/test.cpp b/test/test.cpp
index 6794a34..3b253df 100644
--- a/test/test.cpp
+++ b/test/test.cpp
@@ -563,6 +563,49 @@ static MPT_NOINLINE void TestStringFormatting()
 }
 
 
+struct Gregorian {
+	int Y,M,D,h,m,s;
+	Gregorian() {}
+	Gregorian(int Y, int M, int D, int h, int m, int s) : Y(Y), M(M), D(D), h(h), m(m), s(s) {}
+	static Gregorian FromTM(tm t) {
+		Gregorian g;
+		g.Y = t.tm_year + 1900;
+		g.M = t.tm_mon + 1;
+		g.D = t.tm_mday;
+		g.h = t.tm_hour;
+		g.m = t.tm_min;
+		g.s = t.tm_sec;
+		return g;
+	}
+	static tm ToTM(Gregorian g) {
+		tm t;
+		MemsetZero(t);
+		t.tm_year = g.Y - 1900;
+		t.tm_mon = g.M - 1;
+		t.tm_mday = g.D;
+		t.tm_hour = g.h;
+		t.tm_min = g.m;
+		t.tm_sec = g.s;
+		return t;
+	}
+};
+
+bool operator ==(Gregorian a, Gregorian b) {
+	return a.Y == b.Y && a.M == b.M && a.D == b.D && a.h == b.h && a.m == b.m && a.s == b.s;
+}
+
+bool operator !=(Gregorian a, Gregorian b) {
+	return !(a == b);
+}
+
+int64 TestDate1(int s, int m, int h, int D, int M, int Y) {
+	return mpt::Date::Unix::FromUTC(Gregorian::ToTM(Gregorian(Y,M,D,h,m,s)));
+}
+
+Gregorian TestDate2(int s, int m, int h, int D, int M, int Y) {
+	return Gregorian(Y,M,D,h,m,s);
+}
+
 static MPT_NOINLINE void TestMisc()
 //---------------------------------
 {
@@ -929,6 +972,59 @@ static MPT_NOINLINE void TestMisc()
 	for(int32 transpose = -128; transpose < 128; transpose += 32)
 		for(int32 finetune = -128; finetune < 128; finetune += 64, freqIndex++)
 			VERIFY_EQUAL_EPS(transposeToFrequency[freqIndex], static_cast<int32>(ModSample::TransposeToFrequency(transpose, finetune)), 1);
+
+	// date
+
+	VERIFY_EQUAL(             0, TestDate1(  0,  0,  0,  1,  1, 1970 ));
+	VERIFY_EQUAL(          3600, TestDate1(  0,  0,  1,  1,  1, 1970 ));
+	VERIFY_EQUAL(         86400, TestDate1(  0,  0,  0,  2,  1, 1970 ));
+	VERIFY_EQUAL(      31536000, TestDate1(  0,  0,  0,  1,  1, 1971 ));
+	VERIFY_EQUAL(     100000000, TestDate1( 40, 46,  9,  3,  3, 1973 ));
+	VERIFY_EQUAL(     951782400, TestDate1(  0,  0,  0, 29,  2, 2000 ));
+	VERIFY_EQUAL(    1000000000, TestDate1( 40, 46,  1,  9,  9, 2001 ));
+	VERIFY_EQUAL(    1044057600, TestDate1(  0,  0,  0,  1,  2, 2003 ));
+	VERIFY_EQUAL(    1044144000, TestDate1(  0,  0,  0,  2,  2, 2003 ));
+	VERIFY_EQUAL(    1046476800, TestDate1(  0,  0,  0,  1,  3, 2003 ));
+	VERIFY_EQUAL(    1064966400, TestDate1(  0,  0,  0,  1, 10, 2003 ));
+	VERIFY_EQUAL(    1077926399, TestDate1( 59, 59, 23, 27,  2, 2004 ));
+	VERIFY_EQUAL(    1077926400, TestDate1(  0,  0,  0, 28,  2, 2004 ));
+	VERIFY_EQUAL(    1077926410, TestDate1( 10,  0,  0, 28,  2, 2004 ));
+	VERIFY_EQUAL(    1078012799, TestDate1( 59, 59, 23, 28,  2, 2004 ));
+	VERIFY_EQUAL(    1078012800, TestDate1(  0,  0,  0, 29,  2, 2004 ));
+	VERIFY_EQUAL(    1078012820, TestDate1( 20,  0,  0, 29,  2, 2004 ));
+	VERIFY_EQUAL(    1078099199, TestDate1( 59, 59, 23, 29,  2, 2004 ));
+	VERIFY_EQUAL(    1078099200, TestDate1(  0,  0,  0,  1,  3, 2004 ));
+	VERIFY_EQUAL(    1078099230, TestDate1( 30,  0,  0,  1,  3, 2004 ));
+	VERIFY_EQUAL(    1078185599, TestDate1( 59, 59, 23,  1,  3, 2004 ));
+	VERIFY_EQUAL(    1096588800, TestDate1(  0,  0,  0,  1, 10, 2004 ));
+	VERIFY_EQUAL(    1413064016, TestDate1( 56, 46, 21, 11, 10, 2014 ));
+	VERIFY_EQUAL(    1413064100, TestDate1( 20, 48, 21, 11, 10, 2014 ));
+
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(             0).AsUTC()), TestDate2(  0,  0,  0,  1,  1, 1970 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(          3600).AsUTC()), TestDate2(  0,  0,  1,  1,  1, 1970 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(         86400).AsUTC()), TestDate2(  0,  0,  0,  2,  1, 1970 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(      31536000).AsUTC()), TestDate2(  0,  0,  0,  1,  1, 1971 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(     100000000).AsUTC()), TestDate2( 40, 46,  9,  3,  3, 1973 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(     951782400).AsUTC()), TestDate2(  0,  0,  0, 29,  2, 2000 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(    1000000000).AsUTC()), TestDate2( 40, 46,  1,  9,  9, 2001 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(    1044057600).AsUTC()), TestDate2(  0,  0,  0,  1,  2, 2003 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(    1044144000).AsUTC()), TestDate2(  0,  0,  0,  2,  2, 2003 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(    1046476800).AsUTC()), TestDate2(  0,  0,  0,  1,  3, 2003 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(    1064966400).AsUTC()), TestDate2(  0,  0,  0,  1, 10, 2003 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(    1077926399).AsUTC()), TestDate2( 59, 59, 23, 27,  2, 2004 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(    1077926400).AsUTC()), TestDate2(  0,  0,  0, 28,  2, 2004 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(    1077926410).AsUTC()), TestDate2( 10,  0,  0, 28,  2, 2004 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(    1078012799).AsUTC()), TestDate2( 59, 59, 23, 28,  2, 2004 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(    1078012800).AsUTC()), TestDate2(  0,  0,  0, 29,  2, 2004 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(    1078012820).AsUTC()), TestDate2( 20,  0,  0, 29,  2, 2004 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(    1078099199).AsUTC()), TestDate2( 59, 59, 23, 29,  2, 2004 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(    1078099200).AsUTC()), TestDate2(  0,  0,  0,  1,  3, 2004 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(    1078099230).AsUTC()), TestDate2( 30,  0,  0,  1,  3, 2004 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(    1078185599).AsUTC()), TestDate2( 59, 59, 23,  1,  3, 2004 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(    1096588800).AsUTC()), TestDate2(  0,  0,  0,  1, 10, 2004 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(    1413064016).AsUTC()), TestDate2( 56, 46, 21, 11, 10, 2014 ));
+	VERIFY_EQUAL(Gregorian::FromTM(mpt::Date::Unix(    1413064100).AsUTC()), TestDate2( 20, 48, 21, 11, 10, 2014 ));
+
 }
 
 

-- 
libopenmpt packaging



More information about the pkg-multimedia-commits mailing list