Ejemplo n.º 1
0
// Remove all comments from the tag with the given description
size_t id3::v2::removeComments(ID3_TagImpl& tag, String desc)
{
  size_t numRemoved = 0;

  for (ID3_TagImpl::iterator iter = tag.begin(); iter != tag.end(); ++iter)
  {
    ID3_Frame* frame = *iter;
    if (frame == NULL)
    {
      continue;
    }
    if (frame->GetID() == ID3FID_COMMENT)
    {
      // See if the description we have matches the description of the
      // current comment.  If so, remove the comment
      String tmpDesc = getString(frame, ID3FN_DESCRIPTION);
      if (tmpDesc == desc)
      {
        frame = tag.RemoveFrame(frame);
        delete frame;
        numRemoved++;
      }
    }
  }

  return numRemoved;
}
Ejemplo n.º 2
0
String id3::v2::getV1Comment(const ID3_TagImpl& tag)
{
  ID3_Frame* frame;
  (frame = tag.Find(ID3FID_COMMENT, ID3FN_DESCRIPTION, STR_V1_COMMENT_DESC)) ||
  (frame = tag.Find(ID3FID_COMMENT, ID3FN_DESCRIPTION, ""                 )) ||
  (frame = tag.Find(ID3FID_COMMENT));
  return getString(frame, ID3FN_TEXT);
}
Ejemplo n.º 3
0
BString id3::v2::getSyncLyrics(const ID3_TagImpl& tag, String lang, String desc)
{
  // check if a SYLT frame of this language or descriptor exists
  ID3_Frame* frame = NULL;
  (frame = tag.Find(ID3FID_SYNCEDLYRICS, ID3FN_LANGUAGE, lang.c_str())) ||
  (frame = tag.Find(ID3FID_SYNCEDLYRICS, ID3FN_DESCRIPTION, desc.c_str())) ||
  (frame = tag.Find(ID3FID_SYNCEDLYRICS));

  // get the lyrics size
  ID3_Field* fld = frame->GetField(ID3FN_DATA);
  return BString(reinterpret_cast<const BString::value_type *>(fld->GetRawBinary()), fld->Size());
}
Ejemplo n.º 4
0
size_t id3::v2::removeFrames(ID3_TagImpl& tag, ID3_FrameID id)
{
  size_t numRemoved = 0;
  ID3_Frame* frame = NULL;

  while ((frame = tag.Find(id)) != NULL)
  {
    frame = tag.RemoveFrame(frame);
    delete frame;
    numRemoved++;
  }

  return numRemoved;
}
Ejemplo n.º 5
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;
        }
    }
}
Ejemplo n.º 6
0
size_t id3::v2::removeArtists(ID3_TagImpl& tag)
{
  size_t numRemoved = 0;
  ID3_Frame* frame = NULL;

  while ((frame = hasArtist(tag)) != NULL)
  {
    frame = tag.RemoveFrame(frame);
    delete frame;
    numRemoved++;
  }

  return numRemoved;
}
Ejemplo n.º 7
0
size_t RenderV1ToFile(ID3_TagImpl& tag, fstream& file)
{
  if (!file)
  {
    return 0;
  }

  // Heck no, this is stupid.  If we do not read in an initial V1(.1)
  // header then we are constantly appending new V1(.1) headers. Files
  // can get very big that way if we never overwrite the old ones.
  //  if (ID3_V1_LEN > tag.GetAppendedBytes())   - Daniel Hazelbaker
  if (ID3_V1_LEN > tag.GetFileSize())
  {
    file.seekp(0, ios::end);
  }
  else
  {
    // We want to check if there is already an id3v1 tag, so we can write over
    // it.  First, seek to the beginning of any possible id3v1 tag
    file.seekg(0-ID3_V1_LEN, ios::end);
    char sID[ID3_V1_LEN_ID];

    // Read in the TAG characters
    file.read(sID, ID3_V1_LEN_ID);

    // If those three characters are TAG, then there's a preexisting id3v1 tag,
    // so we should set the file cursor so we can overwrite it with a new tag.
    if (memcmp(sID, "TAG", ID3_V1_LEN_ID) == 0)
    {
      file.seekp(0-ID3_V1_LEN, ios::end);
    }
    // Otherwise, set the cursor to the end of the file so we can append on
    // the new tag.
    else
    {
      file.seekp(0, ios::end);
    }
  }

  ID3_IOStreamWriter out(file);

  id3::v1::render(out, tag);

  return ID3_V1_LEN;
}
Ejemplo n.º 8
0
size_t RenderV1ToFile(ID3_TagImpl& tag, fstream& file)
{
  if (!file)
  {
    return 0;
  }

  if (ID3_V1_LEN > tag.GetAppendedBytes())
  {
    file.seekp(0, ios::end);
  }
  else
  {
    // We want to check if there is already an id3v1 tag, so we can write over
    // it.  First, seek to the beginning of any possible id3v1 tag
    file.seekg(0-ID3_V1_LEN, ios::end);
    char sID[ID3_V1_LEN_ID];

    // Read in the TAG characters
    file.read(sID, ID3_V1_LEN_ID);

    // If those three characters are TAG, then there's a preexisting id3v1 tag,
    // so we should set the file cursor so we can overwrite it with a new tag.
    if (memcmp(sID, "TAG", ID3_V1_LEN_ID) == 0)
    {
      file.seekp(0-ID3_V1_LEN, ios::end);
    }
    // Otherwise, set the cursor to the end of the file so we can append on 
    // the new tag.
    else
    {
      file.seekp(0, ios::end);
    }
  }
  
  ID3_IOStreamWriter out(file);
  
  id3::v1::render(out, tag);

  return ID3_V1_LEN;
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
0
size_t RenderV2ToFile(const ID3_TagImpl& tag, fstream& file)
{
  ID3D_NOTICE( "RenderV2ToFile: starting" );
  if (!file)
  {
    ID3D_WARNING( "RenderV2ToFile: error in file" );
    return 0;
  }

  String tagString; 
  io::StringWriter writer(tagString);
  id3::v2::render(writer, tag);
  ID3D_NOTICE( "RenderV2ToFile: rendered v2" );

  const char* tagData = tagString.data();
  size_t tagSize = tagString.size();

  // if the new tag fits perfectly within the old and the old one
  // actually existed (ie this isn't the first tag this file has had)
  if ((!tag.GetPrependedBytes() && !ID3_GetDataSize(tag)) ||
      (tagSize == tag.GetPrependedBytes()))
  {
    file.seekp(0, ios::beg);
    file.write(tagData, tagSize);
  }
  else
  {
    String filename = tag.GetFileName();
#if !defined HAVE_MKSTEMP
    // This section is for Windows folk

    FILE *tempOut = tmpfile();
    if (NULL == tempOut)
    {
      // log this
      return 0;
      //ID3_THROW(ID3E_ReadOnly);
    }
    
    fwrite(tagData, 1, tagSize, tempOut);
    
    file.seekg(tag.GetPrependedBytes(), ios::beg);
    
    uchar tmpBuffer[BUFSIZ];
    while (!file)
    {
      file.read((char *)tmpBuffer, BUFSIZ);
      size_t nBytes = file.gcount();
      fwrite(tmpBuffer, 1, nBytes, tempOut);
    }
    
    rewind(tempOut);
    openWritableFile(filename, file);
    
    while (!feof(tempOut))
    {
      size_t nBytes = fread(tmpBuffer, 1, BUFSIZ, tempOut);
      file.write((char *)tmpBuffer, nBytes);
    }
    
    fclose(tempOut);
    
#else

    // else we gotta make a temp file, copy the tag into it, copy the
    // rest of the old file after the tag, delete the old file, rename
    // this new file to the old file's name and update the handle
    String sTmpSuffix = ".XXXXXX";
    if (filename.size() + sTmpSuffix.size() > ID3_PATH_LENGTH)
    {
      // log this
      return 0;
      //ID3_THROW_DESC(ID3E_NoFile, "filename too long");
    }
    char sTempFile[ID3_PATH_LENGTH];
    strcpy(sTempFile, filename.c_str());
    strcat(sTempFile, sTmpSuffix.c_str());
    
    int fd = mkstemp(sTempFile);
    if (fd < 0)
    {
      remove(sTempFile);
      //ID3_THROW_DESC(ID3E_NoFile, "couldn't open temp file");
    }

    ofstream tmpOut(fd);
    if (!tmpOut)
    {
      tmpOut.close();
      remove(sTempFile);
      return 0;
      // log this
      //ID3_THROW(ID3E_ReadOnly);
    }

    tmpOut.write(tagData, tagSize);
    file.seekg(tag.GetPrependedBytes(), ios::beg);
    uchar tmpBuffer[BUFSIZ];
    while (file)
    {
      file.read(tmpBuffer, BUFSIZ);
      size_t nBytes = file.gcount();
      tmpOut.write(tmpBuffer, nBytes);
    }
      
    tmpOut.close();

    file.close();

    remove(filename.c_str());
    rename(sTempFile, filename.c_str());

    openWritableFile(filename, file);
#endif
  }

  return tagSize;
}
Ejemplo n.º 11
0
bool id3::v2::parse(ID3_TagImpl& tag, ID3_Reader& reader)
{
  ID3_Reader::pos_type beg = reader.getCur();
  io::ExitTrigger et(reader);

  ID3_TagHeader hdr;

  io::WindowedReader wr(reader, ID3_TagHeader::SIZE);

  if (!hdr.Parse(wr) || wr.getCur() == beg)
  {
    ID3D_NOTICE( "id3::v2::parse(): parsing header failes" );
    return false;
  }
  if (hdr.GetExtended())
  {
    hdr.ParseExtended(reader);
  }
  tag.SetSpec(hdr.GetSpec());

  size_t dataSize = hdr.GetDataSize();
  ID3D_NOTICE( "ID3_TagImpl::Parse(ID3_Reader&): dataSize = " << dataSize);

  wr.setWindow(wr.getCur(), dataSize);
  et.setExitPos(wr.getEnd());

  ID3D_NOTICE( "ID3_TagImpl::Parse(ID3_Reader&): data window beg = " << wr.getBeg() );
  ID3D_NOTICE( "ID3_TagImpl::Parse(ID3_Reader&): data window cur = " << wr.getCur() );
  ID3D_NOTICE( "ID3_TagImpl::Parse(ID3_Reader&): data window end = " << wr.getEnd() );
  tag.SetExtended(hdr.GetExtended());
  if (!hdr.GetUnsync())
  {
    tag.SetUnsync(false);
    parseFrames(tag, wr);
  }
  else
  {
    // The buffer has been unsynced.  It will have to be resynced to be
    // readable.  This has to be done a character at a time.
    //
    // The original reader may be reading in characters from a file.  Doing
    // this a character at a time is quite slow.  To improve performance, read
    // in the entire buffer into a string, then create an UnsyncedReader from
    // the string.
    //
    // It might be better to implement a BufferedReader so that the details
    // of this can be abstracted away behind a class
    tag.SetUnsync(true);
    BString raw = io::readAllBinary(wr);
    io::BStringReader bsr(raw);
    io::UnsyncedReader ur(bsr);
    ID3D_NOTICE( "ID3_TagImpl::Parse(ID3_Reader&): unsync beg = " << ur.getBeg() );
    ID3D_NOTICE( "ID3_TagImpl::Parse(ID3_Reader&): unsync cur = " << ur.getCur() );
    ID3D_NOTICE( "ID3_TagImpl::Parse(ID3_Reader&): unsync end = " << ur.getEnd() );

    // Now read the UnsyncedReader into another string, and parse the frames
    // from the string.  This is done so that 1. the unsynced reader is
    // unsynced exactly once, removing the possibility of multiple unsyncings
    // of the same string, and 2) so that calls to readChars aren't done a
    // character at a time for every call
    BString synced = io::readAllBinary(ur);
    io::BStringReader sr(synced);
    parseFrames(tag, sr);
  }

  return true;
}
Ejemplo n.º 12
0
size_t RenderV2ToFile(const ID3_TagImpl& tag, fstream& file)
{
  ID3D_NOTICE( "RenderV2ToFile: starting" );
  if (!file)
  {
    ID3D_WARNING( "RenderV2ToFile: error in file" );
    return 0;
  }

  String tagString;
  io::StringWriter writer(tagString);
  id3::v2::render(writer, tag);
  ID3D_NOTICE( "RenderV2ToFile: rendered v2" );

  const char* tagData = tagString.data();
  size_t tagSize = tagString.size();
  // if the new tag fits perfectly within the old and the old one
  // actually existed (ie this isn't the first tag this file has had)
  if ((!tag.GetPrependedBytes() && !ID3_GetDataSize(tag)) ||
      (tagSize == tag.GetPrependedBytes()))
  {
    file.seekp(0, ios::beg);
    file.write(tagData, tagSize);
  }
  else
  {
    String filename = tag.GetFileName();
    String sTmpSuffix = ".XXXXXX";
    if (filename.size() + sTmpSuffix.size() > ID3_PATH_LENGTH)
    {
      // log this
      return 0;
      //ID3_THROW_DESC(ID3E_NoFile, "filename too long");
    }
    char sTempFile[ID3_PATH_LENGTH];
    strcpy(sTempFile, filename.c_str());
    strcat(sTempFile, sTmpSuffix.c_str());

#if ((defined(__GNUC__) && __GNUC__ >= 3  ) || !defined(HAVE_MKSTEMP))
    // This section is for Windows folk && gcc 3.x folk
    fstream tmpOut;
    createFile(sTempFile, tmpOut);

    tmpOut.write(tagData, tagSize);
    file.seekg(tag.GetPrependedBytes(), ios::beg);
    char *tmpBuffer[BUFSIZ];
    while (!file.eof())
    {
      file.read((char *)tmpBuffer, BUFSIZ);
      size_t nBytes = file.gcount();
      tmpOut.write((char *)tmpBuffer, nBytes);
    }

#else //((defined(__GNUC__) && __GNUC__ >= 3  ) || !defined(HAVE_MKSTEMP))

    // else we gotta make a temp file, copy the tag into it, copy the
    // rest of the old file after the tag, delete the old file, rename
    // this new file to the old file's name and update the handle

    int fd = mkstemp(sTempFile);
    if (fd < 0)
    {
      remove(sTempFile);
      //ID3_THROW_DESC(ID3E_NoFile, "couldn't open temp file");
    }

    ofstream tmpOut(fd);
    if (!tmpOut)
    {
      tmpOut.close();
      remove(sTempFile);
      return 0;
      // log this
      //ID3_THROW(ID3E_ReadOnly);
    }

    tmpOut.write(tagData, tagSize);
    file.seekg(tag.GetPrependedBytes(), ios::beg);
    uchar tmpBuffer[BUFSIZ];
    while (file)
    {
      file.read(tmpBuffer, BUFSIZ);
      size_t nBytes = file.gcount();
      tmpOut.write(tmpBuffer, nBytes);
    }

    close(fd); //closes the file

#endif ////((defined(__GNUC__) && __GNUC__ >= 3  ) || !defined(HAVE_MKSTEMP))

    tmpOut.close();
    file.close();

    // the following sets the permissions of the new file
    // to be the same as the original
#if defined(HAVE_SYS_STAT_H)
    struct stat fileStat;
    if(stat(filename.c_str(), &fileStat) == 0)
    {
#endif //defined(HAVE_SYS_STAT_H)
      remove(filename.c_str());
      rename(sTempFile, filename.c_str());
#if defined(HAVE_SYS_STAT_H)
      chmod(filename.c_str(), fileStat.st_mode);
    }
#endif //defined(HAVE_SYS_STAT_H)

//    file = tmpOut;
    file.clear();//to clear the eof mark
    openWritableFile(filename, file);
  }

  return tagSize;
}
Ejemplo n.º 13
0
String id3::v2::getFrameText(const ID3_TagImpl& tag, ID3_FrameID id)
{
  ID3_Frame* frame = tag.Find(id);
  return getString(frame, ID3FN_TEXT);
}
Ejemplo n.º 14
0
String id3::v2::getComment(const ID3_TagImpl& tag, String desc)
{
  ID3_Frame* frame = tag.Find(ID3FID_COMMENT, ID3FN_DESCRIPTION, desc.c_str());
  return getString(frame, ID3FN_TEXT);
}
Ejemplo n.º 15
0
size_t ID3_GetDataSize(const ID3_TagImpl& tag)
{
  return tag.GetFileSize() - tag.GetPrependedBytes() - tag.GetAppendedBytes();
}