mirror of
https://github.com/PredatH0r/ChanSort.git
synced 2026-02-19 04:46:45 +01:00
- 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
This commit is contained in:
@@ -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<int, ChannelInfo> channelDict = new(); // maps record-index of .bin file to Channel object created from .db file
|
||||
private byte[] binFileData;
|
||||
private List<int> 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<IdtvChannel>();
|
||||
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<int>(binFileRecordOffsets.Count);
|
||||
for (int i = 0, c=this.binFileRecordOffsets.Count; i<c; i++)
|
||||
newToOld.Add(i);
|
||||
|
||||
var offFreq = (int)Marshal.OffsetOf<IdtvChannel>(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<int> 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<IdtvChannel>(nameof(IdtvChannel.ProgNr));
|
||||
var offFlags = (int)Marshal.OffsetOf<IdtvChannel>(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<int> newToOld)
|
||||
private void ReorderBinFileRecords(IList<int> 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<int>(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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
23
source/ChanSort/MainForm.Designer.cs
generated
23
source/ChanSort/MainForm.Designer.cs
generated
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -276,7 +276,7 @@
|
||||
<value>gridLeft</value>
|
||||
</data>
|
||||
<data name=">>gridLeft.Type" xml:space="preserve">
|
||||
<value>ChanSort.XGridControl, ChanSort, Version=1.0.8308.20323, Culture=neutral, PublicKeyToken=null</value>
|
||||
<value>ChanSort.XGridControl, ChanSort, Version=1.0.8313.22695, Culture=neutral, PublicKeyToken=null</value>
|
||||
</data>
|
||||
<data name=">>gridLeft.Parent" xml:space="preserve">
|
||||
<value>grpOutputList</value>
|
||||
@@ -410,6 +410,9 @@
|
||||
<data name="miRestoreOriginal.ImageOptions.ImageIndex" type="System.Int32, mscorlib">
|
||||
<value>31</value>
|
||||
</data>
|
||||
<data name="miDeleteBackup.Caption" xml:space="preserve">
|
||||
<value>Delete backup files</value>
|
||||
</data>
|
||||
<data name="miFileInformation.Caption" xml:space="preserve">
|
||||
<value>File &information...</value>
|
||||
</data>
|
||||
@@ -1237,7 +1240,7 @@
|
||||
<value>gviewLeft</value>
|
||||
</data>
|
||||
<data name=">>gviewLeft.Type" xml:space="preserve">
|
||||
<value>ChanSort.XGridView, ChanSort, Version=1.0.8308.20323, Culture=neutral, PublicKeyToken=null</value>
|
||||
<value>ChanSort.XGridView, ChanSort, Version=1.0.8313.22695, Culture=neutral, PublicKeyToken=null</value>
|
||||
</data>
|
||||
<data name=">>colIndex1.Name" xml:space="preserve">
|
||||
<value>colIndex1</value>
|
||||
@@ -1321,13 +1324,13 @@
|
||||
<value>globalImageCollection1</value>
|
||||
</data>
|
||||
<data name=">>globalImageCollection1.Type" xml:space="preserve">
|
||||
<value>ChanSort.Ui.GlobalImageCollection, ChanSort, Version=1.0.8308.20323, Culture=neutral, PublicKeyToken=null</value>
|
||||
<value>ChanSort.Ui.GlobalImageCollection, ChanSort, Version=1.0.8313.22695, Culture=neutral, PublicKeyToken=null</value>
|
||||
</data>
|
||||
<data name=">>gviewRight.Name" xml:space="preserve">
|
||||
<value>gviewRight</value>
|
||||
</data>
|
||||
<data name=">>gviewRight.Type" xml:space="preserve">
|
||||
<value>ChanSort.XGridView, ChanSort, Version=1.0.8308.20323, Culture=neutral, PublicKeyToken=null</value>
|
||||
<value>ChanSort.XGridView, ChanSort, Version=1.0.8313.22695, Culture=neutral, PublicKeyToken=null</value>
|
||||
</data>
|
||||
<data name=">>colIndex.Name" xml:space="preserve">
|
||||
<value>colIndex</value>
|
||||
@@ -2091,12 +2094,24 @@
|
||||
<data name=">>timerSelectFocusedRow.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Timer, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>miDeleteBackup.Name" xml:space="preserve">
|
||||
<value>miDeleteBackup</value>
|
||||
</data>
|
||||
<data name=">>miDeleteBackup.Type" xml:space="preserve">
|
||||
<value>DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v22.1, Version=22.1.5.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
|
||||
</data>
|
||||
<data name=">>$this.Name" xml:space="preserve">
|
||||
<value>MainForm</value>
|
||||
</data>
|
||||
<data name=">>$this.Type" xml:space="preserve">
|
||||
<value>DevExpress.XtraEditors.XtraForm, DevExpress.Utils.v22.1, Version=22.1.5.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
|
||||
</data>
|
||||
<data name="SharedImageCollection.Timestamp" type="System.DateTime, mscorlib">
|
||||
<value>10/05/2022 12:50:36</value>
|
||||
</data>
|
||||
<data name="SharedImageCollection.ImageSize" type="System.Drawing.Size, System.Drawing">
|
||||
<value>16, 16</value>
|
||||
</data>
|
||||
<data name="btnSearchLeft.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>444, 5</value>
|
||||
</data>
|
||||
@@ -2982,7 +2997,7 @@
|
||||
<value>gridRight</value>
|
||||
</data>
|
||||
<data name=">>gridRight.Type" xml:space="preserve">
|
||||
<value>ChanSort.XGridControl, ChanSort, Version=1.0.8308.20323, Culture=neutral, PublicKeyToken=null</value>
|
||||
<value>ChanSort.XGridControl, ChanSort, Version=1.0.8313.22695, Culture=neutral, PublicKeyToken=null</value>
|
||||
</data>
|
||||
<data name=">>gridRight.Parent" xml:space="preserve">
|
||||
<value>grpInputList</value>
|
||||
|
||||
@@ -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];
|
||||
};
|
||||
Reference in New Issue
Block a user