Example #1
0
        //OK
        private void SetProgramList(string content)
        {
            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(content);

            HtmlNodeCollection progDates = doc.DocumentNode.SelectNodes("//td[@class='mlistaido']");
            HtmlNodeCollection progNamesTitles = doc.DocumentNode.SelectNodes("//td[@class='mlistacim']");

            const String br = "|||";
            bool gotCurrent = false;
            programs = new ProgramList<Data.Program>();

            for (int i = 0; i < progDates.Count && i < progNamesTitles.Count; i++)
            {
                String time = progDates[i].InnerText;
                String txt = progNamesTitles[i].InnerHtml;

                txt = txt.Replace("<br>", br);
                txt = Regex.Replace(txt, "<.*?>", string.Empty);

                int hours = int.Parse(time.Substring(0, time.IndexOf(":")));
                int mins = int.Parse(time.Substring(time.IndexOf(":") + 1));

                DateTime dt = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, hours, mins, DateTime.Now.Second);

                Data.Program program = new Data.Program(
                    txt.Substring(0, txt.IndexOf(br)),
                    txt.Substring(txt.IndexOf(br) + br.Length),
                    dt, false
                );

                programs.Add(program);

                if (!gotCurrent && DateTime.Now.CompareTo(program.DateTime) < 0)
                {
                    if (programs.Count == 1)
                    {
                        programs[0].Current = true;
                    }
                    else
                    {
                        programs[programs.Count - 2].Current = true;
                    }

                    gotCurrent = true;
                }
            }

            for (int i = programs.Count - 1; i >= 0; i--)
            {
                if (DateTime.Now.CompareTo(programs[i].DateTime) > 0 && !programs[i].Current)
                {
                    programs.RemoveAt(i);
                }
            }

            if (programs.Count > 0)
            {
                lblTitle.Text = programs[0].Title;
                lblProgram.Text = programs[0].Description;
            }

            foreach (Data.Program program in programs)
            {
                int row = ProgramsForm.Instance.ProgramList.Rows.Add(
                    UppercaseFirst(program.DateTime.ToString("MMM dd. HH:mm")),
                    program.Title +
                    (!program.Description.Equals(string.Empty) ? " - " + program.Description : string.Empty)
                );

                if (program.Current)
                {
                    ProgramsForm.Instance.ProgramList.Rows[row].DefaultCellStyle.BackColor = Color.FromArgb(8, 16, 8);
                    ProgramsForm.Instance.ProgramList.Rows[row].DefaultCellStyle.ForeColor = Color.FromArgb(55, 194, 55);

                    ProgramsForm.Instance.ProgramList.Rows[row].DefaultCellStyle.SelectionBackColor = Color.FromArgb(16, 32, 16);
                    ProgramsForm.Instance.ProgramList.Rows[row].DefaultCellStyle.SelectionForeColor = Color.FromArgb(55, 194, 55);
                }
            }
        }
    void IEpgDataSink.EndChannelPrograms(string id, string name)
    {
      if (_currentChannels == null) return;
      if (_channelPrograms.Count == 0) return;

      // Sort programs
      _channelPrograms.SortIfNeeded();
      _channelPrograms.AlreadySorted = true;

      // Fix end times
      _channelPrograms.FixEndTimes();
      ClipProgramsToWindow();

      // Remove overlapping programs
      _channelPrograms.RemoveOverlappingPrograms();

      if (!_deleteExisting)
      {
        // Remove programs overlapping ones in DB:
        // First retrieve all programs for current channels 
        SqlBuilder sb = new SqlBuilder(StatementType.Select, typeof (Program));
        sb.AddConstraint(Operator.In, "idChannel", _currentChannels, "IdChannel");
        //sb.AddConstraint(Operator.Equals, "idChannel", _currentChannels.IdChannel);
        //sb.AddOrderByField(false, "starttime");
        SqlStatement stmt = sb.GetStatement(true);
        ProgramList dbPrograms = new ProgramList(ObjectFactory.GetCollection<Program>(stmt.Execute()));

        _channelPrograms.RemoveOverlappingPrograms(dbPrograms);
      }
      foreach (Channel chan in _currentChannels)
      {
        layer.RemoveOldPrograms(chan.IdChannel);
      }

      DeleteBeforeImportOption programsToDelete = _deleteExisting
                                                    ? DeleteBeforeImportOption.OverlappingPrograms
                                                    : DeleteBeforeImportOption.None;
      layer.InsertPrograms(_channelPrograms, programsToDelete, ThreadPriority.BelowNormal);

      //_channelPrograms.Clear();
      _channelPrograms = null;
      _currentChannels = null;
    }
Example #3
0
    public bool Import(string fileName, bool deleteBeforeImport, bool showProgress)
    {
      //System.Diagnostics.Debugger.Launch();
      _errorMessage = "";
      if (_isImporting == true)
      {
        _errorMessage = "already importing...";
        return false;
      }
      _isImporting = true;

      bool result = false;
      XmlTextReader xmlReader = null;


      // remove old programs
      _status.Status = "Removing old programs";
      _status.Channels = 0;
      _status.Programs = 0;
      _status.StartTime = DateTime.Now;
      _status.EndTime = new DateTime(1971, 11, 6);
      if (showProgress && ShowProgress != null) ShowProgress(_status);

      layer.RemoveOldPrograms();

      /*
      // for each channel, get the last program's time
      Dictionary<int, DateTime> lastProgramForChannel = new Dictionary<int, DateTime>();
      IList channels = Channel.ListAll();
      foreach (Channel ch in channels)
      {
        SqlBuilder sb = new SqlBuilder(StatementType.Select, typeof(TvDatabase.Program));
        sb.AddConstraint(Operator.Equals, "idChannel", ch.IdChannel);
        sb.AddOrderByField(false, "starttime");
        sb.SetRowLimit(1);
        SqlStatement stmt = sb.GetStatement(true);
        IList programsInDbs = ObjectFactory.GetCollection(typeof(TvDatabase.Program), stmt.Execute());

        DateTime lastProgram = DateTime.MinValue;
        if (programsInDbs.Count > 0)
        {
          TvDatabase.IProgram p = (TvDatabase.Program)programsInDbs[0];
          lastProgram = p.EndTime;
        }
        lastProgramForChannel[ch.IdChannel] = lastProgram;
      }*/

      //TVDatabase.SupressEvents = true;
      bool useTimeZone = layer.GetSetting("xmlTvUseTimeZone", "false").Value == "true";
      int hours = Int32.Parse(layer.GetSetting("xmlTvTimeZoneHours", "0").Value);
      int mins = Int32.Parse(layer.GetSetting("xmlTvTimeZoneMins", "0").Value);
      int timeZoneCorrection = hours * 60 + mins;

      ArrayList Programs = new ArrayList();
      Dictionary<int, ChannelPrograms> dChannelPrograms = new Dictionary<int, ChannelPrograms>();
      try
      {
        Log.WriteFile("xmltv import {0}", fileName);

        //
        // Make sure the file exists before we try to do any processing
        //
        if (File.Exists(fileName))
        {
          _status.Status = "Loading channel list";
          _status.Channels = 0;
          _status.Programs = 0;
          _status.StartTime = DateTime.Now;
          _status.EndTime = new DateTime(1971, 11, 6);
          if (showProgress && ShowProgress != null) ShowProgress(_status);

          Dictionary<int, Channel> guideChannels = new Dictionary<int, Channel>();

          IList<Channel> allChannels = Channel.ListAll();

          int iChannel = 0;

          xmlReader = new XmlTextReader(fileName);

          #region import non-mapped channels by their display-name

          if (xmlReader.ReadToDescendant("tv"))
          {
            // get the first channel
            if (xmlReader.ReadToDescendant("channel"))
            {
              do
              {
                String id = xmlReader.GetAttribute("id");
                if (id == null || id.Length == 0)
                {
                  Log.Error("  channel#{0} doesnt contain an id", iChannel);
                }
                else
                {
                  String displayName = null;

                  XmlReader xmlChannel = xmlReader.ReadSubtree();
                  xmlChannel.ReadStartElement(); // read channel
                  // now, xmlChannel is positioned on the first sub-element of <channel>
                  while (!xmlChannel.EOF)
                  {
                    if (xmlChannel.NodeType == XmlNodeType.Element)
                    {
                      switch (xmlChannel.Name)
                      {
                        case "display-name":
                        case "Display-Name":
                          if (displayName == null) displayName = xmlChannel.ReadString();
                          else xmlChannel.Skip();
                          break;
                          // could read more stuff here, like icon...
                        default:
                          // unknown, skip entire node
                          xmlChannel.Skip();
                          break;
                      }
                    }
                    else
                      xmlChannel.Read();
                  }
                  if (xmlChannel != null)
                  {
                    xmlChannel.Close();
                    xmlChannel = null;
                  }

                  if (displayName == null || displayName.Length == 0)
                  {
                    Log.Error("  channel#{0} xmlid:{1} doesnt contain an displayname", iChannel, id);
                  }
                  else
                  {
                    Channel chan = null;

                    // a guide channel can be mapped to multiple tvchannels
                    foreach (Channel ch in allChannels)
                    {
                      if (ch.ExternalId == id)
                      {
                        chan = ch;
                        chan.ExternalId = id;
                      }

                      if (chan == null)
                      {
                        // no mapping found, ignore channel
                        continue;
                      }

                      ChannelPrograms newProgChan = new ChannelPrograms();
                      newProgChan.Name = chan.DisplayName;
                      newProgChan.ExternalId = chan.ExternalId;
                      Programs.Add(newProgChan);

                      Log.WriteFile("  channel#{0} xmlid:{1} name:{2} dbsid:{3}", iChannel, chan.ExternalId,
                                    chan.DisplayName, chan.IdChannel);
                      if (!guideChannels.ContainsKey(chan.IdChannel))
                      {
                        guideChannels.Add(chan.IdChannel, chan);
                        dChannelPrograms.Add(chan.IdChannel, newProgChan);
                      }
                    }

                    _status.Channels++;
                    if (showProgress && ShowProgress != null) ShowProgress(_status);
                  }
                }
                iChannel++;
                // get the next channel
              } while (xmlReader.ReadToNextSibling("channel"));
            }
          }

          //xmlReader.Close();

          #endregion

          SqlBuilder sb = new SqlBuilder(StatementType.Select, typeof (Channel));
          sb.AddOrderByField(true, "externalId");
          sb.AddConstraint("externalId IS NOT null");
          sb.AddConstraint(Operator.NotEquals, "externalId", "");

          SqlStatement stmt = sb.GetStatement(true);
          allChannels = ObjectFactory.GetCollection<Channel>(stmt.Execute());
          if (allChannels.Count == 0)
          {
            _isImporting = false;
            if (xmlReader != null)
            {
              xmlReader.Close();
              xmlReader = null;
            }

            return true;
          }

          ///////////////////////////////////////////////////////////////////////////
          /*  design:
           * 1. create a Dictionary<string,Channel> using the externalid as the key,
           *    add all channels to this Dictionary 
           *    Note: channel -> guidechannel is a one-to-many relationship. 
           * 2. Read all programs from the xml file
           * 3. Create a program for each mapped channel
           */
          ///////////////////////////////////////////////////////////////////////////
          Dictionary<string, List<Channel>> allChannelMappingsByExternalId = new Dictionary<string, List<Channel>>();

          string previousExternalId = null;
          // one-to-many so we need a collection of channels for each externalId
          List<Channel> eidMappedChannels = new List<Channel>();

          for (int i = 0; i < allChannels.Count; i++)
          {
            Channel ch = (Channel)allChannels[i];

            if (previousExternalId == null)
            {
              eidMappedChannels.Add(ch);
              previousExternalId = ch.ExternalId;
            }
            else if (ch.ExternalId == previousExternalId)
            {
              eidMappedChannels.Add(ch);
            }
            else
            {
              // got all channels for this externalId. Add the mappings
              allChannelMappingsByExternalId.Add(previousExternalId, eidMappedChannels);
              // new externalid, create a new List & add the channel to the new List
              eidMappedChannels = new List<Channel>();
              eidMappedChannels.Add(ch);
              previousExternalId = ch.ExternalId;
            }

            if (i == allChannels.Count - 1)
            {
              allChannelMappingsByExternalId.Add(previousExternalId, eidMappedChannels);
            }
          }

          int programIndex = 0;
          _status.Status = "Loading TV programs";
          if (showProgress && ShowProgress != null) ShowProgress(_status);

          Log.Debug("xmltvimport: Reading TV programs");
          if (xmlReader != null)
          {
            xmlReader.Close();
            xmlReader = null;
          }
          xmlReader = new XmlTextReader(fileName);
          if (xmlReader.ReadToDescendant("tv"))
          {
            // get the first programme
            if (xmlReader.ReadToDescendant("programme"))
            {
              #region read programme node

              do
              {
                ChannelPrograms channelPrograms = new ChannelPrograms();

                String nodeStart = xmlReader.GetAttribute("start");
                String nodeStop = xmlReader.GetAttribute("stop");
                String nodeChannel = xmlReader.GetAttribute("channel");

                String nodeTitle = null;
                String nodeCategory = null;
                String nodeDescription = null;
                String nodeEpisode = null;
                String nodeRepeat = null;
                String nodeEpisodeNum = null;
                String nodeEpisodeNumSystem = null;
                String nodeDate = null;
                String nodeStarRating = null;
                String nodeClassification = null;

                XmlReader xmlProg = xmlReader.ReadSubtree();
                xmlProg.ReadStartElement(); // read programme
                // now, xmlProg is positioned on the first sub-element of <programme>
                while (!xmlProg.EOF)
                {
                  if (xmlProg.NodeType == XmlNodeType.Element)
                  {
                    switch (xmlProg.Name)
                    {
                      case "title":
                        if (nodeTitle == null) nodeTitle = xmlProg.ReadString();
                        else xmlProg.Skip();
                        break;
                      case "category":
                        if (nodeCategory == null) nodeCategory = xmlProg.ReadString();
                        else xmlProg.Skip();
                        break;
                      case "desc":
                        if (nodeDescription == null) nodeDescription = xmlProg.ReadString();
                        else xmlProg.Skip();
                        break;
                      case "sub-title":
                        if (nodeEpisode == null) nodeEpisode = xmlProg.ReadString();
                        else xmlProg.Skip();
                        break;
                      case "previously-shown":
                        if (nodeRepeat == null) nodeRepeat = xmlProg.ReadString();
                        else xmlProg.Skip();
                        break;
                      case "episode-num":
                        if (xmlProg.GetAttribute("system").Equals("xmltv_ns")) 
                        {
                            nodeEpisodeNumSystem = xmlProg.GetAttribute("system");
                            nodeEpisodeNum = xmlProg.ReadString();
                        }
                        else if (nodeEpisodeNum == null && xmlProg.GetAttribute("system").Equals("onscreen"))
                        {
                          nodeEpisodeNumSystem = xmlProg.GetAttribute("system");
                          nodeEpisodeNum = xmlProg.ReadString();
                        }
                        else xmlProg.Skip();
                        break;
                      case "date":
                        if (nodeDate == null) nodeDate = xmlProg.ReadString();
                        else xmlProg.Skip();
                        break;
                      case "star-rating":
                        if (nodeStarRating == null) nodeStarRating = xmlProg.ReadInnerXml();
                        else xmlProg.Skip();
                        break;
                      case "rating":
                        if (nodeClassification == null) nodeClassification = xmlProg.ReadInnerXml();
                        else xmlProg.Skip();
                        break;
                      default:
                        // unknown, skip entire node
                        xmlProg.Skip();
                        break;
                    }
                  }
                  else
                    xmlProg.Read();
                }
                if (xmlProg != null)
                {
                  xmlProg.Close();
                  xmlProg = null;
                }

                #endregion

                #region verify/convert values (programme)

                if (nodeStart != null && nodeChannel != null && nodeTitle != null &&
                    nodeStart.Length > 0 && nodeChannel.Length > 0 && nodeTitle.Length > 0)
                {
                  string description = "";
                  string category = "-";
                  string serEpNum = "";
                  string date = "";
                  string seriesNum = "";
                  string episodeNum = "";
                  string episodeName = "";
                  string episodePart = "";
                  int starRating = -1;
                  string classification = "";

                  string title = ConvertHTMLToAnsi(nodeTitle);

                  long startDate = 0;
                  if (nodeStart.Length >= 14)
                  {
                    if (Char.IsDigit(nodeStart[12]) && Char.IsDigit(nodeStart[13]))
                      startDate = Int64.Parse(nodeStart.Substring(0, 14)); //20040331222000
                    else
                      startDate = 100 * Int64.Parse(nodeStart.Substring(0, 12)); //200403312220
                  }
                  else if (nodeStart.Length >= 12)
                  {
                    startDate = 100 * Int64.Parse(nodeStart.Substring(0, 12)); //200403312220
                  }

                  long stopDate = startDate;
                  if (nodeStop != null)
                  {
                    if (nodeStop.Length >= 14)
                    {
                      if (Char.IsDigit(nodeStop[12]) && Char.IsDigit(nodeStop[13]))
                        stopDate = Int64.Parse(nodeStop.Substring(0, 14)); //20040331222000
                      else
                        stopDate = 100 * Int64.Parse(nodeStop.Substring(0, 12)); //200403312220
                    }
                    else if (nodeStop.Length >= 12)
                    {
                      stopDate = 100 * Int64.Parse(nodeStop.Substring(0, 12)); //200403312220
                    }
                  }

                  startDate = CorrectIllegalDateTime(startDate);
                  stopDate = CorrectIllegalDateTime(stopDate);
                  string timeZoneStart = "";
                  string timeZoneEnd = "";
                  if (nodeStart.Length > 14)
                  {
                    timeZoneStart = nodeStart.Substring(14);
                    timeZoneStart = timeZoneStart.Trim();
                    timeZoneEnd = timeZoneStart;
                  }
                  if (nodeStop != null)
                  {
                    if (nodeStop.Length > 14)
                    {
                      timeZoneEnd = nodeStop.Substring(14);
                      timeZoneEnd = timeZoneEnd.Trim();
                    }
                  }

                  //
                  // add time correction
                  //

                  // correct program starttime
                  DateTime dateTimeStart = longtodate(startDate);
                  dateTimeStart = dateTimeStart.AddMinutes(timeZoneCorrection);

                  if (useTimeZone)
                  {
                    int off = GetTimeOffset(timeZoneStart);
                    int h = off / 100; // 220 -> 2,  -220 -> -2
                    int m = off - (h * 100); // 220 -> 20, -220 -> -20

                    dateTimeStart = dateTimeStart.AddHours(-h);
                    dateTimeStart = dateTimeStart.AddMinutes(-m);
                    dateTimeStart = dateTimeStart.ToLocalTime();
                  }
                  startDate = datetolong(dateTimeStart);

                  if (nodeStop != null)
                  {
                    // correct program endtime
                    DateTime dateTimeEnd = longtodate(stopDate);
                    dateTimeEnd = dateTimeEnd.AddMinutes(timeZoneCorrection);

                    if (useTimeZone)
                    {
                      int off = GetTimeOffset(timeZoneEnd);
                      int h = off / 100; // 220 -> 2,  -220 -> -2
                      int m = off - (h * 100); // 220 -> 20, -220 -> -20

                      dateTimeEnd = dateTimeEnd.AddHours(-h);
                      dateTimeEnd = dateTimeEnd.AddMinutes(-m);
                      dateTimeEnd = dateTimeEnd.ToLocalTime();
                    }
                    stopDate = datetolong(dateTimeEnd);
                  }
                  else stopDate = startDate;

                  //int channelId = -1;
                  //string channelName = "";

                  if (nodeCategory != null)
                    category = nodeCategory;

                  if (nodeDescription != null)
                  {
                    description = ConvertHTMLToAnsi(nodeDescription);
                  }
                  if (nodeEpisode != null)
                  {
                    episodeName = ConvertHTMLToAnsi(nodeEpisode);
                    if (title.Length == 0)
                      title = nodeEpisode;
                  }

                  if (nodeEpisodeNum != null)
                  {
                    if (nodeEpisodeNumSystem != null)
                    {
                      // http://xml.coverpages.org/XMLTV-DTD-20021210.html
                      if (nodeEpisodeNumSystem == "xmltv_ns")
                      {
                        serEpNum = ConvertHTMLToAnsi(nodeEpisodeNum.Replace(" ", ""));
                        int dot1 = serEpNum.IndexOf(".", 0);
                        int dot2 = serEpNum.IndexOf(".", dot1 + 1);
                        seriesNum = serEpNum.Substring(0, dot1);
                        episodeNum = serEpNum.Substring(dot1 + 1, dot2 - (dot1 + 1));
                        episodePart = serEpNum.Substring(dot2 + 1, serEpNum.Length - (dot2 + 1));
                        //xmltv_ns is theorically zero-based number will be increased by one
                        seriesNum = CorrectEpisodeNum(seriesNum, 1);
                        episodeNum = CorrectEpisodeNum(episodeNum, 1);
                        episodePart = CorrectEpisodeNum(episodePart, 1);
                      }
                      else if (nodeEpisodeNumSystem == "onscreen")
                      {
                        // example: 'Episode #FFEE' 
                        serEpNum = ConvertHTMLToAnsi(nodeEpisodeNum);
                        int num1 = serEpNum.IndexOf("#", 0);
                        if (num1 > 0)
                        {
                          episodeNum = CorrectEpisodeNum(serEpNum.Substring(num1, serEpNum.Length - num1), 0);
                        }
                        else
                        {
                          if (serEpNum.IndexOf(":", 0) > 0)
                          {
                            episodeNum = CorrectEpisodeNum(serEpNum, 0);
                          }
                          else
                          {
                            Regex regEpisode = new Regex("(?<episode>\\d*)\\D*(?<series>\\d*)", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture);
                            Match m = regEpisode.Match(serEpNum);
                            if (m.Success)
                            {
                              episodeNum = CorrectEpisodeNum(m.Groups["episode"].Value, 0);
                              seriesNum = CorrectEpisodeNum(m.Groups["series"].Value, 0);
                            }
                            else
                            {
                              episodeNum = CorrectEpisodeNum(serEpNum, 0);
                            }
                          }
                        }
                      }
                    }
                    else
                      // fixing mantis bug 1486: XMLTV import doesn't take episode number from TVGuide.xml made by WebEPG 
                    {
                      // example: '5' like WebEPG is creating
                      serEpNum = ConvertHTMLToAnsi(nodeEpisodeNum.Replace(" ", ""));
                      episodeNum = CorrectEpisodeNum(serEpNum, 0);
                    }
                  }

                  if (nodeDate != null)
                  {
                    date = nodeDate;
                  }

                  if (nodeStarRating != null)
                  {
                    starRating = ParseStarRating(nodeStarRating);
                  }

                  if (nodeClassification != null)
                  {
                    classification = nodeClassification;
                  }

                  if (showProgress && ShowProgress != null && (_status.Programs % 100) == 0) ShowProgress(_status);

                  #endregion

                  #region create a program for every mapped channel

                  List<Channel> mappedChannels;

                  if (allChannelMappingsByExternalId.ContainsKey(nodeChannel))
                  {
                    mappedChannels = allChannelMappingsByExternalId[nodeChannel];
                    if (mappedChannels != null && mappedChannels.Count > 0)
                    {
                      foreach (Channel chan in mappedChannels)
                      {
                        // get the channel program
                        channelPrograms = dChannelPrograms[chan.IdChannel];

                        if (chan.IdChannel < 0)
                        {
                          continue;
                        }

                        title = title.Replace("\r\n", " ");
                        title = title.Replace("\n\r", " ");
                        title = title.Replace("\r", " ");
                        title = title.Replace("\n", " ");
                        title = title.Replace("  ", " ");

                        description = description.Replace("\r\n", " ");
                        description = description.Replace("\n\r", " ");
                        description = description.Replace("\r", " ");
                        description = description.Replace("\n", " ");
                        description = description.Replace("  ", " ");

                        episodeName = episodeName.Replace("\r\n", " ");
                        episodeName = episodeName.Replace("\n\r", " ");
                        episodeName = episodeName.Replace("\r", " ");
                        episodeName = episodeName.Replace("\n", " ");
                        episodeName = episodeName.Replace("  ", " ");

                        Program prog = new Program(chan.IdChannel, longtodate(startDate), longtodate(stopDate), title,
                                                   description, category, Program.ProgramState.None,
                                                   System.Data.SqlTypes.SqlDateTime.MinValue.Value, seriesNum,
                                                   episodeNum, episodeName, episodePart, starRating, classification, -1);
                        channelPrograms.programs.Add(prog);
                        programIndex++;
                        //prog.Description = ConvertHTMLToAnsi(strDescription);
                        //prog.StartTime = iStart;
                        //prog.EndTime = iStop;
                        //prog.Title = ConvertHTMLToAnsi(strTitle);
                        //prog.Genre = ConvertHTMLToAnsi(strCategory);
                        //prog.Channel = ConvertHTMLToAnsi(strChannelName);
                        //prog.Date = strDate;
                        //prog.Episode = ConvertHTMLToAnsi(strEpisode);
                        //prog.Repeat = ConvertHTMLToAnsi(strRepeat);
                        //prog.SeriesNum = ConvertHTMLToAnsi(strSeriesNum);
                        //prog.EpisodeNum = ConvertHTMLToAnsi(strEpisodeNum);
                        //prog.EpisodePart = ConvertHTMLToAnsi(strEpisodePart);
                        //prog.StarRating = ConvertHTMLToAnsi(strStarRating);
                        //prog.Classification = ConvertHTMLToAnsi(strClasification);
                        _status.Programs++;
                      }
                    }
                  }
                }
                // get the next programme
              } while (xmlReader.ReadToNextSibling("programme"));
              //if (xmlReader != null) xmlReader.Close();

              #endregion

              #region sort & remove invalid programs. Save all valid programs

              Log.Debug("xmltvimport: Sorting TV programs");

              _status.Programs = 0;
              _status.Status = "Sorting TV programs";
              if (showProgress && ShowProgress != null) ShowProgress(_status);
              DateTime dtStartDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0, 0);
              //dtStartDate=dtStartDate.AddDays(-4);

              foreach (ChannelPrograms progChan in Programs)
              {
                // empty, skip it
                if (progChan.programs.Count == 0) continue;

                progChan.programs.Sort();
                progChan.programs.AlreadySorted = true;
                progChan.programs.FixEndTimes();
                progChan.programs.RemoveOverlappingPrograms(); // be sure that we do not have any overlapping

                // get the id of the channel, just get the IdChannel of the first program
                int idChannel = progChan.programs[0].IdChannel;

                if (!deleteBeforeImport)
                {
                  // retrieve all programs for this channel
                  SqlBuilder sb2 = new SqlBuilder(StatementType.Select, typeof (Program));
                  sb2.AddConstraint(Operator.Equals, "idChannel", idChannel);
                  sb2.AddOrderByField(false, "starttime");
                  SqlStatement stmt2 = sb2.GetStatement(true);
                  ProgramList dbPrograms = new ProgramList();
                  ObjectFactory.GetCollection<Program>(stmt2.Execute(), dbPrograms);
                  progChan.programs.RemoveOverlappingPrograms(dbPrograms, true);
                }

                for (int i = 0; i < progChan.programs.Count; ++i)
                {
                  Program prog = progChan.programs[i];
                  // don't import programs which have already ended...
                  if (prog.EndTime <= dtStartDate)
                  {
                    progChan.programs.RemoveAt(i);
                    i--;
                    continue;
                  }

                  DateTime start = prog.StartTime;
                  DateTime end = prog.EndTime;
                  DateTime airDate = System.Data.SqlTypes.SqlDateTime.MinValue.Value;
                  try
                  {
                    airDate = prog.OriginalAirDate;
                    if (airDate > System.Data.SqlTypes.SqlDateTime.MinValue.Value &&
                        airDate < System.Data.SqlTypes.SqlDateTime.MaxValue.Value)
                      prog.OriginalAirDate = airDate;
                  }
                  catch (Exception)
                  {
                    Log.Info("XMLTVImport: Invalid year for OnAirDate - {0}", prog.OriginalAirDate);
                  }

                  if (prog.StartTime < _status.StartTime)
                    _status.StartTime = prog.StartTime;
                  if (prog.EndTime > _status.EndTime)
                    _status.EndTime = prog.EndTime;
                  _status.Programs++;
                  if (showProgress && ShowProgress != null && (_status.Programs % 100) == 0) ShowProgress(_status);
                }
                Log.Info("XMLTVImport: Inserting {0} programs for {1}", progChan.programs.Count.ToString(),
                         progChan.Name);
                layer.InsertPrograms(progChan.programs,
                                     deleteBeforeImport
                                       ? DeleteBeforeImportOption.OverlappingPrograms
                                       : DeleteBeforeImportOption.None, ThreadPriority.BelowNormal);
              }
            }

            #endregion

            //TVDatabase.RemoveOverlappingPrograms();

            //TVDatabase.SupressEvents = false;
            if (programIndex > 0)
            {
              _errorMessage = "File imported successfully";
              result = true;
            }
            else
              _errorMessage = "No programs found";
          }
        }
        else
        {
          _errorMessage = "No xmltv file found";
          _status.Status = _errorMessage;
          Log.Error("xmltv data file was not found");
        }
      }
      catch (Exception ex)
      {
        _errorMessage = String.Format("Invalid XML file:{0}", ex.Message);
        _status.Status = String.Format("invalid XML file:{0}", ex.Message);
        Log.Error("XML tv import error loading {0} err:{1} \n {2}", fileName, ex.Message, ex.StackTrace);

        //TVDatabase.RollbackTransaction();
      }

      Programs.Clear();
      Programs = null;

      _isImporting = false;
      //      TVDatabase.SupressEvents = false;
      if (xmlReader != null)
      {
        xmlReader.Close();
        xmlReader = null;
      }
      return result;
    }
    bool IEpgDataSink.StartChannelPrograms(string id, string name)
    {
      string channelKey = name + "-" + id;

      _timeWindow = null;

      if (_channels.TryGetValue(channelKey, out _currentChannels))
      {
        _channelPrograms = new ProgramList();
        _channelPrograms.AlreadySorted = false;
        return true;
      }
      else
      {
        _currentChannels = null;
        Log.Info("WebEPG: Unknown channel (display name = {0}, channel id = {1}) - skipping...", name, id);
        return false;
      }
    }