From ff96a36cc71598c0b360b27947e1c93120bf01b9 Mon Sep 17 00:00:00 2001 From: hbeham Date: Fri, 27 Nov 2015 23:47:09 +0100 Subject: [PATCH] - added tests for Samsung .scm files - fixed some rare file-format detection issues for Samsung (e.g. J-series with .scm format, HExxC, LTxxC) --- .../ChanSort.Loader.Hisense.csproj | 18 +++ .../ChanSort.Loader.Samsung/AnalogChannel.cs | 3 +- .../ChanSort.Loader.Samsung.ini | 18 +-- .../ChanSort.Loader.Samsung/ModelConstants.cs | 6 +- .../Properties/AssemblyInfo.cs | 4 +- .../ChanSort.Loader.Samsung/ScmChannelBase.cs | 6 +- .../ChanSort.Loader.Samsung/ScmSerializer.cs | 23 ++-- source/ChanSort.sln | 18 ++- .../FileFormatDetectionTest.cs | 85 +++++++++++++ .../Properties/AssemblyInfo.cs | 36 ++++++ .../Test.Loader.Samsung.csproj | 114 ++++++++++++++++++ 11 files changed, 301 insertions(+), 30 deletions(-) create mode 100644 source/Test.Loader.Samsung/FileFormatDetectionTest.cs create mode 100644 source/Test.Loader.Samsung/Properties/AssemblyInfo.cs create mode 100644 source/Test.Loader.Samsung/Test.Loader.Samsung.csproj diff --git a/source/ChanSort.Loader.Hisense/ChanSort.Loader.Hisense.csproj b/source/ChanSort.Loader.Hisense/ChanSort.Loader.Hisense.csproj index ab12484..01885a8 100644 --- a/source/ChanSort.Loader.Hisense/ChanSort.Loader.Hisense.csproj +++ b/source/ChanSort.Loader.Hisense/ChanSort.Loader.Hisense.csproj @@ -32,6 +32,24 @@ prompt 4 + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + diff --git a/source/ChanSort.Loader.Samsung/AnalogChannel.cs b/source/ChanSort.Loader.Samsung/AnalogChannel.cs index 3f38a0e..46db84b 100644 --- a/source/ChanSort.Loader.Samsung/AnalogChannel.cs +++ b/source/ChanSort.Loader.Samsung/AnalogChannel.cs @@ -16,12 +16,13 @@ namespace ChanSort.Loader.Samsung this.InitCommonData(slot, signalSource, mapping); var floatFreq = mapping.GetFloat(_Frequency); - if (!float.IsNaN(floatFreq)) + if (!float.IsNaN(floatFreq) && floatFreq > 100 && floatFreq < 2000) // some files seem to have a value way off scale this.FreqInMhz = (decimal)floatFreq; // C,D,E series have the value in the data record if (this.FreqInMhz == 0) // for B series take it from the Tuning table this.FreqInMhz = freq; if (this.FreqInMhz == 0) // fallback since Freq is part of the UID and requires a unique value this.FreqInMhz = slot; + this.ChannelOrTransponder = ""; } diff --git a/source/ChanSort.Loader.Samsung/ChanSort.Loader.Samsung.ini b/source/ChanSort.Loader.Samsung/ChanSort.Loader.Samsung.ini index fad45c4..8a8e673 100644 --- a/source/ChanSort.Loader.Samsung/ChanSort.Loader.Samsung.ini +++ b/source/ChanSort.Loader.Samsung/ChanSort.Loader.Samsung.ini @@ -11,6 +11,7 @@ Favorites = 4 [Series:C] + ; _1001 format. favorites A-D are stored in a bitmask SatDataBase.dat = 145 TransponderDataBase.dat = 45 PTC = 12 @@ -21,6 +22,7 @@ Favorites = 4 [Series:D] + ; _1101 format. favorite A-E have individual number fields, but only allow 0 = not-a-fav, 1=is-a-fav SatDataBase.dat = 145 TransponderDataBase.dat = 45 PTC = 12 @@ -33,6 +35,8 @@ SortedFavorites = 0 [Series:E] + ; _1201 format with favorites A-E and individual numbering (-1 = not-a-fav, 0...x = fav program nr) + ; used by E models SatDataBase.dat = 145 TransponderDataBase.dat = 45 PTC = 12 @@ -46,6 +50,8 @@ SortedFavorites = 1 [Series:F] + ; _1201 format with favorites A-E, but forced to use same numbers as main program number (-1 = not-a-fav, 0...x = main program nr) + ; used by F, H, low-end J and HExxC models SatDataBase.dat = 145 TransponderDataBase.dat = 45 PTC = 12 @@ -58,18 +64,6 @@ Favorites = 5 SortedFavorites = 2 -[Series:H] - SatDataBase.dat = 145 - TransponderDataBase.dat = 45 - PTC = 12 - map-AirA = 64 - map-AirD = 320 - map-CableD = 320 - map-SateD = 168 - map-AstraHDPlusD = 212 - map-CyfraPlusD = 172 - Favorites = 5 - SortedFavorites = 2 [Analog:28] ; map-AirA and map-CableA for B series diff --git a/source/ChanSort.Loader.Samsung/ModelConstants.cs b/source/ChanSort.Loader.Samsung/ModelConstants.cs index 4dbbe73..8620c22 100644 --- a/source/ChanSort.Loader.Samsung/ModelConstants.cs +++ b/source/ChanSort.Loader.Samsung/ModelConstants.cs @@ -7,13 +7,13 @@ namespace ChanSort.Loader.Samsung /// /// D model uses values 0 and 1 /// - Flag = 0, + Boolean = 0, /// - /// E model uses -1 for not-a-fav and 1-x for a fav program number + /// E model uses -1 for not-a-fav and 1..x for a fav program number /// IndividuallySorted = 1, /// - /// some F models and H series uses -1 for not-a-fav, but expects 1-x to match the main program number + /// some F models and H series uses -1 for not-a-fav, but expects 1..x to match the main program number /// MainProgramnrIndex = 2 } diff --git a/source/ChanSort.Loader.Samsung/Properties/AssemblyInfo.cs b/source/ChanSort.Loader.Samsung/Properties/AssemblyInfo.cs index 6602a5f..fc83ef9 100644 --- a/source/ChanSort.Loader.Samsung/Properties/AssemblyInfo.cs +++ b/source/ChanSort.Loader.Samsung/Properties/AssemblyInfo.cs @@ -2,7 +2,9 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -[assembly:InternalsVisibleTo("Test.Loader")] +[assembly: InternalsVisibleTo("Test.Loader")] +[assembly: InternalsVisibleTo("Test.Loader.Samsung")] + // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information diff --git a/source/ChanSort.Loader.Samsung/ScmChannelBase.cs b/source/ChanSort.Loader.Samsung/ScmChannelBase.cs index adb886d..8a23a9d 100644 --- a/source/ChanSort.Loader.Samsung/ScmChannelBase.cs +++ b/source/ChanSort.Loader.Samsung/ScmChannelBase.cs @@ -80,9 +80,9 @@ namespace ChanSort.Loader.Samsung foreach (int off in offsets) { int favValue = BitConverter.ToInt32(this.rawData, baseOffset + off); - if (sortedFavorites == FavoritesIndexMode.Flag && favValue != 0) + if (sortedFavorites == FavoritesIndexMode.Boolean && favValue != 0) fav |= mask; - else if (sortedFavorites != FavoritesIndexMode.Flag && favValue != -1) + else if (sortedFavorites != FavoritesIndexMode.Boolean && favValue != -1) fav |= mask; if (sortedFavorites == FavoritesIndexMode.IndividuallySorted) this.FavIndex[favIndex] = favValue; @@ -173,7 +173,7 @@ namespace ChanSort.Loader.Samsung foreach (int off in offsets) { int favValue; - if (this.sortedFavorites == FavoritesIndexMode.Flag) // D series + if (this.sortedFavorites == FavoritesIndexMode.Boolean) // D series favValue = (fav & mask) != 0 ? 1 : 0; // D series else if (this.sortedFavorites == FavoritesIndexMode.IndividuallySorted) // E series (and some F models with early firmware) favValue = (fav & mask) != 0 ? this.FavIndex[favIndex] : -1; diff --git a/source/ChanSort.Loader.Samsung/ScmSerializer.cs b/source/ChanSort.Loader.Samsung/ScmSerializer.cs index 2e29f78..6b3ff4c 100644 --- a/source/ChanSort.Loader.Samsung/ScmSerializer.cs +++ b/source/ChanSort.Loader.Samsung/ScmSerializer.cs @@ -9,7 +9,7 @@ using ICSharpCode.SharpZipLib.Zip; namespace ChanSort.Loader.Samsung { - class ScmSerializer : SerializerBase + internal class ScmSerializer : SerializerBase { private readonly Dictionary modelConstants = new Dictionary(); private readonly MappingPool analogMappings = new MappingPool("Analog"); @@ -140,7 +140,7 @@ namespace ChanSort.Loader.Samsung #endregion #region DetectModelConstants() - private void DetectModelConstants(ZipFile zip) + internal void DetectModelConstants(ZipFile zip) { if (DetectModelFromFileName()) return; if (DetectModelFromCloneInfoFile(zip)) return; @@ -165,9 +165,9 @@ namespace ChanSort.Loader.Samsung case "1101": series = "D"; break; case "1201": var letter = match.Groups[2].Value; - series = match.Groups[1].Value.StartsWith("LT") ? "F" : // LTxxCxxx is actually an F-series model - StringComparer.OrdinalIgnoreCase.Compare(letter, "E") < 0 ? "E" : // at least E sereis - letter; // E, F, H + + // F, H and low-end J series use same file format + series = letter == "E" ? "E" : "F"; break; default: return false; @@ -192,8 +192,12 @@ namespace ChanSort.Loader.Samsung if (cloneInfo.Length >= 9) { char series = (char) cloneInfo[8]; - if (series == 'B') // 2013 B-series uses E/F-series format + if (series == 'B') // LTxxBxxx uses E/F format. the old B-series has no CloneInfo file, so we can tell the difference series = 'F'; + else if (series == 'C') // there are models with a C that are actually F: LTxxCxxx, HExxCxxx, ... so we can't decide here + return false; + else if (series >= 'F') // F, H, low-end J + series = 'F'; if (this.modelConstants.TryGetValue("Series:" + series, out this.c)) return true; } @@ -212,7 +216,7 @@ namespace ChanSort.Loader.Samsung DetectModelFromAstraHdPlusD(zip) }; - // note: E, F and B(2013) series use an identical format, so we only care about E here + // E, F, B(2013), H, low-end J series use an identical format, so we only care about one here string validCandidates = "BCDE"; foreach (var candidateList in candidates) { @@ -230,7 +234,10 @@ namespace ChanSort.Loader.Samsung if (validCandidates.Length == 0) return false; - this.modelConstants.TryGetValue("Series:" + validCandidates[0], out this.c); + var series = validCandidates[0]; + if (series == 'E') // E allows favorites to be individually sorted, while F-J require them to match the main program nr + series = 'F'; // since we can't tell the difference from the format, we use the safe F/H/J logic, which also works for E + this.modelConstants.TryGetValue("Series:" + series, out this.c); return true; } diff --git a/source/ChanSort.sln b/source/ChanSort.sln index 9b050c7..0df77eb 100644 --- a/source/ChanSort.sln +++ b/source/ChanSort.sln @@ -43,6 +43,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChanSort.Loader.SamsungJ", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChanSort.Loader.Hisense", "ChanSort.Loader.Hisense\ChanSort.Loader.Hisense.csproj", "{D093E7EE-D3AD-4E7B-AF82-C6918CA017FB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Loader.Samsung", "Test.Loader.Samsung\Test.Loader.Samsung.csproj", "{1ED68A9B-6698-4609-B9E6-8E08B6055F2E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -181,14 +183,26 @@ Global {D093E7EE-D3AD-4E7B-AF82-C6918CA017FB}.Debug|Any CPU.Build.0 = Debug|Any CPU {D093E7EE-D3AD-4E7B-AF82-C6918CA017FB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {D093E7EE-D3AD-4E7B-AF82-C6918CA017FB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {D093E7EE-D3AD-4E7B-AF82-C6918CA017FB}.Debug|x86.ActiveCfg = Debug|Any CPU - {D093E7EE-D3AD-4E7B-AF82-C6918CA017FB}.Debug|x86.Build.0 = Debug|Any CPU + {D093E7EE-D3AD-4E7B-AF82-C6918CA017FB}.Debug|x86.ActiveCfg = Debug|x86 + {D093E7EE-D3AD-4E7B-AF82-C6918CA017FB}.Debug|x86.Build.0 = Debug|x86 {D093E7EE-D3AD-4E7B-AF82-C6918CA017FB}.Release|Any CPU.ActiveCfg = Release|Any CPU {D093E7EE-D3AD-4E7B-AF82-C6918CA017FB}.Release|Any CPU.Build.0 = Release|Any CPU {D093E7EE-D3AD-4E7B-AF82-C6918CA017FB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {D093E7EE-D3AD-4E7B-AF82-C6918CA017FB}.Release|Mixed Platforms.Build.0 = Release|Any CPU {D093E7EE-D3AD-4E7B-AF82-C6918CA017FB}.Release|x86.ActiveCfg = Release|Any CPU {D093E7EE-D3AD-4E7B-AF82-C6918CA017FB}.Release|x86.Build.0 = Release|Any CPU + {1ED68A9B-6698-4609-B9E6-8E08B6055F2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1ED68A9B-6698-4609-B9E6-8E08B6055F2E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1ED68A9B-6698-4609-B9E6-8E08B6055F2E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {1ED68A9B-6698-4609-B9E6-8E08B6055F2E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {1ED68A9B-6698-4609-B9E6-8E08B6055F2E}.Debug|x86.ActiveCfg = Debug|x86 + {1ED68A9B-6698-4609-B9E6-8E08B6055F2E}.Debug|x86.Build.0 = Debug|x86 + {1ED68A9B-6698-4609-B9E6-8E08B6055F2E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1ED68A9B-6698-4609-B9E6-8E08B6055F2E}.Release|Any CPU.Build.0 = Release|Any CPU + {1ED68A9B-6698-4609-B9E6-8E08B6055F2E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {1ED68A9B-6698-4609-B9E6-8E08B6055F2E}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {1ED68A9B-6698-4609-B9E6-8E08B6055F2E}.Release|x86.ActiveCfg = Release|Any CPU + {1ED68A9B-6698-4609-B9E6-8E08B6055F2E}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/source/Test.Loader.Samsung/FileFormatDetectionTest.cs b/source/Test.Loader.Samsung/FileFormatDetectionTest.cs new file mode 100644 index 0000000..c3e018a --- /dev/null +++ b/source/Test.Loader.Samsung/FileFormatDetectionTest.cs @@ -0,0 +1,85 @@ +using System; +using System.IO; +using System.Text; +using ChanSort.Loader.Samsung; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Test.Loader.Samsung +{ + [TestClass] + public class FileFormatDetectionTest + { + private readonly StringBuilder errors = new StringBuilder(); + private const string RootPath = @"d:\sources\ChanSort\TestFiles_Samsung\"; + + #region LoadAllFilesAndLogDetecedFileFormat() + + [TestMethod] + public void LoadAllFilesAndLogDetecedFileFormat() + { + + RecurseInto(RootPath); + + Assert.AreEqual("", errors.ToString()); + } + + private void RecurseInto(string dir) + { + foreach (var path in Directory.GetFiles(dir, "*.scm")) + { + if (path.Contains("_null")) + continue; + try + { + var s = new ScmSerializer(path); + s.Load(); + var series = s.Series; + System.Diagnostics.Debug.WriteLine($"{path.Substring(RootPath.Length)}: {series}"); + } + catch (Exception ex) + { + errors.AppendLine($"{path.Substring(RootPath.Length)} : {ex.Message}"); + } + } + + foreach (var path in Directory.GetDirectories(dir)) + RecurseInto(path); + } + #endregion + + [TestMethod] + public void LoadFileWithExcessiveHighFrequency_1() + { + // this seems to be a corrupt file caused by a buffer-overflow from analog channel names into the frequency data bytes + var s = new ScmSerializer(RootPath + @"ThomasSaur_DH\channel_list_UE55H6470_1201-Suchlauf-2015-04-26.scm"); + s.Load(); + } + + [TestMethod] + public void LoadFileWithExcessiveHighFrequency_2() + { + // this seems to be a corrupt file caused by a buffer-overflow from analog channel names into the frequency data bytes + var s = new ScmSerializer(RootPath + @"ThomasSaur_DH\channel_list_UE55H6470_1201.scm"); + s.Load(); + } + + [TestMethod] + public void LoadRenamedFile_HE40Cxxx_1201() + { + // This file uses the 1201 format (E,F,H,J), but has a "C" in its model name + var s = new ScmSerializer(RootPath + @"__C=F\Kinig\Reier Monika.scm"); + s.Load(); + Assert.AreEqual("F", s.Series); + } + + [TestMethod] + public void LoadRenamedFile_LT24B_1201() + { + // This file uses the 1201 format (E,F,H,J), but has a "B" in its model name + var s = new ScmSerializer(RootPath + @"__B=F\DieterHerzberg_B\renamed.scm"); + s.Load(); + Assert.AreEqual("F", s.Series); + } + + } +} diff --git a/source/Test.Loader.Samsung/Properties/AssemblyInfo.cs b/source/Test.Loader.Samsung/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d6c990d --- /dev/null +++ b/source/Test.Loader.Samsung/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Test.Loader.Samsung")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Test.Loader.Samsung")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("1ed68a9b-6698-4609-b9e6-8e08b6055f2e")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/source/Test.Loader.Samsung/Test.Loader.Samsung.csproj b/source/Test.Loader.Samsung/Test.Loader.Samsung.csproj new file mode 100644 index 0000000..a15581b --- /dev/null +++ b/source/Test.Loader.Samsung/Test.Loader.Samsung.csproj @@ -0,0 +1,114 @@ + + + + Debug + AnyCPU + {1ED68A9B-6698-4609-B9E6-8E08B6055F2E} + Library + Properties + Test.Loader.Samsung + Test.Loader.Samsung + v4.5.2 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + + ..\DLL\ICSharpCode.SharpZipLib.dll + + + + + + + + + + + + + + + + + + + + + + {dccffa08-472b-4d17-bb90-8f513fc01392} + ChanSort.Api + + + {a1c9a98d-368a-44e8-9b7f-7eaca46c9ec5} + ChanSort.Loader.Samsung + + + + + + + False + + + False + + + False + + + False + + + + + + + + \ No newline at end of file