- added support for Toshiba "settingsDB.db" lists

This commit is contained in:
Horst Beham
2021-01-23 09:35:00 +01:00
parent c9fb32f40b
commit 4abe7a0b35
8 changed files with 288 additions and 23 deletions

View File

@@ -25,6 +25,7 @@
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<Prefer32Bit>false</Prefer32Bit>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -34,6 +35,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
@@ -45,6 +47,7 @@
<CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
<Prefer32Bit>false</Prefer32Bit>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\Release\</OutputPath>
@@ -56,6 +59,7 @@
<CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
<Prefer32Bit>false</Prefer32Bit>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
@@ -72,9 +76,10 @@
</ItemGroup>
<ItemGroup>
<Compile Include="DbChannel.cs" />
<Compile Include="SettingsDbSerializer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="DbSerializer.cs" />
<Compile Include="DbSerializerPlugin.cs" />
<Compile Include="ChmgtDbSerializer.cs" />
<Compile Include="ToshibaPlugin.cs" />
<Service Include="{94E38DFF-614B-4cbd-B67C-F211BB35CE8B}" />
</ItemGroup>
<ItemGroup>

View File

@@ -5,7 +5,7 @@ using ChanSort.Api;
namespace ChanSort.Loader.Toshiba
{
class DbSerializer : SerializerBase
class ChmgtDbSerializer : SerializerBase
{
private const string FILE_chmgt_db = "\\chmgt_type001\\chmgt.db";
private const string FILE_dvbSysData_db = "\\dvb_type001\\dvbSysData.db";
@@ -19,7 +19,7 @@ namespace ChanSort.Loader.Toshiba
private readonly Dictionary<string, bool> channelInfoByUid = new Dictionary<string, bool>();
#region ctor()
public DbSerializer(string inputFile) : base(inputFile)
public ChmgtDbSerializer(string inputFile) : base(inputFile)
{
DepencencyChecker.AssertVc2010RedistPackageX86Installed();

View File

@@ -1,16 +0,0 @@
using ChanSort.Api;
namespace ChanSort.Loader.Toshiba
{
public class DbSerializerPlugin : ISerializerPlugin
{
public string DllName { get; set; }
public string PluginName => "Toshiba";
public string FileFilter => "*.zip";
public SerializerBase CreateSerializer(string inputFile)
{
return new DbSerializer(inputFile);
}
}
}

View File

@@ -0,0 +1,252 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.IO;
using ChanSort.Api;
namespace ChanSort.Loader.Toshiba
{
/*
* This class loads Toshiba files stores as CLONE00001\settingsDB.db along with settingsDBBackup.db
* Currently only channel renaming, reordering and deletion is supported.
* We don't know yet how/where information about favorites and skip/lock/hide is stored.
*
* Also, there are SatTable and SatTxTable for satellites and transponders in the file, but it's unknown
* how these tables are linked with EASISerTable / DVBSerTable / ...
*/
class SettingsDbSerializer : SerializerBase
{
private readonly ChannelList channels = new ChannelList(SignalSource.All, "All");
#region ctor()
public SettingsDbSerializer(string inputFile) : base(inputFile)
{
DepencencyChecker.AssertVc2010RedistPackageX86Installed();
this.Features.ChannelNameEdit = ChannelNameEditMode.All;
this.Features.DeleteMode = DeleteMode.Physically;
this.Features.CanSkipChannels = false;
this.Features.CanLockChannels = false;
this.Features.CanHideChannels = false;
this.Features.SupportedFavorites = 0;
this.DataRoot.AddChannelList(this.channels);
}
#endregion
#region GetDataFilePaths()
public override IEnumerable<string> GetDataFilePaths()
{
var list = new List<string>();
list.Add(this.FileName);
var backupFile = GetBackupFilePath();
if (File.Exists(backupFile))
list.Add(backupFile);
return list;
}
private string GetBackupFilePath()
{
var dir = Path.GetDirectoryName(this.FileName);
var name = Path.GetFileNameWithoutExtension(this.FileName);
var ext = Path.GetExtension(this.FileName);
var backupFile = Path.Combine(dir, name + "Backup" + ext);
return backupFile;
}
#endregion
#region Load()
public override void Load()
{
string sysDataConnString = "Data Source=" + this.FileName;
using var conn = new SQLiteConnection(sysDataConnString);
conn.Open();
using var cmd = conn.CreateCommand();
this.RepairCorruptedDatabaseImage(cmd);
cmd.CommandText = "SELECT count(1) FROM sqlite_master WHERE type = 'table' and name='EASISerTable'";
if (Convert.ToInt32(cmd.ExecuteScalar()) != 1)
throw new FileLoadException("File doesn't contain the expected tables");
this.ReadSatellites(cmd);
this.ReadTransponders(cmd);
this.ReadChannels(cmd);
}
#endregion
#region RepairCorruptedDatabaseImage()
private void RepairCorruptedDatabaseImage(SQLiteCommand cmd)
{
cmd.CommandText = "REINDEX";
cmd.ExecuteNonQuery();
}
#endregion
#region ReadSatellites()
private void ReadSatellites(SQLiteCommand cmd)
{
cmd.CommandText = "select m_id, m_name_serialized, m_orbital_position from SatTable";
using var r = cmd.ExecuteReader();
while (r.Read())
{
Satellite sat = new Satellite(r.GetInt32(0));
string eastWest = "E";
int pos = r.GetInt32(2);
if (pos < 0)
{
pos = -pos;
eastWest = "W";
}
sat.OrbitalPosition = $"{pos / 10}.{pos % 10}{eastWest}";
sat.Name = r.GetString(1);
this.DataRoot.AddSatellite(sat);
}
}
#endregion
#region ReadTransponders()
private void ReadTransponders(SQLiteCommand cmd)
{
cmd.CommandText = "select m_id, m_satellite_id, m_frequency, m_polarisation, m_symbol_rate from SatTxTable";
using var r = cmd.ExecuteReader();
while (r.Read())
{
int id = r.GetInt32(0);
int satId = r.GetInt32(1);
int freq = r.GetInt32(2);
if (this.DataRoot.Transponder.TryGet(id) != null)
continue;
Transponder tp = new Transponder(id);
tp.FrequencyInMhz = (decimal)freq;
tp.Polarity = r.GetInt32(3) == 0 ? 'H' : 'V';
tp.Satellite = this.DataRoot.Satellites.TryGet(satId);
tp.SymbolRate = r.GetInt32(4);
this.DataRoot.AddTransponder(tp.Satellite, tp);
}
}
#endregion
#region ReadChannels()
private void ReadChannels(SQLiteCommand cmd)
{
int ixE = 0;
int ixD = 3;
int ixA = 8;
int ixT = 9;
int ixDC = 10;
cmd.CommandText = @"
select
e.m_handle, e.m_rsn, e.m_name_serialized,
d.m_onid, d.m_tsid, d.m_id, d.m_type, d.m_name_serialized,
a.m_name_serialized,
t.frequency_in_multiples_of_10Hz,
dc.frequency
from EASISerTable e
left outer join DVBSerTable d on d.m_handle=e.m_handle
left outer join AnalogSerTable a on a.m_handle=e.m_handle
left outer join ChanDataTable dc on dc.handle=d.m_channel_no
left outer join ChanDataTable ac on ac.handle=a.m_channel_no
left outer join TADTunerDataTable t on t.channel=ac.channel_no";
using var r = cmd.ExecuteReader();
while (r.Read())
{
var handle = r.GetInt32(ixE + 0);
var oldProgNr = r.GetInt32(ixE + 1);
var name = r.GetString(ixE + 2);
ChannelInfo channel = new ChannelInfo(0, handle, oldProgNr, name);
// DVB
if (!r.IsDBNull(ixD + 0))
{
channel.OriginalNetworkId = r.GetInt32(ixD + 0) & 0x1FFF;
channel.TransportStreamId = r.GetInt32(ixD + 1) & 0x1FFF;
channel.ServiceId = r.GetInt32(ixD + 2) & 0x1FFF;
channel.ServiceType = r.GetInt32(ixD + 3);
channel.FreqInMhz = (decimal) r.GetInt32(ixDC + 0) / 1000;
}
// analog
if (!r.IsDBNull(ixA + 0))
{
channel.FreqInMhz = (decimal) r.GetInt32(ixT + 0) / 100000;
}
if (!channel.IsDeleted)
this.DataRoot.AddChannel(this.channels, channel);
}
}
#endregion
#region Save()
public override void Save(string tvOutputFile)
{
if (tvOutputFile != this.FileName)
{
File.Copy(this.FileName, tvOutputFile, true);
this.FileName = tvOutputFile;
}
string channelConnString = "Data Source=" + this.FileName;
using var conn = new SQLiteConnection(channelConnString);
conn.Open();
using var cmd = conn.CreateCommand();
using var cmd2 = conn.CreateCommand();
using var trans = conn.BeginTransaction();
this.WriteChannels(cmd, cmd2, this.channels);
trans.Commit();
this.RepairCorruptedDatabaseImage(cmd);
conn.Close();
// copy settingsDB.db to settingsDBBackup.db
var backupFile = GetBackupFilePath();
File.Copy(this.FileName, backupFile, true);
}
#endregion
#region WriteChannels()
private void WriteChannels(SQLiteCommand cmd, SQLiteCommand cmdDelete, ChannelList channelList)
{
cmd.CommandText = "update EASISerTable set m_rsn=@nr, m_name_serialized=@name where m_handle=@handle";
cmd.Parameters.Add(new SQLiteParameter("@handle", DbType.Int32));
cmd.Parameters.Add(new SQLiteParameter("@nr", DbType.Int32));
cmd.Parameters.Add(new SQLiteParameter("@name", DbType.String));
cmd.Prepare();
cmdDelete.CommandText = @"
delete from EASISerTable where m_handle=@handle;
delete from DVBSerTable where m_handle=@handle;
delete from AnalogSerTable where m_handle=@handle;
";
cmdDelete.Parameters.Add(new SQLiteParameter("@handle", DbType.Int32));
foreach (ChannelInfo channel in channelList.Channels)
{
if (channel.IsProxy) // ignore reference list proxy channels
continue;
if (channel.IsDeleted)
{
cmdDelete.Parameters["@handle"].Value = channel.RecordIndex;
cmdDelete.ExecuteNonQuery();
}
else
{
channel.UpdateRawData();
cmd.Parameters["@handle"].Value = channel.RecordIndex;
cmd.Parameters["@nr"].Value = channel.NewProgramNr;
cmd.Parameters["@name"].Value = channel.Name;
cmd.ExecuteNonQuery();
}
}
}
#endregion
}
}

View File

@@ -0,0 +1,20 @@
using System.IO;
using ChanSort.Api;
namespace ChanSort.Loader.Toshiba
{
public class ToshibaPlugin : ISerializerPlugin
{
public string DllName { get; set; }
public string PluginName => "Toshiba";
public string FileFilter => "*.zip;*.db";
public SerializerBase CreateSerializer(string inputFile)
{
if (Path.GetExtension(inputFile).ToLower() == ".db")
return new SettingsDbSerializer(inputFile);
else
return new ChmgtDbSerializer(inputFile);
}
}
}

View File

@@ -534,7 +534,8 @@ namespace ChanSort.Ui
catch (Exception ex)
{
serializer?.Dispose();
errorMsgs.AppendLine($"{plugin.DllName} ({plugin.PluginName}): {ex}\n\n");
var errMsg = ex is FileLoadException ? ex.Message : ex.ToString(); // FileLoadExceptions are normal when a Loader does not support a file. No stack trace needed
errorMsgs.AppendLine($"{plugin.DllName} ({plugin.PluginName}): {errMsg}\n\n");
if (ex is ArgumentException)
{
var msg = ex.ToString();

View File

@@ -34,7 +34,7 @@ namespace Test.Loader.Toshiba
private void TestChannelsAddedToCorrectLists(string fileName, SignalSource signalSource, int expectedTv, int expectedRadio, int dataProgramSid = 0, string dataProgramName = null)
{
var tempFile = TestUtils.DeploymentItem("Test.Loader.Toshiba\\TestFiles\\" + fileName);
var plugin = new DbSerializerPlugin();
var plugin = new ToshibaPlugin();
var ser = plugin.CreateSerializer(tempFile);
ser.Load();
@@ -72,7 +72,7 @@ namespace Test.Loader.Toshiba
public void TestDeletingChannel()
{
var tempFile = TestUtils.DeploymentItem("Test.Loader.Toshiba\\TestFiles\\Toshiba-SL863G.zip");
var plugin = new DbSerializerPlugin();
var plugin = new ToshibaPlugin();
var ser = plugin.CreateSerializer(tempFile);
ser.Load();
var data = ser.DataRoot;

View File

@@ -1,6 +1,9 @@
ChanSort Change Log
===================
2021-01-23
- Toshiba: added support for settingsDB.db lists
2021-01-17
- Philips: added support for ChannelMap_45 format
- Philips: fixed display of symbol rate and frequency (off by factor 1000 depending of list and DVB source)