"name", "dc:creator" => "creator", "dc:description" => "description", "dcterms:extent" => "length");
public function __construct($p_gunid=NULL)
{
}
public static function Insert($p_values)
{
global $CC_CONFIG, $CC_DBC;
// Create the StoredPlaylist object
$storedPlaylist = new Playlist();
$storedPlaylist->name = isset($p_values['filename']) ? $p_values['filename'] : date("H:i:s");
// NOTE: POSTGRES-SPECIFIC KEYWORD "DEFAULT" BEING USED, WOULD BE "NULL" IN MYSQL
$storedPlaylist->id = isset($p_values['id']) && is_integer($p_values['id'])?"'".$p_values['id']."'":'DEFAULT';
// Insert record into the database
$escapedName = pg_escape_string($storedPlaylist->name);
$CC_DBC->query("BEGIN");
$sql = "INSERT INTO ".$CC_CONFIG['playListTable']
."(id, name, state, mtime)"
." VALUES ({$storedPlaylist->id}, '{$escapedName}', "
." 'incomplete', now())";
$res = $CC_DBC->query($sql);
if (PEAR::isError($res)) {
$CC_DBC->query("ROLLBACK");
return $res;
}
if (!is_integer($storedPlaylist->id)) {
// NOTE: POSTGRES-SPECIFIC
$sql = "SELECT currval('".$CC_CONFIG["playListSequence"]."_seq')";
$storedPlaylist->id = $CC_DBC->getOne($sql);
}
// Save state
$res = $storedPlaylist->setState('ready');
// Commit changes
$res = $CC_DBC->query("COMMIT");
if (PEAR::isError($res)) {
$CC_DBC->query("ROLLBACK");
return $res;
}
// Recall the object to get all the proper values
//$storedPlaylist = Playlist::Recall($storedPlaylist->id);
return $storedPlaylist->id;
}
public static function Delete($id) {
global $CC_CONFIG, $CC_DBC;
$CC_DBC->query("BEGIN");
$sql = "DELETE FROM ".$CC_CONFIG['playListTable']. " WHERE id='{$id}'";
$res = $CC_DBC->query($sql);
if (PEAR::isError($res)) {
$CC_DBC->query("ROLLBACK");
return $res;
}
// Commit changes
$res = $CC_DBC->query("COMMIT");
if (PEAR::isError($res)) {
$CC_DBC->query("ROLLBACK");
return $res;
}
return TRUE;
}
/**
* Fetch instance of StoredPlaylist object.
* @param string $p_gunid
* global unique id of file
* @return StoredFile|Playlist|NULL
* Return NULL if the object doesnt exist in the DB.
*/
public static function Recall($id) {
global $CC_DBC, $CC_CONFIG;
$escapedID = pg_escape_string($id);
$sql = "SELECT id,"
." name, state, currentlyaccessing, editedby, "
." mtime"
." FROM ".$CC_CONFIG['playListTable']
." WHERE id ='{$escapedID}'";
$row = $CC_DBC->getRow($sql);
if (PEAR::isError($row)) {
return FALSE;
}
if (is_null($row)) {
return FALSE;
}
$storedPlaylist = new Playlist($id);
$storedPlaylist->id = $row['id'];
$storedPlaylist->name = $row['name'];
$storedPlaylist->state = $row['state'];
$storedPlaylist->currentlyaccessing = $row['currentlyaccessing'];
$storedPlaylist->editedby = $row['editedby'];
$storedPlaylist->mtime = $row['mtime'];
return $storedPlaylist;
}
/**
* Rename stored virtual playlist
*
* @param string $p_newname
* @return TRUE|PEAR_Error
*/
public function setName($p_newname)
{
global $CC_CONFIG, $CC_DBC;
$escapedName = pg_escape_string($p_newname);
$sql = "UPDATE ".$CC_CONFIG['playListTable']
." SET name='$escapedName', mtime=now()"
." WHERE id='{$this->id}'";
$res = $CC_DBC->query($sql);
if (PEAR::isError($res)) {
return $res;
}
$this->name = $p_newname;
return TRUE;
}
/**
* Get mnemonic playlist name
*
* @param string $p_gunid
* global unique id of playlist
* @return string
*/
public function getName($id=NULL)
{
global $CC_CONFIG, $CC_DBC;
if (is_null($id)) {
return $this->name;
}
$sql = "SELECT name FROM ".$CC_CONFIG['playListTable']
." WHERE id='$id'";
return $CC_DBC->getOne($sql);
}
/**
* Set state of virtual playlist
*
* @param string $p_state
* 'empty'|'incomplete'|'ready'|'edited'
* @param int $p_editedby
* user id | 'NULL' for clear editedBy field
* @return TRUE|PEAR_Error
*/
public function setState($p_state, $p_editedby=NULL)
{
global $CC_CONFIG, $CC_DBC;
$escapedState = pg_escape_string($p_state);
$eb = (!is_null($p_editedby) ? ", editedBy=$p_editedby" : '');
$sql = "UPDATE ".$CC_CONFIG['playListTable']
." SET state='$escapedState'$eb, mtime=now()"
." WHERE id='{$this->id}'";
$res = $CC_DBC->query($sql);
if (PEAR::isError($res)) {
return $res;
}
$this->state = $p_state;
$this->editedby = $p_editedby;
return TRUE;
}
/**
* Get storage-internal file state
*
* @param string $p_gunid
* global unique id of file
* @return string
* see install()
*/
public function getState($id=NULL)
{
global $CC_CONFIG, $CC_DBC;
if (is_null($id)) {
return $this->state;
}
$sql = "SELECT state FROM ".$CC_CONFIG['playListTable']
." WHERE id='$id'";
return $CC_DBC->getOne($sql);
}
/**
* TODO have to change this.
* */
/*
public function isScheduled() {
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT * "
." FROM ".$CC_CONFIG['scheduleTable']
." WHERE ends > now() and playlist=x'{$this->gunid}'::bigint";
$scheduled = $CC_DBC->getAll($sql);
return $scheduled;
}
*/
/**
* Returns true if virtual file is currently in use.
* Static or dynamic call is possible.
*
* @param string $p_gunid
* optional (for static call), global unique id
* @return boolean|PEAR_Error
*/
public function isAccessed($id=NULL)
{
global $CC_CONFIG, $CC_DBC;
if (is_null($id)) {
return ($this->currentlyaccessing > 0);
}
$sql = "SELECT currentlyAccessing FROM ".$CC_CONFIG['playListTable']
." WHERE id='$id'";
$ca = $CC_DBC->getOne($sql);
if (is_null($ca)) {
return PEAR::raiseError(
"StoredPlaylist::isAccessed: invalid id ($id)",
GBERR_FOBJNEX
);
}
return ($ca > 0);
}
/**
* Returns id of user editing playlist
*
* @param string $p_playlistId
* playlist global unique ID
* @return int id of user editing playlist
*/
public function isEdited() {
if($this->state === 'edited') {
return $this->editedby;
}
return FALSE;
}
/**
* Set playlist edit flag
*
* @param string $p_playlistId
* Playlist unique ID
* @param boolean $p_val
* Set/clear of edit flag
* @param string $p_sessid
* Session id
* @param int $p_subjid
* Subject id (if sessid is not specified)
* @return boolean
* TRUE on success.
*/
public function setEditFlag($p_val=TRUE, $p_sessid=NULL, $p_subjid=NULL) {
if (!is_null($p_sessid)) {
$p_subjid = Alib::GetSessUserId($p_sessid);
if (PEAR::isError($p_subjid)) {
return $p_subjid;
}
}
$state = $this->state;
if ($p_val) {
$r = $this->setState('edited', $p_subjid);
} else {
$r = $this->setState('ready', 'NULL');
}
if (PEAR::isError($r)) {
return $r;
}
return TRUE;
}
/**
* Return local ID of virtual file.
*
* @return int
*/
public function getId() {
return $this->id;
}
private function getNextPos() {
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT MAX(position) AS nextPos
FROM cc_playlistcontents
WHERE playlist_id='{$this->getId()}'";
$res = $CC_DBC->getOne($sql);
if(is_null($res))
return 0;
if(PEAR::isError($res)){
return $res;
}
return $res + 1;
}
public function getContents() {
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT *
FROM cc_playlistcontents C JOIN cc_files F ON C.file_id = F.id
WHERE C.playlist_id='{$this->getId()}' ORDER BY C.position";
return $CC_DBC->getAll($sql);
}
public function getLength() {
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT SUM(cliplength) AS length FROM ".$CC_CONFIG['playListContentsTable']
." WHERE playlist_id='{$this->getId()}' group by playlist_id";
$res = $CC_DBC->getRow($sql);
if (PEAR::isError($res)) {
return $res;
}
if(is_null($res))
return '00:00:00.000000';
return $res['length'];
}
/**
* Create instance of Playlist object and insert empty file
*
* @param string $fname
* name of new file
* @return instance of Playlist object
*/
public function create($fname=NULL)
{
$values = array("filename" => $fname);
$pl_id = Playlist::Insert($values);
if (PEAR::isError($pl_id)) {
return $pl_id;
}
return $pl_id;
}
/**
* Lock playlist for edit
*
* @param string $sessid
* session id
* @param int $subjid
* local subject (user) id
* @param boolean $val
* if false do unlock
* @return boolean
* previous state or error object
*/
public function lock($sessid, $subjid=NULL, $val=TRUE)
{
if ($val && $this->isEdited() !== FALSE) {
return PEAR::raiseError(
'Playlist::lock: playlist already locked'
);
}
$r = $this->setEditFlag($val, $sessid, $subjid);
return $r;
}
/**
* Unlock playlist
*
* @param sessId
* reference to GreenBox object
* @return boolean
* previous state or error object
*/
public function unlock($sessid)
{
$r = $this->lock($sessid, NULL, FALSE);
return $r;
}
/**
* Add audioClip specified by local id to the playlist
*
* @param string $acId
* local ID of added file
* @param string $fadeIn
* optional, in time format hh:mm:ss.ssssss - total duration
* @param string $fadeOut
* optional, in time format hh:mm:ss.ssssss - total duration
* @param string $plElGunid
* optional playlist element gunid
* @param string $length
* optional length in in time format hh:mm:ss.ssssss -
* for webstream (or for overrule length of audioclip)
* @param string $clipstart
* optional clipstart in time format hh:mm:ss.ssssss - relative to begin
* @param string $clipend
* optional $clipend in time format hh:mm:ss.ssssss - relative to begin
* @return string
* generated playlistElement gunid
*/
public function addAudioClip($acId, $pos=NULL, $fadeIn=NULL, $fadeOut=NULL, $cliplength=NULL, $cuein=NULL, $cueout=NULL)
{
//get audio clip.
$ac = StoredFile::Recall($acId);
if (is_null($ac) || PEAR::isError($ac)) {
return $ac;
}
// get information about audioClip
$acInfo = $this->getAudioClipInfo($ac);
if (PEAR::isError($acInfo)) {
return $acInfo;
}
extract($acInfo); // 'acGunid', 'acLen', 'acTit', 'elType'
if (!is_null($cliplength)) {
$acLen = $cliplength;
}
//insert at end of playlist.
if(is_null($pos))
$pos = $this->getNextPos();
if (PEAR::isError($pos)) {
return $pos;
}
// insert default values if parameter was empty
$cuein = !is_null($cuein) ? $cuein : '00:00:00.000000';
$cueout = !is_null($cueout) ? $cueout : $acLen;
$acLengthS = $clipLengthS = self::playlistTimeToSeconds($acLen);
if (!is_null($cuein)) {
$clipLengthS = $acLengthS - self::playlistTimeToSeconds($cuein);
}
if (!is_null($cueout)) {
$clipLengthS = $clipLengthS - ($acLengthS - self::playlistTimeToSeconds($cueout));
}
$clipLength = self::secondsToPlaylistTime($clipLengthS);
$res = $this->insertPlaylistElement($this->getId(), $acId, $pos, $clipLength, $cuein, $cueout, $fadeIn, $fadeOut);
if (PEAR::isError($res)) {
return $res;
}
return TRUE;
}
/**
* Remove audioClip from playlist
*
* @param int $position
* position of audioclip in the playlist.
* @return boolean
*/
public function delAudioClip($pos)
{
global $CC_CONFIG, $CC_DBC;
$CC_DBC->query("BEGIN");
$sql = "DELETE FROM ".$CC_CONFIG['playListContentsTable']. " WHERE playlist_id='{$this->getId()}' AND position='{$pos}'";
$res = $CC_DBC->query($sql);
if (PEAR::isError($res)) {
$CC_DBC->query("ROLLBACK");
return $res;
}
// Commit changes
$res = $CC_DBC->query("COMMIT");
if (PEAR::isError($res)) {
$CC_DBC->query("ROLLBACK");
return $res;
}
return TRUE;
}
/**
* Move audioClip to the new position in the playlist
*
* @param int $oldPos
* old positioin in playlist
* @param int $newPos
* new position in playlist
* @return mixed
*/
public function moveAudioClip($oldPos, $newPos)
{
global $CC_CONFIG, $CC_DBC;
$CC_DBC->query("BEGIN");
$sql = "SELECT * FROM ".$CC_CONFIG['playListContentsTable']. " WHERE playlist_id='{$this->getId()}' AND position='{$oldPos}'";
$ac = $CC_DBC->getRow($sql);
if (PEAR::isError($ac)) {
return $ac;
}
$res = $this->delAudioClip($oldPos);
if($res !== TRUE)
return FALSE;
$res = $this->addAudioClip($ac['file_id'], $newPos, $ac['fadein'], $ac['fadeOut'], $ac['cliplength'], $ac['cuein'], $ac['cueout']);
if($res !== TRUE)
return FALSE;
return TRUE;
}
/**
* Change fadeIn and fadeOut values for playlist Element
*
* @param int $pos
* position of audioclip in playlist
* @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($pos, $fadeIn, $fadeOut)
{
global $CC_CONFIG, $CC_DBC;
$CC_DBC->query("BEGIN");
$sql = "UPDATE ".$CC_CONFIG['playListContentsTable']. " SET fadein='{$fadeIn}', fadeout='{$fadeOut}' " .
"WHERE playlist_id='{$this->getId()}' AND position='{$pos}'";
$res = $CC_DBC->query($sql);
if (PEAR::isError($res)) {
$CC_DBC->query("ROLLBACK");
return $res;
}
// Commit changes
$res = $CC_DBC->query("COMMIT");
if (PEAR::isError($res)) {
$CC_DBC->query("ROLLBACK");
return $res;
}
return TRUE;
}
/**
* Change cueIn/cueOut values for playlist element
*
* @param int $pos
* position of audioclip in playlist
* @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($pos, $cueIn, $cueOut)
{
global $CC_CONFIG, $CC_DBC;
$CC_DBC->query("BEGIN");
$sql = "UPDATE ".$CC_CONFIG['playListContentsTable']. " SET cuein='{$cueIn}', cueout='{$cueOut}' " .
"WHERE playlist_id='{$this->getId()}' AND position='{$pos}'";
$res = $CC_DBC->query($sql);
if (PEAR::isError($res)) {
$CC_DBC->query("ROLLBACK");
return $res;
}
// Commit changes
$res = $CC_DBC->query("COMMIT");
if (PEAR::isError($res)) {
$CC_DBC->query("ROLLBACK");
return $res;
}
return TRUE;
}
/**
* Find info about clip at specified offset in playlist.
*
* @param string $offset
* current playtime (hh:mm:ss.ssssss)
* @param int $distance
* 0=current clip; 1=next clip ...
* @return array of matching clip info:
*