From 63a51081c12ed296d012f12377d0b707f25ac7dc Mon Sep 17 00:00:00 2001
From: James <james@sourcefabric-DX4840.(none)>
Date: Thu, 9 Aug 2012 17:50:43 -0400
Subject: [PATCH 01/17] CC-4182: Media Library -> Smart Playlist: Empty box
 appears after left clicking a Dynamic Smart Playlist created by other users,
 when login as DJ

- fixed
---
 airtime_mvc/application/controllers/LibraryController.php | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/airtime_mvc/application/controllers/LibraryController.php b/airtime_mvc/application/controllers/LibraryController.php
index 067a33ac6..3d28b3a8a 100644
--- a/airtime_mvc/application/controllers/LibraryController.php
+++ b/airtime_mvc/application/controllers/LibraryController.php
@@ -108,8 +108,6 @@ class LibraryController extends Zend_Controller_Action
                 $menu["del"] = array("name"=> "Delete", "icon" => "delete", "url" => "/library/delete");
                 $menu["edit"] = array("name"=> "Edit", "icon" => "edit", "url" => "/library/edit-file-md/id/{$id}");
             }
-          
-
         }
 
         //SOUNDCLOUD MENU OPTIONS
@@ -136,6 +134,10 @@ class LibraryController extends Zend_Controller_Action
 
             $menu["soundcloud"]["items"]["upload"] = array("name" => $text, "icon" => "soundcloud", "url" => "/library/upload-file-soundcloud/id/{$id}");
         }
+        
+        if (empty($menu)) {
+            $menu["noaction"] = array("name"=>"No action available");
+        }
 
         $this->view->items = $menu;
     }

From fe3f4ea6787d0ad47ffb4a2d822aef97301e76d0 Mon Sep 17 00:00:00 2001
From: Martin Konecny <martin.konecny@gmail.com>
Date: Fri, 10 Aug 2012 00:57:03 -0400
Subject: [PATCH 02/17] CC-1665: Scheduled stream rebroadcasting and recording

-capture stream mime type and store in db.
---
 .../application/controllers/ApiController.php | 14 +-----
 .../controllers/WebstreamController.php       | 20 ++++----
 airtime_mvc/application/models/Playlist.php   |  6 +--
 airtime_mvc/application/models/Webstream.php  | 50 ++++++++++++++++++-
 .../airtime/map/CcWebstreamTableMap.php       |  1 +
 .../models/airtime/om/BaseCcWebstream.php     | 50 ++++++++++++++++++-
 .../models/airtime/om/BaseCcWebstreamPeer.php | 31 +++++++-----
 .../airtime/om/BaseCcWebstreamQuery.php       | 26 ++++++++++
 airtime_mvc/build/schema.xml                  |  1 +
 airtime_mvc/build/sql/schema.sql              |  1 +
 10 files changed, 158 insertions(+), 42 deletions(-)

diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php
index 87002616c..863484a5e 100644
--- a/airtime_mvc/application/controllers/ApiController.php
+++ b/airtime_mvc/application/controllers/ApiController.php
@@ -132,29 +132,19 @@ class ApiController extends Zend_Controller_Action
                     $file_base_name = substr($file_base_name, 1);
                 }
 
-                // possibly use fileinfo module here in the future.
-                // http://www.php.net/manual/en/book.fileinfo.php
-                $ext = pathinfo($file_base_name, PATHINFO_EXTENSION);
                 //Download user left clicks a track and selects Download.
                 if ("true" == $this->_getParam('download')) {
                     //path_info breaks up a file path into seperate pieces of informaiton.
                     //We just want the basename which is the file name with the path
                     //information stripped away. We are using Content-Disposition to specify
                     //to the browser what name the file should be saved as.
-                    //
-                    // By james.moon:
-                    // I'm removing pathinfo() since it strips away UTF-8 characters.
-                    // Using manualy parsing
                     header('Content-Disposition: attachment; filename="'.$file_base_name.'"');
                 } else {
                     //user clicks play button for track and downloads it.
                     header('Content-Disposition: inline; filename="'.$file_base_name.'"');
                 }
-                if (strtolower($ext) === 'mp3') {
-                    $this->smartReadFile($filepath, 'audio/mpeg');
-                } else {
-                    $this->smartReadFile($filepath, 'audio/'.$ext);
-                }
+
+                $this->smartReadFile($filepath, $media->getPropelOrm()->getDbMime());
                 exit;
             } else {
                 header ("HTTP/1.1 404 Not Found");
diff --git a/airtime_mvc/application/controllers/WebstreamController.php b/airtime_mvc/application/controllers/WebstreamController.php
index 0cafb690b..3e82ad47e 100644
--- a/airtime_mvc/application/controllers/WebstreamController.php
+++ b/airtime_mvc/application/controllers/WebstreamController.php
@@ -52,13 +52,8 @@ class WebstreamController extends Zend_Controller_Action
         $hasPermission = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER, UTYPE_HOST));
         $id = $request->getParam("id");
 
-        if ($id == -1) {
-            $webstream = new CcWebstream();
-        } else {
-            $webstream = CcWebstreamQuery::create()->findPK($id);
-        }
-        
         if ($id != -1) {
+            $webstream = CcWebstreamQuery::create()->findPK($id);
             //we are updating a playlist. Ensure that if the user is a host/dj, that he has the correct permission. 
             $user = Application_Model_User::getCurrentUser();
             if ($webstream->getDbCreatorId() != $user->getId()) {
@@ -73,11 +68,14 @@ class WebstreamController extends Zend_Controller_Action
         }
 
         $analysis = Application_Model_Webstream::analyzeFormData($request);
-        
-        if (Application_Model_Webstream::isValid($analysis)) {
-            Application_Model_Webstream::save($request, $webstream);
-            $this->view->statusMessage = "<div class='success'>Webstream saved.</div>";
-        } else {
+        try { 
+            if (Application_Model_Webstream::isValid($analysis)) {
+                Application_Model_Webstream::save($request, $id);
+                $this->view->statusMessage = "<div class='success'>Webstream saved.</div>";
+            } else {
+                throw new Exception();
+            }
+        } catch (Exception $e) {
             $this->view->statusMessage = "<div class='errors'>Invalid form values.</div>"; 
             $this->view->analysis = $analysis;
         }
diff --git a/airtime_mvc/application/models/Playlist.php b/airtime_mvc/application/models/Playlist.php
index 23ca9d2c2..8e1660394 100644
--- a/airtime_mvc/application/models/Playlist.php
+++ b/airtime_mvc/application/models/Playlist.php
@@ -157,7 +157,7 @@ class Application_Model_Playlist
         $files = array();
 
         $sql = <<<SQL
-  (SELECT *
+  SELECT *
    FROM (
            (SELECT pc.id AS id,
                    pc.type,
@@ -212,11 +212,11 @@ class Application_Model_Playlist
             JOIN cc_subjs AS sbj ON bl.creator_id=sbj.id
             WHERE pc.playlist_id = {$this->id}
               AND pc.TYPE = 2)) AS temp
-   ORDER BY temp.position);
+   ORDER BY temp.position;
 SQL;
 
         $con = Propel::getConnection();
-        $rows = $con->query($sql)->fetchAll();
+        $rows = $con->query($sql)->fetchAll(PDO::FETCH_ASSOC);
 
         $offset = 0;
         foreach ($rows as &$row) {
diff --git a/airtime_mvc/application/models/Webstream.php b/airtime_mvc/application/models/Webstream.php
index 97f74666d..a33575a68 100644
--- a/airtime_mvc/application/models/Webstream.php
+++ b/airtime_mvc/application/models/Webstream.php
@@ -22,6 +22,11 @@ class Application_Model_Webstream{
         }
     }
 
+    public function getOrm()
+    {
+        return $this->webstream;
+    }
+
     public function getName()
     {
         return $this->webstream->getDbName();
@@ -151,7 +156,7 @@ class Application_Model_Webstream{
     public static function isValid($analysis)
     {
         foreach ($analysis as $k => $v) {
-            if ($v[0] == false) {
+            if ($v[0] === false) {
                 return false;
             }
         }
@@ -159,7 +164,34 @@ class Application_Model_Webstream{
         return true;
     }
 
-    public static function save($request, $webstream)
+    /*
+     * This function is a callback used by curl to let us work
+     * with the contents returned from an http request. We don't
+     * actually want to work with the contents however (we just want
+     * the response headers), so immediately return a -1 in this function
+     * which tells curl not to download the response body at all.
+     */
+    private function writefn($ch, $chunk) 
+    { 
+        return -1;
+    }
+
+    private function discoverStreamMime()
+    {
+        Logging::log($this->webstream->getDbUrl());
+        $ch = curl_init();
+        curl_setopt($ch, CURLOPT_URL, $this->webstream->getDbUrl());
+        curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
+        curl_setopt($ch, CURLOPT_WRITEFUNCTION, array($this, 'writefn'));
+        $result = curl_exec($ch);
+        $mime = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
+        curl_close($ch);       
+
+        Logging::log($mime);
+        return $mime;
+    }
+
+    public static function save($request, $id)
     {
         $userInfo = Zend_Auth::getInstance()->getStorage()->read();
 
@@ -178,6 +210,10 @@ class Application_Model_Webstream{
         }
 
 
+        //$ws = new Application_Model_Webstream($id);
+        //$webstream = $ws->getOrm();
+
+        $webstream = new CcWebstream();
         $webstream->setDbName($request->getParam("name"));
         $webstream->setDbDescription($request->getParam("description"));
         $webstream->setDbUrl($request->getParam("url"));
@@ -187,5 +223,15 @@ class Application_Model_Webstream{
         $webstream->setDbUtime(new DateTime("now", new DateTimeZone('UTC')));
         $webstream->setDbMtime(new DateTime("now", new DateTimeZone('UTC')));
         $webstream->save();
+
+        $ws = new Application_Model_Webstream($webstream->getDbId());
+       
+        $mime = $ws->discoverStreamMime();
+        if ($mime !== false) {
+            $webstream->setDbMime($mime);
+        } else {
+            throw new Exception("Couldn't get MIME type!");
+        }
+        $webstream->save();
     }
 }
diff --git a/airtime_mvc/application/models/airtime/map/CcWebstreamTableMap.php b/airtime_mvc/application/models/airtime/map/CcWebstreamTableMap.php
index 316553581..5121aa39b 100644
--- a/airtime_mvc/application/models/airtime/map/CcWebstreamTableMap.php
+++ b/airtime_mvc/application/models/airtime/map/CcWebstreamTableMap.php
@@ -46,6 +46,7 @@ class CcWebstreamTableMap extends TableMap {
 		$this->addColumn('CREATOR_ID', 'DbCreatorId', 'INTEGER', true, null, null);
 		$this->addColumn('MTIME', 'DbMtime', 'TIMESTAMP', true, 6, null);
 		$this->addColumn('UTIME', 'DbUtime', 'TIMESTAMP', true, 6, null);
+		$this->addColumn('MIME', 'DbMime', 'VARCHAR', false, 255, null);
 		// validators
 	} // initialize()
 
diff --git a/airtime_mvc/application/models/airtime/om/BaseCcWebstream.php b/airtime_mvc/application/models/airtime/om/BaseCcWebstream.php
index b570309dc..e5faf12fd 100644
--- a/airtime_mvc/application/models/airtime/om/BaseCcWebstream.php
+++ b/airtime_mvc/application/models/airtime/om/BaseCcWebstream.php
@@ -73,6 +73,12 @@ abstract class BaseCcWebstream extends BaseObject  implements Persistent
 	 */
 	protected $utime;
 
+	/**
+	 * The value for the mime field.
+	 * @var        string
+	 */
+	protected $mime;
+
 	/**
 	 * @var        array CcSchedule[] Collection to store aggregation of CcSchedule objects.
 	 */
@@ -239,6 +245,16 @@ abstract class BaseCcWebstream extends BaseObject  implements Persistent
 		}
 	}
 
+	/**
+	 * Get the [mime] column value.
+	 * 
+	 * @return     string
+	 */
+	public function getDbMime()
+	{
+		return $this->mime;
+	}
+
 	/**
 	 * Set the value of [id] column.
 	 * 
@@ -457,6 +473,26 @@ abstract class BaseCcWebstream extends BaseObject  implements Persistent
 		return $this;
 	} // setDbUtime()
 
+	/**
+	 * Set the value of [mime] column.
+	 * 
+	 * @param      string $v new value
+	 * @return     CcWebstream The current object (for fluent API support)
+	 */
+	public function setDbMime($v)
+	{
+		if ($v !== null) {
+			$v = (string) $v;
+		}
+
+		if ($this->mime !== $v) {
+			$this->mime = $v;
+			$this->modifiedColumns[] = CcWebstreamPeer::MIME;
+		}
+
+		return $this;
+	} // setDbMime()
+
 	/**
 	 * Indicates whether the columns in this object are only set to default values.
 	 *
@@ -501,6 +537,7 @@ abstract class BaseCcWebstream extends BaseObject  implements Persistent
 			$this->creator_id = ($row[$startcol + 5] !== null) ? (int) $row[$startcol + 5] : null;
 			$this->mtime = ($row[$startcol + 6] !== null) ? (string) $row[$startcol + 6] : null;
 			$this->utime = ($row[$startcol + 7] !== null) ? (string) $row[$startcol + 7] : null;
+			$this->mime = ($row[$startcol + 8] !== null) ? (string) $row[$startcol + 8] : null;
 			$this->resetModified();
 
 			$this->setNew(false);
@@ -509,7 +546,7 @@ abstract class BaseCcWebstream extends BaseObject  implements Persistent
 				$this->ensureConsistency();
 			}
 
-			return $startcol + 8; // 8 = CcWebstreamPeer::NUM_COLUMNS - CcWebstreamPeer::NUM_LAZY_LOAD_COLUMNS).
+			return $startcol + 9; // 9 = CcWebstreamPeer::NUM_COLUMNS - CcWebstreamPeer::NUM_LAZY_LOAD_COLUMNS).
 
 		} catch (Exception $e) {
 			throw new PropelException("Error populating CcWebstream object", $e);
@@ -850,6 +887,9 @@ abstract class BaseCcWebstream extends BaseObject  implements Persistent
 			case 7:
 				return $this->getDbUtime();
 				break;
+			case 8:
+				return $this->getDbMime();
+				break;
 			default:
 				return null;
 				break;
@@ -881,6 +921,7 @@ abstract class BaseCcWebstream extends BaseObject  implements Persistent
 			$keys[5] => $this->getDbCreatorId(),
 			$keys[6] => $this->getDbMtime(),
 			$keys[7] => $this->getDbUtime(),
+			$keys[8] => $this->getDbMime(),
 		);
 		return $result;
 	}
@@ -936,6 +977,9 @@ abstract class BaseCcWebstream extends BaseObject  implements Persistent
 			case 7:
 				$this->setDbUtime($value);
 				break;
+			case 8:
+				$this->setDbMime($value);
+				break;
 		} // switch()
 	}
 
@@ -968,6 +1012,7 @@ abstract class BaseCcWebstream extends BaseObject  implements Persistent
 		if (array_key_exists($keys[5], $arr)) $this->setDbCreatorId($arr[$keys[5]]);
 		if (array_key_exists($keys[6], $arr)) $this->setDbMtime($arr[$keys[6]]);
 		if (array_key_exists($keys[7], $arr)) $this->setDbUtime($arr[$keys[7]]);
+		if (array_key_exists($keys[8], $arr)) $this->setDbMime($arr[$keys[8]]);
 	}
 
 	/**
@@ -987,6 +1032,7 @@ abstract class BaseCcWebstream extends BaseObject  implements Persistent
 		if ($this->isColumnModified(CcWebstreamPeer::CREATOR_ID)) $criteria->add(CcWebstreamPeer::CREATOR_ID, $this->creator_id);
 		if ($this->isColumnModified(CcWebstreamPeer::MTIME)) $criteria->add(CcWebstreamPeer::MTIME, $this->mtime);
 		if ($this->isColumnModified(CcWebstreamPeer::UTIME)) $criteria->add(CcWebstreamPeer::UTIME, $this->utime);
+		if ($this->isColumnModified(CcWebstreamPeer::MIME)) $criteria->add(CcWebstreamPeer::MIME, $this->mime);
 
 		return $criteria;
 	}
@@ -1055,6 +1101,7 @@ abstract class BaseCcWebstream extends BaseObject  implements Persistent
 		$copyObj->setDbCreatorId($this->creator_id);
 		$copyObj->setDbMtime($this->mtime);
 		$copyObj->setDbUtime($this->utime);
+		$copyObj->setDbMime($this->mime);
 
 		if ($deepCopy) {
 			// important: temporarily setNew(false) because this affects the behavior of
@@ -1284,6 +1331,7 @@ abstract class BaseCcWebstream extends BaseObject  implements Persistent
 		$this->creator_id = null;
 		$this->mtime = null;
 		$this->utime = null;
+		$this->mime = null;
 		$this->alreadyInSave = false;
 		$this->alreadyInValidation = false;
 		$this->clearAllReferences();
diff --git a/airtime_mvc/application/models/airtime/om/BaseCcWebstreamPeer.php b/airtime_mvc/application/models/airtime/om/BaseCcWebstreamPeer.php
index 0839a8f9b..4ec74befd 100644
--- a/airtime_mvc/application/models/airtime/om/BaseCcWebstreamPeer.php
+++ b/airtime_mvc/application/models/airtime/om/BaseCcWebstreamPeer.php
@@ -26,7 +26,7 @@ abstract class BaseCcWebstreamPeer {
 	const TM_CLASS = 'CcWebstreamTableMap';
 	
 	/** The total number of columns. */
-	const NUM_COLUMNS = 8;
+	const NUM_COLUMNS = 9;
 
 	/** The number of lazy-loaded columns. */
 	const NUM_LAZY_LOAD_COLUMNS = 0;
@@ -55,6 +55,9 @@ abstract class BaseCcWebstreamPeer {
 	/** the column name for the UTIME field */
 	const UTIME = 'cc_webstream.UTIME';
 
+	/** the column name for the MIME field */
+	const MIME = 'cc_webstream.MIME';
+
 	/**
 	 * An identiy map to hold any loaded instances of CcWebstream objects.
 	 * This must be public so that other peer classes can access this when hydrating from JOIN
@@ -71,12 +74,12 @@ abstract class BaseCcWebstreamPeer {
 	 * e.g. self::$fieldNames[self::TYPE_PHPNAME][0] = 'Id'
 	 */
 	private static $fieldNames = array (
-		BasePeer::TYPE_PHPNAME => array ('DbId', 'DbName', 'DbDescription', 'DbUrl', 'DbLength', 'DbCreatorId', 'DbMtime', 'DbUtime', ),
-		BasePeer::TYPE_STUDLYPHPNAME => array ('dbId', 'dbName', 'dbDescription', 'dbUrl', 'dbLength', 'dbCreatorId', 'dbMtime', 'dbUtime', ),
-		BasePeer::TYPE_COLNAME => array (self::ID, self::NAME, self::DESCRIPTION, self::URL, self::LENGTH, self::CREATOR_ID, self::MTIME, self::UTIME, ),
-		BasePeer::TYPE_RAW_COLNAME => array ('ID', 'NAME', 'DESCRIPTION', 'URL', 'LENGTH', 'CREATOR_ID', 'MTIME', 'UTIME', ),
-		BasePeer::TYPE_FIELDNAME => array ('id', 'name', 'description', 'url', 'length', 'creator_id', 'mtime', 'utime', ),
-		BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, 7, )
+		BasePeer::TYPE_PHPNAME => array ('DbId', 'DbName', 'DbDescription', 'DbUrl', 'DbLength', 'DbCreatorId', 'DbMtime', 'DbUtime', 'DbMime', ),
+		BasePeer::TYPE_STUDLYPHPNAME => array ('dbId', 'dbName', 'dbDescription', 'dbUrl', 'dbLength', 'dbCreatorId', 'dbMtime', 'dbUtime', 'dbMime', ),
+		BasePeer::TYPE_COLNAME => array (self::ID, self::NAME, self::DESCRIPTION, self::URL, self::LENGTH, self::CREATOR_ID, self::MTIME, self::UTIME, self::MIME, ),
+		BasePeer::TYPE_RAW_COLNAME => array ('ID', 'NAME', 'DESCRIPTION', 'URL', 'LENGTH', 'CREATOR_ID', 'MTIME', 'UTIME', 'MIME', ),
+		BasePeer::TYPE_FIELDNAME => array ('id', 'name', 'description', 'url', 'length', 'creator_id', 'mtime', 'utime', 'mime', ),
+		BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, 7, 8, )
 	);
 
 	/**
@@ -86,12 +89,12 @@ abstract class BaseCcWebstreamPeer {
 	 * e.g. self::$fieldNames[BasePeer::TYPE_PHPNAME]['Id'] = 0
 	 */
 	private static $fieldKeys = array (
-		BasePeer::TYPE_PHPNAME => array ('DbId' => 0, 'DbName' => 1, 'DbDescription' => 2, 'DbUrl' => 3, 'DbLength' => 4, 'DbCreatorId' => 5, 'DbMtime' => 6, 'DbUtime' => 7, ),
-		BasePeer::TYPE_STUDLYPHPNAME => array ('dbId' => 0, 'dbName' => 1, 'dbDescription' => 2, 'dbUrl' => 3, 'dbLength' => 4, 'dbCreatorId' => 5, 'dbMtime' => 6, 'dbUtime' => 7, ),
-		BasePeer::TYPE_COLNAME => array (self::ID => 0, self::NAME => 1, self::DESCRIPTION => 2, self::URL => 3, self::LENGTH => 4, self::CREATOR_ID => 5, self::MTIME => 6, self::UTIME => 7, ),
-		BasePeer::TYPE_RAW_COLNAME => array ('ID' => 0, 'NAME' => 1, 'DESCRIPTION' => 2, 'URL' => 3, 'LENGTH' => 4, 'CREATOR_ID' => 5, 'MTIME' => 6, 'UTIME' => 7, ),
-		BasePeer::TYPE_FIELDNAME => array ('id' => 0, 'name' => 1, 'description' => 2, 'url' => 3, 'length' => 4, 'creator_id' => 5, 'mtime' => 6, 'utime' => 7, ),
-		BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, 7, )
+		BasePeer::TYPE_PHPNAME => array ('DbId' => 0, 'DbName' => 1, 'DbDescription' => 2, 'DbUrl' => 3, 'DbLength' => 4, 'DbCreatorId' => 5, 'DbMtime' => 6, 'DbUtime' => 7, 'DbMime' => 8, ),
+		BasePeer::TYPE_STUDLYPHPNAME => array ('dbId' => 0, 'dbName' => 1, 'dbDescription' => 2, 'dbUrl' => 3, 'dbLength' => 4, 'dbCreatorId' => 5, 'dbMtime' => 6, 'dbUtime' => 7, 'dbMime' => 8, ),
+		BasePeer::TYPE_COLNAME => array (self::ID => 0, self::NAME => 1, self::DESCRIPTION => 2, self::URL => 3, self::LENGTH => 4, self::CREATOR_ID => 5, self::MTIME => 6, self::UTIME => 7, self::MIME => 8, ),
+		BasePeer::TYPE_RAW_COLNAME => array ('ID' => 0, 'NAME' => 1, 'DESCRIPTION' => 2, 'URL' => 3, 'LENGTH' => 4, 'CREATOR_ID' => 5, 'MTIME' => 6, 'UTIME' => 7, 'MIME' => 8, ),
+		BasePeer::TYPE_FIELDNAME => array ('id' => 0, 'name' => 1, 'description' => 2, 'url' => 3, 'length' => 4, 'creator_id' => 5, 'mtime' => 6, 'utime' => 7, 'mime' => 8, ),
+		BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, 7, 8, )
 	);
 
 	/**
@@ -171,6 +174,7 @@ abstract class BaseCcWebstreamPeer {
 			$criteria->addSelectColumn(CcWebstreamPeer::CREATOR_ID);
 			$criteria->addSelectColumn(CcWebstreamPeer::MTIME);
 			$criteria->addSelectColumn(CcWebstreamPeer::UTIME);
+			$criteria->addSelectColumn(CcWebstreamPeer::MIME);
 		} else {
 			$criteria->addSelectColumn($alias . '.ID');
 			$criteria->addSelectColumn($alias . '.NAME');
@@ -180,6 +184,7 @@ abstract class BaseCcWebstreamPeer {
 			$criteria->addSelectColumn($alias . '.CREATOR_ID');
 			$criteria->addSelectColumn($alias . '.MTIME');
 			$criteria->addSelectColumn($alias . '.UTIME');
+			$criteria->addSelectColumn($alias . '.MIME');
 		}
 	}
 
diff --git a/airtime_mvc/application/models/airtime/om/BaseCcWebstreamQuery.php b/airtime_mvc/application/models/airtime/om/BaseCcWebstreamQuery.php
index b5bf09979..101bbfbd1 100644
--- a/airtime_mvc/application/models/airtime/om/BaseCcWebstreamQuery.php
+++ b/airtime_mvc/application/models/airtime/om/BaseCcWebstreamQuery.php
@@ -14,6 +14,7 @@
  * @method     CcWebstreamQuery orderByDbCreatorId($order = Criteria::ASC) Order by the creator_id column
  * @method     CcWebstreamQuery orderByDbMtime($order = Criteria::ASC) Order by the mtime column
  * @method     CcWebstreamQuery orderByDbUtime($order = Criteria::ASC) Order by the utime column
+ * @method     CcWebstreamQuery orderByDbMime($order = Criteria::ASC) Order by the mime column
  *
  * @method     CcWebstreamQuery groupByDbId() Group by the id column
  * @method     CcWebstreamQuery groupByDbName() Group by the name column
@@ -23,6 +24,7 @@
  * @method     CcWebstreamQuery groupByDbCreatorId() Group by the creator_id column
  * @method     CcWebstreamQuery groupByDbMtime() Group by the mtime column
  * @method     CcWebstreamQuery groupByDbUtime() Group by the utime column
+ * @method     CcWebstreamQuery groupByDbMime() Group by the mime column
  *
  * @method     CcWebstreamQuery leftJoin($relation) Adds a LEFT JOIN clause to the query
  * @method     CcWebstreamQuery rightJoin($relation) Adds a RIGHT JOIN clause to the query
@@ -43,6 +45,7 @@
  * @method     CcWebstream findOneByDbCreatorId(int $creator_id) Return the first CcWebstream filtered by the creator_id column
  * @method     CcWebstream findOneByDbMtime(string $mtime) Return the first CcWebstream filtered by the mtime column
  * @method     CcWebstream findOneByDbUtime(string $utime) Return the first CcWebstream filtered by the utime column
+ * @method     CcWebstream findOneByDbMime(string $mime) Return the first CcWebstream filtered by the mime column
  *
  * @method     array findByDbId(int $id) Return CcWebstream objects filtered by the id column
  * @method     array findByDbName(string $name) Return CcWebstream objects filtered by the name column
@@ -52,6 +55,7 @@
  * @method     array findByDbCreatorId(int $creator_id) Return CcWebstream objects filtered by the creator_id column
  * @method     array findByDbMtime(string $mtime) Return CcWebstream objects filtered by the mtime column
  * @method     array findByDbUtime(string $utime) Return CcWebstream objects filtered by the utime column
+ * @method     array findByDbMime(string $mime) Return CcWebstream objects filtered by the mime column
  *
  * @package    propel.generator.airtime.om
  */
@@ -359,6 +363,28 @@ abstract class BaseCcWebstreamQuery extends ModelCriteria
 		return $this->addUsingAlias(CcWebstreamPeer::UTIME, $dbUtime, $comparison);
 	}
 
+	/**
+	 * Filter the query on the mime column
+	 * 
+	 * @param     string $dbMime The value to use as filter.
+	 *            Accepts wildcards (* and % trigger a LIKE)
+	 * @param     string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
+	 *
+	 * @return    CcWebstreamQuery The current query, for fluid interface
+	 */
+	public function filterByDbMime($dbMime = null, $comparison = null)
+	{
+		if (null === $comparison) {
+			if (is_array($dbMime)) {
+				$comparison = Criteria::IN;
+			} elseif (preg_match('/[\%\*]/', $dbMime)) {
+				$dbMime = str_replace('*', '%', $dbMime);
+				$comparison = Criteria::LIKE;
+			}
+		}
+		return $this->addUsingAlias(CcWebstreamPeer::MIME, $dbMime, $comparison);
+	}
+
 	/**
 	 * Filter the query by a related CcSchedule object
 	 *
diff --git a/airtime_mvc/build/schema.xml b/airtime_mvc/build/schema.xml
index f44043bd1..0773a2675 100644
--- a/airtime_mvc/build/schema.xml
+++ b/airtime_mvc/build/schema.xml
@@ -422,5 +422,6 @@
     <column name="creator_id" phpName="DbCreatorId" type="INTEGER" required="true" />
     <column name="mtime" phpName="DbMtime" type="TIMESTAMP" size="6" required="true" />
     <column name="utime" phpName="DbUtime" type="TIMESTAMP" size="6" required="true" />
+    <column name="mime" phpName="DbMime" type="VARCHAR" />
   </table>
 </database>
diff --git a/airtime_mvc/build/sql/schema.sql b/airtime_mvc/build/sql/schema.sql
index c8d488f97..6fe02acf3 100644
--- a/airtime_mvc/build/sql/schema.sql
+++ b/airtime_mvc/build/sql/schema.sql
@@ -638,6 +638,7 @@ CREATE TABLE "cc_webstream"
 	"creator_id" INTEGER  NOT NULL,
 	"mtime" TIMESTAMP(6)  NOT NULL,
 	"utime" TIMESTAMP(6)  NOT NULL,
+	"mime" VARCHAR(255),
 	PRIMARY KEY ("id")
 );
 

From 8b13af2e04d61ff13f7f9ffbeb70e2debec221de Mon Sep 17 00:00:00 2001
From: James <james@sourcefabric-DX4840.(none)>
Date: Fri, 10 Aug 2012 12:14:15 -0400
Subject: [PATCH 03/17] fix bug on widget

---
 .../application/controllers/ApiController.php | 26 +++++++++----------
 airtime_mvc/application/models/Show.php       |  2 +-
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php
index 87002616c..12bcd5971 100644
--- a/airtime_mvc/application/controllers/ApiController.php
+++ b/airtime_mvc/application/controllers/ApiController.php
@@ -259,7 +259,7 @@ class ApiController extends Zend_Controller_Action
             $request = $this->getRequest();
             $type = $request->getParam('type');
             /* This is some *extremely* lazy programming that needs to bi fixed. For some reason
-             * we are using two entirely different codepaths for very similar functionality (type = endofday 
+             * we are using two entirely different codepaths for very similar functionality (type = endofday
              * vs type = interval). Needs to be fixed for 2.2 - MK */
             if ($type == "endofday") {
                 $limit = $request->getParam('limit');
@@ -275,25 +275,25 @@ class ApiController extends Zend_Controller_Action
                                 "nextShow"=>Application_Model_Show::getNextShows($utcTimeNow, $limit, $utcTimeEnd)
                             );
                 
-                Application_Model_Show::convertToLocalTimeZone($result["currentShow"], 
+                Application_Model_Show::convertToLocalTimeZone($result["currentShow"],
                         array("starts", "ends", "start_timestamp", "end_timestamp"));
-                Application_Model_Show::convertToLocalTimeZone($result["nextShow"], 
+                Application_Model_Show::convertToLocalTimeZone($result["nextShow"],
                         array("starts", "ends", "start_timestamp", "end_timestamp"));
             } else {
                 $result = Application_Model_Schedule::GetPlayOrderRange();
 
                 //Convert from UTC to localtime for Web Browser.
-                Application_Model_Show::ConvertToLocalTimeZone($result["currentShow"], 
+                Application_Model_Show::ConvertToLocalTimeZone($result["currentShow"],
                         array("starts", "ends", "start_timestamp", "end_timestamp"));
-                Application_Model_Show::ConvertToLocalTimeZone($result["nextShow"], 
+                Application_Model_Show::ConvertToLocalTimeZone($result["nextShow"],
                         array("starts", "ends", "start_timestamp", "end_timestamp"));
             }
 
             //used by caller to determine if the airtime they are running or widgets in use is out of date.
-            $result['AIRTIME_API_VERSION'] = AIRTIME_API_VERSION; 
+            $result['AIRTIME_API_VERSION'] = AIRTIME_API_VERSION;
             header("Content-type: text/javascript");
             
-            // If a callback is not given, then just provide the raw JSON. 
+            // If a callback is not given, then just provide the raw JSON.
             echo isset($_GET['callback']) ? $_GET['callback'].'('.json_encode($result).')' : json_encode($result);
         } else {
             header('HTTP/1.0 401 Unauthorized');
@@ -327,8 +327,8 @@ class ApiController extends Zend_Controller_Action
             }
         $result['AIRTIME_API_VERSION'] = AIRTIME_API_VERSION; //used by caller to determine if the airtime they are running or widgets in use is out of date.
             header("Content-type: text/javascript");
-            
-            // If a callback is not given, then just provide the raw JSON. 
+            Logging::log($result);
+            // If a callback is not given, then just provide the raw JSON.
             echo isset($_GET['callback']) ? $_GET['callback'].'('.json_encode($result).')' : json_encode($result);
         } else {
             header('HTTP/1.0 401 Unauthorized');
@@ -466,8 +466,8 @@ class ApiController extends Zend_Controller_Action
         $this->view->watched_dirs = $watchedDirsPath;
     }
 
-    public function dispatchMetadataAction($md, $mode, $dry_run=false) 
-    { 
+    public function dispatchMetadataAction($md, $mode, $dry_run=false)
+    {
         // Replace this compound result in a hash with proper error handling later on
         $return_hash = array();
         if ( $dry_run ) { // for debugging we return garbage not to screw around with the db
@@ -550,7 +550,7 @@ class ApiController extends Zend_Controller_Action
         }
         $return_hash['fileid'] = $file->getId();
         return $return_hash;
-    } 
+    }
 
     public function reloadMetadataGroupAction()
     {
@@ -595,7 +595,7 @@ class ApiController extends Zend_Controller_Action
             $response['key'] = $k;
             array_push($responses, $response);
             // On recorded show requests we do some extra work here. Not sure what it actually is and it
-            // was usually called from the python api client. Now we just call it straight from the controller to 
+            // was usually called from the python api client. Now we just call it straight from the controller to
             // save the http roundtrip
             if( $info_json['is_record'] and !array_key_exists('error', $response) ) {
                 $this->uploadRecordedActionParam($info_json['showinstanceid'],$info_json['fileid'],$dry_run=$dry);
diff --git a/airtime_mvc/application/models/Show.php b/airtime_mvc/application/models/Show.php
index adb86936c..874fe2402 100644
--- a/airtime_mvc/application/models/Show.php
+++ b/airtime_mvc/application/models/Show.php
@@ -1902,7 +1902,7 @@ class Application_Model_Show
         }
 
         //TODO, returning starts + ends twice (once with an alias). Unify this after the 2.0 release. --Martin
-        $sql = "SELECT si.starts as start_timestamp, si.ends as end_timestamp, s.name, s.id, si.id as instance_id, si.record, s.url, starts, ends"
+        $sql = "SELECT si.starts as start_timestamp, si.ends as end_timestamp, s.name, s.id, si.id as instance_id, si.record, s.url, starts, ends FROM"
         ." $CC_CONFIG[showInstances] si, $CC_CONFIG[showTable] s"
         ." WHERE si.show_id = s.id"
         ." AND si.starts >= TIMESTAMP '$timeStart'"

From 7acd4b362f529069e1b0d6667bda615763cf0e7d Mon Sep 17 00:00:00 2001
From: James <james@sourcefabric-DX4840.(none)>
Date: Fri, 10 Aug 2012 12:39:33 -0400
Subject: [PATCH 04/17] bug fix

- Length display was wrong
---
 airtime_mvc/application/models/Block.php | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/airtime_mvc/application/models/Block.php b/airtime_mvc/application/models/Block.php
index 63bbb0bc0..bcc7b2c62 100644
--- a/airtime_mvc/application/models/Block.php
+++ b/airtime_mvc/application/models/Block.php
@@ -1104,6 +1104,9 @@ EOT;
                 }
             } else {
                 $length = $this->getStaticLength();
+                if (!$length) {
+                    $length = "00:00:00";
+                }
                 $this->setLength($length);
             }
             $output['blockLength'] = $this->getFormattedLength();

From 35e3b3bc02f599f0fa356c30d84b8a9ff760df65 Mon Sep 17 00:00:00 2001
From: Martin Konecny <martin.konecny@gmail.com>
Date: Fri, 10 Aug 2012 12:40:28 -0400
Subject: [PATCH 05/17] CC-1665: Scheduled stream rebroadcasting and recording

-use mime type so that webstreams can play with invalid filenames
---
 .../controllers/AudiopreviewController.php    |  4 ++
 .../controllers/LibraryController.php         |  9 ++--
 .../controllers/WebstreamController.php       | 43 ++++++++++-------
 airtime_mvc/application/models/Webstream.php  | 47 +++++--------------
 .../scripts/audiopreview/audio-preview.phtml  |  1 +
 .../airtime/audiopreview/preview_jplayer.js   | 12 +++--
 6 files changed, 57 insertions(+), 59 deletions(-)

diff --git a/airtime_mvc/application/controllers/AudiopreviewController.php b/airtime_mvc/application/controllers/AudiopreviewController.php
index d667363df..e32ba730a 100644
--- a/airtime_mvc/application/controllers/AudiopreviewController.php
+++ b/airtime_mvc/application/controllers/AudiopreviewController.php
@@ -51,14 +51,18 @@ class AudiopreviewController extends Zend_Controller_Action
 
         if ($type == "audioclip") {
             $uri = "/api/get-media/file/".$audioFileID;
+            $media = Application_Model_StoredFile::Recall($audioFileID);
+            $mime = $media->getPropelOrm()->getDbMime();
         } else if ($type == "stream") {
             $webstream = CcWebstreamQuery::create()->findPk($audioFileID);
             $uri = $webstream->getDbUrl();
+            $mime = $webstream->getDbMime();
         } else {
             throw new Exception("Unknown type for audio preview!");
         }
 
         $this->view->uri = $uri;
+        $this->view->mime = $mime;
         $this->view->audioFileID = $audioFileID;
         $this->view->audioFileArtist = $audioFileArtist;
         $this->view->audioFileTitle = $audioFileTitle;
diff --git a/airtime_mvc/application/controllers/LibraryController.php b/airtime_mvc/application/controllers/LibraryController.php
index 067a33ac6..2748463f8 100644
--- a/airtime_mvc/application/controllers/LibraryController.php
+++ b/airtime_mvc/application/controllers/LibraryController.php
@@ -76,7 +76,7 @@ class LibraryController extends Zend_Controller_Action
                 $obj = new Application_Model_Playlist($id);
             } else {
                 $obj = new Application_Model_Block($id);
-                if (!$obj->isStatic()){
+                if (!$obj->isStatic()) {
                     unset($menu["play"]);
                 }
                 if (($isAdminOrPM || $obj->getCreatorId() == $user->getId()) && $screen == "playlist") {
@@ -96,7 +96,8 @@ class LibraryController extends Zend_Controller_Action
             }
         } else if ($type == "stream") {
 
-            $obj = new Application_Model_Webstream($id);
+            $webstream = CcWebstreamQuery::create()->findPK($id);
+            $obj = new Application_Model_Webstream($webstream);
             if (isset($this->obj_sess->id) && $screen == "playlist") {
                 if ($isAdminOrPM || $obj->getCreatorId() == $user->getId()) {
                     if ($this->obj_sess->type === "playlist") {
@@ -330,7 +331,9 @@ class LibraryController extends Zend_Controller_Action
                 }
                 $this->view->block = $block;
             } else if ($type == "stream") {
-                $file = new Application_Model_Webstream($id);
+                    
+                $webstream = CcWebstreamQuery::create()->findPK($id);
+                $file = new Application_Model_Webstream($webstream);
 
                 $md = $file->getMetadata();
 
diff --git a/airtime_mvc/application/controllers/WebstreamController.php b/airtime_mvc/application/controllers/WebstreamController.php
index 3e82ad47e..c7ed7d048 100644
--- a/airtime_mvc/application/controllers/WebstreamController.php
+++ b/airtime_mvc/application/controllers/WebstreamController.php
@@ -15,19 +15,19 @@ class WebstreamController extends Zend_Controller_Action
 
     public function newAction()
     {
-        $this->view->ws = new Application_Model_Webstream();
+
+        $webstream = new CcWebstream();
+
+        //we're not saving this primary key in the DB so it's OK
+        $webstream->setDbId(-1);
+        $webstream->setDbName("Untitled Webstream");
+        $webstream->setDbDescription("");
+        $webstream->setDbUrl("http://");
+        $webstream->setDbLength("00:00:00");
+        $webstream->setDbName("Untitled Webstream");
+
+        $this->view->ws = new Application_Model_Webstream($webstream);
         $this->view->html = $this->view->render('webstream/webstream.phtml');
-        /*
-        $pl_sess = $this->pl_sess;
-        $userInfo = Zend_Auth::getInstance()->getStorage()->read();
-
-        $pl = new Application_Model_Playlist();
-        $pl->setName("Untitled Playlist");
-        $pl->setPLMetaData('dc:creator', $userInfo->id);
-
-        $this->changePlaylist($pl->getId());
-        $this->createFullResponse($pl);
-        */
     }
 
     public function editAction()
@@ -39,7 +39,8 @@ class WebstreamController extends Zend_Controller_Action
             throw new Exception("Missing parameter 'id'"); 
         }
 
-        $this->view->ws = new Application_Model_Webstream($id);
+        $webstream = CcWebstreamQuery::create()->findPK($id);
+        $this->view->ws = new Application_Model_Webstream($webstream);
         $this->view->html = $this->view->render('webstream/webstream.phtml');
     }
 
@@ -52,8 +53,15 @@ class WebstreamController extends Zend_Controller_Action
         $hasPermission = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER, UTYPE_HOST));
         $id = $request->getParam("id");
 
-        if ($id != -1) {
-            $webstream = CcWebstreamQuery::create()->findPK($id);
+        $parameters = array();
+        $parameters['id'] = trim($request->getParam("id"));
+        $parameters['length'] = trim($request->getParam("length"));
+        $parameters['name'] = trim($request->getParam("name"));
+        $parameters['description'] = trim($request->getParam("description"));
+        $parameters['url'] = trim($request->getParam("url"));
+
+        if ($parameters['id'] != -1) {
+            $webstream = CcWebstreamQuery::create()->findPK($parameters['id']);
             //we are updating a playlist. Ensure that if the user is a host/dj, that he has the correct permission. 
             $user = Application_Model_User::getCurrentUser();
             if ($webstream->getDbCreatorId() != $user->getId()) {
@@ -67,15 +75,16 @@ class WebstreamController extends Zend_Controller_Action
             return;
         }
 
-        $analysis = Application_Model_Webstream::analyzeFormData($request);
+        $analysis = Application_Model_Webstream::analyzeFormData($parameters);
         try { 
             if (Application_Model_Webstream::isValid($analysis)) {
-                Application_Model_Webstream::save($request, $id);
+                Application_Model_Webstream::save($parameters);
                 $this->view->statusMessage = "<div class='success'>Webstream saved.</div>";
             } else {
                 throw new Exception();
             }
         } catch (Exception $e) {
+            Logging::log($e);
             $this->view->statusMessage = "<div class='errors'>Invalid form values.</div>"; 
             $this->view->analysis = $analysis;
         }
diff --git a/airtime_mvc/application/models/Webstream.php b/airtime_mvc/application/models/Webstream.php
index a33575a68..627b81978 100644
--- a/airtime_mvc/application/models/Webstream.php
+++ b/airtime_mvc/application/models/Webstream.php
@@ -4,22 +4,9 @@ class Application_Model_Webstream{
 
     private $id;
 
-    public function __construct($id=-1)
+    public function __construct($webstream)
     {
-        if ($id == -1) {
-            $this->webstream = new CcWebstream();
-
-            //We're not saving this object in the database, so -1 ID is OK.
-            $this->webstream->setDbId(-1);
-            $this->webstream->setDbName("Untitled Webstream");
-            $this->webstream->setDbDescription("");
-            $this->webstream->setDbUrl("http://");
-            $this->webstream->setDbLength("00:00:00");
-            $this->webstream->setDbName("Untitled Webstream");
-        } else {
-            $this->id = $id;
-            $this->webstream = CcWebstreamQuery::create()->findPK($this->id);
-        }
+            $this->webstream = $webstream; 
     }
 
     public function getOrm()
@@ -103,16 +90,15 @@ class Application_Model_Webstream{
         
         $leftOvers = array_diff($p_ids, $ownedStreams);
         return $leftOvers;
-        
     }
 
-    public static function analyzeFormData($request)
+    public static function analyzeFormData($parameters)
     {
         $valid = array("length" => array(true, ''), 
             "url" => array(true, ''),
             "name" => array(true, ''));
 
-        $length = trim($request->getParam("length"));
+        $length = $parameters["length"];
         $result = preg_match("/^([0-9]{1,2})h ([0-5][0-9])m$/", $length, $matches);
         if (!$result == 1 || !count($matches) == 3) { 
             $valid['length'][0] = false;
@@ -120,7 +106,7 @@ class Application_Model_Webstream{
         }
 
 
-        $url = trim($request->getParam("url"));
+        $url = $parameters["url"];
         //simple validator that checks to make sure that the url starts with http(s),
         //and that the domain is at least 1 letter long followed by a period.
         $result = preg_match("/^(http|https):\/\/.+\./", $url, $matches);
@@ -131,13 +117,13 @@ class Application_Model_Webstream{
         }
 
 
-        $name = trim($request->getParam("name"));
+        $name = $parameters["name"];
         if (strlen($name) == 0) {
             $valid['name'][0] = false;
             $valid['name'][1] = 'Webstream name cannot be empty';
         }
 
-        $id = trim($request->getParam("id"));
+        $id = $parameters["id"];
 
         if (!is_null($id)) {
             // user has performed a create stream action instead of edit
@@ -148,8 +134,6 @@ class Application_Model_Webstream{
             Logging::log("EDIT");
         }
 
-
-
         return $valid; 
     }
 
@@ -191,11 +175,11 @@ class Application_Model_Webstream{
         return $mime;
     }
 
-    public static function save($request, $id)
+    public static function save($parameters)
     {
         $userInfo = Zend_Auth::getInstance()->getStorage()->read();
 
-        $length = trim($request->getParam("length"));
+        $length = $parameters["length"];
         $result = preg_match("/^([0-9]{1,2})h ([0-5][0-9])m$/", $length, $matches);
 
         if ($result == 1 && count($matches) == 3) { 
@@ -209,22 +193,17 @@ class Application_Model_Webstream{
             throw new Exception("Invalid date format: $length");
         }
 
-
-        //$ws = new Application_Model_Webstream($id);
-        //$webstream = $ws->getOrm();
-
         $webstream = new CcWebstream();
-        $webstream->setDbName($request->getParam("name"));
-        $webstream->setDbDescription($request->getParam("description"));
-        $webstream->setDbUrl($request->getParam("url"));
+        $webstream->setDbName($parameters["name"]);
+        $webstream->setDbDescription($parameters["description"]);
+        $webstream->setDbUrl($parameters["url"]);
 
         $webstream->setDbLength($dblength);
         $webstream->setDbCreatorId($userInfo->id);
         $webstream->setDbUtime(new DateTime("now", new DateTimeZone('UTC')));
         $webstream->setDbMtime(new DateTime("now", new DateTimeZone('UTC')));
-        $webstream->save();
 
-        $ws = new Application_Model_Webstream($webstream->getDbId());
+        $ws = new Application_Model_Webstream($webstream);
        
         $mime = $ws->discoverStreamMime();
         if ($mime !== false) {
diff --git a/airtime_mvc/application/views/scripts/audiopreview/audio-preview.phtml b/airtime_mvc/application/views/scripts/audiopreview/audio-preview.phtml
index 447157a16..9cc956a4e 100644
--- a/airtime_mvc/application/views/scripts/audiopreview/audio-preview.phtml
+++ b/airtime_mvc/application/views/scripts/audiopreview/audio-preview.phtml
@@ -8,6 +8,7 @@
     <span class='blockIndex'><?php echo "$this->blockIndex" ?></span>
 <?php elseif (isset($this->uri)): ?>
     <span class='audioUri'><?php echo "$this->uri" ?></span>
+    <span class='audioMime'><?php echo "$this->mime" ?></span>
     <span class='audioFileTitle'><?php echo "$this->audioFileTitle" ?></span>
     <span class='audioFileArtist'><?php echo "$this->audioFileArtist" ?></span>
 <?php elseif (isset($this->showID)): ?>
diff --git a/airtime_mvc/public/js/airtime/audiopreview/preview_jplayer.js b/airtime_mvc/public/js/airtime/audiopreview/preview_jplayer.js
index a20f7421a..ad697a05f 100644
--- a/airtime_mvc/public/js/airtime/audiopreview/preview_jplayer.js
+++ b/airtime_mvc/public/js/airtime/audiopreview/preview_jplayer.js
@@ -36,6 +36,7 @@ $(document).ready(function(){
     $.jPlayer.timeFormat.showHour = true;
     
     var audioUri = $('.audioUri').text();
+    var audioMime = $('.audioMime').text();
     //var audioFileID = $('.audioFileID').text();
     var playlistID = $('.playlistID').text();
     var playlistIndex = $('.playlistIndex').text();
@@ -49,7 +50,7 @@ $(document).ready(function(){
     if (playlistID != "" && playlistID !== ""){
         playAllPlaylist(playlistID, playlistIndex);
     }else if (audioUri != "") {
-        playOne(audioUri);
+        playOne(audioUri, audioMime);
     }else if (showID != "") {
         playAllShow(showID, showIndex);
     }else if(blockId != "" && blockIndex != ""){
@@ -188,20 +189,21 @@ function play(p_playlistIndex){
  * Playing one audio track occurs from the library. This function will create the media, setup
  * jplayer and play the track.
  */
-function playOne(uri) {
+function playOne(uri, mime) {
     var playlist = new Array();
-    var fileExtension = uri.split('.').pop();
-    if (fileExtension.toLowerCase() === 'mp3') {
+    
+    if (mime.search(/mp3/i) > 0 || mime.search(/mpeg/i) > 0) {
         media = {title: $('.audioFileTitle').text() !== 'null' ?$('.audioFileTitle').text():"",
             artist: $('.audioFileArtist').text() !== 'null' ?$('.audioFileArtist').text():"",
             mp3:uri
         };
-    } else if (fileExtension.toLowerCase() === 'ogg' ) {
+    } else if (mime.search(/og(g|a)/i) > 0 || mime.search(/vorbis/i) > 0) {
         media = {title: $('.audioFileTitle').text() != 'null' ?$('.audioFileTitle').text():"",
             artist: $('.audioFileArtist').text() != 'null' ?$('.audioFileArtist').text():"",
             oga:uri
         };
     }
+
     _playlist_jplayer.option("autoPlay", true);
     playlist[0] = media;
     //_playlist_jplayer.setPlaylist(playlist); --if I use this the player will call _init on the setPlaylist and on the ready

From 27025c8ca2748123d6e2a8f6c431ccd580c800fb Mon Sep 17 00:00:00 2001
From: Martin Konecny <martin.konecny@gmail.com>
Date: Fri, 10 Aug 2012 12:42:56 -0400
Subject: [PATCH 06/17] CC-1665: Scheduled stream rebroadcasting and recording

-relax domain validator so we can use names like "localhost"
---
 airtime_mvc/application/models/Webstream.php | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/airtime_mvc/application/models/Webstream.php b/airtime_mvc/application/models/Webstream.php
index 627b81978..940989b72 100644
--- a/airtime_mvc/application/models/Webstream.php
+++ b/airtime_mvc/application/models/Webstream.php
@@ -107,9 +107,10 @@ class Application_Model_Webstream{
 
 
         $url = $parameters["url"];
-        //simple validator that checks to make sure that the url starts with http(s),
-        //and that the domain is at least 1 letter long followed by a period.
-        $result = preg_match("/^(http|https):\/\/.+\./", $url, $matches);
+        //simple validator that checks to make sure that the url starts with 
+        //http(s),
+        //and that the domain is at least 1 letter long
+        $result = preg_match("/^(http|https):\/\/.+/", $url, $matches);
 
         if ($result == 0) {
             $valid['url'][0] = false;

From 41320d0e5d08ea0534e012bd1b34b42c5a5f8f92 Mon Sep 17 00:00:00 2001
From: Martin Konecny <martin.konecny@gmail.com>
Date: Fri, 10 Aug 2012 12:52:36 -0400
Subject: [PATCH 07/17] CC-1665: Scheduled stream rebroadcasting and recording

-remove warning icons from playlists with streams
---
 .../application/views/scripts/playlist/update.phtml       | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/airtime_mvc/application/views/scripts/playlist/update.phtml b/airtime_mvc/application/views/scripts/playlist/update.phtml
index c876f1f26..5c73512cc 100644
--- a/airtime_mvc/application/views/scripts/playlist/update.phtml
+++ b/airtime_mvc/application/views/scripts/playlist/update.phtml
@@ -16,14 +16,14 @@ if ($item['type'] == 2) {
             <div class="big_play" audioFile="<?php echo $item["id"]; ?>">
                 <span class="ui-icon ui-icon-play"></span>
             </div>
+            <?php elseif ($item['type'] == 1 && $item['exists']): ?>
+            <div class="big_play ui-state-hover">
+                <span class="ui-icon ui-icon-play"></span>
+            </div>
             <?php elseif ($item['type'] == 2 && $item['exists']): ?>
             <div class="big_play ui-state-hover" blockId="<?php echo $item["item_id"]; ?>">
                 <span class="ui-icon ui-icon-alert"></span>
             </div>
-            <?php else: ?>
-            <div class="big_play ui-state-hover">
-                <span class="ui-icon ui-icon-alert"></span>
-            </div>
             <?php endif; ?>
             <div class="text-row top">
                 <span class="spl_playlength"><?php echo $item["length"] ?></span>

From d84ad78984c855aca18e145dfd35ee4af2422258 Mon Sep 17 00:00:00 2001
From: Martin Konecny <martin.konecny@gmail.com>
Date: Fri, 10 Aug 2012 12:53:22 -0400
Subject: [PATCH 08/17] CC-1665: Scheduled stream rebroadcasting and recording

-remove warning icons from playlists with streams
-play icons are now white, not orange
---
 airtime_mvc/application/views/scripts/playlist/update.phtml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/airtime_mvc/application/views/scripts/playlist/update.phtml b/airtime_mvc/application/views/scripts/playlist/update.phtml
index 5c73512cc..280437d87 100644
--- a/airtime_mvc/application/views/scripts/playlist/update.phtml
+++ b/airtime_mvc/application/views/scripts/playlist/update.phtml
@@ -17,7 +17,7 @@ if ($item['type'] == 2) {
                 <span class="ui-icon ui-icon-play"></span>
             </div>
             <?php elseif ($item['type'] == 1 && $item['exists']): ?>
-            <div class="big_play ui-state-hover">
+            <div class="big_play">
                 <span class="ui-icon ui-icon-play"></span>
             </div>
             <?php elseif ($item['type'] == 2 && $item['exists']): ?>

From 028f6636dd81d94aa6e5a68e721d9064c8aec0b8 Mon Sep 17 00:00:00 2001
From: Martin Konecny <martin.konecny@gmail.com>
Date: Fri, 10 Aug 2012 14:37:32 -0400
Subject: [PATCH 09/17] CC-1665: Scheduled stream rebroadcasting and recording

-fix right clicking in playlist builder to view metadata causing exception
---
 airtime_mvc/application/controllers/LibraryController.php | 5 ++---
 airtime_mvc/application/models/Webstream.php              | 3 +--
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/airtime_mvc/application/controllers/LibraryController.php b/airtime_mvc/application/controllers/LibraryController.php
index f291c1bdc..2bfa074f7 100644
--- a/airtime_mvc/application/controllers/LibraryController.php
+++ b/airtime_mvc/application/controllers/LibraryController.php
@@ -333,11 +333,10 @@ class LibraryController extends Zend_Controller_Action
                 }
                 $this->view->block = $block;
             } else if ($type == "stream") {
-                    
                 $webstream = CcWebstreamQuery::create()->findPK($id);
-                $file = new Application_Model_Webstream($webstream);
+                $ws = new Application_Model_Webstream($webstream);
 
-                $md = $file->getMetadata();
+                $md = $ws->getMetadata();
 
                 $this->view->md = $md;
                 $this->view->type = $type;
diff --git a/airtime_mvc/application/models/Webstream.php b/airtime_mvc/application/models/Webstream.php
index 940989b72..cdbd14af0 100644
--- a/airtime_mvc/application/models/Webstream.php
+++ b/airtime_mvc/application/models/Webstream.php
@@ -53,8 +53,7 @@ class Application_Model_Webstream{
 
     public function getMetadata()
     {
-        $webstream = CcWebstreamQuery::create()->findPK($this->id);
-        $subjs = CcSubjsQuery::create()->findPK($webstream->getDbCreatorId());
+        $subjs = CcSubjsQuery::create()->findPK($this->webstream->getDbCreatorId());
 
         $username = $subjs->getDbLogin();
         return array(

From 09897064c67e5eb8009b364e48b56ea1fcf84bf8 Mon Sep 17 00:00:00 2001
From: James <james@sourcefabric-DX4840.(none)>
Date: Mon, 13 Aug 2012 10:59:21 -0400
Subject: [PATCH 10/17] CC-4215: Smart Playlist: Exception happens when
 generate with criteria Length is 2012-08-10 14:00:00

- fixed
---
 airtime_mvc/application/models/Block.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/airtime_mvc/application/models/Block.php b/airtime_mvc/application/models/Block.php
index 286a7735c..cca9b63c5 100644
--- a/airtime_mvc/application/models/Block.php
+++ b/airtime_mvc/application/models/Block.php
@@ -976,7 +976,7 @@ EOT;
                 $column = CcFilesPeer::getTableMap()->getColumnByPhpName(self::$criteria2PeerMap[$d['sp_criteria_field']]);
                 // validation on type of column
                 if ($d['sp_criteria_field'] == 'length') {
-                    if (!preg_match("/(\d{2}):(\d{2}):(\d{2})/", $d['sp_criteria_value'])) {
+                    if (!preg_match("/^(\d{2}):(\d{2}):(\d{2})$/", $d['sp_criteria_value'])) {
                         $error[] =  "'Length' should be in '00:00:00' format";
                     }
                 } else if ($column->getType() == PropelColumnTypes::TIMESTAMP) {

From 7cd814da064c01693283624f3a69896419b5fdfc Mon Sep 17 00:00:00 2001
From: Martin Konecny <martin.konecny@gmail.com>
Date: Mon, 13 Aug 2012 11:04:21 -0400
Subject: [PATCH 11/17] airtime-check-system not using user define port in all
 cases

---
 utils/airtime-check-system.php | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/utils/airtime-check-system.php b/utils/airtime-check-system.php
index 22ff7362c..fa244f3b3 100644
--- a/utils/airtime-check-system.php
+++ b/utils/airtime-check-system.php
@@ -17,7 +17,7 @@ if (substr($sapi_type, 0, 3) == 'cli') {
 
 
     $status = AirtimeCheck::GetStatus($baseUrl, $base_port, $apiKey);
-    AirtimeCheck::PrintStatus($baseUrl, $status);
+    AirtimeCheck::PrintStatus($baseUrl, $base_port, $status);
 }
 
 class AirtimeCheck {
@@ -92,8 +92,9 @@ class AirtimeCheck {
         return $os_string." ".$machine;
     }
     
-    public static function GetServerType($p_baseUrl){
-        $headerInfo = get_headers("http://$p_baseUrl",1);
+    public static function GetServerType($p_baseUrl, $p_basePort)
+    {
+        $headerInfo = get_headers("http://$p_baseUrl:$p_basePort",1);
         
         if (!isset($headerInfo['Server'][0]))
             return self::UNKNOWN;
@@ -120,7 +121,7 @@ class AirtimeCheck {
         return $data;
     }
 
-    public static function PrintStatus($p_baseUrl, $p_status){
+    public static function PrintStatus($p_baseUrl, $p_basePort, $p_status){
         
         if ($p_status === false){
             self::output_status("AIRTIME_SERVER_RESPONDING", "FAILED");
@@ -150,7 +151,7 @@ class AirtimeCheck {
             }
             self::output_status("OS", self::CheckOsTypeVersion());
             self::output_status("CPU", self::GetCpuInfo());
-            self::output_status("WEB_SERVER", self::GetServerType($p_baseUrl));
+            self::output_status("WEB_SERVER", self::GetServerType($p_baseUrl, $p_basePort));
             
             if (isset($data->services)) {
                 $services = $data->services;

From 8055a9c80b00e2ed3a25faa328b51e8b25a5ce71 Mon Sep 17 00:00:00 2001
From: James <james@sourcefabric-DX4840.(none)>
Date: Mon, 13 Aug 2012 11:18:15 -0400
Subject: [PATCH 12/17] CC-4214: Smart Playlist -> Criteria about datetime:
 Please convert the searched value from local time to UTC

- fixed
---
 airtime_mvc/application/models/Block.php | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/airtime_mvc/application/models/Block.php b/airtime_mvc/application/models/Block.php
index cca9b63c5..bca194d20 100644
--- a/airtime_mvc/application/models/Block.php
+++ b/airtime_mvc/application/models/Block.php
@@ -1301,9 +1301,16 @@ EOT;
                 foreach ($crit as $criteria) {
                     $spCriteriaPhpName = self::$criteria2PeerMap[$criteria['criteria']];
                     $spCriteria = $criteria['criteria'];
-        
                     $spCriteriaModifier = $criteria['modifier'];
-                    $spCriteriaValue = $criteria['value'];
+                    
+                    $column = CcFilesPeer::getTableMap()->getColumnByPhpName(self::$criteria2PeerMap[$spCriteria]);
+                    // if the column is timestamp, convert it into UTC
+                    if ($column->getType() == PropelColumnTypes::TIMESTAMP) {
+                        $spCriteriaValue = Application_Common_DateHelper::ConvertToUtcDateTimeString($criteria['value']);
+                    } else {
+                        $spCriteriaValue = $criteria['value'];
+                    }
+                    
                     if ($spCriteriaModifier == "starts with") {
                         $spCriteriaValue = "$spCriteriaValue%";
                     } else if ($spCriteriaModifier == "ends with") {

From 1bd94a0757541692e0406a1d33927f4c4063bc29 Mon Sep 17 00:00:00 2001
From: James <james@sourcefabric-DX4840.(none)>
Date: Mon, 13 Aug 2012 11:32:06 -0400
Subject: [PATCH 13/17] CC-4212: Smart Playlist: The formats of 'Bit Rate' are
 not matched between Media Library and Criteria

- fixed
---
 airtime_mvc/application/models/Block.php | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/airtime_mvc/application/models/Block.php b/airtime_mvc/application/models/Block.php
index bca194d20..b16ce7e5d 100644
--- a/airtime_mvc/application/models/Block.php
+++ b/airtime_mvc/application/models/Block.php
@@ -1307,6 +1307,10 @@ EOT;
                     // if the column is timestamp, convert it into UTC
                     if ($column->getType() == PropelColumnTypes::TIMESTAMP) {
                         $spCriteriaValue = Application_Common_DateHelper::ConvertToUtcDateTimeString($criteria['value']);
+                    } else if($spCriteria == "bit_rate") {
+                        // multiply 1000 because we store only number value
+                        // e.g 192kps is stored as 192000
+                        $spCriteriaValue = $criteria['value']*1000;
                     } else {
                         $spCriteriaValue = $criteria['value'];
                     }

From 19c90e66880adc18970d7efbca0831bfc1281b79 Mon Sep 17 00:00:00 2001
From: James <james@sourcefabric-DX4840.(none)>
Date: Mon, 13 Aug 2012 11:42:48 -0400
Subject: [PATCH 14/17] CC-4204: Dynamic Smart Playlist: Set limit to 500
 minutes and click Save will froze the Browser

- fixed
---
 airtime_mvc/application/models/Block.php | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/airtime_mvc/application/models/Block.php b/airtime_mvc/application/models/Block.php
index b16ce7e5d..2025e39a4 100644
--- a/airtime_mvc/application/models/Block.php
+++ b/airtime_mvc/application/models/Block.php
@@ -277,7 +277,12 @@ EOT;
         } else {
             $value = str_pad($value, 2, "0", STR_PAD_LEFT);
             if ($modifier == "minutes") {
-                $length = "00:".$value.":00";
+                $hour = "00";
+                if ($value >59) {
+                    $hour = intval($value/60);
+                    $value = $value%60;
+                }
+                $length = $hour.":".$value.":00";
             } else if ($modifier == "hours") {
                 $length = $value.":00:00";
             }

From 1e36d778578451175014a6ff3f7f122c710adbde Mon Sep 17 00:00:00 2001
From: James <james@sourcefabric-DX4840.(none)>
Date: Mon, 13 Aug 2012 11:51:25 -0400
Subject: [PATCH 15/17] CC-4213: Smart Playlist -> Criteria Bpm: Cannot find
 track by 'is in the range'

- changed BPM to string type
---
 airtime_mvc/application/forms/SmartBlockCriteria.php            | 2 +-
 airtime_mvc/public/js/airtime/playlist/smart_playlistbuilder.js | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/airtime_mvc/application/forms/SmartBlockCriteria.php b/airtime_mvc/application/forms/SmartBlockCriteria.php
index 55abc296a..016105740 100644
--- a/airtime_mvc/application/forms/SmartBlockCriteria.php
+++ b/airtime_mvc/application/forms/SmartBlockCriteria.php
@@ -42,7 +42,7 @@ class Application_Form_SmartBlockCriteria extends Zend_Form_SubForm
             "album_title" => "s",
             "artist_name" => "s",
             "bit_rate" => "n",
-            "bpm" => "n",
+            "bpm" => "s",
             "comments" => "s",
             "composer" => "s",
             "conductor" => "s",
diff --git a/airtime_mvc/public/js/airtime/playlist/smart_playlistbuilder.js b/airtime_mvc/public/js/airtime/playlist/smart_playlistbuilder.js
index 1a9a5b85b..81dadd729 100644
--- a/airtime_mvc/public/js/airtime/playlist/smart_playlistbuilder.js
+++ b/airtime_mvc/public/js/airtime/playlist/smart_playlistbuilder.js
@@ -568,7 +568,7 @@ var criteriaTypes = {
     "album_title" : "s",
     "artist_name" : "s",
     "bit_rate" : "n",
-    "bpm" : "n",
+    "bpm" : "s",
     "comments" : "s",
     "composer" : "s",
     "conductor" : "s",

From db3a9357f96b5f8af23cfcfca2c3bd51e9e13748 Mon Sep 17 00:00:00 2001
From: James <james@sourcefabric-DX4840.(none)>
Date: Mon, 13 Aug 2012 11:59:28 -0400
Subject: [PATCH 16/17] CC-4211: Smart Playlist: length of dynamic block wont
 be convert to hh:mm:ss if set limit as float number, such as 23.999

- fixed
---
 airtime_mvc/application/models/Block.php | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/airtime_mvc/application/models/Block.php b/airtime_mvc/application/models/Block.php
index 2025e39a4..bb7f50a9e 100644
--- a/airtime_mvc/application/models/Block.php
+++ b/airtime_mvc/application/models/Block.php
@@ -275,17 +275,24 @@ EOT;
         if ($modifier == "items") {
             $length = $value." ".$modifier;
         } else {
-            $value = str_pad($value, 2, "0", STR_PAD_LEFT);
+            $hour = "00";
             if ($modifier == "minutes") {
-                $hour = "00";
                 if ($value >59) {
                     $hour = intval($value/60);
                     $value = $value%60;
+                    
                 }
-                $length = $hour.":".$value.":00";
             } else if ($modifier == "hours") {
-                $length = $value.":00:00";
+                $mins = $value * 60;
+                if ($mins >59) {
+                    $hour = intval($mins/60);
+                    $hour = str_pad($hour, 2, "0", STR_PAD_LEFT);
+                    $value = $mins%60;
+                }
             }
+            $hour = str_pad($hour, 2, "0", STR_PAD_LEFT);
+            $value = str_pad($value, 2, "0", STR_PAD_LEFT);
+            $length = $hour.":".$value.":00";
         }
         return $length;
     }

From dad8762f4f9e3780f1c7758372040858ec2d87cb Mon Sep 17 00:00:00 2001
From: James <james@sourcefabric-DX4840.(none)>
Date: Mon, 13 Aug 2012 12:31:49 -0400
Subject: [PATCH 17/17] CC-4209: Smart Playlist: 'Processing' wont disappear
 after clicking Generate during 'File import in progress'

- fixed
---
 airtime_mvc/application/controllers/LibraryController.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/airtime_mvc/application/controllers/LibraryController.php b/airtime_mvc/application/controllers/LibraryController.php
index 2bfa074f7..de175004d 100644
--- a/airtime_mvc/application/controllers/LibraryController.php
+++ b/airtime_mvc/application/controllers/LibraryController.php
@@ -268,7 +268,7 @@ class LibraryController extends Zend_Controller_Action
                 Logging::log($data['MDATA_KEY_FILEPATH']);
                 Application_Model_RabbitMq::SendMessageToMediaMonitor("md_update", $data);
 
-                $this->_redirect('playlist/index');
+                $this->_redirect('Playlist');
             }
         }