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 CPVRTimerInfoTag::CreateFromEpg(const CEpgInfoTagPtr &tag) { /* create a new timer */ CPVRTimerInfoTagPtr newTag(new CPVRTimerInfoTag()); if (!newTag) { CLog::Log(LOGERROR, "%s - couldn't create new timer", __FUNCTION__); return CPVRTimerInfoTagPtr(); } /* 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()) { 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 = -1; 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_iGenreType = tag->GenreType(); newTag->m_iGenreSubType = tag->GenreSubType(); newTag->m_channel = channel; newTag->SetStartFromUTC(newStart); newTag->SetEndFromUTC(newEnd); if (tag->Plot().empty()) { newTag->m_strSummary= StringUtils::Format("%s %s %s %s %s", newTag->StartAsLocalTime().GetAsLocalizedDate().c_str(), g_localizeStrings.Get(19159).c_str(), newTag->StartAsLocalTime().GetAsLocalizedTime("", false).c_str(), g_localizeStrings.Get(19160).c_str(), newTag->EndAsLocalTime().GetAsLocalizedTime("", false).c_str()); } else { newTag->m_strSummary = tag->Plot(); } newTag->m_epgTag = g_EpgContainer.GetById(tag->EpgID())->GetTag(tag->StartAsUTC()); /* unused only for reference */ newTag->m_strFileNameAndPath = "pvr://timers/new"; return newTag; }
void CGUIEPGGridContainerModel::Refresh(const std::unique_ptr<CFileItemList> &items, const CDateTime &gridStart, const CDateTime &gridEnd, int iRulerUnit, int iBlocksPerPage, float fBlockSize) { Reset(); //////////////////////////////////////////////////////////////////////// // Create programme & channel items m_programmeItems.reserve(items->Size()); CFileItemPtr fileItem; int iLastChannelID = -1; ItemsPtr itemsPointer; itemsPointer.start = 0; CPVRChannelPtr channel; int j = 0; for (int i = 0; i < items->Size(); ++i) { fileItem = items->Get(i); if (!fileItem->HasEPGInfoTag() || !fileItem->GetEPGInfoTag()->HasPVRChannel()) continue; m_programmeItems.emplace_back(fileItem); channel = fileItem->GetEPGInfoTag()->ChannelTag(); if (!channel) continue; int iCurrentChannelID = channel->ChannelID(); if (iCurrentChannelID != iLastChannelID) { if (j > 0) { itemsPointer.stop = j - 1; m_epgItemsPtr.emplace_back(itemsPointer); itemsPointer.start = j; } iLastChannelID = iCurrentChannelID; m_channelItems.emplace_back(CFileItemPtr(new CFileItem(channel))); } ++j; } if (!m_programmeItems.empty()) { itemsPointer.stop = m_programmeItems.size() - 1; m_epgItemsPtr.emplace_back(itemsPointer); } /* check for invalid start and end time */ if (gridStart >= gridEnd) { // default to start "now minus 30 minutes" and end "start plus one page". m_gridStart = CDateTime::GetCurrentDateTime().GetAsUTCDateTime() - CDateTimeSpan(0, 0, 30, 0); m_gridEnd = m_gridStart + CDateTimeSpan(0, 0, iBlocksPerPage * MINSPERBLOCK, 0); } else { m_gridStart = CDateTime(gridStart.GetYear(), gridStart.GetMonth(), gridStart.GetDay(), gridStart.GetHour(), gridStart.GetMinute() >= 30 ? 30 : 0, 0); m_gridEnd = CDateTime(gridEnd.GetYear(), gridEnd.GetMonth(), gridEnd.GetDay(), gridEnd.GetHour(), gridEnd.GetMinute() >= 30 ? 30 : 0, 0); } //////////////////////////////////////////////////////////////////////// // Create ruler items CDateTime ruler; ruler.SetFromUTCDateTime(m_gridStart); CDateTime rulerEnd; rulerEnd.SetFromUTCDateTime(m_gridEnd); CFileItemPtr rulerItem(new CFileItem(ruler.GetAsLocalizedDate(true))); rulerItem->SetProperty("DateLabel", true); m_rulerItems.emplace_back(rulerItem); const CDateTimeSpan unit(0, 0, iRulerUnit * MINSPERBLOCK, 0); for (; ruler < rulerEnd; ruler += unit) { rulerItem.reset(new CFileItem(ruler.GetAsLocalizedTime("", false))); rulerItem->SetLabel2(ruler.GetAsLocalizedDate(true)); m_rulerItems.emplace_back(rulerItem); } FreeItemsMemory(); //////////////////////////////////////////////////////////////////////// // Create epg grid const CDateTimeSpan blockDuration(0, 0, MINSPERBLOCK, 0); const CDateTimeSpan gridDuration(m_gridEnd - m_gridStart); m_blocks = (gridDuration.GetDays() * 24 * 60 + gridDuration.GetHours() * 60 + gridDuration.GetMinutes()) / MINSPERBLOCK; if (m_blocks >= MAXBLOCKS) m_blocks = MAXBLOCKS; m_gridIndex.reserve(m_channelItems.size()); const std::vector<GridItem> blocks(m_blocks); for (size_t channel = 0; channel < m_channelItems.size(); ++channel) { m_gridIndex.emplace_back(blocks); 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(); int itemSize = 1; // size of the programme in blocks int savedBlock = 0; CFileItemPtr item; CEpgInfoTagPtr tag; for (int block = 0; block < m_blocks; ++block) { while (progIdx <= lastIdx) { item = m_programmeItems[progIdx]; tag = item->GetEPGInfoTag(); if (tag->EpgID() != iEpgId || gridCursor < tag->StartAsUTC() || m_gridEnd <= tag->StartAsUTC()) break; if (gridCursor < tag->EndAsUTC()) { m_gridIndex[channel][block].item = item; m_gridIndex[channel][block].progIndex = progIdx; break; } progIdx++; } gridCursor += blockDuration; if (block == 0) continue; const CFileItemPtr prevItem(m_gridIndex[channel][block - 1].item); const CFileItemPtr currItem(m_gridIndex[channel][block].item); if (block == m_blocks - 1 || prevItem != currItem) { // special handling for last block. int blockDelta = -1; int sizeDelta = 0; if (block == m_blocks - 1 && prevItem == currItem) { itemSize++; blockDelta = 0; sizeDelta = 1; } if (prevItem) { m_gridIndex[channel][savedBlock].item->SetProperty("GenreType", prevItem->GetEPGInfoTag()->GenreType()); } else { CEpgInfoTagPtr gapTag(CEpgInfoTag::CreateDefaultTag()); gapTag->SetPVRChannel(m_channelItems[channel]->GetPVRChannelInfoTag()); CFileItemPtr gapItem(new CFileItem(gapTag)); for (int i = block + blockDelta; i >= block - itemSize + sizeDelta; --i) { m_gridIndex[channel][i].item = gapItem; } } float fItemWidth = itemSize * fBlockSize; m_gridIndex[channel][savedBlock].originWidth = fItemWidth; m_gridIndex[channel][savedBlock].width = fItemWidth; itemSize = 1; savedBlock = block; // special handling for last block. if (block == m_blocks - 1 && prevItem != currItem) { if (currItem) { m_gridIndex[channel][savedBlock].item->SetProperty("GenreType", currItem->GetEPGInfoTag()->GenreType()); } else { CEpgInfoTagPtr gapTag(CEpgInfoTag::CreateDefaultTag()); gapTag->SetPVRChannel(m_channelItems[channel]->GetPVRChannelInfoTag()); CFileItemPtr gapItem(new CFileItem(gapTag)); m_gridIndex[channel][block].item = gapItem; } m_gridIndex[channel][savedBlock].originWidth = fBlockSize; // size always 1 block here m_gridIndex[channel][savedBlock].width = fBlockSize; } } else { itemSize++; } } } }
CPVRTimerInfoTagPtr CPVRTimerInfoTag::CreateFromEpg(const CEpgInfoTagPtr &tag, bool bRepeating /* = 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()) { 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 = -1; 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_iGenreType = tag->GenreType(); newTag->m_iGenreSubType = tag->GenreSubType(); newTag->m_channel = channel; newTag->SetStartFromUTC(newStart); newTag->SetEndFromUTC(newEnd); CPVRTimerTypePtr timerType; if (bRepeating) { // create repeating epg-based timer timerType = CPVRTimerType::CreateFromAttributes( PVR_TIMER_TYPE_IS_REPEATING, PVR_TIMER_TYPE_IS_MANUAL | PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES, channel->ClientID()); } if (!timerType) { // 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->m_epgTag = g_EpgContainer.GetById(tag->EpgID())->GetTag(tag->StartAsUTC()); /* unused only for reference */ newTag->m_strFileNameAndPath = CPVRTimersPath::PATH_NEW; return newTag; }