mirror of
https://github.com/PredatH0r/ChanSort.git
synced 2026-01-15 11:52:04 +01:00
Blaupunkt, Dyon, Hisense, Sharp and many others using DVBS_Program.csv, DVBS_CHANNEL_TABLE.csv, MSxxxx_DVBS_CHANNEL_TABLE.csv:
- added support for Hisense .csv files with 6 columns including "channel number" and "LCN" - using separate lists for DTV, Radio and Data, which all start with 1
This commit is contained in:
@@ -14,21 +14,21 @@ namespace ChanSort.Loader.Sharp
|
||||
* ===================================
|
||||
* These formats lack a way to uniquely identify a channel via ONID-TSID-SID and as described in their file header,
|
||||
* can only be physically reordered to change the zapping order, but don't allow changing the channel number:
|
||||
* - Hisense LTDN40D50TS: LCN,Channel Name,Service Type,[B]
|
||||
* - Hisense LTDN40D50TS (LCN is a bogus column name and is actually the physical channel record index in the .dat file): LCN,Channel Name,Service Type,[B]
|
||||
* - Hisense 40A5100F (DTV,Radio,Data all start at LCN 1): Channel Number,LCN,Channel Name,Service Type,Free or Scramble,Transponder,[S]
|
||||
* - Sharp LC-43CFE4142E firmware V1.16: Channel Number,Channel Name,Service Type,Free or Scramble,Transponder,[S]
|
||||
* - Dyon Live 24 Pro, Dyon ENTER 32 Pro X: Channel Number,Channel Name,Service Type,Free or Scramble,Transponder,[S]
|
||||
* - Blaupunkt B32B133T2CSHD: Channel Number,Channel Name,Service Type,Free or Scramble,Transponder,[S]
|
||||
*
|
||||
* MS6486_DVBS_CHANNEL_TABLE + MS6488_HOTELMODE_TABLE.json
|
||||
* =======================================
|
||||
* Channel Number,Channel Name,Service Type,Free or Scramble,Frequency(MHz),Polarity,SymbolRate(KS/s),[S]
|
||||
* - Channel Number,Channel Name,Service Type,Free or Scramble,Frequency(MHz),Polarity,SymbolRate(KS/s),[S]
|
||||
*
|
||||
*
|
||||
* DVBS_CHANNEL_TABLE.csv + dtv_cmdb_*.bin
|
||||
* =======================================
|
||||
* This format supposedly supports deleting and changing the program numbers along with reordering (despite the NOTE in the header).
|
||||
* - Channel number,Channel Name,program count,program index,RF channel number,QAM mode,Band width,PlpID,Frequency,symbol rate,Polarity,SatName,SatID,SatTableID,LowLOF,HighLOF,LNBType,LNBTypeReal,DISEQC level,ToneburstType,Swt10Port,Swt11Port,22KOnOff,LNB power,12VOnOff,Motor position bit8 1:USALS 0:DISEQC1.2,Satellite Angle,Transponder number,Begin transponder,channel Id,unicable frequency,unicable MDU,unicable password pin,LNB index 0:A 1:B,TS id,orig network id,network id,PCR pid,LCN,Free or Scramble,PmtPID,ServiceID,Video_pid,Audio_pid,VideoType,AudioType,NitVer,PatVer,PmtVer,SdtVer,Service Type,[S]
|
||||
* The file from user "blackbox" was encoded in UTF-8 without BOM
|
||||
*
|
||||
*/
|
||||
internal class SharpSerializer : SerializerBase
|
||||
@@ -37,11 +37,15 @@ namespace ChanSort.Loader.Sharp
|
||||
{
|
||||
Hisense3Columns = 1,
|
||||
Sharp5Columns = 2,
|
||||
Sharp7Columns = 3,
|
||||
Sharp51Columns = 4
|
||||
Hisense6Columns = 3,
|
||||
Sharp7Columns = 4,
|
||||
Sharp51Columns = 5
|
||||
}
|
||||
|
||||
private readonly ChannelList dvbsChannels = new ChannelList(0, "DVB-S");
|
||||
private readonly ChannelList dtvChannels = new ChannelList(SignalSource.DvbS| SignalSource.Tv, "DTV");
|
||||
private readonly ChannelList radioChannels = new ChannelList(SignalSource.DvbS|SignalSource.Radio, "Radio");
|
||||
private readonly ChannelList dataChannels = new ChannelList(SignalSource.DvbS|SignalSource.Data, "Data");
|
||||
|
||||
private Encoding encoding;
|
||||
private FormatVersion formatVersion;
|
||||
private string[] cols;
|
||||
@@ -60,7 +64,9 @@ namespace ChanSort.Loader.Sharp
|
||||
this.Features.CanHaveGaps = false;
|
||||
this.Features.FavoritesMode = FavoritesMode.None;
|
||||
|
||||
this.DataRoot.AddChannelList(this.dvbsChannels);
|
||||
this.DataRoot.AddChannelList(this.dtvChannels);
|
||||
this.DataRoot.AddChannelList(this.radioChannels);
|
||||
this.DataRoot.AddChannelList(this.dataChannels);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -88,99 +94,129 @@ namespace ChanSort.Loader.Sharp
|
||||
if (data[0] == "[E]")
|
||||
break;
|
||||
|
||||
var ch = new ChannelInfo(SignalSource.DvbS, i, i-2, "");
|
||||
for (int j = 0; j < data.Length; j++)
|
||||
{
|
||||
var val = data[j];
|
||||
int.TryParse(val, out var intval);
|
||||
switch (cols[j])
|
||||
{
|
||||
case "lcn":
|
||||
case "channel number":
|
||||
ch.RecordOrder = intval;
|
||||
break;
|
||||
case "channel name":
|
||||
ch.Name = val;
|
||||
break;
|
||||
case "service type":
|
||||
if (intval != 0)
|
||||
{
|
||||
if (intval == 1)
|
||||
{
|
||||
ch.SignalSource |= SignalSource.Tv;
|
||||
ch.ServiceTypeName = "DTV";
|
||||
}
|
||||
else if (intval == 2)
|
||||
{
|
||||
ch.SignalSource |= SignalSource.Radio;
|
||||
ch.ServiceTypeName = "Radio";
|
||||
}
|
||||
else if (intval == 3)
|
||||
{
|
||||
ch.SignalSource |= SignalSource.Data;
|
||||
ch.ServiceTypeName = "Data";
|
||||
}
|
||||
}
|
||||
else
|
||||
ch.ServiceTypeName = val;
|
||||
break;
|
||||
case "free or scramble":
|
||||
ch.Encrypted = val == "Scramble" || val == "1";
|
||||
break;
|
||||
case "transponder":
|
||||
{
|
||||
var parts = val.Split(' ');
|
||||
if (int.TryParse(parts[0], out var mhz))
|
||||
ch.FreqInMhz = mhz;
|
||||
if (parts.Length > 1 && parts[1].Length > 0)
|
||||
ch.Polarity = parts[1][0];
|
||||
if (parts.Length > 2 && int.TryParse(parts[2], out var sr))
|
||||
ch.SymbolRate = sr;
|
||||
break;
|
||||
}
|
||||
case "frequency(mhz)":
|
||||
case "frequency":
|
||||
ch.FreqInMhz = intval;
|
||||
break;
|
||||
case "polarity":
|
||||
if (val.Length > 0)
|
||||
ch.Polarity = val[0] == '0' || val[0] == 'H' ? 'H' : 'V';
|
||||
break;
|
||||
case "symbolrate(ks/s)":
|
||||
case "symbol rate":
|
||||
ch.SymbolRate = intval;
|
||||
break;
|
||||
case "satname":
|
||||
ch.Satellite = val;
|
||||
break;
|
||||
case "satellite angle":
|
||||
ch.SatPosition = val;
|
||||
break;
|
||||
case "orig network id":
|
||||
ch.OriginalNetworkId = intval;
|
||||
break;
|
||||
case "ts id":
|
||||
ch.TransportStreamId = intval;
|
||||
break;
|
||||
case "serviceid":
|
||||
ch.ServiceId = intval;
|
||||
break;
|
||||
case "pcr pid":
|
||||
ch.PcrPid = intval;
|
||||
break;
|
||||
case "video_pid":
|
||||
ch.VideoPid = intval;
|
||||
break;
|
||||
case "audio_pid":
|
||||
ch.AudioPid = intval;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.DataRoot.AddChannel(this.dvbsChannels, ch);
|
||||
ReadChannel(i, data);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ReadChannel()
|
||||
private void ReadChannel(int i, string[] data)
|
||||
{
|
||||
var ch = new ChannelInfo(SignalSource.DvbS, i, 0, "");
|
||||
for (int j = 0; j < data.Length; j++)
|
||||
{
|
||||
var val = data[j];
|
||||
int.TryParse(val, out var intval);
|
||||
switch (cols[j])
|
||||
{
|
||||
case "lcn":
|
||||
if (this.formatVersion == FormatVersion.Hisense3Columns) // this format incorrectly labels the physical channel index column as "LCN"
|
||||
ch.RecordOrder = intval;
|
||||
else if (this.formatVersion != FormatVersion.Sharp51Columns) // the Sharp51 format has "channel number", "program index" with valid numbers and "LCN" with all values 65535
|
||||
ch.OldProgramNr = intval;
|
||||
break;
|
||||
case "channel number":
|
||||
ch.RecordOrder = intval;
|
||||
if (this.formatVersion == FormatVersion.Sharp51Columns)
|
||||
ch.OldProgramNr = intval;
|
||||
break;
|
||||
case "channel name":
|
||||
ch.Name = val;
|
||||
break;
|
||||
case "service type":
|
||||
// some files use int values, other use strings
|
||||
if (intval != 0)
|
||||
{
|
||||
if (intval == 1)
|
||||
{
|
||||
ch.SignalSource |= SignalSource.Tv;
|
||||
ch.ServiceTypeName = "DTV";
|
||||
}
|
||||
else if (intval == 2)
|
||||
{
|
||||
ch.SignalSource |= SignalSource.Radio;
|
||||
ch.ServiceTypeName = "Radio";
|
||||
}
|
||||
else if (intval == 3)
|
||||
{
|
||||
ch.SignalSource |= SignalSource.Data;
|
||||
ch.ServiceTypeName = "Data";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ch.ServiceTypeName = val;
|
||||
var lval = val.ToLowerInvariant();
|
||||
if (lval == "dtv")
|
||||
ch.SignalSource |= SignalSource.Tv;
|
||||
else if (lval == "radio")
|
||||
ch.SignalSource |= SignalSource.Radio;
|
||||
else
|
||||
ch.SignalSource |= SignalSource.Data;
|
||||
}
|
||||
|
||||
break;
|
||||
case "free or scramble":
|
||||
ch.Encrypted = val == "Scramble" || val == "1";
|
||||
break;
|
||||
case "transponder":
|
||||
{
|
||||
var parts = val.Split(' ');
|
||||
if (int.TryParse(parts[0], out var mhz))
|
||||
ch.FreqInMhz = mhz;
|
||||
if (parts.Length > 1 && parts[1].Length > 0)
|
||||
ch.Polarity = parts[1][0];
|
||||
if (parts.Length > 2 && int.TryParse(parts[2], out var sr))
|
||||
ch.SymbolRate = sr;
|
||||
break;
|
||||
}
|
||||
case "frequency(mhz)":
|
||||
case "frequency":
|
||||
ch.FreqInMhz = intval;
|
||||
break;
|
||||
case "polarity":
|
||||
if (val.Length > 0)
|
||||
ch.Polarity = val[0] == '0' || val[0] == 'H' ? 'H' : 'V';
|
||||
break;
|
||||
case "symbolrate(ks/s)":
|
||||
case "symbol rate":
|
||||
ch.SymbolRate = intval;
|
||||
break;
|
||||
case "satname":
|
||||
ch.Satellite = val;
|
||||
break;
|
||||
case "satellite angle":
|
||||
ch.SatPosition = val;
|
||||
break;
|
||||
case "orig network id":
|
||||
ch.OriginalNetworkId = intval;
|
||||
break;
|
||||
case "ts id":
|
||||
ch.TransportStreamId = intval;
|
||||
break;
|
||||
case "serviceid":
|
||||
ch.ServiceId = intval;
|
||||
break;
|
||||
case "pcr pid":
|
||||
ch.PcrPid = intval;
|
||||
break;
|
||||
case "video_pid":
|
||||
ch.VideoPid = intval;
|
||||
break;
|
||||
case "audio_pid":
|
||||
ch.AudioPid = intval;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var list = this.GetChannelList(ch);
|
||||
if (ch.OldProgramNr == 0) // if there was no explicit LCN, channels are automatically numbered sequentially by order in their list
|
||||
ch.OldProgramNr = list.Count + 1;
|
||||
this.DataRoot.AddChannel(list, ch);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DetectFormatVersion()
|
||||
private FormatVersion DetectFormatVersion()
|
||||
{
|
||||
@@ -192,6 +228,8 @@ namespace ChanSort.Loader.Sharp
|
||||
{
|
||||
if (lines[2] == "Channel Number,Channel Name,Service Type,Free or Scramble,Transponder,[S]")
|
||||
return FormatVersion.Sharp5Columns;
|
||||
if (lines[2] == "Channel Number,LCN,Channel Name,Service Type,Free or Scramble,Transponder,[S]")
|
||||
return FormatVersion.Hisense6Columns;
|
||||
if (lines[2] == "Channel Number,Channel Name,Service Type,Free or Scramble,Frequency(MHz),Polarity,SymbolRate(KS/s),[S]")
|
||||
return FormatVersion.Sharp7Columns;
|
||||
|
||||
@@ -216,35 +254,49 @@ namespace ChanSort.Loader.Sharp
|
||||
#region AdjustVisibleColumns()
|
||||
private void AdjustVisibleColumns()
|
||||
{
|
||||
var list = this.dvbsChannels;
|
||||
list.VisibleColumnFieldNames.Clear();
|
||||
list.VisibleColumnFieldNames.Add("Position");
|
||||
list.VisibleColumnFieldNames.Add("OldPosition");
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.RecordOrder));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.Name));
|
||||
if (this.formatVersion >= FormatVersion.Sharp5Columns)
|
||||
foreach (var list in this.DataRoot.ChannelLists)
|
||||
{
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.Encrypted));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.FreqInMhz));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.Polarity));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.SymbolRate));
|
||||
}
|
||||
list.VisibleColumnFieldNames.Clear();
|
||||
list.VisibleColumnFieldNames.Add("Position");
|
||||
list.VisibleColumnFieldNames.Add("OldPosition");
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.RecordOrder));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.Name));
|
||||
if (this.formatVersion >= FormatVersion.Sharp5Columns)
|
||||
{
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.Encrypted));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.FreqInMhz));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.Polarity));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.SymbolRate));
|
||||
}
|
||||
|
||||
if (this.formatVersion >= FormatVersion.Sharp51Columns)
|
||||
{
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.Satellite));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.OriginalNetworkId));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.TransportStreamId));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.ServiceId));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.PcrPid));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.AudioPid));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.VideoPid));
|
||||
if (this.formatVersion >= FormatVersion.Sharp51Columns)
|
||||
{
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.Satellite));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.OriginalNetworkId));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.TransportStreamId));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.ServiceId));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.PcrPid));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.AudioPid));
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.VideoPid));
|
||||
}
|
||||
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.ServiceTypeName));
|
||||
}
|
||||
list.VisibleColumnFieldNames.Add(nameof(ChannelInfo.ServiceTypeName));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetChannelList()
|
||||
private ChannelList GetChannelList(ChannelInfo channel)
|
||||
{
|
||||
switch (channel.SignalSource & SignalSource.MaskTvRadioData)
|
||||
{
|
||||
case SignalSource.Tv: return dtvChannels;
|
||||
case SignalSource.Radio: return radioChannels;
|
||||
default: return dataChannels;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Save()
|
||||
|
||||
@@ -261,26 +313,38 @@ namespace ChanSort.Loader.Sharp
|
||||
// index of fields in the extended FormatVersion.Sharp51Columns
|
||||
var ixChannelNumber = Array.IndexOf(this.cols, "channel number");
|
||||
var ixProgramIndex = ixChannelNumber < 0 ? -1 : Array.IndexOf(this.cols, "program index");
|
||||
var ixLcn = ixChannelNumber < 0 ? -1 : Array.IndexOf(this.cols, "lcn");
|
||||
|
||||
foreach (var channel in this.dvbsChannels.GetChannelsByNewOrder())
|
||||
foreach (var channelList in new[] {dtvChannels, radioChannels, dataChannels})
|
||||
{
|
||||
// when a reference list was applied, the list may contain proxy entries for deleted channels, which must be ignored
|
||||
if (channel.IsProxy || channel.IsDeleted)
|
||||
continue;
|
||||
foreach (var channel in channelList.GetChannelsByNewOrder())
|
||||
{
|
||||
// when a reference list was applied, the list may contain proxy entries for deleted channels, which must be ignored
|
||||
if (channel.IsProxy || channel.IsDeleted)
|
||||
continue;
|
||||
|
||||
var line = this.lines[channel.RecordIndex];
|
||||
if (ixProgramIndex >= 0)
|
||||
{
|
||||
// this extended format would only change the zapping order unless the "Channel Number" and "Channel Index" fields are updated too
|
||||
var fields = this.lines[channel.RecordIndex].Split(',');
|
||||
fields[ixChannelNumber] = fields[ixProgramIndex] = channel.NewProgramNr.ToString();
|
||||
line = string.Join(",", fields);
|
||||
var line = this.lines[channel.RecordIndex];
|
||||
if (ixProgramIndex >= 0)
|
||||
{
|
||||
// this extended format would only change the zapping order unless the "Channel Number" and "Channel Index" fields are updated too
|
||||
var fields = this.lines[channel.RecordIndex].Split(',');
|
||||
fields[ixChannelNumber] = fields[ixProgramIndex] = channel.NewProgramNr.ToString();
|
||||
line = string.Join(",", fields);
|
||||
}
|
||||
else if (ixLcn >= 0)
|
||||
{
|
||||
// Hisense 6 column format with Channel Number, LCN, ...
|
||||
var fields = this.lines[channel.RecordIndex].Split(',');
|
||||
fields[ixLcn] = channel.NewProgramNr.ToString();
|
||||
line = string.Join(",", fields);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the older formats require the "Channel Number" to be unchanged and update it internally during the import based on the order of the lines
|
||||
}
|
||||
|
||||
file.WriteLine(line);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the older formats require the "Channel Number" to be unchanged and update it internally during the import based on the order of the lines
|
||||
}
|
||||
file.WriteLine(line);
|
||||
}
|
||||
|
||||
file.WriteLine("[E]");
|
||||
|
||||
Reference in New Issue
Block a user