d223a4dc698888140b7331099c13a44b840f8eeb
[vuplus_xbmc] / xbmc / filesystem / PVRFile.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 "PVRFile.h"
22 #include "Util.h"
23 #include "cores/dvdplayer/DVDInputStreams/DVDInputStream.h"
24 #include "pvr/PVRManager.h"
25 #include "pvr/channels/PVRChannelGroupsContainer.h"
26 #include "pvr/recordings/PVRRecordings.h"
27 #include "pvr/addons/PVRClients.h"
28 #include "utils/log.h"
29 #include "utils/StringUtils.h"
30 #include "URL.h"
31
32 using namespace std;
33 using namespace XFILE;
34 using namespace PVR;
35
36 CPVRFile::CPVRFile()
37 {
38   m_isPlayRecording = false;
39   m_playingItem     = -1;
40 }
41
42 CPVRFile::~CPVRFile()
43 {
44 }
45
46 bool CPVRFile::Open(const CURL& url)
47 {
48   Close();
49
50   if (!g_PVRManager.IsStarted())
51     return false;
52
53   CStdString strURL = url.Get();
54
55   if (strURL.Left(18) == "pvr://channels/tv/" || strURL.Left(21) == "pvr://channels/radio/")
56   {
57     CFileItemPtr tag = g_PVRChannelGroups->GetByPath(strURL);
58     if (tag && tag->HasPVRChannelInfoTag())
59     {
60       if (!g_PVRManager.OpenLiveStream(*tag))
61         return false;
62
63       m_isPlayRecording = false;
64       CLog::Log(LOGDEBUG, "PVRFile - %s - playback has started on filename %s", __FUNCTION__, strURL.c_str());
65     }
66     else
67     {
68       CLog::Log(LOGERROR, "PVRFile - %s - channel not found with filename %s", __FUNCTION__, strURL.c_str());
69       return false;
70     }
71   }
72   else if (strURL.Left(17) == "pvr://recordings/")
73   {
74     CFileItemPtr tag = g_PVRRecordings->GetByPath(strURL);
75     if (tag && tag->HasPVRRecordingInfoTag())
76     {
77       if (!g_PVRManager.OpenRecordedStream(*tag->GetPVRRecordingInfoTag()))
78         return false;
79
80       m_isPlayRecording = true;
81       CLog::Log(LOGDEBUG, "%s - Recording has started on filename %s", __FUNCTION__, strURL.c_str());
82     }
83     else
84     {
85       CLog::Log(LOGERROR, "PVRFile - Recording not found with filename %s", strURL.c_str());
86       return false;
87     }
88   }
89   else
90   {
91     CLog::Log(LOGERROR, "%s - invalid path specified %s", __FUNCTION__, strURL.c_str());
92     return false;
93   }
94
95   return true;
96 }
97
98 void CPVRFile::Close()
99 {
100   g_PVRManager.CloseStream();
101 }
102
103 unsigned int CPVRFile::Read(void* buffer, int64_t size)
104 {
105   return g_PVRManager.IsStarted() ? g_PVRClients->ReadStream((BYTE*)buffer, size) : 0;
106 }
107
108 int64_t CPVRFile::GetLength()
109 {
110   return g_PVRManager.IsStarted() ? g_PVRClients->GetStreamLength() : 0;
111 }
112
113 int64_t CPVRFile::Seek(int64_t pos, int whence)
114 {
115   return g_PVRManager.IsStarted() ? g_PVRClients->SeekStream(pos, whence) : 0;
116 }
117
118 int64_t CPVRFile::GetPosition()
119 {
120   return g_PVRManager.IsStarted() ? g_PVRClients->GetStreamPosition() : 0;
121 }
122
123 int CPVRFile::GetTotalTime()
124 {
125   // for recordings leave this to demuxer
126   return m_isPlayRecording ? 0 : g_PVRManager.GetTotalTime();
127 }
128
129 int CPVRFile::GetStartTime()
130 {
131   return g_PVRManager.GetStartTime();
132 }
133
134 bool CPVRFile::NextChannel(bool preview/* = false*/)
135 {
136   unsigned int newchannel;
137
138   if (m_isPlayRecording)
139   {
140     /* We are inside a recording, skip channelswitch */
141     return true;
142   }
143
144   /* Do channel switch and save new channel number, it is not always
145    * increased by one in a case if next channel is encrypted or we
146    * on the beginning or end of the channel list!
147    */
148   if (g_PVRManager.ChannelUp(&newchannel, preview))
149   {
150     m_playingItem = newchannel;
151     return true;
152   }
153   else
154   {
155     return false;
156   }
157 }
158
159 bool CPVRFile::PrevChannel(bool preview/* = false*/)
160 {
161   unsigned int newchannel;
162
163   if (m_isPlayRecording)
164   {
165     /* We are inside a recording, skip channelswitch */
166     return true;
167   }
168
169   /* Do channel switch and save new channel number, it is not always
170    * increased by one in a case if next channel is encrypted or we
171    * on the beginning or end of the channel list!
172    */
173   if (g_PVRManager.ChannelDown(&newchannel, preview))
174   {
175     m_playingItem = newchannel;
176     return true;
177   }
178   else
179   {
180     return false;
181   }
182 }
183
184 bool CPVRFile::SelectChannel(unsigned int channel)
185 {
186   if (m_isPlayRecording)
187   {
188     /* We are inside a recording, skip channelswitch */
189     /** TODO:
190      ** Add support for cutting keys (functions becomes the numeric keys as integer)
191      **/
192     return true;
193   }
194
195   if (g_PVRManager.ChannelSwitch(channel))
196   {
197     m_playingItem = channel;
198     return true;
199   }
200   else
201   {
202     return false;
203   }
204 }
205
206 bool CPVRFile::UpdateItem(CFileItem& item)
207 {
208   return g_PVRManager.UpdateItem(item);
209 }
210
211 CStdString CPVRFile::TranslatePVRFilename(const CStdString& pathFile)
212 {
213   if (!g_PVRManager.IsStarted())
214     return StringUtils::EmptyString;
215
216   CStdString FileName = pathFile;
217   if (FileName.substr(0, 14) == "pvr://channels")
218   {
219     CFileItemPtr channel = g_PVRChannelGroups->GetByPath(FileName);
220     if (channel && channel->HasPVRChannelInfoTag())
221     {
222       CStdString stream = channel->GetPVRChannelInfoTag()->StreamURL();
223       if(!stream.IsEmpty())
224       {
225         if (stream.compare(6, 7, "stream/") == 0)
226         {
227           // pvr://stream
228           // This function was added to retrieve the stream URL for this item
229           // Is is used for the MediaPortal (ffmpeg) PVR addon
230           // see PVRManager.cpp
231           return g_PVRClients->GetStreamURL(*channel->GetPVRChannelInfoTag());
232         }
233         else
234         {
235           return stream;
236         }
237       }
238     }
239   }
240   return FileName;
241 }
242
243 bool CPVRFile::CanRecord()
244 {
245   if (m_isPlayRecording || !g_PVRManager.IsStarted())
246     return false;
247
248   return g_PVRClients->CanRecordInstantly();
249 }
250
251 bool CPVRFile::IsRecording()
252 {
253   return g_PVRManager.IsStarted() && g_PVRClients->IsRecordingOnPlayingChannel();
254 }
255
256 bool CPVRFile::Record(bool bOnOff)
257 {
258   return g_PVRManager.StartRecordingOnPlayingChannel(bOnOff);
259 }
260
261 bool CPVRFile::Delete(const CURL& url)
262 {
263   if (!g_PVRManager.IsStarted())
264     return false;
265
266   CStdString path(url.GetFileName());
267   if (path.Left(11) == "recordings/" && path[path.size()-1] != '/')
268   {
269     CStdString strURL = url.Get();
270     CFileItemPtr tag = g_PVRRecordings->GetByPath(strURL);
271     if (tag && tag->HasPVRRecordingInfoTag())
272       return tag->GetPVRRecordingInfoTag()->Delete();
273   }
274   return false;
275 }
276
277 bool CPVRFile::Rename(const CURL& url, const CURL& urlnew)
278 {
279   if (!g_PVRManager.IsStarted())
280     return false;
281
282   CStdString path(url.GetFileName());
283   CStdString newname(urlnew.GetFileName());
284
285   size_t found = newname.find_last_of("/");
286   if (found != CStdString::npos)
287     newname = newname.substr(found+1);
288
289   if (path.Left(11) == "recordings/" && path[path.size()-1] != '/')
290   {
291     CStdString strURL = url.Get();
292     CFileItemPtr tag = g_PVRRecordings->GetByPath(strURL);
293     if (tag && tag->HasPVRRecordingInfoTag())
294       return tag->GetPVRRecordingInfoTag()->Rename(newname);
295   }
296   return false;
297 }
298
299 bool CPVRFile::Exists(const CURL& url)
300 {
301   return g_PVRManager.IsStarted() &&
302       g_PVRRecordings->GetByPath(url.Get())->HasPVRRecordingInfoTag();
303 }
304
305 int CPVRFile::IoControl(EIoControl request, void *param)
306 {
307   if (request == IOCTRL_SEEK_POSSIBLE)
308   {
309     if (!g_PVRManager.IsStarted())
310       return 0;
311     else if (g_PVRClients->CanSeekStream())
312       return 1;
313     else
314       return 0;
315   }
316
317   return -1;
318 }