mirror of
https://github.com/PredatH0r/ChanSort.git
synced 2026-02-03 21:19:02 +01:00
- 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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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} "
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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"];
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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")))
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user