- moved all files to a "source" subdirectory to tidy up the GitHub project page

- started to write a readme.md
This commit is contained in:
hbeham
2015-06-04 13:31:43 +02:00
parent 664235b1ed
commit d4318b13a5
397 changed files with 602 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
using ChanSort.Api;
namespace ChanSort.Loader.Samsung
{
internal class AnalogChannel : ScmChannelBase
{
private const string _Frequency = "offFrequency";
#region ctor()
public AnalogChannel(int slot, bool isCable, DataMapping mapping, decimal freq, FavoritesIndexMode sortedFavorites) :
base(mapping, sortedFavorites)
{
var signalSource = SignalSource.Analog | SignalSource.Tv;
signalSource |= isCable ? SignalSource.Cable : SignalSource.Antenna;
this.InitCommonData(slot, signalSource, mapping);
var floatFreq = mapping.GetFloat(_Frequency);
if (!float.IsNaN(floatFreq))
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 = "";
}
#endregion
}
}

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{A1C9A98D-368A-44E8-9B7F-7EACA46C9EC5}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ChanSort.Loader.Samsung</RootNamespace>
<AssemblyName>ChanSort.Loader.Samsung</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
<CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
<CodeAnalysisFailOnMissingRules>true</CodeAnalysisFailOnMissingRules>
</PropertyGroup>
<ItemGroup>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\DLL\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AnalogChannel.cs" />
<Compile Include="DigitalChannel.cs" />
<Compile Include="FavMode.cs" />
<Compile Include="ModelConstants.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Resource.de.Designer.cs">
<DependentUpon>Resource.de.resx</DependentUpon>
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="Resource.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resource.resx</DependentUpon>
</Compile>
<Compile Include="SatChannel.cs" />
<Compile Include="SatelliteMapping.cs" />
<Compile Include="ScmChannelBase.cs" />
<Compile Include="ScmSerializer.cs" />
<Compile Include="ScmSerializerPlugin.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ChanSort.Api\ChanSort.Api.csproj">
<Project>{DCCFFA08-472B-4D17-BB90-8F513FC01392}</Project>
<Name>ChanSort.Api</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="ChanSort.Loader.Samsung.ini">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resource.de.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resource.de.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Resource.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resource.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,359 @@
[Series:B]
SatDataBase.dat = 145
TransponderDataBase.dat = 49
FineTune = 20
FineTune_Digital = 28
PTC = 12
map-AirA = 28
map-AirD = 248
map-CableD = 248
map-SateD = 144
Favorites = 4
[Series:C]
SatDataBase.dat = 145
TransponderDataBase.dat = 45
PTC = 12
map-AirA = 40
map-AirD = 292
map-CableD = 292
map-SateD = 144
Favorites = 4
[Series:D]
SatDataBase.dat = 145
TransponderDataBase.dat = 45
PTC = 12
map-AirA = 64
map-AirD = 320
map-CableD = 320
map-SateD = 172
map-AstraHDPlusD = 212
Favorites = 5
SortedFavorites = 0
[Series:E]
SatDataBase.dat = 145
TransponderDataBase.dat = 45
PTC = 12
map-AirA = 64
map-AirD = 320
map-CableD = 320
map-SateD = 168
map-AstraHDPlusD = 212
Favorites = 5
SortedFavorites = 1
[Series:F]
SatDataBase.dat = 145
TransponderDataBase.dat = 45
PTC = 12
map-AirA = 64
map-AirD = 320
map-CableD = 320
map-SateD = 168
map-AstraHDPlusD = 212
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
offInUse = 0
maskInUse = 0x02
offProgramNr = 4
offNameLength =
offName = 12
lenName = 10
offFavorites = 26
offChecksum = 27
[Analog:40]
; map-AirA and map-CableA for C series
offInUse = 1
maskInUse = 0x01
offDeleted = 2
maskDeleted = 0x01
offLock = 6
maskLock = 0x01
offTuned = 8
maskTuned = 0x01
offProgramNr = 9
offSlotNr = 16
offNameLength = 18
offName = 20
lenName = 10
offFrequency = 32
offFavorites = 38
offChecksum = 39
[Analog:64]
; map-AirA and map-CableA for D,E and F series
offInUse = 1
maskInUse = 0x01
offDeleted = 2
maskDeleted = 0x01
offLock = 6
maskLock = 0x01
offTuned = 8
maskTuned = 0x01
offProgramNr = 9
offSlotNr = 16
offNameLength = 18
offName = 20
lenName = 10
offFrequency = 32
offFavorites = 36,40,44,48,52
offChecksum = 63
[FineTune:20]
offIsCable = 0
maskIsCable = 0x01
offSlotNr = 4
offFrequency = 8
[FineTune_Digital:28]
offIsCable = 0
maskIsCable = 0x01
offChannelTransponder = 4
offFrequency = 16
[PTC:12]
offFrequency = 4
offChannelTransponder = 8
[ServiceProvider:108]
offSignalSource = 0
offIndex = 2
offLenName = 6
offName = 8
[DvbCT:248]
; map-AirD and map-CableD for B series
offProgramNr = 0
offVideoPid = 2
offPcrPid = 4
; "Deleted"-flag is implemented in reverse by IsActive
offIsActive = 6
maskIsActive = 0x02
offQam = 7
offInUse = 8
maskInUse = 0x80
offServiceType = 9
offServiceId = 10
offOriginalNetworkId = 12
offNetworkId = 14
offEncrypted = 23
maskEncrypted = 0x20
offChannelTransponder = 26
offLogicalProgramNr = 28
offSymbolRate = 32
offBouquet = 34
offTransportStreamId = 36
offName = 44
lenName = 100
offLock = 245
maskLock = 0x01
offFavorites = 246
offChecksum = 247
[DvbCT:292]
; map-AirD and map-CableD for C series
offProgramNr = 0
offVideoPid = 2
offPcrPid = 4
offServiceId = 6
offDeleted = 8
maskDeleted = 0x01
offSignalSource = 10
offQam = 12
offBandwidth = 14
offServiceType = 15
offCodec = 16
offHRes = 20
offVRes = 22
offEncrypted = 24
maskEncrypted = 0x01
offFrameRate = 25
offSymbolRate = 28
offLock = 31
maskLock = 0x01
offOriginalNetworkId = 32
offNetworkId = 34
offServiceProviderId = 40
offChannelTransponder = 42
offLogicalProgramNr = 44
offTransportStreamId = 48
offName = 64
lenName = 100
offShortName = 264
lenShortName = 18
offVideoFormat = 282
offFavorites = 290
offChecksum = 291
[DvbCT:320]
; map-AirD, map-CableD, Freesat for D,E and F series
offProgramNr = 0
offVideoPid = 2
offPcrPid = 4
offServiceId = 6
offDeleted = 8
maskDeleted = 0x01
offSignalSource = 10
offQam = 12
offBandwidth = 14
offServiceType = 15
offCodec = 16
offHRes = 20
offVRes = 22
offEncrypted = 24
maskEncrypted = 0x01
offFrameRate = 25
offSymbolRate = 28
offLock = 31
maskLock = 0x01
offOriginalNetworkId = 32
offNetworkId = 34
offServiceProviderId = 40
offChannelTransponder = 42
offLogicalProgramNr = 44
offTransportStreamId = 48
offName = 64
lenName = 100
offShortName = 264
lenShortName = 18
offVideoFormat = 282
offFavorites = 292,296,300,304,308
offChecksum = 319
[TransponderDataBase.dat:49]
; B Series
offMagicByte = 0
offTransponderIndex = 1
offSatelliteIndex = 5
offFrequency = 9
offSymbolRate = 17
[TransponderDataBase.dat:45]
; C,D,E Series
offMagicByte = 0
offTransponderIndex = 1
offSatelliteIndex = 5
offFrequency = 9
offSymbolRate = 13
[DvbS:144]
; map-SateD for B and C Series
offProgramNr = 0
offVideoPid = 2
offPcrPid = 4
offInUse = 7
maskInUse = 0x01
offSignalSource = 10
offLock = 13
maskLock = 0x01
offServiceType = 14
offServiceId = 16
offTransponderIndex = 18
offSatelliteIndex = 20
offTransportStreamId = 24
offOriginalNetworkId = 28
offHRes = 32
offVRes = 34
offName = 36
lenName = 100
offEncrypted = 136
maskEncrypted = 0x01
offServiceProviderId = 138
offFavorites = 142
offChecksum = 143
[DvbS:172]
; map-SateD for D Series
offProgramNr = 0
offVideoPid = 2
offPcrPid = 4
offInUse = 7
maskInUse = 0x01
offSignalSource = 10
offLock = 13
maskLock = 0x01
offServiceType = 14
offServiceId = 16
offTransponderIndex = 18
offSatelliteIndex = 20
offTransportStreamId = 24
offOriginalNetworkId = 28
offHRes = 32
offVRes = 34
offName = 36
lenName = 100
offEncrypted = 136
maskEncrypted = 0x01
offServiceProviderId = 138
offFavorites = 140,144,148,152,156
offChecksum = 171
[DvbS:168]
; map-SateD for E and F Series
offProgramNr = 0
offVideoPid = 2
offPcrPid = 4
offInUse = 7
maskInUse = 0x01
offSignalSource = 10
offLock = 13
maskLock = 0x01
offServiceType = 14
offServiceId = 16
offTransponderIndex = 18
offSatelliteIndex = 20
offTransportStreamId = 24
offOriginalNetworkId = 28
offHRes = 32
offVRes = 34
offName = 36
offEncrypted = 136
maskEncrypted = 0x01
lenName = 100
offServiceProviderId = 138
offFavorites = 140,144,148,152,156
offChecksum = 167
[AstraHDPlusD:212]
; map-AstraHDPlusD for D, E and F Series
offProgramNr = 0,20
offVideoPid=2
offPcrId=4
offInUse = 7
maskInUse = 0x01
offSignalSource = 10
offLock = 13
maskLock = 0x01
offServiceType = 14
offServiceId = 16
offTransponderIndex = 18
; satindex is just a guess-pick of a field thats always 0001
offSatelliteIndex = 40
offTransportStreamId = 36
offOriginalNetworkId = 32
offName = 48
lenName = 100
offEncrypted = 180
maskEncrypted = 0x01
offFavorites = 184,188,192,196,200
offChecksum = 211

View File

@@ -0,0 +1,30 @@
using System.Collections.Generic;
using ChanSort.Api;
namespace ChanSort.Loader.Samsung
{
public class DigitalChannel : ScmChannelBase
{
private const string _ChannelOrTransponder = "offChannelTransponder";
public DigitalChannel(int slot, SignalSource signalSource, DataMapping data,
IDictionary<int, decimal> transpFreq, FavoritesIndexMode sortedFavorites, IDictionary<int, string> providerNames) :
base(data, sortedFavorites)
{
this.InitCommonData(slot, (SignalSource)((int)signalSource & ~(int)(SignalSource.TvAndRadio)), data);
if (!this.InUse || this.OldProgramNr == 0)
return;
this.InitDvbData(data, providerNames);
int transp = data.GetByte(_ChannelOrTransponder);
decimal freq = transpFreq.TryGet(transp);
if (freq == 0)
freq = transp*8 + 106; // (106 = DVB-C; DVB-T=306?)
this.ChannelOrTransponder = LookupData.Instance.GetDvbtTransponder(freq).ToString();
this.FreqInMhz = freq;
}
}
}

View File

@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ChanSort.Loader.Samsung
{
class FavMode
{
}
}

View File

@@ -0,0 +1,60 @@
using ChanSort.Api;
namespace ChanSort.Loader.Samsung
{
public enum FavoritesIndexMode
{
/// <summary>
/// D model uses values 0 and 1
/// </summary>
Flag = 0,
/// <summary>
/// E model uses -1 for not-a-fav and 1-x for a fav program number
/// </summary>
IndividuallySorted = 1,
/// <summary>
/// some F models and H series uses -1 for not-a-fav, but expects 1-x to match the main program number
/// </summary>
MainProgramnrIndex = 2
}
internal class ModelConstants
{
public readonly string series;
public readonly int dvbsSatelliteLength;
public readonly int dvbsTransponderLength;
public readonly int dvbsChannelLength;
public readonly int dvbtChannelLength;
public readonly int avbtChannelLength;
public readonly int hdplusChannelLength;
public readonly int avbtFineTuneLength;
public readonly int dvbtFineTuneLength;
public readonly Favorites supportedFavorites;
public readonly int ptcLength;
public readonly int serviceProviderLength;
public readonly FavoritesIndexMode SortedFavorites;
public readonly int cyfraPlusChannelSize;
public ModelConstants(IniFile.Section iniSection)
{
this.series = iniSection.Name.Substring(iniSection.Name.Length - 1);
this.avbtChannelLength = iniSection.GetInt("map-AirA");
this.dvbtChannelLength = iniSection.GetInt("map-AirD");
this.dvbsChannelLength = iniSection.GetInt("map-SateD");
this.hdplusChannelLength = iniSection.GetInt("map-AstraHDPlusD");
this.cyfraPlusChannelSize = iniSection.GetInt("map-CyfraPlusD");
this.ptcLength = iniSection.GetInt("PTC");
this.dvbsSatelliteLength = iniSection.GetInt("SatDataBase.dat");
this.dvbsTransponderLength = iniSection.GetInt("TransponderDataBase.dat");
this.avbtFineTuneLength = iniSection.GetInt("FineTune");
this.dvbtFineTuneLength = iniSection.GetInt("FineTune_Digital");
this.serviceProviderLength = iniSection.GetInt("ServiceProvider", 108);
int numFavorites = iniSection.GetInt("Favorites");
int mask = 0;
for (int i = 0; i < numFavorites; i++)
mask = (mask << 1) | 1;
this.supportedFavorites = (Favorites)mask;
this.SortedFavorites = (FavoritesIndexMode)iniSection.GetInt("SortedFavorites");
}
}
}

View File

@@ -0,0 +1,38 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly:InternalsVisibleTo("Test.Loader")]
// 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("ChanSort.Loader.Samsung")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ChanSort.Loader.Samsung")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[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("6f59ac5a-afba-42e3-a63e-c74793c15980")]
// 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")]

View File

@@ -0,0 +1,76 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.34014
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ChanSort.Loader.Samsung {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resource {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resource() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ChanSort.Loader.Samsung.Resource", typeof(Resource).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to This file contains no data, all bytes in it are set to 0.
///
///Please make sure your USB stick is formatted as FAT32 and preferrably not larger than 4GB.
///If that still does not work, try to reset your TV to factory defaults and run a new channel search.
///(This might be necessary after a firmware update.).
/// </summary>
internal static string ScmSerializer_AllBytesInFileAreZero {
get {
return ResourceManager.GetString("ScmSerializer_AllBytesInFileAreZero", resourceCulture);
}
}
}
}

View File

View File

@@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ScmSerializer_AllBytesInFileAreZero" xml:space="preserve">
<value>Diese Datei enthält keine Daten, alle Bytes darin haben den Wert 0.
Bitte stellen Sie sicher, dass der USB Stick mit FAT32 formatiert ist und wenn möglich nicht größer als 4GB ist.
Sollte es danach weiterhin nicht funktionieren, versuchen Sie bitte das Gerät auf Werkseinstellungen zurückzusetzen und einen Suchlauf durchzuführen.
(Dies kann nach machen Firmwareupdates nötig sein, damit Export/Import wieder funktionieren.)</value>
</data>
</root>

View File

@@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ScmSerializer_AllBytesInFileAreZero" xml:space="preserve">
<value>This file contains no data, all bytes in it are set to 0.
Please make sure your USB stick is formatted as FAT32 and preferrably not larger than 4GB.
If that still does not work, try to reset your TV to factory defaults and run a new channel search.
(This might be necessary after a firmware update.)</value>
</data>
</root>

View File

@@ -0,0 +1,45 @@
using System.Collections.Generic;
using ChanSort.Api;
namespace ChanSort.Loader.Samsung
{
class SatChannel : ScmChannelBase
{
private const string _TransponderIndex = "offTransponderIndex";
public SatChannel(int slot, SignalSource presetList, DataMapping data, DataRoot dataRoot, FavoritesIndexMode sortedFavorites, IDictionary<int,string> providerNames) :
base(data, sortedFavorites)
{
this.InitCommonData(slot, SignalSource.DvbS | presetList, data);
if (!this.InUse)
return;
this.InitDvbData(data, providerNames);
int transponderIndex = data.GetWord(_TransponderIndex);
Transponder transponder = dataRoot.Transponder.TryGet(transponderIndex);
if (transponder == null)
{
var list = dataRoot.GetChannelList(this.SignalSource|SignalSource.Tv);
dataRoot.Warnings.AppendFormat("{0} channel record #{1} (Pr# {2} \"{3}\") contains invalid transponder index {4}\r\n",
list.ShortCaption, slot, this.OldProgramNr, this.Name, transponderIndex);
return;
}
Satellite sat = transponder.Satellite;
this.Satellite = sat.Name;
this.SatPosition = sat.OrbitalPosition;
this.Polarity = transponder.Polarity;
this.SymbolRate = transponder.SymbolRate;
this.FreqInMhz = transponder.FrequencyInMhz;
this.ChannelOrTransponder = "";
}
public override void UpdateRawData()
{
if (this.NewProgramNr < 0) // "deleted" flag is currently unknown for sat channels
this.InUse = false;
base.UpdateRawData();
}
}
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Text;
namespace ChanSort.Loader.Samsung
{
internal class SatelliteMapping
{
private static readonly Encoding utf16Encoding = new UnicodeEncoding(false, false);
private readonly byte[] data;
public int BaseOffset;
public SatelliteMapping(byte[] data, int offset)
{
this.data = data;
this.BaseOffset = offset;
}
public byte MagicMarker { get { return data[BaseOffset]; } }
public int SatelliteNr { get { return BitConverter.ToInt32(data, BaseOffset + 1); } }
public string Name { get { return utf16Encoding.GetString(data, BaseOffset + 9, 128).TrimEnd('\0'); } }
public bool IsEast { get { return BitConverter.ToInt32(data, BaseOffset + 137) != 0; } }
public int Longitude { get { return BitConverter.ToInt32(data, BaseOffset + 141); } }
}
}

View File

@@ -0,0 +1,201 @@
using System;
using System.Collections.Generic;
using System.Text;
using ChanSort.Api;
namespace ChanSort.Loader.Samsung
{
public class ScmChannelBase : ChannelInfo
{
// common
private const string _InUse = "InUse";
private const string _ProgramNr = "offProgramNr";
private const string _Name = "offName";
private const string _NameLength = "offNameLength";
private const string _ShortName = "offShortName";
private const string _Favorites = "offFavorites";
private const string _IsActive = "IsActive";
private const string _Deleted = "Deleted";
private const string _Encrypted = "Encrypted";
private const string _Lock = "Lock";
private const string _Checksum = "offChecksum";
// DVB
private const string _ServiceId = "offServiceId";
private const string _VideoPid = "offVideoPid";
private const string _AudioPid = "offAudioPid";
private const string _OriginalNetworkId = "offOriginalNetworkId";
private const string _TransportStreamId = "offTransportStreamId";
private const string _ServiceType = "offServiceType";
private const string _SymbolRate = "offSymbolRate";
private const string _ServiceProviderId = "offServiceProviderId";
private static readonly Encoding Utf16BigEndian = new UnicodeEncoding(true, false);
private readonly FavoritesIndexMode sortedFavorites;
protected readonly DataMapping mapping;
protected readonly byte[] rawData;
internal readonly int baseOffset;
internal bool InUse { get; set; }
protected ScmChannelBase(DataMapping data, FavoritesIndexMode sortedFavorites)
{
this.mapping = data;
this.rawData = data.Data;
this.baseOffset = data.BaseOffset;
this.mapping.DefaultEncoding = Utf16BigEndian;
this.sortedFavorites = sortedFavorites;
}
#region InitCommonData()
protected void InitCommonData(int slot, SignalSource signalSource, DataMapping data)
{
this.InUse = data.GetFlag(_InUse, true);
this.RecordIndex = slot;
this.RecordOrder = slot;
this.SignalSource = signalSource;
this.OldProgramNr = (short)data.GetWord(_ProgramNr);
this.Name = data.GetString(_Name, data.Settings.GetInt("lenName"));
this.Favorites = this.ParseRawFavorites();
this.Lock = data.GetFlag(_Lock);
this.Encrypted = data.GetFlag(_Encrypted);
this.IsDeleted = data.GetFlag(_Deleted, false) || !data.GetFlag(_IsActive, true);
if (this.IsDeleted)
this.OldProgramNr = -1;
}
#endregion
#region ParseRawFavorites()
private Favorites ParseRawFavorites()
{
var offsets = mapping.GetOffsets(_Favorites);
if (offsets.Length == 1) // series B,C
return (Favorites) mapping.GetByte(_Favorites);
// series D,E,F
byte fav = 0;
byte mask = 0x01;
int favIndex = 0;
foreach (int off in offsets)
{
int favValue = BitConverter.ToInt32(this.rawData, baseOffset + off);
if (sortedFavorites == FavoritesIndexMode.Flag && favValue != 0)
fav |= mask;
else if (sortedFavorites != FavoritesIndexMode.Flag && favValue != -1)
fav |= mask;
if (sortedFavorites == FavoritesIndexMode.IndividuallySorted)
this.FavIndex[favIndex] = favValue;
mask <<= 1;
++favIndex;
}
return (Favorites) fav;
}
#endregion
#region InitDvbData()
protected void InitDvbData(DataMapping data, IDictionary<int, string> providerNames)
{
this.ShortName = data.GetString(_ShortName, data.Settings.GetInt("lenShortName"));
this.ServiceId = data.GetWord(_ServiceId);
//this.PcrPid = data.GetWord(_PcrPid);
this.VideoPid = data.GetWord(_VideoPid);
this.AudioPid = data.GetWord(_AudioPid);
this.OriginalNetworkId = data.GetWord(_OriginalNetworkId);
this.TransportStreamId = data.GetWord(_TransportStreamId);
this.ServiceType = data.GetByte(_ServiceType);
this.SymbolRate = data.GetWord(_SymbolRate);
if (data.Settings.GetInt(_ServiceProviderId, -1) != -1)
{
int source = -1;
if ((this.SignalSource & SignalSource.MaskProvider) == SignalSource.Freesat)
source = 4;
else if ((this.SignalSource & SignalSource.MaskProvider) == SignalSource.TivuSat)
source = 6;
else if ((this.SignalSource & SignalSource.Antenna) != 0)
source = 0;
else if ((this.SignalSource & SignalSource.Cable) != 0)
source = 1;
else if ((this.SignalSource & SignalSource.Sat) != 0)
source = 3;
int providerId = data.GetWord(_ServiceProviderId);
this.Provider = providerNames.TryGet((source << 16) + providerId);
}
this.SignalSource |= LookupData.Instance.IsRadioOrTv(this.ServiceType);
}
#endregion
#region UpdateRawData()
public override void UpdateRawData()
{
mapping.SetDataPtr(this.rawData, this.baseOffset);
mapping.SetFlag(_InUse, this.InUse);
if (this.NewProgramNr >= 0)
mapping.SetWord(_ProgramNr, this.NewProgramNr);
if (this.IsNameModified)
{
int bytes = mapping.SetString(_Name, this.Name, mapping.Settings.GetInt("lenName"));
mapping.SetByte(_NameLength, bytes);
this.IsNameModified = false;
}
this.UpdateRawFavorites();
mapping.SetFlag(_Lock, this.Lock);
mapping.SetFlag(_Deleted, this.NewProgramNr < 0);
mapping.SetFlag(_IsActive, this.NewProgramNr >= 0);
this.UpdateChecksum();
}
#endregion
#region EraseRawData()
internal virtual void EraseRawData()
{
int len = this.mapping.Settings.GetInt("offChecksum") + 1;
Tools.MemSet(this.rawData, this.baseOffset, 0, len);
}
#endregion
#region UpdateRawFavorites()
private void UpdateRawFavorites()
{
var offsets = mapping.GetOffsets(_Favorites);
if (offsets.Length == 1) // series B,C
{
mapping.SetByte(_Favorites, (byte)this.Favorites & 0x0F);
return;
}
// series D,E,F
byte fav = (byte)this.Favorites;
byte mask = 0x01;
int favIndex = 0;
foreach (int off in offsets)
{
int favValue;
if (this.sortedFavorites == FavoritesIndexMode.Flag) // 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;
else
favValue = (fav & mask) != 0 ? this.NewProgramNr : -1; // F series (newer models/firmware), H series
Array.Copy(BitConverter.GetBytes(favValue), 0, this.rawData, baseOffset + off, 4);
mask <<= 1;
++favIndex;
}
}
#endregion
#region UpdateChecksum()
private void UpdateChecksum()
{
var offChecksum = this.baseOffset + this.mapping.GetOffsets(_Checksum)[0];
byte crc = 0;
for (int i = this.baseOffset; i < offChecksum; i++)
crc += this.rawData[i];
this.rawData[offChecksum] = crc;
}
#endregion
}
}

View File

@@ -0,0 +1,723 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ChanSort.Api;
using ICSharpCode.SharpZipLib.Zip;
namespace ChanSort.Loader.Samsung
{
class ScmSerializer : SerializerBase
{
private readonly Dictionary<string, ModelConstants> modelConstants = new Dictionary<string, ModelConstants>();
private readonly MappingPool<DataMapping> analogMappings = new MappingPool<DataMapping>("Analog");
private readonly MappingPool<DataMapping> dvbctMappings = new MappingPool<DataMapping>("DVB-C/T");
private readonly MappingPool<DataMapping> dvbsMappings = new MappingPool<DataMapping>("DVB-S");
private readonly MappingPool<DataMapping> hdplusMappings = new MappingPool<DataMapping>("AstraHD+");
private readonly MappingPool<DataMapping> analogFineTuneMappings = new MappingPool<DataMapping>("FineTune");
private readonly MappingPool<DataMapping> ptccableMappings = new MappingPool<DataMapping>("PTC");
private readonly MappingPool<DataMapping> transponderMappings = new MappingPool<DataMapping>("TransponderDataBase");
private readonly MappingPool<DataMapping> serviceProviderMappings = new MappingPool<DataMapping>("ServiceProvider");
private readonly ChannelList avbtChannels = new ChannelList(SignalSource.AnalogT|SignalSource.TvAndRadio, "Analog Air");
private readonly ChannelList avbcChannels = new ChannelList(SignalSource.AnalogC|SignalSource.TvAndRadio, "Analog Cable");
private readonly ChannelList avbxChannels = new ChannelList(SignalSource.AnalogCT | SignalSource.TvAndRadio, "Analog Air/Cable");
private readonly ChannelList dvbtChannels = new ChannelList(SignalSource.DvbT | SignalSource.Tv, "Digital Air");
private readonly ChannelList dvbcChannels = new ChannelList(SignalSource.DvbC | SignalSource.TvAndRadio, "Digital Cable");
private readonly ChannelList dvbxChannels = new ChannelList(SignalSource.DvbCT | SignalSource.TvAndRadio, "Digital Air/Cable");
private readonly ChannelList dvbsChannels = new ChannelList(SignalSource.DvbS | SignalSource.TvAndRadio, "Satellite");
private readonly ChannelList primeChannels = new ChannelList(SignalSource.CablePrimeD | SignalSource.TvAndRadio, "Cable Prime");
private readonly ChannelList hdplusChannels = new ChannelList(SignalSource.HdPlusD | SignalSource.TvAndRadio, "Astra HD+");
private readonly ChannelList freesatChannels = new ChannelList(SignalSource.FreesatD | SignalSource.TvAndRadio, "Freesat");
private readonly ChannelList tivusatChannels = new ChannelList(SignalSource.TivuSatD | SignalSource.TvAndRadio, "TivuSat");
private readonly ChannelList canalDigitalChannels = new ChannelList(SignalSource.CanalDigitalSatD | SignalSource.TvAndRadio, "Canal Digital Sat");
private readonly ChannelList digitalPlusChannels = new ChannelList(SignalSource.DigitalPlusD | SignalSource.TvAndRadio, "Canal+ Digital");
private readonly ChannelList cyfraPlusChannels = new ChannelList(SignalSource.CyfraPlusD | SignalSource.TvAndRadio, "Cyfra+ Digital");
private readonly Dictionary<int, decimal> avbtFrequency = new Dictionary<int, decimal>();
private readonly Dictionary<int, decimal> avbcFrequency = new Dictionary<int, decimal>();
private readonly Dictionary<int, decimal> dvbcFrequency = new Dictionary<int, decimal>();
private readonly Dictionary<int, decimal> dvbtFrequency = new Dictionary<int, decimal>();
private byte[] avbtFileContent;
private byte[] avbcFileContent;
private byte[] avbxFileContent;
private byte[] dvbtFileContent;
private byte[] dvbcFileContent;
private byte[] dvbxFileContent;
private byte[] dvbsFileContent;
private byte[] hdplusFileContent;
private byte[] primeFileContent;
private byte[] freesatFileContent;
private byte[] tivusatFileContent;
private byte[] canalDigitalFileContent;
private byte[] digitalPlusFileContent;
private byte[] cyfraPlusFileContent;
private ModelConstants c;
private Dictionary<int, string> serviceProviderNames;
#region ctor()
public ScmSerializer(string inputFile) : base(inputFile)
{
this.ReadConfigurationFromIniFile();
this.Features.ChannelNameEdit = true;
this.Features.CleanUpChannelData = true;
}
#endregion
#region DisplayName
public override string DisplayName { get { return "Samsung *.scm Loader"; } }
#endregion
#region ReadConfigurationFromIniFile()
private void ReadConfigurationFromIniFile()
{
string iniFile = Assembly.GetExecutingAssembly().Location.Replace(".dll", ".ini");
IniFile ini = new IniFile(iniFile);
foreach (var section in ini.Sections)
{
int idx = section.Name.IndexOf(":");
int len=0;
if (idx >= 0)
int.TryParse(section.Name.Substring(idx + 1), out len);
if (section.Name.StartsWith("Series:"))
modelConstants.Add(section.Name, new ModelConstants(section));
else if (section.Name.StartsWith("Analog:"))
analogMappings.AddMapping(len, new DataMapping(section));
else if (section.Name.StartsWith("DvbCT:"))
dvbctMappings.AddMapping(len, new DataMapping(section));
else if (section.Name.StartsWith("DvbS:"))
dvbsMappings.AddMapping(len, new DataMapping(section));
else if (section.Name.StartsWith("FineTune:"))
analogFineTuneMappings.AddMapping(len, new DataMapping(section));
else if (section.Name.StartsWith("AstraHDPlusD:"))
hdplusMappings.AddMapping(len, new DataMapping(section));
else if (section.Name.StartsWith("TransponderDataBase.dat:"))
transponderMappings.AddMapping(len, new DataMapping(section));
else if (section.Name.StartsWith("PTC:"))
ptccableMappings.AddMapping(len, new DataMapping(section));
else if (section.Name.StartsWith("ServiceProvider"))
serviceProviderMappings.AddMapping(len, new DataMapping(section));
}
}
#endregion
#region Load()
public override void Load()
{
if (AllBytesInFileAreZero())
return;
using (ZipFile zip = new ZipFile(this.FileName))
{
DetectModelConstants(zip);
DataRoot.SupportedFavorites = c.supportedFavorites;
DataRoot.SortedFavorites = c.SortedFavorites == FavoritesIndexMode.IndividuallySorted;
ReadAnalogFineTuning(zip);
ReadAnalogChannels(zip, "map-AirA", this.avbtChannels, out this.avbtFileContent, this.avbtFrequency);
ReadAnalogChannels(zip, "map-CableA", this.avbcChannels, out this.avbcFileContent, this.avbcFrequency);
ReadAnalogChannels(zip, "map-AirCableMixedA", this.avbxChannels, out this.avbxFileContent, this.avbcFrequency);
ReadDvbTransponderFrequenciesFromPtc(zip, "PTCAIR", this.dvbtFrequency);
ReadDvbServiceProviders(zip);
ReadDvbctChannels(zip, "map-AirD", this.dvbtChannels, out this.dvbtFileContent, this.dvbtFrequency);
ReadDvbTransponderFrequenciesFromPtc(zip, "PTCCABLE", this.dvbcFrequency);
ReadDvbctChannels(zip, "map-CableD", this.dvbcChannels, out this.dvbcFileContent, this.dvbcFrequency);
ReadDvbctChannels(zip, "map-AirCableMixedD", this.dvbxChannels, out this.dvbxFileContent, this.dvbcFrequency);
ReadDvbctChannels(zip, "map-CablePrime_D", this.primeChannels, out this.primeFileContent, this.dvbcFrequency);
ReadDvbctChannels(zip, "map-FreesatD", this.freesatChannels, out this.freesatFileContent, this.dvbcFrequency);
ReadDvbctChannels(zip, "map-TivusatD", this.tivusatChannels, out this.tivusatFileContent, this.dvbcFrequency);
ReadDvbctChannels(zip, "map-CanalDigitalSatD", this.canalDigitalChannels, out this.canalDigitalFileContent, this.dvbcFrequency);
ReadDvbctChannels(zip, "map-DigitalPlusD", this.digitalPlusChannels, out this.digitalPlusFileContent, this.dvbcFrequency);
ReadSatellites(zip);
ReadTransponder(zip, "TransponderDataBase.dat");
ReadTransponder(zip, "UserTransponderDataBase.dat");
ReadDvbsChannels(zip, "map-SateD", this.dvbsChannels, out this.dvbsFileContent, c.dvbsChannelLength);
ReadDvbsChannels(zip, "map-CyfraPlusD", this.cyfraPlusChannels, out this.cyfraPlusFileContent, c.cyfraPlusChannelSize);
ReadAstraHdPlusChannels(zip);
}
}
#endregion
#region AllBytesInFileAreZero()
private bool AllBytesInFileAreZero()
{
byte[] content = File.ReadAllBytes(this.FileName);
foreach (var b in content)
{
if (b != 0)
return false;
}
throw new FileLoadException(Resource.ScmSerializer_AllBytesInFileAreZero);
}
#endregion
#region DetectModelConstants()
private void DetectModelConstants(ZipFile zip)
{
if (DetectModelFromFileName()) return;
if (DetectModelFromCloneInfoFile(zip)) return;
if (DetectModelFromContentFileLengths(zip)) return;
throw new FileLoadException("Unable to determine TV model from file content or name");
}
#endregion
#region DetectModelFromFileName()
private bool DetectModelFromFileName()
{
string file = Path.GetFileName(this.FileName)??"";
System.Text.RegularExpressions.Regex regex =
new System.Text.RegularExpressions.Regex("channel_list_([A-Z]{2}[0-9]{2}|BD-)([A-Z])[0-9A-Z]+_([0-9]{4}).*\\.scm");
var match = regex.Match(file);
if (match.Success)
{
string series;
switch (match.Groups[3].Value)
{
case "1001": series = "C"; break;
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
break;
default:
return false;
}
if (this.modelConstants.TryGetValue("Series:" + series, out this.c))
return true;
}
return false;
}
#endregion
#region DetectModelFromCloneInfoFile()
private bool DetectModelFromCloneInfoFile(ZipFile zip)
{
byte[] cloneInfo = ReadFileContent(zip, "CloneInfo");
if (cloneInfo == null)
{
this.c = this.modelConstants["Series:B"];
return true;
}
if (cloneInfo.Length >= 9)
{
char series = (char) cloneInfo[8];
if (series == 'B') // 2013 B-series uses E/F-series format
series = 'F';
if (this.modelConstants.TryGetValue("Series:" + series, out this.c))
return true;
}
return false;
}
#endregion
#region DetectModelFromContentFileLengths()
private bool DetectModelFromContentFileLengths(ZipFile zip)
{
string[] candidates = {
DetectModelFromAirAOrCableA(zip),
DetectModelFromAirDOrCableD(zip),
DetectModelFromSateD(zip),
DetectModelFromTranspoderDatabase(zip),
DetectModelFromAstraHdPlusD(zip)
};
// note: E, F and B(2013) series use an identical format, so we only care about E here
string validCandidates = "BCDE";
foreach (var candidateList in candidates)
{
if (candidateList == null)
continue;
string newValidCandidats = "";
foreach (var candidate in candidateList)
{
if (validCandidates.Contains(candidate))
newValidCandidats += candidate;
}
validCandidates = newValidCandidats;
}
if (validCandidates.Length == 0)
return false;
this.modelConstants.TryGetValue("Series:" + validCandidates[0], out this.c);
return true;
}
#endregion
#region DetectModelFromAirAOrCableA()
private string DetectModelFromAirAOrCableA(ZipFile zip)
{
var entry = zip.GetEntry("map-AirA") ?? zip.GetEntry("map-CableA");
if (entry == null)
return null;
var candidates = "";
if (entry.Size % 28000 == 0)
candidates += "B";
if (entry.Size % 40000 == 0)
candidates += "C";
if (entry.Size % 64000 == 0)
candidates += "DE";
return candidates;
}
#endregion
#region DetectModelFromAirDOrCableD()
private string DetectModelFromAirDOrCableD(ZipFile zip)
{
var entry = zip.GetEntry("map-AirD") ?? zip.GetEntry("map-CableD") ?? zip.GetEntry("map-CablePrime_D") ?? zip.GetEntry("map-FreesatD")
?? zip.GetEntry("map-TivusatD") ?? zip.GetEntry("map-CanalDigitalSatD") ?? zip.GetEntry("map-DigitalPlusD");
if (entry == null)
return null;
var candidates = "";
if (entry.Size % 248 == 0)
candidates += "B";
if (entry.Size % 292 == 0)
candidates += "C";
if (entry.Size % 320 == 0)
candidates += "DE";
return candidates;
}
#endregion
#region DetectModelFromSateD()
private string DetectModelFromSateD(ZipFile zip)
{
var entry = zip.GetEntry("map-SateD");
if (entry == null)
return null;
var candidates = "";
if (entry.Size % 144 == 0)
candidates += "BC";
if (entry.Size % 172 == 0)
candidates += "D";
if (entry.Size % 168 == 0)
candidates += "E";
return candidates;
}
#endregion
#region DetectModelFromTranspoderDatabase()
private string DetectModelFromTranspoderDatabase(ZipFile zip)
{
var entry = zip.GetEntry("TransponderDatabase.dat");
if (entry == null)
return null;
var size = entry.Size - 4;
var candidates = "";
if (size%49 == 0)
candidates += "B";
if (size%45 == 0)
candidates += "CDE";
return candidates;
}
#endregion
#region DetectModelFromAstraHdPlusD()
private string DetectModelFromAstraHdPlusD(ZipFile zip)
{
var entry = zip.GetEntry("map-AstraHDPlusD");
if (entry == null)
return null;
var size = entry.Size;
string candidates = null;
if (size % 212 == 0)
candidates += "DE";
return candidates;
}
#endregion
#region ReadAnalogFineTuning()
private void ReadAnalogFineTuning(ZipFile zip)
{
int entrySize = c.avbtFineTuneLength;
if (entrySize == 0)
return;
byte[] data = ReadFileContent(zip, "FineTune");
if (data == null)
return;
var mapping = analogFineTuneMappings.GetMapping(c.avbtFineTuneLength);
mapping.SetDataPtr(data, 0);
int count = data.Length / c.avbtFineTuneLength;
for (int i = 0; i < count; i++)
{
bool isCable = mapping.GetFlag("offIsCable", "maskIsCable"); // HACK: this is just a guess
int slot = mapping.GetWord("offSlotNr");
float freq = mapping.GetFloat("offFrequency");
var dict = isCable ? avbcFrequency : avbtFrequency;
dict[slot] = (decimal)freq;
mapping.BaseOffset += c.avbtFineTuneLength;
}
}
#endregion
#region ReadAnalogChannels()
private void ReadAnalogChannels(ZipFile zip, string fileName, ChannelList list, out byte[] data, Dictionary<int,decimal> freq)
{
data = null;
int entrySize = c.avbtChannelLength;
if (entrySize == 0)
return;
data = ReadFileContent(zip, fileName);
if (data == null)
return;
this.DataRoot.AddChannelList(list);
var rawChannel = analogMappings.GetMapping(entrySize);
list.MaxChannelNameLength = rawChannel.Settings.GetInt("lenName")/2;
rawChannel.SetDataPtr(data, 0);
int count = data.Length / entrySize;
for (int slotIndex = 0; slotIndex < count; slotIndex++)
{
MapAnalogChannel(rawChannel, slotIndex, list, freq.TryGet(slotIndex));
rawChannel.BaseOffset += entrySize;
}
}
#endregion
#region MapAnalogChannel()
private void MapAnalogChannel(DataMapping rawChannel, int slotIndex, ChannelList list, decimal freq)
{
bool isCable = (list.SignalSource & SignalSource.Cable) != 0;
AnalogChannel ci = new AnalogChannel(slotIndex, isCable, rawChannel, freq, c.SortedFavorites);
if (!ci.InUse)
return;
this.DataRoot.AddChannel(list, ci);
}
#endregion
#region ReadDvbTransponderFrequenciesFromPtc()
private void ReadDvbTransponderFrequenciesFromPtc(ZipFile zip, string file, IDictionary<int, decimal> table)
{
byte[] data = ReadFileContent(zip, file);
if (data == null)
return;
var mapping = ptccableMappings.GetMapping(c.ptcLength);
mapping.SetDataPtr(data, 0);
int count = data.Length / c.ptcLength;
for (int i = 0; i < count; i++)
{
int transp = mapping.GetWord("offChannelTransponder");
float freq = mapping.GetFloat("offFrequency");
table[transp] = (decimal)freq;
mapping.BaseOffset += c.ptcLength;
}
}
#endregion
#region ReadDvbServiceProviders()
private void ReadDvbServiceProviders(ZipFile zip)
{
this.serviceProviderNames = new Dictionary<int, string>();
var data = ReadFileContent(zip, "ServiceProviders");
if (data == null) return;
if (data.Length % c.serviceProviderLength != 0) return;
var mapping = serviceProviderMappings.GetMapping(c.serviceProviderLength, false);
if (mapping == null) return;
int count = data.Length/c.serviceProviderLength;
var enc = new UnicodeEncoding(true, false);
var offName = mapping.Settings.GetInt("offName");
for (int i = 0; i < count; i++)
{
mapping.SetDataPtr(data, i*c.serviceProviderLength);
int source = mapping.GetWord("offSignalSource");
int index = mapping.GetWord("offIndex");
int len = System.Math.Min(mapping.GetWord("offLenName"), c.serviceProviderLength - offName);
var name = len < 2 ? "" : enc.GetString(data, mapping.BaseOffset + offName, len);
this.serviceProviderNames[(source << 16) + index] = name;
}
}
#endregion
#region ReadDvbctChannels()
private void ReadDvbctChannels(ZipFile zip, string fileName, ChannelList list, out byte[] data, Dictionary<int, decimal> frequency)
{
data = null;
int entrySize = c.dvbtChannelLength;
if (entrySize == 0)
return;
data = ReadFileContent(zip, fileName);
if (data == null)
return;
this.DataRoot.AddChannelList(list);
var source = list.SignalSource;
DataMapping rawChannel = dvbctMappings.GetMapping(entrySize);
list.MaxChannelNameLength = rawChannel.Settings.GetInt("lenName") / 2;
rawChannel.SetDataPtr(data, 0);
int count = data.Length / entrySize;
for (int slotIndex = 0; slotIndex < count; slotIndex++)
{
DigitalChannel ci = new DigitalChannel(slotIndex, source, rawChannel, frequency, c.SortedFavorites, this.serviceProviderNames);
if (ci.InUse && !ci.IsDeleted && ci.OldProgramNr > 0)
this.DataRoot.AddChannel(list, ci);
rawChannel.BaseOffset += entrySize;
}
}
#endregion
#region ReadSatellites()
private void ReadSatellites(ZipFile zip)
{
byte[] data = ReadFileContent(zip, "SatDataBase.dat");
if (data == null || data.Length < 4)
return;
this.SatDatabaseVersion = System.BitConverter.ToInt32(data, 0);
SatelliteMapping satMapping = new SatelliteMapping(data, 4);
int count = data.Length/this.c.dvbsSatelliteLength;
for (int i = 0; i < count; i++)
{
if (satMapping.MagicMarker == 'U')
{
string location = string.Format("{0}.{1}{2}",
satMapping.Longitude / 10, satMapping.Longitude % 10, satMapping.IsEast ? "E" : "W");
Satellite satellite = new Satellite(satMapping.SatelliteNr);
satellite.Name = satMapping.Name;
satellite.OrbitalPosition = location;
this.DataRoot.Satellites.Add(satMapping.SatelliteNr, satellite);
}
else if (satMapping.MagicMarker != 'E')
throw new FileLoadException("Unknown SatDataBase.dat format");
satMapping.BaseOffset += this.c.dvbsSatelliteLength;
}
}
#endregion
#region ReadTransponder()
private void ReadTransponder(ZipFile zip, string fileName)
{
byte[] data = ReadFileContent(zip, fileName);
if (data == null)
return;
int count = (data.Length-4)/c.dvbsTransponderLength;
var mapping = this.transponderMappings.GetMapping(c.dvbsTransponderLength);
for (int i=0; i<count; i++)
{
mapping.SetDataPtr(data, 4 + i * c.dvbsTransponderLength);
if (mapping.GetByte("offMagicByte") == 0)
continue;
int transponderNr = (int)mapping.GetDword("offTransponderIndex");
if (transponderNr == 0)
continue;
int satelliteNr = (int)mapping.GetDword("offSatelliteIndex");
var sat = this.DataRoot.Satellites.TryGet(satelliteNr);
if (sat == null)
{
DataRoot.Warnings.Append(string.Format("Transponder #{0} references invalid satellite #{1}",
transponderNr, satelliteNr));
continue;
}
Transponder transponder = new Transponder(transponderNr);
transponder.FrequencyInMhz = (uint)(mapping.GetDword("offFrequency")/1000);
transponder.SymbolRate = (int) (mapping.GetDword("offSymbolRate")/1000);
this.DataRoot.AddTransponder(sat, transponder);
}
}
#endregion
#region ReadDvbsChannels()
private void ReadDvbsChannels(ZipFile zip, string filename, ChannelList channels, out byte[] fileContent, int entrySize)
{
fileContent = ReadFileContent(zip, filename);
if (fileContent == null)
return;
this.DataRoot.AddChannelList(channels);
int count = fileContent.Length/entrySize;
DataMapping mapping = dvbsMappings.GetMapping(entrySize);
channels.MaxChannelNameLength = mapping.Settings.GetInt("lenName") / 2;
mapping.SetDataPtr(fileContent, 0);
for (int slotIndex = 0; slotIndex < count; slotIndex++)
{
SatChannel ci = new SatChannel(slotIndex, channels.SignalSource, mapping, this.DataRoot, c.SortedFavorites, this.serviceProviderNames);
if (ci.InUse)
this.DataRoot.AddChannel(channels, ci);
mapping.BaseOffset += entrySize;
}
}
#endregion
#region ReadAstraHdPlusChannels()
private void ReadAstraHdPlusChannels(ZipFile zip)
{
this.hdplusFileContent = ReadFileContent(zip, "map-AstraHDPlusD");
if (hdplusFileContent == null || c.hdplusChannelLength == 0)
return;
this.DataRoot.AddChannelList(this.hdplusChannels);
int entrySize = c.hdplusChannelLength;
int count = hdplusFileContent.Length / entrySize;
DataMapping mapping = hdplusMappings.GetMapping(entrySize);
mapping.SetDataPtr(hdplusFileContent, 0);
for (int slotIndex = 0; slotIndex < count; slotIndex++)
{
SatChannel ci = new SatChannel(slotIndex, SignalSource.AstraHdPlus, mapping, this.DataRoot, c.SortedFavorites, this.serviceProviderNames);
if (ci.InUse)
this.DataRoot.AddChannel(this.hdplusChannels, ci);
mapping.BaseOffset += entrySize;
}
}
#endregion
#region ReadFileContent()
private static byte[] ReadFileContent(ZipFile zip, string fileName)
{
var entry = zip.GetEntry(fileName);
if (entry == null)
return null;
byte[] data = new byte[entry.Size];
using (var stream = zip.GetInputStream(entry))
{
stream.Read(data, 0, data.Length);
}
return data;
}
#endregion
#region Save()
public override void Save(string tvOutputFile)
{
if (tvOutputFile != this.FileName)
{
File.Copy(this.FileName, tvOutputFile, true);
this.FileName = tvOutputFile;
}
using (ZipFile zip = new ZipFile(tvOutputFile))
{
zip.BeginUpdate();
this.SaveChannels(zip, "map-AirA", this.avbtChannels, this.avbtFileContent);
this.SaveChannels(zip, "map-CableA", this.avbcChannels, this.avbcFileContent);
this.SaveChannels(zip, "map-AirCableMixedA", this.avbxChannels, this.avbxFileContent);
this.SaveChannels(zip, "map-AirD", this.dvbtChannels, this.dvbtFileContent);
this.SaveChannels(zip, "map-CableD", this.dvbcChannels, this.dvbcFileContent);
this.SaveChannels(zip, "map-AirCableMixedD", this.dvbxChannels, this.dvbxFileContent);
this.SaveChannels(zip, "map-SateD", this.dvbsChannels, this.dvbsFileContent);
this.SaveChannels(zip, "map-AstraHDPlusD", this.hdplusChannels, this.hdplusFileContent);
this.SaveChannels(zip, "map-CablePrime_D", this.primeChannels, this.primeFileContent);
this.SaveChannels(zip, "map-FreesatD", this.freesatChannels, this.freesatFileContent);
this.SaveChannels(zip, "map-TivusatD", this.tivusatChannels, this.tivusatFileContent);
this.SaveChannels(zip, "map-CanalDigitalSatD", this.canalDigitalChannels, this.canalDigitalFileContent);
this.SaveChannels(zip, "map-DigitalPlusD", this.digitalPlusChannels, this.digitalPlusFileContent);
this.SaveChannels(zip, "map-CyfraPlusD", this.cyfraPlusChannels, this.cyfraPlusFileContent);
zip.CommitUpdate();
}
}
#endregion
#region SaveChannels()
private void SaveChannels(ZipFile zip, string fileName, ChannelList channels, byte[] fileContent)
{
if (fileContent == null)
return;
zip.Delete(fileName);
string tempFilePath = Path.GetTempFileName();
using (var stream = new FileStream(tempFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
this.WriteChannels(channels, fileContent, stream);
}
zip.Add(tempFilePath, fileName);
}
#endregion
#region WriteChannels()
private void WriteChannels(ChannelList list, byte[] fileContent, FileStream stream)
{
foreach (var channel in list.Channels)
{
channel.UpdateRawData();
channel.OldProgramNr = channel.NewProgramNr;
}
stream.Write(fileContent, 0, fileContent.Length);
}
#endregion
// -------- cleanup --------
#region CleanUpChannelData()
public override string CleanUpChannelData()
{
StringBuilder log = new StringBuilder();
RemoveChannelsWithServiceType0(log);
RemoveDuplicateAnalogList(log);
return log.ToString();
}
private void RemoveChannelsWithServiceType0(StringBuilder log)
{
foreach (var list in this.DataRoot.ChannelLists)
{
if ((list.SignalSource & SignalSource.Digital) == 0)
continue;
var listOfChannels = new List<ChannelInfo>(list.Channels);
foreach (var chan in listOfChannels)
{
ScmChannelBase channel = chan as ScmChannelBase;
if (channel == null) // ignore proxy channels (which only exist in loaded reference list)
continue;
if (channel.ServiceType == 0)
{
channel.EraseRawData();
list.Channels.Remove(channel);
log.AppendFormat("{0} channel at index {1} (Pr# {2} \"{3}\") was erased due to invalid service type 0\r\n",
list.ShortCaption, channel.RecordIndex, channel.OldProgramNr, channel.Name);
}
}
}
}
private void RemoveDuplicateAnalogList(StringBuilder log)
{
if (this.avbtChannels.Count == 0 || this.avbcChannels.Count == 0)
return;
// TODO
}
#endregion
// ------- testing -----------
internal string Series { get { return c.series; } }
internal int AnalogChannelLength { get { return c.avbtChannelLength; } }
internal int DigitalChannelLength { get { return c.dvbtChannelLength; } }
internal int SatChannelLength { get { return c.dvbsChannelLength; } }
internal int HdPlusChannelLength { get { return c.hdplusChannelLength; } }
internal int SatDatabaseVersion { get; private set; }
}
}

View File

@@ -0,0 +1,15 @@
using ChanSort.Api;
namespace ChanSort.Loader.Samsung
{
public class ScmSerializerPlugin : ISerializerPlugin
{
public string PluginName { get { return "Samsung *.scm"; } }
public string FileFilter { get { return "*.scm"; } }
public SerializerBase CreateSerializer(string inputFile)
{
return new ScmSerializer(inputFile);
}
}
}