libretime/backend/Playlist.php

1498 lines
44 KiB
PHP

<?php
define('INDCH', ' ');
/**
* Auxiliary class for GreenBox playlist editing methods.
*
* remark: dcterms:extent format: hh:mm:ss.ssssss
*
* @package Campcaster
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
*/
class Playlist {
// *** Variable stored in the database ***
/**
* @var int
*/
private $id;
/**
* @var string
*/
private $name;
/**
* Can be 'ready', 'edited', 'incomplete'.
*
* @var string
*/
private $state;
/**
* @var int
*/
private $currentlyaccessing;
/**
* @var int
*/
private $editedby;
/**
* @var timestamp
*/
private $mtime;
/**
* @var MetaData
*/
public $md;
//using propel's phpNames.
private $categories = array("dc:title" => "DbName", "dc:creator" => "DbCreator", "dc:description" => "DbDescription", "dcterms:extent" => "length");
/**
* @param string $p_gunid
*/
public function __construct($p_gunid=NULL)
{
}
/**
* @param array $p_name
* The name of the playlist
*/
private static function Insert($p_name = null)
{
// Create the StoredPlaylist object
$storedPlaylist = new Playlist();
$storedPlaylist->name = !empty($p_name) ? $p_name : date("H:i:s");
$storedPlaylist->mtime = new DateTime("now");
$pl = new CcPlaylist();
$pl->setDbName($storedPlaylist->name);
$pl->setDbState("incomplete");
$pl->setDbMtime($storedPlaylist->mtime);
$pl->save();
$storedPlaylist->id = $pl->getDbId();
$storedPlaylist->setState('ready');
return $storedPlaylist->id;
}
public static function Delete($id) {
$pl = CcPlaylistQuery::create()->findPK($id);
if($pl === NULL)
return FALSE;
$pl->delete();
return TRUE;
}
/**
* Delete the file from all playlists.
* @param string $p_fileId
*/
public static function DeleteFileFromAllPlaylists($p_fileId)
{
CcPlaylistcontentsQuery::create()->filterByDbFileId($p_fileId)->delete();
}
/**
* Fetch instance of Playlist object.<br>
*
* @param string $id
* DB id of file
* @return Playlist|FALSE
* Return FALSE if the object doesnt exist in the DB.
*/
public static function Recall($id) {
$pl = CcPlaylistQuery::create()->findPK($id);
if($pl === NULL)
return FALSE;
$storedPlaylist = new Playlist();
$storedPlaylist->id = $pl->getDbId();
$storedPlaylist->name = $pl->getDbName();
$storedPlaylist->state = $pl->getDbState();
$storedPlaylist->currentlyaccessing = $pl->getDbCurrentlyaccessing();
$storedPlaylist->editedby = $pl->getDbEditedby();
$storedPlaylist->mtime = $pl->getDbMtime();
return $storedPlaylist;
}
/**
* Rename stored virtual playlist
*
* @param string $p_newname
* @return TRUE|PEAR_Error
*/
public function setName($p_newname)
{
$pl = CcPlaylistQuery::create()->findPK($this->id);
if($pl === NULL)
return FALSE;
$pl->setDbName($p_newname);
$pl->setDbMtime(new DateTime("now"));
$pl->save();
$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)
{
if (is_null($id)) {
return $this->name;
}
$pl = CcPlaylistQuery::create()->findPK($id);
if($pl === NULL)
return FALSE;
return $pl->getDbName();
}
/**
* 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)
{
$pl = CcPlaylistQuery::create()->findPK($this->id);
if($pl === NULL)
return FALSE;
$pl->setDbState($p_state);
$pl->setDbMtime(new DateTime("now"));
$eb = (!is_null($p_editedby) ? $p_editedby : NULL);
$pl->setDbEditedby($eb);
$pl->save();
$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)
{
if (is_null($id)) {
return $this->state;
}
$pl = CcPlaylistQuery::create()->findPK($id);
if($pl === NULL)
return FALSE;
return $pl->getDbState();
}
/**
* 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.<br>
* 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)
{
if (is_null($id)) {
return ($this->currentlyaccessing > 0);
}
$pl = CcPlaylistQuery::create()->findPK($id);
if (is_null($pl)) {
return PEAR::raiseError(
"StoredPlaylist::isAccessed: invalid id ($id)",
GBERR_FOBJNEX
);
}
return ($pl->getDbCurrentlyaccessing() > 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;
}
}
if ($p_val) {
$r = $this->setState('edited', $p_subjid);
} else {
$r = $this->setState('ready');
}
if ($r === FALSE) {
return FALSE;
}
return TRUE;
}
/**
* Return local ID of virtual file.
*
* @return int
*/
public function getId() {
return $this->id;
}
private function getNextPos() {
$res = CcPlaylistQuery::create()
->findPK($this->id)
->computeLastPosition();
if(is_null($res)) {
return 0;
}
return $res + 1;
}
/**
* Get the entire playlist as a two dimentional array, sorted in order of play.
* @return array
*/
public function getContents() {
$files = array();
$rows = CcPlaylistcontentsQuery::create()
->joinWith('CcFiles')
->orderByDbPosition()
->filterByDbPlaylistId($this->id)
->find();
foreach ($rows as $row) {
$files[] = $row->toArray(BasePeer::TYPE_FIELDNAME, true, true);
}
return $files;
}
public function getLength() {
$res = CcPlaylistQuery::create()
->findPK($this->id)
->computeLength();
if(is_null($res)) {
return '00:00:00.000000';
}
return $res;
}
/**
* 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)
{
$pl_id = Playlist::Insert($fname);
$this->id = $pl_id;
return $this->id;
}
public static function findPlaylistByName($p_name)
{
$res = CcPlaylistQuery::create()->findByDbName($p_name);
return $res;
}
/**
* 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 audio clip to the playlist
*
* @param string $p_id
* local ID of added file
* @param string $p_position
* optional, Which position in the playlist to insert the audio clip
* @param string $p_fadeIn
* optional, in time format hh:mm:ss.ssssss - total duration
* @param string $p_fadeOut
* optional, in time format hh:mm:ss.ssssss - total duration
* @param string $p_clipLength
* optional length in in time format hh:mm:ss.ssssss -
* for webstream (or for overrule length of audioclip)
* @return true|PEAR_Error
* TRUE on success
*/
public function addAudioClip($p_mediaId, $p_position=NULL, $p_fadeIn=NULL, $p_fadeOut=NULL, $p_clipLength=NULL, $p_cuein=NULL, $p_cueout=NULL)
{
$_SESSION['debug'] = "in add";
//get audio clip.
$media = StoredFile::Recall($p_mediaId);
if (is_null($media) || PEAR::isError($media)) {
return $media;
}
// get information about audioClip
// $acInfo = $this->getAudioClipInfo($ac);
// if (PEAR::isError($acInfo)) {
// return $acInfo;
// }
// extract($acInfo); // 'acGunid', 'acLen', 'acTit', 'elType'
$metadata = $media->getMetadata();
$length = $metadata["length"];
if (!is_null($p_clipLength)) {
$length = $p_clipLength;
}
// insert at end of playlist.
if (is_null($p_position))
$p_position = $this->getNextPos();
if (PEAR::isError($p_position)) {
return $p_position;
}
// insert default values if parameter was empty
$p_cuein = !is_null($p_cuein) ? $p_cuein : '00:00:00.000000';
$p_cueout = !is_null($p_cueout) ? $p_cueout : $length;
$mediaLengthSec = $clipLengthSec = self::playlistTimeToSeconds($length);
if (!is_null($p_cuein)) {
$clipLengthSec = $mediaLengthSec - self::playlistTimeToSeconds($p_cuein);
}
if (!is_null($p_cueout)) {
$clipLengthSec = $clipLengthSec - ($mediaLengthSec - self::playlistTimeToSeconds($p_cueout));
}
$p_clipLength = self::secondsToPlaylistTime($clipLengthSec);
$res = $this->insertPlaylistElement($this->id, $p_mediaId, $p_position, $p_clipLength, $p_cuein, $p_cueout, $p_fadeIn, $p_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)
{
if($pos < 0 || $pos >= $this->getNextPos())
return FALSE;
$row = CcPlaylistcontentsQuery::create()
->filterByDbPlaylistId($this->id)
->filterByDbPosition($pos)
->findOne();
if(is_null($row))
return FALSE;
$row->delete();
return $row;
}
/**
* 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)
{
if($newPos < 0 || $newPos >= $this->getNextPos() || $oldPos < 0 || $oldPos >= $this->getNextPos())
return FALSE;
$row = $this->delAudioClip($oldPos);
if($row === FALSE)
return FALSE;
$res = $this->addAudioClip($row->getDbFileId(), $newPos, $row->getDbFadein(), $row->getDbFadeout(), $row->getDbCliplength(), $row->getDbCuein(), $row->getDbCueout());
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)
{
$errArray= array();
if(is_null($pos) || $pos < 0 || $pos >= $this->getNextPos()) {
$errArray["error"]="Invalid position.";
return $errArray;
}
$row = CcPlaylistcontentsQuery::create()
->filterByDbPlaylistId($this->id)
->filterByDbPosition($pos)
->findOne();
$clipLength = $row->getDbCliplength();
if(!is_null($fadeIn) && !is_null($fadeOut)) {
if(Playlist::playlistTimeToSeconds($fadeIn) > Playlist::playlistTimeToSeconds($clipLength)) {
$errArray["error"]="Fade In can't be larger than overall playlength.";
return $errArray;
}
if(Playlist::playlistTimeToSeconds($fadeOut) > Playlist::playlistTimeToSeconds($clipLength)) {
$errArray["error"]="Fade Out can't be larger than overall playlength.";
return $errArray;
}
$row->setDbFadein($fadeIn);
$row->setDbFadeout($fadeOut);
}
else if(!is_null($fadeIn)) {
if(Playlist::playlistTimeToSeconds($fadeIn) > Playlist::playlistTimeToSeconds($clipLength)) {
$errArray["error"]="Fade In can't be larger than overall playlength.";
return $errArray;
}
$row->setDbFadein($fadeIn);
}
else if(!is_null($fadeOut)){
if(Playlist::playlistTimeToSeconds($fadeOut) > Playlist::playlistTimeToSeconds($clipLength)) {
$errArray["error"]="Fade Out can't be larger than overall playlength.";
return $errArray;
}
$row->setDbFadeout($fadeOut);
}
$row->save();
return array("fadeIn"=>$fadeIn, "fadeOut"=>$fadeOut);
}
/**
* 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)
{
$errArray= array();
if(is_null($cueIn) && is_null($cueOut)) {
$errArray["error"]="Cue in and cue out are null.";
return $errArray;
}
if(is_null($pos) || $pos < 0 || $pos >= $this->getNextPos()) {
$errArray["error"]="Invalid position.";
return $errArray;
}
$row = CcPlaylistcontentsQuery::create()
->joinWith(CcFiles)
->filterByDbPlaylistId($this->id)
->filterByDbPosition($pos)
->findOne();
$oldCueIn = $row->getDBCuein();
$oldCueOut = $row->getDbCueout();
$fadeIn = $row->getDbFadein();
$fadeOut = $row->getDbFadeout();
$file = $row->getCcFiles();
$origLength = $file->getDbLength();
if(!is_null($cueIn) && !is_null($cueOut)){
if($cueOut === ""){
$cueOut = $origLength;
}
if(Playlist::playlistTimeToSeconds($cueIn) > Playlist::playlistTimeToSeconds($cueOut)) {
$errArray["error"]= "Can't set cue in to be larger than cue out.";
return $errArray;
}
if(Playlist::playlistTimeToSeconds($cueOut) > Playlist::playlistTimeToSeconds($origLength)){
$errArray["error"] = "Can't set cue out to be greater than file length.";
return $errArray;
}
$row->setDbCuein($cueIn);
$row->setDbCueout($cueOut);
$row->setDBCliplength(Playlist::secondsToPlaylistTime(Playlist::playlistTimeToSeconds($cueOut)
- Playlist::playlistTimeToSeconds($cueIn)));
}
else if(!is_null($cueIn)) {
if(Playlist::playlistTimeToSeconds($cueIn) > Playlist::playlistTimeToSeconds($oldCueOut)) {
$errArray["error"] = "Can't set cue in to be larger than cue out.";
return $errArray;
}
$row->setDbCuein($cueIn);
$row->setDBCliplength(Playlist::secondsToPlaylistTime(Playlist::playlistTimeToSeconds($oldCueOut)
- Playlist::playlistTimeToSeconds($cueIn)));
}
else if(!is_null($cueOut)) {
if($cueOut === ""){
$cueOut = $origLength;
}
if(Playlist::playlistTimeToSeconds($cueOut) < Playlist::playlistTimeToSeconds($oldCueIn)) {
$errArray["error"] ="Can't set cue out to be smaller than cue in.";
return $errArray;
}
if(Playlist::playlistTimeToSeconds($cueOut) > Playlist::playlistTimeToSeconds($origLength)){
$errArray["error"] ="Can't set cue out to be greater than file length.";
return $errArray;
}
$row->setDbCueout($cueOut);
$row->setDBCliplength(Playlist::secondsToPlaylistTime(Playlist::playlistTimeToSeconds($cueOut)
- Playlist::playlistTimeToSeconds($oldCueIn)));
}
$cliplength = $row->getDbCliplength();
if(Playlist::playlistTimeToSeconds($fadeIn) > Playlist::playlistTimeToSeconds($cliplength)){
$fadeIn = $cliplength;
$row->setDbFadein($fadeIn);
}
if(Playlist::playlistTimeToSeconds($fadeOut) > Playlist::playlistTimeToSeconds($cliplength)){
$fadeOut = $cliplength;
$row->setDbFadein($fadeOut);
}
$row->save();
return array("cliplength"=>$cliplength, "cueIn"=>$cueIn, "cueOut"=>$cueOut, "length"=>$this->getLength(),
"fadeIn"=>$fadeIn, "fadeOut"=>$fadeOut);
}
/**
* 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:
* <ul>
* <li>gunid string, global unique id of clip</li>
* <li>elapsed string, already played time of clip</li>
* <li>remaining string, remaining time of clip</li>
* <li>duration string, total playlength of clip </li>
* </ul>
*/
public function getPlaylistClipAtPosition($pos)
{
}
public function getPLMetaData($category)
{
$cat = $this->categories[$category];
if($cat === 'length') {
return $this->getLength();
}
$row = CcPlaylistQuery::create()->findPK($this->id);
$method = 'get' . $cat;
return $row->$method();
}
public function setPLMetaData($category, $value)
{
$cat = $this->categories[$category];
$row = CcPlaylistQuery::create()->findPK($this->id);
$method = 'set' . $cat;
$row->$method($value);
$row->save();
return TRUE;
}
/**
* Return array with gunids of all sub-playlists and clips used in
* the playlist
*
* @return array with hash elements:
* gunid - global id
* type - playlist | audioClip
*/
public function export()
{
}
/**
* Convert playlist time value to float seconds
*
* @param string $plt
* playlist time value (HH:mm:ss.dddddd)
* @return int
* seconds
*/
public static function playlistTimeToSeconds($plt)
{
$arr = preg_split('/:/', $plt);
if (isset($arr[2])) {
return (intval($arr[0])*60 + intval($arr[1]))*60 + floatval($arr[2]);
}
if (isset($arr[1])) {
return intval($arr[0])*60 + floatval($arr[1]);
}
return floatval($arr[0]);
}
/**
* Convert float seconds value to playlist time format
*
* @param float $seconds
* @return string
* time in playlist time format (HH:mm:ss.dddddd)
*/
public static function secondsToPlaylistTime($p_seconds)
{
$seconds = $p_seconds;
$milliseconds = intval(($seconds - intval($seconds)) * 1000);
$milliStr = str_pad($milliseconds, 6, '0');
$hours = floor($seconds / 3600);
$seconds -= $hours * 3600;
$minutes = floor($seconds / 60);
$seconds -= $minutes * 60;
$res = sprintf("%02d:%02d:%02d.%s", $hours, $minutes, $seconds, $milliStr);
return $res;
}
/**
* Export playlist as simplified SMIL XML file.
*
* @param boolean $toString
* if false don't real export,
* return misc info about playlist only
* @return string
* XML string or hasharray with misc info
*/
public function outputToSmil($toString=TRUE)
{
}
/**
* Export playlist as M3U file.
*
* @param boolean $toString
* if false don't real export,
* return misc info about playlist only
* @return string|array
* M3U string or hasharray with misc info
*/
public function outputToM3u($toString=TRUE)
{
}
/**
* Export playlist as RSS XML file
*
* @param boolean $toString
* if false don't really export,
* return misc info about playlist only
* @return mixed
* XML string or hasharray with misc info
*/
public function outputToRss($toString=TRUE)
{
}
/**
* Get audioClip length and title
*
* @param StoredFile $p_media
*
* @return array with fields:
* <ul>
* <li>acGunid, string - audioClip gunid</li>
* <li>acLen string - length of clip in dcterms:extent format</li>
* <li>acTit string - clip title</li>
* <li>elType string - audioClip | playlist</li>
* </ul>
*/
// private function getAudioClipInfo($p_media)
// {
// $ac_id = $p_media->getId();
//
// $r = $p_media->getMetadataValue('dcterms:extent');
// if (isset($r)) {
// $acLen = $r;
// } else {
// $acLen = '00:00:00.000000';
// }
//
// $r = $p_media->getMetadataValue('dc:title');
// if (isset($r)) {
// $acTit = $r;
// } else {
// $acTit = $acGunid;
// }
// $elType = $p_media->getType();
// $trTbl = array('audioclip'=>'audioClip', 'webstream'=>'audioClip','playlist'=>'playlist');
// $elType = $trTbl[$elType];
//
// return compact('acGunid', 'acLen', 'acTit', 'elType');
// }
/**
* Insert a new playlist element.
*
* @param int $plId
* id of Playlist
* @param int $fileId
* id of File
* @param string $offset
* relative offset in extent format
* @param string $clipstart
* audioClip clipstart in extent format
* @param string $clipEnd
* audioClip clipEnd in extent format
* @param string $clipLength
* audioClip playlength in extent format (?)
* @param string $acGunid
* audioClip gunid
* @param string $acLen
* audioClip length in extent format
* @param string $acTit
* audioClip title
* @param string $fadeIn
* fadeIn value in ss.ssssss or extent format
* @param string $fadeOut
* fadeOut value in ss.ssssss or extent format
* @return array with fields:
* <ul>
* <li>plElId int - record id of playlistElement</li>
* <li>plElGunid string - gl.unique id of playlistElement</li>
* <li>fadeInId int - record id</li>
* <li>fadeOutId int - record id</li>
* </ul>
*/
private function insertPlaylistElement($plId, $fileId, $pos, $clipLength, $cuein, $cueout, $fadeIn=NULL, $fadeOut=NULL)
{
if(is_null($fadeIn))
$fadeIn = '00:00:00.000';
if(is_null($fadeOut))
$fadeOut = '00:00:00.000';
$row = new CcPlaylistcontents();
$row->setDbPlaylistId($plId);
$row->setDbFileId($fileId);
$row->setDbPosition($pos);
$row->save();
$row->setDbCliplength($clipLength);
$row->setDbCuein($cuein);
$row->setDbCueout($cueout);
$row->setDbFadein($fadeIn);
$row->setDbFadeout($fadeOut);
return TRUE;
}
/**
* Set playlist length - dcterm:extent
*
* @param string $newPlLen
* new length in extent format
* @param int $parid
* playlist container record id
* @param int $metaParid
* metadata container record id
* @return boolean
*/
private function setPlaylistLength($newPlLen, $parid, $metaParid)
{
$mid = $this->_getMidOrInsert('playlength', $parid, $newPlLen, 'A');
if (PEAR::isError($mid)) {
return $mid;
}
$r = $this->_setValueOrInsert(
$mid, $newPlLen, $parid, 'playlength', 'A');
if (PEAR::isError($r)) {
return $r;
}
$mid = $this->_getMidOrInsert('dcterms:extent', $metaParid, $newPlLen);
if (PEAR::isError($mid)) {
return $mid;
}
$r = $this->_setValueOrInsert(
$mid, $newPlLen, $metaParid, 'dcterms:extent');
if (PEAR::isError($r)) {
return $r;
}
return TRUE;
}
} // class Playlist
/**
* Auxiliary class for GB playlist editing methods
*
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
*/
class PlaylistElement {
private $pl = NULL;
private $plEl = NULL;
public function PlaylistElement($pl, $plEl)
{
$this->pl = $pl;
$this->plEl = $plEl;
}
public function analyze()
{
$plInfo = array(
'acLen' => '00:00:00.000000',
'acLenS' => 0,
'fadeIn' => '00:00:00.000000',
'fadeInS' => 0,
'fadeOut' => '00:00:00.000000',
'fadeOutS' => 0,
'clipStart' => '00:00:00.000000',
'clipStartS' => 0,
'clipEnd' => '00:00:00.000000',
'clipEndS' => 0
);
$plInfo['elOffset'] = $this->plEl['attrs']['relativeOffset'];
$plInfo['elOffsetS'] = Playlist::playlistTimeToSeconds($plInfo['elOffset']);
// cycle over tags inside playlistElement
foreach ($this->plEl['children'] as $j => $acFi) {
switch ($acFi['elementname']) {
case "playlist":
$plInfo['type'] = 'playlist';
break;
case "audioClip":
$plInfo['type'] = 'audioClip';
break;
}
switch ($acFi['elementname']) {
case "playlist":
case "audioClip":
$plInfo['acLen'] = $acFi['attrs']['playlength'];
$plInfo['acLenS'] = Playlist::playlistTimeToSeconds($plInfo['acLen']);
$plInfo['acGunid'] = $acFi['attrs']['id'];
break;
case "fadeInfo":
$plInfo['fadeIn'] = $acFi['attrs']['fadeIn'];
$plInfo['fadeInS'] = Playlist::playlistTimeToSeconds($plInfo['fadeIn']);
$plInfo['fadeOut'] = $acFi['attrs']['fadeOut'];
$plInfo['fadeOutS'] = Playlist::playlistTimeToSeconds($plInfo['fadeOut']);
break;
}
$plInfo['clipStart'] = $this->plEl['attrs']['clipStart'];
$plInfo['clipStartS'] = Playlist::playlistTimeToSeconds($this->plEl['attrs']['clipStart']);
$plInfo['clipEnd'] = $this->plEl['attrs']['clipEnd'];
$plInfo['clipEndS'] = Playlist::playlistTimeToSeconds($this->plEl['attrs']['clipEnd']);
}
return $plInfo;
}
} // class PlaylistElement
/**
* @package Campcaster
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
* @todo Rename this class PlaylistTag
*/
class PlaylistTagExport
{
public static function OutputToSmil(&$pl, $plt, $ind='')
{
$ind2 = $ind.INDCH;
$ind3 = $ind2.INDCH;
$ind4 = $ind3.INDCH;
$res = "";
foreach ($plt['children'] as $ple) {
switch ($ple['elementname']) {
case "playlistElement":
$r = PlaylistElementExport::OutputToSmil($pl, $ple, $ind4);
if (PEAR::isError($r)) {
return $r;
}
if (!is_null($r)) {
$res .= $r;
}
break;
case "metadata":
$r = PlaylistMetadataExport::OutputToSmil($pl, $ple, $ind4);
if (PEAR::isError($r)) {
return $r;
}
if (!is_null($r)) {
$res .= $r;
}
break;
default:
}
}
$res = "$ind<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n".
"$ind<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n".
"$ind2<body>\n".
"$ind3<par>\n".
"$res".
"$ind3</par>\n".
"$ind2</body>\n".
"$ind</smil>\n";
return $res;
}
public static function OutputToM3u(&$pl, $plt, $ind='')
{
$res = "";
foreach ($plt['children'] as $ple) {
switch ($ple['elementname']) {
case"playlistElement":
$r = PlaylistElementExport::OutputToM3u($pl, $ple);
if (PEAR::isError($r)) {
return $r;
}
if (!is_null($r)) {
$res .= $r;
}
break;
}
}
$res = "#EXTM3U\n$res";
return $res;
}
public static function OutputToRss(&$pl, $plt, $ind='')
{
$ind2 = $ind.INDCH;
$ind3 = $ind2.INDCH;
$res = "";
foreach ($plt['children'] as $ple) {
switch ($ple['elementname']) {
case "playlistElement":
$r = PlaylistElementExport::OutputToRss($pl, $ple, $ind3);
if (PEAR::isError($r)) {
return $r;
}
if (!is_null($r)) {
$res .= $r;
}
break;
case "metadata":
$r = PlaylistMetadataExport::OutputToRss($pl, $ple, $ind3);
if (PEAR::isError($r)) {
return $r;
}
if (!is_null($r)) {
$res .= $r;
}
break;
default:
}
}
$res = "$ind<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n".
"$ind<rss version=\"2.0\">\n".
"$ind2<channel>\n".
"$res".
"$ind2</channel>\n".
"$ind</rss>\n";
return $res;
}
}
/**
* @package Campcaster
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
* @todo Rename this class "PlaylistElement"
*/
class PlaylistElementExport {
public static function OutputToSmil(&$pl, $ple, $ind='')
{
$acOrPl = NULL;
$finfo = array('fi'=>0, 'fo'=>0);
$ind2 = $ind.INDCH;
$ind3 = $ind2.INDCH;
$anim = '';
foreach ($ple['children'] as $ac) {
switch ($ac['elementname']) {
case "audioClip":
$r = PlaylistAudioClipExport::OutputToSmil($pl, $ac, $ind2);
if (PEAR::isError($r)) {
return $r;
}
if (!is_null($r)) {
$acOrPl = $r;
}
break;
case "playlist":
$gunid = $ac['attrs']['id'];
$pl2 = StoredFile::RecallByGunid($gunid);
if (is_null($pl2) || PEAR::isError($pl2)) {
return $pl2;
}
$r = $pl2->outputToSmil(FALSE);
if (PEAR::isError($r)) {
return $r;
}
if (!is_null($r)) {
$acOrPl = $r;
}
break;
case "fadeInfo":
$r = PlaylistFadeInfoExport::OutputToSmil($pl, $ac, $ind2);
if (PEAR::isError($r)) {
return $r;
}
if (!is_null($r)) {
$finfo = $r;
}
break;
default:
return PEAR::raiseError(
"PlaylistElementExport::OutputToSmil:".
" unknown tag {$ac['elementname']}"
);
}
}
$beginS = Playlist::playlistTimeToSeconds($ple['attrs']['relativeOffset']);
$playlengthS = Playlist::playlistTimeToSeconds($acOrPl['playlength']);
$fadeOutS = Playlist::playlistTimeToSeconds($finfo['fo']);
$fiBeginS = 0;
$fiEndS = Playlist::playlistTimeToSeconds($finfo['fi']);
$foBeginS = ($playlengthS - $fadeOutS);
$foEndS = Playlist::playlistTimeToSeconds($acOrPl['playlength']);
foreach (array('fi','fo') as $ff) {
if (${$ff."EndS"} - ${$ff."BeginS"} > 0) {
$anim .= "{$ind2}<animate attributeName = \"soundLevel\"\n".
"{$ind3}from = \"".($ff == 'fi' ? 0 : 100)."%\"\n".
"{$ind3}to = \"".($ff == 'fi' ? 100 : 0)."%\"\n".
"{$ind3}calcMode = \"linear\"\n".
"{$ind3}begin = \"{${$ff."BeginS"}}s\"\n".
"{$ind3}end = \"{${$ff."EndS"}}s\"\n".
"{$ind3}fill = \"freeze\"\n".
"{$ind2}/>\n"
;
}
}
$src = $acOrPl['src'];
$str = "$ind<audio src=\"$src\" begin=\"{$beginS}s\"".
($anim ? ">\n$anim$ind</audio>" : " />").
" <!-- {$acOrPl['type']}, {$acOrPl['gunid']}, {$acOrPl['playlength']} -->".
"\n";
return $str;
}
public static function OutputToM3u(&$pl, $ple, $ind='')
{
$acOrPl = NULL;
foreach ($ple['children'] as $ac) {
switch ($ac['elementname']) {
case "audioClip":
$r = PlaylistAudioClipExport::OutputToM3u($pl, $ac);
if (PEAR::isError($r)) {
return $r;
}
if (!is_null($r)) {
$acOrPl = $r;
}
break;
case "playlist":
$gunid = $ac['attrs']['id'];
$pl2 = StoredFile::RecallByGunid($gunid);
if (is_null($pl2) || PEAR::isError($pl2)) {
return $pl2;
}
$r = $pl2->outputToM3u(FALSE);
if (PEAR::isError($r)) {
return $r;
}
if (!is_null($r)) {
$acOrPl = $r;
}
break;
}
}
if (is_null($acOrPl)) {
return '';
}
$playlength = ceil(Playlist::playlistTimeToSeconds($acOrPl['playlength']));
$title = $acOrPl['title'];
$uri = (isset($acOrPl['uri']) ? $acOrPl['uri'] : '???' );
$res = "#EXTINF: $playlength, $title\n";
$res .= "$uri\n";
return $res;
}
public static function OutputToRss(&$pl, $ple, $ind='')
{
$acOrPl = NULL;
$ind2 = $ind.INDCH;
$anim = '';
foreach ($ple['children'] as $ac) {
switch ($ac['elementname']) {
case "audioClip":
$r = PlaylistAudioClipExport::OutputToRss($pl, $ac, $ind2);
if (PEAR::isError($r)) {
return $r;
}
if (!is_null($r)) {
$acOrPl = $r;
}
break;
case "playlist":
$gunid = $ac['attrs']['id'];
$pl2 = StoredFile::RecallByGunid($gunid);
if (is_null($pl2) || PEAR::isError($pl2)) {
return $pl2;
}
$r = $pl2->outputToRss(FALSE);
if (PEAR::isError($r)) {
return $r;
}
if (!is_null($r)) {
$acOrPl = $r;
}
break;
case "fadeInfo":
break;
default:
return PEAR::raiseError(
"PlaylistElementExport::OutputToRss:".
" unknown tag {$ac['elementname']}"
);
}
}
$title = (isset($acOrPl['title']) ? htmlspecialchars($acOrPl['title']) : '' );
$desc = (isset($acOrPl['desc']) ? htmlspecialchars($acOrPl['desc']) : '' );
$link = htmlspecialchars($acOrPl['src']);
$desc = '';
$str = "$ind<item>\n".
"$ind2<title>$title</title>\n".
"$ind2<description>$desc</description>\n".
"$ind2<link>$link</link>\n".
"$ind</item>\n";
return $str;
}
}
/**
* @package Campcaster
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
* @todo Rename this class to PlaylistAudioClip (notice the caps)
*/
class PlaylistAudioClipExport
{
public static function OutputToSmil(&$pl, $plac, $ind='')
{
$gunid = $plac['attrs']['id'];
$ac = StoredFile::RecallByGunid($gunid);
if (is_null($ac) || PEAR::isError($ac)) {
return $ac;
}
$RADext = $ac->getFileExtension();
if (PEAR::isError($RADext)) {
return $RADext;
}
return array(
'type' => 'audioclip',
'gunid' => $gunid,
'src' => AC_URL_RELPATH."$gunid.$RADext",
'playlength' => $plac['attrs']['playlength'],
);
}
public static function OutputToM3u(&$pl, $plac, $ind='')
{
$gunid = $plac['attrs']['id'];
$ac = StoredFile::RecallByGunid($gunid);
if (is_null($ac) || PEAR::isError($ac)) {
return $ac;
}
$RADext = $ac->getFileExtension();
if (PEAR::isError($RADext)) {
return $RADext;
}
return array(
'playlength' => $plac['attrs']['playlength'],
'title' => $plac['attrs']['title'],
'uri' => AC_URL_RELPATH."$gunid.$RADext",
);
}
public static function OutputToRss(&$pl, $plac, $ind='')
{
$id = $plac['attrs']['id'];
$playlist = Playlist::Recall($id);
if (is_null($playlist) || PEAR::isError($playlist)) {
return $playlist;
}
$RADext = $playlist->getFileExtension();
if (PEAR::isError($RADext)) {
return $RADext;
}
$title = $playlist->getName();
$desc = $playlist->getPLMetaData("dc:description");
return array(
'type' => 'audioclip',
'gunid' => $id,
'src' => "http://XXX/YY/$id.$RADext",
'playlength' => $plac['attrs']['playlength'],
'title' => $title,
'desc' => $desc,
);
}
}
/**
* @package Campcaster
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
* @todo Rename this class "PlaylistFadeInfo" (notive the caps)
*/
class PlaylistFadeInfoExport
{
public static function OutputToSmil(&$pl, $plfi, $ind='')
{
$r = array(
'fi'=>$plfi['attrs']['fadeIn'],
'fo'=>$plfi['attrs']['fadeOut'],
);
return $r;
}
public static function OutputToM3u(&$pl, $plfa, $ind='')
{
return '';
}
public static function OutputToRss(&$pl, $plfa, $ind='')
{
return '';
}
}
/**
* @package Campcaster
* @subpackage StorageServer
* @copyright 2010 Sourcefabric O.P.S.
* @license http://www.gnu.org/licenses/gpl.txt
* @todo Rename this class to PlaylistMetadata (notice the caps)
*/
class PlaylistMetadataExport
{
public static function OutputToSmil(&$pl, $md, $ind='')
{
return NULL;
}
public static function OutputToM3u(&$pl, $md, $ind='')
{
return NULL;
}
public static function OutputToRss(&$pl, $md, $ind='')
{
return NULL;
}
}
?>