package com.nerdwaller;
import java.awt.image.BufferedImage;
import java.io.File;
import java.net.MalformedURLException;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
/**
* Search for and download Chromecast backgrounds currently visible on the Chromecast home page.
* Backgrounds can have a gradient applied to them, closely mimicking the Chromecast's standard display.
* Backgrounds can also have a watermark applied to the bottom right corner.
*/
public class Main {
private static int totalDownloads = 0;
/**
* Find, download, and optionally watermark/apply gradient to the chromecast backgrounds.
*
* @param args Are to be provided as command line switches. The switches/params can be:
* * settings - string, path a file to Load the settings from, if provided - other switches are ignored.
* * outdir - string, path to the output directory (where to save the images to).
* * watermark - switch, if provided a watermark will be applied to the images with the author's name.
* * gradient - switch, if provided a gradient will be applied to the image, mimicking the display on a chromecast.
*
* Example:
* java -jar ChromecastBackground.jar -outdir /Users/nerdwaller/chromecastbg/ -watermark -gradient
*/
public static void main(String[] args) {
final Settings settings = loadSettings(args);
System.out.println("Chromecast Backgrounds");
System.out.println("\tSaving to: " + settings.savePath());
System.out.println("\tAdding Gradient: " + settings.applyGradient());
System.out.println("\tApplying Watermark: " + settings.applyWatermark() + "\n");
// Get a list of background currently displayed on the Chromecast's homepage (only ever
// gives 100, but there appear to be well over 500 individual images and growing).
System.out.print("Searching for backgrounds...");
Chromecast cc = null;
try {
cc = new Chromecast();
} catch (MalformedURLException e) {
System.out.println("The Chromecast URL is malformed, they must have moved the page.");
System.exit(1);
}
List<Background> bgs = cc.getAllBackgrounds();
System.out.println(" " + bgs.size() + " found.");
// Create the save path if necessary
File savePath = new File(settings.savePath());
if (!savePath.exists()) {
savePath.mkdirs();
}
boolean foundNew = false;
System.out.println("Checking for new images...");
// Loop through all found backgrounds checking if the image has already been downloaded.
// If not, thread out the download and processing (gradient/watermark if applied) of images.
ExecutorService executor = Executors.newFixedThreadPool(10);
for (final Background bg : bgs) {
final File saveFile = new File(settings.savePath() + bg.getName());
if (!saveFile.exists()) {
foundNew = true;
System.out.println("\tDownloading new image '" + bg.getName() + "'");
Thread t = new Thread(
new Runnable() {
public void run() {
BufferedImage image = Images.downloadImage(bg.getHref());
if (image != null) {
if (settings.applyGradient()) {
image = Images.overlayGradient(image);
}
if (settings.applyWatermark()) {
image = Images.applyWatermark(image, bg.author);
}
if (Images.saveImageAsJpg(image, saveFile.toString(), 1.0f)) {
markDownloaded();
}
}
}
}
);
executor.execute(t);
}
}
executor.shutdown();
while (!executor.isTerminated()) {
// Spin until all threaded items are completed.
}
if (!foundNew) {
System.out.println("No new images found.");
} else {
System.out.println(String.format("Found %s new images.", totalDownloads));
}
System.out.println("Finished.");
}
/**
* Create the options for the Command Line argument parser (apache)
*
* @return Options that can be parsed from the command line argument parser.
*/
private static final Options createOptions() {
Options options = new Options();
Option help = new Option("help", "Print this message");
Option settingsFile = new Option("settings", true, "Load settings from the specified file");
Option outputDirectory = new Option("outdir", true, "Output directory path");
Option applyWatermark = new Option("watermark", false, "Apply the author's name as a watermark");
Option applyGradient = new Option("gradient", false, "Overlay a gradient (attempts to match the Chromecast's display of images)");
options.addOption(help);
options.addOption(settingsFile);
options.addOption(outputDirectory);
options.addOption(applyWatermark);
options.addOption(applyGradient);
return options;
}
/**
* Load the settings based on the arguments provided by the user. If none were provided, the default settings
* will be loaded.
*
* @param args Command line arguments, all are optional: "settings" (string: path to the settings file to load, other args are ignored),
* "outdir" (string: the output/save directory), "watermark" (switch: include the author's name as a watermark), "gradient" (switch:
* apply a gradient to the image, mimick's the chromecast theme).
* @return
*/
private static final Settings loadSettings(final String[] args) {
Settings settings = null;
if (args.length == 0) {
settings = new Settings();
}
else {
try {
Options options = createOptions();
CommandLineParser parser = new BasicParser();
CommandLine cli = parser.parse(options, args);
// Only show the help info
if (cli.hasOption("help")) {
HelpFormatter helpFormatter = new HelpFormatter();
helpFormatter.printHelp("Chromecast-Backgrounds", options);
System.exit(0);
}
// Load from a settings file. If provided, other args are ignored.
else if (cli.hasOption("settings")) {
settings = new Settings(cli.getOptionValue("settings"));
}
// Load from the provided switches.
else {
settings = new Settings(cli.getOptionValue("outdir"), cli.hasOption("watermark"), cli.hasOption("gradient"));
}
}
catch (ParseException e) {
e.printStackTrace();
}
}
return settings;
}
private static void markDownloaded() {
totalDownloads++;
}
}