void CAddonCallbacksPVR::PVRTransferTimerEntry(void *addonData, const PVR_HANDLE handle, const PVR_TIMER *timer) { CAddonCallbacks* addon = (CAddonCallbacks*) addonData; if (addon == NULL || handle == NULL || timer == NULL) { CLog::Log(LOGERROR, "CAddonCallbacksPVR - %s - called with a null pointer", __FUNCTION__); return; } CPVRTimers *xbmcTimers = (CPVRTimers*) handle->dataAddress; CPVRClient* client = (CPVRClient*) handle->callerAddress; CPVRChannel *channel = (CPVRChannel *) g_PVRChannelGroups->GetByUniqueID(timer->iClientChannelUid, client->GetClientID()); if (channel == NULL) { CLog::Log(LOGERROR, "CAddonCallbacksPVR - %s - cannot find channel %d on client %d", __FUNCTION__, timer->iClientChannelUid, client->GetClientID()); return; } CPVRTimerInfoTag tag(*timer, channel, client->GetClientID()); /* transfer this entry to the timers container */ xbmcTimers->UpdateFromClient(tag); }
void CAddonCallbacksPVR::PVRTransferTimerEntry(void *addonData, const ADDON_HANDLE handle, const PVR_TIMER *timer) { if (!handle) { CLog::Log(LOGERROR, "PVR - %s - invalid handler data", __FUNCTION__); return; } CPVRClient *client = GetPVRClient(addonData); CPVRTimers *xbmcTimers = static_cast<CPVRTimers *>(handle->dataAddress); if (!timer || !client || !xbmcTimers) { CLog::Log(LOGERROR, "PVR - %s - invalid handler data", __FUNCTION__); return; } CPVRChannelPtr channel = g_PVRChannelGroups->GetByUniqueID(timer->iClientChannelUid, client->GetID()); if (!channel) { CLog::Log(LOGERROR, "PVR - %s - cannot find channel %d on client %d", __FUNCTION__, timer->iClientChannelUid, client->GetID()); return; } /* transfer this entry to the timers container */ CPVRTimerInfoTag transferTimer(*timer, channel, client->GetID()); xbmcTimers->UpdateFromClient(transferTimer); }
void CPVREpgContainer::Clear(bool bClearDb /* = false */) { CSingleLock lock(m_critSection); // XXX stop the timers from being updated while clearing tags /* remove all pointers to epg tables on timers */ CPVRTimers *timers = CPVRManager::GetTimers(); for (unsigned int iTimerPtr = 0; iTimerPtr < timers->size(); iTimerPtr++) timers->at(iTimerPtr)->SetEpgInfoTag(NULL); CEpgContainer::Clear(bClearDb); }
int CPVREpgContainer::GetEPGSearch(CFileItemList* results, const PVREpgSearchFilter &filter) { CEpgContainer::GetEPGSearch(results, filter); /* filter recordings */ if (filter.m_bIgnorePresentRecordings && CPVRManager::GetRecordings()->size() > 0) { for (unsigned int iRecordingPtr = 0; iRecordingPtr < CPVRManager::GetRecordings()->size(); iRecordingPtr++) { for (int iResultPtr = 0; iResultPtr < results->Size(); iResultPtr++) { const CPVREpgInfoTag *epgentry = (CPVREpgInfoTag *) results->Get(iResultPtr)->GetEPGInfoTag(); CPVRRecording *recording = CPVRManager::GetRecordings()->at(iRecordingPtr); if (epgentry) { if (epgentry->Title() != recording->m_strTitle || epgentry->PlotOutline() != recording->m_strPlotOutline || epgentry->Plot() != recording->m_strPlot) continue; results->Remove(iResultPtr); iResultPtr--; } } } } /* filter timers */ if (filter.m_bIgnorePresentTimers) { CPVRTimers *timers = CPVRManager::GetTimers(); for (unsigned int iTimerPtr = 0; iTimerPtr < timers->size(); iTimerPtr++) { for (int iResultPtr = 0; iResultPtr < results->Size(); iResultPtr++) { const CPVREpgInfoTag *epgentry = (CPVREpgInfoTag *) results->Get(iResultPtr)->GetEPGInfoTag(); CPVRTimerInfoTag *timer = timers->at(iTimerPtr); if (epgentry) { if (epgentry->ChannelTag()->ChannelNumber() != timer->ChannelNumber() || epgentry->Start() < timer->m_StartTime || epgentry->End() > timer->m_StopTime) continue; results->Remove(iResultPtr); iResultPtr--; } } } } return results->Size(); }
bool CPVRChannelGroupInternal::UpdateTimers(void) { /* update the timers with the new channel numbers */ CPVRTimers *timers = CPVRManager::GetTimers(); for (unsigned int ptr = 0; ptr < timers->size(); ptr++) { CPVRTimerInfoTag *timer = timers->at(ptr); const CPVRChannel *tag = GetByClient(timer->Number(), timer->ClientID()); if (tag) timer->SetNumber(tag->ChannelNumber()); } return true; }
bool CPVRChannelGroupInternal::UpdateTimers(void) { CSingleLock lock(m_critSection); /* update the timers with the new channel numbers */ CPVRTimers *timers = g_PVRTimers; for (unsigned int ptr = 0; ptr < timers->size(); ptr++) { CPVRTimerInfoTag *timer = timers->at(ptr); const CPVRChannel *tag = GetByClient(timer->m_iClientChannelUid, timer->m_iClientId); if (tag) timer->m_channel = tag; } return true; }
JSONRPC_STATUS CPVROperations::GetTimers(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { if (!g_PVRManager.IsStarted()) return FailedToExecute; CPVRTimers* timers = g_PVRTimers; if (!timers) return FailedToExecute; CFileItemList timerList; timers->GetAll(timerList); HandleFileItemList("timerid", false, "timers", timerList, parameterObject, result, true); return OK; }
JSONRPC_STATUS CPVROperations::DeleteTimer(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { if (!g_PVRManager.IsStarted()) return FailedToExecute; CPVRTimers* timers = g_PVRTimers; CPVRTimerInfoTagPtr timer = timers->GetById(parameterObject["timerid"].asInteger()); if (!timer) return InvalidParams; if (timers->DeleteTimer(timer, timer->IsRecording(), false)) return ACK; return FailedToExecute; }
JSONRPC_STATUS CPVROperations::GetTimerDetails(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { if (!g_PVRManager.IsStarted()) return FailedToExecute; CPVRTimers* timers = g_PVRTimers; if (!timers) return FailedToExecute; CPVRTimerInfoTagPtr timer = timers->GetById((int)parameterObject["timerid"].asInteger()); if (!timer) return InvalidParams; HandleFileItem("timerid", false, "timerdetails", CFileItemPtr(new CFileItem(*timer)), parameterObject, parameterObject["properties"], result, false); return OK; }
void CEpgContainer::Clear(bool bClearDb /* = false */) { /* make sure the update thread is stopped */ bool bThreadRunning = !m_bStop; if (bThreadRunning && !Stop()) { CLog::Log(LOGERROR, "%s - cannot stop the update thread", __FUNCTION__); return; } if (g_PVRManager.IsStarted()) { // XXX stop the timers from being updated while clearing tags /* remove all pointers to epg tables on timers */ CPVRTimers *timers = g_PVRTimers; for (unsigned int iTimerPtr = 0; timers != NULL && iTimerPtr < timers->size(); iTimerPtr++) timers->at(iTimerPtr)->SetEpgInfoTag(NULL); } { CSingleLock lock(m_critSection); /* clear all epg tables and remove pointers to epg tables on channels */ for (unsigned int iEpgPtr = 0; iEpgPtr < m_epgs.size(); iEpgPtr++) delete m_epgs[iEpgPtr]; m_epgs.clear(); m_iNextEpgUpdate = 0; m_bIsInitialising = true; } /* clear the database entries */ if (bClearDb && !m_bIgnoreDbForClient) { if (m_database.Open()) { m_database.DeleteEpg(); m_database.Close(); } } SetChanged(); NotifyObservers("epg", true); if (bThreadRunning) Start(); }
void CAddonHelpers_PVR::PVRTransferTimerEntry(void *addonData, const PVRHANDLE handle, const PVR_TIMERINFO *timer) { CAddonHelpers* addon = (CAddonHelpers*) addonData; if (addon == NULL || handle == NULL || timer == NULL) { CLog::Log(LOGERROR, "PVR: PVRTransferTimerEntry is called with NULL-Pointer!!!"); return; } CPVRTimers *xbmcTimers = (CPVRTimers*) handle->DATA_ADDRESS; CPVRClient* client = (CPVRClient*) handle->CALLER_ADDRESS; const CPVRChannel *channel = CPVRManager::GetChannelGroups()->GetByClientFromAll(timer->channelNum, client->GetClientID()); if (channel == NULL) { CLog::Log(LOGERROR, "PVR: PVRTransferTimerEntry is called with not present channel"); return; } CPVRTimerInfoTag tag; tag.SetClientID(client->GetClientID()); tag.SetClientIndex(timer->index); tag.SetActive(timer->active == 1); tag.SetTitle(timer->title); tag.SetDir(timer->directory); tag.SetClientNumber(timer->channelNum); tag.SetStart((time_t) (timer->starttime+client->GetTimeCorrection())); tag.SetStop((time_t) (timer->endtime+client->GetTimeCorrection())); tag.SetFirstDay((time_t) (timer->firstday+client->GetTimeCorrection())); tag.SetPriority(timer->priority); tag.SetLifetime(timer->lifetime); tag.SetRecording(timer->recording == 1); tag.SetRepeating(timer->repeat == 1); tag.SetWeekdays(timer->repeatflags); CStdString path; path.Format("pvr://client%i/timers/%i", tag.ClientID(), tag.ClientIndex()); tag.SetPath(path); xbmcTimers->Update(tag); return; }
void CAddonCallbacksPVR::PVRTransferTimerEntry(void *addonData, const ADDON_HANDLE handle, const PVR_TIMER *timer) { if (!handle) { CLog::Log(LOGERROR, "PVR - %s - invalid handler data", __FUNCTION__); return; } CPVRClient *client = GetPVRClient(addonData); CPVRTimers *xbmcTimers = static_cast<CPVRTimers *>(handle->dataAddress); if (!timer || !client || !xbmcTimers) { CLog::Log(LOGERROR, "PVR - %s - invalid handler data", __FUNCTION__); return; } /* Note: channel can be NULL here, for instance for epg-based timer rules ("record on any channel" condition). */ CPVRChannelPtr channel = g_PVRChannelGroups->GetByUniqueID(timer->iClientChannelUid, client->GetID()); /* transfer this entry to the timers container */ CPVRTimerInfoTagPtr transferTimer(new CPVRTimerInfoTag(*timer, channel, client->GetID())); xbmcTimers->UpdateFromClient(transferTimer); }
bool CPVREpgInfoTag::HasTimer(void) const { bool bReturn = false; if (m_Timer == NULL) { CPVRTimers *timers = CPVRManager::GetTimers(); for (unsigned int iTimerPtr = 0; iTimerPtr < timers->size(); iTimerPtr++) { if (timers->at(iTimerPtr)->EpgInfoTag() == this) { bReturn = true; break; } } } else { bReturn = true; } return bReturn; }
bool CPVRTimers::UpdateEntries(const CPVRTimers &timers) { bool bChanged(false); bool bAddedOrDeleted(false); std::vector<std::string> timerNotifications; CSingleLock lock(m_critSection); /* go through the timer list and check for updated or new timers */ for (MapTags::const_iterator it = timers.m_tags.begin(); it != timers.m_tags.end(); ++it) { for (VecTimerInfoTag::const_iterator timerIt = it->second->begin(); timerIt != it->second->end(); ++timerIt) { /* check if this timer is present in this container */ CPVRTimerInfoTagPtr existingTimer = GetByClient((*timerIt)->m_iClientId, (*timerIt)->m_iClientIndex); if (existingTimer) { /* if it's present, update the current tag */ bool bStateChanged(existingTimer->m_state != (*timerIt)->m_state); if (existingTimer->UpdateEntry(*timerIt)) { bChanged = true; UpdateEpgEvent(existingTimer); if (bStateChanged && g_PVRManager.IsStarted()) { std::string strMessage; existingTimer->GetNotificationText(strMessage); timerNotifications.push_back(strMessage); } CLog::Log(LOGDEBUG,"PVRTimers - %s - updated timer %d on client %d", __FUNCTION__, (*timerIt)->m_iClientIndex, (*timerIt)->m_iClientId); } } else { /* new timer */ CPVRTimerInfoTagPtr newTimer = CPVRTimerInfoTagPtr(new CPVRTimerInfoTag); newTimer->UpdateEntry(*timerIt); UpdateEpgEvent(newTimer); VecTimerInfoTag* addEntry = NULL; MapTags::iterator itr = m_tags.find(newTimer->StartAsUTC()); if (itr == m_tags.end()) { addEntry = new VecTimerInfoTag; m_tags.insert(std::make_pair(newTimer->StartAsUTC(), addEntry)); } else { addEntry = itr->second; } newTimer->m_iTimerId = ++m_iLastId; addEntry->push_back(newTimer); UpdateEpgEvent(newTimer); bChanged = true; bAddedOrDeleted = true; if (g_PVRManager.IsStarted()) { std::string strMessage; newTimer->GetNotificationText(strMessage); timerNotifications.push_back(strMessage); } CLog::Log(LOGDEBUG,"PVRTimers - %s - added timer %d on client %d", __FUNCTION__, (*timerIt)->m_iClientIndex, (*timerIt)->m_iClientId); } } } /* to collect timer with changed starting time */ VecTimerInfoTag timersToMove; /* check for deleted timers */ for (MapTags::iterator it = m_tags.begin(); it != m_tags.end();) { for (std::vector<CPVRTimerInfoTagPtr>::iterator it2 = it->second->begin(); it2 != it->second->end();) { CPVRTimerInfoTagPtr timer(*it2); if (!timers.GetByClient(timer->m_iClientId, timer->m_iClientIndex)) { /* timer was not found */ CLog::Log(LOGDEBUG,"PVRTimers - %s - deleted timer %d on client %d", __FUNCTION__, timer->m_iClientIndex, timer->m_iClientId); if (g_PVRManager.IsStarted()) timerNotifications.push_back(timer->GetDeletedNotificationText()); /** clear the EPG tag explicitly here, because it no longer happens automatically with shared pointers */ timer->ClearEpgTag(); it2 = it->second->erase(it2); bChanged = true; bAddedOrDeleted = true; } else if (timer->StartAsUTC() != it->first) { /* timer start has changed */ CLog::Log(LOGDEBUG,"PVRTimers - %s - changed start time timer %d on client %d", __FUNCTION__, timer->m_iClientIndex, timer->m_iClientId); timer->ClearEpgTag(); /* remember timer */ timersToMove.push_back(timer); /* remove timer for now, reinsert later */ it2 = it->second->erase(it2); bChanged = true; bAddedOrDeleted = true; } else { ++it2; } } if (it->second->empty()) it = m_tags.erase(it); else ++it; } /* reinsert timers with changed timer start */ for (VecTimerInfoTag::const_iterator timerIt = timersToMove.begin(); timerIt != timersToMove.end(); ++timerIt) { VecTimerInfoTag* addEntry = NULL; MapTags::const_iterator itr = m_tags.find((*timerIt)->StartAsUTC()); if (itr == m_tags.end()) { addEntry = new VecTimerInfoTag; m_tags.insert(std::make_pair((*timerIt)->StartAsUTC(), addEntry)); } else { addEntry = itr->second; } addEntry->push_back(*timerIt); UpdateEpgEvent(*timerIt); } m_bIsUpdating = false; if (bChanged) { UpdateChannels(); SetChanged(); lock.Leave(); NotifyObservers(bAddedOrDeleted ? ObservableMessageTimersReset : ObservableMessageTimers); if (CSettings::GetInstance().GetBool(CSettings::SETTING_PVRRECORD_TIMERNOTIFICATIONS)) { /* queue notifications */ for (unsigned int iNotificationPtr = 0; iNotificationPtr < timerNotifications.size(); iNotificationPtr++) { CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(19166), timerNotifications.at(iNotificationPtr)); } } } return bChanged; }
bool CPVRTimers::UpdateEntries(const CPVRTimers &timers) { bool bChanged(false); bool bAddedOrDeleted(false); vector<CStdString> timerNotifications; CSingleLock lock(m_critSection); /* go through the timer list and check for updated or new timers */ for (map<CDateTime, vector<CPVRTimerInfoTagPtr>* >::const_iterator it = timers.m_tags.begin(); it != timers.m_tags.end(); it++) { for (vector<CPVRTimerInfoTagPtr>::const_iterator timerIt = it->second->begin(); timerIt != it->second->end(); timerIt++) { /* check if this timer is present in this container */ CPVRTimerInfoTagPtr existingTimer = GetByClient((*timerIt)->m_iClientId, (*timerIt)->m_iClientIndex); if (existingTimer) { /* if it's present, update the current tag */ bool bStateChanged(existingTimer->m_state != (*timerIt)->m_state); if (existingTimer->UpdateEntry(*(*timerIt))) { bChanged = true; UpdateEpgEvent(existingTimer); if (bStateChanged && g_PVRManager.IsStarted()) { CStdString strMessage; existingTimer->GetNotificationText(strMessage); timerNotifications.push_back(strMessage); } CLog::Log(LOGDEBUG,"PVRTimers - %s - updated timer %d on client %d", __FUNCTION__, (*timerIt)->m_iClientIndex, (*timerIt)->m_iClientId); } } else { /* new timer */ CPVRTimerInfoTagPtr newTimer = CPVRTimerInfoTagPtr(new CPVRTimerInfoTag); newTimer->UpdateEntry(*(*timerIt)); UpdateEpgEvent(newTimer); vector<CPVRTimerInfoTagPtr>* addEntry = NULL; map<CDateTime, vector<CPVRTimerInfoTagPtr>* >::iterator itr = m_tags.find(newTimer->StartAsUTC()); if (itr == m_tags.end()) { addEntry = new vector<CPVRTimerInfoTagPtr>; m_tags.insert(make_pair(newTimer->StartAsUTC(), addEntry)); } else { addEntry = itr->second; } addEntry->push_back(newTimer); UpdateEpgEvent(newTimer); bChanged = true; bAddedOrDeleted = true; if (g_PVRManager.IsStarted()) { CStdString strMessage; newTimer->GetNotificationText(strMessage); timerNotifications.push_back(strMessage); } CLog::Log(LOGDEBUG,"PVRTimers - %s - added timer %d on client %d", __FUNCTION__, (*timerIt)->m_iClientIndex, (*timerIt)->m_iClientId); } } } /* to collect timer with changed starting time */ vector<CPVRTimerInfoTagPtr> timersToMove; /* check for deleted timers */ for (map<CDateTime, vector<CPVRTimerInfoTagPtr>* >::iterator it = m_tags.begin(); it != m_tags.end();) { for (int iTimerPtr = it->second->size() - 1; iTimerPtr >= 0; iTimerPtr--) { CPVRTimerInfoTagPtr timer = it->second->at(iTimerPtr); if (!timers.GetByClient(timer->m_iClientId, timer->m_iClientIndex)) { /* timer was not found */ CLog::Log(LOGDEBUG,"PVRTimers - %s - deleted timer %d on client %d", __FUNCTION__, timer->m_iClientIndex, timer->m_iClientId); if (g_PVRManager.IsStarted()) { CStdString strMessage; strMessage.Format("%s: '%s'", (timer->EndAsUTC() <= CDateTime::GetCurrentDateTime().GetAsUTCDateTime()) ? g_localizeStrings.Get(19227) : g_localizeStrings.Get(19228), timer->m_strTitle.c_str()); timerNotifications.push_back(strMessage); } it->second->erase(it->second->begin() + iTimerPtr); bChanged = true; bAddedOrDeleted = true; } else if (timer->StartAsUTC() != it->first) { /* timer start has changed */ CLog::Log(LOGDEBUG,"PVRTimers - %s - changed start time timer %d on client %d", __FUNCTION__, timer->m_iClientIndex, timer->m_iClientId); timer->ClearEpgTag(); /* remember timer */ timersToMove.push_back(timer); /* remove timer for now, reinsert later */ it->second->erase(it->second->begin() + iTimerPtr); bChanged = true; bAddedOrDeleted = true; } } if (it->second->size() == 0) m_tags.erase(it++); else ++it; } /* reinsert timers with changed timer start */ for (vector<CPVRTimerInfoTagPtr>::const_iterator timerIt = timersToMove.begin(); timerIt != timersToMove.end(); timerIt++) { vector<CPVRTimerInfoTagPtr>* addEntry = NULL; map<CDateTime, vector<CPVRTimerInfoTagPtr>* >::const_iterator itr = m_tags.find((*timerIt)->StartAsUTC()); if (itr == m_tags.end()) { addEntry = new vector<CPVRTimerInfoTagPtr>; m_tags.insert(make_pair((*timerIt)->StartAsUTC(), addEntry)); } else { addEntry = itr->second; } addEntry->push_back(*timerIt); UpdateEpgEvent(*timerIt); } m_bIsUpdating = false; if (bChanged) { UpdateChannels(); SetChanged(); lock.Leave(); NotifyObservers(bAddedOrDeleted ? ObservableMessageTimersReset : ObservableMessageTimers); if (g_guiSettings.GetBool("pvrrecord.timernotifications")) { /* queue notifications */ for (unsigned int iNotificationPtr = 0; iNotificationPtr < timerNotifications.size(); iNotificationPtr++) { CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(19166), timerNotifications.at(iNotificationPtr)); } } } return bChanged; }
bool CPVRTimers::UpdateEntries(const CPVRTimers &timers, const std::vector<int> &failedClients) { bool bChanged(false); bool bAddedOrDeleted(false); std::vector< std::pair< int, std::string> > timerNotifications; CSingleLock lock(m_critSection); /* go through the timer list and check for updated or new timers */ for (MapTags::const_iterator it = timers.m_tags.begin(); it != timers.m_tags.end(); ++it) { for (VecTimerInfoTag::const_iterator timerIt = it->second->begin(); timerIt != it->second->end(); ++timerIt) { /* check if this timer is present in this container */ CPVRTimerInfoTagPtr existingTimer = GetByClient((*timerIt)->m_iClientId, (*timerIt)->m_iClientIndex); if (existingTimer) { /* if it's present, update the current tag */ bool bStateChanged(existingTimer->m_state != (*timerIt)->m_state); if (existingTimer->UpdateEntry(*timerIt)) { bChanged = true; existingTimer->ResetChildState(); if (bStateChanged && g_PVRManager.IsStarted()) { std::string strMessage; existingTimer->GetNotificationText(strMessage); timerNotifications.push_back(std::make_pair((*timerIt)->m_iClientId, strMessage)); } CLog::Log(LOGDEBUG,"PVRTimers - %s - updated timer %d on client %d", __FUNCTION__, (*timerIt)->m_iClientIndex, (*timerIt)->m_iClientId); } } else { /* new timer */ CPVRTimerInfoTagPtr newTimer = CPVRTimerInfoTagPtr(new CPVRTimerInfoTag); newTimer->UpdateEntry(*timerIt); VecTimerInfoTag* addEntry = NULL; MapTags::iterator itr = m_tags.find(newTimer->m_bStartAnyTime ? CDateTime() : newTimer->StartAsUTC()); if (itr == m_tags.end()) { addEntry = new VecTimerInfoTag; m_tags.insert(std::make_pair(newTimer->m_bStartAnyTime ? CDateTime() : newTimer->StartAsUTC(), addEntry)); } else { addEntry = itr->second; } newTimer->m_iTimerId = ++m_iLastId; addEntry->push_back(newTimer); bChanged = true; bAddedOrDeleted = true; if (g_PVRManager.IsStarted()) { std::string strMessage; newTimer->GetNotificationText(strMessage); timerNotifications.push_back(std::make_pair(newTimer->m_iClientId, strMessage)); } CLog::Log(LOGDEBUG,"PVRTimers - %s - added timer %d on client %d", __FUNCTION__, (*timerIt)->m_iClientIndex, (*timerIt)->m_iClientId); } } } /* to collect timer with changed starting time */ VecTimerInfoTag timersToMove; /* check for deleted timers */ for (MapTags::iterator it = m_tags.begin(); it != m_tags.end();) { for (std::vector<CPVRTimerInfoTagPtr>::iterator it2 = it->second->begin(); it2 != it->second->end();) { CPVRTimerInfoTagPtr timer(*it2); if (!timers.GetByClient(timer->m_iClientId, timer->m_iClientIndex)) { /* timer was not found */ bool bIgnoreTimer(false); for (const auto &failedClient : failedClients) { if (failedClient == timer->m_iClientId) { bIgnoreTimer = true; break; } } if (bIgnoreTimer) { ++it2; continue; } CLog::Log(LOGDEBUG,"PVRTimers - %s - deleted timer %d on client %d", __FUNCTION__, timer->m_iClientIndex, timer->m_iClientId); if (g_PVRManager.IsStarted()) timerNotifications.push_back(std::make_pair(timer->m_iClientId, timer->GetDeletedNotificationText())); /** clear the EPG tag explicitly here, because it no longer happens automatically with shared pointers */ timer->ClearEpgTag(); it2 = it->second->erase(it2); bChanged = true; bAddedOrDeleted = true; } else if ((timer->m_bStartAnyTime && it->first != CDateTime()) || (!timer->m_bStartAnyTime && timer->StartAsUTC() != it->first)) { /* timer start has changed */ CLog::Log(LOGDEBUG,"PVRTimers - %s - changed start time timer %d on client %d", __FUNCTION__, timer->m_iClientIndex, timer->m_iClientId); timer->ClearEpgTag(); /* remember timer */ timersToMove.push_back(timer); /* remove timer for now, reinsert later */ it2 = it->second->erase(it2); bChanged = true; bAddedOrDeleted = true; } else { ++it2; } } if (it->second->empty()) it = m_tags.erase(it); else ++it; } /* reinsert timers with changed timer start */ for (VecTimerInfoTag::const_iterator timerIt = timersToMove.begin(); timerIt != timersToMove.end(); ++timerIt) { VecTimerInfoTag* addEntry = NULL; MapTags::const_iterator itr = m_tags.find((*timerIt)->m_bStartAnyTime ? CDateTime() : (*timerIt)->StartAsUTC()); if (itr == m_tags.end()) { addEntry = new VecTimerInfoTag; m_tags.insert(std::make_pair((*timerIt)->m_bStartAnyTime ? CDateTime() : (*timerIt)->StartAsUTC(), addEntry)); } else { addEntry = itr->second; } addEntry->push_back(*timerIt); } /* update child information for all parent timers */ for (const auto &tagsEntry : m_tags) { for (const auto &timersEntry : *tagsEntry.second) { if (timersEntry->GetTimerRuleId() != PVR_TIMER_NO_PARENT) { const CPVRTimerInfoTagPtr parentTimer(GetByClient(timersEntry->m_iClientId, timersEntry->GetTimerRuleId())); if (parentTimer) parentTimer->UpdateChildState(timersEntry); } } } m_bIsUpdating = false; if (bChanged) { UpdateChannels(); SetChanged(); lock.Leave(); NotifyObservers(bAddedOrDeleted ? ObservableMessageTimersReset : ObservableMessageTimers); /* queue notifications / fill eventlog */ for (const auto &entry : timerNotifications) { if (CSettings::GetInstance().GetBool(CSettings::SETTING_PVRRECORD_TIMERNOTIFICATIONS)) CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(19166), entry.second); std::string strName; g_PVRClients->GetClientAddonName(entry.first, strName); std::string strIcon; g_PVRClients->GetClientAddonIcon(entry.first, strIcon); CEventLog::GetInstance().Add(EventPtr(new CNotificationEvent(strName, entry.second, strIcon, EventLevel::Information))); } } return bChanged; }