- W.I.P: Enigma2 lamedb / bouquets support for Linux based Set-Top-Boxes (Dreambox, VU+, Octagon, ...)

- Toshiba settingsDB.db: support for lists without analog tuner data (missing TADTunerDataTable)
- Grunding: failed to load lists where the <Digital> element did not contain a <channels> child element
- W.I.P: reworking the reference list system so that a simple list of channels can be applied to the main channel numbers or a particular favorite list.
  (The "Automatically reorder all lists" options currently does not work)
This commit is contained in:
Horst Beham
2021-03-13 18:11:30 +01:00
parent 9d4467c868
commit f5010439cb
22 changed files with 158 additions and 127 deletions

View File

@@ -208,7 +208,7 @@ namespace ChanSort.Api
log.AppendFormat("Skipped reference list {0}\r\n", refList.ShortCaption);
continue;
}
ApplyReferenceList(refDataRoot, refList, tvList, true);
ApplyReferenceList(refDataRoot, refList, -1, tvList, -1, true);
}
}
@@ -225,7 +225,7 @@ namespace ChanSort.Api
/// </param>
/// <param name="overwrite">controls whether Pr# will be reassigned to the reference channel when they are already in-use in the TV list</param>
/// <param name="consecutive">when true, consecutive numbers will be used instead of the Pr# in the reference list when applying the order</param>
public void ApplyReferenceList(DataRoot refDataRoot, ChannelList refList, ChannelList tvList, bool addProxyChannels = true, int positionOffset = 0, Func<ChannelInfo, bool, bool> chanFilter = null, bool overwrite = true, bool consecutive = false)
public void ApplyReferenceList(DataRoot refDataRoot, ChannelList refList, int refListPosIndex, ChannelList tvList, int tvListPosIndex, bool addProxyChannels = true, int positionOffset = 0, Func<ChannelInfo, bool, bool> chanFilter = null, bool overwrite = true, bool consecutive = false)
{
// create Hashtable for exact channel lookup
// the UID of a TV channel list contains a source-indicator (Analog, Cable, Sat), which may be undefined in the reference list)
@@ -245,39 +245,12 @@ namespace ChanSort.Api
}
var incNr = 1 + positionOffset;
foreach (var refChannel in refList.Channels.OrderBy(ch => ch.OldProgramNr))
foreach (var refChannel in refList.Channels.OrderBy(ch => ch.GetOldPosition(refListPosIndex)))
{
if (!(chanFilter?.Invoke(refChannel, true) ?? true))
continue;
var tvChannels = refChannel.Uid == "0-0-0" ? null : tvList.GetChannelByUid(refChannel.Uid);
// try to find matching channels based on ONID+TSID+SID
if ((tvChannels?.Count ?? 0) == 0)
{
var key = DvbKey(refChannel.OriginalNetworkId, refChannel.TransportStreamId, refChannel.ServiceId);
if (key != 0 && onidTsidSid.TryGetValue(key, out var candidates))
{
tvChannels = candidates;
// narrow the list down further when a transponder is also provided (i.e. the same TV channel can be received on multiple DVB-T frequencies)
if (tvChannels.Count > 1 && !string.IsNullOrEmpty(refChannel.ChannelOrTransponder))
{
candidates = tvChannels.Where(ch => ch.ChannelOrTransponder == refChannel.ChannelOrTransponder).ToList();
if (candidates.Count > 0)
tvChannels = candidates;
}
}
}
// try to find matching channels by name
if ((tvChannels?.Count ?? 0) == 0 && !string.IsNullOrWhiteSpace(refChannel.Name))
tvChannels = tvList.GetChannelByName(refChannel.Name).ToList();
// get the first unassigned channel from the candidates (e.g. when matching by non-unique names), or fall back to the first matching channel (e.g. by unique ID)
ChannelInfo tvChannel = tvChannels.FirstOrDefault(c => c.GetPosition(0) == -1);
if (tvChannel == null && tvChannels.Count > 0)
tvChannel = tvChannels[0];
var tvChannel = FindChannel(tvList, refChannel, onidTsidSid);
if (tvChannel != null)
{
@@ -293,7 +266,7 @@ namespace ChanSort.Api
foreach (var chan in curChans)
chan.NewProgramNr = -1;
tvChannel.SetPosition(0, newNr);
tvChannel.SetPosition(tvListPosIndex, newNr);
if (refDataRoot.CanSkip && this.DataRoot.CanSkip)
tvChannel.Skip = refChannel.Skip;
if (refDataRoot.CanLock && this.DataRoot.CanLock)
@@ -308,7 +281,8 @@ namespace ChanSort.Api
tvChannel.IsNameModified = true;
}
ApplyFavorites(refDataRoot, refChannel, tvChannel);
if (tvListPosIndex == -1)
ApplyFavorites(refDataRoot, refChannel, tvChannel);
}
else if (addProxyChannels)
{
@@ -318,6 +292,39 @@ namespace ChanSort.Api
}
}
private ChannelInfo FindChannel(ChannelList tvList, ChannelInfo refChannel, Dictionary<long, List<ChannelInfo>> onidTsidSid)
{
var tvChannels = refChannel.Uid == "0-0-0" ? null : tvList.GetChannelByUid(refChannel.Uid);
// try to find matching channels based on ONID+TSID+SID
if ((tvChannels?.Count ?? 0) == 0)
{
var key = DvbKey(refChannel.OriginalNetworkId, refChannel.TransportStreamId, refChannel.ServiceId);
if (key != 0 && onidTsidSid.TryGetValue(key, out var candidates))
{
tvChannels = candidates;
// narrow the list down further when a transponder is also provided (i.e. the same TV channel can be received on multiple DVB-T frequencies)
if (tvChannels.Count > 1 && !string.IsNullOrEmpty(refChannel.ChannelOrTransponder))
{
candidates = tvChannels.Where(ch => ch.ChannelOrTransponder == refChannel.ChannelOrTransponder).ToList();
if (candidates.Count > 0)
tvChannels = candidates;
}
}
}
// try to find matching channels by name
if ((tvChannels?.Count ?? 0) == 0 && !string.IsNullOrWhiteSpace(refChannel.Name))
tvChannels = tvList.GetChannelByName(refChannel.Name).ToList();
// get the first unassigned channel from the candidates (e.g. when matching by non-unique names), or fall back to the first matching channel (e.g. by unique ID)
ChannelInfo tvChannel = tvChannels.FirstOrDefault(c => c.GetPosition(0) == -1);
if (tvChannel == null && tvChannels.Count > 0)
tvChannel = tvChannels[0];
return tvChannel;
}
long DvbKey(int onid, int tsid, int sid)
{
return ((long)onid << 32) | ((long)tsid << 16) | (long)sid;
@@ -332,9 +339,9 @@ namespace ChanSort.Api
tvChannel.Favorites = refChannel.Favorites & DataRoot.SupportedFavorites;
if (refDataRoot.SortedFavorites)
{
var c = Math.Min(refChannel.FavIndex.Count, tvChannel.OldFavIndex.Count);
var c = Math.Min(refDataRoot.FavListCount, this.DataRoot.FavListCount);
for (int i = 0; i < c; i++)
tvChannel.FavIndex[i] = refChannel.OldFavIndex[i];
tvChannel.SetPosition(i+1, refChannel.GetOldPosition(i+1));
}
else
this.ApplyPrNrToFavLists(tvChannel);
@@ -363,13 +370,13 @@ namespace ChanSort.Api
if (sortedFav)
{
foreach (var channel in favList.Channels)
maxPosition = Math.Max(maxPosition, channel.FavIndex[favIndex]);
maxPosition = Math.Max(maxPosition, channel.GetPosition(favIndex+1));
}
foreach (var channel in list)
{
if (sortedFav && channel.FavIndex[favIndex] == -1)
channel.FavIndex[favIndex] = ++maxPosition;
if (sortedFav && channel.GetPosition(favIndex+1) == -1)
channel.SetPosition(favIndex+1,++maxPosition);
channel.Favorites |= favMask;
}
}
@@ -377,8 +384,8 @@ namespace ChanSort.Api
{
foreach (var channel in list)
{
if (sortedFav && channel.FavIndex[favIndex] != -1)
channel.FavIndex[favIndex] = -1;
if (sortedFav && channel.GetPosition(favIndex+1) != -1)
channel.SetPosition(favIndex+1, -1);
channel.Favorites &= ~favMask;
}
@@ -386,10 +393,10 @@ namespace ChanSort.Api
if (sortedFav && !this.DataRoot.AllowGapsInFavNumbers)
{
int i = 0;
foreach (var channel in favList.Channels.OrderBy(c => c.FavIndex[favIndex]))
foreach (var channel in favList.Channels.OrderBy(c => c.GetPosition(favIndex + 1)))
{
if (channel.FavIndex[favIndex] != -1)
channel.FavIndex[favIndex] = ++i;
if (channel.GetPosition(favIndex+1) != -1)
channel.SetPosition(favIndex+1, ++i);
}
}
}
@@ -419,7 +426,7 @@ namespace ChanSort.Api
var refMask = (ulong)tvChannel.Favorites;
for (int i = 0; supMask != 0; i++)
{
tvChannel.FavIndex[i] = (refMask & 0x01) == 0 ? -1 : tvChannel.NewProgramNr;
tvChannel.SetPosition(i+1, (refMask & 0x01) == 0 ? -1 : tvChannel.NewProgramNr);
supMask >>= 1;
refMask >>= 1;
}
@@ -439,13 +446,13 @@ namespace ChanSort.Api
bool changed = false;
for (int fav = 0; fav < favCount; fav++)
{
var list = channelList.Channels.Where(c => c.FavIndex[fav] >= 0).OrderBy(c => c.FavIndex[fav]).ToList();
var list = channelList.Channels.Where(c => c.GetPosition(fav+1) >= 0).OrderBy(c => c.GetPosition(fav+1)).ToList();
int i = 1;
foreach (var channel in list)
{
if (channel.FavIndex[fav] != i)
if (channel.GetPosition(fav+1) != i)
{
channel.FavIndex[fav] = ++i;
channel.SetPosition(fav+1, ++i);
changed = true;
}
}

View File

@@ -72,11 +72,11 @@ namespace ChanSort.Api
/// <summary>
/// current number of the channel in the various favorite lists (if individual sorting is supported)
/// </summary>
public List<int> FavIndex { get; }
private List<int> FavIndex { get; }
/// <summary>
/// original number of the channel in the various favorite lists (if individual sorting is supported)
/// </summary>
public List<int> OldFavIndex { get; }
private List<int> OldFavIndex { get; }
/// <summary>
/// predefined LCN (logical channel number) assigned by TV firmware or cable/sat operator
@@ -330,7 +330,7 @@ namespace ChanSort.Api
this.NewProgramNr = newPos;
else
{
for (int i=this.FavIndex.Count; i<=subListIndex;i++)
for (int i = this.FavIndex.Count; i < subListIndex; i++)
this.FavIndex.Add(-1);
this.FavIndex[subListIndex - 1] = newPos;
int mask = 1 << (subListIndex - 1);
@@ -352,7 +352,7 @@ namespace ChanSort.Api
this.OldProgramNr = oldPos;
else
{
for (int i = this.OldFavIndex.Count; i <= subListIndex; i++)
for (int i = this.OldFavIndex.Count; i < subListIndex; i++)
this.OldFavIndex.Add(-1);
this.OldFavIndex[subListIndex - 1] = oldPos;
}

View File

@@ -12,8 +12,6 @@ namespace ChanSort.Api
private int insertProgramNr = 1;
private int duplicateUidCount;
private int duplicateProgNrCount;
public int FavListCount { get; set; }
public static List<string> DefaultVisibleColumns { get; set; } = new List<string>(); // initialized by MainForm

View File

@@ -27,6 +27,8 @@ namespace ChanSort.Api
public bool CanHide => this.loader.Features.CanHideChannels;
public bool CanEditFavListName => this.loader.Features.CanEditFavListNames;
public int FavListCount { get; private set; }
public DataRoot(SerializerBase loader)
{
this.loader = loader;
@@ -108,14 +110,12 @@ namespace ChanSort.Api
#region ValidateAfterLoad()
public virtual void ValidateAfterLoad()
{
this.FavListCount = 0;
for (ulong m = (ulong)this.loader.Features.SupportedFavorites; m != 0; m >>= 1)
++this.FavListCount;
foreach (var list in this.ChannelLists)
{
if (list.FavListCount == 0)
{
for (ulong m = (ulong) this.loader.Features.SupportedFavorites; m != 0; m >>= 1)
++list.FavListCount;
}
if (list.IsMixedSourceFavoritesList)
{
loader.Features.SortedFavorites = true; // all mixed source favorite lists must support ordering
@@ -144,18 +144,11 @@ namespace ChanSort.Api
#region ApplyCurrentProgramNumbers()
public void ApplyCurrentProgramNumbers()
{
int c = 0;
if (this.MixedSourceFavorites || this.SortedFavorites)
{
for (ulong m = (ulong) this.SupportedFavorites; m != 0; m >>= 1)
++c;
}
foreach (var list in this.ChannelLists)
{
foreach (var channel in list.Channels)
{
for (int i = 0; i <= c; i++)
for (int i = 0; i <= this.FavListCount; i++)
channel.SetPosition(i, channel.GetOldPosition(i));
}
}
@@ -247,9 +240,8 @@ namespace ChanSort.Api
chan.NewProgramNr = -1;
}
chan.OldProgramNr = chan.NewProgramNr;
chan.OldFavIndex.Clear();
chan.OldFavIndex.AddRange(chan.FavIndex);
for (int j=0; j<=this.FavListCount; j++)
chan.SetOldPosition(j, chan.GetPosition(j));
}
}
}

View File

@@ -7,7 +7,7 @@ namespace ChanSort.Loader.Enigma2
/// <summary>
/// first two fields of the lamedb entry
/// </summary>
public string Prefix { get; set; }
public string Prefix { get; set; } = "1:0";
/// <summary>
/// For DVB-S it is the orbital position * 10 (e.g. 192 for Astra 19.2E) * 65536
@@ -15,11 +15,11 @@ namespace ChanSort.Loader.Enigma2
public int DvbNamespace { get; set; }
public int ServiceNumber { get; set; }
/// <summary>
/// all fields after the DVB-namespace in the lamedb entry
/// </summary>
public string Suffix { get; set; }
public string Suffix { get; set; } = ":0:0:0:";
/// <summary>
/// #DESCRIPTION of the userbouquet entry

View File

@@ -84,14 +84,14 @@ namespace ChanSort.Loader.Enigma2
LoadBouquets(path, ref favIndex);
// load all unlisted userbouquet files
foreach (var file in Directory.GetFiles(Path.GetDirectoryName(this.FileName), "userbouquet.*"))
{
var ext = Path.GetExtension(file);
if (ext != ".tv" && ext != ".radio") // ignore .del, .bak and other irrelevant files
continue;
if (!this.favListFileNames.Contains(file))
this.LoadUserBouquet(file, ref favIndex);
}
//foreach (var file in Directory.GetFiles(Path.GetDirectoryName(this.FileName), "userbouquet.*"))
//{
// var ext = Path.GetExtension(file);
// if (ext != ".tv" && ext != ".radio") // ignore .del, .bak and other irrelevant files
// continue;
// if (!this.favListFileNames.Contains(file))
// this.LoadUserBouquet(file, ref favIndex);
//}
}
#endregion
@@ -188,7 +188,6 @@ namespace ChanSort.Loader.Enigma2
ch.RecordIndex = chanId;
ch.RecordOrder = chanId;
ch.OldProgramNr = ++chanId;
ch.NewProgramNr = chanId;
ch.IsDeleted = false;
ch.ServiceId = FromHex(parts[0]);
ch.DvbNamespace = FromHex(parts[1]);
@@ -254,7 +253,7 @@ namespace ChanSort.Loader.Enigma2
#region LoadUserBoquet
private void LoadUserBouquet(string file, ref int favIndex)
{
if (!File.Exists(file))
if (!File.Exists(file) || this.favListFileNames.Contains(file))
return;
using var r = new StreamReader(File.OpenRead(file), utf8WithoutBom);

View File

@@ -194,7 +194,10 @@ namespace ChanSort.Loader.Grundig
return;
}
foreach (XmlNode networkNode in digital["channels"].ChildNodes)
var channels = digital["channels"];
if (channels == null)
return;
foreach (XmlNode networkNode in channels.ChildNodes)
{
if (networkNode.LocalName != "network")
continue;
@@ -361,7 +364,7 @@ namespace ChanSort.Loader.Grundig
if (ch.IsNameModified)
att["name"].Value = ch.Name;
for (int i=1; i<=4; i++)
att["f"+i].Value = Math.Max(0, ch.FavIndex[i-1]).ToString(); // convert -1 to 0
att["f"+i].Value = Math.Max(0, ch.GetPosition(i)).ToString(); // convert -1 to 0
att["skp"].InnerText = ch.Skip ? "1" : "0";
att["lck"].InnerText = ch.Lock ? "1" : "0";
if ((ch.SignalSource & SignalSource.Digital) != 0)

View File

@@ -442,7 +442,7 @@ namespace ChanSort.Loader.Hisense.ChannelDb
var id = ((long) r.GetInt32(0) << 32) | (uint) r.GetInt32(1);
var ci = this.channelsById.TryGet(id);
if (ci != null)
ci.OldFavIndex[i - 1] = r.GetInt32(2);
ci.SetOldPosition(i, r.GetInt32(2));
}
}
}
@@ -608,7 +608,7 @@ namespace ChanSort.Loader.Hisense.ChannelDb
{
for (int i = 0; i < 4; i++)
{
if (ci.FavIndex[i] <= 0)
if (ci.GetPosition(i+1) <= 0)
{
cmd.CommandText = $"delete from fav_{i + 1} where ui2_svc_id={ci.RecordIndex >> 32} and ui2_svc_rec_id={ci.RecordIndex & 0xFFFFFFFF}";
cmd.ExecuteNonQuery();
@@ -621,7 +621,7 @@ namespace ChanSort.Loader.Hisense.ChannelDb
cmd.Parameters.Add("@name", DbType.String);
cmd.Parameters.Add("@svcid", DbType.Int32);
cmd.Parameters.Add("@recid", DbType.Int32);
cmd.Parameters["@chnr"].Value = ci.FavIndex[i].ToString();
cmd.Parameters["@chnr"].Value = ci.GetPosition(i+1).ToString();
cmd.Parameters["@name"].Value = ci.Name;
cmd.Parameters["@svcid"].Value = ci.RecordIndex >> 32;
cmd.Parameters["@recid"].Value = ci.RecordIndex & 0xFFFF;
@@ -640,7 +640,7 @@ namespace ChanSort.Loader.Hisense.ChannelDb
{
for (int i = 0; i < 4; i++)
{
if (ci.FavIndex[i] <= 0)
if (ci.GetPosition(i+1) <= 0)
continue;
cmd.CommandText = $"insert into fav_{i + 1} (sortId, channelId, svlId, channelName, svlRecId, nwMask) values (@chnr,@chanid,@svcid,@name,@recid,@nwmask)";
@@ -651,7 +651,7 @@ namespace ChanSort.Loader.Hisense.ChannelDb
cmd.Parameters.Add("@name", DbType.String);
cmd.Parameters.Add("@recid", DbType.Int32);
cmd.Parameters.Add("@nwmask", DbType.Int32);
cmd.Parameters["@chnr"].Value = ci.FavIndex[i];
cmd.Parameters["@chnr"].Value = ci.GetPosition(i+1);
cmd.Parameters["@chanid"].Value = ci.ChannelId;
cmd.Parameters["@name"].Value = ci.Name;
cmd.Parameters["@svcid"].Value = ci.RecordIndex >> 32;

View File

@@ -358,7 +358,7 @@ left outer join Lcn l on l.ServiceId=fi.ServiceId and l.FavoriteId=fi.FavoriteId
int favListIdx = favListIdToFavIndex.TryGet(favListId, -1);
if (favListIdx >= 0)
ci.OldFavIndex[favListIdx] = r.GetInt32(2);
ci.SetOldPosition(favListIdx+1, r.GetInt32(2));
ci.SetOldPosition(favListIdx + 1, r.GetInt32(2)); // 0=main nr, 1-4=fav 1-4
if (favListIdx < 0)

View File

@@ -69,7 +69,7 @@ namespace ChanSort.Loader.Panasonic
if (favIndex > 0)
{
this.Favorites |= (Favorites) (1 << i);
this.OldFavIndex[i] = favIndex;
this.SetOldPosition(i, favIndex);
}
}
}

View File

@@ -358,7 +358,7 @@ order by s.ntype,major_channel
cmd.Parameters["@progNr"].Value = channel.NewProgramNr;
cmd.Parameters["@sname"].Value = channel.RawName;
for (int fav = 0; fav < 4; fav++)
cmd.Parameters["@fav" + (fav + 1)].Value = Math.Max(0, channel.FavIndex[fav]);
cmd.Parameters["@fav" + (fav + 1)].Value = Math.Max(0, channel.GetPosition(fav+1));
cmd.Parameters["@lock"].Value = channel.Lock;
cmd.Parameters["@skip"].Value = channel.Skip;
cmd.ExecuteNonQuery();

View File

@@ -901,7 +901,7 @@ namespace ChanSort.Loader.Philips
var recordSize = 4;
var recordCount = (dataSize - 4) / recordSize;
var favList = this.dvbsChannels.Channels.Where(c => c.FavIndex[0] != -1).OrderBy(c => c.FavIndex[0]).ToList();
var favList = this.dvbsChannels.Channels.Where(c => c.GetPosition(1) != -1).OrderBy(c => c.GetPosition(1)).ToList();
var favCount = favList.Count;
var firstFavIndex = favCount == 0 ? -1 : (int)favList[0].RecordIndex;
data.SetInt16(4, firstFavIndex);

View File

@@ -432,7 +432,7 @@ namespace ChanSort.Loader.Philips
foreach (var chan in rootList.Channels)
{
favChannels.Channels.Add(chan);
for (int i=0; i<chan.FavIndex.Count; i++)
for (int i=0; i<this.DataRoot.FavListCount; i++)
chan.SetOldPosition(i+1, -1);
}
}
@@ -547,7 +547,7 @@ namespace ChanSort.Loader.Philips
// ChannelMap_100 supports a single fav list and stores the favorite number directly here in the channel.
// ChannelMap_105 and later always store the value 0 in the channel and instead use a separate Favorites.xml file.
ch.SetupNode.Attributes["FavoriteNumber"].Value = setFavoriteNumber ? Math.Max(ch.FavIndex[0], 0).ToString() : "0";
ch.SetupNode.Attributes["FavoriteNumber"].Value = setFavoriteNumber ? Math.Max(ch.GetPosition(1), 0).ToString() : "0";
if (ch.OldProgramNr != ch.NewProgramNr)
{

View File

@@ -188,7 +188,7 @@ namespace ChanSort.Loader.Samsung.Scm
if (this.sortedFavorites == FavoritesIndexMode.Boolean) // D series
favValue = (fav & mask) != 0 ? 1 : 0; // D series
else if (this.sortedFavorites == FavoritesIndexMode.IndividuallySorted) // E series (and some F models with early firmware)
favValue = (fav & mask) != 0 ? this.FavIndex[favIndex] : -1;
favValue = (fav & mask) != 0 ? this.GetPosition(favIndex+1) : -1;
else
favValue = (fav & mask) != 0 ? this.NewProgramNr : -1; // F series (newer models/firmware), H series

View File

@@ -383,7 +383,7 @@ namespace ChanSort.Loader.Samsung.Zip
if (pos >= 0)
{
channel.Favorites |= (Favorites) (1 << fav);
channel.OldFavIndex[fav] = pos;
channel.SetOldPosition(fav+1, pos);
}
}
}
@@ -634,7 +634,7 @@ namespace ChanSort.Loader.Samsung.Zip
cmdDeleteFav.ExecuteNonQuery();
}
channel.FavIndex[i] = newPos;
channel.SetPosition(i+1, newPos);
}
}
}

View File

@@ -358,7 +358,7 @@ namespace ChanSort.Loader.Sony
for (int j = 0; j < 4 && j < favNumbers.Length; j++)
{
if (int.TryParse(favNumbers[j], out var favNr) && favNr > 0)
chan.OldFavIndex[j] = favNr;
chan.SetOldPosition(j+1, favNr);
}
}
var muxId = int.Parse(svcData["MuxID"][i]) + idAdjustment;
@@ -752,7 +752,7 @@ namespace ChanSort.Loader.Sony
{
var vals = value.Split(' ');
for (int i = 0; i < 4; i++)
vals[i] = ch.FavIndex[i] <= 0 ? "0" : ch.FavIndex[i].ToString();
vals[i] = ch.GetPosition(i+1) <= 0 ? "0" : ch.GetPosition(i+1).ToString();
return string.Join(" ", vals);
}
}

View File

@@ -19,6 +19,8 @@ namespace ChanSort.Loader.Toshiba
{
private readonly ChannelList channels = new ChannelList(SignalSource.All, "All");
private readonly HashSet<string> tableNames = new();
#region ctor()
public SettingsDbSerializer(string inputFile) : base(inputFile)
{
@@ -32,6 +34,15 @@ namespace ChanSort.Loader.Toshiba
this.Features.SupportedFavorites = 0;
this.DataRoot.AddChannelList(this.channels);
channels.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.Lock));
channels.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.Skip));
channels.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.Hidden));
channels.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.Encrypted));
channels.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.PcrPid));
channels.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.VideoPid));
channels.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.AudioPid));
channels.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.Satellite));
channels.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.ShortName));
}
#endregion
@@ -63,12 +74,19 @@ namespace ChanSort.Loader.Toshiba
string sysDataConnString = "Data Source=" + this.FileName;
using var conn = new SQLiteConnection(sysDataConnString);
conn.Open();
using var cmd = conn.CreateCommand();
this.RepairCorruptedDatabaseImage(cmd);
cmd.CommandText = "SELECT count(1) FROM sqlite_master WHERE type = 'table' and name='EASISerTable'";
if (Convert.ToInt32(cmd.ExecuteScalar()) != 1)
cmd.CommandText = "SELECT name FROM sqlite_master WHERE type = 'table'";
using (var r = cmd.ExecuteReader())
{
while (r.Read())
this.tableNames.Add(r.GetString(0).ToLowerInvariant());
}
if (!this.tableNames.Contains("easisertable"))
throw new FileLoadException("File doesn't contain the expected tables");
this.ReadSatellites(cmd);
@@ -135,23 +153,27 @@ namespace ChanSort.Loader.Toshiba
{
int ixE = 0;
int ixD = 3;
int ixA = 8;
int ixT = 9;
int ixA = 9;
int ixDC = 10;
int ixT = 12;
cmd.CommandText = @"
var hasTADTunerDataTable = this.tableNames.Contains("tadtunerdatatable");
string analogTunerFields = hasTADTunerDataTable ? ",t.frequency_in_multiples_of_10Hz" : "";
string analogTunerTable = hasTADTunerDataTable ? " left outer join TADTunerDataTable t on t.channel=ac.channel_no" : "";
cmd.CommandText = $@"
select
e.m_handle, e.m_rsn, e.m_name_serialized,
d.m_onid, d.m_tsid, d.m_id, d.m_type, d.m_name_serialized,
d.m_onid, d.m_tsid, d.m_id, d.m_type, d.m_name_serialized, d.m_provider_serialized,
a.m_name_serialized,
t.frequency_in_multiples_of_10Hz,
dc.frequency
dc.frequency, dc.symbol_rate
{analogTunerFields}
from EASISerTable e
left outer join DVBSerTable d on d.m_handle=e.m_handle
left outer join AnalogSerTable a on a.m_handle=e.m_handle
left outer join ChanDataTable dc on dc.handle=d.m_channel_no
left outer join ChanDataTable ac on ac.handle=a.m_channel_no
left outer join TADTunerDataTable t on t.channel=ac.channel_no";
{analogTunerTable}";
using var r = cmd.ExecuteReader();
while (r.Read())
{
@@ -166,12 +188,16 @@ left outer join TADTunerDataTable t on t.channel=ac.channel_no";
channel.OriginalNetworkId = r.GetInt32(ixD + 0) & 0x1FFF;
channel.TransportStreamId = r.GetInt32(ixD + 1) & 0x1FFF;
channel.ServiceId = r.GetInt32(ixD + 2) & 0x1FFF;
channel.ServiceType = r.GetInt32(ixD + 3);
channel.ServiceType = r.GetInt32(ixD + 3) & 0x1FFF;
channel.Provider = r.GetString(ixD + 5);
channel.FreqInMhz = (decimal) r.GetInt32(ixDC + 0) / 1000;
channel.SymbolRate = r.GetInt32(ixDC + 1);
if (channel.FreqInMhz > 10000)
channel.FreqInMhz = (int) channel.FreqInMhz;
}
// analog
if (!r.IsDBNull(ixA + 0))
if (!r.IsDBNull(ixA + 0) && hasTADTunerDataTable)
{
channel.FreqInMhz = (decimal) r.GetInt32(ixT + 0) / 100000;
}

View File

@@ -479,7 +479,7 @@ namespace ChanSort.Ui
this.tabSubList.TabPages[i].Text = this.DataRoot.GetFavListCaption(i - 1, true);
this.tabSubList.EndUpdate();
if (!this.DataRoot.SortedFavorites || this.subListIndex >= favCount)
if (!this.DataRoot.SortedFavorites || this.subListIndex > favCount)
{
this.tabSubList.SelectedTabPageIndex = 0;
this.subListIndex = 0;

View File

@@ -20,7 +20,6 @@ namespace ChanSort.Ui
class ListOption
{
private DataRoot root;
public ChannelList ChannelList { get; }
public int PosIndex { get; }
@@ -125,6 +124,7 @@ namespace ChanSort.Ui
this.edFile.Text = serializer.FileName;
this.rbAuto.Enabled = this.rbManual.Enabled = true;
ser.DataRoot.ApplyCurrentProgramNumbers();
ser.DataRoot.ValidateAfterLoad();
this.comboSource.EditValue = null;
this.comboSource.Properties.Items.Clear();
@@ -132,13 +132,12 @@ namespace ChanSort.Ui
{
if (list.Channels.Count == 0)
continue;
if (list.IsMixedSourceFavoritesList)
{
for (int i = 0; i <= list.FavListCount; i++)
this.comboSource.Properties.Items.Add(new ListOption(list, i, list + (i==0 ? "" : " - " + serializer.DataRoot.GetFavListCaption(i-1))));
}
else
if (!list.IsMixedSourceFavoritesList)
this.comboSource.Properties.Items.Add(new ListOption(list, 0, list.Caption));
for (int i = 1; i <= serializer.DataRoot.FavListCount; i++)
this.comboSource.Properties.Items.Add(new ListOption(list, i, list + " - " + serializer.DataRoot.GetFavListCaption(i-1)));
}
this.comboTarget.EditValue = null;
@@ -149,7 +148,7 @@ namespace ChanSort.Ui
continue;
if (list.IsMixedSourceFavoritesList)
{
for (int i = 0; i <= list.FavListCount; i++)
for (int i = 0; i <= main.DataRoot.FavListCount; i++)
this.comboTarget.Properties.Items.Add(new ListOption(list, i, list + (i==0 ? "" : " - " + main.DataRoot.GetFavListCaption(i-1))));
}
else
@@ -341,7 +340,7 @@ namespace ChanSort.Ui
switch (dlg.ShowDialog(this))
{
case DialogResult.OK:
target.ChannelList.Channels.ForEach(ch => ch.NewProgramNr = -1);
target.ChannelList.Channels.ForEach(ch => ch.SetPosition(target.PosIndex, -1));
break;
case DialogResult.Yes:
//overwrite = true;
@@ -355,7 +354,7 @@ namespace ChanSort.Ui
}
}
main.Editor.ApplyReferenceList(this.serializer.DataRoot, src.ChannelList, target.ChannelList, false, offset, FilterChannel, overwrite, this.cbConsecutive.Checked);
main.Editor.ApplyReferenceList(this.serializer.DataRoot, src.ChannelList, src.PosIndex, target.ChannelList, target.PosIndex, false, offset, FilterChannel, overwrite, this.cbConsecutive.Checked);
main.RefreshGrids();
}

View File

@@ -39,7 +39,7 @@ namespace Test.Loader.M3u
ed.DataRoot = ser.DataRoot;
ed.ChannelList = lists[0];
//ed.ApplyReferenceList(refSer.DataRoot);
ed.ApplyReferenceList(refSer.DataRoot, refSer.DataRoot.ChannelLists.First(), lists[0], false, 0, null, true, false);
ed.ApplyReferenceList(refSer.DataRoot, refSer.DataRoot.ChannelLists.First(), 0, lists[0], 0,false, 0, null, true, false);
Assert.AreEqual(1, chans[5].NewProgramNr);
Assert.AreEqual(2, chans[4].NewProgramNr);

View File

@@ -88,9 +88,9 @@ namespace Test.Loader.Philips
var ch8 = list.Channels.FirstOrDefault(ch => ch.RecordIndex == 8);
Assert.IsTrue(ch8.IsDeleted);
Assert.AreEqual(1, ch4.OldFavIndex[0]);
Assert.AreEqual(2, ch7.OldFavIndex[0]);
Assert.AreEqual(3, ch3.OldFavIndex[0]);
Assert.AreEqual(1, ch4.GetOldPosition(1));
Assert.AreEqual(2, ch7.GetOldPosition(1));
Assert.AreEqual(3, ch3.GetOldPosition(1));
}
}

View File

@@ -1,6 +1,13 @@
ChanSort Change Log
===================
2021-03-13 (alpha)
- Enigma2 lamedb / bouquets support for Linux based Set-Top-Boxes (Dreambox, VU+, Octagon, ...)
- Toshiba settingsDB.db: support for lists without analog tuner data (missing TADTunerDataTable)
- Grunding: failed to load lists where the <Digital> element did not contain a <channels> child element
- W.I.P: reworking the reference list system so that a given flat list of channels can be applied to the
main channel numbers or a particular favorite list.
2021-02-24
- Philips ChannelMap\_45: TV did not remember last selected favorite list when first fav list was created by ChanSort.
- Philips ChannelMap\_100 and later: "Channel" XML elements inside the DVB\*.xml files are now reordered by program nr.