Example #1
0
bool lyr3::v1::parse(ID3_TagImpl& tag, ID3_Reader& reader)
{
  io::ExitTrigger et(reader);
  ID3_Reader::pos_type end = reader.getCur();
  if (end < reader.getBeg() + 9 + 128)
  {
    ID3D_NOTICE( "id3::v1::parse: bailing, not enough bytes to parse, pos = " << end );
    return false;
  }
  reader.setCur(end - (9 + 128));

  {
    if (io::readText(reader, 9) != "LYRICSEND" ||
        io::readText(reader, 3) != "TAG")
    {
      return false;
    }
  }

  // we have a Lyrics3 v1.00 tag
  if (end < reader.getBeg() + 11 + 9 + 128)
  {
    // the file size isn't large enough to actually hold lyrics
    ID3D_WARNING( "id3::v1::parse: not enough data to parse lyrics3" );
    return false;
  }

  // reserve enough space for lyrics3 + id3v1 tag
  size_t window = end - reader.getBeg();
  size_t lyrDataSize = min<size_t>(window, 11 + 5100 + 9 + 128);
  reader.setCur(end - lyrDataSize);
  io::WindowedReader wr(reader, lyrDataSize - (9 + 128));

  if (!findText(wr, "LYRICSBEGIN"))
  {
    ID3D_WARNING( "id3::v1::parse: couldn't find LYRICSBEGIN, bailing" );
    return false;
  }

  et.setExitPos(wr.getCur());
  wr.skipChars(11);
  wr.setBeg(wr.getCur());

  io::LineFeedReader lfr(wr);
  String lyrics = io::readText(lfr, wr.remainingBytes());
  id3::v2::setLyrics(tag, lyrics, "Converted from Lyrics3 v1.00", "XXX");

  return true;
}
Example #2
0
bool id3::v1::parse(ID3_TagImpl& tag, ID3_Reader& reader)
{
  io::ExitTrigger et(reader);
  
  ID3_Reader::pos_type end = reader.getCur();
  // posn ourselves at 128 bytes from the current position
  if (end < reader.getBeg() + ID3_V1_LEN)
  {
    ID3D_NOTICE( "id3::v1::parse: not enough bytes to parse, pos = " << end );
    return false;
  }
  reader.setCur(end - ID3_V1_LEN);
  ID3_Reader::pos_type beg = reader.getCur();
  //file.seekg(-static_cast<long>(ID3_V1_LEN), ios::cur);
  if (end != beg + ID3_V1_LEN)
  {
    ID3D_WARNING( "id3::v1::parse: failed to reposition " << ID3_V1_LEN << 
                  " bytes" );
    return false;
  }
  
  // read the next 128 bytes in;
  String field = io::readText(reader, ID3_V1_LEN_ID);
  
  // check to see if it was a tag
  if (field != "TAG")
  {
    return false;
  }
  et.setExitPos(beg);
  
  // guess so, let's start checking the v2 tag for frames which are the
  // equivalent of the v1 fields.  When we come across a v1 field that has
  // no current equivalent v2 frame, we create the frame, copy the data
  // from the v1 frame and attach it to the tag

  // (Scott Wheeler) The above comment was nice in theory, but it wasn't
  // first checking (before my hacks) to see if there already was v2 data.

  ID3D_NOTICE("id3::v1::parse: read bytes: " << reader.getCur() - beg);
  String title = io::readTrailingSpaces(reader, ID3_V1_LEN_TITLE);
  field = id3::v2::getTitle(tag);
  if (title.size() > 0 && (field.size() == 0 || field == ""))
  {
    id3::v2::setTitle(tag, title);
  }
  ID3D_NOTICE( "id3::v1::parse: title = \"" << title << "\"" );
  
  ID3D_NOTICE("id3::v1::parse: read bytes: " << reader.getCur() - beg);
  String artist = io::readTrailingSpaces(reader, ID3_V1_LEN_ARTIST);
  field = id3::v2::getArtist(tag);
  if (artist.size() > 0 && (field.size() == 0 || field == ""))
  {
    id3::v2::setArtist(tag, artist);
  }
  ID3D_NOTICE( "id3::v1::parse: artist = \"" << artist << "\"" );
  
  ID3D_NOTICE("id3::v1::parse: read bytes: " << reader.getCur() - beg);
  String album = io::readTrailingSpaces(reader, ID3_V1_LEN_ALBUM);
  field = id3::v2::getAlbum(tag);
  if (album.size() > 0 && (field.size() == 0 || field == ""))
  {
    id3::v2::setAlbum(tag, album);
  }
  ID3D_NOTICE( "id3::v1::parse: album = \"" << title << "\"" );
  
  ID3D_NOTICE("id3::v1::parse: read bytes: " << reader.getCur() - beg);
  String year = io::readTrailingSpaces(reader, ID3_V1_LEN_YEAR);
  field = id3::v2::getYear(tag);
  if (year.size() > 0 && (field.size() == 0 || field == ""))
  {
    id3::v2::setYear(tag, year);
  }
  ID3D_NOTICE( "id3::v1::parse: year = \"" << year << "\"" );
  
  ID3D_NOTICE("id3::v1::parse: read bytes: " << reader.getCur() - beg);
  String comment = io::readTrailingSpaces(reader, ID3_V1_LEN_COMMENT-2);
  // fixes bug for when tracknumber is 0x20
  BString trackno = io::readBinary(reader, ID3_V1_LEN_COMMENT-28);
  if (trackno[0] == '\0')
  {
    if (trackno[1] != '\0')
    { //we've got a tracknumber
      size_t track = trackno[1];
      field = id3::v2::getTrack(tag);
      if (field.size() == 0 || field == "00")
      {
        id3::v2::setTrack(tag, track, 0);
      }
      ID3D_NOTICE( "id3::v1::parse: track = \"" << track << "\"" );
      ID3D_NOTICE( "id3::v1::parse: comment length = \"" << comment.length() << "\"" );
    }
  }
  else
  {
    // trackno[0] != '\0'
    const int paddingsize = (ID3_V1_LEN_COMMENT-2) - comment.size();
    const char * padding = "                            "; //28 spaces

    if (trackno[1] == '\0' || trackno[1] == 0x20 && trackno[0] != 0x20)
    {
      // if there used to be spaces they are gone now, we need to rebuild them
      comment.append(padding, paddingsize);
      comment.append((const char *)trackno.data(), 1);
    }
    else if (trackno[1] != '\0' && trackno[1] != 0x20 &&  trackno[0] != 0x20)
    {
      // if there used to be spaces they are gone now, we need to rebuild them
      comment.append(padding, paddingsize);
      comment.append((const char *)trackno.data(), 2);
    }
  }
  ID3D_NOTICE( "id3::v1::parse: comment = \"" << comment << "\"" );
  if (comment.size() > 0)
  {
    id3::v2::setComment(tag, comment, STR_V1_COMMENT_DESC, "XXX");
  }
  
  ID3D_NOTICE("id3::v1::parse: read bytes: " << reader.getCur() - beg);
  // the GENRE field/frame
  uchar genre = reader.readChar();
  field = id3::v2::getGenre(tag);
  if (genre != 0xFF && (field.size() == 0 || field == ""))
  {
    id3::v2::setGenre(tag, genre);
  }
  ID3D_NOTICE( "id3::v1::parse: genre = \"" << (int) genre << "\"" );

  ID3D_NOTICE("id3::v1::parse: read bytes: " << reader.getCur() - beg);
  return true;
}
Example #3
0
bool mm::parse(ID3_TagImpl& tag, ID3_Reader& rdr)
{
  io::ExitTrigger et(rdr);
  ID3_Reader::pos_type end = rdr.getCur();
  if (end < rdr.getBeg() + 48)
  {
    ID3D_NOTICE( "mm::parse: bailing, not enough bytes to parse, pos = " << end );
    return false;
  }
  
  rdr.setCur(end - 48);
  String version;
  
  {
    if (io::readText(rdr, 32) != "Brava Software Inc.             ")
    {
      ID3D_NOTICE( "mm::parse: bailing, couldn't find footer" );
      return false;
    }
    
    version = io::readText(rdr, 4);
    if (version.size() != 4 || 
        !isdigit(version[0]) || version[1] != '.' ||
        !isdigit(version[2]) || 
        !isdigit(version[3]))
    {
      ID3D_WARNING( "mm::parse: bailing, nonstandard version = " << version );
      return false;
    }
  }
    
  ID3_Reader::pos_type beg = rdr.setCur(end - 48);
  et.setExitPos(beg);
  if (end < 68)
  {
    ID3D_NOTICE( "mm::parse: bailing, not enough bytes to parse offsets, pos = " << end );
    return false;
  }
  rdr.setCur(end - 68);
    
  io::WindowedReader dataWindow(rdr);
  dataWindow.setEnd(rdr.getCur());

  uint32 offsets[5];
    
  io::WindowedReader offsetWindow(rdr, 20);
  for (size_t i = 0; i < 5; ++i)
  {
    offsets[i] = io::readLENumber(rdr, sizeof(uint32));
  }

  size_t metadataSize = 0;
  if (version <= "3.00")
  {
    // All MusicMatch tags up to and including version 3.0 had metadata 
    // sections exactly 7868 bytes in length.
    metadataSize = 7868;
  }
  else
  {
    // MusicMatch tags after version 3.0 had three possible lengths for their
    // metadata sections.  We can determine which it was by searching for
    // the version section signature that should precede the metadata section
    // by exactly 256 bytes.
    size_t possibleSizes[] = { 8132, 8004, 7936 };
      
    for (size_t i = 0; i < sizeof(possibleSizes)/sizeof(size_t); ++i)
    {
      dataWindow.setCur(dataWindow.getEnd());
        
      // Our offset will be exactly 256 bytes prior to our potential metadata
      // section
      size_t offset = possibleSizes[i] + 256;
      if (dataWindow.getCur() < offset)
      {
        // if our filesize is less than the offset, then it can't possibly
        // be the correct offset, so try again.
        continue;
      }
      dataWindow.setCur(dataWindow.getCur() - offset);
        
      // now read in the signature to see if it's a match
      if (io::readText(dataWindow, 8) == "18273645")
      {
        metadataSize = possibleSizes[i];
        break;
      }
    }
  }
  if (0 == metadataSize)
  {
    // if we didn't establish a size for the metadata, then something is
    // wrong.  probably should log this.
    ID3D_WARNING( "mm::parse: bailing, couldn't find meta data signature, end = " << end );
    return false;
  }
    
  // parse the offset pointers to determine the actual sizes of all the 
  // sections
  size_t sectionSizes[5];
  size_t tagSize = metadataSize;
    
  // we already know the size of the last section
  sectionSizes[4] = metadataSize;
    
  size_t lastOffset = 0;
  for (int i = 0; i < 5; i++)
  {
    size_t thisOffset = offsets[i];
    //ASSERT(thisOffset > lastOffset);
    if (i > 0)
    {
      size_t sectionSize = thisOffset - lastOffset;
      sectionSizes[i-1] = sectionSize;
      tagSize += sectionSize;
    }
    lastOffset = thisOffset;
  }
    
  // now check to see that our tag size is reasonable
  if (dataWindow.getEnd() < tagSize)
  {
    // Ack!  The tag size doesn't jive with the tag's ending position in
    // the file.  Bail!
    ID3D_WARNING( "mm::parse: bailing, tag size is too big, tag size = " << tagSize << ", end = " << end );
    return false;
  }

  dataWindow.setBeg(dataWindow.getEnd() - tagSize);
  dataWindow.setCur(dataWindow.getBeg());
    
  // Now calculate the adjusted offsets
  offsets[0] = dataWindow.getBeg();
  for (size_t i = 0; i < 4; ++i)
  {
    offsets[i+1] = offsets[i] + sectionSizes[i];
  }
    
  // now check for a tag header and adjust the tag_beg pointer appropriately
  if (dataWindow.getBeg() >= 256)
  {
    rdr.setCur(dataWindow.getBeg() - 256);
    if (io::readText(rdr, 8) == "18273645")
    {
      et.setExitPos(rdr.getCur() - 8);
    }
    else
    {
      et.setExitPos(dataWindow.getBeg());
    }
    dataWindow.setCur(dataWindow.getBeg());
  }
    
  // Now parse the various sections...
    
  // Parse the image extension at offset 0
  dataWindow.setCur(offsets[0]);
  String imgExt = io::readTrailingSpaces(dataWindow, 4);
    
  // Parse the image binary at offset 1
  dataWindow.setCur(offsets[1]);
  uint32 imgSize = io::readLENumber(dataWindow, 4);
  if (imgSize == 0)
  {
    // no image binary.  don't do anything.
  }
  else
  {
    io::WindowedReader imgWindow(dataWindow, imgSize);
    if (imgWindow.getEnd() < imgWindow.getBeg() + imgSize)
    {
      // Ack!  The image size given extends beyond the next offset!  This is 
      // not good...  log?
    }
    else
    {
      BString imgData = io::readAllBinary(imgWindow);
      ID3_Frame* frame = new ID3_Frame(ID3FID_PICTURE);
      if (frame)
      {
        String mimetype("image/");
        mimetype += imgExt;
        frame->GetField(ID3FN_MIMETYPE)->Set(mimetype.c_str());
        frame->GetField(ID3FN_IMAGEFORMAT)->Set("");
        frame->GetField(ID3FN_PICTURETYPE)->Set(static_cast<unsigned int>(0));
        frame->GetField(ID3FN_DESCRIPTION)->Set("");
        frame->GetField(ID3FN_DATA)->Set(reinterpret_cast<const uchar*>(imgData.data()), imgData.size());
        tag.AttachFrame(frame);
      }
    }
  }
    
  //file.seekg(offsets[2]);
  //file.seekg(offsets[3]);
  dataWindow.setCur(offsets[4]);
    
  tag.AttachFrame(readTextFrame(dataWindow, ID3FID_TITLE));
  tag.AttachFrame(readTextFrame(dataWindow, ID3FID_ALBUM));
  tag.AttachFrame(readTextFrame(dataWindow, ID3FID_LEADARTIST));
  tag.AttachFrame(readTextFrame(dataWindow, ID3FID_CONTENTTYPE));
  tag.AttachFrame(readTextFrame(dataWindow, ID3FID_COMMENT, "MusicMatch_Tempo"));
  tag.AttachFrame(readTextFrame(dataWindow, ID3FID_COMMENT, "MusicMatch_Mood"));
  tag.AttachFrame(readTextFrame(dataWindow, ID3FID_COMMENT, "MusicMatch_Situation"));
  tag.AttachFrame(readTextFrame(dataWindow, ID3FID_COMMENT, "MusicMatch_Preference"));
  tag.AttachFrame(readTextFrame(dataWindow, ID3FID_SONGLEN));
    
  // The next 12 bytes can be ignored.  The first 8 represent the 
  // creation date as a 64 bit floating point number.  The last 4 are
  // for a play counter.
  dataWindow.skipChars(12);
    
  tag.AttachFrame(readTextFrame(dataWindow, ID3FID_COMMENT, "MusicMatch_Path"));
  tag.AttachFrame(readTextFrame(dataWindow, ID3FID_COMMENT, "MusicMatch_Serial"));
    
  // 2 bytes for track
  uint32 trkNum = io::readLENumber(dataWindow, 2);
  if (trkNum > 0)
  {
    String trkStr = toString(trkNum);
    ID3_Frame* frame = new ID3_Frame(ID3FID_TRACKNUM);
    if (frame)
    {
      frame->GetField(ID3FN_TEXT)->Set(trkStr.c_str());
      tag.AttachFrame(frame);
    }
  }
    
  tag.AttachFrame(readTextFrame(dataWindow, ID3FID_COMMENT, "MusicMatch_Notes"));
  tag.AttachFrame(readTextFrame(dataWindow, ID3FID_COMMENT, "MusicMatch_Bio"));
  tag.AttachFrame(readTextFrame(dataWindow, ID3FID_UNSYNCEDLYRICS));
  tag.AttachFrame(readTextFrame(dataWindow, ID3FID_WWWARTIST));
  tag.AttachFrame(readTextFrame(dataWindow, ID3FID_WWWCOMMERCIALINFO));
  tag.AttachFrame(readTextFrame(dataWindow, ID3FID_COMMENT, "MusicMatch_ArtistEmail"));
    
  // email?

  return true;
}
Example #4
0
//bool parse(TagImpl& tag, ID3_Reader& reader)
bool lyr3::v2::parse(ID3_TagImpl& tag, ID3_Reader& reader)
{
  io::ExitTrigger et(reader);
  ID3_Reader::pos_type end = reader.getCur();
  if (end < reader.getBeg() + 6 + 9 + 128)
  {
    ID3D_NOTICE( "lyr3::v2::parse: bailing, not enough bytes to parse, pos = " << reader.getCur() );
    return false;
  }

  reader.setCur(end - (6 + 9 + 128));
  uint32 lyrSize = 0;

  ID3_Reader::pos_type beg = reader.getCur();
  lyrSize = readIntegerString(reader, 6);
  if (reader.getCur() < beg + 6)
  {
    ID3D_NOTICE( "lyr3::v2::parse: couldn't find numeric string, lyrSize = " <<
                 lyrSize );
    return false;
  }

  if (io::readText(reader, 9) != "LYRICS200" ||
      io::readText(reader, 3) != "TAG")
  {
    return false;
  }

  if (end < reader.getBeg() + lyrSize + 6 + 9 + 128)
  {
    ID3D_WARNING( "lyr3::v2::parse: not enough data to parse tag, lyrSize = " << lyrSize );
    return false;
  }
  reader.setCur(end - (lyrSize + 6 + 9 + 128));

  io::WindowedReader wr(reader);
  wr.setWindow(wr.getCur(), lyrSize);

  beg = wr.getCur();

  if (io::readText(wr, 11) != "LYRICSBEGIN")
  {
    // not a lyrics v2.00 tag
    ID3D_WARNING( "lyr3::v2::parse: couldn't find LYRICSBEGIN, bailing" );
    return false;
  }

  bool has_time_stamps = false;

  ID3_Frame* lyr_frame = NULL;

  while (!wr.atEnd())
  {
    uint32 fldSize;

    String fldName = io::readText(wr, 3);
    ID3D_NOTICE( "lyr3::v2::parse: fldName = " << fldName );
    fldSize = readIntegerString(wr, 5);
    ID3D_NOTICE( "lyr3::v2::parse: fldSize = " << fldSize );

    String fldData;

    io::WindowedReader wr2(wr, fldSize);
    io::LineFeedReader lfr(wr2);

    fldData = io::readText(lfr, fldSize);
    ID3D_NOTICE( "lyr3::v2::parse: fldData = \"" << fldData << "\"" );

    // the IND field
    if (fldName == "IND")
    {
      has_time_stamps = (fldData.size() > 1 && fldData[1] == '1');
    }

    // the TITLE field
    else if (fldName == "ETT" && !id3::v2::hasTitle(tag))
    {
      //tag.setTitle(fldData);
      id3::v2::setTitle(tag, fldData);
    }

    // the ARTIST field
    else if (fldName == "EAR" && !id3::v2::hasArtist(tag))
    {
      //tag.setArtist(fldData);
      id3::v2::setArtist(tag, fldData);
    }

    // the ALBUM field
    else if (fldName == "EAL" && !id3::v2::hasAlbum(tag))
    {
      //tag.setAlbum(fldData);
      id3::v2::setAlbum(tag, fldData);
    }

    // the Lyrics/Music AUTHOR field
    else if (fldName == "AUT")
    {
      //tag.setAuthor(fldData);
      id3::v2::setLyricist(tag, fldData);
    }

    // the INFORMATION field
    else if (fldName == "INF")
    {
      //tag.setInfo(fldData);
      id3::v2::setComment(tag, fldData, "Lyrics3 v2.00 INF", "XXX");
    }

    // the LYRICS field
    else if (fldName == "LYR")
    {
      // if already found an INF field, use it as description
      String desc =  "Converted from Lyrics3 v2.00";
      //tag.setLyrics(fldData);
      if (!has_time_stamps)
      {
        lyr_frame = id3::v2::setLyrics(tag, fldData, desc, "XXX");
      }
      else
      {
        // converts from lyrics3 to SYLT in-place
        io::StringReader sr(fldData);
        ID3D_NOTICE( "lyr3::v2::parse: determining synced lyrics" );
        BString sylt;
        io::BStringWriter sw(sylt);
        lyrics3ToSylt(sr, sw);

        lyr_frame = id3::v2::setSyncLyrics(tag, sylt, ID3TSF_MS, desc,
                                           "XXX", ID3CT_LYRICS);
        ID3D_NOTICE( "lyr3::v2::parse: determined synced lyrics" );
      }
    }
    else if (fldName == "IMG")
    {
      // currently unsupported
      ID3D_WARNING( "lyr3::v2::parse: IMG field unsupported" );
    }
    else
    {
      ID3D_WARNING( "lyr3::v2::parse: undefined field id: " <<
                    fldName );
    }
  }

  et.setExitPos(beg);
  return true;
}
void ID3_TagHeader::ParseExtended(ID3_Reader& reader)
{
  if (this->GetSpec() == ID3V2_3_0)
  {
/*
    Extended header size   $xx xx xx xx
    Extended Flags         $xx xx
    Size of padding        $xx xx xx xx
*/
    // skip over header size, we are not using it anyway, we calculate it
    reader.setCur(reader.getCur()+4); //Extended header size
    //io::readBENumber(reader, 4); //Extended header size
    uint16 tmpval = io::readBENumber(reader, 2); //Extended Flags
    // skip over padding size, we are not using it anyway
    reader.setCur(reader.getCur()+4); //Size of padding
    // io::readBENumber(reader, 4); //Size of padding
    if (tmpval != 0) //there is only one flag defined in ID3V2_3_0: crc
    {
      //skip over crc data, we are not using it anyway
      reader.setCur(reader.getCur()+4); //Crc
      //io::readBENumber(reader, 4); //Crc
      _info->extended_bytes = 14;
    }
    else
      _info->extended_bytes = 10;
  }
  if (this->GetSpec() == ID3V2_4_0)
  {
/*
    Extended header size   4 * %0xxxxxxx
    Number of flag bytes       $01
    Extended Flags             $xx
*/
    uint16 i;
    uint16 extrabytes;

    io::readUInt28(reader);
    const int extflagbytes = reader.readChar(); //Number of flag bytes
    ID3_Flags* extflags[1]; // ID3V2_4_0 has 1 flag byte, extflagbytes should be equal to 1
    for (i = 0; i < extflagbytes; ++i)
    {
      extflags[i] = new ID3_Flags;
      extflags[i]->set(reader.readChar()); //flags
    }
    extrabytes = 0;
    //extflags[0]->test(EXT_HEADER_FLAG_BIT1); // ID3V2_4_0 ext header flag bit 1 *should* be 0
    if (extflags[0]->test(EXT_HEADER_FLAG_BIT2))
    {
      // ID3V2_4_0 ext header flag bit 2 = Tag is an update
      // read size
      extrabytes += 1; // add a byte for the char containing the extflagdatasize
      const int extheaderflagdatasize = reader.readChar();
      extrabytes += extheaderflagdatasize;
      // Set the cursor right; we are not parsing the data, no-one is using extended flags anyway
      reader.setCur(reader.getCur() + extheaderflagdatasize);
      //reader.readChars(buf, extheaderflagdatasize); //buf should be at least 127 bytes = max extended header flagdata size
    }
   if (extflags[0]->test(EXT_HEADER_FLAG_BIT3))
   {
      // ID3V2_4_0 ext header flag bit 3 = CRC data present
      // read size
      extrabytes += 1; // add a byte for the char containing the extflagdatasize
      const int extheaderflagdatasize = reader.readChar();
      extrabytes += extheaderflagdatasize;
      // Set the cursor right; we are not parsing the data, no-one is using extended flags anyway
      reader.setCur(reader.getCur() + extheaderflagdatasize);
      //reader.readChars(buf, extheaderflagdatasize); //buf should be at least 127 bytes = max extended header flagdata size
    }
    if (extflags[0]->test(EXT_HEADER_FLAG_BIT4))
    {
      // ID3V2_4_0 ext header flag bit 4 = Tag restrictions
      // read size
      extrabytes += 1; // add a byte for the char containing the extflagdatasize
      const int extheaderflagdatasize = reader.readChar();
      extrabytes += extheaderflagdatasize;
      // Set the cursor right; we are not parsing the data, no-one is using extended flags anyway
      reader.setCur(reader.getCur() + extheaderflagdatasize);
      //reader.readChars(buf, extheaderflagdatasize); //buf should be at least 127 bytes = max extended header flagdata size
    }
    _info->extended_bytes = 5 + extflagbytes + extrabytes;
  }
  // a bit unorthodox, but since we are not using any of the extended header, but were merely
  // parsing it to get the cursor right, we delete it. Be Gone !
  _flags.set(HEADER_FLAG_EXTENDED, false);
  if (_info)
  {
    _data_size -= _info->extended_bytes;
    _info->extended_bytes = 0;
  }//else there is a tag with a higher or lower version than supported
}
Example #6
0
bool id3::v1::parse(ID3_TagImpl& tag, ID3_Reader& reader)
{
  io::ExitTrigger et(reader);
  
  ID3_Reader::pos_type end = reader.getCur();
  // posn ourselves at 128 bytes from the current position
  if (end < reader.getBeg() + ID3_V1_LEN)
  {
    ID3D_NOTICE( "id3::v1::parse: not enough bytes to parse, pos = " << end );
    return false;
  }
  reader.setCur(end - ID3_V1_LEN);
  ID3_Reader::pos_type beg = reader.getCur();
  //file.seekg(-static_cast<long>(ID3_V1_LEN), ios::cur);
  if (end != beg + ID3_V1_LEN)
  {
    ID3D_WARNING( "id3::v1::parse: failed to reposition " << ID3_V1_LEN << 
                  " bytes" );
    return false;
  }
  
  // read the next 128 bytes in;
  String id = io::readText(reader, ID3_V1_LEN_ID);
  
  // check to see if it was a tag
  if (id != "TAG")
  {
    return false;
  }
  et.setExitPos(beg);
  
  // guess so, let's start checking the v2 tag for frames which are the
  // equivalent of the v1 fields.  When we come across a v1 field that has
  // no current equivalent v2 frame, we create the frame, copy the data
  // from the v1 frame and attach it to the tag
  ID3D_NOTICE("id3::v1::parse: read bytes: " << reader.getCur() - beg);
  String title = io::readTrailingSpaces(reader, ID3_V1_LEN_TITLE);
  if (title.size() > 0)
  {
    id3::v2::setTitle(tag, title);
  }
  ID3D_NOTICE( "id3::v1::parse: title = \"" << title << "\"" );
  
  ID3D_NOTICE("id3::v1::parse: read bytes: " << reader.getCur() - beg);
  String artist = io::readTrailingSpaces(reader, ID3_V1_LEN_ARTIST);
  if (artist.size() > 0)
  {
    id3::v2::setArtist(tag, artist);
  }
  ID3D_NOTICE( "id3::v1::parse: artist = \"" << artist << "\"" );
  
  ID3D_NOTICE("id3::v1::parse: read bytes: " << reader.getCur() - beg);
  String album = io::readTrailingSpaces(reader, ID3_V1_LEN_ALBUM);
  if (album.size() > 0) 
  {
    id3::v2::setAlbum(tag, album);
  }
  ID3D_NOTICE( "id3::v1::parse: album = \"" << title << "\"" );
  
  ID3D_NOTICE("id3::v1::parse: read bytes: " << reader.getCur() - beg);
  String year = io::readTrailingSpaces(reader, ID3_V1_LEN_YEAR);
  if (year.size() > 0)
  {
    id3::v2::setYear(tag, year);
  }
  ID3D_NOTICE( "id3::v1::parse: year = \"" << year << "\"" );
  
  ID3D_NOTICE("id3::v1::parse: read bytes: " << reader.getCur() - beg);
  String comment = io::readTrailingSpaces(reader, ID3_V1_LEN_COMMENT);
  if (comment.length() == ID3_V1_LEN_COMMENT  &&
      '\0' == comment[ID3_V1_LEN_COMMENT - 2] ||
      '\0' != comment[ID3_V1_LEN_COMMENT - 1])
  {
    // This is an id3v1.1 tag.  The last byte of the comment is the track
    // number.  
    size_t track = comment[ID3_V1_LEN_COMMENT - 1];
    id3::v2::setTrack(tag, track, 0);
    ID3D_NOTICE( "id3::v1::parse: track = \"" << track << "\"" );

    ID3D_NOTICE( "id3::v1::parse: comment length = \"" << comment.length() << "\"" );
    io::StringReader sr(comment);
    comment = io::readTrailingSpaces(sr, ID3_V1_LEN_COMMENT - 2);
  }
  ID3D_NOTICE( "id3::v1::parse: comment = \"" << comment << "\"" );
  if (comment.size() > 0)
  {
    id3::v2::setComment(tag, comment, STR_V1_COMMENT_DESC, "XXX");
  }
  
  ID3D_NOTICE("id3::v1::parse: read bytes: " << reader.getCur() - beg);
  // the GENRE field/frame
  uchar genre = reader.readChar();
  if (genre != 0xFF) 
  {
    id3::v2::setGenre(tag, genre);
  }
  ID3D_NOTICE( "id3::v1::parse: genre = \"" << (int) genre << "\"" );

  ID3D_NOTICE("id3::v1::parse: read bytes: " << reader.getCur() - beg);
  return true;
}