CC-84: Smart Playlists

- propel usage chage
- cleaning up code
- some js changes
This commit is contained in:
James 2012-07-18 11:52:09 -04:00
parent 0aae7c75ae
commit 2a38527161
8 changed files with 171 additions and 151 deletions

View File

@ -24,7 +24,7 @@ class PlaylistController extends Zend_Controller_Action
->addActionContext('get-playlist', 'json')
->addActionContext('smart-playlist-criteria-save', 'json')
->addActionContext('smart-playlist-generate', 'json')
->addActionContext('smart-playlist-get', 'json')
->addActionContext('smart-playlist-shuffle', 'json')
->initContext();
$this->pl_sess = new Zend_Session_Namespace(UI_PLAYLIST_SESSNAME);
@ -79,7 +79,6 @@ class PlaylistController extends Zend_Controller_Action
$form = new Application_Form_SmartPlaylistCriteria();
$form->removeDecorator('DtDdWrapper');
$form->startForm($pl->getId());
//$form->loadCriteria($pl->getId());
$this->view->form = $form;
$this->view->pl = $pl;
@ -105,6 +104,12 @@ class PlaylistController extends Zend_Controller_Action
$this->view->error = $e->getMessage();
}
private function playlistDynamic($pl)
{
$this->view->error = "You cannot add tracks to dynamic playlist.";
$this->createFullResponse($pl);
}
private function playlistNotFound()
{
$this->view->error = "Playlist not found";
@ -244,11 +249,15 @@ class PlaylistController extends Zend_Controller_Action
$ids = (!is_array($ids)) ? array($ids) : $ids;
$afterItem = $this->_getParam('afterItem', null);
$addType = $this->_getParam('type', 'after');
try {
$pl = $this->getPlaylist();
$pl->addAudioClips($ids, $afterItem, $addType);
$this->createUpdateResponse($pl);
if ($pl->isStatic()) {
$pl->addAudioClips($ids, $afterItem, $addType);
$this->createUpdateResponse($pl);
} else {
throw new PlaylistDyanmicException;
}
}
catch (PlaylistOutDatedException $e) {
$this->playlistOutdated($pl, $e);
@ -256,6 +265,9 @@ class PlaylistController extends Zend_Controller_Action
catch (PlaylistNotFoundException $e) {
$this->playlistNotFound();
}
catch (PlaylistDyanmicException $e) {
$this->playlistDynamic($pl);
}
catch (Exception $e) {
$this->playlistUnknownError($e);
}
@ -457,32 +469,19 @@ class PlaylistController extends Zend_Controller_Action
{
$request = $this->getRequest();
$params = $request->getPost();
$result = Application_Model_Playlist::saveSmartPlaylistCriteria($params['data'], $params['pl_id']);
$pl = new Application_Model_Playlist($params['pl_id']);
$result = $pl->saveSmartPlaylistCriteria($params['data']);
die(json_encode($result));
/*if ($result['result'] != 0) {
die(json_encode($result));
} else{
try {
$pl = new Application_Model_Playlist($params['pl_id']);
$this->createFullResponse($pl);
}
catch (PlaylistNotFoundException $e) {
$this->playlistNotFound();
}
catch (Exception $e) {
$this->playlistUnknownError($e);
}
}*/
}
public function smartPlaylistGenerateAction()
{
$request = $this->getRequest();
$params = $request->getPost();
$result = Application_Model_Playlist::generateSmartPlaylist($params['data'], $params['pl_id']);
$pl = new Application_Model_Playlist($params['pl_id']);
$result = $pl->generateSmartPlaylist($params['data']);
if ($result['result'] == 0) {
try {
$pl = new Application_Model_Playlist($params['pl_id']);
die(json_encode(array("result"=>0, "html"=>$this->createFullResponse($pl, true))));
}
catch (PlaylistNotFoundException $e) {
@ -496,12 +495,25 @@ class PlaylistController extends Zend_Controller_Action
}
}
public function smartPlaylistGetAction()
{
public function smartPlaylistShuffleAction()
{
$request = $this->getRequest();
$playlistId = $request->getParam('playlistId');
$result = Application_Model_Playlist::getSmartPlaylistCriteria($playlistId);
die(json_encode($result));
$params = $request->getPost();
$pl = new Application_Model_Playlist($params['pl_id']);
$result = $pl->shuffleSmartPlaylist();
if ($result['result'] == 0) {
try {
die(json_encode(array("result"=>0, "html"=>$this->createFullResponse($pl, true))));
}
catch (PlaylistNotFoundException $e) {
$this->playlistNotFound();
}
catch (Exception $e) {
$this->playlistUnknownError($e);
}
}else{
die(json_encode($result));
}
}
}

View File

@ -90,18 +90,10 @@ class Application_Form_SmartPlaylistCriteria extends Zend_Form_SubForm
"minutes" => "minutes",
"items" => "items"
);
$this->setDecorators(array(
array('ViewScript', array('viewScript' => 'form/smart-playlist-criteria.phtml',
'criteriasLength' => count($criteriaOptions)))
));
// load type
$c = new Criteria();
$c->add(CcPlaylistPeer::ID, $p_playlistId);
$out = CcPlaylistPeer::doSelect($c);
if ($out[0]->getDbType() == "static") {
$out = CcPlaylistQuery::create()->findPk($p_playlistId);
if ($out->getDbType() == "static") {
$playlistType = 0;
} else {
$playlistType = 1;
@ -118,9 +110,7 @@ class Application_Form_SmartPlaylistCriteria extends Zend_Form_SubForm
$this->addElement($spType);
// load criteria from db
$c = new Criteria();
$c->add(CcPlaylistcriteriaPeer::PLAYLIST_ID, $p_playlistId);
$out = CcPlaylistcriteriaPeer::doSelect($c);
$out = CcPlaylistcriteriaQuery::create()->findByDbPlaylistId($p_playlistId);
$storedCrit = array();
foreach ($out as $crit) {
@ -136,6 +126,11 @@ class Application_Form_SmartPlaylistCriteria extends Zend_Form_SubForm
}
}
$openSmartPlaylistOption = false;
if (!empty($storedCrit)) {
$openSmartPlaylistOption = true;
}
$numElements = count($criteriaOptions);
for ($i = 0; $i < $numElements; $i++) {
$criteriaType = "";
@ -233,7 +228,10 @@ class Application_Form_SmartPlaylistCriteria extends Zend_Form_SubForm
$shuffle->setLabel('Shuffle');
$shuffle->setDecorators(array('viewHelper'));
$this->addElement($shuffle);
$this->setDecorators(array(
array('ViewScript', array('viewScript' => 'form/smart-playlist-criteria.phtml', "openOption"=> $openSmartPlaylistOption,
'criteriasLength' => count($criteriaOptions)))
));
}
}

View File

@ -59,32 +59,32 @@ class Application_Model_Playlist {
private static $criteria2PeerMap = array(
0 => "Select criteria",
"album_title" => CcFilesPeer::ALBUM_TITLE,
"artist_name" => CcFilesPeer::ARTIST_NAME,
"bit_rate" => CcFilesPeer::BIT_RATE,
"bpm" => CcFilesPeer::BPM,
"comments" => CcFilesPeer::COMMENTS,
"composer" => CcFilesPeer::COMPOSER,
"conductor" => CcFilesPeer::CONDUCTOR,
"utime" => CcFilesPeer::UTIME,
"mtime" => CcFilesPeer::MTIME,
"disc_number" => CcFilesPeer::DISC_NUMBER,
"genre" => CcFilesPeer::GENRE,
"isrc_number" => CcFilesPeer::ISRC_NUMBER,
"label" => CcFilesPeer::LABEL,
"language" => CcFilesPeer::LANGUAGE,
"length" => CcFilesPeer::LENGTH,
"lyricist" => CcFilesPeer::LYRICIST,
"mood" => CcFilesPeer::MOOD,
"name" => CcFilesPeer::NAME,
"orchestra" => CcFilesPeer::ORCHESTRA,
"radio_station_name" => CcFilesPeer::RADIO_STATION_NAME,
"rating" => CcFilesPeer::RATING,
"sample_rate" => CcFilesPeer::SAMPLE_RATE,
"soundcloud_id" => CcFilesPeer::SOUNDCLOUD_ID,
"track_title" => CcFilesPeer::TRACK_TITLE,
"track_num" => CcFilesPeer::TRACK_NUMBER,
"year" => CcFilesPeer::YEAR
"album_title" => "DbAlbumTitle",
"artist_name" => "DbArtistName",
"bit_rate" => "DbBitRate",
"bpm" => "DbBpm",
"comments" => "DbComments",
"composer" => "DbComposer",
"conductor" => "DbConductor",
"utime" => "DbUtime",
"mtime" => "DbMtime",
"disc_number" => "DbDiscNumber",
"genre" => "DbGenre",
"isrc_number" => "DbIsrcNumber",
"label" => "DbLabel",
"language" => "DbLanguage",
"length" => "DbLength",
"lyricist" => "DbLyricist",
"mood" => "DbMood",
"name" => "DbName",
"orchestra" => "DbOrchestra",
"radio_station_name" => "DbRadioStation",
"rating" => "DbRating",
"sample_rate" => "DbSampleRate",
"soundcloud_id" => "DbSoundcloudId",
"track_title" => "DbTrackTitle",
"track_num" => "DbTrackNum",
"year" => "DbYear"
);
@ -292,6 +292,14 @@ class Application_Model_Playlist {
throw new Exception("trying to add a file that does not exist.");
}
}
public function isStatic(){
if ($this->pl->getDbType() == "static") {
return true;
} else {
return false;
}
}
/*
* @param array $p_items
@ -852,20 +860,43 @@ class Application_Model_Playlist {
* Delete all files from playlist
* @param int $p_playlistId
*/
public static function deleteAllFilesFromPlaylist($p_playlistId)
public function deleteAllFilesFromPlaylist()
{
CcPlaylistcontentsQuery::create()->findByDbPlaylistId($p_playlistId)->delete();
CcPlaylistcontentsQuery::create()->findByDbPlaylistId($this->id)->delete();
}
// smart playlist functions start
public function shuffleSmartPlaylist(){
// if it here that means it's static pl
$this->saveType("static");
$contents = CcPlaylistcontentsQuery::create()
->filterByDbPlaylistId($this->id)
->orderByDbPosition()
->find();
$shuffledPos = range(0, count($contents)-1);
shuffle($shuffledPos);
$temp = new CcPlaylist();
foreach ($contents as $item) {
$item->setDbPosition(array_shift($shuffledPos));
$item->save();
}
return array("result"=>0);
}
public function saveType($p_playlistType)
{
// saving dynamic/static flag
CcPlaylistQuery::create()->findPk($this->id)->setDbType($p_playlistType)->save();
}
/**
* Saves smart playlist criteria
* @param array $p_criteria
*/
public static function saveSmartPlaylistCriteria($p_criteria, $p_playlistId)
public function saveSmartPlaylistCriteria($p_criteria)
{
$data = self::organizeSmartPlyalistCriteria($p_criteria);
$data = $this->organizeSmartPlyalistCriteria($p_criteria);
// things we need to check
// 1. limit value shouldn't be empty and has upperbound of 24 hrs
// 2. sp_criteria or sp_criteria_modifier shouldn't be 0
@ -877,10 +908,7 @@ class Application_Model_Playlist {
// saving dynamic/static flag
$playlistType = $data['etc']['sp_type'] == 0 ? 'static':'dynamic';
$playlistCrit = new Criteria();
$playlistCrit->add(CcPlaylistPeer::ID, $p_playlistId);
$playlistCrit->add(CcPlaylistPeer::TYPE, $playlistType);
CcPlaylistPeer::doUpdate($playlistCrit);
$this->saveType($playlistType);
if ($data['etc']['sp_limit_options'] == 'hours') {
$multiplier = 60;
@ -912,7 +940,7 @@ class Application_Model_Playlist {
$error[] = "'Length' should be in '00:00:00' format";
}
}else{
if (CcFilesPeer::getTableMap()->getColumn(self::$criteria2PeerMap[$d['sp_criteria_field']])->getType() == PropelColumnTypes::TIMESTAMP) {
if (CcFilesPeer::getTableMap()->getColumnByPhpName(self::$criteria2PeerMap[$d['sp_criteria_field']])->getType() == PropelColumnTypes::TIMESTAMP) {
if (!preg_match("/(\d{4})-(\d{2})-(\d{2})/", $d['sp_criteria_value'])) {
$error[] = "The value should be in timestamp format(eg. 0000-00-00 or 00-00-00 00:00:00";
}
@ -929,45 +957,35 @@ class Application_Model_Playlist {
}
$result = count($errors) > 0 ? 1 :0;
if ($result == 0) {
self::storeCriteriaIntoDb($data, $p_playlistId);
$this->storeCriteriaIntoDb($data);
}
return array("result"=>$result, "errors"=>$errors);
}
public static function storeCriteriaIntoDb($p_criteriaData, $p_playlistId){
public function storeCriteriaIntoDb($p_criteriaData){
// delete criteria under $p_playlistId
$deleteCrit = new Criteria();
$deleteCrit->add(CcPlaylistcriteriaPeer::PLAYLIST_ID, $p_playlistId);
CcPlaylistcriteriaPeer::doDelete($deleteCrit);
CcPlaylistcriteriaQuery::create()->findByDbPlaylistId($this->id)->delete();
foreach( $p_criteriaData['criteria'] as $d){
$crit = new Criteria();
$crit->add(CcPlaylistcriteriaPeer::CRITERIA, $d['sp_criteria_field']);
$crit->add(CcPlaylistcriteriaPeer::MODIFIER, $d['sp_criteria_modifier']);
$crit->add(CcPlaylistcriteriaPeer::VALUE, $d['sp_criteria_value']);
$qry = new CcPlaylistcriteria();
$qry->setDbCriteria($d['sp_criteria_field'])
->setDbModifier($d['sp_criteria_modifier'])
->setDbValue($d['sp_criteria_value'])
->setDbPlaylistId($this->id);
if (isset($d['sp_criteria_extra'])) {
$crit->add(CcPlaylistcriteriaPeer::EXTRA, $d['sp_criteria_extra']);
$qry->setDbExtra($d['sp_criteria_extra']);
}
$crit->add(CcPlaylistcriteriaPeer::PLAYLIST_ID, $p_playlistId);
CcPlaylistcriteriaPeer::doInsert($crit);
$qry->save();
}
// insert limit info
$crit = new Criteria();
$crit->add(CcPlaylistcriteriaPeer::CRITERIA, "limit");
$crit->add(CcPlaylistcriteriaPeer::MODIFIER, $p_criteriaData['etc']['sp_limit_options']);
$crit->add(CcPlaylistcriteriaPeer::VALUE, $p_criteriaData['etc']['sp_limit_value']);
$crit->add(CcPlaylistcriteriaPeer::PLAYLIST_ID, $p_playlistId);
CcPlaylistcriteriaPeer::doInsert($crit);
}
/**
* Get smart playlist criteria
* @param array $p_playlistId
*/
public static function getSmartPlaylistCriteria($p_playlistId)
{
$qry = new CcPlaylistcriteria();
$qry->setDbCriteria("limit")
->setDbModifier($p_criteriaData['etc']['sp_limit_options'])
->setDbValue($p_criteriaData['etc']['sp_limit_value'])
->setDbPlaylistId($this->id)
->save();
}
/**
@ -975,43 +993,25 @@ class Application_Model_Playlist {
* tracks.
* @param array $p_criteria
*/
public static function generateSmartPlaylist($p_criteria, $p_playlistId, $returnList=false)
public function generateSmartPlaylist($p_criteria, $returnList=false)
{
$result = self::saveSmartPlaylistCriteria($p_criteria, $p_playlistId);
$result = $this->saveSmartPlaylistCriteria($p_criteria);
if ($result['result'] != 0) {
return $result;
} else {
/*$info = self::getListofFilesMeetCriteria($p_playlistId);
$files = $info['files'];
$limit = $info['limit'];
// construct ids of track candidates
self::deleteAllFilesFromPlaylist($p_playlistId);
$playlist = new self($p_playlistId);
$insertList = array();
$totalTime = 0;
while ($totalTime < $limit['time'] && !empty($files)) {
$key = array_rand($files);
$insertList[$key] = $files[$key];
$totalTime += $files[$key];
unset($files[$key]);
if ( !is_null($limit['items']) && $limit['items'] == count($insertList)) {
break;
}
}*/
$insertList = self::getListOfFilesUnderLimit($p_playlistId);
$playlist = new self($p_playlistId);
$playlist->addAudioClips(array_keys($insertList));
return array("result"=>0, "ids"=>array_keys($insertList));
$insertList = $this->getListOfFilesUnderLimit();
$this->deleteAllFilesFromPlaylist();
$this->addAudioClips(array_keys($insertList));
return array("result"=>0);
}
}
public static function getListOfFilesUnderLimit($p_playlistId)
public function getListOfFilesUnderLimit()
{
$info = self::getListofFilesMeetCriteria($p_playlistId);
$info = $this->getListofFilesMeetCriteria();
$files = $info['files'];
$limit = $info['limit'];
// construct ids of track candidates
self::deleteAllFilesFromPlaylist($p_playlistId);
$insertList = array();
$totalTime = 0;
while ($totalTime < $limit['time'] && !empty($files)) {
@ -1027,12 +1027,9 @@ class Application_Model_Playlist {
}
// this function return list of propel object
private static function getListofFilesMeetCriteria($p_playlistId)
private function getListofFilesMeetCriteria()
{
$c = new Criteria();
$c->add(CcPlaylistcriteriaPeer::PLAYLIST_ID, $p_playlistId);
$out = CcPlaylistcriteriaPeer::doSelect($c);
$out = CcPlaylistcriteriaQuery::create()->findByDbPlaylistId($this->id);
$storedCrit = array();
foreach ($out as $crit) {
$criteria = $crit->getDbCriteria();
@ -1046,9 +1043,12 @@ class Application_Model_Playlist {
$storedCrit["crit"][] = array("criteria"=>$criteria, "value"=>$value, "modifier"=>$modifier, "extra"=>$extra);
}
}
$ccFileCriteria = new Criteria();
$qry = CcFilesQuery::create();
foreach ($storedCrit["crit"] as $criteria) {
$spCriteria = self::$criteria2PeerMap[$criteria['criteria']];
// propel doc says we should use phpname for column name but
// it looks like we have to use actual column name
//$spCriteria = self::$criteria2PeerMap[$criteria['criteria']];
$spCriteria = $criteria['criteria'];
$spCriteriaModifier = $criteria['modifier'];
$spCriteriaValue = $criteria['value'];
if ($spCriteriaModifier == "starts with") {
@ -1059,7 +1059,11 @@ class Application_Model_Playlist {
$spCriteriaValue = "$spCriteria > '$spCriteriaValue' AND $spCriteria < '$criteria[extra]'";
}
$spCriteriaModifier = self::$modifier2CriteriaMap[$spCriteriaModifier];
$ccFileCriteria->add($spCriteria, $spCriteriaValue, $spCriteriaModifier);
try{
$qry->filterBy($spCriteria, $spCriteriaValue, $spCriteriaModifier);
}catch (Exception $e){
Logging::log($e);
}
}
// construct limit restriction
$limits = array();
@ -1070,15 +1074,18 @@ class Application_Model_Playlist {
$limits['time'] = $storedCrit['limit']['modifier'] == "hours" ? intval($storedCrit['limit']['value']) * 60 * 60 : intval($storedCrit['limit']['value'] * 60);
$limits['items'] = null;
}
Logging::log("2222");
try{
$out = CcFilesPeer::doSelect($ccFileCriteria);
$out = $qry->find();
Logging::log("3333");
$files = array();
foreach ($out as $file) {
$files[$file->getDbId()] = Application_Common_DateHelper::calculateLengthInSeconds($file->getDbLength());
}
Logging::log($files);
return array("files"=>$files, "limit"=>$limits);
}catch(Exception $e){
//Logging::log($e);
Logging::log($e);
}
}
@ -1106,3 +1113,4 @@ class Application_Model_Playlist {
class PlaylistNotFoundException extends Exception {}
class PlaylistOutDatedException extends Exception {}
class PlaylistDyanmicException extends Exception {}

View File

@ -153,7 +153,7 @@ class Application_Model_Scheduler {
$c = new Criteria();
$c->add(CcPlaylistPeer::ID, $id);
$pl = CcPlaylistPeer::doSelect($c);
$playlistType = $pl->getDbType();
$playlistType = $pl[0]->getDbType();
if ($playlistType == "static") {
$contents = CcPlaylistcontentsQuery::create()
@ -161,14 +161,15 @@ class Application_Model_Scheduler {
->filterByDbPlaylistId($id)
->find($this->con);
} else {
$contents = Application_Model_Playlist::getListOfFilesUnderLimit($id);
$pl = new Application_Model_Playlist($id);
$contents = $pl->getListOfFilesUnderLimit();
}
if (is_null($contents)) {
throw new Exception("A selected Playlist does not exist!");
}
foreach ($contents as $plItem) {
foreach ($contents as $fileId => $plItem) {
$data = $this->fileInfo;
if ($playlistType == "static"){
$file = $plItem->getCcFiles($this->con);
@ -181,10 +182,11 @@ class Application_Model_Scheduler {
$data["fadeout"] = $plItem->getDbFadeout();
}
} else {
// on dynamic playslsit, $plItem is id of files
$file = Application_Model_StoredFile::Recall($plItem);
// on dynamic playslsit, $fileId is id of files
$file = Application_Model_StoredFile::Recall($fileId)->getPropelOrm();
if (isset($file) && $file->getDbFileExists()) {
$data["id"] = $plItem;
$data["id"] = $fileId;
$data["cliplength"] = $file->getDbLength();
}
}
$files[] = $data;

View File

@ -1,5 +1,5 @@
<form id="smart-playlist-form" method="post" action="">
<fieldset class='toggle closed' id='smart_playlist_options' style='overflow-x:auto; width:781px'>
<fieldset class='toggle <?php echo $this->openOption ? "" : "closed"?>' id='smart_playlist_options' style='overflow-x:auto; width:781px'>
<legend style='cursor: pointer;'><span class='ui-icon ui-icon-triangle-2-n-s'></span>Smart Playlist Options</legend>
<dl class='zend_form'>
<div id='sp-success' class='success' style='display:none'></div>

View File

@ -60,7 +60,7 @@ var AIRTIME = (function(AIRTIME) {
count++;
}
}
visibleChosenItems = {};
return count;
};
@ -123,7 +123,7 @@ var AIRTIME = (function(AIRTIME) {
data.push(visibleChosenItems[id]);
}
}
visibleChosenItems = {};
return data;
};
@ -441,7 +441,6 @@ var AIRTIME = (function(AIRTIME) {
$tr = $(el).parent();
data = $tr.data("aData");
AIRTIME.library.dblClickAdd(data.id, data.ftype);
//AIRTIME.playlist.fnAddItems([data.id], undefined, 'after');
}
else
{

View File

@ -674,6 +674,7 @@ var AIRTIME = (function(AIRTIME){
//Block UI changes the postion to relative to display the messages.
$lib.css("position", "static");
$pl.css("position", "static");
setupUI();
};
function playlistResponse(json){

View File

@ -173,7 +173,7 @@ function setupUI() {
$('button[id="generate_button"]').show();
$('button[id="shuffle_button"]').show();
$('#spl_sortable').unblock();
$('#library_content').unblock();
$('#spl_sortable').css("position", "static");
} else {
$('button[id="generate_button"]').hide();
$('button[id="shuffle_button"]').hide();