added function readTag() to AudioClip class to read ID3v2 tag info

This commit is contained in:
fgerlits 2005-01-25 18:21:42 +00:00
parent 317b50732f
commit 047a6ba6d0
19 changed files with 350 additions and 92 deletions

View file

@ -21,7 +21,7 @@
# #
# #
# Author : $Author: fgerlits $ # Author : $Author: fgerlits $
# Version : $Revision: 1.24 $ # Version : $Revision: 1.25 $
# Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/etc/Makefile.in,v $ # Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/etc/Makefile.in,v $
# #
# @configure_input@ # @configure_input@
@ -73,6 +73,9 @@ LIBXMLPP_LIBS=@LIBXMLPP_LIBS@
ICU_CFLAGS= ICU_CFLAGS=
ICU_LIBS=`${USR_DIR}/bin/icu-config --ldflags --ldflags-toolutil --ldflags-icuio` ICU_LIBS=`${USR_DIR}/bin/icu-config --ldflags --ldflags-toolutil --ldflags-icuio`
TAGLIB_CFLAGS =`${USR_DIR}/bin/taglib-config --cflags`
TAGLIB_LIBS =`${USR_DIR}/bin/taglib-config --libs`
TEST_RESULTS = ${DOC_DIR}/testResults.xml TEST_RESULTS = ${DOC_DIR}/testResults.xml
# the text result XSLT has to be relative to the test result file, e.g. TMP_DIR # the text result XSLT has to be relative to the test result file, e.g. TMP_DIR
TEST_XSLT = ../etc/testResultToHtml.xsl TEST_XSLT = ../etc/testResultToHtml.xsl
@ -93,12 +96,14 @@ CPPFLAGS = @CPPFLAGS@
CXXFLAGS = @CXXFLAGS@ @DEFS@ @COVERAGE_CXXFLAGS@ -pthread \ CXXFLAGS = @CXXFLAGS@ @DEFS@ @COVERAGE_CXXFLAGS@ -pthread \
-pedantic -Wall -Wno-long-long \ -pedantic -Wall -Wno-long-long \
${ICU_CFLAGS} \ ${ICU_CFLAGS} \
${TAGLIB_CFLAGS} \
${LIBXMLPP_CFLAGS} \ ${LIBXMLPP_CFLAGS} \
-I${USR_INCLUDE_DIR} \ -I${USR_INCLUDE_DIR} \
-I${BOOST_INCLUDE_DIR} \ -I${BOOST_INCLUDE_DIR} \
-I${INCLUDE_DIR} -I${TMP_DIR} -I${INCLUDE_DIR} -I${TMP_DIR}
LDFLAGS = @LDFLAGS@ -pthread \ LDFLAGS = @LDFLAGS@ -pthread \
${ICU_LIBS} \ ${ICU_LIBS} \
${TAGLIB_LIBS} \
${LIBXMLPP_LIBS} \ ${LIBXMLPP_LIBS} \
-L${USR_LIB_DIR} \ -L${USR_LIB_DIR} \
-L${LIB_DIR} -L${LIB_DIR}
@ -142,8 +147,8 @@ TEST_RUNNER_RES = ${TMP_DIR}/${PACKAGE_NAME}_root.res \
${TMP_DIR}/${PACKAGE_NAME}_hu.res \ ${TMP_DIR}/${PACKAGE_NAME}_hu.res \
${TMP_DIR}/${PACKAGE_NAME}_jp.res ${TMP_DIR}/${PACKAGE_NAME}_jp.res
TEST_RUNNER_LIBS = -l${CORE_LIB} ${ICU_LIBS} -lboost_date_time-gcc \ TEST_RUNNER_LIBS = -l${CORE_LIB} ${ICU_LIBS} \
-lcppunit -ldl -lxmlrpc++ -lboost_date_time-gcc -lcppunit -ldl -lxmlrpc++
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE tagConversionTable [ <!DOCTYPE tagConversionTable [
<!ELEMENT tagConversionTable (tag*) > <!ELEMENT tagConversionTable (tag*) >
<!ELEMENT tag ((id3, dc)*) > <!ELEMENT tag (id3+, dc) >
<!ELEMENT id3 (CDATA) > <!ELEMENT id3 (CDATA) >
<!ELEMENT dc (CDATA) > <!ELEMENT dc (CDATA) >
]> ]>
@ -9,14 +9,22 @@
<tagConversionTable> <tagConversionTable>
<tag> <tag>
<id3>Title</id3> <id3>Title</id3>
<id3>TIT2</id3>
<dc>dc:title</dc> <dc>dc:title</dc>
</tag> </tag>
<tag> <tag>
<id3>TPE1</id3>
<id3>Artist</id3> <id3>Artist</id3>
<dc>dc:creator</dc> <dc>dc:creator</dc>
</tag> </tag>
<tag> <tag>
<id3>Length</id3> <id3>Length</id3>
<id3>TLEN</id3>
<dc>dcterms:extent</dc> <dc>dcterms:extent</dc>
</tag> </tag>
<tag>
<!-- beats per minute -->
<id3>TBPM</id3>
<dc>ourdcextension:bpm</dc>
</tag>
</tagConversionTable> </tagConversionTable>

View file

@ -22,7 +22,7 @@
Author : $Author: fgerlits $ Author : $Author: fgerlits $
Version : $Revision: 1.18 $ Version : $Revision: 1.19 $
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/include/LiveSupport/Core/AudioClip.h,v $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/include/LiveSupport/Core/AudioClip.h,v $
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
@ -124,7 +124,7 @@ using namespace boost::posix_time;
* </code></pre> * </code></pre>
* *
* @author $Author: fgerlits $ * @author $Author: fgerlits $
* @version $Revision: 1.18 $ * @version $Revision: 1.19 $
*/ */
class AudioClip : public Configurable, class AudioClip : public Configurable,
public Playable public Playable
@ -165,6 +165,18 @@ class AudioClip : public Configurable,
*/ */
Ptr<xmlpp::Document>::Ref xmlAudioClip; Ptr<xmlpp::Document>::Ref xmlAudioClip;
/**
* Set the value of a metadata field in this audio clip.
*
* @param value the new value of the metadata field.
* @param name the name of the metadata field (without prefix)
* @param prefix the prefix of the metadata field
*/
virtual void
setMetadata(Ptr<const Glib::ustring>::Ref value,
const std::string &name, const std::string &prefix)
throw ();
public: public:
/** /**
@ -424,25 +436,23 @@ class AudioClip : public Configurable,
/** /**
* Return the value of a metadata field in this audio clip. * Return the value of a metadata field in this audio clip.
* *
* @param key the name of the metadata field * @param key the name of the metadata field
* @param ns the namespace of the metadata field (optional)
* @return the value of the metadata field; 0 if there is * @return the value of the metadata field; 0 if there is
* no such field; * no such field;
*/ */
virtual Ptr<Glib::ustring>::Ref virtual Ptr<Glib::ustring>::Ref
getMetadata(const std::string &key, const std::string &ns = "") const getMetadata(const std::string &key) const
throw (); throw ();
/** /**
* Set the value of a metadata field in this audio clip. * Set the value of a metadata field in this audio clip.
* *
* @param value the new value of the metadata field. * @param value the new value of the metadata field.
* @param key the name of the metadata field * @param key the name of the metadata field
* @param ns the namespace of the metadata field (optional)
*/ */
virtual void virtual void
setMetadata(Ptr<const Glib::ustring>::Ref value, setMetadata(Ptr<const Glib::ustring>::Ref value,
const std::string &key, const std::string &ns = "") const std::string &key)
throw (); throw ();
@ -478,6 +488,30 @@ class AudioClip : public Configurable,
*/ */
Ptr<Glib::ustring>::Ref Ptr<Glib::ustring>::Ref
getMetadataString() throw (); getMetadataString() throw ();
/**
* Read the metadata contained in the id3v2 tag of the mp3 sound
* file. The id3v1 tag is also read; if a field is present in both,
* the id3v2 tag is used.
*
* Ogg Vorbis sound files are not supported yet. If the
* sound file is not in mp3 format, the method returns normally
* and does not do anything; however, some junk is printed on
* the standard error.
*
* The tags are processed and translated into Dublin Core
* metadata fields using the TagConversion class. Only those fields
* are processed which have a Dublin Core equivalent listed in the
* xml element used for configuring TagConversion.
*
* @exception std::invalid_argument if TagConversion has not been
* configured yet, or if the AudioClip instance does not
* have a uri field, or the file name contained in the uri
* field is invalid
*/
void
readTag() throw (std::invalid_argument);
}; };
@ -487,6 +521,15 @@ class AudioClip : public Configurable,
/* ====================================================== function prototypes */ /* ====================================================== function prototypes */
/**
* Auxilliary method used by satisfiesCondition().
*/
void
separateNameAndNameSpace(const std::string & key,
std::string & name,
std::string & nameSpace)
throw ();
} // namespace Core } // namespace Core
} // namespace LiveSupport } // namespace LiveSupport

View file

@ -22,7 +22,7 @@
Author : $Author: fgerlits $ Author : $Author: fgerlits $
Version : $Revision: 1.6 $ Version : $Revision: 1.7 $
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/include/LiveSupport/Core/Playable.h,v $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/include/LiveSupport/Core/Playable.h,v $
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
@ -73,7 +73,7 @@ using namespace boost::posix_time;
* It contains the methods which are common to these classes. * It contains the methods which are common to these classes.
* *
* @author $Author: fgerlits $ * @author $Author: fgerlits $
* @version $Revision: 1.6 $ * @version $Revision: 1.7 $
*/ */
class Playable : public boost::enable_shared_from_this<Playable> class Playable : public boost::enable_shared_from_this<Playable>
{ {
@ -194,12 +194,11 @@ class Playable : public boost::enable_shared_from_this<Playable>
* Return the value of a metadata field in this audio clip or playlist. * Return the value of a metadata field in this audio clip or playlist.
* *
* @param key the name of the metadata field * @param key the name of the metadata field
* @param ns the namespace of the metadata field (optional)
* @return the value of the metadata field; 0 if there is * @return the value of the metadata field; 0 if there is
* no such field; * no such field;
*/ */
virtual Ptr<Glib::ustring>::Ref virtual Ptr<Glib::ustring>::Ref
getMetadata(const std::string &key, const std::string &ns = "") const getMetadata(const std::string &key) const
throw () = 0; throw () = 0;
/** /**
@ -207,12 +206,10 @@ class Playable : public boost::enable_shared_from_this<Playable>
* *
* @param value the new value of the metadata field. * @param value the new value of the metadata field.
* @param key the name of the metadata field * @param key the name of the metadata field
* @param ns the namespace of the metadata field (optional)
*/ */
virtual void virtual void
setMetadata(Ptr<const Glib::ustring>::Ref value, setMetadata(Ptr<const Glib::ustring>::Ref value,
const std::string &key, const std::string &key)
const std::string &ns = "")
throw () = 0; throw () = 0;
/** /**

View file

@ -22,7 +22,7 @@
Author : $Author: fgerlits $ Author : $Author: fgerlits $
Version : $Revision: 1.28 $ Version : $Revision: 1.29 $
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/include/LiveSupport/Core/Playlist.h,v $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/include/LiveSupport/Core/Playlist.h,v $
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
@ -93,7 +93,7 @@ using namespace boost::posix_time;
* </code></pre> * </code></pre>
* *
* @author $Author: fgerlits $ * @author $Author: fgerlits $
* @version $Revision: 1.28 $ * @version $Revision: 1.29 $
*/ */
class Playlist : public Configurable, class Playlist : public Configurable,
public Playable public Playable
@ -618,12 +618,11 @@ class Playlist : public Configurable,
* Return the value of a metadata field in this playlist. * Return the value of a metadata field in this playlist.
* *
* @param key the name of the metadata field * @param key the name of the metadata field
* @param ns the namespace of the metadata field (optional)
* @return the value of the metadata field; 0 if there is * @return the value of the metadata field; 0 if there is
* no such field; * no such field;
*/ */
virtual Ptr<Glib::ustring>::Ref virtual Ptr<Glib::ustring>::Ref
getMetadata(const std::string &key, const std::string &ns = "") const getMetadata(const std::string &key) const
throw (); throw ();
/** /**
@ -631,11 +630,10 @@ class Playlist : public Configurable,
* *
* @param value the new value of the metadata field. * @param value the new value of the metadata field.
* @param key the name of the metadata field * @param key the name of the metadata field
* @param ns the namespace of the metadata field (optional)
*/ */
virtual void virtual void
setMetadata(Ptr<const Glib::ustring>::Ref value, setMetadata(Ptr<const Glib::ustring>::Ref value,
const std::string &key, const std::string &ns = "") const std::string &key)
throw (); throw ();

View file

@ -22,7 +22,7 @@
Author : $Author: fgerlits $ Author : $Author: fgerlits $
Version : $Revision: 1.1 $ Version : $Revision: 1.2 $
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/include/LiveSupport/Core/Attic/TagConversion.h,v $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/include/LiveSupport/Core/Attic/TagConversion.h,v $
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
@ -77,15 +77,27 @@ using namespace LiveSupport::Core;
* &lt;dc&gt;dc:title&lt;/dc&gt; * &lt;dc&gt;dc:title&lt;/dc&gt;
* &lt;/tag&gt; * &lt;/tag&gt;
* &lt;tag&gt; * &lt;tag&gt;
* &lt;id3&gt;Length&lt;/id3&gt; * &lt;id3&gt;Artist&lt;/id3&gt;
* &lt;id3&gt;TPE1&lt;/id3&gt;
* &lt;dc&gt;dcterms:extent&lt;/dc&gt; * &lt;dc&gt;dcterms:extent&lt;/dc&gt;
* &lt;/tag&gt; * &lt;/tag&gt;
* ... * ...
* &lt;/tagConversionTable&gt; * &lt;/tagConversionTable&gt;
* </code></pre> * </code></pre>
* *
* Note that more than one id3 tag name can map to the same dc tag name.
*
* The DTD for the above element is:
*
* <pre><code>
* &lt;!ELEMENT tagConversionTable (tag*) &gt;
* &lt;!ATTLIST tag (id3+, dc) &gt;
* &lt;!ATTLIST id3 (#CDATA) &gt;
* &lt;!ATTLIST dc (#CDATA) &gt;
* </code></pre>
*
* @author $Author: fgerlits $ * @author $Author: fgerlits $
* @version $Revision: 1.1 $ * @version $Revision: 1.2 $
*/ */
class TagConversion class TagConversion
{ {
@ -155,6 +167,8 @@ class TagConversion
* Check whether a given id3v2 tag is listed in the table. * Check whether a given id3v2 tag is listed in the table.
* *
* @return true or false * @return true or false
* @exception std::invalid_argument if the conversion table has not
* not been configured yet
*/ */
static bool static bool
existsId3Tag(const std::string &id3Tag) throw (std::invalid_argument) existsId3Tag(const std::string &id3Tag) throw (std::invalid_argument)
@ -171,6 +185,9 @@ class TagConversion
* Convert an id3v2 tag to a Dublin Core tag (with namespace). * Convert an id3v2 tag to a Dublin Core tag (with namespace).
* *
* @return the converted tag * @return the converted tag
* @exception std::invalid_argument if the conversion table has not
* not been configured yet, or if the id3Tag name does
* not exist in the table
*/ */
static const std::string & static const std::string &
id3ToDublinCore(const std::string &id3Tag) id3ToDublinCore(const std::string &id3Tag)

View file

@ -22,7 +22,7 @@
Author : $Author: fgerlits $ Author : $Author: fgerlits $
Version : $Revision: 1.18 $ Version : $Revision: 1.19 $
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/AudioClip.cxx,v $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/AudioClip.cxx,v $
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
@ -34,7 +34,13 @@
#endif #endif
#include <sstream> #include <sstream>
#include <typeinfo>
#include <fileref.h> // for TagLib
#include <mpegfile.h> // for TagLib
#include <id3v1tag.h> // for TagLib
#include <id3v2tag.h> // for TagLib
#include "LiveSupport/Core/TagConversion.h"
#include "LiveSupport/Core/AudioClip.h" #include "LiveSupport/Core/AudioClip.h"
using namespace boost::posix_time; using namespace boost::posix_time;
@ -344,9 +350,12 @@ AudioClip :: configure(const xmlpp::Element & element)
* Return the value of a metadata field. * Return the value of a metadata field.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
Ptr<Glib::ustring>::Ref Ptr<Glib::ustring>::Ref
AudioClip :: getMetadata(const string &key, const std::string &ns) const AudioClip :: getMetadata(const string &key) const
throw () throw ()
{ {
std::string name, prefix;
separateNameAndNameSpace(key, name, prefix);
Ptr<Glib::ustring>::Ref value; Ptr<Glib::ustring>::Ref value;
if (! xmlAudioClip) { if (! xmlAudioClip) {
@ -362,12 +371,12 @@ AudioClip :: getMetadata(const string &key, const std::string &ns) const
} }
xmlpp::Node* metadata = rootList.front(); xmlpp::Node* metadata = rootList.front();
xmlpp::Node::NodeList nodeList = metadata->get_children(key); xmlpp::Node::NodeList nodeList = metadata->get_children(name);
xmlpp::Node::NodeList::iterator it = nodeList.begin(); xmlpp::Node::NodeList::iterator it = nodeList.begin();
while (it != nodeList.end()) { while (it != nodeList.end()) {
xmlpp::Node* node = *it; xmlpp::Node* node = *it;
if (node->get_namespace_prefix() == ns) { if (node->get_namespace_prefix() == prefix) {
xmlpp::Element* element = dynamic_cast<xmlpp::Element*> (node); xmlpp::Element* element = dynamic_cast<xmlpp::Element*> (node);
value.reset(new Glib::ustring(element->get_child_text() value.reset(new Glib::ustring(element->get_child_text()
->get_content())); ->get_content()));
@ -381,20 +390,33 @@ AudioClip :: getMetadata(const string &key, const std::string &ns) const
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Set the value of a metadata field. * Set the value of a metadata field (public).
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void
AudioClip :: setMetadata(Ptr<const Glib::ustring>::Ref value, AudioClip :: setMetadata(Ptr<const Glib::ustring>::Ref value,
const std::string &key, const std::string &key)
const std::string &ns)
throw () throw ()
{ {
if (ns == extentElementPrefix && key == extentElementName) { std::string name, prefix;
separateNameAndNameSpace(key, name, prefix);
setMetadata(value, name, prefix);
}
/*------------------------------------------------------------------------------
* Set the value of a metadata field (private).
*----------------------------------------------------------------------------*/
void
AudioClip :: setMetadata(Ptr<const Glib::ustring>::Ref value,
const std::string &name, const std::string &prefix)
throw ()
{
if (prefix == extentElementPrefix && name == extentElementName) {
playlength.reset(new time_duration( playlength.reset(new time_duration(
duration_from_string(*value) )); duration_from_string(*value) ));
} }
if (ns == titleElementPrefix && key == titleElementName) { if (prefix == titleElementPrefix && name == titleElementName) {
title = value; title = value;
} }
@ -418,13 +440,13 @@ AudioClip :: setMetadata(Ptr<const Glib::ustring>::Ref value,
extentElementPrefix); extentElementPrefix);
} }
xmlpp::Node::NodeList nodeList = metadata->get_children(key); xmlpp::Node::NodeList nodeList = metadata->get_children(name);
xmlpp::Node::NodeList::iterator it = nodeList.begin(); xmlpp::Node::NodeList::iterator it = nodeList.begin();
xmlpp::Element* element = 0; xmlpp::Element* element = 0;
while (it != nodeList.end()) { while (it != nodeList.end()) {
xmlpp::Node* node = *it; xmlpp::Node* node = *it;
if (node->get_namespace_prefix() == ns) { if (node->get_namespace_prefix() == prefix) {
element = dynamic_cast<xmlpp::Element*> (nodeList.front()); element = dynamic_cast<xmlpp::Element*> (nodeList.front());
break; break;
} }
@ -432,9 +454,9 @@ AudioClip :: setMetadata(Ptr<const Glib::ustring>::Ref value,
} }
if (it == nodeList.end()) { if (it == nodeList.end()) {
element = metadata->add_child(key); element = metadata->add_child(name);
try { try {
element->set_namespace(ns); element->set_namespace(prefix);
} }
catch (xmlpp::exception &e) { catch (xmlpp::exception &e) {
// this namespace has not been declared; well OK, do nothing then // this namespace has not been declared; well OK, do nothing then
@ -485,3 +507,112 @@ AudioClip :: getMetadataString() throw ()
return metadataString; return metadataString;
} }
/*------------------------------------------------------------------------------
* Read the metadata contained in the id3v2 tag of the binary sound file.
*----------------------------------------------------------------------------*/
void
AudioClip :: readTag() throw (std::invalid_argument)
{
if (!TagConversion::isConfigured()) {
throw std::invalid_argument("tag conversion table not loaded");
}
if (!getUri()) {
throw std::invalid_argument("audio clip has no uri field");
}
if (!TagLib::File::isReadable(getUri()->c_str())) {
throw std::invalid_argument("binary sound file not found");
}
TagLib::FileRef genericFileRef(getUri()->c_str());
TagLib::Tag* tag = genericFileRef.tag();
if (!tag) {
return;
}
Ptr<const Glib::ustring>::Ref value; // true = unicode
if (TagConversion::existsId3Tag("Artist")) {
value.reset(new const Glib::ustring(tag->artist().to8Bit(true)));
setMetadata(value, TagConversion::id3ToDublinCore("Artist"));
}
if (TagConversion::existsId3Tag("Title")) {
value.reset(new const Glib::ustring(tag->title().to8Bit(true)));
setMetadata(value, TagConversion::id3ToDublinCore("Title"));
}
if (TagConversion::existsId3Tag("Album")) {
value.reset(new const Glib::ustring(tag->album().to8Bit(true)));
setMetadata(value, TagConversion::id3ToDublinCore("Album"));
}
if (TagConversion::existsId3Tag("Comment")) {
value.reset(new const Glib::ustring(tag->comment().to8Bit(true)));
setMetadata(value, TagConversion::id3ToDublinCore("Comment"));
}
if (TagConversion::existsId3Tag("Genre")) {
value.reset(new const Glib::ustring(tag->genre().to8Bit(true)));
setMetadata(value, TagConversion::id3ToDublinCore("Genre"));
}
if (TagConversion::existsId3Tag("Year")) {
std::stringstream yearString;
yearString << tag->year();
value.reset(new const Glib::ustring(yearString.str()));
setMetadata(value, TagConversion::id3ToDublinCore("Year"));
}
if (TagConversion::existsId3Tag("Track")) {
std::stringstream trackString;
trackString << tag->track();
value.reset(new const Glib::ustring(trackString.str()));
setMetadata(value, TagConversion::id3ToDublinCore("Track"));
}
TagLib::MPEG::File mpegFile(getUri()->c_str());
TagLib::ID3v2::Tag* id3v2Tag = mpegFile.ID3v2Tag();
if (!id3v2Tag) {
return;
}
TagLib::ID3v2::FrameListMap frameListMap = id3v2Tag->frameListMap();
TagLib::ID3v2::FrameListMap::ConstIterator it = frameListMap.begin();
while (it != frameListMap.end()) {
const char* keyBuffer = it->first.data();
std::string keyString(keyBuffer, 4);
if (TagConversion::existsId3Tag(keyString)) {
TagLib::ID3v2::FrameList frameList = it->second;
if (!frameList.isEmpty()) {
value.reset(new const Glib::ustring(frameList.front()
->toString().to8Bit(true)));
setMetadata(value, TagConversion::id3ToDublinCore(keyString));
}
}
++it;
}
}
/*------------------------------------------------------------------------------
* Separate a key into the metadata name and its namespace
*----------------------------------------------------------------------------*/
void
LiveSupport::Core :: separateNameAndNameSpace(const std::string & key,
std::string & name,
std::string & prefix)
throw ()
{
unsigned int colonPosition = key.find(':');
if (colonPosition != std::string::npos) { // there is a colon
prefix = key.substr(0, colonPosition);
name = key.substr(colonPosition+1);
} else { // no colon found
prefix = "";
name = key;
}
}

View file

@ -22,7 +22,7 @@
Author : $Author: fgerlits $ Author : $Author: fgerlits $
Version : $Revision: 1.8 $ Version : $Revision: 1.9 $
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/AudioClipTest.cxx,v $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/AudioClipTest.cxx,v $
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
@ -45,6 +45,7 @@
#include "LiveSupport/Core/AudioClip.h" #include "LiveSupport/Core/AudioClip.h"
#include "LiveSupport/Core/Playlist.h" #include "LiveSupport/Core/Playlist.h"
#include "LiveSupport/Core/TagConversion.h"
#include "AudioClipTest.h" #include "AudioClipTest.h"
@ -63,6 +64,11 @@ CPPUNIT_TEST_SUITE_REGISTRATION(AudioClipTest);
*/ */
static const std::string configFileName = "etc/audioClip.xml"; static const std::string configFileName = "etc/audioClip.xml";
/**
* The name of the configuration file for the tag conversion table.
*/
static const std::string tagConversionConfig = "etc/tagConversionTable.xml";
/* =============================================== local function prototypes */ /* =============================================== local function prototypes */
@ -115,12 +121,12 @@ AudioClipTest :: firstTest(void)
CPPUNIT_ASSERT(*title == "File Title txt"); CPPUNIT_ASSERT(*title == "File Title txt");
Ptr<const Glib::ustring>::Ref subject = audioClip Ptr<const Glib::ustring>::Ref subject = audioClip
->getMetadata("subject", "dc"); ->getMetadata("dc:subject");
CPPUNIT_ASSERT(subject); CPPUNIT_ASSERT(subject);
CPPUNIT_ASSERT(*subject == "Keywords: qwe, asd, zcx"); CPPUNIT_ASSERT(*subject == "Keywords: qwe, asd, zcx");
Ptr<const Glib::ustring>::Ref alternativeTitle = audioClip Ptr<const Glib::ustring>::Ref alternativeTitle = audioClip
->getMetadata("alternative", "dcterms"); ->getMetadata("dcterms:alternative");
CPPUNIT_ASSERT(alternativeTitle); CPPUNIT_ASSERT(alternativeTitle);
CPPUNIT_ASSERT(*alternativeTitle == CPPUNIT_ASSERT(*alternativeTitle ==
"Alternative File Title ín sőmé %$#@* LÁNGŰAGÉ"); "Alternative File Title ín sőmé %$#@* LÁNGŰAGÉ");
@ -177,3 +183,42 @@ AudioClipTest :: conversionTest(void)
CPPUNIT_ASSERT(!playlist); CPPUNIT_ASSERT(!playlist);
} }
/*------------------------------------------------------------------------------
* Test id3v2 tag extraction
*----------------------------------------------------------------------------*/
void
AudioClipTest :: tagTest(void)
throw (CPPUNIT_NS::Exception)
{
try {
Ptr<xmlpp::DomParser>::Ref parser(
new xmlpp::DomParser(tagConversionConfig, false));
const xmlpp::Document * document = parser->get_document();
const xmlpp::Element * root = document->get_root_node();
TagConversion::configure(*root);
} catch (std::invalid_argument &e) {
CPPUNIT_FAIL(e.what());
} catch (xmlpp::exception &e) {
CPPUNIT_FAIL(e.what());
}
Ptr<AudioClip>::Ref audioClip(new AudioClip());
Ptr<std::string>::Ref uri(new std::string("var/test10001.mp3"));
audioClip->setUri(uri);
try {
audioClip->readTag();
} catch (std::invalid_argument &e) {
CPPUNIT_FAIL(e.what());
}
Ptr<const Glib::ustring>::Ref title
= audioClip->getMetadata("dc:title");
CPPUNIT_ASSERT(*title == "Theme Song");
Ptr<const Glib::ustring>::Ref artist
= audioClip->getMetadata("dc:creator");
CPPUNIT_ASSERT(*artist == "The Muppets");
}

View file

@ -22,7 +22,7 @@
Author : $Author: fgerlits $ Author : $Author: fgerlits $
Version : $Revision: 1.2 $ Version : $Revision: 1.3 $
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/AudioClipTest.h,v $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/AudioClipTest.h,v $
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
@ -58,7 +58,7 @@ namespace Core {
* Unit test for the AudioClip class. * Unit test for the AudioClip class.
* *
* @author $Author: fgerlits $ * @author $Author: fgerlits $
* @version $Revision: 1.2 $ * @version $Revision: 1.3 $
* @see AudioClip * @see AudioClip
*/ */
class AudioClipTest : public CPPUNIT_NS::TestFixture class AudioClipTest : public CPPUNIT_NS::TestFixture
@ -66,6 +66,7 @@ class AudioClipTest : public CPPUNIT_NS::TestFixture
CPPUNIT_TEST_SUITE(AudioClipTest); CPPUNIT_TEST_SUITE(AudioClipTest);
CPPUNIT_TEST(firstTest); CPPUNIT_TEST(firstTest);
CPPUNIT_TEST(conversionTest); CPPUNIT_TEST(conversionTest);
CPPUNIT_TEST(tagTest);
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
protected: protected:
@ -86,6 +87,14 @@ class AudioClipTest : public CPPUNIT_NS::TestFixture
void void
conversionTest(void) throw (CPPUNIT_NS::Exception); conversionTest(void) throw (CPPUNIT_NS::Exception);
/**
* Id3v2 tag extraction test.
*
* @exception CPPUNIT_NS::Exception on test failures.
*/
void
tagTest(void) throw (CPPUNIT_NS::Exception);
public: public:

View file

@ -22,7 +22,7 @@
Author : $Author: fgerlits $ Author : $Author: fgerlits $
Version : $Revision: 1.27 $ Version : $Revision: 1.28 $
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/Playlist.cxx,v $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/Playlist.cxx,v $
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
@ -397,11 +397,10 @@ Playlist::revertToSavedCopy(void) throw (std::invalid_argument)
* Return the value of a metadata field. * Return the value of a metadata field.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
Ptr<Glib::ustring>::Ref Ptr<Glib::ustring>::Ref
Playlist :: getMetadata(const string &key, const string &ns) const Playlist :: getMetadata(const string &key) const
throw () throw ()
{ {
std::string completeKey = ns + ":" + key; metadataType::const_iterator it = metadata.find(key);
metadataType::const_iterator it = metadata.find(completeKey);
if (it != metadata.end()) { if (it != metadata.end()) {
Ptr<Glib::ustring>::Ref data(new Glib::ustring(*it->second)); Ptr<Glib::ustring>::Ref data(new Glib::ustring(*it->second));
@ -418,17 +417,16 @@ Playlist :: getMetadata(const string &key, const string &ns) const
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void
Playlist :: setMetadata(Ptr<const Glib::ustring>::Ref value, Playlist :: setMetadata(Ptr<const Glib::ustring>::Ref value,
const string &key, const string &ns) const string &key)
throw () throw ()
{ {
std::string completeKey = ns + ":" + key; metadata[key] = value;
metadata[completeKey] = value;
if (completeKey == "dcterms:extent") { if (key == "dcterms:extent") {
playlength.reset(new time_duration(duration_from_string(*value))); playlength.reset(new time_duration(duration_from_string(*value)));
} }
if (completeKey == "dc:title") { if (key == "dc:title") {
title = value; title = value;
} }
} }

View file

@ -22,7 +22,7 @@
Author : $Author: fgerlits $ Author : $Author: fgerlits $
Version : $Revision: 1.1 $ Version : $Revision: 1.2 $
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/Attic/TagConversion.cxx,v $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/Attic/TagConversion.cxx,v $
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
@ -100,19 +100,23 @@ TagConversion :: configure(const xmlpp::Element & element)
Node::NodeList id3Tags = (*listIt)->get_children(id3TagElementName); Node::NodeList id3Tags = (*listIt)->get_children(id3TagElementName);
Node::NodeList dcTags = (*listIt)->get_children(dcTagElementName); Node::NodeList dcTags = (*listIt)->get_children(dcTagElementName);
if (id3Tags.size() != 1 || dcTags.size() != 1) { if (id3Tags.size() < 1 || dcTags.size() != 1) {
std::string eMsg = "bad <"; std::string eMsg = "bad <";
eMsg += tagElementName; eMsg += tagElementName;
eMsg += "> element found"; eMsg += "> element found";
throw std::invalid_argument(eMsg); throw std::invalid_argument(eMsg);
} }
Element* id3Element = dynamic_cast<Element*> (id3Tags.front());
Element* dcElement = dynamic_cast<Element*> (dcTags.front()); Element* dcElement = dynamic_cast<Element*> (dcTags.front());
Node::NodeList::iterator
table->insert(std::make_pair( id3Iterator = id3Tags.begin();
while (id3Iterator != id3Tags.end()) {
Element* id3Element = dynamic_cast<Element*> (*id3Iterator);
table->insert(std::make_pair(
id3Element->get_child_text()->get_content(), id3Element->get_child_text()->get_content(),
dcElement ->get_child_text()->get_content() )); dcElement ->get_child_text()->get_content() ));
++id3Iterator;
}
++listIt; ++listIt;
} }
} }

View file

@ -22,7 +22,7 @@
Author : $Author: fgerlits $ Author : $Author: fgerlits $
Version : $Revision: 1.1 $ Version : $Revision: 1.2 $
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/Attic/TagConversionTest.cxx,v $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/Attic/TagConversionTest.cxx,v $
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
@ -85,19 +85,6 @@ void
TagConversionTest :: firstTest(void) TagConversionTest :: firstTest(void)
throw (CPPUNIT_NS::Exception) throw (CPPUNIT_NS::Exception)
{ {
try {
TagConversion::existsId3Tag("Title");
CPPUNIT_FAIL("allowed to use class before configuration");
} catch (std::invalid_argument &e) {
}
try {
TagConversion::id3ToDublinCore("Title");
CPPUNIT_FAIL("allowed to use class before configuration");
} catch (std::invalid_argument &e) {
}
CPPUNIT_ASSERT(!TagConversion::isConfigured());
try { try {
Ptr<xmlpp::DomParser>::Ref parser( Ptr<xmlpp::DomParser>::Ref parser(
new xmlpp::DomParser(configFileName, false)); new xmlpp::DomParser(configFileName, false));
@ -126,6 +113,14 @@ TagConversionTest :: firstTest(void)
CPPUNIT_FAIL(e.what()); CPPUNIT_FAIL(e.what());
} }
try {
CPPUNIT_ASSERT(TagConversion::id3ToDublinCore("TIT2") == "dc:title");
std::string dcTag = TagConversion::id3ToDublinCore("TBPM");
CPPUNIT_ASSERT(dcTag == "ourdcextension:bpm");
} catch (std::invalid_argument &e) {
CPPUNIT_FAIL(e.what());
}
try { try {
std::string dcTag = TagConversion::id3ToDublinCore("Boringness"); std::string dcTag = TagConversion::id3ToDublinCore("Boringness");
CPPUNIT_FAIL("allowed to convert non-existent tag"); CPPUNIT_FAIL("allowed to convert non-existent tag");

Binary file not shown.

View file

@ -21,7 +21,7 @@
# #
# #
# Author : $Author: fgerlits $ # Author : $Author: fgerlits $
# Version : $Revision: 1.18 $ # Version : $Revision: 1.19 $
# Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/etc/Makefile.in,v $ # Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/etc/Makefile.in,v $
# #
# @configure_input@ # @configure_input@
@ -75,6 +75,8 @@ LIBXMLPP_LIBS=@LIBXMLPP_LIBS@
CURL_LIBS=`${USR_DIR}/bin/curl-config --libs` CURL_LIBS=`${USR_DIR}/bin/curl-config --libs`
TAGLIB_LIBS =`${USR_DIR}/bin/taglib-config --libs`
TEST_RESULTS = ${DOC_DIR}/testResults.xml TEST_RESULTS = ${DOC_DIR}/testResults.xml
# the text result XSLT has to be relative to the test result file, e.g. TMP_DIR # the text result XSLT has to be relative to the test result file, e.g. TMP_DIR
TEST_XSLT = ../etc/testResultToHtml.xsl TEST_XSLT = ../etc/testResultToHtml.xsl
@ -103,6 +105,7 @@ CXXFLAGS = @CXXFLAGS@ @DEFS@ @COVERAGE_CXXFLAGS@ -pthread \
LDFLAGS = @LDFLAGS@ -pthread \ LDFLAGS = @LDFLAGS@ -pthread \
${LIBXMLPP_LIBS} \ ${LIBXMLPP_LIBS} \
${CURL_LIBS} \ ${CURL_LIBS} \
${TAGLIB_LIBS} \
-L${USR_LIB_DIR} \ -L${USR_LIB_DIR} \
-L${CORE_LIB_DIR} \ -L${CORE_LIB_DIR} \
-L${AUTHENTICATION_LIB_DIR} \ -L${AUTHENTICATION_LIB_DIR} \

View file

@ -22,7 +22,7 @@
Author : $Author: fgerlits $ Author : $Author: fgerlits $
Version : $Revision: 1.33 $ Version : $Revision: 1.34 $
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/TestStorageClient.cxx,v $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/TestStorageClient.cxx,v $
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
@ -817,10 +817,7 @@ TestStorageClient :: satisfiesCondition(
const SearchCriteria::SearchConditionType & condition) const SearchCriteria::SearchConditionType & condition)
throw (XmlRpcException) throw (XmlRpcException)
{ {
std::string name, nameSpace; Ptr<Glib::ustring>::Ref value = playable->getMetadata(condition.key);
separateNameAndNameSpace(condition.key, name, nameSpace);
Ptr<Glib::ustring>::Ref value = playable->getMetadata(name, nameSpace);
if (!value) { if (!value) {
return false; return false;
} }
@ -855,16 +852,16 @@ TestStorageClient :: satisfiesCondition(
void void
LiveSupport::Storage :: separateNameAndNameSpace(const std::string & key, LiveSupport::Storage :: separateNameAndNameSpace(const std::string & key,
std::string & name, std::string & name,
std::string & nameSpace) std::string & prefix)
throw () throw ()
{ {
unsigned int colonPosition = key.find(':'); unsigned int colonPosition = key.find(':');
if (colonPosition != std::string::npos) { // there is a colon if (colonPosition != std::string::npos) { // there is a colon
nameSpace = key.substr(0, colonPosition); prefix = key.substr(0, colonPosition);
name = key.substr(colonPosition+1); name = key.substr(colonPosition+1);
} else { // no colon found } else { // no colon found
nameSpace = ""; prefix = "";
name = key; name = key;
} }
} }

View file

@ -22,7 +22,7 @@
Author : $Author: fgerlits $ Author : $Author: fgerlits $
Version : $Revision: 1.27 $ Version : $Revision: 1.28 $
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/TestStorageClient.h,v $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/TestStorageClient.h,v $
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
@ -86,7 +86,7 @@ using namespace LiveSupport::Core;
* </code></pre> * </code></pre>
* *
* @author $Author: fgerlits $ * @author $Author: fgerlits $
* @version $Revision: 1.27 $ * @version $Revision: 1.28 $
*/ */
class TestStorageClient : class TestStorageClient :
virtual public Configurable, virtual public Configurable,
@ -556,7 +556,7 @@ class TestStorageClient :
void void
separateNameAndNameSpace(const std::string & key, separateNameAndNameSpace(const std::string & key,
std::string & name, std::string & name,
std::string & nameSpace) std::string & prefix)
throw (); throw ();
} // namespace Storage } // namespace Storage

View file

@ -20,8 +20,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# #
# #
# Author : $Author: maroy $ # Author : $Author: fgerlits $
# Version : $Revision: 1.21 $ # Version : $Revision: 1.22 $
# Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/gLiveSupport/etc/Makefile.in,v $ # Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/gLiveSupport/etc/Makefile.in,v $
# #
# @configure_input@ # @configure_input@
@ -119,6 +119,8 @@ GTKMM_LIBS=@GTKMM_LIBS@
ICU_CFLAGS= ICU_CFLAGS=
ICU_LIBS=`${USR_DIR}/bin/icu-config --ldflags-toolutil --ldflags-icuio` ICU_LIBS=`${USR_DIR}/bin/icu-config --ldflags-toolutil --ldflags-icuio`
TAGLIB_LIBS=`${USR_DIR}/bin/taglib-config --libs`
TEST_RESULTS = ${DOC_DIR}/testResults.xml TEST_RESULTS = ${DOC_DIR}/testResults.xml
# the text result XSLT has to be relative to the test result file, e.g. TMP_DIR # the text result XSLT has to be relative to the test result file, e.g. TMP_DIR
TEST_XSLT = ../etc/testResultToHtml.xsl TEST_XSLT = ../etc/testResultToHtml.xsl
@ -155,6 +157,7 @@ LDFLAGS = @LDFLAGS@ -pthread \
${LIBXMLPP_LIBS} \ ${LIBXMLPP_LIBS} \
${CURL_LIBS} \ ${CURL_LIBS} \
${GTKMM_LIBS} \ ${GTKMM_LIBS} \
${TAGLIB_LIBS} \
-L${USR_LIB_DIR} \ -L${USR_LIB_DIR} \
-L${HELIX_LIB_DIR} \ -L${HELIX_LIB_DIR} \
-L${CORE_LIB_DIR} \ -L${CORE_LIB_DIR} \

View file

@ -20,8 +20,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# #
# #
# Author : $Author: maroy $ # Author : $Author: fgerlits $
# Version : $Revision: 1.43 $ # Version : $Revision: 1.44 $
# Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/etc/Makefile.in,v $ # Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/etc/Makefile.in,v $
# #
# @configure_input@ # @configure_input@
@ -67,6 +67,8 @@ LIBXMLPP_LIBS=@LIBXMLPP_LIBS@
CURL_LIBS=`${USR_DIR}/bin/curl-config --libs` CURL_LIBS=`${USR_DIR}/bin/curl-config --libs`
TAGLIB_LIBS =`${USR_DIR}/bin/taglib-config --libs`
MODULES_DIR = ${BASE_DIR}/../../modules MODULES_DIR = ${BASE_DIR}/../../modules
CORE_DIR = ${MODULES_DIR}/core CORE_DIR = ${MODULES_DIR}/core
@ -140,6 +142,7 @@ CXXFLAGS = @CXXFLAGS@ @DEFS@ @COVERAGE_CXXFLAGS@ -pthread \
LDFLAGS = @LDFLAGS@ -pthread \ LDFLAGS = @LDFLAGS@ -pthread \
${LIBXMLPP_LIBS} \ ${LIBXMLPP_LIBS} \
${CURL_LIBS} \ ${CURL_LIBS} \
${TAGLIB_LIBS} \
-L${USR_LIB_DIR} \ -L${USR_LIB_DIR} \
-L${HELIX_LIB_DIR} \ -L${HELIX_LIB_DIR} \
-L${CORE_LIB_DIR} \ -L${CORE_LIB_DIR} \

View file

@ -21,8 +21,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Author : $Author: maroy $ Author : $Author: fgerlits $
Version : $Revision: 1.3 $ Version : $Revision: 1.4 $
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/src/PlaylistEventTest.cxx,v $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/products/scheduler/src/PlaylistEventTest.cxx,v $
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
@ -231,6 +231,8 @@ PlaylistEventTest :: playTest(void)
playlistEvent->deInitialize(); playlistEvent->deInitialize();
} catch (std::logic_error &e) { } catch (std::logic_error &e) {
CPPUNIT_FAIL(e.what()); CPPUNIT_FAIL(e.what());
} catch (std::exception &e) {
CPPUNIT_FAIL(e.what());
} }
} }