mirror of
https://github.com/PredatH0r/ChanSort.git
synced 2026-01-15 11:52:04 +01:00
- added partial support for Philips .xml channel lists
(There are MANY different file formats, only a few are currently supported) - fixed "most-recently-used" getting reversed every time the program was started - added "UTF-8 (Unicode)" character set to menu - fixed disappearing columns when loading different channel lists without restarting the application
This commit is contained in:
@@ -11,7 +11,7 @@ About ChanSort
|
||||
--------------
|
||||
ChanSort is a Windows application that allows you to reorder your TV's channel list.
|
||||
Most modern TVs can transfer channel lists via USB stick, which you can plug into your PC.
|
||||
ChanSort supports various file formats from **Sony** (new), **ITT, Medion, Nabo, ok., PEAQ, Schaub-Lorenz, Silva-Schneider, Telefunken** (new),
|
||||
ChanSort supports various file formats from **Philips** (new), **Sony** (new), **ITT, Medion, Nabo, ok., PEAQ, Schaub-Lorenz, Silva-Schneider, Telefunken** (new),
|
||||
Hisense, Samsung, LG, Panasonic, Toshiba and the Linux VDR project.
|
||||
|
||||

|
||||
@@ -96,6 +96,10 @@ Models that export a .zip file containing chmgt.db, dvbSysData.db and dvbMainDat
|
||||
**ITT, Medion, Nabo, ok., PEAQ, Schaub-Lorenz, Silva-Schneider, Telefunken**
|
||||
These brands use .sdx files (currently only satellite lists are supported)
|
||||
|
||||
**Philips**
|
||||
Philips uses countless incompatible file formats for various TV models.
|
||||
ChanSort currently supports 2 different versions of .xml files, other formats are not supported.
|
||||
|
||||
**VDR (Linux Video Disk Recorder)**
|
||||
Supports the channels.conf file format.
|
||||
Implementation for this was provided by TCr82 from the VDR project.
|
||||
|
||||
@@ -11,7 +11,7 @@ Links
|
||||
--------------
|
||||
ChanSort ist eine Windows-Anwendung, die das Sortieren von Fernsehsenderlisten erlaubt.
|
||||
Die meisten modernen Fernseher k<>nnen Senderlisten auf einen USB-Stick <20>bertragen, den man danach am PC anschlie<69>t.
|
||||
ChanSort unterst<73>tzt diverse Dateiformate von **Sony** (new), **ITT, Medion, Nabo, ok., PEAQ, Schaub-Lorenz, Silva-Schneider, Telefunken** (new),
|
||||
ChanSort unterst<73>tzt diverse Dateiformate von **Philips** (neu), **Sony** (new), **ITT, Medion, Nabo, ok., PEAQ, Schaub-Lorenz, Silva-Schneider, Telefunken** (new),
|
||||
Hisense, Samsung, LG, Panasonic, Toshiba und dem Linux VDR Projekt.
|
||||
|
||||

|
||||
@@ -91,6 +91,10 @@ Die Marken nutzen .sdx Dateien (derzeit wird nur Satellitenempfang unterst
|
||||
Modelle, die eine .zip-Datei mit folgendem Inhalt: chmgt.db, dvbSysData.db und dvbMainData.db.
|
||||
(z.B. RL, SL, TL, UL, VL, WL, XL, YL models of series 8xx/9xx)
|
||||
|
||||
**Philips**
|
||||
Philips verwendet unz<6E>hlige unterschiedliche Dateiformate f<>r diverse TV-Modelle.
|
||||
ChanSort unterst<73>tzt derzeit 2 Varianten von .xml-Dateien. Andere Formate werden nicht unterst<73>tzt.
|
||||
|
||||
**VDR (Linux Video Disk Recorder)**
|
||||
Unterst<EFBFBD>tzung des channels.conf Dateiformats.
|
||||
Die Implementation hierf<72>r wurde vom Mitglied "TCr82" des VDR Projekts beigesteuert.
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace ChanSort.Api
|
||||
this.SignalSource = source;
|
||||
this.ShortCaption = caption;
|
||||
this.FirstProgramNumber = (source & SignalSource.Digital) != 0 ? 1 : 0;
|
||||
this.VisibleColumnFieldNames = DefaultVisibleColumns;
|
||||
this.VisibleColumnFieldNames = DefaultVisibleColumns.ToList(); // create copy of default list, so it can be modified
|
||||
}
|
||||
|
||||
public string ShortCaption { get; }
|
||||
|
||||
@@ -24,6 +24,8 @@ namespace ChanSort.Api
|
||||
Sat = 0x0040,
|
||||
IP = 0x0080,
|
||||
|
||||
MaskAdInput = MaskAnalogDigital | MaskAntennaCableSat,
|
||||
|
||||
// bit 9+10: TV/Radio
|
||||
MaskTvRadio = 0x0300,
|
||||
Tv = 0x0100,
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
<?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>{D7BAFD55-50F5-46C3-A76B-2193BED5358F}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>ChanSort.Loader.PhilipsXml</RootNamespace>
|
||||
<AssemblyName>ChanSort.Loader.PhilipsXml</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</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>
|
||||
</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>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</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.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Channel.cs" />
|
||||
<Compile Include="CustomXmlWriter.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>
|
||||
20
source/ChanSort.Loader.PhilipsXml/Channel.cs
Normal file
20
source/ChanSort.Loader.PhilipsXml/Channel.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System.Xml;
|
||||
using ChanSort.Api;
|
||||
|
||||
namespace ChanSort.Loader.PhilipsXml
|
||||
{
|
||||
internal class Channel : ChannelInfo
|
||||
{
|
||||
public readonly XmlNode SetupNode;
|
||||
public string RawName;
|
||||
public string RawSatellite;
|
||||
|
||||
internal Channel(SignalSource source, int order, int rowId, XmlNode setupNode)
|
||||
{
|
||||
this.SignalSource = source;
|
||||
this.RecordOrder = order;
|
||||
this.RecordIndex = rowId;
|
||||
this.SetupNode = setupNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
170
source/ChanSort.Loader.PhilipsXml/CustomXmlWriter.cs
Normal file
170
source/ChanSort.Loader.PhilipsXml/CustomXmlWriter.cs
Normal file
@@ -0,0 +1,170 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
|
||||
namespace ChanSort.Loader.PhilipsXml
|
||||
{
|
||||
/// <summary>
|
||||
/// This XmlWriter replaces some characters with Char- or Entity- references the same way
|
||||
/// they are escaped in the original Sony XML files
|
||||
/// </summary>
|
||||
class CustomXmlWriter : XmlWriter
|
||||
{
|
||||
private static readonly char[] CharsToEscape = { '\'', '\"', '&', '<', '>' };
|
||||
private static readonly string[] CharEntites = { "apos", "quot", "amp", "lt", "gt" };
|
||||
|
||||
private XmlWriter w;
|
||||
private readonly bool escapeAsEntityRef; // if true, use & otherwise "
|
||||
|
||||
public CustomXmlWriter(TextWriter tw, XmlWriterSettings settings, bool useEntityRef)
|
||||
{
|
||||
this.w = XmlWriter.Create(tw, settings);
|
||||
this.escapeAsEntityRef = useEntityRef;
|
||||
}
|
||||
|
||||
public override void WriteString(string text)
|
||||
{
|
||||
int i = 0, j;
|
||||
while ((j = text.IndexOfAny(CharsToEscape, i)) >= 0)
|
||||
{
|
||||
this.w.WriteString(text.Substring(i, j - i));
|
||||
if (this.escapeAsEntityRef)
|
||||
{
|
||||
// => &
|
||||
int k = Array.IndexOf(CharsToEscape, text[j]);
|
||||
this.w.WriteEntityRef(CharEntites[k]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// => &
|
||||
//this.w.WriteCharEntity(text[j]);
|
||||
this.w.WriteRaw("&#" + (int)text[j] + ";");
|
||||
}
|
||||
|
||||
i = j + 1;
|
||||
}
|
||||
this.w.WriteString(text.Substring(i));
|
||||
}
|
||||
|
||||
#region 1:1 delegation
|
||||
|
||||
public override void WriteStartDocument()
|
||||
{
|
||||
this.w.WriteStartDocument();
|
||||
}
|
||||
|
||||
public override void WriteStartDocument(bool standalone)
|
||||
{
|
||||
this.w.WriteStartDocument(standalone);
|
||||
}
|
||||
|
||||
public override void WriteEndDocument()
|
||||
{
|
||||
this.w.WriteEndDocument();
|
||||
}
|
||||
|
||||
public override void WriteDocType(string name, string pubid, string sysid, string subset)
|
||||
{
|
||||
this.w.WriteDocType(name, pubid, sysid, subset);
|
||||
}
|
||||
|
||||
public override void WriteStartElement(string prefix, string localName, string ns)
|
||||
{
|
||||
this.w.WriteStartElement(prefix, localName, ns);
|
||||
}
|
||||
|
||||
public override void WriteEndElement()
|
||||
{
|
||||
this.w.WriteEndElement();
|
||||
}
|
||||
|
||||
public override void WriteFullEndElement()
|
||||
{
|
||||
this.w.WriteFullEndElement();
|
||||
}
|
||||
|
||||
public override void WriteStartAttribute(string prefix, string localName, string ns)
|
||||
{
|
||||
this.w.WriteStartAttribute(prefix, localName, ns);
|
||||
}
|
||||
|
||||
public override void WriteEndAttribute()
|
||||
{
|
||||
this.w.WriteEndAttribute();
|
||||
}
|
||||
|
||||
public override void WriteCData(string text)
|
||||
{
|
||||
this.w.WriteCData(text);
|
||||
}
|
||||
|
||||
public override void WriteComment(string text)
|
||||
{
|
||||
this.w.WriteComment(text);
|
||||
}
|
||||
|
||||
public override void WriteProcessingInstruction(string name, string text)
|
||||
{
|
||||
this.w.WriteProcessingInstruction(name, text);
|
||||
}
|
||||
|
||||
public override void WriteEntityRef(string name)
|
||||
{
|
||||
this.w.WriteEntityRef(name);
|
||||
}
|
||||
|
||||
public override void WriteCharEntity(char ch)
|
||||
{
|
||||
this.w.WriteCharEntity(ch);
|
||||
}
|
||||
|
||||
public override void WriteWhitespace(string ws)
|
||||
{
|
||||
this.w.WriteWhitespace(ws);
|
||||
}
|
||||
|
||||
public override void WriteSurrogateCharEntity(char lowChar, char highChar)
|
||||
{
|
||||
this.w.WriteSurrogateCharEntity(lowChar, highChar);
|
||||
}
|
||||
|
||||
public override void WriteChars(char[] buffer, int index, int count)
|
||||
{
|
||||
this.w.WriteChars(buffer, index, count);
|
||||
}
|
||||
|
||||
public override void WriteRaw(char[] buffer, int index, int count)
|
||||
{
|
||||
this.w.WriteRaw(buffer, index, count);
|
||||
}
|
||||
|
||||
public override void WriteRaw(string data)
|
||||
{
|
||||
this.w.WriteRaw(data);
|
||||
}
|
||||
|
||||
public override void WriteBase64(byte[] buffer, int index, int count)
|
||||
{
|
||||
this.w.WriteBase64(buffer, index, count);
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
this.w.Close();
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
this.w.Flush();
|
||||
}
|
||||
|
||||
public override string LookupPrefix(string ns)
|
||||
{
|
||||
return this.w.LookupPrefix(ns);
|
||||
}
|
||||
|
||||
public override WriteState WriteState => this.w.WriteState;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
36
source/ChanSort.Loader.PhilipsXml/Properties/AssemblyInfo.cs
Normal file
36
source/ChanSort.Loader.PhilipsXml/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.PhilipsXml")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("ChanSort.Loader.PhilipsXml")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2019")]
|
||||
[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("d7bafd55-50f5-46c3-a76b-2193bed5358f")]
|
||||
|
||||
// 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")]
|
||||
408
source/ChanSort.Loader.PhilipsXml/Serializer.cs
Normal file
408
source/ChanSort.Loader.PhilipsXml/Serializer.cs
Normal file
@@ -0,0 +1,408 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
using ChanSort.Api;
|
||||
|
||||
namespace ChanSort.Loader.PhilipsXml
|
||||
{
|
||||
/*
|
||||
This loader supports 2 different kinds of XML files from Philips.
|
||||
|
||||
I had a test file "DVBS.xml" with satellite channels and entries like:
|
||||
<Channel>
|
||||
<Setup SatelliteName="0x54 0x00 0x55 0x00 0x52 0x00 0x4B 0x00 0x53 0x00 0x41 0x00 0x54 0x00 0x20 0x00 0x34 0x00 0x32 0x00 0x45 0x00 " ChannelNumber="1" ChannelName="0x54 0x00 0xC4 0x00 0xB0 0x00 0x56 0x00 0xC4 0x00 0xB0 0x00 0x42 0x00 0x55 0x00 0x20 0x00 0x53 0x00 0x50 0x00 0x4F 0x00 0x52 0x00 " ChannelLock="0" UserModifiedName="0" LogoID="0" UserModifiedLogo="0" LogoLock="0" UserHidden="0" FavoriteNumber="0" />
|
||||
<Broadcast ChannelType="3" Onid="1070" Tsid="43203" Sid="16001" Frequency="11794" Modulation="0" ServiceType="1" SymbolRate="27507" LNBNumber="38" Polarization="0" SystemHidden="0" />
|
||||
</Channel>
|
||||
|
||||
The other file was "CM_TPM1013E_LA_CK.xml" with entries like:
|
||||
<Channel>
|
||||
<Setup oldpresetnumber="1" presetnumber="1" name="Das Erste" ></Setup>
|
||||
<Broadcast medium="dvbc" frequency="410000" system="west" serviceID="1" ONID="41985" TSID="1101" modulation="256" symbolrate="6901000" bandwidth="Unknown"></Broadcast>
|
||||
</Channel>
|
||||
|
||||
*/
|
||||
class Serializer : SerializerBase
|
||||
{
|
||||
private readonly ChannelList terrChannels = new ChannelList(SignalSource.DvbT | SignalSource.Tv | SignalSource.Radio, "DVB-T");
|
||||
private readonly ChannelList cableChannels = new ChannelList(SignalSource.DvbC | SignalSource.Tv | SignalSource.Radio, "DVB-C");
|
||||
private readonly ChannelList satChannels = new ChannelList(SignalSource.DvbS | SignalSource.Tv | SignalSource.Radio, "DVB-S");
|
||||
|
||||
private ChannelList curList;
|
||||
|
||||
private XmlDocument doc;
|
||||
private byte[] content;
|
||||
private string textContent;
|
||||
private string newline;
|
||||
private int formatVersion;
|
||||
|
||||
#region ctor()
|
||||
public Serializer(string inputFile) : base(inputFile)
|
||||
{
|
||||
this.Features.ChannelNameEdit = ChannelNameEditMode.All;
|
||||
this.Features.CanDeleteChannels = true;
|
||||
|
||||
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("PcrPid");
|
||||
list.VisibleColumnFieldNames.Remove("VideoPid");
|
||||
list.VisibleColumnFieldNames.Remove("AudioPid");
|
||||
list.VisibleColumnFieldNames.Remove("Skip");
|
||||
list.VisibleColumnFieldNames.Remove("ShortName");
|
||||
list.VisibleColumnFieldNames.Remove("Provider");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region DisplayName
|
||||
public override string DisplayName => "Philips *.xml loader";
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Load()
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
bool fail = false;
|
||||
try
|
||||
{
|
||||
this.doc = new XmlDocument();
|
||||
this.content = File.ReadAllBytes(this.FileName);
|
||||
this.textContent = Encoding.UTF8.GetString(this.content);
|
||||
this.newline = this.textContent.Contains("\r\n") ? "\r\n" : "\n";
|
||||
|
||||
var settings = new XmlReaderSettings
|
||||
{
|
||||
CheckCharacters = false,
|
||||
IgnoreProcessingInstructions = true,
|
||||
ValidationFlags = XmlSchemaValidationFlags.None,
|
||||
DtdProcessing = DtdProcessing.Ignore
|
||||
};
|
||||
using (var reader = XmlReader.Create(new StringReader(textContent), settings))
|
||||
{
|
||||
doc.Load(reader);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
fail = true;
|
||||
}
|
||||
|
||||
var root = doc.FirstChild;
|
||||
if (root is XmlDeclaration)
|
||||
root = root.NextSibling;
|
||||
if (fail || root == null || root.LocalName != "ChannelMap")
|
||||
throw new FileLoadException("\"" + this.FileName + "\" is not a supported Philips XML file");
|
||||
|
||||
|
||||
int rowId = 0;
|
||||
foreach (XmlNode child in root.ChildNodes)
|
||||
{
|
||||
switch (child.LocalName)
|
||||
{
|
||||
case "Channel":
|
||||
if (rowId == 0)
|
||||
this.DetectFormatAndFeatures(child);
|
||||
if (this.curList != null)
|
||||
this.ReadChannel(child, rowId++);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region DetectFormatAndFeatures()
|
||||
|
||||
private void DetectFormatAndFeatures(XmlNode node)
|
||||
{
|
||||
var setupNode = node["Setup"] ?? throw new FileLoadException("Missing Setup XML element");
|
||||
var bcastNode = node["Broadcast"] ?? throw new FileLoadException("Missing Broadcast XML element");
|
||||
|
||||
var fname = Path.GetFileNameWithoutExtension(this.FileName).ToLower();
|
||||
var medium = bcastNode.GetAttribute("medium");
|
||||
if (medium == "" && fname.Length == 4 && fname.StartsWith("dvb"))
|
||||
medium = fname;
|
||||
bool hasEncrypt = false;
|
||||
|
||||
if (setupNode.HasAttribute("ChannelName"))
|
||||
{
|
||||
this.formatVersion = 1;
|
||||
this.DataRoot.SupportedFavorites = Favorites.A;
|
||||
this.DataRoot.SortedFavorites = true;
|
||||
|
||||
var dtype = bcastNode.GetAttribute("DecoderType");
|
||||
if (dtype == "1")
|
||||
medium = "dvbt";
|
||||
else if (dtype == "2")
|
||||
medium = "dvbc";
|
||||
else if (dtype == "3")
|
||||
medium = "dvbs";
|
||||
|
||||
hasEncrypt = setupNode.HasAttribute("Scrambled");
|
||||
}
|
||||
else if (setupNode.HasAttribute("name"))
|
||||
{
|
||||
this.formatVersion = 2;
|
||||
this.DataRoot.SupportedFavorites = 0;
|
||||
this.DataRoot.SortedFavorites = false;
|
||||
foreach (var list in this.DataRoot.ChannelLists)
|
||||
{
|
||||
list.VisibleColumnFieldNames.Remove("Favorites");
|
||||
list.VisibleColumnFieldNames.Remove("Lock");
|
||||
list.VisibleColumnFieldNames.Remove("Hidden");
|
||||
list.VisibleColumnFieldNames.Remove("ServiceType");
|
||||
list.VisibleColumnFieldNames.Remove("ServiceTypeName");
|
||||
list.VisibleColumnFieldNames.Remove("Encrypted");
|
||||
}
|
||||
}
|
||||
else
|
||||
throw new FileLoadException("Unknown data format");
|
||||
|
||||
switch (medium)
|
||||
{
|
||||
case "dvbt":
|
||||
this.curList = this.terrChannels;
|
||||
break;
|
||||
case "dvbc":
|
||||
this.curList = this.cableChannels;
|
||||
break;
|
||||
case "dvbs":
|
||||
this.curList = this.satChannels;
|
||||
break;
|
||||
default:
|
||||
this.curList = null;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!hasEncrypt)
|
||||
this.curList?.VisibleColumnFieldNames.Remove("Encrypted");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ReadChannel()
|
||||
private void ReadChannel(XmlNode node, int rowId)
|
||||
{
|
||||
var setupNode = node["Setup"] ?? throw new FileLoadException("Missing Setup XML element");
|
||||
var bcastNode = node["Broadcast"] ?? throw new FileLoadException("Missing Broadcast XML element");
|
||||
var data = new Dictionary<string,string>(StringComparer.InvariantCultureIgnoreCase);
|
||||
foreach (var n in new[] {setupNode, bcastNode})
|
||||
{
|
||||
foreach(XmlAttribute attr in n.Attributes)
|
||||
data.Add(attr.LocalName, attr.Value);
|
||||
}
|
||||
|
||||
var chan = new Channel(this.curList.SignalSource, rowId, rowId, setupNode);
|
||||
chan.OldProgramNr = -1;
|
||||
chan.IsDeleted = false;
|
||||
if (this.formatVersion == 1)
|
||||
this.ParseChannelFormat1(data, chan);
|
||||
else if (this.formatVersion == 2)
|
||||
this.ParseChannelFormat2(data, chan);
|
||||
|
||||
if ((chan.SignalSource & SignalSource.MaskAdInput) == SignalSource.DvbT)
|
||||
chan.ChannelOrTransponder = LookupData.Instance.GetDvbtTransponder(chan.FreqInMhz).ToString();
|
||||
else if ((chan.SignalSource & SignalSource.MaskAdInput) == SignalSource.DvbC)
|
||||
chan.ChannelOrTransponder = LookupData.Instance.GetDvbcChannelName(chan.FreqInMhz);
|
||||
|
||||
DataRoot.AddChannel(this.curList, chan);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ParseChannelFormat1
|
||||
private void ParseChannelFormat1(Dictionary<string,string> data, Channel chan)
|
||||
{
|
||||
chan.RawSatellite = data.TryGet("SatelliteName");
|
||||
chan.Satellite = DecodeName(chan.RawSatellite);
|
||||
chan.OldProgramNr = ParseInt(data.TryGet("ChannelNumber"));
|
||||
chan.RawName = data.TryGet("ChannelName");
|
||||
chan.Name = DecodeName(chan.RawName);
|
||||
chan.Lock = data.TryGet("ChannelLock") == "1";
|
||||
chan.Hidden = data.TryGet("UserHidden") == "1";
|
||||
var fav = ParseInt(data.TryGet("FavoriteNumber"));
|
||||
chan.FavIndex[0] = fav == 0 ? -1 : fav;
|
||||
chan.OriginalNetworkId = ParseInt(data.TryGet("Onid"));
|
||||
chan.TransportStreamId = ParseInt(data.TryGet("Tsid"));
|
||||
chan.ServiceId = ParseInt(data.TryGet("Sid"));
|
||||
var freq = ParseInt(data.TryGet("Frequency"));
|
||||
chan.FreqInMhz = freq;
|
||||
chan.ServiceType = ParseInt(data.TryGet("ServiceType"));
|
||||
chan.SignalSource |= LookupData.Instance.IsRadioOrTv(chan.ServiceType);
|
||||
chan.SymbolRate = ParseInt(data.TryGet("SymbolRate"));
|
||||
if (data.TryGetValue("Polarization", out var pol))
|
||||
chan.Polarity = pol == "0" ? 'H' : 'V';
|
||||
chan.Hidden |= data.TryGet("SystemHidden") == "1";
|
||||
|
||||
chan.Encrypted = data.TryGet("Scrambled") == "1"; // doesn't exist in all format versions
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ParseChannelFormat2
|
||||
private void ParseChannelFormat2(Dictionary<string, string> data, Channel chan)
|
||||
{
|
||||
chan.OldProgramNr = ParseInt(data.TryGet("presetnumber"));
|
||||
chan.Name = data.TryGet("name");
|
||||
chan.RawName = chan.Name;
|
||||
chan.FreqInMhz = ParseInt(data.TryGet("frequency"));
|
||||
if (chan.FreqInMhz > 100000)
|
||||
chan.FreqInMhz /= 1000;
|
||||
chan.ServiceId = ParseInt(data.TryGet("serviceID"));
|
||||
chan.OriginalNetworkId = ParseInt(data.TryGet("ONID"));
|
||||
chan.TransportStreamId = ParseInt(data.TryGet("TSID"));
|
||||
chan.ServiceType = ParseInt(data.TryGet("serviceType"));
|
||||
chan.SymbolRate = ParseInt(data.TryGet("symbolrate")) / 1000;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ParseInt()
|
||||
private int ParseInt(string input)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
return 0;
|
||||
if (input.Length > 2 && input[0] == '0' && char.ToLower(input[1]) == 'x')
|
||||
return int.Parse(input.Substring(2), NumberStyles.HexNumber);
|
||||
if (int.TryParse(input, out var value))
|
||||
return value;
|
||||
return 0;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region DecodeName()
|
||||
private string DecodeName(string input)
|
||||
{
|
||||
if (input == null || !input.StartsWith("0x")) // fallback for unknown input
|
||||
return input;
|
||||
|
||||
var hexParts = input.Split(' ');
|
||||
var buffer = new MemoryStream();
|
||||
|
||||
foreach (var part in hexParts)
|
||||
{
|
||||
if (part == "" || part == "0x00")
|
||||
continue;
|
||||
buffer.WriteByte((byte)ParseInt(part));
|
||||
}
|
||||
|
||||
return this.DefaultEncoding.GetString(buffer.GetBuffer(), 0, (int)buffer.Length);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region DefaultEncoding
|
||||
public override Encoding DefaultEncoding
|
||||
{
|
||||
get => base.DefaultEncoding;
|
||||
set
|
||||
{
|
||||
if (value == this.DefaultEncoding)
|
||||
return;
|
||||
base.DefaultEncoding = value;
|
||||
this.ChangeEncoding();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ChangeEncoding
|
||||
private void ChangeEncoding()
|
||||
{
|
||||
foreach (var list in this.DataRoot.ChannelLists)
|
||||
{
|
||||
foreach (var channel in list.Channels)
|
||||
{
|
||||
if (!(channel is Channel ch))
|
||||
continue;
|
||||
ch.Name = this.DecodeName(ch.RawName);
|
||||
ch.Satellite = this.DecodeName(ch.RawSatellite);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Save()
|
||||
public override void Save(string tvOutputFile)
|
||||
{
|
||||
foreach (var list in this.DataRoot.ChannelLists)
|
||||
this.UpdateChannelList(list);
|
||||
|
||||
// by default .NET reformats the whole XML. These settings produce almost same format as the TV xml files use
|
||||
var xmlSettings = new XmlWriterSettings();
|
||||
xmlSettings.Encoding = this.DefaultEncoding;
|
||||
xmlSettings.CheckCharacters = false;
|
||||
xmlSettings.Indent = true;
|
||||
xmlSettings.IndentChars = "";
|
||||
xmlSettings.NewLineHandling = NewLineHandling.None;
|
||||
xmlSettings.NewLineChars = this.newline;
|
||||
xmlSettings.OmitXmlDeclaration = false;
|
||||
|
||||
string xml;
|
||||
using (var sw = new StringWriter())
|
||||
using (var w = new CustomXmlWriter(sw, xmlSettings, false))
|
||||
{
|
||||
this.doc.WriteTo(w);
|
||||
w.Flush();
|
||||
xml = sw.ToString();
|
||||
}
|
||||
|
||||
var enc = new UTF8Encoding(false, false);
|
||||
File.WriteAllText(tvOutputFile, 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 || ch.NewProgramNr < 0)
|
||||
{
|
||||
ch.SetupNode.ParentNode.ParentNode.RemoveChild(ch.SetupNode.ParentNode);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.formatVersion == 1)
|
||||
this.UpdateChannelFormat1(ch);
|
||||
else if (this.formatVersion == 2)
|
||||
this.UpdateChannelFormat2(ch);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UpdateChannelFormat1 and 2
|
||||
private void UpdateChannelFormat1(Channel ch)
|
||||
{
|
||||
ch.SetupNode.Attributes["ChannelNumber"].Value = ch.NewProgramNr.ToString();
|
||||
if (ch.IsNameModified)
|
||||
ch.SetupNode.Attributes["ChannelName"].Value = EncodeName(ch.Name);
|
||||
ch.SetupNode.Attributes["FavoriteNumber"].Value = Math.Max(ch.FavIndex[0], 0).ToString();
|
||||
}
|
||||
|
||||
private void UpdateChannelFormat2(Channel ch)
|
||||
{
|
||||
ch.SetupNode.Attributes["presetnumber"].Value = ch.NewProgramNr.ToString();
|
||||
if (ch.IsNameModified)
|
||||
ch.SetupNode.Attributes["name"].Value = ch.Name;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeName
|
||||
private string EncodeName(string name)
|
||||
{
|
||||
var bytes = this.DefaultEncoding.GetBytes(name);
|
||||
var sb = new StringBuilder();
|
||||
foreach (var b in bytes)
|
||||
sb.Append($"0x{b:X2} 0x00 ");
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
16
source/ChanSort.Loader.PhilipsXml/SerializerPlugin.cs
Normal file
16
source/ChanSort.Loader.PhilipsXml/SerializerPlugin.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using ChanSort.Api;
|
||||
|
||||
namespace ChanSort.Loader.PhilipsXml
|
||||
{
|
||||
public class SerializerPlugin : ISerializerPlugin
|
||||
{
|
||||
public string DllName { get; set; }
|
||||
public string PluginName => "Philips .xml";
|
||||
public string FileFilter => "*.xml";
|
||||
|
||||
public SerializerBase CreateSerializer(string inputFile)
|
||||
{
|
||||
return new Serializer(inputFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ namespace ChanSort.Loader.Sony
|
||||
|
||||
private const string SupportedFormatVersions = " e1.1.0 1.0.0 1.1.0 1.2.0 ";
|
||||
|
||||
private readonly ChannelList terrChannels = new ChannelList(SignalSource.DvbC | SignalSource.Tv | SignalSource.Radio, "DVB-T");
|
||||
private readonly ChannelList terrChannels = new ChannelList(SignalSource.DvbT | SignalSource.Tv | SignalSource.Radio, "DVB-T");
|
||||
private readonly ChannelList cableChannels = new ChannelList(SignalSource.DvbC | SignalSource.Tv | SignalSource.Radio, "DVB-C");
|
||||
private readonly ChannelList satChannels = new ChannelList(SignalSource.DvbS | SignalSource.Tv | SignalSource.Radio, "DVB-S");
|
||||
private readonly ChannelList satChannelsP = new ChannelList(SignalSource.DvbS | SignalSource.Tv | SignalSource.Radio, "DVB-S Preset");
|
||||
|
||||
@@ -52,6 +52,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChanSort.Loader.SilvaSchnei
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChanSort.Loader.Sony", "ChanSort.Loader.Sony\ChanSort.Loader.Sony.csproj", "{70E29C6B-B926-4859-9548-23375BF1E1B5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChanSort.Loader.PhilipsXml", "ChanSort.Loader.PhilipsXml\ChanSort.Loader.PhilipsXml.csproj", "{D7BAFD55-50F5-46C3-A76B-2193BED5358F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -254,6 +256,18 @@ Global
|
||||
{70E29C6B-B926-4859-9548-23375BF1E1B5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{70E29C6B-B926-4859-9548-23375BF1E1B5}.Release|x86.ActiveCfg = Release|x86
|
||||
{70E29C6B-B926-4859-9548-23375BF1E1B5}.Release|x86.Build.0 = Release|x86
|
||||
{D7BAFD55-50F5-46C3-A76B-2193BED5358F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D7BAFD55-50F5-46C3-A76B-2193BED5358F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D7BAFD55-50F5-46C3-A76B-2193BED5358F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{D7BAFD55-50F5-46C3-A76B-2193BED5358F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{D7BAFD55-50F5-46C3-A76B-2193BED5358F}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{D7BAFD55-50F5-46C3-A76B-2193BED5358F}.Debug|x86.Build.0 = Debug|x86
|
||||
{D7BAFD55-50F5-46C3-A76B-2193BED5358F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D7BAFD55-50F5-46C3-A76B-2193BED5358F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D7BAFD55-50F5-46C3-A76B-2193BED5358F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{D7BAFD55-50F5-46C3-A76B-2193BED5358F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{D7BAFD55-50F5-46C3-A76B-2193BED5358F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D7BAFD55-50F5-46C3-A76B-2193BED5358F}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -386,6 +386,10 @@
|
||||
<Project>{68da8072-3a29-4076-9f64-d66f38349585}</Project>
|
||||
<Name>ChanSort.Loader.Panasonic</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\ChanSort.Loader.PhilipsXml\ChanSort.Loader.PhilipsXml.csproj">
|
||||
<Project>{d7bafd55-50f5-46c3-a76b-2193bed5358f}</Project>
|
||||
<Name>ChanSort.Loader.PhilipsXml</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\ChanSort.Loader.SamsungJ\ChanSort.Loader.SamsungJ.csproj">
|
||||
<Project>{33897002-0537-49a4-b963-a18d17311b3d}</Project>
|
||||
<Name>ChanSort.Loader.SamsungJ</Name>
|
||||
|
||||
31
source/ChanSort/MainForm.Designer.cs
generated
31
source/ChanSort/MainForm.Designer.cs
generated
@@ -161,6 +161,7 @@
|
||||
this.miShowWarningsAfterLoad = new DevExpress.XtraBars.BarCheckItem();
|
||||
this.miAllowEditPredefinedLists = new DevExpress.XtraBars.BarButtonItem();
|
||||
this.miExplorerIntegration = new DevExpress.XtraBars.BarButtonItem();
|
||||
this.miCheckUpdates = new DevExpress.XtraBars.BarButtonItem();
|
||||
this.mnuAccessibility = new DevExpress.XtraBars.BarSubItem();
|
||||
this.mnuGotoChannelList = new DevExpress.XtraBars.BarSubItem();
|
||||
this.mnuInputSource = new DevExpress.XtraBars.BarLinkContainerItem();
|
||||
@@ -206,7 +207,7 @@
|
||||
this.pageProgNr = new DevExpress.XtraTab.XtraTabPage();
|
||||
this.popupInputSource = new DevExpress.XtraBars.PopupMenu(this.components);
|
||||
this.popupFavList = new DevExpress.XtraBars.PopupMenu(this.components);
|
||||
this.miCheckUpdates = new DevExpress.XtraBars.BarButtonItem();
|
||||
this.miUtf8Charset = new DevExpress.XtraBars.BarButtonItem();
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainerControl1)).BeginInit();
|
||||
this.splitContainerControl1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.grpOutputList)).BeginInit();
|
||||
@@ -1026,9 +1027,10 @@
|
||||
this.miCzech,
|
||||
this.miRomanian,
|
||||
this.miExplorerIntegration,
|
||||
this.miCheckUpdates});
|
||||
this.miCheckUpdates,
|
||||
this.miUtf8Charset});
|
||||
this.barManager1.MainMenu = this.bar1;
|
||||
this.barManager1.MaxItemId = 99;
|
||||
this.barManager1.MaxItemId = 100;
|
||||
this.barManager1.ShowFullMenus = true;
|
||||
//
|
||||
// bar1
|
||||
@@ -1608,7 +1610,8 @@
|
||||
this.mnuCharset.ImageOptions.ImageIndex = ((int)(resources.GetObject("mnuCharset.ImageOptions.ImageIndex")));
|
||||
this.mnuCharset.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] {
|
||||
new DevExpress.XtraBars.LinkPersistInfo(this.miCharsetForm),
|
||||
new DevExpress.XtraBars.LinkPersistInfo(this.miIsoCharSets, true)});
|
||||
new DevExpress.XtraBars.LinkPersistInfo(this.miUtf8Charset, true),
|
||||
new DevExpress.XtraBars.LinkPersistInfo(this.miIsoCharSets)});
|
||||
this.mnuCharset.Name = "mnuCharset";
|
||||
this.mnuCharset.PaintStyle = DevExpress.XtraBars.BarItemPaintStyle.CaptionInMenu;
|
||||
//
|
||||
@@ -1653,6 +1656,14 @@
|
||||
this.miExplorerIntegration.Name = "miExplorerIntegration";
|
||||
this.miExplorerIntegration.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miExplorerIntegration_ItemClick);
|
||||
//
|
||||
// miCheckUpdates
|
||||
//
|
||||
this.miCheckUpdates.ButtonStyle = DevExpress.XtraBars.BarButtonStyle.Check;
|
||||
resources.ApplyResources(this.miCheckUpdates, "miCheckUpdates");
|
||||
this.miCheckUpdates.Id = 98;
|
||||
this.miCheckUpdates.Name = "miCheckUpdates";
|
||||
this.miCheckUpdates.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miCheckUpdates_ItemClick);
|
||||
//
|
||||
// mnuAccessibility
|
||||
//
|
||||
resources.ApplyResources(this.mnuAccessibility, "mnuAccessibility");
|
||||
@@ -2055,13 +2066,12 @@
|
||||
this.popupFavList.Name = "popupFavList";
|
||||
this.popupFavList.ShowCaption = true;
|
||||
//
|
||||
// miCheckUpdates
|
||||
// miUtf8Charset
|
||||
//
|
||||
this.miCheckUpdates.ButtonStyle = DevExpress.XtraBars.BarButtonStyle.Check;
|
||||
resources.ApplyResources(this.miCheckUpdates, "miCheckUpdates");
|
||||
this.miCheckUpdates.Id = 98;
|
||||
this.miCheckUpdates.Name = "miCheckUpdates";
|
||||
this.miCheckUpdates.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miCheckUpdates_ItemClick);
|
||||
resources.ApplyResources(this.miUtf8Charset, "miUtf8Charset");
|
||||
this.miUtf8Charset.Id = 99;
|
||||
this.miUtf8Charset.Name = "miUtf8Charset";
|
||||
this.miUtf8Charset.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.MiUtf8Charset_ItemClick);
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
@@ -2304,6 +2314,7 @@
|
||||
private DevExpress.XtraGrid.Columns.GridColumn colPcrPid;
|
||||
private DevExpress.XtraBars.BarButtonItem miExplorerIntegration;
|
||||
private DevExpress.XtraBars.BarButtonItem miCheckUpdates;
|
||||
private DevExpress.XtraBars.BarButtonItem miUtf8Charset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -412,6 +412,9 @@ namespace ChanSort.Ui
|
||||
|
||||
private void UpdateFavoritesEditor(Favorites favorites)
|
||||
{
|
||||
var miSet = new[] {this.miFavASet, this.miFavBSet, this.miFavCSet, this.miFavDSet, this.miFavESet};
|
||||
var miUnset = new[] { this.miFavAUnset, this.miFavBUnset, this.miFavCUnset, this.miFavDUnset, this.miFavEUnset };
|
||||
|
||||
this.repositoryItemCheckedComboBoxEdit1.Items.Clear();
|
||||
this.repositoryItemCheckedComboBoxEdit2.Items.Clear();
|
||||
byte mask = 0x01;
|
||||
@@ -424,9 +427,16 @@ namespace ChanSort.Ui
|
||||
var c = (char) ('A' + bit);
|
||||
this.repositoryItemCheckedComboBoxEdit1.Items.Add(c);
|
||||
this.repositoryItemCheckedComboBoxEdit2.Items.Add(c);
|
||||
miSet[bit].Visibility = BarItemVisibility.Always;
|
||||
miUnset[bit].Visibility = BarItemVisibility.Always;
|
||||
regex += c;
|
||||
++favCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
miSet[bit].Visibility = BarItemVisibility.Never;
|
||||
miUnset[bit].Visibility = BarItemVisibility.Never;
|
||||
}
|
||||
}
|
||||
regex += "]*";
|
||||
this.repositoryItemCheckedComboBoxEdit1.Mask.EditMask = regex;
|
||||
@@ -1257,8 +1267,8 @@ namespace ChanSort.Ui
|
||||
this.cbCloseGap.Checked = Config.Default.CloseGaps;
|
||||
this.ClearLeftFilter();
|
||||
this.ClearRightFilter();
|
||||
foreach(var path in Config.Default.MruFiles)
|
||||
this.AddFileToMruList(path);
|
||||
this.mruFiles.Clear();
|
||||
this.mruFiles.AddRange(Config.Default.MruFiles);
|
||||
this.UpdateMruMenu();
|
||||
|
||||
this.miExplorerIntegration.Down = Config.Default.ExplorerIntegration;
|
||||
@@ -2872,6 +2882,11 @@ namespace ChanSort.Ui
|
||||
|
||||
#region Character set menu
|
||||
|
||||
private void MiUtf8Charset_ItemClick(object sender, ItemClickEventArgs e)
|
||||
{
|
||||
TryExecute(() => this.SetDefaultEncoding(Encoding.UTF8));
|
||||
}
|
||||
|
||||
private void miIsoCharSets_ListItemClick(object sender, ListItemClickEventArgs e)
|
||||
{
|
||||
TryExecute(() => this.SetDefaultEncoding(Encoding.GetEncoding(this.isoEncodings[e.Index])));
|
||||
|
||||
@@ -647,6 +647,9 @@
|
||||
<data name="miCharsetForm.ImageOptions.ImageIndex" type="System.Int32, mscorlib">
|
||||
<value>9</value>
|
||||
</data>
|
||||
<data name="miUtf8Charset.Caption" xml:space="preserve">
|
||||
<value>UTF-8 (Unicode)</value>
|
||||
</data>
|
||||
<data name="miIsoCharSets.Caption" xml:space="preserve">
|
||||
<value>ISO character sets</value>
|
||||
</data>
|
||||
@@ -1255,7 +1258,7 @@
|
||||
<value>globalImageCollection1</value>
|
||||
</data>
|
||||
<data name=">>globalImageCollection1.Type" xml:space="preserve">
|
||||
<value>ChanSort.Ui.GlobalImageCollection, ChanSort, Version=1.0.7134.23381, Culture=neutral, PublicKeyToken=null</value>
|
||||
<value>ChanSort.Ui.GlobalImageCollection, ChanSort, Version=1.0.7156.40088, Culture=neutral, PublicKeyToken=null</value>
|
||||
</data>
|
||||
<data name=">>gviewRight.Name" xml:space="preserve">
|
||||
<value>gviewRight</value>
|
||||
@@ -1809,6 +1812,12 @@
|
||||
<data name=">>miExplorerIntegration.Type" xml:space="preserve">
|
||||
<value>DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v19.1, Version=19.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
|
||||
</data>
|
||||
<data name=">>miCheckUpdates.Name" xml:space="preserve">
|
||||
<value>miCheckUpdates</value>
|
||||
</data>
|
||||
<data name=">>miCheckUpdates.Type" xml:space="preserve">
|
||||
<value>DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v19.1, Version=19.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
|
||||
</data>
|
||||
<data name=">>mnuAccessibility.Name" xml:space="preserve">
|
||||
<value>mnuAccessibility</value>
|
||||
</data>
|
||||
@@ -1971,10 +1980,10 @@
|
||||
<data name=">>popupFavList.Type" xml:space="preserve">
|
||||
<value>DevExpress.XtraBars.PopupMenu, DevExpress.XtraBars.v19.1, Version=19.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
|
||||
</data>
|
||||
<data name=">>miCheckUpdates.Name" xml:space="preserve">
|
||||
<value>miCheckUpdates</value>
|
||||
<data name=">>miUtf8Charset.Name" xml:space="preserve">
|
||||
<value>miUtf8Charset</value>
|
||||
</data>
|
||||
<data name=">>miCheckUpdates.Type" xml:space="preserve">
|
||||
<data name=">>miUtf8Charset.Type" xml:space="preserve">
|
||||
<value>DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v19.1, Version=19.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
|
||||
</data>
|
||||
<data name=">>$this.Name" xml:space="preserve">
|
||||
@@ -1984,7 +1993,7 @@
|
||||
<value>DevExpress.XtraEditors.XtraForm, DevExpress.Utils.v19.1, Version=19.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
|
||||
</data>
|
||||
<data name="SharedImageCollection.Timestamp" type="System.DateTime, mscorlib">
|
||||
<value>07/14/2019 13:16:32</value>
|
||||
<value>08/05/2019 22:23:17</value>
|
||||
</data>
|
||||
<data name="SharedImageCollection.ImageSize" type="System.Drawing.Size, System.Drawing">
|
||||
<value>16, 16</value>
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
ChanSort Change Log
|
||||
===================
|
||||
|
||||
2019-08-05
|
||||
- added partial support for Philips .xml channel lists
|
||||
(There are MANY different file formats, only a few are currently supported)
|
||||
- fixed "most-recently-used" getting reversed every time the program was started
|
||||
- added "UTF-8 (Unicode)" character set to menu
|
||||
- fixed disappearing columns when loading different channel lists without restarting the application
|
||||
|
||||
2019-07-25
|
||||
- fix: Application failed to save config and didn't exit when the folder %LOCALAPPDATA%\ChanSort doesn't exist
|
||||
|
||||
|
||||
Reference in New Issue
Block a user