📄 tag_parse_lyrics3.cpp
字号:
// $Id: tag_parse_lyrics3.cpp,v 1.35 2002/10/04 08:52:23 t1mpy Exp $// id3lib: a C++ library for creating and manipulating id3v1/v2 tags// Copyright 1999, 2000 Scott Thomas Haug// Copyright 2002 Thijmen Klok (thijmen@id3lib.org)// 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/#include <ctype.h>#include <memory.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"#include "io_strings.h"using namespace dami;namespace{ uint32 readIntegerString(ID3_Reader& reader, size_t numBytes) { uint32 val = 0; for (size_t i = 0; i < numBytes && isdigit(reader.peekChar()); ++i) { val = (val * 10) + (reader.readChar() - '0'); } ID3D_NOTICE( "readIntegerString: val = " << val ); return val; } uint32 readIntegerString(ID3_Reader& reader) { return readIntegerString(reader, reader.remainingBytes()); } bool isTimeStamp(ID3_Reader& reader) { ID3_Reader::pos_type cur = reader.getCur(); if (reader.getEnd() < cur + 7) { return false; } bool its = ('[' == reader.readChar() && isdigit(reader.readChar()) && isdigit(reader.readChar()) && ':' == reader.readChar() && isdigit(reader.readChar()) && isdigit(reader.readChar()) && ']' == reader.readChar()); reader.setCur(cur); if (its) { ID3D_NOTICE( "isTimeStamp(): found timestamp, cur = " << reader.getCur() ); } return its; } uint32 readTimeStamp(ID3_Reader& reader) { reader.skipChars(1); size_t sec = readIntegerString(reader, 2) * 60; reader.skipChars(1); sec += readIntegerString(reader, 2); reader.skipChars(1); ID3D_NOTICE( "readTimeStamp(): timestamp = " << sec ); return sec * 1000; } bool findText(ID3_Reader& reader, String text) { if (text.empty()) { return true; } size_t index = 0; while (!reader.atEnd()) { ID3_Reader::char_type ch = reader.readChar(); if (ch == text[index]) { index++; } else if (ch == text[0]) { index = 1; } else { index = 0; } if (index == text.size()) { reader.setCur(reader.getCur() - index); ID3D_NOTICE( "findText: found \"" << text << "\" at " << reader.getCur() ); break; } } return !reader.atEnd(); }; void lyrics3ToSylt(ID3_Reader& reader, ID3_Writer& writer) { while (!reader.atEnd()) { bool lf = false; size_t ms = 0; size_t count = 0; while (isTimeStamp(reader)) { // For now, just skip over multiple time stamps if (count++ > 0) { readTimeStamp(reader); } else { ms = readTimeStamp(reader); } } while (!reader.atEnd() && !isTimeStamp(reader)) { ID3_Reader::char_type ch = reader.readChar(); if (0x0A == ch && (reader.atEnd() || isTimeStamp(reader))) { lf = true; break; } else { writer.writeChar(ch); } } // put synch identifier writer.writeChar('\0'); // put timestamp ID3D_NOTICE( "lyrics3toSylt: ms = " << ms ); io::writeBENumber(writer, ms, sizeof(uint32)); if (lf) { ID3D_NOTICE( "lyrics3toSylt: adding lf" ); // put the LF writer.writeChar(0x0A); } } }};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;}//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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -