View Javadoc

1   package com.melloware.jukes.gui.view.tasks;
2   
3   import java.io.File;
4   import java.util.HashMap;
5   import java.util.Iterator;
6   import java.util.List;
7   import java.util.Map;
8   
9   import javazoom.jlgui.basicplayer.BasicPlayer;
10  
11  import org.apache.commons.io.FileUtils;
12  import org.apache.commons.io.FilenameUtils;
13  import org.apache.commons.lang.StringUtils;
14  import org.apache.commons.logging.Log;
15  import org.apache.commons.logging.LogFactory;
16  
17  import com.jgoodies.uif.action.ActionManager;
18  import com.jgoodies.uif.application.Application;
19  import com.jgoodies.uif.util.Worker;
20  import com.melloware.jspiff.jaxp.XspfPlaylist;
21  import com.melloware.jspiff.jaxp.XspfTrack;
22  import com.melloware.jukes.db.orm.Artist;
23  import com.melloware.jukes.db.orm.Catalog;
24  import com.melloware.jukes.db.orm.Disc;
25  import com.melloware.jukes.db.orm.Track;
26  import com.melloware.jukes.file.Playlist;
27  import com.melloware.jukes.file.filter.M3uFilter;
28  import com.melloware.jukes.file.filter.XspfFilter;
29  import com.melloware.jukes.gui.tool.Actions;
30  import com.melloware.jukes.gui.tool.Player;
31  import com.melloware.jukes.gui.view.MainFrame;
32  
33  /**
34   * In a thread attempts to load the playlist one song at a time and notify
35   * user of the progress.
36   * <p>
37   * Copyright (c) 1999-2007 Melloware, Inc. <http://www.melloware.com>
38   * @author Emil A. Lefkof III <info@melloware.com>
39   * @version 4.0
40   */
41  @SuppressWarnings("unchecked")
42  public final class LoadPlaylistTask
43      extends LongTask {
44  
45      private static final Log LOG = LogFactory.getLog(LoadPlaylistTask.class);
46      private static final String BREAK = " - ";
47      private final File file;
48      private final List m3uLines;
49      private final Playlist playlist;
50      private final XspfPlaylist xspfPlaylist;
51      private final Map artists;
52  
53      /**
54       * Constructor that needs a file to load.
55       * <p>
56       * @param aFile the file to load
57       * @throws Exception if any error occurs
58       */
59      public LoadPlaylistTask(File aFile, Playlist aPlaylist)
60                       throws Exception {
61          super();
62          LOG.debug("Loading playlist");
63          this.file = aFile;
64          this.playlist = aPlaylist;
65          
66          //put all the artists in a map for faster access
67          List artists = Catalog.findAllArtists();
68          HashMap map = new HashMap(artists.size());
69          Iterator iter = artists.iterator();
70          while (iter.hasNext()) {
71  			Artist element = (Artist) iter.next();
72  			map.put(element.getName(), element);
73  		}
74          this.artists = map;
75  
76          
77          // determine the playlist type and load appropriately
78          if (FilenameUtils.isExtension(file.getName(), M3uFilter.M3U)) {
79              m3uLines = FileUtils.readLines(file, null);
80              lengthOfTask = m3uLines.size();
81              xspfPlaylist = null;
82          } else if (FilenameUtils.isExtension(file.getName(), XspfFilter.XSPF)) {
83              xspfPlaylist = new XspfPlaylist(file);
84              lengthOfTask = xspfPlaylist.getPlaylistTrackList().sizeTrack();
85              m3uLines = null;
86          } else {
87              throw new IllegalArgumentException("Playlist is not a valid type");
88          }
89          LOG.debug("Length of Task = " + lengthOfTask);
90      }
91  
92      /**
93       * Called to start the task.
94       */
95      public void go() {
96          final Worker worker = new Worker() {
97              public Object construct() {
98                  current = 0;
99                  done = false;
100                 canceled = false;
101                 statMessage = null;
102                 return new ActualTask();
103             }
104         };
105         worker.start();
106     }
107 
108     /**
109      * Try to locate this track in the database and load into playlist.
110      * <p>
111      * @param artistName the artist name
112      * @param discName the disc name
113      * @param trackName the track name
114      * @return the Track if found else null
115      */
116     @SuppressWarnings("unused")
117     private Track findTrack(String artistName, String discName, String trackName) {
118         Track result = null;
119         
120         Artist artist = (Artist)this.artists.get(artistName);
121         if (artist == null) {
122 			return result;
123 		}
124         Iterator iter = artist.getDiscs().iterator();
125         DISC_LOOP:
126         while (iter.hasNext()) {
127 			Disc disc = (Disc) iter.next();
128 			if (StringUtils.equalsIgnoreCase(disc.getName(), discName)) {
129 				Iterator iterator = disc.getTracks().iterator();
130 				TRACK_LOOP:
131 				while (iterator.hasNext()) {
132 					Track track = (Track) iterator.next();
133 					if (StringUtils.equalsIgnoreCase(track.getName(), trackName)) {
134 						result = track;
135 						break DISC_LOOP;
136 					}
137 				}
138 			}
139 		}
140 
141         return result;
142     }
143 
144     /**
145      * The actual long running task.  This runs in a SwingWorker thread.
146      */
147     class ActualTask {
148         ActualTask() {
149             while (!canceled && !done) {
150                 try {
151                     if (m3uLines != null) { //NOPMD
152                         int count = 1;
153                         final Iterator iter = m3uLines.iterator();
154                         while ((iter.hasNext()) && (!canceled && !done)) {
155                             current = count;
156                             count++;
157                             String element = (String)iter.next();
158 
159                             // skip any lines that don't start with #
160                             if (!element.startsWith("#EXTINF")) {
161                                 continue;
162                             }
163 
164                             // strip off the '#EXTINF:duration,'
165                             element = StringUtils.substringAfter(element, ",");
166                             String artist = StringUtils.substringBefore(element, BREAK).trim();
167                             String title = StringUtils.substringAfterLast(element, BREAK).trim();
168                             element = StringUtils.substringAfter(element, BREAK).trim();
169                             element = StringUtils.substringBeforeLast(element, BREAK).trim();
170                             String disc = element;
171 
172                             Track track = findTrack(artist, disc, title);
173                             if (track != null) {
174                                 statMessage = "Loading: " + track.getName();
175                                 playlist.add(track);
176                             }
177 
178                         }
179                     } else if (xspfPlaylist != null) { //NOPMD
180                         final XspfTrack[] array = xspfPlaylist.getPlaylistTrackList().getTrack();
181                         for (int i = 0; i < array.length; i++) {
182                             if ((canceled || done)) {
183                                 break;
184                             }
185                             current = i;
186                             final XspfTrack element = array[i];
187                             Track track = findTrack(element.getCreator(), element.getAlbum(), element.getTitle());
188                             if (track != null) {
189                                 statMessage = "Loading: " + track.getName();
190                                 playlist.add(track);
191                             }
192                         }
193                     } else {
194                         throw new IllegalArgumentException("Unknown type.");
195                     }
196 
197                     // if the player was stopped then play the next song
198                     final Player player = ((MainFrame)Application.getDefaultParentFrame()).getPlayer();
199                     if ((player.getStatus() == BasicPlayer.STOPPED) || (player.getStatus() == BasicPlayer.UNKNOWN)) {
200                         ActionManager.get(Actions.PLAYER_NEXT_ID).actionPerformed(null);
201                     }
202 
203                     done = true;
204                 } catch (Exception ex) {
205                     stop();
206                     LOG.info("Exception caught loading tracks:", ex);
207                     statMessage = "Exception caught loading tracks: " + ex.getMessage();
208                 }
209             }
210         }
211 
212     }
213 
214 }