[SCM] kodi/upstream: Imported Upstream version 17.0~alpha3+dfsg1

rbalint at users.alioth.debian.org rbalint at users.alioth.debian.org
Thu Aug 4 23:55:38 UTC 2016


The following commit has been merged in the upstream branch:
commit b68fb6f7a65f12c767c3ca861b45a37e21a0ef28
Author: Balint Reczey <balint at balintreczey.hu>
Date:   Thu Aug 4 10:53:49 2016 +0200

    Imported Upstream version 17.0~alpha3+dfsg1

diff --git a/.gitignore b/.gitignore
index 687e665..3ce6655 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,6 +37,7 @@ config.log
 *.bak
 *.apk
 *.class
+*.dwo
 
 # Windows specific generated files
 *.exp
@@ -181,11 +182,13 @@ cmake_install.cmake
 /lib/cpluff/*/*/*/*/Makefile
 /lib/cpluff/po/*template
 /lib/cpluff/po/*header
+lib/cpluff/console/cpluff-console
 lib/cpluff/examples/cpfile/cpfile
 lib/cpluff/libcpluff/cpluffdef.h
 lib/cpluff/libcpluff/docsrc/Doxyfile-impl
 lib/cpluff/libcpluff/docsrc/Doxyfile-ref
 lib/cpluff/libtool
+lib/cpluff/loader/cpluff-loader
 lib/cpluff/po/POTFILES
 lib/cpluff/stamp-h1
 
@@ -224,7 +227,6 @@ lib/cpluff/stamp-h1
 
 # /project/cmake
 /project/cmake/KodiConfig.cmake
-/project/cmake/XBMCConfig.cmake
 /project/cmake/addons/*.error
 /project/cmake/addons/.failure
 /project/cmake/addons/.success
@@ -243,7 +245,7 @@ lib/cpluff/stamp-h1
 /project/Win32BuildSetup/makeclean
 /project/Win32BuildSetup/noprompt
 /project/Win32BuildSetup/BUILD_WIN32/
-/project/Win32BuildSetup/dependencies
+/project/Win32BuildSetup/dependencies/
 
 # /project/BuildDependencies
 /project/BuildDependencies/downloads
@@ -282,22 +284,38 @@ lib/cpluff/stamp-h1
 
 # /system
 /system/cpluff.dll
+/system/EasyHook32.dll
 /system/libcurl.dll
 /system/libeay32.dll
 /system/librtmp.dll
 /system/libexif.dll
-/system/libexpat.dll
-/system/libidn-11.dll
-/system/libssh2.dll
-/system/libssl32.dll
 /system/ssh.dll
 /system/sqlite3.dll
 /system/libnfs.dll
 /system/dnssd.dll
-/system/libcec.dll
-/system/pthreadVC2.dll
+/system/cec.dll
 /system/libxslt.dll
 /system/ssleay32.dll
+/system/avcodec-57.dll
+/system/avfilter-6.dll
+/system/avformat-57.dll
+/system/avutil-55.dll
+/system/postproc-54.dll
+/system/swscale-4.dll
+/system/swresample-2.dll
+/system/libxml2.dll
+/system/libdvdcss-2.dll
+/system/libdvdnav.dll
+/system/libass.dll
+/system/libbluray*
+/system/libcdio.dll
+/system/libplist.dll
+/system/shairplay.dll
+/system/libmysql.dll
+/system/python27.dll
+/system/zlib.dll
+
+
 
 # /system/players/VideoPlayer
 /system/players/VideoPlayer/*
@@ -350,6 +368,7 @@ lib/cpluff/stamp-h1
 /tools/depends/target/libdvdread/native/
 /tools/depends/target/Toolchain_binaddons.cmake
 /tools/depends/target/config-binaddons.site
+/tools/depends/target/binary-addons/native
 
 # /tools/EventClients/
 /tools/EventClients/*.pyc
@@ -499,10 +518,10 @@ lib/cpluff/stamp-h1
 #/xbmc/utils
 /xbmc/utils/Makefile
 
-#/xbmc/win32/
-/xbmc/win32/XBMC_PC.rc
+#/xbmc/platform/win32/
+/xbmc/platform/win32/XBMC_PC.rc
 # no longer used
-/xbmc/win32/git_rev.h
+/xbmc/platform/win32/git_rev.h
 
 # /xbmc/windowing/
 /xbmc/windowing/Makefile
@@ -551,9 +570,6 @@ lib/cpluff/stamp-h1
 
 # Doxygen generated files
 /docs/html
-system/libmysql.dll
-system/python27.dll
-system/zlib.dll
 lib/addons/library.kodi.inputstream/project/VS2010Express/Debug
 lib/addons/library.kodi.inputstream/project/VS2010Express/Release
 /project/VS2010Express/XBMC for Windows.VC.db
@@ -561,3 +577,4 @@ lib/addons/library.kodi.inputstream/project/VS2010Express/Release
 tools/depends/native/TexturePacker/src/Win32/Debug/
 tools/depends/native/TexturePacker/src/Win32/Release/
 tools/depends/native/TexturePacker/src/Win32/TexturePacker.VC.db
+exclude_dll.txt
diff --git a/Kodi.xcodeproj/project.pbxproj b/Kodi.xcodeproj/project.pbxproj
index 75270de..b935680 100644
--- a/Kodi.xcodeproj/project.pbxproj
+++ b/Kodi.xcodeproj/project.pbxproj
@@ -134,6 +134,8 @@
 		1DE0443515828F4B005DDB4D /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1DE0443315828F4B005DDB4D /* Exception.cpp */; };
 		228FA65D1C53F9D50023BBF0 /* InfoScanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 228FA65C1C53F9D50023BBF0 /* InfoScanner.cpp */; };
 		228FA65E1C53F9D50023BBF0 /* InfoScanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 228FA65C1C53F9D50023BBF0 /* InfoScanner.cpp */; };
+		2A1D96BD1D437911009D8B25 /* GUIDialogPlayerProcessInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A1D96BC1D437911009D8B25 /* GUIDialogPlayerProcessInfo.cpp */; };
+		2A1D96BE1D437911009D8B25 /* GUIDialogPlayerProcessInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A1D96BC1D437911009D8B25 /* GUIDialogPlayerProcessInfo.cpp */; };
 		2A7B2BDC1BD6F16600044BCD /* PVRSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A7B2BDB1BD6F16600044BCD /* PVRSettings.cpp */; };
 		2A7B2BDD1BD6F16600044BCD /* PVRSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A7B2BDB1BD6F16600044BCD /* PVRSettings.cpp */; };
 		2AB491701CDDF1920004C263 /* HTTPRequestHandlerUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2AB4916E1CDDF1920004C263 /* HTTPRequestHandlerUtils.cpp */; };
@@ -464,6 +466,10 @@
 		7CAA469119427AED00008885 /* PosixDirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CAA468E19427AED00008885 /* PosixDirectory.cpp */; };
 		7CAA57471C8AF6C20032A326 /* DebugRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CAA57451C8AF6C20032A326 /* DebugRenderer.cpp */; };
 		7CAA57481C8AF6C20032A326 /* DebugRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CAA57451C8AF6C20032A326 /* DebugRenderer.cpp */; };
+		7CAEF0CE1D0E9E3800B1316C /* ColorManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CAEF0CC1D0E9E3800B1316C /* ColorManager.cpp */; };
+		7CAEF0CF1D0E9E3800B1316C /* ColorManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CAEF0CC1D0E9E3800B1316C /* ColorManager.cpp */; };
+		7CAEF0D21D0E9F0D00B1316C /* GUIDialogCMSSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CAEF0D01D0E9F0D00B1316C /* GUIDialogCMSSettings.cpp */; };
+		7CAEF0D31D0E9F0D00B1316C /* GUIDialogCMSSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CAEF0D01D0E9F0D00B1316C /* GUIDialogCMSSettings.cpp */; };
 		7CBEBB8412912BA400431822 /* fstrcmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 7CBEBB8212912BA300431822 /* fstrcmp.c */; };
 		7CC30DB116291A5C003E7579 /* MusicThumbLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CC30DAF16291A5C003E7579 /* MusicThumbLoader.cpp */; };
 		7CC30DC016291C2C003E7579 /* VideoThumbLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CC30DBE16291C2C003E7579 /* VideoThumbLoader.cpp */; };
@@ -2563,9 +2569,17 @@
 		1DE0443415828F4B005DDB4D /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Exception.h; path = commons/Exception.h; sourceTree = "<group>"; };
 		228FA65B1C53F9D50023BBF0 /* InfoScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InfoScanner.h; sourceTree = "<group>"; };
 		228FA65C1C53F9D50023BBF0 /* InfoScanner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InfoScanner.cpp; sourceTree = "<group>"; };
+		2A1D96BB1D4378CC009D8B25 /* GUIDialogPlayerProcessInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogPlayerProcessInfo.h; sourceTree = "<group>"; };
+		2A1D96BC1D437911009D8B25 /* GUIDialogPlayerProcessInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogPlayerProcessInfo.cpp; sourceTree = "<group>"; };
+		2A1D96BF1D437CDB009D8B25 /* WindowIDs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WindowIDs.h; sourceTree = "<group>"; };
+		2A45E7A71D2D042B000E49FA /* types.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = types.json; path = schema/types.json; sourceTree = "<group>"; };
+		2A45E7A81D2D042B000E49FA /* version.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = version.txt; path = schema/version.txt; sourceTree = "<group>"; };
 		2A4AAD251CEBC2060057AD44 /* DVDDemuxVobsub.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDDemuxVobsub.h; sourceTree = "<group>"; };
 		2A4AAD261CEBC2130057AD44 /* DVDFactoryDemuxer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDFactoryDemuxer.h; sourceTree = "<group>"; };
 		2A4AAD281CEBC64A0057AD44 /* GUIInfoLabels.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIInfoLabels.h; sourceTree = "<group>"; };
+		2A5531F81D4A0F9C00BDCE99 /* AddonEvents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddonEvents.h; sourceTree = "<group>"; };
+		2A5531F91D4A0FEB00BDCE99 /* EventStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventStream.h; sourceTree = "<group>"; };
+		2A5531FA1D4A0FEB00BDCE99 /* EventStreamDetail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventStreamDetail.h; sourceTree = "<group>"; };
 		2A7B2BDB1BD6F16600044BCD /* PVRSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PVRSettings.cpp; sourceTree = "<group>"; };
 		2A7B2BDE1BD6F18B00044BCD /* PVRSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PVRSettings.h; sourceTree = "<group>"; };
 		2A7E24C71CEBBC3B003096EB /* libKODI_peripheral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = libKODI_peripheral.h; path = "kodi-addon-dev-kit/include/kodi/libKODI_peripheral.h"; sourceTree = "<group>"; };
@@ -3016,6 +3030,10 @@
 		7CAA468F19427AED00008885 /* PosixDirectory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PosixDirectory.h; sourceTree = "<group>"; };
 		7CAA57451C8AF6C20032A326 /* DebugRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DebugRenderer.cpp; sourceTree = "<group>"; };
 		7CAA57461C8AF6C20032A326 /* DebugRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugRenderer.h; sourceTree = "<group>"; };
+		7CAEF0CC1D0E9E3800B1316C /* ColorManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ColorManager.cpp; sourceTree = "<group>"; };
+		7CAEF0CD1D0E9E3800B1316C /* ColorManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ColorManager.h; sourceTree = "<group>"; };
+		7CAEF0D01D0E9F0D00B1316C /* GUIDialogCMSSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogCMSSettings.cpp; sourceTree = "<group>"; };
+		7CAEF0D11D0E9F0D00B1316C /* GUIDialogCMSSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogCMSSettings.h; sourceTree = "<group>"; };
 		7CBEBB8212912BA300431822 /* fstrcmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fstrcmp.c; sourceTree = "<group>"; };
 		7CC30DAF16291A5C003E7579 /* MusicThumbLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MusicThumbLoader.cpp; sourceTree = "<group>"; };
 		7CC30DB016291A5C003E7579 /* MusicThumbLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MusicThumbLoader.h; sourceTree = "<group>"; };
@@ -5102,6 +5120,7 @@
 				18B7C3821294203F009E7A26 /* AddonDatabase.cpp */,
 				18B7C3831294203F009E7A26 /* AddonDatabase.h */,
 				18B49FF31152BFA5001AF8A6 /* AddonDll.h */,
+				2A5531F81D4A0F9C00BDCE99 /* AddonEvents.h */,
 				7C4705AC12EF584C00369E51 /* AddonInstaller.cpp */,
 				7C4705AD12EF584C00369E51 /* AddonInstaller.h */,
 				18B49FF41152BFA5001AF8A6 /* AddonManager.cpp */,
@@ -5340,6 +5359,7 @@
 				18B7C7501294222E009E7A26 /* Tween.h */,
 				18B7C7A61294222E009E7A26 /* VisibleEffect.cpp */,
 				18B7C7511294222E009E7A26 /* VisibleEffect.h */,
+				2A1D96BF1D437CDB009D8B25 /* WindowIDs.h */,
 				18B7C7A71294222E009E7A26 /* XBTF.cpp */,
 				18B7C7521294222E009E7A26 /* XBTF.h */,
 				18B7C7A81294222E009E7A26 /* XBTFReader.cpp */,
@@ -5730,6 +5750,8 @@
 				7C99B7941340723F00FC2B16 /* GUIDialogPlayEject.h */,
 				E38E17C80D25F9FA00618676 /* GUIDialogPlayerControls.cpp */,
 				E38E17C90D25F9FA00618676 /* GUIDialogPlayerControls.h */,
+				2A1D96BC1D437911009D8B25 /* GUIDialogPlayerProcessInfo.cpp */,
+				2A1D96BB1D4378CC009D8B25 /* GUIDialogPlayerProcessInfo.h */,
 				E38E17CE0D25F9FA00618676 /* GUIDialogProgress.cpp */,
 				E38E17CF0D25F9FA00618676 /* GUIDialogProgress.h */,
 				E38E17D00D25F9FA00618676 /* GUIDialogSeekBar.cpp */,
@@ -5985,6 +6007,8 @@
 			children = (
 				18B7C8FE12942761009E7A26 /* GUIDialogAudioSubtitleSettings.cpp */,
 				18B7C8FF12942761009E7A26 /* GUIDialogAudioSubtitleSettings.h */,
+				7CAEF0D01D0E9F0D00B1316C /* GUIDialogCMSSettings.cpp */,
+				7CAEF0D11D0E9F0D00B1316C /* GUIDialogCMSSettings.h */,
 				886328150E07B37200BB3DAB /* GUIDialogFullScreenInfo.cpp */,
 				886328160E07B37200BB3DAB /* GUIDialogFullScreenInfo.h */,
 				7C4E6F701829AA9700F1068F /* GUIDialogSubtitles.cpp */,
@@ -6296,6 +6320,8 @@
 			isa = PBXGroup;
 			children = (
 				7C7A40361C240D60006D95A0 /* methods.json */,
+				2A45E7A71D2D042B000E49FA /* types.json */,
+				2A45E7A81D2D042B000E49FA /* version.txt */,
 			);
 			name = schema;
 			sourceTree = "<group>";
@@ -8114,6 +8140,8 @@
 				E38E166B0D25F9FA00618676 /* VideoShaders */,
 				7CAA204F1079C8160096DE39 /* BaseRenderer.cpp */,
 				7CAA20501079C8160096DE39 /* BaseRenderer.h */,
+				7CAEF0CC1D0E9E3800B1316C /* ColorManager.cpp */,
+				7CAEF0CD1D0E9E3800B1316C /* ColorManager.h */,
 				7CAA57461C8AF6C20032A326 /* DebugRenderer.h */,
 				7CAA57451C8AF6C20032A326 /* DebugRenderer.cpp */,
 				7C921F8F1CD603C600684D0B /* FrameBufferObject.cpp */,
@@ -8675,6 +8703,8 @@
 				436B38F3106628850049AB3B /* EndianSwap.h */,
 				DF529BAC1741697B00523FB4 /* Environment.cpp */,
 				DF529BAD1741697B00523FB4 /* Environment.h */,
+				2A5531F91D4A0FEB00BDCE99 /* EventStream.h */,
+				2A5531FA1D4A0FEB00BDCE99 /* EventStreamDetail.h */,
 				E36C29E90DA72486001F0C9D /* Fanart.cpp */,
 				6E97BDC30DA2B620003A2A89 /* Fanart.h */,
 				F5F244641110DC6B009126C6 /* FileOperationJob.cpp */,
@@ -10539,9 +10569,11 @@
 				7C8FC6EE1829A4580045153D /* DirectoryProvider.cpp in Sources */,
 				7C4E6F721829AA9700F1068F /* GUIDialogSubtitles.cpp in Sources */,
 				7C140989183224B8009F9411 /* ISetting.cpp in Sources */,
+				7CAEF0D21D0E9F0D00B1316C /* GUIDialogCMSSettings.cpp in Sources */,
 				7C14098C183224B8009F9411 /* ISettingControl.cpp in Sources */,
 				68AE5BDF1C92421800C4D527 /* AddonButtonMap.cpp in Sources */,
 				7C14098F183224B8009F9411 /* Setting.cpp in Sources */,
+				7CAEF0CE1D0E9E3800B1316C /* ColorManager.cpp in Sources */,
 				DF56EF241A798A5E00CAAEFB /* HttpRangeUtils.cpp in Sources */,
 				7C140992183224B8009F9411 /* SettingCategoryAccess.cpp in Sources */,
 				7C140995183224B8009F9411 /* SettingConditions.cpp in Sources */,
@@ -10683,6 +10715,7 @@
 				7CCDAA82192756250074CF51 /* NptPosixDynamicLibraries.cpp in Sources */,
 				7CCDAA85192756250074CF51 /* NptPosixEnvironment.cpp in Sources */,
 				7CCDAA8B192756250074CF51 /* NptPosixNetwork.cpp in Sources */,
+				2A1D96BD1D437911009D8B25 /* GUIDialogPlayerProcessInfo.cpp in Sources */,
 				7CCDAA8E192756250074CF51 /* NptPosixQueue.cpp in Sources */,
 				7CCDAA97192756250074CF51 /* NptPosixSystem.cpp in Sources */,
 				7CCDAAA0192756250074CF51 /* NptPosixThreads.cpp in Sources */,
@@ -11098,6 +11131,7 @@
 				E49912E3174E5DAD00741B6D /* GUIAction.cpp in Sources */,
 				E49912E4174E5DAD00741B6D /* GUIAudioManager.cpp in Sources */,
 				E49912E5174E5DAD00741B6D /* GUIBaseContainer.cpp in Sources */,
+				2A1D96BE1D437911009D8B25 /* GUIDialogPlayerProcessInfo.cpp in Sources */,
 				E49912E6174E5DAD00741B6D /* GUIBorderedImage.cpp in Sources */,
 				E49912E7174E5DAD00741B6D /* GUIButtonControl.cpp in Sources */,
 				E49912E9174E5DAD00741B6D /* GUIColorManager.cpp in Sources */,
@@ -11274,6 +11308,7 @@
 				E49913A6174E5F2100741B6D /* HTTPWebinterfaceAddonsHandler.cpp in Sources */,
 				E49913A7174E5F2100741B6D /* HTTPWebinterfaceHandler.cpp in Sources */,
 				DFD7175C1C0A031B0025D964 /* IOSEAGLView.mm in Sources */,
+				7CAEF0CF1D0E9E3800B1316C /* ColorManager.cpp in Sources */,
 				E49913A8174E5F2100741B6D /* IHTTPRequestHandler.cpp in Sources */,
 				3994425C1A8DD8D0006C39E9 /* ProgressJob.cpp in Sources */,
 				E49913A9174E5F2100741B6D /* NetworkLinux.cpp in Sources */,
@@ -11427,6 +11462,7 @@
 				E4991438174E604700741B6D /* Atomics.cpp in Sources */,
 				E4991439174E604700741B6D /* Event.cpp in Sources */,
 				E499143B174E604700741B6D /* SystemClock.cpp in Sources */,
+				7CAEF0D31D0E9F0D00B1316C /* GUIDialogCMSSettings.cpp in Sources */,
 				E499143C174E604700741B6D /* Thread.cpp in Sources */,
 				E499143D174E604700741B6D /* Timer.cpp in Sources */,
 				E499143E174E605900741B6D /* AlarmClock.cpp in Sources */,
diff --git a/addons/repository.xbmc.org/addon.xml b/addons/repository.xbmc.org/addon.xml
index 96010aa..f0c23b1 100644
--- a/addons/repository.xbmc.org/addon.xml
+++ b/addons/repository.xbmc.org/addon.xml
@@ -1,19 +1,16 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <addon id="repository.xbmc.org"
 		name="Kodi Add-on repository"
-		version="2.5.4"
+		version="2.5.5"
 		provider-name="Team Kodi">
   <requires>
     <import addon="xbmc.addon" version="12.0.0"/>
   </requires>
-	<extension point="xbmc.addon.repository"
-		name="Official XBMC.org Add-on Repository">
-		<dir minversion="16.9.0">
-			<info>http://mirrors.kodi.tv/addons/krypton/addons.xml.gz</info>
-			<checksum>http://mirrors.kodi.tv/addons/krypton/addons.xml.gz.md5</checksum>
-			<datadir zip="true">http://mirrors.kodi.tv/addons/krypton</datadir>
-			<hashes>true</hashes>
-		</dir>
+	<extension point="xbmc.addon.repository">
+		<info>http://mirrors.kodi.tv/addons/krypton/addons.xml.gz</info>
+		<checksum>http://mirrors.kodi.tv/addons/krypton/addons.xml.gz.md5</checksum>
+		<datadir>http://mirrors.kodi.tv/addons/krypton</datadir>
+		<hashes>true</hashes>
 	</extension>
 	<extension point="xbmc.addon.metadata">
 		<summary lang="af_ZA">Installeer Byvoegsels vanaf Kodi.tv</summary>
@@ -26,7 +23,7 @@
 		<summary lang="cy_GB">Gosod Ychwanegion o Kodi.tv</summary>
 		<summary lang="da_DK">Installer Add-ons fra Kodi.tv</summary>
 		<summary lang="de_DE">Installiere Addons von Kodi.tv</summary>
-		<summary lang="el_GR">Εγκατάσταση Πρόσθετων από το Kodi.tv</summary>
+		<summary lang="el_GR">Εγκατάσταση Προσθέτων από το Kodi.tv</summary>
 		<summary lang="en_AU">Install Add-ons from Kodi.tv</summary>
 		<summary lang="en_GB">Install Add-ons from Kodi.tv</summary>
 		<summary lang="en_NZ">Install Add-ons from Kodi.tv</summary>
@@ -83,7 +80,7 @@
 		<description lang="cy_GB">Llwytho i lawr a gosod ychwanegion o storfa ychwanegion Swyddogol Kodi.tv.{CR}Drwy ddefnyddio'r Storfa swyddogol bydd modd i chi gymryd mantais o'n gwasanaeth drychau ffeiliau i'ch cynorthwyoi lwytho i lawr yn gyflym o ardal yn agos i chi.[CR] Mae pob ychwnaegyn yn y storfa hwn wedi eu profi'n fras, os ydych yn canfod ychwanegyn sydd wedi torri  neu ddim yn gweithio yna hysbyswch Team Kodi fel bod modd i ni weithredu.</description>
 		<description lang="da_DK">Hent og installer add-ons fra det officielle Kodi.tv add-on fjernlager.[CR] Ved at bruge det officielle fjernlager drager du fordel af vores omfattende spejltjeneste, som gør at du kan hente hurtigere fra et sted nær dig.[CR]  Alle add-ons i dette fjernlager har gennemgået grundlæggende tests. Hvis du finder en defekt add-on, så rapporter venligst dette til Team Kodi, så vi kan tage hånd i hanke med eventuelle problemer.</description>
 		<description lang="de_DE">Dies ist das offizielle Kodi.tv Addon-Verzeichnis.[CR]Dieses Addon-Verzeichnis ermöglicht aufgrund umfangreicher Spiegelserver in der Nähe schnelle Downloads.[CR]Alle Addons in diesem Verzeichnis wurden einfachen Tests unterzogen. Sollte dennoch ein Addon nicht richtig funktionieren benachrichtige bitte Team Kodi, damit wir reagieren können.</description>
-		<description lang="el_GR">Λήψη και εγκατάσταση πρόσθετων από το επίσημο αποθετήριο του Kodi.tv.[CR]  Χρησιμοποιώντας το Επίσημο Αποθετήριο μπορείτε να εκμεταλλευτείτε τους εκτεταμένους διακομιστές αρχείων μας για ταχύτερες λήψεις από μία κοντινή σας περιοχή.[CR]  Όλα τα πρόσθετα σε αυτό το αποθετήριο έχουν περάσει τις στοιχειώδεις δοκιμές, αν βρείτε ένα κατεστραμμένο ή ανενεργό πρόσθετο παρακαλούμε να το αναφέρετε στην Ομάδα Kodi ούτως ώστε να ληφθούν οι απαραίτητες ενέργειες.</description>
+		<description lang="el_GR">Πραγματοποιήστε λήψη και εγκατάσταση προσθέτων από το επίσημο αποθετήριο του Kodi.tv.[CR]  Χρησιμοποιώντας το Επίσημο Αποθετήριο μπορείτε να εκμεταλλευτείτε τους εκτεταμένους διακομιστές αρχείων μας για ταχύτερες λήψεις από μία κοντινή σας περιοχή.[CR]  Όλα τα πρόσθετα σε αυτό το αποθετήριο έχουν περάσει τις στοιχειώδεις δοκιμές, αν βρείτε ένα κατεστραμμένο ή ανενεργό πρόσθετο παρακαλούμε να το αναφέρετε στην Ομάδα Kodi ούτως ώστε να πραγματοποιηθούν οι απαραίτητες ενέργειες.</description>
 		<description lang="en_AU">Download and install add-ons from the Official Kodi.tv add-on repository.[CR]  By using the official Repository you will be able to take advantage of our extensive file mirror service to help get you faster downloads from a region close to you.[CR]  All add-ons on this repository have undergone basic testing, if you find a broken or not working add-on please report it to Team Kodi so we can take any action needed.</description>
 		<description lang="en_GB">Download and install add-ons from the Official Kodi.tv add-on repository.[CR]  By using the official Repository you will be able to take advantage of our extensive file mirror service to help get you faster downloads from a region close to you.[CR]  All add-ons on this repository have under gone basic testing, if you find a broken or not working add-on please report it to Team Kodi so we can take any action needed.</description>
 		<description lang="en_NZ">Download and install add-ons from the Official Kodi.tv add-on repository.[CR]  By using the official Repository you will be able to take advantage of our extensive file mirror service to help get you faster downloads from a region close to you.[CR]  All add-ons on this repository have under gone basic testing, if you find a broken or not working add-on please report it to Team Kodi so we can take any action needed.</description>
@@ -140,7 +137,7 @@
 		<disclaimer lang="cy_GB">Nid Team Kodi wnaeth yr holl ychwanegion yn y storfa hon ac nid ydynt yn gyfrifol am eu cynnwys.</disclaimer>
 		<disclaimer lang="da_DK">Team Kodi har ikke lavet alle add-ons i dette fjernlager og er ikke ansvarlig for deres indhold</disclaimer>
 		<disclaimer lang="de_DE">Die Addons in diesem Verzeichnis wurden nicht alle vom Team Kodi erstellt. Verantwortlich für den Inhalt sind die jeweiligen Autoren.</disclaimer>
-		<disclaimer lang="el_GR">Η Ομάδα Kodi δεν δημιούργησε όλα τα πρόσθετα σε αυτό το αποθετήριο συνεπώς δεν είναι υπεύθυνοι για το περιεχόμενό τους</disclaimer>
+		<disclaimer lang="el_GR">Η Ομάδα Kodi δεν δημιούργησε όλα τα πρόσθετα σε αυτό το αποθετήριο συνεπώς δεν είναι υπεύθυνη για το περιεχόμενό τους</disclaimer>
 		<disclaimer lang="en_AU">Team Kodi did not make all the add-ons on this repository and are not responsible for their content</disclaimer>
 		<disclaimer lang="en_GB">Team Kodi did not make all the add-ons on this repository and are not responsible for their content</disclaimer>
 		<disclaimer lang="en_NZ">Team Kodi did not make all the add-ons on this repository and are not responsible for their content</disclaimer>
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po
index 3cb5426..26915cb 100644
--- a/addons/resource.language.en_gb/resources/strings.po
+++ b/addons/resource.language.en_gb/resources/strings.po
@@ -3602,13 +3602,13 @@ msgstr ""
 #. Representation of a timer rule
 #: xbmc/pvr/addons/PVRClient.cpp
 msgctxt "#822"
-msgid "Repeating"
+msgid "Timer rule"
 msgstr ""
 
 #. Representation of an epg-based timer rule.
 #: xbmc/pvr/addons/PVRClient.cpp
 msgctxt "#823"
-msgid "Repeating (guide-based)"
+msgid "Timer rule (guide-based)"
 msgstr ""
 
 #empty strings from id 824 to 827
@@ -7552,7 +7552,17 @@ msgctxt "#14210"
 msgid "Profile settings"
 msgstr ""
 
-#empty strings from id 14211 to 14214
+#: system/settings/settings.xml
+msgctxt "#14211"
+msgid "Media"
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#14212"
+msgid "Media settings"
+msgstr ""
+
+#empty strings from id 14213 to 14214
 
 #: system/settings/settings.xml
 msgctxt "#14215"
@@ -7609,7 +7619,12 @@ msgctxt "#14225"
 msgid "Network Control"
 msgstr ""
 
-#empty strings from id 14226 to 14229
+#: system/settings/settings.xml
+msgctxt "#14226"
+msgid "Manage Sources"
+msgstr ""
+
+#empty strings from id 14227 to 14229
 
 #: system/settings/settings.xml
 msgctxt "#14230"
@@ -7641,7 +7656,17 @@ msgctxt "#14235"
 msgid "Download Services"
 msgstr ""
 
-#empty strings from id 14236 to 14239
+#: system/settings/settings.xml
+msgctxt "#14236"
+msgid "Video Library"
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#14237"
+msgid "Music Library"
+msgstr ""
+
+#empty strings from id 14238 to 14239
 
 #: system/settings/settings.xml
 msgctxt "#14240"
@@ -7653,7 +7678,20 @@ msgctxt "#14241"
 msgid "Metadata"
 msgstr ""
 
-#empty strings from id 14242 to 14244
+#: system/settings/settings.xml
+msgctxt "#14242"
+msgid "Videos..."
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#14243"
+msgid "Music..."
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#14244"
+msgid "Pictures..."
+msgstr ""
 
 #: system/settings/settings.xml
 msgctxt "#14245"
@@ -8179,7 +8217,7 @@ msgstr ""
 
 #: system/settings/settings.xml
 msgctxt "#15108"
-msgid "GUI sounds"
+msgid "GUI Sounds"
 msgstr ""
 
 msgctxt "#15109"
@@ -8463,17 +8501,7 @@ msgctxt "#16039"
 msgid "Off"
 msgstr ""
 
-#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp
-msgctxt "#16040"
-msgid "Auto"
-msgstr ""
-
-#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp
-msgctxt "#16041"
-msgid "On"
-msgstr ""
-
-#empty strings from id 16042 to 16099
+#empty strings from id 16040 to 16099
 
 #: xbmc/video/windows/GUIWindowVideoNav.cpp
 msgctxt "#16100"
@@ -9981,10 +10009,19 @@ msgctxt "#19239"
 msgid "Starting background threads"
 msgstr ""
 
-#empty strings from id 19240 to 19241
+#empty string with id 19240
+
+#. Label for context menu entry to open settings dialog for a timer (read-only)
+#: xbmc/pvr/windows/GUIWindowPVRGuide.cpp
+#: xbmc/pvr/windows/GUIWindowPVRSearch.cpp
+#: xbmc/pvr/windows/GUIWindowPVRTimersBase.cpp
+msgctxt "#19241"
+msgid "View timer information"
+msgstr ""
 
 #. Label for context menu entry to open settings dialog for a timer
 #: xbmc/pvr/windows/GUIWindowPVRGuide.cpp
+#: xbmc/pvr/windows/GUIWindowPVRSearch.cpp
 msgctxt "#19242"
 msgid "Edit timer"
 msgstr ""
@@ -12473,7 +12510,7 @@ msgstr ""
 
 #: system/settings/settings.xml
 msgctxt "#20458"
-msgid "Group movies in sets"
+msgid "Show movie sets"
 msgstr ""
 
 #: xbmc/dialogs/GUIDialogMediaFilter.cpp
@@ -12528,7 +12565,7 @@ msgstr ""
 
 #: system/settings/settings.xml
 msgctxt "#20470"
-msgid "Use movie sets for single movies"
+msgid "Include sets containing a single movie"
 msgstr ""
 
 #: system/settings/settings.xml
@@ -13799,6 +13836,7 @@ msgid "Media sources"
 msgstr ""
 
 #. Name of an add-on type
+#: system/settings/settings.xml
 #: xbmc/addons/Addon.cpp
 msgctxt "#24006"
 msgid "GUI sounds"
@@ -18502,7 +18540,192 @@ msgctxt "#36552"
 msgid "Defines the number of presentation buffers used by the graphics driver. Select 2 if the driver uses double buffering or 3 for triple buffering."
 msgstr ""
 
-#empty strings from id 36553 to 36597
+#empty strings from id 36553 to 36559
+
+#: system/settings/settings.xml
+msgctxt "#36560"
+msgid "Colour management"
+msgstr ""
+
+#. Description of setting "System -> Video output -> Colour management" with label #36560
+#: system/settings/settings.xml
+msgctxt "#36561"
+msgid "Reproduce video colours accurately using a display profile or a 3D lookup table."
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#36562"
+msgid "Colour management mode"
+msgstr ""
+
+#. Description of setting "System -> Video output -> Colour management mode" with label #36562
+#: system/settings/settings.xml
+msgctxt "#36563"
+msgid "Use a precalculated 3D lookup table for video colour correction, or calculate the transformation for each video from a profile of your display. A precalculated 3D lookup table is preferred as it allows you to take advantage of the advanced features and high precision in ArgyllCMS. Display profile based correction is useful for testing different parameters, or emulating display settings that you don't have a 3D LUT prepared for."
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#36564"
+msgid "3D LUT"
+msgstr ""
+
+#. Description of setting "System -> Video output -> 3D LUT" with label #36564
+#: system/settings/settings.xml
+msgctxt "#36565"
+msgid "TODO: 3D LUT filename description"
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#36566"
+msgid "ICC display profile"
+msgstr ""
+
+#. Description of setting "System -> Video output -> ICC display profile" with label #36566
+#: system/settings/settings.xml
+msgctxt "#36567"
+msgid "TODO: ICC display profile filename description"
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#36568"
+msgid "Whitepoint"
+msgstr ""
+
+#. Description of setting "System -> Video output -> Whitepoint" with label #36568
+#: system/settings/settings.xml
+msgctxt "#36569"
+msgid "TODO: Whitepoint selection description"
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#36570"
+msgid "Primaries"
+msgstr ""
+
+#. Description of setting "System -> Video output -> Primaries" with label #36570
+#: system/settings/settings.xml
+msgctxt "#36571"
+msgid "TODO: Primary coordinates description"
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#36572"
+msgid "Gamma mode"
+msgstr ""
+
+#. Description of setting "System -> Video output -> Gamma mode" with label #36572
+#: system/settings/settings.xml
+msgctxt "#36573"
+msgid "TODO: Gamma mode description"
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#36574"
+msgid "Gamma"
+msgstr ""
+
+#. Description of setting "System -> Video output -> Gamma" with label #36574
+#: system/settings/settings.xml
+msgctxt "#36575"
+msgid "TODO: Gamma description"
+msgstr ""
+
+#: system/settings/settings.xml
+msgctxt "#36576"
+msgid "Lookup table size"
+msgstr ""
+
+#. Description of setting "System -> Video output -> Lookup table size" with label #36576
+#: system/settings/settings.xml
+msgctxt "#36577"
+msgid "TODO: Lookup table size description"
+msgstr ""
+
+#empty strings from id 36578 to 36579
+
+# Dialog title for 3D LUT file picker
+#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+msgctxt "#36580"
+msgid "3D LUT file"
+msgstr ""
+
+# Dialog title for ICC display profile file picker
+#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+msgctxt "#36581"
+msgid "ICC Profile"
+msgstr ""
+
+#. gamma type labels
+#: xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+msgctxt "#36582"
+msgid "BT.1886"
+msgstr ""
+
+msgctxt "#36583"
+msgid "Input offset"
+msgstr ""
+
+msgctxt "#36584"
+msgid "Output offset"
+msgstr ""
+
+msgctxt "#36585"
+msgid "Absolute"
+msgstr ""
+
+#. whitepoint labels
+#: xbmc/video/dialogs/GUIDialogCMSSettings.cpp
+msgctxt "#36586"
+msgid "D65 (standard)"
+msgstr ""
+
+msgctxt "#36587"
+msgid "D93 (Japanese NTSC)"
+msgstr ""
+
+#. primaries labels
+#: xbmc/video/dialogs/GUIDialogCMSSettings.cpp
+msgctxt "#36588"
+msgid "Automatic"
+msgstr ""
+
+msgctxt "#36589"
+msgid "HDTV (BT.709)"
+msgstr ""
+
+msgctxt "#36590"
+msgid "SDTV (SMPTE C)"
+msgstr ""
+
+msgctxt "#36591"
+msgid "NTSC 1953 (BT.470 M)"
+msgstr ""
+
+msgctxt "#36592"
+msgid "PAL/SECAM 1975 (BT.470 B/G)"
+msgstr ""
+
+msgctxt "#36593"
+msgid "HDTV 1988 (SMPTE 240M)"
+msgstr ""
+
+#. 3D LUT size labels
+#: xbmc/video/dialogs/GUIDialogCMSSettings.cpp
+msgctxt "#36594"
+msgid "16x16x16"
+msgstr ""
+
+msgctxt "#36595"
+msgid "64x64x64"
+msgstr ""
+
+msgctxt "#36596"
+msgid "256x256x256"
+msgstr ""
+
+msgctxt "#36597"
+msgid "%1.2f"
+msgstr ""
 
 #. Description of setting with label #36099 "Dither"
 #: system/settings/settings.xml
@@ -19121,10 +19344,10 @@ msgctxt "#38100"
 msgid "Section that contains the settings for the playback of media"
 msgstr ""
 
-#. Description of section #14201 "Library"
+#. Description of section #14201 "Media"
 #: system/settings/settings.xml
 msgctxt "#38101"
-msgid "Section that contains the settings for how media information is collected, stored, shown, and navigated"
+msgid "Section that contains the settings for sources and how media information is collected, stored, shown, and navigated"
 msgstr ""
 
 #. Description of section #14203 "Customise"
@@ -19208,3 +19431,28 @@ msgstr ""
 msgctxt "#39003"
 msgid "Accelerate h264"
 msgstr ""
+
+#. Description of category "Library" with label #14202
+#: system/settings/settings.xml
+msgctxt "#39004"
+msgid "This category contains provides access to the windows for source management and the Library settings for the databases"
+msgstr ""
+
+#. Description of setting "Videos... with label #14242
+#: system/settings/settings.xml
+msgctxt "#39005"
+msgid "This provides access to where video sources can be added and otherwise managed."
+msgstr ""
+
+#. Description of setting "Music... with label #14243
+#: system/settings/settings.xml
+msgctxt "#39006"
+msgid "This provides access to where music sources can be added and otherwise managed."
+msgstr ""
+
+#. Description of setting "Pictures... with label #14244
+#: system/settings/settings.xml
+msgctxt "#39007"
+msgid "This provides access to where picture sources can be added and otherwise managed."
+msgstr ""
+
diff --git a/addons/skin.estouchy/addon.xml b/addons/skin.estouchy/addon.xml
index d8140fc..073bc50 100644
--- a/addons/skin.estouchy/addon.xml
+++ b/addons/skin.estouchy/addon.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<addon id="skin.estouchy" version="1.0.17" name="Estouchy" provider-name="Team Kodi">
+<addon id="skin.estouchy" version="1.0.20" name="Estouchy" provider-name="Team Kodi">
 	<requires>
 		<import addon="xbmc.gui" version="5.12.0"/>
 	</requires>
@@ -31,12 +31,14 @@
 		<summary lang="pl_PL">Skóra dedykowana urządzeniom z ekranem dotykowym</summary>
 		<summary lang="pt_BR">Skin para dispositivos com telas de toque</summary>
 		<summary lang="pt_PT">Tema para dispositivos touchscreen</summary>
+		<summary lang="ru_RU">Обложка для устройств с сенсорным экраном</summary>
 		<summary lang="sk_SK">Grafický vzhľad pre zariadenia s dotykovým displejom</summary>
 		<summary lang="sr_RS">Маска за уређаје са екраном осетљивим на додир</summary>
 		<summary lang="sr_RS at latin">Maska za uređaje sa ekranom osetljivim na dodir</summary>
 		<summary lang="sv_SE">Skin för enheter med touchskärm</summary>
 		<summary lang="tr_TR">Dokunmatik ekranlı aygıtlar için dış görünüm</summary>
 		<summary lang="zh_CN">针对触屏设备的皮肤</summary>
+		<summary lang="zh_TW">為具有觸控螢幕的裝置所製作的佈景主題</summary>
 		<description lang="bg_BG">Обликът е разработен за ползване на устройства, с екран чувствителен на допир като таблет или телефон.</description>
 		<description lang="cs_CZ">Skin navržený pro zařízení s dotykovou obrazovkou, jako jsou tablety a smartphony.</description>
 		<description lang="de_DE">Dieses Skin wurde für die Benutzung mit Touchscreen-Geräten wie Tablets und Handys entworfen</description>
@@ -60,12 +62,14 @@
 		<description lang="pl_PL">Skóra dedykowana urządzeniom z ekranem dotykowym takim jak tablety i smartfony.</description>
 		<description lang="pt_BR">Skin concebida para ser usada em dispositivos com telas de toque como tablets e smartphones</description>
 		<description lang="pt_PT">Tema criado com o intuito de ser utilizado em tablets e smartphones</description>
+		<description lang="ru_RU">Обложка предназначена для использования на устройствах с сенсорным экраном, таких как планшеты и смартфоны</description>
 		<description lang="sk_SK">Grafický vzhľad určený pre použitie na dotykových zariadeniach ako sú tablety alebo mobilné telefóny</description>
 		<description lang="sr_RS">Маска дизајнирана да би била коришћена на уређајима са екранима осетљивим на додир као што су таблети и паметни телефони</description>
 		<description lang="sr_RS at latin">Maska dizajnirana da bi bila korišćena na uređajima sa ekranima osetljivim na dodir kao što su tableti i pametni telefoni</description>
 		<description lang="sv_SE">Skal avsedd att användas på enheter med pekskärm som surfplattor och smarttelefoner</description>
 		<description lang="tr_TR">Bu dış görünüm tabletler ve akıllı telefonlar gibi dokunmatik ekranlı aygıtlarda kullanılmak üzere tasarlandı</description>
 		<description lang="zh_CN">为触屏设备如平板电脑和智能手机而设计的皮肤</description>
+		<description lang="zh_TW">本佈景主題專為平板及手機等具有觸控螢幕的裝置而設計</description>
 		<platform>all</platform>
 		<license>Creative Commons Attribution-Share Alike 3.0 United States</license>
 		<forum>http://forum.kodi.tv/forumdisplay.php?fid=261</forum>
diff --git a/addons/skin.estouchy/changelog.txt b/addons/skin.estouchy/changelog.txt
index 4597a84..d7691b5 100644
--- a/addons/skin.estouchy/changelog.txt
+++ b/addons/skin.estouchy/changelog.txt
@@ -1,3 +1,12 @@
+V1.0.20
+- Fix seeklabel
+
+V1.0.19
+- Updated language files from Transifex
+
+V1.0.18
+- Updated language files from Transifex
+
 V1.0.17
 - Wider scrollbars
 
diff --git a/addons/skin.estouchy/language/resource.language.da_dk/strings.po b/addons/skin.estouchy/language/resource.language.da_dk/strings.po
index f990b6f..9b2a967 100644
--- a/addons/skin.estouchy/language/resource.language.da_dk/strings.po
+++ b/addons/skin.estouchy/language/resource.language.da_dk/strings.po
@@ -152,6 +152,10 @@ msgctxt "#31356"
 msgid "Download Subtitles"
 msgstr "Hent Undertekster"
 
+msgctxt "#31358"
+msgid "Teletext"
+msgstr "Tekst-tv"
+
 msgctxt "#31390"
 msgid "Skin default"
 msgstr "Skinnets standard"
diff --git a/addons/skin.estouchy/language/resource.language.el_gr/strings.po b/addons/skin.estouchy/language/resource.language.el_gr/strings.po
index 2f83f4e..bc2128d 100644
--- a/addons/skin.estouchy/language/resource.language.el_gr/strings.po
+++ b/addons/skin.estouchy/language/resource.language.el_gr/strings.po
@@ -18,11 +18,11 @@ msgstr ""
 
 msgctxt "#31002"
 msgid "Audio Settings"
-msgstr "Ρυθμίσεις Ήχου"
+msgstr "Ρυθμίσεις ήχου"
 
 msgctxt "#31003"
 msgid "IP"
-msgstr "Πρωτόκολλο Internet (IP)"
+msgstr "IP"
 
 msgctxt "#31004"
 msgid "Caps[CR]Lock"
@@ -30,15 +30,15 @@ msgstr "Caps[CR]Lock"
 
 msgctxt "#31005"
 msgid "Visualization Options"
-msgstr "Ρυθμίσεις Οπτικοποίησης"
+msgstr "Ρυθμίσεις οπτικοποίησης"
 
 msgctxt "#31006"
 msgid "Visualization Presets"
-msgstr "Προρυθμίσεις Οπτικοποιητή"
+msgstr "Προρυθμίσεις οπτικοποιητή"
 
 msgctxt "#31007"
 msgid "Context Menu"
-msgstr "Μενού Επιλογών"
+msgstr "Μενού επιλογών"
 
 msgctxt "#31009"
 msgid "Working..."
@@ -50,11 +50,11 @@ msgstr "Πρόσφατο"
 
 msgctxt "#31013"
 msgid "Movies"
-msgstr "Ταινίες"
+msgstr "ΤΑΙΝΙΕΣ"
 
 msgctxt "#31014"
 msgid "Episodes"
-msgstr "Επεισόδια"
+msgstr "ΕΠΕΙΣΟΔΙΑ"
 
 msgctxt "#31016"
 msgid "Albums"
@@ -78,11 +78,11 @@ msgstr "Ενημερωμένο:"
 
 msgctxt "#31044"
 msgid "FAST FORWARD"
-msgstr "ΜΠΡΟΣΤΑ"
+msgstr "ΠΡΟΩΘΗΣΗ"
 
 msgctxt "#31045"
 msgid "REWIND"
-msgstr "ΠΙΣΩ"
+msgstr "ΕΠΑΝΑΦΟΡΑ"
 
 msgctxt "#31049"
 msgid "End Time"
@@ -154,15 +154,15 @@ msgstr "Πρώτη προβολή"
 
 msgctxt "#31355"
 msgid "Video Menu"
-msgstr "Μενού Βίντεο"
+msgstr "Μενού βίντεο"
 
 msgctxt "#31356"
 msgid "Download Subtitles"
-msgstr "Λήψη Υποτίτλων"
+msgstr "Λήψη υποτίτλων"
 
 msgctxt "#31358"
 msgid "Teletext"
-msgstr "Τελετέξτ"
+msgstr "Teletext"
 
 msgctxt "#31390"
 msgid "Skin default"
@@ -170,11 +170,43 @@ msgstr "Προεπιλογή"
 
 msgctxt "#31391"
 msgid "Arial based"
-msgstr "Βασισμένη σε Arial"
+msgstr "Βασισμένη στην Arial"
 
 msgctxt "#31400"
 msgid "Change the skin · Set language and region · Change file listing options · Set up a screensaver"
-msgstr "Αλλαγή κελύφους ·  Αλλαγή χώρας και γλώσσας συστήματος ·  Επιλογές καταλόγου αρχείων · Προσαρμογή της προφύλαξης οθόνης"
+msgstr "Αλλαγή κελύφους · Ορισμός γλώσσας και περιοχής · Επιλογές καταλόγου αρχείων · Προσαρμογή προφύλαξης οθόνης"
+
+msgctxt "#31405"
+msgid "Configure & manage media sharing services · Configure & manage the weather service"
+msgstr "Ρύθμιση & διαχείριση υπηρεσιών διαμοιρασμού μέσων · Ρύθμιση & διαχείριση της υπηρεσίας καιρού"
+
+msgctxt "#31406"
+msgid "Configure display · Configure audio · Configure internet access · Configure power saving· Configure logging"
+msgstr "Ρύθμιση οθόνης · Ρύθμιση ήχου · Ρύθμιση πρόσβασης στο διαδίκτυο · Ρύθμιση ενέργειας · Ρύθμιση καταγραφών"
+
+msgctxt "#31407"
+msgid "Manage your installed add-ons · Browse for and install add-ons from kodi.tv · Modify add-on settings"
+msgstr "Διαχείριση εγκατεστημένων προσθέτων · Περιήγηση και εγκατάσταση προσθέτων από το kodi.tv · Τροποποίηση των ρυθμίσεων των προσθέτων"
+
+msgctxt "#31408"
+msgid "Configure actions that can be used during playback · Configure how media content is played"
+msgstr "Ρύθμιση ενεργειών κατά την αναπαραγωγή · Ρύθμσιη της αναπαραγωγή μέσων"
+
+msgctxt "#31409"
+msgid "Configure how the media lists display content ·  Configure how library lists are navigated · Configure database options"
+msgstr "Ρύθμιση της προβολής καταλόγων μέσων · Ρύθμιση της πλοήγησης στους καταλόγους βιβλιοθηκών · Ρύθμιση των βάσεων δεδομένων"
+
+msgctxt "#31410"
+msgid "Configure skin · Configure region · Configure control · Configure screensaver · Configure master lock"
+msgstr "Ρύθμιση κελύφους · Ρύθμιση περιοχής · Ρύθμιση ελέγχου · Ρύθμιση προφύλαξης οθόνης · Ρύθμιση κεντρικού κλειδώματος"
+
+msgctxt "#31411"
+msgid "Configure your profiles · Set locking options · Enable login screen"
+msgstr "Ρύθμιση των προφίλ · Ορισμός επιλογών κλειδώματος · Ενεργοποίηση οθόνης εισόδου"
+
+msgctxt "#31412"
+msgid "Display system information · Hardware statistics · Check storage availability · View network configuration"
+msgstr "Προβολή πληροφοριών συστήματος · Στατιστικά υλικού · Έλεγχος αποθηκευτικού χώρου · Προβολή διαμόρφωσης δικτύου"
 
 msgctxt "#31421"
 msgid "Select your Kodi user Profile[CR]to login and continue"
@@ -186,7 +218,7 @@ msgstr "Πλήκτρα Κατηγοριών Κεντρικού Μενού"
 
 msgctxt "#31501"
 msgid "Home Page Add-on Quick Links"
-msgstr "Ταχείς Σύνδεσμοι Πρόσθετων Αρχικής Οθόνης"
+msgstr "Σύνδεσμοι Προσθέτων Αρχικής Οθόνης"
 
 msgctxt "#31502"
 msgid "Miscellaneous Options"
@@ -200,6 +232,10 @@ msgctxt "#31551"
 msgid "Add-on Shortcut"
 msgstr "Συντόμευση Πρόσθετου"
 
+msgctxt "#31552"
+msgid "SYNC"
+msgstr "Συγχρονισμός"
+
 msgctxt "#31553"
 msgid "Use Custom Background"
 msgstr "Χρήση Προσαρμοσμένου φόντου"
@@ -208,6 +244,10 @@ msgctxt "#31554"
 msgid "Background:"
 msgstr "Φόντο:"
 
+msgctxt "#31555"
+msgid "Configure TV settings · Change full screen info · Manage EPG data settings"
+msgstr "Ρύθμιση επιλογών TV · Αλλαγή πληροφοριών πλήρους οθόνης · Διαχείριση ρυθμίσεων δεδομένων EPG"
+
 msgctxt "#31556"
 msgid "Live TV"
 msgstr "Live TV"
@@ -216,25 +256,29 @@ msgctxt "#31557"
 msgid "Hide video background"
 msgstr "Απόκρυψη υποβάθρου βίντεο"
 
+msgctxt "#31558"
+msgid "Hide visualization background"
+msgstr "Απόκρυψη υποβάθρου οπτικοποίησης"
+
 msgctxt "#31559"
 msgid "Channel settings"
 msgstr "Ρυθμίσεις καναλιών"
 
 msgctxt "#31560"
 msgid "Available groups"
-msgstr "Διαθέσιμα γκρουπ"
+msgstr "Διαθέσιμες ομάδες"
 
 msgctxt "#31561"
 msgid "Add Group"
-msgstr "Προσθήκη Γκρουπ"
+msgstr "Προσθήκη Ομάδας"
 
 msgctxt "#31562"
 msgid "Rename Group"
-msgstr "Ονομασία Γκρουπ"
+msgstr "Ονομασία Ομάδας"
 
 msgctxt "#31563"
 msgid "Delete Group"
-msgstr "Διαγραφή Γκρουπ"
+msgstr "Διαγραφή Ομάδας"
 
 msgctxt "#31564"
 msgid "Show hidden"
@@ -250,7 +294,15 @@ msgstr "Πρώτη εκκίνηση"
 
 msgctxt "#31901"
 msgid "There are two things to know about navigating Estouchy"
-msgstr "Υπάρχου δύο πράγματα που πρέπει να γνωρίζετε για την πλοήγηση Estouchy"
+msgstr "Υπάρχουν δύο πράγματα που πρέπει να γνωρίζετε για την πλοήγηση στο Estouchy"
+
+msgctxt "#31902"
+msgid "The Kodi logo functions as a 'HOME' button. Whenever you touch it, you will be taken back to the home screen."
+msgstr "Το λογότυπο του Kodi λειτουργεί σαν πλήκτρο \"Αρχικής οθόνης\". Όποτε το πατήσετε, θα μεταφερθείτε στην αρχική οθόνη."
+
+msgctxt "#31903"
+msgid "When you are playing audio or video, the item title will appear at the top of the screen. Touching it will take you to the fullscreen visualization or video window."
+msgstr "Όταν αναπαράγεται ήχος ή βίντεο, ο τίτλος του θα εμφανιστεί στην κορυφή της οθόνης. Με το πάτημα αυτού θα μεταφερθείτε στην οπτικοποίηση πλήρους οθόνης ή στο παράθυρο του βίντεο."
 
 msgctxt "#31904"
 msgid "Now Playing Title..."
diff --git a/addons/skin.estouchy/language/resource.language.en_gb/strings.po b/addons/skin.estouchy/language/resource.language.en_gb/strings.po
index fb745d9..9e2afb5 100644
--- a/addons/skin.estouchy/language/resource.language.en_gb/strings.po
+++ b/addons/skin.estouchy/language/resource.language.en_gb/strings.po
@@ -244,7 +244,7 @@ msgid "Configure actions that can be used during playback · Configure how media
 msgstr ""
 
 msgctxt "#31409"
-msgid "Configure how the media lists display content ·  Configure how library lists are navigated · Configure database options"
+msgid "Configure library sources· Show the media lists display content · Configure how library lists are navigated"
 msgstr ""
 
 msgctxt "#31410"
diff --git a/addons/skin.estouchy/language/resource.language.es_es/strings.po b/addons/skin.estouchy/language/resource.language.es_es/strings.po
index bec1c71..3cd838e 100644
--- a/addons/skin.estouchy/language/resource.language.es_es/strings.po
+++ b/addons/skin.estouchy/language/resource.language.es_es/strings.po
@@ -176,10 +176,38 @@ msgctxt "#31400"
 msgid "Change the skin · Set language and region · Change file listing options · Set up a screensaver"
 msgstr "Cambiar la skin - Seleccionar idioma y zona - Cambiar la visualización de los archivos - Elegir un salvapantallas"
 
+msgctxt "#31405"
+msgid "Configure & manage media sharing services · Configure & manage the weather service"
+msgstr "Configure y gestione los servicios para compartir medios · Configure y gestione el servicio de clima"
+
+msgctxt "#31406"
+msgid "Configure display · Configure audio · Configure internet access · Configure power saving· Configure logging"
+msgstr "Configure la pantalla · Configure el sonido · Configure el acceso a internet · Configure el ahorro de energia · Configure la depuración de errores"
+
 msgctxt "#31407"
 msgid "Manage your installed add-ons · Browse for and install add-ons from kodi.tv · Modify add-on settings"
 msgstr "Gestiona los add-ons instalados · Busca e instala add-ons desde kodi.tv · Modifica los ajustes de los add-ons"
 
+msgctxt "#31408"
+msgid "Configure actions that can be used during playback · Configure how media content is played"
+msgstr "Configure acciones que se pueden usar durante la reproducción · Configure cómo se reproducen los contenidos"
+
+msgctxt "#31409"
+msgid "Configure how the media lists display content ·  Configure how library lists are navigated · Configure database options"
+msgstr "Configure cómo se muestran los contenidos en las vistas de Archivos o Colecciones · Configure cómo se navega por las vistas de Archivos o Colecciones · Configure las opciones de las bases de datos de medios"
+
+msgctxt "#31410"
+msgid "Configure skin · Configure region · Configure control · Configure screensaver · Configure master lock"
+msgstr "Configure el skin · Configure la región · Configure el control · Configure el salvapantallas · Configure el bloqueo maestro"
+
+msgctxt "#31411"
+msgid "Configure your profiles · Set locking options · Enable login screen"
+msgstr "Configure sus perfiles · Añada opciones de bloqueo · Habilite una pantalla de inicio de sesión"
+
+msgctxt "#31412"
+msgid "Display system information · Hardware statistics · Check storage availability · View network configuration"
+msgstr "Muestre información del sistema · Estadísticas de Hardware · Compruebe el espacio disponible · Vea la configuración de red"
+
 msgctxt "#31421"
 msgid "Select your Kodi user Profile[CR]to login and continue"
 msgstr "Selecciona tu usuario [CR] y continua"
@@ -228,6 +256,10 @@ msgctxt "#31557"
 msgid "Hide video background"
 msgstr "Ocultar vídeo de fondo"
 
+msgctxt "#31558"
+msgid "Hide visualization background"
+msgstr "Ocultar visualización de fondo"
+
 msgctxt "#31559"
 msgid "Channel settings"
 msgstr "Ajustes del canal"
@@ -264,6 +296,14 @@ msgctxt "#31901"
 msgid "There are two things to know about navigating Estouchy"
 msgstr "Aprende un par de cosas que debes conocer sobre la navegación en Estouchy"
 
+msgctxt "#31902"
+msgid "The Kodi logo functions as a 'HOME' button. Whenever you touch it, you will be taken back to the home screen."
+msgstr "El logo de Kodi funciona como un botón 'INICIO'. En cuanto lo toque, volverá a la pantalla de inicio."
+
+msgctxt "#31903"
+msgid "When you are playing audio or video, the item title will appear at the top of the screen. Touching it will take you to the fullscreen visualization or video window."
+msgstr "Cuando esté reproduciendo vídeo o audio, el título del elemento aparecerá en la parte superior de la pantalla. Tocarlo le llevára a una visualización a pantalla completa o a una ventana de vídeo."
+
 msgctxt "#31904"
 msgid "Now Playing Title..."
 msgstr "Título de la reproducción actual..."
diff --git a/addons/skin.estouchy/language/resource.language.fi_fi/strings.po b/addons/skin.estouchy/language/resource.language.fi_fi/strings.po
index c809929..7927bf9 100644
--- a/addons/skin.estouchy/language/resource.language.fi_fi/strings.po
+++ b/addons/skin.estouchy/language/resource.language.fi_fi/strings.po
@@ -180,6 +180,10 @@ msgctxt "#31406"
 msgid "Configure display · Configure audio · Configure internet access · Configure power saving· Configure logging"
 msgstr "Määritä näyttö · Määritä ääni · Määritä internetyhteys · Määritä tehonsäästö · Määritä kirjaaminen"
 
+msgctxt "#31407"
+msgid "Manage your installed add-ons · Browse for and install add-ons from kodi.tv · Modify add-on settings"
+msgstr "Hallitse asennettuja lisäosia · Valitse ja asenna lisäosia kodi.tv:stä · Muokkaa lisäosien asetuksia"
+
 msgctxt "#31421"
 msgid "Select your Kodi user Profile[CR]to login and continue"
 msgstr "Valitse Kodi-käyttäjäprofiili[CR]kirjautuaksesi sisään"
diff --git a/addons/skin.estouchy/language/resource.language.fr_fr/strings.po b/addons/skin.estouchy/language/resource.language.fr_fr/strings.po
index 3c4a69d..6312e0b 100644
--- a/addons/skin.estouchy/language/resource.language.fr_fr/strings.po
+++ b/addons/skin.estouchy/language/resource.language.fr_fr/strings.po
@@ -186,7 +186,7 @@ msgstr "Configuration de l'affichage · Configuration de l'audio · Configuratio
 
 msgctxt "#31407"
 msgid "Manage your installed add-ons · Browse for and install add-ons from kodi.tv · Modify add-on settings"
-msgstr "Gestion des extensions installées · Parcours et installation des extensions depuis kodi.tv[CR]Modification des paramètres des extensions"
+msgstr "Gestion des extensions installées · Parcours et installation des extensions depuis kodi.tv · Modification des paramètres des extensions"
 
 msgctxt "#31408"
 msgid "Configure actions that can be used during playback · Configure how media content is played"
diff --git a/addons/skin.estouchy/language/resource.language.gl_es/strings.po b/addons/skin.estouchy/language/resource.language.gl_es/strings.po
index f94d5f3..488a3a3 100644
--- a/addons/skin.estouchy/language/resource.language.gl_es/strings.po
+++ b/addons/skin.estouchy/language/resource.language.gl_es/strings.po
@@ -90,11 +90,11 @@ msgstr "Tempo final"
 
 msgctxt "#31050"
 msgid "Sort: Ascending"
-msgstr "Ordear: Ascendentemente"
+msgstr "Ordenar: Ascendentemente"
 
 msgctxt "#31051"
 msgid "Sort: Descending"
-msgstr "Ordear: Descendentemente"
+msgstr "Ordenar: Descendentemente"
 
 msgctxt "#31055"
 msgid "Open playlist"
@@ -110,7 +110,7 @@ msgstr "Pechar lista de reprodución"
 
 msgctxt "#31058"
 msgid "System music files"
-msgstr "Arquivos de música do sistema"
+msgstr "Ficheiros de música do sistema"
 
 msgctxt "#31059"
 msgid "Current playlist"
@@ -138,7 +138,7 @@ msgstr "Última actualización"
 
 msgctxt "#31303"
 msgid "Data provider"
-msgstr "Proveedor de datos"
+msgstr "Provedor de datos"
 
 msgctxt "#31309"
 msgid "Memory Used:"
@@ -154,7 +154,7 @@ msgstr "Emitido"
 
 msgctxt "#31355"
 msgid "Video Menu"
-msgstr "Menú de video"
+msgstr "Menú de vídeo"
 
 msgctxt "#31356"
 msgid "Download Subtitles"
@@ -174,7 +174,35 @@ msgstr "Baseado en Arial"
 
 msgctxt "#31400"
 msgid "Change the skin · Set language and region · Change file listing options · Set up a screensaver"
-msgstr "Trocar pel · Estabrecer lingua e rexión · Trocar opcións do listado de arquivos · Configurar un gardapantallas"
+msgstr "Trocar pel · Definir idioma e rexión · Trocar opcións do listado de ficheiros · Configurar un protector de pantalla"
+
+msgctxt "#31405"
+msgid "Configure & manage media sharing services · Configure & manage the weather service"
+msgstr "Configurar e xestionar os servizos de compartición de medios · Configurar e xestionar o servizo metereolóxico"
+
+msgctxt "#31406"
+msgid "Configure display · Configure audio · Configure internet access · Configure power saving· Configure logging"
+msgstr "Configurar a pantalla · Configurar o son · Configurar internet · Configurar o aforro de enerxía · Configurar o rexistro de eventos"
+
+msgctxt "#31407"
+msgid "Manage your installed add-ons · Browse for and install add-ons from kodi.tv · Modify add-on settings"
+msgstr "Xestiona os teus complementos instalados · Busca e instala complementos de kodi.tv · Modifica os axustes dos complementos"
+
+msgctxt "#31408"
+msgid "Configure actions that can be used during playback · Configure how media content is played"
+msgstr "Configurar as accións permitidas durante a reprodución · Configurar como se reproduce o contido multimedia"
+
+msgctxt "#31410"
+msgid "Configure skin · Configure region · Configure control · Configure screensaver · Configure master lock"
+msgstr "Configurar o tema · Configurar a rexión · Configurar o control · Configurar  o protector de pantalla · Configurar o bloqueo maestro"
+
+msgctxt "#31411"
+msgid "Configure your profiles · Set locking options · Enable login screen"
+msgstr "Configurar os teus perfís · Definir as opción de bloqueo · Activar a pantalla de inicio de sesión"
+
+msgctxt "#31412"
+msgid "Display system information · Hardware statistics · Check storage availability · View network configuration"
+msgstr "Amosar información do sistema · Estatísticas do Hardware · Verificar o almacenamento · Ver a configuración de rede"
 
 msgctxt "#31421"
 msgid "Select your Kodi user Profile[CR]to login and continue"
@@ -198,7 +226,7 @@ msgstr "Botón e información da pantalla meteorolóxica inicial"
 
 msgctxt "#31551"
 msgid "Add-on Shortcut"
-msgstr "Atallo a Engadido"
+msgstr "Atallo a complemento"
 
 msgctxt "#31553"
 msgid "Use Custom Background"
@@ -208,6 +236,10 @@ msgctxt "#31554"
 msgid "Background:"
 msgstr "Fondo:"
 
+msgctxt "#31555"
+msgid "Configure TV settings · Change full screen info · Manage EPG data settings"
+msgstr "Configurar os axustes da TV · Mudar a configuración da pantalla completa · Xestionar os axustes dos datos da Guía"
+
 msgctxt "#31556"
 msgid "Live TV"
 msgstr "TV en Directo"
@@ -251,3 +283,7 @@ msgstr "Primeira execución"
 msgctxt "#31901"
 msgid "There are two things to know about navigating Estouchy"
 msgstr "Hai dúas cousas que tes que saber canto a navegación en Estouchy"
+
+msgctxt "#31904"
+msgid "Now Playing Title..."
+msgstr "Reproducindo"
diff --git a/addons/skin.estouchy/language/resource.language.ja_jp/strings.po b/addons/skin.estouchy/language/resource.language.ja_jp/strings.po
index 9b8cf6c..0d46de2 100644
--- a/addons/skin.estouchy/language/resource.language.ja_jp/strings.po
+++ b/addons/skin.estouchy/language/resource.language.ja_jp/strings.po
@@ -152,6 +152,10 @@ msgctxt "#31356"
 msgid "Download Subtitles"
 msgstr "字幕をダウンロード"
 
+msgctxt "#31358"
+msgid "Teletext"
+msgstr "文字多重放送"
+
 msgctxt "#31390"
 msgid "Skin default"
 msgstr "スキンのデフォルト"
@@ -188,6 +192,10 @@ msgctxt "#31556"
 msgid "Live TV"
 msgstr "ライブTV"
 
+msgctxt "#31560"
+msgid "Available groups"
+msgstr "利用可能なグループ"
+
 msgctxt "#31561"
 msgid "Add Group"
 msgstr "グループの追加"
diff --git a/addons/skin.estouchy/language/resource.language.ro_ro/strings.po b/addons/skin.estouchy/language/resource.language.ro_ro/strings.po
index 925a4c9..9a9b433 100644
--- a/addons/skin.estouchy/language/resource.language.ro_ro/strings.po
+++ b/addons/skin.estouchy/language/resource.language.ro_ro/strings.po
@@ -152,6 +152,10 @@ msgctxt "#31356"
 msgid "Download Subtitles"
 msgstr "Descărcare subtitrare"
 
+msgctxt "#31358"
+msgid "Teletext"
+msgstr "Teletext"
+
 msgctxt "#31390"
 msgid "Skin default"
 msgstr "Standard pentru costum"
diff --git a/addons/skin.estouchy/language/resource.language.sr_rs/strings.po b/addons/skin.estouchy/language/resource.language.sr_rs/strings.po
index a39456b..c276593 100644
--- a/addons/skin.estouchy/language/resource.language.sr_rs/strings.po
+++ b/addons/skin.estouchy/language/resource.language.sr_rs/strings.po
@@ -176,10 +176,38 @@ msgctxt "#31400"
 msgid "Change the skin · Set language and region · Change file listing options · Set up a screensaver"
 msgstr "Промените маску · Поставите језик и регију - Промените опције излиставања датотека - Поставите чувара екрана"
 
+msgctxt "#31405"
+msgid "Configure & manage media sharing services · Configure & manage the weather service"
+msgstr "Подеси & управљај сервисима дељења медија · Подеси & управљај метео сервисом"
+
+msgctxt "#31406"
+msgid "Configure display · Configure audio · Configure internet access · Configure power saving· Configure logging"
+msgstr "Подеси приказ ·  Подеси аудио · Подеси приступ интернету · Подеси уштеду енергије · Подеси пријављивање"
+
 msgctxt "#31407"
 msgid "Manage your installed add-ons · Browse for and install add-ons from kodi.tv · Modify add-on settings"
 msgstr "Управљајте вашим инсталираним додатним програмима · Потражите и инсталирајте додатне програме са kodi.tv - Подесите подешавања додатних програма"
 
+msgctxt "#31408"
+msgid "Configure actions that can be used during playback · Configure how media content is played"
+msgstr "Подесите акције које се могу користити током репродукције · Подесите како се медијски садржаји репродукују"
+
+msgctxt "#31409"
+msgid "Configure how the media lists display content ·  Configure how library lists are navigated · Configure database options"
+msgstr "Подеси како листе медија приказују садржај · Подеси навигацију у листама библиотеке · Подеси опције базе података"
+
+msgctxt "#31410"
+msgid "Configure skin · Configure region · Configure control · Configure screensaver · Configure master lock"
+msgstr "Подеси маску · Подеси регион · Подеси контролу · Подеси чувар екрана · Подеси главно закључавање"
+
+msgctxt "#31411"
+msgid "Configure your profiles · Set locking options · Enable login screen"
+msgstr "Подесите ваше профиле · Подесите опције закључавања · Активирајте екран за пријаву"
+
+msgctxt "#31412"
+msgid "Display system information · Hardware statistics · Check storage availability · View network configuration"
+msgstr "Прикажи системске информације · Хардверску статистику · Провери доступност складишта · Погледај конфигурацију мреже"
+
 msgctxt "#31421"
 msgid "Select your Kodi user Profile[CR]to login and continue"
 msgstr "Изаберите ваш Коди кориснички Профил[CR]за пријаву, а потом наставите даље"
diff --git a/addons/skin.estouchy/language/resource.language.zh_tw/strings.po b/addons/skin.estouchy/language/resource.language.zh_tw/strings.po
index d899dd4..325d4bc 100644
--- a/addons/skin.estouchy/language/resource.language.zh_tw/strings.po
+++ b/addons/skin.estouchy/language/resource.language.zh_tw/strings.po
@@ -44,6 +44,10 @@ msgctxt "#31009"
 msgid "Working..."
 msgstr "處理中..."
 
+msgctxt "#31011"
+msgid "Recent"
+msgstr "最近的"
+
 msgctxt "#31013"
 msgid "Movies"
 msgstr "電影"
@@ -68,6 +72,10 @@ msgctxt "#31038"
 msgid "Login"
 msgstr "登入"
 
+msgctxt "#31039"
+msgid "Updated:"
+msgstr "已更新:"
+
 msgctxt "#31044"
 msgid "FAST FORWARD"
 msgstr "快轉"
@@ -168,10 +176,46 @@ msgctxt "#31400"
 msgid "Change the skin · Set language and region · Change file listing options · Set up a screensaver"
 msgstr "改變佈景主題 · 設定語言和地區 · 修改檔案列表選項 · 設定螢幕保護程式"
 
+msgctxt "#31405"
+msgid "Configure & manage media sharing services · Configure & manage the weather service"
+msgstr "設定並管理媒體共享服務  · 設定並管理天氣服務"
+
+msgctxt "#31406"
+msgid "Configure display · Configure audio · Configure internet access · Configure power saving· Configure logging"
+msgstr "設定顯示器 · 設定音效 · 設定網路存取 · 設定電力節約 · 設定記錄檔"
+
+msgctxt "#31407"
+msgid "Manage your installed add-ons · Browse for and install add-ons from kodi.tv · Modify add-on settings"
+msgstr "管理已安裝的附加元件 · 從 kodi.tv 瀏覽並安裝附加元件 · 修改附加元件設定"
+
+msgctxt "#31408"
+msgid "Configure actions that can be used during playback · Configure how media content is played"
+msgstr "設定播放中可執行的動作 · 設定媒體檔案播放的方式"
+
+msgctxt "#31409"
+msgid "Configure how the media lists display content ·  Configure how library lists are navigated · Configure database options"
+msgstr "設定媒體檔列表方式如何顯示內容 · 設定如何進行資料庫列表的導覽 · 設定資料庫的選項"
+
+msgctxt "#31410"
+msgid "Configure skin · Configure region · Configure control · Configure screensaver · Configure master lock"
+msgstr "設定佈景主題 · 設定地區 · 設定控制項 · 設定螢幕保護程式 · 設定主密碼鎖"
+
+msgctxt "#31411"
+msgid "Configure your profiles · Set locking options · Enable login screen"
+msgstr "設定您的個人設定檔 · 設定密碼鎖的選項 · 使用登入畫面"
+
+msgctxt "#31412"
+msgid "Display system information · Hardware statistics · Check storage availability · View network configuration"
+msgstr "顯示系統資訊 · 硬體狀態 · 查看可用儲存空間 · 檢視網路設定"
+
 msgctxt "#31421"
 msgid "Select your Kodi user Profile[CR]to login and continue"
 msgstr "選擇您的 Kodi 使用者設定檔[CR]登入並繼續"
 
+msgctxt "#31500"
+msgid "Home Menu Catagory Buttons"
+msgstr "主選單分類按鈕"
+
 msgctxt "#31501"
 msgid "Home Page Add-on Quick Links"
 msgstr "首頁附加元件快速連結"
@@ -188,6 +232,22 @@ msgctxt "#31551"
 msgid "Add-on Shortcut"
 msgstr "附加元件捷徑"
 
+msgctxt "#31552"
+msgid "SYNC"
+msgstr "SYNC"
+
+msgctxt "#31553"
+msgid "Use Custom Background"
+msgstr "使用自訂桌面背景"
+
+msgctxt "#31554"
+msgid "Background:"
+msgstr "背景:"
+
+msgctxt "#31555"
+msgid "Configure TV settings · Change full screen info · Manage EPG data settings"
+msgstr "電視設定 · 修改全螢幕資訊 · 管理電子節目表資料設定"
+
 msgctxt "#31556"
 msgid "Live TV"
 msgstr "電視"
@@ -196,6 +256,18 @@ msgctxt "#31557"
 msgid "Hide video background"
 msgstr "隱藏影片背景"
 
+msgctxt "#31558"
+msgid "Hide visualization background"
+msgstr "隱藏視覺化特效的背景"
+
+msgctxt "#31559"
+msgid "Channel settings"
+msgstr "頻道設定"
+
+msgctxt "#31560"
+msgid "Available groups"
+msgstr "可用的群組"
+
 msgctxt "#31561"
 msgid "Add Group"
 msgstr "新增群組"
@@ -207,3 +279,31 @@ msgstr "重新命名群組"
 msgctxt "#31563"
 msgid "Delete Group"
 msgstr "刪除群組"
+
+msgctxt "#31564"
+msgid "Show hidden"
+msgstr "顯示被隱藏的"
+
+msgctxt "#31565"
+msgid "Show deleted"
+msgstr "顯示被刪除的"
+
+msgctxt "#31900"
+msgid "First Run"
+msgstr "第一次執行"
+
+msgctxt "#31901"
+msgid "There are two things to know about navigating Estouchy"
+msgstr "使用Estouchy時需要知道的兩件事"
+
+msgctxt "#31902"
+msgid "The Kodi logo functions as a 'HOME' button. Whenever you touch it, you will be taken back to the home screen."
+msgstr "Kodi的logo即為「回首頁」的按鈕,任何時候按下它就會被直接帶回首頁。"
+
+msgctxt "#31903"
+msgid "When you are playing audio or video, the item title will appear at the top of the screen. Touching it will take you to the fullscreen visualization or video window."
+msgstr "當正在播放音樂或影片時,該檔案的標題會顯示在螢幕中的最上端。按下該處會顯示全螢幕視覺化特效或影像視窗。"
+
+msgctxt "#31904"
+msgid "Now Playing Title..."
+msgstr "播放中的片名..."
diff --git a/addons/skin.estouchy/fanart.jpg b/addons/skin.estouchy/resources/fanart.jpg
similarity index 100%
rename from addons/skin.estouchy/fanart.jpg
rename to addons/skin.estouchy/resources/fanart.jpg
diff --git a/addons/skin.estouchy/icon.png b/addons/skin.estouchy/resources/icon.png
similarity index 100%
rename from addons/skin.estouchy/icon.png
rename to addons/skin.estouchy/resources/icon.png
diff --git a/addons/skin.estouchy/resources/screenshot-01.jpg b/addons/skin.estouchy/resources/screenshot-01.jpg
new file mode 100644
index 0000000..91ad9b5
Binary files /dev/null and b/addons/skin.estouchy/resources/screenshot-01.jpg differ
diff --git a/addons/skin.estouchy/resources/screenshot-02.jpg b/addons/skin.estouchy/resources/screenshot-02.jpg
new file mode 100644
index 0000000..e184527
Binary files /dev/null and b/addons/skin.estouchy/resources/screenshot-02.jpg differ
diff --git a/addons/skin.estouchy/resources/screenshot-03.jpg b/addons/skin.estouchy/resources/screenshot-03.jpg
new file mode 100644
index 0000000..7b464ac
Binary files /dev/null and b/addons/skin.estouchy/resources/screenshot-03.jpg differ
diff --git a/addons/skin.estouchy/resources/screenshot-04.jpg b/addons/skin.estouchy/resources/screenshot-04.jpg
new file mode 100644
index 0000000..8075153
Binary files /dev/null and b/addons/skin.estouchy/resources/screenshot-04.jpg differ
diff --git a/addons/skin.estouchy/resources/screenshot-05.jpg b/addons/skin.estouchy/resources/screenshot-05.jpg
new file mode 100644
index 0000000..3fcfd51
Binary files /dev/null and b/addons/skin.estouchy/resources/screenshot-05.jpg differ
diff --git a/addons/skin.estouchy/resources/screenshot-06.jpg b/addons/skin.estouchy/resources/screenshot-06.jpg
new file mode 100644
index 0000000..614653d
Binary files /dev/null and b/addons/skin.estouchy/resources/screenshot-06.jpg differ
diff --git a/addons/skin.estouchy/resources/screenshot-07.jpg b/addons/skin.estouchy/resources/screenshot-07.jpg
new file mode 100644
index 0000000..05c5c87
Binary files /dev/null and b/addons/skin.estouchy/resources/screenshot-07.jpg differ
diff --git a/addons/skin.estouchy/resources/screenshot-08.jpg b/addons/skin.estouchy/resources/screenshot-08.jpg
new file mode 100644
index 0000000..e0ed056
Binary files /dev/null and b/addons/skin.estouchy/resources/screenshot-08.jpg differ
diff --git a/addons/skin.estouchy/resources/screenshot-09.jpg b/addons/skin.estouchy/resources/screenshot-09.jpg
new file mode 100644
index 0000000..245e995
Binary files /dev/null and b/addons/skin.estouchy/resources/screenshot-09.jpg differ
diff --git a/addons/skin.estouchy/resources/screenshot-10.jpg b/addons/skin.estouchy/resources/screenshot-10.jpg
new file mode 100644
index 0000000..113a857
Binary files /dev/null and b/addons/skin.estouchy/resources/screenshot-10.jpg differ
diff --git a/addons/skin.estouchy/resources/screenshot-11.jpg b/addons/skin.estouchy/resources/screenshot-11.jpg
new file mode 100644
index 0000000..a2c09d8
Binary files /dev/null and b/addons/skin.estouchy/resources/screenshot-11.jpg differ
diff --git a/addons/skin.estouchy/resources/screenshot-12.jpg b/addons/skin.estouchy/resources/screenshot-12.jpg
new file mode 100644
index 0000000..1dd782f
Binary files /dev/null and b/addons/skin.estouchy/resources/screenshot-12.jpg differ
diff --git a/addons/skin.estouchy/xml/DialogSelect.xml b/addons/skin.estouchy/xml/DialogSelect.xml
index b3467db..c616eaf 100644
--- a/addons/skin.estouchy/xml/DialogSelect.xml
+++ b/addons/skin.estouchy/xml/DialogSelect.xml
@@ -153,7 +153,7 @@
 					<font>font22</font>
 					<align>left</align>
 					<aligny>center</aligny>
-					<label>$INFO[ListItem.AddonSummary]</label>
+					<label>$INFO[ListItem.Label2]</label>
 				</control>
 				<control type="image">
 					<posx>555</posx>
@@ -190,7 +190,7 @@
 					<font>font22</font>
 					<align>left</align>
 					<aligny>center</aligny>
-					<label>$INFO[ListItem.AddonSummary]</label>
+					<label>$INFO[ListItem.Label2]</label>
 				</control>
 				<control type="image">
 					<posx>555</posx>
diff --git a/addons/skin.estouchy/xml/Includes.xml b/addons/skin.estouchy/xml/Includes.xml
index 911ce76..512fc41 100644
--- a/addons/skin.estouchy/xml/Includes.xml
+++ b/addons/skin.estouchy/xml/Includes.xml
@@ -70,12 +70,11 @@
 		<value>icon_breadcrumb_settings.png</value>
 	</variable>
 	<variable name="SeekLabel">
+		<value condition="!String.IsEmpty(Player.SeekStepSize)">[UPPERCASE]$LOCALIZE[773][/UPPERCASE] $INFO[Player.SeekStepSize]</value>
+		<value condition="!String.IsEmpty(Player.SeekOffset)">[UPPERCASE]$LOCALIZE[773][/UPPERCASE] $INFO[Player.SeekOffset]</value>
 		<value condition="Player.Forwarding">$LOCALIZE[31044] $VAR[Speed]</value>
 		<value condition="Player.Rewinding">$LOCALIZE[31045] $VAR[Speed]</value>
-		<value condition="Player.Seeking + !Player.DisplayAfterSeek">[UPPERCASE]$LOCALIZE[773][/UPPERCASE]</value>
-		<value condition="Player.Seeking">$INFO[Player.SeekTime]</value>
-		<value condition="Player.DisplayAfterSeek + ![Player.Forwarding | Player.Rewinding]">[UPPERCASE]$LOCALIZE[773][/UPPERCASE] $INFO[Player.SeekOffset]</value>
-		<value condition="!String.IsEmpty(Player.SeekStepSize) + ![Player.Forwarding | Player.Rewinding]">[UPPERCASE]$LOCALIZE[773][/UPPERCASE] $INFO[Player.SeekStepSize]</value>
+		<value condition="Player.Paused">[UPPERCASE]$LOCALIZE[31043][/UPPERCASE]</value>
 	</variable>
 	<variable name="Speed">
 		<value condition="Player.Forwarding2x | Player.Rewinding2x">2x</value>
diff --git a/addons/skin.estouchy/xml/Settings.xml b/addons/skin.estouchy/xml/Settings.xml
index f2a57a9..5469a4c 100644
--- a/addons/skin.estouchy/xml/Settings.xml
+++ b/addons/skin.estouchy/xml/Settings.xml
@@ -131,9 +131,9 @@
 					<icon>icon_settings_player.png</icon>
 				</item>
 				<item id="2">
-					<label>14202</label>
+					<label>14211</label>
 					<label2>31409</label2>
-					<onclick>ActivateWindow(LibrarySettings)</onclick>
+					<onclick>ActivateWindow(MediaSettings)</onclick>
 					<icon>icon_settings_library.png</icon>
 				</item>
 				<item id="3">
diff --git a/addons/skin.estuary/1080i/Custom_1108_PVROverlay.xml b/addons/skin.estuary/1080i/Custom_1108_PVROverlay.xml
index 78f0dcd..6fd834a 100644
--- a/addons/skin.estuary/1080i/Custom_1108_PVROverlay.xml
+++ b/addons/skin.estuary/1080i/Custom_1108_PVROverlay.xml
@@ -60,6 +60,7 @@
 			<texturebg border="3" colordiffuse="00FFFFFF">colors/white50.png</texturebg>
 			<midtexture colordiffuse="button_focus">colors/white50.png</midtexture>
 			<animation effect="fade" start="100" end="80" time="0" condition="true">Conditional</animation>
+			<visible>!Player.ChannelPreviewActive</visible>
 		</control>
 		<control type="progress" id="23">
 			<animation effect="fade" end="0" time="200">WindowClose</animation>
@@ -70,6 +71,7 @@
 			<info>Player.Progress</info>
 			<texturebg border="3" colordiffuse="80FFFFFF">colors/white50.png</texturebg>
 			<midtexture colordiffuse="button_focus">colors/white50.png</midtexture>
+			<visible>!Player.ChannelPreviewActive | VideoPlayer.HasEpg</visible>
 		</control>
 		<control type="label">
 			<left>530</left>
@@ -78,6 +80,7 @@
 			<height>25</height>
 			<label>[COLOR button_focus]$INFO[VideoPlayer.NextStartTime]$INFO[VideoPlayer.NextEndTime, - ,: ][/COLOR]$INFO[VideoPlayer.NextTitle]</label>
 			<aligny>center</aligny>
+			<visible>VideoPlayer.HasEpg</visible>
 		</control>
 		<control type="grouplist">
 			<left>1260</left>
@@ -87,6 +90,7 @@
 			<align>right</align>
 			<orientation>horizontal</orientation>
 			<itemgap>10</itemgap>
+			<visible>!Player.ChannelPreviewActive</visible>
 			<include content="MediaFlag">
 				<param name="texture" value="$INFO[VideoPlayer.AudioChannels,flags/audiochannel/,.png]" />
 			</include>
diff --git a/addons/skin.estuary/1080i/Custom_1109_TopBarOverlay.xml b/addons/skin.estuary/1080i/Custom_1109_TopBarOverlay.xml
index 0b8f3f4..98944f4 100644
--- a/addons/skin.estuary/1080i/Custom_1109_TopBarOverlay.xml
+++ b/addons/skin.estuary/1080i/Custom_1109_TopBarOverlay.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <window type="dialog" id="1109">
-    <visible>Window.IsActive(videoosd) | Window.IsActive(fullscreeninfo) | [Player.ShowInfo + !System.HasModalDialog + VideoPlayer.Content(LiveTV) + Window.IsActive(fullscreenvideo)]</visible>
+    <visible>Window.IsActive(videoosd) | Window.IsActive(fullscreeninfo) | [Window.IsActive(playerprocessinfo) + Window.IsActive(fullscreenvideo)] | [Player.ShowInfo + !System.HasModalDialog + VideoPlayer.Content(LiveTV) + Window.IsActive(fullscreenvideo)]</visible>
     <depth>DepthOSD</depth>
     <animation effect="fade" start="0" end="100" time="100">WindowOpen</animation>
     <animation effect="fade" start="100" end="0" time="100">WindowClose</animation>
@@ -11,7 +11,7 @@
             <control type="image">
                 <left>0</left>
                 <top>0</top>
-                <width>1920</width>
+                <width>100%</width>
                 <height>83</height>
                 <texture>frame/InfoBar.png</texture>
             </control>
@@ -79,6 +79,7 @@
                     <height>100</height>
                     <width>500</width>
                     <align>right</align>
+                    <visible>!VideoPlayer.Content(LiveTV) | VideoPlayer.HasEpg</visible>
                 </control>
             </control>
         </control>
diff --git a/addons/skin.estuary/1080i/DialogAddonInfo.xml b/addons/skin.estuary/1080i/DialogAddonInfo.xml
index 8c15bbd..c840cd4 100644
--- a/addons/skin.estuary/1080i/DialogAddonInfo.xml
+++ b/addons/skin.estuary/1080i/DialogAddonInfo.xml
@@ -7,38 +7,117 @@
 	<controls>
 		<control type="group">
 			<include>OpenClose_Right</include>
-			<control type="button">
-				<left>770</left>
-				<top>162</top>
-				<width>1040</width>
-				<height>559</height>
+			<control type="button" id="5000">
+				<left>605</left>
+				<top>400</top>
+				<width>1235</width>
+				<height>375</height>
 				<label>-</label>
+				<onup>50</onup>
+				<ondown>9000</ondown>
+				<onclick>SetProperty(TextViewer_Header,$LOCALIZE[31141] $INFO[ListItem.AddonVersion],home)</onclick>
+				<onclick>SetProperty(TextViewer_Text,$ESCINFO[ListItem.AddonNews],home)</onclick>
+				<onclick>ActivateWindow(1102)</onclick>
+				<enable>!String.IsEmpty(ListItem.AddonNews)</enable>
 			</control>
 			<control type="textbox">
-				<left>840</left>
-				<top>200</top>
-				<width>900</width>
-				<height>380</height>
+				<left>670</left>
+				<top>435</top>
+				<width>1050</width>
+				<height>300</height>
 				<font>font_textbox</font>
-				<label>$INFO[ListItem.AddonSummary,[B],[/B][CR]][COLOR=white]$INFO[ListItem.AddonDescription][/COLOR][COLOR=white][CR][/COLOR]</label>
+				<label>$INFO[ListItem.AddonSummary,[B],[/B][CR]][COLOR=white]$INFO[ListItem.AddonDescription][/COLOR][COLOR=white][CR][/COLOR]$VAR[AddonNewsVar,[CR][CR]]</label>
 				<textcolor>button_focus</textcolor>
+				<autoscroll delay="5000" repeat="7500" time="5000">true</autoscroll>
 			</control>
-			<control type="textbox">
-				<left>840</left>
-				<top>610</top>
-				<width>900</width>
-				<height>70</height>
-				<font>font_textbox</font>
-				<label fallback="31008">$INFO[ListItem.AddonDisclaimer,$LOCALIZE[24052]: ]</label>
-				<textcolor>button_focus</textcolor>
+			<control type="group">
+				<left>625</left>
+				<top>176</top>
+				<visible>Integer.IsEqual(Container(50).NumItems,0)</visible>
+				<control type="image">
+					<width>385</width>
+					<height>220</height>
+					<texture border="2" background="true">DefaultNoPreview.png</texture>
+					<aspectratio>scale</aspectratio>
+					<bordertexture colordiffuse="border_alpha">colors/black.png</bordertexture>
+					<bordersize>4</bordersize>
+				</control>
+				<control type="image">
+					<left>405</left>
+					<width>385</width>
+					<height>220</height>
+					<texture border="2" background="true">DefaultNoPreview.png</texture>
+					<aspectratio>scale</aspectratio>
+					<bordertexture colordiffuse="border_alpha">colors/black.png</bordertexture>
+					<bordersize>4</bordersize>
+				</control>
+				<control type="image">
+					<left>810</left>
+					<width>385</width>
+					<height>220</height>
+					<texture border="2" background="true">DefaultNoPreview.png</texture>
+					<aspectratio>scale</aspectratio>
+					<bordertexture colordiffuse="border_alpha">colors/black.png</bordertexture>
+					<bordersize>4</bordersize>
+				</control>
 			</control>
-			<control type="image">
-				<left>790</left>
-				<top>600</top>
-				<width>1000</width>
-				<height>3</height>
-				<texture colordiffuse="button_focus" border="2">dialogs/separator-grey.png</texture>
+			<control type="panel" id="50">
+				<left>625</left>
+				<top>176</top>
+				<width>1215</width>
+				<height>233</height>
+				<ondown>5000</ondown>
+				<onup>9000</onup>
+				<orientation>horizontal</orientation>
+				<itemlayout height="225" width="405">
+					<control type="image">
+						<width>385</width>
+						<height>220</height>
+						<texture border="2" background="true">DefaultNoPreview.png</texture>
+						<aspectratio>scale</aspectratio>
+						<bordertexture colordiffuse="border_alpha">colors/black.png</bordertexture>
+						<bordersize>4</bordersize>
+					</control>
+					<control type="image">
+						<width>385</width>
+						<height>220</height>
+						<texture border="2" background="true">$INFO[ListItem.Icon]</texture>
+						<aspectratio>scale</aspectratio>
+						<bordertexture colordiffuse="border_alpha">colors/black.png</bordertexture>
+						<bordersize>4</bordersize>
+					</control>
+				</itemlayout>
+				<focusedlayout height="225" width="405">
+					<control type="image">
+						<width>385</width>
+						<height>220</height>
+						<texture border="2" background="true">DefaultNoPreview.png</texture>
+						<aspectratio>scale</aspectratio>
+						<bordertexture colordiffuse="border_alpha">colors/black.png</bordertexture>
+						<bordersize>4</bordersize>
+					</control>
+					<control type="image">
+						<width>385</width>
+						<height>220</height>
+						<texture border="2" background="true">$INFO[ListItem.Icon]</texture>
+						<aspectratio>scale</aspectratio>
+						<bordertexture colordiffuse="border_alpha">colors/black.png</bordertexture>
+						<bordersize>4</bordersize>
+					</control>
+					<control type="image">
+						<width>385</width>
+						<height>220</height>
+						<texture border="8" colordiffuse="button_focus">buttons/thumbnail_focused.png</texture>
+					</control>
+				</focusedlayout>
 			</control>
+			<include content="LeftRightArrows">
+				<param name="list_id" value="50" />
+				<param name="left_posx" value="580" />
+				<param name="right_posx" value="1840" />
+				<param name="posy" value="280" />
+				<param name="visible" value="true" />
+			</include>
 			<control type="grouplist" id="9000">
 				<left>90</left>
 				<top>820</top>
@@ -46,7 +125,7 @@
 				<height>300</height>
 				<onleft>9000</onleft>
 				<onright>9000</onright>
-				<onup>9000</onup>
+				<onup>5000</onup>
 				<ondown>9000</ondown>
 				<align>center</align>
 				<itemgap>-18</itemgap>
@@ -97,11 +176,11 @@
 		</control>
 		<control type="group">
 			<include>OpenClose_Left</include>
-			<left>120</left>
+			<top>158</top>
+			<left>80</left>
 			<control type="image">
-				<top>162</top>
-				<width>559</width>
-				<height>559</height>
+				<width>505</width>
+				<height>505</height>
 				<aspectratio>scale</aspectratio>
 				<texture colordiffuse="border_alpha">colors/black.png</texture>
 				<bordertexture border="20">overlays/shadow.png</bordertexture>
@@ -109,13 +188,30 @@
 			</control>
 			<control type="image">
 				<left>24</left>
-				<top>186</top>
-				<width>511</width>
-				<height>511</height>
+				<top>24</top>
+				<width>457</width>
+				<height>457</height>
 				<aspectratio aligny="top">scale</aspectratio>
 				<fadetime>300</fadetime>
 				<texture background="true" fallback="DefaultFolderSquare.png">$INFO[ListItem.Art(thumb)]</texture>
 			</control>
+			<control type="button">
+				<left>-3</left>
+				<top>490</top>
+				<width>511</width>
+				<height>128</height>
+				<label>-</label>
+			</control>
+			<control type="textbox">
+				<left>30</left>
+				<top>515</top>
+				<width>446</width>
+				<height>80</height>
+				<font>font_textbox</font>
+				<label fallback="31008">$INFO[ListItem.AddonDisclaimer,$LOCALIZE[24052]: ]</label>
+				<textcolor>button_focus</textcolor>
+				<autoscroll time="2000" delay="3000" repeat="5000">true</autoscroll>
+			</control>
 			<control type="group">
 				<visible>!String.IsEmpty(ListItem.AddonBroken)</visible>
 				<include>OpenClose_Fade</include>
diff --git a/addons/skin.estuary/1080i/DialogExtendedProgressBar.xml b/addons/skin.estuary/1080i/DialogExtendedProgressBar.xml
index 1d90905..ebc905b 100644
--- a/addons/skin.estuary/1080i/DialogExtendedProgressBar.xml
+++ b/addons/skin.estuary/1080i/DialogExtendedProgressBar.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <window>
-	<defaultcontrol />
 	<zorder>3</zorder>
 	<animation effect="fade" start="0" end="100" time="300">WindowOpen</animation>
 	<animation effect="fade" start="100" end="0" time="200">WindowClose</animation>
@@ -9,6 +8,7 @@
 			<depth>DepthBars</depth>
 			<left>1830</left>
 			<top>0</top>
+			<animation effect="slide" end="0,-90" time="300" tween="sine" easing="inout" condition="$EXP[infodialog_active]">conditional</animation>
 			<animation effect="slide" end="0,-80" time="150" condition="Window.IsVisible(FullscreenVideo)">conditional</animation>
 			<control type="image">
 				<left>-4</left>
diff --git a/addons/skin.estuary/1080i/DialogFullScreenInfo.xml b/addons/skin.estuary/1080i/DialogFullScreenInfo.xml
index 6e51d46..ef1644f 100644
--- a/addons/skin.estuary/1080i/DialogFullScreenInfo.xml
+++ b/addons/skin.estuary/1080i/DialogFullScreenInfo.xml
@@ -8,7 +8,7 @@
 			<description>background close area</description>
 			<left>0</left>
 			<top>0</top>
-			<width>1920</width>
+			<width>100%</width>
 			<height>800</height>
 			<texturefocus>-</texturefocus>
 			<texturenofocus>-</texturenofocus>
@@ -16,6 +16,8 @@
 		</control>
 		<control type="group">
 			<top>912</top>
+			<visible>!Window.IsVisible(playerprocessinfo)</visible>
+			<animation effect="fade" time="200">VisibleChange</animation>
 			<control type="image">
 				<left>10</left>
 				<top>-240</top>
@@ -49,7 +51,7 @@
 				<align>left</align>
 				<orientation>horizontal</orientation>
 				<itemgap>10</itemgap>
-				<visible>Control.HasFocus(5552)</visible>
+				<visible>Control.HasFocus(5552) + !Player.ChannelPreviewActive</visible>
 				<include content="MediaFlag">
 					<param name="texture" value="$INFO[VideoPlayer.AudioChannels,flags/audiochannel/,.png]" />
 				</include>
@@ -233,7 +235,7 @@
 				<control type="label">
 					<left>250</left>
 					<top>940</top>
-					<width>1920</width>
+					<width>100%</width>
 					<height>100</height>
 					<font>font16</font>
 					<shadowcolor>text_shadow</shadowcolor>
diff --git a/addons/skin.estuary/1080i/DialogPVRInfo.xml b/addons/skin.estuary/1080i/DialogPVRInfo.xml
index 51aaf52..90a997d 100644
--- a/addons/skin.estuary/1080i/DialogPVRInfo.xml
+++ b/addons/skin.estuary/1080i/DialogPVRInfo.xml
@@ -6,8 +6,8 @@
 	<controls>
 		<control type="image">
 			<texture fallback="special://skin/extras/backgrounds/SKINDEFAULT.jpg">$VAR[GlobalFanartVar]</texture>
-			<width>1920</width>
-			<height>1080</height>
+			<width>100%</width>
+			<height>100%</height>
 			<aspectratio align="center">scale</aspectratio>
 			<animation effect="fade" start="0" end="100" time="100">WindowOpen</animation>
 			<animation effect="fade" start="100" end="0" time="100">WindowClose</animation>
diff --git a/addons/skin.estuary/1080i/DialogPlayerProcessInfo.xml b/addons/skin.estuary/1080i/DialogPlayerProcessInfo.xml
new file mode 100644
index 0000000..a608e33
--- /dev/null
+++ b/addons/skin.estuary/1080i/DialogPlayerProcessInfo.xml
@@ -0,0 +1,262 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<window>
+	<defaultcontrol always="true">5550</defaultcontrol>
+	<animation effect="fade" start="0" end="100" time="300">WindowOpen</animation>
+	<animation effect="fade" start="100" end="0" time="200">WindowClose</animation>
+	<controls>
+		<control type="group">
+			<top>912</top>
+			<control type="image">
+				<left>10</left>
+				<top>-240</top>
+				<width>1902</width>
+				<height>400</height>
+				<texture border="40">buttons/dialogbutton-nofo.png</texture>
+			</control>
+			<control type="grouplist">
+				<left>52</left>
+				<top>-204</top>
+				<visible>Control.HasFocus(5551)</visible>
+				<control type="label">
+					<width>1200</width>
+					<height>50</height>
+					<aligny>bottom</aligny>
+					<label>$INFO[PVR.ActStreamServiceName,[COLOR button_focus]$LOCALIZE[19099]:[/COLOR] ]</label>
+					<font>font14</font>
+					<shadowcolor>black</shadowcolor>
+				</control>
+				<control type="label">
+					<width>1200</width>
+					<height>50</height>
+					<aligny>bottom</aligny>
+					<label>$INFO[PVR.ActStreamProviderName,[COLOR button_focus]$LOCALIZE[19101]:[/COLOR] ]</label>
+					<font>font14</font>
+					<shadowcolor>black</shadowcolor>
+				</control>
+				<control type="label">
+					<width>1200</width>
+					<height>50</height>
+					<aligny>bottom</aligny>
+					<label>$INFO[PVR.ActStreamClient,[COLOR button_focus]$LOCALIZE[19012]:[/COLOR] ]</label>
+					<font>font14</font>
+					<shadowcolor>black</shadowcolor>
+				</control>
+				<control type="label">
+					<width>1200</width>
+					<height>50</height>
+					<aligny>bottom</aligny>
+					<label>$INFO[PVR.ActStreamDevice,[COLOR button_focus]$LOCALIZE[19006]:[/COLOR] ]</label>
+					<font>font14</font>
+					<shadowcolor>black</shadowcolor>
+				</control>
+				<control type="label">
+					<width>1200</width>
+					<height>50</height>
+					<aligny>bottom</aligny>
+					<label>$INFO[PVR.ActStreamStatus,[COLOR button_focus]$LOCALIZE[19007]:[/COLOR] ]</label>
+					<font>font14</font>
+					<shadowcolor>black</shadowcolor>
+				</control>
+				<control type="label">
+					<width>1200</width>
+					<height>50</height>
+					<aligny>bottom</aligny>
+					<label>$INFO[PVR.ActStreamEncryptionName,[COLOR button_focus]$LOCALIZE[19015]:[/COLOR] ]</label>
+					<font>font14</font>
+					<shadowcolor>black</shadowcolor>
+				</control>
+			</control>
+			<control type="grouplist">
+				<left>1250</left>
+				<top>-204</top>
+				<visible>Control.HasFocus(5551)</visible>
+				<usecontrolcoords>true</usecontrolcoords>
+				<control type="label">
+					<width>600</width>
+					<height>50</height>
+					<aligny>bottom</aligny>
+					<label>$INFO[PVR.ActStreamBer,[COLOR button_focus]$LOCALIZE[19010]:[/COLOR] ]</label>
+					<font>font14</font>
+					<shadowcolor>black</shadowcolor>
+				</control>
+				<control type="label">
+					<width>600</width>
+					<height>50</height>
+					<aligny>bottom</aligny>
+					<label>$INFO[PVR.ActStreamUnc,[COLOR button_focus]$LOCALIZE[19011]:[/COLOR] ]</label>
+					<font>font14</font>
+					<shadowcolor>black</shadowcolor>
+				</control>
+				<control type="label">
+					<width>600</width>
+					<height>50</height>
+					<aligny>bottom</aligny>
+					<label>$INFO[PVR.ActStreamMux,[COLOR button_focus]$LOCALIZE[19100]:[/COLOR] ]</label>
+					<font>font14</font>
+					<shadowcolor>black</shadowcolor>
+				</control>
+				<control type="label">
+					<width>600</width>
+					<height>50</height>
+					<aligny>bottom</aligny>
+					<label>$INFO[PVR.ActStreamSignal,[COLOR button_focus]$LOCALIZE[19008]:[/COLOR] ]</label>
+					<font>font14</font>
+					<shadowcolor>black</shadowcolor>
+				</control>
+				<control type="progress">
+					<top>5</top>
+					<width>600</width>
+					<height>18</height>
+					<info>PVR.ActStreamProgrSignal</info>
+				</control>
+				<control type="label">
+					<top>5</top>
+					<width>1600</width>
+					<height>50</height>
+					<aligny>bottom</aligny>
+					<label>$INFO[PVR.ActStreamSNR,[COLOR button_focus]$LOCALIZE[19009]:[/COLOR] ]</label>
+					<font>font14</font>
+					<shadowcolor>black</shadowcolor>
+				</control>
+				<control type="progress">
+					<top>0</top>
+					<width>600</width>
+					<height>18</height>
+					<info>PVR.ActStreamProgrSNR</info>
+				</control>
+			</control>
+			<control type="grouplist">
+				<left>52</left>
+				<top>-204</top>
+				<visible>Control.HasFocus(5552)</visible>
+				<control type="label">
+					<width>1600</width>
+					<height>50</height>
+					<aligny>bottom</aligny>
+					<label>$INFO[Player.Process(videodecoder),[COLOR button_focus]$LOCALIZE[31139]:[/COLOR] ]$VAR[VideoHWDecoder, (,)]</label>
+					<font>font14</font>
+					<shadowcolor>black</shadowcolor>
+					<visible>Player.HasVideo</visible>					
+				</control>
+				<control type="label">
+					<width>1600</width>
+					<height>50</height>
+					<aligny>bottom</aligny>
+					<label>$INFO[Player.Process(pixformat),[COLOR button_focus]$LOCALIZE[31140]:[/COLOR] ]</label>
+					<font>font14</font>
+					<shadowcolor>black</shadowcolor>
+					<visible>Player.HasVideo</visible>					
+				</control>
+				<control type="label">
+					<width>1600</width>
+					<height>50</height>
+					<aligny>bottom</aligny>
+					<label>$INFO[Player.Process(deintmethod),[COLOR button_focus]$LOCALIZE[16038]:[/COLOR] ]</label>
+					<font>font14</font>
+					<shadowcolor>black</shadowcolor>
+					<visible>Player.HasVideo</visible>					
+				</control>
+				<control type="label">
+					<width>1600</width>
+					<height>50</height>
+					<aligny>bottom</aligny>
+					<label>$INFO[Player.Process(videowidth),[COLOR button_focus]$LOCALIZE[38031]:[/COLOR] ,x]$INFO[Player.Process(videoheight),, px]$INFO[Player.Process(videodar),$COMMA , AR]$INFO[Player.Process(videofps),$COMMA , FPS]</label>
+					<font>font14</font>
+					<shadowcolor>black</shadowcolor>
+					<visible>Player.HasVideo</visible>					
+				</control>
+				<control type="label">
+					<width>1600</width>
+					<height>50</height>
+					<aligny>bottom</aligny>
+					<label>[COLOR button_focus]$LOCALIZE[460]:[/COLOR] $INFO[Player.Process(audiochannels),,$COMMA ]$INFO[Player.Process(audiodecoder)]$INFO[Player.Process(audiobitspersample),$COMMA , bits]$INFO[Player.Process(audiosamplerate),$COMMA , Hz]</label>
+					<font>font14</font>
+					<shadowcolor>black</shadowcolor>
+				</control>
+				<control type="label">
+					<width>1600</width>
+					<height>50</height>
+					<aligny>bottom</aligny>
+					<label>$INFO[System.Memory(used.percent),[COLOR button_focus]$LOCALIZE[31030]:[/COLOR] ,       ]$INFO[System.CpuUsage,[COLOR button_focus]$LOCALIZE[13271][/COLOR] ]</label>
+					<font>font14</font>
+					<shadowcolor>black</shadowcolor>
+				</control>
+			</control>
+			<control type="grouplist" id="5550">
+				<right>15</right>
+				<top>-310</top>
+				<width>1000</width>
+				<height>100</height>
+				<align>right</align>
+				<orientation>horizontal</orientation>
+				<itemgap>-10</itemgap>
+				<onup>Close</onup>
+				<ondown>Close</ondown>
+				<usecontrolcoords>true</usecontrolcoords>
+				<control type="button" id="5551">
+					<width>auto</width>
+					<height>100</height>
+					<textoffsetx>40</textoffsetx>
+					<label>$LOCALIZE[31137]</label>
+					<visible>VideoPlayer.Content(livetv)</visible>
+				</control>
+				<control type="button" id="5552">
+					<width>auto</width>
+					<height>100</height>
+					<textoffsetx>40</textoffsetx>
+					<label>$LOCALIZE[31138]</label>
+				</control>
+			</control>
+			<!-- Progress -->
+			<control type="group">
+				<top>119</top>
+				<control type="progress">
+					<animation effect="fade" end="0" time="200">WindowClose</animation>
+					<left>29</left>
+					<top>-10</top>
+					<width>1862</width>
+					<height>30</height>
+					<info>Player.ProgressCache</info>
+					<texturebg border="3" colordiffuse="00FFFFFF">colors/white50.png</texturebg>
+					<midtexture colordiffuse="button_focus">colors/white50.png</midtexture>
+					<animation effect="fade" start="100" end="80" time="0" condition="true">Conditional</animation>
+				</control>
+				<control type="progress" id="23">
+					<animation effect="fade" end="0" time="200">WindowClose</animation>
+					<left>29</left>
+					<top>-10</top>
+					<width>1862</width>
+					<height>30</height>
+					<info>Player.Progress</info>
+					<texturebg border="3" colordiffuse="80FFFFFF">colors/white50.png</texturebg>
+					<midtexture colordiffuse="button_focus">colors/white50.png</midtexture>
+				</control>
+				<control type="button" id="87">
+					<include>HiddenObject</include>
+					<onup condition="Player.Forwarding | Player.Rewinding">PlayerControl(Play)</onup>
+					<onup>201</onup>
+					<ondown condition="Player.Forwarding | Player.Rewinding">PlayerControl(Play)</ondown>
+					<ondown>201</ondown>
+					<onright>PlayerControl(Forward)</onright>
+					<onleft>PlayerControl(Rewind)</onleft>
+					<visible>Player.SeekEnabled</visible>
+					<onclick condition="Player.Forwarding | Player.Rewinding">PlayerControl(Play)</onclick>
+				</control>
+				<control type="slider">
+					<left>29</left>
+					<top>-10</top>
+					<width>1862</width>
+					<height>30</height>
+					<onup>8010</onup>
+					<ondown>650</ondown>
+					<texturesliderbar colordiffuse="00FFFFFF">osd/progress/nub_bar.png</texturesliderbar>
+					<textureslidernib>osd/progress/nub_bar.png</textureslidernib>
+					<textureslidernibfocus colordiffuse="button_focus">osd/progress/nub_bar.png</textureslidernibfocus>
+					<info>Player.Progress</info>
+					<action>seek</action>
+					<visible>!Control.HasFocus(87)</visible>
+				</control>
+			</control>
+		</control>
+	</controls>
+</window>
diff --git a/addons/skin.estuary/1080i/EventLog.xml b/addons/skin.estuary/1080i/EventLog.xml
index a83bca5..09e5b18 100644
--- a/addons/skin.estuary/1080i/EventLog.xml
+++ b/addons/skin.estuary/1080i/EventLog.xml
@@ -20,10 +20,11 @@
 				<control type="togglebutton" id="4">
 					<width>420</width>
 					<height>110</height>
-					<align>center</align>
+					<align>left</align>
 					<aligny>top</aligny>
 					<font>font12</font>
-					<textoffsetx>20</textoffsetx>
+					<textoffsetx>100</textoffsetx>
+					<textwidth>300</textwidth>
 					<textoffsety>35</textoffsety>
 					<label>$LOCALIZE[31032]: $LOCALIZE[584]</label>
 					<altlabel>$LOCALIZE[31032]: $LOCALIZE[585]</altlabel>
@@ -48,11 +49,12 @@
 				<control type="radiobutton" id="22">
 					<width>420</width>
 					<height>110</height>
-					<align>center</align>
+					<align>left</align>
 					<aligny>top</aligny>
 					<font>font12</font>
-					<textoffsetx>20</textoffsetx>
+					<textoffsetx>100</textoffsetx>
 					<textoffsety>35</textoffsety>
+					<textwidth>300</textwidth>
 					<radioposx>-1</radioposx>
 				</control>
 				<include content="PlaylistWindowButton">
diff --git a/addons/skin.estuary/1080i/Home.xml b/addons/skin.estuary/1080i/Home.xml
index 298e2ca..6653180 100644
--- a/addons/skin.estuary/1080i/Home.xml
+++ b/addons/skin.estuary/1080i/Home.xml
@@ -690,7 +690,7 @@
 							<param name="item3_onclick" value="Weather.LocationNext" />
 							<param name="item3_icon" value="location-next.png" />
 							<param name="item3_label" value="$LOCALIZE[31078]" />
-							<param name="item4_onclick" value="ActivateWindow(weathersettings)" />
+							<param name="item4_onclick" value="ActivateWindow(servicesettings,weather)" />
 							<param name="item4_icon" value="weather-settings.png" />
 							<param name="item4_label" value="$LOCALIZE[1390]" />
 							<param name="item5_vis" value="False" />
@@ -794,7 +794,7 @@
 							<param name="image_path" value="special://skin/extras/home-images/weather.jpg"/>
 							<param name="text_label" value="$LOCALIZE[31120]" />
 							<param name="button_label" value="$LOCALIZE[31121]" />
-							<param name="button_onclick" value="ActivateWindow(weathersettings)"/>
+							<param name="button_onclick" value="ActivateWindow(servicesettings,weather)"/>
 							<param name="button_id" value="15300"/>
 							<param name="visible" value="String.IsEmpty(Weather.plugin)"/>
 							<param name="button2_onclick" value="Skin.SetBool(HomeMenuNoWeatherButton)"/>
@@ -1106,21 +1106,25 @@
 						<param name="control_id" value="804" />
 						<param name="onclick" value="ActivateWindow(shutdownmenu)" />
 						<param name="icon" value="icons/power.png" />
+						<param name="label" value="$LOCALIZE[33060]" />
 					</include>
 					<include content="BottomMainMenuItem">
 						<param name="control_id" value="802" />
 						<param name="onclick" value="ActivateWindow(settings)" />
 						<param name="icon" value="icons/settings.png" />
+						<param name="label" value="$LOCALIZE[21417]" />
 					</include>
 					<include content="BottomMainMenuItem">
 						<param name="control_id" value="803" />
 						<param name="onclick" value="ActivateWindow(favourites)" />
 						<param name="icon" value="icons/favourites.png" />
+						<param name="label" value="$LOCALIZE[10134]" />
 					</include>
 					<include content="BottomMainMenuItem">
 						<param name="control_id" value="801" />
 						<param name="onclick" value="ActivateWindow(filemanager)" />
 						<param name="icon" value="icons/filemanager.png" />
+						<param name="label" value="$LOCALIZE[10003]" />
 					</include>
 				</control>
 			</control>
@@ -1157,7 +1161,7 @@
 					<left>0</left>
 					<top>1041</top>
 					<height>30</height>
-					<width>1920</width>
+					<width>100%</width>
 					<font>font12</font>
 					<urlset>1</urlset>
 					<titlecolor>button_focus</titlecolor>
diff --git a/addons/skin.estuary/1080i/Includes.xml b/addons/skin.estuary/1080i/Includes.xml
index 6f21c32..8e9d36e 100644
--- a/addons/skin.estuary/1080i/Includes.xml
+++ b/addons/skin.estuary/1080i/Includes.xml
@@ -27,7 +27,7 @@
 	<constant name="DepthBackground">-0.80</constant>
 	<constant name="DepthSideBlade">0.10</constant>
 	<constant name="bg_alpha">79</constant>
-	<expression name="infodialog_active">Window.IsActive(musicinformation) | Window.IsActive(movieinformation) | Window.IsActive(addoninformation) | Window.IsActive(pvrguideinfo) | Window.IsActive(pvrrecordinginfo) | Window.IsActive(pictureinfo) | Window.IsVisible(script-script.extendedinfo-DialogVideoInfo.xml) | Window.IsVisible(script-script.extendedinfo-DialogInfo.xml) | Window.IsVisible(script-script.extendedinfo-VideoList.xml)</expression>
+	<expression name="infodialog_active">Window.IsActive(musicinformation) | Window.IsActive(songinformation) | Window.IsActive(movieinformation) | Window.IsActive(addoninformation) | Window.IsActive(pvrguideinfo) | Window.IsActive(pvrrecordinginfo) | Window.IsActive(pictureinfo) | Window.IsVisible(script-script.extendedinfo-DialogVideoInfo.xml) | Window.IsVisible(script-script.extendedinfo-DialogInfo.xml) | Window.IsVisible(script-script.extendedinfo-VideoList.xml)</expression>
 	<expression name="sidebar_focused">ControlGroup(9000).HasFocus | Control.HasFocus(6130)</expression>
 	<include name="CommonScrollbars">
 		<control type="group">
@@ -35,7 +35,7 @@
 			<animation effect="fade" start="100" end="0" time="200" tween="sine" condition="System.HasModalDialog">Conditional</animation>
 			<animation effect="fade" start="0" end="100" delay="300" time="320">WindowOpen</animation>
 			<control type="scrollbar" id="531">
-				<left>1907</left>
+				<right>0</right>
 				<top>80</top>
 				<width>13</width>
 				<height>919</height>
@@ -50,7 +50,7 @@
 			<control type="scrollbar" id="5199">
 				<left>0</left>
 				<top>988</top>
-				<width>1920</width>
+				<width>100%</width>
 				<height>12</height>
 				<texturesliderbackground colordiffuse="22FFFFFF">colors/white.png</texturesliderbackground>
 				<onup>50</onup>
@@ -880,7 +880,7 @@
 				<control type="image">
 					<left>0</left>
 					<top>0</top>
-					<width>2000</width>
+					<width>110%</width>
 					<height>83</height>
 					<texture>frame/InfoBar.png</texture>
 					<animation effect="fade" start="100" end="0" time="300" condition="Window.Next(screencalibration)">WindowClose</animation>
@@ -925,7 +925,7 @@
 						<label>$INFO[Container.FolderName, / ]</label>
 						<include>BreadcrumbsLabel</include>
 						<visible>![Container.Content() + Window.IsActive(videos)]</visible>
-						<visible>![Window.IsActive(PVR) | Window.IsActive(MyPVRTimers.xml)]</visible>
+						<visible>![Window.IsActive(MyPVRChannels.xml) | Window.IsActive(MyPVRTimers.xml)]</visible>
 					</control>
 					<control type="label">
 						<label>$INFO[Container.PluginCategory, / ]</label>
@@ -990,7 +990,7 @@
 							<top>40</top>
 							<label>$PARAM[time_sublabel]</label>
 							<font>font10</font>
-							<left>1340</left>
+							<right>85</right>
 							<shadowcolor>text_shadow</shadowcolor>
 							<height>100</height>
 							<width>500</width>
@@ -1077,7 +1077,7 @@
 				<control type="image">
 					<left>0</left>
 					<top>995</top>
-					<width>2000</width>
+					<width>110%</width>
 					<height>85</height>
 					<texture flipy="true">frame/InfoBar.png</texture>
 				</control>
@@ -1296,7 +1296,7 @@
 	<include name="FullScreenDimensions">
 		<left>0</left>
 		<top>0</top>
-		<width>1920</width>
-		<height>1080</height>
+		<width>100%</width>
+		<height>100%</height>
 	</include>
 </includes>
diff --git a/addons/skin.estuary/1080i/Includes_Buttons.xml b/addons/skin.estuary/1080i/Includes_Buttons.xml
index 99ca474..552e52e 100644
--- a/addons/skin.estuary/1080i/Includes_Buttons.xml
+++ b/addons/skin.estuary/1080i/Includes_Buttons.xml
@@ -129,7 +129,7 @@
 				<aligny>top</aligny>
 				<font>font10</font>
 				<textoffsetx>100</textoffsetx>
-				<textwidth>200</textwidth>
+				<textwidth>300</textwidth>
 				<textoffsety>35</textoffsety>
 				<label>$PARAM[label]</label>
 				<selectedcolor>white</selectedcolor>
@@ -203,6 +203,7 @@
 				<aligny>center</aligny>
 				<onclick>$PARAM[onclick]</onclick>
 				<font>-</font>
+				<label>$PARAM[label]</label>
 				<texturefocus border="40" colordiffuse="button_focus">buttons/button-fo.png</texturefocus>
 				<texturenofocus border="40">buttons/button-nofo.png</texturenofocus>
 				<radioposx>38</radioposx>
diff --git a/addons/skin.estuary/1080i/Includes_MediaMenu.xml b/addons/skin.estuary/1080i/Includes_MediaMenu.xml
index 9634a6e..667c2a8 100644
--- a/addons/skin.estuary/1080i/Includes_MediaMenu.xml
+++ b/addons/skin.estuary/1080i/Includes_MediaMenu.xml
@@ -53,7 +53,7 @@
 				<top>90</top>
 				<left>0</left>
 				<width>430</width>
-				<height>1080</height>
+				<height>100%</height>
 				<onleft>9000</onleft>
 				<onup>9000</onup>
 				<onright>50</onright>
@@ -319,7 +319,7 @@
 			<left>0</left>
 			<top>100</top>
 			<width>430</width>
-			<height>1080</height>
+			<height>100%</height>
 			<onleft>9000</onleft>
 			<onup>9000</onup>
 			<onright>50</onright>
@@ -370,7 +370,7 @@
 	<include name="MediaMenuMouseOverlay">
 		<control type="button" id="6130">
 			<label>-</label>
-			<height>1080</height>
+			<height>100%</height>
 			<width>50</width>
 			<left>-50</left>
 			<top>0</top>
diff --git a/addons/skin.estuary/1080i/MusicOSD.xml b/addons/skin.estuary/1080i/MusicOSD.xml
index 46b8ee8..3b8a106 100644
--- a/addons/skin.estuary/1080i/MusicOSD.xml
+++ b/addons/skin.estuary/1080i/MusicOSD.xml
@@ -6,7 +6,7 @@
 			<description>background close area</description>
 			<left>0</left>
 			<top>0</top>
-			<width>1920</width>
+			<width>100%</width>
 			<height>900</height>
 			<texturefocus>-</texturefocus>
 			<texturenofocus>-</texturenofocus>
@@ -14,14 +14,14 @@
 		</control>
 		<control type="group">
 			<top>900</top>
-			<visible>!Window.IsActive(osdaudiosettings) + !Window.IsActive(osdvideosettings)</visible>
+			<visible>!Window.IsActive(osdaudiosettings) + !Window.IsActive(osdvideosettings) + !Window.IsActive(playerprocessinfo)</visible>
 			<animation effect="fade" end="100" time="200">WindowOpen</animation>
 			<animation effect="fade" time="200">VisibleChange</animation>
 			<animation effect="fade" start="100" end="0" time="200">WindowClose</animation>
 			<control type="grouplist" id="201">
 				<left>50</left>
 				<top>10</top>
-				<width>1920</width>
+				<width>100%</width>
 				<height>135</height>
 				<align>left</align>
 				<itemgap>-20</itemgap>
@@ -154,18 +154,6 @@
 				</control>
 			</control>
 			<control type="label">
-				<left>30</left>
-				<top>40</top>
-				<width>1858</width>
-				<height>75</height>
-				<align>center</align>
-				<aligny>bottom</aligny>
-				<label>$INFO[Player.Time]$INFO[Player.Duration, / ]</label>
-				<font>font30</font>
-				<shadowcolor>black</shadowcolor>
-				<textcolor>white</textcolor>
-			</control>
-			<control type="label">
 				<right>30</right>
 				<top>-90</top>
 				<textoffsetx>20</textoffsetx>
diff --git a/addons/skin.estuary/1080i/MusicVisualisation.xml b/addons/skin.estuary/1080i/MusicVisualisation.xml
index a158e95..8843b12 100644
--- a/addons/skin.estuary/1080i/MusicVisualisation.xml
+++ b/addons/skin.estuary/1080i/MusicVisualisation.xml
@@ -10,8 +10,8 @@
 		<control type="image">
 			<left>0</left>
 			<top>0</top>
-			<width>1920</width>
-			<height>1080</height>
+			<width>100%</width>
+			<height>100%</height>
 			<aspectratio>scale</aspectratio>
 			<fadetime>400</fadetime>
 			<animation effect="fade" start="0" end="100" time="400">WindowOpen</animation>
@@ -20,8 +20,8 @@
 		</control>
 		<control type="image">
 			<texture fallback="special://skin/extras/backgrounds/SKINDEFAULT.jpg">$VAR[GlobalFanartVar]</texture>
-			<width>1920</width>
-			<height>1080</height>
+			<width>100%</width>
+			<height>100%</height>
 			<aspectratio align="center">scale</aspectratio>
 			<animation effect="fade" start="100" end="50" time="0" condition="!String.IsEmpty(Player.Art(fanart)) | !String.IsEmpty(Visualisation.Name)">Conditional</animation>
 		</control>
@@ -40,7 +40,7 @@
 		</control>
 		<control type="group">
 			<top>-30</top>
-			<visible>Player.ShowInfo | Window.IsActive(musicosd)</visible>
+			<visible>[Player.ShowInfo | Window.IsActive(musicosd)] + !Window.IsActive(playerprocessinfo)</visible>
 			<include>OpenClose_Right</include>
 			<include>Visible_Right</include>
 			<control type="image">
@@ -124,6 +124,7 @@
 					<height>99</height>
 					<texture colordiffuse="grey" fallback="empty.png">$INFO[MusicPlayer.Codec,flags/audiocodec/,.png]</texture>
 					<aspectratio>keep</aspectratio>
+					<visible>!Player.ChannelPreviewActive</visible>
 				</control>
 				<control type="image">
 					<left>280</left>
@@ -135,8 +136,8 @@
 				</control>
 			</control>
 			<control type="label">
-				<left>1840</left>
-				<top>834</top>
+				<left>1450</left>
+				<top>720</top>
 				<width>400</width>
 				<height>45</height>
 				<align>right</align>
@@ -158,6 +159,7 @@
 				<texturebg border="3" colordiffuse="00FFFFFF">colors/white50.png</texturebg>
 				<midtexture colordiffuse="button_focus">colors/white50.png</midtexture>
 				<animation effect="fade" start="100" end="80" time="0" condition="true">Conditional</animation>
+				<visible>!Player.ChannelPreviewActive</visible>
 			</control>
 			<control type="progress" id="23">
 				<animation effect="fade" end="0" time="200">WindowClose</animation>
@@ -168,6 +170,7 @@
 				<info>Player.Progress</info>
 				<texturebg border="3" colordiffuse="80FFFFFF">colors/white50.png</texturebg>
 				<midtexture colordiffuse="button_focus">colors/white50.png</midtexture>
+				<visible>!Player.ChannelPreviewActive | VideoPlayer.HasEpg</visible>
 			</control>
 		</control>
 		<control type="group">
diff --git a/addons/skin.estuary/1080i/MyPVRChannels.xml b/addons/skin.estuary/1080i/MyPVRChannels.xml
index f457bb6..35874c7 100644
--- a/addons/skin.estuary/1080i/MyPVRChannels.xml
+++ b/addons/skin.estuary/1080i/MyPVRChannels.xml
@@ -189,12 +189,12 @@
 							<width>50</width>
 							<height>12</height>
 							<midtexture border="3">progress/texturebg_white.png</midtexture>
-							<visible>ListItem.HasEpg + !ListItem.IsRecording</visible>
+							<visible>ListItem.HasEpg</visible>
 							<info>ListItem.Progress</info>
 						</control>
 						<control type="image">
-							<left>945</left>
-							<top>9</top>
+							<left>870</left>
+							<top>20</top>
 							<width>40</width>
 							<height>40</height>
 							<texture>$VAR[PVRStatusImageVar]</texture>
@@ -254,12 +254,12 @@
 							<width>50</width>
 							<height>12</height>
 							<colordiffuse>88FFFFFF</colordiffuse>
-							<visible>ListItem.HasEpg + !ListItem.IsRecording</visible>
+							<visible>ListItem.HasEpg</visible>
 							<info>ListItem.Progress</info>
 						</control>
 						<control type="image">
-							<left>945</left>
-							<top>9</top>
+							<left>870</left>
+							<top>20</top>
 							<width>40</width>
 							<height>40</height>
 							<texture>$VAR[PVRStatusImageVar]</texture>
diff --git a/addons/skin.estuary/1080i/MyPics.xml b/addons/skin.estuary/1080i/MyPics.xml
index 8b26a4f..1c86222 100644
--- a/addons/skin.estuary/1080i/MyPics.xml
+++ b/addons/skin.estuary/1080i/MyPics.xml
@@ -181,11 +181,11 @@
 					</include>
 					<include content="PicsInfoLine">
 						<param name="label" value="$LOCALIZE[21843]"/>
-						<param name="value" value="$INFO[ListItem.PictureOrientation]" />
+						<param name="value" value="ListItem.PictureOrientation" />
 					</include>
 					<include content="PicsInfoLine">
 						<param name="label" value="$LOCALIZE[21808]"/>
-						<param name="value" value="$INFO[ListItem.PictureProcess]" />
+						<param name="value" value="ListItem.PictureProcess" />
 					</include>
 				</control>
 			</control>
diff --git a/addons/skin.estuary/1080i/MyWeather.xml b/addons/skin.estuary/1080i/MyWeather.xml
index 1d7c91b..8765895 100644
--- a/addons/skin.estuary/1080i/MyWeather.xml
+++ b/addons/skin.estuary/1080i/MyWeather.xml
@@ -6,7 +6,7 @@
 	<controls>
 		<control type="button" id="20000">
 			<include>HiddenObject</include>
-			<onfocus>ActivateWindow(weathersettings)</onfocus>
+			<onfocus>ActivateWindow(servicesettings,weather)</onfocus>
 			<onclick>noop</onclick>
 		</control>
 			<control type="videowindow">
diff --git a/addons/skin.estuary/1080i/Settings.xml b/addons/skin.estuary/1080i/Settings.xml
index 06f9d53..ad1972a 100644
--- a/addons/skin.estuary/1080i/Settings.xml
+++ b/addons/skin.estuary/1080i/Settings.xml
@@ -104,8 +104,8 @@
 					<icon>icons/settings/video.png</icon>
 				</item>
 				<item>
-					<label>$LOCALIZE[14203]</label>
-					<onclick>ActivateWindow(LibrarySettings)</onclick>
+					<label>$LOCALIZE[14212]</label>
+					<onclick>ActivateWindow(MediaSettings)</onclick>
 					<icon>icons/settings/library.png</icon>
 				</item>
 				<item>
diff --git a/addons/skin.estuary/1080i/SettingsCategory.xml b/addons/skin.estuary/1080i/SettingsCategory.xml
index 71b297f..a91ca30 100644
--- a/addons/skin.estuary/1080i/SettingsCategory.xml
+++ b/addons/skin.estuary/1080i/SettingsCategory.xml
@@ -84,10 +84,11 @@
 				<description>control area</description>
 				<left>442</left>
 				<top>160</top>
+				<pagecontrol>60</pagecontrol>
 				<width>1256</width>
 				<height>640</height>
 				<onleft>3</onleft>
-				<onright>3</onright>
+				<onright>60</onright>
 				<onup>5</onup>
 				<ondown>5</ondown>
 			</control>
@@ -150,14 +151,14 @@
 			<param name="down_posy" value="940" />
 			<param name="visible" value="!System.HasModalDialog" />
 		</include>
-		<control type="image">
-			<description>Section header image</description>
-			<left>20</left>
-			<top>3</top>
-			<width>35</width>
-			<height>35</height>
-			<aspectratio>keep</aspectratio>
-			<texture>icon_system.png</texture>
+		<control type="scrollbar" id="60">
+			<right>0</right>
+			<top>80</top>
+			<width>12</width>
+			<height>920</height>
+			<onleft>5</onleft>
+			<onright>5</onright>
+			<orientation>vertical</orientation>
 		</control>
 		<include content="TopBar">
 			<param name="breadcrumbs_label" value="$LOCALIZE[5]$INFO[Control.GetLabel(2), / ]" />
diff --git a/addons/skin.estuary/1080i/SlideShow.xml b/addons/skin.estuary/1080i/SlideShow.xml
index 50b6429..bfe6d61 100644
--- a/addons/skin.estuary/1080i/SlideShow.xml
+++ b/addons/skin.estuary/1080i/SlideShow.xml
@@ -1,5 +1,3 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <window>
-	<defaultcontrol>2</defaultcontrol>
-	<controls />
 </window>
diff --git a/addons/skin.estuary/1080i/Variables.xml b/addons/skin.estuary/1080i/Variables.xml
index a3199e9..a35ba2b 100644
--- a/addons/skin.estuary/1080i/Variables.xml
+++ b/addons/skin.estuary/1080i/Variables.xml
@@ -120,6 +120,7 @@
 		<value>$INFO[ListItem.Art(fanart)]</value>
 	</variable>
 	<variable name="ListBoxInfoVar">
+		<value condition="Stringcompare(Container.FolderPath,addons://outdated/) + !IsEmpty(ListItem.Addonnews)">$INFO[ListItem.Addonnews]</value>
 		<value condition="Container.Content(addons)">$INFO[ListItem.AddonDescription]</value>
 		<value condition="Container.Content(albums)">$INFO[ListItem.Property(album_description)]</value>
 		<value condition="Container.Content(mixed) | Container.Content(videos)">$INFO[ListItem.Genre,[COLOR button_focus]$LOCALIZE[515]: [/COLOR],[CR]]$INFO[ListItem.Plot]</value>
@@ -176,7 +177,7 @@
 		<value condition="!String.IsEmpty(ListItem.Art(tvshow.poster))">$INFO[ListItem.Art(tvshow.poster)]</value>
 	</variable>
 	<variable name="ListPosterVar">
-		<value condition="ListItem.IsParentFolder">DefaultFolderBack.png</value>
+		<value condition="ListItem.IsParentFolder">DefaultFolderBackSquare.png</value>
 		<value>$INFO[ListItem.Art(poster)]</value>
 	</variable>
 	<variable name="BannerLabel2Var">
@@ -214,13 +215,15 @@
 		<value condition="Control.HasFocus(70041)">$LOCALIZE[19069]</value>
 		<value condition="Control.HasFocus(70043)">$LOCALIZE[5]</value>
 		<value condition="Control.HasFocus(255)">$LOCALIZE[36501]</value>
+		<value condition="Control.HasFocus(606)+ Player.Recording">$LOCALIZE[19059]</value>
 		<value condition="Control.HasFocus(606)">$LOCALIZE[264]</value>
 		<value condition="ControlGroup(6000).HasFocus + Player.SeekEnabled">$LOCALIZE[31054]</value>
 	</variable>
 	<variable name="MusicOSDHelpTextVar">
 		<value condition="Control.HasFocus(620)">$LOCALIZE[31033]$INFO[MusicPlayer.UserRating, : ]</value>
 		<value condition="Control.HasFocus(704)">$LOCALIZE[486]$INFO[Playlist.Repeat, : ]</value>
-		<value condition="Control.HasFocus(607)">$LOCALIZE[590]$INFO[Playlist.Random, : ]</value>
+		<value condition="Control.HasFocus(607) + Playlist.IsRandom">$LOCALIZE[590]: $LOCALIZE[16041]</value>
+		<value condition="Control.HasFocus(607)">$LOCALIZE[590]: $LOCALIZE[16039]</value>
 		<value condition="Control.HasFocus(703)">$LOCALIZE[24013]</value>
 		<value condition="Control.HasFocus(5000)">$LOCALIZE[10004]</value>
 	</variable>
@@ -321,7 +324,6 @@
 		<value condition="Window.IsActive(pvrsettings)">icons/settings/livetv.png</value>
 		<value condition="Window.IsActive(servicesettings)">icons/settings/network.png</value>
 		<value condition="Window.IsActive(interfacesettings)">icons/settings/appearance.png</value>
-		<value condition="Window.IsActive(musicsettings)">icons/settings/music.png</value>
 		<value condition="Window.IsActive(systemsettings)">icons/settings/system.png</value>
 	</variable>
 	<!-- Breadcrumbs -->
@@ -389,4 +391,11 @@
 		<value condition="ListItem.HasTimerSchedule">icons/pvr/PVR-HasTimerSchedule.png</value>
 		<value condition="ListItem.HasTimer">icons/pvr/PVR-HasTimer.png</value>
 	</variable>
+	<variable name="VideoHWDecoder">
+		<value condition="Player.Process(videohwdecoder)">HW</value>
+		<value>SW</value>
+	</variable>
+	<variable name="AddonNewsVar">
+		<value condition="!String.IsEmpty(ListItem.AddonNews)">$LOCALIZE[31136]</value>
+	</variable>
 </includes>
diff --git a/addons/skin.estuary/1080i/VideoFullScreen.xml b/addons/skin.estuary/1080i/VideoFullScreen.xml
index 3fe87e4..a860989 100644
--- a/addons/skin.estuary/1080i/VideoFullScreen.xml
+++ b/addons/skin.estuary/1080i/VideoFullScreen.xml
@@ -2,123 +2,6 @@
 <window>
 	<defaultcontrol>-</defaultcontrol>
 	<controls>
-		<control type="group" id="0">
-			<!-- codec infos -->
-			<control type="image">
-				<left>10</left>
-				<top>-465</top>
-				<width>1902</width>
-				<height>765</height>
-				<texture border="40">buttons/dialogbutton-nofo.png</texture>
-				<animation effect="slide" end="0,250" time="160" tween="cubic" condition="VideoPlayer.Content(LiveTV) + System.GetBool(pvrplayback.signalquality)">Conditional</animation>
-			</control>
-			<control type="label" id="10">
-				<left>45</left>
-				<top>15</top>
-				<width>1770</width>
-				<height>100</height>
-				<label>-</label>
-				<font>font12</font>
-			</control>
-			<control type="label" id="11">
-				<left>45</left>
-				<top>95</top>
-				<width>1770</width>
-				<height>100</height>
-				<label>-</label>
-				<font>font12</font>
-			</control>
-			<control type="label" id="12">
-				<left>45</left>
-				<top>175</top>
-				<width>1770</width>
-				<height>100</height>
-				<label>-</label>
-				<font>font12</font>
-			</control>
-			<control type="group">
-				<visible>VideoPlayer.Content(LiveTV) + system.getbool(pvrplayback.signalquality)</visible>
-				<top>310</top>
-				<control type="label">
-					<description>Header</description>
-					<left>50</left>
-					<width>1720</width>
-					<height>65</height>
-					<align>center</align>
-					<aligny>top</aligny>
-					<label>$LOCALIZE[19005]</label>
-					<font>font24_title</font>
-					<textcolor>button_focus</textcolor>
-				</control>
-				<control type="grouplist">
-					<orientation>vertical</orientation>
-					<left>20</left>
-					<top>90</top>
-					<include content="LeftRightAlignedInfoLine">
-						<param name="label" value="$LOCALIZE[19012]" />
-						<param name="value" value="$INFO[PVR.ActStreamClient]" />
-					</include>
-					<include content="LeftRightAlignedInfoLine">
-						<param name="label" value="$LOCALIZE[19006]" />
-						<param name="value" value="$INFO[PVR.ActStreamDevice]" />
-					</include>
-					<include content="LeftRightAlignedInfoLine">
-						<param name="label" value="$LOCALIZE[19007]" />
-						<param name="value" value="$INFO[PVR.ActStreamStatus]" />
-					</include>
-				</control>
-				<control type="group">
-					<left>1470</left>
-					<top>90</top>
-					<control type="label">
-						<description>Signal</description>
-						<width>250</width>
-						<height>25</height>
-						<aligny>center</aligny>
-						<label>[COLOR button_focus]$LOCALIZE[19008]:[/COLOR] $INFO[PVR.ActStreamSignal]</label>
-						<font>font12</font>
-					</control>
-					<control type="progress">
-						<top>30</top>
-						<width>360</width>
-						<height>12</height>
-						<info>PVR.ActStreamProgrSignal</info>
-					</control>
-					<control type="label">
-						<description>SNR</description>
-						<top>60</top>
-						<width>250</width>
-						<height>25</height>
-						<aligny>center</aligny>
-						<label>[COLOR button_focus]$LOCALIZE[19009]:[/COLOR] $INFO[PVR.ActStreamSNR]</label>
-						<font>font12</font>
-					</control>
-					<control type="progress">
-						<top>90</top>
-						<width>360</width>
-						<height>12</height>
-						<info>PVR.ActStreamProgrSNR</info>
-					</control>
-				</control>
-				<control type="grouplist">
-					<orientation>vertical</orientation>
-					<left>800</left>
-					<top>90</top>
-					<include content="LeftRightAlignedInfoLine">
-						<param name="label" value="$LOCALIZE[19010]" />
-						<param name="value" value="$INFO[PVR.ActStreamBER]" />
-					</include>
-					<include content="LeftRightAlignedInfoLine">
-						<param name="label" value="$LOCALIZE[19011]" />
-						<param name="value" value="$INFO[PVR.ActStreamUNC]" />
-					</include>
-					<include content="LeftRightAlignedInfoLine">
-						<param name="label" value="$LOCALIZE[19015]" />
-						<param name="value" value="$INFO[PVR.ActStreamEncryptionName]" />
-					</include>
-				</control>
-			</control>
-		</control>
 		<control type="group" id="1">
 			<visible>Player.Caching</visible>
 			<animation delay="300" effect="fade" time="200">Visible</animation>
diff --git a/addons/skin.estuary/1080i/VideoOSD.xml b/addons/skin.estuary/1080i/VideoOSD.xml
index 4bb0092..fcdf43e 100644
--- a/addons/skin.estuary/1080i/VideoOSD.xml
+++ b/addons/skin.estuary/1080i/VideoOSD.xml
@@ -16,13 +16,13 @@
 			<onclick>Action(close)</onclick>
 		</control>
 		<control type="group">
-			<visible>![Window.IsVisible(SliderDialog) | Window.IsVisible(OSDVideoSettings) | Window.IsVisible(OSDAudioSettings) | Window.IsVisible(OSDAudioDSPSettings) | Window.IsVisible(VideoBookmarks)]</visible>
+			<visible>![Window.IsVisible(SliderDialog) | Window.IsVisible(OSDVideoSettings) | Window.IsVisible(OSDAudioSettings) | Window.IsVisible(OSDAudioDSPSettings) | Window.IsVisible(VideoBookmarks) | Window.IsVisible(playerprocessinfo)]</visible>
 			<animation effect="fade" end="100" time="200">WindowOpen</animation>
 			<animation effect="fade" time="200">VisibleChange</animation>
 			<animation effect="fade" start="100" end="0" time="200">WindowClose</animation>
 			<control type="group">
 				<top>900</top>
-				<visible>!Window.IsVisible(fullscreeninfo) + !Window.IsActive(osdaudiosettings) + !Window.IsActive(osdvideosettings) + !Window.IsActive(PVROSDChannels) + !Window.IsActive(PVROSDGuide)</visible>
+				<visible>!Window.IsVisible(fullscreeninfo) + !Window.IsActive(osdaudiosettings) + !Window.IsActive(osdvideosettings) + !Window.IsActive(osdcmssettings) + !Window.IsActive(PVROSDChannels) + !Window.IsActive(PVROSDGuide)</visible>
 				<animation effect="fade" end="100" time="200">WindowOpen</animation>
 				<animation effect="fade" time="200">VisibleChange</animation>
 				<animation effect="fade" start="100" end="0" time="200">WindowClose</animation>
@@ -188,6 +188,7 @@
 							<include content="OSDButton">
 								<param name="texture" value="osd/fullscreen/buttons/settings-subtitle.png"/>
 							</include>
+							<visible>!VideoPlayer.Content(LiveTV) | VideoPlayer.HasSubtitles</visible>
 						</control>
 						<control type="radiobutton" id="255">
 							<include content="OSDButton">
@@ -310,6 +311,13 @@
 						<label>$LOCALIZE[13395]</label>
 						<onclick>ActivateWindow(osdvideosettings)</onclick>
 					</control>
+					<control type="button" id="11105">
+						<width>470</width>
+						<include>DefaultSettingButton</include>
+						<label>$LOCALIZE[36560]</label>
+						<onclick>ActivateWindow(osdcmssettings)</onclick>
+						<visible>System.HasCMS</visible>
+					</control>
 					<control type="button" id="11103">
 						<width>470</width>
 						<include>DefaultSettingButton</include>
diff --git a/addons/skin.estuary/1080i/View_50_List.xml b/addons/skin.estuary/1080i/View_50_List.xml
index d37f547..31363da 100644
--- a/addons/skin.estuary/1080i/View_50_List.xml
+++ b/addons/skin.estuary/1080i/View_50_List.xml
@@ -155,7 +155,7 @@
 			<width>509</width>
 			<height>509</height>
 			<aspectratio>scale</aspectratio>
-			<texture>colors/black.png</texture>
+			<texture colordiffuse="BFFFFFFF">colors/black.png</texture>
 			<bordertexture border="20">overlays/shadow.png</bordertexture>
 			<bordersize>20</bordersize>
 		</control>
diff --git a/addons/skin.estuary/1080i/View_51_Poster.xml b/addons/skin.estuary/1080i/View_51_Poster.xml
index 52454d7..68c63ea 100644
--- a/addons/skin.estuary/1080i/View_51_Poster.xml
+++ b/addons/skin.estuary/1080i/View_51_Poster.xml
@@ -79,101 +79,103 @@
 						</control>
 					</focusedlayout>
 				</control>
-				<control type="image">
-					<right>90</right>
-					<top>375</top>
-					<width>1232</width>
-					<height>110</height>
-					<texture border="22">dialogs/dialog-bg.png</texture>
-				</control>
-				<control type="image">
-					<right>90</right>
-					<top>455</top>
-					<width>1232</width>
-					<height>272</height>
-					<texture border="22">dialogs/dialog-bg.png</texture>
-				</control>
 				<control type="group">
-					<left>635</left>
-					<top>475</top>
-					<visible>ListItem.IsCollection</visible>
-					<include content="InfoList">
-						<param name="sortby" value="year" />
-						<param name="sortorder" value="descending" />
-						<param name="font" value="font12" />
-					</include>
-				</control>
-				<control type="image">
-					<left>645</left>
-					<top>415</top>
-					<width>32</width>
-					<height>32</height>
-					<texture>$VAR[ListWatchedIconVar]</texture>
-				</control>
-				<control type="label">
-					<left>695</left>
-					<top>400</top>
-					<width>930</width>
-					<height>40</height>
-					<label>$INFO[ListItem.Label]</label>
-					<font>font30_title</font>
-					<shadowcolor>text_shadow</shadowcolor>
-				</control>
-				<control type="label">
-					<right>130</right>
-					<top>400</top>
-					<width>1160</width>
-					<height>40</height>
-					<label>$VAR[ListSubLabelVar]</label>
-					<font>font30_title</font>
-					<textcolor>button_focus</textcolor>
-					<shadowcolor>text_shadow</shadowcolor>
-					<align>right</align>
-				</control>
-				<control type="grouplist">
-					<orientation>vertical</orientation>
-					<left>645</left>
-					<top>480</top>
-					<height>195</height>
-					<control type="label">
-						<font>font12</font>
-						<width>1160</width>
-						<height>38</height>
-						<label>$INFO[ListItem.Duration,[COLOR button_focus]$LOCALIZE[180]: [/COLOR], $LOCALIZE[31060]]</label>
-						<shadowcolor>text_shadow</shadowcolor>
-						<visible>!String.IsEmpty(ListItem.Duration)</visible>
+					<control type="image">
+						<left>598</left>
+						<top>375</top>
+						<width>1232</width>
+						<height>110</height>
+						<texture border="22">dialogs/dialog-bg.png</texture>
 					</control>
-					<control type="label">
-						<font>font12</font>
-						<width>1160</width>
-						<height>38</height>
-						<label>$INFO[ListItem.Director,[COLOR button_focus]$LOCALIZE[20339]: [/COLOR]]</label>
-						<shadowcolor>text_shadow</shadowcolor>
-						<visible>!String.IsEmpty(ListItem.Director)</visible>
+					<control type="image">
+						<left>598</left>
+						<top>455</top>
+						<width>1232</width>
+						<height>272</height>
+						<texture border="22">dialogs/dialog-bg.png</texture>
+					</control>
+					<control type="group">
+						<left>635</left>
+						<top>475</top>
+						<visible>ListItem.IsCollection</visible>
+						<include content="InfoList">
+							<param name="sortby" value="year" />
+							<param name="sortorder" value="descending" />
+							<param name="font" value="font12" />
+						</include>
+					</control>
+					<control type="image">
+						<left>645</left>
+						<top>415</top>
+						<width>32</width>
+						<height>32</height>
+						<texture>$VAR[ListWatchedIconVar]</texture>
 					</control>
 					<control type="label">
-						<font>font12</font>
-						<width>1160</width>
-						<height>38</height>
-						<label>$INFO[ListItem.Genre,[COLOR button_focus]$LOCALIZE[515]: [/COLOR]]</label>
+						<left>695</left>
+						<top>400</top>
+						<width>930</width>
+						<height>40</height>
+						<label>$INFO[ListItem.Label]</label>
+						<font>font30_title</font>
 						<shadowcolor>text_shadow</shadowcolor>
-						<visible>[String.IsEmpty(ListItem.Director) | String.IsEmpty(ListItem.Duration)] + !String.IsEmpty(ListItem.Genre)</visible>
 					</control>
 					<control type="label">
-						<font>font12</font>
+						<right>130</right>
+						<top>400</top>
 						<width>1160</width>
-						<height>38</height>
-						<label>$INFO[ListItem.Season,[COLOR button_focus]$LOCALIZE[33054]: [/COLOR],]$INFO[ListItem.Episode,  •  [COLOR button_focus] $LOCALIZE[20360]: [/COLOR],]</label>
+						<height>40</height>
+						<label>$VAR[ListSubLabelVar]</label>
+						<font>font30_title</font>
+						<textcolor>button_focus</textcolor>
 						<shadowcolor>text_shadow</shadowcolor>
-						<visible>!String.IsEmpty(ListItem.Season)</visible>
+						<align>right</align>
 					</control>
-					<control type="textbox">
-						<width>1150</width>
-						<height max="195">auto</height>
-						<font>font12</font>
-						<autoscroll time="3000" delay="3000" repeat="5000">!System.HasModalDialog</autoscroll>
-						<label>$INFO[ListItem.Plot]</label>
-						<shadowcolor>text_shadow</shadowcolor>
+					<control type="grouplist">
+						<orientation>vertical</orientation>
+						<left>645</left>
+						<top>480</top>
+						<height>195</height>
+						<control type="label">
+							<font>font12</font>
+							<width>1160</width>
+							<height>38</height>
+							<label>$INFO[ListItem.Duration,[COLOR button_focus]$LOCALIZE[180]: [/COLOR], $LOCALIZE[31060]]</label>
+							<shadowcolor>text_shadow</shadowcolor>
+							<visible>!String.IsEmpty(ListItem.Duration)</visible>
+						</control>
+						<control type="label">
+							<font>font12</font>
+							<width>1160</width>
+							<height>38</height>
+							<label>$INFO[ListItem.Director,[COLOR button_focus]$LOCALIZE[20339]: [/COLOR]]</label>
+							<shadowcolor>text_shadow</shadowcolor>
+							<visible>!String.IsEmpty(ListItem.Director)</visible>
+						</control>
+						<control type="label">
+							<font>font12</font>
+							<width>1160</width>
+							<height>38</height>
+							<label>$INFO[ListItem.Genre,[COLOR button_focus]$LOCALIZE[515]: [/COLOR]]</label>
+							<shadowcolor>text_shadow</shadowcolor>
+							<visible>[String.IsEmpty(ListItem.Director) | String.IsEmpty(ListItem.Duration)] + !String.IsEmpty(ListItem.Genre)</visible>
+						</control>
+						<control type="label">
+							<font>font12</font>
+							<width>1160</width>
+							<height>38</height>
+							<label>$INFO[ListItem.Season,[COLOR button_focus]$LOCALIZE[33054]: [/COLOR],]$INFO[ListItem.Episode,  •  [COLOR button_focus] $LOCALIZE[20360]: [/COLOR],]</label>
+							<shadowcolor>text_shadow</shadowcolor>
+							<visible>!String.IsEmpty(ListItem.Season)</visible>
+						</control>
+						<control type="textbox">
+							<width>1150</width>
+							<height max="195">auto</height>
+							<font>font12</font>
+							<autoscroll time="3000" delay="3000" repeat="5000">!System.HasModalDialog</autoscroll>
+							<label>$INFO[ListItem.Plot]</label>
+							<shadowcolor>text_shadow</shadowcolor>
+						</control>
 					</control>
 				</control>
 			</control>
diff --git a/addons/skin.estuary/addon.xml b/addons/skin.estuary/addon.xml
index 44fed1e..8fca1fe 100644
--- a/addons/skin.estuary/addon.xml
+++ b/addons/skin.estuary/addon.xml
@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<addon id="skin.estuary" version="0.8.1" name="Estuary" provider-name="phil65, Piers">
+<addon id="skin.estuary" version="0.8.4" name="Estuary" provider-name="phil65, Piers">
 	<requires>
 		<import addon="xbmc.gui" version="5.12.0"/>
 	</requires>
 	<extension point="xbmc.gui.skin" debugging="false">
 		<res width="1920" height="1080" aspect="16:9" default="true" folder="1080i" />
+		<res width="2560" height="1080" aspect="21:9" default="false" folder="1080i" />
 	</extension>
 	<extension point="xbmc.addon.metadata">
 		<summary lang="bg_BG">Estuary облик от phil65 и Piers. (стандартния облик на Kodi)</summary>
@@ -14,13 +15,15 @@
 		<summary lang="en_GB">Estuary skin by phil65 and Piers. (Kodi's default skin)</summary>
 		<summary lang="en_NZ">Estuary skin by phil65 and Piers. (Kodi's default skin)</summary>
 		<summary lang="en_US">Estuary skin by phil65 and Piers. (Kodi's default skin)</summary>
-		<summary lang="fi_FI">Estuary ulkoasu phil65 ja Piersiltä. (Kodin oletus ulkoasu)</summary>
+		<summary lang="es_ES">Skin Estuary, creado por phil65 and Piers (skin por defecto de Kodi).</summary>
+		<summary lang="fi_FI">Estuary-ulkoasu phil65 ja Piersiltä. (Kodin oletusulkoasu)</summary>
 		<summary lang="fr_CA">Habillage Estuaire par phil65 et Piers (habillage par défaut de Kodi).</summary>
 		<summary lang="fr_FR">Estuary, un habillage par phil65 et Piers (habillage d'origine de Kodi).</summary>
 		<summary lang="gl_ES">Pel Estuary por phil65 and Piers. (Kodi's default skin)</summary>
 		<summary lang="hr_HR">Estuary presvlaka autora phil65 i Piersa. (uobičajena Kodi presvlaka)</summary>
 		<summary lang="hu_HU">Estuary felszín. Készítette phil65 és Piers. (Kodi alapértelmezett felszín)</summary>
 		<summary lang="it_IT">Skin Estuary da phil65 e Piers. (Skin predefinita di Kodi)</summary>
+		<summary lang="ja_JP">Estuary スキン by phil65 and Piers (Kodi デフォルトスキン)</summary>
 		<summary lang="ko_KR">phil65와 Piers가 만든 Estuary 스킨 (Kodi 기본 스킨)</summary>
 		<summary lang="lt_LT">Estuary teminė išvaizda, kurią sukūrė phil65 ir Piers. (Numatytoji Kodi teminė išvaizda)</summary>
 		<summary lang="ms_MY">Kulit Estuary oleh phil65 dan rakan-rakan. (Kulit lalai Kodi)</summary>
@@ -28,19 +31,22 @@
 		<summary lang="nl_NL">Estuary skin door phil65 en Piers. (Kodi's standaard skin)</summary>
 		<summary lang="pl_PL">Skóra Eustary autorstwa phil65 i Piers. (Domyślna skóra Kodi)</summary>
 		<summary lang="pt_BR">Skin Esturay por phil65 e Piers. (Skin padrão do Kodi)</summary>
+		<summary lang="ru_RU">Обложка Estuary (стандартная обложка Kodi). Авторы: phil65 and Piers.</summary>
 		<summary lang="sk_SK">Vzhľad Estuary, vytvorili phil65 a Piers. (predvolený vzhľad pre Kodi)</summary>
 		<summary lang="sr_RS">Маска Estuary аутора phil65 и Piers. (Подразумевана Коди маска)</summary>
 		<summary lang="sr_RS at latin">Maska Estuary autora phil65 i Piers. (Podrazumevana Kodi maska)</summary>
 		<summary lang="sv_SE">Estuary-skin av phil65 och Piers. (Kodi's standard-skin)</summary>
 		<summary lang="tr_TR">Estuary dış görünümü. phil65 ve Piers (Kodi'nin varsayılan dış görünümü)</summary>
 		<summary lang="zh_CN">phil65 和 Piers 开发的 Estuary 皮肤(Kodi 的默认皮肤)</summary>
+		<summary lang="zh_TW">phil65與Piers 製作的Estuary佈景主題(Kodi的預設佈景主題)</summary>
 		<description lang="bg_BG">Estuary е стандартният облик на Kodi 17 и по-новите версии. Целта е да се улеснят хората които се сблъскват за първи път с Kodi.</description>
 		<description lang="cs_CZ">Estuary je výchozí skin pro Kodi 17.0 a výše. Jeho snahou je zjednodušit používání Kodi pro nové uživatele.</description>
 		<description lang="de_DE">Estuary ist der Standardskin für Kodi 17.0 und höher. Ziel war es, einen einfach zu bedienenden Skin für neue Kodi-User zu entwickeln.</description>
-		<description lang="el_GR">Το Estuary είναι η προεπιλεγμένη αμφίεση για τις εκδόσεις Kodi 17.0 και άνω.Το οποίο προσπαθεί να είναι εύκολο για τους αρχάριους χρήστες του Kodi να το κατανοήσουν και να το χρησιμοποιήσουν.</description>
+		<description lang="el_GR">Το Estuary είναι η προεπιλεγμένη αμφίεση για τις εκδόσεις Kodi 17.0 και άνω. Επιχειρεί να είναι προσιτό στους αρχάριους χρήστες του Kodi για να το κατανοήσουν και να το χρησιμοποιήσουν.</description>
 		<description lang="en_GB">Estuary is the default skin for Kodi 17.0 and above. It attempts to be easy for first time Kodi users to understand and use.</description>
 		<description lang="en_NZ">Estuary is the default skin for Kodi 17.0 and above. It attempts to be easy for first time Kodi users to understand and use.</description>
 		<description lang="en_US">Estuary is the default skin for Kodi 17.0 and above. It attempts to be easy for first time Kodi users to understand and use.</description>
+		<description lang="es_ES">Estuary es el skin por defecto para Kodi 17.0 o superior. Su objetivo es la facilidad de comprensión y uso para usuarios primerizos de Kodi.</description>
 		<description lang="fi_FI">Estuary on oletusulkoasu Kodi:n versiosta 17.0 lähtien. Se pyrkii olemaan helppo ymmärtää ja käyttää Kodi:n ensikäyttäjille. </description>
 		<description lang="fr_CA">Estuaire est l'habillage par défaut pour Kodi 17.0 et ultérieure. Il s'efforce d'être facile à comprendre et à utiliser pour les utilisateurs débutants de Kodi.</description>
 		<description lang="fr_FR">Estuary est l'habillage d'origine pour Kodi 17.0 et supérieur. Il est facile à comprendre et à utiliser pour les utilisateurs novices de Kodi..</description>
@@ -48,6 +54,7 @@
 		<description lang="hr_HR">Estuary je uobičajena presvlaka za Kodi 17.0 i novije inačice. To je pokušaj da se novim korisnicima olakša prvo korištenje i kasnija upotreba Kodija.</description>
 		<description lang="hu_HU">Az Estuary az alapértelmezett felszín a 17.0 és újabb Kodi kiadásokban.  Megpróbál könnyen kezelhető és használható lenni, az újonc Kodi felhasználóknak is.</description>
 		<description lang="it_IT">Estuary è la skin predefinita di Kodi 17.0 e successivi. Cerca di essere facile da capire e usare per i nuovi utenti di Kodi.</description>
+		<description lang="ja_JP">Estuary は Kodi 17.0 およびそれ以上のバージョンで標準のスキンです。ユーザが初めて Kodi に触れる際にわかりやすく使えるようにしてあります。</description>
 		<description lang="ko_KR">Estuary는 Kodi 17.0이상의 기본 스킨입니다. 처음 Kodi를 접하는 사용자가 쉽게 이해하고 사용할 수 있도록 만들었습니다.</description>
 		<description lang="lt_LT">Estuary yra numatytoji Kodi 17.0 ir aukštesnių versijų teminė išvaizda. Jos tikslas tapti lengvai suprantama ir naudojama naujiems Kodi vartotojams.</description>
 		<description lang="ms_MY">Estuary ialah kulit lalai untuk Kodi 17.0 dan ke atas. Kulit yang mudah digunakan buat pengguna Kodi kali pertama untuk memahami dan menggunakannya.</description>
@@ -55,19 +62,22 @@
 		<description lang="nl_NL">Estuary is de standaard skin voor Kodi 17.0 en hoger. Het tracht eenvoudig te begrijpen en te gebruiken te zijn voor beginnende Kodi gebruikers.</description>
 		<description lang="pl_PL">Eustary jest domyślną skórą Kodi dla wersji 17.0 i późniejszych. Jest próbą łatwego wprowadzenia początkujących użytkowników w funkcje Kodi.</description>
 		<description lang="pt_BR">Estuary é a skin padrão para o Kodi 17.0 e acima. Objetiva ser fácil para usuários que iniciam no Kodi pela primeira vez, facilitando aprendizagem de uso do mesmo.</description>
+		<description lang="ru_RU">Estuary — это стандартная обложка Kodi, начиная с версии 17.0.
Простая и понятная в использовании для новых пользователей Kodi.</description>
 		<description lang="sk_SK">Estuary je predvolený vzhľad pre Kodi 17.0 a vyššie. Pokúša sa byť pre prvotných používateľov Kodi jednoduchým na pochopenie a používanie.</description>
 		<description lang="sr_RS">Estuary је подразумевана маска за Kodi 17.0 и изнад. Покушава да буде једноставан за разумевање и коришћење новим корисницима Kodi-ја.</description>
 		<description lang="sr_RS at latin">Estuary je podrazumevana maska za Kodi 17.0 i iznad. Pokušava da bude jednostavan za razumevanje i korišćenje novim korisnicima Kodija.</description>
 		<description lang="sv_SE">Estuary är standard-skin för Kodi 17.0 och uppåt. Det försöker att vara lättförståeligt för förstagångsanvändare av Kodi att förstå och använda.</description>
 		<description lang="tr_TR">Estuary Kodi 17.0 ve yukarısı için varsayılan dış görünümdür. İlk kez Kodi kullananlar için anlaşılması ve kullanımı kolaydır.</description>
 		<description lang="zh_CN">Estuary 是 Kodi 17.0 的默认皮肤。它力求使首次使用 Kodi 的用户易于上手。</description>
+		<description lang="zh_TW">Estuary是Kodi 17.0開始搭載的預設佈景主題。主要在讓第一次使用 Kodi 的使用者可以簡單地上手。</description>
 		<disclaimer lang="bg_BG">Estuary е стандартният облик на Kodi. Премахването му може да предизвика проблеми</disclaimer>
 		<disclaimer lang="cs_CZ">Estuary je výchozí skin pro Kodi, jeho odebráním může dojít k potížím.</disclaimer>
 		<disclaimer lang="de_DE">Estuary ist der Standardskin von Kodi. Ein Entfernen des Skins kann Probleme verursachen.</disclaimer>
-		<disclaimer lang="el_GR">Το Estuary είναι η προεπιλεγμένη αμφίεση για το Kodi, η αφαίρεσή του μπορεί να δημιουργήσει προβλήματα</disclaimer>
+		<disclaimer lang="el_GR">Το Estuary είναι η προεπιλεγμένη αμφίεση για το Kodi. Η αφαίρεσή του μπορεί να δημιουργήσει προβλήματα.</disclaimer>
 		<disclaimer lang="en_GB">Estuary is the default skin for Kodi, removing it may cause issues</disclaimer>
 		<disclaimer lang="en_NZ">Estuary is the default skin for Kodi, removing it may cause issues</disclaimer>
 		<disclaimer lang="en_US">Estuary is the default skin for Kodi, removing it may cause issues</disclaimer>
+		<disclaimer lang="es_ES">Estuary es el skin por defecto de Kodi. Desinstalarlo puede causar problemas.</disclaimer>
 		<disclaimer lang="fi_FI">Estuary on Kodin oletusteema, sen poisto voi aiheuttaa ongelmia</disclaimer>
 		<disclaimer lang="fr_CA">Estuaire est l'habillage par défaut de Kodi, le supprimer peut créer des problèmes</disclaimer>
 		<disclaimer lang="fr_FR">Estuary est l'habillage d'origine de Kodi, le retirer peut créer des problèmes</disclaimer>
@@ -75,6 +85,7 @@
 		<disclaimer lang="hr_HR">Estuary je uobičajena presvlaka za Kodi, njegovim uklanjanjem može uzrokovati poteškoće</disclaimer>
 		<disclaimer lang="hu_HU">Az Estuary az alapértelmezett Kodi felszín. Eltávolítása problémákat okozhat.</disclaimer>
 		<disclaimer lang="it_IT">Estuary è la skin predefinita di Kodi, rimuoverla potrebbe causare problemi</disclaimer>
+		<disclaimer lang="ja_JP">Estuary は Kodi のデフォルトスキンですので、これを削除するとうまく動かなくなる可能性があります</disclaimer>
 		<disclaimer lang="ko_KR">Estuary는 Kodi의 기본스킨으로 제거시 문제가 생길 수 있습니다.</disclaimer>
 		<disclaimer lang="lt_LT">Estuary yra numatytoji Kodi teminė išvaizda, jos pašalinimas gali sukelti problemų</disclaimer>
 		<disclaimer lang="ms_MY">Estuary ialah kulit lalai Kodi, mengubahnya boleh menimbulkan isu.</disclaimer>
@@ -82,15 +93,29 @@
 		<disclaimer lang="nl_NL">Estuary is de standaard skin voor Kodi, het verwijderen van Estuary kan leiden tot problemen.</disclaimer>
 		<disclaimer lang="pl_PL">Eustary jest domyślną skórą Kodi, jej usunięcie może powodować problemy</disclaimer>
 		<disclaimer lang="pt_BR">Estuary é a skin padrão para o Kodi, removendo-a pode causar problemas</disclaimer>
+		<disclaimer lang="ru_RU">Estuary — это стандартная обложка Kodi, и ее удаление может привести к возникновению проблем</disclaimer>
 		<disclaimer lang="sk_SK">Estuary je predvolený vzhľad pre Kodi, jeho odstránenie môže spôsobiť problémy</disclaimer>
 		<disclaimer lang="sr_RS">Estuary је подразумевана маска за Kodi, уклањање може изазвати проблеме</disclaimer>
 		<disclaimer lang="sr_RS at latin">Estuary je podrazumevana maska za Kodi, uklanjanje može izazvati probleme</disclaimer>
 		<disclaimer lang="sv_SE">Estuary är standard skalet för Kodi, ta bort den kan orsaka problem</disclaimer>
 		<disclaimer lang="tr_TR">Estuary Kodi için varsayılan dış görünümdür, kaldırmak sorunlara yol açabilir</disclaimer>
 		<disclaimer lang="zh_CN">Estuary 是 Kodi 的默认皮肤,删除它可能导致故障。</disclaimer>
+		<disclaimer lang="zh_TW">Estuary 是 Kodi 預設的佈景主題,移除它可能會造成問題</disclaimer>
 		<platform>all</platform>
 		<license>CC BY-SA 4.0, GNU GENERAL PUBLIC LICENSE Version 2.0</license>
 		<forum>http://forum.kodi.tv/</forum>
 		<source>https://github.com/xbmc/skin.estuary/</source>
+		<assets>
+			<icon>resources/icon.png</icon>
+			<fanart>resources/fanart.jpg</fanart>
+			<screenshot>resources/screenshot-01.jpg</screenshot>
+			<screenshot>resources/screenshot-02.jpg</screenshot>
+			<screenshot>resources/screenshot-03.jpg</screenshot>
+			<screenshot>resources/screenshot-04.jpg</screenshot>
+			<screenshot>resources/screenshot-05.jpg</screenshot>
+			<screenshot>resources/screenshot-06.jpg</screenshot>
+			<screenshot>resources/screenshot-07.jpg</screenshot>
+			<screenshot>resources/screenshot-08.jpg</screenshot>
+		</assets>
 	</extension>
 </addon>
diff --git a/addons/skin.estuary/changelog.txt b/addons/skin.estuary/changelog.txt
index 5e1e4fc..cbbf366 100644
--- a/addons/skin.estuary/changelog.txt
+++ b/addons/skin.estuary/changelog.txt
@@ -1,3 +1,9 @@
+[B]0.8.3[/B]
+• Updated language files from Transifex
+
+[B]0.8.2[/B]
+• Updated language files from Transifex
+
 [B]0.8.1[/B]
 • Updated language files from Transifex
 
diff --git a/addons/skin.estuary/language/resource.language.af_za/strings.po b/addons/skin.estuary/language/resource.language.af_za/strings.po
index b64de79..07d3738 100644
--- a/addons/skin.estuary/language/resource.language.af_za/strings.po
+++ b/addons/skin.estuary/language/resource.language.af_za/strings.po
@@ -119,3 +119,7 @@ msgstr "Selekteer jou Kodi gebruikers profiel[CR]om in te teken en voort te gaan
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Versteek"
diff --git a/addons/skin.estuary/language/resource.language.am_et/strings.po b/addons/skin.estuary/language/resource.language.am_et/strings.po
index 24f9732..99b9443 100644
--- a/addons/skin.estuary/language/resource.language.am_et/strings.po
+++ b/addons/skin.estuary/language/resource.language.am_et/strings.po
@@ -63,3 +63,7 @@ msgstr "የ ጣቢያ ቡድን"
 msgctxt "#31096"
 msgid "Local subtitle available"
 msgstr "የ አካባቢ ንዑስ አርእስት ዝግጁ ነው"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "መደበቂያ"
diff --git a/addons/skin.estuary/language/resource.language.ar_sa/strings.po b/addons/skin.estuary/language/resource.language.ar_sa/strings.po
index 9f9cdad..7bcd600 100644
--- a/addons/skin.estuary/language/resource.language.ar_sa/strings.po
+++ b/addons/skin.estuary/language/resource.language.ar_sa/strings.po
@@ -63,3 +63,7 @@ msgstr "تتوفر ترجمات محليه"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "تغير"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "إخف"
diff --git a/addons/skin.estuary/language/resource.language.be_by/strings.po b/addons/skin.estuary/language/resource.language.be_by/strings.po
index e2a837c..764c6ca 100644
--- a/addons/skin.estuary/language/resource.language.be_by/strings.po
+++ b/addons/skin.estuary/language/resource.language.be_by/strings.po
@@ -55,3 +55,7 @@ msgstr "Даступныя лакальныя субтытры"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Hide"
diff --git a/addons/skin.estuary/language/resource.language.bg_bg/strings.po b/addons/skin.estuary/language/resource.language.bg_bg/strings.po
index 565d692..307a9a5 100644
--- a/addons/skin.estuary/language/resource.language.bg_bg/strings.po
+++ b/addons/skin.estuary/language/resource.language.bg_bg/strings.po
@@ -192,6 +192,10 @@ msgctxt "#31050"
 msgid "Press [B]OK[/B] to stop"
 msgstr "Натиснете клавиша [B]OK[/B] за спиране"
 
+msgctxt "#31051"
+msgid "Toggle language"
+msgstr "Превключи езика"
+
 msgctxt "#31053"
 msgid "Arial based"
 msgstr "Основан на Arial"
@@ -455,3 +459,7 @@ msgstr "Настройки свързани с началния екран."
 msgctxt "#31132"
 msgid "min"
 msgstr "мин"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Скрий"
diff --git a/addons/skin.estuary/language/resource.language.ca_es/strings.po b/addons/skin.estuary/language/resource.language.ca_es/strings.po
index 2c16f88..288bde1 100644
--- a/addons/skin.estuary/language/resource.language.ca_es/strings.po
+++ b/addons/skin.estuary/language/resource.language.ca_es/strings.po
@@ -127,3 +127,7 @@ msgstr "Majúscules"
 msgctxt "#31106"
 msgid "Teletext"
 msgstr "Teletext"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Amaga"
diff --git a/addons/skin.estuary/language/resource.language.cs_cz/strings.po b/addons/skin.estuary/language/resource.language.cs_cz/strings.po
index d38c2fc..0d2375f 100644
--- a/addons/skin.estuary/language/resource.language.cs_cz/strings.po
+++ b/addons/skin.estuary/language/resource.language.cs_cz/strings.po
@@ -547,3 +547,7 @@ msgstr "Vybrat balíček fanátrů pro Hlavní nabídku"
 msgctxt "#31132"
 msgid "min"
 msgstr "min"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Skrýt"
diff --git a/addons/skin.estuary/language/resource.language.cy_gb/strings.po b/addons/skin.estuary/language/resource.language.cy_gb/strings.po
index 135a732..78d791d 100644
--- a/addons/skin.estuary/language/resource.language.cy_gb/strings.po
+++ b/addons/skin.estuary/language/resource.language.cy_gb/strings.po
@@ -67,3 +67,7 @@ msgstr "Is deitlau lleol ar gael"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Cuddio"
diff --git a/addons/skin.estuary/language/resource.language.da_dk/strings.po b/addons/skin.estuary/language/resource.language.da_dk/strings.po
index fc980b3..50c8534 100644
--- a/addons/skin.estuary/language/resource.language.da_dk/strings.po
+++ b/addons/skin.estuary/language/resource.language.da_dk/strings.po
@@ -96,6 +96,10 @@ msgctxt "#31085"
 msgid "Channel Group"
 msgstr "Kanalgruppe"
 
+msgctxt "#31086"
+msgid "Metadata"
+msgstr "Metadata"
+
 msgctxt "#31088"
 msgid "Content scanning options"
 msgstr "Indstillinger for indholdsskanning"
@@ -119,3 +123,11 @@ msgstr "Vælg din Kodi brugerprofil[CR]for at logge ind og fortsætte"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31106"
+msgid "Teletext"
+msgstr "Tekst-tv"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Skjul"
diff --git a/addons/skin.estuary/language/resource.language.de_de/strings.po b/addons/skin.estuary/language/resource.language.de_de/strings.po
index 3e1cc93..e0dbc4a 100644
--- a/addons/skin.estuary/language/resource.language.de_de/strings.po
+++ b/addons/skin.estuary/language/resource.language.de_de/strings.po
@@ -547,3 +547,11 @@ msgstr "Wähle Fanart für den Hauptbildschirm"
 msgctxt "#31132"
 msgid "min"
 msgstr "min"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Verstecken"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "Verbleibend"
diff --git a/addons/skin.estuary/language/resource.language.el_gr/strings.po b/addons/skin.estuary/language/resource.language.el_gr/strings.po
index 73dede3..3d6de74 100644
--- a/addons/skin.estuary/language/resource.language.el_gr/strings.po
+++ b/addons/skin.estuary/language/resource.language.el_gr/strings.po
@@ -18,7 +18,7 @@ msgstr ""
 
 msgctxt "#31000"
 msgid "Now playing"
-msgstr "Τώρα εκτελείται"
+msgstr "Σε αναπαραγωγή"
 
 msgctxt "#31001"
 msgid "Search..."
@@ -26,7 +26,7 @@ msgstr "Αναζήτηση..."
 
 msgctxt "#31002"
 msgid "Show media fanart as background"
-msgstr "Προβολή μέσων fanart ως φόντο"
+msgstr "Εμφάνιση μέσων fanart ως φόντο"
 
 msgctxt "#31003"
 msgid "Cinema mode"
@@ -42,11 +42,11 @@ msgstr "Προβολή ως 2D"
 
 msgctxt "#31006"
 msgid "Random movies"
-msgstr "τυχαίες ταινείες"
+msgstr "Τυχαίες ταινίες"
 
 msgctxt "#31007"
 msgid "Unwatched movies"
-msgstr "Μη προβληθέντες ταινίες"
+msgstr "Μη προβληθείσες ταινίες"
 
 msgctxt "#31008"
 msgid "No disclaimer"
@@ -62,19 +62,19 @@ msgstr "Ταινίες σε εξέλιξη"
 
 msgctxt "#31011"
 msgid "Most played albums"
-msgstr "Τα πιο παιγμένα άλμπουμς"
+msgstr "Τα πιο παιγμένα άλμπουμ"
 
 msgctxt "#31012"
 msgid "Random albums"
-msgstr "Τυχαία άλμπουμς"
+msgstr "Τυχαία άλμπουμ"
 
 msgctxt "#31013"
 msgid "Random artists"
-msgstr "Τυχαία σειρά καλλιτεχνών"
+msgstr "Τυχαίοι καλλιτέχνες"
 
 msgctxt "#31014"
 msgid "Unplayed albums"
-msgstr "Μη παιγμένα άλμπουμς"
+msgstr "Μη παιγμένα άλμπουμ"
 
 msgctxt "#31015"
 msgid "Recent recordings"
@@ -118,19 +118,19 @@ msgstr "Επόμενα κομμάτια"
 
 msgctxt "#31025"
 msgid "No favourites found. You can add any item from media views to this list by using the context menu."
-msgstr "Δεν βρέθηκαν αγαπημένα.Μπορείτε να προσθέσετε οποιοδήποτε αντικείμενο από προβολή πολυμέσων σε αυτήν την λίστα επιλέγοντας το κεντρικό μενού"
+msgstr "Δεν βρέθηκαν αγαπημένα. Μπορείτε να προσθέσετε οποιοδήποτε αντικείμενο από την προβολή πολυμέσων σε αυτή τη λίστα χρησιμοποιώντας το κεντρικό μενού."
 
 msgctxt "#31026"
 msgid "Go to albums"
-msgstr "Πήγαινε στα άλμπουμς"
+msgstr "Μετάβαση στα άλμπουμ"
 
 msgctxt "#31027"
 msgid "Go to songs"
-msgstr "Πήγαινε στα τραγούδια"
+msgstr "Μετάβαση στα τραγούδια"
 
 msgctxt "#31028"
 msgid "Show fanart"
-msgstr "Δείξε fanart"
+msgstr "Εμφάνιση fanart"
 
 msgctxt "#31029"
 msgid "Last logged in"
@@ -146,11 +146,11 @@ msgstr "Πληροφορίες εκδοσης"
 
 msgctxt "#31032"
 msgid "Order"
-msgstr "Παραγγελία"
+msgstr "Σειρά"
 
 msgctxt "#31033"
 msgid "Your rating"
-msgstr "Η αξιολόγηση σας"
+msgstr "Αξιολόγηση"
 
 msgctxt "#31034"
 msgid "Extended info"
@@ -170,19 +170,19 @@ msgstr "Λίστα κομματιών"
 
 msgctxt "#31038"
 msgid "Rewind"
-msgstr "Πίσω"
+msgstr "Επαναφορά"
 
 msgctxt "#31039"
 msgid "Fast forward"
-msgstr "Μπροστά"
+msgstr "Γρήγορη Προώθηση"
 
 msgctxt "#31040"
 msgid "Cancel update"
-msgstr "Ακύρωση της ενημέρωσης"
+msgstr "Ακύρωση ενημέρωσης"
 
 msgctxt "#31041"
 msgid "Camera manufacturer"
-msgstr "Κατασκευαστής της φωτογραφικής μηχανής "
+msgstr "Κατασκευαστής κάμερας"
 
 msgctxt "#31042"
 msgid "Playlist options"
@@ -190,23 +190,23 @@ msgstr "Επιλογές λίστας αναπ/γής"
 
 msgctxt "#31043"
 msgid "Set the type and add rules to create a smart playlist. These playlists are dynamic and include all media items from your database which apply to your chosen rules."
-msgstr "Ορισμός του τύπου και πρόσθεση κανόνων για την δημιουργία έξυπνης λίστας αναπαραγωγής.Αυτές οι λίστες αναπαραγωγής είναι δυναμικές και περιέχουν όλα τα αντικείμενα πολυμέσων από την βάση δεδομένων σας,η οποία εφαρμόζεται από τους επιλεγμένους κανόνες σας."
+msgstr "Ορίστε τον τύπο και προσθέστε κανόνες για τη δημιουργία μιας έξυπνης λίστας αναπαραγωγής. Αυτές οι λίστες αναπαραγωγής είναι δυναμικές και περιέχουν όλα τα αντικείμενα πολυμέσων από τη βάση δεδομένων σας, που ταιριάζουν με τους επιλεγμένους κανόνες σας."
 
 msgctxt "#31044"
 msgid "Add group"
-msgstr "Προσθήκη Γκρουπ"
+msgstr "Προσθήκη ομάδας"
 
 msgctxt "#31045"
 msgid "Rename group"
-msgstr "Μετονομασία Γκρουπ"
+msgstr "Μετονομασία ομάδας"
 
 msgctxt "#31046"
 msgid "Delete group"
-msgstr "Διαγραφή Γκρουπ"
+msgstr "Διαγραφή ομάδας"
 
 msgctxt "#31047"
 msgid "Read more..."
-msgstr "Διαβάστε περισσότερα"
+msgstr "Διαβάστε περισσότερα..."
 
 msgctxt "#31048"
 msgid "Available"
@@ -214,11 +214,11 @@ msgstr "Διαθέσιμος"
 
 msgctxt "#31049"
 msgid "Press [B]Up[/B] to rewind or fast-forward"
-msgstr "Πίεσε [B]πάνω[/B] βελάκι για επαναφορά ή γρήγορη προώθηση"
+msgstr "Πατήστε το [B]Επάνω[/B] βέλος για επαναφορά ή γρήγορη προώθηση"
 
 msgctxt "#31050"
 msgid "Press [B]OK[/B] to stop"
-msgstr "Πίεσε [B]OK[/B] για να σταματήσει"
+msgstr "Πατήστε το [B]OK[/B] για να διακοπή"
 
 msgctxt "#31051"
 msgid "Toggle language"
@@ -230,27 +230,27 @@ msgstr "φιλτραρισμένο"
 
 msgctxt "#31053"
 msgid "Arial based"
-msgstr "Βασισμένη σε Arial"
+msgstr "Βασισμένη στην Arial"
 
 msgctxt "#31054"
 msgid "Press [B]Left[/B] to rewind, or [B]Right[/B] to fast-forward"
-msgstr "Πίεσε [B]αριστερά[/B] για επαναφορά,ή [B]δεξιά[/B] για γρήγορη προώθηση"
+msgstr "Πατήστε το [B]Αριστερό[/B] βέλος για επαναφορά, ή το [B]Δεξί[/B] για γρήγορη προώθηση"
 
 msgctxt "#31055"
 msgid "Subtitle download"
-msgstr "Κατέβασμα υποτίτλων"
+msgstr "Λήψη υποτίτλων"
 
 msgctxt "#31056"
 msgid "Go to playlist"
-msgstr "Πήγαινε στην λίστα αναπαραγωγής"
+msgstr "Μετάβαση στη λίστα αναπαραγωγής"
 
 msgctxt "#31057"
 msgid "Show login screen on startup"
-msgstr "Προβολή οθόνης εισόδου στην έναρξη"
+msgstr "Προβολή οθόνης εισόδου κατά την έναρξη"
 
 msgctxt "#31058"
 msgid "Automatic Login on startup"
-msgstr "Αυτόματη είσοδο στην έναρξη"
+msgstr "Αυτόματη είσοδος κατά την έναρξη"
 
 msgctxt "#31059"
 msgid "Updates available"
@@ -258,15 +258,15 @@ msgstr "Ενημερώσεις διαθέσιμες"
 
 msgctxt "#31060"
 msgid "minutes"
-msgstr "Λεπτά"
+msgstr "λεπτά"
 
 msgctxt "#31061"
 msgid "Main menu items"
-msgstr "αντικείμενα βασικού μενού"
+msgstr "Αντικείμενα βασικού μενού"
 
 msgctxt "#31062"
 msgid "Shortcuts to the \"Files\" sections of each media type. Go there to add additional sources for your databases."
-msgstr "Συντομεύσεις στα τμήματα των \"Αρχείων\" κάθε τύπου πολυμέσου.Πήγαινε εκεί να προσθέσεις επιπρόσθετες πηγές για τις βάσεις δεδομένων σου."
+msgstr "Συντομεύσεις στην ενότητα \"Αρχεία\" κάθε τύπου πολυμέσου. Μεταβείτε εκεί ώστε να προσθέσετε νέες πηγές για τις βάσεις δεδομένων σας."
 
 msgctxt "#31063"
 msgid "Sections"
@@ -274,7 +274,7 @@ msgstr "Τμήματα"
 
 msgctxt "#31064"
 msgid "unwatched"
-msgstr "Μη προβληθέν"
+msgstr "μη προβληθέν"
 
 msgctxt "#31065"
 msgid "Video playlist"
@@ -302,7 +302,7 @@ msgstr "Εισαγωγή πηγών πολυμέσων"
 
 msgctxt "#31071"
 msgid "by"
-msgstr "υπο"
+msgstr "ανά"
 
 msgctxt "#31072"
 msgid "Power Options"
@@ -338,7 +338,7 @@ msgstr "Μη διαθέσιμο cast"
 
 msgctxt "#31080"
 msgid "Ends at"
-msgstr "Τελειώνει στο"
+msgstr "Τελειώνει στις"
 
 msgctxt "#31081"
 msgid "Album info"
@@ -354,15 +354,15 @@ msgstr "Ρυθμίσεις προσθέτου στίχων"
 
 msgctxt "#31084"
 msgid "Visualisation settings"
-msgstr "ρυθμίσεις Οπτικοποιήσεων"
+msgstr "Ρυθμίσεις οπτικοποίησης"
 
 msgctxt "#31085"
 msgid "Channel Group"
-msgstr "Γκρουπ Καναλιών"
+msgstr "Ομάδα Καναλιών"
 
 msgctxt "#31086"
 msgid "Metadata"
-msgstr "μεταδεδομένα"
+msgstr "Μεταδεδομένα"
 
 msgctxt "#31087"
 msgid "Provider settings"
@@ -370,11 +370,11 @@ msgstr "Ρυθμίσεις παρόχου"
 
 msgctxt "#31088"
 msgid "Content scanning options"
-msgstr "Επιλογές Σάρωσης Περιεχομένου"
+msgstr "Επιλογές σάρωσης περιεχομένου"
 
 msgctxt "#31089"
 msgid "Available groups"
-msgstr "Διαθέσιμα γκρουπ"
+msgstr "Διαθέσιμες ομάδες"
 
 msgctxt "#31090"
 msgid "Search trailer"
@@ -382,7 +382,7 @@ msgstr "Αναζήτηση τρέιλερ"
 
 msgctxt "#31091"
 msgid "Download subtitles"
-msgstr "Λήψη Υποτίτλων"
+msgstr "Λήψη υποτίτλων"
 
 msgctxt "#31092"
 msgid "Video menu"
@@ -390,23 +390,23 @@ msgstr "Μενού βίντεο"
 
 msgctxt "#31093"
 msgid "Show weather info in top bar"
-msgstr "Προβολή πληροφορίας καιρού στην πάνω μπάρα"
+msgstr "Εμφάνιση πληροφοριών καιρού στην επάνω γραμμή"
 
 msgctxt "#31094"
 msgid "Show media flags for movies / episodes / music videos"
-msgstr "Προβολή σημαδιών πολυμέσων για ταινίες / επεισόδια / μουσικών βίντεο"
+msgstr "Εμφάνιση σημείων για ταινίες / επεισόδια / μουσικά βίντεο"
 
 msgctxt "#31095"
 msgid "Use slide animations"
-msgstr "Χρήση πλευρικών εφέ κίνησης"
+msgstr "Χρήση εφέ κύλισης"
 
 msgctxt "#31096"
 msgid "Local subtitle available"
-msgstr "Διαθέσιμος υπότιτλος τοπικά"
+msgstr "Τοπικός υπότιτλος διαθέσιμος"
 
 msgctxt "#31097"
 msgid "Channel options"
-msgstr "Επιλογές Καναλιού"
+msgstr "Επιλογές καναλιού"
 
 msgctxt "#31098"
 msgid "Select your Kodi user profile[CR]to login and continue"
@@ -434,11 +434,11 @@ msgstr "Εισαγωγή κειμένου εδώ..."
 
 msgctxt "#31104"
 msgid "Your library is currently empty. In order to populate it with your personal media, enter \"Files\" section, add a media source and configure it. After the source has been added and indexed you will be able to browse your library."
-msgstr "Η βιβλιοθήκη σου είναι εντελώς άδεια.Για να το συμπληρώσετε με τα προσωπικά σας αρχεία πολυμέσων,καταχωρείστε τμήματα \"Αρχείων\",προσθέστε μια πηγή πολυμέσων και ρυθμίστε την.Αφού η πηγή προσθεθεί θα είστε σε θέση να περιηγηθείτε τη βιβλιοθήκη σας."
+msgstr "Η βιβλιοθήκη σας είναι προς το παρόν άδεια. Για να τη συμπληρώσετε με τα προσωπικά σας αρχεία πολυμέσων, πηγαίνετε στην ενότητα \"Αρχεία\", προσθέστε μια πηγή πολυμέσων και ρυθμίστε την. Μετά την προσθήκη της πηγής, θα είστε σε θέση να περιηγηθείτε στη βιβλιοθήκη σας."
 
 msgctxt "#31105"
 msgid "Add video sources and set the appropriate content type in order to populate your video libraries."
-msgstr "Πρόσθεσε πηγές βίντεο και όρισε το κατάλληλο είδος περιεχομένου, προκειμένου να συμπληρώσετε τις βιβλιοθήκες βίντεο σας."
+msgstr "Προσθέστε πηγές βίντεο και ορίστε το κατάλληλο είδος περιεχομένου, ώστε να συμπληρώσετε τις βιβλιοθήκες βίντεο."
 
 msgctxt "#31106"
 msgid "Teletext"
@@ -454,19 +454,19 @@ msgstr "Χρήση προσαρμοσμένου καθολικού φόντου"
 
 msgctxt "#31109"
 msgid "Choose image path"
-msgstr "Επιλογή τοποθεσίας φωτογραφίας"
+msgstr "Επιλογή τοποθεσίας εικόνας"
 
 msgctxt "#31110"
 msgid "Enter files section"
-msgstr "Εισαγωγή τμήμα αρχείων"
+msgstr "Μετάβαση στην ενότητα Αρχεία"
 
 msgctxt "#31111"
 msgid "View your personal pictures or download one of the many image add-ons from the official repository."
-msgstr "Δείτε τις προσωπικές σας φωτογραφίες ή να κατεβάσετε ένα από τα πολλά πρόσθετα εικόνας από το επίσημο αποθετήριο."
+msgstr "Δείτε τις προσωπικές σας εικόνες ή κατεβάστε ένα από τα πολλά πρόσθετα εικόνας από το επίσημο αποθετήριο."
 
 msgctxt "#31112"
 msgid "Toggle audio stream"
-msgstr "Εναλλαγή Ηχητικής ροής"
+msgstr "Εναλλαγή ηχητικής ροής"
 
 msgctxt "#31113"
 msgid "Search local library"
@@ -474,7 +474,7 @@ msgstr "Αναζήτηση στην τοπική βιβλιοθήκη"
 
 msgctxt "#31114"
 msgid "Search YouTube"
-msgstr "Αναζήτηση στο  Youtube"
+msgstr "Αναζήτηση στο Youtube"
 
 msgctxt "#31115"
 msgid "Search TheMovieDB"
@@ -482,7 +482,7 @@ msgstr "Αναζήτηση στο TheMovieDB"
 
 msgctxt "#31116"
 msgid "Remove this main menu item"
-msgstr "Αφαίρεση αντικειμένου του κεντρικού μενού"
+msgstr "Αφαίρεση αυτού του αντικειμένου"
 
 msgctxt "#31117"
 msgid "Edit nodes"
@@ -494,19 +494,19 @@ msgstr "Εισαγωγή Περιηγητή πρόσθετων"
 
 msgctxt "#31119"
 msgid "You do not have any add-ons installed yet. Visit our add-on browser to browse through our collection and improve your Kodi experience."
-msgstr "Δεν έχετε εγκαταστήσει κανένα πρόσθετο ακόμα. Επισκεφθείτε  τον περιηγητή προσθέτων μας για να περιηγηθείτε στη συλλογή μας και να βελτιώσουμε την kodi εμπειρία σας "
+msgstr "Δεν έχετε εγκαταστήσει κανένα πρόσθετο ακόμα. Επισκεφθείτε  τον περιηγητή προσθέτων μας για να περιηγηθείτε στη συλλογή μας και να βελτιώσετε την εμπειρία σας στο Kodi."
 
 msgctxt "#31120"
 msgid "You did not set up a weather provider yet. In order to view weather information, choose a weather provider and set up your location."
-msgstr "Δεν έχετε ορίσει ένα πάροχο καιρού ακόμα. Για να δείτε πληροφορίες για τον καιρό,επιλέξτε τον πάροχο του καιρού και ρυθμίστε την τοποθεσία σας."
+msgstr "Δεν έχετε ορίσει έναν πάροχο καιρού ακόμα. Για να δείτε πληροφορίες για τον καιρό, επιλέξτε έναν πάροχο καιρού και ρυθμίστε την τοποθεσία σας."
 
 msgctxt "#31121"
 msgid "Set weather provider"
-msgstr "Όρισε πάροχο καιρού"
+msgstr "Ορισμός παρόχου καιρού"
 
 msgctxt "#31122"
 msgid "Unwatched TV Shows"
-msgstr "Μη προβληθέντες Τηλ.Σειρές"
+msgstr "Μη προβληθείσες Τηλ. Σειρές"
 
 msgctxt "#31123"
 msgid "Same director"
@@ -514,15 +514,15 @@ msgstr "Ίδιος σκηνοθέτης"
 
 msgctxt "#31124"
 msgid "Show images on map"
-msgstr "Προβολή φωτογραφιών στον χάρτη"
+msgstr "Προβολή εικόνων στο χάρτη"
 
 msgctxt "#31125"
 msgid "Press up for actor info"
-msgstr "Πίεσε πάνω βελάκι για πληροφορίες ηθοποιού"
+msgstr "Πατήστε το Επάνω βέλος για πληροφορίες ηθοποιού"
 
 msgctxt "#31126"
 msgid "Press OK to read plot"
-msgstr "Πίεσε ΟΚ για να διαβάσει plot"
+msgstr "Πατήστε ΟΚ για ανάγνωση πλοκής"
 
 msgctxt "#31127"
 msgid "Show icons"
@@ -534,16 +534,24 @@ msgstr "Συντελεστές"
 
 msgctxt "#31129"
 msgid "General settings applying to all areas of the skin."
-msgstr "Οι Γενικές ρυθμίσεις θα εφαρμοστούν σε όλες τις περιοχές του κελύφους"
+msgstr "Γενικές ρυθμίσεις που εφαρμόζονται σε όλες τις περιοχές του κελύφους"
 
 msgctxt "#31130"
 msgid "Main menu-related settings: Configure the home screen to your likings."
-msgstr "Βασικό μενού-σχετιζόμενες ρυθμίσεις: Ρυθμίστε την αρχική οθόνη στα γούστα σας."
+msgstr "Ρυθμίσεις βασικού μενού: Ρυθμίστε την αρχική οθόνη βάσει των προτιμήσεών σας."
 
 msgctxt "#31131"
 msgid "Choose home fanart pack"
-msgstr "Επέλεξε πακέτο fanart για κεντρικό"
+msgstr "Επιλέξτε κεντρικό πακέτο fanart"
 
 msgctxt "#31132"
 msgid "min"
 msgstr "λεπτά"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Απόκρυψη"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "Απομένουν"
diff --git a/addons/skin.estuary/language/resource.language.en_au/strings.po b/addons/skin.estuary/language/resource.language.en_au/strings.po
index f6206a9..f52cfa2 100644
--- a/addons/skin.estuary/language/resource.language.en_au/strings.po
+++ b/addons/skin.estuary/language/resource.language.en_au/strings.po
@@ -71,3 +71,7 @@ msgstr "Local subtitle available"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Hide"
diff --git a/addons/skin.estuary/language/resource.language.en_gb/strings.po b/addons/skin.estuary/language/resource.language.en_gb/strings.po
index 53d71e9..88d56e4 100644
--- a/addons/skin.estuary/language/resource.language.en_gb/strings.po
+++ b/addons/skin.estuary/language/resource.language.en_gb/strings.po
@@ -690,3 +690,38 @@ msgstr ""
 msgctxt "#31134"
 msgid "Remaining"
 msgstr ""
+
+#: /1080i/DialogAddonInfo.xml
+msgctxt "#31135"
+msgid "Installed from"
+msgstr ""
+
+#: /1080i/DialogAddonInfo.xml
+msgctxt "#31136"
+msgid "Click here to see latest changes..."
+msgstr ""
+
+#: /1080i/DialogPlayerProcessInfo.xml
+msgctxt "#31137"
+msgid "PVR info"
+msgstr ""
+
+#: /1080i/DialogPlayerProcessInfo.xml
+msgctxt "#31138"
+msgid "Player process info"
+msgstr ""
+
+#: /1080i/DialogPlayerProcessInfo.xml
+msgctxt "#31139"
+msgid "Video decoder"
+msgstr ""
+
+#: /1080i/DialogPlayerProcessInfo.xml
+msgctxt "#31140"
+msgid "Pixel format"
+msgstr ""
+
+#: /1080i/DialogAddonInfo.xml
+msgctxt "#31141"
+msgid "Changes for version"
+msgstr ""
diff --git a/addons/skin.estuary/language/resource.language.en_nz/strings.po b/addons/skin.estuary/language/resource.language.en_nz/strings.po
index 00333ab..b84ea25 100644
--- a/addons/skin.estuary/language/resource.language.en_nz/strings.po
+++ b/addons/skin.estuary/language/resource.language.en_nz/strings.po
@@ -543,3 +543,7 @@ msgstr "Choose home fanart pack"
 msgctxt "#31132"
 msgid "min"
 msgstr "min"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Hide"
diff --git a/addons/skin.estuary/language/resource.language.en_us/strings.po b/addons/skin.estuary/language/resource.language.en_us/strings.po
index edaed44..9b1f99f 100644
--- a/addons/skin.estuary/language/resource.language.en_us/strings.po
+++ b/addons/skin.estuary/language/resource.language.en_us/strings.po
@@ -543,3 +543,7 @@ msgstr "Choose home fanart pack"
 msgctxt "#31132"
 msgid "min"
 msgstr "min"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Hide"
diff --git a/addons/skin.estuary/language/resource.language.es_ar/strings.po b/addons/skin.estuary/language/resource.language.es_ar/strings.po
index 635d6e6..2a4f03a 100644
--- a/addons/skin.estuary/language/resource.language.es_ar/strings.po
+++ b/addons/skin.estuary/language/resource.language.es_ar/strings.po
@@ -123,3 +123,7 @@ msgstr "Seleccione su perfil de usuario de Kodi[CR]para ingresar y continuar"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Mays."
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Ocultar"
diff --git a/addons/skin.estuary/language/resource.language.es_es/strings.po b/addons/skin.estuary/language/resource.language.es_es/strings.po
index aa738c6..6f5b551 100644
--- a/addons/skin.estuary/language/resource.language.es_es/strings.po
+++ b/addons/skin.estuary/language/resource.language.es_es/strings.po
@@ -24,6 +24,14 @@ msgctxt "#31001"
 msgid "Search..."
 msgstr "Buscar..."
 
+msgctxt "#31002"
+msgid "Show media fanart as background"
+msgstr "Mostrar fanarts de medios como fondo"
+
+msgctxt "#31003"
+msgid "Cinema mode"
+msgstr "Modo cine"
+
 msgctxt "#31004"
 msgid "Change mode"
 msgstr "Cambiar modo"
@@ -32,6 +40,58 @@ msgctxt "#31005"
 msgid "Watch as 2D"
 msgstr "Ver en 2D"
 
+msgctxt "#31006"
+msgid "Random movies"
+msgstr "Películas aleatorias"
+
+msgctxt "#31007"
+msgid "Unwatched movies"
+msgstr "Películas no vistas"
+
+msgctxt "#31008"
+msgid "No disclaimer"
+msgstr "Sin avisos"
+
+msgctxt "#31009"
+msgid "Download icons"
+msgstr "Descargar iconos"
+
+msgctxt "#31010"
+msgid "In progress movies"
+msgstr "Películas en progreso"
+
+msgctxt "#31011"
+msgid "Most played albums"
+msgstr "Álbumes más reproducidos"
+
+msgctxt "#31012"
+msgid "Random albums"
+msgstr "Álbumes aleatorios"
+
+msgctxt "#31013"
+msgid "Random artists"
+msgstr "Artistas al azar"
+
+msgctxt "#31014"
+msgid "Unplayed albums"
+msgstr "Álbumes sin reproducir"
+
+msgctxt "#31015"
+msgid "Recent recordings"
+msgstr "Grabaciones recientes"
+
+msgctxt "#31016"
+msgid "Recently played channels"
+msgstr "Canales reproducidos recientemente"
+
+msgctxt "#31017"
+msgid "Rated"
+msgstr "Puntuados"
+
+msgctxt "#31018"
+msgid "Most played channels"
+msgstr "Canales más reproducidos"
+
 msgctxt "#31019"
 msgid "Forecast"
 msgstr "Pronóstico"
@@ -44,10 +104,70 @@ msgctxt "#31021"
 msgid "Misc options"
 msgstr "Opciones varias"
 
+msgctxt "#31022"
+msgid "Sort by"
+msgstr "Ordenar por"
+
+msgctxt "#31023"
+msgid "Viewtype"
+msgstr "Tipo de vista"
+
+msgctxt "#31024"
+msgid "Next tracks"
+msgstr "Siguientes pistas"
+
+msgctxt "#31025"
+msgid "No favourites found. You can add any item from media views to this list by using the context menu."
+msgstr "No se han encontrado favoritos. Puede añadir cualquier elemento desde las vistas de medios a esta lista usando el menú de contexto."
+
+msgctxt "#31026"
+msgid "Go to albums"
+msgstr "Ir a álbumes"
+
+msgctxt "#31027"
+msgid "Go to songs"
+msgstr "Ir a canciones"
+
+msgctxt "#31028"
+msgid "Show fanart"
+msgstr "Mostrar fanart"
+
 msgctxt "#31029"
 msgid "Last logged in"
 msgstr "Última sesión el"
 
+msgctxt "#31030"
+msgid "Memory used"
+msgstr "Memoria usada"
+
+msgctxt "#31031"
+msgid "Version info"
+msgstr "Información de la versión"
+
+msgctxt "#31032"
+msgid "Order"
+msgstr "Ordenar"
+
+msgctxt "#31033"
+msgid "Your rating"
+msgstr "Tu puntuación"
+
+msgctxt "#31034"
+msgid "Extended info"
+msgstr "Información extendida"
+
+msgctxt "#31035"
+msgid "Pages"
+msgstr "Páginas"
+
+msgctxt "#31036"
+msgid "items"
+msgstr "elementos"
+
+msgctxt "#31037"
+msgid "Tracklist"
+msgstr "Lista de canciones"
+
 msgctxt "#31038"
 msgid "Rewind"
 msgstr "Retroceder"
@@ -56,10 +176,22 @@ msgctxt "#31039"
 msgid "Fast forward"
 msgstr "Avance rápido"
 
+msgctxt "#31040"
+msgid "Cancel update"
+msgstr "Cancelar actualización"
+
+msgctxt "#31041"
+msgid "Camera manufacturer"
+msgstr "Fabricante de la cámara"
+
 msgctxt "#31042"
 msgid "Playlist options"
 msgstr "Opciones de lista de reproducción"
 
+msgctxt "#31043"
+msgid "Set the type and add rules to create a smart playlist. These playlists are dynamic and include all media items from your database which apply to your chosen rules."
+msgstr "Escoja el tipo y añada reglas para crear listas de reproducción inteligentes. Estas listas son dinámicas e incluyen aquellos elementos de su base de datos en los que aplican las reglas escogidas."
+
 msgctxt "#31044"
 msgid "Add group"
 msgstr "Añadir Grupo"
@@ -72,18 +204,142 @@ msgctxt "#31046"
 msgid "Delete group"
 msgstr "Borrar Grupo"
 
+msgctxt "#31047"
+msgid "Read more..."
+msgstr "Leer más..."
+
+msgctxt "#31048"
+msgid "Available"
+msgstr "Disponible"
+
+msgctxt "#31049"
+msgid "Press [B]Up[/B] to rewind or fast-forward"
+msgstr "Presione [B]Arriba[/B] para rebobinar o adelantar"
+
+msgctxt "#31050"
+msgid "Press [B]OK[/B] to stop"
+msgstr "Presione [B]OK[/B] para detener"
+
+msgctxt "#31051"
+msgid "Toggle language"
+msgstr "Cambiar idioma"
+
+msgctxt "#31052"
+msgid "filtered"
+msgstr "filtrado"
+
 msgctxt "#31053"
 msgid "Arial based"
 msgstr "Basada en Arial"
 
+msgctxt "#31054"
+msgid "Press [B]Left[/B] to rewind, or [B]Right[/B] to fast-forward"
+msgstr "Presione [B]Izquierda[/B] para rebobinar, o [B]Derecha[/B] para adelantar"
+
+msgctxt "#31055"
+msgid "Subtitle download"
+msgstr "Descargar subtítulos"
+
+msgctxt "#31056"
+msgid "Go to playlist"
+msgstr "Ir a lista de reproducción"
+
+msgctxt "#31057"
+msgid "Show login screen on startup"
+msgstr "Mostrar pantalla de inicio de sesión al inicio"
+
+msgctxt "#31058"
+msgid "Automatic Login on startup"
+msgstr "Iniciar sesión automáticamente"
+
+msgctxt "#31059"
+msgid "Updates available"
+msgstr "Actualizaciones disponibles"
+
+msgctxt "#31060"
+msgid "minutes"
+msgstr "minutos"
+
+msgctxt "#31061"
+msgid "Main menu items"
+msgstr "Elementos del menú principal"
+
+msgctxt "#31062"
+msgid "Shortcuts to the \"Files\" sections of each media type. Go there to add additional sources for your databases."
+msgstr "Accesos directos a la sección \"Archivos\" de cada tipo de medio. Úsalo para añadir fuentes adicionales a tus bases de datos."
+
+msgctxt "#31063"
+msgid "Sections"
+msgstr "Secciones"
+
+msgctxt "#31064"
+msgid "unwatched"
+msgstr "no vistos"
+
+msgctxt "#31065"
+msgid "Video playlist"
+msgstr "Lista de reproducción de video"
+
+msgctxt "#31066"
+msgid "Music playlist"
+msgstr "Lista de reproducción de música"
+
+msgctxt "#31067"
+msgid "Event log"
+msgstr "Log de eventos"
+
+msgctxt "#31068"
+msgid "Choose presets"
+msgstr "Escoge ajustes por defecto"
+
 msgctxt "#31069"
 msgid "Last Updated"
 msgstr "Última actualización"
 
+msgctxt "#31070"
+msgid "Add media sources"
+msgstr "Añadir fuentes de medios"
+
+msgctxt "#31071"
+msgid "by"
+msgstr "pot"
+
 msgctxt "#31072"
 msgid "Power Options"
 msgstr "Opciones de energía"
 
+msgctxt "#31073"
+msgid "Titles"
+msgstr "Títulos"
+
+msgctxt "#31074"
+msgid "Library root"
+msgstr "Raiz de colección"
+
+msgctxt "#31075"
+msgid "Movie sets"
+msgstr "Sagas de películas"
+
+msgctxt "#31076"
+msgid "Play optical disc"
+msgstr "Reproducir disco óptico"
+
+msgctxt "#31077"
+msgid "Previous location"
+msgstr "Ubicación anterior"
+
+msgctxt "#31078"
+msgid "Next location"
+msgstr "Próxima ubicación"
+
+msgctxt "#31079"
+msgid "Cast not available"
+msgstr "Reparto no disponible"
+
+msgctxt "#31080"
+msgid "Ends at"
+msgstr "Finaliza a las "
+
 msgctxt "#31081"
 msgid "Album info"
 msgstr "Información de álbum"
@@ -92,6 +348,14 @@ msgctxt "#31082"
 msgid "Lyrics add-on"
 msgstr "Add-on para letras"
 
+msgctxt "#31083"
+msgid "Lyrics add-on settings"
+msgstr "Ajustes del addon de letras"
+
+msgctxt "#31084"
+msgid "Visualisation settings"
+msgstr "Ajustes de visualización"
+
 msgctxt "#31085"
 msgid "Channel Group"
 msgstr "Grupo de canales"
@@ -100,6 +364,10 @@ msgctxt "#31086"
 msgid "Metadata"
 msgstr "Metadatos"
 
+msgctxt "#31087"
+msgid "Provider settings"
+msgstr "Ajustes de proveedor"
+
 msgctxt "#31088"
 msgid "Content scanning options"
 msgstr "Opciones de escaneo de contenido"
@@ -108,10 +376,30 @@ msgctxt "#31089"
 msgid "Available groups"
 msgstr "Grupos disponibles"
 
+msgctxt "#31090"
+msgid "Search trailer"
+msgstr "Buscar trailer"
+
 msgctxt "#31091"
 msgid "Download subtitles"
 msgstr "Descargar subtítulos"
 
+msgctxt "#31092"
+msgid "Video menu"
+msgstr "Menú de video"
+
+msgctxt "#31093"
+msgid "Show weather info in top bar"
+msgstr "Mostrar información meteorológica en la barra superior"
+
+msgctxt "#31094"
+msgid "Show media flags for movies / episodes / music videos"
+msgstr "Mostrar íconos de información (media flags) para películas, episodios y vídeos musicales"
+
+msgctxt "#31095"
+msgid "Use slide animations"
+msgstr "Usar animaciones de desplazamiento"
+
 msgctxt "#31096"
 msgid "Local subtitle available"
 msgstr "Subtítulo local disponible"
@@ -124,10 +412,146 @@ msgctxt "#31098"
 msgid "Select your Kodi user profile[CR]to login and continue"
 msgstr "Seleccione su perfil de usuario de Kodi[CR]para ingresar y continuar"
 
+msgctxt "#31099"
+msgid "Icon Wall"
+msgstr "Muro de iconos"
+
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Mays."
 
+msgctxt "#31101"
+msgid "InfoWall"
+msgstr "Muro de información"
+
+msgctxt "#31102"
+msgid "Wall"
+msgstr "Muro"
+
+msgctxt "#31103"
+msgid "Enter text here..."
+msgstr "Introduzca el texto aquí..."
+
+msgctxt "#31104"
+msgid "Your library is currently empty. In order to populate it with your personal media, enter \"Files\" section, add a media source and configure it. After the source has been added and indexed you will be able to browse your library."
+msgstr "Su colección se encuentra vacia. Para proveerla de contenidos, entre en la sección \"Archivos\", añada un origen de medios y configúrelo. Después de que se añada e indexe esta nueva fuente, podrá navegar su colección."
+
+msgctxt "#31105"
+msgid "Add video sources and set the appropriate content type in order to populate your video libraries."
+msgstr "Añada fuentes de vídeo y configure el tipo de contenido apropiado para poblar tus colecciones de vídeo."
+
 msgctxt "#31106"
 msgid "Teletext"
 msgstr "Teletexto"
+
+msgctxt "#31107"
+msgid "WideList"
+msgstr "Lista amplia"
+
+msgctxt "#31108"
+msgid "Use custom global background"
+msgstr "Usar un fondo global personalizado"
+
+msgctxt "#31109"
+msgid "Choose image path"
+msgstr "Elegir ruta de imágenes"
+
+msgctxt "#31110"
+msgid "Enter files section"
+msgstr "Entrar en la sección Archivos"
+
+msgctxt "#31111"
+msgid "View your personal pictures or download one of the many image add-ons from the official repository."
+msgstr "Vea sus imágenes personales o descargue uno de los múltiples addons de imágenes del repositorio oficial."
+
+msgctxt "#31112"
+msgid "Toggle audio stream"
+msgstr "Cambiar canal de audio"
+
+msgctxt "#31113"
+msgid "Search local library"
+msgstr "Buscar en la colección local"
+
+msgctxt "#31114"
+msgid "Search YouTube"
+msgstr "Buscar en YouTube"
+
+msgctxt "#31115"
+msgid "Search TheMovieDB"
+msgstr "Buscar en TheMovieDB"
+
+msgctxt "#31116"
+msgid "Remove this main menu item"
+msgstr "Eliminar este elemento del menú principal"
+
+msgctxt "#31117"
+msgid "Edit nodes"
+msgstr "Editar nodos"
+
+msgctxt "#31118"
+msgid "Enter add-on browser"
+msgstr "Entrar en el navegador de Addons"
+
+msgctxt "#31119"
+msgid "You do not have any add-ons installed yet. Visit our add-on browser to browse through our collection and improve your Kodi experience."
+msgstr "No tiene instalado ningún addon aun. Visite nuestro navegador de addons para navegar a través de nuestra colección y mejorar la experiencia de Kodi."
+
+msgctxt "#31120"
+msgid "You did not set up a weather provider yet. In order to view weather information, choose a weather provider and set up your location."
+msgstr "No ha configurado aun un proveedor de Tiempo. Para poder consultar el Tiempo, elija un proveedor y establezca su localización."
+
+msgctxt "#31121"
+msgid "Set weather provider"
+msgstr "Establecer proveedor de Tiempo"
+
+msgctxt "#31122"
+msgid "Unwatched TV Shows"
+msgstr "Series no vistas"
+
+msgctxt "#31123"
+msgid "Same director"
+msgstr "Mismo director"
+
+msgctxt "#31124"
+msgid "Show images on map"
+msgstr "Mostrar imágenes en un mapa"
+
+msgctxt "#31125"
+msgid "Press up for actor info"
+msgstr "Presione Arriba para ver información del actor"
+
+msgctxt "#31126"
+msgid "Press OK to read plot"
+msgstr "Presione Ok para leer el argumento"
+
+msgctxt "#31127"
+msgid "Show icons"
+msgstr "Mostrar Iconos"
+
+msgctxt "#31128"
+msgid "Contributors"
+msgstr "Colaboradores"
+
+msgctxt "#31129"
+msgid "General settings applying to all areas of the skin."
+msgstr "Los ajustes generales aplican a todas las áreas del skin."
+
+msgctxt "#31130"
+msgid "Main menu-related settings: Configure the home screen to your likings."
+msgstr "Ajustes relativos al menú principal: configuré la pantalla principal a su gusto."
+
+msgctxt "#31131"
+msgid "Choose home fanart pack"
+msgstr "Elija un pack de fanarts para el inicio"
+
+msgctxt "#31132"
+msgid "min"
+msgstr "minutos"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Ocultar"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "Restante"
diff --git a/addons/skin.estuary/language/resource.language.es_mx/strings.po b/addons/skin.estuary/language/resource.language.es_mx/strings.po
index 6c76b2d..86051f2 100644
--- a/addons/skin.estuary/language/resource.language.es_mx/strings.po
+++ b/addons/skin.estuary/language/resource.language.es_mx/strings.po
@@ -67,3 +67,7 @@ msgstr "Subtítulo local disponible"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Mays."
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Esconder"
diff --git a/addons/skin.estuary/language/resource.language.et_ee/strings.po b/addons/skin.estuary/language/resource.language.et_ee/strings.po
index 8df411c..6c51b7f 100644
--- a/addons/skin.estuary/language/resource.language.et_ee/strings.po
+++ b/addons/skin.estuary/language/resource.language.et_ee/strings.po
@@ -67,3 +67,7 @@ msgstr "Lokaalsed subtiitrid on saadaval"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Nihe"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Peida"
diff --git a/addons/skin.estuary/language/resource.language.eu_es/strings.po b/addons/skin.estuary/language/resource.language.eu_es/strings.po
index 7fad6b5..800324a 100644
--- a/addons/skin.estuary/language/resource.language.eu_es/strings.po
+++ b/addons/skin.estuary/language/resource.language.eu_es/strings.po
@@ -127,3 +127,7 @@ msgstr "Shift"
 msgctxt "#31106"
 msgid "Teletext"
 msgstr "Teletestua"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Ezkutatu"
diff --git a/addons/skin.estuary/language/resource.language.fa_af/strings.po b/addons/skin.estuary/language/resource.language.fa_af/strings.po
index b50f5b0..89af587 100644
--- a/addons/skin.estuary/language/resource.language.fa_af/strings.po
+++ b/addons/skin.estuary/language/resource.language.fa_af/strings.po
@@ -19,3 +19,7 @@ msgstr ""
 msgctxt "#31001"
 msgid "Search..."
 msgstr "جستجو..."
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "مخفی"
diff --git a/addons/skin.estuary/language/resource.language.fa_ir/strings.po b/addons/skin.estuary/language/resource.language.fa_ir/strings.po
index 10a9e83..06acd48 100644
--- a/addons/skin.estuary/language/resource.language.fa_ir/strings.po
+++ b/addons/skin.estuary/language/resource.language.fa_ir/strings.po
@@ -95,3 +95,7 @@ msgstr "زیر نویس محلی موجود"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "مخفی کردن"
diff --git a/addons/skin.estuary/language/resource.language.fi_fi/strings.po b/addons/skin.estuary/language/resource.language.fi_fi/strings.po
index 78bd68a..c37165e 100644
--- a/addons/skin.estuary/language/resource.language.fi_fi/strings.po
+++ b/addons/skin.estuary/language/resource.language.fi_fi/strings.po
@@ -26,7 +26,7 @@ msgstr "Etsi..."
 
 msgctxt "#31002"
 msgid "Show media fanart as background"
-msgstr "Naytä "
+msgstr "Käytä fanitaidetta taustakuvana"
 
 msgctxt "#31003"
 msgid "Cinema mode"
@@ -54,7 +54,7 @@ msgstr "Ei huomautusta"
 
 msgctxt "#31009"
 msgid "Download icons"
-msgstr "Lataa ikonit"
+msgstr "Lataa kuvakkeet"
 
 msgctxt "#31010"
 msgid "In progress movies"
@@ -80,6 +80,14 @@ msgctxt "#31015"
 msgid "Recent recordings"
 msgstr "Viimeaikaiset tallennukset"
 
+msgctxt "#31016"
+msgid "Recently played channels"
+msgstr "Viimeksi katsotut kanavat"
+
+msgctxt "#31017"
+msgid "Rated"
+msgstr "Ikäraja"
+
 msgctxt "#31018"
 msgid "Most played channels"
 msgstr "Eniten katsotut kanavat"
@@ -102,12 +110,16 @@ msgstr "Järjestä"
 
 msgctxt "#31023"
 msgid "Viewtype"
-msgstr "Näyttötyyppi"
+msgstr "Näkymä"
 
 msgctxt "#31024"
 msgid "Next tracks"
 msgstr "Seuraavat raidat"
 
+msgctxt "#31025"
+msgid "No favourites found. You can add any item from media views to this list by using the context menu."
+msgstr "Suosikkeja ei löytynyt. Avaa kontekstivalikko haluamasi mediatiedoston kohdalla ja valitse \"Lisää suosikkeihin\"."
+
 msgctxt "#31026"
 msgid "Go to albums"
 msgstr "Siirry albumeihin"
@@ -130,7 +142,7 @@ msgstr "Käytetty muisti"
 
 msgctxt "#31031"
 msgid "Version info"
-msgstr "Versiotieto"
+msgstr "Versiotiedot"
 
 msgctxt "#31032"
 msgid "Order"
@@ -138,7 +150,11 @@ msgstr "Järjestys"
 
 msgctxt "#31033"
 msgid "Your rating"
-msgstr "Sinun arviosi"
+msgstr "Oma arvosana"
+
+msgctxt "#31034"
+msgid "Extended info"
+msgstr "Laajennettu info"
 
 msgctxt "#31035"
 msgid "Pages"
@@ -148,6 +164,10 @@ msgctxt "#31036"
 msgid "items"
 msgstr "kohdetta"
 
+msgctxt "#31037"
+msgid "Tracklist"
+msgstr "Kappalelista"
+
 msgctxt "#31038"
 msgid "Rewind"
 msgstr "Kelaa taaksepäin"
@@ -168,6 +188,10 @@ msgctxt "#31042"
 msgid "Playlist options"
 msgstr "Toistolistan asetukset"
 
+msgctxt "#31043"
+msgid "Set the type and add rules to create a smart playlist. These playlists are dynamic and include all media items from your database which apply to your chosen rules."
+msgstr "Valitse älykkään toistolistan tyyppi ja hakuehdot. Tälle automaattisesti päivittyvälle listalle lisätään kaikki mediakirjastosi kohteet, jotka täyttävät asettamasi ehdot."
+
 msgctxt "#31044"
 msgid "Add group"
 msgstr "Lisää ryhmä"
@@ -188,13 +212,17 @@ msgctxt "#31048"
 msgid "Available"
 msgstr "Saatavilla"
 
+msgctxt "#31049"
+msgid "Press [B]Up[/B] to rewind or fast-forward"
+msgstr "Kelaa painamalla [B]Ylös[/B]"
+
 msgctxt "#31050"
 msgid "Press [B]OK[/B] to stop"
-msgstr "Paina [B]OK[/B] pysäyttääksesi"
+msgstr "Pysäytä painamalla [B]OK[/B]"
 
 msgctxt "#31051"
 msgid "Toggle language"
-msgstr "Vaihda kieli"
+msgstr "Tekstitysraita"
 
 msgctxt "#31052"
 msgid "filtered"
@@ -202,7 +230,11 @@ msgstr "suodatetut"
 
 msgctxt "#31053"
 msgid "Arial based"
-msgstr "Arial pohjainen"
+msgstr "Arial-pohjainen"
+
+msgctxt "#31054"
+msgid "Press [B]Left[/B] to rewind, or [B]Right[/B] to fast-forward"
+msgstr "Kelaa painamalla [B]Vasen[/B] tai [B]Oikea[/B]"
 
 msgctxt "#31055"
 msgid "Subtitle download"
@@ -210,7 +242,7 @@ msgstr "Tekstityksen lataus"
 
 msgctxt "#31056"
 msgid "Go to playlist"
-msgstr "Mene soittolistaan"
+msgstr "Mene toistolistaan"
 
 msgctxt "#31057"
 msgid "Show login screen on startup"
@@ -230,7 +262,15 @@ msgstr "minuuttia"
 
 msgctxt "#31061"
 msgid "Main menu items"
-msgstr "Päävalikon kohteet"
+msgstr "Päävalikko"
+
+msgctxt "#31062"
+msgid "Shortcuts to the \"Files\" sections of each media type. Go there to add additional sources for your databases."
+msgstr "Pikakuvakkeet eri mediatyyppien tiedostonäkymiin. Tiedostonäkymän kautta voit lisätä uusia lähteitä mediakirjastoosi."
+
+msgctxt "#31063"
+msgid "Sections"
+msgstr "Osiot"
 
 msgctxt "#31064"
 msgid "unwatched"
@@ -238,7 +278,7 @@ msgstr "katsomaton"
 
 msgctxt "#31065"
 msgid "Video playlist"
-msgstr "Videosoittolista"
+msgstr "Videotoistolista"
 
 msgctxt "#31066"
 msgid "Music playlist"
@@ -260,17 +300,29 @@ msgctxt "#31070"
 msgid "Add media sources"
 msgstr "Lisää medialähteitä"
 
+msgctxt "#31071"
+msgid "by"
+msgstr "Tekijä:"
+
 msgctxt "#31072"
 msgid "Power Options"
 msgstr "Virta-asetukset"
 
 msgctxt "#31073"
 msgid "Titles"
-msgstr "Kappaleet"
+msgstr "Nimet"
 
 msgctxt "#31074"
 msgid "Library root"
-msgstr "Kirjasto päävalikko"
+msgstr "Kirjaston päävalikko"
+
+msgctxt "#31075"
+msgid "Movie sets"
+msgstr "Elokuvasetit"
+
+msgctxt "#31076"
+msgid "Play optical disc"
+msgstr "Toista optinen levy"
 
 msgctxt "#31077"
 msgid "Previous location"
@@ -280,9 +332,13 @@ msgctxt "#31078"
 msgid "Next location"
 msgstr "Seuraava sijainti"
 
+msgctxt "#31079"
+msgid "Cast not available"
+msgstr "Ei esiintyjätietoja"
+
 msgctxt "#31080"
 msgid "Ends at"
-msgstr "loppuu"
+msgstr "Päättyy"
 
 msgctxt "#31081"
 msgid "Album info"
@@ -304,9 +360,13 @@ msgctxt "#31085"
 msgid "Channel Group"
 msgstr "Kanavaryhmä"
 
+msgctxt "#31086"
+msgid "Metadata"
+msgstr "Metatieto"
+
 msgctxt "#31087"
 msgid "Provider settings"
-msgstr "Tarjoaja asetukset"
+msgstr "Tarjoaja-asetukset"
 
 msgctxt "#31088"
 msgid "Content scanning options"
@@ -314,11 +374,11 @@ msgstr "Sisällön hakuasetukset"
 
 msgctxt "#31089"
 msgid "Available groups"
-msgstr "Saatavilla olevat ryhmät"
+msgstr "Kanavaryhmät"
 
 msgctxt "#31090"
 msgid "Search trailer"
-msgstr "Etsi esittely"
+msgstr "Etsi traileria"
 
 msgctxt "#31091"
 msgid "Download subtitles"
@@ -328,13 +388,25 @@ msgctxt "#31092"
 msgid "Video menu"
 msgstr "Elokuvavalikko"
 
+msgctxt "#31093"
+msgid "Show weather info in top bar"
+msgstr "Näytä säätiedot yläpalkissa"
+
+msgctxt "#31094"
+msgid "Show media flags for movies / episodes / music videos"
+msgstr "Näytä video- ja musiikkitiedostojen mediatiedot"
+
+msgctxt "#31095"
+msgid "Use slide animations"
+msgstr "Käytä liukuanimaatioita"
+
 msgctxt "#31096"
 msgid "Local subtitle available"
 msgstr "Paikallinen tekstitys saatavilla"
 
 msgctxt "#31097"
 msgid "Channel options"
-msgstr "Kanavan valinnat"
+msgstr "Kanava-asetukset"
 
 msgctxt "#31098"
 msgid "Select your Kodi user profile[CR]to login and continue"
@@ -342,7 +414,7 @@ msgstr "Valitse Kodi-käyttäjäprofiili[CR]kirjautuaksesi sisään"
 
 msgctxt "#31099"
 msgid "Icon Wall"
-msgstr "Kuvake seinä"
+msgstr "Kuvakeseinä"
 
 msgctxt "#31100"
 msgid "Shift"
@@ -358,27 +430,75 @@ msgstr "Seinä"
 
 msgctxt "#31103"
 msgid "Enter text here..."
-msgstr "lisää teksti tähän.."
+msgstr "Kirjoita tähän..."
+
+msgctxt "#31104"
+msgid "Your library is currently empty. In order to populate it with your personal media, enter \"Files\" section, add a media source and configure it. After the source has been added and indexed you will be able to browse your library."
+msgstr "Mediakirjastosi on tällä hetkellä tyhjä. Avaa tiedostonäkymä ja lisää käyttämäsi medialähde. Valitse medialähteellesi sopiva tietojen tarjoaja tietojen noutamista varten. Kun tiedot ovat latautuneet, voit selata mediakirjastoasi."
+
+msgctxt "#31105"
+msgid "Add video sources and set the appropriate content type in order to populate your video libraries."
+msgstr "Lisää sisältöä videokirjastoosi valitsemalla käyttämäsi videolähde ja asettamalla sen sisältötyyppi."
 
 msgctxt "#31106"
 msgid "Teletext"
 msgstr "Teksti-tv"
 
+msgctxt "#31107"
+msgid "WideList"
+msgstr "Leveä lista"
+
+msgctxt "#31108"
+msgid "Use custom global background"
+msgstr "Valinnainen taustakuva käytössä"
+
 msgctxt "#31109"
 msgid "Choose image path"
 msgstr "Valitse kuvan polku"
 
+msgctxt "#31110"
+msgid "Enter files section"
+msgstr "Avaa tiedostonäkymä"
+
+msgctxt "#31111"
+msgid "View your personal pictures or download one of the many image add-ons from the official repository."
+msgstr "Katsele omia kuvatiedostojasi tai asenna kuvalisäosia virallisesta ohjelmavarastosta."
+
+msgctxt "#31112"
+msgid "Toggle audio stream"
+msgstr "Ääniraita"
+
 msgctxt "#31113"
 msgid "Search local library"
-msgstr "Etsi paikallinen kirjasto"
+msgstr "Etsi mediakirjastosta"
 
 msgctxt "#31114"
 msgid "Search YouTube"
-msgstr "Etsi YouTube"
+msgstr "Etsi YouTubesta"
 
 msgctxt "#31115"
 msgid "Search TheMovieDB"
-msgstr "Etsi TheMovieDB"
+msgstr "Etsi TheMovieDB:stä"
+
+msgctxt "#31116"
+msgid "Remove this main menu item"
+msgstr "Poista tämä kohde päävalikosta"
+
+msgctxt "#31117"
+msgid "Edit nodes"
+msgstr "Muokkaa kansioita"
+
+msgctxt "#31118"
+msgid "Enter add-on browser"
+msgstr "Avaa lisäosaselain"
+
+msgctxt "#31119"
+msgid "You do not have any add-ons installed yet. Visit our add-on browser to browse through our collection and improve your Kodi experience."
+msgstr "Yhtään lisäosaa ei ole asennettuna. Lisäosaselaimen kautta voit tutkia Kodin virallista lisäosatarjontaa ja lisätä ohjelmaan uusia toimintoja."
+
+msgctxt "#31120"
+msgid "You did not set up a weather provider yet. In order to view weather information, choose a weather provider and set up your location."
+msgstr "Säätietojen tarjoajaa ei ole asennettu. Nähdäksesi säätiedot, asenna haluamasi sääpalvelu ja valitse sijaintisi."
 
 msgctxt "#31121"
 msgid "Set weather provider"
@@ -386,20 +506,52 @@ msgstr "Aseta sään tarjoaja"
 
 msgctxt "#31122"
 msgid "Unwatched TV Shows"
-msgstr "Katsomattomat TV sarjat"
+msgstr "Katsomattomat tv-sarjat"
 
 msgctxt "#31123"
 msgid "Same director"
-msgstr "Sama ohjaaja"
+msgstr "Ohjaajahaku"
 
 msgctxt "#31124"
 msgid "Show images on map"
 msgstr "Näytä kuvat kartalla"
 
+msgctxt "#31125"
+msgid "Press up for actor info"
+msgstr "Näyttelijätiedot (Paina YLÖS)"
+
+msgctxt "#31126"
+msgid "Press OK to read plot"
+msgstr "Juoni (Paina OK)"
+
 msgctxt "#31127"
 msgid "Show icons"
-msgstr "Näytä kuvakkeet"
+msgstr "Näytä kanavalogot"
+
+msgctxt "#31128"
+msgid "Contributors"
+msgstr "Tekijät"
+
+msgctxt "#31129"
+msgid "General settings applying to all areas of the skin."
+msgstr "Tämä kategoria sisältää ulkoasun yleisasetukset."
+
+msgctxt "#31130"
+msgid "Main menu-related settings: Configure the home screen to your likings."
+msgstr "Tämä kategoria sisältää päävalikkoon liittyvät asetukset."
+
+msgctxt "#31131"
+msgid "Choose home fanart pack"
+msgstr "Valitse päävalikon taustakuvapaketti"
 
 msgctxt "#31132"
 msgid "min"
 msgstr "min"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Piilota"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "Jäljellä"
diff --git a/addons/skin.estuary/language/resource.language.fo_fo/strings.po b/addons/skin.estuary/language/resource.language.fo_fo/strings.po
index 43af9b6..5453bc9 100644
--- a/addons/skin.estuary/language/resource.language.fo_fo/strings.po
+++ b/addons/skin.estuary/language/resource.language.fo_fo/strings.po
@@ -47,3 +47,7 @@ msgstr "Rás bólkur"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Stórt"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Goym"
diff --git a/addons/skin.estuary/language/resource.language.fr_ca/strings.po b/addons/skin.estuary/language/resource.language.fr_ca/strings.po
index b4a2162..995b888 100644
--- a/addons/skin.estuary/language/resource.language.fr_ca/strings.po
+++ b/addons/skin.estuary/language/resource.language.fr_ca/strings.po
@@ -547,3 +547,11 @@ msgstr "Choisir le paquet de fanart de l'accueil"
 msgctxt "#31132"
 msgid "min"
 msgstr "min"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Masquer"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "Restant"
diff --git a/addons/skin.estuary/language/resource.language.fr_fr/strings.po b/addons/skin.estuary/language/resource.language.fr_fr/strings.po
index 627d961..9ce6b5e 100644
--- a/addons/skin.estuary/language/resource.language.fr_fr/strings.po
+++ b/addons/skin.estuary/language/resource.language.fr_fr/strings.po
@@ -547,3 +547,11 @@ msgstr "Choisir le paquet de FanArt pour l'accueil"
 msgctxt "#31132"
 msgid "min"
 msgstr "min"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Masquer"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "Restant"
diff --git a/addons/skin.estuary/language/resource.language.gl_es/strings.po b/addons/skin.estuary/language/resource.language.gl_es/strings.po
index ce647a6..d5d2f81 100644
--- a/addons/skin.estuary/language/resource.language.gl_es/strings.po
+++ b/addons/skin.estuary/language/resource.language.gl_es/strings.po
@@ -24,6 +24,10 @@ msgctxt "#31001"
 msgid "Search..."
 msgstr "Buscar..."
 
+msgctxt "#31002"
+msgid "Show media fanart as background"
+msgstr "Amosar os fanart como fondo"
+
 msgctxt "#31003"
 msgid "Cinema mode"
 msgstr "Modo cine"
@@ -156,6 +160,10 @@ msgctxt "#31036"
 msgid "items"
 msgstr "Elementos"
 
+msgctxt "#31037"
+msgid "Tracklist"
+msgstr "Lista de pistas"
+
 msgctxt "#31038"
 msgid "Rewind"
 msgstr "Atrás"
@@ -503,3 +511,11 @@ msgstr "Colaboradores"
 msgctxt "#31132"
 msgid "min"
 msgstr "mín."
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Agochar"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "Restante"
diff --git a/addons/skin.estuary/language/resource.language.he_il/strings.po b/addons/skin.estuary/language/resource.language.he_il/strings.po
index 1d345a8..7edc241 100644
--- a/addons/skin.estuary/language/resource.language.he_il/strings.po
+++ b/addons/skin.estuary/language/resource.language.he_il/strings.po
@@ -483,3 +483,7 @@ msgstr "תורמים"
 msgctxt "#31131"
 msgid "Choose home fanart pack"
 msgstr "בחירת חבילת אומנות אוהדים כבית"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "הסתר"
diff --git a/addons/skin.estuary/language/resource.language.hr_hr/strings.po b/addons/skin.estuary/language/resource.language.hr_hr/strings.po
index d48a706..4aa615a 100644
--- a/addons/skin.estuary/language/resource.language.hr_hr/strings.po
+++ b/addons/skin.estuary/language/resource.language.hr_hr/strings.po
@@ -119,3 +119,7 @@ msgstr "Odaberite svoj Kodi korisnički profil[CR]za prijavu i nastavak"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Sakrij"
diff --git a/addons/skin.estuary/language/resource.language.hu_hu/strings.po b/addons/skin.estuary/language/resource.language.hu_hu/strings.po
index ca95157..b796e36 100644
--- a/addons/skin.estuary/language/resource.language.hu_hu/strings.po
+++ b/addons/skin.estuary/language/resource.language.hu_hu/strings.po
@@ -547,3 +547,11 @@ msgstr "Válasszon főkepernyő illusztráció csomagot"
 msgctxt "#31132"
 msgid "min"
 msgstr "perc"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Elrejt"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "Hátralévő"
diff --git a/addons/skin.estuary/language/resource.language.hy_am/strings.po b/addons/skin.estuary/language/resource.language.hy_am/strings.po
index 7ab6d45..8350688 100644
--- a/addons/skin.estuary/language/resource.language.hy_am/strings.po
+++ b/addons/skin.estuary/language/resource.language.hy_am/strings.po
@@ -51,3 +51,7 @@ msgstr "Ô±Õ¶Õ»Õ¡Õ¿Õ´Õ¡Õ¶ Õ¿Õ¡Ö€Õ¢Õ¥Ö€Õ¡Õ¯Õ¶Õ¥Ö€"
 msgctxt "#31085"
 msgid "Channel Group"
 msgstr "Ô±Õ¬Õ«Ö„Õ¶Õ¥Ö€Õ« Õ­Õ¸Ö‚Õ´Õ¢"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Թաքցնել"
diff --git a/addons/skin.estuary/language/resource.language.id_id/strings.po b/addons/skin.estuary/language/resource.language.id_id/strings.po
index 66fa806..5656cac 100644
--- a/addons/skin.estuary/language/resource.language.id_id/strings.po
+++ b/addons/skin.estuary/language/resource.language.id_id/strings.po
@@ -119,3 +119,7 @@ msgstr "Pilih profil pengguna Kodi Anda [CR] untuk login dan lanjutkan"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Sembunyikan"
diff --git a/addons/skin.estuary/language/resource.language.is_is/strings.po b/addons/skin.estuary/language/resource.language.is_is/strings.po
index 43bbe58..df0649b 100644
--- a/addons/skin.estuary/language/resource.language.is_is/strings.po
+++ b/addons/skin.estuary/language/resource.language.is_is/strings.po
@@ -123,3 +123,7 @@ msgstr "Veldu Kodi notanda[CR]til að skrá þig inn og halda áfram"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Fela"
diff --git a/addons/skin.estuary/language/resource.language.it_it/strings.po b/addons/skin.estuary/language/resource.language.it_it/strings.po
index 4113b17..591d86b 100644
--- a/addons/skin.estuary/language/resource.language.it_it/strings.po
+++ b/addons/skin.estuary/language/resource.language.it_it/strings.po
@@ -547,3 +547,11 @@ msgstr "Scegli pacchetto fanart home"
 msgctxt "#31132"
 msgid "min"
 msgstr "min"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Nascondi"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "Rimanenti"
diff --git a/addons/skin.estuary/language/resource.language.ja_jp/strings.po b/addons/skin.estuary/language/resource.language.ja_jp/strings.po
index 8e7025c..ecbbf39 100644
--- a/addons/skin.estuary/language/resource.language.ja_jp/strings.po
+++ b/addons/skin.estuary/language/resource.language.ja_jp/strings.po
@@ -16,10 +16,22 @@ msgstr ""
 "Language: ja_JP\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
+msgctxt "#31000"
+msgid "Now playing"
+msgstr "再生中"
+
 msgctxt "#31001"
 msgid "Search..."
 msgstr "検索..."
 
+msgctxt "#31002"
+msgid "Show media fanart as background"
+msgstr "背景にメディアのファンアートを表示"
+
+msgctxt "#31003"
+msgid "Cinema mode"
+msgstr "シネマモード"
+
 msgctxt "#31004"
 msgid "Change mode"
 msgstr "モードを変更"
@@ -28,6 +40,58 @@ msgctxt "#31005"
 msgid "Watch as 2D"
 msgstr "2D で観る"
 
+msgctxt "#31006"
+msgid "Random movies"
+msgstr "ランダムの映画"
+
+msgctxt "#31007"
+msgid "Unwatched movies"
+msgstr "未視聴の映画"
+
+msgctxt "#31008"
+msgid "No disclaimer"
+msgstr "注意書きなし"
+
+msgctxt "#31009"
+msgid "Download icons"
+msgstr "ダウンロードアイコン"
+
+msgctxt "#31010"
+msgid "In progress movies"
+msgstr "進行中の映画"
+
+msgctxt "#31011"
+msgid "Most played albums"
+msgstr "最も再生したアルバム"
+
+msgctxt "#31012"
+msgid "Random albums"
+msgstr "ランダムアルバム"
+
+msgctxt "#31013"
+msgid "Random artists"
+msgstr "ランダムアーティスト"
+
+msgctxt "#31014"
+msgid "Unplayed albums"
+msgstr "未再生アルバム"
+
+msgctxt "#31015"
+msgid "Recent recordings"
+msgstr "最近の録画"
+
+msgctxt "#31016"
+msgid "Recently played channels"
+msgstr "最近再生したチャンネル"
+
+msgctxt "#31017"
+msgid "Rated"
+msgstr "評価済"
+
+msgctxt "#31018"
+msgid "Most played channels"
+msgstr "最も再生したチャンネル"
+
 msgctxt "#31019"
 msgid "Forecast"
 msgstr "予報"
@@ -36,34 +100,458 @@ msgctxt "#31020"
 msgid "Actions"
 msgstr "アクション"
 
+msgctxt "#31021"
+msgid "Misc options"
+msgstr "その他オプション"
+
+msgctxt "#31022"
+msgid "Sort by"
+msgstr "ソート"
+
+msgctxt "#31023"
+msgid "Viewtype"
+msgstr "表示タイプ"
+
+msgctxt "#31024"
+msgid "Next tracks"
+msgstr "次の曲"
+
+msgctxt "#31025"
+msgid "No favourites found. You can add any item from media views to this list by using the context menu."
+msgstr "お気に入りは見つかりませんでした。メディアビューでコンテキストメニューを使用してこのリストにアイテムを追加できます。"
+
+msgctxt "#31026"
+msgid "Go to albums"
+msgstr "アルバムへ"
+
+msgctxt "#31027"
+msgid "Go to songs"
+msgstr "曲へ"
+
+msgctxt "#31028"
+msgid "Show fanart"
+msgstr "ファンアートを見る"
+
+msgctxt "#31029"
+msgid "Last logged in"
+msgstr "最終ログイン"
+
+msgctxt "#31030"
+msgid "Memory used"
+msgstr "メモリ使用量"
+
+msgctxt "#31031"
+msgid "Version info"
+msgstr "バージョン情報"
+
+msgctxt "#31032"
+msgid "Order"
+msgstr "並べ替え"
+
+msgctxt "#31033"
+msgid "Your rating"
+msgstr "評価"
+
+msgctxt "#31034"
+msgid "Extended info"
+msgstr "メディア情報"
+
+msgctxt "#31035"
+msgid "Pages"
+msgstr "ページ"
+
+msgctxt "#31036"
+msgid "items"
+msgstr "アイテム"
+
+msgctxt "#31037"
+msgid "Tracklist"
+msgstr "トラックリスト"
+
 msgctxt "#31038"
 msgid "Rewind"
 msgstr "巻き戻し"
 
+msgctxt "#31039"
+msgid "Fast forward"
+msgstr "早送り"
+
+msgctxt "#31040"
+msgid "Cancel update"
+msgstr "アップデートをキャンセル"
+
+msgctxt "#31041"
+msgid "Camera manufacturer"
+msgstr "カメラのメーカー"
+
+msgctxt "#31042"
+msgid "Playlist options"
+msgstr "プレイリストオプション"
+
+msgctxt "#31043"
+msgid "Set the type and add rules to create a smart playlist. These playlists are dynamic and include all media items from your database which apply to your chosen rules."
+msgstr "タイプとルールを指定してスマートプレイリストを作成します。すべてのデータベースから指定したルールを使用し動的なプレイリストを作ることができます。"
+
+msgctxt "#31044"
+msgid "Add group"
+msgstr "グループの追加"
+
+msgctxt "#31045"
+msgid "Rename group"
+msgstr "グループの名称変更"
+
+msgctxt "#31046"
+msgid "Delete group"
+msgstr "グループの削除"
+
+msgctxt "#31047"
+msgid "Read more..."
+msgstr "もっと読む..."
+
+msgctxt "#31048"
+msgid "Available"
+msgstr "利用可能"
+
+msgctxt "#31049"
+msgid "Press [B]Up[/B] to rewind or fast-forward"
+msgstr "[B]上[/B]を押して早戻しまたは早送り"
+
+msgctxt "#31050"
+msgid "Press [B]OK[/B] to stop"
+msgstr "[B]決定[/B]を押して停止"
+
+msgctxt "#31051"
+msgid "Toggle language"
+msgstr "言語を切替"
+
+msgctxt "#31052"
+msgid "filtered"
+msgstr "フィルタ済"
+
 msgctxt "#31053"
 msgid "Arial based"
 msgstr "Arial ベース"
 
+msgctxt "#31054"
+msgid "Press [B]Left[/B] to rewind, or [B]Right[/B] to fast-forward"
+msgstr "[B]左[/B]を押して早戻し、または[B]右[/B]で早送り"
+
+msgctxt "#31055"
+msgid "Subtitle download"
+msgstr "字幕ダウンロード"
+
+msgctxt "#31056"
+msgid "Go to playlist"
+msgstr "プレイリストに移動"
+
+msgctxt "#31057"
+msgid "Show login screen on startup"
+msgstr "起動時にログイン画面を表示"
+
+msgctxt "#31058"
+msgid "Automatic Login on startup"
+msgstr "スタートアップ時に自動ログイン"
+
+msgctxt "#31059"
+msgid "Updates available"
+msgstr "アップデート利用可能"
+
+msgctxt "#31060"
+msgid "minutes"
+msgstr "分"
+
+msgctxt "#31061"
+msgid "Main menu items"
+msgstr "メインメニューアイテム"
+
+msgctxt "#31062"
+msgid "Shortcuts to the \"Files\" sections of each media type. Go there to add additional sources for your databases."
+msgstr "各メディアタイプの”ファイル”へのショートカットです。データベースへソースを追加するために移動します。"
+
+msgctxt "#31063"
+msgid "Sections"
+msgstr "セクション"
+
+msgctxt "#31064"
+msgid "unwatched"
+msgstr "未視聴"
+
+msgctxt "#31065"
+msgid "Video playlist"
+msgstr "ビデオプレイリスト"
+
+msgctxt "#31066"
+msgid "Music playlist"
+msgstr "ミュージックプレイリスト"
+
+msgctxt "#31067"
+msgid "Event log"
+msgstr "イベントログ"
+
+msgctxt "#31068"
+msgid "Choose presets"
+msgstr "プリセットを選択"
+
 msgctxt "#31069"
 msgid "Last Updated"
 msgstr "最終更新時刻"
 
+msgctxt "#31070"
+msgid "Add media sources"
+msgstr "メディアソースを追加"
+
+msgctxt "#31071"
+msgid "by"
+msgstr "by"
+
 msgctxt "#31072"
 msgid "Power Options"
 msgstr "電源オプション"
 
+msgctxt "#31073"
+msgid "Titles"
+msgstr "タイトル"
+
+msgctxt "#31074"
+msgid "Library root"
+msgstr "ライブラリルート"
+
+msgctxt "#31075"
+msgid "Movie sets"
+msgstr "ムービーセット"
+
+msgctxt "#31076"
+msgid "Play optical disc"
+msgstr "光学ディスクの再生"
+
+msgctxt "#31077"
+msgid "Previous location"
+msgstr "以前のロケーション"
+
+msgctxt "#31078"
+msgid "Next location"
+msgstr "次のロケーション"
+
+msgctxt "#31079"
+msgid "Cast not available"
+msgstr "キャストは利用できません"
+
+msgctxt "#31080"
+msgid "Ends at"
+msgstr "終了場所"
+
 msgctxt "#31081"
 msgid "Album info"
 msgstr "アルバム情報"
 
+msgctxt "#31082"
+msgid "Lyrics add-on"
+msgstr "歌詞アドオン"
+
+msgctxt "#31083"
+msgid "Lyrics add-on settings"
+msgstr "歌詞アドオン設定"
+
+msgctxt "#31084"
+msgid "Visualisation settings"
+msgstr "ビジュアライザー設定"
+
 msgctxt "#31085"
 msgid "Channel Group"
 msgstr "チャンネルグループ"
 
+msgctxt "#31086"
+msgid "Metadata"
+msgstr "メタデータ"
+
+msgctxt "#31087"
+msgid "Provider settings"
+msgstr "プロバイダー設定"
+
+msgctxt "#31088"
+msgid "Content scanning options"
+msgstr "コンテントスキャンオプション"
+
+msgctxt "#31089"
+msgid "Available groups"
+msgstr "利用可能なグループ"
+
+msgctxt "#31090"
+msgid "Search trailer"
+msgstr "予告編を検索"
+
+msgctxt "#31091"
+msgid "Download subtitles"
+msgstr "字幕をダウンロード"
+
+msgctxt "#31092"
+msgid "Video menu"
+msgstr "ビデオメニュー"
+
+msgctxt "#31093"
+msgid "Show weather info in top bar"
+msgstr "トップバーに天気予報を表示"
+
+msgctxt "#31094"
+msgid "Show media flags for movies / episodes / music videos"
+msgstr "映画/エピソード/ミュージックのメディアフラグを表示"
+
+msgctxt "#31095"
+msgid "Use slide animations"
+msgstr "スライドアニメーションを使用"
+
 msgctxt "#31096"
 msgid "Local subtitle available"
 msgstr "ローカルの字幕を利用できます"
 
+msgctxt "#31097"
+msgid "Channel options"
+msgstr "チャンネルオプション"
+
+msgctxt "#31098"
+msgid "Select your Kodi user profile[CR]to login and continue"
+msgstr "Kodi ユーザープロファイルを選択して[CR]ログインしてください"
+
+msgctxt "#31099"
+msgid "Icon Wall"
+msgstr "アイコンウォール"
+
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31101"
+msgid "InfoWall"
+msgstr "インフォウォール"
+
+msgctxt "#31102"
+msgid "Wall"
+msgstr "ウォール"
+
+msgctxt "#31103"
+msgid "Enter text here..."
+msgstr "テキストを入力..."
+
+msgctxt "#31104"
+msgid "Your library is currently empty. In order to populate it with your personal media, enter \"Files\" section, add a media source and configure it. After the source has been added and indexed you will be able to browse your library."
+msgstr "現在ライブラリには何もありません。手持ちのメディアを追加するにはファイルセクションから設定してください。ソースを追加後インデックス化されライブラリを利用できるようになります。"
+
+msgctxt "#31105"
+msgid "Add video sources and set the appropriate content type in order to populate your video libraries."
+msgstr "ビデオライブラリに追加するために、適切なコンテンツタイプのビデオソースを追加し設定します。"
+
+msgctxt "#31106"
+msgid "Teletext"
+msgstr "文字多重放送"
+
+msgctxt "#31107"
+msgid "WideList"
+msgstr "ワイドリスト"
+
+msgctxt "#31108"
+msgid "Use custom global background"
+msgstr "カスタムグローバル背景を使用"
+
+msgctxt "#31109"
+msgid "Choose image path"
+msgstr "画像のパスを選択"
+
+msgctxt "#31110"
+msgid "Enter files section"
+msgstr "ファイルセクションに入る"
+
+msgctxt "#31111"
+msgid "View your personal pictures or download one of the many image add-ons from the official repository."
+msgstr "個人的な写真を表示またはオフィシャルリポジトリから画像アドオンをダウンロードする。"
+
+msgctxt "#31112"
+msgid "Toggle audio stream"
+msgstr "オーディオストリーム切替"
+
+msgctxt "#31113"
+msgid "Search local library"
+msgstr "ローカルライブラリ検索"
+
+msgctxt "#31114"
+msgid "Search YouTube"
+msgstr "YouTubeを検索"
+
+msgctxt "#31115"
+msgid "Search TheMovieDB"
+msgstr "TheMovieDBを検索"
+
+msgctxt "#31116"
+msgid "Remove this main menu item"
+msgstr "メインメニューから消去"
+
+msgctxt "#31117"
+msgid "Edit nodes"
+msgstr "ノードを編集"
+
+msgctxt "#31118"
+msgid "Enter add-on browser"
+msgstr "アドオンブラウザー"
+
+msgctxt "#31119"
+msgid "You do not have any add-ons installed yet. Visit our add-on browser to browse through our collection and improve your Kodi experience."
+msgstr "アドオンはまだ何もインストールされていません。アドオンブラウザを利用してアドオンを追加しましょう。Kodiがより便利になります。"
+
+msgctxt "#31120"
+msgid "You did not set up a weather provider yet. In order to view weather information, choose a weather provider and set up your location."
+msgstr "あなたはまだ天気プロパイダーを設定していません。天気予報プロパイダーを選択し現在地を設定すれば天気予報を表示できます。"
+
+msgctxt "#31121"
+msgid "Set weather provider"
+msgstr "天気プロパイダーを設定"
+
+msgctxt "#31122"
+msgid "Unwatched TV Shows"
+msgstr "未視聴のTV番組"
+
+msgctxt "#31123"
+msgid "Same director"
+msgstr "同じ監督"
+
+msgctxt "#31124"
+msgid "Show images on map"
+msgstr "地図上の画像を表示"
+
+msgctxt "#31125"
+msgid "Press up for actor info"
+msgstr "上を押して出演者情報"
+
+msgctxt "#31126"
+msgid "Press OK to read plot"
+msgstr "決定を押してあらすじを読む"
+
+msgctxt "#31127"
+msgid "Show icons"
+msgstr "アイコンを表示"
+
+msgctxt "#31128"
+msgid "Contributors"
+msgstr "協力者"
+
+msgctxt "#31129"
+msgid "General settings applying to all areas of the skin."
+msgstr "このスキンのすべてのエリアに一般設定を適用する"
+
+msgctxt "#31130"
+msgid "Main menu-related settings: Configure the home screen to your likings."
+msgstr "メインメニュー関連設定: 好きなようにホームスクリーンを設定できます。"
+
+msgctxt "#31131"
+msgid "Choose home fanart pack"
+msgstr "ホームファンアートパックを選択"
+
+msgctxt "#31132"
+msgid "min"
+msgstr "分"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "隠す"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "残り"
diff --git a/addons/skin.estuary/language/resource.language.ko_kr/strings.po b/addons/skin.estuary/language/resource.language.ko_kr/strings.po
index d2dfbf5..af83ee8 100644
--- a/addons/skin.estuary/language/resource.language.ko_kr/strings.po
+++ b/addons/skin.estuary/language/resource.language.ko_kr/strings.po
@@ -547,3 +547,7 @@ msgstr "홈 화면 팬아트 팩을 선택하세요"
 msgctxt "#31132"
 msgid "min"
 msgstr "분"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "숨김"
diff --git a/addons/skin.estuary/language/resource.language.lt_lt/strings.po b/addons/skin.estuary/language/resource.language.lt_lt/strings.po
index 1ea14b0..01b6f96 100644
--- a/addons/skin.estuary/language/resource.language.lt_lt/strings.po
+++ b/addons/skin.estuary/language/resource.language.lt_lt/strings.po
@@ -547,3 +547,11 @@ msgstr "Pasirinkti pradinio ekrano Fanart paketÄ…"
 msgctxt "#31132"
 msgid "min"
 msgstr "min"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "SlÄ—pti"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "Liko"
diff --git a/addons/skin.estuary/language/resource.language.lv_lv/strings.po b/addons/skin.estuary/language/resource.language.lv_lv/strings.po
index 74330c0..21fcdde 100644
--- a/addons/skin.estuary/language/resource.language.lv_lv/strings.po
+++ b/addons/skin.estuary/language/resource.language.lv_lv/strings.po
@@ -67,3 +67,7 @@ msgstr "Pieejami lokālie subtitri"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Slēpt"
diff --git a/addons/skin.estuary/language/resource.language.mi/strings.po b/addons/skin.estuary/language/resource.language.mi/strings.po
index 198cf23..76ec476 100644
--- a/addons/skin.estuary/language/resource.language.mi/strings.po
+++ b/addons/skin.estuary/language/resource.language.mi/strings.po
@@ -23,3 +23,7 @@ msgstr "Info Album"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Huna"
diff --git a/addons/skin.estuary/language/resource.language.mk_mk/strings.po b/addons/skin.estuary/language/resource.language.mk_mk/strings.po
index c6124e4..1c278f3 100644
--- a/addons/skin.estuary/language/resource.language.mk_mk/strings.po
+++ b/addons/skin.estuary/language/resource.language.mk_mk/strings.po
@@ -75,3 +75,7 @@ msgstr "Локален превод е достапен"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Сокриј"
diff --git a/addons/skin.estuary/language/resource.language.mn_mn/strings.po b/addons/skin.estuary/language/resource.language.mn_mn/strings.po
index 1771120..1c7a739 100644
--- a/addons/skin.estuary/language/resource.language.mn_mn/strings.po
+++ b/addons/skin.estuary/language/resource.language.mn_mn/strings.po
@@ -27,3 +27,7 @@ msgstr "Хайх..."
 msgctxt "#31021"
 msgid "Misc options"
 msgstr "бусад тохиргоонууд"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Нуух"
diff --git a/addons/skin.estuary/language/resource.language.ms_my/strings.po b/addons/skin.estuary/language/resource.language.ms_my/strings.po
index c2cd311..1ae8198 100644
--- a/addons/skin.estuary/language/resource.language.ms_my/strings.po
+++ b/addons/skin.estuary/language/resource.language.ms_my/strings.po
@@ -547,3 +547,11 @@ msgstr "Pilih pek seni peminat rumah"
 msgctxt "#31132"
 msgid "min"
 msgstr "min"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Sembunyi"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "Berbaki"
diff --git a/addons/skin.estuary/language/resource.language.mt_mt/strings.po b/addons/skin.estuary/language/resource.language.mt_mt/strings.po
index f62afa4..25d90ef 100644
--- a/addons/skin.estuary/language/resource.language.mt_mt/strings.po
+++ b/addons/skin.estuary/language/resource.language.mt_mt/strings.po
@@ -99,3 +99,7 @@ msgstr "Għażliet tal-istazzjon"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Kbar"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Aħbi"
diff --git a/addons/skin.estuary/language/resource.language.my_mm/strings.po b/addons/skin.estuary/language/resource.language.my_mm/strings.po
index 8a7f246..13ea74e 100644
--- a/addons/skin.estuary/language/resource.language.my_mm/strings.po
+++ b/addons/skin.estuary/language/resource.language.my_mm/strings.po
@@ -39,3 +39,7 @@ msgstr "Local စာတန်းထိုး များရနိုင်ပ
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "ဖျောက်ထားမည်"
diff --git a/addons/skin.estuary/language/resource.language.nb_no/strings.po b/addons/skin.estuary/language/resource.language.nb_no/strings.po
index 102aee9..eab1ca4 100644
--- a/addons/skin.estuary/language/resource.language.nb_no/strings.po
+++ b/addons/skin.estuary/language/resource.language.nb_no/strings.po
@@ -547,3 +547,7 @@ msgstr "Velg fankunst for hjemmeskjermen"
 msgctxt "#31132"
 msgid "min"
 msgstr "min"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Skjul"
diff --git a/addons/skin.estuary/language/resource.language.nl_nl/strings.po b/addons/skin.estuary/language/resource.language.nl_nl/strings.po
index 4e1cbb5..7ae2aa6 100644
--- a/addons/skin.estuary/language/resource.language.nl_nl/strings.po
+++ b/addons/skin.estuary/language/resource.language.nl_nl/strings.po
@@ -547,3 +547,7 @@ msgstr "Kies home fanart pakket"
 msgctxt "#31132"
 msgid "min"
 msgstr "min"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Verbergen"
diff --git a/addons/skin.estuary/language/resource.language.pl_pl/strings.po b/addons/skin.estuary/language/resource.language.pl_pl/strings.po
index 325316b..4c25c1f 100644
--- a/addons/skin.estuary/language/resource.language.pl_pl/strings.po
+++ b/addons/skin.estuary/language/resource.language.pl_pl/strings.po
@@ -547,3 +547,11 @@ msgstr "Wybierz pakiet fototapet dla ekranu startowego"
 msgctxt "#31132"
 msgid "min"
 msgstr "min"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Ukrywaj"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "Pozostało"
diff --git a/addons/skin.estuary/language/resource.language.pt_br/strings.po b/addons/skin.estuary/language/resource.language.pt_br/strings.po
index f7957bf..b75966e 100644
--- a/addons/skin.estuary/language/resource.language.pt_br/strings.po
+++ b/addons/skin.estuary/language/resource.language.pt_br/strings.po
@@ -547,3 +547,11 @@ msgstr "Escolha pacote fanarts para home"
 msgctxt "#31132"
 msgid "min"
 msgstr "min"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Ocultar"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "Remanescente"
diff --git a/addons/skin.estuary/language/resource.language.pt_pt/strings.po b/addons/skin.estuary/language/resource.language.pt_pt/strings.po
index 2678e3c..7d7d675 100644
--- a/addons/skin.estuary/language/resource.language.pt_pt/strings.po
+++ b/addons/skin.estuary/language/resource.language.pt_pt/strings.po
@@ -359,3 +359,7 @@ msgstr "Shift"
 msgctxt "#31106"
 msgid "Teletext"
 msgstr "Teletexto"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Ocultar"
diff --git a/addons/skin.estuary/language/resource.language.ro_ro/strings.po b/addons/skin.estuary/language/resource.language.ro_ro/strings.po
index 11cc9f4..a5bc56f 100644
--- a/addons/skin.estuary/language/resource.language.ro_ro/strings.po
+++ b/addons/skin.estuary/language/resource.language.ro_ro/strings.po
@@ -24,6 +24,10 @@ msgctxt "#31001"
 msgid "Search..."
 msgstr "Caută..."
 
+msgctxt "#31003"
+msgid "Cinema mode"
+msgstr "Modul cinema"
+
 msgctxt "#31004"
 msgid "Change mode"
 msgstr "Schimbare mod"
@@ -32,6 +36,38 @@ msgctxt "#31005"
 msgid "Watch as 2D"
 msgstr "Afișează în 2D"
 
+msgctxt "#31006"
+msgid "Random movies"
+msgstr "Film aleator"
+
+msgctxt "#31007"
+msgid "Unwatched movies"
+msgstr "Filme nevăzute"
+
+msgctxt "#31009"
+msgid "Download icons"
+msgstr "Descarcă pictogramele"
+
+msgctxt "#31010"
+msgid "In progress movies"
+msgstr "Filme în curs de vizionare"
+
+msgctxt "#31012"
+msgid "Random albums"
+msgstr "Albume aleatoare"
+
+msgctxt "#31013"
+msgid "Random artists"
+msgstr "Artist aleator"
+
+msgctxt "#31014"
+msgid "Unplayed albums"
+msgstr "Albume neredate"
+
+msgctxt "#31015"
+msgid "Recent recordings"
+msgstr "Înregistrări recente"
+
 msgctxt "#31019"
 msgid "Forecast"
 msgstr "Prognoză"
@@ -44,10 +80,46 @@ msgctxt "#31021"
 msgid "Misc options"
 msgstr "Opțiuni diverse"
 
+msgctxt "#31022"
+msgid "Sort by"
+msgstr "Sortează după"
+
+msgctxt "#31026"
+msgid "Go to albums"
+msgstr "Mergi la albume"
+
+msgctxt "#31027"
+msgid "Go to songs"
+msgstr "Mergi la muzică"
+
 msgctxt "#31029"
 msgid "Last logged in"
 msgstr "Ultimul autentificat"
 
+msgctxt "#31030"
+msgid "Memory used"
+msgstr "Memorie folosită"
+
+msgctxt "#31032"
+msgid "Order"
+msgstr "Ordine"
+
+msgctxt "#31033"
+msgid "Your rating"
+msgstr "Nota dumneavoastră"
+
+msgctxt "#31034"
+msgid "Extended info"
+msgstr "Mai multe informații"
+
+msgctxt "#31035"
+msgid "Pages"
+msgstr "Pagini"
+
+msgctxt "#31036"
+msgid "items"
+msgstr "Elemente"
+
 msgctxt "#31038"
 msgid "Rewind"
 msgstr "Derulează înapoi"
@@ -56,6 +128,10 @@ msgctxt "#31039"
 msgid "Fast forward"
 msgstr "Derulează înainte"
 
+msgctxt "#31040"
+msgid "Cancel update"
+msgstr "Anulează actualizarea"
+
 msgctxt "#31042"
 msgid "Playlist options"
 msgstr "Opțiuni listă de redare"
@@ -72,18 +148,58 @@ msgctxt "#31046"
 msgid "Delete group"
 msgstr "Ștergere grup"
 
+msgctxt "#31047"
+msgid "Read more..."
+msgstr "Citește mai mult"
+
+msgctxt "#31048"
+msgid "Available"
+msgstr "Disponibil"
+
+msgctxt "#31052"
+msgid "filtered"
+msgstr "filtrat"
+
 msgctxt "#31053"
 msgid "Arial based"
 msgstr "Cu Arial la bază"
 
+msgctxt "#31060"
+msgid "minutes"
+msgstr "minute"
+
+msgctxt "#31063"
+msgid "Sections"
+msgstr "Secțiuni"
+
+msgctxt "#31064"
+msgid "unwatched"
+msgstr "nevuzute"
+
+msgctxt "#31067"
+msgid "Event log"
+msgstr "Jurnal de evenimente"
+
 msgctxt "#31069"
 msgid "Last Updated"
 msgstr "Ultima actualizare"
 
+msgctxt "#31071"
+msgid "by"
+msgstr "de"
+
 msgctxt "#31072"
 msgid "Power Options"
 msgstr "Opțiuni de alimentare"
 
+msgctxt "#31073"
+msgid "Titles"
+msgstr "Titluri"
+
+msgctxt "#31078"
+msgid "Next location"
+msgstr "Locația următoare"
+
 msgctxt "#31081"
 msgid "Album info"
 msgstr "Info album"
@@ -96,6 +212,10 @@ msgctxt "#31085"
 msgid "Channel Group"
 msgstr "Grup canal"
 
+msgctxt "#31086"
+msgid "Metadata"
+msgstr "Metadata"
+
 msgctxt "#31088"
 msgid "Content scanning options"
 msgstr "Opțiuni scanare conținut"
@@ -104,10 +224,22 @@ msgctxt "#31089"
 msgid "Available groups"
 msgstr "Grupuri disponibile"
 
+msgctxt "#31090"
+msgid "Search trailer"
+msgstr "Caută trailer"
+
 msgctxt "#31091"
 msgid "Download subtitles"
 msgstr "Descarcă subtitluri"
 
+msgctxt "#31092"
+msgid "Video menu"
+msgstr "Meniu video"
+
+msgctxt "#31093"
+msgid "Show weather info in top bar"
+msgstr "Arată vremea in bara de sus"
+
 msgctxt "#31096"
 msgid "Local subtitle available"
 msgstr "Este disponibil un subtitlu local"
@@ -123,3 +255,55 @@ msgstr "Selectați profilul dumneavoastră de utilizator Kodi[CR]pentru a vă au
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Schimbare"
+
+msgctxt "#31103"
+msgid "Enter text here..."
+msgstr "Introduceți text"
+
+msgctxt "#31106"
+msgid "Teletext"
+msgstr "Teletext"
+
+msgctxt "#31109"
+msgid "Choose image path"
+msgstr "Alege calea către imagine"
+
+msgctxt "#31114"
+msgid "Search YouTube"
+msgstr "Caută pe YouTube"
+
+msgctxt "#31115"
+msgid "Search TheMovieDB"
+msgstr "Caută pe TheMovieDB"
+
+msgctxt "#31123"
+msgid "Same director"
+msgstr "Același regizor"
+
+msgctxt "#31124"
+msgid "Show images on map"
+msgstr "Arată imaginile pe hartă"
+
+msgctxt "#31126"
+msgid "Press OK to read plot"
+msgstr "Apasă OK pentru a citi rezumatul"
+
+msgctxt "#31127"
+msgid "Show icons"
+msgstr "Arată pictogramele"
+
+msgctxt "#31128"
+msgid "Contributors"
+msgstr "Contribuitori"
+
+msgctxt "#31132"
+msgid "min"
+msgstr "min"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Ascunde"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "Rămas"
diff --git a/addons/skin.estuary/language/resource.language.ru_ru/strings.po b/addons/skin.estuary/language/resource.language.ru_ru/strings.po
index bb027f8..3cb2140 100644
--- a/addons/skin.estuary/language/resource.language.ru_ru/strings.po
+++ b/addons/skin.estuary/language/resource.language.ru_ru/strings.po
@@ -108,6 +108,10 @@ msgctxt "#31032"
 msgid "Order"
 msgstr "Порядок"
 
+msgctxt "#31033"
+msgid "Your rating"
+msgstr "Ваш рейтинг"
+
 msgctxt "#31034"
 msgid "Extended info"
 msgstr "Дополнительная информация"
@@ -184,6 +188,18 @@ msgctxt "#31060"
 msgid "minutes"
 msgstr "мин."
 
+msgctxt "#31061"
+msgid "Main menu items"
+msgstr "Элементы главного меню"
+
+msgctxt "#31065"
+msgid "Video playlist"
+msgstr "Плейлист видео"
+
+msgctxt "#31066"
+msgid "Music playlist"
+msgstr "Музыкальный плейлист"
+
 msgctxt "#31067"
 msgid "Event log"
 msgstr "Журнал событий"
@@ -200,6 +216,10 @@ msgctxt "#31072"
 msgid "Power Options"
 msgstr "Настройки питания"
 
+msgctxt "#31075"
+msgid "Movie sets"
+msgstr "Киноциклы"
+
 msgctxt "#31081"
 msgid "Album info"
 msgstr "Сведения об альбоме"
@@ -287,3 +307,11 @@ msgstr "Телетекст"
 msgctxt "#31107"
 msgid "WideList"
 msgstr "Широкий список"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Скрыть"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "Осталось"
diff --git a/addons/skin.estuary/language/resource.language.sk_sk/strings.po b/addons/skin.estuary/language/resource.language.sk_sk/strings.po
index 3480e1a..16e1ae2 100644
--- a/addons/skin.estuary/language/resource.language.sk_sk/strings.po
+++ b/addons/skin.estuary/language/resource.language.sk_sk/strings.po
@@ -106,7 +106,7 @@ msgstr "Ďalšie možnosti"
 
 msgctxt "#31022"
 msgid "Sort by"
-msgstr "Usporiadať podľa"
+msgstr "Zoradiť podľa"
 
 msgctxt "#31023"
 msgid "Viewtype"
@@ -547,3 +547,11 @@ msgstr "Vybrať domovský fanart balík"
 msgctxt "#31132"
 msgid "min"
 msgstr "min"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Skryť"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "Zostáva"
diff --git a/addons/skin.estuary/language/resource.language.sl_si/strings.po b/addons/skin.estuary/language/resource.language.sl_si/strings.po
index b502a2d..c274f7b 100644
--- a/addons/skin.estuary/language/resource.language.sl_si/strings.po
+++ b/addons/skin.estuary/language/resource.language.sl_si/strings.po
@@ -123,3 +123,7 @@ msgstr "Izberite svoj Kodi uporabniški profil[CR]za prijavo in nadaljevanje"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Skrij"
diff --git a/addons/skin.estuary/language/resource.language.sq_al/strings.po b/addons/skin.estuary/language/resource.language.sq_al/strings.po
index 425f662..f0dca94 100644
--- a/addons/skin.estuary/language/resource.language.sq_al/strings.po
+++ b/addons/skin.estuary/language/resource.language.sq_al/strings.po
@@ -51,3 +51,7 @@ msgstr "Subtitra lokal në dispozicion"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Fsheh"
diff --git a/addons/skin.estuary/language/resource.language.sr_rs/strings.po b/addons/skin.estuary/language/resource.language.sr_rs/strings.po
index d2527d0..c852b6b 100644
--- a/addons/skin.estuary/language/resource.language.sr_rs/strings.po
+++ b/addons/skin.estuary/language/resource.language.sr_rs/strings.po
@@ -547,3 +547,11 @@ msgstr "Изаберите пакет уметности љубитеља за 
 msgctxt "#31132"
 msgid "min"
 msgstr "мин"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Сакриј"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "Преостало"
diff --git a/addons/skin.estuary/language/resource.language.sr_rs at latin/strings.po b/addons/skin.estuary/language/resource.language.sr_rs at latin/strings.po
index 1b546f9..cf732f6 100644
--- a/addons/skin.estuary/language/resource.language.sr_rs at latin/strings.po
+++ b/addons/skin.estuary/language/resource.language.sr_rs at latin/strings.po
@@ -547,3 +547,7 @@ msgstr "Izaberite paket umetnosti ljubitelja za glavni ekran"
 msgctxt "#31132"
 msgid "min"
 msgstr "min"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Sakrij"
diff --git a/addons/skin.estuary/language/resource.language.sv_se/strings.po b/addons/skin.estuary/language/resource.language.sv_se/strings.po
index 9aea984..60f85e0 100644
--- a/addons/skin.estuary/language/resource.language.sv_se/strings.po
+++ b/addons/skin.estuary/language/resource.language.sv_se/strings.po
@@ -527,3 +527,7 @@ msgstr "Huvudmeny relaterade inställningar: Konfigurera startskärmen till ditt
 msgctxt "#31132"
 msgid "min"
 msgstr "min"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Dölj"
diff --git a/addons/skin.estuary/language/resource.language.szl/strings.po b/addons/skin.estuary/language/resource.language.szl/strings.po
index f5d57fc..4dcaa6d 100644
--- a/addons/skin.estuary/language/resource.language.szl/strings.po
+++ b/addons/skin.estuary/language/resource.language.szl/strings.po
@@ -107,3 +107,7 @@ msgstr "Ôbier swōj profil Kodi,[CR]coby sie zalogować i kōntynuować"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Skryj"
diff --git a/addons/skin.estuary/language/resource.language.tg_tj/strings.po b/addons/skin.estuary/language/resource.language.tg_tj/strings.po
index a81d95a..e65dabf 100644
--- a/addons/skin.estuary/language/resource.language.tg_tj/strings.po
+++ b/addons/skin.estuary/language/resource.language.tg_tj/strings.po
@@ -63,3 +63,7 @@ msgstr "Зерунвонҳои маҳаллӣ дастрасанд"
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Пинҳон кардан"
diff --git a/addons/skin.estuary/language/resource.language.th_th/strings.po b/addons/skin.estuary/language/resource.language.th_th/strings.po
index b7cac76..8258d77 100644
--- a/addons/skin.estuary/language/resource.language.th_th/strings.po
+++ b/addons/skin.estuary/language/resource.language.th_th/strings.po
@@ -119,3 +119,7 @@ msgstr "เลือกโปรไฟล์ผู้ใช้ Kodi ของค
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "ซ่อน"
diff --git a/addons/skin.estuary/language/resource.language.tr_tr/strings.po b/addons/skin.estuary/language/resource.language.tr_tr/strings.po
index 8d1f4c4..034c69e 100644
--- a/addons/skin.estuary/language/resource.language.tr_tr/strings.po
+++ b/addons/skin.estuary/language/resource.language.tr_tr/strings.po
@@ -547,3 +547,7 @@ msgstr "Ana ekran için fanart paketi seçin"
 msgctxt "#31132"
 msgid "min"
 msgstr "dk"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Gizle"
diff --git a/addons/skin.estuary/language/resource.language.uk_ua/strings.po b/addons/skin.estuary/language/resource.language.uk_ua/strings.po
index e1de10a..34082f1 100644
--- a/addons/skin.estuary/language/resource.language.uk_ua/strings.po
+++ b/addons/skin.estuary/language/resource.language.uk_ua/strings.po
@@ -123,3 +123,7 @@ msgstr "Виберіть профіль користувача Kodi,[CR]щоб 
 msgctxt "#31100"
 msgid "Shift"
 msgstr "Shift"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Приховати"
diff --git a/addons/skin.estuary/language/resource.language.vi_vn/strings.po b/addons/skin.estuary/language/resource.language.vi_vn/strings.po
index f490522..7a0953b 100644
--- a/addons/skin.estuary/language/resource.language.vi_vn/strings.po
+++ b/addons/skin.estuary/language/resource.language.vi_vn/strings.po
@@ -83,3 +83,7 @@ msgstr "Phụ đề sẵn có trong máy"
 msgctxt "#31097"
 msgid "Channel options"
 msgstr "Thiết lập kênh"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "Ẩn"
diff --git a/addons/skin.estuary/language/resource.language.zh_cn/strings.po b/addons/skin.estuary/language/resource.language.zh_cn/strings.po
index 61ec01e..c79db28 100644
--- a/addons/skin.estuary/language/resource.language.zh_cn/strings.po
+++ b/addons/skin.estuary/language/resource.language.zh_cn/strings.po
@@ -547,3 +547,7 @@ msgstr "选择主界面同人画包"
 msgctxt "#31132"
 msgid "min"
 msgstr "分"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "隐藏"
diff --git a/addons/skin.estuary/language/resource.language.zh_tw/strings.po b/addons/skin.estuary/language/resource.language.zh_tw/strings.po
index ca75ae0..5e0585d 100644
--- a/addons/skin.estuary/language/resource.language.zh_tw/strings.po
+++ b/addons/skin.estuary/language/resource.language.zh_tw/strings.po
@@ -24,6 +24,14 @@ msgctxt "#31001"
 msgid "Search..."
 msgstr "搜尋..."
 
+msgctxt "#31002"
+msgid "Show media fanart as background"
+msgstr "以背景圖的方式顯示劇照"
+
+msgctxt "#31003"
+msgid "Cinema mode"
+msgstr "劇院模式"
+
 msgctxt "#31004"
 msgid "Change mode"
 msgstr "更改設定"
@@ -32,6 +40,58 @@ msgctxt "#31005"
 msgid "Watch as 2D"
 msgstr "以 2D 模式觀賞"
 
+msgctxt "#31006"
+msgid "Random movies"
+msgstr "隨機選擇電影"
+
+msgctxt "#31007"
+msgid "Unwatched movies"
+msgstr "還沒看過的電影"
+
+msgctxt "#31008"
+msgid "No disclaimer"
+msgstr "無版權宣告"
+
+msgctxt "#31009"
+msgid "Download icons"
+msgstr "下載圖示"
+
+msgctxt "#31010"
+msgid "In progress movies"
+msgstr "還沒看完的電影"
+
+msgctxt "#31011"
+msgid "Most played albums"
+msgstr "最常播放的專輯"
+
+msgctxt "#31012"
+msgid "Random albums"
+msgstr "隨機選擇專輯"
+
+msgctxt "#31013"
+msgid "Random artists"
+msgstr "隨機選擇演出者"
+
+msgctxt "#31014"
+msgid "Unplayed albums"
+msgstr "還沒聽過的專輯"
+
+msgctxt "#31015"
+msgid "Recent recordings"
+msgstr "最近的錄影"
+
+msgctxt "#31016"
+msgid "Recently played channels"
+msgstr "最近播放的頻道"
+
+msgctxt "#31017"
+msgid "Rated"
+msgstr "已評分"
+
+msgctxt "#31018"
+msgid "Most played channels"
+msgstr "最常播放的頻道"
+
 msgctxt "#31019"
 msgid "Forecast"
 msgstr "預報"
@@ -44,10 +104,70 @@ msgctxt "#31021"
 msgid "Misc options"
 msgstr "其他選項"
 
+msgctxt "#31022"
+msgid "Sort by"
+msgstr "排序以"
+
+msgctxt "#31023"
+msgid "Viewtype"
+msgstr "檢視模式"
+
+msgctxt "#31024"
+msgid "Next tracks"
+msgstr "接下來的音軌"
+
+msgctxt "#31025"
+msgid "No favourites found. You can add any item from media views to this list by using the context menu."
+msgstr "沒有找到最愛項目。你可以使用快捷選單來將媒體檔檢視器中的物件加入此列表。"
+
+msgctxt "#31026"
+msgid "Go to albums"
+msgstr "移至專輯列表"
+
+msgctxt "#31027"
+msgid "Go to songs"
+msgstr "移至歌曲列表"
+
+msgctxt "#31028"
+msgid "Show fanart"
+msgstr "顯示劇照"
+
 msgctxt "#31029"
 msgid "Last logged in"
 msgstr "上次登入在"
 
+msgctxt "#31030"
+msgid "Memory used"
+msgstr "已使用記憶體"
+
+msgctxt "#31031"
+msgid "Version info"
+msgstr "版本資訊"
+
+msgctxt "#31032"
+msgid "Order"
+msgstr "排序"
+
+msgctxt "#31033"
+msgid "Your rating"
+msgstr "你的評分"
+
+msgctxt "#31034"
+msgid "Extended info"
+msgstr "延伸資訊"
+
+msgctxt "#31035"
+msgid "Pages"
+msgstr "頁"
+
+msgctxt "#31036"
+msgid "items"
+msgstr "é …ç›®"
+
+msgctxt "#31037"
+msgid "Tracklist"
+msgstr "曲目列表"
+
 msgctxt "#31038"
 msgid "Rewind"
 msgstr "倒轉"
@@ -56,10 +176,22 @@ msgctxt "#31039"
 msgid "Fast forward"
 msgstr "快轉"
 
+msgctxt "#31040"
+msgid "Cancel update"
+msgstr "取消更新"
+
+msgctxt "#31041"
+msgid "Camera manufacturer"
+msgstr "攝影機製造商"
+
 msgctxt "#31042"
 msgid "Playlist options"
 msgstr "播放清單選項"
 
+msgctxt "#31043"
+msgid "Set the type and add rules to create a smart playlist. These playlists are dynamic and include all media items from your database which apply to your chosen rules."
+msgstr "設定類型及規則來產生一個智慧型播放列表。這些播放列表是動態的,並且會包含資料庫中所有符合條件的媒體檔案。"
+
 msgctxt "#31044"
 msgid "Add group"
 msgstr "新增群組"
@@ -72,18 +204,142 @@ msgctxt "#31046"
 msgid "Delete group"
 msgstr "刪除群組"
 
+msgctxt "#31047"
+msgid "Read more..."
+msgstr "繼續閱讀..."
+
+msgctxt "#31048"
+msgid "Available"
+msgstr "可用"
+
+msgctxt "#31049"
+msgid "Press [B]Up[/B] to rewind or fast-forward"
+msgstr "按[B]上[/B]倒退或快轉"
+
+msgctxt "#31050"
+msgid "Press [B]OK[/B] to stop"
+msgstr "按[B]OK[/B]停止"
+
+msgctxt "#31051"
+msgid "Toggle language"
+msgstr "切換語系"
+
+msgctxt "#31052"
+msgid "filtered"
+msgstr "經篩選過的"
+
 msgctxt "#31053"
 msgid "Arial based"
 msgstr "基於 Arial"
 
+msgctxt "#31054"
+msgid "Press [B]Left[/B] to rewind, or [B]Right[/B] to fast-forward"
+msgstr "按[B]左[/B]倒退,或[B]右[/B]快轉"
+
+msgctxt "#31055"
+msgid "Subtitle download"
+msgstr "字幕檔下載"
+
+msgctxt "#31056"
+msgid "Go to playlist"
+msgstr "移至播放列表"
+
+msgctxt "#31057"
+msgid "Show login screen on startup"
+msgstr "啟動時顯示登入畫面"
+
+msgctxt "#31058"
+msgid "Automatic Login on startup"
+msgstr "啟動時自動登入"
+
+msgctxt "#31059"
+msgid "Updates available"
+msgstr "有可用更新"
+
+msgctxt "#31060"
+msgid "minutes"
+msgstr "分"
+
+msgctxt "#31061"
+msgid "Main menu items"
+msgstr "主選單項目"
+
+msgctxt "#31062"
+msgid "Shortcuts to the \"Files\" sections of each media type. Go there to add additional sources for your databases."
+msgstr "指向各媒體類型的\"檔案\"區的捷徑。移至該處來加入更多的影音來源至資料庫中。"
+
+msgctxt "#31063"
+msgid "Sections"
+msgstr "區"
+
+msgctxt "#31064"
+msgid "unwatched"
+msgstr "還沒看過的"
+
+msgctxt "#31065"
+msgid "Video playlist"
+msgstr "視訊播放列表"
+
+msgctxt "#31066"
+msgid "Music playlist"
+msgstr "音樂播放列表"
+
+msgctxt "#31067"
+msgid "Event log"
+msgstr "事件記錄"
+
+msgctxt "#31068"
+msgid "Choose presets"
+msgstr "選擇預設值"
+
 msgctxt "#31069"
 msgid "Last Updated"
 msgstr "最後更新"
 
+msgctxt "#31070"
+msgid "Add media sources"
+msgstr "增加媒體檔來源"
+
+msgctxt "#31071"
+msgid "by"
+msgstr "以"
+
 msgctxt "#31072"
 msgid "Power Options"
 msgstr "電源選項"
 
+msgctxt "#31073"
+msgid "Titles"
+msgstr "標題"
+
+msgctxt "#31074"
+msgid "Library root"
+msgstr "資料庫根目錄"
+
+msgctxt "#31075"
+msgid "Movie sets"
+msgstr "電影集"
+
+msgctxt "#31076"
+msgid "Play optical disc"
+msgstr "播放光碟"
+
+msgctxt "#31077"
+msgid "Previous location"
+msgstr "上衣個位置"
+
+msgctxt "#31078"
+msgid "Next location"
+msgstr "下一個位置"
+
+msgctxt "#31079"
+msgid "Cast not available"
+msgstr "無法取得預報"
+
+msgctxt "#31080"
+msgid "Ends at"
+msgstr "結束於"
+
 msgctxt "#31081"
 msgid "Album info"
 msgstr "專輯資訊"
@@ -92,6 +348,14 @@ msgctxt "#31082"
 msgid "Lyrics add-on"
 msgstr "歌詞附加元件"
 
+msgctxt "#31083"
+msgid "Lyrics add-on settings"
+msgstr "歌詞附加元件設定"
+
+msgctxt "#31084"
+msgid "Visualisation settings"
+msgstr "視覺效果設定"
+
 msgctxt "#31085"
 msgid "Channel Group"
 msgstr "頻道群組"
@@ -100,14 +364,42 @@ msgctxt "#31086"
 msgid "Metadata"
 msgstr "詮釋資料"
 
+msgctxt "#31087"
+msgid "Provider settings"
+msgstr "提供者設定"
+
 msgctxt "#31088"
 msgid "Content scanning options"
 msgstr "內容掃描選項"
 
+msgctxt "#31089"
+msgid "Available groups"
+msgstr "可用的群組"
+
+msgctxt "#31090"
+msgid "Search trailer"
+msgstr "搜尋預告片"
+
 msgctxt "#31091"
 msgid "Download subtitles"
 msgstr "下載字幕"
 
+msgctxt "#31092"
+msgid "Video menu"
+msgstr "視訊選單"
+
+msgctxt "#31093"
+msgid "Show weather info in top bar"
+msgstr "在置頂列顯示天氣資訊"
+
+msgctxt "#31094"
+msgid "Show media flags for movies / episodes / music videos"
+msgstr "顯示電影 / 劇集 / MV 的媒體屬性標記"
+
+msgctxt "#31095"
+msgid "Use slide animations"
+msgstr "使用滑動效果"
+
 msgctxt "#31096"
 msgid "Local subtitle available"
 msgstr "有本地語言的字幕可選用"
@@ -120,10 +412,146 @@ msgctxt "#31098"
 msgid "Select your Kodi user profile[CR]to login and continue"
 msgstr "選擇您的 Kodi 使用者設定檔[CR]登入並繼續"
 
+msgctxt "#31099"
+msgid "Icon Wall"
+msgstr "圖示牆"
+
 msgctxt "#31100"
 msgid "Shift"
 msgstr "轉換"
 
+msgctxt "#31101"
+msgid "InfoWall"
+msgstr "資訊牆"
+
+msgctxt "#31102"
+msgid "Wall"
+msgstr "牆"
+
+msgctxt "#31103"
+msgid "Enter text here..."
+msgstr "在此輸入文字"
+
+msgctxt "#31104"
+msgid "Your library is currently empty. In order to populate it with your personal media, enter \"Files\" section, add a media source and configure it. After the source has been added and indexed you will be able to browse your library."
+msgstr "你的資料庫現在是空的。若要將你收藏的影音檔拉進來這裡,請到\"檔案\"區,加入一個媒體來源並且做些設定,針對該來源內容完成清點及索引後,你即可瀏覽你的資料庫。"
+
+msgctxt "#31105"
+msgid "Add video sources and set the appropriate content type in order to populate your video libraries."
+msgstr "加入視訊來源並且設定合適的內容類型,以豐富你的視訊資料庫。"
+
 msgctxt "#31106"
 msgid "Teletext"
 msgstr "電傳聞訊"
+
+msgctxt "#31107"
+msgid "WideList"
+msgstr "寬版面列表"
+
+msgctxt "#31108"
+msgid "Use custom global background"
+msgstr "使用自訂的全局背景圖"
+
+msgctxt "#31109"
+msgid "Choose image path"
+msgstr "選擇圖片路徑"
+
+msgctxt "#31110"
+msgid "Enter files section"
+msgstr "進入檔案區"
+
+msgctxt "#31111"
+msgid "View your personal pictures or download one of the many image add-ons from the official repository."
+msgstr "檢視你的個人圖片,或下載官方的眾多影像附加元件"
+
+msgctxt "#31112"
+msgid "Toggle audio stream"
+msgstr "切換聲道"
+
+msgctxt "#31113"
+msgid "Search local library"
+msgstr "搜尋本地資料庫"
+
+msgctxt "#31114"
+msgid "Search YouTube"
+msgstr "搜尋YouTube"
+
+msgctxt "#31115"
+msgid "Search TheMovieDB"
+msgstr "搜尋TheMovieDB"
+
+msgctxt "#31116"
+msgid "Remove this main menu item"
+msgstr "移除這個主選單項目"
+
+msgctxt "#31117"
+msgid "Edit nodes"
+msgstr "編輯節點"
+
+msgctxt "#31118"
+msgid "Enter add-on browser"
+msgstr "進入附加元件瀏覽器"
+
+msgctxt "#31119"
+msgid "You do not have any add-ons installed yet. Visit our add-on browser to browse through our collection and improve your Kodi experience."
+msgstr "你還沒安裝任何附加元件。請到我們的附加元件瀏覽器逛逛,讓你的Kodi更好用。"
+
+msgctxt "#31120"
+msgid "You did not set up a weather provider yet. In order to view weather information, choose a weather provider and set up your location."
+msgstr "你還沒設定天氣資訊提供者。請選取一個並設定你的位置來取得天氣資訊。"
+
+msgctxt "#31121"
+msgid "Set weather provider"
+msgstr "設定天氣資訊提供者"
+
+msgctxt "#31122"
+msgid "Unwatched TV Shows"
+msgstr "還沒看過的電視劇集"
+
+msgctxt "#31123"
+msgid "Same director"
+msgstr "同一個導演的作品"
+
+msgctxt "#31124"
+msgid "Show images on map"
+msgstr "在地圖上顯示影像"
+
+msgctxt "#31125"
+msgid "Press up for actor info"
+msgstr "按上鍵查看演員資料"
+
+msgctxt "#31126"
+msgid "Press OK to read plot"
+msgstr "按OK鍵查看劇情簡介"
+
+msgctxt "#31127"
+msgid "Show icons"
+msgstr "顯示圖示"
+
+msgctxt "#31128"
+msgid "Contributors"
+msgstr "發行單位"
+
+msgctxt "#31129"
+msgid "General settings applying to all areas of the skin."
+msgstr "適用於佈景主題所有區塊的通用設定"
+
+msgctxt "#31130"
+msgid "Main menu-related settings: Configure the home screen to your likings."
+msgstr "主選單相關設定:將首頁依照您的喜好做規劃"
+
+msgctxt "#31131"
+msgid "Choose home fanart pack"
+msgstr "選擇首頁劇照合輯"
+
+msgctxt "#31132"
+msgid "min"
+msgstr "分"
+
+msgctxt "#31133"
+msgid "Hide"
+msgstr "隱藏"
+
+msgctxt "#31134"
+msgid "Remaining"
+msgstr "後結束"
diff --git a/addons/skin.estuary/media/DefaultAddon.png b/addons/skin.estuary/media/DefaultAddon.png
index 99cf8e3..d24466a 100644
Binary files a/addons/skin.estuary/media/DefaultAddon.png and b/addons/skin.estuary/media/DefaultAddon.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonAlbumInfo.png b/addons/skin.estuary/media/DefaultAddonAlbumInfo.png
index 5336830..6addf73 100644
Binary files a/addons/skin.estuary/media/DefaultAddonAlbumInfo.png and b/addons/skin.estuary/media/DefaultAddonAlbumInfo.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonArtistInfo.png b/addons/skin.estuary/media/DefaultAddonArtistInfo.png
index 1477935..dc38e55 100644
Binary files a/addons/skin.estuary/media/DefaultAddonArtistInfo.png and b/addons/skin.estuary/media/DefaultAddonArtistInfo.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonAudioDSP.png b/addons/skin.estuary/media/DefaultAddonAudioDSP.png
index cdb94b5..7fc2dc4 100644
Binary files a/addons/skin.estuary/media/DefaultAddonAudioDSP.png and b/addons/skin.estuary/media/DefaultAddonAudioDSP.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonAudioDecoder.png b/addons/skin.estuary/media/DefaultAddonAudioDecoder.png
index 332bb8e..43ee4d9 100644
Binary files a/addons/skin.estuary/media/DefaultAddonAudioDecoder.png and b/addons/skin.estuary/media/DefaultAddonAudioDecoder.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonAudioEncoder.png b/addons/skin.estuary/media/DefaultAddonAudioEncoder.png
index 974a213..6d50ea0 100644
Binary files a/addons/skin.estuary/media/DefaultAddonAudioEncoder.png and b/addons/skin.estuary/media/DefaultAddonAudioEncoder.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonContextItem.png b/addons/skin.estuary/media/DefaultAddonContextItem.png
index 4044e91..d19c68b 100644
Binary files a/addons/skin.estuary/media/DefaultAddonContextItem.png and b/addons/skin.estuary/media/DefaultAddonContextItem.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonGame.png b/addons/skin.estuary/media/DefaultAddonGame.png
index 6be3182..2a8fbef 100644
Binary files a/addons/skin.estuary/media/DefaultAddonGame.png and b/addons/skin.estuary/media/DefaultAddonGame.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonHelper.png b/addons/skin.estuary/media/DefaultAddonHelper.png
index 27a2728..1338ab2 100644
Binary files a/addons/skin.estuary/media/DefaultAddonHelper.png and b/addons/skin.estuary/media/DefaultAddonHelper.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonImages.png b/addons/skin.estuary/media/DefaultAddonImages.png
index e0f5e23..80ee250 100644
Binary files a/addons/skin.estuary/media/DefaultAddonImages.png and b/addons/skin.estuary/media/DefaultAddonImages.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonInfoLibrary.png b/addons/skin.estuary/media/DefaultAddonInfoLibrary.png
index f6c3f8b..8c7302e 100644
Binary files a/addons/skin.estuary/media/DefaultAddonInfoLibrary.png and b/addons/skin.estuary/media/DefaultAddonInfoLibrary.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonInfoProvider.png b/addons/skin.estuary/media/DefaultAddonInfoProvider.png
index f572047..d31917a 100644
Binary files a/addons/skin.estuary/media/DefaultAddonInfoProvider.png and b/addons/skin.estuary/media/DefaultAddonInfoProvider.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonInputstream.png b/addons/skin.estuary/media/DefaultAddonInputstream.png
index df8dece..52fab4c 100644
Binary files a/addons/skin.estuary/media/DefaultAddonInputstream.png and b/addons/skin.estuary/media/DefaultAddonInputstream.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonLanguage.png b/addons/skin.estuary/media/DefaultAddonLanguage.png
index be8fb46..31ec187 100644
Binary files a/addons/skin.estuary/media/DefaultAddonLanguage.png and b/addons/skin.estuary/media/DefaultAddonLanguage.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonLibrary.png b/addons/skin.estuary/media/DefaultAddonLibrary.png
index c1a6284..97ac97c 100644
Binary files a/addons/skin.estuary/media/DefaultAddonLibrary.png and b/addons/skin.estuary/media/DefaultAddonLibrary.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonLookAndFeel.png b/addons/skin.estuary/media/DefaultAddonLookAndFeel.png
index b584d19..c08bc39 100644
Binary files a/addons/skin.estuary/media/DefaultAddonLookAndFeel.png and b/addons/skin.estuary/media/DefaultAddonLookAndFeel.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonLyrics.png b/addons/skin.estuary/media/DefaultAddonLyrics.png
index 467fb24..3035e4a 100644
Binary files a/addons/skin.estuary/media/DefaultAddonLyrics.png and b/addons/skin.estuary/media/DefaultAddonLyrics.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonMovieInfo.png b/addons/skin.estuary/media/DefaultAddonMovieInfo.png
index 149d8bf..4407a56 100644
Binary files a/addons/skin.estuary/media/DefaultAddonMovieInfo.png and b/addons/skin.estuary/media/DefaultAddonMovieInfo.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonMusicVideoInfo.png b/addons/skin.estuary/media/DefaultAddonMusicVideoInfo.png
index cf5e01e..6f339fb 100644
Binary files a/addons/skin.estuary/media/DefaultAddonMusicVideoInfo.png and b/addons/skin.estuary/media/DefaultAddonMusicVideoInfo.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonNone.png b/addons/skin.estuary/media/DefaultAddonNone.png
index f9d5528..b4baedf 100644
Binary files a/addons/skin.estuary/media/DefaultAddonNone.png and b/addons/skin.estuary/media/DefaultAddonNone.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonPVRClient.png b/addons/skin.estuary/media/DefaultAddonPVRClient.png
index dd3cb0c..bf928ed 100644
Binary files a/addons/skin.estuary/media/DefaultAddonPVRClient.png and b/addons/skin.estuary/media/DefaultAddonPVRClient.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonPeripheral.png b/addons/skin.estuary/media/DefaultAddonPeripheral.png
index d14e7b9..c705060 100644
Binary files a/addons/skin.estuary/media/DefaultAddonPeripheral.png and b/addons/skin.estuary/media/DefaultAddonPeripheral.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonProgram.png b/addons/skin.estuary/media/DefaultAddonProgram.png
index 2d8d331..fe4091d 100644
Binary files a/addons/skin.estuary/media/DefaultAddonProgram.png and b/addons/skin.estuary/media/DefaultAddonProgram.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonRepository.png b/addons/skin.estuary/media/DefaultAddonRepository.png
index 5694aa5..7bfd473 100644
Binary files a/addons/skin.estuary/media/DefaultAddonRepository.png and b/addons/skin.estuary/media/DefaultAddonRepository.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonScreensaver.png b/addons/skin.estuary/media/DefaultAddonScreensaver.png
index c67f4f3..a2d35e8 100644
Binary files a/addons/skin.estuary/media/DefaultAddonScreensaver.png and b/addons/skin.estuary/media/DefaultAddonScreensaver.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonService.png b/addons/skin.estuary/media/DefaultAddonService.png
index e4c860e..2d1911e 100644
Binary files a/addons/skin.estuary/media/DefaultAddonService.png and b/addons/skin.estuary/media/DefaultAddonService.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonSkin.png b/addons/skin.estuary/media/DefaultAddonSkin.png
index 78e2b5b..4b72548 100644
Binary files a/addons/skin.estuary/media/DefaultAddonSkin.png and b/addons/skin.estuary/media/DefaultAddonSkin.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonSubtitles.png b/addons/skin.estuary/media/DefaultAddonSubtitles.png
index 7bfff21..fa122cc 100644
Binary files a/addons/skin.estuary/media/DefaultAddonSubtitles.png and b/addons/skin.estuary/media/DefaultAddonSubtitles.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonUISounds.png b/addons/skin.estuary/media/DefaultAddonUISounds.png
index a554cbf..1a0bd7c 100644
Binary files a/addons/skin.estuary/media/DefaultAddonUISounds.png and b/addons/skin.estuary/media/DefaultAddonUISounds.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonVideo.png b/addons/skin.estuary/media/DefaultAddonVideo.png
index 8b016a2..54baa3e 100644
Binary files a/addons/skin.estuary/media/DefaultAddonVideo.png and b/addons/skin.estuary/media/DefaultAddonVideo.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonVisualization.png b/addons/skin.estuary/media/DefaultAddonVisualization.png
index 069c779..6e9e8d1 100644
Binary files a/addons/skin.estuary/media/DefaultAddonVisualization.png and b/addons/skin.estuary/media/DefaultAddonVisualization.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonWeather.png b/addons/skin.estuary/media/DefaultAddonWeather.png
index 0d5f67f..8774f80 100644
Binary files a/addons/skin.estuary/media/DefaultAddonWeather.png and b/addons/skin.estuary/media/DefaultAddonWeather.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonWebSkin.png b/addons/skin.estuary/media/DefaultAddonWebSkin.png
index 8af3d81..8cfafec 100644
Binary files a/addons/skin.estuary/media/DefaultAddonWebSkin.png and b/addons/skin.estuary/media/DefaultAddonWebSkin.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonsInstalled.png b/addons/skin.estuary/media/DefaultAddonsInstalled.png
index 56f4e25..8b016a2 100644
Binary files a/addons/skin.estuary/media/DefaultAddonsInstalled.png and b/addons/skin.estuary/media/DefaultAddonsInstalled.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonsRepo.png b/addons/skin.estuary/media/DefaultAddonsRepo.png
index 73fa0e4..7bfd473 100644
Binary files a/addons/skin.estuary/media/DefaultAddonsRepo.png and b/addons/skin.estuary/media/DefaultAddonsRepo.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonsSearch.png b/addons/skin.estuary/media/DefaultAddonsSearch.png
index 0fd6213..7cecf07 100644
Binary files a/addons/skin.estuary/media/DefaultAddonsSearch.png and b/addons/skin.estuary/media/DefaultAddonsSearch.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonsUpdates.png b/addons/skin.estuary/media/DefaultAddonsUpdates.png
index 0e1a2c6..fa122cc 100644
Binary files a/addons/skin.estuary/media/DefaultAddonsUpdates.png and b/addons/skin.estuary/media/DefaultAddonsUpdates.png differ
diff --git a/addons/skin.estuary/media/DefaultAddonsZip.png b/addons/skin.estuary/media/DefaultAddonsZip.png
index fcb4dba..d4c9345 100644
Binary files a/addons/skin.estuary/media/DefaultAddonsZip.png and b/addons/skin.estuary/media/DefaultAddonsZip.png differ
diff --git a/addons/skin.estuary/media/DefaultAlbumCover.png b/addons/skin.estuary/media/DefaultAlbumCover.png
index 2ba4e44..cf90740 100644
Binary files a/addons/skin.estuary/media/DefaultAlbumCover.png and b/addons/skin.estuary/media/DefaultAlbumCover.png differ
diff --git a/addons/skin.estuary/media/DefaultBackFanart.png b/addons/skin.estuary/media/DefaultBackFanart.png
index 35efe70..eda503b 100644
Binary files a/addons/skin.estuary/media/DefaultBackFanart.png and b/addons/skin.estuary/media/DefaultBackFanart.png differ
diff --git a/addons/skin.estuary/media/DefaultCDDA.png b/addons/skin.estuary/media/DefaultCDDA.png
index 84b57b1..ab0fb09 100644
Binary files a/addons/skin.estuary/media/DefaultCDDA.png and b/addons/skin.estuary/media/DefaultCDDA.png differ
diff --git a/addons/skin.estuary/media/DefaultDVDEmpty.png b/addons/skin.estuary/media/DefaultDVDEmpty.png
index db46c6f..1357a82 100644
Binary files a/addons/skin.estuary/media/DefaultDVDEmpty.png and b/addons/skin.estuary/media/DefaultDVDEmpty.png differ
diff --git a/addons/skin.estuary/media/DefaultDVDFull.png b/addons/skin.estuary/media/DefaultDVDFull.png
index acbcb72..57da69f 100644
Binary files a/addons/skin.estuary/media/DefaultDVDFull.png and b/addons/skin.estuary/media/DefaultDVDFull.png differ
diff --git a/addons/skin.estuary/media/DefaultDVDRom.png b/addons/skin.estuary/media/DefaultDVDRom.png
index 7df03f0..57da69f 100644
Binary files a/addons/skin.estuary/media/DefaultDVDRom.png and b/addons/skin.estuary/media/DefaultDVDRom.png differ
diff --git a/addons/skin.estuary/media/DefaultGameAddons.png b/addons/skin.estuary/media/DefaultGameAddons.png
index c08c56e..2a8fbef 100644
Binary files a/addons/skin.estuary/media/DefaultGameAddons.png and b/addons/skin.estuary/media/DefaultGameAddons.png differ
diff --git a/addons/skin.estuary/media/DefaultGames.png b/addons/skin.estuary/media/DefaultGames.png
index 728372c..2a8fbef 100644
Binary files a/addons/skin.estuary/media/DefaultGames.png and b/addons/skin.estuary/media/DefaultGames.png differ
diff --git a/addons/skin.estuary/media/DefaultMusicSearch.png b/addons/skin.estuary/media/DefaultMusicSearch.png
index 6e81a20..1dce1c4 100644
Binary files a/addons/skin.estuary/media/DefaultMusicSearch.png and b/addons/skin.estuary/media/DefaultMusicSearch.png differ
diff --git a/addons/skin.estuary/media/DefaultMusicTop100Albums.png b/addons/skin.estuary/media/DefaultMusicTop100Albums.png
index 2ba4e44..cf90740 100644
Binary files a/addons/skin.estuary/media/DefaultMusicTop100Albums.png and b/addons/skin.estuary/media/DefaultMusicTop100Albums.png differ
diff --git a/addons/skin.estuary/media/DefaultMusicTop100Songs.png b/addons/skin.estuary/media/DefaultMusicTop100Songs.png
index c227801..7455047 100644
Binary files a/addons/skin.estuary/media/DefaultMusicTop100Songs.png and b/addons/skin.estuary/media/DefaultMusicTop100Songs.png differ
diff --git a/addons/skin.estuary/media/DefaultMusicVideoTitle.png b/addons/skin.estuary/media/DefaultMusicVideoTitle.png
index 726e8a2..8b7b547 100644
Binary files a/addons/skin.estuary/media/DefaultMusicVideoTitle.png and b/addons/skin.estuary/media/DefaultMusicVideoTitle.png differ
diff --git a/addons/skin.estuary/media/DefaultMusicVideos.png b/addons/skin.estuary/media/DefaultMusicVideos.png
index 674d8ad..781cbcc 100644
Binary files a/addons/skin.estuary/media/DefaultMusicVideos.png and b/addons/skin.estuary/media/DefaultMusicVideos.png differ
diff --git a/addons/skin.estuary/media/DefaultNoPreview.png b/addons/skin.estuary/media/DefaultNoPreview.png
new file mode 100644
index 0000000..99ccbb5
Binary files /dev/null and b/addons/skin.estuary/media/DefaultNoPreview.png differ
diff --git a/addons/skin.estuary/media/DefaultPicture.png b/addons/skin.estuary/media/DefaultPicture.png
index 125b104..80ee250 100644
Binary files a/addons/skin.estuary/media/DefaultPicture.png and b/addons/skin.estuary/media/DefaultPicture.png differ
diff --git a/addons/skin.estuary/media/DefaultProgram.png b/addons/skin.estuary/media/DefaultProgram.png
index 2d8d331..fe4091d 100644
Binary files a/addons/skin.estuary/media/DefaultProgram.png and b/addons/skin.estuary/media/DefaultProgram.png differ
diff --git a/addons/skin.estuary/media/DefaultRecentlyAddedMusicVideos.png b/addons/skin.estuary/media/DefaultRecentlyAddedMusicVideos.png
index 2205850..862d409 100644
Binary files a/addons/skin.estuary/media/DefaultRecentlyAddedMusicVideos.png and b/addons/skin.estuary/media/DefaultRecentlyAddedMusicVideos.png differ
diff --git a/addons/skin.estuary/media/DefaultRemovableDisk.png b/addons/skin.estuary/media/DefaultRemovableDisk.png
index 461ebd3..42ae5f1 100644
Binary files a/addons/skin.estuary/media/DefaultRemovableDisk.png and b/addons/skin.estuary/media/DefaultRemovableDisk.png differ
diff --git a/addons/skin.estuary/media/DefaultScript.png b/addons/skin.estuary/media/DefaultScript.png
index 337eb11..b1cb0f6 100644
Binary files a/addons/skin.estuary/media/DefaultScript.png and b/addons/skin.estuary/media/DefaultScript.png differ
diff --git a/addons/skin.estuary/media/DefaultVCD.png b/addons/skin.estuary/media/DefaultVCD.png
index 8808987..d2b881f 100644
Binary files a/addons/skin.estuary/media/DefaultVCD.png and b/addons/skin.estuary/media/DefaultVCD.png differ
diff --git a/addons/skin.estuary/media/DefaultVideoDeleted.png b/addons/skin.estuary/media/DefaultVideoDeleted.png
index b020b2a..7bf6ad8 100644
Binary files a/addons/skin.estuary/media/DefaultVideoDeleted.png and b/addons/skin.estuary/media/DefaultVideoDeleted.png differ
diff --git a/addons/skin.estuary/media/osd/fullscreen/buttons/random_on.png b/addons/skin.estuary/media/osd/fullscreen/buttons/random_on.png
old mode 100755
new mode 100644
diff --git a/addons/skin.estuary/media/osd/fullscreen/buttons/teletext-alternative.png b/addons/skin.estuary/media/osd/fullscreen/buttons/teletext-alternative.png
old mode 100755
new mode 100644
diff --git a/addons/skin.estuary/fanart.jpg b/addons/skin.estuary/resources/fanart.jpg
similarity index 100%
rename from addons/skin.estuary/fanart.jpg
rename to addons/skin.estuary/resources/fanart.jpg
diff --git a/addons/skin.estuary/icon.png b/addons/skin.estuary/resources/icon.png
similarity index 100%
rename from addons/skin.estuary/icon.png
rename to addons/skin.estuary/resources/icon.png
diff --git a/addons/skin.estuary/resources/screenshot-01.jpg b/addons/skin.estuary/resources/screenshot-01.jpg
new file mode 100644
index 0000000..6c8db59
Binary files /dev/null and b/addons/skin.estuary/resources/screenshot-01.jpg differ
diff --git a/addons/skin.estuary/resources/screenshot-02.jpg b/addons/skin.estuary/resources/screenshot-02.jpg
new file mode 100644
index 0000000..a8154d7
Binary files /dev/null and b/addons/skin.estuary/resources/screenshot-02.jpg differ
diff --git a/addons/skin.estuary/resources/screenshot-03.jpg b/addons/skin.estuary/resources/screenshot-03.jpg
new file mode 100644
index 0000000..ccd01ef
Binary files /dev/null and b/addons/skin.estuary/resources/screenshot-03.jpg differ
diff --git a/addons/skin.estuary/resources/screenshot-04.jpg b/addons/skin.estuary/resources/screenshot-04.jpg
new file mode 100644
index 0000000..429bbe0
Binary files /dev/null and b/addons/skin.estuary/resources/screenshot-04.jpg differ
diff --git a/addons/skin.estuary/resources/screenshot-05.jpg b/addons/skin.estuary/resources/screenshot-05.jpg
new file mode 100644
index 0000000..28e5625
Binary files /dev/null and b/addons/skin.estuary/resources/screenshot-05.jpg differ
diff --git a/addons/skin.estuary/resources/screenshot-06.jpg b/addons/skin.estuary/resources/screenshot-06.jpg
new file mode 100644
index 0000000..e110769
Binary files /dev/null and b/addons/skin.estuary/resources/screenshot-06.jpg differ
diff --git a/addons/skin.estuary/resources/screenshot-07.jpg b/addons/skin.estuary/resources/screenshot-07.jpg
new file mode 100644
index 0000000..5f80c8f
Binary files /dev/null and b/addons/skin.estuary/resources/screenshot-07.jpg differ
diff --git a/addons/skin.estuary/resources/screenshot-08.jpg b/addons/skin.estuary/resources/screenshot-08.jpg
new file mode 100644
index 0000000..3ca9acb
Binary files /dev/null and b/addons/skin.estuary/resources/screenshot-08.jpg differ
diff --git a/addons/skin.estuary/themes/curial/buttons/button-nofo.png b/addons/skin.estuary/themes/curial/buttons/button-nofo.png
index 12d56a6..8c57a75 100644
Binary files a/addons/skin.estuary/themes/curial/buttons/button-nofo.png and b/addons/skin.estuary/themes/curial/buttons/button-nofo.png differ
diff --git a/addons/skin.estuary/themes/curial/dialogs/dialog-bg.png b/addons/skin.estuary/themes/curial/dialogs/dialog-bg.png
index 6e47b08..9da682f 100644
Binary files a/addons/skin.estuary/themes/curial/dialogs/dialog-bg.png and b/addons/skin.estuary/themes/curial/dialogs/dialog-bg.png differ
diff --git a/addons/webinterface.default/addon.xml b/addons/webinterface.default/addon.xml
index 19e398e..8d840d9 100644
--- a/addons/webinterface.default/addon.xml
+++ b/addons/webinterface.default/addon.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <addon
   id="webinterface.default"
-  version="2.2.31"
+  version="2.2.32"
   name="Default webinterface"
   provider-name="Team Kodi">
   <requires>
@@ -34,7 +34,7 @@
     <summary lang="fa_IR">رابط وب تیم Kodi. (رابط وب استاندارد Kodi)</summary>
     <summary lang="fi_FI">Team Kodi:n WWW-käyttöliittymä. (Kodi:n oletus WWW-käyttöliittymä)</summary>
     <summary lang="fr_CA">Interface Web de l'équipe Kodi. (Interface Web par défaut de Kodi)</summary>
-    <summary lang="fr_FR">Interface internet de l'Équipe-Kodi. (Interface internet par défaut de Kodi)</summary>
+    <summary lang="fr_FR">Interface Web de l'Équipe Kodi (interface d'origine de Kodi)</summary>
     <summary lang="gl_ES">Interface web da equipa de Kodi. (Interface web predefinida de Kodi)</summary>
     <summary lang="he_IL">ממשק הדפדפן הרשמי של Kodi. (ברירת המחדל)</summary>
     <summary lang="hr_HR">Tim Kodi Web sučelje. (Kodijevo uobičajeno web sučelje)</summary>
diff --git a/addons/webinterface.default/js/MediaLibrary.js b/addons/webinterface.default/js/MediaLibrary.js
index a5bbe72..10f9dc3 100755
--- a/addons/webinterface.default/js/MediaLibrary.js
+++ b/addons/webinterface.default/js/MediaLibrary.js
@@ -70,6 +70,7 @@ MediaLibrary.prototype = {
   },
   remoteControlOpen: function (event) {
     this.resetPage();
+    this.textBuffer = '';
     $('#remoteControl').addClass('selected');
     $('.contentContainer').hide();
     var libraryContainer = $('#remoteContainer');
@@ -149,15 +150,19 @@ MediaLibrary.prototype = {
     if (!key) {
       event.data.key = 'text';
 
-      // Letters
-      if (which >= 65 && which <= 90) {
-        var offset = event.shiftKey ? 0 : 32;
-        event.data.text = String.fromCharCode(which + offset);
-      }
-
-      // Digits
-      if (which >= 96 && which <= 105) {
-        event.data.text = (which-96)+"";
+      if (event.key && event.key.length === 1){
+        event.data.text = event.key;
+      } else {
+        // Letters
+        if (which >= 65 && which <= 90) {
+          var offset = event.shiftKey ? 0 : 32;
+          event.data.text = String.fromCharCode(which + offset);
+        }
+  
+        // Digits
+        if (which >= 96 && which <= 105) {
+          event.data.text = (which-96)+"";
+        }
       }
     }
 
@@ -179,10 +184,26 @@ MediaLibrary.prototype = {
     if (params) { callObj.params = params; }
     return xbmc.rpc.request(callObj);
   },
+  typeRemoteText: function (event){
+    if (event.data.key === 'text' || ((event.data.key === 'playpause' || event.data.key === 'back') && this.textBuffer.length)) {
+      if (event.data.key === 'back') {
+        this.textBuffer = this.textBuffer.substring(0, this.textBuffer.length - 1);
+      } else if (event.data.key === 'playpause') {
+        this.textBuffer += ' ';
+      } else if (event.data.text && event.data.text.length) {
+        this.textBuffer += event.data.text;
+      }
+      console.log(this.textBuffer);
+      return this.rpcCall('Input.SendText', {'text': this.textBuffer, 'done': false});      
+    } else {
+      this.textBuffer = '';
+    }
+  },
   pressRemoteKey: function (event) {
     var player = -1,
       keyPressed = event.data.key;
     $('#spinner').show();
+    if (this.typeRemoteText(event)) { return true; }
 
     switch(keyPressed) {
       case 'up': return this.rpcCall('Input.Up');
@@ -204,8 +225,6 @@ MediaLibrary.prototype = {
         return this.rpcCall('Application.SetVolume', {'volume': 'increment'});
       case 'volumedown':
         return this.rpcCall('Application.SetVolume', {'volume': 'decrement'});
-      case 'text':
-        return this.rpcCall('Input.SendText', {'text': event.data.text});
     }
 
     // TODO: Get active player
diff --git a/appveyor.yml b/appveyor.yml
index 82d69fd..67979f5 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -41,7 +41,7 @@ build_script:
         # Download precompiled mingw32 libraries
         # To run make-mingwlibs.bat on AppVeyor takes too long, 
         # we must use precompiled libs to speed up build
-        bash -c "curl http://repo.msys2.org/mingw/i686/mingw-w64-i686-ffmpeg-3.0-1-any.pkg.tar.xz | tar xJv"
+        bash -c "curl http://repo.msys2.org/mingw/i686/mingw-w64-i686-ffmpeg-3.1.1-1-any.pkg.tar.xz | tar xJv"
         bash -c "curl http://repo.msys2.org/mingw/i686/mingw-w64-i686-libdvdcss-1.4.0-1-any.pkg.tar.xz | tar xJv"
         bash -c "curl http://repo.msys2.org/mingw/i686/mingw-w64-i686-libdvdnav-5.0.3-1-any.pkg.tar.xz | tar xJv"
         bash -c "curl http://repo.msys2.org/mingw/i686/mingw-w64-i686-libdvdread-5.0.3-1-any.pkg.tar.xz | tar xJv"
diff --git a/configure.ac b/configure.ac
index 45145b3..4943d7f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.59)
-AC_INIT([kodi], [16.9.702], [http://trac.kodi.tv])
+AC_INIT([kodi], [16.9.703], [http://trac.kodi.tv])
 AC_CONFIG_HEADERS([xbmc/config.h])
 AH_TOP([#pragma once])
 m4_include([m4/ax_prog_cc_for_build.m4])
@@ -208,6 +208,9 @@ libusb_disabled="== libusb disabled. Plug and play USB device support will not b
 libusb_disabled_udev_found="== libusb disabled. =="
 libcec_enabled="== libcec enabled. =="
 libcec_disabled="== libcec disabled. CEC adapter support will not be available. =="
+lcms2_enabled="== lcms2 enabled. =="
+lcms2_not_found="== Could not find lcms2. ICC profile support will not be available. =="
+lcms2_disabled="== lcms2 disabled. ICC profile support will not be available. =="
 libbluetooth_not_found="== Could not find libbluetooth. Bluetooth support will not be available =="
 libbluetooth_enabled="== libbluetooth enabled. =="
 libbluetooth_disabled="== libbluetooth disabled. Bluetooth support will not be available. =="
@@ -442,6 +445,12 @@ AC_ARG_ENABLE([libcec],
   [use_libcec=$enableval],
   [use_libcec=auto])
 
+AC_ARG_ENABLE([lcms2],
+  [AS_HELP_STRING([--enable-lcms2],
+  [enable lcms2 support (default is auto)])],
+  [use_lcms2=$enableval],
+  [use_lcms2=auto])
+
 AC_ARG_ENABLE([libbluetooth],
   [AS_HELP_STRING([--enable-libbluetooth],
   [enable libbluetooth support (default is auto)])],
@@ -1444,6 +1453,21 @@ else
   AC_MSG_NOTICE($libcec_disabled)
 fi
 
+# lcms2
+if test "$use_lcms2" = "auto"; then
+  PKG_CHECK_MODULES([LCMS2],[lcms2],,[use_lcms2="no";AC_MSG_RESULT($lcms2_not_found)])
+elif test "$use_lcms2" = "yes" ; then
+  PKG_CHECK_MODULES([LCMS2],[lcms2],,[use_lcms2="no";AC_MSG_ERROR($lcms2_not_found)])
+else
+  AC_MSG_NOTICE($lcms2_disabled)
+fi
+
+if test "x$use_lcms2" != "xno"; then
+  USE_LCMS2=1;INCLUDES="$INCLUDES $LCMS2_CFLAGS";LIBS="$LIBS $LCMS2_LIBS"
+  AC_DEFINE([HAVE_LCMS2],[1],["Define to 1 if lcms2 is installed"])
+  AC_MSG_NOTICE($lcms2_enabled)
+fi
+
 # libbluetooth
 USE_LIBBLUETOOTH=0
 if test "$use_libbluetooth" = "auto"; then
@@ -2074,6 +2098,12 @@ else
   final_message="$final_message\n  libcec support:\tNo"
 fi
 
+if test "x$use_lcms2" != "xno"; then
+  final_message="$final_message\n  lcms2 support:\tYes"
+else
+  final_message="$final_message\n  lcms2 support:\tNo"
+fi
+
 if test "x$use_libbluetooth" != "xno"; then
   final_message="$final_message\n  libbluetooth support:\tYes"
 else
@@ -2186,7 +2216,6 @@ OUTPUT_FILES="Makefile \
     xbmc/platform/darwin/osx/Info.plist \
     xbmc/platform/darwin/ios/Info.plist \
     project/cmake/KodiConfig.cmake \
-    project/cmake/XBMCConfig.cmake \
     tools/android/packaging/xbmc/AndroidManifest.xml \
     tools/android/packaging/Makefile \
     tools/android/packaging/xbmc/src/org/xbmc/kodi/Splash.java \
diff --git a/docs/manpages/kodi-j2meremote.1 b/docs/manpages/kodi-j2meremote.1
deleted file mode 100644
index 2e11d14..0000000
--- a/docs/manpages/kodi-j2meremote.1
+++ /dev/null
@@ -1,19 +0,0 @@
-.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.36.
-.TH KODI-J2MEREMOTE "1" "October 2014" "kodi-j2meremote  " "User Commands"
-.SH NAME
-kodi-j2meremote \- Java Bluetooth Phone Remote Control Client for Kodi
-.SH DESCRIPTION
-This script is the Kodi remote control client that will allow Kodi to be
-controlled by a Java Bluetooth Phone.
-.SH USAGE
-Usage for kodi-j2meremote
-.SS "Arguments:"
-.TP
-\fB\-\-address\fR ADDRESS
-(default: localhost)
-.TP
-\fB\-\-port\fR PORT
-(default: 9777)
-.TP
-\fB\-\-help\fR
-(Brings up this message)
diff --git a/lib/addons/library.kodi.adsp/CMakeLists.txt b/lib/addons/library.kodi.adsp/CMakeLists.txt
index 027c5ca..b3fc142 100644
--- a/lib/addons/library.kodi.adsp/CMakeLists.txt
+++ b/lib/addons/library.kodi.adsp/CMakeLists.txt
@@ -1,8 +1,2 @@
-set(SOURCES libKODI_adsp.cpp)
-
-core_add_library(KODI_adsp NO_MAIN_DEPENDS)
-set_target_properties(KODI_adsp PROPERTIES POSITION_INDEPENDENT_CODE True)
-target_include_directories(KODI_adsp PRIVATE
-                           ${CMAKE_CURRENT_SOURCE_DIR}
-                           ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi
-                           ${CORE_SOURCE_DIR}/xbmc)
+project(KODI_adsp)
+core_add_addon_library(${PROJECT_NAME})
diff --git a/lib/addons/library.kodi.adsp/project/VS2010Express/libKODI_adsp.vcxproj b/lib/addons/library.kodi.adsp/project/VS2010Express/libKODI_adsp.vcxproj
index d5fc737..12e716d 100644
--- a/lib/addons/library.kodi.adsp/project/VS2010Express/libKODI_adsp.vcxproj
+++ b/lib/addons/library.kodi.adsp/project/VS2010Express/libKODI_adsp.vcxproj
@@ -14,6 +14,7 @@
     <ProjectGuid>{44F93C4D-85DD-4452-99BB-F1D196174024}</ProjectGuid>
     <RootNamespace>KODI_ADSP</RootNamespace>
     <Keyword>Win32Proj</Keyword>
+    <WindowsTargetPlatformVersion>10.0.10240.0</WindowsTargetPlatformVersion>
   </PropertyGroup>
   <Import Project="$(SolutionDir)\XBMC.core-defaults.props" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
diff --git a/lib/addons/library.kodi.audioengine/CMakeLists.txt b/lib/addons/library.kodi.audioengine/CMakeLists.txt
index e919e29..1a723a2 100644
--- a/lib/addons/library.kodi.audioengine/CMakeLists.txt
+++ b/lib/addons/library.kodi.audioengine/CMakeLists.txt
@@ -1,8 +1,2 @@
-set(SOURCES libKODI_audioengine.cpp)
-
-core_add_library(KODI_audioengine NO_MAIN_DEPENDS)
-set_target_properties(KODI_audioengine PROPERTIES POSITION_INDEPENDENT_CODE True)
-target_include_directories(KODI_audioengine PRIVATE
-                           ${CMAKE_CURRENT_SOURCE_DIR}
-                           ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi
-                           ${CORE_SOURCE_DIR}/xbmc)
+project(KODI_audioengine)
+core_add_addon_library(${PROJECT_NAME})
diff --git a/lib/addons/library.kodi.audioengine/project/VS2010Express/libKODI_audioengine.vcxproj b/lib/addons/library.kodi.audioengine/project/VS2010Express/libKODI_audioengine.vcxproj
index ae5e1cf..07b3089 100644
--- a/lib/addons/library.kodi.audioengine/project/VS2010Express/libKODI_audioengine.vcxproj
+++ b/lib/addons/library.kodi.audioengine/project/VS2010Express/libKODI_audioengine.vcxproj
@@ -20,6 +20,7 @@
     <ProjectGuid>{6B96FD7D-26EE-415B-8858-27757A0B1273}</ProjectGuid>
     <RootNamespace>KODI_ADSP</RootNamespace>
     <Keyword>Win32Proj</Keyword>
+    <WindowsTargetPlatformVersion>10.0.10240.0</WindowsTargetPlatformVersion>
   </PropertyGroup>
   <Import Project="$(SolutionDir)\XBMC.core-defaults.props" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
diff --git a/lib/addons/library.kodi.guilib/CMakeLists.txt b/lib/addons/library.kodi.guilib/CMakeLists.txt
index 4b391ab..70e11fb 100644
--- a/lib/addons/library.kodi.guilib/CMakeLists.txt
+++ b/lib/addons/library.kodi.guilib/CMakeLists.txt
@@ -1,8 +1,2 @@
-set(SOURCES libKODI_guilib.cpp)
-
-core_add_library(KODI_guilib NO_MAIN_DEPENDS)
-set_target_properties(KODI_guilib PROPERTIES POSITION_INDEPENDENT_CODE True)
-target_include_directories(KODI_guilib PRIVATE
-                           ${CMAKE_CURRENT_SOURCE_DIR}
-                           ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi
-                           ${CORE_SOURCE_DIR}/xbmc)
+project(KODI_guilib)
+core_add_addon_library(${PROJECT_NAME})
diff --git a/lib/addons/library.kodi.guilib/project/VS2010Express/libKODI_guilib.vcxproj b/lib/addons/library.kodi.guilib/project/VS2010Express/libKODI_guilib.vcxproj
index ae248d8..fd63cdc 100644
--- a/lib/addons/library.kodi.guilib/project/VS2010Express/libKODI_guilib.vcxproj
+++ b/lib/addons/library.kodi.guilib/project/VS2010Express/libKODI_guilib.vcxproj
@@ -17,6 +17,7 @@
     <ProjectGuid>{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}</ProjectGuid>
     <RootNamespace>XBMC_VDR</RootNamespace>
     <Keyword>Win32Proj</Keyword>
+    <WindowsTargetPlatformVersion>10.0.10240.0</WindowsTargetPlatformVersion>
   </PropertyGroup>
   <Import Project="$(SolutionDir)\XBMC.core-defaults.props" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
diff --git a/lib/addons/library.kodi.inputstream/CMakeLists.txt b/lib/addons/library.kodi.inputstream/CMakeLists.txt
index 167e931..390bf62 100644
--- a/lib/addons/library.kodi.inputstream/CMakeLists.txt
+++ b/lib/addons/library.kodi.inputstream/CMakeLists.txt
@@ -1,8 +1,2 @@
-set(SOURCES libKODI_inputstream.cpp)
-
-core_add_library(KODI_inputstream NO_MAIN_DEPENDS)
-set_target_properties(KODI_inputstream PROPERTIES POSITION_INDEPENDENT_CODE True)
-target_include_directories(KODI_inputstream PRIVATE
-                           ${CMAKE_CURRENT_SOURCE_DIR}
-                           ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi
-                           ${CORE_SOURCE_DIR}/xbmc)
+project(KODI_inputstream)
+core_add_addon_library(${PROJECT_NAME})
diff --git a/lib/addons/library.kodi.inputstream/project/VS2010Express/libKODI_inputstream.vcxproj b/lib/addons/library.kodi.inputstream/project/VS2010Express/libKODI_inputstream.vcxproj
index 870a6ac..5f44b01 100644
--- a/lib/addons/library.kodi.inputstream/project/VS2010Express/libKODI_inputstream.vcxproj
+++ b/lib/addons/library.kodi.inputstream/project/VS2010Express/libKODI_inputstream.vcxproj
@@ -17,6 +17,7 @@
     <ProjectGuid>{8BC9CEB8-8B4A-11D0-8D11-00A0CFEBC942}</ProjectGuid>
     <RootNamespace>XBMC_INPUTSTREAM</RootNamespace>
     <Keyword>Win32Proj</Keyword>
+    <WindowsTargetPlatformVersion>10.0.10240.0</WindowsTargetPlatformVersion>
   </PropertyGroup>
   <Import Project="$(SolutionDir)\XBMC.core-defaults.props" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
diff --git a/lib/addons/library.kodi.peripheral/CMakeLists.txt b/lib/addons/library.kodi.peripheral/CMakeLists.txt
index d409c90..dcaa5b4 100644
--- a/lib/addons/library.kodi.peripheral/CMakeLists.txt
+++ b/lib/addons/library.kodi.peripheral/CMakeLists.txt
@@ -1,8 +1,2 @@
-set(SOURCES libKODI_peripheral.cpp)
-
-core_add_library(KODI_peripheral NO_MAIN_DEPENDS)
-set_target_properties(KODI_peripheral PROPERTIES POSITION_INDEPENDENT_CODE True)
-target_include_directories(KODI_peripheral PRIVATE
-                           ${CMAKE_CURRENT_SOURCE_DIR}
-                           ${CORE_SOURCE_DIR}/xbmc/addons/include
-                           ${CORE_SOURCE_DIR}/xbmc)
+project(KODI_peripheral)
+core_add_addon_library(${PROJECT_NAME})
diff --git a/lib/addons/library.kodi.peripheral/project/VS2010Express/libKODI_peripheral.vcxproj b/lib/addons/library.kodi.peripheral/project/VS2010Express/libKODI_peripheral.vcxproj
index bc85cca..a809f7f 100644
--- a/lib/addons/library.kodi.peripheral/project/VS2010Express/libKODI_peripheral.vcxproj
+++ b/lib/addons/library.kodi.peripheral/project/VS2010Express/libKODI_peripheral.vcxproj
@@ -14,6 +14,7 @@
     <ProjectGuid>{FEA71D39-CB68-486B-A978-246E661A3F89}</ProjectGuid>
     <RootNamespace>XBMC_VDR</RootNamespace>
     <Keyword>Win32Proj</Keyword>
+    <WindowsTargetPlatformVersion>10.0.10240.0</WindowsTargetPlatformVersion>
   </PropertyGroup>
   <Import Project="$(SolutionDir)\XBMC.core-defaults.props" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
diff --git a/lib/addons/library.xbmc.addon/CMakeLists.txt b/lib/addons/library.xbmc.addon/CMakeLists.txt
index e27a361..3f5aac7 100644
--- a/lib/addons/library.xbmc.addon/CMakeLists.txt
+++ b/lib/addons/library.xbmc.addon/CMakeLists.txt
@@ -1,8 +1,2 @@
-set(SOURCES libXBMC_addon.cpp)
-
-core_add_library(XBMC_addon NO_MAIN_DEPENDS)
-set_target_properties(XBMC_addon PROPERTIES POSITION_INDEPENDENT_CODE True)
-target_include_directories(XBMC_addon PRIVATE
-                           ${CMAKE_CURRENT_SOURCE_DIR}
-                           ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi
-                           ${CORE_SOURCE_DIR}/xbmc)
+project(XBMC_addon)
+core_add_addon_library(${PROJECT_NAME})
diff --git a/lib/addons/library.xbmc.addon/project/VS2010Express/libXBMC_addon.vcxproj b/lib/addons/library.xbmc.addon/project/VS2010Express/libXBMC_addon.vcxproj
index 52f0e22..2c2a1bf 100644
--- a/lib/addons/library.xbmc.addon/project/VS2010Express/libXBMC_addon.vcxproj
+++ b/lib/addons/library.xbmc.addon/project/VS2010Express/libXBMC_addon.vcxproj
@@ -14,6 +14,7 @@
     <ProjectGuid>{2DCEA60B-4EBC-4DB7-9FBD-297C1EFD95D7}</ProjectGuid>
     <RootNamespace>XBMC_VDR</RootNamespace>
     <Keyword>Win32Proj</Keyword>
+    <WindowsTargetPlatformVersion>10.0.10240.0</WindowsTargetPlatformVersion>
   </PropertyGroup>
   <Import Project="$(SolutionDir)\XBMC.core-defaults.props" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
diff --git a/lib/addons/library.xbmc.addon/project/VS2010Express/libXBMC_addon.vcxproj.filters b/lib/addons/library.xbmc.addon/project/VS2010Express/libXBMC_addon.vcxproj.filters
index 916673c..6181b0a 100644
--- a/lib/addons/library.xbmc.addon/project/VS2010Express/libXBMC_addon.vcxproj.filters
+++ b/lib/addons/library.xbmc.addon/project/VS2010Express/libXBMC_addon.vcxproj.filters
@@ -12,8 +12,6 @@
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="..\..\..\..\..\addons\library.xbmc.addon\libXBMC_addon.h">
-      <Filter>Source Files</Filter>
-    </ClInclude>
+    <ClInclude Include="..\..\..\..\..\xbmc\addons\kodi-addon-dev-kit\include\kodi\libXBMC_addon.h" />
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/lib/addons/library.xbmc.codec/CMakeLists.txt b/lib/addons/library.xbmc.codec/CMakeLists.txt
index de81d01..0202216 100644
--- a/lib/addons/library.xbmc.codec/CMakeLists.txt
+++ b/lib/addons/library.xbmc.codec/CMakeLists.txt
@@ -1,8 +1,2 @@
-set(SOURCES libXBMC_codec.cpp)
-
-core_add_library(XBMC_codec NO_MAIN_DEPENDS)
-set_target_properties(XBMC_codec PROPERTIES POSITION_INDEPENDENT_CODE True)
-target_include_directories(XBMC_codec PRIVATE
-                           ${CMAKE_CURRENT_SOURCE_DIR}
-                           ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi
-                           ${CORE_SOURCE_DIR}/xbmc)
+project(XBMC_codec)
+core_add_addon_library(${PROJECT_NAME})
diff --git a/lib/addons/library.xbmc.codec/project/VS2010Express/libXBMC_codec.vcxproj b/lib/addons/library.xbmc.codec/project/VS2010Express/libXBMC_codec.vcxproj
index a051f90..3ecdb30 100644
--- a/lib/addons/library.xbmc.codec/project/VS2010Express/libXBMC_codec.vcxproj
+++ b/lib/addons/library.xbmc.codec/project/VS2010Express/libXBMC_codec.vcxproj
@@ -14,6 +14,7 @@
     <ProjectGuid>{F8F1290B-1188-4810-86C9-88178A31D2AF}</ProjectGuid>
     <RootNamespace>XBMC_VDR</RootNamespace>
     <Keyword>Win32Proj</Keyword>
+    <WindowsTargetPlatformVersion>10.0.10240.0</WindowsTargetPlatformVersion>
   </PropertyGroup>
   <Import Project="$(SolutionDir)\XBMC.core-defaults.props" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
diff --git a/lib/addons/library.xbmc.pvr/CMakeLists.txt b/lib/addons/library.xbmc.pvr/CMakeLists.txt
index 98fce55..b431fb7 100644
--- a/lib/addons/library.xbmc.pvr/CMakeLists.txt
+++ b/lib/addons/library.xbmc.pvr/CMakeLists.txt
@@ -1,10 +1,3 @@
-set(SOURCES libXBMC_pvr.cpp)
-
-core_add_library(XBMC_pvr NO_MAIN_DEPENDS)
-set_target_properties(XBMC_pvr PROPERTIES POSITION_INDEPENDENT_CODE True)
-target_include_directories(XBMC_pvr PRIVATE
-                           ${CMAKE_CURRENT_SOURCE_DIR}
-                           ${CORE_SOURCE_DIR}/addons/library.xbmc.addon
-                           ${CORE_SOURCE_DIR}/xbmc
-                           ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include
-                           ${CORE_SOURCE_DIR}/xbmc/cores/VideoPlayer/DVDDemuxers)
+project(XBMC_pvr)
+core_add_addon_library(${PROJECT_NAME})
+target_include_directories(${PROJECT_NAME} PRIVATE ${CORE_SOURCE_DIR}/xbmc/cores/VideoPlayer/DVDDemuxers)
diff --git a/lib/addons/library.xbmc.pvr/project/VS2010Express/libXBMC_pvr.vcxproj b/lib/addons/library.xbmc.pvr/project/VS2010Express/libXBMC_pvr.vcxproj
index 681fab1..89ba869 100644
--- a/lib/addons/library.xbmc.pvr/project/VS2010Express/libXBMC_pvr.vcxproj
+++ b/lib/addons/library.xbmc.pvr/project/VS2010Express/libXBMC_pvr.vcxproj
@@ -14,6 +14,7 @@
     <ProjectGuid>{6D8C91F8-992F-4C83-9DE3-485D64EF8420}</ProjectGuid>
     <RootNamespace>XBMC_VDR</RootNamespace>
     <Keyword>Win32Proj</Keyword>
+    <WindowsTargetPlatformVersion>10.0.10240.0</WindowsTargetPlatformVersion>
   </PropertyGroup>
   <Import Project="$(SolutionDir)\XBMC.core-defaults.props" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
diff --git a/lib/libUPnP/CMakeLists.txt b/lib/libUPnP/CMakeLists.txt
index b565720..73a1d74 100644
--- a/lib/libUPnP/CMakeLists.txt
+++ b/lib/libUPnP/CMakeLists.txt
@@ -70,15 +70,6 @@ set(SOURCES Platinum/Source/Core/PltAction.cpp
             Platinum/Source/Devices/MediaConnect/PltMediaConnect.cpp
             Neptune/Source/System/Posix/NptPosixEnvironment.cpp)
 
-include_directories(Neptune/Source/Core
-                    Platinum/Source/Core
-                    Platinum/Source/Platinum
-                    Platinum/Source/Devices/MediaConnect
-                    Platinum/Source/Devices/MediaRenderer
-                    Platinum/Source/Devices/MediaServer
-                    Neptune/Source/System/Posix
-                    Platinum/Source/Extras)
-
 if(NOT CORE_SYSTEM_NAME STREQUAL windows)
   list(APPEND SOURCES Neptune/Source/System/Posix/NptPosixSystem.cpp
                       Neptune/Source/System/Posix/NptSelectableMessageQueue.cpp
@@ -98,7 +89,6 @@ else()
                       Neptune/Source/System/Win32/NptWin32System.cpp
                       Neptune/Source/System/Win32/NptWin32Threads.cpp
                       Neptune/Source/System/Win32/NptWin32Time.cpp)
-  include_directories(Neptune/Source/System/Win32)
 endif()
 
 if(APPLE)
@@ -106,6 +96,20 @@ if(APPLE)
                       Neptune/Source/System/Apple/NptAppleLogConfig.mm)
 endif()
 
-add_definitions(-DNPT_CONFIG_ENABLE_LOGGING)
-
-core_add_library(upnp)
+add_library(upnp STATIC ${SOURCES} ${HEADERS})
+target_compile_definitions(upnp PUBLIC -DNPT_CONFIG_ENABLE_LOGGING)
+target_include_directories(upnp PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
+                                       Platinum/Source/Core
+                                       Platinum/Source/Platinum
+                                       Platinum/Source/Devices/MediaConnect
+                                       Platinum/Source/Devices/MediaRenderer
+                                       Platinum/Source/Devices/MediaServer
+                                       Platinum/Source/Extras
+                                       Neptune/Source/Core
+                                       Neptune/Source/System/Posix)
+if(CORE_SYSTEM_NAME STREQUAL windows)
+  target_include_directories(upnp PRIVATE Neptune/Source/System/Win32)
+endif()
+set_target_properties(upnp PROPERTIES FOLDER lib)
+source_group_by_folder(upnp)
+set(core_DEPENDS upnp ${core_DEPENDS} CACHE STRING "" FORCE)
diff --git a/lib/libexif/CMakeLists.txt b/lib/libexif/CMakeLists.txt
index d21d4fc..80cee25 100644
--- a/lib/libexif/CMakeLists.txt
+++ b/lib/libexif/CMakeLists.txt
@@ -3,7 +3,12 @@ set(SOURCES ExifParse.cpp
             JpegParse.cpp
             libexif.cpp)
 
-set(CMAKE_POSITION_INDEPENDENT_CODE 1)
+set(HEADERS ExifParse.h
+            IptcParse.h
+            JpegParse.h
+            libexif.h)
 
-core_add_library(exif NO_MAIN_DEPENDS)
+core_add_shared_library(exif WRAPPED)
 target_compile_definitions(exif PRIVATE _LINUX _DLL)
+set_target_properties(exif PROPERTIES FOLDER lib)
+source_group_by_folder(exif)
diff --git a/lib/libexif/libexif.vcxproj b/lib/libexif/libexif.vcxproj
index adf0cfc..de81b48 100644
--- a/lib/libexif/libexif.vcxproj
+++ b/lib/libexif/libexif.vcxproj
@@ -15,6 +15,7 @@
     <ProjectGuid>{AD20A3E2-09CB-42DB-9A70-27F7CDC886CE}</ProjectGuid>
     <RootNamespace>libexif_dll</RootNamespace>
     <Keyword>Win32Proj</Keyword>
+    <WindowsTargetPlatformVersion>10.0.10240.0</WindowsTargetPlatformVersion>
   </PropertyGroup>
   <Import Project="$(SolutionDir)\XBMC.core-defaults.props" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
diff --git a/project/cmake/CMakeLists.txt b/project/cmake/CMakeLists.txt
index a5368ae..1f5a1fc 100644
--- a/project/cmake/CMakeLists.txt
+++ b/project/cmake/CMakeLists.txt
@@ -1,5 +1,5 @@
 cmake_minimum_required(VERSION 3.1)
-project(kodi)
+project(kodi LANGUAGES CXX C ASM)
 
 list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/modules)
 if(DEPENDS_DIR)
@@ -9,6 +9,7 @@ endif()
 set(CMAKE_CXX_STANDARD 11)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 set(CMAKE_CXX_EXTENSIONS OFF)
+set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp")
 
 # general
 option(VERBOSE            "Enable verbose output?" OFF)
@@ -53,13 +54,26 @@ if(NOT WIN32)
 endif()
 if(CMAKE_SYSTEM_NAME STREQUAL Linux)
   option(ENABLE_LIRC            "Enable LIRC support?" ON)
+  option(ENABLE_EVENTCLIENTS    "Enable event clients support?" OFF)
 endif()
 
+# Build static libraries per directory
+if(NOT CMAKE_GENERATOR MATCHES "Visual Studio" AND NOT CMAKE_GENERATOR STREQUAL Xcode)
+  set(STATIC_LIBS_DEFAULT ON)
+else()
+  set(STATIC_LIBS_DEFAULT OFF)
+endif()
+option(ENABLE_STATIC_LIBS "Build static libraries per directory" ${STATIC_LIBS_DEFAULT})
+unset(STATIC_LIBS_DEFAULT)
+
 get_filename_component(CORE_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../.. ABSOLUTE)
 set(CORE_BUILD_DIR build)
 
 message(STATUS "Source directory: ${CORE_SOURCE_DIR}")
 message(STATUS "Build directory: ${CMAKE_BINARY_DIR}")
+if(CMAKE_BINARY_DIR STREQUAL CORE_SOURCE_DIR)
+  message(WARNING "In-source build detected. It is recommended to build out-of-source.")
+endif()
 
 include(modules/extra/ECMEnableSanitizers.cmake)
 include(scripts/common/GeneratorSetup.cmake)
@@ -73,6 +87,11 @@ include(ExternalProject)
 core_find_git_rev()
 core_find_versions()
 
+# Dynamically loaded libraries built with the project
+add_custom_target(${APP_NAME_LC}-libraries)
+set(LIBRARY_FILES "" CACHE STRING "" FORCE)
+mark_as_advanced(LIBRARY_FILES)
+
 set(INCLUDES ${CORE_SOURCE_DIR}
              ${CORE_SOURCE_DIR}/addons/library.xbmc.addon
              ${CORE_SOURCE_DIR}/lib
@@ -227,13 +246,15 @@ list(APPEND install_data addons/xbmc.addon/addon.xml)
 list(APPEND install_data addons/xbmc.json/addon.xml)
 list(APPEND install_data addons/kodi.guilib/addon.xml)
 add_library(compileinfo OBJECT ${CORE_BUILD_DIR}/xbmc/CompileInfo.cpp)
+set_target_properties(compileinfo PROPERTIES FOLDER "Build Utilities")
 target_compile_options(compileinfo PRIVATE "${SYSTEM_DEFINES}")
 
 # RC File
 if(WIN32)
-  configure_file(${CORE_SOURCE_DIR}/xbmc/win32/XBMC_PC.rc.in
-                 ${CORE_BUILD_DIR}/xbmc/win32/XBMC_PC.rc @ONLY)
-  add_library(resources OBJECT ${CORE_BUILD_DIR}/xbmc/win32/XBMC_PC.rc)
+  configure_file(${CORE_SOURCE_DIR}/xbmc/platform/win32/XBMC_PC.rc.in
+                 ${CORE_BUILD_DIR}/xbmc/platform/win32/XBMC_PC.rc @ONLY)
+  add_library(resources OBJECT ${CORE_BUILD_DIR}/xbmc/platform/win32/XBMC_PC.rc)
+  set_target_properties(resources PROPERTIES FOLDER "Build Utilities")
   target_include_directories(resources PRIVATE ${CORE_SOURCE_DIR}/tools/windows/packaging/media)
   set(RESOURCES $<TARGET_OBJECTS:resources>)
 endif()
@@ -248,23 +269,8 @@ mark_as_advanced(core_DEPENDS)
 mark_as_advanced(test_archives)
 mark_as_advanced(test_sources)
 
-file(STRINGS ${PROJECT_SOURCE_DIR}/installdata/addon-bindings.txt bindings)
-foreach(binding ${bindings})
-  list(APPEND addon_bindings ${CORE_SOURCE_DIR}/${binding})
-endforeach()
-
-file(STRINGS ${PROJECT_SOURCE_DIR}/installdata/cmake-files.txt cmakefiles)
-foreach(cmakefile ${cmakefiles})
-  list(APPEND cmake_files ${CORE_SOURCE_DIR}/${cmakefile})
-endforeach()
-
 add_subdirectory(${CORE_SOURCE_DIR}/lib/gtest ${CORE_BUILD_DIR}/gtest EXCLUDE_FROM_ALL)
-
-# Subdirs
-core_add_subdirs_from_filelist(${PROJECT_SOURCE_DIR}/treedata/common/*.txt
-                               ${PROJECT_SOURCE_DIR}/treedata/${CORE_SYSTEM_NAME}/*.txt)
-core_add_optional_subdirs_from_filelist(${PROJECT_SOURCE_DIR}/treedata/optional/common/*.txt
-                                        ${PROJECT_SOURCE_DIR}/treedata/optional/${CORE_SYSTEM_NAME}/*.txt)
+set_target_properties(gtest PROPERTIES FOLDER "External Projects")
 
 # copy files to build tree
 copy_files_from_filelist_to_buildtree(${PROJECT_SOURCE_DIR}/installdata/common/*.txt
@@ -282,23 +288,9 @@ endforeach()
 
 add_custom_target(pack-skins ALL
                   DEPENDS TexturePacker::TexturePacker export-files ${XBT_FILES})
-
-core_link_library(exif system/libexif)
-if(CORE_SYSTEM_NAME STREQUAL linux)
-  core_link_library(sse4 system/libsse4)
-endif()
-
-core_link_library(XBMC_addon addons/library.xbmc.addon/libXBMC_addon nowrap)
-core_link_library(XBMC_codec addons/library.xbmc.codec/libXBMC_codec nowrap)
-core_link_library(XBMC_pvr addons/library.xbmc.pvr/libXBMC_pvr nowrap)
-core_link_library(KODI_adsp addons/library.kodi.adsp/libKODI_adsp nowrap)
-core_link_library(KODI_audioengine addons/library.kodi.audioengine/libKODI_audioengine nowrap)
-core_link_library(KODI_guilib addons/library.kodi.guilib/libKODI_guilib nowrap)
-core_link_library(KODI_inputstream addons/library.kodi.inputstream/libKODI_inputstream nowrap)
-core_link_library(KODI_peripheral addons/library.kodi.peripheral/libKODI_peripheral nowrap)
+set_target_properties(pack-skins PROPERTIES FOLDER "Build Utilities")
 
 file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/system/players/VideoPlayer)
-add_custom_target(wrap-libraries ALL DEPENDS ${WRAP_FILES})
 
 set(LIBCEC_SONAME "${CEC_SONAME}")
 if(NOT CORE_SYSTEM_NAME STREQUAL windows AND NOT CORE_SYSTEM_NAME STREQUAL android)
@@ -309,26 +301,48 @@ elseif(CORE_SYSTEM_NAME STREQUAL android)
                  ${CORE_BUILD_DIR}/DllPaths_generated_android.h @ONLY)
 endif()
 
+# main library (used for main binary and tests)
+add_library(lib${APP_NAME_LC} STATIC $<TARGET_OBJECTS:compileinfo>)
+set_target_properties(lib${APP_NAME_LC} PROPERTIES PREFIX "")
+add_dependencies(lib${APP_NAME_LC} libcpluff ffmpeg dvdnav crossguid)
+
 # Codegen
 add_subdirectory(${CORE_SOURCE_DIR}/xbmc/interfaces/swig build/swig)
 
 # Other files (IDE)
 set(OTHER_FILES README.md)
 
+# Subdirs
+core_add_subdirs_from_filelist(${PROJECT_SOURCE_DIR}/treedata/common/*.txt
+                               ${PROJECT_SOURCE_DIR}/treedata/${CORE_SYSTEM_NAME}/*.txt)
+core_add_optional_subdirs_from_filelist(${PROJECT_SOURCE_DIR}/treedata/optional/common/*.txt
+                                        ${PROJECT_SOURCE_DIR}/treedata/optional/${CORE_SYSTEM_NAME}/*.txt)
+
+target_link_libraries(lib${APP_NAME_LC} PUBLIC ${core_DEPENDS} ${SYSTEM_LDFLAGS} ${DEPLIBS} ${CMAKE_DL_LIBS})
+set_target_properties(lib${APP_NAME_LC} PROPERTIES PROJECT_LABEL "xbmc")
+source_group_by_folder(lib${APP_NAME_LC} RELATIVE ${CORE_SOURCE_DIR}/xbmc)
+if(WIN32)
+  add_precompiled_header(lib${APP_NAME_LC} pch.h ${CORE_SOURCE_DIR}/xbmc/platform/win32/pch.cpp PCH_TARGET kodi)
+  set_language_cxx(lib${APP_NAME_LC})
+endif()
+
 # main binary
 if(NOT CORE_SYSTEM_NAME STREQUAL android)
-  add_executable(${APP_NAME_LC} ${CORE_MAIN_SOURCE} $<TARGET_OBJECTS:compileinfo> "${RESOURCES}" ${OTHER_FILES})
+  add_executable(${APP_NAME_LC} ${CORE_MAIN_SOURCE} "${RESOURCES}" ${OTHER_FILES})
+  add_dependencies(${APP_NAME_LC} ${APP_NAME_LC}-libraries export-files pack-skins)
 else()
-  add_library(${APP_NAME_LC} SHARED ${CORE_MAIN_SOURCE} $<TARGET_OBJECTS:compileinfo> "${RESOURCES}" ${OTHER_FILES})
+  add_library(${APP_NAME_LC} SHARED ${CORE_MAIN_SOURCE} "${RESOURCES}" ${OTHER_FILES})
+  # The libraries depend on the main shared library for wrapping. Because of this we cannot build
+  # the libraries as a dependency. This requires to build the all target on android (and not only kodi).
+  add_dependencies(${APP_NAME_LC} export-files pack-skins)
 endif()
 whole_archive(_MAIN_LIBRARIES ${core_DEPENDS})
-target_link_libraries(${APP_NAME_LC} ${SYSTEM_LDFLAGS} ${_MAIN_LIBRARIES} ${DEPLIBS} ${CMAKE_DL_LIBS})
+target_link_libraries(${APP_NAME_LC} ${_MAIN_LIBRARIES} lib${APP_NAME_LC} ${SYSTEM_LDFLAGS} ${DEPLIBS} ${CMAKE_DL_LIBS})
 unset(_MAIN_LIBRARIES)
-add_dependencies(${APP_NAME_LC} export-files)
 
 if(WIN32)
   set_target_properties(${APP_NAME_LC} PROPERTIES WIN32_EXECUTABLE ON)
-  copy_main_dlls_to_buildtree()
+  set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT ${APP_NAME_LC})
 elseif(CORE_SYSTEM_NAME STREQUAL android)
   # Nothing
 else()
@@ -337,11 +351,14 @@ endif()
 
 # testing
 copy_files_from_filelist_to_buildtree(${PROJECT_SOURCE_DIR}/installdata/test-reference-data.txt NO_INSTALL)
-add_executable(${APP_NAME_LC}-test EXCLUDE_FROM_ALL ${CORE_SOURCE_DIR}/xbmc/test/xbmc-test.cpp $<TARGET_OBJECTS:compileinfo>)
-whole_archive(_TEST_LIBRARIES ${core_DEPENDS} gtest ${test_archives})
-target_link_libraries(${APP_NAME_LC}-test ${SYSTEM_LDFLAGS} ${_TEST_LIBRARIES} ${DEPLIBS} ${CMAKE_DL_LIBS})
+add_executable(${APP_NAME_LC}-test EXCLUDE_FROM_ALL ${CORE_SOURCE_DIR}/xbmc/test/xbmc-test.cpp ${test_sources})
+whole_archive(_TEST_LIBRARIES ${core_DEPENDS} gtest)
+target_link_libraries(${APP_NAME_LC}-test PRIVATE ${SYSTEM_LDFLAGS} ${_TEST_LIBRARIES} lib${APP_NAME_LC} ${DEPLIBS} ${CMAKE_DL_LIBS})
 unset(_TEST_LIBRARIES)
-add_dependencies(${APP_NAME_LC}-test export-files)
+add_dependencies(${APP_NAME_LC}-test ${APP_NAME_LC}-libraries export-files)
+if(WIN32)
+  add_precompiled_header(${APP_NAME_LC}-test pch.h ${CORE_SOURCE_DIR}/xbmc/platform/win32/pch.cpp PCH_TARGET kodi)
+endif()
 
 # make test and make check (cannot be executed when cross compiling)
 if(NOT CMAKE_CROSSCOMPILING)
@@ -353,6 +370,16 @@ if(NOT CMAKE_CROSSCOMPILING)
   # For testing commit series
   add_custom_target(check-commits ${CMAKE_COMMAND} -P ${PROJECT_SOURCE_DIR}/scripts/common/CheckCommits.cmake
                                                    -DCMAKE_BINARY_DIR=${CMAKE_BINARY_DIR})
+  set_target_properties(check-commits PROPERTIES FOLDER "Build Utilities")
+endif()
+
+# code coverage
+if(CMAKE_BUILD_TYPE STREQUAL Coverage)
+  if(EXISTS ${PROJECT_SOURCE_DIR}/scripts/${CORE_SYSTEM_NAME}/CodeCoverage.cmake)
+    include(${PROJECT_SOURCE_DIR}/scripts/${CORE_SYSTEM_NAME}/CodeCoverage.cmake)
+  else()
+    message(FATAL_ERROR "Code coverage not (yet) implemented for platform ${CORE_SYSTEM_NAME}")
+  endif()
 endif()
 
 # link wrapper
@@ -363,19 +390,33 @@ if(FFMPEG_CREATE_SHARED_LIBRARY)
   set(CMAKE_CXX_CREATE_SHARED_LIBRARY "${FFMPEG_CREATE_SHARED_LIBRARY}")
 endif()
 
-# randr
-if(ENABLE_X11 AND XRANDR_FOUND)
-  add_executable(kodi-xrandr ${CORE_SOURCE_DIR}/xbmc-xrandr.c)
-  target_link_libraries(kodi-xrandr ${SYSTEM_LDFLAGS} ${X_LIBRARIES} m ${XRANDR_LIBRARIES})
-endif()
-
-# XBMCHelper
-if(CORE_SYSTEM_NAME STREQUAL osx)
-  add_subdirectory(${CORE_SOURCE_DIR}/tools/EventClients/Clients/OSXRemote build/XBMCHelper)
+# Platform specific additional extra targets
+if(EXISTS ${PROJECT_SOURCE_DIR}/scripts/${CORE_SYSTEM_NAME}/ExtraTargets.cmake)
+  include(${PROJECT_SOURCE_DIR}/scripts/${CORE_SYSTEM_NAME}/ExtraTargets.cmake)
 endif()
 
 include(scripts/${CORE_SYSTEM_NAME}/Install.cmake)
 
+# Create target that allows to build binary-addons.
+# Use make binary-addons ADDONS="visualization.spectrum" to select the addons to build.
+if(CMAKE_GENERATOR STREQUAL "Unix Makefiles")
+  if(CMAKE_CROSSCOMPILING)
+    set(_cross_args CROSS_COMPILING=yes TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE})
+  endif()
+  if(NOT CORE_SYSTEM_NAME STREQUAL android)
+    set(_prefix ${CMAKE_BINARY_DIR}/addons)
+    set(_extra "CMAKE_EXTRA=-DPACKAGE_ZIP=ON")
+  else()
+    set(_prefix ${CMAKE_INSTALL_PREFIX})
+  endif()
+  add_custom_target(binary-addons
+    COMMAND $(MAKE) -C ${CORE_SOURCE_DIR}/tools/depends/target/binary-addons clean
+    COMMAND $(MAKE) -C ${CORE_SOURCE_DIR}/tools/depends/target/binary-addons VERBOSE=1 V=99
+                    PREFIX=${_prefix} INSTALL_PREFIX=${_prefix} ${_cross_args} ${_extra})
+  unset(_cross_args)
+  unset(_prefix)
+endif()
+
 # Prepare add-on build env
 foreach(binding ${addon_bindings})
   get_filename_component(file ${binding} NAME)
@@ -416,6 +457,8 @@ if(VERBOSE)
   message(STATUS "datarootdir: ${datarootdir}")
   message(STATUS "#---------------------------------------------#")
   message(STATUS "GIT_REV: ${APP_SCMID}")
+  message(STATUS "#---------------------------------------------#")
+  message(STATUS "CPACK_GENERATOR       : ${CPACK_GENERATOR}")
+  message(STATUS "CPACK_SOURCE_GENERATOR: ${CPACK_SOURCE_GENERATOR}")
+  message(STATUS "#---------------------------------------------#")
 endif()
-message(STATUS "#---------------------------------------------#")
-
diff --git a/project/cmake/README.md b/project/cmake/README.md
index fafd078..26815f6 100644
--- a/project/cmake/README.md
+++ b/project/cmake/README.md
@@ -7,10 +7,11 @@ The current version of the buildsystem is capable of building the main Kodi
 executable (but no packaging or dependency management yet) for the following
 platforms:
 
-- Linux (GNU Makefiles)
-- Windows (NMake Makefiles, Visual Studio 14 (2015))
-- OSX (GNU Makefiles, Xcode)
+- Linux (GNU Makefiles, Ninja)
+- Windows (NMake Makefiles, Visual Studio 14 (2015), Ninja)
+- OSX and IOS (GNU Makefiles, Xcode, Ninja)
 - Android (GNU Makefiles)
+- FreeBSD (GNU Makefiles)
 
 Before building Kodi with CMake, please ensure that you have the platform
 specific dependencies installed.
@@ -89,6 +90,22 @@ cmake --build . -- VERBOSE=1 -j$(nproc)  # or: make VERBOSE=1 -j$(nproc)
 
 `CMAKE_BUILD_TYPE` defaults to `Release`.
 
+#### Debian package generation
+The buildsystem is capable of generating Debian packages using CPack. To generate them, `CPACK_GENERATOR` has to be set to *DEB*, i.e. executing CMake's configure step with `-DCPACK_GENERATOR=DEB`.
+You should use CMake/CPack 3.6.0 or higher. Lower versions can generate the packages but package names will be mangled.
+
+The following optional variables (which can be passed to buildsystem when executing cmake with the -D`<variable-name>=<value>` format) can be used to manipulate package type, name and version:
+
+- `DEBIAN_PACKAGE_TYPE` controls the name and version of generated packages. Accepted values are `stable`, `unstable` and `nightly` (default is `nightly`).
+- `DEBIAN_PACKAGE_EPOCH` controls package epoch (default is `2`)
+- `DEBIAN_PACKAGE_VERSION` controls package version (default is `0`)
+- `DEBIAN_PACKAGE_REVISION` controls package revision (no default is set)
+
+Packages metadata can be changed simply by editing files present in the `cpack/deb` folder
+A lot more variables are available (see cpack/CPackDebian.cmake file) but you shouldn't mess with them unless you know what you're doing.
+
+Generated packages can be found in <BUILD_DIR>/packages.
+
 ### Raspberry Pi with GNU Makefiles
 
 ```
@@ -152,6 +169,12 @@ When using the makefile builds a few extra targets are defined:
 
 - `make check` builds and executes the test suite.
 
+Code coverage (with Gcov, LCOV and Gcovr) can be built on Linux:
+
+- CMake has to be executed with `-DCMAKE_BUILD_TYPE=Coverage`
+- `make coverage` generates an HTML code coverage report.
+- `make coverage_xml` generates an XML code coverage report.
+
 ## Sanitizers
 
 Clang and GCC support different kinds of Sanitizers. To enable a Sanitizer call CMake with the
diff --git a/project/cmake/XBMCConfig.cmake.in b/project/cmake/XBMCConfig.cmake.in
deleted file mode 100644
index 73d1c9c..0000000
--- a/project/cmake/XBMCConfig.cmake.in
+++ /dev/null
@@ -1,4 +0,0 @@
-message(WARNING "find_package(xbmc) has been deprecated, please use find_package(kodi)")
-
-find_package(kodi REQUIRED)
-set(XBMC_INCLUDE_DIR ${KODI_INCLUDE_DIR})
\ No newline at end of file
diff --git a/project/cmake/cpack/CPackConfigDEB.cmake b/project/cmake/cpack/CPackConfigDEB.cmake
new file mode 100644
index 0000000..5ad7da1
--- /dev/null
+++ b/project/cmake/cpack/CPackConfigDEB.cmake
@@ -0,0 +1,349 @@
+# include Macros.cmake to automate generation of time/date stamps, maintainer, etc.
+include(${PROJECT_SOURCE_DIR}/scripts/common/Macros.cmake)
+
+# find stuff we need
+find_program(LSB_RELEASE_CMD lsb_release)
+find_program(DPKG_CMD dpkg)
+find_package(Git)
+find_program(GZIP_CMD gzip)
+
+# set packaging dir
+if(NOT CPACK_PACKAGE_DIRECTORY)
+  set(CPACK_PACKAGE_DIRECTORY ${CMAKE_BINARY_DIR}/packages)
+endif()
+
+# set architecture
+if(NOT CPACK_SYSTEM_NAME)
+  set(CPACK_SYSTEM_NAME ${CMAKE_SYSTEM_PROCESSOR})
+  # sanity check
+  if(CPACK_SYSTEM_NAME STREQUAL x86_64)
+    set(CPACK_SYSTEM_NAME amd64)
+  endif()
+endif()
+
+# set packaging by components
+set(CPACK_DEB_COMPONENT_INSTALL ON)
+
+# enforce Debian policy permission rules
+set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION ON)
+
+# packaging by components doesn't fully work with CMake/CPack <3.6.0
+# CPACK_DEBIAN_<COMPONENT>_FILE_NAME is a 3.6.0 addition
+# warn if detected version is lower
+if(CMAKE_VERSION VERSION_LESS 3.6)
+  message(WARNING "DEB Generator: CMake/CPack 3.6 or higher is needed to produce correctly named packages.")
+endif()
+
+# distro codename
+if(NOT DISTRO_CODENAME)
+  if(NOT LSB_RELEASE_CMD)
+    message(WARNING "DEB Generator: Can't find lsb_release in your path. Setting DISTRO_CODENAME to unknown.")
+    set(DISTRO_CODENAME unknown)
+  else()
+    execute_process(COMMAND ${LSB_RELEASE_CMD} -cs
+                    OUTPUT_VARIABLE DISTRO_CODENAME
+                    OUTPUT_STRIP_TRAILING_WHITESPACE)
+  endif()
+endif()
+
+# package version
+if(DEBIAN_PACKAGE_VERSION)
+  set(DISTRO_CODENAME ${DEBIAN_PACKAGE_VERSION}${DISTRO_CODENAME})
+else()
+  set(DISTRO_CODENAME 0${DISTRO_CODENAME})
+endif()
+
+# package revision
+if(DEBIAN_PACKAGE_REVISION)
+  set(DISTRO_CODENAME ${DISTRO_CODENAME}${DEBIAN_PACKAGE_REVISION})
+endif()
+
+# package type
+if(DEBIAN_PACKAGE_TYPE STREQUAL stable)
+  set(RELEASE_IDENTIFIER final)
+elseif(DEBIAN_PACKAGE_TYPE STREQUAL unstable)
+  set(RELEASE_IDENTIFIER ${APP_VERSION_TAG_LC})
+else()
+  set(RELEASE_IDENTIFIER ${GIT_HASH})
+endif()
+
+# package name
+string(TIMESTAMP PACKAGE_TIMESTAMP "%Y%m%d.%H%M" UTC)
+set(PACKAGE_NAME_VERSION ${APP_VERSION_MAJOR}.${APP_VERSION_MINOR}~git${PACKAGE_TIMESTAMP}-${RELEASE_IDENTIFIER}-${DISTRO_CODENAME})
+unset(RELEASE_IDENTIFIER)
+
+# package version
+if(DEBIAN_PACKAGE_EPOCH)
+  set(CPACK_DEBIAN_PACKAGE_VERSION ${DEBIAN_PACKAGE_EPOCH}:${PACKAGE_NAME_VERSION})
+else()
+  set(CPACK_DEBIAN_PACKAGE_VERSION 2:${PACKAGE_NAME_VERSION})
+endif()
+
+# architecture
+if(NOT CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
+  if(NOT DPKG_CMD)
+    message(WARNING "DEB Generator: Can't find dpkg in your path. Setting CPACK_DEBIAN_PACKAGE_ARCHITECTURE to i386.")
+    set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE i386)
+  endif()
+  execute_process(COMMAND "${DPKG_CMD}" --print-architecture
+                  OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE
+                  OUTPUT_STRIP_TRAILING_WHITESPACE)
+endif()
+
+# package maintainer
+if(NOT CPACK_DEBIAN_PACKAGE_MAINTAINER)
+  userstamp()
+  set(CPACK_DEBIAN_PACKAGE_MAINTAINER ${PACKAGE_MAINTAINER})
+  unset(PACKAGE_MAINTAINER)
+endif()
+
+# package description common to all packages
+if(NOT CPACK_DEBIAN_PACKAGE_DESCRIPTION)
+  file(STRINGS ${PROJECT_SOURCE_DIR}/cpack/deb/package-description.txt DESC_LINES)
+  foreach(LINE IN LISTS DESC_LINES)
+    set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${CPACK_DEBIAN_PACKAGE_DESCRIPTION} ${LINE}\n")
+  endforeach()
+endif()
+
+# package homepage
+if(NOT CPACK_DEBIAN_PACKAGE_HOMEPAGE)
+  set(CPACK_DEBIAN_PACKAGE_HOMEPAGE ${APP_WEBSITE})
+endif()
+
+# generate a Debian compliant changelog
+set(CHANGELOG_HEADER "${APP_NAME_LC} (${CPACK_DEBIAN_PACKAGE_VERSION}) ${DISTRO_CODENAME}\; urgency=high")
+rfc2822stamp()
+# two spaces between maintainer and timestamp is NOT a mistake
+set(CHANGELOG_FOOTER " -- ${CPACK_DEBIAN_PACKAGE_MAINTAINER}  ${RFC2822_TIMESTAMP}")
+
+if(GIT_FOUND AND GZIP_CMD AND EXISTS ${CORE_SOURCE_DIR}/.git)
+  execute_process(COMMAND ${GIT_EXECUTABLE} log --no-merges --pretty=format:"%n  [%an]%n   * %s" --since="last month"
+                  OUTPUT_VARIABLE CHANGELOG
+                  WORKING_DIRECTORY ${CORE_SOURCE_DIR}
+                  OUTPUT_STRIP_TRAILING_WHITESPACE)
+  string(REPLACE "\"" "" CHANGELOG ${CHANGELOG})
+  file(WRITE ${CPACK_PACKAGE_DIRECTORY}/deb/changelog.Debian ${CHANGELOG_HEADER}\n${CHANGELOG}\n\n${CHANGELOG_FOOTER})
+  execute_process(COMMAND ${GZIP_CMD} -f -9 -n ${CPACK_PACKAGE_DIRECTORY}/deb/changelog.Debian)
+  unset(CHANGELOG_HEADER)
+  unset(CHANGELOG_FOOTER)
+  unset(RFC2822_TIMESTAMP)
+else()
+  message(WARNING "DEB Generator: Can't find git and/or gzip in your path. DEB packages will be missing changelog.Debian.gz.")
+endif()
+
+# Generate NEWS.Debian
+configure_file(${PROJECT_SOURCE_DIR}/cpack/deb/NEWS.Debian
+               ${CPACK_PACKAGE_DIRECTORY}/deb/NEWS.Debian @ONLY)
+if(GZIP_CMD)
+  execute_process(COMMAND ${GZIP_CMD} -f -9 -n ${CPACK_PACKAGE_DIRECTORY}/deb/NEWS.Debian)
+else()
+  message(WARNING "DEB Generator: Can't find gzip in your path. DEB packages will be missing NEWS.Debian.")
+endif()
+
+# Generate man pages
+configure_file(${CORE_SOURCE_DIR}/docs/manpages/kodi.bin.1
+               ${CPACK_PACKAGE_DIRECTORY}/deb/kodi.1 COPYONLY)
+configure_file(${CORE_SOURCE_DIR}/docs/manpages/kodi.bin.1
+               ${CPACK_PACKAGE_DIRECTORY}/deb/kodi.bin.1 COPYONLY)
+configure_file(${CORE_SOURCE_DIR}/docs/manpages/kodi-standalone.1
+               ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-standalone.1 COPYONLY)
+if(ENABLE_EVENTCLIENTS)
+  configure_file(${CORE_SOURCE_DIR}/docs/manpages/kodi-ps3remote.1
+                 ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-ps3remote.1 COPYONLY)
+  configure_file(${CORE_SOURCE_DIR}/docs/manpages/kodi-send.1
+                 ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-send.1 COPYONLY)
+  configure_file(${CORE_SOURCE_DIR}/docs/manpages/kodi-wiiremote.1
+                 ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-wiiremote.1 COPYONLY)
+endif()
+
+if(GZIP_CMD)
+  execute_process(COMMAND ${GZIP_CMD} -f -9 -n ${CPACK_PACKAGE_DIRECTORY}/deb/kodi.1)
+  execute_process(COMMAND ${GZIP_CMD} -f -9 -n ${CPACK_PACKAGE_DIRECTORY}/deb/kodi.bin.1)
+  execute_process(COMMAND ${GZIP_CMD} -f -9 -n ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-standalone.1)
+  if(ENABLE_EVENTCLIENTS)
+    execute_process(COMMAND ${GZIP_CMD} -f -9 -n ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-ps3remote.1)
+    execute_process(COMMAND ${GZIP_CMD} -f -9 -n ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-send.1)
+    execute_process(COMMAND ${GZIP_CMD} -f -9 -n ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-wiiremote.1)
+  endif()
+else()
+  message(WARNING "DEB Generator: Can't find gzip in your path. Several DEB packages will be missing man pages.")
+endif()
+
+install(FILES ${CPACK_PACKAGE_DIRECTORY}/deb/kodi.1.gz
+              ${CPACK_PACKAGE_DIRECTORY}/deb/kodi.bin.1.gz
+              ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-standalone.1.gz
+        DESTINATION share/man/man1
+        COMPONENT kodi)
+if(ENABLE_EVENTCLIENTS)
+install(FILES ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-ps3remote.1.gz
+        DESTINATION share/man/man1
+        COMPONENT kodi-eventclients-ps3)
+install(FILES ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-send.1.gz
+        DESTINATION share/man/man1
+        COMPONENT kodi-eventclients-xbmc-send)
+install(FILES ${CPACK_PACKAGE_DIRECTORY}/deb/kodi-wiiremote.1.gz
+        DESTINATION share/man/man1
+        COMPONENT kodi-eventclients-wiiremote)
+endif()
+
+# configure package metadata files
+file(GLOB DEBIAN_PACKAGE_FILES ${PROJECT_SOURCE_DIR}/cpack/deb/packages/*.txt.in)
+foreach(file ${DEBIAN_PACKAGE_FILES})
+  get_filename_component(package ${file} NAME_WE)
+  # filter eventclients so we don't have to support two more deps
+  # (libbluetooth-dev and libcwiid-dev) just because of wii-remote
+  string(SUBSTRING ${package} 0 17 PACKAGE_FILTER)
+  if(NOT ENABLE_EVENTCLIENTS AND PACKAGE_FILTER STREQUAL kodi-eventclients)
+    message(STATUS "DEB Generator: ${package} matches ${PACKAGE_FILTER}, skipping.")
+    # do nothing
+  else()
+    configure_file(${file}
+                   ${CPACK_PACKAGE_DIRECTORY}/deb/${package}.txt @ONLY)
+    list(APPEND DEBIAN_PACKAGES ${package})
+  endif()
+endforeach()
+unset(DEBIAN_PACKAGE_FILES)
+
+# generate packages
+include(CMakeParseArguments)
+foreach(file ${DEBIAN_PACKAGES})
+  core_file_read_filtered(DEBIAN_METADATA ${CPACK_PACKAGE_DIRECTORY}/deb/${file}.txt)
+  string(REPLACE " " ";" DEBIAN_METADATA "${DEBIAN_METADATA}")
+  cmake_parse_arguments(DEB
+                        ""
+                        "PACKAGE_NAME;PACKAGE_ARCHITECTURE;PACKAGE_SECTION;PACKAGE_PRIORITY;PACKAGE_SHLIBDEPS"
+                        "PACKAGE_DEPENDS;PACKAGE_RECOMMENDS;PACKAGE_SUGGESTS;PACKAGE_BREAKS;PACKAGE_REPLACES;PACKAGE_PROVIDES;PACKAGE_DESCRIPTION_HEADER;PACKAGE_DESCRIPTION_FOOTER"
+                        ${DEBIAN_METADATA})
+  string(REPLACE ";" " " DEB_PACKAGE_DEPENDS "${DEB_PACKAGE_DEPENDS}")
+  string(REPLACE ";" " " DEB_PACKAGE_RECOMMENDS "${DEB_PACKAGE_RECOMMENDS}")
+  string(REPLACE ";" " " DEB_PACKAGE_SUGGESTS "${DEB_PACKAGE_SUGGESTS}")
+  string(REPLACE ";" " " DEB_PACKAGE_BREAKS "${DEB_PACKAGE_BREAKS}")
+  string(REPLACE ";" " " DEB_PACKAGE_REPLACES "${DEB_PACKAGE_REPLACES}")
+  string(REPLACE ";" " " DEB_PACKAGE_PROVIDES "${DEB_PACKAGE_PROVIDES}")
+  string(REPLACE ";" " " DEB_PACKAGE_DESCRIPTION_HEADER "${DEB_PACKAGE_DESCRIPTION_HEADER}")
+  string(REPLACE ";" " " DEB_PACKAGE_DESCRIPTION_FOOTER "${DEB_PACKAGE_DESCRIPTION_FOOTER}")
+
+  string(TOUPPER ${file} COMPONENT)
+
+  if(NOT DEB_PACKAGE_ARCHITECTURE)
+    message(STATUS "DEB Generator: Mandatory variable CPACK_DEBIAN_${COMPONENT}_PACKAGE_ARCHITECTURE is empty. Setting to ${CPACK_SYSTEM_NAME}.")
+    set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_ARCHITECTURE ${CPACK_SYSTEM_NAME})
+  else()
+    set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_ARCHITECTURE ${DEB_PACKAGE_ARCHITECTURE})
+  endif()
+
+  if(DEB_PACKAGE_NAME)
+    if(DEB_PACKAGE_ARCHITECTURE)
+      set(CPACK_DEBIAN_${COMPONENT}_FILE_NAME ${DEB_PACKAGE_NAME}_${PACKAGE_NAME_VERSION}_${DEB_PACKAGE_ARCHITECTURE}.deb)
+    else()
+      set(CPACK_DEBIAN_${COMPONENT}_FILE_NAME ${DEB_PACKAGE_NAME}_${PACKAGE_NAME_VERSION}_${CPACK_SYSTEM_NAME}.deb)
+    endif()
+  else()
+    message(FATAL_ERROR "DEB Generator: Mandatory variable CPACK_DEBIAN_${COMPONENT}_FILE_NAME is not set.")
+  endif()
+
+  set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_SOURCE ${APP_NAME_LC})
+
+  if(DEB_PACKAGE_NAME)
+    set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_NAME ${DEB_PACKAGE_NAME})
+  else()
+    message(FATAL_ERROR "DEB Generator: Mandatory variable CPACK_DEBIAN_${COMPONENT}_PACKAGE_NAME is not set.")
+  endif()
+
+  if(DEB_PACKAGE_SECTION)
+    set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_SECTION ${DEB_PACKAGE_SECTION})
+  else()
+    message(FATAL_ERROR "DEB Generator: Mandatory variable CPACK_DEBIAN_${COMPONENT}_PACKAGE_SECTION is not set.")
+  endif()
+
+  if(DEB_PACKAGE_PRIORITY)
+    set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_PRIORITY ${DEB_PACKAGE_PRIORITY})
+  else()
+    message(FATAL_ERROR "DEB Generator: Mandatory variable CPACK_DEBIAN_${COMPONENT}_PACKAGE_PRIORITY is not set.")
+  endif()
+
+  if(DEB_PACKAGE_SHLIBDEPS)
+    set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_SHLIBDEPS ON)
+  else()
+    if(DEB_PACKAGE_DEPENDS)
+      set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_DEPENDS "${DEB_PACKAGE_DEPENDS}")
+    endif()
+  endif()
+
+  if(DEB_PACKAGE_RECOMMENDS)
+    set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_RECOMMENDS "${DEB_PACKAGE_RECOMMENDS}")
+  endif()
+
+  if(DEB_PACKAGE_SUGGESTS)
+    set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_SUGGESTS "${DEB_PACKAGE_SUGGESTS}")
+  endif()
+
+  if(DEB_PACKAGE_BREAKS)
+    set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_BREAKS "${DEB_PACKAGE_BREAKS}")
+  endif()
+
+  if(DEB_PACKAGE_REPLACES)
+    set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_REPLACES "${DEB_PACKAGE_REPLACES}")
+  endif()
+
+  if(DEB_PACKAGE_PROVIDES)
+    set(CPACK_DEBIAN_${COMPONENT}_PACKAGE_PROVIDES "${DEB_PACKAGE_PROVIDES}")
+  endif()
+
+  if(NOT DEB_PACKAGE_DESCRIPTION_HEADER OR NOT DEB_PACKAGE_DESCRIPTION_FOOTER)
+    message(FATAL_ERROR "DEB Generator: Mandatory variable CPACK_COMPONENT_${COMPONENT}_DESCRIPTION is not set.")
+  else()
+    set(CPACK_COMPONENT_${COMPONENT}_DESCRIPTION "\
+${DEB_PACKAGE_DESCRIPTION_HEADER}\n\
+${CPACK_DEBIAN_PACKAGE_DESCRIPTION} \
+${DEB_PACKAGE_DESCRIPTION_FOOTER}")
+  endif()
+
+  install(FILES ${CPACK_PACKAGE_DIRECTORY}/deb/changelog.Debian.gz
+                ${CPACK_PACKAGE_DIRECTORY}/deb/NEWS.Debian.gz
+                ${PROJECT_SOURCE_DIR}/cpack/deb/copyright
+          DESTINATION share/doc/${file}
+          COMPONENT ${file})
+
+  # kodi package exclusive files
+  if(CPACK_DEBIAN_KODI_PACKAGE_NAME)
+    set(CPACK_DEBIAN_KODI_PACKAGE_CONTROL_EXTRA
+        "${PROJECT_SOURCE_DIR}/cpack/deb/postinst;${PROJECT_SOURCE_DIR}/cpack/deb/postrm")
+    install(FILES ${PROJECT_SOURCE_DIR}/cpack/deb/lintian/overrides/kodi
+        DESTINATION share/lintian/overrides
+        COMPONENT kodi)
+    install(FILES ${PROJECT_SOURCE_DIR}/cpack/deb/menu/kodi
+        DESTINATION share/menu
+        COMPONENT kodi)
+  endif()
+endforeach()
+unset(DEBIAN_PACKAGES)
+
+### source package generation specific variables
+# source generator
+set(CPACK_SOURCE_GENERATOR TGZ)
+
+# source package name
+set(CPACK_SOURCE_PACKAGE_FILE_NAME ${APP_NAME_LC}_${APP_VERSION_MAJOR}.${APP_VERSION_MINOR}~git${PACKAGE_TIMESTAMP}-${GIT_HASH}.orig)
+
+# source dir
+set(CMAKE_SOURCE_DIR ${CORE_SOURCE_DIR})
+
+# ignore files for source package
+set(CPACK_SOURCE_IGNORE_FILES
+  "/build/"
+  "/debian/"
+  "/.git/"
+  ".gitignore"
+  "yml$"
+  "~$")
+
+# unset variables
+unset(PACKAGE_TIMESTAMP)
+unset(DISTRO_CODENAME)
+
+# reference docs
+# https://cmake.org/cmake/help/latest/module/CPack.html
+# https://cmake.org/cmake/help/latest/module/CPackDeb.html
+# https://cmake.org/cmake/help/latest/module/CPackComponent.html
+include(CPack)
diff --git a/project/cmake/cpack/deb/NEWS.Debian b/project/cmake/cpack/deb/NEWS.Debian
new file mode 100644
index 0000000..034774b
--- /dev/null
+++ b/project/cmake/cpack/deb/NEWS.Debian
@@ -0,0 +1,24 @@
+ at CPACK_PACKAGE_NAME@ (@CPACK_DEBIAN_PACKAGE_VERSION@) @DISTRO_CODENAME@; urgency=high
+  * Kodi Krypton (v17.0) will have an awesome new default skin, Estuary.
+    However the vast improvements are deep in the bowels of Kodi core code.
+    .
+    Since the beginning of XBMC back in the days while it was running on
+    the XBOX there was something like DVDPlayer. As the name probably
+    implies it was used to playback DVD discs/files. During the years this
+    DVDPlayer was improved and patched up to stay within modern day
+    standards of video playback expectancy. However it became clear that
+    for the future a major overhaul and rewrite was needed to keep up and
+    be future proof. As such the developers who did the AudioEngine in v12
+    picked up this job and have now transformed it into VideoPlayer.
+    .
+    Together with some platform developers they ripped out the old
+    DVDPlayer code, chopped it into pieces, put it in the blender, picked
+    the needed pieces and put it back in without breaking the rest of Kodi.
+    This certainly wasn’t an easy job as DVDPlayer was like the bottom
+    block of a Jenga tower that needed to be replaced while still being
+    entangled throughout the whole tower. It had it’s tentacles in parts
+    of the code where it shouldn’t have been in the first place. Over a
+    year ago work started on getting this untangled and made ready to
+    be replaced by the new implementation, VideoPlayer.
+
+ -- h.udo <hudokkow at gmail.com>  Tue, 05 Jul 2016 13:34:11 +0000
diff --git a/project/cmake/cpack/deb/copyright b/project/cmake/cpack/deb/copyright
new file mode 100644
index 0000000..5616264
--- /dev/null
+++ b/project/cmake/cpack/deb/copyright
@@ -0,0 +1,3244 @@
+Kodi is downloaded from http://kodi.tv/.
+Orig tarballs are generated from the script located at
+https://github.com/Kodi/Kodi/tree/master/project/cmake. The
+orig tarball is generated using the sources in https://github.com/Kodi/Kodi.
+
+Main Contact: "Team-Kodi" <team at kodi dot tv>
+
+Upstream Authors:
+
+    Andreas Setterlind [Gamester17]
+    Staffan Lindberg [pike]
+    Arne Morten Kvarving [cptspiff]
+    Anoop Menon [d4rk]
+    Joakim Plate [elupus]
+    Jonathan Marshall [jmarshall]
+    Tobias Arrskog [Topfs2]
+    Roee Vulkan [vulkanr]
+    Winfried Soltys [WiSo]
+    Yuval Tal [yuvalt]
+    John W Vanderbeck [agathorn]
+    Trent Nelson [AlTheKiller]
+    Andres Mejia [ceros]
+    Gunnar Norin [blittan]
+    Dean Ross Parry [C-Quel]
+    Sylvain Rebaud [c0diq]
+    Martin van Beurden [chadoe]
+    Scott Davilla [davilla]
+    Stephan Diederich [MaestroDD]
+    Benjamin Bertrand [Beenje]
+    Benjamin Dickgiesser [DonJ]
+    [GeminiServer]
+    Christian Granqvist [Granqvist]
+    Dave [kraqh3d]
+    Luigi Capriotti [l.capriotti]
+    Sean [malloc]
+    Kyle Hill [monkeyman]
+    [MrC]
+    [nad]
+    [nuka1195]
+    Vincent Blackwell-Price [Voinage]
+    Robert Parris [rwparris2]
+    Sigurdur H. Olafsson [sho]
+    Alasdair Campbell [Alcoheca]
+    Georgy Yunaev [oldnemesis]
+    Chris [phi2039]
+    Bob [bobo1on1]
+    David Allonby [motd2k]
+    Robert Rudd [Rudd]
+    Eric G [Tslayer]
+    Amund Scharning [tut-ankh-amon]
+    Matthias Kortstiege [VDRfan]
+    Daniel Mehrwald [AreaScout]
+    Oumar Aziz Outtara [wattazoum]
+    Chris Haley [CHI3f]
+    [Jezz_X]
+    [Smokehead]
+    Darren [Bizzeh]
+    Marc [Bobbin007]
+    Richard [Butcher]
+    Jan-Willem [Darkie]
+    Chris Branson [forza]
+    [Kreet]
+    [Ysbox]
+    Erwin Beckers [Frodo]
+    Albert Griscti-Soler [RUNTiME]
+    Phil Burr [d7o3g4q] (a.k.a. Duo Egaq)
+    Mathias Mahling [chokemaniac]
+
+Credits:
+
+Kodi - Cross-platform Media Center
+<http://Kodi.org/>
+
+    Copyright © 2005-2016 Team Kodi http://kodi.tv
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Generic classes for raster images
+
+    Copyright © 2000, Juan Soulie <jsoulie at cplusplus.com>
+
+    Permission to use, copy, modify, distribute and sell this software or any
+    part thereof and/or its documentation for any purpose is granted without fee
+    provided that the above copyright notice and this permission notice appear
+    in all copies.
+
+    This software is provided "as is" without express or implied warranty of
+    any kind. The author shall have no liability with respect to the
+    infringement of copyrights or patents that any modification to the content
+    of this file or this file itself may incur.
+
+The FreeType Project
+<http://www.freetype.org/>
+
+    Copyright © 1996-2006, by David Turner, Robert Wilhelm, and Werner Lemberg
+
+    This file is part of the FreeType project, and may only be used,
+    modified, and distributed under the terms of the FreeType project
+    license, LICENSE.TXT.  By continuing to use, modify, or distribute
+    this file you indicate that you have read the license and
+    understand and accept it fully.
+
+    A full copy of the FreeType License (FTL) is provided under section
+    "Licenses".
+
+TinyXML - simple, small, C++ XML Parser
+<http://www.grinninglizard.com/tinyxml/>
+
+    Copyright © 2000-2006 Lee Thomason (www.grinninglizard.com)
+    Copyright © 2005 Tyge Lovset
+
+    This software is provided 'as-is', without any express or implied
+    warranty.  In no event will the authors be held liable for any damages
+    arising from the use of this software.
+
+    Permission is granted to anyone to use this software for any purpose,
+    including commercial applications, and to alter it and redistribute it
+    freely, subject to the following restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not
+       claim that you wrote the original software. If you use this software
+       in a product, an acknowledgment in the product documentation would be
+       appreciated but is not required.
+    2. Altered source versions must be plainly marked as such, and must not be
+       misrepresented as being the original software.
+    3. This notice may not be removed or altered from any source distribution.
+
+CString Class in guilib/StdString.h
+
+    Copyright © 2002 Joseph M. O'Leary
+
+    This code is 100% free. Use it anywhere you want. Rewrite it, restructure
+    it, whatever. If you can write software that makes money off of it, good for
+    you. I kinda like capitalism. Please don't blame me if it causes your $30
+    billion dollar satellite explode in orbit. If you redistribute it in any
+    form, I'd appreciate it if you would leave this notice here.
+
+Mach-O library symbol mapping Ruby Scripts
+
+    Copyright © 2008 Elan Feingold (elan at bluemandrill dot com)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Wiimote C Library
+<http://www.wiiuse.net/>
+
+    Copyright © Michael Laforest < para >
+        < thepara (--AT--) g m a i l [--DOT--] com >
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Wiiuse Class for Kodi
+
+    Copyright © 2009 by Cory Fields
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Apple Remote Control Wrapper Classes
+
+    Copyright © 2006 Martin Kahr martinkahr.com. All rights reserved.
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and associated documentation files (the "Software"),
+    to deal in the Software without restriction, including without limitation
+    the rights to use, copy, modify, merge, publish, distribute, sublicense,
+    and/or sell copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included
+    in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+    IN THE SOFTWARE.
+
+Class to Display events received from the Apple Infrared Remote.
+
+    Copyright © 2006-2008 Amit Singh. All Rights Reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+    1. Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+
+ISO C9x  compliant stdint.h and inttypes.h for Microsoft Visual Studio
+
+    Copyright © 2006 Alexander Chemeris
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+
+      1. Redistributions of source code must retain the above copyright notice,
+         this list of conditions and the following disclaimer.
+
+      2. Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+
+      3. The name of the author may be used to endorse or promote products
+         derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+    EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+    OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+    ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+cURL - library and command line tool for transferring files with URL syntax
+<http://curl.haxx.se/>
+
+    Copyright © 1998 - 2006, Daniel Stenberg, <daniel at haxx.se>, et al.
+
+    Permission to use, copy, modify, and distribute this software for any
+    purpose with or without fee is hereby granted, provided that the above
+    copyright notice and this permission notice appear in all copies.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+    USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Except as contained in this notice, the name of a copyright holder shall not
+    be used in advertising or otherwise to promote the sale, use or other
+    dealings in this Software without prior written authorization of the
+    copyright holder.
+
+RegExp.h
+
+    Copyright © 1986, 1993, 1995 by University of Toronto.
+
+    Permission is granted to anyone to use this software for any
+    purpose on any computer system, and to redistribute it in any way,
+    subject to the following restrictions:
+
+    1. The author is not responsible for the consequences of use of
+    this software, no matter how awful, even if they arise
+    from defects in it.
+
+    2. The origin of this software must not be misrepresented, either
+    by explicit claim or by omission.
+
+    3. Altered versions must be plainly marked as such, and must not
+    be misrepresented (by explicit claim or omission) as being
+    the original software.
+
+    4. This notice must not be removed or altered.
+
+GNU gettext - internationalization aids
+<http://www.gnu.org/software/gettext/>
+
+    Copyright © 1988, 1989, 1992, 1993, 1995 Free Software Foundation, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+DBUSServer Class
+<http://www.azurdigitalnetworks.net/>
+
+    Copyright © 2009 Azur Digital Networks
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Really Slick X Screensavers
+<http://www.reallyslick.com/>
+
+    Copyright © 2002-2006  Michael Chapman
+    Copyright © 2002 Terence M. Welsh
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+SDLMain.h
+
+    Copyright © Darrell Walisser <dwaliss1 at purdue.edu>
+    Copyright © Max Horn <max at quendi.de>
+
+    Feel free to customize this file to suit your needs.
+
+XKGeneral.h - General Utility and Helper function Class' Header
+
+    Copyright © TEAM ASSEMBLY www.team-assembly.com
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Goom 2k4
+<http://www.ios-software.com/index.php3?page=projet&quoi=1&lg=AN>
+
+    Copyright © 2000-2004, Jean-Christophe Hoelt <jeko at ios-software.com>
+    Copyright © 2000-2004, Guillaume Borios <gyom at ios-software.com>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+    iTunes Visualizer Plug-In SDK files included in Goom 2k4 are under the
+    following license.
+
+    Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+
+    This Apple software is supplied to you by Apple Computer, Inc. in
+    consideration of your agreement to the following terms, and your use,
+    installation, modification or redistribution of this Apple software
+    constitutes acceptance of these terms. If you do not agree with these terms,
+    please do not use, install, modify or redistribute this Apple software.
+
+    In consideration of your agreement to abide by the following terms, and
+    subject to these terms, Apple grants you a personal, non-exclusive license,
+    under Apple's intellectual property rights in this Apple Software (the
+    "Apple Software"), to use, reproduce, modify and distribute the Apple
+    Software; provided that no license is granted herein under any patents that
+    may be infringed by your modifications, derivative works or by other works
+    in which the Apple Software may be incorporated. No names, trademarks,
+    service marks or logos of Apple Computer, Inc. may be used to endorse or
+    promote products derived from the Apple Software without specific prior
+    written permission from Apple. Except as expressly stated herein, no other
+    rights or licenses, express or implied, are granted by Apple and nothing
+    herein grants any license under any patents except claims of Apple patents
+    that cover this Apple Software as originally provided by Apple, and only to
+    the extent necessary to use and distribute this Apple Software as originally
+    provided by Apple.
+
+    The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+    WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+    WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+    PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+    COMBINATION WITH ANY PRODUCT.
+
+    IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+    INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
+    AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER
+    THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
+    OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+XAnalyser, frequence spectrum analyser for X Window
+<http://arvin.schnell-web.net/xanalyser/>
+
+    Copyright © 1998 Arvin Schnell
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+XMMS - Cross-platform multimedia player
+<http://www.xmms.org/>
+
+    Copyright © 1998-2000  Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson
+        and 4Front Technologies
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Pthreads-win32 - POSIX Threads Library for Win32
+<http://sourceware.org/pthreads-win32/>
+
+    Copyright © 1998 John E. Bossom
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+projectM - OpenGL based advanced music visualization program
+<http://projectm.sourceforge.net/>
+
+    Copyright © 2003-2007 projectM Team
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+GLEW - The OpenGL Extension Wrangler Library
+<http://glew.sourceforge.net/>
+
+    Copyright © 2002-2008, Milan Ikits <milan ikits[]ieee org>
+    Copyright © 2002-2008, Marcelo E. Magallon <mmagallo[]debian org>
+    Copyright © 2002, Lev Povalahev
+    Copyright © 1999-2007  Brian Paul
+    Copyright © 2007 The Khronos Group Inc.
+    All Rights Reserved.
+
+    Falls under three licenses, which are the Modified BSD License, the Mesa 3-D
+    License (MIT License), and the Khronos License (MIT License).
+
+    Modified BSD License
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * The name of the author may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+    THE POSSIBILITY OF SUCH DAMAGE.
+
+    Mesa 3-D License (MIT License)
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and associated documentation files (the "Software"),
+    to deal in the Software without restriction, including without limitation
+    the rights to use, copy, modify, merge, publish, distribute, sublicense,
+    and/or sell copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included
+    in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+    BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+    AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    Khronos License (MIT License)
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and/or associated documentation files (the
+    "Materials"), to deal in the Materials without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Materials, and to
+    permit persons to whom the Materials are furnished to do so, subject to
+    the following conditions:
+
+    The above copyright notice and this permission notice shall be included
+    in all copies or substantial portions of the Materials.
+
+    THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+    MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+OpenDAAP
+<http://www.opendaap.org/>
+
+    Copyright © 2004 Forza (Chris Barnett)
+    Copyright © the authors of libOpenDAAP
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+zlib - A Massively Spiffy Yet Delicately Unobtrusive Compression Library
+<http://www.zlib.net/>
+
+    Copyright © 1995-2002 Jean-loup Gailly and Mark Adler.
+
+    This software is provided 'as-is', without any express or implied
+    warranty.  In no event will the authors be held liable for any damages
+    arising from the use of this software.
+
+    Permission is granted to anyone to use this software for any purpose,
+    including commercial applications, and to alter it and redistribute it
+    freely, subject to the following restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not
+       claim that you wrote the original software. If you use this software
+       in a product, an acknowledgment in the product documentation would be
+       appreciated but is not required.
+    2. Altered source versions must be plainly marked as such, and must not be
+       misrepresented as being the original software.
+    3. This notice may not be removed or altered from any source distribution.
+
+iso9660.h
+
+    Copyright © The Joker / Avalaunch team
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Neptune Portable C++ Runtime Library
+<http://neptune.sourceforge.net/>
+
+    Copyright © 2001-2006 Gilles Boccon-Gibod
+    Copyright © 2002-2008, Axiomatic Systems, LLC.
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+        * Redistributions of source code must retain the above copyright
+          notice, this list of conditions and the following disclaimer.
+        * Redistributions in binary form must reproduce the above copyright
+          notice, this list of conditions and the following disclaimer in the
+          documentation and/or other materials provided with the distribution.
+        * Neither the name of the <organization> nor the
+          names of its contributors may be used to endorse or promote products
+          derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+MMST implementation taken from the xine-mms plugin made by Major MMS
+(http://geocities.com/majormms/).
+
+    Copyright © 2005-2008 Team Kodi
+    Copyright © 2002 Abhijeet Phatak <abhijeetphatak at yahoo.com>
+    Copyright © 2002 the xine project
+    Copyright © 2000-2001 major mms
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Ogg Bitstream Library
+<http://www.xiph.org/>
+
+    Copyright © 1994-2002 Xiph.Org Foundation http://www.xiph.org/
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+
+       * Redistributions of source code must retain the above copyright notice,
+         this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the Xiph.org Foundation nor the names of its
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+    This software is provided by the copyright holders and contributors “as is”
+    and any express or implied warranties, including, but not limited to, the
+    implied warranties of merchantability and fitness for a particular purpose
+    are disclaimed. In no event shall the foundation or contributors be liable
+    for any direct, indirect, incidental, special, exemplary, or consequential
+    damages (including, but not limited to, procurement of substitute goods or
+    services; loss of use, data, or profits; or business interruption) however
+    caused and on any theory of liability, whether in contract, strict
+    liability, or tort (including negligence or otherwise) arising in any way
+    out of the use of this software, even if advised of the possibility of such
+    damage.
+
+The Vorbis General Audio Compression Codec
+<http://www.xiph.org/>
+
+    Copyright © 2002, Xiph.org Foundation
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+
+       * Redistributions of source code must retain the above copyright notice,
+         this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+       * Neither the name of the Xiph.org Foundation nor the names of its
+         contributors may be used to endorse or promote products derived from
+         this software without specific prior written permission.
+
+    This software is provided by the copyright holders and contributors “as is”
+    and any express or implied warranties, including, but not limited to, the
+    implied warranties of merchantability and fitness for a particular purpose
+    are disclaimed. In no event shall the foundation or contributors be liable
+    for any direct, indirect, incidental, special, exemplary, or consequential
+    damages (including, but not limited to, procurement of substitute goods or
+    services; loss of use, data, or profits; or business interruption) however
+    caused and on any theory of liability, whether in contract, strict
+    liability, or tort (including negligence or otherwise) arising in any way
+    out of the use of this software, even if advised of the possibility of such
+    damage.
+
+LAME Ain't an Mp3 Encoder
+<http://lame.sourceforge.net/>
+
+    Copyright © 1999 Mark Taylor
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+GNU libmicrohttpd
+<http://www.gnu.org/software/libmicrohttpd/>
+
+    (C) 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing
+    authors)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+libmodplug
+<http://modplug-xmms.sourceforge.net>
+
+    Copyright 2002-2003 Kenton Varda <temporal at gauge3d.org>,
+                        Olivier Lapicque <olivierl at jps.net>,
+                        Colin DeVilbiss <crdevilb at mtu.edu>,
+                        Markus Fick <marf at gmx.net>,
+                        Adam Goode <adam at evdebs.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Python Programming Language
+<http://www.python.org/>
+
+    Copyright © 2001-2008 Python Software Foundation. All rights reserved.
+    Copyright © 2000 BeOpen.com. All rights reserved.
+    Copyright © 1995-2001 Corporation for National Research Initiatives. All
+        rights reserved.
+    Copyright © 1991-1995 Stichting Mathematisch Centrum. All rights reserved.
+
+    Python is distributed under the Python Software Foundation License
+    version 2. A copy of the license may be retrieved from
+    http://www.python.org/psf/license/ and is repeated below under the section
+    "License: PSF License for Python 2.4".
+
+libopendaap - library which enables applications to discover, and connect to,
+iTunes music shares.
+<http://craz.net/programs/itunes/libopendaap.html>
+
+    Copyright © 2004 David Hammerton.
+
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to
+    deal in the Software without restriction, including without limitation the
+    rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+    sell copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+    IN THE SOFTWARE.
+
+libsamplerate - audio rate conversion library
+<http://www.mega-nerd.com/SRC/>
+
+    Copyright © 2002-2008 Erik de Castro Lopo <erikd at mega-nerd.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+MediaMVP Media Center
+<http://www.mvpmc.org/>
+
+    Copyright © 2004-2006, Eric Lund, Jon Gettler, Sergio Slobodrian
+        http://www.mvpmc.org/
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+MySQL
+<http://www.mysql.com/>
+
+    Copyright © 2000-2003 MySQL AB
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+libid3tag - ID3 tag manipulation library
+<http://www.underbit.com/products/mad/>
+
+    Copyright © 2000-2004 Underbit Technologies, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Simple DirectMedia Layer
+<http://www.libsdl.org/>
+
+    Copyright © 1997-2006 Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+libfribidi - Free Implementation of the Unicode BiDi algorithm
+<http://www.fribidi.org/>
+
+    Copyright © 1999,2000 Dov Grobgeld
+    Copyright © 2001,2002 Behdad Esfahbod
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+CDRip - library that provides methods for extracting data from audio CDs
+<http://libcdrip.sourceforge.net/>
+
+    Copyright © 1999 - 2002 Albert L. Faber
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Platinum - UPnP library
+<http://www.plutinosoft.com/>
+
+    Copyright © 2004-2008, Plutinosoft, LLC. All rights reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+SQLite - library that implements a self-contained, serverless,
+zero-configuration, transactional SQL database engine.
+<http://www.sqlite.org/>
+
+    Copyright © 2004, Leo Seib, Hannover
+
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to
+    deal in the Software without restriction, including without limitation the
+    rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+    sell copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+    IN THE SOFTWARE.
+
+CxImage - C++ image processing and conversion library
+<http://www.xdp.it/cximage.htm>
+
+    Copyright © 2001 - 2008, Davide Pizzolato
+
+    Original CImage and CImageIterator implementation are:
+    Copyright © 1995, Alejandro Aguilar Sierra
+        (asierra(at)servidor(dot)unam(dot)mx)
+
+    Covered code is provided under this license on an "as is" basis, without
+    warranty of any kind, either expressed or implied, including, without
+    limitation, warranties that the covered code is free of defects,
+    merchantable, fit for a particular purpose or non-infringing. The entire
+    risk as to the quality and performance of the covered code is with you.
+    Should any covered code prove defective in any respect, you (not the initial
+    developer or any other contributor) assume the cost of any necessary
+    servicing, repair or correction. This disclaimer of warranty constitutes an
+    essential part of this license. No use of any covered code is authorized
+    hereunder except under this disclaimer.
+
+    Permission is hereby granted to use, copy, modify, and distribute this
+    source code, or portions hereof, for any purpose, including commercial
+    applications, freely and without fee, subject to the following restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not
+    claim that you wrote the original software. If you use this software
+    in a product, an acknowledgment in the product documentation would be
+    appreciated but is not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+    misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+
+    Portions of CxImage are under different copyright and under different
+    licenses.
+
+    JasPer
+    Copyright © 2001-2006 Michael David Adams
+    Copyright © 1999-2000 Image Power, Inc.
+    Copyright © 1999-2000 The University of British Columbia
+    All Rights Reserved.
+
+    Permission is hereby granted, free of charge, to any person (the
+    "User") obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without restriction,
+    including without limitation the rights to use, copy, modify, merge,
+    publish, distribute, and/or sell copies of the Software, and to permit
+    persons to whom the Software is furnished to do so, subject to the
+    following conditions:
+
+    1.  The above copyright notices and this permission notice (which
+    includes the disclaimer below) shall be included in all copies or
+    substantial portions of the Software.
+
+    2.  The name of a copyright holder shall not be used to endorse or
+    promote products derived from the Software without specific prior
+    written permission.
+
+    THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
+    LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+    THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
+    "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+    BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+    PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO
+    EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+    INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+    FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+    NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+    WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE
+    PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
+    THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
+    EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
+    BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
+    PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS
+    GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
+    ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE
+    IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
+    SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
+    AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
+    SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
+    THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
+    PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
+    RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
+    EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
+
+    JBIG
+    Copyright © Markus Kuhn -- http://www.cl.cam.ac.uk/~mgk25/
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+    MNG
+    Copyright © 2000-2007 Gerard Juyn (gerard at libmng.com)
+
+    For the purposes of this copyright and license, "Contributing Authors"
+    is defined as the following set of individuals:
+
+       Gerard Juyn
+       Glenn Randers-Pehrson
+
+    The MNG Library is supplied "AS IS".  The Contributing Authors
+    disclaim all warranties, expressed or implied, including, without
+    limitation, the warranties of merchantability and of fitness for any
+    purpose.  The Contributing Authors assume no liability for direct,
+    indirect, incidental, special, exemplary, or consequential damages,
+    which may result from the use of the MNG Library, even if advised of
+    the possibility of such damage.
+
+    Permission is hereby granted to use, copy, modify, and distribute this
+    source code, or portions hereof, for any purpose, without fee, subject
+    to the following restrictions:
+
+    1. The origin of this source code must not be misrepresented;
+       you must not claim that you wrote the original software.
+
+    2. Altered versions must be plainly marked as such and must not be
+       misrepresented as being the original source.
+
+    3. This Copyright notice may not be removed or altered from any source
+       or altered source distribution.
+
+    The Contributing Authors specifically permit, without fee, and
+    encourage the use of this source code as a component to supporting
+    MNG and JNG file format in commercial products.  If you use this
+    source code in a product, acknowledgment would be highly appreciated.
+
+    JPEG
+    Copyright © 1994-1998, Thomas G. Lane.
+
+    JPEG code is under the Independent JPEG Group License which can be found at
+    http://dev.w3.org/cvsweb/Amaya/libjpeg/Attic/README?rev=1.2 and is repeated
+    under the section "License: IJG License".
+
+    TIFF
+    Copyright © 1988-1997 Sam Leffler
+    Copyright © 1991-1997 Silicon Graphics, Inc.
+
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to
+    deal in the Software without restriction, including without limitation the
+    rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+    sell copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+    IN THE SOFTWARE.
+
+    PNG
+    Copyright © 1998, 1999 Glenn Randers-Pehrson
+
+    This software is provided 'as-is', without any express or implied
+    warranty.  In no event will the authors be held liable for any damages
+    arising from the use of this software.
+
+    Permission is granted to anyone to use this software for any purpose,
+    including commercial applications, and to alter it and redistribute it
+    freely, subject to the following restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not
+       claim that you wrote the original software. If you use this software
+       in a product, an acknowledgment in the product documentation would be
+       appreciated but is not required.
+    2. Altered source versions must be plainly marked as such, and must not be
+       misrepresented as being the original software.
+    3. This notice may not be removed or altered from any source distribution.
+
+    Dave Coffin's raw photo decoder
+    Copyright © 1997-2009 by Dave Coffin, dcoffin a cybercom o net
+
+    Covered code is provided under this license on an "as is" basis, without
+    warranty of any kind, either expressed or implied, including, without
+    limitation, warranties that the covered code is free of defects,
+    merchantable, fit for a particular purpose or non-infringing. The entire
+    risk as to the quality and performance of the covered code is with you.
+    Should any covered code prove defective in any respect, you (not the initial
+    developer or any other contributor) assume the cost of any necessary
+    servicing, repair or correction. This disclaimer of warranty constitutes an
+    essential part of this license. No use of any covered code is authorized
+    hereunder except under this disclaimer.
+
+    No license is required to download and use libdcr.  However,
+    to lawfully redistribute libdcr, you must either (a) offer, at
+    no extra charge, full source code for all executable files
+    containing RESTRICTED functions, (b) distribute this code under
+    the GPL Version 2 or later, (c) remove all RESTRICTED functions,
+    re-implement them, or copy them from an earlier, unrestricted
+    revision of dcraw.c, or (d) purchase a license from the author
+    of dcraw.c.
+
+PortAudio - portable cross-platform Audio API
+<http://www.portaudio.com/>
+
+    Copyright © 1999-2002 Ross Bencina and Phil Burk
+
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to
+    deal in the Software without restriction, including without limitation the
+    rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+    sell copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+    IN THE SOFTWARE.
+
+Audioscrobbler - The Social Music Technology Playground
+<http://www.audioscrobbler.net/>
+
+    Copyright © 2003 Russell Garrett (russ-scrobbler at garrett.co.uk)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Samba - Opening Windows to a Wider World
+<http://www.samba.org/>
+
+    Copyright © Andrew Tridgell 1998
+    Copyright © Richard Sharpe 2000
+    Copyright © John Terpsra 2000
+    Copyright © Tom Jansen (Ninja ISD) 2002
+    Copyright © Derrell Lipman 2003
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+PCRE - Perl Compatible Regular Expressions
+<http://www.pcre.org/>
+
+    Copyright © 1997-2007 University of Cambridge
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+
+        * Redistributions of source code must retain the above copyright notice,
+          this list of conditions and the following disclaimer.
+
+        * Redistributions in binary form must reproduce the above copyright
+          notice, this list of conditions and the following disclaimer in the
+          documentation and/or other materials provided with the distribution.
+
+        * Neither the name of the University of Cambridge nor the names of its
+          contributors may be used to endorse or promote products derived from
+          this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+    POSSIBILITY OF SUCH DAMAGE.
+
+HDHomeRun - Networked Digital Tuner
+<http://www.silicondust.com/>
+
+    Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 3 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library.  If not, see
+    <http://www.gnu.org/licenses/>.
+
+    As a special exception to the GNU Lesser General Public License,
+    you may link, statically or dynamically, an application with a
+    publicly distributed version of the Library to produce an
+    executable file containing portions of the Library, and
+    distribute that executable file under terms of your choice,
+    without any of the additional requirements listed in clause 4 of
+    the GNU Lesser General Public License.
+
+    By "a publicly distributed version of the Library", we mean
+    either the unmodified Library as distributed by Silicondust, or a
+    modified version of the Library that is distributed under the
+    conditions defined in the GNU Lesser General Public License.
+
+LibASS - portable library for SSA/ASS subtitles rendering
+<http://sourceforge.net/projects/libass/>
+
+    Copyright © 2006 Evgeniy Stepanov <eugeni.stepanov at gmail.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+libRTV - ReplayTV library
+
+    Copyright © 2002 John Todd Larason <jtl at molehill.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+libiconv - iconv() implementation
+<http://www.gnu.org/software/libiconv/>
+
+    Copyright © 1999-2003 Free Software Foundation, Inc.
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Boost C++ Libraries
+<http://www.boost.org/>
+
+    Copyright © 2001, 2002 Peter Dimov and Multi Media Ltd.
+    Copyright © 2007 Peter Dimov
+
+    Permission is hereby granted, free of charge, to any person or organization
+    obtaining a copy of the software and accompanying documentation covered by
+    this license (the "Software") to use, reproduce, display, distribute,
+    execute, and transmit the Software, and to prepare derivative works of the
+    Software, and to permit third-parties to whom the Software is furnished to
+    do so, all subject to the following:
+
+    The copyright notices in the Software and this entire statement, including
+    the above license grant, this restriction and the following disclaimer,
+    must be included in all copies of the Software, in whole or in part, and
+    all derivative works of the Software, unless such copies or derivative
+    works are solely in the form of machine-executable object code generated by
+    a source language processor.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+    SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+    FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+    DEALINGS IN THE SOFTWARE.
+
+HTS Tvheadend - Combined DVB receiver, Digital Video Recorder and Showtime
+streaming server for Linux.
+<http://www.lonelycoder.com/hts/>
+
+    Copyright © 2008 Andreas Öman
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+GNU Compact Disc Input and Control Library
+<http://www.gnu.org/software/libcdio/index.html>
+
+    Copyright © 2001 Herbert Valerio Riedel <hvr at gnu.org>
+    Copyright © 2003, 2004, 2005 Rocky Bernstein <rocky at panix.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+SNESAPU - SNES APU emulator library
+<http://www.alpha-ii.com/>
+
+    Copyright © 2001-2006 Alpha-II
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Musepack Decoder Library
+<http://www.musepack.net/>
+
+    Copyright © 2005, The Musepack Development Team. All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are
+    met:
+
+        * Redistributions of source code must retain the above copyrig
+          notice, this list of conditions and the following disclaimer.
+
+        * Redistributions in binary form must reproduce the above
+          copyright notice, this list of conditions and the following
+          disclaimer in the documentation and/or other materials provided
+          with the distribution.
+
+        * Neither the name of the The Musepack Development Team nor the
+          names of its contributors may be used to endorse or promote
+          products derived from this software without specific prior
+          written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+FLAC - Free Lossless Audio Codec
+
+    Copyright © 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Gens APU from Gens
+<http://info.sonicretro.org/Gens/GS>
+
+    Copyright © 2002 by Stéphane Dallongeville
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+vgmstream - library for playback of various video game audio formats
+<http://vgmstream.sourceforge.net/>
+
+    Copyright © 2008-2009 Adam Gashlin, Fastelbja, Ronny Elfert
+
+    Permission to use, copy, modify, and/or distribute this software for any
+    purpose with or without fee is hereby granted, provided that the above
+    copyright notice and this permission notice appear in all copies.
+
+    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+    SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+    OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+    CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+nosefart - NES sound format player
+<http://nosefart.sourceforge.net/>
+
+    Copyright © 1998-2000 Matthew Conte (matt at conte.com)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+MAD - MPEG Audio Decoder
+<http://www.underbit.com/products/mad/>
+
+    Copyright © 2000-2004 Underbit Technologies, Inc
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+SID Player Music Library V2
+<http://sidplay2.sourceforge.net/>
+
+    Copyright © Michael Schwendt <mschwendt at yahoo.com>
+    Copyright © 2000 by Simon White
+    Copyright © 2001-2002 by Jarno Paananen
+    Copyright © 2004  Dag Lem <resid at nimrod.no>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Xbox ADPCM audio codec
+<http://www.winamp.com/plugins/details/147392>
+
+    Copyright © Luigi Auriemma
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+ST-Sound - general "Nostalgic" Computer Sound Emulator
+<http://leonard.oxg.free.fr>
+
+    Copyright © 1995-1999 Arnaud Carré ( http://leonard.oxg.free.fr )
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+TiMidity++ - software synthesizer
+<http://timidity.sourceforge.net/>
+
+    Copyright © 1999-2002 Masanao Izumo <mo at goice.co.jp>
+    Copyright © 1995 Tuukka Toivonen <tt at cgs.fi>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+FFmpeg - complete, cross-platform solution to record, convert and stream audio
+and video
+<http://www.ffmpeg.org/>
+
+    Copyright © Fabrice Bellard
+    Copyright © Alex Beregszaszi
+    Copyright © BERO
+    Copyright © Mario Brito
+    Copyright © Ronald Bultje
+    Copyright © Tim Ferguson
+    Copyright © Brian Foley
+    Copyright © Arpad Gereoffy
+    Copyright © Philip Gladstone
+    Copyright © Vladimir Gneushev
+    Copyright © Wolfgang Hesseler
+    Copyright © Falk Hueffner
+    Copyright © Zdenek Kabelac
+    Copyright © Robin Kay
+    Copyright © Todd Kirby
+    Copyright © Nick Kurshev
+    Copyright © Mike Melanson
+    Copyright © Michael Niedermayer
+    Copyright © François Revol
+    Copyright © Roman Shaposhnik
+    Copyright © Dieter Shirley
+    Copyright © Juan J. Sierralta
+    Copyright © Ewald Snel
+    Copyright © Leon van Stuivenberg
+    Copyright © Roberto Togni
+    Copyright © Lionel Ulmer
+
+    Falls under two licenses, the LGPL-2.1 and GPL-2.
+
+    LGPL-2.1
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+    GPL-2
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+nuttcp - TCP/UDP network testing tool
+<http://www.lcp.nrl.navy.mil/nuttcp/>
+
+    Copyright © 1995-1999 WIDE Project.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+    1. Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+    3. Neither the name of the project nor the names of its contributors
+       may be used to endorse or promote products derived from this software
+       without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+
+libdvdnav and libdvdread - libraries to read DVDs and navigate DVD menus
+<http://www.mplayerhq.hu/>
+
+    Copyright © 2001-2004 Rich Wareham <richwareham at users.sourceforge.net>
+    Copyright © 2000, 2001, 2002 H�kan Hjort <d95hjort at dtek.chalmers.se>
+    Copyright © 1998, 1999 Eric Smith <eric at brouhaha.com>
+    Copyright © 2001, 2002 Billy Biggs <vektor at dumbterm.net>
+    Copyright © 2000, 2001 Martin Norb�ck
+    Copyright © 2000, 2001 Bj�rn Englund
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+libdca - free library for decoding DTS Coherent Acoustics streams
+<http://www.videolan.org/developers/libdca.html>
+
+    Copyright © 2004 Gildas Bazin <gbazin at videolan.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+libspucc - library that's part of the Xine project
+<http://www.xine-project.org/home>
+
+    Copyright © 2000-2008 the xine project
+    Copyright © Christian Vogler cvogler at gradient.cis.upenn.edu - December 2001
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+libmpeg2 - a free MPEG-2 video stream decoder
+<http://libmpeg2.sourceforge.net/>
+
+    Copyright © 2000-2004 Michel Lespinasse <walken at zoy.org>
+    Copyright © 1999-2000 Aaron Holtzman <aholtzma at ess.engr.uvic.ca>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+libdvdcss - library designed for accessing encrypted DVDs
+<http://www.videolan.org/developers/libdvdcss.html>
+
+    Copyright © 1999-2001 VideoLAN
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Sample frequency change classes
+
+    Copyright © Spoon (www.dbpoweramp.com) March 2002 dbpoweramp at dbpoweramp.com
+
+    The code is based on original SSRC by Naoki Shibata
+    <http://shibatch.sourceforge.net/
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Kodi-xrandr.c
+
+    Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
+    Copyright © 2002 Hewlett Packard Company, Inc.
+    Copyright © 2006 Intel Corporation
+
+    Permission to use, copy, modify, distribute, and sell this software and its
+    documentation for any purpose is hereby granted without fee, provided that
+    the above copyright notice appear in all copies and that both that copyright
+    notice and this permission notice appear in supporting documentation, and
+    that the name of the copyright holders not be used in advertising or
+    publicity pertaining to distribution of the software without specific,
+    written prior permission.  The copyright holders make no representations
+    about the suitability of this software for any purpose.  It is provided "as
+    is" without express or implied warranty.
+
+    THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+    INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+    EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+    CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+    DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+    TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+    OF THIS SOFTWARE.
+
+Kodi/Crc32.cpp and Kodi/Crc32.h
+
+    Copyright (C) 2005-2009 Team Kodi
+    http://kodi.tv
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+    Portion of this code was taken from efone.
+    efone - Distributed internet phone system.
+
+    (c) 1999,2000 Krzysztof Dabrowski
+    (c) 1999,2000 ElysiuM deeZine
+
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License
+    as published by the Free Software Foundation; either version
+    2 of the License, or (at your option) any later version.
+
+    based on implementation by Finn Yannick Jacobs
+
+guilib/AnimatedGif.cpp and guilib/AnimatedGif.h
+
+    Copyright (c) 2000, Juan Soulie <jsoulie at cplusplus.com>
+
+    Permission to use, copy, modify, distribute and sell this software or any
+    part thereof and/or its documentation for any purpose is granted without fee
+    provided that the above copyright notice and this permission notice appear
+    in all copies.
+
+    This software is provided "as is" without express or implied warranty of
+    any kind. The author shall have no liability with respect to the
+    infringement of copyrights or patents that any modification to the content
+    of this file or this file itself may incur.
+
+json-cpp - lightweight data-interchange format
+<http://jsoncpp.sourceforge.net/>
+
+    Author is Baptiste Lepilleur <blep at users.sourceforge.net>
+
+    The json-cpp library and this documentation are in Public Domain.
+
+Crystal HD
+<http://www.broadcom.com/support/crystal_hd/>
+
+    Copyright(c) 2006-2009 Broadcom Corporation.
+
+    The Crystal HD library is free software: you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public License as
+    published by the Free Software Foundation, version 2.1 of the License.
+
+    The Crystal HD library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+    You should have received a copy of the GNU Lesser General Public License
+    along with this header.  If not, see <http://www.gnu.org/licenses/>.
+
+    The Crystal HD driver is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, version 2 of the License.
+
+    The Crystal HD driver is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this driver.  If not, see <http://www.gnu.org/licenses/>.
+
+OpenSSH
+<http://www.openssh.org/>
+
+    Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
+    All rights reserved.
+
+    See the section 'License: OpenSSH' for full license terms.
+
+Enca - Extremely Naive Charset Analyser
+<http://freshmeat.net/projects/enca/>
+
+    Copyright (C) 2000-2003 David Necas (Yeti) <yeti at physics.muni.cz>
+    Copyright (C) 2009 Michal Cihar <michal at cihar.com>
+
+    This program is free software; you can redistribute it and/or modify it
+    under the terms of version 2 of the GNU General Public License as published
+    by the Free Software Foundation.
+
+    This program is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+C-Pluff - a plug-in framework for C
+<http://www.c-pluff.org/>
+
+    Copyright 2007 Johannes Lehtinen
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and associated documentation files (the "Software"),
+    to deal in the Software without restriction, including without limitation
+    the rights to use, copy, modify, merge, publish, distribute, sublicense,
+    and/or sell copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included
+    in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    C-Pluff uses data structure implementations from Kazlib library.
+
+    KazLib copyright and license
+    ----------------------------
+
+    Hash Table Data Type
+    List Abstract Data Type
+    Copyright (C) 1997 Kaz Kylheku <kaz at ashi.footprints.net>
+
+    Free Software License:
+
+    All rights are reserved by the author, with the following exceptions:
+    Permission is granted to freely reproduce and distribute this software,
+    possibly in exchange for a fee, provided that this copyright notice appears
+    intact. Permission is also granted to adapt this software to produce
+    derivative works, as long as the modified versions carry this copyright
+    notice and additional notices stating that the work has been modified.
+    This source code may be translated into executable form and incorporated
+    into proprietary software; there is no requirement for such software to
+    contain a copyright notice related to this source.
+
+J2ME Event Client
+
+    Copyright (c) 2008 topfs2
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+OSXRemote Client
+
+    Created by Stephan Diederich.
+    Copyright 2008 University Heidelberg. All rights reserved.
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+HIDRemote Classes used by OSXRemote Client
+
+    Copyright (c) 2007-2009 IOSPIRIT GmbH (http://www.iospirit.com/)
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+
+    * Neither the name of IOSPIRIT GmbH nor the names of its contributors may be
+      used to endorse or promote products derived from this software without
+      specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+    POSSIBILITY OF SUCH DAMAGE.
+
+Implementation of POSIX directory browsing functions and types for Win32.
+
+    Copyright Kevlin Henney, 1997, 2003. All rights reserved.
+
+    Permission to use, copy, modify, and distribute this software and its
+    documentation for any purpose is hereby granted without fee, provided
+    that this copyright and permissions notice appear in all copies and
+    derivatives.
+
+    This software is supplied "as is" without express or implied warranty.
+
+    But that said, if there are any problems please get in touch.
+
+Bitstream Vera Fonts
+
+    Copyright (C) 2003 Bitstream, Inc.
+    All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc.
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of the fonts accompanying this license ("Fonts") and associated
+    documentation files (the "Font Software"), to reproduce and distribute
+    the Font Software, including without limitation the rights to use, copy,
+    merge, publish, distribute, and/or sell copies of the Font Software, and
+    to permit persons to whom the Font Software is furnished to do so,
+    subject to the following conditions:
+
+    The above copyright and trademark notices and this permission notice
+    shall be included in all copies of one or more of the Font Software
+    typefaces.
+
+    The Font Software may be modified, altered, or added to, and in
+    particular the designs of glyphs or characters in the Fonts may be
+    modified and additional glyphs or characters may be added to the Fonts,
+    only if the fonts are renamed to names not containing either the words
+    "Bitstream" or the word "Vera".
+
+    This License becomes null and void to the extent applicable to Fonts or
+    Font Software that has been modified and is distributed under the
+    "Bitstream Vera" names.
+
+    The Font Software may be sold as part of a larger software package but
+    no copy of one or more of the Font Software typefaces may be sold by
+    itself.
+
+    THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
+    COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
+    BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR
+    OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL,
+    OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+    OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT
+    SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
+
+    Except as contained in this notice, the names of Gnome, the Gnome
+    Foundation, and Bitstream Inc., shall not be used in advertising or
+    otherwise to promote the sale, use or other dealings in this Font
+    Software without prior written authorization from the Gnome Foundation
+    or Bitstream Inc., respectively. For further information, contact:
+    <fonts at gnome.org>.
+
+DejaVu Fonts
+
+    Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
+    Glyphs imported from Arev fonts are (c) Tavmjung Bah (see below)
+    Bitstream Vera Fonts Copyright
+    ------------------------------
+    Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
+    a trademark of Bitstream, Inc.
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of the fonts accompanying this license ("Fonts") and associated
+    documentation files (the "Font Software"), to reproduce and distribute the
+    Font Software, including without limitation the rights to use, copy, merge,
+    publish, distribute, and/or sell copies of the Font Software, and to permit
+    persons to whom the Font Software is furnished to do so, subject to the
+    following conditions:
+    The above copyright and trademark notices and this permission notice shall
+    be included in all copies of one or more of the Font Software typefaces.
+    The Font Software may be modified, altered, or added to, and in particular
+    the designs of glyphs or characters in the Fonts may be modified and
+    additional glyphs or characters may be added to the Fonts, only if the fonts
+    are renamed to names not containing either the words "Bitstream" or the word
+    "Vera".
+    This License becomes null and void to the extent applicable to Fonts or Font
+    Software that has been modified and is distributed under the "Bitstream
+    Vera" names.
+    The Font Software may be sold as part of a larger software package but no
+    copy of one or more of the Font Software typefaces may be sold by itself.
+    THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
+    TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
+    FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
+    ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
+    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+    THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
+    FONT SOFTWARE.
+    Except as contained in this notice, the names of Gnome, the Gnome
+    Foundation, and Bitstream Inc., shall not be used in advertising or
+    otherwise to promote the sale, use or other dealings in this Font Software
+    without prior written authorization from the Gnome Foundation or Bitstream
+    Inc., respectively. For further information, contact: fonts at gnome dot
+    org.
+    Arev Fonts Copyright
+    ------------------------------
+    Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
+    Permission is hereby granted, free of charge, to any person obtaining
+    a copy of the fonts accompanying this license ("Fonts") and
+    associated documentation files (the "Font Software"), to reproduce
+    and distribute the modifications to the Bitstream Vera Font Software,
+    including without limitation the rights to use, copy, merge, publish,
+    distribute, and/or sell copies of the Font Software, and to permit
+    persons to whom the Font Software is furnished to do so, subject to
+    the following conditions:
+    The above copyright and trademark notices and this permission notice
+    shall be included in all copies of one or more of the Font Software
+    typefaces.
+    The Font Software may be modified, altered, or added to, and in
+    particular the designs of glyphs or characters in the Fonts may be
+    modified and additional glyphs or characters may be added to the
+    Fonts, only if the fonts are renamed to names not containing either
+    the words "Tavmjong Bah" or the word "Arev".
+    This License becomes null and void to the extent applicable to Fonts
+    or Font Software that has been modified and is distributed under the
+    "Tavmjong Bah Arev" names.
+    The Font Software may be sold as part of a larger software package but
+    no copy of one or more of the Font Software typefaces may be sold by
+    itself.
+    THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+    OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
+    TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+    INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+    DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+    OTHER DEALINGS IN THE FONT SOFTWARE.
+    Except as contained in this notice, the name of Tavmjong Bah shall not
+    be used in advertising or otherwise to promote the sale, use or other
+    dealings in this Font Software without prior written authorization
+    from Tavmjong Bah. For further information, contact: tavmjong @ free
+
+SlingboxLib - Library to communicate with Slingbox devices
+<http://www.stonyx.com>
+
+    Copyright (C) 2010-2011 Stonyx
+
+    This library is free software. You can redistribute it and/or modify it
+    under the terms of the GNU General Public License Version 2 (or at your
+    option any later version) as published by The Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+    General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+ASAP (Another Slight Atari Player)
+<http://asap.sourceforge.net>
+
+    Copyright (C) 2005-2009  Piotr Fusik
+
+    ASAP is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published
+    by the Free Software Foundation; either version 2 of the License,
+    or (at your option) any later version.
+
+    ASAP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty
+    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+    See the GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+CMyth - C library for communicating with MythTv server
+<http://www.mvpmc.org>
+
+    Copyright (C) 2004-2006, Eric Lund, Jon Gettler
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+libapetag - Library for manipulating APE tags.
+<http://src.gnu-darwin.org/ports/audio/easytag/work/easytag-2.1/src/libapetag/>
+
+    Copyright (c) 2002 Artur Polaczynski (Ar't)  All rights reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as
+    published by the Free Software Foundation; either version 2.1
+    of the License, or (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+libbluray - Blu-ray disc playback support library
+
+    Copyright (C) 2010, hpi1
+    Copyright (C) 2010, fraxinas
+    Copyright (C) 2010, John Stebbins
+    Copyright (C) 2010, Joakim
+    Copyright (C) 2010, Obliter0n
+    Copyright (C) 2010, William Hahne
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+libexif - library to parse EXIF files
+
+    Copyright (C) 2001-2009, Lutz Müller <urc8 at rz.uni-karlsruhe.de>
+    Copyright (C) 2004-2009, Jan Patera <patera at users.sourceforge.net>
+    Copyright (C) 2004, Joerg Hoh<joerg at devone.org>
+    Copyright (C) 2005-2006, Hubert Figuiere <hub at figuiere.net>
+    Copyright (C) 2002-2005, Hans Ulrich Niedermann <gp at n-dimensional.de>
+    Copyright (C) 2007-2010, Dan Fandrich <dan at coneharvesters.com>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+libnfs - NFS client library
+
+    Copyright (C) 2010-2011 Ronnie Sahlberg <ronniesahlberg at gmail.com>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+librtmp - toolkit for RTMP streams
+
+    Copyright (C) 2009 Andrej Stepanchuk
+    Copyright (C) 2009-2010 Howard Chu
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+libsquish - Open source DXT compression library
+
+    Copyright (C) 2006 Simon Brown <si at sjbrown.co.uk>
+
+    Permission is hereby granted, free of charge, to any person obtaining
+    a copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
+
+    The above copyright notice and this permission notice shall be included
+    in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+LZO Library - LZO real-time data compression library
+
+    Copyright (C) 1996-1997 Markus Franz Xaver Johannes Oberhumer
+
+    The LZO library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of
+    the License, or (at your option) any later version.
+
+    The LZO library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Licenses:
+
+License: GPL
+
+A copy of the GPL can be found on Debian systems at
+/usr/share/common-licenses/GPL.
+
+License: LGPL
+
+A copy of the LGPL can be found on Debian systems at
+/usr/share/common-licenses/LGPL.
+
+License: FTL
+                    The FreeType Project LICENSE
+                    ----------------------------
+
+                            2006-Jan-27
+
+                    Copyright 1996-2002, 2006 by
+          David Turner, Robert Wilhelm, and Werner Lemberg
+
+
+
+Introduction
+============
+
+  The FreeType  Project is distributed in  several archive packages;
+  some of them may contain, in addition to the FreeType font engine,
+  various tools and  contributions which rely on, or  relate to, the
+  FreeType Project.
+
+  This  license applies  to all  files found  in such  packages, and
+  which do not  fall under their own explicit  license.  The license
+  affects  thus  the  FreeType   font  engine,  the  test  programs,
+  documentation and makefiles, at the very least.
+
+  This  license   was  inspired  by  the  BSD,   Artistic,  and  IJG
+  (Independent JPEG  Group) licenses, which  all encourage inclusion
+  and  use of  free  software in  commercial  and freeware  products
+  alike.  As a consequence, its main points are that:
+
+    o We don't promise that this software works. However, we will be
+      interested in any kind of bug reports. (`as is' distribution)
+
+    o You can  use this software for whatever you  want, in parts or
+      full form, without having to pay us. (`royalty-free' usage)
+
+    o You may not pretend that  you wrote this software.  If you use
+      it, or  only parts of it,  in a program,  you must acknowledge
+      somewhere  in  your  documentation  that  you  have  used  the
+      FreeType code. (`credits')
+
+  We  specifically  permit  and  encourage  the  inclusion  of  this
+  software, with  or without modifications,  in commercial products.
+  We  disclaim  all warranties  covering  The  FreeType Project  and
+  assume no liability related to The FreeType Project.
+
+
+  Finally,  many  people  asked  us  for  a  preferred  form  for  a
+  credit/disclaimer to use in compliance with this license.  We thus
+  encourage you to use the following text:
+
+   """
+    Portions of this software are copyright © <year> The FreeType
+    Project (www.freetype.org).  All rights reserved.
+   """
+
+  Please replace <year> with the value from the FreeType version you
+  actually use.
+
+
+Legal Terms
+===========
+
+0. Definitions
+--------------
+
+  Throughout this license,  the terms `package', `FreeType Project',
+  and  `FreeType  archive' refer  to  the  set  of files  originally
+  distributed  by the  authors  (David Turner,  Robert Wilhelm,  and
+  Werner Lemberg) as the `FreeType Project', be they named as alpha,
+  beta or final release.
+
+  `You' refers to  the licensee, or person using  the project, where
+  `using' is a generic term including compiling the project's source
+  code as  well as linking it  to form a  `program' or `executable'.
+  This  program is  referred to  as  `a program  using the  FreeType
+  engine'.
+
+  This  license applies  to all  files distributed  in  the original
+  FreeType  Project,   including  all  source   code,  binaries  and
+  documentation,  unless  otherwise  stated   in  the  file  in  its
+  original, unmodified form as  distributed in the original archive.
+  If you are  unsure whether or not a particular  file is covered by
+  this license, you must contact us to verify this.
+
+  The FreeType  Project is copyright (C) 1996-2000  by David Turner,
+  Robert Wilhelm, and Werner Lemberg.  All rights reserved except as
+  specified below.
+
+1. No Warranty
+--------------
+
+  THE FREETYPE PROJECT  IS PROVIDED `AS IS' WITHOUT  WARRANTY OF ANY
+  KIND, EITHER  EXPRESS OR IMPLIED,  INCLUDING, BUT NOT  LIMITED TO,
+  WARRANTIES  OF  MERCHANTABILITY   AND  FITNESS  FOR  A  PARTICULAR
+  PURPOSE.  IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS
+  BE LIABLE  FOR ANY DAMAGES CAUSED  BY THE USE OR  THE INABILITY TO
+  USE, OF THE FREETYPE PROJECT.
+
+2. Redistribution
+-----------------
+
+  This  license  grants  a  worldwide, royalty-free,  perpetual  and
+  irrevocable right  and license to use,  execute, perform, compile,
+  display,  copy,   create  derivative  works   of,  distribute  and
+  sublicense the  FreeType Project (in  both source and  object code
+  forms)  and  derivative works  thereof  for  any  purpose; and  to
+  authorize others  to exercise  some or all  of the  rights granted
+  herein, subject to the following conditions:
+
+    o Redistribution of  source code  must retain this  license file
+      (`FTL.TXT') unaltered; any  additions, deletions or changes to
+      the original  files must be clearly  indicated in accompanying
+      documentation.   The  copyright   notices  of  the  unaltered,
+      original  files must  be  preserved in  all  copies of  source
+      files.
+
+    o Redistribution in binary form must provide a  disclaimer  that
+      states  that  the software is based in part of the work of the
+      FreeType Team,  in  the  distribution  documentation.  We also
+      encourage you to put an URL to the FreeType web page  in  your
+      documentation, though this isn't mandatory.
+
+  These conditions  apply to any  software derived from or  based on
+  the FreeType Project,  not just the unmodified files.   If you use
+  our work, you  must acknowledge us.  However, no  fee need be paid
+  to us.
+
+3. Advertising
+--------------
+
+  Neither the  FreeType authors and  contributors nor you  shall use
+  the name of the  other for commercial, advertising, or promotional
+  purposes without specific prior written permission.
+
+  We suggest,  but do not require, that  you use one or  more of the
+  following phrases to refer  to this software in your documentation
+  or advertising  materials: `FreeType Project',  `FreeType Engine',
+  `FreeType library', or `FreeType Distribution'.
+
+  As  you have  not signed  this license,  you are  not  required to
+  accept  it.   However,  as  the FreeType  Project  is  copyrighted
+  material, only  this license, or  another one contracted  with the
+  authors, grants you  the right to use, distribute,  and modify it.
+  Therefore,  by  using,  distributing,  or modifying  the  FreeType
+  Project, you indicate that you understand and accept all the terms
+  of this license.
+
+4. Contacts
+-----------
+
+  There are two mailing lists related to FreeType:
+
+    o freetype at nongnu.org
+
+      Discusses general use and applications of FreeType, as well as
+      future and  wanted additions to the  library and distribution.
+      If  you are looking  for support,  start in  this list  if you
+      haven't found anything to help you in the documentation.
+
+    o freetype-devel at nongnu.org
+
+      Discusses bugs,  as well  as engine internals,  design issues,
+      specific licenses, porting, etc.
+
+  Our home page can be found at
+
+    http://www.freetype.org
+
+
+--- end of FTL ---
+
+License: PSF License for Python 2.4
+
+A. HISTORY OF THE SOFTWARE
+==========================
+
+Python was created in the early 1990s by Guido van Rossum at Stichting
+Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
+as a successor of a language called ABC.  Guido remains Python's
+principal author, although it includes many contributions from others.
+
+In 1995, Guido continued his work on Python at the Corporation for
+National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
+in Reston, Virginia where he released several versions of the
+software.
+
+In May 2000, Guido and the Python core development team moved to
+BeOpen.com to form the BeOpen PythonLabs team.  In October of the same
+year, the PythonLabs team moved to Digital Creations (now Zope
+Corporation, see http://www.zope.com).  In 2001, the Python Software
+Foundation (PSF, see http://www.python.org/psf/) was formed, a
+non-profit organization created specifically to own Python-related
+Intellectual Property.  Zope Corporation is a sponsoring member of
+the PSF.
+
+All Python releases are Open Source (see http://www.opensource.org for
+the Open Source Definition).  Historically, most, but not all, Python
+releases have also been GPL-compatible; the table below summarizes
+the various releases.
+
+    Release         Derived     Year        Owner       GPL-
+                    from                                compatible? (1)
+
+    0.9.0 thru 1.2              1991-1995   CWI         yes
+    1.3 thru 1.5.2  1.2         1995-1999   CNRI        yes
+    1.6             1.5.2       2000        CNRI        no
+    2.0             1.6         2000        BeOpen.com  no
+    1.6.1           1.6         2001        CNRI        yes (2)
+    2.1             2.0+1.6.1   2001        PSF         no
+    2.0.1           2.0+1.6.1   2001        PSF         yes
+    2.1.1           2.1+2.0.1   2001        PSF         yes
+    2.2             2.1.1       2001        PSF         yes
+    2.1.2           2.1.1       2002        PSF         yes
+    2.1.3           2.1.2       2002        PSF         yes
+    2.2.1           2.2         2002        PSF         yes
+    2.2.2           2.2.1       2002        PSF         yes
+    2.2.3           2.2.2       2003        PSF         yes
+    2.3             2.2.2       2002-2003   PSF         yes
+    2.3.1           2.3         2002-2003   PSF         yes
+    2.3.2           2.3.1       2002-2003   PSF         yes
+    2.3.3           2.3.2       2002-2003   PSF         yes
+    2.3.4           2.3.3       2004        PSF         yes
+    2.3.5           2.3.4       2005        PSF         yes
+    2.4             2.3         2004        PSF         yes
+    2.4.1           2.4         2005        PSF         yes
+    2.4.2           2.4.1       2005        PSF         yes
+    2.4.3           2.4.2       2006        PSF         yes
+    2.4.4           2.4.3       2006        PSF         yes
+
+Footnotes:
+
+(1) GPL-compatible doesn't mean that we're distributing Python under
+    the GPL.  All Python licenses, unlike the GPL, let you distribute
+    a modified version without making your changes open source.  The
+    GPL-compatible licenses make it possible to combine Python with
+    other software that is released under the GPL; the others don't.
+
+(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
+    because its license has a choice of law clause.  According to
+    CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
+    is "not incompatible" with the GPL.
+
+Thanks to the many outside volunteers who have worked under Guido's
+direction to make these releases possible.
+
+
+B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
+===============================================================
+
+PSF LICENSE AGREEMENT FOR PYTHON 2.4
+------------------------------------
+
+1. This LICENSE AGREEMENT is between the Python Software Foundation
+("PSF"), and the Individual or Organization ("Licensee") accessing and
+otherwise using Python 2.4 software in source or binary form and its
+associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, PSF
+hereby grants Licensee a nonexclusive, royalty-free, world-wide
+license to reproduce, analyze, test, perform and/or display publicly,
+prepare derivative works, distribute, and otherwise use Python 2.4
+alone or in any derivative version, provided, however, that PSF's
+License Agreement and PSF's notice of copyright, i.e., "Copyright (c)
+2001, 2002, 2003, 2004 Python Software Foundation; All Rights Reserved"
+are retained in Python 2.4 alone or in any derivative version prepared
+by Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python 2.4 or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python 2.4.
+
+4. PSF is making Python 2.4 available to Licensee on an "AS IS"
+basis.  PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.4 WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+2.4 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.4,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any
+relationship of agency, partnership, or joint venture between PSF and
+Licensee.  This License Agreement does not grant permission to use PSF
+trademarks or trade name in a trademark sense to endorse or promote
+products or services of Licensee, or any third party.
+
+8. By copying, installing or otherwise using Python 2.4, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
+
+
+BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
+-------------------------------------------
+
+BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
+
+1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
+office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
+Individual or Organization ("Licensee") accessing and otherwise using
+this software in source or binary form and its associated
+documentation ("the Software").
+
+2. Subject to the terms and conditions of this BeOpen Python License
+Agreement, BeOpen hereby grants Licensee a non-exclusive,
+royalty-free, world-wide license to reproduce, analyze, test, perform
+and/or display publicly, prepare derivative works, distribute, and
+otherwise use the Software alone or in any derivative version,
+provided, however, that the BeOpen Python License is retained in the
+Software, alone or in any derivative version prepared by Licensee.
+
+3. BeOpen is making the Software available to Licensee on an "AS IS"
+basis.  BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
+SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
+AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
+DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+5. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+6. This License Agreement shall be governed by and interpreted in all
+respects by the law of the State of California, excluding conflict of
+law provisions.  Nothing in this License Agreement shall be deemed to
+create any relationship of agency, partnership, or joint venture
+between BeOpen and Licensee.  This License Agreement does not grant
+permission to use BeOpen trademarks or trade names in a trademark
+sense to endorse or promote products or services of Licensee, or any
+third party.  As an exception, the "BeOpen Python" logos available at
+http://www.pythonlabs.com/logos.html may be used according to the
+permissions granted on that web page.
+
+7. By copying, installing or otherwise using the software, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
+
+
+CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
+---------------------------------------
+
+1. This LICENSE AGREEMENT is between the Corporation for National
+Research Initiatives, having an office at 1895 Preston White Drive,
+Reston, VA 20191 ("CNRI"), and the Individual or Organization
+("Licensee") accessing and otherwise using Python 1.6.1 software in
+source or binary form and its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, CNRI
+hereby grants Licensee a nonexclusive, royalty-free, world-wide
+license to reproduce, analyze, test, perform and/or display publicly,
+prepare derivative works, distribute, and otherwise use Python 1.6.1
+alone or in any derivative version, provided, however, that CNRI's
+License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
+1995-2001 Corporation for National Research Initiatives; All Rights
+Reserved" are retained in Python 1.6.1 alone or in any derivative
+version prepared by Licensee.  Alternately, in lieu of CNRI's License
+Agreement, Licensee may substitute the following text (omitting the
+quotes): "Python 1.6.1 is made available subject to the terms and
+conditions in CNRI's License Agreement.  This Agreement together with
+Python 1.6.1 may be located on the Internet using the following
+unique, persistent identifier (known as a handle): 1895.22/1013.  This
+Agreement may also be obtained from a proxy server on the Internet
+using the following URL: http://hdl.handle.net/1895.22/1013".
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python 1.6.1 or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python 1.6.1.
+
+4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
+basis.  CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. This License Agreement shall be governed by the federal
+intellectual property law of the United States, including without
+limitation the federal copyright law, and, to the extent such
+U.S. federal law does not apply, by the law of the Commonwealth of
+Virginia, excluding Virginia's conflict of law provisions.
+Notwithstanding the foregoing, with regard to derivative works based
+on Python 1.6.1 that incorporate non-separable material that was
+previously distributed under the GNU General Public License (GPL), the
+law of the Commonwealth of Virginia shall govern this License
+Agreement only as to issues arising under or with respect to
+Paragraphs 4, 5, and 7 of this License Agreement.  Nothing in this
+License Agreement shall be deemed to create any relationship of
+agency, partnership, or joint venture between CNRI and Licensee.  This
+License Agreement does not grant permission to use CNRI trademarks or
+trade name in a trademark sense to endorse or promote products or
+services of Licensee, or any third party.
+
+8. By clicking on the "ACCEPT" button where indicated, or by copying,
+installing or otherwise using Python 1.6.1, Licensee agrees to be
+bound by the terms and conditions of this License Agreement.
+
+        ACCEPT
+
+
+CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
+--------------------------------------------------
+
+Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
+The Netherlands.  All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+-- End of PSF License for Python 2.4 --
+
+License: IJG License
+
+LEGAL ISSUES
+============
+
+In plain English:
+
+1. We don't promise that this software works.  (But if you find any bugs,
+   please let us know!)
+2. You can use this software for whatever you want.  You don't have to pay us.
+3. You may not pretend that you wrote this software.  If you use it in a
+   program, you must acknowledge somewhere in your documentation that
+   you've used the IJG code.
+
+In legalese:
+
+The authors make NO WARRANTY or representation, either express or implied,
+with respect to this software, its quality, accuracy, merchantability, or
+fitness for a particular purpose.  This software is provided "AS IS", and you,
+its user, assume the entire risk as to its quality and accuracy.
+
+This software is copyright (C) 1991-1998, Thomas G. Lane.
+All Rights Reserved except as specified below.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+software (or portions thereof) for any purpose, without fee, subject to these
+conditions:
+(1) If any part of the source code for this software is distributed, then this
+README file must be included, with this copyright and no-warranty notice
+unaltered; and any additions, deletions, or changes to the original files
+must be clearly indicated in accompanying documentation.
+(2) If only executable code is distributed, then the accompanying
+documentation must state that "this software is based in part on the work of
+the Independent JPEG Group".
+(3) Permission for use of this software is granted only if the user accepts
+full responsibility for any undesirable consequences; the authors accept
+NO LIABILITY for damages of any kind.
+
+These conditions apply to any software derived from or based on the IJG code,
+not just to the unmodified library.  If you use our work, you ought to
+acknowledge us.
+
+Permission is NOT granted for the use of any IJG author's name or company name
+in advertising or publicity relating to this software or products derived from
+it.  This software may be referred to only as "the Independent JPEG Group's
+software".
+
+We specifically permit and encourage the use of this software as the basis of
+commercial products, provided that all warranty or liability claims are
+assumed by the product vendor.
+
+
+ansi2knr.c is included in this distribution by permission of L. Peter Deutsch,
+sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA.
+ansi2knr.c is NOT covered by the above copyright and conditions, but instead
+by the usual distribution terms of the Free Software Foundation; principally,
+that you must include source code if you redistribute it.  (See the file
+ansi2knr.c for full details.)  However, since ansi2knr.c is not needed as part
+of any program generated from the IJG code, this does not limit you more than
+the foregoing paragraphs do.
+
+The Unix configuration script "configure" was produced with GNU Autoconf.
+It is copyright by the Free Software Foundation but is freely distributable.
+The same holds for its supporting scripts (config.guess, config.sub,
+ltconfig, ltmain.sh).  Another support script, install-sh, is copyright
+by M.I.T. but is also freely distributable.
+
+It appears that the arithmetic coding option of the JPEG spec is covered by
+patents owned by IBM, AT&T, and Mitsubishi.  Hence arithmetic coding cannot
+legally be used without obtaining one or more licenses.  For this reason,
+support for arithmetic coding has been removed from the free JPEG software.
+(Since arithmetic coding provides only a marginal gain over the unpatented
+Huffman mode, it is unlikely that very many implementations will support it.)
+So far as we are aware, there are no patent restrictions on the remaining
+code.
+
+The IJG distribution formerly included code to read and write GIF files.
+To avoid entanglement with the Unisys LZW patent, GIF reading support has
+been removed altogether, and the GIF writer has been simplified to produce
+"uncompressed GIFs".  This technique does not use the LZW algorithm; the
+resulting GIF files are larger than usual, but are readable by all standard
+GIF decoders.
+
+We are required to state that
+    "The Graphics Interchange Format(c) is the Copyright property of
+    CompuServe Incorporated.  GIF(sm) is a Service Mark property of
+    CompuServe Incorporated."
+
+-- End of IJG License --
+
+License: OpenSSH
+
+This file is part of the OpenSSH software.
+
+The licences which components of this software fall under are as
+follows.  First, we will summarize and say that all components
+are under a BSD licence, or a licence more free than that.
+
+OpenSSH contains no GPL code.
+
+1)
+     * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
+     *                    All rights reserved
+     *
+     * As far as I am concerned, the code I have written for this software
+     * can be used freely for any purpose.  Any derived versions of this
+     * software must be clearly marked as such, and if the derived work is
+     * incompatible with the protocol description in the RFC file, it must be
+     * called by a name other than "ssh" or "Secure Shell".
+
+    [Tatu continues]
+     *  However, I am not implying to give any licenses to any patents or
+     * copyrights held by third parties, and the software includes parts that
+     * are not under my direct control.  As far as I know, all included
+     * source code is used in accordance with the relevant license agreements
+     * and can be used freely for any purpose (the GNU license being the most
+     * restrictive); see below for details.
+
+    [However, none of that term is relevant at this point in time.  All of
+    these restrictively licenced software components which he talks about
+    have been removed from OpenSSH, i.e.,
+
+     - RSA is no longer included, found in the OpenSSL library
+     - IDEA is no longer included, its use is deprecated
+     - DES is now external, in the OpenSSL library
+     - GMP is no longer used, and instead we call BN code from OpenSSL
+     - Zlib is now external, in a library
+     - The make-ssh-known-hosts script is no longer included
+     - TSS has been removed
+     - MD5 is now external, in the OpenSSL library
+     - RC4 support has been replaced with ARC4 support from OpenSSL
+     - Blowfish is now external, in the OpenSSL library
+
+    [The licence continues]
+
+    Note that any information and cryptographic algorithms used in this
+    software are publicly available on the Internet and at any major
+    bookstore, scientific library, and patent office worldwide.  More
+    information can be found e.g. at "http://www.cs.hut.fi/crypto".
+
+    The legal status of this program is some combination of all these
+    permissions and restrictions.  Use only at your own responsibility.
+    You will be responsible for any legal consequences yourself; I am not
+    making any claims whether possessing or using this is legal or not in
+    your country, and I am not taking any responsibility on your behalf.
+
+
+          NO WARRANTY
+
+    BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+    FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+    OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+    PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+    OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+    TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+    PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+    REPAIR OR CORRECTION.
+
+    IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+    WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+    REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+    INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+    OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+    TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+    YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+    PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+    POSSIBILITY OF SUCH DAMAGES.
+
+2)
+    The 32-bit CRC compensation attack detector in deattack.c was
+    contributed by CORE SDI S.A. under a BSD-style license.
+
+     * Cryptographic attack detector for ssh - source code
+     *
+     * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
+     *
+     * All rights reserved. Redistribution and use in source and binary
+     * forms, with or without modification, are permitted provided that
+     * this copyright notice is retained.
+     *
+     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+     * WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE
+     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR
+     * CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS
+     * SOFTWARE.
+     *
+     * Ariel Futoransky <futo at core-sdi.com>
+     * <http://www.core-sdi.com>
+
+3)
+    ssh-keyscan was contributed by David Mazieres under a BSD-style
+    license.
+
+     * Copyright 1995, 1996 by David Mazieres <dm at lcs.mit.edu>.
+     *
+     * Modification and redistribution in source and binary forms is
+     * permitted provided that due credit is given to the author and the
+     * OpenBSD project by leaving this copyright notice intact.
+
+4)
+    The Rijndael implementation by Vincent Rijmen, Antoon Bosselaers
+    and Paulo Barreto is in the public domain and distributed
+    with the following license:
+
+     * @version 3.0 (December 2000)
+     *
+     * Optimised ANSI C code for the Rijndael cipher (now AES)
+     *
+     * @author Vincent Rijmen <vincent.rijmen at esat.kuleuven.ac.be>
+     * @author Antoon Bosselaers <antoon.bosselaers at esat.kuleuven.ac.be>
+     * @author Paulo Barreto <paulo.barreto at terra.com.br>
+     *
+     * This code is hereby placed in the public domain.
+     *
+     * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+     * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+     * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+     * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+5)
+    One component of the ssh source code is under a 3-clause BSD license,
+    held by the University of California, since we pulled these parts from
+    original Berkeley code.
+
+     * Copyright (c) 1983, 1990, 1992, 1993, 1995
+     *      The Regents of the University of California.  All rights reserved.
+     *
+     * Redistribution and use in source and binary forms, with or without
+     * modification, are permitted provided that the following conditions
+     * are met:
+     * 1. Redistributions of source code must retain the above copyright
+     *    notice, this list of conditions and the following disclaimer.
+     * 2. Redistributions in binary form must reproduce the above copyright
+     *    notice, this list of conditions and the following disclaimer in the
+     *    documentation and/or other materials provided with the distribution.
+     * 3. Neither the name of the University nor the names of its contributors
+     *    may be used to endorse or promote products derived from this software
+     *    without specific prior written permission.
+     *
+     * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+     * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+     * THE POSSIBILITY OF SUCH DAMAGE.
+
+6)
+    Remaining components of the software are provided under a standard
+    2-term BSD licence with the following names as copyright holders:
+
+  Markus Friedl
+  Theo de Raadt
+  Niels Provos
+  Dug Song
+  Aaron Campbell
+  Damien Miller
+  Kevin Steves
+  Daniel Kouril
+  Wesley Griffin
+  Per Allansson
+  Nils Nordman
+  Simon Wilkinson
+
+     * Redistribution and use in source and binary forms, with or without
+     * modification, are permitted provided that the following conditions
+     * are met:
+     * 1. Redistributions of source code must retain the above copyright
+     *    notice, this list of conditions and the following disclaimer.
+     * 2. Redistributions in binary form must reproduce the above copyright
+     *    notice, this list of conditions and the following disclaimer in the
+     *    documentation and/or other materials provided with the distribution.
+     *
+     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+     * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+     * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+     * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+     * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+     * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-- End of OpenSSH License --
diff --git a/project/cmake/cpack/deb/lintian/overrides/kodi b/project/cmake/cpack/deb/lintian/overrides/kodi
new file mode 100644
index 0000000..d9536c4
--- /dev/null
+++ b/project/cmake/cpack/deb/lintian/overrides/kodi
@@ -0,0 +1 @@
+kodi: description-starts-with-package-name
diff --git a/project/cmake/cpack/deb/menu/kodi b/project/cmake/cpack/deb/menu/kodi
new file mode 100644
index 0000000..0c221a4
--- /dev/null
+++ b/project/cmake/cpack/deb/menu/kodi
@@ -0,0 +1,2 @@
+?package(kodi):needs="X11" section="Applications/Video" \
+  title="kodi" command="/usr/bin/kodi"
diff --git a/project/cmake/cpack/deb/package-description.txt b/project/cmake/cpack/deb/package-description.txt
new file mode 100644
index 0000000..961e1c8
--- /dev/null
+++ b/project/cmake/cpack/deb/package-description.txt
@@ -0,0 +1,16 @@
+Kodi, formerly known as XBMC Media Center, is an award winning free and open
+source software media-player and entertainment hub for all your digital media.
+Kodi is available for Linux, Mac OS X (Leopard, Tiger and Apple TV) and
+Microsoft Windows, as well as the original Xbox game console. Created in 2003
+by a group of like minded programmers, Kodi is a non-profit project run and
+developed by volunteers located around the world. More than 50 software
+developers have contributed to Kodi, and 100-plus translators have worked to
+expand its reach, making it available in more than 30 languages.
+.
+While Kodi functions very well as a standard media player application for your
+computer, it has been designed to be the perfect companion for your HTPC.
+Supporting an almost endless range of remote controls, and combined with its
+beautiful interface and powerful skinning engine, Kodi feels very natural to
+use from the couch and is the ideal solution for your home theater. Once
+installed, your computer will become a fully functional multimedia jukebox.
+.
\ No newline at end of file
diff --git a/project/cmake/cpack/deb/packages/kodi-addon-dev.txt.in b/project/cmake/cpack/deb/packages/kodi-addon-dev.txt.in
new file mode 100644
index 0000000..aebae7e
--- /dev/null
+++ b/project/cmake/cpack/deb/packages/kodi-addon-dev.txt.in
@@ -0,0 +1,25 @@
+# kodi-addon-dev debian package metadata
+#
+# Setting PACKAGE_SHLIBDEPS to 'ON' will cause CPack to ignore PACKAGE_DEPENDS
+# content and use dpkg-shlibdeps to automatically generate the package dependency
+# list. Only useful for packages that contain binaries.
+#
+# PACKAGE_ARCHITECTURE should be set to 'all' only if package contains
+# architecture agnostic data. CPack will set proper architecture (amd64/i386/etc)
+# based on build options.
+#
+# Remaining settings are (hopefully) self-explanatory.
+
+PACKAGE_NAME @APP_NAME_LC at -addon-dev
+PACKAGE_ARCHITECTURE all
+PACKAGE_SECTION libdevel
+PACKAGE_PRIORITY optional
+PACKAGE_SHLIBDEPS
+PACKAGE_DEPENDS
+PACKAGE_RECOMMENDS @APP_NAME_LC at -audio-dev, @APP_NAME_LC at -inputstream-dev, @APP_NAME_LC at -pvr-dev, @APP_NAME_LC at -screensaver-dev, @APP_NAME_LC at -visualization-dev
+PACKAGE_SUGGESTS
+PACKAGE_BREAKS
+PACKAGE_REPLACES
+PACKAGE_PROVIDES xbmc-addon-dev
+PACKAGE_DESCRIPTION_HEADER @APP_NAME@ Media Center (general add-on dev package)
+PACKAGE_DESCRIPTION_FOOTER This is the development package for @APP_NAME@'s add-ons.
diff --git a/project/cmake/cpack/deb/packages/kodi-audio-dev.txt.in b/project/cmake/cpack/deb/packages/kodi-audio-dev.txt.in
new file mode 100644
index 0000000..f03a64d
--- /dev/null
+++ b/project/cmake/cpack/deb/packages/kodi-audio-dev.txt.in
@@ -0,0 +1,25 @@
+# kodi-audio-dev debian package metadata
+#
+# Setting PACKAGE_SHLIBDEPS to 'ON' will cause CPack to ignore PACKAGE_DEPENDS
+# content and use dpkg-shlibdeps to automatically generate the package dependency
+# list. Only useful for packages that contain binaries.
+#
+# PACKAGE_ARCHITECTURE should be set to 'all' only if package contains
+# architecture agnostic data. CPack will set proper architecture (amd64/i386/etc)
+# based on build options.
+#
+# Remaining settings are (hopefully) self-explanatory.
+
+PACKAGE_NAME @APP_NAME_LC at -audio-dev
+PACKAGE_ARCHITECTURE all
+PACKAGE_SECTION libdevel
+PACKAGE_PRIORITY optional
+PACKAGE_SHLIBDEPS
+PACKAGE_DEPENDS @APP_NAME_LC at -addon-dev
+PACKAGE_RECOMMENDS
+PACKAGE_SUGGESTS
+PACKAGE_BREAKS
+PACKAGE_REPLACES
+PACKAGE_PROVIDES xbmc-audio-dev
+PACKAGE_DESCRIPTION_HEADER @APP_NAME@ Media Center (audio add-ons dev package)
+PACKAGE_DESCRIPTION_FOOTER This is the development package for @APP_NAME@'s audio add-ons.
diff --git a/project/cmake/cpack/deb/packages/kodi-bin.txt.in b/project/cmake/cpack/deb/packages/kodi-bin.txt.in
new file mode 100644
index 0000000..8ee33d3
--- /dev/null
+++ b/project/cmake/cpack/deb/packages/kodi-bin.txt.in
@@ -0,0 +1,25 @@
+# kodi-bin debian package metadata
+#
+# Setting PACKAGE_SHLIBDEPS to 'ON' will cause CPack to ignore PACKAGE_DEPENDS
+# content and use dpkg-shlibdeps to automatically generate the package dependency
+# list. Only useful for packages that contain binaries.
+#
+# PACKAGE_ARCHITECTURE should be set to 'all' only if package contains
+# architecture agnostic data. CPack will set proper architecture (amd64/i386/etc)
+# based on build options.
+#
+# Remaining settings are (hopefully) self-explanatory.
+
+PACKAGE_NAME @APP_NAME_LC at -bin
+PACKAGE_ARCHITECTURE
+PACKAGE_SECTION video
+PACKAGE_PRIORITY optional
+PACKAGE_SHLIBDEPS
+PACKAGE_DEPENDS libasound2 (>= 1.0.27), libavahi-client3 (>= 0.6.16), libavahi-common3 (>= 0.6.16), libbluetooth3 (>= 4.91), libbz2-1.0, libc6 (>= 2.15), libcdio13 (>= 0.83), libcrossguid1, libdbus-1-3 (>= 1.9.14), libdrm2 (>= 2.4.16), libegl1-mesa (>= 7.8.1) | libegl1-x11, libexpat1 (>= 2.0.1), libfreetype6 (>= 2.2.1), libfribidi0 (>= 0.19.2), libgcc1 (>= 1:3.0), libgl1-mesa-glx | libgl1, libgnutls30 (>= 3.4.2), liblzma5 (>= 5.1.1alpha+20120614), liblzo2-2, libmicrohttpd10 (>= 0.9.20), libmysqlclient20 (>= 5.7.11), libpcre3, libpcrecpp0v5 (>= 7.7), libpulse0 (>= 0.99.4), libpython2.7 (>= 2.7), libsmbclient (>= 2:4.0.3+dfsg1), libsqlite3-0 (>= 3.6.11), libssh-4 (>= 0.6.1), libstdc++6 (>= 5.2), libtag1v5 (>= 1.9.1-2.4ubuntu1), libtinyxml2.6.2v5, libudev1 (>= 183), libva-x11-1 (>= 1.0.3), libva1 (>= 1.4.0), libx11-6, libxext6, libxml2 (>= 2.7.4), libxrandr2 (>= 2:1.2.99.3), libxslt1.1 (>= 1.1.25), libyajl2 (>= 2.0.4), zlib1g (>= 1:1.2.0.2)
+PACKAGE_RECOMMENDS
+PACKAGE_SUGGESTS
+PACKAGE_BREAKS xbmc-bin (<< 2:14.0~git20141019), xbmc-common
+PACKAGE_REPLACES xbmc-bin (<< 2:14.0~git20141019), xbmc-common
+PACKAGE_PROVIDES @APP_NAME_LC at -bin, @APP_NAME_LC at -common, xbmc-bin, xbmc-common
+PACKAGE_DESCRIPTION_HEADER @APP_NAME@ Media Center (binary data package)
+PACKAGE_DESCRIPTION_FOOTER This package contains @APP_NAME@'s binary data.
diff --git a/project/cmake/cpack/deb/packages/kodi-eventclients-common.txt.in b/project/cmake/cpack/deb/packages/kodi-eventclients-common.txt.in
new file mode 100644
index 0000000..6559842
--- /dev/null
+++ b/project/cmake/cpack/deb/packages/kodi-eventclients-common.txt.in
@@ -0,0 +1,25 @@
+# kodi-eventclients-common debian package metadata
+#
+# Setting PACKAGE_SHLIBDEPS to 'ON' will cause CPack to ignore PACKAGE_DEPENDS
+# content and use dpkg-shlibdeps to automatically generate the package dependency
+# list. Only useful for packages that contain binaries.
+#
+# PACKAGE_ARCHITECTURE should be set to 'all' only if package contains
+# architecture agnostic data. CPack will set proper architecture (amd64/i386/etc)
+# based on build options.
+#
+# Remaining settings are (hopefully) self-explanatory.
+
+PACKAGE_NAME @APP_NAME_LC at -eventclients-common
+PACKAGE_ARCHITECTURE all
+PACKAGE_SECTION video
+PACKAGE_PRIORITY optional
+PACKAGE_SHLIBDEPS
+PACKAGE_DEPENDS
+PACKAGE_RECOMMENDS
+PACKAGE_SUGGESTS
+PACKAGE_BREAKS
+PACKAGE_REPLACES
+PACKAGE_PROVIDES xbmc-eventclients-common
+PACKAGE_DESCRIPTION_HEADER @APP_NAME@ Media Center (event client common package)
+PACKAGE_DESCRIPTION_FOOTER This is the common package for @APP_NAME@'s event client.
diff --git a/project/cmake/cpack/deb/packages/kodi-eventclients-dev.txt.in b/project/cmake/cpack/deb/packages/kodi-eventclients-dev.txt.in
new file mode 100644
index 0000000..4b166b5
--- /dev/null
+++ b/project/cmake/cpack/deb/packages/kodi-eventclients-dev.txt.in
@@ -0,0 +1,25 @@
+# kodi-eventclients-dev debian package metadata
+#
+# Setting PACKAGE_SHLIBDEPS to 'ON' will cause CPack to ignore PACKAGE_DEPENDS
+# content and use dpkg-shlibdeps to automatically generate the package dependency
+# list. Only useful for packages that contain binaries.
+#
+# PACKAGE_ARCHITECTURE should be set to 'all' only if package contains
+# architecture agnostic data. CPack will set proper architecture (amd64/i386/etc)
+# based on build options.
+#
+# Remaining settings are (hopefully) self-explanatory.
+
+PACKAGE_NAME @APP_NAME_LC at -eventclients-dev
+PACKAGE_ARCHITECTURE all
+PACKAGE_SECTION libdevel
+PACKAGE_PRIORITY optional
+PACKAGE_SHLIBDEPS
+PACKAGE_DEPENDS @APP_NAME_LC at -eventclients-common (= @CPACK_DEBIAN_PACKAGE_VERSION@)
+PACKAGE_RECOMMENDS
+PACKAGE_SUGGESTS
+PACKAGE_BREAKS
+PACKAGE_REPLACES
+PACKAGE_PROVIDES xbmc-eventclients-dev
+PACKAGE_DESCRIPTION_HEADER @APP_NAME@ Media Center (event client dev package)
+PACKAGE_DESCRIPTION_FOOTER This is the development package for @APP_NAME@'s event client.
diff --git a/project/cmake/cpack/deb/packages/kodi-eventclients-ps3.txt.in b/project/cmake/cpack/deb/packages/kodi-eventclients-ps3.txt.in
new file mode 100644
index 0000000..bd432a2
--- /dev/null
+++ b/project/cmake/cpack/deb/packages/kodi-eventclients-ps3.txt.in
@@ -0,0 +1,25 @@
+# kodi-eventclients-ps3 debian package metadata
+#
+# Setting PACKAGE_SHLIBDEPS to 'ON' will cause CPack to ignore PACKAGE_DEPENDS
+# content and use dpkg-shlibdeps to automatically generate the package dependency
+# list. Only useful for packages that contain binaries.
+#
+# PACKAGE_ARCHITECTURE should be set to 'all' only if package contains
+# architecture agnostic data. CPack will set proper architecture (amd64/i386/etc)
+# based on build options.
+#
+# Remaining settings are (hopefully) self-explanatory.
+
+PACKAGE_NAME @APP_NAME_LC at -eventclients-ps3
+PACKAGE_ARCHITECTURE all
+PACKAGE_SECTION video
+PACKAGE_PRIORITY optional
+PACKAGE_SHLIBDEPS
+PACKAGE_DEPENDS @APP_NAME_LC at -eventclients-common (= @CPACK_DEBIAN_PACKAGE_VERSION@), python-bluez | python-lightblue
+PACKAGE_RECOMMENDS
+PACKAGE_SUGGESTS
+PACKAGE_BREAKS
+PACKAGE_REPLACES
+PACKAGE_PROVIDES xbmc-eventclients-ps3
+PACKAGE_DESCRIPTION_HEADER @APP_NAME@ Media Center (PS3 event client package)
+PACKAGE_DESCRIPTION_FOOTER This is the PS3 package for @APP_NAME@'s event client.
diff --git a/project/cmake/cpack/deb/packages/kodi-eventclients-wiiremote.txt.in b/project/cmake/cpack/deb/packages/kodi-eventclients-wiiremote.txt.in
new file mode 100644
index 0000000..5973784
--- /dev/null
+++ b/project/cmake/cpack/deb/packages/kodi-eventclients-wiiremote.txt.in
@@ -0,0 +1,25 @@
+# kodi-eventclients-wiiremote debian package metadata
+#
+# Setting PACKAGE_SHLIBDEPS to 'ON' will cause CPack to ignore PACKAGE_DEPENDS
+# content and use dpkg-shlibdeps to automatically generate the package dependency
+# list. Only useful for packages that contain binaries.
+#
+# PACKAGE_ARCHITECTURE should be set to 'all' only if package contains
+# architecture agnostic data. CPack will set proper architecture (amd64/i386/etc)
+# based on build options.
+#
+# Remaining settings are (hopefully) self-explanatory.
+
+PACKAGE_NAME @APP_NAME_LC at -eventclients-wiiremote
+PACKAGE_ARCHITECTURE
+PACKAGE_SECTION video
+PACKAGE_PRIORITY optional
+PACKAGE_SHLIBDEPS
+PACKAGE_DEPENDS @APP_NAME_LC at -eventclients-common (= @CPACK_DEBIAN_PACKAGE_VERSION@), libbluetooth3 (>= 4.91), libc6 (>= 2.14), libcwiid1 (>= 0.6.00+svn184), libgcc1 (>= 1:3.0), libstdc++6 (>= 5.2)
+PACKAGE_RECOMMENDS
+PACKAGE_SUGGESTS
+PACKAGE_BREAKS
+PACKAGE_REPLACES
+PACKAGE_PROVIDES xbmc-eventclients-wiiremote
+PACKAGE_DESCRIPTION_HEADER @APP_NAME@ Media Center (Wii Remote event client package)
+PACKAGE_DESCRIPTION_FOOTER This is the Wii Remote package for @APP_NAME@'s event client.
diff --git a/project/cmake/cpack/deb/packages/kodi-eventclients-xbmc-send.txt.in b/project/cmake/cpack/deb/packages/kodi-eventclients-xbmc-send.txt.in
new file mode 100644
index 0000000..0062479
--- /dev/null
+++ b/project/cmake/cpack/deb/packages/kodi-eventclients-xbmc-send.txt.in
@@ -0,0 +1,25 @@
+# kodi-eventclients-xbmc-send debian package metadata
+#
+# Setting PACKAGE_SHLIBDEPS to 'ON' will cause CPack to ignore PACKAGE_DEPENDS
+# content and use dpkg-shlibdeps to automatically generate the package dependency
+# list. Only useful for packages that contain binaries.
+#
+# PACKAGE_ARCHITECTURE should be set to 'all' only if package contains
+# architecture agnostic data. CPack will set proper architecture (amd64/i386/etc)
+# based on build options.
+#
+# Remaining settings are (hopefully) self-explanatory.
+
+PACKAGE_NAME @APP_NAME_LC at -eventclients-xbmc-send
+PACKAGE_ARCHITECTURE all
+PACKAGE_SECTION video
+PACKAGE_PRIORITY optional
+PACKAGE_SHLIBDEPS
+PACKAGE_DEPENDS @APP_NAME_LC at -eventclients-common (= @CPACK_DEBIAN_PACKAGE_VERSION@)
+PACKAGE_RECOMMENDS
+PACKAGE_SUGGESTS
+PACKAGE_BREAKS
+PACKAGE_REPLACES
+PACKAGE_PROVIDES xbmc-eventclients-xbmc-send
+PACKAGE_DESCRIPTION_HEADER @APP_NAME@ Media Center (@APP_NAME at -send event client package)
+PACKAGE_DESCRIPTION_FOOTER This is the Kodi-SEND package for @APP_NAME@'s event client.
diff --git a/project/cmake/cpack/deb/packages/kodi-inputstream-dev.txt.in b/project/cmake/cpack/deb/packages/kodi-inputstream-dev.txt.in
new file mode 100644
index 0000000..3b4c381
--- /dev/null
+++ b/project/cmake/cpack/deb/packages/kodi-inputstream-dev.txt.in
@@ -0,0 +1,25 @@
+# kodi-inputstream-dev debian package metadata
+#
+# Setting PACKAGE_SHLIBDEPS to 'ON' will cause CPack to ignore PACKAGE_DEPENDS
+# content and use dpkg-shlibdeps to automatically generate the package dependency
+# list. Only useful for packages that contain binaries.
+#
+# PACKAGE_ARCHITECTURE should be set to 'all' only if package contains
+# architecture agnostic data. CPack will set proper architecture (amd64/i386/etc)
+# based on build options.
+#
+# Remaining settings are (hopefully) self-explanatory.
+
+PACKAGE_NAME @APP_NAME_LC at -inputstream-dev
+PACKAGE_ARCHITECTURE all
+PACKAGE_SECTION libdevel
+PACKAGE_PRIORITY optional
+PACKAGE_SHLIBDEPS
+PACKAGE_DEPENDS @APP_NAME_LC at -addon-dev
+PACKAGE_RECOMMENDS
+PACKAGE_SUGGESTS
+PACKAGE_BREAKS
+PACKAGE_REPLACES
+PACKAGE_PROVIDES xbmc-inputstream-dev
+PACKAGE_DESCRIPTION_HEADER @APP_NAME@ Media Center (inputstream add-ons dev package)
+PACKAGE_DESCRIPTION_FOOTER This is the development package for @APP_NAME@'s inputstream add-ons.
diff --git a/project/cmake/cpack/deb/packages/kodi-pvr-dev.txt.in b/project/cmake/cpack/deb/packages/kodi-pvr-dev.txt.in
new file mode 100644
index 0000000..90e4a14
--- /dev/null
+++ b/project/cmake/cpack/deb/packages/kodi-pvr-dev.txt.in
@@ -0,0 +1,25 @@
+# kodi-pvr-dev debian package metadata
+#
+# Setting PACKAGE_SHLIBDEPS to 'ON' will cause CPack to ignore PACKAGE_DEPENDS
+# content and use dpkg-shlibdeps to automatically generate the package dependency
+# list. Only useful for packages that contain binaries.
+#
+# PACKAGE_ARCHITECTURE should be set to 'all' only if package contains
+# architecture agnostic data. CPack will set proper architecture (amd64/i386/etc)
+# based on build options.
+#
+# Remaining settings are (hopefully) self-explanatory.
+
+PACKAGE_NAME @APP_NAME_LC at -pvr-dev
+PACKAGE_ARCHITECTURE all
+PACKAGE_SECTION libdevel
+PACKAGE_PRIORITY optional
+PACKAGE_SHLIBDEPS
+PACKAGE_DEPENDS @APP_NAME_LC at -addon-dev
+PACKAGE_RECOMMENDS
+PACKAGE_SUGGESTS
+PACKAGE_BREAKS
+PACKAGE_REPLACES
+PACKAGE_PROVIDES xbmc-pvr-dev
+PACKAGE_DESCRIPTION_HEADER @APP_NAME@ Media Center (PVR add-ons dev package)
+PACKAGE_DESCRIPTION_FOOTER This is the development package for @APP_NAME@'s PVR add-ons.
diff --git a/project/cmake/cpack/deb/packages/kodi-screensaver-dev.txt.in b/project/cmake/cpack/deb/packages/kodi-screensaver-dev.txt.in
new file mode 100644
index 0000000..877c3ab
--- /dev/null
+++ b/project/cmake/cpack/deb/packages/kodi-screensaver-dev.txt.in
@@ -0,0 +1,25 @@
+# kodi-screensaver-dev debian package metadata
+#
+# Setting PACKAGE_SHLIBDEPS to 'ON' will cause CPack to ignore PACKAGE_DEPENDS
+# content and use dpkg-shlibdeps to automatically generate the package dependency
+# list. Only useful for packages that contain binaries.
+#
+# PACKAGE_ARCHITECTURE should be set to 'all' only if package contains
+# architecture agnostic data. CPack will set proper architecture (amd64/i386/etc)
+# based on build options.
+#
+# Remaining settings are (hopefully) self-explanatory.
+
+PACKAGE_NAME @APP_NAME_LC at -screensaver-dev
+PACKAGE_ARCHITECTURE all
+PACKAGE_SECTION libdevel
+PACKAGE_PRIORITY optional
+PACKAGE_SHLIBDEPS
+PACKAGE_DEPENDS @APP_NAME_LC at -addon-dev
+PACKAGE_RECOMMENDS
+PACKAGE_SUGGESTS
+PACKAGE_BREAKS
+PACKAGE_REPLACES
+PACKAGE_PROVIDES xbmc-screensaver-dev
+PACKAGE_DESCRIPTION_HEADER @APP_NAME@ Media Center (screensaver add-ons dev package)
+PACKAGE_DESCRIPTION_FOOTER This is the development package for @APP_NAME@'s screensaver add-ons.
diff --git a/project/cmake/cpack/deb/packages/kodi-tools-texturepacker.txt.in b/project/cmake/cpack/deb/packages/kodi-tools-texturepacker.txt.in
new file mode 100644
index 0000000..c5c5f8d
--- /dev/null
+++ b/project/cmake/cpack/deb/packages/kodi-tools-texturepacker.txt.in
@@ -0,0 +1,25 @@
+# kodi-tools-texturepacker debian package metadata
+#
+# Setting PACKAGE_SHLIBDEPS to 'ON' will cause CPack to ignore PACKAGE_DEPENDS
+# content and use dpkg-shlibdeps to automatically generate the package dependency
+# list. Only useful for packages that contain binaries.
+#
+# PACKAGE_ARCHITECTURE should be set to 'all' only if package contains
+# architecture agnostic data. CPack will set proper architecture (amd64/i386/etc)
+# based on build options.
+#
+# Remaining settings are (hopefully) self-explanatory.
+
+PACKAGE_NAME @APP_NAME_LC at -tools-texturepacker
+PACKAGE_ARCHITECTURE
+PACKAGE_SECTION video
+PACKAGE_PRIORITY optional
+PACKAGE_SHLIBDEPS
+PACKAGE_DEPENDS 
+PACKAGE_RECOMMENDS
+PACKAGE_SUGGESTS
+PACKAGE_BREAKS
+PACKAGE_REPLACES
+PACKAGE_PROVIDES
+PACKAGE_DESCRIPTION_HEADER @APP_NAME@ Media Center (skin development - TexturePacker tool)
+PACKAGE_DESCRIPTION_FOOTER This is @APP_NAME@'s TexturePacker tool for skin development.
diff --git a/project/cmake/cpack/deb/packages/kodi-visualization-dev.txt.in b/project/cmake/cpack/deb/packages/kodi-visualization-dev.txt.in
new file mode 100644
index 0000000..ecc5436
--- /dev/null
+++ b/project/cmake/cpack/deb/packages/kodi-visualization-dev.txt.in
@@ -0,0 +1,25 @@
+# kodi-visualization-dev debian package metadata
+#
+# Setting PACKAGE_SHLIBDEPS to 'ON' will cause CPack to ignore PACKAGE_DEPENDS
+# content and use dpkg-shlibdeps to automatically generate the package dependency
+# list. Only useful for packages that contain binaries.
+#
+# PACKAGE_ARCHITECTURE should be set to 'all' only if package contains
+# architecture agnostic data. CPack will set proper architecture (amd64/i386/etc)
+# based on build options.
+#
+# Remaining settings are (hopefully) self-explanatory.
+
+PACKAGE_NAME @APP_NAME_LC at -visualization-dev
+PACKAGE_ARCHITECTURE all
+PACKAGE_SECTION libdevel
+PACKAGE_PRIORITY optional
+PACKAGE_SHLIBDEPS
+PACKAGE_DEPENDS @APP_NAME_LC at -addon-dev
+PACKAGE_RECOMMENDS
+PACKAGE_SUGGESTS
+PACKAGE_BREAKS
+PACKAGE_REPLACES
+PACKAGE_PROVIDES xbmc-visualization-dev
+PACKAGE_DESCRIPTION_HEADER @APP_NAME@ Media Center (visualization add-ons dev package)
+PACKAGE_DESCRIPTION_FOOTER This is the development package for @APP_NAME@'s visualization add-ons.
diff --git a/project/cmake/cpack/deb/packages/kodi.txt.in b/project/cmake/cpack/deb/packages/kodi.txt.in
new file mode 100644
index 0000000..3a5cde1
--- /dev/null
+++ b/project/cmake/cpack/deb/packages/kodi.txt.in
@@ -0,0 +1,25 @@
+# kodi debian package metadata
+#
+# Setting PACKAGE_SHLIBDEPS to 'ON' will cause CPack to ignore PACKAGE_DEPENDS
+# content and use dpkg-shlibdeps to automatically generate the package dependency
+# list. Only useful for packages that contain binaries.
+#
+# PACKAGE_ARCHITECTURE should be set to 'all' only if package contains
+# architecture agnostic data. CPack will set proper architecture (amd64/i386/etc)
+# based on build options.
+#
+# Remaining settings are (hopefully) self-explanatory.
+
+PACKAGE_NAME @APP_NAME_LC@
+PACKAGE_ARCHITECTURE all
+PACKAGE_SECTION video
+PACKAGE_PRIORITY optional
+PACKAGE_SHLIBDEPS
+PACKAGE_DEPENDS @APP_NAME_LC at -bin (>= @CPACK_DEBIAN_PACKAGE_VERSION@), @APP_NAME_LC at -bin (<< @CPACK_DEBIAN_PACKAGE_VERSION at .1~), curl, libcurl3, mesa-utils, x11-utils, fonts-liberation | ttf-liberation, fonts-dejavu-core | ttf-dejavu-core, python-bluez | python-lightblue, python-imaging, python-simplejson, libmad0, libass5 | libass4, libgif5 | libgif7, libssh-4 | libssh2-1, libnfs8 | libnfs4 | libnfs1, libbluray1, libshairplay0, libvorbisfile3, libaacs0, libcec3, librtmp1 | librtmp0, libgnutls30 | libgnutls-deb0-28 | libgnutls28 | libgnutls26, libxslt1.1, libyajl2
+PACKAGE_RECOMMENDS libvdpau1, libva-intel-vaapi-driver, libva1
+PACKAGE_SUGGESTS @APP_NAME_LC at -pvr-mythtv, @APP_NAME_LC at -pvr-vuplus, @APP_NAME_LC at -pvr-vdr-vnsi, @APP_NAME_LC at -pvr-njoy, @APP_NAME_LC at -pvr-nextpvr, @APP_NAME_LC at -pvr-mediaportal-tvserver, @APP_NAME_LC at -pvr-tvheadend-hts, @APP_NAME_LC at -pvr-dvbviewer, @APP_NAME_LC at -pvr-argustv, @APP_NAME_LC at -pvr-iptvsimple, @APP_NAME_LC at -audioencoder-vorbis, @APP_NAME_LC at -audioencoder-flac, @APP_NAME_LC at -audioencoder-lame
+PACKAGE_BREAKS xbmc (<< 2:14.0~git20141019), xbmc-data, xbmc-standalone
+PACKAGE_REPLACES xbmc (<< 2:14.0~git20141019), xbmc-data, xbmc-standalone
+PACKAGE_PROVIDES @APP_NAME_LC at -data, @APP_NAME_LC at -skin-estuary, @APP_NAME_LC at -standalone, xbmc, xbmc-data, xbmc-standalone
+PACKAGE_DESCRIPTION_HEADER @APP_NAME@ Media Center (arch-independent data package)
+PACKAGE_DESCRIPTION_FOOTER This package contains @APP_NAME@'s architecture independent data.
diff --git a/project/cmake/cpack/deb/postinst b/project/cmake/cpack/deb/postinst
new file mode 100755
index 0000000..318d280
--- /dev/null
+++ b/project/cmake/cpack/deb/postinst
@@ -0,0 +1,5 @@
+#!/bin/sh
+set -e
+if [ "$1" = "configure" ] && [ -x "`which update-menus 2>/dev/null`" ]; then
+	update-menus
+fi
diff --git a/project/cmake/cpack/deb/postrm b/project/cmake/cpack/deb/postrm
new file mode 100755
index 0000000..adc11fd
--- /dev/null
+++ b/project/cmake/cpack/deb/postrm
@@ -0,0 +1,3 @@
+#!/bin/sh
+set -e
+if [ -x "`which update-menus 2>/dev/null`" ]; then update-menus ; fi
diff --git a/project/cmake/installdata/addon-bindings.txt b/project/cmake/installdata/addon-bindings.txt
deleted file mode 100644
index 5655da5..0000000
--- a/project/cmake/installdata/addon-bindings.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_addon_cpp_dll.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_addon_dll.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_addon_types.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_adsp_dll.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_adsp_types.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_audiodec_dll.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_audiodec_types.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_audioenc_dll.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_audioenc_types.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_audioengine_types.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_codec_types.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_epg_types.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_inputstream_dll.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_inputstream_types.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_vfs_types.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_vfs_utils.hpp
-xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_callbacks.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_dll.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_types.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_peripheral_utils.hpp
-xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_dll.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_types.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_scr_dll.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_scr_types.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_vis_dll.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_vis_types.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_addon.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_audioengine.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_adsp.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_guilib.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_inputstream.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_peripheral.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_pvr.h
-xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_codec.h
-xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxPacket.h
-xbmc/cores/AudioEngine/Utils/AEChannelData.h
-xbmc/filesystem/IFileTypes.h
diff --git a/project/cmake/installdata/cmake-files.txt b/project/cmake/installdata/cmake-files.txt
deleted file mode 100644
index 7ae9a8d..0000000
--- a/project/cmake/installdata/cmake-files.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-project/cmake/scripts/common/AddonHelpers.cmake
-project/cmake/scripts/common/AddOptions.cmake
-project/cmake/scripts/common/ArchSetup.cmake
-project/cmake/scripts/common/CheckCommits.cmake
-project/cmake/scripts/common/CheckTargetPlatform.cmake
-project/cmake/scripts/common/GenerateVersionedFiles.cmake
-project/cmake/scripts/common/GeneratorSetup.cmake
-project/cmake/scripts/common/HandleDepends.cmake
-project/cmake/scripts/common/Macros.cmake
-project/cmake/scripts/common/PrepareEnv.cmake
-project/cmake/scripts/common/ProjectMacros.cmake
diff --git a/project/cmake/installdata/ios/certificates.txt b/project/cmake/installdata/ios/certificates.txt
new file mode 100644
index 0000000..14e74a7
--- /dev/null
+++ b/project/cmake/installdata/ios/certificates.txt
@@ -0,0 +1 @@
+tools/depends/target/openssl/cacert.pem system/certs
\ No newline at end of file
diff --git a/project/cmake/installdata/osx/certificates.txt b/project/cmake/installdata/osx/certificates.txt
new file mode 100644
index 0000000..14e74a7
--- /dev/null
+++ b/project/cmake/installdata/osx/certificates.txt
@@ -0,0 +1 @@
+tools/depends/target/openssl/cacert.pem system/certs
\ No newline at end of file
diff --git a/project/cmake/installdata/windows/dlls.txt b/project/cmake/installdata/windows/dlls.txt
index 72cca7d..64d9756 100644
--- a/project/cmake/installdata/windows/dlls.txt
+++ b/project/cmake/installdata/windows/dlls.txt
@@ -1,6 +1,2 @@
-system/*.dll
-system/airplay/*.dll
-system/cdrip/*.dll
-system/players/dvdplayer/*.dll
-system/players/paplayer/*.dll
-system/players/VideoPlayer/*.dll
+system/*.dll .
+project/Win32BuildSetup/dependencies/python27.dll .
\ No newline at end of file
diff --git a/project/cmake/installdata/windows/python.txt b/project/cmake/installdata/windows/python.txt
new file mode 100644
index 0000000..b805318
--- /dev/null
+++ b/project/cmake/installdata/windows/python.txt
@@ -0,0 +1 @@
+system/python/*
\ No newline at end of file
diff --git a/project/cmake/modules/FindBluetooth.cmake b/project/cmake/modules/FindBluetooth.cmake
new file mode 100644
index 0000000..f3ed258
--- /dev/null
+++ b/project/cmake/modules/FindBluetooth.cmake
@@ -0,0 +1,30 @@
+#.rst:
+# FindBluetooth
+# ---------
+# Finds the Bluetooth library
+#
+# This will will define the following variables::
+#
+# BLUETOOTH_FOUND - system has Bluetooth
+# BLUETOOTH_INCLUDE_DIRS - the Bluetooth include directory
+# BLUETOOTH_LIBRARIES - the Bluetooth libraries
+
+if(PKG_CONFIG_FOUND)
+  pkg_check_modules(PC_BLUETOOTH bluetooth QUIET)
+endif()
+
+find_path(BLUETOOTH_INCLUDE_DIR NAMES bluetooth/bluetooth.h
+                                PATHS ${PC_BLUETOOTH_INCLUDEDIR})
+find_library(BLUETOOTH_LIBRARY NAMES bluetooth
+                                PATHS ${PC_BLUETOOTH_LIBDIR})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(BLUETOOTH
+                                  REQUIRED_VARS BLUETOOTH_LIBRARY BLUETOOTH_INCLUDE_DIR)
+
+if(BLUETOOTH_FOUND)
+  set(BLUETOOTH_INCLUDE_DIRS ${BLUETOOTH_INCLUDE_DIR})
+  set(BLUETOOTH_LIBRARIES ${BLUETOOTH_LIBRARY})
+endif()
+
+mark_as_advanced(BLUETOOTH_INCLUDE_DIR BLUETOOTH_LIBRARY)
diff --git a/project/cmake/modules/FindCWiid.cmake b/project/cmake/modules/FindCWiid.cmake
new file mode 100644
index 0000000..2f23abb
--- /dev/null
+++ b/project/cmake/modules/FindCWiid.cmake
@@ -0,0 +1,30 @@
+#.rst:
+# FindCWiid
+# ---------
+# Finds the CWiid library
+#
+# This will will define the following variables::
+#
+# CWIID_FOUND - system has CWiid
+# CWIID_INCLUDE_DIRS - the CWiid include directory
+# CWIID_LIBRARIES - the CWiid libraries
+
+if(PKG_CONFIG_FOUND)
+  pkg_check_modules(PC_CWIID cwiid QUIET)
+endif()
+
+find_path(CWIID_INCLUDE_DIR NAMES cwiid.h
+                            PATHS ${PC_CWIID_INCLUDEDIR})
+find_library(CWIID_LIBRARY NAMES cwiid
+                           PATHS ${PC_CWIID_LIBDIR})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(CWIID
+                                  REQUIRED_VARS CWIID_LIBRARY CWIID_INCLUDE_DIR)
+
+if(CWIID_FOUND)
+  set(CWIID_INCLUDE_DIRS ${CWIID_INCLUDE_DIR})
+  set(CWIID_LIBRARIES ${CWIID_LIBRARY})
+endif()
+
+mark_as_advanced(CWIID_INCLUDE_DIR CWIID_LIBRARY)
diff --git a/project/cmake/modules/FindCpluff.cmake b/project/cmake/modules/FindCpluff.cmake
index 51a7d73..545112e 100644
--- a/project/cmake/modules/FindCpluff.cmake
+++ b/project/cmake/modules/FindCpluff.cmake
@@ -21,8 +21,7 @@ if(NOT WIN32)
                                         --prefix=<INSTALL_DIR>
                                         --host=${ARCH}
                                         CFLAGS=${defines}
-                                        LDFLAGS=${ldflags}
-                      BUILD_COMMAND make V=1)
+                                        LDFLAGS=${ldflags})
   ExternalProject_Add_Step(libcpluff autoreconf
                                      DEPENDEES download update patch
                                      DEPENDERS configure
@@ -33,20 +32,21 @@ if(NOT WIN32)
   set(ldflags "${ldflags};-lexpat")
   core_link_library(${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/cpluff/lib/libcpluff.a
                     system/libcpluff libcpluff extras "${ldflags}")
-  set(WRAP_FILES ${WRAP_FILES} PARENT_SCOPE)
+  set(CPLUFF_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/cpluff/include)
+  set(CPLUFF_FOUND 1)
+  mark_as_advanced(CPLUFF_INCLUDE_DIRS CPLUFF_FOUND)
 else()
-  ExternalProject_Add(libcpluff SOURCE_DIR ${CORE_SOURCE_DIR}/lib/cpluff
-                      PREFIX ${CORE_BUILD_DIR}/cpluff
-                      CONFIGURE_COMMAND ""
-                      # TODO: Building the project directly from lib/cpluff/libcpluff/win32/cpluff.vcxproj
-                      #       fails becaue it imports XBMC.defaults.props
-                      BUILD_COMMAND msbuild ${CORE_SOURCE_DIR}/project/VS2010Express/XBMC\ for\ Windows.sln
-                                            /t:cpluff /p:Configuration=${CORE_BUILD_CONFIG}
-                      INSTALL_COMMAND "")
-  copy_file_to_buildtree(${CORE_SOURCE_DIR}/system/cpluff.dll ${CORE_SOURCE_DIR})
-  add_dependencies(export-files libcpluff)
-endif()
+  find_path(CPLUFF_INCLUDE_DIR cpluff.h)
 
-set(CPLUFF_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/cpluff/include)
-set(CPLUFF_FOUND 1)
-mark_as_advanced(CPLUFF_INCLUDE_DIRS CPLUFF_FOUND)
+  include(FindPackageHandleStandardArgs)
+  find_package_handle_standard_args(CPLUFF
+                                    REQUIRED_VARS CPLUFF_INCLUDE_DIR)
+
+  if(CPLUFF_FOUND)
+    set(CPLUFF_INCLUDE_DIRS ${CPLUFF_INCLUDE_DIR})
+  endif()
+  mark_as_advanced(CPLUFF_INCLUDE_DIRS CPLUFF_FOUND)
+
+  add_custom_target(libcpluff)
+endif()
+set_target_properties(libcpluff PROPERTIES FOLDER "External Projects")
diff --git a/project/cmake/modules/FindCrossGUID.cmake b/project/cmake/modules/FindCrossGUID.cmake
index 05f2abc..6ae9668 100644
--- a/project/cmake/modules/FindCrossGUID.cmake
+++ b/project/cmake/modules/FindCrossGUID.cmake
@@ -21,6 +21,7 @@ if(ENABLE_INTERNAL_CROSSGUID)
                                     ${CORE_SOURCE_DIR}/tools/depends/target/crossguid/FindCXX11.cmake
                                     <SOURCE_DIR>
                       BUILD_BYPRODUCTS ${CROSSGUID_LIBRARY})
+  set_target_properties(crossguid PROPERTIES FOLDER "External Projects")
 
   set(CROSSGUID_FOUND 1)
   set(CROSSGUID_LIBRARIES ${CROSSGUID_LIBRARY})
@@ -45,6 +46,9 @@ else()
   if(CROSSGUID_FOUND)
     set(CROSSGUID_LIBRARIES ${CROSSGUID_LIBRARY})
     set(CROSSGUID_INCLUDE_DIRS ${CROSSGUID_INCLUDE_DIR})
+
+    add_custom_target(crossguid)
+    set_target_properties(crossguid PROPERTIES FOLDER "External Projects")
   endif()
   mark_as_advanced(CROSSGUID_INCLUDE_DIR CROSSGUID_LIBRARY)
 endif()
diff --git a/project/cmake/modules/FindD3DX11Effects.cmake b/project/cmake/modules/FindD3DX11Effects.cmake
index 5a58993..8a36f9c 100644
--- a/project/cmake/modules/FindD3DX11Effects.cmake
+++ b/project/cmake/modules/FindD3DX11Effects.cmake
@@ -16,6 +16,7 @@ ExternalProject_Add(d3dx11effects
                                   /t:Effects11 /p:Configuration=${CORE_BUILD_CONFIG}
             INSTALL_COMMAND ""
             BUILD_BYPRODUCTS ${D3DX11EFFECTS_LIBRARY_RELEASE} ${D3DX11EFFECTS_LIBRARY_DEBUG})
+set_target_properties(d3dx11effects PROPERTIES FOLDER "External Projects")
 
 set(D3DX11EFFECTS_FOUND 1)
 set(D3DX11EFFECTS_INCLUDE_DIRS ${CORE_SOURCE_DIR}/lib/win32/Effects11/inc)
@@ -37,6 +38,7 @@ if(NOT D3DCOMPILER_DLL)
   message(WARNING "Could NOT find Direct3D Compiler")
 endif()
 mark_as_advanced(D3DCOMPILER_DLL)
+copy_file_to_buildtree(${D3DCOMPILER_DLL} DIRECTORY .)
 
 find_program(FXC fxc
              PATHS
diff --git a/project/cmake/modules/FindFFMPEG.cmake b/project/cmake/modules/FindFFMPEG.cmake
index 1c600cd..9a74b77 100644
--- a/project/cmake/modules/FindFFMPEG.cmake
+++ b/project/cmake/modules/FindFFMPEG.cmake
@@ -76,6 +76,7 @@ else()
     pkg_check_modules (FFMPEG ${FFMPEG_PKGS})
     string(REGEX REPLACE "framework;" "framework " FFMPEG_LDFLAGS "${FFMPEG_LDFLAGS}")
     set(FFMPEG_LIBRARIES ${FFMPEG_LDFLAGS})
+    add_custom_target(ffmpeg)
   else()
     find_path(FFMPEG_INCLUDE_DIRS libavcodec/avcodec.h PATH_SUFFIXES ffmpeg)
     find_library(FFMPEG_LIBAVCODEC NAMES avcodec libavcodec PATH_SUFFIXES ffmpeg/libavcodec)
@@ -94,5 +95,6 @@ else()
   set(FFMPEG_FOUND 1)
   list(APPEND FFMPEG_DEFINITIONS -DFFMPEG_VER_SHA=\"${FFMPEG_VER}\")
 endif()
+set_target_properties(ffmpeg PROPERTIES FOLDER "External Projects")
 
 mark_as_advanced(FFMPEG_INCLUDE_DIRS FFMPEG_LIBRARIES FFMPEG_DEFINITIONS FFMPEG_FOUND)
diff --git a/project/cmake/modules/FindJsonSchemaBuilder.cmake b/project/cmake/modules/FindJsonSchemaBuilder.cmake
index 78e8d0a..ecff1e4 100644
--- a/project/cmake/modules/FindJsonSchemaBuilder.cmake
+++ b/project/cmake/modules/FindJsonSchemaBuilder.cmake
@@ -12,8 +12,10 @@ if(NOT TARGET JsonSchemaBuilder::JsonSchemaBuilder)
     add_executable(JsonSchemaBuilder::JsonSchemaBuilder IMPORTED GLOBAL)
     set_target_properties(JsonSchemaBuilder::JsonSchemaBuilder PROPERTIES
                                                                IMPORTED_LOCATION "${NATIVEPREFIX}/bin/JsonSchemaBuilder")
+    set_target_properties(JsonSchemaBuilder::JsonSchemaBuilder PROPERTIES FOLDER Tools)
   else()
     add_subdirectory(${CORE_SOURCE_DIR}/tools/depends/native/JsonSchemaBuilder build/jsonschemabuilder)
     add_executable(JsonSchemaBuilder::JsonSchemaBuilder ALIAS JsonSchemaBuilder)
+    set_target_properties(JsonSchemaBuilder PROPERTIES FOLDER Tools)
   endif()
 endif()
diff --git a/project/cmake/modules/FindLibDvd.cmake b/project/cmake/modules/FindLibDvd.cmake
index 834d436..6f0a6d1 100644
--- a/project/cmake/modules/FindLibDvd.cmake
+++ b/project/cmake/modules/FindLibDvd.cmake
@@ -55,6 +55,7 @@ if(NOT WIN32)
                                     COMMAND PATH=${NATIVEPREFIX}/bin:$ENV{PATH} autoreconf -vif
                                     WORKING_DIRECTORY <SOURCE_DIR>)
 
+    set_target_properties(dvdcss PROPERTIES FOLDER "External Projects")
     core_link_library(${DVDCSS_LIBRARY} system/players/VideoPlayer/libdvdcss dvdcss)
   endif()
 
@@ -86,6 +87,7 @@ if(NOT WIN32)
     add_dependencies(dvdread dvdcss)
   endif()
 
+  set_target_properties(dvdread PROPERTIES FOLDER "External Projects")
   core_link_library(${DVDREAD_LIBRARY} system/players/VideoPlayer/libdvdread dvdread)
 
   if(ENABLE_DVDCSS)
@@ -115,10 +117,9 @@ if(NOT WIN32)
                                   COMMAND PATH=${NATIVEPREFIX}/bin:$ENV{PATH} autoreconf -vif
                                   WORKING_DIRECTORY <SOURCE_DIR>)
   add_dependencies(dvdnav dvdread)
+  set_target_properties(dvdnav PROPERTIES FOLDER "External Projects")
   core_link_library(${DVDNAV_LIBRARY} system/players/VideoPlayer/libdvdnav dvdnav)
 
-  set(WRAP_FILES ${WRAP_FILES} PARENT_SCOPE)
-
   set(LIBDVD_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/libdvd/include)
   set(LIBDVD_LIBRARIES ${DVDNAV_LIBRARY} ${DVDREAD_LIBRARY})
   if(ENABLE_DVDCSS)
@@ -135,6 +136,9 @@ else()
 
   if(LIBDVD_FOUND)
     set(LIBDVD_INCLUDE_DIRS ${LIBDVD_INCLUDE_DIR})
+
+    add_custom_target(dvdnav)
+    set_target_properties(dvdnav PROPERTIES FOLDER "External Projects")
   endif()
 
   mark_as_advanced(LIBDVD_INCLUDE_DIR)
diff --git a/project/cmake/modules/FindPulseAudio.cmake b/project/cmake/modules/FindPulseAudio.cmake
index f471f78..b180fae 100644
--- a/project/cmake/modules/FindPulseAudio.cmake
+++ b/project/cmake/modules/FindPulseAudio.cmake
@@ -1,72 +1,49 @@
-# Try to find the PulseAudio library
+#.rst:
+# FindPulseAudio
+# --------------
+# Finds the PulseAudio library
 #
-# Once done this will define:
+# This will define the following variables::
 #
 #  PULSEAUDIO_FOUND - system has the PulseAudio library
-#  PULSEAUDIO_INCLUDE_DIR - the PulseAudio include directory
-#  PULSEAUDIO_LIBRARY - the libraries needed to use PulseAudio
-#  PULSEAUDIO_MAINLOOP_LIBRARY - the libraries needed to use PulsAudio Mailoop
-#
-# Copyright (c) 2008, Matthias Kretz, <kretz at kde.org>
-# Copyright (c) 2009, Marcus Hufgard, <Marcus.Hufgard at hufgard.de>
-#
-# Redistribution and use is allowed according to the terms of the BSD license.
-# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
-
-if(NOT PULSEAUDIO_MINIMUM_VERSION)
-  set(PULSEAUDIO_MINIMUM_VERSION "1.0.0")
-endif()
+#  PULSEAUDIO_INCLUDE_DIRS - the PulseAudio include directory
+#  PULSEAUDIO_LIBRARIES - the libraries needed to use PulseAudio
 
-if(PULSEAUDIO_INCLUDE_DIRS AND PULSEAUDIO_LIBRARY AND PULSEAUDIO_MAINLOOP_LIBRARY)
-   # Already in cache, be silent
-   set(PULSEAUDIO_FIND_QUIETLY TRUE)
+if(NOT PULSEAUDIO_FIND_VERSION)
+  set(PULSEAUDIO_FIND_VERSION 2.0.0)
 endif()
 
-if(NOT WIN32)
-   include(FindPkgConfig)
-   pkg_check_modules(PC_PULSEAUDIO libpulse>=${PULSEAUDIO_MINIMUM_VERSION})
-   pkg_check_modules(PC_PULSEAUDIO_MAINLOOP libpulse-mainloop-glib)
+if(PKG_CONFIG_FOUND)
+  pkg_check_modules(PC_PULSEAUDIO libpulse>=${PULSEAUDIO_FIND_VERSION})
+  pkg_check_modules(PC_PULSEAUDIO_MAINLOOP libpulse-mainloop-glib)
 endif()
 
-find_path(PULSEAUDIO_INCLUDE_DIRS pulse/pulseaudio.h
-   HINTS
-   ${PC_PULSEAUDIO_INCLUDEDIR}
-   ${PC_PULSEAUDIO_INCLUDE_DIRS}
-   )
+find_path(PULSEAUDIO_INCLUDE_DIR NAMES pulse/pulseaudio.h
+                                 PATHS ${PC_PULSEAUDIO_INCLUDEDIR} ${PC_PULSEAUDIO_INCLUDE_DIRS})
 
 find_library(PULSEAUDIO_LIBRARY NAMES pulse libpulse
-   HINTS
-   ${PC_PULSEAUDIO_LIBDIR}
-   ${PC_PULSEAUDIO_LIBRARY_DIRS}
-   )
+                                PATHS ${PC_PULSEAUDIO_LIBDIR} ${PC_PULSEAUDIO_LIBRARY_DIRS})
 
 find_library(PULSEAUDIO_MAINLOOP_LIBRARY NAMES pulse-mainloop pulse-mainloop-glib libpulse-mainloop-glib
-   HINTS
-   ${PC_PULSEAUDIO_LIBDIR}
-   ${PC_PULSEAUDIO_LIBRARY_DIRS}
-   )
-
-if(NOT PULSEAUDIO_INCLUDE_DIRS OR NOT PULSEAUDIO_LIBRARY)
-  set(PULSEAUDIO_FOUND FALSE)
-else()
-  set(PULSEAUDIO_FOUND TRUE)
+                                         PATHS ${PC_PULSEAUDIO_LIBDIR} ${PC_PULSEAUDIO_LIBRARY_DIRS})
+
+if(PC_PULSEAUDIO_VERSION)
+  set(PULSEAUDIO_VERSION_STRING ${PC_PULSEAUDIO_VERSION})
+elseif(PULSEAUDIO_INCLUDE_DIR AND EXISTS "${PULSEAUDIO_INCLUDE_DIR}/pulse/version.h")
+  file(STRINGS "${PULSEAUDIO_INCLUDE_DIR}/pulse/version.h" pulseaudio_version_str REGEX "^#define[\t ]+pa_get_headers_version\\(\\)[\t ]+\\(\".*\"\\).*")
+  string(REGEX REPLACE "^#define[\t ]+pa_get_headers_version\\(\\)[\t ]+\\(\"([^\"]+)\"\\).*" "\\1" PULSEAUDIO_VERSION_STRING "${pulseaudio_version_str}")
+  unset(pulseaudio_version_str)
 endif()
 
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(PULSEAUDIO
+                                  REQUIRED_VARS PULSEAUDIO_LIBRARY PULSEAUDIO_MAINLOOP_LIBRARY PULSEAUDIO_INCLUDE_DIR
+                                  VERSION_VAR PULSEAUDIO_VERSION_STRING)
+
 if(PULSEAUDIO_FOUND)
-   if(NOT PULSEAUDIO_FIND_QUIETLY)
-      message(STATUS "Found PulseAudio: ${PULSEAUDIO_LIBRARY}")
-      if(PULSEAUDIO_MAINLOOP_LIBRARY)
-          message(STATUS "Found PulseAudio Mainloop: ${PULSEAUDIO_MAINLOOP_LIBRARY}")
-      else()
-          message(STATUS "Could NOT find PulseAudio Mainloop Library")
-      endif()
-   endif()
-else()
-   message(STATUS "Could NOT find PulseAudio")
+  set(PULSEAUDIO_INCLUDE_DIRS ${PULSEAUDIO_INCLUDE_DIR})
+  set(PULSEAUDIO_LIBRARIES ${PULSEAUDIO_LIBRARY} ${PULSEAUDIO_MAINLOOP_LIBRARY})
+  set(PULSEAUDIO_DEFINITIONS -DHAVE_LIBPULSE=1)
 endif()
 
-set(PULSEAUDIO_LIBRARIES ${PULSEAUDIO_LIBRARY})
-
-list(APPEND PULSEAUDIO_DEFINITIONS -DHAVE_LIBPULSE=1)
-
-mark_as_advanced(PULSEAUDIO_INCLUDE_DIRS PULSEAUDIO_LIBRARIES PULSEAUDIO_LIBRARY PULSEAUDIO_MAINLOOP_LIBRARY)
+mark_as_advanced(PULSEAUDIO_INCLUDE_DIR PULSEAUDIO_LIBRARY PULSEAUDIO_MAINLOOP_LIBRARY)
diff --git a/project/cmake/modules/FindSWIG.cmake b/project/cmake/modules/FindSWIG.cmake
index 84c7a51..202b731 100644
--- a/project/cmake/modules/FindSWIG.cmake
+++ b/project/cmake/modules/FindSWIG.cmake
@@ -1,5 +1,5 @@
 if(NOT SWIG_EXECUTABLE)
-  find_program(SWIG_EXECUTABLE NAMES swig2.0 swig PATH_SUFFIXES swig)
+  find_program(SWIG_EXECUTABLE NAMES swig3.0 swig2.0 swig PATH_SUFFIXES swig)
 endif()
 if(SWIG_EXECUTABLE)
   execute_process(COMMAND ${SWIG_EXECUTABLE} -swiglib
diff --git a/project/cmake/modules/LDGOLD.cmake b/project/cmake/modules/LDGOLD.cmake
new file mode 100644
index 0000000..ad19c6b
--- /dev/null
+++ b/project/cmake/modules/LDGOLD.cmake
@@ -0,0 +1,45 @@
+option(ENABLE_LDGOLD "Use GNU gold linker" ON)
+
+set(LDGOLD_FOUND FALSE)
+if(ENABLE_LDGOLD)
+  execute_process(COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
+  if(LD_VERSION MATCHES "GNU gold")
+    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
+    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
+    set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
+    set(LDGOLD_FOUND TRUE)
+    message(STATUS "Linker: GNU gold")
+  else()
+    message(WARNING "GNU gold linker is not available, falling back to default system linker")
+  endif()
+else()
+  message(STATUS "Linker: Default system linker")
+endif()
+
+set(DEFAULT_ENABLE_DEBUGFISSION FALSE)
+if(CMAKE_BUILD_TYPE STREQUAL Debug OR
+   CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo AND
+   LDGOLD_FOUND)
+  set(DEFAULT_ENABLE_DEBUGFISSION TRUE)
+endif()
+
+include(CMakeDependentOption)
+cmake_dependent_option(ENABLE_DEBUGFISSION "Enable Debug Fission support" ON
+                       "DEFAULT_ENABLE_DEBUGFISSION" OFF)
+
+set(DEBUGFISSION_FOUND FALSE)
+if(ENABLE_DEBUGFISSION)
+  include(TestCXXAcceptsFlag)
+  check_cxx_accepts_flag(-gsplit-dwarf CXX_ACCEPTS_GSPLIT_DWARF)
+  if(CXX_ACCEPTS_GSPLIT_DWARF)
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -gsplit-dwarf")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -gsplit-dwarf")
+    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gdb-index")
+    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gdb-index")
+    set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gdb-index")
+    set(DEBUGFISSION_FOUND TRUE)
+    message(STATUS "Debug Fission enabled")
+  else()
+    message(WARNING "Debug Fission is not available")
+  endif()
+endif()
diff --git a/project/cmake/scripts/android/Install.cmake b/project/cmake/scripts/android/Install.cmake
index f0fd566..0558294 100644
--- a/project/cmake/scripts/android/Install.cmake
+++ b/project/cmake/scripts/android/Install.cmake
@@ -60,7 +60,6 @@ function(add_bundle_file file destination relative)
     file(REMOVE ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/BundleFiles.cmake)
     add_custom_target(bundle_files COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/BundleFiles.cmake)
     add_dependencies(bundle bundle_files)
-    add_dependencies(bundle_files export-files pack-skins wrap-libraries generate_json_header)
   endif()
 
   string(REPLACE "${relative}/" "" outfile ${file})
@@ -75,8 +74,8 @@ foreach(file IN LISTS XBT_FILES install_data)
   add_bundle_file(${CMAKE_BINARY_DIR}/${file} ${datarootdir}/${APP_NAME_LC} ${CMAKE_BINARY_DIR})
 endforeach()
 
-foreach(file IN LISTS WRAP_FILES)
-  add_bundle_file(${CMAKE_BINARY_DIR}/${file} ${libdir}/${APP_NAME_LC} ${CMAKE_BINARY_DIR})
+foreach(library IN LISTS LIBRARY_FILES)
+  add_bundle_file(${library} ${libdir}/${APP_NAME_LC} ${CMAKE_BINARY_DIR})
 endforeach()
 
 foreach(lib IN LISTS required_dyload dyload_optional ITEMS Shairplay)
@@ -87,6 +86,7 @@ foreach(lib IN LISTS required_dyload dyload_optional ITEMS Shairplay)
   endif()
 endforeach()
 add_bundle_file(${SMBCLIENT_LIBRARY} ${libdir} "")
+add_bundle_file(${DEPENDS_PATH}/lib/librtmp.so ${libdir} "")
 
 # Main targets from Makefile.in
 if(CPU MATCHES i686)
diff --git a/project/cmake/scripts/common/ArchSetup.cmake b/project/cmake/scripts/common/ArchSetup.cmake
index a19e9d5..556e90b 100644
--- a/project/cmake/scripts/common/ArchSetup.cmake
+++ b/project/cmake/scripts/common/ArchSetup.cmake
@@ -75,6 +75,13 @@ endif()
 set(CORE_MAIN_SOURCE ${CORE_SOURCE_DIR}/xbmc/platform/posix/main.cpp)
 
 # system specific arch setup
+if(NOT EXISTS ${PROJECT_SOURCE_DIR}/scripts/${CORE_SYSTEM_NAME}/ArchSetup.cmake)
+  message(FATAL_ERROR "Couldn't find configuration for '${CORE_SYSTEM_NAME}' "
+                      "Either the platform is not (yet) supported "
+                      "or a toolchain file has to be specified. "
+                      "Consult ${CMAKE_SOURCE_DIR}/README.md for instructions. "
+                      "Note: Specifying a toolchain requires a clean build directory!")
+endif()
 include(${PROJECT_SOURCE_DIR}/scripts/${CORE_SYSTEM_NAME}/ArchSetup.cmake)
 
 message(STATUS "Core system type: ${CORE_SYSTEM_NAME}")
diff --git a/project/cmake/scripts/common/CMakeHelpers.cmake b/project/cmake/scripts/common/CMakeHelpers.cmake
new file mode 100644
index 0000000..995c38a
--- /dev/null
+++ b/project/cmake/scripts/common/CMakeHelpers.cmake
@@ -0,0 +1,54 @@
+# This file contains functions that support the debugging of the CMake files.
+
+# This file shouldn't be included per default in any CMake file. It should be
+# included and used only on demand. All functions are prefixed with "debug_".
+#
+# Usage:
+# include(scripts/common/CMakeHelpers.cmake)
+# debug_print_variables()
+
+# Print all CMake variables.
+macro(debug_print_variables)
+  get_cmake_property(_variableNames VARIABLES)
+  foreach(_variableName ${_variableNames})
+    message(STATUS "${_variableName} = ${${_variableName}}")
+  endforeach()
+endmacro()
+
+# Get all properties that CMake supports and convert them to a list.
+function(debug_get_properties VAR)
+  execute_process(COMMAND cmake --help-property-list
+                  OUTPUT_VARIABLE _properties)
+  string(REGEX REPLACE ";" "\\\\;" _properties "${_properties}")
+  string(REGEX REPLACE "\n" ";" _properties "${_properties}")
+  list(REMOVE_DUPLICATES _properties)
+  list(REMOVE_ITEM _properties LOCATION)
+  set(${VAR} ${_properties} PARENT_SCOPE)
+endfunction()
+
+# List all properties.
+function(debug_list_properties)
+  debug_get_properties(_properties)
+  message("CMake properties = ${_properties}")
+endfunction()
+
+# Print all set properties of a specified target.
+function(debug_print_target_properties target)
+  if(NOT TARGET ${target})
+    message(FATAL_ERROR "There is no target named '${target}'")
+  endif()
+
+  debug_get_properties(_properties)
+
+  # Reading LOCATION property is deprecated and triggers a fatal error.
+  string(REGEX REPLACE ";LOCATION;|LOCATION" "" _properties "${_properties}")
+  string(REGEX REPLACE "<CONFIG>" "${CMAKE_BUILD_TYPE}" _properties
+         "${_properties}")
+  foreach(_property ${_properties})
+    get_property(_value TARGET ${target} PROPERTY ${_property} SET)
+    if(_value)
+      get_target_property(_value ${target} ${_property})
+      message("${target} ${_property} = ${_value}")
+    endif()
+  endforeach()
+endfunction()
diff --git a/project/cmake/scripts/common/GeneratorSetup.cmake b/project/cmake/scripts/common/GeneratorSetup.cmake
index a19730a..47b43de 100644
--- a/project/cmake/scripts/common/GeneratorSetup.cmake
+++ b/project/cmake/scripts/common/GeneratorSetup.cmake
@@ -23,6 +23,21 @@ else()
   message(STATUS "Generator: Single-configuration: ${CMAKE_BUILD_TYPE} (${CMAKE_GENERATOR})")
 endif()
 
+# Print CMake version
+message(STATUS "CMake Version: ${CMAKE_VERSION}")
+
+# Deal with CMake special cases
+if(CMAKE_VERSION VERSION_EQUAL 3.5.1)
+  message(WARNING "CMake 3.5.1 introduced a crash during configuration. "
+                  "Please consider upgrading to 3.5.2 (cmake.org/Bug/view.php?id=16044)")
+endif()
+
+# Darwin needs CMake 3.4
+if(APPLE AND CMAKE_VERSION VERSION_LESS 3.4)
+  message(WARNING "Build on Darwin requires CMake 3.4 or later (tdb library support) "
+                  "or the usage of the patched version in depends.")
+endif()
+
 # Ninja needs CMake 3.2 due to ExternalProject BUILD_BYPRODUCTS usage
 if(CMAKE_GENERATOR STREQUAL Ninja AND CMAKE_VERSION VERSION_LESS 3.2)
   message(FATAL_ERROR "Generator: Ninja requires CMake 3.2 or later")
diff --git a/project/cmake/scripts/common/Macros.cmake b/project/cmake/scripts/common/Macros.cmake
index b8dd860..f473181 100644
--- a/project/cmake/scripts/common/Macros.cmake
+++ b/project/cmake/scripts/common/Macros.cmake
@@ -3,92 +3,221 @@
 # include system specific macros
 include(${CORE_SOURCE_DIR}/project/cmake/scripts/${CORE_SYSTEM_NAME}/Macros.cmake)
 
-# Add a library, optionally as a dependency of the main application
+# IDEs: Group source files in target in folders (file system hierarchy)
+# Source: http://blog.audio-tk.com/2015/09/01/sorting-source-files-and-projects-in-folders-with-cmake-and-visual-studioxcode/
 # Arguments:
-#   name name of the library to add
+#   target The target that shall be grouped by folders.
 # Optional Arguments:
-#   NO_MAIN_DEPENDS if specified, the library is not added to main depends
+#   RELATIVE allows to specify a different reference folder.
+function(source_group_by_folder target)
+  if(NOT TARGET ${target})
+    message(FATAL_ERROR "There is no target named '${target}'")
+  endif()
+
+  set(SOURCE_GROUP_DELIMITER "/")
+
+  cmake_parse_arguments(arg "" "RELATIVE" "" ${ARGN})
+  if(arg_RELATIVE)
+    set(relative_dir ${arg_RELATIVE})
+  else()
+    set(relative_dir ${CMAKE_CURRENT_SOURCE_DIR})
+  endif()
+
+  get_property(files TARGET ${target} PROPERTY SOURCES)
+  if(files)
+    list(SORT files)
+
+    if(CMAKE_GENERATOR STREQUAL Xcode)
+      set_target_properties(${target} PROPERTIES SOURCES "${files}")
+    endif()
+  endif()
+  foreach(file ${files})
+    if(NOT IS_ABSOLUTE ${file})
+      set(file ${CMAKE_CURRENT_SOURCE_DIR}/${file})
+    endif()
+    file(RELATIVE_PATH relative_file ${relative_dir} ${file})
+    get_filename_component(dir "${relative_file}" PATH)
+    if(NOT dir STREQUAL "${last_dir}")
+      if(files)
+        source_group("${last_dir}" FILES ${files})
+      endif()
+      set(files "")
+    endif()
+    set(files ${files} ${file})
+    set(last_dir "${dir}")
+  endforeach(file)
+  if(files)
+    source_group("${last_dir}" FILES ${files})
+  endif()
+endfunction()
+
+# Add sources to main application
+# Arguments:
+#   name name of the library to add
 # Implicit arguments:
+#   ENABLE_STATIC_LIBS Build static libraries per directory
 #   SOURCES the sources of the library
 #   HEADERS the headers of the library (only for IDE support)
 #   OTHERS  other library related files (only for IDE support)
 # On return:
 #   Library will be built, optionally added to ${core_DEPENDS}
+#   Sets CORE_LIBRARY for calls for setting target specific options
 function(core_add_library name)
-  cmake_parse_arguments(arg "NO_MAIN_DEPENDS" "" "" ${ARGN})
+  if(ENABLE_STATIC_LIBS)
+    add_library(${name} STATIC ${SOURCES} ${HEADERS} ${OTHERS})
+    set_target_properties(${name} PROPERTIES PREFIX "")
+    set(core_DEPENDS ${name} ${core_DEPENDS} CACHE STRING "" FORCE)
+    add_dependencies(${name} libcpluff ffmpeg dvdnav crossguid)
+    set(CORE_LIBRARY ${name} PARENT_SCOPE)
 
-  if(NOT SOURCES)
-      message(STATUS "No sources added to ${name} skipping")
-      return()
+    # Add precompiled headers to Kodi main libraries
+    if(CORE_SYSTEM_NAME STREQUAL windows)
+      add_precompiled_header(${name} pch.h ${CORE_SOURCE_DIR}/xbmc/platform/win32/pch.cpp PCH_TARGET kodi)
+      set_language_cxx(${name})
+    endif()
+  else()
+    foreach(src IN LISTS SOURCES HEADERS OTHERS)
+      get_filename_component(src_path "${src}" ABSOLUTE)
+      list(APPEND FILES ${src_path})
+    endforeach()
+    target_sources(lib${APP_NAME_LC} PRIVATE ${FILES})
+    set(CORE_LIBRARY lib${APP_NAME_LC} PARENT_SCOPE)
   endif()
+endfunction()
 
-  add_library(${name} STATIC ${SOURCES} ${HEADERS} ${OTHERS})
-  set_target_properties(${name} PROPERTIES PREFIX "")
-  if(NOT arg_NO_MAIN_DEPENDS)
-    set(core_DEPENDS ${name} ${core_DEPENDS} CACHE STRING "" FORCE)
+# Add a test library, and add sources to list for gtest integration macros
+function(core_add_test_library name)
+  if(ENABLE_STATIC_LIBS)
+    add_library(${name} STATIC ${SOURCES} ${SUPPORTED_SOURCES} ${HEADERS} ${OTHERS})
+    set_target_properties(${name} PROPERTIES PREFIX ""
+                                             EXCLUDE_FROM_ALL 1
+                                             FOLDER "Build Utilities/tests")
+    add_dependencies(${name} libcpluff ffmpeg dvdnav crossguid)
+    set(test_archives ${test_archives} ${name} CACHE STRING "" FORCE)
   endif()
+  foreach(src IN LISTS SOURCES)
+    get_filename_component(src_path "${src}" ABSOLUTE)
+    set(test_sources "${src_path}" ${test_sources} CACHE STRING "" FORCE)
+  endforeach()
+endfunction()
+
+# Add an addon callback library
+# Arguments:
+#   name name of the library to add
+# Implicit arguments:
+#   SOURCES the sources of the library
+#   HEADERS the headers of the library (only for IDE support)
+#   OTHERS  other library related files (only for IDE support)
+# On return:
+#   Library target is defined and added to LIBRARY_FILES
+function(core_add_addon_library name)
+  get_filename_component(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} NAME)
+  list(APPEND SOURCES lib${name}.cpp)
+  core_add_shared_library(${name} OUTPUT_DIRECTORY addons/${DIRECTORY})
+  set_target_properties(${name} PROPERTIES FOLDER addons)
+  target_include_directories(${name} PRIVATE
+                             ${CMAKE_CURRENT_SOURCE_DIR}
+                             ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi
+                             ${CORE_SOURCE_DIR}/xbmc)
+endfunction()
 
-  # Add precompiled headers to Kodi main libraries
-  if(WIN32 AND "${CMAKE_CURRENT_LIST_DIR}" MATCHES "^${CORE_SOURCE_DIR}/xbmc")
-    add_precompiled_header(${name} pch.h ${CORE_SOURCE_DIR}/xbmc/win32/pch.cpp
-                           PCH_TARGET kodi)
+# Add an dl-loaded shared library
+# Arguments:
+#   name name of the library to add
+# Optional arguments:
+#   WRAPPED wrap this library on POSIX platforms to add VFS support for
+#           libraries that would otherwise not support it.
+#   OUTPUT_DIRECTORY where to create the library in the build dir
+#           (default: system)
+# Implicit arguments:
+#   SOURCES the sources of the library
+#   HEADERS the headers of the library (only for IDE support)
+#   OTHERS  other library related files (only for IDE support)
+# On return:
+#   Library target is defined and added to LIBRARY_FILES
+function(core_add_shared_library name)
+  cmake_parse_arguments(arg "WRAPPED" "OUTPUT_DIRECTORY" "" ${ARGN})
+  if(arg_OUTPUT_DIRECTORY)
+    set(OUTPUT_DIRECTORY ${arg_OUTPUT_DIRECTORY})
+  else()
+    if(NOT CORE_SYSTEM_NAME STREQUAL windows)
+      set(OUTPUT_DIRECTORY system)
+    endif()
+  endif()
+  if(CORE_SYSTEM_NAME STREQUAL windows)
+    set(OUTPUT_NAME lib${name})
+  else()
+    set(OUTPUT_NAME lib${name}-${ARCH})
   endif()
 
-  # IDE support
-  if(CMAKE_GENERATOR MATCHES "Xcode")
-    file(RELATIVE_PATH parentfolder ${CORE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/..)
-    set_target_properties(${name} PROPERTIES FOLDER "${parentfolder}")
-  elseif(CMAKE_GENERATOR MATCHES "Visual Studio")
-    file(RELATIVE_PATH foldername ${CORE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
-    set_target_properties(${name} PROPERTIES FOLDER "${foldername}")
-    source_group(" " REGULAR_EXPRESSION ".*")
+  if(NOT arg_WRAPPED OR CORE_SYSTEM_NAME STREQUAL windows)
+    add_library(${name} SHARED ${SOURCES} ${HEADERS} ${OTHERS})
+    set_target_properties(${name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${OUTPUT_DIRECTORY}
+                                             RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${OUTPUT_DIRECTORY}
+                                             RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/${OUTPUT_DIRECTORY}
+                                             RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/${OUTPUT_DIRECTORY}
+                                             OUTPUT_NAME ${OUTPUT_NAME} PREFIX "")
+
+    set(LIBRARY_FILES ${LIBRARY_FILES} ${CMAKE_BINARY_DIR}/${OUTPUT_DIRECTORY}/${OUTPUT_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX} CACHE STRING "" FORCE)
+    add_dependencies(${APP_NAME_LC}-libraries ${name})
+  else()
+    add_library(${name} STATIC ${SOURCES} ${HEADERS} ${OTHERS})
+    set_target_properties(${name} PROPERTIES POSITION_INDEPENDENT_CODE 1)
+    core_link_library(${name} ${OUTPUT_DIRECTORY}/lib${name})
   endif()
 endfunction()
 
-# Add a test library, and add sources to list for gtest integration macros
-function(core_add_test_library name)
-  # Backup the old SOURCES variable, since we'll append SUPPORT_SOURCES to it
-  set(TEST_ONLY_SOURCES ${SOURCES})
-  set(SOURCES ${SOURCES} ${SUPPORT_SOURCES})
-  core_add_library(${name} NO_MAIN_DEPENDS)
-  set_target_properties(${name} PROPERTIES EXCLUDE_FROM_ALL 1)
-  foreach(src ${TEST_ONLY_SOURCES})
-    # This will prepend CMAKE_CURRENT_SOURCE_DIR if the path is relative,
-    # otherwise use the absolute path.
-    get_filename_component(src_path "${src}" ABSOLUTE)
-    set(test_sources "${src_path}" ${test_sources} CACHE STRING "" FORCE)
+# Sets the compile language for all C source files in a target to CXX.
+# Needs to be called from the CMakeLists.txt that defines the target.
+# Arguments:
+#   target   target
+function(set_language_cxx target)
+  get_property(sources TARGET ${target} PROPERTY SOURCES)
+  foreach(file IN LISTS sources)
+    if(file MATCHES "\.c$")
+      set_source_files_properties(${file} PROPERTIES LANGUAGE CXX)
+    endif()
   endforeach()
-  set(test_archives ${test_archives} ${name} CACHE STRING "" FORCE)
 endfunction()
 
 # Add a data file to installation list with a mirror in build tree
+# Mirroring files in the buildtree allows to execute the app from there.
 # Arguments:
-#   file     full path to file to mirror
-#   relative the relative base of file path in the build/install tree
+#   file        full path to file to mirror
 # Optional Arguments:
-#   NO_INSTALL: exclude file from installation target
-# Implicit arguments:
-#   CORE_SOURCE_DIR - root of source tree
+#   NO_INSTALL: exclude file from installation target (only mirror)
+#   DIRECTORY:  directory where the file should be mirrored to
+#               (default: preserve tree structure relative to CORE_SOURCE_DIR)
 # On return:
 #   Files is mirrored to the build tree and added to ${install_data}
 #   (if NO_INSTALL is not given).
-function(copy_file_to_buildtree file relative)
-  cmake_parse_arguments(arg "NO_INSTALL" "" "" ${ARGN})
-  string(REPLACE "${relative}/" "" outfile ${file})
-  get_filename_component(outdir ${outfile} DIRECTORY)
+function(copy_file_to_buildtree file)
+  cmake_parse_arguments(arg "NO_INSTALL" "DIRECTORY" "" ${ARGN})
+  if(arg_DIRECTORY)
+    set(outdir ${arg_DIRECTORY})
+    get_filename_component(outfile ${file} NAME)
+    set(outfile ${outdir}/${outfile})
+  else()
+    string(REPLACE "${CORE_SOURCE_DIR}/" "" outfile ${file})
+    get_filename_component(outdir ${outfile} DIRECTORY)
+  endif()
 
   if(NOT TARGET export-files)
     file(REMOVE ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/ExportFiles.cmake)
     add_custom_target(export-files ALL COMMENT "Copying files into build tree"
                       COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/ExportFiles.cmake)
+    set_target_properties(export-files PROPERTIES FOLDER "Build Utilities")
+    file(APPEND ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/ExportFiles.cmake "# Export files to build tree\n")
   endif()
-  if(NOT ${CORE_SOURCE_DIR} MATCHES ${CMAKE_BINARY_DIR})
+
+  if(NOT file STREQUAL ${CMAKE_BINARY_DIR}/${outfile})
     if(VERBOSE)
       message(STATUS "copy_file_to_buildtree - copying file: ${file} -> ${CMAKE_BINARY_DIR}/${outfile}")
     endif()
     file(APPEND ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/ExportFiles.cmake
          "file(COPY \"${file}\" DESTINATION \"${CMAKE_BINARY_DIR}/${outdir}\")\n")
   endif()
+
   if(NOT arg_NO_INSTALL)
     list(APPEND install_data ${outfile})
     set(install_data ${install_data} PARENT_SCOPE)
@@ -121,12 +250,20 @@ function(copy_files_from_filelist_to_buildtree pattern)
       string(STRIP ${filename} filename)
       core_file_read_filtered(fstrings ${filename})
       foreach(dir ${fstrings})
-        file(GLOB_RECURSE files RELATIVE ${CORE_SOURCE_DIR} ${CORE_SOURCE_DIR}/${dir})
+        string(REPLACE " " ";" dir ${dir})
+        list(GET dir 0 src)
+        list(LENGTH dir len)
+        if(len EQUAL 1)
+          set(dest)
+        else()
+          list(GET dir -1 dest)
+        endif()
+        file(GLOB_RECURSE files RELATIVE ${CORE_SOURCE_DIR} ${CORE_SOURCE_DIR}/${src})
         foreach(file ${files})
           if(arg_NO_INSTALL)
-            copy_file_to_buildtree(${CORE_SOURCE_DIR}/${file} ${CORE_SOURCE_DIR} NO_INSTALL)
+            copy_file_to_buildtree(${CORE_SOURCE_DIR}/${file} DIRECTORY ${dest} NO_INSTALL)
           else()
-            copy_file_to_buildtree(${CORE_SOURCE_DIR}/${file} ${CORE_SOURCE_DIR})
+            copy_file_to_buildtree(${CORE_SOURCE_DIR}/${file} DIRECTORY ${dest})
           endif()
         endforeach()
       endforeach()
@@ -265,7 +402,7 @@ function(core_add_subdirs_from_filelist files)
       list(GET subdir  0 subdir_src)
       list(GET subdir -1 subdir_dest)
       if(VERBOSE)
-        message(STATUS "  core_add_subdirs_from_filelist - adding subdir: ${CORE_SOURCE_DIR}${subdir_src} -> ${CORE_BUILD_DIR}/${subdir_dest}")
+        message(STATUS "  core_add_subdirs_from_filelist - adding subdir: ${CORE_SOURCE_DIR}/${subdir_src} -> ${CORE_BUILD_DIR}/${subdir_dest}")
       endif()
       add_subdirectory(${CORE_SOURCE_DIR}/${subdir_src} ${CORE_BUILD_DIR}/${subdir_dest})
     endforeach()
@@ -327,11 +464,51 @@ macro(today RESULT)
     string(REGEX REPLACE "(..)/(..)/..(..).*" "\\1/\\2/\\3" ${RESULT} ${${RESULT}})
   else()
     message(SEND_ERROR "date not implemented")
-    set(${RESULT} 000000)
+    set(${RESULT} 00000000)
   endif()
   string(REGEX REPLACE "(\r?\n)+$" "" ${RESULT} "${${RESULT}}")
 endmacro()
 
+# Generates an RFC2822 timestamp
+#
+# The following variable is set:
+#   RFC2822_TIMESTAMP
+function(rfc2822stamp)
+  execute_process(COMMAND date -R
+                  OUTPUT_VARIABLE RESULT)
+  set(RFC2822_TIMESTAMP ${RESULT} PARENT_SCOPE)
+endfunction()
+
+# Generates an user stamp from git config info
+#
+# The following variable is set:
+#   PACKAGE_MAINTAINER - user stamp in the form of "username <username at example.com>"
+#                        if no git tree is found, value is set to "nobody <nobody at example.com>"
+function(userstamp)
+  find_package(Git)
+  if(GIT_FOUND AND EXISTS ${CORE_SOURCE_DIR}/.git)
+    execute_process(COMMAND ${GIT_EXECUTABLE} config user.name
+                    OUTPUT_VARIABLE username
+                    WORKING_DIRECTORY ${CORE_SOURCE_DIR}
+                    OUTPUT_STRIP_TRAILING_WHITESPACE)
+    execute_process(COMMAND ${GIT_EXECUTABLE} config user.email
+                    OUTPUT_VARIABLE useremail
+                    WORKING_DIRECTORY ${CORE_SOURCE_DIR}
+                    OUTPUT_STRIP_TRAILING_WHITESPACE)
+    set(PACKAGE_MAINTAINER "${username} <${useremail}>" PARENT_SCOPE)
+  else()
+    set(PACKAGE_MAINTAINER "nobody <nobody at example.com>" PARENT_SCOPE)
+  endif()
+endfunction()
+
+# Parses git info and sets variables used to identify the build
+#
+# The following variables are set:
+#   APP_SCMID - git HEAD commit in the form of 'YYYYMMDD-hash'
+#               if git tree is dirty, value is set in the form of 'YYYYMMDD-hash-dirty'
+#               if no git tree is found, value is set in the form of 'YYYYMMDD-nogitfound'
+#   GIT_HASH  - git HEAD commit in the form of 'hash'. if git tree is dirty,
+#               value is set in the form of 'hash-dirty'
 function(core_find_git_rev)
   find_package(Git)
   if(GIT_FOUND AND EXISTS ${CORE_SOURCE_DIR}/.git)
@@ -366,6 +543,7 @@ function(core_find_git_rev)
   set(GIT_REV "${DATE}-${HASH}")
   if(GIT_REV)
     set(APP_SCMID ${GIT_REV} PARENT_SCOPE)
+    set(GIT_HASH ${HASH} PARENT_SCOPE)
   endif()
 endfunction()
 
@@ -422,3 +600,4 @@ macro(core_find_versions)
     message(FATAL_ERROR "Could not determine add-on API version! Make sure that ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_guilib.h exists")
   endif()
 endmacro()
+
diff --git a/project/cmake/scripts/common/PrepareEnv.cmake b/project/cmake/scripts/common/PrepareEnv.cmake
index bf258d5..2d18602 100644
--- a/project/cmake/scripts/common/PrepareEnv.cmake
+++ b/project/cmake/scripts/common/PrepareEnv.cmake
@@ -45,9 +45,6 @@ file(COPY ${CORE_SOURCE_DIR}/project/cmake/scripts/common/AddonHelpers.cmake
           ${CORE_SOURCE_DIR}/project/cmake/scripts/common/AddOptions.cmake
      DESTINATION ${APP_LIB_DIR})
 
-# generate XBMCConfig.cmake for backwards compatibility to xbmc
-configure_file(${CORE_SOURCE_DIR}/project/cmake/XBMCConfig.cmake.in ${XBMC_LIB_DIR}/XBMCConfig.cmake @ONLY)
-
 ### copy all the addon binding header files to include/kodi
 # parse addon-bindings.mk to get the list of header files to copy
 file(STRINGS ${CORE_SOURCE_DIR}/xbmc/addons/addon-bindings.mk bindings)
diff --git a/project/cmake/scripts/common/ProjectMacros.cmake b/project/cmake/scripts/common/ProjectMacros.cmake
index f6a3c7d..653382c 100644
--- a/project/cmake/scripts/common/ProjectMacros.cmake
+++ b/project/cmake/scripts/common/ProjectMacros.cmake
@@ -23,18 +23,17 @@ endfunction()
 # Add a skin to installation list, mirroring it in build tree, packing textures
 # Arguments:
 #   skin     skin directory
-#   relative relative base path in build tree
 # On return:
 #   xbt is added to ${XBT_FILES}, data added to ${install_data}, mirror in build tree
-function(copy_skin_to_buildtree skin relative)
+function(copy_skin_to_buildtree skin)
   file(GLOB_RECURSE FILES ${skin}/*)
   file(GLOB_RECURSE MEDIA_FILES ${skin}/media/*)
   list(REMOVE_ITEM FILES ${MEDIA_FILES})
   foreach(file ${FILES})
-    copy_file_to_buildtree(${file} ${relative})
+    copy_file_to_buildtree(${file})
   endforeach()
   file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/${dest}/media)
-  string(REPLACE "${relative}/" "" dest ${skin})
+  string(REPLACE "${CORE_SOURCE_DIR}/" "" dest ${skin})
   pack_xbt(${skin}/media ${CMAKE_BINARY_DIR}/${dest}/media/Textures.xbt)
 
   file(GLOB THEMES RELATIVE ${skin}/themes ${skin}/themes/*)
diff --git a/project/cmake/scripts/freebsd/Install.cmake b/project/cmake/scripts/freebsd/Install.cmake
deleted file mode 100644
index 4d95d96..0000000
--- a/project/cmake/scripts/freebsd/Install.cmake
+++ /dev/null
@@ -1,60 +0,0 @@
-set(libdir ${CMAKE_INSTALL_PREFIX}/lib)
-set(bindir ${CMAKE_INSTALL_PREFIX}/bin)
-
-configure_file(${CORE_SOURCE_DIR}/tools/Linux/xbmc.sh.in
-               ${CORE_BUILD_DIR}/scripts/xbmc @ONLY)
-configure_file(${CORE_SOURCE_DIR}/tools/Linux/xbmc-standalone.sh.in
-               ${CORE_BUILD_DIR}/scripts/xbmc-standalone @ONLY)
-
-install(TARGETS xbmc-xrandr DESTINATION lib/xbmc)
-install(FILES ${addon_bindings} DESTINATION include/xbmc)
-install(FILES ${cmake_files} ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/modules/XBMCConfig.cmake
-        DESTINATION lib/xbmc)
-install(PROGRAMS ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/scripts/xbmc
-                 ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/scripts/xbmc-standalone
-        DESTINATION bin)
-install(FILES ${CORE_SOURCE_DIR}/tools/Linux/FEH.py
-        DESTINATION share/xbmc)
-
-install(FILES ${CORE_SOURCE_DIR}/tools/Linux/xbmc-xsession.desktop
-        RENAME XBMC.desktop
-        DESTINATION share/xsessions)
-                
-install(FILES ${CORE_SOURCE_DIR}/copying.txt
-              ${CORE_SOURCE_DIR}/LICENSE.GPL
-              ${CORE_SOURCE_DIR}/version.txt
-              ${CORE_SOURCE_DIR}/docs/README.freebsd
-        DESTINATION share/doc/xbmc)
-
-foreach(texture ${XBT_FILES})
-  string(REPLACE "${CMAKE_BINARY_DIR}/" "" dir ${texture})
-  get_filename_component(dir ${dir} PATH)
-  install(FILES ${texture}
-          DESTINATION share/xbmc/${dir})
-endforeach()
-
-foreach(wraplib ${WRAP_FILES})
-  get_filename_component(dir ${wraplib} PATH)
-  install(PROGRAMS ${CMAKE_BINARY_DIR}/${wraplib}
-          DESTINATION lib/xbmc/${dir})
-endforeach()
-
-foreach(file ${install_data})
-  get_filename_component(dir ${file} PATH)
-  install(FILES ${CMAKE_BINARY_DIR}/${file}
-          DESTINATION share/xbmc/${dir})
-endforeach()
-
-install(CODE "file(STRINGS ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/extra-installs dirs)
-              foreach(dir \${dirs})
-                file(GLOB_RECURSE FILES RELATIVE ${CMAKE_BINARY_DIR} \${dir}/*)
-                foreach(file \${FILES})
-                  get_filename_component(dir \${file} PATH)
-                  file(INSTALL \${file} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/xbmc/\${dir})
-                endforeach()
-              endforeach()")
-foreach(subdir ${build_dirs})
-  string(REPLACE " " ";" subdir ${subdir})
-  list(GET subdir 0 id)
-  install(CODE "execute_process(COMMAND make -C ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/${id}/src/${id}-build install)")
-endforeach()
diff --git a/project/cmake/scripts/freebsd/Install.cmake b/project/cmake/scripts/freebsd/Install.cmake
new file mode 120000
index 0000000..28ce012
--- /dev/null
+++ b/project/cmake/scripts/freebsd/Install.cmake
@@ -0,0 +1 @@
+../linux/Install.cmake
\ No newline at end of file
diff --git a/project/cmake/scripts/ios/Install.cmake b/project/cmake/scripts/ios/Install.cmake
index dee3d34..052565f 100644
--- a/project/cmake/scripts/ios/Install.cmake
+++ b/project/cmake/scripts/ios/Install.cmake
@@ -52,7 +52,7 @@ add_custom_target(bundle
             "WRAPPER_EXTENSION=app"
             "SRCROOT=${CMAKE_BINARY_DIR}"
             ${CORE_SOURCE_DIR}/tools/darwin/Support/copyframeworks-ios.command)
-add_dependencies(bundle ${APP_NAME_LC} export-files pack-skins wrap-libraries generate_json_header)
+add_dependencies(bundle ${APP_NAME_LC})
 
 set(DEPENDS_ROOT_FOR_XCODE ${NATIVEPREFIX}/..)
 configure_file(${CORE_SOURCE_DIR}/tools/darwin/packaging/ios/mkdeb-ios.sh.in
diff --git a/project/cmake/scripts/linux/ArchSetup.cmake b/project/cmake/scripts/linux/ArchSetup.cmake
index 1e4e88b..09675f1 100644
--- a/project/cmake/scripts/linux/ArchSetup.cmake
+++ b/project/cmake/scripts/linux/ArchSetup.cmake
@@ -16,8 +16,17 @@ else()
 endif()
 
 find_package(CXX11 REQUIRED)
+include(LDGOLD)
 
 if(ENABLE_LIRC)
   set(LIRC_DEVICE "\"/dev/lircd\"" CACHE STRING "LIRC device to use")
   set(DEP_DEFINES -DLIRC_DEVICE=${LIRC_DEVICE} -DHAVE_LIRC=1)
 endif()
+
+# Code Coverage
+if(CMAKE_BUILD_TYPE STREQUAL Coverage)
+  set(COVERAGE_TEST_BINARY ${APP_NAME_LC}-test)
+  set(COVERAGE_SOURCE_DIR ${CORE_SOURCE_DIR})
+  set(COVERAGE_DEPENDS "\${APP_NAME_LC}" "\${APP_NAME_LC}-test")
+  set(COVERAGE_EXCLUDES */test/* lib/* */lib/*)
+endif()
diff --git a/project/cmake/scripts/linux/CodeCoverage.cmake b/project/cmake/scripts/linux/CodeCoverage.cmake
new file mode 100644
index 0000000..efc2208
--- /dev/null
+++ b/project/cmake/scripts/linux/CodeCoverage.cmake
@@ -0,0 +1,97 @@
+# - CodeCoverage
+# Generate code coverage reports with LCOV and GCovr.
+#
+# Configuration:
+#  COVERAGE_SOURCE_DIR      - Source root directory (default ${CMAKE_SOURCE_DIR}).
+#  COVERAGE_BINARY_DIR      - Directory where the coverage reports (and intermediate files)
+#                             are generated to.
+#  COVERAGE_EXCLUDES        - List of exclude patterns (for example '*/tests/*').
+#
+# The following targets will be generated:
+#  coverage                 - Builds an html report. Requires LCOV.
+#  coverage_xml             - Builds an xml report (in Cobertura format for Jenkins).
+#                             Requires Gcovr.
+#
+# Inspired by https://github.com/bilke/cmake-modules/blob/master/CodeCoverage.cmake
+
+# Comiler and linker setup
+set(CMAKE_C_FLAGS_COVERAGE "-g -O0 --coverage" CACHE STRING
+  "Flags used by the C compiler during coverage builds." FORCE)
+set(CMAKE_CXX_FLAGS_COVERAGE "-g -O0 --coverage" CACHE STRING
+  "Flags used by the C++ compiler during coverage builds." FORCE)
+set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "--coverage" CACHE STRING
+  "Flags used for linking binaries during coverage builds." FORCE)
+set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "--coverage" CACHE STRING
+  "Flags used by the shared libraries linker during coverage builds." FORCE)
+mark_as_advanced(
+  CMAKE_C_FLAGS_COVERAGE CMAKE_CXX_FLAGS_COVERAGE CMAKE_EXE_LINKER_FLAGS_COVERAGE
+  CMAKE_SHARED_LINKER_FLAGS_COVERAGE CMAKE_STATIC_LINKER_FLAGS_COVERAGE
+)
+
+find_program(LCOV_EXECUTABLE lcov)
+find_program(GENINFO_EXECUTABLE geninfo)
+find_program(GENHTML_EXECUTABLE genhtml)
+find_program(GCOVR_EXECUTABLE gcovr)
+mark_as_advanced(LCOV_EXECUTABLE GENINFO_EXECUTABLE GENHTML_EXECUTABLE GCOVR_EXECUTABLE)
+
+# Default options
+if(NOT COVERAGE_SOURCE_DIR)
+  set(COVERAGE_SOURCE_DIR ${CMAKE_SOURCE_DIR})
+endif()
+if(NOT COVERAGE_BINARY_DIR)
+  set(COVERAGE_BINARY_DIR ${CMAKE_BINARY_DIR}/coverage)
+endif()
+if(NOT COVERAGE_EXCLUDES)
+  set(COVERAGE_EXCLUDES)
+endif()
+
+# Allow variables in COVERAGE_DEPENDS that are not evaluated before this file is included.
+string(CONFIGURE "${COVERAGE_DEPENDS}" COVERAGE_DEPENDS)
+
+# Add coverage target that generates an HTML report using LCOV
+if(LCOV_EXECUTABLE AND GENINFO_EXECUTABLE AND GENHTML_EXECUTABLE)
+  file(MAKE_DIRECTORY ${COVERAGE_BINARY_DIR})
+  add_custom_target(coverage
+    COMMAND ${CMAKE_COMMAND} -E make_directory ${COVERAGE_BINARY_DIR}
+    COMMAND ${LCOV_EXECUTABLE} -z -q -d ${CMAKE_BINARY_DIR}
+    COMMAND ${LCOV_EXECUTABLE} -c -q -i -d ${CMAKE_BINARY_DIR} -b ${COVERAGE_SOURCE_DIR}
+                               -o ${COVERAGE_BINARY_DIR}/${PROJECT_NAME}.coverage_base.info
+    COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target test || true
+    COMMAND ${LCOV_EXECUTABLE} -c -q -d ${CMAKE_BINARY_DIR} -b ${COVERAGE_SOURCE_DIR}
+                               -o ${COVERAGE_BINARY_DIR}/${PROJECT_NAME}.coverage_test.info
+    COMMAND ${LCOV_EXECUTABLE} -a ${COVERAGE_BINARY_DIR}/${PROJECT_NAME}.coverage_base.info
+                               -a ${COVERAGE_BINARY_DIR}/${PROJECT_NAME}.coverage_test.info
+                               -o ${COVERAGE_BINARY_DIR}/${PROJECT_NAME}.coverage.info -q
+    COMMAND ${LCOV_EXECUTABLE} -q -r ${COVERAGE_BINARY_DIR}/${PROJECT_NAME}.coverage.info
+                               /usr/include/* ${CMAKE_BINARY_DIR}/* ${COVERAGE_EXCLUDES}
+                               -o ${COVERAGE_BINARY_DIR}/${PROJECT_NAME}.coverage.info
+    COMMAND ${GENHTML_EXECUTABLE} ${COVERAGE_BINARY_DIR}/${PROJECT_NAME}.coverage.info
+                               -o ${COVERAGE_BINARY_DIR}/html -s --legend --highlight --demangle-cpp
+    COMMAND ${CMAKE_COMMAND} -E echo "Coverage report: file://${COVERAGE_BINARY_DIR}/html/index.html"
+    WORKING_DIRECTORY ${COVERAGE_BINARY_DIR}
+    VERBATIM
+    DEPENDS ${COVERAGE_DEPENDS}
+    COMMENT "Generate code coverage html report"
+  )
+else()
+  message(WARNING "Target coverage not available (lcov, geninfo and genhtml needed).")
+endif()
+
+# Add coverage target that generates an XML report using Gcovr
+if(GCOVR_EXECUTABLE)
+  file(MAKE_DIRECTORY ${COVERAGE_BINARY_DIR})
+  string(REGEX REPLACE "([^;]+)" "--exclude=\"\\1\"" _gcovr_excludes "${COVERAGE_EXCLUDES}")
+  string(REPLACE "*" ".*" _gcovr_excludes "${_gcovr_excludes}")
+  add_custom_target(coverage_xml
+    COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target test || true
+    COMMAND ${GCOVR_EXECUTABLE} -x -r ${COVERAGE_SOURCE_DIR} -o ${COVERAGE_BINARY_DIR}/coverage.xml
+                                --object-directory ${CMAKE_BINARY_DIR} ${_gcovr_excludes} ${CMAKE_BINARY_DIR}
+    COMMAND ${CMAKE_COMMAND} -E echo "Coverage report: file://${COVERAGE_BINARY_DIR}/coverage.xml"
+    WORKING_DIRECTORY ${COVERAGE_BINARY_DIR}
+    DEPENDS ${COVERAGE_DEPENDS}
+    COMMENT "Generate code coverage xml report"
+  )
+  unset(_gcovr_excludes)
+else()
+  message(WARNING "Target coverage_xml not available (gcovr needed).")
+endif()
diff --git a/project/cmake/scripts/linux/ExtraTargets.cmake b/project/cmake/scripts/linux/ExtraTargets.cmake
new file mode 100644
index 0000000..e0bd7e9
--- /dev/null
+++ b/project/cmake/scripts/linux/ExtraTargets.cmake
@@ -0,0 +1,10 @@
+# xrandr
+if(ENABLE_X11 AND XRANDR_FOUND)
+  add_executable(${APP_NAME_LC}-xrandr ${CORE_SOURCE_DIR}/xbmc-xrandr.c)
+  target_link_libraries(kodi-xrandr ${SYSTEM_LDFLAGS} ${X_LIBRARIES} m ${XRANDR_LIBRARIES})
+endif()
+
+# WiiRemote
+if(ENABLE_EVENTCLIENTS AND CORE_SYSTEM_NAME STREQUAL linux)
+  add_subdirectory(${CORE_SOURCE_DIR}/tools/EventClients/Clients/WiiRemote build/WiiRemote)
+endif()
diff --git a/project/cmake/scripts/linux/Install.cmake b/project/cmake/scripts/linux/Install.cmake
index 67cb2ee..c70f816 100644
--- a/project/cmake/scripts/linux/Install.cmake
+++ b/project/cmake/scripts/linux/Install.cmake
@@ -34,7 +34,6 @@ configure_file(${CORE_SOURCE_DIR}/tools/Linux/kodi.sh.in
 configure_file(${CORE_SOURCE_DIR}/tools/Linux/kodi-standalone.sh.in
                ${CORE_BUILD_DIR}/scripts/${APP_NAME_LC}-standalone @ONLY)
 
-
 # Configure cmake files
 configure_file(${PROJECT_SOURCE_DIR}/KodiConfig.cmake.in
                ${CORE_BUILD_DIR}/scripts/${APP_NAME}Config.cmake @ONLY)
@@ -43,31 +42,29 @@ configure_file(${PROJECT_SOURCE_DIR}/KodiConfig.cmake.in
 configure_file(${CORE_SOURCE_DIR}/tools/Linux/kodi-xsession.desktop.in
                ${CORE_BUILD_DIR}/${APP_NAME_LC}.desktop @ONLY)
 
-# Install cmake files
-# TODO: revisit, refactor and nuke txt file globbing
-install(FILES ${cmake_files} DESTINATION lib/${APP_NAME_LC})
-install(FILES ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/scripts/${APP_NAME}Config.cmake
-              ${PROJECT_SOURCE_DIR}/scripts/common/AddOptions.cmake
-              ${PROJECT_SOURCE_DIR}/scripts/common/AddonHelpers.cmake
-              ${PROJECT_SOURCE_DIR}/scripts/linux/PathSetup.cmake
-        DESTINATION lib/${APP_NAME_LC})
-
 # Install app
-install(TARGETS ${APP_NAME_LC} DESTINATION lib/${APP_NAME_LC})
+install(TARGETS ${APP_NAME_LC}
+        DESTINATION lib/${APP_NAME_LC}
+        COMPONENT kodi-bin)
 if(ENABLE_X11 AND XRANDR_FOUND)
-  install(TARGETS ${APP_NAME_LC}-xrandr DESTINATION lib/${APP_NAME_LC})
+  install(TARGETS ${APP_NAME_LC}-xrandr
+          DESTINATION lib/${APP_NAME_LC}
+          COMPONENT kodi-bin)
 endif()
 
 # Install scripts
 install(PROGRAMS ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/scripts/${APP_NAME_LC}
                  ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/scripts/${APP_NAME_LC}-standalone
-        DESTINATION bin)
+        DESTINATION bin
+        COMPONENT kodi)
 
 # Install libraries
-foreach(wraplib ${WRAP_FILES})
-  get_filename_component(dir ${wraplib} PATH)
-  install(PROGRAMS ${CMAKE_BINARY_DIR}/${wraplib}
-          DESTINATION lib/${APP_NAME_LC}/${dir})
+foreach(library ${LIBRARY_FILES})
+  get_filename_component(dir ${library} PATH)
+  string(REPLACE "${CMAKE_BINARY_DIR}/" "" dir ${dir})
+  install(PROGRAMS ${library}
+          DESTINATION lib/${APP_NAME_LC}/${dir}
+          COMPONENT kodi-bin)
 endforeach()
 
 # Install add-ons, fonts, icons, keyboard maps, keymaps, etc
@@ -75,61 +72,237 @@ endforeach()
 foreach(file ${install_data})
   get_filename_component(dir ${file} PATH)
   install(FILES ${CMAKE_BINARY_DIR}/${file}
-          DESTINATION share/${APP_NAME_LC}/${dir})
+          DESTINATION share/${APP_NAME_LC}/${dir}
+          COMPONENT kodi)
 endforeach()
 
-# Install add-on bindings
-install(FILES ${addon_bindings} DESTINATION include/${APP_NAME_LC})
-
 # Install xsession entry
 install(FILES ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/${APP_NAME_LC}.desktop
-        DESTINATION share/xsessions)
+        DESTINATION share/xsessions
+        COMPONENT kodi)
 
 # Install desktop entry
 install(FILES ${CORE_SOURCE_DIR}/tools/Linux/kodi.desktop
-        DESTINATION share/applications/${APP_NAME_LC}.desktop)
+        DESTINATION share/applications
+        COMPONENT kodi)
 
 # Install icons
 install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon16x16.png
         RENAME ${APP_NAME_LC}.png
-        DESTINATION share/icons/hicolor/16x16/apps)
+        DESTINATION share/icons/hicolor/16x16/apps
+        COMPONENT kodi)
 install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon22x22.png
         RENAME ${APP_NAME_LC}.png
-        DESTINATION share/icons/hicolor/22x22/apps)
+        DESTINATION share/icons/hicolor/22x22/apps
+        COMPONENT kodi)
 install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon24x24.png
         RENAME ${APP_NAME_LC}.png
-        DESTINATION share/icons/hicolor/24x24/apps)
+        DESTINATION share/icons/hicolor/24x24/apps
+        COMPONENT kodi)
 install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon32x32.png
         RENAME ${APP_NAME_LC}.png
-        DESTINATION share/icons/hicolor/32x32/apps)
+        DESTINATION share/icons/hicolor/32x32/apps
+        COMPONENT kodi)
 install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon48x48.png
         RENAME ${APP_NAME_LC}.png
-        DESTINATION share/icons/hicolor/48x48/apps)
+        DESTINATION share/icons/hicolor/48x48/apps
+        COMPONENT kodi)
 install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon64x64.png
         RENAME ${APP_NAME_LC}.png
-        DESTINATION share/icons/hicolor/64x64/apps)
+        DESTINATION share/icons/hicolor/64x64/apps
+        COMPONENT kodi)
 install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon128x128.png
         RENAME ${APP_NAME_LC}.png
-        DESTINATION share/icons/hicolor/128x128/apps)
+        DESTINATION share/icons/hicolor/128x128/apps
+        COMPONENT kodi)
 install(FILES ${CORE_SOURCE_DIR}/tools/Linux/packaging/media/icon256x256.png
         RENAME ${APP_NAME_LC}.png
-        DESTINATION share/icons/hicolor/256x256/apps)
+        DESTINATION share/icons/hicolor/256x256/apps
+        COMPONENT kodi)
 install(CODE "execute_process(COMMAND gtk-update-icon-cache -f -q -t
-        $ENV{DESTDIR}${datarootdir}/icons/hicolor ERROR_QUIET)")
+        $ENV{DESTDIR}${datarootdir}/icons/hicolor ERROR_QUIET)"
+        COMPONENT kodi)
 
 # Install docs
 install(FILES ${CORE_SOURCE_DIR}/copying.txt
               ${CORE_SOURCE_DIR}/LICENSE.GPL
               ${CORE_SOURCE_DIR}/version.txt
               ${CORE_SOURCE_DIR}/docs/README.linux
-        DESTINATION share/doc/${APP_NAME_LC})
+        DESTINATION share/doc/${APP_NAME_LC}
+        COMPONENT kodi)
+
+# Install kodi-tools-texturepacker
+install(PROGRAMS ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/texturepacker/TexturePacker
+        DESTINATION bin
+        COMPONENT kodi-tools-texturepacker)
+
+# Install kodi-addon-dev headers
+install(FILES ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_vfs_types.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_adsp.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_audioengine.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_guilib.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_inputstream.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_peripheral.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_addon.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_codec.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_pvr.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_addon_cpp_dll.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_addon_dll.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_addon_types.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_codec_types.h
+              ${CORE_SOURCE_DIR}/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxPacket.h
+              ${CORE_SOURCE_DIR}/xbmc/filesystem/IFileTypes.h
+        DESTINATION include/${APP_NAME_LC}
+        COMPONENT kodi-addon-dev)
+
+# Install kodi-addon-dev add-on bindings
+install(FILES ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/scripts/${APP_NAME}Config.cmake
+              ${CORE_SOURCE_DIR}/project/cmake/scripts/common/AddonHelpers.cmake
+              ${CORE_SOURCE_DIR}/project/cmake/scripts/common/AddOptions.cmake
+              ${CORE_SOURCE_DIR}/project/cmake/scripts/common/ArchSetup.cmake
+              ${CORE_SOURCE_DIR}/project/cmake/scripts/common/CheckCommits.cmake
+              ${CORE_SOURCE_DIR}/project/cmake/scripts/common/CheckTargetPlatform.cmake
+              ${CORE_SOURCE_DIR}/project/cmake/scripts/common/GenerateVersionedFiles.cmake
+              ${CORE_SOURCE_DIR}/project/cmake/scripts/common/GeneratorSetup.cmake
+              ${CORE_SOURCE_DIR}/project/cmake/scripts/common/HandleDepends.cmake
+              ${CORE_SOURCE_DIR}/project/cmake/scripts/common/Macros.cmake
+              ${CORE_SOURCE_DIR}/project/cmake/scripts/common/PrepareEnv.cmake
+              ${CORE_SOURCE_DIR}/project/cmake/scripts/common/ProjectMacros.cmake
+              ${CORE_SOURCE_DIR}/project/cmake/scripts/linux/PathSetup.cmake
+        DESTINATION lib/${APP_NAME_LC}
+        COMPONENT kodi-addon-dev)
+
+# Install kodi-audio-dev
+install(FILES ${CORE_SOURCE_DIR}/xbmc/cores/AudioEngine/Utils/AEChannelData.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_adsp_dll.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_adsp_types.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_audiodec_dll.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_audiodec_types.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_audioenc_dll.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_audioenc_types.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_audioengine_types.h
+        DESTINATION include/${APP_NAME_LC}
+        COMPONENT kodi-audio-dev)
+
+if(ENABLE_EVENTCLIENTS)
+  # Install kodi-eventclients-common BT python files
+  install(PROGRAMS ${CORE_SOURCE_DIR}/tools/EventClients/lib/python/bt/__init__.py
+                   ${CORE_SOURCE_DIR}/tools/EventClients/lib/python/bt/bt.py
+                   ${CORE_SOURCE_DIR}/tools/EventClients/lib/python/bt/hid.py
+          DESTINATION lib/python2.7/dist-packages/${APP_NAME_LC}/bt
+          COMPONENT kodi-eventclients-common)
+
+  # Install kodi-eventclients-common PS3 python files
+  install(PROGRAMS ${CORE_SOURCE_DIR}/tools/EventClients/lib/python/ps3/__init__.py
+                   ${CORE_SOURCE_DIR}/tools/EventClients/lib/python/ps3/keymaps.py
+                   ${CORE_SOURCE_DIR}/tools/EventClients/lib/python/ps3/sixaxis.py
+                   ${CORE_SOURCE_DIR}/tools/EventClients/lib/python/ps3/sixpair.py
+                   ${CORE_SOURCE_DIR}/tools/EventClients/lib/python/ps3/sixwatch.py
+          DESTINATION lib/python2.7/dist-packages/${APP_NAME_LC}/ps3
+          COMPONENT kodi-eventclients-common)
+
+  # Install kodi-eventclients-common python files
+  file(WRITE ${CMAKE_BINARY_DIR}/packages/deb/defs.py ICON_PATH="usr/share/pixmaps/${APP_NAME_LC}/")
+  install(PROGRAMS ${CMAKE_BINARY_DIR}/packages/deb/defs.py
+                   ${CORE_SOURCE_DIR}/tools/EventClients/lib/python/__init__.py
+                   "${CORE_SOURCE_DIR}/tools/EventClients/Clients/PS3 BD Remote/ps3_remote.py"
+                   ${CORE_SOURCE_DIR}/tools/EventClients/lib/python/xbmcclient.py
+                   ${CORE_SOURCE_DIR}/tools/EventClients/lib/python/zeroconf.py
+          DESTINATION lib/python2.7/dist-packages/${APP_NAME_LC}
+          COMPONENT kodi-eventclients-common)
+
+  # Install kodi-eventclients-common icons
+  install(FILES ${CORE_SOURCE_DIR}/tools/EventClients/icons/bluetooth.png
+                ${CORE_SOURCE_DIR}/tools/EventClients/icons/phone.png
+                ${CORE_SOURCE_DIR}/tools/EventClients/icons/mail.png
+                ${CORE_SOURCE_DIR}/tools/EventClients/icons/mouse.png
+          DESTINATION share/pixmaps/${APP_NAME_LC}
+          COMPONENT kodi-eventclients-common)
+
+  # Install kodi-eventclients-dev headers
+  install(FILES ${CORE_SOURCE_DIR}/tools/EventClients/lib/c++/xbmcclient.h
+          DESTINATION include/${APP_NAME_LC}
+          COMPONENT kodi-eventclients-dev)
+
+  # Install kodi-eventclients-dev C# examples
+  install(FILES "${CORE_SOURCE_DIR}/tools/EventClients/examples/c#/XBMCDemoClient1.cs"
+          DESTINATION "share/doc/${APP_NAME_LC}-eventclients-dev/examples/C#"
+          COMPONENT kodi-eventclients-dev)
+
+  # Install kodi-eventclients-dev C++ examples
+  install(FILES ${CORE_SOURCE_DIR}/tools/EventClients/examples/c++/example_notification.cpp
+                ${CORE_SOURCE_DIR}/tools/EventClients/examples/c++/example_log.cpp
+                ${CORE_SOURCE_DIR}/tools/EventClients/examples/c++/example_button1.cpp
+                ${CORE_SOURCE_DIR}/tools/EventClients/examples/c++/example_mouse.cpp
+                ${CORE_SOURCE_DIR}/tools/EventClients/examples/c++/example_button2.cpp
+          DESTINATION share/doc/${APP_NAME_LC}-eventclients-dev/examples/C++
+          COMPONENT kodi-eventclients-dev)
+
+  # Install kodi-eventclients-dev java examples
+  install(FILES ${CORE_SOURCE_DIR}/tools/EventClients/examples/java/XBMCDemoClient1.java
+          DESTINATION share/doc/${APP_NAME_LC}-eventclients-dev/examples/java
+          COMPONENT kodi-eventclients-dev)
+
+  # Install kodi-eventclients-dev python examples
+  install(PROGRAMS ${CORE_SOURCE_DIR}/tools/EventClients/examples/python/example_mouse.py
+                   ${CORE_SOURCE_DIR}/tools/EventClients/examples/python/example_button1.py
+                   ${CORE_SOURCE_DIR}/tools/EventClients/examples/python/example_notification.py
+                   ${CORE_SOURCE_DIR}/tools/EventClients/examples/python/example_action.py
+                   ${CORE_SOURCE_DIR}/tools/EventClients/examples/python/example_button2.py
+                   ${CORE_SOURCE_DIR}/tools/EventClients/examples/python/example_simple.py
+          DESTINATION share/doc/${APP_NAME_LC}-eventclients-dev/examples/python
+          COMPONENT kodi-eventclients-dev)
+
+  # Install kodi-eventclients-ps3
+  install(PROGRAMS "${CORE_SOURCE_DIR}/tools/EventClients/Clients/PS3 BD Remote/ps3_remote.py"
+          RENAME ${APP_NAME_LC}-ps3remote
+          DESTINATION bin
+          COMPONENT kodi-eventclients-ps3)
+
+  # Install kodi-eventclients-wiiremote
+  install(PROGRAMS ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/WiiRemote/${APP_NAME_LC}-wiiremote
+          DESTINATION bin
+          COMPONENT kodi-eventclients-wiiremote)
+
+  # Install kodi-eventclients-xbmc-send
+  install(PROGRAMS "${CORE_SOURCE_DIR}/tools/EventClients/Clients/Kodi Send/kodi-send.py"
+          RENAME ${APP_NAME_LC}-send
+          DESTINATION bin
+          COMPONENT kodi-eventclients-xbmc-send)
+endif()
+
+# Install kodi-inputstream-dev
+install(FILES ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_inputstream_dll.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_inputstream_types.h
+        DESTINATION include/${APP_NAME_LC}
+        COMPONENT kodi-inputstream-dev)
+
+# Install kodi-pvr-dev
+install(FILES ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_epg_types.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_dll.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_types.h
+        DESTINATION include/${APP_NAME_LC}
+        COMPONENT kodi-pvr-dev)
+
+# Install kodi-screensaver-dev
+install(FILES ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_scr_dll.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_scr_types.h
+        DESTINATION include/${APP_NAME_LC}
+        COMPONENT kodi-screensaver-dev)
+
+# Install kodi-visualization-dev
+install(FILES ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_vis_dll.h
+              ${CORE_SOURCE_DIR}/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_vis_types.h
+        DESTINATION include/${APP_NAME_LC}
+        COMPONENT kodi-visualization-dev)
 
 # Install XBT skin files
 foreach(texture ${XBT_FILES})
   string(REPLACE "${CMAKE_BINARY_DIR}/" "" dir ${texture})
   get_filename_component(dir ${dir} PATH)
   install(FILES ${texture}
-          DESTINATION share/${APP_NAME_LC}/${dir})
+          DESTINATION share/${APP_NAME_LC}/${dir}
+          COMPONENT kodi)
 endforeach()
 
 # Install extra stuff if it exists
@@ -151,33 +324,18 @@ foreach(subdir ${build_dirs})
   if(NOT subdir MATCHES kodi-platform)
     string(REPLACE " " ";" subdir ${subdir})
     list(GET subdir 0 id)
-    install(CODE "execute_process(COMMAND make -C ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/${id}/src/${id}-build install DESTDIR=${DESTDIR})")
+    install(CODE "execute_process(COMMAND ${CMAKE_MAKE_PROGRAM} -C ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/${id}/src/${id}-build install DESTDIR=${DESTDIR})")
   endif()
 endforeach()
 
-# Create xbmc -> kodi symlinks
-if(NOT EXISTS ${libdir}/xbmc)
-  install(CODE "execute_process(COMMAND ln -sf ${APP_NAME_LC}/ xbmc
-          WORKING_DIRECTORY ${libdir})")
-endif()
-if(NOT EXISTS ${includedir}/xbmc)
-  install(CODE "execute_process(COMMAND ln -sf ${APP_NAME_LC}/ xbmc
-          WORKING_DIRECTORY ${includedir})")
-endif()
-if(NOT EXISTS ${bindir}/xbmc)
-  install(CODE "execute_process(COMMAND ln -sf ${APP_NAME_LC} xbmc
-          WORKING_DIRECTORY ${bindir})")
-endif()
-if(NOT EXISTS ${bindir}/xbmc-standalone)
-  install(CODE "execute_process(COMMAND ln -sf ${APP_NAME_LC}-standalone xbmc-standalone
-          WORKING_DIRECTORY ${bindir})")
-endif()
-if(NOT EXISTS ${datarootdir}/xsessions/xbmc.desktop)
-  install(CODE "execute_process(COMMAND ln -sf ${APP_NAME_LC}.desktop xbmc.desktop
-          WORKING_DIRECTORY ${datarootdir}/xsessions/)")
-endif()
-if(NOT EXISTS ${datarootdir}/xbmc)
-  install(CODE "execute_process(COMMAND ln -sf ${APP_NAME_LC}/ xbmc
-          WORKING_DIRECTORY ${datarootdir})")
+# generate packages? yes please, if everything checks out
+if(CPACK_GENERATOR)
+  if(CPACK_GENERATOR STREQUAL DEB AND CORE_SYSTEM_NAME STREQUAL linux)
+    if(CMAKE_BUILD_TYPE STREQUAL Debug)
+      message(STATUS "DEB Generator: Build type is set to 'Debug'. Packaged binaries will be unstripped.")
+    endif()
+    include(${PROJECT_SOURCE_DIR}/cpack/CPackConfigDEB.cmake)
+  else()
+    message(FATAL_ERROR "DEB Generator: Can't configure CPack to generate Debian packages on non-linux systems.")
+  endif()
 endif()
-
diff --git a/project/cmake/scripts/linux/Macros.cmake b/project/cmake/scripts/linux/Macros.cmake
index 7453a1c..386c996 100644
--- a/project/cmake/scripts/linux/Macros.cmake
+++ b/project/cmake/scripts/linux/Macros.cmake
@@ -5,7 +5,7 @@ function(core_link_library lib wraplib)
   set(check_arg "")
   if(TARGET ${lib})
     set(target ${lib})
-    set(link_lib ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/${lib}/${lib}.a)
+    set(link_lib $<TARGET_FILE:${lib}>)
     set(check_arg ${ARGV2})
     set(data_arg  ${ARGV3})
   else()
@@ -14,11 +14,15 @@ function(core_link_library lib wraplib)
     set(check_arg ${ARGV3})
     set(data_arg ${ARGV4})
   endif()
+
+  # wrapper has to be adapted in order to support coverage.
+  if(CMAKE_BUILD_TYPE STREQUAL Coverage)
+    set(export "")
+  endif()
+
   if(check_arg STREQUAL export)
-    set(export ${export} 
+    set(export ${export}
         -Wl,--version-script=${ARGV3})
-  elseif(check_arg STREQUAL nowrap)
-    set(export ${data_arg})
   elseif(check_arg STREQUAL extras)
     foreach(arg ${data_arg})
       list(APPEND export ${arg})
@@ -29,13 +33,18 @@ function(core_link_library lib wraplib)
                      COMMAND cmake -E make_directory ${dir}
                      COMMAND ${CMAKE_C_COMPILER}
                      ARGS    -Wl,--whole-archive
-                             ${link_lib}
+                             "${link_lib}"
                              -Wl,--no-whole-archive -lm
                              -shared -o ${CMAKE_BINARY_DIR}/${wraplib}-${ARCH}${CMAKE_SHARED_MODULE_SUFFIX}
                              ${export}
                      DEPENDS ${target} wrapper.def wrapper)
-  list(APPEND WRAP_FILES ${wraplib}-${ARCH}${CMAKE_SHARED_MODULE_SUFFIX})
-  set(WRAP_FILES ${WRAP_FILES} PARENT_SCOPE)
+
+  get_filename_component(libname ${wraplib} NAME_WE)
+  add_custom_target(wrap_${libname} ALL DEPENDS ${wraplib}-${ARCH}${CMAKE_SHARED_MODULE_SUFFIX})
+  set_target_properties(wrap_${libname} PROPERTIES FOLDER lib/wrapped)
+  add_dependencies(${APP_NAME_LC}-libraries wrap_${libname})
+
+  set(LIBRARY_FILES ${LIBRARY_FILES} ${CMAKE_BINARY_DIR}/${wraplib}-${ARCH}${CMAKE_SHARED_MODULE_SUFFIX} CACHE STRING "" FORCE)
 endfunction()
 
 function(find_soname lib)
diff --git a/project/cmake/scripts/osx/ExtraTargets.cmake b/project/cmake/scripts/osx/ExtraTargets.cmake
new file mode 100644
index 0000000..ed9c089
--- /dev/null
+++ b/project/cmake/scripts/osx/ExtraTargets.cmake
@@ -0,0 +1,3 @@
+# XBMCHelper
+add_subdirectory(${CORE_SOURCE_DIR}/tools/EventClients/Clients/OSXRemote build/XBMCHelper)
+add_dependencies(${APP_NAME_LC} XBMCHelper)
diff --git a/project/cmake/scripts/osx/Install.cmake b/project/cmake/scripts/osx/Install.cmake
index 1f130d7..3924ccf 100644
--- a/project/cmake/scripts/osx/Install.cmake
+++ b/project/cmake/scripts/osx/Install.cmake
@@ -23,7 +23,8 @@ add_custom_target(bundle
             "FULL_PRODUCT_NAME=${APP_NAME}.app"
             "SRCROOT=${CMAKE_BINARY_DIR}"
             ${CORE_SOURCE_DIR}/tools/darwin/Support/copyframeworks-osx.command)
-add_dependencies(bundle ${APP_NAME_LC} export-files pack-skins wrap-libraries generate_json_header XBMCHelper)
+set_target_properties(bundle PROPERTIES FOLDER "Build Utilities")
+add_dependencies(bundle ${APP_NAME_LC})
 
 configure_file(${CORE_SOURCE_DIR}/tools/darwin/packaging/osx/mkdmg-osx.sh.in
                ${CMAKE_BINARY_DIR}/tools/darwin/packaging/osx/mkdmg-osx.sh @ONLY)
@@ -35,4 +36,5 @@ add_custom_target(dmg
                                                ${CMAKE_BINARY_DIR}/tools/darwin/packaging/media/osx/
     COMMAND ./mkdmg-osx.sh ${CORE_BUILD_CONFIG}
     WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tools/darwin/packaging/osx)
+set_target_properties(dmg PROPERTIES FOLDER "Build Utilities")
 add_dependencies(dmg bundle)
diff --git a/project/cmake/scripts/osx/Macros.cmake b/project/cmake/scripts/osx/Macros.cmake
index 48962a8..d8d5a6a 100644
--- a/project/cmake/scripts/osx/Macros.cmake
+++ b/project/cmake/scripts/osx/Macros.cmake
@@ -8,8 +8,8 @@ function(core_link_library lib wraplib)
   endif()
 
   set(export -bundle -undefined dynamic_lookup -read_only_relocs suppress
-             -Wl,-alias_list,${CORE_BUILD_DIR}/cores/dll-loader/exports/wrapper.def
-             ${CORE_BUILD_DIR}/${wrapper_obj})
+             -Wl,-alias_list,${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/cores/dll-loader/exports/wrapper.def
+             ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/${wrapper_obj})
   set(extension ${CMAKE_SHARED_MODULE_SUFFIX})
   set(check_arg "")
   if(TARGET ${lib})
@@ -26,9 +26,6 @@ function(core_link_library lib wraplib)
   if(check_arg STREQUAL export)
     set(export ${export}
         -Wl,--version-script=${ARGV3})
-  elseif(check_arg STREQUAL nowrap)
-    set(export -undefined dynamic_lookup -dynamiclib ${data_arg})
-    set(extension ${CMAKE_SHARED_LIBRARY_SUFFIX})
   elseif(check_arg STREQUAL extras)
     foreach(arg ${data_arg})
       list(APPEND export ${arg})
@@ -49,12 +46,12 @@ function(core_link_library lib wraplib)
                      DEPENDS ${target} wrapper.def wrapper
                      VERBATIM)
 
-  # Uncomment to create wrap_<lib> targets for debugging
-  #get_filename_component(libname ${wraplib} NAME_WE)
-  #add_custom_target(wrap_${libname} ALL DEPENDS ${wraplib}-${ARCH}${extension})
+  get_filename_component(libname ${wraplib} NAME_WE)
+  add_custom_target(wrap_${libname} ALL DEPENDS ${wraplib}-${ARCH}${extension})
+  set_target_properties(wrap_${libname} PROPERTIES FOLDER lib/wrapped)
+  add_dependencies(${APP_NAME_LC}-libraries wrap_${libname})
 
-  list(APPEND WRAP_FILES ${wraplib}-${ARCH}${extension})
-  set(WRAP_FILES ${WRAP_FILES} PARENT_SCOPE)
+  set(LIBRARY_FILES ${LIBRARY_FILES} ${CMAKE_BINARY_DIR}/${wraplib}-${ARCH}${extension} CACHE STRING "" FORCE)
 endfunction()
 
 function(find_soname lib)
diff --git a/project/cmake/scripts/windows/ArchSetup.cmake b/project/cmake/scripts/windows/ArchSetup.cmake
index ae815ce..b912dcb 100644
--- a/project/cmake/scripts/windows/ArchSetup.cmake
+++ b/project/cmake/scripts/windows/ArchSetup.cmake
@@ -5,7 +5,7 @@ set(ARCH win32)
 
 # -------- Paths (mainly for find_package) ---------
 
-set(PLATFORM_DIR win32)
+set(PLATFORM_DIR platform/win32)
 
 # Precompiled headers fail with per target output directory. (needs CMake 3.1)
 set(PRECOMPILEDHEADER_DIR ${PROJECT_BINARY_DIR}/${CORE_BUILD_CONFIG}/objs)
@@ -35,6 +35,9 @@ if(CMAKE_GENERATOR MATCHES "Visual Studio")
   set(CMAKE_CXX_FLAGS "/MP /FS ${CMAKE_CXX_FLAGS}")
 endif()
 
+# Google Test needs to use shared version of runtime libraries
+set(gtest_force_shared_crt ON CACHE STRING "" FORCE)
+
 
 # -------- Linker options ---------
 
@@ -77,4 +80,11 @@ set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OP
 
 if(CMAKE_GENERATOR MATCHES "Visual Studio")
   set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+
+  # Generate a batch file that opens Visual Studio with the necessary env variables set.
+  file(WRITE ${CMAKE_BINARY_DIR}/kodi-sln.bat
+             "@echo off\n"
+             "set KODI_HOME=%~dp0\n"
+             "set PATH=%~dp0\\system\n"
+             "start %~dp0\\${PROJECT_NAME}.sln")
 endif()
diff --git a/project/cmake/scripts/windows/Macros.cmake b/project/cmake/scripts/windows/Macros.cmake
index f4cef0e..2d3500d 100644
--- a/project/cmake/scripts/windows/Macros.cmake
+++ b/project/cmake/scripts/windows/Macros.cmake
@@ -1,29 +1,5 @@
 function(core_link_library lib wraplib)
-  # On Windows there is no need to wrap libraries.
-  # Since we cannot build a DLL from an existing LIB, we simply compile the DLL.
-  # TODO: core_add_library and core_link_library should be refactored so that we have
-  #       decoupled functions for generating the shared libraries. Libs that are not
-  #       wrapped should directly be compiled into shared libs.
-  if(TARGET ${lib})
-    get_property(SOURCES TARGET ${lib} PROPERTY SOURCES)
-    get_property(SOURCE_DIR TARGET ${lib} PROPERTY SOURCE_DIR)
-    get_property(INCLUDES TARGET ${lib} PROPERTY INCLUDE_DIRECTORIES)
-    get_property(DEFINITIONS TARGET ${lib} PROPERTY COMPILE_DEFINITIONS)
-    foreach(source IN LISTS SOURCES)
-      list(APPEND SOURCES_ABS ${SOURCE_DIR}/${source})
-    endforeach()
-
-    add_library(wrap_${lib} SHARED ${SOURCES_ABS})
-    set_target_properties(wrap_${lib} PROPERTIES OUTPUT_NAME lib${lib})
-    target_include_directories(wrap_${lib} PRIVATE ${INCLUDES})
-    target_compile_definitions(wrap_${lib} PRIVATE ${DEFINITIONS})
-    
-    if(MSVC)
-      string(REPLACE "/lib${lib}" "" libdir ${wraplib})
-      set_target_properties(wrap_${lib} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/${libdir}"
-                                                   RUNTIME_OUTPUT_DIRECTORY_DEBUG   "${CMAKE_BINARY_DIR}/${libdir}")
-    endif()
-  endif()
+  message(AUTHOR_WARNING "core_link_library is not compatible with windows.")
 endfunction()
 
 function(find_soname lib)
@@ -76,7 +52,8 @@ function(add_precompiled_header target pch_header pch_source)
     if(NOT TARGET ${PCH_PCH_TARGET}_pch)
       add_library(${PCH_PCH_TARGET}_pch STATIC ${pch_source})
       set_target_properties(${PCH_PCH_TARGET}_pch PROPERTIES COMPILE_PDB_NAME vc140
-                                                             COMPILE_PDB_OUTPUT_DIRECTORY ${PRECOMPILEDHEADER_DIR})
+                                                             COMPILE_PDB_OUTPUT_DIRECTORY ${PRECOMPILEDHEADER_DIR}
+                                                             FOLDER "Build Utilities")
     endif()
     # From VS2012 onwards, precompiled headers have to be linked against (LNK2011).
     target_link_libraries(${target} PUBLIC ${PCH_PCH_TARGET}_pch)
@@ -87,47 +64,3 @@ function(add_precompiled_header target pch_header pch_source)
     target_sources(${target} PRIVATE ${pch_source})
   endif()
 endfunction()
-
-# Adds an FX-compiled shader to a target
-#   Creates a custom command that FX-compiles the given shader and adds the
-#   generated header file to the given target.
-# Arguments:
-#   target Target to add the FX-compiled shader to
-#   hlsl HLSL shader input file
-#   profile HLSL profile that specifies the shader model
-#   entrypoint Shader entry point
-# On return:
-#   FXC_FILE is set to the name of the generated header file.
-function(add_shader_dx target hlsl profile entrypoint)
-  get_filename_component(file ${hlsl} NAME_WE)
-  add_custom_command(OUTPUT ${file}.h
-                     COMMAND ${FXC} /Fh ${file}.h
-                                    /E ${entrypoint}
-                                    /T ${profile}
-                                    /Vn ${file}
-                                    /Qstrip_reflect
-                                    ${hlsl}
-                     DEPENDS ${hlsl}
-                     COMMENT "FX compile ${hlsl}"
-                     VERBATIM)
-  target_sources(${target} PRIVATE ${file}.h)
-  target_include_directories(${target} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
-endfunction()
-
-# Copies the main dlls to the root of the buildtree
-# On return:
-#   files added to ${install_data}, mirror in build tree
-function(copy_main_dlls_to_buildtree)
-  set(dir ${PROJECT_SOURCE_DIR}/../Win32BuildSetup/dependencies)
-  file(GLOB_RECURSE files ${dir}/*)
-  foreach(file ${files})
-    copy_file_to_buildtree(${file} ${dir})
-  endforeach()
-
-  if(D3DCOMPILER_DLL)
-    get_filename_component(d3dcompiler_dir ${D3DCOMPILER_DLL} DIRECTORY)
-    copy_file_to_buildtree(${D3DCOMPILER_DLL} ${d3dcompiler_dir})
-  endif()
-
-  set(install_data ${install_data} PARENT_SCOPE)
-endfunction()
diff --git a/project/cmake/treedata/freebsd/subdirs.txt b/project/cmake/treedata/freebsd/subdirs.txt
index faff03c..df2fa76 100644
--- a/project/cmake/treedata/freebsd/subdirs.txt
+++ b/project/cmake/treedata/freebsd/subdirs.txt
@@ -1,4 +1,13 @@
-xbmc/linux   linuxsupport
-xbmc/input/linux input/linux
-xbmc/network/linux network/linux
-xbmc/freebsd freebsdsupport
+xbmc/linux                 linuxsupport
+xbmc/linux/sse4            sse4
+xbmc/input/linux           input/linux
+xbmc/input/touch           input/touch
+xbmc/input/touch/generic   input/touch/generic
+xbmc/network/linux         network/linux
+xbmc/peripherals/bus/linux peripherals/bus/linux
+xbmc/powermanagement/linux powermanagement/linux
+xbmc/storage/linux         storage/linux
+xbmc/filesystem/posix      filesystem/posix
+xbmc/utils/posix           utils_posix
+xbmc/platform/posix        posix
+xbmc/freebsd               freebsdsupport
diff --git a/project/cmake/treedata/windows/subdirs.txt b/project/cmake/treedata/windows/subdirs.txt
index 60c0095..e52d2f6 100644
--- a/project/cmake/treedata/windows/subdirs.txt
+++ b/project/cmake/treedata/windows/subdirs.txt
@@ -1,4 +1,4 @@
-xbmc/win32                   win32support
+xbmc/platform/win32          platform_win32
 xbmc/input/windows           input/windows
 xbmc/input/touch             input/touch
 xbmc/input/touch/generic     input/touch/generic
@@ -9,7 +9,6 @@ xbmc/powermanagement/windows powermanagement/windows
 xbmc/storage/windows         storage/windows
 xbmc/filesystem/win32        filesystem/win32
 xbmc/utils/win32             utils_win32
-xbmc/platform/win32          platform_win32
 xbmc/rendering/dx            rendering_dx
 xbmc/threads/platform/win    threads_win
 xbmc/windowing/windows       windowing/windows
diff --git a/system/keyboardlayouts/slovak.xml b/system/keyboardlayouts/slovak.xml
new file mode 100644
index 0000000..5737079
--- /dev/null
+++ b/system/keyboardlayouts/slovak.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+Please use English language names instead.
+Default font lacks support for all characters
+-->
+<keyboardlayouts>
+  <layout language="Slovak" layout="QWERTZ">
+    <keyboard>
+      <row>ĺľščťžýáíéó_</row>
+      <row>qwertzuiopúä</row>
+      <row>asdfghjklôďň</row>
+      <row>/yxcvbnmŕ:.-</row>
+    </keyboard>
+    <keyboard modifiers="shift">
+      <row>ĹĽŠČŤŽÝÁÍÉÓ_</row>
+      <row>QWERTZUIOPÚÄ</row>
+      <row>ASDFGHJKLÔĎŇ</row>
+      <row>\YXCVBNMÅ”:.-</row>
+    </keyboard>
+    <keyboard modifiers="symbol,shift+symbol">
+      <row>1234567890%</row>
+      <row>+@#$~^&*{}=</row>
+      <row>[]()/"'`;!</row>
+      <row>\|<>,.?:-_</row>
+    </keyboard>
+  </layout>
+  <layout language="Slovak" layout="QWERTY">
+    <keyboard>
+      <row>ĺľščťžýáíéó_</row>
+      <row>qwertyuiopúä</row>
+      <row>asdfghjklôďň</row>
+      <row>/zxcvbnmŕ:.-</row>
+    </keyboard>
+    <keyboard modifiers="shift">
+      <row>ĹĽŠČŤŽÝÁÍÉÓ_</row>
+      <row>QWERTYUIOPÚÄ</row>
+      <row>ASDFGHJKLÔĎŇ</row>
+      <row>\ZXCVBNMÅ”:.-</row>
+    </keyboard>
+    <keyboard modifiers="symbol,shift+symbol">
+      <row>1234567890%</row>
+      <row>+@#$~^&*{}=</row>
+      <row>[]()/"'`;!</row>
+      <row>\|<>,.?:-_</row>
+    </keyboard>
+  </layout>
+  <layout language="Slovak" layout="ABC">
+    <keyboard>
+      <row>aáäbcčdďeéfg</row>
+      <row>hiíjklĺľmnňo</row>
+      <row>óôpqrŕsštťuú</row>
+      <row>vwxyýzž:./\@</row>
+    </keyboard>
+    <keyboard modifiers="shift">
+      <row>AÁÄBCČDĎEÉFG</row>
+      <row>HIÍJKLĹĽMNŇO</row>
+      <row>ÓÔPQRŔSŠTŤUÚ</row>
+      <row>VWXYÝZŽ:./\@</row>
+    </keyboard>
+    <keyboard modifiers="symbol,shift+symbol">
+      <row>1234567890%</row>
+      <row>+@#$~^&*{}=</row>
+      <row>[]()/"'`;!</row>
+      <row>\|<>,.?:-_</row>
+    </keyboard>
+  </layout>
+</keyboardlayouts>
diff --git a/system/keymaps/customcontroller.Harmony.xml b/system/keymaps/customcontroller.Harmony.xml
index 6666f11..50d82d9 100644
--- a/system/keymaps/customcontroller.Harmony.xml
+++ b/system/keymaps/customcontroller.Harmony.xml
@@ -103,7 +103,7 @@
       <!-- pwrToggle   -->   <button id="166">ShutDown()</button>
       <!-- Queue	-->      <button id="162">Queue</button>
       <!-- Sleep	-->      <button id="146">Suspend()</button>
-      <!-- Red		-->      <button id="183">CodecInfo</button>
+      <!-- Red		-->      <button id="183">PlayerProcessInfo</button>
       <!-- Green	-->      <button id="184">ActivateWindow(Settings)</button>
       <!-- Yellow	-->      <button id="185">xbmc.ActivateWindow(SystemSettings)</button>
       <!-- Blue		-->      <button id="186">ActivateWindow(SystemInfo)</button>
@@ -201,7 +201,7 @@
   <MusicOSD>
     <customcontroller name="Harmony">
       <!-- menu       	-->      <button id="106">Back</button>
-      <!-- Info  	-->      <button id="131">CodecInfo</button>
+      <!-- Info  	-->      <button id="131">PlayerProcessInfo</button>
     </customcontroller>
   </MusicOSD>
   <AddonSettings>
diff --git a/system/keymaps/gamepad.xml b/system/keymaps/gamepad.xml
index ab298f0..a9d1c65 100644
--- a/system/keymaps/gamepad.xml
+++ b/system/keymaps/gamepad.xml
@@ -88,7 +88,7 @@
       <A>Pause</A>
       <B>Stop</B>
       <Y>AspectRatio</Y>
-      <black>CodecInfo</black>
+      <black>PlayerProcessInfo</black>
       <white>Info</white>
       <back>Seek(-7)</back><!-- Replaces smallstepback -->
       <start>OSD</start>
@@ -119,7 +119,7 @@
   <FullscreenInfo>
     <gamepad>
       <start>OSD</start>
-      <black>CodecInfo</black>
+      <black>PlayerProcessInfo</black>
       <white>Back</white>
       <leftanalogtrigger>AnalogRewind</leftanalogtrigger>
       <rightanalogtrigger>AnalogFastForward</rightanalogtrigger>
@@ -135,7 +135,7 @@
       <A>Pause</A>
       <B>Stop</B>
       <Y>ActivateWindow(VisualisationPresetList)</Y>
-      <black>CodecInfo</black>
+      <black>PlayerProcessInfo</black>
       <white>Info</white>
       <start>OSD</start>
       <back>LockPreset</back>
@@ -150,7 +150,7 @@
   <MusicOSD>
     <gamepad>
       <start>Back</start>
-      <black>CodecInfo</black>
+      <black>PlayerProcessInfo</black>
       <white>Info</white>
       <leftanalogtrigger>AnalogRewind</leftanalogtrigger>
       <rightanalogtrigger>AnalogFastForward</rightanalogtrigger>
@@ -177,7 +177,7 @@
       <B>Stop</B>
       <Y>Rotate</Y>
       <X>ZoomNormal</X>
-      <black>CodecInfo</black>
+      <black>Info</black>
       <white>Info</white>
       <righttrigger>NextPicture</righttrigger>
       <lefttrigger>PreviousPicture</lefttrigger>
@@ -207,7 +207,7 @@
   <VideoOSD>
     <gamepad>
       <start>Back</start>
-      <black>CodecInfo</black>
+      <black>PlayerProcessInfo</black>
       <white>Info</white>
       <leftanalogtrigger>AnalogRewind</leftanalogtrigger>
       <rightanalogtrigger>AnalogFastForward</rightanalogtrigger>
@@ -219,7 +219,7 @@
       <B>Stop</B>
       <start>OSD</start>
       <white>Info</white>
-      <black>CodecInfo</black>
+      <black>PlayerProcessInfo</black>
       <leftanalogtrigger>AnalogRewind</leftanalogtrigger>
       <rightanalogtrigger>AnalogFastForward</rightanalogtrigger>
     </gamepad>
@@ -229,7 +229,7 @@
       <X/>
       <Y>AspectRatio</Y>
       <start>Back</start>
-      <black>CodecInfo</black>
+      <black>PlayerProcessInfo</black>
       <white>Info</white>
       <leftanalogtrigger>AnalogRewind</leftanalogtrigger>
       <rightanalogtrigger>AnalogFastForward</rightanalogtrigger>
@@ -240,7 +240,7 @@
       <X/>
       <Y>AspectRatio</Y>
       <start>Back</start>
-      <black>CodecInfo</black>
+      <black>PlayerProcessInfo</black>
       <white>Info</white>
       <leftanalogtrigger>AnalogRewind</leftanalogtrigger>
       <rightanalogtrigger>AnalogFastForward</rightanalogtrigger>
@@ -315,4 +315,9 @@
       <dpadright>NextPicture</dpadright>
     </gamepad>
   </PictureInfo>
+  <PlayerProcessInfo>
+    <gamepad>
+      <black>PlayerProcessInfo</black>
+    </gamepad>
+  </PlayerProcessInfo>
 </keymap>
diff --git a/system/keymaps/joystick.xml b/system/keymaps/joystick.xml
index 516726d..6b7aa92 100644
--- a/system/keymaps/joystick.xml
+++ b/system/keymaps/joystick.xml
@@ -141,7 +141,7 @@
       <b>Stop</b>
       <y>ZoomNormal</y>
       <leftbumper>Rotate</leftbumper>
-      <rightbumper>CodecInfo</rightbumper>
+      <rightbumper>Info</rightbumper>
       <up>ZoomIn</up>
       <down>ZoomOut</down>
       <left>PreviousPicture</left>
diff --git a/system/keymaps/keyboard.xml b/system/keymaps/keyboard.xml
index b898242..90517af 100644
--- a/system/keymaps/keyboard.xml
+++ b/system/keymaps/keyboard.xml
@@ -12,7 +12,7 @@
 <!-- not used in the current window's section.                                            -->
 <!--                                                                                      -->
 <!-- Actions can be built-in functions.                                                   -->
-<!--  eg <B>ActivateWindow(Music)</B>                                                   -->
+<!--  eg <B>ActivateWindow(Music)</B>                                                     -->
 <!-- would automatically go to Music on the press of the B button.                        -->
 <!--                                                                                      -->
 <!--  Long presses                                                                        -->
@@ -123,6 +123,7 @@
       <prev_track>SkipPrevious</prev_track>
       <stop>Stop</stop>
       <play_pause>PlayPause</play_pause>
+      <play_pause mod="longpress">Info</play_pause>
       <fastforward>FastForward</fastforward>
       <rewind>Rewind</rewind>
       <record/>
@@ -188,6 +189,7 @@
       <backspace>Backspace</backspace>
       <browser_back>Backspace</browser_back>
       <browser_back mod="longpress">PreviousMenu</browser_back>
+      <play_pause mod="longpress">Enter</play_pause>
     </keyboard>
   </VirtualKeyboard>
   <MyTVChannels>
@@ -311,7 +313,7 @@
       <m>OSD</m>
       <menu>OSD</menu>
       <i>Info</i>
-      <o>CodecInfo</o>
+      <o>PlayerProcessInfo</o>
       <z>AspectRatio</z>
       <zoom>AspectRatio</zoom>
       <t>ShowSubtitles</t>
@@ -321,6 +323,10 @@
       <right>StepForward</right>
       <up>ChapterOrBigStepForward</up>
       <down>ChapterOrBigStepBack</down>
+      <left mod="longpress">Rewind</left>
+      <right mod="longpress">FastForward</right>
+      <up mod="longpress">AudioNextLanguage</up>
+      <down mod="longpress">NextSubtitle</down>
       <a>AudioDelay</a>
       <escape>Fullscreen</escape>
       <c>Playlist</c>
@@ -343,7 +349,7 @@
       <f>FastForward</f>
       <r>Rewind</r>
       <period>StepForward</period>
-      <o>CodecInfo</o>
+      <o>PlayerProcessInfo</o>
       <i>Back</i>
       <d mod="ctrl">Back</d>
       <m>OSD</m>
@@ -368,7 +374,9 @@
       <browser_back>Fullscreen</browser_back>
       <browser_back mod="longpress">Stop</browser_back>
       <return>OSD</return>
+      <return mod="longpress">PlayPause</return>
       <enter>OSD</enter>
+      <enter mod="longpress">PlayPause</enter>
       <m>OSD</m>
       <menu>OSD</menu>
       <i>Info</i>
@@ -378,9 +386,11 @@
       <n>ActivateWindow(MusicPlaylist)</n>
       <left>StepBack</left>
       <right>StepForward</right>
+      <left mod="longpress">Rewind</left>
+      <right mod="longpress">FastForward</right>
       <up>SkipNext</up>
       <down>SkipPrevious</down>
-      <o>CodecInfo</o>
+      <o>PlayerProcessInfo</o>
       <l>LockPreset</l>
       <escape>FullScreen</escape>
       <g>ActivateWindow(PVROSDGuide)</g>
@@ -396,7 +406,7 @@
       <m>Back</m>
       <menu>Back</menu>
       <i>Info</i>
-      <o>CodecInfo</o>
+      <o>PlayerProcessInfo</o>
       <p>ActivateWindow(VisualisationPresetList)</p>
       <v>Addon.Default.OpenSettings(xbmc.player.musicviz)</v>
       <text>Addon.Default.OpenSettings(xbmc.player.musicviz)</text>
@@ -411,7 +421,7 @@
       <comma>SkipPrevious</comma>
       <m>Back</m>
       <i>Info</i>
-      <o>CodecInfo</o>
+      <o>PlayerProcessInfo</o>
       <p>Back</p>
       <v>Back</v>
       <text>Back</text>
@@ -431,7 +441,7 @@
       <eight>ZoomLevel8</eight>
       <nine>ZoomLevel9</nine>
       <i>Info</i>
-      <o>CodecInfo</o>
+      <o>Info</o>
       <period>NextPicture</period>
       <comma>PreviousPicture</comma>
       <plus>ZoomIn</plus>
@@ -463,7 +473,7 @@
       <menu>Back</menu>
       <g mod="ctrl">Back</g> <!-- MCE Guide button -->
       <i>Info</i>
-      <o>CodecInfo</o>
+      <o>PlayerProcessInfo</o>
     </keyboard>
   </VideoOSD>
   <VideoMenu>
@@ -473,7 +483,7 @@
       <m>OSD</m>
       <menu>OSD</menu>
       <i>Info</i>
-      <o>CodecInfo</o>
+      <o>PlayerProcessInfo</o>
       <z>AspectRatio</z>
       <zoom>AspectRatio</zoom>
       <t>ShowSubtitles</t>
@@ -489,13 +499,13 @@
   <OSDVideoSettings>
     <keyboard>
       <i>Info</i>
-      <o>CodecInfo</o>
+      <o>PlayerProcessInfo</o>
     </keyboard>
   </OSDVideoSettings>
   <OSDAudioSettings>
     <keyboard>
       <i>Info</i>
-      <o>CodecInfo</o>
+      <o>PlayerProcessInfo</o>
     </keyboard>
   </OSDAudioSettings>
   <VideoBookmarks>
@@ -686,4 +696,9 @@
       <backspace mod="longpress">ActivateWindow(Home)</backspace>
     </keyboard>
   </Weather>
+  <PlayerProcessInfo>
+    <keyboard>
+      <o>PlayerProcessInfo</o>
+    </keyboard>
+  </PlayerProcessInfo>
 </keymap>
diff --git a/system/keymaps/remote.xml b/system/keymaps/remote.xml
index 2220ae4..dedcc9b 100644
--- a/system/keymaps/remote.xml
+++ b/system/keymaps/remote.xml
@@ -1,45 +1,28 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- This file contains the mapping of keys (gamepad, remote, and keyboard) to actions within XBMC -->
-<!-- The <global> section is a fall through - they will only be used if the button is not          -->
-<!-- used in the current window's section.  Note that there is only handling                       -->
-<!-- for a single action per button at this stage.                                                 -->
-<!-- For joystick/gamepad configuration under linux/win32, see below as it differs from xbox       -->
-<!-- gamepads.                                                                                     -->
-
-<!-- The format is:                      -->
-<!--    <device>                         -->
-<!--      <button>action</button>        -->
-<!--    </device>                        -->
-
-<!-- To map keys from other remotes using the RCA protocol, you may add <universalremote> blocks -->
-<!-- In this case, the tags used are <obc#> where # is the original button code (OBC) of the key -->
-<!-- You set it up by adding a <universalremote> block to the window or <global> section:       -->
-<!--    <universalremote>             -->
-<!--       <obc45>Stop</obc45>         -->
-<!--    </universalremote>            -->
-
-<!-- Note that the action can be a built-in function.                                         -->
-<!--  eg <B>ActivateWindow(Music)</B>                                                       -->
-<!-- would automatically go to My Music on the press of the B button.                         -->
-<!-- An empty action removes the corresponding mapping from the default keymap                -->
-
-<!-- Joysticks / Gamepads:                                                                    -->
-<!--   See the sample PS3 controller configuration below for the format.                      -->
-<!--                                                                                          -->
-<!--  Joystick Name:                                                                          -->
-<!--   Do 'cat /proc/bus/input/devices' or see your xbmc log file  to find the names of       -->
-<!--   detected joysticks. The name used in the configuration should match the detected name. -->
-<!--                                                                                          -->
-<!--  Button Ids:                                                                             -->
-<!--   'id' is the button ID used by SDL. Joystick button ids of connected joysticks appear   -->
-<!--   in xbmc.log when they are pressed. Use your log to map custom buttons to actions.      -->
-<!--                                                                                          -->
-<!--  Axis Ids / Analog Controls                                                              -->
-<!--   Coming soon.                                                                           -->
-<!--                                                                                          -->
-<!--  Long presses                                                                            -->
-<!--   A limitation is that if a single press is mapped in a section, a global "longpress"    -->
-<!--   will be ignored. The workaround is to duplicate the long mapping in the section.       -->
+<!-- This file contains the mapping of remote keys to actions within Kodi.                -->
+<!--                                                                                      -->
+<!-- The format is:                                                                       -->
+<!--  <window>                                                                            -->
+<!--    <device>                                                                          -->
+<!--      <button>action</button>                                                         -->
+<!--    </device>                                                                         -->
+<!--  </window>                                                                           -->
+<!--                                                                                      -->
+<!-- The <global> section is a fall through - they will only be used if the button is     -->
+<!-- not used in the current window's section.                                            -->
+<!--                                                                                      -->
+<!-- Actions can be built-in functions.                                                   -->
+<!--  eg <B>ActivateWindow(Music)</B>                                                     -->
+<!-- would automatically go to Music on the press of the B button.                        -->
+<!--                                                                                      -->
+<!--  Long presses                                                                        -->
+<!--   A limitation is that if a single press is mapped in a section, a global "longpress"-->
+<!--   will be ignored. The workaround is to duplicate the long mapping in the section.   -->
+<!--                                                                                      -->
+<!-- An empty action removes the corresponding mapping from default and parent keymaps.   -->
+<!-- This is different from a "noop" action, which disables a button.                     -->
+<!--                                                                                      -->
+<!-- More documentation on keymaps can be found on http://kodi.wiki/view/keymaps          -->
 <keymap>
   <global>
     <remote>
@@ -58,7 +41,6 @@
       <pageminus>PageDown</pageminus>
       <back>Back</back>
       <menu>ContextMenu</menu>
-      <menu mod="longpress">Menu</menu>
       <contentsmenu>PreviousMenu</contentsmenu>
       <rootmenu>PreviousMenu</rootmenu>
       <title>ContextMenu</title>
@@ -194,7 +176,7 @@
       <rootmenu>OSD</rootmenu>
       <start>OSD</start>
       <select>OSD</select>
-      <title>CodecInfo</title>
+      <title>PlayerProcessInfo</title>
       <info>Info</info>
       <guide>ActivateWindow(PVROSDGuide)</guide>
       <teletext>ActivateWindow(Teletext)</teletext>
@@ -215,7 +197,7 @@
   </VideoTimeSeek>
   <FullscreenInfo>
     <remote>
-      <title>CodecInfo</title>
+      <title>PlayerProcessInfo</title>
       <info>Back</info>
       <menu>OSD</menu>
       <contentsmenu>OSD</contentsmenu>
@@ -238,7 +220,7 @@
       <pageplus>IncreaseRating</pageplus>
       <pageminus>DecreaseRating</pageminus>
       <back>Back</back>
-      <title>CodecInfo</title>
+      <title>PlayerProcessInfo</title>
       <select>OSD</select>
       <menu>OSD</menu>
       <contentsmenu>OSD</contentsmenu>
@@ -255,7 +237,7 @@
       <contentsmenu>Back</contentsmenu>
       <rootmenu>Back</rootmenu>
       <title>Info</title>
-      <info>CodecInfo</info>
+      <info>PlayerProcessInfo</info>
     </remote>
   </MusicOSD>
   <VisualisationPresetList>
@@ -277,7 +259,7 @@
       <seven>ZoomLevel7</seven>
       <eight>ZoomLevel8</eight>
       <nine>ZoomLevel9</nine>
-      <info>CodecInfo</info>
+      <info>Info</info>
       <skipplus>NextPicture</skipplus>
       <skipminus>PreviousPicture</skipminus>
       <title>Info</title>
@@ -312,7 +294,7 @@
       <contentsmenu>OSD</contentsmenu>
       <rootmenu>OSD</rootmenu>
       <info>Info</info>
-      <title>CodecInfo</title>
+      <title>PlayerProcessInfo</title>
       <zero>Number0</zero>
       <one>Number1</one>
       <two>Number2</two>
@@ -674,4 +656,9 @@
       <blue>Blue</blue>
     </remote>
   </Addon>
+  <PlayerProcessInfo>
+    <remote>
+      <title>PlayerProcessInfo</title>
+    </remote>
+  </PlayerProcessInfo>
 </keymap>
diff --git a/system/keymaps/wetek-play/keyboard.xml b/system/keymaps/wetek-play/keyboard.xml
new file mode 100644
index 0000000..407635f
--- /dev/null
+++ b/system/keymaps/wetek-play/keyboard.xml
@@ -0,0 +1,275 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<keymap>
+  <Global>
+    <keyboard>
+      <play_pause>Playpause</play_pause>
+      <play_pause mod="longpress">Info</play_pause>
+      <f2>ActivateWindow(TVGuide)</f2>
+      <f3>ActivateWindow(Home)</f3>
+      <f4>ContextMenu</f4>
+      <f4 mod="longpress">Menu</f4>
+      <f6>Info</f6>
+      <f6 mod="longpress">Playpause</f6>
+      <f7>ContextMenu</f7>
+      <f7 mod="longpress">Menu</f7>
+      <f11>ShowSubtitles</f11>
+      <escape>Back</escape>
+      <escape mod="longpress">ActivateWindow(Home)</escape>
+      <zero>Number0</zero>
+      <one>Number1</one>
+      <two>JumpSMS2</two>
+      <three>JumpSMS3</three>
+      <four>JumpSMS4</four>
+      <five>JumpSMS5</five>
+      <six>JumpSMS6</six>
+      <seven>JumpSMS7</seven>
+      <eight>JumpSMS8</eight>
+      <nine>JumpSMS9</nine>
+    </keyboard>
+  </Global>
+  <Home>
+    <keyboard>
+      <backspace>ActivateWindow(Favourites)</backspace>
+      <backspace mod="longpress">ActivateWindow(ShutdownMenu)</backspace>
+      <browser_back>ActivateWindow(Favourites)</browser_back>
+      <browser_back mod="longpress">ActivateWindow(ShutdownMenu)</browser_back>
+      <escape>ActivateWindow(Favourites)</escape>
+      <escape mod="longpress">ActivateWindow(ShutdownMenu)</escape>
+    </keyboard>
+  </Home>
+  <FullscreenVideo>
+    <keyboard>
+      <f4>Playlist</f4>
+      <f7>Playlist</f7>
+      <escape>Stop</escape>
+      <escape mod="longpress">Fullscreen</escape>
+      <backspace>Stop</backspace>
+      <backspace mod="longpress">Fullscreen</backspace>
+      <browser_back>Stop</browser_back>
+      <browser_back mod="longpress">Fullscreen</browser_back>
+      <return>PlayPause</return>
+      <return mod="longpress">OSD</return>
+      <zero>Number0</zero>
+      <one>Number1</one>
+      <two>Number2</two>
+      <three>Number3</three>
+      <four>Number4</four>
+      <five>Number5</five>
+      <six>Number6</six>
+      <seven>Number7</seven>
+      <eight>Number8</eight>
+      <nine>Number9</nine>
+      <backspace mod="longpress">FullScreen</backspace>
+      <browser_back mod="longpress">FullScreen</browser_back>
+      <escape mod="longpress">FullScreen</escape>
+      <up mod="longpress">SkipNext</up>
+      <down mod="longpress">SkipPrevious</down>
+      <left mod="longpress">Rewind</left>
+      <right mod="longpress">FastForward</right>
+    </keyboard>
+  </FullscreenVideo>
+  <Visualisation>
+    <keyboard>
+      <f4>Playlist</f4>
+      <f7>Playlist</f7>
+      <return>PlayPause</return>
+      <return mod="longpress">OSD</return>
+      <zero>Number0</zero>
+      <one>Number1</one>
+      <two>Number2</two>
+      <three>Number3</three>
+      <four>Number4</four>
+      <five>Number5</five>
+      <six>Number6</six>
+      <seven>Number7</seven>
+      <eight>Number8</eight>
+      <nine>Number9</nine>
+      <backspace mod="longpress">Stop</backspace>
+      <browser_back mod="longpress">Stop</browser_back>
+      <escape mod="longpress">Stop</escape>
+    </keyboard>
+  </Visualisation>
+  <VirtualKeyboard>
+    <keyboard>
+      <f1>Backspace</f1>
+      <f2>Shift</f2>
+      <f6>Enter</f6>
+      <play_pause>Enter</play_pause>
+      <zero>Number0</zero>
+      <one>Number1</one>
+      <two>Number2</two>
+      <three>Number3</three>
+      <four>Number4</four>
+      <five>Number5</five>
+      <six>Number6</six>
+      <seven>Number7</seven>
+      <eight>Number8</eight>
+      <nine>Number9</nine>
+      <backspace>Backspace</backspace>
+      <browser_back>PreviousMenu</browser_back>
+      <escape>PreviousMenu</escape>
+    </keyboard>
+  </VirtualKeyboard>
+  <VideoMenu>
+    <keyboard>
+      <zero>Number0</zero>
+      <one>Number1</one>
+      <two>Number2</two>
+      <three>Number3</three>
+      <four>Number4</four>
+      <five>Number5</five>
+      <six>Number6</six>
+      <seven>Number7</seven>
+      <eight>Number8</eight>
+      <nine>Number9</nine>
+      <return mod="longpress">OSD</return>
+      <enter mod="longpress">OSD</enter>
+    </keyboard>
+  </VideoMenu>
+  <NumericInput>
+    <keyboard>
+      <zero>Number0</zero>
+      <one>Number1</one>
+      <two>Number2</two>
+      <three>Number3</three>
+      <four>Number4</four>
+      <five>Number5</five>
+      <six>Number6</six>
+      <seven>Number7</seven>
+      <eight>Number8</eight>
+      <nine>Number9</nine>
+    </keyboard>
+  </NumericInput>
+  <Teletext>
+    <keyboard>
+      <zero>Number0</zero>
+      <one>Number1</one>
+      <two>Number2</two>
+      <three>Number3</three>
+      <four>Number4</four>
+      <five>Number5</five>
+      <six>Number6</six>
+      <seven>Number7</seven>
+      <eight>Number8</eight>
+      <nine>Number9</nine>
+    </keyboard>
+  </Teletext>
+  <VideoOSD>
+    <keyboard>
+      <return mod="longpress">Back</return>
+      <enter mod="longpress">Back</enter>
+    </keyboard>
+  </VideoOSD>
+  <ContextMenu>
+    <keyboard>
+      <f4>Back</f4>
+      <f7>Back</f7>
+    </keyboard>
+  </ContextMenu>
+  <PVROSDChannels>
+    <keyboard>
+      <zero>Number0</zero>
+      <one>Number1</one>
+      <two>Number2</two>
+      <three>Number3</three>
+      <four>Number4</four>
+      <five>Number5</five>
+      <six>Number6</six>
+      <seven>Number7</seven>
+      <eight>Number8</eight>
+      <nine>Number9</nine>
+      <f4>Close</f4>
+      <f7>Close</f7>
+    </keyboard>
+  </PVROSDChannels>
+  <TVChannels>
+    <keyboard>
+      <zero>Number0</zero>
+      <one>Number1</one>
+      <two>Number2</two>
+      <three>Number3</three>
+      <four>Number4</four>
+      <five>Number5</five>
+      <six>Number6</six>
+      <seven>Number7</seven>
+      <eight>Number8</eight>
+      <nine>Number9</nine>
+    </keyboard>
+  </TVChannels>
+  <PVROSDGuide>
+    <keyboard>
+      <zero>Number0</zero>
+      <one>Number1</one>
+      <two>Number2</two>
+      <three>Number3</three>
+      <four>Number4</four>
+      <five>Number5</five>
+      <six>Number6</six>
+      <seven>Number7</seven>
+      <eight>Number8</eight>
+      <nine>Number9</nine>
+    </keyboard>
+  </PVROSDGuide>
+  <TVGuide>
+    <keyboard>
+      <zero>Number0</zero>
+      <one>Number1</one>
+      <two>Number2</two>
+      <three>Number3</three>
+      <four>Number4</four>
+      <five>Number5</five>
+      <six>Number6</six>
+      <seven>Number7</seven>
+      <eight>Number8</eight>
+      <nine>Number9</nine>
+    </keyboard>
+  </TVGuide>
+  <RadioChannels>
+    <keyboard>
+      <zero>Number0</zero>
+      <one>Number1</one>
+      <two>Number2</two>
+      <three>Number3</three>
+      <four>Number4</four>
+      <five>Number5</five>
+      <six>Number6</six>
+      <seven>Number7</seven>
+      <eight>Number8</eight>
+      <nine>Number9</nine>
+    </keyboard>
+  </RadioChannels>
+  <FullscreenLiveTV>
+    <keyboard>
+      <return>OSD</return>
+      <enter>OSD</enter>
+    </keyboard>
+  </FullscreenLiveTV>
+  <FullscreenRadio>
+    <keyboard>
+      <return>OSD</return>
+      <enter>OSD</enter>
+    </keyboard>
+  </FullscreenRadio>
+  <SlideShow>
+    <keyboard>
+      <up>ZoomIn</up>
+      <down>ZoomOut</down>
+      <left>PreviousPicture</left>
+      <right>NextPicture</right>
+      <up mod="longpress">Up</up> <!-- Longpress on direction keys for panning when zoomed in -->
+      <down mod="longpress">Down</down>
+      <left mod="longpress">Left</left>
+      <right mod="longpress">Right</right>
+      <backspace>Stop</backspace>
+      <browser_back>Stop</browser_back>
+      <return mod="longpress">Info</return>
+      <enter mod="longpress">Info</enter>
+    </keyboard>
+  </SlideShow>
+  <FileManager>
+    <keyboard>
+      <right mod="longpress">Highlight</right>
+      <left mod="longpress">Highlight</left>
+    </keyboard>
+  </FileManager>
+</keymap>
\ No newline at end of file
diff --git a/system/peripherals.xml b/system/peripherals.xml
index ec3c3fe..b9c8e9d 100644
--- a/system/peripherals.xml
+++ b/system/peripherals.xml
@@ -44,4 +44,9 @@
     <setting key="do_not_use_custom_keymap" type="bool" value="1" label="35009" configurable="0"/>
     <setting key="disable_winjoystick" type="bool" value="1" label="35102" order="1" />
   </peripheral>
+
+  <peripheral vendor_product="2252:0106" bus="usb" name="WETEK Play remote" mapTo="hid">
+    <setting key="do_not_use_custom_keymap" type="bool" value="0" label="35009" order="1" />
+    <setting key="keymap" value="wetek-play" label="35007" configurable="0" />
+  </peripheral>
 </peripherals>
diff --git a/system/settings/darwin_ios.xml b/system/settings/darwin_ios.xml
index 09f07a9..ea9c482 100644
--- a/system/settings/darwin_ios.xml
+++ b/system/settings/darwin_ios.xml
@@ -7,7 +7,7 @@
           <visible>false</visible>
         </setting>
       </group>
-      <group id="4">
+      <group id="3">
         <setting id="videoplayer.hqscalers">
           <visible>false</visible>
         </setting>
diff --git a/system/settings/imx6.xml b/system/settings/imx6.xml
index b8c90a5..3af9b3f 100644
--- a/system/settings/imx6.xml
+++ b/system/settings/imx6.xml
@@ -2,7 +2,7 @@
 <settings>
   <section id="player">
     <category id="videoplayer">
-      <group id="4">
+      <group id="3">
         <setting id="videoplayer.limitguiupdate" type="integer" label="38013" help="38014">
           <level>2</level>
           <default>10</default>
diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml
index 806eadf..c3238c0 100644
--- a/system/settings/rbp.xml
+++ b/system/settings/rbp.xml
@@ -2,7 +2,7 @@
 <settings>
   <section id="player">
     <category id="videoplayer">
-      <group id="4">
+      <group id="3">
         <setting id="videoplayer.rendermethod">
           <visible>false</visible>
         </setting>
diff --git a/system/settings/rbp2.xml b/system/settings/rbp2.xml
index a0f9b68..e87e32e 100644
--- a/system/settings/rbp2.xml
+++ b/system/settings/rbp2.xml
@@ -2,7 +2,7 @@
 <settings>
   <section id="player">
     <category id="videoplayer">
-      <group id="4">
+      <group id="3">
         <setting id="videoplayer.useomxplayer">
           <default>false</default>
         </setting>
diff --git a/system/settings/settings.xml b/system/settings/settings.xml
index 53a4fe3..3ab531e 100644
--- a/system/settings/settings.xml
+++ b/system/settings/settings.xml
@@ -78,18 +78,7 @@
           <control type="list" format="string" />
         </setting>
       </group>
-      <group id="3">
-        <requirement>
-          <and>
-            <or>
-              <condition>HAS_GL</condition>
-              <condition>HAS_GLESv2</condition>
-            </or>
-            <condition>HAVE_LIBVDPAU</condition>
-          </and>
-        </requirement>
-      </group>
-      <group id="4" label="14231">
+      <group id="3" label="14231">
         <setting id="videoplayer.rendermethod" type="integer" label="13415" help="36153">
           <level>2</level>
           <default>0</default> <!-- RENDER_METHOD_AUTO -->
@@ -335,7 +324,7 @@
           <control type="toggle" />
         </setting>
       </group>
-      <group id="5" label="14232">
+      <group id="4" label="14232">
         <setting id="videoplayer.stereoscopicplaybackmode" type="integer" label="36520" help="36537">
           <level>2</level>
           <default>0</default>
@@ -355,7 +344,7 @@
           <control type="toggle" />
         </setting>
       </group>
-      <group id="6" label="14233">
+      <group id="5" label="14233">
         <setting id="videoplayer.teletextenabled" type="boolean" label="23050" help="36174">
           <level>3</level>
           <default>true</default>
@@ -846,7 +835,71 @@
       </group>
     </category>
   </section>
-  <section id="library" label="14202" help="38101">
+  <section id="media" label="14211" help="38101">
+    <category id="library" label="14202" help="39004">
+      <group id="1" label="14226">
+        <setting id="source.videos" type="action" label="14242" help="39005">
+          <level>1</level>
+          <control type="button" format="action" />
+        </setting>
+        <setting id="source.music" type="action" label="14243" help="39006">
+          <level>1</level>
+          <control type="button" format="action" />
+        </setting>
+        <setting id="source.pictures" type="action" label="14244" help="39007">
+          <level>1</level>
+          <control type="button" format="action" />
+        </setting>
+      </group>
+      <group id="2" label="14236">
+        <setting id="videolibrary.updateonstartup" type="boolean" label="14245" help="36146">
+          <level>1</level>
+          <default>false</default>
+          <control type="toggle" />
+        </setting>
+        <setting id="videolibrary.backgroundupdate" type="boolean" label="14246" help="36147">
+          <level>1</level>
+          <default>false</default>
+          <control type="toggle" />
+        </setting>
+        <setting id="videolibrary.cleanup" type="action" label="14247" help="36148">
+          <level>2</level>
+          <control type="button" format="action" />
+        </setting>
+        <setting id="videolibrary.export" type="action" label="14248" help="36149">
+          <level>2</level>
+          <control type="button" format="action" />
+        </setting>
+        <setting id="videolibrary.import" type="action" label="14249" help="36150">
+          <level>2</level>
+          <control type="button" format="action" />
+        </setting>
+      </group>
+      <group id="3" label="14237">
+        <setting id="musiclibrary.updateonstartup" type="boolean" label="14245" help="36259">
+          <level>1</level>
+          <default>false</default>
+          <control type="toggle" />
+        </setting>
+        <setting id="musiclibrary.backgroundupdate" type="boolean" label="14246" help="36147">
+          <level>1</level>
+          <default>false</default>
+          <control type="toggle" />
+        </setting>
+        <setting id="musiclibrary.cleanup" type="action" label="14247" help="36148">
+          <level>2</level>
+          <control type="button" format="action" />
+        </setting>
+        <setting id="musiclibrary.export" type="action" label="14248" help="36262">
+          <level>2</level>
+          <control type="button" format="action" />
+        </setting>
+        <setting id="musiclibrary.import" type="action" label="14249" help="36263">
+          <level>2</level>
+          <control type="button" format="action" />
+        </setting>
+      </group>
+    </category>
     <category id="filelists" label="16000" help="36121">
       <group id="1" label="593">
         <setting id="filelists.showparentdiritems" type="boolean" label="13306" help="36122">
@@ -858,7 +911,7 @@
           <level>1</level>
           <default>true</default>
           <control type="toggle" />
-        </setting>		
+        </setting>
       </group>
       <group id="2" label="744">
         <setting id="filelists.showextensions" type="boolean" label="497" help="36123">
@@ -900,7 +953,7 @@
       </group>
     </category>
     <category id="video" label="14215" help="38107">
-	  <group id="1" label="593">
+      <group id="1" label="593">
         <setting id="myvideos.selectaction" type="integer" label="22079" help="36177">
           <level>0</level>
           <default>1</default> <!-- SELECT_ACTION_PLAY_OR_RESUME -->
@@ -929,8 +982,8 @@
           <default>true</default>
           <control type="toggle" />
         </setting>
-      </group>		
-	  <group id="2" label="744">
+      </group>
+      <group id="2" label="744">
         <setting id="myvideos.stackvideos" type="boolean" label="20435" help="36182">
           <level>1</level>
           <default>false</default>
@@ -941,7 +994,7 @@
           <default>true</default>
           <control type="toggle" />
         </setting>
-      </group>	
+      </group>
       <group id="3" label="14022">
         <setting id="videolibrary.showallitems" type="boolean" label="38011" help="38012">
           <level>2</level>
@@ -953,6 +1006,16 @@
           <default>true</default>
           <control type="toggle" />
         </setting>
+        <setting id="videolibrary.groupmoviesets" type="boolean" label="20458" help="36145">
+          <level>1</level>
+          <default>false</default>
+          <control type="toggle" />
+        </setting>
+        <setting id="videolibrary.groupsingleitemsets" type="boolean" parent="videolibrary.groupmoviesets" label="20470" help="36157">
+          <level>1</level>
+          <default>false</default>
+          <control type="toggle" />
+        </setting>
         <setting id="myvideos.flatten" type="boolean" label="20456" help="36183">
           <level>2</level>
           <default>false</default>
@@ -1003,23 +1066,13 @@
           </dependencies>
           <control type="spinner" format="string" />
         </setting>
-        <setting id="videolibrary.groupmoviesets" type="boolean" label="20458" help="36145">
-          <level>1</level>
-          <default>false</default>
-          <control type="toggle" />
-        </setting>
-        <setting id="videolibrary.groupsingleitemsets" type="boolean" label="20470" help="36157">
-          <level>1</level>
-          <default>false</default>
-          <control type="toggle" />
-        </setting>
         <setting id="videolibrary.actorthumbs" type="boolean" label="20402" help="36143">
           <level>2</level>
           <default>true</default>
           <control type="toggle" />
         </setting>
       </group>
-    </category>	
+    </category>
     <category id="music" label="14216" help="38108">
       <group id="1" label="593">
         <setting id="musicfiles.trackformat" type="string" label="13307" help="36275">
@@ -1054,13 +1107,13 @@
           <default>true</default>
           <control type="toggle" />
         </setting>
-      </group>  
+      </group>
       <group id="2" label="744">
         <setting id="musicfiles.usetags" type="boolean" label="258" help="36274">
           <level>1</level>
           <default>true</default>
           <control type="toggle" />
-        </setting>	  
+        </setting>
       </group>
       <group id="3" label="14022">
         <setting id="musiclibrary.showallitems" type="boolean" label="38011" help="38012">
@@ -1143,56 +1196,6 @@
         </setting>
       </group>
     </category>
-    <category id="databases" label="14219" help="38110">
-      <group id="1" label="14215">
-        <setting id="videolibrary.updateonstartup" type="boolean" label="14245" help="36146">
-          <level>1</level>
-          <default>false</default>
-          <control type="toggle" />
-        </setting>
-        <setting id="videolibrary.backgroundupdate" type="boolean" label="14246" help="36147">
-          <level>1</level>
-          <default>false</default>
-          <control type="toggle" />
-        </setting>
-        <setting id="videolibrary.cleanup" type="action" label="14247" help="36148">
-          <level>2</level>
-          <control type="button" format="action" />
-        </setting>
-        <setting id="videolibrary.export" type="action" label="14248" help="36149">
-          <level>2</level>
-          <control type="button" format="action" />
-        </setting>
-        <setting id="videolibrary.import" type="action" label="14249" help="36150">
-          <level>2</level>
-          <control type="button" format="action" />
-        </setting>
-      </group>
-      <group id="2" label="14216">
-        <setting id="musiclibrary.updateonstartup" type="boolean" label="14245" help="36259">
-          <level>1</level>
-          <default>false</default>
-          <control type="toggle" />
-        </setting>
-        <setting id="musiclibrary.backgroundupdate" type="boolean" label="14246" help="36147">
-          <level>1</level>
-          <default>false</default>
-          <control type="toggle" />
-        </setting>
-        <setting id="musiclibrary.cleanup" type="action" label="14247" help="36148">
-          <level>2</level>
-          <control type="button" format="action" />
-        </setting>
-        <setting id="musiclibrary.export" type="action" label="14248" help="36262">
-          <level>2</level>
-          <control type="button" format="action" />
-        </setting>
-        <setting id="musiclibrary.import" type="action" label="14249" help="36263">
-          <level>2</level>
-          <control type="button" format="action" />
-        </setting>
-      </group>
-    </category>
     <category id="scrapers" label="0" help="36197">
       <visible>false</visible>
       <group id="1">
@@ -1556,6 +1559,10 @@
           <default>true</default>
           <control type="toggle" />
         </setting>
+        <setting id="pvrrecord.grouprecordings" type="boolean" label="" help="">
+          <default>true</default>
+          <level>4</level>
+        </setting>
       </group>
     </category>
     <category id="pvrpowermanagement" label="14095" help="36240">
@@ -1688,7 +1695,7 @@
           <default>Kodi</default>
           <control type="edit" format="string" />
         </setting>
-      </group>		
+      </group>
       <group id="2" label="1259">
       <requirement>HAS_ZEROCONF</requirement>
         <setting id="services.zeroconf" type="boolean" label="1260" help="36342">
@@ -1999,6 +2006,149 @@
           </dependencies>
           <control type="spinner" format="integer" />
         </setting>
+        <setting id="videoscreen.cmsenabled" type="boolean" label="36560" help="36561">
+          <requirement>HAS_GL</requirement>
+          <level>3</level>
+          <default>false</default>
+          <control type="toggle" />
+        </setting>
+        <setting id="videoscreen.cmsmode" type="integer" label="36562" help="36563">
+          <requirement>HAS_GL</requirement>
+          <level>3</level>
+          <default>0</default>
+          <constraints>
+            <options>cmsmodes</options>
+          </constraints>
+          <dependencies>
+            <dependency type="visible" setting="videoscreen.cmsenabled" operator="is">true</dependency>
+          </dependencies>
+          <control type="list" format="integer"/>
+        </setting>
+        <setting id="videoscreen.cms3dlut" type="string" label="36564" help="36565">
+          <requirement>
+            <and>
+              <condition>HAS_GL</condition>
+            </and>
+          </requirement>
+          <level>3</level>
+          <default></default>
+          <constraints>
+            <allowempty>true</allowempty>
+          </constraints>
+          <dependencies>
+            <dependency type="visible" setting="videoscreen.cmsenabled" operator="is">true</dependency>
+            <dependency type="visible" setting="videoscreen.cmsmode" operator="is">0</dependency>
+          </dependencies>
+          <control type="button" format="action" />
+        </setting>
+        <setting id="videoscreen.displayprofile" type="string" label="36566" help="36567">
+          <requirement>
+            <and>
+              <condition>HAS_GL</condition>
+              <condition>HAVE_LCMS2</condition>
+            </and>
+          </requirement>
+          <level>3</level>
+          <default></default>
+          <constraints>
+            <allowempty>true</allowempty>
+          </constraints>
+          <dependencies>
+            <dependency type="visible" setting="videoscreen.cmsenabled" operator="is">true</dependency>
+            <dependency type="visible" setting="videoscreen.cmsmode" operator="is">1</dependency>
+          </dependencies>
+          <control type="button" format="action" />
+        </setting>
+        <setting id="videoscreen.cmswhitepoint" type="integer" label="36568" help="36569">
+          <requirement>
+            <and>
+              <condition>HAS_GL</condition>
+              <condition>HAVE_LCMS2</condition>
+            </and>
+          </requirement>
+          <level>3</level>
+          <default>0</default>
+          <constraints>
+            <options>cmswhitepoints</options>
+          </constraints>
+          <dependencies>
+            <dependency type="visible" setting="videoscreen.cmsenabled" operator="is">true</dependency>
+            <dependency type="visible" setting="videoscreen.cmsmode" operator="is">1</dependency>
+          </dependencies>
+          <control type="list" format="integer"/>
+        </setting>
+        <setting id="videoscreen.cmsprimaries" type="integer" label="36570" help="36571">
+          <requirement>
+            <and>
+              <condition>HAS_GL</condition>
+              <condition>HAVE_LCMS2</condition>
+            </and>
+          </requirement>
+          <level>3</level>
+          <default>0</default>
+          <constraints>
+            <options>cmsprimaries</options>
+          </constraints>
+          <dependencies>
+            <dependency type="visible" setting="videoscreen.cmsenabled" operator="is">true</dependency>
+            <dependency type="visible" setting="videoscreen.cmsmode" operator="is">1</dependency>
+          </dependencies>
+          <control type="list" format="integer"/>
+        </setting>
+        <setting id="videoscreen.cmsgammamode" type="integer" label="36572" help="36573">
+          <requirement>
+            <and>
+              <condition>HAS_GL</condition>
+              <condition>HAVE_LCMS2</condition>
+            </and>
+          </requirement>
+          <level>3</level>
+          <default>0</default>
+          <constraints>
+            <options>cmsgammamodes</options>
+          </constraints>
+          <dependencies>
+            <dependency type="visible" setting="videoscreen.cmsenabled" operator="is">true</dependency>
+            <dependency type="visible" setting="videoscreen.cmsmode" operator="is">1</dependency>
+          </dependencies>
+          <control type="list" format="integer"/>
+        </setting>
+        <setting id="videoscreen.cmsgamma" type="integer" label="36574" help="36575">
+          <requirement>
+            <and>
+              <condition>HAS_GL</condition>
+              <condition>HAVE_LCMS2</condition>
+            </and>
+          </requirement>
+          <level>3</level>
+          <default>220</default>
+          <constraints>
+            <minimum>160</minimum>
+            <step>005</step>
+            <maximum>280</maximum>
+          </constraints>
+          <dependencies>
+            <dependency type="visible" setting="videoscreen.cmsenabled" operator="is">true</dependency>
+            <dependency type="visible" setting="videoscreen.cmsmode" operator="is">1</dependency>
+            <dependency type="visible" setting="videoscreen.cmsgammamode" operator="!is">0</dependency>
+          </dependencies>
+          <control type="spinner" format="integer" />
+        </setting>
+        <setting id="videoscreen.cmslutsize" type="integer" label="36576" help="36577">
+          <requirement>HAS_GL</requirement>
+          <level>3</level>
+          <default>6</default>
+          <constraints>
+            <minimum>4</minimum>
+            <step>1</step>
+            <maximum>8</maximum>
+          </constraints>
+          <dependencies>
+            <dependency type="visible" setting="videoscreen.cmsenabled" operator="is">true</dependency>
+            <dependency type="visible" setting="videoscreen.cmsmode" operator="is">1</dependency>
+          </dependencies>
+          <control type="spinner" format="integer" />
+        </setting>
       </group>
       <group id="2" label="14232">
         <setting id="videoscreen.stereoscopicmode" type="integer" label="36500" help="36539">
@@ -2157,6 +2307,8 @@
           </constraints>
           <control type="list" format="string" />
         </setting>
+      </group>
+      <group id="2" label="15108">
         <setting id="audiooutput.guisoundmode" type="integer" label="34120" help="36373">
           <level>0</level>
           <default>1</default> <!-- AE_SOUND_IDLE -->
@@ -2169,42 +2321,19 @@
           </constraints>
           <control type="list" format="string" />
         </setting>
-      </group>
-      <group id="2" label="14251">
-        <setting id="audiooutput.dspaddonsenabled" type="boolean" label="36441" help="36438">
-          <level>3</level>
-          <default>false</default>
-          <dependencies>
-            <dependency type="visible">
-              <or>
-                <condition on="property" name="aesettingvisible" setting="audiooutput.passthrough">audiooutput.dspaddonsenabled</condition>
-                <condition on="property" name="aesettingvisible" setting="audiooutput.ac3passthrough">audiooutput.dspaddonsenabled</condition>
-              </or>
-            </dependency>
-          </dependencies>
-          <control type="toggle" />
-        </setting>
-        <setting id="audiooutput.dspsettings" type="action" label="36436" help="36437">
-          <level>3</level>
-          <control type="button" format="action" />
-          <dependencies>
-            <dependency type="visible">
-              <or>
-                <condition on="property" name="aesettingvisible" setting="audiooutput.dspaddonsenabled">audiooutput.dspsettings</condition>
-              </or>
-            </dependency>
-          </dependencies>
-        </setting>
-        <setting id="audiooutput.dspresetdb" type="action" label="14082" help="36439">
-          <level>3</level>
-          <control type="button" format="action" />
-          <dependencies>
-            <dependency type="visible">
-              <or>
-                <condition on="property" name="aesettingvisible" setting="audiooutput.dspaddonsenabled">audiooutput.dspresetdb</condition>
-              </or>
-            </dependency>
-          </dependencies>
+        <setting id="lookandfeel.soundskin" type="addon" label="24006" help="36110">
+          <level>0</level>
+          <default>resource.uisounds.confluence</default>
+          <constraints>
+            <addontype>kodi.resource.uisounds</addontype>
+            <allowempty>true</allowempty>
+          </constraints>
+          <updates>
+            <update type="change" />
+          </updates>
+          <control type="button" format="addon">
+            <show more="true" details="true">installed</show>
+          </control>
         </setting>
       </group>
       <group id="3" label="14252">
@@ -2318,6 +2447,43 @@
           <control type="toggle" />
         </setting>
       </group>
+      <group id="4" label="14251">
+        <setting id="audiooutput.dspaddonsenabled" type="boolean" label="36441" help="36438">
+          <level>3</level>
+          <default>false</default>
+          <dependencies>
+            <dependency type="visible">
+              <or>
+                <condition on="property" name="aesettingvisible" setting="audiooutput.passthrough">audiooutput.dspaddonsenabled</condition>
+                <condition on="property" name="aesettingvisible" setting="audiooutput.ac3passthrough">audiooutput.dspaddonsenabled</condition>
+              </or>
+            </dependency>
+          </dependencies>
+          <control type="toggle" />
+        </setting>
+        <setting id="audiooutput.dspsettings" type="action" label="36436" help="36437">
+          <level>3</level>
+          <control type="button" format="action" />
+          <dependencies>
+            <dependency type="visible">
+              <or>
+                <condition on="property" name="aesettingvisible" setting="audiooutput.dspaddonsenabled">audiooutput.dspsettings</condition>
+              </or>
+            </dependency>
+          </dependencies>
+        </setting>
+        <setting id="audiooutput.dspresetdb" type="action" label="14082" help="36439">
+          <level>3</level>
+          <control type="button" format="action" />
+          <dependencies>
+            <dependency type="visible">
+              <or>
+                <condition on="property" name="aesettingvisible" setting="audiooutput.dspaddonsenabled">audiooutput.dspresetdb</condition>
+              </or>
+            </dependency>
+          </dependencies>
+        </setting>
+      </group>
     </category>
     <category id="network" label="798" help="36379">
       <group id="1" label="16000">
@@ -2773,32 +2939,6 @@
             <formatlabel>14047</formatlabel>
           </control>
         </setting>
-        <setting id="audiooutput.guisoundmode" type="integer" label="34120" help="36373">
-          <level>0</level>
-          <default>1</default> <!-- AE_SOUND_IDLE -->
-          <constraints>
-            <options>
-              <option label="34121">1</option> <!-- AE_SOUND_IDLE -->
-              <option label="34122">2</option> <!-- AE_SOUND_ALWAYS -->
-              <option label="34123">0</option> <!-- AE_SOUND_OFF -->
-            </options>
-          </constraints>
-          <control type="list" format="string" />
-        </setting>
-        <setting id="lookandfeel.soundskin" type="addon" label="15108" help="36110">
-          <level>0</level>
-          <default>resource.uisounds.confluence</default>
-          <constraints>
-            <addontype>kodi.resource.uisounds</addontype>
-            <allowempty>true</allowempty>
-          </constraints>
-          <updates>
-            <update type="change" />
-          </updates>
-          <control type="button" format="addon">
-            <show more="true" details="true">installed</show>
-          </control>
-        </setting>
         <setting id="lookandfeel.stereostrength" type="integer" label="36550" help="36551">
           <level>2</level>
           <default>5</default>
@@ -2975,12 +3115,12 @@
           <control type="button" format="action" />
         </setting>
       </group>
-      <group id="3" label="14275">		
+      <group id="3" label="14275">
       <requirement>
-          <or>
+        <or>
           <condition>HAS_EVENT_SERVER</condition>
           <condition>HAS_JSONRPC</condition>
-          </or>
+        </or>
       </requirement>
         <setting id="services.esenabled" type="boolean" label="14276" help="36334">
           <level>1</level>
@@ -3184,7 +3324,7 @@
         </setting>
         <setting id="lookandfeel.enablerssfeeds" type="boolean" label="13305" help="36111">
           <level>0</level>
-          <default>true</default>
+          <default>false</default>
           <control type="toggle" />
         </setting>
         <setting id="lookandfeel.rssedit" type="string" parent="lookandfeel.enablerssfeeds" label="21450" help="36112">
diff --git a/system/shaders/output.glsl b/system/shaders/output.glsl
index c95c948..a0c69c5 100644
--- a/system/shaders/output.glsl
+++ b/system/shaders/output.glsl
@@ -3,11 +3,20 @@ uniform sampler2D m_dither;
 uniform float     m_ditherquant;
 uniform vec2      m_dithersize;
 #endif
+#if defined(KODI_3DLUT)
+uniform float     m_CLUTsize;
+uniform sampler3D m_CLUT;
+#endif
 
 void main()
 {
   vec4 rgb        = process();
 
+#if defined(KODI_3DLUT)
+  // FIXME: can this be optimized?
+  rgb             = texture3D(m_CLUT, (rgb.rgb*(m_CLUTsize-1.0) + 0.5) / m_CLUTsize);
+#endif
+
 #if defined(XBMC_FULLRANGE)
 #if __VERSION__ <= 120
   rgb = (rgb-(16.0/255.0)) * 255.0/219.0;
diff --git a/tools/EventClients/Clients/J2ME Client/README b/tools/EventClients/Clients/J2ME Client/README
deleted file mode 100644
index ee14268..0000000
--- a/tools/EventClients/Clients/J2ME Client/README	
+++ /dev/null
@@ -1,23 +0,0 @@
-1. Can I use it?
-To use the J2ME client only CLDC 1.0 and MIDP 1.0 is needed.
-The client will also need bluetooth and must be able to initialize the connection.
-
-2. Compiling the client
-To compile the J2ME Application some libraries are needed:
-  *Suns Wireless Toolkit
-  *Java
-  *Ant
-Before it can be compiled the link to Suns Wireless Toolkit are needed and are in build.xml 
-under <property name="WTK" value=""> where the value should be the path to the toolkit.
-When compiling in ubuntu all that is needed are the following command
-# ant
-The final jar file will end up in build/release/
-For installations on some J2ME devices a jad file is needed and it needs the correct filesize of the JAR. This is not an
-automated process and thus open the build/release/XBMCRemote.jad and alter it is requiered. The filesize is in bytes
-and reflects that of build/release/XBMCRemote.jar
-
-3. Pre Usage
-To use the EventClient you'll need to run the EventClient on a computer by:
-# python XBMCJ2ME.py
-It depends on Pybluez (http://org.csail.mit.edu/pybluez/) and is available in repository
-# sudo apt-get install python-bluetooth
diff --git a/tools/EventClients/Clients/J2ME Client/build.xml b/tools/EventClients/Clients/J2ME Client/build.xml
deleted file mode 100644
index 4e583b2..0000000
--- a/tools/EventClients/Clients/J2ME Client/build.xml	
+++ /dev/null
@@ -1,31 +0,0 @@
-<project name="XBMC Remote" default="make">
-  <property name="WTK" value=""/>
-  <property name="OUTNAME" value="XBMCRemote"/> 
-  <property name="MIDP10_LIB" value="${WTK}/lib/midpapi10.jar"/>
-  <property name="CLDC10_LIB" value="${WTK}/lib/cldcapi10.jar"/>
-  <property name="JSR082_LIB" value="${WTK}/lib/jsr082.jar"/>
-  <property name="ALL_LIB" value="${MIDP10_LIB}:${CLDC10_LIB}:${JSR082_LIB}"/>
-
-  <target name="compile">
-    <tstamp/>
-    <mkdir dir="build/compiled"/>
-    <javac destdir="build/compiled" srcdir="src" bootclasspath="${ALL_LIB}" target="1.1"/>
-  </target>
-
-  <target name="preverify" depends="compile">
-      <mkdir dir="build/preverified"/>
-      <exec executable="${WTK}/bin/preverify">
-        <arg line="-classpath ${ALL_LIB}"/>
-        <arg line="-d build/preverified"/>
-        <arg line="build/compiled"/>
-      </exec>
-  </target>
-
-  <target name="make" depends="preverify">
-    <mkdir dir="build/release"/>
-    <jar basedir="build/preverified" jarfile="build/release/${OUTNAME}.jar" manifest="manifest.mf">
-      <fileset dir="icons"/>
-    </jar>
-    <copy file="src/XBMCRemote.jad" tofile="build/release/${OUTNAME}.jad"/>
-  </target>
-</project>
diff --git a/tools/EventClients/Clients/J2ME Client/icons/icon.png b/tools/EventClients/Clients/J2ME Client/icons/icon.png
deleted file mode 100644
index 812237b..0000000
Binary files a/tools/EventClients/Clients/J2ME Client/icons/icon.png and /dev/null differ
diff --git a/tools/EventClients/Clients/J2ME Client/j2me_remote.py b/tools/EventClients/Clients/J2ME Client/j2me_remote.py
deleted file mode 100755
index b963a87..0000000
--- a/tools/EventClients/Clients/J2ME Client/j2me_remote.py	
+++ /dev/null
@@ -1,175 +0,0 @@
-#!/usr/bin/python
-#
-# XBMC Media Center
-# J2ME Remote
-# Copyright (c) 2008 topfs2
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-
-import sys
-try:
-    from kodi.xbmcclient import *
-    from kodi.bt.bt import *
-    from kodi.defs import *
-except:
-    sys.path.append('../../lib/python')
-    from xbmcclient import *
-    from bt.bt import *
-    ICON_PATH = "../../icons/"
-
-from socket import *
-import os
-from threading import Thread
-
-host = "localhost"
-port = 9777
-addr = (host, port)
-sock = socket(AF_INET,SOCK_DGRAM)
-
-def send_key(key):
-    packet = PacketBUTTON(map_name="JS0:J2ME", code=key, repeat=0, queue=0)
-    packet.send(sock, addr)
-
-def send_message(caption, msg):
-    packet = PacketNOTIFICATION(caption,
-                                msg,
-                                ICON_PNG,
-                                icon_file=ICON_PATH + "/phone.png")
-
-    packet.send(sock, addr)
-
-def send_ImageToBluetooth(Image):
-    imageData = file( Image ).read()
-    print "Data len ", len( imageData )
-    client_sock.send( format.uint32( len( imageData) ) )
-    client_sock.sendall(imageData)
-    print "Sent file"
-
-class Ping(Thread):
-    def __init__ (self):
-        Thread.__init__(self)
-    def run(self):
-        import time
-        while 1: # ping the server every 19s
-            packet = PacketPING()
-            packet.send(sock, addr)
-            time.sleep (19)
-
-def main():
-    import time
-
-    # connect to localhost, port 9777 using a UDP socket
-    # this only needs to be done once.
-    # by default this is where XBMC will be listening for incoming
-    # connections.
-    server_sock=bt_create_rfcomm_socket()
-    server_sock.listen(2)
-
-    portBT = server_sock.getsockname()[1]
-
-    uuid = "ACDC"
-    bt_advertise(socket=server_sock, name="XBMC Remote", uuid=uuid)
-
-    print "Waiting for connection on RFCOMM channel %d" % portBT
-
-    packet = PacketHELO(devicename="J2ME Remote",
-                        icon_type=ICON_PNG,
-                        icon_file=ICON_PATH + "/phone.png")
-    packet.send(sock, addr)
-    Ping().start()
-    while(True):
-        try:
-            client_sock, client_info = server_sock.accept()
-            print "Accepted connection from ", client_info
-            client_addr, client_port  = client_info
-            runFlag  = True
-            firstRun = True
-            print "Accepted connection from ", client_addr
-        except KeyboardInterrupt:
-            packet = PacketLOG(LOGNOTICE, "J2ME: User interrupted")
-            packet.send(sock, addr)
-            bt_stop_advertising(socket = server_sock)
-            server_sock.close()
-            sys.exit(0)
-        try:
-            while runFlag:
-                if firstRun:
-                    client_name = client_sock.recv(1024)
-                    firstRun = False
-                    send_message("J2ME: Phone Connected", client_name)
-                    packet = PacketLOG(LOGNOTICE, "Phone Connected")
-                    packet.send(sock, addr)
-                data = client_sock.recv(3)
-                if(data[0] == "0"):
-                    if(data[1] == "0"):
-                        runFlag = False
-                        packet = PacketLOG(LOGNOTICE, "J2ME: Recieved disconnect command")
-                        packet.send(sock, addr)
-                        client_sock.close()
-                    if(data[1] == "1"):
-                        print "Shuting down server"
-                        client_sock.close()
-                        bt_stop_advertising(socket = server_sock)
-                        server_sock.close()
-                        packet = PacketBYE()
-                        packet.send(sock, addr)
-                        sys.exit(0)
-
-                elif(data[0] == "2"):
-                    print "<button id=\"%i\">" % ord( data[1] )
-                    send_key(ord( data[1] ) )
-                else:
-                  print "Unkown received data [%s]" % data
-        except IOError:
-            print "Lost connection too %s" % client_name
-            runFlag = False
-            send_message("Phone Disconnected", client_name)
-            pass
-        except KeyboardInterrupt:
-            packet = PacketLOG(LOGNOTICE, "J2ME: User interrupted")
-            packet.send(sock, addr)
-            client_sock.close()
-            bt_stop_advertising(socket = server_sock)
-            server_sock.close()
-            packet = PacketBYE()    # PacketPING if you want to ping
-            packet.send(sock, addr)
-            sys.exit(0)
-
-def usage():
-    print """
-Java Bluetooth Phone Remote Control Client for XBMC v0.1
-
-Usage for xbmcphone.py
-    --address ADDRESS  (default: localhost)
-    --port PORT        (default: 9777)
-    --help             (Brings up this message)
-"""
-
-if __name__=="__main__":
-    try:
-        i = 0
-        while (i < len(sys.argv)):
-            if   (sys.argv[i] == "--address"):
-                host = sys.argv[i + 1]
-            elif (sys.argv[i] == "--port"):
-                port = sys.argv[i + 1]
-            elif (sys.argv[i] == "--help"):
-                usage()
-                sys.exit(0)
-            i = i + 1
-        main()
-    except:
-        sys.exit(0)
diff --git a/tools/EventClients/Clients/J2ME Client/manifest.mf b/tools/EventClients/Clients/J2ME Client/manifest.mf
deleted file mode 100644
index 49cddf5..0000000
--- a/tools/EventClients/Clients/J2ME Client/manifest.mf	
+++ /dev/null
@@ -1,7 +0,0 @@
-MIDlet-1: MainScreen, , MainScreen
-MIDlet-Vendor: team-xbmc
-MIDlet-Name: XBMC Remote
-MIDlet-Icon: icon.png
-MIDlet-Version: 0.1
-MicroEdition-Configuration: CLDC-1.0
-MicroEdition-Profile: MIDP-1.0
diff --git a/tools/EventClients/Clients/J2ME Client/src/BluetoothCommunicator.java b/tools/EventClients/Clients/J2ME Client/src/BluetoothCommunicator.java
deleted file mode 100644
index 2db3f54..0000000
--- a/tools/EventClients/Clients/J2ME Client/src/BluetoothCommunicator.java	
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
-* XBMC Media Center
-* UDP Event Server
-* Copyright (c) 2008 topfs2
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-import javax.microedition.io.Connector;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import javax.microedition.io.StreamConnection;
-import java.lang.NullPointerException;
-import java.util.Vector;
-import javax.bluetooth.*;
-import javax.bluetooth.LocalDevice;
-import javax.microedition.lcdui.Form;
-import javax.microedition.lcdui.Image;
-import javax.microedition.lcdui.Display;
-import java.lang.*;
-
-public class BluetoothCommunicator extends Thread
-{
-  private boolean Run;
-  private Form    Log;
-  private BluetoothEvent recvEvent;
-
-  protected static String Address = null;
-  private static StreamConnection Connection = null;
-  private static DataInputStream  inputStream = null;
-  private static DataOutputStream outputStream = null;
-
-  public BluetoothCommunicator(BluetoothEvent recvEvent, Form Log)
-  {
-    this.recvEvent = recvEvent;
-    this.Log = Log;
-  }
-
-  public static boolean Connect(Form Log, String addr)
-  {
-    Log.append("Going to connect\n");
-    try
-    {
-      Connection = (StreamConnection)Connector.open(addr);
-
-      if (Connection == null)
-      {
-        Log.append("Connector.open returned null\n");
-        return false;
-      }
-      else
-      {
-        Log.append("Connector.open returned connection\n");
-        inputStream  = Connection.openDataInputStream();
-        outputStream = Connection.openDataOutputStream();
-        Address = addr;
-        return true;
-      }
-    }
-    catch (Exception e)
-    {
-      Log.append("Exception" + e.getMessage() + "\n");
-      try
-      {
-        if (Connection != null)
-          Connection.close();
-      }
-      catch (Exception ee)
-      {
-        Log.append("Exception " + ee.getMessage() + "\n");
-      }
-      Connection = null;
-      return false;
-    }
-  }
-
-  public static boolean Handshake(Form Log, Display disp)
-  {
-      if (Connection == null)
-        return false;
-      try
-      {
-        LocalDevice localDevice = LocalDevice.getLocalDevice();
-        Send(localDevice.getFriendlyName());
-
-        return true;
-      }
-      catch(NullPointerException NPE)
-      {
-        Log.append("Null " + NPE.getMessage());
-      }
-      catch (IndexOutOfBoundsException IOBE)
-      {
-        Log.append("IndexOutOfBounds " + IOBE.getMessage());
-      }
-      catch (IllegalArgumentException IAE)
-      {
-        Log.append("illegalArg " + IAE.getMessage());
-      }
-      catch(Exception e)
-      {
-        Log.append("Exception in handshake " + e.getMessage());
-      }
-      return false;
-  }
-  public void run()
-  {
-    Run = true;
-    while (Run)
-    {
-      try
-      {
-        if (inputStream.available() <= 0)
-            sleep(10);
-        else
-        {
-          Log.append("run:Ava " + inputStream.available() + "\n");
-          byte []b = new byte[1];
-          b[0] = (byte)255; // safe thing for now
-          inputStream.read(b, 0, 1);
-          byte[] recv = null;
-          switch (b[0])
-          {
-            case BluetoothEvent.RECV_SYSTEM:
-              recv = new byte[]{ inputStream.readByte() };
-              break;
-            case BluetoothEvent.RECV_COMMAND:
-              recv = new byte[]{ inputStream.readByte() };
-              break;
-            case BluetoothEvent.RECV_IMAGE:
-              Log.append("Recv_Image\n");
-              recv = RecvImage(Log);
-              break;
-          }
-          if (recv != null)
-            recvEvent.Recv(b[0], recv);
-        }
-      }
-      catch (Exception e)
-      {
-        Log.append("RecvException " + e.getMessage());
-      }
-    }
-  }
-  public void close()
-  {
-    Run = false;
-  }
-  public static byte[] RecvImage(Form Log)
-  {
-    try
-    {
-      int length = inputStream.readInt();
-      Log.append("readUnsignedShort: " + length + "\n");
-      byte[] arrayToUse = new byte[length];
-      inputStream.readFully(arrayToUse, 0, length);
-      return arrayToUse;
-    }
-    catch (Exception e )
-    {
-      Log.append("Exception RecvImage " + e.getMessage());
-      return null;
-    }
-  }
-
-  public static int Recv(byte[] arrayToUse, Form Log )
-  {
-    if (Connection == null)
-      return -1;
-    try
-    {
-      return inputStream.read(arrayToUse);
-    }
-    catch (Exception e)
-    {
-      Log.append("Exception in Recv " + e.getMessage());
-      return -1;
-    }
-  }
-
-  public static boolean Send(byte[] packet)
-  {
-    if (Connection == null)
-      return false;
-    try
-    {
-      outputStream.write(packet, 0, packet.length);
-      return true;
-    }
-    catch (Exception e)
-    {
-      return false;
-    }
-  }
-
-  public static boolean Send(String packet)
-  {
-    return Send(packet.getBytes());
-  }
-
-  public static void Disconnect()
-  {
-    if (Connection == null)
-      return;
-    
-    try
-    {
-      byte[] packet = { '0', '0' };
-      Send(packet);
-      Connection.close();
-    }
-    catch (Exception e)
-    { }
-    
-    Connection = null;
-  }
-}
diff --git a/tools/EventClients/Clients/J2ME Client/src/BluetoothEvent.java b/tools/EventClients/Clients/J2ME Client/src/BluetoothEvent.java
deleted file mode 100644
index 6557dca..0000000
--- a/tools/EventClients/Clients/J2ME Client/src/BluetoothEvent.java	
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-* XBMC Media Center
-* UDP Event Server
-* Copyright (c) 2008 topfs2
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-public interface BluetoothEvent {
-  public final int RECV_SYSTEM  = 0;
-  public final int RECV_COMMAND = 1;
-  public final int RECV_IMAGE   = 2;
-    
-  // The header is a byte IRL. 0 - 255 and tells packet type
-  public void Recv(int Header, byte[] Payload);
-}
diff --git a/tools/EventClients/Clients/J2ME Client/src/BluetoothServiceDiscovery.java b/tools/EventClients/Clients/J2ME Client/src/BluetoothServiceDiscovery.java
deleted file mode 100644
index 3ff71f1..0000000
--- a/tools/EventClients/Clients/J2ME Client/src/BluetoothServiceDiscovery.java	
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
-* XBMC Media Center
-* UDP Event Server
-* Copyright (c) 2008 topfs2
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-import java.util.Vector;
-import javax.bluetooth.DeviceClass;
-import javax.bluetooth.DiscoveryAgent;
-import javax.bluetooth.DiscoveryListener;
-import javax.bluetooth.LocalDevice;
-import javax.bluetooth.RemoteDevice;
-import javax.bluetooth.ServiceRecord;
-import javax.bluetooth.UUID;
-
-import javax.microedition.lcdui.*;
-
-public class BluetoothServiceDiscovery implements DiscoveryListener
-{
-	private static Object lock=new Object();
-	private static Vector vecDevices=new Vector();
-	private static String connectionURL=null;
-
-	public static String Scan(Form Log, String ScanForUUID) throws Exception
-  {
-    BluetoothServiceDiscovery bluetoothServiceDiscovery=new BluetoothServiceDiscovery();
-    //display local device address and name
-    LocalDevice localDevice = LocalDevice.getLocalDevice();
-    //find devices
-    DiscoveryAgent agent = localDevice.getDiscoveryAgent();
-
-    agent.startInquiry(DiscoveryAgent.GIAC, bluetoothServiceDiscovery);
-    try 
-    {
-      synchronized(lock)
-      { lock.wait(); }
-    }
-    catch (InterruptedException e)
-    {
-      e.printStackTrace();
-    }
-    Log.append("Device Inquiry Completed. \n");
-
-    int deviceCount=vecDevices.size();
-    if(deviceCount <= 0)
-    {
-      Log.append("No Devices Found .\n");
-      return null;
-    }
-    else
-    {
-      Log.append("Bluetooth Devices: \n");
-      for (int i = 0; i <deviceCount; i++)
-      {
-        RemoteDevice remoteDevice=(RemoteDevice)vecDevices.elementAt(i);
-        String t = i + ": \"" + remoteDevice.getFriendlyName(true) + "\"";
-        Log.append(t + "\n");
-      }
-    }
-    UUID[] uuidSet = new UUID[1];
-    if (ScanForUUID != null)
-      uuidSet[0]=new UUID(ScanForUUID, true);
-    else
-      uuidSet[0]=new UUID("ACDC", true);
-
-    for (int i = 0; i < vecDevices.capacity(); i++)
-    {
-      RemoteDevice remoteDevice=(RemoteDevice)vecDevices.elementAt(i);
-      String t = remoteDevice.getFriendlyName(true);
-      agent.searchServices(null,uuidSet,remoteDevice,bluetoothServiceDiscovery);
-      try
-      {
-        synchronized(lock)
-        { lock.wait(); }
-      }
-      catch (InterruptedException e)
-      {
-        e.printStackTrace();
-      }
-      if(connectionURL != null)
-        return connectionURL;
-    }
-    Log.append("Couldn't find any computer that were suitable\n");
-    return null;
-	}
-
-	public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod)
-  {
-		if(!vecDevices.contains(btDevice))
-			vecDevices.addElement(btDevice);
-	}
-
-	public void servicesDiscovered(int transID, ServiceRecord[] servRecord)
-  {
-		if(servRecord!=null && servRecord.length>0){
-			connectionURL=servRecord[0].getConnectionURL(0,false);
-		}
-		synchronized(lock)
-    { lock.notify(); }
-	}
-
-	public void serviceSearchCompleted(int transID, int respCode)
-  {
-		synchronized(lock)
-    { lock.notify(); }
-	}
-
-	public void inquiryCompleted(int discType)
-  {
-		synchronized(lock)
-    { lock.notify(); }
-	}
-}
diff --git a/tools/EventClients/Clients/J2ME Client/src/KeyCanvas.java b/tools/EventClients/Clients/J2ME Client/src/KeyCanvas.java
deleted file mode 100644
index 8c2153c..0000000
--- a/tools/EventClients/Clients/J2ME Client/src/KeyCanvas.java	
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-* XBMC Media Center
-* UDP Event Server
-* Copyright (c) 2008 topfs2
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-import javax.microedition.lcdui.*;
-
-public class KeyCanvas extends Canvas
-{
-  private KeyHandler m_SendKey = null;
-  private Image Cover = null;
-  private boolean SetCover = false;
-
-  public KeyCanvas(KeyHandler sendKey)
-  {
-    m_SendKey = sendKey;
-    try
-    {
-//      Cover = Image.createImage("home.png");
-    }
-    catch (Exception e)
-    { }
-  }
-
-  public void SetCover(Image newCover)
-  {
-    if (newCover != null)
-    {
-      SetCover = true;
-      Cover = newCover;
-    }
-  }
-
-  public void paint(Graphics g)
-  {
-    g.drawRect(0, 0, this.getWidth(), this.getHeight());
-    if (Cover != null)
-      g.drawImage(Cover, 0, 0, g.TOP|g.LEFT);
-  }
-
-  public void keyPressed(int keyCode)
-  {
-    if (m_SendKey != null)
-      m_SendKey.keyPressed(keyCode);
-  }
-
-  public void keyRepeated(int keyCode)
-  {
-    if (m_SendKey != null)
-      m_SendKey.keyPressed(keyCode);
-  }
-}
diff --git a/tools/EventClients/Clients/J2ME Client/src/KeyHandler.java b/tools/EventClients/Clients/J2ME Client/src/KeyHandler.java
deleted file mode 100644
index a6a5ac1..0000000
--- a/tools/EventClients/Clients/J2ME Client/src/KeyHandler.java	
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-* XBMC Media Center
-* UDP Event Server
-* Copyright (c) 2008 topfs2
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-public interface KeyHandler
-{
-  public void keyPressed(int keyCode);
-}
diff --git a/tools/EventClients/Clients/J2ME Client/src/MainScreen.java b/tools/EventClients/Clients/J2ME Client/src/MainScreen.java
deleted file mode 100644
index 2e68c7d..0000000
--- a/tools/EventClients/Clients/J2ME Client/src/MainScreen.java	
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
-* XBMC Media Center
-* UDP Event Server
-* Copyright (c) 2008 topfs2
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-import java.util.Vector;
-import javax.bluetooth.DeviceClass;
-import javax.bluetooth.DiscoveryAgent;
-import javax.bluetooth.DiscoveryListener;
-import javax.bluetooth.LocalDevice;
-import javax.bluetooth.RemoteDevice;
-import javax.bluetooth.ServiceRecord;
-import javax.bluetooth.UUID;
-
-import javax.microedition.midlet.*;
-import javax.microedition.lcdui.*;
-
-public class MainScreen extends MIDlet implements CommandListener, KeyHandler, BluetoothEvent
-{
-  private boolean LogActive = true;
-  private final int VersionMajor = 0;
-  private final int VersionMinor = 1;
-  private final String Version = (VersionMajor + "." + VersionMinor);
-
-  private final Command CMD_OK            = new Command("OK", Command.OK, 1);
-  private final Command CMD_CONNECT       = new Command("Connect", Command.OK, 1);
-  private final Command CMD_DISCONNECT    = new Command("Disconnect", Command.CANCEL, 1);
-  private final Command CMD_EXIT          = new Command("Exit", Command.CANCEL, 1);
-  private final Command CMD_LOG           = new Command("Log", Command.OK, 1);
-  private final Command CMD_SHOWREMOTE    = new Command("Remote", Command.OK, 1);
-  private Display display;
-  private Form MainForm;
-
-  private KeyCanvas keyHandler;
-  private BluetoothCommunicator RecvThread;
-
-  private final int CONNECTED     = 1;
-  private final int NOT_CONNECTED  = -1;
-  private final int CONNECTING    = 0;
-
-  private int Connect = NOT_CONNECTED;
-
-  public MainScreen()
-  {
-    display = Display.getDisplay(this);
-    keyHandler = new KeyCanvas(this);
-    keyHandler.addCommand(CMD_LOG);
-    keyHandler.addCommand(CMD_DISCONNECT);
-    keyHandler.setCommandListener(this);
-  }
-
-
-  public void Disconnect()
-  {
-    RecvThread.close();
-    BluetoothCommunicator.Disconnect();
-    MainForm.removeCommand(CMD_DISCONNECT);
-    MainForm.removeCommand(CMD_SHOWREMOTE);
-    MainForm.addCommand(CMD_CONNECT);
-    Connect = NOT_CONNECTED;
-  }
-
-  public void Connect()
-  {
-    if (Connect == CONNECTED)
-      return;
-    Connect = CONNECTING;
-    MainForm = CreateForm("Connect log");
-    display.setCurrent(MainForm);
-    try
-    {
-      String Connectable = BluetoothServiceDiscovery.Scan(MainForm, "ACDC");
-      if (Connectable != null)
-      {
-        MainForm.append("\n" + Connectable);
-        display.setCurrent(MainForm);
-        if (BluetoothCommunicator.Connect(MainForm, Connectable))
-          Connect = CONNECTED;
-        else
-          Connect = NOT_CONNECTED;
-        
-        display.setCurrent(MainForm);
-        BluetoothCommunicator.Handshake(MainForm, display);
-        RecvThread = new BluetoothCommunicator(this, MainForm);
-        
-        display.setCurrent(MainForm);
-      }
-    }
-    catch (Exception e)
-    {
-      MainForm.append("Error: Couldn't Search");
-      Connect = NOT_CONNECTED;
-      display.setCurrent(MainForm);
-      return;
-    }
-
-    if (Connect == CONNECTED)
-    {
-      MainForm.addCommand(CMD_SHOWREMOTE);
-      MainForm.addCommand(CMD_DISCONNECT);
-      MainForm.append("Connected to a server now we start the receive thread\n");
-      RecvThread.start();
-    }
-    else
-    {
-      MainForm.addCommand(CMD_CONNECT);
-      MainForm.addCommand(CMD_EXIT);
-      MainForm.append("Not connected to a server");
-    }
-    setCurrent();
-  }
-
-  public void startApp()
-  {
-    int length = ((255 << 8) | (255));
-    System.out.println("Len " + length);
-    
-    
-    MainForm = CreateForm("XBMC Remote");
-    MainForm.append("Hi and welcome to the version " + Version + " of XBMC Remote.\nPressing Connect will have this remote connect to the first available Server");
-    setCurrent();
-  }
-
-  private Form CreateForm(String Title)
-  {
-    Form rtnForm = new Form(Title);
-    if (Connect == CONNECTED)
-      rtnForm.addCommand(CMD_OK);
-    else if (Connect == NOT_CONNECTED)
-      rtnForm.addCommand(CMD_CONNECT);
-    
-    if (Connect == CONNECTED)
-      rtnForm.addCommand(CMD_DISCONNECT);
-    else if (Connect == NOT_CONNECTED)
-      rtnForm.addCommand(CMD_EXIT);
-
-    rtnForm.setCommandListener(this);
-    return rtnForm;
-  }
-
-  private void setCurrent()
-  {
-    setCurrent(false);
-  }
-  private void setCurrent(boolean forceLog)
-  {
-    if (forceLog)
-      display.setCurrent(MainForm);
-    else if (Connect == CONNECTED)
-    {
-      display.setCurrent(keyHandler);
-      keyHandler.repaint();
-    }
-    else
-    {
-      display.setCurrent(MainForm);
-    }
-  }
-
-  public void pauseApp()
-  {
-  }
-
-  public void destroyApp(boolean unconditional)
-  {
-    if (Connect == CONNECTED)
-    {
-      BluetoothCommunicator.Disconnect();
-      RecvThread.close();
-    }
-  }
-
-  public void commandAction(Command c, Displayable d)
-  {
-    if (c.equals(CMD_LOG))
-      setCurrent(true);
-    else if (c.equals(CMD_SHOWREMOTE))
-    {
-      display.setCurrent(keyHandler);
-      keyHandler.repaint();
-    }
-    else if (d.equals(MainForm))
-    {
-      if      (c.equals(CMD_OK))
-      {
-        byte[] Packet = {'1', '1'}; // 48 == '0'
-        BluetoothCommunicator.Send(Packet);
-      }
-      else if (c.equals(CMD_CONNECT))
-      {
-        this.Connect();
-      }
-      else if (c.equals(CMD_EXIT))
-        System.out.println("QUIT");
-      else if (c.equals(CMD_DISCONNECT))
-      {
-        this.Disconnect();
-        this.RecvThread.close();
-        setCurrent();
-      }
-    }
-    else if (d.equals(keyHandler))
-    {
-      if (c.equals(CMD_OK))
-      {
-        byte[] Packet = {'2', (byte)251 };
-        BluetoothCommunicator.Send(Packet);
-      }
-      else if (c.equals(CMD_DISCONNECT))
-      {
-        this.Disconnect();
-        Connect = NOT_CONNECTED;
-        setCurrent();
-      }
-    }
-  }
-
-  public void keyPressed(int keyCode)
-  {
-    byte[] Packet = {'2', (byte)keyCode};
-    if (keyCode >= Canvas.KEY_NUM0 && keyCode <= Canvas.KEY_NUM9)
-      Packet[1] = (byte)keyCode;
-    
-    else if (keyCode == Canvas.UP       || keyCode == -1)
-      Packet[1] = 'U';
-    else if (keyCode == Canvas.DOWN     || keyCode == -2)
-      Packet[1] = 'D';
-    else if (keyCode == Canvas.LEFT     || keyCode == -3)
-      Packet[1] = 'L';
-    else if (keyCode == Canvas.RIGHT    || keyCode == -4)
-      Packet[1] = 'R';
-
-    else if (keyCode == Canvas.KEY_STAR)
-      Packet[1] = '*';
-    else if (keyCode == Canvas.KEY_POUND)
-      Packet[1] = '#';
-    
-    BluetoothCommunicator.Send(Packet);
-    System.out.println("got" + keyCode + " I'll send [" + Packet[0] + "," + Packet[1] + "]");
-  }
-  public void Recv(int Header, byte[] Payload)
-  {
-    switch(Header)
-    {
-      case BluetoothEvent.RECV_COMMAND:
-        break;
-      case BluetoothEvent.RECV_SYSTEM:
-        if (Payload[0] == 0)
-          this.Disconnect();
-        break;
-      case BluetoothEvent.RECV_IMAGE:
-        keyHandler.SetCover(Image.createImage(Payload, 0, Payload.length));
-        break;
-    }
-  }
-}
diff --git a/tools/EventClients/Clients/J2ME Client/src/XBMCRemote.jad b/tools/EventClients/Clients/J2ME Client/src/XBMCRemote.jad
deleted file mode 100644
index e40999e..0000000
--- a/tools/EventClients/Clients/J2ME Client/src/XBMCRemote.jad	
+++ /dev/null
@@ -1,9 +0,0 @@
-MIDlet-1: MainScreen, , MainScreen
-MIDlet-Icon: icon.png
-MIDlet-Jar-Size: 12153
-MIDlet-Jar-URL: XBMC Remote.jar
-MIDlet-Name: XBMC Remote
-MIDlet-Vendor: team-xbmc
-MIDlet-Version: 0.1
-MicroEdition-Configuration: CLDC-1.0
-MicroEdition-Profile: MIDP-1.0
diff --git a/tools/EventClients/Clients/WiiRemote/CMakeLists.txt b/tools/EventClients/Clients/WiiRemote/CMakeLists.txt
new file mode 100644
index 0000000..2442d61
--- /dev/null
+++ b/tools/EventClients/Clients/WiiRemote/CMakeLists.txt
@@ -0,0 +1,22 @@
+list(APPEND CMAKE_MODULE_PATH ${CORE_SOURCE_DIR}/project/cmake/modules)
+
+find_package(Bluetooth REQUIRED)
+find_package(CWiid REQUIRED)
+
+set(SOURCES CWIID_WiiRemote.cpp)
+
+set(HEADERS CWIID_WiiRemote.h)
+
+add_executable(${APP_NAME_LC}-wiiremote ${SOURCES} ${HEADERS})
+
+target_include_directories(${APP_NAME_LC}-wiiremote
+                           PRIVATE ${BLUETOOTH_INCLUDE_DIRS}
+                                   ${CWIID_INCLUDE_DIRS})
+
+target_link_libraries(${APP_NAME_LC}-wiiremote
+                      PRIVATE ${SYSTEM_LDFLAGS}
+                              ${BLUETOOTH_LIBRARIES}
+                              ${CWIID_LIBRARIES})
+
+target_compile_options(${APP_NAME_LC}-wiiremote PRIVATE ${ARCH_DEFINES})
+
diff --git a/tools/EventClients/Makefile.in b/tools/EventClients/Makefile.in
index 757ee0b..2cd5712 100644
--- a/tools/EventClients/Makefile.in
+++ b/tools/EventClients/Makefile.in
@@ -10,14 +10,9 @@ Clients/WiiRemote/WiiRemote:
 	cd Clients/WiiRemote && \
 	$(CXX) $(CXXFLAGS) $(LDFLAGS) CWIID_WiiRemote.cpp -lcwiid -lbluetooth -DICON_PATH="\"$(datarootdir)/pixmaps/@APP_NAME_LC@/\"" $(WII_EXTRA_OPTS) -o WiiRemote
 
-j2me-remote:
-	cd Clients/J2ME\ Client
-	ant -f build.xml
-
 install: Clients/WiiRemote/WiiRemote
 	mkdir -p $(DESTDIR)$(bindir)
 	cp -a Clients/WiiRemote/WiiRemote $(DESTDIR)$(bindir)/@APP_NAME_LC at -wiiremote
-	cp -a Clients/J2ME\ Client/j2me_remote.py $(DESTDIR)$(bindir)/@APP_NAME_LC at -j2meremote
 	cp -a Clients/PS3\ BD\ Remote/ps3_remote.py $(DESTDIR)$(bindir)/@APP_NAME_LC at -ps3remote
 	cp -a Clients/PS3\ Sixaxis\ Controller/ps3d.py $(DESTDIR)$(bindir)/@APP_NAME_LC at -ps3d
 	cp -a Clients/Kodi\ Send/kodi-send.py $(DESTDIR)$(bindir)/@APP_NAME_LC at -send
diff --git a/tools/EventClients/README.txt b/tools/EventClients/README.txt
index 6e1a454..591964f 100644
--- a/tools/EventClients/README.txt
+++ b/tools/EventClients/README.txt
@@ -88,14 +88,3 @@ The WiiRemote is mappable with keymap.xml where button id's are the following:
 10 = 1
 11 = 2
 The name is by standard WiiRemote but this can be changed with the --joystick-name
-
-J2ME (Java Phone Application)
------------------------------
-
-To use the J2ME client only CLDC 1.0 and MIDP 1.0 is needed.
-The client will also need bluetooth and must be able to initialize the connection.
-For compilation of the Java Application see Clients/J2ME Client/README but precompiled versions
-exists in our forum.
-
-The Client is mappable in the same manner as PS3 in keymap.xml but with the name J2ME (<joystick name="J2ME">).
-The KeyID's generated in terminal when running j2me_remote.py.
diff --git a/tools/android/packaging/xbmc/AndroidManifest.xml.in b/tools/android/packaging/xbmc/AndroidManifest.xml.in
index dcf3d55..b4dc83e 100644
--- a/tools/android/packaging/xbmc/AndroidManifest.xml.in
+++ b/tools/android/packaging/xbmc/AndroidManifest.xml.in
@@ -87,7 +87,6 @@
         <receiver android:name=".XBMCBroadcastReceiver" >
             <intent-filter>
                 <action android:name="android.intent.action.DREAMING_STOPPED" />
-                <action android:name="android.intent.action.HEADSET_PLUG" />
                 <action android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
                 <action android:name="android.intent.action.MEDIA_BUTTON" />
             </intent-filter>
diff --git a/tools/buildsteps/linux64/run-tests b/tools/buildsteps/linux64/run-tests
index 265ff01..abcaea4 100755
--- a/tools/buildsteps/linux64/run-tests
+++ b/tools/buildsteps/linux64/run-tests
@@ -4,7 +4,11 @@ XBMC_PLATFORM_DIR=linux64
 
 if [ "$CMAKE_BUILD" = true ]; then
   cd $WORKSPACE/build;make -j$BUILDTHREADS kodi-test
-  cd $WORKSPACE;build/kodi-test --gtest_output=xml:gtestresults.xml
+  if [ "$Configuration" != "Coverage" ]; then
+    cd $WORKSPACE;build/kodi-test --gtest_output=xml:gtestresults.xml
+  else
+    cd $WORKSPACE/build;GTEST_OUTPUT="xml:$WORKSPACE/gtestresults.xml" make coverage
+  fi
 else
   cd $WORKSPACE;make -j$BUILDTHREADS testsuite
   cd $WORKSPACE;./kodi-test --gtest_output=xml:gtestresults.xml
diff --git a/tools/buildsteps/win32/buildffmpeg.sh b/tools/buildsteps/win32/buildffmpeg.sh
index 9283838..99515fd 100644
--- a/tools/buildsteps/win32/buildffmpeg.sh
+++ b/tools/buildsteps/win32/buildffmpeg.sh
@@ -138,7 +138,7 @@ do_print_status "$LIBNAME-$VERSION (${BITS})" "$blue_color" "Configuring"
   --extra-cflags="$extra_cflags" --extra-ldflags="$extra_ldflags"
 
 do_makelib &&
-cp $FFMPEGDESTDIR/bin/*.dll /xbmc/system/players/VideoPlayer/ &&
+cp $FFMPEGDESTDIR/bin/*.dll /xbmc/system/ &&
 
 #remove the bgprocessfile for signaling the process end
 if [ -f $BGPROCESSFILE ]; then
diff --git a/tools/buildsteps/win32/buildlibdvd.sh b/tools/buildsteps/win32/buildlibdvd.sh
index 7fddea0..3dab424 100644
--- a/tools/buildsteps/win32/buildlibdvd.sh
+++ b/tools/buildsteps/win32/buildlibdvd.sh
@@ -26,7 +26,7 @@ CC="gcc -static-libgcc" \
 do_makelib $MAKEFLAGS
 
 strip -S $LIBDVDPREFIX/bin/libdvdcss-2.dll &&
-cp "$LIBDVDPREFIX/bin/libdvdcss-2.dll" /xbmc/system/players/VideoPlayer/
+cp "$LIBDVDPREFIX/bin/libdvdcss-2.dll" /xbmc/system/
 
 #libdvdread
 do_load_autoconf /xbmc/tools/depends/target/libdvdread/DVDREAD-VERSION 
@@ -62,7 +62,7 @@ gcc \
    -static-libgcc
 
 strip -S $LIBDVDPREFIX/bin/libdvdnav.dll &&
-cp $LIBDVDPREFIX/bin/libdvdnav.dll /xbmc/system/players/VideoPlayer/
+cp $LIBDVDPREFIX/bin/libdvdnav.dll /xbmc/system/
 do_print_status "libdvd (${BITS})" "$green_color" "Done"
 
 #remove the bgprocessfile for signaling the process end
diff --git a/tools/buildsteps/win32/make-mingwlibs.sh b/tools/buildsteps/win32/make-mingwlibs.sh
index 6c58b7d..e657e96 100644
--- a/tools/buildsteps/win32/make-mingwlibs.sh
+++ b/tools/buildsteps/win32/make-mingwlibs.sh
@@ -80,7 +80,7 @@ echo "-------------------------------------------------"
 echo " building FFmpeg $BITS"
 echo "-------------------------------------------------"
 runBackgroundProcess "./buildffmpeg.sh $MAKECLEAN"
-setfilepath /xbmc/system/players/VideoPlayer
+setfilepath /xbmc/system
 checkfiles avcodec-57.dll avformat-57.dll avutil-55.dll postproc-54.dll swscale-4.dll avfilter-6.dll swresample-2.dll
 echo "-------------------------------------------------"
 echo " building of FFmpeg $BITS done..."
@@ -91,7 +91,7 @@ echo "-------------------------------------------------"
 echo " building libdvd $BITS"
 echo "-------------------------------------------------"
 runBackgroundProcess "./buildlibdvd.sh $MAKECLEAN"
-setfilepath /xbmc/system/players/VideoPlayer
+setfilepath /xbmc/system
 checkfiles libdvdcss-2.dll libdvdnav.dll
 echo "-------------------------------------------------"
 echo " building of libdvd $BITS done..."
diff --git a/tools/buildsteps/win32/run-tests.bat b/tools/buildsteps/win32/run-tests.bat
index 4954bdc..cfde6d7 100644
--- a/tools/buildsteps/win32/run-tests.bat
+++ b/tools/buildsteps/win32/run-tests.bat
@@ -5,12 +5,13 @@ SET cur_dir=%WORKSPACE%\project\Win32BuildSetup
 cd %cur_dir%
 SET base_dir=%cur_dir%\..\..
 SET builddeps_dir=%cur_dir%\..\..\project\BuildDependencies
-SET bin_dir=%builddeps_dir%\bin
-SET msys_bin_dir=%builddeps_dir%\msys\bin
+SET msys_dir=%builddeps_dir%\msys64
+IF NOT EXIST %msys_dir% (SET msys_dir=%builddeps_dir%\msys32)
+SET awk_exe=%msys_dir%\usr\bin\awk.exe
+SET sed_exe=%msys_dir%\usr\bin\sed.exe
+
 REM read the version values from version.txt
-FOR /f %%i IN ('%msys_bin_dir%\awk.exe "/APP_NAME/ {print $2}" %base_dir%\version.txt') DO SET APP_NAME=%%i
-FOR /f %%i IN ('%msys_bin_dir%\awk.exe "/COMPANY_NAME/ {print $2}" %base_dir%\version.txt') DO SET COMPANY=%%i
-FOR /f %%i IN ('%msys_bin_dir%\awk.exe "/WEBSITE/ {print $2}" %base_dir%\version.txt') DO SET WEBSITE=%%i
+FOR /f %%i IN ('%awk_exe% "/APP_NAME/ {print $2}" %base_dir%\version.txt') DO SET APP_NAME=%%i
 
 CLS
 COLOR 1B
@@ -56,7 +57,7 @@ ECHO Compiling testsuite...
 %NET% %OPTS_EXE%
 
 IF %errorlevel%==1 (
-  set DIETEXT="%APP_NAME%-test.EXE failed to build!  See %CD%\..\vs2010express\XBMC\%buildconfig%\objs\XBMC.log"
+  set DIETEXT="%APP_NAME%-test.exe failed to build!  See %CD%\..\vs2010express\XBMC\%buildconfig%\objs\XBMC.log"
   type "%CD%\..\vs2010express\XBMC\%buildconfig%\objs\XBMC.log"
   goto DIE
 )
@@ -67,7 +68,7 @@ ECHO ------------------------------------------------------------
 ECHO Running testsuite...
   cd %WORKSPACE%\project\vs2010express\
   set KODI_HOME=%WORKSPACE%
-  set PATH=%WORKSPACE%\project\Win32BuildSetup\dependencies;%PATH%
+  set PATH=%WORKSPACE%\system;%PATH%
 
   %EXE% --gtest_output=xml:%WORKSPACE%\gtestresults.xml
 
@@ -77,7 +78,7 @@ ECHO Running testsuite...
   rem <testcase name="IsStarted" status="notrun" time="0" classname="TestWebServer"/>
   rem becomes
   rem <testcase name="IsStarted" status="notrun" time="0" classname="TestWebServer"><skipped/></testcase>
-  %msys_bin_dir%\sed.exe "s/<testcase\(.*\)\"notrun\"\(.*\)\/>$/<testcase\1\"notrun\"\2><skipped\/><\/testcase>/" %WORKSPACE%\gtestresults.xml > %WORKSPACE%\gtestresults-skipped.xml
+  %sed_exe% "s/<testcase\(.*\)\"notrun\"\(.*\)\/>$/<testcase\1\"notrun\"\2><skipped\/><\/testcase>/" %WORKSPACE%\gtestresults.xml > %WORKSPACE%\gtestresults-skipped.xml
   del %WORKSPACE%\gtestresults.xml
   move %WORKSPACE%\gtestresults-skipped.xml %WORKSPACE%\gtestresults.xml
 ECHO Done running testsuite!
diff --git a/tools/darwin/Support/CopyRootFiles-ios.command b/tools/darwin/Support/CopyRootFiles-ios.command
index 23f78bc..9781090 100755
--- a/tools/darwin/Support/CopyRootFiles-ios.command
+++ b/tools/darwin/Support/CopyRootFiles-ios.command
@@ -44,8 +44,7 @@ SYNCSKIN_A="${SKINSYNC} --exclude *.png --exclude *.jpg"
 fi
 ${SYNCSKIN_A} "$SRCROOT/addons/skin.estouchy"    "$TARGET_BUILD_DIR/$TARGET_NAME/AppData/AppHome/addons"
 ${SYNC} "$SRCROOT/addons/skin.estouchy/background"   "$TARGET_BUILD_DIR/$TARGET_NAME/AppData/AppHome/addons/skin.estouchy"
-${SYNC} "$SRCROOT/addons/skin.estouchy/icon.png"   "$TARGET_BUILD_DIR/$TARGET_NAME/AppData/AppHome/addons/skin.estouchy"
-${SYNC} "$SRCROOT/addons/skin.estouchy/fanart.jpg"   "$TARGET_BUILD_DIR/$TARGET_NAME/AppData/AppHome/addons/skin.estouchy"
+${SYNC} "$SRCROOT/addons/skin.estouchy/resources"   "$TARGET_BUILD_DIR/$TARGET_NAME/AppData/AppHome/addons/skin.estouchy"
 
 # sync skin.estuary
 SYNCSKIN_B=${SKINSYNC}
@@ -54,8 +53,7 @@ SYNCSKIN_B="${SKINSYNC} --exclude *.png --exclude *.jpg"
 fi
 ${SYNCSKIN_B} "$SRCROOT/addons/skin.estuary"     "$TARGET_BUILD_DIR/$TARGET_NAME/AppData/AppHome/addons"
 ${SYNC} "$SRCROOT/addons/skin.estuary/extras"   "$TARGET_BUILD_DIR/$TARGET_NAME/AppData/AppHome/addons/skin.estuary"
-${SYNC} "$SRCROOT/addons/skin.estuary/icon.png"    "$TARGET_BUILD_DIR/$TARGET_NAME/AppData/AppHome/addons/skin.estuary"
-${SYNC} "$SRCROOT/addons/skin.estuary/fanart.jpg"    "$TARGET_BUILD_DIR/$TARGET_NAME/AppData/AppHome/addons/skin.estuary"
+${SYNC} "$SRCROOT/addons/skin.estuary/resources"   "$TARGET_BUILD_DIR/$TARGET_NAME/AppData/AppHome/addons/skin.estuary"
 
 ${SYNC} "$SRCROOT/system"     "$TARGET_BUILD_DIR/$TARGET_NAME/AppData/AppHome"
 ${SYNC} "$SRCROOT/userdata"   "$TARGET_BUILD_DIR/$TARGET_NAME/AppData/AppHome"
diff --git a/tools/darwin/Support/CopyRootFiles-osx.command b/tools/darwin/Support/CopyRootFiles-osx.command
index a4831eb..c59354c 100755
--- a/tools/darwin/Support/CopyRootFiles-osx.command
+++ b/tools/darwin/Support/CopyRootFiles-osx.command
@@ -35,12 +35,10 @@ ${ADDONSYNC} "$SRCROOT/addons"		"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resourc
 ${SYNC} "$SRCROOT/media" 		"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/$APP_NAME"
 ${SYNCSKIN} "$SRCROOT/addons/skin.estuary" 	"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/$APP_NAME/addons"
 ${SYNC} "$SRCROOT/addons/skin.estuary/extras" 	"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/$APP_NAME/addons/skin.estuary"
-${SYNC} "$SRCROOT/addons/skin.estuary/icon.png" 	"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/$APP_NAME/addons/skin.estuary"
-${SYNC} "$SRCROOT/addons/skin.estuary/fanart.jpg"   "$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/$APP_NAME/addons/skin.estuary"
+${SYNC} "$SRCROOT/addons/skin.estuary/resources"   "$TARGET_BUILD_DIR/$TARGET_NAME/AppData/AppHome/addons/skin.estuary"
 ${SYNCSKIN} "$SRCROOT/addons/skin.estouchy" 	"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/$APP_NAME/addons"
 ${SYNC} "$SRCROOT/addons/skin.estouchy/background" 	"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/$APP_NAME/addons/skin.estouchy"
-${SYNC} "$SRCROOT/addons/skin.estouchy/icon.png" 	"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/$APP_NAME/addons/skin.estouchy"
-${SYNC} "$SRCROOT/addons/skin.estouchy/fanart.jpg" 	"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/$APP_NAME/addons/skin.estouchy"
+${SYNC} "$SRCROOT/addons/skin.estouchy/resources" 	"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/$APP_NAME/addons/skin.estouchy"
 ${SYNC} "$SRCROOT/system" 		"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/$APP_NAME"
 ${SYNC} "$SRCROOT/userdata" 	"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/$APP_NAME"
 
diff --git a/tools/depends/configure.ac b/tools/depends/configure.ac
index 11b60e2..fb0bd6d 100644
--- a/tools/depends/configure.ac
+++ b/tools/depends/configure.ac
@@ -593,5 +593,7 @@ if test "x$has_localeconv" == "xno" && test "$platform_os" == "android"; then
 fi
 
 cp -vf target/config.site $prefix/$deps_dir/share
+cp -vf target/config-binaddons.site $prefix/$tool_dir/share
 cp -vf target/Toolchain.cmake $prefix/$deps_dir/share
+cp -vf target/Toolchain_binaddons.cmake $prefix/$deps_dir/share
 cp -vf native/config.site.native $prefix/$tool_dir/share/config.site
diff --git a/tools/depends/native/python27-native/Makefile b/tools/depends/native/python27-native/Makefile
index cfa705e..ed3e76a 100644
--- a/tools/depends/native/python27-native/Makefile
+++ b/tools/depends/native/python27-native/Makefile
@@ -4,7 +4,7 @@ DEPS= ../../Makefile.include.in Makefile
 
 # lib name, version
 LIBNAME=Python
-VERSION=2.7.11
+VERSION=2.7.12
 SOURCE=$(LIBNAME)-$(VERSION)
 ARCHIVE=$(SOURCE).tar.xz
 CWD=$(shell pwd)
diff --git a/userdata/iOS/sources.xml b/userdata/iOS/sources.xml
new file mode 100644
index 0000000..db2ff31
--- /dev/null
+++ b/userdata/iOS/sources.xml
@@ -0,0 +1,32 @@
+<sources>
+    <programs>
+        <default pathversion="1"></default>
+    </programs>
+    <video>
+        <default pathversion="1"></default>
+        <source>
+            <name>Inbox</name>
+            <path pathversion="1">special://envhome/Documents/Inbox/</path>
+            <allowsharing>true</allowsharing>
+        </source>
+    </video>
+    <music>
+        <default pathversion="1"></default>
+        <source>
+            <name>Inbox</name>
+            <path pathversion="1">special://envhome/Documents/Inbox/</path>
+            <allowsharing>true</allowsharing>
+        </source>
+    </music>
+    <pictures>
+        <default pathversion="1"></default>
+        <source>
+            <name>Inbox</name>
+            <path pathversion="1">special://envhome/Documents/Inbox/</path>
+            <allowsharing>true</allowsharing>
+        </source>
+    </pictures>
+    <files>
+        <default pathversion="1"></default>
+    </files>
+</sources>
diff --git a/version.txt b/version.txt
index f044993..b06a5d6 100644
--- a/version.txt
+++ b/version.txt
@@ -3,9 +3,9 @@ COMPANY_NAME XBMC-Foundation
 WEBSITE http://kodi.tv
 VERSION_MAJOR 17
 VERSION_MINOR 0
-VERSION_TAG ALPHA2
-VERSION_CODE 169702
-ADDON_API 16.9.702
+VERSION_TAG ALPHA3
+VERSION_CODE 169703
+ADDON_API 16.9.703
 
 # Notes:
 # Change AC_INIT in configure.ac
diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp
index cdcf53e..1c33cbb 100644
--- a/xbmc/Application.cpp
+++ b/xbmc/Application.cpp
@@ -387,9 +387,14 @@ extern "C" void __stdcall cleanup_emu_environ();
 // Utility function used to copy files from the application bundle
 // over to the user data directory in Application Support/Kodi.
 //
-static void CopyUserDataIfNeeded(const std::string &strPath, const std::string &file)
+static void CopyUserDataIfNeeded(const std::string &strPath, const std::string &file, const std::string &destname = "")
 {
-  std::string destPath = URIUtils::AddFileToFolder(strPath, file);
+  std::string destPath;
+  if (destname == "")
+    destPath = URIUtils::AddFileToFolder(strPath, file);
+  else
+    destPath = URIUtils::AddFileToFolder(strPath, destname);
+  
   if (!CFile::Exists(destPath))
   {
     // need to copy it across
@@ -469,7 +474,12 @@ bool CApplication::Create()
   win32_exception::install_handler();
 
 #endif
-
+  
+  #if defined(TARGET_POSIX)
+    // set special://envhome
+    CSpecialProtocol::SetEnvHomePath(getenv("HOME"));
+  #endif
+    
   // only the InitDirectories* for the current platform should return true
   bool inited = InitDirectoriesLinux();
   if (!inited)
@@ -481,6 +491,10 @@ bool CApplication::Create()
   CopyUserDataIfNeeded("special://masterprofile/", "RssFeeds.xml");
   CopyUserDataIfNeeded("special://masterprofile/", "favourites.xml");
   CopyUserDataIfNeeded("special://masterprofile/", "Lircmap.xml");
+  
+  #ifdef TARGET_DARWIN_IOS
+    CopyUserDataIfNeeded("special://masterprofile/", "iOS/sources.xml", "sources.xml");
+  #endif
 
   if (!CLog::Init(CSpecialProtocol::TranslatePath("special://logpath").c_str()))
   {
@@ -540,7 +554,7 @@ bool CApplication::Create()
       CLog::Log(LOGNOTICE, "WARNING: unsupported ffmpeg version detected");
   }
 #endif
-  
+
   std::string cpuModel(g_cpuInfo.getCPUModel());
   if (!cpuModel.empty())
     CLog::Log(LOGNOTICE, "Host CPU: %s, %d core%s available", cpuModel.c_str(), g_cpuInfo.getCPUCount(), (g_cpuInfo.getCPUCount() == 1) ? "" : "s");
@@ -600,6 +614,8 @@ bool CApplication::Create()
   av_register_all();
   // register avfilter
   avfilter_register_all();
+  // initialize network protocols
+  avformat_network_init();
   // set avutil callback
   av_log_set_callback(ff_avutil_log);
 
@@ -924,6 +940,11 @@ bool CApplication::InitDirectoriesLinux()
     CSpecialProtocol::SetLogPath(strTempPath);
     CreateUserDirs();
   }
+  CSpecialProtocol::SetXBMCBinAddonPath(appBinPath + "/addons");
+
+#if defined(TARGET_ANDROID)
+  CXBMCApp::InitDirectories();
+#endif
 
   return true;
 #else
@@ -1010,7 +1031,7 @@ bool CApplication::InitDirectoriesOSX()
     CSpecialProtocol::SetTempPath(strTempPath);
     CSpecialProtocol::SetLogPath(strTempPath);
   }
-
+  CSpecialProtocol::SetXBMCBinAddonPath(appPath + "/addons");
   return true;
 #else
   return false;
@@ -1026,6 +1047,7 @@ bool CApplication::InitDirectoriesWin32()
   CEnvironment::setenv("KODI_HOME", xbmcPath);
   CSpecialProtocol::SetXBMCBinPath(xbmcPath);
   CSpecialProtocol::SetXBMCPath(xbmcPath);
+  CSpecialProtocol::SetXBMCBinAddonPath(xbmcPath + "/addons");
 
   std::string strWin32UserFolder = CWIN32Util::GetProfilePath();
   CSpecialProtocol::SetLogPath(strWin32UserFolder);
@@ -1037,16 +1059,13 @@ bool CApplication::InitDirectoriesWin32()
 
   CreateUserDirs();
 
-  // Expand the DLL search path with our directories
-  CWIN32Util::ExtendDllPath();
-
   return true;
 #else
   return false;
 #endif
 }
 
-void CApplication::CreateUserDirs()
+void CApplication::CreateUserDirs() const
 {
   CDirectory::Create("special://home/");
   CDirectory::Create("special://home/addons");
@@ -1057,6 +1076,12 @@ void CApplication::CreateUserDirs()
   CDirectory::Create("special://temp/");
   CDirectory::Create("special://logpath");
   CDirectory::Create("special://temp/temp"); // temp directory for python and dllGetTempPathA
+
+  //Let's clear our archive cache before starting up anything more
+  auto archiveCachePath = CSpecialProtocol::TranslatePath("special://temp/archive_cache/");
+  CDirectory::Remove(archiveCachePath);
+  CDirectory::Create(archiveCachePath);
+
 }
 
 bool CApplication::Initialize()
@@ -1442,6 +1467,18 @@ void CApplication::OnSettingAction(const CSetting *setting)
     g_windowManager.ActivateWindow(WINDOW_SCREEN_CALIBRATION);
   else if (settingId == CSettings::SETTING_VIDEOSCREEN_TESTPATTERN)
     g_windowManager.ActivateWindow(WINDOW_TEST_PATTERN);
+  else if (settingId == CSettings::SETTING_SOURCE_VIDEOS)
+  {
+    std::vector<std::string> params{"library://video/files.xml", "return"};
+    g_windowManager.ActivateWindow(WINDOW_VIDEO_NAV, params);
+  }
+  else if (settingId == CSettings::SETTING_SOURCE_MUSIC)
+  {
+    std::vector<std::string> params{"library://music/files.xml", "return"};
+    g_windowManager.ActivateWindow(WINDOW_MUSIC_NAV, params);
+  }
+  else if (settingId == CSettings::SETTING_SOURCE_PICTURES)
+    g_windowManager.ActivateWindow(WINDOW_PICTURES);
 }
 
 bool CApplication::OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode)
@@ -2138,7 +2175,7 @@ bool CApplication::OnAction(const CAction &action)
   if (action.GetID() == ACTION_PREV_ITEM && m_pPlayer->CanSeek())
   {
     SeekTime(0);
-    m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
+    m_pPlayer->SetPlaySpeed(1);
     return true;
   }
 
@@ -2161,7 +2198,7 @@ bool CApplication::OnAction(const CAction &action)
       m_pPlayer->Pause();
       // go back to normal play speed on unpause
       if (!m_pPlayer->IsPaused() && m_pPlayer->GetPlaySpeed() != 1)
-        m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
+        m_pPlayer->SetPlaySpeed(1);
 
       g_audioManager.Enable(m_pPlayer->IsPaused());
       return true;
@@ -2174,7 +2211,7 @@ bool CApplication::OnAction(const CAction &action)
         return OnAction(CAction(ACTION_PAUSE));
       // if we do a FF/RW then go back to normal speed
       if (m_pPlayer->GetPlaySpeed() != 1)
-        m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
+        m_pPlayer->SetPlaySpeed(1);
       return true;
     }
     if (!m_pPlayer->IsPaused())
@@ -2196,7 +2233,7 @@ bool CApplication::OnAction(const CAction &action)
         if (iPlaySpeed > 32 || iPlaySpeed < -32)
           iPlaySpeed = 1;
 
-        m_pPlayer->SetPlaySpeed(iPlaySpeed, g_application.m_muted);
+        m_pPlayer->SetPlaySpeed(iPlaySpeed);
         return true;
       }
       else if ((action.GetAmount() || m_pPlayer->GetPlaySpeed() != 1) && (action.GetID() == ACTION_ANALOG_REWIND || action.GetID() == ACTION_ANALOG_FORWARD))
@@ -2209,7 +2246,7 @@ bool CApplication::OnAction(const CAction &action)
         int iSpeed = 1 << iPower;
         if (iSpeed != 1 && action.GetID() == ACTION_ANALOG_REWIND)
           iSpeed = -iSpeed;
-        g_application.m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
+        g_application.m_pPlayer->SetPlaySpeed(iSpeed);
         if (iSpeed == 1)
           CLog::Log(LOGDEBUG,"Resetting playspeed");
         return true;
@@ -2224,7 +2261,7 @@ bool CApplication::OnAction(const CAction &action)
         m_pPlayer->Pause();
         g_audioManager.Enable(m_pPlayer->IsPaused());
 
-        g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
+        g_application.m_pPlayer->SetPlaySpeed(1);
         return true;
       }
     }
@@ -3165,8 +3202,7 @@ PlayBackRet CApplication::PlayFile(CFileItem item, const std::string& player, bo
     CMediaSettings::GetInstance().GetCurrentAudioSettings() = CMediaSettings::GetInstance().GetDefaultAudioSettings();
     // see if we have saved options in the database
 
-    m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
-    m_pPlayer->m_iPlaySpeed = 1;     // Reset both CApp's & Player's speed else we'll get confused
+    m_pPlayer->SetPlaySpeed(1);
 
     m_itemCurrentFile.reset(new CFileItem(item));
 
@@ -3403,21 +3439,10 @@ PlayBackRet CApplication::PlayFile(CFileItem item, const std::string& player, bo
     iResult = PLAYBACK_FAIL;
   }
 
-  if(iResult == PLAYBACK_OK)
+  if (iResult == PLAYBACK_OK)
   {
-    if (m_pPlayer->GetPlaySpeed() != 1)
-    {
-      int iSpeed = m_pPlayer->GetPlaySpeed();
-      m_pPlayer->m_iPlaySpeed = 1;
-      m_pPlayer->SetPlaySpeed(iSpeed, g_application.m_muted);
-    }
-
-    // if player has volume control, set it.
-    if (m_pPlayer->ControlsVolume())
-    {
-      m_pPlayer->SetVolume(m_volumeLevel);
-      m_pPlayer->SetMute(m_muted);
-    }
+    m_pPlayer->SetVolume(m_volumeLevel);
+    m_pPlayer->SetMute(m_muted);
 
     if(m_pPlayer->IsPlayingAudio())
     {
@@ -4244,9 +4269,6 @@ bool CApplication::OnMessage(CGUIMessage& message)
       else
       {
         m_pPlayer->ClosePlayer();
-
-        // Reset playspeed
-        m_pPlayer->m_iPlaySpeed = 1;
       }
 
       if (!m_pPlayer->IsPlaying())
@@ -4419,10 +4441,6 @@ void CApplication::Process()
   CApplicationMessenger::GetInstance().ProcessMessages();
   if (g_application.m_bStop) return; //we're done, everything has been unloaded
 
-  // check how far we are through playing the current item
-  // and do anything that needs doing (playcount updates etc)
-  CheckPlayingProgress();
-
   // update sound
   m_pPlayer->DoAudioWork();
 
@@ -4713,11 +4731,8 @@ void CApplication::VolumeChanged() const
   CAnnouncementManager::GetInstance().Announce(Application, "xbmc", "OnVolumeChanged", data);
 
   // if player has volume control, set it.
-  if (m_pPlayer->ControlsVolume())
-  {
-     m_pPlayer->SetVolume(m_volumeLevel);
-     m_pPlayer->SetMute(m_muted);
-  }
+  m_pPlayer->SetVolume(m_volumeLevel);
+  m_pPlayer->SetMute(m_muted);
 }
 
 int CApplication::GetSubtitleDelay() const
@@ -5035,30 +5050,6 @@ void CApplication::StartMusicArtistScan(const std::string& strDirectory,
   m_musicInfoScanner->FetchArtistInfo(strDirectory,refresh);
 }
 
-void CApplication::CheckPlayingProgress()
-{
-  // check if we haven't rewound past the start of the file
-  if (m_pPlayer->IsPlaying())
-  {
-    int iSpeed = g_application.m_pPlayer->GetPlaySpeed();
-    if (iSpeed < 1)
-    {
-      iSpeed *= -1;
-      int iPower = 0;
-      while (iSpeed != 1)
-      {
-        iSpeed >>= 1;
-        iPower++;
-      }
-      if (g_infoManager.GetPlayTime() / 1000 < iPower)
-      {
-        g_application.m_pPlayer->SetPlaySpeed(1, g_application.m_muted);
-        g_application.SeekTime(0);
-      }
-    }
-  }
-}
-
 bool CApplication::ProcessAndStartPlaylist(const std::string& strPlayList, CPlayList& playlist, int iPlaylist, int track)
 {
   CLog::Log(LOGDEBUG,"CApplication::ProcessAndStartPlaylist(%s, %i)",strPlayList.c_str(), iPlaylist);
diff --git a/xbmc/Application.h b/xbmc/Application.h
index 5d38663..c14f62d 100644
--- a/xbmc/Application.h
+++ b/xbmc/Application.h
@@ -66,7 +66,7 @@ namespace PLAYLIST
 #include "storage/DetectDVDType.h"
 #endif
 #ifdef TARGET_WINDOWS
-#include "win32/WIN32Util.h"
+#include "platform/win32/WIN32Util.h"
 #endif
 #include "utils/Stopwatch.h"
 #ifdef HAS_PERFORMANCE_SAMPLE
@@ -203,7 +203,6 @@ public:
   bool IsIdleShutdownInhibited() const;
   // Checks whether the screensaver and / or DPMS should become active.
   void CheckScreenSaverAndDPMS();
-  void CheckPlayingProgress();
   void ActivateScreenSaver(bool forceType = false);
   bool SetupNetwork();
   void CloseNetworkShares();
@@ -506,7 +505,7 @@ protected:
   bool InitDirectoriesLinux();
   bool InitDirectoriesOSX();
   bool InitDirectoriesWin32();
-  void CreateUserDirs();
+  void CreateUserDirs() const;
 
   /*! \brief Helper method to determine how to handle TMSG_SHUTDOWN
   */
diff --git a/xbmc/ApplicationPlayer.cpp b/xbmc/ApplicationPlayer.cpp
index f163bcd..a657816 100644
--- a/xbmc/ApplicationPlayer.cpp
+++ b/xbmc/ApplicationPlayer.cpp
@@ -113,6 +113,12 @@ PlayBackRet CApplicationPlayer::OpenFile(const CFileItem& item, const CPlayerOpt
     // check whether the OpenFile was canceled by either CloseFile or another OpenFile.
     if (m_iPlayerOPSeq != startingSeq)
       iResult = PLAYBACK_CANCELED;
+
+    // reset caching timers
+    m_audioStreamUpdate.SetExpired();
+    m_videoStreamUpdate.SetExpired();
+    m_subtitleStreamUpdate.SetExpired();
+    m_speedUpdate.SetExpired();
   }
   return iResult;
 }
@@ -187,10 +193,9 @@ bool CApplicationPlayer::HasRDS() const
   return (player && player->HasRDS());
 }
 
-bool CApplicationPlayer::IsPaused() const
+bool CApplicationPlayer::IsPaused()
 {
-  std::shared_ptr<IPlayer> player = GetInternal();
-  return (player && player->IsPaused());
+  return (GetPlaySpeed() == 0);
 }
 
 bool CApplicationPlayer::IsPlaying() const
@@ -199,9 +204,9 @@ bool CApplicationPlayer::IsPlaying() const
   return (player && player->IsPlaying());
 }
 
-bool CApplicationPlayer::IsPausedPlayback() const
+bool CApplicationPlayer::IsPausedPlayback()
 {
-  return (IsPlaying() && IsPaused());
+  return (IsPlaying() && (GetPlaySpeed() == 0));
 }
 
 bool CApplicationPlayer::IsPlayingAudio() const
@@ -223,13 +228,10 @@ void CApplicationPlayer::Pause()
 {
   std::shared_ptr<IPlayer> player = GetInternal();
   if (player)
+  {
     player->Pause();
-}
-
-bool CApplicationPlayer::ControlsVolume() const
-{
-  std::shared_ptr<IPlayer> player = GetInternal();
-  return (player && player->ControlsVolume());
+    m_speedUpdate.SetExpired();
+  }
 }
 
 void CApplicationPlayer::SetMute(bool bOnOff)
@@ -454,11 +456,11 @@ float CApplicationPlayer::GetCachePercentage() const
     return 0.0;
 }
 
-void CApplicationPlayer::ToFFRW(int iSpeed)
+void CApplicationPlayer::SetSpeed(int iSpeed)
 {
   std::shared_ptr<IPlayer> player = GetInternal();
   if (player)
-    player->ToFFRW(iSpeed);
+    player->SetSpeed(iSpeed);
 }
 
 void CApplicationPlayer::DoAudioWork()
@@ -708,13 +710,6 @@ void CApplicationPlayer::GetDeinterlaceMethods(std::vector<int> &deinterlaceMeth
     player->OMXGetDeinterlaceMethods(deinterlaceMethods);
 }
 
-void CApplicationPlayer::GetDeinterlaceModes(std::vector<int> &deinterlaceModes)
-{
-  std::shared_ptr<IPlayer> player = GetInternal();
-  if (player)
-    player->OMXGetDeinterlaceModes(deinterlaceModes);
-}
-
 void CApplicationPlayer::GetScalingMethods(std::vector<int> &scalingMethods)
 {
   std::shared_ptr<IPlayer> player = GetInternal();
@@ -722,7 +717,7 @@ void CApplicationPlayer::GetScalingMethods(std::vector<int> &scalingMethods)
     player->OMXGetScalingMethods(scalingMethods);
 }
 
-void CApplicationPlayer::SetPlaySpeed(int iSpeed, bool bApplicationMuted)
+void CApplicationPlayer::SetPlaySpeed(int iSpeed)
 {
   std::shared_ptr<IPlayer> player = GetInternal();
   if (!player)
@@ -730,43 +725,25 @@ void CApplicationPlayer::SetPlaySpeed(int iSpeed, bool bApplicationMuted)
 
   if (!IsPlayingAudio() && !IsPlayingVideo())
     return ;
-  if (m_iPlaySpeed == iSpeed)
-    return ;
-  if (!CanSeek())
-    return;
-  if (IsPaused())
-  {
-    if (
-      ((m_iPlaySpeed > 1) && (iSpeed > m_iPlaySpeed)) ||
-      ((m_iPlaySpeed < -1) && (iSpeed < m_iPlaySpeed))
-    )
-    {
-      iSpeed = m_iPlaySpeed; // from pause to ff/rw, do previous ff/rw speed
-    }
-    Pause();
-  }
-  m_iPlaySpeed = iSpeed;
 
-  ToFFRW(m_iPlaySpeed);
-
-  // if player has volume control, set it.
-  if (ControlsVolume())
-  {
-    if (m_iPlaySpeed == 1)
-    { // restore volume
-      player->SetVolume(g_application.GetVolume(false));
-    }
-    else
-    { // mute volume
-      player->SetVolume(VOLUME_MINIMUM);
-    }
-    player->SetMute(bApplicationMuted);
-  }
+  SetSpeed(iSpeed);
+  m_speedUpdate.SetExpired();
 }
 
-int CApplicationPlayer::GetPlaySpeed() const
+int CApplicationPlayer::GetPlaySpeed()
 {
-  return m_iPlaySpeed;
+  if (!m_speedUpdate.IsTimePast())
+    return m_iPlaySpeed;
+
+  std::shared_ptr<IPlayer> player = GetInternal();
+  if (player)
+  {
+    m_iPlaySpeed = player->GetSpeed();
+    m_speedUpdate.Set(1000);
+    return m_iPlaySpeed;
+  }
+  else
+    return 0;
 }
 
 void CApplicationPlayer::FrameMove()
@@ -849,15 +826,6 @@ bool CApplicationPlayer::IsRenderingVideoLayer()
     return false;
 }
 
-bool CApplicationPlayer::Supports(EDEINTERLACEMODE mode)
-{
-  std::shared_ptr<IPlayer> player = GetInternal();
-  if (player)
-    return player->Supports(mode);
-  else
-    return false;
-}
-
 bool CApplicationPlayer::Supports(EINTERLACEMETHOD method)
 {
   std::shared_ptr<IPlayer> player = GetInternal();
diff --git a/xbmc/ApplicationPlayer.h b/xbmc/ApplicationPlayer.h
index 1cde0da..870d286 100644
--- a/xbmc/ApplicationPlayer.h
+++ b/xbmc/ApplicationPlayer.h
@@ -65,22 +65,22 @@ class CApplicationPlayer
   int m_iVideoStream;
   XbmcThreads::EndTime m_subtitleStreamUpdate;
   int m_iSubtitleStream;
-  
+  XbmcThreads::EndTime m_speedUpdate;
+  int m_iPlaySpeed;
+
 public:
   CApplicationPlayer();
 
-  int m_iPlaySpeed;
-
   // player management
   void CloseFile(bool reopen = false);
   void ClosePlayer();
   void ClosePlayerGapless(std::string &playername);
   void CreatePlayer(const std::string &player, IPlayerCallback& callback);
   std::string GetCurrentPlayer();
-  int  GetPlaySpeed() const;
+  int  GetPlaySpeed();
   bool HasPlayer() const;
   PlayBackRet OpenFile(const CFileItem& item, const CPlayerOptions& options);
-  void SetPlaySpeed(int iSpeed, bool bApplicationMuted);
+  void SetPlaySpeed(int iSpeed);
 
   void FrameMove();
   bool HasFrame();
@@ -92,7 +92,6 @@ public:
   bool IsRenderingVideo();
   bool IsRenderingGuiLayer();
   bool IsRenderingVideoLayer();
-  bool Supports(EDEINTERLACEMODE mode);
   bool Supports(EINTERLACEMETHOD method);
   bool Supports(ESCALINGMETHOD method);
   bool Supports(ERENDERFEATURE feature);
@@ -107,7 +106,6 @@ public:
   bool  CanPause();
   bool  CanRecord();
   bool  CanSeek();
-  bool  ControlsVolume() const;
   void  DoAudioWork();
   void  GetAudioCapabilities(std::vector<int> &audioCaps);
   int   GetAudioStream();
@@ -120,7 +118,6 @@ public:
   void  GetChapterName(std::string& strChapterName, int chapterIdx=-1);
   int64_t GetChapterPos(int chapterIdx=-1);
   void  GetDeinterlaceMethods(std::vector<int> &deinterlaceMethods);
-  void  GetDeinterlaceModes(std::vector<int> &deinterlaceModes);
   float GetPercentage() const;
   std::string GetPlayerState();
   std::string GetPlayingTitle();
@@ -146,8 +143,8 @@ public:
   bool  HasRDS() const;
   bool  IsCaching() const;
   bool  IsInMenu() const;
-  bool  IsPaused() const;
-  bool  IsPausedPlayback() const;
+  bool  IsPaused();
+  bool  IsPausedPlayback();
   bool  IsPassthrough() const;
   bool  IsPlaying() const;
   bool  IsPlayingAudio() const;
@@ -179,7 +176,7 @@ public:
   void  SetVideoStream(int iStream);
   void  SetVolume(float volume);
   bool  SwitchChannel(const PVR::CPVRChannelPtr &channel);
-  void  ToFFRW(int iSpeed = 0);
+  void  SetSpeed(int iSpeed);
   
   protected:
     std::shared_ptr<IPlayer> GetInternal() const;
diff --git a/xbmc/AutoSwitch.cpp b/xbmc/AutoSwitch.cpp
index cd12746..e2bb56c 100644
--- a/xbmc/AutoSwitch.cpp
+++ b/xbmc/AutoSwitch.cpp
@@ -238,5 +238,5 @@ float CAutoSwitch::MetadataPercentage(const CFileItemList &vecItems)
     if(item->IsParentFolder())
       total--;
   }
-  return (float)count / total;
+  return (total != 0) ? ((float)count / total) : 0.0f;
 }
diff --git a/xbmc/CMakeLists.txt b/xbmc/CMakeLists.txt
index d8c9514..e2917fc 100644
--- a/xbmc/CMakeLists.txt
+++ b/xbmc/CMakeLists.txt
@@ -83,8 +83,3 @@ set(HEADERS AppParamParser.h
             system_gl.h)
 
 core_add_library(xbmc)
-add_dependencies(xbmc libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(xbmc ffmpeg)
-endif()
diff --git a/xbmc/DbUrl.cpp b/xbmc/DbUrl.cpp
index 81baf51..f48a280 100644
--- a/xbmc/DbUrl.cpp
+++ b/xbmc/DbUrl.cpp
@@ -18,11 +18,8 @@
  *
  */
 
-#include <sstream>
-
 #include "DbUrl.h"
 #include "utils/URIUtils.h"
-#include "utils/Variant.h"
 
 CDbUrl::CDbUrl()
 {
diff --git a/xbmc/DbUrl.h b/xbmc/DbUrl.h
index 0e85d25..266da34 100644
--- a/xbmc/DbUrl.h
+++ b/xbmc/DbUrl.h
@@ -19,15 +19,14 @@
  *
  */
 
-#include <map>
-#include <string>
-
-#include "URL.h"
 #include "utils/UrlOptions.h"
+#include "URL.h"
+
+#include <string>
 
 class CVariant;
 
-class CDbUrl : public CUrlOptions
+class CDbUrl : CUrlOptions
 {
 public:
   CDbUrl();
@@ -42,14 +41,18 @@ public:
   const std::string& GetType() const { return m_type; }
   void AppendPath(const std::string &subPath);
 
-  virtual void AddOption(const std::string &key, const char *value);
-  virtual void AddOption(const std::string &key, const std::string &value);
-  virtual void AddOption(const std::string &key, int value);
-  virtual void AddOption(const std::string &key, float value);
-  virtual void AddOption(const std::string &key, double value);
-  virtual void AddOption(const std::string &key, bool value);
-  virtual void AddOptions(const std::string &options);
-  virtual void RemoveOption(const std::string &key);
+  using CUrlOptions::HasOption;
+  using CUrlOptions::GetOptions;
+  using CUrlOptions::GetOptionsString;
+
+  void AddOption(const std::string &key, const char *value) override;
+  void AddOption(const std::string &key, const std::string &value) override;
+  void AddOption(const std::string &key, int value) override;
+  void AddOption(const std::string &key, float value) override;
+  void AddOption(const std::string &key, double value) override;
+  void AddOption(const std::string &key, bool value) override;
+  void AddOptions(const std::string &options) override;
+  void RemoveOption(const std::string &key) override;
 
 protected:
   virtual bool parse() = 0;
diff --git a/xbmc/DllPaths_win32.h b/xbmc/DllPaths_win32.h
index 3748589..2cd8880 100644
--- a/xbmc/DllPaths_win32.h
+++ b/xbmc/DllPaths_win32.h
@@ -22,20 +22,20 @@
  */
 
 /* libraries */
-#define DLL_PATH_CPLUFF        "special://xbmcbin/system/cpluff.dll"
-#define DLL_PATH_LIBEXIF       "special://xbmcbin/system/libexif.dll"
-#define DLL_PATH_LIBCURL       "special://xbmcbin/system/libcurl.dll"
-#define DLL_PATH_LIBNFS        "special://xbmcbin/system/libnfs.dll"
-#define DLL_PATH_LIBPLIST      "special://xbmcbin/system/airplay/libplist.dll"
-#define DLL_PATH_LIBSHAIRPLAY  "special://xbmcbin/system/airplay/libshairplay-1.dll"
-#define DLL_PATH_LIBCEC        "special://xbmcbin/system/libcec.dll"
+#define DLL_PATH_CPLUFF        "special://xbmcbin/cpluff.dll"
+#define DLL_PATH_LIBEXIF       "special://xbmcbin/libexif.dll"
+#define DLL_PATH_LIBCURL       "special://xbmcbin/libcurl.dll"
+#define DLL_PATH_LIBNFS        "special://xbmcbin/libnfs.dll"
+#define DLL_PATH_LIBPLIST      "special://xbmcbin/libplist.dll"
+#define DLL_PATH_LIBSHAIRPLAY  "special://xbmcbin/shairplay.dll"
+#define DLL_PATH_LIBCEC        "special://xbmcbin/cec.dll"
 
 /* VideoPlayer */
-#define DLL_PATH_LIBASS        "special://xbmcbin/system/players/dvdplayer/libass.dll"
-#define DLL_PATH_LIBDVDNAV     "special://xbmcbin/system/players/VideoPlayer/libdvdnav.dll"
+#define DLL_PATH_LIBASS        "special://xbmcbin/libass.dll"
+#define DLL_PATH_LIBDVDNAV     "special://xbmcbin/libdvdnav.dll"
 
 /* libbluray */
-#define DLL_PATH_LIBBLURAY     "special://xbmcbin/system/players/dvdplayer/libbluray.dll"
+#define DLL_PATH_LIBBLURAY     "special://xbmcbin/libbluray.dll"
 
 #endif
 
diff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cpp
index 3cd0932..eda5cc1 100644
--- a/xbmc/FileItem.cpp
+++ b/xbmc/FileItem.cpp
@@ -202,7 +202,7 @@ CFileItem::CFileItem(const CPVRTimerInfoTagPtr& timer)
 
   Initialize();
 
-  m_bIsFolder = timer->IsRepeating();
+  m_bIsFolder = timer->IsTimerRule();
   m_pvrTimerInfoTag = timer;
   m_strPath = timer->Path();
   SetLabel(timer->Title());
@@ -876,7 +876,6 @@ bool CFileItem::IsFileFolder(EFileFolderType types) const
   if(IsInternetStream())
     always_type = EFILEFOLDER_TYPE_ONCLICK;
 
-
   if(types & always_type)
   {
     if(IsSmartPlayList()
@@ -903,7 +902,6 @@ bool CFileItem::IsFileFolder(EFileFolderType types) const
   return false;
 }
 
-
 bool CFileItem::IsSmartPlayList() const
 {
   if (HasProperty("library.smartplaylist") && GetProperty("library.smartplaylist").asBoolean())
@@ -1379,7 +1377,7 @@ bool CFileItem::IsSamePath(const CFileItem *item) const
   {
     if (m_videoInfoTag->m_iDbId != -1 && item->m_videoInfoTag->m_iDbId != -1)
       return ((m_videoInfoTag->m_iDbId == item->m_videoInfoTag->m_iDbId) &&
-        (m_videoInfoTag->m_type == item->m_videoInfoTag->m_type));        
+        (m_videoInfoTag->m_type == item->m_videoInfoTag->m_type));
   }
   if (IsMusicDb() && HasMusicInfoTag())
   {
@@ -1472,7 +1470,7 @@ void CFileItem::SetFromVideoInfoTag(const CVideoInfoTag &video)
     m_strPath = video.m_strFileNameAndPath;
     m_bIsFolder = false;
   }
-  
+
   *GetVideoInfoTag() = video;
   if (video.m_iSeason == 0)
     SetProperty("isspecial", "true");
@@ -1643,13 +1641,13 @@ bool CFileItem::LoadTracksFromCueDocument(CFileItemList& scannedItems)
       {
         if (song.strAlbum.empty() && !tag.GetAlbum().empty())
           song.strAlbum = tag.GetAlbum();
-        //Pass album artist to final MusicInfoTag object via setting song album artist vector. 
+        //Pass album artist to final MusicInfoTag object via setting song album artist vector.
         if (song.GetAlbumArtist().empty() && !tag.GetAlbumArtist().empty())
-          song.SetAlbumArtist(tag.GetAlbumArtist());        
+          song.SetAlbumArtist(tag.GetAlbumArtist());
         if (song.genre.empty() && !tag.GetGenre().empty())
           song.genre = tag.GetGenre();
         //Pass artist to final MusicInfoTag object via setting song artist description string only.
-        //Artist credits not used during loading from cue sheet. 
+        //Artist credits not used during loading from cue sheet.
         if (song.strArtistDesc.empty() && !tag.GetArtistString().empty())
           song.strArtistDesc = tag.GetArtistString();
         if (tag.GetDiscNumber())
@@ -1684,7 +1682,6 @@ bool CFileItem::LoadTracksFromCueDocument(CFileItemList& scannedItems)
   return tracksFound != 0;
 }
 
-
 /////////////////////////////////////////////////////////////////////////////////
 /////
 ///// CFileItemList
@@ -1811,15 +1808,21 @@ void CFileItemList::ClearItems()
   m_map.clear();
 }
 
-void CFileItemList::Add(const CFileItemPtr &pItem)
+void CFileItemList::Add(CFileItemPtr pItem)
 {
   CSingleLock lock(m_lock);
-
-  m_items.push_back(pItem);
   if (m_fastLookup)
-  {
     m_map.insert(MAPFILEITEMSPAIR(m_ignoreURLOptions ? CURL(pItem->GetPath()).GetWithoutOptions() : pItem->GetPath(), pItem));
-  }
+  m_items.emplace_back(std::move(pItem));
+}
+
+void CFileItemList::Add(CFileItem&& item)
+{
+  CSingleLock lock(m_lock);
+  auto ptr = std::make_shared<CFileItem>(std::move(item));
+  if (m_fastLookup)
+    m_map.insert(MAPFILEITEMSPAIR(m_ignoreURLOptions ? CURL(ptr->GetPath()).GetWithoutOptions() : ptr->GetPath(), ptr));
+  m_items.emplace_back(std::move(ptr));
 }
 
 void CFileItemList::AddFront(const CFileItemPtr &pItem, int itemPosition)
@@ -2433,7 +2436,7 @@ void CFileItemList::StackFolders()
       // 1. rars and zips may be on slow sources? is this supposed to be allowed?
       if( !item->IsRemote()
         || item->IsSmb()
-        || item->IsNfs() 
+        || item->IsNfs()
         || URIUtils::IsInRAR(item->GetPath())
         || URIUtils::IsInZIP(item->GetPath())
         || URIUtils::IsOnLAN(item->GetPath())
@@ -2676,15 +2679,23 @@ void CFileItemList::StackFiles()
 bool CFileItemList::Load(int windowID)
 {
   CFile file;
-  if (file.Open(GetDiscFileCache(windowID)))
+  auto path = GetDiscFileCache(windowID);
+  try
   {
-    CArchive ar(&file, CArchive::load);
-    ar >> *this;
-    CLog::Log(LOGDEBUG,"Loading items: %i, directory: %s sort method: %i, ascending: %s", Size(), CURL::GetRedacted(GetPath()).c_str(), m_sortDescription.sortBy,
-      m_sortDescription.sortOrder == SortOrderAscending ? "true" : "false");
-    ar.Close();
-    file.Close();
-    return true;
+    if (file.Open(path))
+    {
+      CArchive ar(&file, CArchive::load);
+      ar >> *this;
+      CLog::Log(LOGDEBUG,"Loading items: %i, directory: %s sort method: %i, ascending: %s", Size(), CURL::GetRedacted(GetPath()).c_str(), m_sortDescription.sortBy,
+        m_sortDescription.sortOrder == SortOrderAscending ? "true" : "false");
+      ar.Close();
+      file.Close();
+      return true;
+    }
+  }
+  catch(std::out_of_range ex)
+  {
+    CLog::Log(LOGERROR, "Corrupt archive: %s", CURL::GetRedacted(path).c_str());
   }
 
   return false;
@@ -2727,23 +2738,25 @@ std::string CFileItemList::GetDiscFileCache(int windowID) const
   std::string strPath(GetPath());
   URIUtils::RemoveSlashAtEnd(strPath);
 
-  Crc32 crc;
-  crc.ComputeFromLowerCase(strPath);
+  uint32_t crc = Crc32::ComputeFromLowerCase(strPath);
 
   std::string cacheFile;
   if (IsCDDA() || IsOnDVD())
-    cacheFile = StringUtils::Format("special://temp/r-%08x.fi", (unsigned __int32)crc);
-  else if (IsMusicDb())
-    cacheFile = StringUtils::Format("special://temp/mdb-%08x.fi", (unsigned __int32)crc);
-  else if (IsVideoDb())
-    cacheFile = StringUtils::Format("special://temp/vdb-%08x.fi", (unsigned __int32)crc);
-  else if (IsSmartPlayList())
-    cacheFile = StringUtils::Format("special://temp/sp-%08x.fi", (unsigned __int32)crc);
-  else if (windowID)
-    cacheFile = StringUtils::Format("special://temp/%i-%08x.fi", windowID, (unsigned __int32)crc);
-  else
-    cacheFile = StringUtils::Format("special://temp/%08x.fi", (unsigned __int32)crc);
-  return cacheFile;
+    return StringUtils::Format("special://temp/archive_cache/r-%08x.fi", crc);
+
+  if (IsMusicDb())
+    return StringUtils::Format("special://temp/archive_cache/mdb-%08x.fi", crc);
+
+  if (IsVideoDb())
+    return StringUtils::Format("special://temp/archive_cache/vdb-%08x.fi", crc);
+
+  if (IsSmartPlayList())
+    return StringUtils::Format("special://temp/archive_cache/sp-%08x.fi", crc);
+
+  if (windowID)
+    return StringUtils::Format("special://temp/archive_cache/%i-%08x.fi", windowID, crc);
+
+  return StringUtils::Format("special://temp/archive_cache/%08x.fi", crc);
 }
 
 bool CFileItemList::AlwaysCache() const
diff --git a/xbmc/FileItem.h b/xbmc/FileItem.h
index 252f6c3..1630072 100644
--- a/xbmc/FileItem.h
+++ b/xbmc/FileItem.h
@@ -605,7 +605,8 @@ public:
   const CFileItemPtr operator[] (const std::string& strPath) const;
   void Clear();
   void ClearItems();
-  void Add(const CFileItemPtr &pItem);
+  void Add(CFileItemPtr item);
+  void Add(CFileItem&& item);
   void AddFront(const CFileItemPtr &pItem, int itemPosition);
   void Remove(CFileItem* pItem);
   void Remove(int iItem);
diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp
index 0d37f1f..9435f00 100644
--- a/xbmc/GUIInfoManager.cpp
+++ b/xbmc/GUIInfoManager.cpp
@@ -768,6 +768,12 @@ const infomap weather[] =        {{ "isfetched",        WEATHER_IS_FETCHED },
 ///     Returns true if ADSP is supported from Kodi
 ///     \note normally always true
 ///   }
+///   \table_row3{   <b>`System.HasCMS`</b>,
+///                  \anchor System_HasCMS
+///                  _boolean_,
+///     Returns true if colour management is supported from Kodi
+///     \note currently only supported for OpenGL
+///   }
 ///   \table_row3{   <b>`System.HasModalDialog`</b>,
 ///                  \anchor System_HasModalDialog
 ///                  _boolean_,
@@ -1182,7 +1188,8 @@ const infomap system_labels[] =  {{ "hasnetwork",       SYSTEM_ETHERNET_LINK_ACT
                                   { "haspvr",           SYSTEM_HAS_PVR },
                                   { "startupwindow",    SYSTEM_STARTUP_WINDOW },
                                   { "stereoscopicmode", SYSTEM_STEREOSCOPIC_MODE },
-                                  { "hasadsp",          SYSTEM_HAS_ADSP }};
+                                  { "hasadsp",          SYSTEM_HAS_ADSP },
+                                  { "hascms",           SYSTEM_HAS_CMS }};
 
 /// \page modules__General__List_of_gui_access
 /// @{
@@ -2108,6 +2115,22 @@ const infomap videoplayer[] =    {{ "title",            VIDEOPLAYER_TITLE },
                                   { "episodename",      VIDEOPLAYER_EPISODENAME }
 };
 
+const infomap player_process[] =
+{
+  { "videodecoder", PLAYER_PROCESS_VIDEODECODER },
+  { "deintmethod", PLAYER_PROCESS_DEINTMETHOD },
+  { "pixformat", PLAYER_PROCESS_PIXELFORMAT },
+  { "videowidth", PLAYER_PROCESS_VIDEOWIDTH },
+  { "videoheight", PLAYER_PROCESS_VIDEOHEIGHT },
+  { "videofps", PLAYER_PROCESS_VIDEOFPS },
+  { "videodar", PLAYER_PROCESS_VIDEODAR },
+  { "videohwdecoder", PLAYER_PROCESS_VIDEOHWDECODER },
+  { "audiodecoder", PLAYER_PROCESS_AUDIODECODER },
+  { "audiochannels", PLAYER_PROCESS_AUDIOCHANNELS },
+  { "audiosamplerate", PLAYER_PROCESS_AUDIOSAMPLERATE },
+  { "audiobitspersample", PLAYER_PROCESS_AUDIOBITSPERSAMPLE }
+};
+
 /// \page modules__General__List_of_gui_access
 /// \section modules__General__List_of_gui_access_Container Container
 /// @{
@@ -3530,7 +3553,7 @@ const infomap container_str[]  = {{ "property",         CONTAINER_PROPERTY },
 ///   \table_row3{   <b>`ListItem.HasTimerSchedule`</b>,
 ///                  \anchor ListItem_HasTimerSchedule
 ///                  _boolean_,
-///     Whether the item is part of a repeating timer schedule (PVR). (v16 addition)
+///     Whether the item was scheduled by a timer rule (PVR). (v16 addition)
 ///   }
 ///   \table_row3{   <b>`ListItem.HasRecording`</b>,
 ///                  \anchor ListItem_HasRecording
@@ -5143,6 +5166,14 @@ int CGUIInfoManager::TranslateSingleString(const std::string &strCondition, bool
         if (prop.name == player_times[i].str)
           return AddMultiInfo(GUIInfo(player_times[i].val, TranslateTimeFormat(prop.param())));
       }
+      if (prop.name == "process" && prop.num_params())
+      {
+        for (size_t i = 0; i < sizeof(player_process) / sizeof(infomap); i++)
+        {
+          if (prop.param() == player_process[i].str)
+            return player_process[i].val;
+        }
+      }
       if (prop.num_params() == 1)
       {
         for (size_t i = 0; i < sizeof(player_param) / sizeof(infomap); i++)
@@ -5313,7 +5344,9 @@ int CGUIInfoManager::TranslateSingleString(const std::string &strCondition, bool
           return AddMultiInfo(GUIInfo(player_times[i].val, TranslateTimeFormat(prop.param())));
       }
       if (prop.name == "content" && prop.num_params())
+      {
         return AddMultiInfo(GUIInfo(VIDEOPLAYER_CONTENT, ConditionalStringParameter(prop.param()), 0));
+      }
       for (size_t i = 0; i < sizeof(videoplayer) / sizeof(infomap); i++)
       {
         if (prop.name == videoplayer[i].str)
@@ -5993,6 +6026,39 @@ std::string CGUIInfoManager::GetLabel(int info, int contextWindow, std::string *
       strLabel = info.language;
     }
     break;
+  case PLAYER_PROCESS_VIDEODECODER:
+      strLabel = CServiceBroker::GetDataCacheCore().GetVideoDecoderName();
+      break;
+  case PLAYER_PROCESS_DEINTMETHOD:
+      strLabel = CServiceBroker::GetDataCacheCore().GetVideoDeintMethod();
+      break;
+  case PLAYER_PROCESS_PIXELFORMAT:
+      strLabel = CServiceBroker::GetDataCacheCore().GetVideoPixelFormat();
+      break;
+  case PLAYER_PROCESS_VIDEOFPS:
+      strLabel = StringUtils::Format("%.3f", CServiceBroker::GetDataCacheCore().GetVideoFps());
+      break;
+  case PLAYER_PROCESS_VIDEODAR:
+      strLabel = StringUtils::Format("%.2f", CServiceBroker::GetDataCacheCore().GetVideoDAR());
+      break;
+  case PLAYER_PROCESS_VIDEOWIDTH:
+      strLabel = StringUtils::FormatNumber(CServiceBroker::GetDataCacheCore().GetVideoWidth());
+      break;
+  case PLAYER_PROCESS_VIDEOHEIGHT:
+      strLabel = StringUtils::FormatNumber(CServiceBroker::GetDataCacheCore().GetVideoHeight());
+      break;
+  case PLAYER_PROCESS_AUDIODECODER:
+      strLabel = CServiceBroker::GetDataCacheCore().GetAudioDecoderName();
+      break;
+  case PLAYER_PROCESS_AUDIOCHANNELS:
+      strLabel = CServiceBroker::GetDataCacheCore().GetAudioChannels();
+      break;
+  case PLAYER_PROCESS_AUDIOSAMPLERATE:
+      strLabel = StringUtils::FormatNumber(CServiceBroker::GetDataCacheCore().GetAudioSampleRate());
+      break;
+  case PLAYER_PROCESS_AUDIOBITSPERSAMPLE:
+      strLabel = StringUtils::FormatNumber(CServiceBroker::GetDataCacheCore().GetAudioBitsPerSampe());
+      break;
   case RDS_AUDIO_LANG:
   case RDS_CHANNEL_COUNTRY:
   case RDS_TITLE:
@@ -6729,6 +6795,12 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI
     bReturn = true;
   else if (condition == SYSTEM_HAS_ADSP)
     bReturn = true;
+  else if (condition == SYSTEM_HAS_CMS)
+#ifdef HAS_GL
+    bReturn = true;
+#else
+    bReturn = false;
+#endif
   else if (condition == SYSTEM_ISMASTER)
     bReturn = CProfilesManager::GetInstance().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE && g_passwordManager.bMasterUser;
   else if (condition == SYSTEM_ISFULLSCREEN)
@@ -6891,46 +6963,46 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI
       bReturn = g_application.m_pPlayer->IsPlayingVideo();
       break;
     case PLAYER_PLAYING:
-      bReturn = !g_application.m_pPlayer->IsPausedPlayback() && (g_application.m_pPlayer->GetPlaySpeed() == 1);
+      bReturn = g_application.m_pPlayer->GetPlaySpeed() == 1;
       break;
     case PLAYER_PAUSED:
       bReturn = g_application.m_pPlayer->IsPausedPlayback();
       break;
     case PLAYER_REWINDING:
-      bReturn = !g_application.m_pPlayer->IsPausedPlayback() && g_application.m_pPlayer->GetPlaySpeed() < 1;
+      bReturn = g_application.m_pPlayer->GetPlaySpeed() < 0;
       break;
     case PLAYER_FORWARDING:
-      bReturn = !g_application.m_pPlayer->IsPausedPlayback() && g_application.m_pPlayer->GetPlaySpeed() > 1;
+      bReturn = g_application.m_pPlayer->GetPlaySpeed() > 1;
       break;
     case PLAYER_REWINDING_2x:
-      bReturn = !g_application.m_pPlayer->IsPausedPlayback() && g_application.m_pPlayer->GetPlaySpeed() == -2;
+      bReturn = g_application.m_pPlayer->GetPlaySpeed() == -2;
       break;
     case PLAYER_REWINDING_4x:
-      bReturn = !g_application.m_pPlayer->IsPausedPlayback() && g_application.m_pPlayer->GetPlaySpeed() == -4;
+      bReturn = g_application.m_pPlayer->GetPlaySpeed() == -4;
       break;
     case PLAYER_REWINDING_8x:
-      bReturn = !g_application.m_pPlayer->IsPausedPlayback() && g_application.m_pPlayer->GetPlaySpeed() == -8;
+      bReturn = g_application.m_pPlayer->GetPlaySpeed() == -8;
       break;
     case PLAYER_REWINDING_16x:
-      bReturn = !g_application.m_pPlayer->IsPausedPlayback() && g_application.m_pPlayer->GetPlaySpeed() == -16;
+      bReturn = g_application.m_pPlayer->GetPlaySpeed() == -16;
       break;
     case PLAYER_REWINDING_32x:
-      bReturn = !g_application.m_pPlayer->IsPausedPlayback() && g_application.m_pPlayer->GetPlaySpeed() == -32;
+      bReturn = g_application.m_pPlayer->GetPlaySpeed() == -32;
       break;
     case PLAYER_FORWARDING_2x:
-      bReturn = !g_application.m_pPlayer->IsPausedPlayback() && g_application.m_pPlayer->GetPlaySpeed() == 2;
+      bReturn = g_application.m_pPlayer->GetPlaySpeed() == 2;
       break;
     case PLAYER_FORWARDING_4x:
-      bReturn = !g_application.m_pPlayer->IsPausedPlayback() && g_application.m_pPlayer->GetPlaySpeed() == 4;
+      bReturn = g_application.m_pPlayer->GetPlaySpeed() == 4;
       break;
     case PLAYER_FORWARDING_8x:
-      bReturn = !g_application.m_pPlayer->IsPausedPlayback() && g_application.m_pPlayer->GetPlaySpeed() == 8;
+      bReturn = g_application.m_pPlayer->GetPlaySpeed() == 8;
       break;
     case PLAYER_FORWARDING_16x:
-      bReturn = !g_application.m_pPlayer->IsPausedPlayback() && g_application.m_pPlayer->GetPlaySpeed() == 16;
+      bReturn = g_application.m_pPlayer->GetPlaySpeed() == 16;
       break;
     case PLAYER_FORWARDING_32x:
-      bReturn = !g_application.m_pPlayer->IsPausedPlayback() && g_application.m_pPlayer->GetPlaySpeed() == 32;
+      bReturn = g_application.m_pPlayer->GetPlaySpeed() == 32;
       break;
     case PLAYER_CAN_RECORD:
       bReturn = g_application.m_pPlayer->CanRecord();
@@ -7090,6 +7162,9 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI
                    !m_currentFile->GetPVRRadioRDSInfoTag()->GetSMSStudio().empty() ||
                    !m_currentFile->GetPVRRadioRDSInfoTag()->GetPhoneStudio().empty());
     break;
+    case PLAYER_PROCESS_VIDEOHWDECODER:
+        bReturn = CServiceBroker::GetDataCacheCore().IsVideoHwDecoder();
+        break;
     default: // default, use integer value different from 0 as true
       {
         int val;
@@ -8619,7 +8694,7 @@ std::string CGUIInfoManager::GetVideoLabel(int item)
       return StringUtils::Join(m_currentFile->GetVideoInfoTag()->m_director, g_advancedSettings.m_videoItemSeparator);
       break;
     case VIDEOPLAYER_IMDBNUMBER:
-      return m_currentFile->GetVideoInfoTag()->m_strIMDBNumber;
+      return m_currentFile->GetVideoInfoTag()->GetUniqueID();
     case VIDEOPLAYER_RATING:
       {
         std::string strRating;
@@ -9090,7 +9165,7 @@ void CGUIInfoManager::UpdateAVInfo()
 {
   if(g_application.m_pPlayer->IsPlaying())
   {
-    if (g_dataCacheCore.HasAVInfoChanges())
+    if (CServiceBroker::GetDataCacheCore().HasAVInfoChanges())
     {
       SPlayerVideoStreamInfo video;
       SPlayerAudioStreamInfo audio;
@@ -10154,7 +10229,7 @@ std::string CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, std::
       if (item->HasEPGInfoTag())
         return item->GetEPGInfoTag()->IMDBNumber();
       if (item->HasVideoInfoTag())
-        return item->GetVideoInfoTag()->m_strIMDBNumber;
+        return item->GetVideoInfoTag()->GetUniqueID();
       break;
     }
   case LISTITEM_EPISODENAME:
diff --git a/xbmc/ServiceBroker.cpp b/xbmc/ServiceBroker.cpp
index fff03c3..dd5c640 100644
--- a/xbmc/ServiceBroker.cpp
+++ b/xbmc/ServiceBroker.cpp
@@ -50,3 +50,8 @@ ActiveAE::CActiveAEDSP &CServiceBroker::GetADSP()
 {
   return g_application.m_ServiceManager->GetADSPManager();
 }
+
+CDataCacheCore &CServiceBroker::GetDataCacheCore()
+{
+  return g_application.m_ServiceManager->GetDataCacheCore();
+}
diff --git a/xbmc/ServiceBroker.h b/xbmc/ServiceBroker.h
index 32add30..9f9de19 100644
--- a/xbmc/ServiceBroker.h
+++ b/xbmc/ServiceBroker.h
@@ -40,6 +40,7 @@ namespace PVR
 }
 
 class XBPython;
+class CDataCacheCore;
 
 class CServiceBroker
 {
@@ -50,4 +51,5 @@ public:
   static XBPython &GetXBPython();
   static PVR::CPVRManager &GetPVRManager();
   static ActiveAE::CActiveAEDSP& GetADSP();
+  static CDataCacheCore& GetDataCacheCore();
 };
diff --git a/xbmc/ServiceManager.cpp b/xbmc/ServiceManager.cpp
index 3cc188c..d8b83a6 100644
--- a/xbmc/ServiceManager.cpp
+++ b/xbmc/ServiceManager.cpp
@@ -21,6 +21,7 @@
 #include "ServiceManager.h"
 #include "addons/BinaryAddonCache.h"
 #include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h"
+#include "cores/DataCacheCore.h"
 #include "utils/log.h"
 #include "interfaces/AnnouncementManager.h"
 #include "interfaces/generic/ScriptInvocationManager.h"
@@ -49,6 +50,7 @@ bool CServiceManager::Init2()
 
   m_ADSPManager.reset(new ActiveAE::CActiveAEDSP());
   m_PVRManager.reset(new PVR::CPVRManager());
+  m_dataCacheCore.reset(new CDataCacheCore());
 
   m_binaryAddonCache.reset( new ADDON::CBinaryAddonCache());
   m_binaryAddonCache->Init();
@@ -104,3 +106,14 @@ ActiveAE::CActiveAEDSP& CServiceManager::GetADSPManager()
 {
   return *m_ADSPManager;
 }
+
+CDataCacheCore& CServiceManager::GetDataCacheCore()
+{
+  return *m_dataCacheCore;
+}
+
+// deleters for unique_ptr
+void CServiceManager::delete_dataCacheCore::operator()(CDataCacheCore *p) const
+{
+  delete p;
+}
diff --git a/xbmc/ServiceManager.h b/xbmc/ServiceManager.h
index 9b7806f..f4bcdd4 100644
--- a/xbmc/ServiceManager.h
+++ b/xbmc/ServiceManager.h
@@ -42,6 +42,7 @@ class CPVRManager;
 }
 
 class XBPython;
+class CDataCacheCore;
 
 class CServiceManager
 {
@@ -56,12 +57,19 @@ public:
   XBPython& GetXBPython();
   PVR::CPVRManager& GetPVRManager();
   ActiveAE::CActiveAEDSP& GetADSPManager();
+  CDataCacheCore& GetDataCacheCore();
 
 protected:
+  struct delete_dataCacheCore
+  {
+    void operator()(CDataCacheCore *p) const;
+  };
+
   std::unique_ptr<ADDON::CAddonMgr> m_addonMgr;
   std::unique_ptr<ADDON::CBinaryAddonCache> m_binaryAddonCache;
   std::unique_ptr<ANNOUNCEMENT::CAnnouncementManager> m_announcementManager;
   std::unique_ptr<XBPython> m_XBPython;
   std::unique_ptr<PVR::CPVRManager> m_PVRManager;
   std::unique_ptr<ActiveAE::CActiveAEDSP> m_ADSPManager;
+  std::unique_ptr<CDataCacheCore, delete_dataCacheCore> m_dataCacheCore;
 };
diff --git a/xbmc/SystemGlobals.cpp b/xbmc/SystemGlobals.cpp
index 9354471..3d1cb55 100644
--- a/xbmc/SystemGlobals.cpp
+++ b/xbmc/SystemGlobals.cpp
@@ -19,7 +19,6 @@
  */
 #include "system.h"
 #include "SectionLoader.h"
-#include "cores/DataCacheCore.h"
 #include "GUILargeTextureManager.h"
 #include "guilib/TextureManager.h"
 #include "utils/AlarmClock.h"
@@ -71,6 +70,3 @@ std::map<std::string, std::string> CSpecialProtocol::m_pathMap;
 #endif
 
   CZipManager g_ZipManager;
-
-  CDataCacheCore g_dataCacheCore;
-
diff --git a/xbmc/TextureCache.cpp b/xbmc/TextureCache.cpp
index bcd16c0..69586ce 100644
--- a/xbmc/TextureCache.cpp
+++ b/xbmc/TextureCache.cpp
@@ -241,9 +241,8 @@ bool CTextureCache::ClearCachedTexture(int id, std::string &cachedURL)
 
 std::string CTextureCache::GetCacheFile(const std::string &url)
 {
-  Crc32 crc;
-  crc.ComputeFromLowerCase(url);
-  std::string hex = StringUtils::Format("%08x", (unsigned int)crc);
+  auto crc = Crc32::ComputeFromLowerCase(url);
+  std::string hex = StringUtils::Format("%08x", crc);
   std::string hash = StringUtils::Format("%c/%s", hex[0], hex.c_str());
   return hash;
 }
diff --git a/xbmc/URL.cpp b/xbmc/URL.cpp
index cc734ad..4ad62ab 100644
--- a/xbmc/URL.cpp
+++ b/xbmc/URL.cpp
@@ -37,16 +37,6 @@
 
 using namespace ADDON;
 
-CURL::CURL(const std::string& strURL1)
-{
-  Parse(strURL1);
-}
-
-CURL::CURL()
-{
-  m_iPort = 0;
-}
-
 CURL::~CURL()
 {
 }
@@ -357,21 +347,6 @@ void CURL::SetFileName(const std::string& strFileName)
   StringUtils::ToLower(m_strFileType);
 }
 
-void CURL::SetHostName(const std::string& strHostName)
-{
-  m_strHostName = strHostName;
-}
-
-void CURL::SetUserName(const std::string& strUserName)
-{
-  m_strUserName = strUserName;
-}
-
-void CURL::SetPassword(const std::string& strPassword)
-{
-  m_strPassword = strPassword;
-}
-
 void CURL::SetProtocol(const std::string& strProtocol)
 {
   m_strProtocol = strProtocol;
@@ -411,57 +386,6 @@ void CURL::SetProtocolOptions(const std::string& strOptions)
   }
 }
 
-void CURL::SetPort(int port)
-{
-  m_iPort = port;
-}
-
-bool CURL::HasPort() const
-{
-  return (m_iPort != 0);
-}
-
-int CURL::GetPort() const
-{
-  return m_iPort;
-}
-
-
-const std::string& CURL::GetHostName() const
-{
-  return m_strHostName;
-}
-
-const std::string&  CURL::GetShareName() const
-{
-  return m_strShareName;
-}
-
-const std::string& CURL::GetDomain() const
-{
-  return m_strDomain;
-}
-
-const std::string& CURL::GetUserName() const
-{
-  return m_strUserName;
-}
-
-const std::string& CURL::GetPassWord() const
-{
-  return m_strPassword;
-}
-
-const std::string& CURL::GetFileName() const
-{
-  return m_strFileName;
-}
-
-const std::string& CURL::GetProtocol() const
-{
-  return m_strProtocol;
-}
-
 const std::string CURL::GetTranslatedProtocol() const
 {
   if (IsProtocol("shout")
@@ -475,21 +399,6 @@ const std::string CURL::GetTranslatedProtocol() const
   return GetProtocol();
 }
 
-const std::string& CURL::GetFileType() const
-{
-  return m_strFileType;
-}
-
-const std::string& CURL::GetOptions() const
-{
-  return m_strOptions;
-}
-
-const std::string& CURL::GetProtocolOptions() const
-{
-  return m_strProtocolOptions;
-}
-
 const std::string CURL::GetFileNameWithoutPath() const
 {
   // *.zip and *.rar store the actual zip/rar path in the hostname of the url
diff --git a/xbmc/URL.h b/xbmc/URL.h
index debe942..c21aa0b 100644
--- a/xbmc/URL.h
+++ b/xbmc/URL.h
@@ -30,8 +30,12 @@
 class CURL
 {
 public:
-  explicit CURL(const std::string& strURL);
-  CURL();
+  explicit CURL(const std::string& strURL)
+  {
+    Parse(strURL);
+  }
+
+  CURL():m_iPort(0) {}
   virtual ~CURL(void);
 
   // explicit equals operator for std::string comparison
@@ -40,28 +44,91 @@ public:
   void Reset();
   void Parse(const std::string& strURL);
   void SetFileName(const std::string& strFileName);
-  void SetHostName(const std::string& strHostName);
-  void SetUserName(const std::string& strUserName);
-  void SetPassword(const std::string& strPassword);
+  void SetHostName(const std::string& strHostName)
+  {
+    m_strHostName = strHostName;
+  }
+
+  void SetUserName(const std::string& strUserName)
+  {
+    m_strUserName = strUserName;
+  }
+
+  void SetPassword(const std::string& strPassword)
+  {
+    m_strPassword = strPassword;
+  }
+
   void SetProtocol(const std::string& strProtocol);
   void SetOptions(const std::string& strOptions);
   void SetProtocolOptions(const std::string& strOptions);
-  void SetPort(int port);
+  void SetPort(int port)
+  {
+    m_iPort = port;
+  }
+
+  bool HasPort() const
+  {
+    return (m_iPort != 0);
+  }
+
+  int GetPort() const
+  {
+    return m_iPort;
+  }
+
+  const std::string& GetHostName() const
+  {
+    return m_strHostName;
+  }
+
+  const std::string& GetDomain() const
+  {
+    return m_strDomain;
+  }
 
-  bool HasPort() const;
+  const std::string& GetUserName() const
+  {
+    return m_strUserName;
+  }
+
+  const std::string& GetPassWord() const
+  {
+    return m_strPassword;
+  }
+
+  const std::string& GetFileName() const
+  {
+    return m_strFileName;
+  }
+
+  const std::string& GetProtocol() const
+  {
+    return m_strProtocol;
+  }
 
-  int GetPort() const;
-  const std::string& GetHostName() const;
-  const std::string& GetDomain() const;
-  const std::string& GetUserName() const;
-  const std::string& GetPassWord() const;
-  const std::string& GetFileName() const;
-  const std::string& GetProtocol() const;
   const std::string GetTranslatedProtocol() const;
-  const std::string& GetFileType() const;
-  const std::string& GetShareName() const;
-  const std::string& GetOptions() const;
-  const std::string& GetProtocolOptions() const;
+
+  const std::string& GetFileType() const
+  {
+    return m_strFileType;
+  }
+
+  const std::string& GetShareName() const
+  {
+      return m_strShareName;
+  }
+
+  const std::string& GetOptions() const
+  {
+    return m_strOptions;
+  }
+
+  const std::string& GetProtocolOptions() const
+  {
+    return m_strProtocolOptions;
+  }
+
   const std::string GetFileNameWithoutPath() const; /* return the filename excluding path */
 
   char GetDirectorySeparator() const;
diff --git a/xbmc/Util.cpp b/xbmc/Util.cpp
index b0de1c8..f1754ef 100644
--- a/xbmc/Util.cpp
+++ b/xbmc/Util.cpp
@@ -1770,6 +1770,11 @@ void CUtil::ScanPathsForAssociatedItems(const std::string& videoName,
       continue;
 
     std::string strCandidate = URIUtils::GetFileName(pItem->GetPath());
+
+    // skip duplicates
+    if (std::find(associatedFiles.begin(), associatedFiles.end(), pItem->GetPath()) != associatedFiles.end())
+      continue;
+
     URIUtils::RemoveExtension(strCandidate);
     if (StringUtils::StartsWithNoCase(strCandidate, videoName))
     {
diff --git a/xbmc/addons/Addon.h b/xbmc/addons/Addon.h
index e64845d..515afe1 100644
--- a/xbmc/addons/Addon.h
+++ b/xbmc/addons/Addon.h
@@ -70,11 +70,11 @@ public:
   std::string libname;
   std::string author;
   std::string source;
-  //! @todo fix parts relying on mutating these
-  mutable std::string path;
-  mutable std::string icon;
+  std::string path;
+  std::string icon;
   std::string changelog;
-  mutable std::string fanart;
+  std::string fanart;
+  std::vector<std::string> screenshots;
   std::string disclaimer;
   ADDONDEPS dependencies;
   std::string broken;
@@ -96,7 +96,6 @@ public:
   TYPE Type() const override { return m_props.type; }
   TYPE FullType() const override { return Type(); }
   bool IsType(TYPE type) const override { return type == m_props.type; }
-  const AddonProps& Props() override { return m_props; }
   std::string ID() const override{ return m_props.id; }
   std::string Name() const override { return m_props.name; }
   bool IsInUse() const override{ return false; };
@@ -111,6 +110,7 @@ public:
   std::string ChangeLog() const override { return m_props.changelog; }
   std::string FanArt() const override { return m_props.fanart; }
   std::string Icon() const override { return m_props.icon; };
+  std::vector<std::string> Screenshots() const override { return m_props.screenshots; };
   std::string Disclaimer() const override { return m_props.disclaimer; }
   std::string Broken() const override { return m_props.broken; }
   CDateTime InstallDate() const override { return m_props.installDate; }
diff --git a/xbmc/addons/AddonBuilder.h b/xbmc/addons/AddonBuilder.h
index 074f7eb..2966364 100644
--- a/xbmc/addons/AddonBuilder.h
+++ b/xbmc/addons/AddonBuilder.h
@@ -40,6 +40,7 @@ public:
   void SetSource(std::string source) { m_props.source = std::move(source); }
   void SetIcon(std::string icon) { m_props.icon = std::move(icon); }
   void SetFanart(std::string fanart) { m_props.fanart = std::move(fanart); }
+  void SetScreenshots(std::vector<std::string> screenshots) { m_props.screenshots = std::move(screenshots); }
   void SetChangelog(std::string changelog) { m_props.changelog = std::move(changelog); }
   void SetBroken(std::string broken) { m_props.broken = std::move(broken); }
   void SetPath(std::string path) { m_props.path = std::move(path); }
diff --git a/xbmc/addons/AddonDatabase.cpp b/xbmc/addons/AddonDatabase.cpp
index 6f49f14..76fdb11 100644
--- a/xbmc/addons/AddonDatabase.cpp
+++ b/xbmc/addons/AddonDatabase.cpp
@@ -50,6 +50,10 @@ static std::string SerializeMetadata(const IAddon& addon)
   variant["fanart"] = addon.FanArt();
   variant["icon"] = addon.Icon();
 
+  variant["screenshots"] = CVariant(CVariant::VariantTypeArray);
+  for (const auto& item : addon.Screenshots())
+    variant["screenshots"].push_back(item);
+
   variant["extensions"] = CVariant(CVariant::VariantTypeArray);
   variant["extensions"].push_back(ADDON::TranslateType(addon.Type(), false));
 
@@ -88,6 +92,11 @@ static void DeserializeMetadata(const std::string& document, CAddonBuilder& buil
   builder.SetFanart(variant["fanart"].asString());
   builder.SetIcon(variant["icon"].asString());
 
+  std::vector<std::string> screenshots;
+  for (auto it = variant["screenshots"].begin_array(); it != variant["screenshots"].end_array(); ++it)
+    screenshots.push_back(it->asString());
+  builder.SetScreenshots(std::move(screenshots));
+
   builder.SetType(TranslateType(variant["extensions"][0].asString()));
 
   ADDONDEPS deps;
@@ -668,7 +677,12 @@ bool CAddonDatabase::GetRepositoryContent(const std::string& id, VECADDONS& addo
 
       auto addon = builder.Build();
       if (addon)
-        result.push_back(std::move(addon));
+      {
+        if (!result.empty() && result.back()->ID() == addonId)
+          result.back() = std::move(addon);
+        else
+          result.push_back(std::move(addon));
+      }
       else
         CLog::Log(LOGWARNING, "CAddonDatabase: failed to build %s", addonId.c_str());
       m_pDS->next();
diff --git a/xbmc/addons/BinaryAddonCache.h b/xbmc/addons/AddonEvents.h
similarity index 57%
copy from xbmc/addons/BinaryAddonCache.h
copy to xbmc/addons/AddonEvents.h
index 1642885..04b8693 100644
--- a/xbmc/addons/BinaryAddonCache.h
+++ b/xbmc/addons/AddonEvents.h
@@ -17,32 +17,37 @@
  *  <http://www.gnu.org/licenses/>.
  *
  */
-
 #pragma once
 
-#include "utils/Observer.h"
-#include "Addon.h"
-#include "threads/CriticalSection.h"
-#include <map>
-#include <vector>
-
-namespace ADDON {
+#include <string>
 
-class CBinaryAddonCache : public Observer
+namespace ADDON
 {
-public:
-  virtual ~CBinaryAddonCache();
-  void Init();
-  void Deinit();
-  void GetAddons(VECADDONS& addons, const TYPE& type);
-  virtual void Notify(const Observable &obs, const ObservableMessage msg) override;
+  struct AddonEvent
+  {
+    virtual ~AddonEvent() {};
+  };
 
-protected:
-  void Update();
-  
-  CCriticalSection m_critSection;
-  std::multimap<TYPE, VECADDONS> m_addons;
-  std::vector<TYPE> m_addonsToCache;
-};
+  namespace AddonEvents
+  {
+    struct Enabled : AddonEvent
+    {
+      std::string id;
+      Enabled(std::string id) : id(std::move(id)) {}
+    };
 
-}
\ No newline at end of file
+    struct Disabled : AddonEvent
+    {
+      std::string id;
+      Disabled(std::string id) : id(std::move(id)) {}
+    };
+
+    struct MetadataChanged : AddonEvent
+    {
+      std::string id;
+      MetadataChanged(std::string id) : id(std::move(id)) {}
+    };
+
+    struct InstalledChanged : AddonEvent {};
+  };
+};
diff --git a/xbmc/addons/AddonInstaller.cpp b/xbmc/addons/AddonInstaller.cpp
index c0e365c..5fb6505 100644
--- a/xbmc/addons/AddonInstaller.cpp
+++ b/xbmc/addons/AddonInstaller.cpp
@@ -220,7 +220,9 @@ void CAddonInstaller::Install(const std::string& addonId, const AddonVersion& ve
   if (!CAddonMgr::GetInstance().GetAddon(repoId, repo, ADDON_REPOSITORY))
     return;
 
-  std::string hash = std::static_pointer_cast<CRepository>(repo)->GetAddonHash(addon);
+  std::string hash;
+  if (!std::static_pointer_cast<CRepository>(repo)->GetAddonHash(addon, hash))
+    return;
   DoInstall(addon, std::static_pointer_cast<CRepository>(repo), hash, true, false);
 }
 
@@ -277,20 +279,9 @@ bool CAddonInstaller::InstallFromZip(const std::string &path)
     return false;
   }
 
-  //! @todo possibly add support for github generated zips here?
-  std::string archive = URIUtils::AddFileToFolder(items[0]->GetPath(), "addon.xml");
-
-  CXBMCTinyXML xml;
   AddonPtr addon;
-  if (xml.LoadFile(archive) && CAddonMgr::GetInstance().LoadAddonDescriptionFromMemory(xml.RootElement(), addon))
-  {
-    // set the correct path
-    addon->Props().path = items[0]->GetPath();
-    addon->Props().icon = URIUtils::AddFileToFolder(items[0]->GetPath(), "icon.png");
-
-    // install the addon
+  if (CAddonMgr::GetInstance().LoadAddonDescription(items[0]->GetPath(), addon))
     return DoInstall(addon, RepositoryPtr());
-  }
 
   CEventLog::GetInstance().AddWithNotification(EventPtr(new CNotificationEvent(24045,
       StringUtils::Format(g_localizeStrings.Get(24143).c_str(), path.c_str()),
@@ -497,8 +488,7 @@ bool CAddonInstallJob::GetAddonWithHash(const std::string& addonID, const std::s
   if (!CAddonMgr::GetInstance().GetAddon(repoID, repo, ADDON_REPOSITORY))
     return false;
 
-  hash = std::static_pointer_cast<CRepository>(repo)->GetAddonHash(addon);
-  return true;
+  return std::static_pointer_cast<CRepository>(repo)->GetAddonHash(addon, hash);
 }
 
 bool CAddonInstallJob::DoWork()
@@ -574,7 +564,8 @@ bool CAddonInstallJob::DoWork()
         {
           CFile::Delete(package);
 
-          CLog::Log(LOGERROR, "CAddonInstallJob[%s]: MD5 mismatch after download %s", m_addon->ID().c_str(), package.c_str());
+          CLog::Log(LOGERROR, "CAddonInstallJob[%s]: MD5 mismatch after download. Expected %s, was %s",
+              m_addon->ID().c_str(), m_hash.c_str(), md5.c_str());
           ReportInstallError(m_addon->ID(), URIUtils::GetFileName(package));
           return false;
         }
@@ -610,10 +601,7 @@ bool CAddonInstallJob::DoWork()
   if (!Install(installFrom, m_repo))
     return false;
 
-  CAddonMgr::GetInstance().UnregisterAddon(m_addon->ID());
-  CAddonMgr::GetInstance().FindAddons();
-
-  if (!CAddonMgr::GetInstance().GetAddon(m_addon->ID(), m_addon, ADDON_UNKNOWN, false))
+  if (!CAddonMgr::GetInstance().ReloadAddon(m_addon))
   {
     CLog::Log(LOGERROR, "CAddonInstallJob[%s]: failed to reload addon", m_addon->ID().c_str());
     return false;
@@ -624,9 +612,6 @@ bool CAddonInstallJob::DoWork()
 
   ADDON::OnPostInstall(m_addon, m_update, IsModal());
 
-  //Enable it if it was previously disabled
-  CAddonMgr::GetInstance().EnableAddon(m_addon->ID());
-
   {
     CAddonDatabase database;
     database.Open();
@@ -635,9 +620,6 @@ bool CAddonInstallJob::DoWork()
       database.SetLastUpdated(m_addon->ID(), CDateTime::GetCurrentDateTime());
   }
 
-  // notify any observers that add-ons have changed
-  CAddonMgr::GetInstance().NotifyObservers(ObservableMessageAddons);
-
   CEventLog::GetInstance().Add(
     EventPtr(new CAddonManagementEvent(m_addon, m_update ? 24065 : 24064)),
     !IsModal() && CSettings::GetInstance().GetBool(CSettings::SETTING_ADDONS_NOTIFICATIONS), false);
@@ -863,7 +845,11 @@ bool CAddonUnInstallJob::DoWork()
 
   //Unregister addon with the manager to ensure nothing tries
   //to interact with it while we are uninstalling.
-  CAddonMgr::GetInstance().UnregisterAddon(m_addon->ID());
+  if (!CAddonMgr::GetInstance().UnloadAddon(m_addon))
+  {
+    CLog::Log(LOGERROR, "CAddonUnInstallJob[%s]: failed to unload addon.", m_addon->ID().c_str());
+    return false;
+  }
 
   if (!DeleteAddon(m_addon->Path()))
   {
diff --git a/xbmc/addons/AddonManager.cpp b/xbmc/addons/AddonManager.cpp
index e5a4c34..ee9ad79 100644
--- a/xbmc/addons/AddonManager.cpp
+++ b/xbmc/addons/AddonManager.cpp
@@ -93,21 +93,23 @@ static cp_extension_t* GetFirstExtPoint(const cp_plugin_info_t* addon, TYPE type
 AddonPtr CAddonMgr::Factory(const cp_plugin_info_t* plugin, TYPE type)
 {
   CAddonBuilder builder;
-  return Factory(plugin, type, builder);
+  if (Factory(plugin, type, builder))
+    return builder.Build();
+  return nullptr;
 }
 
-AddonPtr CAddonMgr::Factory(const cp_plugin_info_t* plugin, TYPE type, CAddonBuilder& builder)
+bool CAddonMgr::Factory(const cp_plugin_info_t* plugin, TYPE type, CAddonBuilder& builder)
 {
   if (!plugin || !plugin->identifier)
-    return nullptr;
+    return false;
 
   if (!PlatformSupportsAddon(plugin))
-    return nullptr;
+    return false;
 
   cp_extension_t* ext = GetFirstExtPoint(plugin, type);
 
   if (ext == nullptr && type != ADDON_UNKNOWN)
-    return nullptr; // no extension point satisfies the type requirement
+    return false; // no extension point satisfies the type requirement
 
   if (ext)
   {
@@ -121,7 +123,7 @@ AddonPtr CAddonMgr::Factory(const cp_plugin_info_t* plugin, TYPE type, CAddonBui
   }
 
   FillCpluffMetadata(plugin, builder);
-  return builder.Build();
+  return true;
 }
 
 void CAddonMgr::FillCpluffMetadata(const cp_plugin_info_t* plugin, CAddonBuilder& builder)
@@ -141,11 +143,7 @@ void CAddonMgr::FillCpluffMetadata(const cp_plugin_info_t* plugin, CAddonBuilder
     builder.SetAuthor(plugin->provider_name);
 
   if (plugin->plugin_path && strcmp(plugin->plugin_path, "") != 0)
-  {
     builder.SetPath(plugin->plugin_path);
-    builder.SetIcon(URIUtils::AddFileToFolder(plugin->plugin_path, "icon.png"));
-    builder.SetFanart(URIUtils::AddFileToFolder(plugin->plugin_path, "fanart.jpg"));
-  }
 
   {
     ADDONDEPS dependencies;
@@ -164,6 +162,18 @@ void CAddonMgr::FillCpluffMetadata(const cp_plugin_info_t* plugin, CAddonBuilder
   auto metadata = CAddonMgr::GetInstance().GetExtension(plugin, "xbmc.addon.metadata");
   if (!metadata)
     metadata = CAddonMgr::GetInstance().GetExtension(plugin, "kodi.addon.metadata");
+
+  if (plugin->plugin_path && strcmp(plugin->plugin_path, "") != 0)
+  {
+    //backwards compatibility
+    std::string icon = metadata && CAddonMgr::GetInstance().GetExtValue(metadata->configuration, "noicon") == "true" ? "" : "icon.png";
+    std::string fanart = metadata && CAddonMgr::GetInstance().GetExtValue(metadata->configuration, "nofanart") == "true" ? "" : "fanart.jpg";
+    if (!icon.empty())
+      builder.SetIcon(URIUtils::AddFileToFolder(plugin->plugin_path, icon));
+    if (!fanart.empty())
+      builder.SetFanart(URIUtils::AddFileToFolder(plugin->plugin_path, fanart));
+  }
+
   if (metadata)
   {
     builder.SetSummary(CAddonMgr::GetInstance().GetTranslatedString(metadata->configuration, "summary"));
@@ -183,10 +193,34 @@ void CAddonMgr::FillCpluffMetadata(const cp_plugin_info_t* plugin, CAddonBuilder
 
     builder.SetBroken(CAddonMgr::GetInstance().GetExtValue(metadata->configuration, "broken"));
 
-    if (CAddonMgr::GetInstance().GetExtValue(metadata->configuration, "nofanart") == "true")
-      builder.SetFanart("");
-    if (CAddonMgr::GetInstance().GetExtValue(metadata->configuration, "noicon") == "true")
-      builder.SetIcon("");
+    if (plugin->plugin_path && strcmp(plugin->plugin_path, "") != 0)
+    {
+      auto assets = CAddonMgr::GetInstance().GetExtElement(metadata->configuration, "assets");
+      if (assets)
+      {
+        builder.SetIcon("");
+        builder.SetFanart("");
+        std::string icon = CAddonMgr::GetInstance().GetExtValue(assets, "icon");
+        std::string fanart = CAddonMgr::GetInstance().GetExtValue(assets, "fanart");
+
+        if (!icon.empty())
+          builder.SetIcon(URIUtils::AddFileToFolder(plugin->plugin_path, icon));
+        if (!fanart.empty())
+          builder.SetFanart(URIUtils::AddFileToFolder(plugin->plugin_path, fanart));
+
+        std::vector<std::string> screenshots;
+        ELEMENTS elements;
+        if (CAddonMgr::GetInstance().GetExtElements(assets, "screenshot", elements))
+        {
+          for (const auto& elem : elements)
+          {
+            if (elem->value && strcmp(elem->value, "") != 0)
+              screenshots.emplace_back(URIUtils::AddFileToFolder(plugin->plugin_path, elem->value));
+          }
+        }
+        builder.SetScreenshots(std::move(screenshots));
+      }
+    }
   }
 }
 
@@ -323,7 +357,7 @@ bool CAddonMgr::Init()
  if (!m_database.Open())
    CLog::Log(LOGFATAL, "ADDONS: Failed to open database");
 
-  FindAddonsAndNotify();
+  FindAddons();
 
   //Ensure required add-ons are installed and enabled
   for (const auto& id : m_systemAddons)
@@ -529,7 +563,9 @@ bool CAddonMgr::GetAddonsInternal(const TYPE &type, VECADDONS &addons, bool enab
         continue;
       }
 
-      AddonPtr addon = Factory(cp_addon, type, builder);
+      AddonPtr addon;
+      if (Factory(cp_addon, type, builder))
+        addon = builder.Build();
       m_cpluff->release_info(m_cp_context, cp_addon);
 
       if (addon)
@@ -687,32 +723,36 @@ bool CAddonMgr::FindAddons()
     m_database.GetBlacklisted(tmp);
     m_updateBlacklist = std::move(tmp);
 
-    SetChanged();
+    m_events.Publish(AddonEvents::InstalledChanged());
   }
 
   return result;
 }
 
-bool CAddonMgr::FindAddonsAndNotify()
-{
-  if (!FindAddons())
-    return false;
-
-  NotifyObservers(ObservableMessageAddons);
-
-  return true;
-}
-
-void CAddonMgr::UnregisterAddon(const std::string& ID)
+bool CAddonMgr::UnloadAddon(const AddonPtr& addon)
 {
   CSingleLock lock(m_critSection);
   if (m_cpluff && m_cp_context)
   {
-    m_cpluff->uninstall_plugin(m_cp_context, ID.c_str());
-    SetChanged();
-    lock.Leave();
-    NotifyObservers(ObservableMessageAddons);
+    if (m_cpluff->uninstall_plugin(m_cp_context, addon->ID().c_str()) == CP_OK)
+    {
+      m_events.Publish(AddonEvents::InstalledChanged());
+      return true;
+    }
   }
+  return false;
+}
+
+bool CAddonMgr::ReloadAddon(AddonPtr& addon)
+{
+  CSingleLock lock(m_critSection);
+  if (!addon ||!m_cpluff || !m_cp_context)
+    return false;
+
+  m_cpluff->uninstall_plugin(m_cp_context, addon->ID().c_str());
+  return FindAddons()
+      && GetAddon(addon->ID(), addon, ADDON_UNKNOWN, false)
+      && EnableAddon(addon->ID());
 }
 
 void CAddonMgr::OnPostUnInstall(const std::string& id)
@@ -744,6 +784,18 @@ bool CAddonMgr::IsBlacklisted(const std::string& id) const
   return m_updateBlacklist.find(id) != m_updateBlacklist.end();
 }
 
+void CAddonMgr::UpdateLastUsed(const std::string& id)
+{
+  auto time = CDateTime::GetCurrentDateTime();
+  CJobManager::GetInstance().Submit([this, id, time](){
+    {
+      CSingleLock lock(m_critSection);
+      m_database.SetLastUsed(id, time);
+    }
+    m_events.Publish(AddonEvents::MetadataChanged(id));
+  });
+}
+
 static void ResolveDependencies(const std::string& addonId, std::vector<std::string>& needed, std::vector<std::string>& missing)
 {
   if (std::find(needed.begin(), needed.end(), addonId) != needed.end())
@@ -773,12 +825,14 @@ bool CAddonMgr::DisableAddon(const std::string& id)
   if (!m_disabled.insert(id).second)
     return false;
 
+  //success
+  ADDON::OnDisabled(id);
+
   AddonPtr addon;
   if (GetAddon(id, addon, ADDON_UNKNOWN, false) && addon != NULL)
     CEventLog::GetInstance().Add(EventPtr(new CAddonManagementEvent(addon, 24141)));
 
-  //success
-  ADDON::OnDisabled(id);
+  m_events.Publish(AddonEvents::Disabled(id));
   return true;
 }
 
@@ -797,11 +851,14 @@ bool CAddonMgr::EnableSingle(const std::string& id)
     CEventLog::GetInstance().Add(EventPtr(new CAddonManagementEvent(addon, 24064)));
 
   CLog::Log(LOGDEBUG, "CAddonMgr: enabled %s", addon->ID().c_str());
+  m_events.Publish(AddonEvents::Enabled(id));
   return true;
 }
 
 bool CAddonMgr::EnableAddon(const std::string& id)
 {
+  if (id.empty() || !IsAddonInstalled(id))
+    return false;
   std::vector<std::string> needed;
   std::vector<std::string> missing;
   ResolveDependencies(id, needed, missing);
@@ -810,6 +867,7 @@ bool CAddonMgr::EnableAddon(const std::string& id)
         "correctly", dep.c_str(), id.c_str());
   for (auto it = needed.rbegin(); it != needed.rend(); ++it)
     EnableSingle(*it);
+
   return true;
 }
 
@@ -1051,31 +1109,63 @@ std::string CAddonMgr::GetPlatformLibraryName(cp_cfg_element_t *base) const
   return libraryName;
 }
 
-// FIXME: This function may not be required
-bool CAddonMgr::LoadAddonDescription(const std::string &path, AddonPtr &addon)
+bool CAddonMgr::LoadAddonDescription(const std::string &directory, AddonPtr &addon)
 {
+  auto addonXmlPath = CSpecialProtocol::TranslatePath(URIUtils::AddFileToFolder(directory, "addon.xml"));
+
+  XFILE::CFile file;
+  XFILE::auto_buffer buffer;
+  if (file.LoadFile(addonXmlPath, buffer) <= 0)
+  {
+    CLog::Log(LOGERROR, "Failed to read '%s'", addonXmlPath.c_str());
+    return false;
+  }
+
   cp_status_t status;
-  cp_plugin_info_t *info = m_cpluff->load_plugin_descriptor(m_cp_context, CSpecialProtocol::TranslatePath(path).c_str(), &status);
+  cp_context_t* context = m_cpluff->create_context(&status);
+  if (!context)
+    return false;
+
+  auto info = m_cpluff->load_plugin_descriptor_from_memory(context, buffer.get(), buffer.size(), &status);
   if (info)
   {
+    // Correct the path. load_plugin_descriptor_from_memory sets it to 'memory'
+    info->plugin_path = (char*)malloc(strlen(directory.c_str()) + 1);
+    strcpy(info->plugin_path, directory.c_str());
     addon = Factory(info, ADDON_UNKNOWN);
-    m_cpluff->release_info(m_cp_context, info);
-    return NULL != addon.get();
+    m_cpluff->release_info(context, info);
   }
-  return false;
+  else
+    CLog::Log(LOGERROR, "Failed to parse '%s'", addonXmlPath.c_str());
+
+  m_cpluff->destroy_context(context);
+  return addon != nullptr;
 }
 
-bool CAddonMgr::AddonsFromRepoXML(const TiXmlElement *root, VECADDONS &addons)
+bool CAddonMgr::AddonsFromRepoXML(const CRepository::DirInfo& repo, const std::string& xml, VECADDONS& addons)
 {
+  CXBMCTinyXML doc;
+  if (!doc.Parse(xml))
+  {
+    CLog::Log(LOGERROR, "CAddonMgr: Failed to parse addons.xml.");
+    return false;
+  }
+
+  if (doc.RootElement() == nullptr || doc.RootElement()->ValueStr() != "addons")
+  {
+    CLog::Log(LOGERROR, "CAddonMgr: Failed to parse addons.xml. Malformed.");
+    return false;
+  }
+
   // create a context for these addons
   cp_status_t status;
   cp_context_t *context = m_cpluff->create_context(&status);
-  if (!root || !context)
+  if (!context)
     return false;
 
   // each addon XML should have a UTF-8 declaration
   TiXmlDeclaration decl("1.0", "UTF-8", "");
-  const TiXmlElement *element = root->FirstChildElement("addon");
+  auto element = doc.RootElement()->FirstChildElement("addon");
   while (element)
   {
     // dump the XML back to text
@@ -1086,9 +1176,19 @@ bool CAddonMgr::AddonsFromRepoXML(const TiXmlElement *root, VECADDONS &addons)
     cp_plugin_info_t *info = m_cpluff->load_plugin_descriptor_from_memory(context, xml.c_str(), xml.size(), &status);
     if (info)
     {
-      AddonPtr addon = Factory(info, ADDON_UNKNOWN);
-      if (addon.get())
-        addons.push_back(std::move(addon));
+      CAddonBuilder builder;
+      auto basePath = URIUtils::AddFileToFolder(repo.datadir, std::string(info->identifier));
+      info->plugin_path = (char*)malloc(strlen(basePath.c_str()) + 1);
+      strcpy(info->plugin_path, basePath .c_str());
+
+      if (Factory(info, ADDON_UNKNOWN, builder))
+      {
+        builder.SetPath(URIUtils::AddFileToFolder(repo.datadir, StringUtils::Format("%s/%s-%s.zip",
+            info->identifier, info->identifier, builder.GetVersion().asString().c_str())));
+        auto addon = builder.Build();
+        if (addon)
+          addons.push_back(std::move(addon));
+      }
       m_cpluff->release_info(context, info);
     }
     element = element->NextSiblingElement("addon");
@@ -1097,27 +1197,6 @@ bool CAddonMgr::AddonsFromRepoXML(const TiXmlElement *root, VECADDONS &addons)
   return true;
 }
 
-bool CAddonMgr::LoadAddonDescriptionFromMemory(const TiXmlElement *root, AddonPtr &addon)
-{
-  // create a context for these addons
-  cp_status_t status;
-  cp_context_t *context = m_cpluff->create_context(&status);
-  if (!root || !context)
-    return false;
-
-  // dump the XML back to text
-  std::string xml;
-  xml << TiXmlDeclaration("1.0", "UTF-8", "");
-  xml << *root;
-  cp_plugin_info_t *info = m_cpluff->load_plugin_descriptor_from_memory(context, xml.c_str(), xml.size(), &status);
-  if (info)
-  {
-    addon = Factory(info, ADDON_UNKNOWN);
-    m_cpluff->release_info(context, info);
-  }
-  m_cpluff->destroy_context(context);
-  return addon != NULL;
-}
 
 bool CAddonMgr::StartServices(const bool beforelogin)
 {
diff --git a/xbmc/addons/AddonManager.h b/xbmc/addons/AddonManager.h
index 2ed405a..7a2835c 100644
--- a/xbmc/addons/AddonManager.h
+++ b/xbmc/addons/AddonManager.h
@@ -19,13 +19,16 @@
  *
  */
 #include "Addon.h"
+#include "AddonDatabase.h"
+#include "AddonEvents.h"
+#include "Repository.h"
 #include "threads/CriticalSection.h"
-#include "utils/Observer.h"
+#include "utils/EventStream.h"
 #include <string>
 #include <vector>
 #include <map>
 #include <deque>
-#include "AddonDatabase.h"
+
 
 class DllLibCPluff;
 extern "C"
@@ -61,7 +64,7 @@ namespace ADDON
   * otherwise. Services the generic callbacks available
   * to all addon variants.
   */
-  class CAddonMgr : public Observable
+  class CAddonMgr
   {
   public:
     static CAddonMgr &GetInstance();
@@ -74,6 +77,7 @@ namespace ADDON
     CAddonMgr const& operator=(CAddonMgr const&);
     virtual ~CAddonMgr();
 
+    CEventStream<AddonEvent>& Events() { return m_events; }
 
     IAddonMgrCallback* GetCallbackForType(TYPE type);
     bool RegisterAddonMgrCallback(TYPE type, IAddonMgrCallback* cb);
@@ -134,12 +138,11 @@ namespace ADDON
      */
     bool FindAddons();
 
-    /*! \brief Checks for new / updated add-ons and notifies all observers
-    \return True if everything went ok, false otherwise
-    */
-    bool FindAddonsAndNotify();
+    /*! Unload addon from the system. Returns true if it was unloaded, otherwise false. */
+    bool UnloadAddon(const AddonPtr& addon);
 
-    void UnregisterAddon(const std::string& ID);
+    /*! Returns true if the addon was successfully loaded and enabled; otherwise false. */
+    bool ReloadAddon(AddonPtr& addon);
 
     /*! Hook for clearing internal state after uninstall. */
     void OnPostUnInstall(const std::string& id);
@@ -181,6 +184,8 @@ namespace ADDON
     bool RemoveFromUpdateBlacklist(const std::string& id);
     bool IsBlacklisted(const std::string& id) const;
 
+    void UpdateLastUsed(const std::string& id);
+
     /* libcpluff */
     std::string GetExtValue(cp_cfg_element_t *base, const char *path) const;
 
@@ -223,21 +228,14 @@ namespace ADDON
      */
     bool LoadAddonDescription(const std::string &path, AddonPtr &addon);
 
-    /*! \brief Load the addon in the given in-memory xml
-     This loads the addon using c-pluff which parses the addon descriptor file.
-     \param root Root element of an XML document.
-     \param addon [out] returned addon.
-     \return true if addon is set, false otherwise.
-     */
-    bool LoadAddonDescriptionFromMemory(const TiXmlElement *root, AddonPtr &addon);
-
     /*! \brief Parse a repository XML file for addons and load their descriptors
      A repository XML is essentially a concatenated list of addon descriptors.
-     \param root Root element of an XML document.
+     \param repo The repository info.
+     \param xml The XML document from repository.
      \param addons [out] returned list of addons.
      \return true if the repository XML file is parsed, false otherwise.
      */
-    bool AddonsFromRepoXML(const TiXmlElement *root, VECADDONS &addons);
+    bool AddonsFromRepoXML(const CRepository::DirInfo& repo, const std::string& xml, VECADDONS& addons);
 
     /*! \brief Start all services addons.
         \return True is all addons are started, false otherwise
@@ -246,8 +244,9 @@ namespace ADDON
     /*! \brief Stop all services addons.
     */
     void StopServices(const bool onlylogin);
+
     static AddonPtr Factory(const cp_plugin_info_t* plugin, TYPE type);
-    static AddonPtr Factory(const cp_plugin_info_t* plugin, TYPE type, CAddonBuilder& builder);
+    static bool Factory(const cp_plugin_info_t* plugin, TYPE type, CAddonBuilder& builder);
     static void FillCpluffMetadata(const cp_plugin_info_t* plugin, CAddonBuilder& builder);
 
   private:
@@ -271,6 +270,7 @@ namespace ADDON
     static std::map<TYPE, IAddonMgrCallback*> m_managers;
     CCriticalSection m_critSection;
     CAddonDatabase m_database;
+    CEventSource<AddonEvent> m_events;
     std::set<std::string> m_systemAddons;
     std::set<std::string> m_optionalAddons;
   };
diff --git a/xbmc/addons/BinaryAddonCache.cpp b/xbmc/addons/BinaryAddonCache.cpp
index c2caa5e..0c3a2b7 100644
--- a/xbmc/addons/BinaryAddonCache.cpp
+++ b/xbmc/addons/BinaryAddonCache.cpp
@@ -33,13 +33,13 @@ CBinaryAddonCache::~CBinaryAddonCache()
 void CBinaryAddonCache::Init()
 {
   m_addonsToCache = {ADDON_AUDIODECODER, ADDON_INPUTSTREAM};
-  CAddonMgr::GetInstance().RegisterObserver(this);
+  CAddonMgr::GetInstance().Events().Subscribe(this, &CBinaryAddonCache::OnEvent);
   Update();
 }
 
 void CBinaryAddonCache::Deinit()
 {
-  CAddonMgr::GetInstance().UnregisterObserver(this);
+  CAddonMgr::GetInstance().Events().Unsubscribe(this);
 }
 
 void CBinaryAddonCache::GetAddons(VECADDONS& addons, const TYPE& type)
@@ -57,9 +57,10 @@ void CBinaryAddonCache::GetAddons(VECADDONS& addons, const TYPE& type)
   }
 }
 
-void CBinaryAddonCache::Notify(const Observable &obs, const ObservableMessage msg)
+void CBinaryAddonCache::OnEvent(const AddonEvent& event)
 {
-  Update();
+  if (typeid(event) == typeid(AddonEvents::InstalledChanged))
+    Update();
 }
 
 void CBinaryAddonCache::Update()
diff --git a/xbmc/addons/BinaryAddonCache.h b/xbmc/addons/BinaryAddonCache.h
index 1642885..9700697 100644
--- a/xbmc/addons/BinaryAddonCache.h
+++ b/xbmc/addons/BinaryAddonCache.h
@@ -22,23 +22,24 @@
 
 #include "utils/Observer.h"
 #include "Addon.h"
+#include "AddonEvents.h"
 #include "threads/CriticalSection.h"
 #include <map>
 #include <vector>
 
 namespace ADDON {
 
-class CBinaryAddonCache : public Observer
+class CBinaryAddonCache
 {
 public:
   virtual ~CBinaryAddonCache();
   void Init();
   void Deinit();
   void GetAddons(VECADDONS& addons, const TYPE& type);
-  virtual void Notify(const Observable &obs, const ObservableMessage msg) override;
 
 protected:
   void Update();
+  void OnEvent(const AddonEvent& event);
   
   CCriticalSection m_critSection;
   std::multimap<TYPE, VECADDONS> m_addons;
diff --git a/xbmc/addons/CMakeLists.txt b/xbmc/addons/CMakeLists.txt
index fe97136..cb4da8c 100644
--- a/xbmc/addons/CMakeLists.txt
+++ b/xbmc/addons/CMakeLists.txt
@@ -32,6 +32,7 @@ set(SOURCES Addon.cpp
 
 set(HEADERS Addon.h
             AddonBuilder.h
+            AddonEvents.h
             BinaryAddonCache.h
             AddonDatabase.h
             AddonDll.h
@@ -70,8 +71,3 @@ set(HEADERS Addon.h
             Webinterface.h)
 
 core_add_library(addons)
-add_dependencies(addons libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(addons ffmpeg)
-endif()
diff --git a/xbmc/addons/GUIDialogAddonInfo.cpp b/xbmc/addons/GUIDialogAddonInfo.cpp
index ae5756a..81f1104 100644
--- a/xbmc/addons/GUIDialogAddonInfo.cpp
+++ b/xbmc/addons/GUIDialogAddonInfo.cpp
@@ -36,6 +36,7 @@
 #include "GUIUserMessages.h"
 #include "guilib/GUIWindowManager.h"
 #include "input/Key.h"
+#include "pictures/GUIWindowSlideShow.h"
 #include "settings/Settings.h"
 #include "utils/JobManager.h"
 #include "utils/FileOperationJob.h"
@@ -55,6 +56,7 @@
 #define CONTROL_BTN_SETTINGS         9
 #define CONTROL_BTN_SELECT          12
 #define CONTROL_BTN_AUTOUPDATE      13
+#define CONTROL_LIST_SCREENSHOTS    50
 
 using namespace ADDON;
 using namespace XFILE;
@@ -135,6 +137,17 @@ bool CGUIDialogAddonInfo::OnMessage(CGUIMessage& message)
         OnToggleAutoUpdates();
         return true;
       }
+      else if (iControl == CONTROL_LIST_SCREENSHOTS)
+      {
+        if (message.GetParam1() == ACTION_SELECT_ITEM || message.GetParam1() == ACTION_MOUSE_LEFT_CLICK)
+        {
+          CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), iControl);
+          OnMessage(msg);
+          int start = msg.GetParam1();
+          if (start >= 0 && start < m_item->GetAddonInfo()->Screenshots().size())
+            CGUIWindowSlideShow::RunSlideShow(m_item->GetAddonInfo()->Screenshots(), start);
+        }
+      }
     }
     break;
 default:
@@ -198,6 +211,16 @@ void CGUIDialogAddonInfo::UpdateControls()
   SET_CONTROL_LABEL(CONTROL_BTN_SELECT, CanUse() ? 21480 : (CanOpen() ? 21478 : 21479));
 
   CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_SETTINGS, isInstalled && m_localAddon->HasSettings());
+
+  CFileItemList items;
+  for (const auto& screenshot : m_item->GetAddonInfo()->Screenshots())
+  {
+    auto item = std::make_shared<CFileItem>("");
+    item->SetArt("thumb", screenshot);
+    items.Add(std::move(item));
+  }
+  CGUIMessage msg(GUI_MSG_LABEL_BIND, GetID(), CONTROL_LIST_SCREENSHOTS, 0, 0, &items);
+  OnMessage(msg);
 }
 
 static const std::string LOCAL_CACHE = "\\0_local_cache"; // \0 to give it the lowest priority when sorting
@@ -434,7 +457,6 @@ void CGUIDialogAddonInfo::OnEnableDisable()
     CAddonMgr::GetInstance().EnableAddon(m_localAddon->ID());
 
   UpdateControls();
-  g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE);
 }
 
 void CGUIDialogAddonInfo::OnSettings()
diff --git a/xbmc/addons/GUIDialogAddonSettings.cpp b/xbmc/addons/GUIDialogAddonSettings.cpp
index 1c9a05e..8b189f1 100644
--- a/xbmc/addons/GUIDialogAddonSettings.cpp
+++ b/xbmc/addons/GUIDialogAddonSettings.cpp
@@ -782,15 +782,18 @@ void CGUIDialogAddonSettings::CreateControls()
           int iAdd = i;
           if (entryVec.size() > i)
             iAdd = atoi(entryVec[i].c_str());
-          if (!lvalues.empty())
+          std::string replace;
+          if (!lvalues.empty() && std::all_of(valuesVec[i].begin(), valuesVec[i].end(), ::isdigit))
           {
-            std::string replace = g_localizeStrings.GetAddonString(m_addon->ID(),atoi(valuesVec[i].c_str()));
+            replace = g_localizeStrings.GetAddonString(m_addon->ID(), atoi(valuesVec[i].c_str()));
             if (replace.empty())
               replace = g_localizeStrings.Get(atoi(valuesVec[i].c_str()));
-            ((CGUISpinControlEx *)pControl)->AddLabel(replace, iAdd);
+            if (replace.empty())
+              replace = valuesVec[i];
           }
           else
-            ((CGUISpinControlEx *)pControl)->AddLabel(valuesVec[i], iAdd);
+            replace = valuesVec[i];
+          ((CGUISpinControlEx *)pControl)->AddLabel(replace, iAdd);
         }
         if (type == "labelenum")
         { // need to run through all our settings and find the one that matches
diff --git a/xbmc/addons/GUIViewStateAddonBrowser.cpp b/xbmc/addons/GUIViewStateAddonBrowser.cpp
index 29dd891..abb9304 100644
--- a/xbmc/addons/GUIViewStateAddonBrowser.cpp
+++ b/xbmc/addons/GUIViewStateAddonBrowser.cpp
@@ -60,7 +60,6 @@ CGUIViewStateAddonBrowser::CGUIViewStateAddonBrowser(const CFileItemList& items)
   }
   SetViewAsControl(DEFAULT_VIEW_AUTO);
 
-  SetSortOrder(SortOrderAscending);
   LoadViewState(items.GetPath(), WINDOW_ADDON_BROWSER);
 }
 
diff --git a/xbmc/addons/GUIWindowAddonBrowser.cpp b/xbmc/addons/GUIWindowAddonBrowser.cpp
index a79b404..b2909d7 100644
--- a/xbmc/addons/GUIWindowAddonBrowser.cpp
+++ b/xbmc/addons/GUIWindowAddonBrowser.cpp
@@ -71,12 +71,18 @@ bool CGUIWindowAddonBrowser::OnMessage(CGUIMessage& message)
   {
     case GUI_MSG_WINDOW_DEINIT:
     {
+      CRepositoryUpdater::GetInstance().Events().Unsubscribe(this);
+      CAddonMgr::GetInstance().Events().Unsubscribe(this);
+
       if (m_thumbLoader.IsLoading())
         m_thumbLoader.StopThread();
     }
     break;
   case GUI_MSG_WINDOW_INIT:
     {
+      CRepositoryUpdater::GetInstance().Events().Subscribe(this, &CGUIWindowAddonBrowser::OnEvent);
+      CAddonMgr::GetInstance().Events().Subscribe(this, &CGUIWindowAddonBrowser::OnEvent);
+
       SetProperties();
     }
     break;
@@ -163,6 +169,17 @@ class UpdateAddons : public IRunnable
   }
 };
 
+void CGUIWindowAddonBrowser::OnEvent(const ADDON::CRepositoryUpdater::RepositoryUpdated& event)
+{
+  CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE);
+  g_windowManager.SendThreadMessage(msg);
+}
+
+void CGUIWindowAddonBrowser::OnEvent(const ADDON::AddonEvent& event)
+{
+  CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE);
+  g_windowManager.SendThreadMessage(msg);
+}
 
 bool CGUIWindowAddonBrowser::OnClick(int iItem, const std::string &player)
 {
diff --git a/xbmc/addons/GUIWindowAddonBrowser.h b/xbmc/addons/GUIWindowAddonBrowser.h
index 0831fd9..b1c7822 100644
--- a/xbmc/addons/GUIWindowAddonBrowser.h
+++ b/xbmc/addons/GUIWindowAddonBrowser.h
@@ -22,10 +22,12 @@
 
 #include <string>
 #include <vector>
-
-#include "addons/Addon.h"
-#include "windows/GUIMediaWindow.h"
+#include "Addon.h"
+#include "AddonEvents.h"
+#include "RepositoryUpdater.h"
 #include "ThumbLoader.h"
+#include "windows/GUIMediaWindow.h"
+
 
 class CFileItem;
 class CFileItemList;
@@ -75,6 +77,8 @@ protected:
 private:
   void SetProperties();
   void UpdateStatus(const CFileItemPtr& item);
+  void OnEvent(const ADDON::CRepositoryUpdater::RepositoryUpdated& event);
+  void OnEvent(const ADDON::AddonEvent& event);
   CProgramThumbLoader m_thumbLoader;
 };
 
diff --git a/xbmc/addons/IAddon.h b/xbmc/addons/IAddon.h
index fcabb6a..1b1dfb3 100644
--- a/xbmc/addons/IAddon.h
+++ b/xbmc/addons/IAddon.h
@@ -26,6 +26,7 @@
 #include <set>
 #include <string>
 #include <utility>
+#include <vector>
 #include "XBDateTime.h"
 
 class TiXmlElement;
@@ -94,7 +95,6 @@ namespace ADDON
     virtual TYPE Type() const =0;
     virtual TYPE FullType() const =0;
     virtual bool IsType(TYPE type) const =0;
-    virtual const AddonProps& Props() =0;
     virtual std::string ID() const =0;
     virtual std::string Name() const =0;
     virtual bool IsInUse() const =0;
@@ -107,6 +107,7 @@ namespace ADDON
     virtual std::string LibPath() const =0;
     virtual std::string ChangeLog() const =0;
     virtual std::string FanArt() const =0;
+    virtual std::vector<std::string> Screenshots() const =0;
     virtual std::string Author() const =0;
     virtual std::string Icon() const =0;
     virtual std::string Disclaimer() const =0;
diff --git a/xbmc/addons/PVRClient.cpp b/xbmc/addons/PVRClient.cpp
index e617adb..0e7f7c0 100644
--- a/xbmc/addons/PVRClient.cpp
+++ b/xbmc/addons/PVRClient.cpp
@@ -468,7 +468,7 @@ bool CPVRClient::GetAddonProperties(void)
         // This code can be removed once all addons actually support the respective PVR Addon API version.
 
         size = 0;
-        // One-shot manual
+        // manual one time
         memset(&types_array[size], 0, sizeof(types_array[size]));
         types_array[size].iId         = size + 1;
         types_array[size].iAttributes = PVR_TIMER_TYPE_IS_MANUAL               |
@@ -481,7 +481,7 @@ bool CPVRClient::GetAddonProperties(void)
                                         PVR_TIMER_TYPE_SUPPORTS_RECORDING_FOLDERS;
         ++size;
 
-        // Repeating manual
+        // manual timer rule
         memset(&types_array[size], 0, sizeof(types_array[size]));
         types_array[size].iId         = size + 1;
         types_array[size].iAttributes = PVR_TIMER_TYPE_IS_MANUAL               |
@@ -534,14 +534,14 @@ bool CPVRClient::GetAddonProperties(void)
             if (types_array[i].iAttributes & PVR_TIMER_TYPE_IS_REPEATING)
             {
               id = (types_array[i].iAttributes & PVR_TIMER_TYPE_IS_MANUAL)
-                 ? 822  // "Repeating"
-                 : 823; // "Repeating (Guide-based)"
+                 ? 822  // "Timer rule"
+                 : 823; // "Timer rule (guide-based)"
             }
             else
             {
               id = (types_array[i].iAttributes & PVR_TIMER_TYPE_IS_MANUAL)
-                 ? 820  // "One Time"
-                 : 821; // "One Time (Guide-based)
+                 ? 820  // "One time"
+                 : 821; // "One time (guide-based)
             }
             std::string descr(g_localizeStrings.Get(id));
             strncpy(types_array[i].strDescription, descr.c_str(), descr.size());
diff --git a/xbmc/addons/Repository.cpp b/xbmc/addons/Repository.cpp
index 3de88c0..cb6bc19 100644
--- a/xbmc/addons/Repository.cpp
+++ b/xbmc/addons/Repository.cpp
@@ -70,30 +70,24 @@ std::unique_ptr<CRepository> CRepository::FromExtension(AddonProps props, const
       if (min_version <= version)
       {
         DirInfo dir;
-        dir.version    = min_version;
-        dir.checksum   = CAddonMgr::GetInstance().GetExtValue(&ext->configuration->children[i], "checksum");
-        dir.compressed = CAddonMgr::GetInstance().GetExtValue(&ext->configuration->children[i], "info at compressed") == "true";
-        dir.info       = CAddonMgr::GetInstance().GetExtValue(&ext->configuration->children[i], "info");
-        dir.datadir    = CAddonMgr::GetInstance().GetExtValue(&ext->configuration->children[i], "datadir");
-        dir.zipped     = CAddonMgr::GetInstance().GetExtValue(&ext->configuration->children[i], "datadir at zip") == "true";
-        dir.hashes     = CAddonMgr::GetInstance().GetExtValue(&ext->configuration->children[i], "hashes") == "true";
-        dirs.push_back(dir);
+        dir.version = min_version;
+        dir.checksum = CAddonMgr::GetInstance().GetExtValue(&ext->configuration->children[i], "checksum");
+        dir.info = CAddonMgr::GetInstance().GetExtValue(&ext->configuration->children[i], "info");
+        dir.datadir = CAddonMgr::GetInstance().GetExtValue(&ext->configuration->children[i], "datadir");
+        dir.hashes = CAddonMgr::GetInstance().GetExtValue(&ext->configuration->children[i], "hashes") == "true";
+        dirs.push_back(std::move(dir));
       }
     }
   }
-  // backward compatibility
   if (!CAddonMgr::GetInstance().GetExtValue(ext->configuration, "info").empty())
   {
     DirInfo info;
-    info.checksum   = CAddonMgr::GetInstance().GetExtValue(ext->configuration, "checksum");
-    info.compressed = CAddonMgr::GetInstance().GetExtValue(ext->configuration, "info at compressed") == "true";
-    info.info       = CAddonMgr::GetInstance().GetExtValue(ext->configuration, "info");
-    info.datadir    = CAddonMgr::GetInstance().GetExtValue(ext->configuration, "datadir");
-    info.zipped     = CAddonMgr::GetInstance().GetExtValue(ext->configuration, "datadir at zip") == "true";
-    info.hashes     = CAddonMgr::GetInstance().GetExtValue(ext->configuration, "hashes") == "true";
-    dirs.push_back(info);
+    info.checksum = CAddonMgr::GetInstance().GetExtValue(ext->configuration, "checksum");
+    info.info = CAddonMgr::GetInstance().GetExtValue(ext->configuration, "info");
+    info.datadir = CAddonMgr::GetInstance().GetExtValue(ext->configuration, "datadir");
+    info.hashes = CAddonMgr::GetInstance().GetExtValue(ext->configuration, "hashes") == "true";
+    dirs.push_back(std::move(info));
   }
-
   return std::unique_ptr<CRepository>(new CRepository(std::move(props), std::move(dirs)));
 }
 
@@ -102,111 +96,113 @@ CRepository::CRepository(AddonProps props, DirList dirs)
 {
 }
 
-std::string CRepository::FetchChecksum(const std::string& url)
-{
-  CFile file;
-  try
-  {
-    if (file.Open(url))
-    {    
-      // we intentionally avoid using file.GetLength() for 
-      // Transfer-Encoding: chunked servers.
-      std::stringstream str;
-      char temp[1024];
-      int read;
-      while ((read=file.Read(temp, sizeof(temp))) > 0)
-        str.write(temp, read);
-      return str.str();
-    }
-    return "";
-  }
-  catch (...)
-  {
-    return "";
-  }
-}
 
-std::string CRepository::GetAddonHash(const AddonPtr& addon) const
+bool CRepository::GetAddonHash(const AddonPtr& addon, std::string& checksum) const
 {
-  std::string checksum;
   DirList::const_iterator it;
   for (it = m_dirs.begin();it != m_dirs.end(); ++it)
     if (URIUtils::PathHasParent(addon->Path(), it->datadir, true))
       break;
-  if (it != m_dirs.end() && it->hashes)
+
+  if (it != m_dirs.end())
   {
-    checksum = FetchChecksum(addon->Path()+".md5");
-    size_t pos = checksum.find_first_of(" \n");
-    if (pos != std::string::npos)
-      return checksum.substr(0, pos);
+    if (!it->hashes)
+    {
+      checksum = "";
+      return true;
+    }
+    if (FetchChecksum(addon->Path() + ".md5", checksum))
+    {
+      size_t pos = checksum.find_first_of(" \n");
+      if (pos != std::string::npos)
+      {
+        checksum = checksum.substr(0, pos);
+        return true;
+      }
+    }
   }
-  return checksum;
+  return false;
 }
 
-#define SET_IF_NOT_EMPTY(x,y) \
-  { \
-    if (!x.empty()) \
-       x = y; \
-  }
+bool CRepository::FetchChecksum(const std::string& url, std::string& checksum) noexcept
+{
+  CFile file;
+  if (!file.Open(url))
+    return false;
 
+  // we intentionally avoid using file.GetLength() for
+  // Transfer-Encoding: chunked servers.
+  std::stringstream ss;
+  char temp[1024];
+  int read;
+  while ((read = file.Read(temp, sizeof(temp))) > 0)
+    ss.write(temp, read);
+  if (read <= -1)
+    return false;
+  checksum = ss.str();
+  return true;
+}
 
-bool CRepository::FetchIndex(const std::string& url, VECADDONS& addons)
+bool CRepository::FetchIndex(const DirInfo& repo, VECADDONS& addons) noexcept
 {
   XFILE::CCurlFile http;
   http.SetAcceptEncoding("gzip");
 
-  std::string content;
-  if (!http.Get(url, content))
+  std::string response;
+  if (!http.Get(repo.info, response))
+  {
+    CLog::Log(LOGERROR, "CRepository: failed to read %s", repo.info.c_str());
     return false;
+  }
 
-  if (URIUtils::HasExtension(url, ".gz")
+  if (URIUtils::HasExtension(repo.info, ".gz")
       || CMime::GetFileTypeFromMime(http.GetMimeType()) == CMime::EFileType::FileTypeGZip)
   {
-    CLog::Log(LOGDEBUG, "CRepository '%s' is gzip. decompressing", url.c_str());
+    CLog::Log(LOGDEBUG, "CRepository '%s' is gzip. decompressing", repo.info.c_str());
     std::string buffer;
-    if (!CZipFile::DecompressGzip(content, buffer))
+    if (!CZipFile::DecompressGzip(response, buffer))
+    {
+      CLog::Log(LOGERROR, "CRepository: failed to decompress gzip from '%s'", repo.info.c_str());
       return false;
-    content = std::move(buffer);
+    }
+    response = std::move(buffer);
   }
 
-  CXBMCTinyXML doc;
-  if (!doc.Parse(content) || !doc.RootElement()
-      || !CAddonMgr::GetInstance().AddonsFromRepoXML(doc.RootElement(), addons))
-  {
-    CLog::Log(LOGERROR, "CRepository: Failed to parse addons.xml. Malformated.");
-    return false;
-  }
-  return true;
+  return CAddonMgr::GetInstance().AddonsFromRepoXML(repo, response, addons);
 }
 
-bool CRepository::Parse(const DirInfo& dir, VECADDONS& addons)
+CRepository::FetchStatus CRepository::FetchIfChanged(const std::string& oldChecksum,
+    std::string& checksum, VECADDONS& addons) const
 {
-  if (!FetchIndex(dir.info, addons))
-    return false;
-
-    for (IVECADDONS i = addons.begin(); i != addons.end(); ++i)
+  checksum = "";
+  for (const auto& dir : m_dirs)
+  {
+    if (!dir.checksum.empty())
     {
-      AddonPtr addon = *i;
-      if (dir.zipped)
-      {
-        std::string file = StringUtils::Format("%s/%s-%s.zip", addon->ID().c_str(), addon->ID().c_str(), addon->Version().asString().c_str());
-        addon->Props().path = URIUtils::AddFileToFolder(dir.datadir,file);
-        SET_IF_NOT_EMPTY(addon->Props().icon,URIUtils::AddFileToFolder(dir.datadir,addon->ID()+"/icon.png"))
-        SET_IF_NOT_EMPTY(addon->Props().fanart,URIUtils::AddFileToFolder(dir.datadir,addon->ID()+"/fanart.jpg"))
-      }
-      else
+      std::string part;
+      if (!FetchChecksum(dir.checksum, part))
       {
-        addon->Props().path = URIUtils::AddFileToFolder(dir.datadir,addon->ID()+"/");
-        SET_IF_NOT_EMPTY(addon->Props().icon,URIUtils::AddFileToFolder(dir.datadir,addon->ID()+"/icon.png"))
-        SET_IF_NOT_EMPTY(addon->Props().fanart,URIUtils::AddFileToFolder(dir.datadir,addon->ID()+"/fanart.jpg"))
+        CLog::Log(LOGERROR, "CRepository: failed read '%s'", dir.checksum.c_str());
+        return STATUS_ERROR;
       }
+      checksum += part;
     }
-  return true;
-}
+  }
 
+  if (oldChecksum == checksum && !oldChecksum.empty())
+    return STATUS_NOT_MODIFIED;
 
-CRepositoryUpdateJob::CRepositoryUpdateJob(const RepositoryPtr& repo) : m_repo(repo) {}
+  for (const auto& dir : m_dirs)
+  {
+    VECADDONS tmp;
+    if (!FetchIndex(dir, tmp))
+      return STATUS_ERROR;
+    addons.insert(addons.end(), tmp.begin(), tmp.end());
+  }
+  return STATUS_OK;
+}
 
+CRepositoryUpdateJob::CRepositoryUpdateJob(const RepositoryPtr& repo) : m_repo(repo) {}
 
 bool CRepositoryUpdateJob::DoWork()
 {
@@ -220,17 +216,17 @@ bool CRepositoryUpdateJob::DoWork()
 
   std::string newChecksum;
   VECADDONS addons;
-  auto status = FetchIfChanged(oldChecksum, newChecksum, addons);
+  auto status = m_repo->FetchIfChanged(oldChecksum, newChecksum, addons);
 
   database.SetLastChecked(m_repo->ID(), m_repo->Version(),
       CDateTime::GetCurrentDateTime().GetAsDBDateTime());
 
   MarkFinished();
 
-  if (status == STATUS_ERROR)
+  if (status == CRepository::STATUS_ERROR)
     return false;
 
-  if (status == STATUS_NOT_MODIFIED)
+  if (status == CRepository::STATUS_NOT_MODIFIED)
   {
     CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] checksum not changed.", m_repo->ID().c_str());
     return true;
@@ -247,12 +243,14 @@ bool CRepositoryUpdateJob::DoWork()
       AddonPtr oldAddon;
       if (database.GetAddon(addon->ID(), oldAddon) && addon->Version() > oldAddon->Version())
       {
-        if (!addon->Icon().empty() || !addon->FanArt().empty())
+        if (!oldAddon->Icon().empty() || !oldAddon->FanArt().empty() || !oldAddon->Screenshots().empty())
           CLog::Log(LOGDEBUG, "CRepository: invalidating cached art for '%s'", addon->ID().c_str());
-        if (!addon->Icon().empty())
-          textureDB.InvalidateCachedTexture(addon->Icon());
-        if (!addon->FanArt().empty())
-          textureDB.InvalidateCachedTexture(addon->Icon());
+        if (!oldAddon->Icon().empty())
+          textureDB.InvalidateCachedTexture(oldAddon->Icon());
+        if (!oldAddon->FanArt().empty())
+          textureDB.InvalidateCachedTexture(oldAddon->Icon());
+        for (const auto& path : oldAddon->Screenshots())
+          textureDB.InvalidateCachedTexture(path);
       }
     }
     textureDB.CommitMultipleExecute();
@@ -314,51 +312,3 @@ bool CRepositoryUpdateJob::DoWork()
   database.CommitMultipleExecute();
   return true;
 }
-
-CRepositoryUpdateJob::FetchStatus CRepositoryUpdateJob::FetchIfChanged(const std::string& oldChecksum,
-    std::string& checksum, VECADDONS& addons)
-{
-  SetText(StringUtils::Format(g_localizeStrings.Get(24093).c_str(), m_repo->Name().c_str()));
-  const unsigned int total = m_repo->m_dirs.size() * 2;
-
-  checksum = "";
-  for (auto it = m_repo->m_dirs.cbegin(); it != m_repo->m_dirs.cend(); ++it)
-  {
-    if (!it->checksum.empty())
-    {
-      if (ShouldCancel(std::distance(m_repo->m_dirs.cbegin(), it), total))
-        return STATUS_ERROR;
-
-      auto dirsum = CRepository::FetchChecksum(it->checksum);
-      if (dirsum.empty())
-      {
-        CLog::Log(LOGERROR, "CRepositoryUpdateJob[%s] failed read checksum for "
-            "directory '%s'", m_repo->ID().c_str(), it->info.c_str());
-        return STATUS_ERROR;
-      }
-      checksum += dirsum;
-    }
-  }
-
-  if (oldChecksum == checksum && !oldChecksum.empty())
-    return STATUS_NOT_MODIFIED;
-
-  for (auto it = m_repo->m_dirs.cbegin(); it != m_repo->m_dirs.cend(); ++it)
-  {
-    if (ShouldCancel(m_repo->m_dirs.size() + std::distance(m_repo->m_dirs.cbegin(), it), total))
-      return STATUS_ERROR;
-
-    VECADDONS tmp;
-    if (!CRepository::Parse(*it, tmp))
-    {
-      CLog::Log(LOGERROR, "CRepositoryUpdateJob[%s] failed to read or parse "
-          "directory '%s'", m_repo->ID().c_str(), it->info.c_str());
-      return STATUS_ERROR;
-    }
-    addons.insert(addons.end(), tmp.begin(), tmp.end());
-  }
-
-  SetProgress(total, total);
-  return STATUS_OK;
-}
-
diff --git a/xbmc/addons/Repository.h b/xbmc/addons/Repository.h
index 5ceabc4..442d0e1 100644
--- a/xbmc/addons/Repository.h
+++ b/xbmc/addons/Repository.h
@@ -34,20 +34,16 @@ namespace ADDON
   public:
     struct DirInfo
     {
-      DirInfo() : version("0.0.0"), compressed(false), zipped(false), hashes(false) {}
+      DirInfo() : version("0.0.0"), hashes(false) {}
       AddonVersion version;
       std::string info;
       std::string checksum;
       std::string datadir;
-      bool compressed;
-      bool zipped;
       bool hashes;
     };
 
     typedef std::vector<DirInfo> DirList;
 
-    DirList m_dirs;
-
     static std::unique_ptr<CRepository> FromExtension(AddonProps props, const cp_extension_t* ext);
 
     explicit CRepository(AddonProps props) : CAddon(std::move(props)) {};
@@ -55,15 +51,23 @@ namespace ADDON
 
     /*! \brief Get the md5 hash for an addon.
      \param the addon in question.
-     \return the md5 hash for the given addon, empty if non exists.
      */
-    std::string GetAddonHash(const AddonPtr& addon) const;
+    bool GetAddonHash(const AddonPtr& addon, std::string& checksum) const;
+
+    enum FetchStatus
+    {
+      STATUS_OK,
+      STATUS_NOT_MODIFIED,
+      STATUS_ERROR
+    };
 
-    static bool Parse(const DirInfo& dir, VECADDONS& addons);
-    static std::string FetchChecksum(const std::string& url);
+    FetchStatus FetchIfChanged(const std::string& oldChecksum, std::string& checksum, VECADDONS& addons) const;
 
   private:
-    static bool FetchIndex(const std::string& url, VECADDONS& addons);
+    static bool FetchChecksum(const std::string& url, std::string& checksum) noexcept;
+    static bool FetchIndex(const DirInfo& repo, VECADDONS& addons) noexcept;
+
+    DirList m_dirs;
   };
 
   typedef std::shared_ptr<CRepository> RepositoryPtr;
@@ -78,16 +82,6 @@ namespace ADDON
     const RepositoryPtr& GetAddon() const { return m_repo; };
 
   private:
-    enum FetchStatus
-    {
-      STATUS_OK,
-      STATUS_NOT_MODIFIED,
-      STATUS_ERROR
-    };
-
-    FetchStatus FetchIfChanged(const std::string& oldChecksum,
-        std::string& checksum, VECADDONS& addons);
-
     const RepositoryPtr m_repo;
   };
 }
diff --git a/xbmc/addons/RepositoryUpdater.cpp b/xbmc/addons/RepositoryUpdater.cpp
index 719f884..41bc15c 100644
--- a/xbmc/addons/RepositoryUpdater.cpp
+++ b/xbmc/addons/RepositoryUpdater.cpp
@@ -20,7 +20,6 @@
 
 #include "RepositoryUpdater.h"
 #include "Application.h"
-#include "GUIUserMessages.h"
 #include "addons/AddonInstaller.h"
 #include "addons/AddonManager.h"
 #include "addons/AddonSystemSettings.h"
@@ -89,8 +88,7 @@ void CRepositoryUpdater::OnJobComplete(unsigned int jobID, bool success, CJob* j
 
     ScheduleUpdate();
 
-    CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE);
-    g_windowManager.SendThreadMessage(msg);
+    m_events.Publish(RepositoryUpdated{});
   }
 }
 
diff --git a/xbmc/addons/RepositoryUpdater.h b/xbmc/addons/RepositoryUpdater.h
index 80afc91..9075df1 100644
--- a/xbmc/addons/RepositoryUpdater.h
+++ b/xbmc/addons/RepositoryUpdater.h
@@ -23,6 +23,7 @@
 #include "dialogs/GUIDialogExtendedProgressBar.h"
 #include "threads/CriticalSection.h"
 #include "threads/Timer.h"
+#include "utils/EventStream.h"
 #include "XBDateTime.h"
 #include <vector>
 
@@ -65,8 +66,13 @@ public:
    */
   CDateTime LastUpdated() const;
 
+
   virtual void OnSettingChanged(const CSetting* setting) override;
 
+  struct RepositoryUpdated { };
+
+  CEventStream<RepositoryUpdated>& Events() { return m_events; }
+
 private:
   CRepositoryUpdater();
   CRepositoryUpdater(const CRepositoryUpdater&) = delete;
@@ -82,5 +88,7 @@ private:
   CTimer m_timer;
   CEvent m_doneEvent;
   std::vector<CRepositoryUpdateJob*> m_jobs;
+
+  CEventSource<RepositoryUpdated> m_events;
 };
 }
diff --git a/xbmc/addons/Scraper.cpp b/xbmc/addons/Scraper.cpp
index 63e0191..be0e5be 100644
--- a/xbmc/addons/Scraper.cpp
+++ b/xbmc/addons/Scraper.cpp
@@ -1035,16 +1035,16 @@ bool CScraper::GetArtistDetails(CCurlFile &fcurl, const CScraperUrl &scurl,
 
 bool CScraper::GetArtwork(XFILE::CCurlFile &fcurl, CVideoInfoTag &details)
 {
-  if (details.m_strIMDBNumber.empty())
+  if (!details.HasUniqueID())
     return false;
 
   CLog::Log(LOGDEBUG, "%s: Reading artwork for '%s' using %s scraper "
-    "(file: '%s', content: '%s', version: '%s')", __FUNCTION__, details.m_strIMDBNumber.c_str(),
+    "(file: '%s', content: '%s', version: '%s')", __FUNCTION__, details.GetUniqueID().c_str(),
     Name().c_str(), Path().c_str(), ADDON::TranslateContent(Content()).c_str(), Version().asString().c_str());
 
   std::vector<std::string> vcsIn;
   CScraperUrl scurl;
-  vcsIn.push_back(details.m_strIMDBNumber);
+  vcsIn.push_back(details.GetUniqueID());
   std::vector<std::string> vcsOut = RunNoThrow("GetArt", scurl, fcurl, &vcsIn);
 
   bool fRet(false);
diff --git a/xbmc/addons/binary/interfaces/AddonInterfaces.cpp b/xbmc/addons/binary/interfaces/AddonInterfaces.cpp
index b8d55a8..5d517a4 100644
--- a/xbmc/addons/binary/interfaces/AddonInterfaces.cpp
+++ b/xbmc/addons/binary/interfaces/AddonInterfaces.cpp
@@ -53,7 +53,7 @@ CAddonInterfaces::CAddonInterfaces(CAddon* addon)
     m_helperInputStream(nullptr),
     m_helperPeripheral(nullptr)
 {
-  m_callbacks->libBasePath                  = strdup(CSpecialProtocol::TranslatePath("special://xbmcbin/addons").c_str());
+  m_callbacks->libBasePath                  = strdup(CSpecialProtocol::TranslatePath("special://xbmcbinaddons").c_str());
   m_callbacks->addonData                    = this;
 
   m_callbacks->AddOnLib_RegisterMe          = CAddonInterfaces::AddOnLib_RegisterMe;
diff --git a/xbmc/addons/binary/interfaces/CMakeLists.txt b/xbmc/addons/binary/interfaces/CMakeLists.txt
index 6c9804f..83a64ef 100644
--- a/xbmc/addons/binary/interfaces/CMakeLists.txt
+++ b/xbmc/addons/binary/interfaces/CMakeLists.txt
@@ -4,7 +4,3 @@ set(HEADERS AddonInterfaces.h
             IAddonInterface.h)
 
 core_add_library(addonsBinaryInterfaces)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(addonsBinaryInterfaces ffmpeg)
-endif()
diff --git a/xbmc/addons/binary/interfaces/api1/Addon/CMakeLists.txt b/xbmc/addons/binary/interfaces/api1/Addon/CMakeLists.txt
index e04be2c..5fd0aa5 100644
--- a/xbmc/addons/binary/interfaces/api1/Addon/CMakeLists.txt
+++ b/xbmc/addons/binary/interfaces/api1/Addon/CMakeLists.txt
@@ -3,8 +3,3 @@ set(SOURCES AddonCallbacksAddon.cpp)
 set(HEADERS AddonCallbacksAddon.h)
 
 core_add_library(api1AddonCallbacks_Addon)
-add_dependencies(api1AddonCallbacks_Addon libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(api1AddonCallbacks_Addon ffmpeg)
-endif()
diff --git a/xbmc/addons/binary/interfaces/api1/AudioDSP/CMakeLists.txt b/xbmc/addons/binary/interfaces/api1/AudioDSP/CMakeLists.txt
index 87da211..020e076 100644
--- a/xbmc/addons/binary/interfaces/api1/AudioDSP/CMakeLists.txt
+++ b/xbmc/addons/binary/interfaces/api1/AudioDSP/CMakeLists.txt
@@ -3,8 +3,3 @@ set(SOURCES AddonCallbacksAudioDSP.cpp)
 set(HEADERS AddonCallbacksAudioDSP.h)
 
 core_add_library(api1AddonCallbacks_AudioDSP)
-add_dependencies(api1AddonCallbacks_AudioDSP libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(api1AddonCallbacks_AudioDSP ffmpeg)
-endif()
diff --git a/xbmc/addons/binary/interfaces/api1/AudioEngine/CMakeLists.txt b/xbmc/addons/binary/interfaces/api1/AudioEngine/CMakeLists.txt
index e0dc76a..f0eb70c 100644
--- a/xbmc/addons/binary/interfaces/api1/AudioEngine/CMakeLists.txt
+++ b/xbmc/addons/binary/interfaces/api1/AudioEngine/CMakeLists.txt
@@ -3,8 +3,3 @@ set(SOURCES AddonCallbacksAudioEngine.cpp)
 set(HEADERS AddonCallbacksAudioEngine.h)
 
 core_add_library(api1AddonCallbacks_AudioEngine)
-add_dependencies(api1AddonCallbacks_AudioEngine libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(api1AddonCallbacks_AudioEngine ffmpeg)
-endif()
diff --git a/xbmc/addons/binary/interfaces/api1/Codec/CMakeLists.txt b/xbmc/addons/binary/interfaces/api1/Codec/CMakeLists.txt
index d760b00..0fe6925 100644
--- a/xbmc/addons/binary/interfaces/api1/Codec/CMakeLists.txt
+++ b/xbmc/addons/binary/interfaces/api1/Codec/CMakeLists.txt
@@ -3,8 +3,3 @@ set(SOURCES AddonCallbacksCodec.cpp)
 set(HEADERS AddonCallbacksCodec.h)
 
 core_add_library(api1AddonCallbacks_Codec)
-add_dependencies(api1AddonCallbacks_Codec libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(api1AddonCallbacks_Codec ffmpeg)
-endif()
diff --git a/xbmc/addons/binary/interfaces/api1/GUI/CMakeLists.txt b/xbmc/addons/binary/interfaces/api1/GUI/CMakeLists.txt
index 877c6bc..d3c0868 100644
--- a/xbmc/addons/binary/interfaces/api1/GUI/CMakeLists.txt
+++ b/xbmc/addons/binary/interfaces/api1/GUI/CMakeLists.txt
@@ -7,8 +7,3 @@ set(HEADERS AddonCallbacksGUI.h
             AddonGUIWindow.h)
 
 core_add_library(api1AddonCallbacks_GUI)
-add_dependencies(api1AddonCallbacks_GUI libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(api1AddonCallbacks_GUI ffmpeg)
-endif()
diff --git a/xbmc/addons/binary/interfaces/api1/InputStream/CMakeLists.txt b/xbmc/addons/binary/interfaces/api1/InputStream/CMakeLists.txt
index 2e572ff..b3e51a3 100644
--- a/xbmc/addons/binary/interfaces/api1/InputStream/CMakeLists.txt
+++ b/xbmc/addons/binary/interfaces/api1/InputStream/CMakeLists.txt
@@ -3,8 +3,3 @@ set(SOURCES AddonCallbacksInputStream.cpp)
 set(HEADERS AddonCallbacksInputStream.h)
 
 core_add_library(api1AddonCallbacks_InputStream)
-add_dependencies(api1AddonCallbacks_InputStream libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(api1AddonCallbacks_InputStream ffmpeg)
-endif()
diff --git a/xbmc/addons/binary/interfaces/api1/PVR/AddonCallbacksPVR.cpp b/xbmc/addons/binary/interfaces/api1/PVR/AddonCallbacksPVR.cpp
index e8ca3da..3d35cfe 100644
--- a/xbmc/addons/binary/interfaces/api1/PVR/AddonCallbacksPVR.cpp
+++ b/xbmc/addons/binary/interfaces/api1/PVR/AddonCallbacksPVR.cpp
@@ -223,7 +223,7 @@ void CAddonCallbacksPVR::PVRTransferTimerEntry(void *addonData, const ADDON_HAND
     return;
   }
 
-  /* Note: channel can be NULL here, for instance for epg-based repeating timers ("record on any channel" condition). */
+  /* Note: channel can be NULL here, for instance for epg-based timer rules ("record on any channel" condition). */
   CPVRChannelPtr channel = g_PVRChannelGroups->GetByUniqueID(timer->iClientChannelUid, client->GetID());
 
   /* transfer this entry to the timers container */
diff --git a/xbmc/addons/binary/interfaces/api1/PVR/CMakeLists.txt b/xbmc/addons/binary/interfaces/api1/PVR/CMakeLists.txt
index 1751696..dfcac82 100644
--- a/xbmc/addons/binary/interfaces/api1/PVR/CMakeLists.txt
+++ b/xbmc/addons/binary/interfaces/api1/PVR/CMakeLists.txt
@@ -3,8 +3,3 @@ set(SOURCES AddonCallbacksPVR.cpp)
 set(HEADERS AddonCallbacksPVR.h)
 
 core_add_library(api1AddonCallbacks_PVR)
-add_dependencies(api1AddonCallbacks_PVR libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(api1AddonCallbacks_PVR ffmpeg)
-endif()
diff --git a/xbmc/addons/binary/interfaces/api1/Peripheral/CMakeLists.txt b/xbmc/addons/binary/interfaces/api1/Peripheral/CMakeLists.txt
index 1f08b2f..086519b 100644
--- a/xbmc/addons/binary/interfaces/api1/Peripheral/CMakeLists.txt
+++ b/xbmc/addons/binary/interfaces/api1/Peripheral/CMakeLists.txt
@@ -3,8 +3,3 @@ set(SOURCES AddonCallbacksPeripheral.cpp)
 set(HEADERS AddonCallbacksPeripheral.h)
 
 core_add_library(api1AddonCallbacks_Peripheral)
-add_dependencies(api1AddonCallbacks_Peripheral libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(api1AddonCallbacks_Peripheral ffmpeg)
-endif()
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_adsp.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_adsp.h
index 46e34a6..fb0c15f 100644
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_adsp.h
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_adsp.h
@@ -29,12 +29,8 @@
 
 typedef void* ADSPHANDLE;
 
-#ifdef _WIN32
-#define ADSP_HELPER_DLL "\\library.kodi.adsp\\libKODI_adsp" ADDON_HELPER_EXT
-#else
-#define ADSP_HELPER_DLL_NAME "libKODI_adsp-" ADDON_HELPER_ARCH ADDON_HELPER_EXT
-#define ADSP_HELPER_DLL "/library.kodi.adsp/" ADSP_HELPER_DLL_NAME
-#endif
+#define ADSP_HELPER_DLL KODI_DLL("adsp")
+#define ADSP_HELPER_DLL_NAME KODI_DLL_NAME("adsp")
 
 class CAddonSoundPlay;
 
@@ -69,15 +65,6 @@ public:
     libBasePath  = ((cb_array*)m_Handle)->libPath;
     libBasePath += ADSP_HELPER_DLL;
 
-#if defined(ANDROID)
-      struct stat st;
-      if(stat(libBasePath.c_str(),&st) != 0)
-      {
-        std::string tempbin = getenv("XBMC_ANDROID_LIBS");
-        libBasePath = tempbin + "/" + ADSP_HELPER_DLL_NAME;
-      }
-#endif
-
     m_libKODI_adsp = dlopen(libBasePath.c_str(), RTLD_LAZY);
     if (m_libKODI_adsp == NULL)
     {
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_audioengine.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_audioengine.h
index be3b93d..cfe6f2e 100644
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_audioengine.h
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_audioengine.h
@@ -38,12 +38,8 @@
 
 #include "libXBMC_addon.h"
 
-#ifdef _WIN32
-#define AUDIOENGINE_HELPER_DLL "\\library.kodi.audioengine\\libKODI_audioengine" ADDON_HELPER_EXT
-#else
-#define AUDIOENGINE_HELPER_DLL_NAME "libKODI_audioengine-" ADDON_HELPER_ARCH ADDON_HELPER_EXT
-#define AUDIOENGINE_HELPER_DLL "/library.kodi.audioengine/" AUDIOENGINE_HELPER_DLL_NAME
-#endif
+#define AUDIOENGINE_HELPER_DLL KODI_DLL("audioengine")
+#define AUDIOENGINE_HELPER_DLL_NAME KODI_DLL_NAME("audioengine")
 
 class CAddonAEStream;
 
@@ -78,15 +74,6 @@ public:
     libBasePath  = ((cb_array*)m_Handle)->libPath;
     libBasePath += AUDIOENGINE_HELPER_DLL;
 
-#if defined(ANDROID)
-      struct stat st;
-      if(stat(libBasePath.c_str(),&st) != 0)
-      {
-        std::string tempbin = getenv("XBMC_ANDROID_LIBS");
-        libBasePath = tempbin + "/" + AUDIOENGINE_HELPER_DLL;
-      }
-#endif
-
     m_libKODI_audioengine = dlopen(libBasePath.c_str(), RTLD_LAZY);
     if (m_libKODI_audioengine == NULL)
     {
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_guilib.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_guilib.h
index bdaeb4c..3fe12c9 100644
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_guilib.h
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_guilib.h
@@ -28,12 +28,8 @@
 
 typedef void* GUIHANDLE;
 
-#ifdef _WIN32
-#define GUI_HELPER_DLL "\\library.kodi.guilib\\libKODI_guilib" ADDON_HELPER_EXT
-#else
-#define GUI_HELPER_DLL_NAME "libKODI_guilib-" ADDON_HELPER_ARCH ADDON_HELPER_EXT
-#define GUI_HELPER_DLL "/library.kodi.guilib/" GUI_HELPER_DLL_NAME
-#endif
+#define GUI_HELPER_DLL KODI_DLL("guilib")
+#define GUI_HELPER_DLL_NAME KODI_DLL_NAME("guilib")
 
 /* current ADDONGUI API version */
 #define KODI_GUILIB_API_VERSION "5.11.0"
@@ -80,15 +76,6 @@ public:
     libBasePath  = ((cb_array*)m_Handle)->libPath;
     libBasePath += GUI_HELPER_DLL;
 
-#if defined(ANDROID)
-      struct stat st;
-      if(stat(libBasePath.c_str(),&st) != 0)
-      {
-        std::string tempbin = getenv("XBMC_ANDROID_LIBS");
-        libBasePath = tempbin + "/" + GUI_HELPER_DLL_NAME;
-      }
-#endif
-
     m_libKODI_guilib = dlopen(libBasePath.c_str(), RTLD_LAZY);
     if (m_libKODI_guilib == NULL)
     {
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_inputstream.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_inputstream.h
index 7fe1725..a6e83cb 100644
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_inputstream.h
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_inputstream.h
@@ -33,12 +33,8 @@
 #include "cores/VideoPlayer/DVDDemuxers/DVDDemuxPacket.h"
 #endif
 
-#ifdef _WIN32
-#define INPUTSTREAM_HELPER_DLL "\\library.kodi.inputstream\\libKODI_inputstream" ADDON_HELPER_EXT
-#else
-#define INPUTSTREAM_HELPER_DLL_NAME "libKODI_inputstream-" ADDON_HELPER_ARCH ADDON_HELPER_EXT
-#define INPUTSTREAM_HELPER_DLL "/library.kodi.inputstream/" INPUTSTREAM_HELPER_DLL_NAME
-#endif
+#define INPUTSTREAM_HELPER_DLL KODI_DLL("inputstream")
+#define INPUTSTREAM_HELPER_DLL_NAME KODI_DLL_NAME("inputstream")
 
 /* current input stream API version */
 #define KODI_INPUTSTREAM_API_VERSION "1.0.0"
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_addon.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_addon.h
index ddeb1db..70bd19b 100644
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_addon.h
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_addon.h
@@ -34,6 +34,7 @@
 #endif
 
 struct VFSDirEntry;
+struct __stat64;
 
 #ifdef _WIN32                   // windows
 #ifndef _SSIZE_T_DEFINED
@@ -47,9 +48,14 @@ typedef intptr_t      ssize_t;
 #include "dlfcn-win32.h"
 #endif
 
-#define ADDON_DLL               "\\library.xbmc.addon\\libXBMC_addon" ADDON_HELPER_EXT
 #define ADDON_HELPER_EXT        ".dll"
+#define ADDON_HELPER_PATHSEP    "\\"
+#define ADDON_HELPER_ARCHSEP    ""
+#define ADDON_HELPER_ARCH       ""
+
 #else // windows
+#define ADDON_HELPER_PATHSEP    "/"
+#define ADDON_HELPER_ARCHSEP    "-"
 // the ADDON_HELPER_ARCH is the platform dependend name which is used
 // as part of the name of dynamic addon libraries. It has to match the 
 // strings which are set in configure.ac for the "ARCH" variable.
@@ -79,14 +85,20 @@ typedef intptr_t      ssize_t;
 #define ADDON_HELPER_EXT        ".so"
 #endif
 #include <dlfcn.h>              // linux+osx
-#define ADDON_DLL_NAME "libXBMC_addon-" ADDON_HELPER_ARCH ADDON_HELPER_EXT
-#define ADDON_DLL "/library.xbmc.addon/" ADDON_DLL_NAME
 #endif
+
+#define KODI_DLL_NAME(name) "libKODI_" name ADDON_HELPER_ARCHSEP ADDON_HELPER_ARCH ADDON_HELPER_EXT
+#define XBMC_DLL_NAME(name) "libXBMC_" name ADDON_HELPER_ARCHSEP ADDON_HELPER_ARCH ADDON_HELPER_EXT
 #if defined(ANDROID)
-#include <sys/stat.h>
+#define KODI_DLL(name) ADDON_HELPER_PATHSEP KODI_DLL_NAME(name)
+#define XBMC_DLL(name) ADDON_HELPER_PATHSEP XBMC_DLL_NAME(name)
+#else
+#define KODI_DLL(name) ADDON_HELPER_PATHSEP "library.kodi." name ADDON_HELPER_PATHSEP KODI_DLL_NAME(name)
+#define XBMC_DLL(name) ADDON_HELPER_PATHSEP "library.xbmc." name ADDON_HELPER_PATHSEP XBMC_DLL_NAME(name)
 #endif
 
-struct __stat64;
+#define ADDON_DLL_NAME XBMC_DLL_NAME("addon")
+#define ADDON_DLL XBMC_DLL("addon")
 
 #ifdef LOG_DEBUG
 #undef LOG_DEBUG
@@ -147,15 +159,6 @@ namespace ADDON
       libBasePath  = ((cb_array*)m_Handle)->libPath;
       libBasePath += ADDON_DLL;
 
-#if defined(ANDROID)
-      struct stat st;
-      if(stat(libBasePath.c_str(),&st) != 0)
-      {
-        std::string tempbin = getenv("XBMC_ANDROID_LIBS");
-        libBasePath = tempbin + "/" + ADDON_DLL_NAME;
-      }
-#endif
-
       m_libXBMC_addon = dlopen(libBasePath.c_str(), RTLD_LAZY);
       if (m_libXBMC_addon == NULL)
       {
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_codec.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_codec.h
index 3853f08..0e64b11 100644
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_codec.h
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_codec.h
@@ -27,12 +27,8 @@
 #include "xbmc_codec_types.h"
 #include "libXBMC_addon.h"
 
-#ifdef _WIN32
-#define CODEC_HELPER_DLL "\\library.xbmc.codec\\libXBMC_codec" ADDON_HELPER_EXT
-#else
-#define CODEC_HELPER_DLL_NAME "libXBMC_codec-" ADDON_HELPER_ARCH ADDON_HELPER_EXT
-#define CODEC_HELPER_DLL "/library.xbmc.codec/" CODEC_HELPER_DLL_NAME
-#endif
+#define CODEC_HELPER_DLL_NAME XBMC_DLL_NAME("codec")
+#define CODEC_HELPER_DLL XBMC_DLL("codec")
 
 class CHelper_libXBMC_codec
 {
@@ -65,15 +61,6 @@ public:
     libBasePath  = ((cb_array*)m_Handle)->libPath;
     libBasePath += CODEC_HELPER_DLL;
 
-#if defined(ANDROID)
-      struct stat st;
-      if(stat(libBasePath.c_str(),&st) != 0)
-      {
-        std::string tempbin = getenv("XBMC_ANDROID_LIBS");
-        libBasePath = tempbin + "/" + CODEC_HELPER_DLL_NAME;
-      }
-#endif
-
     m_libXBMC_codec = dlopen(libBasePath.c_str(), RTLD_LAZY);
     if (m_libXBMC_codec == NULL)
     {
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_pvr.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_pvr.h
index 516bb86..a769328 100644
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_pvr.h
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libXBMC_pvr.h
@@ -27,12 +27,8 @@
 #include "xbmc_pvr_types.h"
 #include "libXBMC_addon.h"
 
-#ifdef _WIN32
-#define PVR_HELPER_DLL "\\library.xbmc.pvr\\libXBMC_pvr" ADDON_HELPER_EXT
-#else
-#define PVR_HELPER_DLL_NAME "libXBMC_pvr-" ADDON_HELPER_ARCH ADDON_HELPER_EXT
-#define PVR_HELPER_DLL "/library.xbmc.pvr/" PVR_HELPER_DLL_NAME
-#endif
+#define PVR_HELPER_DLL_NAME XBMC_DLL_NAME("pvr")
+#define PVR_HELPER_DLL XBMC_DLL("pvr")
 
 #define DVD_TIME_BASE 1000000
 
@@ -70,15 +66,6 @@ public:
     libBasePath  = ((cb_array*)m_Handle)->libPath;
     libBasePath += PVR_HELPER_DLL;
 
-#if defined(ANDROID)
-      struct stat st;
-      if(stat(libBasePath.c_str(),&st) != 0)
-      {
-        std::string tempbin = getenv("XBMC_ANDROID_LIBS");
-        libBasePath = tempbin + "/" + PVR_HELPER_DLL_NAME;
-      }
-#endif
-
     m_libXBMC_pvr = dlopen(libBasePath.c_str(), RTLD_LAZY);
     if (m_libXBMC_pvr == NULL)
     {
diff --git a/xbmc/addons/test/TestAddonFactory.cpp b/xbmc/addons/test/TestAddonFactory.cpp
index a97d1bf..c585395 100644
--- a/xbmc/addons/test/TestAddonFactory.cpp
+++ b/xbmc/addons/test/TestAddonFactory.cpp
@@ -116,9 +116,42 @@ TEST_F(TestAddonFactory, ShouldAcceptUnversionedDependencies)
 
 TEST_F(TestAddonFactory, IconPathShouldBeBuiltFromPluginPath)
 {
-  plugin.plugin_path = strdup("a/b");;
+  plugin.plugin_path = strdup("a/b");
   auto addon = CAddonMgr::Factory(&plugin, ADDON_UNKNOWN);
   EXPECT_EQ("a/b", addon->Path());
   EXPECT_EQ("a/b/icon.png", addon->Icon());
   free(plugin.plugin_path);
 }
+
+
+TEST_F(TestAddonFactory, AssetsElementShouldOverrideImplicitArt)
+{
+  cp_cfg_element_t icon{0};
+  icon.name = (char*)"icon";
+  icon.value = (char*)"foo/bar.jpg";
+
+  cp_cfg_element_t assets{0};
+  assets.name = (char*)"assets";
+  assets.num_children = 1;
+  assets.children = &icon;
+
+  cp_cfg_element_t root{0};
+  root.name = (char*)"kodi.addon.metadata";
+  root.num_children = 1;
+  root.children = &assets;
+  assets.parent = &root;
+  icon.parent = &assets;
+
+  cp_extension_t metadata = {&plugin, (char*)"kodi.addon.metadata", nullptr, nullptr, nullptr, &root};
+
+  cp_extension_t extensions[1] = {metadata};
+  plugin.extensions = extensions;
+  plugin.num_extensions = 1;
+  plugin.plugin_path = strdup("a/b");
+
+  auto addon = CAddonMgr::Factory(&plugin, ADDON_UNKNOWN);
+  EXPECT_EQ("a/b", addon->Path());
+  EXPECT_EQ("a/b/foo/bar.jpg", addon->Icon());
+  EXPECT_EQ("", addon->FanArt());
+  free(plugin.plugin_path);
+}
diff --git a/xbmc/cdrip/CMakeLists.txt b/xbmc/cdrip/CMakeLists.txt
index 8cc327b..ef2034a 100644
--- a/xbmc/cdrip/CMakeLists.txt
+++ b/xbmc/cdrip/CMakeLists.txt
@@ -10,8 +10,3 @@ set(HEADERS CDDARipJob.h
             IEncoder.h)
 
 core_add_library(cdrip)
-add_dependencies(cdrip libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(cdrip ffmpeg)
-endif()
diff --git a/xbmc/contrib/kissfft/CMakeLists.txt b/xbmc/contrib/kissfft/CMakeLists.txt
index 35919a3..1a67376 100644
--- a/xbmc/contrib/kissfft/CMakeLists.txt
+++ b/xbmc/contrib/kissfft/CMakeLists.txt
@@ -5,8 +5,4 @@ set(HEADERS _kiss_fft_guts.h
             kiss_fft.h
             kiss_fftr.h)
 
-if(CORE_SYSTEM_NAME STREQUAL windows)
-  set_source_files_properties(${SOURCES} PROPERTIES LANGUAGE CXX)
-endif()
-
 core_add_library(kissfft)
diff --git a/xbmc/cores/AudioEngine/CMakeLists.txt b/xbmc/cores/AudioEngine/CMakeLists.txt
index 41190ad..b50fc4d 100644
--- a/xbmc/cores/AudioEngine/CMakeLists.txt
+++ b/xbmc/cores/AudioEngine/CMakeLists.txt
@@ -124,11 +124,10 @@ if(CORE_SYSTEM_NAME STREQUAL android)
   list(APPEND HEADERS Sinks/AESinkAUDIOTRACK.h)
 endif()
 
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+if(CORE_SYSTEM_NAME STREQUAL freebsd)
+  list(APPEND SOURCES Sinks/AESinkOSS.cpp)
+  list(APPEND HEADERS Sinks/AESinkOSS.h)
+endif()
 
 core_add_library(audioengine)
-add_dependencies(audioengine libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(audioengine ffmpeg)
-endif()
+target_include_directories(${CORE_LIBRARY} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp
index 0cef1c5..c6a7f56 100644
--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp
+++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp
@@ -180,15 +180,18 @@ bool CActiveAEResampleFFMPEG::Init(uint64_t dst_chan_layout, int dst_channels, i
 
 int CActiveAEResampleFFMPEG::Resample(uint8_t **dst_buffer, int dst_samples, uint8_t **src_buffer, int src_samples, double ratio)
 {
+  int delta = 0;
+  int distance = 0;
   if (ratio != 1.0)
   {
-    if (swr_set_compensation(m_pContext,
-                             (dst_samples*ratio-dst_samples)*m_dst_rate/m_src_rate,
-                             dst_samples*m_dst_rate/m_src_rate) < 0)
-    {
-      CLog::Log(LOGERROR, "CActiveAEResampleFFMPEG::Resample - set compensation failed");
-      return -1;
-    }
+    delta = (dst_samples*ratio-dst_samples)*m_dst_rate/m_src_rate;
+    distance = dst_samples*m_dst_rate/m_src_rate;
+  }
+
+  if (swr_set_compensation(m_pContext, delta, distance) < 0)
+  {
+    CLog::Log(LOGERROR, "CActiveAEResampleFFMPEG::Resample - set compensation failed");
+    return -1;
   }
 
   int ret = swr_convert(m_pContext, dst_buffer, dst_samples, (const uint8_t**)src_buffer, src_samples);
diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp
index 53e6554..639901c 100644
--- a/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp
+++ b/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp
@@ -48,7 +48,7 @@ using namespace jni;
 // is the max TrueHD package
 const unsigned int MAX_RAW_AUDIO_BUFFER_HD = 61440;
 const unsigned int MAX_RAW_AUDIO_BUFFER = 16384;
-const unsigned int MOVING_AVERAGE_MAX_MEMBERS = 20;
+const unsigned int MOVING_AVERAGE_MAX_MEMBERS = 5;
 
 /*
  * ADT-1 on L preview as of 2014-10 downmixes all non-5.1/7.1 content
diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp
index 6edde86..182e4a5 100644
--- a/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp
+++ b/xbmc/cores/AudioEngine/Sinks/AESinkPULSE.cpp
@@ -267,6 +267,7 @@ struct SinkInfoStruct
   bool device_found;
   pa_threaded_mainloop *mainloop;
   int samplerate;
+  pa_channel_map map;
   SinkInfoStruct()
   {
     list = NULL;
@@ -274,6 +275,7 @@ struct SinkInfoStruct
     device_found = true;
     mainloop = NULL;
     samplerate = 0;
+    pa_channel_map_init(&map);
   }
 };
 
@@ -290,6 +292,7 @@ static void SinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, void
 
     sinkStruct->samplerate = i->sample_spec.rate;
     sinkStruct->device_found = true;
+    sinkStruct->map = i->channel_map;
   }
   pa_threaded_mainloop_signal(sinkStruct->mainloop, 0);
 }
@@ -628,13 +631,7 @@ bool CAESinkPULSE::Initialize(AEAudioFormat &format, std::string &device)
   }
 
   pa_sample_spec spec;
-  #if PA_CHECK_VERSION(2,0,0)
-    pa_format_info_to_sample_spec(info[0], &spec, NULL);
-  #else
-    spec.rate = (info[0]->encoding == PA_ENCODING_EAC3_IEC61937) ? 4 * samplerate : samplerate;
-    spec.format = pa_fmt;
-    spec.channels = m_Channels;
-  #endif
+  pa_format_info_to_sample_spec(info[0], &spec, NULL);
   if (!pa_sample_spec_valid(&spec))
   {
     CLog::Log(LOGERROR, "PulseAudio: Invalid sample spec");
@@ -681,8 +678,18 @@ bool CAESinkPULSE::Initialize(AEAudioFormat &format, std::string &device)
   buffer_attr.minreq = process_time;
   buffer_attr.prebuf = (uint32_t) -1;
   buffer_attr.tlength = latency;
+  int flags = (PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_ADJUST_LATENCY);
+
+  // by default PA will upmix / remix everything when multi channel layout is configured
+  // if we have enough channels in the target layout ask PA not to remix to related channels
+  // 1:1 remapping is allowed though
+  if (!m_passthrough && m_Channels <= sinkStruct.map.channels)
+    flags |= PA_STREAM_NO_REMIX_CHANNELS;
+
+  if (m_passthrough)
+    flags |= PA_STREAM_PASSTHROUGH;
 
-  if (pa_stream_connect_playback(m_Stream, isDefaultDevice ? NULL : device.c_str(), &buffer_attr, ((pa_stream_flags)(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_ADJUST_LATENCY)), NULL, NULL) < 0)
+  if (pa_stream_connect_playback(m_Stream, isDefaultDevice ? NULL : device.c_str(), &buffer_attr, (pa_stream_flags) flags, NULL, NULL) < 0)
   {
     CLog::Log(LOGERROR, "PulseAudio: Failed to connect stream to output");
     pa_threaded_mainloop_unlock(m_MainLoop);
diff --git a/xbmc/cores/CMakeLists.txt b/xbmc/cores/CMakeLists.txt
index edf46c5..52631bb 100644
--- a/xbmc/cores/CMakeLists.txt
+++ b/xbmc/cores/CMakeLists.txt
@@ -7,7 +7,3 @@ set(HEADERS DataCacheCore.h
             IPlayerCallback.h)
 
 core_add_library(cores)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(cores ffmpeg)
-endif()
diff --git a/xbmc/cores/DataCacheCore.cpp b/xbmc/cores/DataCacheCore.cpp
index 68cf2fb..43a24f1 100644
--- a/xbmc/cores/DataCacheCore.cpp
+++ b/xbmc/cores/DataCacheCore.cpp
@@ -19,6 +19,18 @@
 */
 
 #include "cores/DataCacheCore.h"
+#include "threads/SingleLock.h"
+#include "ServiceBroker.h"
+
+CDataCacheCore::CDataCacheCore()
+{
+  m_hasAVInfoChanges = false;
+}
+
+CDataCacheCore& GetInstance()
+{
+  return CServiceBroker::GetDataCacheCore();
+}
 
 bool CDataCacheCore::HasAVInfoChanges()
 {
@@ -35,4 +47,162 @@ void CDataCacheCore::SignalVideoInfoChange()
 void CDataCacheCore::SignalAudioInfoChange()
 {
   m_hasAVInfoChanges = true;
-}
\ No newline at end of file
+}
+
+void CDataCacheCore::SetVideoDecoderName(std::string name, bool isHw)
+{
+  CSingleLock lock(m_videoPlayerSection);
+
+  m_playerVideoInfo.decoderName = name;
+  m_playerVideoInfo.isHwDecoder = isHw;
+}
+
+std::string CDataCacheCore::GetVideoDecoderName()
+{
+  CSingleLock lock(m_videoPlayerSection);
+
+  return m_playerVideoInfo.decoderName;
+}
+
+bool CDataCacheCore::IsVideoHwDecoder()
+{
+  CSingleLock lock(m_videoPlayerSection);
+
+  return m_playerVideoInfo.isHwDecoder;
+}
+
+
+void CDataCacheCore::SetVideoDeintMethod(std::string method)
+{
+  CSingleLock lock(m_videoPlayerSection);
+
+  m_playerVideoInfo.deintMethod = method;
+}
+
+std::string CDataCacheCore::GetVideoDeintMethod()
+{
+  CSingleLock lock(m_videoPlayerSection);
+
+  return m_playerVideoInfo.deintMethod;
+}
+
+void CDataCacheCore::SetVideoPixelFormat(std::string pixFormat)
+{
+  CSingleLock lock(m_videoPlayerSection);
+
+  m_playerVideoInfo.pixFormat = pixFormat;
+}
+
+std::string CDataCacheCore::GetVideoPixelFormat()
+{
+  CSingleLock lock(m_videoPlayerSection);
+
+  return m_playerVideoInfo.pixFormat;
+}
+
+void CDataCacheCore::SetVideoDimensions(int width, int height)
+{
+  CSingleLock lock(m_videoPlayerSection);
+
+  m_playerVideoInfo.width = width;
+  m_playerVideoInfo.height = height;
+}
+
+int CDataCacheCore::GetVideoWidth()
+{
+  CSingleLock lock(m_videoPlayerSection);
+
+  return m_playerVideoInfo.width;
+}
+
+int CDataCacheCore::GetVideoHeight()
+{
+  CSingleLock lock(m_videoPlayerSection);
+
+  return m_playerVideoInfo.height;
+}
+
+void CDataCacheCore::SetVideoFps(float fps)
+{
+  CSingleLock lock(m_videoPlayerSection);
+
+  m_playerVideoInfo.fps = fps;
+}
+
+float CDataCacheCore::GetVideoFps()
+{
+  CSingleLock lock(m_videoPlayerSection);
+
+  return m_playerVideoInfo.fps;
+}
+
+void CDataCacheCore::SetVideoDAR(float dar)
+{
+  CSingleLock lock(m_videoPlayerSection);
+
+  m_playerVideoInfo.dar = dar;
+}
+
+float CDataCacheCore::GetVideoDAR()
+{
+  CSingleLock lock(m_videoPlayerSection);
+
+  return m_playerVideoInfo.dar;
+}
+
+// player audio info
+void CDataCacheCore::SetAudioDecoderName(std::string name)
+{
+  CSingleLock lock(m_audioPlayerSection);
+
+  m_playerAudioInfo.decoderName = name;
+}
+
+std::string CDataCacheCore::GetAudioDecoderName()
+{
+  CSingleLock lock(m_audioPlayerSection);
+
+  return m_playerAudioInfo.decoderName;
+}
+
+void CDataCacheCore::SetAudioChannels(std::string channels)
+{
+  CSingleLock lock(m_audioPlayerSection);
+
+  m_playerAudioInfo.channels = channels;
+}
+
+std::string CDataCacheCore::GetAudioChannels()
+{
+  CSingleLock lock(m_audioPlayerSection);
+
+  return m_playerAudioInfo.channels;
+}
+
+void CDataCacheCore::SetAudioSampleRate(int sampleRate)
+{
+  CSingleLock lock(m_audioPlayerSection);
+
+  m_playerAudioInfo.sampleRate = sampleRate;
+}
+
+int CDataCacheCore::GetAudioSampleRate()
+{
+  CSingleLock lock(m_audioPlayerSection);
+
+  return m_playerAudioInfo.sampleRate;
+}
+
+void CDataCacheCore::SetAudioBitsPerSample(int bitsPerSample)
+{
+  CSingleLock lock(m_audioPlayerSection);
+
+  m_playerAudioInfo.bitsPerSample = bitsPerSample;
+}
+
+int CDataCacheCore::GetAudioBitsPerSampe()
+{
+  CSingleLock lock(m_audioPlayerSection);
+
+  return m_playerAudioInfo.bitsPerSample;
+}
diff --git a/xbmc/cores/DataCacheCore.h b/xbmc/cores/DataCacheCore.h
index 0df013d..646f512 100644
--- a/xbmc/cores/DataCacheCore.h
+++ b/xbmc/cores/DataCacheCore.h
@@ -20,15 +20,67 @@
 *
 */
 
+#include <atomic>
+#include <string>
+#include "threads/CriticalSection.h"
+
 class CDataCacheCore
 {
 public:
+  CDataCacheCore();
+  static CDataCacheCore& GetInstance();
   bool HasAVInfoChanges();
   void SignalVideoInfoChange();
   void SignalAudioInfoChange();
 
+  // player video info
+  void SetVideoDecoderName(std::string name, bool isHw);
+  std::string GetVideoDecoderName();
+  bool IsVideoHwDecoder();
+  void SetVideoDeintMethod(std::string method);
+  std::string GetVideoDeintMethod();
+  void SetVideoPixelFormat(std::string pixFormat);
+  std::string GetVideoPixelFormat();
+  void SetVideoDimensions(int width, int height);
+  int GetVideoWidth();
+  int GetVideoHeight();
+  void SetVideoFps(float fps);
+  float GetVideoFps();
+  void SetVideoDAR(float dar);
+  float GetVideoDAR();
+
+  // player audio info
+  void SetAudioDecoderName(std::string name);
+  std::string GetAudioDecoderName();
+  void SetAudioChannels(std::string channels);
+  std::string GetAudioChannels();
+  void SetAudioSampleRate(int sampleRate);
+  int GetAudioSampleRate();
+  void SetAudioBitsPerSample(int bitsPerSample);
+  int GetAudioBitsPerSampe();
+  
 protected:
-  volatile bool m_hasAVInfoChanges;
-};
+  std::atomic_bool m_hasAVInfoChanges;
+
+  CCriticalSection m_videoPlayerSection;
+  struct SPlayerVideoInfo
+  {
+    std::string decoderName;
+    bool isHwDecoder;
+    std::string deintMethod;
+    std::string pixFormat;
+    int width;
+    int height;
+    float fps;
+    float dar;
+  } m_playerVideoInfo;
 
-extern CDataCacheCore g_dataCacheCore;
\ No newline at end of file
+  CCriticalSection m_audioPlayerSection;
+  struct SPlayerAudioInfo
+  {
+    std::string decoderName;
+    std::string channels;
+    int sampleRate;
+    int bitsPerSample;
+  } m_playerAudioInfo;
+};
\ No newline at end of file
diff --git a/xbmc/cores/DllLoader/CMakeLists.txt b/xbmc/cores/DllLoader/CMakeLists.txt
index 53b8b81..10fa1c4 100644
--- a/xbmc/cores/DllLoader/CMakeLists.txt
+++ b/xbmc/cores/DllLoader/CMakeLists.txt
@@ -21,11 +21,13 @@ set(HEADERS coff.h
 
 if(NOT CORE_SYSTEM_NAME STREQUAL windows)
   list(APPEND SOURCES mmap_anon.c
-                      ldt_keeper.c
                       SoLoader.cpp)
   list(APPEND HEADERS mmap_anon.h
-                      ldt_keeper.h
                       SoLoader.h)
+  if(NOT CORE_SYSTEM_NAME STREQUAL freebsd)
+    list(APPEND SOURCES ldt_keeper.c) 
+    list(APPEND HEADERS ldt_keeper.h)
+  endif()
 else()
   list(APPEND SOURCES Win32DllLoader.cpp)
   list(APPEND HEADERS Win32DllLoader.h)
diff --git a/xbmc/cores/DllLoader/DllLoaderContainer.cpp b/xbmc/cores/DllLoader/DllLoaderContainer.cpp
index 9d4d341..2d11a70 100644
--- a/xbmc/cores/DllLoader/DllLoaderContainer.cpp
+++ b/xbmc/cores/DllLoader/DllLoaderContainer.cpp
@@ -33,7 +33,17 @@
 #include "utils/log.h"
 #include "URL.h"
 
-#define ENV_PARTIAL_PATH "special://xbmcbin/system/;" \
+#if defined(TARGET_WINDOWS)
+#define ENV_PARTIAL_PATH \
+                 "special://xbmcbin/;" \
+                 "special://xbmcbin/system/;" \
+                 "special://xbmcbin/system/python/;" \
+                 "special://xbmc/;" \
+                 "special://xbmc/system/;" \
+                 "special://xbmc/system/python/"
+#else
+#define ENV_PARTIAL_PATH \
+                 "special://xbmcbin/system/;" \
                  "special://xbmcbin/system/players/mplayer/;" \
                  "special://xbmcbin/system/players/VideoPlayer/;" \
                  "special://xbmcbin/system/players/paplayer/;" \
@@ -43,7 +53,7 @@
                  "special://xbmc/system/players/VideoPlayer/;" \
                  "special://xbmc/system/players/paplayer/;" \
                  "special://xbmc/system/python/"
-
+#endif
 #if defined(TARGET_DARWIN)
 #define ENV_PATH ENV_PARTIAL_PATH \
                  ";special://frameworks/"
diff --git a/xbmc/cores/DllLoader/exports/CMakeLists.txt b/xbmc/cores/DllLoader/exports/CMakeLists.txt
index 71b470a..c0cec95 100644
--- a/xbmc/cores/DllLoader/exports/CMakeLists.txt
+++ b/xbmc/cores/DllLoader/exports/CMakeLists.txt
@@ -11,6 +11,8 @@ core_add_library(dllexports)
 if(APPLE)
   add_library(wrapper OBJECT wrapper.c)
   add_custom_target(wrapper.def ALL ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/wrapper_mach_alias wrapper.def)
+  set_target_properties(wrapper PROPERTIES FOLDER "Build Utilities")
+  set_target_properties(wrapper.def PROPERTIES FOLDER "Build Utilities")
   add_dependencies(wrapper.def wrapper)
 elseif(NOT CORE_SYSTEM_NAME STREQUAL windows)
   add_options(C ALL_BUILDS "-fPIC")
@@ -23,5 +25,8 @@ elseif(NOT CORE_SYSTEM_NAME STREQUAL windows)
     add_dependencies(wrapper.def ${APP_NAME_LC})
   endif()
 
+  set_target_properties(wrapper PROPERTIES FOLDER "Build Utilities")
+  set_target_properties(wrapper.def PROPERTIES FOLDER "Build Utilities")
   add_dependencies(wrapper.def wrapper)
 endif()
+
diff --git a/xbmc/cores/DllLoader/exports/emu_msvcrt.h b/xbmc/cores/DllLoader/exports/emu_msvcrt.h
index 9dae89d..3294d9a 100644
--- a/xbmc/cores/DllLoader/exports/emu_msvcrt.h
+++ b/xbmc/cores/DllLoader/exports/emu_msvcrt.h
@@ -32,7 +32,7 @@ typedef fpos_t fpos64_t;
 #endif
 
 #ifdef TARGET_WINDOWS
-#include "win32/dirent.h"
+#include "platform/win32/dirent.h"
 #else
 #include <dirent.h>
 #endif
diff --git a/xbmc/cores/ExternalPlayer/CMakeLists.txt b/xbmc/cores/ExternalPlayer/CMakeLists.txt
index e1ab835..69c71d9 100644
--- a/xbmc/cores/ExternalPlayer/CMakeLists.txt
+++ b/xbmc/cores/ExternalPlayer/CMakeLists.txt
@@ -3,8 +3,3 @@ set(SOURCES ExternalPlayer.cpp)
 set(HEADERS ExternalPlayer.h)
 
 core_add_library(externalplayer)
-add_dependencies(externalplayer libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(externalplayer ffmpeg)
-endif()
diff --git a/xbmc/cores/ExternalPlayer/ExternalPlayer.cpp b/xbmc/cores/ExternalPlayer/ExternalPlayer.cpp
index 2b85927..bebb4c0 100644
--- a/xbmc/cores/ExternalPlayer/ExternalPlayer.cpp
+++ b/xbmc/cores/ExternalPlayer/ExternalPlayer.cpp
@@ -498,11 +498,6 @@ void CExternalPlayer::Pause()
 {
 }
 
-bool CExternalPlayer::IsPaused() const
-{
-  return false;
-}
-
 bool CExternalPlayer::HasVideo() const
 {
   return true;
@@ -589,11 +584,16 @@ int64_t CExternalPlayer::GetTotalTime() // in milliseconds
   return (int64_t)m_totalTime * 1000;
 }
 
-void CExternalPlayer::ToFFRW(int iSpeed)
+void CExternalPlayer::SetSpeed(int iSpeed)
 {
   m_speed = iSpeed;
 }
 
+int CExternalPlayer::GetSpeed()
+{
+  return m_speed;
+}
+
 void CExternalPlayer::ShowOSD(bool bOnoff)
 {
 }
diff --git a/xbmc/cores/ExternalPlayer/ExternalPlayer.h b/xbmc/cores/ExternalPlayer/ExternalPlayer.h
index 453f4d6..29f97e7 100644
--- a/xbmc/cores/ExternalPlayer/ExternalPlayer.h
+++ b/xbmc/cores/ExternalPlayer/ExternalPlayer.h
@@ -38,8 +38,7 @@ public:
   virtual bool OpenFile(const CFileItem& file, const CPlayerOptions &options);
   virtual bool CloseFile(bool reopen = false);
   virtual bool IsPlaying() const;
-  virtual void Pause();
-  virtual bool IsPaused() const;
+  virtual void Pause() override;
   virtual bool HasVideo() const;
   virtual bool HasAudio() const;
   virtual void ToggleOSD() { }; // empty
@@ -68,9 +67,10 @@ public:
   virtual void SeekTime(int64_t iTime);
   virtual int64_t GetTime();
   virtual int64_t GetTotalTime();
-  virtual void ToFFRW(int iSpeed);
+  virtual void SetSpeed(int iSpeed) override;
+  virtual int GetSpeed() override;
   virtual void ShowOSD(bool bOnoff);
-  virtual void DoAudioWork()                                    {}
+  virtual void DoAudioWork() {};
   
   virtual std::string GetPlayerState();
   virtual bool SetPlayerState(const std::string& state);
diff --git a/xbmc/cores/IPlayer.h b/xbmc/cores/IPlayer.h
index 771355c..89c03dc 100644
--- a/xbmc/cores/IPlayer.h
+++ b/xbmc/cores/IPlayer.h
@@ -130,16 +130,9 @@ struct SPlayerVideoStreamInfo
   }
 };
 
-enum EDEINTERLACEMODE
-{
-  VS_DEINTERLACEMODE_OFF=0,
-  VS_DEINTERLACEMODE_AUTO=1,
-  VS_DEINTERLACEMODE_FORCE=2
-};
-
 enum EINTERLACEMETHOD
 {
-  VS_INTERLACEMETHOD_NONE=0, // Legacy
+  VS_INTERLACEMETHOD_NONE=0,
   VS_INTERLACEMETHOD_AUTO=1,
   VS_INTERLACEMETHOD_RENDER_BLEND=2,
 
@@ -244,7 +237,6 @@ public:
   virtual bool IsPlaying() const { return false;}
   virtual bool CanPause() { return true; };
   virtual void Pause() = 0;
-  virtual bool IsPaused() const = 0;
   virtual bool HasVideo() const = 0;
   virtual bool HasAudio() const = 0;
   virtual bool HasRDS() const { return false; }
@@ -257,7 +249,6 @@ public:
   virtual float GetCachePercentage(){ return 0;}
   virtual void SetMute(bool bOnOff){}
   virtual void SetVolume(float volume){}
-  virtual bool ControlsVolume(){ return false;}
   virtual void SetDynamicRangeCompression(long drc){}
   virtual bool CanRecord() { return false;};
   virtual bool IsRecording() { return false;};
@@ -334,7 +325,8 @@ public:
   virtual void SetTotalTime(int64_t time) { }
   virtual int GetSourceBitrate(){ return 0;}
   virtual bool GetStreamDetails(CStreamDetails &details){ return false;}
-  virtual void ToFFRW(int iSpeed = 0){};
+  virtual void SetSpeed(int iSpeed) = 0;
+  virtual int GetSpeed() = 0;
   // Skip to next track/item inside the current media (if supported).
   virtual bool SkipNext(){return false;}
 
@@ -408,7 +400,6 @@ public:
 
   virtual bool IsRenderingVideoLayer() { return false; };
 
-  virtual bool Supports(EDEINTERLACEMODE mode) { return false; };
   virtual bool Supports(EINTERLACEMETHOD method) { return false; };
   virtual bool Supports(ESCALINGMETHOD method) { return false; };
   virtual bool Supports(ERENDERFEATURE feature) { return false; };
diff --git a/xbmc/cores/VideoPlayer/CMakeLists.txt b/xbmc/cores/VideoPlayer/CMakeLists.txt
index c49644f..00d0232 100644
--- a/xbmc/cores/VideoPlayer/CMakeLists.txt
+++ b/xbmc/cores/VideoPlayer/CMakeLists.txt
@@ -35,12 +35,3 @@ set(HEADERS DVDAudio.h
             VideoPlayerVideo.h)
 
 core_add_library(VideoPlayer)
-add_dependencies(VideoPlayer libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(VideoPlayer ffmpeg)
-endif()
-
-if(NOT CORE_SYSTEM_NAME STREQUAL windows)
-  add_dependencies(VideoPlayer dvdnav)
-endif()
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/CMakeLists.txt b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/CMakeLists.txt
index f362a3e..6df8dde 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/CMakeLists.txt
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/CMakeLists.txt
@@ -6,7 +6,3 @@ set(HEADERS DVDAudioCodec.h
             DVDAudioCodecPassthrough.h)
 
 core_add_library(dvdaudiocodecs)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(dvdaudiocodecs ffmpeg)
-endif()
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodec.h
index 7e0da61..bb698da 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodec.h
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodec.h
@@ -23,6 +23,7 @@
 #include "system.h"
 #include "cores/AudioEngine/Utils/AEAudioFormat.h"
 #include "cores/AudioEngine/Utils/AEUtil.h"
+#include "cores/VideoPlayer/Process/ProcessInfo.h"
 #include "DVDClock.h"
 
 
@@ -64,7 +65,7 @@ class CDVDAudioCodec
 {
 public:
 
-  CDVDAudioCodec() {}
+  CDVDAudioCodec(CProcessInfo &processInfo) : m_processInfo(processInfo) {}
   virtual ~CDVDAudioCodec() {}
 
   /*
@@ -138,4 +139,7 @@ public:
    * should return the ffmpeg profile value
    */
   virtual int GetProfile() { return 0; }
+
+protected:
+  CProcessInfo &m_processInfo;
 };
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp
index a21894e..f5880cc 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp
@@ -35,7 +35,7 @@ extern "C" {
 #include "cores/AudioEngine/Utils/AEUtil.h"
 #endif
 
-CDVDAudioCodecFFmpeg::CDVDAudioCodecFFmpeg() : CDVDAudioCodec()
+CDVDAudioCodecFFmpeg::CDVDAudioCodecFFmpeg(CProcessInfo &processInfo) : CDVDAudioCodec(processInfo)
 {
   m_pCodecContext = NULL;
 
@@ -126,6 +126,7 @@ bool CDVDAudioCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options
   m_iSampleFormat = AV_SAMPLE_FMT_NONE;
   m_matrixEncoding = AV_MATRIX_ENCODING_NONE;
 
+  m_processInfo.SetAudioDecoderName(m_pCodecContext->codec->name);
   return true;
 }
 
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.h b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.h
index a15317a..d5760bb 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.h
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.h
@@ -29,10 +29,12 @@ extern "C" {
 #include "libswresample/swresample.h"
 }
 
+class CProcessInfo;
+
 class CDVDAudioCodecFFmpeg : public CDVDAudioCodec
 {
 public:
-  CDVDAudioCodecFFmpeg();
+  CDVDAudioCodecFFmpeg(CProcessInfo &processInfo);
   virtual ~CDVDAudioCodecFFmpeg();
   virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options);
   virtual void Dispose();
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.cpp
index 1fb00e1..8009297 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.cpp
@@ -29,7 +29,8 @@
 
 #define TRUEHD_BUF_SIZE 61440
 
-CDVDAudioCodecPassthrough::CDVDAudioCodecPassthrough(void) :
+CDVDAudioCodecPassthrough::CDVDAudioCodecPassthrough(CProcessInfo &processInfo) :
+  CDVDAudioCodec(processInfo),
   m_buffer(NULL),
   m_bufferSize(0),
   m_trueHDoffset(0)
@@ -51,22 +52,26 @@ bool CDVDAudioCodecPassthrough::Open(CDVDStreamInfo &hints, CDVDCodecOptions &op
     case AV_CODEC_ID_AC3:
       format.m_streamInfo.m_type = CAEStreamInfo::STREAM_TYPE_AC3;
       format.m_streamInfo.m_sampleRate = hints.samplerate;
+      m_processInfo.SetAudioDecoderName("PT_AC3");
       break;
 
     case AV_CODEC_ID_EAC3:
       format.m_streamInfo.m_type = CAEStreamInfo::STREAM_TYPE_EAC3;
       format.m_streamInfo.m_sampleRate = hints.samplerate;
+      m_processInfo.SetAudioDecoderName("PT_EAC3");
       break;
 
     case AV_CODEC_ID_DTS:
       format.m_streamInfo.m_type = CAEStreamInfo::STREAM_TYPE_DTSHD;
       format.m_streamInfo.m_sampleRate = hints.samplerate;
+      m_processInfo.SetAudioDecoderName("PT_DTSHD");
       break;
 
     case AV_CODEC_ID_TRUEHD:
       format.m_streamInfo.m_type = CAEStreamInfo::STREAM_TYPE_TRUEHD;
       format.m_streamInfo.m_sampleRate = hints.samplerate;
       m_trueHDBuffer.reset(new uint8_t[TRUEHD_BUF_SIZE]);
+      m_processInfo.SetAudioDecoderName("PT_TRUEHD");
       break;
 
     default:
@@ -83,6 +88,8 @@ bool CDVDAudioCodecPassthrough::Open(CDVDStreamInfo &hints, CDVDCodecOptions &op
 
     // only get the dts core from the parser if we don't support dtsHD
     m_parser.SetCoreOnly(true);
+
+    m_processInfo.SetAudioDecoderName("PT_DTS");
   }
 
   m_dataSize = 0;
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.h b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.h
index a04e736..4005429 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.h
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.h
@@ -29,10 +29,12 @@
 #include "cores/AudioEngine/Utils/AEStreamInfo.h"
 #include "cores/AudioEngine/Utils/AEBitstreamPacker.h"
 
+class CProcessInfo;
+
 class CDVDAudioCodecPassthrough : public CDVDAudioCodec
 {
 public:
-  CDVDAudioCodecPassthrough();
+  CDVDAudioCodecPassthrough(CProcessInfo &processInfo);
   virtual ~CDVDAudioCodecPassthrough();
 
   virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options);
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/CMakeLists.txt b/xbmc/cores/VideoPlayer/DVDCodecs/CMakeLists.txt
index 2420583..16f0141 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/CMakeLists.txt
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/CMakeLists.txt
@@ -6,7 +6,3 @@ set(HEADERS DVDCodecUtils.h
             DVDFactoryCodec.h)
 
 core_add_library(dvdcodecs)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(dvdcodecs ffmpeg)
-endif()
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.cpp
index bb5bfe0..9717412 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.cpp
@@ -173,7 +173,7 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, CProces
   return nullptr;;
 }
 
-CDVDAudioCodec* CDVDFactoryCodec::CreateAudioCodec(CDVDStreamInfo &hint, bool allowpassthrough, bool allowdtshddecode)
+CDVDAudioCodec* CDVDFactoryCodec::CreateAudioCodec(CDVDStreamInfo &hint, CProcessInfo &processInfo, bool allowpassthrough, bool allowdtshddecode)
 {
   CDVDAudioCodec* pCodec = NULL;
   CDVDCodecOptions options;
@@ -184,12 +184,12 @@ CDVDAudioCodec* CDVDFactoryCodec::CreateAudioCodec(CDVDStreamInfo &hint, bool al
   // we don't use passthrough if "sync playback to display" is enabled
   if (allowpassthrough)
   {
-    pCodec = OpenCodec(new CDVDAudioCodecPassthrough(), hint, options);
+    pCodec = OpenCodec(new CDVDAudioCodecPassthrough(processInfo), hint, options);
     if (pCodec)
       return pCodec;
   }
 
-  pCodec = OpenCodec(new CDVDAudioCodecFFmpeg(), hint, options);
+  pCodec = OpenCodec(new CDVDAudioCodecFFmpeg(processInfo), hint, options);
   if (pCodec)
     return pCodec;
 
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h
index 45e794b..d11c700 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h
@@ -41,7 +41,8 @@ public:
   static CDVDVideoCodec* CreateVideoCodec(CDVDStreamInfo &hint,
                                           CProcessInfo &processInfo,
                                           const CRenderInfo &info = CRenderInfo());
-  static CDVDAudioCodec* CreateAudioCodec(CDVDStreamInfo &hint, bool allowpassthrough = true, bool allowdtshddecode = true);
+  static CDVDAudioCodec* CreateAudioCodec(CDVDStreamInfo &hint, CProcessInfo &processInfo,
+                                          bool allowpassthrough = true, bool allowdtshddecode = true);
   static CDVDOverlayCodec* CreateOverlayCodec(CDVDStreamInfo &hint );
 
   static CDVDAudioCodec* OpenCodec(CDVDAudioCodec* pCodec, CDVDStreamInfo &hint, CDVDCodecOptions &options );
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/CMakeLists.txt b/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/CMakeLists.txt
index 4a68265..be7b9d1 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/CMakeLists.txt
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Overlay/CMakeLists.txt
@@ -19,12 +19,4 @@ set(HEADERS DVDOverlay.h
             contrib/cc_decoder.h
             contrib/cc_decoder708.h)
 
-if(CORE_SYSTEM_NAME STREQUAL "windows")
-  set_source_files_properties(${SOURCES} PROPERTIES LANGUAGE CXX)
-endif()
-
 core_add_library(dvdoverlaycodecs)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(dvdoverlaycodecs ffmpeg)
-endif()
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/CMakeLists.txt b/xbmc/cores/VideoPlayer/DVDCodecs/Video/CMakeLists.txt
index 491ee8a..7ee3bb6 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/CMakeLists.txt
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/CMakeLists.txt
@@ -64,7 +64,3 @@ if(CORE_SYSTEM_NAME STREQUAL android)
 endif()
 
 core_add_library(dvdvideocodecs)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(dvdvideocodecs ffmpeg)
-endif()
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp
index 021d5c4..6f9ee78 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp
@@ -22,8 +22,7 @@
 // http://developer.android.com/reference/android/media/MediaCodec.html
 //
 // Android MediaCodec class can be used to access low-level media codec,
-// i.e. encoder/decoder components. (android.media.MediaCodec). Requires
-// SDK16+ which is 4.1 Jellybean and above.
+// i.e. encoder/decoder components. (android.media.MediaCodec). Requires SDK21+
 //
 
 #include "DVDVideoCodecAndroidMediaCodec.h"
@@ -230,7 +229,7 @@ void CDVDMediaCodecInfo::ReleaseOutputBuffer(bool render)
   if (xbmc_jnienv()->ExceptionCheck())
   {
     CLog::Log(LOGERROR, "CDVDMediaCodecInfo::ReleaseOutputBuffer "
-      "ExceptionCheck render(%d)", render);
+      "ExceptionCheck index(%d), render(%d)", m_index, render);
     xbmc_jnienv()->ExceptionDescribe();
     xbmc_jnienv()->ExceptionClear();
   }
@@ -310,7 +309,7 @@ void CDVDMediaCodecInfo::RenderUpdate(const CRect &SrcRect, const CRect &DestRec
   {
     CXBMCApp::get()->setVideoViewSurfaceRect(DestRect.x1, DestRect.y1, DestRect.x2, DestRect.y2);
     cur_rect = DestRect;
-    
+
     // setVideoViewSurfaceRect is async, so skip rendering this frame
     ReleaseOutputBuffer(false);
   }
@@ -332,7 +331,7 @@ CDVDVideoCodecAndroidMediaCodec::CDVDVideoCodecAndroidMediaCodec(CProcessInfo &p
 , m_render_surface(surface_render)
 {
   memset(&m_videobuffer, 0x00, sizeof(DVDVideoPicture));
-  memset(&m_demux_pkt, 0, sizeof(m_demux_pkt));
+  memset(&m_demux_pkt, 0x00, sizeof(m_demux_pkt));
 }
 
 CDVDVideoCodecAndroidMediaCodec::~CDVDVideoCodecAndroidMediaCodec()
@@ -356,6 +355,7 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio
 
   m_render_surface = CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_USEMEDIACODECSURFACE);
   m_drop = false;
+  m_codecControlFlags = 0;
   m_hints = hints;
 
   switch(m_hints.codec)
@@ -491,9 +491,6 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio
       return false;
   }
 
-  if (m_render_surface)
-    m_formatname += "(S)";
-
   // CJNIMediaCodec::createDecoderByXXX doesn't handle errors nicely,
   // it crashes if the codec isn't found. This is fixed in latest AOSP,
   // but not in current 4.1 devices. So 1st search for a matching codec, then create it.
@@ -597,6 +594,11 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio
   m_opened = true;
   memset(&m_demux_pkt, 0, sizeof(m_demux_pkt));
 
+  m_processInfo.SetVideoDecoderName(m_formatname, true );
+  m_processInfo.SetVideoPixelFormat(m_render_surface ? "Surface" : (m_render_sw ? "YUV" : "EGL"));
+  m_processInfo.SetVideoDimensions(m_hints.width, m_hints.height);
+  m_processInfo.SetVideoDeintMethod("hardware");
+
   return m_opened;
 }
 
@@ -611,10 +613,7 @@ void CDVDVideoCodecAndroidMediaCodec::Dispose()
   if (m_demux_pkt.pData)
     free(m_demux_pkt.pData);
 
-  // invalidate any inflight outputbuffers, make sure
-  // m_output is empty so we do not create new ones
-  m_input.clear();
-  m_output.clear();
+  // invalidate any inflight outputbuffers
   FlushInternal();
 
   // clear m_videobuffer bits
@@ -646,21 +645,25 @@ void CDVDVideoCodecAndroidMediaCodec::Dispose()
 
 int CDVDVideoCodecAndroidMediaCodec::Decode(uint8_t *pData, int iSize, double dts, double pts)
 {
-  // Handle input, add demuxer packet to input queue, we must accept it or
-  // it will be discarded as VideoPlayerVideo has no concept of "try again".
-  // we must return VC_BUFFER or VC_PICTURE, default to VC_BUFFER.
-  int rtn = VC_BUFFER;
-
   if (!m_opened)
     return VC_ERROR;
 
   if (m_hints.ptsinvalid)
     pts = DVD_NOPTS_VALUE;
 
+  // Handle input, add demuxer packet to input queue, we must accept it or
+  // it will be discarded as VideoPlayerVideo has no concept of "try again".
+  // we must return VC_BUFFER or VC_PICTURE, default to VC_BUFFER.
+  int rtn = VC_BUFFER;
+
   // must check for an output picture 1st,
   // otherwise, mediacodec can stall on some devices.
   if (GetOutputPicture() > 0)
+  {
     rtn |= VC_PICTURE;
+    if (m_codecControlFlags & DVD_CODEC_CTRL_DRAIN)
+      rtn &= ~VC_BUFFER;
+  }
 
   if (!pData)
   {
@@ -688,21 +691,6 @@ int CDVDVideoCodecAndroidMediaCodec::Decode(uint8_t *pData, int iSize, double dt
     }
     else if (index >= 0)
     {
-      // docs lie, getInputBuffers should be good after
-      // m_codec->start() but the internal refs are not
-      // setup until much later on some devices.
-      if (m_input.empty())
-      {
-        m_input = m_codec->getInputBuffers();
-        if (xbmc_jnienv()->ExceptionCheck())
-        {
-          CLog::Log(LOGERROR, "CDVDMediaCodecInfo::getInputBuffers "
-            "ExceptionCheck");
-          xbmc_jnienv()->ExceptionDescribe();
-          xbmc_jnienv()->ExceptionClear();
-        }
-      }
-
       // we have an input buffer, fill it.
       if (m_bitstream)
       {
@@ -710,14 +698,15 @@ int CDVDVideoCodecAndroidMediaCodec::Decode(uint8_t *pData, int iSize, double dt
         iSize = m_bitstream->GetConvertSize();
         pData = m_bitstream->GetConvertBuffer();
       }
-      int size = m_input[index].capacity();
+      CJNIByteBuffer buffer = m_codec->getInputBuffer(index);
+      int size = buffer.capacity();
       if (iSize > size)
       {
         CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::Decode, iSize(%d) > size(%d)", iSize, size);
         iSize = size;
       }
       // fetch a pointer to the ByteBuffer backing store
-      uint8_t *dst_ptr = (uint8_t*)xbmc_jnienv()->GetDirectBufferAddress(m_input[index].get_raw());
+      uint8_t *dst_ptr = (uint8_t*)xbmc_jnienv()->GetDirectBufferAddress(buffer.get_raw());
       if (dst_ptr)
       {
         // Codec specifics
@@ -829,6 +818,8 @@ void CDVDVideoCodecAndroidMediaCodec::Reset()
     if (!m_render_sw)
       m_videobuffer.mediacodec = NULL;
   }
+  m_drop = false;
+  m_codecControlFlags = 0;
 }
 
 bool CDVDVideoCodecAndroidMediaCodec::GetPicture(DVDVideoPicture* pDvdVideoPicture)
@@ -857,6 +848,12 @@ bool CDVDVideoCodecAndroidMediaCodec::ClearPicture(DVDVideoPicture* pDvdVideoPic
 
 void CDVDVideoCodecAndroidMediaCodec::SetDropState(bool bDrop)
 {
+  if (bDrop == m_drop)
+    return;
+
+  if (g_advancedSettings.CanLogComponent(LOGVIDEO))
+    CLog::Log(LOGDEBUG, "%s::%s %s->%s", "CDVDVideoCodecAndroidMediaCodec", __func__, m_drop ? "true" : "false", bDrop ? "true" : "false");
+
   m_drop = bDrop;
   if (m_drop)
     m_videobuffer.iFlags |=  DVP_FLAG_DROPPED;
@@ -864,6 +861,16 @@ void CDVDVideoCodecAndroidMediaCodec::SetDropState(bool bDrop)
     m_videobuffer.iFlags &= ~DVP_FLAG_DROPPED;
 }
 
+void CDVDVideoCodecAndroidMediaCodec::SetCodecControl(int flags)
+{
+  if (m_codecControlFlags != flags)
+  {
+    if (g_advancedSettings.CanLogComponent(LOGVIDEO))
+      CLog::Log(LOGDEBUG, "%s::%s %x->%x", "CDVDVideoCodecAndroidMediaCodec", __func__, m_codecControlFlags, flags);
+    m_codecControlFlags = flags;
+  }
+}
+
 int CDVDVideoCodecAndroidMediaCodec::GetDataSize(void)
 {
   // just ignore internal buffering contribution.
@@ -896,12 +903,6 @@ void CDVDVideoCodecAndroidMediaCodec::FlushInternal()
   }
   m_inflight.clear();
 
-  for (size_t i = 0; i < m_output.size(); i++)
-  {
-    m_inflight.push_back(
-      new CDVDMediaCodecInfo(i, m_textureId, m_codec, m_surfaceTexture, m_frameAvailable)
-    );
-  }
 }
 
 bool CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec(void)
@@ -1012,22 +1013,6 @@ int CDVDVideoCodecAndroidMediaCodec::GetOutputPicture(void)
       return 0;
     }
 
-    // some devices will return a valid index
-    // before signaling INFO_OUTPUT_BUFFERS_CHANGED which
-    // is used to setup m_output, D'uh. setup m_output here.
-    if (m_output.empty())
-    {
-      m_output = m_codec->getOutputBuffers();
-      if (xbmc_jnienv()->ExceptionCheck())
-      {
-        CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::GetOutputPicture ExceptionCheck: getOutputBuffers");
-        xbmc_jnienv()->ExceptionDescribe();
-        xbmc_jnienv()->ExceptionClear();
-        return 0;
-      }
-      FlushInternal();
-    }
-
     int flags = bufferInfo.flags();
     if (flags & CJNIMediaCodec::BUFFER_FLAG_SYNC_FRAME)
       CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec:: BUFFER_FLAG_SYNC_FRAME");
@@ -1051,7 +1036,17 @@ int CDVDVideoCodecAndroidMediaCodec::GetOutputPicture(void)
 
     if (!m_render_sw)
     {
-      m_videobuffer.mediacodec = m_inflight[index]->Retain();
+      size_t i = 0;
+      for (; i < m_inflight.size(); ++i)
+      {
+        if (m_inflight[i]->GetIndex() == index)
+          break;
+      }
+      if (i == m_inflight.size())
+        m_inflight.push_back(
+          new CDVDMediaCodecInfo(index, m_textureId, m_codec, m_surfaceTexture, m_frameAvailable)
+        );
+      m_videobuffer.mediacodec = m_inflight[i]->Retain();
       m_videobuffer.mediacodec->Validate(true);
     }
     else
@@ -1059,12 +1054,16 @@ int CDVDVideoCodecAndroidMediaCodec::GetOutputPicture(void)
       int size = bufferInfo.size();
       int offset = bufferInfo.offset();
 
-      if (!m_output[index].isDirect())
+      CJNIByteBuffer buffer = m_codec->getOutputBuffer(index);;
+      if (!buffer.isDirect())
+        CLog::Log(LOGWARNING, "CDVDVideoCodecAndroidMediaCodec:: buffer.isDirect == false");
+
+      if (!buffer.isDirect())
         CLog::Log(LOGWARNING, "CDVDVideoCodecAndroidMediaCodec:: m_output[index].isDirect == false");
 
-      if (size && m_output[index].capacity())
+      if (size && buffer.capacity())
       {
-        uint8_t *src_ptr = (uint8_t*)xbmc_jnienv()->GetDirectBufferAddress(m_output[index].get_raw());
+        uint8_t *src_ptr = (uint8_t*)xbmc_jnienv()->GetDirectBufferAddress(buffer.get_raw());
         src_ptr += offset;
 
         int loop_end = 0;
@@ -1092,12 +1091,6 @@ int CDVDVideoCodecAndroidMediaCodec::GetOutputPicture(void)
         }
       }
       m_codec->releaseOutputBuffer(index, false);
-      if (xbmc_jnienv()->ExceptionCheck())
-      {
-        CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::GetOutputPicture ExceptionCheck: releaseOutputBuffer");
-        xbmc_jnienv()->ExceptionDescribe();
-        xbmc_jnienv()->ExceptionClear();
-      }
     }
 
     int64_t pts= bufferInfo.presentationTimeUs();
@@ -1116,37 +1109,26 @@ int CDVDVideoCodecAndroidMediaCodec::GetOutputPicture(void)
 
     rtn = 1;
   }
-  else if (index == CJNIMediaCodec::INFO_OUTPUT_BUFFERS_CHANGED)
-  {
-    m_output = m_codec->getOutputBuffers();
-    if (xbmc_jnienv()->ExceptionCheck())
-    {
-      CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::GetOutputPicture(INFO_OUTPUT_BUFFERS_CHANGED) ExceptionCheck: getOutputBuffers");
-      xbmc_jnienv()->ExceptionDescribe();
-      xbmc_jnienv()->ExceptionClear();
-    }
-    FlushInternal();
-  }
   else if (index == CJNIMediaCodec::INFO_OUTPUT_FORMAT_CHANGED)
   {
     CJNIMediaFormat mediaformat = m_codec->getOutputFormat();
     if (xbmc_jnienv()->ExceptionCheck())
     {
-      CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::GetOutputPicture(INFO_OUTPUT_FORMAT_CHANGED) ExceptionCheck: getOutputBuffers");
       xbmc_jnienv()->ExceptionDescribe();
       xbmc_jnienv()->ExceptionClear();
     }
     ConfigureOutputFormat(&mediaformat);
   }
-  else if (index == CJNIMediaCodec::INFO_TRY_AGAIN_LATER)
+  else if (index == CJNIMediaCodec::INFO_TRY_AGAIN_LATER || index == CJNIMediaCodec::INFO_OUTPUT_BUFFERS_CHANGED)
   {
-    // normal dequeueOutputBuffer timeout, ignore it.
+    // ignore
     rtn = -1;
   }
   else
   {
     // we should never get here
     CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::GetOutputPicture unknown index(%d)", index);
+    rtn = -1;
   }
 
   return rtn;
@@ -1426,4 +1408,4 @@ void CDVDVideoCodecAndroidMediaCodec::ReleaseSurfaceTexture(void)
     glDeleteTextures(1, &texture_id);
     m_textureId = 0;
   }
-}
+}
\ No newline at end of file
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h
index 56ce044..fd20801 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h
@@ -101,6 +101,7 @@ public:
   virtual bool    GetPicture(DVDVideoPicture *pDvdVideoPicture);
   virtual bool    ClearPicture(DVDVideoPicture* pDvdVideoPicture);
   virtual void    SetDropState(bool bDrop);
+  virtual void    SetCodecControl(int flags);
   virtual int     GetDataSize(void);
   virtual double  GetTimeSize(void);
   virtual const char* GetName(void) { return m_formatname.c_str(); }
@@ -125,6 +126,7 @@ protected:
   std::string     m_formatname;
   bool            m_opened;
   bool            m_drop;
+  int             m_codecControlFlags;
 
   CJNISurface    *m_surface;
   unsigned int    m_textureId;
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
index 0414d85..3ccf4b8 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
@@ -68,6 +68,7 @@ extern "C" {
 #include "libavfilter/avfilter.h"
 #include "libavfilter/buffersink.h"
 #include "libavfilter/buffersrc.h"
+#include "libavutil/pixdesc.h"
 }
 
 enum DecoderState
@@ -88,15 +89,19 @@ enum EFilterFlags {
   FILTER_ROTATE              = 0x40,  //< rotate image according to the codec hints
 };
 
-enum AVPixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx
-                                                , const AVPixelFormat * fmt )
+enum AVPixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avctx, const AVPixelFormat * fmt)
 {
   CDVDVideoCodecFFmpeg* ctx  = (CDVDVideoCodecFFmpeg*)avctx->opaque;
 
+  const char* pixFmtName = av_get_pix_fmt_name(*fmt);
+
   // if frame threading is enabled hw accel is not allowed
   if(ctx->m_decoderState != STATE_HW_SINGLE)
   {
-    return avcodec_default_get_format(avctx, fmt);
+    AVPixelFormat defaultFmt = avcodec_default_get_format(avctx, fmt);
+    pixFmtName = av_get_pix_fmt_name(defaultFmt);
+    ctx->m_processInfo.SetVideoPixelFormat(pixFmtName ? pixFmtName : "");
+    return defaultFmt;
   }
 
   // fix an ffmpeg issue here, it calls us with an invalid profile
@@ -122,9 +127,10 @@ enum AVPixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avct
     if(VDPAU::CDecoder::IsVDPAUFormat(*cur) && CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_USEVDPAU))
     {
       CLog::Log(LOGNOTICE,"CDVDVideoCodecFFmpeg::GetFormat - Creating VDPAU(%ix%i)", avctx->width, avctx->height);
-      VDPAU::CDecoder* vdp = new VDPAU::CDecoder();
+      VDPAU::CDecoder* vdp = new VDPAU::CDecoder(ctx->m_processInfo);
       if(vdp->Open(avctx, ctx->m_pCodecContext, *cur, ctx->m_uSurfacesCount))
       {
+        ctx->m_processInfo.SetVideoPixelFormat(pixFmtName ? pixFmtName : "");
         ctx->SetHardware(vdp);
         return *cur;
       }
@@ -137,9 +143,10 @@ enum AVPixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avct
      !ctx->m_hints.dvd && !ctx->m_hints.stills)
   {
     CLog::Log(LOGNOTICE, "CDVDVideoCodecFFmpeg::GetFormat - Creating DXVA(%ix%i)", avctx->width, avctx->height);
-    DXVA::CDecoder* dec = new DXVA::CDecoder();
+    DXVA::CDecoder* dec = new DXVA::CDecoder(ctx->m_processInfo);
     if(dec->Open(avctx, ctx->m_pCodecContext, *cur, ctx->m_uSurfacesCount))
     {
+      ctx->m_processInfo.SetVideoPixelFormat(pixFmtName ? pixFmtName : "");
       ctx->SetHardware(dec);
       return *cur;
     }
@@ -151,9 +158,10 @@ enum AVPixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avct
     // mpeg4 vaapi decoding is disabled
     if(*cur == AV_PIX_FMT_VAAPI_VLD && CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_USEVAAPI))
     {
-      VAAPI::CDecoder* dec = new VAAPI::CDecoder();
+      VAAPI::CDecoder* dec = new VAAPI::CDecoder(ctx->m_processInfo);
       if(dec->Open(avctx, ctx->m_pCodecContext, *cur, ctx->m_uSurfacesCount) == true)
       {
+        ctx->m_processInfo.SetVideoPixelFormat(pixFmtName ? pixFmtName : "");
         ctx->SetHardware(dec);
         return *cur;
       }
@@ -165,9 +173,10 @@ enum AVPixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avct
 #ifdef TARGET_DARWIN
     if (*cur == AV_PIX_FMT_VIDEOTOOLBOX && CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_USEVTB))
     {
-      VTB::CDecoder* dec = new VTB::CDecoder();
+      VTB::CDecoder* dec = new VTB::CDecoder(ctx->m_processInfo);
       if(dec->Open(avctx, ctx->m_pCodecContext, *cur, ctx->m_uSurfacesCount))
       {
+        ctx->m_processInfo.SetVideoPixelFormat(pixFmtName ? pixFmtName : "");
         ctx->SetHardware(dec);
         return *cur;
       }
@@ -180,9 +189,9 @@ enum AVPixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avct
     if (*cur == AV_PIX_FMT_YUV420P)
     {
       MMAL::CDecoder* dec = new MMAL::CDecoder();
-      ctx->m_pCodecContext->hwaccel_context = (void *)ctx->m_options.m_opaque_pointer;
       if(dec->Open(avctx, ctx->m_pCodecContext, *cur, ctx->m_uSurfacesCount))
       {
+        ctx->m_processInfo.SetVideoPixelFormat(pixFmtName ? pixFmtName : "");
         ctx->SetHardware(dec);
         return *cur;
       }
@@ -193,6 +202,7 @@ enum AVPixelFormat CDVDVideoCodecFFmpeg::GetFormat( struct AVCodecContext * avct
     cur++;
   }
 
+  ctx->m_processInfo.SetVideoPixelFormat(pixFmtName ? pixFmtName : "");
   ctx->m_decoderState = STATE_HW_FAILED;
   return avcodec_default_get_format(avctx, fmt);
 }
@@ -226,6 +236,7 @@ CDVDVideoCodecFFmpeg::CDVDVideoCodecFFmpeg(CProcessInfo &processInfo) : CDVDVide
   m_skippedDeint = 0;
   m_droppedFrames = 0;
   m_interlaced = false;
+  m_DAR = 1.0;
 }
 
 CDVDVideoCodecFFmpeg::~CDVDVideoCodecFFmpeg()
@@ -385,6 +396,8 @@ bool CDVDVideoCodecFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options
   }
 
   UpdateName();
+
+  m_processInfo.SetVideoDimensions(m_pCodecContext->coded_width, m_pCodecContext->coded_height);
   return true;
 }
 
@@ -434,7 +447,6 @@ void CDVDVideoCodecFFmpeg::SetDropState(bool bDrop)
 void CDVDVideoCodecFFmpeg::SetFilters()
 {
   // ask codec to do deinterlacing if possible
-  EDEINTERLACEMODE mDeintMode = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_DeinterlaceMode;
   EINTERLACEMETHOD mInt = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod;
 
   if (mInt != VS_INTERLACEMETHOD_DEINTERLACE && mInt != VS_INTERLACEMETHOD_DEINTERLACE_HALF)
@@ -442,14 +454,14 @@ void CDVDVideoCodecFFmpeg::SetFilters()
 
   unsigned int filters = 0;
 
-  if (mDeintMode != VS_DEINTERLACEMODE_OFF)
+  if (mInt != VS_INTERLACEMETHOD_NONE)
   {
     if (mInt == VS_INTERLACEMETHOD_DEINTERLACE)
       filters = FILTER_DEINTERLACE_ANY;
     else if (mInt == VS_INTERLACEMETHOD_DEINTERLACE_HALF)
       filters = FILTER_DEINTERLACE_ANY | FILTER_DEINTERLACE_HALFED;
 
-    if (mDeintMode == VS_DEINTERLACEMODE_AUTO && filters)
+    if (filters)
       filters |= FILTER_DEINTERLACE_FLAGGED;
   }
 
@@ -498,6 +510,8 @@ void CDVDVideoCodecFFmpeg::UpdateName()
   if(m_pHardware)
     m_name += "-" + m_pHardware->Name();
 
+  m_processInfo.SetVideoDecoderName(m_name, m_pHardware ? true : false);
+
   CLog::Log(LOGDEBUG, "CDVDVideoCodecFFmpeg - Updated codec: %s", m_name.c_str());
 }
 
@@ -746,6 +760,12 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture)
   if (aspect_ratio <= 0.0)
     aspect_ratio = (float)pDvdVideoPicture->iWidth / (float)pDvdVideoPicture->iHeight;
 
+  if (m_DAR != aspect_ratio)
+  {
+    m_DAR = aspect_ratio;
+    m_processInfo.SetVideoDAR(m_DAR);
+  }
+
   /* XXX: we suppose the screen has a 1.0 pixel ratio */ // CDVDVideo will compensate it.
   pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight;
   pDvdVideoPicture->iDisplayWidth  = ((int)RINT(pDvdVideoPicture->iHeight * aspect_ratio)) & -3;
@@ -937,6 +957,11 @@ int CDVDVideoCodecFFmpeg::FilterOpen(const std::string& filters, bool scale)
 
     avfilter_inout_free(&outputs);
     avfilter_inout_free(&inputs);
+
+    if (filters.compare(0,5,"yadif") == 0)
+    {
+      m_processInfo.SetVideoDeintMethod(filters);
+    }
   }
   else
   {
@@ -945,6 +970,8 @@ int CDVDVideoCodecFFmpeg::FilterOpen(const std::string& filters, bool scale)
       CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterOpen - avfilter_link");
       return result;
     }
+
+    m_processInfo.SetVideoDeintMethod("none");
   }
 
   if ((result = avfilter_graph_config(m_pFilterGraph,  nullptr)) < 0)
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
index 4ef2982..20bc1ff 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
@@ -119,6 +119,7 @@ protected:
   bool   m_requestSkipDeint;
   int    m_codecControlFlags;
   bool m_interlaced;
+  double m_DAR;
   CDVDStreamInfo m_hints;
   CDVDCodecOptions m_options;
 };
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.cpp
index f8730c5..fb83b42 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.cpp
@@ -29,6 +29,7 @@
 #include <d3d11.h>
 #include <Initguid.h>
 #include <windows.h>
+#include "cores/VideoPlayer/Process/ProcessInfo.h"
 #include "cores/VideoPlayer/VideoRenderers/RenderManager.h"
 #include "../DVDCodecUtils.h"
 #include "DXVA.h"
@@ -689,8 +690,9 @@ CRenderPicture::~CRenderPicture()
 // DXVA Decoder
 //-----------------------------------------------------------------------------
 
-CDecoder::CDecoder()
- : m_event(true)
+CDecoder::CDecoder(CProcessInfo& processInfo)
+ : m_event(true),
+   m_processInfo(processInfo)
 {
   m_event.Set();
   m_state     = DXVA_OPEN;
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.h
index ab756f7..2170515 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.h
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.h
@@ -28,6 +28,8 @@
 #include "libavcodec/d3d11va.h"
 #include "threads/Event.h"
 
+class CProcessInfo;
+
 namespace DXVA {
 
 #define CHECK(a) \
@@ -114,7 +116,7 @@ class CDecoder
   , public ID3DResource
 {
 public:
-  CDecoder();
+  CDecoder(CProcessInfo& processInfo);
  ~CDecoder();
 
   // IHardwareDecoder overrides
@@ -163,6 +165,7 @@ protected:
   unsigned int m_surface_alignment;
   CCriticalSection m_section;
   CEvent m_event;
+  CProcessInfo& m_processInfo;
 };
 
 };
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.cpp
index 3d026cd..db15051 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.cpp
@@ -53,8 +53,9 @@ using namespace KODI::MESSAGING;
 
 #define VERBOSE 0
 
-CMMALVideoBuffer::CMMALVideoBuffer(CMMALVideo *omv)
-    : m_omv(omv)
+
+CMMALVideoBuffer::CMMALVideoBuffer(CMMALVideo *omv, std::shared_ptr<CMMALPool> pool)
+    : m_omv(omv), m_pool(pool)
 {
   if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO))
     CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this);
@@ -63,8 +64,9 @@ CMMALVideoBuffer::CMMALVideoBuffer(CMMALVideo *omv)
   m_height = 0;
   m_aligned_width = 0;
   m_aligned_height = 0;
+  m_encoding = MMAL_ENCODING_UNKNOWN;
   m_aspect_ratio = 0.0f;
-  m_refs = 0;
+  m_rendered = false;
 }
 
 CMMALVideoBuffer::~CMMALVideoBuffer()
@@ -92,7 +94,6 @@ CMMALVideo::CMMALVideo(CProcessInfo &processInfo) : CDVDVideoCodec(processInfo)
   m_pFormatName = "mmal-xxxx";
 
   m_interlace_mode = MMAL_InterlaceProgressive;
-  m_interlace_method = VS_INTERLACEMETHOD_NONE;
   m_decoderPts = DVD_NOPTS_VALUE;
   m_demuxerPts = DVD_NOPTS_VALUE;
 
@@ -100,10 +101,7 @@ CMMALVideo::CMMALVideo(CProcessInfo &processInfo) : CDVDVideoCodec(processInfo)
   m_dec_input = NULL;
   m_dec_output = NULL;
   m_dec_input_pool = NULL;
-  m_renderer = NULL;
-
-  m_deint = NULL;
-  m_deint_connection = NULL;
+  m_pool = nullptr;
 
   m_codingType = 0;
 
@@ -113,6 +111,9 @@ CMMALVideo::CMMALVideo(CProcessInfo &processInfo) : CDVDVideoCodec(processInfo)
   m_fps = 0.0f;
   m_num_decoded = 0;
   m_codecControlFlags = 0;
+  m_got_eos = false;
+  m_packet_num = 0;
+  m_packet_num_eos = ~0;
 }
 
 CMMALVideo::~CMMALVideo()
@@ -124,40 +125,19 @@ CMMALVideo::~CMMALVideo()
 
   CSingleLock lock(m_sharedSection);
 
-  if (m_deint && m_deint->control && m_deint->control->is_enabled)
-    mmal_port_disable(m_deint->control);
-
   if (m_dec && m_dec->control && m_dec->control->is_enabled)
     mmal_port_disable(m_dec->control);
 
   if (m_dec_input && m_dec_input->is_enabled)
     mmal_port_disable(m_dec_input);
 
-  if (m_dec_output && m_dec_output->is_enabled)
-    mmal_port_disable(m_dec_output);
   m_dec_output = NULL;
 
-  if (m_deint_connection)
-    mmal_connection_destroy(m_deint_connection);
-  m_deint_connection = NULL;
-
-  if (m_deint && m_deint->is_enabled)
-    mmal_component_disable(m_deint);
-
-  if (m_dec && m_dec->is_enabled)
-      mmal_component_disable(m_dec);
-
   if (m_dec_input_pool)
     mmal_port_pool_destroy(m_dec_input, m_dec_input_pool);
   m_dec_input_pool = NULL;
   m_dec_input = NULL;
 
-  if (m_deint)
-    mmal_component_destroy(m_deint);
-  m_deint = NULL;
-
-  if (m_dec)
-    mmal_component_destroy(m_dec);
   m_dec = NULL;
   mmal_format_free(m_es_format);
   m_es_format = NULL;
@@ -177,6 +157,10 @@ void CMMALVideo::PortSettingsChanged(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *bu
     m_decoded_height = m_es_format->es->video.crop.height;
     m_decoded_aligned_width = m_es_format->es->video.width;
     m_decoded_aligned_height = m_es_format->es->video.height;
+
+    m_processInfo.SetVideoDimensions(m_decoded_width, m_decoded_height);
+    m_processInfo.SetVideoDAR(m_aspect_ratio);
+
     if (g_advancedSettings.CanLogComponent(LOGVIDEO))
       CLog::Log(LOGDEBUG, "%s::%s format changed: %dx%d (%dx%d) %.2f", CLASSNAME, __func__, m_decoded_width, m_decoded_height, m_decoded_aligned_width, m_decoded_aligned_height, m_aspect_ratio);
   }
@@ -235,9 +219,10 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf
 {
   if (!(buffer->cmd == 0 && buffer->length > 0))
     if (g_advancedSettings.CanLogComponent(LOGVIDEO))
-      CLog::Log(LOGDEBUG, "%s::%s port:%p buffer %p, len %d cmd:%x", CLASSNAME, __func__, port, buffer, buffer->length, buffer->cmd);
+      CLog::Log(LOGDEBUG, "%s::%s port:%p buffer %p, len %d cmd:%x flags:%x", CLASSNAME, __func__, port, buffer, buffer->length, buffer->cmd, buffer->flags);
 
   bool kept = false;
+  CMMALVideoBuffer *omvb = (CMMALVideoBuffer *)buffer->user_data;
 
   assert(!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED));
   if (buffer->cmd == 0)
@@ -250,28 +235,28 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf
         m_decoderPts = buffer->dts;
 
       assert(!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_DECODEONLY));
-      CMMALVideoBuffer *omvb = NULL;
+      assert(omvb);
+      assert(omvb->mmal_buffer == buffer);
       bool wanted = true;
       // we don't keep up when running at 60fps in the background so switch to half rate
       if (m_fps > 40.0f && !g_graphicsContext.IsFullScreenVideo() && !(m_num_decoded & 1))
         wanted = false;
       if (g_advancedSettings.m_omxDecodeStartWithValidFrame && (buffer->flags & MMAL_BUFFER_HEADER_FLAG_CORRUPTED))
         wanted = false;
-      if (wanted)
-        omvb = new CMMALVideoBuffer(this);
       m_num_decoded++;
       if (g_advancedSettings.CanLogComponent(LOGVIDEO))
         CLog::Log(LOGDEBUG, "%s::%s - %p (%p) buffer_size(%u) dts:%.3f pts:%.3f flags:%x:%x",
           CLASSNAME, __func__, buffer, omvb, buffer->length, buffer->dts*1e-6, buffer->pts*1e-6, buffer->flags, buffer->type->video.flags);
-      if (omvb)
+      if (wanted)
       {
-        omvb->mmal_buffer = buffer;
-        buffer->user_data = (void *)omvb;
         omvb->m_width = m_decoded_width;
         omvb->m_height = m_decoded_height;
         omvb->m_aligned_width = m_decoded_aligned_width;
         omvb->m_aligned_height = m_decoded_aligned_height;
         omvb->m_aspect_ratio = m_aspect_ratio;
+        if (m_hints.stills) // disable interlace in dvd stills mode
+          omvb->mmal_buffer->flags &= ~MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED;
+        omvb->m_encoding = m_dec_output->format->encoding;
         {
           CSingleLock lock(m_output_mutex);
           m_output_ready.push(omvb);
@@ -280,13 +265,24 @@ void CMMALVideo::dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf
         kept = true;
       }
     }
+    if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS)
+    {
+      CSingleLock lock(m_output_mutex);
+      m_got_eos = true;
+      m_output_cond.notifyAll();
+    }
   }
   else if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED)
   {
     PortSettingsChanged(port, buffer);
   }
   if (!kept)
-    mmal_buffer_header_release(buffer);
+  {
+    if (omvb)
+      omvb->Release();
+    else
+      mmal_buffer_header_release(buffer);
+  }
 }
 
 static void dec_output_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
@@ -319,7 +315,7 @@ bool CMMALVideo::change_dec_output_format()
 
   mmal_format_copy(m_dec_output->format, m_es_format);
 
-  status = mmal_port_parameter_set_boolean(m_dec_output, MMAL_PARAMETER_ZERO_COPY,  MMAL_TRUE);
+  status = mmal_port_parameter_set_boolean(m_dec_output, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE);
   if (status != MMAL_SUCCESS)
     CLog::Log(LOGERROR, "%s::%s Failed to enable zero copy mode on %s (status=%x %s)", CLASSNAME, __func__, m_dec_output->name, status, mmal_status_to_string(status));
 
@@ -332,160 +328,6 @@ bool CMMALVideo::change_dec_output_format()
   return true;
 }
 
-bool CMMALVideo::CreateDeinterlace(EINTERLACEMETHOD interlace_method)
-{
-  CSingleLock lock(m_sharedSection);
-  MMAL_STATUS_T status;
-
-  if (g_advancedSettings.CanLogComponent(LOGVIDEO))
-    CLog::Log(LOGDEBUG, "%s::%s method:%d", CLASSNAME, __func__, interlace_method);
-
-  assert(!m_deint);
-  assert(m_dec_output == m_dec->output[0]);
-
-  status = mmal_port_disable(m_dec_output);
-  if (status != MMAL_SUCCESS)
-  {
-    CLog::Log(LOGERROR, "%s::%s Failed to disable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
-    return false;
-  }
-
-  /* Create deinterlace filter */
-  status = mmal_component_create("vc.ril.image_fx", &m_deint);
-  if (status != MMAL_SUCCESS)
-  {
-    CLog::Log(LOGERROR, "%s::%s Failed to create deinterlace component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
-    return false;
-  }
-  bool advanced_deinterlace = interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED || interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF;
-  bool half_framerate = interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF || interlace_method == VS_INTERLACEMETHOD_MMAL_BOB_HALF;
-
-  MMAL_PARAMETER_IMAGEFX_PARAMETERS_T imfx_param = {{MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, sizeof(imfx_param)},
-        advanced_deinterlace ? MMAL_PARAM_IMAGEFX_DEINTERLACE_ADV : MMAL_PARAM_IMAGEFX_DEINTERLACE_FAST, 4, {3, 0, half_framerate, 1 }};
-
-  status = mmal_port_parameter_set(m_deint->output[0], &imfx_param.hdr);
-  if (status != MMAL_SUCCESS)
-  {
-    CLog::Log(LOGERROR, "%s::%s Failed to set deinterlace parameters (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
-    return false;
-  }
-
-  MMAL_PORT_T *m_deint_input = m_deint->input[0];
-  m_deint_input->userdata = (struct MMAL_PORT_USERDATA_T *)this;
-
-  // Image_fx assumed 3 frames of context. simple deinterlace doesn't require this
-  status = mmal_port_parameter_set_uint32(m_deint_input, MMAL_PARAMETER_EXTRA_BUFFERS, GetAllowedReferences() - 5 + advanced_deinterlace ? 2:0);
-  if (status != MMAL_SUCCESS)
-    CLog::Log(LOGERROR, "%s::%s Failed to enable extra buffers on %s (status=%x %s)", CLASSNAME, __func__, m_deint_input->name, status, mmal_status_to_string(status));
-
-  // Now connect the decoder output port to deinterlace input port
-  status =  mmal_connection_create(&m_deint_connection, m_dec->output[0], m_deint->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT);
-  if (status != MMAL_SUCCESS)
-  {
-    CLog::Log(LOGERROR, "%s::%s Failed to connect deinterlacer component %s (status=%x %s)", CLASSNAME, __func__, m_deint->name, status, mmal_status_to_string(status));
-    return false;
-  }
-
-  status =  mmal_connection_enable(m_deint_connection);
-  if (status != MMAL_SUCCESS)
-  {
-    CLog::Log(LOGERROR, "%s::%s Failed to enable connection %s (status=%x %s)", CLASSNAME, __func__, m_deint->name, status, mmal_status_to_string(status));
-    return false;
-  }
-
-  mmal_format_copy(m_deint->output[0]->format, m_es_format);
-
-  status = mmal_port_parameter_set_boolean(m_deint->output[0], MMAL_PARAMETER_ZERO_COPY,  MMAL_TRUE);
-  if (status != MMAL_SUCCESS)
-    CLog::Log(LOGERROR, "%s::%s Failed to enable zero copy mode on %s (status=%x %s)", CLASSNAME, __func__, m_deint->output[0]->name, status, mmal_status_to_string(status));
-
-  status = mmal_port_format_commit(m_deint->output[0]);
-  if (status != MMAL_SUCCESS)
-  {
-    CLog::Log(LOGERROR, "%s::%s Failed to commit deint output format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
-    return false;
-  }
-
-  status = mmal_component_enable(m_deint);
-  if (status != MMAL_SUCCESS)
-  {
-    CLog::Log(LOGERROR, "%s::%s Failed to enable deinterlacer component %s (status=%x %s)", CLASSNAME, __func__, m_deint->name, status, mmal_status_to_string(status));
-    return false;
-  }
-
-  m_deint->output[0]->buffer_size = m_deint->output[0]->buffer_size_min;
-  m_deint->output[0]->buffer_num = m_deint->output[0]->buffer_num_recommended;
-  m_deint->output[0]->userdata = (struct MMAL_PORT_USERDATA_T *)this;
-  status = mmal_port_enable(m_deint->output[0], dec_output_port_cb_static);
-  if (status != MMAL_SUCCESS)
-  {
-    CLog::Log(LOGERROR, "%s::%s Failed to enable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
-    return false;
-  }
-
-  m_dec_output = m_deint->output[0];
-  m_interlace_method = interlace_method;
-  Prime();
-  return true;
-}
-
-bool CMMALVideo::DestroyDeinterlace()
-{
-  CSingleLock lock(m_sharedSection);
-  MMAL_STATUS_T status;
-
-  if (g_advancedSettings.CanLogComponent(LOGVIDEO))
-    CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__);
-
-  assert(m_deint);
-  assert(m_dec_output == m_deint->output[0]);
-
-  status = mmal_port_disable(m_dec_output);
-  if (status != MMAL_SUCCESS)
-  {
-    CLog::Log(LOGERROR, "%s::%s Failed to disable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
-    return false;
-  }
-
-  status = mmal_connection_destroy(m_deint_connection);
-  if (status != MMAL_SUCCESS)
-  {
-    CLog::Log(LOGERROR, "%s::%s Failed to destroy deinterlace connection (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
-    return false;
-  }
-  m_deint_connection = NULL;
-
-  status = mmal_component_disable(m_deint);
-  if (status != MMAL_SUCCESS)
-  {
-    CLog::Log(LOGERROR, "%s::%s Failed to disable deinterlace component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
-    return false;
-  }
-
-  status = mmal_component_destroy(m_deint);
-  if (status != MMAL_SUCCESS)
-  {
-    CLog::Log(LOGERROR, "%s::%s Failed to destroy deinterlace component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
-    return false;
-  }
-  m_deint = NULL;
-
-  m_dec->output[0]->buffer_size = m_dec->output[0]->buffer_size_min;
-  m_dec->output[0]->buffer_num = m_dec->output[0]->buffer_num_recommended;
-  m_dec->output[0]->userdata = (struct MMAL_PORT_USERDATA_T *)this;
-  status = mmal_port_enable(m_dec->output[0], dec_output_port_cb_static);
-  if (status != MMAL_SUCCESS)
-  {
-    CLog::Log(LOGERROR, "%s::%s Failed to enable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
-    return false;
-  }
-
-  m_dec_output = m_dec->output[0];
-  m_interlace_method = VS_INTERLACEMETHOD_NONE;
-  Prime();
-  return true;
-}
-
 bool CMMALVideo::SendCodecConfigData()
 {
   CSingleLock lock(m_sharedSection);
@@ -526,8 +368,9 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
   if (!CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_USEMMAL) || hints.software)
     return false;
 
+  m_processInfo.SetVideoDeintMethod("none");
+
   m_hints = hints;
-  m_renderer = (CMMALRenderer *)options.m_opaque_pointer;
   MMAL_STATUS_T status;
 
   m_decoded_width = hints.width;
@@ -610,13 +453,15 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
     return false;
   }
 
-  // initialize mmal.
-  status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &m_dec);
-  if (status != MMAL_SUCCESS)
+  /* Create video component with attached pool */
+  m_pool = std::make_shared<CMMALPool>(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, false, MMAL_NUM_OUTPUT_BUFFERS, 128, MMAL_ENCODING_OPAQUE, MMALStateHWDec);
+  if (!m_pool)
   {
-    CLog::Log(LOGERROR, "%s::%s Failed to create MMAL decoder component %s (status=%x %s)", CLASSNAME, __func__, MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, status, mmal_status_to_string(status));
+    CLog::Log(LOGERROR, "%s::%s Failed to create pool for video output", CLASSNAME, __func__);
     return false;
   }
+  m_pool->SetDecoder(this);
+  m_dec = m_pool->GetComponent();
 
   m_dec->control->userdata = (struct MMAL_PORT_USERDATA_T *)this;
   status = mmal_port_enable(m_dec->control, dec_control_port_cb_static);
@@ -666,6 +511,10 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
   if (status != MMAL_SUCCESS)
     CLog::Log(LOGERROR, "%s::%s Failed to configure max num callbacks on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status));
 
+  status = mmal_port_parameter_set_boolean(m_dec_input, MMAL_PARAMETER_ZERO_COPY,  MMAL_TRUE);
+  if (status != MMAL_SUCCESS)
+    CLog::Log(LOGERROR, "%s::%s Failed to enable zero copy mode on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status));
+
   status = mmal_port_format_commit(m_dec_input);
   if (status != MMAL_SUCCESS)
   {
@@ -686,14 +535,8 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
 
   m_dec_output = m_dec->output[0];
 
-  // set up initial decoded frame format - will likely change from this
-  m_dec_output->format->encoding = MMAL_ENCODING_OPAQUE;
   mmal_format_copy(m_es_format, m_dec_output->format);
 
-  status = mmal_port_parameter_set_boolean(m_dec_output, MMAL_PARAMETER_ZERO_COPY,  MMAL_TRUE);
-  if (status != MMAL_SUCCESS)
-    CLog::Log(LOGERROR, "%s::%s Failed to enable zero copy mode on %s (status=%x %s)", CLASSNAME, __func__, m_dec_output->name, status, mmal_status_to_string(status));
-
   status = mmal_port_format_commit(m_dec_output);
   if (status != MMAL_SUCCESS)
   {
@@ -702,7 +545,7 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
   }
 
   m_dec_output->buffer_size = m_dec_output->buffer_size_min;
-  m_dec_output->buffer_num = m_dec_output->buffer_num_recommended;
+  m_dec_output->buffer_num = MMAL_NUM_OUTPUT_BUFFERS;
   m_dec_output->userdata = (struct MMAL_PORT_USERDATA_T *)this;
   status = mmal_port_enable(m_dec_output, dec_output_port_cb_static);
   if (status != MMAL_SUCCESS)
@@ -728,10 +571,13 @@ bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
   if (!SendCodecConfigData())
     return false;
 
-  Prime();
+  if (m_pool)
+    m_pool->Prime();
   m_preroll = !m_hints.stills;
   m_speed = DVD_PLAYSPEED_NORMAL;
 
+  m_processInfo.SetVideoDecoderName(m_pFormatName, true);
+
   return true;
 }
 
@@ -758,21 +604,30 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts)
 
   MMAL_BUFFER_HEADER_T *buffer;
   MMAL_STATUS_T status;
-
-  Prime();
+  bool drain = (m_codecControlFlags & DVD_CODEC_CTRL_DRAIN) ? true : false;
+  bool send_eos = drain && !m_got_eos && m_packet_num_eos != m_packet_num;
+  // we don't get an EOS response if no packets have been sent
+  if (m_packet_num == 0)
+  {
+    send_eos = false;
+    m_got_eos = true;
+  }
+  if (m_pool)
+    m_pool->Prime();
   while (1)
   {
-     if (pData)
+     if (pData || send_eos)
      {
        // 500ms timeout
        {
-         CSingleExit unlock(m_sharedSection);
+         lock.Leave();
          buffer = mmal_queue_timedwait(m_dec_input_pool->queue, 500);
          if (!buffer)
          {
            CLog::Log(LOGERROR, "%s::%s - mmal_queue_get failed", CLASSNAME, __func__);
            return VC_ERROR;
          }
+         lock.Enter();
        }
        mmal_buffer_header_reset(buffer);
        buffer->cmd = 0;
@@ -781,55 +636,35 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts)
        if (m_hints.ptsinvalid) buffer->pts = MMAL_TIME_UNKNOWN;
        buffer->length = (uint32_t)iSize > buffer->alloc_size ? buffer->alloc_size : (uint32_t)iSize;
        // set a flag so we can identify primary frames from generated frames (deinterlace)
-       buffer->flags = MMAL_BUFFER_HEADER_FLAG_USER0;
+       buffer->flags = 0;
        if (m_dropState)
          buffer->flags |= MMAL_BUFFER_HEADER_FLAG_USER3;
 
-       memcpy(buffer->data, pData, buffer->length);
+       if (pData)
+         memcpy(buffer->data, pData, buffer->length);
        iSize -= buffer->length;
        pData += buffer->length;
 
        if (iSize == 0)
+       {
+         m_packet_num++;
          buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END;
-
+         if (send_eos)
+         {
+           buffer->flags |= MMAL_BUFFER_HEADER_FLAG_EOS;
+           m_packet_num_eos = m_packet_num;
+           m_got_eos = false;
+         }
+       }
        if (g_advancedSettings.CanLogComponent(LOGVIDEO))
          CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d/%-6d dts:%.3f pts:%.3f flags:%x ready_queue(%d)",
             CLASSNAME, __func__, buffer, buffer->length, iSize, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, buffer->flags, m_output_ready.size());
-       assert((int)buffer->length > 0);
        status = mmal_port_send_buffer(m_dec_input, buffer);
        if (status != MMAL_SUCCESS)
        {
          CLog::Log(LOGERROR, "%s::%s Failed send buffer to decoder input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
          return VC_ERROR;
        }
-
-       if (iSize == 0)
-       {
-         EDEINTERLACEMODE deinterlace_request = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_DeinterlaceMode;
-         EINTERLACEMETHOD interlace_method = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod;
-         if (interlace_method == VS_INTERLACEMETHOD_AUTO)
-           interlace_method = VS_INTERLACEMETHOD_MMAL_ADVANCED;
-         bool deinterlace = m_interlace_mode != MMAL_InterlaceProgressive;
-
-         // we don't keep up when running at 60fps in the background so switch to half rate
-         if (!g_graphicsContext.IsFullScreenVideo())
-         {
-           if (interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED)
-             interlace_method = VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF;
-           if (interlace_method == VS_INTERLACEMETHOD_MMAL_BOB)
-             interlace_method = VS_INTERLACEMETHOD_MMAL_BOB_HALF;
-         }
-
-         if (m_hints.stills || deinterlace_request == VS_DEINTERLACEMODE_OFF || interlace_method == VS_INTERLACEMETHOD_NONE)
-           deinterlace = false;
-         else if (deinterlace_request == VS_DEINTERLACEMODE_FORCE)
-           deinterlace = true;
-
-         if (((deinterlace && interlace_method != m_interlace_method) || !deinterlace) && m_deint)
-           DestroyDeinterlace();
-         if (deinterlace && !m_deint)
-           CreateDeinterlace(interlace_method);
-       }
     }
     if (!iSize)
       break;
@@ -847,55 +682,32 @@ int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts)
   bool full = queued > DVD_MSEC_TO_TIME(1000);
   int ret = 0;
 
-  unsigned int pics = m_output_ready.size();
-  if (m_preroll && (pics >= GetAllowedReferences() || m_codecControlFlags & DVD_CODEC_CTRL_DRAIN))
-    m_preroll = false;
-  if (pics > 0 && !m_preroll)
-    ret |= VC_PICTURE;
-  if ((m_preroll || pics <= 1) && mmal_queue_length(m_dec_input_pool->queue) > 0 && !(m_codecControlFlags & DVD_CODEC_CTRL_DRAIN))
-    ret |= VC_BUFFER;
-
-  bool slept = false;
-  if (!ret)
+  XbmcThreads::EndTime delay(500);
+  while (!ret && !delay.IsTimePast())
   {
-    slept = true;
+    unsigned int pics = m_output_ready.size();
+    if (m_preroll && (pics >= GetAllowedReferences() || drain))
+      m_preroll = false;
+    if (pics > 0 && !m_preroll)
+      ret |= VC_PICTURE;
+    if ((m_preroll || pics <= 1) && mmal_queue_length(m_dec_input_pool->queue) > 0 && (!drain || m_got_eos || m_packet_num_eos != m_packet_num))
+      ret |= VC_BUFFER;
+    if (!ret)
     {
       // otherwise we busy spin
       lock.Leave();
       CSingleLock output_lock(m_output_mutex);
-      m_output_cond.wait(output_lock, 30);
+      m_output_cond.wait(output_lock, delay.MillisLeft());
       lock.Enter();
     }
-    unsigned int pics = m_output_ready.size();
-    if (m_preroll && (pics >= GetAllowedReferences() || m_codecControlFlags & DVD_CODEC_CTRL_DRAIN))
-      m_preroll = false;
-    if (pics > 0 && !m_preroll)
-      ret |= VC_PICTURE;
-    if ((m_preroll || pics <= 1) && (mmal_queue_length(m_dec_input_pool->queue) > 0 || m_codecControlFlags & DVD_CODEC_CTRL_DRAIN))
-      ret |= VC_BUFFER;
   }
 
   if (g_advancedSettings.CanLogComponent(LOGVIDEO))
-    CLog::Log(LOGDEBUG, "%s::%s - ret(%x) pics(%d) inputs(%d) slept(%d) queued(%.2f) (%.2f:%.2f) full(%d) flags(%x) preroll(%d)", CLASSNAME, __func__, ret, m_output_ready.size(), mmal_queue_length(m_dec_input_pool->queue), slept, queued*1e-6, m_demuxerPts*1e-6, m_decoderPts*1e-6, full, m_codecControlFlags,  m_preroll);
+    CLog::Log(LOGDEBUG, "%s::%s - ret(%x) pics(%d) inputs(%d) slept(%2d) queued(%.2f) (%.2f:%.2f) full(%d) flags(%x) preroll(%d) eos(%d %d/%d)", CLASSNAME, __func__, ret, m_output_ready.size(), mmal_queue_length(m_dec_input_pool->queue), 500-delay.MillisLeft(), queued*1e-6, m_demuxerPts*1e-6, m_decoderPts*1e-6, full, m_codecControlFlags,  m_preroll, m_got_eos, m_packet_num, m_packet_num_eos);
 
   return ret;
 }
 
-void CMMALVideo::Prime()
-{
-  MMAL_BUFFER_HEADER_T *buffer;
-  assert(m_renderer);
-  if (!m_pool)
-    m_pool = m_renderer->GetPool(RENDER_FMT_MMAL, AV_PIX_FMT_YUV420P, true);
-  assert(m_pool);
-  MMAL_POOL_T *render_pool = m_pool->Get();
-  assert(render_pool);
-  if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO))
-    CLog::Log(LOGDEBUG, "%s::%s - queue(%p)", CLASSNAME, __func__, render_pool);
-  while (buffer = mmal_queue_get(render_pool->queue), buffer)
-    Recycle(buffer);
-}
-
 void CMMALVideo::Reset(void)
 {
   CSingleLock lock(m_sharedSection);
@@ -904,16 +716,12 @@ void CMMALVideo::Reset(void)
 
   if (m_dec_input && m_dec_input->is_enabled)
     mmal_port_disable(m_dec_input);
-  if (m_deint_connection && m_deint_connection->is_enabled)
-    mmal_connection_disable(m_deint_connection);
   if (m_dec_output && m_dec_output->is_enabled)
     mmal_port_disable(m_dec_output);
   if (!m_finished)
   {
     if (m_dec_input)
       mmal_port_enable(m_dec_input, dec_input_port_cb_static);
-    if (m_deint_connection)
-      mmal_connection_enable(m_deint_connection);
     if (m_dec_output)
       mmal_port_enable(m_dec_output, dec_output_port_cb_static);
   }
@@ -932,10 +740,7 @@ void CMMALVideo::Reset(void)
       m_output_cond.notifyAll();
     }
     if (buffer)
-    {
-      buffer->Acquire();
       buffer->Release();
-    }
     else
       break;
   }
@@ -943,12 +748,17 @@ void CMMALVideo::Reset(void)
   if (!m_finished)
   {
     SendCodecConfigData();
-    Prime();
+    if (m_pool)
+      m_pool->Prime();
   }
   m_decoderPts = DVD_NOPTS_VALUE;
   m_demuxerPts = DVD_NOPTS_VALUE;
   m_codecControlFlags = 0;
   m_dropState = false;
+  m_num_decoded = 0;
+  m_got_eos = false;
+  m_packet_num = 0;
+  m_packet_num_eos = ~0;
   m_preroll = !m_hints.stills && (m_speed == DVD_PLAYSPEED_NORMAL || m_speed == DVD_PLAYSPEED_PAUSE);
 }
 
@@ -960,32 +770,6 @@ void CMMALVideo::SetSpeed(int iSpeed)
   m_speed = iSpeed;
 }
 
-void CMMALVideo::Recycle(MMAL_BUFFER_HEADER_T *buffer)
-{
-  CSingleLock lock(m_sharedSection);
-  if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO))
-    CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, buffer);
-
-  if (m_finished)
-  {
-    mmal_buffer_header_release(buffer);
-    return;
-  }
-
-  MMAL_STATUS_T status;
-  mmal_buffer_header_reset(buffer);
-  buffer->cmd = 0;
-  if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO))
-    CLog::Log(LOGDEBUG, "%s::%s Send buffer %p from pool to decoder output port %p ready_queue(%d)", CLASSNAME, __func__, buffer, m_dec_output,
-      m_output_ready.size());
-  status = mmal_port_send_buffer(m_dec_output, buffer);
-  if (status != MMAL_SUCCESS)
-  {
-    CLog::Log(LOGERROR, "%s::%s - Failed send buffer to decoder output port (status=0%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
-    return;
-  }
-}
-
 bool CMMALVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
 {
   CSingleLock lock(m_sharedSection);
@@ -1025,7 +809,6 @@ bool CMMALVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
     pDvdVideoPicture->dts = buffer->mmal_buffer->dts == MMAL_TIME_UNKNOWN ? DVD_NOPTS_VALUE : buffer->mmal_buffer->dts;
     pDvdVideoPicture->pts = buffer->mmal_buffer->pts == MMAL_TIME_UNKNOWN ? DVD_NOPTS_VALUE : buffer->mmal_buffer->pts;
 
-    pDvdVideoPicture->MMALBuffer->Acquire();
     pDvdVideoPicture->iFlags  = DVP_FLAG_ALLOCATED;
     if (buffer->mmal_buffer->flags & MMAL_BUFFER_HEADER_FLAG_USER3)
       pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
@@ -1034,6 +817,7 @@ bool CMMALVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
           pDvdVideoPicture->dts == DVD_NOPTS_VALUE ? 0.0 : pDvdVideoPicture->dts*1e-6, pDvdVideoPicture->pts == DVD_NOPTS_VALUE ? 0.0 : pDvdVideoPicture->pts*1e-6,
           pDvdVideoPicture->iFlags, buffer->mmal_buffer->flags, pDvdVideoPicture->MMALBuffer, pDvdVideoPicture->MMALBuffer->mmal_buffer);
     assert(!(buffer->mmal_buffer->flags & MMAL_BUFFER_HEADER_FLAG_DECODEONLY));
+    buffer->mmal_buffer->flags &= ~MMAL_BUFFER_HEADER_FLAG_USER3;
   }
   else
   {
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.h
index d008c6c..d39dc1d 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.h
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALCodec.h
@@ -42,6 +42,9 @@
 #include "cores/VideoPlayer/VideoRenderers/BaseRenderer.h"
 #include "cores/VideoPlayer/DVDResource.h"
 
+
+enum MMALState { MMALStateNone, MMALStateHWDec, MMALStateFFDec, MMALStateDeint, };
+
 // a mmal video frame
 class CMMALBuffer : public IDVDResourceCounted<CMMALBuffer>
 {
@@ -52,7 +55,17 @@ public:
   unsigned int m_height;
   unsigned int m_aligned_width;
   unsigned int m_aligned_height;
+  uint32_t m_encoding;
   float m_aspect_ratio;
+  MMALState m_state;
+  bool m_rendered;
+  const char *GetStateName() {
+    static const char *names[] = { "MMALStateNone", "MMALStateHWDec", "MMALStateFFDec", "MMALStateDeint", };
+    if ((size_t)m_state < vcos_countof(names))
+      return names[(size_t)m_state];
+    else
+      return "invalid";
+  }
 };
 
 class CMMALVideo;
@@ -63,9 +76,11 @@ class CMMALPool;
 class CMMALVideoBuffer : public CMMALBuffer
 {
 public:
-  CMMALVideoBuffer(CMMALVideo *omv);
+  CMMALVideoBuffer(CMMALVideo *dec, std::shared_ptr<CMMALPool> pool);
   virtual ~CMMALVideoBuffer();
   CMMALVideo *m_omv;
+protected:
+  std::shared_ptr<CMMALPool> m_pool;
 };
 
 class CMMALVideo : public CDVDVideoCodec
@@ -88,18 +103,12 @@ public:
   virtual void SetSpeed(int iSpeed);
 
   // MMAL decoder callback routines.
-  void Recycle(MMAL_BUFFER_HEADER_T *buffer);
-
-  // MMAL decoder callback routines.
   void dec_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer);
   void dec_control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer);
   void dec_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer);
 
 protected:
   void QueryCodec(void);
-  bool CreateDeinterlace(EINTERLACEMETHOD interlace_method);
-  bool DestroyDeinterlace();
-  void Prime();
   void Dispose(void);
 
   // Video format
@@ -127,25 +136,24 @@ protected:
   unsigned          m_num_decoded;
   // Components
   MMAL_INTERLACETYPE_T m_interlace_mode;
-  EINTERLACEMETHOD  m_interlace_method;
   double            m_demuxerPts;
   double            m_decoderPts;
   int               m_speed;
   int               m_codecControlFlags;
   bool              m_dropState;
   bool              m_preroll;
+  bool              m_got_eos;
+  uint32_t          m_packet_num;
+  uint32_t          m_packet_num_eos;
 
   CCriticalSection m_sharedSection;
   MMAL_COMPONENT_T *m_dec;
   MMAL_PORT_T *m_dec_input;
   MMAL_PORT_T *m_dec_output;
   MMAL_POOL_T *m_dec_input_pool;
-  CMMALRenderer *m_renderer;
   std::shared_ptr<CMMALPool> m_pool;
 
   MMAL_ES_FORMAT_T *m_es_format;
-  MMAL_COMPONENT_T *m_deint;
-  MMAL_CONNECTION_T *m_deint_connection;
 
   MMAL_FOURCC_T m_codingType;
   bool change_dec_output_format();
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.cpp
index 3825e4c..ad0f65c 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.cpp
@@ -42,105 +42,48 @@ using namespace MMAL;
 
 #define CLASSNAME "CMMALYUVBuffer"
 
-CMMALYUVBuffer::CMMALYUVBuffer(CDecoder *dec, unsigned int width, unsigned int height, unsigned int aligned_width, unsigned int aligned_height)
-  : m_dec(dec)
+CMMALYUVBuffer::CMMALYUVBuffer(std::shared_ptr<CMMALPool> pool, uint32_t mmal_encoding, uint32_t width, uint32_t height, uint32_t aligned_width, uint32_t aligned_height, uint32_t size)
+  : m_pool(pool)
 {
-  unsigned int size_pic = 0;
-  dec->Acquire();
+  uint32_t size_pic = 0;
   m_width = width;
   m_height = height;
   m_aligned_width = aligned_width;
   m_aligned_height = aligned_height;
+  m_encoding = mmal_encoding;
   m_aspect_ratio = 0.0f;
   mmal_buffer = nullptr;
-  if (dec->m_fmt == AV_PIX_FMT_YUV420P)
+  m_rendered = false;
+  if (m_encoding == MMAL_ENCODING_I420)
     size_pic = (m_aligned_width * m_aligned_height * 3) >> 1;
-  else if (dec->m_fmt == AV_PIX_FMT_BGR0)
+  else if (m_encoding == MMAL_ENCODING_YUVUV128)
+    size_pic = (m_aligned_width * m_aligned_height * 3) >> 1;
+  else if (m_encoding == MMAL_ENCODING_ARGB || m_encoding == MMAL_ENCODING_RGBA || m_encoding == MMAL_ENCODING_ABGR || m_encoding == MMAL_ENCODING_BGRA)
     size_pic = (m_aligned_width << 2) * m_aligned_height;
-  else if (dec->m_fmt == AV_PIX_FMT_RGB565LE)
+  else if (m_encoding == MMAL_ENCODING_RGB16)
     size_pic = (m_aligned_width << 1) * m_aligned_height;
   else assert(0);
-  gmem = m_dec->AllocateBuffer(size_pic);
+  if (size)
+  {
+    assert(size_pic <= size);
+    size_pic = size;
+  }
+  gmem = m_pool->AllocateBuffer(size_pic);
   if (gmem)
     gmem->m_opaque = (void *)this;
   if (g_advancedSettings.CanLogComponent(LOGVIDEO))
-    CLog::Log(LOGDEBUG, "%s::%s buf:%p gmem:%p mmal:%p", CLASSNAME, __FUNCTION__, this, gmem, mmal_buffer);
+    CLog::Log(LOGDEBUG, "%s::%s buf:%p gmem:%p mmal:%p %dx%d (%dx%d) size:%d %.4s", CLASSNAME, __FUNCTION__, this, gmem, mmal_buffer, m_width, m_height, m_aligned_width, m_aligned_height, gmem->m_numbytes, (char *)&m_encoding);
 }
 
 CMMALYUVBuffer::~CMMALYUVBuffer()
 {
   if (g_advancedSettings.CanLogComponent(LOGVIDEO))
-    CLog::Log(LOGDEBUG, "%s::%s buf:%p gmem:%p", CLASSNAME, __FUNCTION__, this, gmem);
+    CLog::Log(LOGDEBUG, "%s::%s buf:%p gmem:%p mmal:%p %dx%d (%dx%d) size:%d %.4s", CLASSNAME, __FUNCTION__, this, gmem, mmal_buffer, m_width, m_height, m_aligned_width, m_aligned_height, gmem->m_numbytes, (char *)&m_encoding);
   if (gmem)
-    m_dec->ReleaseBuffer(gmem);
+    m_pool->ReleaseBuffer(gmem);
   gmem = nullptr;
   if (mmal_buffer)
     mmal_buffer_header_release(mmal_buffer);
-  m_dec->Release();
-}
-
-CGPUMEM *CDecoder::AllocateBuffer(unsigned int size_pic)
-{
-  CSingleLock lock(m_section);
-  CGPUMEM *gmem = nullptr;
-  while (!m_freeBuffers.empty())
-  {
-    gmem = m_freeBuffers.front();
-    m_freeBuffers.pop_front();
-    if (gmem->m_numbytes == size_pic)
-      return gmem;
-    if (g_advancedSettings.CanLogComponent(LOGVIDEO))
-      CLog::Log(LOGDEBUG, "%s::%s discarding gmem:%p size %d/%d", CLASSNAME, __FUNCTION__, gmem, gmem->m_numbytes, size_pic);
-    delete gmem;
-  }
-
-  gmem = new CGPUMEM(size_pic, true);
-  if (!gmem)
-    CLog::Log(LOGERROR, "%s::%s GCPUMEM(%d) failed", CLASSNAME, __FUNCTION__, size_pic);
-  return gmem;
-}
-
-void CDecoder::ReleaseBuffer(CGPUMEM *gmem)
-{
-  CSingleLock lock(m_section);
-  if (m_closing)
-    delete gmem;
-  else
-    m_freeBuffers.push_back(gmem);
-}
-
-void CDecoder::AlignedSize(AVCodecContext *avctx, int &w, int &h)
-{
-  AVFrame picture;
-  int unaligned;
-  int stride_align[AV_NUM_DATA_POINTERS];
-
-  avcodec_align_dimensions2(avctx, &w, &h, stride_align);
-  // gpu requirements
-  w = (w + 31) & ~31;
-  h = (h + 15) & ~15;
-
-  do {
-    // NOTE: do not align linesizes individually, this breaks e.g. assumptions
-    // that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2
-    av_image_fill_linesizes(picture.linesize, avctx->pix_fmt, w);
-    // increase alignment of w for next try (rhs gives the lowest bit set in w)
-    w += w & ~(w - 1);
-
-    unaligned = 0;
-    for (int i = 0; i < 4; i++)
-      unaligned |= picture.linesize[i] % stride_align[i];
-  } while (unaligned);
-}
-
-CMMALYUVBuffer *CDecoder::GetBuffer(unsigned int width, unsigned int height, AVCodecContext *avctx)
-{
-  CSingleLock lock(m_section);
-  // ffmpeg requirements
-  int aligned_width = width;
-  int aligned_height = height;
-  AlignedSize(avctx, aligned_width, aligned_height);
-  return new CMMALYUVBuffer(this, width, height, aligned_width, aligned_height);
 }
 
 //-----------------------------------------------------------------------------
@@ -156,8 +99,7 @@ CDecoder::CDecoder()
     CLog::Log(LOGDEBUG, "%s::%s - create %p", CLASSNAME, __FUNCTION__, this);
   m_shared = 0;
   m_avctx = nullptr;
-  m_renderer = nullptr;
-  m_closing = false;
+  m_pool = nullptr;
 }
 
 CDecoder::~CDecoder()
@@ -177,21 +119,7 @@ long CDecoder::Release()
 void CDecoder::Close()
 {
   CSingleLock lock(m_section);
-
-  m_closing = true;
-  if (g_advancedSettings.CanLogComponent(LOGVIDEO))
-    CLog::Log(LOGDEBUG, "%s::%s - close %p", CLASSNAME, __FUNCTION__, this);
-
-  while (!m_freeBuffers.empty())
-  {
-    CGPUMEM *gmem = m_freeBuffers.front();
-    m_freeBuffers.pop_front();
-    delete gmem;
-  }
-  assert(m_freeBuffers.empty());
-
-  if (g_advancedSettings.CanLogComponent(LOGVIDEO))
-    CLog::Log(LOGDEBUG,"%s::%s", CLASSNAME, __FUNCTION__);
+  m_pool->Close();
 }
 
 void CDecoder::FFReleaseBuffer(void *opaque, uint8_t *data)
@@ -217,10 +145,31 @@ int CDecoder::FFGetBuffer(AVCodecContext *avctx, AVFrame *frame, int flags)
     return avcodec_default_get_buffer2(avctx, frame, flags);
   }
 
-  CSingleLock lock(dec->m_section);
+  uint32_t mmal_format = 0;
+  if (dec->m_fmt == AV_PIX_FMT_YUV420P)
+    mmal_format = MMAL_ENCODING_I420;
+  else if (dec->m_fmt == AV_PIX_FMT_ARGB)
+    mmal_format = MMAL_ENCODING_ARGB;
+  else if (dec->m_fmt == AV_PIX_FMT_RGBA)
+    mmal_format = MMAL_ENCODING_RGBA;
+  else if (dec->m_fmt == AV_PIX_FMT_ABGR)
+    mmal_format = MMAL_ENCODING_ABGR;
+  else if (dec->m_fmt == AV_PIX_FMT_BGRA)
+    mmal_format = MMAL_ENCODING_BGRA;
+  else if (dec->m_fmt == AV_PIX_FMT_RGB565LE)
+    mmal_format = MMAL_ENCODING_RGB16;
+  if (mmal_format ==  0)
+    return -1;
 
-  CMMALYUVBuffer *YUVBuffer = dec->GetBuffer(frame->width, frame->height, dec->m_avctx);
+  dec->m_pool->SetFormat(mmal_format, frame->width, frame->height, frame->width, frame->height, 0, dec->m_avctx);
+  CMMALYUVBuffer *YUVBuffer = dynamic_cast<CMMALYUVBuffer *>(dec->m_pool->GetBuffer(500));
+  if (!YUVBuffer || !YUVBuffer->mmal_buffer || !YUVBuffer->gmem)
+  {
+    CLog::Log(LOGERROR,"%s::%s Failed to allocated buffer in time", CLASSNAME, __FUNCTION__);
+    return -1;
+  }
 
+  CSingleLock lock(dec->m_section);
   CGPUMEM *gmem = YUVBuffer->gmem;
   AVBufferRef *buf = av_buffer_create((uint8_t *)gmem->m_arm, (YUVBuffer->m_aligned_width * YUVBuffer->m_aligned_height * 3)>>1, CDecoder::FFReleaseBuffer, gmem, AV_BUFFER_FLAG_READONLY);
   if (!buf)
@@ -264,7 +213,7 @@ int CDecoder::FFGetBuffer(AVCodecContext *avctx, AVFrame *frame, int flags)
   // Leave extended buf alone
 
   if (g_advancedSettings.CanLogComponent(LOGVIDEO))
-    CLog::Log(LOGDEBUG,"%s::%s buf:%p gmem:%p avbuf:%p:%p:%p", CLASSNAME, __FUNCTION__, YUVBuffer, gmem, frame->data[0], frame->data[1], frame->data[2]);
+    CLog::Log(LOGDEBUG,"%s::%s buf:%p mmal:%p gmem:%p avbuf:%p:%p:%p", CLASSNAME, __FUNCTION__, YUVBuffer, YUVBuffer->mmal_buffer, gmem, frame->data[0], frame->data[1], frame->data[2]);
 
   return 0;
 }
@@ -274,11 +223,7 @@ bool CDecoder::Open(AVCodecContext *avctx, AVCodecContext* mainctx, enum AVPixel
 {
   CSingleLock lock(m_section);
 
-  m_renderer = (CMMALRenderer *)mainctx->hwaccel_context;
-
-  CLog::Log(LOGNOTICE, "%s::%s - m_renderer:%p", CLASSNAME, __FUNCTION__, m_renderer);
-  assert(m_renderer);
-  mainctx->hwaccel_context = nullptr;
+  CLog::Log(LOGNOTICE, "%s::%s - fmt:%d", CLASSNAME, __FUNCTION__, fmt);
 
   if (surfaces > m_shared)
     m_shared = surfaces;
@@ -290,6 +235,14 @@ bool CDecoder::Open(AVCodecContext *avctx, AVCodecContext* mainctx, enum AVPixel
 
   m_avctx = mainctx;
   m_fmt = fmt;
+
+  /* Create dummy component with attached pool */
+  m_pool = std::make_shared<CMMALPool>(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, false, MMAL_NUM_OUTPUT_BUFFERS, 0, MMAL_ENCODING_I420, MMALStateFFDec);
+  if (!m_pool)
+  {
+    CLog::Log(LOGERROR, "%s::%s Failed to create pool for decoder output", CLASSNAME, __func__);
+    return false;
+  }
   return true;
 }
 
@@ -305,28 +258,6 @@ int CDecoder::Decode(AVCodecContext* avctx, AVFrame* frame)
     return VC_BUFFER;
 }
 
-MMAL_BUFFER_HEADER_T *CDecoder::GetMmal()
-{
-  if (!m_pool)
-    m_pool = m_renderer->GetPool(RENDER_FMT_MMAL, m_fmt, false);
-
-  assert(m_pool);
-  MMAL_POOL_T *render_pool = m_pool->Get();
-  assert(render_pool);
-  MMAL_BUFFER_HEADER_T *mmal_buffer = mmal_queue_timedwait(render_pool->queue, 500);
-  if (!mmal_buffer)
-  {
-    CLog::Log(LOGERROR, "%s::%s - mmal_queue_get failed", CLASSNAME, __FUNCTION__);
-    return nullptr;
-  }
-  mmal_buffer_header_reset(mmal_buffer);
-  mmal_buffer->cmd = 0;
-  mmal_buffer->offset = 0;
-  mmal_buffer->flags = 0;
-  mmal_buffer->user_data = NULL;
-  return mmal_buffer;
-}
-
 bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture* picture)
 {
   CDVDVideoCodecFFmpeg* ctx = (CDVDVideoCodecFFmpeg*)avctx->opaque;
@@ -338,22 +269,17 @@ bool CDecoder::GetPicture(AVCodecContext* avctx, AVFrame* frame, DVDVideoPicture
       frame->buf[1] != nullptr || frame->buf[0] == nullptr)
     return false;
 
-  MMAL_BUFFER_HEADER_T *mmal_buffer = GetMmal();
-  if (!mmal_buffer)
-    return false;
-
   CSingleLock lock(m_section);
 
   AVBufferRef *buf = frame->buf[0];
   CGPUMEM *gmem = (CGPUMEM *)av_buffer_get_opaque(buf);
-  mmal_buffer->data = (uint8_t *)gmem->m_vc_handle;
-  mmal_buffer->alloc_size = mmal_buffer->length = gmem->m_numbytes;
 
   picture->MMALBuffer = (CMMALYUVBuffer *)gmem->m_opaque;
   assert(picture->MMALBuffer);
   picture->format = RENDER_FMT_MMAL;
-  assert(!picture->MMALBuffer->mmal_buffer);
-  picture->MMALBuffer->mmal_buffer = mmal_buffer;
+  assert(picture->MMALBuffer->mmal_buffer);
+  picture->MMALBuffer->mmal_buffer->data = (uint8_t *)gmem->m_vc_handle;
+  picture->MMALBuffer->mmal_buffer->alloc_size = picture->MMALBuffer->mmal_buffer->length = gmem->m_numbytes;
 
   // need to flush ARM cache so GPU can see it
   gmem->Flush();
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.h
index e0ae5ed..e355fb8 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.h
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.h
@@ -34,17 +34,18 @@ class CGPUMEM;
 namespace MMAL {
 
 class CDecoder;
+class CGPUPool;
 
 // a mmal video frame
 class CMMALYUVBuffer : public CMMALBuffer
 {
 public:
-  CMMALYUVBuffer(CDecoder *dec, unsigned int width, unsigned int height, unsigned int aligned_width, unsigned int aligned_height);
+  CMMALYUVBuffer(std::shared_ptr<CMMALPool> pool, uint32_t mmal_encoding, uint32_t width, uint32_t height, uint32_t aligned_width, uint32_t aligned_height, uint32_t size);
   virtual ~CMMALYUVBuffer();
 
   CGPUMEM *gmem;
 private:
-  CDecoder *m_dec;
+  std::shared_ptr<CMMALPool> m_pool;
 };
 
 class CDecoder
@@ -65,21 +66,12 @@ public:
   static void FFReleaseBuffer(void *opaque, uint8_t *data);
   static int FFGetBuffer(AVCodecContext *avctx, AVFrame *pic, int flags);
 
-  static void AlignedSize(AVCodecContext *avctx, int &w, int &h);
-  CMMALYUVBuffer *GetBuffer(unsigned int width, unsigned int height, AVCodecContext *avctx);
-  CGPUMEM *AllocateBuffer(unsigned int numbytes);
-  void ReleaseBuffer(CGPUMEM *gmem);
-  unsigned sizeFree() { return m_freeBuffers.size(); }
-  enum AVPixelFormat m_fmt;
 protected:
-  MMAL_BUFFER_HEADER_T *GetMmal();
   AVCodecContext *m_avctx;
   unsigned int m_shared;
   CCriticalSection m_section;
-  CMMALRenderer *m_renderer;
   std::shared_ptr<CMMALPool> m_pool;
-  std::deque<CGPUMEM *> m_freeBuffers;
-  bool m_closing;
+  enum AVPixelFormat m_fmt;
 };
 
 };
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.cpp
index c014ce2..08decdd 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.cpp
@@ -24,6 +24,7 @@
 #include "DVDVideoCodec.h"
 #include "cores/VideoPlayer/DVDCodecs/DVDCodecUtils.h"
 #include "cores/VideoPlayer/DVDClock.h"
+#include "cores/VideoPlayer/Process/ProcessInfo.h"
 #include "utils/log.h"
 #include "utils/StringUtils.h"
 #include "threads/SingleLock.h"
@@ -444,7 +445,9 @@ bool CVideoSurfaces::HasRefs()
 // VAAPI
 //-----------------------------------------------------------------------------
 
-CDecoder::CDecoder() : m_vaapiOutput(&m_inMsgEvent)
+CDecoder::CDecoder(CProcessInfo& processInfo) :
+  m_vaapiOutput(&m_inMsgEvent),
+  m_processInfo(processInfo)
 {
   m_vaapiConfig.videoSurfaces = &m_videoSurfaces;
 
@@ -453,6 +456,7 @@ CDecoder::CDecoder() : m_vaapiOutput(&m_inMsgEvent)
   m_vaapiConfig.context = 0;
   m_vaapiConfig.contextId = VA_INVALID_ID;
   m_vaapiConfig.configId = VA_INVALID_ID;
+  m_vaapiConfig.processInfo = &m_processInfo;
   m_avctx = NULL;
   m_getBufferError = 0;
 }
@@ -1986,23 +1990,22 @@ void COutput::InitCycle()
 
   m_config.stats->SetCanSkipDeint(false);
 
-  EDEINTERLACEMODE mode = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_DeinterlaceMode;
   EINTERLACEMETHOD method = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod;
   bool interlaced = m_currentPicture.DVDPic.iFlags & DVP_FLAG_INTERLACED;
 
   if (!(flags & DVD_CODEC_CTRL_NO_POSTPROC) &&
-      (mode == VS_DEINTERLACEMODE_FORCE ||
-      (mode == VS_DEINTERLACEMODE_AUTO && interlaced)))
+      interlaced &&
+      method != VS_INTERLACEMETHOD_NONE)
   {
-    if((method == VS_INTERLACEMETHOD_AUTO && interlaced)
-        ||  method == VS_INTERLACEMETHOD_VAAPI_BOB
-        ||  method == VS_INTERLACEMETHOD_VAAPI_MADI
-        ||  method == VS_INTERLACEMETHOD_VAAPI_MACI
-        ||  method == VS_INTERLACEMETHOD_DEINTERLACE
-        ||  method == VS_INTERLACEMETHOD_RENDER_BOB)
+    if (method == VS_INTERLACEMETHOD_AUTO ||
+        method == VS_INTERLACEMETHOD_VAAPI_BOB ||
+        method == VS_INTERLACEMETHOD_VAAPI_MADI ||
+        method == VS_INTERLACEMETHOD_VAAPI_MACI ||
+        method == VS_INTERLACEMETHOD_DEINTERLACE ||
+        method == VS_INTERLACEMETHOD_RENDER_BOB)
     {
-        if (method == VS_INTERLACEMETHOD_AUTO)
-          method = VS_INTERLACEMETHOD_RENDER_BOB;
+      if (method == VS_INTERLACEMETHOD_AUTO)
+        method = VS_INTERLACEMETHOD_RENDER_BOB;
     }
     else
     {
@@ -2016,6 +2019,7 @@ void COutput::InitCycle()
       delete m_pp;
       m_pp = NULL;
       DropVppProcessedPictures();
+      m_config.processInfo->SetVideoDeintMethod("unknown");
     }
     if (!m_pp)
     {
@@ -2034,6 +2038,17 @@ void COutput::InitCycle()
       {
         m_pp->Init(method);
         m_currentDiMethod = method;
+
+        if (method == VS_INTERLACEMETHOD_DEINTERLACE)
+          m_config.processInfo->SetVideoDeintMethod("yadif");
+        else if (method == VS_INTERLACEMETHOD_RENDER_BOB)
+          m_config.processInfo->SetVideoDeintMethod("render-bob");
+        else if (method == VS_INTERLACEMETHOD_VAAPI_BOB)
+          m_config.processInfo->SetVideoDeintMethod("vaapi-bob");
+        else if (method == VS_INTERLACEMETHOD_VAAPI_MADI)
+          m_config.processInfo->SetVideoDeintMethod("vaapi-madi");
+        else if (method == VS_INTERLACEMETHOD_VAAPI_MACI)
+          m_config.processInfo->SetVideoDeintMethod("vaapi-maci");
       }
       else
       {
@@ -2066,6 +2081,7 @@ void COutput::InitCycle()
       {
         m_pp->Init(method);
         m_currentDiMethod = method;
+        m_config.processInfo->SetVideoDeintMethod("none");
       }
       else
       {
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h
index cc744c7..08c5dfc 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VAAPI.h
@@ -48,6 +48,7 @@ extern "C" {
 
 using namespace Actor;
 
+class CProcessInfo;
 
 #define FULLHD_WIDTH                       1920
 
@@ -125,6 +126,7 @@ struct CVaapiConfig
   VAProfile profile;
   VAConfigAttrib attrib;
   Display *x11dsp;
+  CProcessInfo *processInfo;
 };
 
 /**
@@ -411,7 +413,7 @@ class CDecoder
 
 public:
 
-  CDecoder();
+  CDecoder(CProcessInfo& processInfo);
   virtual ~CDecoder();
 
   virtual bool Open      (AVCodecContext* avctx, AVCodecContext* mainctx, const enum AVPixelFormat, unsigned int surfaces = 0);
@@ -468,6 +470,7 @@ protected:
 
   int m_codecControl;
   std::vector<EINTERLACEMETHOD> m_diMethods;
+  CProcessInfo& m_processInfo;
 };
 
 //-----------------------------------------------------------------------------
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VDPAU.cpp
index 331b719..a754c96 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VDPAU.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VDPAU.cpp
@@ -25,6 +25,7 @@
 #include "windowing/WindowingFactory.h"
 #include "guilib/GraphicContext.h"
 #include "guilib/TextureManager.h"
+#include "cores/VideoPlayer/Process/ProcessInfo.h"
 #include "cores/VideoPlayer/VideoRenderers/RenderManager.h"
 #include "DVDVideoCodecFFmpeg.h"
 #include "DVDClock.h"
@@ -467,13 +468,14 @@ int CVideoSurfaces::Size()
 // CVDPAU
 //-----------------------------------------------------------------------------
 
-CDecoder::CDecoder() : m_vdpauOutput(&m_inMsgEvent)
+CDecoder::CDecoder(CProcessInfo& processInfo) : m_vdpauOutput(&m_inMsgEvent), m_processInfo(processInfo)
 {
   m_vdpauConfig.videoSurfaces = &m_videoSurfaces;
 
   m_vdpauConfigured = false;
   m_DisplayState = VDPAU_OPEN;
   m_vdpauConfig.context = 0;
+  m_vdpauConfig.processInfo = &m_processInfo;
 }
 
 bool CDecoder::Open(AVCodecContext* avctx, AVCodecContext* mainctx, const enum AVPixelFormat fmt, unsigned int surfaces)
@@ -1783,10 +1785,8 @@ void CMixer::CheckFeatures()
     m_Sharpness = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_Sharpness;
     SetSharpness();
   }
-  if (m_DeintMode != CMediaSettings::GetInstance().GetCurrentVideoSettings().m_DeinterlaceMode ||
-      m_Deint     != CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod)
+  if (m_Deint != CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod)
   {
-    m_DeintMode = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_DeinterlaceMode;
     m_Deint     = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod;
     SetDeinterlacing();
   }
@@ -2051,14 +2051,13 @@ void CMixer::SetDeinterlacing()
   if (m_videoMixer == VDP_INVALID_HANDLE)
     return;
 
-  EDEINTERLACEMODE   mode = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_DeinterlaceMode;
   EINTERLACEMETHOD method = GetDeinterlacingMethod(true);
 
   VdpVideoMixerFeature feature[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL,
                                      VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL,
                                      VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE };
 
-  if (mode == VS_DEINTERLACEMODE_OFF)
+  if (method == VS_INTERLACEMETHOD_NONE)
   {
     VdpBool enabled[] = {0,0,0};
     vdp_st = m_config.context->GetProcs().vdp_video_mixer_set_feature_enables(m_videoMixer, ARSIZE(feature), feature, enabled);
@@ -2283,7 +2282,6 @@ void CMixer::Init()
   m_Contrast = 0.0;
   m_NoiseReduction = 0.0;
   m_Sharpness = 0.0;
-  m_DeintMode = 0;
   m_Deint = 0;
   m_Upscale = 0;
   m_SeenInterlaceFlag = false;
@@ -2352,26 +2350,25 @@ void CMixer::InitCycle()
 
   m_config.stats->SetCanSkipDeint(false);
 
-  EDEINTERLACEMODE   mode = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_DeinterlaceMode;
   EINTERLACEMETHOD method = GetDeinterlacingMethod();
   bool interlaced = m_mixerInput[1].DVDPic.iFlags & DVP_FLAG_INTERLACED;
   m_SeenInterlaceFlag |= interlaced;
 
   if (!(flags & DVD_CODEC_CTRL_NO_POSTPROC) &&
-      (mode == VS_DEINTERLACEMODE_FORCE ||
-      (mode == VS_DEINTERLACEMODE_AUTO && interlaced)))
-  {
-    if((method == VS_INTERLACEMETHOD_AUTO && interlaced)
-      ||  method == VS_INTERLACEMETHOD_VDPAU_BOB
-      ||  method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL
-      ||  method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF
-      ||  method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL
-      ||  method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF
-      ||  method == VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE )
-    {
-      if(method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF
-        || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF
-        || !g_graphicsContext.IsFullScreenVideo())
+      interlaced &&
+      method != VS_INTERLACEMETHOD_NONE)
+  {
+    if (method == VS_INTERLACEMETHOD_AUTO  ||
+        method == VS_INTERLACEMETHOD_VDPAU_BOB ||
+        method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL ||
+        method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF ||
+        method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL ||
+        method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF ||
+        method == VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE )
+    {
+      if(method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF ||
+         method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF ||
+         !g_graphicsContext.IsFullScreenVideo())
         m_mixersteps = 1;
       else
       {
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VDPAU.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VDPAU.h
index 56601a1..1157f23 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VDPAU.h
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VDPAU.h
@@ -70,6 +70,8 @@ extern "C" {
 #define FULLHD_WIDTH                       1920
 #define MAX_PIC_Q_LENGTH                   20 //for non-interop_yuv this controls the max length of the decoded pic to render completion Q
 
+class CProcessInfo;
+
 namespace VDPAU
 {
 
@@ -182,6 +184,7 @@ struct CVdpauConfig
   uint32_t maxReferences;
   bool useInteropYuv;
   CVDPAUContext *context;
+  CProcessInfo *processInfo;
 };
 
 /**
@@ -330,7 +333,6 @@ protected:
   float m_Contrast;
   float m_NoiseReduction;
   float m_Sharpness;
-  int m_DeintMode;
   int m_Deint;
   int m_Upscale;
   bool m_SeenInterlaceFlag;
@@ -556,7 +558,7 @@ public:
     uint32_t aux; /* optional extra parameter... */
   };
 
-  CDecoder();
+  CDecoder(CProcessInfo& processInfo);
   virtual ~CDecoder();
 
   virtual bool Open      (AVCodecContext* avctx, AVCodecContext* mainctx, const enum AVPixelFormat, unsigned int surfaces = 0);
@@ -623,6 +625,7 @@ protected:
   CVdpauRenderPicture *m_presentPicture;
 
   int m_codecControl;
+  CProcessInfo& m_processInfo;
 };
 
 }
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VTB.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VTB.cpp
index 253aefd..287b7c1 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VTB.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VTB.cpp
@@ -21,6 +21,7 @@
 #ifdef TARGET_DARWIN
 #include "platform/darwin/osx/CocoaInterface.h"
 #include "platform/darwin/DarwinUtils.h"
+#include "cores/VideoPlayer/Process/ProcessInfo.h"
 #include "DVDVideoCodec.h"
 #include "DVDCodecs/DVDCodecUtils.h"
 #include "utils/log.h"
@@ -34,7 +35,7 @@ extern "C" {
 using namespace VTB;
 
 
-CDecoder::CDecoder()
+CDecoder::CDecoder(CProcessInfo& processInfo) : m_processInfo(processInfo)
 {
   m_avctx = nullptr;
 }
@@ -86,6 +87,7 @@ bool CDecoder::Open(AVCodecContext *avctx, AVCodecContext* mainctx, enum AVPixel
   mainctx->pix_fmt = fmt;
   mainctx->hwaccel_context = avctx->hwaccel_context;
 
+  m_processInfo.SetVideoDeintMethod("none");
   return true;
 }
 
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VTB.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VTB.h
index 1e097d4..bad295b 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/VTB.h
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/VTB.h
@@ -23,6 +23,8 @@
 
 #include "DVDVideoCodecFFmpeg.h"
 
+class CProcessInfo;
+
 namespace VTB
 {
 
@@ -30,7 +32,7 @@ class CDecoder
   : public CDVDVideoCodecFFmpeg::IHardwareDecoder
 {
 public:
-  CDecoder();
+  CDecoder(CProcessInfo& processInfo);
  ~CDecoder();
   virtual bool Open(AVCodecContext* avctx, AVCodecContext* mainctx, const enum AVPixelFormat, unsigned int surfaces = 0);
   virtual int Decode(AVCodecContext* avctx, AVFrame* frame);
@@ -43,7 +45,7 @@ public:
 protected:
   unsigned m_renderbuffers_count;
   AVCodecContext *m_avctx;
-
+  CProcessInfo& m_processInfo;
 };
 
 }
diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/CMakeLists.txt b/xbmc/cores/VideoPlayer/DVDDemuxers/CMakeLists.txt
index 7d254f7..63776b1 100644
--- a/xbmc/cores/VideoPlayer/DVDDemuxers/CMakeLists.txt
+++ b/xbmc/cores/VideoPlayer/DVDDemuxers/CMakeLists.txt
@@ -22,12 +22,3 @@ set(HEADERS DemuxMultiSource.h
             DVDFactoryDemuxer.h)
 
 core_add_library(dvddemuxers)
-add_dependencies(dvddemuxers libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(dvddemuxers ffmpeg)
-endif()
-
-if(NOT CORE_SYSTEM_NAME STREQUAL windows)
-  add_dependencies(dvddemuxers dvdnav)
-endif()
diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
index b76e248..929f987 100644
--- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
+++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
@@ -230,11 +230,14 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput, bool streaminfo, bool filein
 
   if( m_pInput->IsStreamType(DVDSTREAM_TYPE_FFMPEG) )
   {
+    CURL url = m_pInput->GetURL();
+
     // special stream type that makes avformat handle file opening
     // allows internal ffmpeg protocols to be used
-    AVDictionary *options = GetFFMpegOptionsFromInput();
+    AVDictionary *options = GetFFMpegOptionsFromURL(url);
 
-    CURL url = m_pInput->GetURL();
+    // use updated url - options may have been stripped
+    strFile = url.Get();
 
     int result=-1;
     if (url.IsProtocol("mms"))
@@ -629,13 +632,12 @@ void CDVDDemuxFFmpeg::SetSpeed(int iSpeed)
   }
 }
 
-AVDictionary *CDVDDemuxFFmpeg::GetFFMpegOptionsFromInput()
+AVDictionary *CDVDDemuxFFmpeg::GetFFMpegOptionsFromURL(CURL &url)
 {
   const CDVDInputStreamFFmpeg *const input =
     dynamic_cast<CDVDInputStreamFFmpeg*>(m_pInput);
 
-  const CURL url = m_pInput->GetURL();
-  AVDictionary *options = NULL;
+  AVDictionary *options = nullptr;
 
   if (url.IsProtocol("http") || url.IsProtocol("https"))
   {
@@ -698,6 +700,52 @@ AVDictionary *CDVDDemuxFFmpeg::GetFFMpegOptionsFromInput()
     }
   }
 
+  if (url.IsProtocol("rtmp")  || url.IsProtocol("rtmpt")  ||
+      url.IsProtocol("rtmpe") || url.IsProtocol("rtmpte") ||
+      url.IsProtocol("rtmps"))
+  {
+    static const std::map<std::string,std::string> optionmap =
+      {{{"SWFPlayer", "rtmp_swfurl"},
+        {"PageURL", "rtmp_pageurl"},
+        {"PlayPath", "rtmp_playpath"},
+        {"TcUrl",    "rtmp_tcurl"},
+        {"IsLive",   "rtmp_live"},
+        {"playpath", "rtmp_playpath"},
+        {"swfurl",   "rtmp_swfurl"},
+        {"swfvfy",   "rtmp_swfverify"},
+      }};
+    CDVDInputStreamFFmpeg* is = static_cast<CDVDInputStreamFFmpeg*>(m_pInput);
+    for (const auto& it : optionmap)
+    {
+      if (is->GetItem().HasProperty(it.first))
+        av_dict_set(&options, it.second.c_str(),
+                    is->GetItem().GetProperty(it.first).asString().c_str(),0);
+    }
+    std::vector<std::string> opts = StringUtils::Split(url.Get(), " ");
+    if (opts.size() > 1) // inline rtmp options
+    {
+      std::string swfurl;
+      bool swfvfy=false;
+      for (size_t i = 1; i < opts.size(); ++i)
+      {
+        std::vector<std::string> value = StringUtils::Split(opts[i], "=");
+        auto it = optionmap.find(value[0]);
+        if (it != optionmap.end())
+        {
+          if (value[0] == "swfurl" || value[0] == "SWFPlayer")
+            swfurl = value[1];
+          if (value[0] == "swfvfy" && value[1] == "true")
+            swfvfy = true;
+          else
+            av_dict_set(&options, it->second.c_str(), value[1].c_str(), 0);
+        }
+        if (swfvfy)
+          av_dict_set(&options, "rtmp_swfverify", swfurl.c_str(), 0);
+      }
+      url = CURL(opts.front());
+    }
+  }
+
   return options;
 }
 
@@ -953,11 +1001,16 @@ DemuxPacket* CDVDDemuxFFmpeg::Read()
 
 bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts)
 {
+  bool hitEnd = false;
+
   if (!m_pInput)
     return false;
 
-  if(time < 0)
+  if (time < 0)
+  {
     time = 0;
+    hitEnd = true;
+  }
 
   m_pkt.result = -1;
   av_packet_unref(&m_pkt.pkt);
@@ -979,8 +1032,8 @@ bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts)
     return true;
   }
 
-  if(!m_pInput->Seek(0, SEEK_POSSIBLE)
-  && !m_pInput->IsStreamType(DVDSTREAM_TYPE_FFMPEG))
+  if (!m_pInput->Seek(0, SEEK_POSSIBLE) &&
+      !m_pInput->IsStreamType(DVDSTREAM_TYPE_FFMPEG))
   {
     CLog::Log(LOGDEBUG, "%s - input stream reports it is not seekable", __FUNCTION__);
     return false;
@@ -1002,7 +1055,7 @@ bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts)
     else if (ret < 0 && m_pInput->IsEOF())
       ret = 0;
 
-    if(ret >= 0)
+    if (ret >= 0)
       UpdateCurrentPTS();
   }
 
@@ -1012,10 +1065,18 @@ bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts)
     CLog::Log(LOGDEBUG, "%s - seek ended up on time %d", __FUNCTION__, (int)(m_currentPts / DVD_TIME_BASE * 1000));
 
   // in this case the start time is requested time
-  if(startpts)
+  if (startpts)
     *startpts = DVD_MSEC_TO_TIME(time);
 
-  return (ret >= 0);
+  if (ret >= 0)
+  {
+    if (!hitEnd)
+      return true;
+    else
+      return false;
+  }
+  else
+    return false;
 }
 
 bool CDVDDemuxFFmpeg::SeekByte(int64_t pos)
diff --git a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.h b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.h
index 7967978..60cfc6f 100644
--- a/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.h
+++ b/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.h
@@ -133,7 +133,7 @@ protected:
   bool IsVideoReady();
   void ResetVideoStreams();
 
-  AVDictionary *GetFFMpegOptionsFromInput();
+  AVDictionary *GetFFMpegOptionsFromURL(CURL &url);
   double ConvertTimestamp(int64_t pts, int den, int num);
   void UpdateCurrentPTS();
   bool IsProgramChange();
diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/CMakeLists.txt b/xbmc/cores/VideoPlayer/DVDInputStreams/CMakeLists.txt
index 9de5f14..9385cb7 100644
--- a/xbmc/cores/VideoPlayer/DVDInputStreams/CMakeLists.txt
+++ b/xbmc/cores/VideoPlayer/DVDInputStreams/CMakeLists.txt
@@ -30,12 +30,3 @@ if(BLURAY_FOUND)
 endif()
 
 core_add_library(dvdinputstreams)
-add_dependencies(dvdinputstreams libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(dvdinputstreams ffmpeg)
-endif()
-
-if(NOT CORE_SYSTEM_NAME STREQUAL windows)
-  add_dependencies(dvdinputstreams dvdnav)
-endif()
diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp
index fc782b2..d7cbf3f 100644
--- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp
+++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp
@@ -131,6 +131,12 @@ CDVDInputStream* CDVDFactoryInputStream::CreateInputStream(IVideoPlayer* pPlayer
   else if(file.substr(0, 8) == "stack://")
     return new CDVDInputStreamStack(fileitem);
 #endif
+  else if(file.substr(0, 7) == "rtmp://"
+       || file.substr(0, 8) == "rtmpt://"
+       || file.substr(0, 8) == "rtmpe://"
+       || file.substr(0, 9) == "rtmpte://"
+       || file.substr(0, 8) == "rtmps://")
+    return new CDVDInputStreamFFmpeg(fileitem);
   else if (fileitem.IsInternetStream())
   {
     if (fileitem.IsType(".m3u8"))
diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.h b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.h
index ffcdb78..c421441 100644
--- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.h
+++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamFFmpeg.h
@@ -39,6 +39,8 @@ public:
   virtual void  Abort() { m_aborted = true;  }
   bool Aborted() { return m_aborted;  }
 
+  const CFileItem& GetItem() const { return m_item; }
+
   bool CanSeek() { return m_can_seek; }
   bool CanPause() { return m_can_pause; }
 
diff --git a/xbmc/cores/VideoPlayer/DVDMessage.cpp b/xbmc/cores/VideoPlayer/DVDMessage.cpp
index 5aed691..0dcc664 100644
--- a/xbmc/cores/VideoPlayer/DVDMessage.cpp
+++ b/xbmc/cores/VideoPlayer/DVDMessage.cpp
@@ -88,13 +88,9 @@ bool CDVDMsgGeneralSynchronize::Wait(unsigned int milliseconds, unsigned int sou
   return true;
 }
 
-void CDVDMsgGeneralSynchronize::Wait(volatile bool *abort, unsigned int source)
+void CDVDMsgGeneralSynchronize::Wait(std::atomic<bool>& abort, unsigned int source)
 {
-  while(!Wait(100, source))
-  {
-    if(abort && *abort)
-      return;
-  }
+  while(!Wait(100, source) && !abort);
 }
 
 long CDVDMsgGeneralSynchronize::Release()
diff --git a/xbmc/cores/VideoPlayer/DVDMessage.h b/xbmc/cores/VideoPlayer/DVDMessage.h
index dadc640..5518721 100644
--- a/xbmc/cores/VideoPlayer/DVDMessage.h
+++ b/xbmc/cores/VideoPlayer/DVDMessage.h
@@ -30,6 +30,7 @@
 
 // include as less is possible to prevent dependencies
 #include "DVDResource.h"
+#include <atomic>
 #include <string>
 #include <string.h>
 
@@ -148,8 +149,8 @@ public:
 
   // waits until all threads waiting, released the object
   // if abort is set somehow
-  bool Wait(unsigned int   ms   , unsigned int source);
-  void Wait(volatile bool *abort, unsigned int source);
+  bool Wait(unsigned int ms         , unsigned int source);
+  void Wait(std::atomic<bool>& abort, unsigned int source);
 private:
   class CDVDMsgGeneralSynchronizePriv* m_p;
 };
diff --git a/xbmc/cores/VideoPlayer/DVDMessageQueue.cpp b/xbmc/cores/VideoPlayer/DVDMessageQueue.cpp
index a1ccfc4..8d82d91 100644
--- a/xbmc/cores/VideoPlayer/DVDMessageQueue.cpp
+++ b/xbmc/cores/VideoPlayer/DVDMessageQueue.cpp
@@ -23,7 +23,7 @@
 #include "utils/log.h"
 #include "threads/SingleLock.h"
 #include "DVDClock.h"
-#include "utils/MathUtils.h"
+#include "math.h"
 
 CDVDMessageQueue::CDVDMessageQueue(const std::string &owner) : m_hEvent(true), m_owner(owner)
 {
@@ -246,7 +246,7 @@ void CDVDMessageQueue::WaitUntilEmpty()
   CLog::Log(LOGNOTICE, "CDVDMessageQueue(%s)::WaitUntilEmpty", m_owner.c_str());
   CDVDMsgGeneralSynchronize* msg = new CDVDMsgGeneralSynchronize(40000, 0);
   Put(msg->Acquire());
-  msg->Wait(&m_bAbortRequest, 0);
+  msg->Wait(m_bAbortRequest, 0);
   msg->Release();
 }
 
@@ -262,12 +262,12 @@ int CDVDMessageQueue::GetLevel() const
   if (IsDataBased())
     return std::min(100, 100 * m_iDataSize / m_iMaxDataSize);
 
-  int level = std::min(100, MathUtils::round_int(100.0 * m_TimeSize * (m_TimeFront - m_TimeBack) / DVD_TIME_BASE ));
+  int level = std::min(100.0, ceil(100.0 * m_TimeSize * (m_TimeFront - m_TimeBack) / DVD_TIME_BASE ));
 
   // if we added lots of packets with NOPTS, make sure that the queue is not signalled empty
   if (level == 0 && m_iDataSize != 0)
   {
-    CLog::Log(LOGNOTICE, "CDVDMessageQueue::GetLevel() - can't determine level");
+    CLog::Log(LOGDEBUG, "CDVDMessageQueue::GetLevel() - can't determine level");
     return 1;
   }
 
diff --git a/xbmc/cores/VideoPlayer/DVDMessageQueue.h b/xbmc/cores/VideoPlayer/DVDMessageQueue.h
index 41b535a..814883e 100644
--- a/xbmc/cores/VideoPlayer/DVDMessageQueue.h
+++ b/xbmc/cores/VideoPlayer/DVDMessageQueue.h
@@ -21,6 +21,7 @@
  */
 
 #include "DVDMessage.h"
+#include <atomic>
 #include <string>
 #include <list>
 #include <algorithm>
@@ -111,7 +112,7 @@ private:
   CEvent m_hEvent;
   mutable CCriticalSection m_section;
 
-  bool m_bAbortRequest;
+  std::atomic<bool> m_bAbortRequest;
   bool m_bInitialized;
 
   int m_iDataSize;
diff --git a/xbmc/cores/VideoPlayer/DVDSubtitles/CMakeLists.txt b/xbmc/cores/VideoPlayer/DVDSubtitles/CMakeLists.txt
index 0ed320f..84bc2a1 100644
--- a/xbmc/cores/VideoPlayer/DVDSubtitles/CMakeLists.txt
+++ b/xbmc/cores/VideoPlayer/DVDSubtitles/CMakeLists.txt
@@ -27,7 +27,3 @@ set(HEADERS DVDFactorySubtitle.h
             DllLibass.h)
 
 core_add_library(dvdsubtitles)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(dvdsubtitles ffmpeg)
-endif()
diff --git a/xbmc/cores/VideoPlayer/DVDSubtitles/DVDSubtitleTagSami.cpp b/xbmc/cores/VideoPlayer/DVDSubtitles/DVDSubtitleTagSami.cpp
index 326f0eb..a3776f7 100644
--- a/xbmc/cores/VideoPlayer/DVDSubtitles/DVDSubtitleTagSami.cpp
+++ b/xbmc/cores/VideoPlayer/DVDSubtitles/DVDSubtitleTagSami.cpp
@@ -222,23 +222,26 @@ void CDVDSubtitleTagSami::CloseTag(CDVDOverlayText* pOverlay)
 
 void CDVDSubtitleTagSami::LoadHead(CDVDSubtitleStream* samiStream)
 {
-  char line[1024];
+  char cLine[1024];
   bool inSTYLE = false;
   CRegExp reg(true);
   if (!reg.RegComp("\\.([a-z]+)[ \t]*\\{[ \t]*name:([^;]*?);[ \t]*lang:([^;]*?);[ \t]*SAMIType:([^;]*?);[ \t]*\\}"))
     return;
 
-  while (samiStream->ReadLine(line, sizeof(line)))
+  while (samiStream->ReadLine(cLine, sizeof(cLine)))
   {
-    if (!strnicmp(line, "<BODY>", 6))
+    std::string line = cLine;
+    StringUtils::Trim(line);
+
+   if (!StringUtils::CompareNoCase(line, "<BODY>"))
       break;
     if (inSTYLE)
     {
-      if (!strnicmp(line, "</STYLE>", 8))
+      if (!StringUtils::CompareNoCase(line, "</STYLE>"))
         break;
       else
       {
-        if (reg.RegFind(line) > -1)
+        if (reg.RegFind(line.c_str()) > -1)
         {
           SLangclass lc;
           lc.ID = reg.GetMatch(1);
@@ -254,9 +257,8 @@ void CDVDSubtitleTagSami::LoadHead(CDVDSubtitleStream* samiStream)
     }
     else
     {
-      if (!strnicmp(line, "<STYLE TYPE=\"text/css\">", 23))
+      if (!StringUtils::CompareNoCase(line, "<STYLE TYPE=\"text/css\">"))
         inSTYLE = true;
     }
   }
 }
-
diff --git a/xbmc/cores/VideoPlayer/Edl.cpp b/xbmc/cores/VideoPlayer/Edl.cpp
index ca60764..0292047 100644
--- a/xbmc/cores/VideoPlayer/Edl.cpp
+++ b/xbmc/cores/VideoPlayer/Edl.cpp
@@ -840,6 +840,51 @@ bool CEdl::InCut(const int iSeek, Cut *pCut) const
   return false;
 }
 
+bool CEdl::GetNearestCut(bool bPlus, const int iSeek, Cut *pCut) const
+{
+  if (bPlus) 
+  {
+    // Searching forwards
+    for (auto &cut : m_vecCuts)
+    {
+      if (iSeek >= cut.start && iSeek <= cut.end) // Inside cut.
+      {
+        if (pCut)
+          *pCut = cut;
+        return true;
+      }
+      else if (iSeek < cut.start) // before this cut
+      {
+        if (pCut)
+          *pCut = cut;
+        return true;
+      }
+    }
+    return false;
+  } 
+  else
+  {
+    // Searching backwards
+    for (int i = (int)m_vecCuts.size() - 1; i >= 0; i--)
+    {
+      if (iSeek - 20000 >= m_vecCuts[i].start && iSeek <= m_vecCuts[i].end) 
+        // Inside cut. We ignore if we're closer to 20 seconds inside
+      {
+        if (pCut)
+          *pCut = m_vecCuts[i];
+        return true;
+      }
+      else if (iSeek > m_vecCuts[i].end) // after this cut
+      {
+        if (pCut)
+          *pCut = m_vecCuts[i];
+        return true;
+      }
+    }
+    return false;
+  }
+}
+
 bool CEdl::GetNextSceneMarker(bool bPlus, const int iClock, int *iSceneMarker) const
 {
   if (!HasSceneMarker())
diff --git a/xbmc/cores/VideoPlayer/Edl.h b/xbmc/cores/VideoPlayer/Edl.h
index 95eef03..c19b69f 100644
--- a/xbmc/cores/VideoPlayer/Edl.h
+++ b/xbmc/cores/VideoPlayer/Edl.h
@@ -54,6 +54,7 @@ public:
   int RestoreCutTime(int iClock) const;
 
   bool InCut(int iSeek, Cut *pCut = NULL) const;
+  bool GetNearestCut(bool bPlus, const int iSeek, Cut *pCut) const;
 
   bool GetNextSceneMarker(bool bPlus, const int iClock, int *iSceneMarker) const;
 
diff --git a/xbmc/cores/VideoPlayer/IVideoPlayer.h b/xbmc/cores/VideoPlayer/IVideoPlayer.h
index aa9033a..5fdfc74 100644
--- a/xbmc/cores/VideoPlayer/IVideoPlayer.h
+++ b/xbmc/cores/VideoPlayer/IVideoPlayer.h
@@ -181,8 +181,8 @@ public:
   virtual int  GetLevel() const = 0;
   virtual bool IsInited() const = 0;
   virtual void SendMessage(CDVDMsg* pMsg, int priority = 0) = 0;
-  virtual void SetVolume(float fVolume) = 0;
-  virtual void SetMute(bool bOnOff) = 0;
+  virtual void SetVolume(float fVolume) {};
+  virtual void SetMute(bool bOnOff) {};
   virtual void SetDynamicRangeCompression(long drc) = 0;
   virtual std::string GetPlayerInfo() = 0;
   virtual int GetAudioBitrate() = 0;
diff --git a/xbmc/cores/VideoPlayer/Process/CMakeLists.txt b/xbmc/cores/VideoPlayer/Process/CMakeLists.txt
index 2f44d55..37d705c 100644
--- a/xbmc/cores/VideoPlayer/Process/CMakeLists.txt
+++ b/xbmc/cores/VideoPlayer/Process/CMakeLists.txt
@@ -1,11 +1,10 @@
 file(GLOB OVERRIDES_CPP overrides/${CORE_SYSTEM_NAME}/*.cpp)
 file(GLOB OVERRIDES_H overrides/${CORE_SYSTEM_NAME}/*.h)
 
-
 set(SOURCES ProcessInfo.cpp ${OVERRIDES_CPP})
 set(HEADERS ProcessInfo.h ${OVERRIDES_H})
 
 core_add_library(process)
 if(OVERRIDES_CPP)
-  target_compile_definitions(process PRIVATE -DPLATFORM_OVERRIDE)
+  target_compile_definitions(${CORE_LIBRARY} PRIVATE -DPLATFORM_OVERRIDE)
 endif()
diff --git a/xbmc/cores/VideoPlayer/Process/ProcessInfo.cpp b/xbmc/cores/VideoPlayer/Process/ProcessInfo.cpp
index ceaa256..9af9e83 100644
--- a/xbmc/cores/VideoPlayer/Process/ProcessInfo.cpp
+++ b/xbmc/cores/VideoPlayer/Process/ProcessInfo.cpp
@@ -19,6 +19,9 @@
  */
 
 #include "ProcessInfo.h"
+#include "ServiceBroker.h"
+#include "cores/DataCacheCore.h"
+#include "threads/SingleLock.h"
 
 // Override for platform ports
 #if !defined(PLATFORM_OVERRIDE)
@@ -51,3 +54,208 @@ bool CProcessInfo::AllowDTSHDDecode()
 {
   return true;
 }
+
+void CProcessInfo::ResetVideoCodecInfo()
+{
+  CSingleLock lock(m_videoCodecSection);
+
+  m_videoIsHWDecoder = false;
+  m_videoDecoderName = "unknown";
+  m_videoDeintMethod = "unknown";
+  m_videoPixelFormat = "unknown";
+  m_videoWidth = 0;
+  m_videoHeight = 0;
+  m_videoFPS = 0.0;
+
+  CServiceBroker::GetDataCacheCore().SetVideoDecoderName(m_videoDecoderName, m_videoIsHWDecoder);
+  CServiceBroker::GetDataCacheCore().SetVideoDeintMethod(m_videoDeintMethod);
+  CServiceBroker::GetDataCacheCore().SetVideoPixelFormat(m_videoPixelFormat);
+  CServiceBroker::GetDataCacheCore().SetVideoDimensions(m_videoWidth, m_videoHeight);
+  CServiceBroker::GetDataCacheCore().SetVideoFps(m_videoFPS);
+}
+
+void CProcessInfo::SetVideoDecoderName(std::string name, bool isHw)
+{
+  CSingleLock lock(m_videoCodecSection);
+
+  m_videoIsHWDecoder = isHw;
+  m_videoDecoderName = name;
+
+  CServiceBroker::GetDataCacheCore().SetVideoDecoderName(m_videoDecoderName, m_videoIsHWDecoder);
+}
+
+std::string CProcessInfo::GetVideoDecoderName()
+{
+  CSingleLock lock(m_videoCodecSection);
+
+  return m_videoDecoderName;
+}
+
+bool CProcessInfo::IsVideoHwDecoder()
+{
+  CSingleLock lock(m_videoCodecSection);
+
+  return m_videoIsHWDecoder;
+}
+
+void CProcessInfo::SetVideoDeintMethod(std::string method)
+{
+  CSingleLock lock(m_videoCodecSection);
+
+  m_videoDeintMethod = method;
+
+  CServiceBroker::GetDataCacheCore().SetVideoDeintMethod(m_videoDeintMethod);
+}
+
+std::string CProcessInfo::GetVideoDeintMethod()
+{
+  CSingleLock lock(m_videoCodecSection);
+
+  return m_videoDeintMethod;
+}
+
+void CProcessInfo::SetVideoPixelFormat(std::string pixFormat)
+{
+  CSingleLock lock(m_videoCodecSection);
+
+  m_videoPixelFormat = pixFormat;
+
+  CServiceBroker::GetDataCacheCore().SetVideoPixelFormat(m_videoPixelFormat);
+}
+
+std::string CProcessInfo::GetVideoPixelFormat()
+{
+  CSingleLock lock(m_videoCodecSection);
+
+  return m_videoPixelFormat;
+}
+
+void CProcessInfo::SetVideoDimensions(int width, int height)
+{
+  CSingleLock lock(m_videoCodecSection);
+
+  m_videoWidth = width;
+  m_videoHeight = height;
+
+  CServiceBroker::GetDataCacheCore().SetVideoDimensions(m_videoWidth, m_videoHeight);
+}
+
+void CProcessInfo::GetVideoDimensions(int &width, int &height)
+{
+  CSingleLock lock(m_videoCodecSection);
+
+  width = m_videoWidth;
+  height = m_videoHeight;
+}
+
+void CProcessInfo::SetVideoFps(float fps)
+{
+  CSingleLock lock(m_videoCodecSection);
+
+  m_videoFPS = fps;
+
+  CServiceBroker::GetDataCacheCore().SetVideoFps(m_videoFPS);
+}
+
+float CProcessInfo::GetVideoFps()
+{
+  CSingleLock lock(m_videoCodecSection);
+
+  return m_videoFPS;
+}
+
+void CProcessInfo::SetVideoDAR(float dar)
+{
+  CSingleLock lock(m_videoCodecSection);
+
+  m_videoDAR = dar;
+
+  CServiceBroker::GetDataCacheCore().SetVideoDAR(m_videoDAR);
+}
+
+float CProcessInfo::GetVideoDAR()
+{
+  CSingleLock lock(m_videoCodecSection);
+
+  return m_videoDAR;
+}
+
+// player audio info
+void CProcessInfo::ResetAudioCodecInfo()
+{
+  CSingleLock lock(m_audioCodecSection);
+
+  m_audioDecoderName = "unknown";
+  m_audioChannels = "unknown";
+  m_audioSampleRate = 0;;
+  m_audioBitsPerSample = 0;
+
+  CServiceBroker::GetDataCacheCore().SetAudioDecoderName(m_audioDecoderName);
+  CServiceBroker::GetDataCacheCore().SetAudioChannels(m_audioChannels);
+  CServiceBroker::GetDataCacheCore().SetAudioSampleRate(m_audioSampleRate);
+  CServiceBroker::GetDataCacheCore().SetAudioBitsPerSample(m_audioBitsPerSample);
+}
+
+void CProcessInfo::SetAudioDecoderName(std::string name)
+{
+  CSingleLock lock(m_audioCodecSection);
+
+  m_audioDecoderName = name;
+
+  CServiceBroker::GetDataCacheCore().SetAudioDecoderName(m_audioDecoderName);
+}
+
+std::string CProcessInfo::GetAudioDecoderName()
+{
+  CSingleLock lock(m_audioCodecSection);
+
+  return m_audioDecoderName;
+}
+
+void CProcessInfo::SetAudioChannels(std::string channels)
+{
+  CSingleLock lock(m_audioCodecSection);
+
+  m_audioChannels = channels;
+
+  CServiceBroker::GetDataCacheCore().SetAudioChannels(m_audioChannels);
+}
+
+std::string CProcessInfo::GetAudioChannels()
+{
+  CSingleLock lock(m_audioCodecSection);
+
+  return m_audioChannels;
+}
+
+void CProcessInfo::SetAudioSampleRate(int sampleRate)
+{
+  CSingleLock lock(m_audioCodecSection);
+
+  m_audioSampleRate = sampleRate;
+
+  CServiceBroker::GetDataCacheCore().SetAudioSampleRate(m_audioSampleRate);
+}
+
+int CProcessInfo::GetAudioSampleRate()
+{
+  CSingleLock lock(m_audioCodecSection);
+
+  return m_audioSampleRate;
+}
+
+void CProcessInfo::SetAudioBitsPerSample(int bitsPerSample)
+{
+  CSingleLock lock(m_audioCodecSection);
+
+  m_audioBitsPerSample = bitsPerSample;
+
+  CServiceBroker::GetDataCacheCore().SetAudioBitsPerSample(m_audioBitsPerSample);
+}
+
+int CProcessInfo::GetAudioBitsPerSampe()
+{
+  CSingleLock lock(m_audioCodecSection);
+
+  return m_audioBitsPerSample;
+}
diff --git a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h b/xbmc/cores/VideoPlayer/Process/ProcessInfo.h
index b8a4e46..0ec9a2c 100644
--- a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h
+++ b/xbmc/cores/VideoPlayer/Process/ProcessInfo.h
@@ -20,6 +20,8 @@
 #pragma once
 
 #include "cores/IPlayer.h"
+#include "threads/CriticalSection.h"
+#include <string>
 
 class CProcessInfo
 {
@@ -29,6 +31,51 @@ public:
   virtual EINTERLACEMETHOD GetFallbackDeintMethod();
   virtual bool AllowDTSHDDecode();
 
+  // player video info
+  void ResetVideoCodecInfo();
+  void SetVideoDecoderName(std::string name, bool isHw);
+  std::string GetVideoDecoderName();
+  bool IsVideoHwDecoder();
+  void SetVideoDeintMethod(std::string method);
+  std::string GetVideoDeintMethod();
+  void SetVideoPixelFormat(std::string pixFormat);
+  std::string GetVideoPixelFormat();
+  void SetVideoDimensions(int width, int height);
+  void GetVideoDimensions(int &width, int &height);
+  void SetVideoFps(float fps);
+  float GetVideoFps();
+  void SetVideoDAR(float dar);
+  float GetVideoDAR();
+
+  // player audio info
+  void ResetAudioCodecInfo();
+  void SetAudioDecoderName(std::string name);
+  std::string GetAudioDecoderName();
+  void SetAudioChannels(std::string channels);
+  std::string GetAudioChannels();
+  void SetAudioSampleRate(int sampleRate);
+  int GetAudioSampleRate();
+  void SetAudioBitsPerSample(int bitsPerSample);
+  int GetAudioBitsPerSampe();
+
 protected:
   CProcessInfo();
+
+  // player video info
+  bool m_videoIsHWDecoder;
+  std::string m_videoDecoderName;
+  std::string m_videoDeintMethod;
+  std::string m_videoPixelFormat;
+  int m_videoWidth;
+  int m_videoHeight;
+  float m_videoFPS;
+  float m_videoDAR;
+  CCriticalSection m_videoCodecSection;
+
+  // player audio info
+  std::string m_audioDecoderName;
+  std::string m_audioChannels;
+  int m_audioSampleRate;
+  int m_audioBitsPerSample;
+  CCriticalSection m_audioCodecSection;
 };
diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.cpp b/xbmc/cores/VideoPlayer/VideoPlayer.cpp
index 9ed9176..5bf0f9b 100644
--- a/xbmc/cores/VideoPlayer/VideoPlayer.cpp
+++ b/xbmc/cores/VideoPlayer/VideoPlayer.cpp
@@ -45,6 +45,7 @@
 #include "guilib/GUIWindowManager.h"
 #include "guilib/StereoscopicsManager.h"
 #include "Application.h"
+#include "ServiceBroker.h"
 #include "messaging/ApplicationMessenger.h"
 
 #include "DVDDemuxers/DVDDemuxCC.h"
@@ -81,6 +82,7 @@
 #include "cores/omxplayer/OMXHelper.h"
 #endif
 #include "VideoPlayerAudio.h"
+#include "cores/DataCacheCore.h"
 #include "windowing/WindowingFactory.h"
 #include "DVDCodecs/DVDCodecUtils.h"
 
@@ -545,8 +547,8 @@ void CSelectionStreams::Update(CDVDInputStream* input, CDVDDemux* demuxer, std::
       Update(s);
     }
   }
-  g_dataCacheCore.SignalAudioInfoChange();
-  g_dataCacheCore.SignalVideoInfoChange();
+  CServiceBroker::GetDataCacheCore().SignalAudioInfoChange();
+  CServiceBroker::GetDataCacheCore().SignalVideoInfoChange();
 }
 
 int CSelectionStreams::CountSource(StreamType type, StreamSource source) const
@@ -636,6 +638,7 @@ CVideoPlayer::CVideoPlayer(IPlayerCallback& callback)
   m_errorCount = 0;
   m_offset_pts = 0.0;
   m_playSpeed = DVD_PLAYSPEED_NORMAL;
+  m_newPlaySpeed = DVD_PLAYSPEED_NORMAL;
   m_streamPlayerSpeed = DVD_PLAYSPEED_NORMAL;
   m_caching = CACHESTATE_DONE;
   m_HasVideo = false;
@@ -650,7 +653,6 @@ CVideoPlayer::CVideoPlayer(IPlayerCallback& callback)
   m_OmxPlayerState.bOmxWaitAudio       = false;
   m_OmxPlayerState.bOmxSentEOFs        = false;
   m_OmxPlayerState.threshold           = 0.2f;
-  m_OmxPlayerState.current_deinterlace = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_DeinterlaceMode;
   m_OmxPlayerState.interlace_method    = VS_INTERLACEMETHOD_MAX;
 #ifdef HAS_OMXPLAYER
   m_omxplayer_mode                     = CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_USEOMXPLAYER);
@@ -1659,7 +1661,11 @@ void CVideoPlayer::CheckStreamChanges(CCurrentStream& current, CDemuxStream* str
     /* if they have, reopen stream */
 
     if (current.hint != CDVDStreamInfo(*stream, true))
-      OpenStream(current, stream->demuxerId, stream->uniqueId , stream->source );
+    {
+      m_SelectionStreams.Clear(STREAM_NONE, STREAM_SOURCE_DEMUX);
+      m_SelectionStreams.Update(m_pInputStream, m_pDemuxer);
+      OpenDefaultStreams(false);
+    }
 
     current.stream = (void*)stream;
     current.changes = stream->changes;
@@ -1988,7 +1994,12 @@ void CVideoPlayer::HandlePlaySpeed()
         CLog::Log(LOGDEBUG, "VideoPlayer::Sync - Video - pts: %f, cache: %f, totalcache: %f",
                              m_CurrentVideo.starttime, m_CurrentVideo.cachetime, m_CurrentVideo.cachetotal);
 
-      if (m_CurrentAudio.starttime != DVD_NOPTS_VALUE && m_CurrentAudio.packets > 0)
+      if (m_CurrentVideo.starttime != DVD_NOPTS_VALUE && m_CurrentVideo.packets > 0 &&
+          m_playSpeed == DVD_PLAYSPEED_PAUSE)
+      {
+        clock = m_CurrentVideo.starttime;
+      }
+      else if (m_CurrentAudio.starttime != DVD_NOPTS_VALUE && m_CurrentAudio.packets > 0)
       {
         if (m_pInputStream->IsRealtime())
           clock = m_CurrentAudio.starttime - m_CurrentAudio.cachetotal - DVD_MSEC_TO_TIME(400);
@@ -2005,11 +2016,13 @@ void CVideoPlayer::HandlePlaySpeed()
       {
         clock = m_CurrentVideo.starttime - m_CurrentVideo.cachetotal;
       }
+
       if (m_omxplayer_mode)
       {
         CLog::Log(LOGDEBUG, "%s::%s player started RESET", "CVideoPlayer", __FUNCTION__);
         m_OmxPlayerState.av_clock.OMXReset(m_CurrentVideo.id >= 0, m_playSpeed != DVD_PLAYSPEED_NORMAL && m_playSpeed != DVD_PLAYSPEED_PAUSE ? false: (m_CurrentAudio.id >= 0));
       }
+
       m_clock.Discontinuity(clock);
       m_CurrentAudio.syncState = IDVDStreamPlayer::SYNC_INSYNC;
       m_CurrentAudio.avsync = CCurrentStream::AV_SYNC_NONE;
@@ -2024,7 +2037,7 @@ void CVideoPlayer::HandlePlaySpeed()
   }
 
   // handle ff/rw
-  if(m_playSpeed != DVD_PLAYSPEED_NORMAL && m_playSpeed != DVD_PLAYSPEED_PAUSE)
+  if (m_playSpeed != DVD_PLAYSPEED_NORMAL && m_playSpeed != DVD_PLAYSPEED_PAUSE)
   {
     if (isInMenu)
     {
@@ -2354,7 +2367,7 @@ void CVideoPlayer::SynchronizeDemuxer(unsigned int timeout)
 
   CDVDMsgGeneralSynchronize* message = new CDVDMsgGeneralSynchronize(timeout, 0);
   m_messenger.Put(message->Acquire());
-  message->Wait(&m_bStop, 0);
+  message->Wait(m_bStop, 0);
   message->Release();
 }
 
@@ -2510,8 +2523,21 @@ void CVideoPlayer::HandleMessages()
 
           FlushBuffers(!msg.GetFlush(), start, msg.GetAccurate(), msg.GetSync());
         }
-        else
-          CLog::Log(LOGWARNING, "error while seeking");
+        else if (m_pDemuxer)
+        {
+          CLog::Log(LOGDEBUG, "VideoPlayer: seek failed or hit end of stream");
+          // dts after successful seek
+          if (start == DVD_NOPTS_VALUE)
+            start = DVD_MSEC_TO_TIME(time) - m_State.time_offset;
+
+          m_State.dts = start;
+
+          FlushBuffers(false, start, false, true);
+          if (m_playSpeed != DVD_PLAYSPEED_PAUSE)
+          {
+            SetPlaySpeed(DVD_PLAYSPEED_NORMAL);
+          }
+        }
 
         // set flag to indicate we have finished a seeking request
         if(!msg.GetTrickPlay())
@@ -2707,7 +2733,7 @@ void CVideoPlayer::HandleMessages()
           }
 
           m_OmxPlayerState.av_clock.OMXSetSpeed(speed);
-          CLog::Log(LOGDEBUG, "%s::%s CDVDMsg::PLAYER_SETSPEED speed : %d (%d)", "CVideoPlayer", __FUNCTION__, speed, m_playSpeed);
+          CLog::Log(LOGDEBUG, "%s::%s CDVDMsg::PLAYER_SETSPEED speed : %d (%d)", "CVideoPlayer", __FUNCTION__, speed, static_cast<int>(m_playSpeed));
         }
         else if ((speed == DVD_PLAYSPEED_NORMAL) &&
                  (m_playSpeed != DVD_PLAYSPEED_NORMAL) &&
@@ -2726,6 +2752,7 @@ void CVideoPlayer::HandleMessages()
         // 1. disable audio
         // 2. skip frames and adjust their pts or the clock
         m_playSpeed = speed;
+        m_newPlaySpeed = speed;
         m_caching = CACHESTATE_DONE;
         m_clock.SetSpeed(speed);
         m_VideoPlayerAudio->SetSpeed(speed);
@@ -2872,8 +2899,8 @@ void CVideoPlayer::HandleMessages()
       else if (pMsg->IsType(CDVDMsg::PLAYER_AVCHANGE))
       {
         UpdateStreamInfos();
-        g_dataCacheCore.SignalAudioInfoChange();
-        g_dataCacheCore.SignalVideoInfoChange();
+        CServiceBroker::GetDataCacheCore().SignalAudioInfoChange();
+        CServiceBroker::GetDataCacheCore().SignalVideoInfoChange();
       }
 
     pMsg->Release();
@@ -2936,6 +2963,7 @@ void CVideoPlayer::SetPlaySpeed(int speed)
   else
   {
     m_playSpeed = speed;
+    m_newPlaySpeed = speed;
     m_streamPlayerSpeed = speed;
   }
 }
@@ -2948,35 +2976,19 @@ bool CVideoPlayer::CanPause()
 
 void CVideoPlayer::Pause()
 {
-  CSingleLock lock(m_StateSection);
-  if (!m_State.canpause)
-    return;
-  lock.Leave();
-
-  if(m_playSpeed != DVD_PLAYSPEED_PAUSE && IsCaching())
-  {
-    SetCaching(CACHESTATE_DONE);
-    return;
-  }
-
-  // return to normal speed if it was paused before, pause otherwise
-  if (m_playSpeed == DVD_PLAYSPEED_PAUSE)
+  // toggle between pause and normal speed
+  if (GetSpeed() == 0)
   {
-    SetPlaySpeed(DVD_PLAYSPEED_NORMAL);
+    SetSpeed(1);
     m_callback.OnPlayBackResumed();
   }
   else
   {
-    SetPlaySpeed(DVD_PLAYSPEED_PAUSE);
+    SetSpeed(0);
     m_callback.OnPlayBackPaused();
   }
 }
 
-bool CVideoPlayer::IsPaused() const
-{
-  return m_playSpeed == DVD_PLAYSPEED_PAUSE || IsCaching();
-}
-
 bool CVideoPlayer::HasVideo() const
 {
   return m_HasVideo;
@@ -3458,14 +3470,28 @@ int64_t CVideoPlayer::GetTotalTime()
   return GetTotalTimeInMsec();
 }
 
-void CVideoPlayer::ToFFRW(int iSpeed)
+void CVideoPlayer::SetSpeed(int iSpeed)
 {
   // can't rewind in menu as seeking isn't possible
   // forward is fine
-  if (iSpeed < 0 && IsInMenu()) return;
+  if (iSpeed < 0 && IsInMenu())
+    return;
+
+  if (!CanSeek())
+    return;
+  
+  m_newPlaySpeed = iSpeed * DVD_PLAYSPEED_NORMAL;
   SetPlaySpeed(iSpeed * DVD_PLAYSPEED_NORMAL);
 }
 
+int CVideoPlayer::GetSpeed()
+{
+  if (m_playSpeed != m_newPlaySpeed)
+    return m_newPlaySpeed / DVD_PLAYSPEED_NORMAL;
+
+  return m_playSpeed / DVD_PLAYSPEED_NORMAL;
+}
+
 bool CVideoPlayer::OpenStream(CCurrentStream& current, int64_t demuxerId, int iStream, int source, bool reset /*= true*/)
 {
   CDemuxStream* stream = NULL;
@@ -3596,8 +3622,8 @@ bool CVideoPlayer::OpenStream(CCurrentStream& current, int64_t demuxerId, int iS
     }
   }
 
-  g_dataCacheCore.SignalAudioInfoChange();
-  g_dataCacheCore.SignalVideoInfoChange();
+  CServiceBroker::GetDataCacheCore().SignalAudioInfoChange();
+  CServiceBroker::GetDataCacheCore().SignalVideoInfoChange();
 
   return res;
 }
@@ -3895,7 +3921,7 @@ void CVideoPlayer::FlushBuffers(bool queued, double pts, bool accurate, bool syn
       CDVDMsgGeneralSynchronize* msg = new CDVDMsgGeneralSynchronize(1000, 0);
       m_VideoPlayerAudio->SendMessage(msg->Acquire(), 1);
       m_VideoPlayerVideo->SendMessage(msg->Acquire(), 1);
-      msg->Wait(&m_bStop, 0);
+      msg->Wait(m_bStop, 0);
       msg->Release();
 
       // purge any pending PLAYER_STARTED messages
@@ -4355,6 +4381,17 @@ bool CVideoPlayer::OnAction(const CAction &action)
       case ACTION_NEXT_ITEM:
       case ACTION_CHANNEL_UP:
       {
+        if (m_Edl.HasCut()) 
+        {
+          // If the clip has an EDL, we'll search through that instead of sending a CHANNEL message
+          const int64_t clock = m_omxplayer_mode ? GetTime() : DVD_TIME_TO_MSEC(std::min(m_CurrentAudio.dts, m_CurrentVideo.dts) + m_offset_pts);
+          CEdl::Cut cut;
+          if (m_Edl.GetNearestCut(true, clock, &cut)) 
+          {
+            m_messenger.Put(new CDVDMsgPlayerSeek(cut.end + 1, false, true, false, true, false, true));
+            return true;
+          }
+        }
         bool bPreview(action.GetID() == ACTION_MOVE_UP && // only up/down shows a preview, all others do switch
                       CSettings::GetInstance().GetBool(CSettings::SETTING_PVRPLAYBACK_CONFIRMCHANNELSWITCH));
 
@@ -4376,6 +4413,23 @@ bool CVideoPlayer::OnAction(const CAction &action)
       case ACTION_PREV_ITEM:
       case ACTION_CHANNEL_DOWN:
       {
+        if (m_Edl.HasCut())
+        {
+          // If the clip has an EDL, we'll search through that instead of sending a CHANNEL message
+          const int64_t clock = m_omxplayer_mode ? GetTime() : DVD_TIME_TO_MSEC(std::min(m_CurrentAudio.dts, m_CurrentVideo.dts) + m_offset_pts);
+          CEdl::Cut cut;
+          if (m_Edl.GetNearestCut(false, clock, &cut)) 
+          {
+            m_messenger.Put(new CDVDMsgPlayerSeek(cut.start - 1, true, true, false, true, false, true));
+            return true;
+          }
+          else
+          {
+            // Go back to beginning
+            m_messenger.Put(new CDVDMsgPlayerSeek(0, true, true, false, true, false, true));
+            return true;
+          }
+        }
         bool bPreview(action.GetID() == ACTION_MOVE_DOWN && // only up/down shows a preview, all others do switch
                       CSettings::GetInstance().GetBool(CSettings::SETTING_PVRPLAYBACK_CONFIRMCHANNELSWITCH));
 
@@ -4431,9 +4485,17 @@ bool CVideoPlayer::OnAction(const CAction &action)
       CGUIDialogKaiToast::QueueNotification(g_localizeStrings.Get(25011),
                                             g_localizeStrings.Get(m_SkipCommercials ? 25013 : 25012));
       break;
-    case ACTION_SHOW_CODEC:
+    case ACTION_PLAYER_DEBUG:
       m_renderManager.ToggleDebug();
       break;
+
+    case ACTION_PLAYER_PROCESS_INFO:
+      if (g_windowManager.GetActiveWindow() != WINDOW_DIALOG_PLAYER_PROCESS_INFO)
+      {
+        g_windowManager.ActivateWindow(WINDOW_DIALOG_PLAYER_PROCESS_INFO);
+        return true;
+      }
+      break;
   }
 
   // return false to inform the caller we didn't handle the message
@@ -4826,6 +4888,23 @@ void CVideoPlayer::UpdateApplication(double timeout)
   m_UpdateApplication = m_clock.GetAbsoluteClock();
 }
 
+void CVideoPlayer::SetVolume(float nVolume)
+{
+  if (m_omxplayer_mode)
+    m_VideoPlayerAudio->SetVolume(nVolume);
+}
+
+void CVideoPlayer::SetMute(bool bOnOff)
+{
+  if (m_omxplayer_mode)
+    m_VideoPlayerAudio->SetMute(bOnOff);
+}
+
+void CVideoPlayer::SetDynamicRangeCompression(long drc)
+{
+  m_VideoPlayerAudio->SetDynamicRangeCompression(drc);
+}
+
 bool CVideoPlayer::CanRecord()
 {
   CSingleLock lock(m_StateSection);
@@ -4968,11 +5047,6 @@ bool CVideoPlayer::IsRenderingVideoLayer()
   return m_renderManager.IsVideoLayer();
 }
 
-bool CVideoPlayer::Supports(EDEINTERLACEMODE mode)
-{
-  return m_renderManager.Supports(mode);
-}
-
 bool CVideoPlayer::Supports(EINTERLACEMETHOD method)
 {
   return m_renderManager.Supports(method);
diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.h b/xbmc/cores/VideoPlayer/VideoPlayer.h
index 560b975..51ff1c5 100644
--- a/xbmc/cores/VideoPlayer/VideoPlayer.h
+++ b/xbmc/cores/VideoPlayer/VideoPlayer.h
@@ -75,7 +75,6 @@ public:
 struct SOmxPlayerState
 {
   OMXClock av_clock;              // openmax clock component
-  EDEINTERLACEMODE current_deinterlace; // whether deinterlace is currently enabled
   EINTERLACEMETHOD interlace_method; // current deinterlace method
   bool bOmxWaitVideo;             // whether we need to wait for video to play out on EOS
   bool bOmxWaitAudio;             // whether we need to wait for audio to play out on EOS
@@ -242,8 +241,7 @@ public:
   virtual bool OpenFile(const CFileItem& file, const CPlayerOptions &options);
   virtual bool CloseFile(bool reopen = false);
   virtual bool IsPlaying() const;
-  virtual void Pause();
-  virtual bool IsPaused() const;
+  virtual void Pause() override;
   virtual bool HasVideo() const;
   virtual bool HasAudio() const;
   virtual bool HasRDS() const;
@@ -255,9 +253,9 @@ public:
   virtual float GetPercentage();
   virtual float GetCachePercentage();
 
-  virtual void SetVolume(float nVolume)                         { m_VideoPlayerAudio->SetVolume(nVolume); }
-  virtual void SetMute(bool bOnOff)                             { m_VideoPlayerAudio->SetMute(bOnOff); }
-  virtual void SetDynamicRangeCompression(long drc)             { m_VideoPlayerAudio->SetDynamicRangeCompression(drc); }
+  virtual void SetVolume(float nVolume) override;
+  virtual void SetMute(bool bOnOff) override;
+  virtual void SetDynamicRangeCompression(long drc) override;
   virtual bool CanRecord();
   virtual bool IsRecording();
   virtual bool CanPause();
@@ -301,7 +299,8 @@ public:
   virtual bool SeekTimeRelative(int64_t iTime);
   virtual int64_t GetTime();
   virtual int64_t GetTotalTime();
-  virtual void ToFFRW(int iSpeed);
+  virtual void SetSpeed(int iSpeed) override;
+  virtual int GetSpeed() override;
   virtual bool OnAction(const CAction &action);
 
   virtual int GetSourceBitrate();
@@ -325,7 +324,6 @@ public:
   virtual bool IsRenderingVideo();
   virtual bool IsRenderingGuiLayer();
   virtual bool IsRenderingVideoLayer();
-  virtual bool Supports(EDEINTERLACEMODE mode);
   virtual bool Supports(EINTERLACEMETHOD method);
   virtual bool Supports(ESCALINGMETHOD method);
   virtual bool Supports(ERENDERFEATURE feature);
@@ -353,8 +351,6 @@ public:
   virtual int OnDVDNavResult(void* pData, int iMessage) override;
   void GetVideoResolution(unsigned int &width, unsigned int &height) override;
 
-  virtual bool ControlsVolume() {return m_omxplayer_mode;}
-
 protected:
   friend class CSelectionStreams;
 
@@ -398,7 +394,7 @@ protected:
    * one of the DVD_PLAYSPEED defines
    */
   void SetPlaySpeed(int iSpeed);
-  int GetPlaySpeed()                                                { return m_playSpeed; }
+  int GetPlaySpeed() { return m_playSpeed; }
   void SetCaching(ECacheState state);
 
   int64_t GetTotalTimeInMsec();
@@ -459,7 +455,8 @@ protected:
 
   CSelectionStreams m_SelectionStreams;
 
-  int m_playSpeed;
+  std::atomic_int m_playSpeed;
+  std::atomic_int m_newPlaySpeed;
   int m_streamPlayerSpeed;
   struct SSpeedState
   {
diff --git a/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp b/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp
index fb1d993..2422815 100644
--- a/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp
+++ b/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp
@@ -90,11 +90,13 @@ CVideoPlayerAudio::~CVideoPlayerAudio()
 
 bool CVideoPlayerAudio::OpenStream(CDVDStreamInfo &hints)
 {
+  m_processInfo.ResetAudioCodecInfo();
+
   CLog::Log(LOGNOTICE, "Finding audio codec for: %i", hints.codec);
   bool allowpassthrough = !CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_USEDISPLAYASCLOCK);
   if (hints.realtime)
     allowpassthrough = false;
-  CDVDAudioCodec* codec = CDVDFactoryCodec::CreateAudioCodec(hints, allowpassthrough, m_processInfo.AllowDTSHDDecode());
+  CDVDAudioCodec* codec = CDVDFactoryCodec::CreateAudioCodec(hints, m_processInfo, allowpassthrough, m_processInfo.AllowDTSHDDecode());
   if(!codec)
   {
     CLog::Log(LOGERROR, "Unsupported audio codec");
@@ -451,6 +453,11 @@ void CVideoPlayerAudio::Process()
 
           m_streaminfo.channels = audioframe.format.m_channelLayout.Count();
 
+
+          m_processInfo.SetAudioChannels(audioframe.format.m_channelLayout);
+          m_processInfo.SetAudioSampleRate(audioframe.format.m_sampleRate);
+          m_processInfo.SetAudioBitsPerSample(audioframe.bits_per_sample);
+
           m_messageParent.Put(new CDVDMsg(CDVDMsg::PLAYER_AVCHANGE));
         }
 
@@ -595,7 +602,7 @@ bool CVideoPlayerAudio::SwitchCodecIfNeeded()
   bool allowpassthrough = !CSettings::GetInstance().GetBool(CSettings::SETTING_VIDEOPLAYER_USEDISPLAYASCLOCK);
   if (m_streaminfo.realtime)
     allowpassthrough = false;
-  CDVDAudioCodec *codec = CDVDFactoryCodec::CreateAudioCodec(m_streaminfo, allowpassthrough, m_processInfo.AllowDTSHDDecode());
+  CDVDAudioCodec *codec = CDVDFactoryCodec::CreateAudioCodec(m_streaminfo, m_processInfo, allowpassthrough, m_processInfo.AllowDTSHDDecode());
   if (!codec || codec->NeedPassthrough() == m_pAudioCodec->NeedPassthrough()) {
     // passthrough state has not changed
     delete codec;
diff --git a/xbmc/cores/VideoPlayer/VideoPlayerAudio.h b/xbmc/cores/VideoPlayer/VideoPlayerAudio.h
index d1653e0..7f8197a 100644
--- a/xbmc/cores/VideoPlayer/VideoPlayerAudio.h
+++ b/xbmc/cores/VideoPlayer/VideoPlayerAudio.h
@@ -55,8 +55,6 @@ public:
   void SendMessage(CDVDMsg* pMsg, int priority = 0)     { m_messageQueue.Put(pMsg, priority); }
   void FlushMessages()                                  { m_messageQueue.Flush(); }
 
-  void SetVolume(float fVolume)                         { m_dvdAudio.SetVolume(fVolume); }
-  void SetMute(bool bOnOff)                             { }
   void SetDynamicRangeCompression(long drc)             { m_dvdAudio.SetDynamicRangeCompression(drc); }
   float GetDynamicRangeAmplification() const            { return 0.0f; }
 
diff --git a/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp b/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp
index 8e5d33d..fee65c3 100644
--- a/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp
+++ b/xbmc/cores/VideoPlayer/VideoPlayerVideo.cpp
@@ -120,6 +120,8 @@ double CVideoPlayerVideo::GetOutputDelay()
 
 bool CVideoPlayerVideo::OpenStream( CDVDStreamInfo &hint )
 {
+  m_processInfo.ResetVideoCodecInfo();
+
   CRenderInfo info;
   info = m_renderManager.GetRenderInfo();
 
@@ -156,11 +158,13 @@ void CVideoPlayerVideo::OpenStream(CDVDStreamInfo &hint, CDVDVideoCodec* codec)
   {
     m_fFrameRate = DVD_TIME_BASE / CDVDCodecUtils::NormalizeFrameduration((double)DVD_TIME_BASE * hint.fpsscale / hint.fpsrate);
     m_bFpsInvalid = false;
+    m_processInfo.SetVideoFps(m_fFrameRate);
   }
   else
   {
     m_fFrameRate = 25;
     m_bFpsInvalid = true;
+    m_processInfo.SetVideoFps(0);
   }
 
   m_pullupCorrection.ResetVFRDetection();
@@ -1023,6 +1027,7 @@ void CVideoPlayerVideo::CalcFrameRate()
         CLog::Log(LOGDEBUG,"%s framerate was:%f calculated:%f", __FUNCTION__, m_fFrameRate, m_fStableFrameRate / m_iFrameRateCount);
         m_fFrameRate = m_fStableFrameRate / m_iFrameRateCount;
         m_bFpsInvalid = false;
+        m_processInfo.SetVideoFps(m_fFrameRate);
       }
 
       //reset the stored framerates
@@ -1046,7 +1051,6 @@ int CVideoPlayerVideo::CalcDropRequirement(double pts)
   int result = 0;
   int lateframes;
   double iDecoderPts, iRenderPts;
-  double interval;
   int iSkippedPicture = -1;
   int iDroppedFrames = -1;
   int    iBufferLevel;
@@ -1073,8 +1077,6 @@ int CVideoPlayerVideo::CalcDropRequirement(double pts)
       CLog::Log(LOGDEBUG,"CVideoPlayerVideo::CalcDropRequirement - hurry: %d", iBufferLevel);
   }
 
-  interval = 1/m_fFrameRate*(double)DVD_TIME_BASE;
-
   if (m_bAllowDrop)
   {
     if (iSkippedPicture > 0)
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h b/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h
index 649a7e7..5a3157c 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h
@@ -103,7 +103,6 @@ public:
   // Feature support
   virtual bool SupportsMultiPassRendering() = 0;
   virtual bool Supports(ERENDERFEATURE feature) { return false; };
-  virtual bool Supports(EDEINTERLACEMODE mode) = 0;
   virtual bool Supports(EINTERLACEMETHOD method) = 0;
   virtual bool Supports(ESCALINGMETHOD method) = 0;
 
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/CMakeLists.txt b/xbmc/cores/VideoPlayer/VideoRenderers/CMakeLists.txt
index 4426735..6617196 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/CMakeLists.txt
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/CMakeLists.txt
@@ -1,7 +1,5 @@
-enable_language(CXX ASM)
-set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp" )
-
 set(SOURCES BaseRenderer.cpp
+            ColorManager.cpp
             OverlayRenderer.cpp
             OverlayRendererGUI.cpp
             OverlayRendererUtil.cpp
@@ -11,6 +9,7 @@ set(SOURCES BaseRenderer.cpp
             DebugRenderer.cpp)
 
 set(HEADERS BaseRenderer.h
+            ColorManager.h
             OverlayRenderer.h
             OverlayRendererGUI.h
             OverlayRendererUtil.h
@@ -51,12 +50,6 @@ if(ARCH MATCHES arm)
 endif()
 
 core_add_library(videorenderers)
-add_dependencies(videorenderers libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(videorenderers ffmpeg)
-endif()
-
 if(CORE_SYSTEM_NAME STREQUAL windows)
-  add_dependencies(videorenderers d3dx11effects)
+  add_dependencies(${CORE_LIBRARY} d3dx11effects)
 endif()
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.cpp
new file mode 100644
index 0000000..e9d8c9f
--- /dev/null
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.cpp
@@ -0,0 +1,520 @@
+/*
+ *      Copyright (C) 2016 Lauri Mylläri
+ *      http://kodi.org
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <math.h>
+#include <string>
+#include <vector>
+
+#include "system.h"
+#include "ColorManager.h"
+#include "cores/VideoPlayer/VideoRenderers/RenderFlags.h"
+#include "filesystem/File.h"
+#include "settings/Settings.h"
+#include "utils/log.h"
+#include "utils/TimeUtils.h"
+
+using namespace XFILE;
+
+CColorManager::CColorManager()
+{
+  m_curVideoPrimaries = CMS_PRIMARIES_AUTO;
+  m_curClutSize = 0;
+  m_curCmsToken = 0;
+  m_curCmsMode = 0;
+  m_cur3dlutFile = "";
+  m_curIccProfile = "";
+#if defined(HAVE_LCMS2)
+  m_hProfile = NULL;
+#endif  //defined(HAVE_LCMS2)
+}
+
+CColorManager::~CColorManager()
+{
+#if defined(HAVE_LCMS2)
+  if (m_hProfile)
+  {
+    cmsCloseProfile(m_hProfile);
+    m_hProfile = NULL;
+  }
+#endif  //defined(HAVE_LCMS2)
+}
+
+bool CColorManager::IsEnabled()
+{
+  //TODO: check that the configuration is valid here (files exist etc)
+
+  return CSettings::GetInstance().GetBool("videoscreen.cmsenabled");
+}
+
+CMS_PRIMARIES videoFlagsToPrimaries(int flags)
+{
+  if (flags & CONF_FLAGS_COLPRI_BT709)
+    return CMS_PRIMARIES_BT709;
+  if (flags & CONF_FLAGS_COLPRI_170M)
+    return CMS_PRIMARIES_170M;
+  if (flags & CONF_FLAGS_COLPRI_BT470M)
+    return CMS_PRIMARIES_BT470M;
+  if (flags & CONF_FLAGS_COLPRI_BT470BG)
+    return CMS_PRIMARIES_BT470BG;
+  if (flags & CONF_FLAGS_COLPRI_240M)
+    return CMS_PRIMARIES_240M;
+  return CMS_PRIMARIES_BT709; // default to bt.709
+}
+
+bool CColorManager::GetVideo3dLut(int videoFlags, int *cmsToken, int *clutSize, uint16_t **clutData)
+{
+  CMS_PRIMARIES videoPrimaries = videoFlagsToPrimaries(videoFlags);
+  CLog::Log(LOGDEBUG, "video primaries: %d\n", (int)videoPrimaries);
+  switch (CSettings::GetInstance().GetInt("videoscreen.cmsmode"))
+  {
+  case CMS_MODE_3DLUT:
+    CLog::Log(LOGDEBUG, "ColorManager: CMS_MODE_3DLUT\n");
+    m_cur3dlutFile = CSettings::GetInstance().GetString("videoscreen.cms3dlut");
+    if (!Load3dLut(m_cur3dlutFile, clutData, clutSize))
+      return false;
+    m_curCmsMode = CMS_MODE_3DLUT;
+    break;
+
+  case CMS_MODE_PROFILE:
+    CLog::Log(LOGDEBUG, "ColorManager: CMS_MODE_PROFILE\n");
+#if defined(HAVE_LCMS2)
+    {
+      bool changed = false;
+      // check if display profile is not loaded, or has changed
+      if (m_curIccProfile != CSettings::GetInstance().GetString("videoscreen.displayprofile"))
+      {
+        changed = true;
+        // free old profile if there is one
+        if (m_hProfile)
+          cmsCloseProfile(m_hProfile);
+        // load profile
+        m_hProfile = LoadIccDisplayProfile(CSettings::GetInstance().GetString("videoscreen.displayprofile"));
+        if (!m_hProfile)
+          return false;
+        // detect blackpoint
+        if (cmsDetectBlackPoint(&m_blackPoint, m_hProfile, INTENT_PERCEPTUAL, 0))
+        {
+          CLog::Log(LOGDEBUG, "black point: %f\n", m_blackPoint.Y);
+        }
+        m_curIccProfile = CSettings::GetInstance().GetString("videoscreen.displayprofile");
+      }
+      // create gamma curve
+      cmsToneCurve* gammaCurve;
+      m_m_curIccGammaMode = (CMS_TRC_TYPE)CSettings::GetInstance().GetInt("videoscreen.cmsgammamode");
+      m_curIccGamma = CSettings::GetInstance().GetInt("videoscreen.cmsgamma");
+      gammaCurve =
+        CreateToneCurve(m_m_curIccGammaMode, m_curIccGamma/100.0f, m_blackPoint);
+
+      // create source profile
+      m_curIccWhitePoint = (CMS_WHITEPOINT)CSettings::GetInstance().GetInt("videoscreen.cmswhitepoint");
+      m_curIccPrimaries = (CMS_PRIMARIES)CSettings::GetInstance().GetInt("videoscreen.cmsprimaries");
+      CLog::Log(LOGDEBUG, "primaries setting: %d\n", (int)m_curIccPrimaries);
+      if (m_curIccPrimaries == CMS_PRIMARIES_AUTO) m_curIccPrimaries = videoPrimaries;
+      CLog::Log(LOGDEBUG, "source profile primaries: %d\n", (int)m_curIccPrimaries);
+      cmsHPROFILE sourceProfile =
+        CreateSourceProfile(m_curIccPrimaries, gammaCurve, m_curIccWhitePoint);
+
+      // link profiles
+      // TODO: intent selection, switch output to 16 bits?
+      cmsSetAdaptationState(0.0);
+      cmsHTRANSFORM deviceLink =
+        cmsCreateTransform(sourceProfile, TYPE_RGB_FLT,
+            m_hProfile, TYPE_RGB_FLT,
+            INTENT_ABSOLUTE_COLORIMETRIC, 0);
+
+      // sample the transformation
+      *clutSize = 1 << CSettings::GetInstance().GetInt("videoscreen.cmslutsize");
+      Create3dLut(deviceLink, clutData, clutSize);
+
+      // free gamma curve, source profile and transformation
+      cmsDeleteTransform(deviceLink);
+      cmsCloseProfile(sourceProfile);
+      cmsFreeToneCurve(gammaCurve);
+    }
+
+    m_curCmsMode = CMS_MODE_PROFILE;
+    break;
+#else   //defined(HAVE_LCMS2)
+    return false;
+#endif  //defined(HAVE_LCMS2)
+
+  default:
+    CLog::Log(LOGDEBUG, "ColorManager: unknown CMS mode %d\n", CSettings::GetInstance().GetInt("videoscreen.cmsmode"));
+    return false;
+  }
+
+  // set current state
+  m_curVideoPrimaries = videoPrimaries;
+  m_curClutSize = *clutSize;
+  *cmsToken = ++m_curCmsToken;
+  return true;
+}
+
+bool CColorManager::CheckConfiguration(int cmsToken, int flags)
+{
+  if (cmsToken != m_curCmsToken)
+    return false;
+  if (m_curCmsMode != CSettings::GetInstance().GetInt("videoscreen.cmsmode"))
+    return false;   // CMS mode has changed
+  switch (m_curCmsMode)
+  {
+  case CMS_MODE_3DLUT:
+    if (m_cur3dlutFile != CSettings::GetInstance().GetString("videoscreen.cms3dlut"))
+      return false; // different 3dlut file selected
+    break;
+  case CMS_MODE_PROFILE:
+#if defined(HAVE_LCMS2)
+    if (m_curIccProfile != CSettings::GetInstance().GetString("videoscreen.displayprofile"))
+      return false; // different ICC profile selected
+    if (m_curIccWhitePoint != CSettings::GetInstance().GetInt("videoscreen.cmswhitepoint"))
+      return false; // whitepoint changed
+    {
+      CMS_PRIMARIES primaries = (CMS_PRIMARIES)CSettings::GetInstance().GetInt("videoscreen.cmsprimaries");
+      if (primaries == CMS_PRIMARIES_AUTO) primaries = videoFlagsToPrimaries(flags);
+      if (m_curIccPrimaries != primaries)
+        return false; // primaries changed
+    }
+    if (m_m_curIccGammaMode != (CMS_TRC_TYPE)CSettings::GetInstance().GetInt("videoscreen.cmsgammamode"))
+      return false; // gamma mode changed
+    if (m_curIccGamma != CSettings::GetInstance().GetInt("videoscreen.cmsgamma"))
+      return false; // effective gamma changed
+    if (m_curClutSize != 1 << CSettings::GetInstance().GetInt("videoscreen.cmslutsize"))
+      return false; // CLUT size changed
+    // TODO: check other parameters
+#else   //defined(HAVE_LCMS2)
+    return true;
+#endif  //defined(HAVE_LCMS2)
+    break;
+  default:
+    CLog::Log(LOGERROR, "%s: unexpected CMS mode: %d", __FUNCTION__, m_curCmsMode);
+    return false;
+  }
+  return true;
+}
+
+
+
+// madvr 3dlut file format support
+struct H3DLUT
+{
+  char signature[4];            // file signature; must be: '3DLT'
+  uint32_t fileVersion;         // file format version number (currently "1")
+  char programName[32];         // name of the program that created the file
+  uint64_t programVersion;      // version number of the program that created the file
+  uint32_t inputBitDepth[3];    // input bit depth per component (Y,Cb,Cr or R,G,B)
+  uint32_t inputColorEncoding;  // input color encoding standard
+  uint32_t outputBitDepth;      // output bit depth for all components (valid values are 8, 16 and 32)
+  uint32_t outputColorEncoding; // output color encoding standard
+  uint32_t parametersFileOffset;// number of bytes between the beginning of the file and array parametersData
+  uint32_t parametersSize;      // size in bytes of the array parametersData
+  uint32_t lutFileOffset;       // number of bytes between the beginning of the file and array lutData
+  uint32_t lutCompressionMethod;// type of compression used if any (0 = none, ...)
+  uint32_t lutCompressedSize;   // size in bytes of the array lutData inside the file, whether compressed or not
+  uint32_t lutUncompressedSize; // true size in bytes of the array lutData when in memory for usage (outside the file)
+  // This header is followed by the char array 'parametersData', of length 'parametersSize',
+  // and by the array 'lutDataxx', of length 'lutCompressedSize'.
+};
+
+bool CColorManager::Probe3dLut(const std::string filename)
+{
+  struct H3DLUT header;
+  CFile lutFile;
+
+  if (!lutFile.Open(filename))
+  {
+    CLog::Log(LOGERROR, "%s: Could not open 3DLUT file: %s", __FUNCTION__, filename.c_str());
+    return false;
+  }
+
+  if (lutFile.Read(&header, sizeof(header)) < sizeof(header))
+  {
+    CLog::Log(LOGERROR, "%s: Could not read 3DLUT header: %s", __FUNCTION__, filename.c_str());
+    return false;
+  }
+
+  if ( !(header.signature[0]=='3'
+        && header.signature[1]=='D'
+        && header.signature[2]=='L'
+        && header.signature[3]=='T') )
+  {
+    CLog::Log(LOGERROR, "%s: Not a 3DLUT file: %s", __FUNCTION__, filename.c_str());
+    return false;
+  }
+
+  if ( header.fileVersion != 1
+      || header.lutCompressionMethod != 0
+      || header.inputColorEncoding != 0
+      || header.outputColorEncoding != 0 )
+  {
+    CLog::Log(LOGERROR, "%s: Unsupported 3DLUT file: %s", __FUNCTION__, filename.c_str());
+    return false;
+  }
+
+  lutFile.Close();
+  return true;
+}
+
+bool CColorManager::Load3dLut(const std::string filename, uint16_t **CLUT, int *CLUTsize)
+{
+  struct H3DLUT header;
+  CFile lutFile;
+
+  if (!lutFile.Open(filename))
+  {
+    CLog::Log(LOGERROR, "%s: Could not open 3DLUT file: %s", __FUNCTION__, filename.c_str());
+    return false;
+  }
+
+  if (lutFile.Read(&header, sizeof(header)) < sizeof(header))
+  {
+    CLog::Log(LOGERROR, "%s: Could not read 3DLUT header: %s", __FUNCTION__, filename.c_str());
+    return false;
+  }
+
+  int rSize = 1 << header.inputBitDepth[0];
+  int gSize = 1 << header.inputBitDepth[1];
+  int bSize = 1 << header.inputBitDepth[2];
+
+  if ( !((rSize == gSize) && (rSize == bSize)) )
+  {
+    CLog::Log(LOGERROR, "%s: Different channel resolutions unsupported: %s", __FUNCTION__, filename.c_str());
+    return false;
+  }
+
+  int lutsamples = rSize * gSize * bSize * 3;
+  *CLUTsize = rSize; // TODO: assumes cube
+  *CLUT = (uint16_t*)malloc(lutsamples * sizeof(uint16_t));
+
+  lutFile.Seek(header.lutFileOffset, SEEK_SET);
+
+  for (int rIndex=0; rIndex<rSize; rIndex++) {
+    for (int gIndex=0; gIndex<gSize; gIndex++) {
+      std::vector<uint16_t> input(bSize*3);
+      lutFile.Read(input.data(), input.size()*sizeof(input[0]));
+      int index = (rIndex + gIndex*rSize)*3;
+      for (int bIndex=0; bIndex<bSize; bIndex++) {
+        (*CLUT)[index+bIndex*rSize*gSize*3+0] = input[bIndex*3+2];
+        (*CLUT)[index+bIndex*rSize*gSize*3+1] = input[bIndex*3+1];
+        (*CLUT)[index+bIndex*rSize*gSize*3+2] = input[bIndex*3+0];
+      }
+    }
+  }
+
+  lutFile.Close();
+
+  return true;
+}
+
+
+
+#if defined(HAVE_LCMS2)
+// ICC profile support
+
+cmsHPROFILE CColorManager::LoadIccDisplayProfile(const std::string filename)
+{
+  cmsHPROFILE hProfile;
+
+  hProfile = cmsOpenProfileFromFile(filename.c_str(), "r");
+  if (!hProfile)
+  {
+    CLog::Log(LOGERROR, "ICC profile not found\n");
+  }
+  return hProfile;
+}
+
+
+cmsToneCurve* CColorManager::CreateToneCurve(CMS_TRC_TYPE gammaType, float gammaValue, cmsCIEXYZ blackPoint)
+{
+  const int tableSize = 1024;
+  cmsFloat32Number gammaTable[tableSize];
+
+  switch (gammaType)
+  {
+  case CMS_TRC_INPUT_OFFSET:
+    // calculate gamma to match effective gamma provided, then fall through to bt.1886
+    {
+      double effectiveGamma = gammaValue;
+      double gammaLow = effectiveGamma;  // low limit for infinite contrast ratio
+      double gammaHigh = 3.2;            // high limit for 2.4 gamma on 200:1 contrast ratio
+      double gammaGuess = 0.0;
+#define TARGET(gamma) (pow(0.5, (gamma)))
+#define GAIN(bkpt, gamma) (pow(1-pow((bkpt), 1/(gamma)), (gamma)))
+#define LIFT(bkpt, gamma) (pow((bkpt), 1/(gamma)) / (1-pow((bkpt), 1/(gamma))))
+#define HALFPT(bkpt, gamma) (GAIN(bkpt, gamma)*pow(0.5+LIFT(bkpt, gamma), gamma))
+      for (int i=0; i<3; i++)
+      {
+        // calculate 50% output for gammaLow and gammaHigh, compare to target 50% output
+        gammaGuess = gammaLow + (gammaHigh-gammaLow)
+            * ((HALFPT(blackPoint.Y, gammaLow)-TARGET(effectiveGamma))
+                / (HALFPT(blackPoint.Y, gammaLow)-HALFPT(blackPoint.Y, gammaHigh)));
+        if (HALFPT(blackPoint.Y, gammaGuess) < TARGET(effectiveGamma))
+        {
+          // guess is too high
+          // move low limit half way to guess
+          gammaLow = gammaLow + (gammaGuess-gammaLow)/2;
+          // set high limit to guess
+          gammaHigh = gammaGuess;
+        }
+        else
+        {
+          // guess is too low
+          // set low limit to guess
+          gammaLow = gammaGuess;
+          // move high limit half way to guess
+          gammaHigh = gammaHigh + (gammaGuess-gammaLow)/2;
+        }
+      }
+      gammaValue = gammaGuess;
+      CLog::Log(LOGINFO, "calculated technical gamma %0.3f (50%% target %0.4f, output %0.4f)\n",
+        gammaValue,
+        TARGET(effectiveGamma),
+        HALFPT(blackPoint.Y, gammaValue));
+#undef TARGET
+#undef GAIN
+#undef LIFT
+#undef HALFPT
+    }
+    // fall through to bt.1886 with calculated technical gamma
+
+  case CMS_TRC_BT1886:
+    {
+      double bkipow = pow(blackPoint.Y, 1.0/gammaValue);
+      double wtipow = 1.0;
+      double lift = bkipow / (wtipow - bkipow);
+      double gain = pow(wtipow - bkipow, gammaValue);
+      for (int i=0; i<tableSize; i++)
+      {
+        gammaTable[i] = gain * pow(((double) i)/(tableSize-1) + lift, gammaValue);
+      }
+    }
+    break;
+
+  case CMS_TRC_OUTPUT_OFFSET:
+    {
+      double gain = 1-blackPoint.Y;
+      // TODO: here gamma is adjusted to match absolute gamma output at 50%
+      //  - is it a good idea or should the provided gamma be kept?
+      double adjustedGamma = log(gain/(gain+pow(2,-gammaValue)-1))/log(2);
+      for (int i=0; i<tableSize; i++)
+      {
+        gammaTable[i] = gain * pow(((double) i)/(tableSize-1), adjustedGamma) + blackPoint.Y;
+      }
+    }
+    break;
+
+  case CMS_TRC_ABSOLUTE:
+    {
+      for (int i=0; i<tableSize; i++)
+      {
+        gammaTable[i] = fmax(blackPoint.Y, pow(((double) i)/(tableSize-1), gammaValue));
+      }
+    }
+    break;
+
+  default:
+    CLog::Log(LOGERROR, "gamma type %d not implemented\n", gammaType);
+  }
+
+  cmsToneCurve* result = cmsBuildTabulatedToneCurveFloat(0,
+      tableSize,
+      gammaTable);
+  return result;
+}
+
+
+cmsHPROFILE CColorManager::CreateSourceProfile(CMS_PRIMARIES primaries, cmsToneCurve *gamma, CMS_WHITEPOINT whitepoint)
+{
+  cmsToneCurve*  Gamma3[3];
+  cmsHPROFILE hProfile;
+  cmsCIExyY whiteCoords[] = {
+    { 0.3127, 0.3290, 1.0 },    // D65 as specified in BT.709
+    { 0.2830, 0.2980, 1.0 }     // Japanese D93 - is there a definitive source? NHK? ARIB TR-B9?
+  };
+  cmsCIExyYTRIPLE primaryCoords[] = {
+    { 0.640, 0.330, 1.0,        // auto setting, these should not be used (BT.709 just in case)
+      0.300, 0.600, 1.0,
+      0.150, 0.060, 1.0 },
+    { 0.640, 0.330, 1.0,        // BT.709 (HDTV, sRGB)
+      0.300, 0.600, 1.0,
+      0.150, 0.060, 1.0 },
+    { 0.630, 0.340, 1.0,        // SMPTE 170M (SDTV)
+      0.310, 0.595, 1.0,
+      0.155, 0.070, 1.0 },
+    { 0.670, 0.330, 1.0,        // BT.470 M (obsolete NTSC 1953)
+      0.210, 0.710, 1.0,
+      0.140, 0.080, 1.0 },
+    { 0.640, 0.330, 1.0,        // BT.470 B/G (obsolete PAL/SECAM 1975)
+      0.290, 0.600, 1.0,
+      0.150, 0.060, 1.0 },
+    { 0.630, 0.340, 1.0,        // SMPTE 240M (obsolete HDTV 1988)
+      0.310, 0.595, 1.0,
+      0.155, 0.070, 1.0 }
+  };
+
+  Gamma3[0] = Gamma3[1] = Gamma3[2] = gamma;
+  hProfile = cmsCreateRGBProfile(&whiteCoords[whitepoint],
+      &primaryCoords[primaries],
+      Gamma3);
+  return hProfile;
+}
+
+
+void CColorManager::Create3dLut(cmsHTRANSFORM transform, uint16_t **clutData, int *clutSize)
+{
+  const int lutResolution = *clutSize;
+  int lutsamples = lutResolution * lutResolution * lutResolution * 3;
+  *clutData = (uint16_t*)malloc(lutsamples * sizeof(uint16_t));
+
+  cmsFloat32Number input[3*lutResolution];
+  cmsFloat32Number output[3*lutResolution];
+
+#define clamp(x, l, h) ( ((x) < (l)) ? (l) : ( ((x) > (h)) ? (h) : (x) ) )
+#define videoToPC(x) ( clamp((((x)*255)-16)/219,0,1) )
+#define PCToVideo(x) ( (((x)*219)+16)/255 )
+// #define videoToPC(x) ( x )
+// #define PCToVideo(x) ( x )
+  for (int bIndex=0; bIndex<lutResolution; bIndex++) {
+    for (int gIndex=0; gIndex<lutResolution; gIndex++) {
+      for (int rIndex=0; rIndex<lutResolution; rIndex++) {
+        input[rIndex*3+0] = videoToPC(rIndex / (lutResolution-1.0));
+        input[rIndex*3+1] = videoToPC(gIndex / (lutResolution-1.0));
+        input[rIndex*3+2] = videoToPC(bIndex / (lutResolution-1.0));
+      }
+      int index = (bIndex*lutResolution*lutResolution + gIndex*lutResolution)*3;
+      cmsDoTransform(transform, input, output, lutResolution);
+      for (int i=0; i<lutResolution*3; i++) {
+        (*clutData)[index+i] = PCToVideo(output[i]) * 65535;
+      }
+    }
+  }
+
+  for (int y=0; y<lutResolution; y+=1)
+  {
+    int index = 3*(y*lutResolution*lutResolution + y*lutResolution + y);
+    CLog::Log(LOGDEBUG, "  %d (%d): %d %d %d\n",
+        (int)round(y * 255 / (lutResolution-1.0)), y,
+        (int)round((*clutData)[index+0]),
+        (int)round((*clutData)[index+1]),
+        (int)round((*clutData)[index+2]));
+  }
+}
+
+
+#endif //defined(HAVE_LCMS2)
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.h b/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.h
new file mode 100644
index 0000000..98fb8ed
--- /dev/null
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/ColorManager.h
@@ -0,0 +1,165 @@
+/*
+ *      Copyright (C) 2016 Lauri Mylläri
+ *      http://kodi.org
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#if defined(HAVE_LCMS2)
+#include "lcms2.h"
+#endif
+
+#include <string>
+
+enum CMS_MODE
+{
+  CMS_MODE_3DLUT,
+  CMS_MODE_PROFILE,
+  CMS_MODE_COUNT
+};
+
+enum CMS_WHITEPOINT
+{
+  CMS_WHITEPOINT_D65,
+  CMS_WHITEPOINT_D93,
+  CMS_WHITEPOINT_COUNT
+};
+
+enum CMS_PRIMARIES
+{
+  CMS_PRIMARIES_AUTO,
+  CMS_PRIMARIES_BT709,    // HDTV
+  CMS_PRIMARIES_170M,     // SDTV
+  CMS_PRIMARIES_BT470M,   // old NTSC (1953)
+  CMS_PRIMARIES_BT470BG,  // old PAL/SECAM (1975)
+  CMS_PRIMARIES_240M,     // old HDTV (1988)
+  CMS_PRIMARIES_COUNT
+};
+
+enum CMS_TRC_TYPE
+{
+  CMS_TRC_BT1886,
+  CMS_TRC_INPUT_OFFSET,
+  CMS_TRC_OUTPUT_OFFSET,
+  CMS_TRC_ABSOLUTE,
+  CMS_TRC_COUNT
+};
+
+class CColorManager
+{
+public:
+  CColorManager();
+  virtual ~CColorManager();
+
+  /*!
+   \brief Check if user has requested color management
+   \return true on enabled, false otherwise
+   */
+  bool IsEnabled();
+
+  /*!
+   \brief Get a 3D LUT for video color correction
+   \param primaries video primaries (see CONF_FLAGS_COLPRI)
+   \param cmsToken pointer to a color manager configuration token
+   \param clutSize pointer to CLUT resolution
+   \param clutData pointer to CLUT data (caller to free memory afterwards)
+   \return true on success, false otherwise
+   */
+  bool GetVideo3dLut(int primaries, int *cmsToken, int *clutSize, uint16_t **clutData);
+
+  /*!
+   \brief Check if a 3D LUT is still valid
+   \param cmsToken pointer to a color manager configuration token
+   \param flags video renderer flags (see CONF_FLAGS_COLPRI)
+   \return true on valid, false if 3D LUT should be reloaded
+   */
+  bool CheckConfiguration(int cmsToken, int flags);
+
+private:
+  /*! \brief Check .3dlut file validity
+   \param filename full path and filename
+   \return true if the file can be loaded, false otherwise
+   */
+  bool Probe3dLut(const std::string filename);
+
+  /*! \brief Load a .3dlut file
+   \param filename full path and filename
+   \param clutSize pointer to CLUT resolution
+   \param clutData pointer to CLUT data
+   \return true on success, false otherwise
+   */
+  bool Load3dLut(const std::string filename, uint16_t **clutData, int *clutSize);
+
+
+#if defined(HAVE_LCMS2)
+  // ProbeIccDisplayProfile
+
+  // ProbeIccDeviceLink (?)
+
+
+  /* \brief Load an ICC display profile
+   \param filename full path and filename
+   \return display profile (cmsHPROFILE)
+   */
+  cmsHPROFILE LoadIccDisplayProfile(const std::string filename);
+
+  /* \brief Load an ICC device link
+   \param filename full path and filename
+   \return device link (cmsHTRANSFORM)
+   */
+  // LoadIccDeviceLink (?)
+
+
+  // create a gamma curve
+  cmsToneCurve* CreateToneCurve(CMS_TRC_TYPE gammaType, float gammaValue, cmsCIEXYZ blackPoint);
+
+  // create a source profile
+  cmsHPROFILE CreateSourceProfile(CMS_PRIMARIES primaries, cmsToneCurve *gamma, CMS_WHITEPOINT whitepoint);
+
+
+  /* \brief Create 3D LUT
+   Samples a cmsHTRANSFORM object to create a 3D LUT of specified resolution
+   \param transform cmsHTRANSFORM object to sample
+   \param resolution size of the 3D LUT to create
+   \param clut pointer to LUT data
+   */
+  void Create3dLut(cmsHTRANSFORM transform, uint16_t **clutData, int *clutSize);
+
+  // keep current display profile loaded here
+  cmsHPROFILE m_hProfile;
+  cmsCIEXYZ   m_blackPoint = { 0, 0, 0 };
+
+  // display parameters (gamma, input/output offset, primaries, whitepoint, intent?)
+  CMS_WHITEPOINT m_curIccWhitePoint;
+  CMS_PRIMARIES m_curIccPrimaries;
+  CMS_TRC_TYPE m_m_curIccGammaMode;
+  int m_curIccGamma;  // gamma multiplied by 100
+#endif // defined(HAVE_LCMS2)
+
+  // current configuration:
+  CMS_PRIMARIES m_curVideoPrimaries;
+  int m_curClutSize;
+  int m_curCmsToken;
+  // (compare the following to system settings to see if configuration is still valid)
+  int m_curCmsMode;
+  std::string m_cur3dlutFile;
+  std::string m_curIccProfile;
+
+};
+
+
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/CMakeLists.txt b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/CMakeLists.txt
index 91260dc..ed575cf 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/CMakeLists.txt
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/CMakeLists.txt
@@ -51,7 +51,3 @@ if(CORE_SYSTEM_NAME STREQUAL android)
 endif()
 
 core_add_library(videorenderers_hwdec)
-
-if(ENABLE_INTERNAL_FFMPEG AND SOURCES)
-  add_dependencies(videorenderers_hwdec ffmpeg)
-endif()
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.cpp
index 7fc9f36..bb336c3 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.cpp
@@ -34,7 +34,7 @@
 #include "settings/MediaSettings.h"
 #include "utils/Log.h"
 #include "utils/win32/memcpy_sse2.h"
-#include "win32/WIN32Util.h"
+#include "platform/win32/WIN32Util.h"
 #include "windowing/WindowingFactory.h"
 
 using namespace DXVA;
@@ -245,11 +245,6 @@ bool DXVA::CProcessorHD::IsFormatSupported(DXGI_FORMAT format, D3D11_VIDEO_PROCE
 
 bool CProcessorHD::ConfigureProcessor(unsigned int format, unsigned int extended_format)
 {
-  if (g_advancedSettings.m_DXVANoDeintProcForProgressive)
-  {
-    CLog::Log(LOGNOTICE, "%s - Auto deinterlacing mode workaround activated. Deinterlacing processor will be used only for interlaced frames.", __FUNCTION__);
-  }
-
   // check default output format DXGI_FORMAT_B8G8R8A8_UNORM (as render target)
   if (!IsFormatSupported(DXGI_FORMAT_B8G8R8A8_UNORM, D3D11_VIDEO_PROCESSOR_FORMAT_SUPPORT_OUTPUT))
     return false;
@@ -538,12 +533,6 @@ bool CProcessorHD::Render(CRect src, CRect dst, ID3D11Resource* target, ID3D11Vi
   if (!views[2])
     return false;
 
-  EDEINTERLACEMODE deinterlace_mode = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_DeinterlaceMode;
-  if (g_advancedSettings.m_DXVANoDeintProcForProgressive)
-    deinterlace_mode = (flags & RENDER_FLAG_FIELD0 || flags & RENDER_FLAG_FIELD1) ? VS_DEINTERLACEMODE_FORCE : VS_DEINTERLACEMODE_OFF;
-
-  bool progressive = deinterlace_mode == VS_DEINTERLACEMODE_OFF;
-
   RECT sourceRECT = { src.x1, src.y1, src.x2, src.y2 };
   RECT dstRECT    = { dst.x1, dst.y1, dst.x2, dst.y2 };
 
@@ -614,17 +603,6 @@ bool CProcessorHD::Render(CRect src, CRect dst, ID3D11Resource* target, ID3D11Vi
   if (flags & RENDER_FLAG_FIELD1 && flags & RENDER_FLAG_TOP)
     dxvaFrameFormat = D3D11_VIDEO_FRAME_FORMAT_INTERLACED_BOTTOM_FIELD_FIRST;
 
-  // Override the sample format when the processor doesn't need to deinterlace or when deinterlacing is forced and flags are missing.
-  if (progressive)
-  {
-    dxvaFrameFormat = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
-  }
-  else if (deinterlace_mode == VS_DEINTERLACEMODE_FORCE 
-    && dxvaFrameFormat == D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE)
-  {
-    dxvaFrameFormat = D3D11_VIDEO_FRAME_FORMAT_INTERLACED_TOP_FIELD_FIRST;
-  }
-
   bool frameProgressive = dxvaFrameFormat == D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
 
   // Progressive or Interlaced video at normal rate.
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.cpp
index cd57312..78042e6 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.cpp
@@ -35,20 +35,228 @@
 #include "xbmc/Application.h"
 #include "linux/RBP.h"
 
-#define CLASSNAME "CMMALRenderer"
+extern "C" {
+#include "libavutil/imgutils.h"
+}
 
 #define VERBOSE 0
 
-std::shared_ptr<CMMALPool> CMMALRenderer::GetPool(ERenderFormat format, AVPixelFormat pixfmt, bool opaque)
+#undef CLASSNAME
+#define CLASSNAME "CMMALPool"
+
+CMMALPool::CMMALPool(const char *component_name, bool input, uint32_t num_buffers, uint32_t buffer_size, uint32_t encoding, MMALState state)
+ :  m_input(input)
 {
-  CSingleLock lock(m_sharedSection);
-  bool formatChanged = m_format != format || m_opaque != opaque;
-  if (!m_bMMALConfigured || formatChanged)
-    m_bMMALConfigured = init_vout(format, pixfmt, opaque);
+  MMAL_STATUS_T status;
+
+  status = mmal_component_create(component_name, &m_component);
+  if (status != MMAL_SUCCESS)
+    CLog::Log(LOGERROR, "%s::%s Failed to create component %s", CLASSNAME, __func__, component_name);
+
+  MMAL_PORT_T *port = m_input ? m_component->input[0] : m_component->output[0];
+
+  // set up initial decoded frame format - may change from this
+  port->format->encoding = encoding;
+
+  status = mmal_port_parameter_set_boolean(port, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE);
+  if (status != MMAL_SUCCESS)
+    CLog::Log(LOGERROR, "%s::%s Failed to enable zero copy mode on %s (status=%x %s)", CLASSNAME, __func__, port->name, status, mmal_status_to_string(status));
+
+  status = mmal_port_format_commit(port);
+  if (status != MMAL_SUCCESS)
+    CLog::Log(LOGERROR, "%s::%s Failed to commit format for %s (status=%x %s)", CLASSNAME, __func__, port->name, status, mmal_status_to_string(status));
+
+  port->buffer_size = buffer_size;
+  port->buffer_num = std::max(num_buffers, port->buffer_num_recommended);
+
+  m_mmal_pool = mmal_port_pool_create(port, port->buffer_num, port->buffer_size);
+  m_closing = false;
+  m_mmal_format = 0;
+  m_width = 0;
+  m_height = 0;
+  m_aligned_width = 0;
+  m_aligned_height = 0;
+  m_avctx = nullptr;
+  m_dec = nullptr;
+  m_state = state;
+  if (!m_mmal_pool)
+    CLog::Log(LOGERROR, "%s::%s Failed to create pool for port %s", CLASSNAME, __func__, port->name);
+  else
+    CLog::Log(LOGDEBUG, "%s::%s Created pool %p of size %d x %d for port %s", CLASSNAME, __func__, m_mmal_pool, num_buffers, buffer_size, port->name);
+}
+
+CMMALPool::~CMMALPool()
+{
+  MMAL_STATUS_T status;
+
+  MMAL_PORT_T *port = m_input ? m_component->input[0] : m_component->output[0];
+  CLog::Log(LOGDEBUG, "%s::%s Destroying pool %p for port %s", CLASSNAME, __func__, m_mmal_pool, port->name);
+
+  if (port && port->is_enabled)
+  {
+    status = mmal_port_disable(port);
+    if (status != MMAL_SUCCESS)
+       CLog::Log(LOGERROR, "%s::%s Failed to disable port %s (status=%x %s)", CLASSNAME, __func__, port->name, status, mmal_status_to_string(status));
+  }
+
+  if (m_component && m_component->is_enabled)
+  {
+    status = mmal_component_disable(m_component);
+    if (status != MMAL_SUCCESS)
+      CLog::Log(LOGERROR, "%s::%s Failed to disable component %s (status=%x %s)", CLASSNAME, __func__, m_component->name, status, mmal_status_to_string(status));
+  }
+
+  if (m_component)
+    mmal_component_destroy(m_component);
+  m_component = nullptr;
+
+  mmal_port_pool_destroy(port, m_mmal_pool);
+  m_mmal_pool = nullptr;
+  Close();
+}
+
+void CMMALPool::Close()
+{
+  CSingleLock lock(m_section);
+
+  if (g_advancedSettings.CanLogComponent(LOGVIDEO))
+    CLog::Log(LOGDEBUG, "%s::%s - close %p", CLASSNAME, __FUNCTION__, m_mmal_pool);
+
+  m_closing = true;
+  while (!m_freeBuffers.empty())
+  {
+    CGPUMEM *gmem = m_freeBuffers.front();
+    m_freeBuffers.pop_front();
+    delete gmem;
+  }
+  assert(m_freeBuffers.empty());
+}
 
-  return m_vout_input_pool;
+CGPUMEM *CMMALPool::AllocateBuffer(uint32_t size_pic)
+{
+  CSingleLock lock(m_section);
+  CGPUMEM *gmem = nullptr;
+  while (!m_freeBuffers.empty())
+  {
+    gmem = m_freeBuffers.front();
+    m_freeBuffers.pop_front();
+    if (gmem->m_numbytes == size_pic)
+      return gmem;
+    if (g_advancedSettings.CanLogComponent(LOGVIDEO))
+      CLog::Log(LOGDEBUG, "%s::%s discarding gmem:%p size %d/%d", CLASSNAME, __FUNCTION__, gmem, gmem->m_numbytes, size_pic);
+    delete gmem;
+  }
+
+  gmem = new CGPUMEM(size_pic, true);
+  if (!gmem)
+    CLog::Log(LOGERROR, "%s::%s GCPUMEM(%d) failed", CLASSNAME, __FUNCTION__, size_pic);
+  return gmem;
 }
 
+void CMMALPool::ReleaseBuffer(CGPUMEM *gmem)
+{
+  CSingleLock lock(m_section);
+  if (m_closing)
+    delete gmem;
+  else
+    m_freeBuffers.push_back(gmem);
+}
+
+void CMMALPool::AlignedSize(AVCodecContext *avctx, uint32_t &width, uint32_t &height)
+{
+  if (!avctx)
+    return;
+  int w = width, h = height;
+  AVFrame picture;
+  int unaligned;
+  int stride_align[AV_NUM_DATA_POINTERS];
+
+  avcodec_align_dimensions2(avctx, &w, &h, stride_align);
+  // gpu requirements
+  w = (w + 31) & ~31;
+  h = (h + 15) & ~15;
+
+  do {
+    // NOTE: do not align linesizes individually, this breaks e.g. assumptions
+    // that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2
+    av_image_fill_linesizes(picture.linesize, avctx->pix_fmt, w);
+    // increase alignment of w for next try (rhs gives the lowest bit set in w)
+    w += w & ~(w - 1);
+
+    unaligned = 0;
+    for (int i = 0; i < 4; i++)
+      unaligned |= picture.linesize[i] % stride_align[i];
+  } while (unaligned);
+  width = w;
+  height = h;
+}
+
+CMMALBuffer *CMMALPool::GetBuffer(uint32_t timeout)
+{
+  MMAL_BUFFER_HEADER_T *mmal_buffer = nullptr;
+  CMMALBuffer *omvb = nullptr;
+  if (m_mmal_pool && m_mmal_pool->queue)
+    mmal_buffer = mmal_queue_timedwait(m_mmal_pool->queue, timeout);
+  if (mmal_buffer)
+  {
+    mmal_buffer_header_reset(mmal_buffer);
+    mmal_buffer->cmd = 0;
+    mmal_buffer->offset = 0;
+    mmal_buffer->flags = 0;
+
+    // ffmpeg requirements
+    uint32_t aligned_width = m_aligned_width, aligned_height = m_aligned_height;
+    AlignedSize(m_avctx, aligned_width, aligned_height);
+    if (m_dec)
+    {
+      CMMALVideoBuffer *vid = new CMMALVideoBuffer(m_dec, shared_from_this());
+      omvb = vid;
+    }
+    else
+    {
+      MMAL::CMMALYUVBuffer *yuv = new MMAL::CMMALYUVBuffer(shared_from_this(), m_mmal_format, m_width, m_height, aligned_width, aligned_height, m_size);
+      if (yuv)
+      {
+        CGPUMEM *gmem = yuv->gmem;
+        mmal_buffer->data = (uint8_t *)gmem->m_vc_handle;
+        mmal_buffer->alloc_size = gmem->m_numbytes;
+      }
+      omvb = yuv;
+    }
+    if (omvb)
+    {
+      omvb->m_rendered = false;
+      omvb->m_state = m_state;
+      mmal_buffer->user_data = omvb;
+      omvb->mmal_buffer = mmal_buffer;
+    }
+  }
+  if (timeout > 0 && (!omvb || !omvb->mmal_buffer))
+    CLog::Log(LOGERROR, "%s::%s - failed pool:%p omvb:%p mmal:%p timeout:%d", CLASSNAME, __FUNCTION__, m_mmal_pool, omvb, mmal_buffer, timeout);
+  else if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO))
+    CLog::Log(LOGDEBUG, "%s::%s - pool:%p omvb:%p mmal:%p timeout:%d", CLASSNAME, __FUNCTION__, m_mmal_pool, omvb, mmal_buffer, timeout);
+  return omvb;
+}
+
+void CMMALPool::Prime()
+{
+  CMMALBuffer *omvb;
+  if (!m_mmal_pool || !m_component)
+    return;
+  MMAL_PORT_T *port = m_input ? m_component->input[0] : m_component->output[0];
+  while (omvb = GetBuffer(0), omvb)
+  {
+    if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO))
+      CLog::Log(LOGDEBUG, "%s::%s Send buffer %p from pool %p to %s len:%d cmd:%x flags:%x", CLASSNAME, __func__, omvb->mmal_buffer, m_mmal_pool, port->name, omvb->mmal_buffer->length, omvb->mmal_buffer->cmd, omvb->mmal_buffer->flags);
+    MMAL_STATUS_T status = mmal_port_send_buffer(port, omvb->mmal_buffer);
+    if (status != MMAL_SUCCESS)
+      CLog::Log(LOGERROR, "%s::%s - Failed to send buffer %p from pool %p to %s (status=0%x %s)", CLASSNAME, __func__, omvb->mmal_buffer, m_mmal_pool, port->name, status, mmal_status_to_string(status));
+  }
+}
+
+#undef CLASSNAME
+#define CLASSNAME "CMMALRenderer"
+
 CRenderInfo CMMALRenderer::GetRenderInfo()
 {
   CSingleLock lock(m_sharedSection);
@@ -66,14 +274,10 @@ CRenderInfo CMMALRenderer::GetRenderInfo()
 
 void CMMALRenderer::vout_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
 {
-  assert(!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED));
-  buffer->flags &= ~MMAL_BUFFER_HEADER_FLAG_USER2;
-  CMMALBuffer *omvb = (CMMALBuffer *)buffer->user_data;
   if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO))
-    CLog::Log(LOGDEBUG, "%s::%s port:%p omvb:%p mmal:%p:%p len:%d cmd:%x flags:%x flight:%d", CLASSNAME, __func__, port, omvb, buffer, omvb->mmal_buffer, buffer->length, buffer->cmd, buffer->flags, m_inflight);
-  assert(buffer == omvb->mmal_buffer);
-  m_inflight--;
-  omvb->Release();
+    CLog::Log(LOGDEBUG, "%s::%s omvb:%p mmal:%p dts:%.3f pts:%.3f len:%d cmd:%x flags:%x", CLASSNAME, __func__,
+        buffer->user_data, buffer, buffer->dts*1e-6, buffer->pts*1e-6, buffer->length, buffer->cmd, buffer->flags);
+  mmal_queue_put(m_queue_process, buffer);
 }
 
 static void vout_input_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
@@ -82,161 +286,137 @@ static void vout_input_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *b
   mmal->vout_input_port_cb(port, buffer);
 }
 
-static struct {
-   uint32_t encoding;
-   AVPixelFormat pixfmt;
-} pixfmt_to_encoding_table[] =
-{
-   {MMAL_ENCODING_I420,    AV_PIX_FMT_YUV420P},
-   {MMAL_ENCODING_I422,    AV_PIX_FMT_YUV422P},
-   {MMAL_ENCODING_I420,    AV_PIX_FMT_YUVJ420P}, // FIXME
-   {MMAL_ENCODING_I422,    AV_PIX_FMT_YUVJ422P}, // FIXME
-   {MMAL_ENCODING_RGB16,   AV_PIX_FMT_RGB565},
-   {MMAL_ENCODING_RGB16,   AV_PIX_FMT_RGB565LE},
-   {MMAL_ENCODING_BGR16,   AV_PIX_FMT_BGR565},
-   {MMAL_ENCODING_RGB24,   AV_PIX_FMT_RGB24},
-   {MMAL_ENCODING_BGR24,   AV_PIX_FMT_BGR24},
-   {MMAL_ENCODING_ARGB,    AV_PIX_FMT_ARGB},
-   {MMAL_ENCODING_RGBA,    AV_PIX_FMT_RGBA},
-   {MMAL_ENCODING_ABGR,    AV_PIX_FMT_ABGR},
-   {MMAL_ENCODING_BGRA,    AV_PIX_FMT_BGRA},
-   {MMAL_ENCODING_BGRA,    AV_PIX_FMT_BGR0},
-   {MMAL_ENCODING_UNKNOWN, AV_PIX_FMT_NONE}
-};
-
-static uint32_t pixfmt_to_encoding(AVPixelFormat pixfmt)
-{
-  unsigned int i;
-  for (i = 0; pixfmt_to_encoding_table[i].encoding != MMAL_ENCODING_UNKNOWN; i++)
-    if (pixfmt_to_encoding_table[i].pixfmt == pixfmt)
-      break;
-  return pixfmt_to_encoding_table[i].encoding;
-}
-
-CMMALPool::CMMALPool(MMAL_PORT_T *input, uint32_t num_buffers, uint32_t buffer_size)
-{
-  m_input = input;
-  m_pool = mmal_port_pool_create(input, num_buffers, buffer_size);
-  if (!m_pool)
-    CLog::Log(LOGERROR, "%s::%s Failed to create pool for decoder input port", CLASSNAME, __func__);
-  else
-    CLog::Log(LOGDEBUG, "%s::%s Created pool %p of size %d x %d", CLASSNAME, __func__, m_pool, num_buffers, buffer_size);
-}
-
-CMMALPool::~CMMALPool()
-{
-  CLog::Log(LOGDEBUG, "%s::%s destroying pool (%p)", CLASSNAME, __func__, m_pool);
-  mmal_port_pool_destroy(m_input, m_pool);
-  m_pool = nullptr;
-  m_input = nullptr;
-}
-
-bool CMMALRenderer::init_vout(ERenderFormat format, AVPixelFormat pixfmt, bool opaque)
+bool CMMALRenderer::CheckConfigurationVout(uint32_t width, uint32_t height, uint32_t aligned_width, uint32_t aligned_height, uint32_t encoding)
 {
-  CSingleLock lock(m_sharedSection);
-  bool formatChanged = m_format != format || m_opaque != opaque || m_pixfmt != pixfmt;
   MMAL_STATUS_T status;
-  uint32_t encoding = pixfmt_to_encoding(pixfmt);
+  bool sizeChanged = width != m_vout_width || height != m_vout_height || aligned_width != m_vout_aligned_width || aligned_height != m_vout_aligned_height;
+  bool encodingChanged = !m_vout_input || !m_vout_input->format || encoding != m_vout_input->format->encoding;
 
-  CLog::Log(LOGDEBUG, "%s::%s configured:%d format %d->%d pixfmt %x->%x opaque %d->%d", CLASSNAME, __func__, m_bConfigured, m_format, format, m_pixfmt, pixfmt, m_opaque, opaque);
+  if (!m_vout)
+  {
+    /* Create video renderer */
+    if (g_advancedSettings.CanLogComponent(LOGVIDEO))
+      CLog::Log(LOGDEBUG, "%s::%s CreateRenderer", CLASSNAME, __func__);
 
-  if (m_bMMALConfigured && formatChanged)
-    UnInitMMAL();
+    status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &m_vout);
+    if(status != MMAL_SUCCESS)
+    {
+      CLog::Log(LOGERROR, "%s::%s Failed to create vout component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
+      return false;
+    }
 
-  if (m_bMMALConfigured || format == RENDER_FMT_BYPASS)
-    return true;
+    m_vout_input = m_vout->input[0];
 
-  if (format != RENDER_FMT_MMAL || encoding == MMAL_ENCODING_UNKNOWN)
-  {
-    CLog::Log(LOGERROR, "%s::%s Unsupported format", CLASSNAME, __func__);
-    return false;
-  }
+    status = mmal_port_parameter_set_boolean(m_vout_input, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE);
+    if (status != MMAL_SUCCESS)
+       CLog::Log(LOGERROR, "%s::%s Failed to enable zero copy mode on %s (status=%x %s)", CLASSNAME, __func__, m_vout_input->name, status, mmal_status_to_string(status));
 
-  m_format = format;
-  m_pixfmt = pixfmt;
-  m_opaque = opaque;
-
-  /* Create video renderer */
-  status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &m_vout);
-  if(status != MMAL_SUCCESS)
-  {
-    CLog::Log(LOGERROR, "%s::%s Failed to create vout component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
-    return false;
+    m_vout_input->format->type = MMAL_ES_TYPE_VIDEO;
+    if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT709)
+      m_vout_input->format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT709;
+    else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT601)
+      m_vout_input->format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT601;
+    else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_240M)
+      m_vout_input->format->es->video.color_space = MMAL_COLOR_SPACE_SMPTE240M;
   }
 
-  m_vout_input = m_vout->input[0];
-  m_vout_input->userdata = (struct MMAL_PORT_USERDATA_T *)this;
-  MMAL_ES_FORMAT_T *es_format = m_vout_input->format;
-
-  es_format->type = MMAL_ES_TYPE_VIDEO;
-  if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT709)
-    es_format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT709;
-  else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT601)
-    es_format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT601;
-  else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_240M)
-    es_format->es->video.color_space = MMAL_COLOR_SPACE_SMPTE240M;
+  if (m_vout_input && (sizeChanged || encodingChanged))
+  {
+    assert(m_vout_input != nullptr && m_vout_input->format != nullptr && m_vout_input->format->es != nullptr);
+    CLog::Log(LOGDEBUG, "%s::%s Changing Vout dimensions from %dx%d (%dx%d) to %dx%d (%dx%d) %.4s", CLASSNAME, __func__,
+        m_vout_input->format->es->video.crop.width, m_vout_input->format->es->video.crop.height,
+        m_vout_input->format->es->video.width, m_vout_input->format->es->video.height, width, height, aligned_width, aligned_height, (char *)&encoding);
 
-  es_format->es->video.crop.width = m_sourceWidth;
-  es_format->es->video.crop.height = m_sourceHeight;
-  es_format->es->video.width = m_sourceWidth;
-  es_format->es->video.height = m_sourceHeight;
+    // we need to disable port when encoding changes, but not if just resolution changes
+    if (encodingChanged && m_vout_input->is_enabled)
+    {
+      status = mmal_port_disable(m_vout_input);
+      if (status != MMAL_SUCCESS)
+      {
+        CLog::Log(LOGERROR, "%s::%s Failed to disable vout input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
+        return false;
+      }
+    }
 
-  es_format->encoding = m_opaque ? MMAL_ENCODING_OPAQUE : encoding;
+    m_vout_width = width;
+    m_vout_height = height;
+    m_vout_aligned_width = aligned_width;
+    m_vout_aligned_height = aligned_height;
 
-  status = mmal_port_parameter_set_boolean(m_vout_input, MMAL_PARAMETER_ZERO_COPY,  MMAL_TRUE);
-  if (status != MMAL_SUCCESS)
-     CLog::Log(LOGERROR, "%s::%s Failed to enable zero copy mode on %s (status=%x %s)", CLASSNAME, __func__, m_vout_input->name, status, mmal_status_to_string(status));
+    m_vout_input->format->es->video.crop.width = width;
+    m_vout_input->format->es->video.crop.height = height;
+    m_vout_input->format->es->video.width = aligned_width;
+    m_vout_input->format->es->video.height = aligned_height;
+    m_vout_input->format->encoding = encoding;
 
-  status = mmal_port_format_commit(m_vout_input);
-  if (status != MMAL_SUCCESS)
-  {
-    CLog::Log(LOGERROR, "%s::%s Failed to commit vout input format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
-    return false;
-  }
+    status = mmal_port_format_commit(m_vout_input);
+    if (status != MMAL_SUCCESS)
+    {
+      CLog::Log(LOGERROR, "%s::%s Failed to commit vout input format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
+      return false;
+    }
 
-  m_vout_input->buffer_num = std::max(m_vout_input->buffer_num_recommended, (uint32_t)m_NumYV12Buffers+(m_opaque?0:32));
-  m_vout_input->buffer_size = m_vout_input->buffer_size_recommended;
+    if (!m_vout_input->is_enabled)
+    {
+      m_vout_input->buffer_num = MMAL_NUM_OUTPUT_BUFFERS;
+      m_vout_input->buffer_size = m_vout_input->buffer_size_recommended;
+      m_vout_input->userdata = (struct MMAL_PORT_USERDATA_T *)this;
 
-  status = mmal_port_enable(m_vout_input, vout_input_port_cb_static);
-  if(status != MMAL_SUCCESS)
-  {
-    CLog::Log(LOGERROR, "%s::%s Failed to vout enable input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
-    return false;
+      status = mmal_port_enable(m_vout_input, vout_input_port_cb_static);
+      if (status != MMAL_SUCCESS)
+      {
+        CLog::Log(LOGERROR, "%s::%s Failed to enable vout input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
+        return false;
+      }
+    }
   }
 
-  status = mmal_component_enable(m_vout);
-  if(status != MMAL_SUCCESS)
+  if (m_vout && !m_vout->is_enabled)
   {
-    CLog::Log(LOGERROR, "%s::%s Failed to enable vout component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
-    return false;
-  }
+    status = mmal_component_enable(m_vout);
+    if(status != MMAL_SUCCESS)
+    {
+      CLog::Log(LOGERROR, "%s::%s Failed to enable vout component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
+      return false;
+    }
 
-  m_vout_input_pool = std::make_shared<CMMALPool>(m_vout_input, m_vout_input->buffer_num, m_opaque ? m_vout_input->buffer_size:0);
-  if (!CSettings::GetInstance().GetBool("videoplayer.usedisplayasclock"))
-  {
-    m_queue = mmal_queue_create();
-    Create();
+    if (!m_queue_render && !CSettings::GetInstance().GetBool("videoplayer.usedisplayasclock"))
+    {
+      m_queue_render = mmal_queue_create();
+      Create();
+    }
   }
   return true;
 }
 
-CMMALRenderer::CMMALRenderer() : CThread("MMALRenderer")
+CMMALRenderer::CMMALRenderer() : CThread("MMALRenderer"), m_processThread(this, "MMALProcess")
 {
   CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__);
   m_vout = NULL;
   m_vout_input = NULL;
-  m_vout_input_pool = NULL;
   memset(m_buffers, 0, sizeof m_buffers);
   m_iFlags = 0;
   m_format = RENDER_FMT_NONE;
-  m_pixfmt = AV_PIX_FMT_YUV420P;
-  m_opaque = true;
   m_bConfigured = false;
-  m_bMMALConfigured = false;
   m_iYV12RenderBuffer = 0;
-  m_inflight = 0;
-  m_queue = nullptr;
+  m_queue_render = nullptr;
+  m_queue_process = nullptr;
   m_error = 0.0;
+  m_vsync_count = ~0U;
+  m_vout_width = 0;
+  m_vout_height = 0;
+  m_vout_aligned_width = 0;
+  m_vout_aligned_height = 0;
+  m_deint = NULL;
+  m_deint_input = NULL;
+  m_deint_output = NULL;
+  m_deint_width = 0;
+  m_deint_height = 0;
+  m_deint_aligned_width = 0;
+  m_deint_aligned_height = 0;
+
+  m_queue_process = mmal_queue_create();
+  m_processThread.Create();
 }
 
 CMMALRenderer::~CMMALRenderer()
@@ -244,14 +424,27 @@ CMMALRenderer::~CMMALRenderer()
   CSingleLock lock(m_sharedSection);
   CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__);
   UnInit();
+
+  if (m_queue_process)
+    mmal_queue_put(m_queue_process, &m_quitpacket);
+
+  {
+    // leave the lock to allow other threads to exit
+    CSingleExit unlock(m_sharedSection);
+    m_processThread.StopThread();
+  }
+
+  mmal_queue_destroy(m_queue_process);
+  m_queue_process = nullptr;
 }
 
 
 void CMMALRenderer::Process()
 {
+  bool bStop = false;
   SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
   CLog::Log(LOGDEBUG, "%s::%s - starting", CLASSNAME, __func__);
-  while (!m_bStop)
+  while (!bStop)
   {
     g_RBP.WaitVsync();
     double dfps = g_graphicsContext.GetFPS();
@@ -260,32 +453,171 @@ void CMMALRenderer::Process()
     // This algorithm is basically making the decision according to Bresenham's line algorithm.  Imagine drawing a line where x-axis is display frames, and y-axis is video frames
     m_error += m_fps / dfps;
     // we may need to discard frames if queue length gets too high or video frame rate is above display frame rate
-    assert(m_queue);
-    while (mmal_queue_length(m_queue) > 2 || m_error > 1.0)
+    while (mmal_queue_length(m_queue_render) > 2 || m_error > 1.0)
     {
       if (m_error > 1.0)
         m_error -= 1.0;
-      MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(m_queue);
-      if (buffer)
+      MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(m_queue_render);
+      if (buffer == &m_quitpacket)
+        bStop = true;
+      else if (buffer)
       {
         CMMALBuffer *omvb = (CMMALBuffer *)buffer->user_data;
         assert(buffer == omvb->mmal_buffer);
-        m_inflight--;
         omvb->Release();
         if (g_advancedSettings.CanLogComponent(LOGVIDEO))
-          CLog::Log(LOGDEBUG, "%s::%s - discard buffer:%p vsync:%d queue:%d diff:%f", CLASSNAME, __func__, buffer, g_RBP.LastVsync(), mmal_queue_length(m_queue), m_error);
+          CLog::Log(LOGDEBUG, "%s::%s - discard buffer:%p vsync:%d queue:%d diff:%f", CLASSNAME, __func__, buffer, g_RBP.LastVsync(), mmal_queue_length(m_queue_render), m_error);
       }
     }
     // this is case where we would like to display a new frame
     if (m_error > 0.0)
     {
       m_error -= 1.0;
-      MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(m_queue);
-      if (buffer)
-        mmal_port_send_buffer(m_vout_input, buffer);
+      MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(m_queue_render);
+      if (buffer == &m_quitpacket)
+        bStop = true;
+      else if (buffer)
+      {
+        CMMALBuffer *omvb = (CMMALBuffer *)buffer->user_data;
+        assert(buffer == omvb->mmal_buffer);
+        CheckConfigurationVout(omvb->m_width, omvb->m_height, omvb->m_aligned_width, omvb->m_aligned_height, omvb->m_encoding);
+        MMAL_STATUS_T status = mmal_port_send_buffer(m_vout_input, buffer);
+        if (status != MMAL_SUCCESS)
+          CLog::Log(LOGERROR, "%s::%s - Failed to send buffer %p to %s (status=0%x %s)", CLASSNAME, __func__, buffer, m_vout_input->name, status, mmal_status_to_string(status));
+      }
       if (g_advancedSettings.CanLogComponent(LOGVIDEO))
-        CLog::Log(LOGDEBUG, "%s::%s - buffer:%p vsync:%d queue:%d diff:%f", CLASSNAME, __func__, buffer, g_RBP.LastVsync(), mmal_queue_length(m_queue), m_error);
+        CLog::Log(LOGDEBUG, "%s::%s - buffer:%p vsync:%d queue:%d diff:%f", CLASSNAME, __func__, buffer, g_RBP.LastVsync(), mmal_queue_length(m_queue_render), m_error);
+    }
+  }
+  CLog::Log(LOGDEBUG, "%s::%s - stopping", CLASSNAME, __func__);
+}
+
+void CMMALRenderer::Run()
+{
+  CLog::Log(LOGDEBUG, "%s::%s - starting", CLASSNAME, __func__);
+  while (1)
+  {
+    bool prime = false;
+    MMAL_BUFFER_HEADER_T *buffer = mmal_queue_wait(m_queue_process);
+    assert(buffer);
+    if (buffer == &m_quitpacket)
+      break;
+    CSingleLock lock(m_sharedSection);
+    bool kept = false;
+
+    CMMALBuffer *omvb = (CMMALBuffer *)buffer->user_data;
+    if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO))
+      CLog::Log(LOGDEBUG, "%s::%s %s omvb:%p mmal:%p dts:%.3f pts:%.3f len:%d cmd:%x flags:%x encoding:%.4s", CLASSNAME, __func__,
+         omvb ? omvb->GetStateName():"", omvb, buffer, buffer->dts*1e-6, buffer->pts*1e-6, buffer->length, buffer->cmd, buffer->flags, omvb ? (char *)&omvb->m_encoding:"");
+
+    assert(omvb && buffer == omvb->mmal_buffer);
+    assert(buffer->cmd == 0);
+    assert(!(buffer->flags & (MMAL_BUFFER_HEADER_FLAG_EOS | MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED)));
+    if (m_bConfigured)
+    switch (omvb->m_state)
+    {
+    case MMALStateHWDec:
+    case MMALStateFFDec:
+    {
+      if (buffer->length > 0)
+      {
+        EINTERLACEMETHOD interlace_method = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod;
+        if (interlace_method == VS_INTERLACEMETHOD_AUTO)
+          interlace_method = AutoInterlaceMethod();
+        bool interlace = (omvb->mmal_buffer->flags & MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED) ? true:false;
+        // we don't keep up when running at 60fps in the background so switch to half rate
+        if (!g_graphicsContext.IsFullScreenVideo())
+        {
+          if (interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED)
+            interlace_method = VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF;
+          if (interlace_method == VS_INTERLACEMETHOD_MMAL_BOB)
+            interlace_method = VS_INTERLACEMETHOD_MMAL_BOB_HALF;
+        }
+
+        if (interlace_method == VS_INTERLACEMETHOD_NONE)
+        {
+          if (m_deint_input)
+            DestroyDeinterlace();
+        }
+        else if (m_deint_input || interlace)
+          CheckConfigurationDeint(omvb->m_width, omvb->m_height, omvb->m_aligned_width, omvb->m_aligned_height, omvb->m_encoding, interlace_method);
+
+        if (m_deint_input)
+        {
+          MMAL_STATUS_T status = mmal_port_send_buffer(m_deint_input, omvb->mmal_buffer);
+          if (status != MMAL_SUCCESS)
+            CLog::Log(LOGERROR, "%s::%s - Failed to send buffer %p to %s (status=0%x %s)", CLASSNAME, __func__, omvb->mmal_buffer, m_deint_input->name, status, mmal_status_to_string(status));
+          else
+            kept = true;
+        }
+        else if (m_queue_render)
+        {
+          mmal_queue_put(m_queue_render, omvb->mmal_buffer);
+          kept = true;
+        }
+        else
+        {
+          CheckConfigurationVout(omvb->m_width, omvb->m_height, omvb->m_aligned_width, omvb->m_aligned_height, omvb->m_encoding);
+          if (m_vout_input)
+          {
+            MMAL_STATUS_T status = mmal_port_send_buffer(m_vout_input, omvb->mmal_buffer);
+            if (status != MMAL_SUCCESS)
+              CLog::Log(LOGERROR, "%s::%s - Failed to send buffer %p to %s (status=0%x %s)", CLASSNAME, __func__, omvb->mmal_buffer, m_vout_input->name, status, mmal_status_to_string(status));
+            else
+              kept = true;
+          }
+        }
+      }
+      break;
     }
+    case MMALStateDeint:
+    {
+      if (buffer->length > 0)
+      {
+        if (m_queue_render)
+        {
+          mmal_queue_put(m_queue_render, buffer);
+          CLog::Log(LOGDEBUG, "%s::%s send %p to m_queue_render", CLASSNAME, __func__, omvb);
+          kept = true;
+        }
+        else
+        {
+          CheckConfigurationVout(omvb->m_width, omvb->m_height, omvb->m_aligned_width, omvb->m_aligned_height, omvb->m_encoding);
+          if (m_vout_input)
+          {
+            CLog::Log(LOGDEBUG, "%s::%s send %p to m_vout_input", CLASSNAME, __func__, omvb);
+            MMAL_STATUS_T status = mmal_port_send_buffer(m_vout_input, buffer);
+            if (status != MMAL_SUCCESS)
+              CLog::Log(LOGERROR, "%s::%s - Failed to send buffer %p to %s (status=0%x %s)", CLASSNAME, __func__, buffer, m_vout_input->name, status, mmal_status_to_string(status));
+            else
+              kept = true;
+          }
+        }
+      }
+      else
+      {
+        prime = true;
+      }
+      break;
+    }
+    default: assert(0); break;
+    }
+    if (!kept)
+    {
+      if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO))
+        CLog::Log(LOGDEBUG, "%s::%s %s Not kept: omvb:%p mmal:%p dts:%.3f pts:%.3f len:%d cmd:%x flags:%x encoding:%.4s", CLASSNAME, __func__,
+          omvb ? omvb->GetStateName():"", omvb, buffer, buffer->dts*1e-6, buffer->pts*1e-6, buffer->length, buffer->cmd, buffer->flags, omvb ? (char *)&omvb->m_encoding:"");
+      if (omvb)
+        omvb->Release();
+      else
+      {
+        mmal_buffer_header_reset(buffer);
+        buffer->cmd = 0;
+        mmal_buffer_header_release(buffer);
+      }
+    }
+    if (prime && m_deint_output_pool)
+     m_deint_output_pool->Prime();
   }
   CLog::Log(LOGDEBUG, "%s::%s - stopping", CLASSNAME, __func__);
 }
@@ -334,10 +666,9 @@ bool CMMALRenderer::Configure(unsigned int width, unsigned int height, unsigned
   SetViewMode(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ViewMode);
   ManageRenderArea();
 
-  m_bMMALConfigured = init_vout(format, m_pixfmt, m_opaque);
-  m_bConfigured = m_bMMALConfigured;
-  assert(m_bConfigured);
-  return m_bConfigured;
+  m_format = format;
+  m_bConfigured = true;
+  return true;
 }
 
 int CMMALRenderer::GetImage(YV12Image *image, int source, bool readonly)
@@ -345,18 +676,18 @@ int CMMALRenderer::GetImage(YV12Image *image, int source, bool readonly)
   if (!image || source < 0 || m_format != RENDER_FMT_MMAL)
   {
     if (g_advancedSettings.CanLogComponent(LOGVIDEO))
-      CLog::Log(LOGDEBUG, "%s::%s - invalid: format:%d image:%p source:%d ro:%d flight:%d", CLASSNAME, __func__, m_format, image, source, readonly, m_inflight);
+      CLog::Log(LOGDEBUG, "%s::%s - invalid: format:%d image:%p source:%d ro:%d", CLASSNAME, __func__, m_format, image, source, readonly);
     return -1;
   }
   if (g_advancedSettings.CanLogComponent(LOGVIDEO))
-    CLog::Log(LOGDEBUG, "%s::%s - MMAL: image:%p source:%d ro:%d flight:%d", CLASSNAME, __func__, image, source, readonly, m_inflight);
+    CLog::Log(LOGDEBUG, "%s::%s - MMAL: image:%p source:%d ro:%d", CLASSNAME, __func__, image, source, readonly);
   return source;
 }
 
 void CMMALRenderer::ReleaseBuffer(int idx)
 {
   CSingleLock lock(m_sharedSection);
-  if (!m_bMMALConfigured || m_format != RENDER_FMT_MMAL)
+  if (m_format != RENDER_FMT_MMAL)
   {
     if (g_advancedSettings.CanLogComponent(LOGVIDEO))
       CLog::Log(LOGDEBUG, "%s::%s - not configured: source:%d", CLASSNAME, __func__, idx);
@@ -365,7 +696,7 @@ void CMMALRenderer::ReleaseBuffer(int idx)
 
   CMMALBuffer *omvb = m_buffers[idx];
   if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO))
-    CLog::Log(LOGDEBUG, "%s::%s - MMAL: source:%d omvb:%p mmal:%p flight:%d", CLASSNAME, __func__, idx, omvb, omvb ? omvb->mmal_buffer:NULL, m_inflight);
+    CLog::Log(LOGDEBUG, "%s::%s - MMAL: source:%d omvb:%p mmal:%p", CLASSNAME, __func__, idx, omvb, omvb ? omvb->mmal_buffer:NULL);
   if (omvb)
     SAFE_RELEASE(m_buffers[idx]);
 }
@@ -410,7 +741,7 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
     omvb = m_buffers[source];
 
   // we only want to upload frames once
-  if (omvb && omvb->mmal_buffer && omvb->mmal_buffer->flags & MMAL_BUFFER_HEADER_FLAG_USER1)
+  if (omvb && omvb->m_rendered)
   {
     if (g_advancedSettings.CanLogComponent(LOGVIDEO))
       CLog::Log(LOGDEBUG, "%s::%s - MMAL: clear:%d flags:%x alpha:%d source:%d omvb:%p mmal:%p mflags:%x skipping", CLASSNAME, __func__, clear, flags, alpha, source, omvb, omvb->mmal_buffer, omvb->mmal_buffer->flags);
@@ -429,42 +760,32 @@ void CMMALRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
 
   if (omvb && omvb->mmal_buffer)
   {
+    if (flags & RENDER_FLAG_TOP)
+      omvb->mmal_buffer->flags |= MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED | MMAL_BUFFER_HEADER_VIDEO_FLAG_TOP_FIELD_FIRST;
+    else if (flags & RENDER_FLAG_BOT)
+      omvb->mmal_buffer->flags |= MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED;
     if (g_advancedSettings.CanLogComponent(LOGVIDEO))
-      CLog::Log(LOGDEBUG, "%s::%s - MMAL: clear:%d flags:%x alpha:%d source:%d omvb:%p mmal:%p mflags:%x", CLASSNAME, __func__, clear, flags, alpha, source, omvb, omvb->mmal_buffer, omvb->mmal_buffer->flags);
-    // check for changes in aligned sizes
-    if (omvb->m_width != (uint32_t)m_vout_input->format->es->video.crop.width || omvb->m_height != (uint32_t)m_vout_input->format->es->video.crop.height ||
-        omvb->m_aligned_width != m_vout_input->format->es->video.width || omvb->m_aligned_height != m_vout_input->format->es->video.height)
-    {
-      CLog::Log(LOGDEBUG, "%s::%s Changing dimensions from %dx%d (%dx%d) to %dx%d (%dx%d)", CLASSNAME, __func__,
-          m_vout_input->format->es->video.crop.width, m_vout_input->format->es->video.crop.height, omvb->m_width, omvb->m_height,
-          m_vout_input->format->es->video.width, m_vout_input->format->es->video.height, omvb->m_aligned_width, omvb->m_aligned_height);
-      m_vout_input->format->es->video.width = omvb->m_aligned_width;
-      m_vout_input->format->es->video.height = omvb->m_aligned_height;
-      m_vout_input->format->es->video.crop.width = omvb->m_width;
-      m_vout_input->format->es->video.crop.height = omvb->m_height;
-      MMAL_STATUS_T status = mmal_port_format_commit(m_vout_input);
-      if (status != MMAL_SUCCESS)
-      {
-        CLog::Log(LOGERROR, "%s::%s Failed to commit vout input format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
-        goto exit;
-      }
-    }
-    m_inflight++;
+      CLog::Log(LOGDEBUG, "%s::%s - MMAL: clear:%d flags:%x alpha:%d source:%d omvb:%p mmal:%p mflags:%x encoding:%.4s", CLASSNAME, __func__, clear, flags, alpha, source, omvb, omvb->mmal_buffer, omvb->mmal_buffer->flags, (char *)&omvb->m_encoding);
     assert(omvb->mmal_buffer && omvb->mmal_buffer->data && omvb->mmal_buffer->length);
     omvb->Acquire();
-    omvb->mmal_buffer->flags |= MMAL_BUFFER_HEADER_FLAG_USER1 | MMAL_BUFFER_HEADER_FLAG_USER2;
-    omvb->mmal_buffer->user_data = omvb;
-    if (m_queue && m_fps > 0.0f)
-      mmal_queue_put(m_queue, omvb->mmal_buffer);
-    else
-      mmal_port_send_buffer(m_vout_input, omvb->mmal_buffer);
+    omvb->m_rendered = true;
+    assert(omvb->mmal_buffer->user_data == omvb);
+    mmal_queue_put(m_queue_process, omvb->mmal_buffer);
   }
   else
     CLog::Log(LOGDEBUG, "%s::%s - MMAL: No buffer to update clear:%d flags:%x alpha:%d source:%d omvb:%p mmal:%p", CLASSNAME, __func__, clear, flags, alpha, source, omvb, omvb ? omvb->mmal_buffer : nullptr);
 
 exit:
    lock.Leave();
-   g_RBP.WaitVsync();
+   uint32_t v = g_RBP.WaitVsync(m_vsync_count);
+   // allow a frame of slop
+   if (m_vsync_count == ~0U || !(v == m_vsync_count))
+   {
+     CLog::Log(LOGDEBUG, "%s::%s - vsync %d (+%d)", CLASSNAME, __func__, m_vsync_count, v - m_vsync_count);
+     m_vsync_count = v + 1;
+   }
+   else
+     m_vsync_count++;
 }
 
 void CMMALRenderer::FlipPage(int source)
@@ -512,14 +833,20 @@ void CMMALRenderer::ReleaseBuffers()
 
 void CMMALRenderer::UnInitMMAL()
 {
-  CSingleLock lock(m_sharedSection);
-  CLog::Log(LOGDEBUG, "%s::%s pool(%p)", CLASSNAME, __func__, m_vout_input_pool ? m_vout_input_pool->Get() : nullptr);
-  if (m_queue)
+  CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__);
+
+  if (m_queue_render)
   {
-    StopThread(true);
-    mmal_queue_destroy(m_queue);
-    m_queue = nullptr;
+    mmal_queue_put(m_queue_render, &m_quitpacket);
+    {
+      // leave the lock to allow other threads to exit
+      CSingleExit unlock(m_sharedSection);
+      StopThread(true);
+    }
+    mmal_queue_destroy(m_queue_render);
+    m_queue_render = nullptr;
   }
+
   if (m_vout)
   {
     mmal_component_disable(m_vout);
@@ -533,8 +860,6 @@ void CMMALRenderer::UnInitMMAL()
 
   ReleaseBuffers();
 
-  m_vout_input_pool = NULL;
-
   m_vout_input = NULL;
 
   if (m_vout)
@@ -548,15 +873,19 @@ void CMMALRenderer::UnInitMMAL()
   m_video_stereo_mode = RENDER_STEREO_MODE_OFF;
   m_display_stereo_mode = RENDER_STEREO_MODE_OFF;
   m_StereoInvert = false;
-  m_format = RENDER_FMT_NONE;
-
-  m_bConfigured = false;
-  m_bMMALConfigured = false;
+  m_vout_width = 0;
+  m_vout_height = 0;
+  m_vout_aligned_width = 0;
+  m_vout_aligned_height = 0;
 }
 
 void CMMALRenderer::UnInit()
 {
+  CSingleLock lock(m_sharedSection);
+  m_bConfigured = false;
+  DestroyDeinterlace();
   UnInitMMAL();
+  m_format = RENDER_FMT_NONE;
 }
 
 bool CMMALRenderer::RenderCapture(CRenderCapture* capture)
@@ -576,16 +905,6 @@ bool CMMALRenderer::RenderCapture(CRenderCapture* capture)
 // YV12 Texture creation, deletion, copying + clearing
 //********************************************************************************************************
 
-bool CMMALRenderer::Supports(EDEINTERLACEMODE mode)
-{
-  if(mode == VS_DEINTERLACEMODE_OFF
-  || mode == VS_DEINTERLACEMODE_AUTO
-  || mode == VS_DEINTERLACEMODE_FORCE)
-    return true;
-
-  return false;
-}
-
 bool CMMALRenderer::Supports(EINTERLACEMETHOD method)
 {
   if (method == VS_INTERLACEMETHOD_AUTO)
@@ -621,7 +940,7 @@ bool CMMALRenderer::Supports(ESCALINGMETHOD method)
 
 EINTERLACEMETHOD CMMALRenderer::AutoInterlaceMethod()
 {
-  return m_sourceWidth * m_sourceHeight <= 576 * 720 ? VS_INTERLACEMETHOD_MMAL_ADVANCED : VS_INTERLACEMETHOD_MMAL_BOB;
+  return VS_INTERLACEMETHOD_MMAL_ADVANCED;
 }
 
 void CMMALRenderer::SetVideoRect(const CRect& InSrcRect, const CRect& InDestRect)
@@ -645,11 +964,30 @@ void CMMALRenderer::SetVideoRect(const CRect& InSrcRect, const CRect& InDestRect
   // fix up transposed video
   if (m_renderOrientation == 90 || m_renderOrientation == 270)
   {
-    float diff = (DestRect.Height() - DestRect.Width()) * 0.5f;
-    DestRect.x1 -= diff;
-    DestRect.x2 += diff;
-    DestRect.y1 += diff;
-    DestRect.y2 -= diff;
+    float newWidth, newHeight;
+    float aspectRatio = GetAspectRatio();
+    // clamp width if too wide
+    if (DestRect.Height() > DestRect.Width())
+    {
+      newWidth = DestRect.Width(); // clamp to the width of the old dest rect
+      newHeight = newWidth * aspectRatio;
+    }
+    else // else clamp to height
+    {
+      newHeight = DestRect.Height(); // clamp to the height of the old dest rect
+      newWidth = newHeight / aspectRatio;
+    }
+
+    // calculate the center point of the view and offsets
+    float centerX = DestRect.x1 + DestRect.Width() * 0.5f;
+    float centerY = DestRect.y1 + DestRect.Height() * 0.5f;
+    float diffX = newWidth * 0.5f;
+    float diffY = newHeight * 0.5f;
+
+    DestRect.x1 = centerX - diffX;
+    DestRect.x2 = centerX + diffX;
+    DestRect.y1 = centerY - diffY;
+    DestRect.y2 = centerY + diffY;
   }
 
   // check if destination rect or video view mode has changed
@@ -741,3 +1079,237 @@ void CMMALRenderer::SetVideoRect(const CRect& InSrcRect, const CRect& InDestRect
       region.src_rect.x, region.src_rect.y, region.src_rect.width, region.src_rect.height,
       region.dest_rect.x, region.dest_rect.y, region.dest_rect.width, region.dest_rect.height, region.transform);
 }
+
+void CMMALRenderer::deint_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
+{
+  if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO))
+    CLog::Log(LOGDEBUG, "%s::%s omvb:%p mmal:%p dts:%.3f pts:%.3f len:%d cmd:%x flags:%x", CLASSNAME, __func__,
+        buffer->user_data, buffer, buffer->dts*1e-6, buffer->pts*1e-6, buffer->length, buffer->cmd, buffer->flags);
+  mmal_queue_put(m_queue_process, buffer);
+}
+
+static void deint_input_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
+{
+  CMMALRenderer *mmal = reinterpret_cast<CMMALRenderer*>(port->userdata);
+  mmal->deint_input_port_cb(port, buffer);
+}
+
+void CMMALRenderer::deint_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
+{
+  if (VERBOSE && g_advancedSettings.CanLogComponent(LOGVIDEO))
+    CLog::Log(LOGDEBUG, "%s::%s omvb:%p mmal:%p dts:%.3f pts:%.3f len:%d cmd:%x flags:%x", CLASSNAME, __func__,
+        buffer->user_data, buffer, buffer->dts*1e-6, buffer->pts*1e-6, buffer->length, buffer->cmd, buffer->flags);
+  mmal_queue_put(m_queue_process, buffer);
+}
+
+static void deint_output_port_cb_static(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
+{
+  CMMALRenderer *mmal = reinterpret_cast<CMMALRenderer*>(port->userdata);
+  mmal->deint_output_port_cb(port, buffer);
+}
+
+void CMMALRenderer::DestroyDeinterlace()
+{
+  MMAL_STATUS_T status;
+
+  if (g_advancedSettings.CanLogComponent(LOGVIDEO))
+    CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__);
+
+  // (lazily) destroy pool first so new buffers aren't allocated when flushing
+  m_deint_output_pool = nullptr;
+
+  if (m_deint_input && m_deint_input->is_enabled)
+  {
+    status = mmal_port_disable(m_deint_input);
+    if (status != MMAL_SUCCESS)
+      CLog::Log(LOGERROR, "%s::%s Failed to disable deinterlace input port(status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
+  }
+  m_deint_input = nullptr;
+  if (m_deint_output && m_deint_output->is_enabled)
+  {
+    status = mmal_port_disable(m_deint_output);
+    if (status != MMAL_SUCCESS)
+      CLog::Log(LOGERROR, "%s::%s Failed to disable deinterlace output port(status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
+  }
+  m_deint_output = nullptr;
+  m_interlace_method = VS_INTERLACEMETHOD_NONE;
+  m_deint_width = 0;
+  m_deint_height = 0;
+  m_deint_aligned_width = 0;
+  m_deint_aligned_height = 0;
+  m_deint = nullptr;
+}
+
+bool CMMALRenderer::CheckConfigurationDeint(uint32_t width, uint32_t height, uint32_t aligned_width, uint32_t aligned_height, uint32_t encoding, EINTERLACEMETHOD interlace_method)
+{
+  MMAL_STATUS_T status;
+  bool sizeChanged = width != m_deint_width || height != m_deint_height || aligned_width != m_deint_aligned_width || aligned_height != m_deint_aligned_height;
+  bool deinterlaceChanged = interlace_method != m_interlace_method;
+  bool encodingChanged = !m_deint_input || !m_deint_input->format || m_deint_input->format->encoding != encoding;
+  bool advanced_deinterlace = interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED || interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF;
+  bool half_framerate = interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF || interlace_method == VS_INTERLACEMETHOD_MMAL_BOB_HALF;
+
+  if (!m_bConfigured)
+  {
+    CLog::Log(LOGDEBUG, "%s::%s Unconfigured", CLASSNAME, __func__);
+    return false;
+  }
+
+  if (!m_deint)
+  {
+    if (g_advancedSettings.CanLogComponent(LOGVIDEO))
+      CLog::Log(LOGDEBUG, "%s::%s CreateDeinterlace", CLASSNAME, __func__);
+
+    /* Create deinterlace component with attached pool */
+    m_deint_output_pool = std::make_shared<CMMALPool>("vc.ril.image_fx", false, 3, 0, MMAL_ENCODING_I420, MMALStateDeint);
+    if (!m_deint_output_pool)
+    {
+      CLog::Log(LOGERROR, "%s::%s Failed to create pool for deint output", CLASSNAME, __func__);
+      return false;
+    }
+
+    m_deint = m_deint_output_pool->GetComponent();
+    m_deint_output = m_deint->output[0];
+    m_deint_input = m_deint->input[0];
+
+    status = mmal_port_parameter_set_boolean(m_deint_input, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE);
+    if (status != MMAL_SUCCESS)
+      CLog::Log(LOGERROR, "%s::%s Failed to enable zero copy mode on %s (status=%x %s)", CLASSNAME, __func__, m_deint_input->name, status, mmal_status_to_string(status));
+  }
+
+  if (m_deint_input && (sizeChanged || deinterlaceChanged || encodingChanged))
+  {
+    assert(m_deint_input != nullptr && m_deint_input->format != nullptr && m_deint_input->format->es != nullptr);
+    CLog::Log(LOGDEBUG, "%s::%s Changing Deint dimensions from %dx%d (%dx%d) to %dx%d (%dx%d) %.4s->%.4s mode %d->%d", CLASSNAME, __func__,
+        m_deint_input->format->es->video.crop.width, m_deint_input->format->es->video.crop.height,
+        m_deint_input->format->es->video.width, m_deint_input->format->es->video.height, width, height, aligned_width, aligned_height,
+        (char *)&m_deint_input->format->encoding, (char *)&encoding, m_interlace_method, interlace_method);
+
+    // we need to disable port when parameters change
+    if (m_deint_input && m_deint_input->is_enabled)
+    {
+      status = mmal_port_disable(m_deint_input);
+      if (status != MMAL_SUCCESS)
+      {
+        CLog::Log(LOGERROR, "%s::%s Failed to disable deint input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
+        return false;
+      }
+    }
+  }
+
+  if (m_deint_output && (sizeChanged || deinterlaceChanged || encodingChanged))
+  {
+    if (m_deint_output && m_deint_output->is_enabled)
+    {
+      status = mmal_port_disable(m_deint_output);
+      if (status != MMAL_SUCCESS)
+      {
+        CLog::Log(LOGERROR, "%s::%s Failed to disable deint output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
+        return false;
+      }
+    }
+  }
+
+  if (m_deint_input && (sizeChanged || deinterlaceChanged || encodingChanged))
+  {
+    m_deint_width = width;
+    m_deint_height = height;
+    m_deint_aligned_width = aligned_width;
+    m_deint_aligned_height = aligned_height;
+
+    m_deint_input->format->es->video.crop.width = width;
+    m_deint_input->format->es->video.crop.height = height;
+    m_deint_input->format->es->video.width = aligned_width;
+    m_deint_input->format->es->video.height = aligned_height;
+    m_deint_input->format->encoding = encoding;
+
+    status = mmal_port_format_commit(m_deint_input);
+    if (status != MMAL_SUCCESS)
+    {
+      CLog::Log(LOGERROR, "%s::%s Failed to commit deint input format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
+      return false;
+    }
+
+    if (!m_deint_input->is_enabled)
+    {
+      m_deint_input->buffer_num = MMAL_NUM_OUTPUT_BUFFERS;
+      m_deint_input->buffer_size = m_deint_input->buffer_size_recommended;
+      m_deint_input->userdata = (struct MMAL_PORT_USERDATA_T *)this;
+
+      status = mmal_port_enable(m_deint_input, deint_input_port_cb_static);
+      if (status != MMAL_SUCCESS)
+      {
+        CLog::Log(LOGERROR, "%s::%s Failed to enable deint input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
+        return false;
+      }
+    }
+  }
+
+  if (m_deint_output && (sizeChanged || deinterlaceChanged || encodingChanged))
+  {
+    MMAL_PARAMETER_IMAGEFX_PARAMETERS_T imfx_param = {{MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, sizeof(imfx_param)},
+          advanced_deinterlace ? MMAL_PARAM_IMAGEFX_DEINTERLACE_ADV : MMAL_PARAM_IMAGEFX_DEINTERLACE_FAST, 4, {3, 0, half_framerate, 1 }};
+
+    status = mmal_port_parameter_set(m_deint_output, &imfx_param.hdr);
+    if (status != MMAL_SUCCESS)
+    {
+      CLog::Log(LOGERROR, "%s::%s Failed to set deinterlace parameters (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
+      return false;
+    }
+
+    // Image_fx assumed 3 frames of context. simple deinterlace doesn't require this
+    status = mmal_port_parameter_set_uint32(m_deint_input, MMAL_PARAMETER_EXTRA_BUFFERS, 6 - 5 + advanced_deinterlace ? 2:0);
+    if (status != MMAL_SUCCESS)
+      CLog::Log(LOGERROR, "%s::%s Failed to enable extra buffers on %s (status=%x %s)", CLASSNAME, __func__, m_deint_input->name, status, mmal_status_to_string(status));
+  }
+
+  if (m_deint_output && (sizeChanged || deinterlaceChanged || encodingChanged))
+  {
+    m_deint_output->format->es->video.crop.width = width;
+    m_deint_output->format->es->video.crop.height = height;
+    m_deint_output->format->es->video.width = ALIGN_UP(width, 32);
+    m_deint_output->format->es->video.height = ALIGN_UP(height, 16);
+    m_deint_output->format->encoding = advanced_deinterlace ? MMAL_ENCODING_YUVUV128 : MMAL_ENCODING_I420;
+
+    status = mmal_port_format_commit(m_deint_output);
+    if (status != MMAL_SUCCESS)
+    {
+      CLog::Log(LOGERROR, "%s::%s Failed to commit deint output format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
+      return false;
+    }
+
+    if (!m_deint_output->is_enabled)
+    {
+      m_deint_output->buffer_num = 3;
+      m_deint_output->buffer_size = m_deint_output->buffer_size_recommended;
+      m_deint_output->userdata = (struct MMAL_PORT_USERDATA_T *)this;
+
+      status = mmal_port_enable(m_deint_output, deint_output_port_cb_static);
+      if (status != MMAL_SUCCESS)
+      {
+        CLog::Log(LOGERROR, "%s::%s Failed to enable deint output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
+        return false;
+      }
+    }
+    if (m_deint_output_pool)
+      m_deint_output_pool->SetFormat(m_deint_output->format->encoding,
+        m_deint_output->format->es->video.crop.width, m_deint_output->format->es->video.crop.height,
+        m_deint_output->format->es->video.width, m_deint_output->format->es->video.height, m_deint_output->buffer_size, nullptr);
+  }
+
+  if (m_deint && !m_deint->is_enabled)
+  {
+    status = mmal_component_enable(m_deint);
+    if (status != MMAL_SUCCESS)
+    {
+      CLog::Log(LOGERROR, "%s::%s Failed to enable deinterlacer component %s (status=%x %s)", CLASSNAME, __func__, m_deint->name, status, mmal_status_to_string(status));
+      return false;
+    }
+  }
+  m_interlace_method = interlace_method;
+
+  // give buffers to deint
+  if (m_deint_output_pool)
+    m_deint_output_pool->Prime();
+  return true;
+}
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.h
index e2c0223..a1dd438 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/MMALRenderer.h
@@ -29,6 +29,7 @@
 #include "../RenderCapture.h"
 #include "settings/VideoSettings.h"
 #include "cores/VideoPlayer/DVDStreamInfo.h"
+#include "cores/VideoPlayer/DVDCodecs/Video/MMALFFmpeg.h"
 #include "guilib/Geometry.h"
 #include "threads/Thread.h"
 
@@ -40,23 +41,44 @@
 #define NOSOURCE   -2
 #define AUTOSOURCE -1
 
+// worst case number of buffers. 12 for decoder. 8 for multi-threading in ffmpeg. NUM_BUFFERS for renderer.
+// Note, generally these won't necessarily result in allocated pictures
+#define MMAL_NUM_OUTPUT_BUFFERS (12 + 8 + NUM_BUFFERS)
+
 class CBaseTexture;
 class CMMALBuffer;
 
 struct DVDVideoPicture;
 
-class CMMALPool
+class CMMALPool : public std::enable_shared_from_this<CMMALPool>
 {
 public:
-  CMMALPool(MMAL_PORT_T *input, uint32_t num_buffers, uint32_t buffer_size);
+  CMMALPool(const char *component_name, bool input, uint32_t num_buffers, uint32_t buffer_size, uint32_t encoding, MMALState state);
   ~CMMALPool();
-  MMAL_POOL_T *Get() { return m_pool; }
+  MMAL_COMPONENT_T *GetComponent() { return m_component; }
+  static void AlignedSize(AVCodecContext *avctx, uint32_t &w, uint32_t &h);
+  CMMALBuffer *GetBuffer(uint32_t timeout);
+  CGPUMEM *AllocateBuffer(uint32_t numbytes);
+  void ReleaseBuffer(CGPUMEM *gmem);
+  void Close();
+  void Prime();
+  void SetDecoder(CMMALVideo *dec) { m_dec = dec; }
+  void SetFormat(uint32_t mmal_format, uint32_t width, uint32_t height, uint32_t aligned_width, uint32_t aligned_height, uint32_t size, AVCodecContext *avctx)
+    { m_mmal_format = mmal_format; m_width = width; m_height = height; m_aligned_width = aligned_width; m_aligned_height = aligned_height; m_size = size, m_avctx = avctx; }
 protected:
-  MMAL_POOL_T *m_pool;
-  MMAL_PORT_T *m_input;
+  uint32_t m_mmal_format, m_width, m_height, m_aligned_width, m_aligned_height, m_size;
+  AVCodecContext *m_avctx;
+  CMMALVideo *m_dec;
+  MMALState m_state;
+  bool m_input;
+  MMAL_POOL_T *m_mmal_pool;
+  MMAL_COMPONENT_T *m_component;
+  CCriticalSection m_section;
+  std::deque<CGPUMEM *> m_freeBuffers;
+  bool m_closing;
 };
 
-class CMMALRenderer : public CBaseRenderer, public CThread
+class CMMALRenderer : public CBaseRenderer, public CThread, public IRunnable
 {
 public:
   CMMALRenderer();
@@ -83,7 +105,6 @@ public:
 
   virtual bool         SupportsMultiPassRendering() { return false; };
   virtual bool         Supports(ERENDERFEATURE feature);
-  virtual bool         Supports(EDEINTERLACEMODE mode);
   virtual bool         Supports(EINTERLACEMETHOD method);
   virtual bool         Supports(ESCALINGMETHOD method);
 
@@ -96,7 +117,8 @@ public:
   virtual bool         IsGuiLayer() { return false; }
 
   void vout_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer);
-  std::shared_ptr<CMMALPool> GetPool(ERenderFormat format, AVPixelFormat pixfmt, bool opaque);
+  void deint_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer);
+  void deint_output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer);
 protected:
   int m_iYV12RenderBuffer;
   int m_NumYV12Buffers;
@@ -105,7 +127,6 @@ protected:
 
   CMMALBuffer         *m_buffers[NUM_BUFFERS];
   bool                 m_bConfigured;
-  bool                 m_bMMALConfigured;
   unsigned int         m_extended_format;
   int                  m_neededBuffers;
 
@@ -114,18 +135,32 @@ protected:
   RENDER_STEREO_MODE        m_video_stereo_mode;
   RENDER_STEREO_MODE        m_display_stereo_mode;
   bool                      m_StereoInvert;
-  int                       m_inflight;
-  bool                      m_opaque;
-  AVPixelFormat m_pixfmt;
 
   CCriticalSection m_sharedSection;
   MMAL_COMPONENT_T *m_vout;
   MMAL_PORT_T *m_vout_input;
-  std::shared_ptr<CMMALPool> m_vout_input_pool;
-  MMAL_QUEUE_T *m_queue;
+  MMAL_QUEUE_T *m_queue_render;
+  MMAL_QUEUE_T *m_queue_process;
+  CThread m_processThread;
+  MMAL_BUFFER_HEADER_T m_quitpacket;
   double m_error;
 
-  bool init_vout(ERenderFormat format, AVPixelFormat pixfmt, bool opaque);
+  uint32_t m_vout_width, m_vout_height, m_vout_aligned_width, m_vout_aligned_height;
+  // deinterlace
+  MMAL_COMPONENT_T *m_deint;
+  MMAL_PORT_T *m_deint_input;
+  MMAL_PORT_T *m_deint_output;
+  std::shared_ptr<CMMALPool> m_deint_output_pool;
+  MMAL_INTERLACETYPE_T m_interlace_mode;
+  EINTERLACEMETHOD  m_interlace_method;
+  uint32_t m_deint_width, m_deint_height, m_deint_aligned_width, m_deint_aligned_height;
+  MMAL_FOURCC_T m_deinterlace_out_encoding;
+  void DestroyDeinterlace();
+  bool CheckConfigurationDeint(uint32_t width, uint32_t height, uint32_t aligned_width, uint32_t aligned_height, uint32_t encoding, EINTERLACEMETHOD interlace_method);
+
+  bool CheckConfigurationVout(uint32_t width, uint32_t height, uint32_t aligned_width, uint32_t aligned_height, uint32_t encoding);
+  uint32_t m_vsync_count;
   void ReleaseBuffers();
   void UnInitMMAL();
+  virtual void Run() override;
 };
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererMediaCodec.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererMediaCodec.cpp
index a1a5c92..12dacd3 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererMediaCodec.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererMediaCodec.cpp
@@ -116,8 +116,8 @@ CRenderInfo CRendererMediaCodec::GetRenderInfo()
 {
   CRenderInfo info;
   info.formats = m_formats;
-  info.max_buffer_size = NUM_BUFFERS;
-  info.optimal_buffer_size = 2;
+  info.max_buffer_size = 4;
+  info.optimal_buffer_size = 3;
   return info;
 }
 
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererMediaCodecSurface.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererMediaCodecSurface.cpp
index d5f7542..1f53175 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererMediaCodecSurface.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererMediaCodecSurface.cpp
@@ -23,6 +23,7 @@
 #if defined(TARGET_ANDROID)
 #include "../RenderCapture.h"
 
+#include "platform/android/activity/XBMCApp.h"
 #include "DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h"
 #include "utils/log.h"
 
@@ -88,11 +89,6 @@ bool CRendererMediaCodecSurface::Supports(EINTERLACEMETHOD method)
   return false;
 }
 
-bool CRendererMediaCodecSurface::Supports(EDEINTERLACEMODE mode)
-{
-  return false;
-}
-
 EINTERLACEMETHOD CRendererMediaCodecSurface::AutoInterlaceMethod()
 {
   return VS_INTERLACEMETHOD_NONE;
@@ -102,8 +98,8 @@ CRenderInfo CRendererMediaCodecSurface::GetRenderInfo()
 {
   CRenderInfo info;
   info.formats = m_formats;
-  info.max_buffer_size = NUM_BUFFERS;
-  info.optimal_buffer_size = 2;
+  info.max_buffer_size = 4;
+  info.optimal_buffer_size = 3;
   return info;
 }
 
@@ -156,6 +152,7 @@ bool CRendererMediaCodecSurface::RenderUpdateVideoHook(bool clear, DWORD flags,
     mci->RenderUpdate(srcRect, dstRect);
   }
 
+  CXBMCApp::WaitVSync(1000.0 / g_graphicsContext.GetFPS());
   return true;
 }
 
@@ -174,4 +171,3 @@ bool CRendererMediaCodecSurface::UploadTexture(int index)
   return true; // nothing todo
 }
 #endif
-
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererMediaCodecSurface.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererMediaCodecSurface.h
index 9da5e36..f600ee2 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererMediaCodecSurface.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererMediaCodecSurface.h
@@ -41,7 +41,6 @@ public:
 
   // Feature support
   virtual bool Supports(EINTERLACEMETHOD method);
-  virtual bool Supports(EDEINTERLACEMODE mode);  
 
   virtual EINTERLACEMETHOD AutoInterlaceMethod();
   virtual CRenderInfo GetRenderInfo();
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVTBGL.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVTBGL.cpp
index d3e1e03..5e11e00 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVTBGL.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVTBGL.cpp
@@ -65,11 +65,6 @@ bool CRendererVTB::Supports(EINTERLACEMETHOD method)
   return false;
 }
 
-bool CRendererVTB::Supports(EDEINTERLACEMODE mode)
-{
-  return false;
-}
-
 EINTERLACEMETHOD CRendererVTB::AutoInterlaceMethod()
 {
   return VS_INTERLACEMETHOD_NONE;
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVTBGL.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVTBGL.h
index 7e4f693..5ec94c8 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVTBGL.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVTBGL.h
@@ -38,7 +38,6 @@ public:
 
   // Feature support
   virtual bool Supports(EINTERLACEMETHOD method);
-  virtual bool Supports(EDEINTERLACEMODE mode);
 
   virtual EINTERLACEMETHOD AutoInterlaceMethod();
 
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVTBGLES.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVTBGLES.cpp
index ae2a27b..dd13162 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVTBGLES.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVTBGLES.cpp
@@ -85,11 +85,6 @@ bool CRendererVTB::Supports(EINTERLACEMETHOD method)
   return false;
 }
 
-bool CRendererVTB::Supports(EDEINTERLACEMODE mode)
-{
-  return false;
-}
-
 EINTERLACEMETHOD CRendererVTB::AutoInterlaceMethod()
 {
   return VS_INTERLACEMETHOD_NONE;
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVTBGLES.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVTBGLES.h
index d314bfa..a574586 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVTBGLES.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVTBGLES.h
@@ -39,7 +39,6 @@ public:
 
   // Feature support
   virtual bool Supports(EINTERLACEMETHOD method) override;
-  virtual bool Supports(EDEINTERLACEMODE mode) override;
   virtual EINTERLACEMETHOD AutoInterlaceMethod() override;
   virtual CRenderInfo GetRenderInfo() override;
 
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp
index 976dd36..1a9b5a3 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp
@@ -157,6 +157,13 @@ CLinuxRendererGL::CLinuxRendererGL()
   m_nonLinStretch = false;
   m_nonLinStretchGui = false;
   m_pixelRatio = 0.0f;
+
+  m_ColorManager.reset(new CColorManager());
+  m_tCLUTTex = 0;
+  m_CLUT = NULL;
+  m_CLUTsize = 0;
+  m_cmsToken = -1;
+  m_cmsOn = false;
 }
 
 CLinuxRendererGL::~CLinuxRendererGL()
@@ -300,6 +307,22 @@ bool CLinuxRendererGL::Configure(unsigned int width, unsigned int height, unsign
   }
 #endif
 
+  // load 3DLUT
+  if (m_ColorManager->IsEnabled())
+  {
+    if (!m_ColorManager->CheckConfiguration(m_cmsToken, m_iFlags))
+    {
+      CLog::Log(LOGDEBUG, "CMS configuration changed, reload LUT");
+      if (!LoadCLUT())
+        return false;
+    }
+    m_cmsOn = true;
+  }
+  else
+  {
+    m_cmsOn = false;
+  }
+
   return true;
 }
 
@@ -714,6 +737,8 @@ void CLinuxRendererGL::UpdateVideoFilter()
   bool pixelRatioChanged    = (CDisplaySettings::GetInstance().GetPixelRatio() > 1.001f || CDisplaySettings::GetInstance().GetPixelRatio() < 0.999f) !=
                               (m_pixelRatio > 1.001f || m_pixelRatio < 0.999f);
   bool nonLinStretchChanged = false;
+  bool cmsChanged           = (m_cmsOn != m_ColorManager->IsEnabled())
+                              || (m_cmsOn && !m_ColorManager->CheckConfiguration(m_cmsToken, m_iFlags));
   if (m_nonLinStretchGui != CDisplaySettings::GetInstance().IsNonLinearStretched() || pixelRatioChanged)
   {
     m_nonLinStretchGui   = CDisplaySettings::GetInstance().IsNonLinearStretched();
@@ -733,7 +758,7 @@ void CLinuxRendererGL::UpdateVideoFilter()
     }
   }
 
-  if (m_scalingMethodGui == CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ScalingMethod && !nonLinStretchChanged)
+  if (m_scalingMethodGui == CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ScalingMethod && !nonLinStretchChanged && !cmsChanged)
     return;
   else
     m_reloadShaders = 1;
@@ -743,6 +768,23 @@ void CLinuxRendererGL::UpdateVideoFilter()
   if (m_nonLinStretch || nonLinStretchChanged)
     m_reloadShaders = 1;
 
+  if (cmsChanged)
+  {
+    if (m_ColorManager->IsEnabled())
+    {
+      if (!m_ColorManager->CheckConfiguration(m_cmsToken, m_iFlags))
+      {
+        CLog::Log(LOGDEBUG, "CMS configuration changed, reload LUT");
+        LoadCLUT();
+      }
+      m_cmsOn = true;
+    }
+    else
+    {
+      m_cmsOn = false;
+    }
+  }
+
   m_scalingMethodGui = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ScalingMethod;
   m_scalingMethod    = m_scalingMethodGui;
 
@@ -822,7 +864,13 @@ void CLinuxRendererGL::UpdateVideoFilter()
     }
 
     GLSLOutput *out;
-    out = new GLSLOutput(3, m_useDithering, m_ditherDepth, false);
+    out = new GLSLOutput(3,
+        m_useDithering,
+        m_ditherDepth,
+        m_cmsOn ? m_fullRange : false,
+        m_cmsOn ? m_tCLUTTex : 0,
+        m_CLUTsize,
+        m_iFlags);
     m_pVideoFilterShader = new ConvolutionFilterShader(m_scalingMethod, m_nonLinStretch, out);
     if (!m_pVideoFilterShader->CompileAndLink())
     {
@@ -891,11 +939,18 @@ void CLinuxRendererGL::LoadShaders(int field)
         // if single pass, create GLSLOutput helper and pass it to YUV2RGB shader
         GLSLOutput *out = nullptr;
         if (m_renderQuality == RQ_SINGLEPASS)
-          out = new GLSLOutput(3, m_useDithering, m_ditherDepth, false);
+          out = new GLSLOutput(3,
+              m_useDithering,
+              m_ditherDepth,
+              m_cmsOn ? m_fullRange : false,
+              m_cmsOn ? m_tCLUTTex : 0,
+              m_CLUTsize,
+              m_iFlags);
         m_pYUVShader = new YUV2RGBProgressiveShader(m_textureTarget==GL_TEXTURE_RECTANGLE_ARB, m_iFlags, m_format,
                                                     m_nonLinStretch && m_renderQuality == RQ_SINGLEPASS,
                                                     out);
-        m_pYUVShader->SetConvertFullColorRange(m_fullRange);
+        if (!m_cmsOn)
+          m_pYUVShader->SetConvertFullColorRange(m_fullRange);
 
         CLog::Log(LOGNOTICE, "GL: Selecting Single Pass YUV 2 RGB shader");
 
@@ -1008,6 +1063,8 @@ void CLinuxRendererGL::UnInit()
     DeleteTexture(i);
   }
 
+  DeleteCLUT();
+
   // cleanup framebuffer object if it was in use
   m_fbo.fbo.Cleanup();
   m_bValidated = false;
@@ -2421,19 +2478,6 @@ bool CLinuxRendererGL::SupportsMultiPassRendering()
   return g_Windowing.IsExtSupported("GL_EXT_framebuffer_object");
 }
 
-bool CLinuxRendererGL::Supports(EDEINTERLACEMODE mode)
-{
-  if(m_renderMethod & RENDER_CVREF)
-    return false;
-
-  if(mode == VS_DEINTERLACEMODE_OFF
-  || mode == VS_DEINTERLACEMODE_AUTO
-  || mode == VS_DEINTERLACEMODE_FORCE)
-    return true;
-
-  return false;
-}
-
 bool CLinuxRendererGL::Supports(EINTERLACEMETHOD method)
 {
   if(m_renderMethod & RENDER_CVREF)
@@ -2547,4 +2591,54 @@ CRenderInfo CLinuxRendererGL::GetRenderInfo()
   return info;
 }
 
+// Color management helpers
+
+bool CLinuxRendererGL::LoadCLUT()
+{
+  DeleteCLUT();
+
+  // load 3DLUT
+  if ( !m_ColorManager->GetVideo3dLut(m_iFlags, &m_cmsToken, &m_CLUTsize, &m_CLUT) )
+  {
+    CLog::Log(LOGERROR, "Error loading the LUT");
+    return false;
+  }
+
+  // create 3DLUT texture
+  CLog::Log(LOGDEBUG, "LinuxRendererGL: creating 3DLUT");
+  glGenTextures(1, &m_tCLUTTex);
+  glActiveTexture(GL_TEXTURE4);
+  if ( m_tCLUTTex <= 0 )
+  {
+    CLog::Log(LOGERROR, "Error creating 3DLUT texture");
+    return false;
+  }
+
+  // bind and set 3DLUT texture parameters
+  glBindTexture(GL_TEXTURE_3D, m_tCLUTTex);
+  glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+
+  // load 3DLUT data
+  glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB16, m_CLUTsize, m_CLUTsize, m_CLUTsize, 0, GL_RGB, GL_UNSIGNED_SHORT, m_CLUT);
+  free(m_CLUT);
+  glActiveTexture(GL_TEXTURE0);
+  return true;
+}
+
+void CLinuxRendererGL::DeleteCLUT()
+{
+  if (m_tCLUTTex)
+  {
+    CLog::Log(LOGDEBUG, "LinuxRendererGL: deleting 3DLUT");
+    glDeleteTextures(1, &m_tCLUTTex);
+    m_tCLUTTex = 0;
+  }
+}
+
 #endif
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h
index e92010b..f8670fc 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h
@@ -34,6 +34,7 @@
 #include "RenderFormats.h"
 #include "guilib/GraphicContext.h"
 #include "BaseRenderer.h"
+#include "ColorManager.h"
 
 #include "threads/Event.h"
 
@@ -137,7 +138,6 @@ public:
   // Feature support
   virtual bool SupportsMultiPassRendering();
   virtual bool Supports(ERENDERFEATURE feature);
-  virtual bool Supports(EDEINTERLACEMODE mode);
   virtual bool Supports(EINTERLACEMETHOD method);
   virtual bool Supports(ESCALINGMETHOD method);
 
@@ -280,6 +280,17 @@ protected:
   bool  m_nonLinStretch;
   bool  m_nonLinStretchGui;
   float m_pixelRatio;
+
+  // color management
+  std::unique_ptr<CColorManager> m_ColorManager;
+  GLuint m_tCLUTTex;
+  uint16_t *m_CLUT;
+  int m_CLUTsize;
+  int m_cmsToken;
+  bool m_cmsOn;
+
+  bool LoadCLUT();
+  void DeleteCLUT();
 };
 
 
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp
index 3760970..d1baae6 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.cpp
@@ -192,12 +192,10 @@ bool CLinuxRendererGLES::Configure(unsigned int width, unsigned int height, unsi
   {
     m_renderFeatures.clear();
     m_scalingMethods.clear();
-    m_deinterlaceModes.clear();
     m_deinterlaceMethods.clear();
 
     g_application.m_pPlayer->GetRenderFeatures(m_renderFeatures);
     g_application.m_pPlayer->GetDeinterlaceMethods(m_deinterlaceMethods);
-    g_application.m_pPlayer->GetDeinterlaceModes(m_deinterlaceModes);
     g_application.m_pPlayer->GetScalingMethods(m_scalingMethods);
   }
 
@@ -1671,25 +1669,6 @@ bool CLinuxRendererGLES::SupportsMultiPassRendering()
   return false;
 }
 
-bool CLinuxRendererGLES::Supports(EDEINTERLACEMODE mode)
-{
-  // Player controls render, let it dictate available deinterlace modes
-  if((m_renderMethod & RENDER_BYPASS))
-  {
-    Features::iterator itr = std::find(m_deinterlaceModes.begin(),m_deinterlaceModes.end(), mode);
-    return itr != m_deinterlaceModes.end();
-  }
-
-  if (mode == VS_DEINTERLACEMODE_OFF)
-    return true;
-
-  if(mode == VS_DEINTERLACEMODE_AUTO
-  || mode == VS_DEINTERLACEMODE_FORCE)
-    return true;
-
-  return false;
-}
-
 bool CLinuxRendererGLES::Supports(EINTERLACEMETHOD method)
 {
   // Player controls render, let it dictate available deinterlace methods
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h
index afc130e..238e62e 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h
@@ -146,7 +146,6 @@ public:
   // Feature support
   virtual bool SupportsMultiPassRendering() override;
   virtual bool Supports(ERENDERFEATURE feature) override;
-  virtual bool Supports(EDEINTERLACEMODE mode) override;
   virtual bool Supports(EINTERLACEMETHOD method) override;
   virtual bool Supports(ESCALINGMETHOD method) override;
   virtual EINTERLACEMETHOD AutoInterlaceMethod() override;
@@ -266,7 +265,6 @@ protected:
 
   Features m_renderFeatures;
   Features m_deinterlaceMethods;
-  Features m_deinterlaceModes;
   Features m_scalingMethods;
 
   // clear colour for "black" bars
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/Makefile.in b/xbmc/cores/VideoPlayer/VideoRenderers/Makefile.in
index c02e417..83547f6 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/Makefile.in
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/Makefile.in
@@ -1,4 +1,5 @@
 SRCS  = BaseRenderer.cpp
+SRCS += ColorManager.cpp
 SRCS += OverlayRenderer.cpp
 SRCS += OverlayRendererUtil.cpp
 SRCS += OverlayRendererGUI.cpp
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererDX.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererDX.cpp
index 1395c35..e84dd40 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererDX.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/OverlayRendererDX.cpp
@@ -23,6 +23,7 @@
 #include "cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlaySpu.h"
 #include "cores/VideoPlayer/DVDCodecs/Overlay/DVDOverlaySSA.h"
 #include "guilib/D3DResource.h"
+#include "guilib/GraphicContext.h"
 #include "OverlayRenderer.h"
 #include "OverlayRendererUtil.h"
 #include "OverlayRendererDX.h"
@@ -167,6 +168,17 @@ void COverlayQuadsDX::Render(SRenderState &state)
   CGUIShaderDX* pGUIShader = g_Windowing.GetGUIShader();
 
   XMMATRIX world = pGUIShader->GetWorld();
+  XMMATRIX view = pGUIShader->GetView();
+  XMMATRIX proj = pGUIShader->GetProjection();
+
+  if (g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_SPLIT_HORIZONTAL
+   || g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_SPLIT_VERTICAL)
+  {
+    CRect rect;
+    g_Windowing.GetViewPort(rect);
+    g_Windowing.SetCameraPosition(CPoint(rect.Width()*0.5f, rect.Height()*0.5f), rect.Width(), rect.Height());
+  }
+
   XMMATRIX trans = XMMatrixTranslation(state.x, state.y, 0.0f);
   XMMATRIX scale = XMMatrixScaling(state.width, state.height, 1.0f);
 
@@ -190,6 +202,8 @@ void COverlayQuadsDX::Render(SRenderState &state)
 
   // restoring transformation
   pGUIShader->SetWorld(world);
+  pGUIShader->SetView(view);
+  pGUIShader->SetProjection(proj);
   pGUIShader->RestoreBuffers();
 }
 
@@ -295,31 +309,25 @@ void COverlayImageDX::Load(uint32_t* rgba, int width, int height, int stride)
                 , &m_texture))
     return;
 
-  Vertex* vt = new Vertex[6];
+  Vertex vt[4];
 
-  vt[0].texCoord = XMFLOAT2(0.0f, 0.0f);
-  vt[0].pos      = XMFLOAT3(0.0f, 0.0f, 0.0f);
+  vt[0].texCoord = XMFLOAT2(u, 0.0f);
+  vt[0].pos      = XMFLOAT3(1.0f, 0.0f, 0.0f);
 
-  vt[1].texCoord = XMFLOAT2(u, 0.0f);
-  vt[1].pos      = XMFLOAT3(1.0f, 0.0f, 0.0f);
+  vt[1].texCoord = XMFLOAT2(u, v);
+  vt[1].pos      = XMFLOAT3(1.0f, 1.0f, 0.0f);
 
-  vt[2].texCoord = XMFLOAT2(0.0f, v);
-  vt[2].pos      = XMFLOAT3(0.0f, 1.0f, 0.0f);
+  vt[2].texCoord = XMFLOAT2(0.0f, 0.0f);
+  vt[2].pos      = XMFLOAT3(0.0f, 0.0f, 0.0f);
 
-  vt[3] = vt[1];
+  vt[3].texCoord = XMFLOAT2(0.0f, v);
+  vt[3].pos      = XMFLOAT3(0.0f, 1.0f, 0.0f);
 
-  vt[4].texCoord = XMFLOAT2(u, v);
-  vt[4].pos      = XMFLOAT3(1.0f, 1.0f, 0.0f);
-
-  vt[5] = vt[2];
-
-  if (!m_vertex.Create(D3D11_BIND_VERTEX_BUFFER, 6, sizeof(Vertex), DXGI_FORMAT_UNKNOWN, D3D11_USAGE_IMMUTABLE, vt))
+  if (!m_vertex.Create(D3D11_BIND_VERTEX_BUFFER, 4, sizeof(Vertex), DXGI_FORMAT_UNKNOWN, D3D11_USAGE_IMMUTABLE, vt))
   {
     CLog::Log(LOGERROR, "%s - failed to create vertex buffer", __FUNCTION__);
     m_texture.Release();
   }
-
-  delete[] vt;
 }
 
 void COverlayImageDX::Render(SRenderState &state)
@@ -328,6 +336,17 @@ void COverlayImageDX::Render(SRenderState &state)
   CGUIShaderDX* pGUIShader = g_Windowing.GetGUIShader();
 
   XMMATRIX world = pGUIShader->GetWorld();
+  XMMATRIX view = pGUIShader->GetView();
+  XMMATRIX proj = pGUIShader->GetProjection();
+
+  if (g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_SPLIT_HORIZONTAL
+   || g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_SPLIT_VERTICAL)
+  {
+    CRect rect;
+    g_Windowing.GetViewPort(rect);
+    g_Windowing.SetCameraPosition(CPoint(rect.Width()*0.5f, rect.Height()*0.5f), rect.Width(), rect.Height());
+  }
+
   XMMATRIX trans = m_pos == POSITION_RELATIVE
                  ? XMMatrixTranslation(state.x - state.width  * 0.5f, state.y - state.height * 0.5f, 0.0f)
                  : XMMatrixTranslation(state.x, state.y, 0.0f),
@@ -339,20 +358,20 @@ void COverlayImageDX::Render(SRenderState &state)
   const unsigned offset = 0;
 
   ID3D11Buffer* vertexBuffer = m_vertex.Get();
-  // Set the vertex buffer to active in the input assembler so it can be rendered.
   pContext->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
-  // Set the type of primitive that should be rendered from this vertex buffer, in this case triangles.
-  pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+  pContext->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
 
   pGUIShader->Begin(SHADER_METHOD_RENDER_TEXTURE_NOBLEND);
   g_Windowing.SetAlphaBlendEnable(true);
 
   ID3D11ShaderResourceView* views[] = { m_texture.GetShaderResource() };
   pGUIShader->SetShaderViews(1, views);
-  pGUIShader->Draw(6, 0);
+  pGUIShader->Draw(4, 0);
 
   // restoring transformation
   pGUIShader->SetWorld(world);
+  pGUIShader->SetView(view);
+  pGUIShader->SetProjection(proj);
   pGUIShader->RestoreBuffers();
 }
 
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/RenderFlags.h b/xbmc/cores/VideoPlayer/VideoRenderers/RenderFlags.h
index f65d4b2..ac0dfe1 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderFlags.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderFlags.h
@@ -52,11 +52,11 @@
 
 /* defines color primaries */
 #define CONF_FLAGS_COLPRI_MASK(a) ((a) & 0xe0)
-#define CONF_FLAGS_COLPRI_BT709   0x20
-#define CONF_FLAGS_COLPRI_BT470M  0x40
-#define CONF_FLAGS_COLPRI_BT470BG 0x60
-#define CONF_FLAGS_COLPRI_170M    0x80
-#define CONF_FLAGS_COLPRI_240M    0xa0
+#define CONF_FLAGS_COLPRI_BT709   0x20  // sRGB, HDTV (ITU-R BT.709)
+#define CONF_FLAGS_COLPRI_BT470M  0x40  // NTSC (1953) (FCC 1953, ITU-R BT.470 System M)
+#define CONF_FLAGS_COLPRI_BT470BG 0x60  // PAL/SECAM (1970) (EBU Tech. 3213, ITU-R BT.470 System B, G)
+#define CONF_FLAGS_COLPRI_170M    0x80  // NTSC (1987) (SMPTE RP 145 "SMPTE C", SMPTE 170M)
+#define CONF_FLAGS_COLPRI_240M    0xa0  // SMPTE-240M
 
 /* defines chroma subsampling sample location */
 #define CONF_FLAGS_CHROMA_MASK(a) ((a) & 0x0300)
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp
index 93f8d6f..b482fc1 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.cpp
@@ -324,6 +324,7 @@ bool CRenderManager::Configure()
     m_renderState = STATE_UNCONFIGURED;
 
   m_stateEvent.Set();
+  m_playerPort->VideoParamsChange();
   return result;
 }
 
@@ -796,19 +797,15 @@ void CRenderManager::FlipPage(volatile std::atomic_bool& bStop, double pts /* =
 
   EPRESENTMETHOD presentmethod;
 
-  EDEINTERLACEMODE deinterlacemode = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_DeinterlaceMode;
   EINTERLACEMETHOD interlacemethod = AutoInterlaceMethodInternal(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod);
 
-  if (deinterlacemode == VS_DEINTERLACEMODE_OFF)
+  if (interlacemethod == VS_INTERLACEMETHOD_NONE)
   {
     presentmethod = PRESENT_METHOD_SINGLE;
     sync = FS_NONE;
   }
   else
   {
-    if (deinterlacemode == VS_DEINTERLACEMODE_AUTO && sync == FS_NONE)
-      presentmethod = PRESENT_METHOD_SINGLE;
-    else
     {
       bool invert = false;
       if (interlacemethod == VS_INTERLACEMETHOD_RENDER_BLEND)
@@ -834,10 +831,6 @@ void CRenderManager::FlipPage(volatile std::atomic_bool& bStop, double pts /* =
 
       if (presentmethod != PRESENT_METHOD_SINGLE)
       {
-        /* default to odd field if we want to deinterlace and don't know better */
-        if (deinterlacemode == VS_DEINTERLACEMODE_FORCE && sync == FS_NONE)
-          sync = FS_TOP;
-
         /* invert present field */
         if (invert)
         {
@@ -1193,17 +1186,11 @@ bool CRenderManager::Supports(ERENDERFEATURE feature)
     return false;
 }
 
-bool CRenderManager::Supports(EDEINTERLACEMODE method)
-{
-  CSingleLock lock(m_statelock);
-  if (m_pRenderer)
-    return m_pRenderer->Supports(method);
-  else
-    return false;
-}
-
 bool CRenderManager::Supports(EINTERLACEMETHOD method)
 {
+  if (method == VS_INTERLACEMETHOD_NONE)
+    return true;
+  
   CSingleLock lock(m_statelock);
   if (m_pRenderer)
     return m_pRenderer->Supports(method);
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h
index bce8892..209046d 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/RenderManager.h
@@ -91,7 +91,6 @@ public:
 
   // Functions called from GUI
   bool Supports(ERENDERFEATURE feature);
-  bool Supports(EDEINTERLACEMODE method);
   bool Supports(EINTERLACEMETHOD method);
   bool Supports(ESCALINGMETHOD method);
   EINTERLACEMETHOD AutoInterlaceMethod(EINTERLACEMETHOD mInt);
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.cpp
index 72ffa0d..4d9f469 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.cpp
@@ -28,23 +28,32 @@
 
 using namespace Shaders;
 
-GLSLOutput::GLSLOutput(int texunit, bool useDithering, unsigned int ditherDepth, bool fullrange)
+GLSLOutput::GLSLOutput(int texunit, bool useDithering, unsigned int ditherDepth, bool fullrange, GLuint clutTex, int clutSize, unsigned videoflags)
 {
   // set member variable initial values
   m_1stTexUnit = texunit;
   m_uDither = m_1stTexUnit+0;
+  m_uCLUT = m_1stTexUnit+1;
+  m_flags = videoflags;
 
   //   textures
   m_tDitherTex  = 0;
+  m_tCLUTTex  = clutTex;
 
   //   shader attribute handles
   m_hDither      = -1;
   m_hDitherQuant = -1;
   m_hDitherSize  = -1;
+  m_hCLUT        = -1;
+  m_hCLUTSize    = -1;
 
   m_dither = useDithering;
   m_ditherDepth = ditherDepth;
   m_fullRange = fullrange;
+  // make sure CMS is enabled - this allows us to keep the texture
+  // around to quickly switch between CMS on and off
+  m_3DLUT = clutTex > 0;
+  m_uCLUTSize = clutSize;
 }
 
 std::string GLSLOutput::GetDefines()
@@ -54,6 +63,10 @@ std::string GLSLOutput::GetDefines()
     defines += "#define XBMC_DITHER\n";
   if (m_fullRange)
     defines += "#define XBMC_FULLRANGE\n";
+#ifdef HAS_GL
+  if (m_3DLUT)
+    defines += "#define KODI_3DLUT\n";
+#endif //HAS_GL
   return defines;
 }
 
@@ -69,6 +82,14 @@ void GLSLOutput::OnCompiledAndLinked(GLuint programHandle)
     m_hDitherQuant = glGetUniformLocation(programHandle, "m_ditherquant");
     m_hDitherSize = glGetUniformLocation(programHandle, "m_dithersize");
   }
+  //   3DLUT
+  if (m_3DLUT)
+  {
+#ifdef HAS_GL
+    m_hCLUT        = glGetUniformLocation(programHandle, "m_CLUT");
+    m_hCLUTSize    = glGetUniformLocation(programHandle, "m_CLUTsize");
+#endif //HAS_GL
+  }
 
   if (m_dither)
   {
@@ -126,6 +147,22 @@ bool GLSLOutput::OnEnabled()
     VerifyGLState();
   }
 
+  if (m_3DLUT)
+  {
+#ifdef HAS_GL
+    // set texture units
+    glUniform1i(m_hCLUT, m_uCLUT);
+    glUniform1f(m_hCLUTSize, m_uCLUTSize);
+    VerifyGLState();
+
+    // bind textures
+    glActiveTexture(GL_TEXTURE0 + m_uCLUT);
+    glBindTexture(GL_TEXTURE_3D, m_tCLUTTex);
+    glActiveTexture(GL_TEXTURE0);
+    VerifyGLState();
+#endif //HAS_GL
+  }
+
   VerifyGLState();
   return true;
 }
@@ -138,6 +175,13 @@ void GLSLOutput::OnDisabled()
     glActiveTexture(GL_TEXTURE0 + m_uDither);
     glDisable(GL_TEXTURE_2D);
   }
+  if (m_3DLUT)
+  {
+#ifdef HAS_GL
+    glActiveTexture(GL_TEXTURE0 + m_uCLUT);
+    glDisable(GL_TEXTURE_3D);
+#endif //HAS_GL
+  }
   glActiveTexture(GL_TEXTURE0);
   VerifyGLState();
 }
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.h b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.h
index 8df84fb..19d9069 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.h
@@ -29,7 +29,14 @@ namespace Shaders
   {
   public:
     // take the 1st available texture unit as a parameter
-    GLSLOutput(int texunit, bool useDithering, unsigned int ditherDepth, bool fullrange);
+    GLSLOutput(
+      int texunit,
+      bool useDithering,
+      unsigned int ditherDepth,
+      bool fullrange,
+      GLuint clutTex,
+      int clutSize,
+      unsigned videoflags);
     std::string GetDefines();
     void OnCompiledAndLinked(GLuint programHandle);
     bool OnEnabled();
@@ -42,9 +49,13 @@ namespace Shaders
     bool m_dither;
     unsigned int m_ditherDepth;
     bool m_fullRange;
+    bool m_3DLUT;
+    unsigned m_flags;
     // first texture unit available to us
     int m_1stTexUnit;
     int m_uDither;
+    int m_uCLUT;
+    int m_uCLUTSize;
 
     // defines
 
@@ -52,8 +63,11 @@ namespace Shaders
     GLint m_hDither;
     GLint m_hDitherQuant;
     GLint m_hDitherSize;
+    GLint m_hCLUT;
+    GLint m_hCLUTSize;
 
     // textures
     GLuint m_tDitherTex;
+    GLuint m_tCLUTTex;
   };
 }
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.cpp
index 3f614bc..770ca6f 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/WinVideoFilter.cpp
@@ -31,7 +31,7 @@
 #include "guilib/GraphicContext.h"
 #include "Util.h"
 #include "utils/log.h"
-#include "win32/WIN32Util.h"
+#include "platform/win32/WIN32Util.h"
 #include "windowing/WindowingFactory.h"
 #include "YUV2RGBShader.h"
 #include <map>
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp
index d221c8a..e160a09 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.cpp
@@ -34,7 +34,7 @@
 #include "utils/log.h"
 #include "utils/win32/gpu_memcpy_sse4.h"
 #include "VideoShaders/WinVideoFilter.h"
-#include "win32/WIN32Util.h"
+#include "platform/win32/WIN32Util.h"
 #include "windowing/WindowingFactory.h"
 
 typedef struct {
@@ -1006,16 +1006,6 @@ bool CWinRenderer::CreateYV12Texture(int index)
   return true;
 }
 
-bool CWinRenderer::Supports(EDEINTERLACEMODE mode)
-{
-  if(mode == VS_DEINTERLACEMODE_OFF
-  || mode == VS_DEINTERLACEMODE_AUTO
-  || mode == VS_DEINTERLACEMODE_FORCE)
-    return true;
-
-  return false;
-}
-
 bool CWinRenderer::Supports(EINTERLACEMETHOD method)
 {
   if(method == VS_INTERLACEMETHOD_AUTO)
diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h b/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h
index e7adc1c..05b090c 100644
--- a/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h
+++ b/xbmc/cores/VideoPlayer/VideoRenderers/WinRenderer.h
@@ -182,7 +182,6 @@ public:
   // Feature support
   virtual bool SupportsMultiPassRendering() { return false; }
   virtual bool Supports(ERENDERFEATURE feature);
-  virtual bool Supports(EDEINTERLACEMODE mode);
   virtual bool Supports(EINTERLACEMETHOD method);
   virtual bool Supports(ESCALINGMETHOD method);
 
diff --git a/xbmc/cores/omxplayer/CMakeLists.txt b/xbmc/cores/omxplayer/CMakeLists.txt
index 212159e..17cdfb2 100644
--- a/xbmc/cores/omxplayer/CMakeLists.txt
+++ b/xbmc/cores/omxplayer/CMakeLists.txt
@@ -17,8 +17,4 @@ set(HEADERS OMXAudio.h
             OMXVideoCodec.h)
 
 core_add_library(omxplayer)
-add_definitions(-D__STDC_FORMAT_MACROS)
-
-add_dependencies(omxplayer linuxsupport ffmpeg)
-
-
+target_compile_definitions(${CORE_LIBRARY} PRIVATE -D__STDC_FORMAT_MACROS)
diff --git a/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp b/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp
index 20f706c..d8cef9c 100644
--- a/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp
+++ b/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp
@@ -33,7 +33,7 @@
 #define AUDIO_DECODE_OUTPUT_BUFFER (32*1024)
 static const char rounded_up_channels_shift[] = {0,0,1,2,2,3,3,3,3};
 
-COMXAudioCodecOMX::COMXAudioCodecOMX()
+COMXAudioCodecOMX::COMXAudioCodecOMX(CProcessInfo &processInfo) : m_processInfo(processInfo)
 {
   m_pBufferOutput = NULL;
   m_iBufferOutputAlloced = 0;
@@ -134,6 +134,7 @@ bool COMXAudioCodecOMX::Open(CDVDStreamInfo &hints)
 
   m_iSampleFormat = AV_SAMPLE_FMT_NONE;
   m_desiredSampleFormat = m_pCodecContext->sample_fmt == AV_SAMPLE_FMT_S16 ? AV_SAMPLE_FMT_S16 : AV_SAMPLE_FMT_FLTP;
+  m_processInfo.SetAudioDecoderName(m_pCodecContext->codec->name);
   return true;
 }
 
diff --git a/xbmc/cores/omxplayer/OMXAudioCodecOMX.h b/xbmc/cores/omxplayer/OMXAudioCodecOMX.h
index c06a323..3b2a0f3 100644
--- a/xbmc/cores/omxplayer/OMXAudioCodecOMX.h
+++ b/xbmc/cores/omxplayer/OMXAudioCodecOMX.h
@@ -31,11 +31,12 @@ extern "C" {
 
 #include "DVDStreamInfo.h"
 #include "linux/PlatformDefs.h"
+#include "cores/VideoPlayer/Process/ProcessInfo.h"
 
 class COMXAudioCodecOMX
 {
 public:
-  COMXAudioCodecOMX();
+  COMXAudioCodecOMX(CProcessInfo &processInfo);
   virtual ~COMXAudioCodecOMX();
   bool Open(CDVDStreamInfo &hints);
   void Dispose();
@@ -52,6 +53,7 @@ public:
   unsigned int GetFrameSize() { return m_frameSize; }
 
 protected:
+  CProcessInfo &m_processInfo;
   AVCodecContext* m_pCodecContext;
   SwrContext*     m_pConvert;
   enum AVSampleFormat m_iSampleFormat;
diff --git a/xbmc/cores/omxplayer/OMXHelper.cpp b/xbmc/cores/omxplayer/OMXHelper.cpp
index b5db1c4..f135d42 100644
--- a/xbmc/cores/omxplayer/OMXHelper.cpp
+++ b/xbmc/cores/omxplayer/OMXHelper.cpp
@@ -134,15 +134,11 @@ bool OMXDoProcessing(struct SOmxPlayerState &m_OmxPlayerState, int m_playSpeed,
       m_OmxPlayerState.interlace_method = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod;
 
     // if deinterlace setting has changed, we should close and open video
-    if (m_OmxPlayerState.current_deinterlace != CMediaSettings::GetInstance().GetCurrentVideoSettings().m_DeinterlaceMode ||
-       (m_OmxPlayerState.current_deinterlace != VS_DEINTERLACEMODE_OFF &&
-        m_OmxPlayerState.interlace_method != CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod))
+    if (m_OmxPlayerState.interlace_method != CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod)
     {
-      CLog::Log(LOGNOTICE, "%s - Reopen stream due to interlace change (%d,%d,%d,%d)", __FUNCTION__,
-        m_OmxPlayerState.current_deinterlace, CMediaSettings::GetInstance().GetCurrentVideoSettings().m_DeinterlaceMode,
+      CLog::Log(LOGNOTICE, "%s - Reopen stream due to interlace change (%d,%d)", __FUNCTION__,
         m_OmxPlayerState.interlace_method, CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod);
 
-      m_OmxPlayerState.current_deinterlace = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_DeinterlaceMode;
       m_OmxPlayerState.interlace_method    = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod;
       reopen_stream = true;
     }
diff --git a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp
index 50a5b17..1e5d2b9 100644
--- a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp
+++ b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp
@@ -43,6 +43,7 @@
 #include "linux/RBP.h"
 #include "cores/AudioEngine/AEFactory.h"
 #include "cores/DataCacheCore.h"
+#include "ServiceBroker.h"
 
 #include <algorithm>
 #include <iomanip>
@@ -100,7 +101,8 @@ bool OMXPlayerAudio::OpenStream(CDVDStreamInfo &hints)
 {
   m_bad_state = false;
 
-  COMXAudioCodecOMX *codec = new COMXAudioCodecOMX();
+  m_processInfo.ResetAudioCodecInfo();
+  COMXAudioCodecOMX *codec = new COMXAudioCodecOMX(m_processInfo);
 
   if(!codec || !codec->Open(hints))
   {
@@ -142,7 +144,7 @@ void OMXPlayerAudio::OpenStream(CDVDStreamInfo &hints, COMXAudioCodecOMX *codec)
   m_format.m_sampleRate    = 0;
   m_format.m_channelLayout = 0;
 
-  g_dataCacheCore.SignalAudioInfoChange();
+  CServiceBroker::GetDataCacheCore().SignalAudioInfoChange();
 }
 
 void OMXPlayerAudio::CloseStream(bool bWaitForBuffers)
@@ -187,6 +189,7 @@ bool OMXPlayerAudio::CodecChange()
   {
     m_hints.channels = m_pAudioCodec->GetChannels();
     m_hints.samplerate = m_pAudioCodec->GetSampleRate();
+    m_hints.bitspersample = m_pAudioCodec->GetBitsPerSample();
   }
 
   /* only check bitrate changes on AV_CODEC_ID_DTS, AV_CODEC_ID_AC3, AV_CODEC_ID_EAC3 */
@@ -203,7 +206,11 @@ bool OMXPlayerAudio::CodecChange()
      (!m_passthrough && minor_change) || !m_DecoderOpen)
   {
     m_hints_current = m_hints;
-    g_dataCacheCore.SignalAudioInfoChange();
+
+    m_processInfo.SetAudioSampleRate(m_hints.samplerate);
+    m_processInfo.SetAudioBitsPerSample(m_hints.bitspersample);
+
+    CServiceBroker::GetDataCacheCore().SignalAudioInfoChange();
     return true;
   }
 
@@ -561,11 +568,23 @@ bool OMXPlayerAudio::OpenDecoder()
 
   CAEChannelInfo channelMap;
   if (m_pAudioCodec && !m_passthrough)
+  {
     channelMap = m_pAudioCodec->GetChannelMap();
+  }
   else if (m_passthrough)
+  {
     // we just want to get the channel count right to stop OMXAudio.cpp rejecting stream
     // the actual layout is not used
     channelMap = AE_CH_LAYOUT_5_1;
+
+    if (m_hints.codec == AV_CODEC_ID_AC3)
+      m_processInfo.SetAudioDecoderName("PT_AC3");
+    else if (m_hints.codec == AV_CODEC_ID_EAC3)
+      m_processInfo.SetAudioDecoderName("PT_EAC3");
+    else
+      m_processInfo.SetAudioDecoderName("PT_DTS");
+  }
+  m_processInfo.SetAudioChannels(channelMap);
   bool bAudioRenderOpen = m_omxAudio.Initialize(m_format, m_av_clock, m_hints, channelMap, m_passthrough);
 
   m_codec_name = "";
diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
index 236f1b3..f9fa18a 100644
--- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
+++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
@@ -73,8 +73,7 @@ OMXPlayerVideo::OMXPlayerVideo(OMXClock *av_clock,
 : CThread("OMXPlayerVideo")
 , IDVDStreamPlayerVideo(processInfo)
 , m_messageQueue("video")
-, m_omxVideo(renderManager)
-, m_codecname("")
+, m_omxVideo(renderManager, processInfo)
 , m_messageParent(parent)
 , m_renderManager(renderManager)
 {
@@ -471,7 +470,7 @@ void OMXPlayerVideo::Process()
 
         if (m_syncState == IDVDStreamPlayer::SYNC_STARTING && !bRequestDrop && settings_changed)
         {
-          m_codecname = m_omxVideo.GetDecoderName();
+          m_processInfo.SetVideoDecoderName(m_omxVideo.GetDecoderName(), true);
           m_syncState = IDVDStreamPlayer::SYNC_WAITSYNC;
           SStartMsg msg;
           msg.player = VideoPlayer_VIDEO;
@@ -515,6 +514,8 @@ bool OMXPlayerVideo::OpenDecoder()
   if(!m_av_clock)
     return false;
 
+  m_processInfo.ResetVideoCodecInfo();
+
   if (m_hints.fpsrate && m_hints.fpsscale)
     m_fFrameRate = DVD_TIME_BASE / CDVDCodecUtils::NormalizeFrameduration((double)DVD_TIME_BASE * m_hints.fpsscale / m_hints.fpsrate);
   else
@@ -525,13 +526,15 @@ bool OMXPlayerVideo::OpenDecoder()
     CLog::Log(LOGINFO, "OMXPlayerVideo::OpenDecoder : Invalid framerate %d, using forced 25fps and just trust timestamps\n", (int)m_fFrameRate);
     m_fFrameRate = 25;
   }
+  m_processInfo.SetVideoFps(m_fFrameRate);
+
   // use aspect in stream if available
   if (m_hints.forced_aspect)
     m_fForcedAspectRatio = m_hints.aspect;
   else
     m_fForcedAspectRatio = 0.0;
 
-  bool bVideoDecoderOpen = m_omxVideo.Open(m_hints, m_av_clock, CMediaSettings::GetInstance().GetCurrentVideoSettings().m_DeinterlaceMode, m_hdmi_clock_sync);
+  bool bVideoDecoderOpen = m_omxVideo.Open(m_hints, m_av_clock, m_hdmi_clock_sync);
   m_omxVideo.RegisterResolutionUpdateCallBack((void *)this, ResolutionUpdateCallBack);
 
   if(!bVideoDecoderOpen)
@@ -544,7 +547,7 @@ bool OMXPlayerVideo::OpenDecoder()
     CLog::Log(LOGINFO, "OMXPlayerVideo::OpenDecoder : Video codec %s width %d height %d profile %d fps %f\n",
         m_omxVideo.GetDecoderName().c_str() , m_hints.width, m_hints.height, m_hints.profile, m_fFrameRate);
 
-    m_codecname = m_omxVideo.GetDecoderName();
+    m_processInfo.SetVideoDecoderName(m_omxVideo.GetDecoderName(), true);
   }
 
   return bVideoDecoderOpen;
@@ -635,11 +638,30 @@ void OMXPlayerVideo::SetVideoRect(const CRect &InSrcRect, const CRect &InDestRec
   // fix up transposed video
   if (m_hints.orientation == 90 || m_hints.orientation == 270)
   {
-    float diff = (DestRect.Height() - DestRect.Width()) * 0.5f;
-    DestRect.x1 -= diff;
-    DestRect.x2 += diff;
-    DestRect.y1 += diff;
-    DestRect.y2 -= diff;
+    float newWidth, newHeight;
+    float aspectRatio = GetAspectRatio();
+    // clamp width if too wide
+    if (DestRect.Height() > DestRect.Width())
+    {
+      newWidth = DestRect.Width(); // clamp to the width of the old dest rect
+      newHeight = newWidth * aspectRatio;
+    }
+    else // else clamp to height
+    {
+      newHeight = DestRect.Height(); // clamp to the height of the old dest rect
+      newWidth = newHeight / aspectRatio;
+    }
+
+    // calculate the center point of the view and offsets
+    float centerX = DestRect.x1 + DestRect.Width() * 0.5f;
+    float centerY = DestRect.y1 + DestRect.Height() * 0.5f;
+    float diffX = newWidth * 0.5f;
+    float diffY = newHeight * 0.5f;
+
+    DestRect.x1 = centerX - diffX;
+    DestRect.x2 = centerX + diffX;
+    DestRect.y1 = centerY - diffY;
+    DestRect.y2 = centerY + diffY;
   }
 
   // check if destination rect or video view mode has changed
@@ -705,6 +727,9 @@ void OMXPlayerVideo::ResolutionUpdateCallBack(uint32_t width, uint32_t height, f
     m_bAllowFullscreen = false; // only allow on first configure
   }
 
+  m_processInfo.SetVideoDimensions(width, height);
+  m_processInfo.SetVideoDAR(display_aspect);
+
   unsigned int iDisplayWidth  = width;
   unsigned int iDisplayHeight = height;
 
@@ -715,6 +740,7 @@ void OMXPlayerVideo::ResolutionUpdateCallBack(uint32_t width, uint32_t height, f
     iDisplayWidth = (int) (iDisplayHeight * display_aspect);
 
   m_fFrameRate = DVD_TIME_BASE / CDVDCodecUtils::NormalizeFrameduration((double)DVD_TIME_BASE / framerate);
+  m_processInfo.SetVideoFps(m_fFrameRate);
 
   CLog::Log(LOGDEBUG,"%s - change configuration. video:%dx%d. framerate: %4.2f. %dx%d format: BYPASS",
       __FUNCTION__, video_width, video_height, m_fFrameRate, iDisplayWidth, iDisplayHeight);
diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp
index 4c165bf..311dd66 100644
--- a/xbmc/cores/omxplayer/OMXVideo.cpp
+++ b/xbmc/cores/omxplayer/OMXVideo.cpp
@@ -65,14 +65,14 @@
 
 #define MAX_TEXT_LENGTH 1024
 
-COMXVideo::COMXVideo(CRenderManager& renderManager) : m_video_codec_name("")
+COMXVideo::COMXVideo(CRenderManager& renderManager, CProcessInfo &processInfo) : m_video_codec_name("")
 , m_renderManager(renderManager)
+, m_processInfo(processInfo)
 {
   m_is_open           = false;
   m_extradata         = NULL;
   m_extrasize         = 0;
   m_deinterlace       = false;
-  m_deinterlace_request = VS_DEINTERLACEMODE_OFF;
   m_hdmi_clock_sync   = false;
   m_drop_state        = false;
   m_decoded_width     = 0;
@@ -174,14 +174,9 @@ bool COMXVideo::PortSettingsChanged(ResolutionUpdateInfo &resinfo)
   interlace.nPortIndex = m_omx_decoder.GetOutputPort();
   omx_err = m_omx_decoder.GetConfig(OMX_IndexConfigCommonInterlace, &interlace);
 
-  if(m_deinterlace_request == VS_DEINTERLACEMODE_FORCE)
-    m_deinterlace = true;
-  else if(m_deinterlace_request == VS_DEINTERLACEMODE_OFF)
-    m_deinterlace = false;
-  else
-    m_deinterlace = interlace.eMode != OMX_InterlaceProgressive;
+  m_deinterlace = interlace.eMode != OMX_InterlaceProgressive;
 
-    CLog::Log(LOGDEBUG, "%s::%s - %dx%d@%.2f interlace:%d deinterlace:%d", CLASSNAME, __func__,
+  CLog::Log(LOGDEBUG, "%s::%s - %dx%d@%.2f interlace:%d deinterlace:%d", CLASSNAME, __func__,
       port_image.format.video.nFrameWidth, port_image.format.video.nFrameHeight,
       port_image.format.video.xFramerate / (float)(1<<16), interlace.eMode, m_deinterlace);
 
@@ -239,11 +234,27 @@ bool COMXVideo::PortSettingsChanged(ResolutionUpdateInfo &resinfo)
     }
   }
 
-  if(m_deinterlace)
+  EINTERLACEMETHOD interlace_method = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod;
+  if (interlace_method == VS_INTERLACEMETHOD_AUTO)
+    interlace_method = VS_INTERLACEMETHOD_MMAL_ADVANCED;
+
+  if (m_deinterlace && interlace_method != VS_INTERLACEMETHOD_NONE)
   {
-    EINTERLACEMETHOD interlace_method = m_renderManager.AutoInterlaceMethod(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod);
     bool advanced_deinterlace = interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED || interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF;
     bool half_framerate = interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF || interlace_method == VS_INTERLACEMETHOD_MMAL_BOB_HALF;
+
+    if (advanced_deinterlace && !half_framerate)
+       m_processInfo.SetVideoDeintMethod("adv(x2)");
+    else if (advanced_deinterlace && half_framerate)
+       m_processInfo.SetVideoDeintMethod("adv(x1)");
+    else if (!advanced_deinterlace && !half_framerate)
+       m_processInfo.SetVideoDeintMethod("bob(x2)");
+    else if (!advanced_deinterlace && half_framerate)
+       m_processInfo.SetVideoDeintMethod("bob(x1)");
+
+    if (!half_framerate)
+      resinfo.framerate *= 2.0f;
+
     if (!advanced_deinterlace)
     {
       // Image_fx assumed 3 frames of context. simple deinterlace doesn't require this
@@ -280,6 +291,10 @@ bool COMXVideo::PortSettingsChanged(ResolutionUpdateInfo &resinfo)
       return false;
     }
   }
+  else
+  {
+    m_processInfo.SetVideoDeintMethod("none");
+  }
 
   if(m_deinterlace)
   {
@@ -350,7 +365,7 @@ bool COMXVideo::PortSettingsChanged(ResolutionUpdateInfo &resinfo)
   return true;
 }
 
-bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE deinterlace, bool hdmi_clock_sync)
+bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, bool hdmi_clock_sync)
 {
   CSingleLock lock (m_critSection);
   bool vflip = false;
@@ -494,7 +509,6 @@ bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE de
       return false;
     break;
   }
-  m_deinterlace_request = deinterlace;
 
   if(!m_omx_decoder.Initialize(decoder_name, OMX_IndexParamVideoInit))
     return false;
@@ -658,9 +672,9 @@ bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE de
     return false;
 
   CLog::Log(LOGDEBUG,
-    "%s::%s - decoder_component(0x%p), input_port(0x%x), output_port(0x%x) deinterlace %d hdmiclocksync %d\n",
+    "%s::%s - decoder_component(0x%p), input_port(0x%x), output_port(0x%x) hdmiclocksync %d\n",
     CLASSNAME, __func__, m_omx_decoder.GetComponent(), m_omx_decoder.GetInputPort(), m_omx_decoder.GetOutputPort(),
-    m_deinterlace_request, m_hdmi_clock_sync);
+    m_hdmi_clock_sync);
 
   return true;
 }
diff --git a/xbmc/cores/omxplayer/OMXVideo.h b/xbmc/cores/omxplayer/OMXVideo.h
index 46e79cb..86296b5 100644
--- a/xbmc/cores/omxplayer/OMXVideo.h
+++ b/xbmc/cores/omxplayer/OMXVideo.h
@@ -34,6 +34,7 @@
 #include "threads/CriticalSection.h"
 #include "xbmc/rendering/RenderSystem.h"
 #include "cores/VideoPlayer/VideoRenderers/RenderManager.h"
+#include "cores/VideoPlayer/Process/ProcessInfo.h"
 #include <string>
 
 #define VIDEO_BUFFERS 60
@@ -53,12 +54,12 @@ struct ResolutionUpdateInfo {
 class COMXVideo
 {
 public:
-  COMXVideo(CRenderManager& renderManager);
+  COMXVideo(CRenderManager& renderManager, CProcessInfo &processInfo);
   ~COMXVideo();
 
   // Required overrides
   bool SendDecoderConfig();
-  bool Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE deinterlace = VS_DEINTERLACEMODE_OFF, bool hdmi_clock_sync = false);
+  bool Open(CDVDStreamInfo &hints, OMXClock *clock, bool hdmi_clock_sync = false);
   bool PortSettingsChanged(ResolutionUpdateInfo &resinfo);
   void RegisterResolutionUpdateCallBack(void *ctx, ResolutionUpdateCallBackFn callback) { m_res_ctx = ctx; m_res_callback = callback; }
   void Close(void);
@@ -103,7 +104,6 @@ protected:
   std::string       m_video_codec_name;
 
   bool              m_deinterlace;
-  EDEINTERLACEMODE  m_deinterlace_request;
   bool              m_hdmi_clock_sync;
   ResolutionUpdateCallBackFn m_res_callback;
   void              *m_res_ctx;
@@ -112,6 +112,7 @@ protected:
   OMX_DISPLAYTRANSFORMTYPE m_transform;
   bool              m_settings_changed;
   CRenderManager&   m_renderManager;
+  CProcessInfo&     m_processInfo;
   static bool NaluFormatStartCodes(enum AVCodecID codec, uint8_t *in_extradata, int in_extrasize);
   CCriticalSection m_critSection;
 };
diff --git a/xbmc/cores/paplayer/CMakeLists.txt b/xbmc/cores/paplayer/CMakeLists.txt
index 391738b..8da2e7c 100644
--- a/xbmc/cores/paplayer/CMakeLists.txt
+++ b/xbmc/cores/paplayer/CMakeLists.txt
@@ -11,8 +11,3 @@ set(HEADERS AudioDecoder.h
             VideoPlayerCodec.h)
 
 core_add_library(paplayer)
-add_dependencies(paplayer libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(paplayer ffmpeg)
-endif()
diff --git a/xbmc/cores/paplayer/PAPlayer.cpp b/xbmc/cores/paplayer/PAPlayer.cpp
index 17e1cfc..205b69d 100644
--- a/xbmc/cores/paplayer/PAPlayer.cpp
+++ b/xbmc/cores/paplayer/PAPlayer.cpp
@@ -21,6 +21,7 @@
 #include "PAPlayer.h"
 #include "CodecFactory.h"
 #include "FileItem.h"
+#include "ServiceBroker.h"
 #include "settings/AdvancedSettings.h"
 #include "settings/Settings.h"
 #include "music/tags/MusicInfoTag.h"
@@ -759,7 +760,7 @@ inline bool PAPlayer::ProcessStream(StreamInfo *si, double &freeBufferTime)
       time = si->m_startOffset;
       si->m_framesSent      = 0;
       si->m_seekNextAtFrame = 0;
-      ToFFRW(1);
+      SetSpeed(1);
     }
 
     si->m_decoder.Seek(time);
@@ -914,11 +915,6 @@ bool PAPlayer::IsPlaying() const
   return m_isPlaying;
 }
 
-bool PAPlayer::IsPaused() const
-{
-  return m_isPaused;
-}
-
 void PAPlayer::Pause()
 {
   if (m_isPaused)
@@ -945,12 +941,17 @@ void PAPlayer::SetDynamicRangeCompression(long drc)
 
 }
 
-void PAPlayer::ToFFRW(int iSpeed)
+void PAPlayer::SetSpeed(int iSpeed)
 {
-  m_playbackSpeed     = iSpeed;
+  m_playbackSpeed  = iSpeed;
   m_signalSpeedChange = true;
 }
 
+int PAPlayer::GetSpeed()
+{
+  return m_playbackSpeed;
+}
+
 int64_t PAPlayer::GetTimeInternal()
 {
   CSingleLock lock(m_streamsLock);
@@ -1079,7 +1080,7 @@ void PAPlayer::SeekTime(int64_t iTime /*=0*/)
   int seekOffset = (int)(iTime - GetTimeInternal());
 
   if (m_playbackSpeed != 1)
-    ToFFRW(1);
+    SetSpeed(1);
 
   m_currentStream->m_seekFrame = (int)((float)m_currentStream->m_audioFormat.m_sampleRate * ((float)iTime + (float)m_currentStream->m_startOffset) / 1000.0f);
   m_callback.OnPlayBackSeek((int)iTime, seekOffset);
@@ -1130,7 +1131,7 @@ void PAPlayer::UpdateGUIData(StreamInfo *si)
   total -= m_currentStream->m_startOffset;
   m_playerGUIData.m_totalTime = total;
 
-  g_dataCacheCore.SignalAudioInfoChange();
+  CServiceBroker::GetDataCacheCore().SignalAudioInfoChange();
 }
 
 void PAPlayer::OnJobComplete(unsigned int jobID, bool success, CJob *job)
diff --git a/xbmc/cores/paplayer/PAPlayer.h b/xbmc/cores/paplayer/PAPlayer.h
index b82a874..1f6edeb 100644
--- a/xbmc/cores/paplayer/PAPlayer.h
+++ b/xbmc/cores/paplayer/PAPlayer.h
@@ -20,6 +20,7 @@
  *
  */
 
+#include <atomic>
 #include <list>
 #include <vector>
 
@@ -49,8 +50,7 @@ public:
   virtual void OnNothingToQueueNotify();
   virtual bool CloseFile(bool reopen = false);
   virtual bool IsPlaying() const;
-  virtual void Pause();
-  virtual bool IsPaused() const;
+  virtual void Pause() override;
   virtual bool HasVideo() const { return false; }
   virtual bool HasAudio() const { return true; }
   virtual bool CanSeek();
@@ -61,7 +61,8 @@ public:
   virtual void SetDynamicRangeCompression(long drc);
   virtual void GetAudioInfo( std::string& strAudioInfo) {}
   virtual void GetVideoInfo( std::string& strVideoInfo) {}
-  virtual void ToFFRW(int iSpeed = 0);
+  virtual void SetSpeed(int iSpeed = 0) override;
+  virtual int GetSpeed() override;
   virtual int GetCacheLevel() const;
   virtual int64_t GetTotalTime();
   virtual void SetTotalTime(int64_t time);
@@ -125,7 +126,7 @@ private:
   typedef std::list<StreamInfo*> StreamList;
 
   bool                m_signalSpeedChange;   /* true if OnPlaybackSpeedChange needs to be called */
-  int                 m_playbackSpeed;       /* the playback speed (1 = normal) */
+  std::atomic_int m_playbackSpeed;           /* the playback speed (1 = normal) */
   bool                m_isPlaying;
   bool                m_isPaused;
   bool                m_isFinished;          /* if there are no more songs in the queue */
diff --git a/xbmc/cores/paplayer/VideoPlayerCodec.cpp b/xbmc/cores/paplayer/VideoPlayerCodec.cpp
index 9056cf8..32add6c 100644
--- a/xbmc/cores/paplayer/VideoPlayerCodec.cpp
+++ b/xbmc/cores/paplayer/VideoPlayerCodec.cpp
@@ -46,6 +46,8 @@ VideoPlayerCodec::VideoPlayerCodec()
   m_pResampler = NULL;
   m_needConvert = false;
   m_channels = 0;
+
+  m_processInfo.reset(CProcessInfo::CreateInstance());
 }
 
 VideoPlayerCodec::~VideoPlayerCodec()
@@ -165,7 +167,7 @@ bool VideoPlayerCodec::Init(const CFileItem &file, unsigned int filecache)
 
   CDVDStreamInfo hint(*pStream, true);
 
-  m_pAudioCodec = CDVDFactoryCodec::CreateAudioCodec(hint);
+  m_pAudioCodec = CDVDFactoryCodec::CreateAudioCodec(hint, *m_processInfo.get());
   if (!m_pAudioCodec)
   {
     CLog::Log(LOGERROR, "%s: Could not create audio codec", __FUNCTION__);
diff --git a/xbmc/cores/paplayer/VideoPlayerCodec.h b/xbmc/cores/paplayer/VideoPlayerCodec.h
index 81379bd..042f4f7 100644
--- a/xbmc/cores/paplayer/VideoPlayerCodec.h
+++ b/xbmc/cores/paplayer/VideoPlayerCodec.h
@@ -73,6 +73,8 @@ private:
   bool m_needConvert;
   AEAudioFormat m_srcFormat;
   int m_channels;
+
+  std::unique_ptr<CProcessInfo> m_processInfo;
 };
 
 #endif
diff --git a/xbmc/cores/playercorefactory/CMakeLists.txt b/xbmc/cores/playercorefactory/CMakeLists.txt
index d52461e..0cb4d3b 100644
--- a/xbmc/cores/playercorefactory/CMakeLists.txt
+++ b/xbmc/cores/playercorefactory/CMakeLists.txt
@@ -6,7 +6,3 @@ set(HEADERS PlayerCoreConfig.h
             PlayerSelectionRule.h)
 
 core_add_library(playercorefactory)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(playercorefactory ffmpeg)
-endif()
diff --git a/xbmc/dialogs/CMakeLists.txt b/xbmc/dialogs/CMakeLists.txt
index abdd6ee..1fdffbd 100644
--- a/xbmc/dialogs/CMakeLists.txt
+++ b/xbmc/dialogs/CMakeLists.txt
@@ -16,6 +16,7 @@ set(SOURCES GUIDialogBoxBase.cpp
             GUIDialogOK.cpp
             GUIDialogPlayEject.cpp
             GUIDialogPlayerControls.cpp
+            GUIDialogPlayerProcessInfo.cpp
             GUIDialogProgress.cpp
             GUIDialogSeekBar.cpp
             GUIDialogSelect.cpp
@@ -46,6 +47,7 @@ set(HEADERS GUIDialogBoxBase.h
             GUIDialogOK.h
             GUIDialogPlayEject.h
             GUIDialogPlayerControls.h
+            GUIDialogPlayerProcessInfo.h
             GUIDialogProgress.h
             GUIDialogSeekBar.h
             GUIDialogSelect.h
@@ -59,8 +61,3 @@ set(HEADERS GUIDialogBoxBase.h
             GUIDialogYesNo.h)
 
 core_add_library(dialogs)
-add_dependencies(dialogs libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(dialogs ffmpeg)
-endif()
diff --git a/xbmc/dialogs/GUIDialogKeyboardGeneric.h b/xbmc/dialogs/GUIDialogKeyboardGeneric.h
index 1694733..5fd5b93 100644
--- a/xbmc/dialogs/GUIDialogKeyboardGeneric.h
+++ b/xbmc/dialogs/GUIDialogKeyboardGeneric.h
@@ -87,7 +87,7 @@ class CGUIDialogKeyboardGeneric : public CGUIDialog, public CGUIKeyboard
     std::string m_strHeading;
     std::string m_text;       ///< current text
 
-    IInputCodingTable *m_codingtable;
+    IInputCodingTablePtr m_codingtable;
     std::vector<std::wstring> m_words;
     std::string m_hzcode;
     int         m_pos;
diff --git a/xbmc/utils/Crc32.h b/xbmc/dialogs/GUIDialogPlayerProcessInfo.cpp
similarity index 54%
copy from xbmc/utils/Crc32.h
copy to xbmc/dialogs/GUIDialogPlayerProcessInfo.cpp
index 3d30c8f..bf6b9a7 100644
--- a/xbmc/utils/Crc32.h
+++ b/xbmc/dialogs/GUIDialogPlayerProcessInfo.cpp
@@ -1,6 +1,6 @@
 /*
- *      Copyright (C) 2005-2013 Team XBMC
- *      http://xbmc.org
+ *      Copyright (C) 2005-2016 Team Kodi
+ *      http://kodi.tv
  *
  *  This Program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -18,26 +18,26 @@
  *
  */
 
-#pragma once
+#include "GUIDialogPlayerProcessInfo.h"
 
-#include <string>
-#include <stdint.h>
+#include "input/Key.h"
 
-class Crc32
+CGUIDialogPlayerProcessInfo::CGUIDialogPlayerProcessInfo(void)
+    : CGUIDialog(WINDOW_DIALOG_PLAYER_PROCESS_INFO, "DialogPlayerProcessInfo.xml")
 {
-public:
-  Crc32();
-  void Reset();
-  void Compute(const char* buffer, size_t count);
-  void Compute(const std::string& strValue);
-  void ComputeFromLowerCase(const std::string& strValue);
+  m_loadType = KEEP_IN_MEMORY;
+}
 
-  operator uint32_t () const
+CGUIDialogPlayerProcessInfo::~CGUIDialogPlayerProcessInfo(void)
+{
+}
+
+bool CGUIDialogPlayerProcessInfo::OnAction(const CAction &action)
+{
+  if (action.GetID() == ACTION_PLAYER_PROCESS_INFO)
   {
-    return m_crc;
+    Close();
+    return true;
   }
-
-private:
-  uint32_t m_crc;
-};
-
+  return CGUIDialog::OnAction(action);
+}
\ No newline at end of file
diff --git a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h b/xbmc/dialogs/GUIDialogPlayerProcessInfo.h
similarity index 70%
copy from xbmc/cores/VideoPlayer/Process/ProcessInfo.h
copy to xbmc/dialogs/GUIDialogPlayerProcessInfo.h
index b8a4e46..f5063d0 100644
--- a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h
+++ b/xbmc/dialogs/GUIDialogPlayerProcessInfo.h
@@ -1,6 +1,8 @@
+#pragma once
+
 /*
- *      Copyright (C) 2005-2016 Team XBMC
- *      http://xbmc.org
+ *      Copyright (C) 2005-2016 Team Kodi
+ *      http://kodi.tv
  *
  *  This Program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -17,18 +19,14 @@
  *  <http://www.gnu.org/licenses/>.
  *
  */
-#pragma once
 
-#include "cores/IPlayer.h"
+#include "guilib/GUIDialog.h"
 
-class CProcessInfo
+class CGUIDialogPlayerProcessInfo : public CGUIDialog
 {
 public:
-  static CProcessInfo* CreateInstance();
-  virtual ~CProcessInfo();
-  virtual EINTERLACEMETHOD GetFallbackDeintMethod();
-  virtual bool AllowDTSHDDecode();
+  CGUIDialogPlayerProcessInfo(void);
+  virtual ~CGUIDialogPlayerProcessInfo(void);
 
-protected:
-  CProcessInfo();
+  bool OnAction(const CAction &action) override;
 };
diff --git a/xbmc/dialogs/Makefile b/xbmc/dialogs/Makefile
index 5bb8869..9175e37 100644
--- a/xbmc/dialogs/Makefile
+++ b/xbmc/dialogs/Makefile
@@ -16,6 +16,7 @@ SRCS=GUIDialogBoxBase.cpp \
      GUIDialogOK.cpp \
      GUIDialogPlayEject.cpp \
      GUIDialogPlayerControls.cpp \
+     GUIDialogPlayerProcessInfo.cpp \
      GUIDialogProgress.cpp \
      GUIDialogSeekBar.cpp \
      GUIDialogSelect.cpp \
diff --git a/xbmc/epg/CMakeLists.txt b/xbmc/epg/CMakeLists.txt
index 98fde22..e2c3a0d 100644
--- a/xbmc/epg/CMakeLists.txt
+++ b/xbmc/epg/CMakeLists.txt
@@ -15,4 +15,3 @@ set(HEADERS Epg.h
             GUIEPGGridContainerModel.h)
 
 core_add_library(epg)
-add_dependencies(epg libcpluff)
diff --git a/xbmc/epg/Epg.cpp b/xbmc/epg/Epg.cpp
index b8e09b8..2c778cd 100644
--- a/xbmc/epg/Epg.cpp
+++ b/xbmc/epg/Epg.cpp
@@ -309,129 +309,6 @@ void CEpg::AddEntry(const CEpgInfoTag &tag)
   }
 }
 
-bool CEpg::UpdateEntry(const EPG_TAG *data, bool bUpdateDatabase /* = false */)
-{
-  if (!data)
-    return false;
-
-  CEpgInfoTagPtr tag(new CEpgInfoTag(*data));
-  return UpdateEntry(tag, false, bUpdateDatabase);
-}
-
-bool CEpg::UpdateEntry(const CEpgInfoTagPtr &tag, bool bNotifyObservers, bool bUpdateDatabase /* = false */)
-{
-  CSingleLock lock(m_critSection);
-  auto it = m_tags.find(tag->StartAsUTC());
-  EPG_EVENT_STATE state = (it == m_tags.end()) ? EPG_EVENT_CREATED : EPG_EVENT_UPDATED;
-
-  if (UpdateEntry(tag, state, it, bUpdateDatabase))
-  {
-    if (bNotifyObservers)
-    {
-      SetChanged();
-      lock.Leave();
-      NotifyObservers(ObservableMessageEpg);
-    }
-    return true;
-  }
-  return false;
-}
-
-bool CEpg::UpdateEntry(const CEpgInfoTagPtr &tag, EPG_EVENT_STATE newState, bool bUpdateDatabase /* = false */)
-{
-  CSingleLock lock(m_critSection);
-  auto it = m_tags.end();
-  if (UpdateEntry(tag, newState, it, bUpdateDatabase))
-  {
-    SetChanged();
-    lock.Leave();
-    NotifyObservers(ObservableMessageEpg);
-    return true;
-  }
-  return false;
-}
-
-bool CEpg::UpdateEntry(const CEpgInfoTagPtr &tag, EPG_EVENT_STATE newState, std::map<CDateTime, CEpgInfoTagPtr>::iterator &eit, bool bUpdateDatabase /* = false */)
-{
-  CEpgInfoTagPtr infoTag;
-  bool bNewTag(false);
-
-  CSingleLock lock(m_critSection);
-
-  if (newState == EPG_EVENT_CREATED || newState == EPG_EVENT_UPDATED)
-  {
-    // Reuse passed iterator in favor of doing expensive find self
-    auto it = (eit == m_tags.end()) ? m_tags.find(tag->StartAsUTC()) : eit;
-    if (it != m_tags.end())
-    {
-      if (newState == EPG_EVENT_CREATED)
-        CLog::Log(LOGERROR, "EPG - %s - Error: EPG_EVENT_CREATED: uid %d found! Updating existing event.", __FUNCTION__, tag->UniqueBroadcastID());
-
-      infoTag = it->second;
-    }
-    else
-    {
-      if (newState == EPG_EVENT_UPDATED)
-        CLog::Log(LOGERROR, "EPG - %s - Error: EPG_EVENT_UPDATED: uid %d not found. Inserting new event.", __FUNCTION__, tag->UniqueBroadcastID());
-
-      infoTag.reset(new CEpgInfoTag(this, m_pvrChannel, m_strName, m_pvrChannel ? m_pvrChannel->IconPath() : ""));
-      infoTag->SetUniqueBroadcastID(tag->UniqueBroadcastID());
-      m_tags.insert(std::make_pair(tag->StartAsUTC(), infoTag));
-      bNewTag = true;
-    }
-  }
-  else if (newState == EPG_EVENT_DELETED)
-  {
-    // Reuse passed iterator in favor of doing expensive find self
-    auto it = (eit == m_tags.end()) ? m_tags.find(tag->StartAsUTC()) : eit;
-    if (it == m_tags.end())
-    {
-      // It is not guaranteed that the deleted tag contains valid start time. search sequential.
-      for (it = m_tags.begin(); it != m_tags.end(); ++it)
-      {
-        if (it->second->UniqueBroadcastID() == tag->UniqueBroadcastID())
-          break;
-      }
-    }
-
-    if (it != m_tags.end())
-    {
-      // Respect epg linger time.
-      const CDateTime cleanupTime(CDateTime::GetUTCDateTime() - CDateTimeSpan(0, g_advancedSettings.m_iEpgLingerTime / 60, g_advancedSettings.m_iEpgLingerTime % 60, 0));
-      if (it->second->EndAsUTC() < cleanupTime)
-      {
-        if (bUpdateDatabase)
-          m_deletedTags.insert(std::make_pair(it->second->UniqueBroadcastID(), it->second));
-
-        it->second->ClearTimer();
-        m_tags.erase(it);
-      }
-    }
-    else
-    {
-      CLog::Log(LOGERROR, "EPG - %s - Error: EPG_EVENT_DELETED: uid %d not found.", __FUNCTION__, tag->UniqueBroadcastID());
-      return false;
-    }
-
-    return true;
-  }
-  else
-  {
-    CLog::Log(LOGERROR, "EPG - %s - unknownn epg event state '%d'.", __FUNCTION__, newState);
-    return false;
-  }
-
-  infoTag->Update(*tag, bNewTag);
-  infoTag->SetEpg(this);
-  infoTag->SetPVRChannel(m_pvrChannel);
-  infoTag->SetTimer(g_PVRTimers->GetTimerForEpgTag(infoTag));
-
-  if (bUpdateDatabase)
-    m_changedTags.insert(std::make_pair(infoTag->UniqueBroadcastID(), infoTag));
-
-  return true;
-}
-
 bool CEpg::Load(void)
 {
   bool bReturn(false);
@@ -471,7 +348,7 @@ bool CEpg::UpdateEntries(const CEpg &epg, bool bStoreInDb /* = true */)
 #endif
   /* copy over tags */
   for (std::map<CDateTime, CEpgInfoTagPtr>::const_iterator it = epg.m_tags.begin(); it != epg.m_tags.end(); ++it)
-    UpdateEntry(it->second, false, bStoreInDb);
+    UpdateEntry(it->second, bStoreInDb);
 
 #if EPG_DEBUGGING
   CLog::Log(LOGDEBUG, "EPG - %s - %" PRIuS" entries in memory after merging and before fixing", __FUNCTION__, m_tags.size());
@@ -522,6 +399,102 @@ CDateTime CEpg::GetLastScanTime(void)
   return m_lastScanTime;
 }
 
+bool CEpg::UpdateEntry(const EPG_TAG *data, bool bUpdateDatabase /* = false */)
+{
+  if (!data)
+    return false;
+
+  CEpgInfoTagPtr tag(new CEpgInfoTag(*data));
+  return UpdateEntry(tag, bUpdateDatabase);
+}
+
+bool CEpg::UpdateEntry(const CEpgInfoTagPtr &tag, bool bUpdateDatabase /* = false */)
+{
+  CEpgInfoTagPtr infoTag;
+  CSingleLock lock(m_critSection);
+  std::map<CDateTime, CEpgInfoTagPtr>::iterator it = m_tags.find(tag->StartAsUTC());
+  bool bNewTag(false);
+  if (it != m_tags.end())
+  {
+    infoTag = it->second;
+  }
+  else
+  {
+    infoTag.reset(new CEpgInfoTag(this, m_pvrChannel, m_strName, m_pvrChannel ? m_pvrChannel->IconPath() : ""));
+    infoTag->SetUniqueBroadcastID(tag->UniqueBroadcastID());
+    m_tags.insert(std::make_pair(tag->StartAsUTC(), infoTag));
+    bNewTag = true;
+  }
+
+  infoTag->Update(*tag, bNewTag);
+  infoTag->SetEpg(this);
+  infoTag->SetPVRChannel(m_pvrChannel);
+  infoTag->SetTimer(g_PVRTimers->GetTimerForEpgTag(infoTag));
+
+  if (bUpdateDatabase)
+    m_changedTags.insert(std::make_pair(infoTag->UniqueBroadcastID(), infoTag));
+
+  return true;
+}
+
+bool CEpg::UpdateEntry(const CEpgInfoTagPtr &tag, EPG_EVENT_STATE newState, bool bUpdateDatabase /* = false */)
+{
+  bool bRet(true);
+  bool bNotify(true);
+
+  if (newState == EPG_EVENT_CREATED || newState == EPG_EVENT_UPDATED)
+  {
+    bRet = UpdateEntry(tag, bUpdateDatabase);
+  }
+  else if (newState == EPG_EVENT_DELETED)
+  {
+    CSingleLock lock(m_critSection);
+
+    auto it = m_tags.begin();
+    for (; it != m_tags.end(); ++it)
+    {
+      if (it->second->UniqueBroadcastID() == tag->UniqueBroadcastID())
+        break;
+    }
+
+    if (it == m_tags.end())
+    {
+      CLog::Log(LOGERROR, "EPG - %s - Error: EPG_EVENT_DELETED: uid %d not found.", __FUNCTION__, tag->UniqueBroadcastID());
+      bRet = false;
+    }
+    else
+    {
+      // Respect epg linger time.
+      const CDateTime cleanupTime(CDateTime::GetUTCDateTime() - CDateTimeSpan(0, g_advancedSettings.m_iEpgLingerTime / 60, g_advancedSettings.m_iEpgLingerTime % 60, 0));
+      if (it->second->EndAsUTC() < cleanupTime)
+      {
+        if (bUpdateDatabase)
+          m_deletedTags.insert(std::make_pair(it->second->UniqueBroadcastID(), it->second));
+
+        it->second->ClearTimer();
+        m_tags.erase(it);
+      }
+      else
+      {
+        bNotify = false;
+      }
+    }
+  }
+  else
+  {
+    CLog::Log(LOGERROR, "EPG - %s - unknown epg event state value: %d", __FUNCTION__, newState);
+    bRet = false;
+  }
+
+  if (bRet && bNotify)
+  {
+    SetChanged();
+    NotifyObservers(ObservableMessageEpg);
+  }
+
+  return bRet;
+}
+
 bool CEpg::Update(const time_t start, const time_t end, int iUpdateTime, bool bForceUpdate /* = false */)
 {
   bool bGrabSuccess(true);
diff --git a/xbmc/epg/Epg.h b/xbmc/epg/Epg.h
index d47c8d0..1a803ea 100644
--- a/xbmc/epg/Epg.h
+++ b/xbmc/epg/Epg.h
@@ -191,12 +191,19 @@ namespace EPG
 
     /*!
      * @brief Update an entry in this EPG.
+     * @param data The tag to update.
+     * @param bUpdateDatabase If set to true, this event will be persisted in the database.
+     * @return True if it was updated successfully, false otherwise.
+     */
+    bool UpdateEntry(const EPG_TAG *data, bool bUpdateDatabase = false);
+
+    /*!
+     * @brief Update an entry in this EPG.
      * @param tag The tag to update.
-     * @param bNotifyObservers True if observers should be notified
      * @param bUpdateDatabase If set to true, this event will be persisted in the database.
      * @return True if it was updated successfully, false otherwise.
      */
-    bool UpdateEntry(const CEpgInfoTagPtr &tag, bool bNotifyObservers, bool bUpdateDatabase = false);
+    bool UpdateEntry(const CEpgInfoTagPtr &tag, bool bUpdateDatabase = false);
 
     /*!
      * @brief Update an entry in this EPG.
@@ -268,14 +275,6 @@ namespace EPG
      */
     static const std::string &ConvertGenreIdToString(int iID, int iSubID);
 
-    /*!
-     * @brief Update an entry in this EPG.
-     * @param data The tag to update.
-     * @param bUpdateDatabase If set to true, this event will be persisted in the database.
-     * @return True if it was updated successfully, false otherwise.
-     */
-    bool UpdateEntry(const EPG_TAG *data, bool bUpdateDatabase = false);
-
     CEpgInfoTagPtr GetNextEvent(const CEpgInfoTag& tag) const;
 
     size_t Size(void) const;
@@ -291,16 +290,6 @@ namespace EPG
     CEpg(void);
 
     /*!
-     * @brief Update an entry in this EPG.
-     * @param data The tag to update.
-     * @param newState The new state of the event.
-     * @param it An iterator pointing to m_tags entry for the EPG event to update or m_tags.end().
-     * @param bUpdateDatabase If set to true, this event will be persisted in the database.
-     * @return True if it was updated successfully, false otherwise.
-     */
-    bool UpdateEntry(const CEpgInfoTagPtr &tag, EPG_EVENT_STATE newState, std::map<CDateTime, CEpgInfoTagPtr>::iterator &eit, bool bUpdateDatabase = false);
-
-    /*!
      * @brief Update the EPG from a scraper set in the channel tag.
      * @todo not implemented yet for non-pvr EPGs
      * @param start Get entries with a start date after this time.
diff --git a/xbmc/events/CMakeLists.txt b/xbmc/events/CMakeLists.txt
index 5abd9cb..8a602d7 100644
--- a/xbmc/events/CMakeLists.txt
+++ b/xbmc/events/CMakeLists.txt
@@ -14,4 +14,3 @@ set(HEADERS AddonEvent.h
             UniqueEvent.h)
 
 core_add_library(events)
-add_dependencies(events libcpluff)
diff --git a/xbmc/filesystem/AddonsDirectory.cpp b/xbmc/filesystem/AddonsDirectory.cpp
index f176161..fc252a4 100644
--- a/xbmc/filesystem/AddonsDirectory.cpp
+++ b/xbmc/filesystem/AddonsDirectory.cpp
@@ -556,9 +556,6 @@ bool CAddonsDirectory::GetDirectory(const CURL& url, CFileItemList &items)
     if (!GetRecentlyUpdatedAddons(addons))
       return false;
 
-    std::sort(addons.begin(), addons.end(),
-        [](const AddonPtr& a, const AddonPtr& b){ return a->LastUpdated() > b->LastUpdated(); });
-
     CAddonsDirectory::GenerateAddonListing(path, addons, items, g_localizeStrings.Get(24004));
     return true;
 
diff --git a/xbmc/filesystem/CMakeLists.txt b/xbmc/filesystem/CMakeLists.txt
index 6818acf..93b4672 100644
--- a/xbmc/filesystem/CMakeLists.txt
+++ b/xbmc/filesystem/CMakeLists.txt
@@ -180,21 +180,7 @@ if(BLURAY_FOUND)
                       BlurayFile.h)
 endif()
 
-include_directories(${CORE_SOURCE_DIR}/lib/libUPnP
-                    ${CORE_SOURCE_DIR}/lib/libUPnP/Platinum/Source/Core
-                    ${CORE_SOURCE_DIR}/lib/libUPnP/Platinum/Source/Platinum
-                    ${CORE_SOURCE_DIR}/lib/libUPnP/Platinum/Source/Devices/MediaConnect
-                    ${CORE_SOURCE_DIR}/lib/libUPnP/Platinum/Source/Devices/MediaRenderer
-                    ${CORE_SOURCE_DIR}/lib/libUPnP/Platinum/Source/Devices/MediaServer
-                    ${CORE_SOURCE_DIR}/lib/libUPnP/Platinum/Source/Extras
-                    ${CORE_SOURCE_DIR}/lib/libUPnP/Neptune/Source/System/Posix
-                    ${CORE_SOURCE_DIR}/lib/libUPnP/Neptune/Source/Core)
-
-add_definitions(-DNPT_CONFIG_ENABLE_LOGGING)
-
-core_add_library(filesystem)
-add_dependencies(filesystem libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(filesystem ffmpeg)
+core_add_library(filesystem upnp)
+if(ENABLE_STATIC_LIBS)
+  target_link_libraries(filesystem PRIVATE upnp)
 endif()
diff --git a/xbmc/filesystem/MusicDatabaseDirectory.cpp b/xbmc/filesystem/MusicDatabaseDirectory.cpp
index 1797543..c76043d 100644
--- a/xbmc/filesystem/MusicDatabaseDirectory.cpp
+++ b/xbmc/filesystem/MusicDatabaseDirectory.cpp
@@ -117,10 +117,9 @@ void CMusicDatabaseDirectory::ClearDirectoryCache(const std::string& strDirector
   std::string path = CLegacyPathTranslation::TranslateMusicDbPath(strDirectory);
   URIUtils::RemoveSlashAtEnd(path);
 
-  Crc32 crc;
-  crc.ComputeFromLowerCase(path);
+  uint32_t crc = Crc32::ComputeFromLowerCase(path);
 
-  std::string strFileName = StringUtils::Format("special://temp/%08x.fi", (unsigned __int32) crc);
+  std::string strFileName = StringUtils::Format("special://temp/archive_cache/%08x.fi", crc);
   CFile::Delete(strFileName);
 }
 
diff --git a/xbmc/filesystem/PluginDirectory.cpp b/xbmc/filesystem/PluginDirectory.cpp
index bcadd68..76eaf43 100644
--- a/xbmc/filesystem/PluginDirectory.cpp
+++ b/xbmc/filesystem/PluginDirectory.cpp
@@ -71,7 +71,8 @@ void CPluginDirectory::CScriptObserver::Abort()
 }
 
 CPluginDirectory::CPluginDirectory()
-  : m_cancelled(false)
+  : m_fetchComplete(true)
+  , m_cancelled(false)
   , m_success(false)
   , m_totalItems(0)
 {
@@ -474,8 +475,6 @@ bool CPluginDirectory::RunScriptWithParams(const std::string& strPath)
 
 bool CPluginDirectory::WaitOnScriptResult(const std::string &scriptPath, int scriptId, const std::string &scriptName, bool retrievingDir)
 {
-  bool cancelled = false;
-
   // CPluginDirectory::GetDirectory can be called from the main and other threads.
   // If called form the main thread, we need to bring up the BusyDialog in order to
   // keep the render loop alive
@@ -486,21 +485,26 @@ bool CPluginDirectory::WaitOnScriptResult(const std::string &scriptPath, int scr
       CScriptObserver scriptObs(scriptId, m_fetchComplete);
       if (!CGUIDialogBusy::WaitOnEvent(m_fetchComplete, 200))
       {
-        cancelled = true;
+        m_cancelled = true;
       }
       scriptObs.Abort();
     }
   }
   else
   {
-    // kill the script if it does not return within 30 seconds
-    if (!m_fetchComplete.WaitMSec(30000))
-    {
-      cancelled = true;
-    }
+    // Wait for directory fetch to complete, end, or be cancelled
+    while (!m_cancelled
+        && CScriptInvocationManager::GetInstance().IsRunning(scriptId)
+        && !m_fetchComplete.WaitMSec(20));
+
+    // Give the script 30 seconds to exit before we attempt to stop it
+    XbmcThreads::EndTime timer(30000);
+    while (!timer.IsTimePast()
+          && CScriptInvocationManager::GetInstance().IsRunning(scriptId)
+          && !m_fetchComplete.WaitMSec(20));
   }
 
-  if (cancelled)
+  if (m_cancelled)
   { // cancel our script
     if (scriptId != -1 && CScriptInvocationManager::GetInstance().IsRunning(scriptId))
     {
@@ -509,7 +513,7 @@ bool CPluginDirectory::WaitOnScriptResult(const std::string &scriptPath, int scr
     }
   }
 
-  return !cancelled && m_success;
+  return !m_cancelled && m_success;
 }
 
 void CPluginDirectory::SetResolvedUrl(int handle, bool success, const CFileItem *resultItem)
diff --git a/xbmc/filesystem/PluginDirectory.h b/xbmc/filesystem/PluginDirectory.h
index dbf0b05..41d5138 100644
--- a/xbmc/filesystem/PluginDirectory.h
+++ b/xbmc/filesystem/PluginDirectory.h
@@ -22,6 +22,7 @@
 #include "IDirectory.h"
 #include "SortFileItem.h"
 
+#include <atomic>
 #include <string>
 #include <map>
 #include "threads/CriticalSection.h"
@@ -79,7 +80,7 @@ private:
   CFileItem*     m_fileResult;
   CEvent         m_fetchComplete;
 
-  bool          m_cancelled;    // set to true when we are cancelled
+  std::atomic<bool> m_cancelled;
   bool          m_success;      // set by script in EndOfDirectory
   int    m_totalItems;   // set by script in AddDirectoryItem
 
diff --git a/xbmc/filesystem/SpecialProtocol.cpp b/xbmc/filesystem/SpecialProtocol.cpp
index 80b2581..e84b25b 100644
--- a/xbmc/filesystem/SpecialProtocol.cpp
+++ b/xbmc/filesystem/SpecialProtocol.cpp
@@ -50,6 +50,11 @@ void CSpecialProtocol::SetXBMCBinPath(const std::string &dir)
   SetPath("xbmcbin", dir);
 }
 
+void CSpecialProtocol::SetXBMCBinAddonPath(const std::string &dir)
+{
+  SetPath("xbmcbinaddons", dir);
+}
+
 void CSpecialProtocol::SetXBMCFrameworksPath(const std::string &dir)
 {
   SetPath("frameworks", dir);
@@ -65,6 +70,11 @@ void CSpecialProtocol::SetUserHomePath(const std::string &dir)
   SetPath("userhome", dir);
 }
 
+void CSpecialProtocol::SetEnvHomePath(const std::string &dir)
+{
+  SetPath("envhome", dir);
+}
+
 void CSpecialProtocol::SetMasterProfilePath(const std::string &dir)
 {
   SetPath("masterprofile", dir);
@@ -153,7 +163,9 @@ std::string CSpecialProtocol::TranslatePath(const CURL &url)
   // from here on, we have our "real" special paths
   else if (RootDir == "xbmc" ||
            RootDir == "xbmcbin" ||
+           RootDir == "xbmcbinaddons" ||
            RootDir == "home" ||
+           RootDir == "envhome" ||
            RootDir == "userhome" ||
            RootDir == "temp" ||
            RootDir == "profile" ||
@@ -246,7 +258,11 @@ void CSpecialProtocol::LogPaths()
 {
   CLog::Log(LOGNOTICE, "special://xbmc/ is mapped to: %s", GetPath("xbmc").c_str());
   CLog::Log(LOGNOTICE, "special://xbmcbin/ is mapped to: %s", GetPath("xbmcbin").c_str());
+  CLog::Log(LOGNOTICE, "special://xbmcbinaddons/ is mapped to: %s", GetPath("xbmcbinaddons").c_str());
   CLog::Log(LOGNOTICE, "special://masterprofile/ is mapped to: %s", GetPath("masterprofile").c_str());
+#if defined(TARGET_POSIX)
+  CLog::Log(LOGNOTICE, "special://envhome/ is mapped to: %s", GetPath("envhome").c_str());
+#endif
   CLog::Log(LOGNOTICE, "special://home/ is mapped to: %s", GetPath("home").c_str());
   CLog::Log(LOGNOTICE, "special://temp/ is mapped to: %s", GetPath("temp").c_str());
   CLog::Log(LOGNOTICE, "special://logpath/ is mapped to: %s", GetPath("logpath").c_str());
diff --git a/xbmc/filesystem/SpecialProtocol.h b/xbmc/filesystem/SpecialProtocol.h
index 6ba7864..d936546 100644
--- a/xbmc/filesystem/SpecialProtocol.h
+++ b/xbmc/filesystem/SpecialProtocol.h
@@ -31,6 +31,7 @@
                              Linux: ~/.kodi/
                              OS X:  ~/Library/Application Support/Kodi/
                              Win32: ~/Application Data/XBMC/
+ special://envhome/       - on posix systems this will be equal to the $HOME
  special://userhome/      - a writable version of the user home directory
                              Linux, OS X: ~/.kodi
                              Win32: home directory of user
@@ -55,9 +56,11 @@ public:
   static void SetProfilePath(const std::string &path);
   static void SetXBMCPath(const std::string &path);
   static void SetXBMCBinPath(const std::string &path);
+  static void SetXBMCBinAddonPath(const std::string &path);
   static void SetXBMCFrameworksPath(const std::string &path);
   static void SetHomePath(const std::string &path);
   static void SetUserHomePath(const std::string &path);
+  static void SetEnvHomePath(const std::string &path);
   static void SetMasterProfilePath(const std::string &path);
   static void SetTempPath(const std::string &path);
   static void SetLogPath(const std::string &dir);
diff --git a/xbmc/filesystem/VideoDatabaseDirectory.cpp b/xbmc/filesystem/VideoDatabaseDirectory.cpp
index e8c26de..4ff3543 100644
--- a/xbmc/filesystem/VideoDatabaseDirectory.cpp
+++ b/xbmc/filesystem/VideoDatabaseDirectory.cpp
@@ -123,10 +123,9 @@ void CVideoDatabaseDirectory::ClearDirectoryCache(const std::string& strDirector
   std::string path = CLegacyPathTranslation::TranslateVideoDbPath(strDirectory);
   URIUtils::RemoveSlashAtEnd(path);
 
-  Crc32 crc;
-  crc.ComputeFromLowerCase(path);
+  uint32_t crc = Crc32::ComputeFromLowerCase(path);
 
-  std::string strFileName = StringUtils::Format("special://temp/%08x.fi", (unsigned __int32) crc);
+  std::string strFileName = StringUtils::Format("special://temp/archive_cache/%08x.fi", crc);
   CFile::Delete(strFileName);
 }
 
diff --git a/xbmc/filesystem/win32/Win32Directory.cpp b/xbmc/filesystem/win32/Win32Directory.cpp
index 41abde4..339cefa 100644
--- a/xbmc/filesystem/win32/Win32Directory.cpp
+++ b/xbmc/filesystem/win32/Win32Directory.cpp
@@ -21,7 +21,7 @@
 #ifdef TARGET_WINDOWS
 #include "Win32Directory.h"
 #include "FileItem.h"
-#include "win32/WIN32Util.h"
+#include "platform/win32/WIN32Util.h"
 #include "utils/SystemInfo.h"
 #include "utils/CharsetConverter.h"
 #include "URL.h"
diff --git a/xbmc/filesystem/win32/Win32File.cpp b/xbmc/filesystem/win32/Win32File.cpp
index 645b1b9..9389d74 100644
--- a/xbmc/filesystem/win32/Win32File.cpp
+++ b/xbmc/filesystem/win32/Win32File.cpp
@@ -20,7 +20,7 @@
 
 #ifdef TARGET_WINDOWS
 #include "Win32File.h"
-#include "win32/WIN32Util.h"
+#include "platform/win32/WIN32Util.h"
 #include "utils/win32/Win32Log.h"
 #include "utils/SystemInfo.h"
 #include "utils/auto_buffer.h"
diff --git a/xbmc/filesystem/win32/Win32SMBDirectory.cpp b/xbmc/filesystem/win32/Win32SMBDirectory.cpp
index ad594a8..97060ea 100644
--- a/xbmc/filesystem/win32/Win32SMBDirectory.cpp
+++ b/xbmc/filesystem/win32/Win32SMBDirectory.cpp
@@ -22,7 +22,7 @@
 
 #include "Win32SMBDirectory.h"
 #include "FileItem.h"
-#include "win32/WIN32Util.h"
+#include "platform/win32/WIN32Util.h"
 #include "utils/SystemInfo.h"
 #include "utils/CharsetConverter.h"
 #include "URL.h"
diff --git a/xbmc/filesystem/win32/Win32SMBFile.cpp b/xbmc/filesystem/win32/Win32SMBFile.cpp
index 2282ce1..42fc167 100644
--- a/xbmc/filesystem/win32/Win32SMBFile.cpp
+++ b/xbmc/filesystem/win32/Win32SMBFile.cpp
@@ -22,7 +22,7 @@
 #include "Win32SMBFile.h"
 #include "Win32SMBDirectory.h"
 #include "URL.h"
-#include "win32/WIN32Util.h"
+#include "platform/win32/WIN32Util.h"
 
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN 1
diff --git a/xbmc/games/controllers/windows/CMakeLists.txt b/xbmc/games/controllers/windows/CMakeLists.txt
index b56fed4..147f8b9 100644
--- a/xbmc/games/controllers/windows/CMakeLists.txt
+++ b/xbmc/games/controllers/windows/CMakeLists.txt
@@ -11,4 +11,3 @@ set(HEADERS GUIConfigurationWizard.h
             IConfigurationWindow.h)
 
 core_add_library(games_controller_windows)
-add_dependencies(games_controller_windows libcpluff)
diff --git a/xbmc/games/controllers/windows/GUIControllerList.cpp b/xbmc/games/controllers/windows/GUIControllerList.cpp
index 3a088a6..1fabf9b 100644
--- a/xbmc/games/controllers/windows/GUIControllerList.cpp
+++ b/xbmc/games/controllers/windows/GUIControllerList.cpp
@@ -61,17 +61,16 @@ bool CGUIControllerList::Initialize(void)
   if (m_controllerButton)
     m_controllerButton->SetVisible(false);
 
+  CAddonMgr::GetInstance().Events().Subscribe(this, &CGUIControllerList::OnEvent);
   Refresh();
 
-  CAddonMgr::GetInstance().RegisterObserver(this);
-
   return m_controllerList != nullptr &&
          m_controllerButton != nullptr;
 }
 
 void CGUIControllerList::Deinitialize(void)
 {
-  CAddonMgr::GetInstance().UnregisterObserver(this);
+  CAddonMgr::GetInstance().Events().Unsubscribe(this);
 
   CleanupButtons();
 
@@ -143,12 +142,11 @@ void CGUIControllerList::ResetController(void)
   }
 }
 
-void CGUIControllerList::Notify(const Observable& obs, const ObservableMessage msg)
+void CGUIControllerList::OnEvent(const ADDON::AddonEvent& event)
 {
-  using namespace KODI::MESSAGING;
-
-  if (msg == ObservableMessageAddons)
+  if (typeid(event) == typeid(ADDON::AddonEvents::InstalledChanged))
   {
+    using namespace KODI::MESSAGING;
     CGUIMessage msg(GUI_MSG_REFRESH_LIST, m_guiWindow->GetID(), CONTROL_CONTROLLER_LIST);
     CApplicationMessenger::GetInstance().SendGUIMessage(msg);
   }
diff --git a/xbmc/games/controllers/windows/GUIControllerList.h b/xbmc/games/controllers/windows/GUIControllerList.h
index 44197d5..036cea9 100644
--- a/xbmc/games/controllers/windows/GUIControllerList.h
+++ b/xbmc/games/controllers/windows/GUIControllerList.h
@@ -20,9 +20,9 @@
 #pragma once
 
 #include "IConfigurationWindow.h"
+#include "addons/AddonEvents.h"
 #include "addons/Addon.h"
 #include "games/controllers/ControllerTypes.h"
-#include "utils/Observer.h"
 
 #include <set>
 #include <string>
@@ -35,8 +35,7 @@ namespace GAME
 {
   class CGUIControllerWindow;
 
-  class CGUIControllerList : public IControllerList,
-                             public Observer
+  class CGUIControllerList : public IControllerList
   {
   public:
     CGUIControllerList(CGUIWindow* window, IFeatureList* featureList);
@@ -50,9 +49,6 @@ namespace GAME
     virtual void OnSelect(unsigned int controllerIndex) override;
     virtual void ResetController(void) override;
 
-    // implementation of Observer
-    virtual void Notify(const Observable& obs, const ObservableMessage msg) override;
-
   private:
     bool RefreshControllers(void);
 
@@ -63,6 +59,7 @@ namespace GAME
     void UnregisterController(const std::string& controllerId);
 
     void CleanupButtons(void);
+    void OnEvent(const ADDON::AddonEvent& event);
 
     // GUI stuff
     CGUIWindow* const     m_guiWindow;
diff --git a/xbmc/games/controllers/windows/GUIControllerWindow.cpp b/xbmc/games/controllers/windows/GUIControllerWindow.cpp
index 65bb09f..b8f52a6 100644
--- a/xbmc/games/controllers/windows/GUIControllerWindow.cpp
+++ b/xbmc/games/controllers/windows/GUIControllerWindow.cpp
@@ -151,10 +151,9 @@ bool CGUIControllerWindow::OnMessage(CGUIMessage& message)
   return CGUIDialog::OnMessage(message);
 }
 
-void CGUIControllerWindow::Notify(const Observable &obs, const ObservableMessage msg)
+void CGUIControllerWindow::OnEvent(const ADDON::CRepositoryUpdater::RepositoryUpdated& event)
 {
-  if (msg == ObservableMessageAddons)
-    UpdateButtons();
+  UpdateButtons();
 }
 
 void CGUIControllerWindow::OnInitWindow(void)
@@ -205,14 +204,15 @@ void CGUIControllerWindow::OnInitWindow(void)
     Close();
   }
 
-  UpdateButtons();
+  // FIXME: not thread safe
+//  ADDON::CRepositoryUpdater::GetInstance().Events().Subscribe(this, &CGUIControllerWindow::OnEvent);
 
-  ADDON::CAddonMgr::GetInstance().RegisterObserver(this);
+  UpdateButtons();
 }
 
 void CGUIControllerWindow::OnDeinitWindow(int nextWindowID)
 {
-  ADDON::CAddonMgr::GetInstance().UnregisterObserver(this);
+  ADDON::CRepositoryUpdater::GetInstance().Events().Unsubscribe(this);
 
   if (m_controllerList)
   {
diff --git a/xbmc/games/controllers/windows/GUIControllerWindow.h b/xbmc/games/controllers/windows/GUIControllerWindow.h
index ca8c442..835068b 100644
--- a/xbmc/games/controllers/windows/GUIControllerWindow.h
+++ b/xbmc/games/controllers/windows/GUIControllerWindow.h
@@ -19,6 +19,7 @@
  */
 #pragma once
 
+#include "addons/RepositoryUpdater.h"
 #include "guilib/GUIDialog.h"
 #include "utils/Observer.h"
 
@@ -27,8 +28,7 @@ namespace GAME
   class IControllerList;
   class IFeatureList;
 
-  class CGUIControllerWindow : public CGUIDialog,
-                               public Observer
+  class CGUIControllerWindow : public CGUIDialog
   {
   public:
     CGUIControllerWindow(void);
@@ -37,9 +37,6 @@ namespace GAME
     // implementation of CGUIControl via CGUIDialog
     virtual bool OnMessage(CGUIMessage& message) override;
 
-    // implementation of Observer
-    void Notify(const Observable &obs, const ObservableMessage msg) override;
-
   protected:
     // implementation of CGUIWindow via CGUIDialog
     virtual void OnInitWindow(void) override;
@@ -50,7 +47,7 @@ namespace GAME
     void OnControllerSelected(unsigned int controllerIndex);
     void OnFeatureFocused(unsigned int featureIndex);
     void OnFeatureSelected(unsigned int featureIndex);
-
+    void OnEvent(const ADDON::CRepositoryUpdater::RepositoryUpdated& event);
     void UpdateButtons(void);
 
     // Action for the available button
diff --git a/xbmc/guiinfo/GUIInfoLabels.h b/xbmc/guiinfo/GUIInfoLabels.h
index 27d6bc2..b0630ef 100644
--- a/xbmc/guiinfo/GUIInfoLabels.h
+++ b/xbmc/guiinfo/GUIInfoLabels.h
@@ -435,6 +435,7 @@
 
 #define SYSTEM_PROFILEAUTOLOGIN     1004
 #define SYSTEM_HAS_ADSP             1005
+#define SYSTEM_HAS_CMS              1006
 
 #define PVR_CONDITIONS_START        1100
 #define PVR_IS_RECORDING            (PVR_CONDITIONS_START)
@@ -562,6 +563,20 @@
 #define RDS_CHANNEL_COUNTRY         (RDS_DATA_START + 44)
 #define RDS_DATA_END                RDS_CHANNEL_COUNTRY
 
+#define PLAYER_PROCESS              1500
+#define PLAYER_PROCESS_VIDEODECODER (PLAYER_PROCESS)
+#define PLAYER_PROCESS_DEINTMETHOD (PLAYER_PROCESS + 1)
+#define PLAYER_PROCESS_PIXELFORMAT (PLAYER_PROCESS + 2)
+#define PLAYER_PROCESS_VIDEOWIDTH (PLAYER_PROCESS + 3)
+#define PLAYER_PROCESS_VIDEOHEIGHT (PLAYER_PROCESS + 4)
+#define PLAYER_PROCESS_VIDEOFPS (PLAYER_PROCESS + 5)
+#define PLAYER_PROCESS_VIDEODAR (PLAYER_PROCESS + 6)
+#define PLAYER_PROCESS_VIDEOHWDECODER (PLAYER_PROCESS + 7)
+#define PLAYER_PROCESS_AUDIODECODER (PLAYER_PROCESS + 8)
+#define PLAYER_PROCESS_AUDIOCHANNELS (PLAYER_PROCESS + 9)
+#define PLAYER_PROCESS_AUDIOSAMPLERATE (PLAYER_PROCESS + 10)
+#define PLAYER_PROCESS_AUDIOBITSPERSAMPLE (PLAYER_PROCESS + 11)
+
 #define WINDOW_PROPERTY             9993
 #define WINDOW_IS_TOPMOST           9994
 #define WINDOW_IS_VISIBLE           9995
diff --git a/xbmc/guilib/CMakeLists.txt b/xbmc/guilib/CMakeLists.txt
index aa20e7b..9858942 100644
--- a/xbmc/guilib/CMakeLists.txt
+++ b/xbmc/guilib/CMakeLists.txt
@@ -202,11 +202,6 @@ if(CORE_SYSTEM_NAME STREQUAL windows)
 endif()
 
 core_add_library(guilib)
-add_dependencies(guilib libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(guilib ffmpeg)
-endif()
 
 if(CORE_SYSTEM_NAME STREQUAL windows)
   set(SHADERS_VERTEX guishader_vert.hlsl)
@@ -222,16 +217,28 @@ if(CORE_SYSTEM_NAME STREQUAL windows)
                     guishader_video.hlsl
                     guishader_video_control.hlsl)
   foreach(shader ${SHADERS_VERTEX})
-    add_shader_dx(guilib
-                  ${CORE_SOURCE_DIR}/system/shaders/${shader}
-                  vs_4_0_level_9_1
-                  VS)
+    get_filename_component(file ${shader} NAME_WE)
+    add_custom_command(OUTPUT ${file}.h
+                       COMMAND ${FXC} /Fh ${file}.h /E VS /T vs_4_0_level_9_1 /Vn ${file} /Qstrip_reflect
+                                      ${CORE_SOURCE_DIR}/system/shaders/${shader}
+                       DEPENDS ${CORE_SOURCE_DIR}/system/shaders/${shader}
+                       COMMENT "FX compile vertex shader ${shader}"
+                       VERBATIM)
+    list(APPEND SHADERS ${file}.h)
   endforeach()
   foreach(shader ${SHADERS_PIXEL})
-    add_shader_dx(guilib
-                  ${CORE_SOURCE_DIR}/system/shaders/${shader}
-                  ps_4_0_level_9_1
-                  PS)
+    get_filename_component(file ${shader} NAME_WE)
+    add_custom_command(OUTPUT ${file}.h
+                       COMMAND ${FXC} /Fh ${file}.h /E PS /T ps_4_0_level_9_1 /Vn ${file} /Qstrip_reflect
+                                      ${CORE_SOURCE_DIR}/system/shaders/${shader}
+                       DEPENDS ${CORE_SOURCE_DIR}/system/shaders/${shader}
+                       COMMENT "FX compile pixel shader ${shader}"
+                       VERBATIM)
+    list(APPEND SHADERS ${file}.h)
   endforeach()
-  add_dependencies(guilib d3dx11effects)
+
+  add_custom_target(generate_shaders ALL DEPENDS ${SHADERS})
+  set_target_properties(generate_shaders PROPERTIES FOLDER "Build Utilities")
+  target_include_directories(${CORE_LIBRARY} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
+  add_dependencies(${CORE_LIBRARY} generate_shaders)
 endif()
diff --git a/xbmc/guilib/GUIBaseContainer.cpp b/xbmc/guilib/GUIBaseContainer.cpp
index 266c4f4..43aae47 100644
--- a/xbmc/guilib/GUIBaseContainer.cpp
+++ b/xbmc/guilib/GUIBaseContainer.cpp
@@ -349,15 +349,8 @@ bool CGUIBaseContainer::OnAction(const CAction &action)
       }
     }
   case ACTION_CONTEXT_MENU:
-    if (m_listProvider)
-    {
-      int selected = GetSelectedItem();
-      if (selected >= 0 && selected < static_cast<int>(m_items.size()))
-      {
-        m_listProvider->OnContextMenu(m_items[selected]);
-        return true;
-      }
-    }
+    if (OnContextMenu())
+      return true;
     break;
   case ACTION_SHOW_INFO:
     if (m_listProvider)
@@ -699,7 +692,9 @@ bool CGUIBaseContainer::OnMouseOver(const CPoint &point)
 
 EVENT_RESULT CGUIBaseContainer::OnMouseEvent(const CPoint &point, const CMouseEvent &event)
 {
-  if (event.m_id >= ACTION_MOUSE_LEFT_CLICK && event.m_id <= ACTION_MOUSE_DOUBLE_CLICK)
+  if (event.m_id == ACTION_MOUSE_LEFT_CLICK ||
+      event.m_id == ACTION_MOUSE_DOUBLE_CLICK ||
+      event.m_id == ACTION_MOUSE_RIGHT_CLICK)
   {
     if (SelectItemFromPoint(point - CPoint(m_posX, m_posY)))
     {
@@ -779,11 +774,30 @@ bool CGUIBaseContainer::OnClick(int actionID)
     if (focusedLayout)
       subItem = focusedLayout->GetFocusedItem();
   }
+  else if (actionID == ACTION_MOUSE_RIGHT_CLICK)
+  {
+    if (OnContextMenu())
+      return true;
+  }
   // Don't know what to do, so send to our parent window.
   CGUIMessage msg(GUI_MSG_CLICKED, GetID(), GetParentID(), actionID, subItem);
   return SendWindowMessage(msg);
 }
 
+bool CGUIBaseContainer::OnContextMenu()
+{
+  if (m_listProvider)
+  {
+    int selected = GetSelectedItem();
+    if (selected >= 0 && selected < static_cast<int>(m_items.size()))
+    {
+      m_listProvider->OnContextMenu(m_items[selected]);
+      return true;
+    }
+  }
+  return false;
+}
+
 std::string CGUIBaseContainer::GetDescription() const
 {
   std::string strLabel;
diff --git a/xbmc/guilib/GUIBaseContainer.h b/xbmc/guilib/GUIBaseContainer.h
index 52960bf..96d0565 100644
--- a/xbmc/guilib/GUIBaseContainer.h
+++ b/xbmc/guilib/GUIBaseContainer.h
@@ -215,6 +215,8 @@ protected:
   unsigned int m_lastRenderTime;
 
 private:
+  bool OnContextMenu();
+
   int m_cursor;
   int m_offset;
   int m_cacheItems;
diff --git a/xbmc/guilib/GUIFontCache.cpp b/xbmc/guilib/GUIFontCache.cpp
index 72717be..20e2f94 100644
--- a/xbmc/guilib/GUIFontCache.cpp
+++ b/xbmc/guilib/GUIFontCache.cpp
@@ -32,6 +32,10 @@ class CGUIFontCacheImpl
     using HashIter = typename HashMap::iterator;
     using AgeMap = std::multimap<size_t, HashIter>;
 
+    ~EntryList()
+    {
+      Flush();
+    }
     HashIter Insert(size_t hash, CGUIFontCacheEntry<Position, Value> *v)
     {
       auto r (hashMap.insert(typename HashMap::value_type(hash, v)));
diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
index aef14bf..b5a937c 100644
--- a/xbmc/guilib/GUIFontTTF.cpp
+++ b/xbmc/guilib/GUIFontTTF.cpp
@@ -45,7 +45,11 @@
 #define USE_RELEASE_LIBS
 
 #ifdef TARGET_WINDOWS
-#pragma comment(lib, "freetype246MT.lib")
+#ifdef NDEBUG
+#pragma comment(lib, "freetype.lib")
+#else
+#pragma comment(lib, "freetyped.lib")
+#endif
 #endif
 
 #define CHARS_PER_TEXTURE_LINE 20 // number of characters to cache per texture line
diff --git a/xbmc/guilib/GUIWindow.cpp b/xbmc/guilib/GUIWindow.cpp
index 2f15256..70f7063 100644
--- a/xbmc/guilib/GUIWindow.cpp
+++ b/xbmc/guilib/GUIWindow.cpp
@@ -55,7 +55,6 @@ CGUIWindow::CGUIWindow(int id, const std::string &xmlFile)
   SetID(id);
   SetProperty("xmlfile", xmlFile);
   m_lastControlID = 0;
-  m_isDialog = false;
   m_needsScaling = true;
   m_windowLoaded = false;
   m_loadType = LOAD_EVERY_TIME;
@@ -187,14 +186,7 @@ bool CGUIWindow::Load(TiXmlElement* pRootElement)
   while (pChild)
   {
     std::string strValue = pChild->Value();
-    if (strValue == "type" && pChild->FirstChild())
-    {
-      // if we have are a window type (ie not a dialog), and we have <type>dialog</type>
-      // then make this window act like a dialog
-      if (!IsDialog() && strcmpi(pChild->FirstChild()->Value(), "dialog") == 0)
-        m_isDialog = true;
-    }
-    else if (strValue == "previouswindow" && pChild->FirstChild())
+    if (strValue == "previouswindow" && pChild->FirstChild())
     {
       m_previousWindow = CButtonTranslator::TranslateWindow(pChild->FirstChild()->Value());
     }
diff --git a/xbmc/guilib/GUIWindow.h b/xbmc/guilib/GUIWindow.h
index 19d800a..0b64939 100644
--- a/xbmc/guilib/GUIWindow.h
+++ b/xbmc/guilib/GUIWindow.h
@@ -244,7 +244,6 @@ protected:
   bool m_needsScaling;
   bool m_windowLoaded;  // true if the window's xml file has been loaded
   LOAD_TYPE m_loadType;
-  bool m_isDialog;      // true if we have a dialog, false otherwise.
   bool m_dynamicResourceAlloc;
   bool m_closing;
   bool m_active;        // true if window is active or dialog is running
diff --git a/xbmc/guilib/GUIWindowManager.cpp b/xbmc/guilib/GUIWindowManager.cpp
index 0a952e3..82b8b32 100644
--- a/xbmc/guilib/GUIWindowManager.cpp
+++ b/xbmc/guilib/GUIWindowManager.cpp
@@ -79,6 +79,9 @@
 #include "dialogs/GUIDialogTextViewer.h"
 #include "network/GUIDialogNetworkSetup.h"
 #include "dialogs/GUIDialogMediaSource.h"
+#ifdef HAS_GL
+#include "video/dialogs/GUIDialogCMSSettings.h"
+#endif
 #include "video/dialogs/GUIDialogVideoSettings.h"
 #include "video/dialogs/GUIDialogAudioSubtitleSettings.h"
 #include "video/dialogs/GUIDialogVideoBookmarks.h"
@@ -103,6 +106,7 @@
 #include "dialogs/GUIDialogButtonMenu.h"
 #include "dialogs/GUIDialogContextMenu.h"
 #include "dialogs/GUIDialogPlayerControls.h"
+#include "dialogs/GUIDialogPlayerProcessInfo.h"
 #include "music/dialogs/GUIDialogSongInfo.h"
 #include "dialogs/GUIDialogSmartPlaylistEditor.h"
 #include "dialogs/GUIDialogSmartPlaylistRule.h"
@@ -210,9 +214,13 @@ void CGUIWindowManager::CreateWindows()
   Add(new CGUIDialogGamepad);
   Add(new CGUIDialogButtonMenu);
   Add(new CGUIDialogPlayerControls);
+  Add(new CGUIDialogPlayerProcessInfo);
   Add(new CGUIDialogSlider);
   Add(new CGUIDialogMusicOSD);
   Add(new CGUIDialogVisualisationPresetList);
+#ifdef HAS_GL
+  Add(new CGUIDialogCMSSettings);
+#endif
   Add(new CGUIDialogVideoSettings);
   Add(new CGUIDialogAudioSubtitleSettings);
   Add(new CGUIDialogVideoBookmarks);
@@ -315,6 +323,7 @@ bool CGUIWindowManager::DestroyWindows()
     Delete(WINDOW_DIALOG_BUTTON_MENU);
     Delete(WINDOW_DIALOG_CONTEXT_MENU);
     Delete(WINDOW_DIALOG_PLAYER_CONTROLS);
+    Delete(WINDOW_DIALOG_PLAYER_PROCESS_INFO);
     Delete(WINDOW_DIALOG_MUSIC_OSD);
     Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
     Delete(WINDOW_DIALOG_SELECT);
@@ -326,6 +335,7 @@ bool CGUIWindowManager::DestroyWindows()
     Delete(WINDOW_DIALOG_LOCK_SETTINGS);
     Delete(WINDOW_DIALOG_NETWORK_SETUP);
     Delete(WINDOW_DIALOG_MEDIA_SOURCE);
+    Delete(WINDOW_DIALOG_CMS_OSD_SETTINGS);
     Delete(WINDOW_DIALOG_VIDEO_OSD_SETTINGS);
     Delete(WINDOW_DIALOG_AUDIO_OSD_SETTINGS);
     Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS);
@@ -399,7 +409,7 @@ bool CGUIWindowManager::DestroyWindows()
     Remove(WINDOW_SETTINGS_SERVICE);
     Remove(WINDOW_SETTINGS_MYPVR);
     Remove(WINDOW_SETTINGS_PLAYER);
-    Remove(WINDOW_SETTINGS_LIBRARY);
+    Remove(WINDOW_SETTINGS_MEDIA);
     Remove(WINDOW_SETTINGS_INTERFACE);
     Remove(WINDOW_DIALOG_KAI_TOAST);
 
diff --git a/xbmc/guilib/TextureBundle.cpp b/xbmc/guilib/TextureBundle.cpp
index 596fdf3..75c46e8 100644
--- a/xbmc/guilib/TextureBundle.cpp
+++ b/xbmc/guilib/TextureBundle.cpp
@@ -21,7 +21,14 @@
 #include "TextureBundle.h"
 
 CTextureBundle::CTextureBundle()
-  : m_useXBT{false}
+  : m_tbXBT{false}
+	, m_useXBT{false}
+{
+}
+
+CTextureBundle::CTextureBundle(bool useXBT)
+  : m_tbXBT{useXBT}
+	, m_useXBT{useXBT}
 {
 }
 
diff --git a/xbmc/guilib/TextureBundle.h b/xbmc/guilib/TextureBundle.h
index 67d62b4..97161fe 100644
--- a/xbmc/guilib/TextureBundle.h
+++ b/xbmc/guilib/TextureBundle.h
@@ -28,6 +28,7 @@ class CTextureBundle
 {
 public:
   CTextureBundle();
+  explicit CTextureBundle(bool useXBT);
   ~CTextureBundle() = default;
 
   void SetThemeBundle(bool themeBundle);
diff --git a/xbmc/guilib/TextureBundleXBT.cpp b/xbmc/guilib/TextureBundleXBT.cpp
index 85ebd5b..c4f9a45 100644
--- a/xbmc/guilib/TextureBundleXBT.cpp
+++ b/xbmc/guilib/TextureBundleXBT.cpp
@@ -41,12 +41,18 @@
 #endif
 #endif
 
-CTextureBundleXBT::CTextureBundleXBT(void)
+CTextureBundleXBT::CTextureBundleXBT()
   : m_TimeStamp{0}
   , m_themeBundle{false}
 {
 }
 
+CTextureBundleXBT::CTextureBundleXBT(bool themeBundle)
+  : m_TimeStamp{0}
+  , m_themeBundle{themeBundle}
+{
+}
+
 CTextureBundleXBT::~CTextureBundleXBT(void)
 {
   if (m_XBTFReader != nullptr && m_XBTFReader->IsOpen())
@@ -59,6 +65,15 @@ CTextureBundleXBT::~CTextureBundleXBT(void)
 bool CTextureBundleXBT::OpenBundle()
 {
   // Find the correct texture file (skin or theme)
+
+  auto mediaDir = g_graphicsContext.GetMediaDir();
+  if (mediaDir.empty())
+  {
+    mediaDir = CSpecialProtocol::TranslatePath(
+      URIUtils::AddFileToFolder("special://home/addons",
+        CSettings::GetInstance().GetString(CSettings::SETTING_LOOKANDFEEL_SKIN)));
+  }
+
   if (m_themeBundle)
   {
     // if we are the theme bundle, we only load if the user has chosen
@@ -67,7 +82,7 @@ bool CTextureBundleXBT::OpenBundle()
     if (!theme.empty() && !StringUtils::EqualsNoCase(theme, "SKINDEFAULT"))
     {
       std::string themeXBT(URIUtils::ReplaceExtension(theme, ".xbt"));
-      m_path = URIUtils::AddFileToFolder(g_graphicsContext.GetMediaDir(), "media");
+      m_path = URIUtils::AddFileToFolder(mediaDir, "media");
       m_path = URIUtils::AddFileToFolder(m_path, themeXBT);
     }
     else
@@ -77,7 +92,7 @@ bool CTextureBundleXBT::OpenBundle()
   }
   else
   {
-    m_path = URIUtils::AddFileToFolder(g_graphicsContext.GetMediaDir(), "media/Textures.xbt");
+    m_path = URIUtils::AddFileToFolder(mediaDir, "media/Textures.xbt");
   }
 
   m_path = CSpecialProtocol::TranslatePathConvertCase(m_path);
diff --git a/xbmc/guilib/TextureBundleXBT.h b/xbmc/guilib/TextureBundleXBT.h
index 408ec5e..e1de9eb 100644
--- a/xbmc/guilib/TextureBundleXBT.h
+++ b/xbmc/guilib/TextureBundleXBT.h
@@ -33,6 +33,7 @@ class CTextureBundleXBT
 {
 public:
   CTextureBundleXBT();
+  explicit CTextureBundleXBT(bool themeBundle);
   ~CTextureBundleXBT();
 
   void SetThemeBundle(bool themeBundle);
diff --git a/xbmc/guilib/TextureManager.cpp b/xbmc/guilib/TextureManager.cpp
index c1c5c8f..8a51cb0 100644
--- a/xbmc/guilib/TextureManager.cpp
+++ b/xbmc/guilib/TextureManager.cpp
@@ -539,8 +539,9 @@ void CGUITextureManager::Cleanup()
     delete pMap;
     i = m_vecTextures.erase(i);
   }
-  for (int i = 0; i < 2; i++)
-    m_TexBundle[i] = CTextureBundle();
+
+  m_TexBundle[0] = CTextureBundle(true);
+  m_TexBundle[1] = CTextureBundle();
   FreeUnusedTextures();
 }
 
diff --git a/xbmc/guilib/WindowIDs.h b/xbmc/guilib/WindowIDs.h
index fcfcc5d..83c6246 100644
--- a/xbmc/guilib/WindowIDs.h
+++ b/xbmc/guilib/WindowIDs.h
@@ -43,7 +43,7 @@
 #define WINDOW_LOGIN_SCREEN               10029
 
 #define WINDOW_SETTINGS_PLAYER            10030
-#define WINDOW_SETTINGS_LIBRARY           10031
+#define WINDOW_SETTINGS_MEDIA             10031
 #define WINDOW_SETTINGS_INTERFACE         10032
 
 #define WINDOW_SETTINGS_PROFILES          10034
@@ -68,6 +68,7 @@
 #define WINDOW_DIALOG_BUTTON_MENU         10111
 #define WINDOW_DIALOG_PLAYER_CONTROLS     10114
 #define WINDOW_DIALOG_SEEK_BAR            10115
+#define WINDOW_DIALOG_PLAYER_PROCESS_INFO 10116
 #define WINDOW_DIALOG_MUSIC_OSD           10120
 #define WINDOW_DIALOG_VIS_SETTINGS        10121
 #define WINDOW_DIALOG_VIS_PRESET_LIST     10122
@@ -100,6 +101,7 @@
 #define WINDOW_DIALOG_AUDIO_DSP_MANAGER   10154
 #define WINDOW_DIALOG_AUDIO_DSP_OSD_SETTINGS 10155
 #define WINDOW_DIALOG_KEYBOARD_TOUCH      10156
+#define WINDOW_DIALOG_CMS_OSD_SETTINGS    10157
 
 #define WINDOW_MUSIC_PLAYLIST             10500
 #define WINDOW_MUSIC_NAV                  10502
diff --git a/xbmc/guilib/XBTFReader.cpp b/xbmc/guilib/XBTFReader.cpp
index 0c44766..56ab302 100644
--- a/xbmc/guilib/XBTFReader.cpp
+++ b/xbmc/guilib/XBTFReader.cpp
@@ -30,7 +30,7 @@
 #ifdef TARGET_WINDOWS
 #include "filesystem/SpecialProtocol.h"
 #include "utils/CharsetConverter.h"
-#include "win32/PlatformDefs.h"
+#include "platform/win32/PlatformDefs.h"
 #endif
 
 static bool ReadString(FILE* file, char* str, size_t max_length)
diff --git a/xbmc/input/ButtonTranslator.cpp b/xbmc/input/ButtonTranslator.cpp
index 7398fbf..97bb27c 100644
--- a/xbmc/input/ButtonTranslator.cpp
+++ b/xbmc/input/ButtonTranslator.cpp
@@ -87,7 +87,8 @@ static const ActionMapping actions[] =
     { "showsubtitles"            , ACTION_SHOW_SUBTITLES },
     { "nextsubtitle"             , ACTION_NEXT_SUBTITLE },
     { "cyclesubtitle"            , ACTION_CYCLE_SUBTITLE },
-    { "codecinfo"                , ACTION_SHOW_CODEC },
+    { "playerdebug"              , ACTION_PLAYER_DEBUG },
+    { "playerprocessinfo"        , ACTION_PLAYER_PROCESS_INFO },
     { "nextpicture"              , ACTION_NEXT_PICTURE },
     { "previouspicture"          , ACTION_PREV_PICTURE },
     { "zoomout"                  , ACTION_ZOOM_OUT },
@@ -330,7 +331,7 @@ static const ActionMapping windows[] =
     { "servicesettings"          , WINDOW_SETTINGS_SERVICE },
     { "pvrsettings"              , WINDOW_SETTINGS_MYPVR },
     { "playersettings"           , WINDOW_SETTINGS_PLAYER },
-    { "librarysettings"          , WINDOW_SETTINGS_LIBRARY },
+    { "mediasettings"            , WINDOW_SETTINGS_MEDIA },
     { "interfacesettings"        , WINDOW_SETTINGS_INTERFACE },	
     { "videoplaylist"            , WINDOW_VIDEO_PLAYLIST },
     { "loginscreen"              , WINDOW_LOGIN_SCREEN },
@@ -349,10 +350,12 @@ static const ActionMapping windows[] =
     { "gamepadinput"             , WINDOW_DIALOG_GAMEPAD },
     { "shutdownmenu"             , WINDOW_DIALOG_BUTTON_MENU },
     { "playercontrols"           , WINDOW_DIALOG_PLAYER_CONTROLS },
+    { "playerprocessinfo"        , WINDOW_DIALOG_PLAYER_PROCESS_INFO },
     { "seekbar"                  , WINDOW_DIALOG_SEEK_BAR },
     { "musicosd"                 , WINDOW_DIALOG_MUSIC_OSD },
     { "addonsettings"            , WINDOW_DIALOG_ADDON_SETTINGS },
     { "visualisationpresetlist"  , WINDOW_DIALOG_VIS_PRESET_LIST },
+    { "osdcmssettings"           , WINDOW_DIALOG_CMS_OSD_SETTINGS },
     { "osdvideosettings"         , WINDOW_DIALOG_VIDEO_OSD_SETTINGS },
     { "osdaudiosettings"         , WINDOW_DIALOG_AUDIO_OSD_SETTINGS },
     { "audiodspmanager"          , WINDOW_DIALOG_AUDIO_DSP_MANAGER },
diff --git a/xbmc/input/CMakeLists.txt b/xbmc/input/CMakeLists.txt
index ae34a59..a961423 100644
--- a/xbmc/input/CMakeLists.txt
+++ b/xbmc/input/CMakeLists.txt
@@ -33,8 +33,3 @@ set(HEADERS ButtonTranslator.h
             XBMC_vkeys.h)
 
 core_add_library(input)
-add_dependencies(input libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(input ffmpeg)
-endif()
diff --git a/xbmc/input/InputCodingTable.h b/xbmc/input/InputCodingTable.h
index 0bdd96a..e380887 100644
--- a/xbmc/input/InputCodingTable.h
+++ b/xbmc/input/InputCodingTable.h
@@ -21,6 +21,7 @@
 */
 
 #include <string>
+#include <memory>
 #include <vector>
 
 class IInputCodingTable
@@ -58,3 +59,5 @@ public:
 protected:
   std::string m_codechars;
 };
+
+typedef std::shared_ptr<IInputCodingTable> IInputCodingTablePtr;
diff --git a/xbmc/input/Key.h b/xbmc/input/Key.h
index fc989c5..bdc478c 100644
--- a/xbmc/input/Key.h
+++ b/xbmc/input/Key.h
@@ -172,7 +172,7 @@
 #define ACTION_SHOW_OSD               24 //!< show/hide OSD. Can b used in videoFullScreen.xml window id=2005
 #define ACTION_SHOW_SUBTITLES         25 //!< turn subtitles on/off. Can b used in videoFullScreen.xml window id=2005
 #define ACTION_NEXT_SUBTITLE          26 //!< switch to next subtitle of movie. Can b used in videoFullScreen.xml window id=2005
-#define ACTION_SHOW_CODEC             27 //!< show debug info for VideoPlayer
+#define ACTION_PLAYER_DEBUG           27 //!< show debug info for VideoPlayer
 #define ACTION_NEXT_PICTURE           28 //!< show next picture of slideshow. Can b used in slideshow.xml window id=2007
 #define ACTION_PREV_PICTURE           29 //!< show previous picture of slideshow. Can b used in slideshow.xml window id=2007
 #define ACTION_ZOOM_OUT               30 //!< zoom in picture during slideshow. Can b used in slideshow.xml window id=2007
@@ -219,6 +219,7 @@
 #define REMOTE_9                      67
 
 #define ACTION_PLAY                   68  //!< Unused at the moment
+#define ACTION_PLAYER_PROCESS_INFO    69 //!< show player process info (video decoder, pixel format, pvr signal strength and the like
 #define ACTION_SMALL_STEP_BACK        76  //!< jumps a few seconds back during playback of movie. Can b used in videoFullScreen.xml window id=2005
 
 #define ACTION_PLAYER_FORWARD         77  //!< FF in current file played. global action, can be used anywhere
diff --git a/xbmc/input/KeyboardLayout.cpp b/xbmc/input/KeyboardLayout.cpp
index e4b5b1c..30717de 100644
--- a/xbmc/input/KeyboardLayout.cpp
+++ b/xbmc/input/KeyboardLayout.cpp
@@ -69,7 +69,7 @@ bool CKeyboardLayout::Load(const TiXmlElement* element)
 
   const TiXmlElement *keyboard = element->FirstChildElement("keyboard");
   if (element->Attribute("codingtable"))
-    m_codingtable = CInputCodingTableFactory::CreateCodingTable(element->Attribute("codingtable"), element);
+    m_codingtable = IInputCodingTablePtr(CInputCodingTableFactory::CreateCodingTable(element->Attribute("codingtable"), element));
   else
     m_codingtable = NULL;
   while (keyboard != NULL)
diff --git a/xbmc/input/KeyboardLayout.h b/xbmc/input/KeyboardLayout.h
index def9fe1..fd3cd83 100644
--- a/xbmc/input/KeyboardLayout.h
+++ b/xbmc/input/KeyboardLayout.h
@@ -23,15 +23,16 @@
 #include <string>
 #include <vector>
 
+#include "InputCodingTable.h"
+
 class TiXmlElement;
-class IInputCodingTable;
 
 class CKeyboardLayout
 {
 public:
   CKeyboardLayout();
   virtual ~CKeyboardLayout();
-  IInputCodingTable* GetCodingTable() { return m_codingtable; }
+  IInputCodingTablePtr GetCodingTable() { return m_codingtable; }
 
   bool Load(const TiXmlElement* element);
 
@@ -58,5 +59,5 @@ private:
   std::string m_language;
   std::string m_layout;
   Keyboards m_keyboards;
-  IInputCodingTable* m_codingtable;
+  IInputCodingTablePtr m_codingtable;
 };
diff --git a/xbmc/input/joysticks/CMakeLists.txt b/xbmc/input/joysticks/CMakeLists.txt
index 2b3c4cc..db2db69 100644
--- a/xbmc/input/joysticks/CMakeLists.txt
+++ b/xbmc/input/joysticks/CMakeLists.txt
@@ -18,4 +18,3 @@ set(HEADERS DefaultJoystick.h
             KeymapHandler.h)
 
 core_add_library(input_joystick)
-add_dependencies(input_joystick libcpluff)
diff --git a/xbmc/interfaces/AnnouncementManager.cpp b/xbmc/interfaces/AnnouncementManager.cpp
index 7e693aa..9508cac 100644
--- a/xbmc/interfaces/AnnouncementManager.cpp
+++ b/xbmc/interfaces/AnnouncementManager.cpp
@@ -100,13 +100,13 @@ void CAnnouncementManager::Announce(AnnouncementFlag flag, const char *sender, c
   Announce(flag, sender, message, CFileItemPtr(), data);
 }
 
-void CAnnouncementManager::Announce(AnnouncementFlag flag, const char *sender, const char *message, CFileItemPtr item)
+void CAnnouncementManager::Announce(AnnouncementFlag flag, const char *sender, const char *message, const std::shared_ptr<const CFileItem>& item)
 {
   CVariant data;
   Announce(flag, sender, message, item, data);
 }
 
-void CAnnouncementManager::Announce(AnnouncementFlag flag, const char *sender, const char *message, CFileItemPtr item, const CVariant &data)
+void CAnnouncementManager::Announce(AnnouncementFlag flag, const char *sender, const char *message, const std::shared_ptr<const CFileItem>& item, const CVariant &data)
 {
   CAnnounceData announcement;
   announcement.flag = flag;
diff --git a/xbmc/interfaces/AnnouncementManager.h b/xbmc/interfaces/AnnouncementManager.h
index 9785124..0ab56ac 100644
--- a/xbmc/interfaces/AnnouncementManager.h
+++ b/xbmc/interfaces/AnnouncementManager.h
@@ -47,8 +47,10 @@ namespace ANNOUNCEMENT
 
     void Announce(AnnouncementFlag flag, const char *sender, const char *message);
     void Announce(AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data);
-    void Announce(AnnouncementFlag flag, const char *sender, const char *message, CFileItemPtr item);
-    void Announce(AnnouncementFlag flag, const char *sender, const char *message, CFileItemPtr item, const CVariant &data);
+    void Announce(AnnouncementFlag flag, const char *sender, const char *message,
+        const std::shared_ptr<const CFileItem>& item);
+    void Announce(AnnouncementFlag flag, const char *sender, const char *message,
+        const std::shared_ptr<const CFileItem>& item, const CVariant &data);
 
   protected:
     void Process();
diff --git a/xbmc/interfaces/CMakeLists.txt b/xbmc/interfaces/CMakeLists.txt
index d840ec5..0b98732 100644
--- a/xbmc/interfaces/CMakeLists.txt
+++ b/xbmc/interfaces/CMakeLists.txt
@@ -5,4 +5,3 @@ set(HEADERS AnnouncementManager.h
             IAnnouncer.h)
 
 core_add_library(interfaces)
-add_dependencies(interfaces libcpluff)
diff --git a/xbmc/interfaces/builtins/AddonBuiltins.cpp b/xbmc/interfaces/builtins/AddonBuiltins.cpp
index 446fc97..18b112d 100644
--- a/xbmc/interfaces/builtins/AddonBuiltins.cpp
+++ b/xbmc/interfaces/builtins/AddonBuiltins.cpp
@@ -302,7 +302,7 @@ static int UpdateRepos(const std::vector<std::string>& params)
  */
 static int UpdateLocals(const std::vector<std::string>& params)
 {
-  CAddonMgr::GetInstance().FindAddonsAndNotify();
+  CAddonMgr::GetInstance().FindAddons();
 
   return 0;
 }
diff --git a/xbmc/interfaces/builtins/CMakeLists.txt b/xbmc/interfaces/builtins/CMakeLists.txt
index 1a2913e..27785af 100644
--- a/xbmc/interfaces/builtins/CMakeLists.txt
+++ b/xbmc/interfaces/builtins/CMakeLists.txt
@@ -39,8 +39,3 @@ if(CORE_SYSTEM_NAME STREQUAL android)
 endif()
 
 core_add_library(interfaces_builtins)
-add_dependencies(interfaces_builtins libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(interfaces_builtins ffmpeg)
-endif()
diff --git a/xbmc/interfaces/builtins/PlayerBuiltins.cpp b/xbmc/interfaces/builtins/PlayerBuiltins.cpp
index a97f5ce..01c8a5b 100644
--- a/xbmc/interfaces/builtins/PlayerBuiltins.cpp
+++ b/xbmc/interfaces/builtins/PlayerBuiltins.cpp
@@ -125,7 +125,7 @@ static int PlayerControl(const std::vector<std::string>& params)
     if (g_application.m_pPlayer->IsPlaying())
     {
       if (g_application.m_pPlayer->GetPlaySpeed() != 1)
-        g_application.m_pPlayer->SetPlaySpeed(1, g_application.IsMutedInternal());
+        g_application.m_pPlayer->SetPlaySpeed(1);
       else
         g_application.m_pPlayer->Pause();
     }
@@ -154,7 +154,7 @@ static int PlayerControl(const std::vector<std::string>& params)
       if (iPlaySpeed > 32 || iPlaySpeed < -32)
         iPlaySpeed = 1;
 
-      g_application.m_pPlayer->SetPlaySpeed(iPlaySpeed, g_application.IsMutedInternal());
+      g_application.m_pPlayer->SetPlaySpeed(iPlaySpeed);
     }
   }
   else if (paramlow == "next")
diff --git a/xbmc/interfaces/json-rpc/AddonsOperations.cpp b/xbmc/interfaces/json-rpc/AddonsOperations.cpp
index d9ac821..272620b 100644
--- a/xbmc/interfaces/json-rpc/AddonsOperations.cpp
+++ b/xbmc/interfaces/json-rpc/AddonsOperations.cpp
@@ -40,6 +40,7 @@ JSONRPC_STATUS CAddonsOperations::GetAddons(const std::string &method, ITranspor
   TYPE addonType = TranslateType(parameterObject["type"].asString());
   CPluginSource::Content content = CPluginSource::Translate(parameterObject["content"].asString());
   CVariant enabled = parameterObject["enabled"];
+  CVariant installed = parameterObject["installed"];
 
   // ignore the "content" parameter if the type is specified but not a plugin or script
   if (addonType != ADDON_UNKNOWN && addonType != ADDON_PLUGIN && addonType != ADDON_SCRIPT)
@@ -79,19 +80,29 @@ JSONRPC_STATUS CAddonsOperations::GetAddons(const std::string &method, ITranspor
     if (*typeIt == ADDON_UNKNOWN)
     {
       if (!enabled.isBoolean()) //All
-        CAddonMgr::GetInstance().GetInstalledAddons(typeAddons);
-      else if (enabled.asBoolean()) //Enabled
+      {
+        if (!installed.isBoolean() || installed.asBoolean())
+          CAddonMgr::GetInstance().GetInstalledAddons(typeAddons);
+        if (!installed.isBoolean() || (installed.isBoolean() && !installed.asBoolean()))
+          CAddonMgr::GetInstance().GetInstallableAddons(typeAddons);
+      }
+      else if (enabled.asBoolean() && (!installed.isBoolean() || installed.asBoolean())) //Enabled
         CAddonMgr::GetInstance().GetAddons(typeAddons);
-      else
+      else if (!installed.isBoolean() || installed.asBoolean())
         CAddonMgr::GetInstance().GetDisabledAddons(typeAddons);
     }
     else
     {
       if (!enabled.isBoolean()) //All
-        CAddonMgr::GetInstance().GetInstalledAddons(typeAddons, *typeIt);
-      else if (enabled.asBoolean()) //Enabled
+      {
+        if (!installed.isBoolean() || installed.asBoolean())
+          CAddonMgr::GetInstance().GetInstalledAddons(typeAddons, *typeIt);
+        if (!installed.isBoolean() || (installed.isBoolean() && !installed.asBoolean()))
+          CAddonMgr::GetInstance().GetInstallableAddons(typeAddons, *typeIt);
+      }
+      else if (enabled.asBoolean() && (!installed.isBoolean() || installed.asBoolean())) //Enabled
         CAddonMgr::GetInstance().GetAddons(typeAddons, *typeIt);
-      else
+      else if (!installed.isBoolean() || installed.asBoolean())
         CAddonMgr::GetInstance().GetDisabledAddons(typeAddons, *typeIt);
     }
 
@@ -261,12 +272,16 @@ void CAddonsOperations::FillDetails(AddonPtr addon, const CVariant& fields, CVar
   {
     std::string field = fields[index].asString();
     
-    // we need to manually retrieve the enabled state of every addon
+    // we need to manually retrieve the enabled / installed state of every addon
     // from the addon database because it can't be read from addon.xml
     if (field == "enabled")
     {
       object[field] = !CAddonMgr::GetInstance().IsAddonDisabled(addon->ID());
     }
+    else if (field == "installed")
+    {
+      object[field] = CAddonMgr::GetInstance().IsAddonInstalled(addon->ID());
+    }
     else if (field == "fanart" || field == "thumbnail")
     {
       std::string url = addonInfo[field].asString();
diff --git a/xbmc/interfaces/json-rpc/CMakeLists.txt b/xbmc/interfaces/json-rpc/CMakeLists.txt
index 52e40dc..6a0c3c1 100644
--- a/xbmc/interfaces/json-rpc/CMakeLists.txt
+++ b/xbmc/interfaces/json-rpc/CMakeLists.txt
@@ -44,8 +44,4 @@ set(HEADERS AddonsOperations.h
             XBMCOperations.h)
 
 core_add_library(jsonrpc_interface)
-add_dependencies(jsonrpc_interface libcpluff generate_json_header)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(jsonrpc_interface ffmpeg)
-endif()
+add_dependencies(${CORE_LIBRARY} generate_json_header)
diff --git a/xbmc/interfaces/json-rpc/InputOperations.cpp b/xbmc/interfaces/json-rpc/InputOperations.cpp
index 1166471..6788b8f 100644
--- a/xbmc/interfaces/json-rpc/InputOperations.cpp
+++ b/xbmc/interfaces/json-rpc/InputOperations.cpp
@@ -142,7 +142,12 @@ JSONRPC_STATUS CInputOperations::Home(const std::string &method, ITransportLayer
 
 JSONRPC_STATUS CInputOperations::ShowCodec(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
 {
-  return SendAction(ACTION_SHOW_CODEC);
+  return MethodNotFound;
+}
+
+JSONRPC_STATUS CInputOperations::ShowPlayerProcessInfo(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
+{
+  return SendAction(ACTION_PLAYER_PROCESS_INFO);
 }
 
 JSONRPC_STATUS CInputOperations::ShowOSD(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
diff --git a/xbmc/interfaces/json-rpc/InputOperations.h b/xbmc/interfaces/json-rpc/InputOperations.h
index ab596eb..f873b29 100644
--- a/xbmc/interfaces/json-rpc/InputOperations.h
+++ b/xbmc/interfaces/json-rpc/InputOperations.h
@@ -43,6 +43,7 @@ namespace JSONRPC
     static JSONRPC_STATUS Home(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
 
     static JSONRPC_STATUS ShowCodec(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
+    static JSONRPC_STATUS ShowPlayerProcessInfo(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
     static JSONRPC_STATUS ShowOSD(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
 
     static JSONRPC_STATUS SendAction(int actionID, bool wakeScreensaver = true, bool waitResult = false);
diff --git a/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp b/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp
index 1690be5..cda13ce 100644
--- a/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp
+++ b/xbmc/interfaces/json-rpc/JSONServiceDescription.cpp
@@ -217,6 +217,7 @@ JsonRpcMethodMap CJSONServiceDescription::m_methodMaps[] = {
   { "Input.Home",                                   CInputOperations::Home },
   { "Input.ShowCodec",                              CInputOperations::ShowCodec },
   { "Input.ShowOSD",                                CInputOperations::ShowOSD },
+  { "Input.ShowPlayerProcessInfo",                  CInputOperations::ShowPlayerProcessInfo },
 
 // Application operations
   { "Application.GetProperties",                    CApplicationOperations::GetProperties },
diff --git a/xbmc/interfaces/json-rpc/PVROperations.cpp b/xbmc/interfaces/json-rpc/PVROperations.cpp
index a510637..941f71d 100644
--- a/xbmc/interfaces/json-rpc/PVROperations.cpp
+++ b/xbmc/interfaces/json-rpc/PVROperations.cpp
@@ -369,12 +369,10 @@ JSONRPC_STATUS CPVROperations::AddTimer(const std::string &method, ITransportLay
   if (!epgTag)
     return InvalidParams;
 
-  bool repeating = parameterObject["repeating"].asBoolean(false);
-
   if (epgTag->HasTimer())
     return InvalidParams;
 
-  CPVRTimerInfoTagPtr newTimer = CPVRTimerInfoTag::CreateFromEpg(epgTag, repeating);
+  CPVRTimerInfoTagPtr newTimer = CPVRTimerInfoTag::CreateFromEpg(epgTag, parameterObject["timerrule"].asBoolean(false));
   if (newTimer)
   {
     if (g_PVRTimers->AddTimer(newTimer))
@@ -395,9 +393,7 @@ JSONRPC_STATUS CPVROperations::DeleteTimer(const std::string &method, ITransport
   if (!timer)
     return InvalidParams;
 
-  bool repeating = parameterObject["repeating"].asBoolean(false);
-
-  if (timers->DeleteTimer(timer, false, repeating))
+  if (timers->DeleteTimer(timer, timer->IsRecording(), false))
     return ACK;
 
   return FailedToExecute;
@@ -420,16 +416,20 @@ JSONRPC_STATUS CPVROperations::ToggleTimer(const std::string &method, ITransport
   if (!epgTag)
     return InvalidParams;
 
-  bool repeating = parameterObject["repeating"].asBoolean(false);
+  bool timerrule = parameterObject["timerrule"].asBoolean(false);
   bool sentOkay = false;
   CPVRTimerInfoTagPtr timer(epgTag->Timer());
   if (timer)
   {
-    sentOkay = g_PVRTimers->DeleteTimer(timer, false, repeating);
+    if (timerrule)
+      timer = g_PVRTimers->GetTimerRule(timer);
+
+    if (timer)
+      sentOkay = g_PVRTimers->DeleteTimer(timer, timer->IsRecording(), false);
   }
   else
   {
-    timer = CPVRTimerInfoTag::CreateFromEpg(epgTag, repeating);
+    timer = CPVRTimerInfoTag::CreateFromEpg(epgTag, timerrule);
     sentOkay = g_PVRTimers->AddTimer(timer);
   }
 
diff --git a/xbmc/interfaces/json-rpc/PlayerOperations.cpp b/xbmc/interfaces/json-rpc/PlayerOperations.cpp
index e67abad..7e70191 100644
--- a/xbmc/interfaces/json-rpc/PlayerOperations.cpp
+++ b/xbmc/interfaces/json-rpc/PlayerOperations.cpp
@@ -278,7 +278,7 @@ JSONRPC_STATUS CPlayerOperations::PlayPause(const std::string &method, ITranspor
           if (g_application.m_pPlayer->IsPausedPlayback())
             CApplicationMessenger::GetInstance().SendMsg(TMSG_MEDIA_PAUSE);
           else if (g_application.m_pPlayer->GetPlaySpeed() != 1)
-            g_application.m_pPlayer->SetPlaySpeed(1, g_application.IsMutedInternal());
+            g_application.m_pPlayer->SetPlaySpeed(1);
         }
         else if (!g_application.m_pPlayer->IsPausedPlayback())
           CApplicationMessenger::GetInstance().SendMsg(TMSG_MEDIA_PAUSE);
@@ -338,7 +338,7 @@ JSONRPC_STATUS CPlayerOperations::SetSpeed(const std::string &method, ITransport
           // If the player is paused we first need to unpause
           if (g_application.m_pPlayer->IsPausedPlayback())
             g_application.m_pPlayer->Pause();
-          g_application.m_pPlayer->SetPlaySpeed(speed, g_application.IsMutedInternal());
+          g_application.m_pPlayer->SetPlaySpeed(speed);
         }
         else
           g_application.m_pPlayer->Pause();
@@ -1151,6 +1151,9 @@ JSONRPC_STATUS CPlayerOperations::StartSlideshow(const std::string& path, bool r
   if (!firstPicturePath.empty())
     params.push_back(firstPicturePath);
 
+  // Reset screensaver when started from JSON only to avoid potential conflict with slideshow screensavers
+  g_application.ResetScreenSaver();
+  g_application.WakeUpScreenSaverAndDPMS();
   CGUIMessage msg(GUI_MSG_START_SLIDESHOW, 0, 0, flags);
   msg.SetStringParams(params);
   CApplicationMessenger::GetInstance().SendGUIMessage(msg, WINDOW_SLIDESHOW, true);
diff --git a/xbmc/interfaces/json-rpc/VideoLibrary.cpp b/xbmc/interfaces/json-rpc/VideoLibrary.cpp
index c9067a7..bc70976 100644
--- a/xbmc/interfaces/json-rpc/VideoLibrary.cpp
+++ b/xbmc/interfaces/json-rpc/VideoLibrary.cpp
@@ -528,7 +528,7 @@ JSONRPC_STATUS CVideoLibrary::SetMovieDetails(const std::string &method, ITransp
     return InternalError;
 
   CVideoInfoTag infos;
-  if (!videodatabase.GetMovieInfo("", infos, id, RequiresInitialDetails(parameterObject)) || infos.m_iDbId <= 0)
+  if (!videodatabase.GetMovieInfo("", infos, id) || infos.m_iDbId <= 0)
     return InvalidParams;
 
   // get artwork
@@ -605,7 +605,7 @@ JSONRPC_STATUS CVideoLibrary::SetTVShowDetails(const std::string &method, ITrans
     return InternalError;
 
   CVideoInfoTag infos;
-  if (!videodatabase.GetTvShowInfo("", infos, id, (CFileItem *)0, RequiresInitialDetails(parameterObject)) || infos.m_iDbId <= 0)
+  if (!videodatabase.GetTvShowInfo("", infos, id) || infos.m_iDbId <= 0)
     return InvalidParams;
 
   // get artwork
@@ -676,7 +676,7 @@ JSONRPC_STATUS CVideoLibrary::SetEpisodeDetails(const std::string &method, ITran
     return InternalError;
 
   CVideoInfoTag infos;
-  videodatabase.GetEpisodeInfo("", infos, id, RequiresInitialDetails(parameterObject));
+  videodatabase.GetEpisodeInfo("", infos, id);
   if (infos.m_iDbId <= 0)
   {
     videodatabase.Close();
@@ -988,14 +988,6 @@ bool CVideoLibrary::FillFileItemList(const CVariant &parameterObject, CFileItemL
   return success;
 }
 
-int CVideoLibrary::RequiresInitialDetails(const CVariant &parameterObject)
-{
-  int details = VideoDbDetailsNone;
-  if (ParameterNotNull(parameterObject, "ratings") || ParameterNotNull(parameterObject, "rating") || ParameterNotNull(parameterObject, "votes"))
-    return VideoDbDetailsRating;
-  return details;
-}
-
 int CVideoLibrary::RequiresAdditionalDetails(const MediaType& mediaType, const CVariant &parameterObject)
 {
   if (mediaType != MediaTypeMovie && mediaType != MediaTypeTvShow && mediaType != MediaTypeEpisode && mediaType != MediaTypeMusicVideo)
@@ -1010,6 +1002,8 @@ int CVideoLibrary::RequiresAdditionalDetails(const MediaType& mediaType, const C
       details = details | VideoDbDetailsCast;
     else if (propertyValue == "ratings")
       details = details | VideoDbDetailsRating;
+    else if (propertyValue == "uniqueid")
+      details = details | VideoDbDetailsUniqueID;
     else if (propertyValue == "showlink")
       details = details | VideoDbDetailsShowLink;
     else if (propertyValue == "streamdetails")
@@ -1149,7 +1143,24 @@ void CVideoLibrary::UpdateVideoTag(const CVariant &parameterObject, CVideoInfoTa
   if (ParameterNotNull(parameterObject, "mpaa"))
     details.SetMPAARating(parameterObject["mpaa"].asString());
   if (ParameterNotNull(parameterObject, "imdbnumber"))
-    details.SetIMDBNumber(parameterObject["imdbnumber"].asString());
+    details.SetUniqueID(parameterObject["imdbnumber"].asString());
+  if (ParameterNotNull(parameterObject, "uniqueid"))
+  {
+    CVariant uniqueids = parameterObject["uniqueid"];
+    for (CVariant::const_iterator_map idIt = uniqueids.begin_map(); idIt != uniqueids.end_map(); idIt++)
+    {
+      if (idIt->second.isString() && !idIt->second.asString().empty())
+      {
+        details.SetUniqueID(idIt->second.asString(), idIt->first);
+        updatedDetails.insert("uniqueid");
+      }
+      else if (idIt->second.isNull() && idIt->first != details.GetDefaultUniqueID())
+      {
+        details.RemoveUniqueID(idIt->first);
+        updatedDetails.insert("uniqueid");
+      }
+    }
+  }
   if (ParameterNotNull(parameterObject, "premiered"))
   {
     CDateTime premiered;
diff --git a/xbmc/interfaces/json-rpc/VideoLibrary.h b/xbmc/interfaces/json-rpc/VideoLibrary.h
index efe9d5c..f1bac0b 100644
--- a/xbmc/interfaces/json-rpc/VideoLibrary.h
+++ b/xbmc/interfaces/json-rpc/VideoLibrary.h
@@ -84,7 +84,6 @@ namespace JSONRPC
 
   private:
     static int RequiresAdditionalDetails(const MediaType& mediaType, const CVariant &parameterObject);
-    static int RequiresInitialDetails(const CVariant &parameterObject);
     static JSONRPC_STATUS HandleItems(const char *idProperty, const char *resultName, CFileItemList &items, const CVariant &parameterObject, CVariant &result, bool limit = true);
     static JSONRPC_STATUS RemoveVideo(const CVariant &parameterObject);
     static void UpdateVideoTag(const CVariant &parameterObject, CVideoInfoTag &details, std::map<std::string, std::string> &artwork, std::set<std::string> &removedArtwork, std::set<std::string>& updatedDetails);
diff --git a/xbmc/interfaces/json-rpc/schema/CMakeLists.txt b/xbmc/interfaces/json-rpc/schema/CMakeLists.txt
index 9a9109a..7e219fe 100644
--- a/xbmc/interfaces/json-rpc/schema/CMakeLists.txt
+++ b/xbmc/interfaces/json-rpc/schema/CMakeLists.txt
@@ -22,6 +22,7 @@ add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/addons/xbmc.json/addon.xml
 add_custom_target(generate_json_header ALL
                   DEPENDS ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/ServiceDescription.h
                           ${CMAKE_BINARY_DIR}/addons/xbmc.json/addon.xml)
+set_target_properties(generate_json_header PROPERTIES FOLDER "Build Utilities")
 
 if(BOOTSTRAP_IN_TREE)
   add_dependencies(generate_json_header JsonSchemaBuilder::JsonSchemaBuilder)
diff --git a/xbmc/interfaces/json-rpc/schema/methods.json b/xbmc/interfaces/json-rpc/schema/methods.json
index e4897ef..78f2427 100644
--- a/xbmc/interfaces/json-rpc/schema/methods.json
+++ b/xbmc/interfaces/json-rpc/schema/methods.json
@@ -1493,7 +1493,8 @@
       { "name": "userrating", "$ref": "Optional.Integer" },
       { "name": "ratings", "$ref": "Video.Ratings.Set" },
       { "name": "dateadded", "$ref": "Optional.String" },
-      { "name": "premiered", "$ref": "Optional.String", "description": "linked with year. Overriedes year" }
+      { "name": "premiered", "$ref": "Optional.String", "description": "linked with year. Overriedes year" },
+      { "name": "uniqueid", "type": [ "null", { "$ref": "Media.UniqueID.Set", "required": true } ], "default": null }
     ],
     "returns": "string"
   },
@@ -1538,7 +1539,8 @@
       { "name": "ratings", "$ref": "Video.Ratings.Set" },
       { "name": "dateadded", "$ref": "Optional.String" },
       { "name": "runtime", "$ref": "Optional.Integer", "description": "Runtime in seconds" },
-      { "name": "status", "$ref": "Optional.String" }
+      { "name": "status", "$ref": "Optional.String" },
+      { "name": "uniqueid", "type": [ "null", { "$ref": "Media.UniqueID.Set", "required": true } ], "default": null }
     ],
     "returns": "string"
   },
@@ -1581,7 +1583,8 @@
       { "name": "resume", "type": [ "null", { "$ref": "Video.Resume", "required": true } ], "default": null },
       { "name": "userrating", "$ref": "Optional.Integer" },
       { "name": "ratings", "$ref": "Video.Ratings.Set" },
-      { "name": "dateadded", "$ref": "Optional.String" }
+      { "name": "dateadded", "$ref": "Optional.String" },
+      { "name": "uniqueid", "type": [ "null", { "$ref": "Media.UniqueID.Set", "required": true } ], "default": null }
     ],
     "returns": "string"
   },
@@ -1835,7 +1838,8 @@
       { "name": "content", "$ref": "Addon.Content", "description": "Content provided by the addon. Only considered for plugins and scripts." },
       { "name": "enabled", "type": [ { "type": "boolean" }, { "type": "string", "enum": [ "all" ] } ], "default": "all" },
       { "name": "properties", "$ref": "Addon.Fields" },
-      { "name": "limits", "$ref": "List.Limits" }
+      { "name": "limits", "$ref": "List.Limits" },
+      { "name": "installed", "type": [ { "type": "boolean" }, { "type": "string", "enum": [ "all" ] } ], "default": true }
     ],
     "returns": { "type": "object",
       "properties": {
@@ -2042,34 +2046,33 @@
   },
   "PVR.AddTimer": {
     "type": "method",
-    "description": "Adds a timer",
+    "description": "Adds a timer to record the given show one times or a timer rule to record all showings of the given show",
     "transport": "Response",
     "permission": "ControlPVR",
     "params": [
-      { "name": "broadcastid", "$ref": "Library.Id", "required": true, "description": "the broadcast id of item to record" },
-      { "name": "repeating", "type": "boolean", "default": false, "description": "the add should be done for all occurances" }
+      { "name": "broadcastid", "$ref": "Library.Id", "required": true, "description": "the broadcast id of the item to record" },
+      { "name": "timerrule", "type": "boolean", "default": false, "description": "controls whether to create a timer rule or a onetime timer" }
     ],
     "returns":  "string"
   },
   "PVR.DeleteTimer": {
     "type": "method",
-    "description": "Removes a timer",
+    "description": "Deletes a onetime timer or a timer rule",
     "transport": "Response",
     "permission": "ControlPVR",
     "params": [
-      { "name": "timerid", "$ref": "Library.Id", "required": true, "description": "the id of the timer to delete" },
-      { "name": "repeating", "type": "boolean", "default": false, "description": "the delete should be done for all occurances" }
+      { "name": "timerid", "$ref": "Library.Id", "required": true, "description": "the id of the onetime timer or timer rule to delete" }
     ],
     "returns":  "string"
   },
   "PVR.ToggleTimer": {
     "type": "method",
-    "description": "Toggles a timer",
+    "description": "Creates or deletes a onetime timer or timer rule for a given show. If it exists, it will be deleted. If it does not exist, it will be created",
     "transport": "Response",
     "permission": "ControlPVR",
     "params": [
-      { "name": "broadcastid", "$ref": "Library.Id", "required": true, "description": "the id of the broadcast to toggle a timer for" },
-      { "name": "repeating", "type": "boolean", "default": false, "description": "the toggle should be done for all occurances" }
+      { "name": "broadcastid", "$ref": "Library.Id", "required": true, "description": "the broadcast id of the item to toggle a onetime timer or time rule for" }
+      { "name": "timerrule", "type": "boolean", "default": false, "description": "controls whether to create / delete a timer rule or a onetime timer" }
     ],
     "returns":  "string"
   },
@@ -2359,6 +2362,14 @@
     "params": [],
     "returns": "string"
   },
+  "Input.ShowPlayerProcessInfo": {
+    "type": "method",
+    "description": "Show player process information of the playing item, like video decoder, pixel format, pvr signal strength, ...",
+    "transport": "Response",
+    "permission": "Navigate",
+    "params": [],
+    "returns": "string"
+  },
   "Application.GetProperties": {
     "type": "method",
     "description": "Retrieves the values of the given properties",
diff --git a/xbmc/interfaces/json-rpc/schema/types.json b/xbmc/interfaces/json-rpc/schema/types.json
index 6264dea..8472163 100644
--- a/xbmc/interfaces/json-rpc/schema/types.json
+++ b/xbmc/interfaces/json-rpc/schema/types.json
@@ -408,6 +408,14 @@
     "type": "object",
     "additionalProperties": { "type": [ "null", { "$ref": "Video.Rating", "required": true } ] }
   },
+  "Media.UniqueID": {
+    "type": "object",
+    "additionalProperties": { "$ref": "Global.String.NotEmpty" }
+  },
+  "Media.UniqueID.Set": {
+    "type": "object",
+    "additionalProperties": { "type": [ "null", { "$ref": "Global.String.NotEmpty", "required": true } ] }
+  },
   "Library.Fields.Genre": {
     "extends": "Item.Fields.Base",
     "items": { "type": "string", "enum": [ "title", "thumbnail" ] }
@@ -618,13 +626,14 @@
   "Video.Fields.Movie": {
     "extends": "Item.Fields.Base",
     "items": { "type": "string",
-      "description": "Requesting the cast, ratings, showlink, streamdetails and/or tag field will result in increased response times",
+      "description": "Requesting the cast, ratings, showlink, streamdetails, uniqueid and/or tag field will result in increased response times",
       "enum": [ "title", "genre", "year", "rating", "director", "trailer",
                 "tagline", "plot", "plotoutline", "originaltitle", "lastplayed",
                 "playcount", "writer", "studio", "mpaa", "cast", "country",
                 "imdbnumber", "runtime", "set", "showlink", "streamdetails",
                 "top250", "votes", "fanart", "thumbnail", "file", "sorttitle",
-                "resume", "setid", "dateadded", "tag", "art", "userrating", "ratings", "premiered" ]
+                "resume", "setid", "dateadded", "tag", "art", "userrating",  
+                "ratings", "premiered", "uniqueid" ]
     }
   },
   "Video.Fields.MovieSet": {
@@ -636,13 +645,14 @@
   "Video.Fields.TVShow": {
     "extends": "Item.Fields.Base",
     "items": { "type": "string",
-      "description": "Requesting the cast, ratings and/or tag field will result in increased response times",
+      "description": "Requesting the cast, ratings, uniqueid and/or tag field will result in increased response times",
       "enum": [ "title", "genre", "year", "rating", "plot",
                 "studio", "mpaa", "cast", "playcount", "episode",
                 "imdbnumber", "premiered", "votes", "lastplayed",
                 "fanart", "thumbnail", "file", "originaltitle",
                 "sorttitle", "episodeguide", "season", "watchedepisodes",
-                "dateadded", "tag", "art", "userrating", "ratings", "runtime" ]
+                "dateadded", "tag", "art", "userrating", "ratings", 
+                "runtime", "uniqueid" ]
     }
   },
   "Video.Fields.Season": {
@@ -655,7 +665,7 @@
   "Video.Fields.Episode": {
     "extends": "Item.Fields.Base",
     "items": { "type": "string",
-      "description": "Requesting the cast, ratings, streamdetails and/or tag field will result in increased response times",
+      "description": "Requesting the cast, ratings, streamdetails, uniqueid and/or tag field will result in increased response times",
       "enum": [ "title", "plot", "votes", "rating", "writer",
                 "firstaired", "playcount", "runtime", "director",
                 "productioncode", "season", "episode", "originaltitle",
@@ -789,7 +799,8 @@
       "tag": { "$ref": "Array.String" },
       "userrating": { "type": "integer" },
       "ratings": { "type": "Video.Ratings" },
-      "premiered": { "type": "string" }
+      "premiered": { "type": "string" },
+      "uniqueid": { "$ref": "Media.UniqueID" }
     }
   },
   "Video.Details.MovieSet": {
@@ -830,7 +841,8 @@
       "tag": { "$ref": "Array.String" },
       "userrating": { "type": "integer" },
       "ratings": { "type": "Video.Ratings" },
-      "runtime": { "type": "integer", "description": "Runtime in seconds" }
+      "runtime": { "type": "integer", "description": "Runtime in seconds" },
+      "uniqueid": { "$ref": "Media.UniqueID" }
     }
   },
   "Video.Details.Season": {
@@ -856,7 +868,7 @@
       "productioncode": { "type": "string" },
       "season": { "type": "integer" },
       "episode": { "type": "integer" },
-      "uniqueid": { "type": "object", "additionalProperties": { "type": "string", "minLength": 1 } },
+      "uniqueid": { "$ref": "Media.UniqueID" },
       "originaltitle": { "type": "string" },
       "showtitle": { "type": "string" },
       "cast": { "$ref": "Video.Cast" },
@@ -909,7 +921,9 @@
                 "endtime", "runtime", "progress", "progresspercentage",
                 "genre", "episodename", "episodenum", "episodepart",
                 "firstaired", "hastimer", "isactive", "parentalrating",
-                "wasactive", "thumbnail", "rating" ]
+                "wasactive", "thumbnail", "rating", "originaltitle", "cast",
+                "director", "writer", "year", "imdbnumber", "hastimerrule",
+                "hasrecording", "recording", "isseries" ]
     }
   },
   "PVR.Details.Broadcast": {
@@ -934,13 +948,25 @@
       "parentalrating": { "type": "integer" },
       "wasactive": { "type": "boolean" },
       "thumbnail": { "type": "string" },
-      "rating": { "type": "integer" }
+      "rating": { "type": "integer" },
+      "originaltitle": { "type": "string" },
+      "cast": { "type": "string" },
+      "director": { "type": "string" },
+      "writer": { "type": "string" },
+      "year": { "type": "integer" },
+      "imdbnumber": { "type": "integer" },
+      "hastimerrule": { "type": "boolean" },
+      "hasrecording": { "type": "boolean" },
+      "recording": { "type": "string" },
+      "isseries": { "type": "boolean" }
     }
   },
   "PVR.Fields.Channel": {
     "extends": "Item.Fields.Base",
     "items": { "type": "string",
-      "enum": [ "thumbnail", "channeltype", "hidden", "locked", "channel", "lastplayed", "broadcastnow", "broadcastnext", "uniqueid"]
+      "enum": [ "thumbnail", "channeltype", "hidden", "locked", "channel", "lastplayed",
+                "broadcastnow", "broadcastnext", "uniqueid", "icon", "channelnumber",
+                "subchannelnumber" ]
     }
   },
   "PVR.Details.Channel": {
@@ -955,7 +981,10 @@
       "lastplayed": { "type": "string" },
       "broadcastnow": { "$ref": "PVR.Details.Broadcast" },
       "broadcastnext": { "$ref": "PVR.Details.Broadcast" },
-      "uniqueid": { "type": "integer", "required": true }
+      "uniqueid": { "type": "integer", "required": true },
+      "icon": { "type": "string" },
+      "channelnumber": { "type": "integer" },
+      "subchannelnumber": { "type": "integer" }
     }
   },
   "PVR.Details.ChannelGroup": {
@@ -978,15 +1007,17 @@
     "type": "string",
     "enum": [ "unknown", "new", "scheduled", "recording", "completed",
               "aborted", "cancelled", "conflict_ok", "conflict_notok",
-              "error" ]
+              "error", "disabled" ]
   },
   "PVR.Fields.Timer": {
     "extends": "Item.Fields.Base",
     "items": { "type": "string",
-      "enum": [ "title", "summary", "channelid", "isradio", "repeating",
+      "enum": [ "title", "summary", "channelid", "isradio", "istimerrule", "ismanual",
                 "starttime", "endtime", "runtime", "lifetime", "firstday",
                 "weekdays", "priority", "startmargin", "endmargin", "state",
-                "file", "directory" ]
+                "file", "directory", "preventduplicateepisodes", "startanytime",
+                "endanytime", "epgsearchstring", "fulltextepgsearch", "recordinggroup",
+                "maxrecordings", "epguid", "isreadonly" ]
     }
   },
   "PVR.Details.Timer": {
@@ -997,7 +1028,8 @@
       "summary": { "type": "string" },
       "channelid": { "$ref": "Library.Id" },
       "isradio": { "type": "boolean" },
-      "repeating": { "type": "boolean" },
+      "istimerrule": { "type": "boolean" },
+      "ismanual": { "type": "boolean" },
       "starttime": { "type": "string" },
       "endtime": { "type": "string" },
       "runtime": { "type": "integer" },
@@ -1012,7 +1044,16 @@
       "endmargin": { "type": "integer" },
       "state": { "$ref": "PVR.TimerState" },
       "file": { "type": "string" },
-      "directory": { "type": "string" }
+      "directory": { "type": "string" },
+      "preventduplicateepisodes": { "type": "integer" },
+      "startanytime": { "type": "boolean" },
+      "endanytime": { "type": "boolean" },
+      "epgsearchstring": { "type": "string" },
+      "fulltextepgsearch": { "type": "boolean" },
+      "recordinggroup": { "type": "integer" },
+      "maxrecordings": { "type": "integer" },
+      "epguid": { "type": "integer" },
+      "isreadonly": { "type": "boolean" }
     }
   },
   "PVR.Fields.Recording": {
@@ -1021,7 +1062,7 @@
       "enum": [ "title", "plot", "plotoutline", "genre", "playcount",
                 "resume", "channel", "starttime","endtime", "runtime",
                 "lifetime", "icon", "art", "streamurl", "file",
-                "directory", "radio" ]
+                "directory", "radio", "isdeleted", "epgeventid", "channeluid" ]
     }
   },
   "PVR.Details.Recording": {
@@ -1044,7 +1085,10 @@
       "streamurl": { "type": "string" },
       "file": { "type": "string" },
       "directory": { "type": "string" },
-      "radio": { "type": "boolean" }
+      "radio": { "type": "boolean" },
+      "isdeleted": { "type": "boolean" },
+      "epgeventid": { "type": "integer" },
+      "channeluid": { "type": "integer" }
     }
   },
   "Textures.Details.Size": {
@@ -1360,7 +1404,7 @@
       "disc": { "type": "integer" },
       "tag": { "$ref": "Array.String" },
       "albumartistid": { "$ref": "Array.Integer" },
-      "uniqueid": { "type": "object", "additionalProperties": { "type": "string", "minLength": 1 } },
+      "uniqueid": { "$ref": "Media.UniqueID" },
       "episodeguide": { "type": "string" },
       "sorttitle": { "type": "string" },
       "description": { "type": "string" },
@@ -1458,7 +1502,7 @@
     "extends": "Item.Fields.Base",
     "items": { "type": "string",
       "enum": [ "name", "version", "summary", "description", "path", "author", "thumbnail", "disclaimer", "fanart",
-                "dependencies", "broken", "extrainfo", "rating", "enabled" ]
+                "dependencies", "broken", "extrainfo", "rating", "enabled", "installed" ]
     }
   },
   "Addon.Details": {
@@ -1494,7 +1538,8 @@
         }
       },
       "rating": { "type": "integer" },
-      "enabled": { "type": "boolean" }
+      "enabled": { "type": "boolean" },
+      "installed": { "type": "boolean" }
     }
   },
   "GUI.Stereoscopy.Mode": {
diff --git a/xbmc/interfaces/json-rpc/schema/version.txt b/xbmc/interfaces/json-rpc/schema/version.txt
index ee0a997..c650e0f 100644
--- a/xbmc/interfaces/json-rpc/schema/version.txt
+++ b/xbmc/interfaces/json-rpc/schema/version.txt
@@ -1 +1 @@
-7.16.0
\ No newline at end of file
+7.20.1
diff --git a/xbmc/interfaces/legacy/CMakeLists.txt b/xbmc/interfaces/legacy/CMakeLists.txt
index 8f257eb..3614188 100644
--- a/xbmc/interfaces/legacy/CMakeLists.txt
+++ b/xbmc/interfaces/legacy/CMakeLists.txt
@@ -66,8 +66,3 @@ set(HEADERS Addon.h
             WindowXML.h)
 
 core_add_library(legacy_interface)
-add_dependencies(legacy_interface libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(legacy_interface ffmpeg)
-endif()
diff --git a/xbmc/interfaces/legacy/InfoTagVideo.cpp b/xbmc/interfaces/legacy/InfoTagVideo.cpp
index 2f635be..638f8bf 100644
--- a/xbmc/interfaces/legacy/InfoTagVideo.cpp
+++ b/xbmc/interfaces/legacy/InfoTagVideo.cpp
@@ -119,7 +119,7 @@ namespace XBMCAddon
 
     String InfoTagVideo::getIMDBNumber()
     {
-      return infoTag->m_strIMDBNumber;
+      return infoTag->GetUniqueID();
     }
 
     int InfoTagVideo::getSeason()
diff --git a/xbmc/interfaces/legacy/ListItem.cpp b/xbmc/interfaces/legacy/ListItem.cpp
index 244ec80..74b3c96 100644
--- a/xbmc/interfaces/legacy/ListItem.cpp
+++ b/xbmc/interfaces/legacy/ListItem.cpp
@@ -147,6 +147,16 @@ namespace XBMCAddon
       }
     }
 
+    void ListItem::setUniqueIDs(const Properties& dictionary)
+    {
+      if (!item) return;
+
+      LOCKGUI;
+      CVideoInfoTag& vtag = *item->GetVideoInfoTag();
+      for (Properties::const_iterator it = dictionary.begin(); it != dictionary.end(); ++it)
+        vtag.SetUniqueID(it->second, it->first);
+    }
+
     void ListItem::select(bool selected)
     {
       if (!item) return;
@@ -230,6 +240,12 @@ namespace XBMCAddon
       return item->GetArt(key);
     }
 
+    String ListItem::getUniqueID(const char* key)
+    {
+      LOCKGUI;
+      return item->GetVideoInfoTag()->GetUniqueID(key);
+    }
+
 
     void ListItem::setPath(const String& path)
     {
@@ -398,7 +414,7 @@ namespace XBMCAddon
           else if (key == "set")
             item->GetVideoInfoTag()->m_strSet = value;
           else if (key == "imdbnumber")
-            item->GetVideoInfoTag()->m_strIMDBNumber = value;
+            item->GetVideoInfoTag()->SetUniqueID(value);
           else if (key == "code")
             item->GetVideoInfoTag()->m_strProductionCode = value;
           else if (key == "aired")
diff --git a/xbmc/interfaces/legacy/ListItem.h b/xbmc/interfaces/legacy/ListItem.h
index 9b40b07..a4ac58f 100644
--- a/xbmc/interfaces/legacy/ListItem.h
+++ b/xbmc/interfaces/legacy/ListItem.h
@@ -258,6 +258,39 @@ namespace XBMCAddon
 #ifdef DOXYGEN_SHOULD_USE_THIS
       ///
       /// \ingroup python_xbmcgui_listitem
+      /// @brief \python_func{ setUniqueIDs(values) }
+      ///-----------------------------------------------------------------------
+      /// Sets the listitem's uniqueID
+      ///
+      /// @param values             dictionary - pairs of `{ label: value }`.
+      ///  - Some example values (any string possible):
+      ///  | Label         | Type                                              |
+      ///  |:-------------:|:--------------------------------------------------|
+      ///  | imdb          | string - uniqueid name
+      ///  | tvdb          | string - uniqueid name
+      ///  | tmdb          | string - uniqueid name
+      ///  | anidb         | string - uniqueid name
+      ///
+      ///
+      ///
+      ///-----------------------------------------------------------------------
+      ///
+      /// **Example:**
+      /// ~~~~~~~~~~~~~{.py}
+      /// ...
+      /// # setUniqueIDs(values)
+      /// self.list.getSelectedItem().setUniqueIDs({ 'imdb': 'tt8938399', 'tmdb' : '9837493' })
+      /// ...
+      /// ~~~~~~~~~~~~~
+      ///
+      setUniqueIDs(...);
+#else
+      void setUniqueIDs(const Properties& dictionary);
+#endif
+
+#ifdef DOXYGEN_SHOULD_USE_THIS
+      ///
+      /// \ingroup python_xbmcgui_listitem
       /// @brief \python_func{ getArt(key) }
       ///-----------------------------------------------------------------------
       /// Returns a listitem art path as a string, similar to an infolabel.\n
@@ -294,6 +327,38 @@ namespace XBMCAddon
 #ifdef DOXYGEN_SHOULD_USE_THIS
       ///
       /// \ingroup python_xbmcgui_listitem
+      /// @brief \python_func{ getUniqueID(key) }
+      ///-----------------------------------------------------------------------
+      /// Returns a listitem uniqueID as a string, similar to an infolabel.\n
+      ///
+      /// @param key            string - uniqueID name.
+      /// - Some default uniqueID values (any string possible):
+      ///  | Label         | Type                                             |
+      ///  |---------------|--------------------------------------------------|
+      ///  | imdb          | string - uniqueid name
+      ///  | tvdb          | string - uniqueid name
+      ///  | tmdb          | string - uniqueid name
+      ///  | anidb         | string - uniqueid name
+      ///
+      ///
+      ///
+      ///-----------------------------------------------------------------------
+      ///
+      /// **Example:**
+      /// ~~~~~~~~~~~~~{.py}
+      /// ...
+      /// uniqueID = self.list.getSelectedItem().getUniqueID('imdb')
+      /// ...
+      /// ~~~~~~~~~~~~~
+      ///
+      getUniqueID(key);
+#else
+      String getUniqueID(const char* key);
+#endif
+
+#ifdef DOXYGEN_SHOULD_USE_THIS
+      ///
+      /// \ingroup python_xbmcgui_listitem
       /// @brief \python_func{ select(selected) }
       ///-----------------------------------------------------------------------
       /// Sets the listitem's selected status.
diff --git a/xbmc/interfaces/legacy/ModuleXbmc.cpp b/xbmc/interfaces/legacy/ModuleXbmc.cpp
index af6472f..0b921a8 100644
--- a/xbmc/interfaces/legacy/ModuleXbmc.cpp
+++ b/xbmc/interfaces/legacy/ModuleXbmc.cpp
@@ -370,9 +370,8 @@ namespace XBMCAddon
     String getCacheThumbName(const String& path)
     {
       XBMC_TRACE;
-      Crc32 crc;
-      crc.ComputeFromLowerCase(path);
-      return StringUtils::Format("%08x.tbn", (unsigned __int32)crc);
+      auto crc = Crc32::ComputeFromLowerCase(path);
+      return StringUtils::Format("%08x.tbn", crc);
     }
 
     String makeLegalFilename(const String& filename, bool fatX)
diff --git a/xbmc/interfaces/python/CMakeLists.txt b/xbmc/interfaces/python/CMakeLists.txt
index c267180..061cc2b 100644
--- a/xbmc/interfaces/python/CMakeLists.txt
+++ b/xbmc/interfaces/python/CMakeLists.txt
@@ -19,4 +19,3 @@ set(HEADERS AddonPythonInvoker.h
             XBPython.h)
 
 core_add_library(python_interface)
-add_dependencies(python_interface libcpluff)
diff --git a/xbmc/interfaces/swig/CMakeLists.txt b/xbmc/interfaces/swig/CMakeLists.txt
index 928caa6..6e67615 100644
--- a/xbmc/interfaces/swig/CMakeLists.txt
+++ b/xbmc/interfaces/swig/CMakeLists.txt
@@ -1,4 +1,4 @@
-macro(generate_file file)
+function(generate_file file)
   set(classpath ${GROOVY_DIR}/groovy-all-${GROOVY_VER}.jar
                 ${GROOVY_DIR}/commons-lang-${COMMONS_VER}.jar
                 ${CORE_SOURCE_DIR}/tools/codegenerator
@@ -10,14 +10,15 @@ macro(generate_file file)
     set(devnull "nul")
   endif()
 
-  add_custom_command(OUTPUT ${file}.cpp
+  set(CPP_FILE ${file}.cpp)
+  add_custom_command(OUTPUT ${CPP_FILE}
                      COMMAND ${SWIG_EXECUTABLE}
                      ARGS -w401 -c++ -o ${file}.xml -xml -I${CORE_SOURCE_DIR}/xbmc -xmllang python ${CMAKE_CURRENT_SOURCE_DIR}/../swig/${file}
                      COMMAND ${Java_JAVA_EXECUTABLE}
                      ARGS -cp "${classpath}" groovy.ui.GroovyMain ${CORE_SOURCE_DIR}/tools/codegenerator/Generator.groovy ${file}.xml ${CMAKE_CURRENT_SOURCE_DIR}/../python/PythonSwig.cpp.template ${file}.cpp > ${devnull}
-                     IMPLICIT_DEPENDS CXX ${CMAKE_CURRENT_SOURCE_DIR}/../swig/${file})
-  list(APPEND SOURCES ${file}.cpp)
-endmacro()
+                     DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../swig/${file})
+  set(SOURCES ${SOURCES} "${CPP_FILE}" PARENT_SCOPE)
+endfunction()
 
 find_package(Java COMPONENTS Runtime REQUIRED)
 find_package(SWIG REQUIRED)
@@ -34,13 +35,15 @@ set(GROOVY_DIR ${CORE_SOURCE_DIR}/tools/codegenerator/groovy)
 set(GROOVY_VER 2.4.4)
 set(COMMONS_VER 2.6)
 
-file(GLOB INTERFACE_FILES ${CORE_SOURCE_DIR}/xbmc/lib/legacy)
-
-set(SOURCES "")
-
-foreach(INPUT ${INPUTS})
+foreach(INPUT IN LISTS INPUTS)
   generate_file(${INPUT})
+  list(APPEND GEN_SRCS ${CMAKE_CURRENT_BINARY_DIR}/${INPUT}.cpp)
 endforeach()
 
-core_add_library(python_binding)
-add_dependencies(python_binding python_interface libcpluff)
+add_library(python_binding STATIC ${SOURCES})
+set_target_properties(python_binding PROPERTIES POSITION_INDEPENDENT_CODE TRUE
+                                                FOLDER "Build Utilities")
+set(core_DEPENDS python_binding ${core_DEPENDS} CACHE STRING "" FORCE)
+if(WIN32)
+  add_precompiled_header(python_binding pch.h ${CORE_SOURCE_DIR}/xbmc/platform/win32/pch.cpp PCH_TARGET kodi)
+endif()
diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp
index d101638..c417308 100644
--- a/xbmc/linux/RBP.cpp
+++ b/xbmc/linux/RBP.cpp
@@ -218,7 +218,7 @@ uint32_t CRBP::WaitVsync(uint32_t target)
     if (!m_vsync_cond.wait(vlock, delay.MillisLeft()))
       break;
   }
-  if (m_vsync_count < target)
+  if ((signed)(m_vsync_count - target) < 0)
     CLog::Log(LOGDEBUG, "CRBP::%s no  vsync %d/%d display:%x(%x) delay:%d", __FUNCTION__, m_vsync_count, target, m_display, display, delay.MillisLeft());
 
   return m_vsync_count;
diff --git a/xbmc/linux/sse4/CMakeLists.txt b/xbmc/linux/sse4/CMakeLists.txt
index cfee566..3df83ed 100644
--- a/xbmc/linux/sse4/CMakeLists.txt
+++ b/xbmc/linux/sse4/CMakeLists.txt
@@ -2,7 +2,6 @@ set(SOURCES CopyFrame.cpp)
 
 set(HEADERS DllLibSSE4.h)
 
-set(CMAKE_POSITION_INDEPENDENT_CODE 1)
-
-core_add_library(sse4 NO_MAIN_DEPENDS)
+core_add_shared_library(sse4)
+set_target_properties(sse4 PROPERTIES FOLDER lib)
 target_compile_options(sse4 PRIVATE -msse4.1)
diff --git a/xbmc/listproviders/CMakeLists.txt b/xbmc/listproviders/CMakeLists.txt
index 23c6526..a3b6729 100644
--- a/xbmc/listproviders/CMakeLists.txt
+++ b/xbmc/listproviders/CMakeLists.txt
@@ -7,4 +7,3 @@ set(HEADERS DirectoryProvider.h
             StaticProvider.h)
 
 core_add_library(listproviders)
-add_dependencies(listproviders libcpluff)
diff --git a/xbmc/listproviders/DirectoryProvider.cpp b/xbmc/listproviders/DirectoryProvider.cpp
index 75abf5b..d01d6fa 100644
--- a/xbmc/listproviders/DirectoryProvider.cpp
+++ b/xbmc/listproviders/DirectoryProvider.cpp
@@ -22,7 +22,6 @@
 
 #include <memory>
 #include <utility>
-
 #include "addons/GUIDialogAddonInfo.h"
 #include "ContextMenuManager.h"
 #include "FileItem.h"
@@ -37,14 +36,14 @@
 #include "settings/Settings.h"
 #include "threads/SingleLock.h"
 #include "utils/JobManager.h"
+#include "utils/log.h"
 #include "utils/SortUtils.h"
 #include "utils/URIUtils.h"
 #include "utils/Variant.h"
 #include "utils/XMLUtils.h"
 #include "video/VideoThumbLoader.h"
 #include "video/dialogs/GUIDialogVideoInfo.h"
-
-
+#include "video/windows/GUIWindowVideoBase.h"
 
 using namespace XFILE;
 using namespace ANNOUNCEMENT;
@@ -207,7 +206,13 @@ bool CDirectoryProvider::Update(bool forceRefresh)
   fireJob |= UpdateSort();
   fireJob |= UpdateLimit();
   if (fireJob)
+  {
+    {
+      CSingleLock lock(m_section);
+      CLog::Log(LOGDEBUG, "CDirectoryProvider[%s]: refreshing..", m_currentUrl.c_str());
+    }
     FireJob();
+  }
 
   for (std::vector<CGUIStaticItemPtr>::iterator i = m_items.begin(); i != m_items.end(); ++i)
     changed |= (*i)->UpdateVisibility(m_parentID);
@@ -255,6 +260,19 @@ void CDirectoryProvider::Fetch(std::vector<CGUIListItemPtr> &items) const
   }
 }
 
+void CDirectoryProvider::OnEvent(const ADDON::AddonEvent& event)
+{
+  CSingleLock lock(m_section);
+  if (URIUtils::IsProtocol(m_currentUrl, "addons"))
+  {
+    if (typeid(event) == typeid(ADDON::AddonEvents::Enabled) ||
+        typeid(event) == typeid(ADDON::AddonEvents::Disabled) ||
+        typeid(event) == typeid(ADDON::AddonEvents::InstalledChanged) ||
+        typeid(event) == typeid(ADDON::AddonEvents::MetadataChanged))
+    m_updateState = PENDING;
+  }
+}
+
 void CDirectoryProvider::Reset(bool immediately /* = false */)
 {
   // cancel any pending jobs
@@ -273,7 +291,7 @@ void CDirectoryProvider::Reset(bool immediately /* = false */)
     m_currentSort.sortOrder = SortOrderAscending;
     m_currentLimit = 0;
     m_updateState = OK;
-    RegisterListProvider(false);
+    RegisterListProvider();
   }
 }
 
@@ -293,13 +311,22 @@ void CDirectoryProvider::OnJobComplete(unsigned int jobID, bool success, CJob *j
 bool CDirectoryProvider::OnClick(const CGUIListItemPtr &item)
 {
   CFileItem fileItem(*std::static_pointer_cast<CFileItem>(item));
+
+  if (fileItem.HasVideoInfoTag()
+      && CSettings::GetInstance().GetInt(CSettings::SETTING_MYVIDEOS_SELECTACTION) == SELECT_ACTION_INFO
+      && OnInfo(item))
+    return true;
+
   std::string target = fileItem.GetProperty("node.target").asString();
-  if (target.empty())
-    target = m_currentTarget;
-  if (target.empty())
-    target = m_target.GetLabel(m_parentID, false);
-  if (fileItem.HasProperty("node.target_url"))
-    fileItem.SetPath(fileItem.GetProperty("node.target_url").asString());
+  {
+    CSingleLock lock(m_section);
+    if (target.empty())
+      target = m_currentTarget;
+    if (target.empty())
+      target = m_target.GetLabel(m_parentID, false);
+    if (fileItem.HasProperty("node.target_url"))
+      fileItem.SetPath(fileItem.GetProperty("node.target_url").asString());
+  }
   // grab the execute string
   std::string execute = CFavouritesDirectory::GetExecutePath(fileItem, target);
   if (!execute.empty())
@@ -351,36 +378,41 @@ void CDirectoryProvider::FireJob()
   m_jobID = CJobManager::GetInstance().AddJob(new CDirectoryJob(m_currentUrl, m_currentSort, m_currentLimit, m_parentID), this);
 }
 
-void CDirectoryProvider::RegisterListProvider(bool hasLibraryContent)
+void CDirectoryProvider::RegisterListProvider()
 {
-  if (hasLibraryContent && !m_isAnnounced)
+  CSingleLock lock(m_section);
+  if (!m_isAnnounced)
   {
     m_isAnnounced = true;
     CAnnouncementManager::GetInstance().AddAnnouncer(this);
+    ADDON::CAddonMgr::GetInstance().Events().Subscribe(this, &CDirectoryProvider::OnEvent);
   }
-  else if (!hasLibraryContent && m_isAnnounced)
+  else if (m_isAnnounced)
   {
     m_isAnnounced = false;
     CAnnouncementManager::GetInstance().RemoveAnnouncer(this);
+    ADDON::CAddonMgr::GetInstance().Events().Unsubscribe(this);
   }
 }
 
 bool CDirectoryProvider::UpdateURL()
 {
-  std::string value(m_url.GetLabel(m_parentID, false));
-  if (value == m_currentUrl)
-    return false;
-
-  m_currentUrl = value;
+  {
+    CSingleLock lock(m_section);
+    std::string value(m_url.GetLabel(m_parentID, false));
+    if (value == m_currentUrl)
+      return false;
 
-  // Register this provider only if we have library content
-  RegisterListProvider(URIUtils::IsLibraryContent(m_currentUrl));
+    m_currentUrl = value;
+  }
 
+  RegisterListProvider();
   return true;
 }
 
 bool CDirectoryProvider::UpdateLimit()
 {
+  CSingleLock lock(m_section);
   unsigned int value = m_limit.GetIntValue(m_parentID);
   if (value == m_currentLimit)
     return false;
@@ -392,6 +424,7 @@ bool CDirectoryProvider::UpdateLimit()
 
 bool CDirectoryProvider::UpdateSort()
 {
+  CSingleLock lock(m_section);
   SortBy sortMethod(SortUtils::SortMethodFromString(m_sortMethod.GetLabel(m_parentID, false)));
   SortOrder sortOrder(SortUtils::SortOrderFromString(m_sortOrder.GetLabel(m_parentID, false)));
   if (sortOrder == SortOrderNone)
diff --git a/xbmc/listproviders/DirectoryProvider.h b/xbmc/listproviders/DirectoryProvider.h
index a15fdd2..1b0a7e3 100644
--- a/xbmc/listproviders/DirectoryProvider.h
+++ b/xbmc/listproviders/DirectoryProvider.h
@@ -22,7 +22,7 @@
 
 #include <string>
 #include <vector>
-
+#include "addons/AddonEvents.h"
 #include "IListProvider.h"
 #include "guilib/GUIStaticItem.h"
 #include "utils/Job.h"
@@ -85,8 +85,9 @@ private:
   CCriticalSection m_section;
 
   void FireJob();
-  void RegisterListProvider(bool hasLibraryContent);
+  void RegisterListProvider();
   bool UpdateURL();
   bool UpdateLimit();
   bool UpdateSort();
+  void OnEvent(const ADDON::AddonEvent& event);
 };
diff --git a/xbmc/messaging/CMakeLists.txt b/xbmc/messaging/CMakeLists.txt
index 1a370a0..86c6b35 100644
--- a/xbmc/messaging/CMakeLists.txt
+++ b/xbmc/messaging/CMakeLists.txt
@@ -5,4 +5,3 @@ set(HEADERS ApplicationMessenger.h
             ThreadMessage.h)
 
 core_add_library(messaging)
-add_dependencies(messaging libcpluff)
diff --git a/xbmc/music/CMakeLists.txt b/xbmc/music/CMakeLists.txt
index 364f72a..2e29ab6 100644
--- a/xbmc/music/CMakeLists.txt
+++ b/xbmc/music/CMakeLists.txt
@@ -22,8 +22,3 @@ set(HEADERS Album.h
             Song.h)
 
 core_add_library(music)
-add_dependencies(music libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(music ffmpeg)
-endif()
diff --git a/xbmc/music/MusicDatabase.cpp b/xbmc/music/MusicDatabase.cpp
index 3ae0510..aea5b5e 100644
--- a/xbmc/music/MusicDatabase.cpp
+++ b/xbmc/music/MusicDatabase.cpp
@@ -396,9 +396,7 @@ void CMusicDatabase::SaveCuesheet(const std::string& fullSongPath, const std::st
   std::string strSQL;
   try
   {
-    CueCache::const_iterator it;
-
-    it = m_cueCache.find(fullSongPath);
+    auto it = m_cueCache.find(fullSongPath);
     if (it != m_cueCache.end() && it->second == strCuesheet)
       return;
 
@@ -445,8 +443,7 @@ void CMusicDatabase::SaveCuesheet(const std::string& fullSongPath, const std::st
 
 std::string CMusicDatabase::LoadCuesheet(const std::string& fullSongPath)
 {
-  CueCache::const_iterator it;
-  it = m_cueCache.find(fullSongPath);
+  auto it = m_cueCache.find(fullSongPath);
   if (it != m_cueCache.end())
     return it->second;
 
@@ -496,7 +493,7 @@ bool CMusicDatabase::AddAlbum(CAlbum& album)
   // Add the album artists
   if (album.artistCredits.empty())
     AddAlbumArtist(BLANKARTIST_ID, album.idAlbum, BLANKARTIST_NAME, 0); // Album must have at least one artist so set artist to [Missing]
-  for (VECARTISTCREDITS::iterator artistCredit = album.artistCredits.begin(); artistCredit != album.artistCredits.end(); ++artistCredit)
+  for (auto artistCredit = album.artistCredits.begin(); artistCredit != album.artistCredits.end(); ++artistCredit)
   {
     artistCredit->idArtist = AddArtist(artistCredit->GetArtist(), artistCredit->GetMusicBrainzArtistID());
     AddAlbumArtist(artistCredit->idArtist,
@@ -505,7 +502,7 @@ bool CMusicDatabase::AddAlbum(CAlbum& album)
                    std::distance(album.artistCredits.begin(), artistCredit));
   }
 
-  for (VECSONGS::iterator song = album.songs.begin(); song != album.songs.end(); ++song)
+  for (auto song = album.songs.begin(); song != album.songs.end(); ++song)
   {
     song->idAlbum = album.idAlbum;
 
@@ -525,7 +522,7 @@ bool CMusicDatabase::AddAlbum(CAlbum& album)
     if (song->artistCredits.empty())    
       AddSongArtist(BLANKARTIST_ID, song->idSong, ROLE_ARTIST, BLANKARTIST_NAME, 0); // Song must have at least one artist so set artist to [Missing]
     
-    for (VECARTISTCREDITS::iterator artistCredit = song->artistCredits.begin(); artistCredit != song->artistCredits.end(); ++artistCredit)
+    for (auto artistCredit = song->artistCredits.begin(); artistCredit != song->artistCredits.end(); ++artistCredit)
     {
       artistCredit->idArtist = AddArtist(artistCredit->GetArtist(),
                                          artistCredit->GetMusicBrainzArtistID());
@@ -541,13 +538,11 @@ bool CMusicDatabase::AddAlbum(CAlbum& album)
     SaveCuesheet(song->strFileName, song->strCueSheet);
   }
 
-  for (VECSONGS::const_iterator infoSong = album.infoSongs.begin(); infoSong != album.infoSongs.end(); ++infoSong)
-    AddAlbumInfoSong(album.idAlbum, *infoSong);
+  for (const auto &infoSong : album.infoSongs)
+    AddAlbumInfoSong(album.idAlbum, infoSong);
 
-  for (std::map<std::string, std::string>::const_iterator albumArt = album.art.begin();
-                                                          albumArt != album.art.end();
-                                                        ++albumArt)
-    SetArtForItem(album.idAlbum, MediaTypeAlbum, albumArt->first, albumArt->second);
+  for (const auto &albumArt : album.art)
+    SetArtForItem(album.idAlbum, MediaTypeAlbum, albumArt.first, albumArt.second);
 
   CommitTransaction();
   return true;
@@ -574,7 +569,7 @@ bool CMusicDatabase::UpdateAlbum(CAlbum& album, bool OverrideTagData /* = true*/
     DeleteAlbumArtistsByAlbum(album.idAlbum);
     if (album.artistCredits.empty())
       AddAlbumArtist(BLANKARTIST_ID, album.idAlbum, BLANKARTIST_NAME, 0); // Album must have at least one artist so set artist to [Missing]
-    for (VECARTISTCREDITS::iterator artistCredit = album.artistCredits.begin(); artistCredit != album.artistCredits.end(); ++artistCredit)
+    for (auto artistCredit = album.artistCredits.begin(); artistCredit != album.artistCredits.end(); ++artistCredit)
     {
       artistCredit->idArtist = AddArtist(artistCredit->GetArtist(),
         artistCredit->GetMusicBrainzArtistID());
@@ -584,50 +579,50 @@ bool CMusicDatabase::UpdateAlbum(CAlbum& album, bool OverrideTagData /* = true*/
         std::distance(album.artistCredits.begin(), artistCredit));
     }
 
-    for (VECSONGS::iterator song = album.songs.begin(); song != album.songs.end(); ++song)
-    {
-      UpdateSong(song->idSong,
-        song->strTitle,
-        song->strMusicBrainzTrackID,
-        song->strFileName,
-        song->strComment,
-        song->strMood,
-        song->strThumb,
-        song->GetArtistString(),
-        song->genre,
-        song->iTrack,
-        song->iDuration,
-        song->iYear,
-        song->iTimesPlayed,
-        song->iStartOffset,
-        song->iEndOffset,
-        song->lastPlayed,
-        song->rating,
-        song->userrating,
-        song->votes);
+  for (auto &song : album.songs)
+    {
+      UpdateSong(song.idSong,
+        song.strTitle,
+        song.strMusicBrainzTrackID,
+        song.strFileName,
+        song.strComment,
+        song.strMood,
+        song.strThumb,
+        song.GetArtistString(),
+        song.genre,
+        song.iTrack,
+        song.iDuration,
+        song.iYear,
+        song.iTimesPlayed,
+        song.iStartOffset,
+        song.iEndOffset,
+        song.lastPlayed,
+        song.rating,
+        song.userrating,
+        song.votes);
       //Replace song artists and contributors
-      DeleteSongArtistsBySong(song->idSong);
-      if (song->artistCredits.empty())
-        AddSongArtist(BLANKARTIST_ID, song->idSong, ROLE_ARTIST, BLANKARTIST_NAME, 0); // Song must have at least one artist so set artist to [Missing]
-      for (VECARTISTCREDITS::iterator artistCredit = song->artistCredits.begin(); artistCredit != song->artistCredits.end(); ++artistCredit)
+      DeleteSongArtistsBySong(song.idSong);
+      if (song.artistCredits.empty())
+        AddSongArtist(BLANKARTIST_ID, song.idSong, ROLE_ARTIST, BLANKARTIST_NAME, 0); // Song must have at least one artist so set artist to [Missing]
+      for (auto artistCredit = song.artistCredits.begin(); artistCredit != song.artistCredits.end(); ++artistCredit)
       {
         artistCredit->idArtist = AddArtist(artistCredit->GetArtist(),
           artistCredit->GetMusicBrainzArtistID());
         AddSongArtist(artistCredit->idArtist,
-          song->idSong,
+          song.idSong,
           ROLE_ARTIST,
           artistCredit->GetArtist(),
-          std::distance(song->artistCredits.begin(), artistCredit));
+          std::distance(song.artistCredits.begin(), artistCredit));
       }
       // Having added artist credits (maybe with MBID) add the other contributing artists (MBID unknown)
-      AddSongContributors(song->idSong, song->GetContributors());
+      AddSongContributors(song.idSong, song.GetContributors());
 
-      SaveCuesheet(song->strFileName, song->strCueSheet);
+      SaveCuesheet(song.strFileName, song.strCueSheet);
     }
   }
 
-  for (VECSONGS::const_iterator infoSong = album.infoSongs.begin(); infoSong != album.infoSongs.end(); ++infoSong)
-    AddAlbumInfoSong(album.idAlbum, *infoSong);
+  for (const auto &infoSong : album.infoSongs)
+    AddAlbumInfoSong(album.idAlbum, infoSong);
 
   if (!album.art.empty())
     SetArtForItem(album.idAlbum, MediaTypeAlbum, album.art);
@@ -718,11 +713,11 @@ int CMusicDatabase::AddSong(const int idAlbum,
       SetArtForItem(idSong, MediaTypeSong, "thumb", strThumb);
 
     unsigned int index = 0;
-    for (std::vector<std::string>::const_iterator i = genres.begin(); i != genres.end(); ++i)
+    for (const auto &i : genres)
     {
       // index will be wrong for albums, but ordering is not all that relevant
       // for genres anyway
-      int idGenre = AddGenre(*i);
+      int idGenre = AddGenre(i);
       AddSongGenre(idGenre, idSong, index);
       AddAlbumGenre(idGenre, idAlbum, index++);
     }
@@ -1119,9 +1114,8 @@ int CMusicDatabase::AddGenre(const std::string& strGenre1)
 
     if (NULL == m_pDB.get()) return -1;
     if (NULL == m_pDS.get()) return -1;
-    std::map<std::string, int>::const_iterator it;
 
-    it = m_genreCache.find(strGenre);
+    auto it = m_genreCache.find(strGenre);
     if (it != m_genreCache.end())
       return it->second;
 
@@ -1171,10 +1165,9 @@ bool CMusicDatabase::UpdateArtist(const CArtist& artist)
                artist.fanart.m_xml.c_str());
 
   DeleteArtistDiscography(artist.idArtist);
-  std::vector<std::pair<std::string,std::string> >::const_iterator disc;
-  for (disc = artist.discography.begin(); disc != artist.discography.end(); ++disc)
+  for (const auto &disc : artist.discography)
   {
-    AddArtistDiscography(artist.idArtist, disc->first, disc->second);
+    AddArtistDiscography(artist.idArtist, disc.first, disc.second);
   }
 
   return true;
@@ -1492,9 +1485,9 @@ int CMusicDatabase::AddSongContributor(int idSong, const std::string& strRole, c
 
 void CMusicDatabase::AddSongContributors(int idSong, const VECMUSICROLES& contributors)
 {
-  for (VECMUSICROLES::const_iterator credit = contributors.begin(); credit != contributors.end(); ++credit)
+  for (const auto &credit : contributors)
   {
-    AddSongContributor(idSong, credit->GetRoleDesc(), credit->GetArtist());
+    AddSongContributor(idSong, credit.GetRoleDesc(), credit.GetArtist());
   }
 }
 
@@ -1669,12 +1662,12 @@ bool CMusicDatabase::GetArtistsByAlbum(int idAlbum, CFileItem* item)
     std::vector<std::string> musicBrainzID;
     std::vector<std::string> albumartists;
     CVariant artistidObj(CVariant::VariantTypeArray);
-    for (VECARTISTCREDITS::const_iterator artistCredit = artistCredits.begin(); artistCredit != artistCredits.end(); ++artistCredit)
+    for (const auto &artistCredit : artistCredits)
     {
-      artistidObj.push_back(artistCredit->GetArtistId());
-      albumartists.emplace_back(artistCredit->GetArtist());
-      if (!artistCredit->GetMusicBrainzArtistID().empty())
-        musicBrainzID.emplace_back(artistCredit->GetMusicBrainzArtistID());
+      artistidObj.push_back(artistCredit.GetArtistId());
+      albumartists.emplace_back(artistCredit.GetArtist());
+      if (!artistCredit.GetMusicBrainzArtistID().empty())
+        musicBrainzID.emplace_back(artistCredit.GetMusicBrainzArtistID());
     }
     item->GetMusicInfoTag()->SetAlbumArtist(albumartists);
     item->GetMusicInfoTag()->SetMusicBrainzAlbumArtistID(musicBrainzID);
@@ -1877,9 +1870,7 @@ int CMusicDatabase::AddPath(const std::string& strPath1)
     if (NULL == m_pDB.get()) return -1;
     if (NULL == m_pDS.get()) return -1;
 
-    std::map<std::string, int>::const_iterator it;
-
-    it = m_pathCache.find(strPath);
+    auto it = m_pathCache.find(strPath);
     if (it != m_pathCache.end())
       return it->second;
 
@@ -2021,12 +2012,12 @@ void CMusicDatabase::GetFileItemFromArtistCredits(VECARTISTCREDITS& artistCredit
   }
   else
   {
-    for (VECARTISTCREDITS::const_iterator artistCredit = artistCredits.begin(); artistCredit != artistCredits.end(); ++artistCredit)
+    for (const auto &artistCredit : artistCredits)
     {
-      artistidObj.push_back(artistCredit->GetArtistId());
-      songartists.push_back(artistCredit->GetArtist());
-      if (!artistCredit->GetMusicBrainzArtistID().empty())
-        musicBrainzID.push_back(artistCredit->GetMusicBrainzArtistID());
+      artistidObj.push_back(artistCredit.GetArtistId());
+      songartists.push_back(artistCredit.GetArtist());
+      if (!artistCredit.GetMusicBrainzArtistID().empty())
+        musicBrainzID.push_back(artistCredit.GetMusicBrainzArtistID());
     }
   }
   item->GetMusicInfoTag()->SetArtist(songartists); // Also sets ArtistDesc if empty from song.strArtist field
@@ -3386,12 +3377,11 @@ void CMusicDatabase::DeleteCDDBInfo()
     }
 
     std::string strSelectedAlbum = pDlg->GetSelectedFileItem()->GetLabel();
-    std::map<ULONG, std::string>::iterator it;
-    for (it = mapCDDBIds.begin();it != mapCDDBIds.end();++it)
+    for (const auto &i : mapCDDBIds)
     {
-      if (it->second == strSelectedAlbum)
+      if (i.second == strSelectedAlbum)
       {
-        std::string strFile = StringUtils::Format("%x.cddb", (unsigned int) it->first);
+        std::string strFile = StringUtils::Format("%x.cddb", (unsigned int) i.first);
         CFile::Delete(URIUtils::AddFileToFolder(CProfilesManager::GetInstance().GetCDDBFolder(), strFile));
         break;
       }
@@ -3879,9 +3869,9 @@ bool CMusicDatabase::GetArtistsByWhere(const std::string& strBaseDir, const Filt
     // get data from returned rows
     items.Reserve(results.size());
     const dbiplus::query_data &data = m_pDS->get_result_set().records;
-    for (DatabaseResults::const_iterator it = results.begin(); it != results.end(); ++it)
+    for (const auto &i : results)
     {
-      unsigned int targetRow = (unsigned int)it->at(FieldRow).asInteger();
+      unsigned int targetRow = (unsigned int)i.at(FieldRow).asInteger();
       const dbiplus::sql_record* const record = data.at(targetRow);
       
       try
@@ -4043,9 +4033,9 @@ bool CMusicDatabase::GetAlbumsByWhere(const std::string &baseDir, const Filter &
     // get data from returned rows
     items.Reserve(results.size());
     const dbiplus::query_data &data = m_pDS->get_result_set().records;
-    for (DatabaseResults::const_iterator it = results.begin(); it != results.end(); ++it)
+    for (const auto &i : results)
     {
-      unsigned int targetRow = (unsigned int)it->at(FieldRow).asInteger();
+      unsigned int targetRow = (unsigned int)i.at(FieldRow).asInteger();
       const dbiplus::sql_record* const record = data.at(targetRow);
       
       try
@@ -4166,9 +4156,9 @@ bool CMusicDatabase::GetAlbumsByWhere(const std::string &baseDir, const Filter &
     int albumId = -1;
 
     const dbiplus::query_data &data = m_pDS->get_result_set().records;
-    for (DatabaseResults::const_iterator it = results.begin(); it != results.end(); ++it)
+    for (const auto &i : results)
     {
-      unsigned int targetRow = (unsigned int)it->at(FieldRow).asInteger();
+      unsigned int targetRow = (unsigned int)i.at(FieldRow).asInteger();
       const dbiplus::sql_record* const record = data.at(targetRow);
 
       if (albumId != record->at(album_idAlbum).get_asInt())
@@ -4290,9 +4280,9 @@ bool CMusicDatabase::GetSongsFullByWhere(const std::string &baseDir, const Filte
     VECARTISTCREDITS artistCredits;
     const dbiplus::query_data &data = m_pDS->get_result_set().records;
     int count = 0;
-    for (DatabaseResults::const_iterator it = results.begin(); it != results.end(); ++it)
+    for (const auto &i : results)
     {
-      unsigned int targetRow = (unsigned int)it->at(FieldRow).asInteger();
+      unsigned int targetRow = (unsigned int)i.at(FieldRow).asInteger();
       const dbiplus::sql_record* const record = data.at(targetRow);
       
       try
@@ -4427,9 +4417,9 @@ bool CMusicDatabase::GetSongsByWhere(const std::string &baseDir, const Filter &f
     items.Reserve(results.size());
     const dbiplus::query_data &data = m_pDS->get_result_set().records;
     int count = 0;
-    for (DatabaseResults::const_iterator it = results.begin(); it != results.end(); ++it)
+    for (const auto &i : results)
     {
-      unsigned int targetRow = (unsigned int)it->at(FieldRow).asInteger();
+      unsigned int targetRow = (unsigned int)i.at(FieldRow).asInteger();
       const dbiplus::sql_record* const record = data.at(targetRow);
       
       try
@@ -4528,9 +4518,8 @@ void CMusicDatabase::UpdateTables(int version)
       }
       m_pDS->close();
 
-      for (std::vector<std::string>::const_iterator it = contentPaths.begin(); it != contentPaths.end(); ++it)
+      for (const auto &originalPath : contentPaths)
       {
-        std::string originalPath = *it;
         std::string path = CLegacyPathTranslation::TranslateMusicDbPath(originalPath);
         m_pDS->exec(PrepareSQL("UPDATE content SET strPath='%s' WHERE strPath='%s'", path.c_str(), originalPath.c_str()));
       }
@@ -5423,8 +5412,8 @@ bool CMusicDatabase::RemoveSongsFromPath(const std::string &path1, MAPSONGS& son
       m_pDS->close();
 
       //! @todo move this below the m_pDS->exec block, once UPnP doesn't rely on this anymore
-      for (MAPSONGS::iterator songit = songs.begin(); songit != songs.end(); ++songit)
-        AnnounceRemove(MediaTypeSong, songit->second.idSong);
+      for (const auto &song : songs)
+        AnnounceRemove(MediaTypeSong, song.second.idSong);
 
       // and delete all songs, and anything linked to them
       sql = "delete from song where idSong in (" + StringUtils::Join(songIds, ",") + ")";
@@ -5839,12 +5828,12 @@ void CMusicDatabase::ExportToXML(const std::string &xmlFile, bool singleFile, bo
       TiXmlElement xmlMainElement("musicdb");
       pMain = xmlDoc.InsertEndChild(xmlMainElement);
     }
-    for (std::vector<int>::iterator albumId = albumIds.begin(); albumId != albumIds.end(); ++albumId)
+    for (const auto &albumId : albumIds)
     {
       CAlbum album;
-      GetAlbum(*albumId, album);
+      GetAlbum(albumId, album);
       std::string strPath;
-      GetAlbumPath(*albumId, strPath);
+      GetAlbumPath(albumId, strPath);
       album.Save(pMain, "album", strPath);
       if (!singleFile)
       {
@@ -5904,10 +5893,10 @@ void CMusicDatabase::ExportToXML(const std::string &xmlFile, bool singleFile, bo
     }
     m_pDS->close();
 
-    for (std::vector<int>::iterator artistId = artistIds.begin(); artistId != artistIds.end(); ++artistId)
+    for (const auto &artistId : artistIds)
     {
       CArtist artist;
-      GetArtist(*artistId, artist);
+      GetArtist(artistId, artist);
       std::string strPath;
       GetArtistPath(artist.idArtist,strPath);
       artist.Save(pMain, "artist", strPath);
@@ -5916,8 +5905,8 @@ void CMusicDatabase::ExportToXML(const std::string &xmlFile, bool singleFile, bo
       if (GetArtForItem(artist.idArtist, MediaTypeArtist, artwork) && singleFile)
       { // append to the XML
         TiXmlElement additionalNode("art");
-        for (std::map<std::string, std::string>::const_iterator i = artwork.begin(); i != artwork.end(); ++i)
-          XMLUtils::SetString(&additionalNode, i->first.c_str(), i->second);
+        for (const auto &i : artwork)
+          XMLUtils::SetString(&additionalNode, i.first.c_str(), i.second);
         pMain->LastChild()->InsertEndChild(additionalNode);
       }
       if (!singleFile)
@@ -6162,8 +6151,8 @@ void CMusicDatabase::SetPropertiesForFileItem(CFileItem& item)
 
 void CMusicDatabase::SetArtForItem(int mediaId, const std::string &mediaType, const std::map<std::string, std::string> &art)
 {
-  for (std::map<std::string, std::string>::const_iterator i = art.begin(); i != art.end(); ++i)
-    SetArtForItem(mediaId, mediaType, i->first, i->second);
+  for (const auto &i : art)
+    SetArtForItem(mediaId, mediaType, i.first, i.second);
 }
 
 void CMusicDatabase::SetArtForItem(int mediaId, const std::string &mediaType, const std::string &artType, const std::string &url)
@@ -6284,11 +6273,10 @@ bool CMusicDatabase::GetFilter(CDbUrl &musicUrl, Filter &filter, SortDescription
 
   std::string type = musicUrl.GetType();
   const CUrlOptions::UrlOptions& options = musicUrl.GetOptions();
-  CUrlOptions::UrlOptions::const_iterator option;
 
   //Process role options, common to artist and album type filtering
   int idRole = 1; // Default restrict song_artist to "artists" only, no other roles.
-  option = options.find("roleid");
+  auto option = options.find("roleid");
   if (option != options.end())
     idRole = (int)option->second.asInteger();
   else
diff --git a/xbmc/music/MusicDbUrl.h b/xbmc/music/MusicDbUrl.h
index 12444f0..6b2e486 100644
--- a/xbmc/music/MusicDbUrl.h
+++ b/xbmc/music/MusicDbUrl.h
@@ -32,6 +32,6 @@ public:
   virtual ~CMusicDbUrl();
 
 protected:
-  virtual bool parse();
-  virtual bool validateOption(const std::string &key, const CVariant &value);
+  bool parse() override;
+  bool validateOption(const std::string &key, const CVariant &value) override;
 };
diff --git a/xbmc/music/dialogs/CMakeLists.txt b/xbmc/music/dialogs/CMakeLists.txt
index 0c4bbb9..5149f96 100644
--- a/xbmc/music/dialogs/CMakeLists.txt
+++ b/xbmc/music/dialogs/CMakeLists.txt
@@ -9,4 +9,3 @@ set(HEADERS GUIDialogMusicInfo.h
             GUIDialogVisualisationPresetList.h)
 
 core_add_library(music_dialogs)
-add_dependencies(music_dialogs libcpluff)
diff --git a/xbmc/music/infoscanner/CMakeLists.txt b/xbmc/music/infoscanner/CMakeLists.txt
index ad3686a..b8c24a0 100644
--- a/xbmc/music/infoscanner/CMakeLists.txt
+++ b/xbmc/music/infoscanner/CMakeLists.txt
@@ -9,4 +9,3 @@ set(HEADERS MusicAlbumInfo.h
             MusicInfoScraper.h)
 
 core_add_library(music_infoscanner)
-add_dependencies(music_infoscanner libcpluff)
diff --git a/xbmc/music/tags/CMakeLists.txt b/xbmc/music/tags/CMakeLists.txt
index 286aa35..bbd3462 100644
--- a/xbmc/music/tags/CMakeLists.txt
+++ b/xbmc/music/tags/CMakeLists.txt
@@ -20,9 +20,3 @@ set(HEADERS ImusicInfoTagLoader.h
             TagLoaderTagLib.h)
 
 core_add_library(music_tags)
-
-add_dependencies(music_tags libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(music_tags ffmpeg)
-endif()
diff --git a/xbmc/music/windows/CMakeLists.txt b/xbmc/music/windows/CMakeLists.txt
index 57c08bf..031d735 100644
--- a/xbmc/music/windows/CMakeLists.txt
+++ b/xbmc/music/windows/CMakeLists.txt
@@ -13,8 +13,3 @@ set(HEADERS GUIWindowMusicBase.h
             MusicFileItemListModifier.h)
 
 core_add_library(music_windows)
-add_dependencies(music_windows libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(music_windows ffmpeg)
-endif()
diff --git a/xbmc/music/windows/GUIWindowMusicPlaylist.cpp b/xbmc/music/windows/GUIWindowMusicPlaylist.cpp
index c846e66..1016a3a 100644
--- a/xbmc/music/windows/GUIWindowMusicPlaylist.cpp
+++ b/xbmc/music/windows/GUIWindowMusicPlaylist.cpp
@@ -108,7 +108,7 @@ bool CGUIWindowMusicPlayList::OnMessage(CGUIMessage& message)
   case GUI_MSG_WINDOW_INIT:
     {
       // Setup item cache for tagloader
-      m_musicInfoLoader.UseCacheOnHD("special://temp/MusicPlaylist.fi");
+      m_musicInfoLoader.UseCacheOnHD("special://temp/archive_cache/MusicPlaylist.fi");
 
       m_vecItems->SetPath("playlistmusic://");
 
diff --git a/xbmc/network/CMakeLists.txt b/xbmc/network/CMakeLists.txt
index b9d7445..9927e2f 100644
--- a/xbmc/network/CMakeLists.txt
+++ b/xbmc/network/CMakeLists.txt
@@ -45,8 +45,3 @@ if(SHAIRPLAY_FOUND)
 endif()
 
 core_add_library(network)
-add_dependencies(network libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(network ffmpeg)
-endif()
diff --git a/xbmc/network/EventServer.cpp b/xbmc/network/EventServer.cpp
index ce20970..12c3e77 100644
--- a/xbmc/network/EventServer.cpp
+++ b/xbmc/network/EventServer.cpp
@@ -153,14 +153,10 @@ void CEventServer::Process()
 
 void CEventServer::Run()
 {
-  CAddress any_addr;
   CSocketListener listener;
   int packetSize = 0;
 
-  if (!CSettings::GetInstance().GetBool(CSettings::SETTING_SERVICES_ESALLINTERFACES))
-    any_addr.SetAddress("127.0.0.1");  // only listen on localhost
-
-  CLog::Log(LOGNOTICE, "ES: Starting UDP Event server on %s:%d", any_addr.Address(), m_iPort);
+  CLog::Log(LOGNOTICE, "ES: Starting UDP Event server on port %d", m_iPort);
 
   Cleanup();
 
@@ -186,7 +182,7 @@ void CEventServer::Run()
     CLog::Log(LOGERROR, "ES: Invalid port range specified %d, defaulting to 10", port_range);
     port_range = 10;
   }
-  if (!m_pSocket->Bind(any_addr, m_iPort, port_range))
+  if (!m_pSocket->Bind(!CSettings::GetInstance().GetBool(CSettings::SETTING_SERVICES_ESALLINTERFACES), m_iPort, port_range))
   {
     CLog::Log(LOGERROR, "ES: Could not listen on port %d", m_iPort);
     return;
diff --git a/xbmc/network/EventServer.h b/xbmc/network/EventServer.h
index 97869ec..72129bf 100644
--- a/xbmc/network/EventServer.h
+++ b/xbmc/network/EventServer.h
@@ -26,6 +26,7 @@
 #include "threads/CriticalSection.h"
 #include "threads/SingleLock.h"
 
+#include <atomic>
 #include <map>
 #include <queue>
 #include <vector>
@@ -82,7 +83,7 @@ namespace EVENTSERVER
     int              m_iListenTimeout;
     int              m_iMaxClients;
     unsigned char*   m_pPacketBuffer;
-    bool             m_bRunning;
+    std::atomic<bool>  m_bRunning;
     CCriticalSection m_critSection;
     bool             m_bRefreshSettings;
   };
diff --git a/xbmc/network/Network.cpp b/xbmc/network/Network.cpp
index 5247036..25645f6 100644
--- a/xbmc/network/Network.cpp
+++ b/xbmc/network/Network.cpp
@@ -28,7 +28,7 @@
 #include "utils/log.h"
 #ifdef TARGET_WINDOWS
 #include "utils/SystemInfo.h"
-#include "win32/WIN32Util.h"
+#include "platform/win32/WIN32Util.h"
 #include "utils/CharsetConverter.h"
 #endif
 #include "utils/StringUtils.h"
diff --git a/xbmc/network/Socket.cpp b/xbmc/network/Socket.cpp
index 85b5638..3a0c1c5 100644
--- a/xbmc/network/Socket.cpp
+++ b/xbmc/network/Socket.cpp
@@ -38,13 +38,58 @@ using namespace SOCKETS;
 /* CPosixUDPSocket                                                    */
 /**********************************************************************/
 
-bool CPosixUDPSocket::Bind(CAddress& addr, int port, int range)
+bool CPosixUDPSocket::Bind(bool localOnly, int port, int range)
 {
   // close any existing sockets
   Close();
 
-  // create the socket
-  m_iSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+  // If we can, create a socket that works with IPv6 and IPv4.
+  // If not, try an IPv4-only socket (we don't want to end up
+  // with an IPv6-only socket).
+  if (!localOnly) // Only bind loopback to ipv4. TODO : Implement dual bindinds.
+  {
+    m_iSock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+    if (m_iSock != INVALID_SOCKET)
+    {
+#ifdef WINSOCK_VERSION
+      const char zero = 0;
+#else
+      int zero = 0;
+#endif
+      if (setsockopt(m_iSock, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(&zero)) == -1)
+      {
+        close(m_iSock);
+        m_iSock = INVALID_SOCKET;
+      }
+      else
+      {
+        m_addr = CAddress("::");
+
+        SOCKET testSocket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+        setsockopt(testSocket, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(&zero));
+        // Try to bind a socket to validate ipv6 status
+        for (m_iPort = port; m_iPort <= port + range; ++m_iPort)
+        {
+          m_addr.saddr.saddr6.sin6_port = htons(port);
+          if (bind(testSocket, (struct sockaddr*)&m_addr.saddr, m_addr.size) >= 0)
+          {
+            closesocket(testSocket);
+            m_ipv6Socket = true;
+            break;
+          }
+        }
+        if (!m_ipv6Socket)
+        {
+          CLog::Log(LOGWARNING, "UDP: Unable to bind to advertised ipv6, fallback to ipv4");
+          close(m_iSock);
+          m_iSock = INVALID_SOCKET;
+        }
+      }
+    }
+  }
+
+  if (m_iSock == INVALID_SOCKET)
+    m_iSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 
   if (m_iSock == INVALID_SOCKET)
   {
@@ -52,7 +97,7 @@ bool CPosixUDPSocket::Bind(CAddress& addr, int port, int range)
     int ierr = WSAGetLastError();
     CLog::Log(LOGERROR, "UDP: Could not create socket %d", ierr);
     // hack for broken third party libs
-    if(ierr == WSANOTINITIALISED)
+    if (ierr == WSANOTINITIALISED)
     {
       WSADATA wd;
       if (WSAStartup(MAKEWORD(2,2), &wd) != 0)
@@ -77,24 +122,38 @@ bool CPosixUDPSocket::Bind(CAddress& addr, int port, int range)
     CLog::Log(LOGWARNING, "UDP: %s", strerror(errno));
   }
 
-  // set the port
-  m_addr = addr;
-  m_iPort = port;
-  m_addr.saddr.sin_port = htons(port);
+  // bind to any address or localhost
+  if (m_ipv6Socket)
+  {
+    if (localOnly)
+      m_addr = CAddress("::1");
+    else
+      m_addr = CAddress("::");
+  }
+  else
+  {
+    if (localOnly)
+      m_addr = CAddress("127.0.0.1");
+    else
+      m_addr = CAddress("0.0.0.0");
+  }
 
   // bind the socket ( try from port to port+range )
-  while (m_iPort <= port + range)
+  for (m_iPort = port; m_iPort <= port + range; ++m_iPort)
   {
-    if (bind(m_iSock, (struct sockaddr*)&m_addr.saddr, sizeof(m_addr.saddr)) != 0)
+    if (m_ipv6Socket)
+      m_addr.saddr.saddr6.sin6_port = htons(port);
+    else
+      m_addr.saddr.saddr4.sin_port = htons(port);
+
+    if (bind(m_iSock, (struct sockaddr*)&m_addr.saddr, m_addr.size) != 0)
     {
-      CLog::Log(LOGWARNING, "UDP: Error binding socket on port %d", m_iPort);
+      CLog::Log(LOGWARNING, "UDP: Error binding socket on port %d (ipv6 : %s)", m_iPort, m_ipv6Socket ? "true" : "false" );
       CLog::Log(LOGWARNING, "UDP: %s", strerror(errno));
-      m_iPort++;
-      m_addr.saddr.sin_port = htons(m_iPort);
     }
     else
     {
-      CLog::Log(LOGNOTICE, "UDP: Listening on port %d", m_iPort);
+      CLog::Log(LOGNOTICE, "UDP: Listening on port %d (ipv6 : %s)", m_iPort, m_ipv6Socket ? "true" : "false");
       SetBound();
       SetReady();
       break;
@@ -125,6 +184,8 @@ void CPosixUDPSocket::Close()
 
 int CPosixUDPSocket::Read(CAddress& addr, const int buffersize, void *buffer)
 {
+  if (m_ipv6Socket)
+    addr.SetAddress("::");
   return (int)recvfrom(m_iSock, (char*)buffer, (size_t)buffersize, 0,
                        (struct sockaddr*)&addr.saddr, &addr.size);
 }
@@ -133,8 +194,7 @@ int CPosixUDPSocket::SendTo(const CAddress& addr, const int buffersize,
                           const void *buffer)
 {
   return (int)sendto(m_iSock, (const char *)buffer, (size_t)buffersize, 0,
-                     (const struct sockaddr*)&addr.saddr,
-                     sizeof(addr.saddr));
+                     (const struct sockaddr*)&addr.saddr, addr.size);
 }
 
 /**********************************************************************/
diff --git a/xbmc/network/Socket.h b/xbmc/network/Socket.h
index 20088c9..e5d3c92 100644
--- a/xbmc/network/Socket.h
+++ b/xbmc/network/Socket.h
@@ -51,16 +51,21 @@ namespace SOCKETS
   class CAddress
   {
   public:
-    sockaddr_in saddr;
+    union
+    {
+      sockaddr_in saddr4;
+      sockaddr_in6 saddr6;
+      sockaddr saddr_generic;
+    } saddr;
     socklen_t   size;
 
   public:
     CAddress()
     {
       memset(&saddr, 0, sizeof(saddr));
-      saddr.sin_family = AF_INET;
-      saddr.sin_addr.s_addr = htonl(INADDR_ANY);
-      size = sizeof(saddr);
+      saddr.saddr4.sin_family = AF_INET;
+      saddr.saddr4.sin_addr.s_addr = htonl(INADDR_ANY);
+      size = sizeof(saddr.saddr4);
     }
 
     CAddress(const char *address)
@@ -70,21 +75,56 @@ namespace SOCKETS
 
     void SetAddress(const char *address)
     {
+      in6_addr addr6;
       memset(&saddr, 0, sizeof(saddr));
-      saddr.sin_family = AF_INET;
-      saddr.sin_addr.s_addr = inet_addr(address);
-      size = sizeof(saddr);
+      if (inet_pton(AF_INET6, address, &addr6) == 1)
+      {
+        saddr.saddr6.sin6_family = AF_INET6;
+        saddr.saddr6.sin6_addr = addr6;
+        size = sizeof(saddr.saddr6);
+      }
+      else
+      {
+        saddr.saddr4.sin_family = AF_INET;
+        saddr.saddr4.sin_addr.s_addr = inet_addr(address);
+        size = sizeof(saddr.saddr4);
+      }
     }
 
     // returns statically alloced buffer, do not free
-    char *Address()
+    const char *Address()
     {
-      return inet_ntoa(saddr.sin_addr);
+      if (saddr.saddr_generic.sa_family == AF_INET6)
+      {
+        static char buf[INET6_ADDRSTRLEN];
+        return inet_ntop(AF_INET6, &saddr.saddr6.sin6_addr, buf, size);
+      }
+      else
+        return inet_ntoa(saddr.saddr4.sin_addr);
     }
 
     unsigned long ULong()
     {
-      return (unsigned long)saddr.sin_addr.s_addr;
+      if (saddr.saddr_generic.sa_family == AF_INET6)
+      {
+        // IPv4 coercion (see http://home.samfundet.no/~sesse/ipv6-porting.pdf).
+        // We hash the entire IPv6 address because XBMC might conceivably need to
+        // distinguish between different hosts in the same subnet.
+        // This hash function (djbhash) is not too strong, but good enough.
+        uint32_t hash = 5381;
+        for (int i = 0; i < 16; ++i)
+        {
+          hash = hash * 33 + saddr.saddr6.sin6_addr.s6_addr[i];
+        }
+        // Move into 224.0.0.0/3. As a special safeguard, make sure we don't
+        // end up with the the special broadcast address 255.255.255.255.
+        hash |= 0xe0000000u;
+        if (hash == 0xffffffffu)
+          hash = 0xfffffffeu;
+        return (unsigned long)htonl(hash);
+      }
+      else 
+        return (unsigned long)saddr.saddr4.sin_addr.s_addr;
     }
   };
 
@@ -104,7 +144,7 @@ namespace SOCKETS
     virtual ~CBaseSocket() { Close(); }
 
     // socket functions
-    virtual bool Bind(CAddress& addr, int port, int range=0) = 0;
+    virtual bool Bind(bool localOnly, int port, int range=0) = 0;
     virtual bool Connect() = 0;
     virtual void Close() {};
 
@@ -157,9 +197,10 @@ namespace SOCKETS
     CPosixUDPSocket()
       {
         m_iSock = INVALID_SOCKET;
+        m_ipv6Socket = false;
       }
 
-    bool Bind(CAddress& addr, int port, int range=0);
+    bool Bind(bool localOnly, int port, int range=0);
     bool Connect() { return false; }
     bool Listen(int timeout);
     int  SendTo(const CAddress& addr, const int datasize, const void* data);
@@ -175,6 +216,9 @@ namespace SOCKETS
   protected:
     SOCKET   m_iSock;
     CAddress m_addr;
+
+  private:
+    bool m_ipv6Socket;
   };
 
   /**********************************************************************/
diff --git a/xbmc/network/cddb.cpp b/xbmc/network/cddb.cpp
index 3878bfc..4267697 100644
--- a/xbmc/network/cddb.cpp
+++ b/xbmc/network/cddb.cpp
@@ -219,8 +219,8 @@ bool Xcddb::queryCDinfo(CCdInfo* pInfo, int inexact_list_select)
 
   //##########################################################
   // Read the data from cddb
-  Recv(false); //erstmal den Müll abholen
-  if ( !Send(read_buffer.c_str()) )
+  Recv(false); // Clear pending data on our connection
+  if (!Send(read_buffer.c_str()))
   {
     CLog::Log(LOGERROR, "Xcddb::queryCDinfo_inexaxt_list_select Error sending \"%s\"", read_buffer.c_str());
     CLog::Log(LOGERROR, "Xcddb::queryCDinfo_inexaxt_list_select pInfo == NULL");
diff --git a/xbmc/network/httprequesthandler/CMakeLists.txt b/xbmc/network/httprequesthandler/CMakeLists.txt
index 885bf96..0ac98d3 100644
--- a/xbmc/network/httprequesthandler/CMakeLists.txt
+++ b/xbmc/network/httprequesthandler/CMakeLists.txt
@@ -21,4 +21,3 @@ set(HEADERS HTTPFileHandler.h
             IHTTPRequestHandler.h)
 
 core_add_library(network_httprequesthandlers)
-add_dependencies(network_httprequesthandlers libcpluff)
diff --git a/xbmc/network/mdns/ZeroconfBrowserMDNS.cpp b/xbmc/network/mdns/ZeroconfBrowserMDNS.cpp
index 51b9c37..ef8f7dc 100644
--- a/xbmc/network/mdns/ZeroconfBrowserMDNS.cpp
+++ b/xbmc/network/mdns/ZeroconfBrowserMDNS.cpp
@@ -32,7 +32,7 @@
 #include "utils/log.h"
 
 #if defined(TARGET_WINDOWS)
-#include "win32/WIN32Util.h"
+#include "platform/win32/WIN32Util.h"
 #endif //TARGET_WINDOWS
 
 #pragma comment(lib, "dnssd.lib")
diff --git a/xbmc/network/mdns/ZeroconfMDNS.cpp b/xbmc/network/mdns/ZeroconfMDNS.cpp
index 8bfd7df..6ffb7ad 100644
--- a/xbmc/network/mdns/ZeroconfMDNS.cpp
+++ b/xbmc/network/mdns/ZeroconfMDNS.cpp
@@ -28,7 +28,7 @@
 #include "dialogs/GUIDialogKaiToast.h"
 #include "guilib/LocalizeStrings.h"
 #if defined(TARGET_WINDOWS)
-#include "win32/WIN32Util.h"
+#include "platform/win32/WIN32Util.h"
 #endif //TARGET_WINDOWS
 
 #if defined(HAS_MDNS_EMBEDDED)
diff --git a/xbmc/network/test/TestWebServer.cpp b/xbmc/network/test/TestWebServer.cpp
index 09ff413..3a4d9c4 100644
--- a/xbmc/network/test/TestWebServer.cpp
+++ b/xbmc/network/test/TestWebServer.cpp
@@ -485,38 +485,41 @@ TEST_F(TestWebServer, CanGetCachedFileWithOlderIfModifiedSince)
   CheckRangesTestFileResponse(curl);
 }
 
-TEST_F(TestWebServer, CanGetCachedFileWithExactIfModifiedSince)
-{
-  // get the last modified date of the file
-  CDateTime lastModified;
-  ASSERT_TRUE(GetLastModifiedOfTestFile(TEST_FILES_RANGES, lastModified));
-
-  // get the file with the exact If-Modified-Since value
-  std::string result;
-  CCurlFile curl;
-  curl.SetRequestHeader(MHD_HTTP_HEADER_RANGE, "");
-  curl.SetRequestHeader(MHD_HTTP_HEADER_IF_MODIFIED_SINCE, lastModified.GetAsRFC1123DateTime());
-  ASSERT_TRUE(curl.Get(GetUrlOfTestFile(TEST_FILES_RANGES), result));
-  ASSERT_TRUE(result.empty());
-  CheckRangesTestFileResponse(curl, MHD_HTTP_NOT_MODIFIED, true);
-}
-
-TEST_F(TestWebServer, CanGetCachedFileWithNewerIfModifiedSince)
-{
-  // get the last modified date of the file
-  CDateTime lastModified;
-  ASSERT_TRUE(GetLastModifiedOfTestFile(TEST_FILES_RANGES, lastModified));
-  CDateTime lastModifiedNewer = lastModified + CDateTimeSpan(1, 0, 0, 0);
-
-  // get the file with a newer If-Modified-Since value
-  std::string result;
-  CCurlFile curl;
-  curl.SetRequestHeader(MHD_HTTP_HEADER_RANGE, "");
-  curl.SetRequestHeader(MHD_HTTP_HEADER_IF_MODIFIED_SINCE, lastModifiedNewer.GetAsRFC1123DateTime());
-  ASSERT_TRUE(curl.Get(GetUrlOfTestFile(TEST_FILES_RANGES), result));
-  ASSERT_TRUE(result.empty());
-  CheckRangesTestFileResponse(curl, MHD_HTTP_NOT_MODIFIED, true);
-}
+/** @todo Fix these two tests, they keep failing and
+ *  we want to enable the test suite on PR
+ */
+//TEST_F(TestWebServer, CanGetCachedFileWithExactIfModifiedSince)
+//{
+//  // get the last modified date of the file
+//  CDateTime lastModified;
+//  ASSERT_TRUE(GetLastModifiedOfTestFile(TEST_FILES_RANGES, lastModified));
+//
+//  // get the file with the exact If-Modified-Since value
+//  std::string result;
+//  CCurlFile curl;
+//  curl.SetRequestHeader(MHD_HTTP_HEADER_RANGE, "");
+//  curl.SetRequestHeader(MHD_HTTP_HEADER_IF_MODIFIED_SINCE, lastModified.GetAsRFC1123DateTime());
+//  ASSERT_TRUE(curl.Get(GetUrlOfTestFile(TEST_FILES_RANGES), result));
+//  ASSERT_TRUE(result.empty());
+//  CheckRangesTestFileResponse(curl, MHD_HTTP_NOT_MODIFIED, true);
+//}
+//
+//TEST_F(TestWebServer, CanGetCachedFileWithNewerIfModifiedSince)
+//{
+//  // get the last modified date of the file
+//  CDateTime lastModified;
+//  ASSERT_TRUE(GetLastModifiedOfTestFile(TEST_FILES_RANGES, lastModified));
+//  CDateTime lastModifiedNewer = lastModified + CDateTimeSpan(1, 0, 0, 0);
+//
+//  // get the file with a newer If-Modified-Since value
+//  std::string result;
+//  CCurlFile curl;
+//  curl.SetRequestHeader(MHD_HTTP_HEADER_RANGE, "");
+//  curl.SetRequestHeader(MHD_HTTP_HEADER_IF_MODIFIED_SINCE, lastModifiedNewer.GetAsRFC1123DateTime());
+//  ASSERT_TRUE(curl.Get(GetUrlOfTestFile(TEST_FILES_RANGES), result));
+//  ASSERT_TRUE(result.empty());
+//  CheckRangesTestFileResponse(curl, MHD_HTTP_NOT_MODIFIED, true);
+//}
 
 TEST_F(TestWebServer, CanGetCachedFileWithNewerIfModifiedSinceForcingNoCache)
 {
diff --git a/xbmc/network/upnp/CMakeLists.txt b/xbmc/network/upnp/CMakeLists.txt
index 4dc9432..e558cfc 100644
--- a/xbmc/network/upnp/CMakeLists.txt
+++ b/xbmc/network/upnp/CMakeLists.txt
@@ -12,17 +12,7 @@ set(HEADERS UPnP.h
             UPnPServer.h
             UPnPSettings.h)
 
-include_directories(${CORE_SOURCE_DIR}/lib/libUPnP
-                    ${CORE_SOURCE_DIR}/lib/libUPnP/Platinum/Source/Core
-                    ${CORE_SOURCE_DIR}/lib/libUPnP/Platinum/Source/Platinum
-                    ${CORE_SOURCE_DIR}/lib/libUPnP/Platinum/Source/Devices/MediaConnect
-                    ${CORE_SOURCE_DIR}/lib/libUPnP/Platinum/Source/Devices/MediaRenderer
-                    ${CORE_SOURCE_DIR}/lib/libUPnP/Platinum/Source/Devices/MediaServer
-                    ${CORE_SOURCE_DIR}/lib/libUPnP/Platinum/Source/Extras
-                    ${CORE_SOURCE_DIR}/lib/libUPnP/Neptune/Source/System/Posix
-                    ${CORE_SOURCE_DIR}/lib/libUPnP/Neptune/Source/Core)
-
-add_definitions(-DNPT_CONFIG_ENABLE_LOGGING)
-
 core_add_library(network_upnp)
-add_dependencies(network_upnp libcpluff)
+if(ENABLE_STATIC_LIBS)
+  target_link_libraries(network_upnp PRIVATE upnp)
+endif()
diff --git a/xbmc/network/upnp/UPnP.cpp b/xbmc/network/upnp/UPnP.cpp
index a8d5f00..2370ee6 100644
--- a/xbmc/network/upnp/UPnP.cpp
+++ b/xbmc/network/upnp/UPnP.cpp
@@ -421,7 +421,7 @@ CUPnP::CUPnP() :
     m_CtrlPointHolder(new CCtrlPointReferenceHolder())
 {
     NPT_LogManager::GetDefault().Configure("plist:.level=FINE;.handlers=CustomHandler;");
-    NPT_LogHandler::Create("CustomHandler", "xbmc", m_LogHandler);
+    NPT_LogHandler::Create("xbmc", "CustomHandler", m_LogHandler);
     m_LogHandler->SetCustomHandlerFunction(&UPnPLogger);
 
     // initialize upnp context
diff --git a/xbmc/network/upnp/UPnPInternal.cpp b/xbmc/network/upnp/UPnPInternal.cpp
index 8732c58..5264faa 100644
--- a/xbmc/network/upnp/UPnPInternal.cpp
+++ b/xbmc/network/upnp/UPnPInternal.cpp
@@ -315,7 +315,7 @@ PopulateObjectFromTag(CVideoInfoTag&         tag,
     object.m_XbmcInfo.date_added = tag.m_dateAdded.GetAsW3CDate().c_str();
     object.m_XbmcInfo.rating = tag.GetRating().rating;
     object.m_XbmcInfo.votes = tag.GetRating().votes;
-    object.m_XbmcInfo.unique_identifier = tag.m_strIMDBNumber.c_str();
+    object.m_XbmcInfo.unique_identifier = tag.GetUniqueID().c_str();
     for (const auto& country : tag.m_country)
       object.m_XbmcInfo.countries.Add(country.c_str());
     object.m_XbmcInfo.user_rating = tag.m_iUserRating;
@@ -820,7 +820,7 @@ PopulateTagFromObject(CVideoInfoTag&         tag,
 
     tag.m_dateAdded.SetFromW3CDate((const char*)object.m_XbmcInfo.date_added);
     tag.AddRating(object.m_XbmcInfo.rating, object.m_XbmcInfo.votes);
-    tag.m_strIMDBNumber = object.m_XbmcInfo.unique_identifier;
+    tag.SetUniqueID(object.m_XbmcInfo.unique_identifier.GetChars());
     for (unsigned int index = 0; index < object.m_XbmcInfo.countries.GetItemCount(); index++)
       tag.m_country.push_back(object.m_XbmcInfo.countries.GetItem(index)->GetChars());
     tag.m_iUserRating = object.m_XbmcInfo.user_rating;
diff --git a/xbmc/network/upnp/UPnPPlayer.cpp b/xbmc/network/upnp/UPnPPlayer.cpp
index e0adea4..23eff07 100644
--- a/xbmc/network/upnp/UPnPPlayer.cpp
+++ b/xbmc/network/upnp/UPnPPlayer.cpp
@@ -602,4 +602,17 @@ bool CUPnPPlayer::OnAction(const CAction &action)
   }
 }
 
+void CUPnPPlayer::SetSpeed(int iSpeed)
+{
+
+}
+
+int CUPnPPlayer::GetSpeed()
+{
+  if (IsPaused())
+    return 0;
+  else
+    return 1;
+}
+
 } /* namespace UPNP */
diff --git a/xbmc/network/upnp/UPnPPlayer.h b/xbmc/network/upnp/UPnPPlayer.h
index b1af08a..373c894 100644
--- a/xbmc/network/upnp/UPnPPlayer.h
+++ b/xbmc/network/upnp/UPnPPlayer.h
@@ -44,8 +44,7 @@ public:
   virtual bool QueueNextFile(const CFileItem &file);
   virtual bool CloseFile(bool reopen = false);
   virtual bool IsPlaying() const;
-  virtual void Pause();
-  virtual bool IsPaused() const;
+  virtual void Pause() override;
   virtual bool HasVideo() const { return false; }
   virtual bool HasAudio() const { return false; }
   virtual void Seek(bool bPlus, bool bLargeStep, bool bChapterOverride);
@@ -66,7 +65,8 @@ public:
   virtual void SeekTime(__int64 iTime = 0);
   virtual int64_t GetTime();
   virtual int64_t GetTotalTime();
-  virtual void ToFFRW(int iSpeed = 0){};
+  virtual void SetSpeed(int iSpeed = 0) override;
+  virtual int GetSpeed() override;
 
   virtual bool SkipNext(){return false;}
   virtual bool IsCaching() const {return false;};
@@ -79,6 +79,8 @@ public:
   int PlayFile(const CFileItem& file, const CPlayerOptions& options, CGUIDialogBusy*& dialog, XbmcThreads::EndTime& timeout);
 
 private:
+  bool IsPaused() const;
+
   PLT_MediaController*   m_control;
   CUPnPPlayerController* m_delegate;
   std::string            m_current_uri;
diff --git a/xbmc/network/windows/NetworkWin32.cpp b/xbmc/network/windows/NetworkWin32.cpp
index 7ae8cff..f2e6fc7 100644
--- a/xbmc/network/windows/NetworkWin32.cpp
+++ b/xbmc/network/windows/NetworkWin32.cpp
@@ -27,7 +27,7 @@
 #include "threads/SingleLock.h"
 #include "utils/CharsetConverter.h"
 #include "utils/StringUtils.h"
-#include "win32/WIN32Util.h"
+#include "platform/win32/WIN32Util.h"
 
 // undefine if you want to build without the wlan stuff
 // might be needed for VS2003
diff --git a/xbmc/peripherals/CMakeLists.txt b/xbmc/peripherals/CMakeLists.txt
index 1892fc4..7fe53c0 100644
--- a/xbmc/peripherals/CMakeLists.txt
+++ b/xbmc/peripherals/CMakeLists.txt
@@ -8,4 +8,3 @@ set(HEADERS EventScanRate.h
             PeripheralTypes.h)
 
 core_add_library(peripherals)
-add_dependencies(peripherals libcpluff)
diff --git a/xbmc/peripherals/addons/CMakeLists.txt b/xbmc/peripherals/addons/CMakeLists.txt
index d4592b5..9f31978 100644
--- a/xbmc/peripherals/addons/CMakeLists.txt
+++ b/xbmc/peripherals/addons/CMakeLists.txt
@@ -11,4 +11,3 @@ set(HEADERS AddonButtonMap.h
             PeripheralAddonTranslator.h)
 
 core_add_library(peripherals_addons)
-add_dependencies(peripherals_addons libcpluff)
diff --git a/xbmc/peripherals/bus/linux/CMakeLists.txt b/xbmc/peripherals/bus/linux/CMakeLists.txt
index 42a16a1..f9ab837 100644
--- a/xbmc/peripherals/bus/linux/CMakeLists.txt
+++ b/xbmc/peripherals/bus/linux/CMakeLists.txt
@@ -8,5 +8,4 @@ endif()
 
 if(SOURCES)
   core_add_library(peripherals_bus_linux)
-  set_target_properties(peripherals_bus_linux PROPERTIES LINKER_LANGUAGE CXX)
 endif()
diff --git a/xbmc/peripherals/bus/virtual/CMakeLists.txt b/xbmc/peripherals/bus/virtual/CMakeLists.txt
index 6c1e227..edff06b 100644
--- a/xbmc/peripherals/bus/virtual/CMakeLists.txt
+++ b/xbmc/peripherals/bus/virtual/CMakeLists.txt
@@ -8,4 +8,3 @@ if(CEC_FOUND)
 endif()
 
 core_add_library(peripheral_bus_virtual)
-add_dependencies(peripheral_bus_virtual libcpluff)
diff --git a/xbmc/peripherals/bus/virtual/PeripheralBusAddon.cpp b/xbmc/peripherals/bus/virtual/PeripheralBusAddon.cpp
index d6138e0..e563222 100644
--- a/xbmc/peripherals/bus/virtual/PeripheralBusAddon.cpp
+++ b/xbmc/peripherals/bus/virtual/PeripheralBusAddon.cpp
@@ -37,14 +37,14 @@ CPeripheralBusAddon::CPeripheralBusAddon(CPeripherals *manager) :
     CPeripheralBus("PeripBusAddon", manager, PERIPHERAL_BUS_ADDON)
 {
   CAddonMgr::GetInstance().RegisterAddonMgrCallback(ADDON_PERIPHERALDLL, this);
-  CAddonMgr::GetInstance().RegisterObserver(this);
+  CAddonMgr::GetInstance().Events().Subscribe(this, &CPeripheralBusAddon::OnEvent);
 
   UpdateAddons();
 }
 
 CPeripheralBusAddon::~CPeripheralBusAddon()
 {
-  CAddonMgr::GetInstance().UnregisterObserver(this);
+  CAddonMgr::GetInstance().Events().Unsubscribe(this);
   CAddonMgr::GetInstance().UnregisterAddonMgrCallback(ADDON_PERIPHERALDLL);
 
   // stop everything before destroying any (loaded) addons
@@ -293,9 +293,9 @@ bool CPeripheralBusAddon::RequestRemoval(ADDON::AddonPtr addon)
   return true;
 }
 
-void CPeripheralBusAddon::Notify(const Observable &obs, const ObservableMessage msg)
+void CPeripheralBusAddon::OnEvent(const ADDON::AddonEvent& event)
 {
-  if (msg == ObservableMessageAddons)
+  if (typeid(event) == typeid(AddonEvents::InstalledChanged))
     UpdateAddons();
 }
 
diff --git a/xbmc/peripherals/bus/virtual/PeripheralBusAddon.h b/xbmc/peripherals/bus/virtual/PeripheralBusAddon.h
index 2f09b5a..626938d 100644
--- a/xbmc/peripherals/bus/virtual/PeripheralBusAddon.h
+++ b/xbmc/peripherals/bus/virtual/PeripheralBusAddon.h
@@ -34,8 +34,7 @@
 namespace PERIPHERALS
 {
   class CPeripheralBusAddon : public CPeripheralBus,
-                              public ADDON::IAddonMgrCallback,
-                              public Observer
+                              public ADDON::IAddonMgrCallback
   {
   public:
     CPeripheralBusAddon(CPeripherals *manager);
@@ -76,9 +75,6 @@ namespace PERIPHERALS
     bool RequestRestart(ADDON::AddonPtr addon, bool datachanged) override;
     bool RequestRemoval(ADDON::AddonPtr addon) override;
 
-    // implementation of Observer
-    void Notify(const Observable &obs, const ObservableMessage msg) override;
-
     bool SplitLocation(const std::string& strLocation, PeripheralAddonPtr& addon, unsigned int& peripheralIndex) const;
 
   protected:
@@ -89,6 +85,7 @@ namespace PERIPHERALS
 
   private:
     void UpdateAddons(void);
+    void OnEvent(const ADDON::AddonEvent& event);
 
     PeripheralAddonVector m_addons;
     PeripheralAddonVector m_failedAddons;
diff --git a/xbmc/peripherals/devices/CMakeLists.txt b/xbmc/peripherals/devices/CMakeLists.txt
index 0bc17a2..8590854 100644
--- a/xbmc/peripherals/devices/CMakeLists.txt
+++ b/xbmc/peripherals/devices/CMakeLists.txt
@@ -24,4 +24,3 @@ if(CEC_FOUND)
 endif()
 
 core_add_library(peripherals_devices)
-add_dependencies(peripherals_devices libcpluff)
diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
index f784bde..e6bcbce 100644
--- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
+++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp
@@ -175,7 +175,7 @@ void CPeripheralCecAdapter::Announce(AnnouncementFlag flag, const char *sender,
   else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverActivated") && m_bIsReady)
   {
     // Don't put devices to standby if application is currently playing
-    if ((!g_application.m_pPlayer->IsPlaying() && !g_application.m_pPlayer->IsPaused()) && m_configuration.bPowerOffScreensaver == 1)
+    if (!g_application.m_pPlayer->IsPlaying() && m_configuration.bPowerOffScreensaver == 1)
     {
       // only power off when we're the active source
       if (m_cecAdapter->IsLibCECActiveSource())
@@ -594,6 +594,8 @@ void CPeripheralCecAdapter::SetMenuLanguage(const char *strLanguage)
   else if (!strcmp(strLanguage, "srp"))
     strGuiLanguage = "sr_rs at latin";
   else if (!strcmp(strLanguage, "slo"))
+    strGuiLanguage = "sk_sk";
+  else if (!strcmp(strLanguage, "slv"))
     strGuiLanguage = "sl_si";
   else if (!strcmp(strLanguage, "spa"))
     strGuiLanguage = "es_es";
@@ -1183,7 +1185,8 @@ void CPeripheralCecAdapter::CecSourceActivated(void *cbParam, const CEC::cec_log
         // pause/resume player
         CApplicationMessenger::GetInstance().SendMsg(TMSG_MEDIA_PAUSE);
     }
-    else if (adapter->GetSettingInt("pause_or_stop_playback_on_deactivate") == LOCALISED_ID_STOP)
+    else if (bPlayingAndDeactivated
+      && adapter->GetSettingInt("pause_or_stop_playback_on_deactivate") == LOCALISED_ID_STOP)
     {
       if (pSlideShow)
         pSlideShow->OnAction(CAction(ACTION_STOP));
diff --git a/xbmc/pictures/CMakeLists.txt b/xbmc/pictures/CMakeLists.txt
index cc4f90b..56b7c05 100644
--- a/xbmc/pictures/CMakeLists.txt
+++ b/xbmc/pictures/CMakeLists.txt
@@ -22,8 +22,3 @@ set(HEADERS DllLibExif.h
             SlideShowPicture.h)
 
 core_add_library(pictures)
-add_dependencies(pictures libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(pictures ffmpeg)
-endif()
diff --git a/xbmc/pictures/GUIWindowSlideShow.cpp b/xbmc/pictures/GUIWindowSlideShow.cpp
index e62255d..c847bb4 100644
--- a/xbmc/pictures/GUIWindowSlideShow.cpp
+++ b/xbmc/pictures/GUIWindowSlideShow.cpp
@@ -39,6 +39,7 @@
 #include "guilib/Texture.h"
 #include "windowing/WindowingFactory.h"
 #include "guilib/LocalizeStrings.h"
+#include "TextureDatabase.h"
 #include "threads/SingleLock.h"
 #include "utils/log.h"
 #include "utils/Variant.h"
@@ -56,7 +57,7 @@ using namespace KODI::MESSAGING;
 #define MAX_ZOOM_FACTOR                     10
 #define MAX_PICTURE_SIZE             2048*2048
 
-#define IMMEDIATE_TRANSISTION_TIME          20
+#define IMMEDIATE_TRANSITION_TIME          1
 
 #define PICTURE_MOVE_AMOUNT              0.02f
 #define PICTURE_MOVE_AMOUNT_ANALOG       0.01f
@@ -66,12 +67,8 @@ using namespace KODI::MESSAGING;
 
 #define ROTATION_SNAP_RANGE              10.0f
 
-#define FPS                                 25
-
-#define BAR_IMAGE                            1
 #define LABEL_ROW1                          10
 #define LABEL_ROW2                          11
-#define LABEL_ROW2_EXTRA                    12
 #define CONTROL_PAUSE                       13
 
 static float zoomamount[10] = { 1.0f, 1.2f, 1.5f, 2.0f, 2.8f, 4.0f, 6.0f, 9.0f, 13.5f, 20.0f };
@@ -151,22 +148,15 @@ void CBackgroundPicLoader::LoadPic(int iPic, int iSlideNumber, const std::string
 }
 
 CGUIWindowSlideShow::CGUIWindowSlideShow(void)
-    : CGUIWindow(WINDOW_SLIDESHOW, "SlideShow.xml")
+    : CGUIDialog(WINDOW_SLIDESHOW, "SlideShow.xml")
 {
   m_pBackgroundLoader = NULL;
-  m_slides = new CFileItemList;
   m_Resolution = RES_INVALID;
   m_loadType = KEEP_IN_MEMORY;
   m_bLoadNextPic = false;
   Reset();
 }
 
-CGUIWindowSlideShow::~CGUIWindowSlideShow(void)
-{
-  Reset();
-  delete m_slides;
-}
-
 void CGUIWindowSlideShow::AnnouncePlayerPlay(const CFileItemPtr& item)
 {
   CVariant param;
@@ -191,14 +181,6 @@ void CGUIWindowSlideShow::AnnouncePlayerStop(const CFileItemPtr& item)
   ANNOUNCEMENT::CAnnouncementManager::GetInstance().Announce(ANNOUNCEMENT::Player, "xbmc", "OnStop", item, param);
 }
 
-void CGUIWindowSlideShow::AnnouncePlaylistRemove(int pos)
-{
-  CVariant data;
-  data["playlistid"] = PLAYLIST_PICTURE;
-  data["position"] = pos;
-  ANNOUNCEMENT::CAnnouncementManager::GetInstance().Announce(ANNOUNCEMENT::Playlist, "xbmc", "OnRemove", data);
-}
-
 void CGUIWindowSlideShow::AnnouncePlaylistClear()
 {
   CVariant data;
@@ -252,8 +234,7 @@ void CGUIWindowSlideShow::Reset()
   m_iCurrentPic = 0;
   m_iDirection = 1;
   m_iLastFailedNextSlide = -1;
-  CSingleLock lock(m_slideSection);
-  m_slides->Clear();
+  m_slides.clear();
   AnnouncePlaylistClear();
   m_Resolution = g_graphicsContext.GetVideoResolution();
 }
@@ -287,7 +268,7 @@ void CGUIWindowSlideShow::OnDeinitWindow(int nextWindowID)
   }
   g_infoManager.ResetCurrentSlide();
 
-  CGUIWindow::OnDeinitWindow(nextWindowID);
+  CGUIDialog::OnDeinitWindow(nextWindowID);
 }
 
 void CGUIWindowSlideShow::Add(const CFileItem *picture)
@@ -302,14 +283,14 @@ void CGUIWindowSlideShow::Add(const CFileItem *picture)
       // then it is a picture and force tag generation
       item->GetPictureInfoTag();
   }
-  AnnouncePlaylistAdd(item, m_slides->Size());
+  AnnouncePlaylistAdd(item, m_slides.size());
 
-  m_slides->Add(item);
+  m_slides.emplace_back(std::move(item));
 }
 
 void CGUIWindowSlideShow::ShowNext()
 {
-  if (m_slides->Size() == 1)
+  if (m_slides.size() == 1)
     return;
 
   m_iDirection   = 1;
@@ -322,7 +303,7 @@ void CGUIWindowSlideShow::ShowNext()
 
 void CGUIWindowSlideShow::ShowPrevious()
 {
-  if (m_slides->Size() == 1)
+  if (m_slides.size() == 1)
     return;
 
   m_iDirection   = -1;
@@ -336,9 +317,9 @@ void CGUIWindowSlideShow::ShowPrevious()
 
 void CGUIWindowSlideShow::Select(const std::string& strPicture)
 {
-  for (int i = 0; i < m_slides->Size(); ++i)
+  for (int i = 0; i < m_slides.size(); ++i)
   {
-    const CFileItemPtr item = m_slides->Get(i);
+    const CFileItemPtr item = m_slides.at(i);
     if (item->GetPath() == strPicture)
     {
       m_iDirection = 1;
@@ -358,21 +339,16 @@ void CGUIWindowSlideShow::Select(const std::string& strPicture)
   }
 }
 
-const CFileItemList &CGUIWindowSlideShow::GetSlideShowContents()
-{
-  return *m_slides;
-}
-
 void CGUIWindowSlideShow::GetSlideShowContents(CFileItemList &list)
 {
-  for (int index = 0; index < m_slides->Size(); index++)
-    list.Add(CFileItemPtr(new CFileItem(*m_slides->Get(index))));
+  for (int index = 0; index < m_slides.size(); index++)
+    list.Add(CFileItemPtr(new CFileItem(*m_slides.at(index))));
 }
 
-const CFileItemPtr CGUIWindowSlideShow::GetCurrentSlide()
+std::shared_ptr<const CFileItem> CGUIWindowSlideShow::GetCurrentSlide()
 {
-  if (m_iCurrentSlide >= 0 && m_iCurrentSlide < m_slides->Size())
-    return m_slides->Get(m_iCurrentSlide);
+  if (m_iCurrentSlide >= 0 && m_iCurrentSlide < m_slides.size())
+    return m_slides.at(m_iCurrentSlide);
   return CFileItemPtr();
 }
 
@@ -385,8 +361,8 @@ void CGUIWindowSlideShow::StartSlideShow()
 {
   m_bSlideShow = true;
   m_iDirection = 1;
-  if (m_slides->Size())
-    AnnouncePlayerPlay(m_slides->Get(m_iCurrentSlide));
+  if (m_slides.size())
+    AnnouncePlayerPlay(m_slides.at(m_iCurrentSlide));
 }
 
 void CGUIWindowSlideShow::SetDirection(int direction)
@@ -407,16 +383,16 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
   // (unless we are the screensaver!)
   if (m_bSlideShow && !m_bPause && !g_application.IsInScreenSaver())
     g_application.ResetScreenSaver();
-  int iSlides = m_slides->Size();
+  int iSlides = m_slides.size();
   if (!iSlides) return ;
 
   // if we haven't processed yet, we should mark the whole screen
   if (!HasProcessed())
     regions.push_back(CRect(0.0f, 0.0f, (float)g_graphicsContext.GetWidth(), (float)g_graphicsContext.GetHeight()));
 
-  if (m_iCurrentSlide < 0 || m_iCurrentSlide >= m_slides->Size())
+  if (m_iCurrentSlide < 0 || m_iCurrentSlide >= m_slides.size())
     m_iCurrentSlide = 0;
-  if (m_iNextSlide < 0 || m_iNextSlide >= m_slides->Size())
+  if (m_iNextSlide < 0 || m_iNextSlide >= m_slides.size())
     m_iNextSlide = GetNextSlide();
 
   // Create our background loader if necessary
@@ -432,7 +408,7 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
   }
 
   bool bSlideShow = m_bSlideShow && !m_bPause && !m_bPlayingVideo;
-  if (bSlideShow && m_slides->Get(m_iCurrentSlide)->HasProperty("unplayable"))
+  if (bSlideShow && m_slides.at(m_iCurrentSlide)->HasProperty("unplayable"))
   {
     m_iNextSlide    = GetNextSlide();
     if (m_iCurrentSlide == m_iNextSlide)
@@ -454,14 +430,14 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
       }
       else
       {
-        CLog::Log(LOGERROR, "Error loading the current image %d: %s", m_iCurrentSlide, m_slides->Get(m_iCurrentSlide)->GetPath().c_str());
-        if (!m_slides->Get(m_iCurrentPic)->IsVideo())
+        CLog::Log(LOGERROR, "Error loading the current image %d: %s", m_iCurrentSlide, m_slides.at(m_iCurrentSlide)->GetPath().c_str());
+        if (!m_slides.at(m_iCurrentPic)->IsVideo())
         {
           // try next if we are in slideshow
-          CLog::Log(LOGINFO, "set image %s unplayable", m_slides->Get(m_iCurrentSlide)->GetPath().c_str());
-          m_slides->Get(m_iCurrentSlide)->SetProperty("unplayable", true);
+          CLog::Log(LOGINFO, "set image %s unplayable", m_slides.at(m_iCurrentSlide)->GetPath().c_str());
+          m_slides.at(m_iCurrentSlide)->SetProperty("unplayable", true);
         }
-        if (m_bLoadNextPic || (bSlideShow && !m_bPause && !m_slides->Get(m_iCurrentPic)->IsVideo()))
+        if (m_bLoadNextPic || (bSlideShow && !m_bPause && !m_slides.at(m_iCurrentPic)->IsVideo()))
         {
           // change to next item, wait loading.
           m_iCurrentSlide = m_iNextSlide;
@@ -473,12 +449,12 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
     }
     else if (m_iNextSlide == m_pBackgroundLoader->SlideNumber())
     {
-      CLog::Log(LOGERROR, "Error loading the next image %d: %s", m_iNextSlide, m_slides->Get(m_iNextSlide)->GetPath().c_str());
+      CLog::Log(LOGERROR, "Error loading the next image %d: %s", m_iNextSlide, m_slides.at(m_iNextSlide)->GetPath().c_str());
       // load next image failed, then skip to load next of next if next is not video.
-      if (!m_slides->Get(m_iNextSlide)->IsVideo())
+      if (!m_slides.at(m_iNextSlide)->IsVideo())
       {
-        CLog::Log(LOGINFO, "set image %s unplayable", m_slides->Get(m_iNextSlide)->GetPath().c_str());
-        m_slides->Get(m_iNextSlide)->SetProperty("unplayable", true);
+        CLog::Log(LOGINFO, "set image %s unplayable", m_slides.at(m_iNextSlide)->GetPath().c_str());
+        m_slides.at(m_iNextSlide)->SetProperty("unplayable", true);
         // change to next item, wait loading.
         m_iNextSlide = GetNextSlide();
       }
@@ -490,7 +466,7 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
     }
     else
     { // Non-current and non-next slide, just ignore error.
-      CLog::Log(LOGERROR, "Error loading the non-current non-next image %d/%d: %s", m_iNextSlide, m_pBackgroundLoader->SlideNumber(), m_slides->Get(m_iNextSlide)->GetPath().c_str());
+      CLog::Log(LOGERROR, "Error loading the non-current non-next image %d/%d: %s", m_iNextSlide, m_pBackgroundLoader->SlideNumber(), m_slides.at(m_iNextSlide)->GetPath().c_str());
       m_bErrorMessage = false;
     }
   }
@@ -501,11 +477,9 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
     return;
   }
 
-  CSingleLock lock(m_slideSection);
-
   if (!m_Image[m_iCurrentPic].IsLoaded() && !m_pBackgroundLoader->IsLoading())
   { // load first image
-    CFileItemPtr item = m_slides->Get(m_iCurrentSlide);
+    CFileItemPtr item = m_slides.at(m_iCurrentSlide);
     std::string picturePath = GetPicturePath(item.get());
     if (!picturePath.empty())
     {
@@ -533,7 +507,7 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
   if (m_iNextSlide != m_iCurrentSlide && m_Image[m_iCurrentPic].IsLoaded() && !m_Image[1 - m_iCurrentPic].IsLoaded() && !m_pBackgroundLoader->IsLoading() && m_iLastFailedNextSlide != m_iNextSlide)
   { // load the next image
     m_iLastFailedNextSlide = -1;
-    CFileItemPtr item = m_slides->Get(m_iNextSlide);
+    CFileItemPtr item = m_slides.at(m_iNextSlide);
     std::string picturePath = GetPicturePath(item.get());
     if (!picturePath.empty() && (!item->IsVideo() || !m_bSlideShow || m_bPause))
     {
@@ -550,7 +524,7 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
     }
   }
 
-  if (m_slides->Get(m_iCurrentSlide)->IsVideo() && bSlideShow)
+  if (m_slides.at(m_iCurrentSlide)->IsVideo() && bSlideShow)
   {
     if (!PlayVideo())
       return;
@@ -568,10 +542,10 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
   // Check if we should be transistioning immediately
   if (m_bLoadNextPic && m_Image[m_iCurrentPic].IsLoaded())
   {
-    CLog::Log(LOGDEBUG, "Starting immediate transistion due to user wanting slide %s", m_slides->Get(m_iNextSlide)->GetPath().c_str());
+    CLog::Log(LOGDEBUG, "Starting immediate transistion due to user wanting slide %s", m_slides.at(m_iNextSlide)->GetPath().c_str());
     if (m_Image[m_iCurrentPic].StartTransistion())
     {
-      m_Image[m_iCurrentPic].SetTransistionTime(1, IMMEDIATE_TRANSISTION_TIME); // only 20 frames for the transistion
+      m_Image[m_iCurrentPic].SetTransistionTime(1, IMMEDIATE_TRANSITION_TIME);
       m_bLoadNextPic = false;
     }
   }
@@ -579,7 +553,7 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
   // render the next image
   if (m_Image[m_iCurrentPic].DrawNextImage())
   {
-    if (m_bSlideShow && !m_bPause && m_slides->Get(m_iNextSlide)->IsVideo())
+    if (m_bSlideShow && !m_bPause && m_slides.at(m_iNextSlide)->IsVideo())
     {
       // do not show thumb of video when playing slideshow
     }
@@ -594,7 +568,7 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
       }
       // set the appropriate transistion time
       m_Image[1 - m_iCurrentPic].SetTransistionTime(0, m_Image[m_iCurrentPic].GetTransistionTime(1));
-      m_Image[1 - m_iCurrentPic].Pause(!m_bSlideShow || m_bPause || m_slides->Get(m_iNextSlide)->IsVideo());
+      m_Image[1 - m_iCurrentPic].Pause(!m_bSlideShow || m_bPause || m_slides.at(m_iNextSlide)->IsVideo());
       m_Image[1 - m_iCurrentPic].Process(currentTime, regions);
     }
     else // next pic isn't loaded.  We should hang around if it is in progress
@@ -612,10 +586,10 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
   {
     m_bLoadNextPic = false;
     if (m_Image[m_iCurrentPic].IsFinished())
-      CLog::Log(LOGDEBUG, "Image %s is finished rendering, switching to %s", m_slides->Get(m_iCurrentSlide)->GetPath().c_str(), m_slides->Get(m_iNextSlide)->GetPath().c_str());
+      CLog::Log(LOGDEBUG, "Image %s is finished rendering, switching to %s", m_slides.at(m_iCurrentSlide)->GetPath().c_str(), m_slides.at(m_iNextSlide)->GetPath().c_str());
     else
       // what if it's bg loading?
-      CLog::Log(LOGDEBUG, "Image %s is not loaded, switching to %s", m_slides->Get(m_iCurrentSlide)->GetPath().c_str(), m_slides->Get(m_iNextSlide)->GetPath().c_str());
+      CLog::Log(LOGDEBUG, "Image %s is not loaded, switching to %s", m_slides.at(m_iCurrentSlide)->GetPath().c_str(), m_slides.at(m_iNextSlide)->GetPath().c_str());
 
     if (m_Image[m_iCurrentPic].IsFinished() && m_iCurrentSlide == m_iNextSlide && m_Image[m_iCurrentPic].SlideNumber() == m_iNextSlide)
       m_Image[m_iCurrentPic].Reset(GetDisplayEffect(m_iCurrentSlide));
@@ -639,7 +613,7 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
       m_iCurrentSlide = m_iNextSlide;
       m_iNextSlide    = GetNextSlide();
     }
-    AnnouncePlayerPlay(m_slides->Get(m_iCurrentSlide));
+    AnnouncePlayerPlay(m_slides.at(m_iCurrentSlide));
 
     m_iZoomFactor = 1;
     m_fZoom = 1.0f;
@@ -647,14 +621,17 @@ void CGUIWindowSlideShow::Process(unsigned int currentTime, CDirtyRegionList &re
   }
 
   if (m_Image[m_iCurrentPic].IsLoaded())
-    g_infoManager.SetCurrentSlide(*m_slides->Get(m_iCurrentSlide));
+    g_infoManager.SetCurrentSlide(*m_slides.at(m_iCurrentSlide));
 
   RenderPause();
   CGUIWindow::Process(currentTime, regions);
+  m_renderRegion.SetRect(0, 0, (float)g_graphicsContext.GetWidth(), (float)g_graphicsContext.GetHeight());
 }
 
 void CGUIWindowSlideShow::Render()
 {
+  g_graphicsContext.Clear(0xff000000);
+
   if (m_Image[m_iCurrentPic].IsLoaded())
     m_Image[m_iCurrentPic].Render();
 
@@ -667,15 +644,15 @@ void CGUIWindowSlideShow::Render()
 
 int CGUIWindowSlideShow::GetNextSlide()
 {
-  if (m_slides->Size() <= 1)
+  if (m_slides.size() <= 1)
     return m_iCurrentSlide;
   int step = m_iDirection >= 0 ? 1 : -1;
-  int nextSlide = (m_iCurrentSlide + step + m_slides->Size()) % m_slides->Size();
+  int nextSlide = (m_iCurrentSlide + step + m_slides.size()) % m_slides.size();
   while (nextSlide != m_iCurrentSlide)
   {
-    if (!m_slides->Get(nextSlide)->HasProperty("unplayable"))
+    if (!m_slides.at(nextSlide)->HasProperty("unplayable"))
       return nextSlide;
-    nextSlide = (nextSlide + step + m_slides->Size()) % m_slides->Size();
+    nextSlide = (nextSlide + step + m_slides.size()) % m_slides.size();
   }
   return m_iCurrentSlide;
 }
@@ -760,7 +737,7 @@ bool CGUIWindowSlideShow::OnAction(const CAction &action)
 {
   switch (action.GetID())
   {
-  case ACTION_SHOW_CODEC:
+  case ACTION_SHOW_INFO:
     {
       CGUIDialogPictureInfo *pictureInfo = (CGUIDialogPictureInfo *)g_windowManager.GetWindow(WINDOW_DIALOG_PICTURE_INFO);
       if (pictureInfo)
@@ -770,13 +747,10 @@ bool CGUIWindowSlideShow::OnAction(const CAction &action)
       }
     }
     break;
-
-  case ACTION_PREVIOUS_MENU:
-  case ACTION_NAV_BACK:
   case ACTION_STOP:
-    if (m_slides->Size())
-      AnnouncePlayerStop(m_slides->Get(m_iCurrentSlide));
-    g_windowManager.PreviousWindow();
+    if (m_slides.size())
+      AnnouncePlayerStop(m_slides.at(m_iCurrentSlide));
+    Close();
     break;
 
   case ACTION_NEXT_PICTURE:
@@ -811,9 +785,9 @@ bool CGUIWindowSlideShow::OnAction(const CAction &action)
 
   case ACTION_PAUSE:
   case ACTION_PLAYER_PLAY:
-    if (m_slides->Size() == 0)
+    if (m_slides.size() == 0)
       break;
-    if (m_slides->Get(m_iCurrentSlide)->IsVideo())
+    if (m_slides.at(m_iCurrentSlide)->IsVideo())
     {
       if (!m_bPlayingVideo)
       {
@@ -836,12 +810,12 @@ bool CGUIWindowSlideShow::OnAction(const CAction &action)
         if (m_Image[m_iCurrentPic].DisplayEffectNeedChange(effect))
           m_Image[m_iCurrentPic].Reset(effect);
       }
-      AnnouncePlayerPlay(m_slides->Get(m_iCurrentSlide));
+      AnnouncePlayerPlay(m_slides.at(m_iCurrentSlide));
     }
     else if (action.GetID() == ACTION_PAUSE)
     {
       m_bPause = true;
-      AnnouncePlayerPause(m_slides->Get(m_iCurrentSlide));
+      AnnouncePlayerPause(m_slides.at(m_iCurrentSlide));
     }
     break;
 
@@ -900,7 +874,7 @@ bool CGUIWindowSlideShow::OnAction(const CAction &action)
     break;
 
   default:
-    return CGUIWindow::OnAction(action);
+    return CGUIDialog::OnAction(action);
   }
   return true;
 }
@@ -934,10 +908,10 @@ bool CGUIWindowSlideShow::OnMessage(CGUIMessage& message)
       else
         m_Resolution = g_graphicsContext.GetVideoResolution();
 
-      CGUIWindow::OnMessage(message);
+      CGUIDialog::OnMessage(message);
 
       // turn off slideshow if we only have 1 image
-      if (m_slides->Size() <= 1)
+      if (m_slides.size() <= 1)
         m_bSlideShow = false;
 
       return true;
@@ -1016,7 +990,7 @@ bool CGUIWindowSlideShow::OnMessage(CGUIMessage& message)
             m_iCurrentPic = 1 - m_iCurrentPic;
             m_iCurrentSlide = m_iNextSlide;
             m_iNextSlide    = GetNextSlide();
-            AnnouncePlayerPlay(m_slides->Get(m_iCurrentSlide));
+            AnnouncePlayerPlay(m_slides.at(m_iCurrentSlide));
             m_iZoomFactor = 1;
             m_fZoom = 1.0f;
             m_fRotate = 0.0f;
@@ -1025,7 +999,7 @@ bool CGUIWindowSlideShow::OnMessage(CGUIMessage& message)
       }
       break;
   }
-  return CGUIWindow::OnMessage(message);
+  return CGUIDialog::OnMessage(message);
 }
 
 void CGUIWindowSlideShow::RenderPause()
@@ -1038,16 +1012,6 @@ void CGUIWindowSlideShow::RenderPause()
   {
     SET_CONTROL_HIDDEN(CONTROL_PAUSE);
   }
-  /*
-   static DWORD dwCounter=0;
-   dwCounter++;
-   if (dwCounter > 25)
-   {
-    dwCounter=0;
-   }
-   if (!m_bPause) return;
-   if (dwCounter <13) return;*/
-
 }
 
 void CGUIWindowSlideShow::Rotate(float fAngle, bool immediate /* = false */)
@@ -1108,7 +1072,7 @@ void CGUIWindowSlideShow::Move(float fX, float fY)
 
 bool CGUIWindowSlideShow::PlayVideo()
 {
-  CFileItemPtr item = m_slides->Get(m_iCurrentSlide);
+  CFileItemPtr item = m_slides.at(m_iCurrentSlide);
   if (!item || !item->IsVideo())
     return false;
   CLog::Log(LOGDEBUG, "Playing current video slide %s", item->GetPath().c_str());
@@ -1129,7 +1093,7 @@ bool CGUIWindowSlideShow::PlayVideo()
 
 CSlideShowPic::DISPLAY_EFFECT CGUIWindowSlideShow::GetDisplayEffect(int iSlideNumber) const
 {
-  if (m_bSlideShow && !m_bPause && !m_slides->Get(iSlideNumber)->IsVideo())
+  if (m_bSlideShow && !m_bPause && !m_slides.at(iSlideNumber)->IsVideo())
     return CSettings::GetInstance().GetBool(CSettings::SETTING_SLIDESHOW_DISPLAYEFFECTS) ? CSlideShowPic::EFFECT_RANDOM : CSlideShowPic::EFFECT_NONE;
   else
     return CSlideShowPic::EFFECT_NO_TIMEOUT;
@@ -1140,20 +1104,19 @@ void CGUIWindowSlideShow::OnLoadPic(int iPic, int iSlideNumber, const std::strin
   if (pTexture)
   {
     // set the pic's texture + size etc.
-    CSingleLock lock(m_slideSection);
-    if (iSlideNumber >= m_slides->Size() || GetPicturePath(m_slides->Get(iSlideNumber).get()) != strFileName)
+    if (iSlideNumber >= m_slides.size() || GetPicturePath(m_slides.at(iSlideNumber).get()) != strFileName)
     { // throw this away - we must have cleared the slideshow while we were still loading
       delete pTexture;
       return;
     }
-    CLog::Log(LOGDEBUG, "Finished background loading slot %d, %d: %s", iPic, iSlideNumber, m_slides->Get(iSlideNumber)->GetPath().c_str());
+    CLog::Log(LOGDEBUG, "Finished background loading slot %d, %d: %s", iPic, iSlideNumber, m_slides.at(iSlideNumber)->GetPath().c_str());
     m_Image[iPic].SetTexture(iSlideNumber, pTexture, GetDisplayEffect(iSlideNumber));
     m_Image[iPic].SetOriginalSize(pTexture->GetOriginalWidth(), pTexture->GetOriginalHeight(), bFullSize);
     
     m_Image[iPic].m_bIsComic = false;
-    if (URIUtils::IsInRAR(m_slides->Get(m_iCurrentSlide)->GetPath()) || URIUtils::IsInZIP(m_slides->Get(m_iCurrentSlide)->GetPath())) // move to top for cbr/cbz
+    if (URIUtils::IsInRAR(m_slides.at(m_iCurrentSlide)->GetPath()) || URIUtils::IsInZIP(m_slides.at(m_iCurrentSlide)->GetPath())) // move to top for cbr/cbz
     {
-      CURL url(m_slides->Get(m_iCurrentSlide)->GetPath());
+      CURL url(m_slides.at(m_iCurrentSlide)->GetPath());
       std::string strHostName = url.GetHostName();
       if (URIUtils::HasExtension(strHostName, ".cbr|.cbz"))
       {
@@ -1162,9 +1125,9 @@ void CGUIWindowSlideShow::OnLoadPic(int iPic, int iSlideNumber, const std::strin
       }
     }
   }
-  else if (iSlideNumber >= m_slides->Size() || GetPicturePath(m_slides->Get(iSlideNumber).get()) != strFileName)
+  else if (iSlideNumber >= m_slides.size() || GetPicturePath(m_slides.at(iSlideNumber).get()) != strFileName)
   { // Failed to load image. and not match values calling LoadPic, then something is changed, ignore.
-    CLog::Log(LOGDEBUG, "CGUIWindowSlideShow::OnLoadPic(%d, %d, %s) on failure not match current state (cur %d, next %d, curpic %d, pic[0, 1].slidenumber=%d, %d, %s)", iPic, iSlideNumber, strFileName.c_str(), m_iCurrentSlide, m_iNextSlide, m_iCurrentPic, m_Image[0].SlideNumber(), m_Image[1].SlideNumber(), iSlideNumber >= m_slides->Size() ? "" : m_slides->Get(iSlideNumber)->GetPath().c_str());
+    CLog::Log(LOGDEBUG, "CGUIWindowSlideShow::OnLoadPic(%d, %d, %s) on failure not match current state (cur %d, next %d, curpic %d, pic[0, 1].slidenumber=%d, %d, %s)", iPic, iSlideNumber, strFileName.c_str(), m_iCurrentSlide, m_iNextSlide, m_iCurrentPic, m_Image[0].SlideNumber(), m_Image[1].SlideNumber(), iSlideNumber >= m_slides.size() ? "" : m_slides.at(iSlideNumber)->GetPath().c_str());
   }
   else
   { // Failed to load image.  What should be done??
@@ -1176,7 +1139,7 @@ void CGUIWindowSlideShow::OnLoadPic(int iPic, int iSlideNumber, const std::strin
 
 void CGUIWindowSlideShow::Shuffle()
 {
-  m_slides->Randomize();
+  std::random_shuffle(m_slides.begin(), m_slides.end());
   m_iCurrentSlide = 0;
   m_iNextSlide = GetNextSlide();
   m_bShuffled = true;
@@ -1186,7 +1149,7 @@ void CGUIWindowSlideShow::Shuffle()
 
 int CGUIWindowSlideShow::NumSlides() const
 {
-  return m_slides->Size();
+  return m_slides.size();
 }
 
 int CGUIWindowSlideShow::CurrentSlide() const
@@ -1203,7 +1166,6 @@ void CGUIWindowSlideShow::AddFromPath(const std::string &strPath,
   {
     // reset the slideshow
     Reset();
-    m_strExtensions = strExtensions;
     if (bRecursive)
     {
       path_set recursivePaths;
@@ -1316,3 +1278,23 @@ std::string CGUIWindowSlideShow::GetPicturePath(CFileItem *item)
   return picturePath;
 }
 
+
+void CGUIWindowSlideShow::RunSlideShow(std::vector<std::string> paths, int start /* = 0*/)
+{
+  auto dialog = static_cast<CGUIWindowSlideShow*>(g_windowManager.GetWindow(WINDOW_SLIDESHOW));
+  if (dialog)
+  {
+    std::vector<CFileItemPtr> items;
+    for (const auto& path : paths)
+      items.push_back(std::make_shared<CFileItem>(CTextureUtils::GetWrappedImageURL(path), false));
+
+    dialog->Reset();
+    dialog->m_bPause = true;
+    dialog->m_bSlideShow = false;
+    dialog->m_iDirection = 1;
+    dialog->m_iCurrentSlide = start;
+    dialog->m_iNextSlide = (start + 1) % items.size();
+    dialog->m_slides = std::move(items);
+    dialog->Open();
+  }
+}
diff --git a/xbmc/pictures/GUIWindowSlideShow.h b/xbmc/pictures/GUIWindowSlideShow.h
index 8c00b27..4559124 100644
--- a/xbmc/pictures/GUIWindowSlideShow.h
+++ b/xbmc/pictures/GUIWindowSlideShow.h
@@ -21,7 +21,7 @@
  */
 
 #include <set>
-#include "guilib/GUIWindow.h"
+#include "guilib/GUIDialog.h"
 #include "threads/Thread.h"
 #include "threads/CriticalSection.h"
 #include "threads/Event.h"
@@ -59,21 +59,25 @@ private:
   CGUIWindowSlideShow *m_pCallback;
 };
 
-class CGUIWindowSlideShow : public CGUIWindow
+class CGUIWindowSlideShow : public CGUIDialog
 {
 public:
   CGUIWindowSlideShow(void);
-  virtual ~CGUIWindowSlideShow(void);
+  virtual ~CGUIWindowSlideShow() {};
+
+  bool OnMessage(CGUIMessage& message) override;
+  EVENT_RESULT OnMouseEvent(const CPoint &point, const CMouseEvent &event) override;
+  bool OnAction(const CAction &action) override;
+  void Render() override;
+  void Process(unsigned int currentTime, CDirtyRegionList &regions) override;
+  void OnDeinitWindow(int nextWindowID) override;
 
   void Reset();
   void Add(const CFileItem *picture);
   bool IsPlaying() const;
-  void ShowNext();
-  void ShowPrevious();
   void Select(const std::string& strPicture);
-  const CFileItemList &GetSlideShowContents();
   void GetSlideShowContents(CFileItemList &list);
-  const CFileItemPtr GetCurrentSlide();
+  std::shared_ptr<const CFileItem> GetCurrentSlide();
   void RunSlideShow(const std::string &strPath, bool bRecursive = false,
                     bool bRandom = false, bool bNotRandom = false,
                     const std::string &beginSlidePath="", bool startSlideShow = true,
@@ -88,12 +92,6 @@ public:
                    const std::string &strExtensions="");
   void StartSlideShow();
   bool InSlideShow() const;
-  virtual bool OnMessage(CGUIMessage& message);
-  virtual EVENT_RESULT OnMouseEvent(const CPoint &point, const CMouseEvent &event);  
-  virtual bool OnAction(const CAction &action);
-  virtual void Render();
-  virtual void Process(unsigned int currentTime, CDirtyRegionList &regions);
-  virtual void OnDeinitWindow(int nextWindowID);
   void OnLoadPic(int iPic, int iSlideNumber, const std::string &strFileName, CBaseTexture* pTexture, bool bFullSize);
   int NumSlides() const;
   int CurrentSlide() const;
@@ -101,8 +99,14 @@ public:
   bool IsPaused() const { return m_bPause; }
   bool IsShuffled() const { return m_bShuffled; }
   int GetDirection() const { return m_iDirection; }
-  void SetDirection(int direction); // -1: rewind, 1: forward
+
+  static void RunSlideShow(std::vector<std::string> paths, int start=0);
+
 private:
+  void ShowNext();
+  void ShowPrevious();
+  void SetDirection(int direction); // -1: rewind, 1: forward
+
   typedef std::set<std::string> path_set;  // set to track which paths we're adding
   void AddItems(const std::string &strPath, path_set *recursivePaths,
                 SortBy method = SortByLabel,
@@ -123,7 +127,6 @@ private:
   void AnnouncePlayerPlay(const CFileItemPtr& item);
   void AnnouncePlayerPause(const CFileItemPtr& item);
   void AnnouncePlayerStop(const CFileItemPtr& item);
-  void AnnouncePlaylistRemove(int pos);
   void AnnouncePlaylistClear();
   void AnnouncePlaylistAdd(const CFileItemPtr& item, int pos);
   void AnnouncePropertyChanged(const std::string &strProperty, const CVariant &value);
@@ -143,7 +146,7 @@ private:
   bool m_bPlayingVideo;
   bool m_bErrorMessage;
 
-  CFileItemList* m_slides;
+  std::vector<CFileItemPtr> m_slides;
 
   CSlideShowPic m_Image[2];
 
@@ -153,7 +156,5 @@ private:
   int m_iLastFailedNextSlide;
   bool m_bLoadNextPic;
   RESOLUTION m_Resolution;
-  CCriticalSection m_slideSection;
-  std::string m_strExtensions;
   CPoint m_firstGesturePoint;
 };
diff --git a/xbmc/pictures/SlideShowPicture.cpp b/xbmc/pictures/SlideShowPicture.cpp
index 7d77391..f571d04 100644
--- a/xbmc/pictures/SlideShowPicture.cpp
+++ b/xbmc/pictures/SlideShowPicture.cpp
@@ -42,7 +42,7 @@
 
 static float zoomamount[10] = { 1.0f, 1.2f, 1.5f, 2.0f, 2.8f, 4.0f, 6.0f, 9.0f, 13.5f, 20.0f };
 
-CSlideShowPic::CSlideShowPic()
+CSlideShowPic::CSlideShowPic() : m_alpha(0)
 {
   m_pImage = NULL;
   m_bIsLoaded = false;
@@ -75,6 +75,7 @@ void CSlideShowPic::Close()
   m_bDrawNextImage = false;
   m_bTransistionImmediately = false;
   m_bIsDirty = true;
+  m_alpha = 0;
 #ifdef HAS_DX
   SAFE_RELEASE(m_vb);
 #endif
@@ -122,6 +123,18 @@ void CSlideShowPic::SetTexture_Internal(int iSlideNumber, CBaseTexture* pTexture
   // initialize our transistion effect
   m_transistionStart.type = transEffect;
   m_transistionStart.start = 0;
+
+  // initialize our display effect
+  if (dispEffect == EFFECT_RANDOM)
+  {
+    if (((m_fWidth / m_fHeight) > 1.9) || ((m_fHeight / m_fWidth) > 1.9))
+      m_displayEffect = EFFECT_PANORAMA;
+    else
+      m_displayEffect = (DISPLAY_EFFECT)((rand() % (EFFECT_RANDOM - 1)) + 1);
+  }
+  else
+    m_displayEffect = dispEffect;
+
   // the +1's make sure it actually occurs
   float fadeTime = 0.2f;
   if (m_displayEffect != EFFECT_NO_TIMEOUT)
@@ -148,16 +161,6 @@ void CSlideShowPic::SetTexture_Internal(int iSlideNumber, CBaseTexture* pTexture
   m_fZoomAmount = 1;
   m_fZoomLeft = 0;
   m_fZoomTop = 0;
-  // initialize our display effect
-  if (dispEffect == EFFECT_RANDOM)
-  {
-    if (((m_fWidth / m_fHeight) > 1.9) || ((m_fHeight / m_fWidth) > 1.9))
-      m_displayEffect = EFFECT_PANORAMA;
-    else
-      m_displayEffect = (DISPLAY_EFFECT)((rand() % (EFFECT_RANDOM - 1)) + 1);
-  }
-  else
-    m_displayEffect = dispEffect;
   m_fPosX = m_fPosY = 0.0f;
   m_fPosZ = 1.0f;
   m_fVelocityX = m_fVelocityY = m_fVelocityZ = 0.0f;
diff --git a/xbmc/platform/CMakeLists.txt b/xbmc/platform/CMakeLists.txt
index 4ff2d54..679ba11 100644
--- a/xbmc/platform/CMakeLists.txt
+++ b/xbmc/platform/CMakeLists.txt
@@ -6,4 +6,3 @@ set(HEADERS MessagePrinter.h
             XbmcContext.h)
 
 core_add_library(platform_common)
-add_dependencies(platform_common libcpluff)
diff --git a/xbmc/platform/android/activity/AndroidKey.cpp b/xbmc/platform/android/activity/AndroidKey.cpp
index 540da8a..ce91f4a 100644
--- a/xbmc/platform/android/activity/AndroidKey.cpp
+++ b/xbmc/platform/android/activity/AndroidKey.cpp
@@ -128,8 +128,8 @@ static KeyMap keyMap[] = {
   { AKEYCODE_BUTTON_X        , XBMCK_LAST },
   { AKEYCODE_BUTTON_Y        , XBMCK_LAST },
   { AKEYCODE_BUTTON_Z        , XBMCK_LAST },
-  { AKEYCODE_BUTTON_L1       , XBMCK_LAST },
-  { AKEYCODE_BUTTON_R1       , XBMCK_LAST },
+  { AKEYCODE_BUTTON_L1       , XBMCK_PAGEDOWN },
+  { AKEYCODE_BUTTON_R1       , XBMCK_PAGEUP },
   { AKEYCODE_BUTTON_L2       , XBMCK_LAST },
   { AKEYCODE_BUTTON_R2       , XBMCK_LAST },
   { AKEYCODE_BUTTON_THUMBL   , XBMCK_LAST },
diff --git a/xbmc/platform/android/activity/CMakeLists.txt b/xbmc/platform/android/activity/CMakeLists.txt
index 1ad8b0c..11fd016 100644
--- a/xbmc/platform/android/activity/CMakeLists.txt
+++ b/xbmc/platform/android/activity/CMakeLists.txt
@@ -25,7 +25,6 @@ set(HEADERS AndroidExtra.h
             XBMCApp.h)
 
 core_add_library(platform_android_activity)
-add_dependencies(platform_android_activity libcpluff)
-target_include_directories(platform_android_activity
+target_include_directories(${CORE_LIBRARY}
                            PRIVATE ${NDKROOT}/sources/android/native_app_glue
                                    ${NDKROOT}/sources/android/cpufeatures)
diff --git a/xbmc/platform/android/activity/XBMCApp.cpp b/xbmc/platform/android/activity/XBMCApp.cpp
index c042d3b..f889c75 100644
--- a/xbmc/platform/android/activity/XBMCApp.cpp
+++ b/xbmc/platform/android/activity/XBMCApp.cpp
@@ -73,6 +73,7 @@
 #include "platform/android/jni/ContentResolver.h"
 #include "platform/android/jni/MediaStore.h"
 #include "platform/android/jni/Build.h"
+#include "filesystem/SpecialProtocol.h"
 #if defined(HAS_LIBAMCODEC)
 #include "utils/AMLUtils.h"
 #endif
@@ -108,6 +109,7 @@ IInputDeviceEventHandler* CXBMCApp::m_inputDeviceEventHandler = nullptr;
 CCriticalSection CXBMCApp::m_applicationsMutex;
 std::vector<androidPackage> CXBMCApp::m_applications;
 CVideoSyncAndroid* CXBMCApp::m_syncImpl = NULL;
+CEvent CXBMCApp::m_vsyncEvent;
 
 
 CXBMCApp::CXBMCApp(ANativeActivity* nativeActivity)
@@ -167,6 +169,7 @@ void CXBMCApp::onResume()
   CJNIIntentFilter intentFilter;
   intentFilter.addAction("android.intent.action.BATTERY_CHANGED");
   intentFilter.addAction("android.intent.action.SCREEN_ON");
+  intentFilter.addAction("android.intent.action.HEADSET_PLUG");
   registerReceiver(*this, intentFilter);
 
   if (!g_application.IsInScreenSaver())
@@ -559,7 +562,7 @@ std::vector<androidPackage> CXBMCApp::GetApplications()
     CJNIList<CJNIApplicationInfo> packageList = GetPackageManager().getInstalledApplications(CJNIPackageManager::GET_ACTIVITIES);
     int numPackages = packageList.size();
     for (int i = 0; i < numPackages; i++)
-    {            
+    {
       CJNIIntent intent = GetPackageManager().getLaunchIntentForPackage(packageList.get(i).packageName);
       if (!intent && CJNIBuild::SDK_INT >= 21)
         intent = GetPackageManager().getLeanbackLaunchIntentForPackage(packageList.get(i).packageName);
@@ -745,6 +748,11 @@ void CXBMCApp::SetSystemVolume(float percent)
     android_printf("CXBMCApp::SetSystemVolume: Could not get Audio Manager");
 }
 
+void CXBMCApp::InitDirectories()
+{
+  CSpecialProtocol::SetXBMCBinAddonPath(getApplicationInfo().nativeLibraryDir.c_str());
+}
+
 void CXBMCApp::onReceive(CJNIIntent intent)
 {
   std::string action = intent.getAction();
@@ -845,6 +853,13 @@ void CXBMCApp::doFrame(int64_t frameTimeNanos)
 {
   if (m_syncImpl)
     m_syncImpl->FrameCallback(frameTimeNanos);
+
+  m_vsyncEvent.Set();
+}
+
+bool CXBMCApp::WaitVSync(unsigned int milliSeconds)
+{
+  return m_vsyncEvent.WaitMSec(milliSeconds);
 }
 
 void CXBMCApp::SetupEnv()
diff --git a/xbmc/platform/android/activity/XBMCApp.h b/xbmc/platform/android/activity/XBMCApp.h
index 29b7900..ee44234 100644
--- a/xbmc/platform/android/activity/XBMCApp.h
+++ b/xbmc/platform/android/activity/XBMCApp.h
@@ -121,6 +121,7 @@ public:
   static int GetMaxSystemVolume();
   static float GetSystemVolume();
   static void SetSystemVolume(float percent);
+  static void InitDirectories();
 
   static void SetRefreshRate(float rate);
   static int GetDPI();
@@ -145,6 +146,8 @@ public:
   static void InitFrameCallback(CVideoSyncAndroid *syncImpl);
   static void DeinitFrameCallback();
 
+  static bool WaitVSync(unsigned int milliSeconds);
+
   static CXBMCApp* get() { return m_xbmcappinstance; }
 
 protected:
@@ -180,6 +183,7 @@ private:
   static CEvent m_windowCreated;
 
   static CVideoSyncAndroid* m_syncImpl;
+  static CEvent m_vsyncEvent;
 
   void XBMC_Pause(bool pause);
   void XBMC_Stop();
diff --git a/xbmc/platform/android/jni/MediaCodec.cpp b/xbmc/platform/android/jni/MediaCodec.cpp
index 0615862..0c8a73d 100644
--- a/xbmc/platform/android/jni/MediaCodec.cpp
+++ b/xbmc/platform/android/jni/MediaCodec.cpp
@@ -162,16 +162,16 @@ const CJNIMediaFormat CJNIMediaCodec::getOutputFormat()
     "getOutputFormat", "()Landroid/media/MediaFormat;");
 }
 
-std::vector<CJNIByteBuffer> CJNIMediaCodec::getInputBuffers()
+const CJNIByteBuffer CJNIMediaCodec::getInputBuffer(int index)
 {
-  return jcast<CJNIByteBuffers>(call_method<jhobjectArray>(m_object,
-    "getInputBuffers", "()[Ljava/nio/ByteBuffer;"));
+  return call_method<jhobject>(m_object,
+    "getInputBuffer", "(I)Ljava/nio/ByteBuffer;", index);
 }
 
-std::vector<CJNIByteBuffer> CJNIMediaCodec::getOutputBuffers()
+const CJNIByteBuffer CJNIMediaCodec::getOutputBuffer(int index)
 {
-  return jcast<CJNIByteBuffers>(call_method<jhobjectArray>(m_object,
-    "getOutputBuffers", "()[Ljava/nio/ByteBuffer;"));
+  return call_method<jhobject>(m_object,
+    "getOutputBuffer", "(I)Ljava/nio/ByteBuffer;", index);
 }
 
 void CJNIMediaCodec::setVideoScalingMode(int mode)
diff --git a/xbmc/platform/android/jni/MediaCodec.h b/xbmc/platform/android/jni/MediaCodec.h
index a1660ec..560e5b1 100644
--- a/xbmc/platform/android/jni/MediaCodec.h
+++ b/xbmc/platform/android/jni/MediaCodec.h
@@ -48,8 +48,8 @@ public:
   int   dequeueOutputBuffer(const CJNIMediaCodecBufferInfo &info, int64_t timeoutUs);
   void  releaseOutputBuffer(int index, bool render);
   const CJNIMediaFormat getOutputFormat();
-  std::vector<CJNIByteBuffer> getInputBuffers();
-  std::vector<CJNIByteBuffer> getOutputBuffers();
+  const CJNIByteBuffer getInputBuffer(int index);
+  const CJNIByteBuffer getOutputBuffer(int index);
   void  setVideoScalingMode(int mode);
 
   static void  PopulateStaticFields();
diff --git a/xbmc/platform/darwin/CMakeLists.txt b/xbmc/platform/darwin/CMakeLists.txt
index 6f57ec7..ab68426 100644
--- a/xbmc/platform/darwin/CMakeLists.txt
+++ b/xbmc/platform/darwin/CMakeLists.txt
@@ -12,4 +12,3 @@ set(HEADERS AutoPool.h
             OSXGNUReplacements.h)
 
 core_add_library(platform_darwin)
-add_dependencies(platform_darwin libcpluff)
diff --git a/xbmc/platform/darwin/DarwinUtils.mm b/xbmc/platform/darwin/DarwinUtils.mm
index 11be67a..509cce5 100644
--- a/xbmc/platform/darwin/DarwinUtils.mm
+++ b/xbmc/platform/darwin/DarwinUtils.mm
@@ -635,6 +635,7 @@ const std::string& CDarwinUtils::GetManufacturer(void)
 bool CDarwinUtils::IsAliasShortcut(const std::string& path, bool isdirectory)
 {
   bool ret = false;
+
 #if defined(TARGET_DARWIN_OSX)
   CCocoaAutoPool pool;
   
diff --git a/xbmc/platform/darwin/ios-common/CMakeLists.txt b/xbmc/platform/darwin/ios-common/CMakeLists.txt
index a8d6a34..8b78aab 100644
--- a/xbmc/platform/darwin/ios-common/CMakeLists.txt
+++ b/xbmc/platform/darwin/ios-common/CMakeLists.txt
@@ -3,4 +3,3 @@ set(SOURCES AnnounceReceiver.mm)
 set(HEADERS AnnounceReceiver.h)
 
 core_add_library(platform_ios-common)
-add_dependencies(platform_ios-common libcpluff)
diff --git a/xbmc/platform/darwin/ios/CMakeLists.txt b/xbmc/platform/darwin/ios/CMakeLists.txt
index a12116f..368345d 100644
--- a/xbmc/platform/darwin/ios/CMakeLists.txt
+++ b/xbmc/platform/darwin/ios/CMakeLists.txt
@@ -15,4 +15,3 @@ set(HEADERS IOSEAGLView.h
             XBMCDebugHelpers.h)
 
 core_add_library(platform_ios)
-add_dependencies(platform_ios libcpluff)
diff --git a/xbmc/platform/darwin/ios/Info.plist.in b/xbmc/platform/darwin/ios/Info.plist.in
index 6c4443c..557d112 100644
--- a/xbmc/platform/darwin/ios/Info.plist.in
+++ b/xbmc/platform/darwin/ios/Info.plist.in
@@ -165,5 +165,315 @@
 	</array>
 	<key>UIViewControllerBasedStatusBarAppearance</key>
 	<false/>
+  <key>CFBundleURLTypes</key>
+  <array>
+    <dict>
+      <key>CFBundleURLSchemes</key>
+      <array>
+        <string>kodi</string>
+      </array>
+    </dict>
+  </array>
+  <key>CFBundleDocumentTypes</key>
+  <array>
+    <dict>
+      <key>CFBundleTypeIconFiles</key>
+      <array/>
+      <key>CFBundleTypeName</key>
+      <string>Picture</string>
+      <key>LSItemContentTypes</key>
+      <array>
+        <string>org.xbmc.kodi-ios.picture</string>
+      </array>
+    </dict>
+    <dict>
+      <key>CFBundleTypeIconFiles</key>
+      <array/>
+      <key>CFBundleTypeName</key>
+      <string>Music</string>
+      <key>LSItemContentTypes</key>
+      <array>
+        <string>org.xbmc.kodi-ios.music</string>
+      </array>
+    </dict>
+    <dict>
+      <key>CFBundleTypeIconFiles</key>
+      <array/>
+      <key>CFBundleTypeName</key>
+      <string>Video</string>
+      <key>LSItemContentTypes</key>
+      <array>
+        <string>org.xbmc.kodi-ios.video</string>
+      </array>
+    </dict>
+    <dict>
+      <key>CFBundleTypeIconFiles</key>
+      <array/>
+      <key>CFBundleTypeName</key>
+      <string>Subtitle</string>
+      <key>LSItemContentTypes</key>
+      <array>
+        <string>org.xbmc.kodi-ios.subtitle</string>
+      </array>
+    </dict>
+  </array>
+  <key>UTExportedTypeDeclarations</key>
+  <array>
+    <dict>
+      <key>UTTypeSize320IconFile</key>
+      <string>AppIcon60x60</string>
+      <key>UTTypeIdentifier</key>
+      <string>org.xbmc.kodi-ios.picture</string>
+      <key>UTTypeSize64IconFile</key>
+      <string>AppIcon60x60</string>
+      <key>UTTypeConformsTo</key>
+      <array>
+        <string>public.data</string>
+      </array>
+      <key>UTTypeDescription</key>
+      <string>Picture</string>
+      <key>UTTypeTagSpecification</key>
+      <dict>
+        <key>public.filename-extension</key>
+        <array>
+          <string>png</string>
+          <string>jpg</string>
+          <string>jpeg</string>
+          <string>bmp</string>
+          <string>gif</string>
+          <string>ico</string>
+          <string>tif</string>
+          <string>tiff</string>
+          <string>tga</string>
+          <string>pcx</string>
+          <string>cbz</string>
+          <string>zip</string>
+          <string>cbr</string>
+          <string>rar</string>
+          <string>rss</string>
+          <string>webp</string>
+          <string>jp2</string>
+          <string>apng</string>
+        </array>
+      </dict>
+    </dict>
+    <dict>
+      <key>UTTypeSize320IconFile</key>
+      <string>AppIcon60x60</string>
+      <key>UTTypeIdentifier</key>
+      <string>org.xbmc.kodi-ios.music</string>
+      <key>UTTypeSize64IconFile</key>
+      <string>AppIcon60x60</string>
+      <key>UTTypeConformsTo</key>
+      <array>
+        <string>public.data</string>
+      </array>
+      <key>UTTypeDescription</key>
+      <string>Music</string>
+      <key>UTTypeTagSpecification</key>
+      <dict>
+        <key>public.filename-extension</key>
+        <array>
+          <string>nsv</string>
+          <string>m4a</string>
+          <string>flac</string>
+          <string>aac</string>
+          <string>strm</string>
+          <string>pls</string>
+          <string>rm</string>
+          <string>rma</string>
+          <string>mpa</string>
+          <string>wav</string>
+          <string>wma</string>
+          <string>ogg</string>
+          <string>mp3</string>
+          <string>mp2</string>
+          <string>m3u</string>
+          <string>gdm</string>
+          <string>imf</string>
+          <string>m15</string>
+          <string>sfx</string>
+          <string>uni</string>
+          <string>ac3</string>
+          <string>dts</string>
+          <string>cue</string>
+          <string>aif</string>
+          <string>aiff</string>
+          <string>wpl</string>
+          <string>ape</string>
+          <string>mac</string>
+          <string>mpc</string>
+          <string>mp+</string>
+          <string>mpp</string>
+          <string>shn</string>
+          <string>zip</string>
+          <string>rar</string>
+          <string>wv</string>
+          <string>dsp</string>
+          <string>xsp</string>
+          <string>xwav</string>
+          <string>waa</string>
+          <string>wvs</string>
+          <string>wam</string>
+          <string>gcm</string>
+          <string>idsp</string>
+          <string>mpdsp</string>
+          <string>mss</string>
+          <string>spt</string>
+          <string>rsd</string>
+          <string>sap</string>
+          <string>cmc</string>
+          <string>cmr</string>
+          <string>dmc</string>
+          <string>mpt</string>
+          <string>mpd</string>
+          <string>rmt</string>
+          <string>tmc</string>
+          <string>tm8</string>
+          <string>tm2</string>
+          <string>oga</string>
+          <string>url</string>
+          <string>pxml</string>
+          <string>tta</string>
+          <string>rss</string>
+          <string>wtv</string>
+          <string>mka</string>
+          <string>tak</string>
+          <string>opus</string>
+          <string>dff</string>
+          <string>dsf</string>
+        </array>
+      </dict>
+    </dict>
+    <dict>
+      <key>UTTypeSize320IconFile</key>
+      <string>AppIcon60x60</string>
+      <key>UTTypeIdentifier</key>
+      <string>org.xbmc.kodi-ios.video</string>
+      <key>UTTypeSize64IconFile</key>
+      <string>AppIcon60x60</string>
+      <key>UTTypeConformsTo</key>
+      <array>
+        <string>public.data</string>
+      </array>
+      <key>UTTypeDescription</key>
+      <string>Video</string>
+      <key>UTTypeTagSpecification</key>
+      <dict>
+        <key>public.filename-extension</key>
+        <array>
+          <string>m4v</string>
+          <string>3g2</string>
+          <string>3gp</string>
+          <string>nsv</string>
+          <string>tp</string>
+          <string>ts</string>
+          <string>ty</string>
+          <string>strm</string>
+          <string>pls</string>
+          <string>rm</string>
+          <string>rmvb</string>
+          <string>mpd</string>
+          <string>m3u</string>
+          <string>m3u8</string>
+          <string>ifo</string>
+          <string>mov</string>
+          <string>qt</string>
+          <string>divx</string>
+          <string>xvid</string>
+          <string>bivx</string>
+          <string>vob</string>
+          <string>nrg</string>
+          <string>img</string>
+          <string>iso</string>
+          <string>pva</string>
+          <string>wmv</string>
+          <string>asf</string>
+          <string>asx</string>
+          <string>ogm</string>
+          <string>m2v</string>
+          <string>avi</string>
+          <string>bin</string>
+          <string>dat</string>
+          <string>mpg</string>
+          <string>mpeg</string>
+          <string>mp4</string>
+          <string>mkv</string>
+          <string>mk3d</string>
+          <string>avc</string>
+          <string>vp3</string>
+          <string>svq3</string>
+          <string>nuv</string>
+          <string>viv</string>
+          <string>dv</string>
+          <string>fli</string>
+          <string>flv</string>
+          <string>rar</string>
+          <string>001</string>
+          <string>wpl</string>
+          <string>zip</string>
+          <string>vdr</string>
+          <string>dvr-ms</string>
+          <string>xsp</string>
+          <string>mts</string>
+          <string>m2t</string>
+          <string>m2ts</string>
+          <string>evo</string>
+          <string>ogv</string>
+          <string>sdp</string>
+          <string>avs</string>
+          <string>rec</string>
+          <string>url</string>
+          <string>pxml</string>
+          <string>vc1</string>
+          <string>h264</string>
+          <string>rcv</string>
+          <string>rss</string>
+          <string>mpls</string>
+          <string>webm</string>
+          <string>bdmv</string>
+          <string>wtv</string>
+        </array>
+      </dict>
+    </dict>
+    <dict>
+      <key>UTTypeSize320IconFile</key>
+      <string>AppIcon60x60</string>
+      <key>UTTypeIdentifier</key>
+      <string>org.xbmc.kodi-ios.subtitle</string>
+      <key>UTTypeSize64IconFile</key>
+      <string>AppIcon60x60</string>
+      <key>UTTypeConformsTo</key>
+      <array>
+        <string>public.data</string>
+      </array>
+      <key>UTTypeDescription</key>
+      <string>Subtitle</string>
+      <key>UTTypeTagSpecification</key>
+      <dict>
+        <key>public.filename-extension</key>
+        <array>
+          <string>utf</string>
+          <string>utf8</string>
+          <string>utf-8</string>
+          <string>sub</string>
+          <string>srt</string>
+          <string>smi</string>
+          <string>rt</string>
+          <string>txt</string>
+          <string>ssa</string>
+          <string>text</string>
+          <string>ssa</string>
+          <string>aqt</string>
+          <string>jss</string>
+          <string>ass</string>
+          <string>idx</string>
+          <string>ifo</string>
+          <string>rar</string>
+          <string>zip</string>
+        </array>
+      </dict>
+    </dict>
+  </array>
 </dict>
 </plist>
diff --git a/xbmc/platform/darwin/osx/SDLMain.mm b/xbmc/platform/darwin/osx/SDLMain.mm
index 7f12ea1..1748c96 100644
--- a/xbmc/platform/darwin/osx/SDLMain.mm
+++ b/xbmc/platform/darwin/osx/SDLMain.mm
@@ -438,12 +438,12 @@ static void setupWindowMenu(void)
 #define VK_VOLUME_MUTE      0xAD
 #define VK_VOLUME_DOWN      0xAE
 #define VK_VOLUME_UP        0xAF
-#define VK_MEDIA_NEXT_TRACK 0xB0
-#define VK_MEDIA_PREV_TRACK 0xB1
+#define VK_MEDIA_NEXT_TRACK 0x9E
+#define VK_MEDIA_PREV_TRACK 0x9D
 #define VK_MEDIA_STOP       0xB2
 #define VK_MEDIA_PLAY_PAUSE 0xB3
-#define VK_REWIND           0x9D
-#define VK_FAST_FWD         0x9E
+#define VK_REWIND           0xB1
+#define VK_FAST_FWD         0xB0
 
 - (void)powerKeyNotification
 {
diff --git a/xbmc/platform/win32/CMakeLists.txt b/xbmc/platform/win32/CMakeLists.txt
index 2e1bacc..19f20c4 100644
--- a/xbmc/platform/win32/CMakeLists.txt
+++ b/xbmc/platform/win32/CMakeLists.txt
@@ -1,4 +1,27 @@
 set(SOURCES MessagePrinter.cpp
-            WinMain.cpp)
+            WinMain.cpp
+            crts_caller.cpp
+            dxerr.cpp
+            pch.cpp
+            stat_utf8.cpp
+            stdio_utf8.cpp
+            strverscmp.cpp
+            WIN32Util.cpp
+            WindowHelper.cpp)
+
+set(HEADERS crts_caller.h
+            dirent.h
+            dxerr.h
+            IMMNotificationClient.h
+            my_ntddcdrm.h
+            my_ntddscsi.h
+            netdb.h
+            pch.h
+            PlatformDefs.h
+            PlatformInclude.h
+            resource.h
+            unistd.h
+            WIN32Util.h
+            WindowHelper.h)
 
 core_add_library(platform_win32)
diff --git a/xbmc/platform/win32/IMMNotificationClient.h b/xbmc/platform/win32/IMMNotificationClient.h
new file mode 100644
index 0000000..cf267b6
--- /dev/null
+++ b/xbmc/platform/win32/IMMNotificationClient.h
@@ -0,0 +1,173 @@
+//#pragma once
+/*
+ *      Copyright (C) 2014 Team XBMC
+ *      http://xbmc.org
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <mmdeviceapi.h>
+#include "system.h" // for SAFE_RELEASE
+#include "utils/log.h"
+#include "cores/AudioEngine/AEFactory.h"
+#include "powermanagement/windows/Win32PowerSyscall.h"
+
+class CMMNotificationClient : public IMMNotificationClient
+{
+  LONG _cRef;
+  IMMDeviceEnumerator *_pEnumerator;
+
+
+public:
+  CMMNotificationClient() : _cRef(1), _pEnumerator(NULL)
+  {
+  }
+
+  ~CMMNotificationClient()
+  {
+    SAFE_RELEASE(_pEnumerator);
+  }
+
+  // IUnknown methods -- AddRef, Release, and QueryInterface
+
+  ULONG STDMETHODCALLTYPE AddRef()
+  {
+    return InterlockedIncrement(&_cRef);
+  }
+
+  ULONG STDMETHODCALLTYPE Release()
+  {
+    ULONG ulRef = InterlockedDecrement(&_cRef);
+    if (0 == ulRef)
+    {
+      delete this;
+    }
+    return ulRef;
+  }
+
+  HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvInterface)
+  {
+    if (IID_IUnknown == riid)
+    {
+      AddRef();
+      *ppvInterface = (IUnknown*)this;
+    }
+    else if (__uuidof(IMMNotificationClient) == riid)
+    {
+      AddRef();
+      *ppvInterface = (IMMNotificationClient*)this;
+    }
+    else
+    {
+      *ppvInterface = NULL;
+      return E_NOINTERFACE;
+    }
+    return S_OK;
+  }
+
+  // Callback methods for device-event notifications.
+
+  HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId)
+  {
+    // if the default device changes this function is called four times.
+    // therefore we call CAEFactory::DeviceChange() only for one role.
+    char  *pszFlow = "?????";
+    char  *pszRole = "?????";
+
+    switch (flow)
+    {
+    case eRender:
+      pszFlow = "eRender";
+      break;
+    case eCapture:
+      pszFlow = "eCapture";
+      break;
+    }
+
+    switch (role)
+    {
+    case eConsole:
+      pszRole = "eConsole";
+      break;
+    case eMultimedia:
+      pszRole = "eMultimedia";
+      break;
+    case eCommunications:
+      pszRole = "eCommunications";
+      NotifyAE();
+      break;
+    }
+
+    CLog::Log(LOGDEBUG, "%s: New default device: flow = %s, role = %s", __FUNCTION__, pszFlow, pszRole);
+    return S_OK;
+  }
+
+  HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId)
+  {
+    CLog::Log(LOGDEBUG, "%s: Added device: %s", __FUNCTION__, pwstrDeviceId);
+    NotifyAE();
+    return S_OK;
+  }
+
+  HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId)
+  {
+    CLog::Log(LOGDEBUG, "%s: Removed device: %s", __FUNCTION__, pwstrDeviceId);
+    NotifyAE();
+    return S_OK;
+  }
+
+  HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState)
+  {
+    char  *pszState = "?????";
+
+    switch (dwNewState)
+    {
+    case DEVICE_STATE_ACTIVE:
+      pszState = "ACTIVE";
+      break;
+    case DEVICE_STATE_DISABLED:
+      pszState = "DISABLED";
+      break;
+    case DEVICE_STATE_NOTPRESENT:
+      pszState = "NOTPRESENT";
+      break;
+    case DEVICE_STATE_UNPLUGGED:
+      pszState = "UNPLUGGED";
+      break;
+    }
+    CLog::Log(LOGDEBUG, "%s: New device state is DEVICE_STATE_%s", __FUNCTION__, pszState);
+    NotifyAE();
+    return S_OK;
+  }
+
+  HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key)
+  {
+    CLog::Log(LOGDEBUG, "%s: Changed device property of %S is {%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x}#%d", 
+              __FUNCTION__, pwstrDeviceId, key.fmtid.Data1, key.fmtid.Data2, key.fmtid.Data3,
+                                           key.fmtid.Data4[0], key.fmtid.Data4[1],
+                                           key.fmtid.Data4[2], key.fmtid.Data4[3],
+                                           key.fmtid.Data4[4], key.fmtid.Data4[5],
+                                           key.fmtid.Data4[6], key.fmtid.Data4[7],
+                                           key.pid);
+    return S_OK;
+  }
+
+  void STDMETHODCALLTYPE NotifyAE()
+  {
+    if(!CWin32PowerSyscall::IsSuspending())
+      CAEFactory::DeviceChange();
+  }
+};
\ No newline at end of file
diff --git a/xbmc/platform/win32/PlatformDefs.h b/xbmc/platform/win32/PlatformDefs.h
new file mode 100644
index 0000000..4af4c7d
--- /dev/null
+++ b/xbmc/platform/win32/PlatformDefs.h
@@ -0,0 +1,100 @@
+#pragma once
+
+/*
+ *      Copyright (C) 2005-2015 Team Kodi
+ *      http://kodi.tv
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Kodi; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef TARGET_WINDOWS
+
+#define LINE_ENDING "\r\n"
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+typedef __int64       off64_t;
+typedef __int64       fpos64_t;
+typedef __int64       __off64_t;
+typedef long          __off_t;
+
+#if !defined(_SSIZE_T_DEFINED) && !defined(HAVE_SSIZE_T)
+typedef intptr_t      ssize_t;
+#define _SSIZE_T_DEFINED
+#endif // !_SSIZE_T_DEFINED
+#ifndef SSIZE_MAX
+#define SSIZE_MAX INTPTR_MAX
+#endif // !SSIZE_MAX
+
+#if _MSC_VER < 1900
+#define snprintf _snprintf
+#endif
+#define ftello64 _ftelli64
+#define fseeko64 _fseeki64
+#ifndef strcasecmp
+#define strcasecmp strcmpi
+#endif
+#ifndef strncasecmp
+#define strncasecmp strnicmp
+#endif
+
+#define popen   _popen
+#define pclose  _pclose
+
+#if 0
+// big endian
+#define PIXEL_ASHIFT 0
+#define PIXEL_RSHIFT 8
+#define PIXEL_GSHIFT 16
+#define PIXEL_BSHIFT 24
+#define AMASK 0x000000ff
+#define RMASK 0x0000ff00
+#define GMASK 0x00ff0000
+#define BMASK 0xff000000
+#else
+// little endian
+#define PIXEL_ASHIFT 24
+#define PIXEL_RSHIFT 16
+#define PIXEL_GSHIFT 8
+#define PIXEL_BSHIFT 0
+#define AMASK 0xff000000
+#define RMASK 0x00ff0000
+#define GMASK 0x0000ff00
+#define BMASK 0x000000ff
+#endif
+
+#if _MSC_VER < 1800
+#ifndef va_copy
+#define va_copy(dst, src) ((dst) = (src))
+#endif
+
+#define lrint(x) ((x) >= 0 ? ((int)((x) + 0.5)) : ((int)((x) - 0.5)))
+#define llrint(x) ((x) >= 0 ? ((__int64)((x) + 0.5)) : ((__int64)((x) - 0.5)))
+
+#define strtoll(p, e, b) _strtoi64(p, e, b)
+#endif
+
+extern "C" char * strptime(const char *buf, const char *fmt, struct tm *tm);
+extern "C" int strverscmp (const char *s1, const char *s2);
+extern "C" char * strcasestr(const char* haystack, const char* needle);
+
+#if _MSC_VER >= 1800
+#define PRIdS       "Id"
+#define PRIuS       "Iu"
+#endif
+#endif // TARGET_WINDOWS
+
diff --git a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h b/xbmc/platform/win32/PlatformInclude.h
similarity index 63%
copy from xbmc/cores/VideoPlayer/Process/ProcessInfo.h
copy to xbmc/platform/win32/PlatformInclude.h
index b8a4e46..ad8d722 100644
--- a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h
+++ b/xbmc/platform/win32/PlatformInclude.h
@@ -1,6 +1,8 @@
+#pragma once
+
 /*
- *      Copyright (C) 2005-2016 Team XBMC
- *      http://xbmc.org
+ *      Copyright (C) 2005-2015 Team Kodi
+ *      http://kodi.tv
  *
  *  This Program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -13,22 +15,11 @@
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
- *  along with XBMC; see the file COPYING.  If not, see
+ *  along with Kodi; see the file COPYING.  If not, see
  *  <http://www.gnu.org/licenses/>.
  *
  */
-#pragma once
-
-#include "cores/IPlayer.h"
 
-class CProcessInfo
-{
-public:
-  static CProcessInfo* CreateInstance();
-  virtual ~CProcessInfo();
-  virtual EINTERLACEMETHOD GetFallbackDeintMethod();
-  virtual bool AllowDTSHDDecode();
+#include <errno.h> // for ENOENT and EINVAL
+#include "PlatformDefs.h"
 
-protected:
-  CProcessInfo();
-};
diff --git a/xbmc/platform/win32/WIN32Util.cpp b/xbmc/platform/win32/WIN32Util.cpp
new file mode 100644
index 0000000..4adf07b
--- /dev/null
+++ b/xbmc/platform/win32/WIN32Util.cpp
@@ -0,0 +1,1637 @@
+/*
+ *      Copyright (C) 2005-2013 Team XBMC
+ *      http://xbmc.org
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "WIN32Util.h"
+#include "Util.h"
+#include "utils/URIUtils.h"
+#include "storage/cdioSupport.h"
+#include "PowrProf.h"
+#include "WindowHelper.h"
+#include "Application.h"
+#include <shlobj.h>
+#include "filesystem/SpecialProtocol.h"
+#include "my_ntddscsi.h"
+#include "Setupapi.h"
+#include "storage/MediaManager.h"
+#include "windowing/WindowingFactory.h"
+#include "guilib/LocalizeStrings.h"
+#include "utils/CharsetConverter.h"
+#include "utils/log.h"
+#include "powermanagement/PowerManager.h"
+#include "utils/SystemInfo.h"
+#include "utils/Environment.h"
+#include "utils/StringUtils.h"
+#include "platform/win32/crts_caller.h"
+
+#include <cassert>
+
+
+#include <locale.h>
+
+extern HWND g_hWnd;
+
+using namespace MEDIA_DETECT;
+
+CWIN32Util::CWIN32Util(void)
+{
+}
+
+CWIN32Util::~CWIN32Util(void)
+{
+}
+
+int CWIN32Util::GetDriveStatus(const std::string &strPath, bool bStatusEx)
+{
+  HANDLE hDevice;               // handle to the drive to be examined
+  int iResult;                  // results flag
+  ULONG ulChanges=0;
+  DWORD dwBytesReturned;
+  T_SPDT_SBUF sptd_sb;  //SCSI Pass Through Direct variable.
+  byte DataBuf[8];  //Buffer for holding data to/from drive.
+
+  CLog::Log(LOGDEBUG, __FUNCTION__": Requesting status for drive %s.", strPath.c_str());
+
+  hDevice = CreateFile( strPath.c_str(),                  // drive
+                        0,                                // no access to the drive
+                        FILE_SHARE_READ,                  // share mode
+                        NULL,                             // default security attributes
+                        OPEN_EXISTING,                    // disposition
+                        FILE_ATTRIBUTE_READONLY,          // file attributes
+                        NULL);
+
+  if (hDevice == INVALID_HANDLE_VALUE)                    // cannot open the drive
+  {
+    CLog::Log(LOGERROR, __FUNCTION__": Failed to CreateFile for %s.", strPath.c_str());
+    return -1;
+  }
+
+  CLog::Log(LOGDEBUG, __FUNCTION__": Requesting media status for drive %s.", strPath.c_str());
+  iResult = DeviceIoControl((HANDLE) hDevice,             // handle to device
+                             IOCTL_STORAGE_CHECK_VERIFY2, // dwIoControlCode
+                             NULL,                        // lpInBuffer
+                             0,                           // nInBufferSize
+                             &ulChanges,                  // lpOutBuffer
+                             sizeof(ULONG),               // nOutBufferSize
+                             &dwBytesReturned ,           // number of bytes returned
+                             NULL );                      // OVERLAPPED structure
+
+  CloseHandle(hDevice);
+
+  if(iResult == 1)
+    return 2;
+
+  // don't request the tray status as we often doesn't need it
+  if(!bStatusEx)
+    return 0;
+
+  hDevice = CreateFile( strPath.c_str(),
+                        GENERIC_READ | GENERIC_WRITE,
+                        FILE_SHARE_READ | FILE_SHARE_WRITE,
+                        NULL,
+                        OPEN_EXISTING,
+                        FILE_ATTRIBUTE_READONLY,
+                        NULL);
+
+  if (hDevice == INVALID_HANDLE_VALUE)
+  {
+    CLog::Log(LOGERROR, __FUNCTION__": Failed to CreateFile2 for %s.", strPath.c_str());
+    return -1;
+  }
+
+  sptd_sb.sptd.Length=sizeof(SCSI_PASS_THROUGH_DIRECT);
+  sptd_sb.sptd.PathId=0;
+  sptd_sb.sptd.TargetId=0;
+  sptd_sb.sptd.Lun=0;
+  sptd_sb.sptd.CdbLength=10;
+  sptd_sb.sptd.SenseInfoLength=MAX_SENSE_LEN;
+  sptd_sb.sptd.DataIn=SCSI_IOCTL_DATA_IN;
+  sptd_sb.sptd.DataTransferLength=sizeof(DataBuf);
+  sptd_sb.sptd.TimeOutValue=2;
+  sptd_sb.sptd.DataBuffer=(PVOID)&(DataBuf);
+  sptd_sb.sptd.SenseInfoOffset=sizeof(SCSI_PASS_THROUGH_DIRECT);
+
+  sptd_sb.sptd.Cdb[0]=0x4a;
+  sptd_sb.sptd.Cdb[1]=1;
+  sptd_sb.sptd.Cdb[2]=0;
+  sptd_sb.sptd.Cdb[3]=0;
+  sptd_sb.sptd.Cdb[4]=0x10;
+  sptd_sb.sptd.Cdb[5]=0;
+  sptd_sb.sptd.Cdb[6]=0;
+  sptd_sb.sptd.Cdb[7]=0;
+  sptd_sb.sptd.Cdb[8]=8;
+  sptd_sb.sptd.Cdb[9]=0;
+  sptd_sb.sptd.Cdb[10]=0;
+  sptd_sb.sptd.Cdb[11]=0;
+  sptd_sb.sptd.Cdb[12]=0;
+  sptd_sb.sptd.Cdb[13]=0;
+  sptd_sb.sptd.Cdb[14]=0;
+  sptd_sb.sptd.Cdb[15]=0;
+
+  ZeroMemory(DataBuf, 8);
+  ZeroMemory(sptd_sb.SenseBuf, MAX_SENSE_LEN);
+
+  //Send the command to drive
+  CLog::Log(LOGDEBUG, __FUNCTION__": Requesting tray status for drive %s.", strPath.c_str());
+  iResult = DeviceIoControl((HANDLE) hDevice,
+                            IOCTL_SCSI_PASS_THROUGH_DIRECT,
+                            (PVOID)&sptd_sb, (DWORD)sizeof(sptd_sb),
+                            (PVOID)&sptd_sb, (DWORD)sizeof(sptd_sb),
+                            &dwBytesReturned,
+                            NULL);
+
+  CloseHandle(hDevice);
+
+  if(iResult)
+  {
+
+    if(DataBuf[5] == 0) // tray close
+      return 0;
+    else if(DataBuf[5] == 1) // tray open
+      return 1;
+    else
+      return 2; // tray closed, media present
+  }
+  CLog::Log(LOGERROR, __FUNCTION__": Could not determine tray status %d", GetLastError());
+  return -1;
+}
+
+char CWIN32Util::FirstDriveFromMask (ULONG unitmask)
+{
+    char i;
+    for (i = 0; i < 26; ++i)
+    {
+        if (unitmask & 0x1) break;
+        unitmask = unitmask >> 1;
+    }
+    return (i + 'A');
+}
+
+bool CWIN32Util::PowerManagement(PowerState State)
+{
+  static bool gotShutdownPrivileges = false;
+  if (!gotShutdownPrivileges)
+  {
+    HANDLE hToken;
+    // Get a token for this process.
+    if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+    {
+      // Get the LUID for the shutdown privilege.
+      TOKEN_PRIVILEGES tkp = {};
+      if (LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid))
+      {
+        tkp.PrivilegeCount = 1;  // one privilege to set
+        tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+        // Get the shutdown privilege for this process.
+        if (AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0))
+          gotShutdownPrivileges = true;
+      }
+      CloseHandle(hToken);
+    }
+
+    if (!gotShutdownPrivileges)
+      return false;
+  }
+
+  switch (State)
+  {
+  case POWERSTATE_HIBERNATE:
+    CLog::Log(LOGINFO, "Asking Windows to hibernate...");
+    return SetSuspendState(true, true, false) == TRUE;
+    break;
+  case POWERSTATE_SUSPEND:
+    CLog::Log(LOGINFO, "Asking Windows to suspend...");
+    return SetSuspendState(false, true, false) == TRUE;
+    break;
+  case POWERSTATE_SHUTDOWN:
+    CLog::Log(LOGINFO, "Shutdown Windows...");
+    if (g_sysinfo.IsWindowsVersionAtLeast(CSysInfo::WindowsVersionWin8))
+      return InitiateShutdownW(NULL, NULL, 0, SHUTDOWN_HYBRID | SHUTDOWN_INSTALL_UPDATES | SHUTDOWN_POWEROFF,
+                               SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED) == ERROR_SUCCESS;
+    return InitiateShutdownW(NULL, NULL, 0, SHUTDOWN_INSTALL_UPDATES | SHUTDOWN_POWEROFF,
+                             SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED) == ERROR_SUCCESS;
+    break;
+  case POWERSTATE_REBOOT:
+    CLog::Log(LOGINFO, "Rebooting Windows...");
+    if (g_sysinfo.IsWindowsVersionAtLeast(CSysInfo::WindowsVersionWin8))
+      return InitiateShutdownW(NULL, NULL, 0, SHUTDOWN_INSTALL_UPDATES | SHUTDOWN_RESTART,
+                               SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED) == ERROR_SUCCESS;
+    return InitiateShutdownW(NULL, NULL, 0, SHUTDOWN_INSTALL_UPDATES | SHUTDOWN_RESTART,
+                             SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED) == ERROR_SUCCESS;
+    break;
+  default:
+    CLog::Log(LOGERROR, "Unknown PowerState called.");
+    return false;
+    break;
+  }
+}
+
+int CWIN32Util::BatteryLevel()
+{
+  SYSTEM_POWER_STATUS SystemPowerStatus;
+
+  if (GetSystemPowerStatus(&SystemPowerStatus) && SystemPowerStatus.BatteryLifePercent != 255)
+      return SystemPowerStatus.BatteryLifePercent;
+
+  return 0;
+}
+
+bool CWIN32Util::XBMCShellExecute(const std::string &strPath, bool bWaitForScriptExit)
+{
+  std::string strCommand = strPath;
+  std::string strExe = strPath;
+  std::string strParams;
+  std::string strWorkingDir;
+
+  StringUtils::Trim(strCommand);
+  if (strCommand.empty())
+  {
+    return false;
+  }
+  size_t iIndex = std::string::npos;
+  char split = ' ';
+  if (strCommand[0] == '\"')
+  {
+    split = '\"';
+  }
+  iIndex = strCommand.find(split, 1);
+  if (iIndex != std::string::npos)
+  {
+    strExe = strCommand.substr(0, iIndex + 1);
+    strParams = strCommand.substr(iIndex + 1);
+  }
+
+  StringUtils::Replace(strExe, "\"", "");
+
+  strWorkingDir = strExe;
+  iIndex = strWorkingDir.rfind('\\');
+  if(iIndex != std::string::npos)
+  {
+    strWorkingDir[iIndex+1] = '\0';
+  }
+
+  std::wstring WstrExe, WstrParams, WstrWorkingDir;
+  g_charsetConverter.utf8ToW(strExe, WstrExe);
+  g_charsetConverter.utf8ToW(strParams, WstrParams);
+  g_charsetConverter.utf8ToW(strWorkingDir, WstrWorkingDir);
+
+  bool ret;
+  SHELLEXECUTEINFOW ShExecInfo = {0};
+  ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
+  ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
+  ShExecInfo.hwnd = NULL;
+  ShExecInfo.lpVerb = NULL;
+  ShExecInfo.lpFile = WstrExe.c_str();
+  ShExecInfo.lpParameters = WstrParams.c_str();
+  ShExecInfo.lpDirectory = WstrWorkingDir.c_str();
+  ShExecInfo.nShow = SW_SHOW;
+  ShExecInfo.hInstApp = NULL;
+
+  g_windowHelper.StopThread();
+
+  LockSetForegroundWindow(LSFW_UNLOCK);
+  ShowWindow(g_hWnd,SW_MINIMIZE);
+  ret = ShellExecuteExW(&ShExecInfo) == TRUE;
+  g_windowHelper.SetHANDLE(ShExecInfo.hProcess);
+
+  // ShellExecute doesn't return the window of the started process
+  // we need to gather it from somewhere to allow switch back to XBMC
+  // when a program is minimized instead of stopped.
+  //g_windowHelper.SetHWND(ShExecInfo.hwnd);
+  g_windowHelper.Create();
+
+  if(bWaitForScriptExit)
+  {
+    //! @todo Pause music and video playback
+    WaitForSingleObject(ShExecInfo.hProcess,INFINITE);
+  }
+
+  return ret;
+}
+
+std::vector<std::string> CWIN32Util::GetDiskUsage()
+{
+  std::vector<std::string> result;
+  ULARGE_INTEGER ULTotal= { { 0 } };
+  ULARGE_INTEGER ULTotalFree= { { 0 } };
+
+  char* pcBuffer= NULL;
+  DWORD dwStrLength= GetLogicalDriveStrings( 0, pcBuffer );
+  if( dwStrLength != 0 )
+  {
+    std::string strRet;
+
+    dwStrLength+= 1;
+    pcBuffer= new char [dwStrLength];
+    GetLogicalDriveStrings( dwStrLength, pcBuffer );
+    int iPos= 0;
+    do
+    {
+      std::string strDrive = pcBuffer + iPos;
+      if( DRIVE_FIXED == GetDriveType( strDrive.c_str()  ) &&
+        GetDiskFreeSpaceEx( ( strDrive.c_str() ), NULL, &ULTotal, &ULTotalFree ) )
+      {
+        strRet = StringUtils::Format("%s %d MB %s",strDrive.c_str(), int(ULTotalFree.QuadPart/(1024*1024)),g_localizeStrings.Get(160).c_str());
+        result.push_back(strRet);
+      }
+      iPos += (strlen( pcBuffer + iPos) + 1 );
+    }while( strlen( pcBuffer + iPos ) > 0 );
+  }
+  delete[] pcBuffer;
+  return result;
+}
+
+std::string CWIN32Util::GetResInfoString()
+{
+  DEVMODE devmode;
+  ZeroMemory(&devmode, sizeof(devmode));
+  devmode.dmSize = sizeof(devmode);
+  EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+  return StringUtils::Format("Desktop Resolution: %dx%d %dBit at %dHz",devmode.dmPelsWidth,devmode.dmPelsHeight,devmode.dmBitsPerPel,devmode.dmDisplayFrequency);
+}
+
+int CWIN32Util::GetDesktopColorDepth()
+{
+  DEVMODE devmode;
+  ZeroMemory(&devmode, sizeof(devmode));
+  devmode.dmSize = sizeof(devmode);
+  EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+  return (int)devmode.dmBitsPerPel;
+}
+
+std::string CWIN32Util::GetSpecialFolder(int csidl)
+{
+  std::string strProfilePath;
+  static const int bufSize = MAX_PATH;
+  WCHAR* buf = new WCHAR[bufSize];
+
+  if(SUCCEEDED(SHGetFolderPathW(NULL, csidl, NULL, SHGFP_TYPE_CURRENT, buf)))
+  {
+    buf[bufSize-1] = 0;
+    g_charsetConverter.wToUTF8(buf, strProfilePath);
+    strProfilePath = UncToSmb(strProfilePath);
+  }
+  else
+    strProfilePath = "";
+  
+  delete[] buf;
+  return strProfilePath;
+}
+
+std::string CWIN32Util::GetSystemPath()
+{
+  return GetSpecialFolder(CSIDL_SYSTEM);
+}
+
+std::string CWIN32Util::GetProfilePath()
+{
+  std::string strProfilePath;
+  std::string strHomePath;
+
+  CUtil::GetHomePath(strHomePath);
+
+  if(g_application.PlatformDirectoriesEnabled())
+    strProfilePath = URIUtils::AddFileToFolder(GetSpecialFolder(CSIDL_APPDATA|CSIDL_FLAG_CREATE), "Kodi");
+  else
+    strProfilePath = URIUtils::AddFileToFolder(strHomePath , "portable_data");
+
+  if (strProfilePath.length() == 0)
+    strProfilePath = strHomePath;
+
+  URIUtils::AddSlashAtEnd(strProfilePath);
+
+  return strProfilePath;
+}
+
+std::string CWIN32Util::UncToSmb(const std::string &strPath)
+{
+  std::string strRetPath(strPath);
+  if(StringUtils::StartsWith(strRetPath, "\\\\"))
+  {
+    strRetPath = "smb:" + strPath;
+    StringUtils::Replace(strRetPath, '\\', '/');
+  }
+  return strRetPath;
+}
+
+std::string CWIN32Util::SmbToUnc(const std::string &strPath)
+{
+  std::string strRetPath(strPath);
+  if(StringUtils::StartsWithNoCase(strRetPath, "smb://"))
+  {
+    StringUtils::Replace(strRetPath, "smb://", "\\\\");
+    StringUtils::Replace(strRetPath, '/', '\\');
+  }
+  return strRetPath;
+}
+
+bool CWIN32Util::AddExtraLongPathPrefix(std::wstring& path)
+{
+  const wchar_t* const str = path.c_str();
+  if (path.length() < 4 || str[0] != L'\\' || str[1] != L'\\' || str[3] != L'\\' || str[2] != L'?')
+  {
+    path.insert(0, L"\\\\?\\");
+    return true;
+  }
+  return false;
+}
+
+bool CWIN32Util::RemoveExtraLongPathPrefix(std::wstring& path)
+{
+  const wchar_t* const str = path.c_str();
+  if (path.length() >= 4 && str[0] == L'\\' && str[1] == L'\\' && str[3] == L'\\' && str[2] == L'?')
+  {
+    path.erase(0, 4);
+    return true;
+  }
+  return false;
+}
+
+std::wstring CWIN32Util::ConvertPathToWin32Form(const std::string& pathUtf8)
+{
+  std::wstring result;
+  if (pathUtf8.empty())
+    return result;
+
+  bool convertResult;
+
+  if (pathUtf8.compare(0, 2, "\\\\", 2) != 0) // pathUtf8 don't start from "\\"
+  { // assume local file path in form 'C:\Folder\File.ext'
+    std::string formedPath("\\\\?\\"); // insert "\\?\" prefix
+    formedPath += URIUtils::CanonicalizePath(URIUtils::FixSlashesAndDups(pathUtf8, '\\'), '\\'); // fix duplicated and forward slashes, resolve relative path
+    convertResult = g_charsetConverter.utf8ToW(formedPath, result, false, false, true);
+  }
+  else if (pathUtf8.compare(0, 8, "\\\\?\\UNC\\", 8) == 0) // pathUtf8 starts from "\\?\UNC\"
+  {
+    std::string formedPath("\\\\?\\UNC"); // start from "\\?\UNC" prefix
+    formedPath += URIUtils::CanonicalizePath(URIUtils::FixSlashesAndDups(pathUtf8.substr(7), '\\'), '\\'); // fix duplicated and forward slashes, resolve relative path, don't touch "\\?\UNC" prefix,
+    convertResult = g_charsetConverter.utf8ToW(formedPath, result, false, false, true); 
+  }
+  else if (pathUtf8.compare(0, 4, "\\\\?\\", 4) == 0) // pathUtf8 starts from "\\?\", but it's not UNC path
+  {
+    std::string formedPath("\\\\?"); // start from "\\?" prefix
+    formedPath += URIUtils::CanonicalizePath(URIUtils::FixSlashesAndDups(pathUtf8.substr(3), '\\'), '\\'); // fix duplicated and forward slashes, resolve relative path, don't touch "\\?" prefix,
+    convertResult = g_charsetConverter.utf8ToW(formedPath, result, false, false, true);
+  }
+  else // pathUtf8 starts from "\\", but not from "\\?\UNC\"
+  { // assume UNC path in form '\\server\share\folder\file.ext'
+    std::string formedPath("\\\\?\\UNC"); // append "\\?\UNC" prefix
+    formedPath += URIUtils::CanonicalizePath(URIUtils::FixSlashesAndDups(pathUtf8), '\\'); // fix duplicated and forward slashes, resolve relative path, transform "\\" prefix to single "\"
+    convertResult = g_charsetConverter.utf8ToW(formedPath, result, false, false, true);
+  }
+
+  if (!convertResult)
+  {
+    CLog::Log(LOGERROR, "Error converting path \"%s\" to Win32 wide string!", pathUtf8.c_str());
+    return L"";
+  }
+
+  return result;
+}
+
+std::wstring CWIN32Util::ConvertPathToWin32Form(const CURL& url)
+{
+  assert(url.GetProtocol().empty() || url.IsProtocol("smb"));
+
+  if (url.GetFileName().empty())
+    return std::wstring(); // empty string
+
+  if (url.GetProtocol().empty())
+  {
+    std::wstring result;
+    if (g_charsetConverter.utf8ToW("\\\\?\\" +
+          URIUtils::CanonicalizePath(URIUtils::FixSlashesAndDups(url.GetFileName(), '\\'), '\\'), result, false, false, true))
+      return result;
+  }
+  else if (url.IsProtocol("smb"))
+  {
+    if (url.GetHostName().empty())
+      return std::wstring(); // empty string
+    
+    std::wstring result;
+    if (g_charsetConverter.utf8ToW("\\\\?\\UNC\\" +
+          URIUtils::CanonicalizePath(URIUtils::FixSlashesAndDups(url.GetHostName() + '\\' + url.GetFileName(), '\\'), '\\'),
+          result, false, false, true))
+      return result;
+  }
+  else
+    return std::wstring(); // unsupported protocol, return empty string
+
+  CLog::Log(LOGERROR, "%s: Error converting path \"%s\" to Win32 form", __FUNCTION__, url.Get().c_str());
+  return std::wstring(); // empty string
+}
+
+__time64_t CWIN32Util::fileTimeToTimeT(const FILETIME& ftimeft)
+{
+  if (!ftimeft.dwHighDateTime && !ftimeft.dwLowDateTime)
+    return 0;
+
+  return fileTimeToTimeT((__int64(ftimeft.dwHighDateTime) << 32) + __int64(ftimeft.dwLowDateTime));
+}
+
+__time64_t CWIN32Util::fileTimeToTimeT(const LARGE_INTEGER& ftimeli)
+{
+  if (ftimeli.QuadPart == 0)
+    return 0;
+
+  return fileTimeToTimeT(__int64(ftimeli.QuadPart));
+}
+
+
+HRESULT CWIN32Util::ToggleTray(const char cDriveLetter)
+{
+  BOOL bRet= FALSE;
+  DWORD dwReq = 0;
+  char cDL = cDriveLetter;
+  if( !cDL )
+  {
+    std::string dvdDevice = g_mediaManager.TranslateDevicePath("");
+    if(dvdDevice == "")
+      return S_FALSE;
+    cDL = dvdDevice[0];
+  }
+
+  std::string strVolFormat = StringUtils::Format("\\\\.\\%c:", cDL);
+  HANDLE hDrive= CreateFile( strVolFormat.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+                             NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+  std::string strRootFormat = StringUtils::Format("%c:\\", cDL);
+  if( ( hDrive != INVALID_HANDLE_VALUE || GetLastError() == NO_ERROR) &&
+    ( GetDriveType( strRootFormat.c_str() ) == DRIVE_CDROM ) )
+  {
+    DWORD dwDummy;
+    dwReq = (GetDriveStatus(strVolFormat, true) == 1) ? IOCTL_STORAGE_LOAD_MEDIA : IOCTL_STORAGE_EJECT_MEDIA;
+    bRet = DeviceIoControl( hDrive, dwReq, NULL, 0, NULL, 0, &dwDummy, NULL);
+  }
+  // Windows doesn't seem to send always DBT_DEVICEREMOVECOMPLETE
+  // unmount it here too as it won't hurt
+  if(dwReq == IOCTL_STORAGE_EJECT_MEDIA && bRet == 1)
+  {
+    strRootFormat = StringUtils::Format("%c:", cDL);
+    CMediaSource share;
+    share.strPath = strRootFormat;
+    share.strName = share.strPath;
+    g_mediaManager.RemoveAutoSource(share);
+  }
+  CloseHandle(hDrive);
+  return bRet? S_OK : S_FALSE;
+}
+
+HRESULT CWIN32Util::EjectTray(const char cDriveLetter)
+{
+  char cDL = cDriveLetter;
+  if( !cDL )
+  {
+    std::string dvdDevice = g_mediaManager.TranslateDevicePath("");
+    if(dvdDevice.empty())
+      return S_FALSE;
+    cDL = dvdDevice[0];
+  }
+
+  std::string strVolFormat = StringUtils::Format("\\\\.\\%c:", cDL);
+
+  if(GetDriveStatus(strVolFormat, true) != 1)
+    return ToggleTray(cDL);
+  else
+    return S_OK;
+}
+
+HRESULT CWIN32Util::CloseTray(const char cDriveLetter)
+{
+  char cDL = cDriveLetter;
+  if( !cDL )
+  {
+    std::string dvdDevice = g_mediaManager.TranslateDevicePath("");
+    if(dvdDevice.empty())
+      return S_FALSE;
+    cDL = dvdDevice[0];
+  }
+
+  std::string strVolFormat = StringUtils::Format( "\\\\.\\%c:", cDL);
+
+  if(GetDriveStatus(strVolFormat, true) == 1)
+    return ToggleTray(cDL);
+  else
+    return S_OK;
+}
+
+// safe removal of USB drives:
+// http://www.codeproject.com/KB/system/RemoveDriveByLetter.aspx
+// http://www.techtalkz.com/microsoft-device-drivers/250734-remove-usb-device-c-3.html
+
+DEVINST CWIN32Util::GetDrivesDevInstByDiskNumber(long DiskNumber)
+{
+
+  GUID* guid = (GUID*)(void*)&GUID_DEVINTERFACE_DISK;
+
+  // Get device interface info set handle for all devices attached to system
+  HDEVINFO hDevInfo = SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+
+  if (hDevInfo == INVALID_HANDLE_VALUE)
+    return 0;
+
+  // Retrieve a context structure for a device interface of a device
+  // information set.
+  DWORD dwIndex = 0;
+  SP_DEVICE_INTERFACE_DATA devInterfaceData = {0};
+  devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+  BOOL bRet = FALSE;
+
+  PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd;
+  SP_DEVICE_INTERFACE_DATA spdid;
+  SP_DEVINFO_DATA spdd;
+  DWORD dwSize;
+
+  spdid.cbSize = sizeof(spdid);
+
+  while ( true )
+  {
+    bRet = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, guid, dwIndex, &devInterfaceData);
+    if (!bRet)
+      break;
+
+    SetupDiEnumInterfaceDevice(hDevInfo, NULL, guid, dwIndex, &spdid);
+
+    dwSize = 0;
+    SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, NULL, 0, &dwSize, NULL);
+
+    if ( dwSize )
+    {
+      pspdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
+      if ( pspdidd == NULL )
+        continue;
+
+      pspdidd->cbSize = sizeof(*pspdidd);
+      ZeroMemory((PVOID)&spdd, sizeof(spdd));
+      spdd.cbSize = sizeof(spdd);
+
+      long res = SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid,
+      pspdidd, dwSize, &dwSize, &spdd);
+      if ( res )
+      {
+        HANDLE hDrive = CreateFile(pspdidd->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
+        if ( hDrive != INVALID_HANDLE_VALUE )
+        {
+          STORAGE_DEVICE_NUMBER sdn;
+          DWORD dwBytesReturned = 0;
+          res = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL);
+          if ( res )
+          {
+            if ( DiskNumber == (long)sdn.DeviceNumber )
+            {
+              CloseHandle(hDrive);
+              SetupDiDestroyDeviceInfoList(hDevInfo);
+              return spdd.DevInst;
+            }
+          }
+          CloseHandle(hDrive);
+        }
+      }
+      HeapFree(GetProcessHeap(), 0, pspdidd);
+    }
+    dwIndex++;
+  }
+  SetupDiDestroyDeviceInfoList(hDevInfo);
+  return 0;
+}
+
+bool CWIN32Util::EjectDrive(const char cDriveLetter)
+{
+  if( !cDriveLetter )
+    return false;
+
+  std::string strVolFormat = StringUtils::Format("\\\\.\\%c:", cDriveLetter);
+
+  long DiskNumber = -1;
+
+  HANDLE hVolume = CreateFile(strVolFormat.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
+  if (hVolume == INVALID_HANDLE_VALUE)
+    return false;
+
+  STORAGE_DEVICE_NUMBER sdn;
+  DWORD dwBytesReturned = 0;
+  long res = DeviceIoControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER,NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL);
+  CloseHandle(hVolume);
+  if ( res )
+    DiskNumber = sdn.DeviceNumber;
+  else
+    return false;
+
+  DEVINST DevInst = GetDrivesDevInstByDiskNumber(DiskNumber);
+
+  if ( DevInst == 0 )
+    return false;
+
+  ULONG Status = 0;
+  ULONG ProblemNumber = 0;
+  PNP_VETO_TYPE VetoType = PNP_VetoTypeUnknown;
+  char VetoName[MAX_PATH];
+  bool bSuccess = false;
+
+  CM_Get_Parent(&DevInst, DevInst, 0); // disk's parent, e.g. the USB bridge, the SATA controller....
+  CM_Get_DevNode_Status(&Status, &ProblemNumber, DevInst, 0);
+
+  for(int i=0;i<3;i++)
+  {
+    res = CM_Request_Device_Eject(DevInst, &VetoType, VetoName, MAX_PATH, 0);
+    bSuccess = (res==CR_SUCCESS && VetoType==PNP_VetoTypeUnknown);
+   if ( bSuccess )
+    break;
+  }
+
+  return bSuccess;
+}
+
+#ifdef HAS_GL
+void CWIN32Util::CheckGLVersion()
+{
+  if(CWIN32Util::HasGLDefaultDrivers())
+  {
+    MessageBox(NULL, "MS default OpenGL drivers detected. Please get OpenGL drivers from your video card vendor", "XBMC: Fatal Error", MB_OK|MB_ICONERROR);
+    exit(1);
+  }
+
+  if(!CWIN32Util::HasReqGLVersion())
+  {
+    if(MessageBox(NULL, "Your OpenGL version doesn't meet the XBMC requirements", "XBMC: Warning", MB_OKCANCEL|MB_ICONWARNING) == IDCANCEL)
+    {
+      exit(1);
+    }
+  }
+}
+
+bool CWIN32Util::HasGLDefaultDrivers()
+{
+  unsigned int a=0,b=0;
+
+  std::string strVendor = g_Windowing.GetRenderVendor();
+  g_Windowing.GetRenderVersion(a, b);
+
+  if(strVendor.find("Microsoft")!=strVendor.npos && a==1 && b==1)
+    return true;
+  else
+    return false;
+}
+
+bool CWIN32Util::HasReqGLVersion()
+{
+  unsigned int a=0,b=0;
+
+  g_Windowing.GetRenderVersion(a, b);
+  if((a>=2) || (a == 1 && b >= 3))
+    return true;
+  else
+    return false;
+}
+#endif
+
+BOOL CWIN32Util::IsCurrentUserLocalAdministrator()
+{
+  BOOL b;
+  SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
+  PSID AdministratorsGroup;
+  b = AllocateAndInitializeSid(
+      &NtAuthority,
+      2,
+      SECURITY_BUILTIN_DOMAIN_RID,
+      DOMAIN_ALIAS_RID_ADMINS,
+      0, 0, 0, 0, 0, 0,
+      &AdministratorsGroup);
+  if(b)
+  {
+    if (!CheckTokenMembership( NULL, AdministratorsGroup, &b))
+    {
+         b = FALSE;
+    }
+    FreeSid(AdministratorsGroup);
+  }
+
+  return(b);
+}
+
+void CWIN32Util::GetDrivesByType(VECSOURCES &localDrives, Drive_Types eDriveType, bool bonlywithmedia)
+{
+  WCHAR* pcBuffer= NULL;
+  DWORD dwStrLength= GetLogicalDriveStringsW( 0, pcBuffer );
+  if( dwStrLength != 0 )
+  {
+    CMediaSource share;
+
+    dwStrLength+= 1;
+    pcBuffer= new WCHAR [dwStrLength];
+    GetLogicalDriveStringsW( dwStrLength, pcBuffer );
+
+    int iPos= 0;
+    WCHAR cVolumeName[100];
+    do{
+      int nResult = 0;
+      cVolumeName[0]= L'\0';
+
+      std::wstring strWdrive = pcBuffer + iPos;
+
+      UINT uDriveType= GetDriveTypeW( strWdrive.c_str()  );
+      // don't use GetVolumeInformation on fdd's as the floppy controller may be enabled in Bios but
+      // no floppy HW is attached which causes huge delays.
+      if(strWdrive.size() >= 2 && strWdrive.substr(0,2) != L"A:" && strWdrive.substr(0,2) != L"B:")
+        nResult= GetVolumeInformationW( strWdrive.c_str() , cVolumeName, 100, 0, 0, 0, NULL, 25);
+      if(nResult == 0 && bonlywithmedia)
+      {
+        iPos += (wcslen( pcBuffer + iPos) + 1 );
+        continue;
+      }
+
+      // usb hard drives are reported as DRIVE_FIXED and won't be returned by queries with REMOVABLE_DRIVES set
+      // so test for usb hard drives
+      /*if(uDriveType == DRIVE_FIXED)
+      {
+        if(IsUsbDevice(strWdrive))
+          uDriveType = DRIVE_REMOVABLE;
+      }*/
+
+      share.strPath= share.strName= "";
+
+      bool bUseDCD= false;
+      if( uDriveType > DRIVE_UNKNOWN &&
+        (( eDriveType == ALL_DRIVES && (uDriveType == DRIVE_FIXED || uDriveType == DRIVE_REMOTE || uDriveType == DRIVE_CDROM || uDriveType == DRIVE_REMOVABLE )) ||
+         ( eDriveType == LOCAL_DRIVES && (uDriveType == DRIVE_FIXED || uDriveType == DRIVE_REMOTE)) ||
+         ( eDriveType == REMOVABLE_DRIVES && ( uDriveType == DRIVE_REMOVABLE )) ||
+         ( eDriveType == DVD_DRIVES && ( uDriveType == DRIVE_CDROM ))))
+      {
+        //share.strPath = strWdrive;
+        g_charsetConverter.wToUTF8(strWdrive, share.strPath);
+        if( cVolumeName[0] != L'\0' )
+          g_charsetConverter.wToUTF8(cVolumeName, share.strName);
+        if( uDriveType == DRIVE_CDROM && nResult)
+        {
+          // Has to be the same as auto mounted devices
+          share.strStatus = share.strName;
+          share.strName = share.strPath;
+          share.m_iDriveType= CMediaSource::SOURCE_TYPE_LOCAL;
+          bUseDCD= true;
+        }
+        else
+        {
+          // Lets show it, like Windows explorer do...
+          //! @todo Sorting should depend on driver letter
+          switch(uDriveType)
+          {
+          case DRIVE_CDROM:
+            share.strName = StringUtils::Format( "%s (%s)", share.strPath.c_str(), g_localizeStrings.Get(218).c_str());
+            break;
+          case DRIVE_REMOVABLE:
+            if(share.strName.empty())
+              share.strName = StringUtils::Format( "%s (%s)", g_localizeStrings.Get(437).c_str(), share.strPath.c_str());
+            break;
+          case DRIVE_UNKNOWN:
+            share.strName = StringUtils::Format( "%s (%s)", share.strPath.c_str(), g_localizeStrings.Get(13205).c_str());
+            break;
+          default:
+            if(share.strName.empty())
+              share.strName = share.strPath;
+            else
+              share.strName = StringUtils::Format( "%s (%s)", share.strPath.c_str(), share.strName.c_str());
+            break;
+          }
+        }
+        StringUtils::Replace(share.strName, ":\\", ":");
+        StringUtils::Replace(share.strPath, ":\\", ":");
+        share.m_ignore= true;
+        if( !bUseDCD )
+        {
+          share.m_iDriveType= (
+           ( uDriveType == DRIVE_FIXED  )    ? CMediaSource::SOURCE_TYPE_LOCAL :
+           ( uDriveType == DRIVE_REMOTE )    ? CMediaSource::SOURCE_TYPE_REMOTE :
+           ( uDriveType == DRIVE_CDROM  )    ? CMediaSource::SOURCE_TYPE_DVD :
+           ( uDriveType == DRIVE_REMOVABLE ) ? CMediaSource::SOURCE_TYPE_REMOVABLE :
+             CMediaSource::SOURCE_TYPE_UNKNOWN );
+        }
+
+        AddOrReplace(localDrives, share);
+      }
+      iPos += (wcslen( pcBuffer + iPos) + 1 );
+    } while( wcslen( pcBuffer + iPos ) > 0 );
+    delete[] pcBuffer;
+  }
+}
+
+std::string CWIN32Util::GetFirstOpticalDrive()
+{
+  VECSOURCES vShare;
+  std::string strdevice = "\\\\.\\";
+  CWIN32Util::GetDrivesByType(vShare, DVD_DRIVES);
+  if(!vShare.empty())
+    return strdevice.append(vShare.front().strPath);
+  else
+    return "";
+}
+
+extern "C"
+{
+  FILE *fopen_utf8(const char *_Filename, const char *_Mode)
+  {
+    std::string modetmp = _Mode;
+    std::wstring wfilename, wmode(modetmp.begin(), modetmp.end());
+    g_charsetConverter.utf8ToW(_Filename, wfilename, false);
+    return _wfopen(wfilename.c_str(), wmode.c_str());
+  }
+}
+
+extern "C" {
+  /*
+   * Ported from NetBSD to Windows by Ron Koenderink, 2007
+   */
+
+  /*  $NetBSD: strptime.c,v 1.25 2005/11/29 03:12:00 christos Exp $  */
+
+  /*-
+   * Copyright (c) 1997, 1998, 2005 The NetBSD Foundation, Inc.
+   * All rights reserved.
+   *
+   * This code was contributed to The NetBSD Foundation by Klaus Klein.
+   * Heavily optimised by David Laight
+   *
+   * Redistribution and use in source and binary forms, with or without
+   * modification, are permitted provided that the following conditions
+   * are met:
+   * 1. Redistributions of source code must retain the above copyright
+   *    notice, this list of conditions and the following disclaimer.
+   * 2. Redistributions in binary form must reproduce the above copyright
+   *    notice, this list of conditions and the following disclaimer in the
+   *    documentation and/or other materials provided with the distribution.
+   * 3. All advertising materials mentioning features or use of this software
+   *    must display the following acknowledgement:
+   *        This product includes software developed by the NetBSD
+   *        Foundation, Inc. and its contributors.
+   * 4. Neither the name of The NetBSD Foundation nor the names of its
+   *    contributors may be used to endorse or promote products derived
+   *    from this software without specific prior written permission.
+   *
+   * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+   * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+   * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+   * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   * POSSIBILITY OF SUCH DAMAGE.
+   */
+
+  #if !defined(TARGET_WINDOWS)
+  #include <sys/cdefs.h>
+  #endif
+
+  #if defined(LIBC_SCCS) && !defined(lint)
+  __RCSID("$NetBSD: strptime.c,v 1.25 2005/11/29 03:12:00 christos Exp $");
+  #endif
+
+  #if !defined(TARGET_WINDOWS)
+  #include "namespace.h"
+  #include <sys/localedef.h>
+  #else
+  typedef unsigned char u_char;
+  typedef unsigned int uint;
+  #endif
+  #include <ctype.h>
+  #include <locale.h>
+  #include <string.h>
+  #include <time.h>
+  #if !defined(TARGET_WINDOWS)
+  #include <tzfile.h>
+  #endif
+
+  #ifdef __weak_alias
+  __weak_alias(strptime,_strptime)
+  #endif
+
+  #if !defined(TARGET_WINDOWS)
+  #define  _ctloc(x)    (_CurrentTimeLocale->x)
+  #else
+  #define _ctloc(x)   (x)
+  const char *abday[] = {
+    "Sun", "Mon", "Tue", "Wed",
+    "Thu", "Fri", "Sat"
+  };
+  const char *day[] = {
+    "Sunday", "Monday", "Tuesday", "Wednesday",
+    "Thursday", "Friday", "Saturday"
+  };
+  const char *abmon[] =  {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+  };
+  const char *mon[] = {
+    "January", "February", "March", "April", "May", "June",
+    "July", "August", "September", "October", "November", "December"
+  };
+  const char *am_pm[] = {
+    "AM", "PM"
+  };
+  char *d_t_fmt = "%a %Ef %T %Y";
+  char *t_fmt_ampm = "%I:%M:%S %p";
+  char *t_fmt = "%H:%M:%S";
+  char *d_fmt = "%m/%d/%y";
+  #define TM_YEAR_BASE 1900
+  #define __UNCONST(x) ((char *)(((const char *)(x) - (const char *)0) + (char *)0))
+
+  #endif
+  /*
+   * We do not implement alternate representations. However, we always
+   * check whether a given modifier is allowed for a certain conversion.
+   */
+  #define ALT_E      0x01
+  #define ALT_O      0x02
+  #define  LEGAL_ALT(x)    { if (alt_format & ~(x)) return NULL; }
+
+
+  static const u_char *conv_num(const unsigned char *, int *, uint, uint);
+  static const u_char *find_string(const u_char *, int *, const char * const *,
+    const char * const *, int);
+
+
+  char *
+  strptime(const char *buf, const char *fmt, struct tm *tm)
+  {
+    unsigned char c;
+    const unsigned char *bp;
+    int alt_format, i, split_year = 0;
+    const char *new_fmt;
+
+    bp = (const u_char *)buf;
+
+    while (bp != NULL && (c = *fmt++) != '\0') {
+      /* Clear `alternate' modifier prior to new conversion. */
+      alt_format = 0;
+      i = 0;
+
+      /* Eat up white-space. */
+      if (isspace(c)) {
+        while (isspace(*bp))
+          bp++;
+        continue;
+      }
+
+      if (c != '%')
+        goto literal;
+
+
+  again:    switch (c = *fmt++) {
+      case '%':  /* "%%" is converted to "%". */
+  literal:
+        if (c != *bp++)
+          return NULL;
+        LEGAL_ALT(0);
+        continue;
+
+      /*
+       * "Alternative" modifiers. Just set the appropriate flag
+       * and start over again.
+       */
+      case 'E':  /* "%E?" alternative conversion modifier. */
+        LEGAL_ALT(0);
+        alt_format |= ALT_E;
+        goto again;
+
+      case 'O':  /* "%O?" alternative conversion modifier. */
+        LEGAL_ALT(0);
+        alt_format |= ALT_O;
+        goto again;
+
+      /*
+       * "Complex" conversion rules, implemented through recursion.
+       */
+      case 'c':  /* Date and time, using the locale's format. */
+        new_fmt = _ctloc(d_t_fmt);
+        goto recurse;
+
+      case 'D':  /* The date as "%m/%d/%y". */
+        new_fmt = "%m/%d/%y";
+        LEGAL_ALT(0);
+        goto recurse;
+
+      case 'R':  /* The time as "%H:%M". */
+        new_fmt = "%H:%M";
+        LEGAL_ALT(0);
+        goto recurse;
+
+      case 'r':  /* The time in 12-hour clock representation. */
+        new_fmt =_ctloc(t_fmt_ampm);
+        LEGAL_ALT(0);
+        goto recurse;
+
+      case 'T':  /* The time as "%H:%M:%S". */
+        new_fmt = "%H:%M:%S";
+        LEGAL_ALT(0);
+        goto recurse;
+
+      case 'X':  /* The time, using the locale's format. */
+        new_fmt =_ctloc(t_fmt);
+        goto recurse;
+
+      case 'x':  /* The date, using the locale's format. */
+        new_fmt =_ctloc(d_fmt);
+          recurse:
+        bp = (const u_char *)strptime((const char *)bp,
+                    new_fmt, tm);
+        LEGAL_ALT(ALT_E);
+        continue;
+
+      /*
+       * "Elementary" conversion rules.
+       */
+      case 'A':  /* The day of week, using the locale's form. */
+      case 'a':
+        bp = find_string(bp, &tm->tm_wday, _ctloc(day),
+            _ctloc(abday), 7);
+        LEGAL_ALT(0);
+        continue;
+
+      case 'B':  /* The month, using the locale's form. */
+      case 'b':
+      case 'h':
+        bp = find_string(bp, &tm->tm_mon, _ctloc(mon),
+            _ctloc(abmon), 12);
+        LEGAL_ALT(0);
+        continue;
+
+      case 'C':  /* The century number. */
+        i = 20;
+        bp = conv_num(bp, &i, 0, 99);
+
+        i = i * 100 - TM_YEAR_BASE;
+        if (split_year)
+          i += tm->tm_year % 100;
+        split_year = 1;
+        tm->tm_year = i;
+        LEGAL_ALT(ALT_E);
+        continue;
+
+      case 'd':  /* The day of month. */
+      case 'e':
+        bp = conv_num(bp, &tm->tm_mday, 1, 31);
+        LEGAL_ALT(ALT_O);
+        continue;
+
+      case 'k':  /* The hour (24-hour clock representation). */
+        LEGAL_ALT(0);
+        /* FALLTHROUGH */
+      case 'H':
+        bp = conv_num(bp, &tm->tm_hour, 0, 23);
+        LEGAL_ALT(ALT_O);
+        continue;
+
+      case 'l':  /* The hour (12-hour clock representation). */
+        LEGAL_ALT(0);
+        /* FALLTHROUGH */
+      case 'I':
+        bp = conv_num(bp, &tm->tm_hour, 1, 12);
+        if (tm->tm_hour == 12)
+          tm->tm_hour = 0;
+        LEGAL_ALT(ALT_O);
+        continue;
+
+      case 'j':  /* The day of year. */
+        i = 1;
+        bp = conv_num(bp, &i, 1, 366);
+        tm->tm_yday = i - 1;
+        LEGAL_ALT(0);
+        continue;
+
+      case 'M':  /* The minute. */
+        bp = conv_num(bp, &tm->tm_min, 0, 59);
+        LEGAL_ALT(ALT_O);
+        continue;
+
+      case 'm':  /* The month. */
+        i = 1;
+        bp = conv_num(bp, &i, 1, 12);
+        tm->tm_mon = i - 1;
+        LEGAL_ALT(ALT_O);
+        continue;
+
+      case 'p':  /* The locale's equivalent of AM/PM. */
+        bp = find_string(bp, &i, _ctloc(am_pm), NULL, 2);
+        if (tm->tm_hour > 11)
+          return NULL;
+        tm->tm_hour += i * 12;
+        LEGAL_ALT(0);
+        continue;
+
+      case 'S':  /* The seconds. */
+        bp = conv_num(bp, &tm->tm_sec, 0, 61);
+        LEGAL_ALT(ALT_O);
+        continue;
+
+      case 'U':  /* The week of year, beginning on sunday. */
+      case 'W':  /* The week of year, beginning on monday. */
+        /*
+         * XXX This is bogus, as we can not assume any valid
+         * information present in the tm structure at this
+         * point to calculate a real value, so just check the
+         * range for now.
+         */
+         bp = conv_num(bp, &i, 0, 53);
+         LEGAL_ALT(ALT_O);
+         continue;
+
+      case 'w':  /* The day of week, beginning on sunday. */
+        bp = conv_num(bp, &tm->tm_wday, 0, 6);
+        LEGAL_ALT(ALT_O);
+        continue;
+
+      case 'Y':  /* The year. */
+        i = TM_YEAR_BASE;  /* just for data sanity... */
+        bp = conv_num(bp, &i, 0, 9999);
+        tm->tm_year = i - TM_YEAR_BASE;
+        LEGAL_ALT(ALT_E);
+        continue;
+
+      case 'y':  /* The year within 100 years of the epoch. */
+        /* LEGAL_ALT(ALT_E | ALT_O); */
+        bp = conv_num(bp, &i, 0, 99);
+
+        if (split_year)
+          /* preserve century */
+          i += (tm->tm_year / 100) * 100;
+        else {
+          split_year = 1;
+          if (i <= 68)
+            i = i + 2000 - TM_YEAR_BASE;
+          else
+            i = i + 1900 - TM_YEAR_BASE;
+        }
+        tm->tm_year = i;
+        continue;
+
+      /*
+       * Miscellaneous conversions.
+       */
+      case 'n':  /* Any kind of white-space. */
+      case 't':
+        while (isspace(*bp))
+          bp++;
+        LEGAL_ALT(0);
+        continue;
+
+
+      default:  /* Unknown/unsupported conversion. */
+        return NULL;
+      }
+    }
+
+    return __UNCONST(bp);
+  }
+
+
+  static const u_char *
+  conv_num(const unsigned char *buf, int *dest, uint llim, uint ulim)
+  {
+    uint result = 0;
+    unsigned char ch;
+
+    /* The limit also determines the number of valid digits. */
+    uint rulim = ulim;
+
+    ch = *buf;
+    if (ch < '0' || ch > '9')
+      return NULL;
+
+    do {
+      result *= 10;
+      result += ch - '0';
+      rulim /= 10;
+      ch = *++buf;
+    } while ((result * 10 <= ulim) && rulim && ch >= '0' && ch <= '9');
+
+    if (result < llim || result > ulim)
+      return NULL;
+
+    *dest = result;
+    return buf;
+  }
+
+  static const u_char *
+  find_string(const u_char *bp, int *tgt, const char * const *n1,
+      const char * const *n2, int c)
+  {
+    int i;
+    unsigned int len;
+
+    /* check full name - then abbreviated ones */
+    for (; n1 != NULL; n1 = n2, n2 = NULL) {
+      for (i = 0; i < c; i++, n1++) {
+        len = strlen(*n1);
+        if (strnicmp(*n1, (const char *)bp, len) == 0) {
+          *tgt = i;
+          return bp + len;
+        }
+      }
+    }
+
+    /* Nothing matched */
+    return NULL;
+  }
+}
+
+
+LONG CWIN32Util::UtilRegGetValue( const HKEY hKey, const char *const pcKey, DWORD *const pdwType, char **const ppcBuffer, DWORD *const pdwSizeBuff, const DWORD dwSizeAdd )
+{
+  DWORD dwSize;
+  LONG lRet= RegQueryValueEx(hKey, pcKey, NULL, pdwType, NULL, &dwSize );
+  if (lRet == ERROR_SUCCESS)
+  {
+    if (ppcBuffer)
+    {
+      char *pcValue=*ppcBuffer, *pcValueTmp;
+      if (!pcValue || !pdwSizeBuff || dwSize +dwSizeAdd > *pdwSizeBuff) {
+        pcValueTmp = (char*)realloc(pcValue, dwSize +dwSizeAdd);
+        if(pcValueTmp != NULL)
+        {
+          pcValue = pcValueTmp;
+        }
+      }
+      lRet= RegQueryValueEx(hKey,pcKey,NULL,NULL,(LPBYTE)pcValue,&dwSize);
+
+      if ( lRet == ERROR_SUCCESS || *ppcBuffer ) *ppcBuffer= pcValue;
+      else free( pcValue );
+    }
+    if (pdwSizeBuff) *pdwSizeBuff= dwSize +dwSizeAdd;
+  }
+  return lRet;
+}
+
+bool CWIN32Util::UtilRegOpenKeyEx( const HKEY hKeyParent, const char *const pcKey, const REGSAM rsAccessRights, HKEY *hKey, const bool bReadX64 )
+{
+  const REGSAM rsAccessRightsTmp= ( CSysInfo::GetKernelBitness() == 64 ? rsAccessRights | ( bReadX64 ? KEY_WOW64_64KEY : KEY_WOW64_32KEY ) : rsAccessRights );
+  bool bRet= ( ERROR_SUCCESS == RegOpenKeyEx(hKeyParent, pcKey, 0, rsAccessRightsTmp, hKey));
+  return bRet;
+}
+
+// Retrieve the filename of the process that currently has the focus.
+// Typically this will be some process using the system tray grabbing
+// the focus and causing XBMC to minimise. Logging the offending
+// process name can help the user fix the problem.
+bool CWIN32Util::GetFocussedProcess(std::string &strProcessFile)
+{
+  strProcessFile = "";
+
+  // Get the window that has the focus
+  HWND hfocus = GetForegroundWindow();
+  if (!hfocus)
+    return false;
+
+  // Get the process ID from the window handle
+  DWORD pid = 0;
+  GetWindowThreadProcessId(hfocus, &pid);
+
+  // Use OpenProcess to get the process handle from the process ID
+  HANDLE hproc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, pid);
+  if (!hproc)
+    return false;
+
+  // Load QueryFullProcessImageName dynamically because it isn't available
+  // in all versions of Windows.
+  char procfile[MAX_PATH+1];
+  DWORD procfilelen = MAX_PATH;
+
+  HINSTANCE hkernel32 = LoadLibrary("kernel32.dll");
+  if (hkernel32)
+  {
+    DWORD (WINAPI *pQueryFullProcessImageNameA)(HANDLE,DWORD,LPTSTR,PDWORD);
+    pQueryFullProcessImageNameA = (DWORD (WINAPI *)(HANDLE,DWORD,LPTSTR,PDWORD)) GetProcAddress(hkernel32, "QueryFullProcessImageNameA");
+    if (pQueryFullProcessImageNameA)
+      if (pQueryFullProcessImageNameA(hproc, 0, procfile, &procfilelen))
+        strProcessFile = procfile;
+    FreeLibrary(hkernel32);
+  }
+
+  // If QueryFullProcessImageName failed fall back to GetModuleFileNameEx.
+  // Note this does not work across x86-x64 boundaries.
+  if (strProcessFile == "")
+  {
+    HINSTANCE hpsapi = LoadLibrary("psapi.dll");
+    if (hpsapi)
+    {
+      DWORD (WINAPI *pGetModuleFileNameExA)(HANDLE,HMODULE,LPTSTR,DWORD);
+      pGetModuleFileNameExA = (DWORD (WINAPI*)(HANDLE,HMODULE,LPTSTR,DWORD)) GetProcAddress(hpsapi, "GetModuleFileNameExA");
+      if (pGetModuleFileNameExA)
+        if (pGetModuleFileNameExA(hproc, NULL, procfile, MAX_PATH))
+          strProcessFile = procfile;
+      FreeLibrary(hpsapi);
+    }
+  }
+
+  CloseHandle(hproc);
+
+  return true;
+}
+
+// Adjust the src rectangle so that the dst is always contained in the target rectangle.
+void CWIN32Util::CropSource(CRect& src, CRect& dst, CRect target, UINT rotation /* = 0 */)
+{
+  float s_width = src.Width(), s_height = src.Height();
+  float d_width = dst.Width(), d_height = dst.Height();
+
+  if (dst.x1 < target.x1)
+  {
+    switch (rotation)
+    {
+    case 90:
+      src.y1 -= (dst.x1 - target.x1) * s_height / d_width;
+      break;
+    case 180:
+      src.x2 += (dst.x1 - target.x1) * s_width  / d_width;
+      break;
+    case 270:
+      src.y2 += (dst.x1 - target.x1) * s_height / d_width;
+      break;
+    default:
+      src.x1 -= (dst.x1 - target.x1) * s_width  / d_width;
+      break;
+    }
+    dst.x1  = target.x1;
+  }
+  if(dst.y1 < target.y1)
+  {
+    switch (rotation)
+    {
+    case 90:
+      src.x1 -= (dst.y1 - target.y1) * s_width  / d_height;
+      break;
+    case 180:
+      src.y2 += (dst.y1 - target.y1) * s_height / d_height;
+      break;
+    case 270:
+      src.x2 += (dst.y1 - target.y1) * s_width  / d_height;
+      break;
+    default:
+      src.y1 -= (dst.y1 - target.y1) * s_height / d_height;
+      break;
+    }
+    dst.y1  = target.y1;
+  }
+  if(dst.x2 > target.x2)
+  {
+    switch (rotation)
+    {
+    case 90:
+      src.y2 -= (dst.x2 - target.x2) * s_height / d_width;
+      break;
+    case 180:
+      src.x1 += (dst.x2 - target.x2) * s_width  / d_width;
+      break;
+    case 270:
+      src.y1 += (dst.x2 - target.x2) * s_height / d_width;
+      break;
+    default:
+      src.x2 -= (dst.x2 - target.x2) * s_width  / d_width;
+      break;
+    }
+    dst.x2  = target.x2;
+  }
+  if(dst.y2 > target.y2)
+  {
+    switch (rotation)
+    {
+    case 90:
+      src.x2 -= (dst.y2 - target.y2) * s_width / d_height;
+      break;
+    case 180:
+      src.y1 += (dst.y2 - target.y2) * s_height / d_height;
+      break;
+    case 270:
+      src.x1 += (dst.y2 - target.y2) * s_width / d_height;
+      break;
+    default:
+      src.y2 -= (dst.y2 - target.y2) * s_height / d_height;
+      break;
+    }
+    dst.y2  = target.y2;
+  }
+  // Callers expect integer coordinates.
+  src.x1 = floor(src.x1);
+  src.y1 = floor(src.y1);
+  src.x2 = ceil(src.x2);
+  src.y2 = ceil(src.y2);
+  dst.x1 = floor(dst.x1);
+  dst.y1 = floor(dst.y1);
+  dst.x2 = ceil(dst.x2);
+  dst.y2 = ceil(dst.y2);
+}
+
+void CWinIdleTimer::StartZero()
+{
+  if (!g_application.IsDPMSActive())
+    SetThreadExecutionState(ES_SYSTEM_REQUIRED|ES_DISPLAY_REQUIRED);
+  CStopWatch::StartZero();
+}
+
+extern "C"
+{
+  /* case-independent string matching, similar to strstr but
+  * matching */
+  char * strcasestr(const char* haystack, const char* needle)
+  {
+    int i;
+    int nlength = (int) strlen (needle);
+    int hlength = (int) strlen (haystack);
+
+    if (nlength > hlength) return NULL;
+    if (hlength <= 0) return NULL;
+    if (nlength <= 0) return (char *)haystack;
+    /* hlength and nlength > 0, nlength <= hlength */
+    for (i = 0; i <= (hlength - nlength); i++)
+    {
+      if (strncasecmp (haystack + i, needle, nlength) == 0)
+      {
+        return (char *)haystack + i;
+      }
+    }
+    /* substring not found */
+    return NULL;
+  }
+}
+
+// detect if a drive is a usb device
+// code taken from http://banderlogi.blogspot.com/2011/06/enum-drive-letters-attached-for-usb.html
+
+bool CWIN32Util::IsUsbDevice(const std::wstring &strWdrive)
+{
+  if (strWdrive.size() < 2)
+    return false;
+
+  std::wstring strWDevicePath = StringUtils::Format(L"\\\\.\\%s",strWdrive.substr(0, 2).c_str());
+
+  HANDLE deviceHandle = CreateFileW(
+    strWDevicePath.c_str(),
+   0,                // no access to the drive
+   FILE_SHARE_READ | // share mode
+   FILE_SHARE_WRITE,
+   NULL,             // default security attributes
+   OPEN_EXISTING,    // disposition
+   0,                // file attributes
+   NULL);            // do not copy file attributes
+
+  if(deviceHandle == INVALID_HANDLE_VALUE)
+    return false;
+
+  // setup query
+  STORAGE_PROPERTY_QUERY query;
+  memset(&query, 0, sizeof(query));
+  query.PropertyId = StorageDeviceProperty;
+  query.QueryType = PropertyStandardQuery;
+
+  // issue query
+  DWORD bytes;
+  STORAGE_DEVICE_DESCRIPTOR devd;
+  STORAGE_BUS_TYPE busType = BusTypeUnknown;
+
+  if (DeviceIoControl(deviceHandle,
+   IOCTL_STORAGE_QUERY_PROPERTY,
+   &query, sizeof(query),
+   &devd, sizeof(devd),
+   &bytes, NULL))
+  {
+   busType = devd.BusType;
+  }
+
+  CloseHandle(deviceHandle);
+
+  return BusTypeUsb == busType;
+ }
+
+std::string CWIN32Util::WUSysMsg(DWORD dwError)
+{
+  #define SS_DEFLANGID MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT)
+  CHAR szBuf[512];
+
+  if ( 0 != ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError,
+                             SS_DEFLANGID, szBuf, 511, NULL) )
+    return StringUtils::Format("%s (0x%X)", szBuf, dwError);
+  else
+    return StringUtils::Format("Unknown error (0x%X)", dwError);
+}
+
+bool CWIN32Util::SetThreadLocalLocale(bool enable /* = true */)
+{
+  const int param = enable ? _ENABLE_PER_THREAD_LOCALE : _DISABLE_PER_THREAD_LOCALE;
+  return CALL_IN_CRTS(_configthreadlocale, param) != -1;
+}
+
diff --git a/xbmc/platform/win32/WIN32Util.h b/xbmc/platform/win32/WIN32Util.h
new file mode 100644
index 0000000..23cbb59
--- /dev/null
+++ b/xbmc/platform/win32/WIN32Util.h
@@ -0,0 +1,109 @@
+#pragma once
+
+/*
+ *      Copyright (C) 2005-2013 Team XBMC
+ *      http://xbmc.org
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <vector>
+
+#include "URL.h"
+#include "Cfgmgr32.h"
+#include "MediaSource.h"
+#include "guilib/Geometry.h"
+#include "powermanagement/PowerManager.h"
+#include "utils/Stopwatch.h"
+
+enum Drive_Types
+{
+  ALL_DRIVES = 0,
+  LOCAL_DRIVES,
+  REMOVABLE_DRIVES,
+  DVD_DRIVES
+};
+
+#define BONJOUR_EVENT             ( WM_USER + 0x100 )	// Message sent to the Window when a Bonjour event occurs.
+#define BONJOUR_BROWSER_EVENT     ( WM_USER + 0x110 )
+
+class CURL; // forward declaration
+
+class CWIN32Util
+{
+public:
+  CWIN32Util(void);
+  virtual ~CWIN32Util(void);
+
+  static char FirstDriveFromMask (ULONG unitmask);
+  static int GetDriveStatus(const std::string &strPath, bool bStatusEx=false);
+  static bool PowerManagement(PowerState State);
+  static int BatteryLevel();
+  static bool XBMCShellExecute(const std::string &strPath, bool bWaitForScriptExit=false);
+  static std::vector<std::string> GetDiskUsage();
+  static std::string GetResInfoString();
+  static int GetDesktopColorDepth();
+  static std::string GetSpecialFolder(int csidl);
+  static std::string GetSystemPath();
+  static std::string GetProfilePath();
+  static std::string UncToSmb(const std::string &strPath);
+  static std::string SmbToUnc(const std::string &strPath);
+  static bool AddExtraLongPathPrefix(std::wstring& path);
+  static bool RemoveExtraLongPathPrefix(std::wstring& path);
+  static std::wstring ConvertPathToWin32Form(const std::string& pathUtf8);
+  static std::wstring ConvertPathToWin32Form(const CURL& url);
+  static inline __time64_t fileTimeToTimeT(const __int64 ftimei64)
+  {
+    // FILETIME is 100-nanoseconds from 00:00:00 UTC 01 Jan 1601
+    // __time64_t is seconds from 00:00:00 UTC 01 Jan 1970
+    return (ftimei64 - 116444736000000000) / 10000000;
+  }
+  static __time64_t fileTimeToTimeT(const FILETIME& ftimeft);
+  static __time64_t fileTimeToTimeT(const LARGE_INTEGER& ftimeli);
+  static HRESULT ToggleTray(const char cDriveLetter='\0');
+  static HRESULT EjectTray(const char cDriveLetter='\0');
+  static HRESULT CloseTray(const char cDriveLetter='\0');
+  static bool EjectDrive(const char cDriveLetter='\0');
+#ifdef HAS_GL
+  static void CheckGLVersion();
+  static bool HasGLDefaultDrivers();
+  static bool HasReqGLVersion();
+#endif
+  static BOOL IsCurrentUserLocalAdministrator();
+  static void GetDrivesByType(VECSOURCES &localDrives, Drive_Types eDriveType=ALL_DRIVES, bool bonlywithmedia=false);
+  static std::string GetFirstOpticalDrive();
+
+  static LONG UtilRegGetValue( const HKEY hKey, const char *const pcKey, DWORD *const pdwType, char **const ppcBuffer, DWORD *const pdwSizeBuff, const DWORD dwSizeAdd );
+  static bool UtilRegOpenKeyEx( const HKEY hKeyParent, const char *const pcKey, const REGSAM rsAccessRights, HKEY *hKey, const bool bReadX64= false );
+
+  static bool GetFocussedProcess(std::string &strProcessFile);
+  static void CropSource(CRect& src, CRect& dst, CRect target, UINT rotation = 0);
+
+  static bool IsUsbDevice(const std::wstring &strWdrive);
+
+  static std::string WUSysMsg(DWORD dwError);
+
+  static bool SetThreadLocalLocale(bool enable = true);
+private:
+  static DEVINST GetDrivesDevInstByDiskNumber(long DiskNumber);
+};
+
+
+class CWinIdleTimer : public CStopWatch
+{
+public:
+  void StartZero();
+};
diff --git a/xbmc/platform/win32/WindowHelper.cpp b/xbmc/platform/win32/WindowHelper.cpp
new file mode 100644
index 0000000..0f6d2a9
--- /dev/null
+++ b/xbmc/platform/win32/WindowHelper.cpp
@@ -0,0 +1,92 @@
+/*
+ *      Copyright (C) 2005-2013 Team XBMC
+ *      http://xbmc.org
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "WindowHelper.h"
+
+extern HWND g_hWnd;
+
+CWHelper g_windowHelper;
+
+CWHelper::CWHelper(void) : CThread("WindowHelper")
+{
+  m_hwnd = NULL;
+  m_hProcess = NULL;
+}
+
+CWHelper::~CWHelper(void)
+{
+  StopThread();
+  m_hwnd = NULL;
+  if(m_hProcess != NULL)
+  {
+    CloseHandle(m_hProcess);
+    m_hProcess = NULL;
+  }
+}
+
+void CWHelper::OnStartup()
+{
+  if((m_hwnd == NULL) && (m_hProcess == NULL))
+    return;
+
+  // Minimize XBMC if not already
+  ShowWindow(g_hWnd,SW_MINIMIZE);
+  if(m_hwnd != NULL)
+    ShowWindow(m_hwnd,SW_RESTORE);
+
+  OutputDebugString("WindowHelper thread started\n");
+}
+
+void CWHelper::OnExit()
+{
+  // Bring back XBMC window
+  ShowWindow(g_hWnd,SW_RESTORE);
+  SetForegroundWindow(g_hWnd);
+  m_hwnd = NULL;
+  if(m_hProcess != NULL)
+  {
+    CloseHandle(m_hProcess);
+    m_hProcess = NULL;
+  }
+  LockSetForegroundWindow(LSFW_LOCK);
+  OutputDebugString("WindowHelper thread ended\n");
+}
+
+void CWHelper::Process()
+{
+  while (( !m_bStop ))
+  {
+    if(WaitForSingleObject(m_hProcess,500) != WAIT_TIMEOUT)
+      break;
+    /*if((m_hwnd != NULL) && (IsIconic(m_hwnd) == TRUE))
+      break;*/
+  }
+}
+
+void CWHelper::SetHWND(HWND hwnd)
+{
+  m_hwnd = hwnd;
+}
+
+void CWHelper::SetHANDLE(HANDLE hProcess)
+{
+  m_hProcess = hProcess;
+}
+
diff --git a/xbmc/utils/Crc32.h b/xbmc/platform/win32/WindowHelper.h
similarity index 71%
copy from xbmc/utils/Crc32.h
copy to xbmc/platform/win32/WindowHelper.h
index 3d30c8f..6faafaf 100644
--- a/xbmc/utils/Crc32.h
+++ b/xbmc/platform/win32/WindowHelper.h
@@ -1,3 +1,5 @@
+#pragma once
+
 /*
  *      Copyright (C) 2005-2013 Team XBMC
  *      http://xbmc.org
@@ -18,26 +20,25 @@
  *
  */
 
-#pragma once
-
-#include <string>
-#include <stdint.h>
+#include "threads/Thread.h"
 
-class Crc32
+class CWHelper: public CThread
 {
 public:
-  Crc32();
-  void Reset();
-  void Compute(const char* buffer, size_t count);
-  void Compute(const std::string& strValue);
-  void ComputeFromLowerCase(const std::string& strValue);
+  CWHelper(void);
+  virtual ~CWHelper(void);
+
+  virtual void OnStartup();
+  virtual void OnExit();
+  virtual void Process();
 
-  operator uint32_t () const
-  {
-    return m_crc;
-  }
+  void SetHWND(HWND hwnd);
+  void SetHANDLE(HANDLE hProcess);
 
 private:
-  uint32_t m_crc;
+  HWND  m_hwnd;
+  HANDLE m_hProcess;
+
 };
 
+extern CWHelper g_windowHelper;
diff --git a/xbmc/platform/win32/XBMC_PC.rc.in b/xbmc/platform/win32/XBMC_PC.rc.in
new file mode 100644
index 0000000..b76f15d
--- /dev/null
+++ b/xbmc/platform/win32/XBMC_PC.rc.in
@@ -0,0 +1,112 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "windows.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE 
+BEGIN
+    "#include ""windows.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION @FILE_VERSION@
+ PRODUCTVERSION @FILE_VERSION@
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904e4"
+        BEGIN
+            VALUE "CompanyName", "@COMPANY_NAME@"
+            VALUE "FileDescription", "@APP_NAME@"
+            VALUE "FileVersion", "@APP_VERSION@"
+            VALUE "InternalName", "@APP_NAME at .exe"
+            VALUE "LegalCopyright", "Copyright (c) @COMPANY_NAME at .  All rights reserved."
+            VALUE "OriginalFilename", "@APP_NAME at .exe"
+            VALUE "ProductName", "@APP_NAME@ for Windows"
+            VALUE "ProductVersion", "@APP_VERSION@"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1252
+    END
+END
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_MAIN_ICON           ICON                    "application.ico"
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
diff --git a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h b/xbmc/platform/win32/arpa/inet.h
similarity index 71%
copy from xbmc/cores/VideoPlayer/Process/ProcessInfo.h
copy to xbmc/platform/win32/arpa/inet.h
index b8a4e46..c3c3b62 100644
--- a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h
+++ b/xbmc/platform/win32/arpa/inet.h
@@ -1,5 +1,5 @@
 /*
- *      Copyright (C) 2005-2016 Team XBMC
+ *      Copyright (C) 2011-2013 Team XBMC
  *      http://xbmc.org
  *
  *  This Program is free software; you can redistribute it and/or modify
@@ -18,17 +18,4 @@
  *
  */
 #pragma once
-
-#include "cores/IPlayer.h"
-
-class CProcessInfo
-{
-public:
-  static CProcessInfo* CreateInstance();
-  virtual ~CProcessInfo();
-  virtual EINTERLACEMETHOD GetFallbackDeintMethod();
-  virtual bool AllowDTSHDDecode();
-
-protected:
-  CProcessInfo();
-};
+#include <sys/socket.h>
diff --git a/xbmc/platform/win32/crts_caller.cpp b/xbmc/platform/win32/crts_caller.cpp
new file mode 100644
index 0000000..a30e0e5
--- /dev/null
+++ b/xbmc/platform/win32/crts_caller.cpp
@@ -0,0 +1,97 @@
+/*
+ *      Copyright (C) 2015 Team Kodi
+ *      http://kodi.tv
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * \file win32\crts_caller.h
+ * \brief Implements crts_caller class for calling same function for all loaded CRTs.
+ * \author Karlson2k
+ */
+
+#include "crts_caller.h"
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif // WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+#include <cassert>
+
+namespace win32_utils
+{
+
+static const wchar_t* const s_listOfCrts[] =
+{
+  { L"msvcrt.dll" },   // Visual Studio 6.0 / MinGW[-w64]
+  { L"msvcr70.dll" },  // Visual Studio 2002
+  { L"msvcr71.dll" },  // Visual Studio 2003
+  { L"msvcr80.dll" },  // Visual Studio 2005
+  { L"msvcr90.dll" },  // Visual Studio 2008
+#ifdef _DEBUG
+  { L"msvcr90d.dll" }, // Visual Studio 2008 (debug)
+#endif
+  { L"msvcr100.dll" }, // Visual Studio 2010
+#ifdef _DEBUG
+  { L"msvcr100d.dll" },// Visual Studio 2010 (debug)
+#endif
+  { L"msvcr110.dll" }, // Visual Studio 2012
+#ifdef _DEBUG
+  { L"msvcr110d.dll" },// Visual Studio 2012 (debug)
+#endif
+  { L"msvcr120.dll" }, // Visual Studio 2013
+#ifdef _DEBUG
+  { L"msvcr120d.dll" },// Visual Studio 2013 (debug)
+#endif
+};
+
+std::vector<std::wstring> crts_caller::getCrtNames()
+{
+  return std::vector<std::wstring>(s_listOfCrts, s_listOfCrts + (sizeof(s_listOfCrts) / sizeof(s_listOfCrts[0])));
+}
+
+
+crts_caller::crts_caller(const char* func_name)
+{
+  assert(func_name);
+  assert(func_name[0]);
+  if (func_name == NULL)
+    return;
+
+  for (const wchar_t* const crtName : s_listOfCrts)
+  {
+    HMODULE hCrt = NULL;
+    if (!GetModuleHandleExW(0, crtName, &hCrt) || hCrt == NULL) // Flag 0 ensures that CRL will not be unloaded while we are using it here
+      continue; // Module not loaded
+
+    void* func_ptr = GetProcAddress(hCrt, func_name);
+    if (func_ptr != NULL)
+    {
+      m_crts.push_back(hCrt);
+      m_funcPointers.push_back(func_ptr);
+    }
+    else
+      FreeLibrary(hCrt); // this CRT will not be used
+  }
+}
+
+crts_caller::~crts_caller()
+{
+  for (void* hCrt : m_crts)
+    FreeLibrary((HMODULE)hCrt);
+}
+
+}
diff --git a/xbmc/platform/win32/crts_caller.h b/xbmc/platform/win32/crts_caller.h
new file mode 100644
index 0000000..75a4d2d
--- /dev/null
+++ b/xbmc/platform/win32/crts_caller.h
@@ -0,0 +1,71 @@
+#pragma once
+/*
+ *      Copyright (C) 2015 Team Kodi
+ *      http://kodi.tv
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * \file win32\crts_caller.h
+ * \brief Declares crts_caller class for calling same function for all loaded CRTs.
+ * \author Karlson2k
+ */
+
+#include <string>
+#include <vector>
+
+namespace win32_utils
+{
+
+class crts_caller
+{
+public:
+  crts_caller(const char* func_name);
+  const std::vector<void*>& get_pointers(void)
+  { return m_funcPointers; }
+  ~crts_caller();
+
+  template <typename ret_type, typename... param_types>
+  static typename ret_type call_in_all_crts(const char* func_name, ret_type(*cur_fnc_ptr) (param_types...), param_types... params)
+  {
+    typedef ret_type(*ptr_type)(param_types...);
+
+    if (cur_fnc_ptr == NULL)
+      return (ret_type)0; // cur_fnc_ptr must point to process default CRT function
+
+    crts_caller crts(func_name);
+    for (void* func_ptr : crts.m_funcPointers)
+    {
+      ptr_type func = (ptr_type)func_ptr;
+      if (func != cur_fnc_ptr)
+        (void)func(params...); // ignoring result of function call
+    }
+
+    return cur_fnc_ptr(params...); // return result of calling process's CRT function
+  }
+
+  static std::vector<std::wstring> getCrtNames();
+private:
+  std::vector<void*> m_funcPointers;
+  std::vector<void*> m_crts; // actually contains HMODULE
+};
+
+// Call function in all loaded CRTs
+// Function must have same return type and same parameters in all CRTs
+#define CALL_IN_CRTS(function,...) ::win32_utils::crts_caller::call_in_all_crts(#function,&(function),##__VA_ARGS__)
+
+}
diff --git a/xbmc/platform/win32/dirent.h b/xbmc/platform/win32/dirent.h
new file mode 100644
index 0000000..cf3fe56
--- /dev/null
+++ b/xbmc/platform/win32/dirent.h
@@ -0,0 +1,889 @@
+/*
+ * dirent.h - dirent API for Microsoft Visual Studio
+ *
+ * Copyright (C) 2006-2012 Toni Ronkko
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * ``Software''), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Version 1.13, Dec 12 2012, Toni Ronkko
+ * Use traditional 8+3 file name if the name cannot be represented in the
+ * default ANSI code page.  Now compiles again with MSVC 6.0.  Thanks to
+ * Konstantin Khomoutov for testing.
+ *
+ * Version 1.12.1, Oct 1 2012, Toni Ronkko
+ * Bug fix: renamed wide-character DIR structure _wDIR to _WDIR (with
+ * capital W) in order to maintain compatibility with MingW.
+ *
+ * Version 1.12, Sep 30 2012, Toni Ronkko
+ * Define PATH_MAX and NAME_MAX.  Added wide-character variants _wDIR, 
+ * _wdirent, _wopendir(), _wreaddir(), _wclosedir() and _wrewinddir().
+ * Thanks to Edgar Buerkle and Jan Nijtmans for ideas and code.
+ *
+ * Do not include windows.h.  This allows dirent.h to be integrated more
+ * easily into programs using winsock.  Thanks to Fernando Azaldegui.
+ *
+ * Version 1.11, Mar 15, 2011, Toni Ronkko
+ * Defined FILE_ATTRIBUTE_DEVICE for MSVC 6.0.
+ *
+ * Version 1.10, Aug 11, 2010, Toni Ronkko
+ * Added d_type and d_namlen fields to dirent structure.  The former is
+ * especially useful for determining whether directory entry represents a
+ * file or a directory.  For more information, see
+ * http://www.delorie.com/gnu/docs/glibc/libc_270.html
+ *
+ * Improved conformance to the standards.  For example, errno is now set
+ * properly on failure and assert() is never used.  Thanks to Peter Brockam
+ * for suggestions.
+ *
+ * Fixed a bug in rewinddir(): when using relative directory names, change
+ * of working directory no longer causes rewinddir() to fail.
+ *
+ * Version 1.9, Dec 15, 2009, John Cunningham
+ * Added rewinddir member function
+ *
+ * Version 1.8, Jan 18, 2008, Toni Ronkko
+ * Using FindFirstFileA and WIN32_FIND_DATAA to avoid converting string
+ * between multi-byte and unicode representations.  This makes the
+ * code simpler and also allows the code to be compiled under MingW.  Thanks
+ * to Azriel Fasten for the suggestion.
+ *
+ * Mar 4, 2007, Toni Ronkko
+ * Bug fix: due to the strncpy_s() function this file only compiled in
+ * Visual Studio 2005.  Using the new string functions only when the
+ * compiler version allows.
+ *
+ * Nov  2, 2006, Toni Ronkko
+ * Major update: removed support for Watcom C, MS-DOS and Turbo C to
+ * simplify the file, updated the code to compile cleanly on Visual
+ * Studio 2005 with both unicode and multi-byte character strings,
+ * removed rewinddir() as it had a bug.
+ *
+ * Aug 20, 2006, Toni Ronkko
+ * Removed all remarks about MSVC 1.0, which is antiqued now.  Simplified
+ * comments by removing SGML tags.
+ *
+ * May 14 2002, Toni Ronkko
+ * Embedded the function definitions directly to the header so that no
+ * source modules need to be included in the Visual Studio project.  Removed
+ * all the dependencies to other projects so that this header file can be
+ * used independently.
+ *
+ * May 28 1998, Toni Ronkko
+ * First version.
+ *****************************************************************************/
+#ifndef DIRENT_H
+#define DIRENT_H
+
+#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86)
+#   define _X86_
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+#include <windef.h>
+#include <winbase.h>
+#include <wchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+/* Indicates that d_type field is available in dirent structure */
+#define _DIRENT_HAVE_D_TYPE
+
+/* Indicates that d_namlen field is available in dirent structure */
+#define _DIRENT_HAVE_D_NAMLEN
+
+/* Entries missing from MSVC 6.0 */
+#if !defined(FILE_ATTRIBUTE_DEVICE)
+#   define FILE_ATTRIBUTE_DEVICE 0x40
+#endif
+
+/* File type and permission flags for stat() */
+#if !defined(S_IFMT)
+#   define S_IFMT   _S_IFMT                     /* File type mask */
+#endif
+#if !defined(S_IFDIR)
+#   define S_IFDIR  _S_IFDIR                    /* Directory */
+#endif
+#if !defined(S_IFCHR)
+#   define S_IFCHR  _S_IFCHR                    /* Character device */
+#endif
+#if !defined(S_IFFIFO)
+#   define S_IFFIFO _S_IFFIFO                   /* Pipe */
+#endif
+#if !defined(S_IFREG)
+#   define S_IFREG  _S_IFREG                    /* Regular file */
+#endif
+#if !defined(S_IREAD)
+#   define S_IREAD  _S_IREAD                    /* Read permission */
+#endif
+#if !defined(S_IWRITE)
+#   define S_IWRITE _S_IWRITE                   /* Write permission */
+#endif
+#if !defined(S_IEXEC)
+#   define S_IEXEC  _S_IEXEC                    /* Execute permission */
+#endif
+#if !defined(S_IFIFO)
+#   define S_IFIFO _S_IFIFO                     /* Pipe */
+#endif
+#if !defined(S_IFBLK)
+#   define S_IFBLK   0                          /* Block device */
+#endif
+#if !defined(S_IFLNK)
+#   define S_IFLNK   0                          /* Link */
+#endif
+#if !defined(S_IFSOCK)
+#   define S_IFSOCK  0                          /* Socket */
+#endif
+
+#if defined(_MSC_VER)
+#   define S_IRUSR  S_IREAD                     /* Read user */
+#   define S_IWUSR  S_IWRITE                    /* Write user */
+#   define S_IXUSR  0                           /* Execute user */
+#   define S_IRGRP  0                           /* Read group */
+#   define S_IWGRP  0                           /* Write group */
+#   define S_IXGRP  0                           /* Execute group */
+#   define S_IROTH  0                           /* Read others */
+#   define S_IWOTH  0                           /* Write others */
+#   define S_IXOTH  0                           /* Execute others */
+#endif
+
+/* Maximum length of file name */
+#if !defined(PATH_MAX)
+#   define PATH_MAX MAX_PATH
+#endif
+#if !defined(FILENAME_MAX)
+#   define FILENAME_MAX MAX_PATH
+#endif
+#if !defined(NAME_MAX)
+#   define NAME_MAX FILENAME_MAX
+#endif
+
+/* File type flags for d_type */
+#define DT_UNKNOWN  0
+#define DT_REG      S_IFREG
+#define DT_DIR      S_IFDIR
+#define DT_FIFO     S_IFIFO
+#define DT_SOCK     S_IFSOCK
+#define DT_CHR      S_IFCHR
+#define DT_BLK      S_IFBLK
+
+/* Macros for converting between st_mode and d_type */
+#define IFTODT(mode) ((mode) & S_IFMT)
+#define DTTOIF(type) (type)
+
+/*
+ * File type macros.  Note that block devices, sockets and links cannot be
+ * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
+ * only defined for compatibility.  These macros should always return false
+ * on Windows.
+ */
+#define	S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
+#define	S_ISDIR(mode)  (((mode) & S_IFMT) == S_IFDIR)
+#define	S_ISREG(mode)  (((mode) & S_IFMT) == S_IFREG)
+#define	S_ISLNK(mode)  (((mode) & S_IFMT) == S_IFLNK)
+#define	S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
+#define	S_ISCHR(mode)  (((mode) & S_IFMT) == S_IFCHR)
+#define	S_ISBLK(mode)  (((mode) & S_IFMT) == S_IFBLK)
+
+/* Return the exact length of d_namlen without zero terminator */
+#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
+
+/* Return number of bytes needed to store d_namlen */
+#define _D_ALLOC_NAMLEN(p) (PATH_MAX + 1)
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Wide-character version */
+struct _wdirent {
+    long d_ino;                                 /* Always zero */
+    unsigned short d_reclen;                    /* Structure size */
+    size_t d_namlen;                            /* Length of name without \0 */
+    int d_type;                                 /* File type */
+    wchar_t d_name[PATH_MAX + 1];               /* File name */
+};
+typedef struct _wdirent _wdirent;
+
+struct _WDIR {
+    struct _wdirent ent;                        /* Current directory entry */
+    WIN32_FIND_DATAW data;                      /* Private file data */
+    int cached;                                 /* True if data is valid */
+    HANDLE handle;                              /* Win32 search handle */
+    wchar_t *patt;                              /* Initial directory name */
+};
+typedef struct _WDIR _WDIR;
+
+static _WDIR *_wopendir (const wchar_t *dirname);
+static struct _wdirent *_wreaddir (_WDIR *dirp);
+static int _wclosedir (_WDIR *dirp);
+static void _wrewinddir (_WDIR* dirp);
+
+
+/* For compatibility with Symbian */
+#define wdirent _wdirent
+#define WDIR _WDIR
+#define wopendir _wopendir
+#define wreaddir _wreaddir
+#define wclosedir _wclosedir
+#define wrewinddir _wrewinddir
+
+
+/* Multi-byte character versions */
+struct dirent {
+    long d_ino;                                 /* Always zero */
+    unsigned short d_reclen;                    /* Structure size */
+    size_t d_namlen;                            /* Length of name without \0 */
+    int d_type;                                 /* File type */
+    char d_name[PATH_MAX + 1];                  /* File name */
+};
+typedef struct dirent dirent;
+
+struct DIR {
+    struct dirent ent;
+    struct _WDIR *wdirp;
+};
+typedef struct DIR DIR;
+
+static DIR *opendir (const char *dirname);
+static struct dirent *readdir (DIR *dirp);
+static int closedir (DIR *dirp);
+static void rewinddir (DIR* dirp);
+
+
+/* Internal utility functions */
+static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
+static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
+
+static int dirent_mbstowcs_s(
+    size_t *pReturnValue,
+    wchar_t *wcstr,
+    size_t sizeInWords,
+    const char *mbstr,
+    size_t count);
+
+static int dirent_wcstombs_s(
+    size_t *pReturnValue,
+    char *mbstr,
+    size_t sizeInBytes,
+    const wchar_t *wcstr,
+    size_t count);
+
+static void dirent_set_errno (int error);
+
+/*
+ * Open directory stream DIRNAME for read and return a pointer to the
+ * internal working area that is used to retrieve individual directory
+ * entries.
+ */
+static _WDIR*
+_wopendir(
+    const wchar_t *dirname)
+{
+    _WDIR *dirp = NULL;
+    int error;
+
+    /* Must have directory name */
+    if (dirname == NULL  ||  dirname[0] == '\0') {
+        dirent_set_errno (ENOENT);
+        return NULL;
+    }
+
+    /* Allocate new _WDIR structure */
+    dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
+    if (dirp != NULL) {
+        DWORD n;
+
+        /* Reset _WDIR structure */
+        dirp->handle = INVALID_HANDLE_VALUE;
+        dirp->patt = NULL;
+        dirp->cached = 0;
+
+        /* Compute the length of full path plus zero terminator */
+        n = GetFullPathNameW (dirname, 0, NULL, NULL);
+
+        /* Allocate room for absolute directory name and search pattern */
+        dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
+        if (dirp->patt) {
+
+            /*
+             * Convert relative directory name to an absolute one.  This
+             * allows rewinddir() to function correctly even when current
+             * working directory is changed between opendir() and rewinddir().
+             */
+            n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
+            if (n > 0) {
+                wchar_t *p;
+
+                /* Append search pattern \* to the directory name */
+                p = dirp->patt + n;
+                if (dirp->patt < p) {
+                    switch (p[-1]) {
+                    case '\\':
+                    case '/':
+                    case ':':
+                        /* Directory ends in path separator, e.g. c:\temp\ */
+                        /*NOP*/;
+                        break;
+
+                    default:
+                        /* Directory name doesn't end in path separator */
+                        *p++ = '\\';
+                    }
+                }
+                *p++ = '*';
+                *p = '\0';
+
+                /* Open directory stream and retrieve the first entry */
+                if (dirent_first (dirp)) {
+                    /* Directory stream opened successfully */
+                    error = 0;
+                } else {
+                    /* Cannot retrieve first entry */
+                    error = 1;
+                    dirent_set_errno (ENOENT);
+                }
+
+            } else {
+                /* Cannot retrieve full path name */
+                dirent_set_errno (ENOENT);
+                error = 1;
+            }
+
+        } else {
+            /* Cannot allocate memory for search pattern */
+            error = 1;
+        }
+
+    } else {
+        /* Cannot allocate _WDIR structure */
+        error = 1;
+    }
+
+    /* Clean up in case of error */
+    if (error  &&  dirp) {
+        _wclosedir (dirp);
+        dirp = NULL;
+    }
+
+    return dirp;
+}
+
+/*
+ * Read next directory entry.  The directory entry is returned in dirent
+ * structure in the d_name field.  Individual directory entries returned by
+ * this function include regular files, sub-directories, pseudo-directories
+ * "." and ".." as well as volume labels, hidden files and system files.
+ */
+static struct _wdirent*
+_wreaddir(
+    _WDIR *dirp)
+{
+    WIN32_FIND_DATAW *datap;
+    struct _wdirent *entp;
+
+    /* Read next directory entry */
+    datap = dirent_next (dirp);
+    if (datap) {
+        size_t n;
+        DWORD attr;
+        
+        /* Pointer to directory entry to return */
+        entp = &dirp->ent;
+
+        /* 
+         * Copy file name as wide-character string.  If the file name is too
+         * long to fit in to the destination buffer, then truncate file name
+         * to PATH_MAX characters and zero-terminate the buffer.
+         */
+        n = 0;
+        while (n < PATH_MAX  &&  datap->cFileName[n] != 0) {
+            entp->d_name[n] = datap->cFileName[n];
+            n++;
+        }
+        dirp->ent.d_name[n] = 0;
+
+        /* Length of file name excluding zero terminator */
+        entp->d_namlen = n;
+
+        /* File type */
+        attr = datap->dwFileAttributes;
+        if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
+            entp->d_type = DT_CHR;
+        } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+            entp->d_type = DT_DIR;
+        } else {
+            entp->d_type = DT_REG;
+        }
+
+        /* Reset dummy fields */
+        entp->d_ino = 0;
+        entp->d_reclen = sizeof (struct _wdirent);
+
+    } else {
+
+        /* Last directory entry read */
+        entp = NULL;
+
+    }
+
+    return entp;
+}
+
+/*
+ * Close directory stream opened by opendir() function.  This invalidates the
+ * DIR structure as well as any directory entry read previously by
+ * _wreaddir().
+ */
+static int
+_wclosedir(
+    _WDIR *dirp)
+{
+    int ok;
+    if (dirp) {
+
+        /* Release search handle */
+        if (dirp->handle != INVALID_HANDLE_VALUE) {
+            FindClose (dirp->handle);
+            dirp->handle = INVALID_HANDLE_VALUE;
+        }
+
+        /* Release search pattern */
+        if (dirp->patt) {
+            free (dirp->patt);
+            dirp->patt = NULL;
+        }
+
+        /* Release directory structure */
+        free (dirp);
+        ok = /*success*/0;
+
+    } else {
+        /* Invalid directory stream */
+        dirent_set_errno (EBADF);
+        ok = /*failure*/-1;
+    }
+    return ok;
+}
+
+/*
+ * Rewind directory stream such that _wreaddir() returns the very first
+ * file name again.
+ */
+static void
+_wrewinddir(
+    _WDIR* dirp)
+{
+    if (dirp) {
+        /* Release existing search handle */
+        if (dirp->handle != INVALID_HANDLE_VALUE) {
+            FindClose (dirp->handle);
+        }
+
+        /* Open new search handle */
+        dirent_first (dirp);
+    }
+}
+
+/* Get first directory entry (internal) */
+static WIN32_FIND_DATAW*
+dirent_first(
+    _WDIR *dirp)
+{
+    WIN32_FIND_DATAW *datap;
+
+    /* Open directory and retrieve the first entry */
+    dirp->handle = FindFirstFileW (dirp->patt, &dirp->data);
+    if (dirp->handle != INVALID_HANDLE_VALUE) {
+
+        /* a directory entry is now waiting in memory */
+        datap = &dirp->data;
+        dirp->cached = 1;
+
+    } else {
+
+        /* Failed to re-open directory: no directory entry in memory */
+        dirp->cached = 0;
+        datap = NULL;
+
+    }
+    return datap;
+}
+
+/* Get next directory entry (internal) */
+static WIN32_FIND_DATAW*
+dirent_next(
+    _WDIR *dirp)
+{
+    WIN32_FIND_DATAW *p;
+
+    /* Get next directory entry */
+    if (dirp->cached != 0) {
+
+        /* A valid directory entry already in memory */
+        p = &dirp->data;
+        dirp->cached = 0;
+
+    } else if (dirp->handle != INVALID_HANDLE_VALUE) {
+
+        /* Get the next directory entry from stream */
+        if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
+            /* Got a file */
+            p = &dirp->data;
+        } else {
+            /* The very last entry has been processed or an error occured */
+            FindClose (dirp->handle);
+            dirp->handle = INVALID_HANDLE_VALUE;
+            p = NULL;
+        }
+
+    } else {
+
+        /* End of directory stream reached */
+        p = NULL;
+
+    }
+
+    return p;
+}
+
+/* 
+ * Open directory stream using plain old C-string.
+ */
+static DIR*
+opendir(
+    const char *dirname) 
+{
+    struct DIR *dirp;
+    int error;
+
+    /* Must have directory name */
+    if (dirname == NULL  ||  dirname[0] == '\0') {
+        dirent_set_errno (ENOENT);
+        return NULL;
+    }
+
+    /* Allocate memory for DIR structure */
+    dirp = (DIR*) malloc (sizeof (struct DIR));
+    if (dirp) {
+        wchar_t wname[PATH_MAX + 1];
+        size_t n;
+
+        /* Convert directory name to wide-character string */
+        error = dirent_mbstowcs_s(
+            &n, wname, PATH_MAX + 1, dirname, PATH_MAX);
+        if (!error) {
+
+            /* Open directory stream using wide-character name */
+            dirp->wdirp = _wopendir (wname);
+            if (dirp->wdirp) {
+                /* Directory stream opened */
+                error = 0;
+            } else {
+                /* Failed to open directory stream */
+                error = 1;
+            }
+
+        } else {
+            /* 
+             * Cannot convert file name to wide-character string.  This
+             * occurs if the string contains invalid multi-byte sequences or
+             * the output buffer is too small to contain the resulting
+             * string.
+             */
+            error = 1;
+        }
+
+    } else {
+        /* Cannot allocate DIR structure */
+        error = 1;
+    }
+
+    /* Clean up in case of error */
+    if (error  &&  dirp) {
+        free (dirp);
+        dirp = NULL;
+    }
+
+    return dirp;
+}
+
+/*
+ * Read next directory entry.
+ *
+ * When working with text consoles, please note that file names returned by
+ * readdir() are represented in the default ANSI code page while any output to
+ * console is typically formatted on another code page.  Thus, non-ASCII
+ * characters in file names will not usually display correctly on console.  The
+ * problem can be fixed in two ways: (1) change the character set of console
+ * to 1252 using chcp utility and use Lucida Console font, or (2) use
+ * _cprintf function when writing to console.  The _cprinf() will re-encode
+ * ANSI strings to the console code page so many non-ASCII characters will
+ * display correcly.
+ */
+static struct dirent*
+readdir(
+    DIR *dirp) 
+{
+    WIN32_FIND_DATAW *datap;
+    struct dirent *entp;
+
+    /* Read next directory entry */
+    datap = dirent_next (dirp->wdirp);
+    if (datap) {
+        size_t n;
+        int error;
+
+        /* Attempt to convert file name to multi-byte string */
+        error = dirent_wcstombs_s(
+            &n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH);
+
+        /* 
+         * If the file name cannot be represented by a multi-byte string,
+         * then attempt to use old 8+3 file name.  This allows traditional
+         * Unix-code to access some file names despite of unicode
+         * characters, although file names may seem unfamiliar to the user.
+         *
+         * Be ware that the code below cannot come up with a short file
+         * name unless the file system provides one.  At least
+         * VirtualBox shared folders fail to do this.
+         */
+        if (error  &&  datap->cAlternateFileName[0] != '\0') {
+            error = dirent_wcstombs_s(
+                &n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName,
+                sizeof (datap->cAlternateFileName) / 
+                    sizeof (datap->cAlternateFileName[0]));
+        }
+
+        if (!error) {
+            DWORD attr;
+
+            /* Initialize directory entry for return */
+            entp = &dirp->ent;
+
+            /* Length of file name excluding zero terminator */
+            entp->d_namlen = n - 1;
+
+            /* File attributes */
+            attr = datap->dwFileAttributes;
+            if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
+                entp->d_type = DT_CHR;
+            } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+                entp->d_type = DT_DIR;
+            } else {
+                entp->d_type = DT_REG;
+            }
+
+            /* Reset dummy fields */
+            entp->d_ino = 0;
+            entp->d_reclen = sizeof (struct dirent);
+
+        } else {
+            /* 
+             * Cannot convert file name to multi-byte string so construct
+             * an errornous directory entry and return that.  Note that
+             * we cannot return NULL as that would stop the processing
+             * of directory entries completely.
+             */
+            entp = &dirp->ent;
+            entp->d_name[0] = '?';
+            entp->d_name[1] = '\0';
+            entp->d_namlen = 1;
+            entp->d_type = DT_UNKNOWN;
+            entp->d_ino = 0;
+            entp->d_reclen = 0;
+        }
+
+    } else {
+        /* No more directory entries */
+        entp = NULL;
+    }
+
+    return entp;
+}
+
+/*
+ * Close directory stream.
+ */
+static int
+closedir(
+    DIR *dirp) 
+{
+    int ok;
+    if (dirp) {
+
+        /* Close wide-character directory stream */
+        ok = _wclosedir (dirp->wdirp);
+        dirp->wdirp = NULL;
+
+        /* Release multi-byte character version */
+        free (dirp);
+
+    } else {
+
+        /* Invalid directory stream */
+        dirent_set_errno (EBADF);
+        ok = /*failure*/-1;
+
+    }
+    return ok;
+}
+
+/*
+ * Rewind directory stream to beginning.
+ */
+static void
+rewinddir(
+    DIR* dirp) 
+{
+    /* Rewind wide-character string directory stream */
+    _wrewinddir (dirp->wdirp);
+}
+
+/* Convert multi-byte string to wide character string */
+static int
+dirent_mbstowcs_s(
+    size_t *pReturnValue,
+    wchar_t *wcstr,
+    size_t sizeInWords,
+    const char *mbstr,
+    size_t count)
+{
+    int error;
+
+#if defined(_MSC_VER)  &&  _MSC_VER >= 1400
+
+    /* Microsoft Visual Studio 2005 or later */
+    error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
+
+#else
+
+    /* Older Visual Studio or non-Microsoft compiler */
+    size_t n;
+
+    /* Convert to wide-character string */
+    n = mbstowcs (wcstr, mbstr, count);
+    if (n < sizeInWords) {
+
+        /* Zero-terminate output buffer */
+        if (wcstr) {
+            wcstr[n] = 0;
+        }
+
+        /* Length of resuting multi-byte string WITH zero terminator */
+        if (pReturnValue) {
+            *pReturnValue = n + 1;
+        }
+
+        /* Success */
+        error = 0;
+
+    } else {
+
+        /* Could not convert string */
+        error = 1;
+
+    }
+
+#endif
+
+    return error;
+}
+
+/* Convert wide-character string to multi-byte string */
+static int
+dirent_wcstombs_s(
+    size_t *pReturnValue,
+    char *mbstr,
+    size_t sizeInBytes,
+    const wchar_t *wcstr,
+    size_t count)
+{
+    int error;
+
+#if defined(_MSC_VER)  &&  _MSC_VER >= 1400
+
+    /* Microsoft Visual Studio 2005 or later */
+    error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
+
+#else
+
+    /* Older Visual Studio or non-Microsoft compiler */
+    size_t n;
+
+    /* Convert to multi-byte string */
+    n = wcstombs (mbstr, wcstr, count);
+    if (n < sizeInBytes) {
+
+        /* Zero-terminate output buffer */
+        if (mbstr) {
+            mbstr[n] = '\0';
+        }
+
+        /* Lenght of resulting multi-bytes string WITH zero-terminator */
+        if (pReturnValue) {
+            *pReturnValue = n + 1;
+        }
+
+        /* Success */
+        error = 0;
+
+    } else {
+
+        /* Cannot convert string */
+        error = 1;
+
+    }
+
+#endif
+
+    return error;
+}
+
+/* Set errno variable */
+static void
+dirent_set_errno(
+    int error)
+{
+#if defined(_MSC_VER)
+
+    /* Microsoft Visual Studio */
+    _set_errno (error);
+
+#else
+
+    /* Non-Microsoft compiler */
+    errno = error;
+
+#endif
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*DIRENT_H*/
+
diff --git a/xbmc/platform/win32/dxerr.cpp b/xbmc/platform/win32/dxerr.cpp
new file mode 100644
index 0000000..5ad1c12
--- /dev/null
+++ b/xbmc/platform/win32/dxerr.cpp
@@ -0,0 +1,3965 @@
+//--------------------------------------------------------------------------------------
+// File: DXErr.cpp
+//
+// DirectX Error Library
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//--------------------------------------------------------------------------------------
+
+// This version only supports UNICODE.
+
+#include "dxerr.h"
+
+#include <stdio.h>
+#include <algorithm>
+
+#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)
+#include <ddraw.h>
+#include <d3d9.h>
+#include <dsound.h>
+
+#define DIRECTINPUT_VERSION 0x800
+#include <dinput.h>
+#include <dinputd.h>
+#endif
+
+#include <d3d10_1.h>
+#include <d3d11_1.h>
+
+#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
+#include <wincodec.h>
+#include <d2derr.h>
+#include <dwrite.h>
+#endif
+
+#define XAUDIO2_E_INVALID_CALL          0x88960001
+#define XAUDIO2_E_XMA_DECODER_ERROR     0x88960002
+#define XAUDIO2_E_XAPO_CREATION_FAILED  0x88960003
+#define XAUDIO2_E_DEVICE_INVALIDATED    0x88960004
+
+#define XAPO_E_FORMAT_UNSUPPORTED MAKE_HRESULT(SEVERITY_ERROR, 0x897, 0x01)
+
+#define DXUTERR_NODIRECT3D              MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0901)
+#define DXUTERR_NOCOMPATIBLEDEVICES     MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0902)
+#define DXUTERR_MEDIANOTFOUND           MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0903)
+#define DXUTERR_NONZEROREFCOUNT         MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0904)
+#define DXUTERR_CREATINGDEVICE          MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0905)
+#define DXUTERR_RESETTINGDEVICE         MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0906)
+#define DXUTERR_CREATINGDEVICEOBJECTS   MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0907)
+#define DXUTERR_RESETTINGDEVICEOBJECTS  MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0908)
+#define DXUTERR_INCORRECTVERSION        MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0909)
+#define DXUTERR_DEVICEREMOVED           MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x090A)
+
+//-----------------------------------------------------------------------------
+#define BUFFER_SIZE 3000
+
+#pragma warning( disable : 6001 6221 )
+
+//--------------------------------------------------------------------------------------
+#define  CHK_ERR(hrchk, strOut) \
+        case hrchk: \
+             return L##strOut;
+
+#define  CHK_ERRA(hrchk) \
+        case hrchk: \
+             return L#hrchk;
+
+#define HRESULT_FROM_WIN32b(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000)))
+
+#define  CHK_ERR_WIN32A(hrchk) \
+        case HRESULT_FROM_WIN32b(hrchk): \
+        case hrchk: \
+             return L#hrchk;
+
+#define  CHK_ERR_WIN32_ONLY(hrchk, strOut) \
+        case HRESULT_FROM_WIN32b(hrchk): \
+             return L##strOut;
+
+//-----------------------------------------------------
+const WCHAR* WINAPI DXGetErrorStringW( _In_ HRESULT hr )
+{
+   switch(hr)
+   {
+// Commmented out codes are actually alises for other codes
+
+// -------------------------------------------------------------
+// Common Win32 error codes
+// -------------------------------------------------------------
+        CHK_ERRA(S_OK)
+        CHK_ERRA(S_FALSE)
+
+        CHK_ERRA(E_UNEXPECTED)
+        CHK_ERRA(E_NOTIMPL)
+        CHK_ERRA(E_OUTOFMEMORY)
+        CHK_ERRA(E_INVALIDARG)
+        CHK_ERRA(E_NOINTERFACE)
+        CHK_ERRA(E_POINTER)
+        CHK_ERRA(E_HANDLE)
+        CHK_ERRA(E_ABORT)
+        CHK_ERRA(E_FAIL)
+        CHK_ERRA(E_ACCESSDENIED)
+        CHK_ERRA(E_PENDING)
+        CHK_ERRA(CO_E_INIT_TLS)
+        CHK_ERRA(CO_E_INIT_SHARED_ALLOCATOR)
+        CHK_ERRA(CO_E_INIT_MEMORY_ALLOCATOR)
+        CHK_ERRA(CO_E_INIT_CLASS_CACHE)
+        CHK_ERRA(CO_E_INIT_RPC_CHANNEL)
+        CHK_ERRA(CO_E_INIT_TLS_SET_CHANNEL_CONTROL)
+        CHK_ERRA(CO_E_INIT_TLS_CHANNEL_CONTROL)
+        CHK_ERRA(CO_E_INIT_UNACCEPTED_USER_ALLOCATOR)
+        CHK_ERRA(CO_E_INIT_SCM_MUTEX_EXISTS)
+        CHK_ERRA(CO_E_INIT_SCM_FILE_MAPPING_EXISTS)
+        CHK_ERRA(CO_E_INIT_SCM_MAP_VIEW_OF_FILE)
+        CHK_ERRA(CO_E_INIT_SCM_EXEC_FAILURE)
+        CHK_ERRA(CO_E_INIT_ONLY_SINGLE_THREADED)
+        CHK_ERRA(CO_E_CANT_REMOTE)
+        CHK_ERRA(CO_E_BAD_SERVER_NAME)
+        CHK_ERRA(CO_E_WRONG_SERVER_IDENTITY)
+        CHK_ERRA(CO_E_OLE1DDE_DISABLED)
+        CHK_ERRA(CO_E_RUNAS_SYNTAX)
+        CHK_ERRA(CO_E_CREATEPROCESS_FAILURE)
+        CHK_ERRA(CO_E_RUNAS_CREATEPROCESS_FAILURE)
+        CHK_ERRA(CO_E_RUNAS_LOGON_FAILURE)
+        CHK_ERRA(CO_E_LAUNCH_PERMSSION_DENIED)
+        CHK_ERRA(CO_E_START_SERVICE_FAILURE)
+        CHK_ERRA(CO_E_REMOTE_COMMUNICATION_FAILURE)
+        CHK_ERRA(CO_E_SERVER_START_TIMEOUT)
+        CHK_ERRA(CO_E_CLSREG_INCONSISTENT)
+        CHK_ERRA(CO_E_IIDREG_INCONSISTENT)
+        CHK_ERRA(CO_E_NOT_SUPPORTED)
+        CHK_ERRA(CO_E_RELOAD_DLL)
+        CHK_ERRA(CO_E_MSI_ERROR)
+        CHK_ERRA(OLE_E_FIRST)
+        CHK_ERRA(OLE_E_LAST)
+        CHK_ERRA(OLE_S_FIRST)
+        CHK_ERRA(OLE_S_LAST)
+//        CHK_ERRA(OLE_E_OLEVERB)
+        CHK_ERRA(OLE_E_ADVF)
+        CHK_ERRA(OLE_E_ENUM_NOMORE)
+        CHK_ERRA(OLE_E_ADVISENOTSUPPORTED)
+        CHK_ERRA(OLE_E_NOCONNECTION)
+        CHK_ERRA(OLE_E_NOTRUNNING)
+        CHK_ERRA(OLE_E_NOCACHE)
+        CHK_ERRA(OLE_E_BLANK)
+        CHK_ERRA(OLE_E_CLASSDIFF)
+        CHK_ERRA(OLE_E_CANT_GETMONIKER)
+        CHK_ERRA(OLE_E_CANT_BINDTOSOURCE)
+        CHK_ERRA(OLE_E_STATIC)
+        CHK_ERRA(OLE_E_PROMPTSAVECANCELLED)
+        CHK_ERRA(OLE_E_INVALIDRECT)
+        CHK_ERRA(OLE_E_WRONGCOMPOBJ)
+        CHK_ERRA(OLE_E_INVALIDHWND)
+        CHK_ERRA(OLE_E_NOT_INPLACEACTIVE)
+        CHK_ERRA(OLE_E_CANTCONVERT)
+        CHK_ERRA(OLE_E_NOSTORAGE)
+        CHK_ERRA(DV_E_FORMATETC)
+        CHK_ERRA(DV_E_DVTARGETDEVICE)
+        CHK_ERRA(DV_E_STGMEDIUM)
+        CHK_ERRA(DV_E_STATDATA)
+        CHK_ERRA(DV_E_LINDEX)
+        CHK_ERRA(DV_E_TYMED)
+        CHK_ERRA(DV_E_CLIPFORMAT)
+        CHK_ERRA(DV_E_DVASPECT)
+        CHK_ERRA(DV_E_DVTARGETDEVICE_SIZE)
+        CHK_ERRA(DV_E_NOIVIEWOBJECT)
+        CHK_ERRA(DRAGDROP_E_FIRST)
+        CHK_ERRA(DRAGDROP_E_LAST)
+        CHK_ERRA(DRAGDROP_S_FIRST)
+        CHK_ERRA(DRAGDROP_S_LAST)
+//        CHK_ERRA(DRAGDROP_E_NOTREGISTERED)
+        CHK_ERRA(DRAGDROP_E_ALREADYREGISTERED)
+        CHK_ERRA(DRAGDROP_E_INVALIDHWND)
+        CHK_ERRA(CLASSFACTORY_E_FIRST)
+        CHK_ERRA(CLASSFACTORY_E_LAST)
+        CHK_ERRA(CLASSFACTORY_S_FIRST)
+        CHK_ERRA(CLASSFACTORY_S_LAST)
+//        CHK_ERRA(CLASS_E_NOAGGREGATION)
+        CHK_ERRA(CLASS_E_CLASSNOTAVAILABLE)
+        CHK_ERRA(CLASS_E_NOTLICENSED)
+        CHK_ERRA(MARSHAL_E_FIRST)
+        CHK_ERRA(MARSHAL_E_LAST)
+        CHK_ERRA(MARSHAL_S_FIRST)
+        CHK_ERRA(MARSHAL_S_LAST)
+        CHK_ERRA(DATA_E_FIRST)
+        CHK_ERRA(DATA_E_LAST)
+        CHK_ERRA(DATA_S_FIRST)
+        CHK_ERRA(DATA_S_LAST)
+        CHK_ERRA(VIEW_E_FIRST)
+        CHK_ERRA(VIEW_E_LAST)
+        CHK_ERRA(VIEW_S_FIRST)
+        CHK_ERRA(VIEW_S_LAST)
+//        CHK_ERRA(VIEW_E_DRAW)
+        CHK_ERRA(REGDB_E_FIRST)
+        CHK_ERRA(REGDB_E_LAST)
+        CHK_ERRA(REGDB_S_FIRST)
+        CHK_ERRA(REGDB_S_LAST)
+//        CHK_ERRA(REGDB_E_READREGDB)
+        CHK_ERRA(REGDB_E_WRITEREGDB)
+        CHK_ERRA(REGDB_E_KEYMISSING)
+        CHK_ERRA(REGDB_E_INVALIDVALUE)
+        CHK_ERRA(REGDB_E_CLASSNOTREG)
+        CHK_ERRA(REGDB_E_IIDNOTREG)
+        CHK_ERRA(CAT_E_FIRST)
+        CHK_ERRA(CAT_E_LAST)
+//        CHK_ERRA(CAT_E_CATIDNOEXIST)
+//        CHK_ERRA(CAT_E_NODESCRIPTION)
+        CHK_ERRA(CS_E_FIRST)
+        CHK_ERRA(CS_E_LAST)
+//        CHK_ERRA(CS_E_PACKAGE_NOTFOUND)
+        CHK_ERRA(CS_E_NOT_DELETABLE)
+        CHK_ERRA(CS_E_CLASS_NOTFOUND)
+        CHK_ERRA(CS_E_INVALID_VERSION)
+        CHK_ERRA(CS_E_NO_CLASSSTORE)
+        CHK_ERRA(CS_E_OBJECT_NOTFOUND)
+        CHK_ERRA(CS_E_OBJECT_ALREADY_EXISTS)
+        CHK_ERRA(CS_E_INVALID_PATH)
+        CHK_ERRA(CS_E_NETWORK_ERROR)
+        CHK_ERRA(CS_E_ADMIN_LIMIT_EXCEEDED)
+        CHK_ERRA(CS_E_SCHEMA_MISMATCH)
+//        CHK_ERRA(CS_E_INTERNAL_ERROR)
+        CHK_ERRA(CACHE_E_FIRST)
+        CHK_ERRA(CACHE_E_LAST)
+        CHK_ERRA(CACHE_S_FIRST)
+        CHK_ERRA(CACHE_S_LAST)
+//        CHK_ERRA(CACHE_E_NOCACHE_UPDATED)
+        CHK_ERRA(OLEOBJ_E_FIRST)
+        CHK_ERRA(OLEOBJ_E_LAST)
+        CHK_ERRA(OLEOBJ_S_FIRST)
+        CHK_ERRA(OLEOBJ_S_LAST)
+//        CHK_ERRA(OLEOBJ_E_NOVERBS)
+        CHK_ERRA(OLEOBJ_E_INVALIDVERB)
+        CHK_ERRA(CLIENTSITE_E_FIRST)
+        CHK_ERRA(CLIENTSITE_E_LAST)
+        CHK_ERRA(CLIENTSITE_S_FIRST)
+        CHK_ERRA(CLIENTSITE_S_LAST)
+        CHK_ERRA(INPLACE_E_NOTUNDOABLE)
+        CHK_ERRA(INPLACE_E_NOTOOLSPACE)
+//        CHK_ERRA(INPLACE_E_FIRST)
+        CHK_ERRA(INPLACE_E_LAST)
+        CHK_ERRA(INPLACE_S_FIRST)
+        CHK_ERRA(INPLACE_S_LAST)
+        CHK_ERRA(ENUM_E_FIRST)
+        CHK_ERRA(ENUM_E_LAST)
+        CHK_ERRA(ENUM_S_FIRST)
+        CHK_ERRA(ENUM_S_LAST)
+        CHK_ERRA(CONVERT10_E_FIRST)
+        CHK_ERRA(CONVERT10_E_LAST)
+        CHK_ERRA(CONVERT10_S_FIRST)
+        CHK_ERRA(CONVERT10_S_LAST)
+//        CHK_ERRA(CONVERT10_E_OLESTREAM_GET)
+        CHK_ERRA(CONVERT10_E_OLESTREAM_PUT)
+        CHK_ERRA(CONVERT10_E_OLESTREAM_FMT)
+        CHK_ERRA(CONVERT10_E_OLESTREAM_BITMAP_TO_DIB)
+        CHK_ERRA(CONVERT10_E_STG_FMT)
+        CHK_ERRA(CONVERT10_E_STG_NO_STD_STREAM)
+        CHK_ERRA(CONVERT10_E_STG_DIB_TO_BITMAP)
+        CHK_ERRA(CLIPBRD_E_FIRST)
+        CHK_ERRA(CLIPBRD_E_LAST)
+        CHK_ERRA(CLIPBRD_S_FIRST)
+        CHK_ERRA(CLIPBRD_S_LAST)
+//        CHK_ERRA(CLIPBRD_E_CANT_OPEN)
+        CHK_ERRA(CLIPBRD_E_CANT_EMPTY)
+        CHK_ERRA(CLIPBRD_E_CANT_SET)
+        CHK_ERRA(CLIPBRD_E_BAD_DATA)
+        CHK_ERRA(CLIPBRD_E_CANT_CLOSE)
+        CHK_ERRA(MK_E_FIRST)
+        CHK_ERRA(MK_E_LAST)
+        CHK_ERRA(MK_S_FIRST)
+        CHK_ERRA(MK_S_LAST)
+//        CHK_ERRA(MK_E_CONNECTMANUALLY)
+        CHK_ERRA(MK_E_EXCEEDEDDEADLINE)
+        CHK_ERRA(MK_E_NEEDGENERIC)
+        CHK_ERRA(MK_E_UNAVAILABLE)
+        CHK_ERRA(MK_E_SYNTAX)
+        CHK_ERRA(MK_E_NOOBJECT)
+        CHK_ERRA(MK_E_INVALIDEXTENSION)
+        CHK_ERRA(MK_E_INTERMEDIATEINTERFACENOTSUPPORTED)
+        CHK_ERRA(MK_E_NOTBINDABLE)
+        CHK_ERRA(MK_E_NOTBOUND)
+        CHK_ERRA(MK_E_CANTOPENFILE)
+        CHK_ERRA(MK_E_MUSTBOTHERUSER)
+        CHK_ERRA(MK_E_NOINVERSE)
+        CHK_ERRA(MK_E_NOSTORAGE)
+        CHK_ERRA(MK_E_NOPREFIX)
+//        CHK_ERRA(MK_E_ENUMERATION_FAILED)
+        CHK_ERRA(CO_E_NOTINITIALIZED)
+        CHK_ERRA(CO_E_ALREADYINITIALIZED)
+        CHK_ERRA(CO_E_CANTDETERMINECLASS)
+        CHK_ERRA(CO_E_CLASSSTRING)
+        CHK_ERRA(CO_E_IIDSTRING)
+        CHK_ERRA(CO_E_APPNOTFOUND)
+        CHK_ERRA(CO_E_APPSINGLEUSE)
+        CHK_ERRA(CO_E_ERRORINAPP)
+        CHK_ERRA(CO_E_DLLNOTFOUND)
+        CHK_ERRA(CO_E_ERRORINDLL)
+        CHK_ERRA(CO_E_WRONGOSFORAPP)
+        CHK_ERRA(CO_E_OBJNOTREG)
+        CHK_ERRA(CO_E_OBJISREG)
+        CHK_ERRA(CO_E_OBJNOTCONNECTED)
+        CHK_ERRA(CO_E_APPDIDNTREG)
+        CHK_ERRA(CO_E_RELEASED)
+//        CHK_ERRA(OLE_S_USEREG)
+        CHK_ERRA(OLE_S_STATIC)
+        CHK_ERRA(OLE_S_MAC_CLIPFORMAT)
+//        CHK_ERRA(DRAGDROP_S_DROP)
+        CHK_ERRA(DRAGDROP_S_CANCEL)
+        CHK_ERRA(DRAGDROP_S_USEDEFAULTCURSORS)
+//        CHK_ERRA(DATA_S_SAMEFORMATETC)
+//        CHK_ERRA(VIEW_S_ALREADY_FROZEN)
+//        CHK_ERRA(CACHE_S_FORMATETC_NOTSUPPORTED)
+        CHK_ERRA(CACHE_S_SAMECACHE)
+        CHK_ERRA(CACHE_S_SOMECACHES_NOTUPDATED)
+//        CHK_ERRA(OLEOBJ_S_INVALIDVERB)
+        CHK_ERRA(OLEOBJ_S_CANNOT_DOVERB_NOW)
+        CHK_ERRA(OLEOBJ_S_INVALIDHWND)
+//        CHK_ERRA(INPLACE_S_TRUNCATED)
+//        CHK_ERRA(CONVERT10_S_NO_PRESENTATION)
+        CHK_ERRA(MK_S_REDUCED_TO_SELF)
+        CHK_ERRA(MK_S_ME)
+        CHK_ERRA(MK_S_HIM)
+        CHK_ERRA(MK_S_US)
+        CHK_ERRA(MK_S_MONIKERALREADYREGISTERED)
+        CHK_ERRA(CO_E_CLASS_CREATE_FAILED)
+        CHK_ERRA(CO_E_SCM_ERROR)
+        CHK_ERRA(CO_E_SCM_RPC_FAILURE)
+        CHK_ERRA(CO_E_BAD_PATH)
+        CHK_ERRA(CO_E_SERVER_EXEC_FAILURE)
+        CHK_ERRA(CO_E_OBJSRV_RPC_FAILURE)
+        CHK_ERRA(MK_E_NO_NORMALIZED)
+        CHK_ERRA(CO_E_SERVER_STOPPING)
+        CHK_ERRA(MEM_E_INVALID_ROOT)
+        CHK_ERRA(MEM_E_INVALID_LINK)
+        CHK_ERRA(MEM_E_INVALID_SIZE)
+        CHK_ERRA(CO_S_NOTALLINTERFACES)
+        CHK_ERRA(DISP_E_UNKNOWNINTERFACE)
+        CHK_ERRA(DISP_E_MEMBERNOTFOUND)
+        CHK_ERRA(DISP_E_PARAMNOTFOUND)
+        CHK_ERRA(DISP_E_TYPEMISMATCH)
+        CHK_ERRA(DISP_E_UNKNOWNNAME)
+        CHK_ERRA(DISP_E_NONAMEDARGS)
+        CHK_ERRA(DISP_E_BADVARTYPE)
+        CHK_ERRA(DISP_E_EXCEPTION)
+        CHK_ERRA(DISP_E_OVERFLOW)
+        CHK_ERRA(DISP_E_BADINDEX)
+        CHK_ERRA(DISP_E_UNKNOWNLCID)
+        CHK_ERRA(DISP_E_ARRAYISLOCKED)
+        CHK_ERRA(DISP_E_BADPARAMCOUNT)
+        CHK_ERRA(DISP_E_PARAMNOTOPTIONAL)
+        CHK_ERRA(DISP_E_BADCALLEE)
+        CHK_ERRA(DISP_E_NOTACOLLECTION)
+        CHK_ERRA(DISP_E_DIVBYZERO)
+        CHK_ERRA(DISP_E_BUFFERTOOSMALL)
+        CHK_ERRA(TYPE_E_BUFFERTOOSMALL)
+        CHK_ERRA(TYPE_E_FIELDNOTFOUND)
+        CHK_ERRA(TYPE_E_INVDATAREAD)
+        CHK_ERRA(TYPE_E_UNSUPFORMAT)
+        CHK_ERRA(TYPE_E_REGISTRYACCESS)
+        CHK_ERRA(TYPE_E_LIBNOTREGISTERED)
+        CHK_ERRA(TYPE_E_UNDEFINEDTYPE)
+        CHK_ERRA(TYPE_E_QUALIFIEDNAMEDISALLOWED)
+        CHK_ERRA(TYPE_E_INVALIDSTATE)
+        CHK_ERRA(TYPE_E_WRONGTYPEKIND)
+        CHK_ERRA(TYPE_E_ELEMENTNOTFOUND)
+        CHK_ERRA(TYPE_E_AMBIGUOUSNAME)
+        CHK_ERRA(TYPE_E_NAMECONFLICT)
+        CHK_ERRA(TYPE_E_UNKNOWNLCID)
+        CHK_ERRA(TYPE_E_DLLFUNCTIONNOTFOUND)
+        CHK_ERRA(TYPE_E_BADMODULEKIND)
+        CHK_ERRA(TYPE_E_SIZETOOBIG)
+        CHK_ERRA(TYPE_E_DUPLICATEID)
+        CHK_ERRA(TYPE_E_INVALIDID)
+        CHK_ERRA(TYPE_E_TYPEMISMATCH)
+        CHK_ERRA(TYPE_E_OUTOFBOUNDS)
+        CHK_ERRA(TYPE_E_IOERROR)
+        CHK_ERRA(TYPE_E_CANTCREATETMPFILE)
+        CHK_ERRA(TYPE_E_CANTLOADLIBRARY)
+        CHK_ERRA(TYPE_E_INCONSISTENTPROPFUNCS)
+        CHK_ERRA(TYPE_E_CIRCULARTYPE)
+        CHK_ERRA(STG_E_INVALIDFUNCTION)
+        CHK_ERRA(STG_E_FILENOTFOUND)
+        CHK_ERRA(STG_E_PATHNOTFOUND)
+        CHK_ERRA(STG_E_TOOMANYOPENFILES)
+        CHK_ERRA(STG_E_ACCESSDENIED)
+        CHK_ERRA(STG_E_INVALIDHANDLE)
+        CHK_ERRA(STG_E_INSUFFICIENTMEMORY)
+        CHK_ERRA(STG_E_INVALIDPOINTER)
+        CHK_ERRA(STG_E_NOMOREFILES)
+        CHK_ERRA(STG_E_DISKISWRITEPROTECTED)
+        CHK_ERRA(STG_E_SEEKERROR)
+        CHK_ERRA(STG_E_WRITEFAULT)
+        CHK_ERRA(STG_E_READFAULT)
+        CHK_ERRA(STG_E_SHAREVIOLATION)
+        CHK_ERRA(STG_E_LOCKVIOLATION)
+        CHK_ERRA(STG_E_FILEALREADYEXISTS)
+        CHK_ERRA(STG_E_INVALIDPARAMETER)
+        CHK_ERRA(STG_E_MEDIUMFULL)
+        CHK_ERRA(STG_E_PROPSETMISMATCHED)
+        CHK_ERRA(STG_E_ABNORMALAPIEXIT)
+        CHK_ERRA(STG_E_INVALIDHEADER)
+        CHK_ERRA(STG_E_INVALIDNAME)
+        CHK_ERRA(STG_E_UNKNOWN)
+        CHK_ERRA(STG_E_UNIMPLEMENTEDFUNCTION)
+        CHK_ERRA(STG_E_INVALIDFLAG)
+        CHK_ERRA(STG_E_INUSE)
+        CHK_ERRA(STG_E_NOTCURRENT)
+        CHK_ERRA(STG_E_REVERTED)
+        CHK_ERRA(STG_E_CANTSAVE)
+        CHK_ERRA(STG_E_OLDFORMAT)
+        CHK_ERRA(STG_E_OLDDLL)
+        CHK_ERRA(STG_E_SHAREREQUIRED)
+        CHK_ERRA(STG_E_NOTFILEBASEDSTORAGE)
+        CHK_ERRA(STG_E_EXTANTMARSHALLINGS)
+        CHK_ERRA(STG_E_DOCFILECORRUPT)
+        CHK_ERRA(STG_E_BADBASEADDRESS)
+        CHK_ERRA(STG_E_DOCFILETOOLARGE)
+        CHK_ERRA(STG_E_NOTSIMPLEFORMAT)
+        CHK_ERRA(STG_E_INCOMPLETE)
+        CHK_ERRA(STG_E_TERMINATED)
+        CHK_ERRA(STG_S_CONVERTED)
+        CHK_ERRA(STG_S_BLOCK)
+        CHK_ERRA(STG_S_RETRYNOW)
+        CHK_ERRA(STG_S_MONITORING)
+        CHK_ERRA(STG_S_MULTIPLEOPENS)
+        CHK_ERRA(STG_S_CONSOLIDATIONFAILED)
+        CHK_ERRA(STG_S_CANNOTCONSOLIDATE)
+        CHK_ERRA(RPC_E_CALL_REJECTED)
+        CHK_ERRA(RPC_E_CALL_CANCELED)
+        CHK_ERRA(RPC_E_CANTPOST_INSENDCALL)
+        CHK_ERRA(RPC_E_CANTCALLOUT_INASYNCCALL)
+        CHK_ERRA(RPC_E_CANTCALLOUT_INEXTERNALCALL)
+        CHK_ERRA(RPC_E_CONNECTION_TERMINATED)
+        CHK_ERRA(RPC_E_SERVER_DIED)
+        CHK_ERRA(RPC_E_CLIENT_DIED)
+        CHK_ERRA(RPC_E_INVALID_DATAPACKET)
+        CHK_ERRA(RPC_E_CANTTRANSMIT_CALL)
+        CHK_ERRA(RPC_E_CLIENT_CANTMARSHAL_DATA)
+        CHK_ERRA(RPC_E_CLIENT_CANTUNMARSHAL_DATA)
+        CHK_ERRA(RPC_E_SERVER_CANTMARSHAL_DATA)
+        CHK_ERRA(RPC_E_SERVER_CANTUNMARSHAL_DATA)
+        CHK_ERRA(RPC_E_INVALID_DATA)
+        CHK_ERRA(RPC_E_INVALID_PARAMETER)
+        CHK_ERRA(RPC_E_CANTCALLOUT_AGAIN)
+        CHK_ERRA(RPC_E_SERVER_DIED_DNE)
+        CHK_ERRA(RPC_E_SYS_CALL_FAILED)
+        CHK_ERRA(RPC_E_OUT_OF_RESOURCES)
+        CHK_ERRA(RPC_E_ATTEMPTED_MULTITHREAD)
+        CHK_ERRA(RPC_E_NOT_REGISTERED)
+        CHK_ERRA(RPC_E_FAULT)
+        CHK_ERRA(RPC_E_SERVERFAULT)
+        CHK_ERRA(RPC_E_CHANGED_MODE)
+        CHK_ERRA(RPC_E_INVALIDMETHOD)
+        CHK_ERRA(RPC_E_DISCONNECTED)
+        CHK_ERRA(RPC_E_RETRY)
+        CHK_ERRA(RPC_E_SERVERCALL_RETRYLATER)
+        CHK_ERRA(RPC_E_SERVERCALL_REJECTED)
+        CHK_ERRA(RPC_E_INVALID_CALLDATA)
+        CHK_ERRA(RPC_E_CANTCALLOUT_ININPUTSYNCCALL)
+        CHK_ERRA(RPC_E_WRONG_THREAD)
+        CHK_ERRA(RPC_E_THREAD_NOT_INIT)
+        CHK_ERRA(RPC_E_VERSION_MISMATCH)
+        CHK_ERRA(RPC_E_INVALID_HEADER)
+        CHK_ERRA(RPC_E_INVALID_EXTENSION)
+        CHK_ERRA(RPC_E_INVALID_IPID)
+        CHK_ERRA(RPC_E_INVALID_OBJECT)
+        CHK_ERRA(RPC_S_CALLPENDING)
+        CHK_ERRA(RPC_S_WAITONTIMER)
+        CHK_ERRA(RPC_E_CALL_COMPLETE)
+        CHK_ERRA(RPC_E_UNSECURE_CALL)
+        CHK_ERRA(RPC_E_TOO_LATE)
+        CHK_ERRA(RPC_E_NO_GOOD_SECURITY_PACKAGES)
+        CHK_ERRA(RPC_E_ACCESS_DENIED)
+        CHK_ERRA(RPC_E_REMOTE_DISABLED)
+        CHK_ERRA(RPC_E_INVALID_OBJREF)
+        CHK_ERRA(RPC_E_NO_CONTEXT)
+        CHK_ERRA(RPC_E_TIMEOUT)
+        CHK_ERRA(RPC_E_NO_SYNC)
+        CHK_ERRA(RPC_E_FULLSIC_REQUIRED)
+        CHK_ERRA(RPC_E_INVALID_STD_NAME)
+        CHK_ERRA(CO_E_FAILEDTOIMPERSONATE)
+        CHK_ERRA(CO_E_FAILEDTOGETSECCTX)
+        CHK_ERRA(CO_E_FAILEDTOOPENTHREADTOKEN)
+        CHK_ERRA(CO_E_FAILEDTOGETTOKENINFO)
+        CHK_ERRA(CO_E_TRUSTEEDOESNTMATCHCLIENT)
+        CHK_ERRA(CO_E_FAILEDTOQUERYCLIENTBLANKET)
+        CHK_ERRA(CO_E_FAILEDTOSETDACL)
+        CHK_ERRA(CO_E_ACCESSCHECKFAILED)
+        CHK_ERRA(CO_E_NETACCESSAPIFAILED)
+        CHK_ERRA(CO_E_WRONGTRUSTEENAMESYNTAX)
+        CHK_ERRA(CO_E_INVALIDSID)
+        CHK_ERRA(CO_E_CONVERSIONFAILED)
+        CHK_ERRA(CO_E_NOMATCHINGSIDFOUND)
+        CHK_ERRA(CO_E_LOOKUPACCSIDFAILED)
+        CHK_ERRA(CO_E_NOMATCHINGNAMEFOUND)
+        CHK_ERRA(CO_E_LOOKUPACCNAMEFAILED)
+        CHK_ERRA(CO_E_SETSERLHNDLFAILED)
+        CHK_ERRA(CO_E_FAILEDTOGETWINDIR)
+        CHK_ERRA(CO_E_PATHTOOLONG)
+        CHK_ERRA(CO_E_FAILEDTOGENUUID)
+        CHK_ERRA(CO_E_FAILEDTOCREATEFILE)
+        CHK_ERRA(CO_E_FAILEDTOCLOSEHANDLE)
+        CHK_ERRA(CO_E_EXCEEDSYSACLLIMIT)
+        CHK_ERRA(CO_E_ACESINWRONGORDER)
+        CHK_ERRA(CO_E_INCOMPATIBLESTREAMVERSION)
+        CHK_ERRA(CO_E_FAILEDTOOPENPROCESSTOKEN)
+        CHK_ERRA(CO_E_DECODEFAILED)
+        CHK_ERRA(CO_E_ACNOTINITIALIZED)
+        CHK_ERRA(RPC_E_UNEXPECTED)
+        CHK_ERRA(NTE_BAD_UID)
+        CHK_ERRA(NTE_BAD_HASH)
+        CHK_ERRA(NTE_BAD_KEY)
+        CHK_ERRA(NTE_BAD_LEN)
+        CHK_ERRA(NTE_BAD_DATA)
+        CHK_ERRA(NTE_BAD_SIGNATURE)
+        CHK_ERRA(NTE_BAD_VER)
+        CHK_ERRA(NTE_BAD_ALGID)
+        CHK_ERRA(NTE_BAD_FLAGS)
+        CHK_ERRA(NTE_BAD_TYPE)
+        CHK_ERRA(NTE_BAD_KEY_STATE)
+        CHK_ERRA(NTE_BAD_HASH_STATE)
+        CHK_ERRA(NTE_NO_KEY)
+        CHK_ERRA(NTE_NO_MEMORY)
+        CHK_ERRA(NTE_EXISTS)
+        CHK_ERRA(NTE_PERM)
+        CHK_ERRA(NTE_NOT_FOUND)
+        CHK_ERRA(NTE_DOUBLE_ENCRYPT)
+        CHK_ERRA(NTE_BAD_PROVIDER)
+        CHK_ERRA(NTE_BAD_PROV_TYPE)
+        CHK_ERRA(NTE_BAD_PUBLIC_KEY)
+        CHK_ERRA(NTE_BAD_KEYSET)
+        CHK_ERRA(NTE_PROV_TYPE_NOT_DEF)
+        CHK_ERRA(NTE_PROV_TYPE_ENTRY_BAD)
+        CHK_ERRA(NTE_KEYSET_NOT_DEF)
+        CHK_ERRA(NTE_KEYSET_ENTRY_BAD)
+        CHK_ERRA(NTE_PROV_TYPE_NO_MATCH)
+        CHK_ERRA(NTE_SIGNATURE_FILE_BAD)
+        CHK_ERRA(NTE_PROVIDER_DLL_FAIL)
+        CHK_ERRA(NTE_PROV_DLL_NOT_FOUND)
+        CHK_ERRA(NTE_BAD_KEYSET_PARAM)
+        CHK_ERRA(NTE_FAIL)
+        CHK_ERRA(NTE_SYS_ERR)
+        CHK_ERRA(NTE_SILENT_CONTEXT)
+        CHK_ERRA(NTE_TOKEN_KEYSET_STORAGE_FULL)
+        CHK_ERRA(CRYPT_E_MSG_ERROR)
+        CHK_ERRA(CRYPT_E_UNKNOWN_ALGO)
+        CHK_ERRA(CRYPT_E_OID_FORMAT)
+        CHK_ERRA(CRYPT_E_INVALID_MSG_TYPE)
+        CHK_ERRA(CRYPT_E_UNEXPECTED_ENCODING)
+        CHK_ERRA(CRYPT_E_AUTH_ATTR_MISSING)
+        CHK_ERRA(CRYPT_E_HASH_VALUE)
+        CHK_ERRA(CRYPT_E_INVALID_INDEX)
+        CHK_ERRA(CRYPT_E_ALREADY_DECRYPTED)
+        CHK_ERRA(CRYPT_E_NOT_DECRYPTED)
+        CHK_ERRA(CRYPT_E_RECIPIENT_NOT_FOUND)
+        CHK_ERRA(CRYPT_E_CONTROL_TYPE)
+        CHK_ERRA(CRYPT_E_ISSUER_SERIALNUMBER)
+        CHK_ERRA(CRYPT_E_SIGNER_NOT_FOUND)
+        CHK_ERRA(CRYPT_E_ATTRIBUTES_MISSING)
+        CHK_ERRA(CRYPT_E_STREAM_MSG_NOT_READY)
+        CHK_ERRA(CRYPT_E_STREAM_INSUFFICIENT_DATA)
+        CHK_ERRA(CRYPT_E_BAD_LEN)
+        CHK_ERRA(CRYPT_E_BAD_ENCODE)
+        CHK_ERRA(CRYPT_E_FILE_ERROR)
+        CHK_ERRA(CRYPT_E_NOT_FOUND)
+        CHK_ERRA(CRYPT_E_EXISTS)
+        CHK_ERRA(CRYPT_E_NO_PROVIDER)
+        CHK_ERRA(CRYPT_E_SELF_SIGNED)
+        CHK_ERRA(CRYPT_E_DELETED_PREV)
+        CHK_ERRA(CRYPT_E_NO_MATCH)
+        CHK_ERRA(CRYPT_E_UNEXPECTED_MSG_TYPE)
+        CHK_ERRA(CRYPT_E_NO_KEY_PROPERTY)
+        CHK_ERRA(CRYPT_E_NO_DECRYPT_CERT)
+        CHK_ERRA(CRYPT_E_BAD_MSG)
+        CHK_ERRA(CRYPT_E_NO_SIGNER)
+        CHK_ERRA(CRYPT_E_PENDING_CLOSE)
+        CHK_ERRA(CRYPT_E_REVOKED)
+        CHK_ERRA(CRYPT_E_NO_REVOCATION_DLL)
+        CHK_ERRA(CRYPT_E_NO_REVOCATION_CHECK)
+        CHK_ERRA(CRYPT_E_REVOCATION_OFFLINE)
+        CHK_ERRA(CRYPT_E_NOT_IN_REVOCATION_DATABASE)
+        CHK_ERRA(CRYPT_E_INVALID_NUMERIC_STRING)
+        CHK_ERRA(CRYPT_E_INVALID_PRINTABLE_STRING)
+        CHK_ERRA(CRYPT_E_INVALID_IA5_STRING)
+        CHK_ERRA(CRYPT_E_INVALID_X500_STRING)
+        CHK_ERRA(CRYPT_E_NOT_CHAR_STRING)
+        CHK_ERRA(CRYPT_E_FILERESIZED)
+        CHK_ERRA(CRYPT_E_SECURITY_SETTINGS)
+        CHK_ERRA(CRYPT_E_NO_VERIFY_USAGE_DLL)
+        CHK_ERRA(CRYPT_E_NO_VERIFY_USAGE_CHECK)
+        CHK_ERRA(CRYPT_E_VERIFY_USAGE_OFFLINE)
+        CHK_ERRA(CRYPT_E_NOT_IN_CTL)
+        CHK_ERRA(CRYPT_E_NO_TRUSTED_SIGNER)
+        CHK_ERRA(CRYPT_E_OSS_ERROR)
+        CHK_ERRA(OSS_MORE_BUF)
+        CHK_ERRA(OSS_NEGATIVE_UINTEGER)
+        CHK_ERRA(OSS_PDU_RANGE)
+        CHK_ERRA(OSS_MORE_INPUT)
+        CHK_ERRA(OSS_DATA_ERROR)
+        CHK_ERRA(OSS_BAD_ARG)
+        CHK_ERRA(OSS_BAD_VERSION)
+        CHK_ERRA(OSS_OUT_MEMORY)
+        CHK_ERRA(OSS_PDU_MISMATCH)
+        CHK_ERRA(OSS_LIMITED)
+        CHK_ERRA(OSS_BAD_PTR)
+        CHK_ERRA(OSS_BAD_TIME)
+        CHK_ERRA(OSS_INDEFINITE_NOT_SUPPORTED)
+        CHK_ERRA(OSS_MEM_ERROR)
+        CHK_ERRA(OSS_BAD_TABLE)
+        CHK_ERRA(OSS_TOO_LONG)
+        CHK_ERRA(OSS_CONSTRAINT_VIOLATED)
+        CHK_ERRA(OSS_FATAL_ERROR)
+        CHK_ERRA(OSS_ACCESS_SERIALIZATION_ERROR)
+        CHK_ERRA(OSS_NULL_TBL)
+        CHK_ERRA(OSS_NULL_FCN)
+        CHK_ERRA(OSS_BAD_ENCRULES)
+        CHK_ERRA(OSS_UNAVAIL_ENCRULES)
+        CHK_ERRA(OSS_CANT_OPEN_TRACE_WINDOW)
+        CHK_ERRA(OSS_UNIMPLEMENTED)
+        CHK_ERRA(OSS_OID_DLL_NOT_LINKED)
+        CHK_ERRA(OSS_CANT_OPEN_TRACE_FILE)
+        CHK_ERRA(OSS_TRACE_FILE_ALREADY_OPEN)
+        CHK_ERRA(OSS_TABLE_MISMATCH)
+        CHK_ERRA(OSS_TYPE_NOT_SUPPORTED)
+        CHK_ERRA(OSS_REAL_DLL_NOT_LINKED)
+        CHK_ERRA(OSS_REAL_CODE_NOT_LINKED)
+        CHK_ERRA(OSS_OUT_OF_RANGE)
+        CHK_ERRA(OSS_COPIER_DLL_NOT_LINKED)
+        CHK_ERRA(OSS_CONSTRAINT_DLL_NOT_LINKED)
+        CHK_ERRA(OSS_COMPARATOR_DLL_NOT_LINKED)
+        CHK_ERRA(OSS_COMPARATOR_CODE_NOT_LINKED)
+        CHK_ERRA(OSS_MEM_MGR_DLL_NOT_LINKED)
+        CHK_ERRA(OSS_PDV_DLL_NOT_LINKED)
+        CHK_ERRA(OSS_PDV_CODE_NOT_LINKED)
+        CHK_ERRA(OSS_API_DLL_NOT_LINKED)
+        CHK_ERRA(OSS_BERDER_DLL_NOT_LINKED)
+        CHK_ERRA(OSS_PER_DLL_NOT_LINKED)
+        CHK_ERRA(OSS_OPEN_TYPE_ERROR)
+        CHK_ERRA(OSS_MUTEX_NOT_CREATED)
+        CHK_ERRA(OSS_CANT_CLOSE_TRACE_FILE)
+        CHK_ERRA(CERTSRV_E_BAD_REQUESTSUBJECT)
+        CHK_ERRA(CERTSRV_E_NO_REQUEST)
+        CHK_ERRA(CERTSRV_E_BAD_REQUESTSTATUS)
+        CHK_ERRA(CERTSRV_E_PROPERTY_EMPTY)
+        CHK_ERRA(CERTSRV_E_INVALID_CA_CERTIFICATE)
+        CHK_ERRA(CERTSRV_E_UNSUPPORTED_CERT_TYPE)
+        CHK_ERRA(CERTSRV_E_NO_CERT_TYPE)
+        CHK_ERRA(TRUST_E_SYSTEM_ERROR)
+        CHK_ERRA(TRUST_E_NO_SIGNER_CERT)
+        CHK_ERRA(TRUST_E_COUNTER_SIGNER)
+        CHK_ERRA(TRUST_E_CERT_SIGNATURE)
+        CHK_ERRA(TRUST_E_TIME_STAMP)
+        CHK_ERRA(TRUST_E_BAD_DIGEST)
+        CHK_ERRA(TRUST_E_BASIC_CONSTRAINTS)
+        CHK_ERRA(TRUST_E_FINANCIAL_CRITERIA)
+//        CHK_ERRA(NTE_OP_OK)
+        CHK_ERRA(TRUST_E_PROVIDER_UNKNOWN)
+        CHK_ERRA(TRUST_E_ACTION_UNKNOWN)
+        CHK_ERRA(TRUST_E_SUBJECT_FORM_UNKNOWN)
+        CHK_ERRA(TRUST_E_SUBJECT_NOT_TRUSTED)
+        CHK_ERRA(DIGSIG_E_ENCODE)
+        CHK_ERRA(DIGSIG_E_DECODE)
+        CHK_ERRA(DIGSIG_E_EXTENSIBILITY)
+        CHK_ERRA(DIGSIG_E_CRYPTO)
+        CHK_ERRA(PERSIST_E_SIZEDEFINITE)
+        CHK_ERRA(PERSIST_E_SIZEINDEFINITE)
+        CHK_ERRA(PERSIST_E_NOTSELFSIZING)
+        CHK_ERRA(TRUST_E_NOSIGNATURE)
+        CHK_ERRA(CERT_E_EXPIRED)
+        CHK_ERRA(CERT_E_VALIDITYPERIODNESTING)
+        CHK_ERRA(CERT_E_ROLE)
+        CHK_ERRA(CERT_E_PATHLENCONST)
+        CHK_ERRA(CERT_E_CRITICAL)
+        CHK_ERRA(CERT_E_PURPOSE)
+        CHK_ERRA(CERT_E_ISSUERCHAINING)
+        CHK_ERRA(CERT_E_MALFORMED)
+        CHK_ERRA(CERT_E_UNTRUSTEDROOT)
+        CHK_ERRA(CERT_E_CHAINING)
+        CHK_ERRA(TRUST_E_FAIL)
+        CHK_ERRA(CERT_E_REVOKED)
+        CHK_ERRA(CERT_E_UNTRUSTEDTESTROOT)
+        CHK_ERRA(CERT_E_REVOCATION_FAILURE)
+        CHK_ERRA(CERT_E_CN_NO_MATCH)
+        CHK_ERRA(CERT_E_WRONG_USAGE)
+        CHK_ERRA(SPAPI_E_EXPECTED_SECTION_NAME)
+        CHK_ERRA(SPAPI_E_BAD_SECTION_NAME_LINE)
+        CHK_ERRA(SPAPI_E_SECTION_NAME_TOO_LONG)
+        CHK_ERRA(SPAPI_E_GENERAL_SYNTAX)
+        CHK_ERRA(SPAPI_E_WRONG_INF_STYLE)
+        CHK_ERRA(SPAPI_E_SECTION_NOT_FOUND)
+        CHK_ERRA(SPAPI_E_LINE_NOT_FOUND)
+        CHK_ERRA(SPAPI_E_NO_BACKUP)
+        CHK_ERRA(SPAPI_E_NO_ASSOCIATED_CLASS)
+        CHK_ERRA(SPAPI_E_CLASS_MISMATCH)
+        CHK_ERRA(SPAPI_E_DUPLICATE_FOUND)
+        CHK_ERRA(SPAPI_E_NO_DRIVER_SELECTED)
+        CHK_ERRA(SPAPI_E_KEY_DOES_NOT_EXIST)
+        CHK_ERRA(SPAPI_E_INVALID_DEVINST_NAME)
+        CHK_ERRA(SPAPI_E_INVALID_CLASS)
+        CHK_ERRA(SPAPI_E_DEVINST_ALREADY_EXISTS)
+        CHK_ERRA(SPAPI_E_DEVINFO_NOT_REGISTERED)
+        CHK_ERRA(SPAPI_E_INVALID_REG_PROPERTY)
+        CHK_ERRA(SPAPI_E_NO_INF)
+        CHK_ERRA(SPAPI_E_NO_SUCH_DEVINST)
+        CHK_ERRA(SPAPI_E_CANT_LOAD_CLASS_ICON)
+        CHK_ERRA(SPAPI_E_INVALID_CLASS_INSTALLER)
+        CHK_ERRA(SPAPI_E_DI_DO_DEFAULT)
+        CHK_ERRA(SPAPI_E_DI_NOFILECOPY)
+        CHK_ERRA(SPAPI_E_INVALID_HWPROFILE)
+        CHK_ERRA(SPAPI_E_NO_DEVICE_SELECTED)
+        CHK_ERRA(SPAPI_E_DEVINFO_LIST_LOCKED)
+        CHK_ERRA(SPAPI_E_DEVINFO_DATA_LOCKED)
+        CHK_ERRA(SPAPI_E_DI_BAD_PATH)
+        CHK_ERRA(SPAPI_E_NO_CLASSINSTALL_PARAMS)
+        CHK_ERRA(SPAPI_E_FILEQUEUE_LOCKED)
+        CHK_ERRA(SPAPI_E_BAD_SERVICE_INSTALLSECT)
+        CHK_ERRA(SPAPI_E_NO_CLASS_DRIVER_LIST)
+        CHK_ERRA(SPAPI_E_NO_ASSOCIATED_SERVICE)
+        CHK_ERRA(SPAPI_E_NO_DEFAULT_DEVICE_INTERFACE)
+        CHK_ERRA(SPAPI_E_DEVICE_INTERFACE_ACTIVE)
+        CHK_ERRA(SPAPI_E_DEVICE_INTERFACE_REMOVED)
+        CHK_ERRA(SPAPI_E_BAD_INTERFACE_INSTALLSECT)
+        CHK_ERRA(SPAPI_E_NO_SUCH_INTERFACE_CLASS)
+        CHK_ERRA(SPAPI_E_INVALID_REFERENCE_STRING)
+        CHK_ERRA(SPAPI_E_INVALID_MACHINENAME)
+        CHK_ERRA(SPAPI_E_REMOTE_COMM_FAILURE)
+        CHK_ERRA(SPAPI_E_MACHINE_UNAVAILABLE)
+        CHK_ERRA(SPAPI_E_NO_CONFIGMGR_SERVICES)
+        CHK_ERRA(SPAPI_E_INVALID_PROPPAGE_PROVIDER)
+        CHK_ERRA(SPAPI_E_NO_SUCH_DEVICE_INTERFACE)
+        CHK_ERRA(SPAPI_E_DI_POSTPROCESSING_REQUIRED)
+        CHK_ERRA(SPAPI_E_INVALID_COINSTALLER)
+        CHK_ERRA(SPAPI_E_NO_COMPAT_DRIVERS)
+        CHK_ERRA(SPAPI_E_NO_DEVICE_ICON)
+        CHK_ERRA(SPAPI_E_INVALID_INF_LOGCONFIG)
+        CHK_ERRA(SPAPI_E_DI_DONT_INSTALL)
+        CHK_ERRA(SPAPI_E_INVALID_FILTER_DRIVER)
+        CHK_ERRA(SPAPI_E_NON_WINDOWS_NT_DRIVER)
+        CHK_ERRA(SPAPI_E_NON_WINDOWS_DRIVER)
+        CHK_ERRA(SPAPI_E_NO_CATALOG_FOR_OEM_INF)
+        CHK_ERRA(SPAPI_E_DEVINSTALL_QUEUE_NONNATIVE)
+        CHK_ERRA(SPAPI_E_ERROR_NOT_INSTALLED)
+//        CHK_ERRA(SCARD_S_SUCCESS)
+        CHK_ERRA(SCARD_F_INTERNAL_ERROR)
+        CHK_ERRA(SCARD_E_CANCELLED)
+        CHK_ERRA(SCARD_E_INVALID_HANDLE)
+        CHK_ERRA(SCARD_E_INVALID_PARAMETER)
+        CHK_ERRA(SCARD_E_INVALID_TARGET)
+        CHK_ERRA(SCARD_E_NO_MEMORY)
+        CHK_ERRA(SCARD_F_WAITED_TOO_LONG)
+        CHK_ERRA(SCARD_E_INSUFFICIENT_BUFFER)
+        CHK_ERRA(SCARD_E_UNKNOWN_READER)
+        CHK_ERRA(SCARD_E_TIMEOUT)
+        CHK_ERRA(SCARD_E_SHARING_VIOLATION)
+        CHK_ERRA(SCARD_E_NO_SMARTCARD)
+        CHK_ERRA(SCARD_E_UNKNOWN_CARD)
+        CHK_ERRA(SCARD_E_CANT_DISPOSE)
+        CHK_ERRA(SCARD_E_PROTO_MISMATCH)
+        CHK_ERRA(SCARD_E_NOT_READY)
+        CHK_ERRA(SCARD_E_INVALID_VALUE)
+        CHK_ERRA(SCARD_E_SYSTEM_CANCELLED)
+        CHK_ERRA(SCARD_F_COMM_ERROR)
+        CHK_ERRA(SCARD_F_UNKNOWN_ERROR)
+        CHK_ERRA(SCARD_E_INVALID_ATR)
+        CHK_ERRA(SCARD_E_NOT_TRANSACTED)
+        CHK_ERRA(SCARD_E_READER_UNAVAILABLE)
+        CHK_ERRA(SCARD_P_SHUTDOWN)
+        CHK_ERRA(SCARD_E_PCI_TOO_SMALL)
+        CHK_ERRA(SCARD_E_READER_UNSUPPORTED)
+        CHK_ERRA(SCARD_E_DUPLICATE_READER)
+        CHK_ERRA(SCARD_E_CARD_UNSUPPORTED)
+        CHK_ERRA(SCARD_E_NO_SERVICE)
+        CHK_ERRA(SCARD_E_SERVICE_STOPPED)
+        CHK_ERRA(SCARD_E_UNEXPECTED)
+        CHK_ERRA(SCARD_E_ICC_INSTALLATION)
+        CHK_ERRA(SCARD_E_ICC_CREATEORDER)
+        CHK_ERRA(SCARD_E_UNSUPPORTED_FEATURE)
+        CHK_ERRA(SCARD_E_DIR_NOT_FOUND)
+        CHK_ERRA(SCARD_E_FILE_NOT_FOUND)
+        CHK_ERRA(SCARD_E_NO_DIR)
+        CHK_ERRA(SCARD_E_NO_FILE)
+        CHK_ERRA(SCARD_E_NO_ACCESS)
+        CHK_ERRA(SCARD_E_WRITE_TOO_MANY)
+        CHK_ERRA(SCARD_E_BAD_SEEK)
+        CHK_ERRA(SCARD_E_INVALID_CHV)
+        CHK_ERRA(SCARD_E_UNKNOWN_RES_MNG)
+        CHK_ERRA(SCARD_E_NO_SUCH_CERTIFICATE)
+        CHK_ERRA(SCARD_E_CERTIFICATE_UNAVAILABLE)
+        CHK_ERRA(SCARD_E_NO_READERS_AVAILABLE)
+        CHK_ERRA(SCARD_E_COMM_DATA_LOST)
+        CHK_ERRA(SCARD_W_UNSUPPORTED_CARD)
+        CHK_ERRA(SCARD_W_UNRESPONSIVE_CARD)
+        CHK_ERRA(SCARD_W_UNPOWERED_CARD)
+        CHK_ERRA(SCARD_W_RESET_CARD)
+        CHK_ERRA(SCARD_W_REMOVED_CARD)
+        CHK_ERRA(SCARD_W_SECURITY_VIOLATION)
+        CHK_ERRA(SCARD_W_WRONG_CHV)
+        CHK_ERRA(SCARD_W_CHV_BLOCKED)
+        CHK_ERRA(SCARD_W_EOF)
+        CHK_ERRA(SCARD_W_CANCELLED_BY_USER)
+        CHK_ERR_WIN32_ONLY(ERROR_INVALID_FUNCTION, "ERROR_INVALID_FUNCTION")
+        CHK_ERR_WIN32A(ERROR_FILE_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_PATH_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_TOO_MANY_OPEN_FILES)
+        CHK_ERRA(ERROR_ACCESS_DENIED)
+        CHK_ERRA(ERROR_INVALID_HANDLE)
+        CHK_ERR_WIN32A(ERROR_ARENA_TRASHED)
+        CHK_ERR_WIN32A(ERROR_NOT_ENOUGH_MEMORY)
+        CHK_ERR_WIN32A(ERROR_INVALID_BLOCK)
+        CHK_ERR_WIN32A(ERROR_BAD_ENVIRONMENT)
+        CHK_ERR_WIN32A(ERROR_BAD_FORMAT)
+        CHK_ERR_WIN32A(ERROR_INVALID_ACCESS)
+        CHK_ERR_WIN32A(ERROR_INVALID_DATA)
+        CHK_ERRA(ERROR_OUTOFMEMORY)
+        CHK_ERR_WIN32A(ERROR_INVALID_DRIVE)
+        CHK_ERR_WIN32A(ERROR_CURRENT_DIRECTORY)
+        CHK_ERR_WIN32A(ERROR_NOT_SAME_DEVICE)
+        CHK_ERR_WIN32A(ERROR_NO_MORE_FILES)
+        CHK_ERR_WIN32A(ERROR_WRITE_PROTECT)
+        CHK_ERR_WIN32A(ERROR_BAD_UNIT)
+        CHK_ERR_WIN32A(ERROR_NOT_READY)
+        CHK_ERR_WIN32A(ERROR_BAD_COMMAND)
+        CHK_ERR_WIN32A(ERROR_CRC)
+        CHK_ERR_WIN32A(ERROR_BAD_LENGTH)
+        CHK_ERR_WIN32A(ERROR_SEEK)
+        CHK_ERR_WIN32A(ERROR_NOT_DOS_DISK)
+        CHK_ERR_WIN32A(ERROR_SECTOR_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_OUT_OF_PAPER)
+        CHK_ERR_WIN32A(ERROR_WRITE_FAULT)
+        CHK_ERR_WIN32A(ERROR_READ_FAULT)
+        CHK_ERR_WIN32A(ERROR_GEN_FAILURE)
+        CHK_ERR_WIN32A(ERROR_SHARING_VIOLATION)
+        CHK_ERR_WIN32A(ERROR_LOCK_VIOLATION)
+        CHK_ERR_WIN32A(ERROR_WRONG_DISK)
+        CHK_ERR_WIN32A(ERROR_SHARING_BUFFER_EXCEEDED)
+        CHK_ERR_WIN32A(ERROR_HANDLE_EOF)
+        CHK_ERR_WIN32A(ERROR_HANDLE_DISK_FULL)
+        CHK_ERR_WIN32A(ERROR_NOT_SUPPORTED)
+        CHK_ERR_WIN32A(ERROR_REM_NOT_LIST)
+        CHK_ERR_WIN32A(ERROR_DUP_NAME)
+        CHK_ERR_WIN32A(ERROR_BAD_NETPATH)
+        CHK_ERR_WIN32A(ERROR_NETWORK_BUSY)
+        CHK_ERR_WIN32A(ERROR_DEV_NOT_EXIST)
+        CHK_ERR_WIN32A(ERROR_TOO_MANY_CMDS)
+        CHK_ERR_WIN32A(ERROR_ADAP_HDW_ERR)
+        CHK_ERR_WIN32A(ERROR_BAD_NET_RESP)
+        CHK_ERR_WIN32A(ERROR_UNEXP_NET_ERR)
+        CHK_ERR_WIN32A(ERROR_BAD_REM_ADAP)
+        CHK_ERR_WIN32A(ERROR_PRINTQ_FULL)
+        CHK_ERR_WIN32A(ERROR_NO_SPOOL_SPACE)
+        CHK_ERR_WIN32A(ERROR_PRINT_CANCELLED)
+        CHK_ERR_WIN32A(ERROR_NETNAME_DELETED)
+        CHK_ERR_WIN32A(ERROR_NETWORK_ACCESS_DENIED)
+        CHK_ERR_WIN32A(ERROR_BAD_DEV_TYPE)
+        CHK_ERR_WIN32A(ERROR_BAD_NET_NAME)
+        CHK_ERR_WIN32A(ERROR_TOO_MANY_NAMES)
+        CHK_ERR_WIN32A(ERROR_TOO_MANY_SESS)
+        CHK_ERR_WIN32A(ERROR_SHARING_PAUSED)
+        CHK_ERR_WIN32A(ERROR_REQ_NOT_ACCEP)
+        CHK_ERR_WIN32A(ERROR_REDIR_PAUSED)
+        CHK_ERR_WIN32A(ERROR_FILE_EXISTS)
+        CHK_ERR_WIN32A(ERROR_CANNOT_MAKE)
+        CHK_ERR_WIN32A(ERROR_FAIL_I24)
+        CHK_ERR_WIN32A(ERROR_OUT_OF_STRUCTURES)
+        CHK_ERR_WIN32A(ERROR_ALREADY_ASSIGNED)
+        CHK_ERR_WIN32A(ERROR_INVALID_PASSWORD)
+        CHK_ERRA(ERROR_INVALID_PARAMETER)
+        CHK_ERR_WIN32A(ERROR_NET_WRITE_FAULT)
+        CHK_ERR_WIN32A(ERROR_NO_PROC_SLOTS)
+        CHK_ERR_WIN32A(ERROR_TOO_MANY_SEMAPHORES)
+        CHK_ERR_WIN32A(ERROR_EXCL_SEM_ALREADY_OWNED)
+        CHK_ERR_WIN32A(ERROR_SEM_IS_SET)
+        CHK_ERR_WIN32A(ERROR_TOO_MANY_SEM_REQUESTS)
+        CHK_ERR_WIN32A(ERROR_INVALID_AT_INTERRUPT_TIME)
+        CHK_ERR_WIN32A(ERROR_SEM_OWNER_DIED)
+        CHK_ERR_WIN32A(ERROR_SEM_USER_LIMIT)
+        CHK_ERR_WIN32A(ERROR_DISK_CHANGE)
+        CHK_ERR_WIN32A(ERROR_DRIVE_LOCKED)
+        CHK_ERR_WIN32A(ERROR_BROKEN_PIPE)
+        CHK_ERR_WIN32A(ERROR_OPEN_FAILED)
+        CHK_ERR_WIN32A(ERROR_BUFFER_OVERFLOW)
+        CHK_ERR_WIN32A(ERROR_DISK_FULL)
+        CHK_ERR_WIN32A(ERROR_NO_MORE_SEARCH_HANDLES)
+        CHK_ERR_WIN32A(ERROR_INVALID_TARGET_HANDLE)
+        CHK_ERR_WIN32A(ERROR_INVALID_CATEGORY)
+        CHK_ERR_WIN32A(ERROR_INVALID_VERIFY_SWITCH)
+        CHK_ERR_WIN32A(ERROR_BAD_DRIVER_LEVEL)
+        CHK_ERR_WIN32A(ERROR_CALL_NOT_IMPLEMENTED)
+        CHK_ERR_WIN32A(ERROR_SEM_TIMEOUT)
+        CHK_ERR_WIN32A(ERROR_INSUFFICIENT_BUFFER)
+        CHK_ERR_WIN32A(ERROR_INVALID_NAME)
+        CHK_ERR_WIN32A(ERROR_INVALID_LEVEL)
+        CHK_ERR_WIN32A(ERROR_NO_VOLUME_LABEL)
+        CHK_ERR_WIN32A(ERROR_MOD_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_PROC_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_WAIT_NO_CHILDREN)
+        CHK_ERR_WIN32A(ERROR_CHILD_NOT_COMPLETE)
+        CHK_ERR_WIN32A(ERROR_DIRECT_ACCESS_HANDLE)
+        CHK_ERR_WIN32A(ERROR_NEGATIVE_SEEK)
+        CHK_ERR_WIN32A(ERROR_SEEK_ON_DEVICE)
+        CHK_ERR_WIN32A(ERROR_IS_JOIN_TARGET)
+        CHK_ERR_WIN32A(ERROR_IS_JOINED)
+        CHK_ERR_WIN32A(ERROR_IS_SUBSTED)
+        CHK_ERR_WIN32A(ERROR_NOT_JOINED)
+        CHK_ERR_WIN32A(ERROR_NOT_SUBSTED)
+        CHK_ERR_WIN32A(ERROR_JOIN_TO_JOIN)
+        CHK_ERR_WIN32A(ERROR_SUBST_TO_SUBST)
+        CHK_ERR_WIN32A(ERROR_JOIN_TO_SUBST)
+        CHK_ERR_WIN32A(ERROR_SUBST_TO_JOIN)
+        CHK_ERR_WIN32A(ERROR_BUSY_DRIVE)
+        CHK_ERR_WIN32A(ERROR_SAME_DRIVE)
+        CHK_ERR_WIN32A(ERROR_DIR_NOT_ROOT)
+        CHK_ERR_WIN32A(ERROR_DIR_NOT_EMPTY)
+        CHK_ERR_WIN32A(ERROR_IS_SUBST_PATH)
+        CHK_ERR_WIN32A(ERROR_IS_JOIN_PATH)
+        CHK_ERR_WIN32A(ERROR_PATH_BUSY)
+        CHK_ERR_WIN32A(ERROR_IS_SUBST_TARGET)
+        CHK_ERR_WIN32A(ERROR_SYSTEM_TRACE)
+        CHK_ERR_WIN32A(ERROR_INVALID_EVENT_COUNT)
+        CHK_ERR_WIN32A(ERROR_TOO_MANY_MUXWAITERS)
+        CHK_ERR_WIN32A(ERROR_INVALID_LIST_FORMAT)
+        CHK_ERR_WIN32A(ERROR_LABEL_TOO_LONG)
+        CHK_ERR_WIN32A(ERROR_TOO_MANY_TCBS)
+        CHK_ERR_WIN32A(ERROR_SIGNAL_REFUSED)
+        CHK_ERR_WIN32A(ERROR_DISCARDED)
+        CHK_ERR_WIN32A(ERROR_NOT_LOCKED)
+        CHK_ERR_WIN32A(ERROR_BAD_THREADID_ADDR)
+        CHK_ERR_WIN32A(ERROR_BAD_ARGUMENTS)
+        CHK_ERR_WIN32A(ERROR_BAD_PATHNAME)
+        CHK_ERR_WIN32A(ERROR_SIGNAL_PENDING)
+        CHK_ERR_WIN32A(ERROR_MAX_THRDS_REACHED)
+        CHK_ERR_WIN32A(ERROR_LOCK_FAILED)
+        CHK_ERR_WIN32A(ERROR_BUSY)
+        CHK_ERR_WIN32A(ERROR_CANCEL_VIOLATION)
+        CHK_ERR_WIN32A(ERROR_ATOMIC_LOCKS_NOT_SUPPORTED)
+        CHK_ERR_WIN32A(ERROR_INVALID_SEGMENT_NUMBER)
+        CHK_ERR_WIN32A(ERROR_INVALID_ORDINAL)
+        CHK_ERR_WIN32A(ERROR_ALREADY_EXISTS)
+        CHK_ERR_WIN32A(ERROR_INVALID_FLAG_NUMBER)
+        CHK_ERR_WIN32A(ERROR_SEM_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_INVALID_STARTING_CODESEG)
+        CHK_ERR_WIN32A(ERROR_INVALID_STACKSEG)
+        CHK_ERR_WIN32A(ERROR_INVALID_MODULETYPE)
+        CHK_ERR_WIN32A(ERROR_INVALID_EXE_SIGNATURE)
+        CHK_ERR_WIN32A(ERROR_EXE_MARKED_INVALID)
+        CHK_ERR_WIN32A(ERROR_BAD_EXE_FORMAT)
+        CHK_ERR_WIN32A(ERROR_ITERATED_DATA_EXCEEDS_64k)
+        CHK_ERR_WIN32A(ERROR_INVALID_MINALLOCSIZE)
+        CHK_ERR_WIN32A(ERROR_DYNLINK_FROM_INVALID_RING)
+        CHK_ERR_WIN32A(ERROR_IOPL_NOT_ENABLED)
+        CHK_ERR_WIN32A(ERROR_INVALID_SEGDPL)
+        CHK_ERR_WIN32A(ERROR_AUTODATASEG_EXCEEDS_64k)
+        CHK_ERRA(ERROR_RING2SEG_MUST_BE_MOVABLE)
+        CHK_ERRA(ERROR_RELOC_CHAIN_XEEDS_SEGLIM)
+        CHK_ERR_WIN32A(ERROR_INFLOOP_IN_RELOC_CHAIN)
+        CHK_ERR_WIN32A(ERROR_ENVVAR_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_NO_SIGNAL_SENT)
+        CHK_ERR_WIN32A(ERROR_FILENAME_EXCED_RANGE)
+        CHK_ERR_WIN32A(ERROR_RING2_STACK_IN_USE)
+        CHK_ERR_WIN32A(ERROR_META_EXPANSION_TOO_LONG)
+        CHK_ERR_WIN32A(ERROR_INVALID_SIGNAL_NUMBER)
+        CHK_ERR_WIN32A(ERROR_THREAD_1_INACTIVE)
+        CHK_ERR_WIN32A(ERROR_LOCKED)
+        CHK_ERR_WIN32A(ERROR_TOO_MANY_MODULES)
+        CHK_ERR_WIN32A(ERROR_NESTING_NOT_ALLOWED)
+        CHK_ERR_WIN32A(ERROR_EXE_MACHINE_TYPE_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_BAD_PIPE)
+        CHK_ERR_WIN32A(ERROR_PIPE_BUSY)
+        CHK_ERR_WIN32A(ERROR_NO_DATA)
+        CHK_ERR_WIN32A(ERROR_PIPE_NOT_CONNECTED)
+        CHK_ERR_WIN32A(ERROR_MORE_DATA)
+        CHK_ERR_WIN32A(ERROR_VC_DISCONNECTED)
+        CHK_ERR_WIN32A(ERROR_INVALID_EA_NAME)
+        CHK_ERR_WIN32A(ERROR_EA_LIST_INCONSISTENT)
+        CHK_ERR_WIN32A(WAIT_TIMEOUT)
+        CHK_ERR_WIN32A(ERROR_NO_MORE_ITEMS)
+        CHK_ERR_WIN32A(ERROR_CANNOT_COPY)
+        CHK_ERR_WIN32A(ERROR_DIRECTORY)
+        CHK_ERR_WIN32A(ERROR_EAS_DIDNT_FIT)
+        CHK_ERR_WIN32A(ERROR_EA_FILE_CORRUPT)
+        CHK_ERR_WIN32A(ERROR_EA_TABLE_FULL)
+        CHK_ERR_WIN32A(ERROR_INVALID_EA_HANDLE)
+        CHK_ERR_WIN32A(ERROR_EAS_NOT_SUPPORTED)
+        CHK_ERR_WIN32A(ERROR_NOT_OWNER)
+        CHK_ERR_WIN32A(ERROR_TOO_MANY_POSTS)
+        CHK_ERR_WIN32A(ERROR_PARTIAL_COPY)
+        CHK_ERR_WIN32A(ERROR_OPLOCK_NOT_GRANTED)
+        CHK_ERR_WIN32A(ERROR_INVALID_OPLOCK_PROTOCOL)
+        CHK_ERR_WIN32A(ERROR_MR_MID_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_INVALID_ADDRESS)
+        CHK_ERR_WIN32A(ERROR_ARITHMETIC_OVERFLOW)
+        CHK_ERR_WIN32A(ERROR_PIPE_CONNECTED)
+        CHK_ERR_WIN32A(ERROR_PIPE_LISTENING)
+        CHK_ERR_WIN32A(ERROR_EA_ACCESS_DENIED)
+        CHK_ERR_WIN32A(ERROR_OPERATION_ABORTED)
+        CHK_ERR_WIN32A(ERROR_IO_INCOMPLETE)
+        CHK_ERR_WIN32A(ERROR_IO_PENDING)
+        CHK_ERR_WIN32A(ERROR_NOACCESS)
+        CHK_ERR_WIN32A(ERROR_SWAPERROR)
+        CHK_ERR_WIN32A(ERROR_STACK_OVERFLOW)
+        CHK_ERR_WIN32A(ERROR_INVALID_MESSAGE)
+        CHK_ERR_WIN32A(ERROR_CAN_NOT_COMPLETE)
+        CHK_ERR_WIN32A(ERROR_INVALID_FLAGS)
+        CHK_ERR_WIN32A(ERROR_UNRECOGNIZED_VOLUME)
+        CHK_ERR_WIN32A(ERROR_FILE_INVALID)
+        CHK_ERR_WIN32A(ERROR_FULLSCREEN_MODE)
+        CHK_ERR_WIN32A(ERROR_NO_TOKEN)
+        CHK_ERR_WIN32A(ERROR_BADDB)
+        CHK_ERR_WIN32A(ERROR_BADKEY)
+        CHK_ERR_WIN32A(ERROR_CANTOPEN)
+        CHK_ERR_WIN32A(ERROR_CANTREAD)
+        CHK_ERR_WIN32A(ERROR_CANTWRITE)
+        CHK_ERR_WIN32A(ERROR_REGISTRY_RECOVERED)
+        CHK_ERR_WIN32A(ERROR_REGISTRY_CORRUPT)
+        CHK_ERR_WIN32A(ERROR_REGISTRY_IO_FAILED)
+        CHK_ERR_WIN32A(ERROR_NOT_REGISTRY_FILE)
+        CHK_ERR_WIN32A(ERROR_KEY_DELETED)
+        CHK_ERR_WIN32A(ERROR_NO_LOG_SPACE)
+        CHK_ERR_WIN32A(ERROR_KEY_HAS_CHILDREN)
+        CHK_ERR_WIN32A(ERROR_CHILD_MUST_BE_VOLATILE)
+        CHK_ERR_WIN32A(ERROR_NOTIFY_ENUM_DIR)
+        CHK_ERR_WIN32A(ERROR_DEPENDENT_SERVICES_RUNNING)
+        CHK_ERR_WIN32A(ERROR_INVALID_SERVICE_CONTROL)
+        CHK_ERR_WIN32A(ERROR_SERVICE_REQUEST_TIMEOUT)
+        CHK_ERR_WIN32A(ERROR_SERVICE_NO_THREAD)
+        CHK_ERR_WIN32A(ERROR_SERVICE_DATABASE_LOCKED)
+        CHK_ERR_WIN32A(ERROR_SERVICE_ALREADY_RUNNING)
+        CHK_ERR_WIN32A(ERROR_INVALID_SERVICE_ACCOUNT)
+        CHK_ERR_WIN32A(ERROR_SERVICE_DISABLED)
+        CHK_ERR_WIN32A(ERROR_CIRCULAR_DEPENDENCY)
+        CHK_ERR_WIN32A(ERROR_SERVICE_DOES_NOT_EXIST)
+        CHK_ERR_WIN32A(ERROR_SERVICE_CANNOT_ACCEPT_CTRL)
+        CHK_ERR_WIN32A(ERROR_SERVICE_NOT_ACTIVE)
+        CHK_ERR_WIN32A(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
+        CHK_ERR_WIN32A(ERROR_EXCEPTION_IN_SERVICE)
+        CHK_ERR_WIN32A(ERROR_DATABASE_DOES_NOT_EXIST)
+        CHK_ERR_WIN32A(ERROR_SERVICE_SPECIFIC_ERROR)
+        CHK_ERR_WIN32A(ERROR_PROCESS_ABORTED)
+        CHK_ERR_WIN32A(ERROR_SERVICE_DEPENDENCY_FAIL)
+        CHK_ERR_WIN32A(ERROR_SERVICE_LOGON_FAILED)
+        CHK_ERR_WIN32A(ERROR_SERVICE_START_HANG)
+        CHK_ERR_WIN32A(ERROR_INVALID_SERVICE_LOCK)
+        CHK_ERR_WIN32A(ERROR_SERVICE_MARKED_FOR_DELETE)
+        CHK_ERR_WIN32A(ERROR_SERVICE_EXISTS)
+        CHK_ERR_WIN32A(ERROR_ALREADY_RUNNING_LKG)
+        CHK_ERR_WIN32A(ERROR_SERVICE_DEPENDENCY_DELETED)
+        CHK_ERR_WIN32A(ERROR_BOOT_ALREADY_ACCEPTED)
+        CHK_ERR_WIN32A(ERROR_SERVICE_NEVER_STARTED)
+        CHK_ERR_WIN32A(ERROR_DUPLICATE_SERVICE_NAME)
+        CHK_ERR_WIN32A(ERROR_DIFFERENT_SERVICE_ACCOUNT)
+        CHK_ERR_WIN32A(ERROR_CANNOT_DETECT_DRIVER_FAILURE)
+        CHK_ERR_WIN32A(ERROR_CANNOT_DETECT_PROCESS_ABORT)
+        CHK_ERR_WIN32A(ERROR_NO_RECOVERY_PROGRAM)
+        CHK_ERR_WIN32A(ERROR_SERVICE_NOT_IN_EXE)
+        CHK_ERR_WIN32A(ERROR_END_OF_MEDIA)
+        CHK_ERR_WIN32A(ERROR_FILEMARK_DETECTED)
+        CHK_ERR_WIN32A(ERROR_BEGINNING_OF_MEDIA)
+        CHK_ERR_WIN32A(ERROR_SETMARK_DETECTED)
+        CHK_ERR_WIN32A(ERROR_NO_DATA_DETECTED)
+        CHK_ERR_WIN32A(ERROR_PARTITION_FAILURE)
+        CHK_ERR_WIN32A(ERROR_INVALID_BLOCK_LENGTH)
+        CHK_ERR_WIN32A(ERROR_DEVICE_NOT_PARTITIONED)
+        CHK_ERR_WIN32A(ERROR_UNABLE_TO_LOCK_MEDIA)
+        CHK_ERR_WIN32A(ERROR_UNABLE_TO_UNLOAD_MEDIA)
+        CHK_ERR_WIN32A(ERROR_MEDIA_CHANGED)
+        CHK_ERR_WIN32A(ERROR_BUS_RESET)
+        CHK_ERR_WIN32A(ERROR_NO_MEDIA_IN_DRIVE)
+        CHK_ERR_WIN32A(ERROR_NO_UNICODE_TRANSLATION)
+        CHK_ERR_WIN32A(ERROR_DLL_INIT_FAILED)
+        CHK_ERR_WIN32A(ERROR_SHUTDOWN_IN_PROGRESS)
+        CHK_ERR_WIN32A(ERROR_NO_SHUTDOWN_IN_PROGRESS)
+        CHK_ERR_WIN32A(ERROR_IO_DEVICE)
+        CHK_ERR_WIN32A(ERROR_SERIAL_NO_DEVICE)
+        CHK_ERR_WIN32A(ERROR_IRQ_BUSY)
+        CHK_ERR_WIN32A(ERROR_MORE_WRITES)
+        CHK_ERR_WIN32A(ERROR_COUNTER_TIMEOUT)
+        CHK_ERR_WIN32A(ERROR_FLOPPY_ID_MARK_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_FLOPPY_WRONG_CYLINDER)
+        CHK_ERR_WIN32A(ERROR_FLOPPY_UNKNOWN_ERROR)
+        CHK_ERR_WIN32A(ERROR_FLOPPY_BAD_REGISTERS)
+        CHK_ERR_WIN32A(ERROR_DISK_RECALIBRATE_FAILED)
+        CHK_ERR_WIN32A(ERROR_DISK_OPERATION_FAILED)
+        CHK_ERR_WIN32A(ERROR_DISK_RESET_FAILED)
+        CHK_ERR_WIN32A(ERROR_EOM_OVERFLOW)
+        CHK_ERR_WIN32A(ERROR_NOT_ENOUGH_SERVER_MEMORY)
+        CHK_ERR_WIN32A(ERROR_POSSIBLE_DEADLOCK)
+        CHK_ERR_WIN32A(ERROR_MAPPED_ALIGNMENT)
+        CHK_ERR_WIN32A(ERROR_SET_POWER_STATE_VETOED)
+        CHK_ERR_WIN32A(ERROR_SET_POWER_STATE_FAILED)
+        CHK_ERR_WIN32A(ERROR_TOO_MANY_LINKS)
+        CHK_ERR_WIN32A(ERROR_OLD_WIN_VERSION)
+        CHK_ERR_WIN32A(ERROR_APP_WRONG_OS)
+        CHK_ERR_WIN32A(ERROR_SINGLE_INSTANCE_APP)
+        CHK_ERR_WIN32A(ERROR_RMODE_APP)
+        CHK_ERR_WIN32A(ERROR_INVALID_DLL)
+        CHK_ERR_WIN32A(ERROR_NO_ASSOCIATION)
+        CHK_ERR_WIN32A(ERROR_DDE_FAIL)
+        CHK_ERR_WIN32A(ERROR_DLL_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_NO_MORE_USER_HANDLES)
+        CHK_ERR_WIN32A(ERROR_MESSAGE_SYNC_ONLY)
+        CHK_ERR_WIN32A(ERROR_SOURCE_ELEMENT_EMPTY)
+        CHK_ERR_WIN32A(ERROR_DESTINATION_ELEMENT_FULL)
+        CHK_ERR_WIN32A(ERROR_ILLEGAL_ELEMENT_ADDRESS)
+        CHK_ERR_WIN32A(ERROR_MAGAZINE_NOT_PRESENT)
+        CHK_ERR_WIN32A(ERROR_DEVICE_REINITIALIZATION_NEEDED)
+        CHK_ERR_WIN32A(ERROR_DEVICE_REQUIRES_CLEANING)
+        CHK_ERR_WIN32A(ERROR_DEVICE_DOOR_OPEN)
+        CHK_ERR_WIN32A(ERROR_DEVICE_NOT_CONNECTED)
+        CHK_ERR_WIN32A(ERROR_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_NO_MATCH)
+        CHK_ERR_WIN32A(ERROR_SET_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_POINT_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_NO_TRACKING_SERVICE)
+        CHK_ERR_WIN32A(ERROR_NO_VOLUME_ID)
+        CHK_ERR_WIN32A(ERROR_UNABLE_TO_REMOVE_REPLACED)
+        CHK_ERR_WIN32A(ERROR_UNABLE_TO_MOVE_REPLACEMENT)
+        CHK_ERR_WIN32A(ERROR_UNABLE_TO_MOVE_REPLACEMENT_2)
+        CHK_ERR_WIN32A(ERROR_JOURNAL_DELETE_IN_PROGRESS)
+        CHK_ERR_WIN32A(ERROR_JOURNAL_NOT_ACTIVE)
+        CHK_ERR_WIN32A(ERROR_POTENTIAL_FILE_FOUND)
+        CHK_ERR_WIN32A(ERROR_BAD_DEVICE)
+        CHK_ERR_WIN32A(ERROR_CONNECTION_UNAVAIL)
+        CHK_ERR_WIN32A(ERROR_DEVICE_ALREADY_REMEMBERED)
+        CHK_ERR_WIN32A(ERROR_NO_NET_OR_BAD_PATH)
+        CHK_ERR_WIN32A(ERROR_BAD_PROVIDER)
+        CHK_ERR_WIN32A(ERROR_CANNOT_OPEN_PROFILE)
+        CHK_ERR_WIN32A(ERROR_BAD_PROFILE)
+        CHK_ERR_WIN32A(ERROR_NOT_CONTAINER)
+        CHK_ERR_WIN32A(ERROR_EXTENDED_ERROR)
+        CHK_ERR_WIN32A(ERROR_INVALID_GROUPNAME)
+        CHK_ERR_WIN32A(ERROR_INVALID_COMPUTERNAME)
+        CHK_ERR_WIN32A(ERROR_INVALID_EVENTNAME)
+        CHK_ERR_WIN32A(ERROR_INVALID_DOMAINNAME)
+        CHK_ERR_WIN32A(ERROR_INVALID_SERVICENAME)
+        CHK_ERR_WIN32A(ERROR_INVALID_NETNAME)
+        CHK_ERR_WIN32A(ERROR_INVALID_SHARENAME)
+        CHK_ERR_WIN32A(ERROR_INVALID_PASSWORDNAME)
+        CHK_ERR_WIN32A(ERROR_INVALID_MESSAGENAME)
+        CHK_ERR_WIN32A(ERROR_INVALID_MESSAGEDEST)
+        CHK_ERR_WIN32A(ERROR_SESSION_CREDENTIAL_CONFLICT)
+        CHK_ERR_WIN32A(ERROR_REMOTE_SESSION_LIMIT_EXCEEDED)
+        CHK_ERR_WIN32A(ERROR_DUP_DOMAINNAME)
+        CHK_ERR_WIN32A(ERROR_NO_NETWORK)
+        CHK_ERR_WIN32A(ERROR_CANCELLED)
+        CHK_ERR_WIN32A(ERROR_USER_MAPPED_FILE)
+        CHK_ERR_WIN32A(ERROR_CONNECTION_REFUSED)
+        CHK_ERR_WIN32A(ERROR_GRACEFUL_DISCONNECT)
+        CHK_ERR_WIN32A(ERROR_ADDRESS_ALREADY_ASSOCIATED)
+        CHK_ERR_WIN32A(ERROR_ADDRESS_NOT_ASSOCIATED)
+        CHK_ERR_WIN32A(ERROR_CONNECTION_INVALID)
+        CHK_ERR_WIN32A(ERROR_CONNECTION_ACTIVE)
+        CHK_ERR_WIN32A(ERROR_NETWORK_UNREACHABLE)
+        CHK_ERR_WIN32A(ERROR_HOST_UNREACHABLE)
+        CHK_ERR_WIN32A(ERROR_PROTOCOL_UNREACHABLE)
+        CHK_ERR_WIN32A(ERROR_PORT_UNREACHABLE)
+        CHK_ERR_WIN32A(ERROR_REQUEST_ABORTED)
+        CHK_ERR_WIN32A(ERROR_CONNECTION_ABORTED)
+        CHK_ERR_WIN32A(ERROR_RETRY)
+        CHK_ERR_WIN32A(ERROR_CONNECTION_COUNT_LIMIT)
+        CHK_ERR_WIN32A(ERROR_LOGIN_TIME_RESTRICTION)
+        CHK_ERR_WIN32A(ERROR_LOGIN_WKSTA_RESTRICTION)
+        CHK_ERR_WIN32A(ERROR_INCORRECT_ADDRESS)
+        CHK_ERR_WIN32A(ERROR_ALREADY_REGISTERED)
+        CHK_ERR_WIN32A(ERROR_SERVICE_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_NOT_AUTHENTICATED)
+        CHK_ERR_WIN32A(ERROR_NOT_LOGGED_ON)
+        CHK_ERR_WIN32A(ERROR_CONTINUE)
+        CHK_ERR_WIN32A(ERROR_ALREADY_INITIALIZED)
+        CHK_ERR_WIN32A(ERROR_NO_MORE_DEVICES)
+        CHK_ERR_WIN32A(ERROR_NO_SUCH_SITE)
+        CHK_ERR_WIN32A(ERROR_DOMAIN_CONTROLLER_EXISTS)
+        CHK_ERR_WIN32A(ERROR_NOT_ALL_ASSIGNED)
+        CHK_ERR_WIN32A(ERROR_SOME_NOT_MAPPED)
+        CHK_ERR_WIN32A(ERROR_NO_QUOTAS_FOR_ACCOUNT)
+        CHK_ERR_WIN32A(ERROR_LOCAL_USER_SESSION_KEY)
+        CHK_ERR_WIN32A(ERROR_NULL_LM_PASSWORD)
+        CHK_ERR_WIN32A(ERROR_UNKNOWN_REVISION)
+        CHK_ERR_WIN32A(ERROR_REVISION_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_INVALID_OWNER)
+        CHK_ERR_WIN32A(ERROR_INVALID_PRIMARY_GROUP)
+        CHK_ERR_WIN32A(ERROR_NO_IMPERSONATION_TOKEN)
+        CHK_ERR_WIN32A(ERROR_CANT_DISABLE_MANDATORY)
+        CHK_ERR_WIN32A(ERROR_NO_LOGON_SERVERS)
+        CHK_ERR_WIN32A(ERROR_NO_SUCH_LOGON_SESSION)
+        CHK_ERR_WIN32A(ERROR_NO_SUCH_PRIVILEGE)
+        CHK_ERR_WIN32A(ERROR_PRIVILEGE_NOT_HELD)
+        CHK_ERR_WIN32A(ERROR_INVALID_ACCOUNT_NAME)
+        CHK_ERR_WIN32A(ERROR_USER_EXISTS)
+        CHK_ERR_WIN32A(ERROR_NO_SUCH_USER)
+        CHK_ERR_WIN32A(ERROR_GROUP_EXISTS)
+        CHK_ERR_WIN32A(ERROR_NO_SUCH_GROUP)
+        CHK_ERR_WIN32A(ERROR_MEMBER_IN_GROUP)
+        CHK_ERR_WIN32A(ERROR_MEMBER_NOT_IN_GROUP)
+        CHK_ERR_WIN32A(ERROR_LAST_ADMIN)
+        CHK_ERR_WIN32A(ERROR_WRONG_PASSWORD)
+        CHK_ERR_WIN32A(ERROR_ILL_FORMED_PASSWORD)
+        CHK_ERR_WIN32A(ERROR_PASSWORD_RESTRICTION)
+        CHK_ERR_WIN32A(ERROR_LOGON_FAILURE)
+        CHK_ERR_WIN32A(ERROR_ACCOUNT_RESTRICTION)
+        CHK_ERR_WIN32A(ERROR_INVALID_LOGON_HOURS)
+        CHK_ERR_WIN32A(ERROR_INVALID_WORKSTATION)
+        CHK_ERR_WIN32A(ERROR_PASSWORD_EXPIRED)
+        CHK_ERR_WIN32A(ERROR_ACCOUNT_DISABLED)
+        CHK_ERR_WIN32A(ERROR_NONE_MAPPED)
+        CHK_ERR_WIN32A(ERROR_TOO_MANY_LUIDS_REQUESTED)
+        CHK_ERR_WIN32A(ERROR_LUIDS_EXHAUSTED)
+        CHK_ERR_WIN32A(ERROR_INVALID_SUB_AUTHORITY)
+        CHK_ERR_WIN32A(ERROR_INVALID_ACL)
+        CHK_ERR_WIN32A(ERROR_INVALID_SID)
+        CHK_ERR_WIN32A(ERROR_INVALID_SECURITY_DESCR)
+        CHK_ERR_WIN32A(ERROR_BAD_INHERITANCE_ACL)
+        CHK_ERR_WIN32A(ERROR_SERVER_DISABLED)
+        CHK_ERR_WIN32A(ERROR_SERVER_NOT_DISABLED)
+        CHK_ERR_WIN32A(ERROR_INVALID_ID_AUTHORITY)
+        CHK_ERR_WIN32A(ERROR_ALLOTTED_SPACE_EXCEEDED)
+        CHK_ERR_WIN32A(ERROR_INVALID_GROUP_ATTRIBUTES)
+        CHK_ERR_WIN32A(ERROR_BAD_IMPERSONATION_LEVEL)
+        CHK_ERR_WIN32A(ERROR_CANT_OPEN_ANONYMOUS)
+        CHK_ERR_WIN32A(ERROR_BAD_VALIDATION_CLASS)
+        CHK_ERR_WIN32A(ERROR_BAD_TOKEN_TYPE)
+        CHK_ERR_WIN32A(ERROR_NO_SECURITY_ON_OBJECT)
+        CHK_ERR_WIN32A(ERROR_CANT_ACCESS_DOMAIN_INFO)
+        CHK_ERR_WIN32A(ERROR_INVALID_SERVER_STATE)
+        CHK_ERR_WIN32A(ERROR_INVALID_DOMAIN_STATE)
+        CHK_ERR_WIN32A(ERROR_INVALID_DOMAIN_ROLE)
+        CHK_ERR_WIN32A(ERROR_NO_SUCH_DOMAIN)
+        CHK_ERR_WIN32A(ERROR_DOMAIN_EXISTS)
+        CHK_ERR_WIN32A(ERROR_DOMAIN_LIMIT_EXCEEDED)
+        CHK_ERR_WIN32A(ERROR_INTERNAL_DB_CORRUPTION)
+        CHK_ERR_WIN32A(ERROR_INTERNAL_ERROR)
+        CHK_ERR_WIN32A(ERROR_GENERIC_NOT_MAPPED)
+        CHK_ERR_WIN32A(ERROR_BAD_DESCRIPTOR_FORMAT)
+        CHK_ERR_WIN32A(ERROR_NOT_LOGON_PROCESS)
+        CHK_ERR_WIN32A(ERROR_LOGON_SESSION_EXISTS)
+        CHK_ERR_WIN32A(ERROR_NO_SUCH_PACKAGE)
+        CHK_ERR_WIN32A(ERROR_BAD_LOGON_SESSION_STATE)
+        CHK_ERR_WIN32A(ERROR_LOGON_SESSION_COLLISION)
+        CHK_ERR_WIN32A(ERROR_INVALID_LOGON_TYPE)
+        CHK_ERR_WIN32A(ERROR_CANNOT_IMPERSONATE)
+        CHK_ERR_WIN32A(ERROR_RXACT_INVALID_STATE)
+        CHK_ERR_WIN32A(ERROR_RXACT_COMMIT_FAILURE)
+        CHK_ERR_WIN32A(ERROR_SPECIAL_ACCOUNT)
+        CHK_ERR_WIN32A(ERROR_SPECIAL_GROUP)
+        CHK_ERR_WIN32A(ERROR_SPECIAL_USER)
+        CHK_ERR_WIN32A(ERROR_MEMBERS_PRIMARY_GROUP)
+        CHK_ERR_WIN32A(ERROR_TOKEN_ALREADY_IN_USE)
+        CHK_ERR_WIN32A(ERROR_NO_SUCH_ALIAS)
+        CHK_ERR_WIN32A(ERROR_MEMBER_NOT_IN_ALIAS)
+        CHK_ERR_WIN32A(ERROR_MEMBER_IN_ALIAS)
+        CHK_ERR_WIN32A(ERROR_ALIAS_EXISTS)
+        CHK_ERR_WIN32A(ERROR_LOGON_NOT_GRANTED)
+        CHK_ERR_WIN32A(ERROR_TOO_MANY_SECRETS)
+        CHK_ERR_WIN32A(ERROR_SECRET_TOO_LONG)
+        CHK_ERR_WIN32A(ERROR_INTERNAL_DB_ERROR)
+        CHK_ERR_WIN32A(ERROR_TOO_MANY_CONTEXT_IDS)
+        CHK_ERR_WIN32A(ERROR_LOGON_TYPE_NOT_GRANTED)
+        CHK_ERR_WIN32A(ERROR_NT_CROSS_ENCRYPTION_REQUIRED)
+        CHK_ERR_WIN32A(ERROR_NO_SUCH_MEMBER)
+        CHK_ERR_WIN32A(ERROR_INVALID_MEMBER)
+        CHK_ERR_WIN32A(ERROR_TOO_MANY_SIDS)
+        CHK_ERR_WIN32A(ERROR_LM_CROSS_ENCRYPTION_REQUIRED)
+        CHK_ERR_WIN32A(ERROR_NO_INHERITANCE)
+        CHK_ERR_WIN32A(ERROR_FILE_CORRUPT)
+        CHK_ERR_WIN32A(ERROR_DISK_CORRUPT)
+        CHK_ERR_WIN32A(ERROR_NO_USER_SESSION_KEY)
+        CHK_ERR_WIN32A(ERROR_LICENSE_QUOTA_EXCEEDED)
+        CHK_ERR_WIN32A(ERROR_WRONG_TARGET_NAME)
+        CHK_ERR_WIN32A(ERROR_MUTUAL_AUTH_FAILED)
+        CHK_ERR_WIN32A(ERROR_TIME_SKEW)
+        CHK_ERR_WIN32A(ERROR_INVALID_WINDOW_HANDLE)
+        CHK_ERR_WIN32A(ERROR_INVALID_MENU_HANDLE)
+        CHK_ERR_WIN32A(ERROR_INVALID_CURSOR_HANDLE)
+        CHK_ERR_WIN32A(ERROR_INVALID_ACCEL_HANDLE)
+        CHK_ERR_WIN32A(ERROR_INVALID_HOOK_HANDLE)
+        CHK_ERR_WIN32A(ERROR_INVALID_DWP_HANDLE)
+        CHK_ERR_WIN32A(ERROR_TLW_WITH_WSCHILD)
+        CHK_ERR_WIN32A(ERROR_CANNOT_FIND_WND_CLASS)
+        CHK_ERR_WIN32A(ERROR_WINDOW_OF_OTHER_THREAD)
+        CHK_ERR_WIN32A(ERROR_HOTKEY_ALREADY_REGISTERED)
+        CHK_ERR_WIN32A(ERROR_CLASS_ALREADY_EXISTS)
+        CHK_ERR_WIN32A(ERROR_CLASS_DOES_NOT_EXIST)
+        CHK_ERR_WIN32A(ERROR_CLASS_HAS_WINDOWS)
+        CHK_ERR_WIN32A(ERROR_INVALID_INDEX)
+        CHK_ERR_WIN32A(ERROR_INVALID_ICON_HANDLE)
+        CHK_ERR_WIN32A(ERROR_PRIVATE_DIALOG_INDEX)
+        CHK_ERR_WIN32A(ERROR_LISTBOX_ID_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_NO_WILDCARD_CHARACTERS)
+        CHK_ERR_WIN32A(ERROR_CLIPBOARD_NOT_OPEN)
+        CHK_ERR_WIN32A(ERROR_HOTKEY_NOT_REGISTERED)
+        CHK_ERR_WIN32A(ERROR_WINDOW_NOT_DIALOG)
+        CHK_ERR_WIN32A(ERROR_CONTROL_ID_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_INVALID_COMBOBOX_MESSAGE)
+        CHK_ERR_WIN32A(ERROR_WINDOW_NOT_COMBOBOX)
+        CHK_ERR_WIN32A(ERROR_INVALID_EDIT_HEIGHT)
+        CHK_ERR_WIN32A(ERROR_DC_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_INVALID_HOOK_FILTER)
+        CHK_ERR_WIN32A(ERROR_INVALID_FILTER_PROC)
+        CHK_ERR_WIN32A(ERROR_HOOK_NEEDS_HMOD)
+        CHK_ERR_WIN32A(ERROR_GLOBAL_ONLY_HOOK)
+        CHK_ERR_WIN32A(ERROR_JOURNAL_HOOK_SET)
+        CHK_ERR_WIN32A(ERROR_HOOK_NOT_INSTALLED)
+        CHK_ERR_WIN32A(ERROR_INVALID_LB_MESSAGE)
+        CHK_ERR_WIN32A(ERROR_SETCOUNT_ON_BAD_LB)
+        CHK_ERR_WIN32A(ERROR_LB_WITHOUT_TABSTOPS)
+        CHK_ERR_WIN32A(ERROR_DESTROY_OBJECT_OF_OTHER_THREAD)
+        CHK_ERR_WIN32A(ERROR_CHILD_WINDOW_MENU)
+        CHK_ERR_WIN32A(ERROR_NO_SYSTEM_MENU)
+        CHK_ERR_WIN32A(ERROR_INVALID_MSGBOX_STYLE)
+        CHK_ERR_WIN32A(ERROR_INVALID_SPI_VALUE)
+        CHK_ERR_WIN32A(ERROR_SCREEN_ALREADY_LOCKED)
+        CHK_ERR_WIN32A(ERROR_HWNDS_HAVE_DIFF_PARENT)
+        CHK_ERR_WIN32A(ERROR_NOT_CHILD_WINDOW)
+        CHK_ERR_WIN32A(ERROR_INVALID_GW_COMMAND)
+        CHK_ERR_WIN32A(ERROR_INVALID_THREAD_ID)
+        CHK_ERR_WIN32A(ERROR_NON_MDICHILD_WINDOW)
+        CHK_ERR_WIN32A(ERROR_POPUP_ALREADY_ACTIVE)
+        CHK_ERR_WIN32A(ERROR_NO_SCROLLBARS)
+        CHK_ERR_WIN32A(ERROR_INVALID_SCROLLBAR_RANGE)
+        CHK_ERR_WIN32A(ERROR_INVALID_SHOWWIN_COMMAND)
+        CHK_ERR_WIN32A(ERROR_NO_SYSTEM_RESOURCES)
+        CHK_ERR_WIN32A(ERROR_NONPAGED_SYSTEM_RESOURCES)
+        CHK_ERR_WIN32A(ERROR_PAGED_SYSTEM_RESOURCES)
+        CHK_ERR_WIN32A(ERROR_WORKING_SET_QUOTA)
+        CHK_ERR_WIN32A(ERROR_PAGEFILE_QUOTA)
+        CHK_ERR_WIN32A(ERROR_COMMITMENT_LIMIT)
+        CHK_ERR_WIN32A(ERROR_MENU_ITEM_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_INVALID_KEYBOARD_HANDLE)
+        CHK_ERR_WIN32A(ERROR_HOOK_TYPE_NOT_ALLOWED)
+        CHK_ERR_WIN32A(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION)
+        CHK_ERR_WIN32A(ERROR_TIMEOUT)
+        CHK_ERR_WIN32A(ERROR_INVALID_MONITOR_HANDLE)
+        CHK_ERR_WIN32A(ERROR_EVENTLOG_FILE_CORRUPT)
+        CHK_ERR_WIN32A(ERROR_EVENTLOG_CANT_START)
+        CHK_ERR_WIN32A(ERROR_LOG_FILE_FULL)
+        CHK_ERR_WIN32A(ERROR_EVENTLOG_FILE_CHANGED)
+        CHK_ERR_WIN32A(ERROR_INSTALL_USEREXIT)
+        CHK_ERR_WIN32A(ERROR_INSTALL_FAILURE)
+        CHK_ERR_WIN32A(ERROR_INSTALL_SUSPEND)
+        CHK_ERR_WIN32A(ERROR_UNKNOWN_PRODUCT)
+        CHK_ERR_WIN32A(ERROR_UNKNOWN_FEATURE)
+        CHK_ERR_WIN32A(ERROR_UNKNOWN_COMPONENT)
+        CHK_ERR_WIN32A(ERROR_UNKNOWN_PROPERTY)
+        CHK_ERR_WIN32A(ERROR_INVALID_HANDLE_STATE)
+        CHK_ERR_WIN32A(ERROR_BAD_CONFIGURATION)
+        CHK_ERR_WIN32A(ERROR_INDEX_ABSENT)
+        CHK_ERR_WIN32A(ERROR_INSTALL_SOURCE_ABSENT)
+        CHK_ERR_WIN32A(ERROR_PRODUCT_UNINSTALLED)
+        CHK_ERR_WIN32A(ERROR_BAD_QUERY_SYNTAX)
+        CHK_ERR_WIN32A(ERROR_INVALID_FIELD)
+        CHK_ERR_WIN32A(ERROR_DEVICE_REMOVED)
+        CHK_ERR_WIN32A(RPC_S_INVALID_STRING_BINDING)
+        CHK_ERR_WIN32A(RPC_S_WRONG_KIND_OF_BINDING)
+        CHK_ERR_WIN32A(RPC_S_INVALID_BINDING)
+        CHK_ERR_WIN32A(RPC_S_PROTSEQ_NOT_SUPPORTED)
+        CHK_ERR_WIN32A(RPC_S_INVALID_RPC_PROTSEQ)
+        CHK_ERR_WIN32A(RPC_S_INVALID_STRING_UUID)
+        CHK_ERR_WIN32A(RPC_S_INVALID_ENDPOINT_FORMAT)
+        CHK_ERR_WIN32A(RPC_S_INVALID_NET_ADDR)
+        CHK_ERR_WIN32A(RPC_S_NO_ENDPOINT_FOUND)
+        CHK_ERR_WIN32A(RPC_S_INVALID_TIMEOUT)
+        CHK_ERR_WIN32A(RPC_S_OBJECT_NOT_FOUND)
+        CHK_ERR_WIN32A(RPC_S_ALREADY_REGISTERED)
+        CHK_ERR_WIN32A(RPC_S_TYPE_ALREADY_REGISTERED)
+        CHK_ERR_WIN32A(RPC_S_ALREADY_LISTENING)
+        CHK_ERR_WIN32A(RPC_S_NO_PROTSEQS_REGISTERED)
+        CHK_ERR_WIN32A(RPC_S_NOT_LISTENING)
+        CHK_ERR_WIN32A(RPC_S_UNKNOWN_MGR_TYPE)
+        CHK_ERR_WIN32A(RPC_S_UNKNOWN_IF)
+        CHK_ERR_WIN32A(RPC_S_NO_BINDINGS)
+        CHK_ERR_WIN32A(RPC_S_NO_PROTSEQS)
+        CHK_ERR_WIN32A(RPC_S_CANT_CREATE_ENDPOINT)
+        CHK_ERR_WIN32A(RPC_S_OUT_OF_RESOURCES)
+        CHK_ERR_WIN32A(RPC_S_SERVER_UNAVAILABLE)
+        CHK_ERR_WIN32A(RPC_S_SERVER_TOO_BUSY)
+        CHK_ERR_WIN32A(RPC_S_INVALID_NETWORK_OPTIONS)
+        CHK_ERR_WIN32A(RPC_S_NO_CALL_ACTIVE)
+        CHK_ERR_WIN32A(RPC_S_CALL_FAILED)
+        CHK_ERR_WIN32A(RPC_S_CALL_FAILED_DNE)
+        CHK_ERR_WIN32A(RPC_S_PROTOCOL_ERROR)
+        CHK_ERR_WIN32A(RPC_S_UNSUPPORTED_TRANS_SYN)
+        CHK_ERR_WIN32A(RPC_S_UNSUPPORTED_TYPE)
+        CHK_ERR_WIN32A(RPC_S_INVALID_TAG)
+        CHK_ERR_WIN32A(RPC_S_INVALID_BOUND)
+        CHK_ERR_WIN32A(RPC_S_NO_ENTRY_NAME)
+        CHK_ERR_WIN32A(RPC_S_INVALID_NAME_SYNTAX)
+        CHK_ERR_WIN32A(RPC_S_UNSUPPORTED_NAME_SYNTAX)
+        CHK_ERR_WIN32A(RPC_S_UUID_NO_ADDRESS)
+        CHK_ERR_WIN32A(RPC_S_DUPLICATE_ENDPOINT)
+        CHK_ERR_WIN32A(RPC_S_UNKNOWN_AUTHN_TYPE)
+        CHK_ERR_WIN32A(RPC_S_MAX_CALLS_TOO_SMALL)
+        CHK_ERR_WIN32A(RPC_S_STRING_TOO_LONG)
+        CHK_ERR_WIN32A(RPC_S_PROTSEQ_NOT_FOUND)
+        CHK_ERR_WIN32A(RPC_S_PROCNUM_OUT_OF_RANGE)
+        CHK_ERR_WIN32A(RPC_S_BINDING_HAS_NO_AUTH)
+        CHK_ERR_WIN32A(RPC_S_UNKNOWN_AUTHN_SERVICE)
+        CHK_ERR_WIN32A(RPC_S_UNKNOWN_AUTHN_LEVEL)
+        CHK_ERR_WIN32A(RPC_S_INVALID_AUTH_IDENTITY)
+        CHK_ERR_WIN32A(RPC_S_UNKNOWN_AUTHZ_SERVICE)
+        CHK_ERR_WIN32A(EPT_S_INVALID_ENTRY)
+        CHK_ERR_WIN32A(EPT_S_CANT_PERFORM_OP)
+        CHK_ERR_WIN32A(EPT_S_NOT_REGISTERED)
+        CHK_ERR_WIN32A(RPC_S_NOTHING_TO_EXPORT)
+        CHK_ERR_WIN32A(RPC_S_INCOMPLETE_NAME)
+        CHK_ERR_WIN32A(RPC_S_INVALID_VERS_OPTION)
+        CHK_ERR_WIN32A(RPC_S_NO_MORE_MEMBERS)
+        CHK_ERR_WIN32A(RPC_S_NOT_ALL_OBJS_UNEXPORTED)
+        CHK_ERR_WIN32A(RPC_S_INTERFACE_NOT_FOUND)
+        CHK_ERR_WIN32A(RPC_S_ENTRY_ALREADY_EXISTS)
+        CHK_ERR_WIN32A(RPC_S_ENTRY_NOT_FOUND)
+        CHK_ERR_WIN32A(RPC_S_NAME_SERVICE_UNAVAILABLE)
+        CHK_ERR_WIN32A(RPC_S_INVALID_NAF_ID)
+        CHK_ERR_WIN32A(RPC_S_CANNOT_SUPPORT)
+        CHK_ERR_WIN32A(RPC_S_NO_CONTEXT_AVAILABLE)
+        CHK_ERR_WIN32A(RPC_S_INTERNAL_ERROR)
+        CHK_ERR_WIN32A(RPC_S_ZERO_DIVIDE)
+        CHK_ERR_WIN32A(RPC_S_ADDRESS_ERROR)
+        CHK_ERR_WIN32A(RPC_S_FP_DIV_ZERO)
+        CHK_ERR_WIN32A(RPC_S_FP_UNDERFLOW)
+        CHK_ERR_WIN32A(RPC_S_FP_OVERFLOW)
+        CHK_ERR_WIN32A(RPC_X_NO_MORE_ENTRIES)
+        CHK_ERR_WIN32A(RPC_X_SS_CHAR_TRANS_OPEN_FAIL)
+        CHK_ERR_WIN32A(RPC_X_SS_CHAR_TRANS_SHORT_FILE)
+        CHK_ERR_WIN32A(RPC_X_SS_IN_NULL_CONTEXT)
+        CHK_ERR_WIN32A(RPC_X_SS_CONTEXT_DAMAGED)
+        CHK_ERR_WIN32A(RPC_X_SS_HANDLES_MISMATCH)
+        CHK_ERR_WIN32A(RPC_X_SS_CANNOT_GET_CALL_HANDLE)
+        CHK_ERR_WIN32A(RPC_X_NULL_REF_POINTER)
+        CHK_ERR_WIN32A(RPC_X_ENUM_VALUE_OUT_OF_RANGE)
+        CHK_ERR_WIN32A(RPC_X_BYTE_COUNT_TOO_SMALL)
+        CHK_ERR_WIN32A(RPC_X_BAD_STUB_DATA)
+        CHK_ERR_WIN32A(ERROR_INVALID_USER_BUFFER)
+        CHK_ERR_WIN32A(ERROR_UNRECOGNIZED_MEDIA)
+        CHK_ERR_WIN32A(ERROR_NO_TRUST_LSA_SECRET)
+        CHK_ERR_WIN32A(ERROR_NO_TRUST_SAM_ACCOUNT)
+        CHK_ERR_WIN32A(ERROR_TRUSTED_DOMAIN_FAILURE)
+        CHK_ERR_WIN32A(ERROR_TRUSTED_RELATIONSHIP_FAILURE)
+        CHK_ERR_WIN32A(ERROR_TRUST_FAILURE)
+        CHK_ERR_WIN32A(RPC_S_CALL_IN_PROGRESS)
+        CHK_ERR_WIN32A(ERROR_NETLOGON_NOT_STARTED)
+        CHK_ERR_WIN32A(ERROR_ACCOUNT_EXPIRED)
+        CHK_ERR_WIN32A(ERROR_REDIRECTOR_HAS_OPEN_HANDLES)
+        CHK_ERR_WIN32A(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED)
+        CHK_ERR_WIN32A(ERROR_UNKNOWN_PORT)
+        CHK_ERR_WIN32A(ERROR_UNKNOWN_PRINTER_DRIVER)
+        CHK_ERR_WIN32A(ERROR_UNKNOWN_PRINTPROCESSOR)
+        CHK_ERR_WIN32A(ERROR_INVALID_SEPARATOR_FILE)
+        CHK_ERR_WIN32A(ERROR_INVALID_PRIORITY)
+        CHK_ERR_WIN32A(ERROR_INVALID_PRINTER_NAME)
+        CHK_ERR_WIN32A(ERROR_PRINTER_ALREADY_EXISTS)
+        CHK_ERR_WIN32A(ERROR_INVALID_PRINTER_COMMAND)
+        CHK_ERR_WIN32A(ERROR_INVALID_DATATYPE)
+        CHK_ERR_WIN32A(ERROR_INVALID_ENVIRONMENT)
+        CHK_ERR_WIN32A(RPC_S_NO_MORE_BINDINGS)
+        CHK_ERR_WIN32A(ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)
+        CHK_ERR_WIN32A(ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
+        CHK_ERR_WIN32A(ERROR_NOLOGON_SERVER_TRUST_ACCOUNT)
+        CHK_ERR_WIN32A(ERROR_DOMAIN_TRUST_INCONSISTENT)
+        CHK_ERR_WIN32A(ERROR_SERVER_HAS_OPEN_HANDLES)
+        CHK_ERR_WIN32A(ERROR_RESOURCE_DATA_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_RESOURCE_TYPE_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_RESOURCE_NAME_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_RESOURCE_LANG_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_NOT_ENOUGH_QUOTA)
+        CHK_ERR_WIN32A(RPC_S_NO_INTERFACES)
+        CHK_ERR_WIN32A(RPC_S_CALL_CANCELLED)
+        CHK_ERR_WIN32A(RPC_S_BINDING_INCOMPLETE)
+        CHK_ERR_WIN32A(RPC_S_COMM_FAILURE)
+        CHK_ERR_WIN32A(RPC_S_UNSUPPORTED_AUTHN_LEVEL)
+        CHK_ERR_WIN32A(RPC_S_NO_PRINC_NAME)
+        CHK_ERR_WIN32A(RPC_S_NOT_RPC_ERROR)
+        CHK_ERR_WIN32A(RPC_S_UUID_LOCAL_ONLY)
+        CHK_ERR_WIN32A(RPC_S_SEC_PKG_ERROR)
+        CHK_ERR_WIN32A(RPC_S_NOT_CANCELLED)
+        CHK_ERR_WIN32A(RPC_X_INVALID_ES_ACTION)
+        CHK_ERR_WIN32A(RPC_X_WRONG_ES_VERSION)
+        CHK_ERR_WIN32A(RPC_X_WRONG_STUB_VERSION)
+        CHK_ERR_WIN32A(RPC_X_INVALID_PIPE_OBJECT)
+        CHK_ERR_WIN32A(RPC_X_WRONG_PIPE_ORDER)
+        CHK_ERR_WIN32A(RPC_X_WRONG_PIPE_VERSION)
+        CHK_ERR_WIN32A(RPC_S_GROUP_MEMBER_NOT_FOUND)
+        CHK_ERR_WIN32A(EPT_S_CANT_CREATE)
+        CHK_ERR_WIN32A(RPC_S_INVALID_OBJECT)
+        CHK_ERR_WIN32A(ERROR_INVALID_TIME)
+        CHK_ERR_WIN32A(ERROR_INVALID_FORM_NAME)
+        CHK_ERR_WIN32A(ERROR_INVALID_FORM_SIZE)
+        CHK_ERR_WIN32A(ERROR_ALREADY_WAITING)
+        CHK_ERR_WIN32A(ERROR_PRINTER_DELETED)
+        CHK_ERR_WIN32A(ERROR_INVALID_PRINTER_STATE)
+        CHK_ERR_WIN32A(ERROR_PASSWORD_MUST_CHANGE)
+        CHK_ERR_WIN32A(ERROR_DOMAIN_CONTROLLER_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_ACCOUNT_LOCKED_OUT)
+        CHK_ERR_WIN32A(OR_INVALID_OXID)
+        CHK_ERR_WIN32A(OR_INVALID_OID)
+        CHK_ERR_WIN32A(OR_INVALID_SET)
+        CHK_ERR_WIN32A(RPC_S_SEND_INCOMPLETE)
+        CHK_ERR_WIN32A(RPC_S_INVALID_ASYNC_HANDLE)
+        CHK_ERR_WIN32A(RPC_S_INVALID_ASYNC_CALL)
+        CHK_ERR_WIN32A(RPC_X_PIPE_CLOSED)
+        CHK_ERR_WIN32A(RPC_X_PIPE_DISCIPLINE_ERROR)
+        CHK_ERR_WIN32A(RPC_X_PIPE_EMPTY)
+        CHK_ERR_WIN32A(ERROR_NO_SITENAME)
+        CHK_ERR_WIN32A(ERROR_CANT_ACCESS_FILE)
+        CHK_ERR_WIN32A(ERROR_CANT_RESOLVE_FILENAME)
+        CHK_ERR_WIN32A(ERROR_INVALID_PIXEL_FORMAT)
+        CHK_ERR_WIN32A(ERROR_BAD_DRIVER)
+        CHK_ERR_WIN32A(ERROR_INVALID_WINDOW_STYLE)
+        CHK_ERR_WIN32A(ERROR_METAFILE_NOT_SUPPORTED)
+        CHK_ERR_WIN32A(ERROR_TRANSFORM_NOT_SUPPORTED)
+        CHK_ERR_WIN32A(ERROR_CLIPPING_NOT_SUPPORTED)
+        CHK_ERR_WIN32A(ERROR_INVALID_CMM)
+        CHK_ERR_WIN32A(ERROR_INVALID_PROFILE)
+        CHK_ERR_WIN32A(ERROR_TAG_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_TAG_NOT_PRESENT)
+        CHK_ERR_WIN32A(ERROR_DUPLICATE_TAG)
+        CHK_ERR_WIN32A(ERROR_PROFILE_NOT_ASSOCIATED_WITH_DEVICE)
+        CHK_ERR_WIN32A(ERROR_PROFILE_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_INVALID_COLORSPACE)
+        CHK_ERR_WIN32A(ERROR_ICM_NOT_ENABLED)
+        CHK_ERR_WIN32A(ERROR_DELETING_ICM_XFORM)
+        CHK_ERR_WIN32A(ERROR_INVALID_TRANSFORM)
+        CHK_ERR_WIN32A(ERROR_COLORSPACE_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_INVALID_COLORINDEX)
+        CHK_ERR_WIN32A(ERROR_CONNECTED_OTHER_PASSWORD)
+        CHK_ERR_WIN32A(ERROR_BAD_USERNAME)
+        CHK_ERR_WIN32A(ERROR_NOT_CONNECTED)
+        CHK_ERR_WIN32A(ERROR_OPEN_FILES)
+        CHK_ERR_WIN32A(ERROR_ACTIVE_CONNECTIONS)
+        CHK_ERR_WIN32A(ERROR_DEVICE_IN_USE)
+        CHK_ERR_WIN32A(ERROR_UNKNOWN_PRINT_MONITOR)
+        CHK_ERR_WIN32A(ERROR_PRINTER_DRIVER_IN_USE)
+        CHK_ERR_WIN32A(ERROR_SPOOL_FILE_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_SPL_NO_STARTDOC)
+        CHK_ERR_WIN32A(ERROR_SPL_NO_ADDJOB)
+        CHK_ERR_WIN32A(ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED)
+        CHK_ERR_WIN32A(ERROR_PRINT_MONITOR_ALREADY_INSTALLED)
+        CHK_ERR_WIN32A(ERROR_INVALID_PRINT_MONITOR)
+        CHK_ERR_WIN32A(ERROR_PRINT_MONITOR_IN_USE)
+        CHK_ERR_WIN32A(ERROR_PRINTER_HAS_JOBS_QUEUED)
+        CHK_ERR_WIN32A(ERROR_SUCCESS_REBOOT_REQUIRED)
+        CHK_ERR_WIN32A(ERROR_SUCCESS_RESTART_REQUIRED)
+        CHK_ERR_WIN32A(ERROR_PRINTER_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_WINS_INTERNAL)
+        CHK_ERR_WIN32A(ERROR_CAN_NOT_DEL_LOCAL_WINS)
+        CHK_ERR_WIN32A(ERROR_STATIC_INIT)
+        CHK_ERR_WIN32A(ERROR_INC_BACKUP)
+        CHK_ERR_WIN32A(ERROR_FULL_BACKUP)
+        CHK_ERR_WIN32A(ERROR_REC_NON_EXISTENT)
+        CHK_ERR_WIN32A(ERROR_RPL_NOT_ALLOWED)
+        CHK_ERR_WIN32A(ERROR_DHCP_ADDRESS_CONFLICT)
+        CHK_ERR_WIN32A(ERROR_WMI_GUID_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_WMI_INSTANCE_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_WMI_ITEMID_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_WMI_TRY_AGAIN)
+        CHK_ERR_WIN32A(ERROR_WMI_DP_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_WMI_UNRESOLVED_INSTANCE_REF)
+        CHK_ERR_WIN32A(ERROR_WMI_ALREADY_ENABLED)
+        CHK_ERR_WIN32A(ERROR_WMI_GUID_DISCONNECTED)
+        CHK_ERR_WIN32A(ERROR_WMI_SERVER_UNAVAILABLE)
+        CHK_ERR_WIN32A(ERROR_WMI_DP_FAILED)
+        CHK_ERR_WIN32A(ERROR_WMI_INVALID_MOF)
+        CHK_ERR_WIN32A(ERROR_WMI_INVALID_REGINFO)
+        CHK_ERR_WIN32A(ERROR_WMI_ALREADY_DISABLED)
+        CHK_ERR_WIN32A(ERROR_WMI_READ_ONLY)
+        CHK_ERR_WIN32A(ERROR_WMI_SET_FAILURE)
+        CHK_ERR_WIN32A(ERROR_INVALID_MEDIA)
+        CHK_ERR_WIN32A(ERROR_INVALID_LIBRARY)
+        CHK_ERR_WIN32A(ERROR_INVALID_MEDIA_POOL)
+        CHK_ERR_WIN32A(ERROR_DRIVE_MEDIA_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_MEDIA_OFFLINE)
+        CHK_ERR_WIN32A(ERROR_LIBRARY_OFFLINE)
+        CHK_ERR_WIN32A(ERROR_EMPTY)
+        CHK_ERR_WIN32A(ERROR_NOT_EMPTY)
+        CHK_ERR_WIN32A(ERROR_MEDIA_UNAVAILABLE)
+        CHK_ERR_WIN32A(ERROR_RESOURCE_DISABLED)
+        CHK_ERR_WIN32A(ERROR_INVALID_CLEANER)
+        CHK_ERR_WIN32A(ERROR_UNABLE_TO_CLEAN)
+        CHK_ERR_WIN32A(ERROR_OBJECT_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_DATABASE_FAILURE)
+        CHK_ERR_WIN32A(ERROR_DATABASE_FULL)
+        CHK_ERR_WIN32A(ERROR_MEDIA_INCOMPATIBLE)
+        CHK_ERR_WIN32A(ERROR_RESOURCE_NOT_PRESENT)
+        CHK_ERR_WIN32A(ERROR_INVALID_OPERATION)
+        CHK_ERR_WIN32A(ERROR_MEDIA_NOT_AVAILABLE)
+        CHK_ERR_WIN32A(ERROR_DEVICE_NOT_AVAILABLE)
+        CHK_ERR_WIN32A(ERROR_REQUEST_REFUSED)
+        CHK_ERR_WIN32A(ERROR_INVALID_DRIVE_OBJECT)
+        CHK_ERR_WIN32A(ERROR_LIBRARY_FULL)
+        CHK_ERR_WIN32A(ERROR_MEDIUM_NOT_ACCESSIBLE)
+        CHK_ERR_WIN32A(ERROR_UNABLE_TO_LOAD_MEDIUM)
+        CHK_ERR_WIN32A(ERROR_UNABLE_TO_INVENTORY_DRIVE)
+        CHK_ERR_WIN32A(ERROR_UNABLE_TO_INVENTORY_SLOT)
+        CHK_ERR_WIN32A(ERROR_UNABLE_TO_INVENTORY_TRANSPORT)
+        CHK_ERR_WIN32A(ERROR_TRANSPORT_FULL)
+        CHK_ERR_WIN32A(ERROR_CONTROLLING_IEPORT)
+        CHK_ERR_WIN32A(ERROR_UNABLE_TO_EJECT_MOUNTED_MEDIA)
+        CHK_ERR_WIN32A(ERROR_CLEANER_SLOT_SET)
+        CHK_ERR_WIN32A(ERROR_CLEANER_SLOT_NOT_SET)
+        CHK_ERR_WIN32A(ERROR_CLEANER_CARTRIDGE_SPENT)
+        CHK_ERR_WIN32A(ERROR_UNEXPECTED_OMID)
+        CHK_ERR_WIN32A(ERROR_CANT_DELETE_LAST_ITEM)
+        CHK_ERR_WIN32A(ERROR_MESSAGE_EXCEEDS_MAX_SIZE)
+        CHK_ERR_WIN32A(ERROR_FILE_OFFLINE)
+        CHK_ERR_WIN32A(ERROR_REMOTE_STORAGE_NOT_ACTIVE)
+        CHK_ERR_WIN32A(ERROR_REMOTE_STORAGE_MEDIA_ERROR)
+        CHK_ERR_WIN32A(ERROR_NOT_A_REPARSE_POINT)
+        CHK_ERR_WIN32A(ERROR_REPARSE_ATTRIBUTE_CONFLICT)
+        CHK_ERR_WIN32A(ERROR_INVALID_REPARSE_DATA)
+        CHK_ERR_WIN32A(ERROR_DEPENDENT_RESOURCE_EXISTS)
+        CHK_ERR_WIN32A(ERROR_DEPENDENCY_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_DEPENDENCY_ALREADY_EXISTS)
+        CHK_ERR_WIN32A(ERROR_RESOURCE_NOT_ONLINE)
+        CHK_ERR_WIN32A(ERROR_HOST_NODE_NOT_AVAILABLE)
+        CHK_ERR_WIN32A(ERROR_RESOURCE_NOT_AVAILABLE)
+        CHK_ERR_WIN32A(ERROR_RESOURCE_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_SHUTDOWN_CLUSTER)
+        CHK_ERR_WIN32A(ERROR_CANT_EVICT_ACTIVE_NODE)
+        CHK_ERR_WIN32A(ERROR_OBJECT_ALREADY_EXISTS)
+        CHK_ERR_WIN32A(ERROR_OBJECT_IN_LIST)
+        CHK_ERR_WIN32A(ERROR_GROUP_NOT_AVAILABLE)
+        CHK_ERR_WIN32A(ERROR_GROUP_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_GROUP_NOT_ONLINE)
+        CHK_ERR_WIN32A(ERROR_HOST_NODE_NOT_RESOURCE_OWNER)
+        CHK_ERR_WIN32A(ERROR_HOST_NODE_NOT_GROUP_OWNER)
+        CHK_ERR_WIN32A(ERROR_RESMON_CREATE_FAILED)
+        CHK_ERR_WIN32A(ERROR_RESMON_ONLINE_FAILED)
+        CHK_ERR_WIN32A(ERROR_RESOURCE_ONLINE)
+        CHK_ERR_WIN32A(ERROR_QUORUM_RESOURCE)
+        CHK_ERR_WIN32A(ERROR_NOT_QUORUM_CAPABLE)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_SHUTTING_DOWN)
+        CHK_ERR_WIN32A(ERROR_INVALID_STATE)
+        CHK_ERR_WIN32A(ERROR_RESOURCE_PROPERTIES_STORED)
+        CHK_ERR_WIN32A(ERROR_NOT_QUORUM_CLASS)
+        CHK_ERR_WIN32A(ERROR_CORE_RESOURCE)
+        CHK_ERR_WIN32A(ERROR_QUORUM_RESOURCE_ONLINE_FAILED)
+        CHK_ERR_WIN32A(ERROR_QUORUMLOG_OPEN_FAILED)
+        CHK_ERR_WIN32A(ERROR_CLUSTERLOG_CORRUPT)
+        CHK_ERR_WIN32A(ERROR_CLUSTERLOG_RECORD_EXCEEDS_MAXSIZE)
+        CHK_ERR_WIN32A(ERROR_CLUSTERLOG_EXCEEDS_MAXSIZE)
+        CHK_ERR_WIN32A(ERROR_CLUSTERLOG_CHKPOINT_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_CLUSTERLOG_NOT_ENOUGH_SPACE)
+        CHK_ERR_WIN32A(ERROR_ENCRYPTION_FAILED)
+        CHK_ERR_WIN32A(ERROR_DECRYPTION_FAILED)
+        CHK_ERR_WIN32A(ERROR_FILE_ENCRYPTED)
+        CHK_ERR_WIN32A(ERROR_NO_RECOVERY_POLICY)
+        CHK_ERR_WIN32A(ERROR_NO_EFS)
+        CHK_ERR_WIN32A(ERROR_WRONG_EFS)
+        CHK_ERR_WIN32A(ERROR_NO_USER_KEYS)
+        CHK_ERR_WIN32A(ERROR_FILE_NOT_ENCRYPTED)
+        CHK_ERR_WIN32A(ERROR_NOT_EXPORT_FORMAT)
+        CHK_ERR_WIN32A(ERROR_NO_BROWSER_SERVERS_FOUND)
+        CHK_ERR_WIN32A(ERROR_CTX_WINSTATION_NAME_INVALID)
+        CHK_ERR_WIN32A(ERROR_CTX_INVALID_PD)
+        CHK_ERR_WIN32A(ERROR_CTX_PD_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_CTX_WD_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_CTX_CANNOT_MAKE_EVENTLOG_ENTRY)
+        CHK_ERR_WIN32A(ERROR_CTX_SERVICE_NAME_COLLISION)
+        CHK_ERR_WIN32A(ERROR_CTX_CLOSE_PENDING)
+        CHK_ERR_WIN32A(ERROR_CTX_NO_OUTBUF)
+        CHK_ERR_WIN32A(ERROR_CTX_MODEM_INF_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_CTX_INVALID_MODEMNAME)
+        CHK_ERR_WIN32A(ERROR_CTX_MODEM_RESPONSE_ERROR)
+        CHK_ERR_WIN32A(ERROR_CTX_MODEM_RESPONSE_TIMEOUT)
+        CHK_ERR_WIN32A(ERROR_CTX_MODEM_RESPONSE_NO_CARRIER)
+        CHK_ERR_WIN32A(ERROR_CTX_MODEM_RESPONSE_NO_DIALTONE)
+        CHK_ERR_WIN32A(ERROR_CTX_MODEM_RESPONSE_BUSY)
+        CHK_ERR_WIN32A(ERROR_CTX_MODEM_RESPONSE_VOICE)
+        CHK_ERR_WIN32A(ERROR_CTX_TD_ERROR)
+        CHK_ERR_WIN32A(ERROR_CTX_WINSTATION_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_CTX_WINSTATION_ALREADY_EXISTS)
+        CHK_ERR_WIN32A(ERROR_CTX_WINSTATION_BUSY)
+        CHK_ERR_WIN32A(ERROR_CTX_BAD_VIDEO_MODE)
+        CHK_ERR_WIN32A(ERROR_CTX_GRAPHICS_INVALID)
+        CHK_ERR_WIN32A(ERROR_CTX_LOGON_DISABLED)
+        CHK_ERR_WIN32A(ERROR_CTX_NOT_CONSOLE)
+        CHK_ERR_WIN32A(ERROR_CTX_CLIENT_QUERY_TIMEOUT)
+        CHK_ERR_WIN32A(ERROR_CTX_CONSOLE_DISCONNECT)
+        CHK_ERR_WIN32A(ERROR_CTX_CONSOLE_CONNECT)
+        CHK_ERR_WIN32A(ERROR_CTX_SHADOW_DENIED)
+        CHK_ERR_WIN32A(ERROR_CTX_WINSTATION_ACCESS_DENIED)
+        CHK_ERR_WIN32A(ERROR_CTX_INVALID_WD)
+        CHK_ERR_WIN32A(ERROR_CTX_SHADOW_INVALID)
+        CHK_ERR_WIN32A(ERROR_CTX_SHADOW_DISABLED)
+        CHK_ERR_WIN32A(FRS_ERR_INVALID_API_SEQUENCE)
+        CHK_ERR_WIN32A(FRS_ERR_STARTING_SERVICE)
+        CHK_ERR_WIN32A(FRS_ERR_STOPPING_SERVICE)
+        CHK_ERR_WIN32A(FRS_ERR_INTERNAL_API)
+        CHK_ERR_WIN32A(FRS_ERR_INTERNAL)
+        CHK_ERR_WIN32A(FRS_ERR_SERVICE_COMM)
+        CHK_ERR_WIN32A(FRS_ERR_INSUFFICIENT_PRIV)
+        CHK_ERR_WIN32A(FRS_ERR_AUTHENTICATION)
+        CHK_ERR_WIN32A(FRS_ERR_PARENT_INSUFFICIENT_PRIV)
+        CHK_ERR_WIN32A(FRS_ERR_PARENT_AUTHENTICATION)
+        CHK_ERR_WIN32A(FRS_ERR_CHILD_TO_PARENT_COMM)
+        CHK_ERR_WIN32A(FRS_ERR_PARENT_TO_CHILD_COMM)
+        CHK_ERR_WIN32A(FRS_ERR_SYSVOL_POPULATE)
+        CHK_ERR_WIN32A(FRS_ERR_SYSVOL_POPULATE_TIMEOUT)
+        CHK_ERR_WIN32A(FRS_ERR_SYSVOL_IS_BUSY)
+        CHK_ERR_WIN32A(FRS_ERR_SYSVOL_DEMOTE)
+        CHK_ERR_WIN32A(FRS_ERR_INVALID_SERVICE_PARAMETER)
+//        CHK_ERR_WIN32A(DS_S_SUCCESS)
+        CHK_ERR_WIN32A(ERROR_DS_NOT_INSTALLED)
+        CHK_ERR_WIN32A(ERROR_DS_MEMBERSHIP_EVALUATED_LOCALLY)
+        CHK_ERR_WIN32A(ERROR_DS_NO_ATTRIBUTE_OR_VALUE)
+        CHK_ERR_WIN32A(ERROR_DS_INVALID_ATTRIBUTE_SYNTAX)
+        CHK_ERR_WIN32A(ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED)
+        CHK_ERR_WIN32A(ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS)
+        CHK_ERR_WIN32A(ERROR_DS_BUSY)
+        CHK_ERR_WIN32A(ERROR_DS_UNAVAILABLE)
+        CHK_ERR_WIN32A(ERROR_DS_NO_RIDS_ALLOCATED)
+        CHK_ERR_WIN32A(ERROR_DS_NO_MORE_RIDS)
+        CHK_ERR_WIN32A(ERROR_DS_INCORRECT_ROLE_OWNER)
+        CHK_ERR_WIN32A(ERROR_DS_RIDMGR_INIT_ERROR)
+        CHK_ERR_WIN32A(ERROR_DS_OBJ_CLASS_VIOLATION)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_ON_NON_LEAF)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_ON_RDN)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_MOD_OBJ_CLASS)
+        CHK_ERR_WIN32A(ERROR_DS_CROSS_DOM_MOVE_ERROR)
+        CHK_ERR_WIN32A(ERROR_DS_GC_NOT_AVAILABLE)
+        CHK_ERR_WIN32A(ERROR_SHARED_POLICY)
+        CHK_ERR_WIN32A(ERROR_POLICY_OBJECT_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_POLICY_ONLY_IN_DS)
+        CHK_ERR_WIN32A(ERROR_PROMOTION_ACTIVE)
+        CHK_ERR_WIN32A(ERROR_NO_PROMOTION_ACTIVE)
+        CHK_ERR_WIN32A(ERROR_DS_OPERATIONS_ERROR)
+        CHK_ERR_WIN32A(ERROR_DS_PROTOCOL_ERROR)
+        CHK_ERR_WIN32A(ERROR_DS_TIMELIMIT_EXCEEDED)
+        CHK_ERR_WIN32A(ERROR_DS_SIZELIMIT_EXCEEDED)
+        CHK_ERR_WIN32A(ERROR_DS_ADMIN_LIMIT_EXCEEDED)
+        CHK_ERR_WIN32A(ERROR_DS_COMPARE_FALSE)
+        CHK_ERR_WIN32A(ERROR_DS_COMPARE_TRUE)
+        CHK_ERR_WIN32A(ERROR_DS_AUTH_METHOD_NOT_SUPPORTED)
+        CHK_ERR_WIN32A(ERROR_DS_STRONG_AUTH_REQUIRED)
+        CHK_ERR_WIN32A(ERROR_DS_INAPPROPRIATE_AUTH)
+        CHK_ERR_WIN32A(ERROR_DS_AUTH_UNKNOWN)
+        CHK_ERR_WIN32A(ERROR_DS_REFERRAL)
+        CHK_ERR_WIN32A(ERROR_DS_UNAVAILABLE_CRIT_EXTENSION)
+        CHK_ERR_WIN32A(ERROR_DS_CONFIDENTIALITY_REQUIRED)
+        CHK_ERR_WIN32A(ERROR_DS_INAPPROPRIATE_MATCHING)
+        CHK_ERR_WIN32A(ERROR_DS_CONSTRAINT_VIOLATION)
+        CHK_ERR_WIN32A(ERROR_DS_NO_SUCH_OBJECT)
+        CHK_ERR_WIN32A(ERROR_DS_ALIAS_PROBLEM)
+        CHK_ERR_WIN32A(ERROR_DS_INVALID_DN_SYNTAX)
+        CHK_ERR_WIN32A(ERROR_DS_IS_LEAF)
+        CHK_ERR_WIN32A(ERROR_DS_ALIAS_DEREF_PROBLEM)
+        CHK_ERR_WIN32A(ERROR_DS_UNWILLING_TO_PERFORM)
+        CHK_ERR_WIN32A(ERROR_DS_LOOP_DETECT)
+        CHK_ERR_WIN32A(ERROR_DS_NAMING_VIOLATION)
+        CHK_ERR_WIN32A(ERROR_DS_OBJECT_RESULTS_TOO_LARGE)
+        CHK_ERR_WIN32A(ERROR_DS_AFFECTS_MULTIPLE_DSAS)
+        CHK_ERR_WIN32A(ERROR_DS_SERVER_DOWN)
+        CHK_ERR_WIN32A(ERROR_DS_LOCAL_ERROR)
+        CHK_ERR_WIN32A(ERROR_DS_ENCODING_ERROR)
+        CHK_ERR_WIN32A(ERROR_DS_DECODING_ERROR)
+        CHK_ERR_WIN32A(ERROR_DS_FILTER_UNKNOWN)
+        CHK_ERR_WIN32A(ERROR_DS_PARAM_ERROR)
+        CHK_ERR_WIN32A(ERROR_DS_NOT_SUPPORTED)
+        CHK_ERR_WIN32A(ERROR_DS_NO_RESULTS_RETURNED)
+        CHK_ERR_WIN32A(ERROR_DS_CONTROL_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_DS_CLIENT_LOOP)
+        CHK_ERR_WIN32A(ERROR_DS_REFERRAL_LIMIT_EXCEEDED)
+        CHK_ERR_WIN32A(ERROR_DS_ROOT_MUST_BE_NC)
+        CHK_ERR_WIN32A(ERROR_DS_ADD_REPLICA_INHIBITED)
+        CHK_ERR_WIN32A(ERROR_DS_ATT_NOT_DEF_IN_SCHEMA)
+        CHK_ERR_WIN32A(ERROR_DS_MAX_OBJ_SIZE_EXCEEDED)
+        CHK_ERR_WIN32A(ERROR_DS_OBJ_STRING_NAME_EXISTS)
+        CHK_ERR_WIN32A(ERROR_DS_NO_RDN_DEFINED_IN_SCHEMA)
+        CHK_ERR_WIN32A(ERROR_DS_RDN_DOESNT_MATCH_SCHEMA)
+        CHK_ERR_WIN32A(ERROR_DS_NO_REQUESTED_ATTS_FOUND)
+        CHK_ERR_WIN32A(ERROR_DS_USER_BUFFER_TO_SMALL)
+        CHK_ERR_WIN32A(ERROR_DS_ATT_IS_NOT_ON_OBJ)
+        CHK_ERR_WIN32A(ERROR_DS_ILLEGAL_MOD_OPERATION)
+        CHK_ERR_WIN32A(ERROR_DS_OBJ_TOO_LARGE)
+        CHK_ERR_WIN32A(ERROR_DS_BAD_INSTANCE_TYPE)
+        CHK_ERR_WIN32A(ERROR_DS_MASTERDSA_REQUIRED)
+        CHK_ERR_WIN32A(ERROR_DS_OBJECT_CLASS_REQUIRED)
+        CHK_ERR_WIN32A(ERROR_DS_MISSING_REQUIRED_ATT)
+        CHK_ERR_WIN32A(ERROR_DS_ATT_NOT_DEF_FOR_CLASS)
+        CHK_ERR_WIN32A(ERROR_DS_ATT_ALREADY_EXISTS)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_ADD_ATT_VALUES)
+        CHK_ERR_WIN32A(ERROR_DS_SINGLE_VALUE_CONSTRAINT)
+        CHK_ERR_WIN32A(ERROR_DS_RANGE_CONSTRAINT)
+        CHK_ERR_WIN32A(ERROR_DS_ATT_VAL_ALREADY_EXISTS)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_REM_MISSING_ATT)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_REM_MISSING_ATT_VAL)
+        CHK_ERR_WIN32A(ERROR_DS_ROOT_CANT_BE_SUBREF)
+        CHK_ERR_WIN32A(ERROR_DS_NO_CHAINING)
+        CHK_ERR_WIN32A(ERROR_DS_NO_CHAINED_EVAL)
+        CHK_ERR_WIN32A(ERROR_DS_NO_PARENT_OBJECT)
+        CHK_ERR_WIN32A(ERROR_DS_PARENT_IS_AN_ALIAS)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_MIX_MASTER_AND_REPS)
+        CHK_ERR_WIN32A(ERROR_DS_CHILDREN_EXIST)
+        CHK_ERR_WIN32A(ERROR_DS_OBJ_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_DS_ALIASED_OBJ_MISSING)
+        CHK_ERR_WIN32A(ERROR_DS_BAD_NAME_SYNTAX)
+        CHK_ERR_WIN32A(ERROR_DS_ALIAS_POINTS_TO_ALIAS)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_DEREF_ALIAS)
+        CHK_ERR_WIN32A(ERROR_DS_OUT_OF_SCOPE)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_DELETE_DSA_OBJ)
+        CHK_ERR_WIN32A(ERROR_DS_GENERIC_ERROR)
+        CHK_ERR_WIN32A(ERROR_DS_DSA_MUST_BE_INT_MASTER)
+        CHK_ERR_WIN32A(ERROR_DS_CLASS_NOT_DSA)
+        CHK_ERR_WIN32A(ERROR_DS_INSUFF_ACCESS_RIGHTS)
+        CHK_ERR_WIN32A(ERROR_DS_ILLEGAL_SUPERIOR)
+        CHK_ERR_WIN32A(ERROR_DS_ATTRIBUTE_OWNED_BY_SAM)
+        CHK_ERR_WIN32A(ERROR_DS_NAME_TOO_MANY_PARTS)
+        CHK_ERR_WIN32A(ERROR_DS_NAME_TOO_LONG)
+        CHK_ERR_WIN32A(ERROR_DS_NAME_VALUE_TOO_LONG)
+        CHK_ERR_WIN32A(ERROR_DS_NAME_UNPARSEABLE)
+        CHK_ERR_WIN32A(ERROR_DS_NAME_TYPE_UNKNOWN)
+        CHK_ERR_WIN32A(ERROR_DS_NOT_AN_OBJECT)
+        CHK_ERR_WIN32A(ERROR_DS_SEC_DESC_TOO_SHORT)
+        CHK_ERR_WIN32A(ERROR_DS_SEC_DESC_INVALID)
+        CHK_ERR_WIN32A(ERROR_DS_NO_DELETED_NAME)
+        CHK_ERR_WIN32A(ERROR_DS_SUBREF_MUST_HAVE_PARENT)
+        CHK_ERR_WIN32A(ERROR_DS_NCNAME_MUST_BE_NC)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_ADD_SYSTEM_ONLY)
+        CHK_ERR_WIN32A(ERROR_DS_CLASS_MUST_BE_CONCRETE)
+        CHK_ERR_WIN32A(ERROR_DS_INVALID_DMD)
+        CHK_ERR_WIN32A(ERROR_DS_OBJ_GUID_EXISTS)
+        CHK_ERR_WIN32A(ERROR_DS_NOT_ON_BACKLINK)
+        CHK_ERR_WIN32A(ERROR_DS_NO_CROSSREF_FOR_NC)
+        CHK_ERR_WIN32A(ERROR_DS_SHUTTING_DOWN)
+        CHK_ERR_WIN32A(ERROR_DS_UNKNOWN_OPERATION)
+        CHK_ERR_WIN32A(ERROR_DS_INVALID_ROLE_OWNER)
+        CHK_ERR_WIN32A(ERROR_DS_COULDNT_CONTACT_FSMO)
+        CHK_ERR_WIN32A(ERROR_DS_CROSS_NC_DN_RENAME)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_MOD_SYSTEM_ONLY)
+        CHK_ERR_WIN32A(ERROR_DS_REPLICATOR_ONLY)
+        CHK_ERR_WIN32A(ERROR_DS_OBJ_CLASS_NOT_DEFINED)
+        CHK_ERR_WIN32A(ERROR_DS_OBJ_CLASS_NOT_SUBCLASS)
+        CHK_ERR_WIN32A(ERROR_DS_NAME_REFERENCE_INVALID)
+        CHK_ERR_WIN32A(ERROR_DS_CROSS_REF_EXISTS)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_DEL_MASTER_CROSSREF)
+        CHK_ERR_WIN32A(ERROR_DS_SUBTREE_NOTIFY_NOT_NC_HEAD)
+        CHK_ERR_WIN32A(ERROR_DS_NOTIFY_FILTER_TOO_COMPLEX)
+        CHK_ERR_WIN32A(ERROR_DS_DUP_RDN)
+        CHK_ERR_WIN32A(ERROR_DS_DUP_OID)
+        CHK_ERR_WIN32A(ERROR_DS_DUP_MAPI_ID)
+        CHK_ERR_WIN32A(ERROR_DS_DUP_SCHEMA_ID_GUID)
+        CHK_ERR_WIN32A(ERROR_DS_DUP_LDAP_DISPLAY_NAME)
+        CHK_ERR_WIN32A(ERROR_DS_SEMANTIC_ATT_TEST)
+        CHK_ERR_WIN32A(ERROR_DS_SYNTAX_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_DS_EXISTS_IN_MUST_HAVE)
+        CHK_ERR_WIN32A(ERROR_DS_EXISTS_IN_MAY_HAVE)
+        CHK_ERR_WIN32A(ERROR_DS_NONEXISTENT_MAY_HAVE)
+        CHK_ERR_WIN32A(ERROR_DS_NONEXISTENT_MUST_HAVE)
+        CHK_ERR_WIN32A(ERROR_DS_AUX_CLS_TEST_FAIL)
+        CHK_ERR_WIN32A(ERROR_DS_NONEXISTENT_POSS_SUP)
+        CHK_ERR_WIN32A(ERROR_DS_SUB_CLS_TEST_FAIL)
+        CHK_ERR_WIN32A(ERROR_DS_BAD_RDN_ATT_ID_SYNTAX)
+        CHK_ERR_WIN32A(ERROR_DS_EXISTS_IN_AUX_CLS)
+        CHK_ERR_WIN32A(ERROR_DS_EXISTS_IN_SUB_CLS)
+        CHK_ERR_WIN32A(ERROR_DS_EXISTS_IN_POSS_SUP)
+        CHK_ERR_WIN32A(ERROR_DS_RECALCSCHEMA_FAILED)
+        CHK_ERR_WIN32A(ERROR_DS_TREE_DELETE_NOT_FINISHED)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_DELETE)
+        CHK_ERR_WIN32A(ERROR_DS_ATT_SCHEMA_REQ_ID)
+        CHK_ERR_WIN32A(ERROR_DS_BAD_ATT_SCHEMA_SYNTAX)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_CACHE_ATT)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_CACHE_CLASS)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_REMOVE_ATT_CACHE)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_REMOVE_CLASS_CACHE)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_RETRIEVE_DN)
+        CHK_ERR_WIN32A(ERROR_DS_MISSING_SUPREF)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_RETRIEVE_INSTANCE)
+        CHK_ERR_WIN32A(ERROR_DS_CODE_INCONSISTENCY)
+        CHK_ERR_WIN32A(ERROR_DS_DATABASE_ERROR)
+        CHK_ERR_WIN32A(ERROR_DS_GOVERNSID_MISSING)
+        CHK_ERR_WIN32A(ERROR_DS_MISSING_EXPECTED_ATT)
+        CHK_ERR_WIN32A(ERROR_DS_NCNAME_MISSING_CR_REF)
+        CHK_ERR_WIN32A(ERROR_DS_SECURITY_CHECKING_ERROR)
+        CHK_ERR_WIN32A(ERROR_DS_SCHEMA_NOT_LOADED)
+        CHK_ERR_WIN32A(ERROR_DS_SCHEMA_ALLOC_FAILED)
+        CHK_ERR_WIN32A(ERROR_DS_ATT_SCHEMA_REQ_SYNTAX)
+        CHK_ERR_WIN32A(ERROR_DS_GCVERIFY_ERROR)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_SCHEMA_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_FIND_DSA_OBJ)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_FIND_EXPECTED_NC)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_FIND_NC_IN_CACHE)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_RETRIEVE_CHILD)
+        CHK_ERR_WIN32A(ERROR_DS_SECURITY_ILLEGAL_MODIFY)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_REPLACE_HIDDEN_REC)
+        CHK_ERR_WIN32A(ERROR_DS_BAD_HIERARCHY_FILE)
+        CHK_ERR_WIN32A(ERROR_DS_BUILD_HIERARCHY_TABLE_FAILED)
+        CHK_ERR_WIN32A(ERROR_DS_CONFIG_PARAM_MISSING)
+        CHK_ERR_WIN32A(ERROR_DS_COUNTING_AB_INDICES_FAILED)
+        CHK_ERR_WIN32A(ERROR_DS_HIERARCHY_TABLE_MALLOC_FAILED)
+        CHK_ERR_WIN32A(ERROR_DS_INTERNAL_FAILURE)
+        CHK_ERR_WIN32A(ERROR_DS_UNKNOWN_ERROR)
+        CHK_ERR_WIN32A(ERROR_DS_ROOT_REQUIRES_CLASS_TOP)
+        CHK_ERR_WIN32A(ERROR_DS_REFUSING_FSMO_ROLES)
+        CHK_ERR_WIN32A(ERROR_DS_MISSING_FSMO_SETTINGS)
+        CHK_ERR_WIN32A(ERROR_DS_UNABLE_TO_SURRENDER_ROLES)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_GENERIC)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_INVALID_PARAMETER)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_BUSY)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_BAD_DN)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_BAD_NC)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_DN_EXISTS)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_INTERNAL_ERROR)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_INCONSISTENT_DIT)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_CONNECTION_FAILED)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_BAD_INSTANCE_TYPE)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_OUT_OF_MEM)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_MAIL_PROBLEM)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_REF_ALREADY_EXISTS)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_REF_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_OBJ_IS_REP_SOURCE)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_DB_ERROR)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_NO_REPLICA)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_ACCESS_DENIED)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_NOT_SUPPORTED)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_RPC_CANCELLED)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_SOURCE_DISABLED)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_SINK_DISABLED)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_NAME_COLLISION)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_SOURCE_REINSTALLED)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_MISSING_PARENT)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_PREEMPTED)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_ABANDON_SYNC)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_SHUTDOWN)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_INCOMPATIBLE_PARTIAL_SET)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_SOURCE_IS_PARTIAL_REPLICA)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_EXTN_CONNECTION_FAILED)
+        CHK_ERR_WIN32A(ERROR_DS_INSTALL_SCHEMA_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_DS_DUP_LINK_ID)
+        CHK_ERR_WIN32A(ERROR_DS_NAME_ERROR_RESOLVING)
+        CHK_ERR_WIN32A(ERROR_DS_NAME_ERROR_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_DS_NAME_ERROR_NOT_UNIQUE)
+        CHK_ERR_WIN32A(ERROR_DS_NAME_ERROR_NO_MAPPING)
+        CHK_ERR_WIN32A(ERROR_DS_NAME_ERROR_DOMAIN_ONLY)
+        CHK_ERR_WIN32A(ERROR_DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING)
+        CHK_ERR_WIN32A(ERROR_DS_CONSTRUCTED_ATT_MOD)
+        CHK_ERR_WIN32A(ERROR_DS_WRONG_OM_OBJ_CLASS)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_REPL_PENDING)
+        CHK_ERR_WIN32A(DNS_ERROR_RESPONSE_CODES_BASE)
+//        CHK_ERR_WIN32A(DNS_ERROR_MASK)
+        CHK_ERR_WIN32A(DNS_ERROR_RCODE_FORMAT_ERROR)
+        CHK_ERR_WIN32A(DNS_ERROR_RCODE_SERVER_FAILURE)
+        CHK_ERR_WIN32A(DNS_ERROR_RCODE_NAME_ERROR)
+        CHK_ERR_WIN32A(DNS_ERROR_RCODE_NOT_IMPLEMENTED)
+        CHK_ERR_WIN32A(DNS_ERROR_RCODE_REFUSED)
+        CHK_ERR_WIN32A(DNS_ERROR_RCODE_YXDOMAIN)
+        CHK_ERR_WIN32A(DNS_ERROR_RCODE_YXRRSET)
+        CHK_ERR_WIN32A(DNS_ERROR_RCODE_NXRRSET)
+        CHK_ERR_WIN32A(DNS_ERROR_RCODE_NOTAUTH)
+        CHK_ERR_WIN32A(DNS_ERROR_RCODE_NOTZONE)
+        CHK_ERR_WIN32A(DNS_ERROR_RCODE_BADSIG)
+        CHK_ERR_WIN32A(DNS_ERROR_RCODE_BADKEY)
+        CHK_ERR_WIN32A(DNS_ERROR_RCODE_BADTIME)
+        CHK_ERR_WIN32A(DNS_ERROR_PACKET_FMT_BASE)
+        CHK_ERR_WIN32A(DNS_INFO_NO_RECORDS)
+        CHK_ERR_WIN32A(DNS_ERROR_BAD_PACKET)
+        CHK_ERR_WIN32A(DNS_ERROR_NO_PACKET)
+        CHK_ERR_WIN32A(DNS_ERROR_RCODE)
+        CHK_ERR_WIN32A(DNS_ERROR_UNSECURE_PACKET)
+        CHK_ERR_WIN32A(DNS_ERROR_GENERAL_API_BASE)
+        CHK_ERR_WIN32A(DNS_ERROR_INVALID_TYPE)
+        CHK_ERR_WIN32A(DNS_ERROR_INVALID_IP_ADDRESS)
+        CHK_ERR_WIN32A(DNS_ERROR_INVALID_PROPERTY)
+        CHK_ERR_WIN32A(DNS_ERROR_TRY_AGAIN_LATER)
+        CHK_ERR_WIN32A(DNS_ERROR_NOT_UNIQUE)
+        CHK_ERR_WIN32A(DNS_ERROR_NON_RFC_NAME)
+        CHK_ERR_WIN32A(DNS_STATUS_FQDN)
+        CHK_ERR_WIN32A(DNS_STATUS_DOTTED_NAME)
+        CHK_ERR_WIN32A(DNS_STATUS_SINGLE_PART_NAME)
+        CHK_ERR_WIN32A(DNS_ERROR_ZONE_BASE)
+        CHK_ERR_WIN32A(DNS_ERROR_ZONE_DOES_NOT_EXIST)
+        CHK_ERR_WIN32A(DNS_ERROR_NO_ZONE_INFO)
+        CHK_ERR_WIN32A(DNS_ERROR_INVALID_ZONE_OPERATION)
+        CHK_ERR_WIN32A(DNS_ERROR_ZONE_CONFIGURATION_ERROR)
+        CHK_ERR_WIN32A(DNS_ERROR_ZONE_HAS_NO_SOA_RECORD)
+        CHK_ERR_WIN32A(DNS_ERROR_ZONE_HAS_NO_NS_RECORDS)
+        CHK_ERR_WIN32A(DNS_ERROR_ZONE_LOCKED)
+        CHK_ERR_WIN32A(DNS_ERROR_ZONE_CREATION_FAILED)
+        CHK_ERR_WIN32A(DNS_ERROR_ZONE_ALREADY_EXISTS)
+        CHK_ERR_WIN32A(DNS_ERROR_AUTOZONE_ALREADY_EXISTS)
+        CHK_ERR_WIN32A(DNS_ERROR_INVALID_ZONE_TYPE)
+        CHK_ERR_WIN32A(DNS_ERROR_SECONDARY_REQUIRES_MASTER_IP)
+        CHK_ERR_WIN32A(DNS_ERROR_ZONE_NOT_SECONDARY)
+        CHK_ERR_WIN32A(DNS_ERROR_NEED_SECONDARY_ADDRESSES)
+        CHK_ERR_WIN32A(DNS_ERROR_WINS_INIT_FAILED)
+        CHK_ERR_WIN32A(DNS_ERROR_NEED_WINS_SERVERS)
+        CHK_ERR_WIN32A(DNS_ERROR_NBSTAT_INIT_FAILED)
+        CHK_ERR_WIN32A(DNS_ERROR_SOA_DELETE_INVALID)
+        CHK_ERR_WIN32A(DNS_ERROR_DATAFILE_BASE)
+        CHK_ERR_WIN32A(DNS_ERROR_PRIMARY_REQUIRES_DATAFILE)
+        CHK_ERR_WIN32A(DNS_ERROR_INVALID_DATAFILE_NAME)
+        CHK_ERR_WIN32A(DNS_ERROR_DATAFILE_OPEN_FAILURE)
+        CHK_ERR_WIN32A(DNS_ERROR_FILE_WRITEBACK_FAILED)
+        CHK_ERR_WIN32A(DNS_ERROR_DATAFILE_PARSING)
+        CHK_ERR_WIN32A(DNS_ERROR_DATABASE_BASE)
+        CHK_ERR_WIN32A(DNS_ERROR_RECORD_DOES_NOT_EXIST)
+        CHK_ERR_WIN32A(DNS_ERROR_RECORD_FORMAT)
+        CHK_ERR_WIN32A(DNS_ERROR_NODE_CREATION_FAILED)
+        CHK_ERR_WIN32A(DNS_ERROR_UNKNOWN_RECORD_TYPE)
+        CHK_ERR_WIN32A(DNS_ERROR_RECORD_TIMED_OUT)
+        CHK_ERR_WIN32A(DNS_ERROR_NAME_NOT_IN_ZONE)
+        CHK_ERR_WIN32A(DNS_ERROR_CNAME_LOOP)
+        CHK_ERR_WIN32A(DNS_ERROR_NODE_IS_CNAME)
+        CHK_ERR_WIN32A(DNS_ERROR_CNAME_COLLISION)
+        CHK_ERR_WIN32A(DNS_ERROR_RECORD_ONLY_AT_ZONE_ROOT)
+        CHK_ERR_WIN32A(DNS_ERROR_RECORD_ALREADY_EXISTS)
+        CHK_ERR_WIN32A(DNS_ERROR_SECONDARY_DATA)
+        CHK_ERR_WIN32A(DNS_ERROR_NO_CREATE_CACHE_DATA)
+        CHK_ERR_WIN32A(DNS_ERROR_NAME_DOES_NOT_EXIST)
+        CHK_ERR_WIN32A(DNS_WARNING_PTR_CREATE_FAILED)
+        CHK_ERR_WIN32A(DNS_WARNING_DOMAIN_UNDELETED)
+        CHK_ERR_WIN32A(DNS_ERROR_DS_UNAVAILABLE)
+        CHK_ERR_WIN32A(DNS_ERROR_DS_ZONE_ALREADY_EXISTS)
+        CHK_ERR_WIN32A(DNS_ERROR_NO_BOOTFILE_IF_DS_ZONE)
+        CHK_ERR_WIN32A(DNS_ERROR_OPERATION_BASE)
+        CHK_ERR_WIN32A(DNS_INFO_AXFR_COMPLETE)
+        CHK_ERR_WIN32A(DNS_ERROR_AXFR)
+        CHK_ERR_WIN32A(DNS_INFO_ADDED_LOCAL_WINS)
+        CHK_ERR_WIN32A(DNS_ERROR_SECURE_BASE)
+        CHK_ERR_WIN32A(DNS_STATUS_CONTINUE_NEEDED)
+        CHK_ERR_WIN32A(DNS_ERROR_SETUP_BASE)
+        CHK_ERR_WIN32A(DNS_ERROR_NO_TCPIP)
+        CHK_ERR_WIN32A(DNS_ERROR_NO_DNS_SERVERS)
+        CHK_ERR_WIN32A(WSABASEERR)
+        CHK_ERR_WIN32A(WSAEINTR)
+        CHK_ERR_WIN32A(WSAEBADF)
+        CHK_ERR_WIN32A(WSAEACCES)
+        CHK_ERR_WIN32A(WSAEFAULT)
+        CHK_ERR_WIN32A(WSAEINVAL)
+        CHK_ERR_WIN32A(WSAEMFILE)
+        CHK_ERR_WIN32A(WSAEWOULDBLOCK)
+        CHK_ERR_WIN32A(WSAEINPROGRESS)
+        CHK_ERR_WIN32A(WSAEALREADY)
+        CHK_ERR_WIN32A(WSAENOTSOCK)
+        CHK_ERR_WIN32A(WSAEDESTADDRREQ)
+        CHK_ERR_WIN32A(WSAEMSGSIZE)
+        CHK_ERR_WIN32A(WSAEPROTOTYPE)
+        CHK_ERR_WIN32A(WSAENOPROTOOPT)
+        CHK_ERR_WIN32A(WSAEPROTONOSUPPORT)
+        CHK_ERR_WIN32A(WSAESOCKTNOSUPPORT)
+        CHK_ERR_WIN32A(WSAEOPNOTSUPP)
+        CHK_ERR_WIN32A(WSAEPFNOSUPPORT)
+        CHK_ERR_WIN32A(WSAEAFNOSUPPORT)
+        CHK_ERR_WIN32A(WSAEADDRINUSE)
+        CHK_ERR_WIN32A(WSAEADDRNOTAVAIL)
+        CHK_ERR_WIN32A(WSAENETDOWN)
+        CHK_ERR_WIN32A(WSAENETUNREACH)
+        CHK_ERR_WIN32A(WSAENETRESET)
+        CHK_ERR_WIN32A(WSAECONNABORTED)
+        CHK_ERR_WIN32A(WSAECONNRESET)
+        CHK_ERR_WIN32A(WSAENOBUFS)
+        CHK_ERR_WIN32A(WSAEISCONN)
+        CHK_ERR_WIN32A(WSAENOTCONN)
+        CHK_ERR_WIN32A(WSAESHUTDOWN)
+        CHK_ERR_WIN32A(WSAETOOMANYREFS)
+        CHK_ERR_WIN32A(WSAETIMEDOUT)
+        CHK_ERR_WIN32A(WSAECONNREFUSED)
+        CHK_ERR_WIN32A(WSAELOOP)
+        CHK_ERR_WIN32A(WSAENAMETOOLONG)
+        CHK_ERR_WIN32A(WSAEHOSTDOWN)
+        CHK_ERR_WIN32A(WSAEHOSTUNREACH)
+        CHK_ERR_WIN32A(WSAENOTEMPTY)
+        CHK_ERR_WIN32A(WSAEPROCLIM)
+        CHK_ERR_WIN32A(WSAEUSERS)
+        CHK_ERR_WIN32A(WSAEDQUOT)
+        CHK_ERR_WIN32A(WSAESTALE)
+        CHK_ERR_WIN32A(WSAEREMOTE)
+        CHK_ERR_WIN32A(WSASYSNOTREADY)
+        CHK_ERR_WIN32A(WSAVERNOTSUPPORTED)
+        CHK_ERR_WIN32A(WSANOTINITIALISED)
+        CHK_ERR_WIN32A(WSAEDISCON)
+        CHK_ERR_WIN32A(WSAENOMORE)
+        CHK_ERR_WIN32A(WSAECANCELLED)
+        CHK_ERR_WIN32A(WSAEINVALIDPROCTABLE)
+        CHK_ERR_WIN32A(WSAEINVALIDPROVIDER)
+        CHK_ERR_WIN32A(WSAEPROVIDERFAILEDINIT)
+        CHK_ERR_WIN32A(WSASYSCALLFAILURE)
+        CHK_ERR_WIN32A(WSASERVICE_NOT_FOUND)
+        CHK_ERR_WIN32A(WSATYPE_NOT_FOUND)
+        CHK_ERR_WIN32A(WSA_E_NO_MORE)
+        CHK_ERR_WIN32A(WSA_E_CANCELLED)
+        CHK_ERR_WIN32A(WSAEREFUSED)
+        CHK_ERR_WIN32A(WSAHOST_NOT_FOUND)
+        CHK_ERR_WIN32A(WSATRY_AGAIN)
+        CHK_ERR_WIN32A(WSANO_RECOVERY)
+        CHK_ERR_WIN32A(WSANO_DATA)
+        CHK_ERR_WIN32A(WSA_QOS_RECEIVERS)
+        CHK_ERR_WIN32A(WSA_QOS_SENDERS)
+        CHK_ERR_WIN32A(WSA_QOS_NO_SENDERS)
+        CHK_ERR_WIN32A(WSA_QOS_NO_RECEIVERS)
+        CHK_ERR_WIN32A(WSA_QOS_REQUEST_CONFIRMED)
+        CHK_ERR_WIN32A(WSA_QOS_ADMISSION_FAILURE)
+        CHK_ERR_WIN32A(WSA_QOS_POLICY_FAILURE)
+        CHK_ERR_WIN32A(WSA_QOS_BAD_STYLE)
+        CHK_ERR_WIN32A(WSA_QOS_BAD_OBJECT)
+        CHK_ERR_WIN32A(WSA_QOS_TRAFFIC_CTRL_ERROR)
+        CHK_ERR_WIN32A(WSA_QOS_GENERIC_ERROR)
+
+        CHK_ERRA(CO_E_ATTEMPT_TO_CREATE_OUTSIDE_CLIENT_CONTEXT)
+        CHK_ERRA(CO_E_SERVER_PAUSED)
+        CHK_ERRA(CO_E_SERVER_NOT_PAUSED)
+        CHK_ERRA(CO_E_CLASS_DISABLED)
+        CHK_ERRA(CO_E_CLRNOTAVAILABLE)
+        CHK_ERRA(CO_E_ASYNC_WORK_REJECTED)
+        CHK_ERRA(CO_E_SERVER_INIT_TIMEOUT)
+        CHK_ERRA(CO_E_NO_SECCTX_IN_ACTIVATE)
+        CHK_ERRA(CO_E_TRACKER_CONFIG)
+        CHK_ERRA(CO_E_THREADPOOL_CONFIG)
+        CHK_ERRA(CO_E_SXS_CONFIG)
+        CHK_ERRA(CO_E_MALFORMED_SPN)
+        CHK_ERRA(REGDB_E_BADTHREADINGMODEL)
+//        CHK_ERRA(EVENT_E_FIRST)
+//        CHK_ERRA(EVENT_E_LAST)
+//        CHK_ERRA(EVENT_S_FIRST)
+//        CHK_ERRA(EVENT_S_LAST)
+//        CHK_ERRA(EVENT_S_SOME_SUBSCRIBERS_FAILED)
+//        CHK_ERRA(EVENT_E_ALL_SUBSCRIBERS_FAILED)
+        CHK_ERRA(EVENT_S_NOSUBSCRIBERS)
+//        CHK_ERRA(EVENT_E_QUERYSYNTAX)
+//        CHK_ERRA(EVENT_E_QUERYFIELD)
+//        CHK_ERRA(EVENT_E_INTERNALEXCEPTION)
+//        CHK_ERRA(EVENT_E_INTERNALERROR)
+//        CHK_ERRA(EVENT_E_INVALID_PER_USER_SID)
+//        CHK_ERRA(EVENT_E_USER_EXCEPTION)
+//        CHK_ERRA(EVENT_E_TOO_MANY_METHODS)
+//        CHK_ERRA(EVENT_E_MISSING_EVENTCLASS)
+//        CHK_ERRA(EVENT_E_NOT_ALL_REMOVED)
+//        CHK_ERRA(EVENT_E_COMPLUS_NOT_INSTALLED)
+//        CHK_ERRA(EVENT_E_CANT_MODIFY_OR_DELETE_UNCONFIGURED_OBJECT)
+//        CHK_ERRA(EVENT_E_CANT_MODIFY_OR_DELETE_CONFIGURED_OBJECT)
+//        CHK_ERRA(EVENT_E_INVALID_EVENT_CLASS_PARTITION)
+//        CHK_ERRA(EVENT_E_PER_USER_SID_NOT_LOGGED_ON)
+        CHK_ERRA(CONTEXT_E_FIRST)
+        CHK_ERRA(CONTEXT_E_LAST)
+        CHK_ERRA(CONTEXT_S_FIRST)
+        CHK_ERRA(CONTEXT_S_LAST)
+        CHK_ERRA(CONTEXT_E_ABORTED)
+        CHK_ERRA(CONTEXT_E_ABORTING)
+        CHK_ERRA(CONTEXT_E_NOCONTEXT)
+//        CHK_ERRA(CONTEXT_E_WOULD_DEADLOCK)
+        CHK_ERRA(CONTEXT_E_SYNCH_TIMEOUT)
+        CHK_ERRA(CONTEXT_E_OLDREF)
+        CHK_ERRA(CONTEXT_E_ROLENOTFOUND)
+        CHK_ERRA(CONTEXT_E_TMNOTAVAILABLE)
+        CHK_ERRA(CO_E_ACTIVATIONFAILED)
+        CHK_ERRA(CO_E_ACTIVATIONFAILED_EVENTLOGGED)
+        CHK_ERRA(CO_E_ACTIVATIONFAILED_CATALOGERROR)
+        CHK_ERRA(CO_E_ACTIVATIONFAILED_TIMEOUT)
+        CHK_ERRA(CO_E_INITIALIZATIONFAILED)
+        CHK_ERRA(CONTEXT_E_NOJIT)
+        CHK_ERRA(CONTEXT_E_NOTRANSACTION)
+        CHK_ERRA(CO_E_THREADINGMODEL_CHANGED)
+        CHK_ERRA(CO_E_NOIISINTRINSICS)
+        CHK_ERRA(CO_E_NOCOOKIES)
+        CHK_ERRA(CO_E_DBERROR)
+        CHK_ERRA(CO_E_NOTPOOLED)
+        CHK_ERRA(CO_E_NOTCONSTRUCTED)
+        CHK_ERRA(CO_E_NOSYNCHRONIZATION)
+//        CHK_ERRA(CO_E_ISOLEVELMISMATCH)
+        CHK_ERRA(SCHED_S_TASK_READY)
+        CHK_ERRA(SCHED_S_TASK_RUNNING)
+        CHK_ERRA(SCHED_S_TASK_DISABLED)
+        CHK_ERRA(SCHED_S_TASK_HAS_NOT_RUN)
+        CHK_ERRA(SCHED_S_TASK_NO_MORE_RUNS)
+        CHK_ERRA(SCHED_S_TASK_NOT_SCHEDULED)
+        CHK_ERRA(SCHED_S_TASK_TERMINATED)
+        CHK_ERRA(SCHED_S_TASK_NO_VALID_TRIGGERS)
+        CHK_ERRA(SCHED_S_EVENT_TRIGGER)
+        CHK_ERRA(SCHED_E_TRIGGER_NOT_FOUND)
+        CHK_ERRA(SCHED_E_TASK_NOT_READY)
+        CHK_ERRA(SCHED_E_TASK_NOT_RUNNING)
+        CHK_ERRA(SCHED_E_SERVICE_NOT_INSTALLED)
+        CHK_ERRA(SCHED_E_CANNOT_OPEN_TASK)
+        CHK_ERRA(SCHED_E_INVALID_TASK)
+        CHK_ERRA(SCHED_E_ACCOUNT_INFORMATION_NOT_SET)
+        CHK_ERRA(SCHED_E_ACCOUNT_NAME_NOT_FOUND)
+        CHK_ERRA(SCHED_E_ACCOUNT_DBASE_CORRUPT)
+        CHK_ERRA(SCHED_E_NO_SECURITY_SERVICES)
+        CHK_ERRA(SCHED_E_UNKNOWN_OBJECT_VERSION)
+        CHK_ERRA(SCHED_E_UNSUPPORTED_ACCOUNT_OPTION)
+        CHK_ERRA(SCHED_E_SERVICE_NOT_RUNNING)
+        CHK_ERRA(CO_S_MACHINENAMENOTFOUND)
+        CHK_ERRA(STG_E_STATUS_COPY_PROTECTION_FAILURE)
+        CHK_ERRA(STG_E_CSS_AUTHENTICATION_FAILURE)
+        CHK_ERRA(STG_E_CSS_KEY_NOT_PRESENT)
+        CHK_ERRA(STG_E_CSS_KEY_NOT_ESTABLISHED)
+        CHK_ERRA(STG_E_CSS_SCRAMBLED_SECTOR)
+        CHK_ERRA(STG_E_CSS_REGION_MISMATCH)
+        CHK_ERRA(STG_E_RESETS_EXHAUSTED)
+        CHK_ERRA(CO_E_CANCEL_DISABLED)
+        CHK_ERRA(ERROR_AUDITING_DISABLED)
+        CHK_ERRA(ERROR_ALL_SIDS_FILTERED)
+        CHK_ERRA(NTE_TEMPORARY_PROFILE)
+        CHK_ERRA(NTE_FIXEDPARAMETER)
+        CHK_ERRA(SEC_E_INSUFFICIENT_MEMORY)
+        CHK_ERRA(SEC_E_INVALID_HANDLE)
+        CHK_ERRA(SEC_E_UNSUPPORTED_FUNCTION)
+        CHK_ERRA(SEC_E_TARGET_UNKNOWN)
+        CHK_ERRA(SEC_E_INTERNAL_ERROR)
+        CHK_ERRA(SEC_E_SECPKG_NOT_FOUND)
+        CHK_ERRA(SEC_E_NOT_OWNER)
+        CHK_ERRA(SEC_E_CANNOT_INSTALL)
+        CHK_ERRA(SEC_E_INVALID_TOKEN)
+        CHK_ERRA(SEC_E_CANNOT_PACK)
+        CHK_ERRA(SEC_E_QOP_NOT_SUPPORTED)
+        CHK_ERRA(SEC_E_NO_IMPERSONATION)
+        CHK_ERRA(SEC_E_LOGON_DENIED)
+        CHK_ERRA(SEC_E_UNKNOWN_CREDENTIALS)
+        CHK_ERRA(SEC_E_NO_CREDENTIALS)
+        CHK_ERRA(SEC_E_MESSAGE_ALTERED)
+        CHK_ERRA(SEC_E_OUT_OF_SEQUENCE)
+        CHK_ERRA(SEC_E_NO_AUTHENTICATING_AUTHORITY)
+        CHK_ERRA(SEC_I_CONTINUE_NEEDED)
+        CHK_ERRA(SEC_I_COMPLETE_NEEDED)
+        CHK_ERRA(SEC_I_COMPLETE_AND_CONTINUE)
+        CHK_ERRA(SEC_I_LOCAL_LOGON)
+        CHK_ERRA(SEC_E_BAD_PKGID)
+        CHK_ERRA(SEC_E_CONTEXT_EXPIRED)
+        CHK_ERRA(SEC_I_CONTEXT_EXPIRED)
+        CHK_ERRA(SEC_E_INCOMPLETE_MESSAGE)
+        CHK_ERRA(SEC_E_INCOMPLETE_CREDENTIALS)
+        CHK_ERRA(SEC_E_BUFFER_TOO_SMALL)
+        CHK_ERRA(SEC_I_INCOMPLETE_CREDENTIALS)
+        CHK_ERRA(SEC_I_RENEGOTIATE)
+        CHK_ERRA(SEC_E_WRONG_PRINCIPAL)
+        CHK_ERRA(SEC_I_NO_LSA_CONTEXT)
+        CHK_ERRA(SEC_E_TIME_SKEW)
+        CHK_ERRA(SEC_E_UNTRUSTED_ROOT)
+        CHK_ERRA(SEC_E_ILLEGAL_MESSAGE)
+        CHK_ERRA(SEC_E_CERT_UNKNOWN)
+        CHK_ERRA(SEC_E_CERT_EXPIRED)
+        CHK_ERRA(SEC_E_ENCRYPT_FAILURE)
+        CHK_ERRA(SEC_E_DECRYPT_FAILURE)
+        CHK_ERRA(SEC_E_ALGORITHM_MISMATCH)
+        CHK_ERRA(SEC_E_SECURITY_QOS_FAILED)
+        CHK_ERRA(SEC_E_UNFINISHED_CONTEXT_DELETED)
+        CHK_ERRA(SEC_E_NO_TGT_REPLY)
+        CHK_ERRA(SEC_E_NO_IP_ADDRESSES)
+        CHK_ERRA(SEC_E_WRONG_CREDENTIAL_HANDLE)
+        CHK_ERRA(SEC_E_CRYPTO_SYSTEM_INVALID)
+        CHK_ERRA(SEC_E_MAX_REFERRALS_EXCEEDED)
+        CHK_ERRA(SEC_E_MUST_BE_KDC)
+        CHK_ERRA(SEC_E_STRONG_CRYPTO_NOT_SUPPORTED)
+        CHK_ERRA(SEC_E_TOO_MANY_PRINCIPALS)
+        CHK_ERRA(SEC_E_NO_PA_DATA)
+        CHK_ERRA(SEC_E_PKINIT_NAME_MISMATCH)
+        CHK_ERRA(SEC_E_SMARTCARD_LOGON_REQUIRED)
+        CHK_ERRA(SEC_E_SHUTDOWN_IN_PROGRESS)
+        CHK_ERRA(SEC_E_KDC_INVALID_REQUEST)
+        CHK_ERRA(SEC_E_KDC_UNABLE_TO_REFER)
+        CHK_ERRA(SEC_E_KDC_UNKNOWN_ETYPE)
+        CHK_ERRA(SEC_E_UNSUPPORTED_PREAUTH)
+        CHK_ERRA(SEC_E_DELEGATION_REQUIRED)
+        CHK_ERRA(SEC_E_BAD_BINDINGS)
+        CHK_ERRA(SEC_E_MULTIPLE_ACCOUNTS)
+        CHK_ERRA(SEC_E_NO_KERB_KEY)
+//        CHK_ERRA(SEC_E_CERT_WRONG_USAGE)
+//        CHK_ERRA(SEC_E_DOWNGRADE_DETECTED)
+        CHK_ERRA(SEC_E_SMARTCARD_CERT_REVOKED)
+        CHK_ERRA(SEC_E_ISSUING_CA_UNTRUSTED)
+        CHK_ERRA(SEC_E_REVOCATION_OFFLINE_C)
+        CHK_ERRA(SEC_E_PKINIT_CLIENT_FAILURE)
+        CHK_ERRA(SEC_E_SMARTCARD_CERT_EXPIRED)
+//        CHK_ERRA(SEC_E_NO_SPM)
+//        CHK_ERRA(SEC_E_NOT_SUPPORTED)
+        CHK_ERRA(CRYPT_I_NEW_PROTECTION_REQUIRED)
+        CHK_ERRA(CRYPT_E_MISSING_PUBKEY_PARA)
+        CHK_ERRA(CRYPT_E_ASN1_ERROR)
+        CHK_ERRA(CRYPT_E_ASN1_INTERNAL)
+        CHK_ERRA(CRYPT_E_ASN1_EOD)
+        CHK_ERRA(CRYPT_E_ASN1_CORRUPT)
+        CHK_ERRA(CRYPT_E_ASN1_LARGE)
+        CHK_ERRA(CRYPT_E_ASN1_CONSTRAINT)
+        CHK_ERRA(CRYPT_E_ASN1_MEMORY)
+        CHK_ERRA(CRYPT_E_ASN1_OVERFLOW)
+        CHK_ERRA(CRYPT_E_ASN1_BADPDU)
+        CHK_ERRA(CRYPT_E_ASN1_BADARGS)
+        CHK_ERRA(CRYPT_E_ASN1_BADREAL)
+        CHK_ERRA(CRYPT_E_ASN1_BADTAG)
+        CHK_ERRA(CRYPT_E_ASN1_CHOICE)
+        CHK_ERRA(CRYPT_E_ASN1_RULE)
+        CHK_ERRA(CRYPT_E_ASN1_UTF8)
+        CHK_ERRA(CRYPT_E_ASN1_PDU_TYPE)
+        CHK_ERRA(CRYPT_E_ASN1_NYI)
+        CHK_ERRA(CRYPT_E_ASN1_EXTENDED)
+        CHK_ERRA(CRYPT_E_ASN1_NOEOD)
+        CHK_ERRA(CERTSRV_E_SERVER_SUSPENDED)
+        CHK_ERRA(CERTSRV_E_ENCODING_LENGTH)
+        CHK_ERRA(CERTSRV_E_ROLECONFLICT)
+        CHK_ERRA(CERTSRV_E_RESTRICTEDOFFICER)
+        CHK_ERRA(CERTSRV_E_KEY_ARCHIVAL_NOT_CONFIGURED)
+        CHK_ERRA(CERTSRV_E_NO_VALID_KRA)
+        CHK_ERRA(CERTSRV_E_BAD_REQUEST_KEY_ARCHIVAL)
+        CHK_ERRA(CERTSRV_E_NO_CAADMIN_DEFINED)
+        CHK_ERRA(CERTSRV_E_BAD_RENEWAL_CERT_ATTRIBUTE)
+        CHK_ERRA(CERTSRV_E_NO_DB_SESSIONS)
+        CHK_ERRA(CERTSRV_E_ALIGNMENT_FAULT)
+        CHK_ERRA(CERTSRV_E_ENROLL_DENIED)
+        CHK_ERRA(CERTSRV_E_TEMPLATE_DENIED)
+//        CHK_ERRA(CERTSRV_E_DOWNLEVEL_DC_SSL_OR_UPGRADE)
+        CHK_ERRA(CERTSRV_E_TEMPLATE_CONFLICT)
+        CHK_ERRA(CERTSRV_E_SUBJECT_ALT_NAME_REQUIRED)
+        CHK_ERRA(CERTSRV_E_ARCHIVED_KEY_REQUIRED)
+        CHK_ERRA(CERTSRV_E_SMIME_REQUIRED)
+        CHK_ERRA(CERTSRV_E_BAD_RENEWAL_SUBJECT)
+        CHK_ERRA(CERTSRV_E_BAD_TEMPLATE_VERSION)
+        CHK_ERRA(CERTSRV_E_TEMPLATE_POLICY_REQUIRED)
+        CHK_ERRA(CERTSRV_E_SIGNATURE_POLICY_REQUIRED)
+        CHK_ERRA(CERTSRV_E_SIGNATURE_COUNT)
+        CHK_ERRA(CERTSRV_E_SIGNATURE_REJECTED)
+        CHK_ERRA(CERTSRV_E_ISSUANCE_POLICY_REQUIRED)
+        CHK_ERRA(CERTSRV_E_SUBJECT_UPN_REQUIRED)
+        CHK_ERRA(CERTSRV_E_SUBJECT_DIRECTORY_GUID_REQUIRED)
+        CHK_ERRA(CERTSRV_E_SUBJECT_DNS_REQUIRED)
+        CHK_ERRA(CERTSRV_E_ARCHIVED_KEY_UNEXPECTED)
+        CHK_ERRA(CERTSRV_E_KEY_LENGTH)
+//        CHK_ERRA(CERTSRV_E_SUBJECT_EMAIL_REQUIRED)
+//        CHK_ERRA(CERTSRV_E_UNKNOWN_CERT_TYPE)
+//        CHK_ERRA(CERTSRV_E_CERT_TYPE_OVERLAP)
+        CHK_ERRA(XENROLL_E_KEY_NOT_EXPORTABLE)
+        CHK_ERRA(XENROLL_E_CANNOT_ADD_ROOT_CERT)
+        CHK_ERRA(XENROLL_E_RESPONSE_KA_HASH_NOT_FOUND)
+        CHK_ERRA(XENROLL_E_RESPONSE_UNEXPECTED_KA_HASH)
+        CHK_ERRA(XENROLL_E_RESPONSE_KA_HASH_MISMATCH)
+        CHK_ERRA(XENROLL_E_KEYSPEC_SMIME_MISMATCH)
+        CHK_ERRA(MSSIPOTF_E_OUTOFMEMRANGE)
+        CHK_ERRA(MSSIPOTF_E_CANTGETOBJECT)
+        CHK_ERRA(MSSIPOTF_E_NOHEADTABLE)
+        CHK_ERRA(MSSIPOTF_E_BAD_MAGICNUMBER)
+        CHK_ERRA(MSSIPOTF_E_BAD_OFFSET_TABLE)
+        CHK_ERRA(MSSIPOTF_E_TABLE_TAGORDER)
+        CHK_ERRA(MSSIPOTF_E_TABLE_LONGWORD)
+        CHK_ERRA(MSSIPOTF_E_BAD_FIRST_TABLE_PLACEMENT)
+        CHK_ERRA(MSSIPOTF_E_TABLES_OVERLAP)
+        CHK_ERRA(MSSIPOTF_E_TABLE_PADBYTES)
+        CHK_ERRA(MSSIPOTF_E_FILETOOSMALL)
+        CHK_ERRA(MSSIPOTF_E_TABLE_CHECKSUM)
+        CHK_ERRA(MSSIPOTF_E_FILE_CHECKSUM)
+        CHK_ERRA(MSSIPOTF_E_FAILED_POLICY)
+        CHK_ERRA(MSSIPOTF_E_FAILED_HINTS_CHECK)
+        CHK_ERRA(MSSIPOTF_E_NOT_OPENTYPE)
+        CHK_ERRA(MSSIPOTF_E_FILE)
+        CHK_ERRA(MSSIPOTF_E_CRYPT)
+        CHK_ERRA(MSSIPOTF_E_BADVERSION)
+        CHK_ERRA(MSSIPOTF_E_DSIG_STRUCTURE)
+        CHK_ERRA(MSSIPOTF_E_PCONST_CHECK)
+        CHK_ERRA(MSSIPOTF_E_STRUCTURE)
+        CHK_ERRA(TRUST_E_EXPLICIT_DISTRUST)
+        CHK_ERRA(CERT_E_UNTRUSTEDCA)
+        CHK_ERRA(CERT_E_INVALID_POLICY)
+        CHK_ERRA(CERT_E_INVALID_NAME)
+        CHK_ERRA(SPAPI_E_NOT_DISABLEABLE)
+        CHK_ERRA(SPAPI_E_CANT_REMOVE_DEVINST)
+        CHK_ERRA(SPAPI_E_INVALID_TARGET)
+        CHK_ERRA(SPAPI_E_DRIVER_NONNATIVE)
+        CHK_ERRA(SPAPI_E_IN_WOW64)
+        CHK_ERRA(SPAPI_E_SET_SYSTEM_RESTORE_POINT)
+        CHK_ERRA(SPAPI_E_INCORRECTLY_COPIED_INF)
+        CHK_ERRA(SPAPI_E_SCE_DISABLED)
+        CHK_ERRA(SCARD_E_NO_KEY_CONTAINER)
+        CHK_ERRA(SCARD_W_CARD_NOT_AUTHENTICATED)
+        CHK_ERRA(COMADMIN_E_OBJECTERRORS)
+        CHK_ERRA(COMADMIN_E_OBJECTINVALID)
+        CHK_ERRA(COMADMIN_E_KEYMISSING)
+        CHK_ERRA(COMADMIN_E_ALREADYINSTALLED)
+        CHK_ERRA(COMADMIN_E_APP_FILE_WRITEFAIL)
+        CHK_ERRA(COMADMIN_E_APP_FILE_READFAIL)
+        CHK_ERRA(COMADMIN_E_APP_FILE_VERSION)
+        CHK_ERRA(COMADMIN_E_BADPATH)
+        CHK_ERRA(COMADMIN_E_APPLICATIONEXISTS)
+        CHK_ERRA(COMADMIN_E_ROLEEXISTS)
+        CHK_ERRA(COMADMIN_E_CANTCOPYFILE)
+        CHK_ERRA(COMADMIN_E_NOUSER)
+        CHK_ERRA(COMADMIN_E_INVALIDUSERIDS)
+        CHK_ERRA(COMADMIN_E_NOREGISTRYCLSID)
+        CHK_ERRA(COMADMIN_E_BADREGISTRYPROGID)
+        CHK_ERRA(COMADMIN_E_AUTHENTICATIONLEVEL)
+        CHK_ERRA(COMADMIN_E_USERPASSWDNOTVALID)
+        CHK_ERRA(COMADMIN_E_CLSIDORIIDMISMATCH)
+        CHK_ERRA(COMADMIN_E_REMOTEINTERFACE)
+        CHK_ERRA(COMADMIN_E_DLLREGISTERSERVER)
+        CHK_ERRA(COMADMIN_E_NOSERVERSHARE)
+        CHK_ERRA(COMADMIN_E_DLLLOADFAILED)
+        CHK_ERRA(COMADMIN_E_BADREGISTRYLIBID)
+        CHK_ERRA(COMADMIN_E_APPDIRNOTFOUND)
+        CHK_ERRA(COMADMIN_E_REGISTRARFAILED)
+        CHK_ERRA(COMADMIN_E_COMPFILE_DOESNOTEXIST)
+        CHK_ERRA(COMADMIN_E_COMPFILE_LOADDLLFAIL)
+        CHK_ERRA(COMADMIN_E_COMPFILE_GETCLASSOBJ)
+        CHK_ERRA(COMADMIN_E_COMPFILE_CLASSNOTAVAIL)
+        CHK_ERRA(COMADMIN_E_COMPFILE_BADTLB)
+        CHK_ERRA(COMADMIN_E_COMPFILE_NOTINSTALLABLE)
+        CHK_ERRA(COMADMIN_E_NOTCHANGEABLE)
+        CHK_ERRA(COMADMIN_E_NOTDELETEABLE)
+        CHK_ERRA(COMADMIN_E_SESSION)
+        CHK_ERRA(COMADMIN_E_COMP_MOVE_LOCKED)
+        CHK_ERRA(COMADMIN_E_COMP_MOVE_BAD_DEST)
+        CHK_ERRA(COMADMIN_E_REGISTERTLB)
+        CHK_ERRA(COMADMIN_E_SYSTEMAPP)
+        CHK_ERRA(COMADMIN_E_COMPFILE_NOREGISTRAR)
+        CHK_ERRA(COMADMIN_E_COREQCOMPINSTALLED)
+        CHK_ERRA(COMADMIN_E_SERVICENOTINSTALLED)
+        CHK_ERRA(COMADMIN_E_PROPERTYSAVEFAILED)
+        CHK_ERRA(COMADMIN_E_OBJECTEXISTS)
+        CHK_ERRA(COMADMIN_E_COMPONENTEXISTS)
+        CHK_ERRA(COMADMIN_E_REGFILE_CORRUPT)
+        CHK_ERRA(COMADMIN_E_PROPERTY_OVERFLOW)
+        CHK_ERRA(COMADMIN_E_NOTINREGISTRY)
+        CHK_ERRA(COMADMIN_E_OBJECTNOTPOOLABLE)
+        CHK_ERRA(COMADMIN_E_APPLID_MATCHES_CLSID)
+        CHK_ERRA(COMADMIN_E_ROLE_DOES_NOT_EXIST)
+        CHK_ERRA(COMADMIN_E_START_APP_NEEDS_COMPONENTS)
+        CHK_ERRA(COMADMIN_E_REQUIRES_DIFFERENT_PLATFORM)
+        CHK_ERRA(COMADMIN_E_CAN_NOT_EXPORT_APP_PROXY)
+        CHK_ERRA(COMADMIN_E_CAN_NOT_START_APP)
+        CHK_ERRA(COMADMIN_E_CAN_NOT_EXPORT_SYS_APP)
+        CHK_ERRA(COMADMIN_E_CANT_SUBSCRIBE_TO_COMPONENT)
+        CHK_ERRA(COMADMIN_E_EVENTCLASS_CANT_BE_SUBSCRIBER)
+        CHK_ERRA(COMADMIN_E_LIB_APP_PROXY_INCOMPATIBLE)
+        CHK_ERRA(COMADMIN_E_BASE_PARTITION_ONLY)
+        CHK_ERRA(COMADMIN_E_START_APP_DISABLED)
+        CHK_ERRA(COMADMIN_E_CAT_DUPLICATE_PARTITION_NAME)
+        CHK_ERRA(COMADMIN_E_CAT_INVALID_PARTITION_NAME)
+        CHK_ERRA(COMADMIN_E_CAT_PARTITION_IN_USE)
+        CHK_ERRA(COMADMIN_E_FILE_PARTITION_DUPLICATE_FILES)
+        CHK_ERRA(COMADMIN_E_CAT_IMPORTED_COMPONENTS_NOT_ALLOWED)
+        CHK_ERRA(COMADMIN_E_AMBIGUOUS_APPLICATION_NAME)
+        CHK_ERRA(COMADMIN_E_AMBIGUOUS_PARTITION_NAME)
+        CHK_ERRA(COMADMIN_E_REGDB_NOTINITIALIZED)
+        CHK_ERRA(COMADMIN_E_REGDB_NOTOPEN)
+        CHK_ERRA(COMADMIN_E_REGDB_SYSTEMERR)
+        CHK_ERRA(COMADMIN_E_REGDB_ALREADYRUNNING)
+        CHK_ERRA(COMADMIN_E_MIG_VERSIONNOTSUPPORTED)
+        CHK_ERRA(COMADMIN_E_MIG_SCHEMANOTFOUND)
+        CHK_ERRA(COMADMIN_E_CAT_BITNESSMISMATCH)
+        CHK_ERRA(COMADMIN_E_CAT_UNACCEPTABLEBITNESS)
+        CHK_ERRA(COMADMIN_E_CAT_WRONGAPPBITNESS)
+        CHK_ERRA(COMADMIN_E_CAT_PAUSE_RESUME_NOT_SUPPORTED)
+        CHK_ERRA(COMADMIN_E_CAT_SERVERFAULT)
+        CHK_ERRA(COMQC_E_APPLICATION_NOT_QUEUED)
+        CHK_ERRA(COMQC_E_NO_QUEUEABLE_INTERFACES)
+        CHK_ERRA(COMQC_E_QUEUING_SERVICE_NOT_AVAILABLE)
+        CHK_ERRA(COMQC_E_NO_IPERSISTSTREAM)
+        CHK_ERRA(COMQC_E_BAD_MESSAGE)
+        CHK_ERRA(COMQC_E_UNAUTHENTICATED)
+        CHK_ERRA(COMQC_E_UNTRUSTED_ENQUEUER)
+        CHK_ERRA(MSDTC_E_DUPLICATE_RESOURCE)
+        CHK_ERRA(COMADMIN_E_OBJECT_PARENT_MISSING)
+        CHK_ERRA(COMADMIN_E_OBJECT_DOES_NOT_EXIST)
+        CHK_ERRA(COMADMIN_E_APP_NOT_RUNNING)
+        CHK_ERRA(COMADMIN_E_INVALID_PARTITION)
+        CHK_ERRA(COMADMIN_E_SVCAPP_NOT_POOLABLE_OR_RECYCLABLE)
+        CHK_ERRA(COMADMIN_E_USER_IN_SET)
+        CHK_ERRA(COMADMIN_E_CANTRECYCLELIBRARYAPPS)
+        CHK_ERRA(COMADMIN_E_CANTRECYCLESERVICEAPPS)
+        CHK_ERRA(COMADMIN_E_PROCESSALREADYRECYCLED)
+        CHK_ERRA(COMADMIN_E_PAUSEDPROCESSMAYNOTBERECYCLED)
+        CHK_ERRA(COMADMIN_E_CANTMAKEINPROCSERVICE)
+        CHK_ERRA(COMADMIN_E_PROGIDINUSEBYCLSID)
+        CHK_ERRA(COMADMIN_E_DEFAULT_PARTITION_NOT_IN_SET)
+        CHK_ERRA(COMADMIN_E_RECYCLEDPROCESSMAYNOTBEPAUSED)
+        CHK_ERRA(COMADMIN_E_PARTITION_ACCESSDENIED)
+        CHK_ERRA(COMADMIN_E_PARTITION_MSI_ONLY)
+        CHK_ERRA(COMADMIN_E_LEGACYCOMPS_NOT_ALLOWED_IN_1_0_FORMAT)
+        CHK_ERRA(COMADMIN_E_LEGACYCOMPS_NOT_ALLOWED_IN_NONBASE_PARTITIONS)
+        CHK_ERRA(COMADMIN_E_COMP_MOVE_SOURCE)
+        CHK_ERRA(COMADMIN_E_COMP_MOVE_DEST)
+        CHK_ERRA(COMADMIN_E_COMP_MOVE_PRIVATE)
+        CHK_ERRA(COMADMIN_E_BASEPARTITION_REQUIRED_IN_SET)
+        CHK_ERRA(COMADMIN_E_CANNOT_ALIAS_EVENTCLASS)
+        CHK_ERRA(COMADMIN_E_PRIVATE_ACCESSDENIED)
+        CHK_ERRA(COMADMIN_E_SAFERINVALID)
+        CHK_ERRA(COMADMIN_E_REGISTRY_ACCESSDENIED)
+//        CHK_ERRA(COMADMIN_E_PARTITIONS_DISABLED)
+//        CHK_ERR_WIN32A(ERROR_EXE_CANNOT_MODIFY_SIGNED_BINARY)
+//        CHK_ERR_WIN32A(ERROR_EXE_CANNOT_MODIFY_STRONG_SIGNED_BINARY)
+        CHK_ERR_WIN32A(ERROR_DISK_TOO_FRAGMENTED)
+        CHK_ERR_WIN32A(ERROR_DELETE_PENDING)
+//        CHK_ERR_WIN32A(ERROR_SCOPE_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_NOT_SAFEBOOT_SERVICE)
+        CHK_ERR_WIN32A(ERROR_JOURNAL_ENTRY_DELETED)
+        CHK_ERR_WIN32A(ERROR_ONLY_IF_CONNECTED)
+        CHK_ERR_WIN32A(ERROR_OVERRIDE_NOCHANGES)
+        CHK_ERR_WIN32A(ERROR_BAD_USER_PROFILE)
+        CHK_ERR_WIN32A(ERROR_NOT_SUPPORTED_ON_SBS)
+        CHK_ERR_WIN32A(ERROR_SERVER_SHUTDOWN_IN_PROGRESS)
+        CHK_ERR_WIN32A(ERROR_HOST_DOWN)
+        CHK_ERR_WIN32A(ERROR_NON_ACCOUNT_SID)
+        CHK_ERR_WIN32A(ERROR_NON_DOMAIN_SID)
+        CHK_ERR_WIN32A(ERROR_APPHELP_BLOCK)
+        CHK_ERR_WIN32A(ERROR_ACCESS_DISABLED_BY_POLICY)
+        CHK_ERR_WIN32A(ERROR_REG_NAT_CONSUMPTION)
+        CHK_ERR_WIN32A(ERROR_CSCSHARE_OFFLINE)
+        CHK_ERR_WIN32A(ERROR_PKINIT_FAILURE)
+        CHK_ERR_WIN32A(ERROR_SMARTCARD_SUBSYSTEM_FAILURE)
+        CHK_ERR_WIN32A(ERROR_DOWNGRADE_DETECTED)
+        CHK_ERR_WIN32A(ERROR_MACHINE_LOCKED)
+        CHK_ERR_WIN32A(ERROR_CALLBACK_SUPPLIED_INVALID_DATA)
+        CHK_ERR_WIN32A(ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED)
+        CHK_ERR_WIN32A(ERROR_DRIVER_BLOCKED)
+        CHK_ERR_WIN32A(ERROR_INVALID_IMPORT_OF_NON_DLL)
+//        CHK_ERR_WIN32A(ERROR_ACCESS_DISABLED_WEBBLADE)
+//        CHK_ERR_WIN32A(ERROR_ACCESS_DISABLED_WEBBLADE_TAMPER)
+//        CHK_ERR_WIN32A(ERROR_RECOVERY_FAILURE)
+//        CHK_ERR_WIN32A(ERROR_ALREADY_FIBER)
+//        CHK_ERR_WIN32A(ERROR_ALREADY_THREAD)
+//        CHK_ERR_WIN32A(ERROR_STACK_BUFFER_OVERRUN)
+//        CHK_ERR_WIN32A(ERROR_PARAMETER_QUOTA_EXCEEDED)
+//        CHK_ERR_WIN32A(ERROR_DEBUGGER_INACTIVE)
+//        CHK_ERR_WIN32A(ERROR_DELAY_LOAD_FAILED)
+        CHK_ERR_WIN32A(ERROR_CURRENT_DOMAIN_NOT_ALLOWED)
+        CHK_ERR_WIN32A(ERROR_INSTALL_SERVICE_FAILURE)
+        CHK_ERR_WIN32A(ERROR_INSTALL_PACKAGE_VERSION)
+        CHK_ERR_WIN32A(ERROR_INSTALL_ALREADY_RUNNING)
+        CHK_ERR_WIN32A(ERROR_INSTALL_PACKAGE_OPEN_FAILED)
+        CHK_ERR_WIN32A(ERROR_INSTALL_PACKAGE_INVALID)
+        CHK_ERR_WIN32A(ERROR_INSTALL_UI_FAILURE)
+        CHK_ERR_WIN32A(ERROR_INSTALL_LOG_FAILURE)
+        CHK_ERR_WIN32A(ERROR_INSTALL_LANGUAGE_UNSUPPORTED)
+        CHK_ERR_WIN32A(ERROR_INSTALL_TRANSFORM_FAILURE)
+        CHK_ERR_WIN32A(ERROR_INSTALL_PACKAGE_REJECTED)
+        CHK_ERR_WIN32A(ERROR_FUNCTION_NOT_CALLED)
+        CHK_ERR_WIN32A(ERROR_FUNCTION_FAILED)
+        CHK_ERR_WIN32A(ERROR_INVALID_TABLE)
+        CHK_ERR_WIN32A(ERROR_DATATYPE_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_UNSUPPORTED_TYPE)
+        CHK_ERR_WIN32A(ERROR_CREATE_FAILED)
+        CHK_ERR_WIN32A(ERROR_INSTALL_TEMP_UNWRITABLE)
+        CHK_ERR_WIN32A(ERROR_INSTALL_PLATFORM_UNSUPPORTED)
+        CHK_ERR_WIN32A(ERROR_INSTALL_NOTUSED)
+        CHK_ERR_WIN32A(ERROR_PATCH_PACKAGE_OPEN_FAILED)
+        CHK_ERR_WIN32A(ERROR_PATCH_PACKAGE_INVALID)
+        CHK_ERR_WIN32A(ERROR_PATCH_PACKAGE_UNSUPPORTED)
+        CHK_ERR_WIN32A(ERROR_PRODUCT_VERSION)
+        CHK_ERR_WIN32A(ERROR_INVALID_COMMAND_LINE)
+        CHK_ERR_WIN32A(ERROR_INSTALL_REMOTE_DISALLOWED)
+        CHK_ERR_WIN32A(ERROR_SUCCESS_REBOOT_INITIATED)
+        CHK_ERR_WIN32A(ERROR_PATCH_TARGET_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_PATCH_PACKAGE_REJECTED)
+        CHK_ERR_WIN32A(ERROR_INSTALL_TRANSFORM_REJECTED)
+//        CHK_ERR_WIN32A(ERROR_INSTALL_REMOTE_PROHIBITED)
+        CHK_ERR_WIN32A(RPC_S_ENTRY_TYPE_MISMATCH)
+        CHK_ERR_WIN32A(RPC_S_NOT_ALL_OBJS_EXPORTED)
+        CHK_ERR_WIN32A(RPC_S_INTERFACE_NOT_EXPORTED)
+        CHK_ERR_WIN32A(RPC_S_PROFILE_NOT_ADDED)
+        CHK_ERR_WIN32A(RPC_S_PRF_ELT_NOT_ADDED)
+        CHK_ERR_WIN32A(RPC_S_PRF_ELT_NOT_REMOVED)
+        CHK_ERR_WIN32A(RPC_S_GRP_ELT_NOT_ADDED)
+        CHK_ERR_WIN32A(RPC_S_GRP_ELT_NOT_REMOVED)
+        CHK_ERR_WIN32A(ERROR_KM_DRIVER_BLOCKED)
+        CHK_ERR_WIN32A(ERROR_CONTEXT_EXPIRED)
+//        CHK_ERR_WIN32A(ERROR_PER_USER_TRUST_QUOTA_EXCEEDED)
+//        CHK_ERR_WIN32A(ERROR_ALL_USER_TRUST_QUOTA_EXCEEDED)
+//        CHK_ERR_WIN32A(ERROR_USER_DELETE_TRUST_QUOTA_EXCEEDED)
+        CHK_ERR_WIN32A(ERROR_CONNECTED_OTHER_PASSWORD_DEFAULT)
+        CHK_ERR_WIN32A(ERROR_PRINTER_DRIVER_WARNED)
+        CHK_ERR_WIN32A(ERROR_PRINTER_DRIVER_BLOCKED)
+        CHK_ERR_WIN32A(ERROR_VOLUME_CONTAINS_SYS_FILES)
+        CHK_ERR_WIN32A(ERROR_INDIGENOUS_TYPE)
+        CHK_ERR_WIN32A(ERROR_NO_SUPPORTING_DRIVES)
+        CHK_ERR_WIN32A(ERROR_CLEANER_CARTRIDGE_INSTALLED)
+        CHK_ERR_WIN32A(ERROR_REPARSE_TAG_INVALID)
+        CHK_ERR_WIN32A(ERROR_REPARSE_TAG_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_VOLUME_NOT_SIS_ENABLED)
+        CHK_ERR_WIN32A(ERROR_QUORUM_OWNER_ALIVE)
+        CHK_ERR_WIN32A(ERROR_NETWORK_NOT_AVAILABLE)
+        CHK_ERR_WIN32A(ERROR_NODE_NOT_AVAILABLE)
+        CHK_ERR_WIN32A(ERROR_ALL_NODES_NOT_AVAILABLE)
+        CHK_ERR_WIN32A(ERROR_RESOURCE_FAILED)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_INVALID_NODE)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_EXISTS)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_JOIN_IN_PROGRESS)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_LOCAL_NODE_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NETWORK_EXISTS)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NETWORK_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NETINTERFACE_EXISTS)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NETINTERFACE_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_INVALID_REQUEST)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_INVALID_NETWORK_PROVIDER)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_DOWN)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_UNREACHABLE)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_NOT_MEMBER)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_JOIN_NOT_IN_PROGRESS)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_INVALID_NETWORK)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_UP)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_IPADDR_IN_USE)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_NOT_PAUSED)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NO_SECURITY_CONTEXT)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NETWORK_NOT_INTERNAL)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_ALREADY_UP)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_ALREADY_DOWN)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NETWORK_ALREADY_ONLINE)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NETWORK_ALREADY_OFFLINE)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_ALREADY_MEMBER)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_LAST_INTERNAL_NETWORK)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NETWORK_HAS_DEPENDENTS)
+        CHK_ERR_WIN32A(ERROR_INVALID_OPERATION_ON_QUORUM)
+        CHK_ERR_WIN32A(ERROR_DEPENDENCY_NOT_ALLOWED)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_PAUSED)
+        CHK_ERR_WIN32A(ERROR_NODE_CANT_HOST_RESOURCE)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_NOT_READY)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_SHUTTING_DOWN)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_JOIN_ABORTED)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_INCOMPATIBLE_VERSIONS)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_MAXNUM_OF_RESOURCES_EXCEEDED)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_SYSTEM_CONFIG_CHANGED)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_RESOURCE_TYPE_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_RESTYPE_NOT_SUPPORTED)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_RESNAME_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NO_RPC_PACKAGES_REGISTERED)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_OWNER_NOT_IN_PREFLIST)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_DATABASE_SEQMISMATCH)
+        CHK_ERR_WIN32A(ERROR_RESMON_INVALID_STATE)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_GUM_NOT_LOCKER)
+        CHK_ERR_WIN32A(ERROR_QUORUM_DISK_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_DATABASE_BACKUP_CORRUPT)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NODE_ALREADY_HAS_DFS_ROOT)
+        CHK_ERR_WIN32A(ERROR_RESOURCE_PROPERTY_UNCHANGEABLE)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_MEMBERSHIP_INVALID_STATE)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_QUORUMLOG_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_MEMBERSHIP_HALT)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_INSTANCE_ID_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_NETWORK_NOT_FOUND_FOR_IP)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_PROPERTY_DATA_TYPE_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_EVICT_WITHOUT_CLEANUP)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_PARAMETER_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_NODE_CANNOT_BE_CLUSTERED)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_WRONG_OS_VERSION)
+        CHK_ERR_WIN32A(ERROR_CLUSTER_CANT_CREATE_DUP_CLUSTER_NAME)
+//        CHK_ERR_WIN32A(ERROR_CLUSCFG_ALREADY_COMMITTED)
+//        CHK_ERR_WIN32A(ERROR_CLUSCFG_ROLLBACK_FAILED)
+//        CHK_ERR_WIN32A(ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT)
+//        CHK_ERR_WIN32A(ERROR_CLUSTER_OLD_VERSION)
+//        CHK_ERR_WIN32A(ERROR_CLUSTER_MISMATCHED_COMPUTER_ACCT_NAME)
+        CHK_ERR_WIN32A(ERROR_FILE_READ_ONLY)
+        CHK_ERR_WIN32A(ERROR_DIR_EFS_DISALLOWED)
+        CHK_ERR_WIN32A(ERROR_EFS_SERVER_NOT_TRUSTED)
+        CHK_ERR_WIN32A(ERROR_BAD_RECOVERY_POLICY)
+        CHK_ERR_WIN32A(ERROR_EFS_ALG_BLOB_TOO_BIG)
+        CHK_ERR_WIN32A(ERROR_VOLUME_NOT_SUPPORT_EFS)
+        CHK_ERR_WIN32A(ERROR_EFS_DISABLED)
+        CHK_ERR_WIN32A(ERROR_EFS_VERSION_NOT_SUPPORT)
+        CHK_ERR_WIN32A(SCHED_E_SERVICE_NOT_LOCALSYSTEM)
+        CHK_ERR_WIN32A(ERROR_CTX_CLIENT_LICENSE_IN_USE)
+        CHK_ERR_WIN32A(ERROR_CTX_CLIENT_LICENSE_NOT_SET)
+        CHK_ERR_WIN32A(ERROR_CTX_LICENSE_NOT_AVAILABLE)
+        CHK_ERR_WIN32A(ERROR_CTX_LICENSE_CLIENT_INVALID)
+        CHK_ERR_WIN32A(ERROR_CTX_LICENSE_EXPIRED)
+        CHK_ERR_WIN32A(ERROR_CTX_SHADOW_NOT_RUNNING)
+        CHK_ERR_WIN32A(ERROR_CTX_SHADOW_ENDED_BY_MODE_CHANGE)
+//        CHK_ERR_WIN32A(ERROR_ACTIVATION_COUNT_EXCEEDED)
+        CHK_ERR_WIN32A(ERROR_DS_SORT_CONTROL_MISSING)
+        CHK_ERR_WIN32A(ERROR_DS_OFFSET_RANGE_ERROR)
+        CHK_ERR_WIN32A(ERROR_DS_OBJECT_BEING_REMOVED)
+        CHK_ERR_WIN32A(ERROR_DS_DS_REQUIRED)
+        CHK_ERR_WIN32A(ERROR_DS_INVALID_LDAP_DISPLAY_NAME)
+        CHK_ERR_WIN32A(ERROR_DS_NON_BASE_SEARCH)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_RETRIEVE_ATTS)
+        CHK_ERR_WIN32A(ERROR_DS_BACKLINK_WITHOUT_LINK)
+        CHK_ERR_WIN32A(ERROR_DS_EPOCH_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_DS_SRC_NAME_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_DS_SRC_AND_DST_NC_IDENTICAL)
+        CHK_ERR_WIN32A(ERROR_DS_DST_NC_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC)
+        CHK_ERR_WIN32A(ERROR_DS_SRC_GUID_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_MOVE_DELETED_OBJECT)
+        CHK_ERR_WIN32A(ERROR_DS_PDC_OPERATION_IN_PROGRESS)
+        CHK_ERR_WIN32A(ERROR_DS_CROSS_DOMAIN_CLEANUP_REQD)
+        CHK_ERR_WIN32A(ERROR_DS_ILLEGAL_XDOM_MOVE_OPERATION)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_WITH_ACCT_GROUP_MEMBERSHPS)
+        CHK_ERR_WIN32A(ERROR_DS_NC_MUST_HAVE_NC_PARENT)
+        CHK_ERR_WIN32A(ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE)
+        CHK_ERR_WIN32A(ERROR_DS_DST_DOMAIN_NOT_NATIVE)
+        CHK_ERR_WIN32A(ERROR_DS_MISSING_INFRASTRUCTURE_CONTAINER)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_MOVE_ACCOUNT_GROUP)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_MOVE_RESOURCE_GROUP)
+        CHK_ERR_WIN32A(ERROR_DS_INVALID_SEARCH_FLAG)
+        CHK_ERR_WIN32A(ERROR_DS_NO_TREE_DELETE_ABOVE_NC)
+        CHK_ERR_WIN32A(ERROR_DS_COULDNT_LOCK_TREE_FOR_DELETE)
+        CHK_ERR_WIN32A(ERROR_DS_COULDNT_IDENTIFY_OBJECTS_FOR_TREE_DELETE)
+        CHK_ERR_WIN32A(ERROR_DS_SAM_INIT_FAILURE)
+        CHK_ERR_WIN32A(ERROR_DS_SENSITIVE_GROUP_VIOLATION)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_MOD_PRIMARYGROUPID)
+        CHK_ERR_WIN32A(ERROR_DS_ILLEGAL_BASE_SCHEMA_MOD)
+        CHK_ERR_WIN32A(ERROR_DS_NONSAFE_SCHEMA_CHANGE)
+        CHK_ERR_WIN32A(ERROR_DS_SCHEMA_UPDATE_DISALLOWED)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_CREATE_UNDER_SCHEMA)
+        CHK_ERR_WIN32A(ERROR_DS_INSTALL_NO_SRC_SCH_VERSION)
+        CHK_ERR_WIN32A(ERROR_DS_INSTALL_NO_SCH_VERSION_IN_INIFILE)
+        CHK_ERR_WIN32A(ERROR_DS_INVALID_GROUP_TYPE)
+        CHK_ERR_WIN32A(ERROR_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN)
+        CHK_ERR_WIN32A(ERROR_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN)
+        CHK_ERR_WIN32A(ERROR_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER)
+        CHK_ERR_WIN32A(ERROR_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER)
+        CHK_ERR_WIN32A(ERROR_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER)
+        CHK_ERR_WIN32A(ERROR_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER)
+        CHK_ERR_WIN32A(ERROR_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER)
+        CHK_ERR_WIN32A(ERROR_DS_HAVE_PRIMARY_MEMBERS)
+        CHK_ERR_WIN32A(ERROR_DS_STRING_SD_CONVERSION_FAILED)
+        CHK_ERR_WIN32A(ERROR_DS_NAMING_MASTER_GC)
+        CHK_ERR_WIN32A(ERROR_DS_DNS_LOOKUP_FAILURE)
+        CHK_ERR_WIN32A(ERROR_DS_COULDNT_UPDATE_SPNS)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_RETRIEVE_SD)
+        CHK_ERR_WIN32A(ERROR_DS_KEY_NOT_UNIQUE)
+        CHK_ERR_WIN32A(ERROR_DS_WRONG_LINKED_ATT_SYNTAX)
+        CHK_ERR_WIN32A(ERROR_DS_SAM_NEED_BOOTKEY_PASSWORD)
+        CHK_ERR_WIN32A(ERROR_DS_SAM_NEED_BOOTKEY_FLOPPY)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_START)
+        CHK_ERR_WIN32A(ERROR_DS_INIT_FAILURE)
+        CHK_ERR_WIN32A(ERROR_DS_NO_PKT_PRIVACY_ON_CONNECTION)
+        CHK_ERR_WIN32A(ERROR_DS_SOURCE_DOMAIN_IN_FOREST)
+        CHK_ERR_WIN32A(ERROR_DS_DESTINATION_DOMAIN_NOT_IN_FOREST)
+        CHK_ERR_WIN32A(ERROR_DS_DESTINATION_AUDITING_NOT_ENABLED)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_FIND_DC_FOR_SRC_DOMAIN)
+        CHK_ERR_WIN32A(ERROR_DS_SRC_OBJ_NOT_GROUP_OR_USER)
+        CHK_ERR_WIN32A(ERROR_DS_SRC_SID_EXISTS_IN_FOREST)
+        CHK_ERR_WIN32A(ERROR_DS_SRC_AND_DST_OBJECT_CLASS_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_SAM_INIT_FAILURE)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_SCHEMA_INFO_SHIP)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_SCHEMA_CONFLICT)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_EARLIER_SCHEMA_CONFLICT)
+        CHK_ERR_WIN32A(ERROR_DS_DRA_OBJ_NC_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_DS_NC_STILL_HAS_DSAS)
+        CHK_ERR_WIN32A(ERROR_DS_GC_REQUIRED)
+        CHK_ERR_WIN32A(ERROR_DS_LOCAL_MEMBER_OF_LOCAL_ONLY)
+        CHK_ERR_WIN32A(ERROR_DS_NO_FPO_IN_UNIVERSAL_GROUPS)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_ADD_TO_GC)
+        CHK_ERR_WIN32A(ERROR_DS_NO_CHECKPOINT_WITH_PDC)
+        CHK_ERR_WIN32A(ERROR_DS_SOURCE_AUDITING_NOT_ENABLED)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_CREATE_IN_NONDOMAIN_NC)
+        CHK_ERR_WIN32A(ERROR_DS_INVALID_NAME_FOR_SPN)
+        CHK_ERR_WIN32A(ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS)
+        CHK_ERR_WIN32A(ERROR_DS_UNICODEPWD_NOT_IN_QUOTES)
+        CHK_ERR_WIN32A(ERROR_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED)
+        CHK_ERR_WIN32A(ERROR_DS_MUST_BE_RUN_ON_DST_DC)
+        CHK_ERR_WIN32A(ERROR_DS_SRC_DC_MUST_BE_SP4_OR_GREATER)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_TREE_DELETE_CRITICAL_OBJ)
+        CHK_ERR_WIN32A(ERROR_DS_INIT_FAILURE_CONSOLE)
+        CHK_ERR_WIN32A(ERROR_DS_SAM_INIT_FAILURE_CONSOLE)
+        CHK_ERR_WIN32A(ERROR_DS_FOREST_VERSION_TOO_HIGH)
+        CHK_ERR_WIN32A(ERROR_DS_DOMAIN_VERSION_TOO_HIGH)
+        CHK_ERR_WIN32A(ERROR_DS_FOREST_VERSION_TOO_LOW)
+        CHK_ERR_WIN32A(ERROR_DS_DOMAIN_VERSION_TOO_LOW)
+        CHK_ERR_WIN32A(ERROR_DS_INCOMPATIBLE_VERSION)
+        CHK_ERR_WIN32A(ERROR_DS_LOW_DSA_VERSION)
+        CHK_ERR_WIN32A(ERROR_DS_NO_BEHAVIOR_VERSION_IN_MIXEDDOMAIN)
+        CHK_ERR_WIN32A(ERROR_DS_NOT_SUPPORTED_SORT_ORDER)
+        CHK_ERR_WIN32A(ERROR_DS_NAME_NOT_UNIQUE)
+        CHK_ERR_WIN32A(ERROR_DS_MACHINE_ACCOUNT_CREATED_PRENT4)
+        CHK_ERR_WIN32A(ERROR_DS_OUT_OF_VERSION_STORE)
+        CHK_ERR_WIN32A(ERROR_DS_INCOMPATIBLE_CONTROLS_USED)
+        CHK_ERR_WIN32A(ERROR_DS_NO_REF_DOMAIN)
+        CHK_ERR_WIN32A(ERROR_DS_RESERVED_LINK_ID)
+        CHK_ERR_WIN32A(ERROR_DS_LINK_ID_NOT_AVAILABLE)
+        CHK_ERR_WIN32A(ERROR_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER)
+        CHK_ERR_WIN32A(ERROR_DS_MODIFYDN_DISALLOWED_BY_INSTANCE_TYPE)
+        CHK_ERR_WIN32A(ERROR_DS_NO_OBJECT_MOVE_IN_SCHEMA_NC)
+        CHK_ERR_WIN32A(ERROR_DS_MODIFYDN_DISALLOWED_BY_FLAG)
+        CHK_ERR_WIN32A(ERROR_DS_MODIFYDN_WRONG_GRANDPARENT)
+        CHK_ERR_WIN32A(ERROR_DS_NAME_ERROR_TRUST_REFERRAL)
+        CHK_ERR_WIN32A(ERROR_NOT_SUPPORTED_ON_STANDARD_SERVER)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_ACCESS_REMOTE_PART_OF_AD)
+        CHK_ERR_WIN32A(ERROR_DS_CR_IMPOSSIBLE_TO_VALIDATE_V2)
+        CHK_ERR_WIN32A(ERROR_DS_THREAD_LIMIT_EXCEEDED)
+        CHK_ERR_WIN32A(ERROR_DS_NOT_CLOSEST)
+        CHK_ERR_WIN32A(ERROR_DS_CANT_DERIVE_SPN_WITHOUT_SERVER_REF)
+        CHK_ERR_WIN32A(ERROR_DS_SINGLE_USER_MODE_FAILED)
+        CHK_ERR_WIN32A(ERROR_DS_NTDSCRIPT_SYNTAX_ERROR)
+        CHK_ERR_WIN32A(ERROR_DS_NTDSCRIPT_PROCESS_ERROR)
+        CHK_ERR_WIN32A(ERROR_DS_DIFFERENT_REPL_EPOCHS)
+        CHK_ERR_WIN32A(ERROR_DS_DRS_EXTENSIONS_CHANGED)
+        CHK_ERR_WIN32A(ERROR_DS_REPLICA_SET_CHANGE_NOT_ALLOWED_ON_DISABLED_CR)
+        CHK_ERR_WIN32A(ERROR_DS_NO_MSDS_INTID)
+        CHK_ERR_WIN32A(ERROR_DS_DUP_MSDS_INTID)
+        CHK_ERR_WIN32A(ERROR_DS_EXISTS_IN_RDNATTID)
+        CHK_ERR_WIN32A(ERROR_DS_AUTHORIZATION_FAILED)
+        CHK_ERR_WIN32A(ERROR_DS_INVALID_SCRIPT)
+        CHK_ERR_WIN32A(ERROR_DS_REMOTE_CROSSREF_OP_FAILED)
+//        CHK_ERR_WIN32A(ERROR_DS_CROSS_REF_BUSY)
+//        CHK_ERR_WIN32A(ERROR_DS_CANT_DERIVE_SPN_FOR_DELETED_DOMAIN)
+//        CHK_ERR_WIN32A(ERROR_DS_CANT_DEMOTE_WITH_WRITEABLE_NC)
+//        CHK_ERR_WIN32A(ERROR_DS_DUPLICATE_ID_FOUND)
+//        CHK_ERR_WIN32A(ERROR_DS_INSUFFICIENT_ATTR_TO_CREATE_OBJECT)
+//        CHK_ERR_WIN32A(ERROR_DS_GROUP_CONVERSION_ERROR)
+//        CHK_ERR_WIN32A(ERROR_DS_CANT_MOVE_APP_BASIC_GROUP)
+//        CHK_ERR_WIN32A(ERROR_DS_CANT_MOVE_APP_QUERY_GROUP)
+//        CHK_ERR_WIN32A(ERROR_DS_ROLE_NOT_VERIFIED)
+//        CHK_ERR_WIN32A(ERROR_DS_WKO_CONTAINER_CANNOT_BE_SPECIAL)
+//        CHK_ERR_WIN32A(ERROR_DS_DOMAIN_RENAME_IN_PROGRESS)
+//        CHK_ERR_WIN32A(ERROR_DS_EXISTING_AD_CHILD_NC)
+//        CHK_ERR_WIN32A(DNS_ERROR_INVALID_NAME_CHAR)
+//        CHK_ERR_WIN32A(DNS_ERROR_NUMERIC_NAME)
+//        CHK_ERR_WIN32A(DNS_ERROR_NOT_ALLOWED_ON_ROOT_SERVER)
+//        CHK_ERR_WIN32A(DNS_ERROR_NOT_ALLOWED_UNDER_DELEGATION)
+//        CHK_ERR_WIN32A(DNS_ERROR_CANNOT_FIND_ROOT_HINTS)
+//        CHK_ERR_WIN32A(DNS_ERROR_INCONSISTENT_ROOT_HINTS)
+        CHK_ERR_WIN32A(DNS_ERROR_FORWARDER_ALREADY_EXISTS)
+        CHK_ERR_WIN32A(DNS_ERROR_ZONE_REQUIRES_MASTER_IP)
+        CHK_ERR_WIN32A(DNS_ERROR_ZONE_IS_SHUTDOWN)
+        CHK_ERR_WIN32A(DNS_ERROR_DP_BASE)
+        CHK_ERR_WIN32A(DNS_ERROR_DP_DOES_NOT_EXIST)
+        CHK_ERR_WIN32A(DNS_ERROR_DP_ALREADY_EXISTS)
+        CHK_ERR_WIN32A(DNS_ERROR_DP_NOT_ENLISTED)
+        CHK_ERR_WIN32A(DNS_ERROR_DP_ALREADY_ENLISTED)
+//        CHK_ERR_WIN32A(DNS_ERROR_DP_NOT_AVAILABLE)
+        CHK_ERR_WIN32A(WSA_QOS_ESERVICETYPE)
+        CHK_ERR_WIN32A(WSA_QOS_EFLOWSPEC)
+        CHK_ERR_WIN32A(WSA_QOS_EPROVSPECBUF)
+        CHK_ERR_WIN32A(WSA_QOS_EFILTERSTYLE)
+        CHK_ERR_WIN32A(WSA_QOS_EFILTERTYPE)
+        CHK_ERR_WIN32A(WSA_QOS_EFILTERCOUNT)
+        CHK_ERR_WIN32A(WSA_QOS_EOBJLENGTH)
+        CHK_ERR_WIN32A(WSA_QOS_EFLOWCOUNT)
+        CHK_ERR_WIN32A(WSA_QOS_EUNKOWNPSOBJ)
+        CHK_ERR_WIN32A(WSA_QOS_EPOLICYOBJ)
+        CHK_ERR_WIN32A(WSA_QOS_EFLOWDESC)
+        CHK_ERR_WIN32A(WSA_QOS_EPSFLOWSPEC)
+        CHK_ERR_WIN32A(WSA_QOS_EPSFILTERSPEC)
+        CHK_ERR_WIN32A(WSA_QOS_ESDMODEOBJ)
+        CHK_ERR_WIN32A(WSA_QOS_ESHAPERATEOBJ)
+        CHK_ERR_WIN32A(WSA_QOS_RESERVED_PETYPE)
+        CHK_ERR_WIN32A(ERROR_SXS_SECTION_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_SXS_CANT_GEN_ACTCTX)
+        CHK_ERR_WIN32A(ERROR_SXS_INVALID_ACTCTXDATA_FORMAT)
+        CHK_ERR_WIN32A(ERROR_SXS_ASSEMBLY_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_SXS_MANIFEST_FORMAT_ERROR)
+        CHK_ERR_WIN32A(ERROR_SXS_MANIFEST_PARSE_ERROR)
+        CHK_ERR_WIN32A(ERROR_SXS_ACTIVATION_CONTEXT_DISABLED)
+        CHK_ERR_WIN32A(ERROR_SXS_KEY_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_SXS_VERSION_CONFLICT)
+        CHK_ERR_WIN32A(ERROR_SXS_WRONG_SECTION_TYPE)
+        CHK_ERR_WIN32A(ERROR_SXS_THREAD_QUERIES_DISABLED)
+        CHK_ERR_WIN32A(ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET)
+        CHK_ERR_WIN32A(ERROR_SXS_UNKNOWN_ENCODING_GROUP)
+        CHK_ERR_WIN32A(ERROR_SXS_UNKNOWN_ENCODING)
+        CHK_ERR_WIN32A(ERROR_SXS_INVALID_XML_NAMESPACE_URI)
+        CHK_ERR_WIN32A(ERROR_SXS_ROOT_MANIFEST_DEPENDENCY_NOT_INSTALLED)
+        CHK_ERR_WIN32A(ERROR_SXS_LEAF_MANIFEST_DEPENDENCY_NOT_INSTALLED)
+        CHK_ERR_WIN32A(ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE)
+        CHK_ERR_WIN32A(ERROR_SXS_MANIFEST_MISSING_REQUIRED_DEFAULT_NAMESPACE)
+        CHK_ERR_WIN32A(ERROR_SXS_MANIFEST_INVALID_REQUIRED_DEFAULT_NAMESPACE)
+        CHK_ERR_WIN32A(ERROR_SXS_PRIVATE_MANIFEST_CROSS_PATH_WITH_REPARSE_POINT)
+        CHK_ERR_WIN32A(ERROR_SXS_DUPLICATE_DLL_NAME)
+        CHK_ERR_WIN32A(ERROR_SXS_DUPLICATE_WINDOWCLASS_NAME)
+        CHK_ERR_WIN32A(ERROR_SXS_DUPLICATE_CLSID)
+        CHK_ERR_WIN32A(ERROR_SXS_DUPLICATE_IID)
+        CHK_ERR_WIN32A(ERROR_SXS_DUPLICATE_TLBID)
+        CHK_ERR_WIN32A(ERROR_SXS_DUPLICATE_PROGID)
+        CHK_ERR_WIN32A(ERROR_SXS_DUPLICATE_ASSEMBLY_NAME)
+        CHK_ERR_WIN32A(ERROR_SXS_FILE_HASH_MISMATCH)
+        CHK_ERR_WIN32A(ERROR_SXS_POLICY_PARSE_ERROR)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_MISSINGQUOTE)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_COMMENTSYNTAX)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_BADSTARTNAMECHAR)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_BADNAMECHAR)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_BADCHARINSTRING)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_XMLDECLSYNTAX)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_BADCHARDATA)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_MISSINGWHITESPACE)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_EXPECTINGTAGEND)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_MISSINGSEMICOLON)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNBALANCEDPAREN)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_INTERNALERROR)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNEXPECTED_WHITESPACE)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_INCOMPLETE_ENCODING)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_MISSING_PAREN)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_EXPECTINGCLOSEQUOTE)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_MULTIPLE_COLONS)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_INVALID_DECIMAL)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_INVALID_HEXIDECIMAL)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_INVALID_UNICODE)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_WHITESPACEORQUESTIONMARK)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNEXPECTEDENDTAG)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNCLOSEDTAG)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_DUPLICATEATTRIBUTE)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_MULTIPLEROOTS)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_INVALIDATROOTLEVEL)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_BADXMLDECL)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_MISSINGROOT)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNEXPECTEDEOF)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_BADPEREFINSUBSET)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNCLOSEDSTARTTAG)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNCLOSEDENDTAG)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNCLOSEDSTRING)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNCLOSEDCOMMENT)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNCLOSEDDECL)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNCLOSEDCDATA)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_RESERVEDNAMESPACE)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_INVALIDENCODING)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_INVALIDSWITCH)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_BADXMLCASE)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_INVALID_STANDALONE)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_UNEXPECTED_STANDALONE)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_INVALID_VERSION)
+        CHK_ERR_WIN32A(ERROR_SXS_XML_E_MISSINGEQUALS)
+        CHK_ERR_WIN32A(ERROR_SXS_PROTECTION_RECOVERY_FAILED)
+        CHK_ERR_WIN32A(ERROR_SXS_PROTECTION_PUBLIC_KEY_TOO_SHORT)
+        CHK_ERR_WIN32A(ERROR_SXS_PROTECTION_CATALOG_NOT_VALID)
+        CHK_ERR_WIN32A(ERROR_SXS_UNTRANSLATABLE_HRESULT)
+        CHK_ERR_WIN32A(ERROR_SXS_PROTECTION_CATALOG_FILE_MISSING)
+        CHK_ERR_WIN32A(ERROR_SXS_MISSING_ASSEMBLY_IDENTITY_ATTRIBUTE)
+        CHK_ERR_WIN32A(ERROR_SXS_INVALID_ASSEMBLY_IDENTITY_ATTRIBUTE_NAME)
+        CHK_ERR_WIN32A(ERROR_IPSEC_QM_POLICY_EXISTS)
+        CHK_ERR_WIN32A(ERROR_IPSEC_QM_POLICY_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_IPSEC_QM_POLICY_IN_USE)
+        CHK_ERR_WIN32A(ERROR_IPSEC_MM_POLICY_EXISTS)
+        CHK_ERR_WIN32A(ERROR_IPSEC_MM_POLICY_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_IPSEC_MM_POLICY_IN_USE)
+        CHK_ERR_WIN32A(ERROR_IPSEC_MM_FILTER_EXISTS)
+        CHK_ERR_WIN32A(ERROR_IPSEC_MM_FILTER_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_IPSEC_TRANSPORT_FILTER_EXISTS)
+        CHK_ERR_WIN32A(ERROR_IPSEC_TRANSPORT_FILTER_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_IPSEC_MM_AUTH_EXISTS)
+        CHK_ERR_WIN32A(ERROR_IPSEC_MM_AUTH_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_IPSEC_MM_AUTH_IN_USE)
+        CHK_ERR_WIN32A(ERROR_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_IPSEC_TUNNEL_FILTER_EXISTS)
+        CHK_ERR_WIN32A(ERROR_IPSEC_TUNNEL_FILTER_NOT_FOUND)
+        CHK_ERR_WIN32A(ERROR_IPSEC_MM_FILTER_PENDING_DELETION)
+        CHK_ERR_WIN32A(ERROR_IPSEC_TRANSPORT_FILTER_PENDING_DELETION)
+        CHK_ERR_WIN32A(ERROR_IPSEC_TUNNEL_FILTER_PENDING_DELETION)
+        CHK_ERR_WIN32A(ERROR_IPSEC_MM_POLICY_PENDING_DELETION)
+        CHK_ERR_WIN32A(ERROR_IPSEC_MM_AUTH_PENDING_DELETION)
+        CHK_ERR_WIN32A(ERROR_IPSEC_QM_POLICY_PENDING_DELETION)
+//        CHK_ERR_WIN32A(WARNING_IPSEC_MM_POLICY_PRUNED)
+//        CHK_ERR_WIN32A(WARNING_IPSEC_QM_POLICY_PRUNED)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NEG_STATUS_BEGIN)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_AUTH_FAIL)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_ATTRIB_FAIL)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NEGOTIATION_PENDING)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_GENERAL_PROCESSING_ERROR)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_TIMED_OUT)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NO_CERT)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_SA_DELETED)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_SA_REAPED)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_MM_ACQUIRE_DROP)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_QM_ACQUIRE_DROP)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_QUEUE_DROP_MM)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_QUEUE_DROP_NO_MM)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_DROP_NO_RESPONSE)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_MM_DELAY_DROP)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_QM_DELAY_DROP)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_ERROR)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_CRL_FAILED)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_KEY_USAGE)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_CERT_TYPE)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NO_PRIVATE_KEY)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_DH_FAIL)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_HEADER)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NO_POLICY)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_SIGNATURE)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_KERBEROS_ERROR)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NO_PUBLIC_KEY)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_SA)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_PROP)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_TRANS)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_KE)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_ID)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_CERT)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_CERT_REQ)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_HASH)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_SIG)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_NONCE)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_NOTIFY)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_DELETE)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PROCESS_ERR_VENDOR)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_PAYLOAD)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_LOAD_SOFT_SA)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_SOFT_SA_TORN_DOWN)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_COOKIE)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NO_PEER_CERT)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_PEER_CRL_FAILED)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_POLICY_CHANGE)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NO_MM_POLICY)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NOTCBPRIV)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_SECLOADFAIL)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_FAILSSPINIT)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_FAILQUERYSSP)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_SRVACQFAIL)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_SRVQUERYCRED)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_GETSPIFAIL)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_FILTER)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_OUT_OF_MEMORY)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_ADD_UPDATE_KEY_FAILED)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_POLICY)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_UNKNOWN_DOI)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_SITUATION)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_DH_FAILURE)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_GROUP)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_ENCRYPT)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_DECRYPT)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_POLICY_MATCH)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_UNSUPPORTED_ID)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_HASH)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_HASH_ALG)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_HASH_SIZE)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_ENCRYPT_ALG)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_AUTH_ALG)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_SIG)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_LOAD_FAILED)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_RPC_DELETE)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_BENIGN_REINIT)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_RESPONDER_LIFETIME_NOTIFY)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_INVALID_CERT_KEYLEN)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_MM_LIMIT)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NEGOTIATION_DISABLED)
+        CHK_ERR_WIN32A(ERROR_IPSEC_IKE_NEG_STATUS_END)
+
+#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)
+
+// -------------------------------------------------------------
+// ddraw.h error codes
+// -------------------------------------------------------------
+        CHK_ERRA(DDERR_ALREADYINITIALIZED)
+        CHK_ERRA(DDERR_CANNOTATTACHSURFACE)
+        CHK_ERRA(DDERR_CANNOTDETACHSURFACE)
+        CHK_ERRA(DDERR_CURRENTLYNOTAVAIL)
+        CHK_ERRA(DDERR_EXCEPTION)
+//      CHK_ERRA(DDERR_GENERIC)
+        CHK_ERRA(DDERR_HEIGHTALIGN)
+        CHK_ERRA(DDERR_INCOMPATIBLEPRIMARY)
+        CHK_ERRA(DDERR_INVALIDCAPS)
+        CHK_ERRA(DDERR_INVALIDCLIPLIST)
+        CHK_ERRA(DDERR_INVALIDMODE)
+        CHK_ERRA(DDERR_INVALIDOBJECT)
+//        CHK_ERRA(DDERR_INVALIDPARAMS)
+        CHK_ERRA(DDERR_INVALIDPIXELFORMAT)
+        CHK_ERRA(DDERR_INVALIDRECT)
+        CHK_ERRA(DDERR_LOCKEDSURFACES)
+        CHK_ERRA(DDERR_NO3D)
+        CHK_ERRA(DDERR_NOALPHAHW)
+        CHK_ERRA(DDERR_NOSTEREOHARDWARE)
+        CHK_ERRA(DDERR_NOSURFACELEFT)
+        CHK_ERRA(DDERR_NOCLIPLIST)
+        CHK_ERRA(DDERR_NOCOLORCONVHW)
+        CHK_ERRA(DDERR_NOCOOPERATIVELEVELSET)
+        CHK_ERRA(DDERR_NOCOLORKEY)
+        CHK_ERRA(DDERR_NOCOLORKEYHW)
+        CHK_ERRA(DDERR_NODIRECTDRAWSUPPORT)
+        CHK_ERRA(DDERR_NOEXCLUSIVEMODE)
+        CHK_ERRA(DDERR_NOFLIPHW)
+        CHK_ERRA(DDERR_NOGDI)
+        CHK_ERRA(DDERR_NOMIRRORHW)
+        CHK_ERRA(DDERR_NOTFOUND)
+        CHK_ERRA(DDERR_NOOVERLAYHW)
+        CHK_ERRA(DDERR_OVERLAPPINGRECTS)
+        CHK_ERRA(DDERR_NORASTEROPHW)
+        CHK_ERRA(DDERR_NOROTATIONHW)
+        CHK_ERRA(DDERR_NOSTRETCHHW)
+        CHK_ERRA(DDERR_NOT4BITCOLOR)
+        CHK_ERRA(DDERR_NOT4BITCOLORINDEX)
+        CHK_ERRA(DDERR_NOT8BITCOLOR)
+        CHK_ERRA(DDERR_NOTEXTUREHW)
+        CHK_ERRA(DDERR_NOVSYNCHW)
+        CHK_ERRA(DDERR_NOZBUFFERHW)
+        CHK_ERRA(DDERR_NOZOVERLAYHW)
+        CHK_ERRA(DDERR_OUTOFCAPS)
+//        CHK_ERRA(DDERR_OUTOFMEMORY)
+//        CHK_ERRA(DDERR_OUTOFVIDEOMEMORY)
+        CHK_ERRA(DDERR_OVERLAYCANTCLIP)
+        CHK_ERRA(DDERR_OVERLAYCOLORKEYONLYONEACTIVE)
+        CHK_ERRA(DDERR_PALETTEBUSY)
+        CHK_ERRA(DDERR_COLORKEYNOTSET)
+        CHK_ERRA(DDERR_SURFACEALREADYATTACHED)
+        CHK_ERRA(DDERR_SURFACEALREADYDEPENDENT)
+        CHK_ERRA(DDERR_SURFACEBUSY)
+        CHK_ERRA(DDERR_CANTLOCKSURFACE)
+        CHK_ERRA(DDERR_SURFACEISOBSCURED)
+        CHK_ERRA(DDERR_SURFACELOST)
+        CHK_ERRA(DDERR_SURFACENOTATTACHED)
+        CHK_ERRA(DDERR_TOOBIGHEIGHT)
+        CHK_ERRA(DDERR_TOOBIGSIZE)
+        CHK_ERRA(DDERR_TOOBIGWIDTH)
+//        CHK_ERRA(DDERR_UNSUPPORTED)
+        CHK_ERRA(DDERR_UNSUPPORTEDFORMAT)
+        CHK_ERRA(DDERR_UNSUPPORTEDMASK)
+        CHK_ERRA(DDERR_INVALIDSTREAM)
+        CHK_ERRA(DDERR_VERTICALBLANKINPROGRESS)
+        CHK_ERRA(DDERR_WASSTILLDRAWING)
+        CHK_ERRA(DDERR_DDSCAPSCOMPLEXREQUIRED)
+        CHK_ERRA(DDERR_XALIGN)
+        CHK_ERRA(DDERR_INVALIDDIRECTDRAWGUID)
+        CHK_ERRA(DDERR_DIRECTDRAWALREADYCREATED)
+        CHK_ERRA(DDERR_NODIRECTDRAWHW)
+        CHK_ERRA(DDERR_PRIMARYSURFACEALREADYEXISTS)
+        CHK_ERRA(DDERR_NOEMULATION)
+        CHK_ERRA(DDERR_REGIONTOOSMALL)
+        CHK_ERRA(DDERR_CLIPPERISUSINGHWND)
+        CHK_ERRA(DDERR_NOCLIPPERATTACHED)
+        CHK_ERRA(DDERR_NOHWND)
+        CHK_ERRA(DDERR_HWNDSUBCLASSED)
+        CHK_ERRA(DDERR_HWNDALREADYSET)
+        CHK_ERRA(DDERR_NOPALETTEATTACHED)
+        CHK_ERRA(DDERR_NOPALETTEHW)
+        CHK_ERRA(DDERR_BLTFASTCANTCLIP)
+        CHK_ERRA(DDERR_NOBLTHW)
+        CHK_ERRA(DDERR_NODDROPSHW)
+        CHK_ERRA(DDERR_OVERLAYNOTVISIBLE)
+        CHK_ERRA(DDERR_NOOVERLAYDEST)
+        CHK_ERRA(DDERR_INVALIDPOSITION)
+        CHK_ERRA(DDERR_NOTAOVERLAYSURFACE)
+        CHK_ERRA(DDERR_EXCLUSIVEMODEALREADYSET)
+        CHK_ERRA(DDERR_NOTFLIPPABLE)
+        CHK_ERRA(DDERR_CANTDUPLICATE)
+        CHK_ERRA(DDERR_NOTLOCKED)
+        CHK_ERRA(DDERR_CANTCREATEDC)
+        CHK_ERRA(DDERR_NODC)
+        CHK_ERRA(DDERR_WRONGMODE)
+        CHK_ERRA(DDERR_IMPLICITLYCREATED)
+        CHK_ERRA(DDERR_NOTPALETTIZED)
+        CHK_ERRA(DDERR_UNSUPPORTEDMODE)
+        CHK_ERRA(DDERR_NOMIPMAPHW)
+        CHK_ERRA(DDERR_INVALIDSURFACETYPE)
+        CHK_ERRA(DDERR_NOOPTIMIZEHW)
+        CHK_ERRA(DDERR_NOTLOADED)
+        CHK_ERRA(DDERR_NOFOCUSWINDOW)
+        CHK_ERRA(DDERR_NOTONMIPMAPSUBLEVEL)
+        CHK_ERRA(DDERR_DCALREADYCREATED)
+        CHK_ERRA(DDERR_NONONLOCALVIDMEM)
+        CHK_ERRA(DDERR_CANTPAGELOCK)
+        CHK_ERRA(DDERR_CANTPAGEUNLOCK)
+        CHK_ERRA(DDERR_NOTPAGELOCKED)
+        CHK_ERRA(DDERR_MOREDATA)
+        CHK_ERRA(DDERR_EXPIRED)
+        CHK_ERRA(DDERR_TESTFINISHED)
+        CHK_ERRA(DDERR_NEWMODE)
+        CHK_ERRA(DDERR_D3DNOTINITIALIZED)
+        CHK_ERRA(DDERR_VIDEONOTACTIVE)
+        CHK_ERRA(DDERR_NOMONITORINFORMATION)
+        CHK_ERRA(DDERR_NODRIVERSUPPORT)
+        CHK_ERRA(DDERR_DEVICEDOESNTOWNSURFACE)
+
+// -------------------------------------------------------------
+// dinput.h error codes
+// -------------------------------------------------------------
+//      CHK_ERRA(DI_OK)
+//      CHK_ERRA(DI_NOTATTACHED)
+//      CHK_ERRA(DI_BUFFEROVERFLOW)
+//      CHK_ERRA(DI_PROPNOEFFECT)
+//      CHK_ERRA(DI_NOEFFECT)
+//      CHK_ERRA(DI_POLLEDDEVICE)
+//      CHK_ERRA(DI_DOWNLOADSKIPPED)
+//      CHK_ERRA(DI_EFFECTRESTARTED)
+//      CHK_ERRA(DI_SETTINGSNOTSAVED_ACCESSDENIED)
+//      CHK_ERRA(DI_SETTINGSNOTSAVED_DISKFULL)
+//      CHK_ERRA(DI_TRUNCATED)
+//      CHK_ERRA(DI_TRUNCATEDANDRESTARTED)
+//      CHK_ERRA(DI_WRITEPROTECT)
+        CHK_ERR(DIERR_INSUFFICIENTPRIVS, "DIERR_INSUFFICIENTPRIVS & VFW_E_INVALIDMEDIATYPE")
+        CHK_ERR(DIERR_DEVICEFULL, "DIERR_DEVICEFULL & VFW_E_INVALIDSUBTYPE & DMO_E_INVALIDSTREAMINDEX")
+        CHK_ERR(DIERR_MOREDATA, "DIERR_MOREDATA & VFW_E_NEED_OWNER & DMO_E_INVALIDTYPE")
+        CHK_ERR(DIERR_NOTDOWNLOADED, "DIERR_NOTDOWNLOADED & VFW_E_ENUM_OUT_OF_SYNC & DMO_E_TYPE_NOT_SET")
+        CHK_ERR(DIERR_HASEFFECTS, "DIERR_HASEFFECTS & VFW_E_ALREADY_CONNECTED & DMO_E_NOTACCEPTING")
+        CHK_ERR(DIERR_NOTEXCLUSIVEACQUIRED, "DIERR_NOTEXCLUSIVEACQUIRED & VFW_E_FILTER_ACTIVE & DMO_E_TYPE_NOT_ACCEPTED")
+        CHK_ERR(DIERR_INCOMPLETEEFFECT, "DIERR_INCOMPLETEEFFECT & VFW_E_NO_TYPES & DMO_E_NO_MORE_ITEMS")
+        CHK_ERR(DIERR_NOTBUFFERED, "DIERR_NOTBUFFERED & VFW_E_NO_ACCEPTABLE_TYPES")
+        CHK_ERR(DIERR_EFFECTPLAYING, "DIERR_EFFECTPLAYING & VFW_E_INVALID_DIRECTION")
+        CHK_ERR(DIERR_UNPLUGGED, "DIERR_UNPLUGGED & VFW_E_NOT_CONNECTED")
+        CHK_ERR(DIERR_REPORTFULL, "DIERR_REPORTFULL & VFW_E_NO_ALLOCATOR")
+        CHK_ERR(DIERR_MAPFILEFAIL, "DIERR_MAPFILEFAIL & VFW_E_RUNTIME_ERROR")
+//      CHK_ERRA(DIERR_OLDDIRECTINPUTVERSION)
+//      CHK_ERRA(DIERR_GENERIC)
+//      CHK_ERRA(DIERR_OLDDIRECTINPUTVERSION)
+//      CHK_ERRA(DIERR_BETADIRECTINPUTVERSION)
+//      CHK_ERRA(DIERR_BADDRIVERVER)
+//      CHK_ERRA(DIERR_DEVICENOTREG)
+//      CHK_ERRA(DIERR_NOTFOUND)
+//      CHK_ERRA(DIERR_OBJECTNOTFOUND)
+//      CHK_ERRA(DIERR_INVALIDPARAM)
+//      CHK_ERRA(DIERR_NOINTERFACE)
+//      CHK_ERRA(DIERR_GENERIC)
+//      CHK_ERRA(DIERR_OUTOFMEMORY)
+//      CHK_ERRA(DIERR_UNSUPPORTED)
+//      CHK_ERRA(DIERR_NOTINITIALIZED)
+//      CHK_ERRA(DIERR_ALREADYINITIALIZED)
+//      CHK_ERRA(DIERR_NOAGGREGATION)
+//      CHK_ERRA(DIERR_OTHERAPPHASPRIO)
+//      CHK_ERRA(DIERR_INPUTLOST)
+//      CHK_ERRA(DIERR_ACQUIRED)
+//      CHK_ERRA(DIERR_NOTACQUIRED)
+//      CHK_ERRA(DIERR_READONLY)
+//      CHK_ERRA(DIERR_HANDLEEXISTS)
+
+
+// -------------------------------------------------------------
+// dinputd.h error
+// -------------------------------------------------------------
+//        CHK_ERRA(DIERR_NOMOREITEMS)
+        CHK_ERRA(DIERR_DRIVERFIRST)
+        CHK_ERR(DIERR_DRIVERFIRST+1, "DIERR_DRIVERFIRST+1")
+        CHK_ERR(DIERR_DRIVERFIRST+2, "DIERR_DRIVERFIRST+2")
+        CHK_ERR(DIERR_DRIVERFIRST+3, "DIERR_DRIVERFIRST+3")
+        CHK_ERR(DIERR_DRIVERFIRST+4, "DIERR_DRIVERFIRST+4")
+        CHK_ERR(DIERR_DRIVERFIRST+5, "DIERR_DRIVERFIRST+5")
+        CHK_ERRA(DIERR_DRIVERLAST)
+        CHK_ERR(DIERR_INVALIDCLASSINSTALLER, "DIERR_INVALIDCLASSINSTALLER")
+        CHK_ERR(DIERR_CANCELLED, "DIERR_CANCELLED & MS_E_SAMPLEALLOC")
+        CHK_ERRA(DIERR_BADINF)
+
+// -------------------------------------------------------------
+// d3d9.h error codes
+// -------------------------------------------------------------
+//      CHK_ERRA(D3D_OK)
+        CHK_ERRA(D3DERR_WRONGTEXTUREFORMAT)
+        CHK_ERRA(D3DERR_UNSUPPORTEDCOLOROPERATION)
+        CHK_ERRA(D3DERR_UNSUPPORTEDCOLORARG)
+        CHK_ERRA(D3DERR_UNSUPPORTEDALPHAOPERATION)
+        CHK_ERRA(D3DERR_UNSUPPORTEDALPHAARG)
+        CHK_ERRA(D3DERR_TOOMANYOPERATIONS)
+        CHK_ERRA(D3DERR_CONFLICTINGTEXTUREFILTER)
+        CHK_ERRA(D3DERR_UNSUPPORTEDFACTORVALUE)
+        CHK_ERRA(D3DERR_CONFLICTINGRENDERSTATE)
+        CHK_ERRA(D3DERR_UNSUPPORTEDTEXTUREFILTER)
+        CHK_ERRA(D3DERR_CONFLICTINGTEXTUREPALETTE)
+        CHK_ERRA(D3DERR_DRIVERINTERNALERROR)
+        CHK_ERRA(D3DERR_NOTFOUND)
+        CHK_ERRA(D3DERR_MOREDATA)
+        CHK_ERRA(D3DERR_DEVICELOST)
+        CHK_ERRA(D3DERR_DEVICENOTRESET)
+        CHK_ERRA(D3DERR_NOTAVAILABLE)
+        CHK_ERRA(D3DERR_OUTOFVIDEOMEMORY)
+        CHK_ERRA(D3DERR_INVALIDDEVICE)
+        CHK_ERRA(D3DERR_INVALIDCALL)
+        CHK_ERRA(D3DERR_DRIVERINVALIDCALL)
+        //CHK_ERRA(D3DERR_WASSTILLDRAWING)
+        CHK_ERRA(D3DOK_NOAUTOGEN)
+
+	    // Extended for Windows Vista
+	    CHK_ERRA(D3DERR_DEVICEREMOVED)
+	    CHK_ERRA(S_NOT_RESIDENT)
+	    CHK_ERRA(S_RESIDENT_IN_SHARED_MEMORY)
+	    CHK_ERRA(S_PRESENT_MODE_CHANGED)
+	    CHK_ERRA(S_PRESENT_OCCLUDED)
+	    CHK_ERRA(D3DERR_DEVICEHUNG)
+
+        // Extended for Windows 7
+        CHK_ERRA(D3DERR_UNSUPPORTEDOVERLAY)
+        CHK_ERRA(D3DERR_UNSUPPORTEDOVERLAYFORMAT)
+        CHK_ERRA(D3DERR_CANNOTPROTECTCONTENT)
+        CHK_ERRA(D3DERR_UNSUPPORTEDCRYPTO)
+        CHK_ERRA(D3DERR_PRESENT_STATISTICS_DISJOINT)
+
+// -------------------------------------------------------------
+// dsound.h error codes
+// -------------------------------------------------------------
+//      CHK_ERRA(DS_OK)
+        CHK_ERRA(DS_NO_VIRTUALIZATION)
+        CHK_ERRA(DSERR_ALLOCATED)
+        CHK_ERRA(DSERR_CONTROLUNAVAIL)
+//      CHK_ERRA(DSERR_INVALIDPARAM)
+        CHK_ERRA(DSERR_INVALIDCALL)
+//      CHK_ERRA(DSERR_GENERIC)
+        CHK_ERRA(DSERR_PRIOLEVELNEEDED)
+//      CHK_ERRA(DSERR_OUTOFMEMORY)
+        CHK_ERRA(DSERR_BADFORMAT)
+//      CHK_ERRA(DSERR_UNSUPPORTED)
+        CHK_ERRA(DSERR_NODRIVER)
+        CHK_ERRA(DSERR_ALREADYINITIALIZED)
+//      CHK_ERRA(DSERR_NOAGGREGATION)
+        CHK_ERRA(DSERR_BUFFERLOST)
+        CHK_ERRA(DSERR_OTHERAPPHASPRIO)
+        CHK_ERRA(DSERR_UNINITIALIZED)
+//      CHK_ERRA(DSERR_NOINTERFACE)
+//      CHK_ERRA(DSERR_ACCESSDENIED)
+        CHK_ERRA(DSERR_BUFFERTOOSMALL)
+        CHK_ERRA(DSERR_DS8_REQUIRED)
+        CHK_ERRA(DSERR_SENDLOOP)
+        CHK_ERRA(DSERR_BADSENDBUFFERGUID)
+        CHK_ERRA(DSERR_OBJECTNOTFOUND)
+
+    	CHK_ERRA(DSERR_FXUNAVAILABLE)
+
+#endif // !WINAPI_FAMILY || WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP
+
+// -------------------------------------------------------------
+// d3d10.h error codes
+// -------------------------------------------------------------
+        CHK_ERRA(D3D10_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS)
+        CHK_ERRA(D3D10_ERROR_FILE_NOT_FOUND)
+
+// -------------------------------------------------------------
+// dxgi.h error codes
+// -------------------------------------------------------------
+        CHK_ERRA(DXGI_STATUS_OCCLUDED)
+        CHK_ERRA(DXGI_STATUS_CLIPPED)
+        CHK_ERRA(DXGI_STATUS_NO_REDIRECTION)
+        CHK_ERRA(DXGI_STATUS_NO_DESKTOP_ACCESS)
+        CHK_ERRA(DXGI_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE)
+        CHK_ERRA(DXGI_STATUS_MODE_CHANGED)
+        CHK_ERRA(DXGI_STATUS_MODE_CHANGE_IN_PROGRESS)
+        CHK_ERRA(DXGI_ERROR_INVALID_CALL)
+        CHK_ERRA(DXGI_ERROR_NOT_FOUND)
+        CHK_ERRA(DXGI_ERROR_MORE_DATA)
+        CHK_ERRA(DXGI_ERROR_UNSUPPORTED)
+        CHK_ERRA(DXGI_ERROR_DEVICE_REMOVED)
+        CHK_ERRA(DXGI_ERROR_DEVICE_HUNG)
+        CHK_ERRA(DXGI_ERROR_DEVICE_RESET)
+        CHK_ERRA(DXGI_ERROR_WAS_STILL_DRAWING)
+        CHK_ERRA(DXGI_ERROR_FRAME_STATISTICS_DISJOINT)
+        CHK_ERRA(DXGI_ERROR_GRAPHICS_VIDPN_SOURCE_IN_USE)
+        CHK_ERRA(DXGI_ERROR_DRIVER_INTERNAL_ERROR)
+        CHK_ERRA(DXGI_ERROR_NONEXCLUSIVE)
+        CHK_ERRA(DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
+        CHK_ERRA(DXGI_ERROR_REMOTE_CLIENT_DISCONNECTED)
+        CHK_ERRA(DXGI_ERROR_REMOTE_OUTOFMEMORY)
+
+// -------------------------------------------------------------
+// d3d11.h error codes
+// -------------------------------------------------------------
+        CHK_ERRA(D3D11_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS)
+        CHK_ERRA(D3D11_ERROR_FILE_NOT_FOUND)
+        CHK_ERRA(D3D11_ERROR_TOO_MANY_UNIQUE_VIEW_OBJECTS)
+        CHK_ERRA(D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD)
+
+#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
+
+// -------------------------------------------------------------
+// Direct2D error codes
+// -------------------------------------------------------------
+//        CHK_ERRA(D2DERR_UNSUPPORTED_PIXEL_FORMAT)
+//        CHK_ERRA(D2DERR_INSUFFICIENT_BUFFER)
+        CHK_ERRA(D2DERR_WRONG_STATE)
+        CHK_ERRA(D2DERR_NOT_INITIALIZED)
+        CHK_ERRA(D2DERR_UNSUPPORTED_OPERATION)
+        CHK_ERRA(D2DERR_SCANNER_FAILED)
+        CHK_ERRA(D2DERR_SCREEN_ACCESS_DENIED)
+        CHK_ERRA(D2DERR_DISPLAY_STATE_INVALID)
+        CHK_ERRA(D2DERR_ZERO_VECTOR)
+        CHK_ERRA(D2DERR_INTERNAL_ERROR)
+        CHK_ERRA(D2DERR_DISPLAY_FORMAT_NOT_SUPPORTED)
+        CHK_ERRA(D2DERR_INVALID_CALL)
+        CHK_ERRA(D2DERR_NO_HARDWARE_DEVICE)
+        CHK_ERRA(D2DERR_RECREATE_TARGET)
+        CHK_ERRA(D2DERR_TOO_MANY_SHADER_ELEMENTS)
+        CHK_ERRA(D2DERR_SHADER_COMPILE_FAILED)
+        CHK_ERRA(D2DERR_MAX_TEXTURE_SIZE_EXCEEDED)
+        CHK_ERRA(D2DERR_UNSUPPORTED_VERSION)
+        CHK_ERRA(D2DERR_BAD_NUMBER)
+        CHK_ERRA(D2DERR_WRONG_FACTORY)
+        CHK_ERRA(D2DERR_LAYER_ALREADY_IN_USE)
+        CHK_ERRA(D2DERR_POP_CALL_DID_NOT_MATCH_PUSH)
+//        CHK_ERRA(D2DERR_WRONG_RESOURCE_DOMAIN)
+        CHK_ERRA(D2DERR_PUSH_POP_UNBALANCED)
+        CHK_ERRA(D2DERR_RENDER_TARGET_HAS_LAYER_OR_CLIPRECT)
+        CHK_ERRA(D2DERR_INCOMPATIBLE_BRUSH_TYPES)
+        CHK_ERRA(D2DERR_WIN32_ERROR)
+        CHK_ERRA(D2DERR_TARGET_NOT_GDI_COMPATIBLE)
+        CHK_ERRA(D2DERR_TEXT_EFFECT_IS_WRONG_TYPE)
+        CHK_ERRA(D2DERR_TEXT_RENDERER_NOT_RELEASED)
+//        CHK_ERRA(D2DERR_EXCEEDS_MAX_BITMAP_SIZE)
+
+// -------------------------------------------------------------
+// DirectWrite error codes
+// -------------------------------------------------------------
+        CHK_ERRA(DWRITE_E_FILEFORMAT)
+        CHK_ERRA(DWRITE_E_UNEXPECTED)
+        CHK_ERRA(DWRITE_E_NOFONT)
+        CHK_ERRA(DWRITE_E_FILENOTFOUND)
+        CHK_ERRA(DWRITE_E_FILEACCESS)
+        CHK_ERRA(DWRITE_E_FONTCOLLECTIONOBSOLETE)
+        CHK_ERRA(DWRITE_E_ALREADYREGISTERED)
+
+// -------------------------------------------------------------
+// WIC error codes
+// -------------------------------------------------------------
+        CHK_ERRA(WINCODEC_ERR_WRONGSTATE)
+        CHK_ERRA(WINCODEC_ERR_VALUEOUTOFRANGE)
+        CHK_ERRA(WINCODEC_ERR_UNKNOWNIMAGEFORMAT)
+        CHK_ERRA(WINCODEC_ERR_UNSUPPORTEDVERSION)
+        CHK_ERRA(WINCODEC_ERR_NOTINITIALIZED)
+        CHK_ERRA(WINCODEC_ERR_ALREADYLOCKED)
+        CHK_ERRA(WINCODEC_ERR_PROPERTYNOTFOUND)
+        CHK_ERRA(WINCODEC_ERR_PROPERTYNOTSUPPORTED)
+        CHK_ERRA(WINCODEC_ERR_PROPERTYSIZE)
+        CHK_ERRA(WINCODEC_ERR_CODECPRESENT)
+        CHK_ERRA(WINCODEC_ERR_CODECNOTHUMBNAIL)
+        CHK_ERRA(WINCODEC_ERR_PALETTEUNAVAILABLE)
+        CHK_ERRA(WINCODEC_ERR_CODECTOOMANYSCANLINES)
+        CHK_ERRA(WINCODEC_ERR_INTERNALERROR)
+        CHK_ERRA(WINCODEC_ERR_SOURCERECTDOESNOTMATCHDIMENSIONS)
+        CHK_ERRA(WINCODEC_ERR_COMPONENTNOTFOUND)
+        CHK_ERRA(WINCODEC_ERR_IMAGESIZEOUTOFRANGE)
+        CHK_ERRA(WINCODEC_ERR_TOOMUCHMETADATA)
+        CHK_ERRA(WINCODEC_ERR_BADIMAGE)
+        CHK_ERRA(WINCODEC_ERR_BADHEADER)
+        CHK_ERRA(WINCODEC_ERR_FRAMEMISSING)
+        CHK_ERRA(WINCODEC_ERR_BADMETADATAHEADER)
+        CHK_ERRA(WINCODEC_ERR_BADSTREAMDATA)
+        CHK_ERRA(WINCODEC_ERR_STREAMWRITE)
+        CHK_ERRA(WINCODEC_ERR_STREAMREAD)
+        CHK_ERRA(WINCODEC_ERR_STREAMNOTAVAILABLE)
+        CHK_ERRA(WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT)
+        CHK_ERRA(WINCODEC_ERR_UNSUPPORTEDOPERATION)
+        CHK_ERRA(WINCODEC_ERR_INVALIDREGISTRATION)
+        CHK_ERRA(WINCODEC_ERR_COMPONENTINITIALIZEFAILURE)
+        CHK_ERRA(WINCODEC_ERR_INSUFFICIENTBUFFER)
+        CHK_ERRA(WINCODEC_ERR_DUPLICATEMETADATAPRESENT)
+        CHK_ERRA(WINCODEC_ERR_PROPERTYUNEXPECTEDTYPE)
+        CHK_ERRA(WINCODEC_ERR_UNEXPECTEDSIZE)
+        CHK_ERRA(WINCODEC_ERR_INVALIDQUERYREQUEST)
+        CHK_ERRA(WINCODEC_ERR_UNEXPECTEDMETADATATYPE)
+        CHK_ERRA(WINCODEC_ERR_REQUESTONLYVALIDATMETADATAROOT)
+        CHK_ERRA(WINCODEC_ERR_INVALIDQUERYCHARACTER)
+        CHK_ERRA(WINCODEC_ERR_WIN32ERROR)
+        CHK_ERRA(WINCODEC_ERR_INVALIDPROGRESSIVELEVEL)
+
+#endif // !WINAPI_FAMILY || WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
+
+// -------------------------------------------------------------
+// DXUT error codes
+// -------------------------------------------------------------
+        CHK_ERRA(DXUTERR_NODIRECT3D)
+        CHK_ERRA(DXUTERR_NOCOMPATIBLEDEVICES)
+        CHK_ERRA(DXUTERR_MEDIANOTFOUND)
+        CHK_ERRA(DXUTERR_NONZEROREFCOUNT)
+        CHK_ERRA(DXUTERR_CREATINGDEVICE)
+        CHK_ERRA(DXUTERR_RESETTINGDEVICE)
+        CHK_ERRA(DXUTERR_CREATINGDEVICEOBJECTS)
+        CHK_ERRA(DXUTERR_RESETTINGDEVICEOBJECTS)
+        CHK_ERRA(DXUTERR_INCORRECTVERSION)
+        CHK_ERRA(DXUTERR_DEVICEREMOVED)
+
+// -------------------------------------------------------------
+// xaudio2.h error codes
+// -------------------------------------------------------------
+        CHK_ERRA(XAUDIO2_E_INVALID_CALL)
+        CHK_ERRA(XAUDIO2_E_XMA_DECODER_ERROR)
+        CHK_ERRA(XAUDIO2_E_XAPO_CREATION_FAILED)
+        CHK_ERRA(XAUDIO2_E_DEVICE_INVALIDATED)
+
+// -------------------------------------------------------------
+// xapo.h error codes
+// -------------------------------------------------------------
+        CHK_ERRA(XAPO_E_FORMAT_UNSUPPORTED)
+    }
+
+    return L"Unknown";
+}
+
+//--------------------------------------------------------------------------------------
+#undef CHK_ERR
+#undef CHK_ERRA
+#undef HRESULT_FROM_WIN32b
+#undef CHK_ERR_WIN32A
+#undef CHK_ERR_WIN32_ONLY
+
+#define  CHK_ERRA(hrchk) \
+        case hrchk: \
+             wcscpy_s( desc, count, L#hrchk ); \
+             break;
+
+#define  CHK_ERR(hrchk, strOut) \
+        case hrchk: \
+             wcscpy_s( desc, count, L##strOut ); \
+             break;
+
+
+//--------------------------------------------------------------------------------------
+void WINAPI DXGetErrorDescriptionW( _In_ HRESULT hr, _Out_cap_(count) WCHAR* desc, _In_ size_t count )
+{
+    if ( !count )
+        return;
+
+    *desc = 0;
+
+    // First try to see if FormatMessage knows this hr
+    UINT icount = static_cast<UINT>( std::min<size_t>( count, 32767 ) );
+
+    DWORD result = FormatMessageW( FORMAT_MESSAGE_FROM_SYSTEM, nullptr, hr, 
+                                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), desc, icount, nullptr );
+
+    if (result > 0)
+        return;
+
+    switch (hr)
+    {
+// Commmented out codes are actually alises for other codes
+
+#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)
+
+// -------------------------------------------------------------
+// ddraw.h error codes
+// -------------------------------------------------------------
+        CHK_ERR(DDERR_ALREADYINITIALIZED, "This object is already initialized")
+        CHK_ERR(DDERR_CANNOTATTACHSURFACE, "This surface can not be attached to the requested surface.")
+        CHK_ERR(DDERR_CANNOTDETACHSURFACE, "This surface can not be detached from the requested surface.")
+        CHK_ERR(DDERR_CURRENTLYNOTAVAIL, "Support is currently not available.")
+        CHK_ERR(DDERR_EXCEPTION, "An exception was encountered while performing the requested operation")
+//      CHK_ERR(DDERR_GENERIC, "DDERR_GENERIC")
+        CHK_ERR(DDERR_HEIGHTALIGN, "Height of rectangle provided is not a multiple of reqd alignment")
+        CHK_ERR(DDERR_INCOMPATIBLEPRIMARY, "Unable to match primary surface creation request with existing primary surface.")
+        CHK_ERR(DDERR_INVALIDCAPS, "One or more of the caps bits passed to the callback are incorrect.")
+        CHK_ERR(DDERR_INVALIDCLIPLIST, "DirectDraw does not support provided Cliplist.")
+        CHK_ERR(DDERR_INVALIDMODE, "DirectDraw does not support the requested mode")
+        CHK_ERR(DDERR_INVALIDOBJECT, "DirectDraw received a pointer that was an invalid DIRECTDRAW object.")
+//        CHK_ERR(DDERR_INVALIDPARAMS, "DDERR_INVALIDPARAMS")
+        CHK_ERR(DDERR_INVALIDPIXELFORMAT, "pixel format was invalid as specified")
+        CHK_ERR(DDERR_INVALIDRECT, "Rectangle provided was invalid.")
+        CHK_ERR(DDERR_LOCKEDSURFACES, "Operation could not be carried out because one or more surfaces are locked")
+        CHK_ERR(DDERR_NO3D, "There is no 3D present.")
+        CHK_ERR(DDERR_NOALPHAHW, "Operation could not be carried out because there is no alpha accleration hardware present or available.")
+        CHK_ERR(DDERR_NOSTEREOHARDWARE, "Operation could not be carried out because there is no stereo hardware present or available.")
+        CHK_ERR(DDERR_NOSURFACELEFT, "Operation could not be carried out because there is no hardware present which supports stereo surfaces")
+        CHK_ERR(DDERR_NOCLIPLIST, "no clip list available")
+        CHK_ERR(DDERR_NOCOLORCONVHW, "Operation could not be carried out because there is no color conversion hardware present or available.")
+        CHK_ERR(DDERR_NOCOOPERATIVELEVELSET, "Create function called without DirectDraw object method SetCooperativeLevel being called.")
+        CHK_ERR(DDERR_NOCOLORKEY, "Surface doesn't currently have a color key")
+        CHK_ERR(DDERR_NOCOLORKEYHW, "Operation could not be carried out because there is no hardware support of the dest color key.")
+        CHK_ERR(DDERR_NODIRECTDRAWSUPPORT, "No DirectDraw support possible with current display driver")
+        CHK_ERR(DDERR_NOEXCLUSIVEMODE, "Operation requires the application to have exclusive mode but the application does not have exclusive mode.")
+        CHK_ERR(DDERR_NOFLIPHW, "Flipping visible surfaces is not supported.")
+        CHK_ERR(DDERR_NOGDI, "There is no GDI present.")
+        CHK_ERR(DDERR_NOMIRRORHW, "Operation could not be carried out because there is no hardware present or available.")
+        CHK_ERR(DDERR_NOTFOUND, "Requested item was not found")
+        CHK_ERR(DDERR_NOOVERLAYHW, "Operation could not be carried out because there is no overlay hardware present or available.")
+        CHK_ERR(DDERR_OVERLAPPINGRECTS, "Operation could not be carried out because the source and destination rectangles are on the same surface and overlap each other.")
+        CHK_ERR(DDERR_NORASTEROPHW, "Operation could not be carried out because there is no appropriate raster op hardware present or available.")
+        CHK_ERR(DDERR_NOROTATIONHW, "Operation could not be carried out because there is no rotation hardware present or available.")
+        CHK_ERR(DDERR_NOSTRETCHHW, "Operation could not be carried out because there is no hardware support for stretching")
+        CHK_ERR(DDERR_NOT4BITCOLOR, "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color palette.")
+        CHK_ERR(DDERR_NOT4BITCOLORINDEX, "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color index palette.")
+        CHK_ERR(DDERR_NOT8BITCOLOR, "DirectDraw Surface is not in 8 bit color mode and the requested operation requires 8 bit color.")
+        CHK_ERR(DDERR_NOTEXTUREHW, "Operation could not be carried out because there is no texture mapping hardware present or available.")
+        CHK_ERR(DDERR_NOVSYNCHW, "Operation could not be carried out because there is no hardware support for vertical blank synchronized operations.")
+        CHK_ERR(DDERR_NOZBUFFERHW, "Operation could not be carried out because there is no hardware support for zbuffer blting.")
+        CHK_ERR(DDERR_NOZOVERLAYHW, "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support z layering of overlays.")
+        CHK_ERR(DDERR_OUTOFCAPS, "The hardware needed for the requested operation has already been allocated.")
+//        CHK_ERR(DDERR_OUTOFMEMORY, "DDERR_OUTOFMEMORY")
+//        CHK_ERR(DDERR_OUTOFVIDEOMEMORY, "DDERR_OUTOFVIDEOMEMORY")
+        CHK_ERR(DDERR_OVERLAYCANTCLIP, "hardware does not support clipped overlays")
+        CHK_ERR(DDERR_OVERLAYCOLORKEYONLYONEACTIVE, "Can only have ony color key active at one time for overlays")
+        CHK_ERR(DDERR_PALETTEBUSY, "Access to this palette is being refused because the palette is already locked by another thread.")
+        CHK_ERR(DDERR_COLORKEYNOTSET, "No src color key specified for this operation.")
+        CHK_ERR(DDERR_SURFACEALREADYATTACHED, "This surface is already attached to the surface it is being attached to.")
+        CHK_ERR(DDERR_SURFACEALREADYDEPENDENT, "This surface is already a dependency of the surface it is being made a dependency of.")
+        CHK_ERR(DDERR_SURFACEBUSY, "Access to this surface is being refused because the surface is already locked by another thread.")
+        CHK_ERR(DDERR_CANTLOCKSURFACE, "Access to this surface is being refused because no driver exists which can supply a pointer to the surface. This is most likely to happen when attempting to lock the primary surface when no DCI provider is present. Will also happen on attempts to lock an optimized surface.")
+        CHK_ERR(DDERR_SURFACEISOBSCURED, "Access to Surface refused because Surface is obscured.")
+        CHK_ERR(DDERR_SURFACELOST, "Access to this surface is being refused because the surface is gone. The DIRECTDRAWSURFACE object representing this surface should have Restore called on it.")
+        CHK_ERR(DDERR_SURFACENOTATTACHED, "The requested surface is not attached.")
+        CHK_ERR(DDERR_TOOBIGHEIGHT, "Height requested by DirectDraw is too large.")
+        CHK_ERR(DDERR_TOOBIGSIZE, "Size requested by DirectDraw is too large --  The individual height and width are OK.")
+        CHK_ERR(DDERR_TOOBIGWIDTH, "Width requested by DirectDraw is too large.")
+//        CHK_ERR(DDERR_UNSUPPORTED, "DDERR_UNSUPPORTED")
+        CHK_ERR(DDERR_UNSUPPORTEDFORMAT, "Pixel format requested is unsupported by DirectDraw")
+        CHK_ERR(DDERR_UNSUPPORTEDMASK, "Bitmask in the pixel format requested is unsupported by DirectDraw")
+        CHK_ERR(DDERR_INVALIDSTREAM, "The specified stream contains invalid data")
+        CHK_ERR(DDERR_VERTICALBLANKINPROGRESS, "vertical blank is in progress")
+        CHK_ERR(DDERR_WASSTILLDRAWING, "Was still drawing")
+        CHK_ERR(DDERR_DDSCAPSCOMPLEXREQUIRED, "The specified surface type requires specification of the COMPLEX flag")
+        CHK_ERR(DDERR_XALIGN, "Rectangle provided was not horizontally aligned on reqd. boundary")
+        CHK_ERR(DDERR_INVALIDDIRECTDRAWGUID, "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier.")
+        CHK_ERR(DDERR_DIRECTDRAWALREADYCREATED, "A DirectDraw object representing this driver has already been created for this process.")
+        CHK_ERR(DDERR_NODIRECTDRAWHW, "A hardware only DirectDraw object creation was attempted but the driver did not support any hardware.")
+        CHK_ERR(DDERR_PRIMARYSURFACEALREADYEXISTS, "this process already has created a primary surface")
+        CHK_ERR(DDERR_NOEMULATION, "software emulation not available.")
+        CHK_ERR(DDERR_REGIONTOOSMALL, "region passed to Clipper::GetClipList is too small.")
+        CHK_ERR(DDERR_CLIPPERISUSINGHWND, "an attempt was made to set a clip list for a clipper objec that is already monitoring an hwnd.")
+        CHK_ERR(DDERR_NOCLIPPERATTACHED, "No clipper object attached to surface object")
+        CHK_ERR(DDERR_NOHWND, "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND.")
+        CHK_ERR(DDERR_HWNDSUBCLASSED, "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring state.")
+        CHK_ERR(DDERR_HWNDALREADYSET, "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or palettes created.")
+        CHK_ERR(DDERR_NOPALETTEATTACHED, "No palette object attached to this surface.")
+        CHK_ERR(DDERR_NOPALETTEHW, "No hardware support for 16 or 256 color palettes.")
+        CHK_ERR(DDERR_BLTFASTCANTCLIP, "If a clipper object is attached to the source surface passed into a BltFast call.")
+        CHK_ERR(DDERR_NOBLTHW, "No blter.")
+        CHK_ERR(DDERR_NODDROPSHW, "No DirectDraw ROP hardware.")
+        CHK_ERR(DDERR_OVERLAYNOTVISIBLE, "returned when GetOverlayPosition is called on a hidden overlay")
+        CHK_ERR(DDERR_NOOVERLAYDEST, "returned when GetOverlayPosition is called on a overlay that UpdateOverlay has never been called on to establish a destionation.")
+        CHK_ERR(DDERR_INVALIDPOSITION, "returned when the position of the overlay on the destionation is no longer legal for that destionation.")
+        CHK_ERR(DDERR_NOTAOVERLAYSURFACE, "returned when an overlay member is called for a non-overlay surface")
+        CHK_ERR(DDERR_EXCLUSIVEMODEALREADYSET, "An attempt was made to set the cooperative level when it was already set to exclusive.")
+        CHK_ERR(DDERR_NOTFLIPPABLE, "An attempt has been made to flip a surface that is not flippable.")
+        CHK_ERR(DDERR_CANTDUPLICATE, "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created.")
+        CHK_ERR(DDERR_NOTLOCKED, "Surface was not locked.  An attempt to unlock a surface that was not locked at all, or by this process, has been attempted.")
+        CHK_ERR(DDERR_CANTCREATEDC, "Windows can not create any more DCs, or a DC was requested for a paltte-indexed surface when the surface had no palette AND the display mode was not palette-indexed (in this case DirectDraw cannot select a proper palette into the DC)")
+        CHK_ERR(DDERR_NODC, "No DC was ever created for this surface.")
+        CHK_ERR(DDERR_WRONGMODE, "This surface can not be restored because it was created in a different mode.")
+        CHK_ERR(DDERR_IMPLICITLYCREATED, "This surface can not be restored because it is an implicitly created surface.")
+        CHK_ERR(DDERR_NOTPALETTIZED, "The surface being used is not a palette-based surface")
+        CHK_ERR(DDERR_UNSUPPORTEDMODE, "The display is currently in an unsupported mode")
+        CHK_ERR(DDERR_NOMIPMAPHW, "Operation could not be carried out because there is no mip-map texture mapping hardware present or available.")
+        CHK_ERR(DDERR_INVALIDSURFACETYPE, "The requested action could not be performed because the surface was of the wrong type.")
+        CHK_ERR(DDERR_NOOPTIMIZEHW, "Device does not support optimized surfaces, therefore no video memory optimized surfaces")
+        CHK_ERR(DDERR_NOTLOADED, "Surface is an optimized surface, but has not yet been allocated any memory")
+        CHK_ERR(DDERR_NOFOCUSWINDOW, "Attempt was made to create or set a device window without first setting the focus window")
+        CHK_ERR(DDERR_NOTONMIPMAPSUBLEVEL, "Attempt was made to set a palette on a mipmap sublevel")
+        CHK_ERR(DDERR_DCALREADYCREATED, "A DC has already been returned for this surface. Only one DC can be retrieved per surface.")
+        CHK_ERR(DDERR_NONONLOCALVIDMEM, "An attempt was made to allocate non-local video memory from a device that does not support non-local video memory.")
+        CHK_ERR(DDERR_CANTPAGELOCK, "The attempt to page lock a surface failed.")
+        CHK_ERR(DDERR_CANTPAGEUNLOCK, "The attempt to page unlock a surface failed.")
+        CHK_ERR(DDERR_NOTPAGELOCKED, "An attempt was made to page unlock a surface with no outstanding page locks.")
+        CHK_ERR(DDERR_MOREDATA, "There is more data available than the specified buffer size could hold")
+        CHK_ERR(DDERR_EXPIRED, "The data has expired and is therefore no longer valid.")
+        CHK_ERR(DDERR_TESTFINISHED, "The mode test has finished executing.")
+        CHK_ERR(DDERR_NEWMODE, "The mode test has switched to a new mode.")
+        CHK_ERR(DDERR_D3DNOTINITIALIZED, "D3D has not yet been initialized.")
+        CHK_ERR(DDERR_VIDEONOTACTIVE, "The video port is not active")
+        CHK_ERR(DDERR_NOMONITORINFORMATION, "The monitor does not have EDID data.")
+        CHK_ERR(DDERR_NODRIVERSUPPORT, "The driver does not enumerate display mode refresh rates.")
+        CHK_ERR(DDERR_DEVICEDOESNTOWNSURFACE, "Surfaces created by one direct draw device cannot be used directly by another direct draw device.")
+
+
+// -------------------------------------------------------------
+// dinput.h error codes
+// -------------------------------------------------------------
+//      CHK_ERR(DI_OK, "DI_OK")
+//      CHK_ERR(DI_NOTATTACHED, "DI_NOTATTACHED")
+//      CHK_ERR(DI_BUFFEROVERFLOW, "DI_BUFFEROVERFLOW")
+//      CHK_ERR(DI_PROPNOEFFECT, "DI_PROPNOEFFECT")
+//      CHK_ERR(DI_NOEFFECT, "DI_NOEFFECT")
+//      CHK_ERR(DI_POLLEDDEVICE, "DI_POLLEDDEVICE")
+//      CHK_ERR(DI_DOWNLOADSKIPPED, "DI_DOWNLOADSKIPPED")
+//      CHK_ERR(DI_EFFECTRESTARTED, "DI_EFFECTRESTARTED")
+//      CHK_ERR(DI_SETTINGSNOTSAVED_ACCESSDENIED, "DI_SETTINGSNOTSAVED_ACCESSDENIED")
+//      CHK_ERR(DI_SETTINGSNOTSAVED_DISKFULL, "DI_SETTINGSNOTSAVED_DISKFULL")
+//      CHK_ERR(DI_TRUNCATED, "DI_TRUNCATED")
+//      CHK_ERR(DI_TRUNCATEDANDRESTARTED, "DI_TRUNCATEDANDRESTARTED")
+//      CHK_ERR(DI_WRITEPROTECT, "DI_WRITEPROTECT")
+        CHK_ERR(DIERR_OLDDIRECTINPUTVERSION, "The application requires a newer version of DirectInput.")
+//      CHK_ERR(DIERR_GENERIC, "DIERR_GENERIC")
+//      CHK_ERR(DIERR_OLDDIRECTINPUTVERSION, "DIERR_OLDDIRECTINPUTVERSION")
+        CHK_ERR(DIERR_BETADIRECTINPUTVERSION, "The application was written for an unsupported prerelease version of DirectInput.")
+        CHK_ERR(DIERR_BADDRIVERVER, "The object could not be created due to an incompatible driver version or mismatched or incomplete driver components.")
+//      CHK_ERR(DIERR_DEVICENOTREG, "DIERR_DEVICENOTREG")
+//      CHK_ERR(DIERR_NOTFOUND, "The requested object does not exist.")
+//      CHK_ERR(DIERR_OBJECTNOTFOUND, "DIERR_OBJECTNOTFOUND")
+//      CHK_ERR(DIERR_INVALIDPARAM, "DIERR_INVALIDPARAM")
+//      CHK_ERR(DIERR_NOINTERFACE, "DIERR_NOINTERFACE")
+//      CHK_ERR(DIERR_GENERIC, "DIERR_GENERIC")
+//      CHK_ERR(DIERR_OUTOFMEMORY, "DIERR_OUTOFMEMORY")
+//      CHK_ERR(DIERR_UNSUPPORTED, "DIERR_UNSUPPORTED")
+        CHK_ERR(DIERR_NOTINITIALIZED, "This object has not been initialized")
+        CHK_ERR(DIERR_ALREADYINITIALIZED, "This object is already initialized")
+//      CHK_ERR(DIERR_NOAGGREGATION, "DIERR_NOAGGREGATION")
+//      CHK_ERR(DIERR_OTHERAPPHASPRIO, "DIERR_OTHERAPPHASPRIO")
+        CHK_ERR(DIERR_INPUTLOST, "Access to the device has been lost.  It must be re-acquired.")
+        CHK_ERR(DIERR_ACQUIRED, "The operation cannot be performed while the device is acquired.")
+        CHK_ERR(DIERR_NOTACQUIRED, "The operation cannot be performed unless the device is acquired.")
+//      CHK_ERR(DIERR_READONLY, "DIERR_READONLY")
+//      CHK_ERR(DIERR_HANDLEEXISTS, "DIERR_HANDLEEXISTS")
+        CHK_ERR(DIERR_INSUFFICIENTPRIVS, "Unable to IDirectInputJoyConfig_Acquire because the user does not have sufficient privileges to change the joystick configuration. & An invalid media type was specified")
+        CHK_ERR(DIERR_DEVICEFULL, "The device is full. & An invalid media subtype was specified.")
+        CHK_ERR(DIERR_MOREDATA, "Not all the requested information fit into the buffer. & This object can only be created as an aggregated object.")
+        CHK_ERR(DIERR_NOTDOWNLOADED, "The effect is not downloaded. & The enumerator has become invalid.")
+        CHK_ERR(DIERR_HASEFFECTS, "The device cannot be reinitialized because there are still effects attached to it. & At least one of the pins involved in the operation is already connected.")
+        CHK_ERR(DIERR_NOTEXCLUSIVEACQUIRED, "The operation cannot be performed unless the device is acquired in DISCL_EXCLUSIVE mode. & This operation cannot be performed because the filter is active.")
+        CHK_ERR(DIERR_INCOMPLETEEFFECT, "The effect could not be downloaded because essential information is missing.  For example, no axes have been associated with the effect, or no type-specific information has been created. & One of the specified pins supports no media types.")
+        CHK_ERR(DIERR_NOTBUFFERED, "Attempted to read buffered device data from a device that is not buffered. & There is no common media type between these pins.")
+        CHK_ERR(DIERR_EFFECTPLAYING, "An attempt was made to modify parameters of an effect while it is playing.  Not all hardware devices support altering the parameters of an effect while it is playing. & Two pins of the same direction cannot be connected together.")
+        CHK_ERR(DIERR_UNPLUGGED, "The operation could not be completed because the device is not plugged in. & The operation cannot be performed because the pins are not connected.")
+        CHK_ERR(DIERR_REPORTFULL, "SendDeviceData failed because more information was requested to be sent than can be sent to the device.  Some devices have restrictions on how much data can be sent to them.  (For example, there might be a limit on the number of buttons that can be pressed at once.) & No sample buffer allocator is available.")
+        CHK_ERR(DIERR_MAPFILEFAIL, "A mapper file function failed because reading or writing the user or IHV settings file failed. & A run-time error occurred.")
+
+// -------------------------------------------------------------
+// dinputd.h error codes
+// -------------------------------------------------------------
+        CHK_ERR(DIERR_NOMOREITEMS, "No more items.")
+        CHK_ERR(DIERR_DRIVERFIRST, "Device driver-specific codes. Unless the specific driver has been precisely identified, no meaning should be attributed to these values other than that the driver originated the error.")
+        CHK_ERR(DIERR_DRIVERFIRST+1, "DIERR_DRIVERFIRST+1")
+        CHK_ERR(DIERR_DRIVERFIRST+2, "DIERR_DRIVERFIRST+2")
+        CHK_ERR(DIERR_DRIVERFIRST+3, "DIERR_DRIVERFIRST+3")
+        CHK_ERR(DIERR_DRIVERFIRST+4, "DIERR_DRIVERFIRST+4")
+        CHK_ERR(DIERR_DRIVERFIRST+5, "DIERR_DRIVERFIRST+5")
+        CHK_ERR(DIERR_DRIVERLAST, "Device installer errors.")
+        CHK_ERR(DIERR_INVALIDCLASSINSTALLER, "Registry entry or DLL for class installer invalid or class installer not found.")
+        CHK_ERR(DIERR_CANCELLED, "The user cancelled the install operation. & The stream already has allocated samples and the surface doesn't match the sample format.")
+        CHK_ERR(DIERR_BADINF, "The INF file for the selected device could not be found or is invalid or is damaged. & The specified purpose ID can't be used for the call.")
+
+// -------------------------------------------------------------
+// d3d9.h error codes
+// -------------------------------------------------------------
+//      CHK_ERR(D3D_OK, "Ok")
+        CHK_ERR(D3DERR_WRONGTEXTUREFORMAT, "Wrong texture format")
+        CHK_ERR(D3DERR_UNSUPPORTEDCOLOROPERATION, "Unsupported color operation")
+        CHK_ERR(D3DERR_UNSUPPORTEDCOLORARG, "Unsupported color arg")
+        CHK_ERR(D3DERR_UNSUPPORTEDALPHAOPERATION, "Unsupported alpha operation")
+        CHK_ERR(D3DERR_UNSUPPORTEDALPHAARG, "Unsupported alpha arg")
+        CHK_ERR(D3DERR_TOOMANYOPERATIONS, "Too many operations")
+        CHK_ERR(D3DERR_CONFLICTINGTEXTUREFILTER, "Conflicting texture filter")
+        CHK_ERR(D3DERR_UNSUPPORTEDFACTORVALUE, "Unsupported factor value")
+        CHK_ERR(D3DERR_CONFLICTINGRENDERSTATE, "Conflicting render state")
+        CHK_ERR(D3DERR_UNSUPPORTEDTEXTUREFILTER, "Unsupported texture filter")
+        CHK_ERR(D3DERR_CONFLICTINGTEXTUREPALETTE, "Conflicting texture palette")
+        CHK_ERR(D3DERR_DRIVERINTERNALERROR, "Driver internal error")
+        CHK_ERR(D3DERR_NOTFOUND, "Not found")
+        CHK_ERR(D3DERR_MOREDATA, "More data")
+        CHK_ERR(D3DERR_DEVICELOST, "Device lost")
+        CHK_ERR(D3DERR_DEVICENOTRESET, "Device not reset")
+        CHK_ERR(D3DERR_NOTAVAILABLE, "Not available")
+        CHK_ERR(D3DERR_OUTOFVIDEOMEMORY, "Out of video memory")
+        CHK_ERR(D3DERR_INVALIDDEVICE, "Invalid device")
+        CHK_ERR(D3DERR_INVALIDCALL, "Invalid call")
+        CHK_ERR(D3DERR_DRIVERINVALIDCALL, "Driver invalid call")
+        //CHK_ERR(D3DERR_WASSTILLDRAWING, "Was Still Drawing")
+        CHK_ERR(D3DOK_NOAUTOGEN, "The call succeeded but there won't be any mipmaps generated")
+
+	    // Extended for Windows Vista
+	    CHK_ERR(D3DERR_DEVICEREMOVED, "Hardware device was removed")
+	    CHK_ERR(S_NOT_RESIDENT, "Resource not resident in memory")
+	    CHK_ERR(S_RESIDENT_IN_SHARED_MEMORY, "Resource resident in shared memory")
+	    CHK_ERR(S_PRESENT_MODE_CHANGED, "Desktop display mode has changed")
+	    CHK_ERR(S_PRESENT_OCCLUDED, "Client window is occluded (minimized or other fullscreen)")
+	    CHK_ERR(D3DERR_DEVICEHUNG, "Hardware adapter reset by OS")
+
+        // Extended for Windows 7
+        CHK_ERR(D3DERR_UNSUPPORTEDOVERLAY, "Overlay is not supported" )
+        CHK_ERR(D3DERR_UNSUPPORTEDOVERLAYFORMAT, "Overlay format is not supported" )
+        CHK_ERR(D3DERR_CANNOTPROTECTCONTENT, "Contect protection not available" )
+        CHK_ERR(D3DERR_UNSUPPORTEDCRYPTO, "Unsupported cryptographic system" )
+        CHK_ERR(D3DERR_PRESENT_STATISTICS_DISJOINT, "Presentation statistics are disjoint" )
+
+
+// -------------------------------------------------------------
+// dsound.h error codes
+// -------------------------------------------------------------
+//      CHK_ERR(DS_OK, "")
+        CHK_ERR(DS_NO_VIRTUALIZATION, "The call succeeded, but we had to substitute the 3D algorithm")
+        CHK_ERR(DSERR_ALLOCATED, "The call failed because resources (such as a priority level) were already being used by another caller")
+        CHK_ERR(DSERR_CONTROLUNAVAIL, "The control (vol, pan, etc.) requested by the caller is not available")
+//      CHK_ERR(DSERR_INVALIDPARAM, "DSERR_INVALIDPARAM")
+        CHK_ERR(DSERR_INVALIDCALL, "This call is not valid for the current state of this object")
+//      CHK_ERR(DSERR_GENERIC, "DSERR_GENERIC")
+        CHK_ERR(DSERR_PRIOLEVELNEEDED, "The caller does not have the priority level required for the function to succeed")
+//      CHK_ERR(DSERR_OUTOFMEMORY, "Not enough free memory is available to complete the operation")
+        CHK_ERR(DSERR_BADFORMAT, "The specified WAVE format is not supported")
+//      CHK_ERR(DSERR_UNSUPPORTED, "DSERR_UNSUPPORTED")
+        CHK_ERR(DSERR_NODRIVER, "No sound driver is available for use")
+        CHK_ERR(DSERR_ALREADYINITIALIZED, "This object is already initialized")
+//      CHK_ERR(DSERR_NOAGGREGATION, "DSERR_NOAGGREGATION")
+        CHK_ERR(DSERR_BUFFERLOST, "The buffer memory has been lost, and must be restored")
+        CHK_ERR(DSERR_OTHERAPPHASPRIO, "Another app has a higher priority level, preventing this call from succeeding")
+        CHK_ERR(DSERR_UNINITIALIZED, "This object has not been initialized")
+//      CHK_ERR(DSERR_NOINTERFACE, "DSERR_NOINTERFACE")
+//      CHK_ERR(DSERR_ACCESSDENIED, "DSERR_ACCESSDENIED")
+        CHK_ERR(DSERR_BUFFERTOOSMALL, "Tried to create a DSBCAPS_CTRLFX buffer shorter than DSBSIZE_FX_MIN milliseconds")
+        CHK_ERR(DSERR_DS8_REQUIRED, "Attempt to use DirectSound 8 functionality on an older DirectSound object")
+        CHK_ERR(DSERR_SENDLOOP, "A circular loop of send effects was detected")
+        CHK_ERR(DSERR_BADSENDBUFFERGUID, "The GUID specified in an audiopath file does not match a valid MIXIN buffer")
+        CHK_ERR(DSERR_OBJECTNOTFOUND, "The object requested was not found (numerically equal to DMUS_E_NOT_FOUND)")
+
+        CHK_ERR(DSERR_FXUNAVAILABLE, "Requested effects are not available")
+
+#endif // !WINAPI_FAMILY || WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP
+
+// -------------------------------------------------------------
+// d3d10.h error codes
+// -------------------------------------------------------------
+        CHK_ERR(D3D10_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS, "There are too many unique state objects.")
+        CHK_ERR(D3D10_ERROR_FILE_NOT_FOUND, "File not found")
+
+// -------------------------------------------------------------
+// dxgi.h error codes
+// -------------------------------------------------------------
+        CHK_ERR(DXGI_STATUS_OCCLUDED, "The target window or output has been occluded. The application should suspend rendering operations if possible.")
+        CHK_ERR(DXGI_STATUS_CLIPPED, "Target window is clipped.")
+        CHK_ERR(DXGI_STATUS_NO_REDIRECTION, "")
+        CHK_ERR(DXGI_STATUS_NO_DESKTOP_ACCESS, "No access to desktop.")
+        CHK_ERR(DXGI_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE, "")
+        CHK_ERR(DXGI_STATUS_MODE_CHANGED, "Display mode has changed")
+        CHK_ERR(DXGI_STATUS_MODE_CHANGE_IN_PROGRESS, "Display mode is changing")
+        CHK_ERR(DXGI_ERROR_INVALID_CALL, "The application has made an erroneous API call that it had enough information to avoid. This error is intended to denote that the application should be altered to avoid the error. Use of the debug version of the DXGI.DLL will provide run-time debug output with further information.")
+        CHK_ERR(DXGI_ERROR_NOT_FOUND, "The item requested was not found. For GetPrivateData calls, this means that the specified GUID had not been previously associated with the object.")
+        CHK_ERR(DXGI_ERROR_MORE_DATA, "The specified size of the destination buffer is too small to hold the requested data.")
+        CHK_ERR(DXGI_ERROR_UNSUPPORTED, "Unsupported.")
+        CHK_ERR(DXGI_ERROR_DEVICE_REMOVED, "Hardware device removed.")
+        CHK_ERR(DXGI_ERROR_DEVICE_HUNG, "Device hung due to badly formed commands.")
+        CHK_ERR(DXGI_ERROR_DEVICE_RESET, "Device reset due to a badly formed commant.")
+        CHK_ERR(DXGI_ERROR_WAS_STILL_DRAWING, "Was still drawing.")
+        CHK_ERR(DXGI_ERROR_FRAME_STATISTICS_DISJOINT, "The requested functionality is not supported by the device or the driver.")
+        CHK_ERR(DXGI_ERROR_GRAPHICS_VIDPN_SOURCE_IN_USE, "The requested functionality is not supported by the device or the driver.")
+        CHK_ERR(DXGI_ERROR_DRIVER_INTERNAL_ERROR, "An internal driver error occurred.")
+        CHK_ERR(DXGI_ERROR_NONEXCLUSIVE, "The application attempted to perform an operation on an DXGI output that is only legal after the output has been claimed for exclusive owenership.")
+        CHK_ERR(DXGI_ERROR_NOT_CURRENTLY_AVAILABLE, "The requested functionality is not supported by the device or the driver.")
+        CHK_ERR(DXGI_ERROR_REMOTE_CLIENT_DISCONNECTED, "Remote desktop client disconnected.")
+        CHK_ERR(DXGI_ERROR_REMOTE_OUTOFMEMORY, "Remote desktop client is out of memory.")
+
+// -------------------------------------------------------------
+// d3d11.h error codes
+// -------------------------------------------------------------
+        CHK_ERR(D3D11_ERROR_TOO_MANY_UNIQUE_STATE_OBJECTS, "There are too many unique state objects.")
+        CHK_ERR(D3D11_ERROR_FILE_NOT_FOUND, "File not found")
+        CHK_ERR(D3D11_ERROR_TOO_MANY_UNIQUE_VIEW_OBJECTS, "Therea are too many unique view objects.")
+        CHK_ERR(D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD, "Deferred context requires Map-Discard usage pattern")
+
+#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
+
+// -------------------------------------------------------------
+// Direct2D error codes
+// -------------------------------------------------------------
+//        CHK_ERR(D2DERR_UNSUPPORTED_PIXEL_FORMAT, "The pixel format is not supported.")
+//        CHK_ERR(D2DERR_INSUFFICIENT_BUFFER, "The supplied buffer was too small to accomodate the data.")
+        CHK_ERR(D2DERR_WRONG_STATE, "The object was not in the correct state to process the method.")
+        CHK_ERR(D2DERR_NOT_INITIALIZED, "The object has not yet been initialized.")
+        CHK_ERR(D2DERR_UNSUPPORTED_OPERATION, "The requested opertion is not supported.")
+        CHK_ERR(D2DERR_SCANNER_FAILED, "The geomery scanner failed to process the data.")
+        CHK_ERR(D2DERR_SCREEN_ACCESS_DENIED, "D2D could not access the screen.")
+        CHK_ERR(D2DERR_DISPLAY_STATE_INVALID, "A valid display state could not be determined.")
+        CHK_ERR(D2DERR_ZERO_VECTOR, "The supplied vector is zero.")
+        CHK_ERR(D2DERR_INTERNAL_ERROR, "An internal error (D2D bug) occurred. On checked builds, we would assert.")
+        CHK_ERR(D2DERR_DISPLAY_FORMAT_NOT_SUPPORTED, "The display format we need to render is not supported by the hardware device.")
+        CHK_ERR(D2DERR_INVALID_CALL, "A call to this method is invalid.")
+        CHK_ERR(D2DERR_NO_HARDWARE_DEVICE, "No HW rendering device is available for this operation.")
+        CHK_ERR(D2DERR_RECREATE_TARGET, "here has been a presentation error that may be recoverable. The caller needs to recreate, rerender the entire frame, and reattempt present.")
+        CHK_ERR(D2DERR_TOO_MANY_SHADER_ELEMENTS, "Shader construction failed because it was too complex.")
+        CHK_ERR(D2DERR_SHADER_COMPILE_FAILED, "Shader compilation failed.")
+        CHK_ERR(D2DERR_MAX_TEXTURE_SIZE_EXCEEDED, "Requested DX surface size exceeded maximum texture size.")
+        CHK_ERR(D2DERR_UNSUPPORTED_VERSION, "The requested D2D version is not supported.")
+        CHK_ERR(D2DERR_BAD_NUMBER, "Invalid number.")
+        CHK_ERR(D2DERR_WRONG_FACTORY, "Objects used together must be created from the same factory instance.")
+        CHK_ERR(D2DERR_LAYER_ALREADY_IN_USE, "A layer resource can only be in use once at any point in time.")
+        CHK_ERR(D2DERR_POP_CALL_DID_NOT_MATCH_PUSH, "The pop call did not match the corresponding push call")
+//        CHK_ERR(D2DERR_WRONG_RESOURCE_DOMAIN, "The resource was realized on the wrong render target")
+        CHK_ERR(D2DERR_PUSH_POP_UNBALANCED, "The push and pop calls were unbalanced")
+        CHK_ERR(D2DERR_RENDER_TARGET_HAS_LAYER_OR_CLIPRECT, "Attempt to copy from a render target while a layer or clip rect is applied")
+        CHK_ERR(D2DERR_INCOMPATIBLE_BRUSH_TYPES, "The brush types are incompatible for the call.")
+        CHK_ERR(D2DERR_WIN32_ERROR, "An unknown win32 failure occurred.")
+        CHK_ERR(D2DERR_TARGET_NOT_GDI_COMPATIBLE, "The render target is not compatible with GDI")
+        CHK_ERR(D2DERR_TEXT_EFFECT_IS_WRONG_TYPE, "A text client drawing effect object is of the wrong type")
+        CHK_ERR(D2DERR_TEXT_RENDERER_NOT_RELEASED, "The application is holding a reference to the IDWriteTextRenderer interface after the corresponding DrawText or DrawTextLayout call has returned. The IDWriteTextRenderer instance will be zombied.")
+//        CHK_ERR(D2DERR_EXCEEDS_MAX_BITMAP_SIZE, "The requested size is larger than the guaranteed supported texture size.")
+
+// -------------------------------------------------------------
+// DirectWrite error codes
+// -------------------------------------------------------------
+        CHK_ERR(DWRITE_E_FILEFORMAT, "Indicates an error in an input file such as a font file.")
+        CHK_ERR(DWRITE_E_UNEXPECTED, "Indicates an error originating in DirectWrite code, which is not expected to occur but is safe to recover from.")
+        CHK_ERR(DWRITE_E_NOFONT, "Indicates the specified font does not exist.")
+        CHK_ERR(DWRITE_E_FILENOTFOUND, "A font file could not be opened because the file, directory, network location, drive, or other storage location does not exist or is unavailable.")
+        CHK_ERR(DWRITE_E_FILEACCESS, "A font file exists but could not be opened due to access denied, sharing violation, or similar error.")
+        CHK_ERR(DWRITE_E_FONTCOLLECTIONOBSOLETE, "A font collection is obsolete due to changes in the system.")
+        CHK_ERR(DWRITE_E_ALREADYREGISTERED, "The given interface is already registered.")
+
+// -------------------------------------------------------------
+// WIC error codes
+// -------------------------------------------------------------
+        CHK_ERR(WINCODEC_ERR_WRONGSTATE, "WIC object in incorrect state.")
+        CHK_ERR(WINCODEC_ERR_VALUEOUTOFRANGE, "WIC Value out of range.")
+        CHK_ERR(WINCODEC_ERR_UNKNOWNIMAGEFORMAT, "Encountered unexpected value or setting in WIC image format.")
+        CHK_ERR(WINCODEC_ERR_UNSUPPORTEDVERSION, "Unsupported WINCODEC_SD_VERSION passed to WIC factory.")
+        CHK_ERR(WINCODEC_ERR_NOTINITIALIZED, "WIC component not initialized.")
+        CHK_ERR(WINCODEC_ERR_ALREADYLOCKED, "WIC bitmap object already locked.")
+        CHK_ERR(WINCODEC_ERR_PROPERTYNOTFOUND, "WIC property not found.")
+        CHK_ERR(WINCODEC_ERR_PROPERTYNOTSUPPORTED, "WIC property not supported.")
+        CHK_ERR(WINCODEC_ERR_PROPERTYSIZE, "Invalid property size")
+        CHK_ERRA(WINCODEC_ERR_CODECPRESENT) // not currently used by WIC
+        CHK_ERRA(WINCODEC_ERR_CODECNOTHUMBNAIL) // not currently used by WIC
+        CHK_ERR(WINCODEC_ERR_PALETTEUNAVAILABLE, "Required palette data not available.")
+        CHK_ERR(WINCODEC_ERR_CODECTOOMANYSCANLINES, "More scanlines requested than are available in WIC bitmap.")
+        CHK_ERR(WINCODEC_ERR_INTERNALERROR, "Unexpected internal error in WIC.")
+        CHK_ERR(WINCODEC_ERR_SOURCERECTDOESNOTMATCHDIMENSIONS, "Source WIC rectangle does not match bitmap dimensions.")
+        CHK_ERR(WINCODEC_ERR_COMPONENTNOTFOUND, "WIC component not found.")
+        CHK_ERR(WINCODEC_ERR_IMAGESIZEOUTOFRANGE, "Image size beyond expected boundaries for WIC codec." )
+        CHK_ERR(WINCODEC_ERR_TOOMUCHMETADATA, "Image metadata size beyond expected boundaries for WIC codec.")
+        CHK_ERR(WINCODEC_ERR_BADIMAGE, "WIC image is corrupted.")
+        CHK_ERR(WINCODEC_ERR_BADHEADER, "Invalid header found in WIC image.")
+        CHK_ERR(WINCODEC_ERR_FRAMEMISSING, "Expected bitmap frame data not found in WIC image." )
+        CHK_ERR(WINCODEC_ERR_BADMETADATAHEADER, "Invalid metadata header found in WIC image.")
+        CHK_ERR(WINCODEC_ERR_BADSTREAMDATA, "Invalid stream data found in WIC image.")
+        CHK_ERR(WINCODEC_ERR_STREAMWRITE, "WIC operation on write stream failed.")
+        CHK_ERR(WINCODEC_ERR_STREAMREAD, "WIC operation on read stream failed.")
+        CHK_ERR(WINCODEC_ERR_STREAMNOTAVAILABLE, "Required stream is not available." )
+        CHK_ERR(WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT, "The pixel format is not supported.")
+        CHK_ERR(WINCODEC_ERR_UNSUPPORTEDOPERATION, "This operation is not supported by WIC." )
+        CHK_ERR(WINCODEC_ERR_INVALIDREGISTRATION, "Error occurred reading WIC codec registry keys.")
+        CHK_ERR(WINCODEC_ERR_COMPONENTINITIALIZEFAILURE, "Failed initializing WIC codec.")
+        CHK_ERR(WINCODEC_ERR_INSUFFICIENTBUFFER, "Not enough buffer space available for WIC operation.")
+        CHK_ERR(WINCODEC_ERR_DUPLICATEMETADATAPRESENT, "Duplicate metadata detected in WIC image.")
+        CHK_ERR(WINCODEC_ERR_PROPERTYUNEXPECTEDTYPE, "Unexpected property type in WIC image.")
+        CHK_ERR(WINCODEC_ERR_UNEXPECTEDSIZE, "Unexpected value size in WIC metadata.")
+        CHK_ERR(WINCODEC_ERR_INVALIDQUERYREQUEST, "Invalid metadata query.")
+        CHK_ERR(WINCODEC_ERR_UNEXPECTEDMETADATATYPE, "Unexpected metadata type encountered in WIC image.")
+        CHK_ERR(WINCODEC_ERR_REQUESTONLYVALIDATMETADATAROOT, "Operation only valid on meatadata root.")
+        CHK_ERR(WINCODEC_ERR_INVALIDQUERYCHARACTER, "Invalid character in WIC metadata query.")
+        CHK_ERR(WINCODEC_ERR_WIN32ERROR, "General Win32 error encountered during WIC operation.")
+        CHK_ERR(WINCODEC_ERR_INVALIDPROGRESSIVELEVEL, "Invalid level for progressive WIC image decode.")
+
+#endif // !WINAPI_FAMILY || WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
+
+// -------------------------------------------------------------
+// DXUT error codes
+// -------------------------------------------------------------
+        CHK_ERR(DXUTERR_NODIRECT3D, "Could not initialize Direct3D.")
+        CHK_ERR(DXUTERR_NOCOMPATIBLEDEVICES, "No device could be found with the specified device settings.")
+        CHK_ERR(DXUTERR_MEDIANOTFOUND, "A media file could not be found.")
+        CHK_ERR(DXUTERR_NONZEROREFCOUNT, "The device interface has a non-zero reference count, meaning that some objects were not released.")
+        CHK_ERR(DXUTERR_CREATINGDEVICE, "An error occurred when attempting to create a device.")
+        CHK_ERR(DXUTERR_RESETTINGDEVICE, "An error occurred when attempting to reset a device.")
+        CHK_ERR(DXUTERR_CREATINGDEVICEOBJECTS, "An error occurred in the device create callback function.")
+        CHK_ERR(DXUTERR_RESETTINGDEVICEOBJECTS, "An error occurred in the device reset callback function.")
+        CHK_ERR(DXUTERR_INCORRECTVERSION, "Incorrect version of Direct3D or D3DX.")
+        CHK_ERR(DXUTERR_DEVICEREMOVED, "The device was removed.")
+
+// -------------------------------------------------------------
+// xaudio2.h error codes
+// -------------------------------------------------------------
+        CHK_ERR(XAUDIO2_E_INVALID_CALL, "Invalid XAudio2 API call or arguments")
+        CHK_ERR(XAUDIO2_E_XMA_DECODER_ERROR, "Hardware XMA decoder error")
+        CHK_ERR(XAUDIO2_E_XAPO_CREATION_FAILED, "Failed to create an audio effect")
+        CHK_ERR(XAUDIO2_E_DEVICE_INVALIDATED, "Device invalidated (unplugged, disabled, etc)")
+
+// -------------------------------------------------------------
+// xapo.h error codes
+// -------------------------------------------------------------
+        CHK_ERR(XAPO_E_FORMAT_UNSUPPORTED, "Requested audio format unsupported.")
+    }
+}
+
+//-----------------------------------------------------------------------------
+HRESULT WINAPI DXTraceW( _In_z_ const WCHAR* strFile, _In_ DWORD dwLine, _In_ HRESULT hr,
+                         _In_opt_ const WCHAR* strMsg, _In_ bool bPopMsgBox )
+{
+    WCHAR strBufferLine[128];
+    WCHAR strBufferError[256];
+    WCHAR strBuffer[BUFFER_SIZE];
+
+    swprintf_s( strBufferLine, 128, L"%lu", dwLine );
+    if( strFile )
+    {
+       swprintf_s( strBuffer, BUFFER_SIZE, L"%ls(%ls): ", strFile, strBufferLine );
+       OutputDebugStringW( strBuffer );
+    }
+
+    size_t nMsgLen = (strMsg) ? wcsnlen_s( strMsg, 1024 ) : 0;
+    if( nMsgLen > 0 )
+    {
+        OutputDebugStringW( strMsg );
+        OutputDebugStringW( L" " );
+    }
+
+    swprintf_s( strBufferError, 256, L"%ls (0x%0.8x)", DXGetErrorStringW(hr), hr );
+    swprintf_s( strBuffer, BUFFER_SIZE, L"hr=%ls", strBufferError );
+    OutputDebugStringW( strBuffer );
+
+    OutputDebugStringW( L"\n" );
+
+#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)
+    if( bPopMsgBox )
+    {
+        WCHAR strBufferFile[MAX_PATH];
+        wcscpy_s( strBufferFile, MAX_PATH, L"" );
+        if( strFile )
+            wcscpy_s( strBufferFile, MAX_PATH, strFile );
+
+        WCHAR strBufferMsg[1024];
+        wcscpy_s( strBufferMsg, 1024, L"" );
+        if( nMsgLen > 0 )
+            swprintf_s( strBufferMsg, 1024, L"Calling: %ls\n", strMsg );
+
+        swprintf_s( strBuffer, BUFFER_SIZE, L"File: %ls\nLine: %ls\nError Code: %ls\n%lsDo you want to debug the application?",
+                    strBufferFile, strBufferLine, strBufferError, strBufferMsg );
+
+        int nResult = MessageBoxW( GetForegroundWindow(), strBuffer, L"Unexpected error encountered", MB_YESNO | MB_ICONERROR );
+        if( nResult == IDYES )
+            DebugBreak();
+    }
+#else
+    UNREFERENCED_PARAMETER(bPopMsgBox);
+#endif
+
+    return hr;
+}
\ No newline at end of file
diff --git a/xbmc/platform/win32/dxerr.h b/xbmc/platform/win32/dxerr.h
new file mode 100644
index 0000000..52e674c
--- /dev/null
+++ b/xbmc/platform/win32/dxerr.h
@@ -0,0 +1,80 @@
+//--------------------------------------------------------------------------------------
+// File: DXErr.h
+//
+// DirectX Error Library
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//--------------------------------------------------------------------------------------
+
+// This version only supports UNICODE.
+
+#pragma once
+
+#if !defined(NOMINMAX)
+#define NOMINMAX
+#endif
+
+#include <windows.h>
+#include <sal.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//--------------------------------------------------------------------------------------
+// DXGetErrorString
+//--------------------------------------------------------------------------------------
+const WCHAR* WINAPI DXGetErrorStringW( _In_ HRESULT hr );
+
+#define DXGetErrorString DXGetErrorStringW
+
+//--------------------------------------------------------------------------------------
+// DXGetErrorDescription has to be modified to return a copy in a buffer rather than
+// the original static string.
+//--------------------------------------------------------------------------------------
+void WINAPI DXGetErrorDescriptionW( _In_ HRESULT hr, _Out_cap_(count) WCHAR* desc, _In_ size_t count );
+
+#define DXGetErrorDescription DXGetErrorDescriptionW
+
+//--------------------------------------------------------------------------------------
+//  DXTrace
+//
+//  Desc:  Outputs a formatted error message to the debug stream
+//
+//  Args:  WCHAR* strFile   The current file, typically passed in using the 
+//                         __FILEW__ macro.
+//         DWORD dwLine    The current line number, typically passed in using the 
+//                         __LINE__ macro.
+//         HRESULT hr      An HRESULT that will be traced to the debug stream.
+//         CHAR* strMsg    A string that will be traced to the debug stream (may be NULL)
+//         BOOL bPopMsgBox If TRUE, then a message box will popup also containing the passed info.
+//
+//  Return: The hr that was passed in.  
+//--------------------------------------------------------------------------------------
+HRESULT WINAPI DXTraceW( _In_z_ const WCHAR* strFile, _In_ DWORD dwLine, _In_ HRESULT hr, _In_opt_ const WCHAR* strMsg, _In_ bool bPopMsgBox );
+
+#define DXTrace DXTraceW
+
+//--------------------------------------------------------------------------------------
+//
+// Helper macros
+//
+//--------------------------------------------------------------------------------------
+#if defined(DEBUG) || defined(_DEBUG)
+#define DXTRACE_MSG(str)              DXTrace( __FILEW__, (DWORD)__LINE__, 0, str, false )
+#define DXTRACE_ERR(str,hr)           DXTrace( __FILEW__, (DWORD)__LINE__, hr, str, false )
+#define DXTRACE_ERR_MSGBOX(str,hr)    DXTrace( __FILEW__, (DWORD)__LINE__, hr, str, true )
+#else
+#define DXTRACE_MSG(str)              (0L)
+#define DXTRACE_ERR(str,hr)           (hr)
+#define DXTRACE_ERR_MSGBOX(str,hr)    (hr)
+#endif
+
+#ifdef __cplusplus
+}
+#endif //__cplusplus
diff --git a/xbmc/platform/win32/git_revision.t b/xbmc/platform/win32/git_revision.t
new file mode 100644
index 0000000..ac57f1a
--- /dev/null
+++ b/xbmc/platform/win32/git_revision.t
@@ -0,0 +1 @@
+/* custombuild trigger only to generate \git_revision.h */
\ No newline at end of file
diff --git a/xbmc/utils/Crc32.h b/xbmc/platform/win32/my_ntddcdrm.h
similarity index 61%
copy from xbmc/utils/Crc32.h
copy to xbmc/platform/win32/my_ntddcdrm.h
index 3d30c8f..45d876b 100644
--- a/xbmc/utils/Crc32.h
+++ b/xbmc/platform/win32/my_ntddcdrm.h
@@ -1,3 +1,6 @@
+#ifndef MY_NTDDCDRM_H
+#define MY_NTDDCDRM_H
+
 /*
  *      Copyright (C) 2005-2013 Team XBMC
  *      http://xbmc.org
@@ -18,26 +21,21 @@
  *
  */
 
-#pragma once
+#define IOCTL_CDROM_BASE             FILE_DEVICE_CD_ROM
+#define IOCTL_CDROM_RAW_READ         CTL_CODE(IOCTL_CDROM_BASE, 0x000F, METHOD_OUT_DIRECT,  FILE_READ_ACCESS)
 
-#include <string>
-#include <stdint.h>
+typedef enum _TRACK_MODE_TYPE {
+  YellowMode2,
+  XAForm2,
+  CDDA
+} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE;
 
-class Crc32
+typedef struct __RAW_READ_INFO
 {
-public:
-  Crc32();
-  void Reset();
-  void Compute(const char* buffer, size_t count);
-  void Compute(const std::string& strValue);
-  void ComputeFromLowerCase(const std::string& strValue);
-
-  operator uint32_t () const
-  {
-    return m_crc;
-  }
-
-private:
-  uint32_t m_crc;
-};
+  LARGE_INTEGER DiskOffset;
+  ULONG SectorCount;
+  TRACK_MODE_TYPE TrackMode;
+}
+RAW_READ_INFO, *PRAW_READ_INFO;
 
+#endif
\ No newline at end of file
diff --git a/xbmc/platform/win32/my_ntddscsi.h b/xbmc/platform/win32/my_ntddscsi.h
new file mode 100644
index 0000000..f3a679b
--- /dev/null
+++ b/xbmc/platform/win32/my_ntddscsi.h
@@ -0,0 +1,75 @@
+#ifndef MY_NTDDSCSI_H
+#define MY_NTDDSCSI_H
+
+/*
+ *      Copyright (C) 2005-2013 Team XBMC
+ *      http://xbmc.org
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+//** Defines taken from ntddscsi.h in MS Windows DDK CD
+#define SCSI_IOCTL_DATA_OUT             0 //Give data to SCSI device (e.g. for writing)
+#define SCSI_IOCTL_DATA_IN              1 //Get data from SCSI device (e.g. for reading)
+#define SCSI_IOCTL_DATA_UNSPECIFIED     2 //No data (e.g. for ejecting)
+
+#define MAX_SENSE_LEN 18 //Sense data max length
+
+#define IOCTL_SCSI_PASS_THROUGH         0x4D004
+typedef struct _SCSI_PASS_THROUGH {
+    USHORT Length;
+    UCHAR ScsiStatus;
+    UCHAR PathId;
+    UCHAR TargetId;
+    UCHAR Lun;
+    UCHAR CdbLength;
+    UCHAR SenseInfoLength;
+    UCHAR DataIn;
+    ULONG DataTransferLength;
+    ULONG TimeOutValue;
+    ULONG_PTR DataBufferOffset;
+    ULONG SenseInfoOffset;
+    UCHAR Cdb[16];
+}SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH;
+
+#define IOCTL_SCSI_PASS_THROUGH_DIRECT  0x4D014
+typedef struct _SCSI_PASS_THROUGH_DIRECT {
+    USHORT Length;
+    UCHAR ScsiStatus;
+    UCHAR PathId;
+    UCHAR TargetId;
+    UCHAR Lun;
+    UCHAR CdbLength;
+    UCHAR SenseInfoLength;
+    UCHAR DataIn;
+    ULONG DataTransferLength;
+    ULONG TimeOutValue;
+    PVOID DataBuffer;
+    ULONG SenseInfoOffset;
+    UCHAR Cdb[16];
+}SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
+//** End of defines taken from ntddscsi.h from MS Windows DDK CD
+
+typedef struct _SCSI_PASS_THROUGH_AND_BUFFERS {
+    SCSI_PASS_THROUGH spt;
+    BYTE DataBuffer[64*1024];
+}T_SPT_BUFS;
+
+typedef struct _SCSI_PASS_THROUGH_DIRECT_AND_SENSE_BUFFER {
+    SCSI_PASS_THROUGH_DIRECT sptd;
+    UCHAR SenseBuf[MAX_SENSE_LEN];
+}T_SPDT_SBUF;
+#endif
\ No newline at end of file
diff --git a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h b/xbmc/platform/win32/netdb.h
similarity index 71%
copy from xbmc/cores/VideoPlayer/Process/ProcessInfo.h
copy to xbmc/platform/win32/netdb.h
index b8a4e46..c3c3b62 100644
--- a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h
+++ b/xbmc/platform/win32/netdb.h
@@ -1,5 +1,5 @@
 /*
- *      Copyright (C) 2005-2016 Team XBMC
+ *      Copyright (C) 2011-2013 Team XBMC
  *      http://xbmc.org
  *
  *  This Program is free software; you can redistribute it and/or modify
@@ -18,17 +18,4 @@
  *
  */
 #pragma once
-
-#include "cores/IPlayer.h"
-
-class CProcessInfo
-{
-public:
-  static CProcessInfo* CreateInstance();
-  virtual ~CProcessInfo();
-  virtual EINTERLACEMETHOD GetFallbackDeintMethod();
-  virtual bool AllowDTSHDDecode();
-
-protected:
-  CProcessInfo();
-};
+#include <sys/socket.h>
diff --git a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h b/xbmc/platform/win32/netinet/in.h
similarity index 71%
copy from xbmc/cores/VideoPlayer/Process/ProcessInfo.h
copy to xbmc/platform/win32/netinet/in.h
index b8a4e46..c3c3b62 100644
--- a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h
+++ b/xbmc/platform/win32/netinet/in.h
@@ -1,5 +1,5 @@
 /*
- *      Copyright (C) 2005-2016 Team XBMC
+ *      Copyright (C) 2011-2013 Team XBMC
  *      http://xbmc.org
  *
  *  This Program is free software; you can redistribute it and/or modify
@@ -18,17 +18,4 @@
  *
  */
 #pragma once
-
-#include "cores/IPlayer.h"
-
-class CProcessInfo
-{
-public:
-  static CProcessInfo* CreateInstance();
-  virtual ~CProcessInfo();
-  virtual EINTERLACEMETHOD GetFallbackDeintMethod();
-  virtual bool AllowDTSHDDecode();
-
-protected:
-  CProcessInfo();
-};
+#include <sys/socket.h>
diff --git a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h b/xbmc/platform/win32/netinet/tcp.h
similarity index 71%
copy from xbmc/cores/VideoPlayer/Process/ProcessInfo.h
copy to xbmc/platform/win32/netinet/tcp.h
index b8a4e46..c3c3b62 100644
--- a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h
+++ b/xbmc/platform/win32/netinet/tcp.h
@@ -1,5 +1,5 @@
 /*
- *      Copyright (C) 2005-2016 Team XBMC
+ *      Copyright (C) 2011-2013 Team XBMC
  *      http://xbmc.org
  *
  *  This Program is free software; you can redistribute it and/or modify
@@ -18,17 +18,4 @@
  *
  */
 #pragma once
-
-#include "cores/IPlayer.h"
-
-class CProcessInfo
-{
-public:
-  static CProcessInfo* CreateInstance();
-  virtual ~CProcessInfo();
-  virtual EINTERLACEMETHOD GetFallbackDeintMethod();
-  virtual bool AllowDTSHDDecode();
-
-protected:
-  CProcessInfo();
-};
+#include <sys/socket.h>
diff --git a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h b/xbmc/platform/win32/pch.cpp
similarity index 69%
copy from xbmc/cores/VideoPlayer/Process/ProcessInfo.h
copy to xbmc/platform/win32/pch.cpp
index b8a4e46..743e07c 100644
--- a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h
+++ b/xbmc/platform/win32/pch.cpp
@@ -1,5 +1,5 @@
 /*
- *      Copyright (C) 2005-2016 Team XBMC
+ *      Copyright (C) 2009-2013 Team XBMC
  *      http://xbmc.org
  *
  *  This Program is free software; you can redistribute it and/or modify
@@ -17,18 +17,4 @@
  *  <http://www.gnu.org/licenses/>.
  *
  */
-#pragma once
-
-#include "cores/IPlayer.h"
-
-class CProcessInfo
-{
-public:
-  static CProcessInfo* CreateInstance();
-  virtual ~CProcessInfo();
-  virtual EINTERLACEMETHOD GetFallbackDeintMethod();
-  virtual bool AllowDTSHDDecode();
-
-protected:
-  CProcessInfo();
-};
+#include "pch.h"
\ No newline at end of file
diff --git a/xbmc/guilib/TextureBundle.h b/xbmc/platform/win32/pch.h
similarity index 51%
copy from xbmc/guilib/TextureBundle.h
copy to xbmc/platform/win32/pch.h
index 67d62b4..4ab4dbc 100644
--- a/xbmc/guilib/TextureBundle.h
+++ b/xbmc/platform/win32/pch.h
@@ -1,7 +1,5 @@
-#pragma once
-
 /*
- *      Copyright (C) 2005-2013 Team XBMC
+ *      Copyright (C) 2009-2013 Team XBMC
  *      http://xbmc.org
  *
  *  This Program is free software; you can redistribute it and/or modify
@@ -19,30 +17,35 @@
  *  <http://www.gnu.org/licenses/>.
  *
  */
-
-#include <string>
+#pragma once
+#define _CRT_RAND_S
 #include <vector>
-#include "TextureBundleXBT.h"
-
-class CTextureBundle
-{
-public:
-  CTextureBundle();
-  ~CTextureBundle() = default;
-
-  void SetThemeBundle(bool themeBundle);
-  bool HasFile(const std::string& Filename);
-  void GetTexturesFromPath(const std::string &path, std::vector<std::string> &textures);
-  static std::string Normalize(const std::string &name);
-
-  bool LoadTexture(const std::string& Filename, CBaseTexture** ppTexture, int &width, int &height);
-
-  int LoadAnim(const std::string& Filename, CBaseTexture*** ppTextures, int &width, int &height, int& nLoops, int** ppDelays);
-
-private:
-  CTextureBundleXBT m_tbXBT;
-
-  bool m_useXBT;
-};
-
-
+#include <map>
+#include <string>
+#include <iostream>
+#include <fstream>
+#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H))
+#include <winsock2.h>
+#endif
+#include <windows.h>
+#include <mmsystem.h>
+#include <TCHAR.H>
+#include <locale>
+#include <comdef.h>
+#define DIRECTINPUT_VERSION 0x0800
+#include "DInput.h"
+#include "DSound.h"
+#ifdef HAS_DX
+#include "d3d9.h"
+#include "d3d11_1.h"
+#include "dxgi.h"
+#include "d3dcompiler.h"
+#include "directxmath.h"
+#include "directxcolors.h" 
+#else
+#include <d3d9types.h>
+#endif
+#include <memory>
+// anything below here should be headers that very rarely (hopefully never)
+// change yet are included almost everywhere.
+/* empty */
diff --git a/xbmc/utils/Crc32.h b/xbmc/platform/win32/resource.h
similarity index 66%
copy from xbmc/utils/Crc32.h
copy to xbmc/platform/win32/resource.h
index 3d30c8f..b8390a5 100644
--- a/xbmc/utils/Crc32.h
+++ b/xbmc/platform/win32/resource.h
@@ -18,26 +18,16 @@
  *
  */
 
-#pragma once
-
-#include <string>
-#include <stdint.h>
-
-class Crc32
-{
-public:
-  Crc32();
-  void Reset();
-  void Compute(const char* buffer, size_t count);
-  void Compute(const std::string& strValue);
-  void ComputeFromLowerCase(const std::string& strValue);
-
-  operator uint32_t () const
-  {
-    return m_crc;
-  }
-
-private:
-  uint32_t m_crc;
-};
+#define IDI_MAIN_ICON                   100
 
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC                     1
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h b/xbmc/platform/win32/stat_utf8.cpp
similarity index 70%
copy from xbmc/cores/VideoPlayer/Process/ProcessInfo.h
copy to xbmc/platform/win32/stat_utf8.cpp
index b8a4e46..c7e5ed3 100644
--- a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h
+++ b/xbmc/platform/win32/stat_utf8.cpp
@@ -1,5 +1,5 @@
 /*
- *      Copyright (C) 2005-2016 Team XBMC
+ *      Copyright (C) 2005-2013 Team XBMC
  *      http://xbmc.org
  *
  *  This Program is free software; you can redistribute it and/or modify
@@ -17,18 +17,14 @@
  *  <http://www.gnu.org/licenses/>.
  *
  */
-#pragma once
 
-#include "cores/IPlayer.h"
+#include "stat_utf8.h"
+#include "utils/CharsetConverter.h"
 
-class CProcessInfo
+int stat64_utf8(const char* __file, struct stat64* __buf)
 {
-public:
-  static CProcessInfo* CreateInstance();
-  virtual ~CProcessInfo();
-  virtual EINTERLACEMETHOD GetFallbackDeintMethod();
-  virtual bool AllowDTSHDDecode();
+  std::wstring fileW;
+  g_charsetConverter.utf8ToW(__file, fileW, false);
+  return _wstat64(fileW.c_str(), __buf);
+}
 
-protected:
-  CProcessInfo();
-};
diff --git a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h b/xbmc/platform/win32/stat_utf8.h
similarity index 70%
copy from xbmc/cores/VideoPlayer/Process/ProcessInfo.h
copy to xbmc/platform/win32/stat_utf8.h
index b8a4e46..c888921 100644
--- a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h
+++ b/xbmc/platform/win32/stat_utf8.h
@@ -1,5 +1,5 @@
 /*
- *      Copyright (C) 2005-2016 Team XBMC
+ *      Copyright (C) 2005-2013 Team XBMC
  *      http://xbmc.org
  *
  *  This Program is free software; you can redistribute it and/or modify
@@ -17,18 +17,13 @@
  *  <http://www.gnu.org/licenses/>.
  *
  */
-#pragma once
 
-#include "cores/IPlayer.h"
+#ifndef STAT_UTF8_H__
+#define STAT_UTF8_H__
 
-class CProcessInfo
-{
-public:
-  static CProcessInfo* CreateInstance();
-  virtual ~CProcessInfo();
-  virtual EINTERLACEMETHOD GetFallbackDeintMethod();
-  virtual bool AllowDTSHDDecode();
+#define stat64 __stat64
+
+extern int stat64_utf8(const char* __file, struct stat64* __buf);
+
+#endif //STAT_UTF8_H__
 
-protected:
-  CProcessInfo();
-};
diff --git a/xbmc/platform/win32/stdio_utf8.cpp b/xbmc/platform/win32/stdio_utf8.cpp
new file mode 100644
index 0000000..5ff46a1
--- /dev/null
+++ b/xbmc/platform/win32/stdio_utf8.cpp
@@ -0,0 +1,46 @@
+/*
+ *      Copyright (C) 2005-2013 Team XBMC
+ *      http://xbmc.org
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "stdio_utf8.h"
+#include "utils/CharsetConverter.h"
+
+int remove_utf8(const char* __filename)
+{
+  std::wstring filenameW;
+  g_charsetConverter.utf8ToW(__filename, filenameW, false);
+  return ::DeleteFileW(filenameW.c_str()) ? 0 : -1;
+}
+
+int rename_utf8(const char* __old, const char* __new)
+{
+  std::wstring oldW, newW;
+  g_charsetConverter.utf8ToW(__old, oldW, false);
+  g_charsetConverter.utf8ToW(__new, newW, false);
+  return ::MoveFileW(oldW.c_str(), newW.c_str()) ? 0 : -1;
+}
+
+FILE* fopen64_utf8(const char* __filename, const char* __modes)
+{
+  std::wstring filenameW, modesW;
+  g_charsetConverter.utf8ToW(__filename, filenameW, false);
+  g_charsetConverter.utf8ToW(__modes, modesW, false);
+  return _wfopen(filenameW.c_str(), modesW.c_str());
+}
+
diff --git a/xbmc/music/MusicDbUrl.h b/xbmc/platform/win32/stdio_utf8.h
similarity index 68%
copy from xbmc/music/MusicDbUrl.h
copy to xbmc/platform/win32/stdio_utf8.h
index 12444f0..95d859e 100644
--- a/xbmc/music/MusicDbUrl.h
+++ b/xbmc/platform/win32/stdio_utf8.h
@@ -1,6 +1,5 @@
-#pragma once
 /*
- *      Copyright (C) 2012-2013 Team XBMC
+ *      Copyright (C) 2005-2013 Team XBMC
  *      http://xbmc.org
  *
  *  This Program is free software; you can redistribute it and/or modify
@@ -19,19 +18,14 @@
  *
  */
 
-#include <string>
+#ifndef STDIO_UTF8_H__
+#define STDIO_UTF8_H__
 
-#include "DbUrl.h"
+#include <cstdio>
 
-class CVariant;
+extern int   remove_utf8(const char* __filename);
+extern int   rename_utf8(const char* __old, const char* __new);
+extern FILE* fopen64_utf8(const char* __filename, const char* __modes);
 
-class CMusicDbUrl : public CDbUrl
-{
-public:
-  CMusicDbUrl();
-  virtual ~CMusicDbUrl();
+#endif // STDIO_UTF8_H__
 
-protected:
-  virtual bool parse();
-  virtual bool validateOption(const std::string &key, const CVariant &value);
-};
diff --git a/xbmc/platform/win32/strverscmp.cpp b/xbmc/platform/win32/strverscmp.cpp
new file mode 100644
index 0000000..9ebbbb3
--- /dev/null
+++ b/xbmc/platform/win32/strverscmp.cpp
@@ -0,0 +1,134 @@
+extern "C" {
+/* Compare strings while treating digits characters numerically.
+   Copyright (C) 1997, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jean-Franois Bignolles <bignolle at ecoledoc.ibp.fr>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with XBMC; see the file COPYING.  If not, see
+   <http://www.gnu.org/licenses/>.
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <ctype.h>
+
+/* states: S_N: normal, S_I: comparing integral part, S_F: comparing
+           fractional parts, S_Z: idem but with leading Zeroes only */
+#define S_N    0x0
+#define S_I    0x4
+#define S_F    0x8
+#define S_Z    0xC
+
+/* result_type: CMP: return diff; LEN: compare using len_diff/diff */
+#define CMP    2
+#define LEN    3
+
+
+/* ISDIGIT differs from isdigit, as follows:
+   - Its arg may be any int or unsigned int; it need not be an unsigned char.
+   - It's guaranteed to evaluate its argument exactly once.
+   - It's typically faster.
+   Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that
+   only '0' through '9' are digits.  Prefer ISDIGIT to isdigit unless
+   it's important to use the locale's definition of `digit' even when the
+   host does not conform to Posix.  */
+#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
+
+#undef __strverscmp
+#undef strverscmp
+
+#ifndef weak_alias
+# define __strverscmp strverscmp
+#endif
+
+/* Compare S1 and S2 as strings holding indices/version numbers,
+   returning less than, equal to or greater than zero if S1 is less than,
+   equal to or greater than S2 (for more info, see the texinfo doc).
+*/
+
+int
+__strverscmp (const char *s1, const char *s2)
+{
+  const unsigned char *p1 = (const unsigned char *) s1;
+  const unsigned char *p2 = (const unsigned char *) s2;
+  unsigned char c1, c2;
+  int state;
+  int diff;
+
+  /* Symbol(s)    0       [1-9]   others  (padding)
+     Transition   (10) 0  (01) d  (00) x  (11) -   */
+  static const unsigned int next_state[] =
+  {
+      /* state    x    d    0    - */
+      /* S_N */  S_N, S_I, S_Z, S_N,
+      /* S_I */  S_N, S_I, S_I, S_I,
+      /* S_F */  S_N, S_F, S_F, S_F,
+      /* S_Z */  S_N, S_F, S_Z, S_Z
+  };
+
+  static const int result_type[] =
+  {
+      /* state   x/x  x/d  x/0  x/-  d/x  d/d  d/0  d/-
+                 0/x  0/d  0/0  0/-  -/x  -/d  -/0  -/- */
+
+      /* S_N */  CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
+                 CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+      /* S_I */  CMP, -1,  -1,  CMP,  1,  LEN, LEN, CMP,
+                  1,  LEN, LEN, CMP, CMP, CMP, CMP, CMP,
+      /* S_F */  CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
+                 CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+      /* S_Z */  CMP,  1,   1,  CMP, -1,  CMP, CMP, CMP,
+                 -1,  CMP, CMP, CMP
+  };
+
+  if (p1 == p2)
+    return 0;
+
+  c1 = *p1++;
+  c2 = *p2++;
+  /* Hint: '0' is a digit too.  */
+  state = S_N | ((c1 == '0') + (ISDIGIT (c1) != 0));
+
+  while ((diff = c1 - c2) == 0 && c1 != '\0')
+    {
+      state = next_state[state];
+      c1 = *p1++;
+      c2 = *p2++;
+      state |= (c1 == '0') + (ISDIGIT (c1) != 0);
+    }
+
+  state = result_type[state << 2 | ((c2 == '0') + (ISDIGIT (c2) != 0))];
+
+  switch (state)
+    {
+    case CMP:
+      return diff;
+
+    case LEN:
+      while (ISDIGIT (*p1++))
+	if (!ISDIGIT (*p2++))
+	  return 1;
+
+      return ISDIGIT (*p2) ? -1 : diff;
+
+    default:
+      return state;
+    }
+}
+#ifdef weak_alias
+weak_alias (__strverscmp, strverscmp)
+#endif
+}
diff --git a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h b/xbmc/platform/win32/sys/select.h
similarity index 71%
copy from xbmc/cores/VideoPlayer/Process/ProcessInfo.h
copy to xbmc/platform/win32/sys/select.h
index b8a4e46..4d6cbf1 100644
--- a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h
+++ b/xbmc/platform/win32/sys/select.h
@@ -1,5 +1,6 @@
+#pragma once
 /*
- *      Copyright (C) 2005-2016 Team XBMC
+ *      Copyright (C) 2011-2013 Team XBMC
  *      http://xbmc.org
  *
  *  This Program is free software; you can redistribute it and/or modify
@@ -17,18 +18,4 @@
  *  <http://www.gnu.org/licenses/>.
  *
  */
-#pragma once
-
-#include "cores/IPlayer.h"
-
-class CProcessInfo
-{
-public:
-  static CProcessInfo* CreateInstance();
-  virtual ~CProcessInfo();
-  virtual EINTERLACEMETHOD GetFallbackDeintMethod();
-  virtual bool AllowDTSHDDecode();
-
-protected:
-  CProcessInfo();
-};
+#include <sys/socket.h>
diff --git a/xbmc/video/videosync/VideoSyncPi.h b/xbmc/platform/win32/sys/socket.h
similarity index 58%
copy from xbmc/video/videosync/VideoSyncPi.h
copy to xbmc/platform/win32/sys/socket.h
index 10a9fa8..c97170b 100644
--- a/xbmc/video/videosync/VideoSyncPi.h
+++ b/xbmc/platform/win32/sys/socket.h
@@ -1,6 +1,5 @@
-#pragma once
 /*
- *      Copyright (C) 2005-2014 Team XBMC
+ *      Copyright (C) 2011-2013 Team XBMC
  *      http://xbmc.org
  *
  *  This Program is free software; you can redistribute it and/or modify
@@ -18,24 +17,40 @@
  *  <http://www.gnu.org/licenses/>.
  *
  */
+#pragma once
+
+#include <Winsock2.h>
+#include <WS2tcpip.h>
+#include <ws2bth.h>
+
+#ifndef SHUT_RDWR
+#define SHUT_RDWR SD_BOTH
+#endif
+
+#ifndef SHUT_RD
+#define SHUT_RD SD_RECEIVE
+#endif
 
-#if defined(TARGET_RASPBERRY_PI)
+#ifndef SHUT_WR
+#define SHUT_WR SD_SEND
+#endif
 
-#include "video/videosync/VideoSync.h"
-#include "guilib/DispResource.h"
 
-class CVideoSyncPi : public CVideoSync, IDispResource
-{
-public:
-  CVideoSyncPi(CVideoReferenceClock *clock) : CVideoSync(clock) {};
-  virtual bool Setup(PUPDATECLOCK func);
-  virtual void Run(volatile bool& stop);
-  virtual void Cleanup();
-  virtual float GetFps();
-  virtual void OnResetDisplay();
+#ifndef AF_BTH
+#define AF_BTH          32
+#endif
 
-private:
-  volatile bool m_abort;
-};
+#ifndef BTHPROTO_RFCOMM
+#define BTHPROTO_RFCOMM 3
+#endif
 
+#ifndef AF_BLUETOOTH
+#define AF_BLUETOOTH AF_BTH
 #endif
+
+#ifndef BTPROTO_RFCOMM
+#define BTPROTO_RFCOMM BTHPROTO_RFCOMM
+#endif
+
+typedef int socklen_t;
+
diff --git a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h b/xbmc/platform/win32/sys/time.h
similarity index 71%
copy from xbmc/cores/VideoPlayer/Process/ProcessInfo.h
copy to xbmc/platform/win32/sys/time.h
index b8a4e46..e6c159d 100644
--- a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h
+++ b/xbmc/platform/win32/sys/time.h
@@ -1,5 +1,6 @@
+#pragma once
 /*
- *      Copyright (C) 2005-2016 Team XBMC
+ *      Copyright (C) 2011-2013 Team XBMC
  *      http://xbmc.org
  *
  *  This Program is free software; you can redistribute it and/or modify
@@ -17,18 +18,4 @@
  *  <http://www.gnu.org/licenses/>.
  *
  */
-#pragma once
-
-#include "cores/IPlayer.h"
-
-class CProcessInfo
-{
-public:
-  static CProcessInfo* CreateInstance();
-  virtual ~CProcessInfo();
-  virtual EINTERLACEMETHOD GetFallbackDeintMethod();
-  virtual bool AllowDTSHDDecode();
-
-protected:
-  CProcessInfo();
-};
+#include <Windows.h>
\ No newline at end of file
diff --git a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h b/xbmc/platform/win32/unistd.h
similarity index 71%
copy from xbmc/cores/VideoPlayer/Process/ProcessInfo.h
copy to xbmc/platform/win32/unistd.h
index b8a4e46..5f26439 100644
--- a/xbmc/cores/VideoPlayer/Process/ProcessInfo.h
+++ b/xbmc/platform/win32/unistd.h
@@ -1,5 +1,6 @@
+#pragma once
 /*
- *      Copyright (C) 2005-2016 Team XBMC
+ *      Copyright (C) 2005-2013 Team XBMC
  *      http://xbmc.org
  *
  *  This Program is free software; you can redistribute it and/or modify
@@ -17,18 +18,5 @@
  *  <http://www.gnu.org/licenses/>.
  *
  */
-#pragma once
-
-#include "cores/IPlayer.h"
-
-class CProcessInfo
-{
-public:
-  static CProcessInfo* CreateInstance();
-  virtual ~CProcessInfo();
-  virtual EINTERLACEMETHOD GetFallbackDeintMethod();
-  virtual bool AllowDTSHDDecode();
-
-protected:
-  CProcessInfo();
-};
+#include <inttypes.h>
+#include <io.h>
diff --git a/xbmc/platform/xbmc.cpp b/xbmc/platform/xbmc.cpp
index 0c7a4d1..74ee5f9 100644
--- a/xbmc/platform/xbmc.cpp
+++ b/xbmc/platform/xbmc.cpp
@@ -32,7 +32,7 @@
 
 #ifdef TARGET_WINDOWS
 #include <mmdeviceapi.h>
-#include "win32/IMMNotificationClient.h"
+#include "platform/win32/IMMNotificationClient.h"
 #endif
 
 #include "platform/MessagePrinter.h"
diff --git a/xbmc/powermanagement/CMakeLists.txt b/xbmc/powermanagement/CMakeLists.txt
index 43ea808..7ca11f2 100644
--- a/xbmc/powermanagement/CMakeLists.txt
+++ b/xbmc/powermanagement/CMakeLists.txt
@@ -7,8 +7,3 @@ set(HEADERS DPMSSupport.h
             PowerManager.h)
 
 core_add_library(powermanagement)
-add_dependencies(powermanagement libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(powermanagement ffmpeg)
-endif()
diff --git a/xbmc/powermanagement/osx/CMakeLists.txt b/xbmc/powermanagement/osx/CMakeLists.txt
index 0aa95b5..f382b21 100644
--- a/xbmc/powermanagement/osx/CMakeLists.txt
+++ b/xbmc/powermanagement/osx/CMakeLists.txt
@@ -3,4 +3,3 @@ set(SOURCES CocoaPowerSyscall.cpp)
 set(HEADERS CocoaPowerSyscall.h)
 
 core_add_library(powermanagement_osx)
-add_dependencies(powermanagement_osx libcpluff)
diff --git a/xbmc/profiles/CMakeLists.txt b/xbmc/profiles/CMakeLists.txt
index 5794bc9..eea2e3d 100644
--- a/xbmc/profiles/CMakeLists.txt
+++ b/xbmc/profiles/CMakeLists.txt
@@ -5,4 +5,3 @@ set(HEADERS Profile.h
             ProfilesManager.h)
 
 core_add_library(profiles)
-add_dependencies(profiles libcpluff)
diff --git a/xbmc/profiles/windows/CMakeLists.txt b/xbmc/profiles/windows/CMakeLists.txt
index 5283777..232d0aa 100644
--- a/xbmc/profiles/windows/CMakeLists.txt
+++ b/xbmc/profiles/windows/CMakeLists.txt
@@ -3,4 +3,3 @@ set(SOURCES GUIWindowSettingsProfile.cpp)
 set(HEADERS GUIWindowSettingsProfile.h)
 
 core_add_library(profiles_windows)
-add_dependencies(profiles_windows libcpluff)
diff --git a/xbmc/pvr/CMakeLists.txt b/xbmc/pvr/CMakeLists.txt
index 0384cee..6569f8a 100644
--- a/xbmc/pvr/CMakeLists.txt
+++ b/xbmc/pvr/CMakeLists.txt
@@ -11,8 +11,3 @@ set(HEADERS PVRActionListener.h
             PVRSettings.h)
 
 core_add_library(pvr)
-add_dependencies(pvr libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(pvr ffmpeg)
-endif()
diff --git a/xbmc/pvr/PVRGUIInfo.cpp b/xbmc/pvr/PVRGUIInfo.cpp
index faf1cfd..ba0a154 100644
--- a/xbmc/pvr/PVRGUIInfo.cpp
+++ b/xbmc/pvr/PVRGUIInfo.cpp
@@ -120,8 +120,7 @@ void CPVRGUIInfo::Start(void)
 void CPVRGUIInfo::Stop(void)
 {
   StopThread();
-  if (g_PVRTimers)
-    g_PVRTimers->UnregisterObserver(this);
+  g_PVRManager.UnregisterObserver(this);
 }
 
 void CPVRGUIInfo::Notify(const Observable &obs, const ObservableMessage msg)
@@ -196,7 +195,7 @@ void CPVRGUIInfo::Process(void)
   int toggleInterval = g_advancedSettings.m_iPVRInfoToggleInterval / 1000;
 
   /* updated on request */
-  g_PVRTimers->RegisterObserver(this);
+  g_PVRManager.RegisterObserver(this);
   UpdateTimersCache();
 
   /* update the backend cache once initially */
diff --git a/xbmc/pvr/addons/CMakeLists.txt b/xbmc/pvr/addons/CMakeLists.txt
index dade57a..ee4e628 100644
--- a/xbmc/pvr/addons/CMakeLists.txt
+++ b/xbmc/pvr/addons/CMakeLists.txt
@@ -3,4 +3,3 @@ set(SOURCES PVRClients.cpp)
 set(HEADERS PVRClients.h)
 
 core_add_library(pvr_addons)
-add_dependencies(pvr_addons libcpluff)
diff --git a/xbmc/pvr/channels/CMakeLists.txt b/xbmc/pvr/channels/CMakeLists.txt
index e37a88e..838f50b 100644
--- a/xbmc/pvr/channels/CMakeLists.txt
+++ b/xbmc/pvr/channels/CMakeLists.txt
@@ -13,4 +13,3 @@ set(HEADERS PVRChannel.h
             PVRRadioRDSInfoTag.h)
 
 core_add_library(pvr_channels)
-add_dependencies(pvr_channels libcpluff)
diff --git a/xbmc/pvr/dialogs/CMakeLists.txt b/xbmc/pvr/dialogs/CMakeLists.txt
index 3a9fed4..f5b8339 100644
--- a/xbmc/pvr/dialogs/CMakeLists.txt
+++ b/xbmc/pvr/dialogs/CMakeLists.txt
@@ -19,4 +19,3 @@ set(HEADERS GUIDialogPVRChannelManager.h
             GUIDialogPVRTimerSettings.h)
 
 core_add_library(pvr_dialogs)
-add_dependencies(pvr_dialogs libcpluff)
diff --git a/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp b/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp
index 1f72db5..6507163 100644
--- a/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp
+++ b/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp
@@ -47,8 +47,7 @@ using namespace KODI::MESSAGING;
 #define CONTROL_LIST                  11
 
 CGUIDialogPVRChannelsOSD::CGUIDialogPVRChannelsOSD() :
-    CGUIDialog(WINDOW_DIALOG_PVR_OSD_CHANNELS, "DialogPVRChannelsOSD.xml"),
-    Observer()
+    CGUIDialog(WINDOW_DIALOG_PVR_OSD_CHANNELS, "DialogPVRChannelsOSD.xml")
 {
   m_vecItems = new CFileItemList;
 }
diff --git a/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp b/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp
index 2e2bd3b..0a9c0eb 100644
--- a/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp
+++ b/xbmc/pvr/dialogs/GUIDialogPVRTimerSettings.cpp
@@ -114,36 +114,32 @@ void CGUIDialogPVRTimerSettings::SetTimer(const CPVRTimerInfoTagPtr &timer)
 
   m_timerInfoTag = timer;
 
-  if (!m_timerInfoTag)
-  {
-    CLog::Log(LOGERROR, "CGUIDialogPVRTimerSettings::SetTimer - No timer info tag");
-    return;
-  }
-
   // Copy data we need from tag. Do not modify the tag itself until Save()!
   m_timerType     = m_timerInfoTag->GetTimerType();
   m_bIsRadio      = m_timerInfoTag->m_bIsRadio;
   m_bIsNewTimer   = m_timerInfoTag->m_iClientIndex == PVR_TIMER_NO_CLIENT_INDEX;
-  m_bTimerActive  = m_bIsNewTimer || m_timerInfoTag->IsActive();
-  m_bStartAnyTime = m_bIsNewTimer || m_timerInfoTag->m_bStartAnyTime;
-  m_bEndAnyTime   = m_bIsNewTimer || m_timerInfoTag->m_bEndAnyTime;
+  m_bTimerActive  = m_bIsNewTimer || !m_timerType->SupportsEnableDisable() || m_timerInfoTag->IsActive();
+  m_bStartAnyTime = m_bIsNewTimer || !m_timerType->SupportsStartAnyTime() || m_timerInfoTag->m_bStartAnyTime;
+  m_bEndAnyTime   = m_bIsNewTimer || !m_timerType->SupportsEndAnyTime() || m_timerInfoTag->m_bEndAnyTime;
   m_strTitle      = m_timerInfoTag->m_strTitle;
 
-  m_startLocalTime    = m_timerInfoTag->StartAsLocalTime();
-  m_endLocalTime      = m_timerInfoTag->EndAsLocalTime();
+  m_startLocalTime = m_timerInfoTag->StartAsLocalTime();
+  m_endLocalTime   = m_timerInfoTag->EndAsLocalTime();
+  if (m_bIsNewTimer && (m_startLocalTime == m_endLocalTime))
+    m_endLocalTime += CDateTimeSpan(0, 2, 0, 0);
+
   m_timerStartTimeStr = m_startLocalTime.GetAsLocalizedTime("", false);
   m_timerEndTimeStr   = m_endLocalTime.GetAsLocalizedTime("", false);
   m_firstDayLocalTime = m_timerInfoTag->FirstDayAsLocalTime();
 
   m_strEpgSearchString = m_timerInfoTag->m_strEpgSearchString;
-
-  if (m_bIsNewTimer && m_strEpgSearchString.empty() && (m_strTitle != g_localizeStrings.Get(19056)))
+  if ((m_bIsNewTimer || !m_timerType->SupportsEpgTitleMatch()) && m_strEpgSearchString.empty())
     m_strEpgSearchString = m_strTitle;
 
-  m_bFullTextEpgSearch  = m_timerInfoTag->m_bFullTextEpgSearch;
-  m_iWeekdays           = m_timerInfoTag->m_iWeekdays;
+  m_bFullTextEpgSearch = m_timerInfoTag->m_bFullTextEpgSearch;
 
-  if (m_bIsNewTimer && (m_iWeekdays == PVR_WEEKDAY_NONE))
+  m_iWeekdays = m_timerInfoTag->m_iWeekdays;
+  if ((m_bIsNewTimer || !m_timerType->SupportsWeekdays()) && m_iWeekdays == PVR_WEEKDAY_NONE)
     m_iWeekdays = PVR_WEEKDAY_ALLDAYS;
 
   m_iPreventDupEpisodes = m_timerInfoTag->m_iPreventDupEpisodes;
@@ -164,7 +160,7 @@ void CGUIDialogPVRTimerSettings::SetTimer(const CPVRTimerInfoTagPtr &timer)
   if (m_timerInfoTag->m_iClientChannelUid == PVR_CHANNEL_INVALID_UID)
   {
     bool bChannelSet(false);
-    if (m_timerType && m_timerType->IsRepeatingEpgBased())
+    if (m_timerType->IsEpgBasedTimerRule())
     {
       // Select "Any channel"
       const auto it = m_channelEntries.find(ENTRY_ANY_CHANNEL);
@@ -209,10 +205,6 @@ void CGUIDialogPVRTimerSettings::SetTimer(const CPVRTimerInfoTagPtr &timer)
     if (!bChannelSet)
       CLog::Log(LOGERROR, "CGUIDialogPVRTimerSettings::SetTimer - Unable to map channel uid to channel entry!");
   }
-
-
-  if (!m_timerType)
-    CLog::Log(LOGERROR, "CGUIDialogPVRTimerSettings::SetTimer - No timer type!");
 }
 
 void CGUIDialogPVRTimerSettings::SetupView()
@@ -258,12 +250,12 @@ void CGUIDialogPVRTimerSettings::InitializeSettings()
   setting = AddEdit(group, SETTING_TMR_NAME, 19075, 0, m_strTitle, true, false, 19097);
   AddTypeDependentEnableCondition(setting, SETTING_TMR_NAME);
 
-  // epg search string (only for epg-based repeating timers)
+  // epg search string (only for epg-based timer rules)
   setting = AddEdit(group, SETTING_TMR_EPGSEARCH, 804, 0, m_strEpgSearchString, true, false, 805);
   AddTypeDependentVisibilityCondition(setting, SETTING_TMR_EPGSEARCH);
   AddTypeDependentEnableCondition(setting, SETTING_TMR_EPGSEARCH);
 
-  // epg fulltext search (only for epg-based repeating timers)
+  // epg fulltext search (only for epg-based timer rules)
   setting = AddToggle(group, SETTING_TMR_FULLTEXT, 806, 0, m_bFullTextEpgSearch);
   AddTypeDependentVisibilityCondition(setting, SETTING_TMR_FULLTEXT);
   AddTypeDependentEnableCondition(setting, SETTING_TMR_FULLTEXT);
@@ -273,7 +265,7 @@ void CGUIDialogPVRTimerSettings::InitializeSettings()
   AddTypeDependentVisibilityCondition(setting, SETTING_TMR_CHANNEL);
   AddTypeDependentEnableCondition(setting, SETTING_TMR_CHANNEL);
 
-  // Days of week (only for repeating timers)
+  // Days of week (only for timer rules)
   std::vector<int> weekdaysPreselect;
   if (m_iWeekdays & PVR_WEEKDAY_MONDAY)
     weekdaysPreselect.push_back(PVR_WEEKDAY_MONDAY);
@@ -294,7 +286,7 @@ void CGUIDialogPVRTimerSettings::InitializeSettings()
   AddTypeDependentVisibilityCondition(setting, SETTING_TMR_WEEKDAYS);
   AddTypeDependentEnableCondition(setting, SETTING_TMR_WEEKDAYS);
 
-  // "Start any time" (only for repeating timers)
+  // "Start any time" (only for timer rules)
   setting = AddToggle(group, SETTING_TMR_START_ANYTIME, 810, 0, m_bStartAnyTime);
   AddTypeDependentVisibilityCondition(setting, SETTING_TMR_START_ANYTIME);
   AddTypeDependentEnableCondition(setting, SETTING_TMR_START_ANYTIME);
@@ -311,7 +303,7 @@ void CGUIDialogPVRTimerSettings::InitializeSettings()
   AddTypeDependentEnableCondition(setting, SETTING_TMR_BEGIN);
   AddStartAnytimeDependentVisibilityCondition(setting, SETTING_TMR_BEGIN);
 
-  // "End any time" (only for repeating timers)
+  // "End any time" (only for timer rules)
   setting = AddToggle(group, SETTING_TMR_END_ANYTIME, 817, 0, m_bEndAnyTime);
   AddTypeDependentVisibilityCondition(setting, SETTING_TMR_END_ANYTIME);
   AddTypeDependentEnableCondition(setting, SETTING_TMR_END_ANYTIME);
@@ -328,12 +320,12 @@ void CGUIDialogPVRTimerSettings::InitializeSettings()
   AddTypeDependentEnableCondition(setting, SETTING_TMR_END);
   AddEndAnytimeDependentVisibilityCondition(setting, SETTING_TMR_END);
 
-  // First day (only for repeating timers)
+  // First day (only for timer rules)
   setting = AddSpinner(group, SETTING_TMR_FIRST_DAY, 19084, 0, GetDateAsIndex(m_firstDayLocalTime), DaysFiller);
   AddTypeDependentVisibilityCondition(setting, SETTING_TMR_FIRST_DAY);
   AddTypeDependentEnableCondition(setting, SETTING_TMR_FIRST_DAY);
 
-  // "Prevent duplicate episodes" (only for repeating timers)
+  // "Prevent duplicate episodes" (only for timer rules)
   setting = AddList(group, SETTING_TMR_NEW_EPISODES, 812, 0, m_iPreventDupEpisodes, DupEpisodesFiller, 812);
   AddTypeDependentVisibilityCondition(setting, SETTING_TMR_NEW_EPISODES);
   AddTypeDependentEnableCondition(setting, SETTING_TMR_NEW_EPISODES);
@@ -416,7 +408,7 @@ void CGUIDialogPVRTimerSettings::OnSettingChanged(const CSetting *setting)
     {
       m_timerType = it->second;
 
-      if (m_timerType->IsRepeating() && (m_iWeekdays == PVR_WEEKDAY_ALLDAYS))
+      if (m_timerType->IsTimerRule() && (m_iWeekdays == PVR_WEEKDAY_ALLDAYS))
         SetButtonLabels(); // update "Any day" vs. "Every day"
     }
     else
@@ -557,10 +549,10 @@ void CGUIDialogPVRTimerSettings::Save()
   // Name
   m_timerInfoTag->m_strTitle = m_strTitle;
 
-  // epg search string (only for epg-based repeating timers)
+  // epg search string (only for epg-based timer rules)
   m_timerInfoTag->m_strEpgSearchString = m_strEpgSearchString;
 
-  // epg fulltext search, instead of just title match. (only for epg-based repeating timers)
+  // epg fulltext search, instead of just title match. (only for epg-based timer rules)
   m_timerInfoTag->m_bFullTextEpgSearch = m_bFullTextEpgSearch;
 
   // Channel
@@ -597,7 +589,7 @@ void CGUIDialogPVRTimerSettings::Save()
   {
     if (m_timerType->SupportsStartTime() &&    // has start clock entry
         m_timerType->SupportsEndTime() &&      // and end clock entry
-        m_timerType->IsRepeating())            // but no associated start/end day spinners
+        m_timerType->IsTimerRule())            // but no associated start/end day spinners
     {
       if (m_endLocalTime < m_startLocalTime)   // And the end clock is earlier than the start clock
       {
@@ -632,16 +624,16 @@ void CGUIDialogPVRTimerSettings::Save()
   else if (!m_bEndAnyTime)
     m_timerInfoTag->SetEndFromLocalTime(m_endLocalTime);
 
-  // Days of week (only for repeating timers)
-  if (m_timerType->IsRepeating())
+  // Days of week (only for timer rules)
+  if (m_timerType->IsTimerRule())
     m_timerInfoTag->m_iWeekdays = m_iWeekdays;
   else
     m_timerInfoTag->m_iWeekdays = PVR_WEEKDAY_NONE;
 
-  // First day (only for repeating timers)
+  // First day (only for timer rules)
   m_timerInfoTag->SetFirstDayFromLocalTime(m_firstDayLocalTime);
 
-  // "New episodes only" (only for repeating timers)
+  // "New episodes only" (only for timer rules)
   m_timerInfoTag->m_iPreventDupEpisodes = m_iPreventDupEpisodes;
 
   // Pre and post record time
@@ -730,42 +722,46 @@ void CGUIDialogPVRTimerSettings::InitializeTypesList()
 {
   m_typeEntries.clear();
 
+  // If timer is read-only or was created by a timer rule, only add current type, for information. Type can't be changed.
+  if (m_timerType->IsReadOnly() || m_timerInfoTag->GetTimerRuleId() != PVR_TIMER_NO_PARENT)
+  {
+    m_typeEntries.insert(std::make_pair(0, m_timerType));
+    return;
+  }
+
   int idx = 0;
   const std::vector<CPVRTimerTypePtr> types(CPVRTimerType::GetAllTypes());
   for (const auto &type : types)
   {
-    if (m_bIsNewTimer)
+    // Type definition prohibits created of new instances.
+    // But the dialog can act as a viewer for these types.
+    if (type->ForbidsNewInstances())
+      continue;
+
+    // Read-only timers cannot be created using this dialog.
+    // But the dialog can act as a viewer for read-only types.
+    if (type->IsReadOnly())
+      continue;
+
+    // Drop TimerTypes that require EPGInfo, if none is populated
+    if (type->RequiresEpgTagOnCreate() && !m_timerInfoTag->GetEpgInfoTag())
+      continue;
+
+    // Drop TimerTypes without 'Series' EPG attributes if none are set
+    if (type->RequiresEpgSeriesOnCreate())
     {
-      // Type definition prohibits created of new instances.
-      // But the dialog can act as a viewer for these types. (m_bIsNewTimer is false in this case)
-      if (type->ForbidsNewInstances())
-        continue;
-
-      // Read-only timers cannot be created using this dialog.
-      // But the dialog can act as a viewer for read-only types (m_bIsNewTimer is false in this case)
-      if (type->IsReadOnly())
-        continue;
-
-      // Drop TimerTypes that require EPGInfo, if none is populated
-      if (type->RequiresEpgTagOnCreate() && !m_timerInfoTag->GetEpgInfoTag())
+      const EPG::CEpgInfoTagPtr epgTag(m_timerInfoTag->GetEpgInfoTag());
+      if (epgTag && !epgTag->IsSeries())
         continue;
+    }
 
-      // Drop TimerTypes without 'Series' EPG attributes if none are set
-      if (type->RequiresEpgSeriesOnCreate())
-      {
-        const EPG::CEpgInfoTagPtr epgTag(m_timerInfoTag->GetEpgInfoTag());
-        if (epgTag && !epgTag->IsSeries())
-          continue;
-      }
+    // Drop TimerTypes that forbid EPGInfo, if it is populated
+    if (type->ForbidsEpgTagOnCreate() && m_timerInfoTag->GetEpgInfoTag())
+      continue;
 
-      // Drop TimerTypes that forbid EPGInfo, if it is populated
-      if (type->ForbidsEpgTagOnCreate() && m_timerInfoTag->GetEpgInfoTag())
-        continue;
-
-      // Drop TimerTypes that aren't repeating if end time is in the past
-      if (!type->IsRepeating() && m_timerInfoTag->EndAsLocalTime() < CDateTime::GetCurrentDateTime())
-        continue;
-    }
+    // Drop TimerTypes that aren't rules if end time is in the past
+    if (!type->IsTimerRule() && m_timerInfoTag->EndAsLocalTime() < CDateTime::GetCurrentDateTime())
+      continue;
 
     m_typeEntries.insert(std::make_pair(idx++, type));
   }
@@ -787,7 +783,7 @@ void CGUIDialogPVRTimerSettings::InitializeChannelsList()
       std::make_pair(i, ChannelDescriptor(channel->UniqueID(), channel->ClientID(), channelDescription)));
   }
 
-  // Add special "any channel" entry (used for epg-based repeating timers).
+  // Add special "any channel" entry (used for epg-based timer rules).
   m_channelEntries.insert(
     std::make_pair(
       ENTRY_ANY_CHANNEL, ChannelDescriptor(PVR_CHANNEL_INVALID_UID, 0, g_localizeStrings.Get(809))));
@@ -832,8 +828,8 @@ void CGUIDialogPVRTimerSettings::ChannelsFiller(
     {
       if (channelEntry.first == ENTRY_ANY_CHANNEL)
       {
-        // For repeating epg-based timers only, add an "any channel" entry.
-        if (pThis->m_timerType->IsRepeatingEpgBased())
+        // For epg-based timer rules only, add an "any channel" entry.
+        if (pThis->m_timerType->IsEpgBasedTimerRule())
           list.push_back(std::make_pair(channelEntry.second.description, channelEntry.first));
         else
           continue;
@@ -1109,13 +1105,6 @@ bool CGUIDialogPVRTimerSettings::TypeReadOnlyCondition(const std::string &condit
   std::string cond(condition);
   cond.erase(cond.find(TYPE_DEP_ENABLE_COND_ID_POSTFIX));
 
-  // For existing timers, disable type selector (view/edit of existing timer).
-  if (!pThis->m_bIsNewTimer)
-  {
-    if (cond == SETTING_TMR_TYPE)
-      return false;
-  }
-
   // If only one type is available, disable type selector.
   if (pThis->m_typeEntries.size() == 1)
   {
@@ -1124,7 +1113,7 @@ bool CGUIDialogPVRTimerSettings::TypeReadOnlyCondition(const std::string &condit
   }
 
   // For existing one time epg-based timers, disable editing of epg-filled data.
-  if (!pThis->m_bIsNewTimer && pThis->m_timerType->IsOnetimeEpgBased())
+  if (!pThis->m_bIsNewTimer && pThis->m_timerType->IsEpgBasedOnetime())
   {
     if ((cond == SETTING_TMR_NAME)      ||
         (cond == SETTING_TMR_CHANNEL)   ||
diff --git a/xbmc/pvr/recordings/CMakeLists.txt b/xbmc/pvr/recordings/CMakeLists.txt
index eeb4fe1..55f7028 100644
--- a/xbmc/pvr/recordings/CMakeLists.txt
+++ b/xbmc/pvr/recordings/CMakeLists.txt
@@ -7,4 +7,3 @@ set(HEADERS PVRRecording.h
             PVRRecordingsPath.h)
 
 core_add_library(pvr_recordings)
-add_dependencies(pvr_recordings libcpluff)
diff --git a/xbmc/pvr/recordings/PVRRecording.cpp b/xbmc/pvr/recordings/PVRRecording.cpp
index 3de7eca..d6dbb8d 100644
--- a/xbmc/pvr/recordings/PVRRecording.cpp
+++ b/xbmc/pvr/recordings/PVRRecording.cpp
@@ -181,8 +181,8 @@ void CPVRRecording::Serialize(CVariant& value) const
   value["starttime"] = m_recordingTime.IsValid() ? m_recordingTime.GetAsDBDateTime() : "";
   value["endtime"] = m_recordingTime.IsValid() ? (m_recordingTime + m_duration).GetAsDBDateTime() : "";
   value["recordingid"] = m_iRecordingId;
-  value["deleted"] = m_bIsDeleted;
-  value["epgevent"] = m_iEpgEventId;
+  value["isdeleted"] = m_bIsDeleted;
+  value["epgeventid"] = m_iEpgEventId;
   value["channeluid"] = m_iChannelUid;
   value["radio"] = m_bRadio;
 
diff --git a/xbmc/pvr/recordings/PVRRecordings.cpp b/xbmc/pvr/recordings/PVRRecordings.cpp
index 84d19d7..f4261ac 100644
--- a/xbmc/pvr/recordings/PVRRecordings.cpp
+++ b/xbmc/pvr/recordings/PVRRecordings.cpp
@@ -27,6 +27,7 @@
 #include "pvr/addons/PVRClients.h"
 #include "pvr/recordings/PVRRecordingsPath.h"
 #include "pvr/PVRManager.h"
+#include "settings/Settings.h"
 #include "threads/SingleLock.h"
 #include "utils/log.h"
 #include "utils/StringUtils.h"
@@ -38,7 +39,6 @@ using namespace PVR;
 CPVRRecordings::CPVRRecordings(void) :
     m_bIsUpdating(false),
     m_iLastId(0),
-    m_bGroupItems(true),
     m_bDeletedTVRecordings(false),
     m_bDeletedRadioRecordings(false),
     m_iTVRecordings(0),
@@ -79,7 +79,7 @@ bool CPVRRecordings::IsDirectoryMember(const std::string &strDirectory, const st
   std::string strUseEntryDirectory = TrimSlashes(strEntryDirectory);
 
   /* Case-insensitive comparison since sub folders are created with case-insensitive matching (GetSubDirectories) */
-  return m_bGroupItems ?
+  return CSettings::GetInstance().GetBool(CSettings::SETTING_PVRRECORD_GROUPRECORDINGS) ?
       StringUtils::EqualsNoCase(strUseDirectory, strUseEntryDirectory) :
         StringUtils::StartsWithNoCase(strUseEntryDirectory, strUseDirectory);
 }
@@ -160,10 +160,10 @@ void CPVRRecordings::Update(void)
 
   lock.Enter();
   m_bIsUpdating = false;
-  SetChanged();
+  g_PVRManager.SetChanged();
   lock.Leave();
 
-  NotifyObservers(ObservableMessageRecordings);
+  g_PVRManager.NotifyObservers(ObservableMessageRecordings);
 }
 
 int CPVRRecordings::GetNumTVRecordings() const
@@ -318,7 +318,7 @@ bool CPVRRecordings::GetDirectory(const std::string& strPath, CFileItemList &ite
     // Get the directory structure if in non-flatten mode
     // Deleted view is always flatten. So only for an active view
     std::string strDirectory(recPath.GetDirectoryPath());
-    if (!recPath.IsDeleted() && m_bGroupItems)
+    if (!recPath.IsDeleted() && CSettings::GetInstance().GetBool(CSettings::SETTING_PVRRECORD_GROUPRECORDINGS))
       GetSubDirectories(recPath, &items);
 
     // get all files of the currrent directory or recursively all files starting at the current directory if in flatten mode
diff --git a/xbmc/pvr/recordings/PVRRecordings.h b/xbmc/pvr/recordings/PVRRecordings.h
index 675dde8..56e343d 100644
--- a/xbmc/pvr/recordings/PVRRecordings.h
+++ b/xbmc/pvr/recordings/PVRRecordings.h
@@ -20,7 +20,6 @@
  */
 
 #include "FileItem.h"
-#include "utils/Observer.h"
 #include "video/VideoDatabase.h"
 
 #include "PVRRecording.h"
@@ -29,7 +28,7 @@ namespace PVR
 {
   class CPVRRecordingsPath;
 
-  class CPVRRecordings : public Observable
+  class CPVRRecordings
   {
   private:
     typedef std::map<CPVRRecordingUid, CPVRRecordingPtr> PVR_RECORDINGMAP;
@@ -40,7 +39,6 @@ namespace PVR
     bool                         m_bIsUpdating;
     PVR_RECORDINGMAP             m_recordings;
     unsigned int                 m_iLastId;
-    bool                         m_bGroupItems;
     CVideoDatabase               m_database;
     bool                         m_bDeletedTVRecordings;
     bool                         m_bDeletedRadioRecordings;
@@ -95,7 +93,5 @@ namespace PVR
     CPVRRecordingPtr GetById(int iClientId, const std::string &strRecordingId) const;
     void GetAll(CFileItemList &items, bool bDeleted = false);
     CFileItemPtr GetById(unsigned int iId) const;
-
-    void SetGroupItems(bool value) { m_bGroupItems = value; };
   };
 }
diff --git a/xbmc/pvr/timers/CMakeLists.txt b/xbmc/pvr/timers/CMakeLists.txt
index 6e19094..52026ef 100644
--- a/xbmc/pvr/timers/CMakeLists.txt
+++ b/xbmc/pvr/timers/CMakeLists.txt
@@ -7,4 +7,3 @@ set(HEADERS PVRTimerInfoTag.h
             PVRTimerType.h)
 
 core_add_library(pvr_timers)
-add_dependencies(pvr_timers libcpluff)
diff --git a/xbmc/pvr/timers/PVRTimerInfoTag.cpp b/xbmc/pvr/timers/PVRTimerInfoTag.cpp
index 2ff44d4..7071590 100644
--- a/xbmc/pvr/timers/PVRTimerInfoTag.cpp
+++ b/xbmc/pvr/timers/PVRTimerInfoTag.cpp
@@ -87,7 +87,7 @@ CPVRTimerInfoTag::CPVRTimerInfoTag(bool bRadio /* = false */) :
       CLog::Log(LOGERROR, "%s: no timer type, although timers are supported by client %d!", __FUNCTION__, m_iClientId);
   }
 
-  m_iWeekdays = (m_timerType && m_timerType->IsRepeating()) ? PVR_WEEKDAY_ALLDAYS : PVR_WEEKDAY_NONE;
+  m_iWeekdays = (m_timerType && m_timerType->IsTimerRule()) ? PVR_WEEKDAY_ALLDAYS : PVR_WEEKDAY_NONE;
 
   ResetChildState();
   UpdateSummary();
@@ -166,7 +166,7 @@ CPVRTimerInfoTag::CPVRTimerInfoTag(const PVR_TIMER &timer, const CPVRChannelPtr
 
     if (!m_timerType)
       CLog::Log(LOGERROR, "%s: no timer type, although timers are supported by client %d!", __FUNCTION__, m_iClientId);
-    else if (m_iEpgUid == EPG_TAG_INVALID_UID && m_timerType->IsOnetimeEpgBased())
+    else if (m_iEpgUid == EPG_TAG_INVALID_UID && m_timerType->IsEpgBasedOnetime())
       CLog::Log(LOGERROR, "%s: no epg tag given for epg based timer type (%d)!", __FUNCTION__, m_timerType->GetTypeId());
   }
 
@@ -306,23 +306,9 @@ void CPVRTimerInfoTag::Serialize(CVariant &value) const
     break;
   }
 
-  if (m_timerType)
-  {
-    if (m_timerType->IsManual())
-    {
-      if (m_timerType->IsRepeating())
-        value["type"] = "manual_repeating";
-      else
-        value["type"] = "manual_once";
-    }
-    else
-    {
-      if (m_timerType->IsRepeating())
-        value["type"] = "epg_repeating";
-      else
-        value["type"] = "epg_once";
-    }
-  }
+  value["istimerrule"] = m_timerType && m_timerType->IsTimerRule();
+  value["ismanual"] = m_timerType && m_timerType->IsManual();
+  value["isreadonly"] = m_timerType && m_timerType->IsReadOnly();
 
   value["epgsearchstring"]   = m_strEpgSearchString;
   value["fulltextepgsearch"] = m_bFullTextEpgSearch;
@@ -395,7 +381,7 @@ void CPVRTimerInfoTag::SetTimerType(const CPVRTimerTypePtr &type)
     m_iRecordingGroup     = m_timerType->GetRecordingGroupDefault();
   }
 
-  if (m_timerType && !m_timerType->IsRepeating())
+  if (m_timerType && !m_timerType->IsTimerRule())
     m_iWeekdays = PVR_WEEKDAY_NONE;
 }
 
@@ -706,7 +692,7 @@ std::string CPVRTimerInfoTag::ChannelName() const
   CPVRChannelPtr channeltag = ChannelTag();
   if (channeltag)
     strReturn = channeltag->ChannelName();
-  else if (m_timerType && m_timerType->IsRepeatingEpgBased())
+  else if (m_timerType && m_timerType->IsEpgBasedTimerRule())
     strReturn = StringUtils::Format("(%s)", g_localizeStrings.Get(809).c_str()); // "Any channel"
 
   return strReturn;
@@ -827,18 +813,34 @@ CPVRTimerInfoTagPtr CPVRTimerInfoTag::CreateFromEpg(const CEpgInfoTagPtr &tag, b
   CPVRTimerTypePtr timerType;
   if (bCreateRule)
   {
-    // create repeating epg-based timer
+    // create epg-based timer rule
     timerType = CPVRTimerType::CreateFromAttributes(
       PVR_TIMER_TYPE_IS_REPEATING,
       PVR_TIMER_TYPE_IS_MANUAL | PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES, channel->ClientID());
+
+    if (timerType)
+    {
+      if (timerType->SupportsEpgTitleMatch())
+        newTag->m_strEpgSearchString = newTag->m_strTitle;
+
+      if (timerType->SupportsWeekdays())
+        newTag->m_iWeekdays = PVR_WEEKDAY_ALLDAYS;
+
+      if (timerType->SupportsStartAnyTime())
+        newTag->m_bStartAnyTime = true;
+
+      if (timerType->SupportsEndAnyTime())
+        newTag->m_bEndAnyTime = true;
+    }
   }
-  if (!timerType)
+  else
   {
     // create one-shot epg-based timer
     timerType = CPVRTimerType::CreateFromAttributes(
       PVR_TIMER_TYPE_ATTRIBUTE_NONE,
       PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_IS_MANUAL | PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES, channel->ClientID());
   }
+
   if (!timerType)
   {
     CLog::Log(LOGERROR, "%s - unable to create any epg-based timer type", __FUNCTION__);
@@ -907,7 +909,7 @@ void CPVRTimerInfoTag::GetNotificationText(std::string &strText) const
       stringID = 19224; // Recording aborted
     break;
   case PVR_TIMER_STATE_SCHEDULED:
-    if (IsRepeating())
+    if (IsTimerRule())
       stringID = 19058; // Timer enabled
     else
       stringID = 19225; // Recording scheduled
@@ -948,7 +950,7 @@ std::string CPVRTimerInfoTag::GetDeletedNotificationText() const
     break;
   case PVR_TIMER_STATE_SCHEDULED:
   default:
-    if (IsRepeating())
+    if (IsTimerRule())
       stringID = 828; // Timer rule deleted
     else
       stringID = 19228; // Timer deleted
diff --git a/xbmc/pvr/timers/PVRTimerInfoTag.h b/xbmc/pvr/timers/PVRTimerInfoTag.h
index 988f670..8c900df 100644
--- a/xbmc/pvr/timers/PVRTimerInfoTag.h
+++ b/xbmc/pvr/timers/PVRTimerInfoTag.h
@@ -184,10 +184,10 @@ namespace PVR
     void SetTimerType(const CPVRTimerTypePtr &type);
 
     /*!
-      * @brief Checks whether this is a repeating (vs. one-shot) timer.
-      * @return True if this is a repeating timer, false otherwise.
+      * @brief Checks whether this is a timer rule (vs. one time timer).
+      * @return True if this is a timer rule, false otherwise.
       */
-    bool IsRepeating(void) const { return m_timerType && m_timerType->IsRepeating(); }
+    bool IsTimerRule(void) const { return m_timerType && m_timerType->IsTimerRule(); }
 
     /*!
       * @brief Checks whether this is a manual (vs. epg-based) timer.
@@ -265,7 +265,7 @@ namespace PVR
     unsigned int GetTimerRuleId() const { return m_iParentClientIndex; }
 
     std::string           m_strTitle;            /*!< @brief name of this timer */
-    std::string           m_strEpgSearchString;  /*!< @brief a epg data match string for repeating epg-based timers. Format is backend-dependent, for example regexp */
+    std::string           m_strEpgSearchString;  /*!< @brief a epg data match string for epg-based timer rules. Format is backend-dependent, for example regexp */
     bool                  m_bFullTextEpgSearch;  /*!< @brief indicates whether only epg episode title can be matched by the pvr backend or "more" (backend-dependent") data. */
     std::string           m_strDirectory;        /*!< @brief directory where the recording must be stored */
     std::string           m_strSummary;          /*!< @brief summary string with the time to show inside a GUI list */
@@ -279,8 +279,8 @@ namespace PVR
     int                   m_iPriority;           /*!< @brief priority of the timer */
     int                   m_iLifetime;           /*!< @brief lifetime of the timer in days */
     int                   m_iMaxRecordings;      /*!< @brief (optional) backend setting for maximum number of recordings to keep*/
-    unsigned int          m_iWeekdays;           /*!< @brief bit based store of weekdays for repeating timers */
-    unsigned int          m_iPreventDupEpisodes; /*!< @brief only record new episodes for repeating epg based timers */
+    unsigned int          m_iWeekdays;           /*!< @brief bit based store of weekdays for timer rules */
+    unsigned int          m_iPreventDupEpisodes; /*!< @brief only record new episodes for epg-based timer rules */
     unsigned int          m_iRecordingGroup;     /*!< @brief (optional) if set, the addon/backend stores the recording to a group (sub-folder) */
     std::string           m_strFileNameAndPath;  /*!< @brief file name is only for reference */
     int                   m_iChannelNumber;      /*!< @brief integer value of the channel number */
@@ -298,7 +298,7 @@ namespace PVR
     CCriticalSection      m_critSection;
     CDateTime             m_StartTime; /*!< start time */
     CDateTime             m_StopTime;  /*!< stop time */
-    CDateTime             m_FirstDay;  /*!< if it is a manual repeating timer the first date it starts */
+    CDateTime             m_FirstDay;  /*!< if it is a manual timer rule the first date it starts */
     CPVRTimerTypePtr      m_timerType; /*!< the type of this timer */
 
     unsigned int          m_iActiveChildTimers;   /*!< @brief Number of active timers which have this timer as their m_iParentClientIndex */
diff --git a/xbmc/pvr/timers/PVRTimerType.h b/xbmc/pvr/timers/PVRTimerType.h
index cbc01a9..d91c30f 100644
--- a/xbmc/pvr/timers/PVRTimerType.h
+++ b/xbmc/pvr/timers/PVRTimerType.h
@@ -94,16 +94,16 @@ namespace PVR
     const std::string& GetDescription() const { return m_strDescription; }
 
     /*!
-     * @brief Check whether this type is for repeating ore one time timers.
-     * @return True if repeating, false otherwise.
+     * @brief Check whether this type is for timer rules or one time timers.
+     * @return True if type represents a timer rule, false otherwise.
      */
-    bool IsRepeating() const { return (m_iAttributes & PVR_TIMER_TYPE_IS_REPEATING) > 0; }
+    bool IsTimerRule() const { return (m_iAttributes & PVR_TIMER_TYPE_IS_REPEATING) > 0; }
 
     /*!
-     * @brief Check whether this type is for repeating ore one time timers.
-     * @return True if one time, false otherwise.
+     * @brief Check whether this type is for timer rules or one time timers.
+     * @return True if type represents a one time timer, false otherwise.
      */
-    bool IsOnetime() const { return !IsRepeating(); }
+    bool IsOnetime() const { return !IsTimerRule(); }
 
     /*!
      * @brief Check whether this type is for epg-based or manual timers.
@@ -118,28 +118,28 @@ namespace PVR
     bool IsEpgBased() const { return !IsManual(); }
 
     /*!
-     * @brief Check whether this type is for repeating epg-based timers.
-     * @return True if repeating epg-based, false otherwise.
+     * @brief Check whether this type is for epg-based timer rules.
+     * @return True if epg-based timer rule, false otherwise.
      */
-    bool IsRepeatingEpgBased() const { return IsRepeating() && IsEpgBased(); }
+    bool IsEpgBasedTimerRule() const { return IsEpgBased() && IsTimerRule(); }
 
     /*!
      * @brief Check whether this type is for one time epg-based timers.
      * @return True if one time epg-based, false otherwise.
      */
-    bool IsOnetimeEpgBased() const { return IsOnetime() && IsEpgBased(); }
+    bool IsEpgBasedOnetime() const { return IsEpgBased() && IsOnetime(); }
 
     /*!
-     * @brief Check whether this type is for repeating manual timers.
-     * @return True if repeating manual, false otherwise.
+     * @brief Check whether this type is for manual timer rules.
+     * @return True if manual timer rule, false otherwise.
      */
-    bool IsRepeatingManual() const { return IsRepeating() && IsManual(); }
+    bool IsManualTimerRule() const { return IsManual() && IsTimerRule(); }
 
     /*!
      * @brief Check whether this type is for one time manual timers.
      * @return True if one time manual, false otherwise.
      */
-    bool IsOnetimeManual() const { return IsOnetime() && IsManual(); }
+    bool IsManualOnetime() const { return IsManual() && IsOnetime(); }
 
     /*!
      * @brief Check whether this type is readonly (must not be modified after initial creation).
diff --git a/xbmc/pvr/timers/PVRTimers.cpp b/xbmc/pvr/timers/PVRTimers.cpp
index 8f48b52..8b42563 100644
--- a/xbmc/pvr/timers/PVRTimers.cpp
+++ b/xbmc/pvr/timers/PVRTimers.cpp
@@ -105,7 +105,7 @@ bool CPVRTimers::IsRecording(void) const
 
 bool CPVRTimers::SetEpgTagTimer(const CPVRTimerInfoTagPtr &timer)
 {
-  if (timer->IsRepeating() || timer->m_bStartAnyTime || timer->m_bEndAnyTime)
+  if (timer->IsTimerRule() || timer->m_bStartAnyTime || timer->m_bEndAnyTime)
     return false;
 
   std::vector<CEpgInfoTagPtr> tags(g_EpgContainer.GetEpgTagsForTimer(timer));
@@ -125,7 +125,7 @@ bool CPVRTimers::SetEpgTagTimer(const CPVRTimerInfoTagPtr &timer)
 
 bool CPVRTimers::ClearEpgTagTimer(const CPVRTimerInfoTagPtr &timer)
 {
-  if (timer->IsRepeating() || timer->m_bStartAnyTime || timer->m_bEndAnyTime)
+  if (timer->IsTimerRule() || timer->m_bStartAnyTime || timer->m_bEndAnyTime)
     return false;
 
   std::vector<CEpgInfoTagPtr> tags(g_EpgContainer.GetEpgTagsForTimer(timer));
@@ -323,10 +323,10 @@ bool CPVRTimers::UpdateEntries(const CPVRTimers &timers, const std::vector<int>
   if (bChanged)
   {
     UpdateChannels();
-    SetChanged();
+    g_PVRManager.SetChanged();
     lock.Leave();
 
-    NotifyObservers(bAddedOrDeleted ? ObservableMessageTimersReset : ObservableMessageTimers);
+    g_PVRManager.NotifyObservers(bAddedOrDeleted ? ObservableMessageTimersReset : ObservableMessageTimers);
 
     /* queue notifications / fill eventlog */
     for (const auto &entry : timerNotifications)
@@ -382,7 +382,7 @@ CFileItemPtr CPVRTimers::GetNextActiveTimer(void) const
     for (VecTimerInfoTag::const_iterator timerIt = it->second->begin(); timerIt != it->second->end(); ++timerIt)
     {
       CPVRTimerInfoTagPtr current = *timerIt;
-      if (current->IsActive() && !current->IsRecording() && !current->IsRepeating() && !current->IsBroken())
+      if (current->IsActive() && !current->IsRecording() && !current->IsTimerRule() && !current->IsBroken())
       {
         CFileItemPtr fileItem(new CFileItem(current));
         return fileItem;
@@ -404,7 +404,7 @@ std::vector<CFileItemPtr> CPVRTimers::GetActiveTimers(void) const
     for (VecTimerInfoTag::const_iterator timerIt = it->second->begin(); timerIt != it->second->end(); ++timerIt)
     {
       CPVRTimerInfoTagPtr current = *timerIt;
-      if (current->IsActive() && !current->IsRepeating())
+      if (current->IsActive() && !current->IsTimerRule())
       {
         CFileItemPtr fileItem(new CFileItem(current));
         tags.push_back(fileItem);
@@ -422,7 +422,7 @@ int CPVRTimers::AmountActiveTimers(void) const
 
   for (MapTags::const_iterator it = m_tags.begin(); it != m_tags.end(); ++it)
     for (VecTimerInfoTag::const_iterator timerIt = it->second->begin(); timerIt != it->second->end(); ++timerIt)
-      if ((*timerIt)->IsActive() && !(*timerIt)->IsRepeating())
+      if ((*timerIt)->IsActive() && !(*timerIt)->IsTimerRule())
         ++iReturn;
 
   return iReturn;
@@ -438,7 +438,7 @@ std::vector<CFileItemPtr> CPVRTimers::GetActiveRecordings(void) const
     for (VecTimerInfoTag::const_iterator timerIt = it->second->begin(); timerIt != it->second->end(); ++timerIt)
     {
       CPVRTimerInfoTagPtr current = *timerIt;
-      if (current->IsRecording() && !current->IsRepeating())
+      if (current->IsRecording() && !current->IsTimerRule())
       {
         CFileItemPtr fileItem(new CFileItem(current));
         tags.push_back(fileItem);
@@ -456,7 +456,7 @@ int CPVRTimers::AmountActiveRecordings(void) const
 
   for (MapTags::const_iterator it = m_tags.begin(); it != m_tags.end(); ++it)
     for (VecTimerInfoTag::const_iterator timerIt = it->second->begin(); timerIt != it->second->end(); ++timerIt)
-      if ((*timerIt)->IsRecording() && !(*timerIt)->IsRepeating())
+      if ((*timerIt)->IsRecording() && !(*timerIt)->IsTimerRule())
         ++iReturn;
 
   return iReturn;
@@ -467,7 +467,7 @@ bool CPVRTimers::HasActiveTimers(void) const
   CSingleLock lock(m_critSection);
   for (MapTags::const_iterator it = m_tags.begin(); it != m_tags.end(); ++it)
     for (VecTimerInfoTag::const_iterator timerIt = it->second->begin(); timerIt != it->second->end(); ++timerIt)
-      if ((*timerIt)->IsActive() && !(*timerIt)->IsRepeating())
+      if ((*timerIt)->IsActive() && !(*timerIt)->IsTimerRule())
         return true;
 
   return false;
@@ -492,7 +492,7 @@ bool CPVRTimers::GetRootDirectory(const CPVRTimersPath &path, CFileItemList &ite
     for (const auto &timer : *tagsEntry.second)
     {
       if ((bRadio == timer->m_bIsRadio) &&
-          (bRules == timer->IsRepeating()) &&
+          (bRules == timer->IsTimerRule()) &&
           (!bHideDisabled || (timer->m_state != PVR_TIMER_STATE_DISABLED)))
       {
         item.reset(new CFileItem(timer));
@@ -561,7 +561,7 @@ bool CPVRTimers::GetDirectory(const std::string& strPath, CFileItemList &items)
 
 /********** channel methods **********/
 
-bool CPVRTimers::DeleteTimersOnChannel(const CPVRChannelPtr &channel, bool bDeleteRepeating /* = true */, bool bCurrentlyActiveOnly /* = false */)
+bool CPVRTimers::DeleteTimersOnChannel(const CPVRChannelPtr &channel, bool bDeleteTimerRules /* = true */, bool bCurrentlyActiveOnly /* = false */)
 {
   bool bReturn = false;
   {
@@ -572,20 +572,20 @@ bool CPVRTimers::DeleteTimersOnChannel(const CPVRChannelPtr &channel, bool bDele
       for (VecTimerInfoTag::iterator timerIt = it->second->begin(); timerIt != it->second->end(); ++timerIt)
       {
         bool bDeleteActiveItem = !bCurrentlyActiveOnly || (*timerIt)->IsRecording();
-        bool bDeleteRepeatingItem = bDeleteRepeating || !(*timerIt)->IsRepeating();
+        bool bDeleteTimerRuleItem = bDeleteTimerRules || !(*timerIt)->IsTimerRule();
         bool bChannelsMatch = (*timerIt)->ChannelTag() == channel;
 
-        if (bDeleteActiveItem && bDeleteRepeatingItem && bChannelsMatch)
+        if (bDeleteActiveItem && bDeleteTimerRuleItem && bChannelsMatch)
         {
           CLog::Log(LOGDEBUG,"PVRTimers - %s - deleted timer %d on client %d", __FUNCTION__, (*timerIt)->m_iClientIndex, (*timerIt)->m_iClientId);
           bReturn = (*timerIt)->DeleteFromClient(true) || bReturn;
-          SetChanged();
+          g_PVRManager.SetChanged();
         }
       }
     }
   }
 
-  NotifyObservers(ObservableMessageTimersReset);
+  g_PVRManager.NotifyObservers(ObservableMessageTimersReset);
 
   return bReturn;
 }
@@ -594,7 +594,7 @@ bool CPVRTimers::DeleteTimersOnChannel(const CPVRChannelPtr &channel, bool bDele
 
 bool CPVRTimers::AddTimer(const CPVRTimerInfoTagPtr &item)
 {
-  if (!item->m_channel && item->GetTimerType() && !item->GetTimerType()->IsRepeatingEpgBased())
+  if (!item->m_channel && item->GetTimerType() && !item->GetTimerType()->IsEpgBasedTimerRule())
   {
     CLog::Log(LOGERROR, "PVRTimers - %s - no channel given", __FUNCTION__);
     CGUIDialogOK::ShowAndGetInput(CVariant{19033}, CVariant{19109}); // Couldn't save timer
@@ -728,7 +728,7 @@ CPVRTimerInfoTagPtr CPVRTimers::GetTimerForEpgTag(const CEpgInfoTagPtr &epgTag)
         {
           timer = *timerIt;
 
-          if (!timer->IsRepeating() &&
+          if (!timer->IsTimerRule() &&
               (timer->GetEpgInfoTag(false) == epgTag ||
                (timer->m_iEpgUid != EPG_TAG_INVALID_UID && timer->m_iEpgUid == epgTag->UniqueBroadcastID()) ||
                (timer->m_iClientChannelUid == channel->UniqueID() &&
diff --git a/xbmc/pvr/timers/PVRTimers.h b/xbmc/pvr/timers/PVRTimers.h
index 93874a4..54e1781 100644
--- a/xbmc/pvr/timers/PVRTimers.h
+++ b/xbmc/pvr/timers/PVRTimers.h
@@ -41,8 +41,7 @@ namespace PVR
 {
   class CPVRTimersPath;
 
-  class CPVRTimers : public Observer,
-                     public Observable
+  class CPVRTimers : public Observer
   {
   public:
     CPVRTimers(void);
@@ -130,11 +129,11 @@ namespace PVR
     /*!
      * @brief Delete all timers on a channel.
      * @param channel The channel to delete the timers for.
-     * @param bDeleteRepeating True to delete repeating events too, false otherwise.
+     * @param bDeleteTimerRules True to delete timer rules too, false otherwise.
      * @param bCurrentlyActiveOnly True to delete timers that are currently running only.
      * @return True if timers any were deleted, false otherwise.
      */
-    bool DeleteTimersOnChannel(const CPVRChannelPtr &channel, bool bDeleteRepeating = true, bool bCurrentlyActiveOnly = false);
+    bool DeleteTimersOnChannel(const CPVRChannelPtr &channel, bool bDeleteTimerRules = true, bool bCurrentlyActiveOnly = false);
 
     /*!
      * @return Next event time (timer or daily wake up)
diff --git a/xbmc/pvr/windows/CMakeLists.txt b/xbmc/pvr/windows/CMakeLists.txt
index 80708bd..9f5097e 100644
--- a/xbmc/pvr/windows/CMakeLists.txt
+++ b/xbmc/pvr/windows/CMakeLists.txt
@@ -19,8 +19,3 @@ set(HEADERS GUIViewStatePVR.h
             GUIWindowPVRTimersBase.h)
 
 core_add_library(pvr_windows)
-add_dependencies(pvr_windows libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(pvr_windows ffmpeg)
-endif()
diff --git a/xbmc/pvr/windows/GUIWindowPVRBase.cpp b/xbmc/pvr/windows/GUIWindowPVRBase.cpp
index 310aba0..8b7c7e3 100644
--- a/xbmc/pvr/windows/GUIWindowPVRBase.cpp
+++ b/xbmc/pvr/windows/GUIWindowPVRBase.cpp
@@ -592,8 +592,27 @@ bool CGUIWindowPVRBase::EditTimer(CFileItem *item)
   newTimer->UpdateEntry(timer);
 
   if (ShowTimerSettings(newTimer) && !timer->GetTimerType()->IsReadOnly())
-    return g_PVRTimers->UpdateTimer(newTimer);
+  {
+    if (newTimer->GetTimerType() == timer->GetTimerType())
+    {
+      return g_PVRTimers->UpdateTimer(newTimer);
+    }
+    else
+    {
+      // timer type changed. delete the original timer, then create the new timer. this order is
+      // important. for instance, the new timer might be a rule which schedules the original timer.
+      // deleting the original timer after creating the rule would do literally this and we would
+      // end up with one timer missing wrt to the rule defined by the new timer.
+      if (g_PVRTimers->DeleteTimer(timer, timer->IsRecording(), false))
+      {
+        if (g_PVRTimers->AddTimer(newTimer))
+          return true;
 
+        // rollback.
+        return g_PVRTimers->AddTimer(timer);
+      }
+    }
+  }
   return false;
 }
 
@@ -649,7 +668,7 @@ bool CGUIWindowPVRBase::DeleteTimer(CFileItem *item, bool bIsRecording, bool bDe
     return false;
   }
 
-  if (bDeleteRule && !timer->IsRepeating())
+  if (bDeleteRule && !timer->IsTimerRule())
     timer = g_PVRTimers->GetTimerRule(timer);
 
   if (!timer)
@@ -676,8 +695,9 @@ bool CGUIWindowPVRBase::DeleteTimer(CFileItem *item, bool bIsRecording, bool bDe
   return false;
 }
 
-void CGUIWindowPVRBase::CheckResumeRecording(CFileItem *item)
+bool CGUIWindowPVRBase::CheckResumeRecording(CFileItem *item)
 {
+  bool bPlayIt(true);
   std::string resumeString = CGUIWindowPVRRecordings::GetResumeString(*item);
   if (!resumeString.empty())
   {
@@ -687,7 +707,10 @@ void CGUIWindowPVRBase::CheckResumeRecording(CFileItem *item)
     int choice = CGUIDialogContextMenu::ShowAndGetChoice(choices);
     if (choice > 0)
       item->m_lStartOffset = choice == CONTEXT_BUTTON_RESUME_ITEM ? STARTOFFSET_RESUME : 0;
+    else
+      bPlayIt = false; // context menu cancelled
   }
+  return bPlayIt;
 }
 
 bool CGUIWindowPVRBase::PlayRecording(CFileItem *item, bool bPlayMinimized /* = false */, bool bCheckResume /* = true */)
@@ -698,9 +721,9 @@ bool CGUIWindowPVRBase::PlayRecording(CFileItem *item, bool bPlayMinimized /* =
   std::string stream = item->GetPVRRecordingInfoTag()->m_strStreamURL;
   if (stream.empty())
   {
-    if (bCheckResume)
-      CheckResumeRecording(item);
-    CApplicationMessenger::GetInstance().PostMsg(TMSG_MEDIA_PLAY, 0, 0, static_cast<void*>(new CFileItem(*item)));
+    if (!bCheckResume || CheckResumeRecording(item))
+      CApplicationMessenger::GetInstance().PostMsg(TMSG_MEDIA_PLAY, 0, 0, static_cast<void*>(new CFileItem(*item)));
+
     return true;
   }
 
@@ -750,9 +773,8 @@ bool CGUIWindowPVRBase::PlayRecording(CFileItem *item, bool bPlayMinimized /* =
     return false;
   }
 
-  if (bCheckResume)
-    CheckResumeRecording(item);
-  CApplicationMessenger::GetInstance().PostMsg(TMSG_MEDIA_PLAY, 0, 0, static_cast<void*>(new CFileItem(*item)));
+  if (!bCheckResume || CheckResumeRecording(item))
+    CApplicationMessenger::GetInstance().PostMsg(TMSG_MEDIA_PLAY, 0, 0, static_cast<void*>(new CFileItem(*item)));
 
   return true;
 }
@@ -983,7 +1005,7 @@ bool CGUIWindowPVRBase::ConfirmDeleteTimer(const CPVRTimerInfoTagPtr &timer, boo
     // prompt user for confirmation for deleting the timer
     bConfirmed = CGUIDialogYesNo::ShowAndGetInput(
                         CVariant{122}, // "Confirm delete"
-                        timer->IsRepeating()
+                        timer->IsTimerRule()
                           ? CVariant{845}  // "Are you sure you want to delete this timer rule and all timers it has scheduled?"
                           : CVariant{846}, // "Are you sure you want to delete this timer?"
                         CVariant{""},
diff --git a/xbmc/pvr/windows/GUIWindowPVRBase.h b/xbmc/pvr/windows/GUIWindowPVRBase.h
index ebf1347..0d79977 100644
--- a/xbmc/pvr/windows/GUIWindowPVRBase.h
+++ b/xbmc/pvr/windows/GUIWindowPVRBase.h
@@ -113,7 +113,7 @@ namespace PVR
     virtual bool UpdateEpgForChannel(CFileItem *item);
     virtual void UpdateSelectedItemPath();
     virtual bool IsValidMessage(CGUIMessage& message);
-    void CheckResumeRecording(CFileItem *item);
+    bool CheckResumeRecording(CFileItem *item);
 
     bool OnContextButtonEditTimer(CFileItem *item, CONTEXT_BUTTON button);
     bool OnContextButtonEditTimerRule(CFileItem *item, CONTEXT_BUTTON button);
diff --git a/xbmc/pvr/windows/GUIWindowPVRChannels.cpp b/xbmc/pvr/windows/GUIWindowPVRChannels.cpp
index 8580529..397ac28 100644
--- a/xbmc/pvr/windows/GUIWindowPVRChannels.cpp
+++ b/xbmc/pvr/windows/GUIWindowPVRChannels.cpp
@@ -56,8 +56,7 @@ void CGUIWindowPVRChannels::RegisterObservers(void)
 {
   CSingleLock lock(m_critSection);
   g_EpgContainer.RegisterObserver(this);
-  if (g_PVRTimers)
-    g_PVRTimers->RegisterObserver(this);
+  g_PVRManager.RegisterObserver(this);
   g_infoManager.RegisterObserver(this);
   CGUIWindowPVRBase::RegisterObservers();
 }
@@ -67,8 +66,7 @@ void CGUIWindowPVRChannels::UnregisterObservers(void)
   CSingleLock lock(m_critSection);
   CGUIWindowPVRBase::UnregisterObservers();
   g_infoManager.UnregisterObserver(this);
-  if (g_PVRTimers)
-    g_PVRTimers->UnregisterObserver(this);
+  g_PVRManager.UnregisterObserver(this);
   g_EpgContainer.UnregisterObserver(this);
 }
 
diff --git a/xbmc/pvr/windows/GUIWindowPVRGuide.cpp b/xbmc/pvr/windows/GUIWindowPVRGuide.cpp
index 194d1b5..6b71251 100644
--- a/xbmc/pvr/windows/GUIWindowPVRGuide.cpp
+++ b/xbmc/pvr/windows/GUIWindowPVRGuide.cpp
@@ -99,8 +99,7 @@ void CGUIWindowPVRGuide::RegisterObservers(void)
 {
   CSingleLock lock(m_critSection);
   g_EpgContainer.RegisterObserver(this);
-  if (g_PVRTimers)
-    g_PVRTimers->RegisterObserver(this);
+  g_PVRManager.RegisterObserver(this);
   CGUIWindowPVRBase::RegisterObservers();
 }
 
@@ -108,8 +107,7 @@ void CGUIWindowPVRGuide::UnregisterObservers(void)
 {
   CSingleLock lock(m_critSection);
   CGUIWindowPVRBase::UnregisterObservers();
-  if (g_PVRTimers)
-    g_PVRTimers->UnregisterObserver(this);
+  g_PVRManager.UnregisterObserver(this);
   g_EpgContainer.UnregisterObserver(this);
 }
 
@@ -162,8 +160,10 @@ void CGUIWindowPVRGuide::GetContextButtons(int itemNumber, CContextButtons &butt
       }
 
       const CPVRTimerTypePtr timerType(timer->GetTimerType());
-      if (timerType && !timerType->IsReadOnly())
+      if (timerType && !timerType->IsReadOnly() && timer->GetTimerRuleId() == PVR_TIMER_NO_PARENT)
         buttons.Add(CONTEXT_BUTTON_EDIT_TIMER, 19242);    /* Edit timer */
+      else
+        buttons.Add(CONTEXT_BUTTON_EDIT_TIMER, 19241);    /* View timer information */
 
       if (timer->IsRecording())
         buttons.Add(CONTEXT_BUTTON_STOP_RECORD, 19059);   /* Stop recording */
diff --git a/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp b/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp
index 5ff21c7..d4be0ef 100644
--- a/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp
+++ b/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp
@@ -27,6 +27,7 @@
 #include "guilib/GUIRadioButtonControl.h"
 #include "guilib/GUIWindowManager.h"
 #include "input/Key.h"
+#include "settings/Settings.h"
 #include "threads/SingleLock.h"
 #include "utils/StringUtils.h"
 #include "utils/URIUtils.h"
@@ -52,10 +53,7 @@ CGUIWindowPVRRecordings::CGUIWindowPVRRecordings(bool bRadio) :
 void CGUIWindowPVRRecordings::RegisterObservers(void)
 {
   CSingleLock lock(m_critSection);
-  if (g_PVRRecordings)
-    g_PVRRecordings->RegisterObserver(this);
-  if (g_PVRTimers)
-    g_PVRTimers->RegisterObserver(this);
+  g_PVRManager.RegisterObserver(this);
   g_infoManager.RegisterObserver(this);
   CGUIWindowPVRBase::RegisterObservers();
 }
@@ -65,10 +63,7 @@ void CGUIWindowPVRRecordings::UnregisterObservers(void)
   CSingleLock lock(m_critSection);
   CGUIWindowPVRBase::UnregisterObservers();
   g_infoManager.UnregisterObserver(this);
-  if (g_PVRTimers)
-    g_PVRTimers->UnregisterObserver(this);
-  if (g_PVRRecordings)
-    g_PVRRecordings->UnregisterObserver(this);
+  g_PVRManager.UnregisterObserver(this);
 }
 
 void CGUIWindowPVRRecordings::OnWindowLoaded()
@@ -227,6 +222,8 @@ bool CGUIWindowPVRRecordings::Update(const std::string &strDirectory, bool updat
 
 void CGUIWindowPVRRecordings::UpdateButtons(void)
 {
+  SET_CONTROL_SELECTED(GetID(), CONTROL_BTNGROUPITEMS, CSettings::GetInstance().GetBool(CSettings::SETTING_PVRRECORD_GROUPRECORDINGS));
+
   CGUIRadioButtonControl *btnShowDeleted = (CGUIRadioButtonControl*) GetControl(CONTROL_BTNSHOWDELETED);
   if (btnShowDeleted)
   {
@@ -282,8 +279,8 @@ bool CGUIWindowPVRRecordings::OnMessage(CGUIMessage &message)
       }
       else if (message.GetSenderId() == CONTROL_BTNGROUPITEMS)
       {
-        CGUIRadioButtonControl *radioButton = (CGUIRadioButtonControl*) GetControl(CONTROL_BTNGROUPITEMS);
-        g_PVRRecordings->SetGroupItems(radioButton->IsSelected());
+        CSettings::GetInstance().ToggleBool(CSettings::SETTING_PVRRECORD_GROUPRECORDINGS);
+        CSettings::GetInstance().Save();
         Refresh(true);
       }
       else if (message.GetSenderId() == CONTROL_BTNSHOWDELETED)
diff --git a/xbmc/pvr/windows/GUIWindowPVRSearch.cpp b/xbmc/pvr/windows/GUIWindowPVRSearch.cpp
index 636ed9f..0f3f66c 100644
--- a/xbmc/pvr/windows/GUIWindowPVRSearch.cpp
+++ b/xbmc/pvr/windows/GUIWindowPVRSearch.cpp
@@ -65,8 +65,10 @@ void CGUIWindowPVRSearch::GetContextButtons(int itemNumber, CContextButtons &but
       }
 
       const CPVRTimerTypePtr timerType(timer->GetTimerType());
-      if (timerType && !timerType->IsReadOnly())
+      if (timerType && !timerType->IsReadOnly() && timer->GetTimerRuleId() == PVR_TIMER_NO_PARENT)
         buttons.Add(CONTEXT_BUTTON_EDIT_TIMER, 19242);    /* Edit timer */
+      else
+        buttons.Add(CONTEXT_BUTTON_EDIT_TIMER, 19241);    /* View timer information */
 
       if (timer->IsRecording())
         buttons.Add(CONTEXT_BUTTON_STOP_RECORD, 19059);   /* Stop recording */
diff --git a/xbmc/pvr/windows/GUIWindowPVRTimersBase.cpp b/xbmc/pvr/windows/GUIWindowPVRTimersBase.cpp
index acf7c0b..a2f33d3 100644
--- a/xbmc/pvr/windows/GUIWindowPVRTimersBase.cpp
+++ b/xbmc/pvr/windows/GUIWindowPVRTimersBase.cpp
@@ -48,8 +48,7 @@ CGUIWindowPVRTimersBase::CGUIWindowPVRTimersBase(bool bRadio, int id, const std:
 void CGUIWindowPVRTimersBase::RegisterObservers(void)
 {
   CSingleLock lock(m_critSection);
-  if (g_PVRTimers)
-    g_PVRTimers->RegisterObserver(this);
+  g_PVRManager.RegisterObserver(this);
   g_infoManager.RegisterObserver(this);
   CGUIWindowPVRBase::RegisterObservers();
 }
@@ -59,8 +58,7 @@ void CGUIWindowPVRTimersBase::UnregisterObservers(void)
   CSingleLock lock(m_critSection);
   CGUIWindowPVRBase::UnregisterObservers();
   g_infoManager.UnregisterObserver(this);
-  if (g_PVRTimers)
-    g_PVRTimers->UnregisterObserver(this);
+  g_PVRManager.UnregisterObserver(this);
 }
 
 void CGUIWindowPVRTimersBase::GetContextButtons(int itemNumber, CContextButtons &buttons)
@@ -96,6 +94,8 @@ void CGUIWindowPVRTimersBase::GetContextButtons(int itemNumber, CContextButtons
 
         if (timerType && !timerType->IsReadOnly() && timer->GetTimerRuleId() == PVR_TIMER_NO_PARENT)
           buttons.Add(CONTEXT_BUTTON_EDIT_TIMER, 21450);  /* Edit */
+        else
+          buttons.Add(CONTEXT_BUTTON_EDIT_TIMER, 19241);  /* View timer information */
 
         // As epg-based timers will get it's title from the epg tag, they should not be renamable.
         if (timer->IsManual() && !timerType->IsReadOnly())
@@ -374,12 +374,7 @@ bool CGUIWindowPVRTimersBase::ActionShowTimer(CFileItem *item)
   }
   else
   {
-    const CPVRTimerInfoTagPtr tag(item->GetPVRTimerInfoTag());
-    if (ShowTimerSettings(tag) && !tag->GetTimerType()->IsReadOnly())
-    {
-      /* Update timer on pvr backend */
-      bReturn = g_PVRTimers->UpdateTimer(tag);
-    }
+    bReturn = EditTimer(item);
   }
 
   return bReturn;
diff --git a/xbmc/rendering/dx/CMakeLists.txt b/xbmc/rendering/dx/CMakeLists.txt
index 26d4ec8..38f5d5b 100644
--- a/xbmc/rendering/dx/CMakeLists.txt
+++ b/xbmc/rendering/dx/CMakeLists.txt
@@ -5,7 +5,3 @@ set(HEADERS GUIWindowTestPatternDX.h
             RenderSystemDX.h)
 
 core_add_library(rendering_dx)
-
-if(CORE_SYSTEM_NAME STREQUAL windows)
-  add_dependencies(rendering_dx d3dx11effects)
-endif()
diff --git a/xbmc/rendering/dx/RenderSystemDX.cpp b/xbmc/rendering/dx/RenderSystemDX.cpp
index 1666c87..52634c0 100644
--- a/xbmc/rendering/dx/RenderSystemDX.cpp
+++ b/xbmc/rendering/dx/RenderSystemDX.cpp
@@ -33,8 +33,18 @@
 #include "threads/SingleLock.h"
 #include "utils/MathUtils.h"
 #include "utils/log.h"
-#include "win32/dxerr.h"
-
+#include "platform/win32/dxerr.h"
+#include "utils/SystemInfo.h"
+#pragma warning(disable: 4091)
+#include <d3d10umddi.h>
+#pragma warning(default: 4091)
+#include <algorithm>
+
+#ifndef _M_X64
+#pragma comment(lib, "EasyHook32.lib")
+#else
+#pragma comment(lib, "EasyHook64.lib")
+#endif
 #pragma comment(lib, "d3d11.lib")
 #pragma comment(lib, "dxgi.lib")
 #pragma comment(lib, "dxguid.lib")
@@ -42,6 +52,15 @@
 #define RATIONAL_TO_FLOAT(rational) ((rational.Denominator != 0) ? \
  static_cast<float>(rational.Numerator) / static_cast<float>(rational.Denominator) : 0.0f)
 
+// User Mode Driver hooks definitions
+void APIENTRY HookCreateResource(D3D10DDI_HDEVICE hDevice, const D3D10DDIARG_CREATERESOURCE* pResource, D3D10DDI_HRESOURCE hResource, D3D10DDI_HRTRESOURCE hRtResource);
+HRESULT APIENTRY HookCreateDevice(D3D10DDI_HADAPTER hAdapter, D3D10DDIARG_CREATEDEVICE* pCreateData);
+HRESULT APIENTRY HookOpenAdapter10_2(D3D10DDIARG_OPENADAPTER *pOpenData);
+static PFND3D10DDI_OPENADAPTER s_fnOpenAdapter10_2{ nullptr };
+static PFND3D10DDI_CREATEDEVICE s_fnCreateDeviceOrig{ nullptr };
+static PFND3D10DDI_CREATERESOURCE s_fnCreateResourceOrig{ nullptr };
+CRenderSystemDX* s_windowing{ nullptr };
+
 using namespace DirectX::PackedVector;
 
 CRenderSystemDX::CRenderSystemDX() : CRenderSystemBase()
@@ -54,10 +73,12 @@ CRenderSystemDX::CRenderSystemDX() : CRenderSystemBase()
   ZeroMemory(&m_viewPort, sizeof(m_viewPort));
   ZeroMemory(&m_scissor, sizeof(CRect));
   ZeroMemory(&m_adapterDesc, sizeof(DXGI_ADAPTER_DESC));
+  s_windowing = this;
 }
 
 CRenderSystemDX::~CRenderSystemDX()
 {
+  s_windowing = nullptr;
 }
 
 bool CRenderSystemDX::InitRenderSystem()
@@ -98,8 +119,8 @@ void CRenderSystemDX::SetMonitor(HMONITOR monitor)
   IDXGIAdapter1*  pAdapter;
   for (unsigned i = 0; m_dxgiFactory->EnumAdapters1(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++i)
   {
-    DXGI_ADAPTER_DESC1 adaperDesc;
-    pAdapter->GetDesc1(&adaperDesc);
+    DXGI_ADAPTER_DESC1 adapterDesc;
+    pAdapter->GetDesc1(&adapterDesc);
 
     IDXGIOutput* pOutput;
     for (unsigned j = 0; pAdapter->EnumOutputs(j, &pOutput) != DXGI_ERROR_NOT_FOUND; ++j)
@@ -114,15 +135,18 @@ void CRenderSystemDX::SetMonitor(HMONITOR monitor)
         m_pOutput = pOutput;
 
         // check if adapter is changed
-        if ( m_adapterDesc.AdapterLuid.HighPart != adaperDesc.AdapterLuid.HighPart 
-          || m_adapterDesc.AdapterLuid.LowPart != adaperDesc.AdapterLuid.LowPart)
+        if ( m_adapterDesc.AdapterLuid.HighPart != adapterDesc.AdapterLuid.HighPart 
+          || m_adapterDesc.AdapterLuid.LowPart != adapterDesc.AdapterLuid.LowPart)
         {
-          CLog::Log(LOGDEBUG, __FUNCTION__" - Selected %S adapter. ", m_adapterDesc.Description);
+          CLog::Log(LOGDEBUG, __FUNCTION__" - Selected %S adapter. ", adapterDesc.Description);
 
           pAdapter->GetDesc(&m_adapterDesc);
           SAFE_RELEASE(m_adapter);
           m_adapter = pAdapter;
           m_needNewDevice = true;
+
+          // adapter is changed, (re)init hooks into new driver
+          InitHooks();
           return;
         }
 
@@ -220,8 +244,10 @@ void CRenderSystemDX::GetClosestDisplayModeToCurrent(IDXGIOutput* output, DXGI_M
     DXGI_MODE_DESC current;
     current.Width = devMode.dmPelsWidth;
     current.Height = devMode.dmPelsHeight;
-    current.RefreshRate.Numerator = useDefaultRefreshRate ? 0 : devMode.dmDisplayFrequency;
-    current.RefreshRate.Denominator = useDefaultRefreshRate ? 0 : 1;
+    current.RefreshRate.Numerator = 0;
+    current.RefreshRate.Denominator = 0;
+    if (!useDefaultRefreshRate)
+      GetRefreshRatio(devMode.dmDisplayFrequency, &current.RefreshRate.Numerator, &current.RefreshRate.Denominator);
     current.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
     current.ScanlineOrdering = m_interlaced ? DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST : DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
     current.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
@@ -323,8 +349,10 @@ void CRenderSystemDX::SetFullScreenInternal()
     toMatchMode.Width = m_nBackBufferWidth;
     toMatchMode.Height = m_nBackBufferHeight;
     bool useDefaultRefreshRate = 0 == m_refreshRate;
-    toMatchMode.RefreshRate.Numerator = useDefaultRefreshRate ? 0 : m_refreshRate;
-    toMatchMode.RefreshRate.Denominator = useDefaultRefreshRate ? 0 : 1;
+    toMatchMode.RefreshRate.Numerator = 0;
+    toMatchMode.RefreshRate.Denominator = 0;
+    if (!useDefaultRefreshRate)
+      GetRefreshRatio(static_cast<uint32_t>(m_refreshRate), &toMatchMode.RefreshRate.Numerator, &toMatchMode.RefreshRate.Denominator);
     toMatchMode.Format = scDesc.BufferDesc.Format;
     toMatchMode.Scaling = scDesc.BufferDesc.Scaling;
     toMatchMode.ScanlineOrdering = scDesc.BufferDesc.ScanlineOrdering;
@@ -334,11 +362,13 @@ void CRenderSystemDX::SetFullScreenInternal()
 
     float matchedRefreshRate = RATIONAL_TO_FLOAT(matchedMode.RefreshRate);
     CLog::Log(LOGDEBUG, "%s - Found matched mode: %dx%d@%0.3f", __FUNCTION__, matchedMode.Width, matchedMode.Height, matchedRefreshRate);
-
+    // FindClosestMatchingMode doesn't return "fixed" modes, so wee need to check deviation and force switching mode
+    float diff = fabs(matchedRefreshRate - m_refreshRate) / matchedRefreshRate;
     // change mode if required (current != required)
     if ( currentMode.Width != matchedMode.Width
       || currentMode.Height != matchedMode.Height
-      || currentRefreshRate != matchedRefreshRate)
+      || currentRefreshRate != matchedRefreshRate
+      || diff > 0.0005)
     {
       // change monitor resolution (in fullscreen mode) to required mode
       CLog::Log(LOGDEBUG, "%s - Switching mode to %dx%d@%0.3f.", __FUNCTION__, matchedMode.Width, matchedMode.Height, matchedRefreshRate);
@@ -366,6 +396,7 @@ bool CRenderSystemDX::IsFormatSupport(DXGI_FORMAT format, unsigned int usage)
 
 bool CRenderSystemDX::DestroyRenderSystem()
 {
+  UninitHooks();
   DeleteDevice();
 
   // restore stereo setting on exit
@@ -1750,4 +1781,177 @@ void CRenderSystemDX::SetMaximumFrameLatency(uint8_t latency) const
   }
 }
 
+void CRenderSystemDX::UninitHooks()
+{
+  // uninstall
+  LhUninstallAllHooks();
+  // we need to wait for memory release
+  LhWaitForPendingRemovals();
+  SAFE_DELETE(m_hHook);
+  if (m_hDriverModule)
+  {
+    FreeLibrary(m_hDriverModule);
+    m_hDriverModule = nullptr;
+  }
+}
+
+void CRenderSystemDX::InitHooks()
+{
+  DXGI_OUTPUT_DESC outputDesc;
+  if (!m_pOutput || FAILED(m_pOutput->GetDesc(&outputDesc)))
+    return;
+
+  DISPLAY_DEVICEW displayDevice;
+  displayDevice.cb = sizeof(DISPLAY_DEVICEW);
+  DWORD adapter = 0;
+  bool deviceFound = false;
+
+  // delete exiting hooks.
+  UninitHooks();
+
+  // enum devices to find matched
+  while (EnumDisplayDevicesW(NULL, adapter, &displayDevice, 0))
+  {
+    if (wcscmp(displayDevice.DeviceName, outputDesc.DeviceName) == 0)
+    {
+      deviceFound = true;
+      break;
+    }
+    adapter++;
+  }
+  if (!deviceFound)
+    return;
+
+  CLog::Log(LOGDEBUG, __FUNCTION__": Hookind into UserModeDriver on device %S. ", displayDevice.DeviceKey);
+  wchar_t* keyName =
+#ifndef _M_X64
+    // on x64 system and x32 build use UserModeDriverNameWow key
+    CSysInfo::GetKernelBitness() == 64 ? keyName = L"UserModeDriverNameWow" :
+#endif // !_WIN64
+    L"UserModeDriverName";
+
+  DWORD dwType = REG_MULTI_SZ;
+  HKEY hKey = 0;
+  wchar_t value[1024];
+  DWORD valueLength = sizeof(value);
+  LSTATUS lstat;
+
+  // to void \Registry\Machine at the beginning, we use shifted pointer at 18
+  if (ERROR_SUCCESS == (lstat = RegOpenKeyExW(HKEY_LOCAL_MACHINE, displayDevice.DeviceKey + 18, 0, KEY_READ, &hKey))
+   && ERROR_SUCCESS == (lstat = RegQueryValueExW(hKey, keyName, nullptr, &dwType, (LPBYTE)&value, &valueLength)))
+  {
+    // 1. registry value has a list of drivers for each API with the following format: dx9\0dx10\0dx11\0dx12\0\0
+    // 2. we split the value by \0
+    std::vector<std::wstring> drivers;
+    const wchar_t* pValue = value;
+    while (*pValue)
+    {
+      drivers.push_back(std::wstring(pValue));
+      pValue += drivers.back().size() + 1;
+    }
+    // no entries in the registry
+    if (drivers.empty())
+      return;
+    // 3. we take only first three values (dx12 driver isn't needed if it exists ofc)
+    if (drivers.size() > 3)
+      drivers = std::vector<std::wstring>(drivers.begin(), drivers.begin() + 3);
+    // 4. and then iterate with reverse order to start iterate with the best candidate for d3d11 driver
+    for (auto it = drivers.rbegin(); it != drivers.rend(); ++it)
+    {
+      m_hDriverModule = LoadLibraryW(it->c_str());
+      if (m_hDriverModule != nullptr)
+      {
+        s_fnOpenAdapter10_2 = (PFND3D10DDI_OPENADAPTER)GetProcAddress(m_hDriverModule, "OpenAdapter10_2");
+        if (s_fnOpenAdapter10_2 != nullptr)
+        {
+          ULONG ACLEntries[1] = { 0 };
+          m_hHook = new HOOK_TRACE_INFO();
+          // install and activate hook into a driver
+          if (SUCCEEDED(LhInstallHook(s_fnOpenAdapter10_2, HookOpenAdapter10_2, nullptr, m_hHook))
+           && SUCCEEDED(LhSetInclusiveACL(ACLEntries, 1, m_hHook)))
+          {
+            CLog::Log(LOGDEBUG, __FUNCTION__": D3D11 hook installed and activated.");
+            break;
+          }
+          else
+          {
+            CLog::Log(LOGDEBUG, __FUNCTION__": Unable ot install and activate D3D11 hook.");
+            SAFE_DELETE(m_hHook);
+            FreeLibrary(m_hDriverModule);
+            m_hDriverModule = nullptr;
+          }
+        }
+      }
+    }
+  }
+
+  if (lstat != ERROR_SUCCESS)
+    CLog::Log(LOGDEBUG, __FUNCTION__": error open regystry key with error %ld.", lstat);
+
+  if (hKey != 0)
+    RegCloseKey(hKey);
+}
+
+void CRenderSystemDX::FixRefreshRateIfNecessary(const D3D10DDIARG_CREATERESOURCE* pResource)
+{
+  if (pResource && pResource->pPrimaryDesc)
+  {
+    float refreshRate = RATIONAL_TO_FLOAT(pResource->pPrimaryDesc->ModeDesc.RefreshRate);
+    if (refreshRate > 10.0f && refreshRate < 300.0f)
+    {
+      uint32_t refreshNum, refreshDen;
+      GetRefreshRatio(static_cast<uint32_t>(m_refreshRate), &refreshNum, &refreshDen);
+      float diff = fabs(refreshRate - ((float)refreshNum / (float)refreshDen)) / refreshRate;
+      CLog::Log(LOGDEBUG, __FUNCTION__": refreshRate: %0.4f, desired: %0.4f, deviation: %.5f, fixRequired: %s", 
+                refreshRate, m_refreshRate, diff, (diff > 0.0005) ? "true" : "false");
+      if (diff > 0.0005)
+      {
+        pResource->pPrimaryDesc->ModeDesc.RefreshRate.Numerator = refreshNum;
+        pResource->pPrimaryDesc->ModeDesc.RefreshRate.Denominator = refreshDen;
+        CLog::Log(LOGDEBUG, __FUNCTION__": refreshRate fix applied -> %0.3f", RATIONAL_TO_FLOAT(pResource->pPrimaryDesc->ModeDesc.RefreshRate));
+      }
+    }
+  }
+}
+
+void CRenderSystemDX::GetRefreshRatio(uint32_t refresh, uint32_t * num, uint32_t * den)
+{
+  int i = (((refresh + 1) % 24) == 0 || ((refresh + 1) % 30) == 0) ? 1 : 0;
+  *num = (refresh + i) * 1000;
+  *den = 1000 + i;
+}
+
+void APIENTRY HookCreateResource(D3D10DDI_HDEVICE hDevice, const D3D10DDIARG_CREATERESOURCE* pResource, D3D10DDI_HRESOURCE hResource, D3D10DDI_HRTRESOURCE hRtResource)
+{
+  if (s_windowing && pResource && pResource->pPrimaryDesc)
+  {
+    s_windowing->FixRefreshRateIfNecessary(pResource);
+  }
+  s_fnCreateResourceOrig(hDevice, pResource, hResource, hRtResource);
+}
+
+HRESULT APIENTRY HookCreateDevice(D3D10DDI_HADAPTER hAdapter, D3D10DDIARG_CREATEDEVICE* pCreateData)
+{
+  HRESULT hr = s_fnCreateDeviceOrig(hAdapter, pCreateData);
+  if (pCreateData->pDeviceFuncs->pfnCreateResource)
+  {
+    CLog::Log(LOGDEBUG, __FUNCTION__": hook into pCreateData->pDeviceFuncs->pfnCreateResource");
+    s_fnCreateResourceOrig = pCreateData->pDeviceFuncs->pfnCreateResource;
+    pCreateData->pDeviceFuncs->pfnCreateResource = HookCreateResource;
+  }
+  return hr;
+}
+
+HRESULT APIENTRY HookOpenAdapter10_2(D3D10DDIARG_OPENADAPTER *pOpenData)
+{
+  HRESULT hr = s_fnOpenAdapter10_2(pOpenData);
+  if (pOpenData->pAdapterFuncs->pfnCreateDevice)
+  {
+    CLog::Log(LOGDEBUG, __FUNCTION__": hook into pOpenData->pAdapterFuncs->pfnCreateDevice");
+    s_fnCreateDeviceOrig = pOpenData->pAdapterFuncs->pfnCreateDevice;
+    pOpenData->pAdapterFuncs->pfnCreateDevice = HookCreateDevice;
+  }
+  return hr;
+}
+
 #endif
diff --git a/xbmc/rendering/dx/RenderSystemDX.h b/xbmc/rendering/dx/RenderSystemDX.h
index a07dfc8..bde90e4 100644
--- a/xbmc/rendering/dx/RenderSystemDX.h
+++ b/xbmc/rendering/dx/RenderSystemDX.h
@@ -29,6 +29,7 @@
 #include "rendering/RenderSystem.h"
 #include "guilib/GUIShaderDX.h"
 #include "threads/CriticalSection.h"
+#include "easyhook/easyhook.h"
 
 enum PCI_Vendors
 {
@@ -38,6 +39,7 @@ enum PCI_Vendors
 };
 
 class ID3DResource;
+struct D3D10DDIARG_CREATERESOURCE;
 
 class CRenderSystemDX : public CRenderSystemBase
 {
@@ -90,6 +92,7 @@ public:
   void                    SetAlphaBlendEnable(bool enable);
 
   static std::string GetErrorDescription(HRESULT hr);
+  void FixRefreshRateIfNecessary(const D3D10DDIARG_CREATERESOURCE* pResource);
 
 protected:
   bool CreateDevice();
@@ -116,6 +119,8 @@ protected:
   bool GetDisplayStereoEnabled() const;
   void SetDisplayStereoEnabled(bool enable) const;
   void UpdateDisplayStereoStatus(bool isfirst = false);
+  void InitHooks();
+  void UninitHooks();
 
   virtual void Register(ID3DResource *resource);
   virtual void Unregister(ID3DResource *resource);
@@ -124,6 +129,8 @@ protected:
   virtual void OnDisplayReset() {};
   virtual void OnDisplayBack() {};
 
+  static void GetRefreshRatio(uint32_t refresh, uint32_t* num, uint32_t* den);
+
   // our adapter could change as we go
   bool                        m_needNewDevice{false};
   bool                        m_needNewViews;
@@ -178,6 +185,8 @@ protected:
 #endif
   bool                        m_bDefaultStereoEnabled{false};
   bool                        m_bStereoEnabled{false};
+  TRACED_HOOK_HANDLE          m_hHook{nullptr};
+  HMODULE                     m_hDriverModule{nullptr};
 };
 
 #endif
diff --git a/xbmc/rendering/gl/RenderSystemGL.cpp b/xbmc/rendering/gl/RenderSystemGL.cpp
index fd6ed8d..b987f03 100644
--- a/xbmc/rendering/gl/RenderSystemGL.cpp
+++ b/xbmc/rendering/gl/RenderSystemGL.cpp
@@ -105,7 +105,6 @@ void CRenderSystemGL::CheckOpenGLQuirks()
 bool CRenderSystemGL::InitRenderSystem()
 {
   m_bVSync = false;
-  m_iVSyncMode = 0;
   m_bVsyncInit = false;
   m_maxTextureSize = 2048;
   m_renderCaps = 0;
@@ -306,7 +305,7 @@ void CRenderSystemGL::PresentRender(bool rendered, bool videoLayer)
 
 void CRenderSystemGL::SetVSync(bool enable)
 {
-  if (m_bVSync==enable && m_bVsyncInit == true)
+  if (m_bVSync == enable && m_bVsyncInit == true)
     return;
 
   if (!m_bRenderCreated)
@@ -317,20 +316,10 @@ void CRenderSystemGL::SetVSync(bool enable)
   else
     CLog::Log(LOGINFO, "GL: Disabling VSYNC");
 
-  m_iVSyncMode   = 0;
-  m_iVSyncErrors = 0;
-  m_bVSync       = enable;
-  m_bVsyncInit   = true;
+  m_bVSync = enable;
+  m_bVsyncInit = true;
 
   SetVSyncImpl(enable);
-
-  if (!enable)
-    return;
-
-  if (!m_iVSyncMode)
-    CLog::Log(LOGERROR, "GL: Vertical Blank Syncing unsupported");
-  else
-    CLog::Log(LOGINFO, "GL: Selected vsync mode %d", m_iVSyncMode);
 }
 
 void CRenderSystemGL::FinishPipeline()
diff --git a/xbmc/rendering/gl/RenderSystemGL.h b/xbmc/rendering/gl/RenderSystemGL.h
index 5c6ff78..02f2ce7 100644
--- a/xbmc/rendering/gl/RenderSystemGL.h
+++ b/xbmc/rendering/gl/RenderSystemGL.h
@@ -18,9 +18,6 @@
  *
  */
 
-#ifndef RENDER_SYSTEM_GL_H
-#define RENDER_SYSTEM_GL_H
-
 #pragma once
 
 #include "system.h"
@@ -76,20 +73,16 @@ protected:
   virtual void PresentRenderImpl(bool rendered) = 0;
   void CalculateMaxTexturesize();
 
-  int        m_iVSyncMode;
-  int        m_iVSyncErrors;
-  bool       m_bVsyncInit;
-  int        m_width;
-  int        m_height;
+  bool m_bVsyncInit;
+  int m_width;
+  int m_height;
 
   std::string m_RenderExtensions;
 
-  int        m_glslMajor = 0;
-  int        m_glslMinor = 0;
+  int m_glslMajor = 0;
+  int m_glslMinor = 0;
   
-  GLint      m_viewPort[4];
+  GLint m_viewPort[4];
 
   uint8_t m_latencyCounter = 0;
 };
-
-#endif // RENDER_SYSTEM_H
diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp
index e7f13a7..6beebe0 100644
--- a/xbmc/settings/AdvancedSettings.cpp
+++ b/xbmc/settings/AdvancedSettings.cpp
@@ -156,7 +156,6 @@ void CAdvancedSettings::Initialize()
   m_DXVACheckCompatibility = false;
   m_DXVACheckCompatibilityPresent = false;
   m_DXVAForceProcessorRenderer = true;
-  m_DXVANoDeintProcForProgressive = false;
   m_DXVAAllowHqScaling = true;
   m_videoFpsDetect = 1;
   m_videoBusyDialogDelay_ms = 500;
@@ -644,7 +643,6 @@ void CAdvancedSettings::ParseSettingsFile(const std::string &file)
     m_DXVACheckCompatibilityPresent = XMLUtils::GetBoolean(pElement,"checkdxvacompatibility", m_DXVACheckCompatibility);
 
     XMLUtils::GetBoolean(pElement,"forcedxvarenderer", m_DXVAForceProcessorRenderer);
-    XMLUtils::GetBoolean(pElement,"dxvanodeintforprogressive", m_DXVANoDeintProcForProgressive);
     XMLUtils::GetBoolean(pElement, "dxvaallowhqscaling", m_DXVAAllowHqScaling);
     XMLUtils::GetBoolean(pElement, "usedisplaycontrolhwstereo", m_useDisplayControlHWStereo);
     //0 = disable fps detect, 1 = only detect on timestamps with uniform spacing, 2 detect on all timestamps
diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h
index bcbd5d1..1727580 100644
--- a/xbmc/settings/AdvancedSettings.h
+++ b/xbmc/settings/AdvancedSettings.h
@@ -187,7 +187,6 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler
     bool m_DXVACheckCompatibility;
     bool m_DXVACheckCompatibilityPresent;
     bool m_DXVAForceProcessorRenderer;
-    bool m_DXVANoDeintProcForProgressive;
     bool m_DXVAAllowHqScaling;
     int  m_videoFpsDetect;
     int  m_videoBusyDialogDelay_ms;
diff --git a/xbmc/settings/CMakeLists.txt b/xbmc/settings/CMakeLists.txt
index 59522da..4cbc761 100644
--- a/xbmc/settings/CMakeLists.txt
+++ b/xbmc/settings/CMakeLists.txt
@@ -30,8 +30,3 @@ set(HEADERS AdvancedSettings.h
             VideoSettings.h)
 
 core_add_library(settings)
-add_dependencies(settings libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(settings ffmpeg)
-endif()
diff --git a/xbmc/settings/DisplaySettings.cpp b/xbmc/settings/DisplaySettings.cpp
index 363757d..c1cca7e 100644
--- a/xbmc/settings/DisplaySettings.cpp
+++ b/xbmc/settings/DisplaySettings.cpp
@@ -27,6 +27,8 @@
 #include <utility>
 #include <vector>
 
+#include "cores/VideoPlayer/VideoRenderers/ColorManager.h"
+#include "dialogs/GUIDialogFileBrowser.h"
 #include "guilib/GraphicContext.h"
 #include "guilib/gui3d.h"
 #include "guilib/LocalizeStrings.h"
@@ -36,6 +38,7 @@
 #include "settings/AdvancedSettings.h"
 #include "settings/lib/Setting.h"
 #include "settings/Settings.h"
+#include "storage/MediaManager.h"
 #include "threads/SingleLock.h"
 #include "utils/log.h"
 #include "utils/StringUtils.h"
@@ -221,6 +224,34 @@ void CDisplaySettings::Clear()
   m_nonLinearStretched = false;
 }
 
+void CDisplaySettings::OnSettingAction(const CSetting *setting)
+{
+  if (setting == NULL)
+    return;
+
+  const std::string &settingId = setting->GetId();
+  if (settingId == "videoscreen.cms3dlut")
+  {
+    std::string path = ((CSettingString*)setting)->GetValue();
+    VECSOURCES shares;
+    g_mediaManager.GetLocalDrives(shares);
+    if (CGUIDialogFileBrowser::ShowAndGetFile(shares, ".3dlut", g_localizeStrings.Get(36580), path))
+    {
+      ((CSettingString*)setting)->SetValue(path);
+    }
+  }
+  else if (settingId == "videoscreen.displayprofile")
+  {
+    std::string path = ((CSettingString*)setting)->GetValue();
+    VECSOURCES shares;
+    g_mediaManager.GetLocalDrives(shares);
+    if (CGUIDialogFileBrowser::ShowAndGetFile(shares, ".icc|.icm", g_localizeStrings.Get(36581), path))
+    {
+      ((CSettingString*)setting)->SetValue(path);
+    }
+  }
+}
+
 bool CDisplaySettings::OnSettingChanging(const CSetting *setting)
 {
   if (setting == NULL)
@@ -767,3 +798,36 @@ void CDisplaySettings::ClearCustomResolutions()
     m_resolutions.erase(firstCustom, m_resolutions.end());
   }
 }
+
+void CDisplaySettings::SettingOptionsCmsModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data)
+{
+  list.push_back(std::make_pair(g_localizeStrings.Get(36580), CMS_MODE_3DLUT));
+#ifdef HAVE_LCMS2
+  list.push_back(std::make_pair(g_localizeStrings.Get(36581), CMS_MODE_PROFILE));
+#endif
+}
+
+void CDisplaySettings::SettingOptionsCmsWhitepointsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data)
+{
+  list.push_back(std::make_pair(g_localizeStrings.Get(36586), CMS_WHITEPOINT_D65));
+  list.push_back(std::make_pair(g_localizeStrings.Get(36587), CMS_WHITEPOINT_D93));
+}
+
+void CDisplaySettings::SettingOptionsCmsPrimariesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data)
+{
+  list.push_back(std::make_pair(g_localizeStrings.Get(36588), CMS_PRIMARIES_AUTO));
+  list.push_back(std::make_pair(g_localizeStrings.Get(36589), CMS_PRIMARIES_BT709));
+  list.push_back(std::make_pair(g_localizeStrings.Get(36590), CMS_PRIMARIES_170M));
+  list.push_back(std::make_pair(g_localizeStrings.Get(36591), CMS_PRIMARIES_BT470M));
+  list.push_back(std::make_pair(g_localizeStrings.Get(36592), CMS_PRIMARIES_BT470BG));
+  list.push_back(std::make_pair(g_localizeStrings.Get(36593), CMS_PRIMARIES_240M));
+}
+
+void CDisplaySettings::SettingOptionsCmsGammaModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data)
+{
+  list.push_back(std::make_pair(g_localizeStrings.Get(36582), CMS_TRC_BT1886));
+  list.push_back(std::make_pair(g_localizeStrings.Get(36583), CMS_TRC_INPUT_OFFSET));
+  list.push_back(std::make_pair(g_localizeStrings.Get(36584), CMS_TRC_OUTPUT_OFFSET));
+  list.push_back(std::make_pair(g_localizeStrings.Get(36585), CMS_TRC_ABSOLUTE));
+}
+
diff --git a/xbmc/settings/DisplaySettings.h b/xbmc/settings/DisplaySettings.h
index 729bd94..cd0773b 100644
--- a/xbmc/settings/DisplaySettings.h
+++ b/xbmc/settings/DisplaySettings.h
@@ -42,6 +42,7 @@ public:
   virtual bool Save(TiXmlNode *settings) const override;
   virtual void Clear() override;
 
+  virtual void OnSettingAction(const CSetting *setting);
   virtual bool OnSettingChanging(const CSetting *setting) override;
   virtual bool OnSettingUpdate(CSetting* &setting, const char *oldSettingId, const TiXmlNode *oldSettingNode) override;
 
@@ -97,6 +98,11 @@ public:
   static void SettingOptionsStereoscopicModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data);
   static void SettingOptionsPreferredStereoscopicViewModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data);
   static void SettingOptionsMonitorsFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string &current, void *data);
+  static void SettingOptionsCmsModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data);
+  static void SettingOptionsCmsWhitepointsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data);
+  static void SettingOptionsCmsPrimariesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data);
+  static void SettingOptionsCmsGammaModesFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data);
+  
 
 protected:
   CDisplaySettings();
diff --git a/xbmc/settings/MediaSettings.cpp b/xbmc/settings/MediaSettings.cpp
index 859a3b8..2d9358f 100644
--- a/xbmc/settings/MediaSettings.cpp
+++ b/xbmc/settings/MediaSettings.cpp
@@ -85,24 +85,9 @@ bool CMediaSettings::Load(const TiXmlNode *settings)
   const TiXmlElement *pElement = settings->FirstChildElement("defaultvideosettings");
   if (pElement != NULL)
   {
-    int deinterlaceMode;
-    bool deinterlaceModePresent = XMLUtils::GetInt(pElement, "deinterlacemode", deinterlaceMode, VS_DEINTERLACEMODE_OFF, VS_DEINTERLACEMODE_FORCE);
     int interlaceMethod;
     bool interlaceMethodPresent = XMLUtils::GetInt(pElement, "interlacemethod", interlaceMethod, VS_INTERLACEMETHOD_AUTO, VS_INTERLACEMETHOD_MAX);
-    // For smooth conversion of settings stored before the deinterlaceMode existed
-    if (!deinterlaceModePresent && interlaceMethodPresent)
-    {
-      if (interlaceMethod == VS_INTERLACEMETHOD_NONE)
-      {
-        deinterlaceMode = VS_DEINTERLACEMODE_OFF;
-        interlaceMethod = VS_INTERLACEMETHOD_AUTO;
-      }
-      else if (interlaceMethod == VS_INTERLACEMETHOD_AUTO)
-        deinterlaceMode = VS_DEINTERLACEMODE_AUTO;
-      else
-        deinterlaceMode = VS_DEINTERLACEMODE_FORCE;
-    }
-    m_defaultVideoSettings.m_DeinterlaceMode = (EDEINTERLACEMODE)deinterlaceMode;
+
     m_defaultVideoSettings.m_InterlaceMethod = (EINTERLACEMETHOD)interlaceMethod;
     int scalingMethod;
     if (!XMLUtils::GetInt(pElement, "scalingmethod", scalingMethod, VS_SCALINGMETHOD_NEAREST, VS_SCALINGMETHOD_MAX))
@@ -226,7 +211,6 @@ bool CMediaSettings::Save(TiXmlNode *settings) const
   if (pNode == NULL)
     return false;
 
-  XMLUtils::SetInt(pNode, "deinterlacemode", m_defaultVideoSettings.m_DeinterlaceMode);
   XMLUtils::SetInt(pNode, "interlacemethod", m_defaultVideoSettings.m_InterlaceMethod);
   XMLUtils::SetInt(pNode, "scalingmethod", m_defaultVideoSettings.m_ScalingMethod);
   XMLUtils::SetFloat(pNode, "noisereduction", m_defaultVideoSettings.m_NoiseReduction);
diff --git a/xbmc/settings/SettingConditions.cpp b/xbmc/settings/SettingConditions.cpp
index fede213..7870ce0 100644
--- a/xbmc/settings/SettingConditions.cpp
+++ b/xbmc/settings/SettingConditions.cpp
@@ -326,6 +326,9 @@ void CSettingConditions::Initialize()
   m_simpleConditions.insert("has_dx");
   m_simpleConditions.insert("hasdxva2");
 #endif
+#ifdef HAVE_LCMS2
+  m_simpleConditions.insert("have_lcms2");
+#endif
 
   if (g_application.IsStandAlone())
     m_simpleConditions.insert("isstandalone");
diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp
index 1d9e02b..a8114aa 100644
--- a/xbmc/settings/Settings.cpp
+++ b/xbmc/settings/Settings.cpp
@@ -131,7 +131,6 @@ const std::string CSettings::SETTING_VIDEOLIBRARY_SHOWUNWATCHEDPLOTS = "videolib
 const std::string CSettings::SETTING_VIDEOLIBRARY_ACTORTHUMBS = "videolibrary.actorthumbs";
 const std::string CSettings::SETTING_MYVIDEOS_FLATTEN = "myvideos.flatten";
 const std::string CSettings::SETTING_VIDEOLIBRARY_FLATTENTVSHOWS = "videolibrary.flattentvshows";
-const std::string CSettings::SETTING_VIDEOLIBRARY_REMOVE_DUPLICATES = "videolibrary.removeduplicates";
 const std::string CSettings::SETTING_VIDEOLIBRARY_TVSHOWSSELECTFIRSTUNWATCHEDITEM = "videolibrary.tvshowsselectfirstunwatcheditem";
 const std::string CSettings::SETTING_VIDEOLIBRARY_TVSHOWSINCLUDEALLSEASONSANDSPECIALS = "videolibrary.tvshowsincludeallseasonsandspecials";
 const std::string CSettings::SETTING_VIDEOLIBRARY_SHOWALLITEMS = "videolibrary.showallitems";
@@ -250,6 +249,7 @@ const std::string CSettings::SETTING_PVRRECORD_MARGINSTART = "pvrrecord.marginst
 const std::string CSettings::SETTING_PVRRECORD_MARGINEND = "pvrrecord.marginend";
 const std::string CSettings::SETTING_PVRRECORD_PREVENTDUPLICATEEPISODES = "pvrrecord.preventduplicateepisodes";
 const std::string CSettings::SETTING_PVRRECORD_TIMERNOTIFICATIONS = "pvrrecord.timernotifications";
+const std::string CSettings::SETTING_PVRRECORD_GROUPRECORDINGS = "pvrrecord.grouprecordings";
 const std::string CSettings::SETTING_PVRPOWERMANAGEMENT_ENABLED = "pvrpowermanagement.enabled";
 const std::string CSettings::SETTING_PVRPOWERMANAGEMENT_BACKENDIDLETIME = "pvrpowermanagement.backendidletime";
 const std::string CSettings::SETTING_PVRPOWERMANAGEMENT_SETWAKEUPCMD = "pvrpowermanagement.setwakeupcmd";
@@ -341,6 +341,8 @@ const std::string CSettings::SETTING_VIDEOSCREEN_BLANKDISPLAYS = "videoscreen.bl
 const std::string CSettings::SETTING_VIDEOSCREEN_STEREOSCOPICMODE = "videoscreen.stereoscopicmode";
 const std::string CSettings::SETTING_VIDEOSCREEN_PREFEREDSTEREOSCOPICMODE = "videoscreen.preferedstereoscopicmode";
 const std::string CSettings::SETTING_VIDEOSCREEN_NOOFBUFFERS = "videoscreen.noofbuffers";
+const std::string CSettings::SETTING_VIDEOSCREEN_3DLUT = "videoscreen.cms3dlut";
+const std::string CSettings::SETTING_VIDEOSCREEN_DISPLAYPROFILE = "videoscreen.displayprofile";
 const std::string CSettings::SETTING_VIDEOSCREEN_GUICALIBRATION = "videoscreen.guicalibration";
 const std::string CSettings::SETTING_VIDEOSCREEN_TESTPATTERN = "videoscreen.testpattern";
 const std::string CSettings::SETTING_VIDEOSCREEN_LIMITEDRANGE = "videoscreen.limitedrange";
@@ -351,7 +353,6 @@ const std::string CSettings::SETTING_AUDIOOUTPUT_CONFIG = "audiooutput.config";
 const std::string CSettings::SETTING_AUDIOOUTPUT_SAMPLERATE = "audiooutput.samplerate";
 const std::string CSettings::SETTING_AUDIOOUTPUT_STEREOUPMIX = "audiooutput.stereoupmix";
 const std::string CSettings::SETTING_AUDIOOUTPUT_MAINTAINORIGINALVOLUME = "audiooutput.maintainoriginalvolume";
-const std::string CSettings::SETTING_AUDIOOUTPUT_NORMALIZELEVELS = "audiooutput.normalizelevels";
 const std::string CSettings::SETTING_AUDIOOUTPUT_PROCESSQUALITY = "audiooutput.processquality";
 const std::string CSettings::SETTING_AUDIOOUTPUT_STREAMSILENCE = "audiooutput.streamsilence";
 const std::string CSettings::SETTING_AUDIOOUTPUT_DSPADDONSENABLED = "audiooutput.dspaddonsenabled";
@@ -412,6 +413,9 @@ const std::string CSettings::SETTING_ADDONS_ALLOW_UNKNOWN_SOURCES = "addons.unkn
 const std::string CSettings::SETTING_ADDONS_MANAGE_DEPENDENCIES = "addons.managedependencies";
 const std::string CSettings::SETTING_GENERAL_ADDONFOREIGNFILTER = "general.addonforeignfilter";
 const std::string CSettings::SETTING_GENERAL_ADDONBROKENFILTER = "general.addonbrokenfilter";
+const std::string CSettings::SETTING_SOURCE_VIDEOS = "source.videos";
+const std::string CSettings::SETTING_SOURCE_MUSIC = "source.music";
+const std::string CSettings::SETTING_SOURCE_PICTURES = "source.pictures";
 
 CSettings::CSettings()
   : m_initialized(false)
@@ -575,6 +579,10 @@ void CSettings::Uninitialize()
   m_settingsManager->UnregisterSettingOptionsFiller("stereoscopicmodes");
   m_settingsManager->UnregisterSettingOptionsFiller("preferedstereoscopicviewmodes");
   m_settingsManager->UnregisterSettingOptionsFiller("monitors");
+  m_settingsManager->UnregisterSettingOptionsFiller("cmsmodes");
+  m_settingsManager->UnregisterSettingOptionsFiller("cmswhitepoints");
+  m_settingsManager->UnregisterSettingOptionsFiller("cmsprimaries");
+  m_settingsManager->UnregisterSettingOptionsFiller("cmsgammamodes");
   m_settingsManager->UnregisterSettingOptionsFiller("videoseeksteps");
   m_settingsManager->UnregisterSettingOptionsFiller("shutdownstates");
   m_settingsManager->UnregisterSettingOptionsFiller("startupwindows");
@@ -931,6 +939,10 @@ void CSettings::InitializeOptionFillers()
   m_settingsManager->RegisterSettingOptionsFiller("stereoscopicmodes", CDisplaySettings::SettingOptionsStereoscopicModesFiller);
   m_settingsManager->RegisterSettingOptionsFiller("preferedstereoscopicviewmodes", CDisplaySettings::SettingOptionsPreferredStereoscopicViewModesFiller);
   m_settingsManager->RegisterSettingOptionsFiller("monitors", CDisplaySettings::SettingOptionsMonitorsFiller);
+  m_settingsManager->RegisterSettingOptionsFiller("cmsmodes", CDisplaySettings::SettingOptionsCmsModesFiller);
+  m_settingsManager->RegisterSettingOptionsFiller("cmswhitepoints", CDisplaySettings::SettingOptionsCmsWhitepointsFiller);
+  m_settingsManager->RegisterSettingOptionsFiller("cmsprimaries", CDisplaySettings::SettingOptionsCmsPrimariesFiller);
+  m_settingsManager->RegisterSettingOptionsFiller("cmsgammamodes", CDisplaySettings::SettingOptionsCmsGammaModesFiller);
   m_settingsManager->RegisterSettingOptionsFiller("videoseeksteps", CSeekHandler::SettingOptionsSeekStepsFiller);
   m_settingsManager->RegisterSettingOptionsFiller("shutdownstates", CPowerManager::SettingOptionsShutdownStatesFiller);
   m_settingsManager->RegisterSettingOptionsFiller("startupwindows", ADDON::CSkinInfo::SettingOptionsStartupWindowsFiller);
@@ -1016,7 +1028,6 @@ void CSettings::InitializeISettingCallbacks()
   settingSet.insert(CSettings::SETTING_MUSICLIBRARY_IMPORT);
   settingSet.insert(CSettings::SETTING_MUSICFILES_TRACKFORMAT);
   settingSet.insert(CSettings::SETTING_VIDEOLIBRARY_FLATTENTVSHOWS);
-  settingSet.insert(CSettings::SETTING_VIDEOLIBRARY_REMOVE_DUPLICATES);
   settingSet.insert(CSettings::SETTING_VIDEOLIBRARY_GROUPMOVIESETS);
   settingSet.insert(CSettings::SETTING_VIDEOLIBRARY_CLEANUP);
   settingSet.insert(CSettings::SETTING_VIDEOLIBRARY_IMPORT);
@@ -1029,6 +1040,8 @@ void CSettings::InitializeISettingCallbacks()
   settingSet.insert(CSettings::SETTING_VIDEOSCREEN_SCREENMODE);
   settingSet.insert(CSettings::SETTING_VIDEOSCREEN_MONITOR);
   settingSet.insert(CSettings::SETTING_VIDEOSCREEN_PREFEREDSTEREOSCOPICMODE);
+  settingSet.insert(CSettings::SETTING_VIDEOSCREEN_3DLUT);
+  settingSet.insert(CSettings::SETTING_VIDEOSCREEN_DISPLAYPROFILE);
   m_settingsManager->RegisterCallback(&CDisplaySettings::GetInstance(), settingSet);
   
   settingSet.clear();
@@ -1060,7 +1073,6 @@ void CSettings::InitializeISettingCallbacks()
   settingSet.insert(CSettings::SETTING_AUDIOOUTPUT_PASSTHROUGHDEVICE);
   settingSet.insert(CSettings::SETTING_AUDIOOUTPUT_STREAMSILENCE);
   settingSet.insert(CSettings::SETTING_AUDIOOUTPUT_MAINTAINORIGINALVOLUME);
-  settingSet.insert(CSettings::SETTING_AUDIOOUTPUT_NORMALIZELEVELS);
   settingSet.insert(CSettings::SETTING_AUDIOOUTPUT_DSPADDONSENABLED);
   settingSet.insert(CSettings::SETTING_LOOKANDFEEL_SKIN);
   settingSet.insert(CSettings::SETTING_LOOKANDFEEL_SKINSETTINGS);
@@ -1083,6 +1095,9 @@ void CSettings::InitializeISettingCallbacks()
   settingSet.insert(CSettings::SETTING_VIDEOPLAYER_USEMEDIACODEC);
   settingSet.insert(CSettings::SETTING_VIDEOPLAYER_USEMEDIACODECSURFACE);
   settingSet.insert(CSettings::SETTING_AUDIOOUTPUT_VOLUMESTEPS);
+  settingSet.insert(CSettings::SETTING_SOURCE_VIDEOS);
+  settingSet.insert(CSettings::SETTING_SOURCE_MUSIC);
+  settingSet.insert(CSettings::SETTING_SOURCE_PICTURES);
   m_settingsManager->RegisterCallback(&g_application, settingSet);
 
   settingSet.clear();
diff --git a/xbmc/settings/Settings.h b/xbmc/settings/Settings.h
index f6d1d42..be37b69 100644
--- a/xbmc/settings/Settings.h
+++ b/xbmc/settings/Settings.h
@@ -88,7 +88,6 @@ public:
   static const std::string SETTING_VIDEOLIBRARY_ACTORTHUMBS;
   static const std::string SETTING_MYVIDEOS_FLATTEN;
   static const std::string SETTING_VIDEOLIBRARY_FLATTENTVSHOWS;
-  static const std::string SETTING_VIDEOLIBRARY_REMOVE_DUPLICATES;
   static const std::string SETTING_VIDEOLIBRARY_TVSHOWSSELECTFIRSTUNWATCHEDITEM;
   static const std::string SETTING_VIDEOLIBRARY_TVSHOWSINCLUDEALLSEASONSANDSPECIALS;
   static const std::string SETTING_VIDEOLIBRARY_SHOWALLITEMS;
@@ -207,6 +206,7 @@ public:
   static const std::string SETTING_PVRRECORD_MARGINEND;
   static const std::string SETTING_PVRRECORD_PREVENTDUPLICATEEPISODES;
   static const std::string SETTING_PVRRECORD_TIMERNOTIFICATIONS;
+  static const std::string SETTING_PVRRECORD_GROUPRECORDINGS;
   static const std::string SETTING_PVRPOWERMANAGEMENT_ENABLED;
   static const std::string SETTING_PVRPOWERMANAGEMENT_BACKENDIDLETIME;
   static const std::string SETTING_PVRPOWERMANAGEMENT_SETWAKEUPCMD;
@@ -298,6 +298,8 @@ public:
   static const std::string SETTING_VIDEOSCREEN_STEREOSCOPICMODE;
   static const std::string SETTING_VIDEOSCREEN_PREFEREDSTEREOSCOPICMODE;
   static const std::string SETTING_VIDEOSCREEN_NOOFBUFFERS;
+  static const std::string SETTING_VIDEOSCREEN_3DLUT;
+  static const std::string SETTING_VIDEOSCREEN_DISPLAYPROFILE;
   static const std::string SETTING_VIDEOSCREEN_GUICALIBRATION;
   static const std::string SETTING_VIDEOSCREEN_TESTPATTERN;
   static const std::string SETTING_VIDEOSCREEN_LIMITEDRANGE;
@@ -308,7 +310,6 @@ public:
   static const std::string SETTING_AUDIOOUTPUT_SAMPLERATE;
   static const std::string SETTING_AUDIOOUTPUT_STEREOUPMIX;
   static const std::string SETTING_AUDIOOUTPUT_MAINTAINORIGINALVOLUME;
-  static const std::string SETTING_AUDIOOUTPUT_NORMALIZELEVELS;
   static const std::string SETTING_AUDIOOUTPUT_PROCESSQUALITY;
   static const std::string SETTING_AUDIOOUTPUT_STREAMSILENCE;
   static const std::string SETTING_AUDIOOUTPUT_DSPADDONSENABLED;
@@ -369,6 +370,9 @@ public:
   static const std::string SETTING_ADDONS_ALLOW_UNKNOWN_SOURCES;
   static const std::string SETTING_GENERAL_ADDONFOREIGNFILTER;
   static const std::string SETTING_GENERAL_ADDONBROKENFILTER;
+  static const std::string SETTING_SOURCE_VIDEOS;
+  static const std::string SETTING_SOURCE_MUSIC;
+  static const std::string SETTING_SOURCE_PICTURES;
 
   /*!
    \brief Creates a new settings wrapper around a new settings manager.
diff --git a/xbmc/settings/VideoSettings.cpp b/xbmc/settings/VideoSettings.cpp
index 812bead..2f91cca 100644
--- a/xbmc/settings/VideoSettings.cpp
+++ b/xbmc/settings/VideoSettings.cpp
@@ -29,7 +29,6 @@
 
 CVideoSettings::CVideoSettings()
 {
-  m_DeinterlaceMode = VS_DEINTERLACEMODE_AUTO;
   m_InterlaceMethod = VS_INTERLACEMETHOD_AUTO;
   m_ScalingMethod = VS_SCALINGMETHOD_LINEAR;
   m_ViewMode = ViewModeNormal;
@@ -60,7 +59,6 @@ CVideoSettings::CVideoSettings()
 
 bool CVideoSettings::operator!=(const CVideoSettings &right) const
 {
-  if (m_DeinterlaceMode != right.m_DeinterlaceMode) return true;
   if (m_InterlaceMethod != right.m_InterlaceMethod) return true;
   if (m_ScalingMethod != right.m_ScalingMethod) return true;
   if (m_ViewMode != right.m_ViewMode) return true;
diff --git a/xbmc/settings/VideoSettings.h b/xbmc/settings/VideoSettings.h
index 8ad208a..0638b5f 100644
--- a/xbmc/settings/VideoSettings.h
+++ b/xbmc/settings/VideoSettings.h
@@ -35,7 +35,6 @@ public:
 
   bool operator!=(const CVideoSettings &right) const;
 
-  EDEINTERLACEMODE m_DeinterlaceMode;
   EINTERLACEMETHOD m_InterlaceMethod;
   ESCALINGMETHOD   m_ScalingMethod;
   int m_ViewMode;   // current view mode
diff --git a/xbmc/settings/dialogs/CMakeLists.txt b/xbmc/settings/dialogs/CMakeLists.txt
index b8477e2..666601b 100644
--- a/xbmc/settings/dialogs/CMakeLists.txt
+++ b/xbmc/settings/dialogs/CMakeLists.txt
@@ -13,8 +13,3 @@ set(HEADERS GUIDialogAudioDSPManager.h
             GUIDialogSettingsManualBase.h)
 
 core_add_library(settings_dialogs)
-add_dependencies(settings_dialogs libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(settings_dialogs ffmpeg)
-endif()
diff --git a/xbmc/settings/windows/CMakeLists.txt b/xbmc/settings/windows/CMakeLists.txt
index 76745ca..b258610 100644
--- a/xbmc/settings/windows/CMakeLists.txt
+++ b/xbmc/settings/windows/CMakeLists.txt
@@ -11,4 +11,3 @@ set(HEADERS GUIControlSettings.h
             GUIWindowTestPattern.h)
 
 core_add_library(settings_windows)
-add_dependencies(settings_windows libcpluff)
diff --git a/xbmc/settings/windows/GUIWindowSettingsCategory.cpp b/xbmc/settings/windows/GUIWindowSettingsCategory.cpp
index 2cc18d0..d32cfbe 100644
--- a/xbmc/settings/windows/GUIWindowSettingsCategory.cpp
+++ b/xbmc/settings/windows/GUIWindowSettingsCategory.cpp
@@ -35,7 +35,7 @@
 #define SETTINGS_SERVICE                WINDOW_SETTINGS_SERVICE - WINDOW_SETTINGS_START
 #define SETTINGS_PVR                    WINDOW_SETTINGS_MYPVR - WINDOW_SETTINGS_START
 #define SETTINGS_PLAYER                 WINDOW_SETTINGS_PLAYER - WINDOW_SETTINGS_START
-#define SETTINGS_LIBRARY                WINDOW_SETTINGS_LIBRARY - WINDOW_SETTINGS_START
+#define SETTINGS_MEDIA                  WINDOW_SETTINGS_MEDIA - WINDOW_SETTINGS_START
 #define SETTINGS_INTERFACE              WINDOW_SETTINGS_INTERFACE - WINDOW_SETTINGS_START
 
 #define CONTRL_BTN_LEVELS               20
@@ -49,7 +49,7 @@ static const SettingGroup s_settingGroupMap[] = { { SETTINGS_SYSTEM,      "syste
                                                   { SETTINGS_SERVICE,     "services" },
                                                   { SETTINGS_PVR,         "pvr" },
                                                   { SETTINGS_PLAYER,      "player" },
-                                                  { SETTINGS_LIBRARY,     "library" },
+                                                  { SETTINGS_MEDIA,       "media" },
                                                   { SETTINGS_INTERFACE,   "interface" } };
                                                   
 #define SettingGroupSize sizeof(s_settingGroupMap) / sizeof(SettingGroup)
@@ -68,7 +68,7 @@ CGUIWindowSettingsCategory::CGUIWindowSettingsCategory()
   m_idRange.push_back(WINDOW_SETTINGS_SERVICE);
   m_idRange.push_back(WINDOW_SETTINGS_MYPVR);
   m_idRange.push_back(WINDOW_SETTINGS_PLAYER);
-  m_idRange.push_back(WINDOW_SETTINGS_LIBRARY);
+  m_idRange.push_back(WINDOW_SETTINGS_MEDIA);
   m_idRange.push_back(WINDOW_SETTINGS_INTERFACE);
 }
 
diff --git a/xbmc/storage/CMakeLists.txt b/xbmc/storage/CMakeLists.txt
index 5604ad7..29b1b5b 100644
--- a/xbmc/storage/CMakeLists.txt
+++ b/xbmc/storage/CMakeLists.txt
@@ -12,11 +12,3 @@ set(HEADERS AutorunMediaJob.h
             MediaManager.h)
 
 core_add_library(storage)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(storage ffmpeg)
-endif()
-
-if(NOT CORE_SYSTEM_NAME STREQUAL windows)
-  add_dependencies(storage dvdnav)
-endif()
diff --git a/xbmc/storage/MediaManager.cpp b/xbmc/storage/MediaManager.cpp
index b0dbc84..62a4676 100644
--- a/xbmc/storage/MediaManager.cpp
+++ b/xbmc/storage/MediaManager.cpp
@@ -347,7 +347,7 @@ bool CMediaManager::IsDiscInDrive(const std::string& devicePath)
   if(!m_bhasoptical)
     return false;
 
-  std::string strDevice = TranslateDevicePath(devicePath, true);
+  std::string strDevice = TranslateDevicePath(devicePath, false);
   std::map<std::string,CCdInfo*>::iterator it;
   CSingleLock waitLock(m_muAutoSource);
   it = m_mapCdInfo.find(strDevice);
@@ -439,7 +439,7 @@ CCdInfo* CMediaManager::GetCdInfo(const std::string& devicePath)
   if(!m_bhasoptical)
     return NULL;
   
-  std::string strDevice = TranslateDevicePath(devicePath, true);
+  std::string strDevice = TranslateDevicePath(devicePath, false);
   std::map<std::string,CCdInfo*>::iterator it;
   {
     CSingleLock waitLock(m_muAutoSource);
@@ -468,7 +468,7 @@ bool CMediaManager::RemoveCdInfo(const std::string& devicePath)
   if(!m_bhasoptical)
     return false;
 
-  std::string strDevice = TranslateDevicePath(devicePath, true);
+  std::string strDevice = TranslateDevicePath(devicePath, false);
 
   std::map<std::string,CCdInfo*>::iterator it;
   CSingleLock waitLock(m_muAutoSource);
diff --git a/xbmc/storage/cdioSupport.cpp b/xbmc/storage/cdioSupport.cpp
index 2c278eb..3eb7c6d 100644
--- a/xbmc/storage/cdioSupport.cpp
+++ b/xbmc/storage/cdioSupport.cpp
@@ -26,13 +26,14 @@
 #include "threads/SingleLock.h"
 #include "utils/log.h"
 #include "utils/Environment.h"
+#include <cdio/cdio.h>
 #include <cdio/logging.h>
 #include <cdio/util.h>
 #include <cdio/mmc.h>
 #include <cdio/cd_types.h>
 
 #if defined(TARGET_WINDOWS)
-#pragma comment(lib, "libcdio.dll.lib")
+#pragma comment(lib, "libcdio.lib")
 #endif
 
 using namespace MEDIA_DETECT;
diff --git a/xbmc/storage/osx/DarwinStorageProvider.cpp b/xbmc/storage/osx/DarwinStorageProvider.cpp
index b505f30..6d3020f 100644
--- a/xbmc/storage/osx/DarwinStorageProvider.cpp
+++ b/xbmc/storage/osx/DarwinStorageProvider.cpp
@@ -45,10 +45,22 @@ void CDarwinStorageProvider::GetLocalDrives(VECSOURCES &localDrives)
   CMediaSource share;
 
   // User home folder
-  share.strPath = getenv("HOME");
+  #ifdef TARGET_DARWIN_IOS
+    share.strPath = "special://envhome/";
+  #else
+    share.strPath = getenv("HOME");
+  #endif
   share.strName = g_localizeStrings.Get(21440);
   share.m_ignore = true;
   localDrives.push_back(share);
+  
+#if defined(TARGET_DARWIN_IOS)
+  // iOS Inbox folder
+  share.strPath = "special://envhome/Documents/Inbox";
+  share.strName = "Inbox";
+  share.m_ignore = true;
+  localDrives.push_back(share);
+#endif
 
 #if defined(TARGET_DARWIN_OSX)
   // User desktop folder
diff --git a/xbmc/test/TestBasicEnvironment.cpp b/xbmc/test/TestBasicEnvironment.cpp
index 58ccf4d..f7ec852 100644
--- a/xbmc/test/TestBasicEnvironment.cpp
+++ b/xbmc/test/TestBasicEnvironment.cpp
@@ -20,6 +20,7 @@
 
 #include "TestBasicEnvironment.h"
 #include "TestUtils.h"
+#include "cores/DataCacheCore.h"
 #include "cores/AudioEngine/Engines/ActiveAE/AudioDSPAddons/ActiveAEDSP.h"
 #include "filesystem/Directory.h"
 #include "filesystem/File.h"
@@ -35,7 +36,7 @@
 #include "pvr/PVRManager.h"
 
 #if defined(TARGET_WINDOWS)
-#include "win32/WIN32Util.h"
+#include "platform/win32/WIN32Util.h"
 #endif
 
 #include <cstdio>
@@ -92,7 +93,6 @@ void TestBasicEnvironment::SetUp()
   if (!CreateDirectory(lpTempPathBuffer, NULL))
     SetUpError();
   CSpecialProtocol::SetTempPath(lpTempPathBuffer);
-  CWIN32Util::ExtendDllPath(); //Needed for delay loading on windows
 #else
   char buf[MAX_PATH];
   char *tmp;
diff --git a/xbmc/threads/Event.cpp b/xbmc/threads/Event.cpp
index ce58111..b7e5282 100644
--- a/xbmc/threads/Event.cpp
+++ b/xbmc/threads/Event.cpp
@@ -120,6 +120,7 @@ namespace XbmcThreads
          signaled == NULL && iter != events.end(); ++iter)
     {
       CEvent* cur = *iter;
+      CSingleLock lock2(cur->mutex);
       if (cur->signaled) 
         signaled = cur;
     }
diff --git a/xbmc/threads/Thread.h b/xbmc/threads/Thread.h
index bb1c9be..ce377bd 100644
--- a/xbmc/threads/Thread.h
+++ b/xbmc/threads/Thread.h
@@ -24,6 +24,7 @@
 
 #pragma once
 
+#include <atomic>
 #include <string>
 #include <stdint.h>
 #include "Event.h"
@@ -91,7 +92,7 @@ protected:
   virtual void OnExit(){};
   virtual void Process();
 
-  volatile bool m_bStop;
+  std::atomic<bool> m_bStop;
 
   enum WaitResponse { WAIT_INTERRUPTED = -1, WAIT_SIGNALED = 0, WAIT_TIMEDOUT = 1 };
 
diff --git a/xbmc/threads/platform/win/ThreadImpl.cpp b/xbmc/threads/platform/win/ThreadImpl.cpp
index 843839f..5f33187 100644
--- a/xbmc/threads/platform/win/ThreadImpl.cpp
+++ b/xbmc/threads/platform/win/ThreadImpl.cpp
@@ -21,7 +21,7 @@
 #include <windows.h>
 #include <process.h>
 #include "threads/platform/win/Win32Exception.h"
-#include "../../win32/WIN32Util.h"
+#include "platform/win32/WIN32Util.h"
 
 void CThread::SpawnThread(unsigned stacksize)
 {
diff --git a/xbmc/threads/test/CMakeLists.txt b/xbmc/threads/test/CMakeLists.txt
index 8c1fb36..67bbe76 100644
--- a/xbmc/threads/test/CMakeLists.txt
+++ b/xbmc/threads/test/CMakeLists.txt
@@ -6,5 +6,3 @@ set(SOURCES TestEvent.cpp
 set(HEADERS TestHelpers.h)
 
 core_add_test_library(threads_test)
-target_include_directories(threads_test
-                           PRIVATE ${CORE_SOURCE_DIR}/lib/gtest/include)
diff --git a/xbmc/utils/AMLUtils.cpp b/xbmc/utils/AMLUtils.cpp
index 4ae45f3..80fb453 100644
--- a/xbmc/utils/AMLUtils.cpp
+++ b/xbmc/utils/AMLUtils.cpp
@@ -30,7 +30,6 @@
 #include "utils/log.h"
 #include "utils/SysfsUtils.h"
 #include "utils/StringUtils.h"
-#include "utils/AMLUtils.h"
 #include "guilib/gui3d.h"
 #include "utils/RegExp.h"
 
diff --git a/xbmc/utils/Archive.cpp b/xbmc/utils/Archive.cpp
index 56fd2c9..db0b910 100644
--- a/xbmc/utils/Archive.cpp
+++ b/xbmc/utils/Archive.cpp
@@ -18,11 +18,16 @@
  *
  */
 
-#include <algorithm>
-#include <cstring>
 #include "Archive.h"
-#include "IArchivable.h"
+
+#include <cstdint>
+#include <cstring>
+
+#include <algorithm>
+#include <stdexcept>
+
 #include "filesystem/File.h"
+#include "IArchivable.h"
 #include "utils/Variant.h"
 #include "utils/log.h"
 
@@ -32,21 +37,26 @@
 
 using namespace XFILE;
 
+//arbitrarily chosen, should be plenty big enough for our strings
+//without causing random bad things happening
+//not very bad, just tiny bad
+#define MAX_STRING_SIZE 100*1024*1024
+
 CArchive::CArchive(CFile* pFile, int mode)
 {
   m_pFile = pFile;
   m_iMode = mode;
 
-  m_pBuffer = new uint8_t[CARCHIVE_BUFFER_MAX];
-  memset(m_pBuffer, 0, CARCHIVE_BUFFER_MAX);
+  m_pBuffer = std::unique_ptr<uint8_t[]>(new uint8_t[CARCHIVE_BUFFER_MAX]);
+  memset(m_pBuffer.get(), 0, CARCHIVE_BUFFER_MAX);
   if (mode == load)
   {
-    m_BufferPos = m_pBuffer + CARCHIVE_BUFFER_MAX;
+    m_BufferPos = m_pBuffer.get() + CARCHIVE_BUFFER_MAX;
     m_BufferRemain = 0;
   }
   else
   {
-    m_BufferPos = m_pBuffer;
+    m_BufferPos = m_pBuffer.get();
     m_BufferRemain = CARCHIVE_BUFFER_MAX;
   }
 }
@@ -54,7 +64,6 @@ CArchive::CArchive(CFile* pFile, int mode)
 CArchive::~CArchive()
 {
   FlushBuffer();
-  delete[] m_pBuffer;
 }
 
 void CArchive::Close()
@@ -134,16 +143,25 @@ CArchive& CArchive::operator<<(char c)
 
 CArchive& CArchive::operator<<(const std::string& str)
 {
-  *this << str.size();
+  auto size = static_cast<uint32_t>(str.size());
+  if (size > MAX_STRING_SIZE)
+    throw std::out_of_range("String too large, over 100MB");
 
-  return streamout(str.data(), str.size() * sizeof(char));
+  *this << size;
+
+  return streamout(str.data(), size * sizeof(char));
 }
 
 CArchive& CArchive::operator<<(const std::wstring& wstr)
 {
-  *this << wstr.size();
+  if (wstr.size() > MAX_STRING_SIZE)
+    throw std::out_of_range("String too large, over 100MB");
+
+  auto size = static_cast<uint32_t>(wstr.size());
+
+  *this << size;
 
-  return streamout(wstr.data(), wstr.size() * sizeof(wchar_t));
+  return streamout(wstr.data(), size * sizeof(wchar_t));
 }
 
 CArchive& CArchive::operator<<(const SYSTEMTIME& time)
@@ -160,7 +178,7 @@ CArchive& CArchive::operator<<(IArchivable& obj)
 
 CArchive& CArchive::operator<<(const CVariant& variant)
 {
-  *this << (int)variant.type();
+  *this << static_cast<int>(variant.type());
   switch (variant.type())
   {
   case CVariant::VariantTypeInteger:
@@ -183,12 +201,12 @@ CArchive& CArchive::operator<<(const CVariant& variant)
     break;
   case CVariant::VariantTypeArray:
     *this << variant.size();
-    for (unsigned int index = 0; index < variant.size(); index++)
-      *this << variant[index];
+    for (auto i = variant.begin_array(); i != variant.end_array(); ++i)
+      *this << *i;
     break;
   case CVariant::VariantTypeObject:
     *this << variant.size();
-    for (CVariant::const_iterator_map itr = variant.begin_map(); itr != variant.end_map(); ++itr)
+    for (auto itr = variant.begin_map(); itr != variant.end_map(); ++itr)
     {
       *this << itr->first;
       *this << itr->second;
@@ -205,44 +223,56 @@ CArchive& CArchive::operator<<(const CVariant& variant)
 
 CArchive& CArchive::operator<<(const std::vector<std::string>& strArray)
 {
-  *this << strArray.size();
-  for (size_t index = 0; index < strArray.size(); index++)
-    *this << strArray.at(index);
+  if (std::numeric_limits<uint32_t>::max() < strArray.size())
+    throw std::out_of_range("Array too large, over 2^32 in size");
+
+  *this << static_cast<uint32_t>(strArray.size());
+
+  for (auto&& item : strArray)
+    *this << item;
 
   return *this;
 }
 
 CArchive& CArchive::operator<<(const std::vector<int>& iArray)
 {
-  *this << iArray.size();
-  for (size_t index = 0; index < iArray.size(); index++)
-    *this << iArray.at(index);
+  if (std::numeric_limits<uint32_t>::max() < iArray.size())
+    throw std::out_of_range("Array too large, over 2^32 in size");
+
+  *this << static_cast<uint32_t>(iArray.size());
+
+  for (auto&& item : iArray)
+    *this << item;
 
   return *this;
 }
 
 CArchive& CArchive::operator>>(std::string& str)
 {
-  size_t iLength = 0;
+  uint32_t iLength = 0;
   *this >> iLength;
 
-  char *s = new char[iLength];
-  streamin(s, iLength * sizeof(char));
-  str.assign(s, iLength);
-  delete[] s;
+  if (iLength > MAX_STRING_SIZE)
+    throw std::out_of_range("String too large, over 100MB");
+
+  auto s = std::unique_ptr<char[]>(new char[iLength]);
+  streamin(s.get(), iLength * sizeof(char));
+  str.assign(s.get(), iLength);
 
   return *this;
 }
 
 CArchive& CArchive::operator>>(std::wstring& wstr)
 {
-  size_t iLength = 0;
+  uint32_t iLength = 0;
   *this >> iLength;
 
-  wchar_t * const p = new wchar_t[iLength];
-  streamin(p, iLength * sizeof(wchar_t));
-  wstr.assign(p, iLength);
-  delete[] p;
+  if (iLength > MAX_STRING_SIZE)
+    throw std::out_of_range("String too large, over 100MB");
+
+  auto p = std::unique_ptr<wchar_t[]>(new wchar_t[iLength]);
+  streamin(p.get(), iLength * sizeof(wchar_t));
+  wstr.assign(p.get(), iLength);
 
   return *this;
 }
@@ -263,7 +293,7 @@ CArchive& CArchive::operator>>(CVariant& variant)
 {
   int type;
   *this >> type;
-  variant = CVariant((CVariant::VariantType)type);
+  variant = CVariant(static_cast<CVariant::VariantType>(type));
 
   switch (variant.type())
   {
@@ -346,14 +376,14 @@ CArchive& CArchive::operator>>(CVariant& variant)
 
 CArchive& CArchive::operator>>(std::vector<std::string>& strArray)
 {
-  size_t size;
+  uint32_t size;
   *this >> size;
   strArray.clear();
-  for (size_t index = 0; index < size; index++)
+  for (uint32_t index = 0; index < size; index++)
   {
     std::string str;
     *this >> str;
-    strArray.push_back(str);
+    strArray.push_back(std::move(str));
   }
 
   return *this;
@@ -361,10 +391,10 @@ CArchive& CArchive::operator>>(std::vector<std::string>& strArray)
 
 CArchive& CArchive::operator>>(std::vector<int>& iArray)
 {
-  size_t size;
+  uint32_t size;
   *this >> size;
   iArray.clear();
-  for (size_t index = 0; index < size; index++)
+  for (uint32_t index = 0; index < size; index++)
   {
     int i;
     *this >> i;
@@ -376,13 +406,13 @@ CArchive& CArchive::operator>>(std::vector<int>& iArray)
 
 void CArchive::FlushBuffer()
 {
-  if (m_iMode == store && m_BufferPos != m_pBuffer)
+  if (m_iMode == store && m_BufferPos != m_pBuffer.get())
   {
-    if (m_pFile->Write(m_pBuffer, m_BufferPos - m_pBuffer) != m_BufferPos - m_pBuffer)
+    if (m_pFile->Write(m_pBuffer.get(), m_BufferPos - m_pBuffer.get()) != m_BufferPos - m_pBuffer.get())
       CLog::Log(LOGERROR, "%s: Error flushing buffer", __FUNCTION__);
     else
     {
-      m_BufferPos = m_pBuffer;
+      m_BufferPos = m_pBuffer.get();
       m_BufferRemain = CARCHIVE_BUFFER_MAX;
     }
   }
@@ -392,7 +422,7 @@ CArchive &CArchive::streamout_bufferwrap(const uint8_t *ptr, size_t size)
 {
   do
   {
-    size_t chunkSize = std::min(size, m_BufferRemain);
+    auto chunkSize = std::min(size, m_BufferRemain);
     m_BufferPos = std::copy(ptr, ptr + chunkSize, m_BufferPos);
     ptr += chunkSize;
     size -= chunkSize;
@@ -407,19 +437,19 @@ void CArchive::FillBuffer()
 {
   if (m_iMode == load && m_BufferRemain == 0)
   {
-    ssize_t read = m_pFile->Read(m_pBuffer, CARCHIVE_BUFFER_MAX);
+    auto read = m_pFile->Read(m_pBuffer.get(), CARCHIVE_BUFFER_MAX);
     if (read > 0)
     {
       m_BufferRemain = read;
-      m_BufferPos = m_pBuffer;
+      m_BufferPos = m_pBuffer.get();
     }
   }
 }
 
 CArchive &CArchive::streamin_bufferwrap(uint8_t *ptr, size_t size)
 {
-  uint8_t *orig_ptr = ptr;
-  size_t orig_size = size;
+  auto orig_ptr = ptr;
+  auto orig_size = size;
   do
   {
     if (m_BufferRemain == 0)
@@ -427,12 +457,14 @@ CArchive &CArchive::streamin_bufferwrap(uint8_t *ptr, size_t size)
       FillBuffer();
       if (m_BufferRemain < CARCHIVE_BUFFER_MAX && m_BufferRemain < size)
       {
-        CLog::Log(LOGERROR, "%s: can't stream in: requested %lu bytes, was read %lu bytes", __FUNCTION__, (unsigned long) orig_size, (unsigned long) (ptr - orig_ptr + m_BufferRemain));
+        CLog::Log(LOGERROR, "%s: can't stream in: requested %lu bytes, was read %lu bytes", __FUNCTION__,
+            static_cast<unsigned long>(orig_size), static_cast<unsigned long>(ptr - orig_ptr + m_BufferRemain));
+
         memset(orig_ptr, 0, orig_size);
         return *this;
       }
     }
-    size_t chunkSize = std::min(size, m_BufferRemain);
+    auto chunkSize = std::min(size, m_BufferRemain);
     ptr = std::copy(m_BufferPos, m_BufferPos + chunkSize, ptr);
     m_BufferPos += chunkSize;
     m_BufferRemain -= chunkSize;
diff --git a/xbmc/utils/Archive.h b/xbmc/utils/Archive.h
index 6ed0f8f..23cac27 100644
--- a/xbmc/utils/Archive.h
+++ b/xbmc/utils/Archive.h
@@ -21,6 +21,7 @@
  */
 
 #include <string>
+#include <memory>
 #include <vector>
 #include "PlatformDefs.h" // for SYSTEMTIME
 
@@ -41,9 +42,9 @@ public:
 
   /* CArchive support storing and loading of all C basic integer types
    * C basic types was chosen instead of fixed size ints (int16_t - int64_t) to support all integer typedefs
-   * For example size_t can be typedef of unsigned int, long or long long depending on platform 
-   * while int32_t and int64_t are usually unsigned short, int or long long, but not long 
-   * and even if int and long can have same binary representation they are different types for compiler 
+   * For example size_t can be typedef of unsigned int, long or long long depending on platform
+   * while int32_t and int64_t are usually unsigned short, int or long long, but not long
+   * and even if int and long can have same binary representation they are different types for compiler
    * According to section 5.2.4.2.1 of C99 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
    * minimal size of short int is 16 bits
    * minimal size of int is 16 bits (usually 32 or 64 bits, larger or equal to short int)
@@ -149,7 +150,7 @@ public:
 protected:
   inline CArchive &streamout(const void *dataPtr, size_t size)
   {
-    const uint8_t *ptr = (const uint8_t *) dataPtr;
+    auto ptr = static_cast<const uint8_t *>(dataPtr);
     /* Note, the buffer is flushed as soon as it is full (m_BufferRemain == size) rather
      * than waiting until we attempt to put more data into an already full buffer */
     if (m_BufferRemain > size)
@@ -159,15 +160,13 @@ protected:
       m_BufferRemain -= size;
       return *this;
     }
-    else
-    {
-      return streamout_bufferwrap(ptr, size);
-    }
+
+    return streamout_bufferwrap(ptr, size);
   }
 
   inline CArchive &streamin(void *dataPtr, size_t size)
   {
-    uint8_t *ptr = (uint8_t *) dataPtr;
+    auto ptr = static_cast<uint8_t *>(dataPtr);
     /* Note, refilling the buffer is deferred until we know we need to read more from it */
     if (m_BufferRemain >= size)
     {
@@ -176,15 +175,13 @@ protected:
       m_BufferRemain -= size;
       return *this;
     }
-    else
-    {
-      return streamin_bufferwrap(ptr, size);
-    }
+
+    return streamin_bufferwrap(ptr, size);
   }
 
-  XFILE::CFile* m_pFile;
+  XFILE::CFile* m_pFile; //non-owning
   int m_iMode;
-  uint8_t *m_pBuffer;
+  std::unique_ptr<uint8_t[]> m_pBuffer;
   uint8_t *m_BufferPos;
   size_t m_BufferRemain;
 
diff --git a/xbmc/utils/CMakeLists.txt b/xbmc/utils/CMakeLists.txt
index 9cb38cf..ea809a6 100644
--- a/xbmc/utils/CMakeLists.txt
+++ b/xbmc/utils/CMakeLists.txt
@@ -8,7 +8,7 @@ set(SOURCES ActorProtocol.cpp
             BitstreamConverter.cpp
             BitstreamStats.cpp
             BooleanLogic.cpp
-            CharsetConverter.cpp 
+            CharsetConverter.cpp
             CharsetDetection.cpp
             CPUInfo.cpp
             Crc32.cpp
@@ -92,6 +92,8 @@ set(HEADERS ActorProtocol.h
             DatabaseUtils.h
             EndianSwap.h
             Environment.h
+            EventStream.h
+            EventStreamDetail.h
             Fanart.h
             FileOperationJob.h
             FileUtils.h
@@ -173,8 +175,6 @@ if(NOT CORE_SYSTEM_NAME STREQUAL windows)
                       GLUtils.cpp)
   list(APPEND HEADERS CryptThreading.h
                       GLUtils.h)
-else()
-  set_source_files_properties(fstrcmp.c PROPERTIES LANGUAGE CXX)
 endif()
 
 if(AML_FOUND)
@@ -185,12 +185,3 @@ if(AML_FOUND)
 endif()
 
 core_add_library(utils)
-add_dependencies(utils libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(utils ffmpeg)
-endif()
-
-if(ENABLE_INTERNAL_CROSSGUID)
-  add_dependencies(utils crossguid)
-endif()
diff --git a/xbmc/utils/Crc32.cpp b/xbmc/utils/Crc32.cpp
index 2607b40..b70d385 100644
--- a/xbmc/utils/Crc32.cpp
+++ b/xbmc/utils/Crc32.cpp
@@ -105,15 +105,17 @@ void Crc32::Compute(const char* buffer, size_t count)
       m_crc = (m_crc << 8) ^ crc_tab[((m_crc >> 24) ^ *buffer++) & 0xFF];
 }
 
-void Crc32::Compute(const std::string& strValue)
+uint32_t Crc32::Compute(const std::string& strValue)
 {
-  Compute(strValue.c_str(), strValue.size());
+  Crc32 crc;
+  crc.Compute(strValue.c_str(), strValue.size());
+  return crc;
 }
 
-void Crc32::ComputeFromLowerCase(const std::string& strValue)
+uint32_t Crc32::ComputeFromLowerCase(const std::string& strValue)
 {
   std::string strLower = strValue;
   StringUtils::ToLower(strLower);
-  Compute(strLower.c_str(), strLower.size());
+  return Compute(strLower.c_str());
 }
 
diff --git a/xbmc/utils/Crc32.h b/xbmc/utils/Crc32.h
index 3d30c8f..079d7dc 100644
--- a/xbmc/utils/Crc32.h
+++ b/xbmc/utils/Crc32.h
@@ -29,8 +29,8 @@ public:
   Crc32();
   void Reset();
   void Compute(const char* buffer, size_t count);
-  void Compute(const std::string& strValue);
-  void ComputeFromLowerCase(const std::string& strValue);
+  static uint32_t Compute(const std::string& strValue);
+  static uint32_t ComputeFromLowerCase(const std::string& strValue);
 
   operator uint32_t () const
   {
diff --git a/xbmc/utils/DatabaseUtils.cpp b/xbmc/utils/DatabaseUtils.cpp
index cecc83a..a766ba6 100644
--- a/xbmc/utils/DatabaseUtils.cpp
+++ b/xbmc/utils/DatabaseUtils.cpp
@@ -226,7 +226,7 @@ std::string DatabaseUtils::GetField(Field field, const MediaType &mediaType, Dat
     else if (field == FieldDirector) result = StringUtils::Format("episode_view.c%02d", VIDEODB_ID_EPISODE_DIRECTOR);
     else if (field == FieldSeason) result = StringUtils::Format("episode_view.c%02d", VIDEODB_ID_EPISODE_SEASON);
     else if (field == FieldEpisodeNumber) result = StringUtils::Format("episode_view.c%02d", VIDEODB_ID_EPISODE_EPISODE);
-    else if (field == FieldUniqueId) result = StringUtils::Format("episode_view.c%02d", VIDEODB_ID_EPISODE_UNIQUEID);
+    else if (field == FieldUniqueId) result = StringUtils::Format("episode_view.c%02d", VIDEODB_ID_EPISODE_IDENT_ID);
     else if (field == FieldEpisodeNumberSpecialSort) result = StringUtils::Format("episode_view.c%02d", VIDEODB_ID_EPISODE_SORTEPISODE);
     else if (field == FieldSeasonSpecialSort) result = StringUtils::Format("episode_view.c%02d", VIDEODB_ID_EPISODE_SORTSEASON);
     else if (field == FieldFilename) return "episode_view.strFilename";
@@ -645,7 +645,7 @@ int DatabaseUtils::GetField(Field field, const MediaType &mediaType, bool asInde
     else if (field == FieldDirector) index = VIDEODB_ID_EPISODE_DIRECTOR;
     else if (field == FieldSeason) index = VIDEODB_ID_EPISODE_SEASON;
     else if (field == FieldEpisodeNumber) index = VIDEODB_ID_EPISODE_EPISODE;
-    else if (field == FieldUniqueId) index = VIDEODB_ID_EPISODE_UNIQUEID;
+    else if (field == FieldUniqueId) index = VIDEODB_ID_EPISODE_IDENT_ID;
     else if (field == FieldEpisodeNumberSpecialSort) index = VIDEODB_ID_EPISODE_SORTEPISODE;
     else if (field == FieldSeasonSpecialSort) index = VIDEODB_ID_EPISODE_SORTSEASON;
     else if (field == FieldFilename) return VIDEODB_DETAILS_EPISODE_FILE;
diff --git a/xbmc/utils/EventStream.h b/xbmc/utils/EventStream.h
new file mode 100644
index 0000000..279a004
--- /dev/null
+++ b/xbmc/utils/EventStream.h
@@ -0,0 +1,90 @@
+/*
+ *      Copyright (C) 2016 Team Kodi
+ *      http://kodi.tv
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+#pragma once
+
+#include "EventStreamDetail.h"
+#include "JobManager.h"
+#include "threads/CriticalSection.h"
+#include "threads/SingleLock.h"
+#include <algorithm>
+#include <memory>
+#include <vector>
+
+
+template<typename Event>
+class CEventStream
+{
+public:
+
+  template<typename A>
+  void Subscribe(A* owner, void (A::*fn)(const Event&))
+  {
+    auto subscription = std::make_shared<detail::CSubscription<Event, A>>(owner, fn);
+    CSingleLock lock(m_criticalSection);
+    m_subscriptions.emplace_back(std::move(subscription));
+  }
+
+  template<typename A>
+  void Unsubscribe(A* obj)
+  {
+    std::vector<std::shared_ptr<detail::ISubscription<Event>>> toCancel;
+    {
+      CSingleLock lock(m_criticalSection);
+      auto it = m_subscriptions.begin();
+      while (it != m_subscriptions.end())
+      {
+        if ((*it)->IsOwnedBy(obj))
+        {
+          toCancel.push_back(*it);
+          it = m_subscriptions.erase(it);
+        }
+        else
+        {
+          ++it;
+        }
+      }
+    }
+    for (auto& subscription : toCancel)
+      subscription->Cancel();
+  }
+
+protected:
+  std::vector<std::shared_ptr<detail::ISubscription<Event>>> m_subscriptions;
+  CCriticalSection m_criticalSection;
+};
+
+
+template<typename Event>
+class CEventSource : public CEventStream<Event>
+{
+public:
+  template<typename A>
+  void Publish(A event)
+  {
+    CSingleLock lock(this->m_criticalSection);
+    auto& subscriptions = this->m_subscriptions;
+    auto task = [subscriptions, event](){
+      for (auto& s: subscriptions)
+        s->HandleEvent(event);
+    };
+    lock.Leave();
+    CJobManager::GetInstance().Submit(std::move(task));
+  }
+};
diff --git a/xbmc/utils/EventStreamDetail.h b/xbmc/utils/EventStreamDetail.h
new file mode 100644
index 0000000..68d97c2
--- /dev/null
+++ b/xbmc/utils/EventStreamDetail.h
@@ -0,0 +1,80 @@
+/*
+ *      Copyright (C) 2016 Team Kodi
+ *      http://kodi.tv
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+#pragma once
+
+#include "threads/CriticalSection.h"
+#include "threads/SingleLock.h"
+
+namespace detail
+{
+
+template<typename Event>
+class ISubscription
+{
+public:
+  virtual void HandleEvent(const Event& event) = 0;
+  virtual void Cancel() = 0;
+  virtual bool IsOwnedBy(void* obj) = 0;
+  virtual ~ISubscription() {}
+};
+
+template<typename Event, typename Owner>
+class CSubscription : public ISubscription<Event>
+{
+public:
+  typedef void (Owner::*Fn)(const Event&);
+  CSubscription(Owner* owner, Fn fn);
+  void HandleEvent(const Event& event) override;
+  void Cancel() override;
+  bool IsOwnedBy(void *obj) override;
+
+private:
+  Owner* m_owner;
+  Fn m_eventHandler;
+  CCriticalSection m_criticalSection;
+};
+
+template<typename Event, typename Owner>
+CSubscription<Event, Owner>::CSubscription(Owner* owner, Fn fn)
+    : m_owner(owner), m_eventHandler(fn)
+{}
+
+template<typename Event, typename Owner>
+bool CSubscription<Event, Owner>::IsOwnedBy(void* obj)
+{
+  CSingleLock lock(m_criticalSection);
+  return obj != nullptr && obj == m_owner;
+}
+
+template<typename Event, typename Owner>
+void CSubscription<Event, Owner>::Cancel()
+{
+  CSingleLock lock(m_criticalSection);
+  m_owner = nullptr;
+}
+
+template<typename Event, typename Owner>
+void CSubscription<Event, Owner>::HandleEvent(const Event& event)
+{
+  CSingleLock lock(m_criticalSection);
+  if (m_owner)
+    (m_owner->*m_eventHandler)(event);
+}
+}
diff --git a/xbmc/utils/PerformanceSample.h b/xbmc/utils/PerformanceSample.h
index 81730c5..797706f 100644
--- a/xbmc/utils/PerformanceSample.h
+++ b/xbmc/utils/PerformanceSample.h
@@ -26,7 +26,7 @@
 #include <sys/times.h>
 #include <sys/resource.h>
 #elif TARGET_WINDOWS
-#include "win32/PlatformDefs.h"
+#include "platform/win32/PlatformDefs.h"
 #endif
 
 #include <string>
diff --git a/xbmc/utils/UrlOptions.cpp b/xbmc/utils/UrlOptions.cpp
index c7394f0..773e300 100644
--- a/xbmc/utils/UrlOptions.cpp
+++ b/xbmc/utils/UrlOptions.cpp
@@ -18,15 +18,12 @@
  *
  */
 
-#include <sstream>
-
 #include "UrlOptions.h"
 #include "URL.h"
 #include "utils/StringUtils.h"
 #include "utils/log.h"
 
 CUrlOptions::CUrlOptions()
-  : m_strLead("")
 { }
 
 CUrlOptions::CUrlOptions(const std::string &options, const char *strLead /* = "" */)
@@ -41,14 +38,14 @@ CUrlOptions::~CUrlOptions()
 std::string CUrlOptions::GetOptionsString(bool withLeadingSeperator /* = false */) const
 {
   std::string options;
-  for (UrlOptions::const_iterator opt = m_options.begin(); opt != m_options.end(); ++opt)
+  for (const auto &opt : m_options)
   {
-    if (opt != m_options.begin())
+    if (!options.empty())
       options += "&";
 
-    options += CURL::Encode(opt->first);
-    if (!opt->second.empty())
-      options += "=" + CURL::Encode(opt->second.asString());
+    options += CURL::Encode(opt.first);
+    if (!opt.second.empty())
+      options += "=" + CURL::Encode(opt.second.asString());
   }
 
   if (withLeadingSeperator && !options.empty())
@@ -130,18 +127,17 @@ void CUrlOptions::AddOptions(const std::string &options)
   }
 
   // split the options by & and process them one by one
-  std::vector<std::string> optionList = StringUtils::Split(strOptions, "&");
-  for (std::vector<std::string>::const_iterator option = optionList.begin(); option != optionList.end(); ++option)
+  for (const auto &option : StringUtils::Split(strOptions, "&"))
   {
-    if (option->empty())
+    if (option.empty())
       continue;
 
     std::string key, value;
 
-    size_t pos = option->find('=');
-    key = CURL::Decode(option->substr(0, pos));
+    size_t pos = option.find('=');
+    key = CURL::Decode(option.substr(0, pos));
     if (pos != std::string::npos)
-      value = CURL::Decode(option->substr(pos + 1));
+      value = CURL::Decode(option.substr(pos + 1));
 
     // the key cannot be empty
     if (!key.empty())
@@ -159,7 +155,7 @@ void CUrlOptions::RemoveOption(const std::string &key)
   if (key.empty())
     return;
 
-  UrlOptions::iterator option = m_options.find(key);
+  auto option = m_options.find(key);
   if (option != m_options.end())
     m_options.erase(option);
 }
@@ -177,7 +173,7 @@ bool CUrlOptions::GetOption(const std::string &key, CVariant &value) const
   if (key.empty())
     return false;
 
-  UrlOptions::const_iterator option = m_options.find(key);
+  auto option = m_options.find(key);
   if (option == m_options.end())
     return false;
 
diff --git a/xbmc/utils/UrlOptions.h b/xbmc/utils/UrlOptions.h
index a86cd1d..037d502 100644
--- a/xbmc/utils/UrlOptions.h
+++ b/xbmc/utils/UrlOptions.h
@@ -19,11 +19,11 @@
  *
  */
 
+#include "utils/Variant.h"
+
 #include <map>
 #include <string>
 
-#include "utils/Variant.h"
-
 class CUrlOptions
 {
 public:
@@ -33,10 +33,10 @@ public:
   CUrlOptions(const std::string &options, const char *strLead = "");
   virtual ~CUrlOptions();
 
-  virtual void Clear() { m_options.clear(); m_strLead = ""; }
+  void Clear() { m_options.clear(); m_strLead.clear(); }
 
-  virtual const UrlOptions& GetOptions() const { return m_options; }
-  virtual std::string GetOptionsString(bool withLeadingSeperator = false) const;
+  const UrlOptions& GetOptions() const { return m_options; }
+  std::string GetOptionsString(bool withLeadingSeperator = false) const;
 
   virtual void AddOption(const std::string &key, const char *value);
   virtual void AddOption(const std::string &key, const std::string &value);
@@ -48,8 +48,8 @@ public:
   virtual void AddOptions(const CUrlOptions &options);
   virtual void RemoveOption(const std::string &key);
 
-  virtual bool HasOption(const std::string &key) const;
-  virtual bool GetOption(const std::string &key, CVariant &value) const;
+  bool HasOption(const std::string &key) const;
+  bool GetOption(const std::string &key, CVariant &value) const;
 
 protected:
   UrlOptions m_options;
diff --git a/xbmc/utils/Variant.cpp b/xbmc/utils/Variant.cpp
index 1c5c500..270d99e 100644
--- a/xbmc/utils/Variant.cpp
+++ b/xbmc/utils/Variant.cpp
@@ -18,13 +18,13 @@
  *
  */
 
+#include "Variant.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include <sstream>
 #include <utility>
 
-#include "Variant.h"
-
 #ifndef strtoll
 #ifdef TARGET_WINDOWS
 #define strtoll  _strtoi64
diff --git a/xbmc/utils/test/CMakeLists.txt b/xbmc/utils/test/CMakeLists.txt
index dc984ab..c298ba8 100644
--- a/xbmc/utils/test/CMakeLists.txt
+++ b/xbmc/utils/test/CMakeLists.txt
@@ -7,7 +7,6 @@ set(SOURCES TestAlarmClock.cpp
             TestCharsetConverter.cpp
             TestCPUInfo.cpp
             TestCrc32.cpp
-            TestCryptThreading.cpp
             TestDatabaseUtils.cpp
             TestEndianSwap.cpp
             TestFileOperationJob.cpp
@@ -50,4 +49,8 @@ set(SOURCES TestAlarmClock.cpp
 
 set(HEADERS TestGlobalsHandlingPattern1.h)
 
+if(NOT CORE_SYSTEM_NAME STREQUAL windows)
+  list(APPEND SOURCES TestCryptThreading.cpp)
+endif()
+
 core_add_test_library(utils_test)
diff --git a/xbmc/utils/test/TestCharsetConverter.cpp b/xbmc/utils/test/TestCharsetConverter.cpp
index b9fafd0..926f1a8 100644
--- a/xbmc/utils/test/TestCharsetConverter.cpp
+++ b/xbmc/utils/test/TestCharsetConverter.cpp
@@ -259,7 +259,7 @@ TEST_F(TestCharsetConverter, isValidUtf8_4)
 TEST_F(TestCharsetConverter, wToUTF8)
 {
   refstrw1 = L"test_wToUTF8";
-  refstra1 = "test_wToUTF8";
+  refstra1 = u8"test_wToUTF8";
   varstra1.clear();
   g_charsetConverter.wToUTF8(refstrw1, varstra1);
   EXPECT_STREQ(refstra1.c_str(), varstra1.c_str());
diff --git a/xbmc/utils/test/TestCrc32.cpp b/xbmc/utils/test/TestCrc32.cpp
index 4396a94..503e78e 100644
--- a/xbmc/utils/test/TestCrc32.cpp
+++ b/xbmc/utils/test/TestCrc32.cpp
@@ -37,21 +37,16 @@ TEST(TestCrc32, Compute_1)
 
 TEST(TestCrc32, Compute_2)
 {
-  Crc32 a;
   uint32_t varcrc;
   std::string s = refdata;
-  a.Compute(s);
-  varcrc = a;
+  varcrc = Crc32::Compute(s);
   EXPECT_EQ(0xa4eb60e3, varcrc);
 }
 
 TEST(TestCrc32, ComputeFromLowerCase)
 {
-  Crc32 a;
-  uint32_t varcrc;
   std::string s = refdata;
-  a.ComputeFromLowerCase(s);
-  varcrc = a;
+  uint32_t varcrc = Crc32::ComputeFromLowerCase(s);
   EXPECT_EQ((uint32_t)0x7f045b3e, varcrc);
 }
 
@@ -60,7 +55,7 @@ TEST(TestCrc32, Reset)
   Crc32 a;
   uint32_t varcrc;
   std::string s = refdata;
-  a.ComputeFromLowerCase(s);
+  a.Compute(s.c_str(), s.length());
   a.Reset();
   varcrc = a;
   EXPECT_EQ(0xffffffff, varcrc);
diff --git a/xbmc/utils/win32/Win32InterfaceForCLog.cpp b/xbmc/utils/win32/Win32InterfaceForCLog.cpp
index 9599669..117bcdb 100644
--- a/xbmc/utils/win32/Win32InterfaceForCLog.cpp
+++ b/xbmc/utils/win32/Win32InterfaceForCLog.cpp
@@ -23,7 +23,7 @@
 #endif //!TARGET_WINDOWS
 
 #include "Win32InterfaceForCLog.h"
-#include "win32/WIN32Util.h"
+#include "platform/win32/WIN32Util.h"
 #include "utils/StringUtils.h"
 #include "utils/auto_buffer.h"
 
diff --git a/xbmc/video/CMakeLists.txt b/xbmc/video/CMakeLists.txt
index 11f4046..9c81c0c 100644
--- a/xbmc/video/CMakeLists.txt
+++ b/xbmc/video/CMakeLists.txt
@@ -29,12 +29,6 @@ set(HEADERS Bookmark.h
             VideoThumbLoader.h)
 
 core_add_library(video)
-add_dependencies(video libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(video ffmpeg)
-endif()
-
 if(CORE_SYSTEM_NAME STREQUAL windows)
-  add_dependencies(video d3dx11effects)
+  add_dependencies(${CORE_LIBRARY} d3dx11effects)
 endif()
diff --git a/xbmc/video/VideoDatabase.cpp b/xbmc/video/VideoDatabase.cpp
index b02a203..6047073 100644
--- a/xbmc/video/VideoDatabase.cpp
+++ b/xbmc/video/VideoDatabase.cpp
@@ -203,6 +203,9 @@ void CVideoDatabase::CreateTables()
 
   CLog::Log(LOGINFO, "create rating table");
   m_pDS->exec("CREATE TABLE rating (rating_id INTEGER PRIMARY KEY, media_id INTEGER, media_type TEXT, rating_type TEXT, rating FLOAT, votes INTEGER)");
+
+  CLog::Log(LOGINFO, "create uniqueid table");
+  m_pDS->exec("CREATE TABLE uniqueid (uniqueid_id INTEGER PRIMARY KEY, media_id INTEGER, media_type TEXT, value TEXT, type TEXT)");
 }
 
 void CVideoDatabase::CreateLinkIndex(const char *table)
@@ -271,6 +274,9 @@ void CVideoDatabase::CreateAnalytics()
 
   m_pDS->exec("CREATE INDEX ix_rating ON rating(media_id, media_type(20))");
 
+  m_pDS->exec("CREATE INDEX ix_uniqueid1 ON uniqueid(media_id, media_type(20), type(20))");
+  m_pDS->exec("CREATE INDEX ix_uniqueid2 ON uniqueid(media_type(20), value(20))");
+
   CreateLinkIndex("tag");
   CreateLinkIndex("actor");
   CreateForeignLinkIndex("director", "actor");
@@ -291,6 +297,7 @@ void CVideoDatabase::CreateAnalytics()
               "DELETE FROM art WHERE media_id=old.idMovie AND media_type='movie'; "
               "DELETE FROM tag_link WHERE media_id=old.idMovie AND media_type='movie'; "
               "DELETE FROM rating WHERE media_id=old.idMovie AND media_type='movie'; "
+              "DELETE FROM uniqueid WHERE media_id=old.idMovie AND media_type='movie'; "
               "END");
   m_pDS->exec("CREATE TRIGGER delete_tvshow AFTER DELETE ON tvshow FOR EACH ROW BEGIN "
               "DELETE FROM actor_link WHERE media_id=old.idShow AND media_type='tvshow'; "
@@ -303,6 +310,7 @@ void CVideoDatabase::CreateAnalytics()
               "DELETE FROM art WHERE media_id=old.idShow AND media_type='tvshow'; "
               "DELETE FROM tag_link WHERE media_id=old.idShow AND media_type='tvshow'; "
               "DELETE FROM rating WHERE media_id=old.idShow AND media_type='tvshow'; "
+              "DELETE FROM uniqueid WHERE media_id=old.idShow AND media_type='tvshow'; "
               "END");
   m_pDS->exec("CREATE TRIGGER delete_musicvideo AFTER DELETE ON musicvideo FOR EACH ROW BEGIN "
               "DELETE FROM actor_link WHERE media_id=old.idMVideo AND media_type='musicvideo'; "
@@ -318,6 +326,7 @@ void CVideoDatabase::CreateAnalytics()
               "DELETE FROM writer_link WHERE media_id=old.idEpisode AND media_type='episode'; "
               "DELETE FROM art WHERE media_id=old.idEpisode AND media_type='episode'; "
               "DELETE FROM rating WHERE media_id=old.idEpisode AND media_type='episode'; "
+              "DELETE FROM uniqueid WHERE media_id=old.idEpisode AND media_type='episode'; "
               "END");
   m_pDS->exec("CREATE TRIGGER delete_season AFTER DELETE ON seasons FOR EACH ROW BEGIN "
               "DELETE FROM art WHERE media_id=old.idSeason AND media_type='season'; "
@@ -360,7 +369,9 @@ void CVideoDatabase::CreateViews()
                                       "  bookmark.totalTimeInSeconds AS totalTimeInSeconds, "
                                       "  rating.rating AS rating, "
                                       "  rating.votes AS votes, "
-                                      "  rating.rating_type AS rating_type "
+                                      "  rating.rating_type AS rating_type, "
+                                      "  uniqueid.value AS uniqueid_value, "
+                                      "  uniqueid.type AS uniqueid_type "
                                       "FROM episode"
                                       "  JOIN files ON"
                                       "    files.idFile=episode.idFile"
@@ -373,10 +384,13 @@ void CVideoDatabase::CreateViews()
                                       "  LEFT JOIN bookmark ON"
                                       "    bookmark.idFile=episode.idFile AND bookmark.type=1"
                                       "  LEFT JOIN rating ON"
-                                      "    rating.rating_id=episode.c%02d",
+                                      "    rating.rating_id=episode.c%02d"
+                                      "  LEFT JOIN uniqueid ON"
+                                      "    uniqueid.uniqueid_id=episode.c%02d",
                                       VIDEODB_ID_TV_TITLE, VIDEODB_ID_TV_GENRE,
                                       VIDEODB_ID_TV_STUDIOS, VIDEODB_ID_TV_PREMIERED,
-                                      VIDEODB_ID_TV_MPAA, VIDEODB_ID_EPISODE_RATING_ID);
+                                      VIDEODB_ID_TV_MPAA, VIDEODB_ID_EPISODE_RATING_ID,
+                                      VIDEODB_ID_EPISODE_IDENT_ID);
   m_pDS->exec(episodeview);
 
   CLog::Log(LOGINFO, "create tvshowcounts");
@@ -404,7 +418,9 @@ void CVideoDatabase::CreateViews()
                                      "  lastPlayed, totalCount, watchedcount, totalSeasons, "
                                      "  rating.rating AS rating, "
                                      "  rating.votes AS votes, "
-                                     "  rating.rating_type AS rating_type "
+                                     "  rating.rating_type AS rating_type, "
+                                     "  uniqueid.value AS uniqueid_value, "
+                                     "  uniqueid.type AS uniqueid_type "
                                      "FROM tvshow"
                                      "  LEFT JOIN tvshowlinkpath ON"
                                      "    tvshowlinkpath.idShow=tvshow.idShow"
@@ -414,8 +430,10 @@ void CVideoDatabase::CreateViews()
                                      "    tvshow.idShow = tvshowcounts.idShow "
                                      "  LEFT JOIN rating ON"
                                      "    rating.rating_id=tvshow.c%02d "
+                                     "  LEFT JOIN uniqueid ON"
+                                     "    uniqueid.uniqueid_id=tvshow.c%02d "
                                      "GROUP BY tvshow.idShow",
-                                     VIDEODB_ID_TV_RATING_ID);
+                                     VIDEODB_ID_TV_RATING_ID, VIDEODB_ID_TV_IDENT_ID);
   m_pDS->exec(tvshowview);
   CLog::Log(LOGINFO, "create season_view");
   std::string seasonview = PrepareSQL("CREATE VIEW season_view AS SELECT "
@@ -476,7 +494,9 @@ void CVideoDatabase::CreateViews()
                                       "  bookmark.totalTimeInSeconds AS totalTimeInSeconds, "
                                       "  rating.rating AS rating, "
                                       "  rating.votes AS votes, "
-                                      "  rating.rating_type AS rating_type "
+                                      "  rating.rating_type AS rating_type, "
+                                      "  uniqueid.value AS uniqueid_value, "
+                                      "  uniqueid.type AS uniqueid_type "
                                       "FROM movie"
                                       "  LEFT JOIN sets ON"
                                       "    sets.idSet = movie.idSet"
@@ -487,8 +507,10 @@ void CVideoDatabase::CreateViews()
                                       "  LEFT JOIN bookmark ON"
                                       "    bookmark.idFile=movie.idFile AND bookmark.type=1"
                                       "  LEFT JOIN rating ON"
-                                      "    rating.rating_id=movie.c%02d",
-                                      VIDEODB_ID_RATING_ID);
+                                      "    rating.rating_id=movie.c%02d"
+                                      "  LEFT JOIN uniqueid ON"
+                                      "    uniqueid.uniqueid_id=movie.c%02d",
+                                      VIDEODB_ID_RATING_ID, VIDEODB_ID_IDENT_ID);
   m_pDS->exec(movieview);
 }
 
@@ -1474,6 +1496,67 @@ int CVideoDatabase::AddRatings(int mediaId, const char *mediaType, const RatingM
   return ratingid;
 }
 
+int CVideoDatabase::UpdateUniqueIDs(int mediaId, const char *mediaType, const CVideoInfoTag& details)
+{
+  try
+  {
+    if (NULL == m_pDB.get()) return -1;
+    if (NULL == m_pDS.get()) return -1;
+
+    std::string sql = PrepareSQL("DELETE FROM uniqueid WHERE media_id=%i AND media_type='%s'", mediaId, mediaType);
+    m_pDS->exec(sql);
+
+    return AddUniqueIDs(mediaId, mediaType, details);
+  }
+  catch (...)
+  {
+    CLog::Log(LOGERROR, "%s unable to update unique ids of (%s)", __FUNCTION__, mediaType);
+  }
+  return -1;
+}
+
+int CVideoDatabase::AddUniqueIDs(int mediaId, const char *mediaType, const CVideoInfoTag& details)
+{
+  int uniqueid = -1;
+  try
+  {
+    if (NULL == m_pDB.get()) return -1;
+    if (NULL == m_pDS.get()) return -1;
+
+    for (const auto& i : details.GetUniqueIDs())
+    {
+      int id;
+      std::string strSQL = PrepareSQL("SELECT uniqueid_id FROM uniqueid WHERE media_id=%i AND media_type='%s' AND type = '%s'", mediaId, mediaType, i.first.c_str());
+      m_pDS->query(strSQL);
+      if (m_pDS->num_rows() == 0)
+      {
+        m_pDS->close();
+        // doesnt exists, add it
+        strSQL = PrepareSQL("INSERT INTO uniqueid (media_id, media_type, value, type) VALUES (%i, '%s', '%s', '%s')", mediaId, mediaType, i.second.c_str(), i.first.c_str());
+        m_pDS->exec(strSQL);
+        id = (int)m_pDS->lastinsertid();
+      }
+      else
+      {
+        id = m_pDS->fv(0).get_asInt();
+        m_pDS->close();
+        strSQL = PrepareSQL("UPDATE uniqueid SET value = '%s', type = '%s' WHERE uniqueid_id = %i", i.second.c_str(), i.first.c_str(), id);
+        m_pDS->exec(strSQL);
+      }
+      if (i.first == details.GetDefaultUniqueID())
+        uniqueid = id;
+    }
+    return uniqueid;
+
+  }
+  catch (...)
+  {
+    CLog::Log(LOGERROR, "%s (%i - %s) failed", __FUNCTION__, mediaId, mediaType);
+  }
+
+  return uniqueid;
+}
+
 int CVideoDatabase::AddSet(const std::string& strSet, const std::string& strOverview /* = "" */)
 {
   if (strSet.empty())
@@ -1597,11 +1680,11 @@ void CVideoDatabase::RemoveFromLinkTable(int mediaId, const std::string& mediaTy
 
 void CVideoDatabase::AddLinksToItem(int mediaId, const std::string& mediaType, const std::string& field, const std::vector<std::string>& values)
 {
-  for (std::vector<std::string>::const_iterator i = values.begin(); i != values.end(); ++i)
+  for (const auto &i : values)
   {
-    if (!i->empty())
+    if (!i.empty())
     {
-      int idValue = AddToTable(field, field + "_id", "name", *i);
+      int idValue = AddToTable(field, field + "_id", "name", i);
       if (idValue > -1)
         AddToLinkTable(mediaId, mediaType, field, idValue);
     }
@@ -1618,11 +1701,11 @@ void CVideoDatabase::UpdateLinksToItem(int mediaId, const std::string& mediaType
 
 void CVideoDatabase::AddActorLinksToItem(int mediaId, const std::string& mediaType, const std::string& field, const std::vector<std::string>& values)
 {
-  for (std::vector<std::string>::const_iterator i = values.begin(); i != values.end(); ++i)
+  for (const auto &i : values)
   {
-    if (!i->empty())
+    if (!i.empty())
     {
-      int idValue = AddActor(*i, "");
+      int idValue = AddActor(i, "");
       if (idValue > -1)
         AddToLinkTable(mediaId, mediaType, field, idValue, "actor");
     }
@@ -1669,10 +1752,10 @@ void CVideoDatabase::AddCast(int mediaId, const char *mediaType, const std::vect
     return;
 
   int order = std::max_element(cast.begin(), cast.end())->order;
-  for (CVideoInfoTag::iCast it = cast.begin(); it != cast.end(); ++it)
+  for (const auto &i : cast)
   {
-    int idActor = AddActor(it->strName, it->thumbUrl.m_xml, it->thumb);
-    AddLinkToActor(mediaId, mediaType, idActor, it->strRole, it->order >= 0 ? it->order : ++order);
+    int idActor = AddActor(i.strName, i.thumbUrl.m_xml, i.thumb);
+    AddLinkToActor(mediaId, mediaType, idActor, i.strRole, i.order >= 0 ? i.order : ++order);
   }
 }
 
@@ -1785,6 +1868,9 @@ void CVideoDatabase::DeleteDetailsForTvShow(int idTvShow)
     strSQL = PrepareSQL("DELETE FROM rating WHERE media_id=%i AND media_type='tvshow'", idTvShow);
     m_pDS->exec(strSQL);
 
+    strSQL = PrepareSQL("DELETE FROM uniqueid WHERE media_id=%i AND media_type='tvshow'", idTvShow);
+    m_pDS->exec(strSQL);
+
     // remove all info other than the id
     // we do this due to the way we have the link between the file + movie tables.
 
@@ -2189,9 +2275,12 @@ int CVideoDatabase::SetDetailsForMovie(const std::string& strFilenameAndPath, CV
     AddActorLinksToItem(idMovie, MediaTypeMovie, "director", details.m_director);
     AddActorLinksToItem(idMovie, MediaTypeMovie, "writer", details.m_writingCredits);
 
-    // add ratings
+    // add ratingsu
     details.m_iIdRating = AddRatings(idMovie, MediaTypeMovie, details.m_ratings, details.GetDefaultRating());
 
+    // add unique ids
+    details.m_iIdUniqueID = AddUniqueIDs(idMovie, MediaTypeMovie, details);
+
     // add set...
     int idSet = -1;
     if (!details.m_strSet.empty())
@@ -2208,9 +2297,16 @@ int CVideoDatabase::SetDetailsForMovie(const std::string& strFilenameAndPath, CV
 
     SetArtForItem(idMovie, MediaTypeMovie, artwork);
 
-    if (!details.m_strIMDBNumber.empty() && details.HasYear())
-    { // query DB for any movies matching imdbid and year
-      std::string strSQL = PrepareSQL("SELECT files.playCount, files.lastPlayed FROM movie INNER JOIN files ON files.idFile=movie.idFile WHERE movie.c%02d='%s' AND movie.premiered LIKE '%i%%' AND movie.idMovie!=%i AND files.playCount > 0", VIDEODB_ID_IDENT, details.m_strIMDBNumber.c_str(), details.GetYear(), idMovie);
+    if (!details.HasUniqueID() && details.HasYear())
+    { // query DB for any movies matching online id and year
+      std::string strSQL = PrepareSQL("SELECT files.playCount, files.lastPlayed "
+                                      "FROM movie "
+                                      "  INNER JOIN files "
+                                      "    ON files.idFile=movie.idFile "
+                                      "  JOIN uniqueid "
+                                      "    ON movie.idMovie=uniqueid.media_id AND uniqueid.media_type='movie' AND uniqueid.value='%s'"
+                                      "WHERE movie.premiered LIKE '%i%%' AND movie.idMovie!=%i AND files.playCount > 0", 
+                                      details.GetUniqueID().c_str(), details.GetYear(), idMovie);
       m_pDS->query(strSQL);
 
       if (!m_pDS->eof())
@@ -2286,6 +2382,8 @@ int CVideoDatabase::UpdateDetailsForMovie(int idMovie, CVideoInfoTag& details, c
       SetArtForItem(idMovie, MediaTypeMovie, artwork);
     if (updatedDetails.find("ratings") != updatedDetails.end())
       details.m_iIdRating = UpdateRatings(idMovie, MediaTypeMovie, details.m_ratings, details.GetDefaultRating());
+    if (updatedDetails.find("uniqueid") != updatedDetails.end())
+      details.m_iIdUniqueID = UpdateUniqueIDs(idMovie, MediaTypeMovie, details);
     if (updatedDetails.find("dateadded") != updatedDetails.end() && details.m_dateAdded.IsValid())
     {
       if (details.m_iFileId <= 0)
@@ -2397,10 +2495,10 @@ int CVideoDatabase::SetDetailsForMovieSet(const CVideoInfoTag& details, const st
 
 int CVideoDatabase::GetMatchingTvShow(const CVideoInfoTag &details)
 {
-  // first try matching on VIDEODB_ID_TV_IDENT, then on title + year
+  // first try matching on uniqueid, then on title + year
   int id = -1;
-  if (!details.m_strIMDBNumber.empty())
-    id = GetDbId(PrepareSQL("SELECT idShow from tvshow WHERE c%02d='%s'", VIDEODB_ID_TV_IDENT, details.m_strIMDBNumber.c_str()));
+  if (!details.HasUniqueID())
+    id = GetDbId(PrepareSQL("SELECT idShow from tvshow JOIN uniqueid ON uniqueid.value='%s' AND uniqueid.media_type='tvshow'", details.GetUniqueID().c_str()));
   if (id < 0)
     id = GetDbId(PrepareSQL("SELECT idShow FROM tvshow WHERE c%02d='%s' AND c%02d='%s'", VIDEODB_ID_TV_TITLE, details.m_strTitle.c_str(), VIDEODB_ID_TV_PREMIERED, details.GetPremiered().GetAsDBDate().c_str()));
   return id;
@@ -2422,9 +2520,9 @@ int CVideoDatabase::SetDetailsForTvShow(const std::vector<std::pair<std::string,
 
   if (idTvShow < 0)
   {
-    for (std::vector<std::pair<std::string, std::string>>::const_iterator i = paths.begin(); i != paths.end(); ++i)
+    for (const auto &i : paths)
     {
-      idTvShow = GetTvShowId(i->first);
+      idTvShow = GetTvShowId(i.first);
       if (idTvShow > -1)
         break;
     }
@@ -2439,8 +2537,8 @@ int CVideoDatabase::SetDetailsForTvShow(const std::vector<std::pair<std::string,
   }
 
   // add any paths to the tvshow
-  for (std::vector<std::pair<std::string, std::string>>::const_iterator i = paths.begin(); i != paths.end(); ++i)
-    AddPathToTvShow(idTvShow, i->first, i->second, details.m_dateAdded);
+  for (const auto &i : paths)
+    AddPathToTvShow(idTvShow, i.first, i.second, details.m_dateAdded);
 
   UpdateDetailsForTvShow(idTvShow, details, artwork, seasonArt);
 
@@ -2463,6 +2561,9 @@ bool CVideoDatabase::UpdateDetailsForTvShow(int idTvShow, CVideoInfoTag &details
   // add ratings
   details.m_iIdRating = AddRatings(idTvShow, MediaTypeTvShow, details.m_ratings, details.GetDefaultRating());
 
+  // add unique ids
+  details.m_iIdUniqueID = UpdateUniqueIDs(idTvShow, MediaTypeTvShow, details);
+
   // add "all seasons" - the rest are added in SetDetailsForEpisode
   AddSeason(idTvShow, -1);
 
@@ -2482,11 +2583,11 @@ bool CVideoDatabase::UpdateDetailsForTvShow(int idTvShow, CVideoInfoTag &details
   }
 
   SetArtForItem(idTvShow, MediaTypeTvShow, artwork);
-  for (std::map<int, std::map<std::string, std::string>>::const_iterator i = seasonArt.begin(); i != seasonArt.end(); ++i)
+  for (const auto &i : seasonArt)
   {
-    int idSeason = AddSeason(idTvShow, i->first);
+    int idSeason = AddSeason(idTvShow, i.first);
     if (idSeason > -1)
-      SetArtForItem(idSeason, MediaTypeSeason, i->second);
+      SetArtForItem(idSeason, MediaTypeSeason, i.second);
   }
 
   // and insert the new row
@@ -2592,6 +2693,9 @@ int CVideoDatabase::SetDetailsForEpisode(const std::string& strFilenameAndPath,
     // add ratings
     details.m_iIdRating = AddRatings(idEpisode, MediaTypeEpisode, details.m_ratings, details.GetDefaultRating());
 
+    // add unique ids
+    details.m_iIdUniqueID = UpdateUniqueIDs(idEpisode, MediaTypeEpisode, details);
+
     if (details.HasStreamDetails())
     {
       if (details.m_iFileId != -1)
@@ -2798,10 +2902,10 @@ void CVideoDatabase::SetStreamDetailsForFileId(const CStreamDetails& details, in
       tables.emplace_back("movie", VIDEODB_ID_RUNTIME);
       tables.emplace_back("episode", VIDEODB_ID_EPISODE_RUNTIME);
       tables.emplace_back("musicvideo", VIDEODB_ID_MUSICVIDEO_RUNTIME);
-      for (std::vector<std::pair<std::string, int> >::iterator i = tables.begin(); i != tables.end(); ++i)
+      for (const auto &i : tables)
       {
         std::string sql = PrepareSQL("update %s set c%02d=%d where idFile=%d and c%02d=''",
-                                    i->first.c_str(), i->second, details.GetVideoDuration(), idFile, i->second);
+                                    i.first.c_str(), i.second, details.GetVideoDuration(), idFile, i.second);
         m_pDS->exec(sql);
       }
     }
@@ -3233,9 +3337,9 @@ void CVideoDatabase::DeleteTvShow(int idTvShow, bool bKeepId /* = false */)
       strSQL=PrepareSQL("delete from tvshow where idShow=%i", idTvShow);
       m_pDS->exec(strSQL);
 
-      for (std::set<int>::const_iterator i = paths.begin(); i != paths.end(); ++i)
+      for (const auto &i : paths)
       {
-        std::string path = GetSingleValue(PrepareSQL("SELECT strPath FROM path WHERE idPath=%i", *i));
+        std::string path = GetSingleValue(PrepareSQL("SELECT strPath FROM path WHERE idPath=%i", i));
         if (!path.empty())
           InvalidatePathHash(path);
       }
@@ -3680,6 +3784,7 @@ CVideoInfoTag CVideoDatabase::GetDetailsForMovie(const dbiplus::sql_record* cons
   details.AddRating(record->at(VIDEODB_DETAILS_MOVIE_RATING).get_asFloat(), 
                     record->at(VIDEODB_DETAILS_MOVIE_VOTES).get_asInt(),
                     record->at(VIDEODB_DETAILS_MOVIE_RATING_TYPE).get_asString(), true);
+  details.SetUniqueID(record->at(VIDEODB_DETAILS_MOVIE_UNIQUEID_VALUE).get_asString(), record->at(VIDEODB_DETAILS_MOVIE_UNIQUEID_TYPE).get_asString() ,true);
   std::string premieredString = record->at(VIDEODB_DETAILS_MOVIE_PREMIERED).get_asString();
   if (premieredString.size() == 4)
     details.SetYear(record->at(VIDEODB_DETAILS_MOVIE_PREMIERED).get_asInt());
@@ -3701,6 +3806,9 @@ CVideoInfoTag CVideoDatabase::GetDetailsForMovie(const dbiplus::sql_record* cons
     if (getDetails & VideoDbDetailsRating)
       GetRatings(details.m_iDbId, MediaTypeMovie, details.m_ratings);
 
+    if (getDetails & VideoDbDetailsUniqueID)
+     GetUniqueIDs(details.m_iDbId, MediaTypeMovie, details);
+
     details.m_strPictureURL.Parse();
 
     if (getDetails & VideoDbDetailsShowLink)
@@ -3759,6 +3867,7 @@ CVideoInfoTag CVideoDatabase::GetDetailsForTvShow(const dbiplus::sql_record* con
   details.AddRating(record->at(VIDEODB_DETAILS_TVSHOW_RATING).get_asFloat(), 
                     record->at(VIDEODB_DETAILS_TVSHOW_VOTES).get_asInt(),
                     record->at(VIDEODB_DETAILS_TVSHOW_RATING_TYPE).get_asString(), true);
+  details.SetUniqueID(record->at(VIDEODB_DETAILS_TVSHOW_UNIQUEID_VALUE).get_asString(), record->at(VIDEODB_DETAILS_TVSHOW_UNIQUEID_TYPE).get_asString(), true);
   details.m_duration = record->at(VIDEODB_DETAILS_TVSHOW_DURATION).get_asInt();
 
   movieTime += XbmcThreads::SystemClockMillis() - time; time = XbmcThreads::SystemClockMillis();
@@ -3777,6 +3886,9 @@ CVideoInfoTag CVideoDatabase::GetDetailsForTvShow(const dbiplus::sql_record* con
     if (getDetails & VideoDbDetailsRating)
       GetRatings(details.m_iDbId, MediaTypeTvShow, details.m_ratings);
 
+    if (getDetails & VideoDbDetailsUniqueID)
+      GetUniqueIDs(details.m_iDbId, MediaTypeTvShow, details);
+
     details.m_strPictureURL.Parse();
 
     details.m_parsedDetails = getDetails;
@@ -3836,6 +3948,7 @@ CVideoInfoTag CVideoDatabase::GetDetailsForEpisode(const dbiplus::sql_record* co
   details.AddRating(record->at(VIDEODB_DETAILS_EPISODE_RATING).get_asFloat(), 
                     record->at(VIDEODB_DETAILS_EPISODE_VOTES).get_asInt(), 
                     record->at(VIDEODB_DETAILS_EPISODE_RATING_TYPE).get_asString(), true);
+  details.SetUniqueID(record->at(VIDEODB_DETAILS_EPISODE_UNIQUEID_VALUE).get_asString(), record->at(VIDEODB_DETAILS_EPISODE_UNIQUEID_TYPE).get_asString(), true);
   movieTime += XbmcThreads::SystemClockMillis() - time; time = XbmcThreads::SystemClockMillis();
 
   if (getDetails)
@@ -3850,6 +3963,9 @@ CVideoInfoTag CVideoDatabase::GetDetailsForEpisode(const dbiplus::sql_record* co
     if (getDetails & VideoDbDetailsRating)
       GetRatings(details.m_iDbId, MediaTypeEpisode, details.m_ratings);
 
+    if (getDetails & VideoDbDetailsUniqueID)
+      GetUniqueIDs(details.m_iDbId, MediaTypeEpisode, details);
+
     details.m_strPictureURL.Parse();
     
     if (getDetails &  VideoDbDetailsBookmark)
@@ -3938,9 +4054,9 @@ void CVideoDatabase::GetCast(int media_id, const std::string &media_type, std::v
       SActorInfo info;
       info.strName = m_pDS2->fv(0).get_asString();
       bool found = false;
-      for (std::vector<SActorInfo>::iterator i = cast.begin(); i != cast.end(); ++i)
+      for (const auto &i : cast)
       {
-        if (i->strName == info.strName)
+        if (i.strName == info.strName)
         {
           found = true;
           break;
@@ -4008,6 +4124,28 @@ void CVideoDatabase::GetRatings(int media_id, const std::string &media_type, Rat
   }
 }
 
+void CVideoDatabase::GetUniqueIDs(int media_id, const std::string &media_type, CVideoInfoTag& details)
+{
+  try
+  {
+    if (!m_pDB.get()) return;
+    if (!m_pDS2.get()) return;
+
+    std::string sql = PrepareSQL("SELECT type, value FROM uniqueid WHERE media_id = %i AND media_type = '%s'", media_id, media_type.c_str());
+    m_pDS2->query(sql);
+    while (!m_pDS2->eof())
+    {
+      details.SetUniqueID(m_pDS2->fv(1).get_asString(), m_pDS2->fv(0).get_asString());
+      m_pDS2->next();
+    }
+    m_pDS2->close();
+  }
+  catch (...)
+  {
+    CLog::Log(LOGERROR, "%s(%i,%s) failed", __FUNCTION__, media_id, media_type.c_str());
+  }
+}
+
 bool CVideoDatabase::GetVideoSettings(const CFileItem &item, CVideoSettings &settings)
 {
   return GetVideoSettings(GetFileId(item), settings);
@@ -4050,7 +4188,6 @@ bool CVideoDatabase::GetVideoSettings(int idFile, CVideoSettings &settings)
       settings.m_SubtitleStream = m_pDS->fv("SubtitleStream").get_asInt();
       settings.m_ViewMode = m_pDS->fv("ViewMode").get_asInt();
       settings.m_ResumeTime = m_pDS->fv("ResumeTime").get_asInt();
-      settings.m_DeinterlaceMode = (EDEINTERLACEMODE)m_pDS->fv("DeinterlaceMode").get_asInt();
       settings.m_InterlaceMethod = (EINTERLACEMETHOD)m_pDS->fv("Deinterlace").get_asInt();
       settings.m_VolumeAmplification = m_pDS->fv("VolumeAmplification").get_asFloat();
       settings.m_OutputToAllSpeakers = m_pDS->fv("OutputToAllSpeakers").get_asBool();
@@ -4089,13 +4226,11 @@ void CVideoDatabase::SetVideoSettings(const std::string& strFilenameAndPath, con
       // update the item
       strSQL=PrepareSQL("update settings set Deinterlace=%i,ViewMode=%i,ZoomAmount=%f,PixelRatio=%f,VerticalShift=%f,"
                        "AudioStream=%i,SubtitleStream=%i,SubtitleDelay=%f,SubtitlesOn=%i,Brightness=%f,Contrast=%f,Gamma=%f,"
-                       "VolumeAmplification=%f,AudioDelay=%f,OutputToAllSpeakers=%i,Sharpness=%f,NoiseReduction=%f,NonLinStretch=%i,PostProcess=%i,ScalingMethod=%i,"
-                       "DeinterlaceMode=%i,",
+                       "VolumeAmplification=%f,AudioDelay=%f,OutputToAllSpeakers=%i,Sharpness=%f,NoiseReduction=%f,NonLinStretch=%i,PostProcess=%i,ScalingMethod=%i,",
                        setting.m_InterlaceMethod, setting.m_ViewMode, setting.m_CustomZoomAmount, setting.m_CustomPixelRatio, setting.m_CustomVerticalShift,
                        setting.m_AudioStream, setting.m_SubtitleStream, setting.m_SubtitleDelay, setting.m_SubtitleOn,
                        setting.m_Brightness, setting.m_Contrast, setting.m_Gamma, setting.m_VolumeAmplification, setting.m_AudioDelay,
-                       setting.m_OutputToAllSpeakers,setting.m_Sharpness,setting.m_NoiseReduction,setting.m_CustomNonLinStretch,setting.m_PostProcess,setting.m_ScalingMethod,
-                       setting.m_DeinterlaceMode);
+                       setting.m_OutputToAllSpeakers,setting.m_Sharpness,setting.m_NoiseReduction,setting.m_CustomNonLinStretch,setting.m_PostProcess,setting.m_ScalingMethod);
       std::string strSQL2;
       strSQL2=PrepareSQL("ResumeTime=%i,StereoMode=%i,StereoInvert=%i, VideoStream=%i where idFile=%i\n", setting.m_ResumeTime, setting.m_StereoMode,
                         setting.m_StereoInvert, setting.m_VideoStream, idFile);
@@ -4110,15 +4245,15 @@ void CVideoDatabase::SetVideoSettings(const std::string& strFilenameAndPath, con
                 "AudioStream,SubtitleStream,SubtitleDelay,SubtitlesOn,Brightness,"
                 "Contrast,Gamma,VolumeAmplification,AudioDelay,OutputToAllSpeakers,"
                 "ResumeTime,"
-                "Sharpness,NoiseReduction,NonLinStretch,PostProcess,ScalingMethod,DeinterlaceMode,StereoMode,StereoInvert,VideoStream) "
+                "Sharpness,NoiseReduction,NonLinStretch,PostProcess,ScalingMethod,StereoMode,StereoInvert,VideoStream) "
               "VALUES ";
-      strSQL += PrepareSQL("(%i,%i,%i,%f,%f,%f,%i,%i,%f,%i,%f,%f,%f,%f,%f,%i,%i,%f,%f,%i,%i,%i,%i,%i,%i,%i)",
+      strSQL += PrepareSQL("(%i,%i,%i,%f,%f,%f,%i,%i,%f,%i,%f,%f,%f,%f,%f,%i,%i,%f,%f,%i,%i,%i,%i,%i,%i)",
                            idFile, setting.m_InterlaceMethod, setting.m_ViewMode, setting.m_CustomZoomAmount, setting.m_CustomPixelRatio, setting.m_CustomVerticalShift,
                            setting.m_AudioStream, setting.m_SubtitleStream, setting.m_SubtitleDelay, setting.m_SubtitleOn, setting.m_Brightness,
                            setting.m_Contrast, setting.m_Gamma, setting.m_VolumeAmplification, setting.m_AudioDelay, setting.m_OutputToAllSpeakers,
                            setting.m_ResumeTime,
                            setting.m_Sharpness, setting.m_NoiseReduction, setting.m_CustomNonLinStretch, setting.m_PostProcess, setting.m_ScalingMethod,
-                           setting.m_DeinterlaceMode, setting.m_StereoMode, setting.m_StereoInvert, setting.m_VideoStream);
+                           setting.m_StereoMode, setting.m_StereoInvert, setting.m_VideoStream);
       m_pDS->exec(strSQL);
     }
   }
@@ -4130,8 +4265,8 @@ void CVideoDatabase::SetVideoSettings(const std::string& strFilenameAndPath, con
 
 void CVideoDatabase::SetArtForItem(int mediaId, const MediaType &mediaType, const std::map<std::string, std::string> &art)
 {
-  for (std::map<std::string, std::string>::const_iterator i = art.begin(); i != art.end(); ++i)
-    SetArtForItem(mediaId, mediaType, i->first, i->second);
+  for (const auto &i : art)
+    SetArtForItem(mediaId, mediaType, i.first, i.second);
 }
 
 void CVideoDatabase::SetArtForItem(int mediaId, const MediaType &mediaType, const std::string &artType, const std::string &url)
@@ -4209,8 +4344,8 @@ bool CVideoDatabase::RemoveArtForItem(int mediaId, const MediaType &mediaType, c
 bool CVideoDatabase::RemoveArtForItem(int mediaId, const MediaType &mediaType, const std::set<std::string> &artTypes)
 {
   bool result = true;
-  for (std::set<std::string>::const_iterator i = artTypes.begin(); i != artTypes.end(); ++i)
-    result &= RemoveArtForItem(mediaId, mediaType, *i);
+  for (const auto &i : artTypes)
+    result &= RemoveArtForItem(mediaId, mediaType, i);
 
   return result;
 }
@@ -4252,11 +4387,11 @@ bool CVideoDatabase::GetTvShowSeasonArt(int showId, std::map<int, std::map<std::
     std::map<int, int> seasons;
     GetTvShowSeasons(showId, seasons);
 
-    for (std::map<int, int>::const_iterator i = seasons.begin(); i != seasons.end(); ++i)
+    for (const auto &i : seasons)
     {
       std::map<std::string, std::string> art;
-      GetArtForItem(i->second, MediaTypeSeason, art);
-      seasonArt.insert(std::make_pair(i->first,art));
+      GetArtForItem(i.second, MediaTypeSeason, art);
+      seasonArt.insert(std::make_pair(i.first,art));
     }
     return true;
   }
@@ -4313,10 +4448,10 @@ bool CVideoDatabase::GetStackTimes(const std::string &filePath, std::vector<int>
       int timeTotal = 0;
       std::vector<std::string> timeString = StringUtils::Split(m_pDS->fv("times").get_asString(), ",");
       times.clear();
-      for (std::vector<std::string>::const_iterator i = timeString.begin(); i != timeString.end(); ++i)
+      for (const auto &i : timeString)
       {
-        times.push_back(atoi(i->c_str()));
-        timeTotal += atoi(i->c_str());
+        times.push_back(atoi(i.c_str()));
+        timeTotal += atoi(i.c_str());
       }
       m_pDS->close();
       return (timeTotal > 0);
@@ -4386,7 +4521,7 @@ void CVideoDatabase::RemoveContentForPath(const std::string& strPath, CGUIDialog
     std::vector<std::pair<int, std::string> > paths;
     GetSubPaths(strPath, paths);
     int iCurr = 0;
-    for (std::vector<std::pair<int, std::string> >::const_iterator i = paths.begin(); i != paths.end(); ++i)
+    for (const auto &i : paths)
     {
       bool bMvidsChecked=false;
       if (progress)
@@ -4395,15 +4530,15 @@ void CVideoDatabase::RemoveContentForPath(const std::string& strPath, CGUIDialog
         progress->Progress();
       }
 
-      if (HasTvShowInfo(i->second))
-        DeleteTvShow(i->second);
+      if (HasTvShowInfo(i.second))
+        DeleteTvShow(i.second);
       else
       {
-        std::string strSQL = PrepareSQL("select files.strFilename from files join movie on movie.idFile=files.idFile where files.idPath=%i", i->first);
+        std::string strSQL = PrepareSQL("select files.strFilename from files join movie on movie.idFile=files.idFile where files.idPath=%i", i.first);
         m_pDS2->query(strSQL);
         if (m_pDS2->eof())
         {
-          strSQL = PrepareSQL("select files.strFilename from files join musicvideo on musicvideo.idFile=files.idFile where files.idPath=%i", i->first);
+          strSQL = PrepareSQL("select files.strFilename from files join musicvideo on musicvideo.idFile=files.idFile where files.idPath=%i", i.first);
           m_pDS2->query(strSQL);
           bMvidsChecked = true;
         }
@@ -4411,7 +4546,7 @@ void CVideoDatabase::RemoveContentForPath(const std::string& strPath, CGUIDialog
         {
           std::string strMoviePath;
           std::string strFileName = m_pDS2->fv("files.strFilename").get_asString();
-          ConstructPath(strMoviePath, i->second, strFileName);
+          ConstructPath(strMoviePath, i.second, strFileName);
           if (HasMovieInfo(strMoviePath))
             DeleteMovie(strMoviePath);
           if (HasMusicVideoInfo(strMoviePath))
@@ -4419,13 +4554,13 @@ void CVideoDatabase::RemoveContentForPath(const std::string& strPath, CGUIDialog
           m_pDS2->next();
           if (m_pDS2->eof() && !bMvidsChecked)
           {
-            strSQL =PrepareSQL("select files.strFilename from files join musicvideo on musicvideo.idFile=files.idFile where files.idPath=%i", i->first);
+            strSQL =PrepareSQL("select files.strFilename from files join musicvideo on musicvideo.idFile=files.idFile where files.idPath=%i", i.first);
             m_pDS2->query(strSQL);
             bMvidsChecked = true;
           }
         }
         m_pDS2->close();
-        m_pDS2->exec(PrepareSQL("update path set strContent='', strScraper='', strHash='',strSettings='',useFolderNames=0,scanRecursive=0 where idPath=%i", i->first));
+        m_pDS2->exec(PrepareSQL("update path set strContent='', strScraper='', strHash='',strSettings='',useFolderNames=0,scanRecursive=0 where idPath=%i", i.first));
       }
     }
   }
@@ -4561,12 +4696,12 @@ void CVideoDatabase::UpdateTables(int iVersion)
     }
     m_pDS->close();
     // run through these paths figuring out the parent path, and add to the table if found
-    for (std::map<std::string, int>::const_iterator i = paths.begin(); i != paths.end(); ++i)
+    for (const auto &i : paths)
     {
-      std::string parent = URIUtils::GetParentPath(i->first);
-      std::map<std::string, int>::const_iterator j = paths.find(parent);
+      std::string parent = URIUtils::GetParentPath(i.first);
+      auto j = paths.find(parent);
       if (j != paths.end())
-        m_pDS->exec(PrepareSQL("UPDATE path SET idParentPath=%i WHERE idPath=%i", j->second, i->second));
+        m_pDS->exec(PrepareSQL("UPDATE path SET idParentPath=%i WHERE idPath=%i", j->second, i.second));
     }
   }
   if (iVersion < 82)
@@ -4577,7 +4712,7 @@ void CVideoDatabase::UpdateTables(int iVersion)
   if (iVersion < 83)
   {
     // drop duplicates in tvshow table, and update tvshowlinkpath accordingly
-    std::string sql = PrepareSQL("SELECT tvshow.idShow,idPath,c%02d,c%02d,c%02d FROM tvshow JOIN tvshowlinkpath ON tvshow.idShow = tvshowlinkpath.idShow", VIDEODB_ID_TV_TITLE, VIDEODB_ID_TV_PREMIERED, VIDEODB_ID_TV_IDENT);
+    std::string sql = PrepareSQL("SELECT tvshow.idShow,idPath,c%02d,c%02d,c%02d FROM tvshow JOIN tvshowlinkpath ON tvshow.idShow = tvshowlinkpath.idShow", VIDEODB_ID_TV_TITLE, VIDEODB_ID_TV_PREMIERED, VIDEODB_ID_TV_IDENT_ID);
     m_pDS->query(sql);
     std::vector<CShowItem> shows;
     while (!m_pDS->eof())
@@ -4594,10 +4729,10 @@ void CVideoDatabase::UpdateTables(int iVersion)
     m_pDS->close();
     if (!shows.empty())
     {
-      for (std::vector<CShowItem>::iterator i = shows.begin() + 1; i != shows.end(); ++i)
+      for (auto i = shows.begin() + 1; i != shows.end(); ++i)
       {
         // has this show been found before?
-        std::vector<CShowItem>::const_iterator j = find(shows.begin(), i, *i);
+        auto j = find(shows.begin(), i, *i);
         if (j != i)
         { // this is a duplicate
           // update the tvshowlinkpath table
@@ -4633,11 +4768,11 @@ void CVideoDatabase::UpdateTables(int iVersion)
     }
     m_pDS->close();
     // update these
-    for (std::vector<CShowLink>::const_iterator i = shows.begin(); i != shows.end(); ++i)
+    for (auto i = shows.begin(); i != shows.end(); ++i)
     {
       std::vector<std::string> paths;
       CMultiPathDirectory::GetPaths(i->path, paths);
-      for (std::vector<std::string>::const_iterator j = paths.begin(); j != paths.end(); ++j)
+      for (auto j = paths.begin(); j != paths.end(); ++j)
       {
         int idPath = AddPath(*j, URIUtils::GetParentPath(*j));
         /* we can't rely on REPLACE INTO here as analytics (indices) aren't online yet */
@@ -4967,11 +5102,63 @@ void CVideoDatabase::UpdateTables(int iVersion)
     m_pDS->exec("ALTER TABLE musicvideo ADD premiered TEXT");
     m_pDS->exec(PrepareSQL("UPDATE musicvideo SET premiered=c%02d", VIDEODB_ID_MUSICVIDEO_YEAR));
   }
+
+  if (iVersion < 107)
+  {
+    // need this due to the nested GetScraperPath query
+    std::unique_ptr<Dataset> pDS;
+    pDS.reset(m_pDB->CreateDataset());
+    if (NULL == pDS.get()) return;
+
+    pDS->exec("CREATE TABLE uniqueid (uniqueid_id INTEGER PRIMARY KEY, media_id INTEGER, media_type TEXT, value TEXT, type TEXT)");
+
+    for (int i = 0; i < 3; ++i)
+    {
+      std::string mediatype, columnID;
+      int columnUniqueID;
+      switch (i)
+      {
+      case (0):
+        mediatype = "movie";
+        columnID = "idMovie";
+        columnUniqueID = VIDEODB_ID_IDENT_ID;
+        break;
+      case (1):
+        mediatype = "tvshow";
+        columnID = "idShow";
+        columnUniqueID = VIDEODB_ID_TV_IDENT_ID;
+        break;
+      case (2):
+        mediatype = "episode";
+        columnID = "idEpisode";
+        columnUniqueID = VIDEODB_ID_EPISODE_IDENT_ID;
+        break;
+      default:
+        continue;
+      }
+      pDS->query(PrepareSQL("SELECT %s, c%02d FROM %s", columnID.c_str(), columnUniqueID, mediatype.c_str()));
+      while (!pDS->eof())
+      {
+        std::string uniqueid = pDS->fv(1).get_asString();
+        if (!uniqueid.empty())
+        {
+          int mediaid = pDS->fv(0).get_asInt();
+          if (StringUtils::StartsWith(uniqueid, "tt"))
+            m_pDS2->exec(PrepareSQL("INSERT INTO uniqueid(media_id, media_type, type, value) VALUES (%i, '%s', 'imdb', '%s')", mediaid, mediatype.c_str(), uniqueid.c_str()));
+          else
+            m_pDS2->exec(PrepareSQL("INSERT INTO uniqueid(media_id, media_type, type, value) VALUES (%i, '%s', 'unknown', '%s')", mediaid, mediatype.c_str(), uniqueid.c_str()));
+          m_pDS2->exec(PrepareSQL("UPDATE %s SET c%02d='%i' WHERE %s=%i", mediatype.c_str(), columnUniqueID, (int)m_pDS2->lastinsertid(), columnID.c_str(), mediaid));
+        }
+        pDS->next();
+      }
+      pDS->close();
+    }
+  }
 }
 
 int CVideoDatabase::GetSchemaVersion() const
 {
-  return 106;
+  return 107;
 }
 
 bool CVideoDatabase::LookupByFolders(const std::string &path, bool shows)
@@ -5415,14 +5602,13 @@ bool CVideoDatabase::GetNavCommon(const std::string& strBaseDir, CFileItemList&
     if (CProfilesManager::GetInstance().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE && !g_passwordManager.bMasterUser)
     {
       std::map<int, std::pair<std::string,int> > mapItems;
-      std::map<int, std::pair<std::string,int> >::iterator it;
       while (!m_pDS->eof())
       {
         int id = m_pDS->fv(0).get_asInt();
         std::string str = m_pDS->fv(1).get_asString();
 
         // was this already found?
-        it = mapItems.find(id);
+        auto it = mapItems.find(id);
         if (it == mapItems.end())
         {
           // check path
@@ -5438,20 +5624,20 @@ bool CVideoDatabase::GetNavCommon(const std::string& strBaseDir, CFileItemList&
       }
       m_pDS->close();
 
-      for (it = mapItems.begin(); it != mapItems.end(); ++it)
+      for (const auto &i : mapItems)
       {
-        CFileItemPtr pItem(new CFileItem(it->second.first));
-        pItem->GetVideoInfoTag()->m_iDbId = it->first;
+        CFileItemPtr pItem(new CFileItem(i.second.first));
+        pItem->GetVideoInfoTag()->m_iDbId = i.first;
         pItem->GetVideoInfoTag()->m_type = type;
 
         CVideoDbUrl itemUrl = videoUrl;
-        std::string path = StringUtils::Format("%i/", it->first);
+        std::string path = StringUtils::Format("%i/", i.first);
         itemUrl.AppendPath(path);
         pItem->SetPath(itemUrl.ToString());
 
         pItem->m_bIsFolder = true;
         if (idContent == VIDEODB_CONTENT_MOVIES || idContent == VIDEODB_CONTENT_MUSICVIDEOS)
-          pItem->GetVideoInfoTag()->m_playCount = it->second.second;
+          pItem->GetVideoInfoTag()->m_playCount = i.second.second;
         if (!items.Contains(pItem->GetPath()))
         {
           pItem->SetLabelPreformated(true);
@@ -5598,12 +5784,11 @@ bool CVideoDatabase::GetMusicVideoAlbumsNav(const std::string& strBaseDir, CFile
     if (CProfilesManager::GetInstance().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE && !g_passwordManager.bMasterUser)
     {
       std::map<int, std::pair<std::string,std::string> > mapAlbums;
-      std::map<int, std::pair<std::string,std::string> >::iterator it;
       while (!m_pDS->eof())
       {
         int lidMVideo = m_pDS->fv(1).get_asInt();
         std::string strAlbum = m_pDS->fv(0).get_asString();
-        it = mapAlbums.find(lidMVideo);
+        auto it = mapAlbums.find(lidMVideo);
         // was this genre already found?
         if (it == mapAlbums.end())
         {
@@ -5615,14 +5800,14 @@ bool CVideoDatabase::GetMusicVideoAlbumsNav(const std::string& strBaseDir, CFile
       }
       m_pDS->close();
 
-      for (it=mapAlbums.begin();it != mapAlbums.end();++it)
+      for (const auto &i : mapAlbums)
       {
-        if (!it->second.first.empty())
+        if (!i.second.first.empty())
         {
-          CFileItemPtr pItem(new CFileItem(it->second.first));
+          CFileItemPtr pItem(new CFileItem(i.second.first));
 
           CVideoDbUrl itemUrl = videoUrl;
-          std::string path = StringUtils::Format("%i/", it->first);
+          std::string path = StringUtils::Format("%i/", i.first);
           itemUrl.AppendPath(path);
           pItem->SetPath(itemUrl.ToString());
 
@@ -5630,7 +5815,7 @@ bool CVideoDatabase::GetMusicVideoAlbumsNav(const std::string& strBaseDir, CFile
           pItem->SetLabelPreformated(true);
           if (!items.Contains(pItem->GetPath()))
           {
-            pItem->GetVideoInfoTag()->m_artist.push_back(it->second.second);
+            pItem->GetVideoInfoTag()->m_artist.push_back(i.second.second);
             items.Add(pItem);
           }
         }
@@ -5845,7 +6030,6 @@ bool CVideoDatabase::GetPeopleNav(const std::string& strBaseDir, CFileItemList&
     if (CProfilesManager::GetInstance().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE && !g_passwordManager.bMasterUser)
     {
       std::map<int, CActor> mapActors;
-      std::map<int, CActor>::iterator it;
 
       while (!m_pDS->eof())
       {
@@ -5859,7 +6043,7 @@ bool CVideoDatabase::GetPeopleNav(const std::string& strBaseDir, CFileItemList&
           actor.appearances = 1;
         }
         else actor.appearances = m_pDS->fv(4).get_asInt();
-        it = mapActors.find(idActor);
+        auto it = mapActors.find(idActor);
         // is this actor already known?
         if (it == mapActors.end())
         {
@@ -5873,21 +6057,21 @@ bool CVideoDatabase::GetPeopleNav(const std::string& strBaseDir, CFileItemList&
       }
       m_pDS->close();
 
-      for (it=mapActors.begin();it != mapActors.end();++it)
+      for (const auto &i : mapActors)
       {
-        CFileItemPtr pItem(new CFileItem(it->second.name));
+        CFileItemPtr pItem(new CFileItem(i.second.name));
 
         CVideoDbUrl itemUrl = videoUrl;
-        std::string path = StringUtils::Format("%i/", it->first);
+        std::string path = StringUtils::Format("%i/", i.first);
         itemUrl.AppendPath(path);
         pItem->SetPath(itemUrl.ToString());
 
         pItem->m_bIsFolder=true;
-        pItem->GetVideoInfoTag()->m_playCount = it->second.playcount;
-        pItem->GetVideoInfoTag()->m_strPictureURL.ParseString(it->second.thumb);
-        pItem->GetVideoInfoTag()->m_iDbId = it->first;
+        pItem->GetVideoInfoTag()->m_playCount = i.second.playcount;
+        pItem->GetVideoInfoTag()->m_strPictureURL.ParseString(i.second.thumb);
+        pItem->GetVideoInfoTag()->m_iDbId = i.first;
         pItem->GetVideoInfoTag()->m_type = type;
-        pItem->GetVideoInfoTag()->m_relevance = it->second.appearances;
+        pItem->GetVideoInfoTag()->m_relevance = i.second.appearances;
         items.Add(pItem);
       }
     }
@@ -6006,7 +6190,6 @@ bool CVideoDatabase::GetYearsNav(const std::string& strBaseDir, CFileItemList& i
     if (CProfilesManager::GetInstance().GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE && !g_passwordManager.bMasterUser)
     {
       std::map<int, std::pair<std::string,int> > mapYears;
-      std::map<int, std::pair<std::string,int> >::iterator it;
       while (!m_pDS->eof())
       {
         int lYear = 0;
@@ -6019,7 +6202,7 @@ bool CVideoDatabase::GetYearsNav(const std::string& strBaseDir, CFileItemList& i
           time.SetFromDateString(dateString);
           lYear = time.GetYear();
         }
-        it = mapYears.find(lYear);
+        auto it = mapYears.find(lYear);
         if (it == mapYears.end())
         {
           // check path
@@ -6036,20 +6219,20 @@ bool CVideoDatabase::GetYearsNav(const std::string& strBaseDir, CFileItemList& i
       }
       m_pDS->close();
 
-      for (it=mapYears.begin();it != mapYears.end();++it)
+      for (const auto &i : mapYears)
       {
-        if (it->first == 0)
+        if (i.first == 0)
           continue;
-        CFileItemPtr pItem(new CFileItem(it->second.first));
+        CFileItemPtr pItem(new CFileItem(i.second.first));
 
         CVideoDbUrl itemUrl = videoUrl;
-        std::string path = StringUtils::Format("%i/", it->first);
+        std::string path = StringUtils::Format("%i/", i.first);
         itemUrl.AppendPath(path);
         pItem->SetPath(itemUrl.ToString());
 
         pItem->m_bIsFolder=true;
         if (idContent == VIDEODB_CONTENT_MOVIES || idContent == VIDEODB_CONTENT_MUSICVIDEOS)
-          pItem->GetVideoInfoTag()->m_playCount = it->second.second;
+          pItem->GetVideoInfoTag()->m_playCount = i.second.second;
         items.Add(pItem);
       }
     }
@@ -6479,9 +6662,9 @@ bool CVideoDatabase::GetMoviesByWhere(const std::string& strBaseDir, const Filte
     // get data from returned rows
     items.Reserve(results.size());
     const query_data &data = m_pDS->get_result_set().records;
-    for (DatabaseResults::const_iterator it = results.begin(); it != results.end(); ++it)
+    for (const auto &i : results)
     {
-      unsigned int targetRow = (unsigned int)it->at(FieldRow).asInteger();
+      unsigned int targetRow = (unsigned int)i.at(FieldRow).asInteger();
       const dbiplus::sql_record* const record = data.at(targetRow);
 
       CVideoInfoTag movie = GetDetailsForMovie(record, getDetails);
@@ -6586,9 +6769,9 @@ bool CVideoDatabase::GetTvShowsByWhere(const std::string& strBaseDir, const Filt
     // get data from returned rows
     items.Reserve(results.size());
     const query_data &data = m_pDS->get_result_set().records;
-    for (DatabaseResults::const_iterator it = results.begin(); it != results.end(); ++it)
+    for (const auto &i : results)
     {
-      unsigned int targetRow = (unsigned int)it->at(FieldRow).asInteger();
+      unsigned int targetRow = (unsigned int)i.at(FieldRow).asInteger();
       const dbiplus::sql_record* const record = data.at(targetRow);
       
       CFileItemPtr pItem(new CFileItem());
@@ -6714,9 +6897,9 @@ bool CVideoDatabase::GetEpisodesByWhere(const std::string& strBaseDir, const Fil
     CLabelFormatter formatter("%H. %T", "");
 
     const query_data &data = m_pDS->get_result_set().records;
-    for (DatabaseResults::const_iterator it = results.begin(); it != results.end(); ++it)
+    for (const auto &i : results)
     {
-      unsigned int targetRow = (unsigned int)it->at(FieldRow).asInteger();
+      unsigned int targetRow = (unsigned int)i.at(FieldRow).asInteger();
       const dbiplus::sql_record* const record = data.at(targetRow);
 
       CVideoInfoTag movie = GetDetailsForEpisode(record, getDetails);
@@ -7554,9 +7737,9 @@ bool CVideoDatabase::GetMusicVideosByWhere(const std::string &baseDir, const Fil
     items.Reserve(results.size());
     // get songs from returned subtable
     const query_data &data = m_pDS->get_result_set().records;
-    for (DatabaseResults::const_iterator it = results.begin(); it != results.end(); ++it)
+    for (const auto &i : results)
     {
-      unsigned int targetRow = (unsigned int)it->at(FieldRow).asInteger();
+      unsigned int targetRow = (unsigned int)i.at(FieldRow).asInteger();
       const dbiplus::sql_record* const record = data.at(targetRow);
       
       CVideoInfoTag musicvideo = GetDetailsForMusicVideo(record, getDetails);
@@ -8102,8 +8285,8 @@ void CVideoDatabase::CleanDatabase(CGUIDialogProgressBarHandle* handle, const st
     if (!paths.empty())
     {
       std::string strPaths;
-      for (std::set<int>::const_iterator it = paths.begin(); it != paths.end(); ++it)
-        strPaths += StringUtils::Format(",%i", *it);
+      for (const auto &i : paths)
+        strPaths += StringUtils::Format(",%i", i);
       sql += PrepareSQL(" AND path.idPath IN (%s)", strPaths.substr(1).c_str());
     }
 
@@ -8229,8 +8412,8 @@ void CVideoDatabase::CleanDatabase(CGUIDialogProgressBarHandle* handle, const st
     if (!movieIDs.empty())
     {
       std::string moviesToDelete;
-      for (std::vector<int>::const_iterator it = movieIDs.begin(); it != movieIDs.end(); ++it)
-        moviesToDelete += StringUtils::Format("%i,", *it);
+      for (const auto &i : movieIDs)
+        moviesToDelete += StringUtils::Format("%i,", i);
       moviesToDelete = "(" + StringUtils::TrimRight(moviesToDelete, ",") + ")";
 
       CLog::Log(LOGDEBUG, "%s: Cleaning movie table", __FUNCTION__);
@@ -8241,8 +8424,8 @@ void CVideoDatabase::CleanDatabase(CGUIDialogProgressBarHandle* handle, const st
     if (!episodeIDs.empty())
     {
       std::string episodesToDelete;
-      for (std::vector<int>::const_iterator it = episodeIDs.begin(); it != episodeIDs.end(); ++it)
-        episodesToDelete += StringUtils::Format("%i,", *it);
+      for (const auto &i : episodeIDs)
+        episodesToDelete += StringUtils::Format("%i,", i);
       episodesToDelete = "(" + StringUtils::TrimRight(episodesToDelete, ",") + ")";
 
       CLog::Log(LOGDEBUG, "%s: Cleaning episode table", __FUNCTION__);
@@ -8260,9 +8443,9 @@ void CVideoDatabase::CleanDatabase(CGUIDialogProgressBarHandle* handle, const st
     std::string strIds;
     while (!m_pDS->eof())
     {
-      std::map<int, bool>::const_iterator pathsDeleteDecision = pathsDeleteDecisions.find(m_pDS->fv(0).get_asInt());
+      auto pathsDeleteDecision = pathsDeleteDecisions.find(m_pDS->fv(0).get_asInt());
       // Check if we have a decision for the parent path
-      std::map<int, bool>::const_iterator pathsDeleteDecisionByParent = pathsDeleteDecisions.find(m_pDS->fv(2).get_asInt());
+      auto pathsDeleteDecisionByParent = pathsDeleteDecisions.find(m_pDS->fv(2).get_asInt());
       if (((pathsDeleteDecision != pathsDeleteDecisions.end() && pathsDeleteDecision->second) ||
            (pathsDeleteDecision == pathsDeleteDecisions.end() && !CDirectory::Exists(m_pDS->fv(1).get_asString(), false))) &&
           ((pathsDeleteDecisionByParent != pathsDeleteDecisions.end() && pathsDeleteDecisionByParent->second) ||
@@ -8302,8 +8485,8 @@ void CVideoDatabase::CleanDatabase(CGUIDialogProgressBarHandle* handle, const st
     if (!musicVideoIDs.empty())
     {
       std::string musicVideosToDelete;
-      for (std::vector<int>::const_iterator it = musicVideoIDs.begin(); it != musicVideoIDs.end(); ++it)
-        musicVideosToDelete += StringUtils::Format("%i,", *it);
+      for (const auto &i : musicVideoIDs)
+        musicVideosToDelete += StringUtils::Format("%i,", i);
       musicVideosToDelete = "(" + StringUtils::TrimRight(musicVideosToDelete, ",") + ")";
 
       CLog::Log(LOGDEBUG, "%s: Cleaning musicvideo table", __FUNCTION__);
@@ -8363,17 +8546,17 @@ void CVideoDatabase::CleanDatabase(CGUIDialogProgressBarHandle* handle, const st
     time = XbmcThreads::SystemClockMillis() - time;
     CLog::Log(LOGNOTICE, "%s: Cleaning videodatabase done. Operation took %s", __FUNCTION__, StringUtils::SecondsToTimeString(time / 1000).c_str());
 
-    for (std::vector<int>::const_iterator it = movieIDs.begin(); it != movieIDs.end(); ++it)
-      AnnounceRemove(MediaTypeMovie, *it, true);
+    for (const auto &i : movieIDs)
+      AnnounceRemove(MediaTypeMovie, i, true);
 
-    for (std::vector<int>::const_iterator it = episodeIDs.begin(); it != episodeIDs.end(); ++it)
-      AnnounceRemove(MediaTypeEpisode, *it, true);
+    for (const auto &i : episodeIDs)
+      AnnounceRemove(MediaTypeEpisode, i, true);
 
-    for (std::vector<int>::const_iterator it = tvshowIDs.begin(); it != tvshowIDs.end(); ++it)
-      AnnounceRemove(MediaTypeTvShow, *it, true);
+    for (const auto &i : tvshowIDs)
+      AnnounceRemove(MediaTypeTvShow, i, true);
 
-    for (std::vector<int>::const_iterator it = musicVideoIDs.begin(); it != musicVideoIDs.end(); ++it)
-      AnnounceRemove(MediaTypeMusicVideo, *it, true);
+    for (const auto &i : musicVideoIDs)
+      AnnounceRemove(MediaTypeMusicVideo, i, true);
   }
   catch (...)
   {
@@ -8456,7 +8639,7 @@ std::vector<int> CVideoDatabase::CleanMediaType(const std::string &mediaType, co
         sourcePath = parentPath;
 
       int sourcePathID = GetPathId(sourcePath);
-      std::map<int, std::pair<bool, bool> >::const_iterator sourcePathsDeleteDecision = sourcePathsDeleteDecisions.find(sourcePathID);
+      auto sourcePathsDeleteDecision = sourcePathsDeleteDecisions.find(sourcePathID);
       if (sourcePathsDeleteDecision == sourcePathsDeleteDecisions.end())
       {
         bool sourcePathNotExists = (sourceNotFound || !CDirectory::Exists(sourcePath, false));
@@ -8638,8 +8821,8 @@ void CVideoDatabase::ExportToXML(const std::string &path, bool singleFile /* = t
       if (GetArtForItem(movie.m_iDbId, movie.m_type, artwork) && singleFile)
       {
         TiXmlElement additionalNode("art");
-        for (std::map<std::string, std::string>::const_iterator i = artwork.begin(); i != artwork.end(); ++i)
-          XMLUtils::SetString(&additionalNode, i->first.c_str(), i->second);
+        for (const auto &i : artwork)
+          XMLUtils::SetString(&additionalNode, i.first.c_str(), i.second);
         movie.Save(pMain, "movie", true, &additionalNode);
       }
       else
@@ -8707,10 +8890,10 @@ void CVideoDatabase::ExportToXML(const std::string &path, bool singleFile /* = t
             strFileName += StringUtils::Format("_%i", movie.GetYear());
           item.SetPath(GetSafeFile(moviesDir, strFileName) + ".avi");
         }
-        for (std::map<std::string, std::string>::const_iterator i = artwork.begin(); i != artwork.end(); ++i)
+        for (const auto &i : artwork)
         {
-          std::string savedThumb = item.GetLocalArt(i->first, false);
-          CTextureCache::GetInstance().Export(i->second, savedThumb, overwrite);
+          std::string savedThumb = item.GetLocalArt(i.first, false);
+          CTextureCache::GetInstance().Export(i.second, savedThumb, overwrite);
         }
         if (actorThumbs)
           ExportActorThumbs(actorsDir, movie, !singleFile, overwrite);
@@ -8735,8 +8918,8 @@ void CVideoDatabase::ExportToXML(const std::string &path, bool singleFile /* = t
       if (GetArtForItem(movie.m_iDbId, movie.m_type, artwork) && singleFile)
       {
         TiXmlElement additionalNode("art");
-        for (std::map<std::string, std::string>::const_iterator i = artwork.begin(); i != artwork.end(); ++i)
-          XMLUtils::SetString(&additionalNode, i->first.c_str(), i->second);
+        for (const auto &i : artwork)
+          XMLUtils::SetString(&additionalNode, i.first.c_str(), i.second);
         movie.Save(pMain, "musicvideo", true, &additionalNode);
       }
       else
@@ -8796,10 +8979,10 @@ void CVideoDatabase::ExportToXML(const std::string &path, bool singleFile /* = t
             strFileName += StringUtils::Format("_%i", movie.GetYear());
           item.SetPath(GetSafeFile(moviesDir, strFileName) + ".avi");
         }
-        for (std::map<std::string, std::string>::const_iterator i = artwork.begin(); i != artwork.end(); ++i)
+        for (const auto &i : artwork)
         {
-          std::string savedThumb = item.GetLocalArt(i->first, false);
-          CTextureCache::GetInstance().Export(i->second, savedThumb, overwrite);
+          std::string savedThumb = item.GetLocalArt(i.first, false);
+          CTextureCache::GetInstance().Export(i.second, savedThumb, overwrite);
         }
       }
       m_pDS->next();
@@ -8825,14 +9008,14 @@ void CVideoDatabase::ExportToXML(const std::string &path, bool singleFile /* = t
       if (GetArtForItem(tvshow.m_iDbId, tvshow.m_type, artwork) && singleFile)
       {
         TiXmlElement additionalNode("art");
-        for (std::map<std::string, std::string>::const_iterator i = artwork.begin(); i != artwork.end(); ++i)
-          XMLUtils::SetString(&additionalNode, i->first.c_str(), i->second);
-        for (std::map<int, std::map<std::string, std::string> >::const_iterator i = seasonArt.begin(); i != seasonArt.end(); ++i)
+        for (const auto &i : artwork)
+          XMLUtils::SetString(&additionalNode, i.first.c_str(), i.second);
+        for (const auto &i : seasonArt)
         {
           TiXmlElement seasonNode("season");
-          seasonNode.SetAttribute("num", i->first);
-          for (std::map<std::string, std::string>::const_iterator j = i->second.begin(); j != i->second.end(); ++j)
-            XMLUtils::SetString(&seasonNode, j->first.c_str(), j->second);
+          seasonNode.SetAttribute("num", i.first);
+          for (const auto &j : i.second)
+            XMLUtils::SetString(&seasonNode, j.first.c_str(), j.second);
           additionalNode.InsertEndChild(seasonNode);
         }
         tvshow.Save(pMain, "tvshow", true, &additionalNode);
@@ -8890,30 +9073,30 @@ void CVideoDatabase::ExportToXML(const std::string &path, bool singleFile /* = t
         if (singleFile)
           item.SetPath(GetSafeFile(tvshowsDir, tvshow.m_strTitle));
 
-        for (std::map<std::string, std::string>::const_iterator i = artwork.begin(); i != artwork.end(); ++i)
+        for (const auto &i : artwork)
         {
-          std::string savedThumb = item.GetLocalArt(i->first, true);
-          CTextureCache::GetInstance().Export(i->second, savedThumb, overwrite);
+          std::string savedThumb = item.GetLocalArt(i.first, true);
+          CTextureCache::GetInstance().Export(i.second, savedThumb, overwrite);
         }
 
         if (actorThumbs)
           ExportActorThumbs(actorsDir, tvshow, !singleFile, overwrite);
 
         // export season thumbs
-        for (std::map<int, std::map<std::string, std::string> >::const_iterator i = seasonArt.begin(); i != seasonArt.end(); ++i)
+        for (const auto &i : seasonArt)
         {
           std::string seasonThumb;
-          if (i->first == -1)
+          if (i.first == -1)
             seasonThumb = "season-all";
-          else if (i->first == 0)
+          else if (i.first == 0)
             seasonThumb = "season-specials";
           else
-            seasonThumb = StringUtils::Format("season%02i", i->first);
-          for (std::map<std::string, std::string>::const_iterator j = i->second.begin(); j != i->second.end(); ++j)
+            seasonThumb = StringUtils::Format("season%02i", i.first);
+          for (const auto &j : i.second)
           {
-            std::string savedThumb(item.GetLocalArt(seasonThumb + "-" + j->first, true));
-            if (!i->second.empty())
-              CTextureCache::GetInstance().Export(j->second, savedThumb, overwrite);
+            std::string savedThumb(item.GetLocalArt(seasonThumb + "-" + j.first, true));
+            if (!i.second.empty())
+              CTextureCache::GetInstance().Export(j.second, savedThumb, overwrite);
           }
         }
       }
@@ -8930,8 +9113,8 @@ void CVideoDatabase::ExportToXML(const std::string &path, bool singleFile /* = t
         if (GetArtForItem(episode.m_iDbId, MediaTypeEpisode, artwork) && singleFile)
         {
           TiXmlElement additionalNode("art");
-          for (std::map<std::string, std::string>::const_iterator i = artwork.begin(); i != artwork.end(); ++i)
-            XMLUtils::SetString(&additionalNode, i->first.c_str(), i->second);
+          for (const auto &i : artwork)
+            XMLUtils::SetString(&additionalNode, i.first.c_str(), i.second);
           episode.Save(pMain->LastChild(), "episodedetails", true, &additionalNode);
         }
         else if (singleFile)
@@ -8988,10 +9171,10 @@ void CVideoDatabase::ExportToXML(const std::string &path, bool singleFile /* = t
             std::string epName = StringUtils::Format("s%02ie%02i.avi", episode.m_iSeason, episode.m_iEpisode);
             item.SetPath(URIUtils::AddFileToFolder(showDir, epName));
           }
-          for (std::map<std::string, std::string>::const_iterator i = artwork.begin(); i != artwork.end(); ++i)
+          for (const auto &i : artwork)
           {
-            std::string savedThumb = item.GetLocalArt(i->first, false);
-            CTextureCache::GetInstance().Export(i->second, savedThumb, overwrite);
+            std::string savedThumb = item.GetLocalArt(i.first, false);
+            CTextureCache::GetInstance().Export(i.second, savedThumb, overwrite);
           }
           if (actorThumbs)
             ExportActorThumbs(actorsDir, episode, !singleFile, overwrite);
@@ -9016,16 +9199,16 @@ void CVideoDatabase::ExportToXML(const std::string &path, bool singleFile /* = t
       GetPaths(paths);
       TiXmlElement xmlPathElement("paths");
       TiXmlNode *pPaths = pMain->InsertEndChild(xmlPathElement);
-      for(std::set<std::string>::iterator iter = paths.begin(); iter != paths.end(); ++iter)
+      for (const auto &i : paths)
       {
         bool foundDirectly = false;
         SScanSettings settings;
-        ScraperPtr info = GetScraperForPath(*iter, settings, foundDirectly);
+        ScraperPtr info = GetScraperForPath(i, settings, foundDirectly);
         if (info && foundDirectly)
         {
           TiXmlElement xmlPathElement2("path");
           TiXmlNode *pPath = pPaths->InsertEndChild(xmlPathElement2);
-          XMLUtils::SetString(pPath,"url", *iter);
+          XMLUtils::SetString(pPath,"url", i);
           XMLUtils::SetInt(pPath,"scanrecursive", settings.recurse);
           XMLUtils::SetBoolean(pPath,"usefoldernames", settings.parent_name);
           XMLUtils::SetString(pPath,"content", TranslateContent(info->Content()));
@@ -9070,14 +9253,14 @@ void CVideoDatabase::ExportActorThumbs(const std::string &strDir, const CVideoIn
     }
   }
 
-  for (CVideoInfoTag::iCast iter = tag.m_cast.begin();iter != tag.m_cast.end();++iter)
+  for (const auto &i : tag.m_cast)
   {
     CFileItem item;
-    item.SetLabel(iter->strName);
-    if (!iter->thumb.empty())
+    item.SetLabel(i.strName);
+    if (!i.thumb.empty())
     {
-      std::string thumbFile(GetSafeFile(strPath, iter->strName));
-      CTextureCache::GetInstance().Export(iter->thumb, thumbFile, overwrite);
+      std::string thumbFile(GetSafeFile(strPath, i.strName));
+      CTextureCache::GetInstance().Export(i.thumb, thumbFile, overwrite);
     }
   }
 }
@@ -9213,10 +9396,10 @@ void CVideoDatabase::ImportFromXML(const std::string &path)
         std::map<int, std::map<std::string, std::string> > seasonArt;
         artItem.GetVideoInfoTag()->m_strPath = artPath;
         scanner.GetSeasonThumbs(*artItem.GetVideoInfoTag(), seasonArt, CVideoThumbLoader::GetArtTypes(MediaTypeSeason), true);
-        for (std::map<int, std::map<std::string, std::string> >::iterator i = seasonArt.begin(); i != seasonArt.end(); ++i)
+        for (const auto &i : seasonArt)
         {
-          int seasonID = AddSeason(showID, i->first);
-          SetArtForItem(seasonID, MediaTypeSeason, i->second);
+          int seasonID = AddSeason(showID, i.first);
+          SetArtForItem(seasonID, MediaTypeSeason, i.second);
         }
         current++;
         // now load the episodes
@@ -9478,7 +9661,7 @@ bool CVideoDatabase::GetItemsForPath(const std::string &content, const std::stri
 
 void CVideoDatabase::AppendIdLinkFilter(const char* field, const char *table, const MediaType& mediaType, const char *view, const char *viewKey, const CUrlOptions::UrlOptions& options, Filter &filter)
 {
-  CUrlOptions::UrlOptions::const_iterator option = options.find((std::string)field + "id");
+  auto option = options.find((std::string)field + "id");
   if (option == options.end())
     return;
 
@@ -9488,7 +9671,7 @@ void CVideoDatabase::AppendIdLinkFilter(const char* field, const char *table, co
 
 void CVideoDatabase::AppendLinkFilter(const char* field, const char *table, const MediaType& mediaType, const char *view, const char *viewKey, const CUrlOptions::UrlOptions& options, Filter &filter)
 {
-  CUrlOptions::UrlOptions::const_iterator option = options.find(field);
+  auto option = options.find(field);
   if (option == options.end())
     return;
 
@@ -9505,7 +9688,6 @@ bool CVideoDatabase::GetFilter(CDbUrl &videoUrl, Filter &filter, SortDescription
   std::string type = videoUrl.GetType();
   std::string itemType = ((const CVideoDbUrl &)videoUrl).GetItemType();
   const CUrlOptions::UrlOptions& options = videoUrl.GetOptions();
-  CUrlOptions::UrlOptions::const_iterator option;
 
   if (type == "movies")
   {
@@ -9521,7 +9703,7 @@ bool CVideoDatabase::GetFilter(CDbUrl &videoUrl, Filter &filter, SortDescription
     AppendIdLinkFilter("director", "actor", "movie", "movie", "idMovie", options, filter);
     AppendLinkFilter("director", "actor", "movie", "movie", "idMovie", options, filter);
 
-    option = options.find("year");
+    auto option = options.find("year");
     if (option != options.end())
       filter.AppendWhere(PrepareSQL("movie_view.premiered like '%i%%'", (int)option->second.asInteger()));
 
@@ -9551,7 +9733,7 @@ bool CVideoDatabase::GetFilter(CDbUrl &videoUrl, Filter &filter, SortDescription
 
       AppendIdLinkFilter("director", "actor", "tvshow", "tvshow", "idShow", options, filter);
 
-      option = options.find("year");
+      auto option = options.find("year");
       if (option != options.end())
         filter.AppendWhere(PrepareSQL("tvshow_view.c%02d like '%%%i%%'", VIDEODB_ID_TV_PREMIERED, (int)option->second.asInteger()));
 
@@ -9563,7 +9745,7 @@ bool CVideoDatabase::GetFilter(CDbUrl &videoUrl, Filter &filter, SortDescription
     }
     else if (itemType == "seasons")
     {
-      option = options.find("tvshowid");
+      auto option = options.find("tvshowid");
       if (option != options.end())
         filter.AppendWhere(PrepareSQL("season_view.idShow = %i", (int)option->second.asInteger()));
 
@@ -9580,7 +9762,7 @@ bool CVideoDatabase::GetFilter(CDbUrl &videoUrl, Filter &filter, SortDescription
     else if (itemType == "episodes")
     {
       int idShow = -1;
-      option = options.find("tvshowid");
+      auto option = options.find("tvshowid");
       if (option != options.end())
         idShow = (int)option->second.asInteger();
 
@@ -9643,7 +9825,7 @@ bool CVideoDatabase::GetFilter(CDbUrl &videoUrl, Filter &filter, SortDescription
     AppendIdLinkFilter("director", "actor", "musicvideo", "musicvideo", "idMVideo", options, filter);
     AppendLinkFilter("director", "actor", "musicvideo", "musicvideo", "idMVideo", options, filter);
 
-    option = options.find("year");
+    auto option = options.find("year");
     if (option != options.end())
       filter.AppendWhere(PrepareSQL("musicvideo_view.premiered like '%i%%'", (int)option->second.asInteger()));
 
@@ -9676,7 +9858,7 @@ bool CVideoDatabase::GetFilter(CDbUrl &videoUrl, Filter &filter, SortDescription
   else
     return false;
 
-  option = options.find("xsp");
+  auto option = options.find("xsp");
   if (option != options.end())
   {
     CSmartPlaylist xsp;
diff --git a/xbmc/video/VideoDatabase.h b/xbmc/video/VideoDatabase.h
index 3747886..56e878c 100644
--- a/xbmc/video/VideoDatabase.h
+++ b/xbmc/video/VideoDatabase.h
@@ -77,6 +77,7 @@ enum VideoDbDetails
   VideoDbDetailsStream   = 0x08,
   VideoDbDetailsCast     = 0x10,
   VideoDbDetailsBookmark = 0x20,
+  VideoDbDetailsUniqueID = 0x40,
   VideoDbDetailsAll      = 0xFF
 } ;
 
@@ -100,6 +101,8 @@ enum VideoDbDetails
 #define VIDEODB_DETAILS_MOVIE_RATING            VIDEODB_MAX_COLUMNS + 14
 #define VIDEODB_DETAILS_MOVIE_VOTES             VIDEODB_MAX_COLUMNS + 15
 #define VIDEODB_DETAILS_MOVIE_RATING_TYPE       VIDEODB_MAX_COLUMNS + 16
+#define VIDEODB_DETAILS_MOVIE_UNIQUEID_VALUE    VIDEODB_MAX_COLUMNS + 17
+#define VIDEODB_DETAILS_MOVIE_UNIQUEID_TYPE     VIDEODB_MAX_COLUMNS + 18
 
 #define VIDEODB_DETAILS_EPISODE_TVSHOW_ID       VIDEODB_MAX_COLUMNS + 2
 #define VIDEODB_DETAILS_EPISODE_USER_RATING     VIDEODB_MAX_COLUMNS + 3
@@ -119,6 +122,8 @@ enum VideoDbDetails
 #define VIDEODB_DETAILS_EPISODE_RATING          VIDEODB_MAX_COLUMNS + 17
 #define VIDEODB_DETAILS_EPISODE_VOTES           VIDEODB_MAX_COLUMNS + 18
 #define VIDEODB_DETAILS_EPISODE_RATING_TYPE     VIDEODB_MAX_COLUMNS + 19
+#define VIDEODB_DETAILS_EPISODE_UNIQUEID_VALUE  VIDEODB_MAX_COLUMNS + 20
+#define VIDEODB_DETAILS_EPISODE_UNIQUEID_TYPE   VIDEODB_MAX_COLUMNS + 21
 
 #define VIDEODB_DETAILS_TVSHOW_USER_RATING      VIDEODB_MAX_COLUMNS + 1
 #define VIDEODB_DETAILS_TVSHOW_DURATION         VIDEODB_MAX_COLUMNS + 2
@@ -132,6 +137,8 @@ enum VideoDbDetails
 #define VIDEODB_DETAILS_TVSHOW_RATING           VIDEODB_MAX_COLUMNS + 10
 #define VIDEODB_DETAILS_TVSHOW_VOTES            VIDEODB_MAX_COLUMNS + 11
 #define VIDEODB_DETAILS_TVSHOW_RATING_TYPE      VIDEODB_MAX_COLUMNS + 12
+#define VIDEODB_DETAILS_TVSHOW_UNIQUEID_VALUE   VIDEODB_MAX_COLUMNS + 13
+#define VIDEODB_DETAILS_TVSHOW_UNIQUEID_TYPE    VIDEODB_MAX_COLUMNS + 14
 
 #define VIDEODB_DETAILS_MUSICVIDEO_USER_RATING  VIDEODB_MAX_COLUMNS + 2
 #define VIDEODB_DETAILS_MUSICVIDEO_PREMIERED    VIDEODB_MAX_COLUMNS + 3
@@ -174,7 +181,7 @@ typedef enum // this enum MUST match the offset struct further down!! and make s
   VIDEODB_ID_CREDITS = 6,
   VIDEODB_ID_YEAR = 7, // unused
   VIDEODB_ID_THUMBURL = 8,
-  VIDEODB_ID_IDENT = 9,
+  VIDEODB_ID_IDENT_ID = 9,
   VIDEODB_ID_SORTTITLE = 10,
   VIDEODB_ID_RUNTIME = 11,
   VIDEODB_ID_MPAA = 12,
@@ -207,7 +214,7 @@ const struct SDbTableOffsets
   { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_writingCredits) },
   { VIDEODB_TYPE_UNUSED, 0 }, // unused
   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strPictureURL.m_xml) },
-  { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strIMDBNumber) },
+  { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iIdUniqueID) },
   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strSortTitle) },
   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_duration) },
   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strMPAARating) },
@@ -239,7 +246,7 @@ typedef enum // this enum MUST match the offset struct further down!! and make s
   VIDEODB_ID_TV_ORIGINALTITLE = 9,
   VIDEODB_ID_TV_EPISODEGUIDE = 10,
   VIDEODB_ID_TV_FANART = 11,
-  VIDEODB_ID_TV_IDENT = 12,
+  VIDEODB_ID_TV_IDENT_ID = 12,
   VIDEODB_ID_TV_MPAA = 13,
   VIDEODB_ID_TV_STUDIOS = 14,
   VIDEODB_ID_TV_SORTTITLE = 15,
@@ -260,7 +267,7 @@ const struct SDbTableOffsets DbTvShowOffsets[] =
   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strOriginalTitle)},
   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strEpisodeGuide)},
   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_fanart.m_xml)},
-  { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strIMDBNumber)},
+  { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iIdUniqueID)},
   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strMPAARating)},
   { VIDEODB_TYPE_STRINGARRAY, my_offsetof(CVideoInfoTag,m_studio)},
   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strSortTitle)},
@@ -302,7 +309,7 @@ typedef enum // this enum MUST match the offset struct further down!! and make s
   VIDEODB_ID_EPISODE_PLAYCOUNT = 8, // unused - feel free to repurpose
   VIDEODB_ID_EPISODE_RUNTIME = 9,
   VIDEODB_ID_EPISODE_DIRECTOR = 10,
-  VIDEODB_ID_EPISODE_IDENT = 11,
+  VIDEODB_ID_EPISODE_PRODUCTIONCODE = 11,
   VIDEODB_ID_EPISODE_SEASON = 12,
   VIDEODB_ID_EPISODE_EPISODE = 13,
   VIDEODB_ID_EPISODE_ORIGINALTITLE = 14,
@@ -311,7 +318,7 @@ typedef enum // this enum MUST match the offset struct further down!! and make s
   VIDEODB_ID_EPISODE_BOOKMARK = 17,
   VIDEODB_ID_EPISODE_BASEPATH = 18,
   VIDEODB_ID_EPISODE_PARENTPATHID = 19,
-  VIDEODB_ID_EPISODE_UNIQUEID = 20,
+  VIDEODB_ID_EPISODE_IDENT_ID = 20,
   VIDEODB_ID_EPISODE_MAX
 } VIDEODB_EPISODE_IDS;
 
@@ -337,7 +344,7 @@ const struct SDbTableOffsets DbEpisodeOffsets[] =
   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iBookmarkId) },
   { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_basePath) },
   { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_parentPathID) },
-  { VIDEODB_TYPE_STRING, my_offsetof(CVideoInfoTag,m_strUniqueId) }
+  { VIDEODB_TYPE_INT, my_offsetof(CVideoInfoTag,m_iIdUniqueID) }
 };
 
 typedef enum // this enum MUST match the offset struct further down!! and make sure to keep min and max at -1 and sizeof(offsets)
@@ -860,6 +867,8 @@ protected:
   int AddToTable(const std::string& table, const std::string& firstField, const std::string& secondField, const std::string& value);
   int UpdateRatings(int mediaId, const char *mediaType, const RatingMap& values, const std::string& defaultRating);
   int AddRatings(int mediaId, const char *mediaType, const RatingMap& values, const std::string& defaultRating);
+  int UpdateUniqueIDs(int mediaId, const char *mediaType, const CVideoInfoTag& details);
+  int AddUniqueIDs(int mediaId, const char *mediaType, const CVideoInfoTag& details);
   int AddActor(const std::string& strActor, const std::string& thumbURL, const std::string &thumb = "");
 
   int AddTvShow();
@@ -907,6 +916,7 @@ protected:
   void GetCast(int media_id, const std::string &media_type, std::vector<SActorInfo> &cast);
   void GetTags(int media_id, const std::string &media_type, std::vector<std::string> &tags);
   void GetRatings(int media_id, const std::string &media_type, RatingMap &ratings);
+  void GetUniqueIDs(int media_id, const std::string &media_type, CVideoInfoTag& details);
 
   void GetDetailsFromDB(std::unique_ptr<dbiplus::Dataset> &pDS, int min, int max, const SDbTableOffsets *offsets, CVideoInfoTag &details, int idxOffset = 2);
   void GetDetailsFromDB(const dbiplus::sql_record* const record, int min, int max, const SDbTableOffsets *offsets, CVideoInfoTag &details, int idxOffset = 2);
diff --git a/xbmc/video/VideoDbUrl.h b/xbmc/video/VideoDbUrl.h
index 5e6ee74..ef8861c 100644
--- a/xbmc/video/VideoDbUrl.h
+++ b/xbmc/video/VideoDbUrl.h
@@ -32,8 +32,8 @@ public:
   const std::string& GetItemType() const { return m_itemType; }
 
 protected:
-  virtual bool parse();
-  virtual bool validateOption(const std::string &key, const CVariant &value);
+  bool parse() override;
+  bool validateOption(const std::string &key, const CVariant &value) override;
 
 private:
   std::string m_itemType;
diff --git a/xbmc/video/VideoInfoTag.cpp b/xbmc/video/VideoInfoTag.cpp
index 79f9362..6274e4e 100644
--- a/xbmc/video/VideoInfoTag.cpp
+++ b/xbmc/video/VideoInfoTag.cpp
@@ -54,7 +54,6 @@ void CVideoInfoTag::Reset()
   m_tags.clear();
   m_strFile.clear();
   m_strPath.clear();
-  m_strIMDBNumber.clear();
   m_strMPAARating.clear();
   m_strFileNameAndPath.clear();
   m_premiered.Reset();
@@ -69,7 +68,8 @@ void CVideoInfoTag::Reset()
   m_iTop250 = 0;
   m_iSeason = -1;
   m_iEpisode = -1;
-  m_strUniqueId.clear();
+  m_uniqueIDs.clear();
+  m_strDefaultUniqueID = "unknown";
   m_iSpecialSortSeason = -1;
   m_iSpecialSortEpisode = -1;
   m_strDefaultRating = "default";
@@ -154,7 +154,6 @@ bool CVideoInfoTag::Save(TiXmlNode *node, const std::string &tag, bool savePathI
   {
     XMLUtils::SetInt(movie, "season", m_iSeason);
     XMLUtils::SetInt(movie, "episode", m_iEpisode);
-    XMLUtils::SetString(movie, "uniqueid", m_strUniqueId);
     XMLUtils::SetInt(movie, "displayseason",m_iSpecialSortSeason);
     XMLUtils::SetInt(movie, "displayepisode",m_iSpecialSortEpisode);
   }
@@ -204,7 +203,18 @@ bool CVideoInfoTag::Save(TiXmlNode *node, const std::string &tag, bool savePathI
       XMLUtils::SetString(movie, "episodeguide", m_strEpisodeGuide);
   }
 
-  XMLUtils::SetString(movie, "id", m_strIMDBNumber);
+  XMLUtils::SetString(movie, "id", GetUniqueID());
+  for (const auto& uniqueid : m_uniqueIDs)
+  {
+    TiXmlElement uniqueID("uniqueid");
+    uniqueID.SetAttribute("type", uniqueid.first);
+    if (uniqueid.first == m_strDefaultUniqueID)
+      uniqueID.SetAttribute("default", "true");
+    TiXmlText value(uniqueid.second);
+    uniqueID.InsertEndChild(value);
+
+    movie->InsertEndChild(uniqueID);
+  }
   XMLUtils::SetStringArray(movie, "genre", m_genre);
   XMLUtils::SetStringArray(movie, "country", m_country);
   if (!m_strSet.empty())
@@ -342,7 +352,6 @@ void CVideoInfoTag::Archive(CArchive& ar)
     ar << m_duration;
     ar << m_strFile;
     ar << m_strPath;
-    ar << m_strIMDBNumber;
     ar << m_strMPAARating;
     ar << m_strFileNameAndPath;
     ar << m_strOriginalTitle;
@@ -360,7 +369,13 @@ void CVideoInfoTag::Archive(CArchive& ar)
     ar << m_iTop250;
     ar << m_iSeason;
     ar << m_iEpisode;
-    ar << m_strUniqueId;
+    ar << (int)m_uniqueIDs.size();
+    for (const auto& i : m_uniqueIDs)
+    {
+      ar << i.first;
+      ar << (i.first == m_strDefaultUniqueID);
+      ar << i.second;
+    }
     ar << (int)m_ratings.size();
     for (const auto& i : m_ratings)
     {
@@ -434,7 +449,6 @@ void CVideoInfoTag::Archive(CArchive& ar)
     ar >> m_duration;
     ar >> m_strFile;
     ar >> m_strPath;
-    ar >> m_strIMDBNumber;
     ar >> m_strMPAARating;
     ar >> m_strFileNameAndPath;
     ar >> m_strOriginalTitle;
@@ -452,7 +466,20 @@ void CVideoInfoTag::Archive(CArchive& ar)
     ar >> m_iTop250;
     ar >> m_iSeason;
     ar >> m_iEpisode;
-    ar >> m_strUniqueId;
+    int iUniqueIDSize;
+    ar >> iUniqueIDSize;
+    for (int i = 0; i < iUniqueIDSize; ++i)
+    {
+      std::string value;
+      std::string name;
+      bool defaultUniqueID;
+      ar >> name;
+      ar >> defaultUniqueID;
+      ar >> value;
+      SetUniqueID(value, name);
+      if (defaultUniqueID)
+        m_strDefaultUniqueID = name;
+    }
     int iRatingSize;
     ar >> iRatingSize;
     for (int i = 0; i < iRatingSize; ++i)
@@ -535,7 +562,7 @@ void CVideoInfoTag::Serialize(CVariant& value) const
   value["runtime"] = GetDuration();
   value["file"] = m_strFile;
   value["path"] = m_strPath;
-  value["imdbnumber"] = m_strIMDBNumber;
+  value["imdbnumber"] = GetUniqueID();
   value["mpaa"] = m_strMPAARating;
   value["filenameandpath"] = m_strFileNameAndPath;
   value["originaltitle"] = m_strOriginalTitle;
@@ -554,7 +581,9 @@ void CVideoInfoTag::Serialize(CVariant& value) const
   value["year"] = m_premiered.GetYear();
   value["season"] = m_iSeason;
   value["episode"] = m_iEpisode;
-  value["uniqueid"]["unknown"] = m_strUniqueId;
+  for (const auto& i : m_uniqueIDs)
+    value["uniqueid"][i.first] = i.second;
+
   value["rating"] = GetRating().rating;
   CVariant ratings = CVariant(CVariant::VariantTypeObject);
   for (const auto& i : m_ratings)
@@ -708,6 +737,33 @@ const CDateTime& CVideoInfoTag::GetPremiered() const
   return m_premiered;
 }
 
+const std::string CVideoInfoTag::GetUniqueID(std::string type) const
+{
+  if (type.empty())
+    type = m_strDefaultUniqueID;
+
+  const auto& uniqueid = m_uniqueIDs.find(type);
+  if (uniqueid == m_uniqueIDs.end())
+    return "";
+
+  return uniqueid->second;
+}
+
+const std::map<std::string, std::string>& CVideoInfoTag::GetUniqueIDs() const
+{
+  return m_uniqueIDs;
+}
+
+const std::string& CVideoInfoTag::GetDefaultUniqueID() const
+{
+  return m_strDefaultUniqueID;
+}
+
+const bool CVideoInfoTag::HasUniqueID() const
+{
+  return !m_uniqueIDs.empty();
+}
+
 const std::string CVideoInfoTag::GetCast(bool bIncludeRole /*= false*/) const
 {
   std::string strLabel;
@@ -797,8 +853,6 @@ void CVideoInfoTag::ParseNative(const TiXmlElement* movie, bool prioritise)
   XMLUtils::GetInt(movie, "season", m_iSeason);
   XMLUtils::GetInt(movie, "episode", m_iEpisode);
   XMLUtils::GetInt(movie, "track", m_iTrack);
-  if (XMLUtils::GetString(movie, "uniqueid", value))
-    SetUniqueId(value);
 
   XMLUtils::GetInt(movie, "displayseason", m_iSpecialSortSeason);
   XMLUtils::GetInt(movie, "displayepisode", m_iSpecialSortEpisode);
@@ -836,7 +890,21 @@ void CVideoInfoTag::ParseNative(const TiXmlElement* movie, bool prioritise)
     SetPath(value);
 
   if (XMLUtils::GetString(movie, "id", value))
-    SetIMDBNumber(value);
+    SetUniqueID(value);
+
+  for (const TiXmlElement* uniqueid = movie->FirstChildElement("uniqueid"); uniqueid != nullptr; uniqueid = uniqueid->NextSiblingElement("uniqueid"))
+  {
+    if (uniqueid->FirstChild())
+    {
+    if (uniqueid->QueryStringAttribute("type", &value) == TIXML_SUCCESS)
+      SetUniqueID(uniqueid->FirstChild()->ValueStr(), value);
+    else
+      SetUniqueID(uniqueid->FirstChild()->ValueStr());
+    bool isDefault;
+    if ((uniqueid->QueryBoolAttribute("default", &isDefault) == TIXML_SUCCESS) && isDefault)
+      m_strDefaultUniqueID = value;
+    }
+  }
 
   if (XMLUtils::GetString(movie, "filenameandpath", value))
     SetFileNameAndPath(value);
@@ -1276,6 +1344,18 @@ void CVideoInfoTag::SetArtist(std::vector<std::string> artist)
   m_artist = Trim(std::move(artist));
 }
 
+void CVideoInfoTag::SetUniqueIDs(std::map<std::string, std::string> uniqueIDs)
+{
+  for (const auto& uniqueid : uniqueIDs)
+  {
+    if (uniqueid.first.empty())
+      uniqueIDs.erase(uniqueid.first);
+  }
+  if (uniqueIDs.find(m_strDefaultUniqueID) == uniqueIDs.end())
+    uniqueIDs[m_strDefaultUniqueID] = GetUniqueID();
+  m_uniqueIDs = std::move(uniqueIDs);
+}
+
 void CVideoInfoTag::SetSet(std::string set)
 {
   m_strSet = Trim(std::move(set));
@@ -1301,11 +1381,6 @@ void CVideoInfoTag::SetPath(std::string path)
   m_strPath = Trim(std::move(path));
 }
 
-void CVideoInfoTag::SetIMDBNumber(std::string imdbNumber)
-{
-  m_strIMDBNumber = Trim(std::move(imdbNumber));
-}
-
 void CVideoInfoTag::SetMPAARating(std::string mpaaRating)
 {
   m_strMPAARating = Trim(std::move(mpaaRating));
@@ -1356,9 +1431,24 @@ void CVideoInfoTag::SetShowLink(std::vector<std::string> showLink)
   m_showLink = Trim(std::move(showLink));
 }
 
-void CVideoInfoTag::SetUniqueId(std::string uniqueId)
+void CVideoInfoTag::SetUniqueID(const std::string& uniqueid, const std::string& type /* = "" */, bool isDefaultID /* = false */)
+{
+  if (type.empty())
+  {
+    m_uniqueIDs[m_strDefaultUniqueID] = uniqueid;
+  }
+  else
+  {
+    m_uniqueIDs[type] = uniqueid;
+    if (isDefaultID)
+      m_strDefaultUniqueID = type;
+  }
+}
+
+void CVideoInfoTag::RemoveUniqueID(const std::string& type)
 {
-  m_strUniqueId = Trim(std::move(uniqueId));
+  if (m_uniqueIDs.find(type) != m_uniqueIDs.end())
+    m_uniqueIDs.erase(type);
 }
 
 void CVideoInfoTag::SetNamedSeasons(std::map<int, std::string> namedSeasons)
diff --git a/xbmc/video/VideoInfoTag.h b/xbmc/video/VideoInfoTag.h
index e4ead34..ad4cce2 100644
--- a/xbmc/video/VideoInfoTag.h
+++ b/xbmc/video/VideoInfoTag.h
@@ -85,6 +85,10 @@ public:
   virtual void ToSortable(SortItem& sortable, Field field) const;
   const CRating GetRating(std::string type = "") const;
   const std::string& GetDefaultRating() const;
+  const std::string GetUniqueID(std::string type = "") const;
+  const std::map<std::string, std::string>& GetUniqueIDs() const;
+  const std::string& GetDefaultUniqueID() const;
+  const bool HasUniqueID() const;
   const bool HasYear() const;
   const int GetYear() const;
   const bool HasPremiered() const;
@@ -129,6 +133,7 @@ public:
   void RemoveRating(const std::string& type);
   void SetRatings(RatingMap ratings);
   void SetVotes(int votes, const std::string& type = "");
+  void SetUniqueIDs(std::map<std::string, std::string> uniqueIDs);
   void SetPremiered(CDateTime premiered);
   void SetPremieredFromDBDate(std::string premieredString);
   void SetYear(int year);
@@ -138,7 +143,6 @@ public:
   void SetTags(std::vector<std::string> tags);
   void SetFile(std::string file);
   void SetPath(std::string path);
-  void SetIMDBNumber(std::string imdbNumber);
   void SetMPAARating(std::string mpaaRating);
   void SetFileNameAndPath(std::string fileNameAndPath);
   void SetOriginalTitle(std::string originalTitle);
@@ -149,7 +153,8 @@ public:
   void SetStudio(std::vector<std::string> studio);
   void SetAlbum(std::string album);
   void SetShowLink(std::vector<std::string> showLink);
-  void SetUniqueId(std::string uniqueId);
+  void SetUniqueID(const std::string& uniqueid, const std::string& type = "", bool def = false);
+  void RemoveUniqueID(const std::string& type);
   void SetNamedSeasons(std::map<int, std::string> namedSeasons);
   void SetUserrating(int userrating);
 
@@ -175,7 +180,6 @@ public:
   std::vector<std::string> m_tags;
   std::string m_strFile;
   std::string m_strPath;
-  std::string m_strIMDBNumber;
   std::string m_strMPAARating;
   std::string m_strFileNameAndPath;
   std::string m_strOriginalTitle;
@@ -195,7 +199,7 @@ public:
   int m_iTop250;
   int m_iSeason;
   int m_iEpisode;
-  std::string m_strUniqueId;
+  int m_iIdUniqueID;
   int m_iDbId;
   int m_iFileId;
   int m_iSpecialSortSeason;
@@ -228,6 +232,8 @@ private:
   void ParseNative(const TiXmlElement* element, bool prioritise);
 
   std::string m_strDefaultRating;
+  std::string m_strDefaultUniqueID;
+  std::map<std::string, std::string> m_uniqueIDs;
   std::string Trim(std::string &&value);
   std::vector<std::string> Trim(std::vector<std::string> &&items);
 };
diff --git a/xbmc/video/dialogs/CMakeLists.txt b/xbmc/video/dialogs/CMakeLists.txt
index 38d6850..bbbb12f 100644
--- a/xbmc/video/dialogs/CMakeLists.txt
+++ b/xbmc/video/dialogs/CMakeLists.txt
@@ -1,4 +1,5 @@
 set(SOURCES GUIDialogAudioSubtitleSettings.cpp
+            GUIDialogCMSSettings.cpp
             GUIDialogFullScreenInfo.cpp
             GUIDialogSubtitles.cpp
             GUIDialogTeletext.cpp
@@ -8,6 +9,7 @@ set(SOURCES GUIDialogAudioSubtitleSettings.cpp
             GUIDialogVideoSettings.cpp)
 
 set(HEADERS GUIDialogAudioSubtitleSettings.h
+            GUIDialogCMSSettings.h
             GUIDialogFullScreenInfo.h
             GUIDialogSubtitles.h
             GUIDialogTeletext.h
@@ -17,9 +19,3 @@ set(HEADERS GUIDialogAudioSubtitleSettings.h
             GUIDialogVideoSettings.h)
 
 core_add_library(video_dialogs)
-
-add_dependencies(video_dialogs libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(video_dialogs ffmpeg)
-endif()
diff --git a/xbmc/video/dialogs/GUIDialogCMSSettings.cpp b/xbmc/video/dialogs/GUIDialogCMSSettings.cpp
new file mode 100644
index 0000000..64812c5
--- /dev/null
+++ b/xbmc/video/dialogs/GUIDialogCMSSettings.cpp
@@ -0,0 +1,248 @@
+/*
+ *      Copyright (C) 2005-2016 Team Kodi
+ *      http://kodi.tv
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Kodi; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "system.h"
+#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS)
+  #include "config.h"
+#endif
+
+#ifdef HAS_GL
+
+#include "cores/VideoPlayer/VideoRenderers/ColorManager.h"
+#include "FileItem.h"
+#include "GUIDialogCMSSettings.h"
+#include "GUIPassword.h"
+#include "addons/Skin.h"
+#include "cores/VideoPlayer/VideoRenderers/RenderManager.h"
+#include "dialogs/GUIDialogYesNo.h"
+#include "filesystem/Directory.h"
+#include "filesystem/File.h"
+#include "guilib/GUIWindowManager.h"
+#include "profiles/ProfilesManager.h"
+#include "settings/Settings.h"
+#include "settings/lib/Setting.h"
+#include "settings/lib/SettingsManager.h"
+#include "utils/log.h"
+#include "utils/URIUtils.h"
+#include "video/VideoDatabase.h"
+#include "utils/Variant.h"
+
+#include <vector>
+
+#define SETTING_VIDEO_CMSENABLE           "videoscreen.cmsenabled"
+#define SETTING_VIDEO_CMSMODE             "videoscreen.cmsmode"
+#define SETTING_VIDEO_CMS3DLUT            "videoscreen.cms3dlut"
+#define SETTING_VIDEO_CMSWHITEPOINT       "videoscreen.cmswhitepoint"
+#define SETTING_VIDEO_CMSPRIMARIES        "videoscreen.cmsprimaries"
+#define SETTING_VIDEO_CMSGAMMAMODE        "videoscreen.cmsgammamode"
+#define SETTING_VIDEO_CMSGAMMA            "videoscreen.cmsgamma"
+#define SETTING_VIDEO_CMSLUTSIZE          "videoscreen.cmslutsize"
+
+CGUIDialogCMSSettings::CGUIDialogCMSSettings()
+    : CGUIDialogSettingsManualBase(WINDOW_DIALOG_CMS_OSD_SETTINGS, "DialogSettings.xml")
+{ }
+
+CGUIDialogCMSSettings::~CGUIDialogCMSSettings()
+{ }
+
+void CGUIDialogCMSSettings::SetupView()
+{
+  CGUIDialogSettingsManualBase::SetupView();
+
+  SetHeading(36560);
+  SET_CONTROL_HIDDEN(CONTROL_SETTINGS_OKAY_BUTTON);
+  SET_CONTROL_HIDDEN(CONTROL_SETTINGS_CUSTOM_BUTTON);
+  SET_CONTROL_LABEL(CONTROL_SETTINGS_CANCEL_BUTTON, 15067);
+}
+
+void CGUIDialogCMSSettings::InitializeSettings()
+{
+  CGUIDialogSettingsManualBase::InitializeSettings();
+
+  CSettingCategory *category = AddCategory("cms", -1);
+  if (category == NULL)
+  {
+    CLog::Log(LOGERROR, "CGUIDialogCMSSettings: unable to setup settings");
+    return;
+  }
+
+  // get all necessary setting groups
+  CSettingGroup *groupColorManagement = AddGroup(category);
+  if (groupColorManagement == NULL)
+  {
+    CLog::Log(LOGERROR, "CGUIDialogCMSSettings: unable to setup settings");
+    return;
+  }
+
+  bool usePopup = g_SkinInfo->HasSkinFile("DialogSlider.xml");
+
+  StaticIntegerSettingOptions entries;
+
+  // create "depsCmsEnabled" for settings depending on CMS being enabled
+  CSettingDependency dependencyCmsEnabled(SettingDependencyTypeEnable, m_settingsManager);
+  dependencyCmsEnabled.Or()
+    ->Add(CSettingDependencyConditionPtr(new CSettingDependencyCondition(SETTING_VIDEO_CMSENABLE, "true", SettingDependencyOperatorEquals, false, m_settingsManager)));
+  SettingDependencies depsCmsEnabled;
+  depsCmsEnabled.push_back(dependencyCmsEnabled);
+
+  // create "depsCms3dlut" for 3dlut settings
+  CSettingDependency dependencyCms3dlut(SettingDependencyTypeVisible, m_settingsManager);
+  dependencyCms3dlut.And()
+    ->Add(CSettingDependencyConditionPtr(new CSettingDependencyCondition(SETTING_VIDEO_CMSMODE, std::to_string(CMS_MODE_3DLUT), SettingDependencyOperatorEquals, false, m_settingsManager)));
+  SettingDependencies depsCms3dlut;
+  depsCms3dlut.push_back(dependencyCmsEnabled);
+  depsCms3dlut.push_back(dependencyCms3dlut);
+
+  // create "depsCmsIcc" for display settings with icc profile
+  CSettingDependency dependencyCmsIcc(SettingDependencyTypeVisible, m_settingsManager);
+  dependencyCmsIcc.And()
+    ->Add(CSettingDependencyConditionPtr(new CSettingDependencyCondition(SETTING_VIDEO_CMSMODE, std::to_string(CMS_MODE_PROFILE), SettingDependencyOperatorEquals, false, m_settingsManager)));
+  SettingDependencies depsCmsIcc;
+  depsCmsIcc.push_back(dependencyCmsEnabled);
+  depsCmsIcc.push_back(dependencyCmsIcc);
+
+  // create "depsCmsGamma" for effective gamma adjustment (not available with bt.1886)
+  CSettingDependency dependencyCmsGamma(SettingDependencyTypeVisible, m_settingsManager);
+  dependencyCmsGamma.And()
+    ->Add(CSettingDependencyConditionPtr(new CSettingDependencyCondition(SETTING_VIDEO_CMSGAMMAMODE, std::to_string(CMS_TRC_BT1886), SettingDependencyOperatorEquals, true, m_settingsManager)));
+  SettingDependencies depsCmsGamma;
+  depsCmsGamma.push_back(dependencyCmsEnabled);
+  depsCmsGamma.push_back(dependencyCmsIcc);
+  depsCmsGamma.push_back(dependencyCmsGamma);
+
+  // color management settings
+  AddToggle(groupColorManagement, SETTING_VIDEO_CMSENABLE, 36560, 0, CSettings::GetInstance().GetBool(SETTING_VIDEO_CMSENABLE));
+
+  int currentMode = CSettings::GetInstance().GetInt(SETTING_VIDEO_CMSMODE);
+  entries.clear();
+  // entries.push_back(std::make_pair(16039, CMS_MODE_OFF)); // FIXME: get from CMS class
+  entries.push_back(std::make_pair(36580, CMS_MODE_3DLUT));
+#ifdef HAVE_LCMS2
+  entries.push_back(std::make_pair(36581, CMS_MODE_PROFILE));
+#endif
+  CSettingInt *settingCmsMode = AddSpinner(groupColorManagement, SETTING_VIDEO_CMSMODE, 36562, 0, currentMode, entries);
+  settingCmsMode->SetDependencies(depsCmsEnabled);
+
+  std::string current3dLUT = CSettings::GetInstance().GetString(SETTING_VIDEO_CMS3DLUT);
+  CSettingString *settingCms3dlut = AddList(groupColorManagement, SETTING_VIDEO_CMS3DLUT, 36564, 0, current3dLUT, Cms3dLutsFiller, 36564);
+  settingCms3dlut->SetDependencies(depsCms3dlut);
+
+  // display settings
+  int currentWhitepoint = CSettings::GetInstance().GetInt(SETTING_VIDEO_CMSWHITEPOINT);
+  entries.clear();
+  entries.push_back(std::make_pair(36586, CMS_WHITEPOINT_D65));
+  entries.push_back(std::make_pair(36587, CMS_WHITEPOINT_D93));
+  CSettingInt *settingCmsWhitepoint = AddSpinner(groupColorManagement, SETTING_VIDEO_CMSWHITEPOINT, 36568, 0, currentWhitepoint, entries);
+  settingCmsWhitepoint->SetDependencies(depsCmsIcc);
+
+  int currentPrimaries = CSettings::GetInstance().GetInt(SETTING_VIDEO_CMSPRIMARIES);
+  entries.clear();
+  entries.push_back(std::make_pair(36588, CMS_PRIMARIES_AUTO));
+  entries.push_back(std::make_pair(36589, CMS_PRIMARIES_BT709));
+  entries.push_back(std::make_pair(36590, CMS_PRIMARIES_170M));
+  entries.push_back(std::make_pair(36591, CMS_PRIMARIES_BT470M));
+  entries.push_back(std::make_pair(36592, CMS_PRIMARIES_BT470BG));
+  entries.push_back(std::make_pair(36593, CMS_PRIMARIES_240M));
+  CSettingInt *settingCmsPrimaries = AddSpinner(groupColorManagement, SETTING_VIDEO_CMSPRIMARIES, 36570, 0, currentPrimaries, entries);
+  settingCmsPrimaries->SetDependencies(depsCmsIcc);
+
+  int currentGammaMode = CSettings::GetInstance().GetInt(SETTING_VIDEO_CMSGAMMAMODE);
+  entries.clear();
+  entries.push_back(std::make_pair(36582, CMS_TRC_BT1886));
+  entries.push_back(std::make_pair(36583, CMS_TRC_INPUT_OFFSET));
+  entries.push_back(std::make_pair(36584, CMS_TRC_OUTPUT_OFFSET));
+  entries.push_back(std::make_pair(36585, CMS_TRC_ABSOLUTE));
+  CSettingInt *settingCmsGammaMode = AddSpinner(groupColorManagement, SETTING_VIDEO_CMSGAMMAMODE, 36572, 0, currentGammaMode, entries);
+  settingCmsGammaMode->SetDependencies(depsCmsIcc);
+
+  float currentGamma = CSettings::GetInstance().GetInt(SETTING_VIDEO_CMSGAMMA)/100.0f;
+  if (currentGamma == 0.0) currentGamma = 2.20;
+  CSettingNumber *settingCmsGamma = AddSlider(groupColorManagement, SETTING_VIDEO_CMSGAMMA, 36574, 0, currentGamma, 36597, 1.6, 0.05, 2.8, 36574, usePopup);
+  settingCmsGamma->SetDependencies(depsCmsGamma);
+
+  int currentLutSize = CSettings::GetInstance().GetInt(SETTING_VIDEO_CMSLUTSIZE);
+  entries.clear();
+  entries.push_back(std::make_pair(36594, 4));
+  entries.push_back(std::make_pair(36595, 6));
+  entries.push_back(std::make_pair(36596, 8));
+  CSettingInt *settingCmsLutSize = AddSpinner(groupColorManagement, SETTING_VIDEO_CMSLUTSIZE, 36576, 0, currentLutSize, entries);
+  settingCmsLutSize->SetDependencies(depsCmsIcc);
+}
+
+void CGUIDialogCMSSettings::OnSettingChanged(const CSetting *setting)
+{
+  if (setting == NULL)
+    return;
+
+  CGUIDialogSettingsManualBase::OnSettingChanged(setting);
+
+  const std::string &settingId = setting->GetId();
+  if (settingId == SETTING_VIDEO_CMSENABLE)
+    CSettings::GetInstance().SetBool(SETTING_VIDEO_CMSENABLE, (static_cast<const CSettingBool*>(setting)->GetValue()));
+  else if (settingId == SETTING_VIDEO_CMSMODE)
+    CSettings::GetInstance().SetInt(SETTING_VIDEO_CMSMODE, static_cast<int>(static_cast<const CSettingInt*>(setting)->GetValue()));
+  else if (settingId == SETTING_VIDEO_CMS3DLUT)
+    CSettings::GetInstance().SetString(SETTING_VIDEO_CMS3DLUT, static_cast<std::string>(static_cast<const CSettingString*>(setting)->GetValue()));
+  else if (settingId == SETTING_VIDEO_CMSWHITEPOINT)
+    CSettings::GetInstance().SetInt(SETTING_VIDEO_CMSWHITEPOINT, static_cast<int>(static_cast<const CSettingInt*>(setting)->GetValue()));
+  else if (settingId == SETTING_VIDEO_CMSPRIMARIES)
+    CSettings::GetInstance().SetInt(SETTING_VIDEO_CMSPRIMARIES, static_cast<int>(static_cast<const CSettingInt*>(setting)->GetValue()));
+  else if (settingId == SETTING_VIDEO_CMSGAMMAMODE)
+    CSettings::GetInstance().SetInt(SETTING_VIDEO_CMSGAMMAMODE, static_cast<int>(static_cast<const CSettingInt*>(setting)->GetValue()));
+  else if (settingId == SETTING_VIDEO_CMSGAMMA)
+    CSettings::GetInstance().SetInt(SETTING_VIDEO_CMSGAMMA, static_cast<float>(static_cast<const CSettingNumber*>(setting)->GetValue())*100);
+  else if (settingId == SETTING_VIDEO_CMSLUTSIZE)
+    CSettings::GetInstance().SetInt(SETTING_VIDEO_CMSLUTSIZE, static_cast<int>(static_cast<const CSettingInt*>(setting)->GetValue()));
+}
+
+bool CGUIDialogCMSSettings::OnBack(int actionID)
+{
+  Save();
+  return CGUIDialogSettingsBase::OnBack(actionID);
+}
+
+void CGUIDialogCMSSettings::Save()
+{
+  CLog::Log(LOGINFO, "CGUIDialogCMSSettings: Save() called");
+  CSettings::GetInstance().Save();
+}
+
+void CGUIDialogCMSSettings::Cms3dLutsFiller(
+    const CSetting *setting,
+    std::vector< std::pair<std::string, std::string> > &list,
+    std::string &current,
+    void *data)
+{
+  // get 3dLut directory from settings
+  CFileItemList items;
+
+  // list .3dlut files
+  std::string current3dlut = CSettings::GetInstance().GetString(SETTING_VIDEO_CMS3DLUT);
+  if (!current3dlut.empty())
+    current3dlut = URIUtils::GetDirectory(current3dlut);
+  XFILE::CDirectory::GetDirectory(current3dlut, items, ".3dlut");
+
+  for (int i = 0; i < items.Size(); i++)
+  {
+    list.push_back(make_pair(items[i]->GetLabel(), items[i]->GetPath()));
+  }
+}
+
+#endif //HAS_GL
diff --git a/xbmc/video/dialogs/GUIDialogCMSSettings.h b/xbmc/video/dialogs/GUIDialogCMSSettings.h
new file mode 100644
index 0000000..ebd6c6e
--- /dev/null
+++ b/xbmc/video/dialogs/GUIDialogCMSSettings.h
@@ -0,0 +1,51 @@
+#pragma once
+
+/*
+ *      Copyright (C) 2005-2014 Team XBMC
+ *      http://xbmc.org
+ *
+ *  This Program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This Program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "settings/dialogs/GUIDialogSettingsManualBase.h"
+
+class CGUIDialogCMSSettings : public CGUIDialogSettingsManualBase
+{
+public:
+  CGUIDialogCMSSettings();
+  virtual ~CGUIDialogCMSSettings();
+
+protected:
+  // implementations of ISettingCallback
+  virtual void OnSettingChanged(const CSetting *setting) override;
+
+  // specialization of CGUIDialogSettingsBase
+  virtual bool AllowResettingSettings() const override { return false; }
+  virtual bool OnBack(int actionID) override;
+  virtual void Save() override;
+  virtual void SetupView() override;
+
+  // specialization of CGUIDialogSettingsManualBase
+  virtual void InitializeSettings() override;
+
+private:
+  bool m_viewModeChanged;
+  static void Cms3dLutsFiller(
+    const CSetting *setting,
+    std::vector< std::pair<std::string, std::string> > &list,
+    std::string &current,
+    void *data);
+};
diff --git a/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp b/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp
index 53ffdfb..464ccc6 100644
--- a/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp
+++ b/xbmc/video/dialogs/GUIDialogVideoBookmarks.cpp
@@ -435,9 +435,8 @@ bool CGUIDialogVideoBookmarks::AddBookmark(CVideoInfoTag* tag)
   if (hasImage)
   {
 
-    Crc32 crc;
-    crc.ComputeFromLowerCase(g_application.CurrentFile());
-    bookmark.thumbNailImage = StringUtils::Format("%08x_%i.jpg", (unsigned __int32) crc, (int)bookmark.timeInSeconds);
+    auto crc = Crc32::ComputeFromLowerCase(g_application.CurrentFile());
+    bookmark.thumbNailImage = StringUtils::Format("%08x_%i.jpg", crc, (int)bookmark.timeInSeconds);
     bookmark.thumbNailImage = URIUtils::AddFileToFolder(CProfilesManager::GetInstance().GetBookmarksThumbFolder(), bookmark.thumbNailImage);
 
 
diff --git a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp
index fdf4a50..061242a 100644
--- a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp
+++ b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp
@@ -229,14 +229,14 @@ void CGUIDialogVideoInfo::OnInitWindow()
   m_hasUpdatedUserrating = false;
   m_bViewReview = true;
 
-  CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_REFRESH, (CProfilesManager::GetInstance().GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser) && !StringUtils::StartsWithNoCase(m_movieItem->GetVideoInfoTag()->m_strIMDBNumber, "xx"));
-  CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_GET_THUMB, (CProfilesManager::GetInstance().GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser) && !StringUtils::StartsWithNoCase(m_movieItem->GetVideoInfoTag()->m_strIMDBNumber.c_str() + 2, "plugin"));
+  CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_REFRESH, (CProfilesManager::GetInstance().GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser) && !StringUtils::StartsWithNoCase(m_movieItem->GetVideoInfoTag()->GetUniqueID(), "xx"));
+  CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_GET_THUMB, (CProfilesManager::GetInstance().GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser) && !StringUtils::StartsWithNoCase(m_movieItem->GetVideoInfoTag()->GetUniqueID().c_str() + 2, "plugin"));
   // Disable video user rating button for plugins as they don't have tables to save this
   CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_USERRATING, !m_movieItem->IsPlugin());
 
   VIDEODB_CONTENT_TYPE type = (VIDEODB_CONTENT_TYPE)m_movieItem->GetVideoContentType();
   if (type == VIDEODB_CONTENT_TVSHOWS || type == VIDEODB_CONTENT_MOVIES)
-    CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_GET_FANART, (CProfilesManager::GetInstance().GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser) && !StringUtils::StartsWithNoCase(m_movieItem->GetVideoInfoTag()->m_strIMDBNumber.c_str() + 2, "plugin"));
+    CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_GET_FANART, (CProfilesManager::GetInstance().GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser) && !StringUtils::StartsWithNoCase(m_movieItem->GetVideoInfoTag()->GetUniqueID().c_str() + 2, "plugin"));
   else
     CONTROL_DISABLE(CONTROL_BTN_GET_FANART);
 
diff --git a/xbmc/video/dialogs/GUIDialogVideoOSD.cpp b/xbmc/video/dialogs/GUIDialogVideoOSD.cpp
index c1e99cf..e498e1f 100644
--- a/xbmc/video/dialogs/GUIDialogVideoOSD.cpp
+++ b/xbmc/video/dialogs/GUIDialogVideoOSD.cpp
@@ -46,6 +46,7 @@ void CGUIDialogVideoOSD::FrameMove()
                            || g_windowManager.IsWindowActive(WINDOW_DIALOG_AUDIO_OSD_SETTINGS)
                            || g_windowManager.IsWindowActive(WINDOW_DIALOG_AUDIO_DSP_OSD_SETTINGS)
                            || g_windowManager.IsWindowActive(WINDOW_DIALOG_VIDEO_OSD_SETTINGS)
+                           || g_windowManager.IsWindowActive(WINDOW_DIALOG_CMS_OSD_SETTINGS)
                            || g_windowManager.IsWindowActive(WINDOW_DIALOG_VIDEO_BOOKMARKS)
                            || g_windowManager.IsWindowActive(WINDOW_DIALOG_PVR_OSD_CHANNELS)
                            || g_windowManager.IsWindowActive(WINDOW_DIALOG_PVR_OSD_GUIDE)
diff --git a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
index afbe203..f9bc12d 100644
--- a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+++ b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
@@ -52,7 +52,6 @@
 #define SETTING_VIDEO_VDPAU_NOISE         "vdpau.noise"
 #define SETTING_VIDEO_VDPAU_SHARPNESS     "vdpau.sharpness"
 
-#define SETTING_VIDEO_DEINTERLACEMODE     "video.deinterlacemode"
 #define SETTING_VIDEO_INTERLACEMETHOD     "video.interlacemethod"
 #define SETTING_VIDEO_SCALINGMETHOD       "video.scalingmethod"
 
@@ -81,9 +80,7 @@ void CGUIDialogVideoSettings::OnSettingChanged(const CSetting *setting)
   CVideoSettings &videoSettings = CMediaSettings::GetInstance().GetCurrentVideoSettings();
 
   const std::string &settingId = setting->GetId();
-  if (settingId == SETTING_VIDEO_DEINTERLACEMODE)
-    videoSettings.m_DeinterlaceMode = static_cast<EDEINTERLACEMODE>(static_cast<const CSettingInt*>(setting)->GetValue());
-  else if (settingId == SETTING_VIDEO_INTERLACEMETHOD)
+  if (settingId == SETTING_VIDEO_INTERLACEMETHOD)
     videoSettings.m_InterlaceMethod = static_cast<EINTERLACEMETHOD>(static_cast<const CSettingInt*>(setting)->GetValue());
   else if (settingId == SETTING_VIDEO_SCALINGMETHOD)
     videoSettings.m_ScalingMethod = static_cast<ESCALINGMETHOD>(static_cast<const CSettingInt*>(setting)->GetValue());
@@ -255,16 +252,9 @@ void CGUIDialogVideoSettings::InitializeSettings()
   CVideoSettings &videoSettings = CMediaSettings::GetInstance().GetCurrentVideoSettings();
   
   StaticIntegerSettingOptions entries;
-  if (g_application.m_pPlayer->Supports(VS_DEINTERLACEMODE_OFF))
-    entries.push_back(std::make_pair(16039, VS_DEINTERLACEMODE_OFF));
-  if (g_application.m_pPlayer->Supports(VS_DEINTERLACEMODE_AUTO))
-    entries.push_back(std::make_pair(16040, VS_DEINTERLACEMODE_AUTO));
-  if (g_application.m_pPlayer->Supports(VS_DEINTERLACEMODE_FORCE))
-    entries.push_back(std::make_pair(16041, VS_DEINTERLACEMODE_FORCE));
-  if (!entries.empty())
-    AddSpinner(groupVideo, SETTING_VIDEO_DEINTERLACEMODE, 16037, 0, static_cast<int>(videoSettings.m_DeinterlaceMode), entries);
 
   entries.clear();
+  entries.push_back(std::make_pair(16039, VS_INTERLACEMETHOD_NONE));
   entries.push_back(std::make_pair(16019, VS_INTERLACEMETHOD_AUTO));
   entries.push_back(std::make_pair(20131, VS_INTERLACEMETHOD_RENDER_BLEND));
   entries.push_back(std::make_pair(20130, VS_INTERLACEMETHOD_RENDER_WEAVE_INVERTED));
@@ -302,14 +292,7 @@ void CGUIDialogVideoSettings::InitializeSettings()
 
   if (!entries.empty())
   {
-    CSettingInt *settingInterlaceMethod = AddSpinner(groupVideo, SETTING_VIDEO_INTERLACEMETHOD, 16038, 0, static_cast<int>(videoSettings.m_InterlaceMethod), entries);
-
-    CSettingDependency dependencyDeinterlaceModeOff(SettingDependencyTypeEnable, m_settingsManager);
-    dependencyDeinterlaceModeOff.And()
-      ->Add(CSettingDependencyConditionPtr(new CSettingDependencyCondition(SETTING_VIDEO_DEINTERLACEMODE, "0", SettingDependencyOperatorEquals, true, m_settingsManager)));
-    SettingDependencies depsDeinterlaceModeOff;
-    depsDeinterlaceModeOff.push_back(dependencyDeinterlaceModeOff);
-    settingInterlaceMethod->SetDependencies(depsDeinterlaceModeOff);
+    AddSpinner(groupVideo, SETTING_VIDEO_INTERLACEMETHOD, 16038, 0, static_cast<int>(videoSettings.m_InterlaceMethod), entries);
   }
 
   entries.clear();
diff --git a/xbmc/video/dialogs/Makefile b/xbmc/video/dialogs/Makefile
index 0480a6d..fd27b66 100644
--- a/xbmc/video/dialogs/Makefile
+++ b/xbmc/video/dialogs/Makefile
@@ -1,4 +1,5 @@
 SRCS=GUIDialogAudioSubtitleSettings.cpp \
+     GUIDialogCMSSettings.cpp \
      GUIDialogFullScreenInfo.cpp \
      GUIDialogSubtitles.cpp \
      GUIDialogTeletext.cpp \
diff --git a/xbmc/video/videosync/CMakeLists.txt b/xbmc/video/videosync/CMakeLists.txt
index 0dcfab5..f2a9448 100644
--- a/xbmc/video/videosync/CMakeLists.txt
+++ b/xbmc/video/videosync/CMakeLists.txt
@@ -38,6 +38,6 @@ endif()
 if(SOURCES AND HEADERS)
   core_add_library(video_sync)
   if(CORE_SYSTEM_NAME STREQUAL windows)
-    add_dependencies(video_sync d3dx11effects)
+    add_dependencies(${CORE_LIBRARY} d3dx11effects)
   endif()
 endif()
diff --git a/xbmc/video/videosync/VideoSync.h b/xbmc/video/videosync/VideoSync.h
index a4dc688..a430cb0 100644
--- a/xbmc/video/videosync/VideoSync.h
+++ b/xbmc/video/videosync/VideoSync.h
@@ -18,6 +18,7 @@
  *  <http://www.gnu.org/licenses/>.
  *
  */
+#include <atomic>
 
 class CVideoReferenceClock;
 typedef void (*PUPDATECLOCK)(int NrVBlanks, uint64_t time, CVideoReferenceClock *clock);
@@ -28,7 +29,7 @@ public:
   CVideoSync(CVideoReferenceClock *clock) { m_refClock = clock; };
   virtual ~CVideoSync() {};
   virtual bool Setup(PUPDATECLOCK func) = 0;
-  virtual void Run(volatile bool& stop) = 0;
+  virtual void Run(std::atomic<bool>& stop) = 0;
   virtual void Cleanup() = 0;
   virtual float GetFps() = 0;
   virtual void RefreshChanged() {};
diff --git a/xbmc/video/videosync/VideoSyncAndroid.cpp b/xbmc/video/videosync/VideoSyncAndroid.cpp
index 6018910..71d7906 100644
--- a/xbmc/video/videosync/VideoSyncAndroid.cpp
+++ b/xbmc/video/videosync/VideoSyncAndroid.cpp
@@ -47,7 +47,7 @@ bool CVideoSyncAndroid::Setup(PUPDATECLOCK func)
   return true;
 }
 
-void CVideoSyncAndroid::Run(volatile bool& stop)
+void CVideoSyncAndroid::Run(std::atomic<bool>& stop)
 {
   while(!stop && !m_abort)
   {
@@ -69,7 +69,7 @@ float CVideoSyncAndroid::GetFps()
   return m_fps;
 }
 
-void CVideoSyncAndroid::OnResetDevice()
+void CVideoSyncAndroid::OnResetDisplay()
 {
   m_abort = true;
 }
diff --git a/xbmc/video/videosync/VideoSyncAndroid.h b/xbmc/video/videosync/VideoSyncAndroid.h
index 52d337a..803df56 100644
--- a/xbmc/video/videosync/VideoSyncAndroid.h
+++ b/xbmc/video/videosync/VideoSyncAndroid.h
@@ -30,12 +30,12 @@ public:
   
   // CVideoSync interface
   virtual bool Setup(PUPDATECLOCK func);
-  virtual void Run(volatile bool& stop);
+  virtual void Run(std::atomic<bool>& stop);
   virtual void Cleanup();
   virtual float GetFps();
   
   // IDispResource interface
-  virtual void OnResetDevice();
+  virtual void OnResetDisplay();
 
   // Choreographer callback
   void FrameCallback(int64_t frameTimeNanos);
diff --git a/xbmc/video/videosync/VideoSyncD3D.cpp b/xbmc/video/videosync/VideoSyncD3D.cpp
index 8c0ef1f..e48b91e 100644
--- a/xbmc/video/videosync/VideoSyncD3D.cpp
+++ b/xbmc/video/videosync/VideoSyncD3D.cpp
@@ -28,10 +28,10 @@
 #include "windowing\WindowingFactory.h"
 #include "video/videosync/VideoSyncD3D.h"
 #include "guilib/GraphicContext.h"
-#include "win32/dxerr.h"
+#include "platform/win32/dxerr.h"
 #include "utils/StringUtils.h"
 
-void CVideoSyncD3D::OnDestroyDevice()
+void CVideoSyncD3D::OnLostDisplay()
 {
   if (!m_displayLost)
   {
@@ -40,7 +40,7 @@ void CVideoSyncD3D::OnDestroyDevice()
   }
 }
 
-void CVideoSyncD3D::OnResetDevice()
+void CVideoSyncD3D::OnResetDisplay()
 {
   m_displayReset = true;
 }
@@ -67,7 +67,7 @@ bool CVideoSyncD3D::Setup(PUPDATECLOCK func)
   return true;
 }
 
-void CVideoSyncD3D::Run(volatile bool& stop)
+void CVideoSyncD3D::Run(std::atomic<bool>& stop)
 {
   int64_t Now;
   int64_t LastVBlankTime;
@@ -97,15 +97,16 @@ void CVideoSyncD3D::Run(volatile bool& stop)
 
     if ((Now - m_lastUpdateTime) >= systemFrequency)
     {
-      if (m_fps != GetFps())
+      float fps = m_fps;
+      if (fps != GetFps())
         break;
     }
 
     // because we had a vblank, sleep until half the refreshrate period because i think WaitForVBlank block any rendering stuf
     // without sleeping we have freeze rendering
     int SleepTime = (int)((LastVBlankTime + (systemFrequency / MathUtils::round_int(m_fps) / 2) - Now) * 1000 / systemFrequency);
-    if (SleepTime > 100)
-      SleepTime = 100; //failsafe
+    if (SleepTime > 50)
+      SleepTime = 50; //failsafe
     if (SleepTime > 0)
       ::Sleep(SleepTime);
   }
diff --git a/xbmc/video/videosync/VideoSyncD3D.h b/xbmc/video/videosync/VideoSyncD3D.h
index a2e58a9..486b620 100644
--- a/xbmc/video/videosync/VideoSyncD3D.h
+++ b/xbmc/video/videosync/VideoSyncD3D.h
@@ -22,22 +22,22 @@
 #if defined(TARGET_WINDOWS)
 
 #include "video/videosync/VideoSync.h"
-#include "guilib/D3DResource.h"
+#include "guilib/DispResource.h"
 #include "threads/Event.h"
 
-class CVideoSyncD3D : public CVideoSync, ID3DResource
+class CVideoSyncD3D : public CVideoSync, IDispResource
 {
 public:
   CVideoSyncD3D(CVideoReferenceClock *clock) : CVideoSync(clock) {};
-  virtual bool Setup(PUPDATECLOCK func);
-  virtual void Run(volatile bool& stop);
-  virtual void Cleanup();
-  virtual float GetFps();
-  virtual void RefreshChanged();
+  bool Setup(PUPDATECLOCK func) override;
+  void Run(std::atomic<bool>& stop) override;
+  void Cleanup() override;
+  float GetFps() override;
+  void RefreshChanged() override;
+  // IDispResource overrides
+  void OnLostDisplay() override;
+  void OnResetDisplay() override;
 
-  virtual void OnCreateDevice() {}
-  virtual void OnDestroyDevice();
-  virtual void OnResetDevice();
 private:
   static std::string GetErrorDescription(HRESULT hr);
 
diff --git a/xbmc/video/videosync/VideoSyncDRM.cpp b/xbmc/video/videosync/VideoSyncDRM.cpp
index c9955e6..c86a7b7 100644
--- a/xbmc/video/videosync/VideoSyncDRM.cpp
+++ b/xbmc/video/videosync/VideoSyncDRM.cpp
@@ -78,7 +78,7 @@ bool CVideoSyncDRM::Setup(PUPDATECLOCK func)
   return true;
 }
 
-void CVideoSyncDRM::Run(volatile bool& stop)
+void CVideoSyncDRM::Run(std::atomic<bool>& stop)
 {
   drmVBlank vbl;
   VblInfo info;
diff --git a/xbmc/video/videosync/VideoSyncDRM.h b/xbmc/video/videosync/VideoSyncDRM.h
index 040c4f3..b680717 100644
--- a/xbmc/video/videosync/VideoSyncDRM.h
+++ b/xbmc/video/videosync/VideoSyncDRM.h
@@ -29,7 +29,7 @@ class CVideoSyncDRM : public CVideoSync, IDispResource
 public:
   CVideoSyncDRM(CVideoReferenceClock *clock) : CVideoSync(clock) {};
   virtual bool Setup(PUPDATECLOCK func);
-  virtual void Run(volatile bool& stop);
+  virtual void Run(std::atomic<bool>& stop);
   virtual void Cleanup();
   virtual float GetFps();
   virtual void OnResetDisplay();
diff --git a/xbmc/video/videosync/VideoSyncGLX.cpp b/xbmc/video/videosync/VideoSyncGLX.cpp
index d35108a..fd28e00 100644
--- a/xbmc/video/videosync/VideoSyncGLX.cpp
+++ b/xbmc/video/videosync/VideoSyncGLX.cpp
@@ -183,7 +183,7 @@ bool CVideoSyncGLX::Setup(PUPDATECLOCK func)
   return true;
 }
 
-void CVideoSyncGLX::Run(volatile bool& stop)
+void CVideoSyncGLX::Run(std::atomic<bool>& stop)
 {
   unsigned int  PrevVblankCount;
   unsigned int  VblankCount;
diff --git a/xbmc/video/videosync/VideoSyncGLX.h b/xbmc/video/videosync/VideoSyncGLX.h
index c3c3809..7d23c47 100644
--- a/xbmc/video/videosync/VideoSyncGLX.h
+++ b/xbmc/video/videosync/VideoSyncGLX.h
@@ -34,7 +34,7 @@ class CVideoSyncGLX : public CVideoSync, IDispResource
 public:
   CVideoSyncGLX(CVideoReferenceClock *clock) : CVideoSync(clock) {};
   virtual bool Setup(PUPDATECLOCK func);
-  virtual void Run(volatile bool& stop);
+  virtual void Run(std::atomic<bool>& stop);
   virtual void Cleanup();
   virtual float GetFps();
   virtual void OnLostDisplay();
diff --git a/xbmc/video/videosync/VideoSyncIMX.cpp b/xbmc/video/videosync/VideoSyncIMX.cpp
index 51f4f5f..fa7c27c 100644
--- a/xbmc/video/videosync/VideoSyncIMX.cpp
+++ b/xbmc/video/videosync/VideoSyncIMX.cpp
@@ -50,7 +50,7 @@ bool CVideoSyncIMX::Setup(PUPDATECLOCK func)
   return true;
 }
 
-void CVideoSyncIMX::Run(volatile bool& stop)
+void CVideoSyncIMX::Run(std::atomic<bool>& stop)
 {
   int counter;
 
diff --git a/xbmc/video/videosync/VideoSyncIMX.h b/xbmc/video/videosync/VideoSyncIMX.h
index d435292..7220ac6 100644
--- a/xbmc/video/videosync/VideoSyncIMX.h
+++ b/xbmc/video/videosync/VideoSyncIMX.h
@@ -30,7 +30,7 @@ public:
   CVideoSyncIMX(CVideoReferenceClock *clock);
   virtual ~CVideoSyncIMX();
   virtual bool Setup(PUPDATECLOCK func);
-  virtual void Run(volatile bool& stop);
+  virtual void Run(std::atomic<bool>& stop);
   virtual void Cleanup();
   virtual float GetFps();
   virtual void OnResetDisplay();
diff --git a/xbmc/video/videosync/VideoSyncIos.cpp b/xbmc/video/videosync/VideoSyncIos.cpp
index 86fa4a5..8dcefdb 100644
--- a/xbmc/video/videosync/VideoSyncIos.cpp
+++ b/xbmc/video/videosync/VideoSyncIos.cpp
@@ -47,7 +47,7 @@ bool CVideoSyncIos::Setup(PUPDATECLOCK func)
   return setupOk;
 }
 
-void CVideoSyncIos::Run(volatile bool& stop)
+void CVideoSyncIos::Run(std::atomic<bool>& stop)
 {
   //because cocoa has a vblank callback, we just keep sleeping until we're asked to stop the thread
   while(!stop && !m_abort)
diff --git a/xbmc/video/videosync/VideoSyncIos.h b/xbmc/video/videosync/VideoSyncIos.h
index 12e7d8f..a31590f 100644
--- a/xbmc/video/videosync/VideoSyncIos.h
+++ b/xbmc/video/videosync/VideoSyncIos.h
@@ -30,7 +30,7 @@ public:
   
   // CVideoSync interface
   virtual bool Setup(PUPDATECLOCK func);
-  virtual void Run(volatile bool& stop);
+  virtual void Run(std::atomic<bool>& stop);
   virtual void Cleanup();
   virtual float GetFps();
   
diff --git a/xbmc/video/videosync/VideoSyncOsx.cpp b/xbmc/video/videosync/VideoSyncOsx.cpp
index 3ba3823..f7173dc 100644
--- a/xbmc/video/videosync/VideoSyncOsx.cpp
+++ b/xbmc/video/videosync/VideoSyncOsx.cpp
@@ -49,7 +49,7 @@ bool CVideoSyncOsx::Setup(PUPDATECLOCK func)
   return true;
 }
 
-void CVideoSyncOsx::Run(volatile bool& stop)
+void CVideoSyncOsx::Run(std::atomic<bool>& stop)
 {
   InitDisplayLink();
 
diff --git a/xbmc/video/videosync/VideoSyncOsx.h b/xbmc/video/videosync/VideoSyncOsx.h
index b946a4b..b8b5b30 100644
--- a/xbmc/video/videosync/VideoSyncOsx.h
+++ b/xbmc/video/videosync/VideoSyncOsx.h
@@ -36,7 +36,7 @@ public:
   
   // CVideoSync interface
   virtual bool Setup(PUPDATECLOCK func);
-  virtual void Run(volatile bool& stop);
+  virtual void Run(std::atomic<bool>& stop);
   virtual void Cleanup();
   virtual float GetFps();
   virtual void RefreshChanged();
diff --git a/xbmc/video/videosync/VideoSyncPi.cpp b/xbmc/video/videosync/VideoSyncPi.cpp
index f87fdad..0b512d3 100644
--- a/xbmc/video/videosync/VideoSyncPi.cpp
+++ b/xbmc/video/videosync/VideoSyncPi.cpp
@@ -39,7 +39,7 @@ bool CVideoSyncPi::Setup(PUPDATECLOCK func)
   return true;
 }
 
-void CVideoSyncPi::Run(volatile bool& stop)
+void CVideoSyncPi::Run(std::atomic<bool>& stop)
 {
   /* This shouldn't be very busy and timing is important so increase priority */
   CThread::GetCurrentThread()->SetPriority(CThread::GetCurrentThread()->GetPriority()+1);
diff --git a/xbmc/video/videosync/VideoSyncPi.h b/xbmc/video/videosync/VideoSyncPi.h
index 10a9fa8..c7c3d12 100644
--- a/xbmc/video/videosync/VideoSyncPi.h
+++ b/xbmc/video/videosync/VideoSyncPi.h
@@ -29,7 +29,7 @@ class CVideoSyncPi : public CVideoSync, IDispResource
 public:
   CVideoSyncPi(CVideoReferenceClock *clock) : CVideoSync(clock) {};
   virtual bool Setup(PUPDATECLOCK func);
-  virtual void Run(volatile bool& stop);
+  virtual void Run(std::atomic<bool>& stop);
   virtual void Cleanup();
   virtual float GetFps();
   virtual void OnResetDisplay();
diff --git a/xbmc/video/windows/CMakeLists.txt b/xbmc/video/windows/CMakeLists.txt
index 909635a..a9de0e8 100644
--- a/xbmc/video/windows/CMakeLists.txt
+++ b/xbmc/video/windows/CMakeLists.txt
@@ -11,8 +11,3 @@ set(HEADERS GUIWindowFullScreen.h
             VideoFileItemListModifier.h)
 
 core_add_library(video_windows)
-add_dependencies(video_windows libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(video_windows ffmpeg)
-endif()
diff --git a/xbmc/video/windows/GUIWindowVideoBase.cpp b/xbmc/video/windows/GUIWindowVideoBase.cpp
index 0aed13a..63ed45c 100644
--- a/xbmc/video/windows/GUIWindowVideoBase.cpp
+++ b/xbmc/video/windows/GUIWindowVideoBase.cpp
@@ -366,7 +366,7 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItemPtr item, const ScraperPtr &info2, b
   if (bHasInfo)
   {
     if (!info || info->Content() == CONTENT_NONE) // disable refresh button
-      movieDetails.m_strIMDBNumber = "xx"+movieDetails.m_strIMDBNumber;
+      movieDetails.SetUniqueID("xx"+movieDetails.GetUniqueID());
     *item->GetVideoInfoTag() = movieDetails;
     pDlgInfo->SetMovie(item.get());
     pDlgInfo->Open();
@@ -1469,14 +1469,14 @@ void CGUIWindowVideoBase::AddToDatabase(int iItem)
   // everything is ok, so add to database
   m_database.Open();
   int idMovie = m_database.AddMovie(pItem->GetPath());
-  movie.m_strIMDBNumber = StringUtils::Format("xx%08i", idMovie);
+  movie.SetUniqueID(StringUtils::Format("xx%08i", idMovie));
   m_database.SetDetailsForMovie(pItem->GetPath(), movie, pItem->GetArt());
   m_database.Close();
 
   // done...
   CGUIDialogOK::ShowAndGetInput(CVariant{20177}, CVariant{movie.m_strTitle},
                                 CVariant{StringUtils::Join(movie.m_genre, g_advancedSettings.m_videoItemSeparator)},
-                                CVariant{movie.m_strIMDBNumber});
+                                CVariant{movie.GetUniqueID()});
 
   // library view cache needs to be cleared
   CUtil::DeleteVideoDatabaseDirectoryCache();
diff --git a/xbmc/view/CMakeLists.txt b/xbmc/view/CMakeLists.txt
index 0ade734..1370a73 100644
--- a/xbmc/view/CMakeLists.txt
+++ b/xbmc/view/CMakeLists.txt
@@ -10,4 +10,3 @@ set(HEADERS GUIViewControl.h
             ViewStateSettings.h)
 
 core_add_library(view)
-add_dependencies(view libcpluff)
diff --git a/xbmc/windowing/CMakeLists.txt b/xbmc/windowing/CMakeLists.txt
index b4d712c..9f64f8c 100644
--- a/xbmc/windowing/CMakeLists.txt
+++ b/xbmc/windowing/CMakeLists.txt
@@ -22,4 +22,3 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
 endif()
 
 core_add_library(windowing)
-add_dependencies(windowing libcpluff)
diff --git a/xbmc/windowing/X11/CMakeLists.txt b/xbmc/windowing/X11/CMakeLists.txt
index 43de368..5cdac0c 100644
--- a/xbmc/windowing/X11/CMakeLists.txt
+++ b/xbmc/windowing/X11/CMakeLists.txt
@@ -15,4 +15,3 @@ set(HEADERS GLContext.h
             XRandR.h)
 
 core_add_library(windowing_X11)
-add_dependencies(windowing_X11 libcpluff)
diff --git a/xbmc/windowing/X11/GLContext.h b/xbmc/windowing/X11/GLContext.h
index 2182340..1740711 100644
--- a/xbmc/windowing/X11/GLContext.h
+++ b/xbmc/windowing/X11/GLContext.h
@@ -35,8 +35,8 @@ public:
   virtual bool Refresh(bool force, int screen, Window glWindow, bool &newContext) = 0;
   virtual void Destroy() = 0;
   virtual void Detach() = 0;
-  virtual void SetVSync(bool enable, int &mode) = 0;
-  virtual void SwapBuffers(int &mode) = 0;
+  virtual void SetVSync(bool enable) = 0;
+  virtual void SwapBuffers() = 0;
   virtual void QueryExtensions() = 0;
   bool IsExtSupported(const char* extension) const;
 
diff --git a/xbmc/windowing/X11/GLContextEGL.cpp b/xbmc/windowing/X11/GLContextEGL.cpp
index b406418..f47cabd 100644
--- a/xbmc/windowing/X11/GLContextEGL.cpp
+++ b/xbmc/windowing/X11/GLContextEGL.cpp
@@ -351,12 +351,12 @@ Exit:
   return eglConfig;
 }
 
-void CGLContextEGL::SetVSync(bool enable, int &mode)
+void CGLContextEGL::SetVSync(bool enable)
 {
   eglSwapInterval(m_eglDisplay, enable ? 1 : 0);
 }
 
-void CGLContextEGL::SwapBuffers(int &mode)
+void CGLContextEGL::SwapBuffers()
 {
   if ((m_eglDisplay == EGL_NO_DISPLAY) || (m_eglSurface == EGL_NO_SURFACE))
     return;
diff --git a/xbmc/windowing/X11/GLContextEGL.h b/xbmc/windowing/X11/GLContextEGL.h
index b0a2de3..87b5755 100644
--- a/xbmc/windowing/X11/GLContextEGL.h
+++ b/xbmc/windowing/X11/GLContextEGL.h
@@ -32,8 +32,8 @@ public:
   bool Refresh(bool force, int screen, Window glWindow, bool &newContext) override;
   void Destroy() override;
   void Detach() override;
-  void SetVSync(bool enable, int &mode) override;
-  void SwapBuffers(int &mode) override;
+  void SetVSync(bool enable) override;
+  void SwapBuffers() override;
   void QueryExtensions() override;
   XVisualInfo* GetVisual();
   EGLDisplay m_eglDisplay;
diff --git a/xbmc/windowing/X11/GLContextGLX.cpp b/xbmc/windowing/X11/GLContextGLX.cpp
index 7d2d16e..d9abb4a 100644
--- a/xbmc/windowing/X11/GLContextGLX.cpp
+++ b/xbmc/windowing/X11/GLContextGLX.cpp
@@ -31,6 +31,7 @@ CGLContextGLX::CGLContextGLX(Display *dpy) : CGLContext(dpy)
   m_extPrefix = "GLX_";
   m_glxWindow = 0;
   m_glxContext = 0;
+  m_vsyncMode = 0;
 }
 
 bool CGLContextGLX::Refresh(bool force, int screen, Window glWindow, bool &newContext)
@@ -162,7 +163,7 @@ bool CGLContextGLX::IsSuitableVisual(XVisualInfo *vInfo)
   return true;
 }
 
-void CGLContextGLX::SetVSync(bool enable, int &mode)
+void CGLContextGLX::SetVSync(bool enable)
 {
   // turn of current setting first
   if(m_glXSwapIntervalEXT)
@@ -175,31 +176,31 @@ void CGLContextGLX::SetVSync(bool enable, int &mode)
   if(!enable)
     return;
 
-  if (m_glXSwapIntervalEXT && !mode)
+  if (m_glXSwapIntervalEXT)
   {
     m_glXSwapIntervalEXT(m_dpy, m_glxWindow, 1);
-    mode = 6;
+    m_vsyncMode = 6;
   }
-  if (m_glXSwapIntervalMESA && !mode)
+  if (m_glXSwapIntervalMESA)
   {
     if(m_glXSwapIntervalMESA(1) == 0)
-      mode = 2;
+      m_vsyncMode = 2;
     else
       CLog::Log(LOGWARNING, "%s - glXSwapIntervalMESA failed", __FUNCTION__);
   }
-  if (m_glXWaitVideoSyncSGI && m_glXGetVideoSyncSGI && !mode)
+  if (m_glXWaitVideoSyncSGI && m_glXGetVideoSyncSGI && !m_vsyncMode)
   {
     unsigned int count;
     if(m_glXGetVideoSyncSGI(&count) == 0)
-      mode = 3;
+      m_vsyncMode = 3;
     else
       CLog::Log(LOGWARNING, "%s - glXGetVideoSyncSGI failed, glcontext probably not direct", __FUNCTION__);
   }
 }
 
-void CGLContextGLX::SwapBuffers(int &mode)
+void CGLContextGLX::SwapBuffers()
 {
-  if(mode == 3)
+  if (m_vsyncMode == 3)
   {
     glFinish();
     unsigned int before = 0, after = 0;
@@ -221,17 +222,17 @@ void CGLContextGLX::SwapBuffers(int &mode)
     {
       CLog::Log(LOGINFO, "GL: retrace count didn't change after buffer swap, switching to vsync mode 4");
       m_iVSyncErrors = 0;
-      mode = 4;
+      m_vsyncMode = 4;
     }
 
     if (m_iVSyncErrors < -200)
     {
       CLog::Log(LOGINFO, "GL: retrace count change for %d consecutive buffer swap, switching to vsync mode 2", -m_iVSyncErrors);
       m_iVSyncErrors = 0;
-      mode = 2;
+      m_vsyncMode = 2;
     }
   }
-  else if (mode == 4)
+  else if (m_vsyncMode == 4)
   {
     glFinish();
     unsigned int before = 0, swap = 0, after = 0;
@@ -258,7 +259,7 @@ void CGLContextGLX::SwapBuffers(int &mode)
     if (m_iVSyncErrors > 30)
     {
       CLog::Log(LOGINFO, "GL: retrace count seems to be changing due to the swapbuffers call, switching to vsync mode 3");
-      mode = 3;
+      m_vsyncMode = 3;
       m_iVSyncErrors = 0;
     }
   }
diff --git a/xbmc/windowing/X11/GLContextGLX.h b/xbmc/windowing/X11/GLContextGLX.h
index 4bc8bf1..783fa18 100644
--- a/xbmc/windowing/X11/GLContextGLX.h
+++ b/xbmc/windowing/X11/GLContextGLX.h
@@ -31,8 +31,8 @@ public:
   bool Refresh(bool force, int screen, Window glWindow, bool &newContext) override;
   void Destroy() override;
   void Detach() override;
-  void SetVSync(bool enable, int &mode) override;
-  void SwapBuffers(int &mode) override;
+  void SetVSync(bool enable) override;
+  void SwapBuffers() override;
   void QueryExtensions() override;
   GLXWindow m_glxWindow;
   GLXContext m_glxContext;
@@ -45,6 +45,7 @@ protected:
   PFNGLXSWAPINTERVALEXTPROC m_glXSwapIntervalEXT;
   int m_nScreen;
   int m_iVSyncErrors;
+  int m_vsyncMode;
 };
 
 #endif
diff --git a/xbmc/windowing/X11/WinSystemX11GLContext.cpp b/xbmc/windowing/X11/WinSystemX11GLContext.cpp
index f1f94ae..33c5858 100644
--- a/xbmc/windowing/X11/WinSystemX11GLContext.cpp
+++ b/xbmc/windowing/X11/WinSystemX11GLContext.cpp
@@ -47,7 +47,7 @@ CWinSystemX11GLContext::~CWinSystemX11GLContext()
 void CWinSystemX11GLContext::PresentRenderImpl(bool rendered)
 {
   if (rendered)
-    m_pGLContext->SwapBuffers(m_iVSyncMode);
+    m_pGLContext->SwapBuffers();
   
   if (m_delayDispReset && m_dispResetTimer.IsTimePast())
   {
@@ -61,7 +61,7 @@ void CWinSystemX11GLContext::PresentRenderImpl(bool rendered)
 
 void CWinSystemX11GLContext::SetVSyncImpl(bool enable)
 {
-  m_pGLContext->SetVSync(enable, m_iVSyncMode);
+  m_pGLContext->SetVSync(enable);
 }
 
 bool CWinSystemX11GLContext::IsExtSupported(const char* extension)
diff --git a/xbmc/windowing/X11/WinSystemX11GLESContext.cpp b/xbmc/windowing/X11/WinSystemX11GLESContext.cpp
index a9995d6..c829ee2 100644
--- a/xbmc/windowing/X11/WinSystemX11GLESContext.cpp
+++ b/xbmc/windowing/X11/WinSystemX11GLESContext.cpp
@@ -21,7 +21,7 @@ CWinSystemX11GLESContext::~CWinSystemX11GLESContext()
 void CWinSystemX11GLESContext::PresentRenderImpl(bool rendered)
 {
   if (rendered)
-    m_pGLContext->SwapBuffers(m_iVSyncMode);
+    m_pGLContext->SwapBuffers();
 
   if (m_delayDispReset && m_dispResetTimer.IsTimePast())
   {
@@ -35,7 +35,7 @@ void CWinSystemX11GLESContext::PresentRenderImpl(bool rendered)
 
 void CWinSystemX11GLESContext::SetVSyncImpl(bool enable)
 {
-  m_pGLContext->SetVSync(enable, m_iVSyncMode);
+  m_pGLContext->SetVSync(enable);
 }
 
 bool CWinSystemX11GLESContext::IsExtSupported(const char* extension)
diff --git a/xbmc/windowing/android/CMakeLists.txt b/xbmc/windowing/android/CMakeLists.txt
index b7782d0..8e58d66 100644
--- a/xbmc/windowing/android/CMakeLists.txt
+++ b/xbmc/windowing/android/CMakeLists.txt
@@ -3,4 +3,3 @@ set(SOURCES WinEventsAndroid.cpp)
 set(HEADERS WinEventsAndroid.h)
 
 core_add_library(windowing_android)
-add_dependencies(windowing_android libcpluff)
diff --git a/xbmc/windowing/osx/CMakeLists.txt b/xbmc/windowing/osx/CMakeLists.txt
index db2c51c..a007c38 100644
--- a/xbmc/windowing/osx/CMakeLists.txt
+++ b/xbmc/windowing/osx/CMakeLists.txt
@@ -15,4 +15,3 @@ if(CORE_SYSTEM_NAME STREQUAL ios)
 endif()
 
 core_add_library(windowing_osx)
-add_dependencies(windowing_osx libcpluff)
diff --git a/xbmc/windowing/osx/WinSystemOSXGL.mm b/xbmc/windowing/osx/WinSystemOSXGL.mm
index ce71b0e..3e61409 100644
--- a/xbmc/windowing/osx/WinSystemOSXGL.mm
+++ b/xbmc/windowing/osx/WinSystemOSXGL.mm
@@ -47,10 +47,9 @@ void CWinSystemOSXGL::SetVSyncImpl(bool enable)
 {
   EnableVSync(false);
   
-  if (enable && m_iVSyncMode == 0)
+  if (enable)
   {
     EnableVSync(true);
-    m_iVSyncMode = 10;
   }
 }
 
diff --git a/xbmc/windows/CMakeLists.txt b/xbmc/windows/CMakeLists.txt
index 3aa5c6b..3700602 100644
--- a/xbmc/windows/CMakeLists.txt
+++ b/xbmc/windows/CMakeLists.txt
@@ -25,8 +25,3 @@ set(HEADERS GUIMediaWindow.h
             GUIWindowWeather.h)
 
 core_add_library(windows)
-add_dependencies(windows libcpluff)
-
-if(ENABLE_INTERNAL_FFMPEG)
-  add_dependencies(windows ffmpeg)
-endif()
diff --git a/xbmc/windows/GUIMediaWindow.cpp b/xbmc/windows/GUIMediaWindow.cpp
index 075d531..ad9c6bb 100644
--- a/xbmc/windows/GUIMediaWindow.cpp
+++ b/xbmc/windows/GUIMediaWindow.cpp
@@ -653,16 +653,7 @@ bool CGUIMediaWindow::GetDirectory(const std::string &strDirectory, CFileItemLis
   CLog::Log(LOGDEBUG,"  ParentPath = [%s]", CURL::GetRedacted(strParentPath).c_str());
 
   if (pathToUrl.IsProtocol("plugin"))
-  {
-    //Record usage
-    auto& addonId = pathToUrl.GetHostName();
-    auto time = CDateTime::GetCurrentDateTime();
-    CJobManager::GetInstance().Submit([addonId, time](){
-      CAddonDatabase db;
-      if (db.Open())
-        db.SetLastUsed(addonId, time);
-    });
-  }
+    CAddonMgr::GetInstance().UpdateLastUsed(pathToUrl.GetHostName());
 
   // see if we can load a previously cached folder
   CFileItemList cachedItems(strDirectory);
@@ -930,15 +921,8 @@ bool CGUIMediaWindow::OnClick(int iItem, const std::string &player)
     {
       if (!CScriptInvocationManager::GetInstance().Stop(addon->LibPath()))
       {
-        auto time = CDateTime::GetCurrentDateTime();
-
+        CAddonMgr::GetInstance().UpdateLastUsed(addon->ID());
         CScriptInvocationManager::GetInstance().ExecuteAsync(addon->LibPath(), addon);
-
-        CJobManager::GetInstance().Submit([addon, time](){
-          CAddonDatabase db;
-          if (db.Open())
-            db.SetLastUsed(addon->ID(), time);
-        });
       }
       return true;
     }
diff --git a/xbmc/windows/GUIWindowFileManager.cpp b/xbmc/windows/GUIWindowFileManager.cpp
index 57a73b7..547507f 100644
--- a/xbmc/windows/GUIWindowFileManager.cpp
+++ b/xbmc/windows/GUIWindowFileManager.cpp
@@ -489,6 +489,14 @@ bool CGUIWindowFileManager::Update(int iList, const std::string &strDirectory)
     pItem->SetArt("thumb", "DefaultFolder.png");
     pItem->SetLabelPreformated(true);
     m_vecItems[iList]->Add(pItem);
+    
+    #ifdef TARGET_DARWIN_IOS
+      CFileItemPtr iItem(new CFileItem("special://envhome/Documents/Inbox", true));
+      iItem->SetLabel("Inbox");
+      iItem->SetArt("thumb", "DefaultFolder.png");
+      iItem->SetLabelPreformated(true);
+      m_vecItems[iList]->Add(iItem);
+    #endif
   }
 
   // if we have a .tbn file, use itself as the thumb
diff --git a/xbmc/windows/GUIWindowSplash.cpp b/xbmc/windows/GUIWindowSplash.cpp
index 93ffc41..1834013 100644
--- a/xbmc/windows/GUIWindowSplash.cpp
+++ b/xbmc/windows/GUIWindowSplash.cpp
@@ -33,7 +33,7 @@ CGUIWindowSplash::CGUIWindowSplash(void) : CGUIWindow(WINDOW_SPLASH, "")
 
 CGUIWindowSplash::~CGUIWindowSplash(void)
 {
-  delete m_image;
+
 }
 
 void CGUIWindowSplash::OnInitWindow()
@@ -44,7 +44,7 @@ void CGUIWindowSplash::OnInitWindow()
 
   CLog::Log(LOGINFO, "load splash image: %s", CSpecialProtocol::TranslatePath(splashImage).c_str());
 
-  m_image = new CGUIImage(0, 0, 0, 0, g_graphicsContext.GetWidth(), g_graphicsContext.GetHeight(), CTextureInfo(splashImage));
+  m_image = std::unique_ptr<CGUIImage>(new CGUIImage(0, 0, 0, 0, g_graphicsContext.GetWidth(), g_graphicsContext.GetHeight(), CTextureInfo(splashImage)));
   m_image->SetAspectRatio(CAspectRatio::AR_SCALE);
 }
 
@@ -56,4 +56,4 @@ void CGUIWindowSplash::Render()
   m_image->AllocResources();
   m_image->Render();
   m_image->FreeResources();
-}
\ No newline at end of file
+}
diff --git a/xbmc/windows/GUIWindowSplash.h b/xbmc/windows/GUIWindowSplash.h
index 510db06..4c29abd 100644
--- a/xbmc/windows/GUIWindowSplash.h
+++ b/xbmc/windows/GUIWindowSplash.h
@@ -20,6 +20,8 @@
  *
  */
 
+#include <memory>
+
 #include "guilib/GUIWindow.h"
 
 class CGUITextLayout;
@@ -35,5 +37,5 @@ public:
 protected:
   virtual void OnInitWindow();
 private:
-  CGUIImage* m_image;
+  std::unique_ptr<CGUIImage> m_image;
 };

-- 
kodi packaging



More information about the pkg-multimedia-commits mailing list