blob: 928fd610a7cff977ab3cfd4a0dad49119a6ed810 [file] [log] [blame]
// $Id: tag_parse_v1.cpp,v 1.27 2002/07/31 13:45:18 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 "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;
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.size() > 1) { // defensive test to fix Windows WinQual Report# 557960782
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;
}