diff --git a/airtime_mvc/application/common/FileDataHelper.php b/airtime_mvc/application/common/FileDataHelper.php index 3c576f685..d9e8b638a 100644 --- a/airtime_mvc/application/common/FileDataHelper.php +++ b/airtime_mvc/application/common/FileDataHelper.php @@ -155,20 +155,8 @@ class FileDataHelper { } else { $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 { $get_img = ''; } @@ -231,26 +219,120 @@ class FileDataHelper { } else { $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 { $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 * Used in API to render JPEG diff --git a/airtime_mvc/application/controllers/LibraryController.php b/airtime_mvc/application/controllers/LibraryController.php index 28c5f02bb..7b41603f7 100644 --- a/airtime_mvc/application/controllers/LibraryController.php +++ b/airtime_mvc/application/controllers/LibraryController.php @@ -395,7 +395,16 @@ class LibraryController extends Zend_Controller_Action //on edit, if no artwork is set and audiofile has image, automatically add it if ($j["name"] == "artwork") { 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 { $serialized[$j["name"]] = $j["value"]; diff --git a/airtime_mvc/application/forms/EditAudioMD.php b/airtime_mvc/application/forms/EditAudioMD.php index 62a83f66c..dda96aa5c 100644 --- a/airtime_mvc/application/forms/EditAudioMD.php +++ b/airtime_mvc/application/forms/EditAudioMD.php @@ -20,15 +20,32 @@ class Application_Form_EditAudioMD extends Zend_Form // Add artwork hidden field $artwork = new Zend_Form_Element_Hidden('artwork'); + $artwork->class = 'input_text artwork_'. $p_id; $artwork->setFilters(array('StringTrim')) ->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->removeDecorator('Label'); $file_id->setAttrib('class', '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 $track_title = new Zend_Form_Element_Text('track_title'); $track_title->class = 'input_text'; diff --git a/airtime_mvc/application/views/scripts/library/edit-file-md.phtml b/airtime_mvc/application/views/scripts/library/edit-file-md.phtml index 4f09f9db4..c216987ae 100644 --- a/airtime_mvc/application/views/scripts/library/edit-file-md.phtml +++ b/airtime_mvc/application/views/scripts/library/edit-file-md.phtml @@ -19,7 +19,19 @@
- '; ?> +
+
+ + +
+
+
+
+
+
+
+ Remove +
diff --git a/airtime_mvc/public/css/images/no-cover.jpg b/airtime_mvc/public/css/images/no-cover.jpg index cd38cfc0d..bd4f12cf8 100644 Binary files a/airtime_mvc/public/css/images/no-cover.jpg and b/airtime_mvc/public/css/images/no-cover.jpg differ diff --git a/airtime_mvc/public/css/styles.css b/airtime_mvc/public/css/styles.css index 981ac5f92..087bb5ba9 100644 --- a/airtime_mvc/public/css/styles.css +++ b/airtime_mvc/public/css/styles.css @@ -4284,3 +4284,64 @@ li .ui-state-hover { .track-edit-right { 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; +} diff --git a/airtime_mvc/public/js/airtime/library/library.js b/airtime_mvc/public/js/airtime/library/library.js index 38a675e81..d4a28373d 100644 --- a/airtime_mvc/public/js/airtime/library/library.js +++ b/airtime_mvc/public/js/airtime/library/library.js @@ -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() { if (window.location.href.indexOf("showbuilder") > -1) { AIRTIME.library.initPodcastDatatable(); @@ -1613,5 +1677,114 @@ $(document).ready(function() { $(window).resize(function() { 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(); + })(); + +});