mirror of
https://github.com/PredatH0r/ChanSort.git
synced 2026-02-21 13:56:46 +01:00
- DX upgrade
- experimental support for Philips Repair\mgr_chan_s_fta.db file format (DVB-S only) - fixed missing strings for LG empty-channel-list message box
This commit is contained in:
@@ -46,7 +46,7 @@ namespace ChanSort.Loader.Philips
|
||||
Used in format version 30 (not 45) as a 3rd file containing program numbers. SQLite database containing tables "AnalogTable" and "DigSrvTable".
|
||||
|
||||
*/
|
||||
class BinarySerializer : SerializerBase
|
||||
public class BinarySerializer : SerializerBase
|
||||
{
|
||||
private readonly IniFile ini;
|
||||
private readonly List<string> dataFilePaths = new List<string>();
|
||||
|
||||
@@ -96,6 +96,7 @@
|
||||
<Compile Include="ChanLstBin.cs" />
|
||||
<Compile Include="Channel.cs" />
|
||||
<Compile Include="CustomXmlWriter.cs" />
|
||||
<Compile Include="DbSerializer.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="BinarySerializer.cs" />
|
||||
<Compile Include="PhilipsPlugin.cs" />
|
||||
|
||||
@@ -105,3 +105,23 @@ setFavoriteNumber=false
|
||||
[Map110]
|
||||
incrementFavListVersion=true
|
||||
setFavoriteNumber=false
|
||||
|
||||
# Format with Repair\ folder containing channel_db_ver.db, atv_chan_phy_c.db, FLASH_DTVINFO_S_FTA, mgr_chan_s_fta.db, ...
|
||||
|
||||
[mgr_chan_s_fta.db]
|
||||
lenHeader=64
|
||||
lenEntry=476
|
||||
lenFooter=12
|
||||
offFooterChecksum=8
|
||||
|
||||
[mgr_chan_s_fta.db_entry]
|
||||
offProgNr=0,452
|
||||
offName=20
|
||||
offFav=16
|
||||
lenName=200
|
||||
offFreq=444,468
|
||||
offSymbolRate=450
|
||||
offPrevProgNr=456
|
||||
offTsid=460
|
||||
offSid=464
|
||||
offOnid=466
|
||||
|
||||
186
source/ChanSort.Loader.Philips/DbSerializer.cs
Normal file
186
source/ChanSort.Loader.Philips/DbSerializer.cs
Normal file
@@ -0,0 +1,186 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using ChanSort.Api;
|
||||
|
||||
namespace ChanSort.Loader.Philips
|
||||
{
|
||||
/*
|
||||
* This serializer is used for the channel list format with a Repair\ folder containing files like channel_db_ver.db, mgr_chan_s_fta.db, ...
|
||||
* The .db files are proprietary binary files, not SQLite databases.
|
||||
* So far only the mgr_chan_s_fta.db file holing DVB-S channels is reverse engineered, the offsets are defined in PChanSort.Loader.Philips.ini
|
||||
*/
|
||||
class DbSerializer : SerializerBase
|
||||
{
|
||||
private readonly IniFile ini;
|
||||
private readonly List<string> dataFilePaths = new List<string>();
|
||||
|
||||
private readonly ChannelList dvbsChannels = new ChannelList(SignalSource.DvbS, "DVB-S");
|
||||
|
||||
|
||||
public DbSerializer(string inputFile) : base(inputFile)
|
||||
{
|
||||
this.Features.MaxFavoriteLists = 1;
|
||||
this.Features.FavoritesMode = FavoritesMode.OrderedPerSource;
|
||||
this.Features.DeleteMode = DeleteMode.NotSupported;
|
||||
|
||||
string iniFile = Assembly.GetExecutingAssembly().Location.Replace(".dll", ".ini");
|
||||
this.ini = new IniFile(iniFile);
|
||||
|
||||
this.DataRoot.AddChannelList(dvbsChannels);
|
||||
dvbsChannels.VisibleColumnFieldNames = new List<string>
|
||||
{
|
||||
"Position", //nameof(Channel.NewProgramNr),
|
||||
"OldPosition", // nameof(Channel.OldProgramNr),
|
||||
nameof(Channel.Name),
|
||||
nameof(Channel.Favorites),
|
||||
nameof(Channel.FreqInMhz),
|
||||
nameof(Channel.SymbolRate),
|
||||
nameof(Channel.TransportStreamId),
|
||||
nameof(Channel.OriginalNetworkId),
|
||||
nameof(Channel.ServiceId)
|
||||
};
|
||||
}
|
||||
|
||||
#region Load()
|
||||
public override void Load()
|
||||
{
|
||||
bool validList = false;
|
||||
|
||||
foreach (var file in Directory.GetFiles(Path.GetDirectoryName(this.FileName)))
|
||||
{
|
||||
var lc = Path.GetFileName(file).ToLowerInvariant();
|
||||
switch (lc)
|
||||
{
|
||||
case "mgr_chan_s_fta.db":
|
||||
LoadDvbs(file);
|
||||
validList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!validList)
|
||||
throw new FileLoadException(this.FileName + " is not a supported Philips Repair/mgr_chan_s_fta.db channel list");
|
||||
}
|
||||
|
||||
private void LoadDvbs(string file)
|
||||
{
|
||||
var data = File.ReadAllBytes(file);
|
||||
|
||||
var sec = ini.GetSection("mgr_chan_s_fta.db");
|
||||
var lenHeader = sec.GetInt("lenHeader");
|
||||
var lenFooter = sec.GetInt("lenFooter");
|
||||
var lenEntry = sec.GetInt("lenEntry");
|
||||
var offFooterChecksum = sec.GetInt("offFooterChecksum");
|
||||
|
||||
var records = (data.Length - lenHeader - lenFooter) / lenEntry;
|
||||
if (records <= 0)
|
||||
throw new FileLoadException("Currently only DVB-S lists are supported and mgr_chan_s_fta.db contains no channels.");
|
||||
|
||||
var mapping = new DataMapping(this.ini.GetSection("mgr_chan_s_fta.db_entry"));
|
||||
sec = ini.GetSection("mgr_chan_s_fta.db_entry");
|
||||
var lenName = sec.GetInt("lenName");
|
||||
for (int i = 0; i < records; i++)
|
||||
{
|
||||
mapping.SetDataPtr(data, lenHeader + i * lenEntry);
|
||||
var oldProgNr = mapping.GetWord("offProgNr");
|
||||
|
||||
// name can be either an 8-bit ASCII with unspecified encoding or big-endian 16-bit unicode
|
||||
var off = mapping.BaseOffset + mapping.GetOffsets("offName")[0];
|
||||
var name = data[off + 0] == 0 ? (data[off + 1] == 0 ? "" : Encoding.BigEndianUnicode.GetString(data, off, lenName)) : DefaultEncoding.GetString(data, off, lenName);
|
||||
name = name.TrimEnd('\0');
|
||||
|
||||
var ch = new Channel(SignalSource.DvbS, i, oldProgNr, name);
|
||||
ch.RecordOrder = i;
|
||||
var favPos = mapping.GetWord("offFav");
|
||||
if (favPos > 0)
|
||||
ch.SetOldPosition(1, favPos);
|
||||
ch.SymbolRate = mapping.GetWord("offSymbolRate");
|
||||
ch.FreqInMhz = mapping.GetWord("offFreq");
|
||||
ch.TransportStreamId = mapping.GetWord("offTsid");
|
||||
ch.OriginalNetworkId = mapping.GetWord("offOnid");
|
||||
ch.ServiceId = mapping.GetWord("offSid");
|
||||
this.DataRoot.AddChannel(dvbsChannels, ch);
|
||||
}
|
||||
|
||||
var offChecksum = data.Length - lenFooter + offFooterChecksum;
|
||||
var expectedChecksum = BitConverter.ToUInt16(data, offChecksum);
|
||||
var actualChecksum = CalcChecksum(data, 0, offChecksum);
|
||||
if (actualChecksum != expectedChecksum)
|
||||
throw new FileLoadException($"File {file} contains invalid checksum. Expected {expectedChecksum:x4} but calculated {actualChecksum:x4}");
|
||||
|
||||
this.dataFilePaths.Add(file);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CalcChecksum()
|
||||
|
||||
/// <summary>
|
||||
/// The checksum is the 16-bit sum over the byte-values in the file data from offset 0 to right before the checksum field
|
||||
/// </summary>
|
||||
private ushort CalcChecksum(byte[] data, int start, int len)
|
||||
{
|
||||
ushort checksum = 0;
|
||||
while (len > 0)
|
||||
{
|
||||
checksum += data[start++];
|
||||
--len;
|
||||
}
|
||||
|
||||
return checksum;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public override IEnumerable<string> GetDataFilePaths() => this.dataFilePaths.ToList();
|
||||
|
||||
#region Save()
|
||||
|
||||
public override void Save(string tvOutputFile)
|
||||
{
|
||||
foreach (var file in this.dataFilePaths)
|
||||
{
|
||||
var lc = Path.GetFileName(file).ToLowerInvariant();
|
||||
switch (lc)
|
||||
{
|
||||
case "mgr_chan_s_fta.db":
|
||||
SaveDvbs(file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveDvbs(string file)
|
||||
{
|
||||
var data = File.ReadAllBytes(file);
|
||||
|
||||
var sec = ini.GetSection("mgr_chan_s_fta.db");
|
||||
var lenHeader = sec.GetInt("lenHeader");
|
||||
var lenFooter = sec.GetInt("lenFooter");
|
||||
var lenEntry = sec.GetInt("lenEntry");
|
||||
var offFooterChecksum = sec.GetInt("offFooterChecksum");
|
||||
|
||||
var mapping = new DataMapping(ini.GetSection("mgr_chan_s_fta.db_entry"));
|
||||
|
||||
// update channel data
|
||||
foreach (var ch in dvbsChannels.Channels)
|
||||
{
|
||||
mapping.SetDataPtr(data, lenHeader + ch.RecordOrder * lenEntry);
|
||||
mapping.SetWord("offProgNr", ch.NewProgramNr);
|
||||
mapping.SetWord("offPrevProgNr", ch.NewProgramNr - 1);
|
||||
mapping.SetWord("offFav", Math.Max(0, ch.GetPosition(1)));
|
||||
}
|
||||
|
||||
// update checksum
|
||||
var offChecksum = data.Length - lenFooter + offFooterChecksum;
|
||||
var checksum = CalcChecksum(data, 0, offChecksum);
|
||||
data[offChecksum] = (byte)checksum;
|
||||
data[offChecksum + 1] = (byte)(checksum >> 8);
|
||||
|
||||
File.WriteAllBytes(file, data);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ namespace ChanSort.Loader.Philips
|
||||
|
||||
public string DllName { get; set; }
|
||||
public string PluginName => "Philips";
|
||||
public string FileFilter => "*.bin;*.xml";
|
||||
public string FileFilter => "*.bin;*.xml;*.db";
|
||||
|
||||
public SerializerBase CreateSerializer(string inputFile)
|
||||
{
|
||||
@@ -103,6 +103,14 @@ namespace ChanSort.Loader.Philips
|
||||
break;
|
||||
}
|
||||
|
||||
path = Path.Combine(dir, "channel_db_ver.db");
|
||||
if (File.Exists(path))
|
||||
{
|
||||
inputFile = path;
|
||||
majorVersion = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
var dirName = Path.GetFileName(dir).ToLower();
|
||||
if (dirName == "channellib" || dirName == "s2channellib")
|
||||
dir = Path.GetDirectoryName(dir);
|
||||
@@ -125,6 +133,8 @@ namespace ChanSort.Loader.Philips
|
||||
return new XmlSerializer(inputFile);
|
||||
if (majorVersion == 1 || majorVersion == 30 || majorVersion == 45) // || majorVersion == 11 // format version 11 is similar to 1.x, but not (yet) supported
|
||||
return new BinarySerializer(inputFile);
|
||||
if (majorVersion == -1)
|
||||
return new DbSerializer(inputFile);
|
||||
|
||||
throw new FileLoadException($"Philips ChannelMap format version {majorVersion} is not supported.");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user