CDateTime CPVRChannelGroup::GetEPGDate(EpgDateType epgDateType) const { CDateTime date; CEpgPtr epg; CPVRChannelPtr channel; CSingleLock lock(m_critSection); for (PVR_CHANNEL_GROUP_MEMBERS::const_iterator it = m_members.begin(); it != m_members.end(); ++it) { channel = it->second.channel; if (!channel->IsHidden() && (epg = channel->GetEPG())) { CDateTime epgDate; switch (epgDateType) { case EPG_FIRST_DATE: epgDate = epg->GetFirstDate(); if (epgDate.IsValid() && (!date.IsValid() || epgDate < date)) date = epgDate; break; case EPG_LAST_DATE: epgDate = epg->GetLastDate(); if (epgDate.IsValid() && (!date.IsValid() || epgDate > date)) date = epgDate; break; } } } return date; }
int CPVRChannelGroup::GetEPGNowOrNext(CFileItemList &results, bool bGetNext) const { int iInitialSize = results.Size(); CEpgInfoTagPtr epgNext; CPVRChannelPtr channel; CSingleLock lock(m_critSection); for (PVR_CHANNEL_GROUP_SORTED_MEMBERS::const_iterator it = m_sortedMembers.begin(); it != m_sortedMembers.end(); ++it) { channel = (*it).channel; CEpgPtr epg = channel->GetEPG(); if (epg && !channel->IsHidden()) { epgNext = bGetNext ? epg->GetTagNext() : epg->GetTagNow(); if (epgNext) { CFileItemPtr entry(new CFileItem(epgNext)); entry->SetLabel2(epgNext->StartAsLocalTime().GetAsLocalizedTime("", false)); entry->SetPath(channel->Path()); entry->SetArt("thumb", channel->IconPath()); results.Add(entry); } } } return results.Size() - iInitialSize; }
int CPVRChannelGroup::GetEPGAll(CFileItemList &results, bool bIncludeChannelsWithoutEPG /* = false */) const { int iInitialSize = results.Size(); CEpgInfoTagPtr epgTag; CPVRChannelPtr channel; CSingleLock lock(m_critSection); for (PVR_CHANNEL_GROUP_SORTED_MEMBERS::const_iterator it = m_sortedMembers.begin(); it != m_sortedMembers.end(); ++it) { channel = (*it).channel; if (!channel->IsHidden()) { int iAdded = 0; CEpgPtr epg = channel->GetEPG(); if (epg) { // XXX channel pointers aren't set in some occasions. this works around the issue, but is not very nice epg->SetChannel(channel); iAdded = epg->Get(results); } if (bIncludeChannelsWithoutEPG && iAdded == 0) { // Add dummy EPG tag associated with this channel epgTag = CEpgInfoTag::CreateDefaultTag(); epgTag->SetPVRChannel(channel); results.Add(CFileItemPtr(new CFileItem(epgTag))); } } } return results.Size() - iInitialSize; }
CEpgInfoTagPtr CEpgContainer::GetTagById(const CPVRChannelPtr &channel, unsigned int iBroadcastId) const { CEpgInfoTagPtr retval; if (iBroadcastId == EPG_TAG_INVALID_UID) return retval; if (channel) { const CEpgPtr epg(channel->GetEPG()); if (epg) retval = epg->GetTagByBroadcastId(iBroadcastId); } else { for (const auto &epgEntry : m_epgs) { retval = epgEntry.second->GetTagByBroadcastId(iBroadcastId); if (retval) break; } } return retval; }
CEpgInfoTagPtr CPVRTimerInfoTag::GetEpgInfoTag(bool bCreate /* = true */) const { if (!m_epgTag && bCreate) { CPVRChannelPtr channel(g_PVRChannelGroups->GetByUniqueID(m_iClientChannelUid, m_iClientId)); if (channel) { const CEpgPtr epg(channel->GetEPG()); if (epg) { CSingleLock lock(m_critSection); if (!m_epgTag) { if (m_iEpgUid != EPG_TAG_INVALID_UID) { m_epgTag = epg->GetTagByBroadcastId(m_iEpgUid); } else if (!m_bStartAnyTime && !m_bEndAnyTime) { // if no epg uid present, try to find a tag according to timer's start/end time m_epgTag = epg->GetTagBetween(StartAsUTC() - CDateTimeSpan(0, 0, 2, 0), EndAsUTC() + CDateTimeSpan(0, 0, 2, 0)); } if (m_epgTag) m_epgTag->SetTimer(g_PVRTimers->GetById(m_iTimerId)); } } } } return m_epgTag; }
CEpgPtr CEpgContainer::CreateChannelEpg(CPVRChannelPtr channel) { if (!channel) return NULL; WaitForUpdateFinish(true); LoadFromDB(); CEpgPtr epg; if (channel->EpgID() > 0) epg = GetById(channel->EpgID()); if (!epg) { channel->SetEpgID(NextEpgId()); epg.reset(new CEpg(channel, false)); CSingleLock lock(m_critSection); m_epgs.insert(std::make_pair((unsigned int)epg->EpgID(), epg)); SetChanged(); epg->RegisterObserver(this); } epg->SetChannel(channel); { CSingleLock lock(m_critSection); m_bPreventUpdates = false; CDateTime::GetCurrentDateTime().GetAsUTCDateTime().GetAsTime(m_iNextEpgUpdate); } NotifyObservers(ObservableMessageEpgContainer); return epg; }
bool CPVRChannel::ClearEPG() const { CEpgPtr epg = GetEPG(); if (epg) epg->Clear(); return true; }
CEpgInfoTagPtr CPVRChannel::GetEPGNext() const { CEpgPtr epg = GetEPG(); if (epg) return epg->GetTagNext(); CEpgInfoTagPtr empty; return empty; }
bool CGUIWindowPVRBase::UpdateEpgForChannel(CFileItem *item) { CPVRChannelPtr channel(item->GetPVRChannelInfoTag()); CEpgPtr epg = channel->GetEPG(); if (!epg) return false; epg->ForceUpdate(); return true; }
void CEpgContainer::CleanupEpgEvents(const CEpgPtr& epg) { CSingleLock lock(m_critSection); if (epg) { m_epgScans.erase(epg->EpgID()); auto events = epg->GetAllEventsWithBroadcastId(); for (const auto &infoTag : events) m_epgEvents.erase(infoTag->UniqueBroadcastID()); } }
int CPVRChannel::GetEPG(CFileItemList &results) const { CEpgPtr epg = GetEPG(); if (!epg) { CLog::Log(LOGDEBUG, "PVR - %s - cannot get EPG for channel '%s'", __FUNCTION__, m_strChannelName.c_str()); return -1; } return epg->Get(results); }
CEpgInfoTagPtr CEpgContainer::GetTagById(const CPVRChannelPtr &channel, unsigned int iBroadcastId) const { CEpgInfoTagPtr retval; if (!channel || iBroadcastId == EPG_TAG_INVALID_UID) return retval; const CEpgPtr epg(channel->GetEPG()); if (epg) retval = epg->GetTagByBroadcastId(iBroadcastId); return retval; }
std::vector<CEpgInfoTagPtr> CEpgContainer::GetEpgTagsForTimer(const CPVRTimerInfoTagPtr &timer) const { CPVRChannelPtr channel(timer->ChannelTag()); if (!channel) channel = timer->UpdateChannel(); if (channel) { const CEpgPtr epg(channel->GetEPG()); if (epg) return epg->GetTagsBetween(timer->StartAsUTC(), timer->EndAsUTC()); } return std::vector<CEpgInfoTagPtr>(); }
bool CEpgContainer::PersistAll(void) { bool bReturn(true); m_critSection.lock(); auto copy = m_epgs; m_critSection.unlock(); for (EPGMAP::const_iterator it = copy.begin(); it != copy.end() && !m_bStop; ++it) { CEpgPtr epg = it->second; if (epg && epg->NeedsSave()) { bReturn &= epg->Persist(); } } return bReturn; }
void CPVRChannelGroupInternal::CreateChannelEpg(const CPVRChannelPtr &channel, bool bForce /* = false */) { if (!channel) return; CSingleLock lock(channel->m_critSection); if (!channel->m_bEPGCreated || bForce) { CEpgPtr epg = g_EpgContainer.CreateChannelEpg(channel); if (epg) { channel->m_bEPGCreated = true; if (epg->EpgID() != channel->m_iEpgId) { channel->m_iEpgId = epg->EpgID(); channel->m_bChanged = true; } } } }
bool CPVRChannel::Delete(void) { bool bReturn = false; const CPVRDatabasePtr database(g_PVRManager.GetTVDatabase()); if (!database) return bReturn; /* delete the EPG table */ CEpgPtr epg = GetEPG(); if (epg) { CPVRChannelPtr empty; epg->SetChannel(empty); g_EpgContainer.DeleteEpg(*epg, true); CSingleLock lock(m_critSection); m_bEPGCreated = false; } bReturn = database->Delete(*this); return bReturn; }
void CEpgContainer::InsertFromDatabase(int iEpgID, const std::string &strName, const std::string &strScraperName) { // table might already have been created when pvr channels were loaded CEpgPtr epg = GetById(iEpgID); if (epg) { if (epg->Name() != strName || epg->ScraperName() != strScraperName) { // current table data differs from the info in the db epg->SetChanged(); SetChanged(); } } else { // create a new epg table epg.reset(new CEpg(iEpgID, strName, strScraperName, true)); if (epg) { m_epgs.insert(std::make_pair(iEpgID, epg)); SetChanged(); epg->RegisterObserver(this); } } }
void CAddonCallbacksPVR::UpdateEpgEvent(const EpgEventStateChange &ch, bool bQueued) { const CPVRChannelPtr channel(g_PVRChannelGroups->GetByUniqueID(ch.iUniqueChannelId, ch.iClientId)); if (channel) { const CEpgPtr epg(channel->GetEPG()); if (epg) { if (!epg->UpdateEntry(ch.event, ch.state)) CLog::Log(LOGERROR, "PVR - %s - epg update failed for %sevent change (%d)", __FUNCTION__, bQueued ? "queued " : "", ch.event->UniqueBroadcastID()); } else { CLog::Log(LOGERROR, "PVR - %s - channel '%s' does not have an EPG! Unable to deliver %sevent change (%d)!", __FUNCTION__, channel->ChannelName().c_str(), bQueued ? "queued " : "", ch.event->UniqueBroadcastID()); } } else CLog::Log(LOGERROR, "PVR - %s - invalid channel (%d)! Unable to deliver %sevent change (%d)!", __FUNCTION__, ch.iUniqueChannelId, bQueued ? "queued " : "", ch.event->UniqueBroadcastID()); }
JSONRPC_STATUS CPVROperations::GetBroadcasts(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { if (!g_PVRManager.IsStarted()) return FailedToExecute; CPVRChannelGroupsContainerPtr channelGroupContainer = g_PVRManager.ChannelGroups(); if (!channelGroupContainer) return FailedToExecute; CPVRChannelPtr channel = channelGroupContainer->GetChannelById((int)parameterObject["channelid"].asInteger()); if (channel == NULL) return InvalidParams; CEpgPtr channelEpg = channel->GetEPG(); if (!channelEpg) return InternalError; CFileItemList programFull; channelEpg->Get(programFull); HandleFileItemList("broadcastid", false, "broadcasts", programFull, parameterObject, result, programFull.Size(), true); return OK; }
void CPVRTimers::UpdateEpgEvent(CPVRTimerInfoTagPtr timer) { CSingleLock lock(timer->m_critSection); /* repeating timers have no epg event */ if (timer->IsRepeating()) return; /* already got an epg event set */ if (timer->m_epgTag) return; /* try to get the channel */ CPVRChannelPtr channel = g_PVRChannelGroups->GetByUniqueID(timer->m_iClientChannelUid, timer->m_iClientId); if (!channel) return; /* try to get the EPG table */ CEpgPtr epg = channel->GetEPG(); if (!epg) return; /* try to set the timer on the epg tag that matches with a 2 minute margin */ CEpgInfoTagPtr epgTag = epg->GetTagBetween(timer->StartAsUTC() - CDateTimeSpan(0, 0, 2, 0), timer->EndAsUTC() + CDateTimeSpan(0, 0, 2, 0)); if (!epgTag) epgTag = epg->GetTagAround(timer->StartAsUTC()); if (epgTag) { timer->m_epgTag = epgTag; timer->m_genre = epgTag->Genre(); timer->m_iGenreType = epgTag->GenreType(); timer->m_iGenreSubType = epgTag->GenreSubType(); epgTag->SetTimer(timer); } }
bool CEpgContainer::UpdateEPG(bool bOnlyPending /* = false */) { bool bInterrupted(false); unsigned int iUpdatedTables(0); bool bShowProgress(false); int pendingUpdates(0); /* set start and end time */ time_t start; time_t end; CDateTime::GetCurrentDateTime().GetAsUTCDateTime().GetAsTime(start); end = start + m_iDisplayTime; start -= g_advancedSettings.m_iEpgLingerTime * 60; bShowProgress = g_advancedSettings.m_bEpgDisplayUpdatePopup && (m_bIsInitialising || g_advancedSettings.m_bEpgDisplayIncrementalUpdatePopup); { CSingleLock lock(m_critSection); if (m_bIsUpdating || InterruptUpdate()) return false; m_bIsUpdating = true; pendingUpdates = m_pendingUpdates; } if (bShowProgress && !bOnlyPending) ShowProgressDialog(); if (!m_bIgnoreDbForClient && !m_database.IsOpen()) { CLog::Log(LOGERROR, "EpgContainer - %s - could not open the database", __FUNCTION__); { CSingleLock lock(m_critSection); m_bIsUpdating = false; m_updateEvent.Set(); } if (bShowProgress && !bOnlyPending) CloseProgressDialog(); return false; } std::vector<CEpgPtr> invalidTables; /* load or update all EPG tables */ unsigned int iCounter(0); for (const auto &epgEntry : m_epgs) { if (InterruptUpdate()) { bInterrupted = true; break; } CEpgPtr epg = epgEntry.second; if (!epg) continue; if (bShowProgress && !bOnlyPending) UpdateProgressDialog(++iCounter, m_epgs.size(), epg->Name()); // we currently only support update via pvr add-ons. skip update when the pvr manager isn't started if (!g_PVRManager.IsStarted()) continue; // check the pvr manager when the channel pointer isn't set if (!epg->Channel()) { CPVRChannelPtr channel = g_PVRChannelGroups->GetChannelByEpgId(epg->EpgID()); if (channel) epg->SetChannel(channel); } if ((!bOnlyPending || epg->UpdatePending()) && epg->Update(start, end, m_iUpdateTime, bOnlyPending)) iUpdatedTables++; else if (!epg->IsValid()) invalidTables.push_back(epg); } for (auto it = invalidTables.begin(); it != invalidTables.end(); ++it) DeleteEpg(**it, true); if (bInterrupted) { /* the update has been interrupted. try again later */ time_t iNow; CDateTime::GetCurrentDateTime().GetAsUTCDateTime().GetAsTime(iNow); m_iNextEpgUpdate = iNow + g_advancedSettings.m_iEpgRetryInterruptedUpdateInterval; } else { if (g_PVRManager.IsStarted()) g_PVRManager.Recordings()->UpdateEpgTags(); CSingleLock lock(m_critSection); CDateTime::GetCurrentDateTime().GetAsUTCDateTime().GetAsTime(m_iNextEpgUpdate); m_iNextEpgUpdate += g_advancedSettings.m_iEpgUpdateCheckInterval; if (m_pendingUpdates == pendingUpdates) m_pendingUpdates = 0; } if (bShowProgress && !bOnlyPending) CloseProgressDialog(); /* notify observers */ if (iUpdatedTables > 0) { SetChanged(); CSingleExit ex(m_critSection); NotifyObservers(ObservableMessageEpgContainer); } CSingleLock lock(m_critSection); m_bIsUpdating = false; m_updateEvent.Set(); return !bInterrupted; }
void CEpgContainer::Process(void) { time_t iNow(0), iLastSave(0); bool bUpdateEpg(true); bool bHasPendingUpdates(false); while (!m_bStop && !g_application.m_bStop) { CDateTime::GetCurrentDateTime().GetAsUTCDateTime().GetAsTime(iNow); { CSingleLock lock(m_critSection); bUpdateEpg = (iNow >= m_iNextEpgUpdate); } /* update the EPG */ if (!InterruptUpdate() && bUpdateEpg && g_PVRManager.EpgsCreated() && UpdateEPG()) m_bIsInitialising = false; /* clean up old entries */ if (!m_bStop && iNow >= m_iLastEpgCleanup + g_advancedSettings.m_iEpgCleanupInterval) RemoveOldEntries(); /* check for pending manual EPG updates */ while (!m_bStop) { SUpdateRequest request; { CSingleLock lock(m_updateRequestsLock); if (m_updateRequests.empty()) break; request = m_updateRequests.front(); m_updateRequests.pop_front(); } // get the channel CPVRChannelPtr channel = g_PVRChannelGroups->GetByUniqueID(request.channelID, request.clientID); CEpgPtr epg; // get the EPG for the channel if (!channel || !(epg = channel->GetEPG())) { CLog::Log(LOGERROR, "PVR - %s - invalid channel or channel doesn't have an EPG", __FUNCTION__); continue; } // force an update epg->ForceUpdate(); } if (!m_bStop) { { CSingleLock lock(m_critSection); bHasPendingUpdates = (m_pendingUpdates > 0); } if (bHasPendingUpdates) UpdateEPG(true); } /* check for updated active tag */ if (!m_bStop) CheckPlayingEvents(); /* check for changes that need to be saved every 60 seconds */ if (iNow - iLastSave > 60) { PersistAll(); iLastSave = iNow; } Sleep(1000); } }