- added inactive code to read Hisense channel lists (no write support)

- added feature to allow specific channel lists to define which data columns should be visible. This can be customized by individual file format loaders.
- upgraded to DevExpress 15.1.6
This commit is contained in:
hbeham
2015-09-24 12:46:52 +02:00
parent 4d7040a22a
commit e45d897226
12 changed files with 562 additions and 23 deletions

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{D093E7EE-D3AD-4E7B-AF82-C6918CA017FB}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ChanSort.Loader.Hisense</RootNamespace>
<AssemblyName>ChanSort.Loader.Hisense</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="HisSerializer.cs" />
<Compile Include="HisSerializerPlugin.cs" />
</ItemGroup>
<ItemGroup>
<None Include="ChanSort.Loader.Hisense.ini">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ChanSort.Api\ChanSort.Api.csproj">
<Project>{dccffa08-472b-4d17-bb90-8f513fc01392}</Project>
<Name>ChanSort.Api</Name>
</ProjectReference>
</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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,78 @@
[Header]
ID=0
Name=2
NameLength=34
BlockSize=36
[TSL_Record]
RecordSize=328
ID=0
BroadcastType=2
ServiceType=3
Frequency=16
SymbolRate=28
Name=216
NameLength=96
[SVL_Record]
RecordSize=304
RecordId=0
ChannelId=6
HashcodeFieldMask=8
HashcodeFieldMask_Name=0x01
HashcodeFieldMask_ChannelId=0x02
HashcodeFieldMask_BroadcastType=0x04
HashcodeFieldMask_TslRecId=0x08
HashcodeFieldMask_PrgNum=0x10
HashcodeFieldMask_ShortName=0x20
HashcodeFieldMask_Radio = 0x0400
HashcodeFieldMask_Encrypted = 0x0800
HashcodeFieldMask_Tv = 0x2000
NwMask=12
NwMask_Skip = 0x08
NwMask_Fav1 = 0x10
NwMask_Fav2 = 0x20
NwMask_Fav3 = 0x40
NwMask_Fav4 = 0x80
NwMask_Lock = 0x80
NwMask_Hide = 0x00
OptionMask=16
MaskRename = 0x08
MaskMoved = 0x400
OptionMask2=20
ProgramId=24
TslTableId=26
TslRecordId=28
NwlTableId=30
NwlRecordId=32
SatlTableId=34
SatlRecordId=36
BroadcastType=38
ServiceType=39
Name=40
NameLength=96
BroadcastSystemData=136
[DVB_Data]
ShortName=4
ShortName_Size=16
LinkageMask=28
LinkageMask_Ts=0x04
Onid=44
Tsid=46
Ssid=48
Encrypted=64
[Columns]
DVB_T=Position,OldProgramNr,Name,ShortName,Favorites,Lock,Skip,Encrypted,ChannelOrTransponder,FreqInMhz,ServiceTypeName
DVB_C=Position,OldProgramNr,Name,ShortName,Favorites,Lock,Skip,Encrypted,ChannelOrTransponder,FreqInMhz,ServiceTypeName,SymbolRate
DVB_S=Position,OldProgramNr,Name,ShortName,Favorites,Lock,Skip,Encrypted,FreqInMhz,ServiceTypeName,SymbolRate

View File

@@ -0,0 +1,305 @@
using System;
using System.CodeDom;
using System.Collections.Generic;
using System.IO;
using System.Text;
using ChanSort.Api;
namespace ChanSort.Loader.Hisense
{
public class HisSerializer : SerializerBase
{
private readonly ChannelList dvbcChannels = new ChannelList(SignalSource.DvbC | SignalSource.Tv | SignalSource.Radio, "DVB-C");
private readonly ChannelList dvbtChannels = new ChannelList(SignalSource.DvbT | SignalSource.Tv | SignalSource.Radio, "DVB-T");
private readonly ChannelList dvbsChannels = new ChannelList(SignalSource.DvbS | SignalSource.Tv | SignalSource.Radio, "DVB-S");
private byte[] svlFileContent;
private byte[] tslFileContent;
private const int MaxFileSize = 4 << 20; // 4 MB
private int tSize, cSize, sSize;
#region DisplayName
public override string DisplayName => "Hisense HIS_SVL.BIN Loader";
#endregion
private const string ERR_fileTooBig = "The file size {0} is larger than the allowed maximum of {1}.";
private const string ERR_badFileFormat = "The content of the file doesn't match the expected format.";
private DataMapping svlMapping, tslMapping, dvbMapping;
private readonly Dictionary<int, Transponder> transponder = new Dictionary<int, Transponder>();
#region ctor()
public HisSerializer(string inputFile) : base(inputFile)
{
this.Features.ChannelNameEdit = ChannelNameEditMode.All;
this.ReadConfigurationFromIniFile();
this.DataRoot.AddChannelList(dvbcChannels);
this.DataRoot.AddChannelList(dvbtChannels);
this.DataRoot.AddChannelList(dvbsChannels);
}
#endregion
#region ReadConfigurationFromIniFile()
private void ReadConfigurationFromIniFile()
{
string iniFile = this.GetType().Assembly.Location.ToLower().Replace(".dll", ".ini");
IniFile ini = new IniFile(iniFile);
this.svlMapping = new DataMapping(ini.GetSection("SVL_Record"));
this.svlMapping.DefaultEncoding = Encoding.UTF8;
this.tslMapping = new DataMapping(ini.GetSection("TSL_Record"));
this.tslMapping.DefaultEncoding = Encoding.UTF8;
this.dvbMapping = new DataMapping(ini.GetSection("DVB_Data"));
this.dvbMapping.DefaultEncoding = Encoding.UTF8;
var sec = ini.GetSection("Columns");
var fields = sec.GetString("DVB_T");
if (fields != null)
dvbtChannels.VisibleColumnFieldNames = fields.Trim().Split(',');
fields = sec.GetString("DVB_C");
if (fields != null)
dvbcChannels.VisibleColumnFieldNames = fields.Trim().Split(',');
fields = sec.GetString("DVB_S");
if (fields != null)
dvbsChannels.VisibleColumnFieldNames = fields.Trim().Split(',');
}
#endregion
#region Load()
public override void Load()
{
this.LoadTslFile(this.FileName.Replace("SVL", "TSL"));
this.LoadSvlFile(this.FileName);
}
#endregion
#region LoadTslFile()
private void LoadTslFile(string fileName)
{
long fileSize = new FileInfo(fileName).Length;
if (fileSize > MaxFileSize)
throw new FileLoadException(string.Format(ERR_fileTooBig, fileSize, MaxFileSize));
this.tslFileContent = File.ReadAllBytes(fileName);
int off = 0;
tSize = this.ReadHeader(tslFileContent, ref off);
cSize = this.ReadHeader(tslFileContent, ref off);
sSize = this.ReadHeader(tslFileContent, ref off);
this.ReadTransponder(ref off, tSize, 1, 1000000);
this.ReadTransponder(ref off, cSize, 2, 1000000);
this.ReadTransponder(ref off, sSize, 3, 1);
}
#endregion
#region ReadTransponder()
private void ReadTransponder(ref int off, int size, int table, int freqFactor)
{
int recordSize = tslMapping.Settings.GetInt("RecordSize");
if (size % recordSize != 0)
throw new FileLoadException(ERR_badFileFormat);
int count = size / recordSize;
if (count == 0)
return;
for (int i = 0; i < count; i++)
{
tslMapping.SetDataPtr(tslFileContent, off);
var id = (table << 16) + tslMapping.GetWord("ID");
var trans = new Transponder(id);
trans.FrequencyInMhz = (decimal)tslMapping.GetDword("Frequency") / freqFactor;
trans.SymbolRate = tslMapping.GetWord("SymbolRate");
this.transponder.Add(id, trans);
off += recordSize;
}
}
#endregion
#region LoadSvlFile()
private void LoadSvlFile(string fileName)
{
long fileSize = new FileInfo(fileName).Length;
if (fileSize > MaxFileSize)
throw new FileLoadException(string.Format(ERR_fileTooBig, fileSize, MaxFileSize));
this.svlFileContent = File.ReadAllBytes(this.FileName);
int off = 0;
tSize = this.ReadHeader(svlFileContent, ref off);
cSize = this.ReadHeader(svlFileContent, ref off);
sSize = this.ReadHeader(svlFileContent, ref off);
this.ReadChannelList(ref off, tSize, 1, dvbtChannels);
this.ReadChannelList(ref off, cSize, 2, dvbcChannels);
this.ReadChannelList(ref off, sSize, 3, dvbsChannels);
}
#endregion
#region ReadHeader()
private int ReadHeader(byte[] data, ref int off)
{
if (off + 40 > data.Length)
throw new FileLoadException(ERR_badFileFormat);
var blockSize = BitConverter.ToInt32(data, off + 36);
if (off + blockSize > data.Length)
throw new FileLoadException(ERR_badFileFormat);
off += 40;
return blockSize;
}
#endregion
#region ReadChannelList()
private void ReadChannelList(ref int off, int size, int table, ChannelList channels)
{
int recordSize = svlMapping.Settings.GetInt("RecordSize");
if (size % recordSize != 0)
throw new FileLoadException(ERR_badFileFormat);
int channelCount = size/recordSize;
if (channelCount == 0)
return;
var broadcastDataOffset = svlMapping.Settings.GetInt("BroadcastSystemData");
var nameLength = svlMapping.Settings.GetInt("NameLength");
var source = channels.SignalSource & (SignalSource.MaskAnalogDigital | SignalSource.MaskAntennaCableSat);
for (int i = 0; i < channelCount; i++)
{
svlMapping.SetDataPtr(svlFileContent, off);
dvbMapping.SetDataPtr(svlFileContent, off + broadcastDataOffset);
var ci = ReadChannel(source, i, nameLength);
if (ci != null)
this.DataRoot.AddChannel(channels, ci);
off += recordSize;
}
}
#endregion
#region ReadChannel()
private ChannelInfo ReadChannel(SignalSource source, int index, int nameLength)
{
ChannelInfo ci = new ChannelInfo(source, index, 0, "");
//ci.RecordIndex = svlMapping.GetWord("RecordId");
ci.OldProgramNr = svlMapping.GetWord("ChannelId") >> 2;
var nwMask = svlMapping.GetDword("NwMask");
ci.Skip = (nwMask & svlMapping.Settings.GetInt("NwMask_Skip")) != 0;
ci.Lock = (nwMask & svlMapping.Settings.GetInt("NwMask_Lock")) != 0;
ci.Hidden = (nwMask & svlMapping.Settings.GetInt("NwMask_Hide")) != 0;
for (int i = 0; i < 3; i++)
{
bool isFav = (nwMask & svlMapping.Settings.GetInt("NwMask_Fav" + (i + 1))) != 0;
if (isFav)
ci.Favorites |= (Favorites) (1 << i);
}
var fieldMask = svlMapping.GetDword("HashcodeFieldMask");
if ((fieldMask & svlMapping.Settings.GetInt("HashcodeFieldMask_Name")) != 0)
{
ci.Name = svlMapping.GetString("Name", nameLength);
int term = ci.Name.IndexOf('\0');
if (term >= 0)
ci.Name = ci.Name.Substring(0, term);
}
var serviceType = svlMapping.GetByte("ServiceType");
if (serviceType == 1)
{
ci.SignalSource |= SignalSource.Tv;
ci.ServiceTypeName = "TV";
}
else if (serviceType == 2)
{
ci.SignalSource |= SignalSource.Radio;
ci.ServiceTypeName = "Radio";
}
else
{
ci.ServiceTypeName = "Data";
}
if ((fieldMask & svlMapping.Settings.GetInt("HashcodeFieldMask_TslRecId")) != 0)
{
int transpTableId = svlMapping.GetByte("TslTableId");
int transpRecordId = svlMapping.GetByte("TslRecordId");
var transpId = (transpTableId << 16) + transpRecordId;
var transp = this.transponder.TryGet(transpId);
if (transp != null)
{
ci.Transponder = transp;
ci.FreqInMhz = transp.FrequencyInMhz;
ci.SymbolRate = transp.SymbolRate;
}
}
if ((fieldMask & svlMapping.Settings.GetInt("HashcodeFieldMask_BroadcastType")) != 0)
{
var bcastType = svlMapping.GetByte("BroadcastType");
if (bcastType == 1)
ReadAnalogData(ci);
else if (bcastType == 2)
ReadDvbData(ci);
}
ci.Encrypted = (fieldMask & svlMapping.Settings.GetInt("HashcodeFieldMask_Encrypted")) != 0;
//ci.AddDebug("u1=");
//ci.AddDebug(svlMapping.Data, svlMapping.BaseOffset + 2, 2);
//ci.AddDebug("u2=");
//ci.AddDebug(svlMapping.Data, svlMapping.BaseOffset + 4, 2);
//ci.AddDebug(", hash=");
//ci.AddDebug(svlMapping.Data, svlMapping.BaseOffset + 8, 2);
//ci.AddDebug(", nw=");
//ci.AddDebug(svlMapping.Data, svlMapping.BaseOffset + 12, 4);
//ci.AddDebug(", o1=");
//ci.AddDebug(svlMapping.Data, svlMapping.BaseOffset + 16, 4);
ci.AddDebug(", o2=");
ci.AddDebug(svlMapping.Data, svlMapping.BaseOffset + 20, 4);
ci.AddDebug("progId=");
ci.AddDebug(svlMapping.Data, svlMapping.BaseOffset + 24, 4);
return ci;
}
#endregion
#region ReadAnalogData()
private void ReadAnalogData(ChannelInfo ci)
{
}
#endregion
#region ReadDvbData()
private void ReadDvbData(ChannelInfo ci)
{
var mask = dvbMapping.GetDword("LinkageMask");
var tsFlag = dvbMapping.Settings.GetInt("LinkageMask_Ts");
if ((mask & tsFlag) != 0)
{
ci.OriginalNetworkId = dvbMapping.GetWord("Onid");
ci.TransportStreamId = dvbMapping.GetWord("Tsid");
ci.ServiceId = dvbMapping.GetWord("Ssid");
}
//ci.Encrypted = dvbMapping.GetByte("Encrypted") != 0;
if ((ci.SignalSource & SignalSource.DvbT) == SignalSource.DvbT)
ci.ChannelOrTransponder = LookupData.Instance.GetDvbtTransponder(ci.FreqInMhz).ToString();
ci.ShortName = dvbMapping.GetString("ShortName", dvbMapping.Settings.GetInt("ShortName_Size"));
}
#endregion
// Saving ====================================
#region Save()
public override void Save(string tvOutputFile)
{
}
#endregion
}
}

View File

@@ -0,0 +1,26 @@
//#define HISENSE_ENABLED
/*
Support for the Hisense file format (Sep 2015) is currently disabled due to the risk of damaging the TV when
users import files in an older/newer format than the currently installed firmware expects.
*/
using ChanSort.Api;
namespace ChanSort.Loader.Hisense
{
#if HISENSE_ENABLED
public class HisSerializerPlugin : ISerializerPlugin
{
public string PluginName => "Hisense HIS_*.bin";
public string FileFilter => "HIS_SVL.BIN";
#region CreateSerializer()
public SerializerBase CreateSerializer(string inputFile)
{
return new HisSerializer(inputFile);
}
#endregion
}
#endif
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ChanSort.Loader.Hisense")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ChanSort.Loader.Hisense")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("d093e7ee-d3ad-4e7b-af82-c6918ca017fb")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]