- fixed loading .txt reference lists

- added support for HB\_DATABASE\_\*.DBM channel lists with file size 74303  (e.g. Renkforce 1510 C HD, Telestar digiHD TC 7)
- added support for dtv_cmdb_2.bin files with file size 2731173  (e.g. Dijitsu Android TV with LD-M538 board)
- improved experimental support for amdb\*.db Android STB channel lists  (now grouped by TV and radio for each satellite)
- combined HHD Hex Editor Neo structure definition files for HB_DATABASE.DBM file formats
This commit is contained in:
Horst Beham
2023-10-22 21:43:46 +02:00
parent 56676748b7
commit 8ac45d5729
17 changed files with 559 additions and 88 deletions

View File

@@ -4,6 +4,9 @@ using System.Text;
namespace ChanSort.Api
{
/// <summary>
/// This class reads .txt files where each line has the format: progNr;name;onid-tsid-sid
/// </summary>
public class TxtRefListSerializer : SerializerBase
{
private static readonly char[] Separators = { ';' };
@@ -68,7 +71,7 @@ namespace ChanSort.Api
if (!int.TryParse(parts[0], out progNr))
continue;
var channel = new ChannelInfo(SignalSource.All, lineNr, progNr, parts[1]);
var channel = new ChannelInfo(SignalSource.Any, lineNr, progNr, parts[1]);
if (parts.Length >= 3)
{
var subParts = parts[2].Split('-');
@@ -84,7 +87,6 @@ namespace ChanSort.Api
}
}
this.DataRoot.AddChannel(this.allChannels, channel);
lineNr++;
}
}

View File

@@ -0,0 +1,88 @@
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
namespace ChanSort.Api.Utils;
public class ListDictionary<K,V> : IDictionary<K,V>
{
private readonly ListDictionary dict = new();
public IEnumerator<KeyValuePair<K, V>> GetEnumerator() => (IEnumerator<KeyValuePair<K, V>>)dict.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => dict.GetEnumerator();
public void Add(KeyValuePair<K, V> item) => dict.Add(item.Key, item.Value);
public void Clear() => dict.Clear();
public bool Contains(KeyValuePair<K, V> item)
{
var val = dict[item.Key];
return val != null && Equals(val, item.Value);
}
public void CopyTo(KeyValuePair<K, V>[] array, int arrayIndex)
{
var i = arrayIndex;
foreach (DictionaryEntry entry in dict)
array[i++] = new KeyValuePair<K, V>((K)entry.Key, (V)entry.Value);
}
public bool Remove(KeyValuePair<K, V> item)
{
var val = dict[item.Key];
if (val != null && Equals(val, item.Value))
{
dict.Remove(item.Key);
return true;
}
return false;
}
public int Count => dict.Count;
public bool IsReadOnly => dict.IsReadOnly;
public bool ContainsKey(K key) => dict.Contains(key);
public void Add(K key, V value) => dict.Add(key, value);
public bool Remove(K key)
{
if (!dict.Contains(key))
return false;
dict.Remove(key);
return true;
}
public bool TryGetValue(K key, out V value)
{
var obj = dict[key];
if (obj == null)
{
value = default;
return false;
}
value = (V)obj;
return true;
}
public V this[K key]
{
get => (V)dict[key];
set => dict[key] = value;
}
public ICollection<K> Keys => (ICollection<K>)dict.Keys;
public ICollection<V> Values
{
get
{
var list = new List<V>();
foreach(DictionaryEntry e in dict)
list.Add((V)e.Value);
return list;
}
}
}

View File

@@ -1,20 +1,29 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Data.Sqlite;
using ChanSort.Api;
using ChanSort.Api.Utils;
namespace ChanSort.Loader.Amdb
{
/*
* This class loads amdb*.db files from unknown Android set-top-boxes.
* The srv_table contains two columns which somehow represent an order, but neither is the actual program number as shown in the menu.
* chan_num: seems to be grouped by service type (TV, Radio, Other) across satellites, each group starting at 1
* chan_order: is probably the order in which the channels where found during the scan. mostly ordered by satellite, but not strictly
* major_chan_num: always 0 (for DVB-S)
* Regardless of these columns, the receiver displays each combination of TV/Radio and satellite as a separate list starting at 1
*/
class AmdbSerializer : SerializerBase
{
private readonly HashSet<string> tableNames = new();
private readonly ChannelList tv = new (SignalSource.Tv, "TV");
private readonly ChannelList radio = new(SignalSource.Radio, "Radio");
private readonly ChannelList data = new(SignalSource.Data, "Data");
private readonly IDictionary<Tuple<SignalSource, int>, ChannelList> listBySatellite = new ListDictionary<Tuple<SignalSource, int>, ChannelList>();
private static readonly SignalSource[] SignalSources = { SignalSource.Tv, SignalSource.Radio, SignalSource.Data };
private static readonly string[] SignalSourceNames = { "TV", "Radio", "Other" };
private readonly Dictionary<int, int> onidByNetId = new Dictionary<int, int>();
#region ctor()
public AmdbSerializer(string inputFile) : base(inputFile)
@@ -27,10 +36,6 @@ namespace ChanSort.Loader.Amdb
this.Features.CanHaveGaps = false;
this.Features.AllowGapsInFavNumbers = false;
this.Features.FavoritesMode = FavoritesMode.None;
this.DataRoot.AddChannelList(tv);
this.DataRoot.AddChannelList(radio);
this.DataRoot.AddChannelList(data);
}
#endregion
@@ -56,6 +61,7 @@ namespace ChanSort.Loader.Amdb
throw LoaderException.TryNext("File doesn't contain the expected tables");
this.ReadSatellites(cmd);
this.ReadNetworks(cmd);
this.ReadTransponders(cmd);
this.ReadChannels(cmd);
this.AdjustColumns();
@@ -91,31 +97,61 @@ namespace ChanSort.Loader.Amdb
pos = 360 - pos;
eastWest = "W";
}
sat.OrbitalPosition = $"{pos / 10}.{pos % 10}{eastWest}";
sat.Name = r.GetString(1);
this.DataRoot.AddSatellite(sat);
int i = 0;
foreach (var ss in SignalSources)
{
var list = new ChannelList(SignalSource.Sat | ss, SignalSourceNames[i++] + " " + sat.Name);
this.listBySatellite[Tuple.Create(ss, sat.Id)] = list;
}
}
foreach (var entry in this.listBySatellite.OrderBy(e => e.Key.Item1))
{
if ((entry.Key.Item1 & SignalSource.Data) != 0)
continue;
this.DataRoot.AddChannelList(entry.Value);
}
}
#endregion
#region ReadNetworks()
private void ReadNetworks(SqliteCommand cmd)
{
cmd.CommandText = "select db_id, network_id from net_table";
using var r = cmd.ExecuteReader();
while (r.Read())
onidByNetId[r.GetInt32(0)] = r.GetInt32(1);
}
#endregion
#region ReadTransponders()
private void ReadTransponders(SqliteCommand cmd)
{
cmd.CommandText = "select db_id, db_sat_para_id, freq, polar, symb from ts_table";
cmd.CommandText = "select db_id, db_sat_para_id, db_net_id, ts_id, freq, polar, symb from ts_table";
using var r = cmd.ExecuteReader();
while (r.Read())
{
int id = r.GetInt32(0);
int satId = r.GetInt32(1);
int freq = r.GetInt32(2);
var netId = r.GetInt32(2);
var tsid = r.GetInt32(3);
int freq = r.GetInt32(4);
if (this.DataRoot.Transponder.TryGet(id) != null)
continue;
Transponder tp = new Transponder(id);
tp.TransportStreamId = tsid;
tp.FrequencyInMhz = (int)(freq/1000);
tp.Polarity = r.GetInt32(3) == 0 ? 'H' : 'V';
tp.Polarity = r.GetInt32(5) == 0 ? 'H' : 'V';
tp.Satellite = this.DataRoot.Satellites.TryGet(satId);
tp.SymbolRate = r.GetInt32(4) / 1000;
this.onidByNetId.TryGetValue(netId, out var onid);
tp.OriginalNetworkId = onid;
tp.SymbolRate = r.GetInt32(6) / 1000;
this.DataRoot.AddTransponder(tp.Satellite, tp);
}
}
@@ -125,15 +161,12 @@ namespace ChanSort.Loader.Amdb
private void ReadChannels(SqliteCommand cmd)
{
int ixP = 0;
int ixST = ixP + 12;
cmd.CommandText = @"
select
p.db_id, p.chan_num, p.name, p.service_id, p.vid_pid, p.pcr_pid, p.service_type, p.vid_fmt, p.free_ca_mode, p.lock, p.skip, p.hidden,
t.db_sat_para_id, 0, t.ts_id, t.freq, t.polar, t.symb
p.db_id, p.chan_num, p.name, p.service_id, p.vid_pid, p.pcr_pid, p.service_type, p.vid_fmt, p.free_ca_mode, p.lock, p.skip, p.hidden, p.db_net_id, p.db_ts_id, p.db_sat_para_id
from srv_table p
left outer join ts_table t on t.db_id=p.db_ts_id
order by p.chan_num";
order by t.db_sat_para_id, case p.service_type when 0 then 3 when 1 then 0 when 2 then 1 else p.service_type end, p.chan_num";
using var r = cmd.ExecuteReader();
while (r.Read())
@@ -142,8 +175,10 @@ order by p.chan_num";
var oldProgNr = r.GetInt32(ixP + 1);
var name = r.GetString(ixP + 2);
if (name.StartsWith("xxx"))
name = name.Substring(3);
ChannelInfo channel = new ChannelInfo(0, handle, oldProgNr, name);
name = name.Substring(3).Trim();
ChannelInfo channel = new ChannelInfo(0, handle, 0, name);
channel.RecordOrder = oldProgNr;
channel.ServiceId = r.GetInt32(ixP + 3) & 0x7FFF;
channel.VideoPid = r.GetInt32(ixP + 4);
channel.PcrPid = r.IsDBNull(ixP + 5) ? 0 : r.GetInt32(ixP + 5);
@@ -170,25 +205,32 @@ order by p.chan_num";
channel.Skip = r.GetBoolean(ixP + 10);
channel.Hidden = r.GetBoolean(ixP + 11);
// DVB-S
if (!r.IsDBNull(ixST + 0))
var netDbId = r.GetInt32(ixP + 12);
this.onidByNetId.TryGetValue(netDbId, out var onid);
channel.OriginalNetworkId = onid;
var tsDbId = r.GetInt32(ixP + 13);
DataRoot.Transponder.TryGetValue(tsDbId, out var transponder);
if (transponder != null)
{
var satId = r.GetInt32(ixST + 0);
var sat = this.DataRoot.Satellites.TryGet(satId);
channel.Satellite = sat?.Name;
channel.SatPosition = sat?.OrbitalPosition;
channel.OriginalNetworkId = r.GetInt32(ixST + 1) & 0x7FFF;
channel.TransportStreamId = r.GetInt32(ixST + 2) & 0x7FFF;
channel.FreqInMhz = r.GetInt32(ixST + 3);
channel.Transponder = transponder;
channel.TransportStreamId = transponder.TransportStreamId;
channel.Satellite = transponder.Satellite?.Name;
channel.SatPosition = transponder.Satellite?.OrbitalPosition;
channel.FreqInMhz = transponder.FrequencyInMhz;
if (channel.FreqInMhz > 20000) // DVB-S is in MHz already, DVB-C/T in kHz
channel.FreqInMhz /= 1000;
channel.Polarity = r.GetInt32(ixST + 4) == 0 ? 'H' : 'V';
channel.SymbolRate = r.GetInt32(ixST + 5)/1000;
channel.Polarity = transponder.Polarity;
channel.SymbolRate = transponder.SymbolRate;
}
var list = this.DataRoot.GetChannelList(channel.SignalSource);
if (list != null)
var satId = r.GetInt32(ixP + 14);
var key = Tuple.Create(channel.SignalSource & SignalSource.MaskTvRadioData, satId);
if (this.listBySatellite.TryGetValue(key, out var list))
{
channel.OldProgramNr = list.Count + 1;
this.DataRoot.AddChannel(list, channel);
}
}
}
#endregion
@@ -229,9 +271,10 @@ order by p.chan_num";
#region WriteChannels()
private void WriteChannels(SqliteCommand cmd, SqliteCommand cmdDelete)
{
cmd.CommandText = "update srv_table set chan_num=@nr, chan_order=@nr, name=@name, skip=@skip, lock=@lock, hidden=@hide where db_id=@handle";
cmd.CommandText = "update srv_table set chan_num=@num, chan_order=@order, name=@name, skip=@skip, lock=@lock, hidden=@hide where db_id=@handle";
cmd.Parameters.Add("@handle", SqliteType.Integer);
cmd.Parameters.Add("@nr", SqliteType.Integer);
cmd.Parameters.Add("@num", SqliteType.Integer);
cmd.Parameters.Add("@order", SqliteType.Integer);
cmd.Parameters.Add("@name", SqliteType.Text);
cmd.Parameters.Add("@skip", SqliteType.Integer);
cmd.Parameters.Add("@lock", SqliteType.Integer);
@@ -242,30 +285,45 @@ order by p.chan_num";
cmdDelete.Parameters.Add("@handle", SqliteType.Integer);
cmdDelete.Prepare();
foreach (var list in this.DataRoot.ChannelLists)
{
foreach (ChannelInfo channel in list.Channels.OrderBy(ch => (ch.SignalSource & SignalSource.Tv) != 0 ? 0 : 1).ThenBy(ch => ch.NewProgramNr))
{
if (channel.IsProxy) // ignore reference list proxy channels
continue;
// combine all lists (including "others") into a single one
IEnumerable<ChannelInfo> union = new List<ChannelInfo>();
foreach (var list in this.listBySatellite.Values)
union = union.Concat(list.Channels);
if (channel.IsDeleted)
{
cmdDelete.Parameters["@handle"].Value = channel.RecordIndex;
cmdDelete.ExecuteNonQuery();
}
else
{
channel.UpdateRawData();
cmd.Parameters["@handle"].Value = channel.RecordIndex;
cmd.Parameters["@nr"].Value = channel.NewProgramNr;
cmd.Parameters["@name"].Value = "xxx" + channel.Name;
cmd.Parameters["@skip"].Value = channel.Skip ? 1 : 0;
cmd.Parameters["@lock"].Value = channel.Lock ? 1 : 0;
cmd.Parameters["@hide"].Value = channel.Hidden ? 1 : 0;
cmd.ExecuteNonQuery();
}
var chanOrder = 1;
var allChannels = union.OrderBy(SignalSourceOrder).ThenBy(ch => ch.NewProgramNr).ToList();
foreach (ChannelInfo channel in allChannels)
{
if (channel.IsProxy) // ignore reference list proxy channels
continue;
if (channel.IsDeleted)
{
cmdDelete.Parameters["@handle"].Value = channel.RecordIndex;
cmdDelete.ExecuteNonQuery();
}
else
{
channel.UpdateRawData();
cmd.Parameters["@handle"].Value = channel.RecordIndex;
cmd.Parameters["@num"].Value = channel.NewProgramNr;
cmd.Parameters["@order"].Value = chanOrder++;
cmd.Parameters["@name"].Value = "xxx" + channel.Name;
cmd.Parameters["@skip"].Value = channel.Skip ? 1 : 0;
cmd.Parameters["@lock"].Value = channel.Lock ? 1 : 0;
cmd.Parameters["@hide"].Value = channel.Hidden ? 1 : 0;
cmd.ExecuteNonQuery();
}
}
int SignalSourceOrder(ChannelInfo ch)
{
var ss = ch.SignalSource;
if ((ss & SignalSource.Tv) != 0)
return 0;
if ((ss & SignalSource.Radio) != 0)
return 1;
return 2;
}
}
#endregion

View File

@@ -244,6 +244,69 @@ offProvider=200
lenProvider=52
# Dijitsu LDM538 with 2668 KB, 8 byte header with 0004
[dtv_cmdb_2.bin:2731173]
offChannelBitmap=8
lenChannelBitmap=752
offChannelRecord=0x2F8
lenChannelRecord=424
numChannelRecord=6000
offTransponderBitmap=0x0026d478
lenTransponderBitmap=376
offTransponderRecord=0x0026d5f0
lenTransponderRecord=52
numTransponderRecord=3000
offSatelliteBitmap=0x00296d04
lenSatelliteBitmap=32
offSatelliteRecord=0x00296d24
lenSatelliteRecord=64
numSatelliteRecord=254
[dvbsChannel:424]
;offEncrypted=13
;maskEncrypted=0x10
;offSkip=13
;maskSkip=0x20
;offLocked=13
;maskLocked=0x40
offChannelType=15
offServiceType=16
;offFav=18
;maskFav=1
offTransponderIndex=20
offPmtPid=22
offPcrPid=26
offVideoPid=28
offProgramNr=32
offServiceId=34
offAudioPid=54
offName=146
lenName=40
offProvider=196
lenProvider=200
;[dvbsTransponder:52] ; already defined above
;offSatelliteIndex=0
;offTransportStreamId=6
;offOriginalNetworkId=8
;offNetworkId=10
;offTransponderIndex=14
;offFreqInMhz=16
;offSymbolRate=28
[dvbsSatellite:64]
offName=2
lenName=32
offOrbitalPos=50
# Philips ChannelMap_100 lists - dtv_cmdb_2.bin with 3443 KB
#[dtv_cmdb_2.bin:3525205]

View File

@@ -1,4 +1,52 @@
[dbm:163772]

[dbm:74303]
; overall file layout
isDvbS=false
separateTvRadioData=false
offChecksum=0x0000
offDataLength=0x0002
offData=0x0006
offTransponderBitmap=0x0006
lenTransponderBitmap=16
offTransponderData=0x0016
numTransponder=100
lenTransponderData=36
offChannelBitmap=0x0E3C
lenChannelBitmap=50
offChannelData=0x0E6E
numChannel=400
lenChannelData=176
;transponder record
offFreq=0
offSymRate=8
;channel record
offName=0
lenName=64
offProgNr=64
offLcn=66
offTransponderIndex=70
offServiceType=76
offHide=77
maskHide=0x04
offSkip=77
maskSkip=0x08
offLock=77
maskLock=0x10
offFavorites=79
offTsid=96
offOnid=98
offSid=100
offPcrPid=104
offVideoPid=106
;---------------------------------------
[dbm:163772]
; overall file layout
isDvbS=false
offChecksum=0x0000

View File

@@ -18,6 +18,7 @@ namespace ChanSort.Loader.DBM
private IniFile.Section sec;
private DataMapping mapping;
private bool isDvbS;
private bool separateTvRadioData;
private readonly ChannelList allChannels = new(SignalSource.All, "All");
private readonly StringBuilder logMessages = new();
@@ -36,18 +37,6 @@ namespace ChanSort.Loader.DBM
this.Features.AllowGapsInFavNumbers = false;
this.Features.CanEditFavListNames = false;
this.DataRoot.AddChannelList(this.allChannels);
foreach (var list in this.DataRoot.ChannelLists)
{
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.AudioPid));
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.ChannelOrTransponder));
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.Provider));
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.Encrypted));
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.ServiceType));
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.ServiceTypeName));
}
string iniFile = Assembly.GetExecutingAssembly().Location.Replace(".dll", ".ini");
this.ini = new IniFile(iniFile);
}
@@ -63,6 +52,18 @@ namespace ChanSort.Loader.DBM
if (sec == null)
throw LoaderException.Fail($"No configuration for .DBM files with size {info.Length} in .ini file");
this.separateTvRadioData = sec.GetBool("separateTvRadioData");
if (separateTvRadioData)
{
this.DataRoot.AddChannelList(new ChannelList(SignalSource.Tv, "TV"));
this.DataRoot.AddChannelList(new ChannelList(SignalSource.Radio, "Radio"));
this.DataRoot.AddChannelList(new ChannelList(SignalSource.Data, "Data"));
}
else
this.DataRoot.AddChannelList(this.allChannels);
AdjustColumns();
this.isDvbS = sec.GetBool("isDvbS");
if (isDvbS)
{
@@ -89,6 +90,21 @@ namespace ChanSort.Loader.DBM
}
#endregion
#region AdjustColumns()
private void AdjustColumns()
{
foreach (var list in this.DataRoot.ChannelLists)
{
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.AudioPid));
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.ChannelOrTransponder));
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.Provider));
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.Encrypted));
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.ServiceType));
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.ServiceTypeName));
}
}
#endregion
#region ValidateChecksum()
private void ValidateChecksum()
{
@@ -213,7 +229,9 @@ namespace ChanSort.Loader.DBM
c.SatPosition = sat.OrbitalPosition;
}
this.DataRoot.AddChannel(this.allChannels, c);
var list = this.DataRoot.GetChannelList(c.SignalSource);
if (list != null)
this.DataRoot.AddChannel(list, c);
}
mapping.BaseOffset += recordSize;

View File

@@ -5,7 +5,6 @@ using System.IO;
using System.Text;
using Microsoft.Data.Sqlite;
using ChanSort.Api;
using System.Runtime.Remoting.Channels;
namespace ChanSort.Loader.Panasonic
{
@@ -103,7 +102,7 @@ namespace ChanSort.Loader.Panasonic
if (cypherMode == CypherMode.None)
return this.FileName;
this.TempPath = Path.GetTempFileName();
this.TempPath = Path.Combine(Path.GetDirectoryName(this.FileName) ?? "", Path.GetFileNameWithoutExtension(this.FileName) + "_decrypted.db"); //Path.GetTempFileName();
this.DeleteTempPath();
if (cypherMode == CypherMode.Encryption)
@@ -120,9 +119,9 @@ namespace ChanSort.Loader.Panasonic
using var stream = File.OpenRead(file);
using var rdr = new BinaryReader(stream);
uint value = (uint)rdr.ReadInt32();
if (value == 0x694C5153) return CypherMode.None; // "SQLi"
if (value == 0x42445350) return CypherMode.HeaderAndChecksum; // "PSDB"
if (value == 0xA07DCB50) return CypherMode.Encryption;
if (value == 0x694C5153) return CypherMode.None; // "SQLi", already decrypted svl.db or svl.bin
if (value == 0x42445350) return CypherMode.HeaderAndChecksum; // "PSDB" - svl.bin
if (value == 0xA07DCB50) return CypherMode.Encryption; // svl.db
return CypherMode.Unknown;
}
#endregion

View File

@@ -112,6 +112,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HDD Hex Edit Neo", "HDD Hex
Information\FileStructures_for_HHD_Hex_Editor_Neo\chansort.h = Information\FileStructures_for_HHD_Hex_Editor_Neo\chansort.h
Information\FileStructures_for_HHD_Hex_Editor_Neo\cvt_database-dat.h = Information\FileStructures_for_HHD_Hex_Editor_Neo\cvt_database-dat.h
Information\FileStructures_for_HHD_Hex_Editor_Neo\dbm.h = Information\FileStructures_for_HHD_Hex_Editor_Neo\dbm.h
Information\FileStructures_for_HHD_Hex_Editor_Neo\dtv-cmdb.h = Information\FileStructures_for_HHD_Hex_Editor_Neo\dtv-cmdb.h
Information\FileStructures_for_HHD_Hex_Editor_Neo\dtv_cmdb_1-bin.h = Information\FileStructures_for_HHD_Hex_Editor_Neo\dtv_cmdb_1-bin.h
Information\FileStructures_for_HHD_Hex_Editor_Neo\dtv_cmdb_2-bin.h = Information\FileStructures_for_HHD_Hex_Editor_Neo\dtv_cmdb_2-bin.h
Information\FileStructures_for_HHD_Hex_Editor_Neo\get_doc_size.js = Information\FileStructures_for_HHD_Hex_Editor_Neo\get_doc_size.js

View File

@@ -97,6 +97,20 @@ public struct DBM
switch (GetDocumentSize())
{
case 74303:
// Renkforce 1510 C HD, Telestar digiHD TC 7
satBitmapLength = 0;
satRecordCount = 0;
satRecordLength = 84;
transponderBitmapLength = 16;
transponderRecordCount = 100;
transponderRecordLength = 36;
unknownDataLength = 22;
channelBitmapLength = 50;
channelRecordCount = 400;
channelRecordLength = 176;
bytesBetweenTransponderIndexAndServiceType = 2;
break;
case 163772:
// TechniSat DVB-C TS_Programmliste_06_01.DBM
satBitmapLength = 0;

View File

@@ -0,0 +1,151 @@
#include "chansort.h"
#pragma script("get_doc_size.js")
/*
structure definition for various variants of MStar (aka MorningStar) DVB-C and DVB-S receiver channel list formats.
Also used by various models from brands like AEG, Akiwa, Auvisio, Boca, Botech, Comag, Dyon, LogiSat, Kjaerulff, Micro, Megasat, Schwaiger, SeaSat, Strong, TechniSat, TeleSystem, Trekstor, Xoro, Zehnder, ...
Typical file names include: vodafone.DBM, HB_DATABASE_6_29.DBM, MAS_HRS8520_23_08_2011.DBM, ...
*/
struct s_Satellite
{
var off0 = current_offset;
word u;
byte Name[34];
word LowFreq;
word HighFreq;
var off1 = current_offset;
byte u1[50 - (off1 - off0)];
word OrbitalPos;
var off1 = current_offset;
byte unk[satRecordLength - (off1 - off0)];
};
struct s_Transponder
{
var off0 = current_offset;
byte SatIndex;
byte unk1[5];
word Tsid;
word Onid;
word Nid;
byte u[2];
word transponderIndex;
word FreqInMhz;
byte unk2[10];
word SymRate;
var off1 = current_offset;
byte unk[transponderRecordLength - (off1 - off0)];
};
enum e_Favorites : byte
{
A=0x01,
B=0x04,
C=0x08,
D=0x10
};
enum e_Flags : byte
{
Encrypted=0x10,
Skip=0x20,
Lock=0x40
};
enum e_ServiceType : byte
{
TV=1,
Radio=2
};
struct s_Channel
{
var off0 = current_offset;
word Index;
byte u0[13];
//e_Flags Flags;
//byte u1;
byte ChannelType;
byte ServiceType;
byte u1[3];
word TransponderIndex;
word PmtPid;
word u2;
word PcrPid;
word VideoPid;
word u3;
word ProgNr;
word ServiceId;
byte u4[14];
char AudioLang1[4];
word AudioPid1;
char AudioLang2[4];
word AudioPid2;
byte u90[84];
char Name[50];
char Provider[224];
var off1 = current_offset;
byte unk[channelRecordLength - (off1-off0)];
};
public struct dtv_cmdb_2
{
var headerLength = 0;
var channelBitmapLength = 0;
var channelRecordCount = 0;
var channelRecordLength = 0;
var channelBlockUnknownLength = 0;
var transponderBitmapLength = 0;
var transponderRecordCount = 0;
var transponderRecordLength = 0;
var transponderBlockUnknownLength = 0;
var satBitmapLength = 0;
var satRecordCount = 0;
var satRecordLength = 0;
switch (GetDocumentSize())
{
case 2731173:
// Dijitsu LDM538
headerLength = 8;
channelBitmapLength = 750;
channelRecordCount = 6000;
channelRecordLength = 424;
channelBlockUnknownLength = 2;
transponderBitmapLength = 376;
transponderRecordCount = 3200;
transponderBlockUnknownLength = 3348;
transponderRecordLength = 52;
satBitmapLength = 32;
satRecordCount = 254;
satRecordLength = 64;
break;
default:
$assert(false, "Structure for this file size is not supported");
break;
}
byte Header[headerLength];
byte ChannelBitmap[channelBitmapLength];
byte unk[2];
s_Channel ChannelData[channelRecordCount];
//byte ChannelBlockUnknown[channelBlockUnknownLength];
byte TransponderBitmap[transponderBitmapLength];
s_Transponder TransponderData[transponderRecordCount];
byte TransponderBlockUnknown[transponderBlockUnknownLength];
byte SatelliteBitmap[satBitmapLength];
s_Satellite SatelliteData[satRecordCount];
byte Extra[*];
};

View File

@@ -1,6 +1,15 @@
ChanSort Change Log
===================
2023-10-22
- fixed loading .txt reference lists
- added support for HB\_DATABASE\_\*.DBM channel lists with file size 74303
(e.g. Renkforce 1510 C HD, Telestar digiHD TC 7)
- added support for dtv_cmdb_2.bin files with file size 2731173
(e.g. Dijitsu Android TV with LD-M538 board)
- improved experimental support for amdb\*.db Android STB channel lists
(now grouped by TV and radio for each satellite)
2023-09-17
- added support for Philips Repair channel list format 2.0
- added experimental support for amdb\*.db Android STB channel lists

View File

@@ -51,12 +51,21 @@ Special thanks to Hisense for supporting ChanSort with technical information and
<a name="panasonic"/>Panasonic
---
Most Viera models since 2011 with channel list formats
**Android-TVs** come with different internal hardware, firmware and file formats, so support depends on the model.
- mnt/vendor/tvdata/database/tv.db file (LSW500 and LXW700 series)
- channellist.txt (MX700, MZ800)
- channels.sdx ("fire-OS" MXW834)
- NOT supported: CLONE00001/settingsDB\_enc.db (JXW600)
- NOT supported: hotel\_setup/Channel\_list/channel\_list.bin (JXW800)
On some models you can export/import the list by selecting "Input: Cable" (or any other TV source), then
open the menu, Channels, Export/Import.
Other models require to use the secret hotel menu: Menu / Picture / Picture Mode / User Defined / Contrast / 6x ok.
**Viera** models since 2011 with channel list formats
- svl.bin
- svl.db
- Android-TVs of LXS600 and LXW700 series with mnt/vendor/tvdata/database/tv.db file
- NOT supported: models on Vestel plattform, e.g. JXW600 with CLONE00001/settingsDB\_enc.db
- NOT supported: models on MediaTek(?) plattform, e.g. JXW800 with hotel\_setup/Channel\_list/channel\_list.bin
- svl.db (JZT1500, ...)
To export/import files on Viera models, format the USB stick with FAT32 and create an empty file or directory
named hotel.pwd. After plugging in the stick on the TV enter 4850 for TV->USB or 4851 for USB->TV
<a name="tcl"/>TCL / Thomson
---

View File

@@ -51,12 +51,23 @@ Besonderen Dank verdient Hisense f
<a name="panasonic"/>Panasonic
---
Die meisten Viera-Modelle seit 2011 mit Senderlisten im Format
- svl.bin
- svl.db
- Android-TVs der LXS600 und LXW700 Serie mit mnt/vendor/tvdata/database/tv.db Datei
- NICHT unterst<73>tzt: Modelle auf Vestel Plattform, z.B. JXW600 mit CLONE00001/settingsDB\_enc.db
- NICHT unterst<73>tzt: Modelle auf MediaTek(?) Plattform, z.B. JXW800 mit hotel\_setup/Channel\_list/channel\_list.bin
**Android-TVs** gibt es mit unterschiedlicher interner hardware, firmware und Senderlistenformaten. Unterst<73>tzt werden
- mnt/vendor/tvdata/database/tv.db file (LSW500 and LXW700 series)
- channellist.txt (MX700, MZ800)
- channels.sdx ("fire-OS" MXW834)
- NICHT unterst<73>tzt: CLONE00001/settingsDB\_enc.db (JXW600)
- NICHT unterst<73>tzt: hotel\_setup/Channel\_list/channel\_list.bin (JXW800)
Bei einigen Modellen kann man die Senderliste importieren/exportieren, indem man "Input: Kabel" (oder eine andere TV-Quelle)
und dann im Men<65> den Punkt "Kanal".
Bei anderen Modellen ist eventuell nur der Umweg <20>ber das geheime Hotel-Men<65> m<>glich:
Men<EFBFBD> / Bild / Bildmodus / Benutzerdefiniert / Kontrast / 6x Ok.
**Viera** Modelle mit Senderlisten im Format
- svl.bin
- svl.db (JZT1500, ...)
Zum Exportieren/Importieren wird ein USB stickmit FAT32 ben<65>tigt, auf dem man eine leere Datei oder ein Verzeichnis
mit dem Namen "hotel.pwd" erstellt. Nach dem Anstecken an den TV kann man den codes 4850 f<>r TV->USB oder 4851 f<>r
USB->TV eingeben.
<a name="tcl"/>TCL / Thomson
---