com.moviejukebox.scanner.artwork.VideoImageScanner Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of yamj Show documentation
Show all versions of yamj Show documentation
Static analysis of MovieJukebox project
The newest version!
/*
* Copyright (c) 2004-2013 YAMJ Members
* http://code.google.com/p/moviejukebox/people/list
*
* This file is part of the Yet Another Movie Jukebox (YAMJ).
*
* The YAMJ 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
* any later version.
*
* YAMJ 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 the YAMJ. If not, see .
*
* Web: http://code.google.com/p/moviejukebox/
*
*/
package com.moviejukebox.scanner.artwork;
import com.moviejukebox.model.DirtyFlag;
import com.moviejukebox.model.Jukebox;
import com.moviejukebox.model.Movie;
import com.moviejukebox.model.MovieFile;
import com.moviejukebox.plugin.MovieImagePlugin;
import com.moviejukebox.scanner.AttachmentScanner;
import com.moviejukebox.tools.FileTools;
import com.moviejukebox.tools.GraphicTools;
import com.moviejukebox.tools.PropertiesUtil;
import com.moviejukebox.tools.SkinProperties;
import com.moviejukebox.tools.StringTools;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.StringTokenizer;
import org.apache.log4j.Logger;
/**
* Scanner for video image files in local directory
*
* @author Stuart.Boston
* @version 1.0, 25th August 2009 - Initial code copied from FanartScanner.java
*
*/
public class VideoImageScanner {
private static final Logger LOG = Logger.getLogger(VideoImageScanner.class);
private static final String LOG_MESSAGE = "VideoImageScanner: ";
private static String skinHome = SkinProperties.getSkinHome();
private static final Collection videoimageExtensions = new ArrayList();
private static String videoimageToken;
private static boolean videoimageOverwrite;
static {
// We get valid extensions
StringTokenizer st = new StringTokenizer(PropertiesUtil.getProperty("videoimage.scanner.videoimageExtensions", "jpg,jpeg,gif,bmp,png"), ",;| ");
while (st.hasMoreTokens()) {
videoimageExtensions.add(st.nextToken());
}
videoimageToken = PropertiesUtil.getProperty("mjb.scanner.videoimageToken", ".videoimage");
videoimageOverwrite = PropertiesUtil.getBooleanProperty("mjb.forceVideoImagesOverwrite", Boolean.FALSE);
}
private VideoImageScanner() {
throw new UnsupportedOperationException("Class cannot be instantiated");
}
/**
* Try to locate a local video image and if that fails, download the image from the Internet.
*
* @param imagePlugin
* @param jukeboxDetailsRoot
* @param tempJukeboxDetailsRoot
* @param movie
*/
public static void scan(MovieImagePlugin imagePlugin, Jukebox jukebox, Movie movie) {
// Check to see if this is a TV show.
if (!movie.isTVShow()) {
return;
}
String genericVideoImageFilename;
File genericVideoImageFile;
String localVideoImageBaseFilename;
File localVideoImageFile = null;
String fullVideoImageFilename;
String videoimageExtension = null;
String originalFullVideoImageFilename;
boolean foundLocalVideoImage;
boolean localOverwrite;
int firstPart, lastPart;
LOG.debug(LOG_MESSAGE + "Checking for videoimages for " + movie.getTitle() + " [Season " + movie.getSeason() + "]");
// Check for the generic video image for use in the loop later.
localVideoImageBaseFilename = FileTools.getParentFolder(movie.getFile());
localVideoImageBaseFilename = localVideoImageBaseFilename.substring(localVideoImageBaseFilename.lastIndexOf(File.separator) + 1);
genericVideoImageFilename = movie.getFile().getParent() + File.separator + localVideoImageBaseFilename + videoimageToken;
// Look for the various versions of the file with different image extensions
genericVideoImageFile = FileTools.findFileFromExtensions(genericVideoImageFilename, videoimageExtensions);
if (genericVideoImageFile.exists()) {
genericVideoImageFilename = genericVideoImageFile.getAbsolutePath();
} else {
genericVideoImageFilename = null;
}
// Now we look through all the movie files to locate a local video image
for (MovieFile mf : movie.getFiles()) {
firstPart = mf.getFirstPart(); // The first part of the moviefile
lastPart = mf.getLastPart(); // The last part of the moviefile
// Check to see if the file is null, this might be the case if the file is in the middle of a series
if (mf.getFile() == null) {
LOG.debug(LOG_MESSAGE + "Missing file - " + mf.getFilename());
continue;
}
// Loop round each of the parts looking for the video_name.videoimageToken.Extension
for (int part = firstPart; part <= lastPart; part++) {
foundLocalVideoImage = false; // Reset the "found" variable
String partSuffix = "_" + (part - firstPart + 1);
if (mf.getFile().isDirectory()) {
localVideoImageBaseFilename = mf.getFile().getPath();
localVideoImageBaseFilename = localVideoImageBaseFilename.substring(localVideoImageBaseFilename.lastIndexOf(File.separator) + 1) + videoimageToken;
} else if (mf.getFile().getParent().contains("BDMV" + File.separator + "STREAM")) {
localVideoImageBaseFilename = mf.getFile().getPath();
localVideoImageBaseFilename = localVideoImageBaseFilename.substring(0, localVideoImageBaseFilename.indexOf("BDMV" + File.separator + "STREAM") - 1);
localVideoImageBaseFilename = localVideoImageBaseFilename.substring(localVideoImageBaseFilename.lastIndexOf(File.separator) + 1) + videoimageToken;
} else {
localVideoImageBaseFilename = mf.getFile().getName();
localVideoImageBaseFilename = localVideoImageBaseFilename.substring(0, localVideoImageBaseFilename.lastIndexOf(".")) + videoimageToken;
}
fullVideoImageFilename = FileTools.getParentFolder(mf.getFile()) + File.separator + localVideoImageBaseFilename;
originalFullVideoImageFilename = fullVideoImageFilename;
// Check for the videoimage filename with the suffix
if (firstPart < lastPart) {
String suffixFullVideoImageFilename = originalFullVideoImageFilename + partSuffix;
// Check for the videoimage filename with the "_part" suffix
localVideoImageFile = FileTools.findFileFromExtensions(suffixFullVideoImageFilename, videoimageExtensions);
if (localVideoImageFile.exists()) {
LOG.debug(LOG_MESSAGE + "File " + localVideoImageFile.getName() + " found");
foundLocalVideoImage = true;
fullVideoImageFilename = localVideoImageFile.getAbsolutePath();
mf.setVideoImageFilename(part, localVideoImageFile.getName());
}
}
// If the wasn't a specific "videoimage_{part}" then look for a more generic videoimage filename
if (!foundLocalVideoImage) {
// Check for the videoimage filename without the "_part" suffix
localVideoImageFile = FileTools.findFileFromExtensions(fullVideoImageFilename, videoimageExtensions);
if (localVideoImageFile.exists()) {
LOG.debug(LOG_MESSAGE + "File " + localVideoImageFile.getName() + " found");
foundLocalVideoImage = true;
fullVideoImageFilename = localVideoImageFile.getAbsolutePath();
mf.setVideoImageFilename(part, localVideoImageFile.getName());
}
}
// Check file attachments
if (!foundLocalVideoImage) {
localVideoImageFile = AttachmentScanner.extractAttachedVideoimage(movie, part);
if (localVideoImageFile != null) {
foundLocalVideoImage = true;
fullVideoImageFilename = localVideoImageFile.getAbsolutePath();
// need to create the commonly used local video image file name
String extension = "." + FileTools.getFileExtension(fullVideoImageFilename);
String attachedImageFilename = localVideoImageBaseFilename;
if (firstPart < lastPart) {
attachedImageFilename += partSuffix + extension;
} else {
attachedImageFilename += extension;
}
mf.setVideoImageFilename(part, attachedImageFilename);
}
}
// If we don't have a filename, then fill it in here.
if (StringTools.isNotValidString(mf.getVideoImageFilename(part))) {
LOG.debug(LOG_MESSAGE + "No valid filename was found for part " + part);
if (videoimageExtension == null) {
videoimageExtension = "." + PropertiesUtil.getProperty("videoimages.format", "jpg");
}
if (firstPart < lastPart) {
localVideoImageBaseFilename += partSuffix + videoimageExtension;
} else {
localVideoImageBaseFilename += videoimageExtension;
}
// This is the YAMJ generated filename.
mf.setVideoImageFilename(part, localVideoImageBaseFilename);
}
// If we haven't found a local image, but a generic image exists, use that now.
if (!foundLocalVideoImage && genericVideoImageFilename != null) {
LOG.debug(LOG_MESSAGE + "Generic Video Image used from " + genericVideoImageFilename);
// Copy the generic filename over.
fullVideoImageFilename = genericVideoImageFilename;
foundLocalVideoImage = true;
}
// If we've found the VideoImage, copy it to the jukebox, otherwise download it.
if (foundLocalVideoImage) {
LOG.debug(LOG_MESSAGE + "Found local file: " + fullVideoImageFilename);
// Check to see if the URL is UNKNOWN and the local file is found, in which case
// the videoimage in the jukebox should be overwritten with this file
localOverwrite = false; // first reset the check variable
if (StringTools.isNotValidString(mf.getVideoImageURL(part))) {
localOverwrite = true; // Means the file will be overwritten regardless of any other checks
}
// Derive the URL to the local file
if (StringTools.isNotValidString(mf.getVideoImageURL(part))) {
// This occurs when there isn't a videoimage URL in the XML
if (localVideoImageFile != null) {
// holds the old file name cause setVideoImageURL overrides videoImageFileName
String oldVideoImageFilename = mf.getVideoImageFilename(part);
mf.setVideoImageURL(part, localVideoImageFile.toURI().toString());
mf.setVideoImageFilename(part, oldVideoImageFilename);
} else {
mf.setVideoImageURL(part, new File(genericVideoImageFilename).toURI().toString());
mf.setVideoImageFilename(part, genericVideoImageFilename);
}
}
// String videoimageFilename = FileTools.makeSafeFilename(mf.getVideoImageFilename(part));
String videoimageFilename = mf.getVideoImageFilename(part);
String finalDestinationFileName = StringTools.appendToPath(jukebox.getJukeboxRootLocationDetails(), videoimageFilename);
String tmpDestFilename = StringTools.appendToPath(jukebox.getJukeboxTempLocationDetails(), videoimageFilename);
// Add the filename to the safe list
FileTools.addJukeboxFile(videoimageFilename);
File tmpDestFile = new File(tmpDestFilename);
File finalDestinationFile = new File(finalDestinationFileName);
File fullVideoImageFile = new File(fullVideoImageFilename);
// Local VideoImage is newer OR ForceVideoImageOverwrite OR DirtyVideoImage
// Can't check the file size because the jukebox videoimage may have been re-sized
// This may mean that the local art is different to the jukebox art even if the local file date is newer
// Also check for DIRTY_WATCHED to see if we need to redo the image for the watched flag
if (FileTools.isNewer(fullVideoImageFile, finalDestinationFile)
|| videoimageOverwrite
|| localOverwrite
|| movie.isDirty(DirtyFlag.RECHECK)
|| movie.isDirty(DirtyFlag.WATCHED)) {
if (processImage(imagePlugin, movie, fullVideoImageFilename, tmpDestFilename, part)) {
LOG.debug(LOG_MESSAGE + fullVideoImageFile.getName() + " has been copied to " + tmpDestFilename);
} else {
// Processing failed, so try backup image
LOG.debug(LOG_MESSAGE + "Failed loading videoimage : " + fullVideoImageFilename);
// Copy the dummy videoimage to the temp folder
FileTools.copyFile(new File(skinHome + File.separator + "resources" + File.separator + "dummy_videoimage.jpg"), tmpDestFile);
// Process the dummy videoimage in the temp folder
if (processImage(imagePlugin, movie, tmpDestFilename, tmpDestFilename, part)) {
LOG.debug(LOG_MESSAGE + "Using default videoimage");
mf.setVideoImageURL(part, Movie.UNKNOWN); // So we know this is a dummy videoimage
} else {
LOG.debug(LOG_MESSAGE + "Failed loading default videoimage");
// Copying the default image failed, so leave everything blank
mf.setVideoImageFilename(part, Movie.UNKNOWN);
mf.setVideoImageURL(part, Movie.UNKNOWN);
}
}
} else {
LOG.debug(LOG_MESSAGE + finalDestinationFileName + " already exists");
}
} else {
// logger.debug("VideoImageScanner : No local VideoImage found for " + movie.getBaseName() + " attempting to download");
downloadVideoImage(imagePlugin, jukebox, movie, mf, part);
}
}
}
}
/**
* Try to load, process and save the image file
*
* @param imagePlugin The image plugin to use
* @param imageFilename The filename of the image to process
* @param movie The movie that the image relates to
* @return True if the image was successfully processed, false otherwise
*/
private static boolean processImage(MovieImagePlugin imagePlugin, Movie movie, String imageFilename, String targetFilename, int part) {
boolean imageOK = true;
try {
BufferedImage videoimageImage = GraphicTools.loadJPEGImage(imageFilename);
if (videoimageImage != null) {
videoimageImage = imagePlugin.generate(movie, videoimageImage, "videoimages" + Integer.toString(part), null);
GraphicTools.saveImageToDisk(videoimageImage, targetFilename);
} else {
imageOK = false;
}
} catch (Exception error) {
imageOK = false;
}
return imageOK;
}
/**
* Download the videoimage from the URL. Initially this is populated from TheTVDB plugin
*
* @param imagePlugin
* @param jukeboxDetailsRoot
* @param tempJukeboxDetailsRoot
* @param movie
*/
private static void downloadVideoImage(MovieImagePlugin imagePlugin, Jukebox jukebox, Movie movie, MovieFile mf, int part) {
if (StringTools.isValidString(mf.getVideoImageURL(part))) {
// String safeVideoImageFilename = FileTools.makeSafeFilename(mf.getVideoImageFilename(part));
String safeVideoImageFilename = mf.getVideoImageFilename(part);
String videoimageFilename = StringTools.appendToPath(jukebox.getJukeboxRootLocationDetails(), safeVideoImageFilename);
File videoimageFile = FileTools.fileCache.getFile(videoimageFilename);
String tmpDestFilename = StringTools.appendToPath(jukebox.getJukeboxTempLocationDetails(), safeVideoImageFilename);
File tmpDestFile = new File(tmpDestFilename);
boolean fileOK = true;
// Add file to safe list
FileTools.addJukeboxFile(safeVideoImageFilename);
// Do not overwrite existing videoimage unless ForceVideoImageOverwrite = true
if ((!videoimageFile.exists() && !tmpDestFile.exists())
|| videoimageOverwrite
|| movie.isDirty(DirtyFlag.RECHECK)
|| movie.isDirty(DirtyFlag.NFO)
|| movie.isDirty(DirtyFlag.WATCHED)) {
FileTools.makeDirectories(videoimageFile);
// Download the videoimage using the proxy save downloadImage
try {
FileTools.downloadImage(tmpDestFile, mf.getVideoImageURL(part));
} catch (Exception error) {
LOG.debug(LOG_MESSAGE + "Failed to download videoimage : " + mf.getVideoImageURL(part) + " error: " + error.getMessage());
fileOK = false;
}
if (fileOK && processImage(imagePlugin, movie, tmpDestFilename, tmpDestFilename, part)) {
LOG.debug(LOG_MESSAGE + "Downloaded videoimage for " + mf.getVideoImageFilename(part) + " to " + tmpDestFilename);
} else {
// failed use dummy
FileTools.copyFile(new File(skinHome + File.separator + "resources" + File.separator + "dummy_videoimage.jpg"), tmpDestFile);
if (processImage(imagePlugin, movie, tmpDestFilename, tmpDestFilename, part)) {
LOG.debug(LOG_MESSAGE + "Using default videoimage");
mf.setVideoImageURL(part, Movie.UNKNOWN); // So we know this is a dummy videoimage
mf.setVideoImageFilename(part, safeVideoImageFilename); // See MovieFile.java: setVideoImageURL sets setVideoImageFilename=UNKNOWN !!??
} else {
// Copying the default image failed, so leave everything blank
LOG.debug(LOG_MESSAGE + "Failed loading default videoimage");
mf.setVideoImageFilename(part, Movie.UNKNOWN);
mf.setVideoImageURL(part, Movie.UNKNOWN);
}
}
} else {
LOG.debug(LOG_MESSAGE + "VideoImage exists for " + mf.getVideoImageFilename(part));
}
}
}
}