Example #1
0
bool CPVRClients::SwitchChannel(const CPVRChannel &channel)
{
  {
    CSingleLock lock(m_critSection);
    if (m_bIsSwitchingChannels)
    {
      CLog::Log(LOGDEBUG, "PVRClients - %s - can't switch to channel '%s'. waiting for the previous switch to complete", __FUNCTION__, channel.ChannelName().c_str());
      return false;
    }
    m_bIsSwitchingChannels = true;
  }

  bool bSwitchSuccessful(false);
  CPVRChannelPtr currentChannel;
  if (// no channel is currently playing
      !GetPlayingChannel(currentChannel) ||
      // different backend
      currentChannel->ClientID() != channel.ClientID() ||
      // different type
      currentChannel->IsRadio() != channel.IsRadio() ||
      // stream URL should always be opened as a new file
      !channel.StreamURL().IsEmpty() || !currentChannel->StreamURL().IsEmpty())
  {
    if (channel.StreamURL().IsEmpty())
    {
      CloseStream();
      bSwitchSuccessful = OpenStream(channel, true);
    }
    else
    {
      CFileItem m_currentFile(channel);
      CApplicationMessenger::Get().PlayFile(m_currentFile, false);
      bSwitchSuccessful = true;
    }
  }
  // same channel
  else if (currentChannel.get() && *currentChannel == channel)
  {
    bSwitchSuccessful = true;
  }
  else
  {
    PVR_CLIENT client;
    if (GetConnectedClient(channel.ClientID(), client))
      bSwitchSuccessful = client->SwitchChannel(channel);
  }

  {
    CSingleLock lock(m_critSection);
    m_bIsSwitchingChannels = false;
    if (bSwitchSuccessful)
      m_bIsValidChannelSettings = false;
  }

  if (!bSwitchSuccessful)
    CLog::Log(LOGERROR, "PVR - %s - cannot switch to channel '%s' on client '%d'",__FUNCTION__, channel.ChannelName().c_str(), channel.ClientID());

  return bSwitchSuccessful;
}
Example #2
0
bool CPVRClient::OpenStream(const CPVRChannel &channel, bool bIsSwitchingChannel)
{
  bool bReturn(false);
  CloseStream();

  if(!CanPlayChannel(channel))
  {
    CLog::Log(LOGDEBUG, "add-on '%s' can not play channel '%s'", GetFriendlyName().c_str(), channel.ChannelName().c_str());
  }
  else if (!channel.StreamURL().IsEmpty())
  {
    CLog::Log(LOGDEBUG, "opening live stream on url '%s'", channel.StreamURL().c_str());
    bReturn = true;

    // the Njoy N7 sometimes doesn't switch channels, but opens a stream to the previous channel
    // when not waiting for a short period.
    // added in 1.1.0
    AddonVersion checkVersion("1.1.0");
    if (m_apiVersion >= checkVersion)
    {
      unsigned int iWaitTimeMs = m_pStruct->GetChannelSwitchDelay();
      if (iWaitTimeMs > 0)
        XbmcThreads::ThreadSleep(iWaitTimeMs);
    }
  }
  else
  {
    CLog::Log(LOGDEBUG, "opening live stream for channel '%s'", channel.ChannelName().c_str());
    PVR_CHANNEL tag;
    WriteClientChannelInfo(channel, tag);

    try
    {
      bReturn = m_pStruct->OpenLiveStream(tag);
      if (bReturn)
      {
        m_bCanPauseStream = m_pStruct->CanPauseStream();
        m_bCanSeekStream = m_pStruct->CanSeekStream();
      }
    }
    catch (exception &e) { LogException(e, __FUNCTION__); }
  }

  if (bReturn)
  {
    CPVRChannelPtr currentChannel = g_PVRChannelGroups->GetByUniqueID(channel.UniqueID(), channel.ClientID());
    CSingleLock lock(m_critSection);
    m_playingChannel      = currentChannel;
    m_bIsPlayingTV        = true;
    m_bIsPlayingRecording = false;
  }

  return bReturn;
}
Example #3
0
bool CPVRDatabase::Persist(CPVRChannel &channel, bool bQueueWrite /* = false */)
{
  bool bReturn(false);

  /* invalid channel */
  if (channel.UniqueID() <= 0)
  {
    CLog::Log(LOGERROR, "PVR - %s - invalid channel uid: %d", __FUNCTION__, channel.UniqueID());
    return bReturn;
  }

  CStdString strQuery;
  if (channel.ChannelID() <= 0)
  {
    /* new channel */
    strQuery = PrepareSQL("INSERT INTO channels ("
        "iUniqueId, bIsRadio, bIsHidden, bIsUserSetIcon, bIsLocked, "
        "sIconPath, sChannelName, bIsVirtual, bEPGEnabled, sEPGScraper, iLastWatched, iClientId, "
        "iClientChannelNumber, sInputFormat, sStreamURL, iEncryptionSystem, idEpg) "
        "VALUES (%i, %i, %i, %i, %i, '%s', '%s', %i, %i, '%s', %u, %i, %i, '%s', '%s', %i, %i)",
        channel.UniqueID(), (channel.IsRadio() ? 1 :0), (channel.IsHidden() ? 1 : 0), (channel.IsUserSetIcon() ? 1 : 0), (channel.IsLocked() ? 1 : 0),
        channel.IconPath().c_str(), channel.ChannelName().c_str(), (channel.IsVirtual() ? 1 : 0), (channel.EPGEnabled() ? 1 : 0), channel.EPGScraper().c_str(), channel.LastWatched(), channel.ClientID(),
        channel.ClientChannelNumber(), channel.InputFormat().c_str(), channel.StreamURL().c_str(), channel.EncryptionSystem(),
        channel.EpgID());
  }
  else
  {
    /* update channel */
    strQuery = PrepareSQL("REPLACE INTO channels ("
        "iUniqueId, bIsRadio, bIsHidden, bIsUserSetIcon, bIsLocked, "
        "sIconPath, sChannelName, bIsVirtual, bEPGEnabled, sEPGScraper, iLastWatched, iClientId, "
        "iClientChannelNumber, sInputFormat, sStreamURL, iEncryptionSystem, idChannel, idEpg) "
        "VALUES (%i, %i, %i, %i, %i, '%s', '%s', %i, %i, '%s', %u, %i, %i, '%s', '%s', %i, %i, %i)",
        channel.UniqueID(), (channel.IsRadio() ? 1 :0), (channel.IsHidden() ? 1 : 0), (channel.IsUserSetIcon() ? 1 : 0), (channel.IsLocked() ? 1 : 0),
        channel.IconPath().c_str(), channel.ChannelName().c_str(), (channel.IsVirtual() ? 1 : 0), (channel.EPGEnabled() ? 1 : 0), channel.EPGScraper().c_str(), channel.LastWatched(), channel.ClientID(),
        channel.ClientChannelNumber(), channel.InputFormat().c_str(), channel.StreamURL().c_str(), channel.EncryptionSystem(), channel.ChannelID(),
        channel.EpgID());
  }

  if (bQueueWrite)
  {
    QueueInsertQuery(strQuery);
    bReturn = true;
  }
  else if (ExecuteQuery(strQuery))
  {
    CSingleLock lock(channel.m_critSection);
    if (channel.m_iChannelId <= 0)
      channel.m_iChannelId = (int)m_pDS->lastinsertid();
    bReturn = true;
  }

  return bReturn;
}
Example #4
0
int CPVRDatabase::Persist(const CPVRChannel &channel, bool bQueueWrite /* = false */)
{
  int iReturn = -1;

  /* invalid channel */
  if (channel.UniqueID() <= 0)
  {
    CLog::Log(LOGERROR, "PVRDB - %s - invalid channel uid: %d",
        __FUNCTION__, channel.UniqueID());
    return iReturn;
  }

  CStdString strQuery;

  if (channel.ChannelID() <= 0)
  {
    /* new channel */
    strQuery = FormatSQL("INSERT INTO channels ("
        "iUniqueId, bIsRadio, bIsHidden, "
        "sIconPath, sChannelName, bIsVirtual, bEPGEnabled, sEPGScraper, iLastWatched, iClientId, "
        "iClientChannelNumber, sInputFormat, sStreamURL, iEncryptionSystem, idEpg) "
        "VALUES (%i, %i, %i, '%s', '%s', %i, %i, '%s', %u, %i, %i, '%s', '%s', %i, %i);",
        channel.UniqueID(), (channel.IsRadio() ? 1 :0), (channel.IsHidden() ? 1 : 0),
        channel.IconPath().c_str(), channel.ChannelName().c_str(), (channel.IsVirtual() ? 1 : 0), (channel.EPGEnabled() ? 1 : 0), channel.EPGScraper().c_str(), channel.LastWatched(), channel.ClientID(),
        channel.ClientChannelNumber(), channel.InputFormat().c_str(), channel.StreamURL().c_str(), channel.EncryptionSystem(),
        channel.EpgID());
  }
  else
  {
    /* update channel */
    strQuery = FormatSQL("REPLACE INTO channels ("
        "iUniqueId, bIsRadio, bIsHidden, "
        "sIconPath, sChannelName, bIsVirtual, bEPGEnabled, sEPGScraper, iLastWatched, iClientId, "
        "iClientChannelNumber, sInputFormat, sStreamURL, iEncryptionSystem, idChannel, idEpg) "
        "VALUES (%i, %i, %i, '%s', '%s', %i, %i, '%s', %u, %i, %i, '%s', '%s', %i, %i, %i);",
        channel.UniqueID(), (channel.IsRadio() ? 1 :0), (channel.IsHidden() ? 1 : 0),
        channel.IconPath().c_str(), channel.ChannelName().c_str(), (channel.IsVirtual() ? 1 : 0), (channel.EPGEnabled() ? 1 : 0), channel.EPGScraper().c_str(), channel.LastWatched(), channel.ClientID(),
        channel.ClientChannelNumber(), channel.InputFormat().c_str(), channel.StreamURL().c_str(), channel.EncryptionSystem(), channel.ChannelID(),
        channel.EpgID());
  }

  if (bQueueWrite)
  {
    QueueInsertQuery(strQuery);
    iReturn = 0;
  }
  else if (ExecuteQuery(strQuery))
  {
    iReturn = (channel.ChannelID() <= 0) ? (int) m_pDS->lastinsertid() : channel.ChannelID();
  }

  return iReturn;
}
Example #5
0
long CPVRDatabase::UpdateChannel(const CPVRChannel &channel, bool bQueueWrite /* = false */)
{
  long iReturn = -1;

  /* invalid channel */
  if (channel.UniqueID() <= 0)
  {
    CLog::Log(LOGERROR, "PVRDB - %s - invalid channel uid: %d",
        __FUNCTION__, channel.UniqueID());
    return iReturn;
  }

  CStdString strQuery;

  if (channel.ChannelID() <= 0)
  {
    /* new channel */
    strQuery = FormatSQL("INSERT INTO Channels ("
        "UniqueId, ChannelNumber, GroupId, IsRadio, IsHidden, "
        "IconPath, ChannelName, IsVirtual, EPGEnabled, EPGScraper, ClientId, "
        "ClientChannelNumber, InputFormat, StreamURL, EncryptionSystem) "
        "VALUES (%i, %i, %i, %i, %i, '%s', '%s', %i, %i, '%s', %i, %i, '%s', '%s', %i)\n",
        channel.UniqueID(), channel.ChannelNumber(), channel.GroupID(), (channel.IsRadio() ? 1 :0), (channel.IsHidden() ? 1 : 0),
        channel.IconPath().c_str(), channel.ChannelName().c_str(), (channel.IsVirtual() ? 1 : 0), (channel.EPGEnabled() ? 1 : 0), channel.EPGScraper().c_str(), channel.ClientID(),
        channel.ClientChannelNumber(), channel.InputFormat().c_str(), channel.StreamURL().c_str(), channel.EncryptionSystem());
  }
  else
  {
    /* update channel */
    strQuery = FormatSQL("REPLACE INTO Channels ("
        "UniqueId, ChannelNumber, GroupId, IsRadio, IsHidden, "
        "IconPath, ChannelName, IsVirtual, EPGEnabled, EPGScraper, ClientId, "
        "ClientChannelNumber, InputFormat, StreamURL, EncryptionSystem, ChannelId) "
        "VALUES (%i, %i, %i, %i, %i, '%s', '%s', %i, %i, '%s', %i, %i, '%s', '%s', %i, %i)\n",
        channel.UniqueID(), channel.ChannelNumber(), channel.GroupID(), (channel.IsRadio() ? 1 :0), (channel.IsHidden() ? 1 : 0),
        channel.IconPath().c_str(), channel.ChannelName().c_str(), (channel.IsVirtual() ? 1 : 0), (channel.EPGEnabled() ? 1 : 0), channel.EPGScraper().c_str(), channel.ClientID(),
        channel.ClientChannelNumber(), channel.InputFormat().c_str(), channel.StreamURL().c_str(), channel.EncryptionSystem(), channel.ChannelID());
  }

  if (bQueueWrite)
  {
    QueueInsertQuery(strQuery);
    iReturn = 0;
  }
  else if (ExecuteQuery(strQuery))
  {
    iReturn = (channel.ChannelID() <= 0) ? (long) m_pDS->lastinsertid() : channel.ChannelID();
  }

  return iReturn;
}
Example #6
0
bool CPVRClients::OpenLiveStream(const CPVRChannel &tag)
{
  bool bReturn = false;
  CSingleLock lock(m_critSection);

  if (m_currentChannel)
    delete m_currentChannel;
  if (m_currentRecording)
    delete m_currentRecording;

  ResetQualityData();

  /* try to open the stream on the client */
  if (tag.StreamURL().IsEmpty() &&
      m_clientsProps[tag.ClientID()].HandleInputStream &&
      m_clientMap[tag.ClientID()]->OpenLiveStream(tag))
  {
    m_currentChannel = &tag;
    if (tag.ClientID() == XBMC_VIRTUAL_CLIENTID)
      m_strPlayingClientName = g_localizeStrings.Get(19209);
    else if (!tag.IsVirtual())
      m_strPlayingClientName = GetClientName(tag.ClientID());
    else
      m_strPlayingClientName = g_localizeStrings.Get(13205);

    m_scanStart = CTimeUtils::GetTimeMS();  /* Reset the stream scan timer */
    bReturn = true;
  }

  return bReturn;
}
Example #7
0
bool CPVRClients::OpenLiveStream(const CPVRChannel &tag)
{
  bool bReturn(false);
  CSingleLock lock(m_critSection);

  m_bIsPlayingLiveTV = false;
  m_bIsPlayingRecording = false;

  ResetQualityData(m_qualityInfo);

  /* try to open the stream on the client */
  boost::shared_ptr<CPVRClient> client;
  if (tag.StreamURL().IsEmpty() == false ||
      (GetConnectedClient(tag.ClientID(), client) &&
      client->GetAddonCapabilities().bHandlesInputStream &&
      client->OpenLiveStream(tag)))
  {
    m_currentChannel = tag;
    m_bIsPlayingLiveTV = true;
    if (tag.ClientID() == XBMC_VIRTUAL_CLIENTID)
      m_strPlayingClientName = g_localizeStrings.Get(19209);
    else if (!tag.IsVirtual())
      GetClientName(tag.ClientID(), m_strPlayingClientName);
    else
      m_strPlayingClientName = g_localizeStrings.Get(13205);

    bReturn = true;
  }

  return bReturn;
}
Example #8
0
bool CGUIWindowPVRCommon::PlayFile(CFileItem *item, bool bPlayMinimized /* = false */)
{
  if (item->m_bIsFolder)
  {
    return false;
  }

  if (item->GetPath() == g_application.CurrentFile())
  {
    CGUIMessage msg(GUI_MSG_FULLSCREEN, 0, m_parent->GetID());
    g_windowManager.SendMessage(msg);
    return true;
  }

  CMediaSettings::Get().SetVideoStartWindowed(bPlayMinimized);

  if (item->HasPVRRecordingInfoTag())
  {
    return PlayRecording(item, bPlayMinimized);
  }
  else
  {
    bool bSwitchSuccessful(false);

    CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL;

    if (channel && g_PVRManager.CheckParentalLock(*channel))
    {
      /* try a fast switch */
      if (channel && (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio()) &&
         (channel->IsRadio() == g_PVRManager.IsPlayingRadio()) && g_application.m_pPlayer)
      {
        if (channel->StreamURL().IsEmpty())
          bSwitchSuccessful = g_application.m_pPlayer->SwitchChannel(*channel);
      }

      if (!bSwitchSuccessful)
      {
        CApplicationMessenger::Get().PlayFile(*item, false);
        return true;
      }
    }

    if (!bSwitchSuccessful)
    {
      CStdString msg;
      CStdString channelName = g_localizeStrings.Get(19029); // Channel
      if (channel)
        channelName = channel->ChannelName();
      msg.Format(g_localizeStrings.Get(19035).c_str(), channelName.c_str()); // CHANNELNAME could not be played. Check the log for details.

      CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error,
              g_localizeStrings.Get(19166), // PVR information
              msg);
      return false;
    }
  }

  return true;
}
Example #9
0
bool CPVRChannel::UpdateFromClient(const CPVRChannel &channel)
{
  bool bChanged = false;

  bChanged = SetClientID(channel.ClientID()) || bChanged;
  bChanged = SetClientChannelNumber(channel.ClientChannelNumber()) || bChanged;
  bChanged = SetClientChannelName(channel.ClientChannelName()) || bChanged;
  bChanged = SetInputFormat(channel.InputFormat()) || bChanged;
  bChanged = SetStreamURL(channel.StreamURL()) || bChanged;
  bChanged = SetEncryptionSystem(channel.EncryptionSystem()) || bChanged;
  bChanged = SetRecording(channel.IsRecording()) || bChanged;

  if (m_strChannelName.IsEmpty())
  {
    m_strChannelName = channel.ClientChannelName();
    bChanged = true;
  }

  if (m_strIconPath.IsEmpty())
  {
    m_strIconPath = channel.IconPath();
    bChanged = true;
  }

  return bChanged;
}
Example #10
0
/*!
 * @brief Copy over channel info from xbmcChannel to addonClient.
 * @param xbmcChannel The channel on XBMC's side.
 * @param addonChannel The channel on the addon's side.
 */
inline void PVRWriteClientChannelInfo(const CPVRChannel &xbmcChannel, PVR_CHANNEL &addonChannel)
{
  addonChannel.iUniqueId         = xbmcChannel.UniqueID();
  addonChannel.iChannelNumber    = xbmcChannel.ClientChannelNumber();
  addonChannel.strChannelName    = xbmcChannel.ClientChannelName().c_str();
  addonChannel.strIconPath       = xbmcChannel.IconPath().c_str();
  addonChannel.iEncryptionSystem = xbmcChannel.EncryptionSystem();
  addonChannel.bIsRadio          = xbmcChannel.IsRadio();
  addonChannel.bIsHidden         = xbmcChannel.IsHidden();
  addonChannel.strInputFormat    = xbmcChannel.InputFormat().c_str();
  addonChannel.strStreamURL      = xbmcChannel.StreamURL().c_str();
}
Example #11
0
bool CGUIWindowPVRCommon::PlayFile(CFileItem *item, bool bPlayMinimized /* = false */)
{
  if (item->m_bIsFolder)
  {
    return false;
  }

  if (item->GetPath() == g_application.CurrentFile())
  {
    CGUIMessage msg(GUI_MSG_FULLSCREEN, 0, m_parent->GetID());
    g_windowManager.SendMessage(msg);
    return true;
  }

  g_settings.m_bStartVideoWindowed = bPlayMinimized;

  if (item->HasPVRRecordingInfoTag())
  {
    return PlayRecording(item, bPlayMinimized);
  }
  else
  {
    bool bSwitchSuccessful(false);

    CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL;

    if (channel && g_PVRManager.CheckParentalLock(*channel))
    {
      /* try a fast switch */
      if (channel && (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio()) &&
         (channel->IsRadio() == g_PVRManager.IsPlayingRadio()) && g_application.m_pPlayer)
      {
        if (channel->StreamURL().IsEmpty())
          bSwitchSuccessful = g_application.m_pPlayer->SwitchChannel(*channel);
      }

      if (!bSwitchSuccessful)
      {
        CApplicationMessenger::Get().PlayFile(*item, false);
        return true;
      }
    }

    if (!bSwitchSuccessful)
    {
      CGUIDialogOK::ShowAndGetInput(19033,0,19035,0);
      return false;
    }
  }

  return true;
}
Example #12
0
/*!
 * @brief Copy over channel info from xbmcChannel to addonClient.
 * @param xbmcChannel The channel on XBMC's side.
 * @param addonChannel The channel on the addon's side.
 */
void CPVRClient::WriteClientChannelInfo(const CPVRChannel &xbmcChannel, PVR_CHANNEL &addonChannel)
{
  memset(&addonChannel, 0, sizeof(addonChannel));

  addonChannel.iUniqueId         = xbmcChannel.UniqueID();
  addonChannel.iChannelNumber    = xbmcChannel.ClientChannelNumber();
  strncpy(addonChannel.strChannelName, xbmcChannel.ClientChannelName().c_str(), sizeof(addonChannel.strChannelName) - 1);
  strncpy(addonChannel.strIconPath, xbmcChannel.IconPath().c_str(), sizeof(addonChannel.strIconPath) - 1);
  addonChannel.iEncryptionSystem = xbmcChannel.EncryptionSystem();
  addonChannel.bIsRadio          = xbmcChannel.IsRadio();
  addonChannel.bIsHidden         = xbmcChannel.IsHidden();
  strncpy(addonChannel.strInputFormat, xbmcChannel.InputFormat().c_str(), sizeof(addonChannel.strInputFormat) - 1);
  strncpy(addonChannel.strStreamURL, xbmcChannel.StreamURL().c_str(), sizeof(addonChannel.strStreamURL) - 1);
}
Example #13
0
bool CPVRChannel::UpdateFromClient(const CPVRChannel &channel)
{
    SetClientID(channel.ClientID());
    SetClientChannelNumber(channel.ClientChannelNumber());
    SetInputFormat(channel.InputFormat());
    SetStreamURL(channel.StreamURL());
    SetEncryptionSystem(channel.EncryptionSystem());
    SetClientChannelName(channel.ClientChannelName());

    CSingleLock lock(m_critSection);
    if (m_strChannelName.IsEmpty())
        SetChannelName(channel.ClientChannelName());
    if (m_strIconPath.IsEmpty()||(!m_strIconPath.Equals(channel.IconPath()) && !IsUserSetIcon()))
        SetIconPath(channel.IconPath());

    return m_bChanged;
}
Example #14
0
bool CPVRChannel::UpdateFromClient(const CPVRChannel &channel)
{
  SetClientID(channel.ClientID());
  SetClientChannelNumber(channel.ClientChannelNumber());
  SetInputFormat(channel.InputFormat());
  SetStreamURL(channel.StreamURL());
  SetEncryptionSystem(channel.EncryptionSystem());
  SetClientChannelName(channel.ClientChannelName());

  CSingleLock lock(m_critSection);
  
  // only update the channel name and icon if the user hasn't changed them manually
  if (m_strChannelName.empty() || !IsUserSetName())
    SetChannelName(channel.ClientChannelName());
  if (m_strIconPath.empty() || !IsUserSetIcon())
    SetIconPath(channel.IconPath());

  return m_bChanged;
}
bool CPVRClients::OpenLiveStream(const CPVRChannel &tag)
{
  bool bReturn(false);
  CSingleLock lock(m_critSection);

  if (m_currentChannel)
  {
    delete m_currentChannel;
    m_currentChannel = NULL;
  }
  if (m_currentRecording)
  {
    delete m_currentRecording;
    m_currentRecording = NULL;
  }

  ResetQualityData();

  /* try to open the stream on the client */
  if ((tag.StreamURL().IsEmpty() == false ||
      m_clientsProps[tag.ClientID()].bHandlesInputStream) &&
      m_clientMap[tag.ClientID()]->OpenLiveStream(tag))
  {
    m_currentChannel = &tag;
    if (tag.ClientID() == XBMC_VIRTUAL_CLIENTID)
      m_strPlayingClientName = g_localizeStrings.Get(19209);
    else if (!tag.IsVirtual())
      m_strPlayingClientName = GetClientName(tag.ClientID());
    else
      m_strPlayingClientName = g_localizeStrings.Get(13205);

    bReturn = true;
  }

  return bReturn;
}
Example #16
0
bool CPVRClients::SwitchChannel(const CPVRChannel &channel)
{
  bool bSwitchSuccessful(false);
  bool bNewStreamOpened(false);

  {
    CSingleLock lock(m_critSection);
    if (m_bIsSwitchingChannels)
    {
      CLog::Log(LOGDEBUG, "PVRClients - %s - can't switch to channel '%s'. waiting for the previous switch to complete", __FUNCTION__, channel.ChannelName().c_str());
      return false;
    }
    m_bIsSwitchingChannels = true;
  }

  CPVRChannel currentChannel;
  bool bGotPlayingChannel = GetPlayingChannel(currentChannel);
  if (bGotPlayingChannel)
  {
    if (currentChannel != channel)
    {
      /* different client add-on */
      if (currentChannel.ClientID() != channel.ClientID() ||
      /* switch from radio -> tv or tv -> radio */
      currentChannel.IsRadio() != channel.IsRadio())
      {
        CloseStream();
        bSwitchSuccessful = OpenLiveStream(channel);
      }
      else if (!channel.StreamURL().IsEmpty() || !currentChannel.StreamURL().IsEmpty())
      {
        // StreamURL should always be opened as a new file
        CFileItem m_currentFile(channel);
        g_application.getApplicationMessenger().PlayFile(m_currentFile, false);
        bSwitchSuccessful = true;
        bNewStreamOpened = true;
      }
      else
      {
        boost::shared_ptr<CPVRClient> client;
        if (GetConnectedClient(channel.ClientID(), client))
          bSwitchSuccessful = client->SwitchChannel(channel);
      }
    }
    else
    {
      bSwitchSuccessful = true;
    }
  }

  {
    CSingleLock lock(m_critSection);
    m_bIsSwitchingChannels = false;
    if (bSwitchSuccessful && !bNewStreamOpened)
    {
      m_currentChannel = channel;
      m_bIsPlayingLiveTV = true;
      ResetQualityData(m_qualityInfo);
      m_bIsValidChannelSettings = false;
    }
  }

  if (!bSwitchSuccessful)
    CLog::Log(LOGERROR, "PVR - %s - cannot switch channel on client %d",__FUNCTION__, channel.ClientID());

  return bSwitchSuccessful;
}