private void LoadDvbS(ChannelList list, string path, string mappingName) { if (!File.Exists(path)) { return; } var data = File.ReadAllBytes(path); if (data.Length < 12) { return; } var version = chanLstBin.VersionMajor; if (version <= 11) { var checksum = BitConverter.ToUInt32(data, data.Length - 4); var crcObj = new Crc32(false, Crc32.NormalPoly); var crc = ~crcObj.CalcCrc32(data, 0, data.Length - 4); if (checksum != crc) { throw new FileLoadException("Invalid CRC32 in " + path); } } int recordSize = BitConverter.ToInt32(data, 4); int recordCount = BitConverter.ToInt32(data, 8); if (recordSize == 0 && version != 1) { recordSize = recordCount == 0 ? 0 : (data.Length - 12) / recordCount; } if (chanLstBin.VersionMajor <= 11) { // 12 bytes header, then a "next/prev" table, then the service records, then a CRC32 // the "next/prev" table is a ring-list, every entry consists of 2 ushorts with the next and previous channel, wrapping around on the ends if (data.Length != 12 + recordCount * 4 + recordCount * recordSize + 4) { throw new FileLoadException("Unsupported file content: " + path); } } this.dataFilePaths.Add(path); var dvbStringDecoder = new DvbStringDecoder(this.DefaultEncoding); var mapping = new DataMapping(this.ini.GetSection(mappingName)); mapping.SetDataPtr(data, 12 + (chanLstBin.VersionMajor <= 11 ? recordCount * 4 : 0)); for (int i = 0; i < recordCount; i++, mapping.BaseOffset += recordSize) { var ch = LoadDvbsChannel(list, mapping, i, dvbStringDecoder); this.DataRoot.AddChannel(list, ch); } }
public override void Load() { var decoder = new DvbStringDecoder(this.DefaultEncoding); var pos = 0; content = File.ReadAllBytes(this.FileName); int prevPos = 0, nextPos; while (prevPos < content.Length && content[prevPos] != 0 && (nextPos = Array.FindIndex(content, prevPos, ch => ch == (byte)'\n')) >= 0) { if (nextPos - prevPos == 0) { continue; } string line = Encoding.ASCII.GetString(content, prevPos, nextPos - prevPos); ChannelInfo channel = new Channel(pos, line, content, prevPos, nextPos - prevPos, decoder); this.DataRoot.AddChannel(this.allChannels, channel); pos++; prevPos = nextPos + 1; } // SATCODX105 files contain a \0 character to mark the end, followed by an arbitrary number or spaces (or whatever data). We'll preserve it as-is. this.trailingDataPos = prevPos; }
private bool GetRecommendedEncoding(ref Encoding encoding, out int startOffset, out int bytesPerChar) { startOffset = 0; bytesPerChar = 1; if (RawName[0] < 0x10) // single byte character sets { encoding = DvbStringDecoder.GetEncoding(RawName[0]); startOffset = 1; } else if (RawName[0] == 0x10) // prefix for 16 bit code page ID with single byte character sets { if (RawName.Length < 3) { return(false); } encoding = DvbStringDecoder.GetEncoding(0x100000 + RawName[1] * 256 + RawName[2]); startOffset = 3; } else if (RawName[0] == 0x15) // UTF-8 { encoding = Encoding.UTF8; startOffset = 1; } else if (RawName[0] < 0x20) // various 2-byte character sets { encoding = DvbStringDecoder.GetEncoding(RawName[0]); startOffset = 1; bytesPerChar = 2; } return(true); }
private void ParseNames() { mapping.SetDataPtr(this.rawData, this.baseOffset); DvbStringDecoder dec = new DvbStringDecoder(mapping.DefaultEncoding); string longName, shortName; dec.GetChannelNames(this.rawData, this.baseOffset + mapping.GetOffsets(_Name)[0], mapping.GetByte(_NameLength), out longName, out shortName); this.Name = longName; this.ShortName = shortName; }
public override void Load() { var decoder = new DvbStringDecoder(this.DefaultEncoding); var pos = 0; content = File.ReadAllBytes(this.FileName); int prevPos = 0, nextPos; while (prevPos < content.Length && (nextPos = Array.FindIndex(content, prevPos, ch => ch == (byte)'\n')) >= 0) { if (nextPos - prevPos == 0) { continue; } string line = Encoding.ASCII.GetString(content, prevPos, nextPos - prevPos); ChannelInfo channel = new Channels(pos, line, content, prevPos, nextPos - prevPos, decoder); this.DataRoot.AddChannel(this.allChannels, channel); pos++; prevPos = nextPos + 1; } }
private void InsertChannelData(DbCommand cmd, int listId) { PrepareChannelInsert(cmd); DvbStringDecoder decoder = new DvbStringDecoder(this.DefaultEncoding); DataMapping dvbsMapping = this.dvbsMappings.GetMapping(this.dvbsBlockSize); dvbsMapping.SetDataPtr(this.fileContent, this.dvbsBlockOffset + this.satConfig.ChannelListOffset); 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.GetFlag("InUse") ? 0 : 1; cmd.Parameters["@progmask"].Value = dvbsMapping.GetWord("offProgramNr"); cmd.Parameters["@prognr"].Value = dvbsMapping.GetWord("offProgramNr") & 0x3FFF; cmd.Parameters["@progfix"].Value = dvbsMapping.GetWord("offProgramNrPreset"); int absNameOffset = dvbsMapping.BaseOffset + dvbsMapping.GetOffsets("offName")[0]; string longName, shortName; decoder.GetChannelNames(fileContent, absNameOffset, dvbsMapping.GetByte("offNameLength"), out longName, out shortName); cmd.Parameters["@name"].Value = longName; cmd.Parameters["@tpnr"].Value = dvbsMapping.GetWord("offTransponderIndex"); var transp = this.DataRoot.Transponder.TryGet(dvbsMapping.GetWord("offTransponderIndex")); 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.GetWord("offServiceId"); cmd.Parameters["@uid"].Value = transp == null ? (object)DBNull.Value : transp.TransportStreamId + "-" + transp.OriginalNetworkId + "-" + dvbsMapping.GetWord("offServiceId"); cmd.Parameters["@favcrypt"].Value = (int)dvbsMapping.GetByte("offFavorites"); cmd.Parameters["@lockskiphide"].Value = (int)dvbsMapping.GetByte("offLock"); cmd.ExecuteNonQuery(); dvbsMapping.BaseOffset += this.satConfig.dvbsChannelLength; } }
/// <summary> /// SATCODX103 files can contain channel names with unspecified implicit encoding, so we support reparsing based on a user selected default code page /// </summary> /// <param name="decoder"></param> public void ParseName(DvbStringDecoder decoder) { var length = this.Length; var start = this.FileOffset; // 43-50 + 115-126 in version 103 or 115-131 in version 105: channel name byte[] nameBytes = new byte[8 + 17]; var nameLen2 = Math.Min(length - 115, 17); // version 103 has 12 extra bytes for channel name, version 105 has 17 Array.Copy(data, start + 43, nameBytes, 0, 8); Array.Copy(data, start + 115, nameBytes, 8, nameLen2); // I have seen format 103 files using only implicit CP1252 encoding for Umlauts, as well as format 105 with implicit UTF-8/explicit DVB-encoding var oldDefaultEncoding = decoder.DefaultEncoding; if (nameLen2 > 12) { decoder.DefaultEncoding = Encoding.UTF8; } decoder.GetChannelNames(nameBytes, 0, nameBytes.Length, out var longName, out var shortName); decoder.DefaultEncoding = oldDefaultEncoding; this.Name = longName.TrimEnd(); this.ShortName = shortName.TrimEnd(); }
private void LoadChannels() { if (this.doc["channelList"] == null) { throw new FileLoadException("JSON does not contain a channelList node"); } var dec = new DvbStringDecoder(this.DefaultEncoding); int i = 0; foreach (var node in this.doc["channelList"]) { var ch = new GcChannel <JToken>(0, i, node); ch.PcrPid = (int)node["pcrPid"]; ch.IsDisabled = (bool)node["disabled"]; ch.FreqInMhz = (int)node["frequency"]; if (ch.FreqInMhz >= 100000 && ch.FreqInMhz < 1000000) // DVBS is given in MHz, DVBC/T in kHz { ch.FreqInMhz /= 1000; } ch.AudioPid = (int)node["audioPid"]; ch.Source = (string)node["sourceIndex"]; if (ch.Source == "SATELLITE DIGITAL") { ch.SignalSource |= SignalSource.DvbS; } else if (ch.Source == "CABLE DIGITAL") { ch.SignalSource |= SignalSource.DvbC; } else if (ch.Source.Contains("DIGITAL")) // not seen yet. maybe DIGITAL ANTENNA? { ch.SignalSource |= SignalSource.DvbT; } ch.Skip = (bool)node["skipped"]; ch.Hidden = (bool)node["Invisible"]; ch.IsDeleted = (bool)node["deleted"]; //if (int.TryParse((string) node["satelliteId"], out var satId)) ch.Satellite = (string)node["satelliteId"]; //this.DataRoot.Satellites.TryGet(satId); ch.Encrypted = (bool)node["scrambled"]; var nameBytes = Convert.FromBase64String((string)node["chNameBase64"]); dec.GetChannelNames(nameBytes, 0, nameBytes.Length, out var name, out var shortName); ch.Name = name; ch.ShortName = shortName; ch.VideoPid = (int)node["videoPid"]; var transSystem = (string)node["transSystem"]; var tpId = (string)node["tpId"]; if (tpId != null && tpId.Length == 10) { ch.Transponder = this.DataRoot.Transponder.TryGet((int.Parse(tpId.Substring(0, 4)) << 16) + int.Parse(tpId.Substring(4))); // satId + freq, e.g. 0192126041 } ch.TransportStreamId = (int)node["TSID"]; ch.OldProgramNr = ch.IsDeleted ? -1 : (int)node["majorNumber"]; ch.ServiceType = (int)node["serviceType"]; ch.Lock = (bool)node["locked"]; if (string.IsNullOrWhiteSpace(ch.Name)) { ch.Name = (string)node["channelName"]; } ch.ServiceId = (int)node["SVCID"]; if (ch.ServiceId == 0) { ch.ServiceId = (int)node["programNum"]; } ch.OriginalNetworkId = (int)node["ONID"]; ch.SignalSource |= LookupData.Instance.IsRadioTvOrData(ch.ServiceType); if ((ch.OldProgramNr & 0x4000) != 0) { ch.OldProgramNr &= 0x3FFF; ch.SignalSource |= SignalSource.Radio; } var list = this.DataRoot.GetChannelList(ch.SignalSource); this.DataRoot.AddChannel(list, ch); } }
private ChannelInfo LoadDvbsChannel(ChannelList list, DataMapping mapping, int recordIndex, DvbStringDecoder dvbStringDecoder) { var transponderId = mapping.GetWord("offTransponderIndex"); var progNr = mapping.GetWord("offProgNr"); var ch = new ChannelInfo(list.SignalSource, recordIndex, progNr, null); // deleted channels must be kept in the list because their records must also be physically reordered when saving the list if (progNr == 0xFFFF || transponderId == 0xFFFF) { ch.IsDeleted = true; ch.OldProgramNr = -1; return(ch); } // onid, tsid, pcrpid and vpid can be 0 in some lists ch.PcrPid = mapping.GetWord("offPcrPid") & mapping.GetMask("maskPcrPid"); ch.Lock = mapping.GetFlag("Locked"); ch.OriginalNetworkId = mapping.GetWord("OffOnid"); ch.TransportStreamId = mapping.GetWord("offTsid"); ch.ServiceId = mapping.GetWord("offSid"); ch.VideoPid = mapping.GetWord("offVpid") & mapping.GetMask("maskVpid"); ch.Favorites = mapping.GetFlag("IsFav") ? Favorites.A : 0; ch.OldProgramNr = progNr; // the 0x1F as the first byte of the channel name is likely the DVB encoding indicator for UTF-8. So we use the DvbStringDecoder here dvbStringDecoder.GetChannelNames(mapping.Data, mapping.BaseOffset + mapping.GetConst("offName", 0), mapping.GetConst("lenName", 0), out var longName, out var shortName); ch.Name = longName.TrimEnd('\0'); ch.ShortName = shortName.TrimEnd('\0'); dvbStringDecoder.GetChannelNames(mapping.Data, mapping.BaseOffset + mapping.GetConst("offProvider", 0), mapping.GetConst("lenProvider", 0), out var provider, out _); ch.Provider = provider.TrimEnd('\0'); // copy values from the satellite/transponder tables to the channel if (this.DataRoot.Transponder.TryGetValue(transponderId, out var t)) { ch.Transponder = t; ch.FreqInMhz = t.FrequencyInMhz; ch.SymbolRate = t.SymbolRate; ch.SatPosition = t.Satellite?.OrbitalPosition; ch.Satellite = t.Satellite?.Name; if (t.OriginalNetworkId != 0) { ch.OriginalNetworkId = t.OriginalNetworkId; } if (t.TransportStreamId != 0) { ch.TransportStreamId = t.TransportStreamId; } } return(ch); }
internal Channels(int pos, string line, byte[] data, int start, int length, DvbStringDecoder decoder) { this.FileOffset = start; this.Length = length; this.RecordIndex = pos; this.RecordOrder = this.OldProgramNr = pos + 1; if (!line.StartsWith("SATCODX")) { throw new FileLoadException("Only SAT channels are supported"); } if (line.Length < 106) { throw new FileLoadException("Unrecognized channel format"); } this.Satellite = line.Substring(10, 18); var type = line[28]; this.SignalSource = SignalSource.Digital | SignalSource.Sat | (type == 'T' ? SignalSource.Tv : type == 'R' ? SignalSource.Radio : 0); this.ServiceType = type == 'T' ? 1 : type == 'R' ? 2 : 0; // 1=SD-TV, 2=Radio if (int.TryParse(line.Substring(34, 5), out var mhz)) { this.FreqInMhz = mhz; } this.Polarity = line[39] == '1' ? 'H' : 'V'; byte[] nameBytes = new byte[8 + 17]; var nameLen2 = Math.Min(length - 115, 17); // version 103 has 12 extra bytes for channel name, version 105 has 17 Array.Copy(data, start + 43, nameBytes, 0, 8); Array.Copy(data, start + 115, nameBytes, 8, nameLen2); decoder.GetChannelNames(nameBytes, 0, nameBytes.Length, out var longName, out var shortName); this.Name = longName.TrimEnd(); this.ShortName = shortName.TrimEnd(); var spos = line.Substring(51, 4).TrimStart('0'); this.SatPosition = spos.Substring(0, spos.Length - 1) + CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator + spos.Substring(spos.Length - 1); if (int.TryParse(line.Substring(69, 5), out var symrate)) { this.SymbolRate = symrate; } if (int.TryParse(line.Substring(87, 5), out var sid)) { this.ServiceId = sid; } if (int.TryParse(line.Substring(92, 5), out var onid)) { this.OriginalNetworkId = onid; } if (int.TryParse(line.Substring(97, 5), out var tsid)) { this.TransportStreamId = tsid; } }
internal Channel(int pos, string line, byte[] data, int start, int length, DvbStringDecoder decoder) { this.data = data; this.FileOffset = start; this.Length = length; this.RecordIndex = pos; this.RecordOrder = this.OldProgramNr = pos + 1; if (!line.StartsWith("SATCODX")) { throw new FileLoadException("Only SAT channels are supported"); } if (line.Length < 106) { throw new FileLoadException("Unrecognized channel format"); } // 10-27: satellite name this.Satellite = line.Substring(10, 18); // 28: channel type var type = line[28]; this.SignalSource = SignalSource.Digital | SignalSource.Sat | (type == 'T' ? SignalSource.Tv : type == 'R' ? SignalSource.Radio : 0); this.ServiceTypeName = type == 'T' ? "TV" : type == 'R' ? "Radio" : type == 'D' ? "Data" : "Other"; // 29-32: broadcast system // 33-41: frequency in kHz if (int.TryParse(line.Substring(33, 9), out var khz)) { this.FreqInMhz = (decimal)khz / 1000; } // 42: polarity this.Polarity = line[42] == '1' ? 'H' : 'V'; // 43-50 + 115-126 in version 103 or 115-131 in version 105: channel name this.ParseName(decoder); // 51-54: sat position var spos = line.Substring(51, 4).TrimStart('0'); this.SatPosition = spos.Substring(0, spos.Length - 1) + CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator + spos.Substring(spos.Length - 1); // 69-73: symbol rate if (int.TryParse(line.Substring(69, 5), out var symrate)) { this.SymbolRate = symrate; } // 74: FEC 0=-, 1=1/2, 2=2/3, 3=3/4, 5=5/6, 7=7/8 // 75-78: vpid or ____ // 79-82: apid or ____ // 83-86: pcrpid or ____ // 87-91: sid if (int.TryParse(line.Substring(87, 5), out var sid)) { this.ServiceId = sid; } // 92-96: nid / onid if (int.TryParse(line.Substring(92, 5), out var onid)) { this.OriginalNetworkId = onid; } // 97-101: tsid if (int.TryParse(line.Substring(97, 5), out var tsid)) { this.TransportStreamId = tsid; } // 102-104: language // 106-107: country code // 108-110: language code // 111-114: crypto code }