diff --git a/source/ChanSort.Loader.Panasonic/DbChannel.cs b/source/ChanSort.Loader.Panasonic/DbChannel.cs index f1b6c9e..e9e1217 100644 --- a/source/ChanSort.Loader.Panasonic/DbChannel.cs +++ b/source/ChanSort.Loader.Panasonic/DbChannel.cs @@ -100,31 +100,35 @@ namespace ChanSort.Loader.Panasonic if (deliveryLength >= 12) { - // byte 5 and 6 contain hex-encoded decimal digits for symbol rate divided by 10. bytes 10 and 11 are the sat orbital position - // however there are some files that swap the bytes with no clear indication what format is used by the TV. - // we use a heuristic approach whether byte 0 or byte 3 is 0x01 + // Bytes 4-6 or 5-7 contain hex-encoded decimal digits for symbol rate. Bytes 10 and 11 are the sat orbital position. + // The byte-order varies between files and neither the endian-ness of the file header nor any other field gives a reliable clue which order is used. + // So I use bytes 0 and 3 as a heuristic to check for 0x01 - if (delivery[3] == 0x01) + // 01 14 92 99 00 21 99 90 02 31 01 92 00 00 00 + var bigEndianSymbolRate = (delivery[5] >> 4) * 10000 + (delivery[5] & 0x0F) * 1000 + // 21 99 90 => 21999 + (delivery[6] >> 4) * 100 + (delivery[6] & 0x0F) * 10 + (delivery[7] >> 4); + var bigEndianSatPosition = (delivery[10] >> 4) * 1000 + (delivery[10] & 0x0F) * 100 + (delivery[11] >> 4) * 10 + (delivery[11] & 0x0F); // 01 92 => 192 + + // 50 94 14 01 90 99 21 00 22 31 92 01 00 00 00 00 00 + // 04 54 10 01 10 50 27 00 04 09 30 01 00 00 00 + var littleEndianSymbolRate = (delivery[6] >> 4) * 10000 + (delivery[6] & 0x0F) * 1000 + // 21 99 90 => 21999 + (delivery[5] >> 4) * 100 + (delivery[5] & 0x0F) * 10 + (delivery[4] >> 4); + var littleEndianSatPosition = (delivery[11] >> 4) * 1000 + (delivery[11] & 0x0F) * 100 + (delivery[10] >> 4) * 10 + (delivery[10] & 0x0F); // 92 01 => 192 + + + bool useBigEndian = delivery[0] == 1 ? delivery[3] != 1 || bigEndianSymbolRate >= 4000 && bigEndianSymbolRate <= 60000 && (bigEndianSymbolRate + 5) % 100 <= 10 : false; + if (useBigEndian) { - // 50 94 14 01 90 99 21 00 22 31 92 01 00 00 00 00 00 - // 04 54 10 01 10 50 27 00 04 09 30 01 00 00 00 - - this.SymbolRate = (delivery[6] >> 4) * 10000 + (delivery[6] & 0x0F) * 1000 + - (delivery[5] >> 4) * 100 + (delivery[5] & 0x0F) * 10; - this.SatPosition = ((decimal)((delivery[11] >> 4) * 1000 + (delivery[11] & 0x0F) * 100 + // 99 21 => 21990, 50 27 => 27500 - (delivery[10] >> 4) * 10 + (delivery[10] & 0x0F)) / 10).ToString("n1"); // 92 01 => 19.2 - this.Satellite = this.SatPosition; + this.SymbolRate = bigEndianSymbolRate; + this.SatPosition = ((decimal)bigEndianSatPosition / 10).ToString("n1"); } else { - // 01 14 92 99 00 21 99 90 02 31 01 92 00 00 00 - - this.SymbolRate = (delivery[5] >> 4) * 10000 + (delivery[5] & 0x0F) * 1000 + // 21 99 => 21990 - (delivery[6] >> 4) * 100 + (delivery[6] & 0x0F) * 10; - this.SatPosition = ((decimal)((delivery[10] >> 4) * 1000 + (delivery[10] & 0x0F) * 100 + (delivery[11] >> 4) * 10 + - (delivery[11] & 0x0F)) / 10).ToString("n1"); // 01 92 => 19.2 - this.Satellite = this.SatPosition; + this.SymbolRate = littleEndianSymbolRate; + this.SatPosition = ((decimal)littleEndianSatPosition / 10).ToString("n1"); } + + this.Satellite = this.SatPosition; } else { diff --git a/source/ChanSort.Loader.Panasonic/Serializer.cs b/source/ChanSort.Loader.Panasonic/Serializer.cs index 361ca26..c983d94 100644 --- a/source/ChanSort.Loader.Panasonic/Serializer.cs +++ b/source/ChanSort.Loader.Panasonic/Serializer.cs @@ -8,6 +8,8 @@ using ChanSort.Api; namespace ChanSort.Loader.Panasonic { + internal enum ByteOrder { BigEndian, LittleEndian } + class Serializer : SerializerBase { private readonly ChannelList avbtChannels = new ChannelList(SignalSource.AnalogT, "Analog Antenna"); @@ -22,7 +24,7 @@ namespace ChanSort.Loader.Panasonic private CypherMode cypherMode; private byte[] fileHeader = Array.Empty(); private int dbSizeOffset; - private bool littleEndianByteOrder; + private ByteOrder headerByteOrder; private string charEncoding; private bool explicitUtf8; private bool implicitUtf8; @@ -168,12 +170,12 @@ namespace ChanSort.Loader.Panasonic throw new FileLoadException("Checksum validation failed"); int offset; - if (!this.ValidateFileSize(data, false, out offset) - && !this.ValidateFileSize(data, true, out offset)) + if (!this.ValidateFileSize(data, ByteOrder.BigEndian, out offset) && + !this.ValidateFileSize(data, ByteOrder.LittleEndian, out offset)) throw new FileLoadException("File size validation failed"); using (var stream = new FileStream(outputFile, FileMode.Create, FileAccess.Write)) - stream.Write(data, offset, data.Length - offset - 4); + stream.Write(data, offset, data.Length - offset - 4); this.fileHeader = new byte[offset]; Array.Copy(data, 0, this.fileHeader, 0, offset); @@ -181,13 +183,13 @@ namespace ChanSort.Loader.Panasonic #endregion #region ValidateFileSize() - private bool ValidateFileSize(byte[] data, bool littleEndian, out int offset) + private bool ValidateFileSize(byte[] data, ByteOrder byteOrder, out int offset) { - this.littleEndianByteOrder = littleEndian; - offset = 30 + Tools.GetInt16(data, 28, littleEndian); + this.headerByteOrder = byteOrder; + offset = 30 + Tools.GetInt16(data, 28, byteOrder == ByteOrder.LittleEndian); if (offset >= data.Length) return false; this.dbSizeOffset = offset; - int dbSize = Tools.GetInt32(data, offset, littleEndian); + int dbSize = Tools.GetInt32(data, offset, byteOrder == ByteOrder.LittleEndian); offset += 4; return data.Length == offset + dbSize + 4; } @@ -403,7 +405,7 @@ order by s.ntype,major_channel using (var stream = new FileStream(this.workFile, FileMode.Open, FileAccess.Read)) stream.Read(data, fileHeader.Length, (int)workFileSize); - Tools.SetInt32(data, this.dbSizeOffset, (int)workFileSize, this.littleEndianByteOrder); + Tools.SetInt32(data, this.dbSizeOffset, (int)workFileSize, this.headerByteOrder == ByteOrder.LittleEndian); this.UpdateChecksum(data); using (var stream = new FileStream(this.FileName, FileMode.Create, FileAccess.Write)) @@ -435,8 +437,7 @@ order by s.ntype,major_channel case CypherMode.Encryption: sb.AppendLine("encrypted SQLite database"); break; case CypherMode.HeaderAndChecksum: sb.AppendLine("embedded SQLite database"); - sb.Append("Byte order: ").AppendLine(this.littleEndianByteOrder ? - "little-endian (least significant byte first)" : "big-endian (most significant byte first)"); + sb.Append("Header byte order: ").AppendLine(this.headerByteOrder.ToString()); break; } sb.Append("Character encoding: ").AppendLine(this.charEncoding); diff --git a/source/ChanSort/MainForm.cs b/source/ChanSort/MainForm.cs index 108bc1c..927d87b 100644 --- a/source/ChanSort/MainForm.cs +++ b/source/ChanSort/MainForm.cs @@ -2157,8 +2157,16 @@ namespace ChanSort.Ui this.bar1.Visible = false; GlobalImageCollection.Scale(absScaleFactor.Height, false); var newSize = this.ClientSize; - if (this.adjustWindowLocationOnScale) // adjust WindowStartPosition "CenterScreen" to new window size - this.Location = new Point(this.Left - (newSize.Width - oldSize.Width) / 2, this.Top - (newSize.Height - oldSize.Height) / 2); + if (this.adjustWindowLocationOnScale) // adjust WindowStartPosition "CenterScreen" to new window size, but don't move upper left corner off-screen + { + var screen = Screen.FromPoint(new Point(this.Left + this.Width / 2, this.Top + this.Height / 2)); + this.Bounds = new Rectangle( + Math.Max(screen.Bounds.Left, this.Left - (newSize.Width - oldSize.Width) / 2), + Math.Max(screen.Bounds.Top, this.Top - (newSize.Height - oldSize.Height) / 2), + Math.Min(screen.Bounds.Width, this.Width), + Math.Min(screen.Bounds.Height, this.Height)); + } + this.bar1.Visible = true; this.ResumeRedraw(); } diff --git a/source/changelog.md b/source/changelog.md index 03180c0..ccaae56 100644 --- a/source/changelog.md +++ b/source/changelog.md @@ -1,6 +1,10 @@ ChanSort Change Log =================== +TBD +- Panasonic: improved symbol rate and satellite position detection +- startup window location and size are adjusted to fit on screen + 2021-09-23 - improved per-monitor DPI scaling (i.e. moving the window from a Full-HD to a 4K display with 100% and 200% scale) - improved "column auto width" (right clicking a column header) by forcing line breaks in the column captions