[cosmetics] update date in GPL header
[vuplus_xbmc] / xbmc / cores / dvdplayer / DVDInputStreams / DVDInputStreamRTMP.cpp
1 /*
2  *      Copyright (C) 2005-2013 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, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #if (defined HAVE_CONFIG_H) && (!defined WIN32)
22   #include "config.h"
23 #endif
24 #ifdef _WIN32
25 #include "system.h" // just for HAS_LIBRTMP
26 #endif
27
28 #ifdef HAS_LIBRTMP
29 #include "settings/AdvancedSettings.h"
30 #include "DVDInputStreamRTMP.h"
31 #include "threads/SingleLock.h"
32 #include "utils/log.h"
33 #include "utils/Variant.h"
34
35 #include <string>
36
37 using namespace XFILE;
38 using namespace std;
39
40 static int RTMP_level=0;
41 extern "C" 
42 {
43   static void CDVDInputStreamRTMP_Log(int level, const char *fmt, va_list args)
44   {
45     char buf[2048];
46
47     if (level > RTMP_level)
48       return;
49
50     switch(level) 
51     {
52       default:
53       case RTMP_LOGCRIT:    level = LOGFATAL;   break;
54       case RTMP_LOGERROR:   level = LOGERROR;   break;
55       case RTMP_LOGWARNING: level = LOGWARNING; break;
56       case RTMP_LOGINFO:    level = LOGNOTICE;  break;
57       case RTMP_LOGDEBUG:   level = LOGINFO;    break;
58       case RTMP_LOGDEBUG2:  level = LOGDEBUG;   break;
59     }
60
61     vsnprintf(buf, sizeof(buf), fmt, args);
62     CLog::Log(level, "%s", buf);
63   }
64 }
65
66 CDVDInputStreamRTMP::CDVDInputStreamRTMP() : CDVDInputStream(DVDSTREAM_TYPE_RTMP)
67 {
68   if (m_libRTMP.Load())
69   {
70     CLog::Log(LOGINFO,"%s: Using external libRTMP",__FUNCTION__);
71     RTMP_LogLevel level;
72
73     m_libRTMP.LogSetCallback(CDVDInputStreamRTMP_Log);
74     switch (g_advancedSettings.m_logLevel)
75     {
76       case LOG_LEVEL_DEBUG_SAMBA: level = RTMP_LOGDEBUG2; break;
77       case LOG_LEVEL_DEBUG_FREEMEM:
78       case LOG_LEVEL_DEBUG: level = RTMP_LOGDEBUG; break;
79       case LOG_LEVEL_NORMAL: level = RTMP_LOGINFO; break;
80       default: level = RTMP_LOGCRIT; break;
81     }
82     m_libRTMP.LogSetLevel(level);
83     RTMP_level = level;
84     
85     m_rtmp = m_libRTMP.Alloc();
86     m_libRTMP.Init(m_rtmp);
87   }
88   else
89   {
90     m_rtmp = NULL;
91   }
92
93   m_eof = true;
94   m_bPaused = false;
95   m_sStreamPlaying = NULL;
96 }
97
98 CDVDInputStreamRTMP::~CDVDInputStreamRTMP()
99 {
100   free(m_sStreamPlaying);
101   m_sStreamPlaying = NULL;
102
103   Close();
104   m_libRTMP.Free(m_rtmp);
105   m_rtmp = NULL;
106   m_bPaused = false;
107 }
108
109 bool CDVDInputStreamRTMP::IsEOF()
110 {
111   return m_eof;
112 }
113
114 #define  SetAVal(av, cstr)  av.av_val = (char *)cstr.c_str(); av.av_len = cstr.length()
115 #undef AVC
116 #define AVC(str)  {(char *)str,sizeof(str)-1}
117
118 /* librtmp option names are slightly different */
119 static const struct {
120   const char *name;
121   AVal key;
122 } options[] = {
123   { "SWFPlayer", AVC("swfUrl") },
124   { "PageURL",   AVC("pageUrl") },
125   { "PlayPath",  AVC("playpath") },
126   { "TcUrl",     AVC("tcUrl") },
127   { "IsLive",    AVC("live") },
128   { NULL }
129 };
130
131 bool CDVDInputStreamRTMP::Open(const char* strFile, const std::string& content)
132 {
133   if (m_sStreamPlaying)
134   {
135     free(m_sStreamPlaying);
136     m_sStreamPlaying = NULL;
137   }
138
139   if (!CDVDInputStream::Open(strFile, "video/x-flv"))
140     return false;
141
142   CSingleLock lock(m_RTMPSection);
143
144   // libRTMP can and will alter strFile, so take a copy of it
145   m_sStreamPlaying = (char*)calloc(strlen(strFile)+1,sizeof(char));
146   strcpy(m_sStreamPlaying,strFile);
147
148   if (!m_libRTMP.SetupURL(m_rtmp, m_sStreamPlaying))
149     return false;
150
151   // SetOpt and SetAVal copy pointers to the value. librtmp doesn't use the values until the Connect() call,
152   // so value objects must stay allocated until then. To be extra safe, keep the values around until Close(),
153   // in case librtmp needs them again.
154   m_optionvalues.clear();
155   for (int i=0; options[i].name; i++)
156   {
157     CStdString tmp = m_item.GetProperty(options[i].name).asString();
158     if (!tmp.empty())
159     {
160       m_optionvalues.push_back(tmp);
161       AVal av_tmp;
162       SetAVal(av_tmp, m_optionvalues.back());
163       m_libRTMP.SetOpt(m_rtmp, &options[i].key, &av_tmp);
164     }
165   }
166
167   if (!m_libRTMP.Connect(m_rtmp, NULL) || !m_libRTMP.ConnectStream(m_rtmp, 0))
168     return false;
169
170   m_eof = false;
171
172   return true;
173 }
174
175 // close file and reset everything
176 void CDVDInputStreamRTMP::Close()
177 {
178   CSingleLock lock(m_RTMPSection);
179   CDVDInputStream::Close();
180
181   m_libRTMP.Close(m_rtmp);
182
183   m_optionvalues.clear();
184   m_eof = true;
185   m_bPaused = false;
186 }
187
188 int CDVDInputStreamRTMP::Read(BYTE* buf, int buf_size)
189 {
190   int i = m_libRTMP.Read(m_rtmp, (char *)buf, buf_size);
191   if (i < 0)
192     m_eof = true;
193
194   return i;
195 }
196
197 int64_t CDVDInputStreamRTMP::Seek(int64_t offset, int whence)
198 {
199   if (whence == SEEK_POSSIBLE)
200     return 0;
201   else
202     return -1;
203 }
204
205 bool CDVDInputStreamRTMP::SeekTime(int iTimeInMsec)
206 {
207   CLog::Log(LOGNOTICE, "RTMP Seek to %i requested", iTimeInMsec);
208   CSingleLock lock(m_RTMPSection);
209
210   if (m_libRTMP.SendSeek(m_rtmp, iTimeInMsec))
211     return true;
212
213   return false;
214 }
215
216 int64_t CDVDInputStreamRTMP::GetLength()
217 {
218   return -1;
219 }
220
221 bool CDVDInputStreamRTMP::Pause(double dTime)
222 {
223   CSingleLock lock(m_RTMPSection);
224
225   m_bPaused = !m_bPaused;
226   m_libRTMP.Pause(m_rtmp, m_bPaused);
227
228   return true;
229 }
230 #endif