- ChanSort didn't work properly for Turkish (and other system locales) that don't translate ".bin" to uppercase

".BIN" and ".BIN" to lowercase ".bin".
- Philips: Removing a channel from a list is no longer possible (because it is not supported by the TV's import).
  When saving a file, all unsorted channels will be placed at the end of the list.
- support for Philips Repair\mgr_chan_s_fta.db lists is now read-only. Files can be used as a reference list,
  but modifying them won't be possible.
This commit is contained in:
Horst Beham
2021-08-31 22:13:28 +02:00
parent b0b09de733
commit 1b250b2a18
24 changed files with 225 additions and 148 deletions

View File

@@ -12,7 +12,7 @@ namespace ChanSort.Api
public SerializerBase CreateSerializer(string inputFile)
{
var ext = (Path.GetExtension(inputFile) ?? "").ToLower();
var ext = (Path.GetExtension(inputFile) ?? "").ToLowerInvariant();
if (ext == ".csv")
return new CsvRefListSerializer(inputFile);
else

View File

@@ -213,7 +213,7 @@ namespace ChanSort.Api
{
if (string.IsNullOrWhiteSpace(input))
return 0;
if (input.Length > 2 && input[0] == '0' && char.ToLower(input[1]) == 'x')
if (input.Length > 2 && input[0] == '0' && char.ToLowerInvariant(input[1]) == 'x')
return int.Parse(input.Substring(2), NumberStyles.HexNumber);
if (int.TryParse(input, out var value))
return value;
@@ -226,7 +226,7 @@ namespace ChanSort.Api
{
if (string.IsNullOrWhiteSpace(input))
return 0;
if (input.Length > 2 && input[0] == '0' && char.ToLower(input[1]) == 'x')
if (input.Length > 2 && input[0] == '0' && char.ToLowerInvariant(input[1]) == 'x')
return long.Parse(input.Substring(2), NumberStyles.HexNumber);
if (long.TryParse(input, out var value))
return value;

View File

@@ -110,7 +110,7 @@ namespace ChanSort.Api
public static void Save(string fileName, ChannelList list)
{
var samToolBoxMode = (Path.GetExtension(fileName) ?? "").ToLower() == ".chl";
var samToolBoxMode = (Path.GetExtension(fileName) ?? "").ToLowerInvariant() == ".chl";
using (var writer = new StreamWriter(fileName, false, Encoding.UTF8))
{

View File

@@ -102,7 +102,7 @@ namespace ChanSort.Api
if (!isDupeProgNr)
this.channelByProgNr[ci.OldProgramNr] = ci;
var lowerName = (ci.Name ?? "").ToLower().Trim();
var lowerName = (ci.Name ?? "").ToLowerInvariant().Trim();
var byNameList = this.channelByName.TryGet(lowerName);
if (byNameList == null)
{
@@ -138,7 +138,7 @@ namespace ChanSort.Api
#region GetChannelByName()
public IEnumerable<ChannelInfo> GetChannelByName(string name)
{
var hits = this.channelByName.TryGet(name.ToLower().Trim());
var hits = this.channelByName.TryGet(name.ToLowerInvariant().Trim());
return hits ?? new List<ChannelInfo>();
}
#endregion

View File

@@ -73,7 +73,7 @@ namespace ChanSort.Api
var fields = CsvFile.Parse(line, ';');
if (fields.Count == 0)
continue;
switch (fields[0].ToLower())
switch (fields[0].ToLowerInvariant())
{
case "onid": this.ParseNetwork(fields); break;
case "transp": this.ParseTransponder(fields); break;

View File

@@ -110,7 +110,7 @@ namespace ChanSort.Api
int sig = value.StartsWith("-") ? -1 : 1;
if (sig < 0)
value = value.Substring(1).Trim();
if (value.ToLower().StartsWith("0x"))
if (value.ToLowerInvariant().StartsWith("0x"))
{
try { return Convert.ToInt32(value, 16) * sig; }
catch { return 0; }

View File

@@ -110,9 +110,9 @@ namespace ChanSort.Api
var bytes = new byte[input.Length/2];
for (int i = 0, c = input.Length/2; i < c; i++)
{
char ch = Char.ToUpper(input[i*2]);
char ch = Char.ToUpperInvariant(input[i*2]);
var high = Char.IsDigit(ch) ? ch - '0' : ch - 'A' + 10;
ch = Char.ToUpper(input[i*2 + 1]);
ch = Char.ToUpperInvariant(input[i*2 + 1]);
var low = Char.IsDigit(ch) ? ch - '0' : ch - 'A' + 10;
bytes[i] = (byte)((high << 4) | low);
}

View File

@@ -162,7 +162,7 @@ namespace ChanSort.Loader.Hisense.ServicelistDb
cmd.CommandText = "SELECT name FROM sqlite_master WHERE type = 'table' order by name";
using var r = cmd.ExecuteReader();
while (r.Read())
tableNames.Add(r.GetString(0).ToLower());
tableNames.Add(r.GetString(0).ToLowerInvariant());
}
#endregion
@@ -298,7 +298,7 @@ namespace ChanSort.Loader.Hisense.ServicelistDb
private void LoadTunerData2017(SqliteCommand cmd, string joinTable, string joinFields, Action<HisTransponder, SqliteDataReader, int> enhanceTransponderInfo)
{
if (!tableNames.Contains(joinTable.ToLower()))
if (!tableNames.Contains(joinTable.ToLowerInvariant()))
return;
cmd.CommandText = $"select tuner.tunerid, oid, tid, satellite {joinFields} "

View File

@@ -113,7 +113,7 @@ namespace ChanSort.Loader.LG.Binary
private void ReadConfigurationFromIniFile()
{
string iniFile = this.GetType().Assembly.Location.ToLower().Replace(".dll", ".ini");
string iniFile = this.GetType().Assembly.Location.ToLowerInvariant().Replace(".dll", ".ini");
IniFile ini = new IniFile(iniFile);
foreach (var section in ini.Sections)
{
@@ -142,7 +142,7 @@ namespace ChanSort.Loader.LG.Binary
{
this.InitUiFactory();
string basename = (Path.GetFileNameWithoutExtension(this.FileName) ?? "").ToUpper();
string basename = (Path.GetFileNameWithoutExtension(this.FileName) ?? "").ToUpperInvariant();
if (basename.StartsWith("XXLH250"))
this.specialModel = SpecialHandlingModels.LH250;
else if (basename.StartsWith("XXLH3000"))
@@ -1131,7 +1131,7 @@ Due to issues with most recent LG firmwares such lists can no longer be modified
set
{
if (value.Length < 3 || this.settingsBlockOffset == 0 || this.settingsBlockSize < 8) return;
value = value.ToUpper();
value = value.ToUpperInvariant();
int off = this.settingsBlockOffset + 4 + 4 + 2;
for (int i = 0; i < 3; i++)
this.fileContent[off--] = (byte)value[i];

View File

@@ -183,7 +183,7 @@ namespace ChanSort.Loader.GlobalClone
tp.FrequencyInMhz = (int) node["frequency"];
tp.Number = (int) node["channelIdx"];
var pol = ((string) node["polarization"]).ToLower();
var pol = ((string) node["polarization"]).ToLowerInvariant();
tp.Polarity = pol.StartsWith("h") ? 'H' : pol.StartsWith("V") ? 'V' : '\0';
tp.TransportStreamId = (int) node["TSID"];
tp.OriginalNetworkId = (int)node["ONID"];

View File

@@ -115,7 +115,7 @@ namespace ChanSort.Loader.GlobalClone
// ask whether binary TLL file should be deleted
var dir = Path.GetDirectoryName(this.FileName) ?? ".";
var binTlls = Directory.GetFiles(dir, "xx" + series + "*.tll");
if (binTlls.Length > 0 && !(binTlls.Length == 1 && Path.GetFileName(binTlls[0]).ToLower() == Path.GetFileName(this.FileName).ToLower()))
if (binTlls.Length > 0 && !(binTlls.Length == 1 && Path.GetFileName(binTlls[0]).ToLowerInvariant() == Path.GetFileName(this.FileName).ToLowerInvariant()))
{
var txt = Resource.GcSerializer_ReadModelInfo_ModelWarning;
if (Api.View.Default != null && Api.View.Default.MessageBox(txt, "LG GlobalClone", View.MessageBoxButtons.YesNo, View.MessageBoxIcon.Information) == View.DialogResult.Yes)
@@ -585,7 +585,7 @@ namespace ChanSort.Loader.GlobalClone
private int HexNibble(char hexDigit)
{
return hexDigit >= '0' && hexDigit <= '9' ? hexDigit - '0' : (Char.ToUpper(hexDigit) - 'A') + 10;
return hexDigit >= '0' && hexDigit <= '9' ? hexDigit - '0' : (Char.ToUpperInvariant(hexDigit) - 'A') + 10;
}
#endregion
}

View File

@@ -166,7 +166,7 @@ namespace ChanSort.Loader.M3u
break;
case "pol":
if (val.Length == 1)
chan.Polarity = Char.ToUpper(val[0]);
chan.Polarity = Char.ToUpperInvariant(val[0]);
break;
case "sr":
chan.SymbolRate = this.ParseInt(val);

View File

@@ -12,6 +12,9 @@ namespace ChanSort.Loader.Philips
* This serializer is used for the channel list format with a Repair\ folder containing files like channel_db_ver.db, mgr_chan_s_fta.db, ...
* The .db files are proprietary binary files, not SQLite databases.
* So far only the mgr_chan_s_fta.db file holing DVB-S channels is reverse engineered, the offsets are defined in PChanSort.Loader.Philips.ini
*
* Unfortunately modifying the .db files does not seem to be enough. The TV also depends on channel data in the FLASH_* files, which I don't know how how to edit.
* Therefore lists of this format can be read as read-only reference lists, but modifications are disabled.
*/
class DbSerializer : SerializerBase
{
@@ -26,6 +29,7 @@ namespace ChanSort.Loader.Philips
this.Features.MaxFavoriteLists = 1;
this.Features.FavoritesMode = FavoritesMode.OrderedPerSource;
this.Features.DeleteMode = DeleteMode.NotSupported;
this.Features.CanHaveGaps = false;
string iniFile = Assembly.GetExecutingAssembly().Location.Replace(".dll", ".ini");
this.ini = new IniFile(iniFile);
@@ -43,6 +47,7 @@ namespace ChanSort.Loader.Philips
nameof(Channel.OriginalNetworkId),
nameof(Channel.ServiceId)
};
dvbsChannels.ReadOnly = true;
}
#region Load()
@@ -163,7 +168,7 @@ namespace ChanSort.Loader.Philips
var offFooterChecksum = sec.GetInt("offFooterChecksum");
var mapping = new DataMapping(ini.GetSection("mgr_chan_s_fta.db_entry"));
#if JUST_CHANGE_NUMBERS
// update channel data
foreach (var ch in dvbsChannels.Channels)
{
@@ -172,7 +177,28 @@ namespace ChanSort.Loader.Philips
mapping.SetWord("offPrevProgNr", ch.NewProgramNr - 1);
mapping.SetWord("offFav", Math.Max(0, ch.GetPosition(1)));
}
#else
// physically reorder channels
var newData = new byte[data.Length];
Array.Copy(data, newData, lenHeader);
var off = lenHeader + lenEntry * dvbsChannels.Channels.Count;
Array.Copy(data, off, newData, off, lenFooter);
int i = 0;
foreach (var ch in dvbsChannels.Channels.OrderBy(c => c.NewProgramNr))
{
off = lenHeader + i * lenEntry;
Array.Copy(data, lenHeader + ch.RecordOrder * lenEntry, newData, off, lenEntry);
mapping.SetDataPtr(newData, off);
mapping.SetWord("offProgNr", ch.NewProgramNr);
mapping.SetWord("offPrevProgNr", ch.NewProgramNr - 1);
mapping.SetWord("offFav", Math.Max(0, ch.GetPosition(1)));
ch.RecordOrder = i;
++i;
}
data = newData;
#endif
// update checksum
var offChecksum = data.Length - lenFooter + offFooterChecksum;
var checksum = CalcChecksum(data, 0, offChecksum);

View File

@@ -85,7 +85,7 @@ namespace ChanSort.Loader.Philips
public SerializerBase CreateSerializer(string inputFile)
{
int majorVersion = int.MinValue;
var filename = Path.GetFileName(inputFile).ToLower();
var filename = Path.GetFileName(inputFile).ToLowerInvariant();
if (Regex.IsMatch(filename, @"^CM_.*\.(?:bin|xml)$", RegexOptions.IgnoreCase))
majorVersion = 0;
else
@@ -111,7 +111,7 @@ namespace ChanSort.Loader.Philips
break;
}
var dirName = Path.GetFileName(dir).ToLower();
var dirName = Path.GetFileName(dir).ToLowerInvariant();
if (dirName == "channellib" || dirName == "s2channellib")
dir = Path.GetDirectoryName(dir);
else if (Directory.Exists(Path.Combine(dir, "PhilipsChannelMaps")))

View File

@@ -14,11 +14,19 @@ namespace ChanSort.Loader.Philips
This loader supports 2 different kinds of XML files from Philips, the first in a "Repair" folder, the others in a "ChannelMap_100" (or later) folder
Example from Repair\CM_TPM1013E_LA_CK.xml:
This "Repair" format comes with a visible .BIN file and a .xml file that has file system attributes "hidden" and "system".
The TV seems to use the .BIN file as its primary source for setting up the internal list and then applies the .xml on top of it to reorder channels.
It uses the "oldpresetnumber" from the XML to lookup the channel from the .BIN file and then apply the new "presetnumber".
The .BIN file itself is compressed with some unknown cl_Zip compression / archive format and can't be edited with ChanSort.
Deleting a channel is not possible by modifiying the .xml file. Omitting a channel only results in duplicate numbers with the TV still showing the missing channels at their old numbers.
<Channel>
<Setup oldpresetnumber="1" presetnumber="1" name="Das Erste" ></Setup>
<Broadcast medium="dvbc" frequency="410000" system="west" serviceID="1" ONID="41985" TSID="1101" modulation="256" symbolrate="6901000" bandwidth="Unknown"></Broadcast>
</Channel>
Newer channel lists from Philips contain multiple XML files with a different internal structure, which also varies based on the version number in the ChannelMap_xxx folder name:
<Channel>
<Setup SatelliteName="0x54 0x00 0x55 0x00 0x52 0x00 0x4B 0x00 0x53 0x00 0x41 0x00 0x54 0x00 0x20 0x00 0x34 0x00 0x32 0x00 0x45 0x00 " ChannelNumber="1" ChannelName="0x54 0x00 0xC4 0x00 0xB0 0x00 0x56 0x00 0xC4 0x00 0xB0 0x00 0x42 0x00 0x55 0x00 0x20 0x00 0x53 0x00 0x50 0x00 0x4F 0x00 0x52 0x00 " ChannelLock="0" UserModifiedName="0" LogoID="0" UserModifiedLogo="0" LogoLock="0" UserHidden="0" FavoriteNumber="0" />
@@ -70,7 +78,7 @@ namespace ChanSort.Loader.Philips
this.Features.CanSkipChannels = false;
this.Features.CanLockChannels = true;
this.Features.CanHideChannels = true;
this.Features.DeleteMode = DeleteMode.Physically;
this.Features.DeleteMode = DeleteMode.NotSupported;
this.Features.CanSaveAs = false;
this.Features.AllowGapsInFavNumbers = false;
this.Features.CanEditFavListNames = true;
@@ -132,7 +140,7 @@ namespace ChanSort.Loader.Philips
// support for files in a ChannelMap_xxx directory structure
bool isChannelMapFolderStructure = false;
var dir = Path.GetDirectoryName(this.FileName);
var dirName = Path.GetFileName(dir).ToLower();
var dirName = Path.GetFileName(dir).ToLowerInvariant();
if (dirName == "channellib" || dirName == "s2channellib")
{
dir = Path.GetDirectoryName(dir);
@@ -147,7 +155,7 @@ namespace ChanSort.Loader.Philips
this.chanLstBin = new ChanLstBin();
this.chanLstBin.Load(this.FileName, msg => this.logMessages.AppendLine(msg));
}
else if (Path.GetExtension(this.FileName).ToLower() == ".bin")
else if (Path.GetExtension(this.FileName).ToLowerInvariant() == ".bin")
{
// older Philips models export a visible file like Repair\CM_T911_LA_CK.BIN and an invisible (hidden+system) .xml file with the same name
var xmlPath = Path.Combine(dir, Path.GetFileNameWithoutExtension(this.FileName) + ".xml");
@@ -264,7 +272,7 @@ namespace ChanSort.Loader.Philips
var setupNode = node["Setup"] ?? throw new FileLoadException("Missing Setup XML element");
var bcastNode = node["Broadcast"] ?? throw new FileLoadException("Missing Broadcast XML element");
var fname = Path.GetFileNameWithoutExtension(file.path).ToLower();
var fname = Path.GetFileNameWithoutExtension(file.path).ToLowerInvariant();
var medium = bcastNode.GetAttribute("medium");
if (medium == "" && fname.Length >= 4 && fname.StartsWith("dvb"))
medium = fname;
@@ -276,9 +284,22 @@ namespace ChanSort.Loader.Philips
list.VisibleColumnFieldNames.Add("ServiceTypeName");
}
if (setupNode.HasAttribute("ChannelName"))
if (setupNode.HasAttribute("name"))
{
file.formatVersion = 1;
this.Features.FavoritesMode = FavoritesMode.None;
foreach (var list in this.DataRoot.ChannelLists)
{
list.VisibleColumnFieldNames.Remove("Favorites");
list.VisibleColumnFieldNames.Remove("Lock");
list.VisibleColumnFieldNames.Remove("Hidden");
list.VisibleColumnFieldNames.Remove("ServiceTypeName");
list.VisibleColumnFieldNames.Remove("Encrypted");
}
}
else if (setupNode.HasAttribute("ChannelName"))
{
file.formatVersion = 2;
this.Features.FavoritesMode = FavoritesMode.OrderedPerSource;
this.Features.MaxFavoriteLists = 1;
@@ -292,19 +313,6 @@ namespace ChanSort.Loader.Philips
hasEncrypt = setupNode.HasAttribute("Scrambled");
}
else if (setupNode.HasAttribute("name"))
{
file.formatVersion = 2;
this.Features.FavoritesMode = FavoritesMode.None;
foreach (var list in this.DataRoot.ChannelLists)
{
list.VisibleColumnFieldNames.Remove("Favorites");
list.VisibleColumnFieldNames.Remove("Lock");
list.VisibleColumnFieldNames.Remove("Hidden");
list.VisibleColumnFieldNames.Remove("ServiceTypeName");
list.VisibleColumnFieldNames.Remove("Encrypted");
}
}
else
throw new FileLoadException("Unknown data format");
@@ -353,9 +361,9 @@ namespace ChanSort.Loader.Philips
chan.OldProgramNr = -1;
chan.IsDeleted = false;
if (file.formatVersion == 1)
this.ParseChannelFormat1(data, chan);
this.ParseRepairFormat(data, chan);
else if (file.formatVersion == 2)
this.ParseChannelFormat2(data, chan);
this.ParseChannelMapFormat(data, chan);
if ((chan.SignalSource & SignalSource.MaskAdInput) == SignalSource.DvbT)
chan.ChannelOrTransponder = LookupData.Instance.GetDvbtTransponder(chan.FreqInMhz).ToString();
@@ -366,10 +374,30 @@ namespace ChanSort.Loader.Philips
}
#endregion
#region ParseChannelFormat1
private void ParseChannelFormat1(Dictionary<string,string> data, Channel chan)
#region ParseRepairFormat
private void ParseRepairFormat(Dictionary<string, string> data, Channel chan)
{
chan.Format = 1;
chan.OldProgramNr = ParseInt(data.TryGet("presetnumber"));
chan.Name = data.TryGet("name");
chan.RawName = chan.Name;
chan.FreqInMhz = ParseInt(data.TryGet("frequency"));
//if ((chan.SignalSource & SignalSource.Analog) != 0) // analog channels have some really strange values (e.g. 00080 - 60512) that I can't convert to a plausible freq range (48-856 MHz)
// chan.FreqInMhz /= 16;
if (chan.FreqInMhz > 1200 && (chan.SignalSource & SignalSource.Sat) == 0)
chan.FreqInMhz /= 1000;
chan.ServiceId = ParseInt(data.TryGet("serviceID"));
chan.OriginalNetworkId = ParseInt(data.TryGet("ONID"));
chan.TransportStreamId = ParseInt(data.TryGet("TSID"));
chan.ServiceType = ParseInt(data.TryGet("serviceType"));
chan.SymbolRate = ParseInt(data.TryGet("symbolrate")) / 1000;
}
#endregion
#region ParseChannelMapFormat
private void ParseChannelMapFormat(Dictionary<string,string> data, Channel chan)
{
chan.Format = 2;
chan.RawSatellite = data.TryGet("SatelliteName");
chan.Satellite = DecodeName(chan.RawSatellite);
chan.OldProgramNr = ParseInt(data.TryGet("ChannelNumber"));
@@ -410,26 +438,6 @@ namespace ChanSort.Loader.Philips
}
#endregion
#region ParseChannelFormat2
private void ParseChannelFormat2(Dictionary<string, string> data, Channel chan)
{
chan.Format = 2;
chan.OldProgramNr = ParseInt(data.TryGet("presetnumber"));
chan.Name = data.TryGet("name");
chan.RawName = chan.Name;
chan.FreqInMhz = ParseInt(data.TryGet("frequency"));
//if ((chan.SignalSource & SignalSource.Analog) != 0) // analog channels have some really strange values (e.g. 00080 - 60512) that I can't convert to a plausible freq range (48-856 MHz)
// chan.FreqInMhz /= 16;
if (chan.FreqInMhz > 1200 && (chan.SignalSource & SignalSource.Sat) == 0)
chan.FreqInMhz /= 1000;
chan.ServiceId = ParseInt(data.TryGet("serviceID"));
chan.OriginalNetworkId = ParseInt(data.TryGet("ONID"));
chan.TransportStreamId = ParseInt(data.TryGet("TSID"));
chan.ServiceType = ParseInt(data.TryGet("serviceType"));
chan.SymbolRate = ParseInt(data.TryGet("symbolrate")) / 1000;
}
#endregion
#region ReadFavList
private void ReadFavList(XmlNode node)
{
@@ -542,15 +550,25 @@ namespace ChanSort.Loader.Philips
}
if (ch.Format == 1)
this.UpdateChannelFormat1(ch, setFavoriteNumber);
this.UpdateRepairFormat(ch);
else if (ch.Format == 2)
this.UpdateChannelFormat2(ch);
this.UpdateChannelMapFormat(ch, setFavoriteNumber);
}
}
#endregion
#region UpdateChannelFormat1 and 2
private void UpdateChannelFormat1(Channel ch, bool setFavoriteNumber)
#region UpdateRepairFormat()
private void UpdateRepairFormat(Channel ch)
{
ch.SetupNode.Attributes["presetnumber"].Value = ch.NewProgramNr.ToString();
if (ch.IsNameModified)
ch.SetupNode.Attributes["name"].Value = ch.Name;
}
#endregion
#region UpdateChannelMapFormat()
private void UpdateChannelMapFormat(Channel ch, bool setFavoriteNumber)
{
ch.SetupNode.Attributes["ChannelNumber"].Value = ch.NewProgramNr.ToString();
@@ -574,18 +592,12 @@ namespace ChanSort.Loader.Philips
}
}
private void UpdateChannelFormat2(Channel ch)
{
ch.SetupNode.Attributes["presetnumber"].Value = ch.NewProgramNr.ToString();
if (ch.IsNameModified)
ch.SetupNode.Attributes["name"].Value = ch.Name;
}
#endregion
#region UpdateFavList
private void UpdateFavList()
{
var favFile = this.fileDataList.FirstOrDefault(fd => Path.GetFileName(fd.path).ToLower() == "favorite.xml");
var favFile = this.fileDataList.FirstOrDefault(fd => Path.GetFileName(fd.path).ToLowerInvariant() == "favorite.xml");
if (favFile == null)
return;
@@ -644,7 +656,7 @@ namespace ChanSort.Loader.Philips
#region ReorderNodes
private void ReorderNodes(FileData file)
{
if (file.formatVersion != 1)
if (file.formatVersion != 2)
return;
var nodes = file.doc.DocumentElement.GetElementsByTagName("Channel");

View File

@@ -120,7 +120,7 @@ namespace ChanSort.Loader.Samsung.Zip
cmd.CommandText = "select name from sqlite_master where type='table'";
using var r = cmd.ExecuteReader();
while (r.Read())
this.tableNames.Add(r.GetString(0).ToUpper());
this.tableNames.Add(r.GetString(0).ToUpperInvariant());
if (tableNames.Contains("SAT") && tableNames.Contains("SAT_TP"))
return FileType.SatDb;

View File

@@ -11,7 +11,7 @@ namespace ChanSort.Loader.Toshiba
public SerializerBase CreateSerializer(string inputFile)
{
if (Path.GetExtension(inputFile).ToLower() == ".db")
if (Path.GetExtension(inputFile).ToLowerInvariant() == ".db")
return new SettingsDbSerializer(inputFile);
else
return new ChmgtDbSerializer(inputFile);

View File

@@ -214,7 +214,7 @@ namespace ChanSort.Loader.VDR
#region ParseParams
private void ParseParams(String Params)
{
Params = Params.ToUpper();
Params = Params.ToUpperInvariant();
for (int i = 0; i < Params.Length; i++)
{
switch (Params[i])

View File

@@ -265,7 +265,7 @@ namespace ChanSort.Ui
{
filter.Append(plugin.PluginName).Append("|").Append(plugin.FileFilter);
filter.Append("|");
foreach (var ext in plugin.FileFilter.ToLower().Split(';'))
foreach (var ext in plugin.FileFilter.ToLowerInvariant().Split(';'))
{
if (!(";" + extension + ";").Contains(";" + ext + ";"))
{
@@ -533,10 +533,10 @@ namespace ChanSort.Ui
candidates.Add(hint);
else
{
var upperFileName = (Path.GetFileName(inputFileName) ?? "").ToUpper();
var upperFileName = (Path.GetFileName(inputFileName) ?? "").ToLowerInvariant();
foreach (var plugin in this.Plugins)
{
foreach (var filter in plugin.FileFilter.ToUpper().Split(';'))
foreach (var filter in plugin.FileFilter.ToLowerInvariant().Split(';'))
{
var regex = filter.Replace(".", "\\.").Replace("*", ".*").Replace("?", ".");
if (Regex.IsMatch(upperFileName, regex))
@@ -966,7 +966,7 @@ namespace ChanSort.Ui
fileName = dlg.FileName;
}
var ext = (Path.GetExtension(fileName) ?? "").ToLower();
var ext = (Path.GetExtension(fileName) ?? "").ToLowerInvariant();
if (ext == ".csv")
CsvRefListSerializer.Save(fileName, this.DataRoot);
else if (ext == ".chl" || ext == ".txt")
@@ -1652,7 +1652,7 @@ namespace ChanSort.Ui
private void SetFavorite(string fav, bool set)
{
if (string.IsNullOrEmpty(fav) || !this.mnuFavSet.Enabled) return;
int idx = char.ToUpper(fav[0]) - 'A';
int idx = char.ToUpperInvariant(fav[0]) - 'A';
if (idx < 0 || idx >= this.mnuFavSet.ItemLinks.Count || this.subListIndex == idx + 1) return;
var list = this.GetSelectedChannels(this.lastFocusedGrid);
if (list.Count == 0) return;

View File

@@ -347,7 +347,7 @@ namespace ChanSort
try
{
this.isExporting = true;
switch ((Path.GetExtension(dlg.FileName) ?? "").ToLower())
switch ((Path.GetExtension(dlg.FileName) ?? "").ToLowerInvariant())
{
case ".xlsx":
this.ExportToXlsx(dlg.FileName);

View File

@@ -0,0 +1,9 @@
// Copyright (c) 2015 by HHD Software Ltd.
// This file is part of the HHD Software Hex Editor
// For usage and distribution policies, consult the license distributed with a product installation program
// Get the current document size
function GetDocumentSize()
{
return document.FileSize;
}

View File

@@ -1,52 +1,77 @@
#include <stddefs.h>
struct SHeader
{
uint32 blockId;
uint32 blockSize;
uint16 u1;
uint16 u2;
uint32 numTvChannels;
uint32 numRadioChannels;
uint32 u3;
uint32 channelBlockId;
uint32 channelBlockSize;
};
struct SChannel
{
uint32 curProgNr;
uint32 u1;
uint8 u2[8];
uint32 favNr;
union
{
char chName1[200];
#pragma byte_order (BigEndian)
big_endian wchar_t chName2[100];
#pragma byte_order ()
struct
{
uint8 zero;
wchar_t chName3[99];
uint8 zero2;
} chName4;
} chName;
uint16 u3;
uint8 u3b[208];
uint8 u3c[2];
uint16 u3d;
uint8 u4[10];
uint16 freqInMhz1;
uint16 u5;
uint16 u6;
uint16 symRate;
uint32 curProgNr2;
uint32 prevProgNr;
uint16 tsid;
uint16 u7;
uint16 sid;
uint16 onid;
uint16 freqInMhz2;
uint16 u9;
uint32 u10;
};
struct SFooter
{
uint32 numDataBlocks;
uint32 numDataBlockBytes;
uint16 bytesumFrom0;
uint16 u_zero;
};
#pragma script("get_doc_size.js")
public struct Philips_mgr_chan_s_fta
{
uint8 header[64];
struct
{
uint32 curProgNr;
uint32 u1;
uint8 u2[8];
uint32 favNr;
union
{
char chName1[200];
//#pragma byte_order(BigEndian)
big_endian wchar_t chName2[100];
little_endian wchar_t chName3[100];
struct
{
uint8 zero;
wchar_t chName3[99];
uint8 zero2;
} chName4;
//#pragma byte_order(Default)
} chName;
uint16 u3;
uint8 u3b[208];
uint8 u3c[2];
uint16 u3d;
uint8 u4[10];
uint16 freqInMhz1;
uint16 u5;
uint16 u6;
uint16 symRate;
uint32 curProgNr2;
uint32 prevProgNr;
uint16 tsid;
uint16 u7;
uint16 sid;
uint16 onid;
uint16 freqInMhz2;
uint16 u9;
uint32 u10;
} channels[1231];
struct
{
uint8 u1[8];
uint16 wordsum;
uint8 u2[2];
} footer;
var docSize = GetDocumentSize();
char filename[32];
SHeader header;
var recordCount = header.channelBlockSize / sizeof(SChannel);
SChannel channels[recordCount];
SFooter footer;
};

View File

@@ -8,34 +8,34 @@ namespace Test.Loader.Philips
[TestClass]
public class PhilipsXmlTest
{
#region TestFormat1SatChannelsAddedToCorrectLists
#region TestRepairFormatCableChannelsAddedToCorrectLists
[TestMethod]
public void TestFormat1SatChannelsAddedToCorrectLists()
public void TestRepairFormatCableChannelsAddedToCorrectLists()
{
// this file format doesn't provide any information whether a channel is TV/radio/data or analog/digital. It only contains the "medium" for antenna/cable/sat
var file = TestUtils.DeploymentItem("Test.Loader.Philips\\TestFiles") + "\\Repair\\CM_TPM1013E_LA_CK.xml";
this.TestChannelsAddedToCorrectLists(file, SignalSource.DvbC, 483, 0, 0);
}
#endregion
#region TestChannelMapFormatSatChannelsAddedToCorrectLists
[TestMethod]
public void TestChannelMapFormatSatChannelsAddedToCorrectLists()
{
var file = TestUtils.DeploymentItem("Test.Loader.Philips\\TestFiles") + "\\ChannelMap_100\\ChannelList\\chanLst.bin";
this.TestChannelsAddedToCorrectLists(file, SignalSource.DvbS, 502, 350, 152);
}
#endregion
#region TestFormat1CableChannelsAddedToCorrectLists
#region TestChannelMapFormatCableChannelsAddedToCorrectLists
[TestMethod]
public void TestFormat1CableChannelsAddedToCorrectLists()
public void TestChannelMapFormatCableChannelsAddedToCorrectLists()
{
var file = TestUtils.DeploymentItem("Test.Loader.Philips\\TestFiles") + "\\ChannelMap_100\\ChannelList\\chanLst.bin";
this.TestChannelsAddedToCorrectLists(file, SignalSource.DvbC, 459, 358, 101);
}
#endregion
#region TestFormat2CableChannelsAddedToCorrectLists
[TestMethod]
public void TestFormat2CableChannelsAddedToCorrectLists()
{
// this file format doesn't provide any information whether a channel is TV/radio/data or analog/digital. It only contains the "medium" for antenna/cable/sat
var file = TestUtils.DeploymentItem("Test.Loader.Philips\\TestFiles") + "\\Repair\\CM_TPM1013E_LA_CK.xml";
this.TestChannelsAddedToCorrectLists(file, SignalSource.DvbC, 483, 0, 0);
}
#endregion
#region TestChannelsAddedToCorrectList
private void TestChannelsAddedToCorrectLists(string filePath, SignalSource signalSource, int expectedTotal, int expectedTv, int expectedRadio)

View File

@@ -1,11 +1,16 @@
ChanSort Change Log
===================
TBD
2021-08-31
- ChanSort didn't work properly for Turkish (and other system locales) that don't translate ".bin" to uppercase
".BIN" and ".BIN" to lowercase ".bin".
- Sony: Files with incorrect checksum are no longer rejected. Information about a bad checksum is visible
unter File / File Information. (The TV seems to ignore bad checksums during the import and the official
Sony PC Editor ignores bad checksums and write incorrect ones, depending on the file format version)
- Philips: experimental support for Repair\mgr_chan_s_fta.db file format (DVB-S only)
- Philips: Removing a channel from a list is no longer possible (because it is not supported by the TV's import).
When saving a file, all unsorted channels will be placed at the end of the list.
- Added read-only support for Philips Repair\\Mgr_chan_s_fta.db lists. Files can be used as a reference list,
but modifying them won't be possible.
- Updated Hungarian translation. Thanks to efi99 on Github!
2021-07-27