libretime/airtime_mvc/application/models/Block.php

1328 lines
44 KiB
PHP
Raw Normal View History

<?php
require_once 'formatters/LengthFormatter.php';
2012-07-30 23:31:54 +02:00
/**
*
* @package Airtime
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
*/
class Application_Model_Block implements Application_Model_LibraryEditable
{
2012-07-30 23:31:54 +02:00
/**
* propel connection object.
*/
private $con;
2012-07-30 23:31:54 +02:00
/**
* unique id for the block.
*/
private $id;
private $block;
2012-07-30 23:31:54 +02:00
/**
* info needed to insert a new block element.
*/
private $blockItem = array(
"id" => "",
"pos" => "",
"cliplength" => "",
"cuein" => "00:00:00",
"cueout" => "00:00:00",
"fadein" => "0.0",
"fadeout" => "0.0",
);
2012-07-30 23:31:54 +02:00
//using propel's phpNames.
private $categories = array(
"dc:title" => "Name",
"dc:creator" => "Creator",
"dc:description" => "Description",
"dcterms:extent" => "Length"
);
2012-07-30 23:31:54 +02:00
private static $modifier2CriteriaMap = array(
"contains" => Criteria::ILIKE,
"does not contain" => Criteria::NOT_ILIKE,
"is" => Criteria::EQUAL,
"is not" => Criteria::NOT_EQUAL,
"starts with" => Criteria::ILIKE,
"ends with" => Criteria::ILIKE,
"is greater than" => Criteria::GREATER_THAN,
"is less than" => Criteria::LESS_THAN,
"is in the range" => Criteria::CUSTOM);
2012-07-30 23:31:54 +02:00
private static $criteria2PeerMap = array(
0 => "Select criteria",
"album_title" => "DbAlbumTitle",
"artist_name" => "DbArtistName",
"bit_rate" => "DbBitRate",
"bpm" => "DbBpm",
"comments" => "DbComments",
"composer" => "DbComposer",
"conductor" => "DbConductor",
"utime" => "DbUtime",
"mtime" => "DbMtime",
"lptime" => "DbLPtime",
"disc_number" => "DbDiscNumber",
"genre" => "DbGenre",
"isrc_number" => "DbIsrcNumber",
"label" => "DbLabel",
"language" => "DbLanguage",
"length" => "DbLength",
"lyricist" => "DbLyricist",
"mood" => "DbMood",
"name" => "DbName",
"orchestra" => "DbOrchestra",
"rating" => "DbRating",
"sample_rate" => "DbSampleRate",
"track_title" => "DbTrackTitle",
"track_number" => "DbTrackNumber",
2012-07-30 23:31:54 +02:00
"year" => "DbYear"
);
2012-07-30 23:31:54 +02:00
public function __construct($id=null, $con=null)
{
if (isset($id)) {
$this->block = CcBlockQuery::create()->findPk($id);
2012-07-30 23:31:54 +02:00
if (is_null($this->block)) {
throw new BlockNotFoundException();
}
} else {
$this->block = new CcBlock();
$this->block->setDbUTime(new DateTime("now", new DateTimeZone("UTC")));
$this->block->save();
}
2012-07-30 23:31:54 +02:00
$defaultFade = Application_Model_Preference::GetDefaultFade();
if ($defaultFade !== "") {
//fade is in format SS.uuuuuu
2012-07-30 23:31:54 +02:00
$this->blockItem["fadein"] = $defaultFade;
$this->blockItem["fadeout"] = $defaultFade;
}
2012-07-30 23:31:54 +02:00
$this->con = isset($con) ? $con : Propel::getConnection(CcBlockPeer::DATABASE_NAME);
$this->id = $this->block->getDbId();
}
2012-07-30 23:31:54 +02:00
/**
* Return local ID of virtual file.
*
* @return int
*/
public function getId()
{
return $this->id;
}
2012-07-30 23:31:54 +02:00
/**
* Rename stored virtual block
*
* @param string $p_newname
*/
public function setName($p_newname)
{
$this->block->setDbName($p_newname);
$this->block->setDbMtime(new DateTime("now", new DateTimeZone("UTC")));
$this->block->save($this->con);
}
2012-07-30 23:31:54 +02:00
/**
* Get mnemonic block name
*
* @return string
*/
public function getName()
{
return $this->block->getDbName();
}
2012-07-30 23:31:54 +02:00
public function setDescription($p_description)
{
$this->block->setDbDescription($p_description);
$this->block->setDbMtime(new DateTime("now", new DateTimeZone("UTC")));
$this->block->save($this->con);
}
2012-07-30 23:31:54 +02:00
public function getDescription()
{
return $this->block->getDbDescription();
}
2012-07-30 23:31:54 +02:00
public function getCreator()
{
return $this->block->getCcSubjs()->getDbLogin();
}
2012-07-30 23:31:54 +02:00
public function getCreatorId()
{
return $this->block->getCcSubjs()->getDbId();
}
2012-07-30 23:31:54 +02:00
public function setCreator($p_id)
{
$this->block->setDbCreatorId($p_id);
$this->block->setDbMtime(new DateTime("now", new DateTimeZone("UTC")));
$this->block->save($this->con);
}
2012-07-30 23:31:54 +02:00
public function getLastModified($format = null)
{
return $this->block->getDbMtime($format);
}
2012-07-30 23:31:54 +02:00
public function getSize()
{
return $this->block->countCcBlockcontentss();
}
2012-07-30 23:31:54 +02:00
/**
* Get the entire block as a two dimentional array, sorted in order of play.
* @param boolean $filterFiles if this is true, it will only return files that has
* file_exists flag set to true
* @return array
*/
public function getContents($filterFiles=false)
{
2012-08-22 00:41:56 +02:00
Logging::info("Getting contents for block {$this->id}");
$files = array();
$sql = <<<"EOT"
SELECT pc.id as id, pc.position, pc.cliplength as length, pc.cuein, pc.cueout, pc.fadein, pc.fadeout, bl.type, f.length as orig_length,
f.id as item_id, f.track_title, f.artist_name as creator, f.file_exists as exists, f.filepath as path FROM cc_blockcontents AS pc
LEFT JOIN cc_files AS f ON pc.file_id=f.id
LEFT JOIN cc_block AS bl ON pc.block_id = bl.id
WHERE pc.block_id = {$this->id}
ORDER BY pc.position;
EOT;
$con = Propel::getConnection();
$rows = $con->query($sql)->fetchAll();
$offset = 0;
foreach ($rows as &$row) {
$clipSec = Application_Common_DateHelper::playlistTimeToSeconds($row['length']);
$offset += $clipSec;
$offset_cliplength = Application_Common_DateHelper::secondsToPlaylistTime($offset);
//format the length for UI.
$formatter = new LengthFormatter($row['length']);
$row['length'] = $formatter->format();
$formatter = new LengthFormatter($offset_cliplength);
$row['offset'] = $formatter->format();
//format the fades in format 00(.000000)
$fades = $this->getFadeInfo($row['position']);
$row['fadein'] = $fades[0];
$row['fadeout'] = $fades[1];
//format original length
$formatter = new LengthFormatter($row['orig_length']);
$row['orig_length'] = $formatter->format();
}
2012-07-30 23:31:54 +02:00
return $rows;
}
2012-07-30 23:31:54 +02:00
/**
* The database stores fades in 00:00:00 Time format with optional millisecond resolution .000000
* but this isn't practical since fades shouldn't be very long usuall 1 second or less. This function
* will normalize the fade so that it looks like 00.000000 to the user.
**/
public function normalizeFade($fade)
{
//First get rid of the first six characters 00:00: which will be added back later for db update
$fade = substr($fade, 6);
2012-07-30 23:31:54 +02:00
//Second add .000000 if the fade does't have milliseconds format already
$dbFadeStrPos = strpos( $fade, '.' );
if ( $dbFadeStrPos === False )
$fade .= '.000000';
else
while( strlen( $fade ) < 9 )
$fade .= '0';
2012-07-30 23:31:54 +02:00
//done, just need to set back the formated values
return $fade;
}
public function getUnformatedLength()
2012-07-30 23:31:54 +02:00
{
$this->block->reload();
if ($this->isStatic()) {
$length = $this->block->getDbLength();
} else {
$length = $this->getDynamicBlockLength();
}
return $length;
}
public function getLength()
{
$this->block->reload();
$prepend = "";
if ($this->isStatic()) {
$length = $this->block->getDbLength();
} else {
$length = $this->getDynamicBlockLength();
if (!$this->hasItemLimit()) {
$prepend = "~";
}
}
$formatter = new LengthFormatter($length);
$length = $prepend.$formatter->format();
return $length;
}
public function getDynamicBlockLength()
{
list($value, $modifier) = $this->getLimitValueAndModifier();
if ($modifier == "items") {
$length = $value." ".$modifier;
} else {
$hour = "00";
if ($modifier == "minutes") {
if ($value >59) {
$hour = intval($value/60);
$value = $value%60;
}
} elseif ($modifier == "hours") {
$mins = $value * 60;
if ($mins >59) {
$hour = intval($mins/60);
$hour = str_pad($hour, 2, "0", STR_PAD_LEFT);
$value = $mins%60;
}
}
$hour = str_pad($hour, 2, "0", STR_PAD_LEFT);
$value = str_pad($value, 2, "0", STR_PAD_LEFT);
$length = $hour.":".$value.":00";
}
return $length;
}
public function getLimitValueAndModifier()
{
$result = CcBlockcriteriaQuery::create()->filterByDbBlockId($this->id)
->filterByDbCriteria('limit')->findOne();
$modifier = $result->getDbModifier();
$value = $result->getDbValue();
return array($value, $modifier);
}
// this function returns sum of all track length under this block.
public function getStaticLength()
{
$sql = "SELECT SUM(cliplength) as length FROM cc_blockcontents WHERE block_id={$this->id}";
$r = $this->con->query($sql);
$result = $r->fetchAll(PDO::FETCH_NUM);
return $result[0][0];
2012-07-30 23:31:54 +02:00
}
2012-07-30 23:31:54 +02:00
private function insertBlockElement($info)
{
$row = new CcBlockcontents();
$row->setDbBlockId($this->id);
$row->setDbFileId($info["id"]);
$row->setDbPosition($info["pos"]);
$row->setDbCliplength($info["cliplength"]);
$row->setDbCuein($info["cuein"]);
$row->setDbCueout($info["cueout"]);
$row->setDbFadein($info["fadein"]);
$row->setDbFadeout($info["fadeout"]);
$row->save($this->con);
// above save result update on cc_block table on length column.
// but $this->block doesn't get updated automatically
// so we need to manually grab it again from DB so it has updated values
// It is something to do FORMAT_ON_DEMAND( Lazy Loading )
$this->block = CcBlockQuery::create()->findPK($this->id);
}
2012-07-30 23:31:54 +02:00
/*
*
*/
private function buildEntry($p_item, $pos)
{
$file = CcFilesQuery::create()->findPK($p_item, $this->con);
2012-07-30 23:31:54 +02:00
if (isset($file) && $file->getDbFileExists()) {
$entry = $this->blockItem;
$entry["id"] = $file->getDbId();
$entry["pos"] = $pos;
$entry["cliplength"] = $file->getDbLength();
$entry["cueout"] = $file->getDbLength();
2012-07-30 23:31:54 +02:00
return $entry;
} else {
throw new Exception("trying to add a file that does not exist.");
}
}
public function isStatic()
{
2012-07-30 23:31:54 +02:00
if ($this->block->getDbType() == "static") {
return true;
} else {
return false;
}
}
2012-07-30 23:31:54 +02:00
/*
* @param array $p_items
* an array of audioclips to add to the block
* @param int|null $p_afterItem
* item which to add the new items after in the block, null if added to the end.
* @param string (before|after) $addAfter
* whether to add the clips before or after the selected item.
*/
public function addAudioClips($p_items, $p_afterItem=NULL, $addType = 'after')
{
$this->con->beginTransaction();
$contentsToUpdate = array();
2012-07-30 23:31:54 +02:00
try {
2012-07-30 23:31:54 +02:00
if (is_numeric($p_afterItem)) {
2012-08-22 00:41:56 +02:00
Logging::info("Finding block content item {$p_afterItem}");
2012-07-30 23:31:54 +02:00
$afterItem = CcBlockcontentsQuery::create()->findPK($p_afterItem);
$index = $afterItem->getDbPosition();
2012-08-22 00:41:56 +02:00
Logging::info("index is {$index}");
2012-07-30 23:31:54 +02:00
$pos = ($addType == 'after') ? $index + 1 : $index;
2012-07-30 23:31:54 +02:00
$contentsToUpdate = CcBlockcontentsQuery::create()
->filterByDbBlockId($this->id)
->filterByDbPosition($pos, Criteria::GREATER_EQUAL)
->orderByDbPosition()
->find($this->con);
2012-08-22 00:41:56 +02:00
Logging::info("Adding to block");
Logging::info("at position {$pos}");
2012-07-30 23:31:54 +02:00
} else {
2012-07-30 23:31:54 +02:00
//add to the end of the block
if ($addType == 'after') {
$pos = $this->getSize();
}
//add to the beginning of the block.
else {
$pos = 0;
2012-07-30 23:31:54 +02:00
$contentsToUpdate = CcBlockcontentsQuery::create()
->filterByDbBlockId($this->id)
->orderByDbPosition()
->find($this->con);
}
2012-07-30 23:31:54 +02:00
$contentsToUpdate = CcBlockcontentsQuery::create()
->filterByDbBlockId($this->id)
->filterByDbPosition($pos, Criteria::GREATER_EQUAL)
->orderByDbPosition()
->find($this->con);
2012-08-22 00:41:56 +02:00
Logging::info("Adding to block");
Logging::info("at position {$pos}");
2012-07-30 23:31:54 +02:00
}
2012-07-30 23:31:54 +02:00
foreach ($p_items as $ac) {
2012-08-22 00:41:56 +02:00
Logging::info("Adding audio file {$ac}");
try {
if (is_array($ac) && $ac[1] == 'audioclip') {
$res = $this->insertBlockElement($this->buildEntry($ac[0], $pos));
$pos = $pos + 1;
} elseif (!is_array($ac)) {
$res = $this->insertBlockElement($this->buildEntry($ac, $pos));
$pos = $pos + 1;
}
} catch (Exception $e) {
Logging::log($e->getMessage());
}
2012-07-30 23:31:54 +02:00
}
2012-07-30 23:31:54 +02:00
//reset the positions of the remaining items.
for ($i = 0; $i < count($contentsToUpdate); $i++) {
$contentsToUpdate[$i]->setDbPosition($pos);
$contentsToUpdate[$i]->save($this->con);
$pos = $pos + 1;
}
2012-07-30 23:31:54 +02:00
$this->block->setDbMtime(new DateTime("now", new DateTimeZone("UTC")));
$this->block->save($this->con);
2012-07-30 23:31:54 +02:00
$this->con->commit();
$this->updateBlockLengthInAllPlaylist();
2012-07-30 23:31:54 +02:00
} catch (Exception $e) {
$this->con->rollback();
throw $e;
}
}
2012-07-30 23:31:54 +02:00
/**
* Move audioClip to the new position in the block
*
* @param array $p_items
* array of unique ids of the selected items
* @param int $p_afterItem
* unique id of the item to move the clip after
*/
public function moveAudioClips($p_items, $p_afterItem=NULL)
{
$this->con->beginTransaction();
2012-07-30 23:31:54 +02:00
try {
2012-07-30 23:31:54 +02:00
$contentsToMove = CcBlockcontentsQuery::create()
->filterByDbId($p_items, Criteria::IN)
->orderByDbPosition()
->find($this->con);
2012-07-30 23:31:54 +02:00
$otherContent = CcBlockcontentsQuery::create()
->filterByDbId($p_items, Criteria::NOT_IN)
->filterByDbBlockId($this->id)
->orderByDbPosition()
->find($this->con);
2012-07-30 23:31:54 +02:00
$pos = 0;
//moving items to beginning of the block.
if (is_null($p_afterItem)) {
2012-08-22 00:41:56 +02:00
Logging::info("moving items to beginning of block");
2012-07-30 23:31:54 +02:00
foreach ($contentsToMove as $item) {
2012-08-22 00:41:56 +02:00
Logging::info("item {$item->getDbId()} to pos {$pos}");
2012-07-30 23:31:54 +02:00
$item->setDbPosition($pos);
$item->save($this->con);
$pos = $pos + 1;
}
foreach ($otherContent as $item) {
2012-08-22 00:41:56 +02:00
Logging::info("item {$item->getDbId()} to pos {$pos}");
2012-07-30 23:31:54 +02:00
$item->setDbPosition($pos);
$item->save($this->con);
$pos = $pos + 1;
}
} else {
2012-08-22 00:41:56 +02:00
Logging::info("moving items after {$p_afterItem}");
2012-07-30 23:31:54 +02:00
foreach ($otherContent as $item) {
2012-08-22 00:41:56 +02:00
Logging::info("item {$item->getDbId()} to pos {$pos}");
2012-07-30 23:31:54 +02:00
$item->setDbPosition($pos);
$item->save($this->con);
$pos = $pos + 1;
2012-07-30 23:31:54 +02:00
if ($item->getDbId() == $p_afterItem) {
foreach ($contentsToMove as $move) {
2012-08-22 00:41:56 +02:00
Logging::info("item {$move->getDbId()} to pos {$pos}");
2012-07-30 23:31:54 +02:00
$move->setDbPosition($pos);
$move->save($this->con);
$pos = $pos + 1;
}
}
}
}
2012-07-30 23:31:54 +02:00
$this->con->commit();
} catch (Exception $e) {
$this->con->rollback();
throw $e;
}
2012-07-30 23:31:54 +02:00
$this->block = CcBlockQuery::create()->findPK($this->id);
$this->block->setDbMtime(new DateTime("now", new DateTimeZone("UTC")));
$this->block->save($this->con);
}
2012-07-30 23:31:54 +02:00
/**
* Remove audioClip from block
*
* @param array $p_items
* array of unique item ids to remove from the block..
*/
public function delAudioClips($p_items)
{
2012-07-30 23:31:54 +02:00
$this->con->beginTransaction();
2012-07-30 23:31:54 +02:00
try {
2012-07-30 23:31:54 +02:00
CcBlockcontentsQuery::create()
->findPKs($p_items)
->delete($this->con);
2012-07-30 23:31:54 +02:00
$contents = CcBlockcontentsQuery::create()
->filterByDbBlockId($this->id)
->orderByDbPosition()
->find($this->con);
2012-07-30 23:31:54 +02:00
//reset the positions of the remaining items.
for ($i = 0; $i < count($contents); $i++) {
$contents[$i]->setDbPosition($i);
$contents[$i]->save($this->con);
}
2012-07-30 23:31:54 +02:00
$this->block->setDbMtime(new DateTime("now", new DateTimeZone("UTC")));
$this->block->save($this->con);
2012-07-30 23:31:54 +02:00
$this->con->commit();
$this->updateBlockLengthInAllPlaylist();
2012-07-30 23:31:54 +02:00
} catch (Exception $e) {
$this->con->rollback();
throw $e;
}
}
2012-07-30 23:31:54 +02:00
public function getFadeInfo($pos)
{
2012-08-22 00:41:56 +02:00
Logging::info("Getting fade info for pos {$pos}");
2012-07-30 23:31:54 +02:00
$row = CcBlockcontentsQuery::create()
->joinWith(CcFilesPeer::OM_CLASS)
->filterByDbBlockId($this->id)
->filterByDbPosition($pos)
->findOne();
2012-07-30 23:31:54 +02:00
#Propel returns values in form 00.000000 format which is for only seconds.
$fadeIn = $row->getDbFadein();
$fadeOut = $row->getDbFadeout();
2012-07-30 23:31:54 +02:00
return array($fadeIn, $fadeOut);
}
2012-07-30 23:31:54 +02:00
/**
* Change fadeIn and fadeOut values for block Element
*
* @param int $pos
* position of audioclip in block
* @param string $fadeIn
* new value in ss.ssssss or extent format
* @param string $fadeOut
* new value in ss.ssssss or extent format
* @return boolean
*/
public function changeFadeInfo($id, $fadeIn, $fadeOut)
{
//See issue CC-2065, pad the fadeIn and fadeOut so that it is TIME compatable with the DB schema
//For the top level PlayList either fadeIn or fadeOut will sometimes be Null so need a gaurd against
//setting it to nonNull for checks down below
$fadeIn = $fadeIn?'00:00:'.$fadeIn:$fadeIn;
$fadeOut = $fadeOut?'00:00:'.$fadeOut:$fadeOut;
2012-07-30 23:31:54 +02:00
$this->con->beginTransaction();
2012-07-30 23:31:54 +02:00
$errArray= array();
2012-07-30 23:31:54 +02:00
try {
$row = CcBlockcontentsQuery::create()->findPK($id);
2012-07-30 23:31:54 +02:00
if (is_null($row)) {
throw new Exception("Block item does not exist.");
}
2012-07-30 23:31:54 +02:00
$clipLength = $row->getDbCliplength();
2012-07-30 23:31:54 +02:00
if (!is_null($fadeIn)) {
2012-07-30 23:31:54 +02:00
$sql = "SELECT INTERVAL '{$fadeIn}' > INTERVAL '{$clipLength}'";
$r = $this->con->query($sql);
if ($r->fetchColumn(0)) {
//"Fade In can't be larger than overall playlength.";
$fadeIn = $clipLength;
}
$row->setDbFadein($fadeIn);
}
if (!is_null($fadeOut)) {
2012-07-30 23:31:54 +02:00
$sql = "SELECT INTERVAL '{$fadeOut}' > INTERVAL '{$clipLength}'";
$r = $this->con->query($sql);
if ($r->fetchColumn(0)) {
//Fade Out can't be larger than overall playlength.";
$fadeOut = $clipLength;
}
$row->setDbFadeout($fadeOut);
}
2012-07-30 23:31:54 +02:00
$row->save($this->con);
$this->block->setDbMtime(new DateTime("now", new DateTimeZone("UTC")));
$this->block->save($this->con);
2012-07-30 23:31:54 +02:00
$this->con->commit();
} catch (Exception $e) {
$this->con->rollback();
throw $e;
}
2012-07-30 23:31:54 +02:00
return array("fadeIn" => $fadeIn, "fadeOut" => $fadeOut);
}
public function setfades($fadein, $fadeout)
2012-07-30 23:31:54 +02:00
{
if (isset($fadein)) {
2012-08-22 00:41:56 +02:00
Logging::info("Setting block fade in {$fadein}");
2012-07-30 23:31:54 +02:00
$row = CcBlockcontentsQuery::create()
->filterByDbBlockId($this->id)
->filterByDbPosition(0)
->findOne($this->con);
2012-07-30 23:31:54 +02:00
$this->changeFadeInfo($row->getDbId(), $fadein, null);
}
2012-07-30 23:31:54 +02:00
if (isset($fadeout)) {
2012-08-22 00:41:56 +02:00
Logging::info("Setting block fade out {$fadeout}");
2012-07-30 23:31:54 +02:00
$row = CcBlockcontentsQuery::create()
->filterByDbBlockId($this->id)
->filterByDbPosition($this->getSize()-1)
->findOne($this->con);
2012-07-30 23:31:54 +02:00
$this->changeFadeInfo($row->getDbId(), null, $fadeout);
}
}
2012-07-30 23:31:54 +02:00
/**
* Change cueIn/cueOut values for block element
*
* @param int $pos
* position of audioclip in block
* @param string $cueIn
* new value in ss.ssssss or extent format
* @param string $cueOut
* new value in ss.ssssss or extent format
* @return boolean or pear error object
*/
public function changeClipLength($id, $cueIn, $cueOut)
{
$this->con->beginTransaction();
2012-07-30 23:31:54 +02:00
$errArray= array();
2012-07-30 23:31:54 +02:00
try {
if (is_null($cueIn) && is_null($cueOut)) {
$errArray["error"] = "Cue in and cue out are null.";
2012-07-30 23:31:54 +02:00
return $errArray;
}
2012-07-30 23:31:54 +02:00
$row = CcBlockcontentsQuery::create()
->joinWith(CcFilesPeer::OM_CLASS)
->filterByPrimaryKey($id)
->findOne($this->con);
2012-07-30 23:31:54 +02:00
if (is_null($row)) {
throw new Exception("Block item does not exist.");
}
2012-07-30 23:31:54 +02:00
$oldCueIn = $row->getDBCuein();
$oldCueOut = $row->getDbCueout();
$fadeIn = $row->getDbFadein();
$fadeOut = $row->getDbFadeout();
2012-07-30 23:31:54 +02:00
$file = $row->getCcFiles($this->con);
$origLength = $file->getDbLength();
2012-07-30 23:31:54 +02:00
if (!is_null($cueIn) && !is_null($cueOut)) {
2012-07-30 23:31:54 +02:00
if ($cueOut === "") {
$cueOut = $origLength;
}
2012-07-30 23:31:54 +02:00
$sql = "SELECT INTERVAL '{$cueIn}' > INTERVAL '{$cueOut}'";
$r = $this->con->query($sql);
if ($r->fetchColumn(0)) {
$errArray["error"] = "Can't set cue in to be larger than cue out.";
2012-07-30 23:31:54 +02:00
return $errArray;
}
2012-07-30 23:31:54 +02:00
$sql = "SELECT INTERVAL '{$cueOut}' > INTERVAL '{$origLength}'";
$r = $this->con->query($sql);
if ($r->fetchColumn(0)) {
$errArray["error"] = "Can't set cue out to be greater than file length.";
2012-07-30 23:31:54 +02:00
return $errArray;
}
2012-07-30 23:31:54 +02:00
$sql = "SELECT INTERVAL '{$cueOut}' - INTERVAL '{$cueIn}'";
$r = $this->con->query($sql);
$cliplength = $r->fetchColumn(0);
2012-07-30 23:31:54 +02:00
$row->setDbCuein($cueIn);
$row->setDbCueout($cueOut);
$row->setDBCliplength($cliplength);
2012-07-30 23:31:54 +02:00
} elseif (!is_null($cueIn)) {
2012-07-30 23:31:54 +02:00
$sql = "SELECT INTERVAL '{$cueIn}' > INTERVAL '{$oldCueOut}'";
$r = $this->con->query($sql);
if ($r->fetchColumn(0)) {
$errArray["error"] = "Can't set cue in to be larger than cue out.";
2012-07-30 23:31:54 +02:00
return $errArray;
}
2012-07-30 23:31:54 +02:00
$sql = "SELECT INTERVAL '{$oldCueOut}' - INTERVAL '{$cueIn}'";
$r = $this->con->query($sql);
$cliplength = $r->fetchColumn(0);
2012-07-30 23:31:54 +02:00
$row->setDbCuein($cueIn);
$row->setDBCliplength($cliplength);
} elseif (!is_null($cueOut)) {
2012-07-30 23:31:54 +02:00
if ($cueOut === "") {
$cueOut = $origLength;
}
2012-07-30 23:31:54 +02:00
$sql = "SELECT INTERVAL '{$cueOut}' < INTERVAL '{$oldCueIn}'";
$r = $this->con->query($sql);
if ($r->fetchColumn(0)) {
$errArray["error"] = "Can't set cue out to be smaller than cue in.";
2012-07-30 23:31:54 +02:00
return $errArray;
}
2012-07-30 23:31:54 +02:00
$sql = "SELECT INTERVAL '{$cueOut}' > INTERVAL '{$origLength}'";
$r = $this->con->query($sql);
if ($r->fetchColumn(0)) {
$errArray["error"] = "Can't set cue out to be greater than file length.";
2012-07-30 23:31:54 +02:00
return $errArray;
}
2012-07-30 23:31:54 +02:00
$sql = "SELECT INTERVAL '{$cueOut}' - INTERVAL '{$oldCueIn}'";
$r = $this->con->query($sql);
$cliplength = $r->fetchColumn(0);
2012-07-30 23:31:54 +02:00
$row->setDbCueout($cueOut);
$row->setDBCliplength($cliplength);
}
2012-07-30 23:31:54 +02:00
$cliplength = $row->getDbCliplength();
2012-07-30 23:31:54 +02:00
$sql = "SELECT INTERVAL '{$fadeIn}' > INTERVAL '{$cliplength}'";
$r = $this->con->query($sql);
if ($r->fetchColumn(0)) {
$fadeIn = $cliplength;
$row->setDbFadein($fadeIn);
}
2012-07-30 23:31:54 +02:00
$sql = "SELECT INTERVAL '{$fadeOut}' > INTERVAL '{$cliplength}'";
$r = $this->con->query($sql);
if ($r->fetchColumn(0)) {
$fadeOut = $cliplength;
$row->setDbFadein($fadeOut);
}
2012-07-30 23:31:54 +02:00
$row->save($this->con);
$this->block->setDbMtime(new DateTime("now", new DateTimeZone("UTC")));
$this->block->save($this->con);
2012-07-30 23:31:54 +02:00
$this->con->commit();
} catch (Exception $e) {
$this->con->rollback();
throw $e;
}
return array("cliplength"=> $cliplength, "cueIn"=> $cueIn, "cueOut"=> $cueOut, "length"=> $this->getUnformatedLength(),
2012-07-30 23:31:54 +02:00
"fadeIn"=> $fadeIn, "fadeOut"=> $fadeOut);
}
2012-07-30 23:31:54 +02:00
public function getAllPLMetaData()
{
$categories = $this->categories;
$md = array();
2012-07-30 23:31:54 +02:00
foreach ($categories as $key => $val) {
$method = 'get' . $val;
$md[$key] = $this->$method();
}
2012-07-30 23:31:54 +02:00
return $md;
}
2012-07-30 23:31:54 +02:00
public function getMetaData($category)
{
$cat = $this->categories[$category];
$method = 'get' . $cat;
return $this->$method();
}
public function setMetadata($category, $value)
2012-07-30 23:31:54 +02:00
{
$cat = $this->categories[$category];
2012-07-30 23:31:54 +02:00
$method = 'set' . $cat;
$this->$method($value);
}
2012-07-30 23:31:54 +02:00
public static function getBlockCount()
{
global $CC_CONFIG;
$con = Propel::getConnection();
$sql = 'SELECT count(*) as cnt FROM '.$CC_CONFIG["playListTable"];
2012-07-30 23:31:54 +02:00
return $con->query($sql)->fetchColumn(0);
}
2012-07-30 23:31:54 +02:00
/**
* Delete the file from all blocks.
* @param string $p_fileId
*/
public static function DeleteFileFromAllBlocks($p_fileId)
{
CcBlockcontentsQuery::create()->filterByDbFileId($p_fileId)->delete();
}
2012-07-30 23:31:54 +02:00
/**
* Delete blocks that match the ids..
* @param array $p_ids
*/
public static function deleteBlocks($p_ids, $p_userId)
{
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new Application_Model_User($userInfo->id);
$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
if (!$isAdminOrPM) {
$leftOver = self::blocksNotOwnedByUser($p_ids, $p_userId);
if (count($leftOver) == 0) {
CcBlockQuery::create()->findPKs($p_ids)->delete();
} else {
throw new BlockNoPermissionException;
}
2012-07-30 23:31:54 +02:00
} else {
CcBlockQuery::create()->findPKs($p_ids)->delete();
2012-07-30 23:31:54 +02:00
}
}
2012-07-30 23:31:54 +02:00
// This function returns that are not owen by $p_user_id among $p_ids
private static function blocksNotOwnedByUser($p_ids, $p_userId)
2012-07-30 23:31:54 +02:00
{
$ownedByUser = CcBlockQuery::create()->filterByDbCreatorId($p_userId)->find()->getData();
$selectedPls = $p_ids;
$ownedPls = array();
foreach ($ownedByUser as $pl) {
if (in_array($pl->getDbId(), $selectedPls)) {
$ownedPls[] = $pl->getDbId();
}
}
2012-07-30 23:31:54 +02:00
$leftOvers = array_diff($selectedPls, $ownedPls);
2012-07-30 23:31:54 +02:00
return $leftOvers;
}
2012-07-30 23:31:54 +02:00
/**
* Delete all files from block
*/
public function deleteAllFilesFromBlock()
{
CcBlockcontentsQuery::create()->findByDbBlockId($this->id)->delete();
$this->block->reload();
2012-07-30 23:31:54 +02:00
}
2012-07-30 23:31:54 +02:00
// smart block functions start
public function shuffleSmartBlock()
{
2012-07-30 23:31:54 +02:00
// if it here that means it's static pl
$this->saveType("static");
$contents = CcBlockcontentsQuery::create()
->filterByDbBlockId($this->id)
->orderByDbPosition()
->find();
$shuffledPos = range(0, count($contents)-1);
shuffle($shuffledPos);
foreach ($contents as $item) {
$item->setDbPosition(array_shift($shuffledPos));
$item->save();
}
2012-07-30 23:31:54 +02:00
return array("result"=>0);
}
2012-07-30 23:31:54 +02:00
public function saveType($p_blockType)
{
// saving dynamic/static flag
CcBlockQuery::create()->findPk($this->id)->setDbType($p_blockType)->save();
}
public function setLength($value)
{
$this->block->setDbLength($value);
$this->block->save($this->con);
$this->updateBlockLengthInAllPlaylist();
}
2012-07-30 23:31:54 +02:00
/**
* Saves smart block criteria
* @param array $p_criteria
*/
public function saveSmartBlockCriteria($p_criteria)
{
$data = $this->organizeSmartPlyalistCriteria($p_criteria);
// saving dynamic/static flag
$blockType = $data['etc']['sp_type'] == 0 ? 'static':'dynamic';
$this->saveType($blockType);
$this->storeCriteriaIntoDb($data);
//get number of files that meet the criteria
$files = $this->getListofFilesMeetCriteria();
// if the block is dynamic, put null to the length
// as it cannot be calculated
if ($blockType == 'dynamic') {
if ($this->hasItemLimit()) {
$this->setLength(null);
2012-07-30 23:31:54 +02:00
} else {
$this->setLength($this->getDynamicBlockLength());
2012-07-30 23:31:54 +02:00
}
} else {
$length = $this->getStaticLength();
if (!$length) {
$length = "00:00:00";
2012-07-30 23:31:54 +02:00
}
$this->setLength($length);
2012-07-30 23:31:54 +02:00
}
$this->updateBlockLengthInAllPlaylist();
2012-07-30 23:31:54 +02:00
}
public function hasItemLimit()
{
list($value, $modifier) = $this->getLimitValueAndModifier();
if ($modifier == 'items') {
return true;
} else {
return false;
}
}
public function storeCriteriaIntoDb($p_criteriaData)
{
2012-07-30 23:31:54 +02:00
// delete criteria under $p_blockId
CcBlockcriteriaQuery::create()->findByDbBlockId($this->id)->delete();
2012-08-22 00:41:56 +02:00
Logging::info($p_criteriaData);
//insert modifier rows
if (isset($p_criteriaData['criteria'])) {
$critKeys = array_keys($p_criteriaData['criteria']);
for ($i = 0; $i < count($critKeys); $i++) {
foreach ($p_criteriaData['criteria'][$critKeys[$i]] as $d) {
$qry = new CcBlockcriteria();
$qry->setDbCriteria($d['sp_criteria_field'])
->setDbModifier($d['sp_criteria_modifier'])
->setDbValue($d['sp_criteria_value'])
->setDbBlockId($this->id);
if (isset($d['sp_criteria_extra'])) {
$qry->setDbExtra($d['sp_criteria_extra']);
}
$qry->save();
}
}
2012-07-30 23:31:54 +02:00
}
2012-07-30 23:31:54 +02:00
// insert limit info
$qry = new CcBlockcriteria();
$qry->setDbCriteria("limit")
->setDbModifier($p_criteriaData['etc']['sp_limit_options'])
->setDbValue($p_criteriaData['etc']['sp_limit_value'])
->setDbBlockId($this->id)
->save();
}
2012-07-30 23:31:54 +02:00
/**
* generate list of tracks. This function saves creiteria and generate
* tracks.
* @param array $p_criteria
*/
public function generateSmartBlock($p_criteria, $returnList=false)
{
2012-08-16 21:40:36 +02:00
$this->saveSmartBlockCriteria($p_criteria);
$insertList = $this->getListOfFilesUnderLimit();
$this->deleteAllFilesFromBlock();
$this->addAudioClips(array_keys($insertList));
// update length in playlist contents.
$this->updateBlockLengthInAllPlaylist();
2012-08-16 21:40:36 +02:00
return array("result"=>0);
2012-07-30 23:31:54 +02:00
}
public function updateBlockLengthInAllPlaylist()
{
$blocks = CcPlaylistcontentsQuery::create()->filterByDbBlockId($this->id)->find();
$blocks->getFirst();
$iterator = $blocks->getIterator();
while ($iterator->valid()) {
$length = $this->getUnformatedLength();
if (!preg_match("/^[0-9]{2}:[0-9]{2}:[0-9]{2}/", $length)) {
$iterator->current()->setDbClipLength(null);
} else {
$iterator->current()->setDbClipLength($length);
}
$iterator->current()->save();
$iterator->next();
}
}
2012-07-30 23:31:54 +02:00
public function getListOfFilesUnderLimit()
{
$info = $this->getListofFilesMeetCriteria();
$files = $info['files'];
$limit = $info['limit'];
2012-07-30 23:31:54 +02:00
$insertList = array();
$totalTime = 0;
$totalItems = 0;
2012-07-30 23:31:54 +02:00
// this moves the pointer to the first element in the collection
$files->getFirst();
$iterator = $files->getIterator();
while ($iterator->valid() && $totalTime < $limit['time']) {
$id = $iterator->current()->getDbId();
$length = Application_Common_DateHelper::calculateLengthInSeconds($iterator->current()->getDbLength());
$insertList[$id] = $length;
$totalTime += $length;
$totalItems++;
if ((!is_null($limit['items']) && $limit['items'] == count($insertList)) || $totalItems > 500) {
2012-07-30 23:31:54 +02:00
break;
}
2012-07-30 23:31:54 +02:00
$iterator->next();
}
2012-07-30 23:31:54 +02:00
return $insertList;
}
public function getCriteria()
{
$criteriaOptions = array(
0 => "Select criteria",
"album_title" => "Album",
"bit_rate" => "Bit Rate",
"bpm" => "Bpm",
"comments" => "Comments",
"composer" => "Composer",
"conductor" => "Conductor",
"artist_name" => "Creator",
"disc_number" => "Disc Number",
"genre" => "Genre",
"isrc_number" => "ISRC",
"label" => "Label",
"language" => "Language",
"mtime" => "Last Modified",
"lptime" => "Last Played",
"length" => "Length",
"lyricist" => "Lyricist",
"mood" => "Mood",
"name" => "Name",
"orchestra" => "Orchestra",
"rating" => "Rating",
"sample_rate" => "Sample Rate",
"track_title" => "Title",
"track_number" => "Track Number",
"utime" => "Uploaded",
"year" => "Year"
);
// Load criteria from db
$out = CcBlockcriteriaQuery::create()->orderByDbCriteria()->findByDbBlockId($this->id);
$storedCrit = array();
foreach ($out as $crit) {
$criteria = $crit->getDbCriteria();
$modifier = $crit->getDbModifier();
$value = $crit->getDbValue();
$extra = $crit->getDbExtra();
if ($criteria == "limit") {
$storedCrit["limit"] = array("value"=>$value, "modifier"=>$modifier);
} else {
$storedCrit["crit"][$criteria][] = array("criteria"=>$criteria, "value"=>$value, "modifier"=>$modifier, "extra"=>$extra, "display_name"=>$criteriaOptions[$criteria]);
}
}
return $storedCrit;
}
2012-07-30 23:31:54 +02:00
// this function return list of propel object
public function getListofFilesMeetCriteria()
{
$storedCrit = $this->getCriteria();
2012-07-30 23:31:54 +02:00
$qry = CcFilesQuery::create();
2012-07-30 23:31:54 +02:00
if (isset($storedCrit["crit"])) {
foreach ($storedCrit["crit"] as $crit) {
$i = 0;
foreach ($crit as $criteria) {
$spCriteriaPhpName = self::$criteria2PeerMap[$criteria['criteria']];
$spCriteria = $criteria['criteria'];
$spCriteriaModifier = $criteria['modifier'];
$column = CcFilesPeer::getTableMap()->getColumnByPhpName(self::$criteria2PeerMap[$spCriteria]);
// if the column is timestamp, convert it into UTC
if ($column->getType() == PropelColumnTypes::TIMESTAMP) {
$spCriteriaValue = Application_Common_DateHelper::ConvertToUtcDateTimeString($criteria['value']);
/* Check if only a date was supplied and trim
* the time after it is converted to UTC time
*/
if (strlen($criteria['value']) <= 10) {
//extract date only from timestamp in db
$spCriteria = 'date('.$spCriteria.')';
$spCriteriaValue = substr($spCriteriaValue, 0, 10);
}
if (isset($criteria['extra'])) {
$spCriteriaExtra = Application_Common_DateHelper::ConvertToUtcDateTimeString($criteria['extra']);
if (strlen($criteria['extra']) <= 10) {
$spCriteriaExtra = substr($spCriteriaExtra, 0, 10);
}
}
} elseif ($spCriteria == "bit_rate" || $spCriteria == 'sample_rate') {
// multiply 1000 because we store only number value
// e.g 192kps is stored as 192000
$spCriteriaValue = $criteria['value']*1000;
if (isset($criteria['extra'])) {
$spCriteriaExtra = $criteria['extra']*1000;
}
/*
* If user is searching for an exact match of length we need to
* search as if it starts with the specified length because the
* user only sees the rounded version (i.e. 4:02.7 is 4:02.761625
* in the database)
*/
} elseif ($spCriteria == 'length' && $spCriteriaModifier == "is") {
$spCriteriaModifier = "starts with";
$spCriteria = $spCriteria.'::text';
$spCriteriaValue = $criteria['value'];
} else {
/* Propel does not escape special characters properly when using LIKE/ILIKE
* We have to add extra slashes in these cases
*/
$tempModifier = trim(self::$modifier2CriteriaMap[$spCriteriaModifier]);
if ($tempModifier == 'ILIKE') {
$spCriteriaValue = addslashes($criteria['value']);
// addslashes() does not esapce '%' so we have to do it manually
$spCriteriaValue = str_replace('%', '\%', $spCriteriaValue);
} else {
$spCriteriaValue = ($criteria['value']);
}
$spCriteriaExtra = $criteria['extra'];
}
if ($spCriteriaModifier == "starts with") {
$spCriteriaValue = "$spCriteriaValue%";
} elseif ($spCriteriaModifier == "ends with") {
$spCriteriaValue = "%$spCriteriaValue";
} elseif ($spCriteriaModifier == "contains" || $spCriteriaModifier == "does not contain") {
$spCriteriaValue = "%$spCriteriaValue%";
} elseif ($spCriteriaModifier == "is in the range") {
$spCriteriaValue = "$spCriteria >= '$spCriteriaValue' AND $spCriteria <= '$spCriteriaExtra'";
}
$spCriteriaModifier = self::$modifier2CriteriaMap[$spCriteriaModifier];
2012-08-24 03:43:55 +02:00
try {
if ($i > 0) {
$qry->addOr($spCriteria, $spCriteriaValue, $spCriteriaModifier);
} else {
$qry->add($spCriteria, $spCriteriaValue, $spCriteriaModifier);
}
2012-08-24 03:43:55 +02:00
} catch (Exception $e) {
2012-08-22 00:41:56 +02:00
Logging::info($e);
}
$i++;
2012-07-30 23:31:54 +02:00
}
}
$qry->addAscendingOrderByColumn('random()');
2012-07-30 23:31:54 +02:00
}
// construct limit restriction
$limits = array();
if (isset($storedCrit['limit'])) {
if ($storedCrit['limit']['modifier'] == "items") {
$limits['time'] = 1440 * 60;
$limits['items'] = $storedCrit['limit']['value'];
} else {
$limits['time'] = $storedCrit['limit']['modifier'] == "hours" ?
intval(floatval($storedCrit['limit']['value']) * 60 * 60) :
intval($storedCrit['limit']['value'] * 60);
2012-07-30 23:31:54 +02:00
$limits['items'] = null;
}
}
2012-08-24 03:43:55 +02:00
try {
2012-07-30 23:31:54 +02:00
$out = $qry->setFormatter(ModelCriteria::FORMAT_ON_DEMAND)->find();
2012-07-30 23:31:54 +02:00
return array("files"=>$out, "limit"=>$limits, "count"=>$out->count());
2012-08-24 03:43:55 +02:00
} catch (Exception $e) {
2012-08-22 00:41:56 +02:00
Logging::info($e);
2012-07-30 23:31:54 +02:00
}
}
public static function organizeSmartPlyalistCriteria($p_criteria)
2012-07-30 23:31:54 +02:00
{
$fieldNames = array('sp_criteria_field', 'sp_criteria_modifier', 'sp_criteria_value', 'sp_criteria_extra');
$output = array();
foreach ($p_criteria as $ele) {
$index = strrpos($ele['name'], '_');
/* Strip field name of modifier index
* Ex: sp_criteria_field_0_0 -> sp_criteria_field_0
*/
$fieldName = substr($ele['name'], 0, $index);
// Get criteria row index.
$tempName = $ele['name'];
// Get the last digit in the field name
preg_match('/^\D*(?=\d)/', $tempName, $r);
if (isset($r[0])) {
$critIndexPos = strlen($r[0]);
$critIndex = $tempName[$critIndexPos];
}
$lastChar = substr($ele['name'], -1);
// If lastChar is an integer we should strip it off
if (!preg_match("/^[a-zA-Z]$/", $lastChar)) {
/* Strip field name of criteria index
* Ex: sp_criteria_field_0 -> sp_criteria_field
* We do this to check if the field name is a criteria
* or the block type
*/
$n = strrpos($fieldName, '_');
$fieldName = substr($fieldName, 0, $n);
}
if (in_array($fieldName, $fieldNames)) {
$rowNum = intval(substr($ele['name'], $index+1));
$output['criteria'][$critIndex][$lastChar][$fieldName] = trim($ele['value']);
} else {
$output['etc'][$ele['name']] = $ele['value'];
2012-07-30 23:31:54 +02:00
}
}
2012-07-30 23:31:54 +02:00
return $output;
}
// smart block functions end
}
2012-07-30 23:31:54 +02:00
class BlockNotFoundException extends Exception {}
class BlockNoPermissionException extends Exception {}
class BlockOutDatedException extends Exception {}
class BlockDyanmicException extends Exception {}