void CPVRGUIInfo::UpdatePlayingTag(void) { CPVRChannelPtr currentChannel; CPVRRecording recording; if (g_PVRManager.GetCurrentChannel(currentChannel)) { CEpgInfoTag epgTag; bool bHasEpgTag = GetPlayingTag(epgTag); CPVRChannelPtr channel; if (bHasEpgTag) channel = epgTag.ChannelTag(); if (!bHasEpgTag || !epgTag.IsActive() || !channel || *channel != *currentChannel) { CEpgInfoTag newTag; { CSingleLock lock(m_critSection); ResetPlayingTag(); if (currentChannel->GetEPGNow(newTag)) { m_playingEpgTag = new CEpgInfoTag(newTag); m_iDuration = m_playingEpgTag->GetDuration() * 1000; } } g_PVRManager.UpdateCurrentFile(); } } else if (g_PVRClients->GetPlayingRecording(recording)) { ResetPlayingTag(); m_iDuration = recording.GetDuration() * 1000; } }
void CPVRRecordings::GetContents(const CStdString &strDirectory, CFileItemList *results) { for (unsigned int iRecordingPtr = 0; iRecordingPtr < m_recordings.size(); iRecordingPtr++) { CPVRRecording *current = m_recordings.at(iRecordingPtr); bool directMember = !HasAllRecordingsPathExtension(strDirectory); if (!IsDirectoryMember(RemoveAllRecordingsPathExtension(strDirectory), current->m_strDirectory, directMember)) continue; current->UpdateMetadata(); CFileItemPtr pFileItem(new CFileItem(*current)); pFileItem->SetLabel2(current->RecordingTimeAsLocalTime().GetAsLocalizedDateTime(true, false)); pFileItem->m_dateTime = current->RecordingTimeAsLocalTime(); pFileItem->SetPath(current->m_strFileNameAndPath); if (!current->m_strIconPath.IsEmpty()) pFileItem->SetIconImage(current->m_strIconPath); if (!current->m_strThumbnailPath.IsEmpty()) pFileItem->SetArt("thumb", current->m_strThumbnailPath); if (!current->m_strFanartPath.IsEmpty()) pFileItem->SetArt("fanart", current->m_strFanartPath); pFileItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, pFileItem->GetPVRRecordingInfoTag()->m_playCount > 0); results->Add(pFileItem); } }
void CPVRRecordings::UpdateEntry(const CPVRRecording &tag) { bool bFound = false; CSingleLock lock(m_critSection); for (unsigned int iRecordingPtr = 0; iRecordingPtr < m_recordings.size(); iRecordingPtr++) { CPVRRecording *currentTag = m_recordings.at(iRecordingPtr); if (currentTag->m_iClientId == tag.m_iClientId && currentTag->m_strRecordingId.Equals(tag.m_strRecordingId)) { currentTag->Update(tag); bFound = true; break; } } if (!bFound) { CPVRRecording *newTag = new CPVRRecording(); newTag->Update(tag); newTag->m_iRecordingId = ++m_iLastId; m_recordings.push_back(newTag); } }
/*! * @brief Copy over recording info from xbmcRecording to addonRecording. * @param xbmcRecording The recording on XBMC's side. * @param addonRecording The recording on the addon's side. */ void CPVRClient::WriteClientRecordingInfo(const CPVRRecording &xbmcRecording, PVR_RECORDING &addonRecording) { time_t recTime; xbmcRecording.RecordingTimeAsUTC().GetAsTime(recTime); memset(&addonRecording, 0, sizeof(addonRecording)); addonRecording.recordingTime = recTime - g_advancedSettings.m_iPVRTimeCorrection; strncpy(addonRecording.strRecordingId, xbmcRecording.m_strRecordingId.c_str(), sizeof(addonRecording.strRecordingId) - 1); strncpy(addonRecording.strTitle, xbmcRecording.m_strTitle.c_str(), sizeof(addonRecording.strTitle) - 1); strncpy(addonRecording.strPlotOutline, xbmcRecording.m_strPlotOutline.c_str(), sizeof(addonRecording.strPlotOutline) - 1); strncpy(addonRecording.strPlot, xbmcRecording.m_strPlot.c_str(), sizeof(addonRecording.strPlot) - 1); strncpy(addonRecording.strChannelName, xbmcRecording.m_strChannelName.c_str(), sizeof(addonRecording.strChannelName) - 1); addonRecording.iDuration = xbmcRecording.GetDuration(); addonRecording.iPriority = xbmcRecording.m_iPriority; addonRecording.iLifetime = xbmcRecording.m_iLifetime; addonRecording.iPlayCount = xbmcRecording.m_playCount; addonRecording.iLastPlayedPosition = (int)xbmcRecording.m_resumePoint.timeInSeconds; addonRecording.bIsDeleted = xbmcRecording.IsDeleted(); strncpy(addonRecording.strDirectory, xbmcRecording.m_strDirectory.c_str(), sizeof(addonRecording.strDirectory) - 1); strncpy(addonRecording.strStreamURL, xbmcRecording.m_strStreamURL.c_str(), sizeof(addonRecording.strStreamURL) - 1); strncpy(addonRecording.strIconPath, xbmcRecording.m_strIconPath.c_str(), sizeof(addonRecording.strIconPath) - 1); strncpy(addonRecording.strThumbnailPath, xbmcRecording.m_strThumbnailPath.c_str(), sizeof(addonRecording.strThumbnailPath) - 1); strncpy(addonRecording.strFanartPath, xbmcRecording.m_strFanartPath.c_str(), sizeof(addonRecording.strFanartPath) - 1); }
bool CPVRRecording::operator ==(const CPVRRecording& right) const { return (this == &right) || (m_strRecordingId == right.m_strRecordingId && m_iClientId == right.m_iClientId && m_strChannelName == right.m_strChannelName && m_recordingTime == right.m_recordingTime && GetDuration() == right.GetDuration() && m_strPlotOutline == right.m_strPlotOutline && m_strPlot == right.m_strPlot && m_iPriority == right.m_iPriority && m_iLifetime == right.m_iLifetime && m_strDirectory == right.m_strDirectory && m_strFileNameAndPath == right.m_strFileNameAndPath && m_strTitle == right.m_strTitle && m_strShowTitle == right.m_strShowTitle && m_iSeason == right.m_iSeason && m_iEpisode == right.m_iEpisode && GetPremiered() == right.GetPremiered() && m_strIconPath == right.m_strIconPath && m_strThumbnailPath == right.m_strThumbnailPath && m_strFanartPath == right.m_strFanartPath && m_iRecordingId == right.m_iRecordingId && m_bIsDeleted == right.m_bIsDeleted && m_iEpgEventId == right.m_iEpgEventId && m_iChannelUid == right.m_iChannelUid && m_bRadio == right.m_bRadio); }
void CPVRRecordings::GetAll(CFileItemList &items) { CSingleLock lock(m_critSection); for (unsigned int iRecordingPtr = 0; iRecordingPtr < m_recordings.size(); iRecordingPtr++) { CPVRRecording *current = m_recordings.at(iRecordingPtr); CFileItemPtr pFileItem(new CFileItem(*current)); pFileItem->SetLabel2(current->RecordingTimeAsLocalTime().GetAsLocalizedDateTime(true, false)); pFileItem->m_dateTime = current->RecordingTimeAsLocalTime(); pFileItem->SetPath(current->m_strFileNameAndPath); // Set the play count either directly from client (if supported) or from video db if (g_PVRClients->SupportsRecordingPlayCount(pFileItem->GetPVRRecordingInfoTag()->m_iClientId)) { pFileItem->GetPVRRecordingInfoTag()->m_playCount=pFileItem->GetPVRRecordingInfoTag()->m_iRecPlayCount; } else { CVideoDatabase db; if (db.Open()) pFileItem->GetPVRRecordingInfoTag()->m_playCount=db.GetPlayCount(*pFileItem); } pFileItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, pFileItem->GetPVRRecordingInfoTag()->m_playCount > 0); items.Add(pFileItem); } }
bool CPVRRecordings::DeleteRecording(const CFileItem &item) { if (!item.IsPVRRecording()) { CLog::Log(LOGERROR, "CPVRRecordings - %s - cannot delete file: no valid recording tag", __FUNCTION__); return false; } CPVRRecording *tag = (CPVRRecording *)item.GetPVRRecordingInfoTag(); return tag->Delete(); }
void CPVRRecording::Update(const CPVRRecording &tag) { m_strRecordingId = tag.m_strRecordingId; m_iClientId = tag.m_iClientId; m_strTitle = tag.m_strTitle; m_strShowTitle = tag.m_strShowTitle; m_iSeason = tag.m_iSeason; m_iEpisode = tag.m_iEpisode; SetPremiered(tag.GetPremiered()); m_recordingTime = tag.m_recordingTime; m_iPriority = tag.m_iPriority; m_iLifetime = tag.m_iLifetime; m_strDirectory = tag.m_strDirectory; m_strPlot = tag.m_strPlot; m_strPlotOutline = tag.m_strPlotOutline; m_strStreamURL = tag.m_strStreamURL; m_strChannelName = tag.m_strChannelName; m_genre = tag.m_genre; m_strIconPath = tag.m_strIconPath; m_strThumbnailPath = tag.m_strThumbnailPath; m_strFanartPath = tag.m_strFanartPath; m_bIsDeleted = tag.m_bIsDeleted; m_iEpgEventId = tag.m_iEpgEventId; m_iChannelUid = tag.m_iChannelUid; m_bRadio = tag.m_bRadio; CVideoInfoTag::SetPlayCount(tag.GetLocalPlayCount()); CVideoInfoTag::SetResumePoint(tag.GetLocalResumePoint()); SetDuration(tag.GetDuration()); //Old Method of identifying TV show title and subtitle using m_strDirectory and strPlotOutline (deprecated) std::string strShow = StringUtils::Format("%s - ", g_localizeStrings.Get(20364).c_str()); if (StringUtils::StartsWithNoCase(m_strPlotOutline, strShow)) { CLog::Log(LOGDEBUG,"CPVRRecording::Update - PVR addon provides episode name in strPlotOutline which is deprecated"); std::string strEpisode = m_strPlotOutline; std::string strTitle = m_strDirectory; size_t pos = strTitle.rfind('/'); strTitle.erase(0, pos + 1); strEpisode.erase(0, strShow.size()); m_strTitle = strTitle; pos = strEpisode.find('-'); strEpisode.erase(0, pos + 2); m_strShowTitle = strEpisode; } if (m_bIsDeleted) OnDelete(); UpdatePath(); }
bool CPVRRecordings::RenameRecording(CFileItem &item, CStdString &strNewName) { bool bReturn = false; if (!item.IsPVRRecording()) { CLog::Log(LOGERROR, "CPVRRecordings - %s - cannot rename file: no valid recording tag", __FUNCTION__); return bReturn; } CPVRRecording* tag = item.GetPVRRecordingInfoTag(); return tag->Rename(strNewName); }
bool CPVRFile::Delete(const CURL& url) { CStdString path(url.GetFileName()); if (path.Left(11) == "recordings/" && path[path.size()-1] != '/') { CStdString strURL = url.Get(); CPVRRecording *tag = CPVRManager::GetRecordings()->GetByPath(strURL); if (tag) return tag->Delete(); } return false; }
void CPVRRecordings::GetContents(const CStdString &strDirectory, CFileItemList *results) const { for (unsigned int iRecordingPtr = 0; iRecordingPtr < size(); iRecordingPtr++) { CPVRRecording *current = at(iRecordingPtr); if (!IsDirectoryMember(strDirectory, current->m_strDirectory, true)) continue; CFileItemPtr pFileItem(new CFileItem(*current)); pFileItem->SetLabel2(current->RecordingTimeAsLocalTime().GetAsLocalizedDateTime(true, false)); pFileItem->m_dateTime = current->RecordingTimeAsLocalTime(); pFileItem->m_strPath.Format("pvr://recordings/%05i-%05i.pvr", current->m_iClientId, current->m_iClientIndex); results->Add(pFileItem); } }
/*! * @brief Copy over recording info from xbmcRecording to addonRecording. * @param xbmcRecording The recording on XBMC's side. * @param addonRecording The recording on the addon's side. */ inline void PVRWriteClientRecordingInfo(const CPVRRecording &xbmcRecording, PVR_RECORDING &addonRecording) { time_t recTime; xbmcRecording.RecordingTimeAsUTC().GetAsTime(recTime); addonRecording.recordingTime = recTime - g_advancedSettings.m_iPVRTimeCorrection; addonRecording.strRecordingId = xbmcRecording.m_strRecordingId.c_str(); addonRecording.strTitle = xbmcRecording.m_strTitle.c_str(); addonRecording.strPlotOutline = xbmcRecording.m_strPlotOutline.c_str(); addonRecording.strPlot = xbmcRecording.m_strPlot.c_str(); addonRecording.strChannelName = xbmcRecording.m_strChannelName.c_str(); addonRecording.iDuration = xbmcRecording.GetDuration(); addonRecording.iPriority = xbmcRecording.m_iPriority; addonRecording.iLifetime = xbmcRecording.m_iLifetime; addonRecording.strDirectory = xbmcRecording.m_strDirectory.c_str(); addonRecording.strStreamURL = xbmcRecording.m_strStreamURL.c_str(); }
void CPVRRecordings::SetPlayCount(const CFileItem &item, int iPlayCount) { if (!item.HasPVRRecordingInfoTag()) return; const CPVRRecording *recording = item.GetPVRRecordingInfoTag(); CSingleLock lock(m_critSection); for (unsigned int iRecordingPtr = 0; iRecordingPtr < m_recordings.size(); iRecordingPtr++) { CPVRRecording *current = m_recordings.at(iRecordingPtr); if (*current == *recording) { current->SetPlayCount(iPlayCount); break; } } }
void CPVRRecordings::GetAll(CFileItemList &items) { CSingleLock lock(m_critSection); for (unsigned int iRecordingPtr = 0; iRecordingPtr < m_recordings.size(); iRecordingPtr++) { CPVRRecording *current = m_recordings.at(iRecordingPtr); current->UpdateMetadata(); CFileItemPtr pFileItem(new CFileItem(*current)); pFileItem->SetLabel2(current->RecordingTimeAsLocalTime().GetAsLocalizedDateTime(true, false)); pFileItem->m_dateTime = current->RecordingTimeAsLocalTime(); pFileItem->SetPath(current->m_strFileNameAndPath); pFileItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, pFileItem->GetPVRRecordingInfoTag()->m_playCount > 0); items.Add(pFileItem); } }
bool CPVRFile::Rename(const CURL& url, const CURL& urlnew) { CStdString path(url.GetFileName()); CStdString newname(urlnew.GetFileName()); size_t found = newname.find_last_of("/"); if (found != CStdString::npos) newname = newname.substr(found+1); if (path.Left(11) == "recordings/" && path[path.size()-1] != '/') { CStdString strURL = url.Get(); CPVRRecording *tag = CPVRManager::GetRecordings()->GetByPath(strURL); if (tag) return tag->Rename(newname); } return false; }
void CPVRGUIInfo::UpdatePlayingTag(void) { CSingleLock lock(m_critSection); CPVRChannel currentChannel; CPVRRecording recording; if (g_PVRManager.GetCurrentChannel(¤tChannel)) { if (!m_playingEpgTag || !m_playingEpgTag->IsActive() || (*m_playingEpgTag->ChannelTag() != currentChannel)) { m_playingEpgTag = currentChannel.GetEPGNow(); m_iDuration = m_playingEpgTag ? m_playingEpgTag->GetDuration() * 1000 : 0; g_PVRManager.UpdateCurrentFile(); } } else if (g_PVRClients->GetPlayingRecording(&recording)) { m_playingEpgTag = NULL; m_iDuration = recording.GetDuration() * 1000; } }
void CPVRRecordings::UpdateEntry(const CPVRRecording &tag) { bool bFound = false; CSingleLock lock(m_critSection); for (unsigned int iRecordingPtr = 0; iRecordingPtr < size(); iRecordingPtr++) { CPVRRecording *currentTag = at(iRecordingPtr); if (currentTag->m_iClientId == tag.m_iClientId && currentTag->m_iClientIndex == tag.m_iClientIndex) { currentTag->Update(tag); bFound = true; break; } } if (!bFound) { CPVRRecording *newTag = new CPVRRecording(); newTag->Update(tag); push_back(newTag); } }
PVR_ERROR CPVRClients::UndeleteRecording(const CPVRRecording &recording) { PVR_ERROR error(PVR_ERROR_UNKNOWN); if (!recording.IsDeleted()) return error; PVR_CLIENT client; if (GetConnectedClient(recording.m_iClientId, client)) error = client->UndeleteRecording(recording); if (error != PVR_ERROR_NO_ERROR) CLog::Log(LOGERROR, "PVR - %s - cannot undelete recording from client '%d': %s",__FUNCTION__, recording.m_iClientId, CPVRClient::ToString(error)); return error; }
void CPVRRecordings::GetContents(const CStdString &strDirectory, CFileItemList *results) { for (unsigned int iRecordingPtr = 0; iRecordingPtr < m_recordings.size(); iRecordingPtr++) { CPVRRecording *current = m_recordings.at(iRecordingPtr); bool directMember = !HasAllRecordingsPathExtension(strDirectory); if (!IsDirectoryMember(RemoveAllRecordingsPathExtension(strDirectory), current->m_strDirectory, directMember)) continue; CFileItemPtr pFileItem(new CFileItem(*current)); pFileItem->SetLabel2(current->RecordingTimeAsLocalTime().GetAsLocalizedDateTime(true, false)); pFileItem->m_dateTime = current->RecordingTimeAsLocalTime(); pFileItem->SetPath(current->m_strFileNameAndPath); if (!current->m_strIconPath.IsEmpty()) pFileItem->SetIconImage(current->m_strIconPath); if (!current->m_strThumbnailPath.IsEmpty()) pFileItem->SetThumbnailImage(current->m_strThumbnailPath); if (!current->m_strFanartPath.IsEmpty()) pFileItem->SetProperty("Fanart_Image", current->m_strFanartPath); // Set the play count either directly from client (if supported) or from video db if (g_PVRClients->SupportsRecordingPlayCount(pFileItem->GetPVRRecordingInfoTag()->m_iClientId)) { pFileItem->GetPVRRecordingInfoTag()->m_playCount=pFileItem->GetPVRRecordingInfoTag()->m_iRecPlayCount; } else { CVideoDatabase db; if (db.Open()) pFileItem->GetPVRRecordingInfoTag()->m_playCount=db.GetPlayCount(*pFileItem); } pFileItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, pFileItem->GetPVRRecordingInfoTag()->m_playCount > 0); // Set the resumePoint either directly from client (if supported) or from video db int positionInSeconds = current->GetLastPlayedPosition(); if (positionInSeconds > 0) { // If the back-end does report a saved position then make sure there is a corresponding resume bookmark CBookmark bookmark; bookmark.timeInSeconds = positionInSeconds; bookmark.totalTimeInSeconds = (double)current->GetDuration(); pFileItem->GetPVRRecordingInfoTag()->m_resumePoint = bookmark; } else if (positionInSeconds < 0) { CVideoDatabase db; if (db.Open()) { CBookmark bookmark; if (db.GetResumeBookMark(current->m_strFileNameAndPath, bookmark)) pFileItem->GetPVRRecordingInfoTag()->m_resumePoint = bookmark; db.Close(); } } results->Add(pFileItem); } }
void CPVRRecordings::GetSubDirectories(const CStdString &strBase, CFileItemList *results, bool bAutoSkip /* = true */) { CStdString strUseBase = TrimSlashes(strBase); std::set<CStdString> unwatchedFolders; for (unsigned int iRecordingPtr = 0; iRecordingPtr < m_recordings.size(); iRecordingPtr++) { CPVRRecording *current = m_recordings.at(iRecordingPtr); const CStdString strCurrent = GetDirectoryFromPath(current->m_strDirectory, strUseBase); if (strCurrent.IsEmpty()) continue; CStdString strFilePath; if(strUseBase.empty()) strFilePath.Format("pvr://recordings/%s/", strCurrent.c_str()); else strFilePath.Format("pvr://recordings/%s/%s/", strUseBase.c_str(), strCurrent.c_str()); if (!results->Contains(strFilePath)) { CFileItemPtr pFileItem; pFileItem.reset(new CFileItem(strCurrent, true)); pFileItem->SetPath(strFilePath); pFileItem->SetLabel(strCurrent); pFileItem->SetLabelPreformated(true); pFileItem->m_dateTime = current->RecordingTimeAsLocalTime(); // Initialize folder overlay from play count (either directly from client or from video database) CVideoDatabase db; bool supportsPlayCount = g_PVRClients->SupportsRecordingPlayCount(current->m_iClientId); if ((supportsPlayCount && current->m_iRecPlayCount > 0) || (!supportsPlayCount && db.Open() && db.GetPlayCount(*pFileItem) > 0)) { pFileItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_WATCHED, false); } else { unwatchedFolders.insert(strFilePath); } results->Add(pFileItem); } else { CFileItemPtr pFileItem; pFileItem=results->Get(strFilePath); if (pFileItem->m_dateTime<current->RecordingTimeAsLocalTime()) pFileItem->m_dateTime = current->RecordingTimeAsLocalTime(); // Unset folder overlay if recording is unwatched if (unwatchedFolders.find(strFilePath) == unwatchedFolders.end()) { CVideoDatabase db; bool supportsPlayCount = g_PVRClients->SupportsRecordingPlayCount(current->m_iClientId); if ((supportsPlayCount && current->m_iRecPlayCount == 0) || (!supportsPlayCount && db.Open() && db.GetPlayCount(*pFileItem) == 0)) { pFileItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, false); unwatchedFolders.insert(strFilePath); } } } } int subDirectories = results->Size(); CFileItemList files; GetContents(strBase, &files); if (bAutoSkip && results->Size() == 1 && files.Size() == 0) { CStdString strGetPath; strGetPath.Format("%s/%s/", strUseBase.c_str(), results->Get(0)->GetLabel()); results->Clear(); CLog::Log(LOGDEBUG, "CPVRRecordings - %s - '%s' only has 1 subdirectory, selecting that directory ('%s')", __FUNCTION__, strUseBase.c_str(), strGetPath.c_str()); GetSubDirectories(strGetPath, results, true); return; } results->Append(files); // Add 'All Recordings' item (if we have at least one subdirectory in the list) if (subDirectories > 0) { CStdString strLabel(g_localizeStrings.Get(19270)); // "* All recordings" CFileItemPtr pItem(new CFileItem(strLabel)); CStdString strAllPath; if(strUseBase.empty()) strAllPath = "pvr://recordings"; else strAllPath.Format("pvr://recordings/%s", strUseBase.c_str()); pItem->SetPath(AddAllRecordingsPathExtension(strAllPath)); pItem->SetSpecialSort(SortSpecialOnTop); pItem->SetLabelPreformated(true); pItem->m_bIsFolder = true; pItem->m_bIsShareOrDrive = false; for(int i=0; i<results->Size(); ++i) { if(pItem->m_dateTime < results->Get(i)->m_dateTime) pItem->m_dateTime = results->Get(i)->m_dateTime; } results->AddFront(pItem, 0); } if (!strUseBase.IsEmpty()) { CStdString strLabel(".."); CFileItemPtr pItem(new CFileItem(strLabel)); pItem->SetPath(m_strDirectoryHistory); pItem->m_bIsFolder = true; pItem->m_bIsShareOrDrive = false; results->AddFront(pItem, 0); } m_strDirectoryHistory.Format("pvr://recordings/%s", strUseBase.c_str()); }