- support for LG LB55/LB556 binary TLL format

- support for LG LB58 binary TLL format
- support for LG GlobalClone XML format with UTF8-enveloped binary DVB channel names (look like chinese), plain text channel names and hex-encoded DVB channel names
This commit is contained in:
hbeham
2014-05-29 19:36:29 +02:00
parent 21ace2a380
commit 7c1cdbdba3
14 changed files with 878 additions and 124 deletions

View File

@@ -103,6 +103,7 @@ namespace ChanSort.Api
}
#endregion
#region HexDecode()
public static byte[] HexDecode(string input)
{
var bytes = new byte[input.Length/2];
@@ -110,11 +111,12 @@ namespace ChanSort.Api
{
char ch = Char.ToUpper(input[i*2]);
var high = Char.IsDigit(ch) ? ch - '0' : ch - 'A' + 10;
ch = input[i*2 + 1];
ch = Char.ToUpper(input[i*2 + 1]);
var low = Char.IsDigit(ch) ? ch - '0' : ch - 'A' + 10;
bytes[i] = (byte)((high << 4) | low);
}
return bytes;
}
#endregion
}
}

View File

@@ -70,6 +70,16 @@
<Compile Include="GcSerializer.cs" />
<Compile Include="GcSerializerPlugin.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Resources.de.Designer.cs">
<DependentUpon>Resources.de.resx</DependentUpon>
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ChanSort.Api\ChanSort.Api.csproj">
@@ -80,6 +90,18 @@
<ItemGroup>
<Content Include="readme.txt" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources.de.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.de.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -1,5 +1,7 @@
using System.IO;
using System;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using ChanSort.Api;
@@ -13,7 +15,7 @@ namespace ChanSort.Loader.GlobalClone
private readonly ChannelList satTvChannels = new ChannelList(SignalSource.DvbS | SignalSource.Tv, "Sat-TV");
private readonly ChannelList satRadioChannels = new ChannelList(SignalSource.DvbS | SignalSource.Radio, "Sat-Radio");
private XmlDocument doc;
private DvbStringDecoder dvbStringDecoder = new DvbStringDecoder(Encoding.Default);
private readonly DvbStringDecoder dvbStringDecoder = new DvbStringDecoder(Encoding.Default);
#region ctor()
public GcSerializer(string inputFile) : base(inputFile)
@@ -34,13 +36,15 @@ namespace ChanSort.Loader.GlobalClone
#region Load()
public override void Load()
{
bool fail = false;
try
{
this.doc = new XmlDocument();
doc.Load(this.FileName);
using (var reader = new StreamReader(new FileStream(this.FileName, FileMode.Open), Encoding.UTF8))
doc.Load(reader);
}
catch
{
@@ -57,6 +61,9 @@ namespace ChanSort.Loader.GlobalClone
{
switch (child.LocalName)
{
case "ModelInfo":
this.ReadModelInfo(child);
break;
case "CHANNEL":
this.ReadChannelLists(child);
break;
@@ -65,6 +72,30 @@ namespace ChanSort.Loader.GlobalClone
}
#endregion
#region ReadModelInfo()
private void ReadModelInfo(XmlNode modelInfoNode)
{
var regex = new System.Text.RegularExpressions.Regex(@"\d{2}([A-Z]{2})(\d{2})\d[0-9A-Z].*");
foreach (XmlNode child in modelInfoNode.ChildNodes)
{
switch (child.LocalName)
{
case "ModelName":
var match = regex.Match(child.InnerText);
if (match.Success)
{
if (match.Groups[1].Value == "LB" && StringComparer.InvariantCulture.Compare(match.Groups[2].Value, "60") >= 0)
return;
}
break;
}
}
var txt = Resources.GcSerializer_ReadModelInfo_ModelWarning;
MessageBox.Show(txt, "LG GlobalClone editor", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
#endregion
#region ReadChannelLists()
private void ReadChannelLists(XmlNode channelNode)
{
@@ -93,8 +124,7 @@ namespace ChanSort.Loader.GlobalClone
continue;
++i;
GcChannel ch = new GcChannel(analog ? SignalSource.AnalogCT | SignalSource.Tv : SignalSource.Digital, i, itemNode);
foreach (XmlNode info in itemNode.ChildNodes)
ParseChannelInfoNode(info, ch);
this.ParseChannelInfoNodes(itemNode, ch);
var list = this.DataRoot.GetChannelList(ch.SignalSource);
this.DataRoot.AddChannel(list, ch);
@@ -103,82 +133,139 @@ namespace ChanSort.Loader.GlobalClone
#endregion
#region ParseChannelInfoNode()
private void ParseChannelInfoNode(XmlNode info, ChannelInfo ch)
private void ParseChannelInfoNodes(XmlNode itemNode, ChannelInfo ch, bool onlyNames = false)
{
switch (info.LocalName)
bool hasHexName = false;
int mapType = 0;
foreach (XmlNode info in itemNode.ChildNodes)
{
// common to ATV and DTV
case "prNum":
ch.OldProgramNr = int.Parse(info.InnerText) & 0x3FFF;
break;
case "vchName":
var name = ParseName(info.InnerText);
if (string.IsNullOrWhiteSpace(ch.Name) || !string.IsNullOrWhiteSpace(name)) // avoid overwriting valid name from <hexVchName> with empty <vchName>
ch.Name = name;
break;
case "sourceIndex":
var source = int.Parse(info.InnerText);
if (source == 2)
ch.SignalSource |= SignalSource.Cable;
else if (source == 7)
ch.SignalSource |= SignalSource.Sat;
else
ch.SignalSource |= SignalSource.Antenna;
break;
case "isBlocked":
ch.Lock = int.Parse(info.InnerText) == 1;
break;
case "isSkipped":
ch.Skip = int.Parse(info.InnerText) == 1;
break;
if (onlyNames && info.LocalName != "vchName" && info.LocalName != "hexVchName")
continue;
switch (info.LocalName)
{
// common to ATV and DTV
case "prNum":
ch.OldProgramNr = int.Parse(info.InnerText) & 0x3FFF;
break;
case "vchName":
// In old file format versions, this field contains binary data stuffed into UTF8 envelopes. that data is correct
// In newer file formats, this field contains plain text but fails to hold localized characters. The hexVchName field, if present, contains the correct data then.
if (!hasHexName)
ch.Name = ParseName(info.InnerText);
break;
case "sourceIndex":
var source = int.Parse(info.InnerText);
if (source == 2)
ch.SignalSource |= SignalSource.Cable;
else if (source == 7)
ch.SignalSource |= SignalSource.Sat;
else
ch.SignalSource |= SignalSource.Antenna;
break;
case "mapType":
mapType = int.Parse(info.InnerText);
break;
case "mapAttr":
if (mapType == 1)
ch.Favorites = (Favorites) int.Parse(info.InnerText);
break;
case "isBlocked":
ch.Lock = int.Parse(info.InnerText) == 1;
break;
case "isSkipped":
ch.Skip = int.Parse(info.InnerText) == 1;
break;
// ATV
case "pllData":
ch.FreqInMhz = (decimal)int.Parse(info.InnerText) / 20;
break;
// ATV
case "pllData":
ch.FreqInMhz = (decimal) int.Parse(info.InnerText)/20;
break;
// DTV
case "original_network_id":
ch.OriginalNetworkId = int.Parse(info.InnerText);
break;
case "transport_id":
ch.TransportStreamId = int.Parse(info.InnerText);
break;
case "service_id":
ch.ServiceId = int.Parse(info.InnerText);
break;
case "serviceType":
ch.ServiceType = int.Parse(info.InnerText);
ch.SignalSource |= LookupData.Instance.IsRadioOrTv(ch.ServiceType);
break;
case "frequency":
ch.FreqInMhz = int.Parse(info.InnerText);
if ((ch.SignalSource & SignalSource.Sat) == 0)
ch.FreqInMhz /= 1000;
break;
case "isInvisable": // that spelling error is part of the XML
ch.Hidden = int.Parse(info.InnerText) == 1;
break;
case "isDisabled":
ch.IsDeleted = int.Parse(info.InnerText) != 0;
break;
// DTV
case "original_network_id":
ch.OriginalNetworkId = int.Parse(info.InnerText);
break;
case "transport_id":
ch.TransportStreamId = int.Parse(info.InnerText);
break;
case "service_id":
ch.ServiceId = int.Parse(info.InnerText);
break;
case "serviceType":
ch.ServiceType = int.Parse(info.InnerText);
ch.SignalSource |= LookupData.Instance.IsRadioOrTv(ch.ServiceType);
break;
case "frequency":
ch.FreqInMhz = int.Parse(info.InnerText);
if ((ch.SignalSource & SignalSource.Sat) == 0)
ch.FreqInMhz /= 1000;
break;
case "isInvisable": // that spelling error is part of the XML
ch.Hidden = int.Parse(info.InnerText) == 1;
break;
case "isDisabled":
ch.IsDeleted = int.Parse(info.InnerText) != 0;
break;
// not present in all XML files
case "hexVchName":
var bytes = Tools.HexDecode(info.InnerText);
string longName, shortName;
dvbStringDecoder.GetChannelNames(bytes, 0, bytes.Length, out longName, out shortName);
ch.Name = longName;
ch.ShortName = shortName;
break;
// not present in all XML files. if present, the <vchName> might be empty or corrupted
case "hexVchName":
var bytes = Tools.HexDecode(info.InnerText);
string longName, shortName;
dvbStringDecoder.GetChannelNames(bytes, 0, bytes.Length, out longName, out shortName);
ch.Name = longName;
ch.ShortName = shortName;
hasHexName = true;
break;
}
}
}
#endregion
#region ParseName()
private string ParseName(string input)
{
return input;
var bytes = Encoding.UTF8.GetBytes(input);
if (bytes.Length == 0 || bytes[0] < 0xC0)
return input;
// older GlobalClone files look like as if the <vchName> is Chinese, but it's a weired "binary inside UTF8 envelope" encoding:
// A 3 byte UTF-8 envelope is used to encode 2 input bytes: 1110aaaa 10bbbbcc 10ccdddd represents the 16bit little endian integer aaaabbbbccccdddd, which represents bytes ccccdddd, aaaabbbb
// If a remaining byte is >= 0x80, it is encoded in a 2 byte UTF-8 envelope: 110000aa 10aabbbb represents the byte aaaabbbb
// If a remaining byte is < 0x80, it is encoded directly into a 1 byte UTF-8 char
using (MemoryStream ms = new MemoryStream(40))
{
for (int i = 0, c = bytes.Length; i < c; i++)
{
int b0 = bytes[i + 0];
if (b0 >= 0xE0) // 3-byte UTF envelope for 2 input bytes
{
int b1 = bytes[i + 1];
int b2 = bytes[i + 2];
int ch1 = ((b1 & 0x03) << 6) | (b2 & 0x3F);
int ch2 = ((b0 & 0x0F) << 4) | ((b1 & 0x3C) >> 2);
ms.WriteByte((byte) ch1);
ms.WriteByte((byte) ch2);
i += 2;
}
else if (b0 >= 0xC0) // 2-byte UTF envelope for 1 input byte >= 0x80
{
int b1 = bytes[i + 1];
int ch = ((b0 & 0x03) << 6) | (b1 & 0x3F);
ms.WriteByte((byte)ch);
i++;
}
else if (b0 < 0x80) // 1-byte UTF envelope for 1 input byte < 0x80
ms.WriteByte(bytes[i]);
}
string longName, shortName;
this.dvbStringDecoder.GetChannelNames(ms.GetBuffer(), 0, (int)ms.Length, out longName, out shortName);
return longName;
}
}
#endregion
#region Save()
public override void Save(string tvOutputFile)
@@ -215,5 +302,35 @@ namespace ChanSort.Loader.GlobalClone
}
#endregion
#region DefaultEncoding
public override Encoding DefaultEncoding
{
get { return base.DefaultEncoding; }
set
{
if (ReferenceEquals(value, this.DefaultEncoding))
return;
base.DefaultEncoding = value;
this.dvbStringDecoder.DefaultEncoding = value;
this.ChangeEncoding();
}
}
#endregion
#region ChangeEncoding()
private void ChangeEncoding()
{
foreach (var list in this.DataRoot.ChannelLists)
{
foreach (var channel in list.Channels)
{
var gcChannel = channel as GcChannel;
if (gcChannel != null)
this.ParseChannelInfoNodes(gcChannel.XmlNode, channel, true);
}
}
}
#endregion
}
}

View File

@@ -5,7 +5,7 @@ namespace ChanSort.Loader.GlobalClone
public class GcSerializerPlugin : ISerializerPlugin
{
public string PluginName { get { return "LG GlobalClone"; } }
public string FileFilter { get { return "GlobalClone*.tll"; } }
public string FileFilter { get { return "*Clone*.tll"; } }
public SerializerBase CreateSerializer(string inputFile)
{

View File

@@ -0,0 +1,79 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.34014
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ChanSort.Loader.GlobalClone {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ChanSort.Loader.GlobalClone.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Before you waste your time...
///
///...make sure that your LG TV can load this file (without modifications).
///Some LG TVs export 2 files, a GlobalClone00001.TLL and file like xxLB550U-ZA00001.TLL.
///
///If you have both file types, it&apos;s likely that the TV can only load the xxLB550U-ZA00001.TLL and you should edit that file instead.
///
///If your TV only exports a single &quot;Clone&quot; TLL, you&apos;re good to continue!.
/// </summary>
internal static string GcSerializer_ReadModelInfo_ModelWarning {
get {
return ResourceManager.GetString("GcSerializer_ReadModelInfo_ModelWarning", resourceCulture);
}
}
}
}

View File

View File

@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="GcSerializer_ReadModelInfo_ModelWarning" xml:space="preserve">
<value>Bevor Sie Ihre Zeit verschwenden...
...überprüfen Sie, ob Ihr LG Gerät diese Datei (unmodifiziert) einlesen kann.
Einige LG Geräte exportieren 2 Dateien: eine "Clone" TLL und eine Datei ähnlich wie xxLB550U-ZA00001.TLL.
Wenn Ihr Gerät 2 Dateien erzeugt, kann es vermutlich nur die xxLB550U-ZA00001.TLL einlesen und Sie sollten deshalb jene Datei bearbeiten.
Wenn Ihr Gerät nur diese "Clone" Datei erstellt, können Sie mit der Bearbeitung fortfahren.</value>
</data>
</root>

View File

@@ -0,0 +1,111 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="GcSerializer_ReadModelInfo_ModelWarning" xml:space="preserve">
<value>Before you waste your time...
...make sure that your LG TV can load this file (without modifications).
Some LG TVs export 2 files, a GlobalClone00001.TLL and file like xxLB550U-ZA00001.TLL.
If you have both file types, it's likely that the TV can only load the xxLB550U-ZA00001.TLL and you should edit that file instead.
If your TV only exports a single "Clone" TLL, you're good to continue!</value>
</data>
</root>

View File

@@ -1,15 +1,13 @@
This module allows loading of LG's GlobalClone*.TLL files.
There seem to be different versions of this XML file format around.
There seem to be different versions of this XML file format, depending on Series, Model and/or firmware version.
2014 LB-Series (e.g. Model LB731V, LB630V):
- vchName is a readable text, but sometimes left empty
- <hexVchName> contains hex-encoded channel name (not empty even when vchName is empty)
- <notConvertedLengthOfVchName>
2013 LA-Series, 2014 LB55xx and LB56xx:
<vchName> is binary data inside an UTF8 envelope. Once decoded, this data is correct.
Some higher numbered models seem to exclusively support the GlobalClone and no longer have a binary TLL file,
while lower numbered models export both files and can only load the binary file.
<hexVchName> is not included in these models
2014 LB-Series (e.g. 42LB630V-ZA)
- vchName is a readable text
- no extra hex encoded version
2014 LB6xxx and higher:
<vchName> is a readable text, but sometimes left empty and misses all local characters
<hexVchName> may be present, depending on firmware. It contains a hex-encoded DVB encoded channel name with correct data.
2014 LB561V, LB580V
- vchName binary data (with high bit set)
- separate binary TLL file available

View File

@@ -1,6 +1,39 @@
; FileConfigurationX: overall file and DVB-S data layout
; ACTChannelDataMappingX: analog, DVB-C and DVB-T channel data mapping for data length X
[ACTChannelDataMapping:244]
; LB550U, LB561V
reorderChannelData = 0
lenName = 40
offSignalSource = 8
offChannelTransponder = 10, 136, 173, 180
offProgramNr = 12, 176
offProgramNrPreset = 14, 178
offFavorites = 20
offPcrPid = 24, 228
offAudioPid = 26
offVideoPid = 36
offName = 44, 188
offNameLength = 84, 187
offServiceId = 86, 184
offFrequencyLong = 140
offOriginalNetworkId = 150
offTransportStreamId = 152
offFavorites2 = 182
offDeleted = 182
maskDeleted = 0x42
offLock = 183
maskLock = 0x01
offSkip = 183
maskSkip = 0x02
offHide = 183
maskHide = 0x04
offProgNrCustomized = 183
maskProgNrCustomized = 0x40
offServiceType = 186
offAudioPid2 = 230
[ACTChannelDataMapping:260]
; LA 2013 series firmware 04.20.29 and later
reorderChannelData = 0
@@ -407,6 +440,18 @@
lnbCount = 40
lnbLength = 48
[DvbsBlock:639532]
; LB550U, LB561V
satCount = 64
satLength = 44
transponderCount = 2400
transponderLength = 48
linkedListExtraDataLength = 2
dvbsChannelCount = 6000
dvbsChannelLength = 76
lnbCount = 40
lnbLength = 48
[DvbsBlock:687880]
; everything before LM series + LM340S, LM611S, LS560S
satCount = 64
@@ -453,7 +498,7 @@
lnbLength = 52
[DvbsBlock:967496]
; LB series
; LB580V
satCount = 64
satLength = 48
transponderCount = 2400
@@ -499,8 +544,20 @@
offSymbolRate = 29
offSatIndex = 40
[TransponderDataMapping:48]
; LB550U, LB561V
offFirstChannelIndex = 0
offLastChannelIndex = 2
offChannelCount = 4
offTransponderIndex = 12
offFrequency = 16
offOriginalNetworkId = 26
offTransportStreamId = 28
offSymbolRate = 33
offSatIndex = 44
[TransponderDataMapping:56]
; LA
; LA, LB580V
offFirstChannelIndex = 0
offLastChannelIndex = 2
offChannelCount = 4
@@ -574,7 +631,7 @@
[SatChannelDataMapping:76]
; LN series, LA6136
; LN series, LA6136, LB550U, LB561V
lenName = 40
offSatelliteNr = 0
offSourceType = 4
@@ -659,7 +716,7 @@
offAudioPid = 74
[SatChannelDataMapping:100]
; LB series
; LB580V
lenName = 40
offSatelliteNr = 0
offSourceType = 4
@@ -761,6 +818,10 @@
offHotelModeEnabled=13873
offHotelModeDtvUpdate=13883
[FirmwareData:17808]
; LB550U, LB561V
offSize = 0
[FirmwareData:23072]
; LE3300, LD420, LD450, LD550
offSize = 0
@@ -823,3 +884,7 @@
offHotelModeEnabled=38255
offHotelModeDtvUpdate=38266
offHotelMenuAccessCode = 38282
[FirmwareData:39680]
; LB580V
offSize = 0

View File

@@ -25,7 +25,7 @@ namespace ChanSort.Ui
{
public partial class MainForm : XtraForm
{
public const string AppVersion = "v2014-05-26 (beta)";
public const string AppVersion = "v2014-05-29";
private const int MaxMruEntries = 10;

View File

@@ -20,7 +20,7 @@ typedef TLL52_Lnb TLL_Lnb;
#include "tll-satellite.h"
struct LB260_AnalogChannel
struct LB244_AnalogChannel
{
byte t1[8];
TLL_SignalSource SignalSource;
@@ -35,19 +35,23 @@ struct LB260_AnalogChannel
word APID1;
byte ChannelNumberInBand;
byte ChannelBand;
byte t3[10];
byte t3[18];
char CH_Name1[40];
byte CH_NameLength1;
byte t4;
word SID1;
byte t5a[42];
byte t5a[45];
byte na_NitVersion;
word t5b;
word ChannelTransponder2;
word t5c;
dword FrequencyDiv50;
byte t6[6];
word ONID;
word TSID;
byte t7[32];
byte t7[19];
word ChannelTransponder3;
byte t7b;
word ProgramNr2;
word LogicalProgramNr2;
word ChannelTransponder4;
@@ -57,22 +61,22 @@ struct LB260_AnalogChannel
byte ServiceType;
byte CH_NameLength2;
char CH_Name2[40];
byte t10[12];
byte t10[0];
word Frequency2Div50;
word APID2;
word u1;
word u2;
byte t11[12];
byte t11[8];
};
struct LB260_AnalogBlock
struct LB244_AnalogBlock
{
dword BlockSize;
dword ChannelCount;
LB260_AnalogChannel Channels[ChannelCount];
LB244_AnalogChannel Channels[ChannelCount];
};
struct LB260_HotelSettings
struct LB244_HotelSettings
{
byte HotelModeActive;
byte PowerOnStatus;
@@ -102,15 +106,15 @@ struct LB260_HotelSettings
byte AccessCode[4];
};
struct LB260_FirmwareBlock
struct LB244_FirmwareBlock
{
dword BlockSize;
byte u[38251];
LB260_HotelSettings HotelSettings;
byte Data[BlockSize - 38251 - sizeof(LB260_HotelSettings)];
byte u[17808];
// LB244_HotelSettings HotelSettings;
// byte Data[BlockSize - 38251 - sizeof(LB244_HotelSettings)];
};
struct LB260_DvbCtChannel
struct LB244_DvbCtChannel
{
byte t1[8];
TLL_SignalSource SignalSource;
@@ -125,22 +129,25 @@ struct LB260_DvbCtChannel
word APID1;
byte t2c[8];
word VPID1;
byte t3[2];
byte t3[6];
char CH_Name1[40];
byte CH_NameLength1;
byte t4;
word SID1;
byte t5a[41];
byte t5a[45];
byte NitVersion;
word t5b;
word ChannelTransponder2;
word t5c;
dword Frequency;
byte t6[6];
word ONID;
word TSID;
word NID;
dword SpecialData;
byte t7[26];
byte t7[13];
word ChannelTransponder3;
byte t7b;
word ProgramNr2;
word LogicalProgramNr2;
word ChannelTransponder4;
@@ -150,19 +157,19 @@ struct LB260_DvbCtChannel
byte ServiceType;
byte CH_NameLength2;
char CH_Name2[40];
byte t10[12];
byte t10[0];
word PcrPid2;
word APID2;
word u1;
word u2;
byte t11[12];
byte t11[8];
};
struct LB260_DvbCTBlock
struct LB244_DvbCTBlock
{
dword BlockSize;
dword ChannelCount;
LB260_DvbCtChannel Channels[ChannelCount];
LB244_DvbCtChannel Channels[ChannelCount];
};
struct TLL48_Satellite // ok
@@ -236,13 +243,13 @@ struct TLL52_Lnb
};
public struct LB260
public struct LB244
{
byte Header[4];
LB260_AnalogBlock Analog;
LB260_FirmwareBlock Firmware;
LB260_DvbCTBlock DvbCT;
LB244_AnalogBlock Analog;
LB244_FirmwareBlock Firmware;
LB244_DvbCTBlock DvbCT;
TLL_DvbSBlock DvbS;
TLL_SettingsBlock Settings;
};

View File

@@ -0,0 +1,241 @@
#include "tll-common.h"
#define MAX_SAT_COUNT 64
struct TLL44_Satellite;
typedef TLL44_Satellite TLL_Satellite;
#define MAX_TP_COUNT 2400
struct TLL48_Transponder;
typedef TLL48_Transponder TLL_Transponder;
#define MAX_DVBS_COUNT 6000
struct TLL76_SatChannel;
typedef TLL76_SatChannel TLL_SatChannel;
#define MAX_LNB_COUNT 40
struct TLL48_Lnb;
typedef TLL48_Lnb TLL_Lnb;
#define DVBS_CHANNELLIST_PREFIXSIZE 2
#include "tll-satellite.h"
struct LB244_AnalogChannel
{
byte t1[8];
TLL_SignalSource SignalSource;
byte t1b;
word ChannelTransponder1;
word ProgramNr;
word LogicalProgramNr1;
byte t2[4];
byte Favorites1;
byte t2b[3];
word Frequency1Div50;
word APID1;
byte ChannelNumberInBand;
byte ChannelBand;
byte t3[18];
char CH_Name1[40];
byte CH_NameLength1;
byte t4;
word SID1;
byte t5a[45];
byte na_NitVersion;
word t5b;
word ChannelTransponder2;
word t5c;
dword FrequencyDiv50;
byte t6[6];
word ONID;
word TSID;
byte t7[19];
word ChannelTransponder3;
byte t7b;
word ProgramNr2;
word LogicalProgramNr2;
word ChannelTransponder4;
byte Favorites2;
TLL_EditFlags EditFlags;
word SID2;
byte ServiceType;
byte CH_NameLength2;
char CH_Name2[40];
byte t10[0];
word Frequency2Div50;
word APID2;
word u1;
word u2;
byte t11[8];
};
struct LB244_AnalogBlock
{
dword BlockSize;
dword ChannelCount;
LB244_AnalogChannel Channels[ChannelCount];
};
struct LB244_HotelSettings
{
byte HotelModeActive;
byte PowerOnStatus;
byte SetupMenuDisplay;
byte ProgramChange;
byte InputSourceChange;
byte MenuDisplay;
byte OsdDisplay;
byte LgIrOperation;
byte LocalKeyOp;
byte MaxVolume;
byte Unknown1;
byte DtvChannelUpdate;
byte PowerOnDefault;
byte InputSource;
word Programme;
byte Unknown2;
byte Volume;
byte AvSettings;
byte RadioVideoBlank;
byte unknown3;
byte StartProgNr;
byte unknown4;
byte NumberOfPrograms;
byte RadioNameDisplay;
byte unknown5[2];
byte AccessCode[4];
};
struct LB244_FirmwareBlock
{
dword BlockSize;
byte u[17808];
// LB244_HotelSettings HotelSettings;
// byte Data[BlockSize - 38251 - sizeof(LB244_HotelSettings)];
};
struct LB244_DvbCtChannel
{
byte t1[8];
TLL_SignalSource SignalSource;
byte t1b;
word ChannelTransponder1;
word ProgramNr;
word LogicalProgramNr1;
byte t2a[4];
byte Fav1;
byte t2b[3];
word PcrPid1;
word APID1;
byte t2c[8];
word VPID1;
byte t3[6];
char CH_Name1[40];
byte CH_NameLength1;
byte t4;
word SID1;
byte t5a[45];
byte NitVersion;
word t5b;
word ChannelTransponder2;
word t5c;
dword Frequency;
byte t6[6];
word ONID;
word TSID;
word NID;
dword SpecialData;
byte t7[13];
word ChannelTransponder3;
byte t7b;
word ProgramNr2;
word LogicalProgramNr2;
word ChannelTransponder4;
byte Favorites2;
TLL_EditFlags EditFlags;
word SID2;
byte ServiceType;
byte CH_NameLength2;
char CH_Name2[40];
byte t10[0];
word PcrPid2;
word APID2;
word u1;
word u2;
byte t11[8];
};
struct LB244_DvbCTBlock
{
dword BlockSize;
dword ChannelCount;
LB244_DvbCtChannel Channels[ChannelCount];
};
struct TLL48_Transponder
{
word FirstChannelIndex;
word LastChannelIndex;
word ChannelCount;
byte t1[6];
word TP_Number;
byte t1b[2];
word TP_Freq;
byte t2[8];
word NID;
word TID;
byte t3[3];
word SRateTimes2;
byte t4[9];
byte SatIndexTimes2;
byte t5[3];
byte u40[0];
};
struct TLL76_SatChannel
{
word LnbConfigIndex;
word u2;
byte SourceType;
word TP_Number;
byte u3;
word CH_Number;
word CH_NumberFixed;
word TP_Number2;
byte FavCrypt;
byte LockSkipHide;
word SID;
byte ServiceType;
byte CH_NameLength;
char CH_Name[40];
word VPID;
word APID;
word APID2;
word XPID;
byte t6[8];
};
struct TLL48_Lnb
{
byte SettingsID;
byte t2[3];
byte SatelliteID;
byte t3[3];
char FrequenceName[12];
word LOF1;
byte t4[2];
word LOF2;
byte t5[22];
};
public struct LB550U
{
byte Header[4];
LB244_AnalogBlock Analog;
LB244_FirmwareBlock Firmware;
LB244_DvbCTBlock DvbCT;
TLL_DvbSBlock DvbS;
TLL_SettingsBlock Settings;
};

View File

@@ -1,10 +1,10 @@
Version v2014-05-26 (beta) ================================================
Version v2014-05-29 =======================================================
Changes:
- supports LG's 2014 LB5xx models' xxLB5*.TLL satellite channel lists
(works for satellite channels. DVB-C/T are not implemented due to lack of
test files)
- supports LG's 2014 LB6xx and higher models' GlobalClone.TLL channel lists
- supports LG LB55xx and LB56xx xxLB*.TLL channel lists
- supports LG LB58xx*.TLL channel lists
(satellite channels ONLY due to lack of DVB-C/T test files)
- supports LG *Clone*.TLL channel lists (e.g. LA8xxx, LB6xxx, LB7xxx models)
(deleting channels is not yet implemented)
The complete change log can be found at the end of this document
@@ -54,8 +54,8 @@ Samsung
LG
------
Series: CS, DM, LA, LD, LE, LH, LK, LM*, LN, LP**, LS, LT, LV, LW, LX,
PM, PN, PT
Series: CS, DM, LA, LB, LD, LE, LH, LK, LM*, LN, LP**, LS, LT, LV, LW,
LX, PM, PN, PT
Lists: Analog TV, DTV (DVB-C, DVB-T), Radio (DVB-C/T),
Sat-DTV (DVB-S2), Sat-Radio (DVB-S2)
@@ -119,11 +119,11 @@ OTHER DEALINGS IN THE SOFTWARE.
Change log ================================================================
2014-05-26 (beta)
- supports LG's 2014 LB5xx models' xxLB5*.TLL satellite channel lists
(works for satellite channels. DVB-C/T are not implemented due to lack of
test files)
- supports LG's 2014 LB6xx and higher models' GlobalClone.TLL channel lists
2014-05-29
- supports LG LB55xx and LB56xx xxLB*.TLL channel lists
- supports LG LB58xx*.TLL channel lists
(satellite channels ONLY due to lack of DVB-C/T test files)
- supports LG *Clone*.TLL channel lists (e.g. LA8xxx, LB6xxx, LB7xxx models)
(deleting channels is not yet implemented)
2014-05-06