mirror of
https://github.com/PredatH0r/ChanSort.git
synced 2026-01-16 20:32:04 +01:00
- 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:
@@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
88
source/ChanSort.Api/Utils/ListDictionary.cs
Normal file
88
source/ChanSort.Api/Utils/ListDictionary.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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[*];
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
---
|
||||
|
||||
@@ -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
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user