Group support and multiple package import.
1.1 --- a/KingOfSat.cs Fri May 15 22:41:33 2015 +0200
1.2 +++ b/KingOfSat.cs Sat May 16 01:31:32 2015 +0200
1.3 @@ -9,148 +9,274 @@
1.4
1.5 namespace SatChanGen
1.6 {
1.7 - class KingOfSat
1.8 - {
1.9 - //
1.10 - // Summary:
1.11 - // Create a new CQ object wrapping a single element.
1.12 - //
1.13 - // Parameters:
1.14 - // aUrl:
1.15 - // URL to a KingOfSat channel list. Typically a package list.
1.16 - //
1.17 - // Return:
1.18 - // List of channels parsed.
1.19 - public static List<Channel> Parse(string aUrl, string aOrbitalPosition)
1.20 - {
1.21 - string kos = new WebClient().DownloadString(aUrl);
1.22 - //Debug.Write(kos);
1.23 + class KingOfSat
1.24 + {
1.25 + //
1.26 + // Summary:
1.27 + // Create a new CQ object wrapping a single element.
1.28 + //
1.29 + // Parameters:
1.30 + // aUrl:
1.31 + // URL to a KingOfSat channel list. Typically a package list.
1.32 + //
1.33 + // Return:
1.34 + // List of channels parsed.
1.35 + public static List<Channel> Parse(List<Channel> aChannels, string aUrl, string aOrbitalPosition)
1.36 + {
1.37 + //To avoid duplicated name
1.38 + Dictionary<string, int> names = new Dictionary<string, int>();
1.39
1.40 - CQ dom = kos;
1.41 + string kos = new WebClient().DownloadString(aUrl);
1.42 + //Debug.Write(kos);
1.43
1.44 - //Get all the Frequency elements in our page
1.45 - CQ sats = dom[".frq"];
1.46 + CQ dom = kos;
1.47
1.48 - //Create our list of channels
1.49 - List<Channel> channels = new List<Channel>();
1.50 + //Get all the Frequency elements in our page
1.51 + CQ sats = dom[".frq"];
1.52
1.53 - foreach (IDomObject frq in sats.ToList())
1.54 - {
1.55 - Channel common = new Channel();
1.56 + //Create our list of channels
1.57 + List<Channel> channels = new List<Channel>();
1.58
1.59 - //Parse channel details
1.60 - common.OrbitalPosition = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td > a > font").Get(0).InnerText).Trim();
1.61 - if (common.OrbitalPosition != aOrbitalPosition)
1.62 - {
1.63 + foreach (IDomObject frq in sats.ToList())
1.64 + {
1.65 + Channel common = new Channel();
1.66 +
1.67 + //Parse channel details
1.68 + common.OrbitalPosition = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td > a > font").Get(0).InnerText).Trim();
1.69 + if (common.OrbitalPosition != aOrbitalPosition)
1.70 + {
1.71 //Wrong sat, skip
1.72 - continue;
1.73 - }
1.74 - common.Satellite = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(2) > a").Get(0).InnerText);
1.75 - common.Frequency = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(3)").Get(0).InnerText);
1.76 - common.Polarisation = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(4)").Get(0).InnerText);
1.77 - common.Transponder = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(5) > a").Get(0).InnerText);
1.78 - common.Beam = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(6) > a").Get(0).InnerText);
1.79 - common.Standard = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(7)").Get(0).InnerText);
1.80 - common.Modulation = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(8)").Get(0).InnerText);
1.81 - common.SymbolRate = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(9) > a").Get(0).InnerText);
1.82 - common.FEC = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(9) > a:nth-child(2)").Get(0).InnerText);
1.83 - try
1.84 - {
1.85 - common.Provider = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(10) > b").Get(0).InnerText);
1.86 - }
1.87 - catch (Exception)
1.88 - {
1.89 - }
1.90 + continue;
1.91 + }
1.92 + common.Satellite = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(2) > a").Get(0).InnerText);
1.93 + common.Frequency = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(3)").Get(0).InnerText);
1.94 + common.Polarisation = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(4)").Get(0).InnerText);
1.95 + common.Transponder = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(5) > a").Get(0).InnerText);
1.96 + common.Beam = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(6) > a").Get(0).InnerText);
1.97 + common.Standard = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(7)").Get(0).InnerText);
1.98 + common.Modulation = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(8)").Get(0).InnerText);
1.99 + common.SymbolRate = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(9) > a").Get(0).InnerText);
1.100 + common.FEC = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(9) > a:nth-child(2)").Get(0).InnerText);
1.101 + try
1.102 + {
1.103 + common.Provider = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(10) > b").Get(0).InnerText);
1.104 + }
1.105 + catch (Exception)
1.106 + {
1.107 + }
1.108
1.109 - common.Bitrate = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(10)").Get(0).InnerText);
1.110 - if (common.Bitrate.Substring(0, ", ".Length) == ", ")
1.111 - {
1.112 - common.Bitrate = common.Bitrate.Substring(", ".Length, common.Bitrate.Length - ", ".Length);
1.113 - }
1.114 - //
1.115 - common.NetworkID = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(11)").Get(0).InnerText);
1.116 - common.NetworkID = common.NetworkID.Substring("NID:".Length, common.NetworkID.Length - "NID:".Length);
1.117 - //
1.118 - common.TransponderID = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(12)").Get(0).InnerText);
1.119 - common.TransponderID = common.TransponderID.Substring("TID:".Length, common.TransponderID.Length - "TID:".Length);
1.120 + common.Bitrate = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(10)").Get(0).InnerText);
1.121 + if (common.Bitrate.Substring(0, ", ".Length) == ", ")
1.122 + {
1.123 + common.Bitrate = common.Bitrate.Substring(", ".Length, common.Bitrate.Length - ", ".Length);
1.124 + }
1.125 + //
1.126 + common.NetworkID = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(11)").Get(0).InnerText);
1.127 + common.NetworkID = common.NetworkID.Substring("NID:".Length, common.NetworkID.Length - "NID:".Length);
1.128 + //
1.129 + common.TransponderID = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(12)").Get(0).InnerText);
1.130 + common.TransponderID = common.TransponderID.Substring("TID:".Length, common.TransponderID.Length - "TID:".Length);
1.131
1.132 - //We got common properties for the coming channels
1.133 - //Debug.Write(common.ToString());
1.134 + //We got common properties for the coming channels
1.135 + //Debug.Write(common.ToString());
1.136
1.137 - //Now get all the channels for that frequency
1.138 - //Channel common = new Channel();
1.139 + //Now get all the channels for that frequency
1.140 + //Channel common = new Channel();
1.141
1.142 - CQ channelsDiv = frq.Cq().Next("div");
1.143 - CQ channelsTableRows = channelsDiv.Find("table.fl > tbody").Children("tr");
1.144 + CQ channelsDiv = frq.Cq().Next("div");
1.145 + CQ channelsTableRows = channelsDiv.Find("table.fl > tbody").Children("tr");
1.146
1.147 - foreach (IDomObject row in channelsTableRows)
1.148 - {
1.149 - Channel channel = new Channel();
1.150 - //Initialize this channel with common properties on this frequency
1.151 + foreach (IDomObject row in channelsTableRows)
1.152 + {
1.153 + Channel channel = new Channel();
1.154 + //Initialize this channel with common properties on this frequency
1.155 channel.Copy(common);
1.156
1.157 - //Try and parse channel name
1.158 - CQ cqChannelName = row.Cq().Find("td:nth-child(3) > a");
1.159 - if (cqChannelName.Length == 0)
1.160 - {
1.161 - cqChannelName = row.Cq().Find("td:nth-child(3) > i");
1.162 - if (cqChannelName.Length == 0)
1.163 - {
1.164 - //Can't get channel name
1.165 - Debug.Write("WARNING: Can't find channel name! Skipping this channel");
1.166 - continue;
1.167 - }
1.168 - }
1.169 + //Try and parse channel name
1.170 + CQ cqChannelName = row.Cq().Find("td:nth-child(3) > a");
1.171 + if (cqChannelName.Length == 0)
1.172 + {
1.173 + cqChannelName = row.Cq().Find("td:nth-child(3) > i");
1.174 + if (cqChannelName.Length == 0)
1.175 + {
1.176 + //Can't get channel name
1.177 + Debug.Write("WARNING: Can't find channel name! Skipping this channel");
1.178 + continue;
1.179 + }
1.180 + }
1.181
1.182 - channel.Name = WebUtility.HtmlDecode(cqChannelName.Get(0).InnerText).Trim();
1.183 - if (channel.Name == "Name")
1.184 - {
1.185 - //Skipping header rows
1.186 - continue;
1.187 - }
1.188 + string channelNameInnerText = cqChannelName.Get(0).InnerText;
1.189 + channel.Name = WebUtility.HtmlDecode(channelNameInnerText).Trim();
1.190 + //Encoding decoder = Encoding.UTF8;
1.191 + //channel.Name = decoder.GetString(channel.Name);
1.192 + //channel.Name = channelNameInnerText.Trim(); //Make up your mind :)
1.193 + if (channel.Name == "Name")
1.194 + {
1.195 + //Skipping header rows
1.196 + continue;
1.197 + }
1.198
1.199 - //Make sure our channel name looks descent
1.200 - channel.Name = CleanChannelName(channel.Name);
1.201 + //Make sure our channel name looks descent
1.202 + channel.Name = CleanChannelName(channel.Name);
1.203 + //Make sure the resulting name is unique to avoid having multiple tuning detail for a single channel
1.204 + if (names.ContainsKey(channel.Name))
1.205 + {
1.206 + names[channel.Name]++;
1.207 + channel.Name += " " + names[channel.Name];
1.208 + }
1.209 + else
1.210 + {
1.211 + names.Add(channel.Name, 1);
1.212 + }
1.213
1.214 - //So we have a channel name get the other properties then
1.215 - channel.Country = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(4)").Get(0).InnerText).Trim();
1.216 - channel.Category = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(5)").Get(0).InnerText).Trim();
1.217 - //Skip the packages
1.218 - //Skip the encryptions
1.219 - channel.SID = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(8)").Get(0).InnerText).Trim();
1.220 - channel.VPID = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(9)").Get(0).InnerText).Trim();
1.221 - //Skip audios
1.222 - channel.PMT = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(11)").Get(0).InnerText).Trim();
1.223 - channel.PCR = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(11)").Get(0).InnerText).Trim();
1.224 - channel.TXT = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(11)").Get(0).InnerText).Trim();
1.225 + //
1.226 + //We don't want channels we already have
1.227 + Channel existingChannel = aChannels.Find(c => c.Name == channel.Name);
1.228 + if (existingChannel!=null)
1.229 + {
1.230 + continue;
1.231 + }
1.232
1.233 - //Append that new channel to our list
1.234 - channels.Add(channel);
1.235
1.236 - //Show it in debug output
1.237 - Debug.Write(channel);
1.238 - } //For each channel
1.239 - } //For each frequency
1.240 + //So we have a channel name get the other properties then
1.241 + channel.Country = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(4)").Get(0).InnerText).Trim();
1.242 + channel.Category = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(5)").Get(0).InnerText).Trim();
1.243 + if (channel.Category=="")
1.244 + {
1.245 + channel.Category = "Other";
1.246 + }
1.247 + //Skip the packages
1.248 + //Skip the encryptions
1.249 + channel.SID = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(8)").Get(0).InnerText).Trim();
1.250 + channel.VPID = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(9)").Get(0).InnerText).Trim();
1.251 + //Skip audios
1.252 + channel.PMT = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(11)").Get(0).InnerText).Trim();
1.253 + channel.PCR = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(11)").Get(0).InnerText).Trim();
1.254 + channel.TXT = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(11)").Get(0).InnerText).Trim();
1.255
1.256 - return channels;
1.257 - }
1.258 + //Append that new channel to our list
1.259 + channels.Add(channel);
1.260
1.261 - //
1.262 - public static string CleanChannelName(string aName)
1.263 - {
1.264 - aName.Trim();
1.265 - string[] remove = { "Germany", "Deutschland", "(Germany)", "(Deutschland)" };
1.266 + //Show it in debug output
1.267 + Debug.Write(channel);
1.268 + } //For each channel
1.269 + } //For each frequency
1.270
1.271 - foreach (string item in remove)
1.272 - {
1.273 - if (aName.EndsWith(item))
1.274 + return channels;
1.275 + }
1.276 +
1.277 + //
1.278 + public static string CleanChannelName(string aName)
1.279 {
1.280 - aName = aName.Substring(0, aName.LastIndexOf(item));
1.281 - break; //only allow one match at most
1.282 + aName = aName.Trim();
1.283 + string[] remove = { " Germany", " Deutschland", " (Germany)", " (Deutschland)" };
1.284 +
1.285 + foreach (string item in remove)
1.286 + {
1.287 + //if (aName.EndsWith(item))
1.288 + if (aName.Contains(item))
1.289 + {
1.290 + aName = aName.Substring(0, aName.LastIndexOf(item));
1.291 + break; //only allow one match at most
1.292 + }
1.293 + }
1.294 + aName = aName.Trim();
1.295 + return aName;
1.296 }
1.297 - }
1.298 - aName.Trim();
1.299 - return aName;
1.300 +
1.301 + //
1.302 + public static List<Channel> CleanChannelList(List<Channel> aChannels)
1.303 + {
1.304 + //Create our list of channels
1.305 + List<Channel> channels = new List<Channel>();
1.306 +
1.307 + foreach (Channel channel in aChannels)
1.308 + {
1.309 + Channel hdChannel = aChannels.Find(c => c.Name == channel.Name + " HD");
1.310 + if (hdChannel==null
1.311 + && !(channel.Name.Contains("Bundesliga") && !channel.Name.Contains("HD")) //We don't want non HD bundesliga
1.312 + && !(channel.Name.StartsWith("Sky Sport") && !channel.Name.Contains("HD")) //We don't want non HD Sky Sport
1.313 + )
1.314 + {
1.315 + //Patch some missing or bad categories
1.316 + if (channel.Name.Contains("Bundesliga")
1.317 + || channel.Name.Contains("Sport"))
1.318 + {
1.319 + channel.Category = "Sport";
1.320 + }
1.321 +
1.322 + if (channel.Name.Contains("Sky Select"))
1.323 + {
1.324 + channel.Category = "Pay per view";
1.325 + }
1.326 +
1.327 +
1.328 + if (channel.Name.StartsWith("Sky Atlantic")
1.329 + || channel.Name.StartsWith("SyFy")
1.330 + || channel.Name.StartsWith("Fox"))
1.331 + {
1.332 + channel.Category = "Series";
1.333 + }
1.334 +
1.335 + if (channel.Name.StartsWith("Sky 3D"))
1.336 + {
1.337 + channel.Category = "Movies";
1.338 + }
1.339 +
1.340 + //Collapse some categories
1.341 + if (channel.Category == "Entertainment"
1.342 + || channel.Category == "Music"
1.343 + || channel.Name.Contains("Music"))
1.344 + {
1.345 + channel.Category = "General";
1.346 + }
1.347 +
1.348 + if (channel.Category == "Porn")
1.349 + {
1.350 + channel.Category = "Erotic";
1.351 + }
1.352 +
1.353 + if (channel.Category == "Presentations")
1.354 + {
1.355 + channel.Category = "News";
1.356 + }
1.357 +
1.358 + if (channel.Category == "History")
1.359 + {
1.360 + channel.Category = "Documentaries";
1.361 + }
1.362 +
1.363 + if (channel.Category == "Lifestyle")
1.364 + {
1.365 + channel.Category = "General";
1.366 + }
1.367 +
1.368 + //if (channel.Category == "Regional")
1.369 + //{
1.370 + // channel.Category = "General";
1.371 + //}
1.372 +
1.373 + if (channel.Category == "Other")
1.374 + {
1.375 + channel.Category = "General";
1.376 + }
1.377 +
1.378 + if (channel.Category == "Cultural")
1.379 + {
1.380 + channel.Category = "General";
1.381 + }
1.382 +
1.383 +
1.384 + //No corresponding HD channel, keep it then
1.385 + channels.Add(channel);
1.386 + }
1.387 + else
1.388 + {
1.389 + Debug.Write("WARNING: Found HD channel for " + channel.Name + ". Discarding it!\n");
1.390 + }
1.391 + }
1.392 +
1.393 + return channels;
1.394 + }
1.395 }
1.396 - }
1.397 }
2.1 --- a/MainForm.cs Fri May 15 22:41:33 2015 +0200
2.2 +++ b/MainForm.cs Sat May 16 01:31:32 2015 +0200
2.3 @@ -24,17 +24,21 @@
2.4
2.5 private void buttonGenerate_Click(object sender, EventArgs e)
2.6 {
2.7 - //List<Channel> channels = new List<Channel>();
2.8 - List<Channel> channels=KingOfSat.Parse("http://en.kingofsat.net/pack-skygermany.php","19.2°E");
2.9 + List<Channel> channels = new List<Channel>();
2.10 + channels.AddRange(KingOfSat.Parse(channels, "http://en.kingofsat.net/pack-skygermany.php", "19.2°E"));
2.11 + channels.AddRange(KingOfSat.Parse(channels, "http://en.kingofsat.net/pack-hdplus.php", "19.2°E"));
2.12 + channels.AddRange(KingOfSat.Parse(channels, "http://en.kingofsat.net/pack-arddigital.php", "19.2°E"));
2.13 + channels.AddRange(KingOfSat.Parse(channels, "http://en.kingofsat.net/pack-zdfvision.php", "19.2°E"));
2.14 + channels.AddRange(KingOfSat.Parse(channels, "http://en.kingofsat.net/pack-tntsat.php", "19.2°E"));
2.15 +
2.16 + //Discard non HD channels we don't need
2.17 + channels = KingOfSat.CleanChannelList(channels);
2.18
2.19 - //Declare tuner cards so that we don't need to create mapping manually after import
2.20 - List<string> tuners = new List<string>()
2.21 - {
2.22 - "3",
2.23 - "4"
2.24 - };
2.25 + //Declare tuner cards so that we don't need to create mapping manually after import
2.26 + List<string> tuners = new List<string>(){"3","4"};
2.27
2.28 - MediaPortal.Export(channels, tuners, "channels.xml",false);
2.29 + //Export to XML for MediaPortal to import
2.30 + MediaPortal.Export(channels, tuners, "channels.xml", false);
2.31 }
2.32 }
2.33 }
3.1 --- a/MediaPortal.cs Fri May 15 22:41:33 2015 +0200
3.2 +++ b/MediaPortal.cs Sat May 16 01:31:32 2015 +0200
3.3 @@ -5,6 +5,7 @@
3.4 using System.Text;
3.5 using System.Threading.Tasks;
3.6 using System.Xml;
3.7 +using System.IO;
3.8
3.9 namespace SatChanGen
3.10 {
3.11 @@ -144,9 +145,18 @@
3.12
3.13 }
3.14
3.15 + //
3.16 + //
3.17 + //
3.18 public static void Export(List<Channel> aChannels, List<string> aTunerCards, string aFileName, bool aAddMapping)
3.19 {
3.20 + //Create a dictionary for our groups
3.21 + Dictionary<string, List<Channel>> groups = new Dictionary<string, List<Channel>>();
3.22 +
3.23 XmlDocument xmlDoc = new XmlDocument();
3.24 + XmlDeclaration xmlDeclaration = xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", null);
3.25 + xmlDoc.AppendChild(xmlDeclaration);
3.26 +
3.27 XmlNode rootElement = xmlDoc.CreateElement("tvserver");
3.28 AddAttribute(rootElement, "version", "1.0");
3.29 xmlDoc.AppendChild(rootElement);
3.30 @@ -155,38 +165,49 @@
3.31 rootElement.AppendChild(nodechannels);
3.32
3.33 int channelId = 0;
3.34 - int channelMapId = 0;
3.35 + int channelMapId = 0;
3.36 foreach (Channel channel in aChannels)
3.37 {
3.38 + //Create group if needed
3.39 + if (!groups.ContainsKey(channel.Category))
3.40 + {
3.41 + //KeyValuePair<string, List<Channel>> entry=new KeyValuePair<string, List<Channel>>();
3.42 + groups.Add(channel.Category, new List<Channel>());
3.43 + }
3.44 +
3.45 + //Add that channel to its group
3.46 + groups[channel.Category].Add(channel);
3.47 +
3.48 + //Create and populate channel element
3.49 channelId++;
3.50 XmlNode nodechannel = xmlDoc.CreateElement("channel");
3.51 AddAttribute(nodechannel, "GrabEpg", "True");
3.52 AddAttribute(nodechannel, "IdChannel", channelId);
3.53 AddAttribute(nodechannel, "IsRadio", "False");
3.54 AddAttribute(nodechannel, "IsTv", "True");
3.55 - AddAttribute(nodechannel, "LastGrabTime", "2000-1-1 0:0:0");
3.56 + AddAttribute(nodechannel, "LastGrabTime", "2000-1-1 0:0:0");
3.57 //AddAttribute(nodechannel, "SortOrder", channel.SortOrder);
3.58 - //sAddAttribute(nodechannel, "TimesWatched", "0");
3.59 - AddAttribute(nodechannel, "TotalTimeWatched", "2000-1-1 0:0:0");
3.60 + //AddAttribute(nodechannel, "TimesWatched", "0");
3.61 + AddAttribute(nodechannel, "TotalTimeWatched", "2000-1-1 0:0:0");
3.62 AddAttribute(nodechannel, "VisibleInGuide", "True");
3.63 AddAttribute(nodechannel, "DisplayName", channel.Name);
3.64 AddAttribute(nodechannel, "ChannelNumber", channelId);
3.65
3.66 - if (aAddMapping)
3.67 - {
3.68 - //I don't think we can get mapping to work without having corresponding server and card definition elements
3.69 - XmlNode nodeMaps = xmlDoc.CreateElement("mappings");
3.70 - foreach (string tuner in aTunerCards)
3.71 - {
3.72 - channelMapId++;
3.73 - XmlNode nodeMap = xmlDoc.CreateElement("map");
3.74 - AddAttribute(nodeMap, "IdCard", tuner);
3.75 - AddAttribute(nodeMap, "IdChannel", channelId);
3.76 - AddAttribute(nodeMap, "IdChannelMap", channelMapId);
3.77 - nodeMaps.AppendChild(nodeMap);
3.78 - }
3.79 - nodechannel.AppendChild(nodeMaps);
3.80 - }
3.81 + if (aAddMapping)
3.82 + {
3.83 + //I don't think we can get mapping to work without having corresponding server and card definition elements
3.84 + XmlNode nodeMaps = xmlDoc.CreateElement("mappings");
3.85 + foreach (string tuner in aTunerCards)
3.86 + {
3.87 + channelMapId++;
3.88 + XmlNode nodeMap = xmlDoc.CreateElement("map");
3.89 + AddAttribute(nodeMap, "IdCard", tuner);
3.90 + AddAttribute(nodeMap, "IdChannel", channelId);
3.91 + AddAttribute(nodeMap, "IdChannelMap", channelMapId);
3.92 + nodeMaps.AppendChild(nodeMap);
3.93 + }
3.94 + nodechannel.AppendChild(nodeMaps);
3.95 + }
3.96
3.97 XmlNode nodeTuningDetails = xmlDoc.CreateElement("TuningDetails");
3.98 XmlNode nodeTune = xmlDoc.CreateElement("tune");
3.99 @@ -229,9 +250,43 @@
3.100 nodechannels.AppendChild(nodechannel);
3.101 }
3.102
3.103 + //Create groups element
3.104 + XmlNode nodeChannelGroups = xmlDoc.CreateElement("channelgroups");
3.105 + rootElement.AppendChild(nodeChannelGroups);
3.106
3.107 + int groupSortOrder = 0;
3.108 + foreach (KeyValuePair<string, List<Channel>> group in groups)
3.109 + {
3.110 + //Create group element
3.111 + XmlNode nodeChannelGroup = xmlDoc.CreateElement("channelgroup");
3.112 + AddAttribute(nodeChannelGroup, "GroupName", group.Key);
3.113 + AddAttribute(nodeChannelGroup, "SortOrder", groupSortOrder.ToString());
3.114 + XmlNode nodeGroupMap = xmlDoc.CreateElement("mappings");
3.115 + nodeChannelGroup.AppendChild(nodeGroupMap);
3.116 + nodeChannelGroups.AppendChild(nodeChannelGroup);
3.117
3.118 - xmlDoc.Save(aFileName);
3.119 + //Sort by name
3.120 + List<Channel> sortedChannels = group.Value.OrderBy(o => o.Name).ToList();
3.121 +
3.122 + //Add each channel to its group
3.123 + int channelSortOrder = 0;
3.124 + foreach (Channel channel in sortedChannels)
3.125 + {
3.126 + XmlNode nodeMap = xmlDoc.CreateElement("map");
3.127 + AddAttribute(nodeMap, "ChannelName", channel.Name);
3.128 + AddAttribute(nodeMap, "SortOrder", channelSortOrder.ToString());
3.129 + nodeGroupMap.AppendChild(nodeMap);
3.130 + channelSortOrder++;
3.131 + }
3.132 +
3.133 + groupSortOrder++;
3.134 + }
3.135 +
3.136 + using (TextWriter sw = new StreamWriter(aFileName, false, Encoding.UTF8)) //Set encoding
3.137 + {
3.138 + xmlDoc.Save(sw);
3.139 + }
3.140 + //xmlDoc.Save(aFileName);
3.141 }
3.142
3.143 private static void AddAttribute(XmlNode node, string tagName, string tagValue)