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