UpdateTuningDetails() public method

public UpdateTuningDetails ( TvDatabase.Channel channel, IChannel tvChannel, TvDatabase.TuningDetail detail ) : TvDatabase.TuningDetail
channel TvDatabase.Channel
tvChannel IChannel
detail TvDatabase.TuningDetail
return TvDatabase.TuningDetail
示例#1
0
    /// <summary>
    /// Scan Thread
    /// </summary>
    private void DoScan()
    {
      suminfo tv = new suminfo();
      suminfo radio = new suminfo();
      IUser user = new User();
      user.CardId = _cardNumber;
      try
      {
        scanState = ScanState.Scanning;
        if (_dvbcChannels.Count == 0)
          return;

        RemoteControl.Instance.EpgGrabberEnabled = false;

        SetButtonState();
        TvBusinessLayer layer = new TvBusinessLayer();
        Card card = layer.GetCardByDevicePath(RemoteControl.Instance.CardDevice(_cardNumber));

        for (int index = 0; index < _dvbcChannels.Count; ++index)
        {
          if (scanState == ScanState.Cancel)
            return;

          float percent = ((float)(index)) / _dvbcChannels.Count;
          percent *= 100f;
          if (percent > 100f)
            percent = 100f;
          progressBar1.Value = (int)percent;

          Application.DoEvents();

          DVBCChannel tuneChannel = new DVBCChannel(_dvbcChannels[index]); // new DVBCChannel();
          string line = String.Format("{0}tp- {1}", 1 + index, tuneChannel.TuningInfo.ToString());
          ListViewItem item = listViewStatus.Items.Add(new ListViewItem(line));
          item.EnsureVisible();

          if (index == 0)
          {
            RemoteControl.Instance.Scan(ref user, tuneChannel, -1);
          }

          IChannel[] channels = RemoteControl.Instance.Scan(_cardNumber, tuneChannel);
          UpdateStatus();

          if (channels == null || channels.Length == 0)
          {
            if (RemoteControl.Instance.TunerLocked(_cardNumber) == false)
            {
              line = String.Format("{0}tp- {1} {2} {3}:No signal", 1 + index, tuneChannel.Frequency,
                                   tuneChannel.ModulationType, tuneChannel.SymbolRate);
              item.Text = line;
              item.ForeColor = Color.Red;
              continue;
            }
            line = String.Format("{0}tp- {1} {2} {3}:Nothing found", 1 + index, tuneChannel.Frequency,
                                 tuneChannel.ModulationType, tuneChannel.SymbolRate);
            item.Text = line;
            item.ForeColor = Color.Red;
            continue;
          }

          radio.newChannel = 0;
          radio.updChannel = 0;
          tv.newChannel = 0;
          tv.updChannel = 0;
          for (int i = 0; i < channels.Length; ++i)
          {
            Channel dbChannel;
            DVBCChannel channel = (DVBCChannel)channels[i];
            bool exists;
            TuningDetail currentDetail;
            //Check if we already have this tuningdetail. The user has the option to enable channel move detection...
            if (checkBoxEnableChannelMoveDetection.Checked)
            {
              //According to the DVB specs ONID + SID is unique, therefore we do not need to use the TSID to identify a service.
              //The DVB spec recommends that the SID should not change if a service moves. This theoretically allows us to
              //track channel movements.
              currentDetail = layer.GetTuningDetail(channel.NetworkId, channel.ServiceId,
                                                                 TvBusinessLayer.GetChannelType(channel));
            }
            else
            {
              //There are certain providers that do not maintain unique ONID + SID combinations.
              //In those cases, ONID + TSID + SID is generally unique. The consequence of using the TSID to identify
              //a service is that channel movement tracking won't work (each transponder/mux should have its own TSID).
              currentDetail = layer.GetTuningDetail(channel.NetworkId, channel.TransportId, channel.ServiceId,
                                                                 TvBusinessLayer.GetChannelType(channel));
            }

            if (currentDetail == null)
            {
              //add new channel
              exists = false;
              dbChannel = layer.AddNewChannel(channel.Name);
              dbChannel.SortOrder = 10000;
              if (channel.LogicalChannelNumber >= 1)
              {
                dbChannel.SortOrder = channel.LogicalChannelNumber;
              }
              dbChannel.IsTv = channel.IsTv;
              dbChannel.IsRadio = channel.IsRadio;
              dbChannel.Persist();
            }
            else
            {
              exists = true;
              dbChannel = currentDetail.ReferencedChannel();
            }

            if (dbChannel.IsTv)
            {
              layer.AddChannelToGroup(dbChannel, TvConstants.TvGroupNames.AllChannels);
              if (checkBoxCreateSignalGroup.Checked)
              {
                layer.AddChannelToGroup(dbChannel, TvConstants.TvGroupNames.DVBC);
              }
              if (checkBoxCreateGroups.Checked)
              {
                layer.AddChannelToGroup(dbChannel, channel.Provider);
              }
            }
            if (dbChannel.IsRadio)
            {
              layer.AddChannelToRadioGroup(dbChannel, TvConstants.RadioGroupNames.AllChannels);
              if (checkBoxCreateSignalGroup.Checked)
              {
                layer.AddChannelToRadioGroup(dbChannel, TvConstants.RadioGroupNames.DVBC);
              }
              if (checkBoxCreateGroups.Checked)
              {
                layer.AddChannelToRadioGroup(dbChannel, channel.Provider);
              }
            }

            if (currentDetail == null)
            {
              layer.AddTuningDetails(dbChannel, channel);
            }
            else
            {
              //update tuning details...
              TuningDetail td = layer.UpdateTuningDetails(dbChannel, channel, currentDetail);
              td.Persist();
            }

            if (channel.IsTv)
            {
              if (exists)
              {
                tv.updChannel++;
              }
              else
              {
                tv.newChannel++;
                tv.newChannels.Add(channel);
              }
            }
            if (channel.IsRadio)
            {
              if (exists)
              {
                radio.updChannel++;
              }
              else
              {
                radio.newChannel++;
                radio.newChannels.Add(channel);
              }
            }
            layer.MapChannelToCard(card, dbChannel, false);
            line = String.Format("{0}tp- {1} {2} {3}:New TV/Radio:{4}/{5} Updated TV/Radio:{6}/{7}", 1 + index,
                                 tuneChannel.Frequency, tuneChannel.ModulationType, tuneChannel.SymbolRate,
                                 tv.newChannel, radio.newChannel, tv.updChannel, radio.updChannel);
            item.Text = line;
          }
          tv.updChannelSum += tv.updChannel;
          radio.updChannelSum += radio.updChannel;
        }
      }
      catch (Exception ex)
      {
        Log.Write(ex);
      }
      finally
      {
        RemoteControl.Instance.StopCard(user);
        RemoteControl.Instance.EpgGrabberEnabled = true;
        progressBar1.Value = 100;

        scanState = ScanState.Done;
        SetButtonState();
      }
      listViewStatus.Items.Add(
        new ListViewItem(String.Format("Total radio channels updated:{0}, new:{1}", radio.updChannelSum,
                                       radio.newChannelSum)));
      foreach (IChannel newChannel in radio.newChannels)
      {
        listViewStatus.Items.Add(new ListViewItem(String.Format("  -> new channel: {0}", newChannel.Name)));
      }

      listViewStatus.Items.Add(
        new ListViewItem(String.Format("Total tv channels updated:{0}, new:{1}", tv.updChannelSum, tv.newChannelSum)));
      foreach (IChannel newChannel in tv.newChannels)
      {
        listViewStatus.Items.Add(new ListViewItem(String.Format("  -> new channel: {0}", newChannel.Name)));
      }
      ListViewItem lastItem = listViewStatus.Items.Add(new ListViewItem("Scan done..."));
      lastItem.EnsureVisible();
    }
示例#2
0
 private void DoScan()
 {
   int tvChannelsNew = 0;
   int radioChannelsNew = 0;
   int tvChannelsUpdated = 0;
   int radioChannelsUpdated = 0;
   string buttonText = mpButtonScanTv.Text;
   try
   {
     _isScanning = true;
     _stopScanning = false;
     mpButtonScanTv.Text = "Cancel...";
     RemoteControl.Instance.EpgGrabberEnabled = false;
     if (_atscChannels.Count == 0)
       return;
     mpComboBoxFrequencies.Enabled = false;
     listViewStatus.Items.Clear();
     TvBusinessLayer layer = new TvBusinessLayer();
     Card card = layer.GetCardByDevicePath(RemoteControl.Instance.CardDevice(_cardNumber));
     IUser user = new User();
     user.CardId = _cardNumber;
     int minchan = 2;
     int maxchan = 69;
     //Check if QAM if so then the number of channels varies
     if (checkBoxQAM.Checked)
     {
       minchan = 0;
       maxchan = _atscChannels.Count;
     }
     for (int index = minchan; index < maxchan; ++index)
     {
       if (_stopScanning)
         return;
       float percent = ((float)(index)) / (maxchan - minchan);
       percent *= 100f;
       if (percent > 100f)
         percent = 100f;
       progressBar1.Value = (int)percent;
       ATSCChannel tuneChannel = new ATSCChannel();
       tuneChannel.NetworkId = -1;
       tuneChannel.TransportId = -1;
       tuneChannel.ServiceId = -1;
       tuneChannel.MinorChannel = -1;
       tuneChannel.MajorChannel = -1;
       if (checkBoxQAM.Checked)
       {
         Log.WriteFile("ATSC tune: QAM checkbox selected... using Modulation 256Qam");
         tuneChannel.PhysicalChannel = index + 1;
         tuneChannel.Frequency = _atscChannels[index].frequency;
         tuneChannel.ModulationType = ModulationType.Mod256Qam;
       }
       else
       {
         Log.WriteFile("ATSC tune: QAM checkbox not selected... using Modulation 8Vsb");
         tuneChannel.PhysicalChannel = index;
         tuneChannel.Frequency = -1;
         tuneChannel.ModulationType = ModulationType.Mod8Vsb;
       }
       Log.WriteFile("ATSC tune: PhysicalChannel: {0} Frequency: {1} Modulation: {2}", tuneChannel.PhysicalChannel,
                     tuneChannel.Frequency, tuneChannel.ModulationType);
       string line = String.Format("physical channel:{0} frequency:{1} modulation:{2}", tuneChannel.PhysicalChannel,
                                   tuneChannel.Frequency, tuneChannel.ModulationType);
       ListViewItem item = listViewStatus.Items.Add(new ListViewItem(line));
       item.EnsureVisible();
       if (index == minchan)
       {
         RemoteControl.Instance.Scan(ref user, tuneChannel, -1);
       }
       IChannel[] channels = RemoteControl.Instance.Scan(_cardNumber, tuneChannel);
       UpdateStatus();
       /*if (channels == null || channels.Length == 0)
       {
         if (checkBoxQAM.Checked)
         {
           //try Modulation 64Qam now
           tuneChannel.PhysicalChannel = index + 1;
           tuneChannel.Frequency = _atscChannels[index].frequency;
           tuneChannel.ModulationType = ModulationType.Mod64Qam;
           line = String.Format("physical channel:{0} frequency:{1} modulation:{2}: No signal", tuneChannel.PhysicalChannel, tuneChannel.Frequency, tuneChannel.ModulationType);
           item.Text = line;
           channels = RemoteControl.Instance.Scan(_cardNumber, tuneChannel);
         }
       }*/
       UpdateStatus();
       if (channels == null || channels.Length == 0)
       {
         if (RemoteControl.Instance.TunerLocked(_cardNumber) == false)
         {
           line = String.Format("physical channel:{0} frequency:{1} modulation:{2}: No signal",
                                tuneChannel.PhysicalChannel, tuneChannel.Frequency, tuneChannel.ModulationType);
           item.Text = line;
           item.ForeColor = Color.Red;
           continue;
         }
         line = String.Format("physical channel:{0} frequency:{1} modulation:{2}: Nothing found",
                              tuneChannel.PhysicalChannel, tuneChannel.Frequency, tuneChannel.ModulationType);
         item.Text = line;
         item.ForeColor = Color.Red;
         continue;
       }
       int newChannels = 0;
       int updatedChannels = 0;
       for (int i = 0; i < channels.Length; ++i)
       {
         Channel dbChannel;
         ATSCChannel channel = (ATSCChannel)channels[i];
         //No support for channel moving, or merging with existing channels here.
         //We do not know how ATSC works to correctly implement this.
         TuningDetail currentDetail = layer.GetTuningDetail(channel);
         if (currentDetail != null)
           if (channel.Frequency != currentDetail.Frequency)
             currentDetail = null;
         bool exists;
         if (currentDetail == null)
         {
           //add new channel
           exists = false;
           dbChannel = layer.AddNewChannel(channel.Name);
           dbChannel.SortOrder = 10000;
           if (channel.LogicalChannelNumber >= 1)
           {
             dbChannel.SortOrder = channel.LogicalChannelNumber;
           }
         }
         else
         {
           exists = true;
           dbChannel = currentDetail.ReferencedChannel();
         }
         dbChannel.IsTv = channel.IsTv;
         dbChannel.IsRadio = channel.IsRadio;
         dbChannel.Persist();
         if (dbChannel.IsTv)
         {
           layer.AddChannelToGroup(dbChannel, TvConstants.TvGroupNames.AllChannels);
         }
         if (dbChannel.IsRadio)
         {
           layer.AddChannelToRadioGroup(dbChannel, TvConstants.RadioGroupNames.AllChannels);
         }
         if (currentDetail == null)
         {
           layer.AddTuningDetails(dbChannel, channel);
         }
         else
         {
           //update tuning details...
           TuningDetail td = layer.UpdateTuningDetails(dbChannel, channel, currentDetail);
           td.Persist();
         }
         if (channel.IsTv)
         {
           if (exists)
           {
             tvChannelsUpdated++;
             updatedChannels++;
           }
           else
           {
             tvChannelsNew++;
             newChannels++;
           }
         }
         if (channel.IsRadio)
         {
           if (exists)
           {
             radioChannelsUpdated++;
             updatedChannels++;
           }
           else
           {
             radioChannelsNew++;
             newChannels++;
           }
         }
         layer.MapChannelToCard(card, dbChannel, false);
         line = String.Format("physical channel:{0} frequency:{1} modulation:{2} New:{3} Updated:{4}",
                              tuneChannel.PhysicalChannel, tuneChannel.Frequency, tuneChannel.ModulationType,
                              newChannels, updatedChannels);
         item.Text = line;
       }
     }
     //DatabaseManager.Instance.SaveChanges();
   }
   catch (Exception ex)
   {
     Log.Write(ex);
   }
   finally
   {
     IUser user = new User();
     user.CardId = _cardNumber;
     RemoteControl.Instance.StopCard(user);
     RemoteControl.Instance.EpgGrabberEnabled = true;
     progressBar1.Value = 100;
     checkBoxQAM.Enabled = true;
     mpComboBoxFrequencies.Enabled = true;
     mpButtonScanTv.Text = buttonText;
     _isScanning = false;
   }
   listViewStatus.Items.Add(
     new ListViewItem(String.Format("Total radio channels new:{0} updated:{1}", radioChannelsNew,
                                    radioChannelsUpdated)));
   listViewStatus.Items.Add(
     new ListViewItem(String.Format("Total tv channels new:{0} updated:{1}", tvChannelsNew, tvChannelsUpdated)));
   ListViewItem lastItem = listViewStatus.Items.Add(new ListViewItem("Scan done..."));
   lastItem.EnsureVisible();
 }
示例#3
0
    private void DoScan()
    {
      int tvChannelsNew = 0;
      int radioChannelsNew = 0;
      int tvChannelsUpdated = 0;
      int radioChannelsUpdated = 0;

      string buttonText = mpButtonScanTv.Text;
      IUser user = new User();
      user.CardId = _cardNumber;
      try
      {
        // First lock the card, because so that other parts of a hybrid card can't be used at the same time
        _isScanning = true;
        _stopScanning = false;
        mpButtonScanTv.Text = "Cancel...";
        RemoteControl.Instance.EpgGrabberEnabled = false;
        listViewStatus.Items.Clear();

        PlayList playlist = new PlayList();
        if (mpComboBoxService.SelectedIndex == 0)
        {
          //TODO read SAP announcements
        }
        else
        {
          IPlayListIO playlistIO =
            PlayListFactory.CreateIO(String.Format(@"{0}\TuningParameters\dvbip\{1}.m3u", PathManager.GetDataPath,
                                                   mpComboBoxService.SelectedItem));
          playlistIO.Load(playlist,
                          String.Format(@"{0}\TuningParameters\dvbip\{1}.m3u", PathManager.GetDataPath,
                                        mpComboBoxService.SelectedItem));
        }
        if (playlist.Count == 0) return;

        mpComboBoxService.Enabled = false;
        checkBoxCreateGroups.Enabled = false;
        checkBoxEnableChannelMoveDetection.Enabled = false;
        TvBusinessLayer layer = new TvBusinessLayer();
        Card card = layer.GetCardByDevicePath(RemoteControl.Instance.CardDevice(_cardNumber));

        int index = -1;
        IEnumerator<PlayListItem> enumerator = playlist.GetEnumerator();

        while (enumerator.MoveNext())
        {
          if (_stopScanning) return;
          index++;
          float percent = ((float)(index)) / playlist.Count;
          percent *= 100f;
          if (percent > 100f) percent = 100f;
          progressBar1.Value = (int)percent;

          string url = enumerator.Current.FileName.Substring(enumerator.Current.FileName.LastIndexOf('\\') + 1);
          string name = enumerator.Current.Description;

          DVBIPChannel tuneChannel = new DVBIPChannel();
          tuneChannel.Url = url;
          tuneChannel.Name = name;
          string line = String.Format("{0}- {1} - {2}", 1 + index, tuneChannel.Name, tuneChannel.Url);
          ListViewItem item = listViewStatus.Items.Add(new ListViewItem(line));
          item.EnsureVisible();
          RemoteControl.Instance.Tune(ref user, tuneChannel, -1);
          IChannel[] channels;
          channels = RemoteControl.Instance.Scan(_cardNumber, tuneChannel);
          UpdateStatus();
          if (channels == null || channels.Length == 0)
          {
            if (RemoteControl.Instance.TunerLocked(_cardNumber) == false)
            {
              line = String.Format("{0}- {1} - {2} :No Signal", 1 + index, tuneChannel.Url, tuneChannel.Name);
              item.Text = line;
              item.ForeColor = Color.Red;
              continue;
            }
            else
            {
              line = String.Format("{0}- {1} - {2} :Nothing found", 1 + index, tuneChannel.Url, tuneChannel.Name);
              item.Text = line;
              item.ForeColor = Color.Red;
              continue;
            }
          }

          int newChannels = 0;
          int updatedChannels = 0;

          for (int i = 0; i < channels.Length; ++i)
          {
            Channel dbChannel;
            DVBIPChannel channel = (DVBIPChannel)channels[i];
            if (channels.Length > 1)
            {
              if (channel.Name.IndexOf("Unknown") == 0)
              {
                channel.Name = name + (i + 1);
              }
            }
            else
            {
              channel.Name = name;
            }
            bool exists;
            TuningDetail currentDetail;
            //Check if we already have this tuningdetail. According to DVB-IP specifications there are two ways to identify DVB-IP
            //services: one ONID + SID based, the other domain/URL based. At this time we don't fully and properly implement the DVB-IP
            //specifications, so the safest method for service identification is the URL. The user has the option to enable the use of
            //ONID + SID identification and channel move detection...
            if (checkBoxEnableChannelMoveDetection.Checked)
            {
              currentDetail = layer.GetTuningDetail(channel.NetworkId, channel.ServiceId,
                                                                 TvBusinessLayer.GetChannelType(channel));
            }
            else
            {
              currentDetail = layer.GetTuningDetail(channel.Url, TvBusinessLayer.GetChannelType(channel));
            }

            if (currentDetail == null)
            {
              //add new channel
              exists = false;
              dbChannel = layer.AddNewChannel(channel.Name, channel.LogicalChannelNumber);
              dbChannel.SortOrder = 10000;
              if (channel.LogicalChannelNumber >= 1)
              {
                dbChannel.SortOrder = channel.LogicalChannelNumber;
              }
              dbChannel.IsTv = channel.IsTv;
              dbChannel.IsRadio = channel.IsRadio;
              dbChannel.Persist();
            }
            else
            {
              exists = true;
              dbChannel = currentDetail.ReferencedChannel();
            }

            layer.AddChannelToGroup(dbChannel, TvConstants.TvGroupNames.AllChannels);

            if (checkBoxCreateGroups.Checked)
            {
              layer.AddChannelToGroup(dbChannel, channel.Provider);
            }
            if (currentDetail == null)
            {
              layer.AddTuningDetails(dbChannel, channel);
            }
            else
            {
              //update tuning details...
              TuningDetail td = layer.UpdateTuningDetails(dbChannel, channel, currentDetail);
              td.Persist();
            }

            if (channel.IsTv)
            {
              if (exists)
              {
                tvChannelsUpdated++;
                updatedChannels++;
              }
              else
              {
                tvChannelsNew++;
                newChannels++;
              }
            }
            if (channel.IsRadio)
            {
              if (exists)
              {
                radioChannelsUpdated++;
                updatedChannels++;
              }
              else
              {
                radioChannelsNew++;
                newChannels++;
              }
            }
            layer.MapChannelToCard(card, dbChannel, false);
            line = String.Format("{0}- {1} :New:{2} Updated:{3}", 1 + index, tuneChannel.Name, newChannels,
                                 updatedChannels);
            item.Text = line;
          }
        }
        //DatabaseManager.Instance.SaveChanges();
      }
      catch (Exception ex)
      {
        Log.Write(ex);
      }
      finally
      {
        RemoteControl.Instance.StopCard(user);
        RemoteControl.Instance.EpgGrabberEnabled = true;
        progressBar1.Value = 100;
        mpComboBoxService.Enabled = true;
        checkBoxCreateGroups.Enabled = true;
        checkBoxEnableChannelMoveDetection.Enabled = true;
        mpButtonScanTv.Text = buttonText;
        _isScanning = false;
      }
      ListViewItem lastItem = listViewStatus.Items.Add(new ListViewItem("Scan done..."));
      lastItem =
        listViewStatus.Items.Add(
          new ListViewItem(String.Format("Total radio channels new:{0} updated:{1}", radioChannelsNew,
                                         radioChannelsUpdated)));
      lastItem =
        listViewStatus.Items.Add(
          new ListViewItem(String.Format("Total tv channels new:{0} updated:{1}", tvChannelsNew, tvChannelsUpdated)));
      lastItem.EnsureVisible();
    }
示例#4
0
 private void DoScan()
 {
   int tvChannelsNew = 0;
   int radioChannelsNew = 0;
   int tvChannelsUpdated = 0;
   int radioChannelsUpdated = 0;
   string buttonText = mpButtonScanTv.Text;
   try
   {
     _isScanning = true;
     _stopScanning = false;
     mpButtonScanTv.Text = "Cancel...";
     RemoteControl.Instance.EpgGrabberEnabled = false;
     if (_atscChannels.Count == 0)
       return;
     mpComboBoxFrequencies.Enabled = false;
     listViewStatus.Items.Clear();
     TvBusinessLayer layer = new TvBusinessLayer();
     Card card = layer.GetCardByDevicePath(RemoteControl.Instance.CardDevice(_cardNumber));
     IUser user = new User();
     user.CardId = _cardNumber;
     int minchan = 2;
     int maxchan = 69 + 1;
     if ((string)mpComboBoxTuningMode.SelectedItem == "Clear QAM Cable")
     {
       minchan = 1;
       maxchan = _atscChannels.Count + 1;
     }
     else if ((string)mpComboBoxTuningMode.SelectedItem == "Digital Cable")
     {
       minchan = 0;
       maxchan = 1;
     }
     for (int index = minchan; index < maxchan; ++index)
     {
       if (_stopScanning)
         return;
       float percent = ((float)(index)) / (maxchan - minchan);
       percent *= 100f;
       if (percent > 100f)
         percent = 100f;
       progressBar1.Value = (int)percent;
       ATSCChannel tuneChannel = new ATSCChannel();
       tuneChannel.NetworkId = -1;
       tuneChannel.TransportId = -1;
       tuneChannel.ServiceId = -1;
       tuneChannel.MinorChannel = -1;
       tuneChannel.MajorChannel = -1;
       string line;
       if ((string)mpComboBoxTuningMode.SelectedItem == "Clear QAM Cable")
       {
         tuneChannel.PhysicalChannel = index;
         tuneChannel.Frequency = _atscChannels[index - 1].frequency;
         if (tuneChannel.Frequency < 10000)
         {
           continue;
         }
         tuneChannel.ModulationType = ModulationType.Mod256Qam;
         line = string.Format("physical channel = {0}, frequency = {1} kHz, modulation = 256 QAM", tuneChannel.PhysicalChannel, tuneChannel.Frequency);
         Log.Info("ATSC: scanning clear QAM cable, {0}, frequency plan = {1}", line, mpComboBoxFrequencies.SelectedItem);
       }
       else if ((string)mpComboBoxTuningMode.SelectedItem == "ATSC Digital Terrestrial")
       {
         tuneChannel.PhysicalChannel = index;
         tuneChannel.Frequency = -1;
         tuneChannel.ModulationType = ModulationType.Mod8Vsb;
         line = string.Format("physical channel = {0}, modulation = 8 VSB", tuneChannel.PhysicalChannel);
         Log.Info("ATSC: scanning ATSC over-the-air, {0}", line);
       }
       else
       {
         tuneChannel.PhysicalChannel = 0;
         tuneChannel.ModulationType = ModulationType.Mod256Qam;
         line = "out-of-band service information";
         Log.Info("ATSC: scanning digital cable, {0}", line);
       }
       line += "... ";
       ListViewItem item = listViewStatus.Items.Add(new ListViewItem(line));
       item.EnsureVisible();
       if (index == minchan)
       {
         RemoteControl.Instance.Scan(ref user, tuneChannel, -1);
       }
       IChannel[] channels = RemoteControl.Instance.Scan(_cardNumber, tuneChannel);
       UpdateStatus();
       if (channels == null || channels.Length == 0)
       {
         if (tuneChannel.PhysicalChannel > 0 && !RemoteControl.Instance.TunerLocked(_cardNumber))
         {
           line += "no signal";
         }
         else
         {
           line += "signal locked, no channels found";
         }
         item.Text = line;
         item.ForeColor = Color.Red;
         continue;
       }
       int newChannels = 0;
       int updatedChannels = 0;
       for (int i = 0; i < channels.Length; ++i)
       {
         Channel dbChannel;
         ATSCChannel channel = (ATSCChannel)channels[i];
         //No support for channel moving, or merging with existing channels here.
         //We do not know how ATSC works to correctly implement this.
         TuningDetail currentDetail = layer.GetTuningDetail(channel);
         if (currentDetail != null)
         {
           if (channel.IsDifferentTransponder(layer.GetTuningChannel(currentDetail)))
           {
             currentDetail = null;
           }
         }
         bool exists;
         if (currentDetail == null)
         {
           //add new channel
           exists = false;
           dbChannel = layer.AddNewChannel(channel.Name, channel.LogicalChannelNumber);
           dbChannel.SortOrder = 10000;
           if (channel.LogicalChannelNumber >= 1)
           {
             dbChannel.SortOrder = channel.LogicalChannelNumber;
           }
         }
         else
         {
           exists = true;
           dbChannel = currentDetail.ReferencedChannel();
         }
         dbChannel.IsTv = channel.IsTv;
         dbChannel.IsRadio = channel.IsRadio;
         dbChannel.Persist();
         if (dbChannel.IsTv)
         {
           layer.AddChannelToGroup(dbChannel, TvConstants.TvGroupNames.AllChannels);
         }
         if (dbChannel.IsRadio)
         {
           layer.AddChannelToRadioGroup(dbChannel, TvConstants.RadioGroupNames.AllChannels);
         }
         if (currentDetail == null)
         {
           layer.AddTuningDetails(dbChannel, channel);
         }
         else
         {
           //update tuning details...
           TuningDetail td = layer.UpdateTuningDetails(dbChannel, channel, currentDetail);
           td.Persist();
         }
         if (channel.IsTv)
         {
           if (exists)
           {
             tvChannelsUpdated++;
             updatedChannels++;
           }
           else
           {
             tvChannelsNew++;
             newChannels++;
           }
         }
         if (channel.IsRadio)
         {
           if (exists)
           {
             radioChannelsUpdated++;
             updatedChannels++;
           }
           else
           {
             radioChannelsNew++;
             newChannels++;
           }
         }
         layer.MapChannelToCard(card, dbChannel, false);
       }
       line += string.Format("new = {0}, updated = {1}", newChannels, updatedChannels);
       item.Text = line;
       Log.Info("ATSC: scan result, new = {0}, updated = {1}", newChannels, updatedChannels);
     }
   }
   catch (Exception ex)
   {
     Log.Write(ex);
   }
   finally
   {
     IUser user = new User();
     user.CardId = _cardNumber;
     RemoteControl.Instance.StopCard(user);
     RemoteControl.Instance.EpgGrabberEnabled = true;
     progressBar1.Value = 100;
     mpComboBoxTuningMode.Enabled = true;
     UpdateQamFrequencyFieldAvailability();
     mpButtonScanTv.Text = buttonText;
     _isScanning = false;
   }
   listViewStatus.Items.Add(
     new ListViewItem(String.Format("Total radio channels, new = {0}, updated = {1}", radioChannelsNew,
                                    radioChannelsUpdated)));
   listViewStatus.Items.Add(
     new ListViewItem(String.Format("Total TV channels, new = {0} updated = {1}", tvChannelsNew, tvChannelsUpdated)));
   ListViewItem lastItem = listViewStatus.Items.Add(new ListViewItem("Scan done!"));
   lastItem.EnsureVisible();
   Log.Info("ATSC: scan summary, new TV = {0}, updated TV = {1}, new radio = {2}, updated radio = {3}", tvChannelsNew, tvChannelsUpdated, radioChannelsNew, radioChannelsUpdated);
 }