001/* 002 * Copyright (c) 2012, the Last.fm Java Project and Committers 003 * All rights reserved. 004 * 005 * Redistribution and use of this software in source and binary forms, with or without modification, are 006 * permitted provided that the following conditions are met: 007 * 008 * - Redistributions of source code must retain the above 009 * copyright notice, this list of conditions and the 010 * following disclaimer. 011 * 012 * - Redistributions in binary form must reproduce the above 013 * copyright notice, this list of conditions and the 014 * following disclaimer in the documentation and/or other 015 * materials provided with the distribution. 016 * 017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 018 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 019 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 020 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 021 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 023 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 024 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 025 */ 026 027package de.umass.lastfm; 028 029import de.umass.xml.DomElement; 030 031import java.util.ArrayList; 032import java.util.List; 033 034/** 035 * Bean for music playlists. Contains the {@link #fetch(String, String) fetch} method and various <code>fetchXXX</code> 036 * methods to retrieve playlists from the server. Playlists are identified by lastfm:// playlist urls. Valid urls 037 * include: 038 * <ul> 039 * <li><b>Album Playlists:</b> lastfm://playlist/album/{@literal <album_id>}</li> 040 * <li><b>User Playlists:</b> lastfm://playlist/{@literal <playlist_id>}</li> 041 * <li><b>Tag Playlists:</b> lastfm://playlist/tag/{@literal <tag_name>}/freetracks</li> 042 * </ul> 043 * See <a href="https://www.last.fm/api/playlists">https://www.last.fm/api/playlists</a> for more information about playlists. 044 * 045 * @author Janni Kovacs 046 */ 047public class Playlist { 048 049 static final ItemFactory<Playlist> FACTORY = new PlaylistFactory(); 050 051 private int id; 052 private String title; 053 private String annotation; 054 private int size; 055 private String creator; 056 057 private List<Track> tracks = new ArrayList<Track>(); 058 059 private Playlist() { 060 } 061 062 public String getCreator() { 063 return creator; 064 } 065 066 public int getId() { 067 return id; 068 } 069 070 public int getSize() { 071 return size; 072 } 073 074 public String getTitle() { 075 return title; 076 } 077 078 public String getAnnotation() { 079 return annotation; 080 } 081 082 public List<Track> getTracks() { 083 return tracks; 084 } 085 086 /** 087 * Fetches an album playlist, which contains the tracks of the specified album. 088 * 089 * @param albumId The album id as returned in {@link Album#getInfo(String, String, String) Album.getInfo}. 090 * @param apiKey A Last.fm API key. 091 * @return a playlist 092 */ 093 public static Playlist fetchAlbumPlaylist(String albumId, String apiKey) { 094 return fetch("lastfm://playlist/album/" + albumId, apiKey); 095 } 096 097 /** 098 * Fetches a user-created playlist. 099 * 100 * @param playlistId A playlist id. 101 * @param apiKey A Last.fm API key. 102 * @return a playlist 103 */ 104 public static Playlist fetchUserPlaylist(int playlistId, String apiKey) { 105 return fetch("lastfm://playlist/" + playlistId, apiKey); 106 } 107 108 /** 109 * Fetches a playlist of freetracks for a given tag name. 110 * 111 * @param tag A tag name. 112 * @param apiKey A Last.fm API key. 113 * @return a playlist 114 */ 115 public static Playlist fetchTagPlaylist(String tag, String apiKey) { 116 return fetch("lastfm://playlist/tag/" + tag + "/freetracks", apiKey); 117 } 118 119 /** 120 * Fetches a playlist using a lastfm playlist url. See the class description for a list of valid 121 * playlist urls. 122 * 123 * @param playlistUrl A valid playlist url. 124 * @param apiKey A Last.fm API key. 125 * @return a playlist 126 */ 127 public static Playlist fetch(String playlistUrl, String apiKey) { 128 Result result = Caller.getInstance().call("playlist.fetch", apiKey, "playlistURL", playlistUrl); 129 return ResponseBuilder.buildItem(result, Playlist.class); 130 } 131 132 /** 133 * Add a track to a Last.fm user's playlist. 134 * 135 * @param playlistId The ID of the playlist - this is available in user.getPlaylists 136 * @param artist The artist name that corresponds to the track to be added. 137 * @param track The track name to add to the playlist. 138 * @param session A Session instance. 139 * @return the result of the operation 140 */ 141 public static Result addTrack(int playlistId, String artist, String track, Session session) { 142 return Caller.getInstance() 143 .call("playlist.addTrack", session, "playlistID", String.valueOf(playlistId), "artist", artist, "track", 144 track); 145 } 146 147 /** 148 * Creates a Last.fm playlist. 149 * 150 * @param title A title for the playlist 151 * @param description A description for the playlist 152 * @param session A Session instance 153 * @return the result of the operation 154 */ 155 public static Playlist create(String title, String description, Session session) { 156 Result result = Caller.getInstance().call("playlist.create", session, "title", title, "description", description); 157 if (!result.isSuccessful()) 158 return null; 159 return ResponseBuilder.buildItem(result.getContentElement().getChild("playlist"), Playlist.class); 160 } 161 162 private static class PlaylistFactory implements ItemFactory<Playlist> { 163 public Playlist createItemFromElement(DomElement element) { 164 Playlist playlist = new Playlist(); 165 166 if (element.hasChild("id")) 167 playlist.id = Integer.parseInt(element.getChildText("id")); 168 169 playlist.title = element.getChildText("title"); 170 171 if (element.hasChild("size")) 172 playlist.size = Integer.parseInt(element.getChildText("size")); 173 174 playlist.creator = element.getChildText("creator"); 175 playlist.annotation = element.getChildText("annotation"); 176 177 DomElement trackList = element.getChild("trackList"); 178 if (trackList != null) { 179 for (DomElement te : trackList.getChildren("track")) { 180 Track t = new Track(te.getChildText("title"), te.getChildText("identifier"), te.getChildText("creator")); 181 t.album = te.getChildText("album"); 182 t.duration = Integer.parseInt(te.getChildText("duration")) / 1000; 183 t.imageUrls.put(ImageSize.LARGE, te.getChildText("image")); 184 t.imageUrls.put(ImageSize.ORIGINAL, te.getChildText("image")); 185 t.location = te.getChildText("location"); 186 for (DomElement ext : te.getChildren("extension")) { 187 if ("http://www.last.fm".equals(ext.getAttribute("application"))) { 188 for (DomElement child : ext.getChildren()) { 189 t.lastFmExtensionInfos.put(child.getTagName(), child.getText()); 190 } 191 } 192 } 193 playlist.tracks.add(t); 194 } 195 196 if (playlist.size == 0) 197 playlist.size = playlist.tracks.size(); 198 } 199 200 return playlist; 201 } 202 } 203}