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
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 }