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

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