- fixed 200MHz offset for Samsung DVB-C channels

- added support for Sony channel lists (read-only at the moment)
- added option to disable check for updates
This commit is contained in:
hbeham
2019-07-14 22:54:46 +02:00
parent d10845a701
commit daeb9ffb1b
21 changed files with 864 additions and 50 deletions

View File

@@ -430,42 +430,33 @@ TRANSP;119;12722
TRANSP;120;12728
DVBC;kHz;Channel
DVBC;50500;2
DVBC;57500;3
DVBC;64500;4
DVBC;71500;S 01
DVBC;78500;S 02
DVBC;85500;S 03
DVBC;107500;SE 1
DVBC;113000;SE 2
DVBC;114500;SE 2
DVBC;121000;SE 3
DVBC;121500;SE 3
DVBC;128500;SE 4
DVBC;135500;SE 5
DVBC;142500;SE 6
DVBC;149500;SE 7
DVBC;156500;SE 8
DVBC;163500;SE 9
DVBC;170500;SE 10
DVBC;177500;5
DVBC;184500;6
DVBC;191500;7
DVBC;198500;8
DVBC;205500;9
DVBC;212500;10
DVBC;219500;11
DVBC;226500;12
DVBC;233500;SE 11
DVBC;240500;SE 12
DVBC;247500;SE 13
DVBC;254500;SE 14
DVBC;261500;SE 15
DVBC;268500;SE 16
DVBC;275500;SE 17
DVBC;282500;SE 18
DVBC;289500;SE 19
DVBC;296500;SE 20
DVBC;73000;D73
DVBC;81000;D81
DVBC;106000;SE 1
DVBC;114000;SE 2
DVBC;123000;SE 3
DVBC;130000;SE 4
DVBC;138000;SE 5
DVBC;146000;SE 6
DVBC;154000;SE 7
DVBC;162000;SE 8
DVBC;170000;SE 9
DVBC;178000;5
DVBC;186000;6
DVBC;194000;7
DVBC;202000;8
DVBC;210000;9
DVBC;218000;10
DVBC;226000;11
DVBC;234000;SE 11
DVBC;242000;SE 12
DVBC;250000;SE 13
DVBC;258000;SE 14
DVBC;266000;SE 15
DVBC;274000;SE 16
DVBC;282000;SE 17
DVBC;290000;SE 18
DVBC;298000;SE 19
DVBC;306000;S 21
DVBC;314000;S 22
DVBC;322000;S 23
1 SERVICETYPE Number Description
430 DVBC 50500 73000 2 D73
431 DVBC 57500 81000 3 D81
432 DVBC 64500 106000 4 SE 1
433 DVBC 71500 114000 S 01 SE 2
434 DVBC 78500 123000 S 02 SE 3
435 DVBC 85500 130000 S 03 SE 4
436 DVBC 107500 138000 SE 1 SE 5
437 DVBC 113000 146000 SE 2 SE 6
438 DVBC 114500 154000 SE 2 SE 7
439 DVBC 121000 162000 SE 3 SE 8
440 DVBC 121500 170000 SE 3 SE 9
441 DVBC 128500 178000 SE 4 5
442 DVBC 135500 186000 SE 5 6
443 DVBC 142500 194000 SE 6 7
444 DVBC 149500 202000 SE 7 8
445 DVBC 156500 210000 SE 8 9
446 DVBC 163500 218000 SE 9 10
447 DVBC 170500 226000 SE 10 11
448 DVBC 177500 234000 5 SE 11
449 DVBC 184500 242000 6 SE 12
450 DVBC 191500 250000 7 SE 13
451 DVBC 198500 258000 8 SE 14
452 DVBC 205500 266000 9 SE 15
453 DVBC 212500 274000 10 SE 16
454 DVBC 219500 282000 11 SE 17
455 DVBC 226500 290000 12 SE 18
456 DVBC 233500 298000 SE 11 SE 19
457 DVBC 240500 306000 SE 12 S 21
458 DVBC 247500 314000 SE 13 S 22
459 DVBC 254500 322000 SE 14 S 23
DVBC 261500 SE 15
DVBC 268500 SE 16
DVBC 275500 SE 17
DVBC 282500 SE 18
DVBC 289500 SE 19
DVBC 296500 SE 20
DVBC 306000 S 21
DVBC 314000 S 22
DVBC 322000 S 23
460 DVBC 330000 S 24
461 DVBC 338000 S 25
462 DVBC 346000 S 26

View File

@@ -204,7 +204,7 @@ namespace ChanSort.Api
#endregion
#region GetDvbtFrequency()
public decimal GetDvbtFrequeny(int channelTransponder)
public decimal GetDvbtFrequency(int channelTransponder)
{
return channelTransponder * 8 + 306;
}
@@ -212,12 +212,17 @@ namespace ChanSort.Api
public int GetDvbcTransponder(decimal freqInMhz)
{
return GetDvbtTransponder(freqInMhz) + 25; // Samsung handles it like this
return (int)(freqInMhz - 106) / 8;
}
public decimal GetDvbcFrequency(int channelTransponder)
{
return channelTransponder * 8 + 106;
}
public string GetDvbcChannelName(decimal freqInMhz)
{
return dvbcChannels.TryGet((int)(freqInMhz * 1000)) ?? "";
return dvbcChannels.TryGet((int)(freqInMhz * 1000)) ?? dvbcChannels.TryGet((int)((freqInMhz-1) * 1000)) ?? "";
}
}
}

View File

@@ -332,6 +332,8 @@ namespace ChanSort.Loader.Hisense
if ((ci.SignalSource & SignalSource.DvbT) == SignalSource.DvbT)
ci.ChannelOrTransponder = LookupData.Instance.GetDvbtTransponder(ci.FreqInMhz).ToString();
else if ((ci.SignalSource & SignalSource.DvbC) == SignalSource.DvbC)
ci.ChannelOrTransponder = LookupData.Instance.GetDvbcTransponder(ci.FreqInMhz).ToString();
#if LOCK_LCN_LISTS
// make the current list read-only if LCN is used

View File

@@ -26,7 +26,7 @@ namespace ChanSort.Loader.LG
this.FreqInMhz = (data.GetDword(_FrequencyLong)+10) / 1000;
// ReSharper restore PossibleLossOfFraction
if (this.FreqInMhz == 0)
this.FreqInMhz = LookupData.Instance.GetDvbtFrequeny(channel);
this.FreqInMhz = LookupData.Instance.GetDvbtFrequency(channel);
}
}
}

View File

@@ -21,7 +21,12 @@ namespace ChanSort.Loader.Samsung
int transp = data.GetByte(_ChannelOrTransponder);
decimal freq = transpFreq.TryGet(transp);
if (freq == 0)
freq = LookupData.Instance.GetDvbtFrequeny(transp); // transp*8 + 106); // (106 = DVB-C; DVB-T=306?)
{
if ((this.SignalSource & SignalSource.Antenna) != 0)
freq = transp * 8 + 306;
else if ((this.SignalSource & SignalSource.Cable) != 0)
freq = transp * 8 + 106;
}
this.ChannelOrTransponder = transp.ToString();
this.FreqInMhz = freq;

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{70E29C6B-B926-4859-9548-23375BF1E1B5}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ChanSort.Loader.Sony</RootNamespace>
<AssemblyName>ChanSort.Loader.Sony</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</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>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</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>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Channel.cs" />
<Compile Include="Serializer.cs" />
<Compile Include="SerializerPlugin.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</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" />
</Project>

View File

@@ -0,0 +1,22 @@
using System.Xml;
using ChanSort.Api;
namespace ChanSort.Loader.Sony
{
internal class Channel : ChannelInfo
{
internal int Index;
internal XmlNode XmlNode;
internal bool IsDisabled;
#region ctor()
internal Channel(SignalSource source, int index, XmlNode node)
{
this.SignalSource = source;
this.Index = index;
this.XmlNode = node;
}
#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.Sony")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ChanSort.Loader.Sony")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[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("70e29c6b-b926-4859-9548-23375bf1e1b5")]
// 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,572 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using ChanSort.Api;
namespace ChanSort.Loader.Sony
{
class Serializer : SerializerBase
{
private readonly ChannelList satChannels = new ChannelList(SignalSource.DvbS | SignalSource.Tv | SignalSource.Radio, "Sat");
private XmlDocument doc;
private byte[] content;
private string textContent;
private XmlNode sdbXml;
private string format;
#region Crc32Table
private static readonly uint[] Crc32Table =
{
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,
2552477408, 2632100695, 2443283854, 2506133561, 2334638140, 2414271883, 2191915858, 2254759653, 3190512472, 3135915759, 3081330742, 3009969537, 2905550212, 2850959411, 2762807018, 2691435357,
3560074640, 3505614887, 3719321342, 3648080713, 3342211916, 3287746299, 3467911202, 3396681109, 4063920168, 4143685023, 4223187782, 4286162673, 3779000052, 3858754371, 3904687514, 3967668269,
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,
2896545431, 2825181984, 2770861561, 2716262478, 3215044683, 3143675388, 3055782693, 3001194130, 2326604591, 2389456536, 2200899649, 2280525302, 2578013683, 2640855108, 2418763421, 2498394922,
3769900519, 3832873040, 3912640137, 3992402750, 4088425275, 4151408268, 4197601365, 4277358050, 3334271071, 3263032808, 3476998961, 3422541446, 3585640067, 3514407732, 3694837229, 3640369242,
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,
4046411278, 4126034873, 4172115296, 4234965207, 3794477266, 3874110821, 3953728444, 4016571915, 3609705398, 3555108353, 3735388376, 3664026991, 3290680682, 3236090077, 3449943556, 3378572211,
3174993278, 3120533705, 3032266256, 2961025959, 2923101090, 2868635157, 2813903052, 2742672763, 2604032198, 2683796849, 2461293480, 2524268063, 2284983834, 2364738477, 2175806836, 2238787779,
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,
3316196985, 3244833742, 3425377559, 3370778784, 3601682597, 3530312978, 3744426955, 3689838204, 3819031489, 3881883254, 3928223919, 4007849240, 4037393693, 4100235434, 4180117107, 4259748804,
2310601993, 2373574846, 2151335527, 2231098320, 2596047829, 2659030626, 2470359227, 2550115596, 2947551409, 2876312838, 2788305887, 2733848168, 3165939309, 3094707162, 3040238851, 2985771188
};
#endregion
#region ctor()
public Serializer(string inputFile) : base(inputFile)
{
this.Features.ChannelNameEdit = ChannelNameEditMode.All;
this.Features.CanDeleteChannels = true;
satChannels.VisibleColumnFieldNames.Remove("PcrPid");
satChannels.VisibleColumnFieldNames.Remove("VideoPid");
satChannels.VisibleColumnFieldNames.Remove("AudioPid");
satChannels.VisibleColumnFieldNames.Remove("Lock");
satChannels.VisibleColumnFieldNames.Remove("Skip");
satChannels.VisibleColumnFieldNames.Remove("Provider");
this.DataRoot.AddChannelList(this.satChannels);
}
#endregion
#region DisplayName
public override string DisplayName => "Sony sdb.xml loader";
#endregion
#region Load()
public override void Load()
{
bool fail = false;
try
{
this.doc = new XmlDocument();
this.content = File.ReadAllBytes(this.FileName);
this.textContent = Encoding.UTF8.GetString(this.content);
var tc2 = ReplaceInvalidXmlCharacters(textContent);
if (tc2 != this.textContent)
this.textContent = tc2;
var settings = new XmlReaderSettings
{
CheckCharacters = false,
IgnoreProcessingInstructions = true,
ValidationFlags = XmlSchemaValidationFlags.None,
DtdProcessing = DtdProcessing.Ignore
};
using (var reader = XmlReader.Create(new StringReader(textContent), settings))
{
doc.Load(reader);
}
}
catch
{
fail = true;
}
var root = doc.FirstChild;
if (root is XmlDeclaration)
root = root.NextSibling;
if (fail || root == null || root.LocalName != "SdbRoot")
throw new FileLoadException("\"" + this.FileName + "\" is not a supported Sony XML file");
foreach (XmlNode child in root.ChildNodes)
{
switch (child.LocalName)
{
case "SdbXml":
this.ReadSdbXml(child);
break;
case "CheckSum":
this.ReadChecksum(child);
break;
}
}
this.Features.ChannelNameEdit = ChannelNameEditMode.All;
if (this.format != "1.1.0e")
{
satChannels.VisibleColumnFieldNames.Remove("Hidden");
satChannels.VisibleColumnFieldNames.Remove("Satellite");
}
}
#endregion
#region ReadSdbXml()
private void ReadSdbXml(XmlNode node)
{
this.sdbXml = node;
this.format = null;
var formatNode = node["FormatVer"];
if (formatNode != null)
this.format = formatNode.InnerText;
else if ((formatNode = node["FormateVer"]) != null)
this.format = formatNode.InnerText + "e";
if (" 1.0.0 1.1.0e 1.1.0 1.2.0 ".IndexOf(" " + this.format + " ") < 0)
throw new FileLoadException("Unsupported file format version: " + this.format);
foreach(XmlNode child in node.ChildNodes)
{
var name = child.LocalName.ToLowerInvariant();
if (name == "sdbgs")
ReadSdb(child);
}
}
#endregion
#region ReadSdb
private void ReadSdb(XmlNode node)
{
this.satChannels.ReadOnly = node["Editable"].InnerText != "T";
this.ReadSatellites(node);
this.ReadTransponder(node);
if (this.format == "1.1.0e")
this.ReadServices110e(node);
else
this.ReadServices(node);
}
#endregion
#region ReadSatellites
private void ReadSatellites(XmlNode node)
{
var satlRec = node["SATL_REC"];
if (satlRec == null)
return;
var data = this.SplitLines(satlRec);
var ids = data["ui2_satl_rec_id"];
for (int i = 0, c = ids.Length; i < c; i++)
{
var sat = new Satellite(int.Parse(ids[i]));
sat.Name = data["ac_sat_name"][i];
var pos = int.Parse(data["i2_orb_pos"][i]);
sat.OrbitalPosition = Math.Abs((decimal) pos / 10) + (pos < 0 ? "W" : "E");
this.DataRoot.AddSatellite(sat);
}
}
#endregion
#region ReadTransponder
private void ReadTransponder(XmlNode node)
{
var mux = node["Multiplex"] ?? throw new FileLoadException("Missing Multiplex XML element");
var muxData = SplitLines(mux);
var muxIds = this.format == "1.1.0e" ? muxData["MuxID"] : muxData["MuxRowId"];
var rfParmData = this.format != "1.1.0e" ? SplitLines(mux["RfParam"]) : null;
var dvbsData = rfParmData != null ? SplitLines(mux["RfParam"]["DvbS"]) : null;
for (int i = 0, c = muxIds.Length; i < c; i++)
{
Satellite sat = null;
var transp = new Transponder(int.Parse(muxIds[i]));
if (this.format == "1.1.0e")
{
var satId = int.Parse(muxData["ui2_satl_rec_id"][i]);
transp.FrequencyInMhz = int.Parse(muxData["SysFreq"][i]);
transp.SymbolRate = int.Parse(muxData["ui4_sym_rate"][i]);
transp.Polarity = muxData["e_pol"][i] == "1" ? 'H' : 'V';
sat = DataRoot.Satellites[satId];
}
else
{
transp.OriginalNetworkId = intParse(muxData["Onid"][i]);
transp.TransportStreamId = intParse(muxData["Tsid"][i]);
transp.FrequencyInMhz = int.Parse(rfParmData["Freq"][i]) / 1000;
transp.Polarity = dvbsData["Pola"][i] == "H_L" ? 'H' : 'V';
transp.SymbolRate = int.Parse(dvbsData["SymbolRate"][i]) / 1000;
}
this.DataRoot.AddTransponder(sat, transp);
}
}
#endregion
#region ReadServices110e
private void ReadServices110e(XmlNode node)
{
var tsDescrNode = node["TS_Descr"] ?? throw new FileLoadException("Missing TS_Descr XML element");
var tsData = SplitLines(tsDescrNode);
var serviceNode = node["Service"] ?? throw new FileLoadException("Missing Service XML element");
var svcData = SplitLines(serviceNode);
var dvbData = SplitLines(serviceNode["dvb_info"]);
for (int i = 0, c = svcData["ui2_svl_rec_id"].Length; i < c; i++)
{
var chan = new Channel(SignalSource.DvbS, i, serviceNode.ChildNodes[i]);
chan.OldProgramNr = int.Parse(svcData["ui2_svl_rec_id"][i]);
chan.IsDeleted = svcData["b_deleted_by_user"][i] != "1";
var nwMask = int.Parse(svcData["ui4_nw_mask"][i]);
chan.Hidden = (nwMask & 8) == 0;
chan.Encrypted = (nwMask & 2048) != 0;
chan.Encrypted = dvbData["t_free_ca_mode"][i] == "1";
chan.Favorites = (Favorites) ((nwMask & 0xF0) >> 4);
chan.ServiceId = int.Parse(svcData["ui2_prog_id"][i]);
chan.Name = svcData["Name"][i];
var muxId = int.Parse(svcData["MuxID"][i]);
var transp = this.DataRoot.Transponder[muxId];
chan.Transponder = transp;
if (transp != null)
{
chan.FreqInMhz = transp.FrequencyInMhz;
chan.SymbolRate = transp.SymbolRate;
chan.Polarity = transp.Polarity;
chan.Satellite = transp.Satellite?.Name;
chan.SatPosition = transp.Satellite?.OrbitalPosition;
}
var tsIdx = int.Parse(svcData["ui2_tsl_rec_id"][i]) - 1;
chan.TransportStreamId = int.Parse(tsData["Tsid"][tsIdx]);
chan.OriginalNetworkId = int.Parse(tsData["Onid"][tsIdx]);
chan.ServiceType = int.Parse(dvbData["ui1_sdt_service_type"][i]);
chan.SignalSource |= LookupData.Instance.IsRadioOrTv(chan.ServiceType);
this.DataRoot.AddChannel(this.satChannels, chan);
}
}
#endregion
#region ReadServices
private void ReadServices(XmlNode node)
{
var serviceNode = node["Service"] ?? throw new FileLoadException("Missing Service XML element");
var svcData = SplitLines(serviceNode);
var progNode = node["Programme"] ?? throw new FileLoadException("Missing Programme XML element");
var progData = SplitLines(progNode);
var map = new Dictionary<int, Channel>();
for (int i = 0, c = svcData["ServiceRowId"].Length; i < c; i++)
{
var rowId = int.Parse(svcData["ServiceRowId"][i]);
var chan = new Channel(SignalSource.DvbS, rowId, serviceNode.ChildNodes[i]);
map[rowId] = chan;
chan.OldProgramNr = -1;
chan.IsDeleted = true;
chan.ServiceType = int.Parse(svcData["Type"][i]);
chan.OriginalNetworkId = intParse(svcData["Onid"][i]);
chan.TransportStreamId = intParse(svcData["Tsid"][i]);
chan.ServiceId = intParse(svcData["Sid"][i]);
chan.Name = svcData["Name"][i];
var muxId = int.Parse(svcData["MuxRowId"][i]);
var transp = this.DataRoot.Transponder[muxId];
chan.Transponder = transp;
if (transp != null)
{
chan.FreqInMhz = transp.FrequencyInMhz;
chan.SymbolRate = transp.SymbolRate;
chan.Polarity = transp.Polarity;
}
chan.SignalSource |= LookupData.Instance.IsRadioOrTv(chan.ServiceType);
var att = intParse(svcData["Attribute"][i]);
chan.Encrypted = (att & 8) != 0;
this.DataRoot.AddChannel(this.satChannels, chan);
}
for (int i = 0, c = progData["ServiceRowId"].Length; i < c; i++)
{
var rowId = int.Parse(progData["ServiceRowId"][i]);
var chan = map.TryGet(rowId);
if (chan == null)
continue;
chan.IsDeleted = false;
chan.OldProgramNr = int.Parse(progData["No"][i]);
var flag = int.Parse(progData["Flag"][i]);
chan.Favorites = (Favorites)(flag & 0x0F);
}
}
#endregion
#region SplitLines
private Dictionary<string, string[]> SplitLines(XmlNode parent)
{
var dict = new Dictionary<string, string[]>();
foreach (XmlNode node in parent.ChildNodes)
{
if (node.Attributes["loop"] == null)
continue;
var lines = node.InnerText.Trim('\n').Split('\n');
dict[node.LocalName] = lines;
}
return dict;
}
#endregion
#region ReadChecksum()
private void ReadChecksum(XmlNode node)
{
byte[] data;
int start;
int end;
uint expectedCrc;
if (this.format == "1.1.0e")
{
// files with the typo-element "<FormateVer>1.1.0</FormateVer>" differ in several ways from all other files (including <FormatVer>1.1.0</FormatVer>):
// "\n" after the closing <SdbXml> Tag is included in the checksum, the checksum has no 0x prefix and the bytes are used as-is for the calculation, without any XML cleanup
data = this.content;
start = this.IndexOf("<SdbXml>");
end = this.IndexOf("</SdbXml>") + 10; // including the \n at the end
expectedCrc = uint.Parse(node.InnerText, NumberStyles.HexNumber); // no 0x prefix
}
else
{
start = this.textContent.IndexOf("<SdbXml>");
end = this.textContent.IndexOf("</SdbXml>") + 9;
var text = this.textContent.Substring(start, end - start);
text = text.Replace("\r\n", "\n");
text = text.Replace(" />", "/>");
text = text.Replace("&lt;", "&#60;");
text = text.Replace("&gt;", "&#62;");
text = text.Replace("&quot;", "&#34;");
text = text.Replace("&amp;", "&#38;");
text = text.Replace("&apos;", "&#39;");
text = text.Replace("'", "&#39;");
data = Encoding.UTF8.GetBytes(text);
start = 0;
end = data.Length;
expectedCrc = uint.Parse(node.InnerText.Substring(2), NumberStyles.HexNumber);
}
uint crc = 0xFFFFFFFF;
for (int i = start; i < end; i++)
{
var b = data[i];
crc = (crc << 8) ^ Crc32Table[b ^ (crc >> 24)];
}
crc = ~crc;
if (crc != expectedCrc)
throw new FileLoadException($"Invalid checksum: expected 0x{expectedCrc:x8}, calculated 0x{crc:x8}");
}
private int IndexOf(string marker)
{
var bytes = Encoding.ASCII.GetBytes(marker);
var len = bytes.Length;
int i = -1, c = this.content.Length - len;
for (; ; )
{
i = Array.IndexOf(this.content, bytes[0], i + 1);
if (i < 0)
return -1;
int j;
for (j = 1; j < len; j++)
{
if (this.content[i + j] != bytes[j])
break;
}
if (j == len)
return i;
}
}
#endregion
#region Save()
public override void Save(string tvOutputFile)
{
throw new NotImplementedException("Sorry, but Sony lists are currently read-only. Support for writing is coming soon.");
foreach (var list in this.DataRoot.ChannelLists)
{
foreach (var channel in list.Channels)
{
var ch = channel as Channel;
if (ch == null) continue; // ignore proxy channels from reference lists
var nameBytes = Encoding.UTF8.GetBytes(ch.Name);
bool nameNeedsEncoding = nameBytes.Length != ch.Name.Length;
string mapType = "";
foreach (XmlNode node in ch.XmlNode.ChildNodes)
{
switch (node.LocalName)
{
case "prNum":
var nr = ch.NewProgramNr;
if ((ch.SignalSource & SignalSource.Radio) != 0)
nr |= 0x4000;
node.InnerText = nr.ToString();
break;
case "hexVchName":
if (channel.IsNameModified)
node.InnerText = (nameNeedsEncoding ? "15" : "") + Tools.HexEncode(nameBytes); // 0x15 = DVB encoding indicator for UTF-8
break;
case "notConvertedLengthOfVchName":
if (channel.IsNameModified)
node.InnerText = ((nameNeedsEncoding ? 1 : 0) + ch.Name.Length).ToString();
break;
case "vchName":
if (channel.IsNameModified)
node.InnerText = nameNeedsEncoding ? " " : ch.Name;
if (node.InnerText == "") // XmlTextReader removed the required space from empty channel names
node.InnerText = " ";
break;
case "isInvisable":
node.InnerText = ch.Hidden ? "1" : "0";
break;
case "isBlocked":
node.InnerText = ch.Lock ? "1" : "0";
break;
case "isSkipped":
node.InnerText = ch.Skip ? "1" : "0";
break;
case "isNumUnSel":
// ?
break;
case "isDisabled":
node.InnerText = ch.IsDeleted || ch.IsDisabled ? "1" : "0";
break;
case "isDeleted":
node.InnerText = ch.IsDeleted ? "1" : "0";
break;
case "isUserSelCHNo":
if (ch.NewProgramNr != ch.OldProgramNr)
node.InnerText = "1";
break;
case "mapType":
mapType = node.InnerText;
break;
case "mapAttr":
if (mapType == "1")
node.InnerText = ((int) ch.Favorites).ToString();
break;
}
}
}
}
// by default .NET reformats the whole XML. These settings produce the same format as the TV xml files use
var settings = new XmlWriterSettings();
settings.Encoding = new UTF8Encoding(false);
settings.Indent = true;
settings.NewLineChars = "\r\n";
settings.NewLineHandling = NewLineHandling.Replace;
settings.OmitXmlDeclaration = true;
settings.IndentChars = "";
settings.CheckCharacters = false;
using (StringWriter sw = new StringWriter())
using (XmlWriter xw = XmlWriter.Create(sw, settings))
{
doc.Save(xw);
xw.Flush();
string xml = RestoreInvalidXmlCharacters(sw.ToString());
xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n\r\n" + xml;
xml = xml.Replace("<ATV></ATV>\r\n", "<ATV>\r\n</ATV>\r\n");
xml = xml.Replace("<DTV></DTV>\r\n", "<DTV>\r\n</DTV>\r\n");
if (!xml.EndsWith("\r\n"))
xml += "\r\n";
File.WriteAllText(tvOutputFile, xml, settings.Encoding);
}
}
#endregion
#region intParse
private int intParse(string input)
{
if (string.IsNullOrWhiteSpace(input))
return 0;
if (input.StartsWith("0x"))
return int.Parse(input.Substring(2), NumberStyles.HexNumber);
if (int.TryParse(input, out var value))
return value;
return 0;
}
#endregion
#region ReplaceInvalidXmlCharacters()
private string ReplaceInvalidXmlCharacters(string input)
{
StringBuilder output = new StringBuilder();
foreach (var c in input)
{
if (c >= ' ' || c == '\r' || c == '\n' || c == '\t')
output.Append(c);
else
output.AppendFormat("&#x{0:d}{1:d};", c >> 4, c & 0x0F);
}
return output.ToString();
}
#endregion
#region RestoreInvalidXmlCharacters()
private string RestoreInvalidXmlCharacters(string input)
{
StringBuilder output = new StringBuilder();
int prevIdx = 0;
while(true)
{
int nextIdx = input.IndexOf("&#", prevIdx);
if (nextIdx < 0)
break;
output.Append(input, prevIdx, nextIdx - prevIdx);
int numBase = 10;
char inChar;
int outChar = 0;
for (nextIdx += 2; (inChar=input[nextIdx]) != ';'; nextIdx++)
{
if (inChar == 'x' || inChar == 'X')
numBase = 16;
else
outChar = outChar*numBase + HexNibble(inChar);
}
var binChar = (char)outChar;
output.Append(binChar);
prevIdx = nextIdx + 1;
}
output.Append(input, prevIdx, input.Length - prevIdx);
return output.ToString();
}
private int HexNibble(char hexDigit)
{
return hexDigit >= '0' && hexDigit <= '9' ? hexDigit - '0' : (Char.ToUpper(hexDigit) - 'A') + 10;
}
#endregion
}
}

View File

@@ -0,0 +1,16 @@
using ChanSort.Api;
namespace ChanSort.Loader.Sony
{
public class SerializerPlugin : ISerializerPlugin
{
public string DllName { get; set; }
public string PluginName => "Sony sdb.xml";
public string FileFilter => "sdb*.xml";
public SerializerBase CreateSerializer(string inputFile)
{
return new Serializer(inputFile);
}
}
}

View File

@@ -50,6 +50,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChanSort.Loader.Hisense2017
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChanSort.Loader.SilvaSchneider", "ChanSort.Loader.SilvaSchneider\ChanSort.Loader.SilvaSchneider.csproj", "{E6279FF8-362A-41E6-AC0D-D0861D43F01C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChanSort.Loader.Sony", "ChanSort.Loader.Sony\ChanSort.Loader.Sony.csproj", "{70E29C6B-B926-4859-9548-23375BF1E1B5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -238,8 +240,20 @@ Global
{E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Release|Any CPU.Build.0 = Release|Any CPU
{E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Release|x86.ActiveCfg = Release|Any CPU
{E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Release|x86.Build.0 = Release|Any CPU
{E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Release|x86.ActiveCfg = Release|x86
{E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Release|x86.Build.0 = Release|x86
{70E29C6B-B926-4859-9548-23375BF1E1B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{70E29C6B-B926-4859-9548-23375BF1E1B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{70E29C6B-B926-4859-9548-23375BF1E1B5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{70E29C6B-B926-4859-9548-23375BF1E1B5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{70E29C6B-B926-4859-9548-23375BF1E1B5}.Debug|x86.ActiveCfg = Debug|x86
{70E29C6B-B926-4859-9548-23375BF1E1B5}.Debug|x86.Build.0 = Debug|x86
{70E29C6B-B926-4859-9548-23375BF1E1B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{70E29C6B-B926-4859-9548-23375BF1E1B5}.Release|Any CPU.Build.0 = Release|Any CPU
{70E29C6B-B926-4859-9548-23375BF1E1B5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{70E29C6B-B926-4859-9548-23375BF1E1B5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{70E29C6B-B926-4859-9548-23375BF1E1B5}.Release|x86.ActiveCfg = Release|x86
{70E29C6B-B926-4859-9548-23375BF1E1B5}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -396,6 +396,10 @@
<Project>{e6279ff8-362a-41e6-ac0d-d0861d43f01c}</Project>
<Name>ChanSort.Loader.SilvaSchneider</Name>
</ProjectReference>
<ProjectReference Include="..\ChanSort.Loader.Sony\ChanSort.Loader.Sony.csproj">
<Project>{70e29c6b-b926-4859-9548-23375bf1e1b5}</Project>
<Name>ChanSort.Loader.Sony</Name>
</ProjectReference>
<ProjectReference Include="..\ChanSort.Loader.Toshiba\ChanSort.Loader.Toshiba.csproj">
<Project>{f6f02792-07f1-48d5-9af3-f945ca5e3931}</Project>
<Name>ChanSort.Loader.Toshiba</Name>

View File

@@ -206,6 +206,7 @@
this.pageProgNr = new DevExpress.XtraTab.XtraTabPage();
this.popupInputSource = new DevExpress.XtraBars.PopupMenu(this.components);
this.popupFavList = new DevExpress.XtraBars.PopupMenu(this.components);
this.miCheckUpdates = new DevExpress.XtraBars.BarButtonItem();
((System.ComponentModel.ISupportInitialize)(this.splitContainerControl1)).BeginInit();
this.splitContainerControl1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.grpOutputList)).BeginInit();
@@ -1024,9 +1025,10 @@
this.miAllowEditPredefinedLists,
this.miCzech,
this.miRomanian,
this.miExplorerIntegration});
this.miExplorerIntegration,
this.miCheckUpdates});
this.barManager1.MainMenu = this.bar1;
this.barManager1.MaxItemId = 98;
this.barManager1.MaxItemId = 99;
this.barManager1.ShowFullMenus = true;
//
// bar1
@@ -1516,7 +1518,8 @@
new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.PaintStyle, this.mnuCharset, DevExpress.XtraBars.BarItemPaintStyle.CaptionGlyph),
new DevExpress.XtraBars.LinkPersistInfo(this.miShowWarningsAfterLoad),
new DevExpress.XtraBars.LinkPersistInfo(this.miAllowEditPredefinedLists),
new DevExpress.XtraBars.LinkPersistInfo(this.miExplorerIntegration)});
new DevExpress.XtraBars.LinkPersistInfo(this.miExplorerIntegration),
new DevExpress.XtraBars.LinkPersistInfo(this.miCheckUpdates)});
this.mnuOptions.Name = "mnuOptions";
//
// barSubItem1
@@ -2052,6 +2055,14 @@
this.popupFavList.Name = "popupFavList";
this.popupFavList.ShowCaption = true;
//
// miCheckUpdates
//
this.miCheckUpdates.ButtonStyle = DevExpress.XtraBars.BarButtonStyle.Check;
resources.ApplyResources(this.miCheckUpdates, "miCheckUpdates");
this.miCheckUpdates.Id = 98;
this.miCheckUpdates.Name = "miCheckUpdates";
this.miCheckUpdates.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miCheckUpdates_ItemClick);
//
// MainForm
//
this.AllowDrop = true;
@@ -2292,6 +2303,7 @@
private DevExpress.XtraBars.BarButtonItem miRomanian;
private DevExpress.XtraGrid.Columns.GridColumn colPcrPid;
private DevExpress.XtraBars.BarButtonItem miExplorerIntegration;
private DevExpress.XtraBars.BarButtonItem miCheckUpdates;
}
}

View File

@@ -152,7 +152,8 @@ namespace ChanSort.Ui
}
}
this.BeginInvoke((Action) UpdateCheck.CheckForNewVersion);
if (Settings.Default.CheckForUpdates)
this.BeginInvoke((Action) UpdateCheck.CheckForNewVersion);
}
#endregion
@@ -1266,6 +1267,7 @@ namespace ChanSort.Ui
this.UpdateMruMenu();
this.miExplorerIntegration.Down = Settings.Default.ExplorerIntegration;
this.miCheckUpdates.Down = Settings.Default.CheckForUpdates;
}
#endregion
@@ -2607,6 +2609,7 @@ namespace ChanSort.Ui
for (var i = 0; i < this.mruFiles.Count; i++)
Settings.Default.GetType().GetProperty("MruFile" + i).SetValue(Settings.Default, this.mruFiles[i], null);
Settings.Default.ExplorerIntegration = this.miExplorerIntegration.Down;
Settings.Default.CheckForUpdates = this.miCheckUpdates.Down;
Settings.Default.Save();
}
@@ -2951,6 +2954,9 @@ namespace ChanSort.Ui
{
try
{
if (this.miExplorerIntegration.Down == Settings.Default.ExplorerIntegration)
return;
// get all file extensions from loader plugins
var ext = new HashSet<string>();
foreach (var loader in this.Plugins)
@@ -2978,6 +2984,24 @@ namespace ChanSort.Ui
}
#endregion
#region miCheckUpdates_ItemClick
private void miCheckUpdates_ItemClick(object sender, ItemClickEventArgs e)
{
try
{
if (this.miCheckUpdates.Down == Settings.Default.CheckForUpdates)
return;
if (this.miCheckUpdates.Down)
UpdateCheck.CheckForNewVersion();
this.SaveSettings();
}
catch (Exception ex)
{
HandleException(ex);
}
}
#endregion
#region gview_MouseDown, gview_MouseUp, timerEditDelay_Tick, gview_ShowingEditor

View File

@@ -628,4 +628,10 @@ speziellen Anbieter, Satelliten oder Länderlisten aus.</value>
<data name="colSource.Caption" xml:space="preserve">
<value>Quelle</value>
</data>
<data name="miExplorerIntegration.Caption" xml:space="preserve">
<value>Windows Explorer Integration</value>
</data>
<data name="miCheckUpdates.Caption" xml:space="preserve">
<value>Nach Programmupdates suchen</value>
</data>
</root>

View File

@@ -666,7 +666,10 @@
<value>37</value>
</data>
<data name="miExplorerIntegration.Caption" xml:space="preserve">
<value>Windows Explorer Integration (handle file extensions)</value>
<value>Windows Explorer Integration</value>
</data>
<data name="miCheckUpdates.Caption" xml:space="preserve">
<value>Check for updates</value>
</data>
<data name="mnuAccessibility.Caption" xml:space="preserve">
<value>&amp;Accessibility</value>
@@ -1252,7 +1255,7 @@
<value>globalImageCollection1</value>
</data>
<data name="&gt;&gt;globalImageCollection1.Type" xml:space="preserve">
<value>ChanSort.Ui.GlobalImageCollection, ChanSort, Version=1.0.7133.39305, Culture=neutral, PublicKeyToken=null</value>
<value>ChanSort.Ui.GlobalImageCollection, ChanSort, Version=1.0.7134.23381, Culture=neutral, PublicKeyToken=null</value>
</data>
<data name="&gt;&gt;gviewRight.Name" xml:space="preserve">
<value>gviewRight</value>
@@ -1968,6 +1971,12 @@
<data name="&gt;&gt;popupFavList.Type" xml:space="preserve">
<value>DevExpress.XtraBars.PopupMenu, DevExpress.XtraBars.v19.1, Version=19.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
</data>
<data name="&gt;&gt;miCheckUpdates.Name" xml:space="preserve">
<value>miCheckUpdates</value>
</data>
<data name="&gt;&gt;miCheckUpdates.Type" xml:space="preserve">
<value>DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v19.1, Version=19.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
</data>
<data name="&gt;&gt;$this.Name" xml:space="preserve">
<value>MainForm</value>
</data>
@@ -1975,7 +1984,7 @@
<value>DevExpress.XtraEditors.XtraForm, DevExpress.Utils.v19.1, Version=19.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
</data>
<data name="SharedImageCollection.Timestamp" type="System.DateTime, mscorlib">
<value>07/13/2019 21:51:28</value>
<value>07/14/2019 13:16:32</value>
</data>
<data name="SharedImageCollection.ImageSize" type="System.Drawing.Size, System.Drawing">
<value>16, 16</value>

View File

@@ -478,5 +478,17 @@ namespace ChanSort.Ui.Properties {
this["ExplorerIntegration"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool CheckForUpdates {
get {
return ((bool)(this["CheckForUpdates"]));
}
set {
this["CheckForUpdates"] = value;
}
}
}
}

View File

@@ -116,5 +116,8 @@
<Setting Name="ExplorerIntegration" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="CheckForUpdates" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
</Settings>
</SettingsFile>

View File

@@ -122,6 +122,9 @@
<setting name="ExplorerIntegration" serializeAs="String">
<value>False</value>
</setting>
<setting name="CheckForUpdates" serializeAs="String">
<value>True</value>
</setting>
</ChanSort.Ui.Properties.Settings>
<GUI.Properties.Settings>
<setting name="InputTLL" serializeAs="String">

Binary file not shown.

View File

@@ -1,5 +1,10 @@
ChanSort Change Log
===================
2019-07-xx
- added partial support for Sony sdb.xml channel list format (DVB-S only)
- added option to disable check for program updates
2019-07-14
- added support for Silva-Schneider .sdx channel lists