Changeset 93
- Timestamp:
- 01/03/08 00:49:25 (11 months ago)
- Files:
-
- trunk/src/main/org/lastpod/ModelImpl.java (modified) (2 diffs)
- trunk/src/main/org/lastpod/action/DeletePlayCounts.java (modified) (2 diffs)
- trunk/src/main/org/lastpod/parser/ItunesDbParser.java (modified) (7 diffs)
- trunk/src/main/org/lastpod/parser/ItunesStatsParser.java (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/src/main/org/lastpod/ModelImpl.java
r90 r93 24 24 import org.lastpod.parser.TrackItemParser; 25 25 26 import org.lastpod.util.ItunesStatsFilter;27 26 import org.lastpod.util.MiscUtilities; 28 29 import java.io.File;30 27 31 28 import java.util.ArrayList; … … 101 98 History.getInstance(iTunesPath); 102 99 100 boolean isShuffle = ItunesStatsParser.isIpodShuffle(iTunesPath); 101 103 102 ItunesDbParser itunesDbParser = 104 new ItunesDbParser(iTunesPath, parseVariousArtists, splitVariousArtistStrings); 105 106 /* Defaults to the parser for non-shuffle iPods. */ 107 TrackItemParser playCountsParser = new PlayCountsParser(iTunesPath, parseMultiPlayTracks); 108 109 /* Checks for the "iTunesStats" file. If it exists, switch to the iPod 110 * shuffle parser. */ 111 File file = new File(iTunesPath); 112 File[] itunesStatsFiles = file.listFiles(new ItunesStatsFilter()); 113 114 if ((itunesStatsFiles != null) && (itunesStatsFiles.length != 0)) { 103 new ItunesDbParser(iTunesPath, parseVariousArtists, splitVariousArtistStrings, isShuffle); 104 105 TrackItemParser playCountsParser = null; 106 107 /* If the iPod is a Shuffle, use the iPod shuffle parser. Otherwise 108 * use the non-shuffle parser. */ 109 if (isShuffle) { 115 110 playCountsParser = new ItunesStatsParser(iTunesPath, parseMultiPlayTracks); 111 } else { 112 playCountsParser = new PlayCountsParser(iTunesPath, parseMultiPlayTracks); 116 113 } 117 114 trunk/src/main/org/lastpod/action/DeletePlayCounts.java
r89 r93 22 22 import org.lastpod.UI; 23 23 24 import org.lastpod. util.ItunesStatsFilter;24 import org.lastpod.parser.ItunesStatsParser; 25 25 26 26 import java.awt.event.ActionEvent; … … 91 91 playCountsFile = new File(iTunesPath + "Play Counts"); 92 92 93 /* Checks for the "iTunesStats" file. If it exists, switch to the iPod 94 * shuffle file. */ 95 File file = new File(iTunesPath); 96 File[] itunesStatsFiles = file.listFiles(new ItunesStatsFilter()); 97 98 if ((itunesStatsFiles != null) && (itunesStatsFiles.length != 0)) { 93 /* If the iPod is a Shuffle, switch to the shuffle delete logic. */ 94 if (ItunesStatsParser.isIpodShuffle(iTunesPath)) { 99 95 playCountsFile = new File(iTunesPath + "iTunesStats"); 100 96 putValue(SHORT_DESCRIPTION, "Removes the iTunesStats file from the iPod shuffle."); trunk/src/main/org/lastpod/parser/ItunesDbParser.java
r92 r93 29 29 import java.io.InputStream; 30 30 31 import java.math.BigInteger; 32 31 33 import java.util.ArrayList; 34 import java.util.HashMap; 32 35 import java.util.List; 36 import java.util.Map; 33 37 34 38 /** … … 45 49 46 50 /** 51 * The location of the iTunesSD file. 52 */ 53 private String iTunesSdFile; 54 55 /** 47 56 * Stores a boolean value that will be passed into <code>TrackItem</code>. 48 57 */ … … 53 62 */ 54 63 String[] variousArtistsStrings; 64 65 /** 66 * Stores <code>true</code> if this iTunesDB is for an iPod shuffle. 67 */ 68 boolean isShuffle = false; 55 69 56 70 /** … … 70 84 * @param variousArtistsStrings A String array containing the various artist 71 85 * strings that should be parsed. 86 * @param isShuffle <code>true</code> if this iTunesDB is for an iPod shuffle. 72 87 */ 73 88 public ItunesDbParser(String iTunesPath, boolean parseVariousArtists, 74 String[] variousArtistsStrings ) {89 String[] variousArtistsStrings, boolean isShuffle) { 75 90 if (!iTunesPath.endsWith(File.separator)) { 76 91 iTunesPath += File.separator; … … 78 93 79 94 this.iTunesFile = iTunesPath + "iTunesDB"; 95 this.iTunesSdFile = iTunesPath + "iTunesSD"; 80 96 this.parseVariousArtists = parseVariousArtists; 81 97 this.variousArtistsStrings = variousArtistsStrings; 98 this.isShuffle = isShuffle; 82 99 } 83 100 … … 95 112 itunesBufferedIn = new BufferedInputStream(itunesFileIn, 65535); 96 113 97 return parseitunesdb(itunesBufferedIn); 114 List trackList = parseitunesdb(itunesBufferedIn); 115 116 if (!isShuffle) { 117 return trackList; 118 } else { 119 return readItunesSdAndReorderList(trackList); 120 } 98 121 } catch (IOException e) { 99 122 throw new RuntimeException("Error reading iTunes Database"); … … 240 263 241 264 /** 265 * Reads the iTunesSD file and uses the ordering in this file to reorder 266 * the track list. 267 * @param trackList The track list from the iTunesDB 268 * @return A new <code>java.util.List</code> that is ordered per the 269 * iTunesSD order. 270 * @throws IOException Thrown if I/O errors occur. 271 */ 272 private List readItunesSdAndReorderList(List trackList) 273 throws IOException { 274 InputStream itunesSdFileIn = null; 275 InputStream itunesSdBufferedIn = null; 276 277 try { 278 itunesSdFileIn = new FileInputStream(iTunesSdFile); 279 itunesSdBufferedIn = new BufferedInputStream(itunesSdFileIn, 65535); 280 281 /* Converts the trackList into a Map. */ 282 Map trackMap = new HashMap(); 283 TrackItem track = null; 284 285 for (int i = 0; i < trackList.size(); i++) { 286 track = (TrackItem) trackList.get(i); 287 trackMap.put(track.getLocation(), track); 288 } 289 290 List orderedTrackList = new ArrayList(); 291 292 byte[] threeBytes = new byte[3]; 293 294 itunesSdBufferedIn.read(threeBytes); 295 296 int numentries = (new BigInteger(threeBytes)).intValue(); 297 298 IoUtils.skipFully(itunesSdBufferedIn, 15); //skip rest of header 299 assert (numentries == trackList.size()); 300 301 for (int i = 0; i < (numentries - 1); i++) { 302 itunesSdBufferedIn.mark(1048576); //save beginning of entry location 303 304 itunesSdBufferedIn.read(threeBytes); 305 306 int entrylen = (new BigInteger(threeBytes)).intValue(); 307 308 IoUtils.skipFully(itunesSdBufferedIn, 30); 309 310 byte[] data = new byte[522]; 311 itunesSdBufferedIn.read(data); 312 313 /* Filename should have : characters instead of / characters. */ 314 String filename = new String(data, "UTF-16LE").replace('/', ':').trim(); 315 316 orderedTrackList.add(trackMap.get(filename)); 317 318 itunesSdBufferedIn.reset(); 319 IoUtils.skipFully(itunesSdBufferedIn, entrylen); 320 } 321 322 return orderedTrackList; 323 } finally { 324 IoUtils.cleanup(itunesSdFileIn, null); 325 IoUtils.cleanup(itunesSdBufferedIn, null); 326 } 327 } 328 329 /** 242 330 * Does nothing for this implementation. 243 331 * @param trackList Does nothing for this implementation. trunk/src/main/org/lastpod/parser/ItunesStatsParser.java
r91 r93 22 22 23 23 import org.lastpod.util.IoUtils; 24 import org.lastpod.util.ItunesStatsFilter; 24 25 25 26 import java.io.BufferedInputStream; … … 113 114 playCountsBufferedIn = new BufferedInputStream(playCountsFileIn, 65535); 114 115 115 return parseitunesStats(playCountsBufferedIn); 116 List trackList = parseitunesStats(playCountsBufferedIn); 117 118 return manufactureLastPlayed(trackList); 116 119 } catch (IOException e) { 117 120 String errorMsg = … … 145 148 IoUtils.skipFully(itunesStatsistream, 3); //skip rest of header 146 149 147 Calendar calendar = Calendar.getInstance();148 149 150 for (int i = 0; i < (numentries - 1); i++) { 150 151 itunesStatsistream.mark(1048576); //save beginning of entry location … … 164 165 TrackItem temptrack = (TrackItem) trackList.get(i); 165 166 temptrack.setPlaycount(playcount); 166 calendar.add(Calendar.SECOND, -(int) temptrack.getLength());167 temptrack.setLastplayed(calendar.getTimeInMillis() / 1000);168 169 167 recentPlays.add(trackList.get(i)); 170 168 … … 173 171 174 172 for (long j = 0; j < numberToManufacture; j++) { 175 temptrack = manufactureTrack(temptrack , calendar);173 temptrack = manufactureTrack(temptrack); 176 174 recentPlays.add(temptrack); 177 175 } … … 193 191 * @return A manufactured <code>TrackItem</code>. 194 192 */ 195 private TrackItem manufactureTrack(TrackItem temptrack , Calendar calendar) {193 private TrackItem manufactureTrack(TrackItem temptrack) { 196 194 TrackItem manufacturedTrack = new TrackItem(temptrack); 197 calendar.add(Calendar.SECOND, -(int) manufacturedTrack.getLength());198 manufacturedTrack.setLastplayed(calendar.getTimeInMillis() / 1000);199 200 195 manufacturedTrack.setPlaycount(1); 201 196 temptrack.setPlaycount(1); … … 203 198 return manufacturedTrack; 204 199 } 200 201 /** 202 * Manufactures the last played times for all the track items. 203 * @param trackItems The list of track items to modify. 204 * @return The modified list of track items. 205 */ 206 private List manufactureLastPlayed(List trackItems) { 207 Calendar calendar = Calendar.getInstance(); 208 TrackItem temptrack = null; 209 210 for (int i = trackItems.size() - 1; i >= 0; i--) { 211 temptrack = (TrackItem) trackItems.get(i); 212 calendar.add(Calendar.SECOND, -(int) temptrack.getLength()); 213 temptrack.setLastplayed(calendar.getTimeInMillis() / 1000); 214 } 215 216 return trackItems; 217 } 218 219 /** 220 * Utility function to determine if the iTunesPath is that of an iPod shuffle. 221 * @param iTunesPath The path to the iTunes_Control directory. 222 * @return <code>true</code> if the iPod is a Shuffle. 223 */ 224 public static boolean isIpodShuffle(String iTunesPath) { 225 /* Checks for the "iTunesStats" file. If it exists, switch to the iPod 226 * shuffle file. */ 227 File file = new File(iTunesPath); 228 File[] itunesStatsFiles = file.listFiles(new ItunesStatsFilter()); 229 230 return (itunesStatsFiles != null) && (itunesStatsFiles.length != 0); 231 } 205 232 }
