Merge branch 'devel' of dev.sourcefabric.org:airtime into devel

This commit is contained in:
Martin Konecny 2012-04-12 11:54:58 -04:00
commit 8303eb728e
36 changed files with 215 additions and 50 deletions

View File

@ -875,11 +875,10 @@ class ApiController extends Zend_Controller_Action
$watched_dirs = Application_Model_MusicDir::getWatchedDirs(null,null);
foreach( $added_list as $ad){
$ad .= '/';
foreach( $watched_dirs as $dir ){
$dirPath = $dir->getDirectory();
$ad .= '/';
// if mount path itself was watched
if($dirPath == $ad){
Application_Model_MusicDir::addWatchedDir($dirPath, false);
@ -901,9 +900,9 @@ class ApiController extends Zend_Controller_Action
}
}
foreach( $removed_list as $rd){
$rd .= '/';
foreach( $watched_dirs as $dir ){
$dirPath = $dir->getDirectory();
$rd .= '/';
// if dir contains any dir in removed_list( if watched dir resides on new mounted path )
if(substr($dirPath, 0, strlen($rd)) === $rd && $dir->getExistsFlag() == true){
Application_Model_MusicDir::removeWatchedDir($dirPath, false);

View File

@ -45,7 +45,7 @@ class LibraryController extends Zend_Controller_Action
$file = Application_Model_StoredFile::Recall($id);
if (isset($this->pl_sess->id) && $screen == "playlist") {
$menu["pl_add"] = array("name"=> "Add to Playlist", "icon" => "copy");
$menu["pl_add"] = array("name"=> "Add to Playlist", "icon" => "add-playlist", "icon" => "copy");
}
@ -56,7 +56,7 @@ class LibraryController extends Zend_Controller_Action
}
$url = $file->getRelativeFileUrl($baseUrl).'/download/true';
$menu["download"] = array("name" => "Download", "url" => $url);
$menu["download"] = array("name" => "Download", "icon" => "download", "url" => $url);
if (Application_Model_Preference::GetUploadToSoundcloudOption()) {
@ -75,11 +75,11 @@ class LibraryController extends Zend_Controller_Action
$text = "Upload to SoundCloud";
}
$menu["soundcloud"]["items"]["upload"] = array("name" => $text, "url" => "/library/upload-file-soundcloud/id/{$id}");
$menu["soundcloud"]["items"]["upload"] = array("name" => $text, "icon" => "soundcloud", "url" => "/library/upload-file-soundcloud/id/{$id}");
if ($scid > 0){
$url = $file->getSoundCloudLinkToFile();
$menu["soundcloud"]["items"]["view"] = array("name" => "View on Soundcloud", "url" => $url);
$menu["soundcloud"]["items"]["view"] = array("name" => "View on Soundcloud", "icon" => "soundcloud", "url" => $url);
}
}
}
@ -93,7 +93,7 @@ class LibraryController extends Zend_Controller_Action
}
//Open a jPlayer window and play the audio clip.
$menu["play"] = array("name"=> "Play", "icon" => "big_play");
$menu["play"] = array("name"=> "Play", "icon" => "play");
$this->view->items = $menu;
}

View File

@ -233,10 +233,10 @@ class ScheduleController extends Zend_Controller_Action
&& !$instance->isRecorded()
&& !$instance->isRebroadcast()) {
$menu["schedule"] = array("name"=> "Add / Remove Content",
$menu["schedule"] = array("name"=> "Add / Remove Content", "icon" => "add-remove-content",
"url" => "/showbuilder/builder-dialog/");
$menu["clear"] = array("name"=> "Remove All Content", "icon" => "delete",
$menu["clear"] = array("name"=> "Remove All Content", "icon" => "remove-all-content",
"url" => "/schedule/clear-show");
}
@ -244,7 +244,7 @@ class ScheduleController extends Zend_Controller_Action
if (!$instance->isRecorded()) {
$menu["content"] = array("name"=> "Show Content", "url" => "/schedule/show-content-dialog");
$menu["content"] = array("name"=> "Show Content", "icon" => "overview", "url" => "/schedule/show-content-dialog");
}
if ($showEndLocalDT->getTimestamp() <= $epochNow

View File

@ -167,10 +167,10 @@ class ShowbuilderController extends Zend_Controller_Action
$item = CcScheduleQuery::create()->findPK($id);
$instance = $item->getCcShowInstances();
$menu["preview"] = array("name"=> "Preview");
$menu["preview"] = array("name"=> "Preview","icon" => "overview");
//select the cursor
$menu["selCurs"] = array("name"=> "Select Cursor");
$menu["delCurs"] = array("name"=> "Remove Cursor");
$menu["selCurs"] = array("name"=> "Select Cursor","icon" => "select-cursor");
$menu["delCurs"] = array("name"=> "Remove Cursor","icon" => "select-cursor");
if ($now < floatval($item->getDbEnds("U.u")) && $user->canSchedule($instance->getDbShowId())) {

View File

@ -84,12 +84,14 @@ class Application_Form_EditAudioMD extends Zend_Form
));
// Add bmp field
$this->addElement('text', 'bpm', array(
'label' => 'BPM:',
'class' => 'input_text',
'filters' => array('StringTrim'),
'validators' => array(array('StringLength', false, array(0, 8)))
));
$bpm = new Zend_Form_Element_Text('bpm');
$bpm->class = 'input_text';
$bpm->setLabel('BPM:')
->setFilters(array('StringTrim'))
->setValidators(array(
new Zend_Validate_StringLength(array('min'=>0,'max' => 8)),
new Zend_Validate_Digits()));
$this->addElement($bpm);
// Add copyright field
$this->addElement('text', 'copyright', array(

View File

@ -114,6 +114,10 @@ class Application_Model_Schedule {
$timeNowAsMillis = strtotime($p_timeNow);
for( $i = 0; $i < $numberOfRows; ++$i ){
// if the show is overbooked, then update the track end time to the end of the show time.
if($rows[$i]['ends'] > $rows[$i]["show_ends"]){
$rows[$i]['ends'] = $rows[$i]["show_ends"];
}
if ((strtotime($rows[$i]['starts']) <= $timeNowAsMillis) && (strtotime($rows[$i]['ends']) >= $timeNowAsMillis)){
if ( $i - 1 >= 0){
$results['previous'] = array("name"=>$rows[$i-1]["artist_name"]." - ".$rows[$i-1]["track_title"],
@ -351,7 +355,7 @@ class Application_Model_Schedule {
if (strpos($t[2], ".")) {
$secParts = explode(".", $t[2]);
$millisecs = $secParts[1];
$millisecs = substr($millisecs, 0, 3);
$millisecs = str_pad(substr($millisecs, 0, 3),3, '0');
$millisecs = intval($millisecs);
$seconds = intval($secParts[0]);
} else {
@ -408,6 +412,7 @@ class Application_Model_Schedule {
$baseQuery = "SELECT st.file_id AS file_id,"
." st.id as id,"
." st.instance_id as instance_id,"
." st.starts AS start,"
." st.ends AS end,"
." st.cue_in AS cue_in,"
@ -523,7 +528,12 @@ class Application_Model_Schedule {
}
foreach ($items as $item){
$showInstance = CcShowInstancesQuery::create()->findPK($item["instance_id"]);
$showId = $showInstance->getDbShowId();
$show = CcShowQuery::create()->findPK($showId);
$showName = $show->getDbName();
$showEndDateTime = new DateTime($item["show_end"], $utcTimeZone);
$trackStartDateTime = new DateTime($item["start"], $utcTimeZone);
$trackEndDateTime = new DateTime($item["end"], $utcTimeZone);
@ -555,7 +565,8 @@ class Application_Model_Schedule {
'cue_in' => Application_Model_DateHelper::CalculateLengthInSeconds($item["cue_in"]),
'cue_out' => Application_Model_DateHelper::CalculateLengthInSeconds($item["cue_out"]),
'start' => $start,
'end' => Application_Model_Schedule::AirtimeTimeToPypoTime($item["end"])
'end' => Application_Model_Schedule::AirtimeTimeToPypoTime($item["end"]),
'show_name' => $showName
);
}

View File

@ -38,7 +38,7 @@
<?php if (count($watched_dirs) > 0): ?>
<?php foreach($watched_dirs as $watched_dir): ?>
<dd class="block-display selected-item">
<span><?php echo ($watched_dir->getExistsFlag())?"":"<img src='/css/images/warning-icon.png'>"?></span><span><?php echo $watched_dir->getDirectory();?></span></span><span class="ui-icon ui-icon-close"></span>
<?php echo ($watched_dir->getExistsFlag())?"":"<span class='ui-icon-alert'><img src='/css/images/warning-icon.png'></span>"?><span><?php echo $watched_dir->getDirectory();?></span></span><span class="ui-icon ui-icon-close"></span>
</dd>
<?php endforeach; ?>
<?php else: ?>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -22,8 +22,8 @@
position: absolute;
list-style-type: none;
border: 1px solid #DDD;
background: #EEE;
border: 1px solid #333333;
background: #f0f0f0;
-webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
-moz-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
@ -31,14 +31,15 @@
-o-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
font-family: Verdana, Arial, Helvetica, sans-serif;
font-family: Arial, Helvetica, sans-serif;
font-size: 11px;
}
.context-menu-item {
padding: 2px 2px 2px 28px;
background-color: #EEE;
background-color: #f0f0f0;
position: relative;
min-height: 18px;
-moz-user-select: -moz-none;
}
@ -53,7 +54,7 @@
.context-menu-item.hover {
cursor: pointer;
background-color: #39F;
background-color: #ff5d1a;
}
.context-menu-item.disabled {
@ -82,13 +83,21 @@
.context-menu-item.icon:before {}
*/
.context-menu-item.icon { min-height: 18px; background-repeat: no-repeat; background-position: 4px 2px; }
.context-menu-item.icon-edit { background-image: url(images/icon_edit.png); }
.context-menu-item.icon-cut { background-image: url(images/icon_cut.png); }
.context-menu-item.icon-copy { background-image: url(images/icon_copy.png); }
.context-menu-item.icon-paste { background-image: url(images/icon_paste.png); }
.context-menu-item.icon-delete { background-image: url(images/icon_delete.png); }
.context-menu-item.icon-quit { background-image: url(images/icon_door.png); }
.context-menu-item.icon-soundcloud { background-image: url(images/icon_soundcloud.png); }
.context-menu-item.icon-edit { background-image: url(images/icon_edit_cm.png); }
.context-menu-item.icon-cut { background-image: url(images/icon_cut_cm.png); }
.context-menu-item.icon-copy { background-image: url(images/icon_copy_cm.png); }
.context-menu-item.icon-paste { background-image: url(images/icon_paste_cm.png); }
.context-menu-item.icon-delete { background-image: url(images/icon_delete_cm.png); }
.context-menu-item.icon-quit { background-image: url(images/icon_door_cm.png); }
.context-menu-item.icon-soundcloud { background-image: url(images/icon_soundcloud_cm.png); }
.context-menu-item.icon-download { background-image: url(images/icon_download_cm.png); }
.context-menu-item.icon-overview { background-image: url(images/icon_overview_cm.png); }
.context-menu-item.icon-play { background-image: url(images/icon_play_cm.png); }
.context-menu-item.icon-select-cursor { background-image: url(images/icon_select-cursor_cm.png); }
.context-menu-item.icon-add-playlist { background-image: url(images/icon_add_playlist_cm.png); }
.context-menu-item.icon-add-remove-content { background-image: url(images/icon_add_content_cm.png); }
.context-menu-item.icon-remove-all-content { background-image: url(images/icon_remove_all_content_cm.png); }
/* vertically align inside labels */
.context-menu-input > label > * { vertical-align: top; }

View File

@ -135,25 +135,28 @@ function updateProgressBarValue(){
function updatePlaybar(){
/* Column 0 update */
$('#previous').empty();
$('#prev-length').empty();
$('#current').html("Current: <span style='color:red; font-weight:bold'>Nothing Scheduled</span>");
$('#next').empty();
$('#next-length').empty();
if (previousSong !== null){
$('#previous').text(previousSong.name+",");
$('#prev-length').text(convertToHHMMSSmm(previousSong.songLengthMs));
}else{
$('#previous').empty();
$('#prev-length').empty();
}
if (currentSong !== null){
if (currentSong.record == "1")
$('#current').html("<span style='color:red; font-weight:bold'>Recording: </span>"+currentSong.name+",");
else
$('#current').text(currentSong.name+",");
}else{
$('#current').html("Current: <span style='color:red; font-weight:bold'>Nothing Scheduled</span>");
}
if (nextSong !== null){
$('#next').text(nextSong.name+",");
$('#next-length').text(convertToHHMMSSmm(nextSong.songLengthMs));
}else{
$('#next').empty();
$('#next-length').empty();
}
$('#start').empty();

View File

@ -764,7 +764,7 @@ var AIRTIME = (function(AIRTIME){
$pl.find(".ui-icon-alert").qtip({
content: {
text: "File does not exist on disk..."
text: "Airtime is unsure about the status of this file. This can happen when the file is on a remote drive that is unaccessible or the file is in a directory that isn't \"watched\" anymore."
},
position:{
adjust: {

View File

@ -98,5 +98,23 @@ function setWatchedDirEvents() {
$(document).ready(function() {
setWatchedDirEvents();
$(".ui-icon-alert").qtip({
content: {
text: "This path is currently not accessible."
},
position:{
adjust: {
resize: true,
method: "flip flip"
},
at: "right center",
my: "left top",
viewport: $(window)
},
style: {
classes: "ui-tooltip-dark"
},
show: 'mouseover',
hide: 'mouseout'
});
});

View File

@ -8,12 +8,48 @@ class AirtimeDatabaseUpgrade{
public static function start(){
echo "* Updating Database".PHP_EOL;
self::task0();
self::task1();
}
private static function task0(){
UpgradeCommon::MigrateTablesToVersion(__DIR__, '20120410143340');
UpgradeCommon::MigrateTablesToVersion(__DIR__, '20120411174904');
$sql = "INSERT INTO cc_pref(\"keystr\", \"valstr\") VALUES('scheduled_play_switch', 'on')";
UpgradeCommon::nonSelectQueryDb($sql);
}
/*
* set values for playout_status in cc_schedule
*/
private static function task1() {
// Define path to application directory
defined('APPLICATION_PATH')
|| define('APPLICATION_PATH', realpath(__DIR__.'/../../../airtime_mvc/application'));
// Ensure library is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
get_include_path(),
realpath(APPLICATION_PATH . '/../library')
)));
//Propel classes.
set_include_path(APPLICATION_PATH . '/models' . PATH_SEPARATOR . get_include_path());
//include_once APPLICATION_PATH."/configs/conf.php";
include_once 'propel/runtime/lib/Propel.php';
Propel::init(APPLICATION_PATH."/configs/airtime-conf-production.php");
$con = Propel::getConnection(CcSchedulePeer::DATABASE_NAME);
$showInstances = CcShowInstancesQuery::create()
->setFormatter(ModelCriteria::FORMAT_ON_DEMAND)
->filterByDbStarts(gmdate("Y-m-d H:i:s"), Criteria::GREATER_EQUAL)
->find($con);
foreach ($showInstances as $instance) {
$instance->updateScheduleStatus($con);
}
}
}

View File

@ -28,6 +28,10 @@ class Version20120410104441 extends AbstractMigration
//add utime, lptime
$this->_addSql("ALTER TABLE cc_files ADD utime timestamp(6)");
$this->_addSql("ALTER TABLE cc_files ADD lptime timestamp(6)");
//setting these to a default now for timeline refresh purposes.
$now = gmdate("Y-m-d H:i:s");
$this->_addSql("UPDATE cc_files SET utime = '$now'");
}
public function down(Schema $schema)

View File

@ -0,0 +1,41 @@
<?php
namespace DoctrineMigrations;
use Doctrine\DBAL\Migrations\AbstractMigration,
Doctrine\DBAL\Schema\Schema;
class Version20120411102907 extends AbstractMigration
{
/*
* changing many columns from time without timezone to interval
*
* altering cc_schedule for 2.1
*/
public function up(Schema $schema)
{
$this->_addSql("ALTER TABLE cc_files ALTER COLUMN length TYPE interval");
$this->_addSql("ALTER TABLE cc_playlistcontents ALTER COLUMN cuein TYPE interval");
$this->_addSql("ALTER TABLE cc_playlistcontents ALTER COLUMN cueout TYPE interval");
$this->_addSql("ALTER TABLE cc_playlistcontents ALTER COLUMN cliplength TYPE interval");
$this->_addSql("ALTER TABLE cc_schedule ALTER COLUMN cue_in TYPE interval");
$this->_addSql("ALTER TABLE cc_schedule ALTER COLUMN cue_out TYPE interval");
$this->_addSql("ALTER TABLE cc_schedule ALTER COLUMN clip_length TYPE interval");
$this->_addSql("ALTER TABLE cc_show_instances ALTER COLUMN time_filled TYPE interval");
//remove old columns from cc_schedule that deal with groups or playlists.
$this->_addSql("ALTER TABLE cc_schedule DROP COLUMN group_id");
$this->_addSql("ALTER TABLE cc_schedule DROP COLUMN schedule_group_played");
$this->_addSql("ALTER TABLE cc_schedule DROP COLUMN playlist_id");
$this->_addSql("ALTER TABLE cc_schedule ADD playout_status integer DEFAULT 1 NOT NULL");
}
public function down(Schema $schema)
{
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace DoctrineMigrations;
use Doctrine\DBAL\Migrations\AbstractMigration,
Doctrine\DBAL\Schema\Schema;
class Version20120411174904 extends AbstractMigration
{
/*
* modifications to cc_show_instances for 2.1
*/
public function up(Schema $schema)
{
$this->_addSql("ALTER TABLE cc_show_instances ADD created timestamp(6)");
$this->_addSql("ALTER TABLE cc_show_instances ADD last_scheduled timestamp(6)");
//setting these to a default now for timeline refresh purposes.
$now = gmdate("Y-m-d H:i:s");
$this->_addSql("UPDATE cc_show_instances SET created = '$now'");
$this->_addSql("UPDATE cc_show_instances SET last_scheduled = '$now'");
}
public function down(Schema $schema)
{
}
}

View File

@ -442,7 +442,10 @@ class AirTimeApiClient(ApiClientInterface):
except Exception, e:
response = None
logger.error("Exception with file %s: %s", md, e)
import traceback
top = traceback.format_exc()
logger.error('Exception: %s', e)
logger.error("traceback: %s", top)
return response

View File

@ -15,6 +15,15 @@ def append_title(m) =
end
end
def crossfade(s)
#duration is automatically overwritten by metadata fields passed in
#with audio
s = fade.in(type="log", duration=0., s)
s = fade.out(type="log", duration=0., s)
fader = fun (a,b) -> add(normalize=false,[b,a])
cross(fader,s)
end
def transition(a,b) =
log("transition called...")
add(normalize=false,

View File

@ -29,6 +29,8 @@ s3_namespace = ref ''
queue = on_metadata(notify, queue)
queue = map_metadata(append_title, queue)
# the crossfade function controls fade in/out
queue = crossfade(queue)
ignore(output.dummy(queue, fallible=true))
server.register(namespace="vars", "pypo_data", fun (s) -> begin pypo_data := s "Done" end)

View File

@ -90,7 +90,7 @@ class PypoFetch(Thread):
self.switch_source(self.logger, self.telnet_lock, m['sourcename'], m['status'])
elif command == 'disconnect_source':
self.logger.info("disconnect_on_source show command received...")
self.disconnect_source(self.logger, self.telnet.lock, m['sourcename'])
self.disconnect_source(self.logger, self.telnet_lock, m['sourcename'])
except Exception, e:
import traceback
top = traceback.format_exc()
@ -421,8 +421,7 @@ class PypoFetch(Thread):
try:
mediaKeys = sorted(media.iterkeys())
for mkey in mediaKeys:
media_item = media[mkey]
media_item['show_name'] = "TODO"
media_item = media[mkey]
except Exception, e:
self.logger.error("%s", e)

View File

@ -99,7 +99,7 @@ class PypoMessageHandler(Thread):
self.handle_message(message.payload)
# ACK the message to take it off the queue
message.ack()
except IOError, e:
except (IOError, AttributeError), e:
import traceback
top = traceback.format_exc()
self.logger.error('Exception: %s', e)

View File

@ -429,7 +429,8 @@ class PypoPush(Thread):
self.telnet_lock.release()
def create_liquidsoap_annotation(self, media):
return 'annotate:media_id="%s",liq_fade_in="%s",liq_fade_out="%s",liq_cue_in="%s",liq_cue_out="%s",schedule_table_id="%s":%s' \
# we need lia_start_next value in the annotate. That is the value that controlls overlap duration of crossfade.
return 'annotate:media_id="%s",liq_start_next="0",liq_fade_in="%s",liq_fade_out="%s",liq_cue_in="%s",liq_cue_out="%s",schedule_table_id="%s":%s' \
% (media['id'], float(media['fade_in'])/1000, float(media['fade_out'])/1000, float(media['cue_in']), float(media['cue_out']), media['row_id'], media['dst'])
def run(self):