com.beaglebuddy.id3.v23

## Class ID3v23Frame

- java.lang.Object
- - com.beaglebuddy.id3.v23.ID3v23Frame

-     public class ID3v23Frame
      extends java.lang.Object

  This class provides methods for reading and writing ID3v2.3 frames. As the .mp3 file format shows below, an `ID3v2.3 tag` is comprised mostly of frames. It is in these frames where the actual information about the .mp3 file is contained. Information such as the song title, the track number, the lyrics of the song, the band who recorded the song, etc. are stored in the frames. The ID3v2.3 Specification defines 74 different `types of frames`. A frame consists of a `header` and a `body`. The frame header contains some information about the frame body (such as its size, type, etc.) and as such does not vary much between the different frame types. This is in contrast to the `body`, which contains the actual information (song title, etc.) and hence varies widely between the different types of frames.

  A very common scenario is to read in an existing .mp3 file from your hard drive, and then to view the information about it or to modify the information. Reading in an existing .mp3 file raises the question of what to do when an error occurs. There are three types of errors that can happen and they are listed below, as well as how the Beaglebuddy MP3 library handles them.

  Potential Errors When Reading in an .mp3 File
  | Error Type | Description
  --- | --- | ---
  1. | IO Exception | This error is pretty straight forward and the easiest to explain. Simply put, an error occurrs while trying to read in the .mp3 file from disk. Possible causes include bad sectors on your hard drive, the .mp3 file itself is corrupt (maybe some bytes were lost when you downloaded it/ripped it), etc. There is not much that can be done about this, other than to try reading it in again. If that doesn't work, you might need to obtain a new copy of the .mp3 file.
  2. | an invalid frame id is encountered | The ID3v2.3 Specification defines 74 frame types, each with its own unique 4 character `frame id`. If the Beaglebuddy MP3 library encounters a frame with an invalid frame id, then it tries to skip over the invalid frame, and to continue reading in the rest of the .mp3 file in the hope that the invalid frame was just an isolated bad frame and that the remainder of the frames will be valid. From tests run at Beaglebuddy on about 12,000 mp3 files, this has been the case, and the rest of the .mp3 file can be read in, the bad frame discarded, and the .mp3 file saved so that it contains only valid ID3v2.3 frames.
  3. | a valid frame id was read, but it contained an invalid value in the frame body | This is the most common type of error that you will encounter. In this case, we have one of the valid 74 frame types, but the frame contains some invalid field value(s). Examples of invalid field values include an invalid `language code`, an invalid `character encoding` (must be 0 or 1), an invalid `time stamp format` (must be 1 or 2), a required field is left blank (such as the comments being blank in a Comment frame), etc. In each case, a suitable valid value is used to replace the invalid value. For example, if an invalid language code is specified, then the Beaglebuddy MP3 library will replace the invalid value with ENG (english). If a suitable replacement value can not be found or doesn't make sense, then the frame will be marked as invalid, and the Beaglebuddy MP3 library will discard the invalid frame and continue to parse the remaining frames. For example, if the comments field in a Comments frame is empty, there is no reasonable replacement value that can be used, and since a Comments frame without a comment doesn't make any sense, the frame is flagged as invalid, which essentially means it is discarded, and the Beaglebuddy MP3 library skips over the invalid frame and moves on to the next frame to try and read the remaining frames.

  When an invalid frame can not be fixed (as described above in error types 2 and 3), it is tagged as invalid so that the Beaglebuddy MP3 library knows to ignore it, and not to include it when the user finishes his work and goes to save the .mp3 file back to disk. This tagging is done by setting the `invalidMessage` field with a description of the error. To determine if a frame is valid or not, you can simply call the `isValid()` method.

  See Also:
    ID3 tag version 2.3.0 standard, wikipedia history of ID3 tags

- - ### Constructor Summary

    Constructors
    Constructor and Description
    `ID3v23Frame(FrameType frameType)` constructor.
    `ID3v23Frame(FrameType frameType, ID3v23FrameBody frameBody)` constructor.
    `ID3v23Frame(ID3v23FrameHeader header, java.io.InputStream inputStream)` constructor.

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `ID3v23FrameBody` | `getBody()` gets the body part of the frame.
    `java.lang.String` | `getDescription()` gets a description of the frame's type.
    `ID3v23FrameHeader` | `getHeader()` gets the header part of the frame.
    `java.lang.String` | `getInvalidMessage()` if the frame is invalid, then the reason why the frame is not valid is returned.
    `int` | `getSize()` gets the size (in bytes) of the frame.
    `boolean` | `isDirty()` returns a boolean indicating whether the frame has been modified.
    `boolean` | `isValid()` indicates whether the frame read in is a valid ID3v2.3 frame.
    `void` | `save(java.io.OutputStream file)` saves the frame to the .mp3 file.
    `void` | `save(java.io.RandomAccessFile file)` save the frame to the .mp3 file.
    `void` | `setBody(ID3v23FrameBody body)` sets the ID3v2.3 frame's body to one of the 74 types defined by the ID32.3 Specification.
    `void` | `setBuffer()` If the frame header or body's values have been modified, then resize the frame's internal raw binary buffer and store the new values there.
    `void` | `setHeader(ID3v23FrameHeader header)` sets the ID3v2.3 frame's header.
    `java.lang.String` | `toString()` gets a string representation of the ID3v2.3 tag frame.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait`

- - ### Constructor Detail

    - #### ID3v23Frame

          public ID3v23Frame(FrameType frameType)

      constructor. called when creating a new frame.
      Parameters:
        `frameType` - the ID3v2.3 type of frame to create.

    - #### ID3v23Frame

          public ID3v23Frame(FrameType frameType,
                     ID3v23FrameBody frameBody)
                      throws java.lang.IllegalArgumentException

      constructor. called when creating a new frame.
      Parameters:
        `frameType` - the ID3v2.3 id of the type of frame to create.
        `frameBody` - the ID3v2.3 frame body corresponding to the frame type being created.
      Throws:
        `java.lang.IllegalArgumentException` - if the class of the frame body does not correspond that specified by the frameType. For example, if you have a frameType of FrameType.ATTACHED_PICTURE and a frame body of type ID3v23FrameBodyTextInformation instead of ID3v23FrameBodyAttachedPicture.

    - #### ID3v23Frame

          public ID3v23Frame(ID3v23FrameHeader header,
                     java.io.InputStream inputStream)
                      throws java.io.IOException,
                             java.lang.IllegalArgumentException

      constructor. called when reading in an existing frame header from an .mp3 file. If a parsing error occurs while reading the frame, then the frame is tagged as being invalid by setting the `invalidMessage` field.
      Parameters:
        `header` - the frame's header.
        `inputStream` - input stream pointing to the next frame in the ID3v2.3 tag.
      Throws:
        `java.io.IOException` - if there is an error while reading the frame.
        `java.lang.IllegalArgumentException` - if a valid frame id was read, and the bytes for the frame body were read, but an invalid value was encountered while parsing the frame body. Examples of such errors include an invalid language code (must be 3 character ISO-639-2 code), an invalid encoding (must be 0 or 1), an invalid time stamp format (must be 1 or 2), a comments frame with no comments, an attached picture frame with no picture data, etc. since all the bytes for the frame were read, this frame will simply be marked as being invalid, and processing of the remainder of the ID3 v2.3 tag will continue.

  - ### Method Detail

    - #### getHeader

          public ID3v23FrameHeader getHeader()

      gets the header part of the frame.
      Returns:
        the ID3v2.3 frame header;

    - #### setHeader

          public void setHeader(ID3v23FrameHeader header)

      sets the ID3v2.3 frame's header.
      Parameters:
        `header` - the fraame's header.

    - #### getBody

          public ID3v23FrameBody getBody()

      gets the body part of the frame.
      Returns:
        the ID3v2.3 frame body;

    - #### setBody

          public void setBody(ID3v23FrameBody body)

      sets the ID3v2.3 frame's body to one of the 74 types defined by the ID32.3 Specification.
      Parameters:
        `body` - the frame's body.

    - #### isDirty

          public boolean isDirty()

      returns a boolean indicating whether the frame has been modified. If any part of the frame's header or body have been modified, then true is returned. Otherwise, if no changes have been made since the last time the frame was saved, then false is returned. If the frame has been modified and the dirty flag returns true, then the frame's `setBuffer()` method must be called prior to calling the `save()` method.
      Returns:
        whether the frame has been modified.

    - #### isValid

          public boolean isValid()

      indicates whether the frame read in is a valid ID3v2.3 frame. This prevents invalid frames that are encountered while parsing an .mp3 file from interrupting the parsing of the rest of the .mp3 file. If an invalid frame is encountered while reading in an .mp3 file, then the invalid frame is simply tagged as being invalid by setting the `invalidMessage` field. Parsing then continues with the next frame.
      Returns:
        whether the frame id read in from the .mp3 file is a valid ID3v2.3 frame id.

    - #### getInvalidMessage

          public java.lang.String getInvalidMessage()

      if the frame is invalid, then the reason why the frame is not valid is returned.
      Returns:
        if the frame is invalid, the reason why the frame is not a valid ID3v2.3 frame is returned. Otherwise, null is returned.

    - #### getDescription

          public java.lang.String getDescription()

      gets a description of the frame's type.
      Returns:
        the ID3v2.3 description of the frame.

    - #### getSize

          public int getSize()

      gets the size (in bytes) of the frame.
      Returns:
        the size (in bytes) of the frame.

    - #### save

          public void save(java.io.OutputStream file)
                    throws java.io.IOException,
                           java.lang.IllegalStateException

      saves the frame to the .mp3 file.
      Parameters:
        `file` - file output stream pointing to the starting location of the ID3v2.3 tag within the .mp3 file.
      Throws:
        `java.lang.IllegalStateException` - if the frame has been modified (`dirty` flag is true) and the frame's `setBuffer()`) method has not yet been called.
        `java.io.IOException` - if there was an error writing the ID3v2.3 tag to the .mp3 file.

    - #### save

          public void save(java.io.RandomAccessFile file)
                    throws java.io.IOException

      save the frame to the .mp3 file. Before calling save(), make sure you have called `setBuffer()` so that any changes to the frame can first be written to the frame's internal byte buffer. Failure to do so will result in an IllegalStateException being thrown.
      Parameters:
        `file` - random access file pointing to the starting location of the ID3v2.3 tag within the .mp3 file.
      Throws:
        `java.lang.IllegalStateException` - if the frame has been modified but `setBuffer()` has not been called to write the changes to the frame's internal byte buffer.
        `java.io.IOException` - if there was an error writing the ID3v2.3 tag to the .mp3 file.

    - #### setBuffer

          public void setBuffer()

      If the frame header or body's values have been modified, then resize the frame's internal raw binary buffer and store the new values there. When finished, the dirty flag is reset to indicate that the internal buffer is up to date, and the frame is now ready to be saved to the .mp3 file.

    - #### toString

          public java.lang.String toString()

      gets a string representation of the ID3v2.3 tag frame.
      Overrides:
        `toString` in class `java.lang.Object`
      Returns:
        a string representation of the ID3v2.3 tag frame.