]> granicus.if.org Git - taglib/commitdiff
Support for URL link framesSupport for URL link frames, patch by Urs Fleisch.
authorLukáš Lalinský <lalinsky@gmail.com>
Thu, 22 Nov 2007 13:48:01 +0000 (13:48 +0000)
committerLukáš Lalinský <lalinsky@gmail.com>
Thu, 22 Nov 2007 13:48:01 +0000 (13:48 +0000)
BUG:151079
CCMAIL:ufleisch@users.sourceforge.net

git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@740080 283d02a7-25f6-0310-bc7c-ecb5cbfe19da

taglib/CMakeLists.txt
taglib/mpeg/id3v2/frames/CMakeLists.txt
taglib/mpeg/id3v2/frames/Makefile.am
taglib/mpeg/id3v2/frames/urllinkframe.cpp [new file with mode: 0644]
taglib/mpeg/id3v2/frames/urllinkframe.h [new file with mode: 0644]
taglib/mpeg/id3v2/id3v2framefactory.cpp
tests/test_id3v2.cpp

index 9957458f399a37ba61908695258af98f17c5fb8f..b036185820df0b300fa5a18144de9fd4beb91ef9 100644 (file)
@@ -67,6 +67,7 @@ mpeg/id3v2/frames/relativevolumeframe.cpp
 mpeg/id3v2/frames/textidentificationframe.cpp
 mpeg/id3v2/frames/uniquefileidentifierframe.cpp
 mpeg/id3v2/frames/unknownframe.cpp
+mpeg/id3v2/frames/urllinkframe.cpp
 )
 
 SET(ogg_SRCS
index e076918bd98521bc23ee5c41d1b564d25de61466..90716949fe5d31adb104f7acd01c200749ef0fac 100644 (file)
@@ -1,35 +1,10 @@
-INSTALL( FILES  attachedpictureframe.h         commentsframe.h         generalencapsulatedobjectframe.h        relativevolumeframe.h   textidentificationframe.h       uniquefileidentifierframe.h     unknownframe.h DESTINATION ${INCLUDE_INSTALL_DIR}/taglib)
-
-
-
-#original Makefile.am contents follow:
-
-#INCLUDES = \
-#      -I$(top_srcdir)/taglib \
-#      -I$(top_srcdir)/taglib/toolkit \
-#      -I$(top_srcdir)/taglib/mpeg/id3v2 \
-#      $(all_includes)
-#
-#noinst_LTLIBRARIES = libframes.la
-#
-#libframes_la_SOURCES = \
-#      attachedpictureframe.cpp \
-#      commentsframe.cpp \
-#      generalencapsulatedobjectframe.cpp \
-#      relativevolumeframe.cpp \
-#      textidentificationframe.cpp \
-#      uniquefileidentifierframe.cpp \
-#      unknownframe.cpp
-#
-#taglib_include_HEADERS = \
-#      attachedpictureframe.h \
-#      commentsframe.h \
-#      generalencapsulatedobjectframe.h \
-#      relativevolumeframe.h \
-#      textidentificationframe.h \
-#      uniquefileidentifierframe.h \
-#      unknownframe.h
-#
-#taglib_includedir = $(includedir)/taglib
-#
-#EXTRA_DIST = $(libframes_la_SOURCES) $(taglib_include_HEADERS)
+INSTALL(FILES
+       attachedpictureframe.h
+       commentsframe.h
+       generalencapsulatedobjectframe.h
+       relativevolumeframe.h
+       textidentificationframe.h
+       uniquefileidentifierframe.h
+       unknownframe.h
+       urllinkframe.h
+       DESTINATION ${INCLUDE_INSTALL_DIR}/taglib)
index 8026a23379c6e470a3407f3a51cc410296fcb890..bb8affd4a7cadf2ec3d5b466fecb310c8724d743 100644 (file)
@@ -13,7 +13,8 @@ libframes_la_SOURCES = \
        relativevolumeframe.cpp \
        textidentificationframe.cpp \
        uniquefileidentifierframe.cpp \
-       unknownframe.cpp
+       unknownframe.cpp \
+       urllinkframe.cpp
 
 taglib_include_HEADERS = \
        attachedpictureframe.h \
@@ -22,6 +23,7 @@ taglib_include_HEADERS = \
        relativevolumeframe.h \
        textidentificationframe.h \
        uniquefileidentifierframe.h \
-       unknownframe.h
+       unknownframe.h \
+       urllinkframe.h
 
 taglib_includedir = $(includedir)/taglib
diff --git a/taglib/mpeg/id3v2/frames/urllinkframe.cpp b/taglib/mpeg/id3v2/frames/urllinkframe.cpp
new file mode 100644 (file)
index 0000000..2e9ac59
--- /dev/null
@@ -0,0 +1,186 @@
+/***************************************************************************
+    copyright            : (C) 2002, 2003 by Scott Wheeler
+    email                : wheeler@kde.org
+    copyright            : (C) 2006 by Urs Fleisch
+    email                : ufleisch@users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *   This library is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Lesser General Public License version   *
+ *   2.1 as published by the Free Software Foundation.                     *
+ *                                                                         *
+ *   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     *
+ *   Lesser General Public License for more details.                       *
+ *                                                                         *
+ *   You should have received a copy of the GNU Lesser 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                                                                   *
+ *                                                                         *
+ *   Alternatively, this file is available under the Mozilla Public        *
+ *   License Version 1.1.  You may obtain a copy of the License at         *
+ *   http://www.mozilla.org/MPL/                                           *
+ ***************************************************************************/
+
+#include "urllinkframe.h"
+#include <tdebug.h>
+
+using namespace TagLib;
+using namespace ID3v2;
+
+class UrlLinkFrame::UrlLinkFramePrivate {
+public:
+  String url;
+};
+
+class UserUrlLinkFrame::UserUrlLinkFramePrivate {
+public:
+  UserUrlLinkFramePrivate() : textEncoding(String::Latin1) {}
+  String::Type textEncoding;
+  String description;
+};
+
+UrlLinkFrame::UrlLinkFrame(const ByteVector &data) :
+  Frame(data)
+{
+  d = new UrlLinkFramePrivate;
+  setData(data);
+}
+
+UrlLinkFrame::~UrlLinkFrame()
+{
+  delete d;
+}
+
+void UrlLinkFrame::setUrl(const String &s)
+{
+  d->url = s;
+}
+
+String UrlLinkFrame::url() const
+{
+  return d->url;
+}
+
+void UrlLinkFrame::setText(const String &s)
+{
+  setUrl(s);
+}
+
+String UrlLinkFrame::toString() const
+{
+  return url();
+}
+
+void UrlLinkFrame::parseFields(const ByteVector &data)
+{
+  d->url = String(data);
+}
+
+ByteVector UrlLinkFrame::renderFields() const
+{
+  return d->url.data(String::Latin1);
+}
+
+UrlLinkFrame::UrlLinkFrame(const ByteVector &data, Header *h) : Frame(h)
+{
+  d = new UrlLinkFramePrivate;
+  parseFields(fieldData(data));
+}
+
+
+UserUrlLinkFrame::UserUrlLinkFrame(String::Type encoding) :
+  UrlLinkFrame("WXXX")
+{
+  d = new UserUrlLinkFramePrivate;
+  d->textEncoding = encoding;
+}
+
+UserUrlLinkFrame::UserUrlLinkFrame(const ByteVector &data) :
+  UrlLinkFrame(data)
+{
+  d = new UserUrlLinkFramePrivate;
+  setData(data);
+}
+
+UserUrlLinkFrame::~UserUrlLinkFrame()
+{
+  delete d;
+}
+
+String UserUrlLinkFrame::toString() const
+{
+  return "[" + description() + "] " + url();
+}
+
+String::Type UserUrlLinkFrame::textEncoding() const
+{
+  return d->textEncoding;
+}
+
+void UserUrlLinkFrame::setTextEncoding(String::Type encoding)
+{
+  d->textEncoding = encoding;
+}
+
+String UserUrlLinkFrame::description() const
+{
+  return d->description;
+}
+
+void UserUrlLinkFrame::setDescription(const String &s)
+{
+  d->description = s;
+}
+
+void UserUrlLinkFrame::parseFields(const ByteVector &data)
+{
+  if (data.size() < 2) {
+    debug("A user URL link frame must contain at least 2 bytes.");
+    return;
+  }
+
+  int pos = 0;
+
+  d->textEncoding = String::Type(data[0]);
+  pos += 1;
+
+  if (d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8) {
+    int offset = data.find(textDelimiter(d->textEncoding), pos);
+    if (offset < pos)
+      return;
+
+    d->description = String(data.mid(pos, offset - pos), d->textEncoding);
+    pos = offset + 1;
+  } else {
+    int len = data.mid(pos).find(textDelimiter(d->textEncoding), 0, 2);
+    if (len < 0)
+      return;
+
+    d->description = String(data.mid(pos, len), d->textEncoding);
+    pos += len + 2;
+  }
+
+  setUrl(String(data.mid(pos)));
+}
+
+ByteVector UserUrlLinkFrame::renderFields() const
+{
+  ByteVector v;
+
+  v.append(char(d->textEncoding));
+  v.append(d->description.data(d->textEncoding));
+  v.append(textDelimiter(d->textEncoding));
+  v.append(url().data(String::Latin1));
+
+  return v;
+}
+
+UserUrlLinkFrame::UserUrlLinkFrame(const ByteVector &data, Header *h) : UrlLinkFrame(data, h)
+{
+  d = new UserUrlLinkFramePrivate;
+  parseFields(fieldData(data));
+}
diff --git a/taglib/mpeg/id3v2/frames/urllinkframe.h b/taglib/mpeg/id3v2/frames/urllinkframe.h
new file mode 100644 (file)
index 0000000..8ff2ec9
--- /dev/null
@@ -0,0 +1,167 @@
+/***************************************************************************
+    copyright            : (C) 2002, 2003 by Scott Wheeler
+    email                : wheeler@kde.org
+    copyright            : (C) 2006 by Urs Fleisch
+    email                : ufleisch@users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *   This library is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Lesser General Public License version   *
+ *   2.1 as published by the Free Software Foundation.                     *
+ *                                                                         *
+ *   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     *
+ *   Lesser General Public License for more details.                       *
+ *                                                                         *
+ *   You should have received a copy of the GNU Lesser 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                                                                   *
+ *                                                                         *
+ *   Alternatively, this file is available under the Mozilla Public        *
+ *   License Version 1.1.  You may obtain a copy of the License at         *
+ *   http://www.mozilla.org/MPL/                                           *
+ ***************************************************************************/
+
+#ifndef TAGLIB_URLLINKFRAME_H
+#define TAGLIB_URLLINKFRAME_H
+
+#include <id3v2frame.h>
+
+namespace TagLib {
+
+  namespace ID3v2 {
+
+    /*!
+     * An implementation of ID3v2 URL link frames.
+     */
+    class UrlLinkFrame : public Frame {
+      friend class FrameFactory;
+
+    public:
+      /*!
+       * This is a dual purpose constructor.  \a data can either be binary data
+       * that should be parsed or (at a minimum) the frame ID.
+       */
+      explicit UrlLinkFrame(const ByteVector &data);
+
+      /*!
+       * Destroys this UrlLinkFrame instance.
+       */
+      virtual ~UrlLinkFrame();
+
+      /*!
+       * Returns the URL.
+       */
+      virtual String url() const;
+
+      /*!
+       * Sets the URL to \a s.
+       */
+      virtual void setUrl(const String &s);
+
+      // Reimplementations.
+
+      virtual void setText(const String &s);
+      virtual String toString() const;
+
+    protected:
+      virtual void parseFields(const ByteVector &data);
+      virtual ByteVector renderFields() const;
+
+      /*!
+       * The constructor used by the FrameFactory.
+       */
+      UrlLinkFrame(const ByteVector &data, Header *h);
+
+    private:
+      UrlLinkFrame(const UrlLinkFrame &);
+      UrlLinkFrame &operator=(const UrlLinkFrame &);
+
+      class UrlLinkFramePrivate;
+      UrlLinkFramePrivate *d;
+    };
+
+    /*!
+     * This is a specialization of URL link frames that allows for
+     * user defined entries.  Each entry has a description in addition to the
+     * normal list of fields that a URL link frame has.
+     *
+     * This description identifies the frame and must be unique.
+     */
+    class UserUrlLinkFrame : public UrlLinkFrame {
+      friend class FrameFactory;
+
+    public:
+      /*!
+       * Constructs an empty user defined URL link frame.  For this to be
+       * a useful frame both a description and text must be set.
+       */
+      explicit UserUrlLinkFrame(String::Type encoding = String::Latin1);
+
+      /*!
+       * This is a dual purpose constructor.  \a data can either be binary data
+       * that should be parsed or (at a minimum) the frame ID.
+       */
+      explicit UserUrlLinkFrame(const ByteVector &data);
+
+      /*!
+       * Destroys this UserUrlLinkFrame instance.
+       */
+      virtual ~UserUrlLinkFrame();
+
+      // Reimplementations.
+
+      virtual String toString() const;
+
+      /*!
+       * Returns the text encoding that will be used in rendering this frame.
+       * This defaults to the type that was either specified in the constructor
+       * or read from the frame when parsed.
+       *
+       * \see setTextEncoding()
+       * \see render()
+       */
+      String::Type textEncoding() const;
+
+      /*!
+       * Sets the text encoding to be used when rendering this frame to
+       * \a encoding.
+       *
+       * \see textEncoding()
+       * \see render()
+       */
+      void setTextEncoding(String::Type encoding);
+
+      /*!
+       * Returns the description for this frame.
+       */
+      String description() const;
+
+      /*!
+       * Sets the description of the frame to \a s.  \a s must be unique.
+       */
+      void setDescription(const String &s);
+
+    protected:
+      virtual void parseFields(const ByteVector &data);
+      virtual ByteVector renderFields() const;
+
+      /*!
+       * The constructor used by the FrameFactory.
+       */
+      UserUrlLinkFrame(const ByteVector &data, Header *h);
+
+    private:
+      UserUrlLinkFrame(const UserUrlLinkFrame &);
+      UserUrlLinkFrame &operator=(const UserUrlLinkFrame &);
+
+      class UserUrlLinkFramePrivate;
+      UserUrlLinkFramePrivate *d;
+    };
+
+  }
+}
+#endif
index 02b6cfaf77538b7d073764ab38249dea69a60eb9..3595cc46eee286f726c73d96e426e8b134f2e336 100644 (file)
@@ -37,6 +37,7 @@
 #include "frames/uniquefileidentifierframe.h"
 #include "frames/unknownframe.h"
 #include "frames/generalencapsulatedobjectframe.h"
+#include "frames/urllinkframe.h"
 
 using namespace TagLib;
 using namespace ID3v2;
@@ -187,6 +188,19 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader)
   if(frameID == "GEOB")
     return new GeneralEncapsulatedObjectFrame(data, header);
 
+  // URL link (frames 4.3)
+
+  if(frameID.startsWith("W")) {
+    if(frameID != "WXXX") {
+      return new UrlLinkFrame(data, header);
+    } else {
+      UserUrlLinkFrame *f = new UserUrlLinkFrame(data, header);
+      if(d->useDefaultEncoding)
+        f->setTextEncoding(d->defaultEncoding);
+      return f;
+    }
+  }
+
   return new UnknownFrame(data, header);
 }
 
index bfdf84bbb244e1ff991f245a6cfbc2620642220f..0cd43546d3800cfe6da49ed8b8bc0191fb070b33 100644 (file)
@@ -9,6 +9,7 @@
 #include <attachedpictureframe.h>
 #include <generalencapsulatedobjectframe.h>
 #include <relativevolumeframe.h>
+#include <urllinkframe.h>
 
 using namespace std;
 using namespace TagLib;
@@ -39,6 +40,10 @@ class TestID3v2 : public CppUnit::TestFixture
   CPPUNIT_TEST(testParseEmptyUniqueFileIdentifierFrame);
   CPPUNIT_TEST(testBrokenFrame1);
   //CPPUNIT_TEST(testItunes24FrameSize);
+  CPPUNIT_TEST(testParseUrlLinkFrame);
+  CPPUNIT_TEST(testRenderUrlLinkFrame);
+  CPPUNIT_TEST(testParseUserUrlLinkFrame);
+  CPPUNIT_TEST(testRenderUserUrlLinkFrame);
   CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -166,6 +171,56 @@ public:
                          f.identifier());
   }
 
+  void testParseUrlLinkFrame()
+  {
+    ID3v2::UrlLinkFrame f(
+      ByteVector("WOAF"                      // Frame ID
+                 "\x00\x00\x00\x12"          // Frame size
+                 "\x00\x00"                  // Frame flags
+                 "http://example.com", 28)); // URL
+    CPPUNIT_ASSERT_EQUAL(String("http://example.com"), f.url());
+  }
+
+  void testRenderUrlLinkFrame()
+  {
+    ID3v2::UrlLinkFrame f("WOAF");
+    f.setUrl("http://example.com");
+    CPPUNIT_ASSERT_EQUAL(
+      ByteVector("WOAF"                      // Frame ID
+                 "\x00\x00\x00\x12"          // Frame size
+                 "\x00\x00"                  // Frame flags
+                 "http://example.com", 28),  // URL
+      f.render());
+  }
+
+  void testParseUserUrlLinkFrame()
+  {
+    ID3v2::UserUrlLinkFrame f(
+      ByteVector("WXXX"                      // Frame ID
+                 "\x00\x00\x00\x17"          // Frame size
+                 "\x00\x00"                  // Frame flags
+                 "\x00"                      // Text encoding
+                 "foo\x00"                   // Description
+                 "http://example.com", 33)); // URL
+    CPPUNIT_ASSERT_EQUAL(String("foo"), f.description());
+    CPPUNIT_ASSERT_EQUAL(String("http://example.com"), f.url());
+  }
+
+  void testRenderUserUrlLinkFrame()
+  {
+    ID3v2::UserUrlLinkFrame f;
+    f.setDescription("foo");
+    f.setUrl("http://example.com");
+    CPPUNIT_ASSERT_EQUAL(
+      ByteVector("WXXX"                      // Frame ID
+                 "\x00\x00\x00\x17"          // Frame size
+                 "\x00\x00"                  // Frame flags
+                 "\x00"                      // Text encoding
+                 "foo\x00"                   // Description
+                 "http://example.com", 33),  // URL
+      f.render());
+  }
+
   /*void testItunes24FrameSize()
   {
     MPEG::File f("data/005411.id3", false);