Merge pull request #4676 from jmarshallnz/dont_set_scraper_on_tvshow_on_nfo
[vuplus_xbmc] / xbmc / utils / SaveFileStateJob.h
1 /*
2  *      Copyright (C) 2010-2013 Team XBMC
3  *      http://xbmc.org
4  *
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)
8  *  any later version.
9  *
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.
14  *
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/>.
18  *
19  */
20 #ifndef SAVE_FILE_STATE_H__
21 #define SAVE_FILE_STATE_H__
22
23 #include "Job.h"
24 #include "FileItem.h"
25 #include "pvr/PVRManager.h"
26 #include "pvr/recordings/PVRRecordings.h"
27 #include "settings/MediaSettings.h"
28 #include "network/upnp/UPnP.h"
29
30 class CSaveFileStateJob : public CJob
31 {
32   CFileItem m_item;
33   CFileItem m_item_discstack;
34   CBookmark m_bookmark;
35   bool      m_updatePlayCount;
36 public:
37                 CSaveFileStateJob(const CFileItem& item,
38                                   const CFileItem& item_discstack,
39                                   const CBookmark& bookmark,
40                                   bool updatePlayCount)
41                   : m_item(item),
42                     m_item_discstack(item_discstack),
43                     m_bookmark(bookmark),
44                     m_updatePlayCount(updatePlayCount) {}
45   virtual       ~CSaveFileStateJob() {}
46   virtual bool  DoWork();
47 };
48
49 bool CSaveFileStateJob::DoWork()
50 {
51   CStdString progressTrackingFile = m_item.GetPath();
52
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"))
56   {
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;
61   }
62
63   if (progressTrackingFile != "")
64   {
65 #ifdef HAS_UPNP
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)) {
69         return true;
70     }
71 #endif
72     if (m_item.IsVideo())
73     {
74       std::string redactPath = CURL::GetRedacted(progressTrackingFile);
75       CLog::Log(LOGDEBUG, "%s - Saving file state for video item %s", __FUNCTION__, redactPath.c_str());
76
77       CVideoDatabase videodatabase;
78       if (!videodatabase.Open())
79       {
80         CLog::Log(LOGWARNING, "%s - Unable to open video database. Can not save file state!", __FUNCTION__);
81       }
82       else
83       {
84         bool updateListing = false;
85         // No resume & watched status for livetv
86         if (!m_item.IsLiveTV())
87         {
88           if (m_updatePlayCount)
89           {
90             CLog::Log(LOGDEBUG, "%s - Marking video item %s as watched", __FUNCTION__, redactPath.c_str());
91
92             // consider this item as played
93             videodatabase.IncrementPlayCount(m_item);
94             m_item.GetVideoInfoTag()->m_playCount++;
95
96             // PVR: Set recording's play count on the backend (if supported)
97             if (m_item.HasPVRRecordingInfoTag())
98               m_item.GetPVRRecordingInfoTag()->IncrementPlayCount();
99
100             m_item.SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, true);
101             updateListing = true;
102           }
103           else
104             videodatabase.UpdateLastPlayed(m_item);
105
106           if (!m_item.HasVideoInfoTag() || m_item.GetVideoInfoTag()->m_resumePoint.timeInSeconds != m_bookmark.timeInSeconds)
107           {
108             if (m_bookmark.timeInSeconds <= 0.0f)
109               videodatabase.ClearBookMarksOfFile(progressTrackingFile, CBookmark::RESUME);
110             else
111               videodatabase.AddBookMarkToFile(progressTrackingFile, m_bookmark, CBookmark::RESUME);
112             if (m_item.HasVideoInfoTag())
113               m_item.GetVideoInfoTag()->m_resumePoint = m_bookmark;
114
115             // PVR: Set/clear recording's resume bookmark on the backend (if supported)
116             if (m_item.HasPVRRecordingInfoTag())
117             {
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;
121             }
122
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)
126             {
127               CVariant data;
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);
131             }
132
133             updateListing = true;
134           }
135         }
136
137         if (CMediaSettings::Get().GetCurrentVideoSettings() != CMediaSettings::Get().GetDefaultVideoSettings())
138         {
139           videodatabase.SetVideoSettings(progressTrackingFile, CMediaSettings::Get().GetCurrentVideoSettings());
140         }
141
142         if (m_item.HasVideoInfoTag() && m_item.GetVideoInfoTag()->HasStreamDetails())
143         {
144           CFileItem dbItem(m_item);
145
146           // Check whether the item's db streamdetails need updating
147           if (!videodatabase.GetStreamDetails(dbItem) || dbItem.GetVideoInfoTag()->m_streamDetails != m_item.GetVideoInfoTag()->m_streamDetails)
148           {
149             videodatabase.SetStreamDetailsForFile(m_item.GetVideoInfoTag()->m_streamDetails, progressTrackingFile);
150             updateListing = true;
151           }
152         }
153
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"))
156         {
157           m_item = m_item_discstack; // as of now, the item is replaced by the discstack item
158           videodatabase.GetResumePoint(*m_item.GetVideoInfoTag());
159         }
160         videodatabase.Close();
161
162         if (updateListing)
163         {
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);
170         }
171       }
172     }
173
174     if (m_item.IsAudio())
175     {
176       std::string redactPath = CURL::GetRedacted(progressTrackingFile);
177       CLog::Log(LOGDEBUG, "%s - Saving file state for audio item %s", __FUNCTION__, redactPath.c_str());
178
179       if (m_updatePlayCount)
180       {
181 #if 0
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())
185 #endif
186         {
187           CMusicDatabase musicdatabase;
188           if (!musicdatabase.Open())
189           {
190             CLog::Log(LOGWARNING, "%s - Unable to open music database. Can not save file state!", __FUNCTION__);
191           }
192           else
193           {
194             // consider this item as played
195             CLog::Log(LOGDEBUG, "%s - Marking audio item %s as listened", __FUNCTION__, redactPath.c_str());
196
197             musicdatabase.IncrementPlayCount(m_item);
198             musicdatabase.Close();
199           }
200         }
201       }
202     }
203   }
204   return true;
205 }
206
207 #endif // SAVE_FILE_STATE_H__
208