diff -Nru makemkv-oss-1.10.7/debian/changelog makemkv-oss-1.10.8/debian/changelog --- makemkv-oss-1.10.7/debian/changelog 2017-09-09 19:39:18.000000000 +0000 +++ makemkv-oss-1.10.8/debian/changelog 2017-11-20 08:16:53.000000000 +0000 @@ -1,4 +1,17 @@ -makemkv-oss (1.10.7-1~trusty) trusty; urgency=low +makemkv-oss (1.10.8-1~trusty) trusty; urgency=medium + + * MakeMKV v1.10.8 (18.11.2017 ) + + Added support for (non-encrypted) UHD discs + Added support for HEVC in MKV files + Improved support for discs with BD-Java protection + Many small miscellaneous improvements + Bug fixes: + Restored compatibility with OS X 10.6 + + -- hjmooses Mon, 20 Nov 2017 09:14:28 +0100 + +makemkv-oss (1.10.7-1~trusty) trusty; urgency=medium * MakeMKV v1.10.7 (4.9.2017 ) diff -Nru makemkv-oss-1.10.7/libabi/inc/lgpl/osslabi.h makemkv-oss-1.10.8/libabi/inc/lgpl/osslabi.h --- makemkv-oss-1.10.7/libabi/inc/lgpl/osslabi.h 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libabi/inc/lgpl/osslabi.h 2017-11-17 12:59:31.000000000 +0000 @@ -48,15 +48,22 @@ unsigned char *ivec); /* SHA */ -typedef struct _OSSL_SHA_CTX OSSL_SHA_CTX; -#define OSSL_SHA_DIGEST_LENGTH 20 +typedef struct _OSSL_SHA_CTX OSSL_SHA_CTX; +typedef struct _OSSL_SHA256_CTX OSSL_SHA256_CTX; +#define OSSL_SHA_DIGEST_LENGTH 20 +#define OSSL_SHA256_DIGEST_LENGTH 32 unsigned int OSSL_sizeof_SHA_CTX(); +unsigned int OSSL_sizeof_SHA256_CTX(); int OSSL_SHA1_Init(OSSL_SHA_CTX *c); int OSSL_SHA1_Update(OSSL_SHA_CTX *c, const void *data, size_t len); int OSSL_SHA1_Final(unsigned char *md, OSSL_SHA_CTX *c); +int OSSL_SHA256_Init(OSSL_SHA256_CTX *c); +int OSSL_SHA256_Update(OSSL_SHA256_CTX *c, const void *data, size_t len); +int OSSL_SHA256_Final(unsigned char *md, OSSL_SHA256_CTX *c); + /* BN */ typedef struct _OSSL_BIGNUM OSSL_BIGNUM; typedef struct _OSSL_BN_CTX OSSL_BN_CTX; diff -Nru makemkv-oss-1.10.7/libabi/src/ossl_sha.c makemkv-oss-1.10.8/libabi/src/ossl_sha.c --- makemkv-oss-1.10.7/libabi/src/ossl_sha.c 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libabi/src/ossl_sha.c 2017-11-17 12:59:31.000000000 +0000 @@ -43,3 +43,23 @@ return SHA1_Final(md,(SHA_CTX*)c); } +unsigned int OSSL_sizeof_SHA256_CTX() +{ + return (((sizeof(SHA256_CTX) + (sizeof(void*) - 1)) / sizeof(void*))*sizeof(void*)); +} + +int OSSL_SHA256_Init(OSSL_SHA256_CTX *c) +{ + return SHA256_Init((SHA256_CTX*)c); +} + +int OSSL_SHA256_Update(OSSL_SHA256_CTX *c, const void *data, size_t len) +{ + return SHA256_Update((SHA256_CTX*)c, data, len); +} + +int OSSL_SHA256_Final(unsigned char *md, OSSL_SHA256_CTX *c) +{ + return SHA256_Final(md, (SHA256_CTX*)c); +} + diff -Nru makemkv-oss-1.10.7/libdriveio/src/stdquery.cpp makemkv-oss-1.10.8/libdriveio/src/stdquery.cpp --- makemkv-oss-1.10.7/libdriveio/src/stdquery.cpp 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libdriveio/src/stdquery.cpp 2017-11-17 12:59:31.000000000 +0000 @@ -197,6 +197,7 @@ if (0==memcmp(ptr+8,"BDO",3)) struct_size=64; if (0==memcmp(ptr+8,"BDW",3)) struct_size=112; if (0==memcmp(ptr+8,"BDR",3)) struct_size=112; + if (0==memcmp(ptr+8,"BDU",3)) struct_size=64; if (0==struct_size) break; if (struct_size>rest) { diff -Nru makemkv-oss-1.10.7/libebml/inc/ebml/c/libebml_t.h makemkv-oss-1.10.8/libebml/inc/ebml/c/libebml_t.h --- makemkv-oss-1.10.7/libebml/inc/ebml/c/libebml_t.h 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libebml/inc/ebml/c/libebml_t.h 2017-11-17 12:59:31.000000000 +0000 @@ -108,10 +108,10 @@ typedef int16_t int16; typedef int8_t int8; typedef int8_t character; - typedef u_int64_t uint64; - typedef u_int32_t uint32; - typedef u_int16_t uint16; - typedef u_int8_t uint8; + typedef uint64_t uint64; + typedef uint32_t uint32; + typedef uint16_t uint16; + typedef uint8_t uint8; #endif /* anything else */ typedef uint8 binary; diff -Nru makemkv-oss-1.10.7/libebml/inc/ebml/EbmlConfig.h makemkv-oss-1.10.8/libebml/inc/ebml/EbmlConfig.h --- makemkv-oss-1.10.7/libebml/inc/ebml/EbmlConfig.h 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libebml/inc/ebml/EbmlConfig.h 2017-11-17 12:59:31.000000000 +0000 @@ -111,11 +111,6 @@ # endif #endif -// For compilers that don't define __TIMESTAMP__ (e.g. gcc 2.95, gcc 3.2) -#ifndef __TIMESTAMP__ -#define __TIMESTAMP__ __DATE__ " " __TIME__ -#endif - #ifdef __GNUC__ #define EBML_PRETTYLONGINT(c) (c ## ll) #else // __GNUC__ diff -Nru makemkv-oss-1.10.7/libebml/inc/ebml/EbmlMaster.h makemkv-oss-1.10.8/libebml/inc/ebml/EbmlMaster.h --- makemkv-oss-1.10.7/libebml/inc/ebml/EbmlMaster.h 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libebml/inc/ebml/EbmlMaster.h 2017-11-17 12:59:31.000000000 +0000 @@ -165,7 +165,6 @@ /*! \brief facility for Master elements to write only the head and force the size later - \warning */ filepos_t WriteHead(IOCallback & output, int SizeLength, bool bWithDefault = false); @@ -224,6 +223,12 @@ } template +Type * FindNextChild(EbmlMaster & Master, const Type & PastElt) +{ + return static_cast(Master.FindNextElt(PastElt, false)); +} + +template Type & AddNewChild(EbmlMaster & Master) { return *(static_cast(Master.AddNewElt(EBML_INFO(Type)))); diff -Nru makemkv-oss-1.10.7/libebml/inc/ebml/EbmlVersion.h makemkv-oss-1.10.8/libebml/inc/ebml/EbmlVersion.h --- makemkv-oss-1.10.7/libebml/inc/ebml/EbmlVersion.h 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libebml/inc/ebml/EbmlVersion.h 2017-11-17 12:59:31.000000000 +0000 @@ -42,7 +42,7 @@ START_LIBEBML_NAMESPACE -#define LIBEBML_VERSION 0x010303 +#define LIBEBML_VERSION 0x010305 extern const ccc::string EbmlCodeVersion; extern const ccc::string EbmlCodeDate; diff -Nru makemkv-oss-1.10.7/libebml/inc/ebml/MemReadIOCallback.h makemkv-oss-1.10.8/libebml/inc/ebml/MemReadIOCallback.h --- makemkv-oss-1.10.7/libebml/inc/ebml/MemReadIOCallback.h 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libebml/inc/ebml/MemReadIOCallback.h 2017-11-17 12:59:31.000000000 +0000 @@ -17,7 +17,7 @@ ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ** ** See http://www.matroska.org/license/lgpl/ for LGPL licensing information. ** diff -Nru makemkv-oss-1.10.7/libebml/inc/ebml/SafeReadIOCallback.h makemkv-oss-1.10.8/libebml/inc/ebml/SafeReadIOCallback.h --- makemkv-oss-1.10.7/libebml/inc/ebml/SafeReadIOCallback.h 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libebml/inc/ebml/SafeReadIOCallback.h 2017-11-17 12:59:31.000000000 +0000 @@ -19,7 +19,7 @@ ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ** ** See http://www.matroska.org/license/lgpl/ for LGPL licensing information. ** diff -Nru makemkv-oss-1.10.7/libebml/src/Debug.cpp makemkv-oss-1.10.8/libebml/src/Debug.cpp --- makemkv-oss-1.10.7/libebml/src/Debug.cpp 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libebml/src/Debug.cpp 2017-11-17 12:59:31.000000000 +0000 @@ -36,7 +36,7 @@ */ #include -#ifdef WIN32 +#if defined(WIN32) || defined(_WIN32) #include // For OutputDebugString #else #include @@ -79,7 +79,7 @@ char tst[1000]; char myformat[256]; -#ifdef WIN32 +#if defined(WIN32) || defined(_WIN32) if (my_time_included) { SYSTEMTIME time; GetSystemTime(&time); @@ -193,7 +193,7 @@ result = false; -#ifdef WIN32 +#if defined(WIN32) || defined(_WIN32) hFile = CreateFileA(NewFilename, GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (hFile != INVALID_HANDLE_VALUE) { @@ -222,7 +222,7 @@ if (result) return true; -#ifdef WIN32 +#if defined(WIN32) || defined(_WIN32) result = (CloseHandle(hFile) != 0); #else result = (fclose(hFile) == 0); diff -Nru makemkv-oss-1.10.7/libebml/src/EbmlElement.cpp makemkv-oss-1.10.8/libebml/src/EbmlElement.cpp --- makemkv-oss-1.10.7/libebml/src/EbmlElement.cpp 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libebml/src/EbmlElement.cpp 2017-11-17 12:59:31.000000000 +0000 @@ -32,6 +32,7 @@ \author Steve Lhomme */ +#include #include #include @@ -221,8 +222,10 @@ assert(i= %u)", (unsigned int)i, (unsigned int)Size); + throw mkv_logic_error(ss); } @@ -268,12 +271,12 @@ int PossibleID_Length = 0; binary PossibleSize[8]; // we don't support size stored in more than 64 bits uint32 PossibleSizeLength = 0; - uint64 SizeUnknown; - uint64 SizeFound; + uint64 SizeUnknown = 0; + uint64 SizeFound = 0; bool bElementFound = false; binary BitMask; - uint64 aElementPosition, aSizePosition; + uint64 aElementPosition = 0, aSizePosition = 0; while (!bElementFound) { // read ID aElementPosition = DataStream.getFilePointer(); @@ -406,6 +409,10 @@ } while (!bFound && MaxDataSize > ReadSize); + if (!bFound) + // we reached the maximum we could read without a proper ID + return NULL; + SizeIdx = ReadIndex; ReadIndex -= PossibleID_Length; diff -Nru makemkv-oss-1.10.7/libebml/src/EbmlMaster.cpp makemkv-oss-1.10.8/libebml/src/EbmlMaster.cpp --- makemkv-oss-1.10.7/libebml/src/EbmlMaster.cpp 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libebml/src/EbmlMaster.cpp 2017-11-17 12:59:31.000000000 +0000 @@ -206,11 +206,16 @@ for (EltIdx = 0; EltIdx < EBML_CTX_SIZE(Context); EltIdx++) { if (EBML_CTX_IDX(Context,EltIdx).IsMandatory()) { if (FindElt(EBML_CTX_IDX_INFO(Context,EltIdx)) == NULL) { + EbmlElement *testElement = &EBML_CTX_IDX(Context,EltIdx).Create(); + bool hasDefaultValue = testElement->DefaultISset(); + delete testElement; + #if defined(LIBEBML_DEBUG) // you are missing this Mandatory element // const char * MissingName = EBML_INFO_NAME(EBML_CTX_IDX_INFO(Context,EltIdx)); #endif // LIBEBML_DEBUG - return false; + if (!hasDefaultValue) + return false; } } } diff -Nru makemkv-oss-1.10.7/libebml/src/EbmlVersion.cpp makemkv-oss-1.10.8/libebml/src/EbmlVersion.cpp --- makemkv-oss-1.10.7/libebml/src/EbmlVersion.cpp 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libebml/src/EbmlVersion.cpp 2017-11-17 12:59:31.000000000 +0000 @@ -38,6 +38,11 @@ START_LIBEBML_NAMESPACE -const ccc::string EbmlCodeVersion = "1.3.3"; +const ccc::string EbmlCodeVersion = "1.3.5"; + +// Up to version 1.3.3 this library exported a build date string. As +// this made the build non-reproducible, replace it by a placeholder to +// remain API compatible. +const ccc::string EbmlCodeDate = "Unknown"; END_LIBEBML_NAMESPACE diff -Nru makemkv-oss-1.10.7/libebml/src/StdIOCallback.cpp makemkv-oss-1.10.8/libebml/src/StdIOCallback.cpp --- makemkv-oss-1.10.7/libebml/src/StdIOCallback.cpp 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libebml/src/StdIOCallback.cpp 2017-11-17 12:59:31.000000000 +0000 @@ -131,8 +131,9 @@ ostringstream Msg; Msg<<"Failed to seek file "< +#include -class mkv_error_exception : public std::exception +class mkv_error_exception_unbuffered : public std::exception { const char* m_message; public: - mkv_error_exception(const char* Message) - : m_message(Message) + mkv_error_exception_unbuffered(const char* Message) throw() + : m_message(Message) + { + } + ~mkv_error_exception_unbuffered() throw() { } const char* what() const throw() @@ -37,6 +41,31 @@ } }; +class mkv_error_exception_buffered : public std::exception +{ + buf::string m_message; +public: + mkv_error_exception_buffered(const char* Message) throw() + : m_message(Message) + { + } + mkv_error_exception_buffered(const StringPointer& Message) throw() + : m_message(Message) + { + } + ~mkv_error_exception_buffered() throw() + { + } + const char* what() const throw() + { + return m_message.c_str(); + } +}; + +typedef mkv_error_exception_buffered mkv_logic_error; + +#define mkv_error_exception(x) mkv_error_exception_unbuffered(x "\0") + int MkvAssertHelper(const char* Message); #define MKV_ASSERT(_Expression_) \ diff -Nru makemkv-oss-1.10.7/libmakemkv/inc/lgpl/stdstring.h makemkv-oss-1.10.8/libmakemkv/inc/lgpl/stdstring.h --- makemkv-oss-1.10.7/libmakemkv/inc/lgpl/stdstring.h 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libmakemkv/inc/lgpl/stdstring.h 2017-11-17 12:59:31.000000000 +0000 @@ -72,6 +72,7 @@ const ref::string* pr = static_cast(p); return *pr; } + void format(size_t maxSize,const char* fmt, ...); }; }; diff -Nru makemkv-oss-1.10.7/libmakemkv/src/libmkv.cpp makemkv-oss-1.10.8/libmakemkv/src/libmkv.cpp --- makemkv-oss-1.10.7/libmakemkv/src/libmkv.cpp 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libmakemkv/src/libmkv.cpp 2017-11-17 12:59:31.000000000 +0000 @@ -38,7 +38,7 @@ #define AUTO_DURATION_TIMECODE 4500000000ll #define BAD_TIMECODE ((1ll<<62)+1) -#define CNZ(x) if (!(x)) { throw mkv_error_exception( "Error in " #x ); }; +#define CNZ(x) if (!(x)) { throw mkv_error_exception_unbuffered( "Error in " #x ); }; template static inline Tv& GetChild(EbmlMaster *node) diff -Nru makemkv-oss-1.10.7/libmakemkv/src/stdstring.cpp makemkv-oss-1.10.8/libmakemkv/src/stdstring.cpp --- makemkv-oss-1.10.7/libmakemkv/src/stdstring.cpp 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libmakemkv/src/stdstring.cpp 2017-11-17 12:59:31.000000000 +0000 @@ -20,6 +20,13 @@ */ #include #include +#include +#include +#include + +#ifdef _WIN32 +#define vsnprintf _vsnprintf +#endif const char* buf::string::emptyString = ""; @@ -39,8 +46,23 @@ } } +void buf::string::format(size_t maxSize, const char* fmt, ...) +{ + va_list lst; + char* tmp = (char*)alloca(maxSize + 1); + + va_start(lst,fmt); + vsnprintf(tmp, maxSize, fmt, lst); + va_end(lst); + + tmp[maxSize] = 0; + + assign(tmp); +} + int MkvAssertHelper(const char* Message) { - throw mkv_error_exception(Message); + throw mkv_error_exception_unbuffered(Message); return 0; } + diff -Nru makemkv-oss-1.10.7/libmatroska/inc/matroska/KaxCluster.h makemkv-oss-1.10.8/libmatroska/inc/matroska/KaxCluster.h --- makemkv-oss-1.10.7/libmatroska/inc/matroska/KaxCluster.h 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libmatroska/inc/matroska/KaxCluster.h 2017-11-17 12:59:31.000000000 +0000 @@ -53,19 +53,19 @@ /*! \brief Addition of a frame without references - \param the timecode is expressed in nanoseconds, relative to the beggining of the Segment + \param timecode the timecode is expressed in nanoseconds, relative to the beggining of the Segment */ bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, KaxBlockGroup * & MyNewBlock, LacingType lacing = LACING_AUTO); /*! \brief Addition of a frame with a backward reference (P frame) - \param the timecode is expressed in nanoseconds, relative to the beggining of the Segment + \param timecode the timecode is expressed in nanoseconds, relative to the beggining of the Segment */ bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, KaxBlockGroup * & MyNewBlock, const KaxBlockGroup & PastBlock, LacingType lacing = LACING_AUTO); /*! \brief Addition of a frame with a backward+forward reference (B frame) - \param the timecode is expressed in nanoseconds, relative to the beggining of the Segment + \param timecode the timecode is expressed in nanoseconds, relative to the beggining of the Segment */ bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, KaxBlockGroup * & MyNewBlock, const KaxBlockGroup & PastBlock, const KaxBlockGroup & ForwBlock, LacingType lacing = LACING_AUTO); diff -Nru makemkv-oss-1.10.7/libmatroska/inc/matroska/KaxSemantic.h makemkv-oss-1.10.8/libmatroska/inc/matroska/KaxSemantic.h --- makemkv-oss-1.10.7/libmatroska/inc/matroska/KaxSemantic.h 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libmatroska/inc/matroska/KaxSemantic.h 2017-11-17 12:59:31.000000000 +0000 @@ -1,9 +1,10 @@ /********************************************************************** ** DO NOT EDIT, GENERATED WITH DATA2LIB +** https://github.com/Matroska-Org/foundation-source/tree/master/spectool ** ** libmatroska : parse Matroska files, see http://www.matroska.org/ ** -** Copyright (c) 2002-2010, Matroska (non-profit organisation) +** Copyright (c) 2002-2017, Matroska (non-profit organisation) ** All rights reserved. ** ** This file is part of libmatroska. @@ -208,6 +209,7 @@ public: filepos_t RenderData(IOCallback & output, bool bForceRender, bool bSaveDefault); }; + #endif DECLARE_MKX_MASTER(KaxTracks) @@ -272,6 +274,11 @@ DECLARE_MKX_STRING(KaxTrackLanguage) }; +#if MATROSKA_VERSION >= 2 +DECLARE_MKX_STRING(KaxLanguageIETF) +}; +#endif + DECLARE_MKX_STRING(KaxCodecID) }; @@ -336,6 +343,9 @@ DECLARE_MKX_UINTEGER(KaxVideoFlagInterlaced) }; +DECLARE_MKX_UINTEGER(KaxVideoFieldOrder) +}; + DECLARE_MKX_UINTEGER(KaxVideoStereoMode) }; @@ -393,6 +403,103 @@ public: filepos_t RenderData(IOCallback & output, bool bForceRender, bool bSaveDefault); }; + +DECLARE_MKX_MASTER(KaxVideoColour) +}; + + +DECLARE_MKX_UINTEGER(KaxVideoColourMatrix) +}; + +DECLARE_MKX_UINTEGER(KaxVideoBitsPerChannel) +}; + +DECLARE_MKX_UINTEGER(KaxVideoChromaSubsampHorz) +}; + +DECLARE_MKX_UINTEGER(KaxVideoChromaSubsampVert) +}; + +DECLARE_MKX_UINTEGER(KaxVideoCbSubsampHorz) +}; + +DECLARE_MKX_UINTEGER(KaxVideoCbSubsampVert) +}; + +DECLARE_MKX_UINTEGER(KaxVideoChromaSitHorz) +}; + +DECLARE_MKX_UINTEGER(KaxVideoChromaSitVert) +}; + +DECLARE_MKX_UINTEGER(KaxVideoColourRange) +}; + +DECLARE_MKX_UINTEGER(KaxVideoColourTransferCharacter) +}; + +DECLARE_MKX_UINTEGER(KaxVideoColourPrimaries) +}; + +DECLARE_MKX_UINTEGER(KaxVideoColourMaxCLL) +}; + +DECLARE_MKX_UINTEGER(KaxVideoColourMaxFALL) +}; + +DECLARE_MKX_MASTER(KaxVideoColourMasterMeta) +}; + + +DECLARE_MKX_FLOAT(KaxVideoRChromaX) +}; + +DECLARE_MKX_FLOAT(KaxVideoRChromaY) +}; + +DECLARE_MKX_FLOAT(KaxVideoGChromaX) +}; + +DECLARE_MKX_FLOAT(KaxVideoGChromaY) +}; + +DECLARE_MKX_FLOAT(KaxVideoBChromaX) +}; + +DECLARE_MKX_FLOAT(KaxVideoBChromaY) +}; + +DECLARE_MKX_FLOAT(KaxVideoWhitePointChromaX) +}; + +DECLARE_MKX_FLOAT(KaxVideoWhitePointChromaY) +}; + +DECLARE_MKX_FLOAT(KaxVideoLuminanceMax) +}; + +DECLARE_MKX_FLOAT(KaxVideoLuminanceMin) +}; + +DECLARE_MKX_MASTER(KaxVideoProjection) +}; + + +DECLARE_MKX_UINTEGER(KaxVideoProjectionType) +}; + +DECLARE_MKX_BINARY (KaxVideoProjectionPrivate) +}; + +DECLARE_MKX_FLOAT(KaxVideoProjectionPoseYaw) +}; + +DECLARE_MKX_FLOAT(KaxVideoProjectionPosePitch) +}; + +DECLARE_MKX_FLOAT(KaxVideoProjectionPoseRoll) +}; + #endif DECLARE_MKX_MASTER(KaxTrackAudio) @@ -554,6 +661,7 @@ public: filepos_t RenderData(IOCallback & output, bool bForceRender, bool bSaveDefault); }; + #endif DECLARE_MKX_MASTER(KaxAttachments) @@ -590,6 +698,7 @@ DECLARE_MKX_UINTEGER(KaxFileUsedEndTime) }; + #endif DECLARE_MKX_MASTER(KaxChapters) @@ -664,6 +773,11 @@ DECLARE_MKX_STRING(KaxChapterLanguage) }; +#if MATROSKA_VERSION >= 2 +DECLARE_MKX_STRING(KaxChapLanguageIETF) +}; +#endif + DECLARE_MKX_STRING(KaxChapterCountry) }; @@ -727,6 +841,11 @@ DECLARE_MKX_STRING(KaxTagLangue) }; +#if MATROSKA_VERSION >= 2 +DECLARE_MKX_STRING(KaxTagLanguageIETF) +}; +#endif + DECLARE_MKX_UINTEGER(KaxTagDefault) }; diff -Nru makemkv-oss-1.10.7/libmatroska/inc/matroska/KaxVersion.h makemkv-oss-1.10.8/libmatroska/inc/matroska/KaxVersion.h --- makemkv-oss-1.10.7/libmatroska/inc/matroska/KaxVersion.h 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libmatroska/inc/matroska/KaxVersion.h 2017-11-17 12:59:31.000000000 +0000 @@ -40,7 +40,7 @@ START_LIBMATROSKA_NAMESPACE -#define LIBMATROSKA_VERSION 0x010404 +#define LIBMATROSKA_VERSION 0x010407 extern const ccc::string KaxCodeVersion; extern const ccc::string KaxCodeDate; diff -Nru makemkv-oss-1.10.7/libmatroska/src/KaxSemantic.cpp makemkv-oss-1.10.8/libmatroska/src/KaxSemantic.cpp --- makemkv-oss-1.10.7/libmatroska/src/KaxSemantic.cpp 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libmatroska/src/KaxSemantic.cpp 2017-11-17 12:59:31.000000000 +0000 @@ -1,9 +1,10 @@ /********************************************************************** ** DO NOT EDIT, GENERATED WITH DATA2LIB +** https://github.com/Matroska-Org/foundation-source/tree/master/spectool ** ** libmatroska : parse Matroska files, see http://www.matroska.org/ ** -** Copyright (c) 2002-2010, Matroska (non-profit organisation) +** Copyright (c) 2002-2017, Matroska (non-profit organisation) ** All rights reserved. ** ** This file is part of libmatroska. @@ -254,6 +255,9 @@ DEFINE_SEMANTIC_ITEM(true, true, KaxMaxBlockAdditionID) DEFINE_SEMANTIC_ITEM(false, true, KaxTrackName) DEFINE_SEMANTIC_ITEM(false, true, KaxTrackLanguage) +#if MATROSKA_VERSION >= 2 +DEFINE_SEMANTIC_ITEM(false, true, KaxLanguageIETF) +#endif // MATROSKA_VERSION DEFINE_SEMANTIC_ITEM(true, true, KaxCodecID) DEFINE_SEMANTIC_ITEM(false, true, KaxCodecPrivate) DEFINE_SEMANTIC_ITEM(false, true, KaxCodecName) @@ -306,6 +310,9 @@ DEFINE_MKX_UINTEGER_DEF(KaxMaxBlockAdditionID, 0x55EE, 2, KaxTrackEntry, "MaxBlockAdditionID", 0); DEFINE_MKX_UNISTRING(KaxTrackName, 0x536E, 2, KaxTrackEntry, "TrackName"); DEFINE_MKX_STRING_DEF(KaxTrackLanguage, 0x22B59C, 3, KaxTrackEntry, "TrackLanguage", "eng"); +#if MATROSKA_VERSION >= 2 +DEFINE_MKX_STRING(KaxLanguageIETF, 0x22B59D, 3, KaxTrackEntry, "LanguageIETF"); +#endif DEFINE_MKX_STRING(KaxCodecID, 0x86, 1, KaxTrackEntry, "CodecID"); DEFINE_MKX_BINARY (KaxCodecPrivate, 0x63A2, 2, KaxTrackEntry, "CodecPrivate"); DEFINE_MKX_UNISTRING(KaxCodecName, 0x258688, 3, KaxTrackEntry, "CodecName"); @@ -336,6 +343,7 @@ DEFINE_START_SEMANTIC(KaxTrackVideo) #if MATROSKA_VERSION >= 2 DEFINE_SEMANTIC_ITEM(true, true, KaxVideoFlagInterlaced) +DEFINE_SEMANTIC_ITEM(true, true, KaxVideoFieldOrder) DEFINE_SEMANTIC_ITEM(false, true, KaxVideoStereoMode) DEFINE_SEMANTIC_ITEM(false, true, KaxVideoAlphaMode) DEFINE_SEMANTIC_ITEM(false, true, KaxOldStereoMode) // not supported @@ -354,12 +362,15 @@ #if MATROSKA_VERSION >= 2 DEFINE_SEMANTIC_ITEM(false, true, KaxVideoGamma) // not supported DEFINE_SEMANTIC_ITEM(false, true, KaxVideoFrameRate) // not supported +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoColour) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoProjection) #endif // MATROSKA_VERSION DEFINE_END_SEMANTIC(KaxTrackVideo) DEFINE_MKX_MASTER(KaxTrackVideo, 0xE0, 1, KaxTrackEntry, "TrackVideo"); #if MATROSKA_VERSION >= 2 DEFINE_MKX_UINTEGER_DEF(KaxVideoFlagInterlaced, 0x9A, 1, KaxTrackVideo, "VideoFlagInterlaced", 0); +DEFINE_MKX_UINTEGER_DEF(KaxVideoFieldOrder, 0x9D, 1, KaxTrackVideo, "VideoFieldOrder", 2); DEFINE_MKX_UINTEGER_DEF(KaxVideoStereoMode, 0x53B8, 2, KaxTrackVideo, "VideoStereoMode", 0); DEFINE_MKX_UINTEGER_DEF(KaxVideoAlphaMode, 0x53C0, 2, KaxTrackVideo, "VideoAlphaMode", 0); DEFINE_MKX_UINTEGER(KaxOldStereoMode, 0x53B9, 2, KaxTrackVideo, "OldStereoMode"); @@ -378,6 +389,78 @@ #if MATROSKA_VERSION >= 2 DEFINE_MKX_FLOAT(KaxVideoGamma, 0x2FB523, 3, KaxTrackVideo, "VideoGamma"); DEFINE_MKX_FLOAT(KaxVideoFrameRate, 0x2383E3, 3, KaxTrackVideo, "VideoFrameRate"); + +DEFINE_START_SEMANTIC(KaxVideoColour) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoColourMatrix) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoBitsPerChannel) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoChromaSubsampHorz) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoChromaSubsampVert) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoCbSubsampHorz) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoCbSubsampVert) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoChromaSitHorz) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoChromaSitVert) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoColourRange) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoColourTransferCharacter) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoColourPrimaries) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoColourMaxCLL) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoColourMaxFALL) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoColourMasterMeta) +DEFINE_END_SEMANTIC(KaxVideoColour) + +DEFINE_MKX_MASTER(KaxVideoColour, 0x55B0, 2, KaxTrackVideo, "VideoColour"); +DEFINE_MKX_UINTEGER_DEF(KaxVideoColourMatrix, 0x55B1, 2, KaxVideoColour, "VideoColourMatrix", 2); +DEFINE_MKX_UINTEGER_DEF(KaxVideoBitsPerChannel, 0x55B2, 2, KaxVideoColour, "VideoBitsPerChannel", 0); +DEFINE_MKX_UINTEGER(KaxVideoChromaSubsampHorz, 0x55B3, 2, KaxVideoColour, "VideoChromaSubsampHorz"); +DEFINE_MKX_UINTEGER(KaxVideoChromaSubsampVert, 0x55B4, 2, KaxVideoColour, "VideoChromaSubsampVert"); +DEFINE_MKX_UINTEGER(KaxVideoCbSubsampHorz, 0x55B5, 2, KaxVideoColour, "VideoCbSubsampHorz"); +DEFINE_MKX_UINTEGER(KaxVideoCbSubsampVert, 0x55B6, 2, KaxVideoColour, "VideoCbSubsampVert"); +DEFINE_MKX_UINTEGER_DEF(KaxVideoChromaSitHorz, 0x55B7, 2, KaxVideoColour, "VideoChromaSitHorz", 0); +DEFINE_MKX_UINTEGER_DEF(KaxVideoChromaSitVert, 0x55B8, 2, KaxVideoColour, "VideoChromaSitVert", 0); +DEFINE_MKX_UINTEGER_DEF(KaxVideoColourRange, 0x55B9, 2, KaxVideoColour, "VideoColourRange", 0); +DEFINE_MKX_UINTEGER_DEF(KaxVideoColourTransferCharacter, 0x55BA, 2, KaxVideoColour, "VideoColourTransferCharacter", 2); +DEFINE_MKX_UINTEGER_DEF(KaxVideoColourPrimaries, 0x55BB, 2, KaxVideoColour, "VideoColourPrimaries", 2); +DEFINE_MKX_UINTEGER(KaxVideoColourMaxCLL, 0x55BC, 2, KaxVideoColour, "VideoColourMaxCLL"); +DEFINE_MKX_UINTEGER(KaxVideoColourMaxFALL, 0x55BD, 2, KaxVideoColour, "VideoColourMaxFALL"); + +DEFINE_START_SEMANTIC(KaxVideoColourMasterMeta) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoRChromaX) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoRChromaY) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoGChromaX) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoGChromaY) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoBChromaX) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoBChromaY) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoWhitePointChromaX) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoWhitePointChromaY) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoLuminanceMax) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoLuminanceMin) +DEFINE_END_SEMANTIC(KaxVideoColourMasterMeta) + +DEFINE_MKX_MASTER(KaxVideoColourMasterMeta, 0x55D0, 2, KaxVideoColour, "VideoColourMasterMeta"); +DEFINE_MKX_FLOAT(KaxVideoRChromaX, 0x55D1, 2, KaxVideoColourMasterMeta, "VideoRChromaX"); +DEFINE_MKX_FLOAT(KaxVideoRChromaY, 0x55D2, 2, KaxVideoColourMasterMeta, "VideoRChromaY"); +DEFINE_MKX_FLOAT(KaxVideoGChromaX, 0x55D3, 2, KaxVideoColourMasterMeta, "VideoGChromaX"); +DEFINE_MKX_FLOAT(KaxVideoGChromaY, 0x55D4, 2, KaxVideoColourMasterMeta, "VideoGChromaY"); +DEFINE_MKX_FLOAT(KaxVideoBChromaX, 0x55D5, 2, KaxVideoColourMasterMeta, "VideoBChromaX"); +DEFINE_MKX_FLOAT(KaxVideoBChromaY, 0x55D6, 2, KaxVideoColourMasterMeta, "VideoBChromaY"); +DEFINE_MKX_FLOAT(KaxVideoWhitePointChromaX, 0x55D7, 2, KaxVideoColourMasterMeta, "VideoWhitePointChromaX"); +DEFINE_MKX_FLOAT(KaxVideoWhitePointChromaY, 0x55D8, 2, KaxVideoColourMasterMeta, "VideoWhitePointChromaY"); +DEFINE_MKX_FLOAT(KaxVideoLuminanceMax, 0x55D9, 2, KaxVideoColourMasterMeta, "VideoLuminanceMax"); +DEFINE_MKX_FLOAT(KaxVideoLuminanceMin, 0x55DA, 2, KaxVideoColourMasterMeta, "VideoLuminanceMin"); + +DEFINE_START_SEMANTIC(KaxVideoProjection) +DEFINE_SEMANTIC_ITEM(true, true, KaxVideoProjectionType) +DEFINE_SEMANTIC_ITEM(false, true, KaxVideoProjectionPrivate) +DEFINE_SEMANTIC_ITEM(true, true, KaxVideoProjectionPoseYaw) +DEFINE_SEMANTIC_ITEM(true, true, KaxVideoProjectionPosePitch) +DEFINE_SEMANTIC_ITEM(true, true, KaxVideoProjectionPoseRoll) +DEFINE_END_SEMANTIC(KaxVideoProjection) + +DEFINE_MKX_MASTER(KaxVideoProjection, 0x7670, 2, KaxTrackVideo, "VideoProjection"); +DEFINE_MKX_UINTEGER_DEF(KaxVideoProjectionType, 0x7671, 2, KaxVideoProjection, "VideoProjectionType", 0); +DEFINE_MKX_BINARY (KaxVideoProjectionPrivate, 0x7672, 2, KaxVideoProjection, "VideoProjectionPrivate"); +DEFINE_MKX_FLOAT_DEF(KaxVideoProjectionPoseYaw, 0x7673, 2, KaxVideoProjection, "VideoProjectionPoseYaw", 0); +DEFINE_MKX_FLOAT_DEF(KaxVideoProjectionPosePitch, 0x7674, 2, KaxVideoProjection, "VideoProjectionPosePitch", 0); +DEFINE_MKX_FLOAT_DEF(KaxVideoProjectionPoseRoll, 0x7675, 2, KaxVideoProjection, "VideoProjectionPoseRoll", 0); #endif DEFINE_START_SEMANTIC(KaxTrackAudio) @@ -625,12 +708,18 @@ DEFINE_START_SEMANTIC(KaxChapterDisplay) DEFINE_SEMANTIC_ITEM(true, true, KaxChapterString) DEFINE_SEMANTIC_ITEM(true, false, KaxChapterLanguage) +#if MATROSKA_VERSION >= 2 +DEFINE_SEMANTIC_ITEM(false, true, KaxChapLanguageIETF) +#endif // MATROSKA_VERSION DEFINE_SEMANTIC_ITEM(false, false, KaxChapterCountry) DEFINE_END_SEMANTIC(KaxChapterDisplay) DEFINE_MKX_MASTER(KaxChapterDisplay, 0x80, 1, KaxChapterAtom, "ChapterDisplay"); DEFINE_MKX_UNISTRING(KaxChapterString, 0x85, 1, KaxChapterDisplay, "ChapterString"); DEFINE_MKX_STRING_DEF(KaxChapterLanguage, 0x437C, 2, KaxChapterDisplay, "ChapterLanguage", "eng"); +#if MATROSKA_VERSION >= 2 +DEFINE_MKX_STRING(KaxChapLanguageIETF, 0x437D, 2, KaxChapterDisplay, "ChapLanguageIETF"); +#endif DEFINE_MKX_STRING(KaxChapterCountry, 0x437E, 2, KaxChapterDisplay, "ChapterCountry"); DEFINE_START_SEMANTIC(KaxChapterProcess) @@ -686,6 +775,9 @@ DEFINE_SEMANTIC_ITEM(false, false, KaxTagSimple) // recursive DEFINE_SEMANTIC_ITEM(true, true, KaxTagName) DEFINE_SEMANTIC_ITEM(true, true, KaxTagLangue) +#if MATROSKA_VERSION >= 2 +DEFINE_SEMANTIC_ITEM(false, true, KaxTagLanguageIETF) +#endif // MATROSKA_VERSION DEFINE_SEMANTIC_ITEM(true, true, KaxTagDefault) DEFINE_SEMANTIC_ITEM(false, true, KaxTagString) DEFINE_SEMANTIC_ITEM(false, true, KaxTagBinary) @@ -694,6 +786,9 @@ DEFINE_MKX_MASTER(KaxTagSimple, 0x67C8, 2, KaxTag, "TagSimple"); DEFINE_MKX_UNISTRING(KaxTagName, 0x45A3, 2, KaxTagSimple, "TagName"); DEFINE_MKX_STRING_DEF(KaxTagLangue, 0x447A, 2, KaxTagSimple, "TagLanguage", "und"); +#if MATROSKA_VERSION >= 2 +DEFINE_MKX_STRING(KaxTagLanguageIETF, 0x447B, 2, KaxTagSimple, "TagLanguageIETF"); +#endif DEFINE_MKX_UINTEGER_DEF(KaxTagDefault, 0x4484, 2, KaxTagSimple, "TagDefault", 1); DEFINE_MKX_UNISTRING(KaxTagString, 0x4487, 2, KaxTagSimple, "TagString"); DEFINE_MKX_BINARY (KaxTagBinary, 0x4485, 2, KaxTagSimple, "TagBinary"); diff -Nru makemkv-oss-1.10.7/libmatroska/src/KaxVersion.cpp makemkv-oss-1.10.8/libmatroska/src/KaxVersion.cpp --- makemkv-oss-1.10.7/libmatroska/src/KaxVersion.cpp 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/libmatroska/src/KaxVersion.cpp 2017-11-17 12:59:31.000000000 +0000 @@ -37,6 +37,11 @@ START_LIBMATROSKA_NAMESPACE -const ccc::string KaxCodeVersion = "1.4.4"; +const ccc::string KaxCodeVersion = "1.4.7"; + +// Up to version 1.4.4 this library exported a build date string. As +// this made the build non-reproducible, replace it by a placeholder to +// remain binary compatible. +const ccc::string KaxCodeDate = "Unknown"; END_LIBMATROSKA_NAMESPACE diff -Nru makemkv-oss-1.10.7/makemkvgui/inc/ver_num.h makemkv-oss-1.10.8/makemkvgui/inc/ver_num.h --- makemkv-oss-1.10.7/makemkvgui/inc/ver_num.h 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/makemkvgui/inc/ver_num.h 2017-11-17 12:59:31.000000000 +0000 @@ -10,7 +10,7 @@ #ifndef VERNUM_H_INCLUDED #define VERNUM_H_INCLUDED -#define MAKEMKV_VERSION_NUMBER "v1.10.7" +#define MAKEMKV_VERSION_NUMBER "v1.10.8" #define LIBMMBD_VERSION_NUMBER "v1.2.1" #endif // VERNUM_H_INCLUDED diff -Nru makemkv-oss-1.10.7/makemkvgui/src/scsiinfo.cpp makemkv-oss-1.10.8/makemkvgui/src/scsiinfo.cpp --- makemkv-oss-1.10.7/makemkvgui/src/scsiinfo.cpp 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/makemkvgui/src/scsiinfo.cpp 2017-11-17 12:59:31.000000000 +0000 @@ -25,7 +25,7 @@ append_const(Qstr,Str); } -static QString FormatProtectionString(AP_DiskFsFlags FsFlags,const uint8_t* CopyrightInfo,const uint8_t* MkbSmall,const uint8_t* SvmSmall) +static QString FormatProtectionString(AP_DiskFsFlags FsFlags,const uint8_t* CopyrightInfo,const uint8_t* MkbSmall,const uint8_t* CCSmall,const uint8_t* SvmSmall) { bool have_css=false,have_aacs=false,have_bdsvm=false,have_cprm=false; unsigned int aacs_ver = 0; @@ -75,12 +75,49 @@ if (have_css) append_item(str,"CSS/CPPM"); if (have_cprm) append_item(str,"CPRM/CPPM"); - if (have_aacs) append_item(str,"AACS"); - if (aacs_ver) + if (have_aacs) { - char ver[8]; - sprintf(ver," v%u",aacs_ver); - append_const(str,ver); + uint8_t version = (MkbSmall != NULL) ? MkbSmall[5] : 4; + uint8_t category = (CCSmall != NULL) ? ((CCSmall[1]>>5)&3) : 0; + + append_item(str, "AACS"); + switch (version) + { + default: + case 3: + case 4: + break; + case 10: + append_const(str, "/II"); + break; + case 20: + append_const(str, "2.0"); + break; + case 21: + append_const(str, "2.1"); + break; + } + if (version >= 20) + { + switch (category) + { + case 0: + append_const(str, "/C"); + break; + case 1: + append_const(str, "/B"); + break; + case 2: + append_const(str, "/A"); + break; + } + } + if (aacs_ver) + { + char ver[8]; + sprintf(ver, " v%u", aacs_ver); + append_const(str, ver); + } } if (have_bdsvm) append_item(str,"BD+"); @@ -241,6 +278,7 @@ ProtectionString=FormatProtectionString(FsFlags, (items.copyright_info.Size>=8)?items.copyright_info.Data:NULL, (items.mkb_small.Size>=12)?items.mkb_small.Data:NULL, + (items.ccert_small.Size>=4)?items.ccert_small.Data:NULL, (items.svm_small.Size>=17)?items.svm_small.Data:NULL ); @@ -476,7 +514,8 @@ ( (0==cmemcmp(items.bd_disc_info.Data+4+8,"BDO",3)) || (0==cmemcmp(items.bd_disc_info.Data+4+8,"BDW",3)) || - (0==cmemcmp(items.bd_disc_info.Data+4+8,"BDR",3)) + (0==cmemcmp(items.bd_disc_info.Data+4+8,"BDR",3)) || + (0==cmemcmp(items.bd_disc_info.Data+4+8,"BDU",3)) ) && true) { @@ -487,6 +526,7 @@ case 1: p="BD-ROM"; break; case 2: p="BD-R"; break; case 4: p="BD-RE"; break; + case 9: p="BD-ROM UHD"; break; default: p=NULL; break; } if (NULL!=p) @@ -506,6 +546,7 @@ { case 1: pw=AP_UI_STRING(APP_SI_DISCCBL25); break; case 2: pw=AP_UI_STRING(APP_SI_DISCCBL27); break; + case 5: // what is UHD channel bit length? default: pw=NULL; break; } if (NULL!=pw) diff -Nru makemkv-oss-1.10.7/sstring/src/sstring.cpp makemkv-oss-1.10.8/sstring/src/sstring.cpp --- makemkv-oss-1.10.7/sstring/src/sstring.cpp 2017-09-04 10:29:38.000000000 +0000 +++ makemkv-oss-1.10.8/sstring/src/sstring.cpp 2017-11-17 12:59:31.000000000 +0000 @@ -96,7 +96,7 @@ { if ((c >= 'A') && (c <= 'Z')) { - return (c - ('a' - 'A')); + return (c + ('a' - 'A')); } else { return c; }