bool CPVRClients::SwitchChannel(const CPVRChannelPtr &channel) { assert(channel.get()); { 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(GetPlayingChannel()); if (// no channel is currently playing !currentChannel || // different backend currentChannel->ClientID() != channel->ClientID() || // stream URL should always be opened as a new file !channel->StreamURL().empty() || !currentChannel->StreamURL().empty()) { if (channel->StreamURL().empty()) { CloseStream(); bSwitchSuccessful = OpenStream(channel, true); } else { CFileItem m_currentFile(channel); CApplicationMessenger::Get().PlayFile(m_currentFile, false); bSwitchSuccessful = true; } } // same channel else if (currentChannel && 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) 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 CPVRChannelPtr &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().empty()) { 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); } catch (std::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 CPVRChannel::UpdateFromClient(const CPVRChannelPtr &channel) { assert(channel.get()); SetClientID(channel->ClientID()); SetStreamURL(channel->StreamURL()); CSingleLock lock(m_critSection); if (m_iClientChannelNumber.channel != channel->ClientChannelNumber() || m_iClientChannelNumber.subchannel != channel->ClientSubChannelNumber() || m_strInputFormat != channel->InputFormat() || m_iClientEncryptionSystem != channel->EncryptionSystem() || m_strClientChannelName != channel->ClientChannelName()) { m_iClientChannelNumber.channel = channel->ClientChannelNumber(); m_iClientChannelNumber.subchannel = channel->ClientSubChannelNumber(); m_strInputFormat = channel->InputFormat(); m_iClientEncryptionSystem = channel->EncryptionSystem(); m_strClientChannelName = channel->ClientChannelName(); UpdateEncryptionName(); SetChanged(); } // 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; }
/*! * @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 CPVRChannelPtr &xbmcChannel, PVR_CHANNEL &addonChannel) { assert(xbmcChannel.get()); memset(&addonChannel, 0, sizeof(addonChannel)); addonChannel.iUniqueId = xbmcChannel->UniqueID(); addonChannel.iChannelNumber = xbmcChannel->ClientChannelNumber(); addonChannel.iSubChannelNumber = xbmcChannel->ClientSubChannelNumber(); 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 CGUIDialogPVRGuideInfo::OnClickButtonPlay(CGUIMessage &message) { bool bReturn = false; if (message.GetSenderId() == CONTROL_BTN_SWITCH || message.GetSenderId() == CONTROL_BTN_PLAY_RECORDING) { Close(); PlayBackRet ret = PLAYBACK_CANCELED; CEpgInfoTagPtr epgTag(m_progItem->GetEPGInfoTag()); if (epgTag) { if (message.GetSenderId() == CONTROL_BTN_PLAY_RECORDING && epgTag->HasRecording()) ret = g_application.PlayFile(CFileItem(epgTag->Recording()), "videoplayer"); else if (epgTag->HasPVRChannel()) { CPVRChannelPtr channel = epgTag->ChannelTag(); // try a fast switch bool bSwitchSuccessful = false; if ((g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio()) && (channel->IsRadio() == g_PVRManager.IsPlayingRadio())) { if (channel->StreamURL().empty()) bSwitchSuccessful = g_application.m_pPlayer->SwitchChannel(channel); } if (!bSwitchSuccessful) { CApplicationMessenger::GetInstance().PostMsg(TMSG_MEDIA_PLAY, 0, 0, static_cast<void*>(new CFileItem(channel)), "videoplayer"); } } } bReturn = true; } return bReturn; }
bool CGUIWindowPVRBase::PlayFile(CFileItem *item, bool bPlayMinimized /* = false */, bool bCheckResume /* = true */) { if (item->m_bIsFolder) { return false; } CPVRChannelPtr channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : CPVRChannelPtr(); if (item->GetPath() == g_application.CurrentFile() || (channel && channel->HasRecording() && channel->GetRecording()->GetPath() == g_application.CurrentFile())) { CGUIMessage msg(GUI_MSG_FULLSCREEN, 0, GetID()); g_windowManager.SendMessage(msg); return true; } CMediaSettings::GetInstance().SetVideoStartWindowed(bPlayMinimized); if (item->HasPVRRecordingInfoTag()) { return PlayRecording(item, bPlayMinimized, bCheckResume); } else { bool bSwitchSuccessful(false); CPVRChannelPtr channel(item->GetPVRChannelInfoTag()); if (channel && g_PVRManager.CheckParentalLock(channel)) { CPVRRecordingPtr recording = channel->GetRecording(); if (recording) { CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*) g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO); if (pDialog) { pDialog->SetHeading(CVariant{19687}); // Play recording pDialog->SetLine(0, CVariant{""}); pDialog->SetLine(1, CVariant{12021}); // Start from beginning pDialog->SetLine(2, CVariant{recording->m_strTitle}); pDialog->Open(); if (pDialog->IsConfirmed()) { CFileItem recordingItem(recording); return PlayRecording(&recordingItem, CSettings::GetInstance().GetBool(CSettings::SETTING_PVRPLAYBACK_PLAYMINIMIZED), bCheckResume); } } } /* try a fast switch */ if ((g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio()) && (channel->IsRadio() == g_PVRManager.IsPlayingRadio())) { if (channel->StreamURL().empty()) bSwitchSuccessful = g_application.m_pPlayer->SwitchChannel(channel); } if (!bSwitchSuccessful) { CApplicationMessenger::GetInstance().PostMsg(TMSG_MEDIA_PLAY, 0, 0, static_cast<void*>(new CFileItem(*item))); return true; } } if (!bSwitchSuccessful) { std::string channelName = g_localizeStrings.Get(19029); // Channel if (channel) channelName = channel->ChannelName(); std::string msg = StringUtils::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 CPVRGUIActions::SwitchToChannel(const CFileItemPtr &item, bool bPlayMinimized, bool bCheckResume) const { if (item->m_bIsFolder) return false; const CPVRChannelPtr channel(CPVRItem(item).GetChannel()); if ((channel && g_PVRManager.IsPlayingChannel(channel)) || (channel && channel->HasRecording() && g_PVRManager.IsPlayingRecording(channel->GetRecording()))) { CGUIMessage msg(GUI_MSG_FULLSCREEN, 0, g_windowManager.GetActiveWindow()); g_windowManager.SendMessage(msg); return true; } CMediaSettings::GetInstance().SetVideoStartWindowed(bPlayMinimized); // switch to channel or if recording present, ask whether to switch or play recording... bool bSwitchSuccessful(false); if (channel && g_PVRManager.CheckParentalLock(channel)) { const CPVRRecordingPtr recording(channel->GetRecording()); if (recording) { bool bCancel(false); bool bPlayRecording = CGUIDialogYesNo::ShowAndGetInput(CVariant{19687}, // "Play recording" CVariant{""}, CVariant{12021}, // "Play from beginning" CVariant{recording->m_strTitle}, bCancel, CVariant{19000}, // "Switch to channel" CVariant{19687}, // "Play recording" 0); // no autoclose if (bCancel) return false; if (bPlayRecording) { const CFileItemPtr recordingItem(new CFileItem(recording)); return PlayRecording(recordingItem, CServiceBroker::GetSettings().GetBool(CSettings::SETTING_PVRPLAYBACK_PLAYMINIMIZED), bCheckResume); } } /* try a fast switch */ if ((g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio()) && (channel->IsRadio() == g_PVRManager.IsPlayingRadio())) { if (channel->StreamURL().empty()) bSwitchSuccessful = g_application.m_pPlayer->SwitchChannel(channel); } if (!bSwitchSuccessful) { CApplicationMessenger::GetInstance().PostMsg(TMSG_MEDIA_PLAY, 0, 0, static_cast<void*>(new CFileItem(channel))); return true; } } if (!bSwitchSuccessful) { std::string channelName = g_localizeStrings.Get(19029); // Channel if (channel) channelName = channel->ChannelName(); std::string msg = StringUtils::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), msg); // PVR information return false; } return true; }