Merge pull request #4857 from t-nelson/Gotham_13.2_backports
[vuplus_xbmc] / xbmc / filesystem / VTPFile.cpp
1 /*
2  *      Copyright (C) 2005-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 "system.h"
22 #include "VTPFile.h"
23 #include "VTPSession.h"
24 #include "utils/URIUtils.h"
25 #include "URL.h"
26 #include "utils/log.h"
27 #include "utils/StringUtils.h"
28 #include "video/VideoInfoTag.h"
29
30 using namespace XFILE;
31 using namespace std;
32
33 CVTPFile::CVTPFile()
34   : m_socket(INVALID_SOCKET)
35   , m_channel(0)
36 {
37   m_session = new CVTPSession();
38 }
39
40 CVTPFile::~CVTPFile()
41 {
42   Close();
43   delete m_session;
44 }
45 void CVTPFile::Close()
46 {
47   if(m_socket != INVALID_SOCKET)
48   {
49     m_session->AbortStreamLive();
50     closesocket(m_socket);
51   }
52
53   m_session->Close();
54   m_socket  = INVALID_SOCKET;
55 }
56
57 bool CVTPFile::Open(const CURL& url2)
58 {
59   Close();
60   CURL url(url2);
61   if(url.GetHostName() == "")
62     url.SetHostName("localhost");
63
64   if(url.GetPort() == 0)
65     url.SetPort(2004);
66
67   CStdString path(url.GetFileName());
68
69   if (StringUtils::StartsWith(path, "channels/"))
70   {
71
72     CStdString channel = path.substr(9);
73     if(!URIUtils::HasExtension(channel, ".ts"))
74     {
75       CLog::Log(LOGERROR, "%s - invalid channel url %s", __FUNCTION__, channel.c_str());
76       return false;
77     }
78     URIUtils::RemoveExtension(channel);
79
80     if(!m_session->Open(url.GetHostName(), url.GetPort()))
81       return false;
82
83     m_channel = atoi(channel.c_str());
84     m_socket  = m_session->GetStreamLive(m_channel);
85   }
86   else
87   {
88     CLog::Log(LOGERROR, "%s - invalid path specified %s", __FUNCTION__, path.c_str());
89     return false;
90   }
91
92   return true;
93 }
94
95 unsigned int CVTPFile::Read(void* buffer, int64_t size)
96 {
97   if(m_socket == INVALID_SOCKET)
98     return 0;
99
100   fd_set         set_r, set_e;
101   struct timeval tv;
102   int            res;
103
104   tv.tv_sec = 30;
105   tv.tv_usec = 0;
106
107   FD_ZERO(&set_r);
108   FD_ZERO(&set_e);
109   FD_SET(m_socket, &set_r);
110   FD_SET(m_socket, &set_e);
111   res = select(FD_SETSIZE, &set_r, NULL, &set_e, &tv);
112   if(res < 0)
113   {
114     CLog::Log(LOGERROR, "CVTPFile::Read - select failed");
115     return 0;
116   }
117   if(res == 0)
118   {
119     CLog::Log(LOGERROR, "CVTPFile::Read - timeout waiting for data");
120     return 0;
121   }
122
123   res = recv(m_socket, (char*)buffer, (size_t)size, 0);
124   if(res < 0)
125   {
126     CLog::Log(LOGERROR, "CVTPFile::Read - failed");
127     return 0;
128   }
129   if(res == 0)
130   {
131     CLog::Log(LOGERROR, "CVTPFile::Read - eof");
132     return 0;
133   }
134
135   return res;
136 }
137
138 int64_t CVTPFile::Seek(int64_t pos, int whence)
139 {
140   CLog::Log(LOGDEBUG, "CVTPFile::Seek - seek to pos %"PRId64", whence %d", pos, whence);
141   return -1;
142 }
143
144 bool CVTPFile::NextChannel(bool preview/* = false*/)
145 {
146   if(m_session == NULL)
147     return false;
148
149   int channel = m_channel;
150   while(++channel < 1000)
151   {
152     if(!m_session->CanStreamLive(channel))
153       continue;
154
155     if(m_socket != INVALID_SOCKET)
156     {
157       shutdown(m_socket, SHUT_RDWR);
158       m_session->AbortStreamLive();
159       closesocket(m_socket);
160     }
161
162     m_channel = channel;
163     m_socket  = m_session->GetStreamLive(m_channel);
164     if(m_socket != INVALID_SOCKET)
165       return true;
166   }
167   return false;
168 }
169
170 bool CVTPFile::PrevChannel(bool preview/* = false*/)
171 {
172   if(m_session == NULL)
173     return false;
174
175   int channel = m_channel;
176   while(--channel > 0)
177   {
178     if(!m_session->CanStreamLive(channel))
179       continue;
180
181     m_session->AbortStreamLive();
182
183     if(m_socket != INVALID_SOCKET)
184     {
185       shutdown(m_socket, SHUT_RDWR);
186       m_session->AbortStreamLive();
187       closesocket(m_socket);
188     }
189
190     m_channel = channel;
191     m_socket  = m_session->GetStreamLive(m_channel);
192     if(m_socket != INVALID_SOCKET)
193       return true;
194   }
195   return false;
196 }
197
198 bool CVTPFile::SelectChannel(unsigned int channel)
199 {
200   if(!m_session->CanStreamLive(channel))
201     return false;
202
203   m_session->AbortStreamLive();
204
205   if(m_socket != INVALID_SOCKET)
206   {
207     shutdown(m_socket, SHUT_RDWR);
208     m_session->AbortStreamLive();
209     closesocket(m_socket);
210   }
211
212   m_channel = channel;
213   m_socket  = m_session->GetStreamLive(m_channel);
214   if(m_socket != INVALID_SOCKET)
215     return true;
216   else
217     return false;
218 }
219
220 int CVTPFile::IoControl(EIoControl request, void* param)
221 {
222   if(request == IOCTRL_SEEK_POSSIBLE)
223     return 0;
224
225   return -1;
226 }