View Javadoc

1   package com.melloware.jukes.file.tag;
2   
3   import java.io.File;
4   import java.util.Map;
5   
6   import org.apache.commons.lang.StringUtils;
7   import org.apache.commons.logging.Log;
8   import org.apache.commons.logging.LogFactory;
9   import entagged.audioformats.exceptions.CannotReadException;
10  import entagged.audioformats.exceptions.CannotWriteException;
11  
12  import entagged.audioformats.AudioFile;
13  import entagged.audioformats.AudioFileIO;
14  
15  import com.jgoodies.uif.application.Application;
16  import com.jgoodies.uif.util.ResourceUtils;
17  import com.melloware.jukes.exception.MusicTagException;
18  import com.melloware.jukes.gui.view.MainFrame;
19  import com.melloware.jukes.util.MessageUtil;
20  
21  
22  
23  /**
24   * MusicTag class used for editing  APE file tags. 
25   * <p>
26   * The Entagged (http://entagged.sourceforge.net/) library is used to read these
27   * types of Tags.
28   * <p>
29   * Copyright (c) 2006 Melloware, Inc. <http://www.melloware.com>
30   * @author Emil A. Lefkof III <info@melloware.com>
31   * @version 4.0
32   * AZ (C) 2010
33   */
34  public final class ApeFileTag extends MusicTag {
35  
36     private static final Log LOG = LogFactory.getLog(ApeFileTag.class);
37     private AudioFile audioFile;
38  
39  
40     /**
41      * Constructor that accepts a file.
42      * <p>
43      * @param aFile the file to open
44      * @throws MusicTagException if any error occurs loading tag
45      */
46     public ApeFileTag(File aFile) throws MusicTagException {
47        super(aFile);
48          try {
49           // create the audio file object
50           this.audioFile = AudioFileIO.read(aFile);
51           // initialize all tags
52           initializeTags();
53        } catch (CannotReadException ex) {
54           LOG.error(ex.getMessage(), ex);
55           throw new MusicTagException("CannotReadException opening Music File Tag." + aFile.getAbsolutePath() + "\n\n"
56                    + ex.getMessage());
57        } catch (Exception ex) {
58           LOG.error(ex.getMessage(), ex);
59           throw new MusicTagException("Unexpected exception opening Music File Tag." + aFile.getAbsolutePath() + "\n\n"
60                    + ex.getMessage());
61        }
62  
63     }
64  
65     /*
66      * (non-Javadoc)
67      * @see com.melloware.jukes.file.tag.MusicTag#getArtist()
68      */
69     public String getArtist() {
70  		
71  	  String Artist = "";
72  	  if (this.artist == null) {
73  
74      	  if ( audioFile.getTag().get(settings.getAlbumArtistTag()).size() != 0){
75      		  Artist = audioFile.getTag().get(settings.getAlbumArtistTag()).get(0).toString().trim();
76      	  }
77      	  if (Artist == "") {
78      	   if ( audioFile.getTag().get("Album artist").size() != 0){
79      		  Artist = audioFile.getTag().get("Album artist").get(0).toString().trim();
80      	   }
81      	  }
82      	  if (Artist == "") {
83         	   if ( audioFile.getTag().getFirstArtist() != null){
84      	   this.artist = StringUtils.defaultIfEmpty(audioFile.getTag().getFirstArtist(), NO_TAG).trim();
85         	   }
86      	  }
87      	  else {
88      	    this.artist = Artist;  
89      	  }
90  	  }
91        return this.artist;
92     }
93  
94     /*
95      * (non-Javadoc)
96      * @see com.melloware.jukes.file.tag.MusicTag#getBitRate()
97      */
98     public Long getBitRate() {
99        if (this.bitRate == null) {
100          this.bitRate = Long.valueOf(audioFile.getBitrate());
101       }
102       return this.bitRate;
103    }
104 
105    /*
106     * (non-Javadoc)
107     * @see com.melloware.jukes.file.tag.MusicTag#getComment()
108     */
109    public String getComment() {
110       if (StringUtils.isBlank(this.comment)) {
111          this.comment = StringUtils.defaultIfEmpty(audioFile.getTag().getFirstComment(), "").trim();
112       }
113       return this.comment;
114    }
115 
116    /*
117     * (non-Javadoc)
118     * @see com.melloware.jukes.file.tag.MusicTag#getCopyrighted()
119     */
120    public String getCopyrighted() {
121       return "No";
122    }
123 
124    /*
125     * (non-Javadoc)
126     * @see com.melloware.jukes.file.tag.MusicTag#getDisc()
127     */
128    public String getDisc() {
129    /** AZ **/		
130    	 if (StringUtils.isBlank(this.disc)) {
131    	 String CD_Number = "";	 
132      this.disc = StringUtils.defaultIfEmpty(audioFile.getTag().getFirstAlbum(), NO_TAG).trim();
133      if (settings.isUseCDNumber()) {	 
134        if (audioFile.getTag().get("Disc").size() != 0) {
135        CD_Number = " - CD " + audioFile.getTag().get("Disc").get(0).toString().trim(); 
136        this.disc = this.disc + CD_Number;	
137        }
138       }
139    	 }
140      return this.disc;
141    }
142 
143    /*
144     * (non-Javadoc)
145     * @see com.melloware.jukes.file.tag.MusicTag#getEmphasis()
146     */
147    public String getEmphasis() {
148       return "None";
149    }
150 
151    /*
152     * (non-Javadoc)
153     * @see com.melloware.jukes.file.tag.MusicTag#getEncodedBy()
154     */
155    public String getEncodedBy() {
156       if (StringUtils.isBlank(this.encodedBy)) {
157          this.encodedBy = System.getProperty("application.name");
158       }
159       return this.encodedBy;
160    }
161 
162    /*
163     * (non-Javadoc)
164     * @see com.melloware.jukes.file.tag.MusicTag#getFrequency()
165     */
166    public String getFrequency() {
167       return Integer.toString(audioFile.getSamplingRate());
168 
169    }
170 
171    /*
172     * (non-Javadoc)
173     * @see com.melloware.jukes.file.tag.MusicTag#getGenre()
174     */
175    public String getGenre() {
176       if (StringUtils.isBlank(this.genre)) {
177          this.genre = StringUtils.defaultIfEmpty(audioFile.getTag().getFirstGenre(), "Other").trim();
178       }
179       return this.genre;
180    }
181 
182    /*
183     * (non-Javadoc)
184     * @see com.melloware.jukes.file.tag.MusicTag#getHeader()
185     */
186    public Map getHeader() {
187       return header;
188    }
189 
190    /*
191     * (non-Javadoc)
192     * @see com.melloware.jukes.file.tag.MusicTag#getLayer()
193     */
194    public String getLayer() {
195       return audioFile.getEncodingType();
196    }
197 
198    /*
199     * (non-Javadoc)
200     * @see com.melloware.jukes.file.tag.MusicTag#getMode()
201     */
202    public String getMode() {
203       return audioFile.getEncodingType();
204    }
205 
206    /*
207     * (non-Javadoc)
208     * @see com.melloware.jukes.file.tag.MusicTag#getTitle()
209     */
210    public String getTitle() {
211       if (StringUtils.isBlank(this.title)) {
212 
213          String temp = StringUtils.defaultIfEmpty(audioFile.getTag().getFirstTitle(), NO_TAG).trim();
214 
215          // if this is the max length for a tag, or it begins with "Track"
216          // try and grab by filename it may be longer
217          if ((temp.length() == 30) || (temp.equals(NO_TAG)) || (temp.startsWith("Track"))) {
218             temp = extractTitleFromFilename();
219             LOG.debug("Filename extracted");
220          }
221 
222          // return v2 tag else if empty return the v1 tag
223          this.title = StringUtils.defaultIfEmpty(temp, NO_TAG).trim();
224       }
225       return this.title;
226    }
227 
228    /*
229     * (non-Javadoc)
230     * @see com.melloware.jukes.file.tag.MusicTag#getTrack()
231     */
232    public String getTrack() {
233       if (StringUtils.isBlank(this.track)) {
234          int trackNum = 0;
235          String tracknumber = StringUtils.defaultIfEmpty(audioFile.getTag().getFirstTrack(), "X").trim();
236          if (StringUtils.isNumeric(tracknumber)) {
237             trackNum = Integer.parseInt(tracknumber);
238          }
239 
240          // return v2 tag else if empty return the v1 tag
241          this.track = StringUtils.leftPad(String.valueOf(trackNum), 2, "0").trim();
242 
243       }
244       return this.track;
245    }
246 
247    /*
248     * (non-Javadoc)
249     * @see com.melloware.jukes.file.tag.MusicTag#getTrackLength()
250     */
251    public long getTrackLength() {
252       if (this.trackLength > 1) {
253          return this.trackLength;
254       }
255       this.trackLength = audioFile.getLength();
256       return this.trackLength;
257    }
258 
259    /*
260     * (non-Javadoc)
261     * @see com.melloware.jukes.file.tag.MusicTag#getVersion()
262     */
263    public String getVersion() {
264       return audioFile.getEncodingType();
265    }
266 
267    /*
268     * (non-Javadoc)
269     * @see com.melloware.jukes.file.tag.MusicTag#getYear()
270     */
271    public String getYear() {
272       if (StringUtils.isBlank(this.year)) {
273          this.year = StringUtils.defaultIfEmpty(audioFile.getTag().getFirstYear(), CURRENT_YEAR).trim();
274       }
275       return this.year;
276    }
277 
278    /*
279     * (non-Javadoc)
280     * @see com.melloware.jukes.file.tag.MusicTag#setArtist(java.lang.String)
281     */
282    public void setArtist(String aArtist) {
283       this.artist = StringUtils.defaultIfEmpty(aArtist, NO_TAG).trim();
284       try {
285          audioFile.getTag().setArtist(this.artist);
286       } catch (Exception ex) {
287          LOG.error("FieldDataInvalidException", ex);
288    	     final MainFrame mainFrame = (MainFrame) Application.getDefaultParentFrame();
289 	     MessageUtil.showError(mainFrame, "FieldDataInvalidException: " + ex.getMessage()); //AZ
290       }
291 
292    }
293 
294    /*
295     * (non-Javadoc)
296     * @see com.melloware.jukes.file.tag.MusicTag#setComment(java.lang.String)
297     */
298    public void setComment(String aComment) {
299       this.comment = StringUtils.defaultIfEmpty(aComment, "").trim();
300       try {
301          audioFile.getTag().setComment(this.comment);
302       } catch (Exception ex) {
303          LOG.error("FieldDataInvalidException", ex);
304    	     final MainFrame mainFrame = (MainFrame) Application.getDefaultParentFrame();
305 	     MessageUtil.showError(mainFrame, "FieldDataInvalidException: " + ex.getMessage()); //AZ
306       }
307    }
308 
309    /*
310     * (non-Javadoc)
311     * @see com.melloware.jukes.file.tag.MusicTag#setDisc(java.lang.String)
312     */
313    public void setDisc(String aDisc) {
314       this.disc = StringUtils.defaultIfEmpty(aDisc, NO_TAG).trim();
315       try {
316          audioFile.getTag().setAlbum(this.disc);
317       } catch (Exception ex) {
318          LOG.error("FieldDataInvalidException", ex);
319    	     final MainFrame mainFrame = (MainFrame) Application.getDefaultParentFrame();
320 	     MessageUtil.showError(mainFrame, "FieldDataInvalidException: "+ex.getMessage()); //AZ
321       }
322 
323    }
324 
325    /*
326     * (non-Javadoc)
327     * @see com.melloware.jukes.file.tag.MusicTag#setEncodedBy(java.lang.String)
328     */
329    public void setEncodedBy(String aEncodedBy) {
330 	  //AZ - Do not fill EncodedBy with "Jukes" 
331       //this.encodedBy = StringUtils.defaultIfEmpty(aEncodedBy, System.getProperty("application.name")).trim();
332       this.encodedBy = aEncodedBy;
333    }
334 
335    /*
336     * (non-Javadoc)
337     * @see com.melloware.jukes.file.tag.MusicTag#setGenre(java.lang.String)
338     */
339    public void setGenre(String aGenre) {
340       this.genre = StringUtils.defaultIfEmpty(aGenre, NO_TAG).trim();
341       try {
342          audioFile.getTag().setGenre(this.genre);
343       } catch (Exception ex) {
344          LOG.error("FieldDataInvalidException", ex);
345    	     final MainFrame mainFrame = (MainFrame) Application.getDefaultParentFrame();
346 	     MessageUtil.showError(mainFrame, "FieldDataInvalidException: "+ex.getMessage()); //AZ
347       }
348 
349    }
350 
351    /*
352     * (non-Javadoc)
353     * @see com.melloware.jukes.file.tag.MusicTag#setTitle(java.lang.String)
354     */
355    public void setTitle(String aTitle) {
356       this.title = StringUtils.defaultIfEmpty(aTitle, NO_TAG).trim();
357 
358       try {
359          audioFile.getTag().setTitle(this.title);
360       } catch (Exception ex) {
361          LOG.error("FieldDataInvalidException", ex);
362    	     final MainFrame mainFrame = (MainFrame) Application.getDefaultParentFrame();
363 	     MessageUtil.showError(mainFrame, "FieldDataInvalidException: "+ ex.getMessage()); //AZ
364       }
365    }
366 
367    /*
368     * (non-Javadoc)
369     * @see com.melloware.jukes.file.tag.MusicTag#setTrack(java.lang.String)
370     */
371    public void setTrack(String aTrack) {
372       setTrack(aTrack, 2);
373    }
374 
375    /**
376     * Sets the track.
377     * <p>
378     * @param aTrack The track to set.
379     * @param aPadding the number of 0's to pad this track with
380     */
381    public void setTrack(final String aTrack, final int aPadding) {
382       final String current = StringUtils.defaultIfEmpty(aTrack, "0").trim();
383       this.track = StringUtils.leftPad(current, aPadding, "0").trim();
384       try {
385          audioFile.getTag().setTrack(this.track);
386       } catch (Exception ex) {
387          LOG.error("FieldDataInvalidException", ex);
388    	     final MainFrame mainFrame = (MainFrame) Application.getDefaultParentFrame();
389 	     MessageUtil.showError(mainFrame, "FieldDataInvalidException: " + ex.getMessage()); //AZ
390       }
391    }
392 
393    /*
394     * (non-Javadoc)
395     * @see com.melloware.jukes.file.tag.MusicTag#setTrackLength(long)
396     */
397    public void setTrackLength(long aTrackLength) {
398       this.trackLength = aTrackLength;
399    }
400 
401    /*
402     * (non-Javadoc)
403     * @see com.melloware.jukes.file.tag.MusicTag#setYear(java.lang.String)
404     */
405    public void setYear(String aYear) {
406       this.year = StringUtils.defaultIfEmpty(aYear, CURRENT_YEAR).trim();
407       try {
408          audioFile.getTag().setYear(this.year);
409       } catch (Exception ex) {
410          LOG.error("FieldDataInvalidException", ex);
411    	     final MainFrame mainFrame = (MainFrame) Application.getDefaultParentFrame();
412 	     MessageUtil.showError(mainFrame, "FieldDataInvalidException: "+ex.getMessage()); //AZ
413       }
414    }
415 
416    /*
417     * (non-Javadoc)
418     * @see com.melloware.jukes.file.tag.MusicTag#isVBR()
419     */
420    public boolean isVBR() {
421       return audioFile.isVbr();
422    }
423 
424    /*
425     * (non-Javadoc)
426     * @see com.melloware.jukes.file.tag.MusicTag#removeTags()
427     */
428    public void removeTags() throws MusicTagException {
429       if (audioFile != null) {
430          try {
431             AudioFileIO.delete(audioFile);
432          } catch (Exception e) {
433             throw new MusicTagException("Error removing AudioFile tag: " + e.getMessage(), e);
434          }
435          initializeTags();
436       }
437    }
438 
439    /**
440     * Renames this Music file based on a format from prefs. The format is in
441     * aFormat and can have values %n for track number, %t for title, %a for
442     * artist, and %d for disc. Replaces any invalid characters (\\, /, :, , *, ?, ", <, >,
443     * or |) with underscores _ to prevent any errors on file systems. Examples:
444     * %n -%t = 01 - Track.mp3 %a - %d - %n - %t = Artist - Album - 01 -
445     * Track.mp3
446     * <p>
447     * @param aFormat the string format like %n -%t to rename 01 - Track.mp3
448     * @return true if renamed, false if failure
449     */
450    public boolean renameFile(String aFormat) {
451       boolean result = false;
452       try {
453          final String newFileName = createFilenameFromFormat(aFormat);
454          final File newFile = new File(newFileName);
455          // close the audioFile
456          audioFile = null;
457 
458          result = this.file.renameTo(newFile);
459          if (result) {
460             this.file = newFile;
461             this.audioFile = AudioFileIO.read(newFile);
462             initializeTags();
463          }
464       } catch (Exception ex) {
465     	 final String errorMessage = ResourceUtils.getString("messages.ErrorRenamingFile");
466          LOG.error(errorMessage, ex);
467    	     final MainFrame mainFrame = (MainFrame) Application.getDefaultParentFrame();
468 	     MessageUtil.showError(mainFrame, errorMessage); //AZ
469       }
470       return result;
471    }
472 
473    /*
474     * (non-Javadoc)
475     * @see com.melloware.jukes.file.tag.MusicTag#save()
476     */
477    public void save() throws MusicTagException {
478       if (audioFile != null) {
479          try {
480             audioFile.commit();
481          } catch (CannotWriteException ex) {
482             throw new MusicTagException("Error saving AudioFile tag: " + ex.getMessage());
483          }
484 
485       }
486 
487    }
488 
489    /**
490     * Initialize the tags for this audio file.
491     */
492    private void initializeTags() {
493       // initialize private variables from tags
494       this.getDisc();
495       this.getArtist();
496       this.getComment();
497       this.getGenre();
498       this.getTitle();
499       this.getTrack();
500       this.getYear();
501       this.getTrackLength();
502       this.getEncodedBy();
503    }
504 
505 }