From 3fb0fbd73fa582250de337c3ecb7ded5d171de75 Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Fri, 24 Aug 2012 19:25:19 -0400 Subject: [PATCH] CC-4291: Adding webstreams: Need ability to parse webstreams from .m3u and .xspf urls -fixed --- .../controllers/WebstreamController.php | 6 +- airtime_mvc/application/models/Webstream.php | 80 ++++++++++++++++--- 2 files changed, 70 insertions(+), 16 deletions(-) diff --git a/airtime_mvc/application/controllers/WebstreamController.php b/airtime_mvc/application/controllers/WebstreamController.php index 670fc859a..4f6cf4053 100644 --- a/airtime_mvc/application/controllers/WebstreamController.php +++ b/airtime_mvc/application/controllers/WebstreamController.php @@ -28,7 +28,7 @@ class WebstreamController extends Zend_Controller_Action $webstream->setDbName("Untitled Webstream"); $webstream->setDbDescription(""); $webstream->setDbUrl("http://"); - $webstream->setDbLength("00:00:00"); + $webstream->setDbLength("00:30:00"); $webstream->setDbName("Untitled Webstream"); $webstream->setDbCreatorId($userInfo->id); $webstream->setDbUtime(new DateTime("now", new DateTimeZone('UTC'))); @@ -139,10 +139,10 @@ class WebstreamController extends Zend_Controller_Action } - list($analysis, $mime, $di) = Application_Model_Webstream::analyzeFormData($parameters); + list($analysis, $mime, $mediaUrl, $di) = Application_Model_Webstream::analyzeFormData($parameters); try { if (Application_Model_Webstream::isValid($analysis)) { - $streamId = Application_Model_Webstream::save($parameters, $mime, $di); + $streamId = Application_Model_Webstream::save($parameters, $mime, $mediaUrl, $di); Application_Model_Library::changePlaylist($streamId, "stream"); diff --git a/airtime_mvc/application/models/Webstream.php b/airtime_mvc/application/models/Webstream.php index 71c5a110a..1db3d6124 100644 --- a/airtime_mvc/application/models/Webstream.php +++ b/airtime_mvc/application/models/Webstream.php @@ -143,7 +143,16 @@ class Application_Model_Webstream implements Application_Model_LibraryEditable } else { try { - $mime = Application_Model_Webstream::discoverStreamMime($url); + list($mime, $content_length_found) = self::discoverStreamMime($url); + if (is_null($mime)) { + throw new Exception("No MIME type found for webstream."); + } + //TODO: return url + $mediaUrl = self::getMediaUrl($url, $mime, $content_length_found); + + if (preg_match("/xspf\+xml/", $mime)) { + list($mime, $content_length_found) = self::discoverStreamMime($mediaUrl); + } } catch (Exception $e) { $valid['url'][0] = false; $valid['url'][1] = $e->getMessage(); @@ -158,7 +167,7 @@ class Application_Model_Webstream implements Application_Model_LibraryEditable $id = $parameters["id"]; - return array($valid, $mime, $di); + return array($valid, $mime, $mediaUrl, $di); } public static function isValid($analysis) @@ -182,36 +191,81 @@ class Application_Model_Webstream implements Application_Model_LibraryEditable { + } + + private static function getXspfUrl($url) + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + + // grab URL and pass it to the browser + //TODO: What if invalid url? + $content = curl_exec($ch); + + Logging::info($content); + + // close cURL resource, and free up system resources + curl_close($ch); + + $dom = new DOMDocument; + //TODO: What if invalid xml? + $dom->loadXML($content); + $tracks = $dom->getElementsByTagName('track'); + + foreach ($tracks as $track) { + $locations = $track->getElementsByTagName('location'); + foreach ($locations as $loc) { + return $loc->nodeValue; + } + } + + throw new Exception("Could not parse XSPF playlist"); + } + + private static function getMediaUrl($url, $mime, $content_length_found) + { + if (preg_match("/(mpeg|ogg)/", $mime)) { + if ($content_length_found) { + throw new Exception("Invalid webstream - This appears to be a file download."); + } + $media_url = $url; + } else if (preg_match("/x-mpegurl/", $mime)) { + $media_url = $url; + } else if (preg_match("/xspf\+xml/", $mime)) { + $media_url = self::getXspfUrl($url); + } else { + throw new Exception("Unrecognized stream type: $mime"); + } + + return $media_url; + } private static function discoverStreamMime($url) { + //TODO: What if invalid URL? $headers = get_headers($url); $mime = null; + $content_length_found = false; foreach ($headers as $h) { if (preg_match("/^content-type:/i", $h)) { list(, $value) = explode(":", $h, 2); $mime = trim($value); } if (preg_match("/^content-length:/i", $h)) { + $content_length_found = true; //if content-length appears, this is not a web stream!!!! //Aborting the save process. - throw new Exception("Invalid webstream - This appears to be a file download."); } } - if (is_null($mime)) { - throw new Exception("No MIME type found for webstream."); - } else { - if (!preg_match("/(mpeg|ogg)/", $mime)) { - throw new Exception("Unrecognized stream type: $mime"); - } - } - return $mime; + return array($mime, $content_length_found); } - public static function save($parameters, $mime, $di) + public static function save($parameters, $mime, $mediaUrl, $di) { $userInfo = Zend_Auth::getInstance()->getStorage()->read(); @@ -224,7 +278,7 @@ class Application_Model_Webstream implements Application_Model_LibraryEditable $webstream->setDbName($parameters["name"]); $webstream->setDbDescription($parameters["description"]); - $webstream->setDbUrl($parameters["url"]); + $webstream->setDbUrl($mediaUrl); $dblength = $di->format("%H:%I"); $webstream->setDbLength($dblength);