diff --git a/airtime_mvc/application/Bootstrap.php b/airtime_mvc/application/Bootstrap.php
index 7edb8b0ea..b6c3440ed 100644
--- a/airtime_mvc/application/Bootstrap.php
+++ b/airtime_mvc/application/Bootstrap.php
@@ -31,6 +31,7 @@ require_once "Auth.php";
 require_once "interface/OAuth2.php";
 require_once "TaskManager.php";
 require_once "UsabilityHints.php";
+require_once __DIR__.'/models/formatters/LengthFormatter.php';
 require_once __DIR__.'/services/CeleryService.php';
 require_once __DIR__.'/services/SoundcloudService.php';
 require_once __DIR__.'/forms/helpers/ValidationTypes.php';
diff --git a/airtime_mvc/application/configs/ACL.php b/airtime_mvc/application/configs/ACL.php
index 39bba31ae..bbd10bd7d 100644
--- a/airtime_mvc/application/configs/ACL.php
+++ b/airtime_mvc/application/configs/ACL.php
@@ -16,6 +16,7 @@ $ccAcl->add(new Zend_Acl_Resource('library'))
       ->add(new Zend_Acl_Resource('error'))
       ->add(new Zend_Acl_Resource('login'))
       ->add(new Zend_Acl_Resource('whmcs-login'))
+      ->add(new Zend_Acl_Resource('new-playlist'))
       ->add(new Zend_Acl_Resource('playlist'))
       ->add(new Zend_Acl_Resource('plupload'))
       ->add(new Zend_Acl_Resource('schedule'))
@@ -30,6 +31,7 @@ $ccAcl->add(new Zend_Acl_Resource('library'))
       ->add(new Zend_Acl_Resource('listenerstat'))
       ->add(new Zend_Acl_Resource('usersettings'))
       ->add(new Zend_Acl_Resource('audiopreview'))
+      ->add(new Zend_Acl_Resource('new-webstream'))
       ->add(new Zend_Acl_Resource('webstream'))
       ->add(new Zend_Acl_Resource('locale'))
       ->add(new Zend_Acl_Resource('upgrade'))
@@ -55,6 +57,7 @@ $ccAcl->allow('G', 'index')
       ->allow('G', 'schedule')
       ->allow('G', 'dashboard')
       ->allow('G', 'audiopreview')
+      ->allow('G', 'new-webstream')
       ->allow('G', 'webstream')
       ->allow('G', 'locale')
       ->allow('G', 'upgrade')
@@ -69,6 +72,7 @@ $ccAcl->allow('G', 'index')
       ->allow('H', 'usersettings')
       ->allow('H', 'plupload')
       ->allow('H', 'library')
+      ->allow('H', 'new-playlist')
       ->allow('H', 'playlist')
       ->allow('H', 'playouthistory')
       ->allow('A', 'playouthistorytemplate')
diff --git a/airtime_mvc/application/controllers/NewPlaylistController.php b/airtime_mvc/application/controllers/NewPlaylistController.php
new file mode 100644
index 000000000..f26a5d9c0
--- /dev/null
+++ b/airtime_mvc/application/controllers/NewPlaylistController.php
@@ -0,0 +1,643 @@
+<?php
+
+class NewPlaylistController extends Zend_Controller_Action
+{
+
+    public function init()
+    {
+        $ajaxContext = $this->_helper->getHelper('AjaxContext');
+        $ajaxContext->addActionContext('add-items', 'json')
+                    ->addActionContext('move-items', 'json')
+                    ->addActionContext('delete-items', 'json')
+                    ->addActionContext('set-fade', 'json')
+                    ->addActionContext('set-crossfade', 'json')
+                    ->addActionContext('set-cue', 'json')
+                    ->addActionContext('new', 'json')
+                    ->addActionContext('edit', 'json')
+                    ->addActionContext('delete', 'json')
+                    ->addActionContext('close-playlist', 'json')
+                    ->addActionContext('play', 'json')
+                    ->addActionContext('set-playlist-fades', 'json')
+                    ->addActionContext('get-playlist-fades', 'json')
+                    ->addActionContext('set-playlist-name', 'json')
+                    ->addActionContext('set-playlist-description', 'json')
+                    ->addActionContext('playlist-preview', 'json')
+                    ->addActionContext('get-playlist', 'json')
+                    ->addActionContext('save', 'json')
+                    ->addActionContext('smart-block-generate', 'json')
+                    ->addActionContext('smart-block-shuffle', 'json')
+                    ->addActionContext('get-block-info', 'json')
+                    ->addActionContext('shuffle', 'json')
+                    ->addActionContext('empty-content', 'json')
+                    ->initContext();
+
+        //This controller writes to the session all over the place, so we're going to reopen it for writing here.
+        session_start(); //Reopen the session for writing
+    }
+
+    private function getPlaylist($p_type)
+    {
+        $obj = null;
+        $objInfo = Application_Model_Library::getObjInfo($p_type);
+
+        $obj_sess = new Zend_Session_Namespace(UI_PLAYLISTCONTROLLER_OBJ_SESSNAME);
+
+        if (isset($obj_sess->id)) {
+            $obj = new $objInfo['className']($obj_sess->id);
+
+            $modified = $this->_getParam('modified', null);
+            if ($obj->getLastModified("U") !== $modified) {
+                $this->createFullResponse($obj);
+                throw new PlaylistOutDatedException(sprintf(_("You are viewing an older version of %s"), $obj->getName()));
+            }
+        }
+
+        return $obj;
+    }
+
+    private function createUpdateResponse($obj)
+    {
+        $formatter = new LengthFormatter($obj->getLength());
+        $this->view->length = $formatter->format();
+
+        $this->view->obj = $obj;
+        $this->view->contents = $obj->getContents();
+        $this->view->html = $this->view->render('playlist/update.phtml');
+        $this->view->name = $obj->getName();
+        $this->view->description = $obj->getDescription();
+        $this->view->modified = $obj->getLastModified("U");
+
+        unset($this->view->obj);
+    }
+
+    private function createFullResponse($obj = null, $isJson = false,
+        $formIsValid = false)
+    {
+        $isBlock = false;
+        $viewPath = 'playlist/_playlist.phtml';
+        if ($obj instanceof Application_Model_Block) {
+            $isBlock = true;
+            $viewPath = 'playlist/_smart-block.phtml';
+        }
+        if (isset($obj)) {
+            $formatter = new LengthFormatter($obj->getLength());
+            $this->view->length = $formatter->format();
+
+            if ($isBlock) {
+                $form = new Application_Form_SmartBlockCriteria();
+                $form->removeDecorator('DtDdWrapper');
+                $form->startForm($obj->getId(), $formIsValid);
+
+                $this->view->form = $form;
+                $this->view->obj = $obj;
+                $this->view->id = $obj->getId();
+
+                if ($isJson) {
+                    return $this->view->render($viewPath);
+                } else {
+                    $this->view->html = $this->view->render($viewPath);
+                }
+            } else {
+                $this->view->obj = $obj;
+                $this->view->id = $obj->getId();
+                if ($isJson) {
+                    return $this->view->html = $this->view->render($viewPath);
+                } else {
+                    $this->view->html = $this->view->render($viewPath);
+                }
+                unset($this->view->obj);
+            }
+        } else {
+            if ($isJson) {
+                return $this->view->render($viewPath);
+            } else {
+                $this->view->html = $this->view->render($viewPath);
+            }
+        }
+    }
+
+    private function playlistOutdated($e)
+    {
+        $this->view->error = $e->getMessage();
+    }
+
+    private function blockDynamic($obj)
+    {
+        $this->view->error = _("You cannot add tracks to dynamic blocks.");
+        $this->createFullResponse($obj);
+    }
+
+    private function playlistNotFound($p_type, $p_isJson = false)
+    {
+        $p_type = ucfirst($p_type);
+        $this->view->error = sprintf(_("%s not found"), $p_type);
+
+        Logging::info("{$p_type} not found");
+        Application_Model_Library::changePlaylist(null, $p_type);
+        
+        if (!$p_isJson) {
+            $this->createFullResponse(null);
+        } else {
+            $this->_helper->json->sendJson(array("error"=>$this->view->error, "result"=>1, "html"=>$this->createFullResponse(null, $p_isJson)));
+        }
+    }
+
+    private function playlistNoPermission($p_type)
+    {
+        $this->view->error = sprintf(_("You don't have permission to delete selected %s(s)."), $p_type);
+        $this->changePlaylist(null, $p_type);
+        $this->createFullResponse(null);
+    }
+
+    private function playlistUnknownError($e)
+    {
+        $this->view->error = _("Something went wrong.");
+        Logging::info($e->getMessage());
+    }
+
+    private function wrongTypeToBlock($obj)
+    {
+        $this->view->error = _("You can only add tracks to smart block.");
+        $this->createFullResponse($obj);
+    }
+
+    private function wrongTypeToPlaylist($obj)
+    {
+        $this->view->error = _("You can only add tracks, smart blocks, and webstreams to playlists.");
+        $this->createFullResponse($obj);
+    }
+
+    public function newAction()
+    {
+        //$pl_sess = $this->pl_sess;
+        $userInfo = Zend_Auth::getInstance()->getStorage()->read();
+        $type = $this->_getParam('type');
+
+        $objInfo = Application_Model_Library::getObjInfo($type);
+
+        $name = _('Untitled Playlist');
+        if ($type == 'block') {
+            $name = _('Untitled Smart Block');
+        }
+
+        $obj = new $objInfo['className']();
+        $obj->setName($name);
+        $obj->setMetadata('dc:creator', $userInfo->id);
+
+        Application_Model_Library::changePlaylist($obj->getId(), $type);
+        $this->createFullResponse($obj);
+    }
+
+    public function editAction()
+    {
+        $id = $this->_getParam('id', null);
+        $type = $this->_getParam('type');
+        $objInfo = Application_Model_Library::getObjInfo($type);
+        Logging::info("editing {$type} {$id}");
+
+        if (!is_null($id)) {
+            Application_Model_Library::changePlaylist($id, $type);
+        }
+
+        try {
+            $obj = new $objInfo['className']($id);
+            $this->createFullResponse($obj);
+        } catch (PlaylistNotFoundException $e) {
+            $this->playlistNotFound();
+        } catch (Exception $e) {
+            $this->playlistUnknownError($e);
+        }
+    }
+
+    public function deleteAction()
+    {
+        $ids  = $this->_getParam('ids');
+        $ids  = (!is_array($ids)) ? array($ids) : $ids;
+        $type = $this->_getParam('type');
+
+        $obj      = null;
+
+        $objInfo  = Application_Model_Library::getObjInfo($type);
+
+        $userInfo = Zend_Auth::getInstance()->getStorage()->read();
+
+        $obj_sess = new Zend_Session_Namespace(
+            UI_PLAYLISTCONTROLLER_OBJ_SESSNAME);
+
+        try {
+            Logging::info("Currently active {$type} {$obj_sess->id}");
+            if (in_array($obj_sess->id, $ids)) {
+                Logging::info("Deleting currently active {$type}");
+                Application_Model_Library::changePlaylist(null, $type);
+            } else {
+                Logging::info("Not deleting currently active {$type}");
+                $obj = new $objInfo['className']($obj_sess->id);
+            }
+
+            if (strcmp($objInfo['className'], 'Application_Model_Playlist')==0) {
+                Application_Model_Playlist::deletePlaylists($ids, $userInfo->id);
+            } else {
+                Application_Model_Block::deleteBlocks($ids, $userInfo->id);
+            }
+            $this->createFullResponse($obj);
+        } catch (PlaylistNoPermissionException $e) {
+            $this->playlistNoPermission($type);
+        } catch (BlockNoPermissionException $e) {
+            $this->playlistNoPermission($type);
+        } catch (PlaylistNotFoundException $e) {
+            $this->playlistNotFound($type);
+        } catch (Exception $e) {
+            $this->playlistUnknownError($e);
+        }
+    }
+
+    public function closePlaylistAction() {
+        $type = $this->_getParam('type');
+        $obj = null;
+        Application_Model_Library::changePlaylist($obj, $type);
+        $this->createFullResponse($obj);
+    }
+
+    public function addItemsAction()
+    {
+        $ids = $this->_getParam('aItems', array());
+        $ids = (!is_array($ids)) ? array($ids) : $ids;
+        $afterItem = $this->_getParam('afterItem', null);
+        $addType = $this->_getParam('type', 'after');
+        // this is the obj type of destination
+        $obj_type = $this->_getParam('obj_type');
+
+        try {
+            $obj = $this->getPlaylist($obj_type);
+            if ($obj_type == 'playlist') {
+                foreach ($ids as $id) {
+                    if (is_array($id) && isset($id[1])) {
+                        if ($id[1] == 'playlist') {
+                            throw new WrongTypeToPlaylistException;
+                        }
+                    }
+                }
+                $obj->addAudioClips($ids, $afterItem, $addType);
+            } elseif ($obj->isStatic()) {
+                // if the dest is a block object
+                //check if any items are playlists
+                foreach ($ids as $id) {
+                    if (is_array($id) && isset($id[1])) {
+                        if ($id[1] != 'audioclip') {
+                            throw new WrongTypeToBlockException;
+                        }
+                    }
+                }
+                $obj->addAudioClips($ids, $afterItem, $addType);
+            } else {
+                throw new BlockDynamicException;
+            }
+            $this->createUpdateResponse($obj);
+        } catch (PlaylistOutDatedException $e) {
+            $this->playlistOutdated($e);
+        } catch (PlaylistNotFoundException $e) {
+            $this->playlistNotFound($obj_type);
+        } catch (WrongTypeToBlockException $e) {
+            $this->wrongTypeToBlock($obj);
+        } catch (WrongTypeToPlaylistException $e) {
+            $this->wrongTypeToPlaylist($obj);
+        } catch (BlockDynamicException $e) {
+            $this->blockDynamic($obj);
+        } catch (BlockNotFoundException $e) {
+            $this->playlistNotFound($obj_type);
+        } catch (Exception $e) {
+            $this->playlistUnknownError($e);
+        }
+    }
+
+    public function moveItemsAction()
+    {
+        $ids = $this->_getParam('ids');
+        $ids = (!is_array($ids)) ? array($ids) : $ids;
+        $afterItem = $this->_getParam('afterItem', null);
+        $type = $this->_getParam('obj_type');
+
+        try {
+            $obj = $this->getPlaylist($type);
+            $obj->moveAudioClips($ids, $afterItem);
+            $this->createUpdateResponse($obj);
+        } catch (PlaylistOutDatedException $e) {
+            $this->playlistOutdated($e);
+        } catch (PlaylistNotFoundException $e) {
+            $this->playlistNotFound($type);
+        } catch (Exception $e) {
+            $this->playlistUnknownError($e);
+        }
+    }
+
+    public function deleteItemsAction()
+    {
+        $ids = $this->_getParam('ids');
+        $ids = (!is_array($ids)) ? array($ids) : $ids;
+        $modified = $this->_getParam('modified');
+        $type = $this->_getParam('obj_type');
+
+        try {
+            $obj = $this->getPlaylist($type);
+            $obj->delAudioClips($ids);
+            $this->createUpdateResponse($obj);
+        } catch (PlaylistOutDatedException $e) {
+            $this->playlistOutdated($e);
+        } catch (PlaylistNotFoundException $e) {
+            $this->playlistNotFound($type);
+        } catch (Exception $e) {
+            $this->playlistUnknownError($e);
+        }
+    }
+    
+    public function emptyContentAction()
+    {
+        $type = $this->_getParam('obj_type');
+        try {
+            $obj = $this->getPlaylist($type);
+            if ($type == 'playlist') {
+                $obj->deleteAllFilesFromPlaylist();
+            } else {
+                $obj->deleteAllFilesFromBlock();
+            }
+            $this->createUpdateResponse($obj);
+        } catch (PlaylistOutDatedException $e) {
+            $this->playlistOutdated($e);
+        } catch (PlaylistNotFoundException $e) {
+            $this->playlistNotFound($type);
+        } catch (Exception $e) {
+            $this->playlistUnknownError($e);
+        }
+    }
+
+    public function setCueAction()
+    {
+        $id = $this->_getParam('id');
+        $cueIn = $this->_getParam('cueIn', null);
+        $cueOut = $this->_getParam('cueOut', null);
+        $type = $this->_getParam('type');
+
+        try {
+            $obj = $this->getPlaylist($type);
+            $response = $obj->changeClipLength($id, $cueIn, $cueOut);
+
+            if (!isset($response["error"])) {
+                $this->view->response = $response;
+                $this->createUpdateResponse($obj);
+            } else {
+                $this->view->cue_error = $response["error"];
+                $this->view->code = $response["type"];
+            }
+        } catch (PlaylistOutDatedException $e) {
+            $this->playlistOutdated($e);
+        } catch (PlaylistNotFoundException $e) {
+            $this->playlistNotFound($type);
+        } catch (Exception $e) {
+            $this->playlistUnknownError($e);
+        }
+    }
+
+    public function setFadeAction()
+    {
+        $id = $this->_getParam('id');
+        $fadeIn = $this->_getParam('fadeIn', null);
+        $fadeOut = $this->_getParam('fadeOut', null);
+        $type = $this->_getParam('type');
+
+        try {
+            $obj = $this->getPlaylist($type);
+            $response = $obj->changeFadeInfo($id, $fadeIn, $fadeOut);
+
+            if (!isset($response["error"])) {
+                $this->createUpdateResponse($obj);
+                $this->view->response = $response;
+            } else {
+                $this->view->fade_error = $response["error"];
+            }
+        } catch (PlaylistOutDatedException $e) {
+            $this->playlistOutdated($e);
+        } catch (PlaylistNotFoundException $e) {
+            $this->playlistNotFound($type);
+        } catch (Exception $e) {
+            $this->playlistUnknownError($e);
+        }
+    }
+    
+    public function setCrossfadeAction()
+    {
+        $id1 = $this->_getParam('id1', null);
+        $id2 = $this->_getParam('id2', null);
+        $type = $this->_getParam('type');
+        $fadeIn = $this->_getParam('fadeIn', 0);
+        $fadeOut = $this->_getParam('fadeOut', 0);
+        $offset = $this->_getParam('offset', 0);
+    
+        try {
+            $obj = $this->getPlaylist($type);
+            $response = $obj->createCrossfade($id1, $fadeOut, $id2, $fadeIn, $offset);
+    
+            if (!isset($response["error"])) {
+                $this->createUpdateResponse($obj);
+            } else {
+                $this->view->error = $response["error"];
+            }
+        } catch (PlaylistOutDatedException $e) {
+            $this->playlistOutdated($e);
+        } catch (PlaylistNotFoundException $e) {
+            $this->playlistNotFound($type);
+        } catch (Exception $e) {
+            $this->playlistUnknownError($e);
+        }
+    }
+
+    public function getPlaylistFadesAction()
+    {
+        $type = $this->_getParam('type');
+        try {
+            $obj = $this->getPlaylist($type);
+            $fades = $obj->getFadeInfo(0);
+            $this->view->fadeIn = $fades[0];
+
+            $fades = $obj->getFadeInfo($obj->getSize()-1);
+            $this->view->fadeOut = $fades[1];
+        } catch (PlaylistOutDatedException $e) {
+            $this->playlistOutdated($e);
+        } catch (PlaylistNotFoundException $e) {
+            $this->playlistNotFound($type);
+        } catch (Exception $e) {
+            $this->playlistUnknownError($e);
+        }
+    }
+
+    /**
+     * The playlist fades are stored in the elements themselves.
+     * The fade in is set to the first elements fade in and
+     * the fade out is set to the last elements fade out.
+     **/
+    public function setPlaylistFadesAction()
+    {
+        $fadeIn = $this->_getParam('fadeIn', null);
+        $fadeOut = $this->_getParam('fadeOut', null);
+        $type = $this->_getParam('type');
+
+        try {
+            $obj = $this->getPlaylist($type);
+            $obj->setfades($fadeIn, $fadeOut);
+            $this->view->modified = $obj->getLastModified("U");
+        } catch (PlaylistOutDatedException $e) {
+            $this->playlistOutdated($e);
+        } catch (PlaylistNotFoundException $e) {
+            $this->playlistNotFound($type);
+        } catch (Exception $e) {
+            $this->playlistUnknownError($e);
+        }
+    }
+
+    public function setPlaylistNameDescAction()
+    {
+        $name = $this->_getParam('name', _('Unknown Playlist'));
+        $description = $this->_getParam('description', "");
+        $type = $this->_getParam('type');
+
+        try {
+            $obj = $this->getPlaylist($type);
+            $obj->setName(trim($name));
+            $obj->setDescription($description);
+            $this->view->description = $description;
+            $this->view->playlistName = $name;
+            $this->view->modified = $obj->getLastModified("U");
+        } catch (PlaylistOutDatedException $e) {
+            $this->playlistOutdated($e);
+        } catch (PlaylistNotFoundException $e) {
+            $this->playlistNotFound($type, true);
+        } catch (Exception $e) {
+            $this->playlistUnknownError($e);
+        }
+    }
+
+    public function saveAction()
+    {
+        $request = $this->getRequest();
+        $params = $request->getPost();
+        $result = array();
+
+        if ($params['type'] == 'block') {
+            try {
+                $bl = new Application_Model_Block($params['obj_id']);
+            } catch (BlockNotFoundException $e) {
+                $this->playlistNotFound('block', true);
+            }
+            $form = new Application_Form_SmartBlockCriteria();
+            $form->startForm($params['obj_id']);
+            if ($form->isValid($params)) {
+                $this->setPlaylistNameDescAction();
+                $bl->saveSmartBlockCriteria($params['data']);
+                $result['html'] = $this->createFullResponse($bl, true, true);
+                $result['result'] = 0;
+            } else {
+                $this->view->obj = $bl;
+                $this->view->id = $bl->getId();
+                $this->view->form = $form;
+                $this->view->unsavedName = $params['name'];
+                $this->view->unsavedDesc = $params['description'];
+                $viewPath = 'playlist/_smart-block.phtml';
+                $result['html'] = $this->view->render($viewPath);
+                $result['result'] = 1;
+            }
+        } else if ($params['type'] == 'playlist') {
+            $this->setPlaylistNameDescAction();
+        }
+
+        $result["modified"] = $this->view->modified;
+        $this->_helper->json->sendJson($result);
+    }
+
+    public function smartBlockGenerateAction()
+    {
+        $request = $this->getRequest();
+        $params = $request->getPost();
+        
+        //make sure block exists
+        try {
+            $bl = new Application_Model_Block($params['obj_id']);
+            
+            $form = new Application_Form_SmartBlockCriteria();
+            $form->startForm($params['obj_id']);
+            if ($form->isValid($params)) {
+                $result = $bl->generateSmartBlock($params['data']);
+                $this->_helper->json->sendJson(array("result"=>0, "html"=>$this->createFullResponse($bl, true, true)));
+            } else {
+                $this->view->obj = $bl;
+                $this->view->id = $bl->getId();
+                $this->view->form = $form;
+                $viewPath = 'playlist/_smart-block.phtml';
+                $result['html'] = $this->view->render($viewPath);
+                $result['result'] = 1;
+                $this->_helper->json->sendJson($result);
+            }
+        } catch (BlockNotFoundException $e) {
+            $this->playlistNotFound('block', true);
+        } catch (Exception $e) {
+            Logging::info($e);
+            $this->playlistUnknownError($e);
+        }
+    }
+
+    public function smartBlockShuffleAction()
+    {
+        $request = $this->getRequest();
+        $params = $request->getPost();
+        try {
+            $bl = new Application_Model_Block($params['obj_id']);
+            $result = $bl->shuffleSmartBlock();
+    
+            if ($result['result'] == 0) {
+                $this->_helper->json->sendJson(array("result"=>0, "html"=>$this->createFullResponse($bl, true)));
+            } else {
+                $this->_helper->json->sendJson($result);
+            }
+        } catch (BlockNotFoundException $e) {
+            $this->playlistNotFound('block', true);
+        } catch (Exception $e) {
+            $this->playlistUnknownError($e);
+        }
+    }
+    
+    public function shuffleAction()
+    {
+        $request = $this->getRequest();
+        $params = $request->getPost();
+        try {
+            $pl = new Application_Model_Playlist($params['obj_id']);
+            $result = $pl->shuffle();
+            
+            if ($result['result'] == 0) {
+                $this->_helper->json->sendJson(array("result"=>0, "html"=>$this->createFullResponse($pl, true)));
+            } else {
+                $this->_helper->json->sendJson($result);
+            }
+        } catch (PlaylistNotFoundException $e) {
+            $this->playlistNotFound('block', true);
+        } catch (Exception $e) {
+            $this->playlistUnknownError($e);
+        }
+    }
+
+    public function getBlockInfoAction()
+    {
+        $request = $this->getRequest();
+        $params = $request->getPost();
+        $bl = new Application_Model_Block($params['id']);
+        if ($bl->isStatic()) {
+            $out = $bl->getContents();
+            $out['isStatic'] = true;
+        } else {
+            $out = $bl->getCriteria();
+            $out['isStatic'] = false;
+        }
+        $this->_helper->json->sendJson($out);
+    }
+}
+class WrongTypeToBlockException extends Exception {}
+class WrongTypeToPlaylistException extends Exception {}
+class BlockDynamicException extends Exception {}
diff --git a/airtime_mvc/application/controllers/NewWebstreamController.php b/airtime_mvc/application/controllers/NewWebstreamController.php
new file mode 100644
index 000000000..22db7bf7f
--- /dev/null
+++ b/airtime_mvc/application/controllers/NewWebstreamController.php
@@ -0,0 +1,150 @@
+<?php
+
+class NewWebstreamController extends Zend_Controller_Action
+{
+    public function init()
+    {
+        $ajaxContext = $this->_helper->getHelper('AjaxContext');
+        $ajaxContext->addActionContext('new', 'json')
+                    ->addActionContext('save', 'json')
+                    ->addActionContext('edit', 'json')
+                    ->addActionContext('delete', 'json')
+                    ->initContext();
+    }
+
+    public function newAction()
+    {
+        $userInfo = Zend_Auth::getInstance()->getStorage()->read();
+        if (!$this->isAuthorized(-1)) {
+            // TODO: this header call does not actually print any error message
+            header("Status: 401 Not Authorized");
+            return;
+        }
+
+        $webstream = new CcWebstream();
+
+        //we're not saving this primary key in the DB so it's OK to be -1
+        $webstream->setDbId(-1);
+        $webstream->setDbName(_("Untitled Webstream"));
+        $webstream->setDbDescription("");
+        $webstream->setDbUrl("http://");
+        $webstream->setDbLength("00:30:00");
+        $webstream->setDbName(_("Untitled Webstream"));
+        $webstream->setDbCreatorId($userInfo->id);
+        $webstream->setDbUtime(new DateTime("now", new DateTimeZone('UTC')));
+        $webstream->setDbMtime(new DateTime("now", new DateTimeZone('UTC')));
+
+        //clear the session in case an old playlist was open: CC-4196
+        Application_Model_Library::changePlaylist(null, null);
+
+        $this->view->obj = new Application_Model_Webstream($webstream);
+        $this->view->action = "new";
+        $this->view->html = $this->view->render('webstream/_webstream.phtml');
+    }
+
+    public function editAction()
+    {
+        $request = $this->getRequest();
+
+        $id = $request->getParam("id");
+        if (is_null($id)) {
+            throw new Exception("Missing parameter 'id'");
+        }
+
+        $webstream = CcWebstreamQuery::create()->findPK($id);
+        if ($webstream) {
+            Application_Model_Library::changePlaylist($id, "stream");
+        }
+        $this->view->obj = new Application_Model_Webstream($webstream);
+        $this->view->action = "edit";
+        $this->view->html = $this->view->render('webstream/_webstream.phtml');
+    }
+
+    public function deleteAction()
+    {
+        $request = $this->getRequest();
+        $id = $request->getParam("ids");
+
+        if (!$this->isAuthorized($id)) {
+            header("Status: 401 Not Authorized");
+
+            return;
+        }
+
+        $type = "stream";
+        Application_Model_Library::changePlaylist(null, $type);
+
+        $webstream = CcWebstreamQuery::create()->findPK($id)->delete();
+
+        $this->view->obj = null;
+        $this->view->action = "delete";
+        $this->view->html = $this->view->render('webstream/_webstream.phtml');
+
+    }
+
+    /*TODO : make a user object be passed a parameter into this function so
+        that it does not have to be fetched multiple times.*/
+    public function isAuthorized($webstream_id)
+    {
+        $user = Application_Model_User::getCurrentUser();
+        if ($user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
+            return true;
+        }
+
+        if ($user->isHost()) {
+            // not creating a webstream
+            if ($webstream_id != -1) {
+                $webstream = CcWebstreamQuery::create()->findPK($webstream_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();
+                //only allow when webstream belongs to the DJ
+                return $webstream->getDbCreatorId() == $user->getId();
+            }
+            /*we are creating a new stream. Don't need to check whether the
+                DJ/Host owns the stream*/
+            return true;
+        } else {
+            Logging::info( $user );
+        }
+        return false;
+    }
+
+    public function saveAction()
+    {
+        $request = $this->getRequest();
+
+        $id = $request->getParam("id");
+
+        $parameters = array();
+        foreach (array('id','length','name','description','url') as $p) {
+            $parameters[$p] = trim($request->getParam($p));
+        }
+
+        if (!$this->isAuthorized($id)) {
+            header("Status: 401 Not Authorized");
+            return;
+        }
+
+
+        list($analysis, $mime, $mediaUrl, $di) = Application_Model_Webstream::analyzeFormData($parameters);
+        try {
+            if (Application_Model_Webstream::isValid($analysis)) {
+                $streamId = Application_Model_Webstream::save($parameters, $mime, $mediaUrl, $di);
+
+                Application_Model_Library::changePlaylist($streamId, "stream");
+
+                $this->view->statusMessage = "<div class='success'>"._("Webstream saved.")."</div>";
+                $this->view->streamId = $streamId;
+                $this->view->length = $di->format("%Hh %Im");
+            } else {
+                throw new Exception("isValid returned false");
+            }
+        } catch (Exception $e) {
+            Logging::debug($e->getMessage());
+            $this->view->statusMessage = "<div class='errors'>"._("Invalid form values.")."</div>";
+            $this->view->streamId = -1;
+            $this->view->analysis = $analysis;
+        }
+    }
+}
diff --git a/airtime_mvc/application/layouts/scripts/layout.phtml b/airtime_mvc/application/layouts/scripts/layout.phtml
index 3bb782dee..8192b474e 100644
--- a/airtime_mvc/application/layouts/scripts/layout.phtml
+++ b/airtime_mvc/application/layouts/scripts/layout.phtml
@@ -69,14 +69,12 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
     <?php endif; //suspended ?>
 </div>
 
+<?php $hint = Application_Common_UsabilityHints::getUsabilityHint(); ?>
+<div class="usability_hint" <?php if ($hint == "") { echo "style='display:none'"; } ?>><?php echo $hint; ?></div>
 
 <div class="wrapper" id="content">
-    <?php
-    $hint = Application_Common_UsabilityHints::getUsabilityHint(); ?>
-
-    <div class="usability_hint" <?php if ($hint == "") { echo "style='display:none'"; } ?>><?php echo $hint; ?></div>
-
-    <?php echo $this->layout()->content ?></div>
+    <?php echo $this->layout()->content ?>
+</div>
 
 <script id="tmpl-pl-cues" type="text/template">
 <div class="waveform-cues">
diff --git a/airtime_mvc/application/models/Library.php b/airtime_mvc/application/models/Library.php
index 1659f498d..336bd7e7b 100644
--- a/airtime_mvc/application/models/Library.php
+++ b/airtime_mvc/application/models/Library.php
@@ -11,7 +11,7 @@ class Application_Model_Library
             $info['className'] = 'Application_Model_Playlist';
         } elseif (strcmp($p_type, 'block')==0) {
             $info['className'] = 'Application_Model_Block';
-        } elseif (strcmp($p_type, 'stream')==0) {
+        } elseif (strcmp($p_type, 'webstream')==0) {
             $info['className'] = 'Application_Model_Webstream';
         } else {
             throw new Exception("Unknown object type: '$p_type'");
diff --git a/airtime_mvc/application/views/scripts/playlist/_playlist.phtml b/airtime_mvc/application/views/scripts/playlist/_playlist.phtml
new file mode 100644
index 000000000..2dde0b61c
--- /dev/null
+++ b/airtime_mvc/application/views/scripts/playlist/_playlist.phtml
@@ -0,0 +1,76 @@
+<?php
+if (isset($this->obj)) {
+    $contents = $this->obj->getContents();
+    $count = count($contents);
+}
+?>
+<a href="#" class="close-round" id="lib_pl_close"></a>
+<div class="btn-toolbar spl-no-top-margin clearfix">
+<?php if (isset($this->obj)) : ?>
+    <div class='btn-group pull-right'>
+        <button class="btn btn-inverse" title='<?php echo _("Empty playlist content") ?>' type="button" id="pl-bl-clear-content"><?php echo _("Clear") ?></button>
+    </div>
+    <div class='btn-group pull-right'>
+        <button class="btn btn-inverse" title='<?php echo _("Shuffle playlist") ?>' type="button" id="playlist_shuffle_button"><?php echo _("Shuffle") ?></button>
+    </div>
+    <div class='btn-group pull-right'>
+        <button class="btn btn-inverse" title='<?php echo _("Save playlist") ?>' type="button" id="save_button"><?php echo _("Save") ?></button>
+    </div>
+    <div class='btn-group pull-right'>
+        <button id="spl_delete" class="btn" role="button" aria-disabled="false"><?php echo _("Delete") ?></button>
+    </div>
+    <div class='btn-group pull-right'>
+        <a href="#" id="spl_crossfade" class="btn crossfade-main-button" style="display:<?php echo $count > 0 ?"block;":"none;"?>">
+            <i class='crossfade-main-icon'></i><span class="ui-button-text"><?php echo _("Playlist crossfade") ?></span>
+        </a>
+    </div>
+<?php endif; ?>
+</div>
+
+<?php if (isset($this->obj)) : ?>
+    <input id="obj_id" type="hidden" value="<?php echo $this->obj->getId(); ?>"></input>
+    <input id="obj_lastMod" type="hidden" value="<?php echo $this->obj->getLastModified('U'); ?>"></input>
+    <input id='obj_type' type='hidden' value='playlist'></input>
+    <div class="playlist_title">
+        <h3 id="obj_name">
+            <a id="playlist_name_display" contenteditable="true"><?php echo $this->escape($this->obj->getName()); ?></a>
+        </h3>
+        <h4 id="obj_length"><?php echo $this->length; ?></h4>
+    </div>
+    <div id='sp-success' class='success' style='display:none'></div>
+
+    <fieldset class="toggle closed" id="fieldset-metadate_change">
+        <legend style="cursor: pointer;"><span class="ui-icon ui-icon-triangle-2-n-s"></span><?php echo _("View / edit description"); ?></legend>
+        <dl class="zend_form">
+            <dt id="description-label"><label for="description"><?php echo _("Description") ?></label></dt>
+            <dd id="description-element">
+                <textarea cols="80" rows="24" id="description" name="description"><?php echo $this->escape($this->obj->getDescription()); ?></textarea>
+            </dd>
+        </dl>
+    </fieldset>
+    
+    <?php //echo $this->form; ?>
+
+    <div id="crossfade_main" class="crossfade-main clearfix" style="display:none;">
+      	<span class="ui-icon ui-icon-closethick sp-closethick-center"></span>
+	    <dl id="spl_editor-main" class="inline-list">
+            <dt><?php echo _("Fade in: "); ?><span class='spl_cue_hint'>(ss.t)</span></dt>
+            <dd><span contenteditable="true" class="spl_text_input spl_main_fade_in">00</span></dd>
+            <dd class="edit-error"></dd>
+            <dt><?php echo _("Fade out: "); ?><span class='spl_cue_hint'>(ss.t)</span></dt>
+            <dd><span contenteditable="true" class="spl_text_input spl_main_fade_out">00</span></dd>
+            <dd class="edit-error"></dd>
+        </dl>
+    </div>
+
+    <div class="clear"></div>
+    <div class="" style="clear:both; float:none; width:100%;">
+	    <ul id="spl_sortable">
+            <?php  $this->contents = $contents;
+                echo $this->render('playlist/update.phtml') ?>
+	    </ul>
+    </div>
+
+<?php else : ?>
+    <div><?php echo _("No open playlist") ?></div>
+<?php endif; ?>
diff --git a/airtime_mvc/application/views/scripts/playlist/_smart-block.phtml b/airtime_mvc/application/views/scripts/playlist/_smart-block.phtml
new file mode 100644
index 000000000..843f98fb3
--- /dev/null
+++ b/airtime_mvc/application/views/scripts/playlist/_smart-block.phtml
@@ -0,0 +1,81 @@
+<?php
+if (isset($this->obj)) {
+    $contents = $this->obj->getContents();
+    $count = count($contents);
+}
+?>
+<a href="#" class="close-round" id="lib_pl_close"></a>
+<div class="btn-toolbar spl-no-top-margin clearfix">
+<?php if (isset($this->obj)) : ?>
+    <div class='btn-group pull-right'>
+        <button class="btn btn-inverse" title='<?php echo _("Empty smart block content") ?>' type="button" id="pl-bl-clear-content"><?php echo _("Clear") ?></button>
+    </div>
+    <div class='btn-group pull-right'>
+        <button class="btn btn-inverse" title='Save smart block&#39s title, description, and criteria' type="button" id="save_button"><?php echo _("Save") ?></button>
+    </div>
+    <div class='btn-group pull-right'>
+        <button id="spl_delete" class="btn" role="button" aria-disabled="false"><?php echo _("Delete") ?></button>
+    </div>
+    <div class='btn-group pull-right'>
+        <a href="#" id="spl_crossfade" class="btn crossfade-main-button" style="display:<?php echo ($this->obj->isStatic() && $count > 0) ?"block;":"none;"?>">
+            <i class='crossfade-main-icon'></i><span class="ui-button-text"><?php echo _("Playlist crossfade") ?></span>
+        </a>
+    </div>
+<?php endif; ?>
+</div>
+
+<?php if (isset($this->obj)) : ?>
+    <input id="obj_id" type="hidden" value="<?php echo $this->obj->getId(); ?>"></input>
+    <input id="obj_lastMod" type="hidden" value="<?php echo $this->obj->getLastModified('U'); ?>"></input>
+    <input id='obj_type' type='hidden' value='block'></input>
+    <div class="playlist_title">
+        <h3 id="obj_name">
+            <a id="playlist_name_display" contenteditable="true">
+            <?php
+                if (isset($this->unsavedName)) echo $this->unsavedName;
+                else echo $this->escape($this->obj->getName());
+            ?>
+            </a>
+        </h3>
+        <h4 id="obj_length"><?php echo $this->length; ?></h4>
+    </div>
+    <div id='sp-success-saved' class='success' style='display:none'></div>
+
+    <fieldset class="toggle closed" id="fieldset-metadate_change">
+        <legend style="cursor: pointer;"><span class="ui-icon ui-icon-triangle-2-n-s"></span><?php echo _("View / edit description"); ?></legend>
+        <dl class="zend_form">
+            <dt id="description-label"><label for="description"><?php echo _("Description") ?></label></dt>
+            <dd id="description-element">
+                <textarea cols="80" rows="24" id="description" name="description"><?php
+                    if (isset($this->unsavedDesc)) echo $this->unsavedDesc;
+                    else echo $this->obj->getDescription();?>
+                </textarea>
+            </dd>
+        </dl>
+    </fieldset>
+    
+    <?php echo $this->form; ?>
+
+    <div id="crossfade_main" class="crossfade-main clearfix" style="display:none;">
+      	<span class="ui-icon ui-icon-closethick"></span>
+	    <dl id="spl_editor-main" class="inline-list">
+            <dt><?php echo _("Fade in: "); ?><span class='spl_cue_hint'><?php echo _("(ss.t)")?></span></dt>
+            <dd><span contenteditable="true" class="spl_text_input spl_main_fade_in">00</span></dd>
+            <dd class="edit-error"></dd>
+            <dt><?php echo _("Fade out: "); ?><span class='spl_cue_hint'><?php echo _("(ss.t)")?></span></dt>
+            <dd><span contenteditable="true" class="spl_text_input spl_main_fade_out">00</span></dd>
+            <dd class="edit-error"></dd>
+        </dl>
+    </div>
+
+    <div class="clear"></div>
+    <div class="" style="clear:both; float:none; width:100%;">
+	    <ul id="spl_sortable">
+            <?php $this->contents = $contents;
+                echo $this->render('playlist/update.phtml') ?>
+	    </ul>
+    </div>
+
+<?php else : ?>
+    <div><?php echo _("No open smart block") ?></div>
+<?php endif; ?>
diff --git a/airtime_mvc/application/views/scripts/playlist/playlist.phtml b/airtime_mvc/application/views/scripts/playlist/playlist.phtml
index 263b9008c..d187dc866 100644
--- a/airtime_mvc/application/views/scripts/playlist/playlist.phtml
+++ b/airtime_mvc/application/views/scripts/playlist/playlist.phtml
@@ -6,16 +6,16 @@ if (isset($this->obj)) {
 ?>
 <a href="#" class="close-round" id="lib_pl_close"></a>
 <div class="btn-toolbar spl-no-top-margin clearfix">
-<!--    <div class="btn-group pull-left">-->
-<!--        <button id="spl_new" class="btn dropdown-toggle" data-toggle="dropdown" aria-disabled="false">-->
-<!--            --><?php //echo _("New")?><!-- <span class="caret"></span>-->
-<!--        </button>-->
-<!--        <ul class="dropdown-menu">-->
-<!--            <li id='lib-new-pl'><a href="#">--><?php //echo _("New Playlist") ?><!--</a></li>-->
-<!--            <li id='lib-new-bl'><a href="#">--><?php //echo _("New Smart Block") ?><!--</a></li>-->
-<!--            <li id='lib-new-ws'><a href="#">--><?php //echo _("New Webstream") ?><!--</a></li>-->
-<!--        </ul>-->
-<!--    </div>-->
+    <div class="btn-group pull-left">
+        <button id="spl_new" class="btn dropdown-toggle" data-toggle="dropdown" aria-disabled="false">
+            <?php echo _("New")?> <span class="caret"></span>
+        </button>
+        <ul class="dropdown-menu">
+            <li id='lib-new-pl'><a href="#"><?php echo _("New Playlist") ?></a></li>
+            <li id='lib-new-bl'><a href="#"><?php echo _("New Smart Block") ?></a></li>
+            <li id='lib-new-ws'><a href="#"><?php echo _("New Webstream") ?></a></li>
+        </ul>
+    </div>
 <?php if (isset($this->obj)) : ?>
     <div class='btn-group pull-right'>
         <button class="btn btn-inverse" title='<?php echo _("Empty playlist content") ?>' type="button" id="pl-bl-clear-content"><?php echo _("Clear") ?></button>
diff --git a/airtime_mvc/application/views/scripts/playlist/smart-block.phtml b/airtime_mvc/application/views/scripts/playlist/smart-block.phtml
index 8b9e0ad82..716fdce38 100644
--- a/airtime_mvc/application/views/scripts/playlist/smart-block.phtml
+++ b/airtime_mvc/application/views/scripts/playlist/smart-block.phtml
@@ -6,16 +6,16 @@ if (isset($this->obj)) {
 ?>
 <a href="#" class="close-round" id="lib_pl_close"></a>
 <div class="btn-toolbar spl-no-top-margin clearfix">
-<!--    <div class="btn-group pull-left">-->
-<!--        <button id="spl_new" class="btn dropdown-toggle" data-toggle='dropdown' aria-disabled="false">-->
-<!--            --><?php //echo _("New")?><!-- <span class="caret"></span>-->
-<!--        </button>-->
-<!--        <ul class="dropdown-menu">-->
-<!--            <li id='lib-new-pl'><a href="#">--><?php //echo _("New Playlist") ?><!--</a></li>-->
-<!--            <li id='lib-new-bl'><a href="#">--><?php //echo _("New Smart Block") ?><!--</a></li>-->
-<!--            <li id='lib-new-ws'><a href="#">--><?php //echo _("New Webstream") ?><!--</a></li>-->
-<!--        </ul>-->
-<!--    </div>-->
+    <div class="btn-group pull-left">
+        <button id="spl_new" class="btn dropdown-toggle" data-toggle='dropdown' aria-disabled="false">
+            <?php echo _("New")?> <span class="caret"></span>
+        </button>
+        <ul class="dropdown-menu">
+            <li id='lib-new-pl'><a href="#"><?php echo _("New Playlist") ?></a></li>
+            <li id='lib-new-bl'><a href="#"><?php echo _("New Smart Block") ?></a></li>
+            <li id='lib-new-ws'><a href="#"><?php echo _("New Webstream") ?></a></li>
+        </ul>
+    </div>
 <?php if (isset($this->obj)) : ?>
     <div class='btn-group pull-right'>
         <button class="btn btn-inverse" title='<?php echo _("Empty smart block content") ?>' type="button" id="pl-bl-clear-content"><?php echo _("Clear") ?></button>
diff --git a/airtime_mvc/application/views/scripts/show-builder/index.phtml b/airtime_mvc/application/views/scripts/show-builder/index.phtml
index 8142bd68c..0308b1cf0 100644
--- a/airtime_mvc/application/views/scripts/show-builder/index.phtml
+++ b/airtime_mvc/application/views/scripts/show-builder/index.phtml
@@ -5,7 +5,7 @@
 <!--    </div>-->
 <!--</form>-->
 
-<div id="media_type_nav">
+<div id="media_type_nav" class="content-pane">
     <div class="btn-group">
         <button id="new_media_selector" class="btn btn-small dropdown-toggle" data-toggle="dropdown">
             New <span class="caret"></span>
@@ -28,26 +28,33 @@
     <div class="media_type_selector" selection_id="4"><?php echo _("Webstreams") ?></div>
 </div>
 
-<div id="library_content" class="lib-content tabs">
-    <fieldset class="toggle closed" id="filter_options">
-        <legend style="cursor: pointer;">
-            <span class="ui-icon ui-icon-triangle-2-n-s"></span>
-            <?php echo _("Advanced Search Options") ?>
-        </legend>
-        <div id="advanced_search" class="advanced_search form-horizontal"></div>
-    </fieldset>
-    <table id="library_display" cellpadding="0" cellspacing="0" class="datatable">
-    </table>
-</div>
-
-<div id="show_builder" class="sb-content">
-    <div class="sb-timerange">
-        <?php echo $this->sb_form; ?>
+<div id="library_content" class="lib-content tabs content-pane wide-panel">
+    <div class="panel-header">
+        <fieldset class="toggle closed" id="filter_options">
+            <legend style="cursor: pointer;">
+                <span class="ui-icon ui-icon-triangle-2-n-s"></span>
+                <?php echo _("Advanced Search Options") ?>
+            </legend>
+            <div id="advanced_search" class="advanced_search form-horizontal"></div>
+        </fieldset>
+    </div>
+    <div class="outer-datatable-wrapper">
+        <table id="library_display" cellpadding="0" cellspacing="0" class="datatable"></table>
     </div>
-    <table id="show_builder_table" cellpadding="0" cellspacing="0" class="datatable"></table>
 </div>
 
-<div id="side_playlist" class="pl-content">
+<div id="show_builder" class="sb-content content-pane wide-panel">
+    <div class="panel-header">
+        <ul class="nav nav-tabs">
+            <li id="timeline-tab" role="presentation" class="active"><a href="#">Timeline</a></li>
+        </ul>
+    </div>
+    <div class="outer-datatable-wrapper active-tab">
+        <table id="show_builder_table" cellpadding="0" cellspacing="0" class="datatable"></table>
+        <div class="sb-timerange">
+            <?php echo $this->sb_form; ?>
+        </div>
+    </div>
 </div>
 
 <?php echo $this->dialog ?>
diff --git a/airtime_mvc/application/views/scripts/webstream/_webstream.phtml b/airtime_mvc/application/views/scripts/webstream/_webstream.phtml
new file mode 100644
index 000000000..3fb175c9c
--- /dev/null
+++ b/airtime_mvc/application/views/scripts/webstream/_webstream.phtml
@@ -0,0 +1,55 @@
+<a href="#" class="close-round" id="lib_pl_close"></a>
+<div class="btn-toolbar spl-no-top-margin clearfix">
+
+<?php if (isset($this->obj)) : ?>
+ <div class="btn-group pull-right">
+    <button class="btn btn-inverse" type="submit" id="webstream_save" name="submit"><?php echo _("Save") ?></button>
+</div>
+<div class="btn-group pull-right">
+    <button id="ws_delete" class="btn" <?php if ($this->action == "new"): ?>style="display:none;"<?php endif; ?>aria-disabled="false"><?php echo _("Delete") ?></button>
+</div>
+<?php endif; ?>
+</div>
+
+<?php if (isset($this->obj)) : ?>
+    <input id="obj_id" type="hidden" value="<?php echo $this->obj->getId(); ?>"/>
+    <input id="obj_lastMod" type="hidden" value="<?php echo "1";//$this->obj->getLastModified('U'); ?>"/>
+    <input id="obj_type" type="hidden" value="webstream"/>
+    <div class="status" style="display:none;"></div>
+
+    <div class="playlist_title">
+        <div id="name-error" class="errors" style="display:none;"></div>
+        <h3 id="ws_name">
+            <a id="playlist_name_display" contenteditable="true"><?php echo $this->escape($this->obj->getName()); ?></a>
+        </h3>
+        <h4 id="ws_length"><?php echo $this->obj->getDefaultLength(); ?></h4>
+    </div>
+
+    <fieldset class="toggle" id="fieldset-metadate_change">
+        <legend style="cursor: pointer;"><span class="ui-icon ui-icon-triangle-2-n-s"></span><?php echo _("View / edit description"); ?></legend>
+        <dl class="zend_form">
+            <dt id="description-label"><label for="description"><?php echo _("Description") ?></label></dt>
+            <dd id="description-element">
+                <textarea cols="80" rows="24" id="description" name="description"><?php echo $this->obj->getDescription(); ?></textarea>
+            </dd>
+         
+       </dl>
+    </fieldset>
+    
+    <dl class="zend_form">
+        <dt id="submit-label" style="display: none;">&nbsp;</dt>
+        <div id="url-error" class="errors" style="display:none;"></div>
+        <dt id="streamurl-label"><label for="streamurl"><?php echo _("Stream URL:"); ?></label></dt>
+        <dd id="streamurl-element">
+        <input type="text" value="<?php echo $this->obj->getUrl(); ?>" size="40"/>
+        </dd>
+        <div id="length-error" class="errors" style="display:none;"></div>
+        <dt id="streamlength-label"><label for="streamlength"><?php echo _("Default Length:"); ?></label></dt>
+        <dd id="streamlength-element">
+        <input type="text" value="<?php echo $this->obj->getDefaultLength() ?>"/>
+        </dd>
+    </dl>
+
+<?php else : ?>
+    <div><?php echo _("No webstream") ?></div>
+<?php endif; ?>
diff --git a/airtime_mvc/application/views/scripts/webstream/webstream.phtml b/airtime_mvc/application/views/scripts/webstream/webstream.phtml
index 45790bb3b..9c9af52b4 100644
--- a/airtime_mvc/application/views/scripts/webstream/webstream.phtml
+++ b/airtime_mvc/application/views/scripts/webstream/webstream.phtml
@@ -1,15 +1,15 @@
 <a href="#" class="close-round" id="lib_pl_close"></a>
 <div class="btn-toolbar spl-no-top-margin clearfix">
-<!--    <div class="btn-group pull-left">-->
-<!--        <button id="ws_new" class="btn dropdown-toggle" data-toggle="dropdown" aria-disabled="false">-->
-<!--            --><?php //echo _("New")?><!-- <span class="caret"></span>-->
-<!--        </button>-->
-<!--        <ul class="dropdown-menu">-->
-<!--            <li id='lib-new-pl'><a href="#">--><?php //echo _("New Playlist") ?><!--</a></li>-->
-<!--            <li id='lib-new-bl'><a href="#">--><?php //echo _("New Smart Block") ?><!--</a></li>-->
-<!--            <li id='lib-new-ws'><a href="#">--><?php //echo _("New Webstream") ?><!--</a></li>-->
-<!--        </ul>-->
-<!--    </div>-->
+    <div class="btn-group pull-left">
+        <button id="ws_new" class="btn dropdown-toggle" data-toggle="dropdown" aria-disabled="false">
+            <?php echo _("New")?> <span class="caret"></span>
+        </button>
+        <ul class="dropdown-menu">
+            <li id='lib-new-pl'><a href="#"><?php echo _("New Playlist") ?></a></li>
+            <li id='lib-new-bl'><a href="#"><?php echo _("New Smart Block") ?></a></li>
+            <li id='lib-new-ws'><a href="#"><?php echo _("New Webstream") ?></a></li>
+        </ul>
+    </div>
 
 <?php if (isset($this->obj)) : ?>
  <div class="btn-group pull-right">
diff --git a/airtime_mvc/public/css/_showbuilder.css b/airtime_mvc/public/css/_showbuilder.css
index 9d2daa730..d42272c12 100644
--- a/airtime_mvc/public/css/_showbuilder.css
+++ b/airtime_mvc/public/css/_showbuilder.css
@@ -9,17 +9,12 @@ div.ColVis_collectionBackground {
 }
 
 .wrapper {
-    position: absolute;
-    /* Height of the top panel */
-    top: 141px;
-    bottom: 0;
     /*background: #242424;*/
     background: #111;
     left: 0;
     right: 0;
+    bottom: 0;
     padding: 10px;
-    overflow-y: auto;
-    overflow-x: hidden;
 
     display: -webkit-box;
     display: -moz-box;
@@ -28,6 +23,8 @@ div.ColVis_collectionBackground {
     display: flex;
     -webkit-flex-flow: row wrap;
     flex-flow: row wrap;
+
+    overflow: auto;
 }
 
 /* Usability hint */
@@ -57,40 +54,98 @@ div.ColVis_collectionBackground {
 
 /* Show Builder*/
 
+.content-pane {
+    position: relative;
+
+    border: 1px solid #202020;
+    border-top: 1px solid #353535;
+    border-left: 1px solid #2a2a2a;
+
+    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.65);
+    -moz-box-shadow: inset 0 0 6px rgba(0,0,0,.65);
+    box-shadow: inset 0 0 6px rgba(0,0,0,.65);
+
+    background-color: #242424;
+}
+
+.wide-panel {
+    display: -webkit-box;
+    display: -moz-box;
+    display: -ms-flexbox;
+    display: -webkit-flex;
+    display: flex;
+    -webkit-flex-flow: column;
+    flex-flow: column;
+
+    /* Account for the left pane */
+    flex: 6 auto;
+    min-width: 555px;
+}
+
+.btn {
+    color: #efefef;
+}
+
+.outer-datatable-wrapper {
+    position: relative;
+    flex: 1;
+}
+
+@media screen and (max-height: 650px) {
+    #master-panel {
+        display: none;
+    }
+    .wrapper {
+        top: 40px !important;
+    }
+}
+
 @media screen and (max-width: 1475px) {
-    #library_content, #show_builder, #side_playlist, #media_type_nav {
-        /*height: auto !important;*/
-        max-height: 50% !important;
+    .wrapper {
+        -webkit-flex-flow: column !important;
+        flex-flow: column !important;
+    }
+    .content-pane {
+        height: auto !important;
         width: 100% !important;
     }
+    .wide-panel {
+        flex: 8 100%;
+        min-height: 50%;
+    }
     #side_playlist {
         margin-top: 0 !important;
     }
-    #media_type_nav div {
-        float: left;
-        width: 20%;
-        text-align: center;
-        margin: auto;
+    #media_type_nav {
+        display: -webkit-box;
+        display: -moz-box;
+        display: -ms-flexbox;
+        display: -webkit-flex;
+        display: flex;
+        -webkit-flex-flow: row;
+        flex-flow: row;
+
+        -webkit-align-items: center;
+        align-items: center;
+        -webkit-justify-content: center;
+        justify-content: center;
+    }
+    #media_type_nav .btn-group {
+        flex: 1 100%;
     }
     #media_type_nav .dropdown-menu {
         width: 100%;
-        text-align: center;
     }
     #media_type_nav .media_type_selector {
+        flex: 1 100%;
         margin-top: 3px;
     }
 }
 
 @media screen and (max-width: 780px) {
-    #library_content .dataTables_filter input[type="text"] {
-        position: relative;
-        width: calc(100% - 10px) !important;
-        margin: 0 .5em .5em 0;
-    }
     .wrapper {
-        height: calc(100% - 166px) !important; /* Correct for margins */
+        height: 100% !important; /* Correct for margins */
         padding: 0 15px 15px !important;
-        margin-top: 10px; /* This is only necessary if we aren't using a responsive menu! */
     }
 }
 
@@ -101,23 +156,11 @@ div.ColVis_collectionBackground {
     }
 }
 
-.btn {
-    color: #efefef;
-}
-
 /* Library */
 
 #library_content {
     margin-right: 10px;
     overflow: hidden !important;
-
-    display: -webkit-box;
-    display: -moz-box;
-    display: -ms-flexbox;
-    display: -webkit-flex;
-    display: flex;
-    -webkit-flex-flow: row wrap;
-    flex-flow: row wrap;
 }
 
 #library_content .dataTables_filter {
@@ -143,67 +186,56 @@ div.ColVis_collectionBackground {
     color: #555555;
 }
 
+#library_content legend {
+    position: absolute;
+    top: 0;
+
+    padding-top: 4px;
+    font-size: 14px;
+}
+
 #library_content legend, #library_content span, #library_content label {
     font-weight: normal;
     color: #efefef;
 }
 
-#library_content .fg-toolbar.ui-toolbar.ui-widget-header.ui-corner-bl.ui-corner-br.ui-helper-clearfix {
+.fg-toolbar.ui-toolbar.ui-widget-header.ui-corner-bl.ui-corner-br.ui-helper-clearfix {
     position: absolute;
     right: 0;
     left: 0;
     bottom: 0;
 }
 
-#library_display_wrapper {
-    flex: 1 100%;
-}
-
 #library_display_wrapper, #show_builder_table_wrapper {
     position: absolute;
-    top: 36px;
+    top: 4px;
     bottom: 4px;
     right: 4px;
     left: 4px;
-    /*background-color: #474747;*/
 }
 
-#library_content, #show_builder, #side_playlist, #media_type_nav {
-    position: relative;
-    height: 95%;
-
-    border: 1px solid #202020;
-    border-top: 1px solid #272727;
-    border-left: 1px solid #272727;
-
-    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.65);
-       -moz-box-shadow: inset 0 0 6px rgba(0,0,0,.65);
-            box-shadow: inset 0 0 6px rgba(0,0,0,.65);
-
-    background-color: #242424;
-}
-
-#library_content, #show_builder, #side_playlist {
-    /* Account for the left pane */
-    flex: 5 auto;
-    min-width: 470px;
-}
-
-#library_content .dataTables_scrolling {
+.dataTables_scrolling {
     position: absolute;
-    bottom: 38px;
+    bottom: 38px; /* 38 px is the size of the header/footer */
     top: 38px;
-    left: 0;
+    left: 1px; /* Border */
     right: 0;
 }
 
-#filter_options{
-    position: absolute;
-    top: 4px;
-    left: 4px;
-    right: 4px;
+#filter_options {
+    text-align: center;
+    padding: 15px 0 15px 15px;
+    margin: 0;
+    border: none;
+}
 
-    flex: 1 100%;
+#advanced_search {
+    margin-top: 15px;
+}
+
+.panel-header {
+    position: relative;
+    top: 4px;
 }
 
 /* Timeline */
@@ -221,6 +253,7 @@ div.ColVis_collectionBackground {
 }
 
 #sb_submit {
+    font-weight: normal;
     text-decoration: none;
     padding: 4px;
     color: #efefef;
@@ -228,10 +261,8 @@ div.ColVis_collectionBackground {
 }
 
 .sb-options-form {
-    position: absolute;
-    top: 4px;
-    left: 4px;
-    right: 4px;
+    position: relative;
+    padding: 5px;
     float: left;
 }
 
@@ -240,29 +271,64 @@ div.ColVis_collectionBackground {
     line-height: 26px;
 }
 
-.dataTables_scrolling.sb-padded {
-    position: absolute;
-    top: 38px;
-    bottom: 4px;
-    right: 0;
-    left: 0;
-}
-
 #sb_show_filter {
     float: right;
+    margin-left: 4px;
 }
 
-#show_builder_table_wrapper {
-    bottom: 0;
+.nav-tabs {
+    border-bottom: 1px solid #474747;
+    font-family: Arial, Helvetica, sans-serif;
+    font-size: 12px;
+    padding: 0;
+    margin: 0 4px 0;
+}
+
+.nav-tabs a {
+    padding: 4px 8px !important;
+
+    color: #efefef;
+    font-size: 14px;
+    text-decoration: none;
+
+    background-color: rgba(71,71,71,.5);
+
+}
+
+.nav-tabs :not(.active) a:hover {
+    background-color: rgba(239, 76, 10, .5) !important;
+    border: 1px solid transparent !important;
+    border-bottom: 1px solid #474747 !important;
+}
+
+.nav-tabs > .active > a, .nav-tabs > .active > a:hover {
+    color: #efefef;
+
+    background-color: #474747;
+    border: 1px solid #474747;
+    border-bottom-color: transparent;
+    cursor: default;
 }
 
 /* Media editors */
 
 #side_playlist {
-    float: right;
-    color: #efefef;
-    font-size: inherit;
-    overflow: hidden;
+    width: 100%; /* Override because we're using flexbox */
+
+    overflow-x: hidden;
+    overflow-y: auto;
+
+    position: relative;
+
+    flex: 1;
+}
+
+.editor_pane_wrapper {
+    padding: 4px;
+}
+
+#spl_sortable .list-item-container {
+    cursor: move;
 }
 
 /* Media type selector */
@@ -270,6 +336,7 @@ div.ColVis_collectionBackground {
 #media_type_nav {
     flex: 1 auto;
     margin-right: 10px;
+    text-align: center;
 }
 
 #media_type_nav div {
@@ -278,6 +345,7 @@ div.ColVis_collectionBackground {
 
 #new_media_selector {
     width: 100%;
+    font-size: 14px;
 }
 
 .media_type_selector {
@@ -286,7 +354,6 @@ div.ColVis_collectionBackground {
     font-family: Roboto, "Open Sans", sans-serif;
     font-size: 16px;
     font-weight: 400;
-    width: 100%;
     margin: 10px 10px 0 0;
 
     -webkit-transition: color 0.2s linear;
@@ -318,19 +385,21 @@ div.ColVis_collectionBackground {
     overflow: auto;
 }
 
-.helper.ui-draggable-dragging {
-    z-index: 9999;
-}
-
 .datatable tr, .datatable td {
     border: none !important;
 }
 
+/* This is so dragged items show up above the layout */
+.ui-draggable-dragging {
+    z-index: 9999;
+    position: fixed !important;
+}
+
 /* Uploads/Dropzone */
 
 #upload_form {
     width: 100%;
-    min-width: 470px;
+    min-width: 555px;
 
     background: none;
     border: 2px dashed #efefef;
diff --git a/airtime_mvc/public/css/styles.css b/airtime_mvc/public/css/styles.css
index b51c8b049..eb302fb71 100644
--- a/airtime_mvc/public/css/styles.css
+++ b/airtime_mvc/public/css/styles.css
@@ -3310,13 +3310,27 @@ dd .stream-status {
 
 /* Usability Hints */
 
+/*
+ * This is a temporary solution to a larger issue;
+ * we should revisit this (and really all of the
+ * absolute positioning in Airtime) when we want
+ * to focus on responsive design.
+ */
+.usability_hint + .wrapper {
+    top: 170px;
+}
+
 .usability_hint {
     padding: 5px 10px 5px 10px;
-    margin-bottom: 10px;
     border: 1px solid #ff611f;
     background-color: #ff611f;
     color: white;
     font-size: 14px;
+
+    position: absolute;
+    top: 139px;
+    width: 100%;
+    z-index: 1;
 }
 
 .usability_hint a {
diff --git a/airtime_mvc/public/js/airtime/library/_library.js b/airtime_mvc/public/js/airtime/library/_library.js
index b2b4284f0..a8a484e51 100644
--- a/airtime_mvc/public/js/airtime/library/_library.js
+++ b/airtime_mvc/public/js/airtime/library/_library.js
@@ -392,7 +392,7 @@ var AIRTIME = (function(AIRTIME) {
                 $.post(baseUrl+"playlist/close-playlist",
                     {"format": "json", "type": currentObjType},
                     function(json) {
-                        $("#side_playlist").empty().append(json.html);
+                        $("#editor_pane_wrapper").empty().append(json.html);
                     });
             }
         }
@@ -685,7 +685,7 @@ var AIRTIME = (function(AIRTIME) {
             "oLanguage": datatables_dict,
 
             // R = ColReorder, C = ColVis
-            "sDom": 'R<"#library_display_type"><"dt-process-rel"r><"H"<"library_toolbar"Cf>><"dataTables_scrolling"t><"F"ilp>>',
+            "sDom": 'R<"dt-process-rel"r><"H"<"library_toolbar"Cf>><"dataTables_scrolling"t><"F"ilp>>',
 
             "oColVis": {
                 "sAlign": "right",
diff --git a/airtime_mvc/public/js/airtime/library/_spl.js b/airtime_mvc/public/js/airtime/library/_spl.js
index 6b1c29df1..f5885ce30 100644
--- a/airtime_mvc/public/js/airtime/library/_spl.js
+++ b/airtime_mvc/public/js/airtime/library/_spl.js
@@ -15,7 +15,9 @@ var AIRTIME = (function(AIRTIME){
         $togglePl = $("<button id='pl_edit' class='btn btn-small' href='#' title='"+$.i18n._("Open Media Builder")+"'>"+$.i18n._("Open Media Builder")+"</button>"),
         widgetHeight,
         resizeTimeout,
-        width;
+        width,
+        $plCount = 0,
+        $openTabs = {};
 
     function isTimeValid(time) {
         //var regExpr = new RegExp("^\\d{2}[:]\\d{2}[:]\\d{2}([.]\\d{1,6})?$");
@@ -32,6 +34,7 @@ var AIRTIME = (function(AIRTIME){
 
     function playlistError(json) {
         alert(json.error);
+        closeTab();
         openPlaylist(json);
     }
 
@@ -67,7 +70,7 @@ var AIRTIME = (function(AIRTIME){
         event.stopPropagation();
         var span = $(this),
             id = span.parent().attr("id").split("_").pop(),
-            url = baseUrl+"Playlist/set-cue",
+            url = baseUrl+"new-playlist/set-cue",
             cueIn = $.trim(span.text()),
             li = span.parents("li"),
             unqid = li.attr("unqid"),
@@ -104,7 +107,7 @@ var AIRTIME = (function(AIRTIME){
         event.stopPropagation();
         var span = $(this),
             id = span.parent().attr("id").split("_").pop(),
-            url = baseUrl+"Playlist/set-cue",
+            url = baseUrl+"new-playlist/set-cue",
             cueOut = $.trim(span.text()),
             li = span.parents("li"),
             unqid = li.attr("unqid"),
@@ -141,7 +144,7 @@ var AIRTIME = (function(AIRTIME){
     /* used from waveform pop-up */
     function changeCues($el, id, cueIn, cueOut) {
 
-        var url = baseUrl+"Playlist/set-cue",
+        var url = baseUrl+"new-playlist/set-cue",
             lastMod = getModified(),
             type = $('#obj_type').val(),
             li,
@@ -211,7 +214,7 @@ var AIRTIME = (function(AIRTIME){
     /* used from waveform pop-up */
     function changeCrossfade($el, id1, id2, fadeIn, fadeOut, offset, id) {
 
-        var url = baseUrl+"Playlist/set-crossfade",
+        var url = baseUrl+"new-playlist/set-crossfade",
             lastMod = getModified(),
             type = $('#obj_type').val();
 
@@ -229,7 +232,7 @@ var AIRTIME = (function(AIRTIME){
 
                 setPlaylistContent(json);
 
-                $li = $('#side_playlist li[unqid='+id+']');
+                $li = $pl.find('li[unqid='+id+']');
                 $li.find('.crossfade').toggle();
                 highlightActive($li.find('.spl_fade_control'));
             });
@@ -240,7 +243,7 @@ var AIRTIME = (function(AIRTIME){
 
         var span = $(this),
             id = span.parent().attr("id").split("_").pop(),
-            url = baseUrl+"Playlist/set-fade",
+            url = baseUrl+"new-playlist/set-fade",
             fadeIn = $.trim(span.text()),
             li = span.parents("li"),
             unqid = li.attr("unqid"),
@@ -267,7 +270,7 @@ var AIRTIME = (function(AIRTIME){
 
                 setPlaylistContent(json);
 
-                li = $('#side_playlist li[unqid='+unqid+']');
+                li = $pl.find('li[unqid='+unqid+']');
                 li.find('.crossfade').toggle();
                 highlightActive(li.find('.spl_fade_control'));
             });
@@ -278,7 +281,7 @@ var AIRTIME = (function(AIRTIME){
 
         var span = $(this),
             id = span.parent().attr("id").split("_").pop(),
-            url = baseUrl+"Playlist/set-fade",
+            url = baseUrl+"new-playlist/set-fade",
             fadeOut = $.trim(span.text()),
             li = span.parents("li"),
             unqid = li.attr("unqid"),
@@ -305,7 +308,7 @@ var AIRTIME = (function(AIRTIME){
 
                 setPlaylistContent(json);
 
-                li = $('#side_playlist li[unqid='+unqid+']');
+                li = $pl.find('li[unqid='+unqid+']');
                 li.find('.crossfade').toggle();
                 highlightActive(li.find('.spl_fade_control'));
             });
@@ -358,6 +361,9 @@ var AIRTIME = (function(AIRTIME){
         var nameElement = $(this);
             //remove any newlines if user somehow snuck them in (easy to do if dragging/dropping text)
             nameElement.text(nameElement.text().replace("\n", ""));
+
+        var name = $pl.find("#playlist_name_display").text();
+        $(".nav.nav-tabs .active a").text(name);
     }
 
     function redrawLib() {
@@ -392,12 +398,12 @@ var AIRTIME = (function(AIRTIME){
     }
 
     function setFadeIcon(){
-        var contents = $("#spl_sortable");
+        var contents = $pl.find("#spl_sortable");
         var show = contents.is(":visible");
-        var empty = $(".spl_empty");
+        var empty = $pl.find(".spl_empty");
 
         if (!show || empty.length > 0) {
-            $("#spl_crossfade").hide();
+            $pl.find("#spl_crossfade").hide();
         } else {
             //get list of playlist contents
             var list = contents.children();
@@ -407,33 +413,60 @@ var AIRTIME = (function(AIRTIME){
             var last = list.last();
             if (first.find(':first-child').children().attr('blockid') !== undefined &&
                 last.find(':first-child').children().attr('blockid') !== undefined) {
-                $("#spl_crossfade").hide();
+                $pl.find("#spl_crossfade").hide();
             } else {
-                $("#spl_crossfade").show();
+                $pl.find("#spl_crossfade").show();
             }
         }
     }
 
     function getId() {
-        return parseInt($("#obj_id").val(), 10);
+        return parseInt($pl.find("#obj_id").val(), 10);
     }
 
     function getModified() {
-        return parseInt($("#obj_lastMod").val(), 10);
+        return parseInt($pl.find("#obj_lastMod").val(), 10);
     }
 
     function setModified(modified) {
-        $("#obj_lastMod").val(modified);
+        $pl.find("#obj_lastMod").val(modified);
     }
 
     function openPlaylist(json) {
-        $("#side_playlist")
-            .empty()
-            .append(json.html);
+        $plCount++;
+        var tabId = $openTabs[json.id];
+        if ($openTabs[json.id] !== undefined) {
+            AIRTIME.showbuilder.switchTab($(".pl-tab-content-" + tabId), $("#pl-tab-" + tabId));
+            return;
+        }
 
-        setUpPlaylist();
-        setCueEvents();
-        setFadeEvents();
+        var wrapper = "<div id='side_playlist' class='pl-content pl-tab-content-" + $plCount + "'><div class='editor_pane_wrapper'></div></div>",
+            t = $("#show_builder").append(wrapper).find(".pl-tab-content-" + $plCount),
+            pane = $(".editor_pane_wrapper:last"),
+            name = pane.append(json.html).find("#playlist_name_display").text(),
+            tab = "<li id='pl-tab-" + $plCount + "' role='presentation' class='active'><a href='#'>" + name + "</a></li>",
+            tabs = $(".nav.nav-tabs");
+
+        if (json.id) {
+            $openTabs[json.id] = $plCount;
+        }
+
+
+        $(".nav.nav-tabs li").removeClass("active");
+        tabs.append(tab);
+        var newTab = $("#pl-tab-" + $plCount);
+
+        newTab.on("click", function() {
+            AIRTIME.showbuilder.switchTab(t, newTab);
+            $.post(baseUrl+'new-playlist/edit',
+                {format: "json", id: t.find("#obj_id").val(), type: t.find("#obj_type").val()});
+        });
+        AIRTIME.showbuilder.switchTab(t, newTab);
+        AIRTIME.playlist.init();
+
+        //setUpPlaylist();
+        //setCueEvents();
+        //setFadeEvents();
 
         // functions in smart_blockbuilder.js
         setupUI();
@@ -452,6 +485,13 @@ var AIRTIME = (function(AIRTIME){
         $("#pl_edit").hide();
     }
 
+    function closeTab() {
+        delete $openTabs[$(".active-tab").find("#obj_id").val()];
+        $(".nav.nav-tabs .active").remove();
+        $pl.remove();
+        AIRTIME.showbuilder.switchTab($("#show_builder .outer-datatable-wrapper"), $("#timeline-tab"));
+    }
+
     //Purpose of this function is to iterate over all playlist elements
     //and verify whether they can be previewed by the browser or not. If not
     //then the playlist element is greyed out
@@ -514,11 +554,10 @@ var AIRTIME = (function(AIRTIME){
                 }
             }
         });
-    }
+    };
 
     //sets events dynamically for playlist entries (each row in the playlist)
     function setPlaylistEntryEvents() {
-
         $pl.delegate("#spl_sortable .ui-icon-closethick",
                 {"click": function(ev){
                     var id;
@@ -537,7 +576,7 @@ var AIRTIME = (function(AIRTIME){
                     var id = parseInt($(this).attr("id").split("_").pop(), 10);
                     var blockId = parseInt($(this).attr("blockId"), 10);
                     if ($(this).hasClass('close')) {
-                        var sUrl = baseUrl+"playlist/get-block-info";
+                        var sUrl = baseUrl+"new-playlist/get-block-info";
                         mod.disableUI();
                         $.post(sUrl, {format:"json", id:blockId}, function(data){
                             $html = "";
@@ -624,7 +663,7 @@ var AIRTIME = (function(AIRTIME){
         //main playlist fades events
         $pl.on("click", "#spl_crossfade", function() {
             var lastMod = getModified(),
-                type = $('#obj_type').val();
+                type = $pl.find('#obj_type').val();
 
             if ($(this).hasClass("ui-state-active")) {
                 $(this).removeClass("ui-state-active");
@@ -633,7 +672,7 @@ var AIRTIME = (function(AIRTIME){
             else {
                 $(this).addClass("ui-state-active");
 
-                var url = baseUrl+'Playlist/get-playlist-fades';
+                var url = baseUrl+'new-playlist/get-playlist-fades';
                 $.post(url,
                     {format: "json", modified: lastMod, type: type},
                     function(json){
@@ -670,11 +709,11 @@ var AIRTIME = (function(AIRTIME){
         $pl.on("blur", "span.spl_main_fade_in", function(event){
             event.stopPropagation();
 
-            var url = baseUrl+"Playlist/set-playlist-fades",
+            var url = baseUrl+"new-playlist/set-playlist-fades",
                 span = $(this),
                 fadeIn = $.trim(span.text()),
                 lastMod = getModified(),
-                type = $('#obj_type').val();
+                type = $pl.find('#obj_type').val();
 
             if (!isFadeValid(fadeIn)){
                 showError(span, $.i18n._("please put in a time in seconds '00 (.0)'"));
@@ -694,11 +733,11 @@ var AIRTIME = (function(AIRTIME){
         $pl.on("blur", "span.spl_main_fade_out", function(event){
             event.stopPropagation();
 
-            var url = baseUrl+"Playlist/set-playlist-fades",
+            var url = baseUrl+"new-playlist/set-playlist-fades",
                 span = $(this),
                 fadeOut = $.trim(span.text()),
                 lastMod = getModified(),
-                type = $('#obj_type').val();
+                type = $pl.find('#obj_type').val();
 
             if (!isFadeValid(fadeOut)){
                 showError(span, $.i18n._("please put in a time in seconds '00 (.0)'"));
@@ -743,14 +782,14 @@ var AIRTIME = (function(AIRTIME){
 
         $pl.on("click", 'button[id="playlist_shuffle_button"]', function(){
             obj_id = $('input[id="obj_id"]').val();
-            url = baseUrl+"Playlist/shuffle";
+            url = baseUrl+"new-playlist/shuffle";
             enableLoadingIcon();
             $.post(url, {format: "json", obj_id: obj_id}, function(json){
 
                 if (json.error !== undefined) {
                     alert(json.error);
                 }
-                AIRTIME.playlist.fnOpenPlaylist(json);
+                $pl.find(".editor_pane_wrapper").empty().append(json.html);
                 if (json.result == "0") {
                     $pl.find('.success').text($.i18n._('Playlist shuffled'));
                     $pl.find('.success').show();
@@ -760,7 +799,7 @@ var AIRTIME = (function(AIRTIME){
             });
         });
 
-        $pl.on("click", "#webstream_save", function(){
+        $pl.find("#webstream_save").on("click", function(){
             //get all fields and POST to server
             //description
             //stream url
@@ -775,7 +814,7 @@ var AIRTIME = (function(AIRTIME){
             //hide any previous errors (if any)
             $("#side_playlist .errors").empty().hide();
 
-            var url = baseUrl+'Webstream/save';
+            var url = baseUrl+'new-webstream/save';
             $.post(url,
                 {format: "json", id:id, description: description, url:streamurl, length: length, name: name},
                 function(json){
@@ -815,7 +854,7 @@ var AIRTIME = (function(AIRTIME){
 
         $lib.on("click", "#pl_edit", function() {
             openPlaylistPanel();
-            $.ajax( {
+            $.ajax({
                 url : baseUrl+"usersettings/set-library-screen-settings",
                 type : "POST",
                 data : {
@@ -830,18 +869,19 @@ var AIRTIME = (function(AIRTIME){
 
         $pl.on("click", "#lib_pl_close", function() {
             $pl.hide();
-            $("#show_builder").show();
             // We need to update the text on the add button
             AIRTIME.library.checkAddButton();
             // We also need to run the draw callback to update how dragged items are drawn
             AIRTIME.library.fnDrawCallback();
 
-            var name = $('#playlist_name_display').text().trim();
+            var name = $pl.find('#playlist_name_display').text().trim();
 
             if ((name == "Untitled Playlist"
                 || name == "Untitled Smart Block")
-                && $("#spl_sortable .spl_empty").length == 1) {
+                && $pl.find("#spl_sortable .spl_empty").length == 1) {
                 mod.fnDelete();
+            } else {
+                closeTab();
             }
 
             $.ajax( {
@@ -857,16 +897,16 @@ var AIRTIME = (function(AIRTIME){
             });
         });
 
-        $('#save_button').live("click", function(event){
+        $pl.on("click", "#save_button", function(event) {
             /* Smart blocks: get name, description, and criteria
              * Playlists: get name, description
              */
-            var criteria = $('form').serializeArray(),
-                block_name = $('#playlist_name_display').text(),
-                block_desc = $('textarea[name="description"]').val(),
-                save_action = baseUrl+'Playlist/save',
-                obj_id = $('input[id="obj_id"]').val(),
-                obj_type = $('#obj_type').val(),
+            var criteria = $pl.find('form').serializeArray(),
+                block_name = $pl.find('#playlist_name_display').text(),
+                block_desc = $pl.find('textarea[name="description"]').val(),
+                save_action = baseUrl+'new-playlist/save',
+                obj_id = $pl.find('input[id="obj_id"]').val(),
+                obj_type = $pl.find('#obj_type').val(),
                 lastMod = getModified(),
                 dt = $('table[id="library_display"]').dataTable();
             enableLoadingIcon();
@@ -894,8 +934,8 @@ var AIRTIME = (function(AIRTIME){
             );
         });
 
-        $("#pl-bl-clear-content").live("click", function(event) {
-            var sUrl = baseUrl+"playlist/empty-content",
+        $pl.find("#pl-bl-clear-content").live("click", function(event) {
+            var sUrl = baseUrl+"new-playlist/empty-content",
                 oData = {};
             playlistRequest(sUrl, oData);
         });
@@ -994,9 +1034,7 @@ var AIRTIME = (function(AIRTIME){
     }
 
     mod.fnNew = function() {
-        var url = baseUrl+'Playlist/new';
-        $("#side_playlist").show();
-        $("#show_builder").hide();
+        var url = baseUrl+'new-playlist/new';
 
         stopAudioPreview();
 
@@ -1009,9 +1047,7 @@ var AIRTIME = (function(AIRTIME){
     };
 
     mod.fnWsNew = function() {
-        var url = baseUrl+'Webstream/new';
-        $("#side_playlist").show();
-        $("#show_builder").hide();
+        var url = baseUrl+'new-webstream/new';
 
         stopAudioPreview();
 
@@ -1025,9 +1061,7 @@ var AIRTIME = (function(AIRTIME){
 
 
     mod.fnNewBlock = function() {
-        var url = baseUrl+'Playlist/new';
-        $("#side_playlist").show();
-        $("#show_builder").hide();
+        var url = baseUrl+'new-playlist/new';
 
         stopAudioPreview();
 
@@ -1040,18 +1074,14 @@ var AIRTIME = (function(AIRTIME){
     };
 
     mod.fnEdit = function(id, type, url) {
-        $("#side_playlist").show();
-        $("#show_builder").hide();
-
-        if ($pl.is(":hidden")) {
-            openPlaylistPanel();
-        }
+        //openPlaylistPanel();
         stopAudioPreview();
 
         $.post(url,
             {format: "json", id: id, type: type},
             function(json){
                 openPlaylist(json);
+                redrawLib();
             });
     };
 
@@ -1062,13 +1092,14 @@ var AIRTIME = (function(AIRTIME){
         stopAudioPreview();
         id = (plid === undefined) ? getId() : plid;
         lastMod = getModified();
-        type = $('#obj_type').val();
-        url = baseUrl+'Playlist/delete';
+        type = $pl.find('#obj_type').val();
+        url = baseUrl+'new-playlist/delete';
 
         $.post(url,
             {format: "json", ids: id, modified: lastMod, type: type},
-            function(json){
-                openPlaylist(json);
+            function(json) {
+                closeTab();
+                // openPlaylist(json);
                 redrawLib();
             });
     };
@@ -1079,8 +1110,8 @@ var AIRTIME = (function(AIRTIME){
         stopAudioPreview();
         id = (wsid === undefined) ? getId() : wsid;
         lastMod = getModified();
-        type = $('#obj_type').val();
-        url = baseUrl+'Webstream/delete';
+        type = $pl.find('#obj_type').val();
+        url = baseUrl+'new-webstream/delete';
 
         $.post(url,
             {format: "json", ids: id, modified: lastMod, type: type},
@@ -1110,18 +1141,13 @@ var AIRTIME = (function(AIRTIME){
     };
 
     mod.enableUI = function() {
-
         $lib.unblock();
         $pl.unblock();
 
-        //Block UI changes the postion to relative to display the messages.
-        $lib.css("position", "static");
-        $pl.css("position", "static");
         setupUI();
     };
 
     function playlistResponse(json){
-
         if (json.error !== undefined) {
             playlistError(json);
         }
@@ -1135,7 +1161,7 @@ var AIRTIME = (function(AIRTIME){
 
     function playlistRequest(sUrl, oData) {
         var lastMod,
-            obj_type = $('#obj_type').val();
+            obj_type = $pl.find('#obj_type').val();
 
         mod.disableUI();
 
@@ -1153,20 +1179,20 @@ var AIRTIME = (function(AIRTIME){
     }
 
     mod.fnAddItems = function(aItems, iAfter, sAddType) {
-        var sUrl = baseUrl+"playlist/add-items";
+        var sUrl = baseUrl+"new-playlist/add-items";
             oData = {"aItems": aItems, "afterItem": iAfter, "type": sAddType};
         playlistRequest(sUrl, oData);
     };
 
     mod.fnMoveItems = function(aIds, iAfter) {
-        var sUrl = baseUrl+"playlist/move-items",
+        var sUrl = baseUrl+"new-playlist/move-items",
             oData = {"ids": aIds, "afterItem": iAfter};
 
         playlistRequest(sUrl, oData);
     };
 
     mod.fnDeleteItems = function(aItems) {
-        var sUrl = baseUrl+"playlist/delete-items",
+        var sUrl = baseUrl+"new-playlist/delete-items",
             oData = {"ids": aItems};
 
         playlistRequest(sUrl, oData);
@@ -1399,10 +1425,12 @@ var AIRTIME = (function(AIRTIME){
         });
     };
 
+    mod.setAsActive = function() {
+        $pl = $(".active-tab");
+    };
+
     mod.init = function() {
-        $('#new-playlist').live('click', function(){AIRTIME.playlist.fnNew();});
-        $('#new-smart-block').live('click', function(){AIRTIME.playlist.fnNewBlock();});
-        $('#new-webstream').live('click', function(){AIRTIME.playlist.fnWsNew();});
+        AIRTIME.playlist.setAsActive();
 
         $pl.delegate("#spl_delete", {"click": function(ev){
             AIRTIME.playlist.fnDelete();
@@ -1427,15 +1455,6 @@ var AIRTIME = (function(AIRTIME){
 
         initialEvents();
         setUpPlaylist();
-    };
-
-    mod.onReady = function() {
-        $lib = $("#library_content");
-        $pl = $("#side_playlist");
-
-        $pl.hide();
-
-        AIRTIME.playlist.init();
 
         $pl.find(".ui-icon-alert").qtip({
             content: {
@@ -1443,8 +1462,8 @@ var AIRTIME = (function(AIRTIME){
             },
             position: {
                 adjust: {
-                resize: true,
-                method: "flip flip"
+                    resize: true,
+                    method: "flip flip"
                 },
                 at: "right center",
                 my: "left top",
@@ -1458,6 +1477,16 @@ var AIRTIME = (function(AIRTIME){
         });
     };
 
+    mod.onReady = function() {
+        $lib = $("#library_content");
+
+        $('#new-playlist').live('click', function(){AIRTIME.playlist.fnNew();});
+        $('#new-smart-block').live('click', function(){AIRTIME.playlist.fnNewBlock();});
+        $('#new-webstream').live('click', function(){AIRTIME.playlist.fnWsNew();});
+
+        AIRTIME.playlist.init();
+    };
+
     mod.onResize = function() {
     };
 
diff --git a/airtime_mvc/public/js/airtime/library/events/_library_showbuilder.js b/airtime_mvc/public/js/airtime/library/events/_library_showbuilder.js
index 49bf64f27..2cd1b10a3 100644
--- a/airtime_mvc/public/js/airtime/library/events/_library_showbuilder.js
+++ b/airtime_mvc/public/js/airtime/library/events/_library_showbuilder.js
@@ -28,7 +28,7 @@ var AIRTIME = (function(AIRTIME) {
             AIRTIME.button.disableButton("btn-group #library-plus", false);
         }
 
-        if ($("#show_builder").is(":visible")) {
+        if ($("#show_builder_table").is(":visible")) {
             if ($cursor.length !== 0) {
                 btnText = $.i18n._('Add after selected items');
             } else if (current.length !== 0) {
@@ -70,7 +70,7 @@ var AIRTIME = (function(AIRTIME) {
         mod.redrawChosen();
         mod.checkToolBarIcons();
 
-        if ($("#show_builder").is(":visible")) {
+        if ($("#show_builder_table").is(":visible")) {
             $('#library_display tr.lib-audio, tr.lib-pl, tr.lib-stream')
                 .draggable(
                 {
@@ -154,7 +154,7 @@ var AIRTIME = (function(AIRTIME) {
     mod.dblClickAdd = function(data, type) {
         var i, length, temp, aMediaIds = [], aSchedIds = [], aData = [];
 
-        if ($("#show_builder").is(":visible")) {
+        if ($("#show_builder_table").is(":visible")) {
             // process selected files/playlists.
             aMediaIds.push({
                 "id": data.id,
@@ -309,10 +309,10 @@ var AIRTIME = (function(AIRTIME) {
                     buildEditMetadataDialog(json);
                 });
             } else if (data.ftype === "playlist" || data.ftype === "block") {
-                AIRTIME.playlist.fnEdit(data.id, data.ftype, baseUrl+'Playlist/edit');
+                AIRTIME.playlist.fnEdit(data.id, data.ftype, baseUrl+'new-playlist/edit');
                 AIRTIME.playlist.validatePlaylistElements();
             } else if (data.ftype === "stream") {
-                AIRTIME.playlist.fnEdit(data.id, data.ftype, baseUrl + 'Webstream/edit');
+                AIRTIME.playlist.fnEdit(data.id, data.ftype, baseUrl + 'new-webstream/edit');
             }
         });
 
diff --git a/airtime_mvc/public/js/airtime/library/library.js b/airtime_mvc/public/js/airtime/library/library.js
index 23fbc7bd4..735987c49 100644
--- a/airtime_mvc/public/js/airtime/library/library.js
+++ b/airtime_mvc/public/js/airtime/library/library.js
@@ -540,7 +540,7 @@ var AIRTIME = (function(AIRTIME) {
                     dataType: "json"
                   });
                   */
-                
+
                 colReorderMap = oData.ColReorder;
             },
             "fnStateLoad": function fnLibStateLoad(oSettings) {
diff --git a/airtime_mvc/public/js/airtime/showbuilder/_builder.js b/airtime_mvc/public/js/airtime/showbuilder/_builder.js
index 8a53fb9d5..78e2a8d44 100644
--- a/airtime_mvc/public/js/airtime/showbuilder/_builder.js
+++ b/airtime_mvc/public/js/airtime/showbuilder/_builder.js
@@ -106,6 +106,19 @@ var AIRTIME = (function(AIRTIME){
         }
     };
 
+    mod.switchTab = function(tab, el) {
+        $(".active-tab").hide().removeClass("active-tab");
+        tab.addClass("active-tab").show();
+
+        $(".nav.nav-tabs .active").removeClass("active");
+        el.addClass("active");
+
+        if (tab.hasClass("pl-content")) {
+            AIRTIME.playlist.setAsActive();
+        }
+    };
+
+
     mod.checkSelectButton = function() {
         var $selectable = $sbTable.find("tr");
 
@@ -260,10 +273,6 @@ var AIRTIME = (function(AIRTIME){
     mod.enableUI = function() {
         $lib.unblock();
         $sbContent.unblock();
-
-        //Block UI changes the postion to relative to display the messages.
-        $lib.css("position", "static");
-        $sbContent.css("position", "static");
     };
 
     mod.fnItemCallback = function(json) {
@@ -726,7 +735,7 @@ var AIRTIME = (function(AIRTIME){
             },
 
             // R = ColReorder, C = ColVis
-            "sDom": 'R<"dt-process-rel"r><"sb-padded"<"H"C>><"dataTables_scrolling sb-padded"t>',
+            "sDom": 'R<"dt-process-rel"r><"sb-padded"<"H"C>><"dataTables_scrolling sb-padded"t><"F">',
 
             "oColVis": {
                 "aiExclude": [ 0, 1 ],
@@ -950,7 +959,10 @@ var AIRTIME = (function(AIRTIME){
         $sbTable.sortable(sortableConf);
 
         //start setup of the builder toolbar.
-        $toolbar = $(".sb-content .fg-toolbar");
+        $toolbar = $(".sb-content .fg-toolbar:first");
+        var footer = $(".sb-content .fg-toolbar:last"),
+            timerange = $(".sb-timerange");
+        footer.append(timerange);
 
         $menu = $("<div class='btn-toolbar'/>");
         $menu.append("<div class='btn-group'>" +
diff --git a/airtime_mvc/public/js/airtime/showbuilder/_main_builder.js b/airtime_mvc/public/js/airtime/showbuilder/_main_builder.js
index 93ebbc4a0..19c022966 100644
--- a/airtime_mvc/public/js/airtime/showbuilder/_main_builder.js
+++ b/airtime_mvc/public/js/airtime/showbuilder/_main_builder.js
@@ -160,6 +160,10 @@ AIRTIME = (function(AIRTIME) {
         $builder = $("#show_builder");
         $fs = $builder.find('fieldset');
 
+        $("#timeline-tab").on("click", function() {
+            AIRTIME.showbuilder.switchTab($("#show_builder .outer-datatable-wrapper"), $(this));
+        });
+
         /*
          * Icon hover states for search.
          */