function __construct(Zend_Config $options) { $this->options = $options; if ($this->isEnabled()) { X_RtmpDump::getInstance()->setOptions($this->options); } }
/** * @return X_RtmpDump */ public static function getInstance() { if (self::$instance === null) { self::$instance = new X_RtmpDump(); } return self::$instance; }
/** * @see X_VlcShares_Plugins_ResolverInterface::getLocation() */ function resolveLocation($location = null) { if ($location == '' || $location == null) { return false; } if (array_key_exists($location, $this->cachedLocation)) { return $this->cachedLocation[$location]; } X_Debug::i("Requested location: {$location}"); $list = $this->getChannelsList(); $dom = simplexml_load_string($list); $channel = $dom->xpath("//stream[title = \"{$location}\"]"); $return = false; if ($channel) { /* @var $channel SimpleXmlElement */ $channel = $channel[0]; $uriParam = array(); $uriParam['rtmp'] = trim((string) $channel->link); $uriParam['swfUrl'] = trim((string) $channel->swfUrl); $uriParam['pageUrl'] = trim((string) $channel->pageUrl); if (@strlen(trim((string) $channel->playpath))) { $uriParam['playpath'] = trim((string) $channel->playpath); } $advanced = trim((string) $channel->advanced); if (@strlen($advanced)) { $pattern = '/-(?P<arg>[a-zA-Z]) \\"?(?P<value>[^\\-\\" ]+)\\"?/i'; $advParams = array(); if (preg_match_all($pattern, $advanced, $advParams, PREG_SET_ORDER)) { foreach ($advParams as $advParam) { $arg = $advParam['arg']; $value = $advParam['value']; if (array_key_exists($arg, $this->placeholders)) { $uriParam[$this->placeholders[$arg]] = $value; } } } } $uriParam['live'] = true; $return = X_RtmpDump::buildUri($uriParam); } $this->cachedLocation[$location] = $return; return $return; }
public function savertmpAction() { $form = new Application_Form_VideoRtmp(); $form->setAction($this->_helper->url('savertmp')); if ($form->isValid($this->getRequest()->getPost())) { $values = $form->getValues(); $params = array(); foreach ($values as $key => $value) { if ($value == 'true') { $params[$key] = true; } elseif ($value != '') { $params[$key] = $value; } } $url = X_RtmpDump::buildUri($params); $this->_forward('add', 'onlinelibrary', 'default', array('rtmp' => $url)); } else { $this->view->form = $form; } }
public function doStop($threadInfo) { // this should be "->shutdown()" X_RtmpDump::getInstance()->forceKill(); // wait few seconds sleep(2); //TODO tweak value better }
// Define path to application directory if (!defined('APPLICATION_PATH')) { if (realpath(dirname(__FILE__) . '/../application') === false) { // in dev define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../../../core/application')); } else { define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application')); } } // Define application environment defined('APPLICATION_ENV') || define('APPLICATION_ENV', getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'); // Ensure library/ is on include_path set_include_path(implode(PATH_SEPARATOR, array(realpath(APPLICATION_PATH . '/../library'), get_include_path()))); /** Zend_Application */ (bool) @(include_once 'Zend/Application.php') or die('VLCShares needs Zend Framework 1.10.6+. Please, install it in library/ folder'); // Create application, bootstrap, and run $application = new Zend_Application(APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini'); $application->bootstrap(); //->run(); $huluHelper = new X_VlcShares_Plugins_Helper_Hulu(); echo "<html><body>"; try { $fetched = $huluHelper->setLocation('324620/the-daily-show-with-jon-stewart-mon-jan-30-2012')->fetch(); echo '<pre>' . print_r($fetched, true) . '</pre>'; echo '<b>RTMPDump: </b><br /><pre>' . (string) X_RtmpDump::getInstance()->parseUri($fetched['url']) . '</pre>'; } catch (Exception $e) { echo "<h1>Exception:</h1><h2>{$e->getMessage()}</h2>"; echo "<pre>{$e->getTraceAsString()}</pre>"; } echo "</body></html>";
public function fetch($infoOnly = false) { if ($this->_location == null) { X_Debug::w('Trying to fetch a hulu location without a location'); throw new Exception('Trying to fetch a hulu location without a location'); } if ($this->_fetched === false) { // ported code form http://gitorious.org/get-flash-videos-plugins/gfv-plugins/blobs/raw/release/Hulu.pm $http = $this->getHttpClient("http://www.hulu.com/watch/{$this->_location}"); $response = $http->request(); $datas = $response->getBody(); X_Debug::i("Fetching main page for: {{$this->_location}}"); //echo "<b>REQUESTED PAGE</b><textarea>".htmlentities($datas)."</textarea><br/>"; $pageUrl = str_replace('.com:80/', '.com/', $http->getUri(true)); X_Debug::i("Last location is {{$pageUrl}}"); /* $matches = array(); if ( !preg_match('/content_id\"\, (?P<CID>[0-9]+?)\)/', $datas, $matches) ) { X_Debug::e("Content_ID pattern failure"); throw new Exception("Content_ID pattern failure"); } $content_id = $matches['CID']; echo "<b>CONTENT ID FOUND:</b><textarea>".htmlentities($content_id)."</textarea><br/>"; */ $matches = array(); if (!preg_match('/videoEmbedId = "(?P<EID>[^\\"]+?)"/', $datas, $matches)) { X_Debug::e("EID pattern failure"); X_Debug::i("Searching EID in: \n{$datas}"); throw new Exception("EID pattern failure"); } $eid = $matches['EID']; //echo "<b>EID FOUND:</b><textarea>".htmlentities($eid)."</textarea><br/>"; X_Debug::i("EID Found {{$eid}}"); // fetch information about the player, required by rtmp //list($swfsize, $swfhash, $swfUrl) = $this->getPlayerData(); //$http->setHeaders('Host', 'r.hulu.com'); //echo "<b>API URL:</b><textarea>".htmlentities("http://r.hulu.com/videos?content_id=$content_id")."</textarea><br/>"; //$http->setUri("http://r.hulu.com/videos?content_id=$content_id"); $apiUrl = 'http://r.hulu.com/videos?eid=' . $eid; X_Debug::i("Fetching video info from {{$apiUrl}}"); $http->setUri($apiUrl); //echo "<b>API URL:</b><textarea>".htmlentities($apiUrl)."</textarea><br/>"; $datas = $http->request()->getBody(); //$http->setHeaders('Host', null); //echo "<b>API RESPONSE 1</b><textarea>".htmlentities($datas)."</textarea><br/>"; $xml = new SimpleXMLElement($datas); if ($xml->video == null) { X_Debug::e("Invalid response for EID {{$eid}}"); X_Debug::i("Response: \n{$datas}"); throw new Exception("Invalid response for EID {{$eid}}"); } //echo "<b>ENCODED PID</b><textarea>".htmlentities((string) $xml->video->pid[0])."</textarea><br/>"; X_Debug::i("Encoded PID: {{$xml->video[0]->pid[0]}}"); $pid = $this->decodePid((string) $xml->video[0]->pid[0]); X_Debug::i("Decoded PID: {{$pid}}"); //echo "<b>DECRYPTED PID</b><textarea>".htmlentities($pid)."</textarea><br/>"; $title = (string) $xml->video->title[0]; if ($xml->video->{'media-type'} == "TV") { $show_name = $xml->video->show->name[0]; $season = $xml->video->{"season-number"}[0]; $episode_number = $xml->video->{"episode-number"}[0]; $title = sprintf('%s - S%02dE%02d - %s', $show_name, $season, $episode_number, $title); } $description = (string) $xml->video->description[0]; $length = X_Env::formatTime((int) $xml->video->duration[0]); $thumbnail = (string) $xml->video->{"thumbnail-url"}[0]; $needProxy = $xml->video->{"allow-international"}[0] == 'false' ? true : false; if ($infoOnly) { $infos = array('title' => $title, 'description' => $description, 'length' => $length, 'thumbnail' => $thumbnail, 'needProxy' => $needProxy); X_Debug::i("Video info: " . print_r($infos, true)); return $infos; } // new focus on smil infos //$auth = md5($pid.self::$KEYS_PLAYER); //echo "<b>AUTH</b><pre>$auth</pre><br/>"; //echo "<b>REQUEST</b><pre>http://s.hulu.com/select.ashx?pid=$pid&auth=$auth&v=".self::$KEYS_V."</pre><br/>"; //$http->setUri("http://s.hulu.com/select.ashx?pid=$pid&auth=$auth&v=".self::$KEYS_V); $now = (int) time(); $parameters = array('video_id' => $pid, 'v' => self::$KEYS_V, 'ts' => (string) $now, 'np' => '1', 'vp' => '1', 'device_id' => '', 'pp' => 'Desktop', 'dp_id' => 'Hulu', 'region' => 'US', 'ep' => '1', 'language' => 'en'); $paramKeys = array_keys($parameters); $sortedParams = $parameters; ksort($sortedParams); $bcsl = ''; foreach ($sortedParams as $key => $value) { $bcsl .= $key . $value; } $bcs = hash_hmac('md5', $bcsl, self::$HMAC); $smil_file_url = 'http://s.hulu.com/select?' . http_build_query($sortedParams) . "&bcs={$bcs}"; X_Debug::i("Fetching SMIL file from {{$smil_file_url}}"); //echo "<b>SMIL FILE URL</b><textarea>".htmlentities($smil_file_url)."</textarea><br/>"; $http->setUri($smil_file_url); $datas = $http->request()->getBody(); //echo "<b>ENCODED SMIL</b><textarea>".htmlentities($datas)."</textarea><br/>"; $datas = $this->decodeSmil($datas); //echo "<b>DECRYPTED SMIL</b><textarea>".htmlentities($datas)."</textarea><br/>"; X_Debug::i("Decoded SMIL (50 chars only): \n" . substr($datas, 0, 50) . "..."); $xml = new SimpleXMLElement($datas); //$vids = $xml->body->switch[1]->video[0]; $vids = $xml->body->switch[1]->video; //[0]; //$ref = $xml->body->switch[1]->ref[0]; // choose the better source... ignored now //echo "<b>VIDEOS</b><pre>".print_r($vid, true)."</pre><br/>"; if ($this->options->get('priority', 'cdn')) { $vids = $this->filterCdn($vids, $this->options->get('cdn', 'limelight')); $vids = $this->filterCdn($vids, $this->options->get('quality', '400_h264')); } else { $vids = $this->filterCdn($vids, $this->options->get('quality', '400_h264')); $vids = $this->filterCdn($vids, $this->options->get('cdn', 'limelight')); } $vid = @$vids[0]; // if no vid available yet, just try to get the first one if (!$vid) { X_Debug::w('Filter mode failed'); $vid = $xml->body->switch[1]->video[0]; } if (is_null($vid)) { X_Debug::e('No video tag. Video requires HULU Plus or you are not in US'); X_Debug::i("Video info: " . print_r($vid, true)); throw new Exception('No video tag. Video requires HULU Plus or you are not in US'); } X_Debug::i("Selected video info: " . print_r($vid, true)); // ported code: http://code.google.com/p/bluecop-xbmc-repo/source/browse/trunk/plugin.video.hulu/resources/lib/stream_hulu.py?spec=svn157&r=157 $stream = (string) $vid['stream']; $server = (string) $vid['server']; $token = (string) $vid['token']; $cdn = (string) $vid['cdn']; $hostname = ""; $appName = ""; $protocol = ""; $pattern = '/^(?P<protocol>[a-zA-z]+:\\/\\/)(?P<hostname>[^\\/]+)\\/(?P<appname>.*)$/'; $matches = array(); if (preg_match($pattern, $server, $matches)) { $protocol = $matches['protocol']; $hostname = $matches['hostname']; $appName = $matches['appname']; } // rtmp params based on cdn switch ($cdn) { case 'level3': $appName .= "?sessionid=sessionId&{$token}"; $stream = substr($stream, 0, -4); // remove .mp4 $server = "{$server}?sessionid=sessionId&{$token}"; break; case 'limelight': $appName .= "?sessionid=sessionId&{$token}"; $stream = substr($stream, 0, -4); // remove .mp4 $server = "{$server}?sessionid=sessionId&{$token}"; break; case 'akamai': $appName .= "?sessionid=sessionId&{$token}"; $server = "{$server}?sessionid=sessionId&{$token}"; break; default: } $this->_fetched = array('title' => $title, 'description' => $description, 'length' => $length, 'thumbnail' => $thumbnail, 'eid' => $eid, 'pid' => $pid, 'needProxy' => $needProxy, 'stream' => $stream, 'server' => $server, 'token' => $token, 'cdn' => $cdn, 'hostname' => $hostname, 'protocol' => $protocol, 'appName' => $appName, 'playpath' => $stream, 'pageUrl' => self::HULU_PLAYER, 'swfUrl' => self::HULU_PLAYER); $this->_fetched['url'] = X_RtmpDump::buildUri(array('rtmp' => $server, 'app' => $appName, 'playpath' => $stream, 'swfUrl' => self::HULU_PLAYER, 'pageUrl' => self::HULU_PLAYER, 'swfVfy' => self::HULU_PLAYER)); $this->_cachedSearch[$this->_location] = $this->_fetched; //X_Debug::i("All info: ".print_r($this->_fetched, true)); return $this->_fetched; } }