- cleanup (renamed directories to match project structure)

- tested and fixed Samsung favorites and locks for C,D,AstraHD
This commit is contained in:
hbeham
2013-04-03 15:01:53 +02:00
parent c0e0268fdf
commit 8d22767ec2
100 changed files with 23 additions and 3233 deletions

View File

@@ -0,0 +1,29 @@
using ChanSort.Api;
namespace ChanSort.Loader.ScmFile
{
internal class AnalogChannel : ScmChannelBase
{
private const string _Skip = "Skip";
private const string _Frequency = "offFrequency";
#region ctor()
public AnalogChannel(int slot, SignalSource signalSource, DataMapping mapping, decimal freq) : base(mapping)
{
this.InitCommonData(slot, signalSource, mapping);
this.FreqInMhz = (decimal)mapping.GetFloat(_Frequency); // 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.Skip = mapping.GetFlag(_Skip);
this.ChannelOrTransponder = "";
}
#endregion
}
}

View File

@@ -0,0 +1,99 @@
<?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.ScmFile</RootNamespace>
<AssemblyName>ChanSort.Loader.ScmFile</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile>Client</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="ModelConstants.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<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.ScmFile.ini">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</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,315 @@
[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
[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
[Analog:28]
; map-AirA and map-CableA for B series
offInUse = 0
maskInUse = 0x02
offProgramNr = 4
offNameLength =
offName = 12
lenName = 12
offFavorites = 26
offChecksum = 27
[Analog:40]
; map-AirA and map-CableA for C series
offInUse = 1
maskInUse = 0x01
offSkip = 2
maskSkip = 0x01
offLock = 6
maskLock = 0x01
offTuned = 8
maskTuned = 0x01
offProgramNr = 9
offSlotNr = 16
offNameLength = 18
offName = 20
lenName = 12
offFrequency = 32
offFavorites = 38
offChecksum = 39
[Analog:64]
; map-AirA and map-CableA for D,E series
offInUse = 1
maskInUse = 0x01
offSkip = 2
maskSkip = 0x01
offLock = 6
maskLock = 0x01
offTuned = 8
maskTuned = 0x01
offProgramNr = 9
offSlotNr = 16
offNameLength = 18
offName = 20
lenName = 12
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
[DvbCT:248]
; map-AirD and map-CableD for B series
offProgramNr = 0
offVideoPid = 2
offPcrPid = 4
offServiceId = 10
offStatus = 8
offQam = 7
offServiceType = 9
offEncrypted = 23
maskEncrypted = 0xff
offSymbolRate = 32
offLock = 244
maskLock = 0x01
offOriginalNetworkId = 12
offNetworkId = 14
offBouquet = 34
offChannelTransponder = 26
offLogicalProgramNr = 28
offTransportStreamId = 36
offName = 44
lenName = 100
offFavorites = 246
offChecksum = 247
[DvbCT:292]
; map-AirD and map-CableD for C series
offProgramNr = 0
offVideoPid = 2
offPcrPid = 4
offServiceId = 6
offStatus =
offQam = 12
offBandwidth = 14
offServiceType = 15
offCodec = 16
offHRes = 20
offVRes = 22
offEncrypted = 24
maskEncrypted = 0xff
offFrameRate = 25
offSymbolRate = 28
offLock = 31
maskLock = 0x01
offOriginalNetworkId = 32
offNetworkId = 34
offServiceProviderId = 40
offChannelTransponder = 42
offLogicalProgramNr = 44
offTransportStreamId = 48
offName = 64
lenName = 200
offShortName = 264
lenShortName = 18
offVideoFormat = 282
offFavorites = 290
offChecksum = 291
[DvbCT:320]
; map-AirD and map-CableD for D and E series
offProgramNr = 0
offVideoPid = 2
offPcrPid = 4
offServiceId = 6
offStatus =
offQam = 12
offBandwidth = 14
offServiceType = 15
offCodec = 16
offHRes = 20
offVRes = 22
offEncrypted = 24
maskEncrypted = 0xff
offFrameRate = 25
offSymbolRate = 28
offLock = 31
maskLock = 0x01
offOriginalNetworkId = 32
offNetworkId = 34
offServiceProviderId = 40
offChannelTransponder = 42
offLogicalProgramNr = 44
offTransportStreamId = 48
offName = 64
lenName = 200
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
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
offBouquet = 138
offFavorites = 142
offChecksum = 143
[DvbS:172]
; map-SateD for D Series
offProgramNr = 0
offVideoPid = 2
offPcrPid = 4
offInUse = 7
maskInUse = 0x01
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
offBouquet = 138
offFavorites = 140,144,148,152,156
offChecksum = 171
[DvbS:168]
; map-SateD for E Series
offProgramNr = 0
offVideoPid = 2
offPcrPid = 4
offInUse = 7
maskInUse = 0x01
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
offBouquet = 138
offFavorites = 140,144,148,152,156
offChecksum = 167
[AstraHDPlusD:212]
; map-AstraHDPlusD for D and E Series
offProgramNr = 0,20
offVideoPid=2
offPcrId=4
offInUse = 7
maskInUse = 0x01
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,24 @@
using System.Collections.Generic;
using ChanSort.Api;
namespace ChanSort.Loader.ScmFile
{
public class DigitalChannel : ScmChannelBase
{
private const string _ChannelOrTransponder = "offChannelTransponder";
public DigitalChannel(int slot, SignalSource signalSource, DataMapping data, IDictionary<int, decimal> transpFreq) : base(data)
{
this.InitCommonData(slot, signalSource, data);
this.InitDvbData(data);
int transp = data.GetByte(_ChannelOrTransponder);
decimal freq = transpFreq.TryGet(transp);
if (freq == 0)
freq = transp*8 + 106;
this.ChannelOrTransponder = ((int)(freq-106)/8).ToString();
this.FreqInMhz = freq;
}
}
}

View File

@@ -0,0 +1,36 @@
using ChanSort.Api;
namespace ChanSort.Loader.ScmFile
{
internal class ModelConstants
{
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 ModelConstants(IniFile.Section iniSection)
{
this.avbtChannelLength = iniSection.GetInt("map-AirA");
this.dvbtChannelLength = iniSection.GetInt("map-AirD");
this.dvbsChannelLength = iniSection.GetInt("map-SateD");
this.ptcLength = iniSection.GetInt("PTC");
this.hdplusChannelLength = iniSection.GetInt("map-AstraHDPlusD");
this.dvbsSatelliteLength = iniSection.GetInt("SatDataBase.dat");
this.dvbsTransponderLength = iniSection.GetInt("TransponderDataBase.dat");
this.avbtFineTuneLength = iniSection.GetInt("FineTune");
this.dvbtFineTuneLength = iniSection.GetInt("FineTune_Digital");
int numFavorites = iniSection.GetInt("Favorites");
int mask = 0;
for (int i = 0; i < numFavorites; i++)
mask = (mask << 1) | 1;
this.supportedFavorites = (Favorites)mask;
}
}
}

View File

@@ -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("ChanSort.Loader.ScmFile")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ChanSort.Loader.ScmFile")]
[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,34 @@
using ChanSort.Api;
namespace ChanSort.Loader.ScmFile
{
class SatChannel : ScmChannelBase
{
private const string _TransponderIndex = "offTransponderIndex";
public SatChannel(int slot, DataMapping data, DataRoot dataRoot) : base(data)
{
this.InitCommonData(slot, SignalSource.DvbS, data);
if (!this.InUse)
return;
this.InitDvbData(data);
int transponderIndex = data.GetWord(_TransponderIndex);
Transponder transponder = dataRoot.Transponder.TryGet(transponderIndex);
if (transponder == null)
{
dataRoot.Warnings.AppendLine("Invalid transponder index: " + 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 = "";
}
}
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Text;
namespace ChanSort.Loader.ScmFile
{
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,162 @@
using System.Text;
using ChanSort.Api;
namespace ChanSort.Loader.ScmFile
{
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 _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 static readonly Encoding Utf16BigEndian = new UnicodeEncoding(true, false);
protected readonly DataMapping mapping;
protected readonly byte[] rawData;
internal readonly int baseOffset;
internal bool InUse { get; set; }
protected ScmChannelBase(DataMapping data)
{
this.mapping = data;
this.rawData = data.Data;
this.baseOffset = data.BaseOffset;
this.mapping.DefaultEncoding = Utf16BigEndian;
}
#region InitCommonData()
protected void InitCommonData(int slot, SignalSource signalSource, DataMapping data)
{
this.InUse = data.GetFlag(_InUse);
this.RecordIndex = slot;
this.RecordOrder = slot;
this.SignalSource = signalSource;
this.SignalType = SignalType.Mixed;
this.OldProgramNr = 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);
}
#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
byte fav = 0;
byte mask = 0x01;
foreach (int off in offsets)
{
if ((System.BitConverter.ToInt32(this.rawData, baseOffset + off) + 1) > 1) // -1 and 0 mean "not set"
fav |= mask;
mask <<= 1;
}
return (Favorites) fav;
}
#endregion
#region InitDvbData()
protected void InitDvbData(DataMapping data)
{
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);
}
#endregion
#region GetSignalType()
protected SignalType GetSignalType(uint programNr)
{
if ((programNr & 0x4000) != 0)
return SignalType.Radio;
return SignalType.Tv;
}
#endregion
#region UpdateRawData()
public override void UpdateRawData()
{
mapping.SetDataPtr(this.rawData, this.baseOffset);
mapping.SetWord(_ProgramNr, this.NewProgramNr);
if (this.IsNameModified)
{
mapping.SetString(_Name, this.Name, mapping.Settings.GetInt("lenName"));
mapping.SetByte(_NameLength, this.Name.Length * 2);
this.IsNameModified = false;
}
this.UpdateRawFavorites();
mapping.SetFlag(_Lock, this.Lock);
if (this.NewProgramNr == 0)
mapping.SetFlag(_Deleted, true);
this.UpdateChecksum();
}
#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
byte fav = (byte)this.Favorites;
byte mask = 0x01;
foreach (int off in offsets)
{
this.rawData[baseOffset + off + 0] = (byte)((fav & mask) == 0 ? 0 : 1);
this.rawData[baseOffset + off + 1] = 0;
this.rawData[baseOffset + off + 2] = 0;
this.rawData[baseOffset + off + 3] = 0;
mask <<= 1;
}
}
#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,570 @@
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Linq;
using System.Windows.Forms;
using ChanSort.Api;
using ICSharpCode.SharpZipLib.Zip;
namespace ChanSort.Loader.ScmFile
{
class ScmSerializer : SerializerBase
{
public struct ChannelAndFreq
{
public int Channel;
public decimal Frequency;
public ChannelAndFreq(int ch, decimal freq)
{
this.Channel = ch;
this.Frequency = freq;
}
}
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>("AstraHDPlus");
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 ChannelList avbtChannels = new ChannelList(SignalSource.AnalogT, SignalType.Mixed);
private readonly ChannelList avbcChannels = new ChannelList(SignalSource.AnalogC, SignalType.Mixed);
private readonly ChannelList dvbcChannels = new ChannelList(SignalSource.DvbC, SignalType.Mixed);
private readonly ChannelList dvbtChannels = new ChannelList(SignalSource.DvbT, SignalType.Mixed);
private readonly ChannelList dvbsChannels = new ChannelList(SignalSource.DvbS, SignalType.Mixed);
private readonly ChannelList hdplusChannels = new ChannelList(SignalSource.HdPlusD, SignalType.Mixed);
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[] dvbtFileContent;
private byte[] dvbcFileContent;
private byte[] dvbsFileContent;
private byte[] hdplusFileContent;
private ModelConstants c;
#region ctor()
public ScmSerializer(string inputFile) : base(inputFile)
{
this.ReadConfigurationFromIniFile();
this.Features.ChannelNameEdit = 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));
}
}
#endregion
#region Load()
public override void Load()
{
using (ZipFile zip = new ZipFile(this.FileName))
{
DetectModelConstants(zip);
DataRoot.SupportedFavorites = c.supportedFavorites;
ReadAnalogFineTuning(zip);
ReadAnalogChannels(zip, "map-AirA", this.avbtChannels, out this.avbtFileContent, this.avbtFrequency);
ReadAnalogChannels(zip, "map-CableA", this.avbcChannels, out this.avbcFileContent, this.avbcFrequency);
ReadDvbTransponderFrequenciesFromPtc(zip, "PTCAIR", this.dvbtFrequency);
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);
ReadSatellites(zip);
ReadTransponder(zip, "TransponderDataBase.dat");
ReadTransponder(zip, "UserTransponderDataBase.dat");
ReadDvbsChannels(zip);
ReadAstraHdPlusChannels(zip);
}
}
#endregion
#region DetectModelConstants()
private void DetectModelConstants(ZipFile zip)
{
if (DetectModelFromCloneInfoFile(zip)) return;
if (DetectModelFromContentFileLengths(zip)) return;
if (DetectModelFromFileName()) return;
throw new IOException("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}([A-Z])[0-9A-Z]+_[0-9]+\\.scm");
var match = regex.Match(file);
if (match.Success)
{
string series = match.Groups[1].Value;
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 (this.modelConstants.TryGetValue("Series:" + series, out this.c))
return true;
}
return false;
}
#endregion
#region DetectModelFromContentFileLengths()
private bool DetectModelFromContentFileLengths(ZipFile zip)
{
string[] candidates = new[]
{
DetectModelFromAirAOrCableA(zip),
DetectModelFromAirDOrCableD(zip),
DetectModelFromSateD(zip),
DetectModelFromTranspoderDatabase(zip)
};
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 != 1)
return false;
this.modelConstants.TryGetValue("Series:" + validCandidates, 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");
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 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);
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)
{
AnalogChannel ci = new AnalogChannel(slotIndex, list.SignalSource, rawChannel, freq);
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 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);
DataMapping rawChannel = dvbctMappings.GetMapping(entrySize);
rawChannel.SetDataPtr(data, 0);
int count = data.Length / entrySize;
for (int slotIndex = 0; slotIndex < count; slotIndex++)
{
DigitalChannel ci = new DigitalChannel(slotIndex, list.SignalSource, rawChannel, frequency);
if (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)
return;
SatelliteMapping satMapping = new SatelliteMapping(data, 4);
int count = data.Length/this.c.dvbsSatelliteLength;
for (int i = 0; i < count; i++)
{
if (satMapping.MagicMarker != 0x55)
throw new IOException("Unknown SatDataBase.dat format");
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);
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)
{
this.dvbsFileContent = ReadFileContent(zip, "map-SateD");
if (this.dvbsFileContent == null)
return;
this.DataRoot.AddChannelList(this.dvbsChannels);
int entrySize = c.dvbsChannelLength;
int count = this.dvbsFileContent.Length/entrySize;
DataMapping mapping = dvbsMappings.GetMapping(entrySize);
mapping.SetDataPtr(dvbsFileContent, 0);
for (int slotIndex = 0; slotIndex < count; slotIndex++)
{
SatChannel ci = new SatChannel(slotIndex, mapping, this.DataRoot);
if (ci.InUse)
this.DataRoot.AddChannel(this.dvbsChannels, 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, mapping, this.DataRoot);
if (ci.InUse)
this.hdplusChannels.AddChannel(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, string csvOutputFile)
{
if (tvOutputFile != this.FileName)
{
File.Copy(this.FileName, tvOutputFile);
this.FileName = tvOutputFile;
}
using (ZipFile zip = new ZipFile(tvOutputFile))
{
zip.BeginUpdate();
this.SaveChannels(zip, "map-AirA", this.avbtChannels, ref this.avbtFileContent);
this.SaveChannels(zip, "map-CableA", this.avbcChannels, ref this.avbcFileContent);
this.SaveChannels(zip, "map-AirD", this.dvbtChannels, ref this.dvbtFileContent);
this.SaveChannels(zip, "map-CableD", this.dvbcChannels, ref this.dvbcFileContent);
this.SaveChannels(zip, "map-SateD", this.dvbsChannels, ref this.dvbsFileContent);
this.SaveChannels(zip, "map-AstraHDPlusD", this.hdplusChannels, ref this.hdplusFileContent);
zip.CommitUpdate();
}
}
#endregion
#region SaveChannels()
private void SaveChannels(ZipFile zip, string fileName, ChannelList channels, ref 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);
stream.Flush();
stream.Seek(0, SeekOrigin.Begin);
int size = (int)new FileInfo(tempFilePath).Length;
fileContent = new byte[size];
stream.Read(fileContent, 0, size);
}
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
public override void ShowDeviceSettingsForm(object parentWindow)
{
MessageBox.Show((Form) parentWindow, "Sorry, ChanSort currently doesn't support any settings for your TV model.",
"Device Settings",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}

View File

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