diff --git a/source/ChanSort.Api/Controller/Editor.cs b/source/ChanSort.Api/Controller/Editor.cs index 399561a..57dac19 100644 --- a/source/ChanSort.Api/Controller/Editor.cs +++ b/source/ChanSort.Api/Controller/Editor.cs @@ -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 /// /// controls whether Pr# will be reassigned to the reference channel when they are already in-use in the TV list /// when true, consecutive numbers will be used instead of the Pr# in the reference list when applying the order - public void ApplyReferenceList(DataRoot refDataRoot, ChannelList refList, ChannelList tvList, bool addProxyChannels = true, int positionOffset = 0, Func 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 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> 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; } } diff --git a/source/ChanSort.Api/Model/ChannelInfo.cs b/source/ChanSort.Api/Model/ChannelInfo.cs index 266cb2f..3b3897b 100644 --- a/source/ChanSort.Api/Model/ChannelInfo.cs +++ b/source/ChanSort.Api/Model/ChannelInfo.cs @@ -72,11 +72,11 @@ namespace ChanSort.Api /// /// current number of the channel in the various favorite lists (if individual sorting is supported) /// - public List FavIndex { get; } + private List FavIndex { get; } /// /// original number of the channel in the various favorite lists (if individual sorting is supported) /// - public List OldFavIndex { get; } + private List OldFavIndex { get; } /// /// 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; } diff --git a/source/ChanSort.Api/Model/ChannelList.cs b/source/ChanSort.Api/Model/ChannelList.cs index 94e40c0..cce962c 100644 --- a/source/ChanSort.Api/Model/ChannelList.cs +++ b/source/ChanSort.Api/Model/ChannelList.cs @@ -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 DefaultVisibleColumns { get; set; } = new List(); // initialized by MainForm diff --git a/source/ChanSort.Api/Model/DataRoot.cs b/source/ChanSort.Api/Model/DataRoot.cs index bf1a027..ba2eacd 100644 --- a/source/ChanSort.Api/Model/DataRoot.cs +++ b/source/ChanSort.Api/Model/DataRoot.cs @@ -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)); } } } diff --git a/source/ChanSort.Loader.Enigma2/Channel.cs b/source/ChanSort.Loader.Enigma2/Channel.cs index cca83db..b65b7c1 100644 --- a/source/ChanSort.Loader.Enigma2/Channel.cs +++ b/source/ChanSort.Loader.Enigma2/Channel.cs @@ -7,7 +7,7 @@ namespace ChanSort.Loader.Enigma2 /// /// first two fields of the lamedb entry /// - public string Prefix { get; set; } + public string Prefix { get; set; } = "1:0"; /// /// 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; } - + /// /// all fields after the DVB-namespace in the lamedb entry /// - public string Suffix { get; set; } + public string Suffix { get; set; } = ":0:0:0:"; /// /// #DESCRIPTION of the userbouquet entry diff --git a/source/ChanSort.Loader.Enigma2/Serializer.cs b/source/ChanSort.Loader.Enigma2/Serializer.cs index c6abbc0..56baec2 100644 --- a/source/ChanSort.Loader.Enigma2/Serializer.cs +++ b/source/ChanSort.Loader.Enigma2/Serializer.cs @@ -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); diff --git a/source/ChanSort.Loader.Grundig/Serializer.cs b/source/ChanSort.Loader.Grundig/Serializer.cs index 74c08a6..2ac9b9b 100644 --- a/source/ChanSort.Loader.Grundig/Serializer.cs +++ b/source/ChanSort.Loader.Grundig/Serializer.cs @@ -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) diff --git a/source/ChanSort.Loader.Hisense/ChannelDb/ChannelDbSerializer.cs b/source/ChanSort.Loader.Hisense/ChannelDb/ChannelDbSerializer.cs index fcb6a27..867865d 100644 --- a/source/ChanSort.Loader.Hisense/ChannelDb/ChannelDbSerializer.cs +++ b/source/ChanSort.Loader.Hisense/ChannelDb/ChannelDbSerializer.cs @@ -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; diff --git a/source/ChanSort.Loader.Hisense/ServicelistDb/ServicelistDbSerializer.cs b/source/ChanSort.Loader.Hisense/ServicelistDb/ServicelistDbSerializer.cs index 6edbcbc..1cd3f1f 100644 --- a/source/ChanSort.Loader.Hisense/ServicelistDb/ServicelistDbSerializer.cs +++ b/source/ChanSort.Loader.Hisense/ServicelistDb/ServicelistDbSerializer.cs @@ -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) diff --git a/source/ChanSort.Loader.Panasonic/DbChannel.cs b/source/ChanSort.Loader.Panasonic/DbChannel.cs index 17cf98f..f34a297 100644 --- a/source/ChanSort.Loader.Panasonic/DbChannel.cs +++ b/source/ChanSort.Loader.Panasonic/DbChannel.cs @@ -69,7 +69,7 @@ namespace ChanSort.Loader.Panasonic if (favIndex > 0) { this.Favorites |= (Favorites) (1 << i); - this.OldFavIndex[i] = favIndex; + this.SetOldPosition(i, favIndex); } } } diff --git a/source/ChanSort.Loader.Panasonic/Serializer.cs b/source/ChanSort.Loader.Panasonic/Serializer.cs index c5cedec..8343f34 100644 --- a/source/ChanSort.Loader.Panasonic/Serializer.cs +++ b/source/ChanSort.Loader.Panasonic/Serializer.cs @@ -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(); diff --git a/source/ChanSort.Loader.Philips/BinarySerializer.cs b/source/ChanSort.Loader.Philips/BinarySerializer.cs index 90c9cbe..faa08d2 100644 --- a/source/ChanSort.Loader.Philips/BinarySerializer.cs +++ b/source/ChanSort.Loader.Philips/BinarySerializer.cs @@ -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); diff --git a/source/ChanSort.Loader.Philips/XmlSerializer.cs b/source/ChanSort.Loader.Philips/XmlSerializer.cs index 1ec88be..2e1af13 100644 --- a/source/ChanSort.Loader.Philips/XmlSerializer.cs +++ b/source/ChanSort.Loader.Philips/XmlSerializer.cs @@ -432,7 +432,7 @@ namespace ChanSort.Loader.Philips foreach (var chan in rootList.Channels) { favChannels.Channels.Add(chan); - for (int i=0; i= 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); } } } diff --git a/source/ChanSort.Loader.Sony/Serializer.cs b/source/ChanSort.Loader.Sony/Serializer.cs index f46d1e6..a7c31df 100644 --- a/source/ChanSort.Loader.Sony/Serializer.cs +++ b/source/ChanSort.Loader.Sony/Serializer.cs @@ -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); } } diff --git a/source/ChanSort.Loader.Toshiba/SettingsDbSerializer.cs b/source/ChanSort.Loader.Toshiba/SettingsDbSerializer.cs index c9d6993..83e383a 100644 --- a/source/ChanSort.Loader.Toshiba/SettingsDbSerializer.cs +++ b/source/ChanSort.Loader.Toshiba/SettingsDbSerializer.cs @@ -19,6 +19,8 @@ namespace ChanSort.Loader.Toshiba { private readonly ChannelList channels = new ChannelList(SignalSource.All, "All"); + private readonly HashSet 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; } diff --git a/source/ChanSort/MainForm.cs b/source/ChanSort/MainForm.cs index be0f5d3..f97417d 100644 --- a/source/ChanSort/MainForm.cs +++ b/source/ChanSort/MainForm.cs @@ -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; diff --git a/source/ChanSort/ReferenceListForm.cs b/source/ChanSort/ReferenceListForm.cs index 62dd364..103f5a9 100644 --- a/source/ChanSort/ReferenceListForm.cs +++ b/source/ChanSort/ReferenceListForm.cs @@ -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(); } diff --git a/source/Test.Loader.M3u/M3uTest.cs b/source/Test.Loader.M3u/M3uTest.cs index 8958087..4922a5d 100644 --- a/source/Test.Loader.M3u/M3uTest.cs +++ b/source/Test.Loader.M3u/M3uTest.cs @@ -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); diff --git a/source/Test.Loader.Philips/PhilipsBinS2channellibTest.cs b/source/Test.Loader.Philips/PhilipsBinS2channellibTest.cs index 475e6a6..61db45c 100644 --- a/source/Test.Loader.Philips/PhilipsBinS2channellibTest.cs +++ b/source/Test.Loader.Philips/PhilipsBinS2channellibTest.cs @@ -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)); } } diff --git a/source/changelog.md b/source/changelog.md index 92386a9..680b782 100644 --- a/source/changelog.md +++ b/source/changelog.md @@ -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 element did not contain a 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.