From 2e22005fe1bde38e68f17b15c7b027d088447e36 Mon Sep 17 00:00:00 2001 From: Horst Beham Date: Sun, 11 Apr 2021 13:17:53 +0200 Subject: [PATCH] - added support for user-defined favorite list names within each channel list (antenna, cable, sat, ....) - fixed bug saving wrong audioPid values in LG WebOS 4 XML/JSON files --- source/ChanSort.Api/Model/ChannelList.cs | 27 +++++++++-- source/ChanSort.Api/Model/DataRoot.cs | 22 --------- source/ChanSort.Loader.Enigma2/Serializer.cs | 4 +- .../Binary/TllChannelBase.cs | 2 - .../GlobalClone/GcJsonSerializer.cs | 9 ++-- .../BinarySerializer.cs | 45 ++++++++++++------- .../ChanSort.Loader.Philips.ini | 5 ++- .../ChanSort.Loader.Philips/XmlSerializer.cs | 4 +- source/ChanSort/MainForm.cs | 12 +++-- source/ChanSort/ReferenceListForm.cs | 4 +- source/changelog.md | 4 ++ 11 files changed, 80 insertions(+), 58 deletions(-) diff --git a/source/ChanSort.Api/Model/ChannelList.cs b/source/ChanSort.Api/Model/ChannelList.cs index a157bb1a..f9696f92 100644 --- a/source/ChanSort.Api/Model/ChannelList.cs +++ b/source/ChanSort.Api/Model/ChannelList.cs @@ -33,7 +33,6 @@ public ChannelList(SignalSource source, string caption) public string ShortCaption { get; set; } public SignalSource SignalSource { get; } public IList Channels { get; } = new List(); - public int MaxFavLists { get; set; } public int Count => Channels.Count; public int DuplicateUidCount => duplicateUidCount; @@ -124,8 +123,7 @@ public string AddChannel(ChannelInfo ci) #region GetChannelByUid() public IList GetChannelByUid(string uid) { - IList channel; - this.channelByUid.TryGetValue(uid, out channel); + this.channelByUid.TryGetValue(uid, out var channel); return channel ?? new List(0); } #endregion @@ -174,5 +172,28 @@ public void RemoveChannel(ChannelInfo channel) this.channelByProgNr.Remove(channel.OldProgramNr); } #endregion + + + #region Get/SetFavListCaption() + + private readonly Dictionary favListCaptions = new Dictionary(); + + public void SetFavListCaption(int favIndex, string caption) + { + favListCaptions[favIndex] = caption; + } + + public string GetFavListCaption(int favIndex, bool asTabCaption = false) + { + if (favIndex < 0) + return ""; + var hasCaption = favListCaptions.TryGetValue(favIndex, out var caption); + if (!asTabCaption) + return caption; + var letter = favIndex < 26 ? ((char)('A' + favIndex)).ToString() : (favIndex + 1).ToString(); + return hasCaption && !string.IsNullOrEmpty(caption) ? letter + ": " + caption : "Fav " + letter; + } + #endregion + } } diff --git a/source/ChanSort.Api/Model/DataRoot.cs b/source/ChanSort.Api/Model/DataRoot.cs index 881b9aa1..15cace88 100644 --- a/source/ChanSort.Api/Model/DataRoot.cs +++ b/source/ChanSort.Api/Model/DataRoot.cs @@ -254,27 +254,5 @@ public virtual void ValidateAfterSave() } } #endregion - - - #region Get/SetFavListCaption() - - private readonly Dictionary favListCaptions = new Dictionary(); - - public void SetFavListCaption(int favIndex, string caption) - { - favListCaptions[favIndex] = caption; - } - - public string GetFavListCaption(int favIndex, bool asTabCaption = false) - { - if (favIndex < 0) - return ""; - var hasCaption = favListCaptions.TryGetValue(favIndex, out var caption); - if (!asTabCaption) - return caption; - var letter = favIndex < 26 ? ((char)('A' + favIndex)).ToString() : (favIndex + 1).ToString(); - return hasCaption && !string.IsNullOrEmpty(caption) ? letter + ": " + caption : "Fav " + letter; - } - #endregion } } diff --git a/source/ChanSort.Loader.Enigma2/Serializer.cs b/source/ChanSort.Loader.Enigma2/Serializer.cs index 23a149de..eaaef95c 100644 --- a/source/ChanSort.Loader.Enigma2/Serializer.cs +++ b/source/ChanSort.Loader.Enigma2/Serializer.cs @@ -264,7 +264,7 @@ private void LoadUserBouquet(string file, ref int favIndex) return; } - this.DataRoot.SetFavListCaption(favIndex, line.Substring(6)); + this.channels.SetFavListCaption(favIndex, line.Substring(6)); int lineNr = 0; int progNr = 0; @@ -365,7 +365,7 @@ public override void Save(string tvOutputFile) { var file = this.favListFileNames[favIndex]; using var w = new StreamWriter(File.Create(file), utf8WithoutBom); - w.WriteLine($"#NAME {this.DataRoot.GetFavListCaption(favIndex)}"); + w.WriteLine($"#NAME {this.channels.GetFavListCaption(favIndex)}"); foreach (var ch in this.channels.Channels.OrderBy(c => c.GetPosition(favIndex+1))) { if (!(ch is Channel c) || c.GetPosition(favIndex + 1) < 0) diff --git a/source/ChanSort.Loader.LG/Binary/TllChannelBase.cs b/source/ChanSort.Loader.LG/Binary/TllChannelBase.cs index ee0c8271..c27cec6d 100644 --- a/source/ChanSort.Loader.LG/Binary/TllChannelBase.cs +++ b/source/ChanSort.Loader.LG/Binary/TllChannelBase.cs @@ -51,8 +51,6 @@ protected void InitCommonData(int slot, SignalSource signalSource, DataMapping d this.ParseNames(); this.Favorites = (Favorites)((data.GetByte(_Favorites2) & 0x3C) >> 2); - if (this.Favorites != 0) - { } this.Lock = data.GetFlag(_Lock); this.Skip = data.GetFlag(_Skip); this.Hidden = data.GetFlag(_Hide); diff --git a/source/ChanSort.Loader.LG/GlobalClone/GcJsonSerializer.cs b/source/ChanSort.Loader.LG/GlobalClone/GcJsonSerializer.cs index 305df18b..4310bb86 100644 --- a/source/ChanSort.Loader.LG/GlobalClone/GcJsonSerializer.cs +++ b/source/ChanSort.Loader.LG/GlobalClone/GcJsonSerializer.cs @@ -252,9 +252,9 @@ private void LoadChannels() ch.Transponder = this.DataRoot.Transponder.TryGet((int.Parse(tpId.Substring(0, 4)) << 16) + int.Parse(tpId.Substring(4))); // satId + freq, e.g. 0192126041 ch.IsDeleted = (bool) node["deleted"]; - ch.PcrPid = (int) node["pcrPid"] & 0x3FF; - ch.AudioPid = (int) node["audioPid"] & 0x3FF; - ch.VideoPid = (int) node["videoPid"] & 0x3FF; + ch.PcrPid = (int) node["pcrPid"] & 0x1FFF; + ch.AudioPid = (int) node["audioPid"] & 0x1FFF; + ch.VideoPid = (int) node["videoPid"] & 0x1FFF; ch.ServiceId = (int) node["SVCID"]; if (ch.ServiceId == 0) ch.ServiceId = (int) node["programNum"]; @@ -327,7 +327,8 @@ private void UpdateJsonDoc() node["skipped"] = ch.Skip; node["locked"] = ch.Lock; node["Invisible"] = ch.Hidden; - node["audioPid"] = ch.AudioPid; + if (this.Features.CanEditAudioPid) + node["audioPid"] = ((int)node["audioPid"] & ~0x1FFF) | ch.AudioPid; // the only successfully imported file was one where these flags were NOT set by ChanSort // these flags do get set when changing numbers through the TV's menu, but then prevent further modifications, e.g. through an import diff --git a/source/ChanSort.Loader.Philips/BinarySerializer.cs b/source/ChanSort.Loader.Philips/BinarySerializer.cs index 93fd26d8..f0b3b8e9 100644 --- a/source/ChanSort.Loader.Philips/BinarySerializer.cs +++ b/source/ChanSort.Loader.Philips/BinarySerializer.cs @@ -735,18 +735,19 @@ private void LoadMap30Favorites(string listDb) using var conn = new SQLiteConnection($"Data Source={listDb}"); conn.Open(); using var cmd = conn.CreateCommand(); - - // read favorite list names - disabled because currently ChanSort does not support different names for Fav1-4 based on input source - //cmd.CommandText = "select list_id, list_name from List order by list_id"; - //using (var r = cmd.ExecuteReader()) - //{ - // while (r.Read()) - // { - // var id = r.GetInt32(0); - // var name = r.GetString(1); - // this.DataRoot.SetFavListCaption(id - 1, name); - // } - //} + + // read favorite list names + cmd.CommandText = "select list_id, list_name from List order by list_id"; + using (var r = cmd.ExecuteReader()) + { + while (r.Read()) + { + var id = r.GetInt32(0); + var name = r.GetString(1); + var list = id <= 4 ? this.antChannels : id <= 8 ? this.cabChannels : this.satChannels; + list.SetFavListCaption((id - 1)%4, name); + } + } // read favorite channels for (int listIdx=0; listIdx<12; listIdx++) @@ -815,7 +816,7 @@ private void LoadMap45Favorites(string listDb) listIds.Add(listId); if (!this.mustFixFavListIds) listIndex = listId - 1; - this.DataRoot.SetFavListCaption(listIndex, r.GetString(1)); + this.favChannels.SetFavListCaption(listIndex, r.GetString(1)); ++listIndex; } } @@ -1182,7 +1183,6 @@ private void SaveMap30Favorites(string listDb) using var cmd = conn.CreateCommand(); using var trans = conn.BeginTransaction(); - // TODO change data model so we can support different fav list names in each list and not require same name for Fav1-4 in each input source; then save the names in the "List" table // save favorite channels for (int listIdx = 0; listIdx < 12; listIdx++) @@ -1192,7 +1192,21 @@ private void SaveMap30Favorites(string listDb) if ((long)cmd.ExecuteScalar() == 0) continue; + var incFavList = (ini.GetSection("Map" + chanLstBin.VersionMajor)?.GetBool("incrementFavListVersion", true) ?? true) + ? ", list_version=list_version+1" + : ""; + + var list = listIdx < 4 ? this.antChannels : listIdx < 8 ? this.cabChannels : this.satChannels; + cmd.CommandText = "update List set list_name=@name" + incFavList + " where list_id=@listId"; + cmd.Parameters.Add("@listId", DbType.Int32); + cmd.Parameters.Add("@name", DbType.String); + cmd.Parameters["@listId"].Value = listIdx + 1; + cmd.Parameters["@name"].Value = list.GetFavListCaption(listIdx % 4, false); + cmd.ExecuteNonQuery(); + + cmd.CommandText = $"delete from {table}"; + cmd.Parameters.Clear(); cmd.ExecuteNonQuery(); cmd.CommandText = $"insert into {table} (_id, channel_id, rank) values (@id, @channelId, @rank)"; @@ -1201,7 +1215,6 @@ private void SaveMap30Favorites(string listDb) cmd.Parameters.Add("@rank", DbType.Int32); int order = 0; - var list = listIdx < 4 ? this.antChannels : listIdx < 8 ? this.cabChannels : this.satChannels; foreach (var channel in list.Channels) { if (!(channel is Channel ch)) @@ -1256,7 +1269,7 @@ private void SaveMap45Favorites(string listDb) cmd.Parameters.Add(new SQLiteParameter("@id", DbType.Int16)); cmd.Parameters.Add(new SQLiteParameter("@name", DbType.String)); cmd.Parameters["@id"].Value = favListId; - cmd.Parameters["@name"].Value = DataRoot.GetFavListCaption(favListIndex) ?? "Fav " + (favListIndex + 1); + cmd.Parameters["@name"].Value = this.favChannels.GetFavListCaption(favListIndex) ?? "Fav " + (favListIndex + 1); cmd.ExecuteNonQuery(); cmd.CommandText = "insert into FavoriteChannels(fav_list_id, channel_id, rank) values (@listId,@channelId,@rank)"; diff --git a/source/ChanSort.Loader.Philips/ChanSort.Loader.Philips.ini b/source/ChanSort.Loader.Philips/ChanSort.Loader.Philips.ini index 21181d18..5e8bc2c2 100644 --- a/source/ChanSort.Loader.Philips/ChanSort.Loader.Philips.ini +++ b/source/ChanSort.Loader.Philips/ChanSort.Loader.Philips.ini @@ -45,7 +45,7 @@ offChecksum=0 offSymbolRate=8 offFreq=18 -# ChannelMap_45 format +# ChannelMap_45 format (also used for ChannelMap_30) [Map45_CableDb.bin_entry] offId=0 @@ -89,6 +89,9 @@ offUnk1=48 offUnk2=68 offPolarity=72 +[Map30] +incrementFavListVersion=true + [Map45] incrementFavListVersion=true diff --git a/source/ChanSort.Loader.Philips/XmlSerializer.cs b/source/ChanSort.Loader.Philips/XmlSerializer.cs index 4a6e41b6..357e42c0 100644 --- a/source/ChanSort.Loader.Philips/XmlSerializer.cs +++ b/source/ChanSort.Loader.Philips/XmlSerializer.cs @@ -428,7 +428,7 @@ private void ReadFavList(XmlNode node) this.Features.FavoritesMode = FavoritesMode.MixedSource; this.Features.MaxFavoriteLists = Math.Max(this.Features.MaxFavoriteLists, index); - this.DataRoot.SetFavListCaption(index - 1, name); + this.favChannels.SetFavListCaption(index - 1, name); if (this.favChannels.Count == 0) { @@ -586,7 +586,7 @@ private void UpdateFavList() favListNode.InnerXml = ""; // clear all child elements but keep the attributes of the current node var attr = favListNode.Attributes?["Name"]; if (attr != null) - attr.InnerText = EncodeName(this.DataRoot.GetFavListCaption(index - 1), (attr.InnerText.Length + 1)/5, false); + attr.InnerText = EncodeName(this.favChannels.GetFavListCaption(index - 1), (attr.InnerText.Length + 1)/5, false); // increment fav list version, unless disabled in .ini file if (chanLstBin != null && (ini.GetSection("Map" + chanLstBin.VersionMajor)?.GetBool("incrementFavListVersion", true) ?? true)) diff --git a/source/ChanSort/MainForm.cs b/source/ChanSort/MainForm.cs index c13ae77d..2b29bd87 100644 --- a/source/ChanSort/MainForm.cs +++ b/source/ChanSort/MainForm.cs @@ -471,7 +471,7 @@ private void UpdateFavoritesEditor(Favorites favorites) while (this.tabSubList.TabPages.Count < favCount + 1) this.tabSubList.TabPages.Add(); for (int i = 1; i < this.tabSubList.TabPages.Count; i++) - this.tabSubList.TabPages[i].Text = this.DataRoot.GetFavListCaption(i - 1, true); + this.tabSubList.TabPages[i].Text = this.CurrentChannelList?.GetFavListCaption(i - 1, true); this.tabSubList.EndUpdate(); if (!this.DataRoot.SortedFavorites || this.subListIndex > favCount) @@ -724,6 +724,7 @@ private void ShowChannelList(ChannelList channelList) this.UpdateInsertSlotNumber(); this.UpdateMenu(); + this.UpdateFavoritesEditor(this.DataRoot.SupportedFavorites); // this will update the tabs with the (custom) names of the Fav lists this.mnuFavList.Enabled = this.grpSubList.Visible; if (!this.grpSubList.Visible) @@ -3392,6 +3393,9 @@ private void tabSubList_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { + var list = this.CurrentChannelList; + if (list == null) + return; var hit = this.tabSubList.CalcHitInfo(e.Location); if (hit.IsValid && hit.Page != null) { @@ -3399,11 +3403,11 @@ private void tabSubList_MouseUp(object sender, MouseEventArgs e) dlg.StartPosition = FormStartPosition.Manual; dlg.Location = this.tabSubList.PointToScreen(e.Location); var favIndex = this.tabSubList.TabPages.IndexOf(hit.Page) - 1; - dlg.Text = this.DataRoot.GetFavListCaption(favIndex); + dlg.Text = list.GetFavListCaption(favIndex); if (dlg.ShowDialog(this) == DialogResult.OK) { - this.DataRoot.SetFavListCaption(favIndex, dlg.Text); - hit.Page.Text = this.DataRoot.GetFavListCaption(favIndex, true); + list.SetFavListCaption(favIndex, dlg.Text); + hit.Page.Text = list.GetFavListCaption(favIndex, true); } } } diff --git a/source/ChanSort/ReferenceListForm.cs b/source/ChanSort/ReferenceListForm.cs index 79bd6127..cbaaa60d 100644 --- a/source/ChanSort/ReferenceListForm.cs +++ b/source/ChanSort/ReferenceListForm.cs @@ -136,7 +136,7 @@ private void SetInput(SerializerBase ser) if (!serializer.DataRoot.MixedSourceFavorites || list.IsMixedSourceFavoritesList) { for (int i = 1; i <= serializer.DataRoot.FavListCount; i++) - this.comboSource.Properties.Items.Add(new ListOption(list, i, list.ShortCaption + " - " + serializer.DataRoot.GetFavListCaption(i - 1, true))); + this.comboSource.Properties.Items.Add(new ListOption(list, i, list.ShortCaption + " - " + list.GetFavListCaption(i - 1, true))); } } @@ -150,7 +150,7 @@ private void SetInput(SerializerBase ser) if (list.IsMixedSourceFavoritesList) { for (int i = 1; i <= main.DataRoot.FavListCount; i++) - this.comboTarget.Properties.Items.Add(new ListOption(list, i, list.ShortCaption + (i == 0 ? "" : " - " + main.DataRoot.GetFavListCaption(i - 1, true)))); + this.comboTarget.Properties.Items.Add(new ListOption(list, i, list.ShortCaption + (i == 0 ? "" : " - " + list.GetFavListCaption(i - 1, true)))); } else { diff --git a/source/changelog.md b/source/changelog.md index 5d3158de..d2835c1b 100644 --- a/source/changelog.md +++ b/source/changelog.md @@ -1,6 +1,10 @@ ChanSort Change Log =================== +2021-04-11 +- Philips: added support for ChannelMap\_30 format +- LG Web OS 5: fixed a bug that wrote wrong values for "audioPid" to the file (which had no effect on the TV's operation) + 2021-04-10 - Samsung .zip: Support for files that contain an empty SRV_EXT_APP table, which caused the whole list to show up empty.