⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tag_parse_musicmatch.cpp

📁 更新mp3
💻 CPP
字号:
// $Id: tag_parse_musicmatch.cpp,v 1.19 2002/07/02 22:15:18 t1mpy Exp $// id3lib: a C++ library for creating and manipulating id3v1/v2 tags// Copyright 1999, 2000  Scott Thomas Haug// This library is free software; you can redistribute it and/or modify it// under the terms of the GNU Library General Public License as published by// the Free Software Foundation; either version 2 of the License, or (at your// option) any later version.//// This library is distributed in the hope that it will be useful, but WITHOUT// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public// License for more details.//// You should have received a copy of the GNU Library General Public License// along with this library; if not, write to the Free Software Foundation,// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.// The id3lib authors encourage improvements and optimisations to be sent to// the id3lib coordinator.  Please see the README file for details on where to// send such submissions.  See the AUTHORS file for a list of people who have// contributed to id3lib.  See the ChangeLog file for a list of changes to// id3lib.  These files are distributed with id3lib at// http://download.sourceforge.net/id3lib/#if defined HAVE_CONFIG_H#include <config.h>#endif#include <ctype.h>#include "tag_impl.h" //has <stdio.h> "tag.h" "header_tag.h" "frame.h" "field.h" "spec.h" "id3lib_strings.h" "utils.h"#include "helpers.h"#include "id3/io_decorators.h" //has "readers.h" "io_helpers.h" "utils.h"using namespace dami;namespace {  uint32 readSeconds(ID3_Reader& reader, size_t len)  {    io::ExitTrigger et(reader);    io::WindowedReader wr(reader, len);    ID3_Reader::pos_type beg = wr.getCur();    uint32 seconds = 0;    uint32 cur = 0;    while (!wr.atEnd())    {      ID3_Reader::char_type ch = wr.readChar();      if (':' == ch)      {        seconds += 60 * cur;        cur = 0;      }      else if (!isdigit(ch))      {        return 0;      }      else      {        cur = cur * 10 + (ch - '0');      }    }    et.release();    return seconds + cur;  }    ID3_Frame* readTextFrame(ID3_Reader& reader, ID3_FrameID id, const String desc = "")  {    uint32 size = io::readLENumber(reader, 2);    ID3D_NOTICE( "readTextFrame: size = " << size );    if (size == 0)    {      return NULL;    }        String text;    if (ID3FID_SONGLEN != id)    {      io::LineFeedReader lfr(reader);      text = io::readText(lfr, size);      ID3D_NOTICE( "readTextFrame: text = " << text );    }    else    {      text = toString(readSeconds(reader, size) * 1000);      ID3D_NOTICE( "readTextFrame: songlen = " << text );    }        ID3_Frame* frame = new ID3_Frame(id);    if (frame)    {      if (frame->Contains(ID3FN_TEXT))      {        frame->GetField(ID3FN_TEXT)->Set(text.c_str());      }      else if (frame->Contains(ID3FN_URL))      {        frame->GetField(ID3FN_URL)->Set(text.c_str());      }      if (frame->Contains(ID3FN_LANGUAGE))      {        frame->GetField(ID3FN_LANGUAGE)->Set("XXX");      }      if (frame->Contains(ID3FN_DESCRIPTION))      {        frame->GetField(ID3FN_DESCRIPTION)->Set(desc.c_str());      }    }    return frame;  }};  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;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -