2 * Copyright (C) 2010-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
20 #ifndef SAVE_FILE_STATE_H__
21 #define SAVE_FILE_STATE_H__
25 #include "pvr/PVRManager.h"
26 #include "pvr/recordings/PVRRecordings.h"
27 #include "settings/MediaSettings.h"
28 #include "network/upnp/UPnP.h"
30 class CSaveFileStateJob : public CJob
33 CFileItem m_item_discstack;
35 bool m_updatePlayCount;
37 CSaveFileStateJob(const CFileItem& item,
38 const CFileItem& item_discstack,
39 const CBookmark& bookmark,
42 m_item_discstack(item_discstack),
44 m_updatePlayCount(updatePlayCount) {}
45 virtual ~CSaveFileStateJob() {}
46 virtual bool DoWork();
49 bool CSaveFileStateJob::DoWork()
51 CStdString progressTrackingFile = m_item.GetPath();
53 if (m_item.HasVideoInfoTag() && StringUtils::StartsWith(m_item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://"))
54 progressTrackingFile = m_item.GetVideoInfoTag()->m_strFileNameAndPath; // this variable contains removable:// suffixed by disc label+uniqueid or is empty if label not uniquely identified
55 else if (m_item.HasProperty("original_listitem_url"))
57 // only use original_listitem_url for Python, UPnP and Bluray sources
58 CStdString original = m_item.GetProperty("original_listitem_url").asString();
59 if (URIUtils::IsPlugin(original) || URIUtils::IsUPnP(original) || URIUtils::IsBluray(m_item.GetPath()))
60 progressTrackingFile = original;
63 if (progressTrackingFile != "")
66 // checks if UPnP server of this file is available and supports updating
67 if (URIUtils::IsUPnP(progressTrackingFile)
68 && UPNP::CUPnP::SaveFileState(m_item, m_bookmark, m_updatePlayCount)) {
74 std::string redactPath = CURL::GetRedacted(progressTrackingFile);
75 CLog::Log(LOGDEBUG, "%s - Saving file state for video item %s", __FUNCTION__, redactPath.c_str());
77 CVideoDatabase videodatabase;
78 if (!videodatabase.Open())
80 CLog::Log(LOGWARNING, "%s - Unable to open video database. Can not save file state!", __FUNCTION__);
84 bool updateListing = false;
85 // No resume & watched status for livetv
86 if (!m_item.IsLiveTV())
88 if (m_updatePlayCount)
90 CLog::Log(LOGDEBUG, "%s - Marking video item %s as watched", __FUNCTION__, redactPath.c_str());
92 // consider this item as played
93 videodatabase.IncrementPlayCount(m_item);
94 m_item.GetVideoInfoTag()->m_playCount++;
96 // PVR: Set recording's play count on the backend (if supported)
97 if (m_item.HasPVRRecordingInfoTag())
98 m_item.GetPVRRecordingInfoTag()->IncrementPlayCount();
100 m_item.SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, true);
101 updateListing = true;
104 videodatabase.UpdateLastPlayed(m_item);
106 if (!m_item.HasVideoInfoTag() || m_item.GetVideoInfoTag()->m_resumePoint.timeInSeconds != m_bookmark.timeInSeconds)
108 if (m_bookmark.timeInSeconds <= 0.0f)
109 videodatabase.ClearBookMarksOfFile(progressTrackingFile, CBookmark::RESUME);
111 videodatabase.AddBookMarkToFile(progressTrackingFile, m_bookmark, CBookmark::RESUME);
112 if (m_item.HasVideoInfoTag())
113 m_item.GetVideoInfoTag()->m_resumePoint = m_bookmark;
115 // PVR: Set/clear recording's resume bookmark on the backend (if supported)
116 if (m_item.HasPVRRecordingInfoTag())
118 PVR::CPVRRecording *recording = m_item.GetPVRRecordingInfoTag();
119 recording->SetLastPlayedPosition(m_bookmark.timeInSeconds <= 0.0f ? 0 : (int)m_bookmark.timeInSeconds);
120 recording->m_resumePoint = m_bookmark;
123 // UPnP announce resume point changes to clients
124 // however not if playcount is modified as that already announces
125 if (m_item.IsVideoDb() && !m_updatePlayCount)
128 data["id"] = m_item.GetVideoInfoTag()->m_iDbId;
129 data["type"] = m_item.GetVideoInfoTag()->m_type;
130 ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::VideoLibrary, "xbmc", "OnUpdate", data);
133 updateListing = true;
137 if (CMediaSettings::Get().GetCurrentVideoSettings() != CMediaSettings::Get().GetDefaultVideoSettings())
139 videodatabase.SetVideoSettings(progressTrackingFile, CMediaSettings::Get().GetCurrentVideoSettings());
142 if (m_item.HasVideoInfoTag() && m_item.GetVideoInfoTag()->HasStreamDetails())
144 CFileItem dbItem(m_item);
146 // Check whether the item's db streamdetails need updating
147 if (!videodatabase.GetStreamDetails(dbItem) || dbItem.GetVideoInfoTag()->m_streamDetails != m_item.GetVideoInfoTag()->m_streamDetails)
149 videodatabase.SetStreamDetailsForFile(m_item.GetVideoInfoTag()->m_streamDetails, progressTrackingFile);
150 updateListing = true;
154 // in order to properly update the the list, we need to update the stack item which is held in g_application.m_stackFileItemToUpdate
155 if (m_item.HasProperty("stackFileItemToUpdate"))
157 m_item = m_item_discstack; // as of now, the item is replaced by the discstack item
158 videodatabase.GetResumePoint(*m_item.GetVideoInfoTag());
160 videodatabase.Close();
164 CUtil::DeleteVideoDatabaseDirectoryCache();
165 CFileItemPtr msgItem(new CFileItem(m_item));
166 if (m_item.HasProperty("original_listitem_url"))
167 msgItem->SetPath(m_item.GetProperty("original_listitem_url").asString());
168 CGUIMessage message(GUI_MSG_NOTIFY_ALL, g_windowManager.GetActiveWindow(), 0, GUI_MSG_UPDATE_ITEM, 1, msgItem); // 1 to update the listing as well
169 g_windowManager.SendThreadMessage(message);
174 if (m_item.IsAudio())
176 std::string redactPath = CURL::GetRedacted(progressTrackingFile);
177 CLog::Log(LOGDEBUG, "%s - Saving file state for audio item %s", __FUNCTION__, redactPath.c_str());
179 if (m_updatePlayCount)
182 // Can't write to the musicdatabase while scanning for music info
183 CGUIDialogMusicScan *dialog = (CGUIDialogMusicScan *)g_windowManager.GetWindow(WINDOW_DIALOG_MUSIC_SCAN);
184 if (dialog && !dialog->IsDialogRunning())
187 CMusicDatabase musicdatabase;
188 if (!musicdatabase.Open())
190 CLog::Log(LOGWARNING, "%s - Unable to open music database. Can not save file state!", __FUNCTION__);
194 // consider this item as played
195 CLog::Log(LOGDEBUG, "%s - Marking audio item %s as listened", __FUNCTION__, redactPath.c_str());
197 musicdatabase.IncrementPlayCount(m_item);
198 musicdatabase.Close();
207 #endif // SAVE_FILE_STATE_H__