]> granicus.if.org Git - taglib/commitdiff
Adding Ogg/FLAC support to TagLib
authorAllan Sandfeld Jensen <kde@carewolf.com>
Tue, 6 Apr 2004 20:35:29 +0000 (20:35 +0000)
committerAllan Sandfeld Jensen <kde@carewolf.com>
Tue, 6 Apr 2004 20:35:29 +0000 (20:35 +0000)
git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@301825 283d02a7-25f6-0310-bc7c-ecb5cbfe19da

ogg/Makefile.am
ogg/flac/Makefile.am [new file with mode: 0644]
ogg/flac/oggflacfile.cpp [new file with mode: 0644]
ogg/flac/oggflacfile.h [new file with mode: 0644]

index 915146bfedafdf9bbf776558906e8f027bd95eb9..d80e5e4fe34b2e8f56e9dedbc602e74a5e798399 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS = vorbis
+SUBDIRS = vorbis flac
 
 INCLUDES = -I$(top_srcdir)/taglib -I$(top_srcdir)/taglib/toolkit $(all_includes)
 
@@ -18,6 +18,6 @@ taglib_include_HEADERS = \
 
 taglib_includedir = $(includedir)/taglib
 
-libogg_la_LIBADD = ./vorbis/libvorbis.la
+libogg_la_LIBADD = ./vorbis/libvorbis.la ./flac/liboggflac.la
 
 EXTRA_DIST = $(libogg_la_SOURCES) $(taglib_include_HEADERS)
diff --git a/ogg/flac/Makefile.am b/ogg/flac/Makefile.am
new file mode 100644 (file)
index 0000000..83c0853
--- /dev/null
@@ -0,0 +1,15 @@
+INCLUDES = \
+       -I$(top_srcdir)/taglib \
+       -I$(top_srcdir)/taglib/toolkit \
+       -I$(top_srcdir)/taglib/ogg \
+       -I$(top_srcdir)/taglib/flac \
+       $(all_includes)
+
+noinst_LTLIBRARIES = liboggflac.la
+
+liboggflac_la_SOURCES = oggflacfile.cpp
+
+taglib_include_HEADERS = oggflacfile.h
+taglib_includedir = $(includedir)/taglib
+
+EXTRA_DIST = $(liboggflac_la_SOURCES) $(taglib_include_HEADERS)
diff --git a/ogg/flac/oggflacfile.cpp b/ogg/flac/oggflacfile.cpp
new file mode 100644 (file)
index 0000000..210b3b3
--- /dev/null
@@ -0,0 +1,247 @@
+/***************************************************************************
+    copyright            : (C) 2004 by Allan Sandfeld Jensen
+    email                : kde@carewolf.org
+ ***************************************************************************/
+
+/***************************************************************************
+ *   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                                                                   *
+ ***************************************************************************/
+
+#include <tbytevector.h>
+#include <tstring.h>
+#include <tdebug.h>
+
+#include <xiphcomment.h>
+#include "oggflacfile.h"
+
+using namespace TagLib;
+using TagLib::FLAC::Properties;
+
+class Ogg::FLAC::File::FilePrivate
+{
+public:
+  FilePrivate() :
+    comment(0),
+    properties(0),
+    streamStart(0),
+    streamLength(0),
+    scanned(false),
+    hasXiphComment(false),
+    commentPacket(0) {}
+
+  ~FilePrivate()
+  {
+    delete comment;
+    delete properties;
+  }
+
+  Ogg::XiphComment *comment;
+
+  Properties *properties;
+  ByteVector streamInfoData;
+  ByteVector xiphCommentData;
+  long streamStart;
+  long streamLength;
+  bool scanned;
+
+  bool hasXiphComment;
+  int commentPacket;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// public members
+////////////////////////////////////////////////////////////////////////////////
+
+Ogg::FLAC::File::File(const char *file, bool readProperties,
+                 Properties::ReadStyle propertiesStyle) : Ogg::File(file)
+{
+  d = new FilePrivate;
+  read(readProperties, propertiesStyle);
+}
+
+Ogg::FLAC::File::~File()
+{
+  delete d;
+}
+
+TagLib::Tag* Ogg::FLAC::File::tag() const
+{
+  return d->comment;
+}
+
+Properties* Ogg::FLAC::File::audioProperties() const
+{
+  return d->properties;
+}
+
+
+void Ogg::FLAC::File::save()
+{
+  d->xiphCommentData = d->comment->render();
+
+  // Create FLAC metadata-block:
+
+  // Put the size in the first 32 bit ( I assume no more than 24 bit are used )
+
+  ByteVector v = ByteVector::fromUInt(d->xiphCommentData.size());
+
+  // Set the type of the metadata-block to be a Xiph / Vorbis comment
+
+  v[0] = 4;
+
+  // Append the comment-data after the 32 bit header
+
+  v.append(d->xiphCommentData);
+
+  // Save the packet at the old spot
+  // FIXME: Use padding if size is increasing
+
+  setPacket(d->commentPacket, v);
+
+  Ogg::File::save();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// private members
+////////////////////////////////////////////////////////////////////////////////
+
+void Ogg::FLAC::File::read(bool readProperties, Properties::ReadStyle propertiesStyle)
+{
+  // Sanity: Check if we really have an Ogg/FLAC file
+
+/*
+  ByteVector oggHeader = packet(0);
+
+  if (oggHeader.mid(28,4) != "fLaC") {
+    debug("Ogg::FLAC::File::read() -- Not an Ogg/FLAC file");
+    setValid(false);
+    return;
+  }*/
+
+  // Look for FLAC metadata, including vorbis comments
+
+  scan();
+
+  if (!d->scanned) {
+    setValid(false);
+    return;
+  }
+
+
+  if(d->hasXiphComment)
+    d->comment = new Ogg::XiphComment(xiphCommentData());
+  else {
+    d->comment = new Ogg::XiphComment();
+  }
+
+
+  if(readProperties)
+    d->properties = new Properties(streamInfoData(), streamLength(), propertiesStyle);
+}
+
+ByteVector Ogg::FLAC::File::streamInfoData()
+{
+  scan();
+  return d->streamInfoData;
+}
+
+ByteVector Ogg::FLAC::File::xiphCommentData()
+{
+  scan();
+  return d->xiphCommentData;
+}
+
+long Ogg::FLAC::File::streamLength()
+{
+  scan();
+  return d->streamLength;
+}
+
+void Ogg::FLAC::File::scan()
+{
+  // Scan the metadata pages
+
+  if(d->scanned)
+    return;
+
+  if(!isValid())
+    return;
+
+  int ipacket = 1;
+  long overhead = 0;
+
+  ByteVector metadataHeader = packet(ipacket);
+
+  if (metadataHeader == ByteVector::null)
+    return;
+
+  ByteVector header = metadataHeader.mid(0,4);
+
+  // Header format (from spec):
+  // <1> Last-metadata-block flag
+  // <7> BLOCK_TYPE
+  //   0 : STREAMINFO
+  //    1 : PADDING
+  //    ..
+  //    4 : VORBIS_COMMENT
+  //    ..
+  // <24> Length of metadata to follow
+
+  char blockType = header[0] & 0x7f;
+  bool lastBlock = header[0] & 0x80;
+  uint length = header.mid(1, 3).toUInt();
+  overhead += length;
+
+  // Sanity: First block should be the stream_info metadata
+
+  if(blockType != 0) {
+    debug("Ogg::FLAC::File::scan() -- Invalid Ogg/FLAC stream");
+    return;
+  }
+
+  d->streamInfoData = metadataHeader.mid(4,length);
+
+  // Search through the remaining metadata
+
+  while(!lastBlock) {
+    metadataHeader = packet(++ipacket);
+
+    header = metadataHeader.mid(0, 4);
+    blockType = header[0] & 0x7f;
+    lastBlock = header[0] & 0x80;
+    length = header.mid(1, 3).toUInt();
+    overhead += length;
+
+    if(blockType == 1) {
+//      debug("Ogg::FLAC::File::scan() -- Padding found");
+    } else
+    if(blockType == 4) {
+//      debug("Ogg::FLAC::File::scan() -- Vorbis-comments found");
+      d->xiphCommentData = metadataHeader.mid(4, length);
+      d->hasXiphComment = true;
+      d->commentPacket = ipacket;
+    } else
+    if(blockType > 5) {
+      debug("Ogg::FLAC::File::scan() -- Unknown metadata block");
+    }
+
+  }
+
+  // End of metadata, now comes the datastream
+  d->streamStart = overhead;
+  d->streamLength = File::length() - d->streamStart;
+
+  d->scanned = true;
+}
diff --git a/ogg/flac/oggflacfile.h b/ogg/flac/oggflacfile.h
new file mode 100644 (file)
index 0000000..3c3900a
--- /dev/null
@@ -0,0 +1,110 @@
+/***************************************************************************
+    copyright            : (C) 2004 by Allan Sandfeld Jensen
+    email                : kde@carewolf.org
+ ***************************************************************************/
+
+/***************************************************************************
+ *   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                                                                   *
+ ***************************************************************************/
+
+#ifndef TAGLIB_OGGFLACFILE_H
+#define TAGLIB_OGGFLACFILE_H
+
+#include <oggfile.h>
+
+#include <flacproperties.h>
+
+namespace TagLib {
+
+  class Tag;
+
+  //! An implementation of Ogg/FLAC metadata
+
+  /*!
+   * This is implementation of FLAC metadata for Ogg/FLAC files.  For native
+   * FLAC files look under the FLAC hiearchy.
+   *
+   * Unlike native FLAC-files, Ogg/FLAC only supports Xiph-comments, 
+   * while the audio-properties are the same.
+   */
+
+  namespace Ogg {
+  namespace FLAC {
+
+    using TagLib::FLAC::Properties;
+    
+    //! An implementation of TagLib::File with Ogg/FLAC specific methods
+
+    /*!
+     * This implements and provides an interface for Ogg/FLAC files to the
+     * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
+     * the abstract TagLib::File API as well as providing some additional
+     * information specific to Ogg/FLAC files.
+     */
+
+    class File : public TagLib::Ogg::File
+    {
+    public:
+      /*!
+       * Contructs an Ogg/FLAC file from \a file.  If \a readProperties is true
+       * the file's audio properties will also be read using \a propertiesStyle.        * If false, \a propertiesStyle is ignored.
+       */
+      File(const char *file, bool readProperties = true,
+           Properties::ReadStyle propertiesStyle = Properties::Average);
+
+      /*!
+       * Destroys this instance of the File.
+       */
+      virtual ~File();
+
+      /*!
+       * Returns the Tag for this file.  This will always be a XiphComment.
+       */
+      virtual TagLib::Tag *tag() const;
+
+      /*!
+       * Returns the FLAC::Properties for this file.  If no audio properties
+       * were read then this will return a null pointer.
+       */
+      virtual Properties *audioProperties() const;
+
+      /*!
+       * Save the file.  This will primarily save and update the XiphComment.
+       */
+      virtual void save();
+
+      /*!
+       * Returns the length of the audio-stream, used by FLAC::Properties for
+       * calculating the bitrate.
+       */
+      long streamLength();
+
+    private:
+      File(const File &);
+      File &operator=(const File &);
+
+      void read(bool readProperties, Properties::ReadStyle propertiesStyle);
+      void scan();
+      ByteVector streamInfoData();
+      ByteVector xiphCommentData();
+
+      class FilePrivate;
+      FilePrivate *d;
+    };
+  } // namespace FLAC
+  } // namespace Ogg
+} // namespace TagLib
+
+#endif