mirror of
https://github.com/PredatH0r/ChanSort.git
synced 2026-02-26 16:20:43 +01:00
- specific .ini settings for various Philips ChannelMap_xxx versions and sub-variants for version 100
- lots of documentation around Philips lists - working configuration for ChannelMap_100 variant with cmdb files (redordering confirmed, hide/lock/rename/favorites are best-effort) - pressing the "Del"-key on the keyboard no longer deletes a channel when a text editor is open - dragging a file (or something else) from outside ChanSort over the ChanSort window no longer creates an error - opening a file containing a read-only channel list now shows the original numbers
This commit is contained in:
@@ -1,4 +1,39 @@
|
||||
# 1.x format
|
||||
############################################################################
|
||||
# Repair\CM_*_LA_CK.BIN file (or similar) with a hidden .xml - stable
|
||||
|
||||
[Repair_xml]
|
||||
reorderRecordsByChannelNumber=false
|
||||
|
||||
|
||||
############################################################################
|
||||
# Repair\channel_db_ver.db, atv_chan_phy_c.db, FLASH_DTVINFO_S_FTA, mgr_chan_s_fta.db, ... - experimental
|
||||
# unfortunately read-only because all attempts so far produced inconsistencies between the channels in the menu and what the tuner actually put on screen
|
||||
|
||||
[mgr_chan_s_fta.db]
|
||||
lenHeader=64
|
||||
lenEntry=476
|
||||
lenFooter=12
|
||||
offFooterChecksum=8
|
||||
reorderRecordsByChannelNumber=false
|
||||
allowEdit=false
|
||||
|
||||
[mgr_chan_s_fta.db_entry]
|
||||
# there is a program number at offset 0 and 452. My guess is that 0 is the "new" number and 452 the "old" number, which should be left untouched. Or it is the other way around.
|
||||
# when both numbers are updated and also the value at 456 set to PrNr-1, the TV didn't show any changes.
|
||||
offProgNr=0
|
||||
offName=20
|
||||
offFav=16
|
||||
lenName=200
|
||||
offFreq=444,468
|
||||
offSymbolRate=450
|
||||
offRecordIndex=456
|
||||
offTsid=460
|
||||
offSid=464
|
||||
offOnid=466
|
||||
|
||||
|
||||
############################################################################
|
||||
# Repair\ChannelList\chanLst.bin version 1.x with AntennaDigSrvTable, CableDigSrvTable and service.dat (for DVB-S) - should be stable
|
||||
|
||||
[service.dat_entry]
|
||||
offPcrPid=0
|
||||
@@ -45,7 +80,26 @@ offChecksum=0
|
||||
offSymbolRate=8
|
||||
offFreq=18
|
||||
|
||||
# ChannelMap_45 format (also used for ChannelMap_30)
|
||||
|
||||
############################################################################
|
||||
# PhilipsChannelMaps\ChannelMap_11 with AntennaDigSrvTable, CableDigSrvTable, SatelliteDigSrvTable and service.dat - not supported
|
||||
|
||||
|
||||
############################################################################
|
||||
# ChannelMap_30 with list.db, tv.db, CableChannelMaps.db, CableDb.bin, TerrestrialChannelMaps.db, TerrestrialDb.bin, SatelliteChannelMaps.db, SatelliteDb.bin - experimental
|
||||
# uses the [Map45_...] mappings for the *Db.bin files
|
||||
|
||||
[Map30]
|
||||
incrementFavListVersion=false
|
||||
reorderRecordsByChannelNumber=false
|
||||
|
||||
|
||||
############################################################################
|
||||
# ChannelMap_45 with list.db, tv.db, HsvDvbCSettings, CableDb.bin, HsvDvbTSettings.bin, TerrestrialDb.bin, SatelliteDb.bin - experimental
|
||||
|
||||
[Map45]
|
||||
incrementFavListVersion=false
|
||||
reorderRecordsByChannelNumber=false
|
||||
|
||||
[Map45_CableDb.bin_entry]
|
||||
offId=0
|
||||
@@ -89,57 +143,67 @@ offUnk1=48
|
||||
offUnk2=68
|
||||
offPolarity=72
|
||||
|
||||
[Map30]
|
||||
incrementFavListVersion=true
|
||||
|
||||
[Map45]
|
||||
incrementFavListVersion=true
|
||||
############################################################################
|
||||
# ChannelMap_100 with DVBC.xml, DVBT.xml, DVBS.xml, DVBSall.xml
|
||||
# This format has different variants without a unique sub-version number:
|
||||
# 1) with a channelFile.bin, no indentation, uppercase hex digits, padded names, no "Scramble" attribute
|
||||
# 2) without .bin files, no indentation, uppercase hex digits, padded names, a "Scramble" attribute
|
||||
# 3) with additional *tv_cmdb*.bin files, indentation in XML, lowercase hex digits, unpadded names, a "Scramble" attribute and requirement to keep record order between .xml and .bin in-sync. Often with a "Clone" folder. - stable
|
||||
|
||||
[Map100]
|
||||
# setFavoriteNumber: true|false; if false, the FavoriteNumber attribute won't be changed
|
||||
setFavoriteNumber=true
|
||||
#setReorderedFavNumber: true|false; if true, favorites can be in a different order than the main program numbers; default: false
|
||||
setReorderedFavNumber=true
|
||||
# reorderRecordsByChannelNumber: true|false; defines whether the element lines in the XML file are reordered by their ChannelNumber or kept at their location; default: false
|
||||
reorderRecordsByChannelNumber=true
|
||||
# padChannelName: true|false; if true, fill the hex-encoded channel name with 0x00 0x00 to maintain a fixed length; default: true
|
||||
padChannelName=true
|
||||
# allowDelete: true|false; if true, channels can be removed from the .xml. This breaks channel lists that contain .bin files that must be kept in-sync; default: false
|
||||
allowDelete=true
|
||||
|
||||
#setReorderedFavNumber: true to allow favorite numbers in a different order than the main program number; false to enforce same order; default: false
|
||||
setReorderedFavNumber=false
|
||||
# settings for the ChannelMap_100 variant that includes a channelFile.bin file
|
||||
[Map100_channelFile.bin]
|
||||
setFavoriteNumber=true
|
||||
setReorderedFavNumber=true
|
||||
reorderRecordsByChannelNumber=false
|
||||
padChannelName=true
|
||||
allowDelete=false
|
||||
|
||||
# settings for the ChannelMap_100 variant that includes an atv_cmdb.bin file
|
||||
[Map100_cmdb.bin]
|
||||
setFavoriteNumber=true
|
||||
setReorderedFavNumber=true
|
||||
reorderRecordsByChannelNumber=false
|
||||
padChannelName=false
|
||||
allowDelete=false
|
||||
|
||||
|
||||
############################################################################
|
||||
# ChannelMap_105: channelFile.bin, Favorite.xml, *.txt, *.xml.
|
||||
# No XML indentation, added <SatelliteListcopy> element, uppercase hex, padded names, "Scrambled" attribute (with a "d" at the end)
|
||||
|
||||
[Map105]
|
||||
incrementFavListVersion=true
|
||||
setFavoriteNumber=false
|
||||
satelliteListcopy=remove
|
||||
|
||||
[Map110]
|
||||
# satelliteListcopy: true|false|remove|(empty); when empty the original value is kept as-is; "remove" removes the XML element; default: empty
|
||||
satelliteListcopy=remove
|
||||
|
||||
# reorderXmlNodesByChannelNumber: true|false; defines whether the element lines in the XML file are reordered by their ChannelNumber or kept at their location; default: true
|
||||
reorderXmlNodesByChannelNumber=true
|
||||
|
||||
# setFavoriteNumber: true|false; if false (default), the FavoriteNumber attribute will always be 0 in format 105,110 and the actual number is defined in the Favorite.xml file; default: false
|
||||
setFavoriteNumber=false
|
||||
|
||||
# userReorderChannel: 0|1|remove|(blank); when blank the original value is kept as-is, "remove" removes the attribute, 0 and 1 are written as literals; default: 0
|
||||
userReorderChannel=0
|
||||
|
||||
setReorderedFavNumber=false
|
||||
reorderRecordsByChannelNumber=false
|
||||
# incrementFavListVersion: true|false; when true the Version attribute in the Favorite.xml file gets incremented every time the file is saved; default: false
|
||||
incrementFavListVersion=false
|
||||
allowDelete=false
|
||||
|
||||
|
||||
############################################################################
|
||||
# ChannelMap_110: same as 105 with an additional "UserReorderChannel" attribute (which should probably left unchanged, even after reordering)
|
||||
|
||||
# Format with Repair\ folder containing channel_db_ver.db, atv_chan_phy_c.db, FLASH_DTVINFO_S_FTA, mgr_chan_s_fta.db, ...
|
||||
|
||||
[mgr_chan_s_fta.db]
|
||||
lenHeader=64
|
||||
lenEntry=476
|
||||
lenFooter=12
|
||||
offFooterChecksum=8
|
||||
|
||||
[mgr_chan_s_fta.db_entry]
|
||||
offProgNr=0,452
|
||||
offName=20
|
||||
offFav=16
|
||||
lenName=200
|
||||
offFreq=444,468
|
||||
offSymbolRate=450
|
||||
offPrevProgNr=456
|
||||
offTsid=460
|
||||
offSid=464
|
||||
offOnid=466
|
||||
[Map110]
|
||||
satelliteListcopy=remove
|
||||
setFavoriteNumber=false
|
||||
setReorderedFavNumber=false
|
||||
# userReorderChannel: 0|1|remove|(blank); when blank the original value is kept as-is, "remove" removes the attribute, 0 and 1 are written as literals; default: 0
|
||||
userReorderChannel=0
|
||||
reorderRecordsByChannelNumber=false
|
||||
incrementFavListVersion=false
|
||||
allowDelete=false
|
||||
|
||||
@@ -47,7 +47,9 @@ namespace ChanSort.Loader.Philips
|
||||
nameof(Channel.OriginalNetworkId),
|
||||
nameof(Channel.ServiceId)
|
||||
};
|
||||
dvbsChannels.ReadOnly = true;
|
||||
|
||||
var sec = ini.GetSection("mgr_chan_s_fta.db");
|
||||
dvbsChannels.ReadOnly = sec.GetBool("allowEdit", false);
|
||||
}
|
||||
|
||||
#region Load()
|
||||
@@ -168,37 +170,42 @@ 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)
|
||||
{
|
||||
mapping.SetDataPtr(data, lenHeader + ch.RecordOrder * lenEntry);
|
||||
mapping.SetWord("offProgNr", ch.NewProgramNr);
|
||||
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))
|
||||
if (sec.GetBool("reorderRecordsByChannelNumber"))
|
||||
{
|
||||
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;
|
||||
// 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
// update channel data
|
||||
foreach (var ch in dvbsChannels.Channels)
|
||||
{
|
||||
mapping.SetDataPtr(data, lenHeader + ch.RecordOrder * lenEntry);
|
||||
mapping.SetWord("offProgNr", ch.NewProgramNr);
|
||||
//mapping.SetWord("offPrevProgNr", ch.NewProgramNr - 1);
|
||||
mapping.SetWord("offFav", Math.Max(0, ch.GetPosition(1)));
|
||||
}
|
||||
}
|
||||
|
||||
data = newData;
|
||||
#endif
|
||||
// update checksum
|
||||
var offChecksum = data.Length - lenFooter + offFooterChecksum;
|
||||
var checksum = CalcChecksum(data, 0, offChecksum);
|
||||
|
||||
@@ -34,12 +34,17 @@ namespace ChanSort.Loader.Philips
|
||||
The Philips editor updates the checksums in chanLst.bin (but that file does not include the DVBS.xml file, only DVBT.xml, DVBC.xml an DVBSall.xml)
|
||||
|
||||
The ChannelMap_100 formats can also be edited with Onka editor. Unlike the Philips editor, this one sorts the XML nodes by their new ChannelNumber.
|
||||
Onka can also read/write formats 105 and 110, but removes all XML attributes that it doesn't know (and didn't exist in 100), like "Scrambled" and "UserReorderChannel".
|
||||
It adds an XML namespace, indentation and uses short closing tags and removes the <SatelliteListcopy> element from format 105/110.
|
||||
Onka does not update chanLst.bin (which isn't required when only DVBS.xml is modified)
|
||||
Nevertheless a user reported that swapping DVB-S channels 1 and 2 with Onka on a TV that uses format 110 worked for him.
|
||||
|
||||
Onka can also read/write formats 105 and 110, but removes all XML attributes that it doesn't know (and didn't exist in 100), like "Scramble"/"Scrambled" and "UserReorderChannel".
|
||||
It adds an XML namespace, indentation, uses short closing tags and removes the <SatelliteListcopy> element from format 105/110.
|
||||
Onka does not update chanLst.bin (which isn't required when only DVBS.xml is modified since that file has no checksum in chanLst.bin)
|
||||
Nevertheless a user reported that swapping DVB-S channels 1 and 2 with Onka on a TV that uses this xml-only format 110 worked for him.
|
||||
|
||||
There seem to be 3 different flavors or the "100" format:
|
||||
One has only .xml files in the channellib and s2channellib folders, does not indent lines in the .xml files, has a fixed number of bytes for channel and satellite names (padded with 0x00) and has no "Scramble" attribute.
|
||||
And a version that has dtv_cmdb_*.bin next to the .xml files, uses 4 spaces for indentation, only writes as many bytes for names as needed and has a "Scramble" attribute.
|
||||
While the first seems to work fine when XML nodes are reordered by their new programNr, the latter seems to get confused when the .bin and .xml files have different data record orders. This is still under investigation.
|
||||
The Philips editor does not modify these .bin files, appends 0x00 padding to the channel names, changes indentation to 2 tabs and strips the Scramble attribute. It's likely it wasn't designed for this type of list.
|
||||
|
||||
|
||||
<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" />
|
||||
@@ -104,17 +109,17 @@ namespace ChanSort.Loader.Philips
|
||||
this.DataRoot.AddChannelList(this.allSatChannels);
|
||||
//this.DataRoot.AddChannelList(this.favChannels); // format 100.0 does not support mixed source favs and adding it would automatically switch to mixed source fav mode
|
||||
|
||||
this.dvbtChannels.VisibleColumnFieldNames.Add("Source");
|
||||
this.dvbcChannels.VisibleColumnFieldNames.Add("Source");
|
||||
this.dvbtChannels.VisibleColumnFieldNames.Add(nameof(ChannelInfo.Source));
|
||||
this.dvbcChannels.VisibleColumnFieldNames.Add(nameof(ChannelInfo.Source));
|
||||
|
||||
foreach (var list in this.DataRoot.ChannelLists)
|
||||
{
|
||||
list.VisibleColumnFieldNames.Remove("PcrPid");
|
||||
list.VisibleColumnFieldNames.Remove("VideoPid");
|
||||
list.VisibleColumnFieldNames.Remove("AudioPid");
|
||||
list.VisibleColumnFieldNames.Remove("Skip");
|
||||
list.VisibleColumnFieldNames.Remove("ShortName");
|
||||
list.VisibleColumnFieldNames.Remove("Provider");
|
||||
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.PcrPid));
|
||||
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.VideoPid));
|
||||
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.AudioPid));
|
||||
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.Skip));
|
||||
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.ShortName));
|
||||
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.Provider));
|
||||
}
|
||||
|
||||
this.analogChannels.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.OriginalNetworkId));
|
||||
@@ -301,14 +306,15 @@ namespace ChanSort.Loader.Philips
|
||||
if (setupNode.HasAttribute("name"))
|
||||
{
|
||||
file.formatVersion = 1;
|
||||
this.iniMapSection = ini.GetSection("Repair_xml");
|
||||
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");
|
||||
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.Favorites));
|
||||
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.Lock));
|
||||
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.Hidden));
|
||||
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.ServiceTypeName));
|
||||
list.VisibleColumnFieldNames.Remove(nameof(ChannelInfo.Encrypted));
|
||||
}
|
||||
}
|
||||
else if (setupNode.HasAttribute("ChannelName"))
|
||||
@@ -325,7 +331,7 @@ namespace ChanSort.Loader.Philips
|
||||
else if (dtype == "3")
|
||||
medium = "dvbs";
|
||||
|
||||
hasEncrypt = setupNode.HasAttribute("Scrambled");
|
||||
hasEncrypt = setupNode.HasAttribute("Scramble") || setupNode.HasAttribute("Scrambled");
|
||||
}
|
||||
else
|
||||
throw new FileLoadException("Unknown data format");
|
||||
@@ -354,16 +360,27 @@ namespace ChanSort.Loader.Philips
|
||||
chList?.VisibleColumnFieldNames.Remove("Encrypted");
|
||||
|
||||
var ver = this.chanLstBin?.VersionMajor ?? 0;
|
||||
this.iniMapSection = ini.GetSection("Map" + ver);
|
||||
if (ver > 0)
|
||||
this.iniMapSection = ini.GetSection("Map" + ver);
|
||||
|
||||
if (ver >= 105)
|
||||
this.Features.FavoritesMode = FavoritesMode.OrderedPerSource;
|
||||
this.Features.FavoritesMode = FavoritesMode.OrderedPerSource; // will be overridden when a Favorite.xml file is found
|
||||
else if (ver == 100)
|
||||
{
|
||||
// use special configs for version 100 variants
|
||||
var dir = Path.GetDirectoryName(this.FileName) ?? "";
|
||||
if (File.Exists(Path.Combine(dir, "atv_cmdb.bin")))
|
||||
this.iniMapSection = ini.GetSection("Map100_cmdb.bin");
|
||||
else if (File.Exists(Path.Combine(dir, "channelFile.bin")))
|
||||
this.iniMapSection = ini.GetSection("Map100_channelFile.bin");
|
||||
|
||||
if (this.iniMapSection?.GetBool("setReorderedFavNumber") ?? false)
|
||||
this.Features.FavoritesMode = FavoritesMode.OrderedPerSource;
|
||||
}
|
||||
|
||||
if (this.iniMapSection?.GetBool("allowDelete", false) ?? false)
|
||||
this.Features.DeleteMode = DeleteMode.Physically;
|
||||
|
||||
return chList;
|
||||
}
|
||||
#endregion
|
||||
@@ -386,9 +403,9 @@ namespace ChanSort.Loader.Philips
|
||||
chan.OldProgramNr = -1;
|
||||
chan.IsDeleted = false;
|
||||
if (file.formatVersion == 1)
|
||||
this.ParseRepairFormat(data, chan);
|
||||
this.ParseRepairXml(data, chan);
|
||||
else if (file.formatVersion == 2)
|
||||
this.ParseChannelMapFormat(data, chan);
|
||||
this.ParseChannelMapXml(data, chan);
|
||||
|
||||
if ((chan.SignalSource & SignalSource.MaskAdInput) == SignalSource.DvbT)
|
||||
chan.ChannelOrTransponder = LookupData.Instance.GetDvbtTransponder(chan.FreqInMhz).ToString();
|
||||
@@ -399,8 +416,8 @@ namespace ChanSort.Loader.Philips
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ParseRepairFormat
|
||||
private void ParseRepairFormat(Dictionary<string, string> data, Channel chan)
|
||||
#region ParseRepairXml()
|
||||
private void ParseRepairXml(Dictionary<string, string> data, Channel chan)
|
||||
{
|
||||
chan.Format = 1;
|
||||
chan.OldProgramNr = ParseInt(data.TryGet("presetnumber"));
|
||||
@@ -419,8 +436,8 @@ namespace ChanSort.Loader.Philips
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ParseChannelMapFormat
|
||||
private void ParseChannelMapFormat(Dictionary<string,string> data, Channel chan)
|
||||
#region ParseChannelMapXml()
|
||||
private void ParseChannelMapXml(Dictionary<string,string> data, Channel chan)
|
||||
{
|
||||
chan.Format = 2;
|
||||
chan.RawSatellite = data.TryGet("SatelliteName");
|
||||
@@ -459,11 +476,11 @@ namespace ChanSort.Loader.Philips
|
||||
chan.Polarity = pol == "0" ? 'H' : 'V';
|
||||
chan.Hidden |= data.TryGet("SystemHidden") == "1";
|
||||
|
||||
chan.Encrypted = data.TryGet("Scrambled") == "1"; // introduced in ChannelMap_105 format
|
||||
chan.Encrypted = data.TryGet("Scramble") == "1" || data.TryGet("Scrambled") == "1"; // v100 sometimes contains a "Scramble", v105/v110 always contain "Scrambled"
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ReadFavList
|
||||
#region ReadFavList()
|
||||
private void ReadFavList(XmlNode node)
|
||||
{
|
||||
int index = ParseInt(node.Attributes["Index"].InnerText);
|
||||
@@ -544,10 +561,18 @@ namespace ChanSort.Loader.Philips
|
||||
this.UpdateChannelList(list);
|
||||
}
|
||||
|
||||
var reorderNodes = this.iniMapSection?.GetBool("reorderXmlNodesByChannelNumber", true) ?? true;
|
||||
// It is unclear whether XML nodes must be sorted by the new program number or kept in the original order. This may be different for the various format versions.
|
||||
// Onka, which was made for the ChannelMap_100 flavor that doesn't export dtv_cmdb_2.bin files, reorders the XML nodes and users reported that it works.
|
||||
// The official Philips Editor 6.61.22 does not reorder the XML nodes and does not change dtv_cmdb_*.bin when editing a ChannelMap_100 folder. But it is unclear if this editor is designed to handle the cmdb flavor.
|
||||
|
||||
// A user with a ChannelMap_100 export including a dtv_cmdb_2.bin reported, that the TV shows the reordered list in the menu, but tunes the channels based on the original numbers.
|
||||
// It's unclear if that happenes because the XML was reordered and out-of-sync with the .bin, or if the TV always uses the .bin for tuning and XML edits are moot.
|
||||
// On top of that this TV messed up Umlauts during the import, despite ChanSort writing the exact same name data in hex-encoded UTF16. The result was as if the string was exported as UTF-8 bytes and then parsed with an 8-bit code page.
|
||||
var reorderNodes = this.iniMapSection?.GetBool("reorderRecordsByChannelNumber") ?? false;
|
||||
|
||||
foreach (var file in this.fileDataList)
|
||||
{
|
||||
if (reorderNodes && Path.GetFileName(file.path).ToLowerInvariant().StartsWith("dvb"))
|
||||
if (reorderNodes && (file.formatVersion == 1 || Path.GetFileName(file.path).ToLowerInvariant().StartsWith("dvb")))
|
||||
this.ReorderNodes(file);
|
||||
var satelliteListcopy = this.iniMapSection?.GetString("satelliteListcopy") ?? "";
|
||||
var nodeList = file.doc.GetElementsByTagName("SatelliteListcopy");
|
||||
@@ -576,6 +601,7 @@ namespace ChanSort.Loader.Philips
|
||||
#region UpdateChannelList()
|
||||
private void UpdateChannelList(ChannelList list)
|
||||
{
|
||||
var padChannelNameBytes = this.iniMapSection?.GetBool("padChannelName", true) ?? true;
|
||||
var setFavoriteNumber = this.iniMapSection?.GetBool("setFavoriteNumber", false) ?? false;
|
||||
var userReorderChannel = this.iniMapSection?.GetString("userReorderChannel") ?? "";
|
||||
|
||||
@@ -592,16 +618,16 @@ namespace ChanSort.Loader.Philips
|
||||
}
|
||||
|
||||
if (ch.Format == 1)
|
||||
this.UpdateRepairFormat(ch);
|
||||
this.UpdateRepairXml(ch);
|
||||
else if (ch.Format == 2)
|
||||
this.UpdateChannelMapFormat(ch, setFavoriteNumber, userReorderChannel);
|
||||
this.UpdateChannelMapXml(ch, padChannelNameBytes, setFavoriteNumber, userReorderChannel);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UpdateRepairFormat()
|
||||
#region UpdateRepairXml()
|
||||
|
||||
private void UpdateRepairFormat(Channel ch)
|
||||
private void UpdateRepairXml(Channel ch)
|
||||
{
|
||||
ch.SetupNode.Attributes["presetnumber"].Value = ch.NewProgramNr.ToString();
|
||||
if (ch.IsNameModified)
|
||||
@@ -609,42 +635,59 @@ namespace ChanSort.Loader.Philips
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UpdateChannelMapFormat()
|
||||
private void UpdateChannelMapFormat(Channel ch, bool setFavoriteNumber, string userReorderChannel)
|
||||
#region UpdateChannelMapXml()
|
||||
private void UpdateChannelMapXml(Channel ch, bool paddedName, bool setFavoriteNumber, string userReorderChannel)
|
||||
{
|
||||
ch.SetupNode.Attributes["ChannelNumber"].Value = ch.NewProgramNr.ToString();
|
||||
var setup = ch.SetupNode.Attributes;
|
||||
setup["ChannelNumber"].Value = ch.NewProgramNr.ToString();
|
||||
|
||||
if (ch.IsNameModified)
|
||||
{
|
||||
ch.SetupNode.Attributes["ChannelName"].InnerText = EncodeName(ch.Name, (ch.SetupNode.Attributes["ChannelName"].InnerText.Length + 1) / 5, true);
|
||||
var attr = ch.SetupNode.Attributes["UserModifiedName"];
|
||||
|
||||
setup["ChannelName"].InnerText = EncodeName(ch.Name, 50, paddedName, paddedName);
|
||||
var attr = setup["UserModifiedName"];
|
||||
if (attr != null)
|
||||
attr.InnerText = "1";
|
||||
}
|
||||
|
||||
// ChannelMap_100 supports a single fav list and stores the favorite number directly here in the channel.
|
||||
// The official Philips editor forces the favorites to be in the same order as the main program number. I don't know if this is a requirement or just a limitation of the editor.
|
||||
setup["ChannelLock"].Value = ch.Lock ? "1" : "0";
|
||||
setup["UserHidden"].Value = ch.Hidden ? "1" : "0";
|
||||
|
||||
// ChannelMap_105 and later always store the value 0 in the channel and instead use a separate Favorites.xml file.
|
||||
ch.SetupNode.Attributes["FavoriteNumber"].Value = setFavoriteNumber ? Math.Max(ch.GetPosition(1), 0).ToString() : "0";
|
||||
// ChannelMap_100 supports a single fav list and stores the favorite number directly in the channel.
|
||||
// The official Philips editor allows to reorder favorites when switched to the "Favourite" list view
|
||||
|
||||
var urc = ch.SetupNode.Attributes["UserReorderChannel"]; // introduced with format 110, but not always present
|
||||
if (userReorderChannel == "")
|
||||
userReorderChannel = "0";
|
||||
if (userReorderChannel == "delete" || userReorderChannel == "remove")
|
||||
urc.OwnerElement?.RemoveAttributeNode(urc);
|
||||
else if (userReorderChannel == "auto")
|
||||
// ChannelMap_105 and later always store the value 0 and instead use a separate Favorites.xml file with mixed-source channels.
|
||||
setup["FavoriteNumber"].Value = setFavoriteNumber ? Math.Max(ch.GetPosition(1), 0).ToString() : "0";
|
||||
|
||||
// "UserReorderChannel" was introduced with format 110, but not always present.
|
||||
// It is unclear if this should be 0, 1, or removed for the import to work.
|
||||
// One user reported a 110 format file edited with Onka (which basically reverted the file to format 100 and removed UserReorderChannel) worked for him,
|
||||
// while my attempt with ChanSort and setting UserReorderChannel=1 didn't work. But maybe that was due to other factors.
|
||||
var urc = setup["UserReorderChannel"];
|
||||
if (urc != null)
|
||||
{
|
||||
if (urc != null && ch.OldProgramNr != ch.NewProgramNr)
|
||||
urc.InnerText = "1";
|
||||
if (userReorderChannel == "")
|
||||
userReorderChannel = "0";
|
||||
switch (userReorderChannel)
|
||||
{
|
||||
case "delete":
|
||||
case "remove":
|
||||
urc.OwnerElement?.RemoveAttributeNode(urc);
|
||||
break;
|
||||
case "auto":
|
||||
if (ch.OldProgramNr != ch.NewProgramNr)
|
||||
urc.InnerText = "1";
|
||||
break;
|
||||
default:
|
||||
urc.InnerText = userReorderChannel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (urc != null)
|
||||
urc.InnerText = userReorderChannel;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UpdateFavList
|
||||
#region UpdateFavList()
|
||||
private void UpdateFavList()
|
||||
{
|
||||
var favFile = this.fileDataList.FirstOrDefault(fd => Path.GetFileName(fd.path).ToLowerInvariant() == "favorite.xml");
|
||||
@@ -658,7 +701,7 @@ namespace ChanSort.Loader.Philips
|
||||
favListNode.InnerXml = ""; // clear all <FavoriteChannel> child elements but keep the attributes of the current node
|
||||
var attr = favListNode.Attributes?["Name"];
|
||||
if (attr != null)
|
||||
attr.InnerText = EncodeName(this.favChannels.GetFavListCaption(index - 1), (attr.InnerText.Length + 1)/5, false);
|
||||
attr.InnerText = EncodeName(this.favChannels.GetFavListCaption(index - 1), (attr.InnerText.Length + 1)/5 /* 64 */, true, false);
|
||||
|
||||
// increment fav list version, unless disabled in .ini file
|
||||
if (chanLstBin != null && (ini.GetSection("Map" + chanLstBin.VersionMajor)?.GetBool("incrementFavListVersion", true) ?? true))
|
||||
@@ -686,28 +729,32 @@ namespace ChanSort.Loader.Philips
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeName
|
||||
private string EncodeName(string name, int numBytes, bool upperCaseHexDigits)
|
||||
#region EncodeName()
|
||||
private string EncodeName(string name, int maxBytes, bool padBytes, bool upperCaseHexDigits)
|
||||
{
|
||||
var bytes = Encoding.Unicode.GetBytes(name);
|
||||
var sb = new StringBuilder();
|
||||
var pattern = upperCaseHexDigits ? "0x{0:X2} " : "0x{0:x2} ";
|
||||
for (int i = 0; i < numBytes - 2; i++)
|
||||
var len = Math.Min(bytes.Length, padBytes ? maxBytes-2 : maxBytes); // when padding, always add a 0x00 0x00 end-of-string
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
sb.AppendFormat(pattern, bytes[i]);
|
||||
if (padBytes)
|
||||
{
|
||||
var b = i < bytes.Length ? bytes[i] : 0;
|
||||
sb.AppendFormat(pattern, b);
|
||||
for (; i < maxBytes; i++)
|
||||
sb.Append("0x00 ");
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
}
|
||||
|
||||
sb.Append("0x00 0x00"); // always add an end-of-string
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ReorderNodes
|
||||
#region ReorderNodes()
|
||||
private void ReorderNodes(FileData file)
|
||||
{
|
||||
if (file.formatVersion != 2)
|
||||
return;
|
||||
var progNrAttrib = file.formatVersion == 1 ? "presetnumber" : "ChannelNumer";
|
||||
|
||||
var nodes = file.doc.DocumentElement.GetElementsByTagName("Channel");
|
||||
var list = new List<XmlElement>();
|
||||
@@ -715,7 +762,7 @@ namespace ChanSort.Loader.Philips
|
||||
list.Add((XmlElement)node);
|
||||
foreach (var node in list)
|
||||
file.doc.DocumentElement.RemoveChild(node);
|
||||
foreach(var node in list.OrderBy(elem => int.Parse(elem["Setup"].Attributes["ChannelNumber"].InnerText)))
|
||||
foreach(var node in list.OrderBy(elem => int.Parse(elem["Setup"].Attributes[progNrAttrib].InnerText)))
|
||||
file.doc.DocumentElement.AppendChild(node);
|
||||
}
|
||||
#endregion
|
||||
@@ -758,10 +805,13 @@ namespace ChanSort.Loader.Philips
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetFileInformation()
|
||||
public override string GetFileInformation()
|
||||
{
|
||||
return base.GetFileInformation() + this.logMessages.Replace("\n", "\r\n");
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region class FileData
|
||||
private class FileData
|
||||
|
||||
Reference in New Issue
Block a user