diff --git a/source/ChanSort.Api/Controller/SerializerBase.cs b/source/ChanSort.Api/Controller/SerializerBase.cs
index 37dacae7..dcb3347c 100644
--- a/source/ChanSort.Api/Controller/SerializerBase.cs
+++ b/source/ChanSort.Api/Controller/SerializerBase.cs
@@ -38,6 +38,8 @@ public class SupportedFeatures
public bool MixedSourceFavorites { get; set; }
public bool AllowGapsInFavNumbers { get; set; }
public bool CanEditFavListNames { get; set; }
+
+ public bool CanEditAudioPid { get; set; }
}
#endregion
diff --git a/source/ChanSort.Loader.GlobalClone/GcJsonSerializer.cs b/source/ChanSort.Loader.GlobalClone/GcJsonSerializer.cs
index 95cef61b..8656b7e4 100644
--- a/source/ChanSort.Loader.GlobalClone/GcJsonSerializer.cs
+++ b/source/ChanSort.Loader.GlobalClone/GcJsonSerializer.cs
@@ -31,6 +31,7 @@ public GcJsonSerializer(string filename, string content) : base(filename)
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 @@ public override void Load()
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 @@ private void UpdateJsonDoc()
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 @@ private void UpdateJsonDoc()
//}
//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;
}
}
diff --git a/source/ChanSort.Loader.Grundig/ChanSort.Loader.Grundig.csproj b/source/ChanSort.Loader.Grundig/ChanSort.Loader.Grundig.csproj
new file mode 100644
index 00000000..b30266b0
--- /dev/null
+++ b/source/ChanSort.Loader.Grundig/ChanSort.Loader.Grundig.csproj
@@ -0,0 +1,76 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {4D5AF0A3-1B96-42C8-910D-0C4852EA22F4}
+ Library
+ Properties
+ ChanSort.Loader.Grundig
+ ChanSort.Loader.Grundig
+ v4.8
+ 512
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ latest
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ latest
+
+
+ true
+ ..\Debug\
+ DEBUG;TRACE
+ full
+ x86
+ latest
+ prompt
+
+
+ bin\x86\Release\
+ TRACE
+ true
+ pdbonly
+ x86
+ latest
+ prompt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {dccffa08-472b-4d17-bb90-8f513fc01392}
+ ChanSort.Api
+
+
+
+
\ No newline at end of file
diff --git a/source/ChanSort.Loader.Grundig/Channel.cs b/source/ChanSort.Loader.Grundig/Channel.cs
new file mode 100644
index 00000000..10706082
--- /dev/null
+++ b/source/ChanSort.Loader.Grundig/Channel.cs
@@ -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;
+ }
+ }
+}
diff --git a/source/ChanSort.Loader.Grundig/Properties/AssemblyInfo.cs b/source/ChanSort.Loader.Grundig/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..98e4602b
--- /dev/null
+++ b/source/ChanSort.Loader.Grundig/Properties/AssemblyInfo.cs
@@ -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")]
diff --git a/source/ChanSort.Loader.Grundig/Serializer.cs b/source/ChanSort.Loader.Grundig/Serializer.cs
new file mode 100644
index 00000000..b4b84ce5
--- /dev/null
+++ b/source/ChanSort.Loader.Grundig/Serializer.cs
@@ -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 fileDataList = new List();
+ 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 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
+ }
+}
diff --git a/source/ChanSort.Loader.Grundig/SerializerPlugin.cs b/source/ChanSort.Loader.Grundig/SerializerPlugin.cs
new file mode 100644
index 00000000..cdc2f676
--- /dev/null
+++ b/source/ChanSort.Loader.Grundig/SerializerPlugin.cs
@@ -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);
+ }
+ }
+}
diff --git a/source/ChanSort.sln b/source/ChanSort.sln
index 77363684..68d62bd9 100644
--- a/source/ChanSort.sln
+++ b/source/ChanSort.sln
@@ -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
diff --git a/source/ChanSort/MainForm.cs b/source/ChanSort/MainForm.cs
index 4afb5779..d1aa2d30 100644
--- a/source/ChanSort/MainForm.cs
+++ b/source/ChanSort/MainForm.cs
@@ -310,6 +310,7 @@ private void LoadFiles(ISerializerPlugin plugin, string tvDataFile)
//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 @@ private void RestoreBackupFile()
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);
}
-
- 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);
+ 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);
}
#endregion
diff --git a/source/ChanSort/UpdateCheck.cs b/source/ChanSort/UpdateCheck.cs
index 381b1908..c764ef4e 100644
--- a/source/ChanSort/UpdateCheck.cs
+++ b/source/ChanSort/UpdateCheck.cs
@@ -52,7 +52,7 @@ private string GetLatestVersion()
{
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;
diff --git a/source/changelog.md b/source/changelog.md
index e679a57c..5ff8e750 100644
--- a/source/changelog.md
+++ b/source/changelog.md
@@ -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")