summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/SaveFileStateJob.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/utils/SaveFileStateJob.cpp')
-rw-r--r--xbmc/utils/SaveFileStateJob.cpp211
1 files changed, 211 insertions, 0 deletions
diff --git a/xbmc/utils/SaveFileStateJob.cpp b/xbmc/utils/SaveFileStateJob.cpp
new file mode 100644
index 0000000..26b7b5c
--- /dev/null
+++ b/xbmc/utils/SaveFileStateJob.cpp
@@ -0,0 +1,211 @@
1/*
2 * Copyright (C) 2010-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9#include "SaveFileStateJob.h"
10
11#include "Application.h"
12#include "FileItem.h"
13#include "GUIUserMessages.h"
14#include "ServiceBroker.h"
15#include "StringUtils.h"
16#include "URIUtils.h"
17#include "URL.h"
18#include "Util.h"
19#include "guilib/GUIComponent.h"
20#include "guilib/GUIMessage.h"
21#include "guilib/GUIWindowManager.h"
22#include "interfaces/AnnouncementManager.h"
23#include "log.h"
24#include "music/MusicDatabase.h"
25#include "music/tags/MusicInfoTag.h"
26#include "network/upnp/UPnP.h"
27#include "utils/Variant.h"
28#include "video/Bookmark.h"
29#include "video/VideoDatabase.h"
30
31void CSaveFileState::DoWork(CFileItem& item,
32 CBookmark& bookmark,
33 bool updatePlayCount)
34{
35 std::string progressTrackingFile = item.GetPath();
36
37 if (item.HasVideoInfoTag() && StringUtils::StartsWith(item.GetVideoInfoTag()->m_strFileNameAndPath, "removable://"))
38 progressTrackingFile = item.GetVideoInfoTag()->m_strFileNameAndPath; // this variable contains removable:// suffixed by disc label+uniqueid or is empty if label not uniquely identified
39 else if (item.HasVideoInfoTag() && item.IsVideoDb())
40 progressTrackingFile = item.GetVideoInfoTag()->m_strFileNameAndPath; // we need the file url of the video db item to create the bookmark
41 else if (item.HasProperty("original_listitem_url"))
42 {
43 // only use original_listitem_url for Python, UPnP and Bluray sources
44 std::string original = item.GetProperty("original_listitem_url").asString();
45 if (URIUtils::IsPlugin(original) || URIUtils::IsUPnP(original) || URIUtils::IsBluray(item.GetPath()))
46 progressTrackingFile = original;
47 }
48
49 if (!progressTrackingFile.empty())
50 {
51#ifdef HAS_UPNP
52 // checks if UPnP server of this file is available and supports updating
53 if (URIUtils::IsUPnP(progressTrackingFile)
54 && UPNP::CUPnP::SaveFileState(item, bookmark, updatePlayCount))
55 {
56 return;
57 }
58#endif
59 if (item.IsVideo())
60 {
61 std::string redactPath = CURL::GetRedacted(progressTrackingFile);
62 CLog::Log(LOGDEBUG, "%s - Saving file state for video item %s", __FUNCTION__, redactPath.c_str());
63
64 CVideoDatabase videodatabase;
65 if (!videodatabase.Open())
66 {
67 CLog::Log(LOGWARNING, "%s - Unable to open video database. Can not save file state!", __FUNCTION__);
68 }
69 else
70 {
71 if (URIUtils::IsPlugin(progressTrackingFile) && !(item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_iDbId >= 0))
72 {
73 // FileItem from plugin can lack information, make sure all needed fields are set
74 CVideoInfoTag *tag = item.GetVideoInfoTag();
75 CStreamDetails streams = tag->m_streamDetails;
76 if (videodatabase.LoadVideoInfo(progressTrackingFile, *tag))
77 {
78 item.SetPath(progressTrackingFile);
79 item.ClearProperty("original_listitem_url");
80 tag->m_streamDetails = streams;
81 }
82 }
83
84 bool updateListing = false;
85 // No resume & watched status for livetv
86 if (!item.IsLiveTV())
87 {
88 if (updatePlayCount)
89 {
90 // no watched for not yet finished pvr recordings
91 if (!item.IsInProgressPVRRecording())
92 {
93 CLog::Log(LOGDEBUG, "%s - Marking video item %s as watched", __FUNCTION__, redactPath.c_str());
94
95 // consider this item as played
96 videodatabase.IncrementPlayCount(item);
97 item.GetVideoInfoTag()->IncrementPlayCount();
98
99 item.SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, true);
100 updateListing = true;
101
102 if (item.HasVideoInfoTag())
103 {
104 CVariant data;
105 data["id"] = item.GetVideoInfoTag()->m_iDbId;
106 data["type"] = item.GetVideoInfoTag()->m_type;
107 CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::VideoLibrary, "xbmc", "OnUpdate", data);
108 }
109 }
110 }
111 else
112 videodatabase.UpdateLastPlayed(item);
113
114 if (!item.HasVideoInfoTag() ||
115 item.GetVideoInfoTag()->GetResumePoint().timeInSeconds != bookmark.timeInSeconds)
116 {
117 if (bookmark.timeInSeconds <= 0.0f)
118 videodatabase.ClearBookMarksOfFile(progressTrackingFile, CBookmark::RESUME);
119 else
120 videodatabase.AddBookMarkToFile(progressTrackingFile, bookmark, CBookmark::RESUME);
121 if (item.HasVideoInfoTag())
122 item.GetVideoInfoTag()->SetResumePoint(bookmark);
123
124 // UPnP announce resume point changes to clients
125 // however not if playcount is modified as that already announces
126 if (item.HasVideoInfoTag() && !updatePlayCount)
127 {
128 CVariant data;
129 data["id"] = item.GetVideoInfoTag()->m_iDbId;
130 data["type"] = item.GetVideoInfoTag()->m_type;
131 CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::VideoLibrary, "xbmc", "OnUpdate", data);
132 }
133
134 updateListing = true;
135 }
136 }
137
138 if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->HasStreamDetails())
139 {
140 CFileItem dbItem(item);
141
142 // Check whether the item's db streamdetails need updating
143 if (!videodatabase.GetStreamDetails(dbItem) ||
144 dbItem.GetVideoInfoTag()->m_streamDetails != item.GetVideoInfoTag()->m_streamDetails)
145 {
146 videodatabase.SetStreamDetailsForFile(item.GetVideoInfoTag()->m_streamDetails, progressTrackingFile);
147 updateListing = true;
148 }
149 }
150
151 // Could be part of an ISO stack. In this case the bookmark is saved onto the part.
152 // In order to properly update the list, we need to refresh the stack's resume point
153 CApplicationStackHelper& stackHelper = g_application.GetAppStackHelper();
154 if (stackHelper.HasRegisteredStack(item) && stackHelper.GetRegisteredStackTotalTimeMs(item) == 0)
155 videodatabase.GetResumePoint(*(stackHelper.GetRegisteredStack(item)->GetVideoInfoTag()));
156
157 videodatabase.Close();
158
159 if (updateListing)
160 {
161 CUtil::DeleteVideoDatabaseDirectoryCache();
162 CFileItemPtr msgItem(new CFileItem(item));
163 if (item.HasProperty("original_listitem_url"))
164 msgItem->SetPath(item.GetProperty("original_listitem_url").asString());
165 CGUIMessage message(GUI_MSG_NOTIFY_ALL, CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow(), 0, GUI_MSG_UPDATE_ITEM, 0, msgItem);
166 CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(message);
167 }
168 }
169 }
170
171 if (item.IsAudio())
172 {
173 std::string redactPath = CURL::GetRedacted(progressTrackingFile);
174 CLog::Log(LOGDEBUG, "%s - Saving file state for audio item %s", __FUNCTION__, redactPath.c_str());
175
176 CMusicDatabase musicdatabase;
177 if (updatePlayCount)
178 {
179 if (!musicdatabase.Open())
180 {
181 CLog::Log(LOGWARNING, "%s - Unable to open music database. Can not save file state!", __FUNCTION__);
182 }
183 else
184 {
185 // consider this item as played
186 CLog::Log(LOGDEBUG, "%s - Marking audio item %s as listened", __FUNCTION__, redactPath.c_str());
187
188 musicdatabase.IncrementPlayCount(item);
189 musicdatabase.Close();
190
191 // UPnP announce resume point changes to clients
192 // however not if playcount is modified as that already announces
193 if (item.IsMusicDb())
194 {
195 CVariant data;
196 data["id"] = item.GetMusicInfoTag()->GetDatabaseId();
197 data["type"] = item.GetMusicInfoTag()->GetType();
198 CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::AudioLibrary, "xbmc", "OnUpdate", data);
199 }
200 }
201 }
202
203 if (item.IsAudioBook())
204 {
205 musicdatabase.Open();
206 musicdatabase.SetResumeBookmarkForAudioBook(item, item.m_lStartOffset + CUtil::ConvertSecsToMilliSecs(bookmark.timeInSeconds));
207 musicdatabase.Close();
208 }
209 }
210 }
211}