PageRenderTime 27ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/umsp/plugins/revision3/revision3.php

http://umspx.googlecode.com/
PHP | 398 lines | 335 code | 20 blank | 43 comment | 58 complexity | 27af7b8be2b813db2d79724c6fc1970b MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. /*
  3. (C) 2010 Alex Meijer for Eminent Europe B.V.
  4. Revision: modified to pull contents from rev3 shows listings inclusive of show art - shunte
  5. Revision: top down re-tooling - shunte 2010.12.21
  6. Revision: exposed show thumbnails - shunte 2011.02.19
  7. Revision: menu-fast track and R3 today feature - shunte 2011.03.07
  8. Revision: search and additional fast-tracking - shunte 2011.03.10
  9. This revision3 plugin is designed for Zoster's USMP server which runs (amongst others) inside the EM7075 and DTS variant.
  10. This code is GPL licensed. Please read it here: http://www.gnu.org/licenses/gpl.html
  11. In addtion to section 7 of the GPL terms, there is one additional term :
  12. G) You must keep this header intact when you intend to release modified copies of the program.
  13. Thank you, and enjoy this plugin.
  14. */
  15. function _pluginMain($prmQuery)
  16. {
  17. // This function is started if user clicks on the 'Revision3' option in the menu
  18. // It has no parameters and will run 'PluginCreateFeedlist' that returns an array with feeds.
  19. // If run with a feed (/revision3.php?feed=animetv) it will run the function _pluginFeedResolution
  20. // and if run with both present, it will return a list of items in the respective feed.
  21. if (strpos($prmQuery,'&amp;')!==false) $prmQuery=str_replace('&amp;','&',$prmQuery);
  22. parse_str($prmQuery, $queryData);
  23. $items = array();
  24. if ($queryData['today'] !='')
  25. $items = _pluginTodayFeedList($queryData);
  26. elseif ($queryData['feed'] !='')
  27. $items = _pluginFeedResolution($queryData);
  28. elseif ($queryData['episode'] !='')
  29. $items = _pluginEpisodeItem($queryData);
  30. elseif ($queryData['itemurl'] !='')
  31. $items = _pluginCreateVideoItems($queryData);
  32. elseif ($queryData['search']==true)
  33. {
  34. $items = _pluginCreateFeedList();
  35. exec("sudo chmod 666 /tmp/ir_injection && sleep 2 && sudo echo E > /tmp/ir_injection &");
  36. }
  37. else
  38. $items = _pluginCreateFeedList();
  39. return $items;
  40. }
  41. function scrapeShowsHTML($url,&$shows,&$image_url)
  42. {
  43. // we can get shows from the following URL, won't give us archived shows though!
  44. // page scrape method gives show name, URL, desc, thumb and a level of dynamacicity (sp?)
  45. //http://revision3.com/shows
  46. // archived (no longer associated or in production) can be found here
  47. //http://revision3.com/shows/archive
  48. $html = file_get_contents($url);
  49. preg_match_all('/<h3><a href="\/(?P<show>.*?)">(?P<title>.*?)<\/a><\/h3>/',$html,$shows);
  50. preg_match_all('/" class="thumbnail"><img src="(?P<thumb>.*?)" \/><\/a>/',$html,$image_url);
  51. }
  52. function pushMediaItems($shows,$image_url,$configData,$boiler,&$retMediaItems)
  53. {
  54. if(sizeof($shows[1])!=0)
  55. {
  56. $exclude_shows = $configData['exclude'];
  57. for ($z = 0; $z < count($shows[1]); $z++)
  58. {
  59. $upart = trim($shows['show'][$z]);
  60. $title = trim($shows['title'][$z]);
  61. // [to]day sourced show does not have the tekzilla branding
  62. if(('tzdaily'==$upart)&&('ON'!=$configData['dailyshows']))$exclude_shows .= "|$upart|";
  63. if((strpos($exclude_shows,'|'.$upart.'|')) === false)
  64. {
  65. if($configData['defaultres']!='')
  66. {
  67. if ($upart == 'tekzilla')
  68. $subshow = (($configData['dailyshows']=='ON')?'?subshow=true':'?subshow=false');
  69. else
  70. $subshow = '';
  71. $data = array (
  72. 'itemurl' => 'http://revision3.com/'.$upart.$configData['defaultres'].$subshow,
  73. );
  74. }
  75. else
  76. {
  77. $data = array (
  78. 'feed' => $upart,
  79. );
  80. }
  81. $dataStr = http_build_query($data, 'pluginvar_');
  82. $thumb = ((''!=$image_url['thumb'][$z])?$image_url['thumb'][$z]:
  83. "http://videos.revision3.com/revision3/images/shows/{$upart}/{$upart}.jpg"
  84. ///"http://bitcast-a.bitgravity.com/revision3/docs/show/{$upart}/iphone/logo.jpg" // <--- content here is excellent but not active for all shows!
  85. );
  86. $retMediaItems[] = array (
  87. 'id' => 'umsp://plugins/revision3/revision3?'.$dataStr,
  88. 'dc:title' => $boiler.' ('.$title.')',
  89. 'upnp:album_art'=> $thumb,
  90. 'upnp:class' => 'object.container',
  91. );
  92. }
  93. }
  94. }
  95. }
  96. function _pluginSearch($prmQuery)
  97. {
  98. if (preg_match('/and dc:(title|album|genre) contains "(.*?)"/', $prmQuery, $searchterm))
  99. {
  100. $retMediaItems = array();
  101. $configData = getConfigData();
  102. for ($page = 1; $page < 3; $page++) // 10 items per page limit!!
  103. {
  104. $html = file_get_contents('http://revision3.com/search/page?type=video&q='.urlencode($searchterm[2]).'&limit=10&page='.$page);
  105. if(preg_match_all(
  106. '/&client_id=revision3"><img src="(?P<thumb>.*?)" \/><div class="playLine">Play Video<\/div><\/a><a class="title" href='
  107. .'"http:\/\/www.videosurf.com\/webui\/inc\/go.php\?redirect=(?P<episode>.*?)&client_id=revision3">'
  108. .'(?P<title>.*?)<\/a><div class="description"><b>(?P<added>.*?)<\/b>/',$html,$episodes))
  109. {
  110. $exclude_shows = $configData['exclude'];
  111. for ($z = 0; $z < count($episodes[1]); $z++)
  112. {
  113. $title = $episodes['title'][$z].' '.strtolower($episodes['added'][$z]);
  114. $data = array(
  115. 'episode' => urldecode($episodes['episode'][$z]),
  116. 'thumb' => $episodes['thumb'][$z],
  117. 'title' => $title,
  118. );
  119. $dataStr = http_build_query($data, '', '&amp;');
  120. $retMediaItems[] = array (
  121. 'id' => 'umsp://plugins/revision3/revision3?'.$dataStr,
  122. 'dc:title' => $title,
  123. 'upnp:album_art'=> $episodes['thumb'][$z],
  124. 'upnp:class' => 'object.container',
  125. );
  126. }
  127. }
  128. }
  129. return $retMediaItems;
  130. }
  131. else
  132. return null;
  133. }
  134. function _pluginCreateFeedList()
  135. {
  136. $configData = getConfigData();
  137. if($configData['showtoday']=='ON')
  138. $retMediaItems[] = array (
  139. 'id' => 'umsp://plugins/revision3/revision3?today=yes',
  140. 'dc:title' => 'List shows that premiere on Revision3 today',
  141. //'upnp:album_art'=> $configData['today2'],
  142. 'upnp:album_art'=> $configData['today'],
  143. 'upnp:class' => 'object.container',
  144. );
  145. $retMediaItems[] = array (
  146. 'id' => 'umsp://plugins/revision3/revision3?search=1',
  147. 'dc:title' => 'Search Revision3 Past & Present',
  148. 'upnp:album_art'=> $configData['search'],
  149. 'upnp:class' => 'object.container',
  150. );
  151. // parse shows via revision3 shows html
  152. scrapeShowsHTML('http://revision3.com/shows',$shows,$image_url);
  153. pushMediaItems($shows,$image_url,$configData,'Revision3',$retMediaItems);
  154. if($configData['archives']=='ON')
  155. {
  156. scrapeShowsHTML('http://revision3.com/shows/archive',$shows,$image_url);
  157. pushMediaItems($shows,$image_url,$configData,'Revision3 Archive',$retMediaItems);
  158. }
  159. return $retMediaItems;
  160. }
  161. function _pluginEpisodeItem($queryData)
  162. {
  163. // we have an episode page from which we can extract playable uri information
  164. // fast-tack is broken via this mechanism but fills the need or search
  165. $configData = getConfigData();
  166. $retMediaItems = array();
  167. $html = file_get_contents($queryData['episode']);
  168. if(preg_match_all('/<a class="sizename" href="(?P<show>.*?).mp4">(?P<title>.*?)<\/a>/',$html,$playable))
  169. {
  170. for ($z = 0; $z < count($playable[1]); $z++)
  171. {
  172. $data = array(
  173. 'url' => $playable['show'][$z].'.mp4',
  174. );
  175. $dataStr = http_build_query($data, 'pluginvar_');
  176. $retMediaItems[] = array (
  177. 'id' => 'umsp://plugins/revision3/revision3?'.$dataStr,
  178. 'dc:title' => $queryData['title']." ({$playable['title'][$z]})",
  179. 'res' => $data['url'],
  180. 'upnp:album_art'=> $queryData['thumb'],
  181. 'protocolInfo' => 'http-get:*:*:*',
  182. 'upnp:class' => 'object.item.videoItem',
  183. );
  184. }
  185. }
  186. if(empty($retMediaItems))
  187. $retMediaItems[] = array (
  188. 'id' => 'umsp://plugins/revision3/revision3?nothing=',
  189. 'dc:title' => 'Apologies, unable to find playable content for this episode',
  190. 'upnp:album_art'=> $configData['stopbadge'],
  191. 'upnp:class' => 'object.container',
  192. );
  193. return $retMediaItems;
  194. }
  195. function _pluginFeedResolution($queryData)
  196. {
  197. // Create the actual XML feed url with resolution selection added at the end.
  198. // Create variants from $feed: ($feed holds the name, hak5 for ex.)
  199. $feed = $queryData['feed'];
  200. $configData = getConfigData();
  201. // if we want tekzilla daily then subshow arg should be passed (actually default is on)
  202. //http://revision3.com/tekzilla/feed/Xvid-Large?subshow=false
  203. if ($feed == 'tekzilla')
  204. $subshow = (($configData['dailyshows']=='ON')?'?subshow=true':'?subshow=false');
  205. else
  206. $subshow = '';
  207. $variants = array (
  208. array (
  209. 'desc' => 'Small',
  210. 'ext' => '/feed/MP4-Small',
  211. 'badge' => $configData['small'],
  212. ),
  213. array (
  214. 'desc' => 'Large',
  215. 'ext' => '/feed/MP4-Large',
  216. 'badge' => $configData['medium'],
  217. ),
  218. array (
  219. 'desc' => 'HD 720p',
  220. 'ext' => '/feed/MP4-High-Definition',
  221. 'badge' => $configData['large'],
  222. ),
  223. );
  224. foreach ($variants as $variant)
  225. {
  226. $data = array (
  227. 'itemurl' => 'http://revision3.com/'.$feed.$variant['ext'].$subshow,
  228. );
  229. $dataStr = http_build_query($data, 'pluginvar_');
  230. $retMediaItems[] = array (
  231. 'id' => 'umsp://plugins/revision3/revision3?'.$dataStr,
  232. 'dc:title' => $variant['desc'],
  233. 'upnp:album_art'=> $variant['badge'],
  234. 'upnp:class' => 'object.container',
  235. );
  236. }
  237. return $retMediaItems;
  238. }
  239. function _pluginTodayFeedList($queryData)
  240. {
  241. $retMediaItems = array();
  242. $configData = getConfigData();
  243. $date = date('Y-m-d');
  244. $html = file_get_contents('http://revision3.com/schedule');
  245. // looks to be buggy on the R3 side, yes valid daily shows but some weeklies also appearing???
  246. if(preg_match('/<h4><a href="\/schedule\/'.str_replace('-','\/',$date).'">(.*?)<\/ul><\/div><\/div><hr class="clear clear-left" \/><div class="day-block">/',$html,$today))
  247. {
  248. if(preg_match_all('/<p class="title"><a href="\/(?P<show>.*?)" class="show-link">(?P<title>.*?)<\/a><\/p><\/li>/',$today[1],$shows))
  249. {
  250. for ($z = 0; $z < count($shows[1]); $z++)
  251. {
  252. if(!(($configData['dailyshows']=='OFF')&&($shows['show'][$z] == 'tzdaily')))
  253. {
  254. if ($shows['show'][$z] == 'tekzilla')
  255. $subshow = (($configData['dailyshows']=='ON')?'?subshow=true':'?subshow=false');
  256. else
  257. $subshow = '';
  258. // we're fast-tracking here, either user configuration or middle of the road video resolution
  259. $data = array (
  260. 'itemurl' => 'http://revision3.com/'.$shows['show'][$z].(($configData['defaultres']!='')?$configData['defaultres']:'/feed/MP4-Large').$subshow,
  261. 'break' => true,
  262. );
  263. $retMediaItems = array_merge($retMediaItems,_pluginCreateVideoItems($data));
  264. $idx = count($retMediaItems) -1;
  265. $retMediaItems[$idx]['dc:title'] = $shows['title'][$z].' - '.$retMediaItems[$idx]['dc:title'];
  266. }
  267. }
  268. }
  269. }
  270. if(empty($retMediaItems))
  271. $retMediaItems[] = array (
  272. 'id' => 'umsp://plugins/revision3/revision3?nothing=',
  273. 'dc:title' => 'Apologies, no shows are scheduled to premiere today '.$date,
  274. 'upnp:album_art'=> $configData['stopbadge'],
  275. 'upnp:class' => 'object.container',
  276. );
  277. return $retMediaItems;
  278. }
  279. function _pluginCreateVideoItems($queryData)
  280. {
  281. // full re-tool as simple XML seems to discard the media namespace and we wish to surface thumbnail
  282. // some code bloat but net result - thumbage!!!
  283. // (sh) 20011-02-19
  284. $url = $queryData['itemurl'];
  285. $retMediaItems = array();
  286. $xml = file_get_contents($url);
  287. $reader = new XMLReader();
  288. $reader->XML($xml);
  289. $elements = array ('title','author','category','pubDate');
  290. while ($reader->read())
  291. {
  292. if (($reader->nodeType == XMLReader::ELEMENT) && ($reader->name == 'itunes:category'))
  293. {
  294. if($item['genre']=='') // multiple tags so take the first, has be the most important right!?
  295. $item['genre'] = $reader->getAttribute('text');
  296. }
  297. elseif (($reader->nodeType == XMLReader::ELEMENT) && ($reader->name == 'itunes:image'))
  298. {
  299. $item['badge'] = $reader->getAttribute('href'); // use for defaults
  300. }
  301. elseif (($reader->nodeType == XMLReader::ELEMENT) && ($reader->localName == 'item'))
  302. {
  303. do
  304. {
  305. $reader->read();
  306. $name = $reader->name;
  307. if(in_array($name,$elements))
  308. {
  309. $reader->read();
  310. if ($reader->nodeType == XMLReader::TEXT)
  311. $item[$name] = (string)$reader->value;
  312. }
  313. elseif ($name == 'enclosure')
  314. {
  315. $item['url'] = $reader->getAttribute('url');
  316. $item['type'] = $reader->getAttribute('type');
  317. $item['length'] = $reader->getAttribute('length');
  318. }
  319. elseif ($name == 'media:thumbnail')
  320. {
  321. $item['thumb'] = $reader->getAttribute('url');
  322. }
  323. } while (!(($reader->nodeType == XMLReader::END_ELEMENT) && ($reader->localName == 'item')));
  324. $data = array(
  325. 'url' => $item['url'],
  326. );
  327. $dataStr = http_build_query($data, 'pluginvar_');
  328. $retMediaItems[] = array (
  329. 'id' => 'umsp://plugins/revision3/revision3?'.$dataStr,
  330. 'dc:title' => $item['title'],
  331. 'res' => $item['url'],
  332. 'upnp:artist' => $item['author'],
  333. 'upnp:genre' => (($item['category']!='')?$item['category']:$item['genre']),
  334. 'upnp:album' => $item['title'],
  335. 'upnp:album_art'=> (($item['thumb']!='')?$item['thumb']:$item['badge']),
  336. 'size' => $item['length'],
  337. 'dc:date' => $item['pubDate'],
  338. 'protocolInfo' => 'http-get:*:'.(($item['type']!='')?$item['type']:'video/mp4').':*',
  339. 'upnp:class' => 'object.item.videoItem',
  340. );
  341. if($queryData['break']==true)
  342. break;
  343. }
  344. }
  345. return $retMediaItems;
  346. }
  347. function getConfigData()
  348. {
  349. $config = file_get_contents('/conf/config');
  350. if(preg_match('/REV3_EXCLUDE_SHOWS=\'(.+)\'/', $config, $m))$excludes = '|'.strtolower($m[1]).'|';
  351. // only process archiveed if requested (off by default)
  352. if(preg_match('/REV3_INCLUDE_ARCHIVE=\'(.+)\'/', $config, $m))$archives = strtoupper($m[1]);
  353. if(preg_match('/REV3_DAILY_SHOWS=\'(.+)\'/', $config, $m))$daily_shows = strtoupper($m[1]);
  354. if(preg_match('/REV3_DAILY_SHOWS=\'(.+)\'/', $config, $m))$daily_shows = strtoupper($m[1]);
  355. if(preg_match('/REV3_SHOW_TODAY=\'(.+)\'/', $config, $m))$show_today = strtoupper($m[1]);
  356. if(preg_match('/REV3_DEFAULT_RESOLUTION=\'(.+)\'/', $config, $m))$def_resolution = trim($m[1]);
  357. return array (
  358. 'exclude' => $excludes,
  359. 'archives' => $archives,
  360. 'dailyshows' => $daily_shows,
  361. 'showtoday' => $show_today,
  362. 'defaultres' => $def_resolution,
  363. 'search' => 'http://lh3.googleusercontent.com/_xJcSFBlLg_Y/TY0Z-O74N0I/AAAAAAAAAyM/fBRtOzJ6k4A/s200/rev3search.png',
  364. 'badge' => 'http://lh3.ggpht.com/_xJcSFBlLg_Y/TQ_-D84OpOI/AAAAAAAAAFg/JFMIuOhXK78/s200/Revision3.png',
  365. 'today' => 'http://lh3.googleusercontent.com/_xJcSFBlLg_Y/TXULuQl_nZI/AAAAAAAAAdg/8cq0-vameS0/s200/rev3today.png',
  366. 'today2' => 'http://lh3.googleusercontent.com/_xJcSFBlLg_Y/TXeIlAX9iPI/AAAAAAAAAe4/JQ2DNavJpj0/s200/rev3Today.png',
  367. 'large' => 'http://lh3.ggpht.com/_xJcSFBlLg_Y/TRDekc_vrfI/AAAAAAAAAF0/c-91Brvc4Wo/rev3-want-large.png',
  368. 'medium' => 'http://lh3.ggpht.com/_xJcSFBlLg_Y/TRDektn37zI/AAAAAAAAAF4/X8KUbgDKk0U/rev3-want-medium.png',
  369. 'small' => 'http://lh3.ggpht.com/_xJcSFBlLg_Y/TRDekz57jEI/AAAAAAAAAF8/XbMZnlpfelE/rev3-want-small.png',
  370. 'stopbadge' => 'http://lh3.googleusercontent.com/_xJcSFBlLg_Y/TWOoLmVMr6I/AAAAAAAAAYE/_-d60WDF-rQ/stop-a-cop8.png',
  371. );
  372. }
  373. ?>