/*------------------------------------------------------------------------------ Copyright (c) 2004 Media Development Loan Fund This file is part of the LiveSupport project. http://livesupport.campware.org/ To report bugs, send an e-mail to bugs@campware.org LiveSupport is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. LiveSupport 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 General Public License for more details. You should have received a copy of the GNU General Public License along with LiveSupport; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Author : $Author: fgerlits $ Version : $Revision: 1.17 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/TestStorageClient.cxx,v $ ------------------------------------------------------------------------------*/ /* ============================================================ include files */ #ifdef HAVE_CONFIG_H #include "configure.h" #endif #if HAVE_UNISTD_H #include #else #error "Need unistd.h" #endif #include #include #include "TestStorageClient.h" using namespace boost::posix_time; using namespace LiveSupport::Core; using namespace LiveSupport::Storage; /* =================================================== local data structures */ /* ================================================ local constants & macros */ /*------------------------------------------------------------------------------ * The name of the config element for this class *----------------------------------------------------------------------------*/ const std::string TestStorageClient::configElementNameStr = "testStorage"; /*------------------------------------------------------------------------------ * The name of the config element attribute for the temp files *----------------------------------------------------------------------------*/ static const std::string localTempStorageAttrName = "tempFiles"; /*------------------------------------------------------------------------------ * The XML version used to create the SMIL file. *----------------------------------------------------------------------------*/ static const std::string xmlVersion = "1.0"; /*------------------------------------------------------------------------------ * The name of the SMIL root node. *----------------------------------------------------------------------------*/ static const std::string smilRootNodeName = "smil"; /*------------------------------------------------------------------------------ * The name of the SMIL language description attribute. *----------------------------------------------------------------------------*/ static const std::string smilLanguageAttrName = "xmlns"; /*------------------------------------------------------------------------------ * The value of the SMIL language description attribute. *----------------------------------------------------------------------------*/ static const std::string smilLanguageAttrValue = "http://www.w3.org/2001/SMIL20/Language"; /*------------------------------------------------------------------------------ * The name of the SMIL real networks extension attribute. *----------------------------------------------------------------------------*/ static const std::string smilExtensionsAttrName = "xmlns:rn"; /*------------------------------------------------------------------------------ * The value of the SMIL real networks extension attribute. *----------------------------------------------------------------------------*/ static const std::string smilExtensionsAttrValue = "http://features.real.com/2001/SMIL20/Extensions"; /*------------------------------------------------------------------------------ * The name of the body node in the SMIL file. *----------------------------------------------------------------------------*/ static const std::string smilBodyNodeName = "body"; /*------------------------------------------------------------------------------ * The name of the sequential audio clip list node in the SMIL file. *----------------------------------------------------------------------------*/ static const std::string smilSeqNodeName = "seq"; /*------------------------------------------------------------------------------ * The name of the audio clip element node in the SMIL file. *----------------------------------------------------------------------------*/ static const std::string smilAudioClipNodeName = "audio"; /*------------------------------------------------------------------------------ * The name of the attribute containing the URI of the audio clip element. *----------------------------------------------------------------------------*/ static const std::string smilAudioClipUriAttrName = "src"; /* =============================================== local function prototypes */ /* ============================================================= module code */ /*------------------------------------------------------------------------------ * Configure the test storage client. *----------------------------------------------------------------------------*/ void TestStorageClient :: configure(const xmlpp::Element & element) throw (std::invalid_argument, std::logic_error) { if (element.get_name() != configElementNameStr) { std::string eMsg = "Bad configuration element "; eMsg += element.get_name(); throw std::invalid_argument(eMsg); } const xmlpp::Attribute * attribute; if (!(attribute = element.get_attribute(localTempStorageAttrName))) { std::string eMsg = "Missing attribute "; eMsg += localTempStorageAttrName; throw std::invalid_argument(eMsg); } localTempStorage = attribute->get_value(); // iterate through the playlist elements ... xmlpp::Node::NodeList nodes = element.get_children(Playlist::getConfigElementName()); xmlpp::Node::NodeList::iterator it = nodes.begin(); playlistMap.clear(); while (it != nodes.end()) { Ptr::Ref playlist(new Playlist); const xmlpp::Element * element = dynamic_cast (*it); playlist->configure(*element); playlistMap[playlist->getId()->getId()] = playlist; ++it; } // ... and the the audio clip elements nodes = element.get_children(AudioClip::getConfigElementName()); it = nodes.begin(); audioClipMap.clear(); while (it != nodes.end()) { Ptr::Ref audioClip(new AudioClip); const xmlpp::Element * element = dynamic_cast (*it); audioClip->configure(*element); audioClipMap[audioClip->getId()->getId()] = audioClip; ++it; } } /*------------------------------------------------------------------------------ * Tell if a playlist exists. *----------------------------------------------------------------------------*/ const bool TestStorageClient :: existsPlaylist(Ptr::Ref sessionId, Ptr::Ref id) const throw () { return playlistMap.count(id->getId()) == 1 ? true : false; } /*------------------------------------------------------------------------------ * Return a playlist. *----------------------------------------------------------------------------*/ Ptr::Ref TestStorageClient :: getPlaylist(Ptr::Ref sessionId, Ptr::Ref id) const throw (std::invalid_argument) { PlaylistMap::const_iterator it = playlistMap.find(id->getId()); if (it == playlistMap.end()) { throw std::invalid_argument("no such playlist"); } return it->second; } /*------------------------------------------------------------------------------ * Acquire resources for a playlist. *----------------------------------------------------------------------------*/ Ptr::Ref TestStorageClient :: acquirePlaylist(Ptr::Ref sessionId, Ptr::Ref id) const throw (std::logic_error) { PlaylistMap::const_iterator playlistMapIt = playlistMap.find(id->getId()); if (playlistMapIt == playlistMap.end()) { throw std::invalid_argument("no such playlist"); } Ptr::Ref oldPlaylist = playlistMapIt->second; Ptr::Ref playlength(new time_duration( *(oldPlaylist->getPlaylength()) )); Ptr::Ref newPlaylist(new Playlist(UniqueId::generateId(), playlength)); Ptr::Ref smilDocument(new xmlpp::Document(xmlVersion)); xmlpp::Element * smilRootNode = smilDocument->create_root_node(smilRootNodeName); smilRootNode->set_attribute(smilLanguageAttrName, smilLanguageAttrValue); smilRootNode->set_attribute(smilExtensionsAttrName, smilExtensionsAttrValue); xmlpp::Element * smilBodyNode = smilRootNode->add_child(smilBodyNodeName); xmlpp::Element * smilSeqNode = smilBodyNode->add_child(smilSeqNodeName); 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)); } newPlaylist->addAudioClip(audioClip, relativeOffset, newFadeInfo); xmlpp::Element * smilAudioClipNode = smilSeqNode->add_child(smilAudioClipNodeName); smilAudioClipNode->set_attribute( smilAudioClipUriAttrName, *(audioClip->getUri()) ); ++it; } std::stringstream fileName; fileName << localTempStorage << newPlaylist->getId()->getId() << "#" << std::rand() << ".smil"; smilDocument->write_to_file(fileName.str(), "UTF-8"); Ptr::Ref playlistUri(new std::string(fileName.str())); newPlaylist->setUri(playlistUri); return newPlaylist; } /*------------------------------------------------------------------------------ * Release a playlist. *----------------------------------------------------------------------------*/ void TestStorageClient :: releasePlaylist(Ptr::Ref sessionId, Ptr::Ref playlist) const throw (std::logic_error) { if (! playlist->getUri()) { throw std::logic_error("playlist URI not found"); } std::ifstream ifs(playlist->getUri()->substr(7).c_str()); if (!ifs) { ifs.close(); throw std::logic_error("playlist temp file not found"); } ifs.close(); std::remove(playlist->getUri()->substr(7).c_str()); int badAudioClips = 0; Playlist::const_iterator it = playlist->begin(); while (it != playlist->end()) { try { releaseAudioClip(sessionId, it->second->getAudioClip()); } catch (std::invalid_argument &e) { ++badAudioClips; } ++it; } Ptr::Ref nullPointer; playlist->setUri(nullPointer); if (badAudioClips) { std::stringstream eMsg; eMsg << "could not release " << badAudioClips << " audio clips in playlist"; throw std::logic_error(eMsg.str()); } } /*------------------------------------------------------------------------------ * Delete a playlist. *----------------------------------------------------------------------------*/ void TestStorageClient :: deletePlaylist(Ptr::Ref sessionId, Ptr::Ref id) throw (std::invalid_argument) { // erase() returns the number of entries found & erased if (!playlistMap.erase(id->getId())) { throw std::invalid_argument("no such playlist"); } } /*------------------------------------------------------------------------------ * Return a listing of all the playlists in the playlist store. *----------------------------------------------------------------------------*/ Ptr::Ref> >::Ref TestStorageClient :: getAllPlaylists(Ptr::Ref sessionId) const throw () { PlaylistMap::const_iterator it = playlistMap.begin(); Ptr::Ref> >::Ref playlistVector (new std::vector::Ref>); while (it != playlistMap.end()) { playlistVector->push_back(it->second); ++it; } return playlistVector; } /*------------------------------------------------------------------------------ * Create a new playlist. *----------------------------------------------------------------------------*/ Ptr::Ref TestStorageClient :: createPlaylist(Ptr::Ref sessionId) throw () { // generate a new UniqueId -- TODO: fix UniqueId to make sure // this is really unique; not checked here! Ptr::Ref playlistId = Ptr::Ref(UniqueId :: generateId()); Ptr::Ref playLength = Ptr::Ref(new time_duration(0,0,0)); Ptr::Ref playlist = Ptr::Ref(new Playlist(playlistId, playLength)); playlistMap[playlistId->getId()] = playlist; return playlist; } /*------------------------------------------------------------------------------ * Tell if an audio clip exists. *----------------------------------------------------------------------------*/ const bool TestStorageClient :: existsAudioClip(Ptr::Ref sessionId, Ptr::Ref id) const throw () { return audioClipMap.count(id->getId()) == 1 ? true : false; } /*------------------------------------------------------------------------------ * Return an audio clip. *----------------------------------------------------------------------------*/ Ptr::Ref TestStorageClient :: getAudioClip(Ptr::Ref sessionId, Ptr::Ref id) const throw (std::invalid_argument) { AudioClipMap::const_iterator it = audioClipMap.find(id->getId()); if (it == audioClipMap.end()) { throw std::invalid_argument("no such audio clip"); } return it->second; } /*------------------------------------------------------------------------------ * Acquire resources for an audio clip. *----------------------------------------------------------------------------*/ Ptr::Ref TestStorageClient :: acquireAudioClip(Ptr::Ref sessionId, Ptr::Ref id) const throw (std::logic_error) { AudioClipMap::const_iterator it = audioClipMap.find(id->getId()); if (it == audioClipMap.end()) { throw std::invalid_argument("no such audio clip"); } Ptr::Ref storedAudioClip = it->second; if (! storedAudioClip->getUri()) { throw std::logic_error("audio clip URI not found"); } // cut the "file:" off std::string audioClipFileName = storedAudioClip->getUri()->substr(5); std::ifstream ifs(audioClipFileName.c_str()); if (!ifs) { ifs.close(); throw std::logic_error("could not read audio clip"); } ifs.close(); Ptr::Ref audioClip(new AudioClip(*storedAudioClip)); Ptr::Ref audioClipUri(new std::string("file://")); *audioClipUri += get_current_dir_name(); // doesn't work if current *audioClipUri += "/"; // dir = /, but OK for now *audioClipUri += audioClipFileName; audioClip->setUri(audioClipUri); return audioClip; } /*------------------------------------------------------------------------------ * Release an audio clip. *----------------------------------------------------------------------------*/ void TestStorageClient :: releaseAudioClip(Ptr::Ref sessionId, Ptr::Ref audioClip) const throw (std::logic_error) { if (*(audioClip->getUri()) == "") { throw std::logic_error("audio clip URI not found"); } Ptr::Ref nullPointer; audioClip->setUri(nullPointer); } /*------------------------------------------------------------------------------ * Delete an audio clip. *----------------------------------------------------------------------------*/ void TestStorageClient :: deleteAudioClip(Ptr::Ref sessionId, Ptr::Ref id) throw (std::invalid_argument) { // erase() returns the number of entries found & erased if (!audioClipMap.erase(id->getId())) { throw std::invalid_argument("no such audio clip"); } } /*------------------------------------------------------------------------------ * Return a listing of all the audio clips in the audio clip store. *----------------------------------------------------------------------------*/ Ptr::Ref> >::Ref TestStorageClient :: getAllAudioClips(Ptr::Ref sessionId) const throw () { AudioClipMap::const_iterator it = audioClipMap.begin(); Ptr::Ref> >::Ref audioClipVector (new std::vector::Ref>); while (it != audioClipMap.end()) { audioClipVector->push_back(it->second); ++it; } return audioClipVector; }