bool CPVREpg::UpdateEntry(const CPVREpgInfoTagPtr &tag, bool bUpdateDatabase) { CPVREpgInfoTagPtr infoTag; { CSingleLock lock(m_critSection); std::map<CDateTime, CPVREpgInfoTagPtr>::iterator it = m_tags.find(tag->StartAsUTC()); bool bNewTag(false); if (it != m_tags.end()) { infoTag = it->second; } else { infoTag.reset(new CPVREpgInfoTag(this, m_pvrChannel, m_strName, m_pvrChannel ? m_pvrChannel->IconPath() : "")); infoTag->SetUniqueBroadcastID(tag->UniqueBroadcastID()); m_tags.insert(std::make_pair(tag->StartAsUTC(), infoTag)); bNewTag = true; } infoTag->Update(*tag, bNewTag); infoTag->SetEpg(this); infoTag->SetChannel(m_pvrChannel); if (bUpdateDatabase) m_changedTags.insert(std::make_pair(infoTag->UniqueBroadcastID(), infoTag)); } infoTag->SetTimer(CServiceBroker::GetPVRManager().Timers()->GetTimerForEpgTag(infoTag)); infoTag->SetRecording(CServiceBroker::GetPVRManager().Recordings()->GetRecordingForEpgTag(infoTag)); return true; }
CPVRTimerInfoTagPtr CPVRTimers::GetTimerForEpgTag(const CPVREpgInfoTagPtr &epgTag) const { if (epgTag) { CSingleLock lock(m_critSection); for (const auto &tagsEntry : m_tags) { for (const auto &timersEntry : tagsEntry.second) { if (timersEntry->IsTimerRule()) continue; if (timersEntry->GetEpgInfoTag(false) == epgTag) return timersEntry; if (timersEntry->m_iClientChannelUid != PVR_CHANNEL_INVALID_UID && timersEntry->m_iClientChannelUid == epgTag->UniqueChannelID()) { if (timersEntry->UniqueBroadcastID() != EPG_TAG_INVALID_UID && timersEntry->UniqueBroadcastID() == epgTag->UniqueBroadcastID()) return timersEntry; if (timersEntry->m_bIsRadio == epgTag->IsRadio() && timersEntry->StartAsUTC() <= epgTag->StartAsUTC() && timersEntry->EndAsUTC() >= epgTag->EndAsUTC()) return timersEntry; } } } } return CPVRTimerInfoTagPtr(); }
CPVRRecordingPtr CPVRRecordings::GetRecordingForEpgTag(const CPVREpgInfoTagPtr &epgTag) const { CSingleLock lock(m_critSection); for (const auto recording : m_recordings) { if (recording.second->IsDeleted()) continue; unsigned int iEpgEvent = recording.second->BroadcastUid(); if (iEpgEvent != EPG_TAG_INVALID_UID) { if (iEpgEvent == epgTag->UniqueBroadcastID()) { // uid matches. perfect. return recording.second; } } else { // uid is optional, so check other relevant data. // note: don't use recording.second->Channel() for comparing channels here as this can lead // to deadlocks. compare client ids and channel ids instead, this has the same effect. if (epgTag->Channel() && recording.second->ClientID() == epgTag->Channel()->ClientID() && recording.second->ChannelUid() == epgTag->Channel()->UniqueID() && recording.second->RecordingTimeAsUTC() <= epgTag->StartAsUTC() && recording.second->EndTimeAsUTC() >= epgTag->EndAsUTC()) return recording.second; } } return CPVRRecordingPtr(); }
CPVRRecordingPtr CPVRRecordings::GetRecordingForEpgTag(const CPVREpgInfoTagPtr &epgTag) const { if (!epgTag) return {}; CSingleLock lock(m_critSection); for (const auto recording : m_recordings) { if (recording.second->IsDeleted()) continue; if (recording.second->ClientID() != epgTag->ClientID()) continue; if (recording.second->ChannelUid() != epgTag->UniqueChannelID()) continue; unsigned int iEpgEvent = recording.second->BroadcastUid(); if (iEpgEvent != EPG_TAG_INVALID_UID) { if (iEpgEvent == epgTag->UniqueBroadcastID()) return recording.second; } else { if (recording.second->RecordingTimeAsUTC() <= epgTag->StartAsUTC() && recording.second->EndTimeAsUTC() >= epgTag->EndAsUTC()) return recording.second; } } return CPVRRecordingPtr(); }
bool CPVREpgSearchFilter::MatchBroadcastId(const CPVREpgInfoTagPtr &tag) const { if (m_iUniqueBroadcastId != EPG_TAG_INVALID_UID) return (tag->UniqueBroadcastID() == m_iUniqueBroadcastId); return true; }
bool CPVREpg::UpdateEntry(const CPVREpgInfoTagPtr &tag, EPG_EVENT_STATE newState, bool bUpdateDatabase) { bool bRet(true); bool bNotify(true); if (newState == EPG_EVENT_CREATED || newState == EPG_EVENT_UPDATED) { bRet = UpdateEntry(tag, bUpdateDatabase); } else if (newState == EPG_EVENT_DELETED) { CSingleLock lock(m_critSection); auto it = m_tags.begin(); for (; it != m_tags.end(); ++it) { if (it->second->UniqueBroadcastID() == tag->UniqueBroadcastID()) break; } if (it == m_tags.end()) { bRet = false; } else { // Respect epg linger time. int iPastDays = CServiceBroker::GetPVRManager().EpgContainer().GetPastDaysToDisplay(); const CDateTime cleanupTime(CDateTime::GetUTCDateTime() - CDateTimeSpan(iPastDays, 0, 0, 0)); if (it->second->EndAsUTC() < cleanupTime) { if (bUpdateDatabase) m_deletedTags.insert(std::make_pair(it->second->UniqueBroadcastID(), it->second)); it->second->ClearTimer(); it->second->ClearRecording(); m_tags.erase(it); } else { bNotify = false; } } } else { CLog::Log(LOGERROR, "EPG - %s - unknown epg event state value: %d", __FUNCTION__, newState); bRet = false; } if (bRet && bNotify) { SetChanged(); NotifyObservers(ObservableMessageEpgItemUpdate); } return bRet; }
void CGUIEPGGridContainerModel::FindChannelAndBlockIndex(int channelUid, unsigned int broadcastUid, int eventOffset, int &newChannelIndex, int &newBlockIndex) const { const CDateTimeSpan blockDuration(0, 0, MINSPERBLOCK, 0); newChannelIndex = INVALID_INDEX; newBlockIndex = INVALID_INDEX; // find the channel int iCurrentChannel = 0; for (const auto& channel : m_channelItems) { if (channel->GetPVRChannelInfoTag()->UniqueID() == channelUid) { newChannelIndex = iCurrentChannel; break; } iCurrentChannel++; } if (newChannelIndex != INVALID_INDEX) { // find the block CDateTime gridCursor(m_gridStart); //reset cursor for new channel unsigned long progIdx = m_epgItemsPtr[newChannelIndex].start; unsigned long lastIdx = m_epgItemsPtr[newChannelIndex].stop; int iEpgId = m_programmeItems[progIdx]->GetEPGInfoTag()->EpgID(); CPVREpgInfoTagPtr tag; for (int block = 0; block < m_blocks; ++block) { while (progIdx <= lastIdx) { tag = m_programmeItems[progIdx]->GetEPGInfoTag(); if (tag->EpgID() != iEpgId || gridCursor < tag->StartAsUTC() || m_gridEnd <= tag->StartAsUTC()) break; // next block if (gridCursor < tag->EndAsUTC()) { if (broadcastUid > 0 && tag->UniqueBroadcastID() == broadcastUid) { newBlockIndex = block + eventOffset; return; // done. } break; // next block } progIdx++; } gridCursor += blockDuration; } } }
/*! * @brief Copy over timer info from xbmcTimer to addonTimer. * @param xbmcTimer The timer on XBMC's side. * @param addonTimer The timer on the addon's side. */ void CPVRClient::WriteClientTimerInfo(const CPVRTimerInfoTag &xbmcTimer, PVR_TIMER &addonTimer) { time_t start, end, firstDay; xbmcTimer.StartAsUTC().GetAsTime(start); xbmcTimer.EndAsUTC().GetAsTime(end); xbmcTimer.FirstDayAsUTC().GetAsTime(firstDay); CPVREpgInfoTagPtr epgTag = xbmcTimer.GetEpgInfoTag(); memset(&addonTimer, 0, sizeof(addonTimer)); addonTimer.iClientIndex = xbmcTimer.m_iClientIndex; addonTimer.iParentClientIndex = xbmcTimer.m_iParentClientIndex; addonTimer.state = xbmcTimer.m_state; addonTimer.iTimerType = xbmcTimer.GetTimerType() ? xbmcTimer.GetTimerType()->GetTypeId() : PVR_TIMER_TYPE_NONE; addonTimer.iClientChannelUid = xbmcTimer.m_iClientChannelUid; strncpy(addonTimer.strTitle, xbmcTimer.m_strTitle.c_str(), sizeof(addonTimer.strTitle) - 1); strncpy(addonTimer.strEpgSearchString, xbmcTimer.m_strEpgSearchString.c_str(), sizeof(addonTimer.strEpgSearchString) - 1); addonTimer.bFullTextEpgSearch = xbmcTimer.m_bFullTextEpgSearch; strncpy(addonTimer.strDirectory, xbmcTimer.m_strDirectory.c_str(), sizeof(addonTimer.strDirectory) - 1); addonTimer.iPriority = xbmcTimer.m_iPriority; addonTimer.iLifetime = xbmcTimer.m_iLifetime; addonTimer.iMaxRecordings = xbmcTimer.m_iMaxRecordings; addonTimer.iPreventDuplicateEpisodes = xbmcTimer.m_iPreventDupEpisodes; addonTimer.iRecordingGroup = xbmcTimer.m_iRecordingGroup; addonTimer.iWeekdays = xbmcTimer.m_iWeekdays; addonTimer.startTime = start - g_advancedSettings.m_iPVRTimeCorrection; addonTimer.endTime = end - g_advancedSettings.m_iPVRTimeCorrection; addonTimer.bStartAnyTime = xbmcTimer.m_bStartAnyTime; addonTimer.bEndAnyTime = xbmcTimer.m_bEndAnyTime; addonTimer.firstDay = firstDay - g_advancedSettings.m_iPVRTimeCorrection; addonTimer.iEpgUid = epgTag ? epgTag->UniqueBroadcastID() : PVR_TIMER_NO_EPG_UID; strncpy(addonTimer.strSummary, xbmcTimer.m_strSummary.c_str(), sizeof(addonTimer.strSummary) - 1); addonTimer.iMarginStart = xbmcTimer.m_iMarginStart; addonTimer.iMarginEnd = xbmcTimer.m_iMarginEnd; addonTimer.iGenreType = epgTag ? epgTag->GenreType() : 0; addonTimer.iGenreSubType = epgTag ? epgTag->GenreSubType() : 0; }