package com.limegroup.gnutella.metadata.audio.writer; import java.io.File; import java.io.IOException; import java.util.Locale; import org.jaudiotagger.audio.AudioFile; import org.jaudiotagger.audio.AudioFileIO; import org.jaudiotagger.audio.exceptions.CannotReadException; import org.jaudiotagger.audio.exceptions.CannotWriteException; import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException; import org.jaudiotagger.audio.exceptions.ReadOnlyFileException; import org.jaudiotagger.tag.FieldDataInvalidException; import org.jaudiotagger.tag.Tag; import org.jaudiotagger.tag.TagException; import org.limewire.util.FileUtils; import com.limegroup.gnutella.metadata.MetaWriter; import com.limegroup.gnutella.metadata.audio.AudioMetaData; import com.limegroup.gnutella.xml.LimeXMLReplyCollection.MetaDataState; /** * Handles the actual writing of the meta-information to the file. Thanks to the * JAudioTagger, all the common fields that we're concerned with implement the same * interface. As a result, all the supported audio types can be written using this * class. */ public class AudioDataEditor implements MetaWriter { /** * The 7 most common meta-data audio tags can all be written using * this same interface. This should be overridden by a given class * which wishes to write additional tags. * @throws FieldDataInvalidException - exception when there's a problem committing * a given tag field */ protected Tag updateTag(Tag tag, AudioMetaData audioData) throws FieldDataInvalidException { tag.setAlbum(audioData.getAlbum()); tag.setArtist(audioData.getArtist()); tag.setComment(audioData.getComment()); tag.setGenre(audioData.getGenre()); tag.setTitle(audioData.getTitle()); tag.setYear(audioData.getYear()); tag.setTrack(audioData.getTrack()); return tag; } /** * @return true if the audio subtype was chosen properly for the file type */ protected boolean isValidFileType(String fileName) { String fileExtension = FileUtils.getFileExtension(fileName).toLowerCase(Locale.US); for(String extension : getSupportedExtensions()) { if(fileExtension.equals(extension)) return true; } return false; } /** * Given the audio file, return the tag from the file. If the Tag * doesn't already exist, return a valid tag for that audio type. */ protected Tag createTag(AudioFile audioFile, AudioMetaData audioData) { return audioFile.getTagOrCreateAndSetDefault(); } @Override public String[] getSupportedExtensions() { return new String[] { "fla", "flac", "m4a", "m4p", "ogg" }; } /** * Performs the actual writing of the updated meta data to disk. * This always writes the data to disk, it assumes that prior checks were * done to ensure unnecessary disk IO does not occur when no changes have * been made. * @return LimeXMLReplyCollection.NORMAL if write was successful or * a different value if write wasn't successful. */ public MetaDataState commitMetaData(String fileName, AudioMetaData audioData) { if(!isValidFileType(fileName)) return MetaDataState.INCORRECT_FILETYPE; File f = new File(fileName); FileUtils.setWriteable(f); AudioFile audioFile; Tag audioTag; try { audioFile = AudioFileIO.read(f); audioTag = createTag(audioFile, audioData); audioTag = updateTag(audioTag, audioData); audioFile.setTag(audioTag); audioFile.commit(); } catch (CannotReadException e) { return MetaDataState.RW_ERROR; } catch (IOException e) { return MetaDataState.RW_ERROR; } catch (TagException e) { return MetaDataState.FAILED_ALBUM; } catch (ReadOnlyFileException e) { return MetaDataState.RW_ERROR; } catch (InvalidAudioFrameException e) { return MetaDataState.FAILED_ALBUM; } catch (CannotWriteException e) { return MetaDataState.RW_ERROR; } return MetaDataState.NORMAL; } }