1 package org.farng.mp3;
2 
3 import org.farng.mp3.id3.AbstractID3v2FrameBody;
4 import org.farng.mp3.id3.FrameBodyCOMM;
5 import org.farng.mp3.id3.FrameBodyTIPL;
6 
7 import java.util.HashMap;
8 import java.util.Iterator;
9 import java.util.LinkedList;
10 import java.util.List;
11 import java.util.Map;
12 
13 /**
14  * Options that are used for every object and class in this library.
15  *
16  * @author Eric Farng
17  * @version $Revision: 1.3 $
18  */
19 public class TagOptionSingleton {
20 
21     private static final Map tagOptionTable = new HashMap();
22     private static final String DEFAULT = "default";
23     private static Object defaultOptions = TagOptionSingleton.DEFAULT;
24     private Map keywordMap = new HashMap();
25     /**
26      * Map of lyric ID's to Boolean objects if we should or should not save the specific Kyrics3 field. Defaults to
27      * true.
28      */
29     private Map lyrics3SaveFieldMap = new HashMap();
30     /**
31      * parenthesis map stuff
32      */
33     private Map parenthesisMap = new HashMap();
34     /**
35      * <code>HashMap</code> listing words to be replaced if found
36      */
37     private Map replaceWordMap = new HashMap();
38     private List endWordDelimiterList = new LinkedList();
39     /**
40      * delimiters within a file name
41      */
42     private List filenameDelimiterList = new LinkedList();
43     private List startWordDelimiterList = new LinkedList();
44     /**
45      * words to always set the case as upper or lower case
46      */
47     private List upperLowerCaseWordList = new LinkedList();
48     /**
49      * default language for any ID3v2 tags frameswhich require it. This string is in the [ISO-639-2] ISO/FDIS 639-2
50      * definition
51      */
52     private String language = "eng";
53     private boolean compositeMatchOverwrite = false;
54     private boolean filenameTagSave = false;
55     /**
56      * if we should save any fields of the ID3v1 tag or not. Defaults to true.
57      */
58     private boolean id3v1Save = true;
59     /**
60      * if we should save the album field of the ID3v1 tag or not. Defaults to true.
61      */
62     private boolean id3v1SaveAlbum = true;
63     /**
64      * if we should save the artist field of the ID3v1 tag or not. Defaults to true.
65      */
66     private boolean id3v1SaveArtist = true;
67     /**
68      * if we should save the comment field of the ID3v1 tag or not. Defaults to true.
69      */
70     private boolean id3v1SaveComment = true;
71     /**
72      * if we should save the genre field of the ID3v1 tag or not. Defaults to true.
73      */
74     private boolean id3v1SaveGenre = true;
75     /**
76      * if we should save the title field of the ID3v1 tag or not. Defaults to true.
77      */
78     private boolean id3v1SaveTitle = true;
79     /**
80      * if we should save the track field of the ID3v1 tag or not. Defaults to true.
81      */
82     private boolean id3v1SaveTrack = true;
83     /**
84      * if we should save the year field of the ID3v1 tag or not. Defaults to true.
85      */
86     private boolean id3v1SaveYear = true;
87     /**
88      * if we should keep an empty ID3v2 frame while we're reading. This is different from a string of white space.
89      * Defaults to false.
90      */
91     //todo I don't think I'm checking this right now
92     private boolean id3v2KeepEmptyFrameIfRead = false;
93     /**
94      * When adjusting the ID3v2 padding, if should we copy the current ID3v2 tag to the new MP3 file. Defaults to true.
95      */
96     private boolean id3v2PaddingCopyTag = true;
97     /**
98      * When adjusting the ID3v2 padding, if we should shorten the length of the ID3v2 tag padding. Defaults to false.
99      */
100     private boolean id3v2PaddingWillShorten = false;
101     /**
102      * if we should save any fields of the ID3v2 tag or not. Defaults to true.
103      */
104     private boolean id3v2Save = true;
105     /**
106      * if we should save empty ID3v2 frames or not. Defaults to false.
107      */
108     //todo I don't think this is implemented yet.
109     private boolean id3v2SaveEmptyFrame = false;
110     /**
111      * if we should save the ID3v2 extended header or not. Defaults to false.
112      */
113     //todo Not implemented yet
114     private boolean id3v2SaveExtendedHeader = false;
115     /**
116      * if we should keep an empty Lyrics3 field while we're reading. This is different from a string of white space.
117      * Defaults to false.
118      */
119     private boolean lyrics3KeepEmptyFieldIfRead = false;
120     /**
121      * if we should save any fields of the Lyrics3 tag or not. Defaults to true.
122      */
123     private boolean lyrics3Save = true;
124     /**
125      * if we should save empty Lyrics3 field or not. Defaults to false.
126      */
127     //todo I don't think this is implemented yet.
128     private boolean lyrics3SaveEmptyField = false;
129     private boolean originalSavedAfterAdjustingID3v2Padding = true;
130     /**
131      * default play counter size in bytes for the ID3v2 Tag.
132      */
133     //todo implement this.
134     private byte playCounterSize = 4;
135     /**
136      * default text encoding for any ID3v2 tag frames which require it.
137      */
138     private byte textEncoding = 0;
139     /**
140      * default time stamp format for any ID3v2 tag frames which require it.
141      */
142     private byte timeStampFormat = 2;
143     /**
144      * factor to increase the id3v2 padding size. When the ID3v2 tag padding length is calculated and is not large
145      * enough to fit the current ID3v2 tag, the padding length will be multiplied by this number until it is large
146      * enough.
147      */
148     private float id3v2PaddingMultiplier = 2;
149     private int defaultSaveMode = TagConstant.MP3_FILE_SAVE_WRITE;
150     /**
151      * padding length of the ID3v2 tag.
152      */
153     private int id3v2PaddingSize = 2048;
154     /**
155      * number of frames to sync when trying to find the start of the MP3 frame data. The start of the MP3 frame data is
156      * the start of the music and is different from the ID3v2 frame data.
157      */
158     private int numberMP3SyncFrame = 5;
159 
160     /**
161      * Creates a new TagOptions object. All Options are set to their default values
162      */
TagOptionSingleton()163     private TagOptionSingleton() {
164         setToDefault();
165     }
166 
getInstance()167     public static TagOptionSingleton getInstance() {
168         return getInstance(defaultOptions);
169     }
170 
getInstance(final Object instanceKey)171     public static TagOptionSingleton getInstance(final Object instanceKey) {
172         TagOptionSingleton tagOptions = (TagOptionSingleton) tagOptionTable.get(instanceKey);
173         if (tagOptions == null) {
174             tagOptions = new TagOptionSingleton();
175             tagOptionTable.put(instanceKey, tagOptions);
176         }
177         return tagOptions;
178     }
179 
getCloseParenthesis(final String open)180     public String getCloseParenthesis(final String open) {
181         return (String) parenthesisMap.get(open);
182     }
183 
isCloseParenthesis(final String close)184     public boolean isCloseParenthesis(final String close) {
185         return parenthesisMap.containsValue(close);
186     }
187 
setCompositeMatchOverwrite(final boolean compositeMatchOverwrite)188     public void setCompositeMatchOverwrite(final boolean compositeMatchOverwrite) {
189         this.compositeMatchOverwrite = compositeMatchOverwrite;
190     }
191 
isCompositeMatchOverwrite()192     public boolean isCompositeMatchOverwrite() {
193         return compositeMatchOverwrite;
194     }
195 
setDefaultSaveMode(final int defaultSaveMode)196     public void setDefaultSaveMode(final int defaultSaveMode) {
197         this.defaultSaveMode = defaultSaveMode;
198     }
199 
getDefaultSaveMode()200     public int getDefaultSaveMode() {
201         return this.defaultSaveMode;
202     }
203 
setFilenameTagSave(final boolean filenameTagSave)204     public void setFilenameTagSave(final boolean filenameTagSave) {
205         this.filenameTagSave = filenameTagSave;
206     }
207 
isFilenameTagSave()208     public boolean isFilenameTagSave() {
209         return this.filenameTagSave;
210     }
211 
isId3v2SaveExtendedHeader()212     public boolean isId3v2SaveExtendedHeader() {
213         return this.id3v2SaveExtendedHeader;
214     }
215 
setInstanceKey(final Object instanceKey)216     public void setInstanceKey(final Object instanceKey) {
217         TagOptionSingleton.defaultOptions = instanceKey;
218     }
219 
getInstanceKey()220     public static Object getInstanceKey() {
221         return defaultOptions;
222     }
223 
getEndWordDelimiterIterator()224     public Iterator getEndWordDelimiterIterator() {
225         return this.endWordDelimiterList.iterator();
226     }
227 
getFilenameDelimiterIterator()228     public Iterator getFilenameDelimiterIterator() {
229         return this.filenameDelimiterList.iterator();
230     }
231 
setId3v1Save(final boolean id3v1Save)232     public void setId3v1Save(final boolean id3v1Save) {
233         this.id3v1Save = id3v1Save;
234     }
235 
isId3v1Save()236     public boolean isId3v1Save() {
237         return this.id3v1Save;
238     }
239 
setId3v1SaveAlbum(final boolean id3v1SaveAlbum)240     public void setId3v1SaveAlbum(final boolean id3v1SaveAlbum) {
241         this.id3v1SaveAlbum = id3v1SaveAlbum;
242     }
243 
isId3v1SaveAlbum()244     public boolean isId3v1SaveAlbum() {
245         return this.id3v1SaveAlbum;
246     }
247 
setId3v1SaveArtist(final boolean id3v1SaveArtist)248     public void setId3v1SaveArtist(final boolean id3v1SaveArtist) {
249         this.id3v1SaveArtist = id3v1SaveArtist;
250     }
251 
isId3v1SaveArtist()252     public boolean isId3v1SaveArtist() {
253         return this.id3v1SaveArtist;
254     }
255 
setId3v1SaveComment(final boolean id3v1SaveComment)256     public void setId3v1SaveComment(final boolean id3v1SaveComment) {
257         this.id3v1SaveComment = id3v1SaveComment;
258     }
259 
isId3v1SaveComment()260     public boolean isId3v1SaveComment() {
261         return this.id3v1SaveComment;
262     }
263 
setId3v1SaveGenre(final boolean id3v1SaveGenre)264     public void setId3v1SaveGenre(final boolean id3v1SaveGenre) {
265         this.id3v1SaveGenre = id3v1SaveGenre;
266     }
267 
isId3v1SaveGenre()268     public boolean isId3v1SaveGenre() {
269         return this.id3v1SaveGenre;
270     }
271 
setId3v1SaveTitle(final boolean id3v1SaveTitle)272     public void setId3v1SaveTitle(final boolean id3v1SaveTitle) {
273         this.id3v1SaveTitle = id3v1SaveTitle;
274     }
275 
isId3v1SaveTitle()276     public boolean isId3v1SaveTitle() {
277         return this.id3v1SaveTitle;
278     }
279 
setId3v1SaveTrack(final boolean id3v1SaveTrack)280     public void setId3v1SaveTrack(final boolean id3v1SaveTrack) {
281         this.id3v1SaveTrack = id3v1SaveTrack;
282     }
283 
isId3v1SaveTrack()284     public boolean isId3v1SaveTrack() {
285         return this.id3v1SaveTrack;
286     }
287 
setId3v1SaveYear(final boolean id3v1SaveYear)288     public void setId3v1SaveYear(final boolean id3v1SaveYear) {
289         this.id3v1SaveYear = id3v1SaveYear;
290     }
291 
isId3v1SaveYear()292     public boolean isId3v1SaveYear() {
293         return this.id3v1SaveYear;
294     }
295 
setId3v2KeepEmptyFrameIfRead(final boolean id3v2KeepEmptyFrameIfRead)296     public void setId3v2KeepEmptyFrameIfRead(final boolean id3v2KeepEmptyFrameIfRead) {
297         this.id3v2KeepEmptyFrameIfRead = id3v2KeepEmptyFrameIfRead;
298     }
299 
isId3v2KeepEmptyFrameIfRead()300     public boolean isId3v2KeepEmptyFrameIfRead() {
301         return this.id3v2KeepEmptyFrameIfRead;
302     }
303 
setId3v2PaddingCopyTag(final boolean id3v2PaddingCopyTag)304     public void setId3v2PaddingCopyTag(final boolean id3v2PaddingCopyTag) {
305         this.id3v2PaddingCopyTag = id3v2PaddingCopyTag;
306     }
307 
isId3v2PaddingCopyTag()308     public boolean isId3v2PaddingCopyTag() {
309         return this.id3v2PaddingCopyTag;
310     }
311 
312     /**
313      * Sets the factor to increase the id3v2 padding size. When the ID3v2 tag padding length is calculated and is not
314      * large enough to fit the current ID3v2 tag, the padding length will be multiplied by this number until it is large
315      * enough.
316      *
317      * @param mult new factor to increase the id3v2 padding size.
318      */
setId3v2PaddingMultiplier(final float mult)319     public void setId3v2PaddingMultiplier(final float mult) {
320         if (mult > 1) {
321             this.id3v2PaddingMultiplier = mult;
322         }
323     }
324 
325     /**
326      * Returns the factor to increase the id3v2 padding size. When the ID3v2 tag padding length is calculated and is not
327      * large enough to fit the current ID3v2 tag, the padding length will be multiplied by this number until it is large
328      * enough.
329      *
330      * @return the factor to increase the id3v2 padding size
331      */
getId3v2PaddingMultiplier()332     public float getId3v2PaddingMultiplier() {
333         return this.id3v2PaddingMultiplier;
334     }
335 
336     /**
337      * Sets the initial ID3v2 padding length. This will be the minimum padding length of the ID3v2 tag. The
338      * <code>willShorten</code> setting will not make the length shorter than this value.
339      *
340      * @param size the new initial ID3v2 padding length
341      */
setId3v2PaddingSize(final int size)342     public void setId3v2PaddingSize(final int size) {
343         if (size >= 0) {
344             this.id3v2PaddingSize = size;
345         }
346     }
347 
348     /**
349      * Returns the initial ID3v2 padding length. This will be the minimum padding length of the ID3v2 tag. The
350      * <code>willShorten</code> setting will not make the length shorter than this value.
351      *
352      * @return the initial ID3v2 padding length
353      */
getId3v2PaddingSize()354     public int getId3v2PaddingSize() {
355         return this.id3v2PaddingSize;
356     }
357 
setId3v2PaddingWillShorten(final boolean id3v2PaddingWillShorten)358     public void setId3v2PaddingWillShorten(final boolean id3v2PaddingWillShorten) {
359         this.id3v2PaddingWillShorten = id3v2PaddingWillShorten;
360     }
361 
isId3v2PaddingWillShorten()362     public boolean isId3v2PaddingWillShorten() {
363         return this.id3v2PaddingWillShorten;
364     }
365 
setId3v2Save(final boolean id3v2Save)366     public void setId3v2Save(final boolean id3v2Save) {
367         this.id3v2Save = id3v2Save;
368     }
369 
isId3v2Save()370     public boolean isId3v2Save() {
371         return this.id3v2Save;
372     }
373 
setId3v2SaveEmptyFrame(final boolean id3v2SaveEmptyFrame)374     public void setId3v2SaveEmptyFrame(final boolean id3v2SaveEmptyFrame) {
375         this.id3v2SaveEmptyFrame = id3v2SaveEmptyFrame;
376     }
377 
isId3v2SaveEmptyFrame()378     public boolean isId3v2SaveEmptyFrame() {
379         return this.id3v2SaveEmptyFrame;
380     }
381 
setId3v2SaveExtendedHeader(final boolean id3v2SaveExtendedHeader)382     public void setId3v2SaveExtendedHeader(final boolean id3v2SaveExtendedHeader) {
383         this.id3v2SaveExtendedHeader = id3v2SaveExtendedHeader;
384     }
385 
getKeywordIterator()386     public Iterator getKeywordIterator() {
387         return this.keywordMap.keySet().iterator();
388     }
389 
getKeywordListIterator(final Class id3v2_4FrameBody)390     public Iterator getKeywordListIterator(final Class id3v2_4FrameBody) {
391         return ((LinkedList) this.keywordMap.get(id3v2_4FrameBody)).iterator();
392     }
393 
394     /**
395      * Sets the default language for any ID3v2 tag frames which require it. While the value will already exist when
396      * reading from a file, this value will be used when a new ID3v2 Frame is created from scratch.
397      *
398      * @param language language ID, [ISO-639-2] ISO/FDIS 639-2 definition
399      */
setLanguage(final String language)400     public void setLanguage(final String language) {
401         if (TagConstant.languageIdToString.containsKey(language)) {
402             this.language = language;
403         }
404     }
405 
406     /**
407      * Returns the default language for any ID3v2 tag frames which require it.
408      *
409      * @return language ID, [ISO-639-2] ISO/FDIS 639-2 definition
410      */
getLanguage()411     public String getLanguage() {
412         return this.language;
413     }
414 
setLyrics3KeepEmptyFieldIfRead(final boolean lyrics3KeepEmptyFieldIfRead)415     public void setLyrics3KeepEmptyFieldIfRead(final boolean lyrics3KeepEmptyFieldIfRead) {
416         this.lyrics3KeepEmptyFieldIfRead = lyrics3KeepEmptyFieldIfRead;
417     }
418 
isLyrics3KeepEmptyFieldIfRead()419     public boolean isLyrics3KeepEmptyFieldIfRead() {
420         return this.lyrics3KeepEmptyFieldIfRead;
421     }
422 
setLyrics3Save(final boolean lyrics3Save)423     public void setLyrics3Save(final boolean lyrics3Save) {
424         this.lyrics3Save = lyrics3Save;
425     }
426 
isLyrics3Save()427     public boolean isLyrics3Save() {
428         return this.lyrics3Save;
429     }
430 
setLyrics3SaveEmptyField(final boolean lyrics3SaveEmptyField)431     public void setLyrics3SaveEmptyField(final boolean lyrics3SaveEmptyField) {
432         this.lyrics3SaveEmptyField = lyrics3SaveEmptyField;
433     }
434 
isLyrics3SaveEmptyField()435     public boolean isLyrics3SaveEmptyField() {
436         return this.lyrics3SaveEmptyField;
437     }
438 
439     /**
440      * Sets if we should save the Lyrics3 field. Defaults to true.
441      *
442      * @param id   Lyrics3 id string
443      * @param save true if you want to save this specific Lyrics3 field.
444      */
setLyrics3SaveField(final String id, final boolean save)445     public void setLyrics3SaveField(final String id, final boolean save) {
446         this.lyrics3SaveFieldMap.put(id, new Boolean(save));
447     }
448 
449     /**
450      * Returns true if we should save the Lyrics3 field asked for in the argument. Defaults to true.
451      *
452      * @param id Lyrics3 id string
453      *
454      * @return true if we should save the Lyrics3 field.
455      */
getLyrics3SaveField(final String id)456     public boolean getLyrics3SaveField(final String id) {
457         return ((Boolean) this.lyrics3SaveFieldMap.get(id)).booleanValue();
458     }
459 
getLyrics3SaveFieldMap()460     public Map getLyrics3SaveFieldMap() {
461         return this.lyrics3SaveFieldMap;
462     }
463 
getNewReplaceWord(final String oldWord)464     public String getNewReplaceWord(final String oldWord) {
465         return (String) this.replaceWordMap.get(oldWord);
466     }
467 
468     /**
469      * Sets the number of MP3 frames to sync when trying to find the start of the MP3 frame data. The start of the MP3
470      * frame data is the start of the music and is different from the ID3v2 frame data. WinAmp 2.8 seems to sync 3
471      * frames. Default is 5.
472      *
473      * @param numberMP3SyncFrame number of MP3 frames to sync
474      */
setNumberMP3SyncFrame(final int numberMP3SyncFrame)475     public void setNumberMP3SyncFrame(final int numberMP3SyncFrame) {
476         this.numberMP3SyncFrame = numberMP3SyncFrame;
477     }
478 
479     /**
480      * Returns the number of MP3 frames to sync when trying to find the start of the MP3 frame data. The start of the
481      * MP3 frame data is the start of the music and is different from the ID3v2 frame data. WinAmp 2.8 seems to sync 3
482      * frames. Default is 5.
483      *
484      * @return number of MP3 frames to sync
485      */
getNumberMP3SyncFrame()486     public int getNumberMP3SyncFrame() {
487         return this.numberMP3SyncFrame;
488     }
489 
getOldReplaceWordIterator()490     public Iterator getOldReplaceWordIterator() {
491         return this.replaceWordMap.keySet().iterator();
492     }
493 
isOpenParenthesis(final String open)494     public boolean isOpenParenthesis(final String open) {
495         return this.parenthesisMap.containsKey(open);
496     }
497 
getOpenParenthesisIterator()498     public Iterator getOpenParenthesisIterator() {
499         return this.parenthesisMap.keySet().iterator();
500     }
501 
setOriginalSavedAfterAdjustingID3v2Padding(final boolean originalSavedAfterAdjustingID3v2Padding)502     public void setOriginalSavedAfterAdjustingID3v2Padding(final boolean originalSavedAfterAdjustingID3v2Padding) {
503         this.originalSavedAfterAdjustingID3v2Padding = originalSavedAfterAdjustingID3v2Padding;
504     }
505 
isOriginalSavedAfterAdjustingID3v2Padding()506     public boolean isOriginalSavedAfterAdjustingID3v2Padding() {
507         return this.originalSavedAfterAdjustingID3v2Padding;
508     }
509 
510     /**
511      * Sets the default play counter size for the PCNT ID3v2 frame. While the value will already exist when reading from
512      * a file, this value will be used when a new ID3v2 Frame is created from scratch.
513      *
514      * @param size the default play counter size for the PCNT ID3v2 frame
515      */
setPlayCounterSize(final byte size)516     public void setPlayCounterSize(final byte size) {
517         if (size > 0) {
518             this.playCounterSize = size;
519         }
520     }
521 
522     /**
523      * Returns the default play counter size for the PCNT ID3v2 frame.
524      *
525      * @return the default play counter size for the PCNT ID3v2 frame
526      */
getPlayCounterSize()527     public byte getPlayCounterSize() {
528         return this.playCounterSize;
529     }
530 
getStartWordDelimiterIterator()531     public Iterator getStartWordDelimiterIterator() {
532         return this.startWordDelimiterList.iterator();
533     }
534 
535     /**
536      * Sets the default text encoding for any ID3v2 tag frames which require it. While the value will already exist when
537      * reading from a file, this value will be used when a new ID3v2 Frame is created from scratch.
538      * <p/>
539      * <P> $00 ISO-8859-1 [ISO-8859-1]. Terminated with $00. <BR> $01 UTF-16 [UTF-16] encoded Unicode [UNICODE] with
540      * BOM. All strings in the same frame SHALL have the same byteorder. Terminated with $00 00. <BR> $02 UTF-16BE
541      * [UTF-16] encoded Unicode [UNICODE] without BOM. Terminated with $00 00. <BR> $03 UTF-8 [UTF-8] encoded Unicode
542      * [UNICODE]. Terminated with $00. <BR> </p>
543      *
544      * @param enc new default text encoding
545      */
setTextEncoding(final byte enc)546     public void setTextEncoding(final byte enc) {
547         if ((enc >= 0) && (enc <= 3)) {
548             this.textEncoding = enc;
549         }
550     }
551 
552     /**
553      * Returns the default text encoding format for ID3v2 tags which require it.
554      * <p/>
555      * <P> $00 ISO-8859-1 [ISO-8859-1]. Terminated with $00. <BR> $01 UTF-16 [UTF-16] encoded Unicode [UNICODE] with
556      * BOM. All strings in the same frame SHALL have the same byteorder. Terminated with $00 00. <BR> $02 UTF-16BE
557      * [UTF-16] encoded Unicode [UNICODE] without BOM. Terminated with $00 00. <BR> $03 UTF-8 [UTF-8] encoded Unicode
558      * [UNICODE]. Terminated with $00. <BR> </p>
559      *
560      * @return the default text encoding
561      */
getTextEncoding()562     public byte getTextEncoding() {
563         return this.textEncoding;
564     }
565 
566     /**
567      * Sets the default time stamp format for ID3v2 tags which require it. While the value will already exist when
568      * reading from a file, this value will be used when a new ID3v2 Frame is created from scratch.
569      * <p/>
570      * <P> $01 Absolute time, 32 bit sized, using MPEG frames as unit <br> $02 Absolute time, 32 bit sized, using
571      * milliseconds as unit <br> </p>
572      *
573      * @param tsf the new default time stamp format
574      */
setTimeStampFormat(final byte tsf)575     public void setTimeStampFormat(final byte tsf) {
576         if ((tsf == 1) || (tsf == 2)) {
577             this.timeStampFormat = tsf;
578         }
579     }
580 
581     /**
582      * Returns the default time stamp format for ID3v2 tags which require it.
583      * <p/>
584      * <P> $01 Absolute time, 32 bit sized, using MPEG frames as unit <br> $02 Absolute time, 32 bit sized, using
585      * milliseconds as unit <br> </p>
586      *
587      * @return the default time stamp format
588      */
getTimeStampFormat()589     public byte getTimeStampFormat() {
590         return this.timeStampFormat;
591     }
592 
setToDefault()593     public void setToDefault() {
594         this.keywordMap = new HashMap();
595         this.compositeMatchOverwrite = false;
596         this.defaultSaveMode = TagConstant.MP3_FILE_SAVE_WRITE;
597         this.endWordDelimiterList = new LinkedList();
598         this.filenameDelimiterList = new LinkedList();
599         this.filenameTagSave = false;
600         this.id3v1Save = true;
601         this.id3v1SaveAlbum = true;
602         this.id3v1SaveArtist = true;
603         this.id3v1SaveComment = true;
604         this.id3v1SaveGenre = true;
605         this.id3v1SaveTitle = true;
606         this.id3v1SaveTrack = true;
607         this.id3v1SaveYear = true;
608         this.id3v2KeepEmptyFrameIfRead = false;
609         this.id3v2PaddingCopyTag = true;
610         this.id3v2PaddingWillShorten = false;
611         this.id3v2Save = true;
612         this.id3v2SaveEmptyFrame = false;
613         this.id3v2SaveExtendedHeader = false;
614         this.id3v2PaddingMultiplier = 2;
615         this.id3v2PaddingSize = 2048;
616         this.language = "eng";
617         this.lyrics3KeepEmptyFieldIfRead = false;
618         this.lyrics3Save = true;
619         this.lyrics3SaveEmptyField = false;
620         this.lyrics3SaveFieldMap = new HashMap();
621         this.numberMP3SyncFrame = 5;
622         this.parenthesisMap = new HashMap();
623         this.playCounterSize = 4;
624         this.replaceWordMap = new HashMap();
625         this.startWordDelimiterList = new LinkedList();
626         this.textEncoding = 0;
627         this.timeStampFormat = 2;
628         this.upperLowerCaseWordList = new LinkedList();
629 
630         /**
631          * default all lyrics3 fields to save. id3v1 fields are individual
632          * settings. id3v2 fields are always looked at to save.
633          */
634         Iterator iterator = TagConstant.lyrics3v2FieldIdToString.keySet().iterator();
635         String fieldId;
636         while (iterator.hasNext()) {
637             fieldId = (String) iterator.next();
638             this.lyrics3SaveFieldMap.put(fieldId, new Boolean(true));
639         }
640         try {
641             addKeyword(FrameBodyCOMM.class, "ultimix");
642             addKeyword(FrameBodyCOMM.class, "dance");
643             addKeyword(FrameBodyCOMM.class, "mix");
644             addKeyword(FrameBodyCOMM.class, "remix");
645             addKeyword(FrameBodyCOMM.class, "rmx");
646             addKeyword(FrameBodyCOMM.class, "live");
647             addKeyword(FrameBodyCOMM.class, "cover");
648             addKeyword(FrameBodyCOMM.class, "soundtrack");
649             addKeyword(FrameBodyCOMM.class, "version");
650             addKeyword(FrameBodyCOMM.class, "acoustic");
651             addKeyword(FrameBodyCOMM.class, "original");
652             addKeyword(FrameBodyCOMM.class, "cd");
653             addKeyword(FrameBodyCOMM.class, "extended");
654             addKeyword(FrameBodyCOMM.class, "vocal");
655             addKeyword(FrameBodyCOMM.class, "unplugged");
656             addKeyword(FrameBodyCOMM.class, "acapella");
657             addKeyword(FrameBodyCOMM.class, "edit");
658             addKeyword(FrameBodyCOMM.class, "radio");
659             addKeyword(FrameBodyCOMM.class, "original");
660             addKeyword(FrameBodyCOMM.class, "album");
661             addKeyword(FrameBodyCOMM.class, "studio");
662             addKeyword(FrameBodyCOMM.class, "instrumental");
663             addKeyword(FrameBodyCOMM.class, "unedited");
664             addKeyword(FrameBodyCOMM.class, "karoke");
665             addKeyword(FrameBodyCOMM.class, "quality");
666             addKeyword(FrameBodyCOMM.class, "uncensored");
667             addKeyword(FrameBodyCOMM.class, "clean");
668             addKeyword(FrameBodyCOMM.class, "dirty");
669             addKeyword(FrameBodyTIPL.class, "f.");
670             addKeyword(FrameBodyTIPL.class, "feat");
671             addKeyword(FrameBodyTIPL.class, "feat.");
672             addKeyword(FrameBodyTIPL.class, "featuring");
673             addKeyword(FrameBodyTIPL.class, "ftng");
674             addKeyword(FrameBodyTIPL.class, "ftng.");
675             addKeyword(FrameBodyTIPL.class, "ft.");
676             addKeyword(FrameBodyTIPL.class, "ft");
677             iterator = TagConstant.genreStringToId.keySet().iterator();
678             while (iterator.hasNext()) {
679                 addKeyword(FrameBodyCOMM.class, (String) iterator.next());
680             }
681         } catch (TagException ex) {
682             // this shouldn't happen. if it does, we should fix it right away.
683             ex.printStackTrace();
684         }
685         addUpperLowerCaseWord("a");
686         addUpperLowerCaseWord("in");
687         addUpperLowerCaseWord("of");
688         addUpperLowerCaseWord("the");
689         addUpperLowerCaseWord("on");
690         addUpperLowerCaseWord("is");
691         addUpperLowerCaseWord("it");
692         addUpperLowerCaseWord("to");
693         addUpperLowerCaseWord("at");
694         addUpperLowerCaseWord("an");
695         addUpperLowerCaseWord("and");
696         addUpperLowerCaseWord("but");
697         addUpperLowerCaseWord("or");
698         addUpperLowerCaseWord("for");
699         addUpperLowerCaseWord("nor");
700         addUpperLowerCaseWord("not");
701         addUpperLowerCaseWord("so");
702         addUpperLowerCaseWord("yet");
703         addUpperLowerCaseWord("with");
704         addUpperLowerCaseWord("into");
705         addUpperLowerCaseWord("by");
706         addUpperLowerCaseWord("up");
707         addUpperLowerCaseWord("as");
708         addUpperLowerCaseWord("if");
709         addUpperLowerCaseWord("feat.");
710         addUpperLowerCaseWord("vs.");
711         addUpperLowerCaseWord("I'm");
712         addUpperLowerCaseWord("I");
713         addUpperLowerCaseWord("I've");
714         addUpperLowerCaseWord("I'll");
715         addReplaceWord("v.", "vs.");
716         addReplaceWord("vs.", "vs.");
717         addReplaceWord("versus", "vs.");
718         addReplaceWord("f.", "feat.");
719         addReplaceWord("feat", "feat.");
720         addReplaceWord("featuring", "feat.");
721         addReplaceWord("ftng.", "feat.");
722         addReplaceWord("ftng", "feat.");
723         addReplaceWord("ft.", "feat.");
724         addReplaceWord("ft", "feat.");
725         addFilenameDelimiter("/");
726         addFilenameDelimiter("\\");
727         addFilenameDelimiter(" -");
728         addFilenameDelimiter(";");
729         addFilenameDelimiter("|");
730         addFilenameDelimiter(":");
731         iterator = this.getKeywordListIterator(FrameBodyTIPL.class);
732         while (iterator.hasNext()) {
733             addStartWordDelimiter((String) iterator.next());
734         }
735         addParenthesis("(", ")");
736         addParenthesis("[", "]");
737         addParenthesis("{", "}");
738         addParenthesis("<", ">");
739     }
740 
getUpperLowerCaseWordListIterator()741     public Iterator getUpperLowerCaseWordListIterator() {
742         return this.upperLowerCaseWordList.iterator();
743     }
744 
addEndWordDelimiter(final String wordDelimiter)745     public void addEndWordDelimiter(final String wordDelimiter) {
746         this.endWordDelimiterList.add(wordDelimiter);
747     }
748 
addFilenameDelimiter(final String delimiter)749     public void addFilenameDelimiter(final String delimiter) {
750         this.filenameDelimiterList.add(delimiter);
751     }
752 
addKeyword(final Class id3v2FrameBodyClass, final String keyword)753     public void addKeyword(final Class id3v2FrameBodyClass, final String keyword) throws TagException {
754         if (AbstractID3v2FrameBody.class.isAssignableFrom(id3v2FrameBodyClass) == false) {
755             throw new TagException("Invalid class type. Must be AbstractId3v2FrameBody " + id3v2FrameBodyClass);
756         }
757         if ((keyword != null) && (keyword.length() > 0)) {
758             final LinkedList keywordList;
759             if (this.keywordMap.containsKey(id3v2FrameBodyClass) == false) {
760                 keywordList = new LinkedList();
761                 this.keywordMap.put(id3v2FrameBodyClass, keywordList);
762             } else {
763                 keywordList = (LinkedList) this.keywordMap.get(id3v2FrameBodyClass);
764             }
765             keywordList.add(keyword);
766         }
767     }
768 
addParenthesis(final String open, final String close)769     public void addParenthesis(final String open, final String close) {
770         this.parenthesisMap.put(open, close);
771     }
772 
addReplaceWord(final String oldWord, final String newWord)773     public void addReplaceWord(final String oldWord, final String newWord) {
774         this.replaceWordMap.put(oldWord, newWord);
775     }
776 
addStartWordDelimiter(final String wordDelimiter)777     public void addStartWordDelimiter(final String wordDelimiter) {
778         this.startWordDelimiterList.add(wordDelimiter);
779     }
780 
addUpperLowerCaseWord(final String word)781     public void addUpperLowerCaseWord(final String word) {
782         this.upperLowerCaseWordList.add(word);
783     }
784 }