bool CEpg::UpdateEntry(const CEpgInfoTagPtr &tag, bool bUpdateDatabase /* = false */) { CEpgInfoTagPtr infoTag; { CSingleLock lock(m_critSection); std::map<CDateTime, CEpgInfoTagPtr>::iterator it = m_tags.find(tag->StartAsUTC()); bool bNewTag(false); if (it != m_tags.end()) { infoTag = it->second; } else { infoTag.reset(new CEpgInfoTag(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->SetPVRChannel(m_pvrChannel); if (bUpdateDatabase) m_changedTags.insert(std::make_pair(infoTag->UniqueBroadcastID(), infoTag)); } infoTag->SetTimer(g_PVRTimers->GetTimerForEpgTag(infoTag)); infoTag->SetRecording(g_PVRRecordings->GetRecordingForEpgTag(infoTag)); return true; }
/*! * @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); CEpgInfoTagPtr epgTag = xbmcTimer.GetEpgInfoTag(); memset(&addonTimer, 0, sizeof(addonTimer)); addonTimer.iClientIndex = xbmcTimer.m_iClientIndex; addonTimer.state = xbmcTimer.m_state; addonTimer.iClientIndex = xbmcTimer.m_iClientIndex; addonTimer.iClientChannelUid = xbmcTimer.m_iClientChannelUid; strncpy(addonTimer.strTitle, xbmcTimer.m_strTitle.c_str(), sizeof(addonTimer.strTitle) - 1); strncpy(addonTimer.strDirectory, xbmcTimer.m_strDirectory.c_str(), sizeof(addonTimer.strDirectory) - 1); addonTimer.iPriority = xbmcTimer.m_iPriority; addonTimer.iLifetime = xbmcTimer.m_iLifetime; addonTimer.bIsRepeating = xbmcTimer.m_bIsRepeating; addonTimer.iWeekdays = xbmcTimer.m_iWeekdays; addonTimer.startTime = start - g_advancedSettings.m_iPVRTimeCorrection; addonTimer.endTime = end - g_advancedSettings.m_iPVRTimeCorrection; addonTimer.firstDay = firstDay - g_advancedSettings.m_iPVRTimeCorrection; addonTimer.iEpgUid = epgTag ? epgTag->UniqueBroadcastID() : -1; strncpy(addonTimer.strSummary, xbmcTimer.m_strSummary.c_str(), sizeof(addonTimer.strSummary) - 1); addonTimer.iMarginStart = xbmcTimer.m_iMarginStart; addonTimer.iMarginEnd = xbmcTimer.m_iMarginEnd; addonTimer.iGenreType = xbmcTimer.m_iGenreType; addonTimer.iGenreSubType = xbmcTimer.m_iGenreSubType; }
bool CEpg::UpdateEntry(const CEpgInfoTag &tag, bool bUpdateDatabase /* = false */, bool bSort /* = true */) { CEpgInfoTagPtr infoTag; CSingleLock lock(m_critSection); map<CDateTime, CEpgInfoTagPtr>::iterator it = m_tags.find(tag.StartAsUTC()); bool bNewTag(false); if (it != m_tags.end()) { infoTag = it->second; } else { /* create a new tag if no tag with this ID exists */ infoTag.reset(new CEpgInfoTag(this, m_pvrChannel, m_strName, m_pvrChannel ? m_pvrChannel->IconPath() : "")); infoTag->SetUniqueBroadcastID(tag.UniqueBroadcastID()); m_tags.insert(make_pair(tag.StartAsUTC(), infoTag)); bNewTag = true; } infoTag->Update(tag, bNewTag); infoTag->SetEpg(this); infoTag->SetPVRChannel(m_pvrChannel); if (bUpdateDatabase) m_changedTags.insert(make_pair(infoTag->UniqueBroadcastID(), infoTag)); return true; }
bool CEpg::UpdateEntry(const CEpgInfoTagPtr &tag, EPG_EVENT_STATE newState, bool bUpdateDatabase /* = false */) { 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. const CDateTime cleanupTime(CDateTime::GetUTCDateTime() - CDateTimeSpan(0, g_advancedSettings.m_iEpgLingerTime / 60, g_advancedSettings.m_iEpgLingerTime % 60, 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); bool bFoundPrevChannel = false; for (size_t channel = 0; channel < m_channelItems.size(); ++channel) { CDateTime gridCursor(m_gridStart); //reset cursor for new channel unsigned long progIdx = m_epgItemsPtr[channel].start; unsigned long lastIdx = m_epgItemsPtr[channel].stop; int iEpgId = m_programmeItems[progIdx]->GetEPGInfoTag()->EpgID(); CEpgInfoTagPtr tag; CPVRChannelPtr chan; 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) { newChannelIndex = channel; newBlockIndex = block + eventOffset; return; // both found. done. } if (!bFoundPrevChannel && channelUid > -1) { chan = tag->ChannelTag(); if (chan && chan->UniqueID() == channelUid) { newChannelIndex = channel; bFoundPrevChannel = true; } } break; // next block } progIdx++; } gridCursor += blockDuration; } } }
CPVRTimerInfoTagPtr CPVRTimers::GetTimerForEpgTag(const CEpgInfoTagPtr &epgTag) const { if (epgTag) { // already a timer assigned to tag? CPVRTimerInfoTagPtr timer(epgTag->Timer()); if (timer) return timer; // try to find a matching timer for the tag. if (epgTag->ChannelTag()) { const CPVRChannelPtr channel(epgTag->ChannelTag()); CSingleLock lock(m_critSection); for (MapTags::const_iterator it = m_tags.begin(); it != m_tags.end(); ++it) { for (VecTimerInfoTag::const_iterator timerIt = it->second->begin(); timerIt != it->second->end(); ++timerIt) { timer = *timerIt; if (!timer->IsRepeating() && (timer->GetEpgInfoTag(false) == epgTag || (timer->m_iEpgUid != EPG_TAG_INVALID_UID && timer->m_iEpgUid == epgTag->UniqueBroadcastID()) || (timer->m_iClientChannelUid == channel->UniqueID() && timer->m_bIsRadio == channel->IsRadio() && timer->StartAsUTC() <= epgTag->StartAsUTC() && timer->EndAsUTC() >= epgTag->EndAsUTC()))) { return timer; } } } } } return CPVRTimerInfoTagPtr(); }
/*! * @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); CEpgInfoTagPtr 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; }
bool CEpg::UpdateEntry(const CEpgInfoTagPtr &tag, EPG_EVENT_STATE newState, std::map<CDateTime, CEpgInfoTagPtr>::iterator &eit, bool bUpdateDatabase /* = false */) { CEpgInfoTagPtr infoTag; bool bNewTag(false); CSingleLock lock(m_critSection); if (newState == EPG_EVENT_CREATED || newState == EPG_EVENT_UPDATED) { // Reuse passed iterator in favor of doing expensive find self auto it = (eit == m_tags.end()) ? m_tags.find(tag->StartAsUTC()) : eit; if (it != m_tags.end()) { if (newState == EPG_EVENT_CREATED) CLog::Log(LOGERROR, "EPG - %s - Error: EPG_EVENT_CREATED: uid %d found! Updating existing event.", __FUNCTION__, tag->UniqueBroadcastID()); infoTag = it->second; } else { if (newState == EPG_EVENT_UPDATED) CLog::Log(LOGERROR, "EPG - %s - Error: EPG_EVENT_UPDATED: uid %d not found. Inserting new event.", __FUNCTION__, tag->UniqueBroadcastID()); infoTag.reset(new CEpgInfoTag(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; } } else if (newState == EPG_EVENT_DELETED) { // Reuse passed iterator in favor of doing expensive find self auto it = (eit == m_tags.end()) ? m_tags.find(tag->StartAsUTC()) : eit; if (it == m_tags.end()) { // not guranteed that deleted tag contains valid start time. search sequential. for (it = m_tags.begin(); it != m_tags.end(); ++it) { if (it->second->UniqueBroadcastID() == tag->UniqueBroadcastID()) break; } } if (it != m_tags.end()) { it->second->ClearTimer(); m_tags.erase(it); if (bUpdateDatabase) m_deletedTags.insert(std::make_pair(infoTag->UniqueBroadcastID(), infoTag)); } else { CLog::Log(LOGERROR, "EPG - %s - Error: EPG_EVENT_DELETED: uid %d not found.", __FUNCTION__, tag->UniqueBroadcastID()); return false; } return true; } else { CLog::Log(LOGERROR, "EPG - %s - unknownn epg event state '%d'.", __FUNCTION__, newState); return false; } infoTag->Update(*tag, bNewTag); infoTag->SetEpg(this); infoTag->SetPVRChannel(m_pvrChannel); if (bUpdateDatabase) m_changedTags.insert(std::make_pair(infoTag->UniqueBroadcastID(), infoTag)); return true; }
CPVRTimerInfoTagPtr CPVRTimerInfoTag::CreateFromEpg(const CEpgInfoTagPtr &tag, bool bCreateRule /* = false */) { /* create a new timer */ CPVRTimerInfoTagPtr newTag(new CPVRTimerInfoTag()); /* check if a valid channel is set */ CPVRChannelPtr channel = tag->ChannelTag(); if (!channel) { CLog::Log(LOGERROR, "%s - no channel set", __FUNCTION__); return CPVRTimerInfoTagPtr(); } /* check if the epg end date is in the future */ if (tag->EndAsLocalTime() < CDateTime::GetCurrentDateTime() && !bCreateRule) { CLog::Log(LOGERROR, "%s - end time is in the past", __FUNCTION__); return CPVRTimerInfoTagPtr(); } /* set the timer data */ CDateTime newStart = tag->StartAsUTC(); CDateTime newEnd = tag->EndAsUTC(); newTag->m_iClientIndex = PVR_TIMER_NO_CLIENT_INDEX; newTag->m_iParentClientIndex = PVR_TIMER_NO_PARENT; newTag->m_strTitle = tag->Title().empty() ? channel->ChannelName() : tag->Title(); newTag->m_iChannelNumber = channel->ChannelNumber(); newTag->m_iClientChannelUid = channel->UniqueID(); newTag->m_iClientId = channel->ClientID(); newTag->m_bIsRadio = channel->IsRadio(); newTag->m_channel = channel; newTag->m_iEpgUid = tag->UniqueBroadcastID(); newTag->SetStartFromUTC(newStart); newTag->SetEndFromUTC(newEnd); CPVRTimerTypePtr timerType; if (bCreateRule) { // create epg-based timer rule timerType = CPVRTimerType::CreateFromAttributes( PVR_TIMER_TYPE_IS_REPEATING, PVR_TIMER_TYPE_IS_MANUAL | PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES, channel->ClientID()); if (timerType) { if (timerType->SupportsEpgTitleMatch()) newTag->m_strEpgSearchString = newTag->m_strTitle; if (timerType->SupportsWeekdays()) newTag->m_iWeekdays = PVR_WEEKDAY_ALLDAYS; if (timerType->SupportsStartAnyTime()) newTag->m_bStartAnyTime = true; if (timerType->SupportsEndAnyTime()) newTag->m_bEndAnyTime = true; } } else { // create one-shot epg-based timer timerType = CPVRTimerType::CreateFromAttributes( PVR_TIMER_TYPE_ATTRIBUTE_NONE, PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_IS_MANUAL | PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES, channel->ClientID()); } if (!timerType) { CLog::Log(LOGERROR, "%s - unable to create any epg-based timer type", __FUNCTION__); return CPVRTimerInfoTagPtr(); } newTag->SetTimerType(timerType); newTag->UpdateSummary(); newTag->UpdateEpgInfoTag(); /* unused only for reference */ newTag->m_strFileNameAndPath = CPVRTimersPath::PATH_NEW; return newTag; }