commit e194ff983bfd29a54c1b648bbc9019da7ee63793 Author: hbeham Date: Sun Mar 31 14:09:38 2013 +0200 initial import diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0bc8230 --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ + +#ignore thumbnails created by windows +Thumbs.db +#Ignore files build by Visual Studio +*.obj +*.exe +*.pdb +*.user +*.aps +*.pch +*.vspscc +*_i.c +*_p.c +*.ncb +*.suo +*.tlb +*.tlh +*.bak +*.cache +*.ilk +*.log +[Bb]in +[Dd]ebug*/ +*.lib +*.sbr +obj/ +[Rr]elease*/ +_ReSharper*/ +[Tt]est[Rr]esult* diff --git a/ChanSort.Api/ChanSort.Api.csproj b/ChanSort.Api/ChanSort.Api.csproj new file mode 100644 index 0000000..b6b6db8 --- /dev/null +++ b/ChanSort.Api/ChanSort.Api.csproj @@ -0,0 +1,124 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {DCCFFA08-472B-4D17-BB90-8F513FC01392} + Library + Properties + ChanSort.Api + ChanSort.Api + v3.5 + 512 + Client + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + ..\Debug\ + DEBUG;TRACE + full + x86 + prompt + true + true + true + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + true + true + false + + + + + + + + + + + + + + + + + + + + + + True + True + Resources.de.resx + + + True + True + Resources.resx + + + + + + + + + + + + + + + + + + Always + + + + + ResXFileCodeGenerator + Resources.de.Designer.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + + + \ No newline at end of file diff --git a/ChanSort.Api/Controller/ChlFileSerializer.cs b/ChanSort.Api/Controller/ChlFileSerializer.cs new file mode 100644 index 0000000..04b3bf4 --- /dev/null +++ b/ChanSort.Api/Controller/ChlFileSerializer.cs @@ -0,0 +1,98 @@ +using System.IO; +using System.Linq; + +namespace ChanSort.Api +{ + /// + /// Reader for SamToolBox reference lists (*.chl) + /// The file has no header, each line represents a channel and fields are separated by semi-colon: + /// Number;Channel Name[;Transponder Index] + /// + public class ChlFileSerializer + { + private static readonly char[] Separators = new[] { ';' }; + private readonly System.Text.StringBuilder warnings = new System.Text.StringBuilder(); + private int lineNumber; + private DataRoot dataRoot; + private ChannelList channelList; + + #region Load() + public string Load(string fileName, DataRoot root, ChannelList list) + { + this.lineNumber = 0; + this.dataRoot = root; + this.channelList = list; + this.warnings.Remove(0, this.warnings.Length); + + foreach (var channel in this.channelList.Channels) + channel.NewProgramNr = 0; + + using (var stream = new StreamReader(fileName, System.Text.Encoding.Default)) + { + ReadChannelsFromStream(stream); + } + return this.warnings.ToString(); + } + #endregion + + #region ReadChannelsFromStream() + + private void ReadChannelsFromStream(TextReader stream) + { + string line; + while ((line = stream.ReadLine()) != null) + { + ++lineNumber; + ParseChannel(line); + } + } + + #endregion + + #region ParseChannel() + + private void ParseChannel(string line) + { + var parts = line.Split(Separators); + if (parts.Length < 2) return; + int progNr; + Transponder transponder = null; + if (!int.TryParse(parts[0], out progNr)) return; + if (parts.Length >= 3) + { + int transponderIndex; + if (int.TryParse(parts[2], out transponderIndex)) + { + transponder = this.dataRoot.Transponder.TryGet(transponderIndex); + if (transponder == null) + warnings.AppendFormat("Line #{0,4}: invalid transponder index {1}\r\n", this.lineNumber, transponderIndex); + } + } + + string name = parts[1].Replace("\"", ""); + if (name.Trim().Length == 0) + return; + + int found = 0; + var channels = channelList.GetChannelByName(name); + if (transponder != null) + channels = channels.Where(chan => chan.Transponder == transponder); + + foreach(var channel in channels) + { + if (channel.NewProgramNr != 0) + continue; + ++found; + if (found > 1) + break; + channel.NewProgramNr = progNr; + } + + if (found == 0) + this.warnings.AppendFormat("Line {0,4}: Pr# {1,4}, channel '{2}' could not be found\r\n", this.lineNumber, progNr, name); + if (found > 1) + this.warnings.AppendFormat("Line {0,4}: Pr# {1,4}, channel '{2}' found multiple times\r\n", this.lineNumber, progNr, name); + } + #endregion + } +} diff --git a/ChanSort.Api/Controller/CsvFileSerializer.cs b/ChanSort.Api/Controller/CsvFileSerializer.cs new file mode 100644 index 0000000..f36e021 --- /dev/null +++ b/ChanSort.Api/Controller/CsvFileSerializer.cs @@ -0,0 +1,127 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace ChanSort.Api +{ + public class CsvFileSerializer + { + private static readonly char[] Separators = new[] { ',', ';', '\t' }; + + #region Load() + public void Load(string fileName, DataRoot dataRoot) + { + foreach (var list in dataRoot.ChannelLists) + { + foreach (var channel in list.Channels) + channel.NewProgramNr = 0; + } + + using (var stream = new StreamReader(fileName)) + { + ReadChannelsFromStream(stream, dataRoot); + } + } + #endregion + + #region ReadChannelsFromStream() + + public static void ReadChannelsFromStream(TextReader stream, DataRoot dataRoot) + { + string line; + while ((line = stream.ReadLine()) != null) + { + ParseChannel(line, dataRoot); + } + } + + #endregion + + #region ParseChannel() + + private static void ParseChannel(string line, DataRoot dataRoot) + { + var parts = line.Split(Separators); + if (parts.Length < 5) return; + int index, slot, transportStreamId; + if (!int.TryParse(parts[0], out index)) return; + if (!int.TryParse(parts[1], out slot)) return; + if (!int.TryParse(parts[2], out transportStreamId)) return; + string uid = parts[3].Replace("\"", ""); + SignalSource signalSource; + switch (uid[0]) + { + case 'S': signalSource = SignalSource.DvbS; break; + case 'C': signalSource = SignalSource.DvbCT; break; + case 'A': signalSource = SignalSource.AnalogCT; break; + case 'H': signalSource = SignalSource.HdPlusD; break; + default: return; + } + var signalType = slot < 0x4000 ? SignalType.Tv : SignalType.Radio; + var channelList = dataRoot.GetChannelList(signalSource, signalType, true); + string name = parts[4].Replace("\"", ""); + IEnumerable channels = FindChannels(channelList, name, uid); + var channel = channels == null ? null : channels.FirstOrDefault(c => c.NewProgramNr == 0); + if (channel != null) + channel.NewProgramNr = slot & 0x3FFF; + else + { + channel = new ChannelInfo(signalSource, signalType, uid, slot, name); + channel.TransportStreamId = transportStreamId; + channelList.AddChannel(channel); + } + } + #endregion + + #region FindChannels() + private static IEnumerable FindChannels(ChannelList channelList, string name, string uid) + { + IList list = channelList.GetChannelByName(name).ToList(); + if (list.Count == 1) + return list; + + string[] uidParts; + if (uid.StartsWith("C") && (uidParts = uid.Split('-')).Length <= 4) + { + // older CSV files didn't use the Transponder as part of the UID, which is necessary + // to distinguish between identical channels (onid,tsid,sid) received on multiple transponders + // (e.g. from differnt regional DVB-T transmitters) + int onid = int.Parse(uidParts[1]); + int tsid = int.Parse(uidParts[2]); + int sid = int.Parse(uidParts[3]); + return channelList.Channels.Where(c => + c.OriginalNetworkId == onid && + c.TransportStreamId == tsid && + c.ServiceId == sid + ).ToList(); + } + + var byUidList = channelList.GetChannelByUid(uid); + return byUidList; + } + #endregion + + #region Save() + public void Save(string fileName, DataRoot dataRoot, UnsortedChannelMode unsortedChannelMode) + { + using (StreamWriter stream = new StreamWriter(fileName)) + { + foreach (var channelList in dataRoot.ChannelLists) + { + int radioMask = channelList.SignalType == SignalType.Radio ? 0x4000 : 0; + foreach (var channel in channelList.Channels.Where(ch => ch.NewProgramNr != 0).OrderBy(ch => ch.NewProgramNr)) + { + string line = string.Format("{0},{1},{2},{3},\"{4}\"", + channel.RecordIndex, + channel.NewProgramNr | radioMask, + channel.TransportStreamId, + channel.Uid, + channel.Name); + stream.WriteLine(line); + } + } + } + } + #endregion + } +} diff --git a/ChanSort.Api/Controller/Editor.cs b/ChanSort.Api/Controller/Editor.cs new file mode 100644 index 0000000..c9143b5 --- /dev/null +++ b/ChanSort.Api/Controller/Editor.cs @@ -0,0 +1,276 @@ +using System.Collections.Generic; +using System.Linq; + +namespace ChanSort.Api +{ + public class Editor + { + public DataRoot DataRoot; + public ChannelList ChannelList; + +#if false + #region LoadDvbViewerFiles() + private void LoadDvbViewerFiles() + { + List fileList; + Dictionary satPosition; + if (!LoadSatMappingFile(out satPosition, out fileList)) + return; + + foreach (var file in fileList) + { + try + { + string fullPath = Path.IsPathRooted(file) + ? file + : Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), file); + this.LoadDvbViewerChannelFile(fullPath, satPosition); + } + catch + { + } + } + } + #endregion + + #region LoadSatMappingFile() + private static bool LoadSatMappingFile(out Dictionary satPosition, out List fileList) + { + satPosition = null; + fileList = null; + string satMappingFile = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "sat-mapping.ini"); + if (!File.Exists(satMappingFile)) + return false; + + fileList = new List(); + satPosition = new Dictionary(); + string section = null; + using (var stream = new StreamReader(satMappingFile, Encoding.UTF8)) + { + string line; + while ((line = stream.ReadLine()) != null) + { + line = line.Trim(); + if (line.Length == 0 || line.StartsWith(";")) + continue; + if (line.StartsWith("[") && line.EndsWith("]")) + { + section = line; + continue; + } + if (section == "[Satellites]") + { + var parts = line.Split(new[] { '=' }, 2); + if (parts.Length == 2) + satPosition[parts[0].ToLower()] = parts[1].ToUpper(); + } + else if (section == "[DvbViewerChannelFiles]") + { + fileList.Set(line); + } + } + } + return true; + } + #endregion + + #region LoadDvbViewerChannelFile() + private void LoadDvbViewerChannelFile(string file, IDictionary satPosition) + { + string[] unencrypted = { "18", "19", "26", "146", "154" }; + + using (var stream = new StreamReader(file, Encoding.Default)) + { + string line; + bool first = true; + while ((line = stream.ReadLine()) != null) + { + if (first) + { + first = false; + continue; + } + var col = line.Split(new[] { '\t' }); + if (col.Length < 21) + continue; + + string satId; + if (!satPosition.TryGetValue(col[0].ToLower(), out satId)) + continue; + + StringBuilder uid = new StringBuilder(); + uid.Append("S").Append(satId).Append("-").Append(col[20]).Append("-").Append(col[18]).Append("-").Append(col[17]); + + ChannelInfo channel; + if (!TvChannelByUid.TryGetValue(uid.ToString(), out channel)) + continue; + channel.Encrypted = Array.IndexOf(unencrypted, col[19]) < 0; + } + } + } + #endregion +#endif + + #region AddChannels() + + public ChannelInfo AddChannels(IList channels) + { + int count = channels.Count(channel => channel.NewProgramNr == 0); + if (count == 0) return null; + + ChannelInfo lastInsertedChannel = null; + int progNr = this.ChannelList.InsertProgramNumber; + int relativeChannelNumber = 0; + foreach(var channel in this.ChannelList.Channels) + { + if (channel.NewProgramNr != 0 && channel.NewProgramNr >= progNr) + { + int gap = count - (channel.NewProgramNr - progNr - relativeChannelNumber); + if (gap <= 0) + break; + channel.NewProgramNr += gap; + ++relativeChannelNumber; + } + } + + foreach (var channel in channels) + { + if (channel.NewProgramNr != 0) + { + // TODO notify user + continue; + } + + channel.NewProgramNr = progNr++; + lastInsertedChannel = channel; + } + this.ChannelList.InsertProgramNumber += count; + + this.DataRoot.NeedsSaving |= lastInsertedChannel != null; + return lastInsertedChannel; + } + #endregion + + #region RemoveChannels() + + public void RemoveChannels(IList channels) + { + if (channels.Count == 0) return; + + this.ChannelList.InsertProgramNumber = channels[0].NewProgramNr; + foreach (var channel in channels) + { + if (channel.NewProgramNr == 0) + continue; + int prevNr = channel.NewProgramNr; + foreach (var channel2 in this.ChannelList.Channels) + { + if (channel2.NewProgramNr > channel.NewProgramNr) + { + if (prevNr != -1 && channel2.NewProgramNr != prevNr + 1) // don't pull down numbers after a gap + break; + prevNr = channel2.NewProgramNr; + --channel2.NewProgramNr; + } + } + channel.NewProgramNr = 0; + } + + this.DataRoot.NeedsSaving = true; + } + + #endregion + + #region MoveChannels() + + public void MoveChannels(List channels, bool up) + { + if (channels.Count == 0) + return; + if (up && channels[0].NewProgramNr < 2) + return; + + int delta = (up ? - 1 : +1); + foreach (var channel in channels) + { + int newProgramNr = channel.NewProgramNr + delta; + ChannelInfo channelAtNewProgramNr = this.ChannelList.Channels.FirstOrDefault(ch => ch.NewProgramNr == newProgramNr); + if (channelAtNewProgramNr != null) + channelAtNewProgramNr.NewProgramNr -= delta; + channel.NewProgramNr += delta; + } + this.DataRoot.NeedsSaving = true; + } + + #endregion + + #region SortSelectedChannels(), ChannelComparerForSortingByName() + public void SortSelectedChannels(List selectedChannels) + { + if (selectedChannels.Count == 0) return; + var sortedChannels = new List(selectedChannels); + sortedChannels.Sort(this.ChannelComparerForSortingByName); + var programNumbers = selectedChannels.Select(ch => ch.NewProgramNr).ToList(); + for (int i = 0; i < sortedChannels.Count; i++) + sortedChannels[i].NewProgramNr = programNumbers[i]; + + this.DataRoot.NeedsSaving = true; + } + + private int ChannelComparerForSortingByName(ChannelInfo channel1, ChannelInfo channel2) + { + return channel1.Name.CompareTo(channel2.Name); + } + #endregion + + #region SetSlotNumber() + public void SetSlotNumber(IList channels, int slot, bool swap) + { + if (channels.Count == 0) return; + if (swap) + { + foreach (var channel in channels) + { + if (slot != 0) + { + var others = this.ChannelList.GetChannelByNewProgNr(slot); + foreach (var other in others) + other.NewProgramNr = channel.NewProgramNr; + } + channel.NewProgramNr = slot++; + } + } + else + { + this.RemoveChannels(channels); + this.ChannelList.InsertProgramNumber = slot; + this.AddChannels(channels); + } + this.DataRoot.NeedsSaving = true; + } + #endregion + + #region RenumberChannels() + public void RenumberChannels(List channels) + { + if (channels.Count == 0) return; + int progNr = channels.Min(ch => ch.NewProgramNr); + foreach(var channel in channels) + { + if (channel.NewProgramNr == progNr) + { + ++progNr; + continue; + } + + var list = new List(); + list.Add(channel); + this.RemoveChannels(list); + this.ChannelList.InsertProgramNumber = progNr++; + this.AddChannels(list); + this.DataRoot.NeedsSaving = true; + } + } + #endregion + } +} diff --git a/ChanSort.Api/Controller/ISerializerPlugin.cs b/ChanSort.Api/Controller/ISerializerPlugin.cs new file mode 100644 index 0000000..40e6f56 --- /dev/null +++ b/ChanSort.Api/Controller/ISerializerPlugin.cs @@ -0,0 +1,21 @@ +namespace ChanSort.Api +{ + public interface ISerializerPlugin + { + /// + /// Name of the plugin, as displayed in the OpenFileDialog file-type selection combo box + /// + string PluginName { get; } + + /// + /// Semicolon separated list of supported file types (e.g. "xxLM*.TTL;xxLV*.TTL") + /// + string FileFilter { get; } + + /// + /// Create an object that can read/write the file + /// + /// file is not of any supported type + SerializerBase CreateSerializer(string inputFile); + } +} diff --git a/ChanSort.Api/Controller/SerializerBase.cs b/ChanSort.Api/Controller/SerializerBase.cs new file mode 100644 index 0000000..5d9f28e --- /dev/null +++ b/ChanSort.Api/Controller/SerializerBase.cs @@ -0,0 +1,38 @@ +using System.Text; + +namespace ChanSort.Api +{ + public abstract class SerializerBase + { + private Encoding defaultEncoding; + + public string FileName { get; set; } + public DataRoot DataRoot { get; protected set; } + + protected SerializerBase(string inputFile) + { + this.FileName = inputFile; + this.DataRoot = new DataRoot(); + this.defaultEncoding = Encoding.GetEncoding("iso-8859-9"); + } + + public abstract string DisplayName { get; } + public abstract void Load(); + public abstract void Save(string tvOutputFile, string csvOutputFile, UnsortedChannelMode unsortedChannelMode); + + public virtual Encoding DefaultEncoding + { + get { return this.defaultEncoding; } + set { this.defaultEncoding = value; } + } + + public bool SupportsEraseChannelData { get; protected set; } + public virtual void EraseChannelData() { } + + public virtual string GetFileInformation() { return ""; } + + public virtual void ShowDeviceSettingsForm(object parentWindow) { } + + public bool SupportsChannelNameEdit { get; protected set; } + } +} diff --git a/ChanSort.Api/Lookup.csv b/ChanSort.Api/Lookup.csv new file mode 100644 index 0000000..265cf15 --- /dev/null +++ b/ChanSort.Api/Lookup.csv @@ -0,0 +1,476 @@ +ONID;Start;End;Name;Operator +ONID;0x0000;0x0000;(Reserved);(Reserved) +ONID;0x0001;0x0001;Société Européenne des Satellites;Société Européenne des Satellites +ONID;0x0002;0x0002;Société Européenne des Satellites;Société Européenne des Satellites +ONID;0x0003;0x0019;Société Européenne des Satellites;Société Européenne des Satellites +ONID;0x001A;0x001A;Quiero Televisión  ;Quiero Televisión   +ONID;0x001B;0x001B;RAI;RAI +ONID;0x001C;0x001C;Hellas-Sat S.A.;Hellas-Sat S.A. +ONID;0x001D;0x001D;TELECOM ITALIA MEDIA BROADCASTING SRL;TELECOM ITALIA MEDIA BROADCASTING SRL +ONID;0x001F;0x001F;Europe Online Networks S.A  ;Europe Online Networks S.A   +ONID;0x0020;0x0020;Société Européenne des Satellites;Société Européenne des Satellites +ONID;0x0021;0x0021;Hispasat S.A .;Hispasat S.A . +ONID;0x0022;0x0022;Hispasat S.A .;Hispasat S.A . +ONID;0x0023;0x0023;Hispasat S.A .;Hispasat S.A . +ONID;0x0024;0x0024;Hispasat S.A .;Hispasat S.A . +ONID;0x0025;0x0025;Hispasat S.A .;Hispasat S.A . +ONID;0x0026;0x0026;Hispasat S.A .;Hispasat S.A . +ONID;0x0027;0x0027;Hispasat FSS;Hispasat FSS +ONID;0x0028;0x0028;Hispasat DBS;Hispasat DBS +ONID;0x0029;0x0029;Hispasat America;Hispasat America +ONID;0x002A;0x002A;Päijät-Hämeen Puhelin Oyj;Päijät-Hämeen Puhelin Oyj +ONID;0x002B;0x002B;Digita Oy;Digita Oy +ONID;0x002E;0x002E;Xantic BU Broadband;Xantic BU Broadband +ONID;0x002F;0x002F;TVNZ  ;TVNZ   +ONID;0x0030;0x0030;Canal+ SA (for Intelsat 601-325°E);Canal+ SA (for Intelsat 601-325°E) +ONID;0x0031;0x0031;Hispasat S.A.;Hispasat S.A. +ONID;0x0032;0x0032;Hispasat S.A.;Hispasat S.A. +ONID;0x0033;0x0033;Hispasat S.A.;Hispasat S.A. +ONID;0x0034;0x0034;Hispasat S.A.;Hispasat S.A. +ONID;0x0035;0x0035;NetHold IMS;NetHold IMS +ONID;0x0036;0x0036;TV Cabo Portugal  ;TV Cabo Portugal   +ONID;0x0037;0x0037;France Telecom, CNES and DGA;France Telecom, CNES and DGA +ONID;0x0038;0x0038;Hellenic Telecommunications Organization S.A .;Hellenic Telecommunications Organization S.A . +ONID;0x0039;0x0039;Broadcast Australia Pty.;Broadcast Australia Pty. +ONID;0x003A;0x003A;GeoTelecom Satellite Services;GeoTelecom Satellite Services +ONID;0x003B;0x003B;BBC;BBC +ONID;0x003C;0x003C;KPN Broadcast Services;KPN Broadcast Services +ONID;0x003D;0x003D;Skylogic Italia S.A.;Skylogic Italia S.A. +ONID;0x003E;0x003E;Eutelsat S.A.;Eutelsat S.A. +ONID;0x003F;0x003F;Eutelsat S.A.;Eutelsat S.A. +ONID;0x0040;0x0040;Hrvatski Telekom d.d;Hrvatski Telekom d.d +ONID;0x0041;0x0041;Mindport  ;Mindport   +ONID;0x0042;0x0042;DTV haber ve Gorsel yayýncilik;DTV haber ve Gorsel yayýncilik +ONID;0x0043;0x0043;arena Sport Rechte und Marketing GmbH;arena Sport Rechte und Marketing GmbH +ONID;0x0044;0x0044;VisionTV LLC;VisionTV LLC +ONID;0x0045;0x0045;SES-Sirius;SES-Sirius +ONID;0x0046;0x0046;Telenor ;Telenor  +ONID;0x0047;0x0047;Telenor;Telenor +ONID;0x0048;0x0048;STAR DIGITAL A.S .;STAR DIGITAL A.S . +ONID;0x0049;0x0049;Sentech  ;Sentech   +ONID;0x004A;0x004B;Rambouillet ES;Rambouillet ES +ONID;0x004C;0x004C;Skylogic S.A.;Skylogic S.A. +ONID;0x004D;0x004D;Skylogic S.A.;Skylogic S.A. +ONID;0x004E;0x004F;Eutelsat S.A.;Eutelsat S.A. +ONID;0x0050;0x0050;HRT – Croatian Radio and Television;HRT – Croatian Radio and Television +ONID;0x0051;0x0051;Havas ;Havas  +ONID;0x0052;0x0052;StarGuide Digital Networks ;StarGuide Digital Networks  +ONID;0x0053;0x0053;PT Comunicações;PT Comunicações +ONID;0x0054;0x0054;Teracom AB Satellite Services;Teracom AB Satellite Services +ONID;0x0055;0x0055;NSAB (Teracom);NSAB (Teracom) +ONID;0x0056;0x0056;Viasat Satellite Services AB;Viasat Satellite Services AB +ONID;0x0058;0x0058;UBC Thailand ;UBC Thailand  +ONID;0x0059;0x0059;Bharat Business Channel Limited;Bharat Business Channel Limited +ONID;0x005A;0x005A;ICO Satellite Services G.P.;ICO Satellite Services G.P. +ONID;0x005B;0x005B;ZON;ZON +ONID;0x005E;0x005E;NSAB ;NSAB  +ONID;0x005F;0x005F;NSAB ;NSAB  +ONID;0x0060;0x0060;Kabel Deutschland ;Kabel Deutschland  +ONID;0x0064;0x0064;T-Kábel;T-Kábel Magyarország Kft. +ONID;0x0065;0x0065;France Telecom Orange;France Telecom Orange +ONID;0x0066;0x0066;Zweites Deutsches Fernsehen - ZDF (cable contribution);Zweites Deutsches Fernsehen - ZDF +ONID;0x0069;0x0069;Optus B3 156°E;Optus Communications +ONID;0x0070;0x0070;BONUM1 36 Degrees East;NTV+ +ONID;0x0073;0x0073;PanAmSat 4 68.5°E;Pan American Satellite System +ONID;0x007D;0x007D;Skylogic;Skylogic Italia +ONID;0x007E;0x007F;Eutelsat Satellite System at 7°E;EUTELSAT – European Telecommunications Satellite Organization  +ONID;0x0085;0x0085;BetaTechnik;BetaTechnik +ONID;0x0090;0x0090;National network;TDF +ONID;0x009A;0x009B;Eutelsat satellite system at 9°East;Rambouillet ES +ONID;0x009C;0x009D;Eutelsat satellite system at 9°East;Skylogic S.A. +ONID;0x009E;0x009F;Eutelsat satellite system at 9°East;Eutelsat S.A. +ONID;0x00A0;0x00A0;National Cable Network;News Datacom +ONID;0x00A1;0x00A1;DigiSTAR;STAR Television Productions Ltd (HK) (NDS) +ONID;0x00A2;0x00A2;Sky Entertainment Services;NetSat Serviços Ltda (Brazil), Innova S. de R. L. (Mexico) and Multicountry Partnership L. P. (NDS) +ONID;0x00A3;0x00A3;NDS Director systems;Various (product only sold by Tandberg TV) (NDS) +ONID;0x00A4;0x00A4;ISkyB;STAR Television Productions Ltd (HK) (NDS) +ONID;0x00A5;0x00A5;Indovision;PT. Matahari Lintas Cakrawala (MLC) (NDS) +ONID;0x00A6;0x00A6;ART;ART (NDS) +ONID;0x00A7;0x00A7;Globecast;France Telecom (NDS) +ONID;0x00A8;0x00A8;Foxtel;Foxtel (Australia) (NDS) +ONID;0x00A9;0x00A9;Sky New Zealand;Sky Network Television Ltd (NDS) +ONID;0x00AA;0x00AA;OTE;OTE (Greece) (NDS) +ONID;0x00AB;0x00AB;Yes Satellite Services;DBS (Israel) (NDS) +ONID;0x00AC;0x00AC;(NDS satellite services);(NDS to be allocated) +ONID;0x00AD;0x00AD;SkyLife;Korea Digital Broadcasting +ONID;0x00AE;0x00AF;(NDS satellite services);(NDS to be allocated) +ONID;0x00B0;0x00B3;TPS;La Télévision Par Satellite +ONID;0x00B4;0x00B4;Telesat 107.3°W;Telesat Canada +ONID;0x00B5;0x00B5;Telesat 111.1°W;Telesat Canada +ONID;0x00B6;0x00B6;Telstra Saturn;TelstraSaturn Limited   +ONID;0x00BA;0x00BA;Satellite Express – 6 (80°E);Satellite Express  +ONID;0x00C0;0x00CD;Canal +;Canal+ +ONID;0x00D0;0x00D0;CCTV;China Central Television (NDS) +ONID;0x00D1;0x00D1;Galaxy;Galaxy Satellite Broadcasting, Hong Kong (NDS) +ONID;0x00D2;0x00DF;(NDS satellite services);(NDS to be allocated) +ONID;0x00EB;0x00EB;Eurovision Network;European Broadcasting Union   +ONID;0x0100;0x0100;ExpressVu;ExpressVu Inc. +ONID;0x0101;0x0101;Bulsatcom AD;Bulsatcom AD +ONID;0x0104;0x0104;MagtiSat;Magticom Ltd. +ONID;0x010D;0x010D;Skylogic;Skylogic Italia +ONID;0x010E;0x010F;Eutelsat Satellite System at 10°E;European Telecommunications Satellite Organization +ONID;0x0110;0x0110;Mediaset;Mediaset  +ONID;0x011F;0x011F;visAvision Network;European Telecommunications Satellite Organization +ONID;0x013D;0x013D;Skylogic;Skylogic Italia +ONID;0x013E;0x013F;Eutelsat Satellite System 13°E;European Telecommunications Satellite Organization +ONID;0x016D;0x016D;Skylogic;Skylogic Italia +ONID;0x016E;0x016F;Eutelsat Satellite System at 16°E;European Telecommunications Satellite Organization +ONID;0x0170;0x0170;Audio Visual Global Joint Stock Company;Audio Visual Global Joint Stock Company +ONID;0x01F4;0x01F4;MediaKabel B.V; +ONID;0x022D;0x022D;Skylogic;Skylogic Italia +ONID;0x022E;0x022F;Eutelsat Satellite System at 21.5°E;EUTELSAT – European Telecommunications Satellite Organization  +ONID;0x026D;0x026D;Skylogic;Skylogic Italia +ONID;0x026E;0x026F;Eutelsat Satellite System at 25.5°E;EUTELSAT – European Telecommunications Satellite Organization  +ONID;0x029D;0x029D;Skylogic;Skylogic Italia +ONID;0x029E;0x029F;Eutelsat Satellite System at 29°E;European Telecommunications Satellite Organization +ONID;0x02BE;0x02BE;ARABSAT;ARABSAT - Arab Satellite Communications Organization +ONID;0x02C0;0x02C0;MTV Networks Europe;MTV Networks Europe +ONID;0x033D;0x033D;Skylogic at 33°E;Skylogic Italia +ONID;0x033E;0x033F;Eutelsat Satellite System at 33°E;Eutelsat +ONID;0x034E;0x034E;IRIB;IRIB +ONID;0x036D;0x036D;Skylogic;Skylogic Italia +ONID;0x036E;0x036F;Eutelsat Satellite System at 36°E;European Telecommunications Satellite Organization +ONID;0x03E8;0x03E8;Telia;Telia, Sweden +ONID;0x045D;0x045F;Eutelsat satellite system at 15°West;Eutelsat S.A. +ONID;0x047D;0x047D;Skylogic;Skylogic Italia +ONID;0x047E;0x047F;Eutelsat Satellite System at 12.5°W;EUTELSAT – European Telecommunications Satellite Organization  +ONID;0x048D;0x048D;Skylogic;Skylogic Italia +ONID;0x048E;0x048F;Eutelsat Satellite System at 48°E;European Telecommunications Satellite Organization +ONID;0x049D;0x049F;Eutelsat satellite system at 11°West;Eutelsat S.A. +ONID;0x0500;0x0500;Vinasat Center;Vinasat Center +ONID;0x0510;0x0510;Almajd;Almajd Satellite Broadcasting FZ LLC +ONID;0x052D;0x052D;Skylogic;Skylogic Italia +ONID;0x052E;0x052F;Eutelsat Satellite System at 8°W;EUTELSAT – European Telecommunications Satellite Organization  +ONID;0x053D;0x053F;Eutelsat satellite system at 53°East;Eutelsat S.A. +ONID;0x055D;0x055D;Skylogic at 5°W;Skylogic Italia +ONID;0x055E;0x055F;Eutelsat Satellite System at 5°W;Eutelsat +ONID;0x0600;0x0600;UPC Satellite;UPC   +ONID;0x0601;0x0601;UPC Cable;UPC   +ONID;0x0602;0x0602;Tevel;Tevel Cable (Israel ) +ONID;0x071D;0x071D;Skylogic at 70.5°E;Skylogic Italia +ONID;0x071E;0x071F;Eutelsat Satellite System at 70.5°E;Eutelsat S.A. +ONID;0x077D;0x077D;Skylogic Satellite System at 7°W;Skylogic Italia +ONID;0x077E;0x077F;Eutelsat Satellite System at 7°W;Eutelsat S.A. +ONID;0x0800;0x0801;Nilesat 101;Nilesat +ONID;0x0880;0x0880;MEASAT 1, 91.5°E;MEASAT Broadcast Network Systems SDN. BHD. (Kuala Lumpur, Malaysia) +ONID;0x0882;0x0882;MEASAT 2, 91.5°E;MEASAT Broadcast Network Systems SDN. BHD. (Kuala Lumpur, Malaysia) +ONID;0x0883;0x0883;MEASAT 2, 148.0°E;Hsin Chi Broadcast Company Ltd . +ONID;0x088F;0x088F;MEASAT 3;MEASAT Broadcast Network Systems SDN. BHD. (Kuala Lumpur, Malaysia) +ONID;0x08A0;0x08A0;Mainland Television Limited;Mainland Television Limited +ONID;0x0E26;0x0E26;IRIB;IRIB +ONID;0x0FFF;0x0FFF;Optus Networks;Optus Networks +ONID;0x1000;0x1000;Optus B3 156°E;Optus Communications +ONID;0x1001;0x1001;DISH Network;Echostar Communications +ONID;0x1002;0x1002;Dish Network 61.5 W;Echostar Communications +ONID;0x1003;0x1003;Dish Network 83 W;Echostar Communications +ONID;0x1004;0x1004;Dish Network 119 W;Echostar Communications +ONID;0x1005;0x1005;Dish Network 121 W;Echostar Communications +ONID;0x1006;0x1006;Dish Network 148 W;Echostar Communications +ONID;0x1007;0x1007;Dish Network 175 W;Echostar Communications +ONID;0x1008;0x100B;Dish Network W - Z;Echostar Communications +ONID;0x1010;0x1010;ABC TV;Australian Broadcasting Corporation   +ONID;0x1011;0x1011;SBS;SBS Australia   +ONID;0x1012;0x1012;Nine Network Australia;Nine Network Australia   +ONID;0x1013;0x1013;Seven Network Australia;Seven Network Limited   +ONID;0x1014;0x1014;Network TEN Australia;Network TEN Limited   +ONID;0x1015;0x1015;WIN Television Australia;WIN Television Pty Ltd   +ONID;0x1016;0x1016;Prime Television Australia;Prime Television Limited   +ONID;0x1017;0x1017;Southern Cross Broadcasting Australia;Southern Cross Broadcasting (Australia) Limited   +ONID;0x1018;0x1018;Telecasters Australia;Telecasters Australia Limited   +ONID;0x1019;0x1019;NBN Australia;NBN Limited   +ONID;0x101A;0x101A;Imparja Television Australia;Imparja Television Australia  +ONID;0x101B;0x101F;(Reserved for Australian broadcaster);(Reserved for Australian broadcasters) +ONID;0x1100;0x1100;GE Americom;GE American Communications +ONID;0x1101;0x1101;MiTV Networks Broadcast Terrestrial Network - DVB-H;MiTV Networks Sdn Bhd Malaysia +ONID;0x1102;0x1102;Dream Mobile TV;Philippines Multimedia System, Inc. +ONID;0x1103;0x1103;PT MAC;PT. Mediatama Anugrah Citra +ONID;0x1104;0x1104;Levira Mobile TV;Levira AS +ONID;0x1105;0x1105;Mobision;Alsumaria TV +ONID;0x1106;0x1106;Trenmobile;PT. Citra Karya Investasi +ONID;0x1107;0x1107;VTC Mobile TV;VTC Mobile TV +ONID;0x1700;0x1700;Echostar 2A;EchoStar Communications +ONID;0x1701;0x1701;Echostar 2B;EchoStar Communications +ONID;0x1702;0x1702;Echostar 2C;EchoStar Communications +ONID;0x1703;0x1703;Echostar 2D;EchoStar Communications +ONID;0x1704;0x1704;Echostar 2E;EchoStar Communications +ONID;0x1705;0x1705;Echostar 2F;EchoStar Communications +ONID;0x1706;0x1706;Echostar 2G;EchoStar Communications +ONID;0x1707;0x1707;Echostar 2H;EchoStar Communications +ONID;0x1708;0x1708;Echostar 2I;EchoStar Communications +ONID;0x1709;0x1709;Echostar 2J;EchoStar Communications +ONID;0x170A;0x170A;Echostar 2K;EchoStar Communications +ONID;0x170B;0x170B;Echostar 2L;EchoStar Communications +ONID;0x170C;0x170C;Echostar 2M;EchoStar Communications +ONID;0x170D;0x170D;Echostar 2N;EchoStar Communications +ONID;0x170E;0x170E;Echostar 2O;EchoStar Communications +ONID;0x170F;0x170F;Echostar 2P;EchoStar Communications +ONID;0x1710;0x1710;Echostar 2Q;EchoStar Communications +ONID;0x1711;0x1711;Echostar 2R;EchoStar Communications +ONID;0x1712;0x1712;Echostar 2S;EchoStar Communications +ONID;0x1713;0x1713;Echostar 2T;EchoStar Communications +ONID;0x1714;0x1714;Platforma HD;Platforma HD Ltd. +ONID;0x1715;0x1715;Profit Group Terrestrial;Profit Group SpA +ONID;0x1716;0x1716;JSC Mostelekom;JSC Mostelekom +ONID;0x2000;0x2000;Thiacom 1 & 2 co-located 78.5°E;Shinawatra Satellite +ONID;0x2014;0x2014;DTT - Andorran Digital Terrestrial Television;STA +ONID;0x2024;0x2024;Australian Digital Terrestrial Television;Australian Broadcasting Authority  +ONID;0x2028;0x2028;Austrian Digital Terrestrial Television;ORS - Austrian Broadcasting Services +ONID;0x2038;0x2038;Belgian Digital Terrestrial Television;BIPT +ONID;0x209E;0x209E;Taiwanese Digital Terrestrial Television;Directorate General of Telecommunications +ONID;0x20AA;0x20AA;Comision Nacional de Television de Colombia;Comision Nacional de Television de Colombia +ONID;0x20BF;0x20BF;Croatian Post and Electronic Communications Agency (HAKOM);Croatian Post and Electronic Communications Agency (HAKOM) +ONID;0x20C4;0x20C4;Office Of the Commissioner of Electronic Communications and Postal Regulation;Office Of the Commissioner of Electronic Communications and Postal Regulation +ONID;0x20CB;0x20CB;Czech Republic Digital Terrestrial Television;Czech Digital Group   +ONID;0x20D0;0x20D0;Danish Digital Terrestrial Television;National Telecom Agency Denmark   +ONID;0x20E9;0x20E9;Estonian Digital Terrestrial Television;Estonian National Communications Board +ONID;0x20F6;0x20F6;Finnish Digital Terrestrial Television;Telecommunicatoins Administratoin Centre, Finland   +ONID;0x20FA;0x20FA;French Digital Terrestrial Television;Conseil Superieur de l'AudioVisuel +ONID;0x2114;0x2114;German Digital Terrestrial Television;IRT on behalf of the German DVB-T broadcasts  +ONID;0x2124;0x2124;Gibraltar Regulatory Authority;Gibraltar Regulatory Authority +ONID;0x2168;0x2168;Digital Terrestrial Network of Indonesia;Ministry of Communication and Information Technology of the Republic of Indonesia +ONID;0x2174;0x2174;Irish Digital Terrestrial Television;Irish Telecommunications Regulator   +ONID;0x2178;0x2178;Israeli Digital Terrestrial Television;BEZEQ (The Israel Telecommunication Corp Ltd .) +ONID;0x217C;0x217C;Italian Digital Terrestrial Television; +ONID;0x21AC;0x21AC;DTT - Latvian Digital Terrestrial Television;Electronic Communications Office +ONID;0x21B8;0x21B8;DTT Lithuania;Communications Regulatory Authority +ONID;0x21CA;0x21CA;Malaysian Technical Standards Forum Bhd (MTFSB);Malaysian Technical Standards Forum Bhd (MTFSB) +ONID;0x2210;0x2210;Netherlands Digital Terrestrial Television;Nozema   +ONID;0x2213;0x2213;DTT for Country of Curacao;Bureau Telecommunicatie en Post +ONID;0x222A;0x222A;DTT - New Zealand Digial Terrestrial Television;TVNZ on behalf of Freeview New Zealand +ONID;0x2242;0x2242;Norwegian Digital Terrestrial Television;Norwegian Regulator +ONID;0x224F;0x224F;Autoridad Nacional de los Servicios Públicos;Autoridad Nacional de los Servicios Públicos +ONID;0x2260;0x2260;DTT - Philippines Digital Terrestrial Television;NTA (porivionally ABS-CBN) +ONID;0x2268;0x2268;DTT Poland;Office of Electronic Communications +ONID;0x2283;0x2283;DTT - Russian Federation;RTRN +ONID;0x22B0;0x22B0;DTT - Serbia JP Emisiona Tehnika i Veze;JP Emisiona Tehnika i Veze +ONID;0x22BE;0x22BE;Singapore Digital Terrestrial Television;Singapore Broadcasting Authority   +ONID;0x22BF;0x22BF;Telecommunications office of the Slovak republic;Telecommunications office of the Slovak republic +ONID;0x22C1;0x22C1;DTT - Slovenian Digital Terrestrial Television;APEK +ONID;0x22C6;0x22C6;DTT - South African Digital Terrestrial Television;South African Broadcasting Corporation Ltd. (SABC), pending formation of DZONGA +ONID;0x22C7;0x22C7;DTT- Hungarian Digital Terrestrial Television;National Communications Authority, Hungary +ONID;0x22C8;0x22C8;DTT- Portugal Digital Terrestrial Television;ANACOM- National Communications Authority +ONID;0x22D4;0x22D4;Spanish Digital Terrestrial Television;“Spanish Broadcasting Regulator  +ONID;0x22F1;0x22F1;Swedish Digital Terrestrial Television;“Swedish Broadcasting Regulator ” +ONID;0x22F4;0x22F4;Swiss Digital Terrestrial Television;OFCOM +ONID;0x233A;0x233A;UK Digital Terrestrial Television;Independent Television Commission  +ONID;0x2B00;0x2B00;DTT – Sky New Zealand;Sky Network Television Limited +ONID;0x3000;0x3000;PanAmSat 4 68.5°E;Pan American Satellite System +ONID;0x5000;0x5000;Irdeto Mux System;Irdeto Test Laboratories +ONID;0x616D;0x616D;BellSouth Entertainment;BellSouth Entertainment, Atlanta, GA, USA   +ONID;0x6600;0x6600;UPC Satellite;UPC   +ONID;0x6601;0x6601;UPC Cable;UPC   +ONID;0x6602;0x6602;Comcast Media Center;Comcast Media Center +ONID;0xA011;0xA011;Sichuan Cable TV Network;Sichuan Cable TV Network (PRC) +ONID;0xA012;0xA012;China Network Systems;STAR Koos Finance Company (Taiwan) +ONID;0xA013;0xA013;Versatel;Versatel (Russia) +ONID;0xA014;0xA014;Chongqing Cable;Chongqing Municipality, PRC +ONID;0XA015;0XA015;Guizhou Cable;Guizhou Province, PRC +ONID;0xA016;0xA016;Hathway Cable;Hathway Cable and Datacom, India +ONID;0xA017;0xA017;RCN;Rogers Cable Network, USA +ONID;0xA018;0xA040;(NDS satellite services);(NDS to be allocated) +ONID;0xA401;0xA401;ARD;ARD-Sternpunkte +ONID;0xA509;0xA509;Welho Cable Network Helsinki;Welho +ONID;0xA600;0xA600;Madritel;Madritel (Spain) +ONID;0xA602;0xA602;Tevel;Tevel (Israel) (NDS) +ONID;0xA603;0xA603;Globo Cabo (to be recycled);Globo Cabo (Brazil) (NDS) +ONID;0xA604;0xA604;Cablemas (to be recycled);Cablemas (Mexico) (NDS) +ONID;0xA605;0xA605;INC National Cable Network;Information Network Centre of SARFT (PRC) (NDS) +ONID;0xA606;0xA607;Pepcom GmbH;Pepcom GmbH +ONID;0xA900;0xA900;M-net Telekommunikations GmbH;M-net Telekommunikations GmbH +ONID;0xF000;0xF000;SMALL CABLE NETWORKS;(Small cable network network operators) +ONID;0xF001;0xF001;Deutsche Telekom;Deutsche Telekom AG +ONID;0xF010;0xF010;Telefónica Cable;Telefónica Cable SA +ONID;0xF020;0xF020;Cable and Wireless Communication;Cable and Wireless Communications +ONID;0xF100;0xF100;Casema;Casema N.V . +ONID;0xF750;0xF750;Telewest Communications Cable Network;Telewest Communications Plc   +ONID;0xF751;0xF751;OMNE Communications;OMNE Communications Ltd. +ONID;0xFBFC;0xFBFC;MATAV;MATAV (Israel ) (NDS) +ONID;0xFBFD;0xFBFD;Com Hem ab;Com Hem ab +ONID;0xFBFE;0xFBFE;TPS;La Télévision Par Satellite +ONID;0xFBFF;0xFBFF;Sky Italia;Sky Italia Spa. +ONID;0xFC10;0xFC10;Rhône Vision Cable;Rhône Vision Cable +ONID;0xFC41;0xFC41;France Telecom Cable;France Telecom   +ONID;0xFD00;0xFD00;National Cable Network;Lyonnaise Communications +ONID;0xFE00;0xFE00;TeleDenmark Cable TV;TeleDenmark +ONID;0xFEC0;0xFEFF;Network Interface Modules;Common Interface   +ONID;0xFF00;0xFFFA;Private_temporary_use;ETSI + +TRANSP;Number;MHz +TRANSP;49;10714 +TRANSP;50;10729 +TRANSP;51;10744 +TRANSP;52;10758 +TRANSP;53;10773 +TRANSP;54;10788 +TRANSP;55;10803 +TRANSP;56;10818 +TRANSP;57;10832 +TRANSP;58;10847 +TRANSP;59;10862 +TRANSP;60;10876 +TRANSP;61;10891 +TRANSP;62;10906 +TRANSP;63;10921 +TRANSP;64;10936 +TRANSP;33;10964 +TRANSP;34;10979 +TRANSP;35;10994 +TRANSP;36;11009 +TRANSP;37;11023 +TRANSP;38;11038 +TRANSP;39;11053 +TRANSP;40;11067 +TRANSP;41;11082 +TRANSP;42;11097 +TRANSP;43;11112 +TRANSP;44;11127 +TRANSP;45;11141 +TRANSP;46;11156 +TRANSP;47;11171 +TRANSP;48;11186 +TRANSP;1;11214 +TRANSP;2;11229 +TRANSP;3;11244 +TRANSP;4;11258 +TRANSP;5;11273 +TRANSP;6;11288 +TRANSP;7;11303 +TRANSP;8;11318 +TRANSP;9;11332 +TRANSP;10;11347 +TRANSP;11;11362 +TRANSP;12;11376 +TRANSP;13;11391 +TRANSP;14;11406 +TRANSP;15;11421 +TRANSP;16;11436 +TRANSP;17;11464 +TRANSP;18;11479 +TRANSP;19;11494 +TRANSP;20;11509 +TRANSP;21;11523 +TRANSP;22;11538 +TRANSP;23;11553 +TRANSP;24;11568 +TRANSP;25;11582 +TRANSP;26;11597 +TRANSP;27;11612 +TRANSP;28;11627 +TRANSP;29;11641 +TRANSP;30;11656 +TRANSP;31;11671 +TRANSP;32;11686 +TRANSP;65;11720 +TRANSP;66;11739 +TRANSP;67;11758 +TRANSP;68;11778 +TRANSP;69;11798 +TRANSP;70;11817 +TRANSP;71;11836 +TRANSP;72;11856 +TRANSP;73;11876 +TRANSP;74;11895 +TRANSP;75;11914 +TRANSP;76;11934 +TRANSP;77;11954 +TRANSP;78;11973 +TRANSP;79;11992 +TRANSP;80;12012 +TRANSP;81;12032 +TRANSP;82;12051 +TRANSP;83;12070 +TRANSP;84;12090 +TRANSP;85;12110 +TRANSP;86;12129 +TRANSP;87;12148 +TRANSP;88;12168 +TRANSP;89;12188 +TRANSP;90;12207 +TRANSP;91;12226 +TRANSP;92;12246 +TRANSP;93;12266 +TRANSP;94;12285 +TRANSP;95;12304 +TRANSP;96;12324 +TRANSP;97;12344 +TRANSP;98;12363 +TRANSP;99;12382 +TRANSP;100;12402 +TRANSP;101;12422 +TRANSP;102;12441 +TRANSP;103;12460 +TRANSP;104;12480 +TRANSP;105;12515 +TRANSP;106;12522 +TRANSP;107;12545 +TRANSP;108;12552 +TRANSP;109;12574 +TRANSP;110;12581 +TRANSP;111;12604 +TRANSP;112;12610 +TRANSP;113;12633 +TRANSP;114;12640 +TRANSP;115;12663 +TRANSP;116;12670 +TRANSP;117;12692 +TRANSP;118;12699 +TRANSP;119;12722 +TRANSP;120;12728 + +SERVICETYPE;Number;Description +SERVICETYPE;01;SD-TV +SERVICETYPE;02;Radio +SERVICETYPE;12;Daten/Test +SERVICETYPE;25;HD-TV +SERVICETYPE;211;Sky Select + +DVBT;Channel;MHz +DVBT;21;474 +DVBT;22;482 +DVBT;23;490 +DVBT;24;498 +DVBT;25;506 +DVBT;26;514 +DVBT;27;522 +DVBT;28;530 +DVBT;29;538 +DVBT;30;546 +DVBT;31;554 +DVBT;32;562 +DVBT;33;570 +DVBT;34;578 +DVBT;35;586 +DVBT;36;594 +DVBT;37;602 +DVBT;38;610 +DVBT;39;618 +DVBT;40;626 +DVBT;41;634 +DVBT;42;642 +DVBT;43;650 +DVBT;44;658 +DVBT;45;666 +DVBT;46;674 +DVBT;47;682 +DVBT;48;690 +DVBT;49;698 +DVBT;50;706 +DVBT;51;714 +DVBT;52;722 +DVBT;53;730 +DVBT;54;738 +DVBT;55;746 +DVBT;56;754 +DVBT;57;762 +DVBT;58;770 +DVBT;59;778 +DVBT;60;786 +DVBT;61;794 +DVBT;62;802 +DVBT;63;810 +DVBT;64;818 +DVBT;65;826 +DVBT;66;834 +DVBT;67;842 +DVBT;68;850 +DVBT;69;858 diff --git a/ChanSort.Api/Model/ChannelInfo.cs b/ChanSort.Api/Model/ChannelInfo.cs new file mode 100644 index 0000000..02eeba4 --- /dev/null +++ b/ChanSort.Api/Model/ChannelInfo.cs @@ -0,0 +1,205 @@ +using System; +using System.Collections.Generic; + +namespace ChanSort.Api +{ + public class ChannelInfo + { + private string uid; + /// + /// List of channels that have the same UID as this channel and were not added to the channel list directly + /// + public readonly List Duplicates = new List(); + + public SignalSource SignalSource { get; private set; } + public SignalType SignalType { get; private set; } + public int RecordIndex { get; set; } + public int RecordOrder { get; set; } + public int OldProgramNr { get; set; } + public int NewProgramNr { get; set; } + public string Name { get; set; } + public string ShortName { get; set; } + public Favorites Favorites { get; set; } + public bool Skip { get; set; } + public bool Lock { get; set; } + public bool Hidden { get; set; } + public bool? Encrypted { get; set; } + public string ChannelOrTransponder { get; set; } + public string Satellite { get; set; } + public decimal FreqInMhz { get; set; } + public char Polarity { get; set; } + public int ServiceId { get; set; } + public int VideoPid { get; set; } + public int AudioPid { get; set; } + public int OriginalNetworkId { get; set; } + public int TransportStreamId { get; set; } + public int SymbolRate { get; set; } + public int ServiceType { get; set; } + public string Debug { get; private set; } + public string SatPosition { get; set; } + public Transponder Transponder { get; set; } + + public bool IsNameModified { get; set; } + + #region ctor() + /// + /// Constructor for exiting TV channel + /// + public ChannelInfo(SignalSource source, SignalType type, int index, int oldProgNr, string name) + { + this.SignalSource = source; + this.SignalType = type; + this.RecordIndex = index; + this.RecordOrder = index; + this.OldProgramNr = oldProgNr; + this.Name = name; + this.Encrypted = null; + } + + /// + /// Constructor for reference list channels which no longer exist in TV list + /// + /// + /// + /// + /// + /// + public ChannelInfo(SignalSource source, SignalType type, string uid, int newProgNr, string name) + { + this.SignalSource = source; + this.SignalType = type; + this.Uid = uid; + this.NewProgramNr = newProgNr; + this.Name = name; + this.Encrypted = null; + } + #endregion + + #region Uid + public string Uid + { + get + { + if (this.uid == null) + { + if ((this.SignalSource & SignalSource.Digital) == 0) + this.uid = "A-0-" + (int)(this.FreqInMhz*20) + "-0"; + else if (this.SignalSource == SignalSource.DvbS) + this.uid = "S" + this.SatPosition + "-" + this.OriginalNetworkId + "-" + this.TransportStreamId + "-" + this.ServiceId; + else if (this.SignalSource == SignalSource.HdPlusD) + this.uid = "H" + this.OriginalNetworkId + "-" + this.ServiceId; + else + this.uid = "C-" + this.OriginalNetworkId + "-" + this.TransportStreamId + "-" + this.ServiceId + "-" + this.ChannelOrTransponder; + } + return this.uid; + } + set { this.uid = value; } + } + #endregion + + #region ToString(), Equals(), GetHashCode() + + public override string ToString() + { + return this.Name; + } + + public override bool Equals(object obj) + { + //ChannelInfo that = obj as ChannelInfo; + //return that != null && this.Uid == that.Uid && this.OldProgramNr == that.OldProgramNr; + return ReferenceEquals(this, obj); + } + + public override int GetHashCode() + { + return this.Uid.GetHashCode() + this.OldProgramNr; + } + + #endregion + + #region NetworkName, NetworkOperator + public string NetworkName + { + get + { + var network = LookupData.Instance.GetNetwork(this.OriginalNetworkId); + return network == null ? null : network.Name; + } + } + + public string NetworkOperator + { + get + { + var network = LookupData.Instance.GetNetwork(this.OriginalNetworkId); + return network == null ? null : network.Operator; + } + } + #endregion + + #region ServiceTypeName + public string ServiceTypeName { get { return LookupData.Instance.GetServiceTypeDescription(this.ServiceType); } } + #endregion + + #region GetFavString() + public static string GetFavString(Favorites favorites) + { + string sep = ""; + string text = ""; + foreach (Favorites favMask in Enum.GetValues(typeof(Favorites))) + { + if ((favorites & favMask) != 0) + { + text += sep + favMask.ToString(); + sep = ","; + } + } + return text; + } + #endregion + + #region ParseFavString() + public static Favorites ParseFavString(string value) + { + Favorites favMask = 0; + foreach (Favorites fav in Enum.GetValues(typeof (Favorites))) + { + foreach (char c in value) + { + if (c == fav.ToString()[0]) + { + favMask |= fav; + break; + } + } + } + return favMask; + } + #endregion + + #region AddDebug() + public void AddDebug(byte val) + { + if (this.Debug == null) + this.Debug = val.ToString("x2"); + else + this.Debug += " " + val.ToString("x2"); + } + + public void AddDebug(ushort val) + { + if (this.Debug == null) + this.Debug = val.ToString("x2"); + else + this.Debug += " " + val.ToString("x4"); + } + + public unsafe void AddDebug(byte* ptr, int len) + { + for (int i = 0; i < len; i++) + this.AddDebug(ptr[i]); + } + #endregion + } +} diff --git a/ChanSort.Api/Model/ChannelList.cs b/ChanSort.Api/Model/ChannelList.cs new file mode 100644 index 0000000..48211f2 --- /dev/null +++ b/ChanSort.Api/Model/ChannelList.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Linq; + +namespace ChanSort.Api +{ + public class ChannelList + { + private readonly SignalSource source; + private readonly SignalType type; + private readonly IList channels = new List(); + private readonly Dictionary> channelByUid = new Dictionary>(); + private readonly Dictionary channelByProgNr = new Dictionary(); + private readonly Dictionary> channelByName = new Dictionary>(); + private int insertProgramNr = 1; + private int duplicateUidCount; + private int duplicateProgNrCount; + + public ChannelList(SignalSource source, SignalType type) + { + this.source = source; + this.type = type; + } + + public SignalSource SignalSource { get { return this.source; } } + public SignalType SignalType { get { return this.type; } } + public IList Channels { get { return this.channels; } } + public int Count { get { return channels.Count; } } + public int DuplicateUidCount { get { return duplicateUidCount; } } + public int DuplicateProgNrCount { get { return duplicateProgNrCount; } } + + #region ShortCaption + public string ShortCaption + { + get + { + StringBuilder sb = new StringBuilder(); + switch (this.source) + { + case SignalSource.AnalogC: sb.Append("Analog Cable"); break; + case SignalSource.AnalogT: sb.Append("Analog Antenna"); break; + case SignalSource.AnalogCT: sb.Append("Analog Cable/Antenna"); break; + case SignalSource.DvbC: sb.Append("DVB-C"); break; + case SignalSource.DvbT: sb.Append("DVB-T"); break; + case SignalSource.DvbCT: sb.Append("DVB-C/T"); break; + case SignalSource.DvbS: sb.Append("DVB-S"); break; + case SignalSource.HdPlusD: sb.Append("Astra HD Plus"); break; + default: sb.Append(this.source.ToString()); break; + } + switch (this.type) + { + case SignalType.Tv: sb.Append(" - TV"); break; + case SignalType.Radio: sb.Append(" - Radio"); break; + case SignalType.Mixed: break; + default: sb.Append(this.type.ToString()); break; + } + return sb.ToString(); + } + } + #endregion + + #region Caption + public string Caption + { + get + { + string cap = this.ShortCaption; + int validChannelCount = this.Channels.Count(ch => ch.OldProgramNr != 0); + return cap + " (" + validChannelCount + ")"; + } + } + #endregion + + #region InsertProgramNumber + public int InsertProgramNumber + { + get { return this.Count == 0 ? 1 : this.insertProgramNr; } + set { this.insertProgramNr = Math.Max(1, value); } + } + #endregion + + #region AddChannel() + public string AddChannel(ChannelInfo ci) + { + IList others; + if (this.channelByUid.TryGetValue(ci.Uid, out others)) + { + ++duplicateUidCount; + ChannelInfo twin = others.FirstOrDefault(c => c.OldProgramNr == ci.OldProgramNr); + if (twin != null) + { + string warning = null; + if (ci.OldProgramNr != 0) + { + warning = string.Format(Resources.ChannelList_AddChannel__DuplicateUid, + this.ShortCaption, ci.Name, twin.RecordIndex, twin.OldProgramNr, ci.RecordIndex, + ci.OldProgramNr); + } + twin.Duplicates.Add(ci); + ci.OldProgramNr = 0; + return warning; + } + } + else + { + others = new List(); + this.channelByUid.Add(ci.Uid, others); + others.Add(ci); + } + + string warning2 = null; + bool isDupeProgNr = false; + if (ci.OldProgramNr != 0) + { + ChannelInfo other; + this.channelByProgNr.TryGetValue(ci.OldProgramNr, out other); + if (other != null) + { + warning2 = string.Format(Resources.ChannelList_ProgramNrAssignedToMultipleChannels, + this.ShortCaption, ci.OldProgramNr, other.RecordIndex, other.Name, ci.RecordIndex, ci.Name); + ++duplicateProgNrCount; + isDupeProgNr = true; + } + } + + if (!isDupeProgNr) + this.channelByProgNr[ci.OldProgramNr] = ci; + + var lowerName = ci.Name.ToLower().Trim(); + var byNameList = this.channelByName.TryGet(lowerName); + if (byNameList == null) + { + byNameList = new List(); + this.channelByName[lowerName] = byNameList; + } + byNameList.Add(ci); + + this.channels.Add(ci); + + return warning2; + } + #endregion + + #region GetChannelByUid() + public IList GetChannelByUid(string uid) + { + IList channel; + this.channelByUid.TryGetValue(uid, out channel); + return channel ?? new List(0); + } + #endregion + + #region ToString() + public override string ToString() + { + return this.Caption; + } + #endregion + + #region GetChannelByName() + public IEnumerable GetChannelByName(string name) + { + var hits = this.channelByName.TryGet(name.ToLower().Trim()); + return hits ?? new List(); + } + #endregion + + #region GetChannelByNewProgNr() + public IList GetChannelByNewProgNr(int newProgNr) + { + return this.channels.Where(c => c.NewProgramNr == newProgNr).ToList(); + } + #endregion + } +} diff --git a/ChanSort.Api/Model/DataRoot.cs b/ChanSort.Api/Model/DataRoot.cs new file mode 100644 index 0000000..36a3a32 --- /dev/null +++ b/ChanSort.Api/Model/DataRoot.cs @@ -0,0 +1,82 @@ +using System.Collections.Generic; +using System.Text; + +namespace ChanSort.Api +{ + public class DataRoot + { + private readonly IDictionary satellites = new Dictionary(); + private readonly IDictionary transponder = new Dictionary(); + private readonly IList channelLists = new List(); + private readonly StringBuilder warnings = new StringBuilder(); + + public StringBuilder Warnings { get { return this.warnings; } } + public IDictionary Satellites { get { return this.satellites; } } + public IDictionary Transponder { get { return this.transponder; } } + public ICollection ChannelLists { get { return this.channelLists; } } + public bool IsEmpty { get { return this.channelLists.Count == 0; } } + public bool NeedsSaving { get; set; } + public Favorites SupportedFavorites { get; set; } + + public DataRoot() + { + this.SupportedFavorites = Favorites.A | Favorites.B | Favorites.C | Favorites.D; + } + + #region AddSatellite() + public virtual void AddSatellite(Satellite satellite) + { + this.satellites.Add(satellite.Id, satellite); + } + #endregion + + #region AddTransponder() + public virtual void AddTransponder(Satellite sat, Transponder trans) + { + trans.Satellite = sat; + if (this.transponder.ContainsKey(trans.Id)) + { + this.warnings.AppendFormat("Duplicate transponder data record for satellite #{0} with id {1}\r\n", sat.Id, trans.Id); + return; + } + sat.Transponder.Add(trans.Id, trans); + this.transponder.Add(trans.Id, trans); + } + #endregion + + #region AddChannelList() + public virtual void AddChannelList(ChannelList list) + { + this.channelLists.Add(list); + } + #endregion + + #region AddChannel() + public virtual void AddChannel(ChannelList list, ChannelInfo channel) + { + string warning = list.AddChannel(channel); + if (warning != null) + this.Warnings.AppendLine(warning); + } + #endregion + + + #region GetChannelList() + public ChannelList GetChannelList(SignalSource signalSource, SignalType signalType, bool createIfNotExists) + { + foreach (var list in this.channelLists) + { + if ((list.SignalSource&SignalSource.Digital) != (signalSource&SignalSource.Digital)) // match digital/analog + continue; + if (((int)list.SignalSource & 0x0F & (int)signalSource) == 0) // match any of cable/terrestrial/satellite + continue; + if (list.SignalType == signalType || list.SignalType == SignalType.Mixed) // match radio/tv/any + return list; + } + ChannelList newList = new ChannelList(signalSource, signalType); + this.AddChannelList(newList); + return newList; + } + #endregion + } +} diff --git a/ChanSort.Api/Model/Enums.cs b/ChanSort.Api/Model/Enums.cs new file mode 100644 index 0000000..fbde3bd --- /dev/null +++ b/ChanSort.Api/Model/Enums.cs @@ -0,0 +1,36 @@ +using System; + +namespace ChanSort.Api +{ + [Flags] + public enum SignalSource + { + Analog = 0x00, + Digital = 0x10, + + Cable = 0x01, + Antenna = 0x02, + Sat = 0x04, + HdPlus = 0x08, + + AnalogC=Analog + Cable, + AnalogT=Analog + Antenna, + AnalogCT=Analog + Cable + Antenna, + DvbC = Digital + Cable, + DvbT= Digital + Antenna, + DvbCT= Digital + Cable + Antenna, + DvbS= Digital + Sat, + HdPlusD = Digital + HdPlus + } + public enum SignalType { Tv, Radio, Mixed } + + [Flags] + public enum Favorites : byte { A = 0x01, B = 0x02, C = 0x04, D = 0x08, E = 0x10 } + + public enum UnsortedChannelMode + { + AppendInOrder, + AppendAlphabetically, + Hide + } +} diff --git a/ChanSort.Api/Model/LookupData.cs b/ChanSort.Api/Model/LookupData.cs new file mode 100644 index 0000000..e12ee80 --- /dev/null +++ b/ChanSort.Api/Model/LookupData.cs @@ -0,0 +1,198 @@ +using System.Collections.Generic; +using System.IO; +using System.Reflection; + +namespace ChanSort.Api +{ + public class LookupData + { + private readonly IDictionary networks = new Dictionary(); + private readonly IDictionary transponderNrByFreqInMhz = new Dictionary(); + private readonly IDictionary transponderFreqInMhzByNr = new Dictionary(); + private readonly IDictionary serviceTypeDescriptions = new Dictionary(); + private readonly IDictionary dvbtFreqInMhzByTransponder = new Dictionary(); + + public static readonly LookupData Instance = new LookupData(); + + private LookupData() + { + this.LoadDataFromCsvFile(); + } + + #region GetNetwork() + public NetworkInfo GetNetwork(int networkId) + { + NetworkInfo network; + this.networks.TryGetValue((ushort)networkId, out network); + return network; + } + #endregion + + #region GetTransponderNumber(), GetTransponderFrequency() + public int GetTransponderNumber(int frequencyInMhz) + { + int number; + bool found = this.transponderNrByFreqInMhz.TryGetValue(frequencyInMhz, out number) || + this.transponderNrByFreqInMhz.TryGetValue(frequencyInMhz - 1, out number) || + this.transponderNrByFreqInMhz.TryGetValue(frequencyInMhz + 1, out number) || + this.transponderNrByFreqInMhz.TryGetValue(frequencyInMhz - 2, out number) || + this.transponderNrByFreqInMhz.TryGetValue(frequencyInMhz + 2, out number); + return found ? number : 0; + } + + public int GetTransponderFrequency(int transponderNr) + { + return this.transponderNrByFreqInMhz.TryGet(transponderNr); + } + #endregion + + #region GetDvbtTransponderFrequency() + public int GetDvbtTransponderFrequency(int transponderNr) + { + return this.dvbtFreqInMhzByTransponder.TryGet(transponderNr); + } + #endregion + + #region GetServiceTypeDescription() + public string GetServiceTypeDescription(int serviceType) + { + string descr; + this.serviceTypeDescriptions.TryGetValue(serviceType, out descr); + return descr; + } + #endregion + + #region LoadDataFromCsvFile() + public void LoadDataFromCsvFile() + { + this.networks.Clear(); + this.transponderFreqInMhzByNr.Clear(); + this.transponderNrByFreqInMhz.Clear(); + this.serviceTypeDescriptions.Clear(); + this.dvbtFreqInMhzByTransponder.Clear(); + + string file = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "lookup.csv"); + if (!File.Exists(file)) + return; + using (var reader = new StreamReader(file, System.Text.Encoding.UTF8)) + { + string line; + while ((line = reader.ReadLine()) != null) + { + var fields = CsvFile.Parse(line, ';'); + if (fields.Count == 0) + continue; + switch (fields[0].ToLower()) + { + case "onid": this.ParseNetwork(fields); break; + case "dvbt": this.ParseDvbtTransponder(fields); break; + case "transp": this.ParseTransponder(fields); break; + case "servicetype": this.ParseServiceType(fields); break; + } + } + } + } + #endregion + + #region AddNetwork() + private void AddNetwork(NetworkInfo network) + { + this.networks[network.OriginalNetworkId] = network; + } + #endregion + + #region AddTransponderMapping() + private void AddTransponderMapping(int transponderNr, int frequencyInMhz) + { + this.transponderNrByFreqInMhz[frequencyInMhz] = transponderNr; + this.transponderFreqInMhzByNr[transponderNr] = frequencyInMhz; + } + #endregion + + #region AddDvbtTransponderMapping() + private void AddDvbtTransponderMapping(int transponderNr, int frequencyInMhz) + { + this.dvbtFreqInMhzByTransponder[transponderNr] = frequencyInMhz; + } + #endregion + + #region AddServiceType() + public void AddServiceType(int serviceType, string description) + { + this.serviceTypeDescriptions[serviceType] = description; + } + #endregion + + #region ParseNetwork() + private void ParseNetwork(IList fields) + { + if (fields.Count < 3) + return; + int start = ParseNumber(fields[1]); + int end = ParseNumber(fields[2]); + if (start == 0 || end == 0 || start > end) + return; + for (int onid = start; onid <= end; onid++) + { + var network = new NetworkInfo(); + network.OriginalNetworkId = onid; + if (fields.Count >= 4) + network.Name = fields[3]; + if (fields.Count >= 5) + network.Operator = fields[4]; + this.AddNetwork(network); + } + } + #endregion + + #region ParseNumber() + private int ParseNumber(string nr) + { + int number; + if (nr.StartsWith("0x")) + int.TryParse(nr.Substring(2), System.Globalization.NumberStyles.HexNumber, System.Globalization.NumberFormatInfo.InvariantInfo, out number); + else + int.TryParse(nr, System.Globalization.NumberStyles.Integer, System.Globalization.NumberFormatInfo.InvariantInfo, out number); + return number; + } + #endregion + + #region ParseTransponder() + private void ParseTransponder(IList fields) + { + if (fields.Count < 3) + return; + int nr, freq; + int.TryParse(fields[1], out nr); + int.TryParse(fields[2], out freq); + if (nr == 0 || freq == 0) + return; + this.AddTransponderMapping(nr, freq); + } + #endregion + + #region ParseTransponder() + private void ParseDvbtTransponder(IList fields) + { + if (fields.Count < 3) + return; + int nr, freq; + int.TryParse(fields[1], out nr); + int.TryParse(fields[2], out freq); + if (nr == 0 || freq == 0) + return; + this.AddDvbtTransponderMapping(nr, freq); + } + #endregion + + #region ParseServiceType() + private void ParseServiceType(IList fields) + { + if (fields.Count < 3) return; + int serviceType = this.ParseNumber(fields[1]); + if (serviceType <= 0) return; + this.AddServiceType(serviceType, fields[2]); + } + #endregion + } +} diff --git a/ChanSort.Api/Model/NetworkInfo.cs b/ChanSort.Api/Model/NetworkInfo.cs new file mode 100644 index 0000000..3adb984 --- /dev/null +++ b/ChanSort.Api/Model/NetworkInfo.cs @@ -0,0 +1,9 @@ +namespace ChanSort.Api +{ + public class NetworkInfo + { + public int OriginalNetworkId { get; set; } + public string Name { get; set; } + public string Operator { get; set; } + } +} diff --git a/ChanSort.Api/Model/Satellite.cs b/ChanSort.Api/Model/Satellite.cs new file mode 100644 index 0000000..a74c460 --- /dev/null +++ b/ChanSort.Api/Model/Satellite.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; + +namespace ChanSort.Api +{ + public class Satellite + { + private readonly int id; + private readonly IDictionary transponder = new Dictionary(); + + public int Id { get { return this.id; } } + public string Name { get; set; } + public string OrbitalPosition { get; set; } + public IDictionary Transponder { get { return this.transponder; } } + + public Satellite(int id) + { + this.id = id; + } + + public override string ToString() + { + return Name; + } + } +} diff --git a/ChanSort.Api/Model/Transponder.cs b/ChanSort.Api/Model/Transponder.cs new file mode 100644 index 0000000..c1191d5 --- /dev/null +++ b/ChanSort.Api/Model/Transponder.cs @@ -0,0 +1,22 @@ +namespace ChanSort.Api +{ + public class Transponder + { + private readonly int id; + + public int Id { get { return id; } } + public Satellite Satellite { get; set; } + public decimal FrequencyInMhz { get; set; } + public int Number { get; set; } + public int SymbolRate { get; set; } + public char Polarity { get; set; } + public int OriginalNetworkId { get; set; } + public int TransportStreamId { get; set; } + + public Transponder(int id) + { + this.id = id; + } + + } +} diff --git a/ChanSort.Api/Properties/AssemblyInfo.cs b/ChanSort.Api/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..41ef729 --- /dev/null +++ b/ChanSort.Api/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("API")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("API")] +[assembly: AssemblyCopyright("Copyright © 2012")] +[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("5cd52683-ba04-4610-8435-ba409a37e08f")] + +// 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/ChanSort.Api/Resources.Designer.cs b/ChanSort.Api/Resources.Designer.cs new file mode 100644 index 0000000..8de5a0e --- /dev/null +++ b/ChanSort.Api/Resources.Designer.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.586 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ChanSort.Api { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ChanSort.Api.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to {0}: Channel '{1}' has multiple data records: index {2}=Pr#{3} and index {4}=Pr#{5}. + /// + internal static string ChannelList_AddChannel__DuplicateUid { + get { + return ResourceManager.GetString("ChannelList_AddChannel__DuplicateUid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} Program #{1} is assigned to multiple channels: index {2}='{3}' and index {4}='{5}'. + /// + internal static string ChannelList_ProgramNrAssignedToMultipleChannels { + get { + return ResourceManager.GetString("ChannelList_ProgramNrAssignedToMultipleChannels", resourceCulture); + } + } + } +} diff --git a/ChanSort.Api/Resources.de.Designer.cs b/ChanSort.Api/Resources.de.Designer.cs new file mode 100644 index 0000000..e69de29 diff --git a/ChanSort.Api/Resources.de.resx b/ChanSort.Api/Resources.de.resx new file mode 100644 index 0000000..97ce43a --- /dev/null +++ b/ChanSort.Api/Resources.de.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + {0} Program #{1} ist mehreren Sendern zugeordnet: Index {2}='{3}' und Index {4}='{5}' + + + {0}: Sender '{1}' ist in mehreren Datensätzen enthalten: Index {2}=Pr#{3} und Index {4}=Pr#{5} + + \ No newline at end of file diff --git a/ChanSort.Api/Resources.resx b/ChanSort.Api/Resources.resx new file mode 100644 index 0000000..57683a7 --- /dev/null +++ b/ChanSort.Api/Resources.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + {0} Program #{1} is assigned to multiple channels: index {2}='{3}' and index {4}='{5}' + + + {0}: Channel '{1}' has multiple data records: index {2}=Pr#{3} and index {4}=Pr#{5} + + \ No newline at end of file diff --git a/ChanSort.Api/Utils/ChannelMappingBase.cs b/ChanSort.Api/Utils/ChannelMappingBase.cs new file mode 100644 index 0000000..065c9d7 --- /dev/null +++ b/ChanSort.Api/Utils/ChannelMappingBase.cs @@ -0,0 +1,151 @@ +using System.Text; + +namespace ChanSort.Api +{ + public unsafe class ChannelMappingBase : DataMapping + { + protected const string offInUse = "offInUse"; + protected const string maskInUse = "maskInUse"; + protected const string offProgramNr = "offProgramNr"; + protected const string offName = "offName"; + protected const string offNameLength = "offNameLength"; + protected const string lenName = "lenName"; + protected const string offSkip = "offSkip"; + protected const string maskSkip = "maskSkip"; + protected const string offLock = "offLock"; + protected const string maskLock = "maskLock"; + protected const string offLockSkipHide = "offHide"; + protected const string maskHide = "maskHide"; + protected const string offFavorites = "offFavorites"; + private const string offDeleted = "offDeleted"; + private const string maskDeleted = "maskDeleted"; + + #region ctor() + public ChannelMappingBase(IniFile.Section settings, int length, Encoding stringEncoding) : + base(settings, length, stringEncoding) + { + } + #endregion + + #region InUse + public virtual bool InUse + { + get + { + var val = this.GetOffsets(offInUse); + return val.Length == 0 || this.GetFlag(offInUse, maskInUse); + } + } + #endregion + + #region ProgramNr + public virtual ushort ProgramNr + { + get { return this.GetWord(offProgramNr); } + set { this.SetWord(offProgramNr, value); } + } + #endregion + + #region NameLength + public virtual int NameLength + { + get + { + var off = this.GetOffsets(offNameLength); + if (off.Length > 0) + return this.GetWord(off[0]); + return MaxNameLength; + } + set { this.SetByte(offNameLength, (byte) value); } + } + #endregion + + #region MaxNameLength + public virtual int MaxNameLength + { + get + { + var off = this.GetOffsets(lenName); // not an offset! + return off.Length > 0 ? off[0] : 0; + } + } + #endregion + + #region Name + public virtual string Name + { + get { return this.GetString(offName, this.NameLength); } +// ReSharper disable ValueParameterNotUsed + set { } +// ReSharper restore ValueParameterNotUsed + } + #endregion + + #region NamePtr + + public virtual byte* NamePtr + { + get { return this.DataPtr + this.GetOffsets(offName)[0]; } + set + { + int maxLen = this.MaxNameLength - 1; + if (maxLen == 0) + maxLen = this.NameLength; + foreach (int off in this.GetOffsets(offName)) + { + int i; + for (i = 0; i < maxLen && value[i] != 0; i++) + this.DataPtr[off + i] = value[i]; + for (; i <= maxLen; i++) + this.DataPtr[off + i] = 0; + } + } + } + #endregion + + #region ShortName + public virtual string ShortName { get; set; } + #endregion + + #region Skip + public virtual bool Skip + { + get { return this.GetFlag(offSkip, maskSkip); } + set { this.SetFlag(offSkip, maskSkip, value); } + } + #endregion + + #region Lock + public virtual bool Lock + { + get { return this.GetFlag(offLock, maskLock); } + set { this.SetFlag(offLock, maskLock, value); } + } + #endregion + + #region Hide + public virtual bool Hide + { + get { return this.GetFlag(offLockSkipHide, maskHide); } + set { this.SetFlag(offLockSkipHide, maskHide, value); } + } + #endregion + + #region Favorites + public virtual Favorites Favorites + { + get { return (Favorites) this.GetByte(offFavorites); } + set { this.SetByte(offFavorites, (byte) value); } + } + #endregion + + #region IsDeleted + public virtual bool IsDeleted + { + get { return this.GetFlag(offDeleted, maskDeleted); } + set { this.SetFlag(offDeleted, maskDeleted, value); } + } + #endregion + } + +} diff --git a/ChanSort.Api/Utils/Crc32.cs b/ChanSort.Api/Utils/Crc32.cs new file mode 100644 index 0000000..43ae1c9 --- /dev/null +++ b/ChanSort.Api/Utils/Crc32.cs @@ -0,0 +1,60 @@ +namespace ChanSort.Api +{ + public static class Crc32 + { + private const uint CrcMask = 0xFFFFFFFF; + private const uint CrcPoly = 0xEDB88320; + + private static readonly uint[] crc32Table; + + static Crc32() + { + crc32Table = InitCrc32Table(); + } + + #region InitCrc32Table() + + private static uint[] InitCrc32Table() + { + var crcTable = new uint[256]; + for (uint i = 0; i < 256; i++) + { + uint r = i; + for (uint j = 8; j > 0; j--) + { + if ((r & 1) == 1) + r = ((r >> 1) ^ CrcPoly); + else + r >>= 1; + } + crcTable[i] = r; + } + return crcTable; + } + #endregion + + #region CalcCrc32() + public static unsafe uint CalcCrc32(byte* block, int length) + { + uint crc32 = CrcMask; + for (int i = 0; i < length; i++) + crc32 = crc32Table[(crc32 & 0xff) ^ block[i]] ^ (crc32 >> 8); + return crc32; + } + #endregion + + #region Crack() + public static unsafe int Crack(byte* block, int maxLen, uint checksum) + { + uint crc32 = CrcMask; + for (int i = 0; i < maxLen; i++) + { + if (crc32 == checksum) + return i; + crc32 = crc32Table[(crc32 & 0xff) ^ block[i]] ^ (crc32 >> 8); + } + return 0; + } + #endregion + } +} diff --git a/ChanSort.Api/Utils/CsvFile.cs b/ChanSort.Api/Utils/CsvFile.cs new file mode 100644 index 0000000..9ad4147 --- /dev/null +++ b/ChanSort.Api/Utils/CsvFile.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using System.Text; + +namespace ChanSort.Api +{ + public static class CsvFile + { + public static IList Parse(string line, char separator) + { + if (line.EndsWith("\n")) line = line.Substring(0, line.Length - 1); + if (line.EndsWith("\r")) line = line.Substring(0, line.Length - 1); + + List tokens = new List(); + if (line.Length == 0) + return tokens; + + bool inQuote = false; + StringBuilder token = new StringBuilder(); + for(int i = 0, len=line.Length; i 0 ? this.GetByte(offsets[0]) : (byte)0; + } + #endregion + + #region GetWord() + public ushort GetWord(int off) + { + return off < 0 ? (ushort)0 : *(ushort*) (this.DataPtr + off); + } + + public ushort GetWord(string key) + { + var offsets = settings.GetIntList(key); + return offsets.Length > 0 ? this.GetWord(offsets[0]) : (ushort)0; + } + #endregion + + #region GetDword() + public uint GetDword(int off) + { + return off < 0 ? 0 : *(uint*) (this.DataPtr + off); + } + + public uint GetDword(string key) + { + var offsets = settings.GetIntList(key); + return offsets.Length > 0 ? this.GetDword(offsets[0]) : 0; + } + #endregion + + #region GetFloat() + public float GetFloat(int off) + { + return off < 0 ? 0 : *(float*) (this.DataPtr + off); + } + + public float GetFloat(string key) + { + var offsets = settings.GetIntList(key); + return offsets.Length > 0 ? this.GetFloat(offsets[0]) : 0; + } + #endregion + + #region GetFlag() + public bool GetFlag(int offset, byte mask) + { + return offset >= 0 && (this.GetByte(offset) & mask) != 0; + } + + public bool GetFlag(string valueKey, string maskKey) + { + byte mask = (byte)settings.GetInt(maskKey); + var offsets = settings.GetIntList(valueKey); + return offsets.Length > 0 && this.GetFlag(offsets[0], mask); + } + #endregion + + #region GetString() + public string GetString(int offset, int maxByteLen) + { + if (offset < 0) return null; + byte[] buffer = new byte[maxByteLen]; + for (int i = 0; i < maxByteLen; i++) + buffer[i] = this.DataPtr[offset + i]; + return stringEncoding.GetString(buffer).TrimEnd('\0'); + } + + public string GetString(string key, int maxLen) + { + var offsets = settings.GetIntList(key); + return offsets.Length == 0 ? null : GetString(offsets[0], maxLen); + } + #endregion + + + #region SetByte() + public void SetByte(int off, byte value) + { + if (off >= 0) + this.DataPtr[off] = value; + } + + public void SetByte(string key, byte value) + { + var offsets = settings.GetIntList(key); + foreach(int offset in offsets) + this.SetByte(offset, value); + } + #endregion + + #region SetWord() + public void SetWord(int off, int value) + { + if (off >= 0) + *(ushort*) (this.DataPtr + off) = (ushort)value; + } + + public void SetWord(string key, int value) + { + var offsets = settings.GetIntList(key); + foreach (int offset in offsets) + this.SetWord(offset, value); + } + #endregion + + #region SetDword() + public void SetDword(int off, uint value) + { + if (off >= 0) + *(uint*) (this.DataPtr + off) = value; + } + + public void SetDword(string key, uint value) + { + var offsets = settings.GetIntList(key); + foreach (int offset in offsets) + this.SetDword(offset, value); + } + #endregion + + #region SetFloat() + public void SetFloat(int off, float value) + { + if (off >= 0) + *(float*)(this.DataPtr + off) = value; + } + + public void SetFloat(string key, float value) + { + var offsets = settings.GetIntList(key); + foreach (int offset in offsets) + this.SetFloat(offset, value); + } + #endregion + + #region SetFlag() + public void SetFlag(int offset, byte mask, bool set) + { + byte val = this.GetByte(offset); + this.SetByte(offset, (byte)(set ? val | mask : val & ~mask)); + } + + public void SetFlag(string valueKey, string maskKey, bool set) + { + byte mask = (byte)settings.GetInt(maskKey); + var offsets = settings.GetIntList(valueKey); + foreach (int offset in offsets) + this.SetFlag(offset, mask, set); + } + #endregion + } + +} diff --git a/ChanSort.Api/Utils/DvbChannelMappingBase.cs b/ChanSort.Api/Utils/DvbChannelMappingBase.cs new file mode 100644 index 0000000..d64c1aa --- /dev/null +++ b/ChanSort.Api/Utils/DvbChannelMappingBase.cs @@ -0,0 +1,125 @@ +using System.Text; + +namespace ChanSort.Api +{ + public class DvbChannelMappingBase : ChannelMappingBase + { + protected const string offChannelTransponder = "offChannelTransponder"; + protected const string offPcrPid = "offPcrPid"; + protected const string offVideoPid = "offVideoPid"; + protected const string offAudioPid = "offAudioPid"; + protected const string offServiceId = "offServiceId"; + protected const string offOriginalNetworkId = "offOriginalNetworkId"; + protected const string offTransportStreamId = "offTransportStreamId"; + protected const string offServiceType = "offServiceType"; + protected const string offSymbolRate = "offSymbolRate"; + protected const string offEncrypted = "offEncrypted"; + protected const string maskEncrypted = "maskEncrypted"; + protected const string offShortName = "offShortName"; + protected const string offShortNameLength = "offShortNameLength"; + protected const string lenShortName = "lenShortName"; + + + #region ctor() + public DvbChannelMappingBase(IniFile.Section settings, int dataLength, Encoding stringEncoding) + : base(settings, dataLength, stringEncoding) + { + } + #endregion + + #region ChannelOrTransponder + public virtual byte ChannelOrTransponder + { + get { return this.GetByte(offChannelTransponder); } + set { this.SetByte(offChannelTransponder, value); } + } + #endregion + + #region ShortName + public int ShortNameLength + { + get + { + var off = this.GetOffsets(offShortNameLength); + if (off.Length > 0) + return this.GetWord(off[0]); + off = this.GetOffsets(lenShortName); // not an offset! + return off.Length > 0 ? off[0] : 0; + } + } + + public override string ShortName { get { return this.GetString(offShortName, this.ShortNameLength); } } + #endregion + + #region PcrPid + public virtual ushort PcrPid + { + get { return this.GetWord(offPcrPid); } + set { this.SetWord(offPcrPid, value); } + } + #endregion + + #region VideoPid + public virtual ushort VideoPid + { + get { return this.GetWord(offVideoPid); } + set { this.SetWord(offVideoPid, value); } + } + #endregion + + #region AudioPid + public virtual ushort AudioPid + { + get { return this.GetWord(offAudioPid); } + set { this.SetWord(offAudioPid, value); } + } + #endregion + + #region ServiceId + public virtual ushort ServiceId + { + get { return this.GetWord(offServiceId); } + set { this.SetWord(offServiceId, value); } + } + #endregion + + #region OriginalNetworkId + public virtual ushort OriginalNetworkId + { + get { return this.GetWord(offOriginalNetworkId); } + set { this.SetWord(offOriginalNetworkId, value); } + } + #endregion + + #region TransportStreamId + public virtual ushort TransportStreamId + { + get { return this.GetWord(offTransportStreamId); } + set { this.SetWord(offTransportStreamId, value); } + } + #endregion + + #region ServiceType + public virtual byte ServiceType + { + get { return this.GetByte(offServiceType); } + set { this.SetByte(offServiceType, value); } + } + #endregion + + #region SymbolRate + public virtual ushort SymbolRate + { + get { return this.GetWord(offSymbolRate); } + set { this.SetWord(offSymbolRate, value); } + } + #endregion + + #region Encrypted + public virtual bool Encrypted + { + get { return this.GetFlag(offEncrypted, maskEncrypted); } + } + #endregion + } +} diff --git a/ChanSort.Api/Utils/DvbStringDecoder.cs b/ChanSort.Api/Utils/DvbStringDecoder.cs new file mode 100644 index 0000000..2bfbc96 --- /dev/null +++ b/ChanSort.Api/Utils/DvbStringDecoder.cs @@ -0,0 +1,196 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ChanSort.Api +{ + #region Documentation + /* + ETSI EN 300 468 + + For one-byte character tables, the codes in the range 0x80 to 0x9F are assigned to control functions + as shown in Table A.1: Single byte control codes + + Control code - Control code Description + 0x80 to 0x85 reserved for future use + 0x86 character emphasis on + 0x87 character emphasis off + 0x88 to 0x89 reserved for future use + 0x8A CR/LF + 0x8B to 0x9F user defined + + A.2 Selection of character table + First byte value - Character code table - Table description - Reproduced in figure + 0x01 ISO/IEC 8859-5 [27] Latin/Cyrillic alphabet A.2 + 0x02 ISO/IEC 8859-6 [28] Latin/Arabic alphabet A.3 + 0x03 ISO/IEC 8859-7 [29] Latin/Greek alphabet A.4 + 0x04 ISO/IEC 8859-8 [30] Latin/Hebrew alphabet A.5 + 0x05 ISO/IEC 8859-9 [31] Latin alphabet No. 5 A.6 + 0x06 ISO/IEC 8859-10 [32] Latin alphabet No. 6 A.7 + 0x07 ISO/IEC 8859-11 [33] Latin/Thai (draft only) A.8 + 0x08 reserved for future use (see note) + 0x09 ISO/IEC 8859-13 [34] Latin alphabet No. 7 A.9 + 0x0A ISO/IEC 8859-14 [35] Latin alphabet No. 8 (Celtic) A.10 + 0x0B ISO/IEC 8859-15 [36] Latin alphabet No. 9 A.11 + 0x0C to 0x0F reserved for future use + 0x10 ISO/IEC 8859 See table A.4 + 0x11 ISO/IEC 10646 [16] Basic Multilingual Plane (BMP) + 0x12 KSX1001-2004 [44] Korean Character Set + 0x13 GB-2312-1980 Simplified Chinese Character + 0x14 Big5 subset of ISO/IEC 10646 [16] Traditional Chinese + 0x15 UTF-8 encoding of ISO/IEC 10646 [16] Basic Multilingual Plane (BMP) + 0x16 to 0x1E reserved for future use + 0x1F Described by encoding_type_id Described by 8 bit + + Table A.4: Character Coding Tables for first byte 0x10 + First byte value - Second byte value - Third Byte Value - Selected character code - table - Table Description + 0x10 0x00 0x00 reserved for future use + 0x10 0x00 0x01 ISO/IEC 8859-1 [23] West European + 0x10 0x00 0x02 ISO/IEC 8859-2 [24] East European + 0x10 0x00 0x03 ISO/IEC 8859-3 [25] South European + 0x10 0x00 0x04 ISO/IEC 8859-4 [26] North and North-East European + 0x10 0x00 0x05 ISO/IEC 8859-5 [27] Latin/Cyrillic A.2 + 0x10 0x00 0x06 ISO/IEC 8859-6 [28] Latin/Arabic A.3 + 0x10 0x00 0x07 ISO/IEC 8859-7 [29] Latin/Greek A.4 + 0x10 0x00 0x08 ISO/IEC 8859-8 [30] Latin/Hebrew A.5 + 0x10 0x00 0x09 ISO/IEC 8859-9 [31] West European & Turkish A.6 + 0x10 0x00 0x0A ISO/IEC 8859-10 [32] North European A.7 + 0x10 0x00 0x0B ISO/IEC 8859-11 [33] Thai A.8 + 0x10 0x00 0x0C Reserved for future use + 0x10 0x00 0x0D ISO/IEC 8859-13 [34] Baltic A.9 + 0x10 0x00 0x0E ISO/IEC 8859-14 [35] Celtic A.10 + 0x10 0x00 0x0F ISO/IEC 8859-15 [36] West European A.11 + */ + #endregion + + public class DvbStringDecoder + { + static readonly string[] codePages1 = + { + null, "iso-8859-5", "iso-8859-6", "iso-8859-7", "iso-8859-8", "iso-8859-9", "iso-8859-10", "iso-8859-11", + null, "iso-8859-13", "iso-8859-14", "iso-8859-15", null, null, null, null, + null, // codePages2 prefix + "utf-16", "x-cp20949", "x-cp20936", "utf-16", "utf-8", null, null, null + }; + + static readonly string[] codePages2 = + { + null, "iso-8859-1", "iso-8859-2", "iso-8859-3", "iso-8859-4", "iso-8859-5", "iso-8859-6", "iso-8859-7", + "iso-8859-8", "iso-8859-9", "iso-8859-10", "iso-8859-11", null, "iso-8859-13", "iso-8859-14", "iso-8859-15" + }; + + private readonly Dictionary decoderCache = new Dictionary(); + + public DvbStringDecoder(Encoding defaultEncoding) + { + this.DefaultEncoding = defaultEncoding; + } + + public Encoding DefaultEncoding { get; set; } + + #region GetChannelNames() + public unsafe void GetChannelNames(byte* name, int len, out string longName, out string shortName) + { + StringBuilder sbLong = new StringBuilder(); + StringBuilder sbShort = new StringBuilder(); + Decoder decoder = this.DefaultEncoding.GetDecoder(); + bool inShortMode = false; + for (int i = 0; i < len; i++) + { + byte b = name[i]; + if (b == 0x00) + break; + if (b == 0x10) // prefix for 3-byte code page + { + int cpIndex = name[i + 1] * 256 + name[i + 2]; + i += 2; + SetDecoder(codePages2, cpIndex, ref decoder); + continue; + } + if (b <= 0x1F) + { + SetDecoder(codePages1, b, ref decoder); + continue; + } + + char ch = '\0'; + switch (b) + { + case 0x86: inShortMode = true; break; + case 0x87: inShortMode = false; break; + case 0x8a: ch = '\n'; break; + default: + // read as many bytes as necessary to get a character + char[] charArray = new char[1]; + fixed (char* pCh = charArray) + { + byte* start = name + i; + for (int j = 1; i < len && decoder.GetChars(start, j, pCh, 1, true) == 0; ++j) + ++i; + } + ch = charArray[0]; + break; + } + + if (ch == '\0') + continue; + + sbLong.Append(ch); + if (inShortMode) + sbShort.Append(ch); + } + longName = sbLong.ToString(); + shortName = sbShort.ToString(); + } + #endregion + + #region SetDecoder() + private void SetDecoder(string[] codePages, int cpIndex, ref Decoder defaultDecoder) + { + if (cpIndex >= codePages.Length) + return; + Decoder decoder; + + string cp = codePages[cpIndex]; + if (cp == null) + return; + + if (this.decoderCache.TryGetValue(cp, out decoder)) + { + defaultDecoder = decoder; + return; + } + + try + { + var encoding = Encoding.GetEncoding(cp); + defaultDecoder = encoding.GetDecoder(); + } + catch (ArgumentException) + { + } + decoderCache[cp] = defaultDecoder; + } + #endregion + + #region GetCodepageBytes() + public static byte[] GetCodepageBytes(Encoding encoding) + { + var encName = encoding.WebName; + for (int i = 0; i < codePages1.Length; i++) + { + if (codePages1[i] == encName) + return new [] {(byte)i}; + } + + for (int i = 0; i < codePages2.Length; i++) + { + if (codePages2[i] == encName) + return new[] { (byte)0x10, (byte)i }; + } + + return new byte[0]; + } + #endregion + } +} diff --git a/ChanSort.Api/Utils/IniFile.cs b/ChanSort.Api/Utils/IniFile.cs new file mode 100644 index 0000000..4e719a2 --- /dev/null +++ b/ChanSort.Api/Utils/IniFile.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace ChanSort.Api +{ + public class IniFile + { + #region class Section + + public class Section + { + private readonly Dictionary data = new Dictionary(StringComparer.CurrentCultureIgnoreCase); + + public Section(string name) + { + this.Name = name; + } + + #region Name + public string Name { get; private set; } + #endregion + + #region Set() + internal void Set(string key, string value) + { + data[key] = value; + } + #endregion + + #region Keys + public IEnumerable Keys { get { return data.Keys; } } + #endregion + + #region GetString() + + public string GetString(string key) + { + string value; + if (!data.TryGetValue(key, out value)) + return null; + return value; + } + + #endregion + + #region GetInt() + + public int GetInt(string key, int defaultValue = 0) + { + string value; + if (!data.TryGetValue(key, out value)) + return defaultValue; + return this.ParseNumber(value); + } + + #endregion + + #region GetBytes() + + public byte[] GetBytes(string key) + { + string value; + if (!data.TryGetValue(key, out value)) + return null; + if (string.IsNullOrEmpty(value)) + return new byte[0]; + + string[] parts = value.Split(','); + byte[] bytes = new byte[parts.Length]; + int i = 0; + foreach (var part in parts) + bytes[i++] = (byte)this.ParseNumber(part); + return bytes; + } + + #endregion + + #region GetIntList() + public int[] GetIntList(string key) + { + string value = this.GetString(key); + if (string.IsNullOrEmpty(value)) + return new int[0]; + string[] numbers = value.Split(','); + int[] ret = new int[numbers.Length]; + for (int i = 0; i < numbers.Length; i++) + ret[i] = this.ParseNumber(numbers[i]); + return ret; + } + #endregion + + #region ParseNumber() + private int ParseNumber(string value) + { + if (value.ToLower().StartsWith("0x")) + { + try { return Convert.ToInt32(value, 16); } + catch { return 0; } + } + int intValue; + int.TryParse(value, out intValue); + return intValue; + } + #endregion + } + #endregion + + private readonly Dictionary sectionDict; + private readonly List
sectionList; + + public IniFile(string fileName) + { + this.sectionDict = new Dictionary(); + this.sectionList = new List
(); + this.ReadIniFile(fileName); + } + + public IEnumerable
Sections + { + get { return this.sectionList; } + } + + public Section GetSection(string sectionName) + { + return sectionDict.TryGet(sectionName); + } + + #region ReadIniFile() + private void ReadIniFile(string fileName) + { + using (StreamReader rdr = new StreamReader(fileName)) + { + Section currentSection = null; + string line; + while ((line = rdr.ReadLine()) != null) + { + string trimmedLine = line.Trim(); + if (trimmedLine.StartsWith(";")) + continue; + if (trimmedLine.StartsWith("[")) + { + string sectionName = trimmedLine.EndsWith("]") + ? trimmedLine.Substring(1, trimmedLine.Length - 2) + : trimmedLine.Substring(1); + currentSection = new Section(sectionName); + this.sectionList.Add(currentSection); + this.sectionDict[sectionName] = currentSection; + continue; + } + if (currentSection == null) + continue; + int idx = trimmedLine.IndexOf("="); + if (idx < 0) + continue; + string key = trimmedLine.Substring(0, idx).Trim(); + string val = trimmedLine.Substring(idx + 1).Trim(); + currentSection.Set(key, val); + } + } + } + #endregion + } +} diff --git a/ChanSort.Api/Utils/MappingPool.cs b/ChanSort.Api/Utils/MappingPool.cs new file mode 100644 index 0000000..9329efa --- /dev/null +++ b/ChanSort.Api/Utils/MappingPool.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; + +namespace ChanSort.Api +{ + public class MappingPool where T : DataMapping + { + private const string ERR_unknownACTChannelDataLength = "Configuration doesn't contain a {0} data mapping for length {1}"; + private readonly Dictionary mappings = new Dictionary(); + private readonly string caption; + + public MappingPool(string caption) + { + this.caption = caption; + } + + public void AddMapping(T mapping) + { + mappings[mapping.DataLength] = mapping; + } + + public T GetMapping(int dataLength, bool throwException = true) + { + if (dataLength == 0) + return null; + + T mapping; + if (!mappings.TryGetValue(dataLength, out mapping) && throwException) + throw new Exception(string.Format(ERR_unknownACTChannelDataLength, this.caption, dataLength)); + return mapping; + } + } +} diff --git a/ChanSort.Api/Utils/Tools.cs b/ChanSort.Api/Utils/Tools.cs new file mode 100644 index 0000000..75c4809 --- /dev/null +++ b/ChanSort.Api/Utils/Tools.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using System.Text; + +namespace ChanSort.Api +{ + public static class Tools + { + public static V TryGet(this IDictionary dict, K key) + { + V val; + dict.TryGetValue(key, out val); + return val; + } + + public static unsafe string GetString(this Encoding encoding, byte* str, int len) + { + byte[] copy = new byte[len]; + for (int i = 0; i < len; i++) + copy[i] = *str++; + string name = encoding.GetString(copy, 0, len); + int idx = name.IndexOf('\0'); + if (idx >= 0) + name = name.Substring(0, idx); + return name; + } + } +} diff --git a/ChanSort.Plugin.ScmFile/AnalogChannelDataMapping.cs b/ChanSort.Plugin.ScmFile/AnalogChannelDataMapping.cs new file mode 100644 index 0000000..7d0f971 --- /dev/null +++ b/ChanSort.Plugin.ScmFile/AnalogChannelDataMapping.cs @@ -0,0 +1,72 @@ +using System.Text; +using ChanSort.Api; + +namespace ChanSort.Plugin.ScmFile +{ + internal class AnalogChannelDataMapping : ChannelMappingBase + { + const string offFrequency = "offFrequency"; + const string offChecksum = "offChecksum"; + + #region ctor() + public AnalogChannelDataMapping(IniFile.Section settings, int length) : + base(settings, length, new UnicodeEncoding(true, false)) + { + } + #endregion + + #region Favorites + public override Favorites Favorites + { + get + { + if (this.DataLength < 64) + return base.Favorites; + + byte fav = 0; + byte mask = 0x01; + foreach (int off in this.GetOffsets(offFavorites)) + { + if (this.GetByte(off) == 1) + fav |= mask; + mask <<= 1; + } + return (Favorites)fav; + } + set + { + if (this.DataLength < 64) + { + base.Favorites = value; + return; + } + + int intValue = (int)value; + foreach (int off in this.GetOffsets(offFavorites)) + { + if ((intValue & 1) != 0) + this.SetByte(off, 1); + intValue >>= 1; + } + } + } + #endregion + + #region Frequency + public float Frequency + { + get { return this.GetFloat(offFrequency); } + set { this.SetFloat(offFrequency, value); } + } + #endregion + + #region Checksum + public byte Checksum + { + get { return this.GetByte(offChecksum); } + set { this.SetByte(offChecksum, value); } + } + #endregion + } + +} diff --git a/ChanSort.Plugin.ScmFile/ChanSort.Plugin.ScmFile.csproj b/ChanSort.Plugin.ScmFile/ChanSort.Plugin.ScmFile.csproj new file mode 100644 index 0000000..1bec959 --- /dev/null +++ b/ChanSort.Plugin.ScmFile/ChanSort.Plugin.ScmFile.csproj @@ -0,0 +1,98 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {A1C9A98D-368A-44E8-9B7F-7EACA46C9EC5} + Library + Properties + ChanSort.Plugin.ScmFile + ChanSort.Plugin.ScmFile + v3.5 + 512 + Client + + + true + full + false + ..\Debug\ + DEBUG;TRACE + prompt + 4 + true + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + ..\Debug\ + DEBUG;TRACE + true + full + x86 + prompt + false + false + false + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + true + true + true + + + + False + ..\DLL\ICSharpCode.SharpZipLib.dll + + + + + + + + + + + + + + + + + + + {DCCFFA08-472B-4D17-BB90-8F513FC01392} + ChanSort.Api + + + + + Always + + + + + \ No newline at end of file diff --git a/ChanSort.Plugin.ScmFile/ChanSort.Plugin.ScmFile.ini b/ChanSort.Plugin.ScmFile/ChanSort.Plugin.ScmFile.ini new file mode 100644 index 0000000..892f4f4 --- /dev/null +++ b/ChanSort.Plugin.ScmFile/ChanSort.Plugin.ScmFile.ini @@ -0,0 +1,334 @@ +[Series:B] + SatDataBase.dat = 145 + TransponderDataBase.dat = 49 + FineTune = 20 + FineTune_Digital = 28 + map-AirA = 28 + map-AirD = 248 + map-CableD = 248 + map-SateD = 144 + Favorites = 4 + +[Series:C] + SatDataBase.dat = 145 + TransponderDataBase.dat = 45 + map-AirA = 40 + map-AirD = 292 + map-CableD = 292 + map-SateD = 144 + Favorites = 4 + +[Series:D] + SatDataBase.dat = 145 + TransponderDataBase.dat = 45 + map-AirA = 64 + map-AirD = 320 + map-CableD = 320 + map-SateD = 172 + map-AstraHDPlusD = 212 + Favorites = 5 + +[Series:E] + SatDataBase.dat = 145 + TransponderDataBase.dat = 45 + map-AirA = 64 + map-AirD = 320 + map-CableD = 320 + map-SateD = 168 + map-AstraHDPlusD = 212 + Favorites = 5 + +[Analog:28] + ; map-AirA and map-CableA for B series + offInUse = 0 + maskInUse = 0x02 + ;offNameLength = 1 + offProgramNr = 4 + offFavorites = + offName = 12 + lenName = 12 + offChecksum = 27 + +[Analog:40] + ; map-AirA and map-CableA for C series + offInUse = 1 + maskInUse = 0x01 + offSkip = 2 + maskSkip = 0x01 + offLock = 6 + maskLock = 0x01 + offTuned = 8 + maskTuned = 0x01 + offProgramNr = 9 + offSlotNr = 16 + offNameLength = 18 + offName = 20 + offFrequency = 32 + offFavorites = 38 + offChecksum = 39 + +[Analog:64] + ; map-AirA and map-CableA for D series + offInUse = 1 + maskInUse = 0x01 + offSkip = 2 + maskSkip = 0x01 + offLock = 6 + maskLock = 0x01 + offTuned = 8 + maskTuned = 0x01 + offProgramNr = 9 + offSlotNr = 16 + offNameLength = 18 + offName = 20 + offFrequency = 32 + offFavorite = 36,40,44,48,52 + offChecksum = 63 + +[FineTune:20] + offIsCable = 0 + maskIsCable = 0x01 + offSlotNr = 4 + offFrequency = 8 + +[FineTune_Digital:28] + offIsCable = 0 + maskIsCable = 0x01 + offChannelTransponder = 4 + offFrequency = 16 + +[DvbCT:248] + ; map-AirD and map-CableD for B series + offProgramNr = 0 + offVideoPid = 2 + offPcrPid = 4 + offServiceId = 10 + offStatus = 8 + offQam = 7 + offServiceType = 9 + offEncrypted = 23 + maskEncrypted = 0xff + offSymbolRate = 32 + offLock = 244 + maskLock = 0x01 + offOriginalNetworkId = 12 + offNetworkId = 14 + offBouquet = 34 + offChannelTransponder = 26 + offLogicalProgramNr = 28 + offTransportStreamId = 36 + offName = 44 + lenName = 100 + offFavorites = 246 + offChecksum = 247 + offCodec = + offServiceProviderId = + offShortName = + lenShortName = + offVideoFormat = + +[DvbCT:292] + ; map-AirD and map-CableD for C series + offProgramNr = 0 + offVideoPid = 2 + offPcrPid = 4 + offServiceId = 6 + offStatus = + offQam = 12 + offBandwidth = 14 + offServiceType = 15 + offCodec = 16 + offHRes = 20 + offVRes = 22 + offEncrypted = 24 + maskEncrypted = 0xff + offFrameRate = 25 + offSymbolRate = 28 + offLock = 31 + maskLock = 0x01 + offOriginalNetworkId = 32 + offNetworkId = 34 + offServiceProviderId = 40 + offChannelTransponder = 42 + offLogicalProgramNr = 44 + offTransportStreamId = 48 + offName = 64 + lenName = 200 + offShortName = 264 + lenShortName = 18 + offVideoFormat = 282 + offFavorites = 289 + offChecksum = 291 + offBouquet = + + +[DvbCT:320] + ; map-AirD and map-CableD for D and E series + offProgramNr = 0 + offVideoPid = 2 + offPcrPid = 4 + offServiceId = 6 + offStatus = + offQam = 12 + offBandwidth = 14 + offServiceType = 15 + offCodec = 16 + offHRes = 20 + offVRes = 22 + offEncrypted = 24 + maskEncrypted = 0xff + offFrameRate = 25 + offSymbolRate = 28 + offLock = 31 + maskLock = 0x01 + offOriginalNetworkId = 32 + offNetworkId = 34 + offServiceProviderId = 40 + offChannelTransponder = 42 + offLogicalProgramNr = 44 + offTransportStreamId = 48 + offName = 64 + lenName = 200 + offShortName = 264 + lenShortName = 18 + offVideoFormat = 282 + offFavorites = 292,296,300,304,308 + offChecksum = 319 + offBouquet = + + +[DvbS:144] + ; map-SateD for B and C Series + offProgramNr = 0 + offVideoPid = 2 + offPcrPid = 4 + offInUse = 7 + maskInUse = 0x01 + offLock = 13 + maskLock = 0x01 + offServiceType = 14 + offServiceId = 16 + offTransponderNr = 18 + offSatelliteNr = 20 + offTransportStreamId = 24 + offOriginalNetworkId = 28 + offHRes = 32 + offVRes = 34 + offName = 36 + lenName = 100 + offEncrypted = 136 + maskEncrypted = 0x01 + offBouquet = 138 + offFavorites = 142 + offChecksum = 143 + offCodec = + offSymbolRate = + offNetworkId = + offServiceProviderId = + offChannelTransponder = + offLogicalProgramNr = + offShortName = + lenShortName = + offVideoFormat = + +[DvbS:172] + ; map-SateD for D Series + offProgramNr = 0 + offVideoPid = 2 + offPcrPid = 4 + offInUse = 7 + maskInUse = 0x01 + offLock = 13 + maskLock = 0x01 + offServiceType = 14 + offServiceId = 16 + offTransponderNr = 18 + offSatelliteNr = 20 + offTransportStreamId = 24 + offOriginalNetworkId = 28 + offHRes = 32 + offVRes = 34 + offName = 36 + lenName = 100 + offEncrypted = 136 + maskEncrypted = 0x01 + offBouquet = 138 + offFavorites = 140,144,148,152,156 + offChecksum = 171 + offCodec = + offSymbolRate = + offNetworkId = + offServiceProviderId = + offChannelTransponder = + offLogicalProgramNr = + offShortName = + lenShortName = + offVideoFormat = + +[DvbS:168] + ; map-SateD for E Series + offProgramNr = 0 + offVideoPid = 2 + offPcrPid = 4 + offInUse = 7 + maskInUse = 0x01 + offLock = 13 + maskLock = 0x01 + offServiceType = 14 + offServiceId = 16 + offTransponderNr = 18 + offSatelliteNr = 20 + offTransportStreamId = 24 + offOriginalNetworkId = 28 + offHRes = 32 + offVRes = 34 + offName = 36 + offEncrypted = 136 + maskEncrypted = 0x01 + lenName = 100 + offBouquet = 138 + offFavorites = 140,144,148,152,156 + offChecksum = 167 + offCodec = + offSymbolRate = + offNetworkId = + offServiceProviderId = + offChannelTransponder = + offLogicalProgramNr = + offShortName = + lenShortName = + offVideoFormat = + +[AstraHDPlusD:212] + ; map-AstraHDPlusD for D and E Series + offProgramNr = 0,20 + offVideoPid = + offPcrPid = + offInUse = 14 + maskInUse = 0xff + offLock = + maskLock = 0x01 + offServiceType = 14 + offServiceId = 16 + offTransponderNr = 18 + offSatelliteNr = + offTransportStreamId = 36 + offOriginalNetworkId = 32 + offHRes = + offVRes = + offName = 48 + offEncrypted = 180 + maskEncrypted = 0x01 + lenName = 100 + offBouquet = 138 + offFavorites = 184,188,192,196,200 + offChecksum = 211 + offCodec = + offSymbolRate = + offNetworkId = + offServiceProviderId = + offChannelTransponder = + offLogicalProgramNr = + offShortName = + lenShortName = + offVideoFormat = diff --git a/ChanSort.Plugin.ScmFile/DvbCtChannelDataMapping.cs b/ChanSort.Plugin.ScmFile/DvbCtChannelDataMapping.cs new file mode 100644 index 0000000..fff769d --- /dev/null +++ b/ChanSort.Plugin.ScmFile/DvbCtChannelDataMapping.cs @@ -0,0 +1,63 @@ +using System.Text; +using ChanSort.Api; + +namespace ChanSort.Plugin.ScmFile +{ + internal class DvbCtChannelDataMapping : DvbChannelMappingBase + { + const string offChecksum = "offChecksum"; + + #region ctor() + public DvbCtChannelDataMapping(IniFile.Section settings, int dataLength) + : base(settings, dataLength, new UnicodeEncoding(true, false)) + { + } + #endregion + + #region Checksum + public byte Checksum + { + get { return this.GetByte(offChecksum); } + set { this.SetByte(offChecksum, value); } + } + #endregion + + #region Favorites + public override Favorites Favorites + { + get + { + if (this.DataLength < 320) + return base.Favorites; + + byte fav = 0; + byte mask = 0x01; + foreach (int off in this.GetOffsets(offFavorites)) + { + if (this.GetByte(off) == 1) + fav |= mask; + mask <<= 1; + } + return (Favorites)fav; + } + set + { + if (this.DataLength < 320) + { + base.Favorites = value; + return; + } + + int intValue = (int)value; + foreach (int off in this.GetOffsets(offFavorites)) + { + if ((intValue & 1) != 0) + this.SetByte(off, 1); + intValue >>= 1; + } + } + } + #endregion + + } +} diff --git a/ChanSort.Plugin.ScmFile/DvbSChannelDataMapping.cs b/ChanSort.Plugin.ScmFile/DvbSChannelDataMapping.cs new file mode 100644 index 0000000..0ec6991 --- /dev/null +++ b/ChanSort.Plugin.ScmFile/DvbSChannelDataMapping.cs @@ -0,0 +1,83 @@ +using System.Text; +using ChanSort.Api; + +namespace ChanSort.Plugin.ScmFile +{ + internal class DvbSChannelDataMapping : DvbChannelMappingBase + { + private const string offChecksum = "offChecksum"; + private const string offTransponderNr = "offTransponderNr"; + private const string offSatelliteNr = "offSatelliteNr"; + private readonly bool hasExtendedFavorites; + + #region ctor() + public DvbSChannelDataMapping(IniFile.Section settings, int dataLength) + : base(settings, dataLength, new UnicodeEncoding(true, false)) + { + this.hasExtendedFavorites = dataLength >= 168; + } + #endregion + + #region TransponderNr + public ushort TransponderNr + { + get { return this.GetWord(offTransponderNr); } + set { this.SetWord(offTransponderNr, value); } + } + #endregion + + #region SatelliteNr + public ushort SatelliteNr + { + get { return this.GetWord(offSatelliteNr); } + set { this.SetWord(offSatelliteNr, value); } + } + #endregion + + #region Favorites + public override Favorites Favorites + { + get + { + if (!this.hasExtendedFavorites) + return base.Favorites; + + byte fav = 0; + byte mask = 0x01; + foreach (int off in this.GetOffsets(offFavorites)) + { + if (this.GetDword(off) == 1) + fav |= mask; + mask <<= 1; + } + return (Favorites)fav; + } + set + { + if (!this.hasExtendedFavorites) + { + base.Favorites = value; + return; + } + + int intValue = (int)value; + foreach (int off in this.GetOffsets(offFavorites)) + { + if ((intValue & 1) != 0) + this.SetDword(off, 1); + intValue >>= 1; + } + } + } + #endregion + + + #region Checksum + public byte Checksum + { + get { return this.GetByte(offChecksum); } + set { this.SetByte(offChecksum, value); } + } + #endregion + } +} diff --git a/ChanSort.Plugin.ScmFile/ModelConstants.cs b/ChanSort.Plugin.ScmFile/ModelConstants.cs new file mode 100644 index 0000000..f338858 --- /dev/null +++ b/ChanSort.Plugin.ScmFile/ModelConstants.cs @@ -0,0 +1,34 @@ +using ChanSort.Api; + +namespace ChanSort.Plugin.ScmFile +{ + internal class ModelConstants + { + public readonly int dvbsSatelliteLength; + public readonly int dvbsTransponderLength; + public readonly int dvbsChannelLength; + public readonly int dvbtChannelLength; + public readonly int avbtChannelLength; + public readonly int hdplusChannelLength; + public readonly int avbtFineTuneLength; + public readonly int dvbtFineTuneLength; + public readonly Favorites supportedFavorites; + + public ModelConstants(IniFile.Section iniSection) + { + this.avbtChannelLength = iniSection.GetInt("map-AirA"); + this.dvbtChannelLength = iniSection.GetInt("map-AirD"); + this.dvbsChannelLength = iniSection.GetInt("map-SateD"); + this.hdplusChannelLength = iniSection.GetInt("map-AstraHDPlusD"); + this.dvbsSatelliteLength = iniSection.GetInt("SatDataBase.dat"); + this.dvbsTransponderLength = iniSection.GetInt("TransponderDataBase.dat"); + this.avbtFineTuneLength = iniSection.GetInt("FineTune"); + this.dvbtFineTuneLength = iniSection.GetInt("FineTune_Digital"); + int numFavorites = iniSection.GetInt("Favorites"); + int mask = 0; + for (int i = 0; i < numFavorites; i++) + mask = (mask << 1) | 1; + this.supportedFavorites = (Favorites)mask; + } + } +} diff --git a/ChanSort.Plugin.ScmFile/Properties/AssemblyInfo.cs b/ChanSort.Plugin.ScmFile/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..1e0e01e --- /dev/null +++ b/ChanSort.Plugin.ScmFile/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.Plugin.ScmFile")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ChanSort.Plugin.ScmFile")] +[assembly: AssemblyCopyright("Copyright © 2012")] +[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("6f59ac5a-afba-42e3-a63e-c74793c15980")] + +// 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/ChanSort.Plugin.ScmFile/ScmSerializer.cs b/ChanSort.Plugin.ScmFile/ScmSerializer.cs new file mode 100644 index 0000000..9cbd9d8 --- /dev/null +++ b/ChanSort.Plugin.ScmFile/ScmSerializer.cs @@ -0,0 +1,740 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Text; +using System.Linq; +using System.Windows.Forms; +using ChanSort.Api; +using ICSharpCode.SharpZipLib.Zip; + +namespace ChanSort.Plugin.ScmFile +{ + class ScmSerializer : SerializerBase + { + private readonly Dictionary modelConstants = new Dictionary(); + private readonly MappingPool analogMappings = new MappingPool("Analog"); + private readonly MappingPool dvbctMappings = new MappingPool("DVB-C/T"); + private readonly MappingPool dvbsMappings = new MappingPool("DVB-S"); + private readonly MappingPool hdplusMappings = new MappingPool("AstraHDPlus"); + private readonly MappingPool analogFineTuneMappings = new MappingPool("FineTune"); + private readonly ChannelList avbtChannels = new ChannelList(SignalSource.AnalogT, SignalType.Mixed); + private readonly ChannelList avbcChannels = new ChannelList(SignalSource.AnalogC, SignalType.Mixed); + private readonly ChannelList dvbcChannels = new ChannelList(SignalSource.DvbC, SignalType.Mixed); + private readonly ChannelList dvbtChannels = new ChannelList(SignalSource.DvbT, SignalType.Mixed); + private readonly ChannelList dvbsChannels = new ChannelList(SignalSource.DvbS, SignalType.Mixed); + private readonly ChannelList hdplusChannels = new ChannelList(SignalSource.HdPlusD, SignalType.Mixed); + private readonly Dictionary avbtFrequency = new Dictionary(); + private readonly Dictionary avbcFrequency = new Dictionary(); + private byte[] avbtFileContent; + private byte[] avbcFileContent; + private byte[] dvbtFileContent; + private byte[] dvbcFileContent; + private byte[] dvbsFileContent; + private byte[] hdplusFileContent; + private UnsortedChannelMode unsortedChannelMode; + private ModelConstants c; + + #region ctor() + public ScmSerializer(string inputFile) : base(inputFile) + { + this.ReadConfigurationFromIniFile(); + } + #endregion + + #region DisplayName + public override string DisplayName { get { return "Samsung *.scm Loader"; } } + #endregion + + #region ReadConfigurationFromIniFile() + private void ReadConfigurationFromIniFile() + { + string iniFile = Assembly.GetExecutingAssembly().Location.Replace(".dll", ".ini"); + IniFile ini = new IniFile(iniFile); + foreach (var section in ini.Sections) + { + int idx = section.Name.IndexOf(":"); + int len=0; + if (idx >= 0) + int.TryParse(section.Name.Substring(idx + 1), out len); + + if (section.Name.StartsWith("Series:")) + modelConstants.Add(section.Name, new ModelConstants(section)); + else if (section.Name.StartsWith("Analog:")) + analogMappings.AddMapping(new AnalogChannelDataMapping(section, len)); + else if (section.Name.StartsWith("DvbCT:")) + dvbctMappings.AddMapping(new DvbCtChannelDataMapping(section, len)); + else if (section.Name.StartsWith("DvbS:")) + dvbsMappings.AddMapping(new DvbSChannelDataMapping(section, len)); + else if (section.Name.StartsWith("FineTune:")) + analogFineTuneMappings.AddMapping(new DataMapping(section, len, null)); + else if (section.Name.StartsWith("AstraHDPlusD:")) + hdplusMappings.AddMapping(new DvbSChannelDataMapping(section, len)); + } + } + #endregion + + #region Load() + public override void Load() + { + using (ZipFile zip = new ZipFile(this.FileName)) + { + DetectModelConstants(zip); + DataRoot.SupportedFavorites = c.supportedFavorites; + + ReadAnalogFineTuning(zip); + ReadAnalogChannels(zip, "map-AirA", this.avbtChannels, out this.avbtFileContent, this.avbtFrequency); + ReadAnalogChannels(zip, "map-CableA", this.avbcChannels, out this.avbcFileContent, this.avbcFrequency); + ReadDvbctChannels(zip, "map-AirD", this.dvbtChannels, out this.dvbtFileContent); + ReadDvbctChannels(zip, "map-CableD", this.dvbcChannels, out this.dvbcFileContent); + ReadSatellites(zip); + ReadTransponder(zip, "TransponderDataBase.dat"); + ReadTransponder(zip, "UserTransponderDataBase.dat"); + ReadDvbsChannels(zip); + ReadAstraHdPlusChannels(zip); + } + } + #endregion + + #region DetectModelConstants() + private void DetectModelConstants(ZipFile zip) + { + if (DetectModelFromCloneInfoFile(zip)) return; + if (DetectModelFromContentFileLengths(zip)) return; + if (DetectModelFromFileName()) return; + throw new IOException("Unable to determine TV model from file content or name"); + } + #endregion + + #region DetectModelFromFileName() + private bool DetectModelFromFileName() + { + string file = Path.GetFileName(this.FileName); + System.Text.RegularExpressions.Regex regex = + new System.Text.RegularExpressions.Regex("channel_list_[A-Z]{2}[0-9]{2}([A-Z])[0-9A-Z]+_[0-9]+\\.scm"); + var match = regex.Match(file); + if (match.Success) + { + string series = match.Groups[1].Value; + if (this.modelConstants.TryGetValue("Series:" + series, out this.c)) + return true; + } + return false; + } + #endregion + + #region DetectModelFromCloneInfoFile() + private bool DetectModelFromCloneInfoFile(ZipFile zip) + { + byte[] cloneInfo = ReadFileContent(zip, "CloneInfo"); + if (cloneInfo == null) + { + this.c = this.modelConstants["Series:B"]; + return true; + } + + if (cloneInfo.Length >= 9) + { + char series = (char) cloneInfo[8]; + if (this.modelConstants.TryGetValue("Series:" + series, out this.c)) + return true; + } + return false; + } + #endregion + + #region DetectModelFromContentFileLengths() + private bool DetectModelFromContentFileLengths(ZipFile zip) + { + string[] candidates = new[] + { + DetectModelFromAirAOrCableA(zip), + DetectModelFromAirDOrCableD(zip), + DetectModelFromSateD(zip), + DetectModelFromTranspoderDatabase(zip) + }; + + string validCandidates = "BCDE"; + foreach (var candidateList in candidates) + { + if (candidateList == null) + continue; + string newValidCandidats = ""; + foreach (var candidate in candidateList) + { + if (validCandidates.Contains(candidate)) + newValidCandidats += candidate; + } + validCandidates = newValidCandidats; + } + + if (validCandidates.Length != 1) + return false; + + this.modelConstants.TryGetValue("Series:" + validCandidates, out this.c); + return true; + } + + #endregion + + #region DetectModelFromAirAOrCableA() + private string DetectModelFromAirAOrCableA(ZipFile zip) + { + var entry = zip.GetEntry("map-AirA") ?? zip.GetEntry("map-CableA"); + if (entry == null) + return null; + + var candidates = ""; + if (entry.Size % 28000 == 0) + candidates += "B"; + if (entry.Size % 40000 == 0) + candidates += "C"; + if (entry.Size % 64000 == 0) + candidates += "DE"; + return candidates; + } + #endregion + + #region DetectModelFromAirDOrCableD() + private string DetectModelFromAirDOrCableD(ZipFile zip) + { + var entry = zip.GetEntry("map-AirD") ?? zip.GetEntry("map-CableD"); + if (entry == null) + return null; + + var candidates = ""; + if (entry.Size % 248 == 0) + candidates += "B"; + if (entry.Size % 292 == 0) + candidates += "C"; + if (entry.Size % 320 == 0) + candidates += "DE"; + return candidates; + } + #endregion + + #region DetectModelFromSateD() + private string DetectModelFromSateD(ZipFile zip) + { + var entry = zip.GetEntry("map-SateD"); + if (entry == null) + return null; + + var candidates = ""; + if (entry.Size % 144 == 0) + candidates += "BC"; + if (entry.Size % 172 == 0) + candidates += "D"; + if (entry.Size % 168 == 0) + candidates += "E"; + return candidates; + } + #endregion + + #region DetectModelFromTranspoderDatabase() + private string DetectModelFromTranspoderDatabase(ZipFile zip) + { + var entry = zip.GetEntry("TransponderDatabase.dat"); + if (entry == null) + return null; + + var size = entry.Size - 4; + var candidates = ""; + if (size%49 == 0) + candidates += "B"; + if (size%45 == 0) + candidates += "CDE"; + return candidates; + } + #endregion + + + #region ReadAnalogFineTuning() + private unsafe void ReadAnalogFineTuning(ZipFile zip) + { + int entrySize = c.avbtFineTuneLength; + if (entrySize == 0) + return; + + byte[] data = ReadFileContent(zip, "FineTune"); + if (data == null) + return; + + var mapping = analogFineTuneMappings.GetMapping(c.avbtFineTuneLength); + fixed (byte* ptr = data) + { + mapping.DataPtr = ptr; + int count = data.Length / mapping.DataLength; + for (int i = 0; i < count; i++) + { + bool isCable = mapping.GetFlag("offIsCable", "maskIsCable"); // HACK: this is just a guess + int slot = mapping.GetWord("offSlotNr"); + float freq = mapping.GetFloat("offFrequency"); + var dict = isCable ? avbcFrequency : avbtFrequency; + dict[slot] = (decimal)freq; + mapping.Next(); + } + } + } + #endregion + + #region ReadAnalogChannels() + private unsafe void ReadAnalogChannels(ZipFile zip, string fileName, ChannelList list, out byte[] data, Dictionary freq) + { + data = null; + int entrySize = c.avbtChannelLength; + if (entrySize == 0) + return; + + data = ReadFileContent(zip, fileName); + if (data == null) + return; + + this.DataRoot.AddChannelList(list); + fixed (byte* ptr = data) + { + var rawChannel = analogMappings.GetMapping(entrySize); + rawChannel.DataPtr = ptr; + int count = data.Length / entrySize; + + for (int slotIndex = 0; slotIndex < count; slotIndex++) + { + MapAnalogChannel(rawChannel, slotIndex, list, freq); + rawChannel.DataPtr += entrySize; + } + } + } + #endregion + + #region MapAnalogChannel() + private unsafe void MapAnalogChannel(AnalogChannelDataMapping rawChannel, int slotIndex, ChannelList list, Dictionary freq) + { + if (!rawChannel.InUse) + return; + + if (rawChannel.Checksum != CalcChecksum(rawChannel.DataPtr, c.avbtChannelLength)) + this.DataRoot.Warnings.AppendFormat("{0}: Incorrect checksum for channel index {1}\r\n", list, slotIndex); + + ChannelInfo ci = new ChannelInfo(list.SignalSource, list.SignalType, slotIndex, rawChannel.ProgramNr, rawChannel.Name); + ci.FreqInMhz = (decimal)Math.Round(rawChannel.Frequency, 2); + if (ci.FreqInMhz == 0) + ci.FreqInMhz = freq.TryGet(ci.RecordIndex); + if (ci.FreqInMhz == 0) + ci.FreqInMhz = slotIndex; + ci.Lock = rawChannel.Lock; + ci.Skip = rawChannel.Skip; + ci.Favorites = rawChannel.Favorites; + + this.DataRoot.AddChannel(list, ci); + } + + #endregion + + + #region ReadDvbctChannels() + private unsafe void ReadDvbctChannels(ZipFile zip, string fileName, ChannelList list, out byte[] data) + { + data = null; + int entrySize = c.dvbtChannelLength; + if (entrySize == 0) + return; + + data = ReadFileContent(zip, fileName); + if (data == null) + return; + + this.DataRoot.AddChannelList(list); + fixed (byte* ptr = data) + { + DvbCtChannelDataMapping rawChannel = dvbctMappings.GetMapping(entrySize); + rawChannel.DataPtr = ptr; + int count = data.Length / entrySize; + for (int slotIndex = 0; slotIndex < count; slotIndex++) + { + MapDvbctChannel(rawChannel, slotIndex, list); + rawChannel.Next(); + } + } + } + #endregion + + #region MapDvbctChannel() + private unsafe void MapDvbctChannel(DvbCtChannelDataMapping rawChannel, int slotIndex, ChannelList list) + { + if (rawChannel.ProgramNr == 0) + return; + if (rawChannel.Checksum != CalcChecksum(rawChannel.DataPtr, rawChannel.DataLength)) + this.DataRoot.Warnings.AppendFormat("{0}: Incorrect checksum for channel index {1}\r\n", list, slotIndex); + + ChannelInfo ci = new ChannelInfo(list.SignalSource, list.SignalType, slotIndex, rawChannel.ProgramNr, rawChannel.Name); + ci.VideoPid = rawChannel.VideoPid; + ci.ServiceId = rawChannel.ServiceId; + ci.ServiceType = rawChannel.ServiceType; + ci.TransportStreamId = rawChannel.TransportStreamId; + ci.FreqInMhz = LookupData.Instance.GetDvbtTransponderFrequency(rawChannel.ChannelOrTransponder); + ci.OriginalNetworkId = rawChannel.OriginalNetworkId; + ci.Favorites = rawChannel.Favorites; + ci.Lock = rawChannel.Lock; + ci.ShortName = rawChannel.ShortName; + ci.SymbolRate = rawChannel.SymbolRate; + ci.Encrypted = rawChannel.Encrypted; + ci.ChannelOrTransponder = rawChannel.ChannelOrTransponder.ToString(); + + this.DataRoot.AddChannel(list, ci); + } + + #endregion + + + #region ReadSatellites() + private unsafe void ReadSatellites(ZipFile zip) + { + byte[] data = ReadFileContent(zip, "SatDataBase.dat"); + if (data == null) + return; + + var utf16Encoding = new UnicodeEncoding(false, false); + fixed (byte* ptr = data) + { + int count = data.Length/this.c.dvbsSatelliteLength; + for (int i = 0; i < count; i++) + { + SatDataBase* sat = (SatDataBase*)(ptr + 4 + i * this.c.dvbsSatelliteLength); + if (sat->Magic0x55 != 0x55) + throw new IOException("Unknown SatDataBase.dat format"); + string name = utf16Encoding.GetString((byte*)sat->Name, 64*2); + string location = string.Format("{0}.{1}{2}", sat->LongitudeTimes10/10, sat->LongitudeTimes10%10, sat->IsWest != 0 ? "W" : "E"); + + Satellite satellite = new Satellite(sat->SatelliteNr); + satellite.Name = name; + satellite.OrbitalPosition = location; + this.DataRoot.Satellites.Add(sat->SatelliteNr, satellite); + } + } + } + #endregion + + #region ReadTransponder() + + private unsafe void ReadTransponder(ZipFile zip, string fileName) + { + byte[] data = ReadFileContent(zip, fileName); + if (data == null) + return; + + fixed (byte* ptr = data) + { + int count = data.Length/c.dvbsTransponderLength; + for (int i=0; iMagic0x55 == 0) + continue; + + if (trans->TransponderNr == 0) + continue; + + var sat = this.DataRoot.Satellites.TryGet(trans->SatelliteNr); + if (sat == null) + { + DataRoot.Warnings.Append(string.Format("Transponder #{0} references invalid satellite #{1}", + trans->TransponderNr, trans->SatelliteNr)); + continue; + } + Transponder transponder = new Transponder(trans->TransponderNr); + transponder.FrequencyInMhz = (uint) (trans->Frequency/1000); + transponder.Polarity = trans->IsVerticalPolarity == 1 ? 'V' : 'H'; + transponder.SymbolRate = trans->SymbolRate/1000; + this.DataRoot.AddTransponder(sat, transponder); + } + } + } + #endregion + + #region ReadDvbsChannels() + private unsafe void ReadDvbsChannels(ZipFile zip) + { + this.dvbsFileContent = ReadFileContent(zip, "map-SateD"); + if (this.dvbsFileContent == null) + return; + + this.DataRoot.AddChannelList(this.dvbsChannels); + fixed (byte* ptr = this.dvbsFileContent) + { + int entrySize = c.dvbsChannelLength; + int count = this.dvbsFileContent.Length/entrySize; + DvbSChannelDataMapping mapping = dvbsMappings.GetMapping(entrySize); + mapping.DataPtr = ptr; + for (int slotIndex = 0; slotIndex < count; slotIndex++) + { + MapDvbsChannel(this.dvbsChannels, mapping, slotIndex); + mapping.Next(); + } + } + } + #endregion + + #region MapDvbsChannel() + private void MapDvbsChannel(ChannelList channelList, DvbSChannelDataMapping rawChannel, int slotIndex) + { + if (!rawChannel.InUse) + return; + + Transponder transponder = this.DataRoot.Transponder.TryGet(rawChannel.TransponderNr); + Satellite satellite = transponder == null ? null : transponder.Satellite; + string satPosition = satellite != null ? satellite.OrbitalPosition : "#" + rawChannel.SatelliteNr; + + string satName = satellite != null ? satellite.Name : null; + + ChannelInfo ci = new ChannelInfo(channelList.SignalSource, SignalType.Mixed, slotIndex, rawChannel.ProgramNr, rawChannel.Name); + ci.Satellite = satName; + ci.SatPosition = satPosition; + ci.VideoPid = rawChannel.VideoPid; + ci.ServiceId = rawChannel.ServiceId; + ci.ServiceType = rawChannel.ServiceType; + ci.TransportStreamId = rawChannel.TransportStreamId; + ci.OriginalNetworkId = rawChannel.OriginalNetworkId; + ci.Favorites = rawChannel.Favorites; + ci.Encrypted = rawChannel.Encrypted; + ci.Lock = rawChannel.Lock; + ci.ShortName = rawChannel.ShortName; + + if (transponder != null) + { + ci.Transponder = transponder; + ci.FreqInMhz = transponder.FrequencyInMhz; + ci.ChannelOrTransponder = this.GetTransponderChannelNumber((ushort)transponder.FrequencyInMhz); + ci.SymbolRate = transponder.SymbolRate; + ci.Polarity = transponder.Polarity; + } + + this.DataRoot.AddChannel(channelList, ci); + } + + #endregion + + #region GetTransponderChannelNumber() + private string GetTransponderChannelNumber(ushort frequency) + { + int nr = LookupData.Instance.GetTransponderNumber(frequency); + return nr <= 0 ? "" : nr.ToString("d3"); + } + #endregion + + + #region ReadAstraHdPlusChannels() + private unsafe void ReadAstraHdPlusChannels(ZipFile zip) + { + this.hdplusFileContent = ReadFileContent(zip, "map-AstraHDPlusD"); + if (hdplusFileContent == null || c.hdplusChannelLength == 0) + return; + + this.DataRoot.AddChannelList(this.hdplusChannels); + fixed (byte* ptr = hdplusFileContent) + { + int entrySize = c.hdplusChannelLength; + int count = hdplusFileContent.Length / entrySize; + DvbSChannelDataMapping mapping = hdplusMappings.GetMapping(entrySize); + mapping.DataPtr = ptr; + for (int slotIndex = 0; slotIndex < count; slotIndex++) + { + MapDvbsChannel(this.hdplusChannels, mapping, slotIndex); + mapping.Next(); + } + } + } + #endregion + + + #region ReadFileContent() + private static byte[] ReadFileContent(ZipFile zip, string fileName) + { + var entry = zip.GetEntry(fileName); + if (entry == null) + return null; + byte[] data = new byte[entry.Size]; + using (var stream = zip.GetInputStream(entry)) + { + stream.Read(data, 0, data.Length); + } + return data; + } + #endregion + + + private unsafe delegate void UpdateFunc(ChannelInfo channelInfo, byte* fileContent); + + #region Save() + public override unsafe void Save(string tvOutputFile, string csvOutputFile, UnsortedChannelMode unsortedMode) + { + this.unsortedChannelMode = unsortedMode; + if (tvOutputFile != this.FileName) + { + File.Copy(this.FileName, tvOutputFile); + this.FileName = tvOutputFile; + } + using (ZipFile zip = new ZipFile(tvOutputFile)) + { + zip.BeginUpdate(); + this.SaveChannels(zip, "map-AirA", this.avbtChannels, this.UpdateAnalogChannel, ref this.avbtFileContent); + this.SaveChannels(zip, "map-CableA", this.avbcChannels, this.UpdateAnalogChannel, ref this.avbcFileContent); + this.SaveChannels(zip, "map-AirD", this.dvbtChannels, this.UpdateDvbctChannel, ref this.dvbtFileContent); + this.SaveChannels(zip, "map-CableD", this.dvbcChannels, this.UpdateDvbctChannel, ref this.dvbcFileContent); + this.SaveChannels(zip, "map-SateD", this.dvbsChannels, this.UpdateDvbsChannel, ref this.dvbsFileContent); + this.SaveChannels(zip, "map-AstraHDPlusD", this.hdplusChannels, this.UpdateHdPlusChannel, ref this.hdplusFileContent); + zip.CommitUpdate(); + } + } + #endregion + + #region SaveChannels() + private unsafe void SaveChannels(ZipFile zip, string fileName, ChannelList channels, UpdateFunc updateChannel, ref byte[] fileContent) + { + if (fileContent == null) + return; + zip.Delete(fileName); + + string tempFilePath = Path.GetTempFileName(); + using (var stream = new FileStream(tempFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite)) + { + this.WriteChannels(channels, updateChannel, fileContent, stream); + stream.Flush(); + stream.Seek(0, SeekOrigin.Begin); + int size = (int)new FileInfo(tempFilePath).Length; + fileContent = new byte[size]; + stream.Read(fileContent, 0, size); + } + + zip.Add(tempFilePath, fileName); + } + #endregion + + #region WriteChannels() + private unsafe void WriteChannels(ChannelList list, UpdateFunc updateChannel, byte[] fileContent, FileStream stream) + { + fixed (byte* ptr = fileContent) + { + int maxSlot = 0; + foreach (var channel in list.Channels.OrderBy(ChannelComparer)) + { + if (channel.RecordIndex < 0) // channel only exists in reference list + continue; + + int newProgNr; + if (channel.NewProgramNr == 0 && this.unsortedChannelMode == UnsortedChannelMode.Hide) + newProgNr = 0; + else + { + newProgNr = channel.NewProgramNr != 0 ? channel.NewProgramNr : ++maxSlot; + if (newProgNr > maxSlot) + maxSlot = channel.NewProgramNr; + } + + var channels = new List(); + channels.Add(channel); + channels.AddRange(channel.Duplicates); + foreach (var channelInstance in channels) + { + channelInstance.OldProgramNr = newProgNr; + updateChannel(channelInstance, ptr); + } + } + + stream.Write(fileContent, 0, fileContent.Length); +#if false + if (count == 0 || count%padToPageSize != 0) + { + byte[] padding = new byte[(padToPageSize - count%padToPageSize) * entrySize]; + stream.Write(padding, 0, padding.Length); + } +#endif + } + } + #endregion + + #region UpdateAnalogChannel() + private unsafe void UpdateAnalogChannel(ChannelInfo channel, byte* ptr) + { + AnalogChannelDataMapping raw = analogMappings.GetMapping(c.avbtChannelLength); + int startOffset = channel.RecordIndex * raw.DataLength; + raw.DataPtr = ptr + startOffset; + raw.ProgramNr = (ushort)channel.OldProgramNr; + raw.Favorites = channel.Favorites; + raw.Lock = channel.Lock; + raw.Checksum = CalcChecksum(raw.DataPtr, raw.DataLength); + } + #endregion + + #region UpdateDvbctChannel() + private unsafe void UpdateDvbctChannel(ChannelInfo channel, byte* ptr) + { + DvbCtChannelDataMapping raw = dvbctMappings.GetMapping(c.dvbtChannelLength); + int startOffset = channel.RecordIndex * raw.DataLength; + raw.DataPtr = ptr + startOffset; + raw.ProgramNr = (ushort)channel.OldProgramNr; + raw.Favorites = channel.Favorites; + raw.Lock = channel.Lock; + raw.Checksum = CalcChecksum(raw.DataPtr, raw.DataLength); + } + #endregion + + #region UpdateDvbsChannel() + private unsafe void UpdateDvbsChannel(ChannelInfo channel, byte* ptr) + { + DvbSChannelDataMapping raw = dvbsMappings.GetMapping(c.dvbsChannelLength); + int startOffset = channel.RecordIndex*raw.DataLength; + raw.DataPtr = (ptr + startOffset); + raw.ProgramNr = (ushort)channel.OldProgramNr; + raw.Favorites = channel.Favorites; + raw.Lock = channel.Lock; + raw.Checksum = CalcChecksum(raw.DataPtr, raw.DataLength); + } + #endregion + + #region UpdateHdPlusChannel() + private unsafe void UpdateHdPlusChannel(ChannelInfo channel, byte* ptr) + { + DvbSChannelDataMapping raw = hdplusMappings.GetMapping(c.hdplusChannelLength); + int startOffset = channel.RecordIndex * raw.DataLength; + raw.DataPtr = (ptr + startOffset); + raw.ProgramNr = (ushort)channel.OldProgramNr; + raw.Favorites = channel.Favorites; + raw.Lock = channel.Lock; + raw.Checksum = CalcChecksum(raw.DataPtr, raw.DataLength); + } + #endregion + + #region CalcChecksum() + private static unsafe byte CalcChecksum(byte* ptr, int length) + { + byte checksum = 0; + for (int i = 1; i < length; i++) + checksum += *ptr++; + return checksum; + } + #endregion + + #region ChannelComparer() + private string ChannelComparer(ChannelInfo channel) + { + if (channel.NewProgramNr != 0) + return "A" + channel.NewProgramNr.ToString("d4"); + if (channel.OldProgramNr != 0) + { + if (this.unsortedChannelMode == UnsortedChannelMode.AppendInOrder) + return "B" + channel.OldProgramNr.ToString("d4"); + return "B" + channel.Name; + } + return "Z"; + } + #endregion + + public override void ShowDeviceSettingsForm(object parentWindow) + { + MessageBox.Show((Form) parentWindow, "Sorry, ChanSort currently doesn't support any settings for your TV model.", + "Device Settings", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } +} diff --git a/ChanSort.Plugin.ScmFile/ScmSerializerPlugin.cs b/ChanSort.Plugin.ScmFile/ScmSerializerPlugin.cs new file mode 100644 index 0000000..f404d33 --- /dev/null +++ b/ChanSort.Plugin.ScmFile/ScmSerializerPlugin.cs @@ -0,0 +1,15 @@ +using ChanSort.Api; + +namespace ChanSort.Plugin.ScmFile +{ + public class ScmSerializerPlugin : ISerializerPlugin + { + public string PluginName { get { return "Samsung *.scm Loader"; } } + public string FileFilter { get { return "*.scm"; } } + + public SerializerBase CreateSerializer(string inputFile) + { + return new ScmSerializer(inputFile); + } + } +} diff --git a/ChanSort.Plugin.ScmFile/ScmStructures.cs b/ChanSort.Plugin.ScmFile/ScmStructures.cs new file mode 100644 index 0000000..2bafbc7 --- /dev/null +++ b/ChanSort.Plugin.ScmFile/ScmStructures.cs @@ -0,0 +1,97 @@ +using System.Runtime.InteropServices; + +namespace ChanSort.Plugin.ScmFile +{ + [StructLayout(LayoutKind.Sequential, Pack=1)] + unsafe struct SatDataBase + { + public byte Magic0x55; + public int SatelliteNr; + public int TransponderCount; + public fixed ushort Name[64]; + public int IsWest; + public int LongitudeTimes10; + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct TransponderDataBase + { + public byte Magic0x55; + public int TransponderNr; + public int SatelliteNr; + public int Frequency; + public int SymbolRate; + public int IsVerticalPolarity; + public int Modulation; + public int CodeRate; + public int Unknown1; + public int Unknown2; + public int Unknown3; + public int Unknown4; + }; + +#if false + [StructLayout(LayoutKind.Sequential, Pack=1)] + unsafe struct MapSateD + { + public ushort ChannelNumber; + public ushort VideoPid; + public ushort Pid; + public byte Mpeg4; + public byte Unknown8; + public ushort Unknown9; + public ushort Unknonw11; + public ushort Unknown13; + public byte ServiceType; + public byte Unknown16; + public ushort ServiceId; + public ushort TransponderNr; + public ushort SatelliteNr; + public ushort Unknown23; + public ushort TransportStreamId; + public ushort Unknown27; + public ushort OriginalNetworkId; + public ushort Unknown31; + public ushort HRes; + public ushort VRes; + public fixed ushort NameInBigEndianUtf16[51]; + public ushort Bouquet; + public byte Unknown141; + public byte Locked; + public byte Favorites; + public byte ChecksumCSeries; + public fixed byte Padding [28]; + } +#endif +#if false + [StructLayout(LayoutKind.Sequential, Pack = 1)] + unsafe struct MapAirD + { + public ushort ChannelNumber; + public ushort VideoPid; + public ushort PcrPid; + public ushort ServiceId; + public ushort Status; + public ushort Unknown11; + public ushort Qam; + public byte ServiceType; + public byte Codec; + public fixed byte Unknown17 [7]; + public byte Encrypted; + public fixed byte Unknown25 [3]; + public ushort Frequency; + public ushort LogicalChannelNumber; + public fixed byte Unknown31 [2]; + public ushort SymbolRate; + public ushort Bouquet; + public ushort TransportStreamId; + public fixed byte Unknown39 [5]; + public fixed ushort NameInBigEndianUtf16[100]; + public byte Unknown244; + public ushort Locked; + public byte FavoritesX79; + public byte ChecksumBSeries; + public fixed byte PaddingCSeries [292 - 248]; + } +#endif +} diff --git a/ChanSort.Plugin.TllFile/ActChannelDataMapping.cs b/ChanSort.Plugin.TllFile/ActChannelDataMapping.cs new file mode 100644 index 0000000..3c2347c --- /dev/null +++ b/ChanSort.Plugin.TllFile/ActChannelDataMapping.cs @@ -0,0 +1,219 @@ +using System.Collections.Generic; +using System.Text; +using ChanSort.Api; + +namespace ChanSort.Plugin.TllFile +{ + #region class ActChannelDataMapping + /// + /// Mapping for Analog, Cable and Terrestrial + /// + public unsafe class ActChannelDataMapping : DvbChannelMappingBase + { + private readonly DvbStringDecoder dvbsStringDecoder; + + private const string offFrequencyLong = "offFrequencyLong"; + private const string offFavorites2 = "offFavorites2"; + private const string offProgramNr2 = "offProgramNr2"; + + #region ctor() + public ActChannelDataMapping(IniFile.Section settings, int length, DvbStringDecoder dvbsStringDecoder) : base(settings, length, null) + { + this.dvbsStringDecoder = dvbsStringDecoder; + this.ReorderChannelData = settings.GetInt("reorderChannelData") != 0; + } + #endregion + + #region Encoding + public Encoding Encoding + { + get { return this.dvbsStringDecoder.DefaultEncoding; } + set { this.dvbsStringDecoder.DefaultEncoding = value; } + } + #endregion + + public bool ReorderChannelData { get; private set; } + + #region Favorites + public override Favorites Favorites + { + get { return (Favorites)(this.GetByte(offFavorites) & 0x0F); } + set + { + int intValue = (int)value; + foreach (int off in this.GetOffsets(offFavorites)) + this.DataPtr[off] = (byte) ((this.DataPtr[off] & 0xF0) | intValue); + intValue <<= 2; + foreach (int off in this.GetOffsets(offFavorites2)) + this.DataPtr[off] = (byte)((this.DataPtr[off] & 0xC3) | intValue); + } + } + #endregion + + #region ProgramNr + public override ushort ProgramNr + { + get { return base.ProgramNr; } + set + { + base.ProgramNr = value; + this.SetWord(offProgramNr2, (ushort)((value<<2) | (GetWord(offProgramNr2) & 0x03))); + } + } + #endregion + + #region Name + public override string Name + { + get + { + string longName, shortName; + this.dvbsStringDecoder.GetChannelNames(this.NamePtr, this.NameLength, out longName, out shortName); + return longName; + } + set { ChannelDataMapping.SetChannelName(this, value, this.dvbsStringDecoder.DefaultEncoding); } + } + #endregion + + #region ShortName + public override string ShortName + { + get + { + string longName, shortName; + this.dvbsStringDecoder.GetChannelNames(this.NamePtr, this.NameLength, out longName, out shortName); + return shortName; + } + } + #endregion + + #region FrequencyLong + public virtual uint FrequencyLong + { + get { return this.GetDword(offFrequencyLong); } + set { this.SetDword(offFrequencyLong, value); } + } + #endregion + + #region AnalogFrequency, AnalogChannelNr, AnalogChannelBand + + public ushort AnalogFrequency + { + get { return this.PcrPid; } + set { this.PcrPid = value; } + } + + public byte AnalogChannelNr + { + get { return (byte)(this.VideoPid & 0xFF); } + } + + public byte AnalogChannelBand + { + get { return (byte)(this.VideoPid >> 8); } + } + #endregion + + + #region Validate() + public string Validate() + { + bool ok = true; + List warnings = new List(); + ok &= ValidateByte(offChannelTransponder) || AddWarning(warnings, "Channel/Transponder number"); + ok &= ValidateWord(offProgramNr) || AddWarning(warnings, "Program#"); + ok &= ValidateByte(offFavorites) || AddWarning(warnings, "Favorites"); + ok &= ValidateWord(offPcrPid) || AddWarning(warnings, "PCR-PID"); + ok &= ValidateWord(offAudioPid) || AddWarning(warnings, "Audio-PID"); + ok &= ValidateWord(offVideoPid) || AddWarning(warnings, "Video-PID"); + ok &= ValidateString(offName, 40) || AddWarning(warnings, "Channel name"); + ok &= ValidateByte(offNameLength) || AddWarning(warnings, "Channel name length"); + ok &= ValidateWord(offServiceId) || AddWarning(warnings, "Service-ID"); + ok &= ValidateString(offFrequencyLong, 4) || AddWarning(warnings, "Frequency"); + ok &= ValidateWord(offOriginalNetworkId) || AddWarning(warnings, "Original Network-ID"); + ok &= ValidateWord(offTransportStreamId) || AddWarning(warnings, "Transport Stream ID"); + ok &= ValidateByte(offFavorites2) || AddWarning(warnings, "Favorites #2"); + ok &= ValidateByte(offServiceType) || AddWarning(warnings, "Service Type"); + + if (ok) + return null; + + StringBuilder sb = new StringBuilder(); + foreach (var warning in warnings) + { + if (sb.Length > 0) + sb.Append(", "); + sb.Append(warning); + } + return sb.ToString(); + } + #endregion + + #region AddWarning() + private bool AddWarning(List warnings, string p) + { + warnings.Add(p); + return false; + } + #endregion + + #region ValidateByte() + private bool ValidateByte(string key) + { + var offsets = this.GetOffsets(key); + if (offsets == null || offsets.Length < 1) + return true; + byte value = *(this.DataPtr + offsets[0]); + bool ok = true; + foreach(int offset in offsets) + { + if (this.DataPtr[offset] != value) + ok = false; + } + return ok; + } + #endregion + + #region ValidateWord() + private bool ValidateWord(string key) + { + var offsets = this.GetOffsets(key); + if (offsets == null || offsets.Length < 1) + return true; + ushort value = *(ushort*)(this.DataPtr + offsets[0]); + bool ok = true; + foreach (int offset in offsets) + { + if (*(ushort*) (this.DataPtr + offset) != value) + ok = false; + } + return ok; + } + #endregion + + #region ValidateString() + private bool ValidateString(string key, int len) + { + var offsets = this.GetOffsets(key); + if (offsets == null || offsets.Length < 1) + return true; + bool ok = true; + int off0 = offsets[0]; + for (int i = 1; i < offsets.Length; i++) + { + int offI = offsets[i]; + for (int j = 0; j < len; j++) + { + byte b = this.DataPtr[off0 + j]; + if (this.DataPtr[offI + j] != b) + ok = false; + if (b == 0) + break; + } + } + return ok; + } + #endregion + } + #endregion +} diff --git a/ChanSort.Plugin.TllFile/ChanSort.Plugin.TllFile.csproj b/ChanSort.Plugin.TllFile/ChanSort.Plugin.TllFile.csproj new file mode 100644 index 0000000..d931a28 --- /dev/null +++ b/ChanSort.Plugin.TllFile/ChanSort.Plugin.TllFile.csproj @@ -0,0 +1,138 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {E972D8A1-2F5F-421C-AC91-CFF45E5191BE} + Library + Properties + ChanSort.Plugin.TllFile + ChanSort.Plugin.TllFile + v3.5 + 512 + Client + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + ..\Debug\ + DEBUG;TRACE + true + full + x86 + prompt + false + true + true + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + false + true + + + + + + + + + + + + + + + + + + + + + + + True + True + Resource.de.resx + + + True + True + Resource.resx + + + + + + + Form + + + TvSettingsForm.cs + + + + + {DCCFFA08-472B-4D17-BB90-8F513FC01392} + ChanSort.Api + + + + + Always + + + + + + ResXFileCodeGenerator + Resource.de.Designer.cs + Designer + + + ResXFileCodeGenerator + Resource.Designer.cs + Designer + + + TvSettingsForm.cs + Designer + + + TvSettingsForm.cs + Designer + + + + + \ No newline at end of file diff --git a/ChanSort.Plugin.TllFile/ChanSort.Plugin.TllFile.ini b/ChanSort.Plugin.TllFile/ChanSort.Plugin.TllFile.ini new file mode 100644 index 0000000..d262571 --- /dev/null +++ b/ChanSort.Plugin.TllFile/ChanSort.Plugin.TllFile.ini @@ -0,0 +1,331 @@ +; FileConfigurationX: overall file and DVB-S data layout +; ACTChannelDataMappingX: analog, DVB-C and DVB-T channel data mapping for data length X + +[FileConfiguration1] + ; LM and PM series except LM611S and LM340S + magicBytes = 90, 90, 90, 90 + satCount = 64 + satLength = 44 + transponderCount = 2400 + transponderLength = 40 + dvbsChannelCount = 7520 + dvbsChannelLength = 72 + lnbCount = 40 + lnbLength = 44 + +[FileConfiguration2] + ; LV and LW series (some LW don't have DVB-S though), some LM models + magicBytes = 90, 90, 90, 90 + satCount = 64 + satLength = 44 + transponderCount = 2400 + transponderLength = 40 + dvbsChannelCount = 7520 + dvbsChannelLength = 68 + lnbCount = 40 + lnbLength = 44 + +[FileConfiguration3] + ; DM and LH series + magicBytes = + satCount = 0 + + +[ACTChannelDataMapping:192] + ; LM series with Firmware 4.x (all except LM611S and LM340S) + reorderChannelData = 0 + lenName = 40 + offChannelTransponder = 10, 94, 126, 132 + offProgramNr = 12, 128 + offFavorites = 20 + offPcrPid = 22, 180 + offAudioPid = 24 + offVideoPid = 26 + offName = 30, 140 + offNameLength = 70, 139 + offServiceId = 72, 136 + offFrequencyLong = 96 + offOriginalNetworkId = 102 + offTransportStreamId = 104 + offFavorites2 = 134 + offLock = 135 + maskLock = 0x01 + offSkip = 135 + maskSkip = 0x02 + offHide = 135 + maskHide = 0x04 + offServiceType = 138 + offAudioPid2 = 182 + +[ACTChannelDataMapping:188] + ; LM series with Firmware 3.x (LM611S with exceptions, LM340S) + reorderChannelData = 0 + lenName = 40 + offChannelTransponder = 10, 94, 125, 132 + offProgramNr = 12, 128 + offFavorites = 20 + offPcrPid = 22, 180 + offAudioPid = 24 + offVideoPid = 26 + offName = 30, 140 + offNameLength = 70, 139 + offServiceId = 72, 136 + offFrequencyLong = 96 + offOriginalNetworkId = 102 + offTransportStreamId = 104 + offFavorites2 = 134 + offLock = 135 + maskLock = 0x01 + offSkip = 135 + maskSkip = 0x02 + offHide = 135 + maskHide = 0x04 + offServiceType = 138 + offAudioPid2 = 182 + +[ACTChannelDataMapping:184] + ; LV470S,LV570S,LV579S(with exceptions), LW5500,LW5590,LW570S,LW579S,LW650S,LW659S(with exceptions) + ; LK950S, CS460S, PM670S, LM611S(with exceptions) + reorderChannelData = 0 + lenName = 40 + offChannelTransponder = 10, 90, 121, 128 + offProgramNr = 12, 124 + offFavorites = 20 + offPcrPid = 22, 176 + offAudioPid = 24 + offVideoPid = 26 + offName = 30, 136 + offNameLength = 70, 135 + offServiceId = 72, 132 + offFrequencyLong = 92 + offOriginalNetworkId = 98 + offTransportStreamId = 100 + offFavorites2 = 130 + offLock = 131 + maskLock = 0x01 + offSkip = 131 + maskSkip = 0x02 + offHide = 131 + maskHide = 0x04 + offServiceType = 134 + offAudioPid2 = 178 + +[ACTChannelDataMapping:180] + ; PT + reorderChannelData = 0 + lenName = 40 + offChannelTransponder = 10, 90, 124 + offProgramNr = 12 + offFavorites = 20 + offPcrPid = 22, 172 + offAudioPid = 24 + offVideoPid = 26 + offName = 30, 132 + offNameLength = 70, 131 + offServiceId = 72, 128 + offFrequencyLong = 92 + offOriginalNetworkId = 98 + offTransportStreamId = 100 + offProgramNr2 = 120 + offFavorites2 = 126 + offLock = 127 + maskLock = 0x01 + offSkip = 127 + maskSkip = 0x02 + offHide = 127 + maskHide = 0x04 + offServiceType = 130 + offAudioPid2 = 172 + +[ACTChannelDataMapping:176] + ; LD, LE series, LK450, LW4500, LW5400 + reorderChannelData = 0 + lenName = 40 + offChannelTransponder = 10, 86, 120 + offProgramNr = 12 + offFavorites = 20 + offPcrPid = 22, 168 + offAudioPid = 24 + offVideoPid = 26 + offName = 30, 128 + offNameLength = 70, 127 + offServiceId = 72, 124 + offFrequencyLong = 88 + offOriginalNetworkId = 94 + offTransportStreamId = 96 + offProgramNr2 = 116 + offFavorites2 = 122 + offLock = 123 + maskLock = 0x01 + offSkip = 123 + maskSkip = 0x02 + offHide = 123 + maskHide = 0x04 + offServiceType = 126 + offAudioPid2 = 170 + +[ACTChannelDataMapping:164] + ; DM and LH series + reorderChannelData = 1 + lenName = 40 + offChannelTransponder = 9, 112 + offProgramNr = 10 + offFavorites = 18 + offPcrPid = 20, 156 + offAudioPid = 22 + offVideoPid = 24 + offName = 28, 116 + offNameLength = 68 + offServiceId = 70 + offOriginalNetworkId = 86 + offTransportStreamId = 88 + offFrequencyLong = 96 + offProgramNr2 = 108 + offFavorites2 = 113 + offLock = 113 + maskLock = + offSkip = 113 + maskSkip = 0x20 + offHide = 113 + maskHide = + offServiceType = 115 + offAudioPid2 = 158 + +[SatChannelDataMapping:68] + lenName = 40 + offSatelliteNr = 0 + offSourceType = 4 + offTransponderIndex = 5, 12 + offProgramNr = 8 + offProgramNrPreset = 10 + offFavorites = 14 + maskFavorites = 0x3C + offDeleted = 14 + maskDeleted = 0x42 + offEncrypted = 14 + maskEncrypted = 0x80 + offLock = 15 + maskLock = 0x01 + offSkip = 15 + maskSkip = 0x02 + offHide = 15 + maskHide = 0x04 + offProgNrCustomized = 15 + maskProgNrCustomized = 0x40 + offServiceId = 16 + offServiceType = 18 + offNameLength = 19 + offName = 20 + offVideoPid = 60 + offAudioPid = 62 + +[SatChannelDataMapping:72] + lenName = 40 + offSatelliteNr = 0 + offSourceType = 4 + offTransponderIndex = 6, 12 + offProgramNr = 8 + offProgramNrPreset = 10 + offFavorites = 14 + maskFavorites = 0x3C + offDeleted = 14 + maskDeleted = 0x42 + offEncrypted = 14 + maskEncrypted = 0x80 + offLock = 15 + maskLock = 0x01 + offSkip = 15 + maskSkip = 0x02 + offHide = 15 + maskHide = 0x04 + offProgNrCustomized = 15 + maskProgNrCustomized = 0x40 + offServiceId = 16 + offServiceType = 18 + offNameLength = 19 + offName = 20 + offVideoPid = 60 + offAudioPid = 62 + +[FirmwareData:6944] + ; LH series + offSize = 0 + offHotelModeEnabled=6543 + offHotelModeDtvUpdate=6553 + +[FirmwareData:11008] + ; DM (2350D) + offSize = 0 + offHotelModeEnabled=10563 + offHotelModeDtvUpdate=10573 + +[FirmwareData:15936] + ; PT + offSize = 0 + offHotelModeEnabled=12601 + offHotelModeDtvUpdate=12611 + +[FirmwareData:15960] + ; LW4500, LW5400 + offSize = 0 + offHotelModeEnabled=12603 + offHotelModeDtvUpdate=12613 + +[FirmwareData:16024] + ; LM611S, LM340S, CS460S + offSize = 0 + offHotelModeEnabled=12639 + offHotelModeDtvUpdate=12649 + +[FirmwareData:23072] + ; LD420, LD450, LD550 + offSize = 0 + offHotelModeEnabled=19721 + offHotelModeDtvUpdate=19731 + +[FirmwareData:23088] + ; LK450 + offSize = 0 + offHotelModeEnabled=19723 + offHotelModeDtvUpdate=19733 + +[FirmwareData:23096] + ; LE5500, LD750 + offSize = 0 + offHotelModeEnabled=19721 + offHotelModeDtvUpdate=19731 + +[FirmwareData:35504] + ; LV,LW,LK950S + offSize = 0 + offSystemLock = + offTvPassword = + offHbbTvEnabled = + offHotelModeEnabled=34643 + offHotelModeDtvUpdate=34653 + offHotelMenuAccessCode = 34668 + offHotelMenuPin = 34714 + +[FirmwareData:36856] + ; LM860V + offSize = 0 + offSystemLock = 171 + offTvPassword = 173 + offHbbTvEnabled = 35096 + offHotelModeEnabled=35635 + offHotelModeDtvUpdate=35645 + offHotelMenuAccessCode = 35660 + offHotelMenuPin = 35706 + offSettingsChannelUpdate=36544 + +[FirmwareData:36864] + ; LM (except LM611S,LM340S and LM860V),PM,LS + offSize = 0 + offSystemLock = 171 + offTvPassword = 173 + offHbbTvEnabled = 35096 + offHotelModeEnabled=35635 + offHotelModeDtvUpdate=35645 + offHotelMenuAccessCode = 35660 + offHotelMenuPin = 35706 + offSettingsChannelUpdate=36544 diff --git a/ChanSort.Plugin.TllFile/ChannelDataMapping.cs b/ChanSort.Plugin.TllFile/ChannelDataMapping.cs new file mode 100644 index 0000000..bf1e8f3 --- /dev/null +++ b/ChanSort.Plugin.TllFile/ChannelDataMapping.cs @@ -0,0 +1,23 @@ +using System; +using System.Text; +using ChanSort.Api; + +namespace ChanSort.Plugin.TllFile +{ + internal static class ChannelDataMapping + { + public static unsafe void SetChannelName(ChannelMappingBase mapping, string channelName, Encoding defaultEncoding) + { + byte[] codePagePrefix = new byte[0]; // DvbStringDecoder.GetCodepageBytes(defaultEncoding); + byte[] name = defaultEncoding.GetBytes(channelName); + byte[] newName = new byte[codePagePrefix.Length + name.Length + 1]; + Array.Copy(codePagePrefix, 0, newName, 0, codePagePrefix.Length); + Array.Copy(name, 0, newName, codePagePrefix.Length, name.Length); + fixed (byte* ptrNewName = newName) + { + mapping.NamePtr = ptrNewName; + } + mapping.NameLength = newName.Length; + } + } +} diff --git a/ChanSort.Plugin.TllFile/DvbsChannelDataMapping.cs b/ChanSort.Plugin.TllFile/DvbsChannelDataMapping.cs new file mode 100644 index 0000000..24328c9 --- /dev/null +++ b/ChanSort.Plugin.TllFile/DvbsChannelDataMapping.cs @@ -0,0 +1,197 @@ +using System.Collections.Generic; +using System.Text; +using ChanSort.Api; + +namespace ChanSort.Plugin.TllFile +{ + public unsafe class DvbsChannelDataMapping : DvbChannelMappingBase + { + private const string offSatelliteNr = "offSatelliteNr"; + private const string offTransponderIndex = "offTransponderIndex"; + private const string offProgramNrPreset = "offProgramNrPreset"; + private const string offProgNrCustomized = "offProgNrCustomized"; + private const string maskProgNrCustomized = "maskProgNrCustomized"; + + private readonly DvbStringDecoder dvbsStringDecoder; + + public DvbsChannelDataMapping(IniFile.Section settings, int dataLength, DvbStringDecoder dvbsStringDecoder) : + base(settings, dataLength, null) + { + this.dvbsStringDecoder = dvbsStringDecoder; + } + + #region Encoding + public Encoding Encoding + { + get { return this.dvbsStringDecoder.DefaultEncoding; } + set { this.dvbsStringDecoder.DefaultEncoding = value; } + } + #endregion + + #region InUse + public override bool InUse + { + get { return this.SatelliteNr != 0xFFFF; } + } + #endregion + + #region IsDeleted + public override bool IsDeleted + { + get { return base.IsDeleted; } + set + { + base.IsDeleted = value; + if (value) + this.SatelliteNr = 0xFFFF; + } + } + #endregion + + #region SatelliteNr + public int SatelliteNr + { + get { return this.GetWord(offSatelliteNr); } + set { this.SetWord(offSatelliteNr, value); } + } + #endregion + + #region ProgramNr + public override ushort ProgramNr + { + get { return base.ProgramNr; } + set + { + base.ProgramNr = value; + this.IsProgNrCustomized = true; + } + } + #endregion + + #region ProgramNrPreset + public int ProgramNrPreset + { + get { return this.GetWord(offProgramNrPreset); } + set { this.SetWord(offProgramNrPreset, (ushort)value); } + } + #endregion + + #region IsProgNrCustomized + public bool IsProgNrCustomized + { + get { return GetFlag(offProgNrCustomized, maskProgNrCustomized); } + set { SetFlag(offProgNrCustomized, maskProgNrCustomized, value); } + } + #endregion + + #region Name + public override string Name + { + get + { + string longName, shortName; + this.dvbsStringDecoder.GetChannelNames(this.NamePtr, this.NameLength, out longName, out shortName); + return longName; + } + set { ChannelDataMapping.SetChannelName(this, value, this.dvbsStringDecoder.DefaultEncoding); } + } + #endregion + + #region ShortName + public override string ShortName + { + get + { + string longName, shortName; + this.dvbsStringDecoder.GetChannelNames(this.NamePtr, this.NameLength, out longName, out shortName); + return shortName; + } + } + #endregion + + #region Favorites + public override Favorites Favorites + { + get { return (Favorites)((GetByte(offFavorites)>>2) & 0x0F); } + set + { + var newVal = (GetByte(offFavorites) & 0xC3) | (byte)((byte)value << 2); + SetByte(offFavorites, (byte)newVal); + } + } + #endregion + + #region TransponderIndex + public ushort TransponderIndex + { + get { return GetWord(offTransponderIndex); } + set { SetWord(offTransponderIndex, value); } + } + #endregion + + #region Validate() + public string Validate() + { + bool ok = true; + List warnings = new List(); + ok &= ValidateByte(offTransponderIndex) || AddWarning(warnings, "Transponder index"); + ok &= ValidateWord(offProgramNr) || AddWarning(warnings, "Program#"); + + if (ok) + return null; + + StringBuilder sb = new StringBuilder(); + foreach (var warning in warnings) + { + if (sb.Length > 0) + sb.Append(", "); + sb.Append(warning); + } + return sb.ToString(); + } + #endregion + + #region AddWarning() + private bool AddWarning(List warnings, string p) + { + warnings.Add(p); + return false; + } + #endregion + + #region ValidateByte() + private bool ValidateByte(string key) + { + var offsets = this.GetOffsets(key); + if (offsets == null || offsets.Length < 1) + return true; + byte value = *(this.DataPtr + offsets[0]); + bool ok = true; + foreach (int offset in offsets) + { + if (this.DataPtr[offset] != value) + ok = false; + } + return ok; + } + #endregion + + #region ValidateWord() + private bool ValidateWord(string key) + { + var offsets = this.GetOffsets(key); + if (offsets == null || offsets.Length < 1) + return true; + ushort value = *(ushort*)(this.DataPtr + offsets[0]); + bool ok = true; + foreach (int offset in offsets) + { + if (*(ushort*)(this.DataPtr + offset) != value) + ok = false; + } + return ok; + } + #endregion + + } +} diff --git a/ChanSort.Plugin.TllFile/FirmwareDataMapping.cs b/ChanSort.Plugin.TllFile/FirmwareDataMapping.cs new file mode 100644 index 0000000..8ecbac9 --- /dev/null +++ b/ChanSort.Plugin.TllFile/FirmwareDataMapping.cs @@ -0,0 +1,64 @@ +using ChanSort.Api; + +namespace ChanSort.Plugin.TllFile +{ + public class FirmwareDataMapping : DataMapping + { + private const string offSize = "offSize"; + private const string offSystemLock = "offSystemLock"; + private const string offTvPassword = "offTvPassword"; + private const string offHbbTvEnabled = "offHbbTvEnabled"; + private const string offHotelModeEnabled = "offHotelModeEnabled"; + private const string offHotelModeDtvUpdate = "offHotelModeDtvUpdate"; + private const string offHotelMenuAccessCode = "offHotelMenuAccessCode"; + private const string offHotelMenuPin = "offHotelMenuPin"; + private const string offSettingsChannelUpdate = "offSettingsChannelUpdate"; + + public FirmwareDataMapping(IniFile.Section settings, int structureLength) : + base(settings, structureLength, null) + { + } + + public uint Size { get { return this.GetDword(offSize); } } + public bool SystemLocked { get { return this.GetByte(offSystemLock) != 0; } } + public string TvPassword { get { return CodeToString(this.GetDword(offTvPassword)); } } + public string HotelMenuAccessCode { get { return CodeToString(this.GetDword(offHotelMenuAccessCode)); } } + public string HotelMenuPin { get { return CodeToString(this.GetDword(offHotelMenuPin)); } } + + + public bool SettingsAutomaticChannelUpdate + { + get { return this.GetByte(offSettingsChannelUpdate) != 0; } + set { this.SetByte(offSettingsChannelUpdate, (byte) (value ? 1 : 0)); } + } + + public bool HbbTvEnabled + { + get { return this.GetByte(offHbbTvEnabled) != 0; } + set { this.SetByte(offHbbTvEnabled, (byte)(value ? 1 : 0)); } + } + + public bool HotelModeEnabled + { + get { return this.GetByte(offHotelModeEnabled) != 0; } + set { this.SetByte(offHotelModeEnabled, (byte) (value ? 1 : 0)); } + } + + public bool HotelModeDtvUpdate + { + get { return this.GetByte(offHotelModeDtvUpdate) != 0; } + set { this.SetByte(offHotelModeDtvUpdate, (byte)(value ? 1 : 0)); } + } + + private string CodeToString(uint val) + { + var code = ""; + for (int i = 0; i < 4; i++) + { + code += (char)(33 + (val & 0x0f)); + val >>= 8; + } + return code; + } + } +} diff --git a/ChanSort.Plugin.TllFile/ModelConstants.cs b/ChanSort.Plugin.TllFile/ModelConstants.cs new file mode 100644 index 0000000..c49c9fe --- /dev/null +++ b/ChanSort.Plugin.TllFile/ModelConstants.cs @@ -0,0 +1,49 @@ +namespace ChanSort.Plugin.TllFile +{ + public class ModelConstants + { + public readonly string series; + public readonly byte[] magicBytes; + + public int actChannelLength; // auto-detect + + public readonly int satCount; + public readonly int satLength; + public readonly int sizeOfTransponderBlockHeader; + public readonly int transponderCount; + public readonly int transponderLength; + public readonly int sizeOfZappingTableEntry = 8; + public readonly int dvbsMaxChannelCount; + public readonly int dvbsChannelLength; + public readonly int lnbCount; + public readonly int lnbLength; + public readonly int[] dvbsSubblockLength; + + public bool hasDvbSBlock; + public int firmwareBlockLength; // auto-detect + + public ModelConstants(Api.IniFile.Section iniSection) + { + this.series = iniSection.Name; + this.magicBytes = iniSection.GetBytes("magicBytes"); + this.satCount = iniSection.GetInt("satCount"); + this.satLength = iniSection.GetInt("satLength"); + this.transponderCount = iniSection.GetInt("transponderCount"); + this.transponderLength = iniSection.GetInt("transponderLength"); + this.sizeOfTransponderBlockHeader = 14 + transponderCount/8 + transponderCount*6 + 2; + this.dvbsMaxChannelCount = iniSection.GetInt("dvbsChannelCount"); + this.dvbsChannelLength = iniSection.GetInt("dvbsChannelLength"); + this.lnbCount = iniSection.GetInt("lnbCount"); + this.lnbLength = iniSection.GetInt("lnbLength"); + + this.dvbsSubblockLength = new[] + { + 12, + 14 + 2 + this.satCount + this.satCount*this.satLength, // 2896 + sizeOfTransponderBlockHeader - 4 + transponderCount * transponderLength, // 110712 + 12 + dvbsMaxChannelCount/8 + dvbsMaxChannelCount*sizeOfZappingTableEntry + dvbsMaxChannelCount * dvbsChannelLength, // 602552 + 8 + lnbCount * lnbLength // 1768 + }; + } + } +} diff --git a/ChanSort.Plugin.TllFile/Properties/AssemblyInfo.cs b/ChanSort.Plugin.TllFile/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..6874222 --- /dev/null +++ b/ChanSort.Plugin.TllFile/Properties/AssemblyInfo.cs @@ -0,0 +1,38 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: InternalsVisibleTo("Test.Plugin.TllFile")] + +// 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.Plugin.TllFile")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ChanSort.Plugin.TllFile")] +[assembly: AssemblyCopyright("Copyright © 2012")] +[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("387d8661-ecb3-4957-afca-9a156a90f384")] + +// 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/ChanSort.Plugin.TllFile/Properties/licenses.licx b/ChanSort.Plugin.TllFile/Properties/licenses.licx new file mode 100644 index 0000000..88bdc16 --- /dev/null +++ b/ChanSort.Plugin.TllFile/Properties/licenses.licx @@ -0,0 +1,4 @@ +DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.CheckEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/ChanSort.Plugin.TllFile/Resource.Designer.cs b/ChanSort.Plugin.TllFile/Resource.Designer.cs new file mode 100644 index 0000000..ba699a3 --- /dev/null +++ b/ChanSort.Plugin.TllFile/Resource.Designer.cs @@ -0,0 +1,117 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.586 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ChanSort.Plugin.TllFile { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resource { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resource() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ChanSort.Plugin.TllFile.Resource", typeof(Resource).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to File format is not supported: bad header. + /// + internal static string TllFileSerializer_ERR_badFileHeader { + get { + return ResourceManager.GetString("TllFileSerializer_ERR_badFileHeader", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Channel #{0} (Pr# {1}) was erased because it is a duplicate of channel #{2} (Pr# {3}): {4}. + /// + internal static string TllFileSerializer_ERR_dupeChannel { + get { + return ResourceManager.GetString("TllFileSerializer_ERR_dupeChannel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Wrong checksum: calculated {1:x8} but file has {0:x8}. + /// + internal static string TllFileSerializer_ERR_wrongChecksum { + get { + return ResourceManager.GetString("TllFileSerializer_ERR_wrongChecksum", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to File size {0} is larger than allowed maxiumum of {1}. + /// + internal static string TllFileSerializerPlugin_ERR_fileTooBig { + get { + return ResourceManager.GetString("TllFileSerializerPlugin_ERR_fileTooBig", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The file content doesn't match any supported model. + /// + internal static string TllFileSerializerPlugin_ERR_modelUnknown { + get { + return ResourceManager.GetString("TllFileSerializerPlugin_ERR_modelUnknown", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to LG-Electronics *.tll Loader. + /// + internal static string TllFileSerializerPlugin_PluginName { + get { + return ResourceManager.GetString("TllFileSerializerPlugin_PluginName", resourceCulture); + } + } + } +} diff --git a/ChanSort.Plugin.TllFile/Resource.de.Designer.cs b/ChanSort.Plugin.TllFile/Resource.de.Designer.cs new file mode 100644 index 0000000..e69de29 diff --git a/ChanSort.Plugin.TllFile/Resource.de.resx b/ChanSort.Plugin.TllFile/Resource.de.resx new file mode 100644 index 0000000..aed54d5 --- /dev/null +++ b/ChanSort.Plugin.TllFile/Resource.de.resx @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Ungültiges Dateiformat: Dateikopf unbekannt + + + Prüfsummenfehler: berechnet wurde {1:x8} aber Datei enthält {0:x8} + + + Der Dateiinhalt entstpricht keinem bekannten Modell + + + Dateigröße {0} überschreitet das erlaubte Maximum von {1} + + + LG-Electronics *.tll Loader + + + Sender #{0} (Pr# {1}) wurde gelöscht da er ein Duplikat von Sender #{2} (Pr# {3}) ist: {4} + + \ No newline at end of file diff --git a/ChanSort.Plugin.TllFile/Resource.resx b/ChanSort.Plugin.TllFile/Resource.resx new file mode 100644 index 0000000..47800ba --- /dev/null +++ b/ChanSort.Plugin.TllFile/Resource.resx @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + File format is not supported: bad header + + + Wrong checksum: calculated {1:x8} but file has {0:x8} + + + The file content doesn't match any supported model + + + File size {0} is larger than allowed maxiumum of {1} + + + LG-Electronics *.tll Loader + + + Channel #{0} (Pr# {1}) was erased because it is a duplicate of channel #{2} (Pr# {3}): {4} + + \ No newline at end of file diff --git a/ChanSort.Plugin.TllFile/TllFileSerializer.cs b/ChanSort.Plugin.TllFile/TllFileSerializer.cs new file mode 100644 index 0000000..c327d82 --- /dev/null +++ b/ChanSort.Plugin.TllFile/TllFileSerializer.cs @@ -0,0 +1,1001 @@ +#define FIX_SYMBOL_RATE + +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using ChanSort.Api; + +namespace ChanSort.Plugin.TllFile +{ + public partial class TllFileSerializer : SerializerBase + { + private readonly string ERR_badFileHeader = Resource.TllFileSerializer_ERR_badFileHeader; + private readonly string ERR_wrongChecksum = Resource.TllFileSerializer_ERR_wrongChecksum; + private readonly string ERR_dupeChannel = Resource.TllFileSerializer_ERR_dupeChannel; + private const ushort RadioMask = 0x4000; + + private readonly byte[] fileContent; + private readonly ModelConstants c; + private readonly ActChannelDataMapping actMapping; + private readonly DvbsChannelDataMapping dvbsMapping; + private readonly FirmwareDataMapping firmwareMapping; + private int analogBlockOffset; + private int firmwareBlockOffset; + private int dvbctBlockOffset; + private int dvbsBlockOffset; + private int dvbsSatListOffset; + private int dvbsTransponderSubblockOffset; + private int dvbsChannelHeaderOffset; + private int dvbsChannelCount; + private int dvbsChannelListOffset; + private int[] dvbsSubblockCrcOffset; + private int dvbsLnbSubblockOffset; + private int settingsBlockOffset; + private int duplicateChannels; + private int deletedChannelsHard; + private int deletedChannelsSoft; + + private bool isDvbsSymbolRateDiv2; + private UnsortedChannelMode unsortedChannelMode; + private Dictionary nextChannelIndex; + private int settingsBlockLength; + private int dvbsChannelLinkedListOffset; + private string countryCode; + public IList SupportedTvCountryCodes { get; private set; } + + #region ctor() + public TllFileSerializer(string inputFile, ModelConstants model, + ActChannelDataMapping actMapping, + DvbsChannelDataMapping dvbsMapping, + FirmwareDataMapping firmwareMapping, + byte[] fileContent) : base(inputFile) + { + this.c = model; + this.actMapping = actMapping; + this.dvbsMapping = dvbsMapping; + this.firmwareMapping = firmwareMapping; + this.fileContent = fileContent; + + this.SupportsChannelNameEdit = true; + this.SupportsEraseChannelData = true; + this.SupportedTvCountryCodes = new List + { + "___ (None)", "AUT (Austria)", "BEL (Belgium)", "CHE (Switzerland)", + "DEU (Germany)", "ESP (Spain)", "FRA (France)", "GBR (Great Britain)", + "GRC (Greece)", "IRL (Ireland)", "ITA (Italy)", "LUX (Luxembourg)", + "NLD (Netherlands)", "PRT (Protugal)", "SVN (Slovenia)" + }; + } + #endregion + + #region DisplayName + public override string DisplayName + { + get { return "TLL loader " + (this.c == null ? "" : this.c.series); } + } + #endregion + + #region Load() + public unsafe override void Load() + { + if (this.dvbsMapping != null) + this.dvbsMapping.Encoding = this.DefaultEncoding; + if (this.actMapping != null) + this.actMapping.Encoding = this.DefaultEncoding; + + fixed (byte* ptr = &fileContent[0]) + { + // file header + for (int i = 0; i < c.magicBytes.Length; i++) + { + if (ptr[i] != c.magicBytes[i]) + throw new IOException(ERR_badFileHeader); + } + byte* p = ptr + c.magicBytes.Length; + + // analog channels + ChannelBlock* block = (ChannelBlock*)p; + this.analogBlockOffset = (int)(p - ptr); + this.ReadAnalogChannels(block); + p += block->BlockSize + 4; + + // firmware data + this.firmwareBlockOffset = (int) (p - ptr); + this.FirmwareDataLength = *(uint*) p; + p += this.FirmwareDataLength + 4; + + // dvb-c/t + block = (ChannelBlock*)p; + this.dvbctBlockOffset = (int)(p - ptr); + this.ReadDvbCtChannels(block); + p += block->BlockSize + 4; + + // models without DVB-S + if (c.hasDvbSBlock) + { + this.dvbsBlockOffset = (int) (p - ptr); + p = ReadDvbSBlock(ptr, p); + } + + // settings + this.settingsBlockOffset = (int) (p - ptr); + if (this.settingsBlockOffset >= fileContent.Length) + this.settingsBlockOffset = 0; + else +// ReSharper disable RedundantAssignment + p = this.ReadSettingsBlock(p); +// ReSharper restore RedundantAssignment + } + + this.StoreToDatabase(); + } + #endregion + + #region ReadAnalogChannels() + private unsafe void ReadAnalogChannels(ChannelBlock* block) + { + if (block->ChannelCount == 0) return; + this.actMapping.DataPtr = &block->StartOfChannelList; + for (int i = 0; i < block->ChannelCount; i++) + { + string badFields = this.actMapping.Validate(); + if (badFields != null) + DataRoot.Warnings.AppendFormat("Inconsistent data in analog dvbsMapping at index {0:d4}: {1}\r\n", i, badFields); + + ChannelInfo ci = new ChannelInfo(SignalSource.AnalogCT, GetSignalType(actMapping.ProgramNr), + i, actMapping.ProgramNr & 0x3FFF, actMapping.Name); + + ci.FreqInMhz = (decimal)(actMapping.AnalogFrequency)/20; + ci.Favorites = actMapping.Favorites; + ci.ChannelOrTransponder = (actMapping.AnalogChannelBand == 0 ? "E" : "S") + actMapping.AnalogChannelNr.ToString("d2"); + ci.Lock = actMapping.Lock; + ci.Skip = actMapping.Skip; + ci.Hidden = actMapping.Hide; + + var list = this.DataRoot.GetChannelList(ci.SignalSource, ci.SignalType, true); + this.DataRoot.AddChannel(list, ci); + + actMapping.DataPtr += block->ChannelLength; + } + } + + #endregion + + #region ReadDvbCtChannels() + private unsafe void ReadDvbCtChannels(ChannelBlock* block) + { + if (block->ChannelCount == 0) return; + this.actMapping.DataPtr = &block->StartOfChannelList; + for (int i = 0; i < block->ChannelCount; i++) + { + string badFields = this.actMapping.Validate(); + if (badFields != null) + DataRoot.Warnings.AppendFormat("Inconsistent data in DVB-C/T dvbsMapping at index {0:d4}: {1}\r\n", i, badFields); + + ChannelInfo ci = new ChannelInfo(SignalSource.DvbCT, this.GetSignalType(actMapping.ProgramNr), i, actMapping.ProgramNr & 0x3FFF, actMapping.Name); + ci.ShortName = actMapping.ShortName; + ci.ChannelOrTransponder = actMapping.ChannelOrTransponder.ToString("d2"); + ci.FreqInMhz = (decimal)actMapping.FrequencyLong / 1000; + ci.ServiceId = actMapping.ServiceId; + ci.VideoPid = actMapping.VideoPid; + ci.AudioPid = actMapping.AudioPid; + ci.OriginalNetworkId = actMapping.OriginalNetworkId; + ci.TransportStreamId = actMapping.TransportStreamId; + ci.ServiceType = actMapping.ServiceType; + ci.Lock = actMapping.Lock; + ci.Skip = actMapping.Skip; + ci.Hidden = actMapping.Hide; + ci.Favorites = actMapping.Favorites; + + var list = this.DataRoot.GetChannelList(ci.SignalSource, ci.SignalType, true); + this.DataRoot.AddChannel(list, ci); + + actMapping.DataPtr += block->ChannelLength; + } + } + #endregion + + #region ReadDvbSBlock() + private unsafe byte* ReadDvbSBlock(byte* rootPtr, byte* p) + { + var satBlock = (DvbSBlockHeader*)p; + + var endPtr = this.ScanDvbSSubBlockChecksums(rootPtr, (byte*)&satBlock->Crc32ForSubblock1); + if ((int)(endPtr - p) - 4 != satBlock->BlockSize) + throw new IOException("ERR_invalidDvbSBlockLen"); + + // subblock 0 + 1 (header + satellites) + p = satBlock->SatOrder + c.satCount + 2; + this.dvbsSatListOffset = (int)(p - rootPtr); + this.ReadSatellites((TllSatellite*)p); + p += c.satCount * c.satLength; + + // subblock 2 (tllTransponder) + this.dvbsTransponderSubblockOffset = (int)(p - rootPtr); + p += c.sizeOfTransponderBlockHeader; + this.ReadTransponderData((TllTransponder*)p); + p += c.transponderCount * c.transponderLength; + + // subblock 3 (channels) + this.dvbsChannelHeaderOffset = (int) (p - rootPtr); + SatChannelListHeader* header = (SatChannelListHeader*)p; + this.dvbsChannelCount = header->ChannelCount; + p += sizeof(SatChannelListHeader); + p += c.dvbsMaxChannelCount/8; // skip allocation bitmap + this.dvbsChannelLinkedListOffset = (int) (p - rootPtr); + this.ReadDvbsChannelLinkedList(p); + p += c.dvbsMaxChannelCount * c.sizeOfZappingTableEntry; // linked dvbsMapping list + this.dvbsChannelListOffset = (int)(p - rootPtr); + this.ReadDvbSChannels(p, header->LinkedListStartIndex); + p += c.dvbsMaxChannelCount * c.dvbsChannelLength; + + // subblock 4 (LNB) + this.dvbsLnbSubblockOffset = (int) (p - rootPtr); + + return p + sizeof(LnbBlockHeader) + c.lnbCount*c.lnbLength; + } + + #endregion + + #region ScanDvbSSubBlockChecksums() + private unsafe byte* ScanDvbSSubBlockChecksums(byte* rootPtr, byte* p) + { + this.dvbsSubblockCrcOffset = new int[c.dvbsSubblockLength.Length]; + for (int i = 0; i < dvbsSubblockCrcOffset.Length; i++) + { + this.dvbsSubblockCrcOffset[i] = (int)(p - rootPtr); + int subblockLength = c.dvbsSubblockLength[i]; + uint fileCrc = *(uint*)p; + uint calcCrc = Crc32.CalcCrc32(p + 4, subblockLength); + if (fileCrc != calcCrc) + throw new IOException(string.Format(ERR_wrongChecksum, calcCrc, fileCrc)); + p += 4 + subblockLength; + } + return p; + } + #endregion + + #region ReadSatellites() + private unsafe void ReadSatellites(TllSatellite* satellite) + { + for (int i = 0; i < c.satCount; i++) + { + char[] satName = new char[50]; + fixed (char* ptrSatName = satName) + { + Encoding.ASCII.GetDecoder().GetChars(satellite->Name, TllSatellite.SatNameLength, ptrSatName, satName.Length, true); + } + Satellite sat = new Satellite(i); + sat.Name = new string(satName).TrimEnd('\0'); + sat.OrbitalPosition = GetSatLocation(*satellite); + + this.DataRoot.AddSatellite(sat); + satellite = (TllSatellite*) ((byte*) satellite + c.satLength); + } + } + #endregion + + #region ReadTransponderData() + private unsafe void ReadTransponderData(TllTransponder* tllTransponder) + { + for (int i=0; iSatIndex == 0xFF) + continue; +#if FIX_SYMBOL_RATE + ushort sr = (ushort)(tllTransponder->SymbolRate & 0x7FFF); + if (sr % 100 >= 95) + tllTransponder->SymbolRate = (ushort)((tllTransponder->SymbolRate & 0x8000) | ((sr / 100 + 1) * 100)); +#endif + + Transponder transponder = new Transponder(i); + transponder.FrequencyInMhz = tllTransponder->Frequency; + transponder.TransportStreamId = tllTransponder->TransportStreamId; + transponder.SymbolRate = this.GetDvbsSymbolRate(tllTransponder); + transponder.OriginalNetworkId = tllTransponder->NetworkId; + if (tllTransponder->SymbolRate == 11000) + this.isDvbsSymbolRateDiv2 = true; + + var sat = this.DataRoot.Satellites.TryGet(tllTransponder->SatIndex/2); + this.DataRoot.AddTransponder(sat, transponder); + + tllTransponder = (TllTransponder*)((byte*)tllTransponder + c.transponderLength); + } + } + #endregion + + #region ReadDvbsChannelLinkedList() + private unsafe void ReadDvbsChannelLinkedList(byte* p) + { + this.nextChannelIndex = new Dictionary(); + for (int i = 0; i < c.dvbsMaxChannelCount; i++) + { + short* node = (short*) (p + i*c.sizeOfZappingTableEntry); + if (node[2] != i) + break; + this.nextChannelIndex.Add(node[2], node[1]); + } + } + #endregion + + #region ReadDvbSChannels() + private unsafe void ReadDvbSChannels(byte* channelRoot, int startIndex) + { + int index = startIndex; + for (int i = 0; i < this.dvbsChannelCount; i++) + { + this.dvbsMapping.DataPtr = channelRoot + index * dvbsMapping.DataLength; + string badFields = this.dvbsMapping.Validate(); + if (badFields != null) + DataRoot.Warnings.AppendFormat("Inconsistent data in DVB-S dvbsMapping at index {0:d4}: {1}\r\n", i, badFields); + + if (dvbsMapping.ProgramNr == 0xFFFF) + break; + + if (dvbsMapping.InUse) + { + if (dvbsMapping.IsDeleted) + ++this.deletedChannelsSoft; + else + this.ReadDvbsChannel(index, i); + } + else + ++this.deletedChannelsHard; + + if (!this.nextChannelIndex.TryGetValue(index, out index) || index == -1) + break; + } + } + #endregion + + #region ReadDvbsChannel() + private void ReadDvbsChannel(int index, int order) + { + Transponder transponder = this.DataRoot.Transponder.TryGet(dvbsMapping.TransponderIndex); + Satellite sat = transponder.Satellite; + ChannelInfo ci = new ChannelInfo(SignalSource.DvbS, this.GetSignalType(dvbsMapping.ProgramNr), + index, dvbsMapping.ProgramNr & 0x3FFF, dvbsMapping.Name); + + ci.Satellite = sat.Name; + ci.SatPosition = sat.OrbitalPosition; + ci.RecordOrder = order; + ci.ShortName = dvbsMapping.ShortName; + ci.ServiceId = dvbsMapping.ServiceId; + ci.VideoPid = dvbsMapping.VideoPid & 0x3FFF; + ci.AudioPid = dvbsMapping.AudioPid; + ci.ServiceType = dvbsMapping.ServiceType; + ci.Lock = dvbsMapping.Lock; + ci.Skip = dvbsMapping.Skip; + ci.Hidden = dvbsMapping.Hide; + ci.Favorites = dvbsMapping.Favorites; + ci.Encrypted = dvbsMapping.Encrypted; + ci.TransportStreamId = transponder.TransportStreamId; + ci.OriginalNetworkId = transponder.OriginalNetworkId; + ci.SymbolRate = transponder.SymbolRate; + ci.Polarity = transponder.Polarity; + ci.FreqInMhz = transponder.FrequencyInMhz; + ci.ChannelOrTransponder = this.GetTransponderChannelNumber((ushort)transponder.FrequencyInMhz); + + var list = this.DataRoot.GetChannelList(ci.SignalSource, ci.SignalType, true); + var dupes = list.GetChannelByUid(ci.Uid); + if (dupes.Count > 0) + { + // duplicate channels (ONID,TSID,SSID) cause the TV to randomly reorder channels and show wrong ones in the + // program list, so we erase all dupes here + this.DataRoot.Warnings.AppendFormat(ERR_dupeChannel, ci.RecordIndex, ci.OldProgramNr, dupes[0].RecordIndex, dupes[0].OldProgramNr, dupes[0].Name).AppendLine(); + this.EraseDuplicateDvbsChannel(); + ++this.duplicateChannels; + } + else + this.DataRoot.AddChannel(list, ci); + } + #endregion + + #region EraseDuplicateDvbsChannel() + private unsafe void EraseDuplicateDvbsChannel() + { + byte* p = this.dvbsMapping.DataPtr; + for (int c = this.dvbsMapping.DataLength - 1; c >= 0; c--) + *p++ = 0xFF; + } + #endregion + + #region GetTransponderChannelNumber() + private string GetTransponderChannelNumber(ushort frequency) + { + int nr = LookupData.Instance.GetTransponderNumber(frequency); + return nr <= 0 ? "" : nr.ToString("d3"); + } + #endregion + + #region GetSatLocation() + private string GetSatLocation(TllSatellite sat) + { + return string.Format("{0}.{1}{2}", sat.PosDeg, sat.PosCDeg & 0x0f, sat.PosCDeg < 16 ? "W" : "E"); + } + #endregion + + #region GetSignalType() + private SignalType GetSignalType(uint programNr) + { + if ((programNr & RadioMask) != 0) + return SignalType.Radio; + return SignalType.Tv; + } + #endregion + + #region GetDvbsSymbolRate(), SetDvbsSymbolRate() + private unsafe ushort GetDvbsSymbolRate(TllTransponder* data) + { + ushort value = (ushort)(data->SymbolRate & 0x7fff); + return value <= 20000 ? (ushort)(value << 1) : value; + } + #endregion + + #region ReadSettingsBlock() + private unsafe byte * ReadSettingsBlock(byte* ptr) + { + this.settingsBlockLength = *(int*)ptr; + byte* p = ptr + 4; + if (settingsBlockLength >= 8) + { + StringBuilder code = new StringBuilder(); + for (int i = 6; i >= 4; i--) + code.Append((char) p[i]); + this.countryCode = code.ToString(); + } + return ptr + 4 + settingsBlockLength; + } + #endregion + + + #region Save() + public unsafe override void Save(string tvOutputFile, string csvOutputFile, UnsortedChannelMode unsortedChannelsMode) + { + this.unsortedChannelMode = unsortedChannelsMode; + + // update in-memory file content + fixed (byte* ptrFileContent = this.fileContent) + { + WriteAnalogChannels(ptrFileContent); + WriteDvbCtChannels(ptrFileContent); + WriteDvbSChannels(ptrFileContent); + } + + using (var file = new FileStream(tvOutputFile, FileMode.Create, FileAccess.Write)) + { + fixed (byte* ptr = fileContent) + { + int[] blockOffsets = + { + this.analogBlockOffset, this.firmwareBlockOffset, this.dvbctBlockOffset, + this.dvbsBlockOffset, this.settingsBlockOffset + }; + + // header + file.Write(this.fileContent, 0, this.analogBlockOffset); + + // data blocks + foreach (var blockOffset in blockOffsets) + { + if (blockOffset == 0) continue; + ChannelBlock* block = (ChannelBlock*) (ptr + blockOffset); + file.Write(this.fileContent, blockOffset, (int)block->BlockSize + 4); + } + } + } + } + #endregion + + private unsafe delegate void ChannelUpdateFunc(ushort slot, ChannelInfo appChannel, byte* tllChannel); + + #region WriteAnalogChannels() + private unsafe void WriteAnalogChannels(byte* ptrFileContent) + { + if (c.actChannelLength == 0) return; + ChannelBlock* block = (ChannelBlock*) (ptrFileContent + this.analogBlockOffset); + byte* ptr = &block->StartOfChannelList; + + this.WriteChannels(SignalSource.AnalogCT, ptr, (uint)c.actChannelLength, this.UpdateACTChannel); + } + #endregion + + #region WriteDvbCtChannels() + private unsafe void WriteDvbCtChannels(byte* ptrFileContent) + { + ChannelBlock* block = (ChannelBlock*)(ptrFileContent + this.dvbctBlockOffset); + byte* ptr = &block->StartOfChannelList; + this.WriteChannels(SignalSource.DvbCT, ptr, (uint)c.actChannelLength, this.UpdateACTChannel); + } + #endregion + + #region UpdateACTChannel() + private unsafe void UpdateACTChannel(ushort slot, ChannelInfo appChannel, byte* actChannel) + { + this.UpdateRawChannel(this.actMapping, actChannel, slot, appChannel); + } + #endregion + + #region WriteDvbSChannels() + private unsafe void WriteDvbSChannels(byte* ptrFileContent) + { + if (c.dvbsChannelLength == 0 || !c.hasDvbSBlock) return; + byte* ptr = ptrFileContent + this.dvbsChannelListOffset; + this.WriteChannels(SignalSource.DvbS, ptr, (uint)c.dvbsChannelLength, this.UpdateDvbSChannel); + + // update checksums + for(int i=0; i maxSlot) + maxSlot = slot; + if (slot == 0) + { + if (appChannel.OldProgramNr != 0 && this.unsortedChannelMode != UnsortedChannelMode.Hide) + slot = ++maxSlot; + } + appChannel.OldProgramNr = slot; + if (appChannel.SignalType == SignalType.Radio) + slot |= RadioMask; + return slot; + } + #endregion + + #region ReorderChannelData() + private unsafe void ReorderChannelData(byte* channelDataBase, uint channelDataLength, IList sortedList, int baseIndex) + { + channelDataBase += baseIndex * channelDataLength; + byte[] copy = new byte[sortedList.Count * channelDataLength]; + for (int i = 0; i < copy.Length; i++) + copy[i] = channelDataBase[i]; + + fixed (byte* pCopy = copy) + { + byte* pTarget = channelDataBase; + for (int index = 0; index < sortedList.Count; index++, pTarget += channelDataLength) + { + ChannelInfo appChannel = sortedList[index]; + if (appChannel.RecordIndex == baseIndex + index) + continue; + + byte* pSource = pCopy + (appChannel.RecordIndex - baseIndex)*channelDataLength; + for (int i = 0; i < channelDataLength; i++) + pTarget[i] = pSource[i]; + + appChannel.RecordIndex = baseIndex + index; + } + } + } + #endregion + + + #region DefaultEncoding + public override Encoding DefaultEncoding + { + get { return base.DefaultEncoding; } + set + { + if (Equals(value, this.DefaultEncoding)) + return; + base.DefaultEncoding = value; + if (this.dvbsMapping != null) + this.dvbsMapping.Encoding = value; + if (this.actMapping != null) + this.actMapping.Encoding = value; + if (this.DataRoot.IsEmpty) + return; + ChangeEncoding(); + } + } + #endregion + + #region ChangeEncoding() + + private unsafe void ChangeEncoding() + { + fixed (byte* ptr = this.fileContent) + { + byte* analogChannels = &((ChannelBlock*)(ptr + this.analogBlockOffset))->StartOfChannelList; + byte* dvbctChannels = &((ChannelBlock*)(ptr + this.dvbctBlockOffset))->StartOfChannelList; + byte* dvbsChannels = (ptr + this.dvbsChannelListOffset); + + foreach (var list in DataRoot.ChannelLists) + { + foreach (var channel in list.Channels) + { + switch (channel.SignalSource) + { + case SignalSource.AnalogCT: + ChangeEncodingForChannels(channel, this.actMapping, analogChannels); + break; + case SignalSource.DvbCT: + ChangeEncodingForChannels(channel, this.actMapping, dvbctChannels); + break; + case SignalSource.DvbS: + ChangeEncodingForChannels(channel, this.dvbsMapping, dvbsChannels); + break; + } + } + } + } + } + + private unsafe void ChangeEncodingForChannels(ChannelInfo appChannel, ChannelMappingBase mapping, byte* channelList) + { + if (appChannel.RecordIndex >= c.dvbsMaxChannelCount) + return; + + mapping.DataPtr = channelList + appChannel.RecordIndex*mapping.DataLength; + appChannel.Name = mapping.Name; + appChannel.ShortName = mapping.ShortName; + } + #endregion + + + #region EraseChannelData() + public unsafe override void EraseChannelData() + { + this.DataRoot = new DataRoot(); + fixed (byte* ptr = this.fileContent) + { + // analog channels + ChannelBlock* block = (ChannelBlock*) (ptr + this.analogBlockOffset); + block->BlockSize = 4; + block->ChannelCount = 0; + + // DVB-C/T channels + block = (ChannelBlock*)(ptr + this.dvbctBlockOffset); + block->BlockSize = 4; + block->ChannelCount = 0; + + if (this.dvbsChannelListOffset != 0) + { + EraseTransponders(ptr); + EraseSatChannels(ptr); + EraseLnbSettings(ptr); + } + + this.Save(this.FileName, null, UnsortedChannelMode.Hide); + } + } + #endregion + + #region EraseTransponders() + private unsafe void EraseTransponders(byte* ptr) + { + // clear DVB-S sat table tranponder counts + byte* p = ptr + this.dvbsSatListOffset; + for (int count = c.satCount; count > 0; count--) + { + TllSatellite* sat = (TllSatellite*) p; + sat->Unknown_36 = 0xffff; + sat->Unknown_38 = 0xffff; + sat->TransponderCount = 0; + sat->Unknown_42 = 0; + p += c.satLength; + } + + // clear DVB-S tllTransponder table + p = ptr + this.dvbsTransponderSubblockOffset; + TransponderBlockHeader* tpHeader = (TransponderBlockHeader*) p; + tpHeader->Unknown1 = 0; + tpHeader->HeadIndex = 0; + tpHeader->TailIndex1 = 0; + tpHeader->TailIndex2 = 0; + tpHeader->TransponderCount = 0; + for (int i = 0; i < c.transponderCount/8; i++) + tpHeader->AllocationBitmap[i] = 0; + tpHeader->TransponderLinkedList[0] = 0xFFFF; + tpHeader->TransponderLinkedList[1] = 0xFFFF; + tpHeader->TransponderLinkedList[3] = 0x0000; + for (int i = 3, count = c.transponderCount*3; i < count; i++) + tpHeader->TransponderLinkedList[i] = 0; + tpHeader->Unknown3 = 0; + p = (byte*) (&tpHeader->Unknown3 + 1); + for (int i = 0, count = c.transponderCount*c.transponderLength; i < count; i++) + p[i] = 0xff; + for (int i = 0; i < c.transponderCount; i++) + { + int off = i*c.transponderLength; + p[off + 4] = 0; + p[off + 5] = 0; + p[off + 8] = 0xFE; + } + } + + #endregion + + #region EraseSatChannels() + private unsafe void EraseSatChannels(byte* ptr) + { + SatChannelListHeader* header = (SatChannelListHeader*)(ptr + this.dvbsChannelHeaderOffset); + header->ChannelCount = 0; + header->LinkedListEndIndex1 = 0; + header->LinkedListEndIndex2 = 0; + + // clear DVB-S dvbsMapping allocation table + byte* p = ptr + this.dvbsChannelHeaderOffset + sizeof(SatChannelListHeader); + for (int count = c.dvbsMaxChannelCount / 8; count > 0; count--) + *p++ = 0; + + // clear DVB-S dvbsMapping linked list + for (int i = 0; i < 4; i++) + *p++ = 0xFF; + for (int count = c.dvbsMaxChannelCount * 8 - 4; count > 0; count--) + *p++ = 0; + + // clear DVB-S dvbsMapping data + p = ptr + this.dvbsChannelListOffset; + for (int count = c.dvbsMaxChannelCount * c.dvbsChannelLength; count > 0; count--) + *p++ = 0xFF; + } + #endregion + + #region EraseLnbSettings() + private unsafe void EraseLnbSettings(byte* ptr) + { + // clear LNB data (except for first - otherwise TV crashes) + byte* p = ptr + this.dvbsLnbSubblockOffset; + LnbBlockHeader* lnbHeader = (LnbBlockHeader*)p; + for (int i = 0; i < c.lnbCount / 8; i++) + lnbHeader->lnbAllocationBitmap[i] = 0; + lnbHeader->lnbAllocationBitmap[0] = 0x01; + lnbHeader->lastUsedIndex = 0; + p += sizeof(LnbBlockHeader); + p += c.lnbLength; + for (int count = (c.lnbCount - 1) * c.lnbLength; count > 0; count--) + *p++ = 0; + } + #endregion + + // Testing + + #region GetHotelMenuOffset() + public unsafe int GetHotelMenuOffset() + { + fixed (byte* ptr = this.fileContent) + { + byte* p = ptr + this.firmwareBlockOffset; + for (int i = 6500; i < this.FirmwareDataLength - 3; i++) + { + if (*(uint*)(p+i) == 0x05000101) // 1,1,0,5 + { + for (int j = 5; j < 20; j++) // backtrack to find Volume/MaxVolue pattern + { + if (*(p + i - j) == 101 && *(p + i - j - 6) == 100) // check for Volume/MaxVolue to be 101/100 + return this.firmwareBlockOffset + i - j - 15; + } + return -1; + } + } + return -1; + } + } + #endregion + + public uint ACTChannelLength { get { return (uint)c.actChannelLength; } } + public bool HasDvbs { get { return c.hasDvbSBlock; } } + public int SatChannelLength { get { return c.hasDvbSBlock ? c.dvbsChannelLength : 0; } } + public bool SatSymbolRateDiv2 { get { return this.isDvbsSymbolRateDiv2; } } + + #region GetFileInformation() + public unsafe override string GetFileInformation() + { + StringBuilder sb = new StringBuilder(); + + fixed (byte* ptr = this.fileContent) + { + ChannelBlock* block = (ChannelBlock*)(ptr + this.analogBlockOffset); + sb.AppendLine("ANALOG"); + sb.Append("Number of data records: ").Append(block->ChannelCount).AppendLine(); + sb.Append("Length of data record: ").Append(block->ChannelLength).AppendLine(); + sb.AppendLine(); + + sb.AppendLine(); + sb.AppendLine("DVB-C/T"); + block = (ChannelBlock*)(ptr + this.dvbctBlockOffset); + sb.Append("Number of data records: ").Append(block->ChannelCount).AppendLine(); + sb.Append("Length of data record: ").Append(block->ChannelLength).AppendLine(); + sb.AppendLine(); + + sb.AppendLine(); + sb.AppendLine("DVB-S"); + if (c.hasDvbSBlock) + { + int numberOfDupePrNr; + CountDuplicateRecords(out numberOfDupePrNr); + SatChannelListHeader* satHeader = (SatChannelListHeader*) (ptr + dvbsChannelHeaderOffset); + int numberOfDeletedChannels, numberOfChannelsAtPr0; + this.CountDeletedDvbsChannels(ptr, satHeader->ChannelCount, out numberOfDeletedChannels, out numberOfChannelsAtPr0); + sb.Append("Max number of data records: ").Append(c.dvbsMaxChannelCount).AppendLine(); + sb.Append("Length of data record: ").Append(c.dvbsChannelLength).AppendLine(); + sb.Append("Channel records in use: ").Append(satHeader->ChannelCount).AppendLine(); + sb.Append("Channel records marked hard-deleted: ").Append(this.deletedChannelsHard).AppendLine(); + sb.Append("Channel records marked soft-deleted: ").Append(this.deletedChannelsSoft).AppendLine(); + sb.Append("Channel records erased (duplicates): ").Append(this.duplicateChannels).AppendLine(); + sb.Append("Channel records with Pr# 0: ").Append(numberOfChannelsAtPr0).AppendLine(); + sb.Append("Channel records with duplicate Pr#: ").Append(numberOfDupePrNr).AppendLine(); + } + else + sb.AppendLine("not present"); + } + + return sb.ToString(); + } + + private void CountDuplicateRecords(out int numberOfDupePrNr) + { + numberOfDupePrNr = 0; + foreach (var list in this.DataRoot.ChannelLists) + { + if ((list.SignalSource & SignalSource.Sat) != 0) + numberOfDupePrNr += list.DuplicateProgNrCount; + } + } + + private unsafe void CountDeletedDvbsChannels(byte* ptr, ushort count, out int deletedChannels, out int channelsAtPr0) + { + deletedChannels = 0; + channelsAtPr0 = 0; + this.dvbsMapping.DataPtr = ptr + dvbsChannelListOffset; + for (int i = 0; i < count; i++) + { + if (!this.dvbsMapping.InUse) + ++deletedChannels; + else if ((this.dvbsMapping.ProgramNr & 0x3FFF) == 0 && !this.dvbsMapping.IsDeleted) + ++channelsAtPr0; + this.dvbsMapping.Next(); + } + } + #endregion + + #region TvCountryCode + public unsafe string TvCountryCode + { + get { return this.countryCode; } + set + { + if (value.Length < 3 || this.settingsBlockOffset == 0 || this.settingsBlockLength < 8) return; + value = value.ToUpper(); + fixed (byte* ptr = this.fileContent) + { + byte *p = ptr + this.settingsBlockOffset + 4 + 4 + 2; + for (int i = 0; i < 3; i++) + *p-- = (byte) value[i]; + } + this.countryCode = value; + } + } + #endregion + + #region ShowDeviceSettingsForm() + public override void ShowDeviceSettingsForm(object parentWindow) + { + using (var dlg = new TvSettingsForm(this)) + { + dlg.ShowDialog((Form) parentWindow); + } + } + #endregion + + + internal byte[] FileContent { get { return this.fileContent; } } + + internal unsafe FirmwareDataMapping GetFirmwareMapping(byte* ptrFileContent) + { + if (this.firmwareMapping == null) return null; + this.firmwareMapping.DataPtr = ptrFileContent + this.firmwareBlockOffset; + return this.firmwareMapping; + } + + internal uint FirmwareDataLength { get; private set; } + internal int FirmwareOffset { get { return this.firmwareBlockOffset; } } + } +} diff --git a/ChanSort.Plugin.TllFile/TllFileSerializer.sql.cs b/ChanSort.Plugin.TllFile/TllFileSerializer.sql.cs new file mode 100644 index 0000000..bfb24b2 --- /dev/null +++ b/ChanSort.Plugin.TllFile/TllFileSerializer.sql.cs @@ -0,0 +1,208 @@ +using System; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; +using System.Text; +using ChanSort.Api; + +namespace ChanSort.Plugin.TllFile +{ + public partial class TllFileSerializer + { + #region SQL + + /* + +create table list ( +listid int not null, +filename varchar(100), +created datetime, +primary key (listid)) + +create table channel ( +listid int not null, +slot int not null, +isdel bit not null, +seq int, +progmask int not null, +prognr int not null, +name varchar(40) not null, +tpnr int not null, +satnr int, +onid int not null, +tsid int not null, +ssid int not null, +uid varchar(25), +favcrypt int, +lockskiphide int, +progfix int, +primary key (listid, slot)) + +create table chanseq( +listid int not null, +seq int not null, +slot int not null, +primary key (listid, seq)) + + +update channel +set seq=s.seq +from channel c inner join chanseq s on s.listid=c.listid and s.slot=c.slot + + +*/ + #endregion + + private unsafe void StoreToDatabase() + { + return; + var list = this.DataRoot.GetChannelList(SignalSource.DvbS, SignalType.Tv, false); + if (list == null) + return; + + using (var conn = SqlClientFactory.Instance.CreateConnection()) + { + conn.ConnectionString = "server=(local);database=ChanSort;Integrated Security=true"; + conn.Open(); + + using (var cmd = conn.CreateCommand()) + { + var listId = InsertListData(cmd); + + fixed (byte* ptr = this.fileContent) + { + InsertSequenceData(ptr, cmd, listId); + InsertChannelData(ptr, cmd, listId); + } + } + } + } + + private unsafe void InsertSequenceData(byte* ptr, DbCommand cmd, int listId) + { + cmd.Parameters.Clear(); + cmd.CommandText = "insert into chanseq(listid,seq,slot) values (" + listId + ",@seq,@slot)"; + var pSeq = cmd.CreateParameter(); + pSeq.ParameterName = "@seq"; + pSeq.DbType = DbType.Int32; + cmd.Parameters.Add(pSeq); + var pSlot = cmd.CreateParameter(); + pSlot.ParameterName = "@slot"; + pSlot.DbType = DbType.Int32; + cmd.Parameters.Add(pSlot); + + SatChannelListHeader* header = (SatChannelListHeader*) (ptr + this.dvbsChannelHeaderOffset); + + int seq = 0; + ushort tableIndex = header->LinkedListStartIndex; + while(tableIndex != 0xFFFF) + { + ushort* entry = (ushort*)(ptr + this.dvbsChannelLinkedListOffset + tableIndex*c.sizeOfZappingTableEntry); + pSeq.Value = seq; + if (entry[2] != tableIndex) + break; + pSlot.Value = (int)tableIndex; + cmd.ExecuteNonQuery(); + + tableIndex = entry[1]; + ++seq; + } + } + + #region InsertListData() + private int InsertListData(DbCommand cmd) + { + cmd.CommandText = "select max(listid) from list"; + var maxObj = cmd.ExecuteScalar(); + int listId = maxObj == DBNull.Value ? 1 : (int) maxObj + 1; + + cmd.CommandText = "insert into list(listid, filename, created) values (" + listId + ", @filename, getdate())"; + var parm = cmd.CreateParameter(); + parm.ParameterName = "@filename"; + parm.DbType = DbType.String; + parm.Value = this.FileName; + cmd.Parameters.Add(parm); + cmd.ExecuteNonQuery(); + return listId; + } + #endregion + + #region InsertChannelData() + private unsafe void InsertChannelData(byte* ptr, DbCommand cmd, int listId) + { + PrepareChannelInsert(cmd); + + dvbsMapping.DataPtr = ptr + this.dvbsChannelListOffset; + for (int slot = 0; slot < this.dvbsChannelCount; slot++) + { + cmd.Parameters["@listid"].Value = listId; + cmd.Parameters["@slot"].Value = slot; + cmd.Parameters["@seq"].Value = DBNull.Value; + cmd.Parameters["@isdel"].Value = dvbsMapping.InUse ? 0 : 1; + cmd.Parameters["@progmask"].Value = dvbsMapping.ProgramNr; + cmd.Parameters["@prognr"].Value = (dvbsMapping.ProgramNr & 0x3FFF); + cmd.Parameters["@progfix"].Value = dvbsMapping.ProgramNrPreset; + cmd.Parameters["@name"].Value = dvbsMapping.Name; + cmd.Parameters["@tpnr"].Value = dvbsMapping.TransponderIndex; + var transp = this.DataRoot.Transponder.TryGet(dvbsMapping.TransponderIndex); + cmd.Parameters["@satnr"].Value = transp == null ? (object)DBNull.Value : transp.Satellite.Id; + cmd.Parameters["@onid"].Value = transp == null ? (object)DBNull.Value : transp.OriginalNetworkId; + cmd.Parameters["@tsid"].Value = transp == null ? (object)DBNull.Value : transp.TransportStreamId; + cmd.Parameters["@ssid"].Value = (int)dvbsMapping.ServiceId; + cmd.Parameters["@uid"].Value = transp == null + ? (object) DBNull.Value + : transp.TransportStreamId + "-" + transp.OriginalNetworkId + "-" + + dvbsMapping.ServiceId; + cmd.Parameters["@favcrypt"].Value = (int)dvbsMapping.GetByte("offFavorites"); + cmd.Parameters["@lockskiphide"].Value = (int)dvbsMapping.GetByte("offLock"); + cmd.ExecuteNonQuery(); + dvbsMapping.Next(); + } + } + #endregion + + #region PrepareChannelInsert() + private static void PrepareChannelInsert(DbCommand cmd) + { + var cols = new[] { "listid", "slot", "seq", "isdel", "progmask", "prognr", "progfix", "name", "tpnr", "satnr", "onid", "tsid", "ssid", "uid", "favcrypt", "lockskiphide" }; + + cmd.Parameters.Clear(); + + var sb = new StringBuilder(); + sb.Append("insert into channel ("); + var comma = ""; + foreach (var col in cols) + { + sb.Append(comma).Append(col); + comma = ","; + } + sb.Append(") values ("); + comma = ""; + foreach (var col in cols) + { + sb.Append(comma).Append('@').Append(col); + comma = ","; + } + sb.Append(")"); + cmd.CommandText = sb.ToString(); + + foreach (var col in cols) + { + DbParameter parm = cmd.CreateParameter(); + parm.ParameterName = "@" + col; + if (col == "name" || col == "uid") + { + parm.DbType = DbType.String; + parm.Size = 40; + } + else + parm.DbType = DbType.Int32; + cmd.Parameters.Add(parm); + } + + cmd.Prepare(); + } + #endregion + + } +} \ No newline at end of file diff --git a/ChanSort.Plugin.TllFile/TllFileSerializerPlugin.cs b/ChanSort.Plugin.TllFile/TllFileSerializerPlugin.cs new file mode 100644 index 0000000..8d4006b --- /dev/null +++ b/ChanSort.Plugin.TllFile/TllFileSerializerPlugin.cs @@ -0,0 +1,185 @@ +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Text; +using ChanSort.Api; + +namespace ChanSort.Plugin.TllFile +{ + public class TllFileSerializerPlugin : ISerializerPlugin + { + private const int MAX_FILE_SIZE = 16*1000*1000; + private readonly string ERR_modelUnknown = Resource.TllFileSerializerPlugin_ERR_modelUnknown; + private readonly string ERR_fileTooBig = Resource.TllFileSerializerPlugin_ERR_fileTooBig; + private static readonly byte[] DVBS_S2 = Encoding.ASCII.GetBytes("DVBS-S2"); + + private readonly MappingPool actMappings = new MappingPool("Analog and DVB-C/T"); + private readonly MappingPool dvbsMappings = new MappingPool("DVB-S"); + private readonly MappingPool firmwareMappings = new MappingPool("Firmware"); + private readonly List modelConstants = new List(); + private string series = ""; + + public string PluginName { get { return Resource.TllFileSerializerPlugin_PluginName; } } + public string FileFilter { get { return "*.TLL"; } } + + public TllFileSerializerPlugin() + { + this.ReadConfigurationFromIniFile(); + } + + #region ReadConfigurationFromIniFile() + + private void ReadConfigurationFromIniFile() + { + DvbStringDecoder dvbsStringDecoder = new DvbStringDecoder(null); + string iniFile = Assembly.GetExecutingAssembly().Location.Replace(".dll", ".ini"); + IniFile ini = new IniFile(iniFile); + foreach (var section in ini.Sections) + { + int idx = section.Name.IndexOf(":"); + int recordLength = idx < 0 ? 0 : int.Parse(section.Name.Substring(idx + 1)); + if (section.Name.StartsWith("FileConfiguration")) + this.ReadModelConstants(section); + else if (section.Name.StartsWith("ACTChannelDataMapping")) + actMappings.AddMapping(new ActChannelDataMapping(section, recordLength, dvbsStringDecoder)); + else if (section.Name.StartsWith("SatChannelDataMapping")) + dvbsMappings.AddMapping(new DvbsChannelDataMapping(section, recordLength, dvbsStringDecoder)); + else if (section.Name.StartsWith("FirmwareData")) + firmwareMappings.AddMapping(new FirmwareDataMapping(section, recordLength)); + } + } + + private void ReadModelConstants(IniFile.Section section) + { + if (this.series.Length > 0) + this.series += ","; + this.series += section.Name; + + ModelConstants c = new ModelConstants(section); + this.modelConstants.Add(c); + } + #endregion + + #region CreateSerializer() + public SerializerBase CreateSerializer(string inputFile) + { + long fileSize = new FileInfo(inputFile).Length; + if (fileSize > MAX_FILE_SIZE) + throw new IOException(string.Format(ERR_fileTooBig, fileSize, MAX_FILE_SIZE)); + byte[] fileContent = File.ReadAllBytes(inputFile); + ModelConstants model = this.DetermineModel(fileContent); + if (model == null) + throw new IOException(ERR_modelUnknown); + + return new TllFileSerializer(inputFile, model, + this.actMappings.GetMapping(model.actChannelLength), + this.dvbsMappings.GetMapping(model.dvbsChannelLength), + this.firmwareMappings.GetMapping(model.firmwareBlockLength, false), + fileContent); + } + #endregion + + + #region DetermineModel() + private ModelConstants DetermineModel(byte[] fileContent) + { + foreach (var model in this.modelConstants) + { + if (this.IsModel(fileContent, model)) + return model; + } + return null; + } + #endregion + + #region IsModel() + private unsafe bool IsModel(byte[] fileContent, ModelConstants c) + { + c.hasDvbSBlock = false; + fixed (byte* p = fileContent) + { + long fileSize = fileContent.Length; + + // check magic file header + uint offset = 0; + if (fileSize < c.magicBytes.Length) + return false; + if (!ByteCompare(p, c.magicBytes)) + return false; + offset += (uint)c.magicBytes.Length; + + // analog channel block + if (offset + 8 > fileSize) return false; + uint blockSize = *(uint*)(p + offset); + uint channelCount = *(uint*) (p + offset + 4); + if (blockSize < 4 + channelCount) + return false; + if (blockSize > 4 && channelCount > 0) + c.actChannelLength = (int)((blockSize - 4)/channelCount); + offset += 4 + blockSize; + + // firmware data block + if (offset + 4 > fileSize) return false; + blockSize = *(uint*) (p + offset); + c.firmwareBlockLength = (int)blockSize; + offset += 4 + blockSize; + + // DVB-C/T channel block + if (offset + 8 > fileSize) return false; + blockSize = *(uint*) (p + offset); + channelCount = *(uint*) (p + offset + 4); + if (blockSize < 4 + channelCount) + return false; + if (blockSize > 4 && channelCount > 0) + c.actChannelLength = (int)((blockSize - 4) / channelCount); + offset += 4 + blockSize; + + // optional blocks + while (offset != fileSize) + { + if (offset + 4 > fileSize) + return false; + + blockSize = *(uint*) (p + offset); + // check for DVBS-S2 block + if (blockSize >= sizeof(DvbSBlockHeader)) + { + DvbSBlockHeader* header = (DvbSBlockHeader*) (p + offset); + if (ByteCompare(header->DvbS_S2, DVBS_S2)) + { + c.hasDvbSBlock = true; + int length = sizeof(DvbSBlockHeader) + + c.satCount*c.satLength + + c.sizeOfTransponderBlockHeader + + c.transponderCount*c.transponderLength + + sizeof(SatChannelListHeader) + + c.dvbsMaxChannelCount/8 + + c.dvbsMaxChannelCount*c.sizeOfZappingTableEntry + + c.dvbsMaxChannelCount*c.dvbsChannelLength + + sizeof(LnbBlockHeader) + c.lnbCount*c.lnbLength; + if (length != 4 + blockSize) + return false; + } + } + + offset += 4 + blockSize; + } + return true; + } + } + + #endregion + + #region ByteCompare() + private static unsafe bool ByteCompare(byte* buffer, byte[] expected) + { + for (int i = 0; i < expected.Length; i++) + { + if (buffer[i] != expected[i]) + return false; + } + return true; + } + #endregion + } +} diff --git a/ChanSort.Plugin.TllFile/TllStructures.cs b/ChanSort.Plugin.TllFile/TllStructures.cs new file mode 100644 index 0000000..6dc5059 --- /dev/null +++ b/ChanSort.Plugin.TllFile/TllStructures.cs @@ -0,0 +1,169 @@ +using System.Runtime.InteropServices; + +namespace ChanSort.Plugin.TllFile +{ + /* + TllFileHeader? ("ZZZZ" or nothing) + ChannelBlock + AnalogChannel[] + FirmwareBlock + ChannelBlock + DvbCtChannel[] + DvbSBlockHeader + TllSatellite[64] + TransponderBlockHeader + TllTransponder[2400] + SatChannelListHeader + DvbSChannel[7520] + LnbBlockHeader + Lnb[40] + SettingsBlock? + */ + + #region struct ChannelBlock + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct ChannelBlock + { + public uint BlockSize; // = 4 + ChannelCount * ChannelLength + public uint ChannelCount; + public uint ChannelLength { get { return ChannelCount == 0 ? 0 : (BlockSize - 4) / ChannelCount; } } + public byte StartOfChannelList; + } + #endregion + + #region struct FirmwareBlock + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public unsafe struct FirmwareBlock + { + public uint BlockSize; + public fixed byte Unknown_0x0000[35631]; + public fixed byte HotelMenu[29]; + public fixed byte Unknown_0x8B4C[1204]; // or more + } + #endregion + + + #region struct DvbSBlockHeader + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public unsafe struct DvbSBlockHeader + { + public uint BlockSize; + public uint Crc32ForSubblock1; + public fixed byte DvbS_S2 [8]; // "DVBS-S2\0" + public ushort Unknown_0x10; // 0x0007 + public ushort Unknown_0x12; // 0x0004 // 0x0000 + + public uint Crc32ForSubblock2; + public const int Unknown0x18_Length = 12; + public fixed byte Unknown_0x18[Unknown0x18_Length]; + public ushort SatOrderLength; + public fixed byte SatOrder[64]; + public fixed byte Unknown [2]; + //public fixed TllSatellite Satellites[64] + } + #endregion + + #region struct TllSatellite + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public unsafe struct TllSatellite + { + public const int SatNameLength =32; + + public fixed byte Name [SatNameLength]; + public byte PosDeg; + public byte PosCDeg; + public byte Unknown_34; // typically 0 + public byte Unknown_35; // typically 2 + public ushort Unknown_36; // 0xFFFF if sat is not used + public ushort Unknown_38; // 0xFFFF if sat is not used + public ushort TransponderCount; + public ushort Unknown_42; // typically 0 + } + #endregion + + #region struct TransponderLinkedList + public struct TransponderLinkedList + { + public ushort Prev; + public ushort Next; + public ushort Current; + } + #endregion + + #region struct TransponderBlockHeader + public unsafe struct TransponderBlockHeader + { + public uint Crc32; + public ushort Unknown1; + public ushort HeadIndex; + public ushort TailIndex1; + public ushort TailIndex2; + public ushort TransponderCount; + public fixed byte AllocationBitmap [2400/8]; + public fixed ushort TransponderLinkedList [2400*3]; + public ushort Unknown3; + // public fixed TllTransponder Transponders[2400] + } + #endregion + + #region struct TllTransponder + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public unsafe struct TllTransponder + { + public fixed byte Unknown_0x00 [10]; + public ushort Index; + public ushort Frequency; + public fixed byte Unknown_0x0E [4]; + public ushort NetworkId; + public ushort TransportStreamId; + public fixed byte Unknown_0x16 [3]; + public ushort SymbolRateAndPolarity; + public fixed byte Unknown_0x1B [9]; + public byte SatIndex; + public fixed byte Unknown_0x25 [3]; + + //public int SymbolRate { get { return this.SymbolRateAndPolarity & 0x7FFFF; } } + public ushort SymbolRate { get { return this.SymbolRateAndPolarity; } set { this.SymbolRateAndPolarity = value; } } + public char Polarity { get { return '\0'; } } + } + #endregion + + #region struct SatChannelListHeader + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public unsafe struct SatChannelListHeader + { + public uint Checksum; + public fixed byte Unknown_0x04[4]; + public ushort LinkedListStartIndex; + public ushort LinkedListEndIndex1; + public ushort LinkedListEndIndex2; + public ushort ChannelCount; + } + #endregion + + #region struct LnbBlockHeader + public unsafe struct LnbBlockHeader + { + public uint crc32; + public ushort lastUsedIndex; + public fixed byte lnbAllocationBitmap[6]; + // public Lnb lnbs[40]; + } + #endregion + + #region struct Lnb + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public unsafe struct Lnb + { + public byte SettingsID; + public fixed byte Unknown_0x0D[3]; + public byte SatelliteID; + public fixed byte Unknown_0x11[3]; + public fixed byte FrequencyName[12]; + public ushort LOF1; + public fixed byte Unknown_0x22 [2]; + public ushort LOF2; + public fixed byte Unknown_0x26 [18]; + } + #endregion +} diff --git a/ChanSort.Plugin.TllFile/TvSettingsForm.Designer.cs b/ChanSort.Plugin.TllFile/TvSettingsForm.Designer.cs new file mode 100644 index 0000000..c61de4f --- /dev/null +++ b/ChanSort.Plugin.TllFile/TvSettingsForm.Designer.cs @@ -0,0 +1,223 @@ +namespace ChanSort.Plugin.TllFile +{ + partial class TvSettingsForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TvSettingsForm)); + this.grpSettings = new DevExpress.XtraEditors.GroupControl(); + this.cbHbbTv = new DevExpress.XtraEditors.CheckEdit(); + this.cbCustomCountry = new DevExpress.XtraEditors.CheckEdit(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.btnOk = new DevExpress.XtraEditors.SimpleButton(); + this.btnCancel = new DevExpress.XtraEditors.SimpleButton(); + this.grpHotelMode = new DevExpress.XtraEditors.GroupControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.cbDtvUpdate = new DevExpress.XtraEditors.CheckEdit(); + this.cbHotelMode = new DevExpress.XtraEditors.CheckEdit(); + this.cbAutoChannelUpdate = new DevExpress.XtraEditors.CheckEdit(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.grpFirmwareNote = new DevExpress.XtraEditors.GroupControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.grpSettings)).BeginInit(); + this.grpSettings.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.cbHbbTv.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.cbCustomCountry.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.grpHotelMode)).BeginInit(); + this.grpHotelMode.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.cbDtvUpdate.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.cbHotelMode.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.cbAutoChannelUpdate.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.grpFirmwareNote)).BeginInit(); + this.grpFirmwareNote.SuspendLayout(); + this.SuspendLayout(); + // + // grpSettings + // + this.grpSettings.Controls.Add(this.cbHbbTv); + this.grpSettings.Controls.Add(this.cbCustomCountry); + this.grpSettings.Controls.Add(this.comboBoxEdit1); + this.grpSettings.Controls.Add(this.labelControl1); + resources.ApplyResources(this.grpSettings, "grpSettings"); + this.grpSettings.Name = "grpSettings"; + // + // cbHbbTv + // + resources.ApplyResources(this.cbHbbTv, "cbHbbTv"); + this.cbHbbTv.Name = "cbHbbTv"; + this.cbHbbTv.Properties.Caption = resources.GetString("cbHbbTv.Properties.Caption"); + // + // cbCustomCountry + // + resources.ApplyResources(this.cbCustomCountry, "cbCustomCountry"); + this.cbCustomCountry.Name = "cbCustomCountry"; + this.cbCustomCountry.Properties.Caption = resources.GetString("cbCustomCountry.Properties.Caption"); + this.cbCustomCountry.CheckedChanged += new System.EventHandler(this.cbCustomCountry_CheckedChanged); + // + // comboBoxEdit1 + // + resources.ApplyResources(this.comboBoxEdit1, "comboBoxEdit1"); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(((DevExpress.XtraEditors.Controls.ButtonPredefines)(resources.GetObject("comboBoxEdit1.Properties.Buttons"))))}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + // + // labelControl1 + // + resources.ApplyResources(this.labelControl1, "labelControl1"); + this.labelControl1.Name = "labelControl1"; + // + // btnOk + // + resources.ApplyResources(this.btnOk, "btnOk"); + this.btnOk.DialogResult = System.Windows.Forms.DialogResult.OK; + this.btnOk.Name = "btnOk"; + this.btnOk.Click += new System.EventHandler(this.btnOk_Click); + // + // btnCancel + // + resources.ApplyResources(this.btnCancel, "btnCancel"); + this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.btnCancel.Name = "btnCancel"; + // + // grpHotelMode + // + this.grpHotelMode.Controls.Add(this.labelControl3); + this.grpHotelMode.Controls.Add(this.labelControl2); + this.grpHotelMode.Controls.Add(this.cbDtvUpdate); + this.grpHotelMode.Controls.Add(this.cbHotelMode); + resources.ApplyResources(this.grpHotelMode, "grpHotelMode"); + this.grpHotelMode.Name = "grpHotelMode"; + // + // labelControl3 + // + resources.ApplyResources(this.labelControl3, "labelControl3"); + this.labelControl3.Name = "labelControl3"; + // + // labelControl2 + // + resources.ApplyResources(this.labelControl2, "labelControl2"); + this.labelControl2.Name = "labelControl2"; + // + // cbDtvUpdate + // + resources.ApplyResources(this.cbDtvUpdate, "cbDtvUpdate"); + this.cbDtvUpdate.Name = "cbDtvUpdate"; + this.cbDtvUpdate.Properties.Caption = resources.GetString("cbDtvUpdate.Properties.Caption"); + // + // cbHotelMode + // + resources.ApplyResources(this.cbHotelMode, "cbHotelMode"); + this.cbHotelMode.Name = "cbHotelMode"; + this.cbHotelMode.Properties.Caption = resources.GetString("cbHotelMode.Properties.Caption"); + // + // cbAutoChannelUpdate + // + resources.ApplyResources(this.cbAutoChannelUpdate, "cbAutoChannelUpdate"); + this.cbAutoChannelUpdate.Name = "cbAutoChannelUpdate"; + this.cbAutoChannelUpdate.Properties.Caption = resources.GetString("cbAutoChannelUpdate.Properties.Caption"); + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.cbAutoChannelUpdate); + resources.ApplyResources(this.groupControl1, "groupControl1"); + this.groupControl1.Name = "groupControl1"; + // + // grpFirmwareNote + // + this.grpFirmwareNote.Controls.Add(this.labelControl4); + resources.ApplyResources(this.grpFirmwareNote, "grpFirmwareNote"); + this.grpFirmwareNote.Name = "grpFirmwareNote"; + // + // labelControl4 + // + resources.ApplyResources(this.labelControl4, "labelControl4"); + this.labelControl4.Name = "labelControl4"; + // + // TvSettingsForm + // + this.AcceptButton = this.btnOk; + this.Appearance.Options.UseBackColor = true; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.btnCancel; + this.Controls.Add(this.grpHotelMode); + this.Controls.Add(this.btnCancel); + this.Controls.Add(this.btnOk); + this.Controls.Add(this.grpSettings); + this.Controls.Add(this.groupControl1); + this.Controls.Add(this.grpFirmwareNote); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "TvSettingsForm"; + this.Load += new System.EventHandler(this.TvSettingsForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.grpSettings)).EndInit(); + this.grpSettings.ResumeLayout(false); + this.grpSettings.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.cbHbbTv.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.cbCustomCountry.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.grpHotelMode)).EndInit(); + this.grpHotelMode.ResumeLayout(false); + this.grpHotelMode.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.cbDtvUpdate.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.cbHotelMode.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.cbAutoChannelUpdate.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.grpFirmwareNote)).EndInit(); + this.grpFirmwareNote.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl grpSettings; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton btnOk; + private DevExpress.XtraEditors.SimpleButton btnCancel; + private DevExpress.XtraEditors.CheckEdit cbCustomCountry; + private DevExpress.XtraEditors.GroupControl grpHotelMode; + private DevExpress.XtraEditors.CheckEdit cbHbbTv; + private DevExpress.XtraEditors.CheckEdit cbDtvUpdate; + private DevExpress.XtraEditors.CheckEdit cbHotelMode; + private DevExpress.XtraEditors.CheckEdit cbAutoChannelUpdate; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.GroupControl grpFirmwareNote; + private DevExpress.XtraEditors.LabelControl labelControl4; + } +} \ No newline at end of file diff --git a/ChanSort.Plugin.TllFile/TvSettingsForm.cs b/ChanSort.Plugin.TllFile/TvSettingsForm.cs new file mode 100644 index 0000000..7836c45 --- /dev/null +++ b/ChanSort.Plugin.TllFile/TvSettingsForm.cs @@ -0,0 +1,73 @@ +using System; +using DevExpress.XtraEditors; +using DevExpress.XtraEditors.Controls; + +namespace ChanSort.Plugin.TllFile +{ + public partial class TvSettingsForm : XtraForm + { + private readonly TllFileSerializer tvSerializer; + + public TvSettingsForm(TllFileSerializer tvSerializer) + { + this.tvSerializer = tvSerializer; + InitializeComponent(); + } + + private unsafe void TvSettingsForm_Load(object sender, EventArgs e) + { + var items = tvSerializer.SupportedTvCountryCodes; + foreach(var item in items) + this.comboBoxEdit1.Properties.Items.Add(item); + this.comboBoxEdit1.Text = this.tvSerializer.TvCountryCode; + + byte[] fileContent = this.tvSerializer.FileContent; + fixed (byte* ptr = fileContent) + { + var mapping = this.tvSerializer.GetFirmwareMapping(ptr); + if (mapping != null) + { + this.cbAutoChannelUpdate.Checked = mapping.SettingsAutomaticChannelUpdate; + this.cbHbbTv.Checked = mapping.HbbTvEnabled; + this.cbHotelMode.Checked = mapping.HotelModeEnabled; + this.cbDtvUpdate.Checked = mapping.HotelModeDtvUpdate; + + this.grpFirmwareNote.Visible = false; + this.Height -= this.grpFirmwareNote.Height; + } + else + { + this.cbAutoChannelUpdate.Enabled = false; + this.cbHbbTv.Enabled = false; + this.cbHotelMode.Enabled = false; + this.cbDtvUpdate.Enabled = false; + } + } + } + + private unsafe void btnOk_Click(object sender, EventArgs e) + { + this.tvSerializer.TvCountryCode = this.comboBoxEdit1.Text; + + byte[] fileContent = this.tvSerializer.FileContent; + fixed (byte* ptr = fileContent) + { + var mapping = this.tvSerializer.GetFirmwareMapping(ptr); + if (mapping != null) + { + mapping.SettingsAutomaticChannelUpdate = this.cbAutoChannelUpdate.Checked; + mapping.HbbTvEnabled = this.cbHbbTv.Checked; + mapping.HotelModeEnabled = this.cbHotelMode.Checked; + mapping.HotelModeDtvUpdate = this.cbDtvUpdate.Checked; + } + } + } + + private void cbCustomCountry_CheckedChanged(object sender, EventArgs e) + { + this.comboBoxEdit1.Properties.TextEditStyle = this.cbCustomCountry.Checked + ? TextEditStyles.Standard + : TextEditStyles.DisableTextEditor; + } + } +} diff --git a/ChanSort.Plugin.TllFile/TvSettingsForm.de.resx b/ChanSort.Plugin.TllFile/TvSettingsForm.de.resx new file mode 100644 index 0000000..7cbedf2 --- /dev/null +++ b/ChanSort.Plugin.TllFile/TvSettingsForm.de.resx @@ -0,0 +1,325 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + + + + + + True + + + HbbTV aktivieren (funktioniert nur mit den Ländereinstellungen DEU, FRA, NED und ESP) + + + + + + + + + + + + + + + + + + True + + + Eigene Werte erlauben (auf eigene Gefahr!) + + + + + + + + + + + + + + + + + + True + + + + + + False + + + + 27, 13 + + + Land: + + + OPTION Menü + + + Abbrechen + + + HINWEIS: Bei aktivem Hotel-Modus kann man in der EPG nicht zum gewählten Sender wechseln und die Funktion "Werkseinstellungen" ist gesperrt. + + + 341, 13 + + + Die folgenden Einstellungen funktionieren nur bei aktivem Hotel-Modus: + + + + + + + + + True + + + D-TV Senderliste automatisch aktualisieren (empfohlen: AUS) + + + + + + + + + + + + + + + + + + True + + + Hotel Modus aktivieren (empfohlen: EIN) + + + + + + + + + + + + Hotel Modus + + + + + + + + + True + + + Senderliste automatisch aktualisieren (empfohlen: AUS) + + + + + + + + + + + + EINST. Menü + + + Das Dateiformat Ihres TV-Modells wird nicht vollständig unterstützt. Deshalb sind viele Einstellungen in diesem Dialog gesperrt. + + + + + + + + + True + + + + Default + + + False + + + + + + True + + + None + + + _ + + + True + + + True + + + False + + + + + + False + + + Horizontal + + + + + + TV Einstellungen + + \ No newline at end of file diff --git a/ChanSort.Plugin.TllFile/TvSettingsForm.resx b/ChanSort.Plugin.TllFile/TvSettingsForm.resx new file mode 100644 index 0000000..e459046 --- /dev/null +++ b/ChanSort.Plugin.TllFile/TvSettingsForm.resx @@ -0,0 +1,569 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Top, Left, Right + + + + 12, 64 + + + Enable HbbTV (only works with country settings DEU, FRA, NED and ESP) + + + 456, 19 + + + + 3 + + + cbHbbTv + + + DevExpress.XtraEditors.CheckEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpSettings + + + 0 + + + Top, Left, Right + + + 150, 30 + + + allow custom value (at your own risk!) + + + 320, 19 + + + 2 + + + cbCustomCountry + + + DevExpress.XtraEditors.CheckEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpSettings + + + 1 + + + 72, 29 + + + + Combo + + + 72, 20 + + + 1 + + + comboBoxEdit1 + + + DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpSettings + + + 2 + + + 12, 32 + + + 43, 13 + + + 0 + + + Country: + + + labelControl1 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpSettings + + + 3 + + + Top + + + 0, 142 + + + 480, 106 + + + 0 + + + OPTION Menu + + + grpSettings + + + DevExpress.XtraEditors.GroupControl, DevExpress.Utils.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 3 + + + Bottom, Right + + + 310, 413 + + + 75, 23 + + + 1 + + + Ok + + + btnOk + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 2 + + + Bottom, Right + + + 395, 413 + + + 75, 23 + + + 2 + + + Cancel + + + btnCancel + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 1 + + + + Vertical + + + 12, 26 + + + 458, 26 + + + 7 + + + NOTE: When Hotel Mode is active, you can no longer activate a channel from inside the EPG and the "Factory Reset" function becomes disabled. + + + labelControl3 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpHotelMode + + + 0 + + + 41, 93 + + + 315, 13 + + + 6 + + + The settings below are only effective when Hotel Mode is enabled + + + labelControl2 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpHotelMode + + + 1 + + + Top, Left, Right + + + 39, 112 + + + Automatic D-TV channel update (recommended: OFF) + + + 431, 19 + + + 5 + + + cbDtvUpdate + + + DevExpress.XtraEditors.CheckEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpHotelMode + + + 2 + + + Top, Left, Right + + + 10, 58 + + + Enable Hotel Mode (recommended: ON) + + + 456, 19 + + + 4 + + + cbHotelMode + + + DevExpress.XtraEditors.CheckEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpHotelMode + + + 3 + + + Top + + + 0, 248 + + + 480, 151 + + + 3 + + + Hotel Mode + + + grpHotelMode + + + DevExpress.XtraEditors.GroupControl, DevExpress.Utils.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 0 + + + Top, Left, Right + + + 12, 35 + + + Automatic Channel Update (recommended: OFF) + + + 456, 19 + + + 3 + + + cbAutoChannelUpdate + + + DevExpress.XtraEditors.CheckEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + groupControl1 + + + 0 + + + Top + + + 0, 71 + + + 480, 71 + + + 5 + + + SETUP Menu + + + groupControl1 + + + DevExpress.XtraEditors.GroupControl, DevExpress.Utils.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 4 + + + Vertical + + + 11, 29 + + + 458, 26 + + + 8 + + + Your TV model's TLL file format is not fully supported. Therefore many features in this dialog are disabled. + + + labelControl4 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpFirmwareNote + + + 0 + + + Top + + + 0, 0 + + + 480, 71 + + + 6 + + + Information + + + grpFirmwareNote + + + DevExpress.XtraEditors.GroupControl, DevExpress.Utils.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 5 + + + True + + + 6, 13 + + + 480, 448 + + + CenterParent + + + TV Settings + + + TvSettingsForm + + + DevExpress.XtraEditors.XtraForm, DevExpress.Utils.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + \ No newline at end of file diff --git a/ChanSort.Ui/AboutForm.Designer.cs b/ChanSort.Ui/AboutForm.Designer.cs new file mode 100644 index 0000000..c569c4e --- /dev/null +++ b/ChanSort.Ui/AboutForm.Designer.cs @@ -0,0 +1,241 @@ +namespace ChanSort.Ui +{ + partial class AboutForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutForm)); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.hyperLinkEdit1 = new DevExpress.XtraEditors.HyperLinkEdit(); + this.gcPlugins = new DevExpress.XtraGrid.GridControl(); + this.gvPlugins = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.colPlugin = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colDisplayText = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colFileTypes = new DevExpress.XtraGrid.Columns.GridColumn(); + this.hyperLinkEdit2 = new DevExpress.XtraEditors.HyperLinkEdit(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.hyperLinkEdit3 = new DevExpress.XtraEditors.HyperLinkEdit(); + this.txtCredits = new DevExpress.XtraEditors.MemoEdit(); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.picDonate = new DevExpress.XtraEditors.PictureEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.hyperLinkEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gcPlugins)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gvPlugins)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.hyperLinkEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.hyperLinkEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.txtCredits.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + this.xtraTabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picDonate.Properties)).BeginInit(); + this.SuspendLayout(); + // + // labelControl1 + // + resources.ApplyResources(this.labelControl1, "labelControl1"); + this.labelControl1.Name = "labelControl1"; + // + // hyperLinkEdit1 + // + resources.ApplyResources(this.hyperLinkEdit1, "hyperLinkEdit1"); + this.hyperLinkEdit1.Name = "hyperLinkEdit1"; + this.hyperLinkEdit1.Properties.Appearance.BackColor = ((System.Drawing.Color)(resources.GetObject("hyperLinkEdit1.Properties.Appearance.BackColor"))); + this.hyperLinkEdit1.Properties.Appearance.Options.UseBackColor = true; + this.hyperLinkEdit1.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + // + // gcPlugins + // + resources.ApplyResources(this.gcPlugins, "gcPlugins"); + this.gcPlugins.MainView = this.gvPlugins; + this.gcPlugins.Name = "gcPlugins"; + this.gcPlugins.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gvPlugins}); + // + // gvPlugins + // + this.gvPlugins.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.colPlugin, + this.colDisplayText, + this.colFileTypes}); + this.gvPlugins.GridControl = this.gcPlugins; + this.gvPlugins.Name = "gvPlugins"; + this.gvPlugins.OptionsBehavior.ReadOnly = true; + this.gvPlugins.OptionsView.ShowGroupPanel = false; + this.gvPlugins.OptionsView.ShowIndicator = false; + this.gvPlugins.CustomUnboundColumnData += new DevExpress.XtraGrid.Views.Base.CustomColumnDataEventHandler(this.gvPlugins_CustomUnboundColumnData); + // + // colPlugin + // + resources.ApplyResources(this.colPlugin, "colPlugin"); + this.colPlugin.FieldName = "PluginDll"; + this.colPlugin.Name = "colPlugin"; + this.colPlugin.UnboundType = DevExpress.Data.UnboundColumnType.String; + // + // colDisplayText + // + resources.ApplyResources(this.colDisplayText, "colDisplayText"); + this.colDisplayText.FieldName = "PluginName"; + this.colDisplayText.Name = "colDisplayText"; + // + // colFileTypes + // + resources.ApplyResources(this.colFileTypes, "colFileTypes"); + this.colFileTypes.FieldName = "FileFilter"; + this.colFileTypes.Name = "colFileTypes"; + // + // hyperLinkEdit2 + // + resources.ApplyResources(this.hyperLinkEdit2, "hyperLinkEdit2"); + this.hyperLinkEdit2.Name = "hyperLinkEdit2"; + this.hyperLinkEdit2.Properties.Appearance.BackColor = ((System.Drawing.Color)(resources.GetObject("hyperLinkEdit2.Properties.Appearance.BackColor"))); + this.hyperLinkEdit2.Properties.Appearance.Options.UseBackColor = true; + this.hyperLinkEdit2.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + // + // labelControl3 + // + resources.ApplyResources(this.labelControl3, "labelControl3"); + this.labelControl3.Name = "labelControl3"; + // + // labelControl4 + // + resources.ApplyResources(this.labelControl4, "labelControl4"); + this.labelControl4.Name = "labelControl4"; + // + // labelControl5 + // + resources.ApplyResources(this.labelControl5, "labelControl5"); + this.labelControl5.Name = "labelControl5"; + // + // hyperLinkEdit3 + // + resources.ApplyResources(this.hyperLinkEdit3, "hyperLinkEdit3"); + this.hyperLinkEdit3.Name = "hyperLinkEdit3"; + this.hyperLinkEdit3.Properties.Appearance.BackColor = ((System.Drawing.Color)(resources.GetObject("hyperLinkEdit3.Properties.Appearance.BackColor"))); + this.hyperLinkEdit3.Properties.Appearance.Options.UseBackColor = true; + this.hyperLinkEdit3.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + // + // txtCredits + // + resources.ApplyResources(this.txtCredits, "txtCredits"); + this.txtCredits.Name = "txtCredits"; + this.txtCredits.Properties.ReadOnly = true; + // + // xtraTabControl1 + // + resources.ApplyResources(this.xtraTabControl1, "xtraTabControl1"); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.txtCredits); + this.xtraTabPage1.Name = "xtraTabPage1"; + resources.ApplyResources(this.xtraTabPage1, "xtraTabPage1"); + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.gcPlugins); + this.xtraTabPage2.Name = "xtraTabPage2"; + resources.ApplyResources(this.xtraTabPage2, "xtraTabPage2"); + // + // picDonate + // + this.picDonate.Cursor = System.Windows.Forms.Cursors.Hand; + resources.ApplyResources(this.picDonate, "picDonate"); + this.picDonate.Name = "picDonate"; + this.picDonate.Properties.Appearance.BackColor = ((System.Drawing.Color)(resources.GetObject("picDonate.Properties.Appearance.BackColor"))); + this.picDonate.Properties.Appearance.Options.UseBackColor = true; + this.picDonate.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.picDonate.Click += new System.EventHandler(this.picDonate_Click); + // + // labelControl2 + // + resources.ApplyResources(this.labelControl2, "labelControl2"); + this.labelControl2.Name = "labelControl2"; + // + // AboutForm + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.labelControl2); + this.Controls.Add(this.picDonate); + this.Controls.Add(this.xtraTabControl1); + this.Controls.Add(this.hyperLinkEdit3); + this.Controls.Add(this.labelControl5); + this.Controls.Add(this.labelControl4); + this.Controls.Add(this.hyperLinkEdit2); + this.Controls.Add(this.labelControl3); + this.Controls.Add(this.hyperLinkEdit1); + this.Controls.Add(this.labelControl1); + this.Name = "AboutForm"; + ((System.ComponentModel.ISupportInitialize)(this.hyperLinkEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gcPlugins)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gvPlugins)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.hyperLinkEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.hyperLinkEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.txtCredits.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.picDonate.Properties)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.HyperLinkEdit hyperLinkEdit1; + private DevExpress.XtraGrid.GridControl gcPlugins; + private DevExpress.XtraGrid.Views.Grid.GridView gvPlugins; + private DevExpress.XtraGrid.Columns.GridColumn colPlugin; + private DevExpress.XtraGrid.Columns.GridColumn colDisplayText; + private DevExpress.XtraGrid.Columns.GridColumn colFileTypes; + private DevExpress.XtraEditors.HyperLinkEdit hyperLinkEdit2; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.HyperLinkEdit hyperLinkEdit3; + private DevExpress.XtraEditors.MemoEdit txtCredits; + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private DevExpress.XtraEditors.PictureEdit picDonate; + private DevExpress.XtraEditors.LabelControl labelControl2; + } +} \ No newline at end of file diff --git a/ChanSort.Ui/AboutForm.cs b/ChanSort.Ui/AboutForm.cs new file mode 100644 index 0000000..56abe75 --- /dev/null +++ b/ChanSort.Ui/AboutForm.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using System.IO; +using ChanSort.Api; +using DevExpress.XtraEditors; + +namespace ChanSort.Ui +{ + public partial class AboutForm :XtraForm + { + public AboutForm(IList plugins) + { + InitializeComponent(); + this.picDonate.Image = Properties.Resources.Donate; + this.gcPlugins.DataSource = plugins; + + this.txtCredits.Text = @"PDA-User: +Analysis of TLL file structure and extensive testing of ChanSort + +HellG: +For writing TLLsort which was the basis for the first versions of ChanSort + +edank, JLevi, Oleg: +For writing TLLview, TLLedit and edankTLL and making the source available + +Many more on lg-forum.com: +For providing example TLL files, error feedback and other helpful information"; + } + + private void gvPlugins_CustomUnboundColumnData(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDataEventArgs e) + { + if (e.Column == this.colPlugin) + e.Value = (Path.GetFileName(e.Row.GetType().Assembly.Location) ?? "").Replace("ChanSort.Plugin.", ""); + } + + private void picDonate_Click(object sender, System.EventArgs e) + { + try + { + string fileName = Path.GetTempFileName() + ".html"; + File.WriteAllText(fileName, Properties.Resources.paypal_button); + System.Diagnostics.Process.Start(fileName); + } + catch + { + } + } + } +} \ No newline at end of file diff --git a/ChanSort.Ui/AboutForm.de.resx b/ChanSort.Ui/AboutForm.de.resx new file mode 100644 index 0000000..46fbc44 --- /dev/null +++ b/ChanSort.Ui/AboutForm.de.resx @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 80, 13 + + + Aktuelle Version: + + + Beschreibung + + + Dateitypen + + + 86, 13 + + + Online Diskussion: + + + 41, 13 + + + Kontakt: + + + Gruß und Dank + + + Erweiterungen + + + + + + + 151, 13 + + + Wenn dir das Programm gefällt: + + + Über ChanSort + + \ No newline at end of file diff --git a/ChanSort.Ui/AboutForm.resx b/ChanSort.Ui/AboutForm.resx new file mode 100644 index 0000000..865f986 --- /dev/null +++ b/ChanSort.Ui/AboutForm.resx @@ -0,0 +1,546 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 12, 15 + + + 72, 13 + + + + 0 + + + Latest version: + + + labelControl1 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 9 + + + + Top, Left, Right + + + http://beham.biz/ChanSort/ + + + 144, 13 + + + Transparent + + + 436, 18 + + + 1 + + + hyperLinkEdit1 + + + DevExpress.XtraEditors.HyperLinkEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 8 + + + Fill + + + 0, 0 + + + Plugin + + + True + + + 0 + + + 70 + + + Description + + + True + + + 1 + + + 246 + + + File types + + + True + + + 2 + + + 249 + + + 562, 272 + + + 3 + + + gcPlugins + + + DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabPage2 + + + 0 + + + Top, Left, Right + + + http://www.lg-forum.com/lg-led-plasma-lcd-fernseher/5098-channeleditor-45.html + + + 144, 32 + + + Transparent + + + 436, 18 + + + 5 + + + hyperLinkEdit2 + + + DevExpress.XtraEditors.HyperLinkEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 6 + + + 12, 34 + + + 85, 13 + + + 4 + + + Online discussion: + + + labelControl3 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 7 + + + 12, 56 + + + 42, 13 + + + 6 + + + Contact: + + + labelControl4 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 5 + + + 147, 56 + + + 175, 13 + + + 7 + + + User "Pred" @ www.lg-forum.com | + + + labelControl5 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 4 + + + Top, Left, Right + + + mailto:horst@beham.biz + + + 328, 54 + + + Transparent + + + 252, 18 + + + 8 + + + hyperLinkEdit3 + + + DevExpress.XtraEditors.HyperLinkEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 3 + + + Fill + + + 0, 0 + + + 562, 272 + + + 10 + + + txtCredits + + + DevExpress.XtraEditors.MemoEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabPage1 + + + 0 + + + Top, Bottom, Left, Right + + + 12, 134 + + + 562, 272 + + + Credits + + + xtraTabPage1 + + + DevExpress.XtraTab.XtraTabPage, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabControl1 + + + 0 + + + 568, 300 + + + 11 + + + 562, 272 + + + Plugins + + + xtraTabPage2 + + + DevExpress.XtraTab.XtraTabPage, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabControl1 + + + 1 + + + xtraTabControl1 + + + DevExpress.XtraTab.XtraTabControl, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 2 + + + 214, 78 + + + Transparent + + + 177, 58 + + + 12 + + + picDonate + + + DevExpress.XtraEditors.PictureEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 1 + + + 12, 88 + + + 114, 13 + + + 13 + + + If you like this program: + + + labelControl2 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 0 + + + True + + + 6, 13 + + + 592, 446 + + + CenterParent + + + About ChanSort + + + gvPlugins + + + DevExpress.XtraGrid.Views.Grid.GridView, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colPlugin + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colDisplayText + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colFileTypes + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + AboutForm + + + DevExpress.XtraEditors.XtraForm, DevExpress.Utils.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + \ No newline at end of file diff --git a/ChanSort.Ui/ChanSort.Ui.csproj b/ChanSort.Ui/ChanSort.Ui.csproj new file mode 100644 index 0000000..dc88e7e --- /dev/null +++ b/ChanSort.Ui/ChanSort.Ui.csproj @@ -0,0 +1,215 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {5FAFDABC-A52F-498C-BD2F-AFFC4119797A} + WinExe + Properties + ChanSort.Ui + ChanSort + v3.5 + Client + 512 + + + x86 + true + full + false + ..\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\Debug\ + DEBUG;TRACE + full + AnyCPU + prompt + false + false + + + bin\Release\ + TRACE + true + pdbonly + AnyCPU + prompt + false + false + + + app.ico + + + + False + + + False + + + False + + + False + + + False + + + False + + + + + + + + + + + Form + + + InfoBox.cs + + + Form + + + MainForm.cs + + + + + Resources.resx + True + True + + + + Form + + + WaitForm1.cs + + + Form + + + AboutForm.cs + + + Form + + + CharsetForm.cs + + + AboutForm.cs + Designer + + + AboutForm.cs + Designer + + + CharsetForm.cs + + + CharsetForm.cs + Designer + + + InfoBox.cs + + + MainForm.cs + Designer + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + + ResXFileCodeGenerator + Resources.de.Designer.cs + Designer + + + True + Resources.de.resx + True + + + WaitForm1.cs + + + WaitForm1.cs + Designer + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + {DCCFFA08-472B-4D17-BB90-8F513FC01392} + ChanSort.Api + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ChanSort.Ui/CharsetForm.Designer.cs b/ChanSort.Ui/CharsetForm.Designer.cs new file mode 100644 index 0000000..0438fc1 --- /dev/null +++ b/ChanSort.Ui/CharsetForm.Designer.cs @@ -0,0 +1,171 @@ +namespace ChanSort.Ui +{ + partial class CharsetForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CharsetForm)); + this.gcCharset = new DevExpress.XtraGrid.GridControl(); + this.bindingSource1 = new System.Windows.Forms.BindingSource(this.components); + this.gvCharset = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.colCodePage = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colName = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colDisplayName = new DevExpress.XtraGrid.Columns.GridColumn(); + this.panelControl1 = new DevExpress.XtraEditors.PanelControl(); + this.btnMyCountry = new DevExpress.XtraEditors.SimpleButton(); + this.btnCancel = new DevExpress.XtraEditors.SimpleButton(); + this.btnOk = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.gcCharset)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.bindingSource1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gvCharset)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).BeginInit(); + this.panelControl1.SuspendLayout(); + this.SuspendLayout(); + // + // gcCharset + // + resources.ApplyResources(this.gcCharset, "gcCharset"); + this.gcCharset.DataSource = this.bindingSource1; + this.gcCharset.EmbeddedNavigator.AccessibleDescription = resources.GetString("gcCharset.EmbeddedNavigator.AccessibleDescription"); + this.gcCharset.EmbeddedNavigator.AccessibleName = resources.GetString("gcCharset.EmbeddedNavigator.AccessibleName"); + this.gcCharset.EmbeddedNavigator.AllowHtmlTextInToolTip = ((DevExpress.Utils.DefaultBoolean)(resources.GetObject("gcCharset.EmbeddedNavigator.AllowHtmlTextInToolTip"))); + this.gcCharset.EmbeddedNavigator.Anchor = ((System.Windows.Forms.AnchorStyles)(resources.GetObject("gcCharset.EmbeddedNavigator.Anchor"))); + this.gcCharset.EmbeddedNavigator.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("gcCharset.EmbeddedNavigator.BackgroundImage"))); + this.gcCharset.EmbeddedNavigator.BackgroundImageLayout = ((System.Windows.Forms.ImageLayout)(resources.GetObject("gcCharset.EmbeddedNavigator.BackgroundImageLayout"))); + this.gcCharset.EmbeddedNavigator.ImeMode = ((System.Windows.Forms.ImeMode)(resources.GetObject("gcCharset.EmbeddedNavigator.ImeMode"))); + this.gcCharset.EmbeddedNavigator.TextLocation = ((DevExpress.XtraEditors.NavigatorButtonsTextLocation)(resources.GetObject("gcCharset.EmbeddedNavigator.TextLocation"))); + this.gcCharset.EmbeddedNavigator.ToolTip = resources.GetString("gcCharset.EmbeddedNavigator.ToolTip"); + this.gcCharset.EmbeddedNavigator.ToolTipIconType = ((DevExpress.Utils.ToolTipIconType)(resources.GetObject("gcCharset.EmbeddedNavigator.ToolTipIconType"))); + this.gcCharset.EmbeddedNavigator.ToolTipTitle = resources.GetString("gcCharset.EmbeddedNavigator.ToolTipTitle"); + this.gcCharset.MainView = this.gvCharset; + this.gcCharset.Name = "gcCharset"; + this.gcCharset.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gvCharset}); + // + // bindingSource1 + // + this.bindingSource1.DataSource = typeof(System.Text.EncodingInfo); + // + // gvCharset + // + resources.ApplyResources(this.gvCharset, "gvCharset"); + this.gvCharset.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.colCodePage, + this.colName, + this.colDisplayName}); + this.gvCharset.GridControl = this.gcCharset; + this.gvCharset.Name = "gvCharset"; + this.gvCharset.OptionsBehavior.Editable = false; + this.gvCharset.OptionsView.ShowAutoFilterRow = true; + this.gvCharset.OptionsView.ShowGroupPanel = false; + this.gvCharset.OptionsView.ShowIndicator = false; + this.gvCharset.RowClick += new DevExpress.XtraGrid.Views.Grid.RowClickEventHandler(this.gvCharset_RowClick); + this.gvCharset.FocusedRowChanged += new DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventHandler(this.gvCharset_FocusedRowChanged); + // + // colCodePage + // + resources.ApplyResources(this.colCodePage, "colCodePage"); + this.colCodePage.FieldName = "CodePage"; + this.colCodePage.Name = "colCodePage"; + this.colCodePage.OptionsColumn.ReadOnly = true; + // + // colName + // + resources.ApplyResources(this.colName, "colName"); + this.colName.FieldName = "Name"; + this.colName.Name = "colName"; + this.colName.OptionsColumn.ReadOnly = true; + // + // colDisplayName + // + resources.ApplyResources(this.colDisplayName, "colDisplayName"); + this.colDisplayName.FieldName = "DisplayName"; + this.colDisplayName.Name = "colDisplayName"; + this.colDisplayName.OptionsColumn.ReadOnly = true; + this.colDisplayName.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem()}); + // + // panelControl1 + // + resources.ApplyResources(this.panelControl1, "panelControl1"); + this.panelControl1.Controls.Add(this.btnMyCountry); + this.panelControl1.Controls.Add(this.btnCancel); + this.panelControl1.Controls.Add(this.btnOk); + this.panelControl1.Name = "panelControl1"; + // + // btnMyCountry + // + resources.ApplyResources(this.btnMyCountry, "btnMyCountry"); + this.btnMyCountry.Name = "btnMyCountry"; + this.btnMyCountry.Click += new System.EventHandler(this.btnMyCountry_Click); + // + // btnCancel + // + resources.ApplyResources(this.btnCancel, "btnCancel"); + this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.btnCancel.Name = "btnCancel"; + // + // btnOk + // + resources.ApplyResources(this.btnOk, "btnOk"); + this.btnOk.DialogResult = System.Windows.Forms.DialogResult.OK; + this.btnOk.Name = "btnOk"; + // + // CharsetForm + // + this.AcceptButton = this.btnOk; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.btnCancel; + this.Controls.Add(this.gcCharset); + this.Controls.Add(this.panelControl1); + this.Name = "CharsetForm"; + this.Load += new System.EventHandler(this.CharsetForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.gcCharset)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.bindingSource1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gvCharset)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).EndInit(); + this.panelControl1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraGrid.GridControl gcCharset; + private DevExpress.XtraGrid.Views.Grid.GridView gvCharset; + private DevExpress.XtraEditors.PanelControl panelControl1; + private DevExpress.XtraEditors.SimpleButton btnMyCountry; + private DevExpress.XtraEditors.SimpleButton btnCancel; + private DevExpress.XtraEditors.SimpleButton btnOk; + private System.Windows.Forms.BindingSource bindingSource1; + private DevExpress.XtraGrid.Columns.GridColumn colCodePage; + private DevExpress.XtraGrid.Columns.GridColumn colName; + private DevExpress.XtraGrid.Columns.GridColumn colDisplayName; + } +} \ No newline at end of file diff --git a/ChanSort.Ui/CharsetForm.cs b/ChanSort.Ui/CharsetForm.cs new file mode 100644 index 0000000..1463445 --- /dev/null +++ b/ChanSort.Ui/CharsetForm.cs @@ -0,0 +1,100 @@ +using System; +using System.Text; +using DevExpress.XtraEditors; +using DevExpress.XtraGrid.Views.Base; + +namespace ChanSort.Ui +{ + public partial class CharsetForm : XtraForm + { + private readonly Encoding initialEncoding = Encoding.Default; + private Encoding currentEncoding; + + public EventHandler EncodingChanged; + + public CharsetForm(Encoding encoding) + { + this.initialEncoding = encoding; + InitializeComponent(); + } + + public Encoding Encoding + { + get { return this.currentEncoding; } + } + + private void SelectEncoding(Encoding encoding) + { + var encodings = Encoding.GetEncodings(); + for (int i = 0; i < encodings.Length; i++) + { + if (encodings[i].Name == encoding.WebName) + { + this.gvCharset.FocusedRowHandle = i; + this.gvCharset.MakeRowVisible(i); + } + } + } + + private void RaiseEncodingChanged() + { + if (this.EncodingChanged != null) + this.EncodingChanged(this, new EncodingChangedEventArgs(this.currentEncoding)); + } + + private void CharsetForm_Load(object sender, EventArgs e) + { + var encodings = Encoding.GetEncodings(); + this.gcCharset.DataSource = encodings; + } + + protected override void OnShown(EventArgs e) + { + base.OnShown(e); + this.SelectEncoding(this.initialEncoding); + } + + private void gvCharset_FocusedRowChanged(object sender, FocusedRowChangedEventArgs e) + { + var encodingInfo = (EncodingInfo) gvCharset.GetFocusedRow(); + if (encodingInfo == null) + return; + this.currentEncoding = Encoding.GetEncoding(encodingInfo.Name); + this.RaiseEncodingChanged(); + } + + private void gvCharset_RowClick(object sender, DevExpress.XtraGrid.Views.Grid.RowClickEventArgs e) + { + if (e.Clicks == 2 && this.gvCharset.IsDataRow(e.RowHandle)) + this.DialogResult = System.Windows.Forms.DialogResult.OK; + } + + private void btnMyCountry_Click(object sender, EventArgs e) + { + this.SelectEncoding(Encoding.Default); + } + + protected override void OnClosing(System.ComponentModel.CancelEventArgs e) + { + base.OnClosing(e); + if (this.DialogResult != System.Windows.Forms.DialogResult.OK) + { + // restore initial encoding + this.currentEncoding = this.initialEncoding; + this.RaiseEncodingChanged(); + } + } + } + + #region class EncodingChangedEventArgs + public class EncodingChangedEventArgs : EventArgs + { + public readonly Encoding Encoding; + + public EncodingChangedEventArgs(Encoding encoding) + { + this.Encoding = encoding; + } + } + #endregion +} \ No newline at end of file diff --git a/ChanSort.Ui/CharsetForm.de.resx b/ChanSort.Ui/CharsetForm.de.resx new file mode 100644 index 0000000..1890d23 --- /dev/null +++ b/ChanSort.Ui/CharsetForm.de.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Beschreibung + + + Standard-Zeichensatz meines Landes + + + Abbrechen + + + Zeichensatz + + \ No newline at end of file diff --git a/ChanSort.Ui/CharsetForm.resx b/ChanSort.Ui/CharsetForm.resx new file mode 100644 index 0000000..0782b3d --- /dev/null +++ b/ChanSort.Ui/CharsetForm.resx @@ -0,0 +1,367 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panelControl1 + + + 0 + + + + Inherit + + + + 272, 6 + + + colCodePage + + + btnCancel + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + 433, 446 + + + DevExpress.XtraGrid.Views.Grid.GridView, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + CharsetForm + + + + 0 + + + 1 + + + 1 + + + 5, 6 + + + + + + + + + + 6, 13 + + + Bottom + + + 0 + + + + Center + + + + None + + + gvCharset + + + Manual + + + Top, Right + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + Fill + + + 0, 0 + + + 2 + + + $this + + + DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colName + + + + + + 433, 37 + + + 0, 446 + + + Top, Right + + + colDisplayName + + + Cancel + + + panelControl1 + + + btnMyCountry + + + True + + + 0 + + + $this + + + panelControl1 + + + gcCharset + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + Default character set for my country + + + 67 + + + 222 + + + 353, 6 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + 75, 23 + + + bindingSource1 + + + 2 + + + 1 + + + 0 + + + 1 + + + Ok + + + + + + Tile + + + Character set + + + 232, 23 + + + True + + + System.Windows.Forms.BindingSource, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 2 + + + panelControl1 + + + Top, Left + + + 1 + + + 75, 23 + + + btnOk + + + + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + 433, 483 + + + 142 + + + DevExpress.XtraEditors.PanelControl, DevExpress.Utils.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + True + + + + Default + + + DevExpress.XtraEditors.XtraForm, DevExpress.Utils.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + True + + + 17, 17 + + \ No newline at end of file diff --git a/ChanSort.Ui/InfoBox.Designer.cs b/ChanSort.Ui/InfoBox.Designer.cs new file mode 100644 index 0000000..20d4a22 --- /dev/null +++ b/ChanSort.Ui/InfoBox.Designer.cs @@ -0,0 +1,91 @@ +namespace ChanSort.Ui +{ + partial class InfoBox + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.txtMessage = new DevExpress.XtraEditors.MemoEdit(); + this.panelControl1 = new DevExpress.XtraEditors.PanelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.txtMessage.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).BeginInit(); + this.panelControl1.SuspendLayout(); + this.SuspendLayout(); + // + // txtMessage + // + this.txtMessage.Dock = System.Windows.Forms.DockStyle.Fill; + this.txtMessage.Location = new System.Drawing.Point(0, 0); + this.txtMessage.Name = "txtMessage"; + this.txtMessage.Properties.Appearance.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.txtMessage.Properties.Appearance.Options.UseFont = true; + this.txtMessage.Size = new System.Drawing.Size(953, 486); + this.txtMessage.TabIndex = 0; + // + // panelControl1 + // + this.panelControl1.Controls.Add(this.simpleButton1); + this.panelControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.panelControl1.Location = new System.Drawing.Point(0, 486); + this.panelControl1.Name = "panelControl1"; + this.panelControl1.Size = new System.Drawing.Size(953, 45); + this.panelControl1.TabIndex = 1; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.simpleButton1.DialogResult = System.Windows.Forms.DialogResult.OK; + this.simpleButton1.Location = new System.Drawing.Point(866, 10); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(75, 23); + this.simpleButton1.TabIndex = 0; + this.simpleButton1.Text = "Ok"; + // + // InfoBox + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(953, 531); + this.Controls.Add(this.txtMessage); + this.Controls.Add(this.panelControl1); + this.Name = "InfoBox"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "InfoBox"; + ((System.ComponentModel.ISupportInitialize)(this.txtMessage.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).EndInit(); + this.panelControl1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.MemoEdit txtMessage; + private DevExpress.XtraEditors.PanelControl panelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + } +} \ No newline at end of file diff --git a/ChanSort.Ui/InfoBox.cs b/ChanSort.Ui/InfoBox.cs new file mode 100644 index 0000000..fdfb489 --- /dev/null +++ b/ChanSort.Ui/InfoBox.cs @@ -0,0 +1,35 @@ +using System.Windows.Forms; +using DevExpress.XtraEditors; + +namespace ChanSort.Ui +{ + public partial class InfoBox : XtraForm + { + public InfoBox() + { + InitializeComponent(); + this.ActiveControl = this.simpleButton1; + } + + public static void Show(IWin32Window owner, string message, string caption) + { + var box = new InfoBox(); + box.Text = caption; + box.txtMessage.Text = message; + box.txtMessage.Properties.ReadOnly = true; + box.txtMessage.SelectionStart = 0; + box.txtMessage.SelectionLength = 0; + box.ShowDialog(owner); + } + + protected override bool ProcessDialogKey(Keys keyData) + { + if (keyData == Keys.Escape) + { + this.DialogResult = DialogResult.Cancel; + return true; + } + return base.ProcessDialogKey(keyData); + } + } +} \ No newline at end of file diff --git a/ChanSort.Ui/InfoBox.resx b/ChanSort.Ui/InfoBox.resx new file mode 100644 index 0000000..7080a7d --- /dev/null +++ b/ChanSort.Ui/InfoBox.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ChanSort.Ui/MainForm.Designer.cs b/ChanSort.Ui/MainForm.Designer.cs new file mode 100644 index 0000000..537d8aa --- /dev/null +++ b/ChanSort.Ui/MainForm.Designer.cs @@ -0,0 +1,1481 @@ +namespace ChanSort.Ui +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.splitContainerControl1 = new DevExpress.XtraEditors.SplitContainerControl(); + this.grpOutputList = new DevExpress.XtraEditors.GroupControl(); + this.gridOutput = new DevExpress.XtraGrid.GridControl(); + this.dsChannels = new System.Windows.Forms.BindingSource(); + this.gviewOutput = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.colIndex1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colOutSlot = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colOutName = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colOutFav = new DevExpress.XtraGrid.Columns.GridColumn(); + this.repositoryItemCheckedComboBoxEdit1 = new DevExpress.XtraEditors.Repository.RepositoryItemCheckedComboBoxEdit(); + this.colUid1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.lblHotkeyLeft = new DevExpress.XtraEditors.LabelControl(); + this.pnlEditControls = new DevExpress.XtraEditors.PanelControl(); + this.comboEditMode = new DevExpress.XtraEditors.ComboBoxEdit(); + this.barManager1 = new DevExpress.XtraBars.BarManager(); + this.bar1 = new DevExpress.XtraBars.Bar(); + this.miFile = new DevExpress.XtraBars.BarSubItem(); + this.miOpen = new DevExpress.XtraBars.BarButtonItem(); + this.miReload = new DevExpress.XtraBars.BarButtonItem(); + this.miRestoreOriginal = new DevExpress.XtraBars.BarButtonItem(); + this.miFileInformation = new DevExpress.XtraBars.BarButtonItem(); + this.miSave = new DevExpress.XtraBars.BarButtonItem(); + this.miSaveAs = new DevExpress.XtraBars.BarButtonItem(); + this.miOpenReferenceFile = new DevExpress.XtraBars.BarButtonItem(); + this.miQuit = new DevExpress.XtraBars.BarButtonItem(); + this.miEdit = new DevExpress.XtraBars.BarSubItem(); + this.miAddChannel = new DevExpress.XtraBars.BarButtonItem(); + this.miRemove = new DevExpress.XtraBars.BarButtonItem(); + this.miReplace = new DevExpress.XtraBars.BarButtonItem(); + this.miSort = new DevExpress.XtraBars.BarButtonItem(); + this.miRenum = new DevExpress.XtraBars.BarButtonItem(); + this.mnuFavSet = new DevExpress.XtraBars.BarSubItem(); + this.miFavSet = new DevExpress.XtraBars.BarListItem(); + this.mnuFavUnset = new DevExpress.XtraBars.BarSubItem(); + this.miFavUnset = new DevExpress.XtraBars.BarListItem(); + this.miLockOn = new DevExpress.XtraBars.BarButtonItem(); + this.miLockOff = new DevExpress.XtraBars.BarButtonItem(); + this.miSkipOn = new DevExpress.XtraBars.BarButtonItem(); + this.miSkipOff = new DevExpress.XtraBars.BarButtonItem(); + this.miHideOn = new DevExpress.XtraBars.BarButtonItem(); + this.miHideOff = new DevExpress.XtraBars.BarButtonItem(); + this.barSubItem2 = new DevExpress.XtraBars.BarSubItem(); + this.miTvSettings = new DevExpress.XtraBars.BarButtonItem(); + this.mnuOptions = new DevExpress.XtraBars.BarSubItem(); + this.barSubItem1 = new DevExpress.XtraBars.BarSubItem(); + this.miEnglish = new DevExpress.XtraBars.BarButtonItem(); + this.miGerman = new DevExpress.XtraBars.BarButtonItem(); + this.mnuCharset = new DevExpress.XtraBars.BarSubItem(); + this.miCharsetForm = new DevExpress.XtraBars.BarButtonItem(); + this.miIsoCharSets = new DevExpress.XtraBars.BarListItem(); + this.mnuHelp = new DevExpress.XtraBars.BarSubItem(); + this.miAbout = new DevExpress.XtraBars.BarButtonItem(); + this.barDockControlTop = new DevExpress.XtraBars.BarDockControl(); + this.barDockControlBottom = new DevExpress.XtraBars.BarDockControl(); + this.barDockControlLeft = new DevExpress.XtraBars.BarDockControl(); + this.barDockControlRight = new DevExpress.XtraBars.BarDockControl(); + this.sharedImageCollection1 = new DevExpress.Utils.SharedImageCollection(); + this.miMoveUp = new DevExpress.XtraBars.BarButtonItem(); + this.miMoveDown = new DevExpress.XtraBars.BarButtonItem(); + this.btnSyncFromLeft = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.btnClearLeftFilter = new DevExpress.XtraEditors.SimpleButton(); + this.btnRenum = new DevExpress.XtraEditors.SimpleButton(); + this.btnSort = new DevExpress.XtraEditors.SimpleButton(); + this.btnDown = new DevExpress.XtraEditors.SimpleButton(); + this.btnUp = new DevExpress.XtraEditors.SimpleButton(); + this.btnRemove = new DevExpress.XtraEditors.SimpleButton(); + this.txtSetSlot = new DevExpress.XtraEditors.ButtonEdit(); + this.labelControl11 = new DevExpress.XtraEditors.LabelControl(); + this.grpInputList = new DevExpress.XtraEditors.GroupControl(); + this.gridInput = new DevExpress.XtraGrid.GridControl(); + this.gviewInput = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.colIndex = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colSlotOld = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colSlotNew = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colName = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colShortName = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colFavorites = new DevExpress.XtraGrid.Columns.GridColumn(); + this.repositoryItemCheckedComboBoxEdit2 = new DevExpress.XtraEditors.Repository.RepositoryItemCheckedComboBoxEdit(); + this.colLock = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colSkip = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colHidden = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colEncrypted = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colChannelOrTransponder = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colFreqInMhz = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colServiceId = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colVideoPid = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colAudioPid = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colServiceType = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colServiceTypeName = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colSatellite = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colNetworkId = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colTransportStreamId = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colSymbolRate = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colPolarity = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colUid = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colNetworkName = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colNetworkOperator = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colDebug = new DevExpress.XtraGrid.Columns.GridColumn(); + this.colLogicalIndex = new DevExpress.XtraGrid.Columns.GridColumn(); + this.lblHotkeyRight = new DevExpress.XtraEditors.LabelControl(); + this.panelControl3 = new DevExpress.XtraEditors.PanelControl(); + this.btnCloneChannelList = new DevExpress.XtraEditors.SimpleButton(); + this.btnClearRightFilter = new DevExpress.XtraEditors.SimpleButton(); + this.btnSyncFromRight = new DevExpress.XtraEditors.SimpleButton(); + this.btnAdd = new DevExpress.XtraEditors.SimpleButton(); + this.defaultLookAndFeel1 = new DevExpress.LookAndFeel.DefaultLookAndFeel(); + this.splashScreenManager1 = new DevExpress.XtraSplashScreen.SplashScreenManager(this, typeof(global::ChanSort.Ui.WaitForm1), true, true); + this.grpTopPanel = new DevExpress.XtraEditors.GroupControl(); + this.comboUnsortedAction = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.btnResetChannelData = new DevExpress.XtraEditors.SimpleButton(); + this.comboChannelList = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.mnuContext = new DevExpress.XtraBars.PopupMenu(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainerControl1)).BeginInit(); + this.splitContainerControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.grpOutputList)).BeginInit(); + this.grpOutputList.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridOutput)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.dsChannels)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gviewOutput)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemCheckedComboBoxEdit1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pnlEditControls)).BeginInit(); + this.pnlEditControls.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboEditMode.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.barManager1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.sharedImageCollection1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.txtSetSlot.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.grpInputList)).BeginInit(); + this.grpInputList.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridInput)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gviewInput)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemCheckedComboBoxEdit2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.panelControl3)).BeginInit(); + this.panelControl3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.grpTopPanel)).BeginInit(); + this.grpTopPanel.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboUnsortedAction.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboChannelList.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.mnuContext)).BeginInit(); + this.SuspendLayout(); + // + // splitContainerControl1 + // + resources.ApplyResources(this.splitContainerControl1, "splitContainerControl1"); + this.splitContainerControl1.Name = "splitContainerControl1"; + this.splitContainerControl1.Panel1.Controls.Add(this.grpOutputList); + resources.ApplyResources(this.splitContainerControl1.Panel1, "splitContainerControl1.Panel1"); + this.splitContainerControl1.Panel2.Controls.Add(this.grpInputList); + resources.ApplyResources(this.splitContainerControl1.Panel2, "splitContainerControl1.Panel2"); + this.splitContainerControl1.SplitterPosition = 336; + // + // grpOutputList + // + this.grpOutputList.Controls.Add(this.gridOutput); + this.grpOutputList.Controls.Add(this.lblHotkeyLeft); + this.grpOutputList.Controls.Add(this.pnlEditControls); + resources.ApplyResources(this.grpOutputList, "grpOutputList"); + this.grpOutputList.Name = "grpOutputList"; + // + // gridOutput + // + this.gridOutput.DataSource = this.dsChannels; + resources.ApplyResources(this.gridOutput, "gridOutput"); + this.gridOutput.MainView = this.gviewOutput; + this.gridOutput.Name = "gridOutput"; + this.gridOutput.RepositoryItems.AddRange(new DevExpress.XtraEditors.Repository.RepositoryItem[] { + this.repositoryItemCheckedComboBoxEdit1}); + this.gridOutput.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gviewOutput}); + this.gridOutput.ProcessGridKey += new System.Windows.Forms.KeyEventHandler(this.gridOutput_ProcessGridKey); + this.gridOutput.Enter += new System.EventHandler(this.gridOutput_Enter); + // + // dsChannels + // + this.dsChannels.DataSource = typeof(ChanSort.Api.ChannelInfo); + // + // gviewOutput + // + this.gviewOutput.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gviewOutput.Appearance.HeaderPanel.TextOptions.WordWrap = DevExpress.Utils.WordWrap.Wrap; + this.gviewOutput.ColumnPanelRowHeight = 35; + this.gviewOutput.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.colIndex1, + this.colOutSlot, + this.colOutName, + this.colOutFav, + this.colUid1}); + this.gviewOutput.GridControl = this.gridOutput; + this.gviewOutput.Name = "gviewOutput"; + this.gviewOutput.OptionsBehavior.EditorShowMode = DevExpress.Utils.EditorShowMode.Click; + this.gviewOutput.OptionsCustomization.AllowGroup = false; + this.gviewOutput.OptionsLayout.LayoutVersion = "2"; + this.gviewOutput.OptionsSelection.MultiSelect = true; + this.gviewOutput.OptionsView.ColumnAutoWidth = false; + this.gviewOutput.OptionsView.ShowAutoFilterRow = true; + this.gviewOutput.OptionsView.ShowFilterPanelMode = DevExpress.XtraGrid.Views.Base.ShowFilterPanelMode.Never; + this.gviewOutput.OptionsView.ShowGroupPanel = false; + this.gviewOutput.SortInfo.AddRange(new DevExpress.XtraGrid.Columns.GridColumnSortInfo[] { + new DevExpress.XtraGrid.Columns.GridColumnSortInfo(this.colOutSlot, DevExpress.Data.ColumnSortOrder.Ascending)}); + this.gviewOutput.RowClick += new DevExpress.XtraGrid.Views.Grid.RowClickEventHandler(this.gviewOutput_RowClick); + this.gviewOutput.RowCellStyle += new DevExpress.XtraGrid.Views.Grid.RowCellStyleEventHandler(this.gviewOutput_RowCellStyle); + this.gviewOutput.PopupMenuShowing += new DevExpress.XtraGrid.Views.Grid.PopupMenuShowingEventHandler(this.gviewOutput_PopupMenuShowing); + this.gviewOutput.SelectionChanged += new DevExpress.Data.SelectionChangedEventHandler(this.gviewOutput_SelectionChanged); + this.gviewOutput.FocusedRowChanged += new DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventHandler(this.gviewOutput_FocusedRowChanged); + this.gviewOutput.CellValueChanged += new DevExpress.XtraGrid.Views.Base.CellValueChangedEventHandler(this.gviewOutput_CellValueChanged); + this.gviewOutput.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gviewOutput_CustomColumnDisplayText); + this.gviewOutput.LayoutUpgrade += new DevExpress.Utils.LayoutUpgadeEventHandler(this.gviewOutput_LayoutUpgrade); + this.gviewOutput.MouseDown += new System.Windows.Forms.MouseEventHandler(this.gview_MouseDown); + this.gviewOutput.ValidatingEditor += new DevExpress.XtraEditors.Controls.BaseContainerValidateEditorEventHandler(this.gviewOutput_ValidatingEditor); + // + // colIndex1 + // + resources.ApplyResources(this.colIndex1, "colIndex1"); + this.colIndex1.FieldName = "RecordIndex"; + this.colIndex1.Name = "colIndex1"; + // + // colOutSlot + // + resources.ApplyResources(this.colOutSlot, "colOutSlot"); + this.colOutSlot.FieldName = "NewProgramNr"; + this.colOutSlot.Name = "colOutSlot"; + this.colOutSlot.OptionsFilter.AllowAutoFilter = false; + this.colOutSlot.OptionsFilter.AllowFilterModeChanging = DevExpress.Utils.DefaultBoolean.False; + // + // colOutName + // + resources.ApplyResources(this.colOutName, "colOutName"); + this.colOutName.FieldName = "Name"; + this.colOutName.Name = "colOutName"; + this.colOutName.OptionsFilter.AutoFilterCondition = DevExpress.XtraGrid.Columns.AutoFilterCondition.Contains; + // + // colOutFav + // + resources.ApplyResources(this.colOutFav, "colOutFav"); + this.colOutFav.ColumnEdit = this.repositoryItemCheckedComboBoxEdit1; + this.colOutFav.FieldName = "Favorites"; + this.colOutFav.Name = "colOutFav"; + this.colOutFav.OptionsFilter.AutoFilterCondition = DevExpress.XtraGrid.Columns.AutoFilterCondition.Contains; + // + // repositoryItemCheckedComboBoxEdit1 + // + resources.ApplyResources(this.repositoryItemCheckedComboBoxEdit1, "repositoryItemCheckedComboBoxEdit1"); + this.repositoryItemCheckedComboBoxEdit1.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(((DevExpress.XtraEditors.Controls.ButtonPredefines)(resources.GetObject("repositoryItemCheckedComboBoxEdit1.Buttons"))))}); + this.repositoryItemCheckedComboBoxEdit1.CloseUpKey = new DevExpress.Utils.KeyShortcut(System.Windows.Forms.Keys.F2); + this.repositoryItemCheckedComboBoxEdit1.ForceUpdateEditValue = DevExpress.Utils.DefaultBoolean.True; + this.repositoryItemCheckedComboBoxEdit1.Mask.EditMask = resources.GetString("repositoryItemCheckedComboBoxEdit1.Mask.EditMask"); + this.repositoryItemCheckedComboBoxEdit1.Mask.MaskType = ((DevExpress.XtraEditors.Mask.MaskType)(resources.GetObject("repositoryItemCheckedComboBoxEdit1.Mask.MaskType"))); + this.repositoryItemCheckedComboBoxEdit1.Name = "repositoryItemCheckedComboBoxEdit1"; + this.repositoryItemCheckedComboBoxEdit1.PopupSizeable = false; + this.repositoryItemCheckedComboBoxEdit1.SelectAllItemVisible = false; + this.repositoryItemCheckedComboBoxEdit1.ShowButtons = false; + this.repositoryItemCheckedComboBoxEdit1.ShowPopupCloseButton = false; + this.repositoryItemCheckedComboBoxEdit1.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.Standard; + // + // colUid1 + // + resources.ApplyResources(this.colUid1, "colUid1"); + this.colUid1.FieldName = "Uid"; + this.colUid1.Name = "colUid1"; + this.colUid1.OptionsColumn.AllowEdit = false; + // + // lblHotkeyLeft + // + resources.ApplyResources(this.lblHotkeyLeft, "lblHotkeyLeft"); + this.lblHotkeyLeft.Name = "lblHotkeyLeft"; + // + // pnlEditControls + // + this.pnlEditControls.Controls.Add(this.comboEditMode); + this.pnlEditControls.Controls.Add(this.btnSyncFromLeft); + this.pnlEditControls.Controls.Add(this.labelControl2); + this.pnlEditControls.Controls.Add(this.btnClearLeftFilter); + this.pnlEditControls.Controls.Add(this.btnRenum); + this.pnlEditControls.Controls.Add(this.btnSort); + this.pnlEditControls.Controls.Add(this.btnDown); + this.pnlEditControls.Controls.Add(this.btnUp); + this.pnlEditControls.Controls.Add(this.btnRemove); + this.pnlEditControls.Controls.Add(this.txtSetSlot); + this.pnlEditControls.Controls.Add(this.labelControl11); + resources.ApplyResources(this.pnlEditControls, "pnlEditControls"); + this.pnlEditControls.Name = "pnlEditControls"; + // + // comboEditMode + // + resources.ApplyResources(this.comboEditMode, "comboEditMode"); + this.comboEditMode.MenuManager = this.barManager1; + this.comboEditMode.Name = "comboEditMode"; + this.comboEditMode.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(((DevExpress.XtraEditors.Controls.ButtonPredefines)(resources.GetObject("comboEditMode.Properties.Buttons"))))}); + this.comboEditMode.Properties.Items.AddRange(new object[] { + resources.GetString("comboEditMode.Properties.Items"), + resources.GetString("comboEditMode.Properties.Items1"), + resources.GetString("comboEditMode.Properties.Items2")}); + this.comboEditMode.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboEditMode.SelectedIndexChanged += new System.EventHandler(this.comboEditMode_SelectedIndexChanged); + // + // barManager1 + // + this.barManager1.Bars.AddRange(new DevExpress.XtraBars.Bar[] { + this.bar1}); + this.barManager1.Categories.AddRange(new DevExpress.XtraBars.BarManagerCategory[] { + ((DevExpress.XtraBars.BarManagerCategory)(resources.GetObject("barManager1.Categories"))), + ((DevExpress.XtraBars.BarManagerCategory)(resources.GetObject("barManager1.Categories1"))), + ((DevExpress.XtraBars.BarManagerCategory)(resources.GetObject("barManager1.Categories2"))), + ((DevExpress.XtraBars.BarManagerCategory)(resources.GetObject("barManager1.Categories3")))}); + this.barManager1.DockControls.Add(this.barDockControlTop); + this.barManager1.DockControls.Add(this.barDockControlBottom); + this.barManager1.DockControls.Add(this.barDockControlLeft); + this.barManager1.DockControls.Add(this.barDockControlRight); + this.barManager1.Form = this; + this.barManager1.Images = this.sharedImageCollection1; + this.barManager1.Items.AddRange(new DevExpress.XtraBars.BarItem[] { + this.mnuOptions, + this.barSubItem1, + this.miEnglish, + this.miGerman, + this.miFile, + this.miOpen, + this.miOpenReferenceFile, + this.miReload, + this.miRestoreOriginal, + this.miFileInformation, + this.miSave, + this.miSaveAs, + this.miQuit, + this.mnuHelp, + this.miAbout, + this.mnuCharset, + this.miIsoCharSets, + this.miCharsetForm, + this.miEdit, + this.miMoveUp, + this.miMoveDown, + this.miAddChannel, + this.miRemove, + this.miReplace, + this.miSort, + this.miRenum, + this.mnuFavSet, + this.miFavSet, + this.mnuFavUnset, + this.miFavUnset, + this.miLockOn, + this.miLockOff, + this.miSkipOn, + this.miSkipOff, + this.miHideOn, + this.miHideOff, + this.barSubItem2, + this.miTvSettings}); + this.barManager1.MaxItemId = 49; + // + // bar1 + // + this.bar1.BarName = "Tools"; + this.bar1.DockCol = 0; + this.bar1.DockRow = 0; + this.bar1.DockStyle = DevExpress.XtraBars.BarDockStyle.Top; + this.bar1.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.miFile), + new DevExpress.XtraBars.LinkPersistInfo(this.miOpen), + new DevExpress.XtraBars.LinkPersistInfo(this.miOpenReferenceFile), + new DevExpress.XtraBars.LinkPersistInfo(this.miReload), + new DevExpress.XtraBars.LinkPersistInfo(this.miSave), + new DevExpress.XtraBars.LinkPersistInfo(this.miSaveAs), + new DevExpress.XtraBars.LinkPersistInfo(this.miEdit, true), + new DevExpress.XtraBars.LinkPersistInfo(this.mnuFavSet), + new DevExpress.XtraBars.LinkPersistInfo(this.miLockOn), + new DevExpress.XtraBars.LinkPersistInfo(this.miSkipOn), + new DevExpress.XtraBars.LinkPersistInfo(this.miHideOn), + new DevExpress.XtraBars.LinkPersistInfo(this.barSubItem2, true), + new DevExpress.XtraBars.LinkPersistInfo(this.miTvSettings), + new DevExpress.XtraBars.LinkPersistInfo(this.mnuOptions, true), + new DevExpress.XtraBars.LinkPersistInfo(this.barSubItem1), + new DevExpress.XtraBars.LinkPersistInfo(this.mnuHelp, true), + new DevExpress.XtraBars.LinkPersistInfo(this.miAbout)}); + resources.ApplyResources(this.bar1, "bar1"); + // + // miFile + // + resources.ApplyResources(this.miFile, "miFile"); + this.miFile.CategoryGuid = new System.Guid("e6c9a329-010b-4d79-8d4d-215e5f197ed3"); + this.miFile.Id = 4; + this.miFile.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.miOpen), + new DevExpress.XtraBars.LinkPersistInfo(this.miReload), + new DevExpress.XtraBars.LinkPersistInfo(this.miRestoreOriginal), + new DevExpress.XtraBars.LinkPersistInfo(this.miFileInformation), + new DevExpress.XtraBars.LinkPersistInfo(this.miSave), + new DevExpress.XtraBars.LinkPersistInfo(this.miSaveAs), + new DevExpress.XtraBars.LinkPersistInfo(this.miOpenReferenceFile, true), + new DevExpress.XtraBars.LinkPersistInfo(this.miQuit, true)}); + this.miFile.Name = "miFile"; + // + // miOpen + // + resources.ApplyResources(this.miOpen, "miOpen"); + this.miOpen.CategoryGuid = new System.Guid("e6c9a329-010b-4d79-8d4d-215e5f197ed3"); + this.miOpen.Id = 5; + this.miOpen.ImageIndex = 3; + this.miOpen.ItemShortcut = new DevExpress.XtraBars.BarShortcut((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O)); + this.miOpen.Name = "miOpen"; + this.miOpen.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miOpen_ItemClick); + // + // miReload + // + resources.ApplyResources(this.miReload, "miReload"); + this.miReload.CategoryGuid = new System.Guid("e6c9a329-010b-4d79-8d4d-215e5f197ed3"); + this.miReload.Enabled = false; + this.miReload.Id = 7; + this.miReload.ImageIndex = 5; + this.miReload.Name = "miReload"; + this.miReload.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miReload_ItemClick); + // + // miRestoreOriginal + // + resources.ApplyResources(this.miRestoreOriginal, "miRestoreOriginal"); + this.miRestoreOriginal.CategoryGuid = new System.Guid("e6c9a329-010b-4d79-8d4d-215e5f197ed3"); + this.miRestoreOriginal.Id = 42; + this.miRestoreOriginal.Name = "miRestoreOriginal"; + this.miRestoreOriginal.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miRestoreOriginal_ItemClick); + // + // miFileInformation + // + resources.ApplyResources(this.miFileInformation, "miFileInformation"); + this.miFileInformation.CategoryGuid = new System.Guid("e6c9a329-010b-4d79-8d4d-215e5f197ed3"); + this.miFileInformation.Id = 43; + this.miFileInformation.Name = "miFileInformation"; + this.miFileInformation.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miFileInformation_ItemClick); + // + // miSave + // + resources.ApplyResources(this.miSave, "miSave"); + this.miSave.CategoryGuid = new System.Guid("e6c9a329-010b-4d79-8d4d-215e5f197ed3"); + this.miSave.Enabled = false; + this.miSave.Id = 6; + this.miSave.ImageIndex = 4; + this.miSave.ItemShortcut = new DevExpress.XtraBars.BarShortcut((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S)); + this.miSave.Name = "miSave"; + this.miSave.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miSave_ItemClick); + // + // miSaveAs + // + resources.ApplyResources(this.miSaveAs, "miSaveAs"); + this.miSaveAs.CategoryGuid = new System.Guid("e6c9a329-010b-4d79-8d4d-215e5f197ed3"); + this.miSaveAs.Enabled = false; + this.miSaveAs.Id = 8; + this.miSaveAs.ImageIndex = 6; + this.miSaveAs.ItemShortcut = new DevExpress.XtraBars.BarShortcut(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.S)); + this.miSaveAs.Name = "miSaveAs"; + this.miSaveAs.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miSaveAs_ItemClick); + // + // miOpenReferenceFile + // + resources.ApplyResources(this.miOpenReferenceFile, "miOpenReferenceFile"); + this.miOpenReferenceFile.CategoryGuid = new System.Guid("e6c9a329-010b-4d79-8d4d-215e5f197ed3"); + this.miOpenReferenceFile.Id = 44; + this.miOpenReferenceFile.ImageIndex = 23; + this.miOpenReferenceFile.Name = "miOpenReferenceFile"; + this.miOpenReferenceFile.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miOpenReferenceFile_ItemClick); + // + // miQuit + // + resources.ApplyResources(this.miQuit, "miQuit"); + this.miQuit.CategoryGuid = new System.Guid("e6c9a329-010b-4d79-8d4d-215e5f197ed3"); + this.miQuit.Id = 9; + this.miQuit.ItemShortcut = new DevExpress.XtraBars.BarShortcut((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4)); + this.miQuit.Name = "miQuit"; + this.miQuit.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miQuit_ItemClick); + // + // miEdit + // + resources.ApplyResources(this.miEdit, "miEdit"); + this.miEdit.CategoryGuid = new System.Guid("d7eec464-59c9-4f45-88aa-602e64c81cc0"); + this.miEdit.Id = 22; + this.miEdit.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.miAddChannel), + new DevExpress.XtraBars.LinkPersistInfo(this.miRemove), + new DevExpress.XtraBars.LinkPersistInfo(this.miReplace), + new DevExpress.XtraBars.LinkPersistInfo(this.miSort), + new DevExpress.XtraBars.LinkPersistInfo(this.miRenum), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.PaintStyle, this.mnuFavSet, "", true, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.CaptionGlyph), + new DevExpress.XtraBars.LinkPersistInfo(this.mnuFavUnset), + new DevExpress.XtraBars.LinkPersistInfo(this.miLockOn, true), + new DevExpress.XtraBars.LinkPersistInfo(this.miLockOff), + new DevExpress.XtraBars.LinkPersistInfo(this.miSkipOn, true), + new DevExpress.XtraBars.LinkPersistInfo(this.miSkipOff), + new DevExpress.XtraBars.LinkPersistInfo(this.miHideOn, true), + new DevExpress.XtraBars.LinkPersistInfo(this.miHideOff)}); + this.miEdit.Name = "miEdit"; + // + // miAddChannel + // + resources.ApplyResources(this.miAddChannel, "miAddChannel"); + this.miAddChannel.CategoryGuid = new System.Guid("d7eec464-59c9-4f45-88aa-602e64c81cc0"); + this.miAddChannel.Id = 39; + this.miAddChannel.ImageIndex = 20; + this.miAddChannel.ItemShortcut = new DevExpress.XtraBars.BarShortcut((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Add)); + this.miAddChannel.Name = "miAddChannel"; + // + // miRemove + // + resources.ApplyResources(this.miRemove, "miRemove"); + this.miRemove.CategoryGuid = new System.Guid("d7eec464-59c9-4f45-88aa-602e64c81cc0"); + this.miRemove.Id = 25; + this.miRemove.ImageIndex = 11; + this.miRemove.ItemShortcut = new DevExpress.XtraBars.BarShortcut((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.X)); + this.miRemove.Name = "miRemove"; + this.miRemove.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miRemove_ItemClick); + // + // miReplace + // + resources.ApplyResources(this.miReplace, "miReplace"); + this.miReplace.CategoryGuid = new System.Guid("d7eec464-59c9-4f45-88aa-602e64c81cc0"); + this.miReplace.Id = 26; + this.miReplace.ImageIndex = 12; + this.miReplace.ItemShortcut = new DevExpress.XtraBars.BarShortcut((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.R)); + this.miReplace.Name = "miReplace"; + this.miReplace.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miReplace_ItemClick); + // + // miSort + // + resources.ApplyResources(this.miSort, "miSort"); + this.miSort.CategoryGuid = new System.Guid("d7eec464-59c9-4f45-88aa-602e64c81cc0"); + this.miSort.Id = 40; + this.miSort.ImageIndex = 21; + this.miSort.Name = "miSort"; + // + // miRenum + // + resources.ApplyResources(this.miRenum, "miRenum"); + this.miRenum.CategoryGuid = new System.Guid("d7eec464-59c9-4f45-88aa-602e64c81cc0"); + this.miRenum.Id = 41; + this.miRenum.ImageIndex = 22; + this.miRenum.Name = "miRenum"; + // + // mnuFavSet + // + resources.ApplyResources(this.mnuFavSet, "mnuFavSet"); + this.mnuFavSet.CategoryGuid = new System.Guid("d7eec464-59c9-4f45-88aa-602e64c81cc0"); + this.mnuFavSet.Id = 37; + this.mnuFavSet.ImageIndex = 13; + this.mnuFavSet.ItemShortcut = new DevExpress.XtraBars.BarShortcut(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.F)); + this.mnuFavSet.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.miFavSet)}); + this.mnuFavSet.Name = "mnuFavSet"; + this.mnuFavSet.PaintStyle = DevExpress.XtraBars.BarItemPaintStyle.CaptionInMenu; + // + // miFavSet + // + resources.ApplyResources(this.miFavSet, "miFavSet"); + this.miFavSet.CategoryGuid = new System.Guid("d7eec464-59c9-4f45-88aa-602e64c81cc0"); + this.miFavSet.Id = 20; + this.miFavSet.Name = "miFavSet"; + this.miFavSet.ShowNumbers = true; + this.miFavSet.Strings.AddRange(new object[] { + "A", + "B", + "C", + "D"}); + this.miFavSet.ListItemClick += new DevExpress.XtraBars.ListItemClickEventHandler(this.miFavSet_ListItemClick); + // + // mnuFavUnset + // + resources.ApplyResources(this.mnuFavUnset, "mnuFavUnset"); + this.mnuFavUnset.CategoryGuid = new System.Guid("d7eec464-59c9-4f45-88aa-602e64c81cc0"); + this.mnuFavUnset.Id = 38; + this.mnuFavUnset.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.miFavUnset)}); + this.mnuFavUnset.Name = "mnuFavUnset"; + // + // miFavUnset + // + resources.ApplyResources(this.miFavUnset, "miFavUnset"); + this.miFavUnset.CategoryGuid = new System.Guid("d7eec464-59c9-4f45-88aa-602e64c81cc0"); + this.miFavUnset.Id = 21; + this.miFavUnset.Name = "miFavUnset"; + this.miFavUnset.Strings.AddRange(new object[] { + "A", + "B", + "C", + "D"}); + this.miFavUnset.ListItemClick += new DevExpress.XtraBars.ListItemClickEventHandler(this.miFavUnset_ListItemClick); + // + // miLockOn + // + resources.ApplyResources(this.miLockOn, "miLockOn"); + this.miLockOn.CategoryGuid = new System.Guid("d7eec464-59c9-4f45-88aa-602e64c81cc0"); + this.miLockOn.Id = 27; + this.miLockOn.ImageIndex = 15; + this.miLockOn.ItemShortcut = new DevExpress.XtraBars.BarShortcut((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.L)); + this.miLockOn.Name = "miLockOn"; + this.miLockOn.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miLockOn_ItemClick); + // + // miLockOff + // + resources.ApplyResources(this.miLockOff, "miLockOff"); + this.miLockOff.CategoryGuid = new System.Guid("d7eec464-59c9-4f45-88aa-602e64c81cc0"); + this.miLockOff.Id = 28; + this.miLockOff.ItemShortcut = new DevExpress.XtraBars.BarShortcut(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.L)); + this.miLockOff.Name = "miLockOff"; + this.miLockOff.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miLockOff_ItemClick); + // + // miSkipOn + // + resources.ApplyResources(this.miSkipOn, "miSkipOn"); + this.miSkipOn.CategoryGuid = new System.Guid("d7eec464-59c9-4f45-88aa-602e64c81cc0"); + this.miSkipOn.Id = 29; + this.miSkipOn.ImageIndex = 16; + this.miSkipOn.ItemShortcut = new DevExpress.XtraBars.BarShortcut((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.K)); + this.miSkipOn.Name = "miSkipOn"; + this.miSkipOn.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miSkipOn_ItemClick); + // + // miSkipOff + // + resources.ApplyResources(this.miSkipOff, "miSkipOff"); + this.miSkipOff.CategoryGuid = new System.Guid("d7eec464-59c9-4f45-88aa-602e64c81cc0"); + this.miSkipOff.Id = 30; + this.miSkipOff.ItemShortcut = new DevExpress.XtraBars.BarShortcut(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.K)); + this.miSkipOff.Name = "miSkipOff"; + this.miSkipOff.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miSkipOff_ItemClick); + // + // miHideOn + // + resources.ApplyResources(this.miHideOn, "miHideOn"); + this.miHideOn.CategoryGuid = new System.Guid("d7eec464-59c9-4f45-88aa-602e64c81cc0"); + this.miHideOn.Id = 31; + this.miHideOn.ImageIndex = 17; + this.miHideOn.ItemShortcut = new DevExpress.XtraBars.BarShortcut((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.H)); + this.miHideOn.Name = "miHideOn"; + this.miHideOn.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miHideOn_ItemClick); + // + // miHideOff + // + resources.ApplyResources(this.miHideOff, "miHideOff"); + this.miHideOff.CategoryGuid = new System.Guid("d7eec464-59c9-4f45-88aa-602e64c81cc0"); + this.miHideOff.Id = 32; + this.miHideOff.ItemShortcut = new DevExpress.XtraBars.BarShortcut(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.H)); + this.miHideOff.Name = "miHideOff"; + this.miHideOff.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miHideOff_ItemClick); + // + // barSubItem2 + // + resources.ApplyResources(this.barSubItem2, "barSubItem2"); + this.barSubItem2.Id = 47; + this.barSubItem2.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.miTvSettings)}); + this.barSubItem2.Name = "barSubItem2"; + // + // miTvSettings + // + resources.ApplyResources(this.miTvSettings, "miTvSettings"); + this.miTvSettings.Id = 48; + this.miTvSettings.ImageIndex = 27; + this.miTvSettings.Name = "miTvSettings"; + this.miTvSettings.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miTvCountrySetup_ItemClick); + // + // mnuOptions + // + resources.ApplyResources(this.mnuOptions, "mnuOptions"); + this.mnuOptions.CategoryGuid = new System.Guid("870e935c-f3d9-4202-9c58-87966069155d"); + this.mnuOptions.Id = 34; + this.mnuOptions.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.PaintStyle, this.barSubItem1, DevExpress.XtraBars.BarItemPaintStyle.CaptionGlyph), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.PaintStyle, this.mnuCharset, DevExpress.XtraBars.BarItemPaintStyle.CaptionGlyph)}); + this.mnuOptions.Name = "mnuOptions"; + // + // barSubItem1 + // + resources.ApplyResources(this.barSubItem1, "barSubItem1"); + this.barSubItem1.CategoryGuid = new System.Guid("870e935c-f3d9-4202-9c58-87966069155d"); + this.barSubItem1.Id = 0; + this.barSubItem1.ImageIndex = 14; + this.barSubItem1.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.miEnglish), + new DevExpress.XtraBars.LinkPersistInfo(this.miGerman)}); + this.barSubItem1.Name = "barSubItem1"; + this.barSubItem1.PaintStyle = DevExpress.XtraBars.BarItemPaintStyle.CaptionInMenu; + // + // miEnglish + // + this.miEnglish.ButtonStyle = DevExpress.XtraBars.BarButtonStyle.Check; + resources.ApplyResources(this.miEnglish, "miEnglish"); + this.miEnglish.CategoryGuid = new System.Guid("870e935c-f3d9-4202-9c58-87966069155d"); + this.miEnglish.Id = 2; + this.miEnglish.ImageIndex = 0; + this.miEnglish.Name = "miEnglish"; + this.miEnglish.Tag = "en"; + this.miEnglish.DownChanged += new DevExpress.XtraBars.ItemClickEventHandler(this.miLanguage_DownChanged); + // + // miGerman + // + this.miGerman.ButtonStyle = DevExpress.XtraBars.BarButtonStyle.Check; + resources.ApplyResources(this.miGerman, "miGerman"); + this.miGerman.CategoryGuid = new System.Guid("870e935c-f3d9-4202-9c58-87966069155d"); + this.miGerman.Id = 1; + this.miGerman.ImageIndex = 1; + this.miGerman.Name = "miGerman"; + this.miGerman.Tag = "de-DE"; + this.miGerman.DownChanged += new DevExpress.XtraBars.ItemClickEventHandler(this.miLanguage_DownChanged); + // + // mnuCharset + // + resources.ApplyResources(this.mnuCharset, "mnuCharset"); + this.mnuCharset.CategoryGuid = new System.Guid("870e935c-f3d9-4202-9c58-87966069155d"); + this.mnuCharset.Id = 15; + this.mnuCharset.ImageIndex = 9; + this.mnuCharset.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.miCharsetForm), + new DevExpress.XtraBars.LinkPersistInfo(this.miIsoCharSets, true)}); + this.mnuCharset.Name = "mnuCharset"; + this.mnuCharset.PaintStyle = DevExpress.XtraBars.BarItemPaintStyle.CaptionInMenu; + // + // miCharsetForm + // + resources.ApplyResources(this.miCharsetForm, "miCharsetForm"); + this.miCharsetForm.CategoryGuid = new System.Guid("870e935c-f3d9-4202-9c58-87966069155d"); + this.miCharsetForm.Id = 13; + this.miCharsetForm.ImageIndex = 9; + this.miCharsetForm.Name = "miCharsetForm"; + this.miCharsetForm.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miCharset_ItemClick); + // + // miIsoCharSets + // + resources.ApplyResources(this.miIsoCharSets, "miIsoCharSets"); + this.miIsoCharSets.CategoryGuid = new System.Guid("870e935c-f3d9-4202-9c58-87966069155d"); + this.miIsoCharSets.Id = 14; + this.miIsoCharSets.Name = "miIsoCharSets"; + this.miIsoCharSets.ShowNumbers = true; + this.miIsoCharSets.ListItemClick += new DevExpress.XtraBars.ListItemClickEventHandler(this.miIsoCharSets_ListItemClick); + // + // mnuHelp + // + resources.ApplyResources(this.mnuHelp, "mnuHelp"); + this.mnuHelp.CategoryGuid = new System.Guid("0d554574-30e8-4d31-9a70-da702a984260"); + this.mnuHelp.Id = 10; + this.mnuHelp.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.miAbout)}); + this.mnuHelp.Name = "mnuHelp"; + // + // miAbout + // + resources.ApplyResources(this.miAbout, "miAbout"); + this.miAbout.CategoryGuid = new System.Guid("0d554574-30e8-4d31-9a70-da702a984260"); + this.miAbout.Id = 11; + this.miAbout.ImageIndex = 7; + this.miAbout.Name = "miAbout"; + this.miAbout.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miAbout_ItemClick); + // + // barDockControlTop + // + this.barDockControlTop.CausesValidation = false; + resources.ApplyResources(this.barDockControlTop, "barDockControlTop"); + // + // barDockControlBottom + // + this.barDockControlBottom.CausesValidation = false; + resources.ApplyResources(this.barDockControlBottom, "barDockControlBottom"); + // + // barDockControlLeft + // + this.barDockControlLeft.CausesValidation = false; + resources.ApplyResources(this.barDockControlLeft, "barDockControlLeft"); + // + // barDockControlRight + // + this.barDockControlRight.CausesValidation = false; + resources.ApplyResources(this.barDockControlRight, "barDockControlRight"); + // + // sharedImageCollection1 + // + // + // + // + this.sharedImageCollection1.ImageSource.ImageStream = ((DevExpress.Utils.ImageCollectionStreamer)(resources.GetObject("sharedImageCollection1.ImageSource.ImageStream"))); + this.sharedImageCollection1.ImageSource.Images.SetKeyName(24, "0088.png"); + this.sharedImageCollection1.ImageSource.Images.SetKeyName(25, "0089.png"); + this.sharedImageCollection1.ImageSource.Images.SetKeyName(26, "0119.png"); + this.sharedImageCollection1.ImageSource.Images.SetKeyName(27, "0025.png"); + this.sharedImageCollection1.ParentControl = this; + // + // miMoveUp + // + resources.ApplyResources(this.miMoveUp, "miMoveUp"); + this.miMoveUp.CategoryGuid = new System.Guid("d7eec464-59c9-4f45-88aa-602e64c81cc0"); + this.miMoveUp.Id = 45; + this.miMoveUp.ImageIndex = 24; + this.miMoveUp.Name = "miMoveUp"; + this.miMoveUp.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miMoveUp_ItemClick); + // + // miMoveDown + // + resources.ApplyResources(this.miMoveDown, "miMoveDown"); + this.miMoveDown.CategoryGuid = new System.Guid("d7eec464-59c9-4f45-88aa-602e64c81cc0"); + this.miMoveDown.Id = 46; + this.miMoveDown.ImageIndex = 25; + this.miMoveDown.Name = "miMoveDown"; + this.miMoveDown.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.miMoveDown_ItemClick); + // + // btnSyncFromLeft + // + resources.ApplyResources(this.btnSyncFromLeft, "btnSyncFromLeft"); + this.btnSyncFromLeft.Name = "btnSyncFromLeft"; + this.btnSyncFromLeft.Click += new System.EventHandler(this.btnSyncFromLeft_Click); + // + // labelControl2 + // + resources.ApplyResources(this.labelControl2, "labelControl2"); + this.labelControl2.Name = "labelControl2"; + // + // btnClearLeftFilter + // + this.btnClearLeftFilter.Appearance.Font = ((System.Drawing.Font)(resources.GetObject("btnClearLeftFilter.Appearance.Font"))); + this.btnClearLeftFilter.Appearance.Options.UseFont = true; + resources.ApplyResources(this.btnClearLeftFilter, "btnClearLeftFilter"); + this.btnClearLeftFilter.Name = "btnClearLeftFilter"; + this.btnClearLeftFilter.Click += new System.EventHandler(this.btnClearLeftFilter_Click); + // + // btnRenum + // + this.btnRenum.ImageIndex = 22; + this.btnRenum.ImageList = this.sharedImageCollection1; + resources.ApplyResources(this.btnRenum, "btnRenum"); + this.btnRenum.Name = "btnRenum"; + this.btnRenum.Click += new System.EventHandler(this.btnRenum_Click); + // + // btnSort + // + this.btnSort.ImageIndex = 21; + this.btnSort.ImageList = this.sharedImageCollection1; + resources.ApplyResources(this.btnSort, "btnSort"); + this.btnSort.Name = "btnSort"; + this.btnSort.Click += new System.EventHandler(this.btnSort_Click); + // + // btnDown + // + this.btnDown.ImageIndex = 25; + this.btnDown.ImageList = this.sharedImageCollection1; + resources.ApplyResources(this.btnDown, "btnDown"); + this.btnDown.Name = "btnDown"; + this.btnDown.Click += new System.EventHandler(this.btnDown_Click); + // + // btnUp + // + this.btnUp.ImageIndex = 24; + this.btnUp.ImageList = this.sharedImageCollection1; + resources.ApplyResources(this.btnUp, "btnUp"); + this.btnUp.Name = "btnUp"; + this.btnUp.Click += new System.EventHandler(this.btnUp_Click); + // + // btnRemove + // + this.btnRemove.ImageIndex = 11; + this.btnRemove.ImageList = this.sharedImageCollection1; + resources.ApplyResources(this.btnRemove, "btnRemove"); + this.btnRemove.Name = "btnRemove"; + this.btnRemove.Click += new System.EventHandler(this.btnRemove_Click); + // + // txtSetSlot + // + resources.ApplyResources(this.txtSetSlot, "txtSetSlot"); + this.txtSetSlot.Name = "txtSetSlot"; + this.txtSetSlot.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(((DevExpress.XtraEditors.Controls.ButtonPredefines)(resources.GetObject("txtSetSlot.Properties.Buttons"))))}); + this.txtSetSlot.Properties.Mask.EditMask = resources.GetString("txtSetSlot.Properties.Mask.EditMask"); + this.txtSetSlot.Properties.Mask.MaskType = ((DevExpress.XtraEditors.Mask.MaskType)(resources.GetObject("txtSetSlot.Properties.Mask.MaskType"))); + this.txtSetSlot.ButtonClick += new DevExpress.XtraEditors.Controls.ButtonPressedEventHandler(this.txtSetSlot_ButtonClick); + this.txtSetSlot.EditValueChanged += new System.EventHandler(this.txtSetSlot_EditValueChanged); + this.txtSetSlot.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txtSetSlot_KeyDown); + // + // labelControl11 + // + resources.ApplyResources(this.labelControl11, "labelControl11"); + this.labelControl11.Name = "labelControl11"; + // + // grpInputList + // + this.grpInputList.Controls.Add(this.gridInput); + this.grpInputList.Controls.Add(this.lblHotkeyRight); + this.grpInputList.Controls.Add(this.panelControl3); + resources.ApplyResources(this.grpInputList, "grpInputList"); + this.grpInputList.Name = "grpInputList"; + // + // gridInput + // + this.gridInput.DataSource = this.dsChannels; + resources.ApplyResources(this.gridInput, "gridInput"); + this.gridInput.MainView = this.gviewInput; + this.gridInput.Name = "gridInput"; + this.gridInput.RepositoryItems.AddRange(new DevExpress.XtraEditors.Repository.RepositoryItem[] { + this.repositoryItemCheckedComboBoxEdit2}); + this.gridInput.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gviewInput}); + this.gridInput.ProcessGridKey += new System.Windows.Forms.KeyEventHandler(this.gridInput_ProcessGridKey); + this.gridInput.Enter += new System.EventHandler(this.gridInput_Enter); + // + // gviewInput + // + this.gviewInput.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gviewInput.Appearance.HeaderPanel.TextOptions.WordWrap = DevExpress.Utils.WordWrap.Wrap; + this.gviewInput.ColumnPanelRowHeight = 35; + this.gviewInput.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.colIndex, + this.colSlotOld, + this.colSlotNew, + this.colName, + this.colShortName, + this.colFavorites, + this.colLock, + this.colSkip, + this.colHidden, + this.colEncrypted, + this.colChannelOrTransponder, + this.colFreqInMhz, + this.colServiceId, + this.colVideoPid, + this.colAudioPid, + this.colServiceType, + this.colServiceTypeName, + this.colSatellite, + this.colNetworkId, + this.colTransportStreamId, + this.colSymbolRate, + this.colPolarity, + this.colUid, + this.colNetworkName, + this.colNetworkOperator, + this.colDebug, + this.colLogicalIndex}); + this.gviewInput.GridControl = this.gridInput; + this.gviewInput.Name = "gviewInput"; + this.gviewInput.OptionsBehavior.EditorShowMode = DevExpress.Utils.EditorShowMode.Click; + this.gviewInput.OptionsCustomization.AllowGroup = false; + this.gviewInput.OptionsLayout.LayoutVersion = "3"; + this.gviewInput.OptionsSelection.MultiSelect = true; + this.gviewInput.OptionsView.ColumnAutoWidth = false; + this.gviewInput.OptionsView.ShowAutoFilterRow = true; + this.gviewInput.OptionsView.ShowFilterPanelMode = DevExpress.XtraGrid.Views.Base.ShowFilterPanelMode.Never; + this.gviewInput.OptionsView.ShowGroupPanel = false; + this.gviewInput.SortInfo.AddRange(new DevExpress.XtraGrid.Columns.GridColumnSortInfo[] { + new DevExpress.XtraGrid.Columns.GridColumnSortInfo(this.colSlotOld, DevExpress.Data.ColumnSortOrder.Ascending)}); + this.gviewInput.RowClick += new DevExpress.XtraGrid.Views.Grid.RowClickEventHandler(this.gviewInput_RowClick); + this.gviewInput.RowCellStyle += new DevExpress.XtraGrid.Views.Grid.RowCellStyleEventHandler(this.gviewInput_RowCellStyle); + this.gviewInput.PopupMenuShowing += new DevExpress.XtraGrid.Views.Grid.PopupMenuShowingEventHandler(this.gviewInput_PopupMenuShowing); + this.gviewInput.FocusedRowChanged += new DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventHandler(this.gviewInput_FocusedRowChanged); + this.gviewInput.CellValueChanged += new DevExpress.XtraGrid.Views.Base.CellValueChangedEventHandler(this.gviewInput_CellValueChanged); + this.gviewInput.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gviewInput_CustomColumnDisplayText); + this.gviewInput.LayoutUpgrade += new DevExpress.Utils.LayoutUpgadeEventHandler(this.gviewInput_LayoutUpgrade); + this.gviewInput.MouseDown += new System.Windows.Forms.MouseEventHandler(this.gview_MouseDown); + this.gviewInput.ValidatingEditor += new DevExpress.XtraEditors.Controls.BaseContainerValidateEditorEventHandler(this.gviewInput_ValidatingEditor); + // + // colIndex + // + resources.ApplyResources(this.colIndex, "colIndex"); + this.colIndex.FieldName = "RecordIndex"; + this.colIndex.Name = "colIndex"; + this.colIndex.OptionsColumn.AllowEdit = false; + // + // colSlotOld + // + resources.ApplyResources(this.colSlotOld, "colSlotOld"); + this.colSlotOld.FieldName = "OldProgramNr"; + this.colSlotOld.Name = "colSlotOld"; + this.colSlotOld.OptionsColumn.AllowEdit = false; + this.colSlotOld.OptionsFilter.AllowAutoFilter = false; + // + // colSlotNew + // + resources.ApplyResources(this.colSlotNew, "colSlotNew"); + this.colSlotNew.FieldName = "NewProgramNr"; + this.colSlotNew.Name = "colSlotNew"; + // + // colName + // + resources.ApplyResources(this.colName, "colName"); + this.colName.FieldName = "Name"; + this.colName.Name = "colName"; + this.colName.OptionsColumn.AllowEdit = false; + this.colName.OptionsFilter.AutoFilterCondition = DevExpress.XtraGrid.Columns.AutoFilterCondition.Contains; + // + // colShortName + // + resources.ApplyResources(this.colShortName, "colShortName"); + this.colShortName.FieldName = "ShortName"; + this.colShortName.Name = "colShortName"; + this.colShortName.OptionsColumn.AllowEdit = false; + // + // colFavorites + // + resources.ApplyResources(this.colFavorites, "colFavorites"); + this.colFavorites.ColumnEdit = this.repositoryItemCheckedComboBoxEdit2; + this.colFavorites.FieldName = "Favorites"; + this.colFavorites.Name = "colFavorites"; + // + // repositoryItemCheckedComboBoxEdit2 + // + resources.ApplyResources(this.repositoryItemCheckedComboBoxEdit2, "repositoryItemCheckedComboBoxEdit2"); + this.repositoryItemCheckedComboBoxEdit2.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(((DevExpress.XtraEditors.Controls.ButtonPredefines)(resources.GetObject("repositoryItemCheckedComboBoxEdit2.Buttons"))))}); + this.repositoryItemCheckedComboBoxEdit2.CloseUpKey = new DevExpress.Utils.KeyShortcut(System.Windows.Forms.Keys.F2); + this.repositoryItemCheckedComboBoxEdit2.ForceUpdateEditValue = DevExpress.Utils.DefaultBoolean.True; + this.repositoryItemCheckedComboBoxEdit2.Mask.EditMask = resources.GetString("repositoryItemCheckedComboBoxEdit2.Mask.EditMask"); + this.repositoryItemCheckedComboBoxEdit2.Mask.MaskType = ((DevExpress.XtraEditors.Mask.MaskType)(resources.GetObject("repositoryItemCheckedComboBoxEdit2.Mask.MaskType"))); + this.repositoryItemCheckedComboBoxEdit2.Name = "repositoryItemCheckedComboBoxEdit2"; + this.repositoryItemCheckedComboBoxEdit2.PopupSizeable = false; + this.repositoryItemCheckedComboBoxEdit2.SelectAllItemVisible = false; + this.repositoryItemCheckedComboBoxEdit2.ShowButtons = false; + this.repositoryItemCheckedComboBoxEdit2.ShowPopupCloseButton = false; + this.repositoryItemCheckedComboBoxEdit2.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.Standard; + // + // colLock + // + resources.ApplyResources(this.colLock, "colLock"); + this.colLock.FieldName = "Lock"; + this.colLock.Name = "colLock"; + // + // colSkip + // + resources.ApplyResources(this.colSkip, "colSkip"); + this.colSkip.FieldName = "Skip"; + this.colSkip.Name = "colSkip"; + // + // colHidden + // + resources.ApplyResources(this.colHidden, "colHidden"); + this.colHidden.FieldName = "Hidden"; + this.colHidden.Name = "colHidden"; + // + // colEncrypted + // + resources.ApplyResources(this.colEncrypted, "colEncrypted"); + this.colEncrypted.FieldName = "Encrypted"; + this.colEncrypted.Name = "colEncrypted"; + this.colEncrypted.OptionsColumn.AllowEdit = false; + this.colEncrypted.OptionsColumn.FixedWidth = true; + // + // colChannelOrTransponder + // + resources.ApplyResources(this.colChannelOrTransponder, "colChannelOrTransponder"); + this.colChannelOrTransponder.FieldName = "ChannelOrTransponder"; + this.colChannelOrTransponder.Name = "colChannelOrTransponder"; + this.colChannelOrTransponder.OptionsColumn.AllowEdit = false; + // + // colFreqInMhz + // + resources.ApplyResources(this.colFreqInMhz, "colFreqInMhz"); + this.colFreqInMhz.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.colFreqInMhz.FieldName = "FreqInMhz"; + this.colFreqInMhz.Name = "colFreqInMhz"; + this.colFreqInMhz.OptionsColumn.AllowEdit = false; + // + // colServiceId + // + resources.ApplyResources(this.colServiceId, "colServiceId"); + this.colServiceId.FieldName = "ServiceId"; + this.colServiceId.Name = "colServiceId"; + this.colServiceId.OptionsColumn.AllowEdit = false; + // + // colVideoPid + // + resources.ApplyResources(this.colVideoPid, "colVideoPid"); + this.colVideoPid.FieldName = "VideoPid"; + this.colVideoPid.Name = "colVideoPid"; + this.colVideoPid.OptionsColumn.AllowEdit = false; + // + // colAudioPid + // + resources.ApplyResources(this.colAudioPid, "colAudioPid"); + this.colAudioPid.FieldName = "AudioPid"; + this.colAudioPid.Name = "colAudioPid"; + this.colAudioPid.OptionsColumn.AllowEdit = false; + // + // colServiceType + // + resources.ApplyResources(this.colServiceType, "colServiceType"); + this.colServiceType.FieldName = "ServiceType"; + this.colServiceType.Name = "colServiceType"; + this.colServiceType.OptionsColumn.AllowEdit = false; + // + // colServiceTypeName + // + this.colServiceTypeName.FieldName = "ServiceTypeName"; + this.colServiceTypeName.Name = "colServiceTypeName"; + this.colServiceTypeName.OptionsColumn.AllowEdit = false; + resources.ApplyResources(this.colServiceTypeName, "colServiceTypeName"); + // + // colSatellite + // + resources.ApplyResources(this.colSatellite, "colSatellite"); + this.colSatellite.FieldName = "Satellite"; + this.colSatellite.Name = "colSatellite"; + this.colSatellite.OptionsColumn.AllowEdit = false; + // + // colNetworkId + // + resources.ApplyResources(this.colNetworkId, "colNetworkId"); + this.colNetworkId.FieldName = "OriginalNetworkId"; + this.colNetworkId.Name = "colNetworkId"; + this.colNetworkId.OptionsColumn.AllowEdit = false; + // + // colTransportStreamId + // + resources.ApplyResources(this.colTransportStreamId, "colTransportStreamId"); + this.colTransportStreamId.FieldName = "TransportStreamId"; + this.colTransportStreamId.Name = "colTransportStreamId"; + this.colTransportStreamId.OptionsColumn.AllowEdit = false; + // + // colSymbolRate + // + resources.ApplyResources(this.colSymbolRate, "colSymbolRate"); + this.colSymbolRate.FieldName = "SymbolRate"; + this.colSymbolRate.Name = "colSymbolRate"; + this.colSymbolRate.OptionsColumn.AllowEdit = false; + // + // colPolarity + // + resources.ApplyResources(this.colPolarity, "colPolarity"); + this.colPolarity.FieldName = "Polarity"; + this.colPolarity.Name = "colPolarity"; + this.colPolarity.OptionsColumn.AllowEdit = false; + // + // colUid + // + resources.ApplyResources(this.colUid, "colUid"); + this.colUid.FieldName = "Uid"; + this.colUid.Name = "colUid"; + this.colUid.OptionsColumn.AllowEdit = false; + // + // colNetworkName + // + resources.ApplyResources(this.colNetworkName, "colNetworkName"); + this.colNetworkName.FieldName = "NetworkName"; + this.colNetworkName.Name = "colNetworkName"; + this.colNetworkName.OptionsColumn.AllowEdit = false; + // + // colNetworkOperator + // + resources.ApplyResources(this.colNetworkOperator, "colNetworkOperator"); + this.colNetworkOperator.FieldName = "NetworkOperator"; + this.colNetworkOperator.Name = "colNetworkOperator"; + this.colNetworkOperator.OptionsColumn.AllowEdit = false; + // + // colDebug + // + this.colDebug.FieldName = "Debug"; + this.colDebug.Name = "colDebug"; + this.colDebug.OptionsColumn.AllowEdit = false; + // + // colLogicalIndex + // + resources.ApplyResources(this.colLogicalIndex, "colLogicalIndex"); + this.colLogicalIndex.FieldName = "RecordOrder"; + this.colLogicalIndex.Name = "colLogicalIndex"; + this.colLogicalIndex.OptionsColumn.AllowEdit = false; + this.colLogicalIndex.OptionsColumn.ReadOnly = true; + // + // lblHotkeyRight + // + resources.ApplyResources(this.lblHotkeyRight, "lblHotkeyRight"); + this.lblHotkeyRight.Name = "lblHotkeyRight"; + // + // panelControl3 + // + this.panelControl3.Controls.Add(this.btnCloneChannelList); + this.panelControl3.Controls.Add(this.btnClearRightFilter); + this.panelControl3.Controls.Add(this.btnSyncFromRight); + this.panelControl3.Controls.Add(this.btnAdd); + resources.ApplyResources(this.panelControl3, "panelControl3"); + this.panelControl3.Name = "panelControl3"; + // + // btnCloneChannelList + // + resources.ApplyResources(this.btnCloneChannelList, "btnCloneChannelList"); + this.btnCloneChannelList.Name = "btnCloneChannelList"; + this.btnCloneChannelList.Click += new System.EventHandler(this.btnCloneChannelList_Click); + // + // btnClearRightFilter + // + this.btnClearRightFilter.Appearance.Font = ((System.Drawing.Font)(resources.GetObject("btnClearRightFilter.Appearance.Font"))); + this.btnClearRightFilter.Appearance.Options.UseFont = true; + resources.ApplyResources(this.btnClearRightFilter, "btnClearRightFilter"); + this.btnClearRightFilter.Name = "btnClearRightFilter"; + this.btnClearRightFilter.Click += new System.EventHandler(this.btnClearRightFilter_Click); + // + // btnSyncFromRight + // + resources.ApplyResources(this.btnSyncFromRight, "btnSyncFromRight"); + this.btnSyncFromRight.Name = "btnSyncFromRight"; + this.btnSyncFromRight.Click += new System.EventHandler(this.btnSyncFromRight_Click); + // + // btnAdd + // + this.btnAdd.ImageIndex = 20; + this.btnAdd.ImageList = this.sharedImageCollection1; + resources.ApplyResources(this.btnAdd, "btnAdd"); + this.btnAdd.Name = "btnAdd"; + this.btnAdd.Click += new System.EventHandler(this.btnAdd_Click); + // + // defaultLookAndFeel1 + // + this.defaultLookAndFeel1.LookAndFeel.SkinName = "Office 2007 Blue"; + // + // grpTopPanel + // + this.grpTopPanel.Controls.Add(this.comboUnsortedAction); + this.grpTopPanel.Controls.Add(this.labelControl3); + this.grpTopPanel.Controls.Add(this.btnResetChannelData); + this.grpTopPanel.Controls.Add(this.comboChannelList); + this.grpTopPanel.Controls.Add(this.labelControl1); + resources.ApplyResources(this.grpTopPanel, "grpTopPanel"); + this.grpTopPanel.Name = "grpTopPanel"; + this.grpTopPanel.ShowCaption = false; + // + // comboUnsortedAction + // + resources.ApplyResources(this.comboUnsortedAction, "comboUnsortedAction"); + this.comboUnsortedAction.MenuManager = this.barManager1; + this.comboUnsortedAction.Name = "comboUnsortedAction"; + this.comboUnsortedAction.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(((DevExpress.XtraEditors.Controls.ButtonPredefines)(resources.GetObject("comboUnsortedAction.Properties.Buttons"))))}); + this.comboUnsortedAction.Properties.Items.AddRange(new object[] { + resources.GetString("comboUnsortedAction.Properties.Items"), + resources.GetString("comboUnsortedAction.Properties.Items1"), + resources.GetString("comboUnsortedAction.Properties.Items2")}); + this.comboUnsortedAction.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + // + // labelControl3 + // + this.labelControl3.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Far; + resources.ApplyResources(this.labelControl3, "labelControl3"); + this.labelControl3.Name = "labelControl3"; + // + // btnResetChannelData + // + resources.ApplyResources(this.btnResetChannelData, "btnResetChannelData"); + this.btnResetChannelData.Name = "btnResetChannelData"; + this.btnResetChannelData.Click += new System.EventHandler(this.btnResetChannelData_Click); + // + // comboChannelList + // + resources.ApplyResources(this.comboChannelList, "comboChannelList"); + this.comboChannelList.MenuManager = this.barManager1; + this.comboChannelList.Name = "comboChannelList"; + this.comboChannelList.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(((DevExpress.XtraEditors.Controls.ButtonPredefines)(resources.GetObject("comboChannelList.Properties.Buttons"))))}); + this.comboChannelList.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboChannelList.SelectedIndexChanged += new System.EventHandler(this.comboChannelList_SelectedIndexChanged); + // + // labelControl1 + // + resources.ApplyResources(this.labelControl1, "labelControl1"); + this.labelControl1.Name = "labelControl1"; + // + // mnuContext + // + this.mnuContext.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.miMoveUp), + new DevExpress.XtraBars.LinkPersistInfo(this.miMoveDown), + new DevExpress.XtraBars.LinkPersistInfo(this.miAddChannel), + new DevExpress.XtraBars.LinkPersistInfo(this.miRemove), + new DevExpress.XtraBars.LinkPersistInfo(this.miReplace), + new DevExpress.XtraBars.LinkPersistInfo(this.miSort), + new DevExpress.XtraBars.LinkPersistInfo(this.miRenum), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.PaintStyle, this.mnuFavSet, "", true, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.CaptionGlyph), + new DevExpress.XtraBars.LinkPersistInfo(this.mnuFavUnset), + new DevExpress.XtraBars.LinkPersistInfo(this.miLockOn, true), + new DevExpress.XtraBars.LinkPersistInfo(this.miLockOff), + new DevExpress.XtraBars.LinkPersistInfo(this.miSkipOn, true), + new DevExpress.XtraBars.LinkPersistInfo(this.miSkipOff), + new DevExpress.XtraBars.LinkPersistInfo(this.miHideOn, true), + new DevExpress.XtraBars.LinkPersistInfo(this.miHideOff)}); + this.mnuContext.Manager = this.barManager1; + this.mnuContext.Name = "mnuContext"; + // + // MainForm + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.splitContainerControl1); + this.Controls.Add(this.grpTopPanel); + this.Controls.Add(this.barDockControlLeft); + this.Controls.Add(this.barDockControlRight); + this.Controls.Add(this.barDockControlBottom); + this.Controls.Add(this.barDockControlTop); + this.Name = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + this.Shown += new System.EventHandler(this.MainForm_Shown); + ((System.ComponentModel.ISupportInitialize)(this.splitContainerControl1)).EndInit(); + this.splitContainerControl1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.grpOutputList)).EndInit(); + this.grpOutputList.ResumeLayout(false); + this.grpOutputList.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridOutput)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.dsChannels)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gviewOutput)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemCheckedComboBoxEdit1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pnlEditControls)).EndInit(); + this.pnlEditControls.ResumeLayout(false); + this.pnlEditControls.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboEditMode.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.barManager1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.sharedImageCollection1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.txtSetSlot.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.grpInputList)).EndInit(); + this.grpInputList.ResumeLayout(false); + this.grpInputList.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridInput)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gviewInput)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemCheckedComboBoxEdit2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.panelControl3)).EndInit(); + this.panelControl3.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.grpTopPanel)).EndInit(); + this.grpTopPanel.ResumeLayout(false); + this.grpTopPanel.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboUnsortedAction.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboChannelList.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.mnuContext)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.LookAndFeel.DefaultLookAndFeel defaultLookAndFeel1; + private DevExpress.XtraGrid.GridControl gridInput; + private DevExpress.XtraGrid.Views.Grid.GridView gviewInput; + private System.Windows.Forms.BindingSource dsChannels; + private DevExpress.XtraGrid.Columns.GridColumn colIndex; + private DevExpress.XtraGrid.Columns.GridColumn colSlotOld; + private DevExpress.XtraGrid.Columns.GridColumn colSlotNew; + private DevExpress.XtraGrid.Columns.GridColumn colUid; + private DevExpress.XtraGrid.Columns.GridColumn colName; + private DevExpress.XtraEditors.GroupControl grpOutputList; + private DevExpress.XtraEditors.SimpleButton btnRemove; + private DevExpress.XtraEditors.GroupControl grpInputList; + private DevExpress.XtraEditors.SimpleButton btnAdd; + private DevExpress.XtraGrid.GridControl gridOutput; + private DevExpress.XtraGrid.Views.Grid.GridView gviewOutput; + private DevExpress.XtraGrid.Columns.GridColumn colOutSlot; + private DevExpress.XtraGrid.Columns.GridColumn colOutName; + private DevExpress.XtraEditors.SimpleButton btnDown; + private DevExpress.XtraEditors.SimpleButton btnUp; + private DevExpress.XtraEditors.LabelControl lblHotkeyLeft; + private DevExpress.XtraEditors.LabelControl lblHotkeyRight; + private DevExpress.XtraEditors.ButtonEdit txtSetSlot; + private DevExpress.XtraEditors.LabelControl labelControl11; + private DevExpress.XtraGrid.Columns.GridColumn colEncrypted; + private DevExpress.XtraEditors.SimpleButton btnSort; + private DevExpress.XtraBars.BarManager barManager1; + private DevExpress.XtraBars.Bar bar1; + private DevExpress.XtraBars.BarSubItem barSubItem1; + private DevExpress.XtraBars.BarButtonItem miGerman; + private DevExpress.XtraBars.BarButtonItem miEnglish; + private DevExpress.XtraBars.BarDockControl barDockControlTop; + private DevExpress.XtraBars.BarDockControl barDockControlBottom; + private DevExpress.XtraBars.BarDockControl barDockControlLeft; + private DevExpress.XtraBars.BarDockControl barDockControlRight; + private DevExpress.Utils.SharedImageCollection sharedImageCollection1; + private DevExpress.XtraBars.BarSubItem miFile; + private DevExpress.XtraBars.BarButtonItem miOpen; + private DevExpress.XtraBars.BarButtonItem miSave; + private DevExpress.XtraBars.BarButtonItem miReload; + private DevExpress.XtraBars.BarButtonItem miSaveAs; + private DevExpress.XtraBars.BarButtonItem miQuit; + private DevExpress.XtraBars.BarSubItem mnuHelp; + private DevExpress.XtraBars.BarButtonItem miAbout; + private DevExpress.XtraBars.BarButtonItem miCharsetForm; + private DevExpress.XtraBars.BarListItem miIsoCharSets; + private DevExpress.XtraBars.BarSubItem mnuCharset; + private DevExpress.XtraEditors.SimpleButton btnSyncFromRight; + private DevExpress.XtraEditors.SimpleButton btnSyncFromLeft; + private DevExpress.XtraEditors.SimpleButton btnClearRightFilter; + private DevExpress.XtraEditors.SimpleButton btnClearLeftFilter; + private DevExpress.XtraGrid.Columns.GridColumn colAudioPid; + private DevExpress.XtraGrid.Columns.GridColumn colVideoPid; + private DevExpress.XtraGrid.Columns.GridColumn colNetworkId; + private DevExpress.XtraGrid.Columns.GridColumn colFreqInMhz; + private DevExpress.XtraGrid.Columns.GridColumn colServiceId; + private DevExpress.XtraGrid.Columns.GridColumn colServiceType; + private DevExpress.XtraGrid.Columns.GridColumn colShortName; + private DevExpress.XtraGrid.Columns.GridColumn colFavorites; + private DevExpress.XtraGrid.Columns.GridColumn colSkip; + private DevExpress.XtraGrid.Columns.GridColumn colLock; + private DevExpress.XtraGrid.Columns.GridColumn colSatellite; + private DevExpress.XtraGrid.Columns.GridColumn colHidden; + private DevExpress.XtraGrid.Columns.GridColumn colSymbolRate; + private DevExpress.XtraGrid.Columns.GridColumn colPolarity; + private DevExpress.XtraGrid.Columns.GridColumn colTransportStreamId; + private DevExpress.XtraEditors.SplitContainerControl splitContainerControl1; + private DevExpress.XtraEditors.PanelControl pnlEditControls; + private DevExpress.XtraEditors.GroupControl grpTopPanel; + private DevExpress.XtraEditors.ComboBoxEdit comboChannelList; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.PanelControl panelControl3; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraGrid.Columns.GridColumn colOutFav; + private DevExpress.XtraEditors.SimpleButton btnRenum; + private DevExpress.XtraGrid.Columns.GridColumn colIndex1; + private DevExpress.XtraGrid.Columns.GridColumn colUid1; + private DevExpress.XtraEditors.Repository.RepositoryItemCheckedComboBoxEdit repositoryItemCheckedComboBoxEdit1; + private DevExpress.XtraBars.PopupMenu mnuContext; + private DevExpress.XtraBars.BarSubItem miEdit; + private DevExpress.XtraBars.BarListItem miFavSet; + private DevExpress.XtraBars.BarListItem miFavUnset; + private DevExpress.XtraBars.BarButtonItem miRemove; + private DevExpress.XtraBars.BarButtonItem miReplace; + private DevExpress.XtraBars.BarButtonItem miLockOn; + private DevExpress.XtraBars.BarButtonItem miLockOff; + private DevExpress.XtraBars.BarButtonItem miSkipOn; + private DevExpress.XtraBars.BarButtonItem miSkipOff; + private DevExpress.XtraBars.BarButtonItem miHideOn; + private DevExpress.XtraBars.BarButtonItem miHideOff; + private DevExpress.XtraBars.BarSubItem mnuOptions; + private DevExpress.XtraBars.BarSubItem mnuFavSet; + private DevExpress.XtraBars.BarSubItem mnuFavUnset; + private DevExpress.XtraBars.BarButtonItem miAddChannel; + private DevExpress.XtraBars.BarButtonItem miSort; + private DevExpress.XtraBars.BarButtonItem miRenum; + private DevExpress.XtraEditors.Repository.RepositoryItemCheckedComboBoxEdit repositoryItemCheckedComboBoxEdit2; + private DevExpress.XtraGrid.Columns.GridColumn colChannelOrTransponder; + private DevExpress.XtraGrid.Columns.GridColumn colNetworkName; + private DevExpress.XtraGrid.Columns.GridColumn colNetworkOperator; + private DevExpress.XtraGrid.Columns.GridColumn colDebug; + private DevExpress.XtraGrid.Columns.GridColumn colServiceTypeName; + private DevExpress.XtraEditors.SimpleButton btnResetChannelData; + private DevExpress.XtraBars.BarButtonItem miRestoreOriginal; + private DevExpress.XtraEditors.ComboBoxEdit comboUnsortedAction; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraGrid.Columns.GridColumn colLogicalIndex; + private DevExpress.XtraBars.BarButtonItem miFileInformation; + private DevExpress.XtraBars.BarButtonItem miOpenReferenceFile; + private DevExpress.XtraEditors.SimpleButton btnCloneChannelList; + private DevExpress.XtraBars.BarButtonItem miMoveUp; + private DevExpress.XtraBars.BarButtonItem miMoveDown; + private DevExpress.XtraEditors.ComboBoxEdit comboEditMode; + private DevExpress.XtraBars.BarSubItem barSubItem2; + private DevExpress.XtraBars.BarButtonItem miTvSettings; + private DevExpress.XtraSplashScreen.SplashScreenManager splashScreenManager1; + } +} + diff --git a/ChanSort.Ui/MainForm.cs b/ChanSort.Ui/MainForm.cs new file mode 100644 index 0000000..286fdc3 --- /dev/null +++ b/ChanSort.Ui/MainForm.cs @@ -0,0 +1,1712 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Globalization; +using System.IO; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Windows.Forms; +using ChanSort.Api; +using ChanSort.Ui.Properties; +using DevExpress.Utils; +using DevExpress.XtraBars; +using DevExpress.XtraEditors; +using DevExpress.XtraEditors.Controls; +using DevExpress.XtraGrid; +using DevExpress.XtraGrid.Columns; +using DevExpress.XtraGrid.Views.Base; +using DevExpress.XtraGrid.Views.Grid; + +namespace ChanSort.Ui +{ + // http://www.lg-forum.com/lg-led-plasma-lcd-fernseher/5098-channeleditor-40.html + // http://www.lg-hack.info/cgi-bin/sn_forumr.cgi?fid=2677&cid=2674&tid=2690&pg=1&sc=20&x=0 + public partial class MainForm : XtraForm + { + #region enum EditMode + private enum EditMode + { + InsertBefore = 0, + InsertAfter = 1, + Swap = 2 + } + #endregion + + private readonly IList plugins; + private string currentTvFile; + private string currentCsvFile; + private ISerializerPlugin currentPlugin; + private SerializerBase currentTvSerializer; + private Editor editor; + private readonly CsvFileSerializer csvSerializer = new CsvFileSerializer(); + private DataRoot dataRoot; + private bool ignoreLanguageChange; + private readonly string title; + private Encoding defaultEncoding = Encoding.Default; + private readonly List isoEncodings = new List(); + private ChannelList currentChannelList; + private GridView lastFocusedGrid; + private EditMode curEditMode = EditMode.InsertAfter; + + #region ctor() + public MainForm() + { + if (!string.IsNullOrEmpty(Settings.Default.Language)) + Thread.CurrentThread.CurrentUICulture = new CultureInfo(Settings.Default.Language); + this.LookAndFeel.SetSkinStyle("Office 2010 Blue"); + InitializeComponent(); + this.SetControlsEnabled(false); + if (!Settings.Default.WindowSize.IsEmpty) + this.Size = Settings.Default.WindowSize; + this.title = this.Text; + this.plugins = this.LoadSerializerPlugins(); + this.FillMenuWithIsoEncodings(); + + this.Icon = new Icon(Assembly.GetExecutingAssembly().GetManifestResourceStream("ChanSort.Ui.app.ico")); + var bcLeft = new BindingContext(); + this.grpOutputList.BindingContext = bcLeft; + this.lastFocusedGrid = this.gviewInput; + this.comboEditMode.SelectedIndex = (int) this.curEditMode; + this.ActiveControl = this.gridInput; + } + #endregion + + #region SetControlsEnabled() + private void SetControlsEnabled(bool enabled) + { + foreach (Control control in this.grpTopPanel.Controls) + control.Enabled = enabled; + foreach (Control control in this.pnlEditControls.Controls) + { + if (control != this.btnClearLeftFilter && control != this.btnSyncFromLeft) + control.Enabled = enabled; + } + + this.miReload.Enabled = enabled; + this.miSave.Enabled = enabled; + this.miSaveAs.Enabled = enabled; + } + #endregion + + #region LoadSerializerPlugins() + private IList LoadSerializerPlugins() + { + var list = new List(); + string exeDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + foreach (var file in Directory.GetFiles(exeDir, "ChanSort.Plugin.*.dll")) + { + try + { + var assembly = Assembly.LoadFrom(file); + foreach(var type in assembly.GetTypes()) + { + if (typeof(ISerializerPlugin).IsAssignableFrom(type) && !type.IsAbstract) + list.Add((ISerializerPlugin) Activator.CreateInstance(type)); + } + } + catch(Exception ex) { HandleException(new IOException("Plugin " + file + "\n" + ex.Message, ex)); } + } + return list; + } + #endregion + + #region ShowOpenFileDialog() + private void ShowOpenFileDialog() + { + StringBuilder filter = new StringBuilder(); + StringBuilder extension = new StringBuilder(); + foreach (var plugin in this.plugins) + { + filter.Append(plugin.PluginName).Append("|").Append(plugin.FileFilter); + extension.Append(plugin.FileFilter); + filter.Append("|"); + extension.Append(";"); + } + if (extension.Length > 0) + extension.Remove(extension.Length - 1, 1); + + using (OpenFileDialog dlg = new OpenFileDialog()) + { + dlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer); + dlg.AddExtension = true; + dlg.Filter = filter + string.Format(Resources.MainForm_FileDialog_OpenFileFilter, extension); + dlg.FilterIndex = this.plugins.Count + 1; + dlg.CheckFileExists = true; + dlg.RestoreDirectory = true; + if (dlg.ShowDialog() == DialogResult.OK) + { + this.SetFileName(dlg.FileName); + var plugin = dlg.FilterIndex <= this.plugins.Count ? this.plugins[dlg.FilterIndex - 1] : null; + this.LoadFiles(plugin); + } + } + } + #endregion + + #region SetFileName() + private void SetFileName(string tvDataFile) + { + this.currentTvFile = tvDataFile; + if (!string.IsNullOrEmpty(tvDataFile)) + { + this.currentCsvFile = Path.Combine(Path.GetDirectoryName(this.currentTvFile), + Path.GetFileNameWithoutExtension(this.currentTvFile) + ".csv"); + } + this.Text = this.title + " - " + this.currentTvFile; + } + #endregion + + #region LoadFiles() + + private void LoadFiles(ISerializerPlugin plugin) + { + SerializerBase newSerializer = null; + bool dataUpdated = false; + try + { + if (plugin == null) + plugin = this.GetPluginForFile(this.currentTvFile); + // abort action if there is no currentTvSerializer for the input file + newSerializer = plugin == null ? null : plugin.CreateSerializer(this.currentTvFile); + if (newSerializer == null) + { + this.currentTvFile = this.currentTvSerializer == null ? string.Empty : this.currentTvSerializer.FileName; + return; + } + + if (!this.PromptSaveAndContinue()) + return; + + dataUpdated = true; + this.gviewInput.BeginDataUpdate(); + this.gviewOutput.BeginDataUpdate(); + + this.currentPlugin = plugin; + this.currentTvSerializer = newSerializer; + this.currentTvSerializer.DefaultEncoding = this.defaultEncoding; + this.btnResetChannelData.Visible = newSerializer.SupportsEraseChannelData; + if (!this.LoadTvDataFile()) + return; + this.LoadCsvFile(); + + this.editor = new Editor(); + this.editor.DataRoot = this.dataRoot; + + this.currentChannelList = null; + this.editor.ChannelList = null; + this.gridInput.DataSource = null; + this.gridOutput.DataSource = null; + this.comboChannelList.Properties.Items.Clear(); + foreach (var list in this.dataRoot.ChannelLists) + this.comboChannelList.Properties.Items.Add(list); + this.comboChannelList.SelectedIndex = this.dataRoot.IsEmpty ? -1 : 0; + + this.SetControlsEnabled(!this.dataRoot.IsEmpty); + this.UpdateFavoritesEditor(this.dataRoot.SupportedFavorites); + this.colName.OptionsColumn.AllowEdit = this.currentTvSerializer.SupportsChannelNameEdit; + this.colOutName.OptionsColumn.AllowEdit = this.currentTvSerializer.SupportsChannelNameEdit; + + if (this.dataRoot.Warnings.Length > 0) + { + var lines = this.dataRoot.Warnings.ToString().Split('\n'); + Array.Sort(lines); + var sortedWarnings = String.Join("\n", lines); + InfoBox.Show(this, + Resources.MainForm_LoadFiles_ValidationWarningMsg + "\r\n\r\n" + sortedWarnings, + Resources.MainForm_LoadFiles_ValidationWarningCap); + } + } + catch (Exception ex) + { + if (ex.GetType() != typeof(Exception) && !(ex is IOException)) + throw; + string name = newSerializer != null ? newSerializer.DisplayName : plugin.PluginName; + XtraMessageBox.Show(this, name + "\n\n" + ex.Message, Resources.MainForm_LoadFiles_IOException, + MessageBoxButtons.OK, MessageBoxIcon.Error); + this.currentPlugin = null; + this.currentTvFile = null; + this.currentTvSerializer = null; + this.Text = this.title; + } + finally + { + if (dataUpdated) + { + this.gviewInput.EndDataUpdate(); + this.gviewOutput.EndDataUpdate(); + } + } + } + #endregion + + #region UpdateFavoritesEditor() + private void UpdateFavoritesEditor(Favorites favorites) + { + this.repositoryItemCheckedComboBoxEdit1.Items.Clear(); + this.repositoryItemCheckedComboBoxEdit2.Items.Clear(); + byte mask = 0x01; + string regex = "["; + for (int bit=0; bit<8; bit++, mask<<=1) + { + if (((int) favorites & mask) != 0) + { + char c = (char) ('A' + bit); + this.repositoryItemCheckedComboBoxEdit1.Items.Add(c); + this.repositoryItemCheckedComboBoxEdit2.Items.Add(c); + regex += c; + } + } + regex += "]*"; + this.repositoryItemCheckedComboBoxEdit1.Mask.EditMask = regex; + this.repositoryItemCheckedComboBoxEdit2.Mask.EditMask = regex; + } + + #endregion + + #region GetTvFileSerializer() + private ISerializerPlugin GetPluginForFile(string inputFileName) + { + if (!File.Exists(inputFileName)) + { + XtraMessageBox.Show(this, String.Format(Resources.MainForm_LoadTll_SourceTllNotFound, inputFileName)); + return null; + } + string extension = (Path.GetExtension(inputFileName) ?? "").ToUpper(); + foreach (var plugin in this.plugins) + { + if ((plugin.FileFilter.ToUpper()+"|").Contains("*"+extension)) + return plugin; + } + + XtraMessageBox.Show(this, String.Format(Resources.MainForm_LoadTll_SerializerNotFound, inputFileName)); + return null; + } + #endregion + + #region LoadTvDataFile() + private bool LoadTvDataFile() + { + this.currentTvSerializer.Load(); + this.dataRoot = this.currentTvSerializer.DataRoot; + return true; + } + #endregion + + #region PromptSaveAndContinue() + private bool PromptSaveAndContinue() + { + if (this.dataRoot == null || !this.dataRoot.NeedsSaving) + return true; + + switch (XtraMessageBox.Show(this, + Resources.MainForm_PromptSaveAndContinue_Message, + Resources.MainForm_PromptSaveAndContinue_Caption, + MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, + MessageBoxDefaultButton.Button3)) + { + case DialogResult.Yes: this.SaveFiles(); break; + case DialogResult.No: break; + case DialogResult.Cancel: return false; + } + return true; + } + #endregion + + #region LoadCsvFile() + private void LoadCsvFile() + { + if (File.Exists(this.currentCsvFile)) + this.csvSerializer.Load(this.currentCsvFile, this.dataRoot); + else + { + foreach (var list in this.dataRoot.ChannelLists) + { + foreach (var channel in list.Channels) + channel.NewProgramNr = channel.OldProgramNr; + } + } + } + #endregion + + #region ShowOpenReferenceFileDialog() + private void ShowOpenReferenceFileDialog() + { + using (OpenFileDialog dlg = new OpenFileDialog()) + { + dlg.Title = Resources.MainForm_ShowOpenReferenceFileDialog_Title; + dlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer); + dlg.AddExtension = true; + dlg.Filter = Resources.MainForm_ShowOpenReferenceFileDialog_Filter; + dlg.FilterIndex = 3; + dlg.CheckFileExists = true; + dlg.RestoreDirectory = true; + if (dlg.ShowDialog(this) == DialogResult.OK) + { + this.gviewInput.BeginDataUpdate(); + this.gviewOutput.BeginDataUpdate(); + + string ext = (Path.GetExtension(dlg.FileName) ?? "").ToLower(); + if (ext == ".csv") + this.csvSerializer.Load(dlg.FileName, this.dataRoot); + else if (ext == ".chl") + { + ChlFileSerializer loader = new ChlFileSerializer(); + string warnings = loader.Load(dlg.FileName, this.dataRoot, this.currentChannelList); + InfoBox.Show(this, warnings, Path.GetFileName(dlg.FileName)); + } + + this.gviewInput.EndDataUpdate(); + this.gviewOutput.EndDataUpdate(); + } + } + } + #endregion + + + #region ShowChannelList() + private void ShowChannelList(ChannelList channelList) + { + if (this.currentChannelList != null) + this.SaveInputGridLayout(this.currentChannelList.SignalSource); + if (channelList != null) + { + this.LoadInputGridLayout(channelList.SignalSource); + this.gridInput.DataSource = channelList.Channels; + this.gridOutput.DataSource = channelList.Channels; + } + else + { + this.gridInput.DataSource = null; + this.gridOutput.DataSource = null; + } + this.currentChannelList = channelList; + this.editor.ChannelList = channelList; + + if (gviewInput.IsValidRowHandle(0)) + { + this.gviewInput.FocusedRowHandle = 0; + this.gviewInput.SelectRow(0); + } + if (gviewOutput.IsValidRowHandle(0)) + { + this.gviewOutput.FocusedRowHandle = 0; + this.gviewOutput.SelectRow(0); + } + this.UpdateInsertSlotTextBox(); + } + #endregion + + #region ShowSaveFileDialog() + + private void ShowSaveFileDialog() + { + string extension = Path.GetExtension(this.currentTvSerializer.FileName) ?? "."; + using (SaveFileDialog dlg = new SaveFileDialog()) + { + dlg.FileName = this.currentTvFile; + dlg.AddExtension = true; + dlg.DefaultExt = extension; + dlg.Filter = string.Format(Resources.MainForm_FileDialog_SaveFileFilter, extension); + dlg.FilterIndex = 0; + dlg.ValidateNames = true; + dlg.RestoreDirectory = true; + dlg.OverwritePrompt = true; + if (dlg.ShowDialog() == DialogResult.OK) + { + this.SetFileName(dlg.FileName); + this.SaveFiles(); + } + } + } + + #endregion + + #region SaveFiles() + + private void SaveFiles() + { + this.gviewInput.PostEditor(); + this.gviewOutput.PostEditor(); + try + { + this.gviewInput.BeginDataUpdate(); + this.gviewOutput.BeginDataUpdate(); + this.SaveReferenceFile(); + this.SaveTvDataFile(); + this.dataRoot.NeedsSaving = false; + } + catch (IOException ex) + { + XtraMessageBox.Show(this, + Resources.MainForm_SaveFiles_ErrorMsg + + ex.Message, + Resources.MainForm_SaveFiles_ErrorTitle, + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + finally + { + this.gviewInput.EndDataUpdate(); + this.gviewOutput.EndDataUpdate(); + } + } + + #endregion + + #region SaveReferenceFile() + + private void SaveReferenceFile() + { + this.csvSerializer.Save(this.currentCsvFile, this.dataRoot, UnsortedChannelMode.Hide); + } + + #endregion + + #region SaveTvDataFile() + + private void SaveTvDataFile() + { + this.splashScreenManager1.ShowWaitForm(); + try + { + // create backup file if none exists + if (File.Exists(currentTvFile)) + { + string bakFile = currentTvFile + ".bak"; + if (!File.Exists(bakFile)) + File.Copy(currentTvFile, bakFile); + } + this.currentTvSerializer.Save(this.currentTvFile, this.currentCsvFile, (UnsortedChannelMode)this.comboUnsortedAction.SelectedIndex); + } + finally + { + this.splashScreenManager1.CloseWaitForm(); + } + } + #endregion + + #region AddChannels() + private void AddChannels() + { + var selectedChannels = this.GetSelectedChannels(gviewInput); + if (selectedChannels.Count == 0) return; + + ChannelInfo lastInsertedChannel; + this.gviewOutput.BeginDataUpdate(); + this.gviewInput.BeginDataUpdate(); + try + { + lastInsertedChannel = this.editor.AddChannels(selectedChannels); + this.UpdateInsertSlotTextBox(); + } + finally + { + this.gviewInput.EndDataUpdate(); + this.gviewOutput.EndDataUpdate(); + } + + if (lastInsertedChannel == null) + { + this.NavigateToChannel(selectedChannels[0], this.gviewOutput); + return; + } + + this.gviewOutput.BeginSelection(); + try + { + this.gviewOutput.ClearSelection(); + int index = this.currentChannelList.Channels.IndexOf(lastInsertedChannel); + int rowHandle = this.gviewOutput.GetRowHandle(index); + if (this.comboEditMode.SelectedIndex == (int)EditMode.InsertBefore) + ++rowHandle; + this.gviewOutput.FocusedRowHandle = rowHandle; + this.gviewOutput.SelectRow(rowHandle); + } + finally + { + this.gviewOutput.EndSelection(); + } + } + #endregion + + #region RemoveChannels() + + private void RemoveChannels() + { + var selectedChannels = this.GetSelectedChannels(this.lastFocusedGrid); + if (selectedChannels.Count == 0) return; + + int focusedRow = Math.Max(0, this.gviewOutput.FocusedRowHandle - selectedChannels.Count); + if (!gviewOutput.IsLastRow) + ++focusedRow; + this.gviewInput.BeginDataUpdate(); + this.gviewOutput.BeginDataUpdate(); + try + { + this.editor.RemoveChannels(selectedChannels); + } + finally + { + this.gviewOutput.EndDataUpdate(); + this.gviewInput.EndDataUpdate(); + } + this.gviewOutput.FocusedRowHandle = focusedRow; + this.gviewOutput.SelectRow(focusedRow); + this.UpdateInsertSlotTextBox(); + } + + #endregion + + #region MoveChannels() + + private void MoveChannels(bool up) + { + var selectedChannels = this.GetSelectedChannels(this.gviewOutput); + if (selectedChannels.Count == 0) return; + + this.gviewOutput.BeginDataUpdate(); + try + { + this.editor.MoveChannels(selectedChannels, up); + } + finally + { + this.gviewOutput.EndDataUpdate(); + } + this.UpdateInsertSlotTextBox(); + } + + #endregion + + #region SetSlotNumber() + private bool SetSlotNumber(string slotNr) + { + int slot; + if (!int.TryParse(slotNr, out slot) || slot < 0) + return false; + var selectedChannels = this.GetSelectedChannels(this.lastFocusedGrid); + if (selectedChannels.Count == 0) return true; + this.gviewOutput.BeginDataUpdate(); + this.gviewInput.BeginDataUpdate(); + try + { + this.editor.SetSlotNumber(selectedChannels, slot, this.comboEditMode.SelectedIndex == (int)EditMode.Swap); + } + finally + { + this.gviewInput.EndDataUpdate(); + this.gviewOutput.EndDataUpdate(); + } + return true; + } + #endregion + + #region SortSelectedChannels() + private void SortSelectedChannels() + { + var selectedChannels = this.GetSelectedChannels(this.gviewOutput); + if (selectedChannels.Count == 0) return; + this.gviewOutput.BeginDataUpdate(); + this.gviewInput.BeginDataUpdate(); + try + { + this.editor.SortSelectedChannels(selectedChannels); + } + finally + { + this.gviewInput.EndDataUpdate(); + this.gviewOutput.EndDataUpdate(); + } + } + #endregion + + #region CloneChannelList() + private void CloneChannelList() + { + if (this.currentChannelList == null) return; + this.gviewInput.BeginDataUpdate(); + this.gviewOutput.BeginDataUpdate(); + foreach (var channel in this.currentChannelList.Channels) + channel.NewProgramNr = channel.OldProgramNr; + this.gviewInput.EndDataUpdate(); + this.gviewOutput.EndDataUpdate(); + } + #endregion + + #region RenumberSelectedChannels() + private void RenumberSelectedChannels() + { + var list = this.GetSelectedChannels(this.gviewOutput); + if (list.Count == 0) return; + this.gviewInput.BeginDataUpdate(); + this.gviewOutput.BeginDataUpdate(); + this.editor.RenumberChannels(list); + this.gviewOutput.EndDataUpdate(); + this.gviewInput.EndDataUpdate(); + } + #endregion + + #region SwapChannels() + private void SwapChannels() + { + int oldMode = this.comboEditMode.SelectedIndex; + this.comboEditMode.SelectedIndex = (int)EditMode.Swap; + this.RemoveChannels(); + this.AddChannels(); + this.comboEditMode.SelectedIndex = oldMode; + } + #endregion + + #region GetSelectedChannels() + private List GetSelectedChannels(GridView gview) + { + var channels = new List(); + if (gview.IsDataRow(gview.FocusedRowHandle)) + gview.SelectRow(gview.FocusedRowHandle); + foreach (int rowHandle in gview.GetSelectedRows()) + { + if (gview.IsDataRow(rowHandle)) + channels.Add((ChannelInfo)gview.GetRow(rowHandle)); + } + return channels; + } + #endregion + + #region TryExecute() + + private void TryExecute(Action action) + { + try { action(); } + catch (Exception ex) { HandleException(ex); } + } + + #endregion + + #region HandleException() + public static void HandleException(Exception ex) + { + XtraMessageBox.Show(string.Format(Resources.MainForm_TryExecute_Exception, ex)); + } + #endregion + + #region LoadSettings() + private void LoadSettings() + { + // note: WindowSize must be restored in ctor in order to make WindowStartPosition.CenterScreen work + if (!string.IsNullOrEmpty(Settings.Default.Encoding)) + this.defaultEncoding = Encoding.GetEncoding(Settings.Default.Encoding); + this.SetFileName(Settings.Default.InputTLL); + int width = Settings.Default.LeftPanelWidth; + if (width > 0) + this.splitContainerControl1.SplitterPosition = width; + this.SelectLanguageMenuItem(); + + this.SetGridLayout(this.gviewOutput, Settings.Default.OutputListLayout); + this.gviewOutput.ClearSelection(); + if (this.gviewOutput.IsValidRowHandle(this.gviewOutput.FocusedRowHandle)) + this.gviewOutput.SelectRow(Settings.Default.OutputListRowHandle); + + this.ClearLeftFilter(); + } + #endregion + + #region SelectLanguageMenuItem() + private void SelectLanguageMenuItem() + { + this.barManager1.ForceLinkCreate(); + foreach (BarItemLink itemLink in this.barSubItem1.ItemLinks) + { + if (Settings.Default.Language.StartsWith((string) itemLink.Item.Tag)) + { + this.ignoreLanguageChange = true; + ((BarButtonItem) itemLink.Item).Down = true; + this.ignoreLanguageChange = false; + break; + } + } + } + #endregion + + #region SetGridLayout() + private void SetGridLayout(GridView grid, string layout) + { + if (string.IsNullOrEmpty(layout)) return; + MemoryStream stream = new MemoryStream(); + using (StreamWriter wrt = new StreamWriter(stream)) + { + wrt.Write(layout); + wrt.Flush(); + stream.Seek(0, SeekOrigin.Begin); + grid.RestoreLayoutFromStream(stream); + } + + // put the filter text back into the auto-filter-row + foreach (GridColumn col in grid.Columns) + { + string[] parts = (col.FilterInfo.FilterString ?? "").Split('\''); + if (parts.Length >= 2) + this.gviewInput.SetRowCellValue(GridControl.AutoFilterRowHandle, col, parts[1]); + } + } + #endregion + + #region SaveSettings(), GetGridLayout() + private void SaveSettings() + { + this.gviewInput.PostEditor(); + this.gviewOutput.PostEditor(); + + Settings.Default.WindowSize = this.WindowState == FormWindowState.Normal ? this.Size : this.RestoreBounds.Size; + Settings.Default.Encoding = this.defaultEncoding.WebName; + Settings.Default.Language = Thread.CurrentThread.CurrentUICulture.Name; + Settings.Default.InputTLL = this.currentTvFile; + Settings.Default.LeftPanelWidth = this.splitContainerControl1.SplitterPosition; + Settings.Default.OutputListLayout = GetGridLayout(this.gviewOutput); + if (this.currentChannelList != null) + SaveInputGridLayout(this.currentChannelList.SignalSource); + Settings.Default.Save(); + } + + private string GetGridLayout(GridView grid) + { + MemoryStream stream = new MemoryStream(); + grid.SaveLayoutToStream(stream, OptionsLayoutBase.FullLayout); + stream.Seek(0, SeekOrigin.Begin); + using (StreamReader rdr = new StreamReader(stream, Encoding.UTF8)) + return rdr.ReadToEnd(); + } + + #endregion + + #region UpdateInsertSlotTextBox() + private void UpdateInsertSlotTextBox() + { + int programNr = this.currentChannelList == null ? 0 : this.currentChannelList.InsertProgramNumber; + this.txtSetSlot.Text = programNr.ToString(); + } + #endregion + + #region FillMenuWithIsoEncodings() + private void FillMenuWithIsoEncodings() + { + this.miIsoCharSets.Strings.Clear(); + this.isoEncodings.Clear(); + foreach(var encoding in Encoding.GetEncodings()) + { + if (!encoding.Name.StartsWith("iso")) + continue; + this.miIsoCharSets.Strings.Add(encoding.DisplayName); + this.isoEncodings.Add(encoding.Name); + } + } + #endregion + + #region ShowCharsetForm() + private void ShowCharsetForm() + { + using (var form = new CharsetForm(this.defaultEncoding)) + { + form.Location = new Point(this.Location.X + 30, this.Location.Y + 70); + form.EncodingChanged += this.charsetForm_EncodingChanged; + form.ShowDialog(this); + } + } + #endregion + + #region SetDefaultEncoding() + private void SetDefaultEncoding(Encoding encoding) + { + this.defaultEncoding = encoding; + if (this.currentTvSerializer == null) + return; + this.gviewInput.BeginDataUpdate(); + this.gviewOutput.BeginDataUpdate(); + this.currentTvSerializer.DefaultEncoding = encoding; + this.gviewInput.EndDataUpdate(); + this.gviewOutput.EndDataUpdate(); + } + #endregion + + #region ClearLeftFilter(), ClearRightFilter() + private void ClearLeftFilter() + { + this.gviewOutput.BeginSort(); + this.gviewOutput.ClearColumnsFilter(); + this.colOutSlot.FilterInfo = new ColumnFilterInfo("[NewProgramNr]<>0"); + this.gviewOutput.EndSort(); + } + + private void ClearRightFilter() + { + this.gviewInput.BeginSort(); + this.gviewInput.ClearColumnsFilter(); + this.colSlotOld.FilterInfo = new ColumnFilterInfo("[OldProgramNr]<>0"); + this.gviewInput.EndSort(); + } + #endregion + + #region SyncLists() + private void SyncLists(GridView source, GridView target) + { + var channel = (ChannelInfo)source.GetFocusedRow(); + if (channel == null) + return; + target.SetRowCellValue(GridControl.AutoFilterRowHandle, colName, channel.Name); + target.BeginSelection(); + target.ClearSelection(); + int rowIndex = ((IList) target.DataSource).IndexOf(channel); + int rowHandle = target.GetRowHandle(rowIndex); + target.FocusedRowHandle = rowHandle; + target.SelectRow(rowHandle); + target.EndSelection(); + } + #endregion + + #region LoadInputGridLayout() + private void LoadInputGridLayout(SignalSource newSource) + { + string newLayout; + if ((newSource & SignalSource.Digital) == 0) + newLayout = Settings.Default.InputGridLayoutAnalog; + else if (newSource == SignalSource.DvbS) + newLayout = Settings.Default.InputGridLayoutDvbS; + else + newLayout = Settings.Default.InputGridLayoutDvbCT; + if (!string.IsNullOrEmpty(newLayout)) + this.SetGridLayout(this.gviewInput, newLayout); + + foreach (GridColumn col in this.gviewInput.Columns) + col.Visible = GetGridColumnVisibility(col, newSource); + + this.gviewInput.ClearSelection(); + if (this.gviewInput.IsValidRowHandle(this.gviewInput.FocusedRowHandle)) + this.gviewInput.SelectRow(Settings.Default.InputListRowHandle); + + this.ClearRightFilter(); + } + #endregion + + #region SaveInputGridLayout() + private void SaveInputGridLayout(SignalSource signalSource) + { + string currentLayout = GetGridLayout(this.gviewInput); + switch (signalSource) + { + case SignalSource.Analog: Settings.Default.InputGridLayoutAnalog = currentLayout; break; + case SignalSource.DvbCT: Settings.Default.InputGridLayoutDvbCT = currentLayout; break; + case SignalSource.DvbS: Settings.Default.InputGridLayoutDvbS = currentLayout; break; + } + } + #endregion + + #region GetGridColumnVisibility() + + private bool GetGridColumnVisibility(GridColumn col, SignalSource source) + { + if (col == this.colShortName) return (source & SignalSource.Digital) != 0; + if (col == this.colEncrypted) return (source & SignalSource.Digital) != 0; + if (col == this.colServiceId) return (source & SignalSource.Digital) != 0; + if (col == this.colVideoPid) return (source & SignalSource.Digital) != 0; + if (col == this.colAudioPid) return (source & SignalSource.Digital) != 0; + if (col == this.colServiceType) return (source & SignalSource.Digital) != 0; + if (col == this.colServiceTypeName) return (source & SignalSource.Digital) != 0; + if (col == this.colEncrypted) return (source & SignalSource.Digital) != 0; + if (col == this.colTransportStreamId) return (source & SignalSource.Digital) != 0; + if (col == this.colNetworkName) return (source & SignalSource.Digital) != 0; + if (col == this.colNetworkOperator) return (source & SignalSource.Digital) != 0; + if (col == this.colSatellite) return (source & SignalSource.Sat) != 0; + if (col == this.colNetworkId) return (source & SignalSource.Digital) != 0; + if (col == this.colSymbolRate) return (source & SignalSource.Sat) != 0; + if (col == this.colIndex) return col.Visible; + if (col == this.colUid) return col.Visible; + if (col == this.colDebug) return colDebug.Visible; + if (col == this.colLogicalIndex) return colLogicalIndex.Visible; + if (col == this.colPolarity) return false; + + return true; + } + + #endregion + + #region SetFavorite() + private void SetFavorite(string fav, bool set) + { + if (string.IsNullOrEmpty(fav)) return; + char ch = Char.ToUpper(fav[0]); + if (ch<'A' || ch>'D') return; + var list = this.GetSelectedChannels(this.lastFocusedGrid); + if (list.Count == 0) return; + + this.gviewInput.BeginDataUpdate(); + this.gviewOutput.BeginDataUpdate(); + Favorites mask = (Favorites)(1 << (ch - 'A')); + foreach(var channel in list) + { + if (set) + channel.Favorites |= mask; + else + channel.Favorites &= ~mask; + } + this.gviewInput.EndDataUpdate(); + this.gviewOutput.EndDataUpdate(); + } + #endregion + + #region SetChannelFlag() + private void SetChannelFlag(Action setFlag) + { + var list = this.GetSelectedChannels(this.lastFocusedGrid); + if (list.Count == 0) return; + + this.gviewInput.BeginDataUpdate(); + this.gviewOutput.BeginDataUpdate(); + foreach (var channel in list) + setFlag(channel); + this.gviewInput.EndDataUpdate(); + this.gviewOutput.EndDataUpdate(); + this.dataRoot.NeedsSaving = true; + } + #endregion + + #region NavigateToChannel + private void NavigateToChannel(ChannelInfo channel, GridView view) + { + if (channel == null) return; + int rowHandle = this.gviewInput.GetRowHandle(this.currentChannelList.Channels.IndexOf(channel)); + if (view.IsValidRowHandle(rowHandle)) + { + view.ClearSelection(); + view.FocusedRowHandle = rowHandle; + view.SelectRow(rowHandle); + view.MakeRowVisible(rowHandle); + } + } + #endregion + + #region UpdateMenu + private void UpdateMenu() + { + bool isRight = this.lastFocusedGrid == this.gviewInput; + this.miAddChannel.Enabled = isRight; + + var visRight = isRight ? BarItemVisibility.Always : BarItemVisibility.Never; + var visLeft = isRight ? BarItemVisibility.Never : BarItemVisibility.Always; + + this.miSort.Visibility = visLeft; + this.miRenum.Visibility = visLeft; + this.miMoveUp.Visibility = visLeft; + this.miMoveDown.Visibility = visLeft; + this.miRemove.Visibility = visLeft; + this.miAddChannel.Visibility = visRight; + + var sel = this.gviewOutput.GetSelectedRows(); + var channel = sel.Length == 0 ? null : (ChannelInfo) this.gviewInput.GetRow(sel[0]); + this.miMoveUp.Enabled = channel != null && channel.NewProgramNr > 1; + + this.miTvSettings.Enabled = this.currentTvSerializer != null; + } + #endregion + + #region RestoreBackupFile() + private void RestoreBackupFile() + { + var bakFile = this.currentTvFile + ".bak"; + if (!File.Exists(bakFile)) + { + XtraMessageBox.Show(this, string.Format(Resources.MainForm_miRestoreOriginal_ItemClick_NoBackup, bakFile), + this.miRestoreOriginal.Caption, + MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + return; + } + + if (XtraMessageBox.Show(this, + Resources.MainForm_miRestoreOriginal_ItemClick_Confirm, + this.miRestoreOriginal.Caption, + MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) != + DialogResult.Yes) + { + return; + } + + try + { + File.Copy(bakFile, this.currentTvFile, true); + if (this.currentPlugin != null) + this.LoadFiles(this.currentPlugin); + } + catch (Exception) + { + XtraMessageBox.Show(this, string.Format(Resources.MainForm_miRestoreOriginal_Message, this.currentTvFile), + this.miRestoreOriginal.Caption, + MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + } + } + #endregion + + #region ShowFileInformation() + private void ShowFileInformation() + { + if (this.currentTvSerializer == null) + return; + var info = this.currentTvSerializer.GetFileInformation(); + InfoBox.Show(this, info, this.miFileInformation.Caption.Replace("...", "").Replace("&","")); + } + #endregion + + #region VerifyChannelNameModified() + private void VerifyChannelNameModified(ChannelInfo info, string newName) + { + if (newName != info.Name) + info.IsNameModified = true; + } + #endregion + + #region ShowTvCountrySettings() + private void ShowTvCountrySettings() + { + if (this.currentTvSerializer != null) + this.currentTvSerializer.ShowDeviceSettingsForm(this); + } + #endregion + + // UI events + + #region MainForm_Load + private void MainForm_Load(object sender, EventArgs e) + { + TryExecute(this.LoadSettings); + } + #endregion + + #region MainForm_Shown + private void MainForm_Shown(object sender, EventArgs e) + { + try + { + if (this.currentTvFile != "" && File.Exists(this.currentTvFile)) + this.LoadFiles(null); + } + catch (Exception ex) { HandleException(ex); } + } + #endregion + + // -- menus + + #region File menu + + private void miOpen_ItemClick(object sender, ItemClickEventArgs e) + { + TryExecute(this.ShowOpenFileDialog); + } + + private void miOpenReferenceFile_ItemClick(object sender, ItemClickEventArgs e) + { + this.TryExecute(this.ShowOpenReferenceFileDialog); + } + + private void miReload_ItemClick(object sender, ItemClickEventArgs e) + { + TryExecute(() => this.LoadFiles(this.currentPlugin)); + } + + private void miRestoreOriginal_ItemClick(object sender, ItemClickEventArgs e) + { + TryExecute(this.RestoreBackupFile); + } + + private void miFileInformation_ItemClick(object sender, ItemClickEventArgs e) + { + TryExecute(this.ShowFileInformation); + } + + private void miSave_ItemClick(object sender, ItemClickEventArgs e) + { + TryExecute(this.SaveFiles); + } + + private void miSaveAs_ItemClick(object sender, ItemClickEventArgs e) + { + TryExecute(this.ShowSaveFileDialog); + } + + private void miQuit_ItemClick(object sender, ItemClickEventArgs e) + { + this.Close(); + } + + #endregion + + #region Edit menu + + private void miMoveDown_ItemClick(object sender, ItemClickEventArgs e) + { + this.TryExecute(() => this.MoveChannels(false)); + } + + private void miMoveUp_ItemClick(object sender, ItemClickEventArgs e) + { + this.TryExecute(() => this.MoveChannels(true)); + } + + private void miRemove_ItemClick(object sender, ItemClickEventArgs e) + { + this.TryExecute(this.RemoveChannels); + } + + private void miReplace_ItemClick(object sender, ItemClickEventArgs e) + { + this.TryExecute(this.SwapChannels); + } + + private void miFavSet_ListItemClick(object sender, ListItemClickEventArgs e) + { + this.TryExecute(() => this.SetFavorite(this.miFavSet.Strings[e.Index], true)); + } + + private void miFavUnset_ListItemClick(object sender, ListItemClickEventArgs e) + { + this.TryExecute(() => this.SetFavorite(this.miFavSet.Strings[e.Index], false)); + } + + private void miLockOn_ItemClick(object sender, ItemClickEventArgs e) + { + this.TryExecute(() => this.SetChannelFlag(ch => ch.Lock = true)); + } + + private void miLockOff_ItemClick(object sender, ItemClickEventArgs e) + { + this.TryExecute(() => this.SetChannelFlag(ch => ch.Lock = false)); + } + + private void miSkipOn_ItemClick(object sender, ItemClickEventArgs e) + { + this.TryExecute(() => this.SetChannelFlag(ch => ch.Skip = true)); + } + + private void miSkipOff_ItemClick(object sender, ItemClickEventArgs e) + { + this.TryExecute(() => this.SetChannelFlag(ch => ch.Skip = false)); + } + + private void miHideOn_ItemClick(object sender, ItemClickEventArgs e) + { + this.TryExecute(() => this.SetChannelFlag(ch => ch.Hidden = true)); + } + + private void miHideOff_ItemClick(object sender, ItemClickEventArgs e) + { + this.TryExecute(() => this.SetChannelFlag(ch => ch.Hidden = false)); + } + #endregion + + #region Language menu + private void miLanguage_DownChanged(object sender, ItemClickEventArgs e) + { + try + { + if (this.ignoreLanguageChange) + return; + BarButtonItem menuItem = (BarButtonItem)sender; + if (!menuItem.Down) + return; + if (!this.PromptSaveAndContinue()) + return; + string locale = (string)menuItem.Tag; + Program.ChangeLanguage = true; + Thread.CurrentThread.CurrentUICulture = new CultureInfo(locale); + this.Close(); + } + catch (Exception ex) { HandleException(ex); } + } + #endregion + + #region TV-Set menu + private void miTvCountrySetup_ItemClick(object sender, ItemClickEventArgs e) + { + this.TryExecute(this.ShowTvCountrySettings); + } + #endregion + + #region Character set menu + + private void miIsoCharSets_ListItemClick(object sender, ListItemClickEventArgs e) + { + TryExecute(() => this.SetDefaultEncoding(Encoding.GetEncoding(this.isoEncodings[e.Index]))); + } + + private void miCharset_ItemClick(object sender, ItemClickEventArgs e) + { + TryExecute(ShowCharsetForm); + } + + private void charsetForm_EncodingChanged(object sender, EncodingChangedEventArgs e) + { + SetDefaultEncoding(e.Encoding); + } + #endregion + + #region miAbout_ItemClick + private void miAbout_ItemClick(object sender, ItemClickEventArgs e) + { + TryExecute(() => new AboutForm(this.plugins).ShowDialog()); + } + #endregion + + // -- controls + + #region comboChannelList_SelectedIndexChanged + private void comboChannelList_SelectedIndexChanged(object sender, EventArgs e) + { + this.TryExecute(() => ShowChannelList((ChannelList) this.comboChannelList.SelectedItem)); + } + #endregion + + #region gview_MouseDown + private void gview_MouseDown(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Right) + { + GridView view = (GridView)sender; + var hit = view.CalcHitInfo(e.Location); + if (view.IsDataRow(hit.RowHandle) && !view.IsRowSelected(hit.RowHandle)) + { + view.ClearSelection(); + view.SelectRow(hit.RowHandle); + } + } + } + #endregion + + #region gviewOutput_LayoutUpgrade, gviewInput_LayoutUpgrade + private void gviewOutput_LayoutUpgrade(object sender, LayoutUpgadeEventArgs e) + { + this.gviewOutput.ClearGrouping(); + this.gviewOutput.OptionsCustomization.AllowGroup = false; + } + + private void gviewInput_LayoutUpgrade(object sender, LayoutUpgadeEventArgs e) + { + this.gviewInput.ClearGrouping(); + this.gviewInput.OptionsCustomization.AllowGroup = false; + } + #endregion + + #region gridInput_Enter, gridOutput_Enter + private void gridInput_Enter(object sender, EventArgs e) + { + this.lastFocusedGrid = this.gviewInput; + this.UpdateMenu(); + } + + private void gridOutput_Enter(object sender, EventArgs e) + { + this.lastFocusedGrid = this.gviewOutput; + this.UpdateMenu(); + } + #endregion + + #region gviewInput_FocusedRowChanged + private void gviewInput_FocusedRowChanged(object sender, FocusedRowChangedEventArgs e) + { + if (!this.gviewInput.IsRowSelected(e.FocusedRowHandle)) + this.gviewInput.SelectRow(e.FocusedRowHandle); + } + #endregion + + #region gviewInput_CustomColumnDisplayText + private void gviewInput_CustomColumnDisplayText(object sender, CustomColumnDisplayTextEventArgs e) + { + if (e.Column == this.colSlotNew) + { + if (!(e.Value is int)) return; + if ((int) e.Value == 0) + e.DisplayText = string.Empty; + } + else if (e.Column == this.colFavorites) + { + if (!(e.Value is Favorites)) return; + if ((Favorites) e.Value == 0) + e.DisplayText = string.Empty; + } + } + #endregion + + #region gviewInput_RowCellStyle + private void gviewInput_RowCellStyle(object sender, RowCellStyleEventArgs e) + { + ChannelInfo channel = (ChannelInfo)this.gviewInput.GetRow(e.RowHandle); + if (channel == null) return; + if (channel.OldProgramNr == 0) + { + e.Appearance.ForeColor = Color.Red; + e.Appearance.Options.UseForeColor = true; + } + else if (channel.NewProgramNr != 0) + { + e.Appearance.ForeColor = Color.Gray; + e.Appearance.Options.UseForeColor = true; + } + } + #endregion + + #region gviewInput_RowClick + private void gviewInput_RowClick(object sender, RowClickEventArgs e) + { + if (e.Clicks == 2 && e.Button == MouseButtons.Left && this.gviewInput.IsDataRow(e.RowHandle)) + TryExecute(this.AddChannels); + } + #endregion + + #region gridInput_ProcessGridKey + private void gridInput_ProcessGridKey(object sender, KeyEventArgs e) + { + if (this.gviewInput.ActiveEditor != null) + return; + if (e.KeyCode == Keys.Enter) + { + TryExecute(this.AddChannels); + e.Handled = true; + } + } + + #endregion + + #region gviewInput_ValidatingEditor + private void gviewInput_ValidatingEditor(object sender, BaseContainerValidateEditorEventArgs e) + { + try + { + if (gviewInput.FocusedRowHandle == GridControl.AutoFilterRowHandle) + return; + if (this.gviewInput.FocusedColumn == this.colSlotNew && e.Value is string) + e.Valid = this.SetSlotNumber((string)e.Value); + else if (this.gviewInput.FocusedColumn == this.colFavorites && e.Value is string) + e.Value = ChannelInfo.ParseFavString((string)e.Value); + else if (gviewInput.FocusedColumn == this.colName) + this.VerifyChannelNameModified(this.gviewInput.GetFocusedRow() as ChannelInfo, e.Value as string); + dataRoot.NeedsSaving = true; + } catch(Exception ex) { HandleException(ex); } + } + #endregion + + #region gviewInput_PopupMenuShowing + private void gviewInput_PopupMenuShowing(object sender, PopupMenuShowingEventArgs e) + { + this.lastFocusedGrid = this.gviewInput; + this.UpdateMenu(); + if (e.MenuType == GridMenuType.Row) + this.mnuContext.ShowPopup(this.gridInput.PointToScreen(e.Point)); + } + #endregion + + #region gviewOutput_FocusedRowChanged + + private void gviewOutput_FocusedRowChanged(object sender, FocusedRowChangedEventArgs e) + { + var channel = (ChannelInfo)this.gviewOutput.GetRow(e.FocusedRowHandle); + if (channel == null) + return; + int programNr = channel.NewProgramNr; + if (this.comboEditMode.SelectedIndex == (int)EditMode.InsertAfter) + ++programNr; + if (this.currentChannelList != null) + this.currentChannelList.InsertProgramNumber = programNr; + this.UpdateInsertSlotTextBox(); + if (!this.gviewOutput.IsRowSelected(e.FocusedRowHandle)) + this.gviewOutput.SelectRow(e.FocusedRowHandle); + } + + #endregion + + #region gviewOutput_CustomColumnDisplayText + private void gviewOutput_CustomColumnDisplayText(object sender, CustomColumnDisplayTextEventArgs e) + { + if (e.Column == this.colOutFav) + { + if (!(e.Value is Favorites)) return; + if ((Favorites)e.Value == 0) + e.DisplayText = string.Empty; + } + } + #endregion + + #region gviewOutput_RowCellStyle + private void gviewOutput_RowCellStyle(object sender, RowCellStyleEventArgs e) + { + var channel = (ChannelInfo)this.gviewOutput.GetRow(e.RowHandle); + if (channel == null) return; + if (channel.OldProgramNr == 0) + { + e.Appearance.ForeColor = Color.Red; + e.Appearance.Options.UseForeColor = true; + } + } + #endregion + + #region gviewOutput_ValidatingEditor + private void gviewOutput_ValidatingEditor(object sender, BaseContainerValidateEditorEventArgs e) + { + try + { + if (gviewOutput.FocusedRowHandle == GridControl.AutoFilterRowHandle) + return; + if (this.gviewOutput.FocusedColumn == this.colOutSlot && e.Value is string) + e.Valid = this.SetSlotNumber((string)e.Value); + else if (this.gviewOutput.FocusedColumn == this.colOutFav && e.Value is string) + e.Value = ChannelInfo.ParseFavString((string) e.Value); + else if (gviewOutput.FocusedColumn == this.colOutName) + this.VerifyChannelNameModified(this.gviewOutput.GetFocusedRow() as ChannelInfo, e.Value as string); + dataRoot.NeedsSaving = true; + } + catch (Exception ex) { HandleException(ex); } + } + #endregion + + #region gviewOutput_CellValueChanged + private void gviewOutput_CellValueChanged(object sender, CellValueChangedEventArgs e) + { + this.gviewInput.BeginDataUpdate(); + this.gviewInput.EndDataUpdate(); + } + #endregion + + #region gviewOutput_PopupMenuShowing + private void gviewOutput_PopupMenuShowing(object sender, PopupMenuShowingEventArgs e) + { + this.lastFocusedGrid = this.gviewOutput; + this.UpdateMenu(); + if (e.MenuType == GridMenuType.Row) + this.mnuContext.ShowPopup(this.gridOutput.PointToScreen(e.Point)); + } + #endregion + + #region gviewOutput_RowClick + private void gviewOutput_RowClick(object sender, RowClickEventArgs e) + { + if (e.Clicks == 2 && e.Button == MouseButtons.Left && this.gviewOutput.IsDataRow(e.RowHandle)) + { + ChannelInfo channel = (ChannelInfo) this.gviewOutput.GetRow(e.RowHandle); + this.NavigateToChannel(channel, this.gviewInput); + } + } + #endregion + + #region gridOutput_ProcessGridKey + private void gridOutput_ProcessGridKey(object sender, KeyEventArgs e) + { + if (gviewOutput.ActiveEditor != null) + return; + if (e.KeyCode == Keys.Delete) + TryExecute(this.RemoveChannels); + else if (e.KeyCode == Keys.Add) + TryExecute(() => this.MoveChannels(false)); + else if (e.KeyCode == Keys.Subtract) + TryExecute(() => this.MoveChannels(true)); + else + return; + e.Handled = true; + } + #endregion + + #region comboEditMode_SelectedIndexChanged + private void comboEditMode_SelectedIndexChanged(object sender, EventArgs e) + { + try + { + if (this.currentChannelList == null) + return; + int delta = this.curEditMode == EditMode.InsertAfter ? -1 : + (EditMode)this.comboEditMode.SelectedIndex == EditMode.InsertAfter ? +1 : 0; + this.currentChannelList.InsertProgramNumber += delta; + this.UpdateInsertSlotTextBox(); + this.curEditMode = (EditMode) this.comboEditMode.SelectedIndex; + } catch(Exception ex) { HandleException(ex); } + } + #endregion + + #region btnClearLeftFilter_Click, btnClearRightFilter_Click + private void btnClearLeftFilter_Click(object sender, EventArgs e) + { + TryExecute(this.ClearLeftFilter); + } + + private void btnClearRightFilter_Click(object sender, EventArgs e) + { + TryExecute(this.ClearRightFilter); + } + #endregion + + #region btnSyncFromLeft_Click, btnSyncFromRight_Click + private void btnSyncFromLeft_Click(object sender, EventArgs e) + { + TryExecute(() => this.SyncLists(this.gviewOutput, this.gviewInput)); + } + + private void btnSyncFromRight_Click(object sender, EventArgs e) + { + TryExecute(() => this.SyncLists(this.gviewInput, this.gviewOutput)); + } + #endregion + + #region btnAdd_Click + + private void btnAdd_Click(object sender, EventArgs e) + { + TryExecute(this.AddChannels); + } + #endregion + + #region btnRemove_Click + + private void btnRemove_Click(object sender, EventArgs e) + { + TryExecute(this.RemoveChannels); + } + #endregion + + #region btnUp_Click, btnDown_Click + + private void btnUp_Click(object sender, EventArgs e) + { + TryExecute(() => MoveChannels(true)); + } + + private void btnDown_Click(object sender, EventArgs e) + { + TryExecute(() => MoveChannels(false)); + } + + #endregion + + #region txtSetSlot_EditValueChanged + private void txtSetSlot_EditValueChanged(object sender, EventArgs e) + { + TryExecute(() => + { + int nr; + int.TryParse(this.txtSetSlot.Text, out nr); + if (this.currentChannelList != null) + this.currentChannelList.InsertProgramNumber = nr; + }); + } + #endregion + + #region txtSetSlot_ButtonClick, txtSetSlot_KeyDown + private void txtSetSlot_ButtonClick(object sender, ButtonPressedEventArgs e) + { + TryExecute(() => this.SetSlotNumber(this.txtSetSlot.Text)); + } + + private void txtSetSlot_KeyDown(object sender, KeyEventArgs e) + { + if (e.KeyData == Keys.Enter) + { + TryExecute(() => this.SetSlotNumber(this.txtSetSlot.Text)); + e.Handled = true; + } + } + #endregion + + #region btnSort_Click + private void btnSort_Click(object sender, EventArgs e) + { + TryExecute(this.SortSelectedChannels); + } + #endregion + + #region btnRenum_Click + private void btnRenum_Click(object sender, EventArgs e) + { + TryExecute(this.RenumberSelectedChannels); + } + #endregion + + #region ProcessCmdKey + + protected override bool ProcessCmdKey(ref Message msg, Keys keyData) + { + switch (keyData) + { + case Keys.F3: + this.gviewOutput.FocusedRowHandle = GridControl.AutoFilterRowHandle; + this.gviewOutput.FocusedColumn = this.colOutName; + this.gridOutput.Focus(); + return true; + case Keys.F4: + if (this.gviewOutput.SelectedRowsCount > 0) + { + this.gviewOutput.FocusedRowHandle = this.gviewOutput.GetSelectedRows()[0]; + this.gridOutput.Focus(); + } + return true; + case Keys.F5: + this.gviewInput.FocusedRowHandle = GridControl.AutoFilterRowHandle; + this.gviewInput.FocusedColumn = this.colName; + this.gridInput.Focus(); + return true; + case Keys.F6: + if (this.gviewInput.SelectedRowsCount > 0) + { + this.gviewInput.FocusedRowHandle = this.gviewInput.GetSelectedRows()[0]; + this.gridInput.Focus(); + } + return true; + } + return base.ProcessCmdKey(ref msg, keyData); + } + + #endregion + + #region MainForm_FormClosing + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + if (this.PromptSaveAndContinue()) + this.SaveSettings(); + else + e.Cancel = true; + } + #endregion + + #region btnResetChannelData_Click + private void btnResetChannelData_Click(object sender, EventArgs e) + { + if (this.currentTvSerializer == null) + return; + + if (XtraMessageBox.Show(this, + Resources.MainForm_btnResetChannelData_Click_Message, + Resources.MainForm_btnResetChannelData_Click_Caption, + MessageBoxButtons.YesNo, + MessageBoxIcon.Warning, + MessageBoxDefaultButton.Button2) != DialogResult.Yes) + { + return; + } + + TryExecute(() => + { + this.currentTvSerializer.EraseChannelData(); + this.LoadFiles(this.currentPlugin); + }); + } + #endregion + + #region btnCloneChannelList_Click + private void btnCloneChannelList_Click(object sender, EventArgs e) + { + this.TryExecute(this.CloneChannelList); + } + #endregion + + private void gviewOutput_SelectionChanged(object sender, DevExpress.Data.SelectionChangedEventArgs e) + { + this.UpdateMenu(); + } + + private void gviewInput_CellValueChanged(object sender, CellValueChangedEventArgs e) + { + + } + + } +} diff --git a/ChanSort.Ui/MainForm.de.resx b/ChanSort.Ui/MainForm.de.resx new file mode 100644 index 0000000..6ffc157 --- /dev/null +++ b/ChanSort.Ui/MainForm.de.resx @@ -0,0 +1,693 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + + + + + + Default + + + + Top, Left + + + + + + Tile + + + Inherit + + + + Center + + + + + + + None + + + + + + + Horizontal + + + + + + Neue Pr# + + + Neuer Programmplatz + + + Sendername + + + Favoriten + + + Default + + + + False + + + True + + + _ + + + True + + + True + + + False + + + 333, 17 + + + F3: Filter | F4: Liste | -: nach oben | +: nach unten | Entf: entfernen + + + Dahinter einfügen + + + &Datei + + + TV Senderliste &öffnen... + + + &Erneut laden + + + Sicherheitskopie wiederherstellen + + + Datei&information... + + + &Speichern + + + Speichern &unter... + + + Referenzliste öffnen... + + + &Beenden + + + &Bearbeiten + + + Sender &übernehmen + + + Sender &entfernen + + + Sender erset&zen + + + Sender alphabetisch sortieren + + + Sender neu &nummerieren + + + &Favoriten hinzufügen + + + Favoriten entfernen + + + Sender s&perren: ein + + + Sender sperren: aus + + + Sender ü&berspringen: ein + + + Sender überspringen: aus + + + Sender &verstecken: ein + + + Sender verstecken: aus + + + TV-Gerät + + + Geräteeinstellungen... + + + &Einstellungen + + + &Sprache + + + &Zeichensatz + + + &Hilfe + + + &Über ChanSort... + + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAF1EZXZFeHByZXNzLlh0cmFCYXJzLnYxMi4yLCBWZXJzaW9uPTEy + LjIuNi4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI4OGQxNzU0ZDcwMGU0OWEFAQAA + ACZEZXZFeHByZXNzLlh0cmFCYXJzLkJhck1hbmFnZXJDYXRlZ29yeQMAAAAETmFtZQRHdWlkB1Zpc2li + bGUBAwALU3lzdGVtLkd1aWQBAgAAAAYDAAAABEZpbGUE/P///wtTeXN0ZW0uR3VpZAsAAAACX2ECX2IC + X2MCX2QCX2UCX2YCX2cCX2gCX2kCX2oCX2sAAAAAAAAAAAAAAAgHBwICAgICAgICKaPJ5gsBeU2NTSFe + Xxl+0wEL + + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAF1EZXZFeHByZXNzLlh0cmFCYXJzLnYxMi4yLCBWZXJzaW9uPTEy + LjIuNi4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI4OGQxNzU0ZDcwMGU0OWEFAQAA + ACZEZXZFeHByZXNzLlh0cmFCYXJzLkJhck1hbmFnZXJDYXRlZ29yeQMAAAAETmFtZQRHdWlkB1Zpc2li + bGUBAwALU3lzdGVtLkd1aWQBAgAAAAYDAAAABEhlbHAE/P///wtTeXN0ZW0uR3VpZAsAAAACX2ECX2IC + X2MCX2QCX2UCX2YCX2cCX2gCX2kCX2oCX2sAAAAAAAAAAAAAAAgHBwICAgICAgICdEVVDegwMU2acNpw + KphCYAEL + + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAF1EZXZFeHByZXNzLlh0cmFCYXJzLnYxMi4yLCBWZXJzaW9uPTEy + LjIuNi4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI4OGQxNzU0ZDcwMGU0OWEFAQAA + ACZEZXZFeHByZXNzLlh0cmFCYXJzLkJhck1hbmFnZXJDYXRlZ29yeQMAAAAETmFtZQRHdWlkB1Zpc2li + bGUBAwALU3lzdGVtLkd1aWQBAgAAAAYDAAAABEVkaXQE/P///wtTeXN0ZW0uR3VpZAsAAAACX2ECX2IC + X2MCX2QCX2UCX2YCX2cCX2gCX2kCX2oCX2sAAAAAAAAAAAAAAAgHBwICAgICAgICZMTu18lZRU+IqmAu + ZMgcwAEL + + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAF1EZXZFeHByZXNzLlh0cmFCYXJzLnYxMi4yLCBWZXJzaW9uPTEy + LjIuNi4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI4OGQxNzU0ZDcwMGU0OWEFAQAA + ACZEZXZFeHByZXNzLlh0cmFCYXJzLkJhck1hbmFnZXJDYXRlZ29yeQMAAAAETmFtZQRHdWlkB1Zpc2li + bGUBAwALU3lzdGVtLkd1aWQBAgAAAAYDAAAAB09wdGlvbnME/P///wtTeXN0ZW0uR3VpZAsAAAACX2EC + X2ICX2MCX2QCX2UCX2YCX2cCX2gCX2kCX2oCX2sAAAAAAAAAAAAAAAgHBwICAgICAgICXJMOh9nzAkKc + WIeWYGkVXQEL + + + + Horizontal + + + + + + Horizontal + + + + + + Horizontal + + + + + + Horizontal + + + + + + In bestehender Reihenfolge am Ende anhängen + + + + + + + + + True + + + In bestehender Reihenfolge am Ende anhängen + + + In alphabetischer Reihenfolge am Ende anhängen + + + Löschen + + + + + + False + + + 262, 20 + + + + + + Horizontal + + + + + + + + + + + + Nicht explizit sortierte Sender: + + + Senderlisten vollständig löschen + + + + + + + + + True + + + + + + False + + + 57, 13 + + + Senderliste: + + + ChanSort v2013-03-30 - Senderlisten Editor für LG und Samsung TV + + + Nach oben + + + Nach unten + + + + + + + + + True + + + Davor einfügen + + + Dahinter einfügen + + + Austauschen + + + + + + False + + + Nach aktuellem Sender in rechtem Fenster filtern + + + 35, 13 + + + Modus: + + + Horizontal + + + + + + Filter zurücksetzen + + + Markierte Sender neu nummerieren + + + Markierte Sender alphabetisch sortieren + + + Markierte Sender nach unten verschieben + + + Markierte Sender nach oben verschieben + + + Markierte Sender entfernen + + + + + + + + + True + + + Default + + + False + + + True + + + _ + + + True + + + True + + + False + + + + + + False + + + Setze Pr#: + + + Programplatz für Einfügen und Festlegen + + + Sortierte Sender (.csv) + + + + + + + + + Default + + + Top, Left + + + + + + Tile + + + Inherit + + + Center + + + + + + None + + + + + + Horizontal + + + + + + Alte Pr# + + + Alter Programmplatz + + + Neue Pr# + + + Neuer Programmplatz + + + Sendername + + + Kurzname + + + Favoriten + + + Default + + + False + + + True + + + _ + + + True + + + True + + + False + + + Ge- sperrt + + + Über- springen + + + Ver- steckt + + + Ver- schlüss + + + Verschlüsselt + + + Kanal/ Transp. + + + Kanal- bzw. Transpondernummer + + + Freqenz (MHz) + + + Satellit + + + Symbol- rate + + + Polarität + + + Netzwerk Name + + + Netzwerk Betreiber + + + 213, 17 + + + F5: Filter | F6: Liste | Eingabe: übernehmen + + + << Alle hinzufügen (aktuelle Senderliste kopieren) + + + Horizontal + + + + + + Filter zurücksetzen + + + Nach aktuellem Sender in linkem Fenster filtern + + + Markierte Sender übernehmen + + + Alle Sender + + \ No newline at end of file diff --git a/ChanSort.Ui/MainForm.resx b/ChanSort.Ui/MainForm.resx new file mode 100644 index 0000000..bbb1eff --- /dev/null +++ b/ChanSort.Ui/MainForm.resx @@ -0,0 +1,2375 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Fill + + + + 0, 59 + + + 361, 17 + + + Fill + + + 2, 85 + + + Pr. index + + + New Pr# + + + New program number + + + + True + + + 0 + + + 50 + + + Channel name + + + True + + + 1 + + + 180 + + + Favorites + + + False + + + + Combo + + + + + + + + RegEx + + + True + + + 2 + + + 55 + + + UID + + + 332, 436 + + + 1 + + + gridOutput + + + DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpOutputList + + + 0 + + + Bottom + + + 2, 521 + + + 2, 2, 2, 2 + + + 302, 17 + + + 2 + + + F3: Filter | F4: List | -: move up | +: move down | Del: remove + + + lblHotkeyLeft + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpOutputList + + + 1 + + + Insert after + + + 213, 7 + + + 475, 17 + + + &File + + + &Open TV data file... + + + &Reload + + + Restore backup + + + File &information... + + + &Save + + + Save &as... + + + Import reference list... + + + &Quit + + + &Edit + + + &Add channels + + + &Remove channels + + + Re&place channel + + + Sor&t channels alphabetically + + + Re&number channels + + + Add to &Favorites + + + Favoriten setzen + + + Remove from Favorites + + + Favoriten entfernen + + + &Lock channel: on + + + Lock channel: off + + + &Skip channel: on + + + Skip channel: off + + + &Hide channel: on + + + Hide channel: off + + + TV-Set + + + Device setting... + + + &Settings + + + &Language + + + &English + + + &Deutsch + + + &Character set + + + Alle &Zeichensätze... + + + ISO Zeichensätze + + + &Help + + + &About ChanSort... + + + Tools + + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAF1EZXZFeHByZXNzLlh0cmFCYXJzLnYxMi4yLCBWZXJzaW9uPTEy + LjIuNi4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI4OGQxNzU0ZDcwMGU0OWEFAQAA + ACZEZXZFeHByZXNzLlh0cmFCYXJzLkJhck1hbmFnZXJDYXRlZ29yeQMAAAAETmFtZQRHdWlkB1Zpc2li + bGUBAwALU3lzdGVtLkd1aWQBAgAAAAYDAAAABEZpbGUE/P///wtTeXN0ZW0uR3VpZAsAAAACX2ECX2IC + X2MCX2QCX2UCX2YCX2cCX2gCX2kCX2oCX2sAAAAAAAAAAAAAAAgHBwICAgICAgICKaPJ5gsBeU2NTSFe + Xxl+0wEL + + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAF1EZXZFeHByZXNzLlh0cmFCYXJzLnYxMi4yLCBWZXJzaW9uPTEy + LjIuNi4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI4OGQxNzU0ZDcwMGU0OWEFAQAA + ACZEZXZFeHByZXNzLlh0cmFCYXJzLkJhck1hbmFnZXJDYXRlZ29yeQMAAAAETmFtZQRHdWlkB1Zpc2li + bGUBAwALU3lzdGVtLkd1aWQBAgAAAAYDAAAABEhlbHAE/P///wtTeXN0ZW0uR3VpZAsAAAACX2ECX2IC + X2MCX2QCX2UCX2YCX2cCX2gCX2kCX2oCX2sAAAAAAAAAAAAAAAgHBwICAgICAgICdEVVDegwMU2acNpw + KphCYAEL + + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAF1EZXZFeHByZXNzLlh0cmFCYXJzLnYxMi4yLCBWZXJzaW9uPTEy + LjIuNi4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI4OGQxNzU0ZDcwMGU0OWEFAQAA + ACZEZXZFeHByZXNzLlh0cmFCYXJzLkJhck1hbmFnZXJDYXRlZ29yeQMAAAAETmFtZQRHdWlkB1Zpc2li + bGUBAwALU3lzdGVtLkd1aWQBAgAAAAYDAAAABEVkaXQE/P///wtTeXN0ZW0uR3VpZAsAAAACX2ECX2IC + X2MCX2QCX2UCX2YCX2cCX2gCX2kCX2oCX2sAAAAAAAAAAAAAAAgHBwICAgICAgICZMTu18lZRU+IqmAu + ZMgcwAEL + + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAF1EZXZFeHByZXNzLlh0cmFCYXJzLnYxMi4yLCBWZXJzaW9uPTEy + LjIuNi4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI4OGQxNzU0ZDcwMGU0OWEFAQAA + ACZEZXZFeHByZXNzLlh0cmFCYXJzLkJhck1hbmFnZXJDYXRlZ29yeQMAAAAETmFtZQRHdWlkB1Zpc2li + bGUBAwALU3lzdGVtLkd1aWQBAgAAAAYDAAAAB09wdGlvbnME/P///wtTeXN0ZW0uR3VpZAsAAAACX2EC + X2ICX2MCX2QCX2UCX2YCX2cCX2gCX2kCX2oCX2sAAAAAAAAAAAAAAAgHBwICAgICAgICXJMOh9nzAkKc + WIeWYGkVXQEL + + + + Top + + + 0, 0 + + + 1474, 25 + + + barDockControlTop + + + DevExpress.XtraBars.BarDockControl, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 5 + + + Bottom + + + 0, 599 + + + 1474, 0 + + + barDockControlBottom + + + DevExpress.XtraBars.BarDockControl, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 4 + + + Left + + + 0, 25 + + + 0, 574 + + + barDockControlLeft + + + DevExpress.XtraBars.BarDockControl, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 2 + + + Right + + + 1474, 25 + + + 0, 574 + + + barDockControlRight + + + DevExpress.XtraBars.BarDockControl, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 3 + + + True + + + 6, 13 + + + 1474, 599 + + + Delete + + + 511, 7 + + + Combo + + + Append at end in current order + + + Append at end in alphabetical order + + + Delete (=set to Pr# 0) + + + 250, 20 + + + 4 + + + comboUnsortedAction + + + DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpTopPanel + + + 0 + + + Vertical + + + 316, 10 + + + 189, 13 + + + 3 + + + Channels not sorted explicitly: + + + labelControl3 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpTopPanel + + + 1 + + + 784, 6 + + + 170, 23 + + + 2 + + + Erase all channel data + + + btnResetChannelData + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpTopPanel + + + 2 + + + 92, 7 + + + Combo + + + 218, 20 + + + 1 + + + comboChannelList + + + DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpTopPanel + + + 3 + + + 12, 10 + + + 59, 13 + + + 0 + + + Channel list: + + + labelControl1 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpTopPanel + + + 4 + + + Top + + + 0, 25 + + + 1474, 34 + + + 0 + + + groupControl1 + + + grpTopPanel + + + DevExpress.XtraEditors.GroupControl, DevExpress.Utils.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 1 + + + CenterScreen + + + ChanSort v2013-03-30 - Channel List Editor for LG and Samsung TVs + + + dsChannels + + + System.Windows.Forms.BindingSource, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gviewOutput + + + DevExpress.XtraGrid.Views.Grid.GridView, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colIndex1 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colOutSlot + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colOutName + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colOutFav + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + repositoryItemCheckedComboBoxEdit1 + + + DevExpress.XtraEditors.Repository.RepositoryItemCheckedComboBoxEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colUid1 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + barManager1 + + + DevExpress.XtraBars.BarManager, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + bar1 + + + DevExpress.XtraBars.Bar, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miFile + + + DevExpress.XtraBars.BarSubItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miOpen + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miReload + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miRestoreOriginal + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miFileInformation + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miSave + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miSaveAs + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miOpenReferenceFile + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miQuit + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miEdit + + + DevExpress.XtraBars.BarSubItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miAddChannel + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miRemove + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miReplace + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miSort + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miRenum + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + mnuFavSet + + + DevExpress.XtraBars.BarSubItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miFavSet + + + DevExpress.XtraBars.BarListItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + mnuFavUnset + + + DevExpress.XtraBars.BarSubItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miFavUnset + + + DevExpress.XtraBars.BarListItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miLockOn + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miLockOff + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miSkipOn + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miSkipOff + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miHideOn + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miHideOff + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + barSubItem2 + + + DevExpress.XtraBars.BarSubItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miTvSettings + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + mnuOptions + + + DevExpress.XtraBars.BarSubItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + barSubItem1 + + + DevExpress.XtraBars.BarSubItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miEnglish + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miGerman + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + mnuCharset + + + DevExpress.XtraBars.BarSubItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miCharsetForm + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miIsoCharSets + + + DevExpress.XtraBars.BarListItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + mnuHelp + + + DevExpress.XtraBars.BarSubItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miAbout + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + sharedImageCollection1 + + + DevExpress.Utils.SharedImageCollection, DevExpress.Utils.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miMoveUp + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + miMoveDown + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gviewInput + + + DevExpress.XtraGrid.Views.Grid.GridView, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colIndex + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colSlotOld + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colSlotNew + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colName + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colShortName + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colFavorites + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + repositoryItemCheckedComboBoxEdit2 + + + DevExpress.XtraEditors.Repository.RepositoryItemCheckedComboBoxEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colLock + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colSkip + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colHidden + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colEncrypted + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colChannelOrTransponder + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colFreqInMhz + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colServiceId + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colVideoPid + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colAudioPid + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colServiceType + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colServiceTypeName + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colSatellite + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colNetworkId + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colTransportStreamId + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colSymbolRate + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colPolarity + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colUid + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colNetworkName + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colNetworkOperator + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colDebug + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + colLogicalIndex + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + defaultLookAndFeel1 + + + DevExpress.LookAndFeel.DefaultLookAndFeel, DevExpress.Utils.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + splashScreenManager1 + + + DevExpress.XtraSplashScreen.SplashScreenManager, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + mnuContext + + + DevExpress.XtraBars.PopupMenu, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + MainForm + + + DevExpress.XtraEditors.XtraForm, DevExpress.Utils.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + 600, 17 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFpEZXZFeHByZXNzLlV0aWxzLnYxMi4yLCBWZXJzaW9uPTEyLjIu + Ni4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI4OGQxNzU0ZDcwMGU0OWEMAwAAAFFT + eXN0ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRv + a2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAAChEZXZFeHByZXNzLlV0aWxzLkltYWdlQ29sbGVjdGlvblN0 + cmVhbWVyAgAAAAlJbWFnZVNpemUERGF0YQQHE1N5c3RlbS5EcmF3aW5nLlNpemUDAAAAAgIAAAAF/P// + /xNTeXN0ZW0uRHJhd2luZy5TaXplAgAAAAV3aWR0aAZoZWlnaHQAAAgIAwAAABAAAAAQAAAACQUAAAAP + BQAAABRDAAACDgMAAIlQTkcNChoKAAAADUlIRFIAAAAQAAAAEAgGAAAAH/P/YQAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAACukAAArpAf11ztMAAAAqdEVYdENyZWF0aW9uIFRpbWUATWkgMSBNcnogMjAwNiAx + NToxMDo1MSArMDEwMP/NqUUAAAAHdElNRQfWAwEODCaDia/cAAACZ0lEQVQ4T82S7UsTUBSH75eCCAx6 + oTAqg7BMRKjoQ6S9Oa1I10gzU8PUZmYpKEamy8gCX8iS2YxqiRmREMrUltEoLdSMps458wXUEiW0UToN + bdTTpaLtP6gDlwuXe57zO79zxP8RC1M7CCzqRSR0IZI7EepOvLO7CI4qRRGpxTejGRHTioiVd+RrAmMq + 8FA+4k+6EGHJlfA4H+MoiMJviKtO7nbPQcJqOLaSNtsHxKUpxMUpzmobQX+aYI2E/Y3kftJ1LVClwfxF + Qgp+cL3DKQG+ErAek2UUoZmloMwEFeco75hEhJrcAElWRD6ElA3CzVR6ZkDXA5zwgzgfntrsFGnroVLD + leYZRKoEKp+5AP457TR0j/PA4uB9v4QMmGHWAepNcNyPuSEbziYDw2MT3GkcpuZVHz6JT1wA5dESiF0p + q22ERH+ZuPn3ObVNqtgK0RsgfA0cWA57PWC3QLkz0wVQHSmGqCXy41qI8ZZ9S1CclK/eAvFSRYR8D10B + +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 + ZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tl + dCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1s + bnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0 + MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRw + Oi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiBy + ZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4 + bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9u + cy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRv + YmUgUGhvdG9zaG9wIENTNS4xIFdpbmRvd3MiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NjQ1QTVE + QzE1NTY1MTFFMTlEMzlGQkM3NTZEQTg5QjAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NjQ1QTVE + QzI1NTY1MTFFMTlEMzlGQkM3NTZEQTg5QjAiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFu + Y2VJRD0ieG1wLmlpZDo2NDVBNURCRjU1NjUxMUUxOUQzOUZCQzc1NkRBODlCMCIgc3RSZWY6ZG9jdW1l + bnRJRD0ieG1wLmRpZDo2NDVBNURDMDU1NjUxMUUxOUQzOUZCQzc1NkRBODlCMCIvPiA8L3JkZjpEZXNj + cmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqSWWTYAAAJY + SURBVDhPbVJLaxNhFP2gexdCacxrEpIWUbJI2qSPpKn4iNZYGsGkWqFPRaGFaA1qYjOmaqFkEVQIFXWn + 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 + A6hW1582hiNtAAAAAElFTkSuQmCCCw== + + + + 03/28/2013 23:00:31 + + + 16, 16 + + + Move up + + + Move down + + + Combo + + + Insert before + + + Insert after + + + Swap + + + 114, 20 + + + 11 + + + comboEditMode + + + DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + pnlEditControls + + + 0 + + + 273, 34 + + + 54, 23 + + + 10 + + + Filter > + + + Filter for current channel in right list + + + btnSyncFromLeft + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + pnlEditControls + + + 1 + + + 165, 10 + + + 30, 13 + + + 2 + + + Mode: + + + labelControl2 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + pnlEditControls + + + 2 + + + Tahoma, 8.25pt, style=Strikeout + + + 213, 34 + + + 54, 23 + + + 9 + + + Filter + + + Reset filter + + + btnClearLeftFilter + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + pnlEditControls + + + 3 + + + 147, 35 + + + 23, 23 + + + 8 + + + 1-999 + + + Renumber selected channels + + + btnRenum + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + pnlEditControls + + + 4 + + + 118, 34 + + + 23, 23 + + + 7 + + + A-Z + + + Sort selected channels alphabetically + + + btnSort + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + pnlEditControls + + + 5 + + + 34, 34 + + + 23, 23 + + + 6 + + + v + + + Move selected channels down + + + btnDown + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + pnlEditControls + + + 6 + + + 5, 34 + + + 23, 23 + + + 5 + + + ^ + + + Move selected channels up + + + btnUp + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + pnlEditControls + + + 7 + + + 75, 34 + + + 23, 23 + + + 2 + + + >> + + + Remove selected channels + + + btnRemove + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + pnlEditControls + + + 8 + + + 90, 8 + + + OK + + + \d{1,4} + + + RegEx + + + 66, 20 + + + 1 + + + txtSetSlot + + + DevExpress.XtraEditors.ButtonEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + pnlEditControls + + + 9 + + + Vertical + + + 4, 11 + + + 80, 13 + + + 0 + + + Set Pr#: + + + Program number for insert and set operations + + + labelControl11 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + pnlEditControls + + + 10 + + + Top + + + 2, 21 + + + 332, 64 + + + 0 + + + pnlEditControls + + + DevExpress.XtraEditors.PanelControl, DevExpress.Utils.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpOutputList + + + 2 + + + Fill + + + 0, 0 + + + 336, 540 + + + 0 + + + Sorted channels (.csv) + + + grpOutputList + + + DevExpress.XtraEditors.GroupControl, DevExpress.Utils.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + splitContainerControl1.Panel1 + + + 0 + + + Panel1 + + + Fill + + + 2, 85 + + + Pr. index + + + Old Pr# + + + Old program number + + + True + + + 0 + + + 50 + + + New Pr# + + + New program number + + + True + + + 1 + + + 45 + + + Channel name + + + True + + + 2 + + + 180 + + + Short name + + + True + + + 3 + + + Favorites + + + False + + + Combo + + + + + + RegEx + + + True + + + 4 + + + 55 + + + Locked + + + True + + + 5 + + + 40 + + + Skip + + + True + + + 6 + + + 40 + + + Hide + + + True + + + 7 + + + 40 + + + Crypt + + + Encrypted + + + True + + + 8 + + + 40 + + + Chan/ Transp + + + Channel or transponder number + + + True + + + 9 + + + 45 + + + Freqency (MHz) + + + True + + + 10 + + + 57 + + + Service ID + + + True + + + 11 + + + 45 + + + Video PID + + + True + + + 12 + + + 40 + + + Audio PID + + + True + + + 13 + + + 40 + + + Service Typ + + + True + + + 14 + + + 45 + + + True + + + 15 + + + 45 + + + Satellite + + + True + + + 16 + + + 100 + + + Netzwerk (ONID) + + + True + + + 17 + + + 45 + + + TS ID + + + Transport Stream ID + + + True + + + 18 + + + 40 + + + Symbol rate + + + True + + + 19 + + + 40 + + + Polarity + + + 40 + + + Uid + + + 120 + + + Network Name + + + True + + + 20 + + + Network Operator + + + True + + + 21 + + + Order + + + 1130, 436 + + + 1 + + + gridInput + + + DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpInputList + + + 0 + + + Bottom + + + 2, 521 + + + 2, 2, 2, 2 + + + 153, 17 + + + 2 + + + F5: Filter | F6: List | Enter: add + + + lblHotkeyRight + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpInputList + + + 1 + + + 5, 5 + + + 263, 23 + + + 5 + + + << Add all (copy current channel setup) + + + Filter for current channel in left list + + + btnCloneChannelList + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + panelControl3 + + + 0 + + + Tahoma, 8.25pt, style=Strikeout + + + 65, 34 + + + 54, 23 + + + 2 + + + Filter + + + Reset filter + + + btnClearRightFilter + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + panelControl3 + + + 1 + + + 5, 34 + + + 54, 23 + + + 1 + + + < Filter + + + Filter for current channel in left list + + + btnSyncFromRight + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + panelControl3 + + + 2 + + + 136, 36 + + + 23, 23 + + + 4 + + + << + + + Add selected channels + + + btnAdd + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + panelControl3 + + + 3 + + + Top + + + 2, 21 + + + 1130, 64 + + + 0 + + + panelControl3 + + + DevExpress.XtraEditors.PanelControl, DevExpress.Utils.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + grpInputList + + + 2 + + + Fill + + + 0, 0 + + + 1134, 540 + + + 0 + + + All channels + + + grpInputList + + + DevExpress.XtraEditors.GroupControl, DevExpress.Utils.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + splitContainerControl1.Panel2 + + + 0 + + + Panel2 + + + 1474, 540 + + + 5 + + + splitContainerControl1 + + + splitContainerControl1 + + + DevExpress.XtraEditors.SplitContainerControl, DevExpress.Utils.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 0 + + + 194, 17 + + + 783, 17 + + \ No newline at end of file diff --git a/ChanSort.Ui/Program.cs b/ChanSort.Ui/Program.cs new file mode 100644 index 0000000..aabb30b --- /dev/null +++ b/ChanSort.Ui/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Windows.Forms; + +namespace ChanSort.Ui +{ + static class Program + { + internal static bool ChangeLanguage; + + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + do + { + ChangeLanguage = false; + Application.Run(new MainForm()); + } while (ChangeLanguage); + } + } +} diff --git a/ChanSort.Ui/Properties/AssemblyInfo.cs b/ChanSort.Ui/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d723c41 --- /dev/null +++ b/ChanSort.Ui/Properties/AssemblyInfo.cs @@ -0,0 +1,38 @@ +using System.Reflection; +using System.Resources; +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("ChanSortUI")] +[assembly: AssemblyDescription("TV Channel Sort Utility")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ChanSort")] +[assembly: AssemblyCopyright("Copyright © 2012")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: NeutralResourcesLanguage("en-US")] + +// 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("207c2719-5641-4141-917e-e76b7c3b952a")] + +// 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/ChanSort.Ui/Properties/DataSources/ChannelInfo.datasource b/ChanSort.Ui/Properties/DataSources/ChannelInfo.datasource new file mode 100644 index 0000000..53208e9 --- /dev/null +++ b/ChanSort.Ui/Properties/DataSources/ChannelInfo.datasource @@ -0,0 +1,10 @@ + + + + GUI.ChannelInfo, GUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + \ No newline at end of file diff --git a/ChanSort.Ui/Properties/DataSources/System.Text.EncodingInfo.datasource b/ChanSort.Ui/Properties/DataSources/System.Text.EncodingInfo.datasource new file mode 100644 index 0000000..ca71191 --- /dev/null +++ b/ChanSort.Ui/Properties/DataSources/System.Text.EncodingInfo.datasource @@ -0,0 +1,10 @@ + + + + System.Text.EncodingInfo, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + \ No newline at end of file diff --git a/ChanSort.Ui/Properties/Resources.Designer.cs b/ChanSort.Ui/Properties/Resources.Designer.cs new file mode 100644 index 0000000..97bccaa --- /dev/null +++ b/ChanSort.Ui/Properties/Resources.Designer.cs @@ -0,0 +1,337 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.586 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ChanSort.Ui.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ChanSort.Ui.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + internal static System.Drawing.Bitmap Donate { + get { + object obj = ResourceManager.GetObject("Donate", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized string similar to Delete all channel data. + /// + internal static string MainForm_btnResetChannelData_Click_Caption { + get { + return ResourceManager.GetString("MainForm_btnResetChannelData_Click_Caption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to WARNING: All analog, DVB-C/T and DVB-S channel and transponder data will be deleted. + ///You will have to run a full channel scan after loading this file into your TV. + ///Proceed?. + /// + internal static string MainForm_btnResetChannelData_Click_Message { + get { + return ResourceManager.GetString("MainForm_btnResetChannelData_Click_Message", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Supported Files|{0}|All Files (*.*)|*. + /// + internal static string MainForm_FileDialog_OpenFileFilter { + get { + return ResourceManager.GetString("MainForm_FileDialog_OpenFileFilter", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}-Files|*{0}|All Files (*.*)|*. + /// + internal static string MainForm_FileDialog_SaveFileFilter { + get { + return ResourceManager.GetString("MainForm_FileDialog_SaveFileFilter", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The input file contains multiple records that use the same + ///program number. It is possible that the TV will not accept + ///the changes made by ChanSort. + ///This is typically caused by running a manual transponder scan. + ///It is recommended to use a clean input file for any modifications. + ///To do that, turn Hotel Mode OFF, reset the TV to + ///factory defaults, run a new blind channel scan and turn + ///Hotel Mode back ON, then export a new clean TLL file. + ///. + /// + internal static string MainForm_LoadFiles_DupeWarningMsg { + get { + return ResourceManager.GetString("MainForm_LoadFiles_DupeWarningMsg", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Error loading file. + /// + internal static string MainForm_LoadFiles_IOException { + get { + return ResourceManager.GetString("MainForm_LoadFiles_IOException", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Data validation. + /// + internal static string MainForm_LoadFiles_ValidationWarningCap { + get { + return ResourceManager.GetString("MainForm_LoadFiles_ValidationWarningCap", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The verification of the file content showed some anomalies. Possible causes are: + ///- The TV itself created a mess in the channel lists (which happens frequently). + ///- The file format is partially unknown (e.g. unknown TV model or firmware). + ///- The file has been edited with a broken program version. + ///- ChanSort's validation rules are based on wrong assumptions. + ///You can continue editing, but it is possibile that your TV will reject the changes.. + /// + internal static string MainForm_LoadFiles_ValidationWarningMsg { + get { + return ResourceManager.GetString("MainForm_LoadFiles_ValidationWarningMsg", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to An error occured while loading the TV's data file: + ///{0}. + /// + internal static string MainForm_LoadTll_Exception { + get { + return ResourceManager.GetString("MainForm_LoadTll_Exception", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No plugin found to read/write {0} files.. + /// + internal static string MainForm_LoadTll_SerializerNotFound { + get { + return ResourceManager.GetString("MainForm_LoadTll_SerializerNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Quell-TLL konnte nicht gefunden werden: + ///'{0}'. + /// + internal static string MainForm_LoadTll_SourceTllNotFound { + get { + return ResourceManager.GetString("MainForm_LoadTll_SourceTllNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are about to restore the backup file. All changes will be lost! + ///Do you want to continue?. + /// + internal static string MainForm_miRestoreOriginal_ItemClick_Confirm { + get { + return ResourceManager.GetString("MainForm_miRestoreOriginal_ItemClick_Confirm", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No backup file found: {0}. + /// + internal static string MainForm_miRestoreOriginal_ItemClick_NoBackup { + get { + return ResourceManager.GetString("MainForm_miRestoreOriginal_ItemClick_NoBackup", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to copy .bak file to {0}. + /// + internal static string MainForm_miRestoreOriginal_Message { + get { + return ResourceManager.GetString("MainForm_miRestoreOriginal_Message", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Data modified. + /// + internal static string MainForm_PromptSaveAndContinue_Caption { + get { + return ResourceManager.GetString("MainForm_PromptSaveAndContinue_Caption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Do you want to save the changes?. + /// + internal static string MainForm_PromptSaveAndContinue_Message { + get { + return ResourceManager.GetString("MainForm_PromptSaveAndContinue_Message", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Restore order from channel scan. + /// + internal static string MainForm_RestoreScanOrder_Caption { + get { + return ResourceManager.GetString("MainForm_RestoreScanOrder_Caption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to All custom storing will be lost. + ///Are you sure you want to restore the order from the channel scan?. + /// + internal static string MainForm_RestoreScanOrder_Message { + get { + return ResourceManager.GetString("MainForm_RestoreScanOrder_Message", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There was an error saving the file. Please make sure that + ///- you have write permission on the file + ///- the file is not open in another program + /// + ///The error message is: + ///. + /// + internal static string MainForm_SaveFiles_ErrorMsg { + get { + return ResourceManager.GetString("MainForm_SaveFiles_ErrorMsg", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to File write error. + /// + internal static string MainForm_SaveFiles_ErrorTitle { + get { + return ResourceManager.GetString("MainForm_SaveFiles_ErrorTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to An error occured while writing the TV data file: + ///{0}. + /// + internal static string MainForm_SaveTllFile_Exception { + get { + return ResourceManager.GetString("MainForm_SaveTllFile_Exception", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sorted TV data file was created successfully.. + /// + internal static string MainForm_SaveTllFile_Success { + get { + return ResourceManager.GetString("MainForm_SaveTllFile_Success", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ChanSort Reference List|*.csv|SamToolBox Reference List|*.chl|All Reference Lists|*.csv;*.chl. + /// + internal static string MainForm_ShowOpenReferenceFileDialog_Filter { + get { + return ResourceManager.GetString("MainForm_ShowOpenReferenceFileDialog_Filter", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Open Reference List. + /// + internal static string MainForm_ShowOpenReferenceFileDialog_Title { + get { + return ResourceManager.GetString("MainForm_ShowOpenReferenceFileDialog_Title", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to An unexpected error occured: + ///{0}. + /// + internal static string MainForm_TryExecute_Exception { + get { + return ResourceManager.GetString("MainForm_TryExecute_Exception", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to <html> + ///<body> + ///<p style="font-family:Arial;font-size:12pt">PayPal donation page is being opened...</p> + ///<p></p> + ///<p style="font-family:Arial;font-size:12pt">PayPal Spendenseite wird ge&ouml;ffnet...</p> + ///<form action="https://www.paypal.com/cgi-bin/webscr" method="post"> + ///<input type="hidden" name="cmd" value="_s-xclick"> + ///<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----MIIHVwYJKoZIhvcNAQcEoIIHSDCCB0QCAQExggEwMIIBLAIBADCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBW [rest of string was truncated]";. + /// + internal static string paypal_button { + get { + return ResourceManager.GetString("paypal_button", resourceCulture); + } + } + } +} diff --git a/ChanSort.Ui/Properties/Resources.de.Designer.cs b/ChanSort.Ui/Properties/Resources.de.Designer.cs new file mode 100644 index 0000000..e69de29 diff --git a/ChanSort.Ui/Properties/Resources.de.resx b/ChanSort.Ui/Properties/Resources.de.resx new file mode 100644 index 0000000..9bf5b0f --- /dev/null +++ b/ChanSort.Ui/Properties/Resources.de.resx @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Quell-TLL konnte nicht gefunden werden: +'{0}' + + + Beim Auslesen der TLL-Datei trat ein Fehler auf: +{0} + + + Unterstützte Dateien|{0}|Alle Dateien (*.*)|* + + + {0}-Dateien|*{0}|Alle Dateien (*.*)|* + + + Beim Ausführen der Aktion trat ein Programmfehler auf: +{0} + + + Beim Schreiben der TLL-Datei trat ein Fehler auf: +{0} + + + Die sortierte TLL-Datei wurde erfolgreich erstellt. + + + Möchten Sie die Änderungen Speichern? + + + Daten verändert + + + Es konnte kein Modul zum Lesen/Schreiben von {0}-Dateien gefunden werden. + + + Fehler beim Laden der Datei + + + Datenüberprüfung + + + Die Überprüfung des Dateiinhalts fand einige Auffälligkeiten. Mögliche Ursachen sind: +- Der Fernseher hat seine Senderlisten versaut (was häufig vorkommt). +- Das Dateiformat ist teilweise unbekannt (unbekanntes Modell oder Firmware). +- Die Datei wurde mit einer defekten Programmversion bearbeitet. +- Eine von ChanSort's Prüfungen geht von einer falschen Annahme aus. +Sie können mit der Bearbeitung fortfahren, es ist aber möglich, dass Ihr Fernsehgerät die Änderungen nicht annimmt. + + + Die händische Sortierung wird überschrieben. +Wollen Sie wirklich die Reihenfolge des Sendersuchlaufs wiederherstellen? + + + Reihenfolge des Sendersuchlaufs wiederherstellen + + + Die Eingabedatei enthält mehrere Einträge die der +gleichen Programmnummer zugeordnet sind. Es ist möglich, +dass das Fernsehgerät die von ChanSort durchgeführten +Änderungen nicht akzeptiert. +Eine typische Ursache für diese Situation ist ein +manueller Transponderscan. +Es wird empfohlen, für die Bearbeitung eine saubere +Ausgangsdatei zu verwenden. Dazu schalten Sie zunächst +den Hotel-Modus AUS, daraufhin können Sie die +Werkseinstellungen wiederherstellen und einen +Sender-Blindsuchlauf ausführen. Anschließend aktivieren +Sie bitte den den Hotel-Modus wieder und exportieren +die Senderliste erneut auf einen USB-Stick. + + + + ACHTUNG: Alle analogen, DVB-C/T und DVB-S Sender- und Transponderdaten werden gelöscht. +Nach dem Laden der Datei in den Fernseher ist ein vollständer Suchlauf notwendig. +Wollen Sie fortsetzen? + + + Senderinformationen löschen + + + Die .bak Datei konnte nicht nach {0} kopiert werden + + + Sicherheitskopie wurde nicht gefunden: {0} + + + Sie sind dabei die Sicherheitskopie wiederherzustellen. Sämtliche Änderungen gehen verloren! +Möchten Sie fortfahren? + + + Referenzliste öffnen + + + ChanSort Referenzliste (*.csv)|*.csv|SamToolBox Referenzliste|*.chl|Alle Referenzlisten|*.csv;*.chl + + + + ..\Resources\btn_donateCC_LG_de.gif;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + Schreibfehler + + + Beim Schreiben der Datei trat ein Fehler auf. Bitte stellen Sie sicher dass +- Sie Schreibrechte auf die Datei besitzen +- die Datei in keinem anderen Programm geöffnet ist + +Die Fehlermeldung lautet: + + + \ No newline at end of file diff --git a/ChanSort.Ui/Properties/Resources.resx b/ChanSort.Ui/Properties/Resources.resx new file mode 100644 index 0000000..0d7abfc --- /dev/null +++ b/ChanSort.Ui/Properties/Resources.resx @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Quell-TLL konnte nicht gefunden werden: +'{0}' + + + An error occured while loading the TV's data file: +{0} + + + Supported Files|{0}|All Files (*.*)|* + + + {0}-Files|*{0}|All Files (*.*)|* + + + An unexpected error occured: +{0} + + + An error occured while writing the TV data file: +{0} + + + Sorted TV data file was created successfully. + + + Do you want to save the changes? + + + Data modified + + + No plugin found to read/write {0} files. + + + Error loading file + + + The verification of the file content showed some anomalies. Possible causes are: +- The TV itself created a mess in the channel lists (which happens frequently). +- The file format is partially unknown (e.g. unknown TV model or firmware). +- The file has been edited with a broken program version. +- ChanSort's validation rules are based on wrong assumptions. +You can continue editing, but it is possibile that your TV will reject the changes. + + + Data validation + + + All custom storing will be lost. +Are you sure you want to restore the order from the channel scan? + + + Restore order from channel scan + + + The input file contains multiple records that use the same +program number. It is possible that the TV will not accept +the changes made by ChanSort. +This is typically caused by running a manual transponder scan. +It is recommended to use a clean input file for any modifications. +To do that, turn Hotel Mode OFF, reset the TV to +factory defaults, run a new blind channel scan and turn +Hotel Mode back ON, then export a new clean TLL file. + + + + WARNING: All analog, DVB-C/T and DVB-S channel and transponder data will be deleted. +You will have to run a full channel scan after loading this file into your TV. +Proceed? + + + Delete all channel data + + + Unable to copy .bak file to {0} + + + No backup file found: {0} + + + You are about to restore the backup file. All changes will be lost! +Do you want to continue? + + + Open Reference List + + + ChanSort Reference List|*.csv|SamToolBox Reference List|*.chl|All Reference Lists|*.csv;*.chl + + + + ..\Resources\btn_donateCC_LG.gif;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + + ..\Resources\paypal-button.txt;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + + There was an error saving the file. Please make sure that +- you have write permission on the file +- the file is not open in another program + +The error message is: + + + + File write error + + \ No newline at end of file diff --git a/ChanSort.Ui/Properties/Settings.Designer.cs b/ChanSort.Ui/Properties/Settings.Designer.cs new file mode 100644 index 0000000..f033d21 --- /dev/null +++ b/ChanSort.Ui/Properties/Settings.Designer.cs @@ -0,0 +1,266 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.586 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ChanSort.Ui.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string InputTLL { + get { + return ((string)(this["InputTLL"])); + } + set { + this["InputTLL"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("0")] + public int InputListRowHandle { + get { + return ((int)(this["InputListRowHandle"])); + } + set { + this["InputListRowHandle"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("0")] + public int OutputListRowHandle { + get { + return ((int)(this["OutputListRowHandle"])); + } + set { + this["OutputListRowHandle"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string OutputListLayout { + get { + return ((string)(this["OutputListLayout"])); + } + set { + this["OutputListLayout"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string InputFilterName { + get { + return ((string)(this["InputFilterName"])); + } + set { + this["InputFilterName"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string InputFilterOldSlot { + get { + return ((string)(this["InputFilterOldSlot"])); + } + set { + this["InputFilterOldSlot"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string InputFilterCrypt { + get { + return ((string)(this["InputFilterCrypt"])); + } + set { + this["InputFilterCrypt"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string InputFilterNewSlot { + get { + return ((string)(this["InputFilterNewSlot"])); + } + set { + this["InputFilterNewSlot"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string InputFilterChannel { + get { + return ((string)(this["InputFilterChannel"])); + } + set { + this["InputFilterChannel"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string InputFilterUid { + get { + return ((string)(this["InputFilterUid"])); + } + set { + this["InputFilterUid"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string OutputFilterName { + get { + return ((string)(this["OutputFilterName"])); + } + set { + this["OutputFilterName"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string Language { + get { + return ((string)(this["Language"])); + } + set { + this["Language"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string OutputFilterNewSlot { + get { + return ((string)(this["OutputFilterNewSlot"])); + } + set { + this["OutputFilterNewSlot"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string Encoding { + get { + return ((string)(this["Encoding"])); + } + set { + this["Encoding"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool HideLeftList { + get { + return ((bool)(this["HideLeftList"])); + } + set { + this["HideLeftList"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("0, 0")] + public global::System.Drawing.Size WindowSize { + get { + return ((global::System.Drawing.Size)(this["WindowSize"])); + } + set { + this["WindowSize"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string InputGridLayoutAnalog { + get { + return ((string)(this["InputGridLayoutAnalog"])); + } + set { + this["InputGridLayoutAnalog"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string InputGridLayoutDvbCT { + get { + return ((string)(this["InputGridLayoutDvbCT"])); + } + set { + this["InputGridLayoutDvbCT"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string InputGridLayoutDvbS { + get { + return ((string)(this["InputGridLayoutDvbS"])); + } + set { + this["InputGridLayoutDvbS"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("0")] + public int LeftPanelWidth { + get { + return ((int)(this["LeftPanelWidth"])); + } + set { + this["LeftPanelWidth"] = value; + } + } + } +} diff --git a/ChanSort.Ui/Properties/Settings.settings b/ChanSort.Ui/Properties/Settings.settings new file mode 100644 index 0000000..ecb339a --- /dev/null +++ b/ChanSort.Ui/Properties/Settings.settings @@ -0,0 +1,66 @@ + + + + + + + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + + + 0, 0 + + + + + + + + + + + + 0 + + + \ No newline at end of file diff --git a/ChanSort.Ui/Properties/licenses.licx b/ChanSort.Ui/Properties/licenses.licx new file mode 100644 index 0000000..e9727a2 --- /dev/null +++ b/ChanSort.Ui/Properties/licenses.licx @@ -0,0 +1,7 @@ +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.CheckEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.ButtonEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraSplashScreen.SplashScreenManager, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraBars.BarManager, DevExpress.XtraBars.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/ChanSort.Ui/Resources/Donate.bmp b/ChanSort.Ui/Resources/Donate.bmp new file mode 100644 index 0000000..55516c7 Binary files /dev/null and b/ChanSort.Ui/Resources/Donate.bmp differ diff --git a/ChanSort.Ui/Resources/btn_donateCC_LG.gif b/ChanSort.Ui/Resources/btn_donateCC_LG.gif new file mode 100644 index 0000000..ab78d8b Binary files /dev/null and b/ChanSort.Ui/Resources/btn_donateCC_LG.gif differ diff --git a/ChanSort.Ui/Resources/btn_donateCC_LG_de.gif b/ChanSort.Ui/Resources/btn_donateCC_LG_de.gif new file mode 100644 index 0000000..73fbd66 Binary files /dev/null and b/ChanSort.Ui/Resources/btn_donateCC_LG_de.gif differ diff --git a/ChanSort.Ui/Resources/paypal-button.txt b/ChanSort.Ui/Resources/paypal-button.txt new file mode 100644 index 0000000..22a41f1 --- /dev/null +++ b/ChanSort.Ui/Resources/paypal-button.txt @@ -0,0 +1,19 @@ + + +

PayPal donation page is being opened...

+

+

PayPal Spendenseite wird geöffnet...

+
+ + + + +
+ + + \ No newline at end of file diff --git a/ChanSort.Ui/Settings.cs b/ChanSort.Ui/Settings.cs new file mode 100644 index 0000000..9d10655 --- /dev/null +++ b/ChanSort.Ui/Settings.cs @@ -0,0 +1,28 @@ +namespace ChanSort.Ui.Properties { + + + // This class allows you to handle specific events on the settings class: + // The SettingChanging event is raised before a setting's value is changed. + // The PropertyChanged event is raised after a setting's value is changed. + // The SettingsLoaded event is raised after the setting values are loaded. + // The SettingsSaving event is raised before the setting values are saved. + internal sealed partial class Settings { + + public Settings() { + // // To add event handlers for saving and changing settings, uncomment the lines below: + // + // this.SettingChanging += this.SettingChangingEventHandler; + // + // this.SettingsSaving += this.SettingsSavingEventHandler; + // + } + + private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) { + // Add code to handle the SettingChangingEvent event here. + } + + private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) { + // Add code to handle the SettingsSaving event here. + } + } +} diff --git a/ChanSort.Ui/WaitForm1.Designer.cs b/ChanSort.Ui/WaitForm1.Designer.cs new file mode 100644 index 0000000..0d30284 --- /dev/null +++ b/ChanSort.Ui/WaitForm1.Designer.cs @@ -0,0 +1,80 @@ +namespace ChanSort.Ui +{ + partial class WaitForm1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WaitForm1)); + this.progressPanel1 = new DevExpress.XtraWaitForm.ProgressPanel(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.tableLayoutPanel1.SuspendLayout(); + this.SuspendLayout(); + // + // progressPanel1 + // + resources.ApplyResources(this.progressPanel1, "progressPanel1"); + this.progressPanel1.Appearance.BackColor = ((System.Drawing.Color)(resources.GetObject("progressPanel1.Appearance.BackColor"))); + this.progressPanel1.Appearance.GradientMode = ((System.Drawing.Drawing2D.LinearGradientMode)(resources.GetObject("progressPanel1.Appearance.GradientMode"))); + this.progressPanel1.Appearance.Image = ((System.Drawing.Image)(resources.GetObject("progressPanel1.Appearance.Image"))); + this.progressPanel1.Appearance.Options.UseBackColor = true; + this.progressPanel1.AppearanceCaption.Font = ((System.Drawing.Font)(resources.GetObject("resource.Font"))); + this.progressPanel1.AppearanceCaption.GradientMode = ((System.Drawing.Drawing2D.LinearGradientMode)(resources.GetObject("resource.GradientMode"))); + this.progressPanel1.AppearanceCaption.Image = ((System.Drawing.Image)(resources.GetObject("resource.Image"))); + this.progressPanel1.AppearanceCaption.Options.UseFont = true; + this.progressPanel1.AppearanceDescription.Font = ((System.Drawing.Font)(resources.GetObject("resource.Font1"))); + this.progressPanel1.AppearanceDescription.GradientMode = ((System.Drawing.Drawing2D.LinearGradientMode)(resources.GetObject("resource.GradientMode1"))); + this.progressPanel1.AppearanceDescription.Image = ((System.Drawing.Image)(resources.GetObject("resource.Image1"))); + this.progressPanel1.AppearanceDescription.Options.UseFont = true; + this.progressPanel1.ImageHorzOffset = 20; + this.progressPanel1.Name = "progressPanel1"; + // + // tableLayoutPanel1 + // + resources.ApplyResources(this.tableLayoutPanel1, "tableLayoutPanel1"); + this.tableLayoutPanel1.BackColor = System.Drawing.Color.Transparent; + this.tableLayoutPanel1.Controls.Add(this.progressPanel1, 0, 0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + // + // WaitForm1 + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.tableLayoutPanel1); + this.DoubleBuffered = true; + this.Name = "WaitForm1"; + this.tableLayoutPanel1.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DevExpress.XtraWaitForm.ProgressPanel progressPanel1; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + } +} diff --git a/ChanSort.Ui/WaitForm1.cs b/ChanSort.Ui/WaitForm1.cs new file mode 100644 index 0000000..30a14f0 --- /dev/null +++ b/ChanSort.Ui/WaitForm1.cs @@ -0,0 +1,37 @@ +using System; +using DevExpress.XtraWaitForm; + +namespace ChanSort.Ui +{ + public partial class WaitForm1 : WaitForm + { + public WaitForm1() + { + InitializeComponent(); + this.progressPanel1.AutoHeight = true; + } + + #region Overrides + + public override void SetCaption(string caption) + { + base.SetCaption(caption); + this.progressPanel1.Caption = caption; + } + public override void SetDescription(string description) + { + base.SetDescription(description); + this.progressPanel1.Description = description; + } + public override void ProcessCommand(Enum cmd, object arg) + { + base.ProcessCommand(cmd, arg); + } + + #endregion + + public enum WaitFormCommand + { + } + } +} \ No newline at end of file diff --git a/ChanSort.Ui/WaitForm1.de.resx b/ChanSort.Ui/WaitForm1.de.resx new file mode 100644 index 0000000..8b49001 --- /dev/null +++ b/ChanSort.Ui/WaitForm1.de.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitte um Geduld + + + TV Senderliste wird gespeichert... + + \ No newline at end of file diff --git a/ChanSort.Ui/WaitForm1.resx b/ChanSort.Ui/WaitForm1.resx new file mode 100644 index 0000000..b297549 --- /dev/null +++ b/ChanSort.Ui/WaitForm1.resx @@ -0,0 +1,256 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + True + + + Generating TV data file... + + + + GrowAndShrink + + + + 6, 13 + + + Microsoft Sans Serif, 12pt + + + True + + + progressPanel1 + + + 0, 14, 0, 14 + + + DevExpress.XtraWaitForm.WaitForm, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + WaitForm1 + + + 1 + + + + + + + 0, 3, 0, 3 + + + + + + 246, 0 + + + Fill + + + 1 + + + Transparent + + + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="progressPanel1" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /></Controls><Columns Styles="Absolute,246" /><Rows Styles="Percent,100" /></TableLayoutSettings> + + + $this + + + 246, 73 + + + Fill + + + Manual + + + 0, 17 + + + 0, 0 + + + tableLayoutPanel1 + + + GrowAndShrink + + + progressPanel1 + + + 0 + + + + + + 0 + + + 246, 73 + + + 246, 39 + + + 0 + + + Horizontal + + + DevExpress.XtraWaitForm.ProgressPanel, DevExpress.XtraEditors.v12.2, Version=12.2.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + Horizontal + + + Microsoft Sans Serif, 8.25pt + + + System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 1 + + + Form1 + + + Horizontal + + + tableLayoutPanel1 + + + True + + \ No newline at end of file diff --git a/ChanSort.Ui/app.config b/ChanSort.Ui/app.config new file mode 100644 index 0000000..24048ff --- /dev/null +++ b/ChanSort.Ui/app.config @@ -0,0 +1,114 @@ + + + + +
+
+ + + + + + + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + + + 0, 0 + + + + + + + + + + + + 0 + + + + + + + + + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ChanSort.Ui/app.ico b/ChanSort.Ui/app.ico new file mode 100644 index 0000000..9c1ff6a Binary files /dev/null and b/ChanSort.Ui/app.ico differ diff --git a/ChanSort.Ui/icons/flag_austria.png b/ChanSort.Ui/icons/flag_austria.png new file mode 100644 index 0000000..3049cab Binary files /dev/null and b/ChanSort.Ui/icons/flag_austria.png differ diff --git a/ChanSort.Ui/icons/flag_germany.png b/ChanSort.Ui/icons/flag_germany.png new file mode 100644 index 0000000..906cb60 Binary files /dev/null and b/ChanSort.Ui/icons/flag_germany.png differ diff --git a/ChanSort.Ui/icons/flag_great_britain.png b/ChanSort.Ui/icons/flag_great_britain.png new file mode 100644 index 0000000..317aacf Binary files /dev/null and b/ChanSort.Ui/icons/flag_great_britain.png differ diff --git a/ChanSort.sdf b/ChanSort.sdf new file mode 100644 index 0000000..dccf58d Binary files /dev/null and b/ChanSort.sdf differ diff --git a/ChanSort.sln b/ChanSort.sln new file mode 100644 index 0000000..45f19d3 --- /dev/null +++ b/ChanSort.sln @@ -0,0 +1,53 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChanSort.Ui", "ChanSort.Ui\ChanSort.Ui.csproj", "{5FAFDABC-A52F-498C-BD2F-AFFC4119797A}" + ProjectSection(ProjectDependencies) = postProject + {A1C9A98D-368A-44E8-9B7F-7EACA46C9EC5} = {A1C9A98D-368A-44E8-9B7F-7EACA46C9EC5} + {E972D8A1-2F5F-421C-AC91-CFF45E5191BE} = {E972D8A1-2F5F-421C-AC91-CFF45E5191BE} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChanSort.Api", "ChanSort.Api\ChanSort.Api.csproj", "{DCCFFA08-472B-4D17-BB90-8F513FC01392}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChanSort.Plugin.TllFile", "ChanSort.Plugin.TllFile\ChanSort.Plugin.TllFile.csproj", "{E972D8A1-2F5F-421C-AC91-CFF45E5191BE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{67AED502-8AEB-45F2-9B95-AC42B6A5D2C4}" + ProjectSection(SolutionItems) = preProject + FileFormat.docx = FileFormat.docx + readme.txt = readme.txt + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Plugin.TllFile", "Test.Plugin.TllFile\Test.Plugin.TllFile.csproj", "{68CFCB2F-B52A-43A1-AA5C-5D64A1D655D2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChanSort.Plugin.ScmFile", "ChanSort.Plugin.ScmFile\ChanSort.Plugin.ScmFile.csproj", "{A1C9A98D-368A-44E8-9B7F-7EACA46C9EC5}" +EndProject +Global + GlobalSection(TestCaseManagementSettings) = postSolution + CategoryFile = ChanSort1.vsmdi + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5FAFDABC-A52F-498C-BD2F-AFFC4119797A}.Debug|x86.ActiveCfg = Debug|x86 + {5FAFDABC-A52F-498C-BD2F-AFFC4119797A}.Debug|x86.Build.0 = Debug|x86 + {5FAFDABC-A52F-498C-BD2F-AFFC4119797A}.Release|x86.ActiveCfg = Release|x86 + {5FAFDABC-A52F-498C-BD2F-AFFC4119797A}.Release|x86.Build.0 = Release|x86 + {DCCFFA08-472B-4D17-BB90-8F513FC01392}.Debug|x86.ActiveCfg = Debug|x86 + {DCCFFA08-472B-4D17-BB90-8F513FC01392}.Debug|x86.Build.0 = Debug|x86 + {DCCFFA08-472B-4D17-BB90-8F513FC01392}.Release|x86.ActiveCfg = Release|Any CPU + {E972D8A1-2F5F-421C-AC91-CFF45E5191BE}.Debug|x86.ActiveCfg = Debug|x86 + {E972D8A1-2F5F-421C-AC91-CFF45E5191BE}.Debug|x86.Build.0 = Debug|x86 + {E972D8A1-2F5F-421C-AC91-CFF45E5191BE}.Release|x86.ActiveCfg = Release|Any CPU + {68CFCB2F-B52A-43A1-AA5C-5D64A1D655D2}.Debug|x86.ActiveCfg = Debug|x86 + {68CFCB2F-B52A-43A1-AA5C-5D64A1D655D2}.Debug|x86.Build.0 = Debug|x86 + {68CFCB2F-B52A-43A1-AA5C-5D64A1D655D2}.Release|x86.ActiveCfg = Release|Any CPU + {A1C9A98D-368A-44E8-9B7F-7EACA46C9EC5}.Debug|x86.ActiveCfg = Debug|x86 + {A1C9A98D-368A-44E8-9B7F-7EACA46C9EC5}.Debug|x86.Build.0 = Debug|x86 + {A1C9A98D-368A-44E8-9B7F-7EACA46C9EC5}.Release|x86.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/DLL/ICSharpCode.SharpZipLib.dll b/DLL/ICSharpCode.SharpZipLib.dll new file mode 100644 index 0000000..fe643eb Binary files /dev/null and b/DLL/ICSharpCode.SharpZipLib.dll differ diff --git a/Test.Plugin.TllFile/Properties/AssemblyInfo.cs b/Test.Plugin.TllFile/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b51f10e --- /dev/null +++ b/Test.Plugin.TllFile/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +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("Test.Plugin.TllFile")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Test.Plugin.TllFile")] +[assembly: AssemblyCopyright("Copyright © 2012")] +[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("d07e10d4-86d9-47c5-adee-b03032f1213d")] + +// 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.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Test.Plugin.TllFile/Test.Plugin.TllFile.csproj b/Test.Plugin.TllFile/Test.Plugin.TllFile.csproj new file mode 100644 index 0000000..e53d418 --- /dev/null +++ b/Test.Plugin.TllFile/Test.Plugin.TllFile.csproj @@ -0,0 +1,93 @@ + + + + Debug + AnyCPU + + + 2.0 + {68CFCB2F-B52A-43A1-AA5C-5D64A1D655D2} + Library + Properties + Test.Plugin.TllFile + Test.Plugin.TllFile + v3.5 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + ..\Debug\ + DEBUG;TRACE + full + x86 + prompt + false + true + false + true + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + false + + + + + + 3.5 + + + + + False + + + + + + + + + {DCCFFA08-472B-4D17-BB90-8F513FC01392} + ChanSort.Api + True + + + {E972D8A1-2F5F-421C-AC91-CFF45E5191BE} + ChanSort.Plugin.TllFile + True + + + + + \ No newline at end of file diff --git a/Test.Plugin.TllFile/UnitTest1.cs b/Test.Plugin.TllFile/UnitTest1.cs new file mode 100644 index 0000000..67270ec --- /dev/null +++ b/Test.Plugin.TllFile/UnitTest1.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using ChanSort.Plugin.TllFile; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Test.Plugin.TllFile +{ + [TestClass] + public class UnitTest1 + { + #region class ExpectedData + public class ExpectedData + { + public readonly string File; + public readonly int AnalogChannels; + public readonly int DtvChannels; + public readonly int SatChannels; + public readonly int DtvRadio; + public readonly int SatRadio; + + public ExpectedData(string file, int analog, int dtv, int sat, int dtvRadio, int satRadio) + { + this.File = file; + this.AnalogChannels = analog; + this.DtvChannels = dtv; + this.SatChannels = sat; + this.DtvRadio = dtvRadio; + this.SatRadio = satRadio; + } + } + #endregion + + private readonly Dictionary expectedData = new Dictionary(); + + #region ctor() + public UnitTest1() + { + var expected = new [] { + new ExpectedData(@"opel\xx2350D-PZM00001.TLL", 31, 345, 0, 89, 0), // 164/- + new ExpectedData(@"defycgn\xxLH4010-ZD99970.TLL", 34, 280, 0, 129, 0), // 164/- + new ExpectedData(@"karlv\xxLD750-ZA00001.TLL", 30, 248, 0, 104, 0), // 176/- + new ExpectedData(@"JLevi\xxLE5500-ZA00002.TLL", 36, 0, 0,0, 0), // 176/- + new ExpectedData(@"chlabnet\xxLK450-ZB00001.TLL", 34, 310, 0, 128, 0), // 176/- + new ExpectedData(@"Stabilo\xxLW4500-ZB00001.TLL", 31 ,338, 0, 34, 0), // 176/- + new ExpectedData(@"MarioAntonioLiptaj\xxPT353-ZA00001.TLL", 50, 123, 0, 13, 0), // 180/- + new ExpectedData(@"Muffix\xxLW5500-ZE00001.TLL", 34, 290, 0, 125, 0), // 184/- + new ExpectedData(@"FranzSteinert\xxCS460S-ZA00001.TLL", 0, 0, 1261, 0, 200), // ?/68 + new ExpectedData(@"Klausi1\xxLK950S-ZA00001.TLL", 37, 390, 2695, 150, 491), // 184/68 + new ExpectedData(@"MP3Chris2712\xxLV570S-ZB00001.TLL", 0, 12, 2895, 0, 669), // 184/68 + new ExpectedData(@"decklen\xxLW570S-ZD00001.TLL", 0, 30, 1587, 0, 339), // 184/68 + new ExpectedData(@"NeuerScan\xxLM340S-ZA00001.TLL", 34, 317, 1698, 129, 264), // 188/68 + new ExpectedData(@"wagnale\xxLM611S-ZA00001.TLL", 0, 13, 1094, 0, 191), // 188/68 + new ExpectedData(@"_Pred\xxLM620S-ZE00021.TLL", 0, 11, 1302, 0, 191), // 192/72 + }; + + foreach (var entry in expected) + this.expectedData[entry.File] = entry; + } + #endregion + + [TestMethod] + public void MetaTest() + { + } + + #region TestLoadingAllTllFilesInTestFilesDirectory() + [TestMethod] + [DeploymentItem("ChanSort.Plugin.TllFile\\ChanSort.Plugin.TllFile.ini")] + public void TestLoadingAllTllFilesInTestFilesDirectory() + { + TllFileSerializerPlugin plugin = new TllFileSerializerPlugin(); + + StringBuilder errors = new StringBuilder(); + var list = this.FindAllTllFiles(); + var models = new Dictionary(); + var firmwareSize = new Dictionary(); + foreach(var file in list) + { + if (file.Contains("GlobalClone")) + continue; + Debug.Print("Testing " + file); + try + { + var serializer = plugin.CreateSerializer(file) as TllFileSerializer; + Assert.IsNotNull(serializer, "No Serializer for " + file); + + serializer.Load(); + + var fileName = Path.GetFileName(file) ?? ""; + int idx = fileName.IndexOf("-"); + string key = idx < 0 ? fileName : fileName.Substring(0, idx); + var satChannelList = serializer.DataRoot.GetChannelList(ChanSort.Api.SignalSource.DvbS, ChanSort.Api.SignalType.Tv, false); + key += "\t" + serializer.ACTChannelLength+ + "\t"+serializer.HasDvbs+ + "\t"+serializer.SatChannelLength+ + "\t" + (satChannelList == null ? "n/a" : satChannelList.Count.ToString()); + string relPath = Path.GetFileName(Path.GetDirectoryName(file))+"\\"+fileName; + models[key] = relPath; + + var model = this.GetModel(file); + if (firmwareSize.ContainsKey(serializer.FirmwareDataLength)) + { + string x = firmwareSize[serializer.FirmwareDataLength]; + if (!x.Contains(model)) + firmwareSize[serializer.FirmwareDataLength] = x + ", " + model; + } + else + firmwareSize[serializer.FirmwareDataLength] = model; + + + + Assert.IsFalse(serializer.DataRoot.IsEmpty, "No channels loaded from " + file); + + ExpectedData exp; + key = Path.GetFileName(Path.GetDirectoryName(file)) + "\\" + Path.GetFileName(file); + this.expectedData.TryGetValue(key, out exp); + var analogTv = serializer.DataRoot.GetChannelList(ChanSort.Api.SignalSource.AnalogCT, ChanSort.Api.SignalType.Tv, false); + var dtvTv = serializer.DataRoot.GetChannelList(ChanSort.Api.SignalSource.DvbCT, ChanSort.Api.SignalType.Tv, false); + var satTv = serializer.DataRoot.GetChannelList(ChanSort.Api.SignalSource.DvbS, ChanSort.Api.SignalType.Tv, false); + if (exp != null) + { + this.expectedData.Remove(key); + Assert.AreEqual(exp.AnalogChannels, analogTv.Channels.Count, file + ": analog"); + Assert.AreEqual(exp.DtvChannels, dtvTv.Channels.Count, file + ": DTV"); + Assert.AreEqual(exp.SatChannels, satTv.Channels.Count, file + ": Sat"); + } + } + catch(Exception ex) + { + errors.AppendLine(); + errors.AppendLine(); + errors.AppendLine(file); + errors.AppendLine(ex.ToString()); + } + } + + foreach(var model in models.OrderBy(e => e.Key)) + Debug.WriteLine(model.Key + "\t"+model.Value); + + foreach (var size in firmwareSize.OrderBy(e => e.Key)) + Debug.WriteLine(size.Key + "\t" + size.Value); + + if (this.expectedData.Count > 0) + Assert.Fail("Some files were not tested: " + this.expectedData.Keys.Aggregate((prev,cur) => prev+","+cur)); + Assert.AreEqual("", errors.ToString()); + } + #endregion + + private string GetModel(string filePath) + { + string name = Path.GetFileName(filePath); + if (name.StartsWith("xx")) + { + int idx = name.IndexOf("-"); + if (idx > 0) + return name.Substring(2, idx - 2); + } + return filePath; + } + + #region Helper Methods + + private IEnumerable FindAllTllFiles() + { + string path = this.GetTestFileDirectory(); + List files = new List(); + this.FindAllTllFilesRecursively(path, files); + return files; + } + + private string GetTestFileDirectory() + { + string exeDir = Assembly.GetExecutingAssembly().Location; + while (!string.IsNullOrEmpty(exeDir)) + { + string testFileDir = Path.Combine(exeDir, "TestFiles"); + if (Directory.Exists(testFileDir)) + return testFileDir; + exeDir = Path.GetDirectoryName(exeDir); + } + throw new FileNotFoundException("No 'TestFiles' directory found"); + } + + private void FindAllTllFilesRecursively(string path, List files) + { + files.AddRange(Directory.GetFiles(path, "*.TLL")); + foreach (var dir in Directory.GetDirectories(path)) + this.FindAllTllFilesRecursively(dir, files); + } + #endregion + } +} diff --git a/makeDistribZip.cmd b/makeDistribZip.cmd new file mode 100644 index 0000000..7cd002b --- /dev/null +++ b/makeDistribZip.cmd @@ -0,0 +1,35 @@ +@echo off +set target=%cd%\..\Program +set DXversion=12.2 +mkdir "%target%" 2>nul +del /s /q "%target%\*" +copy debug\ChanSort.exe* "%target%" +copy debug\ChanSort.*.dll "%target%" +copy debug\ChanSort.*.ini "%target%" +copy debug\Lookup.csv "%target%" +copy DLL\*.dll "%target%" +mkdir "%target%\de" 2>nul +xcopy /siy debug\de "%target%\de" +copy readme.txt "%target%" +for %%f in (Utils Data XtraEditors XtraBars XtraGrid XtraLayout) do call :copyDll %%f + +cd .. +del Website\ChanSort.zip 2>nul +copy Source\readme.txt . +"c:\program files (x86)\7-Zip\7z.exe" a -tzip Website\ChanSort.zip Source -x!Source\_ReSharper* -x!Source\Debug -x!Source\TestResults -x!Source\*\obj -x!Source\ipch Program readme.txt +del readme.txt + +pause +goto:eof + +:copyDll +echo Copying DevExpress %* +set source="C:\Program Files (x86)\DevExpress\DXperience %DXversion%\Bin\Framework\DevExpress.%*.v%DXversion%.dll" +if exist %source% copy %source% "%target%" +set source="C:\Program Files (x86)\DevExpress\DXperience %DXversion%\Bin\Framework\DevExpress.%*.v%DXversion%.Core.dll" +if exist %source% copy %source% "%target%" +set source="C:\Program Files (x86)\DevExpress\DXperience %DXversion%\Bin\Framework\de\DevExpress.%*.v%DXversion%.resources.dll" +if exist %source% copy %source% "%target%\de" +set source="C:\Program Files (x86)\DevExpress\DXperience %DXversion%\Bin\Framework\de\DevExpress.%*.v%DXversion%.Core.resources.dll" +if exist %source% copy %source% "%target%\de" +goto:eof \ No newline at end of file diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..01673d5 --- /dev/null +++ b/readme.txt @@ -0,0 +1,226 @@ +ChanSort v2012-12-26 + +Allgemeines========================================================== + +!!! Die Verwendung dieses Programms erfolgt auf eigene Gefahr! Es ist +!!! mglich, dass durch die Verwendung das TV Gert beschdigt wird + +Die Vorliegende Version untersttzt folgende TV-Gerte: +LG-Electronics: Serien CS, LD, LE, LH, LM, LK, LV, LW, PM +Samsung: Serien B, C, D und E + +Eine Diskussion zum Thema "ChannelEditor" fr LG Fernseher mit nheren +Infos rund um ChanSort befindet sich hier: +http://www.lg-forum.com/lg-led-plasma-lcd-fernseher/5098-channeleditor-45.html +http://www.hifi-forum.de/viewthread-145-5061.html +http://forum.lg.de/viewtopic.php?f=16&t=5097&sid=3dbbc693bbbaef643a624b82206b4ac0&start=10 + +Systemvoraussetzungen ================================================ + +- Microsoft .NET Framework 3.5 +- fr LG TVs der Serien CS, LM und PM ist eine programmierbare Fernbedienung + ntig (z.B. Logitech Harmony 300, One-For-All URC3920, ...) + + +Benutzung ============================================================ + +LG Fernseher + +1) Zuerst muss man am Fernseher das geheime "In-Start" Men aktivieren +und dort mit dem "TV Link Loader" die Senderliste auf einen USB-Stick +speichern. + +Bei der LM-Serie (2012) bentigt man eine programmierbare Fernbedienung, da +weder die Standard-FB noch der Fernseher eine Zugangsmglichkeit bietet. +Einige Wege um in das Men zu gelangen, werden auf dieser Seite beschrieben: +http://openlgtv.org.ru/wiki/index.php/Access_hidden_service_menus_/_modes + +Gelingt es, den Infrarot-Befehl fr "In-Start" an den Fernseher zu senden, +drckt man anschlieend auf "Settings" (Original-FB) oder "Menu" (Harmony). +Dann stehen das Hotel-Men und der TV-Link-Loader zur Auswahl. + +2) Mit ChanSort die TLL Datei am USB-Stick ffnen. Dies muss immer + Die Original-Datei des TV sein und nicht eine bereits sortierte. + Falls eine gleichnamige CSV-Datei mit einer bestehenden Sortierung + existiert wird diese automatisch eingelesen. +3) Die gewnschte Senderliste zusammenstellen. Am einfachsten in der + rechten Ansicht in Spalte "Sendername" den Namen eintippen, dann in + der Liste doppelclicken. + In der Mitte kann eingestellt werden, wo in der sortierten Liste der + neue Sender landet. Dazu einen Programmplatz in der linken Liste + auswhlen und in der Mitte eventuell "Dahinter". +4) Dateien speichern + Die TLL-Datei erhlt eine 9 als erste Ziffer, um die Originaldatei + nicht zu berschreiben. +5) Senderliste auf USB Stick speichern und ber den TV Link Loader in + den Fernseher laden. + +Samsung Fernseher + + Im Men "Sender" / "Kanalliste bertragen" / "Auf USB exportieren" + +Kontakt ============================================================== + +Benutzer "Pred" auf www.lg-forum.com +Email: horst@beham.biz + + +Versionen ============================================================ + +2013-03-30 +- FIX: bei nicht-LM Gerten wurden die DVB-S Programmnummern falsch ausgelesen +- Hotelmodus/DTV-channel-update kann nun bei allen LG serien gendert werden + +2013-03-29 +- LG: Doppelt vorhandene Sender (die automatisch vom TV bei der Sendersuche + mit Lndervoreinstellung angelegt werden) werden nun automatisch gelscht. + Diese fhren am TV hufig dazu, dass Sender zufllig zwischen deren + Programmpltzen hin- und herspringen. (Bug im TV, unabhngig von ChanSort) +- LG: Sender knnen nun gelscht werden ("Nicht explizit sortierte Sender: Lschen") +- LG: ndern von Sendernamen mglich (um bei DVB-C/T/S die Namen nicht wieder + zu verlieren, muss Hotel-Mode=ein und DTV channel update="manual" sein) +- LG: Fr die LM-Serie kann nun innerhalb von ChanSort der Hotel-Modus bzw + die Senderlisten-Aktualisierung ein-/ausgeschaltet werden. + +2013-02-26 +- Neuer Bearbeitungsmodus "Tauschen" eingebaut, mit dem beim ndern der + Programmnummer die beiden Sender ihre Nummer tauschen und alle anderen + Nummern unverndert bleiben. +- Beim ffnen einer TV-Datei ohne zugehriger Referenzliste werden nun + automatisch alle Sender in die "Sortierte Liste" bernommen. +- "Speichern unter" funktioniert nun auch mit Samsung's SCM Dateien +- Wenn beim Speichern ein Fehler auftritt, wird nun auf mgliche Ursachen + hingewiesen + +2013-02-11 +- Mehrfach vorhandene Sender werden nun getrennt angezeigt, wenn sie + unterschiedlichen Programmnummern zugewiesen sind (z.B. DVB-T Empfang des + gleichen Senders ber verschiedene Sendeanlagen). +- Beim ndern der Programmnr auf eine bisher nicht verwendete Nummer werden + die Programmnummern hinter der neuen Nummer nicht mehr erhht. + +2013-02-04 +- Untersttzung fr Samsung "AstraHDPlus" Senderliste hinzugefgt +- Funktion zum bernehmen der bestehenden Senderliste in die sortierte Liste + +2013-01-22 +- Fix: Import von .chl Referenzlisten, wenn der gleiche Sendername ber + mehrere Satelliten empfangen wird und dort dem gleichen TSID zugewiesen ist. + +2013-01-16 +- Import von .chl Referenzlisten von SamToolBox +- Samsung Senderlisten zeigen nun "verschlsselt"-Info an +- FIX: Mehrfachauswahl in den Senderlisten (mit Strg/Shift + Maus/Cursortasten) +- FIX: Warnung statt Absturz bei mehrfach vergebenen Transponder-IDs (.SCM Datei) + +2013-01-15 +- Samsung Serie E wird nun untersttzt +- Favoritenliste der Samsung Serie D und E wird nun erkannt +- Samsung Modellerkennung verbessert + +2012-12-26 +- Untersttzung fr Samsung Fernseher hinzugefgt +- Funktion zum ffnen einer Referenzliste hinzugefgt +- Funktion zum kompletten Lschen der Senderlisten fr LG Fernseher +- Diverse Bugfixes + +2012-11-07 +- Anzeige von DVB Netzwerk Name und Betreiber +- Anzeige der DVB-S Transpondernummer +- Fix: Direkte Eingabe der Prog# in rechter Liste, wenn sie vorher 0 war + +2012-11-06 +- Fix: Analoge Senderliste wurde nicht korrekt gespeichert +- Fix: Hinzufgen von Sendern zu einer leeren Liste +- Setzen von Favoriten mglich +- Setzen von Sender sperren / berspringen / verstecken +- Direkte Eingabe von neuer Programmnr in den Tabellen +- Kontextmen ber rechte Maustaste + +2012-11-05 +- Fix: DVB-C/T Senderliste wurde nicht korrekt gespeichert +- Fix: Favoriten in DVB-C/T werden nun korrekt angezeigt + +2012-11-04 +- Fix: Transpondernummer und Satelliteninfo wurde falsch ausgelesen +- Mehrfach vorhandene Sender werden nun nicht mehr ausgefiltert + +2012-11-01 +- UI und internes Datenmodell komplett berarbeitet +- Getrennte Listen fr Analog, DVB-C/T, DVB-S in jeweils Radio/TV + +2012-10-30 +- Untersttzung fr LG Serie CS, LD, LE, LH und PM hinzugefgt +- Neue Serien knnen durch Anpassen einer .INI Datei hinzugefgt werden +- Automatischer Test im Sourcecode, der alle bekannten TLLs ldt +- Hilfe-Men hinzugefgt + +2012-10-29 +- Plugin zum direkten Laden/Speichern von TLLs, ohne TLLsort.exe +- Untersttzung fr LG Serie LV und LW hinzugefgt +- Sourcen verffentlicht + +2012-10-26 +- Programm umbenannt von TLLsortGUI auf ChanSort +- bersetzt in Englisch und sterreichisch +- Einstellungen werden beim Beenden/Speichern des Programms bernommen +- Ausgewhlten Zeilen in der sortierten Liste alphabetisch sortieren +- Dateinamen fr Speichern knnen gendert werden +- Untersttzung fr Plugin-DLLs fr verschiedene TV-Modelle + +2012-10-25 +- Neu: Wenn eine Gruppenzeile (Sat, Analog, CableAndTerrestic) ausgewhlt + ist, werden alle darin enthaltene Sender eingefgt bzw. entfernt. +- Bugfix: Eingabefelder fr Einfgepositionen erlauben nun keine + ungltigen (sprich zu hohe, nicht fortlaufende) Nummern mehr. + +2012-10-24 (14:52 MESZ) +- Bugfix: Fehler beim Einlesen der TLL-Datei, wenn der gleiche Sender + (sprich Uid) mehrfach enthalten war. Kann vermutlich passieren, wenn + ein Sendersuchlauf 2x durchgefhrt wurde, ohne die alten Programme zu + lschen. + +2012-10-24 (#1) +- erste Verffentlichung + +Source Code ========================================================== + +The user interface (ChanSort.Ui project) is using the commercial "WinForms" +UI component library from Developer Express. You can get a trial version +from http://www.devexpress.com/Subscriptions/DXperience/WhatsNew2012v1/winforms.xml +The trial version will periodically show popup-windows reminding you to +obtain a license. + +As long as you dont make any changes to the UI, you can exclude the +ChanSort.Ui project from the build list and copy all files from the +"Program" directory to "Source\Debug". + +Alternatively you can just compile the other projects and drop the generated +DLL-File into the "Program" folder and start ChanEdit.exe there + +Lizenz =============================================================== + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to \ No newline at end of file