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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
/*! * @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(); }
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; }
/*! * @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); }
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; }
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; }
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; }