Merge branch '2.1.x' of dev.sourcefabric.org:airtime into 2.1.x

This commit is contained in:
Martin Konecny 2012-06-05 13:08:07 -04:00
commit c37fe4b070
22 changed files with 1213 additions and 1086 deletions

View File

@ -560,7 +560,6 @@ class ApiController extends Zend_Controller_Action
$filepath = str_replace("//", "/", $filepath);
$file = Application_Model_StoredFile::RecallByFilepath($filepath);
if (is_null($file)) {
$file = Application_Model_StoredFile::Insert($md);
}
@ -573,6 +572,7 @@ class ApiController extends Zend_Controller_Action
}else{
// file marked as not exists
$file->setFileExistsFlag(true);
$file->setMetadata($md);
}
}
}

View File

@ -744,6 +744,7 @@ class ScheduleController extends Zend_Controller_Action
$show = new Application_Model_Show($data['add_show_id']);
$validateStartDate = true;
$validateStartTime = true;
if (!array_key_exists('add_show_start_date', $data)){
//Changing the start date was disabled, since the
//array key does not exist. We need to repopulate this entry from the db.

View File

@ -6,7 +6,6 @@ class Application_Form_AddShowLiveStream extends Zend_Form_SubForm
public function init()
{
$description1 = "This follows the same security pattern for the shows: only users assigned to the show can connect.";
$cb_airtime_auth = new Zend_Form_Element_Checkbox("cb_airtime_auth");
$cb_airtime_auth->setLabel("Use Airtime Authentication:")
->setDescription($description1)
@ -14,7 +13,6 @@ class Application_Form_AddShowLiveStream extends Zend_Form_SubForm
->setDecorators(array('ViewHelper'));
$this->addElement($cb_airtime_auth);
$description2 = "Specify custom authentication which will work only for this show.";
$cb_custom_auth = new Zend_Form_Element_Checkbox("cb_custom_auth");
$cb_custom_auth ->setLabel("Use Custom Authentication:")
->setDescription($description2)
@ -74,4 +72,4 @@ class Application_Form_AddShowLiveStream extends Zend_Form_SubForm
}
return $isValid;
}
}
}

View File

@ -67,19 +67,19 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm
// Add duration element
$this->addElement('text', 'add_show_duration', array(
'label' => 'Duration:',
'label' => 'Duration:',
'class' => 'input_text',
'value' => '01h 00m',
'readonly' => true,
'value' => '01h 00m',
'readonly' => true,
'decorators' => array('ViewHelper')
));
// Add repeats element
$this->addElement('checkbox', 'add_show_repeats', array(
// Add repeats element
$this->addElement('checkbox', 'add_show_repeats', array(
'label' => 'Repeats?',
'required' => false,
'decorators' => array('ViewHelper')
));
'decorators' => array('ViewHelper')
));
}
@ -92,21 +92,25 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm
$nowDateTime = new DateTime();
$showStartDateTime = new DateTime($start_time);
if ($validateStartDate){
if($showStartDateTime->getTimestamp() < $nowDateTime->getTimestamp()) {
$this->getElement('add_show_start_time')->setErrors(array('Cannot create show in the past'));
$valid = false;
}
}
if ($validateStartDate){
if($showStartDateTime->getTimestamp() < $nowDateTime->getTimestamp()) {
$this->getElement('add_show_start_time')->setErrors(array('Cannot create show in the past'));
$valid = false;
}
}
$hours = intval(substr($formData["add_show_duration"], 0, strpos($formData["add_show_duration"], 'h')));
$minutes = intval(substr($formData["add_show_duration"], -3, -1));
if( $formData["add_show_duration"] == "00h 00m" ) {
$this->getElement('add_show_duration')->setErrors(array('Cannot have duration 00h 00m'));
$valid = false;
}elseif(strpos($formData["add_show_duration"], 'h') !== false && intval(substr($formData["add_show_duration"], 0, strpos($formData["add_show_duration"], 'h'))) > 24) {
$this->getElement('add_show_duration')->setErrors(array('Cannot have duration greater than 24h'));
$valid = false;
}elseif(strpos($formData["add_show_duration"], 'h') !== false && $hours >= 24) {
if ($hours > 24 || ($hours == 24 && $minutes > 0)) {
$this->getElement('add_show_duration')->setErrors(array('Cannot have duration greater than 24h'));
$valid = false;
}
}elseif( strstr($formData["add_show_duration"], '-') ){
$this->getElement('add_show_duration')->setErrors(array('Cannot have duration < 0m'));
$this->getElement('add_show_duration')->setErrors(array('Cannot have duration < 0m'));
$valid = false;
}

View File

@ -5,6 +5,10 @@ class Application_Form_LiveStreamingPreferences extends Zend_Form_SubForm
public function init()
{
global $CC_CONFIG;
$isDemo = isset($CC_CONFIG['demo']) && $CC_CONFIG['demo'] == 1;
$isStreamConfigable = Application_Model_Preference::GetEnableStreamConf() == "true";
$isSaas = Application_Model_Preference::GetPlanLevel() == 'disabled'?false:true;
$defaultFade = Application_Model_Preference::GetDefaultTransitionFade();
if($defaultFade == ""){
@ -32,7 +36,12 @@ class Application_Form_LiveStreamingPreferences extends Zend_Form_SubForm
$this->addElement($master_username);
//Master password
$master_password = new Zend_Form_Element_Password('master_password');
if($isDemo){
$master_password = new Zend_Form_Element_Text('master_password');
}else{
$master_password = new Zend_Form_Element_Password('master_password');
$master_password->setAttrib('renderPassword','true');
}
$master_password->setAttrib('autocomplete', 'off')
->setAttrib('renderPassword','true')
->setAllowEmpty(true)
@ -81,15 +90,29 @@ class Application_Form_LiveStreamingPreferences extends Zend_Form_SubForm
->setDecorators(array('ViewHelper'));
$this->addElement($live_dj_mount);
}
// demo only code
if(!$isStreamConfigable){
$elements = $this->getElements();
foreach ($elements as $element)
{
if ($element->getType() != 'Zend_Form_Element_Hidden')
{
$element->setAttrib("disabled", "disabled");
}
}
}
}
public function updateVariables(){
global $CC_CONFIG;
$m_port = Application_Model_StreamSetting::GetMasterLiveSteamPort();
$m_mount = Application_Model_StreamSetting::GetMasterLiveSteamMountPoint();
$l_port = Application_Model_StreamSetting::GetDJLiveSteamPort();
$l_mount = Application_Model_StreamSetting::GetDJLiveSteamMountPoint();
$isSaas = Application_Model_Preference::GetPlanLevel() == 'disabled'?false:true;
$isDemo = isset($CC_CONFIG['demo']) && $CC_CONFIG['demo'] == 1;
$master_dj_connection_url = Application_Model_Preference::GetMasterDJSourceConnectionURL();
$live_dj_connection_url = Application_Model_Preference::GetLiveDJSourceConnectionURL();
@ -102,9 +125,9 @@ class Application_Form_LiveStreamingPreferences extends Zend_Form_SubForm
if($l_port=="" || $l_mount==""){
$live_dj_connection_url = "N/A";
}
$this->setDecorators(array(
array('ViewScript', array('viewScript' => 'form/preferences_livestream.phtml', 'master_dj_connection_url'=>$master_dj_connection_url, 'live_dj_connection_url'=>$live_dj_connection_url, 'isSaas' => $isSaas))
array('ViewScript', array('viewScript' => 'form/preferences_livestream.phtml', 'master_dj_connection_url'=>$master_dj_connection_url, 'live_dj_connection_url'=>$live_dj_connection_url, 'isSaas' => $isSaas, 'isDemo' => $isDemo))
));
}

View File

@ -37,17 +37,7 @@ class Application_Form_StreamSetting extends Zend_Form
}
$this->addElement($output_type);
}
# tooltip
$description = 'This option enables metadata for OGG streams (stream
metadata is the track title, artist, and show name that is
displayed in an audio player). VLC and mplayer have a
serious bug when playing an OGG/VORBIS stream that has
metadata information enabled: they will disconnect from the
stream after every song. If you are using an OGG stream and
your listeners do not require support for these audio
players, then feel free to enable this option.';
$icecast_vorbis_metadata = new Zend_Form_Element_Checkbox('icecast_vorbis_metadata');
$icecast_vorbis_metadata->setLabel('Icecast Vorbis Metadata')
->setDescription($description)

View File

@ -1782,6 +1782,7 @@ class Application_Model_Show {
"end_timestamp"=>$rows[$i-1]['end_timestamp'],
"starts"=>$rows[$i-1]['starts'],
"ends"=>$rows[$i-1]['ends'],
"record"=>$rows[$i-1]['record'],
"type"=>"show");
}
@ -1797,6 +1798,7 @@ class Application_Model_Show {
"end_timestamp"=>$rows[$i+1]['end_timestamp'],
"starts"=>$rows[$i+1]['starts'],
"ends"=>$rows[$i+1]['ends'],
"record"=>$rows[$i+1]['record'],
"type"=>"show");
}
@ -1817,6 +1819,7 @@ class Application_Model_Show {
"end_timestamp"=>$rows[$i]['end_timestamp'],
"starts"=>$rows[$i]['starts'],
"ends"=>$rows[$i]['ends'],
"record"=>$rows[$i]['record'],
"type"=>"show");
break;
}
@ -1832,6 +1835,7 @@ class Application_Model_Show {
"end_timestamp"=>$rows[$previousShowIndex]['end_timestamp'],
"starts"=>$rows[$previousShowIndex]['starts'],
"ends"=>$rows[$previousShowIndex]['ends'],
"record"=>$rows[$previousShowIndex]['record'],
"type"=>"show");
}

View File

@ -855,7 +855,6 @@ Logging::log("getting media! - 2");
Logging::log('copyFileToStor: moving file '.$audio_file);
$md5 = md5_file($audio_file);
$duplicate = Application_Model_StoredFile::RecallByMd5($md5, true);
$result = null;
if ($duplicate) {
@ -886,14 +885,22 @@ Logging::log("getting media! - 2");
Logging::log("Warning: couldn't change permissions of $audio_file to 0644");
}
//Martin K.: changed to rename: Much less load + quicker since this is an atomic operation
$r = @rename($audio_file, $audio_stor);
// Check if file is playable
$command = sprintf("/usr/bin/airtime-liquidsoap -c 'output.dummy(audio_to_stereo(single(\"%s\")))' > /dev/null 2>&1", $audio_file);
exec($command, $output, $rv);
if ($rv != 0) {
$result = array("code" => 110, "message" => "This file appears to be corrupted and could not be uploaded.");
}
else {
//Martin K.: changed to rename: Much less load + quicker since this is an atomic operation
$r = @rename($audio_file, $audio_stor);
if ($r === false) {
#something went wrong likely there wasn't enough space in the audio_stor to move the file too.
#warn the user that the file wasn't uploaded and they should check if there is enough disk space.
unlink($audio_file);//remove the file from the organize after failed rename
$result = array("code" => 108, "message" => "The file was not uploaded, this error will occur if the computer hard drive does not have enough disk space.");
if ($r === false) {
#something went wrong likely there wasn't enough space in the audio_stor to move the file too.
#warn the user that the file wasn't uploaded and they should check if there is enough disk space.
unlink($audio_file);//remove the file from the organize after failed rename
$result = array("code" => 108, "message" => "The file was not uploaded, this error will occur if the computer hard drive does not have enough disk space.");
}
}
}
}

View File

@ -3,11 +3,7 @@
<dt id="cb_airtime_auth_override-label">
<label class="optional" for="cb_airtime_auth">
<?php echo $this->element->getElement('cb_airtime_auth')->getLabel() ?>
<span class='info-tooltip'>
<span>
<?php echo $this->element->getElement('cb_airtime_auth')->getDescription() ?>
</span>
</span>
<span class='airtime_auth_help_icon'></span>
</label>
</dt>
<dd id="cb_airtime_auth_override-element">
@ -16,11 +12,7 @@
<dt id="cb_custom_auth_override-label">
<label class="optional" for="cb_custom_auth">
<?php echo $this->element->getElement('cb_custom_auth')->getLabel() ?>
<span class='info-tooltip'>
<span>
<?php echo $this->element->getElement('cb_custom_auth')->getDescription() ?>
</span>
</span>
<span class='custom_auth_help_icon'></span>
</label>
</dt>
<dd id="cb_custom_auth_override-element">

View File

@ -79,7 +79,7 @@
</dt>
<dd id="master_dj_connection_url-element">
<span id="stream_url" class="static_text"><?php echo $this->master_dj_connection_url ?></span>
<?php if( !$this->isSaas ){?>
<?php if( !$this->isSaas && !$this->isDemo){?>
<a href=# id="connection_url_override" style="font-size: 12px;">override</a>&nbsp;&nbsp;
<span class="override_help_icon">
</span><br>
@ -122,7 +122,7 @@
</dt>
<dd id="live_dj_connection_url-element">
<span id="stream_url" class="static_text"><?php echo $this->live_dj_connection_url ?></span>
<?php if( !$this->isSaas ){?>
<?php if( !$this->isSaas && !$this->isDemo ){?>
<a href=# id="connection_url_override" style="font-size: 12px;">override</a>&nbsp;&nbsp;
<span class="override_help_icon">
</span><br>

View File

@ -3,8 +3,12 @@
<fieldset>
<dl class="zend_form">
<dt class="block-display info-text">
Help Airtime improve by letting us know you are using it. This info
will be collected regularly in order to improve your user experience.
Help Airtime improve by letting us know how you are using it. This info
will be collected regularly in order to improve your user experience.
<br /><br />
In additon to that, this is how you vote for existing features. We actively remove
features that are not used, so be sure to click "Yes, help Airtime" to keep
your favourite features around.
</dt>
<dd id="SupportFeedback-element" class="block-display">
<label class="optional" for="SupportFeedback">

View File

@ -2,8 +2,13 @@
<?php if( !$this->isSaas ){?>
<dl class="zend_form">
<dd id="SupportFeedback-element" style="width:90%;">
<div class="info-text">Help Airtime improve by letting us know you are using it. This info
will be collected regularly in order to improve your user experience.</div>
<div class="info-text">
Help Airtime improve by letting us know how you are using it. This info
will be collected regularly in order to improve your user experience.<br /><br />
In additon to that, this is how you vote for existing features. We actively remove
features that are not used, so be sure to click "Yes, help Airtime" to keep
your favourite features around.
</div>
<label class="optional" for="SupportFeedback">
<?php echo $this->element->getElement('SupportFeedback') ?>
<strong><?php echo $this->element->getElement('SupportFeedback')->getLabel() ?></strong>

View File

@ -4,5 +4,6 @@
<div id="login" class="login-content clearfix">
<p class="light">An email has been sent</p>
<p><a class="link" href="<?php echo $this->baseUrl('login'); ?>">Back to login screen</a></p>
</div>
</div>

View File

@ -33,10 +33,7 @@
<dt id="vorbisMetadata-label">
<label class="required">
<?php echo $this->form->getElement('icecast_vorbis_metadata')->getLabel() ?> :
<span class='info-tooltip'>
<span>
<?php echo $this->form->getElement('icecast_vorbis_metadata')->getDescription() ?>
</span>
<span class='icecast_metadata_help_icon'>
</span>
</label>
</dt>

View File

@ -93,7 +93,7 @@ select {
}
/* Version Notification Ends*/
.override_help_icon {
.override_help_icon, .icecast_metadata_help_icon {
cursor: help;
position: relative;
@ -104,8 +104,7 @@ select {
line-height:16px !important;
}
/* Info Tooltip Starts */
.info-tooltip {
.airtime_auth_help_icon, .custom_auth_help_icon {
cursor: help;
position: relative;
display:inline-block; zoom:1;
@ -114,28 +113,6 @@ select {
top:2px; right:7px; left: 3px;
line-height:16px !important;
}
.info-tooltip span {
margin-left: -9999em;
position: absolute;
padding: 1em 1em 1em 1em;
text-indent:0; font-family:Arial, Helvetica, sans-serif !important; font-size:13px !important;
border:#505050 solid 3px;
background:#e6e6e6;
cursor:text;
}
.info-tooltip:hover span:before {
content:"";
position:absolute; top:22px; left:-11px;
width:8px; height:15px;
margin:-7px 0 0 0;
background:url(/css/images/tooltip_arrow.png) 0 0 no-repeat;
}
.info-tooltip:hover span {
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.1); -webkit-box-shadow: 5px 5px rgba(0, 0, 0, 0.1); -moz-box-shadow: 5px 5px rgba(0, 0, 0, 0.1);
position: absolute; left: 25px; top: -18px; z-index: 99;
margin-left: 0; width: 200px;
}
/* Info Tooltip Ends */
/* Clearfix */
.clearfix:after, #side_playlist li:after { content: "."; display: block; height: 0; clear: both; visibility: hidden;}
@ -2401,6 +2378,7 @@ tfoot tr th {
color:red;
border:1px solid #c83f3f;
background:#c6b4b4;
display:none;
}
#plupload_error table td {
color:#902d2d;

View File

@ -83,7 +83,7 @@ function updateProgressBarValue(){
songPercentDone = 0;
currentSong = null;
} else {
if ((currentSong.media_item_played == true && currentShow.length > 0) || songElapsedTime < 5000) {
if ((currentSong.media_item_played == true && currentShow.length > 0) || (songElapsedTime < 5000 && currentShow[0].record != 1)) {
scheduled_play_line_to_switch.attr("class", "line-to-switch on");
scheduled_play_div.addClass("ready");
scheduled_play_source = true;

View File

@ -5,7 +5,8 @@ var AIRTIME = (function(AIRTIME) {
$libContent,
$libTable,
LIB_SELECTED_CLASS = "lib-selected",
chosenItems = {};
chosenItems = {},
visibleChosenItems = {};
if (AIRTIME.library === undefined) {
AIRTIME.library = {};
@ -13,16 +14,45 @@ var AIRTIME = (function(AIRTIME) {
mod = AIRTIME.library;
mod.getChosenItemsLength = function(){
var selected = Object.keys(chosenItems).length;
var cItem,
selected,
$trs;
// Get visible items and check if any chosenItems are visible
$trs = $libTable.find("tbody input:checkbox").parents("tr");
$trs.each(function(i){
for (cItem in chosenItems) {
if (cItem === $(this).attr("id")) {
visibleChosenItems[cItem] = $(this).data('aData');
}
}
});
selected = Object.keys(visibleChosenItems).length;
visibleChosenItems = {};
return selected;
};
mod.getChosenAudioFilesLength = function(){
var files = Object.keys(chosenItems),
i, length,
count = 0,
reAudio=/^au/ ;
//var files = Object.keys(chosenItems),
var files,
$trs,
cItem,
i, length,
count = 0,
reAudio=/^au/ ;
// Get visible items and check if any chosenItems are visible
$trs = $libTable.find("tbody input:checkbox").parents("tr");
$trs.each(function(i){
for (cItem in chosenItems) {
if (cItem === $(this).attr("id")) {
visibleChosenItems[cItem] = $(this).data('aData');
}
}
});
files = Object.keys(visibleChosenItems);
for (i = 0, length = files.length; i < length; i++) {
@ -72,14 +102,27 @@ var AIRTIME = (function(AIRTIME) {
mod.getSelectedData = function() {
var id,
data = [];
data = [],
cItem,
$trs;
$.fn.reverse = [].reverse;
for (id in chosenItems) {
if (chosenItems.hasOwnProperty(id)) {
data.push(chosenItems[id]);
}
}
// Get visible items and check if any chosenItems are visible
$trs = $libTable.find("tbody input:checkbox").parents("tr").reverse();
$trs.each(function(i){
for (cItem in chosenItems) {
if (cItem === $(this).attr("id")) {
visibleChosenItems[cItem] = $(this).data('aData');
}
}
});
for (id in visibleChosenItems) {
if (visibleChosenItems.hasOwnProperty(id)) {
data.push(visibleChosenItems[id]);
}
}
return data;
};
@ -153,10 +196,14 @@ var AIRTIME = (function(AIRTIME) {
/*
* selects all items which the user can currently see.
* (behaviour taken from gmail)
*
* by default the items are selected in reverse order
* so we need to reverse it back
*/
mod.selectCurrentPage = function() {
var $trs = $libTable.find("tbody input:checkbox").parents("tr");
$.fn.reverse = [].reverse;
var $trs = $libTable.find("tbody input:checkbox").parents("tr").reverse();
$trs.each(function(i, el){
$el = $(this);
@ -656,7 +703,7 @@ function checkImportStatus() {
}
else{
if ($(div).is(':visible')) {
table.fnDraw();
table.fnStandingRedraw();
}
div.hide();
}

View File

@ -24,6 +24,7 @@ $(document).ready(function() {
.append('<td>' + j.error.message + '</td>');
$("#plupload_error").find("table").append(row);
$("#plupload_error table").css("display", "inline-table");
}else{
var tempFileName = j.tempfilepath;
$.get('/Plupload/copyfile/format/json/name/'+encodeURIComponent(file.name)+'/tempname/'+encodeURIComponent(tempFileName), function(json){
@ -34,6 +35,7 @@ $(document).ready(function() {
.append('<td>' + jr.error.message + '</td>');
$("#plupload_error").find("table").append(row);
$("#plupload_error table").css("display", "inline-table");
}
});
}

View File

@ -257,4 +257,25 @@ $(document).ready(function() {
at: "right center"
},
})
$(".icecast_metadata_help_icon").qtip({
content: {
text: "This option enables metadata for OGG streams (stream metadata is the track title, artist, and show name that is displayed in an audio player). VLC and mplayer have a serious bug when playing an OGG/VORBIS stream that has metadata information enabled: they will disconnect from the stream after every song. If you are using an OGG stream and your listeners do not require support for these audio players, then feel free to enable this option."
},
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"
},
})
});

View File

@ -179,7 +179,48 @@ function setAddShowEvents() {
form.find("#add_show_day_check-element").addClass("block-display clearfix");
form.find("#add_show_day_check-element label").addClass("wrapp-label");
form.find("#add_show_day_check-element br").remove();
form.find(".airtime_auth_help_icon").qtip({
content: {
text: "This follows the same security pattern for the shows: only users assigned to the show can connect."
},
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"
}
});
form.find(".custom_auth_help_icon").qtip({
content: {
text: "Specify custom authentication which will work only for this show."
},
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();

File diff suppressed because it is too large Load Diff

View File

@ -97,10 +97,12 @@ class AirtimeMetadata:
if value is not None:
value = unicode(value)
else:
value = unicode('');
if len(value) > 0:
self.logger.debug("Saving key '%s' with value '%s' to file", key, value)
airtime_file[self.airtime2mutagen[key]] = value
#if len(value) > 0:
self.logger.debug("Saving key '%s' with value '%s' to file", key, value)
airtime_file[self.airtime2mutagen[key]] = value
airtime_file.save()
except Exception, e: