diff --git a/CREDITS b/CREDITS index 2594f4dc5..02ff8e219 100644 --- a/CREDITS +++ b/CREDITS @@ -1,6 +1,27 @@ ======= CREDITS ======= + +Version 2.2.1 +------------- +Martin Konecny (martin.konecny@sourcefabric.org) + Role: Developer Team Lead + +James Moon (james.moon@sourcefabric.org) + Role: Software Developer + +Denise Rigato (denise.rigato@sourcefabric.org) + Role: Software Developer + +Cliff Wang (cliff.wang@sourcefabric.org) + Role: QA + +Mikayel Karapetian (michael.karapetian@sourcefabric.org) + Role: QA + +Daniel James (daniel.james@sourcefabric.org) + Role: Documentor & QA + Version 2.2.0 ------------- Martin Konecny (martin.konecny@sourcefabric.org) diff --git a/airtime_mvc/application/models/Webstream.php b/airtime_mvc/application/models/Webstream.php index 18545af18..a39b26bde 100644 --- a/airtime_mvc/application/models/Webstream.php +++ b/airtime_mvc/application/models/Webstream.php @@ -309,7 +309,7 @@ class Application_Model_Webstream implements Application_Model_LibraryEditable $media_url = self::getXspfUrl($url); } elseif (preg_match("/pls\+xml/", $mime) || preg_match("/x-scpls/", $mime)) { $media_url = self::getPlsUrl($url); - } elseif (preg_match("/(mpeg|ogg)/", $mime)) { + } elseif (preg_match("/(mpeg|ogg|audio\/aacp)/", $mime)) { if ($content_length_found) { throw new Exception(_("Invalid webstream - This appears to be a file download.")); } @@ -322,10 +322,49 @@ class Application_Model_Webstream implements Application_Model_LibraryEditable } + /* PHP get_headers has an annoying property where if the passed in URL is + * a redirect, then it goes to the new URL, and returns headers from both + * requests. We only want the headers from the final request. Here's an + * example: + * + * 0 => "HTTP/1.1 302 Moved Temporarily", + * 1 => "X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.1 Java/Sun Microsystems Inc./1.6)", + * 2 => "Server: GlassFish Server Open Source Edition 3.1.1", + * 3 => "Location: http://3043.live.streamtheworld.com:80/SAM04AAC89_SC", + * 4 => "Content-Type: text/html;charset=ISO-8859-1", + * 5 => "Content-Language: en-US", + * 6 => "Content-Length: 202", + * 7 => "Date: Thu, 27 Dec 2012 21:52:59 GMT", + * 8 => "Connection: close", + * 9 => "HTTP/1.0 200 OK", + * 10 => "Expires: Thu, 01 Dec 2003 16:00:00 GMT", + * 11 => "Cache-Control: no-cache, must-revalidate", + * 12 => "Pragma: no-cache", + * 13 => "Content-Type: audio/aacp", + * 14 => "icy-br: 68", + * 15 => "Server: MediaGateway 3.2.1-04", + * */ + private static function cleanHeaders($headers) { + //find the position of HTTP/1 200 OK + // + $position = 0; + foreach ($headers as $i => $v) { + if (preg_match("/^HTTP.*200 OK$/i", $v)) { + $position = $i; + break; + } + } + + return array_slice($headers, $position); + } + private static function discoverStreamMime($url) { //TODO: What if invalid URL? $headers = get_headers($url); + + $headers = self::cleanHeaders($headers); + $mime = null; $content_length_found = false; foreach ($headers as $h) { diff --git a/changelog b/changelog index 123d71e5f..7438735ac 100644 --- a/changelog +++ b/changelog @@ -1,3 +1,15 @@ +2.2.1 - December 4th, 2012 + * Bug fixes + * Improved fades between webstreams + * Fix webstreams disconnecting occasionally + * Put 'and' and 'or' connectors between smart blocks + * Fix inability to preview webstreams in the Now Playing page on some + browsers + * Fix airtime-import script failing on FLAC files + * Fix DJ's being able to delete files they don't own + * Add support for 'x-scpls' webstream playlist types + * Fix media-monitor requiring a restart for initial import. + 2.2.0 - October 25th, 2012 * New features * Smart Playlists diff --git a/python_apps/media-monitor2/media/monitor/pure.py b/python_apps/media-monitor2/media/monitor/pure.py index 89d902d69..9bd8b69ef 100644 --- a/python_apps/media-monitor2/media/monitor/pure.py +++ b/python_apps/media-monitor2/media/monitor/pure.py @@ -154,6 +154,9 @@ def walk_supported(directory, clean_empties=False): that support the extensions we are considering. When clean_empties is True we recursively delete empty directories left over in directory after the walk. """ + if directory is None: + return + for root, dirs, files in os.walk(directory): full_paths = ( os.path.join(root, name) for name in files if is_file_supported(name) ) @@ -162,8 +165,7 @@ def walk_supported(directory, clean_empties=False): def file_locked(path): - cmd = "lsof %s" % (pipes.quote(path)) - f = Popen(cmd, shell=True, stdout=PIPE).stdout + f = Popen(["lsof", path], stdout=PIPE).stdout return bool(f.readlines()) def magic_move(old, new, after_dir_make=lambda : None):