| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| AudioFile |
|
| 0.0;0 |
| 1 | /* | |
| 2 | * Entagged Audio Tag library | |
| 3 | * Copyright (c) 2003-2005 Rapha�l Slinckx <raphael@slinckx.net> | |
| 4 | * | |
| 5 | * This library is free software; you can redistribute it and/or | |
| 6 | * modify it under the terms of the GNU Lesser General Public | |
| 7 | * License as published by the Free Software Foundation; either | |
| 8 | * version 2.1 of the License, or (at your option) any later version. | |
| 9 | * | |
| 10 | * This library is distributed in the hope that it will be useful, | |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 13 | * Lesser General Public License for more details. | |
| 14 | * | |
| 15 | * You should have received a copy of the GNU Lesser General Public | |
| 16 | * License along with this library; if not, write to the Free Software | |
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
| 18 | */ | |
| 19 | package org.jaudiotagger.audio; | |
| 20 | ||
| 21 | import java.io.File; | |
| 22 | import java.io.FileNotFoundException; | |
| 23 | import java.io.RandomAccessFile; | |
| 24 | import java.util.logging.Logger; | |
| 25 | import java.util.ArrayList; | |
| 26 | ||
| 27 | import org.jaudiotagger.audio.exceptions.CannotWriteException; | |
| 28 | import org.jaudiotagger.audio.exceptions.ReadOnlyFileException; | |
| 29 | import org.jaudiotagger.audio.flac.metadatablock.MetadataBlockDataPicture; | |
| 30 | import org.jaudiotagger.audio.generic.GenericTag; | |
| 31 | import org.jaudiotagger.audio.asf.tag.AsfTag; | |
| 32 | import org.jaudiotagger.audio.wav.WavTag; | |
| 33 | import org.jaudiotagger.audio.real.RealTag; | |
| 34 | import org.jaudiotagger.tag.Tag; | |
| 35 | import org.jaudiotagger.tag.mp4.Mp4Tag; | |
| 36 | import org.jaudiotagger.tag.vorbiscomment.VorbisCommentTag; | |
| 37 | import org.jaudiotagger.tag.flac.FlacTag; | |
| 38 | ||
| 39 | /** | |
| 40 | * <p>This is the main object manipulated by the user representing an audiofile, its properties and its tag.</p> | |
| 41 | * <p>The prefered way to obtain an <code>AudioFile</code> is to use the <code>AudioFileIO.read(File)</code> method.</p> | |
| 42 | * <p>The <code>AudioFile</code> contains every properties associated with the file itself (no meta-data), like the bitrate, the sampling rate, the encoding audioHeaders, etc.</p> | |
| 43 | * <p>To get the meta-data contained in this file you have to get the <code>Tag</code> of this <code>AudioFile</code></p> | |
| 44 | * | |
| 45 | * @author Raphael Slinckx | |
| 46 | * @version $Id: AudioFile.java,v 1.11 2008/10/28 10:26:24 paultaylor Exp $ | |
| 47 | * @see AudioFileIO | |
| 48 | * @see Tag | |
| 49 | * @since v0.01 | |
| 50 | */ | |
| 51 | public class AudioFile | |
| 52 | { | |
| 53 | //Logger | |
| 54 | 73 | public static Logger logger = Logger.getLogger("org.jaudiotagger.audio"); |
| 55 | ||
| 56 | /** | |
| 57 | * The physical file that this instance represents. | |
| 58 | */ | |
| 59 | protected File file; | |
| 60 | ||
| 61 | /** | |
| 62 | * The Audio header info | |
| 63 | */ | |
| 64 | protected AudioHeader audioHeader; | |
| 65 | ||
| 66 | /** | |
| 67 | * The tag | |
| 68 | */ | |
| 69 | protected Tag tag; | |
| 70 | ||
| 71 | public AudioFile() | |
| 72 | 441 | { |
| 73 | ||
| 74 | 441 | } |
| 75 | ||
| 76 | /** | |
| 77 | * <p>These constructors are used by the different readers, users should not use them, but use the <code>AudioFileIO.read(File)</code> method instead !.</p> | |
| 78 | * <p>Create the AudioFile representing file f, the encodingaudioHeaders and containing the tag</p> | |
| 79 | * | |
| 80 | * @param f The file of the audiofile | |
| 81 | * @param audioHeader the encoding audioHeaders over this file | |
| 82 | * @param tag the tag contained in this file or null if no tag exists | |
| 83 | */ | |
| 84 | public AudioFile(File f, AudioHeader audioHeader, Tag tag) | |
| 85 | 234 | { |
| 86 | 234 | this.file = f; |
| 87 | 234 | this.audioHeader = audioHeader; |
| 88 | 234 | this.tag = tag; |
| 89 | 234 | } |
| 90 | ||
| 91 | ||
| 92 | /** | |
| 93 | * <p>These constructors are used by the different readers, users should not use them, but use the <code>AudioFileIO.read(File)</code> method instead !.</p> | |
| 94 | * <p>Create the AudioFile representing file denoted by pathname s, the encodingaudioHeaders and containing the tag</p> | |
| 95 | * | |
| 96 | * @param s The pathname of the audiofile | |
| 97 | * @param audioHeader the encoding audioHeaders over this file | |
| 98 | * @param tag the tag contained in this file | |
| 99 | */ | |
| 100 | public AudioFile(String s, AudioHeader audioHeader, Tag tag) | |
| 101 | 0 | { |
| 102 | 0 | this.file = new File(s); |
| 103 | 0 | this.audioHeader = audioHeader; |
| 104 | 0 | this.tag = tag; |
| 105 | 0 | } |
| 106 | ||
| 107 | /** | |
| 108 | * <p>Write the tag contained in this AudioFile in the actual file on the disk, this is the same as calling the <code>AudioFileIO.write(this)</code> method.</p> | |
| 109 | * | |
| 110 | * @throws CannotWriteException If the file could not be written/accessed, the extension wasn't recognized, or other IO error occured. | |
| 111 | * @see AudioFileIO | |
| 112 | */ | |
| 113 | public void commit() throws CannotWriteException | |
| 114 | { | |
| 115 | 85 | AudioFileIO.write(this); |
| 116 | 85 | } |
| 117 | ||
| 118 | /** | |
| 119 | * Set the file to store the info in | |
| 120 | * | |
| 121 | * @param file | |
| 122 | */ | |
| 123 | public void setFile(File file) | |
| 124 | { | |
| 125 | 0 | this.file = file; |
| 126 | 0 | } |
| 127 | ||
| 128 | /** | |
| 129 | * Retrieve the physical file | |
| 130 | * | |
| 131 | * @return | |
| 132 | */ | |
| 133 | public File getFile() | |
| 134 | { | |
| 135 | 1264 | return file; |
| 136 | } | |
| 137 | ||
| 138 | public void setTag(Tag tag) | |
| 139 | { | |
| 140 | 2 | this.tag = tag; |
| 141 | 2 | } |
| 142 | ||
| 143 | /** | |
| 144 | * Return audio header | |
| 145 | */ | |
| 146 | public AudioHeader getAudioHeader() | |
| 147 | { | |
| 148 | 1450 | return audioHeader; |
| 149 | } | |
| 150 | ||
| 151 | /** | |
| 152 | * <p>Returns the tag contained in this AudioFile, the <code>Tag</code> contains any useful meta-data, like | |
| 153 | * artist, album, title, etc. If the file does not contain any tag the null is returned. Some audio formats do | |
| 154 | * not allow there to be no tag so in this case the reader would return an empty tag whereas for others such | |
| 155 | * as mp3 it is purely optional. | |
| 156 | * | |
| 157 | * @return Returns the tag contained in this AudioFile, or null if no tag exists. | |
| 158 | */ | |
| 159 | public Tag getTag() | |
| 160 | { | |
| 161 | 1041 | return tag; |
| 162 | } | |
| 163 | ||
| 164 | /** | |
| 165 | * <p>Returns a multi-line string with the file path, the encoding audioHeaderrmations, and the tag contents.</p> | |
| 166 | * | |
| 167 | * @return A multi-line string with the file path, the encoding audioHeaderrmations, and the tag contents. | |
| 168 | * TODO Maybe this can be changed ? | |
| 169 | */ | |
| 170 | public String toString() | |
| 171 | { | |
| 172 | 0 | return "AudioFile " + getFile().getAbsolutePath() |
| 173 | + " --------\n" + audioHeader.toString() + "\n" + ((tag == null) ? "" : tag.toString()) + "\n-------------------"; | |
| 174 | } | |
| 175 | ||
| 176 | /** | |
| 177 | * Checks the file is accessible with the correct permissions, otherwise exception occurs | |
| 178 | * | |
| 179 | * @param file | |
| 180 | * @param readOnly | |
| 181 | * @throws ReadOnlyFileException | |
| 182 | * @throws FileNotFoundException | |
| 183 | */ | |
| 184 | protected RandomAccessFile checkFilePermissions(File file, boolean readOnly) throws ReadOnlyFileException, FileNotFoundException | |
| 185 | { | |
| 186 | RandomAccessFile newFile; | |
| 187 | ||
| 188 | 441 | logger.info("Reading file:" + "path" + file.getPath() + ":abs:" + file.getAbsolutePath()); |
| 189 | 441 | if (file.exists() == false) |
| 190 | { | |
| 191 | 0 | logger.severe("Unable to find:" + file.getPath()); |
| 192 | 0 | throw new FileNotFoundException("Unable to find:" + file.getPath()); |
| 193 | } | |
| 194 | ||
| 195 | // Unless opened as readonly the file must be writable | |
| 196 | 441 | if (readOnly) |
| 197 | { | |
| 198 | 118 | newFile = new RandomAccessFile(file, "r"); |
| 199 | } | |
| 200 | else | |
| 201 | { | |
| 202 | 323 | if (file.canWrite() == false) |
| 203 | { | |
| 204 | 1 | logger.severe("Unable to write:" + file.getPath()); |
| 205 | 1 | throw new ReadOnlyFileException("Unable to write to:" + file.getPath()); |
| 206 | } | |
| 207 | 322 | newFile = new RandomAccessFile(file, "rw"); |
| 208 | } | |
| 209 | 440 | return newFile; |
| 210 | } | |
| 211 | ||
| 212 | /** | |
| 213 | * Optional debugging method | |
| 214 | * | |
| 215 | * @return | |
| 216 | */ | |
| 217 | public String displayStructureAsXML() | |
| 218 | { | |
| 219 | 0 | return ""; |
| 220 | } | |
| 221 | ||
| 222 | /** | |
| 223 | * Optional debugging method | |
| 224 | * | |
| 225 | * @return | |
| 226 | */ | |
| 227 | public String displayStructureAsPlainText() | |
| 228 | { | |
| 229 | 0 | return ""; |
| 230 | } | |
| 231 | ||
| 232 | ||
| 233 | /** Create Default Tag | |
| 234 | * | |
| 235 | * @return | |
| 236 | */ | |
| 237 | //TODO might be better to instantiate classes such as Mp4File,FlacFile ecetera | |
| 238 | //TODO Generic tag is very misleading because soem of these formats cannot actually save the tag | |
| 239 | public Tag createDefaultTag() | |
| 240 | { | |
| 241 | 0 | if(SupportedFileFormat.FLAC.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) |
| 242 | { | |
| 243 | 0 | return new FlacTag(VorbisCommentTag.createNewTag(), new ArrayList< MetadataBlockDataPicture >()); |
| 244 | } | |
| 245 | 0 | else if(SupportedFileFormat.OGG.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) |
| 246 | { | |
| 247 | 0 | return VorbisCommentTag.createNewTag(); |
| 248 | } | |
| 249 | 0 | else if(SupportedFileFormat.MP4.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) |
| 250 | { | |
| 251 | 0 | return new Mp4Tag(); |
| 252 | } | |
| 253 | 0 | else if(SupportedFileFormat.M4A.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) |
| 254 | { | |
| 255 | 0 | return new Mp4Tag(); |
| 256 | } | |
| 257 | 0 | else if(SupportedFileFormat.M4P.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) |
| 258 | { | |
| 259 | 0 | return new Mp4Tag(); |
| 260 | } | |
| 261 | 0 | else if(SupportedFileFormat.WMA.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) |
| 262 | { | |
| 263 | 0 | return new AsfTag(); |
| 264 | } | |
| 265 | 0 | else if(SupportedFileFormat.WAV.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) |
| 266 | { | |
| 267 | 0 | return new WavTag(); |
| 268 | } | |
| 269 | 0 | else if(SupportedFileFormat.RA.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) |
| 270 | { | |
| 271 | 0 | return new RealTag(); |
| 272 | } | |
| 273 | 0 | else if(SupportedFileFormat.RM.getFilesuffix().equals(file.getName().substring(file.getName().lastIndexOf('.')))) |
| 274 | { | |
| 275 | 0 | return new RealTag(); |
| 276 | } | |
| 277 | else | |
| 278 | { | |
| 279 | 0 | throw new RuntimeException("Unable to create default tag for this file format"); |
| 280 | } | |
| 281 | ||
| 282 | } | |
| 283 | ||
| 284 | /** | |
| 285 | * Get the tag or if the file doesnt have one at all, create a default tag and return | |
| 286 | * | |
| 287 | * @return | |
| 288 | */ | |
| 289 | public Tag getTagOrCreateDefault() | |
| 290 | { | |
| 291 | 0 | Tag tag = getTag(); |
| 292 | 0 | if(tag==null) |
| 293 | { | |
| 294 | 0 | return createDefaultTag(); |
| 295 | } | |
| 296 | 0 | return tag; |
| 297 | } | |
| 298 | ||
| 299 | /** | |
| 300 | * Get the tag or if the file doesnt have one at all, create a default tag and set it | |
| 301 | * | |
| 302 | * @return | |
| 303 | */ | |
| 304 | public Tag getTagOrCreateAndSetDefault() | |
| 305 | { | |
| 306 | 5 | Tag tag = getTag(); |
| 307 | 5 | if(tag==null) |
| 308 | { | |
| 309 | 4 | tag = createDefaultTag(); |
| 310 | 4 | setTag(tag); |
| 311 | 4 | return tag; |
| 312 | } | |
| 313 | 1 | return tag; |
| 314 | } | |
| 315 | ||
| 316 | /** | |
| 317 | * | |
| 318 | * @param file | |
| 319 | * @return filename with audioformat seperator stripped of. | |
| 320 | */ | |
| 321 | public static String getBaseFilename(File file) | |
| 322 | { | |
| 323 | 339 | int index=file.getName().toLowerCase().lastIndexOf("."); |
| 324 | 339 | if(index>0) |
| 325 | { | |
| 326 | 339 | return file.getName().substring(0,index); |
| 327 | } | |
| 328 | 0 | return file.getName(); |
| 329 | } | |
| 330 | } |