Merge branch '2.4.x'
Conflicts: python_apps/pypo/pypopush.py python_apps/pypo/schedule/pypofetch.py python_apps/pypo/schedule/pypofile.py python_apps/pypo/schedule/pypoliqqueue.py
This commit is contained in:
commit
586bdf99e9
71 changed files with 5253 additions and 4614 deletions
|
@ -24,7 +24,7 @@ class ErrorController extends Zend_Controller_Action
|
|||
}
|
||||
|
||||
// Log exception, if logger available
|
||||
if ($log = $this->getLog()) {
|
||||
if (($log = $this->getLog())) {
|
||||
$log->crit($this->view->message, $errors->exception);
|
||||
}
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ class LocaleController extends Zend_Controller_Action
|
|||
"Are you sure you want to remove the watched folder?" => _("Are you sure you want to remove the watched folder?"),
|
||||
"This path is currently not accessible." => _("This path is currently not accessible."),
|
||||
//preferences/streamsetting.js
|
||||
"Some steam types require extra configuration. Details about enabling %sAAC+ Support%s or %sOpus Support%s are provided." => _("Some steam types require extra configuration. Details about enabling %sAAC+ Support%s or %sOpus Support%s are provided."),
|
||||
"Some stream types require extra configuration. Details about enabling %sAAC+ Support%s or %sOpus Support%s are provided." => _("Some stream types require extra configuration. Details about enabling %sAAC+ Support%s or %sOpus Support%s are provided."),
|
||||
"Connected to the streaming server" => _("Connected to the streaming server"),
|
||||
"The stream is disabled" => _("The stream is disabled"),
|
||||
"Getting information from the server..." => _("Getting information from the server..."),
|
||||
|
@ -193,6 +193,7 @@ class LocaleController extends Zend_Controller_Action
|
|||
"If your live streaming client does not ask for a username, this field should be 'source'." => _("If your live streaming client does not ask for a username, this field should be 'source'."),
|
||||
"The show instance doesn't exist anymore!" => _("The show instance doesn't exist anymore!"),
|
||||
"Warning: Shows cannot be re-linked" => _("Warning: Shows cannot be re-linked"),
|
||||
"By linking your repeating shows any media items scheduled in any repeat show will also get scheduled in the other repeat shows" => _("By linking your repeating shows any media items scheduled in any repeat show will also get scheduled in the other repeat shows"),
|
||||
//schedule/full-calendar-functions
|
||||
//already in schedule/add-show.js
|
||||
//"The show instance doesn't exist anymore!" => _("The show instance doesn't exist anymore!"),
|
||||
|
|
|
@ -32,6 +32,7 @@ class PreferenceController extends Zend_Controller_Action
|
|||
$this->view->statusMsg = "";
|
||||
|
||||
$form = new Application_Form_Preferences();
|
||||
$values = array();
|
||||
|
||||
if ($request->isPost()) {
|
||||
$params = $request->getPost();
|
||||
|
@ -223,6 +224,7 @@ class PreferenceController extends Zend_Controller_Action
|
|||
$s1_data = array();
|
||||
$s2_data = array();
|
||||
$s3_data = array();
|
||||
$values = array();
|
||||
foreach($postData as $k=>$v) {
|
||||
$v = explode('=', urldecode($v));
|
||||
if (strpos($v[0], "s1_data") !== false) {
|
||||
|
|
|
@ -600,6 +600,7 @@ class ScheduleController extends Zend_Controller_Action
|
|||
|
||||
$baseUrl = $this->getRequest()->getBaseUrl();
|
||||
$url = $file->getRelativeFileUrl($baseUrl).'download/true';
|
||||
$menu = array();
|
||||
$menu[] = array('action' => array('type' => 'gourl', 'url' => $url),
|
||||
'title' => _('Download'));
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ class UserController extends Zend_Controller_Action
|
|||
if ($request->isPost()) {
|
||||
$params = $request->getPost();
|
||||
$postData = explode('&', $params['data']);
|
||||
$formData = array();
|
||||
foreach($postData as $k=>$v) {
|
||||
$v = explode('=', $v);
|
||||
$formData[$v[0]] = urldecode($v[1]);
|
||||
|
|
|
@ -330,7 +330,7 @@ SQL;
|
|||
{
|
||||
list($value, $modifier) = $this->getLimitValueAndModifier();
|
||||
if ($modifier == "items") {
|
||||
$length = $value." ".$modifier;
|
||||
$length = $value." "._("items");
|
||||
} else {
|
||||
$hour = "00";
|
||||
$mins = "00";
|
||||
|
@ -1354,6 +1354,16 @@ SQL;
|
|||
"year" => _("Year")
|
||||
);
|
||||
|
||||
$modifierOptions = array(
|
||||
"0" => _("Select modifier"),
|
||||
"contains" => _("contains"),
|
||||
"does not contain" => _("does not contain"),
|
||||
"is" => _("is"),
|
||||
"is not" => _("is not"),
|
||||
"starts with" => _("starts with"),
|
||||
"ends with" => _("ends with")
|
||||
);
|
||||
|
||||
// Load criteria from db
|
||||
$out = CcBlockcriteriaQuery::create()->orderByDbCriteria()->findByDbBlockId($this->id);
|
||||
$storedCrit = array();
|
||||
|
@ -1365,11 +1375,17 @@ SQL;
|
|||
$extra = $crit->getDbExtra();
|
||||
|
||||
if ($criteria == "limit") {
|
||||
$storedCrit["limit"] = array("value"=>$value, "modifier"=>$modifier);
|
||||
$storedCrit["limit"] = array("value"=>$value, "modifier"=>_($modifier));
|
||||
} else if($criteria == "repeat_tracks") {
|
||||
$storedCrit["repeat_tracks"] = array("value"=>$value);
|
||||
} else {
|
||||
$storedCrit["crit"][$criteria][] = array("criteria"=>$criteria, "value"=>$value, "modifier"=>$modifier, "extra"=>$extra, "display_name"=>$criteriaOptions[$criteria]);
|
||||
$storedCrit["crit"][$criteria][] = array(
|
||||
"criteria"=>$criteria,
|
||||
"value"=>$value,
|
||||
"modifier"=>$modifier,
|
||||
"extra"=>$extra,
|
||||
"display_name"=>$criteriaOptions[$criteria],
|
||||
"display_modifier"=>$modifierOptions[$modifier]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ class Application_Model_Datatables
|
|||
{
|
||||
private static function buildWhereClauseForAdvancedSearch($dbname2searchTerm)
|
||||
{
|
||||
$where = array();
|
||||
$where['clause'] = array();
|
||||
$where['params'] = array();
|
||||
foreach ($dbname2searchTerm as $dbname=>$term) {
|
||||
|
|
|
@ -1075,8 +1075,7 @@ SQL;
|
|||
$sql .= "END WHERE position IN ($currentPos) and playlist_id=:p1";
|
||||
|
||||
Application_Common_Database::prepareAndExecute($sql, array("p1"=>$this->id));
|
||||
$result['result'] = 0;
|
||||
return $result;
|
||||
return array('result' => 0);
|
||||
}
|
||||
|
||||
public static function getAllPlaylistFiles()
|
||||
|
|
|
@ -38,6 +38,8 @@ class Application_Model_Preference
|
|||
$paramMap[':id'] = $userId;
|
||||
}
|
||||
|
||||
Application_Common_Database::prepareAndExecute("LOCK TABLE cc_pref");
|
||||
|
||||
$result = Application_Common_Database::prepareAndExecute($sql,
|
||||
$paramMap,
|
||||
Application_Common_Database::COLUMN,
|
||||
|
|
|
@ -322,7 +322,8 @@ SQL;
|
|||
ft.album_title AS file_album_title,
|
||||
ft.length AS file_length,
|
||||
ft.file_exists AS file_exists,
|
||||
ft.mime AS file_mime
|
||||
ft.mime AS file_mime,
|
||||
ft.soundcloud_id AS soundcloud_id
|
||||
SQL;
|
||||
$filesJoin = <<<SQL
|
||||
cc_schedule AS sched
|
||||
|
@ -357,7 +358,8 @@ SQL;
|
|||
ws.description AS file_album_title,
|
||||
ws.length AS file_length,
|
||||
't'::BOOL AS file_exists,
|
||||
ws.mime as file_mime
|
||||
ws.mime AS file_mime,
|
||||
(SELECT NULL::integer AS soundcloud_id)
|
||||
SQL;
|
||||
$streamJoin = <<<SQL
|
||||
cc_schedule AS sched
|
||||
|
@ -396,7 +398,7 @@ SQL;
|
|||
$map = array();
|
||||
|
||||
for ($i = 0, $len = count($p_shows); $i < $len; $i++) {
|
||||
$holder = "show_".$i;
|
||||
$holder = ":show_".$i;
|
||||
|
||||
$params[] = $holder;
|
||||
$map[$holder] = $p_shows[$i];
|
||||
|
|
|
@ -85,6 +85,9 @@ class Application_Model_Scheduler
|
|||
|
||||
$nowEpoch = floatval($this->nowDT->format("U.u"));
|
||||
|
||||
$schedInfo = array();
|
||||
$instanceInfo = array();
|
||||
|
||||
for ($i = 0; $i < count($items); $i++) {
|
||||
$id = $items[$i]["id"];
|
||||
|
||||
|
@ -103,7 +106,7 @@ class Application_Model_Scheduler
|
|||
}
|
||||
|
||||
$schedIds = array();
|
||||
if (isset($schedInfo)) {
|
||||
if (count($schedInfo) > 0) {
|
||||
$schedIds = array_keys($schedInfo);
|
||||
}
|
||||
$schedItems = CcScheduleQuery::create()->findPKs($schedIds, $this->con);
|
||||
|
@ -527,10 +530,6 @@ class Application_Model_Scheduler
|
|||
|
||||
$linked = false;
|
||||
|
||||
$dropIndex_sql = "DROP INDEX cc_schedule_instance_id_idx";
|
||||
Application_Common_Database::prepareAndExecute(
|
||||
$dropIndex_sql, array(), Application_Common_Database::EXECUTE);
|
||||
|
||||
foreach ($scheduleItems as $schedule) {
|
||||
$id = intval($schedule["id"]);
|
||||
|
||||
|
@ -592,6 +591,7 @@ class Application_Model_Scheduler
|
|||
$instance_sql);
|
||||
}
|
||||
|
||||
$excludePositions = array();
|
||||
foreach($instances as &$instance) {
|
||||
$instanceId = $instance["id"];
|
||||
if ($id !== 0) {
|
||||
|
@ -612,15 +612,24 @@ class Application_Model_Scheduler
|
|||
$instanceId);
|
||||
|
||||
$pos++;
|
||||
|
||||
/* Show is not empty so we need to apply crossfades
|
||||
* for the first inserted item
|
||||
*/
|
||||
$applyCrossfades = true;
|
||||
}
|
||||
//selected empty row to add after
|
||||
else {
|
||||
$showStartDT = new DateTime($instance["starts"], new DateTimeZone("UTC"));
|
||||
$nextStartDT = $this->findNextStartTime($showStartDT, $instanceId);
|
||||
|
||||
//show is empty so start position counter at 0
|
||||
//first item in show so start position counter at 0
|
||||
$pos = 0;
|
||||
$adjustSched = false;
|
||||
|
||||
/* Show is empty so we don't need to calculate crossfades
|
||||
* for the first inserted item
|
||||
*/
|
||||
$applyCrossfades = false;
|
||||
}
|
||||
|
||||
if (!in_array($instanceId, $affectedShowInstances)) {
|
||||
|
@ -635,7 +644,12 @@ class Application_Model_Scheduler
|
|||
|
||||
$pstart = microtime(true);
|
||||
|
||||
if ($applyCrossfades) {
|
||||
$initalStartDT = clone $this->findTimeDifference(
|
||||
$nextStartDT, $this->crossfadeDuration);
|
||||
} else {
|
||||
$initalStartDT = clone $nextStartDT;
|
||||
}
|
||||
|
||||
$pend = microtime(true);
|
||||
Logging::debug("finding all following items.");
|
||||
|
@ -658,6 +672,7 @@ class Application_Model_Scheduler
|
|||
//item existed previously and is being moved.
|
||||
//need to keep same id for resources if we want REST.
|
||||
if (isset($file['sched_id'])) {
|
||||
$adjustFromDT = clone $nextStartDT;
|
||||
$doUpdate = true;
|
||||
|
||||
$movedItem_sql = "SELECT * FROM cc_schedule ".
|
||||
|
@ -693,11 +708,9 @@ class Application_Model_Scheduler
|
|||
$file["fadein"] = $sched["fade_in"];
|
||||
$file["fadeout"] = $sched["fade_out"];
|
||||
} else {
|
||||
//$sched = new CcSchedule();
|
||||
$doInsert = true;
|
||||
}
|
||||
|
||||
$endTimeDT = $this->findEndTime($nextStartDT, $file['cliplength']);
|
||||
// default fades are in seconds
|
||||
// we need to convert to '00:00:00' format
|
||||
$file['fadein'] = Application_Common_DateHelper::secondsToPlaylistTime($file['fadein']);
|
||||
|
@ -715,6 +728,18 @@ class Application_Model_Scheduler
|
|||
default: break;
|
||||
}
|
||||
|
||||
if ($applyCrossfades) {
|
||||
$nextStartDT = $this->findTimeDifference($nextStartDT,
|
||||
$this->crossfadeDuration);
|
||||
$endTimeDT = $this->findEndTime($nextStartDT, $file['cliplength']);
|
||||
$endTimeDT = $this->findTimeDifference($endTimeDT, $this->crossfadeDuration);
|
||||
/* Set it to false because the rest of the crossfades
|
||||
* will be applied after we insert each item
|
||||
*/
|
||||
$applyCrossfades = false;
|
||||
}
|
||||
|
||||
$endTimeDT = $this->findEndTime($nextStartDT, $file['cliplength']);
|
||||
if ($doInsert) {
|
||||
$values[] = "(".
|
||||
"'{$nextStartDT->format("Y-m-d H:i:s")}', ".
|
||||
|
@ -753,12 +778,15 @@ class Application_Model_Scheduler
|
|||
$insert_sql = "INSERT INTO cc_schedule ".
|
||||
"(starts, ends, cue_in, cue_out, fade_in, fade_out, ".
|
||||
"clip_length, position, instance_id, file_id, stream_id) VALUES ".
|
||||
implode($values, ",");
|
||||
implode($values, ",")." RETURNING id";
|
||||
|
||||
Application_Common_Database::prepareAndExecute(
|
||||
$insert_sql, array(), Application_Common_Database::EXECUTE);
|
||||
$stmt = $this->con->prepare($insert_sql);
|
||||
if ($stmt->execute()) {
|
||||
foreach ($stmt->fetchAll() as $row) {
|
||||
$excludeIds[] = $row["id"];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// update is_scheduled flag for each cc_file
|
||||
$fileIds = array();
|
||||
foreach ($filesToInsert as &$file) {
|
||||
|
@ -779,6 +807,7 @@ class Application_Model_Scheduler
|
|||
}
|
||||
|
||||
if ($adjustSched === true) {
|
||||
|
||||
$followingItems_sql = "SELECT * FROM cc_schedule ".
|
||||
"WHERE starts >= '{$initalStartDT->format("Y-m-d H:i:s.u")}' ".
|
||||
"AND instance_id = {$instanceId} ";
|
||||
|
@ -786,7 +815,6 @@ class Application_Model_Scheduler
|
|||
$followingItems_sql .= "AND id NOT IN (". implode($excludeIds, ",").") ";
|
||||
}
|
||||
$followingItems_sql .= "ORDER BY starts";
|
||||
|
||||
$followingSchedItems = Application_Common_Database::prepareAndExecute(
|
||||
$followingItems_sql);
|
||||
|
||||
|
@ -795,6 +823,7 @@ class Application_Model_Scheduler
|
|||
//recalculate the start/end times after the inserted items.
|
||||
foreach ($followingSchedItems as $item) {
|
||||
$endTimeDT = $this->findEndTime($nextStartDT, $item["clip_length"]);
|
||||
$endTimeDT = $this->findTimeDifference($endTimeDT, $this->crossfadeDuration);
|
||||
$update_sql = "UPDATE cc_schedule SET ".
|
||||
"starts = '{$nextStartDT->format("Y-m-d H:i:s")}', ".
|
||||
"ends = '{$endTimeDT->format("Y-m-d H:i:s")}', ".
|
||||
|
@ -814,11 +843,6 @@ class Application_Model_Scheduler
|
|||
}//for each instance
|
||||
}//for each schedule location
|
||||
|
||||
$createIndex_sql = "CREATE INDEX cc_schedule_instance_id_idx ".
|
||||
"ON cc_schedule USING btree(instance_id)";
|
||||
Application_Common_Database::prepareAndExecute(
|
||||
$createIndex_sql, array(), Application_Common_Database::EXECUTE);
|
||||
|
||||
$endProfile = microtime(true);
|
||||
Logging::debug("finished adding scheduled items.");
|
||||
Logging::debug(floatval($endProfile) - floatval($startProfile));
|
||||
|
|
|
@ -388,6 +388,7 @@ class Application_Model_ShowBuilder
|
|||
$outdated = false;
|
||||
$shows = Application_Model_Show::getShows($this->startDT, $this->endDT);
|
||||
|
||||
$include = array();
|
||||
if ($this->opts["showFilter"] !== 0) {
|
||||
$include[] = $this->opts["showFilter"];
|
||||
} elseif ($this->opts["myShows"] === 1) {
|
||||
|
|
|
@ -352,10 +352,10 @@ SQL;
|
|||
);
|
||||
|
||||
//only need to check overlap if show increased in size.
|
||||
if (strtotime($new_ends) > strtotime($ends)) {
|
||||
if (strtotime($now_ends) > strtotime($ends)) {
|
||||
|
||||
$utcStartDateTime = new DateTime($ends, new DateTimeZone("UTC"));
|
||||
$utcEndDateTime = new DateTime($new_ends, new DateTimeZone("UTC"));
|
||||
$utcEndDateTime = new DateTime($now_ends, new DateTimeZone("UTC"));
|
||||
|
||||
$overlap = Application_Model_Show::getShows($utcStartDateTime, $utcEndDateTime);
|
||||
|
||||
|
@ -381,7 +381,7 @@ SQL;
|
|||
|
||||
}
|
||||
|
||||
$this->setShowEnd($new_ends);
|
||||
$this->setShowEnd($now_ends);
|
||||
Application_Model_RabbitMq::PushSchedule();
|
||||
}
|
||||
|
||||
|
|
|
@ -796,7 +796,7 @@ SQL;
|
|||
|
||||
//soundcloud status
|
||||
$file = Application_Model_StoredFile::RecallById($row['id']);
|
||||
$row['soundcloud_status'] = $file->getSoundCloudId();
|
||||
$row['soundcloud_id'] = $file->getSoundCloudId();
|
||||
|
||||
// for audio preview
|
||||
$row['audioFile'] = $row['id'].".".pathinfo($row['filepath'], PATHINFO_EXTENSION);
|
||||
|
@ -893,7 +893,7 @@ SQL;
|
|||
$in = fopen($_FILES['file']['tmp_name'], "rb");
|
||||
|
||||
if ($in) {
|
||||
while ($buff = fread($in, 4096))
|
||||
while (($buff = fread($in, 4096)))
|
||||
fwrite($out, $buff);
|
||||
} else
|
||||
die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": _("Failed to open input stream.")}, "id" : "id"}');
|
||||
|
@ -912,7 +912,7 @@ SQL;
|
|||
$in = fopen("php://input", "rb");
|
||||
|
||||
if ($in) {
|
||||
while ($buff = fread($in, 4096))
|
||||
while (($buff = fread($in, 4096)))
|
||||
fwrite($out, $buff);
|
||||
} else
|
||||
die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": _("Failed to open input stream.")}, "id" : "id"}');
|
||||
|
@ -961,6 +961,7 @@ SQL;
|
|||
// Check if we have enough space before copying
|
||||
if (!self::isEnoughDiskSpaceToCopy($stor, $audio_file)) {
|
||||
$freeSpace = disk_free_space($stor);
|
||||
$fileSize = filesize($audio_file);
|
||||
|
||||
return array("code" => 107,
|
||||
"message" => sprintf(_("The file was not uploaded, there is "
|
||||
|
@ -1255,7 +1256,7 @@ SQL;
|
|||
$description = $file->getDbTrackTitle();
|
||||
$tag = array();
|
||||
$genre = $file->getDbGenre();
|
||||
$release = $file->getDbYear();
|
||||
$release = $file->getDbUtime();
|
||||
try {
|
||||
$soundcloud = new Application_Model_Soundcloud();
|
||||
$soundcloud_res = $soundcloud->uploadTrack(
|
||||
|
|
|
@ -125,6 +125,7 @@ class Application_Model_Systemstatus
|
|||
public static function GetPlatformInfo()
|
||||
{
|
||||
$keys = array("release", "machine", "memory", "swap");
|
||||
$data = array();
|
||||
foreach ($keys as $key) {
|
||||
$data[$key] = "UNKNOWN";
|
||||
}
|
||||
|
@ -212,7 +213,7 @@ class Application_Model_Systemstatus
|
|||
|
||||
public static function GetDiskInfo()
|
||||
{
|
||||
$partions = array();
|
||||
$partitions = array();
|
||||
|
||||
/* First lets get all the watched directories. Then we can group them
|
||||
* into the same partitions by comparing the partition sizes. */
|
||||
|
|
|
@ -226,7 +226,7 @@ class Application_Model_User
|
|||
public function deleteAllFiles()
|
||||
{
|
||||
$my_files = $this->getOwnedFiles();
|
||||
foreach ($files as $file) {
|
||||
foreach ($my_files as $file) {
|
||||
$file->delete();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,14 @@ class CcFiles extends BaseCcFiles {
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function setDbTrackNumber($v)
|
||||
{
|
||||
$max = pow(2, 31)-1;
|
||||
$v = ($v > $max) ? $max : $v;
|
||||
|
||||
return parent::setDbTrackNumber($v);
|
||||
}
|
||||
|
||||
// returns true if the file exists and is not hidden
|
||||
public function visible() {
|
||||
return $this->getDbFileExists() && !$this->getDbHidden();
|
||||
|
|
|
@ -177,10 +177,6 @@ class Application_Service_SchedulerService
|
|||
$timeFilled = Application_Common_Database::prepareAndExecute(
|
||||
$timeFilled_sql, array(), Application_Common_Database::COLUMN);
|
||||
|
||||
$dropIndex_sql = "DROP INDEX cc_schedule_instance_id_idx";
|
||||
Application_Common_Database::prepareAndExecute(
|
||||
$dropIndex_sql, array(), Application_Common_Database::EXECUTE);
|
||||
|
||||
//need to find out which linked instances are empty
|
||||
$values = array();
|
||||
foreach ($instanceIds as $id) {
|
||||
|
@ -210,7 +206,8 @@ class Application_Service_SchedulerService
|
|||
|
||||
if (is_null($item["file_id"])) {
|
||||
$item["file_id"] = "null";
|
||||
} elseif (is_null($item["stream_id"])) {
|
||||
}
|
||||
if (is_null($item["stream_id"])) {
|
||||
$item["stream_id"] = "null";
|
||||
}
|
||||
|
||||
|
@ -240,11 +237,6 @@ class Application_Service_SchedulerService
|
|||
Application_Common_Database::prepareAndExecute(
|
||||
$insert_sql, array(), Application_Common_Database::EXECUTE);
|
||||
|
||||
$createIndex_sql = "CREATE INDEX cc_schedule_instance_id_idx ".
|
||||
"ON cc_schedule USING btree(instance_id)";
|
||||
Application_Common_Database::prepareAndExecute(
|
||||
$createIndex_sql, array(), Application_Common_Database::EXECUTE);
|
||||
|
||||
//update time_filled in cc_show_instances
|
||||
$now = gmdate("Y-m-d H:i:s");
|
||||
$update_sql = "UPDATE cc_show_instances SET ".
|
||||
|
|
|
@ -99,8 +99,9 @@ class Application_Service_ShowFormService
|
|||
public function delegateShowFormPopulation($forms)
|
||||
{
|
||||
$this->populateFormWhat($forms["what"]);
|
||||
$this->populateFormWhen($forms["when"]);
|
||||
$this->populateFormRepeats($forms["repeats"]);
|
||||
//local show start DT
|
||||
$showStart = $this->populateFormWhen($forms["when"]);
|
||||
$this->populateFormRepeats($forms["repeats"], $showStart);
|
||||
$this->populateFormWho($forms["who"]);
|
||||
$this->populateFormStyle($forms["style"]);
|
||||
$this->populateFormLive($forms["live"]);
|
||||
|
@ -136,6 +137,9 @@ class Application_Service_ShowFormService
|
|||
$form->disableStartDateAndTime();
|
||||
} else {
|
||||
list($showStart, $showEnd) = $this->getNextFutureRepeatShowTime();
|
||||
if ($this->hasShowStarted($showStart)) {
|
||||
$form->disableStartDateAndTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,6 +151,8 @@ class Application_Service_ShowFormService
|
|||
'add_show_end_time' => $showEnd->format("H:i"),
|
||||
'add_show_duration' => $ccShowDay->formatDuration(true),
|
||||
'add_show_repeats' => $ccShowDay->isRepeating() ? 1 : 0));
|
||||
|
||||
return $showStart;
|
||||
}
|
||||
|
||||
private function populateInstanceFormWhen($form)
|
||||
|
@ -179,7 +185,13 @@ class Application_Service_ShowFormService
|
|||
$form->getElement('add_show_repeats')->setOptions(array("disabled" => true));
|
||||
}
|
||||
|
||||
private function populateFormRepeats($form)
|
||||
/**
|
||||
*
|
||||
* Enter description here ...
|
||||
* @param $form
|
||||
* @param DateTime $nextFutureShowStart user's local timezone
|
||||
*/
|
||||
private function populateFormRepeats($form, $nextFutureShowStart)
|
||||
{
|
||||
$ccShowDays = $this->ccShow->getCcShowDays();
|
||||
|
||||
|
@ -219,6 +231,14 @@ class Application_Service_ShowFormService
|
|||
if (!$this->ccShow->isLinkable() || $this->ccShow->isRecorded()) {
|
||||
$form->getElement('add_show_linked')->setOptions(array('disabled' => true));
|
||||
}
|
||||
|
||||
/* Because live editing of a linked show is disabled, we will disable
|
||||
* the linking option if the current show is being edited. We don't
|
||||
* want the user to suddenly not be able to edit the current show
|
||||
*/
|
||||
if ($this->hasShowStarted($nextFutureShowStart)) {
|
||||
$form->getElement('add_show_linked')->setOptions(array('disabled' => true));
|
||||
}
|
||||
}
|
||||
|
||||
private function populateFormWho($form)
|
||||
|
@ -295,6 +315,22 @@ class Application_Service_ShowFormService
|
|||
$form->populate($formValues);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Enter description here ...
|
||||
* @param DateTime $showStart user's local time
|
||||
*/
|
||||
private function hasShowStarted($p_showStart) {
|
||||
$showStart = clone $p_showStart;
|
||||
$showStart->setTimeZone(new DateTimeZone("UTC"));
|
||||
|
||||
if ($showStart->format("Y-m-d H:i:s") < gmdate("Y-m-d H:i:s")) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Before we send the form data in for validation, there
|
||||
|
|
|
@ -999,7 +999,7 @@ SQL;
|
|||
}
|
||||
|
||||
if ($this->isRebroadcast) {
|
||||
$this->createRebroadcastInstances($showDay, $date, $ccShowInstance->getDbId());
|
||||
$this->createRebroadcastInstances($showDay, $start, $ccShowInstance->getDbId());
|
||||
}
|
||||
}
|
||||
$start = $this->getNextMonthlyMonthlyRepeatDate($start, $timezone, $showDay->getDbStartTime());
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
Before Width: | Height: | Size: 801 B After Width: | Height: | Size: 481 B |
|
@ -125,7 +125,7 @@ select {
|
|||
|
||||
.airtime_auth_help_icon, .custom_auth_help_icon, .stream_username_help_icon,
|
||||
.playlist_type_help_icon, .master_username_help_icon, .repeat_tracks_help_icon,
|
||||
.admin_username_help_icon, .stream_type_help_icon {
|
||||
.admin_username_help_icon, .stream_type_help_icon, .show_linking_help_icon {
|
||||
cursor: help;
|
||||
position: relative;
|
||||
display:inline-block; zoom:1;
|
||||
|
|
|
@ -262,14 +262,14 @@ function parseItems(obj){
|
|||
|
||||
if (obj.currentShow.length > 0) {
|
||||
calcAdditionalShowData(obj.currentShow);
|
||||
currentShow = obj.currentShow;
|
||||
}
|
||||
if (obj.nextShow.length > 0) {
|
||||
calcAdditionalShowData(obj.nextShow);
|
||||
nextShow = obj.nextShow;
|
||||
calculateTimeToNextShow();
|
||||
}
|
||||
|
||||
currentShow = obj.currentShow;
|
||||
nextShow = obj.nextShow;
|
||||
|
||||
var schedulePosixTime = convertDateToPosixTime(obj.schedulerTime);
|
||||
var date = new Date();
|
||||
|
|
|
@ -593,12 +593,12 @@ var AIRTIME = (function(AIRTIME) {
|
|||
"fnRowCallback": AIRTIME.library.fnRowCallback,
|
||||
"fnCreatedRow": function( nRow, aData, iDataIndex ) {
|
||||
//add soundcloud icon
|
||||
if (aData.soundcloud_status !== undefined) {
|
||||
if (aData.soundcloud_status === "-2") {
|
||||
if (aData.soundcloud_id !== undefined) {
|
||||
if (aData.soundcloud_id === "-2") {
|
||||
$(nRow).find("td.library_title").append('<span class="small-icon progress"/>');
|
||||
} else if (aData.soundcloud_status === "-3") {
|
||||
} else if (aData.soundcloud_id === "-3") {
|
||||
$(nRow).find("td.library_title").append('<span class="small-icon sc-error"/>');
|
||||
} else if (aData.soundcloud_status !== null) {
|
||||
} else if (aData.soundcloud_id !== null) {
|
||||
$(nRow).find("td.library_title").append('<span class="small-icon soundcloud"/>');
|
||||
}
|
||||
}
|
||||
|
@ -1126,7 +1126,6 @@ function checkLibrarySCUploadStatus(){
|
|||
else if (json.sc_id == "-3") {
|
||||
span.removeClass("progress").addClass("sc-error");
|
||||
}
|
||||
setTimeout(checkLibrarySCUploadStatus, 5000);
|
||||
}
|
||||
|
||||
function checkSCUploadStatusRequest() {
|
||||
|
@ -1138,12 +1137,16 @@ function checkLibrarySCUploadStatus(){
|
|||
}
|
||||
|
||||
$("#library_display span.progress").each(checkSCUploadStatusRequest);
|
||||
setTimeout(checkLibrarySCUploadStatus, 5000);
|
||||
}
|
||||
|
||||
function addQtipToSCIcons() {
|
||||
$(".progress, .soundcloud, .sc-error").live('mouseover', function(){
|
||||
$("#content")
|
||||
.on('mouseover', ".progress, .soundcloud, .sc-error", function() {
|
||||
|
||||
var id = $(this).parent().parent().data("aData").id;
|
||||
var aData = $(this).parents("tr").data("aData"),
|
||||
id = aData.id,
|
||||
sc_id = aData.soundcloud_id;
|
||||
|
||||
if ($(this).hasClass("progress")){
|
||||
$(this).qtip({
|
||||
|
@ -1163,24 +1166,15 @@ function addQtipToSCIcons(){
|
|||
classes: "ui-tooltip-dark file-md-long"
|
||||
},
|
||||
show: {
|
||||
ready: true // Needed to make it show on first mouseover
|
||||
// event
|
||||
ready: true // Needed to make it show on first mouseover event
|
||||
}
|
||||
});
|
||||
}
|
||||
else if ($(this).hasClass("soundcloud")){
|
||||
var sc_id = $(this).parent().parent().data("aData").soundcloud_id;
|
||||
|
||||
$(this).qtip({
|
||||
content: {
|
||||
text: $.i18n._("Retrieving data from the server..."),
|
||||
ajax: {
|
||||
url: baseUrl+"Library/get-upload-to-soundcloud-status",
|
||||
type: "post",
|
||||
data: ({format: "json", id : id, type: "file"}),
|
||||
success: function(json, status){
|
||||
this.set('content.text', $.i18n._("The soundcloud id for this file is: ")+json.sc_id);
|
||||
}
|
||||
}
|
||||
text: $.i18n._("The soundcloud id for this file is: ") + sc_id
|
||||
},
|
||||
position:{
|
||||
adjust: {
|
||||
|
@ -1195,11 +1189,11 @@ function addQtipToSCIcons(){
|
|||
classes: "ui-tooltip-dark file-md-long"
|
||||
},
|
||||
show: {
|
||||
ready: true // Needed to make it show on first mouseover
|
||||
// event
|
||||
ready: true // Needed to make it show on first mouseover event
|
||||
}
|
||||
});
|
||||
}else if($(this).hasClass("sc-error")){
|
||||
}
|
||||
else if ($(this).hasClass("sc-error")) {
|
||||
$(this).qtip({
|
||||
content: {
|
||||
text: $.i18n._("Retreiving data from the server..."),
|
||||
|
@ -1227,8 +1221,7 @@ function addQtipToSCIcons(){
|
|||
classes: "ui-tooltip-dark file-md-long"
|
||||
},
|
||||
show: {
|
||||
ready: true // Needed to make it show on first mouseover
|
||||
// event
|
||||
ready: true // Needed to make it show on first mouseover event
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -587,7 +587,7 @@ var AIRTIME = (function(AIRTIME){
|
|||
var extra = (ele['extra']==null)?"":"- "+ele['extra'];
|
||||
$html += "<li>" +
|
||||
"<span class='block-item-title'>"+ele['display_name']+"</span>" +
|
||||
"<span class='block-item-criteria'>"+ele['modifier']+"</span>" +
|
||||
"<span class='block-item-criteria'>"+ele['display_modifier']+"</span>" +
|
||||
"<span class='block-item-criteria'>"+ele['value']+"</span>" +
|
||||
"<span class='block-item-criteria'>"+extra+"</span>" +
|
||||
"</li>";
|
||||
|
|
|
@ -193,6 +193,7 @@ function setAddShowEvents() {
|
|||
}
|
||||
});
|
||||
|
||||
form.find("#add_show_linked-label").before("<span class='show_linking_help_icon'></span>");
|
||||
|
||||
form.find("#add_show_record").click(function(){
|
||||
$(this).blur();
|
||||
|
@ -315,7 +316,26 @@ function setAddShowEvents() {
|
|||
at: "right center"
|
||||
}
|
||||
});
|
||||
|
||||
form.find(".show_linking_help_icon").qtip({
|
||||
content: {
|
||||
text: $.i18n._("By linking your repeating shows any media items scheduled in any repeat show will also get scheduled in the other repeat shows")
|
||||
},
|
||||
hide: {
|
||||
delay: 500,
|
||||
fixed: true
|
||||
},
|
||||
style: {
|
||||
border: {
|
||||
width: 0,
|
||||
radius: 4
|
||||
},
|
||||
classes: "ui-tooltip-dark ui-tooltip-rounded"
|
||||
},
|
||||
position: {
|
||||
my: "left bottom",
|
||||
at: "right center"
|
||||
}
|
||||
});
|
||||
function endDateVisibility(){
|
||||
if(form.find("#add_show_no_end").is(':checked')){
|
||||
form.find("#add_show_end_date").hide();
|
||||
|
|
|
@ -211,6 +211,7 @@ function viewDisplay( view ) {
|
|||
|
||||
function eventRender(event, element, view) {
|
||||
|
||||
$(element).attr("id", "fc-show-instance-"+event.id);
|
||||
$(element).data("event", event);
|
||||
|
||||
//only put progress bar on shows that aren't being recorded.
|
||||
|
@ -229,34 +230,27 @@ function eventRender(event, element, view) {
|
|||
$(element).find(".fc-event-content").append(div);
|
||||
}
|
||||
|
||||
//need to add id for every event to find the current show
|
||||
if (view.name === 'agendaDay' || view.name === 'agendaWeek') {
|
||||
$(element).find(".fc-event-time").attr("id", event.id);
|
||||
} else if (view.name === 'month') {
|
||||
$(element).find(".fc-event-title").attr("id", event.id);
|
||||
}
|
||||
|
||||
//add the record/rebroadcast/soundcloud icons if needed
|
||||
if (event.record === 1) {
|
||||
if (view.name === 'agendaDay' || view.name === 'agendaWeek') {
|
||||
if (event.soundcloud_id === -1) {
|
||||
$(element).find(".fc-event-time").before('<span id="'+event.id+'" class="small-icon recording"></span>');
|
||||
$(element).find(".fc-event-time").before('<span class="small-icon recording"></span>');
|
||||
} else if ( event.soundcloud_id > 0) {
|
||||
$(element).find(".fc-event-time").before('<span id="'+event.id+'" class="small-icon recording"></span><span id="'+event.id+'" class="small-icon soundcloud"></span>');
|
||||
$(element).find(".fc-event-time").before('<span class="small-icon recording"></span><span class="small-icon soundcloud"></span>');
|
||||
} else if (event.soundcloud_id === -2) {
|
||||
$(element).find(".fc-event-time").before('<span id="'+event.id+'" class="small-icon recording"></span><span id="'+event.id+'" class="small-icon progress"></span>');
|
||||
$(element).find(".fc-event-time").before('<span class="small-icon recording"></span><span class="small-icon progress"></span>');
|
||||
} else if (event.soundcloud_id === -3) {
|
||||
$(element).find(".fc-event-time").before('<span id="'+event.id+'" class="small-icon recording"></span><span id="'+event.id+'" class="small-icon sc-error"></span>');
|
||||
$(element).find(".fc-event-time").before('<span class="small-icon recording"></span><span class="small-icon sc-error"></span>');
|
||||
}
|
||||
} else if (view.name === 'month') {
|
||||
if(event.soundcloud_id === -1) {
|
||||
$(element).find(".fc-event-title").after('<span id="'+event.id+'" class="small-icon recording"></span>');
|
||||
$(element).find(".fc-event-title").after('<span class="small-icon recording"></span>');
|
||||
} else if (event.soundcloud_id > 0) {
|
||||
$(element).find(".fc-event-title").after('<span id="'+event.id+'" class="small-icon recording"></span><span id="'+event.id+'" class="small-icon soundcloud"></span>');
|
||||
$(element).find(".fc-event-title").after('<span class="small-icon recording"></span><span class="small-icon soundcloud"></span>');
|
||||
} else if (event.soundcloud_id === -2) {
|
||||
$(element).find(".fc-event-title").after('<span id="'+event.id+'" class="small-icon recording"></span><span id="'+event.id+'" class="small-icon progress"></span>');
|
||||
$(element).find(".fc-event-title").after('<span class="small-icon recording"></span><span class="small-icon progress"></span>');
|
||||
} else if (event.soundcloud_id === -3) {
|
||||
$(element).find(".fc-event-title").after('<span id="'+event.id+'" class="small-icon recording"></span><span id="'+event.id+'" class="small-icon sc-error"></span>');
|
||||
$(element).find(".fc-event-title").after('<span class="small-icon recording"></span><span class="small-icon sc-error"></span>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -267,27 +261,27 @@ function eventRender(event, element, view) {
|
|||
if (event.linked) {
|
||||
$(element)
|
||||
.find(".fc-event-time")
|
||||
.before('<span id="'+event.id+'" class="small-icon linked"></span><span id="'+event.id+'" class="small-icon show-empty"></span>');
|
||||
.before('<span class="small-icon linked"></span><span class="small-icon show-empty"></span>');
|
||||
} else {
|
||||
$(element)
|
||||
.find(".fc-event-time")
|
||||
.before('<span id="'+event.id+'" class="small-icon show-empty"></span>');
|
||||
.before('<span class="small-icon show-empty"></span>');
|
||||
}
|
||||
} else if (event.show_partial_filled === true) {
|
||||
if (event.linked) {
|
||||
$(element)
|
||||
.find(".fc-event-time")
|
||||
.before('<span id="'+event.id+'" class="small-icon linked"></span><span id="'+event.id+'" class="small-icon show-partial-filled"></span>');
|
||||
.before('<span class="small-icon linked"></span><span class="small-icon show-partial-filled"></span>');
|
||||
} else {
|
||||
$(element)
|
||||
.find(".fc-event-time")
|
||||
.before('<span id="'+event.id+'" class="small-icon show-partial-filled"></span>');
|
||||
.before('<span class="small-icon show-partial-filled"></span>');
|
||||
}
|
||||
} else {
|
||||
if (event.linked) {
|
||||
$(element)
|
||||
.find(".fc-event-time")
|
||||
.before('<span id="'+event.id+'" class="small-icon linked"></span>');
|
||||
.before('<span class="small-icon linked"></span>');
|
||||
}
|
||||
}
|
||||
} else if (view.name === 'month') {
|
||||
|
@ -295,27 +289,27 @@ function eventRender(event, element, view) {
|
|||
if (event.linked) {
|
||||
$(element)
|
||||
.find(".fc-event-title")
|
||||
.after('<span id="'+event.id+'" class="small-icon linked"></span><span id="'+event.id+'" title="'+$.i18n._("Show is empty")+'" class="small-icon show-empty"></span>');
|
||||
.after('<span class="small-icon linked"></span><span title="'+$.i18n._("Show is empty")+'" class="small-icon show-empty"></span>');
|
||||
} else {
|
||||
$(element)
|
||||
.find(".fc-event-title")
|
||||
.after('<span id="'+event.id+'" title="'+$.i18n._("Show is empty")+'" class="small-icon show-empty"></span>');
|
||||
.after('<span title="'+$.i18n._("Show is empty")+'" class="small-icon show-empty"></span>');
|
||||
}
|
||||
} else if (event.show_partial_filled === true) {
|
||||
if (event.linked) {
|
||||
$(element)
|
||||
.find(".fc-event-title")
|
||||
.after('<span id="'+event.id+'" class="small-icon linked"></span><span id="'+event.id+'" title="'+$.i18n._("Show is partially filled")+'" class="small-icon show-partial-filled"></span>');
|
||||
.after('<span class="small-icon linked"></span><span title="'+$.i18n._("Show is partially filled")+'" class="small-icon show-partial-filled"></span>');
|
||||
} else {
|
||||
$(element)
|
||||
.find(".fc-event-title")
|
||||
.after('<span id="'+event.id+'" title="'+$.i18n._("Show is partially filled")+'" class="small-icon show-partial-filled"></span>');
|
||||
.after('<span title="'+$.i18n._("Show is partially filled")+'" class="small-icon show-partial-filled"></span>');
|
||||
}
|
||||
} else {
|
||||
if (event.linked) {
|
||||
$(element)
|
||||
.find(".fc-event-title")
|
||||
.after('<span id="'+event.id+'" class="small-icon linked"></span>');
|
||||
.after('<span class="small-icon linked"></span>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -324,9 +318,9 @@ function eventRender(event, element, view) {
|
|||
//rebroadcast icon
|
||||
if (event.rebroadcast === 1) {
|
||||
if (view.name === 'agendaDay' || view.name === 'agendaWeek') {
|
||||
$(element).find(".fc-event-time").before('<span id="'+event.id+'" class="small-icon rebroadcast"></span>');
|
||||
$(element).find(".fc-event-time").before('<span class="small-icon rebroadcast"></span>');
|
||||
} else if (view.name === 'month') {
|
||||
$(element).find(".fc-event-title").after('<span id="'+event.id+'" class="small-icon rebroadcast"></span>');
|
||||
$(element).find(".fc-event-title").after('<span class="small-icon rebroadcast"></span>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -334,7 +328,7 @@ function eventRender(event, element, view) {
|
|||
function eventAfterRender( event, element, view ) {
|
||||
|
||||
$(element).find(".small-icon").live('mouseover',function(){
|
||||
addQtipsToIcons($(this));
|
||||
addQtipsToIcons($(this), event.id);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -403,15 +397,25 @@ function getFullCalendarEvents(start, end, callback) {
|
|||
}
|
||||
|
||||
function checkSCUploadStatus(){
|
||||
var url = baseUrl+'Library/get-upload-to-soundcloud-status/format/json';
|
||||
var url = baseUrl+'Library/get-upload-to-soundcloud-status/format/json',
|
||||
id;
|
||||
$("span[class*=progress]").each(function(){
|
||||
var id = $(this).attr("id");
|
||||
id = $(this).parents("div.fc-event").data("event").id;
|
||||
|
||||
$.post(url, {format: "json", id: id, type:"show"}, function(json){
|
||||
if (json.sc_id > 0){
|
||||
$("span[id="+id+"]:not(.recording)").removeClass("progress").addClass("soundcloud");
|
||||
}else if(json.sc_id == "-3"){
|
||||
$("span[id="+id+"]:not(.recording)").removeClass("progress").addClass("sc-error");
|
||||
$("#fc-show-instance-"+id)
|
||||
.find(".progress")
|
||||
.removeClass("progress")
|
||||
.addClass("soundcloud");
|
||||
}
|
||||
else if (json.sc_id == "-3"){
|
||||
$("#fc-show-instance-"+id)
|
||||
.find(".progress")
|
||||
.removeClass("progress")
|
||||
.addClass("sc-error");
|
||||
}
|
||||
|
||||
setTimeout(checkSCUploadStatus, 5000);
|
||||
});
|
||||
});
|
||||
|
@ -425,7 +429,7 @@ function getCurrentShow(){
|
|||
$el;
|
||||
$.post(url, {format: "json"}, function(json) {
|
||||
if (json.current_show === true) {
|
||||
$el = $("div[class*=fc-event-time][id="+json.si_id+"]");
|
||||
$el = $("div[class*=fc-event-time]");
|
||||
if (view_name === 'agendaDay' || view_name === 'agendaWeek') {
|
||||
|
||||
/* Need to remove now-playing class because if user
|
||||
|
@ -440,38 +444,38 @@ function getCurrentShow(){
|
|||
* icon will overwrite it.
|
||||
*/
|
||||
$el.siblings().remove("span[class=small-icon recording]");
|
||||
$el.before('<span id="'+json.si_id+'" class="small-icon now-playing"></span><span id="'+json.si_id+'" class="small-icon recording"></span>');
|
||||
$el.before('<span class="small-icon now-playing"></span><span class="small-icon recording"></span>');
|
||||
} else if ($el.siblings().hasClass("small-icon rebroadcast")) {
|
||||
|
||||
/* Without removing rebroadcast icon, the now playing
|
||||
* icon will overwrite it.
|
||||
*/
|
||||
$el.siblings().remove("span[class=small-icon rebroadcast]");
|
||||
$el.before('<span id="'+json.si_id+'" class="small-icon now-playing"></span><span id="'+json.si_id+'" class="small-icon rebroadcast"></span>');
|
||||
$el.before('<span class="small-icon now-playing"></span><span class="small-icon rebroadcast"></span>');
|
||||
} else {
|
||||
$el.before('<span id="'+json.si_id+'" class="small-icon now-playing"></span>');
|
||||
$el.before('<span class="small-icon now-playing"></span>');
|
||||
}
|
||||
}
|
||||
} else if (view_name === 'month') {
|
||||
if (!$("span[class*=fc-event-title][id="+json.si_id+"]").siblings().hasClass("small-icon now-playing")) {
|
||||
$("span[class*=fc-event-title][id="+json.si_id+"]").after('<span id="'+json.si_id+'" class="small-icon now-playing"></span>');
|
||||
if (!$("span[class*=fc-event-title]").siblings().hasClass("small-icon now-playing")) {
|
||||
$("span[class*=fc-event-title]").after('<span class="small-icon now-playing"></span>');
|
||||
}
|
||||
}
|
||||
}
|
||||
//remove icon from shows that have ended
|
||||
$(".now-playing").each(function(){
|
||||
id = $(this).attr("id");
|
||||
id = $(this).parents("div.fc-event").data("event").id;
|
||||
|
||||
if (id != json.si_id) {
|
||||
$(this).remove("span[small-icon now-playing]");
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(getCurrentShow, 5000);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function addQtipsToIcons(ele){
|
||||
var id = $(ele).attr("id");
|
||||
function addQtipsToIcons(ele, id){
|
||||
|
||||
if ($(ele).hasClass("progress")){
|
||||
$(ele).qtip({
|
||||
|
|
|
@ -58,24 +58,22 @@ function confirmCancelRecordedShow(show_instance_id){
|
|||
}
|
||||
}
|
||||
|
||||
function uploadToSoundCloud(show_instance_id){
|
||||
function uploadToSoundCloud(show_instance_id, el){
|
||||
|
||||
var url = baseUrl+"Schedule/upload-to-sound-cloud";
|
||||
var span = $(window.triggerElement).find(".recording");
|
||||
var url = baseUrl+"Schedule/upload-to-sound-cloud",
|
||||
$el = $(el),
|
||||
$span = $el.find(".soundcloud");
|
||||
|
||||
$.post(url,
|
||||
{id: show_instance_id, format: "json"},
|
||||
function(json){
|
||||
scheduleRefetchEvents(json);
|
||||
});
|
||||
$.post(url, {id: show_instance_id, format: "json"});
|
||||
|
||||
if(span.length == 0){
|
||||
span = $(window.triggerElement).find(".soundcloud");
|
||||
span.removeClass("soundcloud")
|
||||
.addClass("progress");
|
||||
}else{
|
||||
span.removeClass("recording")
|
||||
.addClass("progress");
|
||||
//first upload to soundcloud.
|
||||
if ($span.length === 0){
|
||||
$span = $("<span/>", {"class": "progress"});
|
||||
|
||||
$el.find(".fc-event-title").after($span);
|
||||
}
|
||||
else {
|
||||
$span.removeClass("soundcloud").addClass("progress");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,8 +91,6 @@ function checkCalendarSCUploadStatus(){
|
|||
else if (json.sc_id == "-3") {
|
||||
span.removeClass("progress").addClass("sc-error");
|
||||
}
|
||||
|
||||
setTimeout(checkCalendarSCUploadStatus, 5000);
|
||||
}
|
||||
|
||||
function checkSCUploadStatusRequest() {
|
||||
|
@ -106,6 +102,7 @@ function checkCalendarSCUploadStatus(){
|
|||
}
|
||||
|
||||
$("#schedule_calendar span.progress").each(checkSCUploadStatusRequest);
|
||||
setTimeout(checkCalendarSCUploadStatus, 5000);
|
||||
}
|
||||
|
||||
function findViewportDimensions() {
|
||||
|
@ -421,7 +418,7 @@ $(document).ready(function() {
|
|||
if (oItems.soundcloud_upload !== undefined) {
|
||||
|
||||
callback = function() {
|
||||
uploadToSoundCloud(data.id);
|
||||
uploadToSoundCloud(data.id, this.context);
|
||||
};
|
||||
oItems.soundcloud_upload.callback = callback;
|
||||
}
|
||||
|
|
|
@ -546,7 +546,7 @@ var AIRTIME = (function(AIRTIME){
|
|||
cl = 'sb-footer';
|
||||
|
||||
//check the show's content status.
|
||||
if (aData.runtime > 0) {
|
||||
if (aData.runtime >= 0) {
|
||||
$node.html('<span class="ui-icon ui-icon-check"></span>');
|
||||
cl = cl + ' ui-state-highlight';
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ VERSION=2.4.0~$(date "+%Y%m%d")
|
|||
BUILDDEST=/tmp/airtime-${VERSION}/
|
||||
DEBDIR=`pwd`/debian
|
||||
|
||||
git checkout master
|
||||
git checkout 2.4.x
|
||||
git pull
|
||||
|
||||
echo "cleaning up previous build..."
|
||||
|
|
|
@ -18,7 +18,6 @@ PIDFILE=/var/run/airtime-liquidsoap.pid
|
|||
EXEC='/usr/bin/airtime-liquidsoap'
|
||||
|
||||
start () {
|
||||
|
||||
mkdir -p /var/log/airtime/pypo-liquidsoap
|
||||
chown $USERID:$GROUPID /var/log/airtime/pypo-liquidsoap
|
||||
|
||||
|
@ -36,9 +35,19 @@ start () {
|
|||
}
|
||||
|
||||
stop () {
|
||||
timeout --version >/dev/null 2>&1
|
||||
RESULT="$?"
|
||||
|
||||
#send term signal after 10 seconds
|
||||
if [ "$RESULT" = "0" ]; then
|
||||
timeout -s9 10s /usr/lib/airtime/airtime_virtualenv/bin/python \
|
||||
/usr/lib/airtime/pypo/bin/liquidsoap_scripts/liquidsoap_prepare_terminate.py
|
||||
else
|
||||
#some earlier versions of Ubuntu (Lucid) had a different timeout
|
||||
#command that takes different input parameters.
|
||||
timeout 10 /usr/lib/airtime/airtime_virtualenv/bin/python \
|
||||
/usr/lib/airtime/pypo/bin/liquidsoap_scripts/liquidsoap_prepare_terminate.py
|
||||
fi
|
||||
# Send TERM after 5 seconds, wait at most 30 seconds.
|
||||
#start-stop-daemon --stop --oknodo --retry=TERM/10/KILL/5 --quiet --pidfile $PIDFILE
|
||||
start-stop-daemon --stop --oknodo --retry=TERM/10/KILL/5 --quiet --exec $EXEC
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
set httpd port 2812
|
||||
|
||||
check process airtime-liquidsoap matching "airtime-liquidsoap.*airtime.*ls_script"
|
||||
if does not exist for 3 cycles then restart
|
||||
|
||||
start program = "/etc/init.d/airtime-liquidsoap start" with timeout 30 seconds
|
||||
stop program = "/etc/init.d/airtime-liquidsoap stop"
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
set httpd port 2812
|
||||
|
||||
check process airtime-liquidsoap
|
||||
with pidfile "/var/run/airtime-liquidsoap.pid"
|
||||
check process airtime-liquidsoap with pidfile "/var/run/airtime-liquidsoap.pid"
|
||||
if does not exist for 3 cycles then restart
|
||||
start program = "/etc/init.d/airtime-liquidsoap start" with timeout 5 seconds
|
||||
stop program = "/etc/init.d/airtime-liquidsoap stop"
|
||||
|
|
196
python_apps/pypo/pypopush.py
Normal file
196
python_apps/pypo/pypopush.py
Normal file
|
@ -0,0 +1,196 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
|
||||
import sys
|
||||
import time
|
||||
import logging.config
|
||||
import telnetlib
|
||||
import calendar
|
||||
import math
|
||||
import traceback
|
||||
import os
|
||||
|
||||
from pypofetch import PypoFetch
|
||||
from pypoliqqueue import PypoLiqQueue
|
||||
|
||||
from Queue import Empty, Queue
|
||||
|
||||
from threading import Thread
|
||||
|
||||
from api_clients import api_client
|
||||
from std_err_override import LogWriter
|
||||
from configobj import ConfigObj
|
||||
|
||||
|
||||
# configure logging
|
||||
logging_cfg = os.path.join(os.path.dirname(__file__), "logging.cfg")
|
||||
logging.config.fileConfig(logging_cfg)
|
||||
logger = logging.getLogger()
|
||||
LogWriter.override_std_err(logger)
|
||||
|
||||
#need to wait for Python 2.7 for this..
|
||||
#logging.captureWarnings(True)
|
||||
|
||||
PUSH_INTERVAL = 2
|
||||
|
||||
|
||||
def is_stream(media_item):
|
||||
return media_item['type'] == 'stream_output_start'
|
||||
|
||||
def is_file(media_item):
|
||||
return media_item['type'] == 'file'
|
||||
|
||||
class PypoPush(Thread):
|
||||
def __init__(self, q, telnet_lock, pypo_liquidsoap, config):
|
||||
Thread.__init__(self)
|
||||
self.api_client = api_client.AirtimeApiClient()
|
||||
self.queue = q
|
||||
|
||||
self.telnet_lock = telnet_lock
|
||||
self.config = config
|
||||
|
||||
self.pushed_objects = {}
|
||||
self.logger = logging.getLogger('push')
|
||||
self.current_prebuffering_stream_id = None
|
||||
self.queue_id = 0
|
||||
|
||||
self.future_scheduled_queue = Queue()
|
||||
self.pypo_liquidsoap = pypo_liquidsoap
|
||||
|
||||
self.plq = PypoLiqQueue(self.future_scheduled_queue, \
|
||||
self.pypo_liquidsoap, \
|
||||
self.logger)
|
||||
self.plq.daemon = True
|
||||
self.plq.start()
|
||||
|
||||
|
||||
def main(self):
|
||||
loops = 0
|
||||
heartbeat_period = math.floor(30 / PUSH_INTERVAL)
|
||||
|
||||
media_schedule = None
|
||||
|
||||
while True:
|
||||
try:
|
||||
media_schedule = self.queue.get(block=True)
|
||||
except Exception, e:
|
||||
self.logger.error(str(e))
|
||||
raise
|
||||
else:
|
||||
self.logger.debug(media_schedule)
|
||||
#separate media_schedule list into currently_playing and
|
||||
#scheduled_for_future lists
|
||||
currently_playing, scheduled_for_future = \
|
||||
self.separate_present_future(media_schedule)
|
||||
|
||||
self.pypo_liquidsoap.verify_correct_present_media(currently_playing)
|
||||
self.future_scheduled_queue.put(scheduled_for_future)
|
||||
|
||||
if loops % heartbeat_period == 0:
|
||||
self.logger.info("heartbeat")
|
||||
loops = 0
|
||||
loops += 1
|
||||
|
||||
|
||||
def separate_present_future(self, media_schedule):
|
||||
tnow = datetime.utcnow()
|
||||
|
||||
present = []
|
||||
future = {}
|
||||
|
||||
sorted_keys = sorted(media_schedule.keys())
|
||||
for mkey in sorted_keys:
|
||||
media_item = media_schedule[mkey]
|
||||
|
||||
diff_td = tnow - media_item['start']
|
||||
diff_sec = self.date_interval_to_seconds(diff_td)
|
||||
|
||||
if diff_sec >= 0:
|
||||
present.append(media_item)
|
||||
else:
|
||||
future[mkey] = media_item
|
||||
|
||||
return present, future
|
||||
|
||||
def get_current_stream_id_from_liquidsoap(self):
|
||||
response = "-1"
|
||||
try:
|
||||
self.telnet_lock.acquire()
|
||||
tn = telnetlib.Telnet(self.config['ls_host'], self.config['ls_port'])
|
||||
|
||||
msg = 'dynamic_source.get_id\n'
|
||||
tn.write(msg)
|
||||
response = tn.read_until("\r\n").strip(" \r\n")
|
||||
tn.write('exit\n')
|
||||
tn.read_all()
|
||||
except Exception, e:
|
||||
self.logger.error("Error connecting to Liquidsoap: %s", e)
|
||||
response = []
|
||||
finally:
|
||||
self.telnet_lock.release()
|
||||
|
||||
return response
|
||||
|
||||
#def is_correct_current_item(self, media_item, liquidsoap_queue_approx, liquidsoap_stream_id):
|
||||
#correct = False
|
||||
#if media_item is None:
|
||||
#correct = (len(liquidsoap_queue_approx) == 0 and liquidsoap_stream_id == "-1")
|
||||
#else:
|
||||
#if is_file(media_item):
|
||||
#if len(liquidsoap_queue_approx) == 0:
|
||||
#correct = False
|
||||
#else:
|
||||
#correct = liquidsoap_queue_approx[0]['start'] == media_item['start'] and \
|
||||
#liquidsoap_queue_approx[0]['row_id'] == media_item['row_id'] and \
|
||||
#liquidsoap_queue_approx[0]['end'] == media_item['end'] and \
|
||||
#liquidsoap_queue_approx[0]['replay_gain'] == media_item['replay_gain']
|
||||
#elif is_stream(media_item):
|
||||
#correct = liquidsoap_stream_id == str(media_item['row_id'])
|
||||
|
||||
#self.logger.debug("Is current item correct?: %s", str(correct))
|
||||
#return correct
|
||||
|
||||
def date_interval_to_seconds(self, interval):
|
||||
"""
|
||||
Convert timedelta object into int representing the number of seconds. If
|
||||
number of seconds is less than 0, then return 0.
|
||||
"""
|
||||
seconds = (interval.microseconds + \
|
||||
(interval.seconds + interval.days * 24 * 3600) * 10 ** 6) / float(10 ** 6)
|
||||
|
||||
return seconds
|
||||
|
||||
def stop_web_stream_all(self):
|
||||
try:
|
||||
self.telnet_lock.acquire()
|
||||
tn = telnetlib.Telnet(self.config['LS_HOST'], self.config['LS_PORT'])
|
||||
|
||||
#msg = 'dynamic_source.read_stop_all xxx\n'
|
||||
msg = 'http.stop\n'
|
||||
self.logger.debug(msg)
|
||||
tn.write(msg)
|
||||
|
||||
msg = 'dynamic_source.output_stop\n'
|
||||
self.logger.debug(msg)
|
||||
tn.write(msg)
|
||||
|
||||
msg = 'dynamic_source.id -1\n'
|
||||
self.logger.debug(msg)
|
||||
tn.write(msg)
|
||||
|
||||
tn.write("exit\n")
|
||||
self.logger.debug(tn.read_all())
|
||||
|
||||
except Exception, e:
|
||||
self.logger.error(str(e))
|
||||
finally:
|
||||
self.telnet_lock.release()
|
||||
|
||||
def run(self):
|
||||
try: self.main()
|
||||
except Exception, e:
|
||||
top = traceback.format_exc()
|
||||
self.logger.error('Pypo Push Exception: %s', top)
|
||||
|
|
@ -382,7 +382,7 @@ class PypoFetch(Thread):
|
|||
"%Y-%m-%d-%H-%M-%S")
|
||||
media_item['end'] = datetime.strptime(media_item['end'],
|
||||
"%Y-%m-%d-%H-%M-%S")
|
||||
media_copy[media_item['start']] = media_item
|
||||
media_copy[key] = media_item
|
||||
|
||||
self.media_prepare_queue.put(copy.copy(media_filtered))
|
||||
except Exception, e: self.logger.error("%s", e)
|
||||
|
|
|
@ -76,14 +76,6 @@ class PypoFile(Thread):
|
|||
self.logger.debug("copying from %s to local cache %s" % (src, dst))
|
||||
try:
|
||||
|
||||
"""
|
||||
List file as "ready" before it starts copying because by the
|
||||
time Liquidsoap is ready to play this file, it should have at
|
||||
least started copying (and can continue copying while
|
||||
Liquidsoap reads from the beginning of the file)
|
||||
"""
|
||||
media_item['file_ready'] = True
|
||||
|
||||
"""
|
||||
copy will overwrite dst if it already exists
|
||||
"""
|
||||
|
@ -91,6 +83,8 @@ class PypoFile(Thread):
|
|||
|
||||
#make file world readable
|
||||
os.chmod(dst, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
|
||||
|
||||
media_item['file_ready'] = True
|
||||
except Exception, e:
|
||||
self.logger.error("Could not copy from %s to %s" % (src, dst))
|
||||
self.logger.error(e)
|
||||
|
|
|
@ -74,8 +74,9 @@ class PypoLiqQueue(Thread):
|
|||
schedule_deque.append(media_schedule[i])
|
||||
|
||||
if len(keys):
|
||||
time_until_next_play = pure.date_interval_to_seconds(\
|
||||
keys[0] - datetime.utcnow())
|
||||
time_until_next_play = self.date_interval_to_seconds(
|
||||
media_schedule[keys[0]]['start'] -
|
||||
datetime.utcnow())
|
||||
else:
|
||||
time_until_next_play = None
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ set_include_path(implode(PATH_SEPARATOR, array(
|
|||
realpath($CC_CONFIG['phpDir'] . '/library')
|
||||
)));
|
||||
|
||||
require_once($CC_CONFIG['phpDir'].'/application/common/Database.php');
|
||||
require_once($CC_CONFIG['phpDir'].'/application/models/StoredFile.php');
|
||||
require_once($CC_CONFIG['phpDir'].'/application/models/Preference.php');
|
||||
require_once($CC_CONFIG['phpDir'].'/application/models/MusicDir.php');
|
||||
|
@ -52,7 +53,8 @@ if(count($argv) != 2){
|
|||
}
|
||||
|
||||
$id = $argv[1];
|
||||
$file = Application_Model_StoredFile::Recall($id);
|
||||
|
||||
$file = Application_Model_StoredFile::RecallById($id);
|
||||
// set id with -2 which is indicator for processing
|
||||
$file->setSoundCloudFileId(SOUNDCLOUD_PROGRESS);
|
||||
$file->uploadToSoundCloud();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue