diff --git a/source/ChanSort.Api/Model/ChannelList.cs b/source/ChanSort.Api/Model/ChannelList.cs index 3dc73cf..b94fea4 100644 --- a/source/ChanSort.Api/Model/ChannelList.cs +++ b/source/ChanSort.Api/Model/ChannelList.cs @@ -148,7 +148,7 @@ namespace ChanSort.Api #region GetChannelsByNewOrder() public IList GetChannelsByNewOrder() { - return this.Channels.OrderBy(c => c.NewProgramNr).ToList(); + return this.Channels.OrderBy(c => c.NewProgramNr).ToList(); } #endregion diff --git a/source/ChanSort.Loader.SamsungJ/Properties/AssemblyInfo.cs b/source/ChanSort.Loader.SamsungJ/Properties/AssemblyInfo.cs index b54eaf9..3b54e92 100644 --- a/source/ChanSort.Loader.SamsungJ/Properties/AssemblyInfo.cs +++ b/source/ChanSort.Loader.SamsungJ/Properties/AssemblyInfo.cs @@ -5,11 +5,11 @@ 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("CahSort.Loader.SamsungJ")] +[assembly: AssemblyTitle("ChanSort.Loader.SamsungJ")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("CahSort.Loader.SamsungJ")] +[assembly: AssemblyProduct("ChanSort.Loader.SamsungJ")] [assembly: AssemblyCopyright("Copyright © 2015")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/source/ChanSort.Loader.SilvaSchneider/ChanSort.Loader.SilvaSchneider.csproj b/source/ChanSort.Loader.SilvaSchneider/ChanSort.Loader.SilvaSchneider.csproj new file mode 100644 index 0000000..e18f301 --- /dev/null +++ b/source/ChanSort.Loader.SilvaSchneider/ChanSort.Loader.SilvaSchneider.csproj @@ -0,0 +1,85 @@ + + + + + Debug + AnyCPU + {E6279FF8-362A-41E6-AC0D-D0861D43F01C} + Library + Properties + ChanSort.Loader.SilvaSchneider + ChanSort.Loader.SilvaSchneider + v4.0 + 512 + Client + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + true + ..\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + false + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + false + + + + + + + + + + + + + + + + + + + + {dccffa08-472b-4d17-bb90-8f513fc01392} + ChanSort.Api + + + + + \ No newline at end of file diff --git a/source/ChanSort.Loader.SilvaSchneider/Channels.cs b/source/ChanSort.Loader.SilvaSchneider/Channels.cs new file mode 100644 index 0000000..f8d64da --- /dev/null +++ b/source/ChanSort.Loader.SilvaSchneider/Channels.cs @@ -0,0 +1,64 @@ +using System; +using System.Globalization; +using System.IO; +using ChanSort.Api; + +namespace ChanSort.Loader.SilvaSchneider +{ + internal class Channels : ChannelInfo + { + public int FileOffset { get; } + public int Length { get; } + + #region ctor() + + internal Channels(int pos, string line, byte[] data, int start, int length, DvbStringDecoder decoder) + { + this.FileOffset = start; + this.Length = length; + this.RecordIndex = pos; + this.RecordOrder = this.OldProgramNr = pos + 1; + + if (!line.StartsWith("SATCODX")) + throw new FileLoadException("Only SAT channels are supported"); + if (line.Length < 106) + throw new FileLoadException("Unrecognized channel format"); + + this.Satellite = line.Substring(10, 18); + + var type = line[28]; + this.SignalSource = SignalSource.Digital | SignalSource.Sat | (type == 'T' ? SignalSource.Tv : type == 'R' ? SignalSource.Radio : 0); + this.ServiceType = type == 'T' ? 1 : type == 'R' ? 2 : 0; // 1=SD-TV, 2=Radio + + if (int.TryParse(line.Substring(34, 5), out var mhz)) + this.FreqInMhz = mhz; + + this.Polarity = line[39] == '1' ? 'H' : 'V'; + + byte[] nameBytes = new byte[8+17]; + var nameLen2 = Math.Min(length - 115, 17); // version 103 has 12 extra bytes for channel name, version 105 has 17 + Array.Copy(data, start + 43, nameBytes, 0, 8); + Array.Copy(data, start + 115, nameBytes, 8, nameLen2); + decoder.GetChannelNames(nameBytes,0, nameBytes.Length, out var longName, out var shortName); + this.Name = longName.TrimEnd(); + this.ShortName = shortName.TrimEnd(); + + var spos = line.Substring(51, 4).TrimStart('0'); + this.SatPosition = spos.Substring(0, spos.Length - 1) + CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator + spos.Substring(spos.Length - 1); + + if (int.TryParse(line.Substring(69, 5), out var symrate)) + this.SymbolRate = symrate; + + if (int.TryParse(line.Substring(87, 5), out var sid)) + this.ServiceId = sid; + + if (int.TryParse(line.Substring(92, 5), out var onid)) + this.OriginalNetworkId = onid; + + if (int.TryParse(line.Substring(97, 5), out var tsid)) + this.TransportStreamId = tsid; + } + + #endregion + } +} \ No newline at end of file diff --git a/source/ChanSort.Loader.SilvaSchneider/Properties/AssemblyInfo.cs b/source/ChanSort.Loader.SilvaSchneider/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..deae951 --- /dev/null +++ b/source/ChanSort.Loader.SilvaSchneider/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.SilvaSchneider")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ChanSort.Loader.SilvaSchneider")] +[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("FAEFA732-0096-45AE-97ED-DBE40764DA15")] + +// 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.SilvaSchneider/Serializer.cs b/source/ChanSort.Loader.SilvaSchneider/Serializer.cs new file mode 100644 index 0000000..2933456 --- /dev/null +++ b/source/ChanSort.Loader.SilvaSchneider/Serializer.cs @@ -0,0 +1,99 @@ +using System; +using System.IO; +using System.Text; +using ChanSort.Api; + +namespace ChanSort.Loader.SilvaSchneider +{ + internal class Serializer : SerializerBase + { + private readonly ChannelList allChannels = new ChannelList(SignalSource.DvbT | SignalSource.DvbC | SignalSource.DvbS | SignalSource.AnalogC | SignalSource.AnalogT | SignalSource.Tv | SignalSource.Radio, "All"); + + private byte[] content; + + #region ctor() + + public Serializer(string inputFile) : base(inputFile) + { + this.Features.ChannelNameEdit = ChannelNameEditMode.None; + this.DataRoot.SortedFavorites = false; + this.DataRoot.SupportedFavorites = 0; + + this.DataRoot.AddChannelList(this.allChannels); + + // hide columns for fields that don't exist in Silva-Schneider channel list + foreach (var list in this.DataRoot.ChannelLists) + { + list.VisibleColumnFieldNames.Remove("PcrPid"); + list.VisibleColumnFieldNames.Remove("VideoPid"); + list.VisibleColumnFieldNames.Remove("AudioPid"); + list.VisibleColumnFieldNames.Remove("Lock"); + list.VisibleColumnFieldNames.Remove("Skip"); + list.VisibleColumnFieldNames.Remove("Hidden"); + list.VisibleColumnFieldNames.Remove("Encrypted"); + list.VisibleColumnFieldNames.Remove("Favorites"); + } + } + + #endregion + + public override string DisplayName => "Silva Schneider *.sdx Loader"; + + #region Load() + + public override void Load() + { + var decoder = new DvbStringDecoder(this.DefaultEncoding); + + var pos = 0; + content = File.ReadAllBytes(this.FileName); + int prevPos = 0, nextPos; + while (prevPos < content.Length && (nextPos = Array.FindIndex(content, prevPos, ch => ch == (byte)'\n')) >= 0) + { + if (nextPos - prevPos == 0) + continue; + string line = Encoding.ASCII.GetString(content, prevPos, nextPos-prevPos); + ChannelInfo channel = new Channels(pos, line, content, prevPos, nextPos-prevPos, decoder); + this.DataRoot.AddChannel(this.allChannels, channel); + pos++; + prevPos = nextPos + 1; + } + } + + #endregion + + #region Save() + + public override void Save(string tvOutputFile) + { + if (tvOutputFile != this.FileName) + { + File.Copy(this.FileName, tvOutputFile); + this.FileName = tvOutputFile; + } + + using (var file = new FileStream(tvOutputFile, FileMode.Create)) + { + foreach (var channel in this.allChannels.GetChannelsByNewOrder()) + { + // when a reference list was applied, the list may contain proxy entries for deleted channels, which must be ignored + if (channel is Channels realChannel && channel.NewProgramNr >= 0) + file.Write(this.content, realChannel.FileOffset, realChannel.Length + 1); + } + } + } + + #endregion + + #region GetFileInformation() + + public override string GetFileInformation() + { + var sb = new StringBuilder(); + sb.Append(base.GetFileInformation()); + return sb.ToString(); + } + + #endregion + } +} \ No newline at end of file diff --git a/source/ChanSort.Loader.SilvaSchneider/SerializerPlugin.cs b/source/ChanSort.Loader.SilvaSchneider/SerializerPlugin.cs new file mode 100644 index 0000000..b275cb3 --- /dev/null +++ b/source/ChanSort.Loader.SilvaSchneider/SerializerPlugin.cs @@ -0,0 +1,16 @@ +using ChanSort.Api; + +namespace ChanSort.Loader.SilvaSchneider +{ + public class SerializerPlugin : ISerializerPlugin + { + public string DllName { get; set; } + public string PluginName { get { return "Silva Schneider"; } } + public string FileFilter { get { return "*.sdx"; } } + + public SerializerBase CreateSerializer(string inputFile) + { + return new Serializer(inputFile); + } + } +} diff --git a/source/ChanSort.sln b/source/ChanSort.sln index 7ef7e1b..2d85bca 100644 --- a/source/ChanSort.sln +++ b/source/ChanSort.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26228.4 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29025.244 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChanSort", "ChanSort\ChanSort.csproj", "{5FAFDABC-A52F-498C-BD2F-AFFC4119797A}" ProjectSection(ProjectDependencies) = postProject @@ -48,6 +48,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Loader.Samsung", "Test EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChanSort.Loader.Hisense2017", "ChanSort.Loader.Hisense2017\ChanSort.Loader.Hisense2017.csproj", "{9282E1DB-CD1F-400A-ACA1-17E0C4562ACF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChanSort.Loader.SilvaSchneider", "ChanSort.Loader.SilvaSchneider\ChanSort.Loader.SilvaSchneider.csproj", "{E6279FF8-362A-41E6-AC0D-D0861D43F01C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -226,8 +228,23 @@ Global {9282E1DB-CD1F-400A-ACA1-17E0C4562ACF}.Release|Mixed Platforms.Build.0 = Release|x86 {9282E1DB-CD1F-400A-ACA1-17E0C4562ACF}.Release|x86.ActiveCfg = Release|x86 {9282E1DB-CD1F-400A-ACA1-17E0C4562ACF}.Release|x86.Build.0 = Release|x86 + {E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Debug|x86.ActiveCfg = Debug|x86 + {E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Debug|x86.Build.0 = Debug|x86 + {E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Release|Any CPU.Build.0 = Release|Any CPU + {E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Release|x86.ActiveCfg = Release|Any CPU + {E6279FF8-362A-41E6-AC0D-D0861D43F01C}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {BBF1F6CB-9445-4F6C-A69A-15C4DA246814} + EndGlobalSection EndGlobal diff --git a/source/ChanSort/ChanSort.csproj b/source/ChanSort/ChanSort.csproj index adb9810..a52f098 100644 --- a/source/ChanSort/ChanSort.csproj +++ b/source/ChanSort/ChanSort.csproj @@ -392,6 +392,10 @@ {a1c9a98d-368a-44e8-9b7f-7eaca46c9ec5} ChanSort.Loader.Samsung + + {e6279ff8-362a-41e6-ac0d-d0861d43f01c} + ChanSort.Loader.SilvaSchneider + {f6f02792-07f1-48d5-9af3-f945ca5e3931} ChanSort.Loader.Toshiba diff --git a/source/ChanSort/MainForm.Designer.cs b/source/ChanSort/MainForm.Designer.cs index 10da80e..1da46e5 100644 --- a/source/ChanSort/MainForm.Designer.cs +++ b/source/ChanSort/MainForm.Designer.cs @@ -160,6 +160,7 @@ this.miIsoCharSets = new DevExpress.XtraBars.BarListItem(); this.miShowWarningsAfterLoad = new DevExpress.XtraBars.BarCheckItem(); this.miAllowEditPredefinedLists = new DevExpress.XtraBars.BarButtonItem(); + this.miExplorerIntegration = new DevExpress.XtraBars.BarButtonItem(); this.mnuAccessibility = new DevExpress.XtraBars.BarSubItem(); this.mnuGotoChannelList = new DevExpress.XtraBars.BarSubItem(); this.mnuInputSource = new DevExpress.XtraBars.BarLinkContainerItem(); @@ -205,7 +206,6 @@ this.pageProgNr = new DevExpress.XtraTab.XtraTabPage(); this.popupInputSource = new DevExpress.XtraBars.PopupMenu(this.components); this.popupFavList = new DevExpress.XtraBars.PopupMenu(this.components); - this.miExplorerIntegration = new DevExpress.XtraBars.BarButtonItem(); ((System.ComponentModel.ISupportInitialize)(this.splitContainerControl1)).BeginInit(); this.splitContainerControl1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.grpOutputList)).BeginInit(); @@ -1642,6 +1642,14 @@ this.miAllowEditPredefinedLists.Name = "miAllowEditPredefinedLists"; this.miAllowEditPredefinedLists.DownChanged += new DevExpress.XtraBars.ItemClickEventHandler(this.miAllowEditPredefinedLists_DownChanged); // + // miExplorerIntegration + // + this.miExplorerIntegration.ButtonStyle = DevExpress.XtraBars.BarButtonStyle.Check; + resources.ApplyResources(this.miExplorerIntegration, "miExplorerIntegration"); + this.miExplorerIntegration.Id = 97; + this.miExplorerIntegration.Name = "miExplorerIntegration"; + this.miExplorerIntegration.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miExplorerIntegration_ItemClick); + // // mnuAccessibility // resources.ApplyResources(this.mnuAccessibility, "mnuAccessibility"); @@ -2044,14 +2052,6 @@ this.popupFavList.Name = "popupFavList"; this.popupFavList.ShowCaption = true; // - // miExplorerIntegration - // - this.miExplorerIntegration.ButtonStyle = DevExpress.XtraBars.BarButtonStyle.Check; - resources.ApplyResources(this.miExplorerIntegration, "miExplorerIntegration"); - this.miExplorerIntegration.Id = 97; - this.miExplorerIntegration.Name = "miExplorerIntegration"; - this.miExplorerIntegration.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miExplorerIntegration_ItemClick); - // // MainForm // this.AllowDrop = true; diff --git a/source/ChanSort/MainForm.resx b/source/ChanSort/MainForm.resx index 56a355e..65bbfe5 100644 --- a/source/ChanSort/MainForm.resx +++ b/source/ChanSort/MainForm.resx @@ -1252,7 +1252,7 @@ globalImageCollection1 - ChanSort.Ui.GlobalImageCollection, ChanSort, Version=1.0.7133.19230, Culture=neutral, PublicKeyToken=null + ChanSort.Ui.GlobalImageCollection, ChanSort, Version=1.0.7133.39305, Culture=neutral, PublicKeyToken=null gviewRight @@ -1800,6 +1800,12 @@ DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v19.1, Version=19.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + miExplorerIntegration + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v19.1, Version=19.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + mnuAccessibility @@ -1962,12 +1968,6 @@ DevExpress.XtraBars.PopupMenu, DevExpress.XtraBars.v19.1, Version=19.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a - - miExplorerIntegration - - - DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v19.1, Version=19.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a - MainForm @@ -1975,7 +1975,7 @@ DevExpress.XtraEditors.XtraForm, DevExpress.Utils.v19.1, Version=19.1.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a - 07/13/2019 11:21:37 + 07/13/2019 21:51:28 16, 16 diff --git a/source/changelog.md b/source/changelog.md index fe7ece3..6347894 100644 --- a/source/changelog.md +++ b/source/changelog.md @@ -1,5 +1,38 @@ ChanSort Change Log =================== +2019-07-14 +- added support for Silva-Schneider .sdx channel lists + +2019-07-13 +- support for channel file name as command line argument +- added explorer integration option in settings menu (to register file types) +- added drag/drop support to drag a file from windows explorer onto chansort to open it +- added reference list for vodafone cable TV in Berlin +- added missing DLL required for printing +- upgrade to DX 19.1 + +2019-02-12 +- fixed "hidden" flag for Samsung C/D/E/F series (.scm lists) + +2019-02-10 +- fixed "delete channels", which were added at the end regardless of the user selection +- fixed handling of SCM lists where the value of the "hidden" flag is 255 (using best-guess based on another field) +- changed logic how channel lists can control which columns are visible in the UI +- added column for PcrPid +- removed column AudioPid from SCM lists +- fixed saving VDR lists after applying a reference list which contained no longer existing channels (cast exception for the proxy ChannelInfo record) +- no longer load samsung .zip lists with invalid internal folder structure (all files must be in the root folder of the .zip) + +2019-02-06 +- fixed deployment script to include DevExpress 18.2 DLLs, which are required to run ChanSort + +2019-02-05 +- upgraded to DevExpress 18.2 +- hide VPID and APID columns for Panasonic (no data provided) +- Samsung J lists could have a \0 character at the end of a unicode16 string, which caused "Copy to Excel" to truncate the text +- fixed new-version check to work with github (only supports TLS 1.2 and newer now, not SSL 3.0) +- added pull-request with GB Sky reference channel list + 2017-11-30 - fixed: deleting channels and selecting to "Remove unsorted channels" when saving could produce problems loading the list on the TV.