View Javadoc

1   /***
2    *     Ambient - A music player for the Android platform
3    Copyright (C) 2007 Martin Vysny
4    
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9    
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14  
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17   */
18  
19  package sk.baka.ambient.lrc;
20  
21  import java.io.File;
22  import java.io.FileInputStream;
23  import java.io.IOException;
24  import java.net.URL;
25  import java.text.ParseException;
26  import java.util.List;
27  import java.util.concurrent.ConcurrentHashMap;
28  import java.util.concurrent.ConcurrentMap;
29  
30  import sk.baka.ambient.AmbientApplication;
31  import sk.baka.ambient.collection.TrackMetadataBean;
32  import sk.baka.ambient.commons.AbstractFileStorage;
33  import sk.baka.ambient.library.ILibraryListener;
34  import sk.baka.ambient.lrc.lyrdb.LyrdbTrack;
35  
36  /***
37   * Storage for downloaded LRC files.
38   * 
39   * @author Martin Vysny
40   */
41  public final class LRCStorage extends AbstractFileStorage {
42  
43  	/***
44  	 * Creates new LRC storage.
45  	 */
46  	public LRCStorage() {
47  		super("karaoke", ".lrc");
48  	}
49  
50  	@Override
51  	protected String[] getFilenameAndExt(URL url, Object fetchInfo) {
52  		final TrackMetadataBean track = ((FetchInfo) fetchInfo).track;
53  		return new String[] { track.getAlbum() + "-" + track.getTitle(), ".lrc" };
54  	}
55  
56  	private static class FetchInfo {
57  		/***
58  		 * Fetching lyrics for this tracks.
59  		 */
60  		public TrackMetadataBean track;
61  		/***
62  		 * Possible results are stored here.
63  		 */
64  		public List<LyrdbTrack> lyrics;
65  	}
66  
67  	@Override
68  	protected void onFileDownloaded(URL url, Object fetchInfo,
69  			final boolean success) {
70  		final FetchInfo fi = (FetchInfo) fetchInfo;
71  		AmbientApplication.getInstance().getBus().getInvocator(
72  				ILibraryListener.class, true).lyricsLoaded(fi.track,
73  				success ? null : fi.lyrics);
74  	}
75  
76  	@Override
77  	protected URL toURL(Object fetchInfo) throws IOException {
78  		final FetchInfo fi = (FetchInfo) fetchInfo;
79  		final LyrdbTrack preferred = preferredLyrics.remove(fi.track);
80  		if (preferred != null) {
81  			return preferred.getKaraokeURL();
82  		}
83  		fi.lyrics = LyrdbTrack.search(fi.track, true);
84  		if (fi.lyrics.size() == 1) {
85  			return fi.lyrics.get(0).getKaraokeURL();
86  		}
87  		if (fi.lyrics.isEmpty()) {
88  			fi.lyrics = LyrdbTrack.search(fi.track, false);
89  		}
90  		return null;
91  	}
92  
93  	/***
94  	 * Contains preferred lyrics for given track.
95  	 */
96  	private final ConcurrentMap<TrackMetadataBean, LyrdbTrack> preferredLyrics = new ConcurrentHashMap<TrackMetadataBean, LyrdbTrack>();
97  
98  	/***
99  	 * Sets preferred lyrics for given track. On next lyrics download for this
100 	 * track these lyrics will be downloaded - no search will be performed.
101 	 * 
102 	 * @param track
103 	 *            the track, must not be <code>null</code>.
104 	 * @param lyrics
105 	 *            preferred lyrics, must not be <code>null</code>.
106 	 */
107 	public void setLyricsForTrack(final TrackMetadataBean track,
108 			final LyrdbTrack lyrics) {
109 		preferredLyrics.put(track, lyrics);
110 	}
111 
112 	/***
113 	 * Deletes lyrics for given track.
114 	 * 
115 	 * @param track
116 	 *            the track to delete the lyrics for.
117 	 */
118 	public void deleteLyrics(final TrackMetadataBean track) {
119 		preferredLyrics.remove(track);
120 		final FetchInfo fi = new FetchInfo();
121 		fi.track = track;
122 		final File file = getCacheFileNull(getFilenameAndExt(null, fi)[0]);
123 		if (file != null) {
124 			removeFile(file);
125 		}
126 	}
127 
128 	/***
129 	 * Fetches the lyrics for a track and returns it. If the cover is not
130 	 * present in the cache and we are not offline the lyrics are fetched in a
131 	 * worker thread and
132 	 * {@link ILibraryListener#lyricsLoaded(TrackMetadataBean, List)} is
133 	 * emitted.
134 	 * 
135 	 * @param track
136 	 *            the track.
137 	 * @return lyrics available or <code>null</code> if the lyrics are not yet
138 	 *         available.
139 	 * @throws ParseException
140 	 *             if lyrics parsing failed
141 	 * @throws IOException
142 	 *             if i/o exception occurred.
143 	 */
144 	public LRCLyrics getLyrics(final TrackMetadataBean track)
145 			throws IOException, ParseException {
146 		final FetchInfo fi = new FetchInfo();
147 		fi.track = track;
148 		File file = getCacheFileNull(getFilenameAndExt(null, fi)[0]);
149 		if (file == null) {
150 			final AmbientApplication app = AmbientApplication.getInstance();
151 			final boolean offline = !app.getStateHandler().getStartupState().online;
152 			if (offline) {
153 				return null;
154 			}
155 		}
156 		// we are online. try to fetch the lyrics from the Internet
157 		if (file == null) {
158 			file = getFile(fi);
159 		}
160 		if (file == null) {
161 			return null;
162 		}
163 		return LRCLyrics.parse(new FileInputStream(file));
164 	}
165 }