mirror of
https://github.com/PredatH0r/ChanSort.git
synced 2026-05-07 06:16:41 +02:00
- experimental support for Grundig and ChangHong atv\_cmdb.bin files (analog antenna and cable TV)
- Reference list dialog further optimized to fit 1920x1080 @150% or 1024x768 @100% screens - re-imported translation file (to fix incorrect letters in language names like "Русский") - upgrade to DevExpress 22.1 libraries
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
@@ -29,6 +30,7 @@
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
|
||||
@@ -124,6 +124,29 @@ offName=144
|
||||
lenName=50
|
||||
|
||||
|
||||
|
||||
# H.P. 20220608 Grundig 1341 KB dtv_cmdb_3.bin (only analog data in atv_cmdb_cable.bin is present)
|
||||
[atv_cmdb.bin:3148]
|
||||
offProgNrList=0x01
|
||||
lenProgNrList=100
|
||||
offChannelBitmap=0x66
|
||||
lenChannelBitmap=13
|
||||
offChannelRecord=0x74
|
||||
lenChannelRecord=30
|
||||
[atv_cmdb_cable.bin:3148]
|
||||
offProgNrList=0x01
|
||||
lenProgNrList=101
|
||||
offChannelBitmap=0x66
|
||||
lenChannelBitmap=13
|
||||
offChannelRecord=0x74
|
||||
lenChannelRecord=30
|
||||
[avbChannel:30]
|
||||
offFrequency=0
|
||||
offSort=14
|
||||
offName=16
|
||||
lenName=8
|
||||
|
||||
|
||||
# ChangHong 1489 KB
|
||||
|
||||
[dtv_cmdb_2.bin:1524001]
|
||||
@@ -280,6 +303,25 @@ offName=2
|
||||
lenName=22
|
||||
offOrbitalPos=38
|
||||
|
||||
[atv_cmdb.bin:13092]
|
||||
offProgNrList=0x01
|
||||
lenProgNrList=256
|
||||
offChannelBitmap=0x101
|
||||
lenChannelBitmap=32
|
||||
offChannelRecord=0x121
|
||||
lenChannelRecord=50
|
||||
[atv_cmdb_cable.bin:13092]
|
||||
offProgNrList=0x01
|
||||
lenProgNrList=256
|
||||
offChannelBitmap=0x101
|
||||
lenChannelBitmap=32
|
||||
offChannelRecord=0x121
|
||||
lenChannelRecord=50
|
||||
[avbChannel:50]
|
||||
;offFrequency=0
|
||||
;offSort=14
|
||||
offName=15
|
||||
lenName=28
|
||||
|
||||
|
||||
# blackbox - 4532 KB
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.CodeDom;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ChanSort.Api;
|
||||
|
||||
@@ -9,19 +10,25 @@ namespace ChanSort.Loader.CmdbBin
|
||||
public class CmdbFileSerializer : SerializerBase
|
||||
{
|
||||
private IniFile ini;
|
||||
private readonly ChannelList dvbsTv = new ChannelList(SignalSource.DvbS | SignalSource.Tv, "Sat TV");
|
||||
private readonly ChannelList dvbsRadio = new ChannelList(SignalSource.DvbS | SignalSource.Radio, "Sat Radio");
|
||||
private readonly ChannelList dvbsData = new ChannelList(SignalSource.DvbS | SignalSource.Radio, "Sat Data");
|
||||
private readonly List<string> files = new();
|
||||
private readonly ChannelList avbtTv = new (SignalSource.AnalogT | SignalSource.Tv, "Analog Antenna TV");
|
||||
private readonly ChannelList avbcTv = new (SignalSource.AnalogC | SignalSource.Tv, "Analog Cable TV");
|
||||
private readonly ChannelList dvbsTv = new (SignalSource.DvbS | SignalSource.Tv, "Sat TV");
|
||||
private readonly ChannelList dvbsRadio = new (SignalSource.DvbS | SignalSource.Radio, "Sat Radio");
|
||||
private readonly ChannelList dvbsData = new (SignalSource.DvbS | SignalSource.Radio, "Sat Data");
|
||||
private DvbStringDecoder dvbStringDecoder;
|
||||
private bool loaded;
|
||||
private readonly StringBuilder protocol = new StringBuilder();
|
||||
private readonly StringBuilder protocol = new ();
|
||||
|
||||
public CmdbFileSerializer(string inputFile) : base(inputFile)
|
||||
{
|
||||
this.Features.FavoritesMode = FavoritesMode.Flags;
|
||||
this.Features.MaxFavoriteLists = 1;
|
||||
this.Features.DeleteMode = DeleteMode.FlagWithoutPrNr; // TODO there can be lots of channels in each list with number 65534, which seems to indicate user-deleted
|
||||
this.Features.ChannelNameEdit = ChannelNameEditMode.Analog;
|
||||
|
||||
this.DataRoot.AddChannelList(avbtTv);
|
||||
this.DataRoot.AddChannelList(avbcTv);
|
||||
this.DataRoot.AddChannelList(dvbsTv);
|
||||
this.DataRoot.AddChannelList(dvbsRadio);
|
||||
// this.DataRoot.AddChannelList(dvbsData); // there seem to be multiple data lists with Toshiba TVs which all have their own numbering starting at 1. Better don't show data channels at all than dupes
|
||||
@@ -52,6 +59,12 @@ namespace ChanSort.Loader.CmdbBin
|
||||
case "dtv_cmdb_2.bin":
|
||||
LoadFile(file, this.dvbsTv, this.dvbsRadio, this.dvbsData);
|
||||
break;
|
||||
case "atv_cmdb.bin":
|
||||
LoadFile(file, this.avbtTv, null, null);
|
||||
break;
|
||||
case "atv_cmdb_cable.bin":
|
||||
LoadFile(file, this.avbcTv, null, null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,25 +86,46 @@ namespace ChanSort.Loader.CmdbBin
|
||||
return;
|
||||
}
|
||||
|
||||
LoadBitmappedRecords(data, sec, "Satellite", ReadSatellite);
|
||||
LoadBitmappedRecords(data, sec, "Transponder", ReadTransponder);
|
||||
LoadBitmappedRecords(data, sec, "Channel", (map, index, len) => ReadChannel(map, tvList, radioList, dataList, index, len));
|
||||
if ((tvList.SignalSource & SignalSource.Analog) != 0)
|
||||
{
|
||||
var seq = LoadAnalogProgramNumbers(data, sec);
|
||||
LoadBitmappedRecords(data, sec, "avb", "Channel", (map, index, len) => ReadAnalogChannel(map, tvList, seq, index, len));
|
||||
}
|
||||
else
|
||||
{
|
||||
LoadBitmappedRecords(data, sec, "dvbs", "Satellite", ReadSatellite);
|
||||
LoadBitmappedRecords(data, sec, "dvbs", "Transponder", ReadTransponder);
|
||||
LoadBitmappedRecords(data, sec, "dvbs", "Channel", (map, index, len) => ReadDigitalChannel(map, tvList, radioList, dataList, index, len));
|
||||
}
|
||||
|
||||
this.loaded = true;
|
||||
this.files.Add(file);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region LoadAnalogProgramNumbers()
|
||||
private byte[] LoadAnalogProgramNumbers(byte[] data, IniFile.Section sec)
|
||||
{
|
||||
var off = sec.GetInt("offProgNrList");
|
||||
var len = sec.GetInt("lenProgNrList");
|
||||
var bytes = new byte[len];
|
||||
Array.Copy(data, off, bytes, 0, len);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region LoadBitmappedRecords()
|
||||
private void LoadBitmappedRecords(byte[] data, IniFile.Section sec, string recordType, Action<DataMapping, int, int> readRecord)
|
||||
private void LoadBitmappedRecords(byte[] data, IniFile.Section sec, string recordSectionPrefix, string recordType, Action<DataMapping, int, int> readRecord)
|
||||
{
|
||||
var lenRecord = sec.GetInt($"len{recordType}Record");
|
||||
var map = new DataMapping(this.ini.GetSection($"dvbs{recordType}:{lenRecord}"));
|
||||
var map = new DataMapping(this.ini.GetSection($"{recordSectionPrefix}{recordType}:{lenRecord}"));
|
||||
map.DefaultEncoding = this.DefaultEncoding;
|
||||
map.SetDataPtr(data, sec.GetInt($"off{recordType}Record"));
|
||||
|
||||
var off = sec.GetInt($"off{recordType}Bitmap");
|
||||
var len = sec.GetInt($"len{recordType}Bitmap");
|
||||
var count = sec.GetInt($"num{recordType}Record");
|
||||
var count = sec.GetInt($"num{recordType}Record", short.MaxValue);
|
||||
int index = 0;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
@@ -101,7 +135,8 @@ namespace ChanSort.Loader.CmdbBin
|
||||
if ((b & mask) != 0)
|
||||
readRecord(map, index, lenRecord);
|
||||
map.BaseOffset += lenRecord;
|
||||
if (++index >= count)
|
||||
++index;
|
||||
if (index >= count)
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -132,9 +167,23 @@ namespace ChanSort.Loader.CmdbBin
|
||||
this.DataRoot.AddTransponder(tp.Satellite, tp);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ReadAnalogChannel
|
||||
private void ReadAnalogChannel(DataMapping chanMap, ChannelList list, byte[] progNrList, int recordIndex, int recordLength)
|
||||
{
|
||||
var channelNameLength = chanMap.Settings.GetInt("lenName");
|
||||
var name = chanMap.GetString("offName", channelNameLength).TrimEnd(new[] { '\0', ' ' });
|
||||
var progNr = Array.IndexOf(progNrList, (byte)recordIndex) + 1;
|
||||
var ch = new ChannelInfo(list.SignalSource, recordIndex, progNr, name);
|
||||
ch.FreqInMhz = (decimal)chanMap.GetWord("offFrequency") * 50 / 1000;
|
||||
//if ((list.SignalSource & SignalSource.Cable) != 0)
|
||||
// ch.ChannelOrTransponder = LookupData.Instance.GetDvbcChannelName(ch.FreqInMhz + ((list.SignalSource & SignalSource.Analog) != 0 ? 2.75m : 0)); //
|
||||
this.DataRoot.AddChannel(list, ch);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ReadChannel()
|
||||
private void ReadChannel(DataMapping chanMap, ChannelList tvList, ChannelList radioList, ChannelList dataList, int recordIndex, int recordLength)
|
||||
#region ReadDigitalChannel()
|
||||
private void ReadDigitalChannel(DataMapping chanMap, ChannelList tvList, ChannelList radioList, ChannelList dataList, int recordIndex, int recordLength)
|
||||
{
|
||||
var channelType = (int)chanMap.GetByte("offChannelType");
|
||||
if (channelType == 0) // some file format versions store the channel type in the upper nibble of a byte
|
||||
@@ -223,16 +272,38 @@ namespace ChanSort.Loader.CmdbBin
|
||||
|
||||
|
||||
#region Save()
|
||||
|
||||
public override void Save(string tvOutputFile)
|
||||
{
|
||||
// save-as is not supported
|
||||
// save-as is not supported, the tvOutputFile is ignored
|
||||
|
||||
// TODO: currently hardcoded to support only dtv_cmdb_2.bin
|
||||
foreach (var path in this.files)
|
||||
{
|
||||
var name = Path.GetFileName(path).ToLowerInvariant();
|
||||
switch (name)
|
||||
{
|
||||
case "dtv_cmdb_2.bin":
|
||||
SaveDtvCmdb(path, "dvbsChannel", SignalSource.DvbS);
|
||||
break;
|
||||
case "atv_cmdb.bin":
|
||||
SaveAtvCmdb(path, "avbChannel", this.avbtTv);
|
||||
break;
|
||||
case "atv_cmdb_cable.bin":
|
||||
SaveAtvCmdb(path, "avbChannel", this.avbcTv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
var data = File.ReadAllBytes(this.FileName); // filename is currently always the dtv_cmdb_2.bin, even if the user selected another file
|
||||
var config = this.ini.GetSection("dtv_cmdb_2.bin:" + data.Length);
|
||||
#region SaveDtvCmdb()
|
||||
private void SaveDtvCmdb(string path, string channelSectionName, SignalSource sourceMask)
|
||||
{
|
||||
var data = File.ReadAllBytes(path);
|
||||
var name = Path.GetFileName(path).ToLowerInvariant();
|
||||
var config = this.ini.GetSection(name + ":" + data.Length);
|
||||
var lenChannelRecord = config.GetInt("lenChannelRecord");
|
||||
var sec = this.ini.GetSection($"dvbsChannel:{lenChannelRecord}");
|
||||
var sec = this.ini.GetSection($"{channelSectionName}:{lenChannelRecord}");
|
||||
sec.Set("offChecksum", lenChannelRecord - 4);
|
||||
var mapping = new DataMapping(sec);
|
||||
|
||||
@@ -240,6 +311,8 @@ namespace ChanSort.Loader.CmdbBin
|
||||
|
||||
foreach (var list in this.DataRoot.ChannelLists)
|
||||
{
|
||||
if ((list.SignalSource & (SignalSource.MaskAnalogDigital | SignalSource.MaskAntennaCableSat)) != sourceMask)
|
||||
continue;
|
||||
foreach (var chan in list.Channels)
|
||||
{
|
||||
mapping.SetDataPtr(data, baseOffset + (int)chan.RecordIndex * lenChannelRecord);
|
||||
@@ -262,6 +335,48 @@ namespace ChanSort.Loader.CmdbBin
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SaveAtvCmdb()
|
||||
private void SaveAtvCmdb(string path, string channelSectionName, ChannelList list)
|
||||
{
|
||||
var data = File.ReadAllBytes(path);
|
||||
var name = Path.GetFileName(path).ToLowerInvariant();
|
||||
var config = this.ini.GetSection(name + ":" + data.Length);
|
||||
var lenChannelRecord = config.GetInt("lenChannelRecord");
|
||||
|
||||
var offProgNrList = config.GetInt("offProgNrList");
|
||||
var lenProgNrList = config.GetInt("lenProgNrList");
|
||||
|
||||
|
||||
var sec = this.ini.GetSection($"{channelSectionName}:{lenChannelRecord}");
|
||||
var mapping = new DataMapping(sec);
|
||||
var offChannelBitmap = config.GetInt("offChannelBitmap");
|
||||
var offChannelRecord = config.GetInt("offChannelRecord");
|
||||
|
||||
var maxNameLen = mapping.Settings.GetInt("lenName");
|
||||
|
||||
data.MemSet(offProgNrList, 0xFD, lenProgNrList);
|
||||
|
||||
foreach (var chan in list.Channels)
|
||||
{
|
||||
if (chan.NewProgramNr > 0 && chan.NewProgramNr < lenProgNrList)
|
||||
data[offProgNrList + chan.NewProgramNr - 1] = (byte)chan.RecordIndex;
|
||||
|
||||
if (chan.IsNameModified)
|
||||
{
|
||||
mapping.SetDataPtr(data, offChannelRecord + (int)chan.RecordIndex * lenChannelRecord);
|
||||
mapping.SetString("offName", chan.Name, maxNameLen);
|
||||
}
|
||||
|
||||
if (chan.IsDeleted)
|
||||
{
|
||||
var idx = (int)chan.RecordIndex;
|
||||
data[offChannelBitmap + idx / 8] &= (byte) ~(1 << (idx & 0x07));
|
||||
}
|
||||
}
|
||||
|
||||
File.WriteAllBytes(path, data);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetFileInformation()
|
||||
public override string GetFileInformation()
|
||||
@@ -269,5 +384,7 @@ namespace ChanSort.Loader.CmdbBin
|
||||
return base.GetFileInformation() + "\n\n" + protocol;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public override IEnumerable<string> GetDataFilePaths() => this.files.ToList(); // these files will be backed up / restored
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user