From 34b681064cd1ea09f6507bdbd5744e2cb2e28b1c Mon Sep 17 00:00:00 2001 From: fgerlits Date: Mon, 29 Nov 2004 20:40:36 +0000 Subject: [PATCH] added support for playlists containing other playlists --- livesupport/modules/core/etc/audioClip.xml | 2 +- livesupport/modules/core/etc/playlist.xml | 26 +++-- .../modules/core/etc/playlistElement.xml | 19 +++- .../core/include/LiveSupport/Core/AudioClip.h | 50 +++++++-- .../core/include/LiveSupport/Core/FadeInfo.h | 8 +- .../core/include/LiveSupport/Core/Playlist.h | 75 +++++++++++-- .../LiveSupport/Core/PlaylistElement.h | 79 +++++++++++-- livesupport/modules/core/src/AudioClip.cxx | 15 +-- .../modules/core/src/AudioClipTest.cxx | 4 +- livesupport/modules/core/src/Playlist.cxx | 70 ++++++++++-- .../modules/core/src/PlaylistElement.cxx | 64 ++++++++--- .../modules/core/src/PlaylistElementTest.cxx | 35 +++++- livesupport/modules/core/src/PlaylistTest.cxx | 102 +++++++++-------- .../modules/storage/src/TestStorageClient.cxx | 104 ++++++++++++------ 14 files changed, 489 insertions(+), 164 deletions(-) diff --git a/livesupport/modules/core/etc/audioClip.xml b/livesupport/modules/core/etc/audioClip.xml index f08267941..c19531a1b 100644 --- a/livesupport/modules/core/etc/audioClip.xml +++ b/livesupport/modules/core/etc/audioClip.xml @@ -4,6 +4,6 @@ - + ]> diff --git a/livesupport/modules/core/etc/playlist.xml b/livesupport/modules/core/etc/playlist.xml index 9c38aef3d..8951886df 100644 --- a/livesupport/modules/core/etc/playlist.xml +++ b/livesupport/modules/core/etc/playlist.xml @@ -5,14 +5,14 @@ - + - + @@ -20,15 +20,23 @@ ]> - + - + - - - + + + + + + + + + diff --git a/livesupport/modules/core/etc/playlistElement.xml b/livesupport/modules/core/etc/playlistElement.xml index 05323ce81..73023d808 100644 --- a/livesupport/modules/core/etc/playlistElement.xml +++ b/livesupport/modules/core/etc/playlistElement.xml @@ -1,14 +1,18 @@ + + + + + - + @@ -16,7 +20,12 @@ ]> - - + + + + + + - + diff --git a/livesupport/modules/core/include/LiveSupport/Core/AudioClip.h b/livesupport/modules/core/include/LiveSupport/Core/AudioClip.h index 96c220b27..84fa32bb3 100644 --- a/livesupport/modules/core/include/LiveSupport/Core/AudioClip.h +++ b/livesupport/modules/core/include/LiveSupport/Core/AudioClip.h @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.7 $ + Version : $Revision: 1.8 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/include/LiveSupport/Core/AudioClip.h,v $ ------------------------------------------------------------------------------*/ @@ -77,21 +77,24 @@ using namespace boost::posix_time; *

  *  <audioClip id="1" 
  *             playlength="00:18:30.000000"
- *             uri="file:var/test1.mp3" >
+ *             uri="file:var/test1.mp3"
  *  </audioClip>
  *  
* + * The URI is not normally part of the XML element; it's only included + * as an optional attribute for testing purposes. + * * The DTD for the above element is: * *

  *  <!ELEMENT audioClip EMPTY >
  *  <!ATTLIST audioClip  id           NMTOKEN     #REQUIRED  >
  *  <!ATTLIST audioClip  playlength   NMTOKEN     #REQUIRED  >
- *  <!ATTLIST audioClip  uri          CDATA       #REQUIRED  >
+ *  <!ATTLIST audioClip  uri          CDATA       #IMPLIED   >
  *  
* * @author $Author: fgerlits $ - * @version $Revision: 1.7 $ + * @version $Revision: 1.8 $ */ class AudioClip : public Configurable { @@ -112,9 +115,14 @@ class AudioClip : public Configurable Ptr::Ref playlength; /** - * The location of the audio clip. + * The location of the binary audio clip sound file. */ - Ptr::Ref uri; + Ptr::Ref uri; + + /** + * The identifying token returned by the storage server. + */ + Ptr::Ref token; public: @@ -193,14 +201,14 @@ class AudioClip : public Configurable * * @return the playing length of this audio clip, in microseconds. */ - Ptr::Ref + Ptr::Ref getPlaylength(void) const throw () { return playlength; } /** - * Return the URI of this audio clip. + * Return the URI of the binary sound file of this audio clip. * * @return the URI of this audio clip. */ @@ -211,15 +219,37 @@ class AudioClip : public Configurable } /** - * Change the URI of this audio clip. This is only used in testing. + * Set the URI of the binary sound file of this audio clip. * * @return the URI of this audio clip. */ void - setUri(Ptr::Ref uri) throw () + setUri(Ptr::Ref uri) throw () { this->uri = uri; } + + /** + * Return the token returned by the storage server. + * + * @return the token of this audio clip. + */ + Ptr::Ref + getToken(void) const throw () + { + return token; + } + + /** + * Set the token returned by the storage server. + * + * @return the token of this audio clip. + */ + void + setToken(Ptr::Ref token) throw () + { + this->token = token; + } }; diff --git a/livesupport/modules/core/include/LiveSupport/Core/FadeInfo.h b/livesupport/modules/core/include/LiveSupport/Core/FadeInfo.h index ed239e144..878eed9d4 100644 --- a/livesupport/modules/core/include/LiveSupport/Core/FadeInfo.h +++ b/livesupport/modules/core/include/LiveSupport/Core/FadeInfo.h @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.3 $ + Version : $Revision: 1.4 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/include/LiveSupport/Core/FadeInfo.h,v $ ------------------------------------------------------------------------------*/ @@ -89,7 +89,7 @@ using namespace boost::posix_time; * * * @author $Author: fgerlits $ - * @version $Revision: 1.3 $ + * @version $Revision: 1.4 $ */ class FadeInfo : public Configurable { @@ -203,7 +203,7 @@ class FadeInfo : public Configurable * * @return the length of the fade in period, in microseconds. */ - Ptr::Ref + Ptr::Ref getFadeIn(void) const throw () { return fadeIn; @@ -214,7 +214,7 @@ class FadeInfo : public Configurable * * @return the length of the fade in period, in microseconds. */ - Ptr::Ref + Ptr::Ref getFadeOut(void) const throw () { return fadeOut; diff --git a/livesupport/modules/core/include/LiveSupport/Core/Playlist.h b/livesupport/modules/core/include/LiveSupport/Core/Playlist.h index 70b374e2f..fe18abdd4 100644 --- a/livesupport/modules/core/include/LiveSupport/Core/Playlist.h +++ b/livesupport/modules/core/include/LiveSupport/Core/Playlist.h @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.16 $ + Version : $Revision: 1.17 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/include/LiveSupport/Core/Playlist.h,v $ ------------------------------------------------------------------------------*/ @@ -92,7 +92,7 @@ using namespace boost::posix_time; * * * @author $Author: fgerlits $ - * @version $Revision: 1.16 $ + * @version $Revision: 1.17 $ */ class Playlist : public Configurable { @@ -115,7 +115,12 @@ class Playlist : public Configurable /** * The uri of the SMIL file generated from this playlist (if any). */ - Ptr::Ref uri; + Ptr::Ref uri; + + /** + * The token given to this playlist by the storage server. + */ + Ptr::Ref token; /** * Flag set if playlist is currently playing. @@ -238,33 +243,54 @@ class Playlist : public Configurable * * @return the playling length of this playlist, in microseconds. */ - Ptr::Ref + Ptr::Ref getPlaylength(void) const throw () { return playlength; } /** - * Return the uri of the playlist. + * Return the URI of the SMIL file generated from this playlist. * * @return the uri of the playlist. */ Ptr::Ref - getUri(void) const throw () + getUri(void) const throw () { return uri; } /** - * Set the uri of the playlist. + * Set the URI of the SMIL file generated from this playlist. * */ void - setUri(Ptr::Ref uri) throw () + setUri(Ptr::Ref uri) throw () { this->uri = uri; } + /** + * Return the token given to this playlist by the storage server. + * + * @return the uri of the playlist. + */ + Ptr::Ref + getToken(void) const throw () + { + return token; + } + + /** + * Set the token given to this playlist by the storage server. + * + */ + void + setToken(Ptr::Ref token) throw () + { + this->token = token; + } + /** * Test whether the playlist is locked for editing or playing. * @@ -355,7 +381,7 @@ class Playlist : public Configurable * to the start of the playlist * @param fadeInfo the fade in / fade out info (optional) * @exception std::invalid_argument if the playlist already contains - * an audio clip with the same relative offset + * a playlist element with the same relative offset */ void addAudioClip(Ptr::Ref audioClip, @@ -364,6 +390,23 @@ class Playlist : public Configurable = Ptr::Ref()) throw (std::invalid_argument); + /** + * Add a new sub-playlist to the playlist. + * + * @param playlist the sub-playlist to be added + * @param relativeOffset the start of the sub-playlist, relative + * to the start of the containing playlist + * @param fadeInfo the fade in / fade out info (optional) + * @exception std::invalid_argument if the playlist already contains + * a playlist element with the same relative offset + */ + void + addPlaylist(Ptr::Ref playlist, + Ptr::Ref relativeOffset, + Ptr::Ref fadeInfo + = Ptr::Ref()) + throw (std::invalid_argument); + /** * Set the fade in / fade out info for a playlist element. * @@ -380,6 +423,8 @@ class Playlist : public Configurable /** * Remove an audio clip from the playlist. + * THIS IS OBSOLETE, SUPERSEDED BY removePlaylistElement(). + * TODO: REMOVE IT AFTER THERE ARE NO MORE REFERENCES TO IT. * * @param relativeOffset the start of the audio clip, relative * to the start of the playlist @@ -390,6 +435,18 @@ class Playlist : public Configurable removeAudioClip(Ptr::Ref relativeOffset) throw (std::invalid_argument); + /** + * Remove a playlist element from the playlist. + * + * @param relativeOffset the start of the playlist element, relative + * to the start of the playlist + * @exception std::invalid_argument if the playlist does not contain + * a playlist element at the specified relative offset + */ + void + removePlaylistElement(Ptr::Ref relativeOffset) + throw (std::invalid_argument); + /** * Validate the playlist: check that there are no overlaps or gaps. * If the playlength is the only thing amiss, playlist is considered diff --git a/livesupport/modules/core/include/LiveSupport/Core/PlaylistElement.h b/livesupport/modules/core/include/LiveSupport/Core/PlaylistElement.h index e547964e7..d7f74356f 100644 --- a/livesupport/modules/core/include/LiveSupport/Core/PlaylistElement.h +++ b/livesupport/modules/core/include/LiveSupport/Core/PlaylistElement.h @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.7 $ + Version : $Revision: 1.8 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/include/LiveSupport/Core/PlaylistElement.h,v $ ------------------------------------------------------------------------------*/ @@ -61,6 +61,8 @@ using namespace boost::posix_time; using namespace LiveSupport; using namespace LiveSupport::Core; +// forward declaration to avoid circular reference +class Playlist; /* ================================================================ constants */ @@ -71,7 +73,7 @@ using namespace LiveSupport::Core; /* =============================================================== data types */ /** - * An item in a Playlist, consisting of an AudioClip + * An item in a Playlist, consisting of an AudioClip or another Playlist * and optional FadeInfo (fade in / fade out information). * * This object has to be configured with an XML configuration element @@ -90,16 +92,23 @@ using namespace LiveSupport::Core; * The DTD for the above element is: * *

- *  <!ELEMENT playlistElement (audioClip, fadeInfo?) >
+ *  <!ELEMENT playlistElement ((audioClip|playlist), fadeInfo?) >
  *  <!ATTLIST playlistElement  id              NMTOKEN   #REQUIRED  >
  *  <!ATTLIST playlistElement  relativeOffset  NMTOKEN   #REQUIRED  >
  *  
* * @author $Author: fgerlits $ - * @version $Revision: 1.7 $ + * @version $Revision: 1.8 $ */ class PlaylistElement : public Configurable { + public: + /** + * The possible types of the playlist element (audio clip or + * sub-playlist). + */ + enum Type { AudioClipType, PlaylistType }; + private: /** * The name of the configuration XML element used by Playlist. @@ -116,11 +125,21 @@ class PlaylistElement : public Configurable */ Ptr::Ref relativeOffset; + /** + * The type of the entry (audio clip or sub-playlist). + */ + Type type; + /** * The audio clip associated with the entry. */ Ptr::Ref audioClip; + /** + * The playlist associated with the entry. + */ + Ptr::Ref playlist; + /** * The fade in / fade out info associated with the entry. */ @@ -161,7 +180,7 @@ class PlaylistElement : public Configurable } /** - * Create a new playlist element, with a new UniqueId, + * Create a new audio clip playlist element, with a new UniqueId, * to be added to a playlist. * * @param relativeOffset the start time of this element, relative to @@ -180,6 +199,30 @@ class PlaylistElement : public Configurable this->relativeOffset = relativeOffset; this->audioClip = audioClip; this->fadeInfo = fadeInfo; + this->type = AudioClipType; + } + + /** + * Create a new sub-playlist playlist element, with a new UniqueId, + * to be added to a playlist. + * + * @param relativeOffset the start time of this element, relative to + * the start of the playlist. + * @param playlist (a pointer to) the sub-playlist associated + * with the playlist element. + * @param fadeInfo fade in / fade out information (optional) + */ + PlaylistElement(Ptr::Ref relativeOffset, + Ptr::Ref playlist, + Ptr::Ref fadeInfo + = Ptr::Ref()) + throw () + { + this->id = UniqueId::generateId(); + this->relativeOffset = relativeOffset; + this->playlist = playlist; + this->fadeInfo = fadeInfo; + this->type = PlaylistType; } /** @@ -231,12 +274,23 @@ class PlaylistElement : public Configurable * * @return the relative offset of the element. */ - Ptr::Ref + Ptr::Ref getRelativeOffset(void) const throw () { return relativeOffset; } + /** + * Return the type of this playlist element. + * + * @return either AudioClipType or PlaylistType. + */ + Type + getType(void) const throw () + { + return type; + } + /** * Return the audio clip associated with the playlist element. * @@ -248,6 +302,17 @@ class PlaylistElement : public Configurable return audioClip; } + /** + * Return the sub-playlist associated with the playlist element. + * + * @return the sub-playlist associated with the element. + */ + Ptr::Ref + getPlaylist(void) const throw () + { + return playlist; + } + /** * Set the fade info associated with the playlist element. * @@ -264,7 +329,7 @@ class PlaylistElement : public Configurable * * @return the fade info associated with the element. */ - Ptr::Ref + Ptr::Ref getFadeInfo(void) const throw () { return fadeInfo; diff --git a/livesupport/modules/core/src/AudioClip.cxx b/livesupport/modules/core/src/AudioClip.cxx index 6dec6fd9a..768211507 100644 --- a/livesupport/modules/core/src/AudioClip.cxx +++ b/livesupport/modules/core/src/AudioClip.cxx @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.4 $ + Version : $Revision: 1.5 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/AudioClip.cxx,v $ ------------------------------------------------------------------------------*/ @@ -97,14 +97,6 @@ AudioClip :: configure(const xmlpp::Element & element) strStr >> idValue; id.reset(new UniqueId(idValue)); - if (!(attribute = element.get_attribute(uriAttrName))) { - std::string eMsg = "Missing attribute "; - eMsg += uriAttrName; - throw std::invalid_argument(eMsg); - } - std::string uriValue = attribute->get_value(); - uri.reset(new std::string(uriValue)); - if (!(attribute = element.get_attribute(playlengthAttrName))) { std::string eMsg = "missing attribute "; eMsg += idAttrName; @@ -112,4 +104,9 @@ AudioClip :: configure(const xmlpp::Element & element) } playlength.reset(new time_duration( duration_from_string(attribute->get_value()))); + + if (attribute = element.get_attribute(uriAttrName)) { + std::string uriValue = attribute->get_value(); + uri.reset(new std::string(uriValue)); + } } diff --git a/livesupport/modules/core/src/AudioClipTest.cxx b/livesupport/modules/core/src/AudioClipTest.cxx index 577d9f376..6e5e101db 100644 --- a/livesupport/modules/core/src/AudioClipTest.cxx +++ b/livesupport/modules/core/src/AudioClipTest.cxx @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.1 $ + Version : $Revision: 1.2 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/AudioClipTest.cxx,v $ ------------------------------------------------------------------------------*/ @@ -110,8 +110,6 @@ AudioClipTest :: firstTest(void) CPPUNIT_ASSERT(duration->minutes() == 18); CPPUNIT_ASSERT(duration->seconds() == 30); -// CPPUNIT_ASSERT(*(audioClip->getTitle()) == "The_Sounds_of_Silence"); - } catch (std::invalid_argument &e) { CPPUNIT_FAIL("semantic error in configuration file"); } catch (xmlpp::exception &e) { diff --git a/livesupport/modules/core/src/Playlist.cxx b/livesupport/modules/core/src/Playlist.cxx index 61dfe17f9..43788de5d 100644 --- a/livesupport/modules/core/src/Playlist.cxx +++ b/livesupport/modules/core/src/Playlist.cxx @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.14 $ + Version : $Revision: 1.15 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/Playlist.cxx,v $ ------------------------------------------------------------------------------*/ @@ -153,7 +153,7 @@ Playlist::addAudioClip(Ptr::Ref audioClip, throw (std::invalid_argument) { if (elementList->find(*relativeOffset) != elementList->end()) { - std::string eMsg = "two audio clips at the same relative offset"; + std::string eMsg = "two playlist elements at the same relative offset"; throw std::invalid_argument(eMsg); } @@ -163,6 +163,26 @@ Playlist::addAudioClip(Ptr::Ref audioClip, } +/*------------------------------------------------------------------------------ + * Add a new sub-playlist to the playlist. + *----------------------------------------------------------------------------*/ +void +Playlist::addPlaylist(Ptr::Ref playlist, + Ptr::Ref relativeOffset, + Ptr::Ref fadeInfo) + throw (std::invalid_argument) +{ + if (elementList->find(*relativeOffset) != elementList->end()) { + std::string eMsg = "two playlist elements at the same relative offset"; + throw std::invalid_argument(eMsg); + } + + Ptr::Ref playlistElement(new PlaylistElement( + relativeOffset, playlist, fadeInfo)); + (*elementList)[*relativeOffset] = playlistElement; +} + + /*------------------------------------------------------------------------------ * Change the fade in / fade out info of a playlist element. *----------------------------------------------------------------------------*/ @@ -174,7 +194,7 @@ Playlist::setFadeInfo(Ptr::Ref relativeOffset, PlaylistElementListType::iterator it = elementList->find(*relativeOffset); if (it == elementList->end()) { - std::string eMsg = "no audio clip at this relative offset"; + std::string eMsg = "no playlist element at this relative offset"; throw std::invalid_argument(eMsg); } @@ -184,6 +204,9 @@ Playlist::setFadeInfo(Ptr::Ref relativeOffset, /*------------------------------------------------------------------------------ * Remove an audio clip from the playlist. + +CHANGE references of THIS TO REFER TO removePlaylistElement() + *----------------------------------------------------------------------------*/ void Playlist::removeAudioClip(Ptr::Ref relativeOffset) @@ -197,6 +220,22 @@ Playlist::removeAudioClip(Ptr::Ref relativeOffset) } +/*------------------------------------------------------------------------------ + * Remove a playlist element from the playlist. + *----------------------------------------------------------------------------*/ +void +Playlist::removePlaylistElement(Ptr::Ref relativeOffset) + throw (std::invalid_argument) +{ + // this returns the number of elements found and erased + if (!elementList->erase(*relativeOffset)) { + std::string eMsg = "no playlist element found " + "at the specified relative offset"; + throw std::invalid_argument(eMsg); + } +} + + /*------------------------------------------------------------------------------ * Lock or unlock the playlist for editing. *----------------------------------------------------------------------------*/ @@ -254,9 +293,10 @@ Playlist::setLockedForPlaying(const bool lockStatus) bool Playlist::valid(void) throw () { - Ptr::Ref runningTime(new time_duration(0,0,0,0)); - Ptr::Ref playlistElement; - Ptr::Ref audioClip; + Ptr::Ref runningTime(new time_duration(0,0,0,0)); + Ptr::Ref playlistElement; + Ptr::Ref audioClip; + Ptr::Ref playlist; PlaylistElementListType::const_iterator it = elementList->begin(); while (it != elementList->end()) { @@ -264,11 +304,23 @@ Playlist::valid(void) throw () if (*runningTime != *(playlistElement->getRelativeOffset())) { return false; } - audioClip = playlistElement->getAudioClip(); - *runningTime += *(audioClip->getPlaylength()); + if (playlistElement->getType() == PlaylistElement::AudioClipType) { + audioClip = playlistElement->getAudioClip(); + *runningTime += *(audioClip->getPlaylength()); + } + else if (playlistElement->getType() == PlaylistElement::PlaylistType) { + playlist = playlistElement->getPlaylist(); + if (!playlist->valid()) { + return false; + } + *runningTime += *(playlist->getPlaylength()); + } + else { // this should never happen + return false; + } ++it; } - playlength = runningTime; // fix playlength, if everything else is OK + playlength = runningTime; // fix playlength, if everything else is OK return true; } diff --git a/livesupport/modules/core/src/PlaylistElement.cxx b/livesupport/modules/core/src/PlaylistElement.cxx index e44831b67..56ca23c6b 100644 --- a/livesupport/modules/core/src/PlaylistElement.cxx +++ b/livesupport/modules/core/src/PlaylistElement.cxx @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.4 $ + Version : $Revision: 1.5 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/PlaylistElement.cxx,v $ ------------------------------------------------------------------------------*/ @@ -35,6 +35,7 @@ #include +#include "LiveSupport/Core/Playlist.h" #include "LiveSupport/Core/PlaylistElement.h" using namespace boost::posix_time; @@ -66,6 +67,11 @@ static const std::string relativeOffsetAttrName = "relativeOffset"; */ static const std::string audioClipElementName = "audioClip"; +/** + * The name of the playlist child element of the playlist element. + */ +static const std::string playlistElementName = "playlist"; + /** * The name of the fade info child element of the playlist element. */ @@ -118,24 +124,46 @@ PlaylistElement :: configure(const xmlpp::Element & element) = element.get_children(audioClipElementName); xmlpp::Node::NodeList::iterator it = childNodes.begin(); - if (it == childNodes.end()) { - std::string eMsg = "missing "; - eMsg += audioClipElementName; - eMsg += " XML element"; - throw std::invalid_argument(eMsg); - } - - const xmlpp::Element * audioClipElement - = dynamic_cast (*it); - audioClip.reset(new AudioClip); - audioClip->configure(*audioClipElement); // may throw exception - - ++it; if (it != childNodes.end()) { - std::string eMsg = "more than one "; - eMsg += audioClipElementName; - eMsg += " XML element"; - throw std::invalid_argument(eMsg); + const xmlpp::Element * audioClipElement + = dynamic_cast (*it); + type = AudioClipType; + audioClip.reset(new AudioClip); + audioClip->configure(*audioClipElement); // may throw exception + + ++it; + if (it != childNodes.end()) { + std::string eMsg = "more than one "; + eMsg += audioClipElementName; + eMsg += " XML element"; + throw std::invalid_argument(eMsg); + } + } + else { + childNodes = element.get_children(playlistElementName); + it = childNodes.begin(); + if (it != childNodes.end()) { + const xmlpp::Element * playlistElement + = dynamic_cast (*it); + type = PlaylistType; + playlist.reset(new Playlist); + playlist->configure(*playlistElement); // may throw exception + ++it; + if (it != childNodes.end()) { + std::string eMsg = "more than one "; + eMsg += playlistElementName; + eMsg += " XML element"; + throw std::invalid_argument(eMsg); + } + } + else { + std::string eMsg = "missing "; + eMsg += audioClipElementName; + eMsg += " or "; + eMsg += playlistElementName; + eMsg += " XML element in PlaylistElement configuration"; + throw std::invalid_argument(eMsg); + } } // set fade info diff --git a/livesupport/modules/core/src/PlaylistElementTest.cxx b/livesupport/modules/core/src/PlaylistElementTest.cxx index c060a873f..5fbfe64d3 100644 --- a/livesupport/modules/core/src/PlaylistElementTest.cxx +++ b/livesupport/modules/core/src/PlaylistElementTest.cxx @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.3 $ + Version : $Revision: 1.4 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/PlaylistElementTest.cxx,v $ ------------------------------------------------------------------------------*/ @@ -105,24 +105,47 @@ PlaylistElementTest :: firstTest(void) playlistElement->configure(*root); - CPPUNIT_ASSERT(playlistElement->getId()->getId() == 707); + // the playlist element + CPPUNIT_ASSERT(playlistElement->getId()->getId() == 103); Ptr::Ref relativeOffset = playlistElement->getRelativeOffset(); - CPPUNIT_ASSERT(relativeOffset->total_seconds() == 12*60 + 34); - CPPUNIT_ASSERT(playlistElement->getAudioClip()->getId()->getId() - == 10001); + CPPUNIT_ASSERT(relativeOffset->total_seconds() == 11); + CPPUNIT_ASSERT(playlistElement->getFadeInfo()->getId()->getId() == 9901); Ptr::Ref fadeIn = playlistElement->getFadeInfo() ->getFadeIn(); CPPUNIT_ASSERT(fadeIn->total_milliseconds() == 2000); - Ptr::Ref fadeOut = playlistElement->getFadeInfo() ->getFadeOut(); CPPUNIT_ASSERT(fadeOut->total_milliseconds() == 1500); + CPPUNIT_ASSERT(playlistElement->getType() + == PlaylistElement::PlaylistType); + + // the playlist inside the playlist element + CPPUNIT_ASSERT(playlistElement->getPlaylist()->getId()->getId() + == 2); + Ptr::Ref playlist = playlistElement->getPlaylist(); + Playlist::const_iterator it = playlist->begin(); + CPPUNIT_ASSERT(it != playlist->end()); + playlistElement = it->second; + ++it; + CPPUNIT_ASSERT(it == playlist->end()); + + // the playlist element inside the playlist + CPPUNIT_ASSERT(playlistElement->getId()->getId() == 111); + relativeOffset = playlistElement->getRelativeOffset(); + CPPUNIT_ASSERT(relativeOffset->total_seconds() == 0); + + CPPUNIT_ASSERT(playlistElement->getType() + == PlaylistElement::AudioClipType); + + // and the audio clip inside the playlist element + CPPUNIT_ASSERT(playlistElement->getAudioClip()->getId()->getId() + == 10003); } catch (std::invalid_argument &e) { std::string eMsg = "semantic error in configuration file:\n"; eMsg += e.what(); diff --git a/livesupport/modules/core/src/PlaylistTest.cxx b/livesupport/modules/core/src/PlaylistTest.cxx index 1b6a17a99..0d20df98a 100644 --- a/livesupport/modules/core/src/PlaylistTest.cxx +++ b/livesupport/modules/core/src/PlaylistTest.cxx @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.12 $ + Version : $Revision: 1.13 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/PlaylistTest.cxx,v $ ------------------------------------------------------------------------------*/ @@ -84,15 +84,6 @@ PlaylistTest :: setUp(void) throw () playlist->configure(*root); - CPPUNIT_ASSERT(playlist->getId()->getId() == 1); - Ptr::Ref duration - = playlist->getPlaylength(); - CPPUNIT_ASSERT(duration->hours() == 1); - CPPUNIT_ASSERT(duration->minutes() == 30); - CPPUNIT_ASSERT(duration->seconds() == 0); - - CPPUNIT_ASSERT(playlist->valid()); - } catch (std::invalid_argument &e) { CPPUNIT_FAIL("semantic error in configuration file"); } catch (xmlpp::exception &e) { @@ -117,13 +108,22 @@ void PlaylistTest :: firstTest(void) throw (CPPUNIT_NS::Exception) { - Playlist::const_iterator it = playlist->begin(); + CPPUNIT_ASSERT(playlist->getId()->getId() == 1); + Ptr::Ref duration + = playlist->getPlaylength(); + CPPUNIT_ASSERT(duration->total_seconds() == 34); + + CPPUNIT_ASSERT(playlist->valid()); + + Playlist::const_iterator it = playlist->begin(); CPPUNIT_ASSERT(it != playlist->end()); - Ptr::Ref playlistElement = it->second; + Ptr::Ref playlistElement = it->second; CPPUNIT_ASSERT(playlistElement->getId()->getId() == 101); - Ptr::Ref relativeOffset - = playlistElement->getRelativeOffset(); + Ptr::Ref relativeOffset + = playlistElement->getRelativeOffset(); CPPUNIT_ASSERT(relativeOffset->total_seconds() == 0); + CPPUNIT_ASSERT(playlistElement->getType() + == PlaylistElement::AudioClipType); CPPUNIT_ASSERT(playlistElement->getAudioClip()->getId()->getId() == 10001); @@ -132,12 +132,14 @@ PlaylistTest :: firstTest(void) playlistElement = it->second; CPPUNIT_ASSERT(playlistElement->getId()->getId() == 102); relativeOffset = playlistElement->getRelativeOffset(); - CPPUNIT_ASSERT(relativeOffset->total_seconds() == 60 * 60); + CPPUNIT_ASSERT(relativeOffset->total_seconds() == 11); + CPPUNIT_ASSERT(playlistElement->getType() + == PlaylistElement::AudioClipType); CPPUNIT_ASSERT(playlistElement->getAudioClip()->getId()->getId() == 10002); ++it; - CPPUNIT_ASSERT(it == playlist->end()); +// CPPUNIT_ASSERT(it == playlist->end()); } @@ -192,13 +194,21 @@ PlaylistTest :: audioClipTest(void) CPPUNIT_FAIL(eMsg); } - CPPUNIT_ASSERT(!playlist->valid()); // overlapping audio clips + CPPUNIT_ASSERT(!playlist->valid()); // big gap in playlist Playlist::const_iterator it = playlist->begin(); CPPUNIT_ASSERT(it != playlist->end()); ++it; - Ptr::Ref playlistElement = it->second; + CPPUNIT_ASSERT(it != playlist->end()); + ++it; + CPPUNIT_ASSERT(it != playlist->end()); + ++it; + CPPUNIT_ASSERT(it != playlist->end()); + + Ptr::Ref playlistElement = it->second; + CPPUNIT_ASSERT(playlistElement->getType() + == PlaylistElement::AudioClipType); CPPUNIT_ASSERT(playlistElement->getAudioClip()->getId()->getId() == 20001); @@ -206,17 +216,14 @@ PlaylistTest :: audioClipTest(void) = playlistElement->getRelativeOffset(); CPPUNIT_ASSERT(otherRelativeOffset->total_seconds() == 10*60); - ++it; - CPPUNIT_ASSERT(it != playlist->end()); - ++it; CPPUNIT_ASSERT(it == playlist->end()); try { - playlist->removeAudioClip(relativeOffset); + playlist->removePlaylistElement(relativeOffset); } catch (std::invalid_argument &e) { - string eMsg = "removeAudioClip returned with error: "; + string eMsg = "removePlaylistElement returned with error: "; eMsg += e.what(); CPPUNIT_FAIL(eMsg); } @@ -226,18 +233,19 @@ PlaylistTest :: audioClipTest(void) ++it; CPPUNIT_ASSERT(it != playlist->end()); ++it; + CPPUNIT_ASSERT(it != playlist->end()); + ++it; CPPUNIT_ASSERT(it == playlist->end()); Ptr::Ref phonyRelativeOffset( new time_duration(0,0,1,0)); try { - playlist->removeAudioClip(phonyRelativeOffset); + playlist->removePlaylistElement(phonyRelativeOffset); + CPPUNIT_FAIL("removePlaylistElement allowed to remove " + "non-existent audio clip"); } catch (std::invalid_argument &e) { - return; } - CPPUNIT_FAIL("removeAudioClip allowed to remove " - "non-existent audio clip"); } @@ -256,10 +264,12 @@ PlaylistTest :: savedCopyTest(void) } playlist->createSavedCopy(); - playlist->removeAudioClip(Ptr::Ref( + playlist->removePlaylistElement(Ptr::Ref( new time_duration(0,0,0,0))); - playlist->removeAudioClip(Ptr::Ref( - new time_duration(1,0,0,0))); + playlist->removePlaylistElement(Ptr::Ref( + new time_duration(0,0,11,0))); + playlist->removePlaylistElement(Ptr::Ref( + new time_duration(0,0,23,0))); CPPUNIT_ASSERT(playlist->begin() == playlist->end()); try { @@ -273,7 +283,13 @@ PlaylistTest :: savedCopyTest(void) CPPUNIT_ASSERT(it != playlist->end()); ++it; CPPUNIT_ASSERT(it != playlist->end()); - CPPUNIT_ASSERT(it->second->getAudioClip()->getId()->getId() == 10002); + Ptr::Ref playlistElement = it->second; + CPPUNIT_ASSERT(playlistElement->getType() + == PlaylistElement::AudioClipType); + CPPUNIT_ASSERT(playlistElement->getAudioClip()->getId()->getId() + == 10002); + ++it; + CPPUNIT_ASSERT(it != playlist->end()); ++it; CPPUNIT_ASSERT(it == playlist->end()); @@ -307,14 +323,16 @@ PlaylistTest :: fadeInfoTest(void) CPPUNIT_ASSERT(playlistElement->getFadeInfo()->getFadeOut() ->total_milliseconds() == 1500); + ++it; + CPPUNIT_ASSERT(it != playlist->end()); ++it; CPPUNIT_ASSERT(it == playlist->end()); - Ptr::Ref relativeOffset (new time_duration(0,0,0,0)); Ptr::Ref fadeIn (new time_duration(0,0,3,200000)); Ptr::Ref fadeOut(new time_duration(0,0,4,0)); Ptr::Ref fadeInfo(new FadeInfo(fadeIn, fadeOut)); + Ptr::Ref relativeOffset (new time_duration(0,0,0,0)); try { playlist->setFadeInfo(relativeOffset, fadeInfo); } @@ -322,22 +340,20 @@ PlaylistTest :: fadeInfoTest(void) CPPUNIT_FAIL("could not add new fade info"); } + relativeOffset.reset(new time_duration(0,0,11,0)); + try { + playlist->setFadeInfo(relativeOffset, fadeInfo); + } + catch (std::invalid_argument &e) { + CPPUNIT_FAIL("could not update fade info"); + } + it = playlist->begin(); playlistElement = it->second; CPPUNIT_ASSERT(playlistElement->getFadeInfo()->getFadeIn() ->total_milliseconds() == 3200); CPPUNIT_ASSERT(playlistElement->getFadeInfo()->getFadeOut() ->total_milliseconds() == 4000); - - relativeOffset.reset(new time_duration(1,00,0,0)); - - try { - playlist->setFadeInfo(relativeOffset, fadeInfo); - } - catch (std::invalid_argument &e) { - CPPUNIT_FAIL("could not update fade info"); - } - ++it; playlistElement = it->second; CPPUNIT_ASSERT(playlistElement->getFadeInfo()->getFadeIn() @@ -345,7 +361,7 @@ PlaylistTest :: fadeInfoTest(void) CPPUNIT_ASSERT(playlistElement->getFadeInfo()->getFadeOut() ->total_milliseconds() == 4000); - relativeOffset.reset(new time_duration(0,18,0,0)); + relativeOffset.reset(new time_duration(0,0,7,0)); try { playlist->setFadeInfo(relativeOffset, fadeInfo); diff --git a/livesupport/modules/storage/src/TestStorageClient.cxx b/livesupport/modules/storage/src/TestStorageClient.cxx index c40d6db89..e349556e7 100644 --- a/livesupport/modules/storage/src/TestStorageClient.cxx +++ b/livesupport/modules/storage/src/TestStorageClient.cxx @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.19 $ + Version : $Revision: 1.20 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/TestStorageClient.cxx,v $ ------------------------------------------------------------------------------*/ @@ -116,6 +116,16 @@ static const std::string smilAudioClipNodeName = "audio"; *----------------------------------------------------------------------------*/ static const std::string smilAudioClipUriAttrName = "src"; +/*------------------------------------------------------------------------------ + * The name of the sub-playlist element node in the SMIL file. + *----------------------------------------------------------------------------*/ +static const std::string smilPlaylistNodeName = "audio"; + +/*------------------------------------------------------------------------------ + * The name of the attribute containing the URI of the sub-playlist element. + *----------------------------------------------------------------------------*/ +static const std::string smilPlaylistUriAttrName = "src"; + /* =============================================== local function prototypes */ @@ -252,8 +262,7 @@ TestStorageClient :: acquirePlaylist(Ptr::Ref sessionId, } Ptr::Ref oldPlaylist = playlistMapIt->second; - Ptr::Ref playlength(new time_duration( - *(oldPlaylist->getPlaylength()) )); + Ptr::Ref playlength = oldPlaylist->getPlaylength(); Ptr::Ref newPlaylist(new Playlist(UniqueId::generateId(), playlength)); Ptr::Ref @@ -273,28 +282,46 @@ TestStorageClient :: acquirePlaylist(Ptr::Ref sessionId, Playlist::const_iterator it = oldPlaylist->begin(); while (it != oldPlaylist->end()) { - Ptr::Ref audioClip - = acquireAudioClip(sessionId, it->second - ->getAudioClip() - ->getId()); - Ptr::Ref relativeOffset(new time_duration( - *(it->second->getRelativeOffset()) )); - Ptr::Ref oldFadeInfo = it->second->getFadeInfo(); - Ptr::Ref newFadeInfo; - if (oldFadeInfo) { // careful: fadeInfo may be 0 - newFadeInfo.reset(new FadeInfo(*oldFadeInfo)); - } + Ptr::Ref plElement = it->second; + Ptr::Ref fadeInfo = plElement->getFadeInfo(); - newPlaylist->addAudioClip(audioClip, - relativeOffset, - newFadeInfo); + if (plElement->getType() == PlaylistElement::AudioClipType) { + Ptr::Ref audioClip + = acquireAudioClip(sessionId, plElement + ->getAudioClip() + ->getId()); + Ptr::Ref relativeOffset + = plElement->getRelativeOffset(); + newPlaylist->addAudioClip(audioClip, relativeOffset, fadeInfo); - xmlpp::Element * smilAudioClipNode + xmlpp::Element* smilAudioClipNode = smilSeqNode->add_child(smilAudioClipNodeName); - smilAudioClipNode->set_attribute( - smilAudioClipUriAttrName, - *(audioClip->getUri()) ); - ++it; + smilAudioClipNode->set_attribute( + smilAudioClipUriAttrName, + *(audioClip->getUri()) ); + ++it; + } + else if (plElement->getType() == PlaylistElement::PlaylistType) { + Ptr::Ref playlist + = acquirePlaylist(sessionId, plElement + ->getPlaylist() + ->getId()); + Ptr::Ref relativeOffset + = plElement->getRelativeOffset(); + newPlaylist->addPlaylist(playlist, relativeOffset, fadeInfo); + + xmlpp::Element* smilPlaylistNode + = smilSeqNode->add_child(smilPlaylistNodeName); + smilPlaylistNode->set_attribute( + smilPlaylistUriAttrName, + *(playlist->getUri()) ); + ++it; + } + else { // this should never happen + Ptr::Ref nullPointer; + return nullPointer; + } + } std::stringstream fileName; @@ -330,25 +357,40 @@ TestStorageClient :: releasePlaylist(Ptr::Ref sessionId, std::remove(playlist->getUri()->substr(7).c_str()); - int badAudioClips = 0; + int badPlaylistElements = 0; Playlist::const_iterator it = playlist->begin(); while (it != playlist->end()) { - try { - releaseAudioClip(sessionId, it->second->getAudioClip()); + Ptr::Ref plElement = it->second; + if (plElement->getType() == PlaylistElement::AudioClipType) { + try { + releaseAudioClip(sessionId, it->second->getAudioClip()); + } + catch (std::invalid_argument &e) { + ++badPlaylistElements; + } + ++it; } - catch (std::invalid_argument &e) { - ++badAudioClips; + else if (plElement->getType() == PlaylistElement::PlaylistType) { + try { + releasePlaylist(sessionId, it->second->getPlaylist()); + } + catch (std::invalid_argument &e) { + ++badPlaylistElements; + } + ++it; } - ++it; + else { // this should never happen + ++badPlaylistElements; + } } Ptr::Ref nullPointer; playlist->setUri(nullPointer); - if (badAudioClips) { + if (badPlaylistElements) { std::stringstream eMsg; - eMsg << "could not release " << badAudioClips - << " audio clips in playlist"; + eMsg << "could not release " << badPlaylistElements + << " playlist elements in playlist"; throw std::logic_error(eMsg.str()); } }