fixed: LINUX build errors
[xbmc:xbmc.git] / xbmc / FileSystem / FileRTV.cpp
1 /*
2  *      Copyright (C) 2005-2008 Team XBMC
3  *      http://www.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, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21
22 // FileRTV.cpp: implementation of the CFileRTV class.
23 //
24 //////////////////////////////////////////////////////////////////////
25
26 #include "FileRTV.h"
27 #include "SectionLoader.h"
28 #include "URL.h"
29 #include "utils/log.h"
30 #include <errno.h>
31 #include <sys/stat.h>
32 extern "C"
33 {
34 #include "lib/libRTV/interface.h"
35 }
36
37
38 using namespace XFILE;
39
40 //////////////////////////////////////////////////////////////////////
41 // Construction/Destruction
42 //////////////////////////////////////////////////////////////////////
43
44 CFileRTV::CFileRTV()
45 {
46   CSectionLoader::Load("LIBRTV");
47   m_filePos = 0;
48   m_fileSize = 0;
49   m_bOpened = false;
50   m_rtvd = NULL;
51 }
52
53 CFileRTV::~CFileRTV()
54 {
55   Close();
56   CSectionLoader::Unload("LIBRTV");
57 }
58
59 //*********************************************************************************************
60 bool CFileRTV::Open(const char* strHostName, const char* strFileName, int iport)
61 {
62   // Close any existing connection
63   if (m_bOpened) Close();
64
65   m_bOpened = false;
66
67   // Set up global variables.  Don't set m_filePos to 0 because we use it to SEEK!
68   m_fileSize = 0;
69   m_rtvd = NULL;
70   strcpy(m_hostName, strHostName);
71   strcpy(m_fileName, strFileName);
72   m_iport = iport;
73
74   // Allow for ReplayTVs on ports other than 80
75   CStdString strHostAndPort;
76   strHostAndPort = strHostName;
77   if (iport)
78   {
79     char buffer[10];
80     strHostAndPort += ':';
81     strHostAndPort += itoa(iport, buffer, 10);
82   }
83
84   // Get the file size of strFileName.  If size is 0 or negative, file doesn't exist so exit.
85   u64 size;
86   size = rtv_get_filesize(strHostAndPort.c_str(), strFileName);
87   if (!size)
88   {
89     CLog::Log(LOGERROR, "%s - Failed to get filesize of %s on %s", __FUNCTION__, strHostName, strFileName);
90     return false;
91   }
92   m_fileSize = size;
93
94   // Open a connection to strFileName stating at position m_filePos
95   // Store the handle to the connection in m_rtvd.  Exit if handle invalid.
96   m_rtvd = rtv_open_file(strHostAndPort.c_str(), strFileName, m_filePos);
97   if (!m_rtvd)
98   {
99     CLog::Log(LOGERROR, "%s - Failed to open %s on %s", __FUNCTION__, strHostName, strFileName);
100     return false;
101   }
102   m_bOpened = true;
103
104   CLog::Log(LOGDEBUG, "%s - Opened %s on %s, Size %llu, Position %llu", __FUNCTION__, strHostName, strFileName, m_fileSize, m_filePos);
105   return true;
106 }
107
108 bool CFileRTV::Open(const CURL& url)
109 {
110   return Open(url.GetHostName(), url.GetFileName(), url.GetPort());
111 }
112
113 bool CFileRTV::Exists(const CURL& url)
114 {
115   return true;
116 }
117
118 int CFileRTV::Stat(const CURL& url, struct stat64* buffer)
119 {
120   errno = ENOENT;
121   return -1;
122 }
123
124 //*********************************************************************************************
125 unsigned int CFileRTV::Read(void *lpBuf, int64_t uiBufSize)
126 {
127   size_t lenread;
128
129   // Don't read if no connection is open!
130   if (!m_bOpened) return 0;
131
132   // Read uiBufSize bytes from the m_rtvd connection
133   lenread = rtv_read_file(m_rtvd, (char *) lpBuf, (size_t) uiBufSize);
134
135   CLog::Log(LOGDEBUG, "%s - Requested %"PRIdS", Recieved %"PRIdS"", __FUNCTION__, (size_t)uiBufSize, lenread);
136
137   // Some extra checking so library behaves
138   if(m_filePos + lenread > m_fileSize)
139   {
140     CLog::Log(LOGWARNING, "%s - RTV library read passed filesize, returning last chunk", __FUNCTION__);
141     lenread = (size_t)(m_fileSize - m_filePos);
142     m_filePos = m_fileSize;
143     return lenread;
144   }
145
146   // Increase the file position by the number of bytes we just read
147   m_filePos += lenread;
148
149   // Return the number of bytes we just read
150   return lenread;
151 }
152
153 //*********************************************************************************************
154 void CFileRTV::Close()
155 {
156   m_bOpened = false;
157
158   // Only try to close a valid handle!
159   if (m_rtvd)
160   {
161     rtv_close_file(m_rtvd);
162   }
163   m_rtvd = NULL;
164 }
165
166 //*********************************************************************************************
167 int64_t CFileRTV::Seek(int64_t iFilePosition, int iWhence)
168 {
169   UINT64 newpos;
170
171   if (!m_bOpened) return 0;
172   switch (iWhence)
173   {
174   case SEEK_SET:
175     // cur = pos
176     newpos = iFilePosition;
177     break;
178   case SEEK_CUR:
179     // cur += pos
180     newpos = m_filePos + iFilePosition;
181     break;
182   case SEEK_END:
183     // end += pos
184     newpos = m_fileSize + iFilePosition;
185     break;
186   default:
187     return -1;
188   }
189   // Return offset from beginning
190   if (newpos > m_fileSize) newpos = m_fileSize;
191
192   // NEW CODE
193   // If the new file position is different from the old, then we must SEEK there!
194   if (m_filePos != newpos)
195   {
196     m_filePos = newpos;
197     Open(m_hostName, m_fileName, m_iport);
198   }
199
200   // OLD CODE
201   // Below is old code that may be useful again.  For some reason I'm not sure of, XBMC
202   // does a few seeks to the beginning and end of the stream before it ever starts playing.
203   // When used instead of the code above, this code seeks only after playing begins.
204   // Theoretically, this saves some time because it prevents needless re-opening of the
205   // connection to the RTV, but in practice it seems to be the same.
206   //m_filePos = newpos;
207
208   //if (m_rtvd->firstReadDone && iWhence == SEEK_SET) {
209   // Open(NULL, NULL, m_hostName, m_fileName, m_iport, true);
210   //}
211
212   // Return the new file position after the seek
213   return m_filePos;
214 }
215
216 //*********************************************************************************************
217 int64_t CFileRTV::GetLength()
218 {
219   if (!m_bOpened) return 0;
220   return m_fileSize;
221 }
222
223 //*********************************************************************************************
224 int64_t CFileRTV::GetPosition()
225 {
226   if (!m_bOpened) return 0;
227   return m_filePos;
228 }