aboutsummaryrefslogtreecommitdiff
path: root/src/helpers.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/helpers.cpp')
-rw-r--r--src/helpers.cpp518
1 files changed, 518 insertions, 0 deletions
diff --git a/src/helpers.cpp b/src/helpers.cpp
new file mode 100644
index 0000000..46dd63e
--- /dev/null
+++ b/src/helpers.cpp
@@ -0,0 +1,518 @@
+// $Id: helpers.cpp,v 1.12 2002/09/21 17:23:32 t1mpy Exp $
+
+// id3lib: a C++ library for creating and manipulating id3v1/v2 tags
+// Copyright 1999, 2000 Scott Thomas Haug
+
+// Lots of hacking added to this file by Scott Wheeler (scott@slackorama.net)
+// 11/02/2001
+
+// 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 "helpers.h"
+#include "tag_impl.h" //has <stdio.h> "tag.h" "header_tag.h" "frame.h" "field.h" "spec.h" "id3lib_strings.h" "utils.h"
+
+using namespace dami;
+
+/** Helper function to get a "good" string for a field, no matter what. */
+String id3::v2::getString(const ID3_Frame* frame, ID3_FieldID fldName)
+{
+ return getStringAtIndex( frame, fldName, 0 );
+}
+
+/** Helper function to get a "good" string for a field, no matter what. */
+String id3::v2::getStringAtIndex(const ID3_Frame* frame, ID3_FieldID fldName,
+ size_t nIndex)
+{
+ if (!frame)
+ return "";
+
+ ID3_Field* fp = frame->GetField(fldName);
+ if (!fp)
+ return "";
+
+ return fp->GetText( nIndex, fp->GetEncoding() );
+}
+
+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;
+}
+
+String id3::v2::getFrameText(const ID3_TagImpl& tag, ID3_FrameID id)
+{
+ ID3_Frame* frame = tag.Find(id);
+ return getString(frame, ID3FN_TEXT);
+}
+
+ID3_Frame* id3::v2::setFrameText(ID3_TagImpl& tag, ID3_FrameID id, String text)
+{
+ ID3_Frame* frame = tag.Find(id);
+ if (!frame)
+ {
+ frame = new ID3_Frame(id);
+ if(!tag.AttachFrame(frame)) return NULL;
+ }
+ frame->GetField(ID3FN_TEXT)->Set(text.c_str());
+
+ return frame;
+}
+
+////////////////////////////////////////////////////////////
+
+ID3_Frame* id3::v2::hasArtist(const ID3_TagImpl& tag)
+{
+ ID3_Frame* fp = NULL;
+ (fp = tag.Find(ID3FID_LEADARTIST)) ||
+ (fp = tag.Find(ID3FID_BAND)) ||
+ (fp = tag.Find(ID3FID_CONDUCTOR)) ||
+ (fp = tag.Find(ID3FID_COMPOSER));
+ return fp;
+}
+
+String id3::v2::getArtist(const ID3_TagImpl& tag)
+{
+ ID3_Frame* frame = hasArtist(tag);
+ return getString(frame, ID3FN_TEXT);
+}
+
+ID3_Frame* id3::v2::setArtist(ID3_TagImpl& tag, String text)
+{
+ removeArtists(tag);
+ return setFrameText(tag, ID3FID_LEADARTIST, text);
+}
+
+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;
+}
+
+////////////////////////////////////////////////////////////
+
+ID3_Frame* id3::v2::hasAlbum(const ID3_TagImpl& tag)
+{
+ ID3_Frame* frame = tag.Find(ID3FID_ALBUM);
+ return(frame);
+}
+
+String id3::v2::getAlbum(const ID3_TagImpl& tag)
+{
+ return getFrameText(tag, ID3FID_ALBUM);
+}
+
+ID3_Frame* id3::v2::setAlbum(ID3_TagImpl& tag, String text)
+{
+ return setFrameText(tag, ID3FID_ALBUM, text);
+}
+
+size_t id3::v2::removeAlbums(ID3_TagImpl& tag)
+{
+ return removeFrames(tag, ID3FID_ALBUM);
+}
+
+////////////////////////////////////////////////////////////
+
+ID3_Frame* id3::v2::hasTitle(const ID3_TagImpl& tag)
+{
+ ID3_Frame* frame = tag.Find(ID3FID_TITLE);
+ return(frame);
+}
+
+String id3::v2::getTitle(const ID3_TagImpl& tag)
+{
+ return getFrameText(tag, ID3FID_TITLE);
+}
+
+ID3_Frame* id3::v2::setTitle(ID3_TagImpl& tag, String text)
+{
+ return setFrameText(tag, ID3FID_TITLE, text);
+}
+
+size_t id3::v2::removeTitles(ID3_TagImpl& tag)
+{
+ return removeFrames(tag, ID3FID_TITLE);
+}
+
+////////////////////////////////////////////////////////////
+
+ID3_Frame* id3::v2::hasYear(const ID3_TagImpl& tag)
+{
+ ID3_Frame* frame = tag.Find(ID3FID_YEAR);
+ return(frame);
+}
+
+String id3::v2::getYear(const ID3_TagImpl& tag)
+{
+ return getFrameText(tag, ID3FID_YEAR);
+}
+
+ID3_Frame* id3::v2::setYear(ID3_TagImpl& tag, String text)
+{
+ return setFrameText(tag, ID3FID_YEAR, text);
+}
+
+size_t id3::v2::removeYears(ID3_TagImpl& tag)
+{
+ return removeFrames(tag, ID3FID_YEAR);
+}
+
+////////////////////////////////////////////////////////////
+
+ID3_Frame* id3::v2::hasV1Comment(const ID3_TagImpl& tag)
+{
+ ID3_Frame* frame = NULL;
+ (frame = tag.Find(ID3FID_COMMENT, ID3FN_DESCRIPTION, STR_V1_COMMENT_DESC)) ||
+ (frame = tag.Find(ID3FID_COMMENT, ID3FN_DESCRIPTION, "" )) ||
+ (frame = tag.Find(ID3FID_COMMENT));
+ return(frame);
+}
+
+ID3_Frame* id3::v2::hasComment(const ID3_TagImpl& tag)
+{
+ ID3_Frame* frame = tag.Find(ID3FID_COMMENT);
+ return(frame);
+}
+
+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);
+}
+
+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);
+}
+
+ID3_Frame* id3::v2::setComment(ID3_TagImpl& tag, String text, String desc,
+ String lang)
+{
+ ID3D_NOTICE( "id3::v2::setComment: trying to find frame with description = " << desc );
+ ID3_Frame* frame = NULL;
+ // See if there is already a comment with this description
+ for (ID3_TagImpl::iterator iter = tag.begin(); iter != tag.end(); ++iter)
+ {
+ frame = *iter;
+ if (frame == NULL)
+ {
+ continue;
+ }
+ if (frame->GetID() == ID3FID_COMMENT)
+ {
+ String tmpDesc = getString(frame, ID3FN_DESCRIPTION);
+ if (tmpDesc == desc)
+ {
+ ID3D_NOTICE( "id3::v2::setComment: found frame with description = " << desc );
+ break;
+ }
+ }
+ frame = NULL;
+ }
+ if (frame == NULL)
+ {
+ ID3D_NOTICE( "id3::v2::setComment: creating new comment frame" );
+ frame = new ID3_Frame(ID3FID_COMMENT);
+ if(!tag.AttachFrame(frame)) return NULL;
+ }
+ if (!frame)
+ {
+ ID3D_WARNING( "id3::v2::setComment: ack! no frame" );
+ }
+ else
+ {
+ frame->GetField(ID3FN_LANGUAGE)->Set(lang.c_str());
+ frame->GetField(ID3FN_DESCRIPTION)->Set(desc.c_str());
+ frame->GetField(ID3FN_TEXT)->Set(text.c_str());
+ }
+
+ return frame;
+}
+
+// Remove all comments from the tag
+size_t id3::v2::removeAllComments(ID3_TagImpl& tag)
+{
+ return removeFrames(tag, ID3FID_COMMENT);
+}
+
+// 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;
+}
+
+////////////////////////////////////////////////////////////
+
+ID3_Frame* id3::v2::hasTrack(const ID3_TagImpl& tag)
+{
+ ID3_Frame* frame = tag.Find(ID3FID_TRACKNUM);
+ return(frame);
+}
+
+String id3::v2::getTrack(const ID3_TagImpl& tag)
+{
+ return getFrameText(tag, ID3FID_TRACKNUM);
+}
+
+size_t id3::v2::getTrackNum(const ID3_TagImpl& tag)
+{
+ String sTrack = getTrack(tag);
+ return ::atoi(sTrack.c_str());
+}
+
+ID3_Frame* id3::v2::setTrack(ID3_TagImpl& tag, uchar trk, uchar ttl)
+{
+ ID3_Frame* frame = NULL;
+ String track = toString((size_t)trk);
+ if (ttl > 0)
+ {
+ track += "/";
+ track += toString((size_t)ttl);
+ }
+ setFrameText(tag, ID3FID_TRACKNUM, track);
+
+ return frame;
+}
+
+size_t id3::v2::removeTracks(ID3_TagImpl& tag)
+{
+ return removeFrames(tag, ID3FID_TRACKNUM);
+}
+
+////////////////////////////////////////////////////////////
+
+ID3_Frame* id3::v2::hasGenre(const ID3_TagImpl& tag)
+{
+ ID3_Frame* frame = tag.Find(ID3FID_CONTENTTYPE);
+ return(frame);
+}
+
+String id3::v2::getGenre(const ID3_TagImpl& tag)
+{
+ return getFrameText(tag, ID3FID_CONTENTTYPE);
+}
+
+size_t id3::v2::getGenreNum(const ID3_TagImpl& tag)
+{
+ String sGenre = getGenre(tag);
+ size_t ulGenre = 0xFF;
+ size_t size = sGenre.size();
+
+ // If the genre string begins with "(ddd)", where "ddd" is a number, then
+ // "ddd" is the genre number---get it
+ size_t i = 0;
+ if (i < size && size && sGenre[i] == '(')
+ {
+ ++i;
+ while (i < size && isdigit(sGenre[i]))
+ {
+ ++i;
+ }
+ if (i < size && sGenre[i] == ')')
+ {
+ // if the genre number is greater than 255, its invalid.
+ ulGenre = min(0xFF, atoi(&sGenre[1]));
+ }
+ }
+
+ return ulGenre;
+}
+
+ID3_Frame* id3::v2::setGenre(ID3_TagImpl& tag, size_t genre)
+{
+ String sGenre = "(";
+ sGenre += toString(genre) + ")";
+ return setFrameText(tag, ID3FID_CONTENTTYPE, sGenre);
+}
+
+size_t id3::v2::removeGenres(ID3_TagImpl& tag)
+{
+ return removeFrames(tag, ID3FID_CONTENTTYPE);
+}
+
+////////////////////////////////////////////////////////////
+
+ID3_Frame* id3::v2::hasLyrics(const ID3_TagImpl& tag)
+{
+ ID3_Frame* frame = tag.Find(ID3FID_UNSYNCEDLYRICS);
+ return(frame);
+}
+
+String id3::v2::getLyrics(const ID3_TagImpl& tag)
+{
+ return getFrameText(tag, ID3FID_UNSYNCEDLYRICS);
+}
+
+ID3_Frame* id3::v2::setLyrics(ID3_TagImpl& tag, String text, String desc,
+ String lang)
+{
+ ID3_Frame* frame = NULL;
+ // See if there is already a comment with this description
+ for (ID3_TagImpl::iterator iter = tag.begin(); iter != tag.end(); ++iter)
+ {
+ frame = *iter;
+ if (frame == NULL)
+ {
+ continue;
+ }
+ if (frame->GetID() == ID3FID_COMMENT)
+ {
+ String tmpDesc = getString(frame, ID3FN_DESCRIPTION);
+ if (tmpDesc == desc)
+ {
+ break;
+ }
+ }
+ frame = NULL;
+ }
+ if (frame == NULL)
+ {
+ frame = new ID3_Frame(ID3FID_UNSYNCEDLYRICS);
+ if(!tag.AttachFrame(frame)) return NULL;
+ }
+ frame->GetField(ID3FN_LANGUAGE)->Set(lang.c_str());
+ frame->GetField(ID3FN_DESCRIPTION)->Set(desc.c_str());
+ frame->GetField(ID3FN_TEXT)->Set(text.c_str());
+
+ return frame;
+}
+
+size_t id3::v2::removeLyrics(ID3_TagImpl& tag)
+{
+ return removeFrames(tag, ID3FID_UNSYNCEDLYRICS);
+}
+
+String id3::v2::getLyricist(const ID3_TagImpl& tag)
+{
+ return getFrameText(tag, ID3FID_LYRICIST);
+}
+
+ID3_Frame* id3::v2::setLyricist(ID3_TagImpl& tag, String text)
+{
+ return setFrameText(tag, ID3FID_LYRICIST, text);
+}
+
+size_t id3::v2::removeLyricists(ID3_TagImpl& tag)
+{
+ return removeFrames(tag, ID3FID_LYRICIST);
+}
+
+////////////////////////////////////////////////////////////
+
+ID3_Frame* id3::v2::hasSyncLyrics(const ID3_TagImpl& tag, String lang, String desc)
+{
+ ID3_Frame* frame=NULL;
+ (frame = tag.Find(ID3FID_SYNCEDLYRICS, ID3FN_LANGUAGE, lang.c_str())) ||
+ (frame = tag.Find(ID3FID_SYNCEDLYRICS, ID3FN_DESCRIPTION, desc.c_str()));
+ return(frame);
+}
+
+ID3_Frame* id3::v2::setSyncLyrics(ID3_TagImpl& tag, BString data,
+ ID3_TimeStampFormat format, String desc,
+ String lang, ID3_ContentType type)
+{
+ ID3_Frame* frame = NULL;
+
+ // check if a SYLT frame of this language or descriptor already exists
+ (frame = tag.Find(ID3FID_SYNCEDLYRICS, ID3FN_LANGUAGE, lang.c_str())) ||
+ (frame = tag.Find(ID3FID_SYNCEDLYRICS, ID3FN_DESCRIPTION, desc.c_str()));
+
+ if (!frame)
+ {
+ frame = new ID3_Frame(ID3FID_SYNCEDLYRICS);
+ if(!tag.AttachFrame(frame)) return NULL;
+ }
+ frame->GetField(ID3FN_LANGUAGE)->Set(lang.c_str());
+ frame->GetField(ID3FN_DESCRIPTION)->Set(desc.c_str());
+ frame->GetField(ID3FN_TIMESTAMPFORMAT)->Set(format);
+ frame->GetField(ID3FN_CONTENTTYPE)->Set(type);
+ frame->GetField(ID3FN_DATA)->Set(data.data(), data.size());
+
+ return frame;
+}
+
+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());
+}
+