From e582cb95b722e5a7391e34112086bf8abdba21f9 Mon Sep 17 00:00:00 2001 From: Horst Beham Date: Wed, 5 Oct 2022 18:03:12 +0200 Subject: [PATCH] - function to remove backup files (so that a new backup will be generated) - remember last directory in FileOpenDialog, even when opening the file failed - HDD Hex Editor Neo file structure definition - improvements for Panasonic LS/LX serializer --- .../IdtvChannelSerializer.cs | 116 +++++++++++------- .../PanasonicPlugin.cs | 15 +-- source/ChanSort/MainForm.Designer.cs | 23 ++-- source/ChanSort/MainForm.cs | 37 +++++- source/ChanSort/MainForm.resx | 25 +++- .../panasonic_idtvChannelBin.h | 51 ++++++++ 6 files changed, 202 insertions(+), 65 deletions(-) create mode 100644 source/Information/FileStructures_for_HHD_Hex_Editor_Neo/panasonic_idtvChannelBin.h diff --git a/source/ChanSort.Loader.Panasonic/IdtvChannelSerializer.cs b/source/ChanSort.Loader.Panasonic/IdtvChannelSerializer.cs index 329efd6..d5c0783 100644 --- a/source/ChanSort.Loader.Panasonic/IdtvChannelSerializer.cs +++ b/source/ChanSort.Loader.Panasonic/IdtvChannelSerializer.cs @@ -4,6 +4,7 @@ using System.IO; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; +using System.Xml.Linq; using ChanSort.Api; using Microsoft.Data.Sqlite; @@ -39,29 +40,35 @@ internal class IdtvChannelSerializer : SerializerBase Encrypted = 0x0002, IsFavorite = 0x0080, Deleted = 0x0100, - Hidden = 0x0400 + Skip = 0x0400, + CustomProgNr = 0x1000 } - [StructLayout(LayoutKind.Sequential)] + [StructLayout(LayoutKind.Sequential,Pack=1)] unsafe struct IdtvChannel { public short U0; // always 1 public short RecordLength; // 60 + length of channel name public short U4; // always 6 - public fixed byte U6[10]; // all 00 + public fixed byte U6[3]; // all 00 + public ushort U9; // 0 = sat, 18 = cable ? + public fixed byte U11[5]; // all 00 public uint Freq; // Hz for DVB-C/T, kHz for DVB-S public uint SymRate; // in Sym/s, like 22000000 public short U24; // always 100 public short U26; // always 0 public short U28; // always 0 public short ProgNr; - public fixed byte U32[4]; // e.g. 0a 01 00 00 + public short Lcn; // maybe? + public fixed byte U32[2]; // e.g. 0a 01 00 00 public Flags Flags; public fixed byte U38[4]; // 12 07 01 02 public short Tsid; public short Onid; public short Sid; - public fixed byte U48[16]; + public fixed byte U48[4]; + public uint InternalProviderFlag2; // seems like all sat channels are in the 20000-29999 range, dvb-c in 30000-39999 + public fixed byte U56[8]; //public fixed byte ChannelName[RecordLength - 60]; // pseudo-C# description of variable length channel name UTF8 data at end of structure } @@ -70,18 +77,21 @@ internal class IdtvChannelSerializer : SerializerBase private readonly string dbFile; private readonly string binFile; private Dictionary channelDict = new(); // maps record-index of .bin file to Channel object created from .db file + private byte[] binFileData; private List binFileRecordOffsets = new(); private readonly StringBuilder log = new(); #region ctor() - public IdtvChannelSerializer(string inputFile) : base(inputFile) + public IdtvChannelSerializer(string hotelBin) : base(hotelBin) { - dbFile = inputFile; - binFile = Path.Combine(Path.GetDirectoryName(dbFile), "channel", "idtvChannel.bin"); + var dir = Path.Combine(Path.GetDirectoryName(hotelBin), "mnt/vendor/tvdata/database"); + dbFile = Path.Combine(dir, "tv.db"); + binFile = Path.Combine(dir, "channel", "idtvChannel.bin"); this.Features.CanSaveAs = false; this.Features.FavoritesMode = FavoritesMode.Flags; + this.Features.DeleteMode = DeleteMode.FlagWithPrNr; this.DataRoot.AddChannelList(new ChannelList(SignalSource.Antenna | SignalSource.MaskTvRadioData, "Antenna")); this.DataRoot.AddChannelList(new ChannelList(SignalSource.Cable | SignalSource.MaskTvRadioData, "Cable")); @@ -89,6 +99,7 @@ internal class IdtvChannelSerializer : SerializerBase foreach (var list in this.DataRoot.ChannelLists) { var names = list.VisibleColumnFieldNames; + names.Remove(nameof(ChannelInfo.Hidden)); // the TV's "hide" function actually works like "skip", only removing it from zapping, but allowing direct number input names.Remove(nameof(ChannelInfo.ShortName)); names.Remove(nameof(ChannelInfo.Satellite)); names.Remove(nameof(ChannelInfo.PcrPid)); @@ -178,8 +189,8 @@ internal class IdtvChannelSerializer : SerializerBase ch.Hidden = !r.GetBoolean(cols["searchable"]); ch.Encrypted = r.GetBoolean(cols["scrambled"]); - ch.OriginalNetworkId = r.GetInt16(cols["original_network_id"]); - ch.TransportStreamId = r.GetInt16(cols["transport_stream_id"]); + ch.OriginalNetworkId = r.GetInt32(cols["original_network_id"]); + ch.TransportStreamId = r.GetInt32(cols["transport_stream_id"]); ch.ServiceId = r.GetInt32(cols["service_id"]); ch.FreqInMhz = r.GetInt64(cols["internal_provider_flag1"]) / 1000; // for DVB-S it is in MHz, for DVB-C/T it is in kHz if (ch.FreqInMhz >= 13000) @@ -197,6 +208,9 @@ internal class IdtvChannelSerializer : SerializerBase var list = this.DataRoot.GetChannelList(signalSource); this.DataRoot.AddChannel(list, ch); + if (channelDict.TryGetValue(ch.RecordOrder, out var otherChannel)) + throw new FileLoadException($"tv.db channel _ids {otherChannel.RecordIndex} ({otherChannel.Name}) and {ch.RecordIndex} ({ch.Name}) both reference same idtvChannel.bin record {ch.RecordOrder}\n"+ + "Please make sure to search satellite channels first and cable/antenna afterwards."); channelDict.Add(ch.RecordOrder, ch); } } @@ -205,19 +219,19 @@ internal class IdtvChannelSerializer : SerializerBase #region ReadIdtvChannelsBin() private void ReadIdtvChannelsBin() { + this.binFileData = File.ReadAllBytes(this.binFile); + // verify MD5 checksum - var data = File.ReadAllBytes(this.binFile); var md5 = MD5.Create(); - var hash = md5.ComputeHash(data, 24, data.Length - 24); + var hash = md5.ComputeHash(binFileData, 24, binFileData.Length - 24); int i; for (i = 0; i < 16; i++) { - if (data[8 + i] != hash[i]) + if (binFileData[8 + i] != hash[i]) throw new FileLoadException("Invalid MD5 checksum in " + binFile); } - - using var strm = new MemoryStream(data); + using var strm = new MemoryStream(binFileData); using var r = new BinaryReader(strm); r.ReadBytes(2 + 2); // 00 00, 4b 09 @@ -226,8 +240,10 @@ internal class IdtvChannelSerializer : SerializerBase r.ReadBytes(16); // md5 i = 0; + log.AppendLine($"#\tname\tprogNr\tonid-tsid-sid\tflags\tlcn\tipf2"); + var structSize = Marshal.SizeOf(); - while (strm.Position + structSize <= data.Length) + while (strm.Position + structSize <= binFileData.Length) { var off = strm.Position; binFileRecordOffsets.Add((int)off); @@ -245,7 +261,7 @@ internal class IdtvChannelSerializer : SerializerBase var progNr = chan.ProgNr; var name = Encoding.UTF8.GetString(r.ReadBytes(chan.RecordLength - 60)); - log.AppendLine($"{i}\t{name}\t{progNr}\t{chan.Onid}-{chan.Tsid}-{chan.Sid}\t{(ushort)chan.Flags:X4}"); + log.AppendLine($"{i}\t{name}\t{progNr}\t{chan.Onid}-{chan.Tsid}-{chan.Sid}\t{(ushort)chan.Flags:X4}\t{chan.Lcn}\t{chan.InternalProviderFlag2}"); if (channelDict.TryGetValue(i, out var ch)) { @@ -260,8 +276,8 @@ internal class IdtvChannelSerializer : SerializerBase if (ch.Encrypted != ((chan.Flags & Flags.Encrypted) != 0)) throw new FileLoadException($"mismatching crypt-flag between tv.db _id {ch.RecordIndex} ({ch.Encrypted}) and idtvChannel.bin record {i}"); - if (ch.Hidden != ((chan.Flags & Flags.Hidden) != 0)) - throw new FileLoadException($"mismatching hide-flag between tv.db _id {ch.RecordIndex} ({ch.Hidden}) and idtvChannel.bin record {i}"); + if (ch.Skip != ((chan.Flags & Flags.Skip) != 0)) + throw new FileLoadException($"mismatching browsable-flag between tv.db _id {ch.RecordIndex} ({ch.Skip}) and idtvChannel.bin record {i}"); if ((ch.Favorites == 0) != ((chan.Flags & Flags.IsFavorite) == 0)) throw new FileLoadException($"mismatching favorites-info between tv.db _id {ch.RecordIndex} ({ch.Favorites}) and idtvChannel.bin record {i}"); @@ -292,9 +308,9 @@ internal class IdtvChannelSerializer : SerializerBase public override void Save(string tvOutputFile) { // saving the list requires to: - // - physically reorder the .bin file and update fields inside the data records + // - update fields inside the data records and physically reorder the records // - updating records in the .db file - // - updating this loaders internal data in channelDict, binFileRecordOffsets and channelInfo.RecordOrder for consecutive save operations to work + // - updating all channel record indexes in this loader's internal data in channelDict, binFileRecordOffsets and channelInfo.RecordOrder for consecutive save operations to work GetNewIdtvChannelBinRecordOrder(out var newToOld, out var oldToNew); @@ -310,8 +326,17 @@ internal class IdtvChannelSerializer : SerializerBase newToOld = new List(binFileRecordOffsets.Count); for (int i = 0, c=this.binFileRecordOffsets.Count; i(nameof(IdtvChannel.Freq)); newToOld.Sort((a, b) => { + // all sat channels must come first before cable/antenna channels + var freq1 = BitConverter.ToUInt32(this.binFileData, binFileRecordOffsets[a] + offFreq); + var freq2 = BitConverter.ToUInt32(this.binFileData, binFileRecordOffsets[b] + offFreq); + var c = (freq1 < 14000000 ? 0 : 1).CompareTo(freq2 < 14000000 ? 0 : 1); // hack: Sat has values below 14 000 000 (in kHz), Cable/antenna above (in Hz) + if (c != 0) + return c; + this.channelDict.TryGetValue(a, out var ch1); this.channelDict.TryGetValue(b, out var ch2); if (ch1 == null && ch2 == null) @@ -321,7 +346,7 @@ internal class IdtvChannelSerializer : SerializerBase if (ch1 == null) return +1; - var c = ch1.SignalSource.CompareTo(ch2.SignalSource); // group by DVB-C/T/S and TV/Radio/Data + c = ((int)ch1.SignalSource).CompareTo((int)ch2.SignalSource); // group TV/Radio/Data if (c != 0) return c; c = ch1.NewProgramNr.CompareTo(ch2.NewProgramNr); @@ -341,64 +366,70 @@ internal class IdtvChannelSerializer : SerializerBase #region SaveIdtvChannelBin() private void SaveIdtvChannelBin(IList newToOld) { - var data = UpdateIdtvChannelBinRecords(); - - data = ReorderBinFileRecords(data, newToOld); + UpdateIdtvChannelBinRecords(); + ReorderBinFileRecords(newToOld); // update MD5 checksum var md5 = MD5.Create(); - var checksum = md5.ComputeHash(data, 8 + 16, data.Length - 8 - 16); - Array.Copy(checksum, 0, data, 8, 16); + var checksum = md5.ComputeHash(binFileData, 8 + 16, binFileData.Length - 8 - 16); + Array.Copy(checksum, 0, binFileData, 8, 16); - File.WriteAllBytes(binFile, data); + File.WriteAllBytes(binFile, binFileData); } #endregion #region UpdateIdtvChannelBinRecords() - private byte[] UpdateIdtvChannelBinRecords() + private void UpdateIdtvChannelBinRecords() { // in-place update of the old .bin file data var offProgNr = (int)Marshal.OffsetOf(nameof(IdtvChannel.ProgNr)); var offFlags = (int)Marshal.OffsetOf(nameof(IdtvChannel.Flags)); - var data = File.ReadAllBytes(this.binFile); - var w = new BinaryWriter(new MemoryStream(data)); + var w = new BinaryWriter(new MemoryStream(this.binFileData)); foreach (var list in this.DataRoot.ChannelLists) { foreach (var ch in list.Channels) { + if (ch.IsProxy) + continue; var filePosition = this.binFileRecordOffsets[ch.RecordOrder]; w.Seek(filePosition + offProgNr, SeekOrigin.Begin); - w.Write((ushort)ch.NewProgramNr); + //w.Write(ch.NewProgramNr > 0 ? (ushort)ch.NewProgramNr : (ushort)0xFFFE); // deleted channels have -2 / 0xFFFE + w.Write(ch.NewProgramNr); // update flags var off = filePosition + offFlags; - var flags = BitConverter.ToUInt16(data, off); + var flags = BitConverter.ToUInt16(this.binFileData, off); if (ch.Favorites == 0) flags = (ushort)(flags & ~(ushort)Flags.IsFavorite); else flags = (ushort)(flags | (ushort)Flags.IsFavorite); - if (ch.Hidden) - flags = (ushort)(flags | (ushort)Flags.Hidden); + + if (ch.Skip) + flags = (ushort)(flags | (ushort)Flags.Skip); else - flags = (ushort)(flags & ~(ushort)Flags.Hidden); + flags = (ushort)(flags & ~(ushort)Flags.Skip); + + if (ch.IsDeleted) + flags |= (ushort)Flags.Deleted; + + flags |= (ushort)Flags.CustomProgNr; w.Seek(filePosition + offFlags, SeekOrigin.Begin); w.Write(flags); } } w.Flush(); - return data; } #endregion #region ReorderBinFileRecords() - private byte[] ReorderBinFileRecords(byte[] binFileData, IList newToOld) + private void ReorderBinFileRecords(IList newToOld) { - using var mem = new MemoryStream(binFileData.Length); + using var mem = new MemoryStream(this.binFileData.Length); mem.Write(binFileData, 0, 8 + 16); // copy header var newOffsets = new List(newToOld.Count); @@ -416,7 +447,6 @@ internal class IdtvChannelSerializer : SerializerBase binFileData = new byte[mem.Length]; Array.Copy(mem.GetBuffer(), 0, binFileData, 0, mem.Length); - return binFileData; } #endregion @@ -430,11 +460,11 @@ internal class IdtvChannelSerializer : SerializerBase using var trans = db.BeginTransaction(); using var upd = db.CreateCommand(); - upd.CommandText = "update channels set display_number=@progNr, browsable=@browseable, searchable=@searchable, locked=@locked, favorite=@fav, channel_index=@recIdx where _id=@id"; + upd.CommandText = "update channels set display_number=@progNr, browsable=@browseable, locked=@locked, favorite=@fav, channel_index=@recIdx where _id=@id"; // searchable=@searchable, upd.Parameters.Add("@id", SqliteType.Integer); upd.Parameters.Add("@progNr", SqliteType.Text); upd.Parameters.Add("@browseable", SqliteType.Integer); - upd.Parameters.Add("@searchable", SqliteType.Integer); + //upd.Parameters.Add("@searchable", SqliteType.Integer); upd.Parameters.Add("@locked", SqliteType.Integer); upd.Parameters.Add("@fav", SqliteType.Integer); upd.Parameters.Add("@recIdx", SqliteType.Integer); @@ -464,7 +494,7 @@ internal class IdtvChannelSerializer : SerializerBase upd.Parameters["@id"].Value = ch.RecordIndex; upd.Parameters["@progNr"].Value = ch.NewProgramNr; upd.Parameters["@browseable"].Value = !ch.Skip; - upd.Parameters["@searchable"].Value = !ch.Hidden; + //upd.Parameters["@searchable"].Value = !ch.Hidden; upd.Parameters["@locked"].Value = ch.Lock; upd.Parameters["@fav"].Value = (int)ch.Favorites; upd.Parameters["@recIdx"].Value = newRecordIndex; diff --git a/source/ChanSort.Loader.Panasonic/PanasonicPlugin.cs b/source/ChanSort.Loader.Panasonic/PanasonicPlugin.cs index fd5ea19..97cc26f 100644 --- a/source/ChanSort.Loader.Panasonic/PanasonicPlugin.cs +++ b/source/ChanSort.Loader.Panasonic/PanasonicPlugin.cs @@ -15,13 +15,14 @@ namespace ChanSort.Loader.Panasonic // check for files in the 2022 /mnt/vendor/tvdata/database/channel/ directory structure file format with tv.db and idtvChannel.bin var name = Path.GetFileName(inputFile).ToLowerInvariant(); var baseDir = Path.GetDirectoryName(inputFile); - if (name == "hotel.bin") - baseDir = Path.Combine(baseDir, "mnt", "vendor", "tvdata", "database"); - if (name == "idtvChannel.bin") - baseDir = Path.GetDirectoryName(baseDir); - var tvDb = Path.Combine(baseDir, "tv.db"); - if (File.Exists(tvDb) && File.Exists(Path.Combine(baseDir, "channel", "idtvChannel.bin"))) - return new IdtvChannelSerializer(tvDb); + if (name == "idtvchannel.bin") + baseDir = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(baseDir))))); // go down channel/database/tvdata/vendor/mnt + else if (name == "tv.db") + baseDir = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(baseDir)))); // go down database/tvdata/vendor/mnt + + var hotelBin = Path.Combine(baseDir, "hotel.bin"); + if (File.Exists(hotelBin) && File.Exists(Path.Combine(baseDir, "mnt/vendor/tvdata/database", "tv.db")) && File.Exists(Path.Combine(baseDir, "mnt/vendor/tvdata/database/channel", "idtvChannel.bin"))) + return new IdtvChannelSerializer(hotelBin); // Android based models use an .xml format. Unfortunately that format is utter garbage and not really useful var ext = Path.GetExtension(inputFile).ToLowerInvariant(); diff --git a/source/ChanSort/MainForm.Designer.cs b/source/ChanSort/MainForm.Designer.cs index 0013cd9..5d2c3ce 100644 --- a/source/ChanSort/MainForm.Designer.cs +++ b/source/ChanSort/MainForm.Designer.cs @@ -220,6 +220,7 @@ this.popupInputSource = new DevExpress.XtraBars.PopupMenu(this.components); this.popupFavList = new DevExpress.XtraBars.PopupMenu(this.components); this.timerSelectFocusedRow = new System.Windows.Forms.Timer(this.components); + this.miDeleteBackup = new DevExpress.XtraBars.BarButtonItem(); ((System.ComponentModel.ISupportInitialize)(this.splitContainerControl1)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.splitContainerControl1.Panel1)).BeginInit(); this.splitContainerControl1.Panel1.SuspendLayout(); @@ -235,7 +236,6 @@ ((System.ComponentModel.ISupportInitialize)(this.repositoryItemTextEdit1)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pnlEditControls)).BeginInit(); this.pnlEditControls.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.globalImageCollection1)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.grpInputList)).BeginInit(); this.grpInputList.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.gridRight)).BeginInit(); @@ -494,10 +494,6 @@ this.btnSearchLeft.Name = "btnSearchLeft"; this.btnSearchLeft.Click += new System.EventHandler(this.btnSearch_Click); // - // globalImageCollection1 - // - this.globalImageCollection1.ParentControl = this; - // // btnToggleFavH // resources.ApplyResources(this.btnToggleFavH, "btnToggleFavH"); @@ -1129,9 +1125,10 @@ this.miSplitView, this.miTheme, this.miAutoHideColumns, - this.miLoadListAfterStart}); + this.miLoadListAfterStart, + this.miDeleteBackup}); this.barManager1.MainMenu = this.bar1; - this.barManager1.MaxItemId = 117; + this.barManager1.MaxItemId = 118; this.barManager1.ShowFullMenus = true; this.barManager1.ShortcutItemClick += new DevExpress.XtraBars.ShortcutItemClickEventHandler(this.barManager1_ShortcutItemClick); // @@ -1182,6 +1179,7 @@ new DevExpress.XtraBars.LinkPersistInfo(this.miOpen), new DevExpress.XtraBars.LinkPersistInfo(this.miReload), new DevExpress.XtraBars.LinkPersistInfo(this.miRestoreOriginal), + new DevExpress.XtraBars.LinkPersistInfo(this.miDeleteBackup), new DevExpress.XtraBars.LinkPersistInfo(this.miFileInformation), new DevExpress.XtraBars.LinkPersistInfo(this.miSave, true), new DevExpress.XtraBars.LinkPersistInfo(this.miSaveAs), @@ -2224,6 +2222,13 @@ // this.timerSelectFocusedRow.Tick += new System.EventHandler(this.timerSelectFocusedRow_Tick); // + // miDeleteBackup + // + resources.ApplyResources(this.miDeleteBackup, "miDeleteBackup"); + this.miDeleteBackup.Id = 117; + this.miDeleteBackup.Name = "miDeleteBackup"; + this.miDeleteBackup.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miDeleteBackup_ItemClick); + // // MainForm // this.AllowDrop = true; @@ -2256,7 +2261,6 @@ ((System.ComponentModel.ISupportInitialize)(this.repositoryItemTextEdit1)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pnlEditControls)).EndInit(); this.pnlEditControls.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.globalImageCollection1)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.grpInputList)).EndInit(); this.grpInputList.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.gridRight)).EndInit(); @@ -2480,6 +2484,7 @@ private System.Windows.Forms.Timer timerSelectFocusedRow; private DevExpress.XtraBars.BarButtonItem miAutoHideColumns; private DevExpress.XtraBars.BarButtonItem miLoadListAfterStart; - } + private DevExpress.XtraBars.BarButtonItem miDeleteBackup; + } } diff --git a/source/ChanSort/MainForm.cs b/source/ChanSort/MainForm.cs index 5e1d4cc..accc03b 100644 --- a/source/ChanSort/MainForm.cs +++ b/source/ChanSort/MainForm.cs @@ -57,6 +57,7 @@ namespace ChanSort.Ui private bool splitView = true; private int ignoreEvents; private bool adjustWindowLocationOnScale = true; + private string lastOpenedFile; #region ctor() @@ -244,7 +245,8 @@ namespace ChanSort.Ui var filter = GetTvDataFileFilter(out var supportedExtensions, out var numberOfFilters); using var dlg = new OpenFileDialog(); - dlg.InitialDirectory = this.mruFiles.Count > 0 ? Path.GetDirectoryName(this.mruFiles[0]) : Environment.GetFolderPath(Environment.SpecialFolder.MyComputer); + var lastFile = this.lastOpenedFile ?? (this.mruFiles.Count > 0 ? this.mruFiles[0] : null); + dlg.InitialDirectory = lastFile != null ? Path.GetDirectoryName(this.lastOpenedFile) : Environment.GetFolderPath(Environment.SpecialFolder.MyComputer); dlg.AddExtension = true; dlg.Filter = filter + string.Format(Resources.MainForm_FileDialog_OpenFileFilter, supportedExtensions); dlg.FilterIndex = numberOfFilters + 1; @@ -321,6 +323,7 @@ namespace ChanSort.Ui private void LoadFiles(ISerializerPlugin plugin, string tvDataFile) { var dataUpdated = false; + this.lastOpenedFile = tvDataFile; try { if (DetectCommonFileCorruptions(tvDataFile)) @@ -1761,6 +1764,7 @@ namespace ChanSort.Ui this.miReload.Enabled = fileLoaded; this.miFileInformation.Enabled = fileLoaded; this.miRestoreOriginal.Enabled = fileLoaded && this.GetPathOfMissingBackupFile() == null; + this.miDeleteBackup.Enabled = fileLoaded; this.miSave.Enabled = fileLoaded; this.miSaveAs.Enabled = fileLoaded && this.currentTvSerializer.Features.CanSaveAs; this.miOpenReferenceFile.Enabled = fileLoaded; @@ -1884,6 +1888,32 @@ namespace ChanSort.Ui } #endregion + #region DeleteBackupFile() + private void DeleteBackupFile() + { + if (this.currentTvSerializer == null) + return; + var files = this.currentTvSerializer.GetDataFilePaths(); + string lastError = null; + foreach (var file in files) + { + try + { + var bak = file + ".bak"; + if (File.Exists(bak)) + File.Delete(bak); + } + catch (Exception ex) + { + lastError = ex.Message; + } + } + + if (lastError != null) + XtraMessageBox.Show(this, lastError); + } + #endregion + #region ShowFileInformation() private void ShowFileInformation() @@ -3159,6 +3189,11 @@ namespace ChanSort.Ui TryExecute(this.RestoreBackupFile); } + private void miDeleteBackup_ItemClick(object sender, ItemClickEventArgs e) + { + TryExecute(this.DeleteBackupFile); + } + private void miFileInformation_ItemClick(object sender, ItemClickEventArgs e) { TryExecute(this.ShowFileInformation); diff --git a/source/ChanSort/MainForm.resx b/source/ChanSort/MainForm.resx index c0c89e2..83e2605 100644 --- a/source/ChanSort/MainForm.resx +++ b/source/ChanSort/MainForm.resx @@ -276,7 +276,7 @@ gridLeft - ChanSort.XGridControl, ChanSort, Version=1.0.8308.20323, Culture=neutral, PublicKeyToken=null + ChanSort.XGridControl, ChanSort, Version=1.0.8313.22695, Culture=neutral, PublicKeyToken=null grpOutputList @@ -410,6 +410,9 @@ 31 + + Delete backup files + File &information... @@ -1237,7 +1240,7 @@ gviewLeft - ChanSort.XGridView, ChanSort, Version=1.0.8308.20323, Culture=neutral, PublicKeyToken=null + ChanSort.XGridView, ChanSort, Version=1.0.8313.22695, Culture=neutral, PublicKeyToken=null colIndex1 @@ -1321,13 +1324,13 @@ globalImageCollection1 - ChanSort.Ui.GlobalImageCollection, ChanSort, Version=1.0.8308.20323, Culture=neutral, PublicKeyToken=null + ChanSort.Ui.GlobalImageCollection, ChanSort, Version=1.0.8313.22695, Culture=neutral, PublicKeyToken=null gviewRight - ChanSort.XGridView, ChanSort, Version=1.0.8308.20323, Culture=neutral, PublicKeyToken=null + ChanSort.XGridView, ChanSort, Version=1.0.8313.22695, Culture=neutral, PublicKeyToken=null colIndex @@ -2091,12 +2094,24 @@ System.Windows.Forms.Timer, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + miDeleteBackup + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v22.1, Version=22.1.5.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + MainForm DevExpress.XtraEditors.XtraForm, DevExpress.Utils.v22.1, Version=22.1.5.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + 10/05/2022 12:50:36 + + + 16, 16 + 444, 5 @@ -2982,7 +2997,7 @@ gridRight - ChanSort.XGridControl, ChanSort, Version=1.0.8308.20323, Culture=neutral, PublicKeyToken=null + ChanSort.XGridControl, ChanSort, Version=1.0.8313.22695, Culture=neutral, PublicKeyToken=null grpInputList diff --git a/source/Information/FileStructures_for_HHD_Hex_Editor_Neo/panasonic_idtvChannelBin.h b/source/Information/FileStructures_for_HHD_Hex_Editor_Neo/panasonic_idtvChannelBin.h new file mode 100644 index 0000000..a8be903 --- /dev/null +++ b/source/Information/FileStructures_for_HHD_Hex_Editor_Neo/panasonic_idtvChannelBin.h @@ -0,0 +1,51 @@ +#include "chansort.h" + +/*********************************************************** + * Panasonic LS/LX 2022 idtvChannel.bin + ***********************************************************/ + +enum Flags : word +{ + Encrypted = 0x0002, + IsFavorite = 0x0080, + Deleted = 0x0100, + Hidden = 0x0400, + CustomProgNr = 0x1000 +}; + +struct Pa_idtvChannel_bin_FileEntry +{ + word U0; // always 1 + word RecordLength; // 60 + length of channel name + word U4; // always 6 + byte U6[3]; // all 00 + word U9; // 0 = Sat, 18 = Cable ? + byte U11[5]; // all 00 + dword Freq; // Hz for DVB-C/T, kHz for DVB-S + dword SymRate; // in Sym/s, like 22000000 + word U24; // always 100 + word U26; // always 0 + word U28; // always 0 + word ProgNr; + word LcnMaybe; + byte U32[2]; // e.g. 0a 01 00 00 + Flags Flags; + byte U38[4]; // 12 07 01 02 + word Tsid; + word Onid; + word Sid; + byte U48[4]; + dword ProviderFlag2; + byte U56[8]; + byte ChannelName[RecordLength - 60]; +}; + +public struct Pa_idtvChannel_bin +{ + word u0; + word u2; + word numRecords; + word u6; + byte md5[16]; + Pa_idtvChannel_bin_FileEntry fileEntries[numRecords]; +};