commit
8c77bfde1d
|
@ -155,20 +155,8 @@ class FileDataHelper {
|
||||||
} else {
|
} else {
|
||||||
$ext = 'jpg';
|
$ext = 'jpg';
|
||||||
}
|
}
|
||||||
|
self::resizeGroup($file, $ext);
|
||||||
|
|
||||||
if (file_exists($file)) {
|
|
||||||
self::resizeImage($file, $file . '-32.jpg', $ext, 32, 100);
|
|
||||||
self::resizeImage($file, $file . '-64.jpg', $ext, 64, 100);
|
|
||||||
self::resizeImage($file, $file . '-128.jpg', $ext, 128, 100);
|
|
||||||
self::resizeImage($file, $file . '-256.jpg', $ext, 256, 100);
|
|
||||||
self::resizeImage($file, $file . '-512.jpg', $ext, 512, 100);
|
|
||||||
self::imgToDataURI($file . '-32.jpg', $file . '-32');
|
|
||||||
self::imgToDataURI($file . '-64.jpg', $file . '-64');
|
|
||||||
self::imgToDataURI($file . '-128.jpg', $file . '-128');
|
|
||||||
self::imgToDataURI($file . '-256.jpg', $file . '-256');
|
|
||||||
} else {
|
|
||||||
Logging::error("The file $file does not exist");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
$get_img = '';
|
$get_img = '';
|
||||||
}
|
}
|
||||||
|
@ -231,26 +219,120 @@ class FileDataHelper {
|
||||||
} else {
|
} else {
|
||||||
$ext = 'jpg';
|
$ext = 'jpg';
|
||||||
}
|
}
|
||||||
|
self::resizeGroup($rfile, $ext);
|
||||||
|
|
||||||
if (file_exists($rfile)) {
|
|
||||||
self::resizeImage($rfile, $rfile . '-32.jpg', $ext, 32, 100);
|
|
||||||
self::resizeImage($rfile, $rfile . '-64.jpg', $ext, 64, 100);
|
|
||||||
self::resizeImage($rfile, $rfile . '-128.jpg', $ext, 128, 100);
|
|
||||||
self::resizeImage($rfile, $rfile . '-256.jpg', $ext, 256, 100);
|
|
||||||
self::resizeImage($rfile, $rfile . '-512.jpg', $ext, 512, 100);
|
|
||||||
self::imgToDataURI($rfile . '-32.jpg', $rfile . '-32');
|
|
||||||
self::imgToDataURI($rfile . '-64.jpg', $rfile . '-64');
|
|
||||||
self::imgToDataURI($rfile . '-128.jpg', $rfile . '-128');
|
|
||||||
self::imgToDataURI($rfile . '-256.jpg', $rfile . '-256');
|
|
||||||
} else {
|
|
||||||
Logging::error("The file $rfile does not exist");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
$get_img = "";
|
$get_img = "";
|
||||||
}
|
}
|
||||||
return $get_img;
|
return $get_img;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload artwork
|
||||||
|
*
|
||||||
|
* @param string $trackid
|
||||||
|
* @param string $data
|
||||||
|
*
|
||||||
|
* @return string Path to artwork
|
||||||
|
*/
|
||||||
|
public static function setArtwork($trackid, $data)
|
||||||
|
{
|
||||||
|
$file = Application_Model_StoredFile::RecallById($trackid);
|
||||||
|
$md = $file->getMetadata();
|
||||||
|
|
||||||
|
$storDir = Application_Model_MusicDir::getStorDir();
|
||||||
|
$fp = $storDir->getDirectory();
|
||||||
|
|
||||||
|
$dbAudioPath = $md["MDATA_KEY_FILEPATH"];
|
||||||
|
$fullpath = $fp . $dbAudioPath;
|
||||||
|
|
||||||
|
if ($data == "0") {
|
||||||
|
|
||||||
|
$get_img = "";
|
||||||
|
self::removeArtwork($trackid, $data);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$base64 = @$data;
|
||||||
|
$mime = explode(';', $base64)[0];
|
||||||
|
|
||||||
|
$audioPath = dirname($fullpath);
|
||||||
|
$dbPath = dirname($dbAudioPath);
|
||||||
|
$path_parts = pathinfo($fullpath);
|
||||||
|
$file = $path_parts['filename'];
|
||||||
|
|
||||||
|
//Save Data URI
|
||||||
|
if (file_put_contents($audioPath . "/" . $file, $base64)) {
|
||||||
|
$get_img = $dbPath . "/" . $file;
|
||||||
|
} else {
|
||||||
|
Logging::error("Could not save Data URI");
|
||||||
|
}
|
||||||
|
|
||||||
|
$rfile = $audioPath . "/" . $file;
|
||||||
|
|
||||||
|
if ($mime == "data:image/png") {
|
||||||
|
$ext = 'png';
|
||||||
|
} elseif ($mime == "data:image/gif") {
|
||||||
|
$ext = 'gif';
|
||||||
|
} elseif ($mime == "data:image/bmp") {
|
||||||
|
$ext = 'bmp';
|
||||||
|
} else {
|
||||||
|
$ext = 'jpg';
|
||||||
|
}
|
||||||
|
self::resizeGroup($rfile, $ext);
|
||||||
|
|
||||||
|
}
|
||||||
|
return $get_img;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Deletes just the artwork
|
||||||
|
*/
|
||||||
|
public static function removeArtwork($trackid)
|
||||||
|
{
|
||||||
|
$file = Application_Model_StoredFile::RecallById($trackid);
|
||||||
|
$md = $file->getMetadata();
|
||||||
|
|
||||||
|
$storDir = Application_Model_MusicDir::getStorDir();
|
||||||
|
$fp = $storDir->getDirectory();
|
||||||
|
|
||||||
|
$dbAudioPath = $md["MDATA_KEY_ARTWORK"];
|
||||||
|
$fullpath = $fp . $dbAudioPath;
|
||||||
|
|
||||||
|
if (file_exists($fullpath)) {
|
||||||
|
foreach (glob("$fullpath*", GLOB_NOSORT) as $filename) {
|
||||||
|
unlink($filename);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Exception("Could not locate file ".$filepath);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize artwork group
|
||||||
|
*
|
||||||
|
* @param string $file
|
||||||
|
* @param string $ext
|
||||||
|
*/
|
||||||
|
public static function resizeGroup($file, $ext)
|
||||||
|
{
|
||||||
|
if (file_exists($file)) {
|
||||||
|
self::resizeImage($file, $file . '-32.jpg', $ext, 32, 100);
|
||||||
|
self::resizeImage($file, $file . '-64.jpg', $ext, 64, 100);
|
||||||
|
self::resizeImage($file, $file . '-128.jpg', $ext, 128, 100);
|
||||||
|
self::resizeImage($file, $file . '-256.jpg', $ext, 256, 100);
|
||||||
|
self::resizeImage($file, $file . '-512.jpg', $ext, 512, 100);
|
||||||
|
self::imgToDataURI($file . '-32.jpg', $file . '-32');
|
||||||
|
self::imgToDataURI($file . '-64.jpg', $file . '-64');
|
||||||
|
self::imgToDataURI($file . '-128.jpg', $file . '-128');
|
||||||
|
self::imgToDataURI($file . '-256.jpg', $file . '-256');
|
||||||
|
} else {
|
||||||
|
Logging::error("The file $file does not exist");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render image
|
* Render image
|
||||||
* Used in API to render JPEG
|
* Used in API to render JPEG
|
||||||
|
|
|
@ -395,7 +395,16 @@ class LibraryController extends Zend_Controller_Action
|
||||||
//on edit, if no artwork is set and audiofile has image, automatically add it
|
//on edit, if no artwork is set and audiofile has image, automatically add it
|
||||||
if ($j["name"] == "artwork") {
|
if ($j["name"] == "artwork") {
|
||||||
if ($j["value"] == null || $j["value"] == ''){
|
if ($j["value"] == null || $j["value"] == ''){
|
||||||
$serialized["artwork"] = FileDataHelper::resetArtwork($file_id);
|
$serialized["artwork"] = FileDataHelper::resetArtwork($file_id);
|
||||||
|
}
|
||||||
|
} elseif ($j["name"] == "set_artwork") {
|
||||||
|
if ($j["value"] != null || $j["value"] != ''){
|
||||||
|
$serialized["artwork"] = FileDataHelper::setArtwork($file_id, $j["value"] );
|
||||||
|
}
|
||||||
|
} elseif ($j["name"] == "remove_artwork") {
|
||||||
|
if ($j["value"] == 1){
|
||||||
|
$remove_artwork = true;
|
||||||
|
$serialized["artwork"] = FileDataHelper::removeArtwork($file_id);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$serialized[$j["name"]] = $j["value"];
|
$serialized[$j["name"]] = $j["value"];
|
||||||
|
|
|
@ -20,15 +20,32 @@ class Application_Form_EditAudioMD extends Zend_Form
|
||||||
|
|
||||||
// Add artwork hidden field
|
// Add artwork hidden field
|
||||||
$artwork = new Zend_Form_Element_Hidden('artwork');
|
$artwork = new Zend_Form_Element_Hidden('artwork');
|
||||||
|
$artwork->class = 'input_text artwork_'. $p_id;
|
||||||
$artwork->setFilters(array('StringTrim'))
|
$artwork->setFilters(array('StringTrim'))
|
||||||
->setValidators(array(
|
->setValidators(array(
|
||||||
new Zend_Validate_StringLength(array('max' => 512))
|
new Zend_Validate_StringLength(array('max' => 2048))
|
||||||
));
|
));
|
||||||
$file_id->addDecorator('HtmlTag', array('tag' => 'div', 'style' => 'display:none'));
|
$file_id->addDecorator('HtmlTag', array('tag' => 'div', 'style' => 'display:none'));
|
||||||
$file_id->removeDecorator('Label');
|
$file_id->removeDecorator('Label');
|
||||||
$file_id->setAttrib('class', 'artwork');
|
$file_id->setAttrib('class', 'artwork');
|
||||||
$this->addElement($artwork);
|
$this->addElement($artwork);
|
||||||
|
|
||||||
|
// Set artwork hidden field
|
||||||
|
$set_artwork = new Zend_Form_Element_Hidden('set_artwork');
|
||||||
|
$set_artwork->class = 'input_text set_artwork_'. $p_id;
|
||||||
|
$file_id->addDecorator('HtmlTag', array('tag' => 'div', 'style' => 'display:none'));
|
||||||
|
$file_id->removeDecorator('Label');
|
||||||
|
$file_id->setAttrib('class', 'set_artwork');
|
||||||
|
$this->addElement($set_artwork);
|
||||||
|
|
||||||
|
// Remove artwork hidden field
|
||||||
|
$remove_artwork = new Zend_Form_Element_Hidden('remove_artwork');
|
||||||
|
$remove_artwork->class = 'input_text remove_artwork_'. $p_id;
|
||||||
|
$file_id->addDecorator('HtmlTag', array('tag' => 'div', 'style' => 'display:none'));
|
||||||
|
$file_id->removeDecorator('Label');
|
||||||
|
$file_id->setAttrib('class', 'remove_artwork');
|
||||||
|
$this->addElement($remove_artwork);
|
||||||
|
|
||||||
// Add title field
|
// Add title field
|
||||||
$track_title = new Zend_Form_Element_Text('track_title');
|
$track_title = new Zend_Form_Element_Text('track_title');
|
||||||
$track_title->class = 'input_text';
|
$track_title->class = 'input_text';
|
||||||
|
|
|
@ -104,7 +104,10 @@ SQL;
|
||||||
$utcNow = new DateTime("now", new DateTimeZone("UTC"));
|
$utcNow = new DateTime("now", new DateTimeZone("UTC"));
|
||||||
|
|
||||||
$shows = Application_Model_Show::getPrevCurrentNext($utcNow, $utcTimeEnd, $showsToRetrieve);
|
$shows = Application_Model_Show::getPrevCurrentNext($utcNow, $utcTimeEnd, $showsToRetrieve);
|
||||||
$currentShowID = (is_array($shows['currentShow'] && count($shows['currentShow'])>0))?$shows['currentShow']['instance_id']:null;
|
$currentShowID = null;
|
||||||
|
if (is_array($shows['currentShow']) && count($shows['currentShow'])>0) {
|
||||||
|
$currentShowID = $shows['currentShow']['instance_id'];
|
||||||
|
}
|
||||||
$source = self::_getSource();
|
$source = self::_getSource();
|
||||||
$results = Application_Model_Schedule::getPreviousCurrentNextMedia($utcNow, $currentShowID, self::_getSource());
|
$results = Application_Model_Schedule::getPreviousCurrentNextMedia($utcNow, $currentShowID, self::_getSource());
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,19 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="track-edit-left">
|
<div class="track-edit-left">
|
||||||
<?php echo '<img width="140" height="140" src="' . $get_artwork .'">'; ?>
|
<div class="artwork-upload" data-id="<?php echo($this->id); ?>">
|
||||||
|
<div class="artwork-edit">
|
||||||
|
<input type='file' class="artworkUpload artwork-uploaded-<?php echo($this->id); ?>" id="artworkUpload" data-id="<?php echo($this->id); ?>" accept=".png, .jpg, .jpeg" />
|
||||||
|
<label for="artworkUpload"></label>
|
||||||
|
</div>
|
||||||
|
<div id="artwork-preview" class="artwork-preview">
|
||||||
|
<div class="artwork-preview-<?php echo($this->id); ?>" id="artworkPreview" style="background-image: url(<?php echo $get_artwork; ?>);">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="#" class="delete-artwork" data-id="<?php echo($this->id); ?>" style="font-size: 11px;">Remove</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="height: 160px;"></div>
|
<div style="height: 160px;"></div>
|
||||||
|
|
|
@ -35,7 +35,7 @@ INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_pass', 'h
|
||||||
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_admin_user', '', 'string');
|
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_admin_user', '', 'string');
|
||||||
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_admin_pass', '', 'string');
|
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_admin_pass', '', 'string');
|
||||||
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_mount', 'airtime_128', 'string');
|
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_mount', 'airtime_128', 'string');
|
||||||
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_url', 'http://airtime.sourcefabric.org', 'string');
|
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_url', 'https://libretime.org', 'string');
|
||||||
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_description', 'LibreTime Radio! Stream #1', 'string');
|
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_description', 'LibreTime Radio! Stream #1', 'string');
|
||||||
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_genre', 'genre', 'string');
|
INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s1_genre', 'genre', 'string');
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 66 KiB |
|
@ -4284,3 +4284,64 @@ li .ui-state-hover {
|
||||||
.track-edit-right {
|
.track-edit-right {
|
||||||
margin-left: 160px;
|
margin-left: 160px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Artwork Upload in Tracks Edit */
|
||||||
|
.artwork-upload {
|
||||||
|
position: relative;
|
||||||
|
max-width: 205px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.artwork-upload .artwork-edit {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
.artwork-upload .artwork-edit input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.artwork-upload .artwork-edit input + label {
|
||||||
|
display: inline-block;
|
||||||
|
width: 140px;
|
||||||
|
height: 140px;
|
||||||
|
margin: 1px;
|
||||||
|
border-radius: 1px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.12);
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: normal;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
.artwork-upload .artwork-edit input + label:hover {
|
||||||
|
background: rgba(0, 0, 0, 0.40);
|
||||||
|
border-color: #d6d6d6;
|
||||||
|
}
|
||||||
|
.artwork-upload .artwork-edit input + label:after {
|
||||||
|
color: #757575;
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
text-align: center;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
.artwork-upload .artwork-preview {
|
||||||
|
width: 140px;
|
||||||
|
height: 140px;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 1px;
|
||||||
|
border: 2px solid #F8F8F8;
|
||||||
|
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
.artwork-upload .artwork-preview > div {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-size: cover;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Drag and Drop Artwork */
|
||||||
|
body.droppable .artwork-upload .artwork-preview {
|
||||||
|
border: 2px dashed lightblue;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
|
@ -1601,6 +1601,70 @@ var validationTypes = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function readArtworkURL(input, id) {
|
||||||
|
|
||||||
|
if (input.files && input.files[0]) {
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onload = function(e) {
|
||||||
|
$('.artwork-preview-'+id).css('background-image', 'url('+e.target.result +')');
|
||||||
|
$('.artwork-preview-'+id).hide();
|
||||||
|
$('.artwork-preview-'+id).fadeIn(500);
|
||||||
|
$('.set_artwork_'+id).val(function() {
|
||||||
|
return e.target.result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
reader.readAsDataURL(input.files[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resample Artwork
|
||||||
|
var resampleImg = (function (canvas) {
|
||||||
|
|
||||||
|
function resampleImg(img, width, height, onresample) {
|
||||||
|
var load = typeof img == "string",
|
||||||
|
i = load || img;
|
||||||
|
if (load) {
|
||||||
|
i = new Image;
|
||||||
|
i.onload = onload;
|
||||||
|
i.onerror = onerror;
|
||||||
|
}
|
||||||
|
i._onresample = onresample;
|
||||||
|
i._width = width;
|
||||||
|
i._height = height;
|
||||||
|
load ? (i.src = img) : onload.call(img);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onerror() {
|
||||||
|
throw ("not found: " + this.src);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onload() {
|
||||||
|
var img = this,
|
||||||
|
width = img._width,
|
||||||
|
height = img._height,
|
||||||
|
onresample = img._onresample;
|
||||||
|
|
||||||
|
var minValue = Math.min(img.height, img.width);
|
||||||
|
width == null && (width = round(img.width * height / img.height));
|
||||||
|
height == null && (height = round(img.height * width / img.width));
|
||||||
|
|
||||||
|
delete img._onresample;
|
||||||
|
delete img._width;
|
||||||
|
delete img._height;
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
context.drawImage(img,0,0,minValue,minValue,0,0,width,height);
|
||||||
|
onresample(canvas.toDataURL("image/jpeg"));
|
||||||
|
}
|
||||||
|
|
||||||
|
var context = canvas.getContext("2d"),
|
||||||
|
round = Math.round;
|
||||||
|
|
||||||
|
return resampleImg;
|
||||||
|
|
||||||
|
}(this.document.createElement("canvas")));
|
||||||
|
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
if (window.location.href.indexOf("showbuilder") > -1) {
|
if (window.location.href.indexOf("showbuilder") > -1) {
|
||||||
AIRTIME.library.initPodcastDatatable();
|
AIRTIME.library.initPodcastDatatable();
|
||||||
|
@ -1613,5 +1677,114 @@ $(document).ready(function() {
|
||||||
$(window).resize(function() {
|
$(window).resize(function() {
|
||||||
resizeAdvancedSearch();
|
resizeAdvancedSearch();
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
|
// delete artwork
|
||||||
|
$(document).on('click', '.delete-artwork', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
var id = $(this).attr('data-id');
|
||||||
|
$('.artwork-preview-'+id).css('background-image', 'url('+ baseUrl +'css/images/no-cover.jpg)');
|
||||||
|
$('.artwork-preview-'+id).hide();
|
||||||
|
$('.artwork-preview-'+id).fadeIn(500);
|
||||||
|
$('.artwork_'+id).val(function() {
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
$('.set_artwork_'+id).val(function() {
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
$('.remove_artwork_'+id).val(function() {
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// image upload by clicking on the artwork container
|
||||||
|
$(document).on('change', '.artworkUpload', 'input', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
var id = $(this).attr('data-id');
|
||||||
|
readArtworkURL(this, id);
|
||||||
|
});
|
||||||
|
|
||||||
|
// image upload by dragging onto the artwork container
|
||||||
|
$.event.props.push('dataTransfer');
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
var s;
|
||||||
|
var Artwork = {
|
||||||
|
settings: {
|
||||||
|
body: $("body")
|
||||||
|
},
|
||||||
|
init: function() {
|
||||||
|
s = Artwork.settings;
|
||||||
|
Artwork.bindUIActions();
|
||||||
|
},
|
||||||
|
bindUIActions: function() {
|
||||||
|
|
||||||
|
var timer;
|
||||||
|
s.body.on('dragover', '.artwork-upload', function(event) {
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
clearTimeout(timer);
|
||||||
|
Artwork.showDroppableArea();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
s.body.on('dragleave', '.artwork-upload', function(event) {
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
timer = setTimeout(function() {
|
||||||
|
Artwork.hideDroppableArea();
|
||||||
|
}, 200);
|
||||||
|
});
|
||||||
|
s.body.on('drop', '.artwork-upload', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
var id = $(this).attr('data-id');
|
||||||
|
Artwork.handleDrop(event.dataTransfer.files, id);
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
showDroppableArea: function() {
|
||||||
|
s.body.addClass("droppable");
|
||||||
|
},
|
||||||
|
hideDroppableArea: function() {
|
||||||
|
s.body.removeClass("droppable");
|
||||||
|
},
|
||||||
|
handleDrop: function(files, id) {
|
||||||
|
Artwork.hideDroppableArea();
|
||||||
|
var file = files[0];
|
||||||
|
if (typeof file !== 'undefined' && file.type.match('image.*')) {
|
||||||
|
Artwork.resizeImage(file, 512, function(data) {
|
||||||
|
Artwork.placeImage(data, id);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
alert("The file is not an image.");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resizeImage: function(file, size, callback) {
|
||||||
|
var fileTracker = new FileReader;
|
||||||
|
fileTracker.onload = function() {
|
||||||
|
resampleImg(this.result, size, size, callback);
|
||||||
|
}
|
||||||
|
fileTracker.readAsDataURL(file);
|
||||||
|
fileTracker.onabort = function() {
|
||||||
|
alert("Upload aborted!");
|
||||||
|
}
|
||||||
|
fileTracker.onerror = function() {
|
||||||
|
alert("File could not be read.");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
placeImage: function(data, id) {
|
||||||
|
$('.artwork-preview-'+id).css('background-image', 'url('+ data +')');
|
||||||
|
$('.artwork-preview-'+id).hide();
|
||||||
|
$('.artwork-preview-'+id).fadeIn(500);
|
||||||
|
$('.set_artwork_'+id).val(function() {
|
||||||
|
return data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Artwork.init();
|
||||||
|
})();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
# Installing LibreTime
|
# Installing LibreTime
|
||||||
|
There two methods of installing LibreTime - [Source](#source) or
|
||||||
|
[Ubuntu package](#ubuntu-package).
|
||||||
|
|
||||||
|
## Source
|
||||||
LibreTime releases can be downloaded [here](https://github.com/LibreTime/libretime/releases).
|
LibreTime releases can be downloaded [here](https://github.com/LibreTime/libretime/releases).
|
||||||
|
|
||||||
Recommendations:
|
Recommendations:
|
||||||
|
@ -18,12 +21,27 @@ sudo ./install
|
||||||
|
|
||||||
By default, the installer will install and configure all dependencies.
|
By default, the installer will install and configure all dependencies.
|
||||||
|
|
||||||
|
## Ubuntu Package
|
||||||
|
LibreTime maintains amd64 .deb packages for Ubuntu 16.04 (Xenial) and 18.04
|
||||||
|
(Bionic). These can be downloaded [here](https://github.com/LibreTime/libretime-debian-packaging/releases).
|
||||||
|
Issues with installation of these packages should be reported to the
|
||||||
|
[LibretTime/libretime-debian-packaging](https://github.com/LibreTime/libretime-debian-packaging)
|
||||||
|
repository.
|
||||||
|
|
||||||
|
These are installed by running the following from the command line (the `./` in
|
||||||
|
front of the libretime package is important):
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt install icecast2 ./libretime_<version>_amd64.deb
|
||||||
|
```
|
||||||
|
`<version>` is replaced by the version of the package downloaded.
|
||||||
|
|
||||||
## Alternative OS installations
|
## Alternative OS installations
|
||||||
Installation in Debian 9 and other Linux distributions is possible, but multiple outstanding issues have yet
|
Installation in Debian 9 and other Linux distributions is possible, but these
|
||||||
to be resolved. Installation on Ubuntu 14.04.5 LTS (Trusty Tahr) is also working, but deprecated due to the
|
are less tested. Installation on Ubuntu 14.04.5 LTS (Trusty Tahr) is also working, but deprecated due to the
|
||||||
fact that this version will reach its official end of life in April 2019.
|
fact that this version will reach its official end of life in April 2019.
|
||||||
|
|
||||||
Plans are in the works for `.deb` and `.rpm` packages, as well as Docker and AWS images.
|
Plans are in the works for `.rpm` packages, as well as Docker and AWS images.
|
||||||
|
|
||||||
Please note that the install script does not take care to ensure that any
|
Please note that the install script does not take care to ensure that any
|
||||||
packages installed are set up in a secure manner. Please see the chapter on
|
packages installed are set up in a secure manner. Please see the chapter on
|
||||||
|
|
|
@ -60,14 +60,14 @@ s3_mount = "airtime_160.mp3"
|
||||||
s4_mount = "airtime_160.mp3"
|
s4_mount = "airtime_160.mp3"
|
||||||
|
|
||||||
# Webstream metadata settings
|
# Webstream metadata settings
|
||||||
s1_url = "http://airtime.sourcefabric.org"
|
s1_url = "https://libretime.org"
|
||||||
s2_url = "http://airtime.sourcefabric.org"
|
s2_url = "https://libretime.org"
|
||||||
s3_url = "http://airtime.sourcefabric.org"
|
s3_url = "https://libretime.org"
|
||||||
s4_url = "http://airtime.sourcefabric.org"
|
s4_url = "https://libretime.org"
|
||||||
s1_description = "Airtime Radio! Stream 1"
|
s1_description = "LibreTime Radio! Stream 1"
|
||||||
s2_description = "Airtime Radio! Stream 2"
|
s2_description = "LibreTime Radio! Stream 2"
|
||||||
s3_description = "Airtime Radio! Stream 3"
|
s3_description = "LibreTime Radio! Stream 3"
|
||||||
s4_description = "Airtime Radio! Stream 4"
|
s4_description = "LibreTime Radio! Stream 4"
|
||||||
s1_genre = "genre"
|
s1_genre = "genre"
|
||||||
s2_genre = "genre"
|
s2_genre = "genre"
|
||||||
s3_genre = "genre"
|
s3_genre = "genre"
|
||||||
|
|
|
@ -7,15 +7,32 @@ import sys
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
import time
|
import time
|
||||||
# For RabbitMQ
|
# For RabbitMQ
|
||||||
from kombu.connection import BrokerConnection
|
from kombu.connection import Connection
|
||||||
from kombu.messaging import Exchange, Queue
|
from kombu.messaging import Exchange, Queue
|
||||||
from kombu.simple import SimpleQueue
|
from kombu.simple import SimpleQueue
|
||||||
from amqp.exceptions import AMQPError
|
from amqp.exceptions import AMQPError
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
from kombu.mixins import ConsumerMixin
|
||||||
|
|
||||||
logging.captureWarnings(True)
|
logging.captureWarnings(True)
|
||||||
|
|
||||||
|
|
||||||
|
class RabbitConsumer(ConsumerMixin):
|
||||||
|
def __init__(self, connection, queues, handler):
|
||||||
|
self.connection = connection
|
||||||
|
self.queues = queues
|
||||||
|
self.handler = handler
|
||||||
|
|
||||||
|
def get_consumers(self, Consumer, channel):
|
||||||
|
return [
|
||||||
|
Consumer(self.queues, callbacks=[self.on_message], accept=['text/plain']),
|
||||||
|
]
|
||||||
|
|
||||||
|
def on_message(self, body, message):
|
||||||
|
self.handler.handle_message(message.payload)
|
||||||
|
message.ack()
|
||||||
|
|
||||||
class PypoMessageHandler(Thread):
|
class PypoMessageHandler(Thread):
|
||||||
def __init__(self, pq, rq, config):
|
def __init__(self, pq, rq, config):
|
||||||
Thread.__init__(self)
|
Thread.__init__(self)
|
||||||
|
@ -26,22 +43,19 @@ class PypoMessageHandler(Thread):
|
||||||
|
|
||||||
def init_rabbit_mq(self):
|
def init_rabbit_mq(self):
|
||||||
self.logger.info("Initializing RabbitMQ stuff")
|
self.logger.info("Initializing RabbitMQ stuff")
|
||||||
simple_queue = None
|
|
||||||
try:
|
try:
|
||||||
schedule_exchange = Exchange("airtime-pypo", "direct", durable=True, auto_delete=True)
|
schedule_exchange = Exchange("airtime-pypo", "direct", durable=True, auto_delete=True)
|
||||||
schedule_queue = Queue("pypo-fetch", exchange=schedule_exchange, key="foo")
|
schedule_queue = Queue("pypo-fetch", exchange=schedule_exchange, key="foo")
|
||||||
connection = BrokerConnection(self.config["host"],
|
with Connection(self.config["host"], \
|
||||||
self.config["user"],
|
self.config["user"], \
|
||||||
self.config["password"],
|
self.config["password"], \
|
||||||
self.config["vhost"])
|
self.config["vhost"], \
|
||||||
|
heartbeat = 5) as connection:
|
||||||
channel = connection.channel()
|
rabbit = RabbitConsumer(connection, [schedule_queue], self)
|
||||||
simple_queue = SimpleQueue(channel, schedule_queue)
|
rabbit.run()
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
self.logger.error(e)
|
self.logger.error(e)
|
||||||
|
|
||||||
return simple_queue
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Handle a message from RabbitMQ, put it into our yucky global var.
|
Handle a message from RabbitMQ, put it into our yucky global var.
|
||||||
Hopefully there is a better way to do this.
|
Hopefully there is a better way to do this.
|
||||||
|
@ -89,12 +103,7 @@ class PypoMessageHandler(Thread):
|
||||||
|
|
||||||
def main(self):
|
def main(self):
|
||||||
try:
|
try:
|
||||||
with self.init_rabbit_mq() as queue:
|
self.init_rabbit_mq()
|
||||||
while True:
|
|
||||||
message = queue.get(block=True)
|
|
||||||
self.handle_message(message.payload)
|
|
||||||
# ACK the message to take it off the queue
|
|
||||||
message.ack()
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
self.logger.error('Exception: %s', e)
|
self.logger.error('Exception: %s', e)
|
||||||
self.logger.error("traceback: %s", traceback.format_exc())
|
self.logger.error("traceback: %s", traceback.format_exc())
|
||||||
|
|
Loading…
Reference in New Issue