diff --git a/source/ChanSort.Api/Lookup.csv b/source/ChanSort.Api/Lookup.csv
index b352789..47254ec 100644
--- a/source/ChanSort.Api/Lookup.csv
+++ b/source/ChanSort.Api/Lookup.csv
@@ -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
diff --git a/source/ChanSort.Api/Model/LookupData.cs b/source/ChanSort.Api/Model/LookupData.cs
index 0a2bac0..9f28f22 100644
--- a/source/ChanSort.Api/Model/LookupData.cs
+++ b/source/ChanSort.Api/Model/LookupData.cs
@@ -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)) ?? "";
}
}
}
diff --git a/source/ChanSort.Loader.Hisense/HisDbSerializer.cs b/source/ChanSort.Loader.Hisense/HisDbSerializer.cs
index 45b01ce..994a663 100644
--- a/source/ChanSort.Loader.Hisense/HisDbSerializer.cs
+++ b/source/ChanSort.Loader.Hisense/HisDbSerializer.cs
@@ -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
diff --git a/source/ChanSort.Loader.LG/DtvChannel.cs b/source/ChanSort.Loader.LG/DtvChannel.cs
index dae3f05..024db4a 100644
--- a/source/ChanSort.Loader.LG/DtvChannel.cs
+++ b/source/ChanSort.Loader.LG/DtvChannel.cs
@@ -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);
}
}
}
diff --git a/source/ChanSort.Loader.Samsung/DigitalChannel.cs b/source/ChanSort.Loader.Samsung/DigitalChannel.cs
index e5b2830..633926a 100644
--- a/source/ChanSort.Loader.Samsung/DigitalChannel.cs
+++ b/source/ChanSort.Loader.Samsung/DigitalChannel.cs
@@ -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;
diff --git a/source/ChanSort.Loader.Sony/ChanSort.Loader.Sony.csproj b/source/ChanSort.Loader.Sony/ChanSort.Loader.Sony.csproj
new file mode 100644
index 0000000..63c63f0
--- /dev/null
+++ b/source/ChanSort.Loader.Sony/ChanSort.Loader.Sony.csproj
@@ -0,0 +1,73 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {70E29C6B-B926-4859-9548-23375BF1E1B5}
+ Library
+ Properties
+ ChanSort.Loader.Sony
+ ChanSort.Loader.Sony
+ v4.0
+ 512
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ true
+ bin\x86\Debug\
+ DEBUG;TRACE
+ full
+ x86
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+ bin\x86\Release\
+ TRACE
+ true
+ pdbonly
+ x86
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {dccffa08-472b-4d17-bb90-8f513fc01392}
+ ChanSort.Api
+
+
+
+
\ No newline at end of file
diff --git a/source/ChanSort.Loader.Sony/Channel.cs b/source/ChanSort.Loader.Sony/Channel.cs
new file mode 100644
index 0000000..f6d71ce
--- /dev/null
+++ b/source/ChanSort.Loader.Sony/Channel.cs
@@ -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
+
+ }
+}
diff --git a/source/ChanSort.Loader.Sony/Properties/AssemblyInfo.cs b/source/ChanSort.Loader.Sony/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..a87d2b9
--- /dev/null
+++ b/source/ChanSort.Loader.Sony/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("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")]
diff --git a/source/ChanSort.Loader.Sony/Serializer.cs b/source/ChanSort.Loader.Sony/Serializer.cs
new file mode 100644
index 0000000..5d04875
--- /dev/null
+++ b/source/ChanSort.Loader.Sony/Serializer.cs
@@ -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();
+ 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 SplitLines(XmlNode parent)
+ {
+ var dict = new Dictionary();
+ 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 "1.1.0" differ in several ways from all other files (including 1.1.0):
+ // "\n" after the closing 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("");
+ end = this.IndexOf("") + 10; // including the \n at the end
+ expectedCrc = uint.Parse(node.InnerText, NumberStyles.HexNumber); // no 0x prefix
+ }
+ else
+ {
+ start = this.textContent.IndexOf("");
+ end = this.textContent.IndexOf("") + 9;
+ var text = this.textContent.Substring(start, end - start);
+ text = text.Replace("\r\n", "\n");
+ text = text.Replace(" />", "/>");
+ text = text.Replace("<", "<");
+ text = text.Replace(">", ">");
+ text = text.Replace(""", """);
+ text = text.Replace("&", "&");
+ text = text.Replace("'", "'");
+ text = text.Replace("'", "'");
+ 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 = "\r\n\r\n" + xml;
+ xml = xml.Replace("\r\n", "\r\n\r\n");
+ xml = xml.Replace("\r\n", "\r\n\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("{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
+ }
+}
diff --git a/source/ChanSort.Loader.Sony/SerializerPlugin.cs b/source/ChanSort.Loader.Sony/SerializerPlugin.cs
new file mode 100644
index 0000000..82ef869
--- /dev/null
+++ b/source/ChanSort.Loader.Sony/SerializerPlugin.cs
@@ -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);
+ }
+ }
+}
diff --git a/source/ChanSort.sln b/source/ChanSort.sln
index 2d85bca..fb494e8 100644
--- a/source/ChanSort.sln
+++ b/source/ChanSort.sln
@@ -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
diff --git a/source/ChanSort/ChanSort.csproj b/source/ChanSort/ChanSort.csproj
index a52f098..bf276a6 100644
--- a/source/ChanSort/ChanSort.csproj
+++ b/source/ChanSort/ChanSort.csproj
@@ -396,6 +396,10 @@
{e6279ff8-362a-41e6-ac0d-d0861d43f01c}
ChanSort.Loader.SilvaSchneider
+
+ {70e29c6b-b926-4859-9548-23375bf1e1b5}
+ ChanSort.Loader.Sony
+
{f6f02792-07f1-48d5-9af3-f945ca5e3931}
ChanSort.Loader.Toshiba
diff --git a/source/ChanSort/MainForm.Designer.cs b/source/ChanSort/MainForm.Designer.cs
index 1da46e5..d3ba2d2 100644
--- a/source/ChanSort/MainForm.Designer.cs
+++ b/source/ChanSort/MainForm.Designer.cs
@@ -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;
}
}
diff --git a/source/ChanSort/MainForm.cs b/source/ChanSort/MainForm.cs
index 2241416..9a1f59b 100644
--- a/source/ChanSort/MainForm.cs
+++ b/source/ChanSort/MainForm.cs
@@ -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();
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
diff --git a/source/ChanSort/MainForm.de.resx b/source/ChanSort/MainForm.de.resx
index 51d7ccc..0d186a6 100644
--- a/source/ChanSort/MainForm.de.resx
+++ b/source/ChanSort/MainForm.de.resx
@@ -628,4 +628,10 @@ speziellen Anbieter, Satelliten oder Länderlisten aus.
Quelle
+
+ Windows Explorer Integration
+
+
+ Nach Programmupdates suchen
+
\ No newline at end of file
diff --git a/source/ChanSort/MainForm.resx b/source/ChanSort/MainForm.resx
index 65bbfe5..5e3d81a 100644
--- a/source/ChanSort/MainForm.resx
+++ b/source/ChanSort/MainForm.resx
@@ -666,7 +666,10 @@
37
- Windows Explorer Integration (handle file extensions)
+ Windows Explorer Integration
+
+
+ Check for updates
&Accessibility
@@ -1252,7 +1255,7 @@
globalImageCollection1
- ChanSort.Ui.GlobalImageCollection, ChanSort, Version=1.0.7133.39305, Culture=neutral, PublicKeyToken=null
+ ChanSort.Ui.GlobalImageCollection, ChanSort, Version=1.0.7134.23381, Culture=neutral, PublicKeyToken=null
gviewRight
@@ -1968,6 +1971,12 @@
DevExpress.XtraBars.PopupMenu, DevExpress.XtraBars.v19.1, Version=19.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a
+
+ miCheckUpdates
+
+
+ DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v19.1, Version=19.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a
+
MainForm
@@ -1975,7 +1984,7 @@
DevExpress.XtraEditors.XtraForm, DevExpress.Utils.v19.1, Version=19.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a
- 07/13/2019 21:51:28
+ 07/14/2019 13:16:32
16, 16
diff --git a/source/ChanSort/Properties/Settings.Designer.cs b/source/ChanSort/Properties/Settings.Designer.cs
index f649572..17667cb 100644
--- a/source/ChanSort/Properties/Settings.Designer.cs
+++ b/source/ChanSort/Properties/Settings.Designer.cs
@@ -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;
+ }
+ }
}
}
diff --git a/source/ChanSort/Properties/Settings.settings b/source/ChanSort/Properties/Settings.settings
index 0c66398..bc8ca8e 100644
--- a/source/ChanSort/Properties/Settings.settings
+++ b/source/ChanSort/Properties/Settings.settings
@@ -116,5 +116,8 @@
False
+
+ True
+
\ No newline at end of file
diff --git a/source/ChanSort/app.config b/source/ChanSort/app.config
index 031a9a9..05b2ed6 100644
--- a/source/ChanSort/app.config
+++ b/source/ChanSort/app.config
@@ -122,6 +122,9 @@
False
+
+ True
+
diff --git a/source/Translation.xlsx b/source/Translation.xlsx
index c891a94..c11c2ca 100644
Binary files a/source/Translation.xlsx and b/source/Translation.xlsx differ
diff --git a/source/changelog.md b/source/changelog.md
index 6347894..63f5df6 100644
--- a/source/changelog.md
+++ b/source/changelog.md
@@ -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