- 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,91 @@
<?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>{68DA8072-3A29-4076-9F64-D66F38349585}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ChanSort.Loader.Panasonic</RootNamespace>
<AssemblyName>ChanSort.Loader.Panasonic</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</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>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
</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>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data.SQLite, Version=1.0.84.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\DLL\System.Data.SQLite.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="DbChannel.cs" />
<Compile Include="Serializer.cs" />
<Compile Include="SerializerPlugin.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Service Include="{94E38DFF-614B-4cbd-B67C-F211BB35CE8B}" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ChanSort.Api\ChanSort.Api.csproj">
<Project>{DCCFFA08-472B-4D17-BB90-8F513FC01392}</Project>
<Name>ChanSort.Api</Name>
</ProjectReference>
</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,238 @@
using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.Text;
using ChanSort.Api;
namespace ChanSort.Loader.Panasonic
{
internal class DbChannel : ChannelInfo
{
internal int Bits;
internal byte[] RawName;
#region ctor()
internal DbChannel(SQLiteDataReader r, IDictionary<string, int> field, DataRoot dataRoot, Encoding encoding)
{
this.RecordIndex = r.GetInt32(field["rowid"]);
this.RecordOrder = r.GetInt32(field["major_channel"]);
this.OldProgramNr = r.GetInt32(field["major_channel"]);
int ntype = r.GetInt32(field["ntype"]);
if (ntype == 1)
{
this.SignalSource |= SignalSource.DvbS;
if (r.GetInt32(field["ya_svcid"]) >= 0)
this.SignalSource |= SignalSource.Freesat;
}
else if (ntype == 2)
this.SignalSource |= SignalSource.DvbT;
else if (ntype == 3)
this.SignalSource |= SignalSource.DvbC;
else if (ntype == 10)
this.SignalSource |= SignalSource.AnalogT | SignalSource.Tv;
else if (ntype == 14)
this.SignalSource |= SignalSource.AnalogC | SignalSource.Tv;
else if (ntype == 15)
this.SignalSource |= SignalSource.SatIP;
byte[] buffer = new byte[1000];
var len = r.GetBytes(field["delivery"], 0, buffer, 0, 1000);
this.AddDebug(buffer, 0, (int) len);
this.Skip = r.GetInt32(field["skip"]) != 0;
this.Encrypted = r.GetInt32(field["free_CA_mode"]) != 0;
this.Lock = r.GetInt32(field["child_lock"]) != 0;
this.ParseFavorites(r, field);
this.ReadNamesWithEncodingDetection(r, field, encoding);
if (ntype == 10 || ntype == 14)
this.ReadAnalogData(r, field);
else
this.ReadDvbData(r, field, dataRoot, buffer);
}
#endregion
#region ParseFavorites
private void ParseFavorites(SQLiteDataReader r, IDictionary<string, int> field)
{
for (int i = 0; i < 4; i++)
{
int favIndex = r.GetInt32(field["profile" + (i + 1) + "index"]);
if (favIndex > 0)
{
this.Favorites |= (Favorites) (1 << i);
this.FavIndex[i] = favIndex;
}
}
}
#endregion
#region ReadAnalogData()
private void ReadAnalogData(SQLiteDataReader r, IDictionary<string, int> field)
{
this.FreqInMhz = r.IsDBNull(field["freq"]) ? 0 : (decimal)r.GetInt32(field["freq"]) / 1000;
this.ChannelOrTransponder = Tools.GetAnalogChannelNumber((int)this.FreqInMhz);
}
#endregion
#region ReadDvbData()
protected void ReadDvbData(SQLiteDataReader r, IDictionary<string, int> field, DataRoot dataRoot, byte[] delivery)
{
int stype = r.GetInt32(field["stype"]);
this.SignalSource |= LookupData.Instance.IsRadioOrTv(stype);
this.ServiceType = stype;
int freq = r.GetInt32(field["freq"]);
if ((this.SignalSource & SignalSource.Sat) != 0)
{
// ReSharper disable PossibleLossOfFraction
this.FreqInMhz = freq/10;
// ReSharper restore PossibleLossOfFraction
int satId = r.GetInt32(field["physical_ch"]) >> 12;
var sat = dataRoot.Satellites.TryGet(satId);
if (sat != null)
{
this.Satellite = sat.Name;
this.SatPosition = sat.OrbitalPosition;
}
if (delivery.Length >= 7)
{
this.SymbolRate = (delivery[5] >> 4)*10000 + (delivery[5] & 0x0F)*1000 +
(delivery[6] >> 4)*100 + (delivery[6] & 0x0F)*10;
}
}
else
{
freq /= 1000;
this.FreqInMhz = freq;
this.ChannelOrTransponder = LookupData.Instance.GetDvbtTransponder(freq).ToString();
this.Satellite = (this.SignalSource & SignalSource.Antenna) != 0 ? "DVB-T" : "DVB-C";
}
this.OriginalNetworkId = r.GetInt32(field["onid"]);
this.TransportStreamId = r.GetInt32(field["tsid"]);
this.ServiceId = r.GetInt32(field["sid"]);
}
#endregion
#region ReadNamesWithEncodingDetection()
/// <summary>
/// Character encoding is a mess here. Code pages mixed with UTF-8 and raw data
/// </summary>
private void ReadNamesWithEncodingDetection(SQLiteDataReader r, IDictionary<string, int> field, Encoding encoding)
{
byte[] buffer = new byte[100];
int len = (int)r.GetBytes(field["sname"], 0, buffer, 0, buffer.Length);
int end = Array.IndexOf<byte>(buffer, 0, 0, len);
if (end >= 0)
len = end;
this.RawName = new byte[len];
Array.Copy(buffer, 0, this.RawName, 0, len);
this.ChangeEncoding(encoding);
}
#endregion
#region ChangeEncoding()
public override void ChangeEncoding(Encoding encoding)
{
// the encoding of channel names is a complete mess:
// it can be UTF-8
// it can be as specified by the DVB-encoding with a valid code page selector byte
// it can have a DVB-encoded code page selector, but ignores the CP and use UTF-8 regardless
// it can be code page encoded without any clue to what the code page is
// it can have DVB-control characters inside an UTF-8 stream
if (RawName.Length == 0)
return;
int startOffset;
int bytesPerChar;
if (!GetRecommendedEncoding(ref encoding, out startOffset, out bytesPerChar))
return;
// single byte code pages might have UTF-8 code mixed in, so we have to parse it manually
StringBuilder sb = new StringBuilder();
for (int i = startOffset; i < this.RawName.Length; i+=bytesPerChar)
{
byte c = this.RawName[i];
byte c2 = i + 1 < this.RawName.Length ? this.RawName[i + 1] : (byte)0;
if (c < 0xA0)
sb.Append((char)c);
else if (bytesPerChar == 1 && c >= 0xC0 && c <= 0xDF && c2 >= 0x80 && c2 <= 0xBF) // 2 byte UTF-8
{
sb.Append((char)(((c & 0x1F) << 6) | (c2 & 0x3F)));
++i;
}
else
sb.Append(encoding.GetString(this.RawName, i, bytesPerChar));
}
string longName, shortName;
this.GetChannelNames(sb.ToString(), out longName, out shortName);
this.Name = longName;
this.ShortName = shortName;
}
#endregion
#region GetRecommendedEncoding()
private bool GetRecommendedEncoding(ref Encoding encoding, out int startOffset, out int bytesPerChar)
{
startOffset = 0;
bytesPerChar = 1;
if (RawName[0] < 0x10) // single byte character sets
{
encoding = DvbStringDecoder.GetEncoding(RawName[0]);
startOffset = 1;
}
else if (RawName[0] == 0x10) // prefix for 16 bit code page ID with single byte character sets
{
if (RawName.Length < 3) return false;
encoding = DvbStringDecoder.GetEncoding(0x100000 + RawName[1]*256 + RawName[2]);
startOffset = 3;
}
else if (RawName[0] == 0x15) // UTF-8
{
encoding = Encoding.UTF8;
startOffset = 1;
}
else if (RawName[0] < 0x20) // various 2-byte character sets
{
encoding = DvbStringDecoder.GetEncoding(RawName[0]);
startOffset = 1;
bytesPerChar = 2;
}
return true;
}
#endregion
#region GetChannelNames()
private void GetChannelNames(string name, out string longName, out string shortName)
{
StringBuilder sbLong = new StringBuilder();
StringBuilder sbShort = new StringBuilder();
bool inShort = false;
foreach (char c in name)
{
if (c < 0x20)
continue;
if (c == 0x86 || c == '\uE086')
inShort = true;
else if (c == 0x87 || c == '\uE087')
inShort = false;
if (c >= 0x80 && c <= 0x9F || c>='\uE080' && c<='\uE09F')
continue;
if (inShort)
sbShort.Append(c);
sbLong.Append(c);
}
longName = sbLong.ToString();
shortName = sbShort.ToString();
}
#endregion
}
}

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.Panasonic")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ChanSort.Loader.Panasonic")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[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("bcd581a8-8959-404c-b7a8-e43f512eec03")]
// 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,705 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.IO;
using System.Text;
using System.Windows.Forms;
using ChanSort.Api;
namespace ChanSort.Loader.Panasonic
{
class Serializer : SerializerBase
{
private const string ERR_FileFormatOrEncryption = "File uses an unknown format or encryption";
private static readonly int[] headerCypherTable;
private readonly ChannelList avbtChannels = new ChannelList(SignalSource.AnalogT | SignalSource.Tv | SignalSource.Radio, "Analog Antenna");
private readonly ChannelList avbcChannels = new ChannelList(SignalSource.AnalogC | SignalSource.Tv | SignalSource.Radio, "Analog Cable");
private readonly ChannelList dvbtChannels = new ChannelList(SignalSource.DvbT | SignalSource.Tv | SignalSource.Radio, "DVB-T");
private readonly ChannelList dvbcChannels = new ChannelList(SignalSource.DvbC | SignalSource.Tv | SignalSource.Radio, "DVB-C");
private readonly ChannelList dvbsChannels = new ChannelList(SignalSource.DvbS | SignalSource.Tv | SignalSource.Radio, "DVB-S");
private readonly ChannelList satipChannels = new ChannelList(SignalSource.SatIP | SignalSource.Tv | SignalSource.Radio, "SAT>IP");
private readonly ChannelList freesatChannels = new ChannelList(SignalSource.DvbS | SignalSource.Freesat | SignalSource.Tv | SignalSource.Radio, "Freesat");
private string workFile;
private CypherMode cypherMode;
private byte[] fileHeader = new byte[0];
private int dbSizeOffset;
private bool littleEndianByteOrder;
private string charEncoding;
enum CypherMode
{
None,
HeaderAndChecksum,
Encryption,
Unknown
}
#region static ctor / headerCypherTable
static Serializer()
{
headerCypherTable = new[]
{
0,
79764919,
159529838,
222504665,
319059676,
398814059,
445009330,
507990021,
638119352,
583659535,
797628118,
726387553,
890018660,
835552979,
1015980042,
944750013,
1276238704,
1221641927,
1167319070,
1095957929,
1595256236,
1540665371,
1452775106,
1381403509,
1780037320,
1859660671,
1671105958,
1733955601,
2031960084,
2111593891,
1889500026,
1952343757,
-1742489888,
-1662866601,
-1851683442,
-1788833735,
-1960329156,
-1880695413,
-2103051438,
-2040207643,
-1104454824,
-1159051537,
-1213636554,
-1284997759,
-1389417084,
-1444007885,
-1532160278,
-1603531939,
-734892656,
-789352409,
-575645954,
-646886583,
-952755380,
-1007220997,
-827056094,
-898286187,
-231047128,
-151282273,
-71779514,
-8804623,
-515967244,
-436212925,
-390279782,
-327299027,
881225847,
809987520,
1023691545,
969234094,
662832811,
591600412,
771767749,
717299826,
311336399,
374308984,
453813921,
533576470,
25881363,
88864420,
134795389,
214552010,
2023205639,
2086057648,
1897238633,
1976864222,
1804852699,
1867694188,
1645340341,
1724971778,
1587496639,
1516133128,
1461550545,
1406951526,
1302016099,
1230646740,
1142491917,
1087903418,
-1398421865,
-1469785312,
-1524105735,
-1578704818,
-1079922613,
-1151291908,
-1239184603,
-1293773166,
-1968362705,
-1905510760,
-2094067647,
-2014441994,
-1716953613,
-1654112188,
-1876203875,
-1796572374,
-525066777,
-462094256,
-382327159,
-302564546,
-206542021,
-143559028,
-97365931,
-17609246,
-960696225,
-1031934488,
-817968335,
-872425850,
-709327229,
-780559564,
-600130067,
-654598054,
1762451694,
1842216281,
1619975040,
1682949687,
2047383090,
2127137669,
1938468188,
2001449195,
1325665622,
1271206113,
1183200824,
1111960463,
1543535498,
1489069629,
1434599652,
1363369299,
622672798,
568075817,
748617968,
677256519,
907627842,
853037301,
1067152940,
995781531,
51762726,
131386257,
177728840,
240578815,
269590778,
349224269,
429104020,
491947555,
-248556018,
-168932423,
-122852000,
-60002089,
-500490030,
-420856475,
-341238852,
-278395381,
-685261898,
-739858943,
-559578920,
-630940305,
-1004286614,
-1058877219,
-845023740,
-916395085,
-1119974018,
-1174433591,
-1262701040,
-1333941337,
-1371866206,
-1426332139,
-1481064244,
-1552294533,
-1690935098,
-1611170447,
-1833673816,
-1770699233,
-2009983462,
-1930228819,
-2119160460,
-2056179517,
1569362073,
1498123566,
1409854455,
1355396672,
1317987909,
1246755826,
1192025387,
1137557660,
2072149281,
2135122070,
1912620623,
1992383480,
1753615357,
1816598090,
1627664531,
1707420964,
295390185,
358241886,
404320391,
483945776,
43990325,
106832002,
186451547,
266083308,
932423249,
861060070,
1041341759,
986742920,
613929101,
542559546,
756411363,
701822548,
-978770311,
-1050133554,
-869589737,
-924188512,
-693284699,
-764654318,
-550540341,
-605129092,
-475935807,
-413084042,
-366743377,
-287118056,
-257573603,
-194731862,
-114850189,
-35218492,
-1984365303,
-1921392450,
-2143631769,
-2063868976,
-1698919467,
-1635936670,
-1824608069,
-1744851700,
-1347415887,
-1418654458,
-1506661409,
-1561119128,
-1129027987,
-1200260134,
-1254728445,
-1309196108
};
}
#endregion
#region ctor()
public Serializer(string inputFile) : base(inputFile)
{
DepencencyChecker.AssertVc2010RedistPackageX86Installed();
this.Features.ChannelNameEdit = false; // due to the chaos with binary data inside the "sname" string column, writing back a name has undesired side effects
this.Features.CanHaveGaps = false;
this.DataRoot.SortedFavorites = true;
this.DataRoot.AddChannelList(this.avbtChannels);
this.DataRoot.AddChannelList(this.avbcChannels);
this.DataRoot.AddChannelList(this.dvbtChannels);
this.DataRoot.AddChannelList(this.dvbcChannels);
this.DataRoot.AddChannelList(this.dvbsChannels);
this.DataRoot.AddChannelList(this.satipChannels);
this.DataRoot.AddChannelList(this.freesatChannels);
}
#endregion
public override string DisplayName { get { return "Panasonic .db/.bin Loader"; } }
#region Load()
public override void Load()
{
this.workFile = this.GetUncypheredWorkFile();
this.CreateDummySatellites();
string channelConnString = "Data Source=" + this.workFile;
using (var conn = new SQLiteConnection(channelConnString))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
RepairCorruptedDatabaseImage(cmd);
InitCharacterEncoding(cmd);
this.ReadChannels(cmd);
}
}
}
#endregion
#region GetUncypheredWorkFile()
private string GetUncypheredWorkFile()
{
this.cypherMode = this.GetCypherMode(this.FileName);
if (cypherMode == CypherMode.Unknown)
throw new FileLoadException(ERR_FileFormatOrEncryption);
if (cypherMode == CypherMode.None)
return this.FileName;
var tempFile = this.FileName + ".tmp";
File.Delete(tempFile);
Application.ApplicationExit += CleanTempFile;
if (cypherMode == CypherMode.Encryption)
this.CypherFile(this.FileName, tempFile, false);
else
this.RemoveHeader(this.FileName, tempFile);
return tempFile;
}
#endregion
#region GetCypherMode()
private CypherMode GetCypherMode(string file)
{
using (var stream = File.OpenRead(file))
using (var rdr = new BinaryReader(stream))
{
uint value = (uint)rdr.ReadInt32();
if (value == 0x694C5153) return CypherMode.None; // "SQLi"
if (value == 0x42445350) return CypherMode.HeaderAndChecksum; // "PSDB"
if (value == 0xA07DCB50) return CypherMode.Encryption;
return CypherMode.Unknown;
}
}
#endregion
#region CypherFile()
/// <summary>
/// XOR-based cypher which can be used to alternately crypt/decrypt data
/// </summary>
private void CypherFile(string input, string output, bool encrypt)
{
byte[] fileContent = File.ReadAllBytes(input);
if (!encrypt && this.CalcChecksum(fileContent, fileContent.Length) != 0)
throw new FileLoadException("Checksum validation failed");
int chiffre = 0x0388;
int step = 0;
for (int i = 0; i < fileContent.Length - 4; i++)
{
byte b = fileContent[i];
byte n = (byte) (b ^ (chiffre >> 8));
fileContent[i] = n;
if (++step < 256)
chiffre += (encrypt ? n : b) + 0x96A3;
else
{
chiffre = 0x0388;
step = 0;
}
}
if (encrypt)
this.UpdateChecksum(fileContent);
File.WriteAllBytes(output, fileContent);
}
#endregion
#region RemoveHeader()
private void RemoveHeader(string inputFile, string outputFile)
{
var data = File.ReadAllBytes(inputFile);
if (this.CalcChecksum(data, data.Length) != 0)
throw new FileLoadException("Checksum validation failed");
int offset;
if (!this.ValidateFileSize(data, false, out offset)
&& !this.ValidateFileSize(data, true, out offset))
throw new FileLoadException("File size validation failed");
using (var stream = new FileStream(outputFile, FileMode.Create, FileAccess.Write))
stream.Write(data, offset, data.Length - offset - 4);
this.fileHeader = new byte[offset];
Array.Copy(data, 0, this.fileHeader, 0, offset);
}
#endregion
#region ValidateFileSize()
private bool ValidateFileSize(byte[] data, bool littleEndian, out int offset)
{
this.littleEndianByteOrder = littleEndian;
offset = 30 + Tools.GetInt16(data, 28, littleEndian);
if (offset >= data.Length) return false;
this.dbSizeOffset = offset;
int dbSize = Tools.GetInt32(data, offset, littleEndian);
offset += 4;
return data.Length == offset + dbSize + 4;
}
#endregion
#region CalcChecksum()
private uint CalcChecksum(byte[] data, int length)
{
uint v = 0xffffffff;
for (int i = 0; i < length; i++)
{
byte b = data[i];
v = (v << 8) ^ (uint)headerCypherTable[((v >> 24) ^ b) & 0xFF];
}
return v;
}
#endregion
#region CleanTempFile()
private void CleanTempFile(object sender, EventArgs e)
{
try
{
if (this.workFile != null)
File.Delete(this.workFile);
}
catch { }
}
#endregion
#region CreateDummySatellites()
private void CreateDummySatellites()
{
for (int i = 1; i <= 4; i++)
{
var sat = new Satellite(i);
sat.Name = "LNB "+i;
sat.OrbitalPosition = i.ToString();
this.DataRoot.Satellites.Add(i, sat);
}
}
#endregion
#region InitCharacterEncoding()
private void InitCharacterEncoding(SQLiteCommand cmd)
{
cmd.CommandText = "PRAGMA encoding";
this.charEncoding = cmd.ExecuteScalar() as string;
}
#endregion
#region RepairCorruptedDatabaseImage()
private void RepairCorruptedDatabaseImage(SQLiteCommand cmd)
{
cmd.CommandText = "REINDEX";
cmd.ExecuteNonQuery();
}
#endregion
#region ReadChannels()
private void ReadChannels(SQLiteCommand cmd)
{
string[] fieldNames = { "rowid", "major_channel", "physical_ch","sname", "freq", "skip", "running_status","free_CA_mode","child_lock",
"profile1index","profile2index","profile3index","profile4index","stype", "onid", "tsid", "sid", "ntype", "ya_svcid", "delivery" };
const string sql = @"
select s.rowid,s.major_channel,s.physical_ch,cast(s.sname as blob),t.freq,s.skip,s.running_status,s.free_CA_mode,s.child_lock,
profile1index,profile2index,profile3index,profile4index,s.stype,s.onid,s.tsid,s.svcid,s.ntype,s.ya_svcid,delivery
from SVL s
left outer join TSL t on s.ntype=t.ntype and s.physical_ch=t.physical_ch and s.tsid=t.tsid
order by s.ntype,major_channel
";
var fields = this.GetFieldMap(fieldNames);
cmd.CommandText = sql;
using (var r = cmd.ExecuteReader())
{
while (r.Read())
{
ChannelInfo channel = new DbChannel(r, fields, this.DataRoot, this.DefaultEncoding);
if (!channel.IsDeleted)
{
var channelList = this.DataRoot.GetChannelList(channel.SignalSource);
if (channelList != null)
this.DataRoot.AddChannel(channelList, channel);
}
}
}
}
#endregion
#region GetFieldMap()
private IDictionary<string, int> GetFieldMap(string[] fieldNames)
{
Dictionary<string, int> field = new Dictionary<string, int>();
for (int i = 0; i < fieldNames.Length; i++)
field[fieldNames[i]] = i;
return field;
}
#endregion
#region DefaultEncoding
public override Encoding DefaultEncoding
{
get { return base.DefaultEncoding; }
set
{
base.DefaultEncoding = value;
foreach (var list in this.DataRoot.ChannelLists)
{
foreach(var channel in list.Channels)
channel.ChangeEncoding(value);
}
}
}
#endregion
#region Save()
public override void Save(string tvOutputFile)
{
this.FileName = tvOutputFile;
string channelConnString = "Data Source=" + this.workFile;
using (var conn = new SQLiteConnection(channelConnString))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
using (var trans = conn.BeginTransaction())
{
this.WriteChannels(cmd, this.avbtChannels);
this.WriteChannels(cmd, this.avbcChannels);
this.WriteChannels(cmd, this.dvbtChannels);
this.WriteChannels(cmd, this.dvbcChannels);
this.WriteChannels(cmd, this.dvbsChannels);
this.WriteChannels(cmd, this.satipChannels);
this.WriteChannels(cmd, this.freesatChannels);
trans.Commit();
}
this.RepairCorruptedDatabaseImage(cmd);
}
}
this.WriteCypheredFile();
}
#endregion
#region WriteChannels()
private void WriteChannels(SQLiteCommand cmd, ChannelList channelList)
{
cmd.CommandText = "update SVL set major_channel=@progNr, profile1index=@fav1, profile2index=@fav2, profile3index=@fav3, profile4index=@fav4, child_lock=@lock, skip=@skip where rowid=@rowid";
cmd.Parameters.Clear();
cmd.Parameters.Add(new SQLiteParameter("@rowid", DbType.Int32));
cmd.Parameters.Add(new SQLiteParameter("@progNr", DbType.Int32));
cmd.Parameters.Add(new SQLiteParameter("@fav1", DbType.Int32));
cmd.Parameters.Add(new SQLiteParameter("@fav2", DbType.Int32));
cmd.Parameters.Add(new SQLiteParameter("@fav3", DbType.Int32));
cmd.Parameters.Add(new SQLiteParameter("@fav4", DbType.Int32));
cmd.Parameters.Add(new SQLiteParameter("@lock", DbType.Int32));
cmd.Parameters.Add(new SQLiteParameter("@skip", DbType.Int32));
cmd.Prepare();
foreach (ChannelInfo channelInfo in channelList.Channels)
{
var channel = channelInfo as DbChannel;
if (channel == null) // skip reference list proxy channels
continue;
if (channel.NewProgramNr < 0 || channel.OldProgramNr < 0)
continue;
cmd.Parameters["@rowid"].Value = channel.RecordIndex;
cmd.Parameters["@progNr"].Value = channel.NewProgramNr;
for (int fav = 0; fav < 4; fav++)
cmd.Parameters["@fav" + (fav + 1)].Value = Math.Max(0, channel.FavIndex[fav]);
cmd.Parameters["@lock"].Value = channel.Lock;
cmd.Parameters["@skip"].Value = channel.Skip;
cmd.ExecuteNonQuery();
}
// delete unassigned channels
cmd.CommandText = "delete from SVL where rowid=@rowid";
cmd.Parameters.Clear();
cmd.Parameters.Add(new SQLiteParameter("@rowid", DbType.Int32));
foreach (ChannelInfo channel in channelList.Channels)
{
if (channel.NewProgramNr == -1 && channel.OldProgramNr >= 0)
{
cmd.Parameters["@rowid"].Value = channel.RecordIndex;
cmd.ExecuteNonQuery();
}
}
}
#endregion
#region WriteCypheredFile()
private void WriteCypheredFile()
{
switch (this.cypherMode)
{
case CypherMode.None:
break;
case CypherMode.Encryption:
this.CypherFile(this.workFile, this.FileName, true);
break;
case CypherMode.HeaderAndChecksum:
this.WriteFileWithHeaderAndChecksum();
break;
}
}
#endregion
#region WriteFileWithHeaderAndChecksum()
private void WriteFileWithHeaderAndChecksum()
{
long workFileSize = new FileInfo(this.workFile).Length;
byte[] data = new byte[this.fileHeader.Length + workFileSize + 4];
Array.Copy(fileHeader, data, fileHeader.Length);
using (var stream = new FileStream(this.workFile, FileMode.Open, FileAccess.Read))
stream.Read(data, fileHeader.Length, (int)workFileSize);
Tools.SetInt32(data, this.dbSizeOffset, (int)workFileSize, this.littleEndianByteOrder);
this.UpdateChecksum(data);
using (var stream = new FileStream(this.FileName, FileMode.Create, FileAccess.Write))
stream.Write(data, 0, data.Length);
}
#endregion
#region UpdateChecksum()
private void UpdateChecksum(byte[] data)
{
uint checksum = this.CalcChecksum(data, data.Length - 4);
data[data.Length - 1] = (byte)(checksum & 0xFF);
data[data.Length - 2] = (byte)((checksum >> 8) & 0xFF);
data[data.Length - 3] = (byte)((checksum >> 16) & 0xFF);
data[data.Length - 4] = (byte)((checksum >> 24) & 0xFF);
}
#endregion
#region GetFileInformation()
public override string GetFileInformation()
{
StringBuilder sb = new StringBuilder();
sb.Append(base.GetFileInformation());
sb.Append("Content type: ");
switch (this.GetCypherMode(this.FileName))
{
case CypherMode.None: sb.AppendLine("unencrypted SQLite database"); break;
case CypherMode.Encryption: sb.AppendLine("encrypted SQLite database"); break;
case CypherMode.HeaderAndChecksum:
sb.AppendLine("embedded SQLite database");
sb.Append("Byte order: ").AppendLine(this.littleEndianByteOrder ?
"little-endian (least significant byte first)" : "big-endian (most significant byte first)");
break;
}
sb.Append("Character encoding: ").AppendLine(this.charEncoding);
return sb.ToString();
}
#endregion
}
}

View File

@@ -0,0 +1,15 @@
using ChanSort.Api;
namespace ChanSort.Loader.Panasonic
{
public class SerializerPlugin : ISerializerPlugin
{
public string PluginName { get { return "Panasonic *.db,*.bin"; } }
public string FileFilter { get { return "*.db;*.bin"; } }
public SerializerBase CreateSerializer(string inputFile)
{
return new Serializer(inputFile);
}
}
}