Пример #1
0
  /**
   * Used by tags when writing to calculate the location of the music file
   *
   * @param file
   * @return the location within the file that the audio starts
   * @throws java.io.IOException
   * @throws org.jaudiotagger.audio.exceptions.InvalidAudioFrameException
   */
  public long getMP3StartByte(File file) throws InvalidAudioFrameException, IOException {
    try {
      // Read ID3v2 tag size (if tag exists) to allow audio header parsing to skip over tag
      long startByte = AbstractID3v2Tag.getV2TagSizeIfExists(file);

      MP3AudioHeader audioHeader = new MP3AudioHeader(file, startByte);
      if (startByte != audioHeader.getMp3StartByte()) {
        logger.config("First header found after tag:" + audioHeader);
        audioHeader = checkAudioStart(startByte, audioHeader);
      }
      return audioHeader.getMp3StartByte();
    } catch (InvalidAudioFrameException iafe) {
      throw iafe;
    } catch (IOException ioe) {
      throw ioe;
    }
  }
Пример #2
0
  /**
   * Saves the tags in this dataType to the file argument. It will be saved as
   * TagConstants.MP3_FILE_SAVE_WRITE
   *
   * @param fileToSave file to save the this dataTypes tags to
   * @throws FileNotFoundException if unable to find file
   * @throws IOException on any I/O error
   */
  public void save(File fileToSave) throws IOException {
    // Ensure we are dealing with absolute filepaths not relative ones
    File file = fileToSave.getAbsoluteFile();

    logger.config("Saving  : " + file.getPath());

    // Checks before starting write
    precheck(file);

    RandomAccessFile rfile = null;
    try {
      // ID3v2 Tag
      if (TagOptionSingleton.getInstance().isId3v2Save()) {
        if (id3v2tag == null) {
          rfile = new RandomAccessFile(file, "rw");
          (new ID3v24Tag()).delete(rfile);
          (new ID3v23Tag()).delete(rfile);
          (new ID3v22Tag()).delete(rfile);
          logger.config("Deleting ID3v2 tag:" + file.getName());
          rfile.close();
        } else {
          logger.config("Writing ID3v2 tag:" + file.getName());
          final MP3AudioHeader mp3AudioHeader = (MP3AudioHeader) this.getAudioHeader();
          final long mp3StartByte = mp3AudioHeader.getMp3StartByte();
          final long newMp3StartByte = id3v2tag.write(file, mp3StartByte);
          if (mp3StartByte != newMp3StartByte) {
            logger.config("New mp3 start byte: " + newMp3StartByte);
            mp3AudioHeader.setMp3StartByte(newMp3StartByte);
          }
        }
      }
      rfile = new RandomAccessFile(file, "rw");

      // Lyrics 3 Tag
      if (TagOptionSingleton.getInstance().isLyrics3Save()) {
        if (lyrics3tag != null) {
          lyrics3tag.write(rfile);
        }
      }
      // ID3v1 tag
      if (TagOptionSingleton.getInstance().isId3v1Save()) {
        logger.config("Processing ID3v1");
        if (id3v1tag == null) {
          logger.config("Deleting ID3v1");
          (new ID3v1Tag()).delete(rfile);
        } else {
          logger.config("Saving ID3v1");
          id3v1tag.write(rfile);
        }
      }
    } catch (FileNotFoundException ex) {
      logger.log(
          Level.SEVERE,
          ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE_FILE_NOT_FOUND.getMsg(file.getName()),
          ex);
      throw ex;
    } catch (IOException iex) {
      logger.log(
          Level.SEVERE,
          ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE.getMsg(file.getName(), iex.getMessage()),
          iex);
      throw iex;
    } catch (RuntimeException re) {
      logger.log(
          Level.SEVERE,
          ErrorMessage.GENERAL_WRITE_FAILED_BECAUSE.getMsg(file.getName(), re.getMessage()),
          re);
      throw re;
    } finally {
      if (rfile != null) {
        rfile.close();
      }
    }
  }
Пример #3
0
  /**
   * Regets the audio header starting from start of file, and write appropriate logging to indicate
   * potential problem to user.
   *
   * @param startByte
   * @param firstHeaderAfterTag
   * @return
   * @throws IOException
   * @throws InvalidAudioFrameException
   */
  private MP3AudioHeader checkAudioStart(long startByte, MP3AudioHeader firstHeaderAfterTag)
      throws IOException, InvalidAudioFrameException {
    MP3AudioHeader headerOne;
    MP3AudioHeader headerTwo;

    logger.warning(
        ErrorMessage.MP3_ID3TAG_LENGTH_INCORRECT.getMsg(
            file.getPath(),
            Hex.asHex(startByte),
            Hex.asHex(firstHeaderAfterTag.getMp3StartByte())));

    // because we cant agree on start location we reread the audioheader from the start of the file,
    // at least
    // this way we cant overwrite the audio although we might overwrite part of the tag if we write
    // this file
    // back later
    headerOne = new MP3AudioHeader(file, 0);
    logger.config("Checking from start:" + headerOne);

    // Although the id3 tag size appears to be incorrect at least we have found the same location
    // for the start
    // of audio whether we start searching from start of file or at the end of the alleged of file
    // so no real
    // problem
    if (firstHeaderAfterTag.getMp3StartByte() == headerOne.getMp3StartByte()) {
      logger.config(
          ErrorMessage.MP3_START_OF_AUDIO_CONFIRMED.getMsg(
              file.getPath(), Hex.asHex(headerOne.getMp3StartByte())));
      return firstHeaderAfterTag;
    } else {

      // We get a different value if read from start, can't guarantee 100% correct lets do some more
      // checks
      logger.config(
          (ErrorMessage.MP3_RECALCULATED_POSSIBLE_START_OF_MP3_AUDIO.getMsg(
              file.getPath(), Hex.asHex(headerOne.getMp3StartByte()))));

      // Same frame count so probably both audio headers with newAudioHeader being the first one
      if (firstHeaderAfterTag.getNumberOfFrames() == headerOne.getNumberOfFrames()) {
        logger.warning(
            (ErrorMessage.MP3_RECALCULATED_START_OF_MP3_AUDIO.getMsg(
                file.getPath(), Hex.asHex(headerOne.getMp3StartByte()))));
        return headerOne;
      }

      // If the size reported by the tag header is a little short and there is only nulls between
      // the recorded value
      // and the start of the first audio found then we stick with the original header as more
      // likely that currentHeader
      // DataInputStream not really a header
      if (isFilePortionNull((int) startByte, (int) firstHeaderAfterTag.getMp3StartByte())) {
        return firstHeaderAfterTag;
      }

      // Skip to the next header (header 2, counting from start of file)
      headerTwo =
          new MP3AudioHeader(
              file, headerOne.getMp3StartByte() + headerOne.mp3FrameHeader.getFrameLength());

      // It matches the header we found when doing the original search from after the ID3Tag
      // therefore it
      // seems that newAudioHeader was a false match and the original header was correct
      if (headerTwo.getMp3StartByte() == firstHeaderAfterTag.getMp3StartByte()) {
        logger.warning(
            (ErrorMessage.MP3_START_OF_AUDIO_CONFIRMED.getMsg(
                file.getPath(), Hex.asHex(firstHeaderAfterTag.getMp3StartByte()))));
        return firstHeaderAfterTag;
      }

      // It matches the frameCount the header we just found so lends weight to the fact that the
      // audio does indeed start at new header
      // however it maybe that neither are really headers and just contain the same data being
      // misrepresented as headers.
      if (headerTwo.getNumberOfFrames() == headerOne.getNumberOfFrames()) {
        logger.warning(
            (ErrorMessage.MP3_RECALCULATED_START_OF_MP3_AUDIO.getMsg(
                file.getPath(), Hex.asHex(headerOne.getMp3StartByte()))));
        return headerOne;
      }
      /// Doesnt match the frameCount lets go back to the original header
      else {
        logger.warning(
            (ErrorMessage.MP3_RECALCULATED_START_OF_MP3_AUDIO.getMsg(
                file.getPath(), Hex.asHex(firstHeaderAfterTag.getMp3StartByte()))));
        return firstHeaderAfterTag;
      }
    }
  }