ae53c3a6e5350ab1a3e7329076cc56275314c270
[vuplus_xbmc] / xbmc / pvr / recordings / PVRRecording.cpp
1 /*
2  *      Copyright (C) 2012-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
21 #include "dialogs/GUIDialogOK.h"
22 #include "pvr/PVRManager.h"
23 #include "settings/AdvancedSettings.h"
24 #include "PVRRecordings.h"
25 #include "pvr/addons/PVRClients.h"
26 #include "utils/StringUtils.h"
27 #include "utils/RegExp.h"
28 #include "utils/StringUtils.h"
29 #include "video/VideoDatabase.h"
30
31 #include "epg/Epg.h"
32
33 using namespace PVR;
34 using namespace EPG;
35
36 CPVRRecording::CPVRRecording()
37 {
38   Reset();
39 }
40
41 CPVRRecording::CPVRRecording(const PVR_RECORDING &recording, unsigned int iClientId)
42 {
43   Reset();
44
45   m_strRecordingId                 = recording.strRecordingId;
46   m_strTitle                       = recording.strTitle;
47   m_iClientId                      = iClientId;
48   m_recordingTime                  = recording.recordingTime + g_advancedSettings.m_iPVRTimeCorrection;
49   m_duration                       = CDateTimeSpan(0, 0, recording.iDuration / 60, recording.iDuration % 60);
50   m_iPriority                      = recording.iPriority;
51   m_iLifetime                      = recording.iLifetime;
52   m_strDirectory                   = recording.strDirectory;
53   m_strPlot                        = recording.strPlot;
54   m_strPlotOutline                 = recording.strPlotOutline;
55   m_strStreamURL                   = recording.strStreamURL;
56   m_strChannelName                 = recording.strChannelName;
57   m_genre                          = StringUtils::Split(CEpg::ConvertGenreIdToString(recording.iGenreType, recording.iGenreSubType), g_advancedSettings.m_videoItemSeparator);
58   m_playCount                      = recording.iPlayCount;
59   m_resumePoint.timeInSeconds      = recording.iLastPlayedPosition;
60   m_resumePoint.totalTimeInSeconds = recording.iDuration;
61   m_strIconPath                    = recording.strIconPath;
62   m_strThumbnailPath               = recording.strThumbnailPath;
63   m_strFanartPath                  = recording.strFanartPath;
64 }
65
66 bool CPVRRecording::operator ==(const CPVRRecording& right) const
67 {
68   return (this == &right) ||
69       (m_strRecordingId     == right.m_strRecordingId &&
70        m_iClientId          == right.m_iClientId &&
71        m_strChannelName     == right.m_strChannelName &&
72        m_recordingTime      == right.m_recordingTime &&
73        m_duration           == right.m_duration &&
74        m_strPlotOutline     == right.m_strPlotOutline &&
75        m_strPlot            == right.m_strPlot &&
76        m_strStreamURL       == right.m_strStreamURL &&
77        m_iPriority          == right.m_iPriority &&
78        m_iLifetime          == right.m_iLifetime &&
79        m_strDirectory       == right.m_strDirectory &&
80        m_strFileNameAndPath == right.m_strFileNameAndPath &&
81        m_strTitle           == right.m_strTitle &&
82        m_strIconPath        == right.m_strIconPath &&
83        m_strThumbnailPath   == right.m_strThumbnailPath &&
84        m_strFanartPath      == right.m_strFanartPath);
85 }
86
87 bool CPVRRecording::operator !=(const CPVRRecording& right) const
88 {
89   return !(*this == right);
90 }
91
92 void CPVRRecording::Reset(void)
93 {
94   m_strRecordingId     = StringUtils::EmptyString;
95   m_iClientId          = 0;
96   m_strChannelName     = StringUtils::EmptyString;
97   m_strDirectory       = StringUtils::EmptyString;
98   m_strStreamURL       = StringUtils::EmptyString;
99   m_iPriority          = -1;
100   m_iLifetime          = -1;
101   m_strFileNameAndPath = StringUtils::EmptyString;
102   m_strIconPath        = StringUtils::EmptyString;
103   m_strThumbnailPath   = StringUtils::EmptyString;
104   m_strFanartPath      = StringUtils::EmptyString;
105   m_bGotMetaData       = false;
106
107   m_recordingTime.Reset();
108   CVideoInfoTag::Reset();
109 }
110
111 int CPVRRecording::GetDuration() const
112 {
113   return (m_duration.GetDays() * 60*60*24 +
114       m_duration.GetHours() * 60*60 +
115       m_duration.GetMinutes() * 60 +
116       m_duration.GetSeconds());
117 }
118
119 bool CPVRRecording::Delete(void)
120 {
121   PVR_ERROR error = g_PVRClients->DeleteRecording(*this);
122   if (error != PVR_ERROR_NO_ERROR)
123   {
124     DisplayError(error);
125     return false;
126   }
127
128   return true;
129 }
130
131 bool CPVRRecording::Rename(const CStdString &strNewName)
132 {
133   m_strTitle.Format("%s", strNewName);
134   PVR_ERROR error = g_PVRClients->RenameRecording(*this);
135   if (error != PVR_ERROR_NO_ERROR)
136   {
137     DisplayError(error);
138     return false;
139   }
140
141   return true;
142 }
143
144 bool CPVRRecording::SetPlayCount(int count)
145 {
146   PVR_ERROR error;
147   m_playCount = count;
148   if (g_PVRClients->SupportsRecordingPlayCount(m_iClientId) &&
149       !g_PVRClients->SetRecordingPlayCount(*this, count, &error))
150   {
151     DisplayError(error);
152     return false;
153   }
154
155   return true;
156 }
157
158 void CPVRRecording::UpdateMetadata(void)
159 {
160   CVideoDatabase db;
161
162   if (!g_PVRClients->SupportsRecordingPlayCount(m_iClientId))
163   {
164     if (!m_bGotMetaData && db.Open())
165     {
166       CFileItem pFileItem(*this);
167       m_playCount = db.GetPlayCount(pFileItem);
168     }
169   }
170
171   if (!g_PVRClients->SupportsLastPlayedPosition(m_iClientId))
172   {
173     if (!m_bGotMetaData && db.Open())
174       db.GetResumeBookMark(m_strFileNameAndPath, m_resumePoint);
175   }
176
177   m_bGotMetaData = true;
178 }
179
180 bool CPVRRecording::IncrementPlayCount()
181 {
182   return SetPlayCount(m_playCount + 1);
183 }
184
185 bool CPVRRecording::SetLastPlayedPosition(int lastplayedposition)
186 {
187   PVR_ERROR error;
188
189   CBookmark bookmark;
190   bookmark.timeInSeconds = lastplayedposition;
191   bookmark.totalTimeInSeconds = (double)GetDuration();
192   m_resumePoint = bookmark;
193
194   if (g_PVRClients->SupportsLastPlayedPosition(m_iClientId) &&
195       !g_PVRClients->SetRecordingLastPlayedPosition(*this, lastplayedposition, &error))
196   {
197     DisplayError(error);
198     return false;
199   }
200   return true;
201 }
202
203 int CPVRRecording::GetLastPlayedPosition() const
204 {
205   int rc = -1;
206   if (g_PVRClients->SupportsLastPlayedPosition(m_iClientId))
207   {
208     rc = g_PVRClients->GetRecordingLastPlayedPosition(*this);
209     if (rc < 0)
210       DisplayError(PVR_ERROR_SERVER_ERROR);
211   }
212   return rc;
213 }
214
215 std::vector<PVR_EDL_ENTRY> CPVRRecording::GetEdl() const
216 {
217   if (g_PVRClients->SupportsRecordingEdl(m_iClientId))
218   {
219     return g_PVRClients->GetRecordingEdl(*this);
220   }
221   return std::vector<PVR_EDL_ENTRY>();
222 }
223
224 void CPVRRecording::DisplayError(PVR_ERROR err) const
225 {
226   if (err == PVR_ERROR_SERVER_ERROR)
227     CGUIDialogOK::ShowAndGetInput(19033,19111,19110,0); /* print info dialog "Server error!" */
228   else if (err == PVR_ERROR_REJECTED)
229     CGUIDialogOK::ShowAndGetInput(19033,19068,19110,0); /* print info dialog "Couldn't delete recording!" */
230   else
231     CGUIDialogOK::ShowAndGetInput(19033,19147,19110,0); /* print info dialog "Unknown error!" */
232
233   return;
234 }
235
236 void CPVRRecording::Update(const CPVRRecording &tag)
237 {
238   m_strRecordingId    = tag.m_strRecordingId;
239   m_iClientId         = tag.m_iClientId;
240   m_strTitle          = tag.m_strTitle;
241   m_recordingTime     = tag.m_recordingTime;
242   m_duration          = tag.m_duration;
243   m_iPriority         = tag.m_iPriority;
244   m_iLifetime         = tag.m_iLifetime;
245   m_strDirectory      = tag.m_strDirectory;
246   m_strPlot           = tag.m_strPlot;
247   m_strPlotOutline    = tag.m_strPlotOutline;
248   m_strStreamURL      = tag.m_strStreamURL;
249   m_strChannelName    = tag.m_strChannelName;
250   m_genre             = tag.m_genre;
251   m_strIconPath       = tag.m_strIconPath;
252   m_strThumbnailPath  = tag.m_strThumbnailPath;
253   m_strFanartPath     = tag.m_strFanartPath;
254
255   if (g_PVRClients->SupportsRecordingPlayCount(m_iClientId))
256     m_playCount       = tag.m_playCount;
257
258   if (g_PVRClients->SupportsLastPlayedPosition(m_iClientId))
259   {
260     m_resumePoint.timeInSeconds = tag.m_resumePoint.timeInSeconds;
261     m_resumePoint.totalTimeInSeconds = tag.m_resumePoint.totalTimeInSeconds;
262   }
263
264   CStdString strShow;
265   strShow.Format("%s - ", g_localizeStrings.Get(20364).c_str());
266   if (m_strPlotOutline.Left(strShow.size()).Equals(strShow))
267   {
268     CStdString strEpisode = m_strPlotOutline;
269     CStdString strTitle = m_strDirectory;
270     
271     int pos = strTitle.ReverseFind('/');
272     strTitle.erase(0, pos + 1);
273     strEpisode.erase(0, strShow.size());
274     m_strTitle.Format("%s - %s", strTitle.c_str(), strEpisode);
275     pos = strEpisode.Find('-');
276     strEpisode.erase(0, pos + 2);
277     m_strPlotOutline = strEpisode;
278   }
279   UpdatePath();
280 }
281
282 void CPVRRecording::UpdatePath(void)
283 {
284   if (!m_strStreamURL.IsEmpty())
285   {
286     m_strFileNameAndPath = m_strStreamURL;
287   }
288   else
289   {
290     CStdString strTitle(m_strTitle);
291     CStdString strDatetime(m_recordingTime.GetAsSaveString());
292     CStdString strDirectory;
293     CStdString strChannel;
294     strTitle.Replace('/',' ');
295
296     if (!m_strDirectory.IsEmpty())
297       strDirectory.Format("%s/", m_strDirectory.c_str());
298     if (!m_strChannelName.IsEmpty())
299       strChannel.Format(" (%s)", m_strChannelName.c_str());
300     m_strFileNameAndPath.Format("pvr://recordings/%s%s, TV%s, %s.pvr", strDirectory.c_str(), strTitle.c_str(), strChannel.c_str(), strDatetime.c_str());
301   }
302 }
303
304 const CDateTime &CPVRRecording::RecordingTimeAsLocalTime(void) const
305 {
306   static CDateTime tmp;
307   tmp.SetFromUTCDateTime(m_recordingTime);
308
309   return tmp;
310 }
311
312 CStdString CPVRRecording::GetTitleFromURL(const CStdString &url)
313 {
314   CRegExp reg(true);
315   if (reg.RegComp("pvr://recordings/(.*/)*(.*), TV( \\(.*\\))?, "
316       "(19[0-9][0-9]|20[0-9][0-9])[0-9][0-9][0-9][0-9]_[0-9][0-9][0-9][0-9][0-9][0-9].pvr"))
317   {
318     if (reg.RegFind(url.c_str()) >= 0)
319       return reg.GetMatch(2);
320   }
321   return StringUtils::EmptyString;
322 }
323
324 void CPVRRecording::CopyClientInfo(CVideoInfoTag *target) const
325 {
326   if (!target)
327     return;
328
329   target->m_playCount   = m_playCount;
330   target->m_resumePoint = m_resumePoint;
331 }