diff options
Diffstat (limited to 'subsonic-main/src/main/java/net/sourceforge/subsonic/controller/CoverArtController.java')
-rw-r--r-- | subsonic-main/src/main/java/net/sourceforge/subsonic/controller/CoverArtController.java | 294 |
1 files changed, 0 insertions, 294 deletions
diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/CoverArtController.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/CoverArtController.java deleted file mode 100644 index a5093024..00000000 --- a/subsonic-main/src/main/java/net/sourceforge/subsonic/controller/CoverArtController.java +++ /dev/null @@ -1,294 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Subsonic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Subsonic. If not, see <http://www.gnu.org/licenses/>. - - Copyright 2009 (C) Sindre Mehus - */ -package net.sourceforge.subsonic.controller; - -import net.sourceforge.subsonic.Logger; -import net.sourceforge.subsonic.dao.AlbumDao; -import net.sourceforge.subsonic.dao.ArtistDao; -import net.sourceforge.subsonic.domain.Album; -import net.sourceforge.subsonic.domain.Artist; -import net.sourceforge.subsonic.domain.MediaFile; -import net.sourceforge.subsonic.service.MediaFileService; -import net.sourceforge.subsonic.service.SecurityService; -import net.sourceforge.subsonic.service.SettingsService; -import net.sourceforge.subsonic.service.metadata.JaudiotaggerParser; -import net.sourceforge.subsonic.util.FileUtil; -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.springframework.web.bind.ServletRequestUtils; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; -import org.springframework.web.servlet.mvc.LastModified; - -import javax.imageio.ImageIO; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * Controller which produces cover art images. - * - * @author Sindre Mehus - */ -public class CoverArtController implements Controller, LastModified { - - public static final String ALBUM_COVERART_PREFIX = "al-"; - public static final String ARTIST_COVERART_PREFIX = "ar-"; - - private static final Logger LOG = Logger.getLogger(CoverArtController.class); - - private SecurityService securityService; - private MediaFileService mediaFileService; - private ArtistDao artistDao; - private AlbumDao albumDao; - - public long getLastModified(HttpServletRequest request) { - try { - File file = getImageFile(request); - if (file == null) { - return 0; // Request for the default image. - } - if (!FileUtil.exists(file)) { - return -1; - } - - return FileUtil.lastModified(file); - } catch (Exception e) { - return -1; - } - } - - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { - File file = getImageFile(request); - - if (file != null && !FileUtil.exists(file)) { - response.sendError(HttpServletResponse.SC_NOT_FOUND); - return null; - } - - // Check access. - if (file != null && !securityService.isReadAllowed(file)) { - response.sendError(HttpServletResponse.SC_FORBIDDEN); - return null; - } - - // Send default image if no path is given. (No need to cache it, since it will be cached in browser.) - Integer size = ServletRequestUtils.getIntParameter(request, "size"); - if (file == null) { - sendDefault(size, response); - return null; - } - - // Optimize if no scaling is required. - if (size == null) { - sendUnscaled(file, response); - return null; - } - - // Send cached image, creating it if necessary. - try { - File cachedImage = getCachedImage(file, size); - sendImage(cachedImage, response); - } catch (IOException e) { - sendDefault(size, response); - } - - return null; - } - - private File getImageFile(HttpServletRequest request) { - String id = request.getParameter("id"); - if (id != null) { - if (id.startsWith(ALBUM_COVERART_PREFIX)) { - return getAlbumImage(Integer.valueOf(id.replace(ALBUM_COVERART_PREFIX, ""))); - } - if (id.startsWith(ARTIST_COVERART_PREFIX)) { - return getArtistImage(Integer.valueOf(id.replace(ARTIST_COVERART_PREFIX, ""))); - } - return getMediaFileImage(Integer.valueOf(id)); - } - - String path = StringUtils.trimToNull(request.getParameter("path")); - return path != null ? new File(path) : null; - } - - private File getArtistImage(int id) { - Artist artist = artistDao.getArtist(id); - return artist == null || artist.getCoverArtPath() == null ? null : new File(artist.getCoverArtPath()); - } - - private File getAlbumImage(int id) { - Album album = albumDao.getAlbum(id); - return album == null || album.getCoverArtPath() == null ? null : new File(album.getCoverArtPath()); - } - - private File getMediaFileImage(int id) { - MediaFile mediaFile = mediaFileService.getMediaFile(id); - return mediaFile == null ? null : mediaFileService.getCoverArt(mediaFile); - } - - private void sendImage(File file, HttpServletResponse response) throws IOException { - InputStream in = new FileInputStream(file); - try { - IOUtils.copy(in, response.getOutputStream()); - } finally { - IOUtils.closeQuietly(in); - } - } - - private void sendDefault(Integer size, HttpServletResponse response) throws IOException { - InputStream in = null; - try { - in = getClass().getResourceAsStream("default_cover.jpg"); - BufferedImage image = ImageIO.read(in); - if (size != null) { - image = scale(image, size, size); - } - ImageIO.write(image, "jpeg", response.getOutputStream()); - } finally { - IOUtils.closeQuietly(in); - } - } - - private void sendUnscaled(File file, HttpServletResponse response) throws IOException { - InputStream in = null; - try { - in = getImageInputStream(file); - IOUtils.copy(in, response.getOutputStream()); - } finally { - IOUtils.closeQuietly(in); - } - } - - private File getCachedImage(File file, int size) throws IOException { - String md5 = DigestUtils.md5Hex(file.getPath()); - File cachedImage = new File(getImageCacheDirectory(size), md5 + ".jpeg"); - - // Is cache missing or obsolete? - if (!cachedImage.exists() || FileUtil.lastModified(file) > cachedImage.lastModified()) { - InputStream in = null; - OutputStream out = null; - try { - in = getImageInputStream(file); - out = new FileOutputStream(cachedImage); - BufferedImage image = ImageIO.read(in); - if (image == null) { - throw new Exception("Unable to decode image."); - } - - image = scale(image, size, size); - ImageIO.write(image, "jpeg", out); - - } catch (Throwable x) { - // Delete corrupt (probably empty) thumbnail cache. - LOG.warn("Failed to create thumbnail for " + file, x); - IOUtils.closeQuietly(out); - cachedImage.delete(); - throw new IOException("Failed to create thumbnail for " + file + ". " + x.getMessage()); - - } finally { - IOUtils.closeQuietly(in); - IOUtils.closeQuietly(out); - } - } - return cachedImage; - } - - /** - * Returns an input stream to the image in the given file. If the file is an audio file, - * the embedded album art is returned. - */ - private InputStream getImageInputStream(File file) throws IOException { - JaudiotaggerParser parser = new JaudiotaggerParser(); - if (parser.isApplicable(file)) { - MediaFile mediaFile = mediaFileService.getMediaFile(file); - return new ByteArrayInputStream(parser.getImageData(mediaFile)); - } else { - return new FileInputStream(file); - } - } - - private synchronized File getImageCacheDirectory(int size) { - File dir = new File(SettingsService.getSubsonicHome(), "thumbs"); - dir = new File(dir, String.valueOf(size)); - if (!dir.exists()) { - if (dir.mkdirs()) { - LOG.info("Created thumbnail cache " + dir); - } else { - LOG.error("Failed to create thumbnail cache " + dir); - } - } - - return dir; - } - - public static BufferedImage scale(BufferedImage image, int width, int height) { - int w = image.getWidth(); - int h = image.getHeight(); - BufferedImage thumb = image; - - // For optimal results, use step by step bilinear resampling - halfing the size at each step. - do { - w /= 2; - h /= 2; - if (w < width) { - w = width; - } - if (h < height) { - h = height; - } - - BufferedImage temp = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); - Graphics2D g2 = temp.createGraphics(); - g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, - RenderingHints.VALUE_INTERPOLATION_BILINEAR); - g2.drawImage(thumb, 0, 0, temp.getWidth(), temp.getHeight(), null); - g2.dispose(); - - thumb = temp; - } while (w != width); - - return thumb; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public void setMediaFileService(MediaFileService mediaFileService) { - this.mediaFileService = mediaFileService; - } - - public void setArtistDao(ArtistDao artistDao) { - this.artistDao = artistDao; - } - - public void setAlbumDao(AlbumDao albumDao) { - this.albumDao = albumDao; - } -} |