/* You may freely copy, distribute, modify and use this class as long as the original author attribution remains intact. See message below. Copyright (C) 2003 Christian Pesch. All Rights Reserved. */ package slash.metamusic.coverdb; import slash.metamusic.util.DiscIndexHelper; import slash.metamusic.util.InputOutput; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.logging.Logger; import static slash.metamusic.util.StringHelper.replaceForURI; import static slash.metamusic.util.StringHelper.toMixedCase; /** * A client that queries cover databases. * * @author Christian Pesch */ public class CoverDBClient { /** * Logging output */ protected static final Logger log = Logger.getLogger(CoverDBClient.class.getName()); private static final String VARIOUS_ARTISTS = "various artists"; private CoverDBCache coverDBCache = new CoverDBCache(); public void setCoverDirectoryName(String coverDirectoryName) { coverDBCache.setCacheDirectoryName(coverDirectoryName); } public File getCachedFile(String artist, String track) { try { return coverDBCache.getCachedFile(artist, track); } catch (IOException e) { log.severe("Cannot get cached cover for artist '" + artist + "' and track '" + track + "': " + e.getMessage()); } return null; } protected byte[] fetchPortrait(String artist, boolean download) { if (artist == null) return null; artist = artist.trim(); byte[] portrait = null; try { portrait = coverDBCache.peekPortrait(artist); if (portrait != null) { log.info("Portrait for artist '" + artist + "' is cached"); } else if (download) { portrait = downloadPortrait(artist); if (portrait != null) storePortrait(artist, portrait); } } catch (IOException e) { log.severe("Cannot fetch portrait for '" + artist + "': " + e.getMessage()); } return portrait; } public byte[] fetchPortrait(String artist) { return fetchPortrait(artist, true); } public void storePortrait(String artist, byte[] portrait) { log.fine("Storing portrait (" + portrait.length + " bytes) for artist '" + artist + "'"); try { coverDBCache.storePortrait(artist, portrait); } catch (IOException e) { log.severe("Cannot store portrait for artist '" + artist + "': " + e.getMessage()); } } protected byte[] fetchCover(String artist, String album, boolean download) { if (artist == null || album == null) return null; artist = artist.trim(); album = DiscIndexHelper.removeDiscIndexPostfix(album); album = album.trim(); byte[] cover = null; try { cover = coverDBCache.peekCover(artist, album); if (cover != null) log.info("Cover for artist '" + artist + "' and album '" + album + "' (" + cover.length + " bytes) is cached"); else if (download) { cover = downloadCover(artist, album); if (cover != null) storeAlbumCover(artist, album, cover); } } catch (IOException e) { log.severe("Cannot fetch cover for artist '" + artist + "' and album '" + album + "': " + e.getMessage()); } return cover; } protected void storeCover(String artist, String album, byte[] cover) { album = DiscIndexHelper.removeDiscIndexPostfix(album); log.fine("Storing cover (" + cover.length + " bytes) for artist '" + artist + "' and album '" + album + "'"); try { coverDBCache.storeCover(artist, album, cover); } catch (IOException e) { log.severe("Cannot store cover for artist '" + artist + "' and album '" + album + "': " + e.getMessage()); } } public byte[] fetchAlbumCover(String artist, String album) { return fetchCover(artist, album, true); } public void storeAlbumCover(String artist, String album, byte[] cover) { storeCover(artist, album, cover); } public byte[] fetchCompilationCover(String compilation) { return fetchCover(VARIOUS_ARTISTS, compilation, true); } public void storeCompilationCover(String compilation, byte[] cover) { storeCover(VARIOUS_ARTISTS, compilation, cover); } protected byte[] downloadPortrait(String artist) { // TODO this is not very successful for portraits, try google image search instead return downloadCover(artist, artist); } protected byte[] downloadCover(String artist, String album) { if (artist == null || artist.length() == 0 || artist.toLowerCase().contains("unknown") || album == null || album.length() == 0 || album.toLowerCase().contains("unknown")) { log.severe("Cannot download cover for unknown artist '" + artist + "' or unknown album '" + album + "'"); return null; } if (coverDBCache.hasDownloadAlreadyFailed(artist, album)) { log.fine("Cover download already failed for artist '" + artist + "' and album '" + album + "'"); return null; } byte[] cover = null; try { AmazonMusicClient client = new AmazonMusicClient(); cover = client.downloadCover(artist, album); /* http://img.darktown.com/cover/audio/download/f/fury_in_the_slaughterhouse_-_jau_a.jpg http://vince8290.free.fr/pochettes/audio/santana_supernatural_front.jpg http://covers.coverkingdom.net/covers_audio/N/N_Sync_-_No_Strings_Attached_(Cd).jpg hrtp://www.cdpochettes.net/audio/d/Dire_staits_Alchemy_1.jpg http://www.cdpochettes.net/audio/d/Depeche_mode_singles_86_98_1.jpg http://www.cdpochettes.net/audio/e/Ema_burton_a_girl_like_me_1.jpg http://www.babilomnia.it/Cover/S/Santana-Supernatural-Front.jpg http://www.babilomnia.it/Cover/B/BackStreet_Boys_Millenium_front.jpg http://cdcovers.iespana.es/cdcovers/CoversA/AC_DC-HighWay_To_Hell-Front.jpg http://www.fredo-covers.com/jaquettes/audio/cher_heart_of_stone_avant.jpg does not work anymore, service stopped */ // http://www.coveralia.com/audio/a/Atomic_Kitten-Feels_So_Good-Frontal.jpg if (cover == null) { char artistChar = Character.toLowerCase(artist.charAt(0)); cover = downloadCover(new URL("http://www.coveralia.com/audio/" + artistChar + "/" + toMixedCase(replaceForURI(artist)) + "-" + toMixedCase(replaceForURI(album)) + "-Frontal.jpg"), artist, album); } // http://coverlandia.altervista.org/Copertine%20cd/D/Depeche_Mode_Ultra.jpg if (cover == null) { char artistChar = Character.toUpperCase(artist.charAt(0)); cover = downloadCover(new URL("http://coverlandia.altervista.org/Copertine%20cd/" + artistChar + "/" + toMixedCase(replaceForURI(artist)) + "_" + toMixedCase(replaceForURI(album)) + ".jpg"), artist, album); } // http://coverlandia.altervista.org/Copertine%20cd/D/Doors_-_Greatest_hits.jpg if (cover == null) { char artistChar = Character.toUpperCase(artist.charAt(0)); cover = downloadCover(new URL("http://coverlandia.altervista.org/Copertine%20cd/" + artistChar + "/" + toMixedCase(replaceForURI(artist)) + "_-_" + toMixedCase(replaceForURI(album)) + ".jpg"), artist, album); } // http://coverlandia.altervista.org/Copertine%20cd/D/def_leppard_-_euphoria.JPG if (cover == null) { char artistChar = Character.toUpperCase(artist.charAt(0)); cover = downloadCover(new URL("http://coverlandia.altervista.org/Copertine%20cd/" + artistChar + "/" + replaceForURI(artist).toLowerCase() + "_-_" + replaceForURI(album).toLowerCase() + ".JPG"), artist, album); } } catch (MalformedURLException e) { log.severe("Could not create url for artist " + artist + " and album " + album + ":" + e.getMessage()); } if (cover == null) { log.fine("Cover download failed for artist '" + artist + "' and album '" + album + "'"); coverDBCache.addFailedDownload(artist, album); } return cover; } protected byte[] downloadCover(URL url, String artist, String album) { log.info("Trying url " + url + " for artist '" + artist + "' and album '" + album + "'"); try { URLConnection connection = url.openConnection(); connection.connect(); InputStream in = connection.getInputStream(); byte[] result = InputOutput.readBytes(in); if (result == null || result.length == 0 || isHtmlErrorPage(result)) { log.warning("Download from url " + url + " failed"); } else { log.info("Download from url " + url + " successfull (" + result.length + " bytes)"); return result; } } catch (IOException e) { log.severe("Could not load cover for artist '" + artist + "' and album '" + album + "': " + e.getMessage()); } return null; } private boolean isHtmlErrorPage(byte[] bytes) throws IOException { BufferedReader reader = null; try { reader = new BufferedReader(new StringReader(new String(bytes))); String data; while ((data = reader.readLine()) != null) { if (data.toLowerCase().contains("html>")) return true; if (data.toLowerCase().contains("head>")) return true; if (data.toLowerCase().contains("meta>")) return true; if (data.toLowerCase().contains("title>")) return true; if (data.toLowerCase().contains("body>")) return true; if (data.toLowerCase().contains("HTTP")) return true; } } finally { if (reader != null) { try { reader.close(); } catch (IOException ioe) { // do nothing... } } } return false; } public static void main(String[] args) throws Exception { if (args.length != 2) { System.out.println("slash.metamusic.coverdb.CoverDBClient <artist> <album>"); System.exit(1); } CoverDBClient client = new CoverDBClient(); client.fetchAlbumCover(args[0], args[1]); System.exit(0); } }