mirror of
https://github.com/PredatH0r/ChanSort.git
synced 2026-01-14 03:12:04 +01:00
- Grundig: added support for dvb*_config.xml channel lists
- experimental feature to allow editing Audio-PID (but turned out to have no effect for webOS 5)
This commit is contained in:
@@ -38,6 +38,8 @@ namespace ChanSort.Api
|
||||
public bool MixedSourceFavorites { get; set; }
|
||||
public bool AllowGapsInFavNumbers { get; set; }
|
||||
public bool CanEditFavListNames { get; set; }
|
||||
|
||||
public bool CanEditAudioPid { get; set; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace ChanSort.Loader.GlobalClone
|
||||
this.Features.CanHideChannels = true;
|
||||
this.Features.CanSkipChannels = true;
|
||||
this.Features.CanLockChannels = true;
|
||||
this.Features.CanEditAudioPid = false;
|
||||
|
||||
this.DataRoot.AddChannelList(new ChannelList(SignalSource.AnalogT | SignalSource.Tv | SignalSource.Data, "Analog Antenna"));
|
||||
this.DataRoot.AddChannelList(new ChannelList(SignalSource.DvbT | SignalSource.Tv | SignalSource.Data, "DVB-T TV"));
|
||||
@@ -72,7 +73,7 @@ namespace ChanSort.Loader.GlobalClone
|
||||
|
||||
var dlg = View.Default.CreateActionBox("!!! WARNING !!!\n\n" +
|
||||
"Support for LG webOS 5 channel lists is experimental only!\n" +
|
||||
"There is a HIGH RISK that your TV will not import the list correctly and you need to run a new search or even reset the TV.\n" +
|
||||
"There is a RISK that your TV will not import the list correctly and you need to run a new search or even reset the TV.\n" +
|
||||
"Please read the information on github with steps that MAY lead to a successful import.\n" +
|
||||
"Any feedback about failure or success is highly appreciated.");
|
||||
dlg.AddAction("Read information about webOS 5 support on github.com", 1);
|
||||
@@ -267,6 +268,7 @@ namespace ChanSort.Loader.GlobalClone
|
||||
node["skipped"] = ch.Skip;
|
||||
node["locked"] = ch.Lock;
|
||||
node["Invisible"] = ch.Hidden;
|
||||
node["audioPid"] = ch.AudioPid;
|
||||
|
||||
// the only successfully imported file was one where these flags were NOT set by ChanSort
|
||||
// these flags do get set when changing numbers through the TV's menu, but then prevent further modifications, e.g. through an import
|
||||
@@ -277,7 +279,7 @@ namespace ChanSort.Loader.GlobalClone
|
||||
//}
|
||||
|
||||
//node["disableUpdate"] = true; // No-Go! This blocked the whole list and required a factory reset. Regardless of the setting, the TV showed wrong numbers.
|
||||
|
||||
|
||||
//node["factoryDefault"] = true; // an exported file after manually changing numbers through the TV-menu had all channels set to userEditChNumber=true, userSelCHNo=true, factoryDefault=true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" 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>{4D5AF0A3-1B96-42C8-910D-0C4852EA22F4}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>ChanSort.Loader.Grundig</RootNamespace>
|
||||
<AssemblyName>ChanSort.Loader.Grundig</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</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>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</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="Channel.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Serializer.cs" />
|
||||
<Compile Include="SerializerPlugin.cs" />
|
||||
</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" />
|
||||
</Project>
|
||||
21
source/ChanSort.Loader.Grundig/Channel.cs
Normal file
21
source/ChanSort.Loader.Grundig/Channel.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Xml;
|
||||
using ChanSort.Api;
|
||||
|
||||
namespace ChanSort.Loader.Grundig
|
||||
{
|
||||
internal class Channel : ChannelInfo
|
||||
{
|
||||
public readonly XmlNode Node;
|
||||
public string RawName;
|
||||
public string RawSatellite;
|
||||
public int Format;
|
||||
|
||||
internal Channel(SignalSource source, int order, int rowId, XmlNode node)
|
||||
{
|
||||
this.SignalSource = source;
|
||||
this.RecordOrder = order;
|
||||
this.RecordIndex = rowId;
|
||||
this.Node = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
36
source/ChanSort.Loader.Grundig/Properties/AssemblyInfo.cs
Normal file
36
source/ChanSort.Loader.Grundig/Properties/AssemblyInfo.cs
Normal 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.Grundig")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("ChanSort.Loader.Grundig")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2021")]
|
||||
[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("4d5af0a3-1b96-42c8-910d-0c4852ea22f4")]
|
||||
|
||||
// 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")]
|
||||
401
source/ChanSort.Loader.Grundig/Serializer.cs
Normal file
401
source/ChanSort.Loader.Grundig/Serializer.cs
Normal file
@@ -0,0 +1,401 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
using ChanSort.Api;
|
||||
|
||||
namespace ChanSort.Loader.Grundig
|
||||
{
|
||||
class Serializer : SerializerBase
|
||||
{
|
||||
private readonly ChannelList terrChannels = new ChannelList(SignalSource.Antenna, "Antenna");
|
||||
private readonly ChannelList cableChannels = new ChannelList(SignalSource.Cable, "Cable");
|
||||
private readonly ChannelList satChannels = new ChannelList(SignalSource.Sat, "Satellite");
|
||||
|
||||
private readonly List<FileData> fileDataList = new List<FileData>();
|
||||
private readonly StringBuilder logMessages = new StringBuilder();
|
||||
|
||||
|
||||
#region ctor()
|
||||
public Serializer(string inputFile) : base(inputFile)
|
||||
{
|
||||
this.Features.ChannelNameEdit = ChannelNameEditMode.All;
|
||||
this.Features.CanSkipChannels = true;
|
||||
this.Features.CanLockChannels = true;
|
||||
this.Features.CanHideChannels = true;
|
||||
this.Features.DeleteMode = DeleteMode.Physically;
|
||||
this.Features.CanSaveAs = false;
|
||||
this.Features.AllowGapsInFavNumbers = false;
|
||||
this.Features.CanEditFavListNames = false;
|
||||
this.Features.SortedFavorites = true;
|
||||
this.Features.MixedSourceFavorites = false;
|
||||
this.Features.SupportedFavorites = Favorites.A | Favorites.B | Favorites.C | Favorites.D;
|
||||
|
||||
|
||||
this.DataRoot.AddChannelList(this.terrChannels);
|
||||
this.DataRoot.AddChannelList(this.cableChannels);
|
||||
this.DataRoot.AddChannelList(this.satChannels);
|
||||
|
||||
foreach (var list in this.DataRoot.ChannelLists)
|
||||
{
|
||||
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.ServiceTypeName));
|
||||
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.PcrPid));
|
||||
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.VideoPid));
|
||||
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.AudioPid));
|
||||
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.ShortName));
|
||||
}
|
||||
|
||||
this.terrChannels.VisibleColumnFieldNames.Add(nameof(ChannelInfo.Source));
|
||||
this.cableChannels.VisibleColumnFieldNames.Add(nameof(ChannelInfo.Source));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Load()
|
||||
public override void Load()
|
||||
{
|
||||
// read all files from a directory structure that looks like
|
||||
// My_Channellist\dvbs_config.xml
|
||||
// My_Channellist\dvbc_config.xml
|
||||
// My_Channellist\dvbt_config.xml
|
||||
|
||||
|
||||
var dataFiles = new[] { "dvbt_config.xml", "dvbc_config.xml", "dvbs_config.xml" };
|
||||
var dir = Path.GetDirectoryName(this.FileName) ?? "";
|
||||
foreach (var file in dataFiles)
|
||||
{
|
||||
var fullPath = Path.GetFullPath(Path.Combine(dir, file));
|
||||
this.LoadFile(fullPath);
|
||||
}
|
||||
if (this.fileDataList.Count == 0)
|
||||
throw new FileLoadException("No XML files found in folder structure");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region LoadFile()
|
||||
|
||||
private void LoadFile(string fileName)
|
||||
{
|
||||
if (!File.Exists(fileName))
|
||||
return;
|
||||
bool fail = false;
|
||||
var fileData = new FileData();
|
||||
try
|
||||
{
|
||||
var content = File.ReadAllBytes(fileName);
|
||||
fileData.path = fileName;
|
||||
fileData.hasBom = content.Length >= 3 && content[0] == 0xef && content[1] == 0xbb && content[2] == 0xbf;
|
||||
var textContent = Encoding.UTF8.GetString(content, fileData.hasBom ? 3 : 0, content.Length - (fileData.hasBom ? 3 : 0));
|
||||
fileData.newline = textContent.Contains("\r\n") ? "\r\n" : "\n";
|
||||
fileData.indent = textContent.Contains(" <");
|
||||
fileData.doc = new XmlDocument();
|
||||
fileData.doc.PreserveWhitespace = true;
|
||||
|
||||
var settings = new XmlReaderSettings
|
||||
{
|
||||
CheckCharacters = false,
|
||||
IgnoreProcessingInstructions = true,
|
||||
ValidationFlags = XmlSchemaValidationFlags.None,
|
||||
DtdProcessing = DtdProcessing.Ignore
|
||||
};
|
||||
using var reader = XmlReader.Create(new StringReader(textContent), settings);
|
||||
fileData.doc.Load(reader);
|
||||
}
|
||||
catch
|
||||
{
|
||||
fail = true;
|
||||
}
|
||||
|
||||
var root = fileData.doc.FirstChild;
|
||||
if (root is XmlDeclaration)
|
||||
root = root.NextSibling;
|
||||
while (root.LocalName == "#whitespace")
|
||||
root = root.NextSibling;
|
||||
if (fail || root == null || root.LocalName != "CONFIG")
|
||||
throw new FileLoadException("\"" + fileName + "\" is not a supported Grundig XML file");
|
||||
|
||||
int transponderId = 0;
|
||||
int chanId = 0;
|
||||
foreach (XmlNode child in root.ChildNodes)
|
||||
{
|
||||
switch (child.LocalName)
|
||||
{
|
||||
case "Digital":
|
||||
ReadDigitalChannels(child, transponderId, ref chanId);
|
||||
break;
|
||||
case "Analog":
|
||||
ReadAnalogChannels(child, ref chanId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.fileDataList.Add(fileData);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ReadAnalogChannels
|
||||
|
||||
private void ReadAnalogChannels(XmlNode analog, ref int chanId)
|
||||
{
|
||||
SignalSource src;
|
||||
var type = analog.Attributes?["type"]?.InnerText;
|
||||
switch (type)
|
||||
{
|
||||
case "DVBT_ANALOG":
|
||||
src = SignalSource.AnalogT;
|
||||
break;
|
||||
case "DVBC_ANALOG":
|
||||
src = SignalSource.AnalogC;
|
||||
break;
|
||||
default:
|
||||
logMessages.AppendFormat("skipped unsupported analog source type: " + type);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (XmlNode service in analog["channels"].ChildNodes)
|
||||
{
|
||||
if (service.LocalName != "service")
|
||||
continue;
|
||||
|
||||
var c = new Channel(src, chanId, chanId, service);
|
||||
c.Source = type;
|
||||
c.FreqInMhz = Int32.Parse(service.Attributes["frq"].InnerText) / 20m;
|
||||
c.Hidden = service.Attributes["hid"].InnerText == "1";
|
||||
ReadCommonChannelData(c, service);
|
||||
var list = this.DataRoot.GetChannelList(src);
|
||||
this.DataRoot.AddChannel(list, c);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ReadDigitalChannels
|
||||
private void ReadDigitalChannels(XmlNode digital, int transponderId, ref int chanId)
|
||||
{
|
||||
SignalSource src;
|
||||
decimal freqDivider;
|
||||
var type = digital.Attributes?["type"]?.InnerText;
|
||||
switch (type)
|
||||
{
|
||||
case "DVBC":
|
||||
src = SignalSource.DvbC;
|
||||
freqDivider = 1000;
|
||||
break;
|
||||
case "DVBT":
|
||||
src = SignalSource.DvbT;
|
||||
freqDivider = 1000;
|
||||
break;
|
||||
case "DVBS":
|
||||
src = SignalSource.DvbS;
|
||||
freqDivider = 1;
|
||||
break;
|
||||
default:
|
||||
logMessages.AppendFormat("skipped unsupported digital source type: " + type);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (XmlNode networkNode in digital["channels"].ChildNodes)
|
||||
{
|
||||
if (networkNode.LocalName != "network")
|
||||
continue;
|
||||
var provider = networkNode.Attributes["nwname"]?.InnerText;
|
||||
foreach (XmlNode mux in networkNode.ChildNodes)
|
||||
{
|
||||
if (mux.LocalName != "mux")
|
||||
continue;
|
||||
var t = CreateTransponder(mux, ref transponderId, freqDivider);
|
||||
foreach (XmlNode service in mux.ChildNodes)
|
||||
{
|
||||
if (service.LocalName != "service")
|
||||
continue;
|
||||
|
||||
var c = CreateChannel(service, src, t, ref chanId);
|
||||
if (c == null)
|
||||
continue;
|
||||
c.Source = type;
|
||||
c.Provider = provider;
|
||||
|
||||
var list = this.DataRoot.GetChannelList(src);
|
||||
this.DataRoot.AddChannel(list, c);
|
||||
++chanId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CreateChannel
|
||||
private Channel CreateChannel(XmlNode service, SignalSource src, Transponder transponder, ref int chanId)
|
||||
{
|
||||
var c = new Channel(src, chanId, chanId, service);
|
||||
c.Transponder = transponder;
|
||||
c.Polarity = transponder.Polarity;
|
||||
c.FreqInMhz = transponder.FrequencyInMhz;
|
||||
c.SymbolRate = transponder.SymbolRate;
|
||||
c.OriginalNetworkId = transponder.OriginalNetworkId;
|
||||
c.TransportStreamId = transponder.TransportStreamId;
|
||||
ReadCommonChannelData(c, service);
|
||||
c.Hidden = service.Attributes["vis"].InnerText == "0";
|
||||
c.ServiceId = Int32.Parse(service.Attributes["sid"].InnerText);
|
||||
c.Encrypted = service.Attributes["ca"].InnerText == "1";
|
||||
c.IsDeleted = service.Attributes["del"].InnerText == "1";
|
||||
return c;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ReadCommonChannelData
|
||||
private void ReadCommonChannelData(Channel c, XmlNode service)
|
||||
{
|
||||
c.OldProgramNr = Int32.Parse(service.Attributes["num"].InnerText);
|
||||
for (int f = 1; f <= 4; f++)
|
||||
{
|
||||
var n = Int32.Parse(service.Attributes["f" + f].InnerText);
|
||||
c.SetOldPosition(f, n == 0 ? -1 : n);
|
||||
}
|
||||
c.Lock = service.Attributes["lck"].InnerText == "1";
|
||||
c.Skip = service.Attributes["skp"].InnerText == "1";
|
||||
c.Name = service.Attributes["name"].InnerText;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CreateTransponder
|
||||
private Transponder CreateTransponder(XmlNode mux, ref int transponderId, decimal freqDivider)
|
||||
{
|
||||
var t = new Transponder(++transponderId);
|
||||
t.Polarity = mux.Attributes["pol"].InnerText == "1" ? 'H' : 'V';
|
||||
t.SymbolRate = Int32.Parse(mux.Attributes["sym"].InnerText);
|
||||
t.FrequencyInMhz = Int32.Parse(mux.Attributes["frq"].InnerText) / freqDivider;
|
||||
t.OriginalNetworkId = Int32.Parse(mux.Attributes["onid"].InnerText);
|
||||
t.TransportStreamId = Int32.Parse(mux.Attributes["tsid"].InnerText);
|
||||
return t;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Save()
|
||||
|
||||
public override void Save(string tvOutputFile)
|
||||
{
|
||||
// "Save As..." is not supported by this loader
|
||||
|
||||
foreach (var list in this.DataRoot.ChannelLists)
|
||||
this.UpdateChannelList(list);
|
||||
|
||||
foreach (var file in this.fileDataList)
|
||||
this.SaveFile(file);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SaveFile()
|
||||
private void SaveFile(FileData file)
|
||||
{
|
||||
// use xmlWriterSettings and some post-processing to maintain the original white spacing as much as possible (new line characters, indentation, empty element close tag, ...),
|
||||
// so that the original and modified files can be hex-compared
|
||||
// From the 2 test files available so far, one only has \n after the XML processing instruction and the document end, all other white spaces are removed.
|
||||
// The other file uses \r\n after all start/end tags and 2 spaces for indentation
|
||||
var xmlSettings = new XmlWriterSettings();
|
||||
xmlSettings.Encoding = this.DefaultEncoding;
|
||||
xmlSettings.CheckCharacters = false;
|
||||
xmlSettings.Indent = file.indent;
|
||||
xmlSettings.IndentChars = " ";
|
||||
xmlSettings.NewLineHandling = NewLineHandling.Replace;
|
||||
xmlSettings.NewLineChars = file.newline;
|
||||
xmlSettings.OmitXmlDeclaration = false;
|
||||
|
||||
using var sw = new StringWriter();
|
||||
using var w = XmlWriter.Create(sw, xmlSettings);
|
||||
file.doc.WriteTo(w);
|
||||
w.Flush();
|
||||
var xml = sw.ToString();
|
||||
|
||||
if (!file.indent)
|
||||
xml = xml.Replace("\" />", "\"/>");
|
||||
var enc = new UTF8Encoding(file.hasBom, false);
|
||||
File.WriteAllText(file.path, xml, enc);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UpdateChannelList()
|
||||
private void UpdateChannelList(ChannelList list)
|
||||
{
|
||||
foreach (var channel in list.Channels)
|
||||
{
|
||||
var ch = channel as Channel;
|
||||
if (ch == null)
|
||||
continue; // might be a proxy channel from a reference list
|
||||
|
||||
if (ch.IsDeleted)
|
||||
continue;
|
||||
if (ch.NewProgramNr < 0)
|
||||
{
|
||||
if ((ch.SignalSource & SignalSource.Digital) != 0)
|
||||
ch.IsDeleted = true;
|
||||
else
|
||||
{
|
||||
// analog channels can only be physically removed (no "del" attribute)
|
||||
ch.Node.ParentNode.RemoveChild(ch.Node);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
this.UpdateChannel(ch);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UpdateChannel
|
||||
private void UpdateChannel(Channel ch)
|
||||
{
|
||||
var att = ch.Node.Attributes;
|
||||
|
||||
if (ch.IsDeleted)
|
||||
{
|
||||
att["del"].InnerText = "1";
|
||||
return; // "num" stays as-is and can be a dupe
|
||||
}
|
||||
|
||||
att["num"].InnerText = ch.NewProgramNr.ToString();
|
||||
if (ch.IsNameModified)
|
||||
att["name"].Value = ch.Name;
|
||||
for (int i=1; i<=4; i++)
|
||||
att["f"+i].Value = Math.Max(0, ch.FavIndex[i-1]).ToString(); // convert -1 to 0
|
||||
att["skp"].InnerText = ch.Skip ? "1" : "0";
|
||||
att["lck"].InnerText = ch.Lock ? "1" : "0";
|
||||
if ((ch.SignalSource & SignalSource.Digital) != 0)
|
||||
att["vis"].InnerText = ch.Hidden ? "0" : "1";
|
||||
else
|
||||
att["hid"].InnerText = ch.Hidden ? "1" : "0";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetDataFilePaths()
|
||||
public override IEnumerable<string> GetDataFilePaths()
|
||||
{
|
||||
return this.fileDataList.Select(fd => fd.path);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetFileInformation()
|
||||
public override string GetFileInformation()
|
||||
{
|
||||
return base.GetFileInformation() + this.logMessages.Replace("\n", "\r\n");
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region class FileData
|
||||
private class FileData
|
||||
{
|
||||
public string path;
|
||||
public bool hasBom;
|
||||
public string newline;
|
||||
public bool indent;
|
||||
public XmlDocument doc;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
16
source/ChanSort.Loader.Grundig/SerializerPlugin.cs
Normal file
16
source/ChanSort.Loader.Grundig/SerializerPlugin.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using ChanSort.Api;
|
||||
|
||||
namespace ChanSort.Loader.Grundig
|
||||
{
|
||||
public class SerializerPlugin : ISerializerPlugin
|
||||
{
|
||||
public string DllName { get; set; }
|
||||
public string PluginName => "Grundig dvb?_config.xml";
|
||||
public string FileFilter => "*.xml";
|
||||
|
||||
public SerializerBase CreateSerializer(string inputFile)
|
||||
{
|
||||
return new Serializer(inputFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChanSort", "ChanSort\ChanSo
|
||||
{A1C9A98D-368A-44E8-9B7F-7EACA46C9EC5} = {A1C9A98D-368A-44E8-9B7F-7EACA46C9EC5}
|
||||
{F6F02792-07F1-48D5-9AF3-F945CA5E3931} = {F6F02792-07F1-48D5-9AF3-F945CA5E3931}
|
||||
{E972D8A1-2F5F-421C-AC91-CFF45E5191BE} = {E972D8A1-2F5F-421C-AC91-CFF45E5191BE}
|
||||
{4D5AF0A3-1B96-42C8-910D-0C4852EA22F4} = {4D5AF0A3-1B96-42C8-910D-0C4852EA22F4}
|
||||
{5361C8CB-F737-4709-AF8C-E1F0456F3C5B} = {5361C8CB-F737-4709-AF8C-E1F0456F3C5B}
|
||||
{D093E7EE-D3AD-4E7B-AF82-C6918CA017FB} = {D093E7EE-D3AD-4E7B-AF82-C6918CA017FB}
|
||||
EndProjectSection
|
||||
@@ -82,6 +83,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Loader.PhilipsBin", "T
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spike.LgWebOs5", "Spike.LgWebOs5\Spike.LgWebOs5.csproj", "{32EFB306-DEF8-4488-B1AE-46D5B183C373}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChanSort.Loader.Grundig", "ChanSort.Loader.Grundig\ChanSort.Loader.Grundig.csproj", "{4D5AF0A3-1B96-42C8-910D-0C4852EA22F4}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -464,6 +467,18 @@ Global
|
||||
{32EFB306-DEF8-4488-B1AE-46D5B183C373}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{32EFB306-DEF8-4488-B1AE-46D5B183C373}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{32EFB306-DEF8-4488-B1AE-46D5B183C373}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4D5AF0A3-1B96-42C8-910D-0C4852EA22F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4D5AF0A3-1B96-42C8-910D-0C4852EA22F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4D5AF0A3-1B96-42C8-910D-0C4852EA22F4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{4D5AF0A3-1B96-42C8-910D-0C4852EA22F4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{4D5AF0A3-1B96-42C8-910D-0C4852EA22F4}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{4D5AF0A3-1B96-42C8-910D-0C4852EA22F4}.Debug|x86.Build.0 = Debug|x86
|
||||
{4D5AF0A3-1B96-42C8-910D-0C4852EA22F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4D5AF0A3-1B96-42C8-910D-0C4852EA22F4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4D5AF0A3-1B96-42C8-910D-0C4852EA22F4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{4D5AF0A3-1B96-42C8-910D-0C4852EA22F4}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{4D5AF0A3-1B96-42C8-910D-0C4852EA22F4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4D5AF0A3-1B96-42C8-910D-0C4852EA22F4}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -310,6 +310,7 @@ namespace ChanSort.Ui
|
||||
//this.SetControlsEnabled(!this.dataRoot.IsEmpty);
|
||||
this.UpdateFavoritesEditor(this.DataRoot.SupportedFavorites);
|
||||
this.colEncrypted.OptionsColumn.AllowEdit = this.currentTvSerializer.Features.EncryptedFlagEdit;
|
||||
this.colAudioPid.OptionsColumn.AllowEdit = this.currentTvSerializer.Features.CanEditAudioPid;
|
||||
this.UpdateMenu(true);
|
||||
|
||||
if (this.DataRoot.Warnings.Length > 0 && this.miShowWarningsAfterLoad.Checked)
|
||||
@@ -1735,26 +1736,26 @@ namespace ChanSort.Ui
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
foreach (var dataFilePath in this.currentTvSerializer.GetDataFilePaths())
|
||||
{
|
||||
foreach (var dataFilePath in this.currentTvSerializer.GetDataFilePaths())
|
||||
bakFile = dataFilePath + ".bak";
|
||||
try
|
||||
{
|
||||
bakFile = dataFilePath + ".bak";
|
||||
File.Copy(bakFile, dataFilePath, true);
|
||||
var attr = File.GetAttributes(dataFilePath);
|
||||
File.SetAttributes(dataFilePath, attr & ~FileAttributes.ReadOnly);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
XtraMessageBox.Show(this, string.Format(Resources.MainForm_miRestoreOriginal_Message, dataFilePath),
|
||||
this.miRestoreOriginal.Caption,
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
|
||||
}
|
||||
}
|
||||
|
||||
this.currentTvSerializer.DataRoot.NeedsSaving = false;
|
||||
if (this.currentPlugin != null)
|
||||
this.LoadFiles(this.currentPlugin, this.currentTvFile);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
XtraMessageBox.Show(this, string.Format(Resources.MainForm_miRestoreOriginal_Message, this.currentTvFile),
|
||||
this.miRestoreOriginal.Caption,
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
|
||||
}
|
||||
this.currentTvSerializer.DataRoot.NeedsSaving = false;
|
||||
if (this.currentPlugin != null)
|
||||
this.LoadFiles(this.currentPlugin, this.currentTvFile);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace ChanSort.Ui
|
||||
{
|
||||
int end = response.IndexOf(".zip", start);
|
||||
int len = end - start - SearchString.Length;
|
||||
if (len >= 10) // YYYY-MM-DD plus optional suffix for a revision
|
||||
if (len >= 10) // YYYY-MM-DD plus optional _HHmm suffix for a revision
|
||||
return response.Substring(start + SearchString.Length, len);
|
||||
}
|
||||
return string.Empty;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
ChanSort Change Log
|
||||
===================
|
||||
|
||||
2021-01-02
|
||||
- Grundig: added support for dvb*_config.xml channel lists
|
||||
|
||||
2020-12-29
|
||||
- update check could not distinguish between 2 program versions from the same day (kept showing "an update is available")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user