Methods Summary |
---|
public void | addField(FieldKey genericKey, java.lang.String value)
TagField tagfield = createField(genericKey, value);
addField(tagfield);
|
public void | addField(TagField field)Add new field
There is a special handling if adding another text field of the same type, in this case the value will
be appended to the existing field, separated by the null character.
if (field == null)
{
return;
}
if (!(field instanceof AbstractID3v2Frame))
{
throw new FieldDataInvalidException("Field " + field + " is not of type AbstractID3v2Frame");
}
AbstractID3v2Frame frame = (AbstractID3v2Frame) field;
Object o = frameMap.get(field.getId());
//No frame of this type
if (o == null)
{
frameMap.put(field.getId(), field);
}
//There are already frames of this type
else if (o instanceof List)
{
List<TagField> list = (List<TagField>) o;
addNewFrameOrAddField(list, frameMap, null, frame);
}
//One frame exists, we are adding another so may need to convert to list
else
{
AbstractID3v2Frame existingFrame = (AbstractID3v2Frame) o;
List<TagField> list = new ArrayList<TagField>();
addNewFrameOrAddField(list, frameMap, existingFrame, frame);
}
|
public void | addField(org.jaudiotagger.tag.images.Artwork artwork)Create field and then set within tag itself
this.addField(createField(artwork));
|
protected abstract void | addFrame(AbstractID3v2Frame frame)
|
private void | addNewFrameOrAddField(java.util.List list, java.util.HashMap frameMap, AbstractID3v2Frame existingFrame, AbstractID3v2Frame frame)Handles adding of a new field that's shares a frame with other fields, so modifies the existing frame rather
than creating an ew frame for these special cases
/**
* If the frame is a TextInformation (but not the TXXX) frame then we just add an extra string to the existing frame
* otherwise we create a new frame
*/
if (frame.getBody() instanceof AbstractFrameBodyTextInfo && !(frame.getBody() instanceof FrameBodyTXXX))
{
AbstractFrameBodyTextInfo frameBody = (AbstractFrameBodyTextInfo) frame.getBody();
AbstractFrameBodyTextInfo existingFrameBody = (AbstractFrameBodyTextInfo) existingFrame.getBody();
existingFrameBody.addTextValue(frameBody.getText());
}
else if (frame.getBody() instanceof FrameBodyIPLS)
{
FrameBodyIPLS frameBody = (FrameBodyIPLS) frame.getBody();
FrameBodyIPLS existingFrameBody = (FrameBodyIPLS) existingFrame.getBody();
existingFrameBody.addPair(frameBody.getText());
}
else if (frame.getBody() instanceof FrameBodyTIPL)
{
FrameBodyTIPL frameBody = (FrameBodyTIPL) frame.getBody();
FrameBodyTIPL existingFrameBody = (FrameBodyTIPL) existingFrame.getBody();
existingFrameBody.addPair(frameBody.getText());
}
else
{
if (list.size() == 0)
{
list.add(existingFrame);
list.add(frame);
frameMap.put(frame.getId(), list);
}
else
{
list.add(frame);
}
}
|
public void | adjustPadding(java.io.File file, int paddingSize, long audioStart)Adjust the length of the padding at the beginning of the MP3 file, this is only called when there is currently
not enough space before the start of the audio to write the tag.
A new file will be created with enough size to fit the ID3v2 tag.
The old file will be deleted, and the new file renamed.
logger.finer("Need to move audio file to accommodate tag");
FileChannel fcIn = null;
FileChannel fcOut;
//Create buffer holds the necessary padding
ByteBuffer paddingBuffer = ByteBuffer.wrap(new byte[paddingSize]);
//Create Temporary File and write channel, make sure it is locked
File paddedFile;
try
{
paddedFile = File.createTempFile(Utils.getBaseFilenameForTempFile(file), ".new", file.getParentFile());
logger.finest("Created temp file:" + paddedFile.getName() + " for " + file.getName());
}
//Vista:Can occur if have Write permission on folder this file would be created in Denied
catch (IOException ioe)
{
logger.log(Level.SEVERE, ioe.getMessage(), ioe);
if (ioe.getMessage().equals(FileSystemMessage.ACCESS_IS_DENIED.getMsg()))
{
logger.severe(ErrorMessage.GENERAL_WRITE_FAILED_TO_CREATE_TEMPORARY_FILE_IN_FOLDER.getMsg(file.getName(), file.getParentFile().getPath()));
throw new UnableToCreateFileException(ErrorMessage.GENERAL_WRITE_FAILED_TO_CREATE_TEMPORARY_FILE_IN_FOLDER.getMsg(file.getName(), file.getParentFile().getPath()));
}
else
{
logger.severe(ErrorMessage.GENERAL_WRITE_FAILED_TO_CREATE_TEMPORARY_FILE_IN_FOLDER.getMsg(file.getName(), file.getParentFile().getPath()));
throw new UnableToCreateFileException(ErrorMessage.GENERAL_WRITE_FAILED_TO_CREATE_TEMPORARY_FILE_IN_FOLDER.getMsg(file.getName(), file.getParentFile().getPath()));
}
}
try
{
fcOut = new FileOutputStream(paddedFile).getChannel();
}
//Vista:Can occur if have special permission Create Folder/Append Data denied
catch (FileNotFoundException ioe)
{
logger.log(Level.SEVERE, ioe.getMessage(), ioe);
logger.severe(ErrorMessage.GENERAL_WRITE_FAILED_TO_MODIFY_TEMPORARY_FILE_IN_FOLDER.getMsg(file.getName(), file.getParentFile().getPath()));
throw new UnableToModifyFileException(ErrorMessage.GENERAL_WRITE_FAILED_TO_MODIFY_TEMPORARY_FILE_IN_FOLDER.getMsg(file.getName(), file.getParentFile().getPath()));
}
try
{
//Create read channel from original file
//TODO lock so cant be modified by anything else whilst reading from it ?
fcIn = new FileInputStream(file).getChannel();
//Write padding to new file (this is where the tag will be written to later)
long written = fcOut.write(paddingBuffer);
//Write rest of file starting from audio
logger.finer("Copying:" + (file.length() - audioStart) + "bytes");
//If the amount to be copied is very large we split into 10MB lumps to try and avoid
//out of memory errors
long audiolength = file.length() - audioStart;
if (audiolength <= MAXIMUM_WRITABLE_CHUNK_SIZE)
{
fcIn.position(audioStart);
long written2 = fcOut.transferFrom(fcIn, paddingSize, audiolength);
logger.finer("Written padding:" + written + " Data:" + written2);
if (written2 != audiolength)
{
throw new RuntimeException(ErrorMessage.MP3_UNABLE_TO_ADJUST_PADDING.getMsg(audiolength, written2));
}
}
else
{
long noOfChunks = audiolength / MAXIMUM_WRITABLE_CHUNK_SIZE;
long lastChunkSize = audiolength % MAXIMUM_WRITABLE_CHUNK_SIZE;
long written2 = 0;
for (int i = 0; i < noOfChunks; i++)
{
written2 += fcIn.transferTo(audioStart + (i * MAXIMUM_WRITABLE_CHUNK_SIZE), MAXIMUM_WRITABLE_CHUNK_SIZE, fcOut);
}
written2 += fcIn.transferTo(audioStart + (noOfChunks * MAXIMUM_WRITABLE_CHUNK_SIZE), lastChunkSize, fcOut);
logger.finer("Written padding:" + written + " Data:" + written2);
if (written2 != audiolength)
{
throw new RuntimeException(ErrorMessage.MP3_UNABLE_TO_ADJUST_PADDING.getMsg(audiolength, written2));
}
}
//Store original modification time
long lastModified = file.lastModified();
//Close Channels and locks
if (fcIn != null)
{
if (fcIn.isOpen())
{
fcIn.close();
}
}
if (fcOut != null)
{
if (fcOut.isOpen())
{
fcOut.close();
}
}
//Replace file with paddedFile
replaceFile(file, paddedFile);
//Update modification time
//TODO is this the right file ?
paddedFile.setLastModified(lastModified);
}
catch(UnableToRenameFileException ure)
{
paddedFile.delete();
throw ure;
}
finally
{
try
{
//Whatever happens ensure all locks and channels are closed/released
if (fcIn != null)
{
if (fcIn.isOpen())
{
fcIn.close();
}
}
if (fcOut != null)
{
if (fcOut.isOpen())
{
fcOut.close();
}
}
}
catch (Exception e)
{
logger.log(Level.WARNING, "Problem closing channels and locks:" + e.getMessage(), e);
}
}
|
protected int | calculateTagSize(int tagSize, int audioStart)This method determines the total tag size taking into account
where the audio file starts, the size of the tagging data and
user options for defining how tags should shrink or grow.
/** We can fit in the tag so no adjustments required */
if (tagSize <= audioStart)
{
return audioStart;
}
/** There is not enough room as we need to move the audio file we might
* as well increase it more than neccessary for future changes
*/
return tagSize + TAG_SIZE_INCREMENT;
|
protected void | copyFrameIntoMap(java.lang.String id, AbstractID3v2Frame newFrame)
if (frameMap.containsKey(newFrame.getIdentifier()))
{
Object o = frameMap.get(newFrame.getIdentifier());
if (o instanceof AbstractID3v2Frame)
{
List<AbstractID3v2Frame> list = new ArrayList<AbstractID3v2Frame>();
list.add((AbstractID3v2Frame) o);
list.add(newFrame);
frameMap.put(newFrame.getIdentifier(), list);
}
else
{
List<AbstractID3v2Frame> list = (List) o;
list.add(newFrame);
}
}
else
{
frameMap.put(newFrame.getIdentifier(), newFrame);
}
|
protected void | copyFrames(org.jaudiotagger.tag.id3.AbstractID3v2Tag copyObject)Copy frames from another tag,
frameMap = new LinkedHashMap();
encryptedFrameMap = new LinkedHashMap();
//Copy Frames that are a valid 2.4 type
for (Object o1 : copyObject.frameMap.keySet())
{
String id = (String) o1;
Object o = copyObject.frameMap.get(id);
//SingleFrames
if (o instanceof AbstractID3v2Frame)
{
addFrame((AbstractID3v2Frame) o);
}
//MultiFrames
else if (o instanceof ArrayList)
{
for (AbstractID3v2Frame frame : (ArrayList<AbstractID3v2Frame>) o)
{
addFrame(frame);
}
}
}
|
protected void | copyPrimitives(org.jaudiotagger.tag.id3.AbstractID3v2Tag copyObject)Copy primitives apply to all tags
logger.config("Copying Primitives");
//Primitives type variables common to all IDv2 Tags
this.duplicateFrameId = copyObject.duplicateFrameId;
this.duplicateBytes = copyObject.duplicateBytes;
this.emptyFrameBytes = copyObject.emptyFrameBytes;
this.fileReadSize = copyObject.fileReadSize;
this.invalidFrames = copyObject.invalidFrames;
|
public TagField | createField(FieldKey genericKey, java.lang.String value)Create a new TagField
Only textual data supported at the moment. The genericKey will be mapped
to the correct implementation key and return a TagField.
if (genericKey == null)
{
throw new KeyNotFoundException();
}
FrameAndSubId formatKey = getFrameAndSubIdFromGenericKey(genericKey);
if (genericKey == FieldKey.TRACK)
{
AbstractID3v2Frame frame = createFrame(formatKey.getFrameId());
FrameBodyTRCK framebody = (FrameBodyTRCK) frame.getBody();
framebody.setTrackNo(Integer.parseInt(value));
return frame;
}
else if (genericKey == FieldKey.TRACK_TOTAL)
{
AbstractID3v2Frame frame = createFrame(formatKey.getFrameId());
FrameBodyTRCK framebody = (FrameBodyTRCK) frame.getBody();
framebody.setTrackTotal(Integer.parseInt(value));
return frame;
}
else if (genericKey == FieldKey.DISC_NO)
{
AbstractID3v2Frame frame = createFrame(formatKey.getFrameId());
FrameBodyTPOS framebody = (FrameBodyTPOS) frame.getBody();
framebody.setDiscNo(Integer.parseInt(value));
return frame;
}
else if (genericKey == FieldKey.DISC_TOTAL)
{
AbstractID3v2Frame frame = createFrame(formatKey.getFrameId());
FrameBodyTPOS framebody = (FrameBodyTPOS) frame.getBody();
framebody.setDiscTotal(Integer.parseInt(value));
return frame;
}
else
{
return doCreateTagField(formatKey, value);
}
|
public abstract AbstractID3v2Frame | createFrame(java.lang.String id)Create Frame of correct ID3 version with the specified id
|
public TagField | createLinkedArtworkField(java.lang.String url)Create a link to artwork, this is not recommended because the link may be broken if the mp3 or image
file is moved
AbstractID3v2Frame frame = createFrame(getFrameAndSubIdFromGenericKey(FieldKey.COVER_ART).getFrameId());
if (frame.getBody() instanceof FrameBodyAPIC)
{
FrameBodyAPIC body = (FrameBodyAPIC) frame.getBody();
body.setObjectValue(DataTypes.OBJ_PICTURE_DATA, Utils.getDefaultBytes(url, TextEncoding.CHARSET_ISO_8859_1));
body.setObjectValue(DataTypes.OBJ_PICTURE_TYPE, PictureTypes.DEFAULT_ID);
body.setObjectValue(DataTypes.OBJ_MIME_TYPE, FrameBodyAPIC.IMAGE_IS_URL);
body.setObjectValue(DataTypes.OBJ_DESCRIPTION, "");
}
else if (frame.getBody() instanceof FrameBodyPIC)
{
FrameBodyPIC body = (FrameBodyPIC) frame.getBody();
body.setObjectValue(DataTypes.OBJ_PICTURE_DATA, Utils.getDefaultBytes(url, TextEncoding.CHARSET_ISO_8859_1));
body.setObjectValue(DataTypes.OBJ_PICTURE_TYPE, PictureTypes.DEFAULT_ID);
body.setObjectValue(DataTypes.OBJ_IMAGE_FORMAT, FrameBodyAPIC.IMAGE_IS_URL);
body.setObjectValue(DataTypes.OBJ_DESCRIPTION, "");
}
return frame;
|
public void | createStructure()
createStructureHeader();
createStructureBody();
|
public void | createStructureBody()
MP3File.getStructureFormatter().openHeadingElement(TYPE_BODY, "");
AbstractID3v2Frame frame;
for (Object o : frameMap.values())
{
if (o instanceof AbstractID3v2Frame)
{
frame = (AbstractID3v2Frame) o;
frame.createStructure();
}
else
{
ArrayList<AbstractID3v2Frame> multiFrames = (ArrayList<AbstractID3v2Frame>) o;
for (ListIterator<AbstractID3v2Frame> li = multiFrames.listIterator(); li.hasNext();)
{
frame = li.next();
frame.createStructure();
}
}
}
MP3File.getStructureFormatter().closeHeadingElement(TYPE_BODY);
|
public void | createStructureHeader()
MP3File.getStructureFormatter().addElement(TYPE_DUPLICATEBYTES, this.duplicateBytes);
MP3File.getStructureFormatter().addElement(TYPE_DUPLICATEFRAMEID, this.duplicateFrameId);
MP3File.getStructureFormatter().addElement(TYPE_EMPTYFRAMEBYTES, this.emptyFrameBytes);
MP3File.getStructureFormatter().addElement(TYPE_FILEREADSIZE, this.fileReadSize);
MP3File.getStructureFormatter().addElement(TYPE_INVALIDFRAMES, this.invalidFrames);
|
public void | delete(java.io.RandomAccessFile file)Delete Tag
// this works by just erasing the "ID3" tag at the beginning
// of the file
byte[] buffer = new byte[FIELD_TAGID_LENGTH];
//Read into Byte Buffer
final FileChannel fc = file.getChannel();
fc.position();
ByteBuffer byteBuffer = ByteBuffer.allocate(TAG_HEADER_LENGTH);
fc.read(byteBuffer, 0);
byteBuffer.flip();
if (seek(byteBuffer))
{
file.seek(0L);
file.write(buffer);
}
|
public void | deleteArtworkField()Delete all instance of artwork Field
this.deleteField(FieldKey.COVER_ART);
|
public void | deleteField(FieldKey genericKey)Delete fields with this generic key
if (genericKey == null)
{
throw new KeyNotFoundException();
}
FrameAndSubId formatKey = getFrameAndSubIdFromGenericKey(genericKey);
doDeleteTagField(formatKey);
|
protected TagField | doCreateTagField(org.jaudiotagger.tag.id3.AbstractID3v2Tag$FrameAndSubId formatKey, java.lang.String value)Create Frame for Id3 Key
Only textual data supported at the moment, should only be used with frames that
support a simple string argument.
AbstractID3v2Frame frame = createFrame(formatKey.getFrameId());
if (frame.getBody() instanceof FrameBodyUFID)
{
((FrameBodyUFID) frame.getBody()).setOwner(formatKey.getSubId());
try
{
((FrameBodyUFID) frame.getBody()).setUniqueIdentifier(value.getBytes("ISO-8859-1"));
}
catch (UnsupportedEncodingException uee)
{
//This will never happen because we are using a charset supported on all platforms
//but just in case
throw new RuntimeException("When encoding UFID charset ISO-8859-1 was deemed unsupported");
}
}
else if (frame.getBody() instanceof FrameBodyTXXX)
{
((FrameBodyTXXX) frame.getBody()).setDescription(formatKey.getSubId());
((FrameBodyTXXX) frame.getBody()).setText(value);
}
else if (frame.getBody() instanceof FrameBodyWXXX)
{
((FrameBodyWXXX) frame.getBody()).setDescription(formatKey.getSubId());
((FrameBodyWXXX) frame.getBody()).setUrlLink(value);
}
else if (frame.getBody() instanceof FrameBodyCOMM)
{
//Set description if set
if (formatKey.getSubId() != null)
{
((FrameBodyCOMM) frame.getBody()).setDescription(formatKey.getSubId());
//Special Handling for Media Monkey Compatability
if (((FrameBodyCOMM) frame.getBody()).isMediaMonkeyFrame())
{
((FrameBodyCOMM) frame.getBody()).setLanguage(Languages.MEDIA_MONKEY_ID);
}
}
((FrameBodyCOMM) frame.getBody()).setText(value);
}
else if (frame.getBody() instanceof FrameBodyUSLT)
{
((FrameBodyUSLT) frame.getBody()).setDescription("");
((FrameBodyUSLT) frame.getBody()).setLyric(value);
}
else if (frame.getBody() instanceof FrameBodyWOAR)
{
((FrameBodyWOAR) frame.getBody()).setUrlLink(value);
}
else if (frame.getBody() instanceof AbstractFrameBodyTextInfo)
{
((AbstractFrameBodyTextInfo) frame.getBody()).setText(value);
}
else if (frame.getBody() instanceof FrameBodyPOPM)
{
((FrameBodyPOPM) frame.getBody()).parseString(value);
}
else if (frame.getBody() instanceof FrameBodyIPLS)
{
PairedTextEncodedStringNullTerminated.ValuePairs pair = new PairedTextEncodedStringNullTerminated.ValuePairs();
pair.add(formatKey.getSubId(), value);
frame.getBody().setObjectValue(DataTypes.OBJ_TEXT, pair);
}
else if (frame.getBody() instanceof FrameBodyTIPL)
{
PairedTextEncodedStringNullTerminated.ValuePairs pair = new PairedTextEncodedStringNullTerminated.ValuePairs();
pair.add(formatKey.getSubId(), value);
frame.getBody().setObjectValue(DataTypes.OBJ_TEXT, pair);
}
else if ((frame.getBody() instanceof FrameBodyAPIC) || (frame.getBody() instanceof FrameBodyPIC))
{
throw new UnsupportedOperationException(ErrorMessage.ARTWORK_CANNOT_BE_CREATED_WITH_THIS_METHOD.getMsg());
}
else
{
throw new FieldDataInvalidException("Field with key of:" + formatKey.getFrameId() + ":does not accept cannot parse data:" + value);
}
return frame;
|
protected void | doDeleteTagField(org.jaudiotagger.tag.id3.AbstractID3v2Tag$FrameAndSubId formatKey)Internal delete method
//Simple 1 to 1 mapping
if (formatKey.getSubId() == null)
{
removeFrame(formatKey.getFrameId());
}
else
{
//Get list of frames that this uses
List<TagField> list = getFields(formatKey.getFrameId());
ListIterator<TagField> li = list.listIterator();
while (li.hasNext())
{
AbstractTagFrameBody next = ((AbstractID3v2Frame) li.next()).getBody();
if (next instanceof FrameBodyTXXX)
{
if (((FrameBodyTXXX) next).getDescription().equals(formatKey.getSubId()))
{
if(list.size()==1)
{
removeFrame(formatKey.getFrameId());
}
else
{
li.remove();
}
}
}
else if (next instanceof FrameBodyWXXX)
{
if (((FrameBodyWXXX) next).getDescription().equals(formatKey.getSubId()))
{
if(list.size()==1)
{
removeFrame(formatKey.getFrameId());
}
else
{
li.remove();
}
}
}
else if (next instanceof FrameBodyUFID)
{
if (Arrays.equals(((FrameBodyUFID) next).getUniqueIdentifier(), formatKey.getSubId().getBytes()))
{
if(list.size()==1)
{
removeFrame(formatKey.getFrameId());
}
else
{
li.remove();
}
}
}
//A single TIPL frame is used for multiple fields, so we just delete the matching pair rather than
//deleting the frame itself unless now empty
else if (next instanceof FrameBodyTIPL)
{
PairedTextEncodedStringNullTerminated.ValuePairs pairs = ((FrameBodyTIPL) next).getPairing();
ListIterator<Pair> pairIterator = pairs.getMapping().listIterator();
while(pairIterator.hasNext())
{
Pair nextPair = pairIterator.next();
if(nextPair.getKey().equals(formatKey.getSubId()))
{
pairIterator.remove();
}
}
if(pairs.getMapping().size()==0)
{
removeFrame(formatKey.getFrameId());
}
}
//A single IPLS frame is used for multiple fields, so we just delete the matching pair rather than
//deleting the frame itself unless now empty
else if (next instanceof FrameBodyIPLS)
{
PairedTextEncodedStringNullTerminated.ValuePairs pairs = ((FrameBodyIPLS) next).getPairing();
ListIterator<Pair> pairIterator = pairs.getMapping().listIterator();
while(pairIterator.hasNext())
{
Pair nextPair = pairIterator.next();
if(nextPair.getKey().equals(formatKey.getSubId()))
{
pairIterator.remove();
}
}
if(pairs.getMapping().size()==0)
{
removeFrame(formatKey.getFrameId());
}
}
else
{
throw new RuntimeException("Need to implement getFields(FieldKey genericKey) for:" + next.getClass());
}
}
}
|
protected java.lang.String | doGetValueAtIndex(org.jaudiotagger.tag.id3.AbstractID3v2Tag$FrameAndSubId formatKey, int index)
//Simple 1 to 1 mapping
if (formatKey.getSubId() == null)
{
List<TagField> list = getFields(formatKey.getFrameId());
if (list.size() > index)
{
return getTextValueForFrame((AbstractID3v2Frame) list.get(index));
}
}
else
{
//Get list of frames that this uses
List<TagField> list = getFields(formatKey.getFrameId());
ListIterator<TagField> li = list.listIterator();
List<String> listOfMatches = new ArrayList<String>();
while (li.hasNext())
{
AbstractTagFrameBody next = ((AbstractID3v2Frame) li.next()).getBody();
if (next instanceof FrameBodyTXXX)
{
if (((FrameBodyTXXX) next).getDescription().equals(formatKey.getSubId()))
{
listOfMatches.add(((FrameBodyTXXX) next).getText());
}
}
else if (next instanceof FrameBodyWXXX)
{
if (((FrameBodyWXXX) next).getDescription().equals(formatKey.getSubId()))
{
listOfMatches.add(((FrameBodyWXXX) next).getUrlLink());
}
}
else if (next instanceof FrameBodyCOMM)
{
if (((FrameBodyCOMM) next).getDescription().equals(formatKey.getSubId()))
{
listOfMatches.add(((FrameBodyCOMM) next).getText());
}
}
else if (next instanceof FrameBodyUFID)
{
if (Arrays.equals(((FrameBodyUFID) next).getUniqueIdentifier(), formatKey.getSubId().getBytes()))
{
listOfMatches.add(new String(((FrameBodyUFID) next).getUniqueIdentifier()));
}
}
else if (next instanceof FrameBodyIPLS)
{
for (Pair entry : ((FrameBodyIPLS) next).getPairing().getMapping())
{
if (entry.getKey().equals(formatKey.getSubId()))
{
listOfMatches.add(entry.getValue());
}
}
}
else if (next instanceof FrameBodyTIPL)
{
for (Pair entry : ((FrameBodyTIPL) next).getPairing().getMapping())
{
if (entry.getKey().equals(formatKey.getSubId()))
{
listOfMatches.add(entry.getValue());
}
}
}
else
{
throw new RuntimeException("Need to implement getFields(FieldKey genericKey) for:" + next.getClass());
}
}
if (listOfMatches.size() > index)
{
return listOfMatches.get(index);
}
else
{
return "";
}
}
return "";
|
public boolean | equals(java.lang.Object obj)Is this tag equivalent to another
if (!(obj instanceof AbstractID3v2Tag))
{
return false;
}
AbstractID3v2Tag object = (AbstractID3v2Tag) obj;
return this.frameMap.equals(object.frameMap) && super.equals(obj);
|
public int | getDuplicateBytes()Returns the number of bytes which come from duplicate frames
return duplicateBytes;
|
public java.lang.String | getDuplicateFrameId()Return the string which holds the ids of all
duplicate frames.
return duplicateFrameId;
|
public int | getEmptyFrameBytes()Returns the number of bytes which come from empty frames
return emptyFrameBytes;
|
public java.lang.Object | getEncryptedFrame(java.lang.String identifier)Return any encrypted frames with this identifier
For single frames return the frame in this tag with given identifier if it exists, if multiple frames
exist with the same identifier it will return a list containing all the frames with this identifier
return encryptedFrameMap.get(identifier);
|
public int | getFieldCount()Count number of frames/fields in this tag
Iterator<TagField> it = getFields();
int count = 0;
//Done this way because it.hasNext() incorrectly counts empty list
//whereas it.next() works correctly
try
{
while (true)
{
TagField next = it.next();
count++;
}
}
catch (NoSuchElementException nse)
{
//this is thrown when no more elements
}
return count;
|
public int | getFieldCountIncludingSubValues()Return count of fields, this considers a text frame with two null separated values as two fields, if you want
a count of frames @see getFrameCount
Iterator<TagField> it = getFields();
int count = 0;
//Done this way because it.hasNext() incorrectly counts empty list
//whereas it.next() works correctly
try
{
while (true)
{
TagField next = it.next();
if (next instanceof AbstractID3v2Frame)
{
AbstractID3v2Frame frame = (AbstractID3v2Frame) next;
if ((frame.getBody() instanceof AbstractFrameBodyTextInfo) && !(frame.getBody() instanceof FrameBodyTXXX))
{
AbstractFrameBodyTextInfo frameBody = (AbstractFrameBodyTextInfo) frame.getBody();
count += frameBody.getNumberOfValues();
continue;
}
}
count++;
}
}
catch (NoSuchElementException nse)
{
//this is thrown when no more elements
}
return count;
|
public java.util.List | getFields(java.lang.String id)Retrieve the values that exists for this id3 frame id
Object o = getFrame(id);
if (o == null)
{
return new ArrayList<TagField>();
}
else if (o instanceof List)
{
//TODO should return copy
return (List<TagField>) o;
}
else if (o instanceof AbstractID3v2Frame)
{
List<TagField> list = new ArrayList<TagField>();
list.add((TagField) o);
return list;
}
else
{
throw new RuntimeException("Found entry in frameMap that was not a frame or a list:" + o);
}
|
public java.util.Iterator | getFields()
//Iterator of each different frameId in this tag
final Iterator<Map.Entry<String, Object>> it = this.frameMap.entrySet().iterator();
//Iterator used by hasNext() so doesn't effect next()
final Iterator<Map.Entry<String, Object>> itHasNext = this.frameMap.entrySet().iterator();
return new Iterator<TagField>()
{
Map.Entry<String, Object> latestEntry = null;
//this iterates through frames through for a particular frameId
private Iterator<TagField> fieldsIt;
private void changeIt()
{
if (!it.hasNext())
{
return;
}
while (it.hasNext())
{
Map.Entry<String, Object> e = it.next();
latestEntry = itHasNext.next();
if (e.getValue() instanceof List)
{
List<TagField> l = (List<TagField>) e.getValue();
//If list is empty (which it shouldn't be) we skip over this entry
if (l.size() == 0)
{
continue;
}
else
{
fieldsIt = l.iterator();
break;
}
}
else
{
//TODO must be a better way
List<TagField> l = new ArrayList<TagField>();
l.add((TagField) e.getValue());
fieldsIt = l.iterator();
break;
}
}
}
//TODO assumes if have entry its valid, but what if empty list but very different to check this
//without causing a side effect on next() so leaving for now
public boolean hasNext()
{
//Check Current frameId, does it contain more values
if (fieldsIt != null)
{
if (fieldsIt.hasNext())
{
return true;
}
}
//No remaining entries return false
if (!itHasNext.hasNext())
{
return false;
}
//Issue #236
//TODO assumes if have entry its valid, but what if empty list but very different to check this
//without causing a side effect on next() so leaving for now
return itHasNext.hasNext();
}
public TagField next()
{
//Hasn't been initialized yet
if (fieldsIt == null)
{
changeIt();
}
if (fieldsIt != null)
{
//Go to the end of the run
if (!fieldsIt.hasNext())
{
changeIt();
}
}
if (fieldsIt == null)
{
throw new NoSuchElementException();
}
return fieldsIt.next();
}
public void remove()
{
fieldsIt.remove();
}
};
|
public java.util.List | getFields(FieldKey genericKey)Get field(s) for this key
if (genericKey == null)
{
throw new KeyNotFoundException();
}
FrameAndSubId formatKey = getFrameAndSubIdFromGenericKey(genericKey);
//Get list of frames that this uses, as we are going to remove entries we don't want take a copy
List<TagField> list = getFields(formatKey.getFrameId());
List<TagField> filteredList = new ArrayList<TagField>();
String subFieldId = formatKey.getSubId();
//... do we need to refine the list further i.e we only want TXXX frames that relate to the particular
//key that was passed as a parameter
if (subFieldId != null)
{
for (TagField tagfield : list)
{
AbstractTagFrameBody next = ((AbstractID3v2Frame) tagfield).getBody();
if (next instanceof FrameBodyTXXX)
{
if (((FrameBodyTXXX) next).getDescription().equals(formatKey.getSubId()))
{
filteredList.add(tagfield);
}
}
else if (next instanceof FrameBodyWXXX)
{
if (((FrameBodyWXXX) next).getDescription().equals(formatKey.getSubId()))
{
filteredList.add(tagfield);
}
}
else if (next instanceof FrameBodyCOMM)
{
if (((FrameBodyCOMM) next).getDescription().equals(formatKey.getSubId()))
{
filteredList.add(tagfield);
}
}
else if (next instanceof FrameBodyUFID)
{
if (Arrays.equals(((FrameBodyUFID) next).getUniqueIdentifier(), formatKey.getSubId().getBytes()))
{
filteredList.add(tagfield);
}
}
else if (next instanceof FrameBodyIPLS)
{
for (Pair entry : ((FrameBodyIPLS) next).getPairing().getMapping())
{
if (entry.getKey().equals(formatKey.getSubId()))
{
filteredList.add(tagfield);
}
}
}
else if (next instanceof FrameBodyTIPL)
{
for (Pair entry : ((FrameBodyTIPL) next).getPairing().getMapping())
{
if (entry.getKey().equals(formatKey.getSubId()))
{
filteredList.add(tagfield);
}
}
}
else
{
throw new RuntimeException("Need to implement getFields(FieldKey genericKey) for:" + next.getClass());
}
}
return filteredList;
}
else
{
return list;
}
|
protected java.nio.channels.FileLock | getFileLockForWriting(java.nio.channels.FileChannel fileChannel, java.lang.String filePath)Get file lock for writing too file
TODO:this appears to have little effect on Windows Vista
logger.finest("locking fileChannel for " + filePath);
FileLock fileLock;
try
{
fileLock = fileChannel.tryLock();
}
//Assumes locking is not supported on this platform so just returns null
catch (IOException exception)
{
return null;
}
//Couldnt getFields lock because file is already locked by another application
if (fileLock == null)
{
throw new IOException(ErrorMessage.GENERAL_WRITE_FAILED_FILE_LOCKED.getMsg(filePath));
}
return fileLock;
|
public int | getFileReadBytes()Returns the tag size as reported by the tag header
return fileReadSize;
|
public java.lang.String | getFirst(java.lang.String identifier)Retrieve the first value that exists for this identifier
If the value is a String it returns that, otherwise returns a summary of the fields information
AbstractID3v2Frame frame = getFirstField(identifier);
if (frame == null)
{
return "";
}
return getTextValueForFrame(frame);
|
public java.lang.String | getFirst(FieldKey genericKey)Retrieve the first value that exists for this generic key
return getValue(genericKey, 0);
|
public org.jaudiotagger.tag.images.Artwork | getFirstArtwork()
List<Artwork> artwork = getArtworkList();
if (artwork.size() > 0)
{
return artwork.get(0);
}
return null;
|
public TagField | getFirstField(FieldKey genericKey)
List<TagField> fields = getFields(genericKey);
if (fields.size() > 0)
{
return fields.get(0);
}
return null;
|
public AbstractID3v2Frame | getFirstField(java.lang.String identifier)Retrieve the first tag field that exists for this identifier
Object object = getFrame(identifier);
if (object == null)
{
return null;
}
if (object instanceof List)
{
return ((List<AbstractID3v2Frame>) object).get(0);
}
else
{
return (AbstractID3v2Frame) object;
}
|
public java.lang.Object | getFrame(java.lang.String identifier)For single frames return the frame in this tag with given identifier if it exists, if multiple frames
exist with the same identifier it will return a list containing all the frames with this identifier
Warning the match is only done against the identifier so if a tag contains a frame with an unsupported body
but happens to have an identifier that is valid for another version of the tag it will be returned.
return frameMap.get(identifier);
|
protected abstract org.jaudiotagger.tag.id3.AbstractID3v2Tag$FrameAndSubId | getFrameAndSubIdFromGenericKey(FieldKey genericKey)
|
public java.util.Iterator | getFrameOfType(java.lang.String identifier)Return all frames which start with the identifier, this
can be more than one which is useful if trying to retrieve
similar frames e.g TIT1,TIT2,TIT3 ... and don't know exactly
which ones there are.
Warning the match is only done against the identifier so if a tag contains a frame with an unsupported body
but happens to have an identifier that is valid for another version of the tag it will be returned.
Iterator<String> iterator = frameMap.keySet().iterator();
HashSet result = new HashSet();
String key;
while (iterator.hasNext())
{
key = iterator.next();
if (key.startsWith(identifier))
{
result.add(frameMap.get(key));
}
}
return result.iterator();
|
protected abstract ID3Frames | getID3Frames()
|
public int | getInvalidFrames()Return byte count of invalid frames
return invalidFrames;
|
public abstract java.util.Comparator | getPreferredFrameOrderComparator()
|
public int | getSize()Return tag size based upon the sizes of the tags rather than the physical
no of bytes between start of ID3Tag and start of Audio Data.Should be extended
by subclasses to include header.
int size = 0;
Iterator iterator = frameMap.values().iterator();
AbstractID3v2Frame frame;
while (iterator.hasNext())
{
Object o = iterator.next();
if (o instanceof AbstractID3v2Frame)
{
frame = (AbstractID3v2Frame) o;
size += frame.getSize();
}
else
{
ArrayList<AbstractID3v2Frame> multiFrames = (ArrayList<AbstractID3v2Frame>) o;
for (ListIterator<AbstractID3v2Frame> li = multiFrames.listIterator(); li.hasNext();)
{
frame = li.next();
size += frame.getSize();
}
}
}
return size;
|
public java.lang.String | getSubValue(FieldKey genericKey, int n, int m)Retrieve the mth value that exists in the nth frame for this generic key
String wholeValue = getValue(genericKey, n);
List<String> values = TextEncodedStringSizeTerminated.splitByNullSeperator(wholeValue);
if (values.size() > m)
{
return values.get(m);
}
return "";
|
private java.lang.String | getTextValueForFrame(AbstractID3v2Frame frame)
return frame.getBody().getUserFriendlyValue();
|
public static long | getV2TagSizeIfExists(java.io.File file)Checks to see if the file contains an ID3tag and if so return its size as reported in
the tag header and return the size of the tag (including header), if no such tag exists return
zero.
FileInputStream fis = null;
FileChannel fc = null;
ByteBuffer bb = null;
try
{
//Files
fis = new FileInputStream(file);
fc = fis.getChannel();
//Read possible Tag header Byte Buffer
bb = ByteBuffer.allocate(TAG_HEADER_LENGTH);
fc.read(bb);
bb.flip();
if (bb.limit() < (TAG_HEADER_LENGTH))
{
return 0;
}
}
finally
{
if (fc != null)
{
fc.close();
}
if (fis != null)
{
fis.close();
}
}
//ID3 identifier
byte[] tagIdentifier = new byte[FIELD_TAGID_LENGTH];
bb.get(tagIdentifier, 0, FIELD_TAGID_LENGTH);
if (!(Arrays.equals(tagIdentifier, TAG_ID)))
{
return 0;
}
//Is it valid Major Version
byte majorVersion = bb.get();
if ((majorVersion != ID3v22Tag.MAJOR_VERSION) && (majorVersion != ID3v23Tag.MAJOR_VERSION) && (majorVersion != ID3v24Tag.MAJOR_VERSION))
{
return 0;
}
//Skip Minor Version
bb.get();
//Skip Flags
bb.get();
//Get size as recorded in frame header
int frameSize = ID3SyncSafeInteger.bufferToValue(bb);
//addField header size to frame size
frameSize += TAG_HEADER_LENGTH;
return frameSize;
|
public java.lang.String | getValue(FieldKey genericKey, int index)Retrieve the value that exists for this generic key and this index
Have to do some special mapping for certain generic keys because they share frame
with another generic key.
if (genericKey == null)
{
throw new KeyNotFoundException();
}
FrameAndSubId frameAndSubId = getFrameAndSubIdFromGenericKey(genericKey);
List<TagField> fields = getFields(genericKey);
if (fields != null && fields.size() > index)
{
AbstractID3v2Frame frame = (AbstractID3v2Frame) fields.get(index);
if (frame != null)
{
if (genericKey == FieldKey.TRACK)
{
return String.valueOf(((FrameBodyTRCK) frame.getBody()).getTrackNo());
}
else if (genericKey == FieldKey.TRACK_TOTAL)
{
return String.valueOf(((FrameBodyTRCK) frame.getBody()).getTrackTotal());
}
else if (genericKey == FieldKey.DISC_NO)
{
return String.valueOf(((FrameBodyTPOS) frame.getBody()).getDiscNo());
}
else if (genericKey == FieldKey.DISC_TOTAL)
{
return String.valueOf(((FrameBodyTPOS) frame.getBody()).getDiscTotal());
}
else if (genericKey == FieldKey.RATING)
{
return String.valueOf(((FrameBodyPOPM) frame.getBody()).getRating());
}
else
{
return doGetValueAtIndex(frameAndSubId, index);
}
}
else
{
return "";
}
}
return "";
|
public boolean | hasCommonFields()
return true;
|
public boolean | hasField(FieldKey key)Does this tag contain a field with the specified key
return getFirstField(key)!=null;
|
public boolean | hasField(java.lang.String id)Does this tag contain a field with the specified id
return hasFrame(id);
|
public boolean | hasFrame(java.lang.String identifier)Return whether tag has frame with this identifier
Warning the match is only done against the identifier so if a tag contains a frame with an unsupported body
but happens to have an identifier that is valid for another version of the tag it will return true
return frameMap.containsKey(identifier);
|
public boolean | hasFrameAndBody(java.lang.String identifier)Return whether tag has frame with this identifier and a related body. This is required to protect
against circumstances whereby a tag contains a frame with an unsupported body
but happens to have an identifier that is valid for another version of the tag which it has been converted to
e.g TDRC is an invalid frame in a v23 tag but if somehow a v23tag has been created by another application
with a TDRC frame we construct an UnsupportedFrameBody to hold it, then this library constructs a
v24 tag, it will contain a frame with id TDRC but it will not have the expected frame body it is not really a
TDRC frame.
if (hasFrame(identifier))
{
Object o = getFrame(identifier);
if (o instanceof AbstractID3v2Frame)
{
return !(((AbstractID3v2Frame) o).getBody() instanceof FrameBodyUnsupported);
}
return true;
}
return false;
|
public boolean | hasFrameOfType(java.lang.String identifier)Return whether tag has frame starting with this identifier
Warning the match is only done against the identifier so if a tag contains a frame with an unsupported body
but happens to have an identifier that is valid for another version of the tag it will return true
Iterator<String> iterator = frameMap.keySet().iterator();
String key;
boolean found = false;
while (iterator.hasNext() && !found)
{
key = iterator.next();
if (key.startsWith(identifier))
{
found = true;
}
}
return found;
|
public boolean | isEmpty()Is this tag empty
return frameMap.size() == 0;
|
private static boolean | isID3V2Header(java.io.RandomAccessFile raf)True if files has a ID3v2 header
long start = raf.getFilePointer();
byte[] tagIdentifier = new byte[FIELD_TAGID_LENGTH];
raf.read(tagIdentifier);
raf.seek(start);
if (!(Arrays.equals(tagIdentifier, TAG_ID)))
{
return false;
}
return true;
|
public static boolean | isId3Tag(java.io.RandomAccessFile raf)Determines if file contain an id3 tag and if so positions the file pointer just after the end
of the tag.
This method is used by non mp3s (such as .ogg and .flac) to determine if they contain an id3 tag
if(!isID3V2Header(raf))
{
return false;
}
//So we have a tag
byte[] tagHeader = new byte[FIELD_TAG_SIZE_LENGTH];
raf.seek(raf.getFilePointer() + 6);
raf.read(tagHeader);
ByteBuffer bb = ByteBuffer.wrap(tagHeader);
int size = ID3SyncSafeInteger.bufferToValue(bb);
raf.seek(size + TAG_HEADER_LENGTH);
return true;
|
public java.util.Iterator | iterator()Return the frames in the order they were added
return frameMap.values().iterator();
|
protected void | loadFrameIntoMap(java.lang.String frameId, AbstractID3v2Frame next)Add frame to the frame map
if (next.getBody() instanceof FrameBodyEncrypted)
{
loadFrameIntoSpecifiedMap(encryptedFrameMap, frameId, next);
}
else
{
loadFrameIntoSpecifiedMap(frameMap, frameId, next);
}
|
protected void | loadFrameIntoSpecifiedMap(java.util.HashMap map, java.lang.String frameId, AbstractID3v2Frame next)Decides what to with the frame that has just been read from file.
If the frame is an allowable duplicate frame and is a duplicate we add all
frames into an ArrayList and add the ArrayList to the HashMap. if not allowed
to be duplicate we store the number of bytes in the duplicateBytes variable and discard
the frame itself.
if ((ID3v24Frames.getInstanceOf().isMultipleAllowed(frameId)) || (ID3v23Frames.getInstanceOf().isMultipleAllowed(frameId)) || (ID3v22Frames.getInstanceOf().isMultipleAllowed(frameId)))
{
//If a frame already exists of this type
if (map.containsKey(frameId))
{
Object o = map.get(frameId);
if (o instanceof ArrayList)
{
ArrayList<AbstractID3v2Frame> multiValues = (ArrayList<AbstractID3v2Frame>) o;
multiValues.add(next);
logger.finer("Adding Multi Frame(1)" + frameId);
}
else
{
ArrayList<AbstractID3v2Frame> multiValues = new ArrayList<AbstractID3v2Frame>();
multiValues.add((AbstractID3v2Frame) o);
multiValues.add(next);
map.put(frameId, multiValues);
logger.finer("Adding Multi Frame(2)" + frameId);
}
}
else
{
logger.finer("Adding Multi FrameList(3)" + frameId);
map.put(frameId, next);
}
}
//If duplicate frame just stores the name of the frame and the number of bytes the frame contains
else if (map.containsKey(frameId))
{
logger.warning("Ignoring Duplicate Frame" + frameId);
//If we have multiple duplicate frames in a tag separate them with semicolons
if (this.duplicateFrameId.length() > 0)
{
this.duplicateFrameId += ";";
}
this.duplicateFrameId += frameId;
this.duplicateBytes += ((AbstractID3v2Frame) frameMap.get(frameId)).getSize();
}
else
{
logger.finer("Adding Frame" + frameId);
map.put(frameId, next);
}
|
public void | mergeDuplicateFrames(AbstractID3v2Frame newFrame, java.util.List frames)Add frame taking into account existing frames of the same type
for (ListIterator<AbstractID3v2Frame> li = frames.listIterator(); li.hasNext();)
{
AbstractID3v2Frame nextFrame = li.next();
if (newFrame.getBody() instanceof FrameBodyTXXX)
{
//Value with matching key exists so replace
if (((FrameBodyTXXX) newFrame.getBody()).getDescription().equals(((FrameBodyTXXX) nextFrame.getBody()).getDescription()))
{
li.set(newFrame);
frameMap.put(newFrame.getId(), frames);
return;
}
}
else if (newFrame.getBody() instanceof FrameBodyWXXX)
{
//Value with matching key exists so replace
if (((FrameBodyWXXX) newFrame.getBody()).getDescription().equals(((FrameBodyWXXX) nextFrame.getBody()).getDescription()))
{
li.set(newFrame);
frameMap.put(newFrame.getId(), frames);
return;
}
}
else if (newFrame.getBody() instanceof FrameBodyCOMM)
{
if (((FrameBodyCOMM) newFrame.getBody()).getDescription().equals(((FrameBodyCOMM) nextFrame.getBody()).getDescription()))
{
li.set(newFrame);
frameMap.put(newFrame.getId(), frames);
return;
}
}
else if (newFrame.getBody() instanceof FrameBodyUFID)
{
if (((FrameBodyUFID) newFrame.getBody()).getOwner().equals(((FrameBodyUFID) nextFrame.getBody()).getOwner()))
{
li.set(newFrame);
frameMap.put(newFrame.getId(), frames);
return;
}
}
else if (newFrame.getBody() instanceof FrameBodyUSLT)
{
if (((FrameBodyUSLT) newFrame.getBody()).getDescription().equals(((FrameBodyUSLT) nextFrame.getBody()).getDescription()))
{
li.set(newFrame);
frameMap.put(newFrame.getId(), frames);
return;
}
}
else if (newFrame.getBody() instanceof FrameBodyPOPM)
{
if (((FrameBodyPOPM) newFrame.getBody()).getEmailToUser().equals(((FrameBodyPOPM) nextFrame.getBody()).getEmailToUser()))
{
li.set(newFrame);
frameMap.put(newFrame.getId(), frames);
return;
}
}
//Just grab any additional info from new TRCK Frame and add to the existing one
else if (newFrame.getBody() instanceof FrameBodyTRCK)
{
FrameBodyTRCK newBody = (FrameBodyTRCK) newFrame.getBody();
FrameBodyTRCK oldBody = (FrameBodyTRCK) nextFrame.getBody();
if (newBody.getTrackNo() != null && newBody.getTrackNo() > 0)
{
oldBody.setTrackNo(newBody.getTrackNo());
}
if (newBody.getTrackTotal() != null && newBody.getTrackTotal() > 0)
{
oldBody.setTrackTotal(newBody.getTrackTotal());
}
return;
}
//Just grab any additional info from new TPOS Frame and add to the existing one
else if (newFrame.getBody() instanceof FrameBodyTPOS)
{
FrameBodyTPOS newBody = (FrameBodyTPOS) newFrame.getBody();
FrameBodyTPOS oldBody = (FrameBodyTPOS) nextFrame.getBody();
Integer newDiscNo = newBody.getDiscNo();
if ((newDiscNo != null) && (newDiscNo > 0))
{
oldBody.setDiscNo(newDiscNo);
}
Integer newDiscTotal = newBody.getDiscTotal();
if ((newDiscTotal != null) && (newDiscTotal > 0))
{
oldBody.setDiscTotal(newDiscTotal);
}
return;
}
else if (newFrame.getBody() instanceof FrameBodyIPLS)
{
FrameBodyIPLS frameBody = (FrameBodyIPLS) newFrame.getBody();
FrameBodyIPLS existingFrameBody = (FrameBodyIPLS) nextFrame.getBody();
existingFrameBody.addPair(frameBody.getText());
return;
}
else if (newFrame.getBody() instanceof FrameBodyTIPL)
{
FrameBodyTIPL frameBody = (FrameBodyTIPL) newFrame.getBody();
FrameBodyTIPL existingFrameBody = (FrameBodyTIPL) nextFrame.getBody();
existingFrameBody.addPair(frameBody.getText());
return;
}
}
if(!getID3Frames().isMultipleAllowed(newFrame.getId()))
{
frameMap.put(newFrame.getId(), newFrame);
}
else
{
//No match found so addField new one
frames.add(newFrame);
frameMap.put(newFrame.getId(), frames);
}
|
public void | removeFrame(java.lang.String identifier)Remove frame(s) with this identifier from tag
logger.finest("Removing frame with identifier:" + identifier);
frameMap.remove(identifier);
|
public void | removeFrameOfType(java.lang.String identifier)Remove any frames starting with this identifier from tag
//First fine matching keys
HashSet<String> result = new HashSet<String>();
for (Object match : frameMap.keySet())
{
String key = (String) match;
if (key.startsWith(identifier))
{
result.add(key);
}
}
//Then deleteField outside of loop to prevent concurrent modificatioon eception if there are two keys
//with the same id
for (String match : result)
{
logger.finest("Removing frame with identifier:" + match + "because starts with:" + identifier);
frameMap.remove(match);
}
|
public void | removeUnsupportedFrames()Remove all frame(s) which have an unsupported body, in other words
remove all frames that are not part of the standard frameSet for
this tag
for (Iterator i = iterator(); i.hasNext();)
{
Object o = i.next();
if (o instanceof AbstractID3v2Frame)
{
if (((AbstractID3v2Frame) o).getBody() instanceof FrameBodyUnsupported)
{
logger.finest("Removing frame" + ((AbstractID3v2Frame) o).getIdentifier());
i.remove();
}
}
}
|
private void | replaceFile(java.io.File originalFile, java.io.File newFile)Replace originalFile with the contents of newFile
Both files must exist in the same folder so that there are no problems with filesystem mount points
boolean renameOriginalResult;
//Rename Original File to make a backup in case problem with new file
File originalFileBackup = new File(originalFile.getAbsoluteFile().getParentFile().getPath(), AudioFile.getBaseFilename(originalFile) + ".old");
//If already exists modify the suffix
int count = 1;
while (originalFileBackup.exists())
{
originalFileBackup = new File(originalFile.getAbsoluteFile().getParentFile().getPath(), AudioFile.getBaseFilename(originalFile) + ".old" + count);
count++;
}
renameOriginalResult = originalFile.renameTo(originalFileBackup);
if (!renameOriginalResult)
{
logger.warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_ORIGINAL_FILE_TO_BACKUP.getMsg(originalFile.getAbsolutePath(), originalFileBackup.getName()));
newFile.delete();
throw new UnableToRenameFileException(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_ORIGINAL_FILE_TO_BACKUP.getMsg(originalFile.getAbsolutePath(), originalFileBackup.getName()));
}
//Rename new Temporary file to the final file
boolean renameResult = newFile.renameTo(originalFile);
if (!renameResult)
{
//Renamed failed so lets do some checks rename the backup back to the original file
//New File doesnt exist
if (!newFile.exists())
{
logger.warning(ErrorMessage.GENERAL_WRITE_FAILED_NEW_FILE_DOESNT_EXIST.getMsg(newFile.getAbsolutePath()));
}
//Rename the backup back to the original
renameOriginalResult = originalFileBackup.renameTo(originalFile);
if (!renameOriginalResult)
{
//TODO now if this happens we are left with testfile.old instead of testfile.mp3
logger.warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_ORIGINAL_BACKUP_TO_ORIGINAL.getMsg(originalFileBackup.getAbsolutePath(), originalFile.getName()));
}
logger.warning(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_TO_ORIGINAL_FILE.getMsg(originalFile.getAbsolutePath(), newFile.getName()));
newFile.delete();
throw new UnableToRenameFileException(ErrorMessage.GENERAL_WRITE_FAILED_TO_RENAME_TO_ORIGINAL_FILE.getMsg(originalFile.getAbsolutePath(), newFile.getName()));
}
else
{
//Rename was okay so we can now deleteField the backup of the original
boolean deleteResult = originalFileBackup.delete();
if (!deleteResult)
{
//Not a disaster but can't deleteField the backup so make a warning
logger.warning(ErrorMessage.GENERAL_WRITE_WARNING_UNABLE_TO_DELETE_BACKUP_FILE.getMsg(originalFileBackup.getAbsolutePath()));
}
}
|
public boolean | seek(java.nio.ByteBuffer byteBuffer)Does a tag of the correct version exist in this file.
byteBuffer.rewind();
logger.config("ByteBuffer pos:" + byteBuffer.position() + ":limit" + byteBuffer.limit() + ":cap" + byteBuffer.capacity());
byte[] tagIdentifier = new byte[FIELD_TAGID_LENGTH];
byteBuffer.get(tagIdentifier, 0, FIELD_TAGID_LENGTH);
if (!(Arrays.equals(tagIdentifier, TAG_ID)))
{
return false;
}
//Major Version
if (byteBuffer.get() != getMajorVersion())
{
return false;
}
//Minor Version
return byteBuffer.get() == getRevision();
|
public boolean | setEncoding(java.lang.String enc)
throw new UnsupportedOperationException("Not Implemented Yet");
|
public void | setField(FieldKey genericKey, java.lang.String value)
TagField tagfield = createField(genericKey, value);
setField(tagfield);
|
public void | setField(TagField field)
if (!(field instanceof AbstractID3v2Frame))
{
throw new FieldDataInvalidException("Field " + field + " is not of type AbstractID3v2Frame");
}
AbstractID3v2Frame newFrame = (AbstractID3v2Frame) field;
Object obj = frameMap.get(field.getId());
//If no frame of this type exist or if multiples are not allowed
if (obj == null)
{
frameMap.put(field.getId(), field);
}
//frame of this type already exists
else if (obj instanceof AbstractID3v2Frame)
{
List<AbstractID3v2Frame> frames = new ArrayList<AbstractID3v2Frame>();
frames.add((AbstractID3v2Frame) obj);
mergeDuplicateFrames(newFrame, frames);
}
//Multiple frames of this type already exist
else if (obj instanceof List)
{
mergeDuplicateFrames(newFrame, (List<AbstractID3v2Frame>) obj);
}
|
public void | setField(org.jaudiotagger.tag.images.Artwork artwork)Create field and then set within tag itself
this.setField(createField(artwork));
|
public void | setFrame(AbstractID3v2Frame frame)Add a frame to this tag
frameMap.put(frame.getIdentifier(), frame);
|
public void | setFrame(java.lang.String identifier, java.util.List multiFrame)Used for setting multiple frames for a single frame Identifier
Warning if frame(s) already exists for this identifier thay are overwritten
TODO needs to ensure do not add an invalid frame for this tag
logger.finest("Adding " + multiFrame.size() + " frames for " + identifier);
frameMap.put(identifier, multiFrame);
|
public java.lang.String | toString()
final StringBuilder out = new StringBuilder();
out.append("Tag content:\n");
final Iterator<TagField> it = getFields();
while (it.hasNext())
{
final TagField field = it.next();
out.append("\t");
out.append(field.getId());
out.append(":");
out.append(field.toString());
out.append("\n");
}
return out.toString();
|
public void | write(java.io.File file, long audioStartByte)Write tag to file.
|
public void | write(java.io.RandomAccessFile file)Write tag to file.
|
public void | write(java.nio.channels.WritableByteChannel channel)Write tag to channel.
|
public void | write(java.io.OutputStream outputStream)Write tag to output stream
write(Channels.newChannel(outputStream));
|
protected void | writeBufferToFile(java.io.File file, java.nio.ByteBuffer headerBuffer, byte[] bodyByteBuffer, int padding, int sizeIncPadding, long audioStartLocation)Write the data from the buffer to the file
FileChannel fc = null;
FileLock fileLock = null;
//We need to adjust location of audio file if true
if (sizeIncPadding > audioStartLocation)
{
logger.finest("Adjusting Padding");
adjustPadding(file, sizeIncPadding, audioStartLocation);
}
try
{
fc = new RandomAccessFile(file, "rws").getChannel();
fileLock = getFileLockForWriting(fc, file.getPath());
fc.write(headerBuffer);
fc.write(ByteBuffer.wrap(bodyByteBuffer));
fc.write(ByteBuffer.wrap(new byte[padding]));
}
catch (FileNotFoundException fe)
{
logger.log(Level.SEVERE, getLoggingFilename() + fe.getMessage(), fe);
if (fe.getMessage().equals(FileSystemMessage.ACCESS_IS_DENIED.getMsg()))
{
logger.severe(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING.getMsg(file.getPath()));
throw new UnableToModifyFileException(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING.getMsg(file.getPath()));
}
else
{
logger.severe(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING.getMsg(file.getPath()));
throw new UnableToCreateFileException(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING.getMsg(file.getPath()));
}
}
catch (IOException ioe)
{
logger.log(Level.SEVERE, getLoggingFilename() + ioe.getMessage(), ioe);
if (ioe.getMessage().equals(FileSystemMessage.ACCESS_IS_DENIED.getMsg()))
{
logger.severe(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING.getMsg(file.getParentFile().getPath()));
throw new UnableToModifyFileException(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING.getMsg(file.getParentFile().getPath()));
}
else
{
logger.severe(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING.getMsg(file.getParentFile().getPath()));
throw new UnableToCreateFileException(ErrorMessage.GENERAL_WRITE_FAILED_TO_OPEN_FILE_FOR_EDITING.getMsg(file.getParentFile().getPath()));
}
}
finally
{
if (fc != null)
{
if (fileLock != null)
{
fileLock.release();
}
fc.close();
}
}
|
protected java.io.ByteArrayOutputStream | writeFramesToBuffer()Write all the frames to the byteArrayOutputStream
Currently Write all frames, defaults to the order in which they were loaded, newly
created frames will be at end of tag.
ByteArrayOutputStream bodyBuffer = new ByteArrayOutputStream();
writeFramesToBufferStream(frameMap, bodyBuffer);
writeFramesToBufferStream(encryptedFrameMap, bodyBuffer);
return bodyBuffer;
|
private void | writeFramesToBufferStream(java.util.Map map, java.io.ByteArrayOutputStream bodyBuffer)Write frames in map to bodyBuffer
//Sort keys into Preferred Order
TreeSet<String> sortedWriteOrder = new TreeSet<String>(getPreferredFrameOrderComparator());
sortedWriteOrder.addAll(map.keySet());
AbstractID3v2Frame frame;
for (String id : sortedWriteOrder)
{
Object o = map.get(id);
if (o instanceof AbstractID3v2Frame)
{
frame = (AbstractID3v2Frame) o;
frame.setLoggingFilename(getLoggingFilename());
frame.write(bodyBuffer);
}
else
{
List<AbstractID3v2Frame> multiFrames = (List<AbstractID3v2Frame>) o;
for (AbstractID3v2Frame nextFrame : multiFrames)
{
nextFrame.setLoggingFilename(getLoggingFilename());
nextFrame.write(bodyBuffer);
}
}
}
|