PageRenderTime 31ms CodeModel.GetById 12ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamHTSP.cpp

http://github.com/xbmc/xbmc
C++ | 275 lines | 207 code | 47 blank | 21 comment | 52 complexity | 73cf40718dcc9eae116ec1392eea80b1 MD5 | raw file
  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 "DVDInputStreamHTSP.h"
 22#include "URL.h"
 23#include "FileItem.h"
 24#include "utils/log.h"
 25#include <limits.h>
 26
 27extern "C" {
 28#include "lib/libhts/net.h"
 29#include "lib/libhts/htsmsg.h"
 30#include "lib/libhts/htsmsg_binary.h"
 31#include "lib/libhts/sha1.h"
 32}
 33
 34using namespace std;
 35using namespace HTSP;
 36
 37
 38
 39htsmsg_t* CDVDInputStreamHTSP::ReadStream()
 40{
 41  htsmsg_t* msg;
 42
 43  /* after anything has started reading, *
 44   * we can guarantee a new stream       */
 45  m_startup = false;
 46
 47  while((msg = m_session.ReadMessage(1000)))
 48  {
 49    const char* method;
 50    if((method = htsmsg_get_str(msg, "method")) == NULL)
 51      return msg;
 52
 53    if     (strstr(method, "channelAdd"))
 54      CHTSPSession::ParseChannelUpdate(msg, m_channels);
 55    else if(strstr(method, "channelUpdate"))
 56      CHTSPSession::ParseChannelUpdate(msg, m_channels);
 57    else if(strstr(method, "channelRemove"))
 58      CHTSPSession::ParseChannelRemove(msg, m_channels);
 59
 60    uint32_t subs;
 61    if(htsmsg_get_u32(msg, "subscriptionId", &subs) || subs != m_subs)
 62    {
 63      htsmsg_destroy(msg);
 64      continue;
 65    }
 66
 67    return msg;
 68  }
 69  return NULL;
 70}
 71
 72CDVDInputStreamHTSP::CDVDInputStreamHTSP()
 73  : CDVDInputStream(DVDSTREAM_TYPE_HTSP)
 74  , m_subs(0)
 75  , m_startup(false)
 76  , m_channel(0)
 77  , m_tag(0)
 78{
 79}
 80
 81CDVDInputStreamHTSP::~CDVDInputStreamHTSP()
 82{
 83  Close();
 84}
 85
 86bool CDVDInputStreamHTSP::Open(const char* file, const std::string& content)
 87{
 88  if (!CDVDInputStream::Open(file, content))
 89    return false;
 90
 91  CURL url(file);
 92  if(sscanf(url.GetFileName().c_str(), "tags/%d/%d", &m_tag, &m_channel) != 2)
 93  {
 94    CLog::Log(LOGERROR, "CDVDInputStreamHTSP::Open - invalid url (%s)\n", url.GetFileName().c_str());
 95    return false;
 96  }
 97
 98  if(!m_session.Connect(url.GetHostName(), url.GetPort()))
 99    return false;
100
101  if(!url.GetUserName().IsEmpty())
102    m_session.Auth(url.GetUserName(), url.GetPassWord());
103
104  m_session.SendEnableAsync();
105
106  if(!m_session.SendSubscribe(m_subs, m_channel))
107    return false;
108
109  m_startup = true;
110  return true;
111}
112
113bool CDVDInputStreamHTSP::IsEOF()
114{
115  return false;
116}
117
118void CDVDInputStreamHTSP::Close()
119{
120  CDVDInputStream::Close();
121  m_session.Close();
122  m_read.Clear();
123}
124
125int CDVDInputStreamHTSP::Read(uint8_t* buf, int buf_size)
126{
127  size_t count = m_read.Size();
128  if(count == 0)
129  {
130    htsmsg_t* msg = ReadStream();
131    if(msg == NULL)
132      return -1;
133
134    uint8_t* p;
135    if(htsmsg_binary_serialize(msg, (void**)&p, &count, INT_MAX) < 0)
136    {
137      htsmsg_destroy(msg);
138      return -1;
139    }
140    htsmsg_destroy(msg);
141
142    m_read.Clear();
143    m_read.buf = p;
144    m_read.cur = p;
145    m_read.end = p + count;
146  }
147
148  if(count == 0)
149    return 0;
150
151  if(count > (size_t)buf_size)
152    count = buf_size;
153
154  memcpy(buf, m_read.cur, count);
155  m_read.cur += count;
156  return count;
157}
158
159bool CDVDInputStreamHTSP::SetChannel(int channel)
160{
161  CLog::Log(LOGDEBUG, "CDVDInputStreamHTSP::SetChannel - changing to channel %d", channel);
162
163  if(!m_session.SendUnsubscribe(m_subs))
164    CLog::Log(LOGERROR, "CDVDInputStreamHTSP::SetChannel - failed to unsubscribe from previous channel");
165
166  if(!m_session.SendSubscribe(m_subs+1, channel))
167  {
168    if(m_session.SendSubscribe(m_subs, m_channel))
169      CLog::Log(LOGERROR, "CDVDInputStreamHTSP::SetChannel - failed to set channel");
170    else
171      CLog::Log(LOGERROR, "CDVDInputStreamHTSP::SetChannel - failed to set channel and restore old channel");
172
173    return false;
174  }
175
176  m_channel = channel;
177  m_subs    = m_subs+1;
178  m_startup = true;
179  return true;
180}
181
182bool CDVDInputStreamHTSP::GetChannels(SChannelV &channels, SChannelV::iterator &it)
183{
184  for(SChannels::iterator it2 = m_channels.begin(); it2 != m_channels.end(); ++it2)
185  {
186    if(m_tag == 0 || it2->second.MemberOf(m_tag))
187      channels.push_back(it2->second);
188  }
189  sort(channels.begin(), channels.end());
190
191  for(it = channels.begin(); it != channels.end(); ++it)
192    if(it->id == m_channel)
193      return true;
194  return false;
195}
196
197bool CDVDInputStreamHTSP::NextChannel(bool preview/* = false*/)
198{
199  SChannelV channels;
200  SChannelV::iterator it;
201  if(!GetChannels(channels, it))
202    return false;
203
204  SChannelC circ(channels.begin(), channels.end(), it);
205  if(++circ == it)
206    return false;
207  else
208    return SetChannel(circ->id);
209}
210
211bool CDVDInputStreamHTSP::PrevChannel(bool preview/* = false*/)
212{
213  SChannelV channels;
214  SChannelV::iterator it;
215  if(!GetChannels(channels, it))
216    return false;
217
218  SChannelC circ(channels.begin(), channels.end(), it);
219  if(--circ == it)
220    return false;
221  else
222    return SetChannel(circ->id);
223}
224
225bool CDVDInputStreamHTSP::SelectChannelByNumber(unsigned int channel)
226{
227  return SetChannel(channel);
228}
229
230bool CDVDInputStreamHTSP::UpdateItem(CFileItem& item)
231{
232  SChannels::iterator it = m_channels.find(m_channel);
233  if(it == m_channels.end())
234    return false;
235
236  SChannel& channel = it->second;
237
238  if(channel.event != m_event.id)
239  {
240    if(!m_session.GetEvent(m_event, channel.event))
241    {
242      m_event.Clear();
243      m_event.id = channel.event;
244    }
245  }
246  CFileItem current(item);
247  CHTSPSession::ParseItem(channel, m_tag, m_event, item);
248  item.SetArt("thumb", channel.icon);
249  return current.GetPath()  != item.GetPath()
250      || current.m_strTitle != item.m_strTitle;
251}
252
253int CDVDInputStreamHTSP::GetTotalTime()
254{
255    if(m_event.id == 0)
256        return 0;
257    return (m_event.stop - m_event.start) * 1000;
258}
259
260int CDVDInputStreamHTSP::GetTime()
261{
262  CDateTimeSpan time;
263  time  = CDateTime::GetUTCDateTime()
264        - CDateTime((time_t)m_event.start);
265
266  return time.GetDays()    * 1000 * 60 * 60 * 24
267       + time.GetHours()   * 1000 * 60 * 60
268       + time.GetMinutes() * 1000 * 60
269       + time.GetSeconds() * 1000;
270}
271
272void CDVDInputStreamHTSP::Abort()
273{
274  m_session.Abort();
275}