예제 #1
0
void ID3_TagHeader::Render(ID3_Writer& writer) const
{
  writer.writeChars((uchar *) ID, strlen(ID));

  writer.writeChar(ID3_V2SpecToVer(ID3V2_LATEST));
  writer.writeChar(ID3_V2SpecToRev(ID3V2_LATEST));

  // set the flags byte in the header
  writer.writeChar(static_cast<uchar>(_flags.get() & MASK8));
  io::writeUInt28(writer, this->GetDataSize()); //now includes the extended header

  // now we render the extended header
  if (_flags.test(HEADER_FLAG_EXTENDED))
  {
    if (this->GetSpec() == ID3V2_4_0)
    {
      io::writeUInt28(writer, 6); //write 4 bytes of v2.4.0 ext header containing size '6'
      io::writeBENumber(writer, 1, 1); //write that it has only one flag byte (value '1')
      io::writeBENumber(writer, 0, 1); //write flag byte with value '0'
    }
    else if (this->GetSpec() == ID3V2_3_0)
    {
      io::writeBENumber(writer, 6, sizeof(uint32));
      for (size_t i = 0; i < 6; ++i)
      {
        if (writer.writeChar('\0') == ID3_Writer::END_OF_WRITER)
        {
          break;
        }
      }
    }
  //  else //not implemented
  }
}
예제 #2
0
void id3::v2::render(ID3_Writer& writer, const ID3_TagImpl& tag)
{
    // There has to be at least one frame for there to be a tag...
    if (tag.NumFrames() == 0)
    {
        ID3D_WARNING( "id3::v2::render(): no frames to render" );
        return;
    }

    ID3D_NOTICE( "id3::v2::render(): rendering" );
    ID3_TagHeader hdr;
    hdr.SetSpec(tag.GetSpec());
    hdr.SetExtended(tag.GetExtended());
    hdr.SetExperimental(tag.GetExperimental());

    // set up the encryption and grouping IDs

    // ...
    String frms;
    io::StringWriter frmWriter(frms);
    if (!tag.GetUnsync())
    {
        ID3D_NOTICE( "id3::v2::render(): rendering frames" );
        renderFrames(frmWriter, tag);
        hdr.SetUnsync(false);
    }
    else
    {
        ID3D_NOTICE( "id3::v2::render(): rendering unsynced frames" );
        io::UnsyncedWriter uw(frmWriter);
        renderFrames(uw, tag);
        uw.flush();
        ID3D_NOTICE( "id3::v2::render(): numsyncs = " << uw.getNumSyncs() );
        hdr.SetUnsync(uw.getNumSyncs() > 0);
    }
    size_t frmSize = frms.size();
    if (frmSize == 0)
    {
        ID3D_WARNING( "id3::v2::render(): rendered frame size is 0 bytes" );
        return;
    }

    // zero the remainder of the buffer so that our padding bytes are zero
    luint nPadding = tag.PaddingSize(frmSize);
    ID3D_NOTICE( "id3::v2::render(): padding size = " << nPadding );
    hdr.SetDataSize(frmSize + nPadding);

    hdr.Render(writer);

    writer.writeChars(frms.data(), frms.size());

    for (size_t i = 0; i < nPadding; ++i)
    {
        if (writer.writeChar('\0') == ID3_Writer::END_OF_WRITER)
        {
            break;
        }
    }
}
예제 #3
0
void ID3_TagHeader::Render(ID3_Writer& writer) const
{
  writer.writeChars((uchar *) ID, strlen(ID));

  writer.writeChar(ID3_V2SpecToVer(ID3V2_LATEST));
  writer.writeChar(ID3_V2SpecToRev(ID3V2_LATEST));
  
  // set the flags byte in the header
  writer.writeChar(static_cast<uchar>(_flags.get() & MASK8));
  io::writeUInt28(writer, this->GetDataSize());

  // now we render the extended header
  if (_flags.test(EXTENDED))
  {
    io::writeBENumber(writer, _info->extended_bytes, sizeof(uint32));
  }
}
size_t io::writeTrailingSpaces(ID3_Writer& writer, String buf, size_t len)
{
  ID3_Writer::pos_type beg = writer.getCur();
  ID3_Writer::size_type strLen = buf.size();
  ID3_Writer::size_type size = min((unsigned int)len, (unsigned int)strLen);
  writer.writeChars(buf.data(), size);
  for (; size < len; ++size)
  {
    writer.writeChar('\0');
  }
  return writer.getCur() - beg;
}
예제 #5
0
void id3::v1::render(ID3_Writer& writer, const ID3_TagImpl& tag)
{
    writer.writeChars("TAG", 3);

    io::writeTrailingSpaces(writer, id3::v2::getTitle(tag),  ID3_V1_LEN_TITLE);
    io::writeTrailingSpaces(writer, id3::v2::getArtist(tag), ID3_V1_LEN_ARTIST);
    io::writeTrailingSpaces(writer, id3::v2::getAlbum(tag),  ID3_V1_LEN_ALBUM);
    io::writeTrailingSpaces(writer, id3::v2::getYear(tag),   ID3_V1_LEN_YEAR);

    size_t track = id3::v2::getTrackNum(tag);
    String comment = id3::v2::getV1Comment(tag);
    if (track > 0)
    {
        io::writeTrailingSpaces(writer, comment, ID3_V1_LEN_COMMENT - 2);
        writer.writeChar('\0');
        writer.writeChar((char) track);
    }
    else
    {
        io::writeTrailingSpaces(writer, comment, ID3_V1_LEN_COMMENT);
    }
    writer.writeChar((char) id3::v2::getGenreNum(tag));
}
size_t io::writeString(ID3_Writer& writer, String data)
{
  size_t size = writeText(writer, data);
  writer.writeChar('\0');
  return size + 1;
}
예제 #7
0
void ID3_FrameImpl::Render(ID3_Writer& writer) const
{
  // Return immediately if we have no fields, which (usually) means we're
  // trying to render a frame which has been Cleared or hasn't been initialized
  if (!this->NumFields())
  {
    return;
  }

  ID3_FrameHeader hdr;
  
  const size_t hdr_size = hdr.Size();

  // 1.  Write out the field data to the buffer, with the assumption that
  //     we won't be decompressing, since this is the usual behavior
  String flds;
  io::StringWriter fldWriter(flds);
  size_t origSize = 0;
  if (!this->GetCompression())
  {
    renderFields(fldWriter, *this);
    origSize = flds.size();
    ID3D_NOTICE ( "ID3_FrameImpl::Render(): uncompressed fields" );
  }
  else
  {
    io::CompressedWriter cr(fldWriter);
    renderFields(cr, *this);
    cr.flush();
    origSize = cr.getOrigSize();
    ID3D_NOTICE ( "ID3_FrameImpl::Render(): compressed fields, orig size = " <<
                  origSize );
  }

  size_t fldSize = flds.size();
  ID3D_NOTICE ( "ID3_FrameImpl::Render(): field size = " << fldSize );
// No need to not write empty frames, why would we not? They can be used to fill up padding space
// which is even recommended in the id3 spec.
//  if (fldSize == 0)
//  {
//    ID3D_WARNING ( "ID3_FrameImpl::Render(): no field data" );
//    return;
//  }
  
  // determine which flags need to be set
  uchar eID = this->GetEncryptionID(), gID = this->GetGroupingID();
  ID3_FrameID fid = this->GetID();
  if (fid == ID3FID_NOFRAME)
  {
    const char *tid = this->GetTextID();
    hdr.SetUnknownFrame(tid);
  }
  else
  {
    hdr.SetFrameID(fid);
  }
  hdr.SetEncryption(eID > 0);
  hdr.SetGrouping(gID > 0);
  hdr.SetCompression(origSize > fldSize);
  hdr.SetDataSize(fldSize + ((hdr.GetCompression() ? 4 : 0) + 
                             (hdr.GetEncryption()  ? 1 : 0) + 
                             (hdr.GetGrouping()    ? 1 : 0)));

  // write out the header
  hdr.Render(writer);

  if (fldSize != 0)
  {
    // No-man's land!  Not part of the header, not part of the data
    if (hdr.GetCompression())
    {
      io::writeBENumber(writer, origSize, sizeof(uint32));
      ID3D_NOTICE( "ID3_FrameImpl::Render(): frame is compressed, wrote origSize = " << origSize );
    }
    if (hdr.GetEncryption())
    {
      writer.writeChar(eID);
      ID3D_NOTICE( "ID3_FrameImpl::Render(): frame is compressed, encryption id = " << eID );
    }
    if (hdr.GetGrouping())
    {
      writer.writeChar(gID);
      ID3D_NOTICE( "ID3_FrameImpl::Render(): frame is compressed, grouping id = " << gID );
    }

    // Write the field data
    writer.writeChars(flds.data(), fldSize);
  }
  _changed = false;
}